summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:18:55 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:18:55 +0100
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /tools
downloadqt4-tools-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Long live Qt 4.5!
Diffstat (limited to 'tools')
-rw-r--r--tools/activeqt/activeqt.pro11
-rw-r--r--tools/activeqt/dumpcpp/dumpcpp.pro6
-rw-r--r--tools/activeqt/dumpcpp/main.cpp1502
-rw-r--r--tools/activeqt/dumpdoc/dumpdoc.pro5
-rw-r--r--tools/activeqt/dumpdoc/main.cpp146
-rw-r--r--tools/activeqt/testcon/ambientproperties.cpp125
-rw-r--r--tools/activeqt/testcon/ambientproperties.h71
-rw-r--r--tools/activeqt/testcon/ambientproperties.ui299
-rw-r--r--tools/activeqt/testcon/changeproperties.cpp286
-rw-r--r--tools/activeqt/testcon/changeproperties.h74
-rw-r--r--tools/activeqt/testcon/changeproperties.ui211
-rw-r--r--tools/activeqt/testcon/controlinfo.cpp122
-rw-r--r--tools/activeqt/testcon/controlinfo.h61
-rw-r--r--tools/activeqt/testcon/controlinfo.ui134
-rw-r--r--tools/activeqt/testcon/docuwindow.cpp161
-rw-r--r--tools/activeqt/testcon/docuwindow.h67
-rw-r--r--tools/activeqt/testcon/invokemethod.cpp170
-rw-r--r--tools/activeqt/testcon/invokemethod.h73
-rw-r--r--tools/activeqt/testcon/invokemethod.ui270
-rw-r--r--tools/activeqt/testcon/main.cpp64
-rw-r--r--tools/activeqt/testcon/mainwindow.cpp461
-rw-r--r--tools/activeqt/testcon/mainwindow.h106
-rw-r--r--tools/activeqt/testcon/mainwindow.ui682
-rw-r--r--tools/activeqt/testcon/scripts/javascript.js25
-rw-r--r--tools/activeqt/testcon/scripts/perlscript.pl24
-rw-r--r--tools/activeqt/testcon/scripts/pythonscript.py15
-rw-r--r--tools/activeqt/testcon/scripts/vbscript.vbs20
-rw-r--r--tools/activeqt/testcon/testcon.idl44
-rw-r--r--tools/activeqt/testcon/testcon.pro21
-rw-r--r--tools/activeqt/testcon/testcon.rc35
-rw-r--r--tools/assistant/assistant.pro8
-rw-r--r--tools/assistant/compat/Info_mac.plist18
-rw-r--r--tools/assistant/compat/LICENSE.GPL280
-rw-r--r--tools/assistant/compat/assistant.icnsbin0 -> 162568 bytes
-rw-r--r--tools/assistant/compat/assistant.icobin0 -> 355574 bytes
-rw-r--r--tools/assistant/compat/assistant.pro84
-rw-r--r--tools/assistant/compat/assistant.qrc37
-rw-r--r--tools/assistant/compat/assistant.rc1
-rw-r--r--tools/assistant/compat/compat.pro84
-rw-r--r--tools/assistant/compat/config.cpp438
-rw-r--r--tools/assistant/compat/config.h165
-rw-r--r--tools/assistant/compat/docuparser.cpp433
-rw-r--r--tools/assistant/compat/docuparser.h166
-rw-r--r--tools/assistant/compat/fontsettingsdialog.cpp137
-rw-r--r--tools/assistant/compat/fontsettingsdialog.h77
-rw-r--r--tools/assistant/compat/helpdialog.cpp1331
-rw-r--r--tools/assistant/compat/helpdialog.h184
-rw-r--r--tools/assistant/compat/helpdialog.ui404
-rw-r--r--tools/assistant/compat/helpwindow.cpp247
-rw-r--r--tools/assistant/compat/helpwindow.h100
-rw-r--r--tools/assistant/compat/images/assistant-128.pngbin0 -> 6448 bytes
-rw-r--r--tools/assistant/compat/images/assistant.pngbin0 -> 2034 bytes
-rw-r--r--tools/assistant/compat/images/close.pngbin0 -> 406 bytes
-rw-r--r--tools/assistant/compat/images/designer.pngbin0 -> 1282 bytes
-rw-r--r--tools/assistant/compat/images/linguist.pngbin0 -> 1382 bytes
-rw-r--r--tools/assistant/compat/images/mac/addtab.pngbin0 -> 469 bytes
-rw-r--r--tools/assistant/compat/images/mac/book.pngbin0 -> 1477 bytes
-rw-r--r--tools/assistant/compat/images/mac/closetab.pngbin0 -> 516 bytes
-rw-r--r--tools/assistant/compat/images/mac/editcopy.pngbin0 -> 1468 bytes
-rw-r--r--tools/assistant/compat/images/mac/find.pngbin0 -> 1836 bytes
-rw-r--r--tools/assistant/compat/images/mac/home.pngbin0 -> 1807 bytes
-rw-r--r--tools/assistant/compat/images/mac/next.pngbin0 -> 1310 bytes
-rw-r--r--tools/assistant/compat/images/mac/prev.pngbin0 -> 1080 bytes
-rw-r--r--tools/assistant/compat/images/mac/print.pngbin0 -> 2087 bytes
-rw-r--r--tools/assistant/compat/images/mac/synctoc.pngbin0 -> 1838 bytes
-rw-r--r--tools/assistant/compat/images/mac/whatsthis.pngbin0 -> 1586 bytes
-rw-r--r--tools/assistant/compat/images/mac/zoomin.pngbin0 -> 1696 bytes
-rw-r--r--tools/assistant/compat/images/mac/zoomout.pngbin0 -> 1662 bytes
-rw-r--r--tools/assistant/compat/images/qt.pngbin0 -> 1422 bytes
-rw-r--r--tools/assistant/compat/images/win/addtab.pngbin0 -> 314 bytes
-rw-r--r--tools/assistant/compat/images/win/book.pngbin0 -> 1109 bytes
-rw-r--r--tools/assistant/compat/images/win/closetab.pngbin0 -> 375 bytes
-rw-r--r--tools/assistant/compat/images/win/editcopy.pngbin0 -> 1325 bytes
-rw-r--r--tools/assistant/compat/images/win/find.pngbin0 -> 1944 bytes
-rw-r--r--tools/assistant/compat/images/win/home.pngbin0 -> 1414 bytes
-rw-r--r--tools/assistant/compat/images/win/next.pngbin0 -> 1038 bytes
-rw-r--r--tools/assistant/compat/images/win/previous.pngbin0 -> 898 bytes
-rw-r--r--tools/assistant/compat/images/win/print.pngbin0 -> 1456 bytes
-rw-r--r--tools/assistant/compat/images/win/synctoc.pngbin0 -> 1235 bytes
-rw-r--r--tools/assistant/compat/images/win/whatsthis.pngbin0 -> 1040 bytes
-rw-r--r--tools/assistant/compat/images/win/zoomin.pngbin0 -> 1208 bytes
-rw-r--r--tools/assistant/compat/images/win/zoomout.pngbin0 -> 1226 bytes
-rw-r--r--tools/assistant/compat/images/wrap.pngbin0 -> 500 bytes
-rw-r--r--tools/assistant/compat/index.cpp581
-rw-r--r--tools/assistant/compat/index.h133
-rw-r--r--tools/assistant/compat/lib/lib.pro78
-rw-r--r--tools/assistant/compat/lib/qassistantclient.cpp447
-rw-r--r--tools/assistant/compat/lib/qassistantclient.h100
-rw-r--r--tools/assistant/compat/lib/qassistantclient_global.h63
-rw-r--r--tools/assistant/compat/main.cpp465
-rw-r--r--tools/assistant/compat/mainwindow.cpp901
-rw-r--r--tools/assistant/compat/mainwindow.h137
-rw-r--r--tools/assistant/compat/mainwindow.ui459
-rw-r--r--tools/assistant/compat/profile.cpp196
-rw-r--r--tools/assistant/compat/profile.h95
-rw-r--r--tools/assistant/compat/tabbedbrowser.cpp530
-rw-r--r--tools/assistant/compat/tabbedbrowser.h122
-rw-r--r--tools/assistant/compat/tabbedbrowser.ui233
-rw-r--r--tools/assistant/compat/topicchooser.cpp101
-rw-r--r--tools/assistant/compat/topicchooser.h77
-rw-r--r--tools/assistant/compat/topicchooser.ui162
-rw-r--r--tools/assistant/compat/translations/translations.pro34
-rw-r--r--tools/assistant/lib/fulltextsearch/fulltextsearch.pri161
-rw-r--r--tools/assistant/lib/fulltextsearch/fulltextsearch.pro50
-rw-r--r--tools/assistant/lib/fulltextsearch/license.txt503
-rw-r--r--tools/assistant/lib/fulltextsearch/qanalyzer.cpp201
-rw-r--r--tools/assistant/lib/fulltextsearch/qanalyzer_p.h145
-rw-r--r--tools/assistant/lib/fulltextsearch/qclucene-config_p.h552
-rw-r--r--tools/assistant/lib/fulltextsearch/qclucene_global_p.h127
-rw-r--r--tools/assistant/lib/fulltextsearch/qdocument.cpp172
-rw-r--r--tools/assistant/lib/fulltextsearch/qdocument_p.h93
-rw-r--r--tools/assistant/lib/fulltextsearch/qfield.cpp163
-rw-r--r--tools/assistant/lib/fulltextsearch/qfield_p.h112
-rw-r--r--tools/assistant/lib/fulltextsearch/qfilter.cpp49
-rw-r--r--tools/assistant/lib/fulltextsearch/qfilter_p.h68
-rw-r--r--tools/assistant/lib/fulltextsearch/qhits.cpp86
-rw-r--r--tools/assistant/lib/fulltextsearch/qhits_p.h79
-rw-r--r--tools/assistant/lib/fulltextsearch/qindexreader.cpp161
-rw-r--r--tools/assistant/lib/fulltextsearch/qindexreader_p.h108
-rw-r--r--tools/assistant/lib/fulltextsearch/qindexwriter.cpp183
-rw-r--r--tools/assistant/lib/fulltextsearch/qindexwriter_p.h117
-rw-r--r--tools/assistant/lib/fulltextsearch/qquery.cpp350
-rw-r--r--tools/assistant/lib/fulltextsearch/qquery_p.h181
-rw-r--r--tools/assistant/lib/fulltextsearch/qqueryparser.cpp168
-rw-r--r--tools/assistant/lib/fulltextsearch/qqueryparser_p.h102
-rw-r--r--tools/assistant/lib/fulltextsearch/qreader.cpp94
-rw-r--r--tools/assistant/lib/fulltextsearch/qreader_p.h97
-rw-r--r--tools/assistant/lib/fulltextsearch/qsearchable.cpp195
-rw-r--r--tools/assistant/lib/fulltextsearch/qsearchable_p.h128
-rw-r--r--tools/assistant/lib/fulltextsearch/qsort.cpp89
-rw-r--r--tools/assistant/lib/fulltextsearch/qsort_p.h77
-rw-r--r--tools/assistant/lib/fulltextsearch/qterm.cpp126
-rw-r--r--tools/assistant/lib/fulltextsearch/qterm_p.h93
-rw-r--r--tools/assistant/lib/fulltextsearch/qtoken.cpp142
-rw-r--r--tools/assistant/lib/fulltextsearch/qtoken_p.h105
-rw-r--r--tools/assistant/lib/fulltextsearch/qtokenizer.cpp110
-rw-r--r--tools/assistant/lib/fulltextsearch/qtokenizer_p.h90
-rw-r--r--tools/assistant/lib/fulltextsearch/qtokenstream.cpp59
-rw-r--r--tools/assistant/lib/fulltextsearch/qtokenstream_p.h88
-rw-r--r--tools/assistant/lib/helpsystem.qrc8
-rw-r--r--tools/assistant/lib/images/1leftarrow.pngbin0 -> 669 bytes
-rw-r--r--tools/assistant/lib/images/1rightarrow.pngbin0 -> 706 bytes
-rw-r--r--tools/assistant/lib/images/3leftarrow.pngbin0 -> 832 bytes
-rw-r--r--tools/assistant/lib/images/3rightarrow.pngbin0 -> 820 bytes
-rw-r--r--tools/assistant/lib/lib.pro65
-rw-r--r--tools/assistant/lib/qhelp_global.h124
-rw-r--r--tools/assistant/lib/qhelpcollectionhandler.cpp595
-rw-r--r--tools/assistant/lib/qhelpcollectionhandler_p.h123
-rw-r--r--tools/assistant/lib/qhelpcontentwidget.cpp585
-rw-r--r--tools/assistant/lib/qhelpcontentwidget.h146
-rw-r--r--tools/assistant/lib/qhelpdatainterface.cpp273
-rw-r--r--tools/assistant/lib/qhelpdatainterface_p.h155
-rw-r--r--tools/assistant/lib/qhelpdbreader.cpp580
-rw-r--r--tools/assistant/lib/qhelpdbreader_p.h128
-rw-r--r--tools/assistant/lib/qhelpengine.cpp212
-rw-r--r--tools/assistant/lib/qhelpengine.h84
-rw-r--r--tools/assistant/lib/qhelpengine_p.h144
-rw-r--r--tools/assistant/lib/qhelpenginecore.cpp727
-rw-r--r--tools/assistant/lib/qhelpenginecore.h136
-rw-r--r--tools/assistant/lib/qhelpgenerator.cpp823
-rw-r--r--tools/assistant/lib/qhelpgenerator_p.h117
-rw-r--r--tools/assistant/lib/qhelpindexwidget.cpp445
-rw-r--r--tools/assistant/lib/qhelpindexwidget.h114
-rw-r--r--tools/assistant/lib/qhelpprojectdata.cpp374
-rw-r--r--tools/assistant/lib/qhelpprojectdata_p.h89
-rw-r--r--tools/assistant/lib/qhelpsearchengine.cpp445
-rw-r--r--tools/assistant/lib/qhelpsearchengine.h121
-rw-r--r--tools/assistant/lib/qhelpsearchindex_default.cpp60
-rw-r--r--tools/assistant/lib/qhelpsearchindex_default_p.h149
-rw-r--r--tools/assistant/lib/qhelpsearchindexreader_clucene.cpp392
-rw-r--r--tools/assistant/lib/qhelpsearchindexreader_clucene_p.h121
-rw-r--r--tools/assistant/lib/qhelpsearchindexreader_default.cpp653
-rw-r--r--tools/assistant/lib/qhelpsearchindexreader_default_p.h165
-rw-r--r--tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp481
-rw-r--r--tools/assistant/lib/qhelpsearchindexwriter_clucene_p.h123
-rw-r--r--tools/assistant/lib/qhelpsearchindexwriter_default.cpp385
-rw-r--r--tools/assistant/lib/qhelpsearchindexwriter_default_p.h132
-rw-r--r--tools/assistant/lib/qhelpsearchquerywidget.cpp353
-rw-r--r--tools/assistant/lib/qhelpsearchquerywidget.h87
-rw-r--r--tools/assistant/lib/qhelpsearchresultwidget.cpp439
-rw-r--r--tools/assistant/lib/qhelpsearchresultwidget.h84
-rw-r--r--tools/assistant/tools/assistant/Info_mac.plist18
-rw-r--r--tools/assistant/tools/assistant/aboutdialog.cpp171
-rw-r--r--tools/assistant/tools/assistant/aboutdialog.h91
-rw-r--r--tools/assistant/tools/assistant/assistant.icnsbin0 -> 162568 bytes
-rw-r--r--tools/assistant/tools/assistant/assistant.icobin0 -> 355574 bytes
-rw-r--r--tools/assistant/tools/assistant/assistant.pro89
-rw-r--r--tools/assistant/tools/assistant/assistant.qchbin0 -> 366592 bytes
-rw-r--r--tools/assistant/tools/assistant/assistant.qrc5
-rw-r--r--tools/assistant/tools/assistant/assistant.rc1
-rw-r--r--tools/assistant/tools/assistant/assistant_images.qrc36
-rw-r--r--tools/assistant/tools/assistant/bookmarkdialog.ui146
-rw-r--r--tools/assistant/tools/assistant/bookmarkmanager.cpp874
-rw-r--r--tools/assistant/tools/assistant/bookmarkmanager.h205
-rw-r--r--tools/assistant/tools/assistant/centralwidget.cpp1080
-rw-r--r--tools/assistant/tools/assistant/centralwidget.h194
-rw-r--r--tools/assistant/tools/assistant/cmdlineparser.cpp320
-rw-r--r--tools/assistant/tools/assistant/cmdlineparser.h99
-rw-r--r--tools/assistant/tools/assistant/contentwindow.cpp173
-rw-r--r--tools/assistant/tools/assistant/contentwindow.h86
-rw-r--r--tools/assistant/tools/assistant/doc/HOWTO17
-rw-r--r--tools/assistant/tools/assistant/doc/assistant.qdoc434
-rw-r--r--tools/assistant/tools/assistant/doc/assistant.qdocconf17
-rw-r--r--tools/assistant/tools/assistant/doc/assistant.qhp22
-rw-r--r--tools/assistant/tools/assistant/doc/classic.css92
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-address-toolbar.pngbin0 -> 2899 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-assistant.pngbin0 -> 105954 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-dockwidgets.pngbin0 -> 50554 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-docwindow.pngbin0 -> 55582 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-examples.pngbin0 -> 9799 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-filter-toolbar.pngbin0 -> 1767 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-preferences-documentation.pngbin0 -> 13417 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-preferences-filters.pngbin0 -> 15561 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-preferences-fonts.pngbin0 -> 13139 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-preferences-options.pngbin0 -> 14255 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-search.pngbin0 -> 59254 bytes
-rw-r--r--tools/assistant/tools/assistant/doc/images/assistant-toolbar.pngbin0 -> 6532 bytes
-rw-r--r--tools/assistant/tools/assistant/filternamedialog.cpp73
-rw-r--r--tools/assistant/tools/assistant/filternamedialog.h67
-rw-r--r--tools/assistant/tools/assistant/filternamedialog.ui67
-rw-r--r--tools/assistant/tools/assistant/helpviewer.cpp556
-rw-r--r--tools/assistant/tools/assistant/helpviewer.h169
-rw-r--r--tools/assistant/tools/assistant/images/assistant-128.pngbin0 -> 6448 bytes
-rw-r--r--tools/assistant/tools/assistant/images/assistant.pngbin0 -> 2034 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/addtab.pngbin0 -> 469 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/book.pngbin0 -> 1477 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/closetab.pngbin0 -> 516 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/editcopy.pngbin0 -> 1468 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/find.pngbin0 -> 1836 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/home.pngbin0 -> 1807 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/next.pngbin0 -> 1310 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/previous.pngbin0 -> 1080 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/print.pngbin0 -> 2087 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/resetzoom.pngbin0 -> 1567 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/synctoc.pngbin0 -> 1838 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/zoomin.pngbin0 -> 1696 bytes
-rw-r--r--tools/assistant/tools/assistant/images/mac/zoomout.pngbin0 -> 1662 bytes
-rw-r--r--tools/assistant/tools/assistant/images/trolltech-logo.pngbin0 -> 10096 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/addtab.pngbin0 -> 314 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/book.pngbin0 -> 1109 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/closetab.pngbin0 -> 375 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/editcopy.pngbin0 -> 1325 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/find.pngbin0 -> 1944 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/home.pngbin0 -> 1414 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/next.pngbin0 -> 1038 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/previous.pngbin0 -> 898 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/print.pngbin0 -> 1456 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/resetzoom.pngbin0 -> 1134 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/synctoc.pngbin0 -> 1235 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/zoomin.pngbin0 -> 1208 bytes
-rw-r--r--tools/assistant/tools/assistant/images/win/zoomout.pngbin0 -> 1226 bytes
-rw-r--r--tools/assistant/tools/assistant/images/wrap.pngbin0 -> 500 bytes
-rw-r--r--tools/assistant/tools/assistant/indexwindow.cpp216
-rw-r--r--tools/assistant/tools/assistant/indexwindow.h90
-rw-r--r--tools/assistant/tools/assistant/installdialog.cpp338
-rw-r--r--tools/assistant/tools/assistant/installdialog.h101
-rw-r--r--tools/assistant/tools/assistant/installdialog.ui118
-rw-r--r--tools/assistant/tools/assistant/main.cpp318
-rw-r--r--tools/assistant/tools/assistant/mainwindow.cpp1008
-rw-r--r--tools/assistant/tools/assistant/mainwindow.h172
-rw-r--r--tools/assistant/tools/assistant/preferencesdialog.cpp453
-rw-r--r--tools/assistant/tools/assistant/preferencesdialog.h106
-rw-r--r--tools/assistant/tools/assistant/preferencesdialog.ui310
-rw-r--r--tools/assistant/tools/assistant/qtdocinstaller.cpp151
-rw-r--r--tools/assistant/tools/assistant/qtdocinstaller.h77
-rw-r--r--tools/assistant/tools/assistant/remotecontrol.cpp283
-rw-r--r--tools/assistant/tools/assistant/remotecontrol.h84
-rw-r--r--tools/assistant/tools/assistant/remotecontrol_win.h68
-rw-r--r--tools/assistant/tools/assistant/searchwidget.cpp246
-rw-r--r--tools/assistant/tools/assistant/searchwidget.h90
-rw-r--r--tools/assistant/tools/assistant/topicchooser.cpp86
-rw-r--r--tools/assistant/tools/assistant/topicchooser.h72
-rw-r--r--tools/assistant/tools/assistant/topicchooser.ui116
-rw-r--r--tools/assistant/tools/qcollectiongenerator/main.cpp559
-rw-r--r--tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro14
-rw-r--r--tools/assistant/tools/qhelpconverter/adpreader.cpp171
-rw-r--r--tools/assistant/tools/qhelpconverter/adpreader.h90
-rw-r--r--tools/assistant/tools/qhelpconverter/assistant-128.pngbin0 -> 6448 bytes
-rw-r--r--tools/assistant/tools/qhelpconverter/assistant.pngbin0 -> 2034 bytes
-rw-r--r--tools/assistant/tools/qhelpconverter/conversionwizard.cpp265
-rw-r--r--tools/assistant/tools/qhelpconverter/conversionwizard.h96
-rw-r--r--tools/assistant/tools/qhelpconverter/doc/filespage.html8
-rw-r--r--tools/assistant/tools/qhelpconverter/doc/filterpage.html13
-rw-r--r--tools/assistant/tools/qhelpconverter/doc/generalpage.html10
-rw-r--r--tools/assistant/tools/qhelpconverter/doc/identifierpage.html17
-rw-r--r--tools/assistant/tools/qhelpconverter/doc/inputpage.html7
-rw-r--r--tools/assistant/tools/qhelpconverter/doc/outputpage.html7
-rw-r--r--tools/assistant/tools/qhelpconverter/doc/pathpage.html8
-rw-r--r--tools/assistant/tools/qhelpconverter/filespage.cpp112
-rw-r--r--tools/assistant/tools/qhelpconverter/filespage.h73
-rw-r--r--tools/assistant/tools/qhelpconverter/filespage.ui79
-rw-r--r--tools/assistant/tools/qhelpconverter/filterpage.cpp147
-rw-r--r--tools/assistant/tools/qhelpconverter/filterpage.h79
-rw-r--r--tools/assistant/tools/qhelpconverter/filterpage.ui125
-rw-r--r--tools/assistant/tools/qhelpconverter/finishpage.cpp76
-rw-r--r--tools/assistant/tools/qhelpconverter/finishpage.h65
-rw-r--r--tools/assistant/tools/qhelpconverter/generalpage.cpp92
-rw-r--r--tools/assistant/tools/qhelpconverter/generalpage.h66
-rw-r--r--tools/assistant/tools/qhelpconverter/generalpage.ui69
-rw-r--r--tools/assistant/tools/qhelpconverter/helpwindow.cpp84
-rw-r--r--tools/assistant/tools/qhelpconverter/helpwindow.h65
-rw-r--r--tools/assistant/tools/qhelpconverter/identifierpage.cpp71
-rw-r--r--tools/assistant/tools/qhelpconverter/identifierpage.h66
-rw-r--r--tools/assistant/tools/qhelpconverter/identifierpage.ui132
-rw-r--r--tools/assistant/tools/qhelpconverter/inputpage.cpp103
-rw-r--r--tools/assistant/tools/qhelpconverter/inputpage.h71
-rw-r--r--tools/assistant/tools/qhelpconverter/inputpage.ui79
-rw-r--r--tools/assistant/tools/qhelpconverter/main.cpp62
-rw-r--r--tools/assistant/tools/qhelpconverter/outputpage.cpp110
-rw-r--r--tools/assistant/tools/qhelpconverter/outputpage.h71
-rw-r--r--tools/assistant/tools/qhelpconverter/outputpage.ui95
-rw-r--r--tools/assistant/tools/qhelpconverter/pathpage.cpp112
-rw-r--r--tools/assistant/tools/qhelpconverter/pathpage.h71
-rw-r--r--tools/assistant/tools/qhelpconverter/pathpage.ui114
-rw-r--r--tools/assistant/tools/qhelpconverter/qhcpwriter.cpp145
-rw-r--r--tools/assistant/tools/qhelpconverter/qhcpwriter.h70
-rw-r--r--tools/assistant/tools/qhelpconverter/qhelpconverter.pro47
-rw-r--r--tools/assistant/tools/qhelpconverter/qhelpconverter.qrc13
-rw-r--r--tools/assistant/tools/qhelpconverter/qhpwriter.cpp184
-rw-r--r--tools/assistant/tools/qhelpconverter/qhpwriter.h85
-rw-r--r--tools/assistant/tools/qhelpgenerator/main.cpp144
-rw-r--r--tools/assistant/tools/qhelpgenerator/qhelpgenerator.pro14
-rw-r--r--tools/assistant/tools/shared/helpgenerator.cpp79
-rw-r--r--tools/assistant/tools/shared/helpgenerator.h72
-rw-r--r--tools/assistant/tools/tools.pro8
-rw-r--r--tools/assistant/translations/qt_help.pro49
-rw-r--r--tools/assistant/translations/translations.pro49
-rw-r--r--tools/assistant/translations/translations_adp.pro41
-rw-r--r--tools/checksdk/README3
-rw-r--r--tools/checksdk/cesdkhandler.cpp131
-rw-r--r--tools/checksdk/cesdkhandler.h111
-rw-r--r--tools/checksdk/checksdk.pro71
-rw-r--r--tools/checksdk/main.cpp159
-rw-r--r--tools/configure/configure.pro106
-rw-r--r--tools/configure/configure_pch.h74
-rw-r--r--tools/configure/configureapp.cpp3586
-rw-r--r--tools/configure/configureapp.h185
-rw-r--r--tools/configure/environment.cpp686
-rw-r--r--tools/configure/environment.h84
-rw-r--r--tools/configure/main.cpp114
-rw-r--r--tools/configure/tools.cpp172
-rw-r--r--tools/configure/tools.h17
-rw-r--r--tools/designer/data/generate_header.xsl465
-rw-r--r--tools/designer/data/generate_impl.xsl1161
-rw-r--r--tools/designer/data/generate_shared.xsl331
-rw-r--r--tools/designer/data/ui3.xsd353
-rw-r--r--tools/designer/data/ui4.xsd574
-rw-r--r--tools/designer/designer.pro5
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor.cpp447
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor.h92
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor.pri16
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor_global.h57
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor_instance.cpp50
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp136
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor_plugin.h93
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor_tool.cpp115
-rw-r--r--tools/designer/src/components/buddyeditor/buddyeditor_tool.h89
-rw-r--r--tools/designer/src/components/component.pri2
-rw-r--r--tools/designer/src/components/components.pro3
-rw-r--r--tools/designer/src/components/formeditor/brushmanagerproxy.cpp305
-rw-r--r--tools/designer/src/components/formeditor/brushmanagerproxy.h77
-rw-r--r--tools/designer/src/components/formeditor/default_actionprovider.cpp208
-rw-r--r--tools/designer/src/components/formeditor/default_actionprovider.h131
-rw-r--r--tools/designer/src/components/formeditor/default_container.cpp173
-rw-r--r--tools/designer/src/components/formeditor/default_container.h213
-rw-r--r--tools/designer/src/components/formeditor/default_layoutdecoration.cpp79
-rw-r--r--tools/designer/src/components/formeditor/default_layoutdecoration.h69
-rw-r--r--tools/designer/src/components/formeditor/defaultbrushes.xml542
-rw-r--r--tools/designer/src/components/formeditor/deviceprofiledialog.cpp203
-rw-r--r--tools/designer/src/components/formeditor/deviceprofiledialog.h104
-rw-r--r--tools/designer/src/components/formeditor/deviceprofiledialog.ui100
-rw-r--r--tools/designer/src/components/formeditor/dpi_chooser.cpp207
-rw-r--r--tools/designer/src/components/formeditor/dpi_chooser.h94
-rw-r--r--tools/designer/src/components/formeditor/embeddedoptionspage.cpp457
-rw-r--r--tools/designer/src/components/formeditor/embeddedoptionspage.h103
-rw-r--r--tools/designer/src/components/formeditor/formeditor.cpp203
-rw-r--r--tools/designer/src/components/formeditor/formeditor.h69
-rw-r--r--tools/designer/src/components/formeditor/formeditor.pri75
-rw-r--r--tools/designer/src/components/formeditor/formeditor.qrc173
-rw-r--r--tools/designer/src/components/formeditor/formeditor_global.h57
-rw-r--r--tools/designer/src/components/formeditor/formeditor_optionspage.cpp189
-rw-r--r--tools/designer/src/components/formeditor/formeditor_optionspage.h79
-rw-r--r--tools/designer/src/components/formeditor/formwindow.cpp2921
-rw-r--r--tools/designer/src/components/formeditor/formwindow.h385
-rw-r--r--tools/designer/src/components/formeditor/formwindow_dnditem.cpp116
-rw-r--r--tools/designer/src/components/formeditor/formwindow_dnditem.h65
-rw-r--r--tools/designer/src/components/formeditor/formwindow_widgetstack.cpp213
-rw-r--r--tools/designer/src/components/formeditor/formwindow_widgetstack.h103
-rw-r--r--tools/designer/src/components/formeditor/formwindowcursor.cpp215
-rw-r--r--tools/designer/src/components/formeditor/formwindowcursor.h93
-rw-r--r--tools/designer/src/components/formeditor/formwindowmanager.cpp1020
-rw-r--r--tools/designer/src/components/formeditor/formwindowmanager.h200
-rw-r--r--tools/designer/src/components/formeditor/formwindowsettings.cpp282
-rw-r--r--tools/designer/src/components/formeditor/formwindowsettings.h85
-rw-r--r--tools/designer/src/components/formeditor/formwindowsettings.ui328
-rw-r--r--tools/designer/src/components/formeditor/iconcache.cpp121
-rw-r--r--tools/designer/src/components/formeditor/iconcache.h78
-rw-r--r--tools/designer/src/components/formeditor/images/color.pngbin0 -> 117 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/configure.pngbin0 -> 1016 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/arrow.pngbin0 -> 171 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/busy.pngbin0 -> 201 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/closedhand.pngbin0 -> 147 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/cross.pngbin0 -> 130 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/hand.pngbin0 -> 159 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/hsplit.pngbin0 -> 155 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/ibeam.pngbin0 -> 124 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/no.pngbin0 -> 199 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/openhand.pngbin0 -> 160 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/sizeall.pngbin0 -> 174 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/sizeb.pngbin0 -> 161 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/sizef.pngbin0 -> 161 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/sizeh.pngbin0 -> 145 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/sizev.pngbin0 -> 141 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/uparrow.pngbin0 -> 132 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/vsplit.pngbin0 -> 161 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/wait.pngbin0 -> 172 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/cursors/whatsthis.pngbin0 -> 191 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/downplus.pngbin0 -> 562 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/dropdownbutton.pngbin0 -> 527 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/edit.pngbin0 -> 929 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/editdelete-16.pngbin0 -> 553 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/emptyicon.pngbin0 -> 108 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/filenew-16.pngbin0 -> 454 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/fileopen-16.pngbin0 -> 549 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/leveldown.pngbin0 -> 557 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/levelup.pngbin0 -> 564 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/adjustsize.pngbin0 -> 1929 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/back.pngbin0 -> 678 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/buddytool.pngbin0 -> 2046 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/down.pngbin0 -> 594 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editbreaklayout.pngbin0 -> 2067 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editcopy.pngbin0 -> 1468 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editcut.pngbin0 -> 1512 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editdelete.pngbin0 -> 1097 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editform.pngbin0 -> 621 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editgrid.pngbin0 -> 751 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/edithlayout.pngbin0 -> 1395 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/edithlayoutsplit.pngbin0 -> 1188 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editlower.pngbin0 -> 595 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editpaste.pngbin0 -> 1906 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editraise.pngbin0 -> 1213 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editvlayout.pngbin0 -> 586 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/editvlayoutsplit.pngbin0 -> 872 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/filenew.pngbin0 -> 772 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/fileopen.pngbin0 -> 904 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/filesave.pngbin0 -> 1206 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/forward.pngbin0 -> 655 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/insertimage.pngbin0 -> 1280 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/minus.pngbin0 -> 488 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/plus.pngbin0 -> 810 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/redo.pngbin0 -> 1752 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/resetproperty.pngbin0 -> 169 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/resourceeditortool.pngbin0 -> 2171 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/signalslottool.pngbin0 -> 1989 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/tabordertool.pngbin0 -> 1963 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textanchor.pngbin0 -> 2543 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textbold.pngbin0 -> 1611 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textcenter.pngbin0 -> 1404 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textitalic.pngbin0 -> 1164 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textjustify.pngbin0 -> 1257 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textleft.pngbin0 -> 1235 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textright.pngbin0 -> 1406 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textsubscript.pngbin0 -> 1054 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textsuperscript.pngbin0 -> 1109 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/textunder.pngbin0 -> 1183 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/undo.pngbin0 -> 1746 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/up.pngbin0 -> 692 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/mac/widgettool.pngbin0 -> 1874 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/minus-16.pngbin0 -> 296 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/plus-16.pngbin0 -> 383 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/prefix-add.pngbin0 -> 411 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/qt3logo.pngbin0 -> 1101 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/qtlogo.pngbin0 -> 825 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/reload.pngbin0 -> 1363 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/resetproperty.pngbin0 -> 169 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/sort.pngbin0 -> 563 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/submenu.pngbin0 -> 179 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/calendarwidget.pngbin0 -> 968 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/checkbox.pngbin0 -> 817 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/columnview.pngbin0 -> 518 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/combobox.pngbin0 -> 853 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/commandlinkbutton.pngbin0 -> 1208 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/dateedit.pngbin0 -> 672 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/datetimeedit.pngbin0 -> 1132 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/dial.pngbin0 -> 978 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/dialogbuttonbox.pngbin0 -> 1003 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/dockwidget.pngbin0 -> 638 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/doublespinbox.pngbin0 -> 749 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/fontcombobox.pngbin0 -> 966 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/frame.pngbin0 -> 721 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/graphicsview.pngbin0 -> 1182 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/groupbox.pngbin0 -> 439 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/groupboxcollapsible.pngbin0 -> 702 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/hscrollbar.pngbin0 -> 408 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/hslider.pngbin0 -> 729 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/hsplit.pngbin0 -> 164 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/label.pngbin0 -> 953 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/lcdnumber.pngbin0 -> 555 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/line.pngbin0 -> 287 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/lineedit.pngbin0 -> 405 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/listbox.pngbin0 -> 797 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/listview.pngbin0 -> 756 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/mdiarea.pngbin0 -> 643 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/plaintextedit.pngbin0 -> 807 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/progress.pngbin0 -> 559 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/pushbutton.pngbin0 -> 408 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/radiobutton.pngbin0 -> 586 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/scrollarea.pngbin0 -> 548 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/spacer.pngbin0 -> 686 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/spinbox.pngbin0 -> 680 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/tabbar.pngbin0 -> 623 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/table.pngbin0 -> 483 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/tabwidget.pngbin0 -> 572 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/textedit.pngbin0 -> 823 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/timeedit.pngbin0 -> 1353 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/toolbox.pngbin0 -> 783 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/toolbutton.pngbin0 -> 1167 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/vline.pngbin0 -> 314 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/vscrollbar.pngbin0 -> 415 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/vslider.pngbin0 -> 726 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/vspacer.pngbin0 -> 677 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/widget.pngbin0 -> 716 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/widgetstack.pngbin0 -> 828 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/widgets/wizard.pngbin0 -> 898 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/adjustsize.pngbin0 -> 1262 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/back.pngbin0 -> 678 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/buddytool.pngbin0 -> 997 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/down.pngbin0 -> 594 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editbreaklayout.pngbin0 -> 1321 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editcopy.pngbin0 -> 1325 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editcut.pngbin0 -> 1384 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editdelete.pngbin0 -> 850 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editform.pngbin0 -> 349 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editgrid.pngbin0 -> 349 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/edithlayout.pngbin0 -> 455 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/edithlayoutsplit.pngbin0 -> 860 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editlower.pngbin0 -> 1038 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editpaste.pngbin0 -> 1482 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editraise.pngbin0 -> 1045 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editvlayout.pngbin0 -> 340 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/editvlayoutsplit.pngbin0 -> 740 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/filenew.pngbin0 -> 768 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/fileopen.pngbin0 -> 1662 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/filesave.pngbin0 -> 1205 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/forward.pngbin0 -> 655 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/insertimage.pngbin0 -> 885 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/minus.pngbin0 -> 429 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/plus.pngbin0 -> 709 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/redo.pngbin0 -> 1212 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/resourceeditortool.pngbin0 -> 1429 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/signalslottool.pngbin0 -> 1128 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/tabordertool.pngbin0 -> 1205 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textanchor.pngbin0 -> 1581 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textbold.pngbin0 -> 1134 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textcenter.pngbin0 -> 627 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textitalic.pngbin0 -> 829 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textjustify.pngbin0 -> 695 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textleft.pngbin0 -> 673 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textright.pngbin0 -> 677 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textsubscript.pngbin0 -> 897 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textsuperscript.pngbin0 -> 864 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/textunder.pngbin0 -> 971 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/undo.pngbin0 -> 1181 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/up.pngbin0 -> 692 bytes
-rw-r--r--tools/designer/src/components/formeditor/images/win/widgettool.pngbin0 -> 1039 bytes
-rw-r--r--tools/designer/src/components/formeditor/itemview_propertysheet.cpp291
-rw-r--r--tools/designer/src/components/formeditor/itemview_propertysheet.h88
-rw-r--r--tools/designer/src/components/formeditor/layout_propertysheet.cpp546
-rw-r--r--tools/designer/src/components/formeditor/layout_propertysheet.h82
-rw-r--r--tools/designer/src/components/formeditor/line_propertysheet.cpp86
-rw-r--r--tools/designer/src/components/formeditor/line_propertysheet.h71
-rw-r--r--tools/designer/src/components/formeditor/previewactiongroup.cpp149
-rw-r--r--tools/designer/src/components/formeditor/previewactiongroup.h90
-rw-r--r--tools/designer/src/components/formeditor/qdesigner_resource.cpp2665
-rw-r--r--tools/designer/src/components/formeditor/qdesigner_resource.h182
-rw-r--r--tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp83
-rw-r--r--tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.h72
-rw-r--r--tools/designer/src/components/formeditor/qmainwindow_container.cpp199
-rw-r--r--tools/designer/src/components/formeditor/qmainwindow_container.h81
-rw-r--r--tools/designer/src/components/formeditor/qmdiarea_container.cpp280
-rw-r--r--tools/designer/src/components/formeditor/qmdiarea_container.h119
-rw-r--r--tools/designer/src/components/formeditor/qtbrushmanager.cpp143
-rw-r--r--tools/designer/src/components/formeditor/qtbrushmanager.h89
-rw-r--r--tools/designer/src/components/formeditor/qwizard_container.cpp226
-rw-r--r--tools/designer/src/components/formeditor/qwizard_container.h123
-rw-r--r--tools/designer/src/components/formeditor/qworkspace_container.cpp100
-rw-r--r--tools/designer/src/components/formeditor/qworkspace_container.h79
-rw-r--r--tools/designer/src/components/formeditor/spacer_propertysheet.cpp82
-rw-r--r--tools/designer/src/components/formeditor/spacer_propertysheet.h72
-rw-r--r--tools/designer/src/components/formeditor/templateoptionspage.cpp183
-rw-r--r--tools/designer/src/components/formeditor/templateoptionspage.h110
-rw-r--r--tools/designer/src/components/formeditor/templateoptionspage.ui59
-rw-r--r--tools/designer/src/components/formeditor/tool_widgeteditor.cpp367
-rw-r--r--tools/designer/src/components/formeditor/tool_widgeteditor.h107
-rw-r--r--tools/designer/src/components/formeditor/widgetselection.cpp746
-rw-r--r--tools/designer/src/components/formeditor/widgetselection.h145
-rw-r--r--tools/designer/src/components/lib/lib.pro74
-rw-r--r--tools/designer/src/components/lib/lib_pch.h43
-rw-r--r--tools/designer/src/components/lib/qdesigner_components.cpp277
-rw-r--r--tools/designer/src/components/objectinspector/objectinspector.cpp839
-rw-r--r--tools/designer/src/components/objectinspector/objectinspector.h95
-rw-r--r--tools/designer/src/components/objectinspector/objectinspector.pri10
-rw-r--r--tools/designer/src/components/objectinspector/objectinspector_global.h61
-rw-r--r--tools/designer/src/components/objectinspector/objectinspectormodel.cpp520
-rw-r--r--tools/designer/src/components/objectinspector/objectinspectormodel_p.h168
-rw-r--r--tools/designer/src/components/propertyeditor/brushpropertymanager.cpp288
-rw-r--r--tools/designer/src/components/propertyeditor/brushpropertymanager.h105
-rw-r--r--tools/designer/src/components/propertyeditor/defs.cpp107
-rw-r--r--tools/designer/src/components/propertyeditor/defs.h60
-rw-r--r--tools/designer/src/components/propertyeditor/designerpropertymanager.cpp2604
-rw-r--r--tools/designer/src/components/propertyeditor/designerpropertymanager.h312
-rw-r--r--tools/designer/src/components/propertyeditor/fontmapping.xml73
-rw-r--r--tools/designer/src/components/propertyeditor/fontpropertymanager.cpp377
-rw-r--r--tools/designer/src/components/propertyeditor/fontpropertymanager.h124
-rw-r--r--tools/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp170
-rw-r--r--tools/designer/src/components/propertyeditor/newdynamicpropertydialog.h104
-rw-r--r--tools/designer/src/components/propertyeditor/newdynamicpropertydialog.ui106
-rw-r--r--tools/designer/src/components/propertyeditor/paletteeditor.cpp623
-rw-r--r--tools/designer/src/components/propertyeditor/paletteeditor.h204
-rw-r--r--tools/designer/src/components/propertyeditor/paletteeditor.ui264
-rw-r--r--tools/designer/src/components/propertyeditor/paletteeditorbutton.cpp92
-rw-r--r--tools/designer/src/components/propertyeditor/paletteeditorbutton.h86
-rw-r--r--tools/designer/src/components/propertyeditor/previewframe.cpp123
-rw-r--r--tools/designer/src/components/propertyeditor/previewframe.h76
-rw-r--r--tools/designer/src/components/propertyeditor/previewwidget.cpp59
-rw-r--r--tools/designer/src/components/propertyeditor/previewwidget.h66
-rw-r--r--tools/designer/src/components/propertyeditor/previewwidget.ui238
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor.cpp1245
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor.h208
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor.pri47
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor.qrc5
-rw-r--r--tools/designer/src/components/propertyeditor/propertyeditor_global.h61
-rw-r--r--tools/designer/src/components/propertyeditor/qlonglongvalidator.cpp153
-rw-r--r--tools/designer/src/components/propertyeditor/qlonglongvalidator.h110
-rw-r--r--tools/designer/src/components/propertyeditor/stringlisteditor.cpp212
-rw-r--r--tools/designer/src/components/propertyeditor/stringlisteditor.h92
-rw-r--r--tools/designer/src/components/propertyeditor/stringlisteditor.ui265
-rw-r--r--tools/designer/src/components/propertyeditor/stringlisteditorbutton.cpp85
-rw-r--r--tools/designer/src/components/propertyeditor/stringlisteditorbutton.h81
-rw-r--r--tools/designer/src/components/signalsloteditor/connectdialog.cpp335
-rw-r--r--tools/designer/src/components/signalsloteditor/connectdialog.ui150
-rw-r--r--tools/designer/src/components/signalsloteditor/connectdialog_p.h109
-rw-r--r--tools/designer/src/components/signalsloteditor/signalslot_utils.cpp331
-rw-r--r--tools/designer/src/components/signalsloteditor/signalslot_utils_p.h104
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor.cpp528
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor.h98
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor.pri21
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor_global.h57
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp50
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor_p.h138
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp136
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.h92
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp127
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditor_tool.h93
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp859
-rw-r--r--tools/designer/src/components/signalsloteditor/signalsloteditorwindow.h94
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor.cpp433
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor.h109
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor.pri16
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor_global.h57
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor_instance.cpp49
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp135
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor_plugin.h93
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor_tool.cpp118
-rw-r--r--tools/designer/src/components/tabordereditor/tabordereditor_tool.h89
-rw-r--r--tools/designer/src/components/taskmenu/button_taskmenu.cpp713
-rw-r--r--tools/designer/src/components/taskmenu/button_taskmenu.h170
-rw-r--r--tools/designer/src/components/taskmenu/combobox_taskmenu.cpp137
-rw-r--r--tools/designer/src/components/taskmenu/combobox_taskmenu.h94
-rw-r--r--tools/designer/src/components/taskmenu/containerwidget_taskmenu.cpp353
-rw-r--r--tools/designer/src/components/taskmenu/containerwidget_taskmenu.h157
-rw-r--r--tools/designer/src/components/taskmenu/groupbox_taskmenu.cpp109
-rw-r--r--tools/designer/src/components/taskmenu/groupbox_taskmenu.h77
-rw-r--r--tools/designer/src/components/taskmenu/inplace_editor.cpp136
-rw-r--r--tools/designer/src/components/taskmenu/inplace_editor.h110
-rw-r--r--tools/designer/src/components/taskmenu/inplace_widget_helper.cpp120
-rw-r--r--tools/designer/src/components/taskmenu/inplace_widget_helper.h88
-rw-r--r--tools/designer/src/components/taskmenu/itemlisteditor.cpp489
-rw-r--r--tools/designer/src/components/taskmenu/itemlisteditor.h163
-rw-r--r--tools/designer/src/components/taskmenu/itemlisteditor.ui156
-rw-r--r--tools/designer/src/components/taskmenu/label_taskmenu.cpp121
-rw-r--r--tools/designer/src/components/taskmenu/label_taskmenu.h81
-rw-r--r--tools/designer/src/components/taskmenu/layouttaskmenu.cpp97
-rw-r--r--tools/designer/src/components/taskmenu/layouttaskmenu.h93
-rw-r--r--tools/designer/src/components/taskmenu/lineedit_taskmenu.cpp107
-rw-r--r--tools/designer/src/components/taskmenu/lineedit_taskmenu.h74
-rw-r--r--tools/designer/src/components/taskmenu/listwidget_taskmenu.cpp121
-rw-r--r--tools/designer/src/components/taskmenu/listwidget_taskmenu.h85
-rw-r--r--tools/designer/src/components/taskmenu/listwidgeteditor.cpp142
-rw-r--r--tools/designer/src/components/taskmenu/listwidgeteditor.h78
-rw-r--r--tools/designer/src/components/taskmenu/menutaskmenu.cpp111
-rw-r--r--tools/designer/src/components/taskmenu/menutaskmenu.h106
-rw-r--r--tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp119
-rw-r--r--tools/designer/src/components/taskmenu/tablewidget_taskmenu.h85
-rw-r--r--tools/designer/src/components/taskmenu/tablewidgeteditor.cpp407
-rw-r--r--tools/designer/src/components/taskmenu/tablewidgeteditor.h114
-rw-r--r--tools/designer/src/components/taskmenu/tablewidgeteditor.ui157
-rw-r--r--tools/designer/src/components/taskmenu/taskmenu.pri50
-rw-r--r--tools/designer/src/components/taskmenu/taskmenu_component.cpp106
-rw-r--r--tools/designer/src/components/taskmenu/taskmenu_component.h73
-rw-r--r--tools/designer/src/components/taskmenu/taskmenu_global.h57
-rw-r--r--tools/designer/src/components/taskmenu/textedit_taskmenu.cpp109
-rw-r--r--tools/designer/src/components/taskmenu/textedit_taskmenu.h89
-rw-r--r--tools/designer/src/components/taskmenu/toolbar_taskmenu.cpp115
-rw-r--r--tools/designer/src/components/taskmenu/toolbar_taskmenu.h99
-rw-r--r--tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp118
-rw-r--r--tools/designer/src/components/taskmenu/treewidget_taskmenu.h85
-rw-r--r--tools/designer/src/components/taskmenu/treewidgeteditor.cpp607
-rw-r--r--tools/designer/src/components/taskmenu/treewidgeteditor.h113
-rw-r--r--tools/designer/src/components/taskmenu/treewidgeteditor.ui257
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.cpp232
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.h103
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.pri14
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.qrc5
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox.xml932
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp215
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox_dnditem.h67
-rw-r--r--tools/designer/src/components/widgetbox/widgetbox_global.h57
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp494
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxcategorylistview.h118
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp998
-rw-r--r--tools/designer/src/components/widgetbox/widgetboxtreewidget.h150
-rw-r--r--tools/designer/src/designer/Info_mac.plist35
-rw-r--r--tools/designer/src/designer/appfontdialog.cpp429
-rw-r--r--tools/designer/src/designer/appfontdialog.h101
-rw-r--r--tools/designer/src/designer/assistantclient.cpp175
-rw-r--r--tools/designer/src/designer/assistantclient.h83
-rw-r--r--tools/designer/src/designer/designer.icnsbin0 -> 154893 bytes
-rw-r--r--tools/designer/src/designer/designer.icobin0 -> 355574 bytes
-rw-r--r--tools/designer/src/designer/designer.pro89
-rw-r--r--tools/designer/src/designer/designer.qrc5
-rw-r--r--tools/designer/src/designer/designer.rc2
-rw-r--r--tools/designer/src/designer/designer_enums.h52
-rw-r--r--tools/designer/src/designer/images/designer.pngbin0 -> 4205 bytes
-rw-r--r--tools/designer/src/designer/images/mdi.pngbin0 -> 59505 bytes
-rw-r--r--tools/designer/src/designer/images/sdi.pngbin0 -> 61037 bytes
-rw-r--r--tools/designer/src/designer/images/workbench.pngbin0 -> 2085 bytes
-rw-r--r--tools/designer/src/designer/main.cpp72
-rw-r--r--tools/designer/src/designer/mainwindow.cpp401
-rw-r--r--tools/designer/src/designer/mainwindow.h187
-rw-r--r--tools/designer/src/designer/newform.cpp227
-rw-r--r--tools/designer/src/designer/newform.h104
-rw-r--r--tools/designer/src/designer/preferencesdialog.cpp118
-rw-r--r--tools/designer/src/designer/preferencesdialog.h82
-rw-r--r--tools/designer/src/designer/preferencesdialog.ui91
-rw-r--r--tools/designer/src/designer/qdesigner.cpp320
-rw-r--r--tools/designer/src/designer/qdesigner.h102
-rw-r--r--tools/designer/src/designer/qdesigner_actions.cpp1406
-rw-r--r--tools/designer/src/designer/qdesigner_actions.h227
-rw-r--r--tools/designer/src/designer/qdesigner_appearanceoptions.cpp167
-rw-r--r--tools/designer/src/designer/qdesigner_appearanceoptions.h136
-rw-r--r--tools/designer/src/designer/qdesigner_appearanceoptions.ui57
-rw-r--r--tools/designer/src/designer/qdesigner_formwindow.cpp289
-rw-r--r--tools/designer/src/designer/qdesigner_formwindow.h97
-rw-r--r--tools/designer/src/designer/qdesigner_pch.h59
-rw-r--r--tools/designer/src/designer/qdesigner_server.cpp158
-rw-r--r--tools/designer/src/designer/qdesigner_server.h89
-rw-r--r--tools/designer/src/designer/qdesigner_settings.cpp250
-rw-r--r--tools/designer/src/designer/qdesigner_settings.h94
-rw-r--r--tools/designer/src/designer/qdesigner_toolwindow.cpp438
-rw-r--r--tools/designer/src/designer/qdesigner_toolwindow.h123
-rw-r--r--tools/designer/src/designer/qdesigner_workbench.cpp1096
-rw-r--r--tools/designer/src/designer/qdesigner_workbench.h215
-rw-r--r--tools/designer/src/designer/saveformastemplate.cpp173
-rw-r--r--tools/designer/src/designer/saveformastemplate.h77
-rw-r--r--tools/designer/src/designer/saveformastemplate.ui166
-rw-r--r--tools/designer/src/designer/versiondialog.cpp218
-rw-r--r--tools/designer/src/designer/versiondialog.h58
-rw-r--r--tools/designer/src/lib/components/qdesigner_components.h82
-rw-r--r--tools/designer/src/lib/components/qdesigner_components_global.h66
-rw-r--r--tools/designer/src/lib/extension/default_extensionfactory.cpp178
-rw-r--r--tools/designer/src/lib/extension/default_extensionfactory.h86
-rw-r--r--tools/designer/src/lib/extension/extension.cpp186
-rw-r--r--tools/designer/src/lib/extension/extension.h109
-rw-r--r--tools/designer/src/lib/extension/extension.pri12
-rw-r--r--tools/designer/src/lib/extension/extension_global.h64
-rw-r--r--tools/designer/src/lib/extension/qextensionmanager.cpp174
-rw-r--r--tools/designer/src/lib/extension/qextensionmanager.h79
-rw-r--r--tools/designer/src/lib/lib.pro78
-rw-r--r--tools/designer/src/lib/lib_pch.h65
-rw-r--r--tools/designer/src/lib/sdk/abstractactioneditor.cpp123
-rw-r--r--tools/designer/src/lib/sdk/abstractactioneditor.h76
-rw-r--r--tools/designer/src/lib/sdk/abstractbrushmanager.h83
-rw-r--r--tools/designer/src/lib/sdk/abstractdialoggui.cpp161
-rw-r--r--tools/designer/src/lib/sdk/abstractdialoggui_p.h107
-rw-r--r--tools/designer/src/lib/sdk/abstractdnditem.h75
-rw-r--r--tools/designer/src/lib/sdk/abstractformeditor.cpp621
-rw-r--r--tools/designer/src/lib/sdk/abstractformeditor.h159
-rw-r--r--tools/designer/src/lib/sdk/abstractformeditorplugin.cpp86
-rw-r--r--tools/designer/src/lib/sdk/abstractformeditorplugin.h73
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindow.cpp814
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindow.h183
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindowcursor.cpp252
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindowcursor.h109
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindowmanager.cpp502
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindowmanager.h122
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindowtool.cpp106
-rw-r--r--tools/designer/src/lib/sdk/abstractformwindowtool.h85
-rw-r--r--tools/designer/src/lib/sdk/abstracticoncache.h83
-rw-r--r--tools/designer/src/lib/sdk/abstractintegration.cpp54
-rw-r--r--tools/designer/src/lib/sdk/abstractintegration.h76
-rw-r--r--tools/designer/src/lib/sdk/abstractintrospection.cpp548
-rw-r--r--tools/designer/src/lib/sdk/abstractintrospection_p.h174
-rw-r--r--tools/designer/src/lib/sdk/abstractlanguage.h100
-rw-r--r--tools/designer/src/lib/sdk/abstractmetadatabase.cpp170
-rw-r--r--tools/designer/src/lib/sdk/abstractmetadatabase.h99
-rw-r--r--tools/designer/src/lib/sdk/abstractnewformwidget.cpp117
-rw-r--r--tools/designer/src/lib/sdk/abstractnewformwidget_p.h88
-rw-r--r--tools/designer/src/lib/sdk/abstractobjectinspector.cpp110
-rw-r--r--tools/designer/src/lib/sdk/abstractobjectinspector.h73
-rw-r--r--tools/designer/src/lib/sdk/abstractoptionspage_p.h79
-rw-r--r--tools/designer/src/lib/sdk/abstractpromotioninterface.cpp113
-rw-r--r--tools/designer/src/lib/sdk/abstractpromotioninterface.h91
-rw-r--r--tools/designer/src/lib/sdk/abstractpropertyeditor.cpp193
-rw-r--r--tools/designer/src/lib/sdk/abstractpropertyeditor.h84
-rw-r--r--tools/designer/src/lib/sdk/abstractresourcebrowser.cpp57
-rw-r--r--tools/designer/src/lib/sdk/abstractresourcebrowser.h75
-rw-r--r--tools/designer/src/lib/sdk/abstractsettings_p.h87
-rw-r--r--tools/designer/src/lib/sdk/abstractwidgetbox.cpp340
-rw-r--r--tools/designer/src/lib/sdk/abstractwidgetbox.h142
-rw-r--r--tools/designer/src/lib/sdk/abstractwidgetdatabase.cpp360
-rw-r--r--tools/designer/src/lib/sdk/abstractwidgetdatabase.h137
-rw-r--r--tools/designer/src/lib/sdk/abstractwidgetfactory.cpp112
-rw-r--r--tools/designer/src/lib/sdk/abstractwidgetfactory.h79
-rw-r--r--tools/designer/src/lib/sdk/dynamicpropertysheet.h81
-rw-r--r--tools/designer/src/lib/sdk/extrainfo.cpp116
-rw-r--r--tools/designer/src/lib/sdk/extrainfo.h84
-rw-r--r--tools/designer/src/lib/sdk/layoutdecoration.h99
-rw-r--r--tools/designer/src/lib/sdk/membersheet.h89
-rw-r--r--tools/designer/src/lib/sdk/propertysheet.h90
-rw-r--r--tools/designer/src/lib/sdk/script.cpp109
-rw-r--r--tools/designer/src/lib/sdk/script_p.h83
-rw-r--r--tools/designer/src/lib/sdk/sdk.pri58
-rw-r--r--tools/designer/src/lib/sdk/sdk_global.h64
-rw-r--r--tools/designer/src/lib/sdk/taskmenu.h72
-rw-r--r--tools/designer/src/lib/shared/actioneditor.cpp822
-rw-r--r--tools/designer/src/lib/shared/actioneditor_p.h168
-rw-r--r--tools/designer/src/lib/shared/actionprovider_p.h108
-rw-r--r--tools/designer/src/lib/shared/actionrepository.cpp659
-rw-r--r--tools/designer/src/lib/shared/actionrepository_p.h257
-rw-r--r--tools/designer/src/lib/shared/addlinkdialog.ui112
-rw-r--r--tools/designer/src/lib/shared/codedialog.cpp266
-rw-r--r--tools/designer/src/lib/shared/codedialog_p.h100
-rw-r--r--tools/designer/src/lib/shared/connectionedit.cpp1612
-rw-r--r--tools/designer/src/lib/shared/connectionedit_p.h324
-rw-r--r--tools/designer/src/lib/shared/csshighlighter.cpp192
-rw-r--r--tools/designer/src/lib/shared/csshighlighter_p.h82
-rw-r--r--tools/designer/src/lib/shared/defaultgradients.xml498
-rw-r--r--tools/designer/src/lib/shared/deviceprofile.cpp467
-rw-r--r--tools/designer/src/lib/shared/deviceprofile_p.h152
-rw-r--r--tools/designer/src/lib/shared/dialoggui.cpp265
-rw-r--r--tools/designer/src/lib/shared/dialoggui_p.h107
-rw-r--r--tools/designer/src/lib/shared/extensionfactory_p.h120
-rw-r--r--tools/designer/src/lib/shared/filterwidget.cpp237
-rw-r--r--tools/designer/src/lib/shared/filterwidget_p.h152
-rw-r--r--tools/designer/src/lib/shared/formlayoutmenu.cpp534
-rw-r--r--tools/designer/src/lib/shared/formlayoutmenu_p.h100
-rw-r--r--tools/designer/src/lib/shared/formlayoutrowdialog.ui166
-rw-r--r--tools/designer/src/lib/shared/formwindowbase.cpp487
-rw-r--r--tools/designer/src/lib/shared/formwindowbase_p.h202
-rw-r--r--tools/designer/src/lib/shared/grid.cpp186
-rw-r--r--tools/designer/src/lib/shared/grid_p.h118
-rw-r--r--tools/designer/src/lib/shared/gridpanel.cpp121
-rw-r--r--tools/designer/src/lib/shared/gridpanel.ui144
-rw-r--r--tools/designer/src/lib/shared/gridpanel_p.h101
-rw-r--r--tools/designer/src/lib/shared/htmlhighlighter.cpp198
-rw-r--r--tools/designer/src/lib/shared/htmlhighlighter_p.h101
-rw-r--r--tools/designer/src/lib/shared/iconloader.cpp80
-rw-r--r--tools/designer/src/lib/shared/iconloader_p.h72
-rw-r--r--tools/designer/src/lib/shared/iconselector.cpp546
-rw-r--r--tools/designer/src/lib/shared/iconselector_p.h142
-rw-r--r--tools/designer/src/lib/shared/invisible_widget.cpp57
-rw-r--r--tools/designer/src/lib/shared/invisible_widget_p.h75
-rw-r--r--tools/designer/src/lib/shared/layout.cpp1326
-rw-r--r--tools/designer/src/lib/shared/layout_p.h152
-rw-r--r--tools/designer/src/lib/shared/layoutinfo.cpp312
-rw-r--r--tools/designer/src/lib/shared/layoutinfo_p.h114
-rw-r--r--tools/designer/src/lib/shared/metadatabase.cpp295
-rw-r--r--tools/designer/src/lib/shared/metadatabase_p.h142
-rw-r--r--tools/designer/src/lib/shared/morphmenu.cpp635
-rw-r--r--tools/designer/src/lib/shared/morphmenu_p.h97
-rw-r--r--tools/designer/src/lib/shared/newactiondialog.cpp197
-rw-r--r--tools/designer/src/lib/shared/newactiondialog.ui277
-rw-r--r--tools/designer/src/lib/shared/newactiondialog_p.h124
-rw-r--r--tools/designer/src/lib/shared/newformwidget.cpp587
-rw-r--r--tools/designer/src/lib/shared/newformwidget.ui192
-rw-r--r--tools/designer/src/lib/shared/newformwidget_p.h143
-rw-r--r--tools/designer/src/lib/shared/orderdialog.cpp192
-rw-r--r--tools/designer/src/lib/shared/orderdialog.ui198
-rw-r--r--tools/designer/src/lib/shared/orderdialog_p.h114
-rw-r--r--tools/designer/src/lib/shared/plaintexteditor.cpp123
-rw-r--r--tools/designer/src/lib/shared/plaintexteditor_p.h89
-rw-r--r--tools/designer/src/lib/shared/plugindialog.cpp207
-rw-r--r--tools/designer/src/lib/shared/plugindialog.ui136
-rw-r--r--tools/designer/src/lib/shared/plugindialog_p.h81
-rw-r--r--tools/designer/src/lib/shared/pluginmanager.cpp670
-rw-r--r--tools/designer/src/lib/shared/pluginmanager_p.h151
-rw-r--r--tools/designer/src/lib/shared/previewconfigurationwidget.cpp382
-rw-r--r--tools/designer/src/lib/shared/previewconfigurationwidget.ui91
-rw-r--r--tools/designer/src/lib/shared/previewconfigurationwidget_p.h96
-rw-r--r--tools/designer/src/lib/shared/previewmanager.cpp815
-rw-r--r--tools/designer/src/lib/shared/previewmanager_p.h184
-rw-r--r--tools/designer/src/lib/shared/promotionmodel.cpp224
-rw-r--r--tools/designer/src/lib/shared/promotionmodel_p.h98
-rw-r--r--tools/designer/src/lib/shared/promotiontaskmenu.cpp361
-rw-r--r--tools/designer/src/lib/shared/promotiontaskmenu_p.h151
-rw-r--r--tools/designer/src/lib/shared/propertylineedit.cpp96
-rw-r--r--tools/designer/src/lib/shared/propertylineedit_p.h85
-rw-r--r--tools/designer/src/lib/shared/qdesigner_command.cpp2968
-rw-r--r--tools/designer/src/lib/shared/qdesigner_command2.cpp159
-rw-r--r--tools/designer/src/lib/shared/qdesigner_command2_p.h101
-rw-r--r--tools/designer/src/lib/shared/qdesigner_command_p.h1136
-rw-r--r--tools/designer/src/lib/shared/qdesigner_dnditem.cpp300
-rw-r--r--tools/designer/src/lib/shared/qdesigner_dnditem_p.h147
-rw-r--r--tools/designer/src/lib/shared/qdesigner_dockwidget.cpp140
-rw-r--r--tools/designer/src/lib/shared/qdesigner_dockwidget_p.h87
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formbuilder.cpp478
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formbuilder_p.h166
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formeditorcommand.cpp64
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formeditorcommand_p.h83
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp149
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formwindowcommand_p.h96
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formwindowmanager.cpp167
-rw-r--r--tools/designer/src/lib/shared/qdesigner_formwindowmanager_p.h99
-rw-r--r--tools/designer/src/lib/shared/qdesigner_integration.cpp496
-rw-r--r--tools/designer/src/lib/shared/qdesigner_integration_p.h152
-rw-r--r--tools/designer/src/lib/shared/qdesigner_introspection.cpp372
-rw-r--r--tools/designer/src/lib/shared/qdesigner_introspection_p.h84
-rw-r--r--tools/designer/src/lib/shared/qdesigner_membersheet.cpp371
-rw-r--r--tools/designer/src/lib/shared/qdesigner_membersheet_p.h120
-rw-r--r--tools/designer/src/lib/shared/qdesigner_menu.cpp1355
-rw-r--r--tools/designer/src/lib/shared/qdesigner_menu_p.h203
-rw-r--r--tools/designer/src/lib/shared/qdesigner_menubar.cpp955
-rw-r--r--tools/designer/src/lib/shared/qdesigner_menubar_p.h177
-rw-r--r--tools/designer/src/lib/shared/qdesigner_objectinspector.cpp80
-rw-r--r--tools/designer/src/lib/shared/qdesigner_objectinspector_p.h103
-rw-r--r--tools/designer/src/lib/shared/qdesigner_promotion.cpp373
-rw-r--r--tools/designer/src/lib/shared/qdesigner_promotion_p.h98
-rw-r--r--tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp452
-rw-r--r--tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h161
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertycommand.cpp1479
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertycommand_p.h301
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp131
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h106
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertysheet.cpp1601
-rw-r--r--tools/designer/src/lib/shared/qdesigner_propertysheet_p.h265
-rw-r--r--tools/designer/src/lib/shared/qdesigner_qsettings.cpp94
-rw-r--r--tools/designer/src/lib/shared/qdesigner_qsettings_p.h88
-rw-r--r--tools/designer/src/lib/shared/qdesigner_stackedbox.cpp396
-rw-r--r--tools/designer/src/lib/shared/qdesigner_stackedbox_p.h164
-rw-r--r--tools/designer/src/lib/shared/qdesigner_tabwidget.cpp567
-rw-r--r--tools/designer/src/lib/shared/qdesigner_tabwidget_p.h153
-rw-r--r--tools/designer/src/lib/shared/qdesigner_taskmenu.cpp781
-rw-r--r--tools/designer/src/lib/shared/qdesigner_taskmenu_p.h132
-rw-r--r--tools/designer/src/lib/shared/qdesigner_toolbar.cpp486
-rw-r--r--tools/designer/src/lib/shared/qdesigner_toolbar_p.h135
-rw-r--r--tools/designer/src/lib/shared/qdesigner_toolbox.cpp437
-rw-r--r--tools/designer/src/lib/shared/qdesigner_toolbox_p.h140
-rw-r--r--tools/designer/src/lib/shared/qdesigner_utils.cpp734
-rw-r--r--tools/designer/src/lib/shared/qdesigner_utils_p.h482
-rw-r--r--tools/designer/src/lib/shared/qdesigner_widget.cpp108
-rw-r--r--tools/designer/src/lib/shared/qdesigner_widget_p.h122
-rw-r--r--tools/designer/src/lib/shared/qdesigner_widgetbox.cpp185
-rw-r--r--tools/designer/src/lib/shared/qdesigner_widgetbox_p.h101
-rw-r--r--tools/designer/src/lib/shared/qdesigner_widgetitem.cpp345
-rw-r--r--tools/designer/src/lib/shared/qdesigner_widgetitem_p.h147
-rw-r--r--tools/designer/src/lib/shared/qlayout_widget.cpp2103
-rw-r--r--tools/designer/src/lib/shared/qlayout_widget_p.h292
-rw-r--r--tools/designer/src/lib/shared/qscripthighlighter.cpp468
-rw-r--r--tools/designer/src/lib/shared/qscripthighlighter_p.h84
-rw-r--r--tools/designer/src/lib/shared/qsimpleresource.cpp283
-rw-r--r--tools/designer/src/lib/shared/qsimpleresource_p.h147
-rw-r--r--tools/designer/src/lib/shared/qtresourceeditordialog.cpp2226
-rw-r--r--tools/designer/src/lib/shared/qtresourceeditordialog.ui177
-rw-r--r--tools/designer/src/lib/shared/qtresourceeditordialog_p.h129
-rw-r--r--tools/designer/src/lib/shared/qtresourcemodel.cpp648
-rw-r--r--tools/designer/src/lib/shared/qtresourcemodel_p.h144
-rw-r--r--tools/designer/src/lib/shared/qtresourceview.cpp766
-rw-r--r--tools/designer/src/lib/shared/qtresourceview_p.h140
-rw-r--r--tools/designer/src/lib/shared/richtexteditor.cpp762
-rw-r--r--tools/designer/src/lib/shared/richtexteditor_p.h102
-rw-r--r--tools/designer/src/lib/shared/scriptcommand.cpp103
-rw-r--r--tools/designer/src/lib/shared/scriptcommand_p.h93
-rw-r--r--tools/designer/src/lib/shared/scriptdialog.cpp128
-rw-r--r--tools/designer/src/lib/shared/scriptdialog_p.h90
-rw-r--r--tools/designer/src/lib/shared/scripterrordialog.cpp112
-rw-r--r--tools/designer/src/lib/shared/scripterrordialog_p.h83
-rw-r--r--tools/designer/src/lib/shared/selectsignaldialog.ui93
-rw-r--r--tools/designer/src/lib/shared/shared.pri189
-rw-r--r--tools/designer/src/lib/shared/shared.qrc20
-rw-r--r--tools/designer/src/lib/shared/shared_enums_p.h99
-rw-r--r--tools/designer/src/lib/shared/shared_global_p.h76
-rw-r--r--tools/designer/src/lib/shared/shared_settings.cpp321
-rw-r--r--tools/designer/src/lib/shared/shared_settings_p.h142
-rw-r--r--tools/designer/src/lib/shared/sheet_delegate.cpp112
-rw-r--r--tools/designer/src/lib/shared/sheet_delegate_p.h85
-rw-r--r--tools/designer/src/lib/shared/signalslotdialog.cpp526
-rw-r--r--tools/designer/src/lib/shared/signalslotdialog.ui129
-rw-r--r--tools/designer/src/lib/shared/signalslotdialog_p.h173
-rw-r--r--tools/designer/src/lib/shared/spacer_widget.cpp280
-rw-r--r--tools/designer/src/lib/shared/spacer_widget_p.h117
-rw-r--r--tools/designer/src/lib/shared/stylesheeteditor.cpp415
-rw-r--r--tools/designer/src/lib/shared/stylesheeteditor_p.h144
-rw-r--r--tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui67
-rw-r--r--tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui71
-rw-r--r--tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui71
-rw-r--r--tools/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui18
-rw-r--r--tools/designer/src/lib/shared/templates/forms/Main_Window.ui24
-rw-r--r--tools/designer/src/lib/shared/templates/forms/Widget.ui21
-rw-r--r--tools/designer/src/lib/shared/textpropertyeditor.cpp429
-rw-r--r--tools/designer/src/lib/shared/textpropertyeditor_p.h156
-rw-r--r--tools/designer/src/lib/shared/widgetdatabase.cpp865
-rw-r--r--tools/designer/src/lib/shared/widgetdatabase_p.h210
-rw-r--r--tools/designer/src/lib/shared/widgetfactory.cpp897
-rw-r--r--tools/designer/src/lib/shared/widgetfactory_p.h191
-rw-r--r--tools/designer/src/lib/shared/zoomwidget.cpp578
-rw-r--r--tools/designer/src/lib/shared/zoomwidget_p.h238
-rw-r--r--tools/designer/src/lib/uilib/abstractformbuilder.cpp2920
-rw-r--r--tools/designer/src/lib/uilib/abstractformbuilder.h290
-rw-r--r--tools/designer/src/lib/uilib/container.h75
-rw-r--r--tools/designer/src/lib/uilib/customwidget.h101
-rw-r--r--tools/designer/src/lib/uilib/formbuilder.cpp562
-rw-r--r--tools/designer/src/lib/uilib/formbuilder.h115
-rw-r--r--tools/designer/src/lib/uilib/formbuilderextra.cpp531
-rw-r--r--tools/designer/src/lib/uilib/formbuilderextra_p.h255
-rw-r--r--tools/designer/src/lib/uilib/formscriptrunner.cpp208
-rw-r--r--tools/designer/src/lib/uilib/formscriptrunner_p.h120
-rw-r--r--tools/designer/src/lib/uilib/properties.cpp676
-rw-r--r--tools/designer/src/lib/uilib/properties_p.h176
-rw-r--r--tools/designer/src/lib/uilib/qdesignerexportwidget.h66
-rw-r--r--tools/designer/src/lib/uilib/resourcebuilder.cpp169
-rw-r--r--tools/designer/src/lib/uilib/resourcebuilder_p.h104
-rw-r--r--tools/designer/src/lib/uilib/textbuilder.cpp84
-rw-r--r--tools/designer/src/lib/uilib/textbuilder_p.h93
-rw-r--r--tools/designer/src/lib/uilib/ui4.cpp10887
-rw-r--r--tools/designer/src/lib/uilib/ui4_p.h3696
-rw-r--r--tools/designer/src/lib/uilib/uilib.pri31
-rw-r--r--tools/designer/src/lib/uilib/uilib_global.h64
-rw-r--r--tools/designer/src/lib/uilib/widgets.table148
-rw-r--r--tools/designer/src/plugins/activeqt/activeqt.pro32
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp117
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.h91
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgetplugin.cpp146
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgetplugin.h77
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp189
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h99
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp186
-rw-r--r--tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.h76
-rw-r--r--tools/designer/src/plugins/activeqt/qdesigneraxwidget.cpp272
-rw-r--r--tools/designer/src/plugins/activeqt/qdesigneraxwidget.h142
-rw-r--r--tools/designer/src/plugins/phononwidgets/images/seekslider.pngbin0 -> 444 bytes
-rw-r--r--tools/designer/src/plugins/phononwidgets/images/videoplayer.pngbin0 -> 644 bytes
-rw-r--r--tools/designer/src/plugins/phononwidgets/images/videowidget.pngbin0 -> 794 bytes
-rw-r--r--tools/designer/src/plugins/phononwidgets/images/volumeslider.pngbin0 -> 470 bytes
-rw-r--r--tools/designer/src/plugins/phononwidgets/phononcollection.cpp82
-rw-r--r--tools/designer/src/plugins/phononwidgets/phononwidgets.pro24
-rw-r--r--tools/designer/src/plugins/phononwidgets/phononwidgets.qrc8
-rw-r--r--tools/designer/src/plugins/phononwidgets/seeksliderplugin.cpp117
-rw-r--r--tools/designer/src/plugins/phononwidgets/seeksliderplugin.h75
-rw-r--r--tools/designer/src/plugins/phononwidgets/videoplayerplugin.cpp135
-rw-r--r--tools/designer/src/plugins/phononwidgets/videoplayerplugin.h75
-rw-r--r--tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp154
-rw-r--r--tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h82
-rw-r--r--tools/designer/src/plugins/phononwidgets/volumesliderplugin.cpp117
-rw-r--r--tools/designer/src/plugins/phononwidgets/volumesliderplugin.h75
-rw-r--r--tools/designer/src/plugins/plugins.pri8
-rw-r--r--tools/designer/src/plugins/plugins.pro9
-rw-r--r--tools/designer/src/plugins/qwebview/images/qwebview.pngbin0 -> 1473 bytes
-rw-r--r--tools/designer/src/plugins/qwebview/qwebview.pro15
-rw-r--r--tools/designer/src/plugins/qwebview/qwebview_plugin.cpp137
-rw-r--r--tools/designer/src/plugins/qwebview/qwebview_plugin.h74
-rw-r--r--tools/designer/src/plugins/qwebview/qwebview_plugin.qrc5
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d.cpp492
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d.h77
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d.pro17
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d_global.h61
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d_plugin.cpp115
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d_plugin.h82
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d_tool.cpp88
-rw-r--r--tools/designer/src/plugins/tools/view3d/view3d_tool.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp183
-rw-r--r--tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h95
-rw-r--r--tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp120
-rw-r--r--tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp151
-rw-r--r--tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h93
-rw-r--r--tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp121
-rw-r--r--tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp249
-rw-r--r--tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h96
-rw-r--r--tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp121
-rw-r--r--tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp130
-rw-r--r--tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h84
-rw-r--r--tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp118
-rw-r--r--tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp196
-rw-r--r--tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.h93
-rw-r--r--tools/designer/src/plugins/widgets/q3table/q3table_plugin.cpp121
-rw-r--r--tools/designer/src/plugins/widgets/q3table/q3table_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp116
-rw-r--r--tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h93
-rw-r--r--tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp122
-rw-r--r--tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp108
-rw-r--r--tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h92
-rw-r--r--tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp128
-rw-r--r--tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp601
-rw-r--r--tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h287
-rw-r--r--tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp115
-rw-r--r--tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h84
-rw-r--r--tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp118
-rw-r--r--tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp217
-rw-r--r--tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h108
-rw-r--r--tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp235
-rw-r--r--tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.h149
-rw-r--r--tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp128
-rw-r--r--tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h76
-rw-r--r--tools/designer/src/plugins/widgets/qt3supportwidgets.cpp107
-rw-r--r--tools/designer/src/plugins/widgets/widgets.pro82
-rw-r--r--tools/designer/src/sharedcomponents.pri30
-rw-r--r--tools/designer/src/src.pro13
-rw-r--r--tools/designer/src/uitools/quiloader.cpp927
-rw-r--r--tools/designer/src/uitools/quiloader.h102
-rw-r--r--tools/designer/src/uitools/quiloader_p.h109
-rw-r--r--tools/designer/src/uitools/uitools.pro41
-rw-r--r--tools/designer/translations/translations.pro140
-rw-r--r--tools/doxygen/config/footer.html8
-rw-r--r--tools/doxygen/config/header.html30
-rw-r--r--tools/doxygen/config/phonon.css114
-rw-r--r--tools/doxygen/config/phonon.doxyfile220
-rw-r--r--tools/installer/README12
-rwxr-xr-xtools/installer/batch/build.bat160
-rwxr-xr-xtools/installer/batch/copy.bat124
-rwxr-xr-xtools/installer/batch/delete.bat76
-rwxr-xr-xtools/installer/batch/env.bat144
-rwxr-xr-xtools/installer/batch/extract.bat86
-rwxr-xr-xtools/installer/batch/installer.bat250
-rwxr-xr-xtools/installer/batch/log.bat61
-rwxr-xr-xtools/installer/batch/toupper.bat72
-rw-r--r--tools/installer/config/config.default.sample67
-rw-r--r--tools/installer/config/mingw-opensource.conf139
-rwxr-xr-xtools/installer/iwmake.bat127
-rw-r--r--tools/installer/nsis/confirmpage.ini62
-rw-r--r--tools/installer/nsis/gwdownload.ini121
-rw-r--r--tools/installer/nsis/gwmirror.ini70
-rw-r--r--tools/installer/nsis/images/install.icobin0 -> 22486 bytes
-rw-r--r--tools/installer/nsis/images/qt-header.bmpbin0 -> 25818 bytes
-rw-r--r--tools/installer/nsis/images/qt-wizard.bmpbin0 -> 154542 bytes
-rw-r--r--tools/installer/nsis/includes/global.nsh146
-rw-r--r--tools/installer/nsis/includes/instdir.nsh257
-rw-r--r--tools/installer/nsis/includes/list.nsh139
-rw-r--r--tools/installer/nsis/includes/qtcommon.nsh574
-rw-r--r--tools/installer/nsis/includes/qtenv.nsh306
-rw-r--r--tools/installer/nsis/includes/system.nsh272
-rw-r--r--tools/installer/nsis/installer.nsi527
-rw-r--r--tools/installer/nsis/modules/environment.nsh219
-rw-r--r--tools/installer/nsis/modules/mingw.nsh676
-rw-r--r--tools/installer/nsis/modules/opensource.nsh98
-rw-r--r--tools/installer/nsis/modules/registeruiext.nsh210
-rw-r--r--tools/installer/nsis/opensource.ini81
-rw-r--r--tools/linguist/LICENSE.GPL280
-rw-r--r--tools/linguist/lconvert/lconvert.pro22
-rw-r--r--tools/linguist/lconvert/main.cpp236
-rw-r--r--tools/linguist/linguist.pro8
-rw-r--r--tools/linguist/linguist/Info_mac.plist18
-rw-r--r--tools/linguist/linguist/batchtranslation.ui260
-rw-r--r--tools/linguist/linguist/batchtranslationdialog.cpp194
-rw-r--r--tools/linguist/linguist/batchtranslationdialog.h87
-rw-r--r--tools/linguist/linguist/errorsview.cpp118
-rw-r--r--tools/linguist/linguist/errorsview.h78
-rw-r--r--tools/linguist/linguist/finddialog.cpp94
-rw-r--r--tools/linguist/linguist/finddialog.h69
-rw-r--r--tools/linguist/linguist/finddialog.ui266
-rw-r--r--tools/linguist/linguist/formpreviewview.cpp535
-rw-r--r--tools/linguist/linguist/formpreviewview.h128
-rw-r--r--tools/linguist/linguist/images/appicon.pngbin0 -> 1382 bytes
-rw-r--r--tools/linguist/linguist/images/down.pngbin0 -> 594 bytes
-rw-r--r--tools/linguist/linguist/images/editdelete.pngbin0 -> 831 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-128-32.pngbin0 -> 5960 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-128-8.pngbin0 -> 5947 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-16-32.pngbin0 -> 537 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-16-8.pngbin0 -> 608 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-32-32.pngbin0 -> 1382 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-32-8.pngbin0 -> 1369 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-48-32.pngbin0 -> 2017 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-48-8.pngbin0 -> 1972 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-64-32.pngbin0 -> 2773 bytes
-rw-r--r--tools/linguist/linguist/images/icons/linguist-64-8.pngbin0 -> 2664 bytes
-rw-r--r--tools/linguist/linguist/images/mac/accelerator.pngbin0 -> 1921 bytes
-rw-r--r--tools/linguist/linguist/images/mac/book.pngbin0 -> 1477 bytes
-rw-r--r--tools/linguist/linguist/images/mac/doneandnext.pngbin0 -> 1590 bytes
-rw-r--r--tools/linguist/linguist/images/mac/editcopy.pngbin0 -> 1468 bytes
-rw-r--r--tools/linguist/linguist/images/mac/editcut.pngbin0 -> 1512 bytes
-rw-r--r--tools/linguist/linguist/images/mac/editpaste.pngbin0 -> 1906 bytes
-rw-r--r--tools/linguist/linguist/images/mac/filenew.pngbin0 -> 1172 bytes
-rw-r--r--tools/linguist/linguist/images/mac/fileopen.pngbin0 -> 2168 bytes
-rw-r--r--tools/linguist/linguist/images/mac/fileprint.pngbin0 -> 741 bytes
-rw-r--r--tools/linguist/linguist/images/mac/filesave.pngbin0 -> 1206 bytes
-rw-r--r--tools/linguist/linguist/images/mac/next.pngbin0 -> 1056 bytes
-rw-r--r--tools/linguist/linguist/images/mac/nextunfinished.pngbin0 -> 1756 bytes
-rw-r--r--tools/linguist/linguist/images/mac/phrase.pngbin0 -> 1932 bytes
-rw-r--r--tools/linguist/linguist/images/mac/prev.pngbin0 -> 1080 bytes
-rw-r--r--tools/linguist/linguist/images/mac/prevunfinished.pngbin0 -> 1682 bytes
-rw-r--r--tools/linguist/linguist/images/mac/print.pngbin0 -> 2087 bytes
-rw-r--r--tools/linguist/linguist/images/mac/punctuation.pngbin0 -> 1593 bytes
-rw-r--r--tools/linguist/linguist/images/mac/redo.pngbin0 -> 1752 bytes
-rw-r--r--tools/linguist/linguist/images/mac/searchfind.pngbin0 -> 1836 bytes
-rw-r--r--tools/linguist/linguist/images/mac/undo.pngbin0 -> 1746 bytes
-rw-r--r--tools/linguist/linguist/images/mac/validateplacemarkers.pngbin0 -> 1452 bytes
-rw-r--r--tools/linguist/linguist/images/mac/whatsthis.pngbin0 -> 1586 bytes
-rw-r--r--tools/linguist/linguist/images/s_check_danger.pngbin0 -> 304 bytes
-rw-r--r--tools/linguist/linguist/images/s_check_empty.pngbin0 -> 404 bytes
-rw-r--r--tools/linguist/linguist/images/s_check_obsolete.pngbin0 -> 192 bytes
-rw-r--r--tools/linguist/linguist/images/s_check_off.pngbin0 -> 434 bytes
-rw-r--r--tools/linguist/linguist/images/s_check_on.pngbin0 -> 192 bytes
-rw-r--r--tools/linguist/linguist/images/s_check_warning.pngbin0 -> 192 bytes
-rw-r--r--tools/linguist/linguist/images/splash.pngbin0 -> 15637 bytes
-rw-r--r--tools/linguist/linguist/images/transbox.pngbin0 -> 782 bytes
-rw-r--r--tools/linguist/linguist/images/up.pngbin0 -> 692 bytes
-rw-r--r--tools/linguist/linguist/images/win/accelerator.pngbin0 -> 1335 bytes
-rw-r--r--tools/linguist/linguist/images/win/book.pngbin0 -> 1109 bytes
-rw-r--r--tools/linguist/linguist/images/win/doneandnext.pngbin0 -> 1233 bytes
-rw-r--r--tools/linguist/linguist/images/win/editcopy.pngbin0 -> 1325 bytes
-rw-r--r--tools/linguist/linguist/images/win/editcut.pngbin0 -> 1384 bytes
-rw-r--r--tools/linguist/linguist/images/win/editpaste.pngbin0 -> 1482 bytes
-rw-r--r--tools/linguist/linguist/images/win/filenew.pngbin0 -> 768 bytes
-rw-r--r--tools/linguist/linguist/images/win/fileopen.pngbin0 -> 1662 bytes
-rw-r--r--tools/linguist/linguist/images/win/filesave.pngbin0 -> 1205 bytes
-rw-r--r--tools/linguist/linguist/images/win/next.pngbin0 -> 1038 bytes
-rw-r--r--tools/linguist/linguist/images/win/nextunfinished.pngbin0 -> 1257 bytes
-rw-r--r--tools/linguist/linguist/images/win/phrase.pngbin0 -> 1371 bytes
-rw-r--r--tools/linguist/linguist/images/win/prev.pngbin0 -> 898 bytes
-rw-r--r--tools/linguist/linguist/images/win/prevunfinished.pngbin0 -> 1260 bytes
-rw-r--r--tools/linguist/linguist/images/win/print.pngbin0 -> 1456 bytes
-rw-r--r--tools/linguist/linguist/images/win/punctuation.pngbin0 -> 1508 bytes
-rw-r--r--tools/linguist/linguist/images/win/redo.pngbin0 -> 1212 bytes
-rw-r--r--tools/linguist/linguist/images/win/searchfind.pngbin0 -> 1944 bytes
-rw-r--r--tools/linguist/linguist/images/win/undo.pngbin0 -> 1181 bytes
-rw-r--r--tools/linguist/linguist/images/win/validateplacemarkers.pngbin0 -> 1994 bytes
-rw-r--r--tools/linguist/linguist/images/win/whatsthis.pngbin0 -> 1040 bytes
-rw-r--r--tools/linguist/linguist/linguist.icnsbin0 -> 152596 bytes
-rw-r--r--tools/linguist/linguist/linguist.icobin0 -> 355574 bytes
-rw-r--r--tools/linguist/linguist/linguist.pro107
-rw-r--r--tools/linguist/linguist/linguist.qrc56
-rw-r--r--tools/linguist/linguist/linguist.rc1
-rw-r--r--tools/linguist/linguist/main.cpp119
-rw-r--r--tools/linguist/linguist/mainwindow.cpp2673
-rw-r--r--tools/linguist/linguist/mainwindow.h266
-rw-r--r--tools/linguist/linguist/mainwindow.ui883
-rw-r--r--tools/linguist/linguist/messageeditor.cpp865
-rw-r--r--tools/linguist/linguist/messageeditor.h169
-rw-r--r--tools/linguist/linguist/messageeditorwidgets.cpp201
-rw-r--r--tools/linguist/linguist/messageeditorwidgets.h130
-rw-r--r--tools/linguist/linguist/messagehighlighter.cpp210
-rw-r--r--tools/linguist/linguist/messagehighlighter.h83
-rw-r--r--tools/linguist/linguist/messagemodel.cpp1403
-rw-r--r--tools/linguist/linguist/messagemodel.h535
-rw-r--r--tools/linguist/linguist/phrase.cpp356
-rw-r--r--tools/linguist/linguist/phrase.h138
-rw-r--r--tools/linguist/linguist/phrasebookbox.cpp240
-rw-r--r--tools/linguist/linguist/phrasebookbox.h89
-rw-r--r--tools/linguist/linguist/phrasebookbox.ui236
-rw-r--r--tools/linguist/linguist/phrasemodel.cpp200
-rw-r--r--tools/linguist/linguist/phrasemodel.h94
-rw-r--r--tools/linguist/linguist/phraseview.cpp271
-rw-r--r--tools/linguist/linguist/phraseview.h120
-rw-r--r--tools/linguist/linguist/printout.cpp210
-rw-r--r--tools/linguist/linguist/printout.h120
-rw-r--r--tools/linguist/linguist/recentfiles.cpp147
-rw-r--r--tools/linguist/linguist/recentfiles.h83
-rw-r--r--tools/linguist/linguist/sourcecodeview.cpp145
-rw-r--r--tools/linguist/linguist/sourcecodeview.h74
-rw-r--r--tools/linguist/linguist/statistics.cpp67
-rw-r--r--tools/linguist/linguist/statistics.h67
-rw-r--r--tools/linguist/linguist/statistics.ui211
-rw-r--r--tools/linguist/linguist/translatedialog.cpp90
-rw-r--r--tools/linguist/linguist/translatedialog.h89
-rw-r--r--tools/linguist/linguist/translatedialog.ui260
-rw-r--r--tools/linguist/linguist/translationsettings.ui137
-rw-r--r--tools/linguist/linguist/translationsettingsdialog.cpp149
-rw-r--r--tools/linguist/linguist/translationsettingsdialog.h79
-rw-r--r--tools/linguist/lrelease/lrelease.197
-rw-r--r--tools/linguist/lrelease/lrelease.pro24
-rw-r--r--tools/linguist/lrelease/main.cpp272
-rw-r--r--tools/linguist/lupdate/lupdate.1132
-rw-r--r--tools/linguist/lupdate/lupdate.exe.manifest14
-rw-r--r--tools/linguist/lupdate/lupdate.pro34
-rw-r--r--tools/linguist/lupdate/main.cpp513
-rw-r--r--tools/linguist/lupdate/winmanifest.rc4
-rw-r--r--tools/linguist/phrasebooks/danish.qph1018
-rw-r--r--tools/linguist/phrasebooks/dutch.qph1044
-rw-r--r--tools/linguist/phrasebooks/finnish.qph1033
-rw-r--r--tools/linguist/phrasebooks/french.qph1104
-rw-r--r--tools/linguist/phrasebooks/german.qph1075
-rw-r--r--tools/linguist/phrasebooks/italian.qph1105
-rw-r--r--tools/linguist/phrasebooks/japanese.qph1021
-rw-r--r--tools/linguist/phrasebooks/norwegian.qph1004
-rw-r--r--tools/linguist/phrasebooks/polish.qph527
-rw-r--r--tools/linguist/phrasebooks/russian.qph982
-rw-r--r--tools/linguist/phrasebooks/spanish.qph1086
-rw-r--r--tools/linguist/phrasebooks/swedish.qph1010
-rw-r--r--tools/linguist/qdoc.conf15
-rw-r--r--tools/linguist/shared/abstractproitemvisitor.h70
-rw-r--r--tools/linguist/shared/cpp.cpp1074
-rw-r--r--tools/linguist/shared/formats.pri26
-rw-r--r--tools/linguist/shared/java.cpp655
-rwxr-xr-xtools/linguist/shared/make-qscript.sh14
-rw-r--r--tools/linguist/shared/numerus.cpp377
-rw-r--r--tools/linguist/shared/po.cpp662
-rw-r--r--tools/linguist/shared/profileevaluator.cpp1785
-rw-r--r--tools/linguist/shared/profileevaluator.h101
-rw-r--r--tools/linguist/shared/proitems.cpp328
-rw-r--r--tools/linguist/shared/proitems.h236
-rw-r--r--tools/linguist/shared/proparser.pri12
-rw-r--r--tools/linguist/shared/proparserutils.h272
-rw-r--r--tools/linguist/shared/qm.cpp717
-rw-r--r--tools/linguist/shared/qph.cpp171
-rw-r--r--tools/linguist/shared/qscript.cpp2408
-rw-r--r--tools/linguist/shared/qscript.g2039
-rw-r--r--tools/linguist/shared/simtexth.cpp277
-rw-r--r--tools/linguist/shared/simtexth.h100
-rw-r--r--tools/linguist/shared/translator.cpp559
-rw-r--r--tools/linguist/shared/translator.h224
-rw-r--r--tools/linguist/shared/translatormessage.cpp217
-rw-r--r--tools/linguist/shared/translatormessage.h181
-rw-r--r--tools/linguist/shared/translatortools.cpp505
-rw-r--r--tools/linguist/shared/translatortools.h77
-rw-r--r--tools/linguist/shared/translatortools.pri11
-rw-r--r--tools/linguist/shared/ts.cpp755
-rw-r--r--tools/linguist/shared/ts.dtd113
-rw-r--r--tools/linguist/shared/ui.cpp226
-rw-r--r--tools/linguist/shared/xliff.cpp828
-rw-r--r--tools/linguist/tests/data/main.cpp35
-rw-r--r--tools/linguist/tests/data/test.pro9
-rw-r--r--tools/linguist/tests/tests.pro16
-rw-r--r--tools/linguist/tests/tst_linguist.cpp4
-rw-r--r--tools/linguist/tests/tst_linguist.h22
-rw-r--r--tools/linguist/tests/tst_lupdate.cpp165
-rw-r--r--tools/linguist/tests/tst_simtexth.cpp43
-rw-r--r--tools/macdeployqt/macchangeqt/macchangeqt.pro9
-rw-r--r--tools/macdeployqt/macchangeqt/main.cpp54
-rw-r--r--tools/macdeployqt/macdeployqt.pro7
-rw-r--r--tools/macdeployqt/macdeployqt/macdeployqt.pro13
-rw-r--r--tools/macdeployqt/macdeployqt/main.cpp116
-rw-r--r--tools/macdeployqt/shared/shared.cpp563
-rw-r--r--tools/macdeployqt/shared/shared.h104
-rw-r--r--tools/macdeployqt/tests/deployment_mac.pro10
-rw-r--r--tools/macdeployqt/tests/tst_deployment_mac.cpp233
-rw-r--r--tools/makeqpf/Blocks.txt185
-rw-r--r--tools/makeqpf/README1
-rw-r--r--tools/makeqpf/main.cpp183
-rw-r--r--tools/makeqpf/mainwindow.cpp322
-rw-r--r--tools/makeqpf/mainwindow.h80
-rw-r--r--tools/makeqpf/mainwindow.ui502
-rw-r--r--tools/makeqpf/makeqpf.pro20
-rw-r--r--tools/makeqpf/makeqpf.qrc5
-rw-r--r--tools/makeqpf/qpf2.cpp767
-rw-r--r--tools/makeqpf/qpf2.h119
-rw-r--r--tools/pixeltool/Info_mac.plist18
-rw-r--r--tools/pixeltool/main.cpp65
-rw-r--r--tools/pixeltool/pixeltool.pro25
-rw-r--r--tools/pixeltool/qpixeltool.cpp536
-rw-r--r--tools/pixeltool/qpixeltool.h118
-rw-r--r--tools/porting/porting.pro2
-rw-r--r--tools/porting/src/ast.cpp1215
-rw-r--r--tools/porting/src/ast.h1598
-rw-r--r--tools/porting/src/codemodel.cpp91
-rw-r--r--tools/porting/src/codemodel.h777
-rw-r--r--tools/porting/src/codemodelattributes.cpp195
-rw-r--r--tools/porting/src/codemodelattributes.h72
-rw-r--r--tools/porting/src/codemodelwalker.cpp125
-rw-r--r--tools/porting/src/codemodelwalker.h80
-rw-r--r--tools/porting/src/cpplexer.cpp1297
-rw-r--r--tools/porting/src/cpplexer.h107
-rw-r--r--tools/porting/src/errors.cpp51
-rw-r--r--tools/porting/src/errors.h71
-rw-r--r--tools/porting/src/fileporter.cpp369
-rw-r--r--tools/porting/src/fileporter.h116
-rw-r--r--tools/porting/src/filewriter.cpp151
-rw-r--r--tools/porting/src/filewriter.h75
-rw-r--r--tools/porting/src/list.h374
-rw-r--r--tools/porting/src/logger.cpp148
-rw-r--r--tools/porting/src/logger.h124
-rw-r--r--tools/porting/src/parser.cpp4526
-rw-r--r--tools/porting/src/parser.h247
-rw-r--r--tools/porting/src/port.cpp297
-rw-r--r--tools/porting/src/portingrules.cpp296
-rw-r--r--tools/porting/src/portingrules.h114
-rw-r--r--tools/porting/src/preprocessorcontrol.cpp430
-rw-r--r--tools/porting/src/preprocessorcontrol.h139
-rw-r--r--tools/porting/src/projectporter.cpp414
-rw-r--r--tools/porting/src/projectporter.h82
-rw-r--r--tools/porting/src/proparser.cpp193
-rw-r--r--tools/porting/src/proparser.h55
-rw-r--r--tools/porting/src/q3porting.xml10567
-rw-r--r--tools/porting/src/qt3headers0.qrc6
-rw-r--r--tools/porting/src/qt3headers0.resourcebin0 -> 547809 bytes
-rw-r--r--tools/porting/src/qt3headers1.qrc6
-rw-r--r--tools/porting/src/qt3headers1.resourcebin0 -> 512251 bytes
-rw-r--r--tools/porting/src/qt3headers2.qrc6
-rw-r--r--tools/porting/src/qt3headers2.resourcebin0 -> 392439 bytes
-rw-r--r--tools/porting/src/qt3headers3.qrc6
-rw-r--r--tools/porting/src/qt3headers3.resourcebin0 -> 553089 bytes
-rw-r--r--tools/porting/src/qt3to4.pri68
-rw-r--r--tools/porting/src/qtsimplexml.cpp278
-rw-r--r--tools/porting/src/qtsimplexml.h97
-rw-r--r--tools/porting/src/replacetoken.cpp105
-rw-r--r--tools/porting/src/replacetoken.h67
-rw-r--r--tools/porting/src/rpp.cpp728
-rw-r--r--tools/porting/src/rpp.h1072
-rw-r--r--tools/porting/src/rppexpressionbuilder.cpp330
-rw-r--r--tools/porting/src/rppexpressionbuilder.h107
-rw-r--r--tools/porting/src/rpplexer.cpp381
-rw-r--r--tools/porting/src/rpplexer.h100
-rw-r--r--tools/porting/src/rpptreeevaluator.cpp554
-rw-r--r--tools/porting/src/rpptreeevaluator.h117
-rw-r--r--tools/porting/src/rpptreewalker.cpp166
-rw-r--r--tools/porting/src/rpptreewalker.h85
-rw-r--r--tools/porting/src/semantic.cpp1227
-rw-r--r--tools/porting/src/semantic.h131
-rw-r--r--tools/porting/src/smallobject.cpp59
-rw-r--r--tools/porting/src/smallobject.h182
-rw-r--r--tools/porting/src/src.pro93
-rw-r--r--tools/porting/src/textreplacement.cpp100
-rw-r--r--tools/porting/src/textreplacement.h91
-rw-r--r--tools/porting/src/tokenengine.cpp402
-rw-r--r--tools/porting/src/tokenengine.h391
-rw-r--r--tools/porting/src/tokenizer.cpp491
-rw-r--r--tools/porting/src/tokenizer.h88
-rw-r--r--tools/porting/src/tokenreplacements.cpp371
-rw-r--r--tools/porting/src/tokenreplacements.h154
-rw-r--r--tools/porting/src/tokens.h186
-rw-r--r--tools/porting/src/tokenstreamadapter.h152
-rw-r--r--tools/porting/src/translationunit.cpp102
-rw-r--r--tools/porting/src/translationunit.h93
-rw-r--r--tools/porting/src/treewalker.cpp457
-rw-r--r--tools/porting/src/treewalker.h235
-rw-r--r--tools/qconfig/LICENSE.GPL280
-rw-r--r--tools/qconfig/feature.cpp240
-rw-r--r--tools/qconfig/feature.h125
-rw-r--r--tools/qconfig/featuretreemodel.cpp451
-rw-r--r--tools/qconfig/featuretreemodel.h104
-rw-r--r--tools/qconfig/graphics.h195
-rw-r--r--tools/qconfig/main.cpp552
-rw-r--r--tools/qconfig/qconfig.pro10
-rw-r--r--tools/qdbus/qdbus.pro2
-rw-r--r--tools/qdbus/qdbus/qdbus.cpp483
-rw-r--r--tools/qdbus/qdbus/qdbus.pro10
-rw-r--r--tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.cpp446
-rw-r--r--tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.pro10
-rw-r--r--tools/qdbus/qdbusviewer/Info_mac.plist18
-rw-r--r--tools/qdbus/qdbusviewer/images/qdbusviewer-128.pngbin0 -> 9850 bytes
-rw-r--r--tools/qdbus/qdbusviewer/images/qdbusviewer.icnsbin0 -> 146951 bytes
-rw-r--r--tools/qdbus/qdbusviewer/images/qdbusviewer.icobin0 -> 355574 bytes
-rw-r--r--tools/qdbus/qdbusviewer/images/qdbusviewer.pngbin0 -> 1231 bytes
-rw-r--r--tools/qdbus/qdbusviewer/main.cpp85
-rw-r--r--tools/qdbus/qdbusviewer/propertydialog.cpp114
-rw-r--r--tools/qdbus/qdbusviewer/propertydialog.h70
-rw-r--r--tools/qdbus/qdbusviewer/qdbusmodel.cpp336
-rw-r--r--tools/qdbus/qdbusviewer/qdbusmodel.h94
-rw-r--r--tools/qdbus/qdbusviewer/qdbusviewer.cpp509
-rw-r--r--tools/qdbus/qdbusviewer/qdbusviewer.h98
-rw-r--r--tools/qdbus/qdbusviewer/qdbusviewer.pro30
-rw-r--r--tools/qdbus/qdbusviewer/qdbusviewer.qrc6
-rw-r--r--tools/qdbus/qdbusviewer/qdbusviewer.rc1
-rw-r--r--tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp1150
-rw-r--r--tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.pro10
-rw-r--r--tools/qdoc3/JAVATODO.txt28
-rw-r--r--tools/qdoc3/README.TXT6
-rw-r--r--tools/qdoc3/TODO.txt96
-rw-r--r--tools/qdoc3/apigenerator.cpp150
-rw-r--r--tools/qdoc3/apigenerator.h65
-rw-r--r--tools/qdoc3/archiveextractor.cpp108
-rw-r--r--tools/qdoc3/archiveextractor.h78
-rw-r--r--tools/qdoc3/atom.cpp357
-rw-r--r--tools/qdoc3/atom.h200
-rw-r--r--tools/qdoc3/bookgenerator.cpp64
-rw-r--r--tools/qdoc3/bookgenerator.h64
-rw-r--r--tools/qdoc3/ccodeparser.cpp73
-rw-r--r--tools/qdoc3/ccodeparser.h66
-rw-r--r--tools/qdoc3/codechunk.cpp150
-rw-r--r--tools/qdoc3/codechunk.h123
-rw-r--r--tools/qdoc3/codemarker.cpp538
-rw-r--r--tools/qdoc3/codemarker.h166
-rw-r--r--tools/qdoc3/codeparser.cpp263
-rw-r--r--tools/qdoc3/codeparser.h94
-rw-r--r--tools/qdoc3/command.cpp92
-rw-r--r--tools/qdoc3/command.h60
-rw-r--r--tools/qdoc3/config.cpp892
-rw-r--r--tools/qdoc3/config.h165
-rw-r--r--tools/qdoc3/cppcodemarker.cpp1009
-rw-r--r--tools/qdoc3/cppcodemarker.h91
-rw-r--r--tools/qdoc3/cppcodeparser.cpp2014
-rw-r--r--tools/qdoc3/cppcodeparser.h167
-rw-r--r--tools/qdoc3/cpptoqsconverter.cpp415
-rw-r--r--tools/qdoc3/cpptoqsconverter.h88
-rw-r--r--tools/qdoc3/dcfsection.cpp111
-rw-r--r--tools/qdoc3/dcfsection.h94
-rw-r--r--tools/qdoc3/doc.cpp5036
-rw-r--r--tools/qdoc3/doc.h315
-rw-r--r--tools/qdoc3/documentation.pri5
-rw-r--r--tools/qdoc3/editdistance.cpp111
-rw-r--r--tools/qdoc3/editdistance.h59
-rw-r--r--tools/qdoc3/generator.cpp995
-rw-r--r--tools/qdoc3/generator.h177
-rw-r--r--tools/qdoc3/helpprojectwriter.cpp653
-rw-r--r--tools/qdoc3/helpprojectwriter.h110
-rw-r--r--tools/qdoc3/htmlgenerator.cpp3195
-rw-r--r--tools/qdoc3/htmlgenerator.h253
-rw-r--r--tools/qdoc3/jambiapiparser.cpp547
-rw-r--r--tools/qdoc3/jambiapiparser.h99
-rw-r--r--tools/qdoc3/javacodemarker.cpp201
-rw-r--r--tools/qdoc3/javacodemarker.h80
-rw-r--r--tools/qdoc3/javadocgenerator.cpp453
-rw-r--r--tools/qdoc3/javadocgenerator.h95
-rw-r--r--tools/qdoc3/linguistgenerator.cpp245
-rw-r--r--tools/qdoc3/linguistgenerator.h85
-rw-r--r--tools/qdoc3/location.cpp401
-rw-r--r--tools/qdoc3/location.h131
-rw-r--r--tools/qdoc3/loutgenerator.cpp63
-rw-r--r--tools/qdoc3/loutgenerator.h67
-rw-r--r--tools/qdoc3/main.cpp496
-rw-r--r--tools/qdoc3/mangenerator.cpp228
-rw-r--r--tools/qdoc3/mangenerator.h79
-rw-r--r--tools/qdoc3/node.cpp1024
-rw-r--r--tools/qdoc3/node.h587
-rw-r--r--tools/qdoc3/openedlist.cpp228
-rw-r--r--tools/qdoc3/openedlist.h91
-rw-r--r--tools/qdoc3/pagegenerator.cpp219
-rw-r--r--tools/qdoc3/pagegenerator.h85
-rw-r--r--tools/qdoc3/plaincodemarker.cpp139
-rw-r--r--tools/qdoc3/plaincodemarker.h79
-rw-r--r--tools/qdoc3/polyarchiveextractor.cpp94
-rw-r--r--tools/qdoc3/polyarchiveextractor.h70
-rw-r--r--tools/qdoc3/polyuncompressor.cpp109
-rw-r--r--tools/qdoc3/polyuncompressor.h71
-rw-r--r--tools/qdoc3/qdoc3.pro108
-rw-r--r--tools/qdoc3/qsakernelparser.cpp186
-rw-r--r--tools/qdoc3/qsakernelparser.h77
-rw-r--r--tools/qdoc3/qscodemarker.cpp385
-rw-r--r--tools/qdoc3/qscodemarker.h80
-rw-r--r--tools/qdoc3/qscodeparser.cpp944
-rw-r--r--tools/qdoc3/qscodeparser.h128
-rw-r--r--tools/qdoc3/quoter.cpp369
-rw-r--r--tools/qdoc3/quoter.h89
-rw-r--r--tools/qdoc3/separator.cpp69
-rw-r--r--tools/qdoc3/separator.h57
-rw-r--r--tools/qdoc3/sgmlgenerator.cpp63
-rw-r--r--tools/qdoc3/sgmlgenerator.h67
-rw-r--r--tools/qdoc3/test/arthurtext.qdocconf6
-rw-r--r--tools/qdoc3/test/assistant.qdocconf45
-rw-r--r--tools/qdoc3/test/carbide-eclipse-integration.qdocconf12
-rw-r--r--tools/qdoc3/test/classic.css131
-rw-r--r--tools/qdoc3/test/compat.qdocconf31
-rw-r--r--tools/qdoc3/test/designer.qdocconf51
-rw-r--r--tools/qdoc3/test/eclipse-integration.qdocconf13
-rw-r--r--tools/qdoc3/test/jambi.qdocconf47
-rw-r--r--tools/qdoc3/test/linguist.qdocconf47
-rw-r--r--tools/qdoc3/test/macros.qdocconf27
-rw-r--r--tools/qdoc3/test/qmake.qdocconf40
-rw-r--r--tools/qdoc3/test/qt-api-only-with-xcode.qdocconf29
-rw-r--r--tools/qdoc3/test/qt-api-only.qdocconf30
-rw-r--r--tools/qdoc3/test/qt-build-docs-with-xcode.qdocconf3
-rw-r--r--tools/qdoc3/test/qt-build-docs.qdocconf109
-rw-r--r--tools/qdoc3/test/qt-cpp-ignore.qdocconf87
-rw-r--r--tools/qdoc3/test/qt-defines.qdocconf26
-rw-r--r--tools/qdoc3/test/qt-for-jambi.qdocconf12
-rw-r--r--tools/qdoc3/test/qt-html-templates.qdocconf32
-rw-r--r--tools/qdoc3/test/qt-inc.qdocconf146
-rw-r--r--tools/qdoc3/test/qt-linguist.qdocconf4
-rw-r--r--tools/qdoc3/test/qt-webxml.qdocconf11
-rw-r--r--tools/qdoc3/test/qt-with-extensions.qdocconf8
-rw-r--r--tools/qdoc3/test/qt-with-xcode.qdocconf3
-rw-r--r--tools/qdoc3/test/qt.qdocconf115
-rw-r--r--tools/qdoc3/test/standalone-eclipse-integration.qdocconf11
-rw-r--r--tools/qdoc3/text.cpp270
-rw-r--r--tools/qdoc3/text.h106
-rw-r--r--tools/qdoc3/tokenizer.cpp753
-rw-r--r--tools/qdoc3/tokenizer.h183
-rw-r--r--tools/qdoc3/tr.h60
-rw-r--r--tools/qdoc3/tree.cpp2012
-rw-r--r--tools/qdoc3/tree.h157
-rw-r--r--tools/qdoc3/uncompressor.cpp108
-rw-r--r--tools/qdoc3/uncompressor.h79
-rw-r--r--tools/qdoc3/webxmlgenerator.cpp1195
-rw-r--r--tools/qdoc3/webxmlgenerator.h122
-rw-r--r--tools/qdoc3/yyindent.cpp1190
-rw-r--r--tools/qev/README2
-rw-r--r--tools/qev/qev.cpp66
-rw-r--r--tools/qev/qev.pro13
-rw-r--r--tools/qtconcurrent/codegenerator/codegenerator.pri5
-rw-r--r--tools/qtconcurrent/codegenerator/example/example.pro9
-rw-r--r--tools/qtconcurrent/codegenerator/example/main.cpp83
-rw-r--r--tools/qtconcurrent/codegenerator/src/codegenerator.cpp140
-rw-r--r--tools/qtconcurrent/codegenerator/src/codegenerator.h204
-rw-r--r--tools/qtconcurrent/generaterun/main.cpp422
-rw-r--r--tools/qtconcurrent/generaterun/run.pro9
-rw-r--r--tools/qtconfig/LICENSE.GPL280
-rw-r--r--tools/qtconfig/colorbutton.cpp206
-rw-r--r--tools/qtconfig/colorbutton.h90
-rw-r--r--tools/qtconfig/images/appicon.pngbin0 -> 2238 bytes
-rw-r--r--tools/qtconfig/main.cpp56
-rw-r--r--tools/qtconfig/mainwindow.cpp1073
-rw-r--r--tools/qtconfig/mainwindow.h110
-rw-r--r--tools/qtconfig/mainwindowbase.cpp250
-rw-r--r--tools/qtconfig/mainwindowbase.h95
-rw-r--r--tools/qtconfig/mainwindowbase.ui1384
-rw-r--r--tools/qtconfig/paletteeditoradvanced.cpp591
-rw-r--r--tools/qtconfig/paletteeditoradvanced.h110
-rw-r--r--tools/qtconfig/paletteeditoradvancedbase.cpp144
-rw-r--r--tools/qtconfig/paletteeditoradvancedbase.h78
-rw-r--r--tools/qtconfig/paletteeditoradvancedbase.ui617
-rw-r--r--tools/qtconfig/previewframe.cpp104
-rw-r--r--tools/qtconfig/previewframe.h84
-rw-r--r--tools/qtconfig/previewwidget.cpp84
-rw-r--r--tools/qtconfig/previewwidget.h62
-rw-r--r--tools/qtconfig/previewwidgetbase.cpp88
-rw-r--r--tools/qtconfig/previewwidgetbase.h68
-rw-r--r--tools/qtconfig/previewwidgetbase.ui340
-rw-r--r--tools/qtconfig/qtconfig.pro28
-rw-r--r--tools/qtconfig/qtconfig.qrc5
-rw-r--r--tools/qtconfig/translations/translations.pro13
-rw-r--r--tools/qtestlib/qtestlib.pro4
-rw-r--r--tools/qtestlib/updater/main.cpp178
-rw-r--r--tools/qtestlib/updater/updater.pro10
-rw-r--r--tools/qtestlib/wince/cetest/activesyncconnection.cpp485
-rw-r--r--tools/qtestlib/wince/cetest/activesyncconnection.h86
-rw-r--r--tools/qtestlib/wince/cetest/bootstrapped.pri38
-rw-r--r--tools/qtestlib/wince/cetest/cetest.pro47
-rw-r--r--tools/qtestlib/wince/cetest/deployment.cpp267
-rw-r--r--tools/qtestlib/wince/cetest/deployment.h75
-rw-r--r--tools/qtestlib/wince/cetest/main.cpp351
-rw-r--r--tools/qtestlib/wince/cetest/qmake_include.pri7
-rw-r--r--tools/qtestlib/wince/cetest/remoteconnection.cpp68
-rw-r--r--tools/qtestlib/wince/cetest/remoteconnection.h82
-rw-r--r--tools/qtestlib/wince/remotelib/commands.cpp120
-rw-r--r--tools/qtestlib/wince/remotelib/commands.h51
-rw-r--r--tools/qtestlib/wince/remotelib/remotelib.pro15
-rw-r--r--tools/qtestlib/wince/wince.pro2
-rw-r--r--tools/qvfb/ClamshellPhone.qrc5
-rw-r--r--tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin30
-rw-r--r--tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.pngbin0 -> 68200 bytes
-rw-r--r--tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.pngbin0 -> 113907 bytes
-rw-r--r--tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.pngbin0 -> 113450 bytes
-rw-r--r--tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf78
-rw-r--r--tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.pngbin0 -> 115575 bytes
-rw-r--r--tools/qvfb/DualScreenPhone.skin/DualScreen.pngbin0 -> 104711 bytes
-rw-r--r--tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin29
-rw-r--r--tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf78
-rw-r--r--tools/qvfb/LICENSE.GPL280
-rw-r--r--tools/qvfb/PDAPhone.qrc5
-rw-r--r--tools/qvfb/PDAPhone.skin/PDAPhone.skin18
-rw-r--r--tools/qvfb/PDAPhone.skin/defaultbuttons.conf36
-rw-r--r--tools/qvfb/PDAPhone.skin/finger.pngbin0 -> 40343 bytes
-rw-r--r--tools/qvfb/PDAPhone.skin/pda_down.pngbin0 -> 52037 bytes
-rw-r--r--tools/qvfb/PDAPhone.skin/pda_up.pngbin0 -> 100615 bytes
-rw-r--r--tools/qvfb/PortableMedia.qrc5
-rw-r--r--tools/qvfb/PortableMedia.skin/PortableMedia.skin14
-rw-r--r--tools/qvfb/PortableMedia.skin/defaultbuttons.conf23
-rw-r--r--tools/qvfb/PortableMedia.skin/portablemedia-pressed.pngbin0 -> 6183 bytes
-rw-r--r--tools/qvfb/PortableMedia.skin/portablemedia.pngbin0 -> 6182 bytes
-rw-r--r--tools/qvfb/PortableMedia.skin/portablemedia.xcfbin0 -> 41592 bytes
-rw-r--r--tools/qvfb/README51
-rw-r--r--tools/qvfb/SmartPhone.qrc5
-rw-r--r--tools/qvfb/SmartPhone.skin/SmartPhone-pressed.pngbin0 -> 111515 bytes
-rw-r--r--tools/qvfb/SmartPhone.skin/SmartPhone.pngbin0 -> 101750 bytes
-rw-r--r--tools/qvfb/SmartPhone.skin/SmartPhone.skin28
-rw-r--r--tools/qvfb/SmartPhone.skin/defaultbuttons.conf78
-rw-r--r--tools/qvfb/SmartPhone2.qrc5
-rw-r--r--tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.pngbin0 -> 134749 bytes
-rw-r--r--tools/qvfb/SmartPhone2.skin/SmartPhone2.pngbin0 -> 121915 bytes
-rw-r--r--tools/qvfb/SmartPhone2.skin/SmartPhone2.skin25
-rw-r--r--tools/qvfb/SmartPhone2.skin/defaultbuttons.conf52
-rw-r--r--tools/qvfb/SmartPhoneWithButtons.qrc5
-rw-r--r--tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.pngbin0 -> 103838 bytes
-rw-r--r--tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.pngbin0 -> 88470 bytes
-rw-r--r--tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin31
-rw-r--r--tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf103
-rw-r--r--tools/qvfb/TouchscreenPhone.qrc5
-rw-r--r--tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.pngbin0 -> 88599 bytes
-rw-r--r--tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.pngbin0 -> 61809 bytes
-rw-r--r--tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin16
-rw-r--r--tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf45
-rw-r--r--tools/qvfb/Trolltech-Keypad.qrc5
-rw-r--r--tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.pngbin0 -> 69447 bytes
-rw-r--r--tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.pngbin0 -> 242107 bytes
-rw-r--r--tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.pngbin0 -> 230638 bytes
-rw-r--r--tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin35
-rw-r--r--tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf142
-rw-r--r--tools/qvfb/Trolltech-Touchscreen.qrc5
-rw-r--r--tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.pngbin0 -> 133117 bytes
-rw-r--r--tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.pngbin0 -> 133180 bytes
-rw-r--r--tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin17
-rw-r--r--tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf53
-rw-r--r--tools/qvfb/config.ui2528
-rw-r--r--tools/qvfb/gammaview.h59
-rw-r--r--tools/qvfb/images/logo-nt.pngbin0 -> 1965 bytes
-rw-r--r--tools/qvfb/images/logo.pngbin0 -> 2238 bytes
-rw-r--r--tools/qvfb/main.cpp155
-rw-r--r--tools/qvfb/pda.qrc5
-rw-r--r--tools/qvfb/pda.skin14
-rw-r--r--tools/qvfb/pda_down.pngbin0 -> 102655 bytes
-rw-r--r--tools/qvfb/pda_up.pngbin0 -> 100615 bytes
-rw-r--r--tools/qvfb/qanimationwriter.cpp451
-rw-r--r--tools/qvfb/qanimationwriter.h71
-rw-r--r--tools/qvfb/qtopiakeysym.h67
-rw-r--r--tools/qvfb/qvfb.cpp1137
-rw-r--r--tools/qvfb/qvfb.h159
-rw-r--r--tools/qvfb/qvfb.pro73
-rw-r--r--tools/qvfb/qvfb.qrc7
-rw-r--r--tools/qvfb/qvfbmmap.cpp222
-rw-r--r--tools/qvfb/qvfbmmap.h91
-rw-r--r--tools/qvfb/qvfbprotocol.cpp193
-rw-r--r--tools/qvfb/qvfbprotocol.h173
-rw-r--r--tools/qvfb/qvfbratedlg.cpp103
-rw-r--r--tools/qvfb/qvfbratedlg.h74
-rw-r--r--tools/qvfb/qvfbshmem.cpp314
-rw-r--r--tools/qvfb/qvfbshmem.h90
-rw-r--r--tools/qvfb/qvfbview.cpp824
-rw-r--r--tools/qvfb/qvfbview.h209
-rw-r--r--tools/qvfb/qvfbx11view.cpp388
-rw-r--r--tools/qvfb/qvfbx11view.h121
-rw-r--r--tools/qvfb/translations/translations.pro32
-rw-r--r--tools/qvfb/x11keyfaker.cpp626
-rw-r--r--tools/qvfb/x11keyfaker.h80
-rw-r--r--tools/shared/deviceskin/deviceskin.cpp857
-rw-r--r--tools/shared/deviceskin/deviceskin.h174
-rw-r--r--tools/shared/deviceskin/deviceskin.pri3
-rw-r--r--tools/shared/findwidget/abstractfindwidget.cpp295
-rw-r--r--tools/shared/findwidget/abstractfindwidget.h115
-rw-r--r--tools/shared/findwidget/findwidget.pri4
-rw-r--r--tools/shared/findwidget/findwidget.qrc14
-rw-r--r--tools/shared/findwidget/images/mac/closetab.pngbin0 -> 516 bytes
-rw-r--r--tools/shared/findwidget/images/mac/next.pngbin0 -> 1310 bytes
-rw-r--r--tools/shared/findwidget/images/mac/previous.pngbin0 -> 1080 bytes
-rw-r--r--tools/shared/findwidget/images/mac/searchfind.pngbin0 -> 1836 bytes
-rw-r--r--tools/shared/findwidget/images/win/closetab.pngbin0 -> 375 bytes
-rw-r--r--tools/shared/findwidget/images/win/next.pngbin0 -> 1038 bytes
-rw-r--r--tools/shared/findwidget/images/win/previous.pngbin0 -> 898 bytes
-rw-r--r--tools/shared/findwidget/images/win/searchfind.pngbin0 -> 1944 bytes
-rw-r--r--tools/shared/findwidget/images/wrap.pngbin0 -> 500 bytes
-rw-r--r--tools/shared/findwidget/itemviewfindwidget.cpp317
-rw-r--r--tools/shared/findwidget/itemviewfindwidget.h78
-rw-r--r--tools/shared/findwidget/texteditfindwidget.cpp169
-rw-r--r--tools/shared/findwidget/texteditfindwidget.h73
-rw-r--r--tools/shared/fontpanel/fontpanel.cpp304
-rw-r--r--tools/shared/fontpanel/fontpanel.h108
-rw-r--r--tools/shared/fontpanel/fontpanel.pri3
-rw-r--r--tools/shared/qtgradienteditor/images/down.pngbin0 -> 594 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/edit.pngbin0 -> 503 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/editdelete.pngbin0 -> 831 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/minus.pngbin0 -> 250 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/plus.pngbin0 -> 462 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/spreadpad.pngbin0 -> 151 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/spreadreflect.pngbin0 -> 165 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/spreadrepeat.pngbin0 -> 156 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/typeconical.pngbin0 -> 937 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/typelinear.pngbin0 -> 145 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/typeradial.pngbin0 -> 583 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/up.pngbin0 -> 692 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/zoomin.pngbin0 -> 1208 bytes
-rw-r--r--tools/shared/qtgradienteditor/images/zoomout.pngbin0 -> 1226 bytes
-rw-r--r--tools/shared/qtgradienteditor/qtcolorbutton.cpp278
-rw-r--r--tools/shared/qtgradienteditor/qtcolorbutton.h86
-rw-r--r--tools/shared/qtgradienteditor/qtcolorbutton.pri4
-rw-r--r--tools/shared/qtgradienteditor/qtcolorline.cpp1124
-rw-r--r--tools/shared/qtgradienteditor/qtcolorline.h124
-rw-r--r--tools/shared/qtgradienteditor/qtgradientdialog.cpp359
-rw-r--r--tools/shared/qtgradienteditor/qtgradientdialog.h87
-rw-r--r--tools/shared/qtgradienteditor/qtgradientdialog.ui121
-rw-r--r--tools/shared/qtgradienteditor/qtgradienteditor.cpp958
-rw-r--r--tools/shared/qtgradienteditor/qtgradienteditor.h111
-rw-r--r--tools/shared/qtgradienteditor/qtgradienteditor.pri33
-rw-r--r--tools/shared/qtgradienteditor/qtgradienteditor.qrc18
-rw-r--r--tools/shared/qtgradienteditor/qtgradienteditor.ui1377
-rw-r--r--tools/shared/qtgradienteditor/qtgradientmanager.cpp135
-rw-r--r--tools/shared/qtgradienteditor/qtgradientmanager.h92
-rw-r--r--tools/shared/qtgradienteditor/qtgradientstopscontroller.cpp730
-rw-r--r--tools/shared/qtgradienteditor/qtgradientstopscontroller.h106
-rw-r--r--tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp480
-rw-r--r--tools/shared/qtgradienteditor/qtgradientstopsmodel.h121
-rw-r--r--tools/shared/qtgradienteditor/qtgradientstopswidget.cpp1156
-rw-r--r--tools/shared/qtgradienteditor/qtgradientstopswidget.h115
-rw-r--r--tools/shared/qtgradienteditor/qtgradientutils.cpp420
-rw-r--r--tools/shared/qtgradienteditor/qtgradientutils.h66
-rw-r--r--tools/shared/qtgradienteditor/qtgradientview.cpp292
-rw-r--r--tools/shared/qtgradienteditor/qtgradientview.h99
-rw-r--r--tools/shared/qtgradienteditor/qtgradientview.ui135
-rw-r--r--tools/shared/qtgradienteditor/qtgradientviewdialog.cpp89
-rw-r--r--tools/shared/qtgradienteditor/qtgradientviewdialog.h75
-rw-r--r--tools/shared/qtgradienteditor/qtgradientviewdialog.ui121
-rw-r--r--tools/shared/qtgradienteditor/qtgradientwidget.cpp817
-rw-r--r--tools/shared/qtgradienteditor/qtgradientwidget.h120
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-arrow.pngbin0 -> 171 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-busy.pngbin0 -> 201 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-closedhand.pngbin0 -> 147 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-cross.pngbin0 -> 130 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-forbidden.pngbin0 -> 199 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-hand.pngbin0 -> 159 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-hsplit.pngbin0 -> 155 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-ibeam.pngbin0 -> 124 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-openhand.pngbin0 -> 160 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-sizeall.pngbin0 -> 174 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-sizeb.pngbin0 -> 161 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-sizef.pngbin0 -> 161 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-sizeh.pngbin0 -> 145 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-sizev.pngbin0 -> 141 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-uparrow.pngbin0 -> 132 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-vsplit.pngbin0 -> 161 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-wait.pngbin0 -> 172 bytes
-rw-r--r--tools/shared/qtpropertybrowser/images/cursor-whatsthis.pngbin0 -> 191 bytes
-rw-r--r--tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.cpp633
-rw-r--r--tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h89
-rw-r--r--tools/shared/qtpropertybrowser/qteditorfactory.cpp2591
-rw-r--r--tools/shared/qtpropertybrowser/qteditorfactory.h401
-rw-r--r--tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.cpp535
-rw-r--r--tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h80
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowser.cpp1965
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowser.h315
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowser.pri19
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowser.qrc23
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowserutils.cpp434
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertybrowserutils_p.h161
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertymanager.cpp6493
-rw-r--r--tools/shared/qtpropertybrowser/qtpropertymanager.h750
-rw-r--r--tools/shared/qtpropertybrowser/qttreepropertybrowser.cpp1048
-rw-r--r--tools/shared/qtpropertybrowser/qttreepropertybrowser.h138
-rw-r--r--tools/shared/qtpropertybrowser/qtvariantproperty.cpp2282
-rw-r--r--tools/shared/qtpropertybrowser/qtvariantproperty.h181
-rw-r--r--tools/shared/qttoolbardialog/images/back.pngbin0 -> 678 bytes
-rw-r--r--tools/shared/qttoolbardialog/images/down.pngbin0 -> 594 bytes
-rw-r--r--tools/shared/qttoolbardialog/images/forward.pngbin0 -> 655 bytes
-rw-r--r--tools/shared/qttoolbardialog/images/minus.pngbin0 -> 250 bytes
-rw-r--r--tools/shared/qttoolbardialog/images/plus.pngbin0 -> 462 bytes
-rw-r--r--tools/shared/qttoolbardialog/images/up.pngbin0 -> 692 bytes
-rw-r--r--tools/shared/qttoolbardialog/qttoolbardialog.cpp1877
-rw-r--r--tools/shared/qttoolbardialog/qttoolbardialog.h138
-rw-r--r--tools/shared/qttoolbardialog/qttoolbardialog.pri6
-rw-r--r--tools/shared/qttoolbardialog/qttoolbardialog.qrc10
-rw-r--r--tools/shared/qttoolbardialog/qttoolbardialog.ui207
-rw-r--r--tools/tools.pro30
-rw-r--r--tools/xmlpatterns/main.cpp386
-rw-r--r--tools/xmlpatterns/main.h75
-rw-r--r--tools/xmlpatterns/qapplicationargument.cpp344
-rw-r--r--tools/xmlpatterns/qapplicationargument_p.h100
-rw-r--r--tools/xmlpatterns/qapplicationargumentparser.cpp1028
-rw-r--r--tools/xmlpatterns/qapplicationargumentparser_p.h111
-rw-r--r--tools/xmlpatterns/qcoloringmessagehandler.cpp193
-rw-r--r--tools/xmlpatterns/qcoloringmessagehandler_p.h99
-rw-r--r--tools/xmlpatterns/qcoloroutput.cpp350
-rw-r--r--tools/xmlpatterns/qcoloroutput_p.h134
-rw-r--r--tools/xmlpatterns/xmlpatterns.pro31
1862 files changed, 383738 insertions, 0 deletions
diff --git a/tools/activeqt/activeqt.pro b/tools/activeqt/activeqt.pro
new file mode 100644
index 0000000000..a0e7de3599
--- /dev/null
+++ b/tools/activeqt/activeqt.pro
@@ -0,0 +1,11 @@
+TEMPLATE = subdirs
+
+CONFIG += ordered
+
+contains(QT_EDITION, OpenSource|Console) {
+ message("You are not licensed to use ActiveQt.")
+} else {
+ SUBDIRS = dumpdoc \
+ dumpcpp \
+ testcon
+}
diff --git a/tools/activeqt/dumpcpp/dumpcpp.pro b/tools/activeqt/dumpcpp/dumpcpp.pro
new file mode 100644
index 0000000000..09a339b0d6
--- /dev/null
+++ b/tools/activeqt/dumpcpp/dumpcpp.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+
+CONFIG += console qaxcontainer
+DESTDIR = ../../../bin
+
+SOURCES += main.cpp
diff --git a/tools/activeqt/dumpcpp/main.cpp b/tools/activeqt/dumpcpp/main.cpp
new file mode 100644
index 0000000000..05f1f193bf
--- /dev/null
+++ b/tools/activeqt/dumpcpp/main.cpp
@@ -0,0 +1,1502 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QAxObject>
+#include <QFile>
+#include <QMetaObject>
+#include <QMetaEnum>
+#include <QTextStream>
+#include <QSettings>
+#include <QStringList>
+#include <QUuid>
+#include <QWidget>
+#include <qt_windows.h>
+#include <ocidl.h>
+
+QT_BEGIN_NAMESPACE
+
+static ITypeInfo *currentTypeInfo = 0;
+
+enum ObjectCategory
+{
+ DefaultObject = 0x00,
+ SubObject = 0x001,
+ ActiveX = 0x002,
+ NoMetaObject = 0x004,
+ NoImplementation = 0x008,
+ NoDeclaration = 0x010,
+ NoInlines = 0x020,
+ OnlyInlines = 0x040,
+ DoNothing = 0x080,
+ Licensed = 0x100,
+ TypeLibID = 0x101
+};
+
+// this comes from moc/qmetaobject.cpp
+enum ProperyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resetable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+ Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000
+};
+
+enum MemberFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ MemberMethod = 0x00,
+ MemberSignal = 0x04,
+ MemberSlot = 0x08,
+ MemberCompatibility = 0x10,
+ MemberCloned = 0x20,
+ MemberScriptable = 0x40,
+};
+
+extern QMetaObject *qax_readEnumInfo(ITypeLib *typeLib, const QMetaObject *parentObject);
+extern QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject);
+extern QMetaObject *qax_readInterfaceInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject);
+extern QList<QByteArray> qax_qualified_usertypes;
+extern QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name);
+extern bool qax_dispatchEqualsIDispatch;
+
+QByteArray nameSpace;
+QMap<QByteArray, QByteArray> namespaceForType;
+
+void writeEnums(QTextStream &out, const QMetaObject *mo)
+{
+ // enums
+ for (int ienum = mo->enumeratorOffset(); ienum < mo->enumeratorCount(); ++ienum) {
+ QMetaEnum metaEnum = mo->enumerator(ienum);
+ out << " enum " << metaEnum.name() << " {" << endl;
+ for (int k = 0; k < metaEnum.keyCount(); ++k) {
+ QByteArray key(metaEnum.key(k));
+ out << " " << key.leftJustified(24) << "= " << metaEnum.value(k);
+ if (k < metaEnum.keyCount() - 1)
+ out << ",";
+ out << endl;
+ }
+ out << " };" << endl;
+ out << endl;
+ }
+}
+
+void writeHeader(QTextStream &out, const QByteArray &nameSpace)
+{
+ out << "#ifndef QAX_DUMPCPP_" << nameSpace.toUpper() << "_H" << endl;
+ out << "#define QAX_DUMPCPP_" << nameSpace.toUpper() << "_H" << endl;
+ out << endl;
+ out << "// Define this symbol to __declspec(dllexport) or __declspec(dllimport)" << endl;
+ out << "#ifndef " << nameSpace.toUpper() << "_EXPORT" << endl;
+ out << "#define " << nameSpace.toUpper() << "_EXPORT" << endl;
+ out << "#endif" << endl;
+ out << endl;
+ out << "#include <qaxobject.h>" << endl;
+ out << "#include <qaxwidget.h>" << endl;
+ out << "#include <qdatetime.h>" << endl;
+ out << "#include <qpixmap.h>" << endl;
+ out << endl;
+ out << "struct IDispatch;" << endl;
+ out << endl;
+}
+
+void generateNameSpace(QTextStream &out, const QMetaObject *mo, const QByteArray &nameSpace)
+{
+ out << "namespace " << nameSpace << " {" << endl;
+ out << endl;
+ writeEnums(out, mo);
+
+ // don't close on purpose
+}
+
+static QByteArray joinParameterNames(const QList<QByteArray> &parameterNames)
+{
+ QByteArray slotParameters;
+ for (int p = 0; p < parameterNames.count(); ++p) {
+ slotParameters += parameterNames.at(p);
+ if (p < parameterNames.count() - 1)
+ slotParameters += ',';
+ }
+
+ return slotParameters;
+}
+
+QByteArray constRefify(const QByteArray &type)
+{
+ QByteArray ctype(type);
+ if (type == "QString" || type == "QPixmap"
+ || type == "QVariant" || type == "QDateTime"
+ || type == "QColor" || type == "QFont"
+ || type == "QByteArray" || type == "QValueList<QVariant>"
+ || type == "QStringList")
+ ctype = "const " + ctype + "&";
+
+ return ctype;
+}
+
+void generateClassDecl(QTextStream &out, const QString &controlID, const QMetaObject *mo, const QByteArray &className, const QByteArray &nameSpace, ObjectCategory category)
+{
+ QList<QByteArray> functions;
+
+ QByteArray indent;
+ if (!(category & OnlyInlines))
+ indent = " ";
+
+ if (!(category & OnlyInlines)) {
+ // constructors
+ out << "class " << nameSpace.toUpper() << "_EXPORT " << className << " : public ";
+ if (category & ActiveX)
+ out << "QAxWidget";
+ else
+ out << "QAxObject";
+ out << endl;
+
+ out << "{" << endl;
+ out << "public:" << endl;
+ out << " " << className << "(";
+ if (category & Licensed)
+ out << "const QString &licenseKey = QString(), ";
+ if (category & ActiveX)
+ out << "QWidget *parent = 0, Qt::WindowFlags f";
+ else if (category & SubObject)
+ out << "IDispatch *subobject = 0, QAxObject *parent";
+ else
+ out << "QObject *parent";
+ out << " = 0)" << endl;
+ out << " : ";
+ if (category & ActiveX)
+ out << "QAxWidget(parent, f";
+ else if (category & SubObject)
+ out << "QAxObject((IUnknown*)subobject, parent";
+ else
+ out << "QAxObject(parent";
+ out << ")" << endl;
+ out << " {" << endl;
+ if (category & SubObject)
+ out << " internalRelease();" << endl;
+ else if (category & Licensed) {
+ out << " if (licenseKey.isEmpty())" << endl;
+ out << " setControl(\"" << controlID << "\");" << endl;
+ out << " else" << endl;
+ out << " setControl(\"" << controlID << ":\" + licenseKey);" << endl;
+ } else {
+ out << " setControl(\"" << controlID << "\");" << endl;
+ }
+ out << " }" << endl;
+ out << endl;
+
+ for (int ci = mo->classInfoOffset(); ci < mo->classInfoCount(); ++ci) {
+ QMetaClassInfo info = mo->classInfo(ci);
+ QByteArray iface_name = info.name();
+ if (iface_name.startsWith("Event "))
+ continue;
+
+ QByteArray iface_class = info.value();
+
+ out << " " << className << "(" << iface_class << " *iface)" << endl;
+
+ if (category & ActiveX)
+ out << " : QAxWidget()" << endl;
+ else
+ out << " : QAxObject()" << endl;
+ out << " {" << endl;
+ out << " initializeFrom(iface);" << endl;
+ out << " delete iface;" << endl;
+ out << " }" << endl;
+ out << endl;
+ }
+ }
+
+ functions << className;
+
+ // enums
+ if (nameSpace.isEmpty() && !(category & OnlyInlines)) {
+ for (int ienum = mo->enumeratorOffset(); ienum < mo->enumeratorCount(); ++ienum) {
+ QMetaEnum metaEnum = mo->enumerator(ienum);
+ out << " enum " << metaEnum.name() << " {" << endl;
+ for (int k = 0; k < metaEnum.keyCount(); ++k) {
+ QByteArray key(metaEnum.key(k));
+ out << " " << key.leftJustified(24) << "= " << metaEnum.value(k);
+ if (k < metaEnum.keyCount() - 1)
+ out << ",";
+ out << endl;
+ }
+ out << " };" << endl;
+ out << endl;
+ }
+ }
+ // QAxBase public virtual functions.
+ QList<QByteArray> axBase_vfuncs;
+ axBase_vfuncs.append("metaObject");
+ axBase_vfuncs.append("qObject");
+ axBase_vfuncs.append("className");
+ axBase_vfuncs.append("propertyWritable");
+ axBase_vfuncs.append("setPropertyWritable");
+
+ // properties
+ for (int iprop = mo->propertyOffset(); iprop < mo->propertyCount(); ++iprop) {
+ QMetaProperty property = mo->property(iprop);
+ if (!property.isReadable())
+ continue;
+
+ QByteArray propertyName(property.name());
+ if (propertyName == "control" || propertyName == className)
+ continue;
+
+ if (!(category & OnlyInlines)) {
+ out << indent << "/*" << endl << indent << "Property " << propertyName << endl;
+ QString documentation = qax_docuFromName(currentTypeInfo, QString::fromLatin1(propertyName.constData()));
+ if (!documentation.isEmpty()) {
+ out << endl;
+ out << indent << documentation << endl;
+ }
+ out << indent << "*/" << endl;
+ }
+
+ // Check whether the new function conflicts with any of QAxBase public virtual functions.
+ // If so, prepend the function name with '<classname>_'. Since all internal metaobject magic
+ // remains the same, we have to use the original name when used with QObject::connect or QMetaObject
+ QByteArray propertyFunctionName(propertyName);
+ if (axBase_vfuncs.contains(propertyFunctionName)) {
+ propertyFunctionName = className + "_" + propertyName;
+ qWarning("property conflits with QAXBase: %s changed to %s", propertyName.constData(), propertyFunctionName.constData());
+ }
+
+ QByteArray propertyType(property.typeName());
+ QByteArray castType(propertyType);
+
+ QByteArray simplePropType = propertyType;
+ simplePropType.replace('*', "");
+
+ out << indent << "inline ";
+ bool foreignNamespace = true;
+ if (!propertyType.contains("::") &&
+ (qax_qualified_usertypes.contains(simplePropType) || qax_qualified_usertypes.contains("enum "+ simplePropType))
+ ) {
+ propertyType = nameSpace + "::" + propertyType;
+ foreignNamespace = false;
+ }
+
+ out << propertyType << " ";
+
+ if (category & OnlyInlines)
+ out << className << "::";
+ out << propertyFunctionName << "() const";
+
+ if (!(category & NoInlines)) {
+ out << endl << indent << "{" << endl;
+ if (qax_qualified_usertypes.contains(simplePropType)) {
+ out << indent << " " << propertyType << " qax_pointer = 0;" << endl;
+ out << indent << " qRegisterMetaType(\"" << property.typeName() << "\", &qax_pointer);" << endl;
+ if (foreignNamespace)
+ out << "#ifdef QAX_DUMPCPP_" << propertyType.left(propertyType.indexOf("::")).toUpper() << "_H" << endl;
+ out << indent << " qRegisterMetaType(\"" << simplePropType << "\", qax_pointer);" << endl;
+ if (foreignNamespace)
+ out << "#endif" << endl;
+ }
+ out << indent << " QVariant qax_result = property(\"" << propertyName << "\");" << endl;
+ if (propertyType.length() && propertyType.at(propertyType.length()-1) == '*')
+ out << indent << " if (!qax_result.constData()) return 0;" << endl;
+ out << indent << " Q_ASSERT(qax_result.isValid());" << endl;
+ if (qax_qualified_usertypes.contains(simplePropType)) {
+ simplePropType = propertyType;
+ simplePropType.replace('*', "");
+ if (foreignNamespace)
+ out << "#ifdef QAX_DUMPCPP_" << propertyType.left(propertyType.indexOf("::")).toUpper() << "_H" << endl;
+ out << indent << " return *(" << propertyType << "*)qax_result.constData();" << endl;
+ if (foreignNamespace) {
+ out << "#else" << endl;
+ out << indent << " return 0; // foreign namespace not included" << endl;
+ out << "#endif" << endl;
+ }
+
+ } else {
+ out << indent << " return *(" << propertyType << "*)qax_result.constData();" << endl;
+ }
+ out << indent << "}" << endl;
+ } else {
+ out << "; //Returns the value of " << propertyName << endl;
+ }
+
+ functions << propertyName;
+
+ if (property.isWritable()) {
+ QByteArray setter(propertyName);
+ QChar firstChar = QLatin1Char(setter.at(0));
+ if (isupper(setter.at(0))) {
+ setter = "Set" + setter;
+ } else {
+ setter[0] = toupper(setter[0]);
+ setter = "set" + setter;
+ }
+
+ out << indent << "inline " << "void ";
+ if (category & OnlyInlines)
+ out << className << "::";
+ out << setter << "(" << constRefify(propertyType) << " value)";
+
+ if (!(category & NoInlines)) {
+ if (propertyType.endsWith('*')) {
+ out << "{" << endl;
+ out << " int typeId = qRegisterMetaType(\"" << propertyType << "\", &value);" << endl;
+ out << " setProperty(\"" << propertyName << "\", QVariant(typeId, &value));" << endl;
+ out << "}" << endl;
+ } else {
+ out << "{ setProperty(\"" << propertyName << "\", QVariant(value)); }" << endl;
+ }
+ } else {
+ out << "; //Sets the value of the " << propertyName << " property" << endl;
+ }
+
+ functions << setter;
+ }
+
+ out << endl;
+ }
+
+ // slots - but not property setters
+ int defaultArguments = 0;
+ for (int islot = mo->methodOffset(); islot < mo->methodCount(); ++islot) {
+ const QMetaMethod slot(mo->method(islot));
+ if (slot.methodType() != QMetaMethod::Slot)
+ continue;
+
+#if 0
+ // makes not sense really to respect default arguments...
+ if (slot.attributes() & Cloned) {
+ ++defaultArguments;
+ continue;
+ }
+#endif
+
+ QByteArray slotSignature(slot.signature());
+ QByteArray slotName = slotSignature.left(slotSignature.indexOf('('));
+ if (functions.contains(slotName))
+ continue;
+
+ if (!(category & OnlyInlines)) {
+ out << indent << "/*" << endl << indent << "Method " << slotName << endl;
+ QString documentation = qax_docuFromName(currentTypeInfo, QString::fromLatin1(slotName.constData()));
+ if (!documentation.isEmpty()) {
+ out << endl;
+ out << indent << documentation << endl;
+ }
+ out << indent << "*/" << endl;
+ }
+
+ QByteArray slotParameters(joinParameterNames(slot.parameterNames()));
+ QByteArray slotTag(slot.tag());
+ QByteArray slotType(slot.typeName());
+
+ QByteArray simpleSlotType = slotType;
+ simpleSlotType.replace('*', "");
+ if (!slotType.contains("::") && qax_qualified_usertypes.contains(simpleSlotType))
+ slotType = nameSpace + "::" + slotType;
+
+
+ QByteArray slotNamedSignature;
+ if (slotSignature.endsWith("()")) { // no parameters - no names
+ slotNamedSignature = slotSignature;
+ } else {
+ slotNamedSignature = slotSignature.left(slotSignature.indexOf('(') + 1);
+ QByteArray slotSignatureTruncated(slotSignature.mid(slotNamedSignature.length()));
+ slotSignatureTruncated.truncate(slotSignatureTruncated.length() - 1);
+
+ QList<QByteArray> signatureSplit = slotSignatureTruncated.split(',');
+ QList<QByteArray> parameterSplit;
+ if (slotParameters.isEmpty()) { // generate parameter names
+ for (int i = 0; i < signatureSplit.count(); ++i)
+ parameterSplit << QByteArray("p") + QByteArray::number(i);
+ } else {
+ parameterSplit = slotParameters.split(',');
+ }
+
+ for (int i = 0; i < signatureSplit.count(); ++i) {
+ QByteArray parameterType = signatureSplit.at(i);
+ if (!parameterType.contains("::") && namespaceForType.contains(parameterType))
+ parameterType = namespaceForType.value(parameterType) + "::" + parameterType;
+
+ slotNamedSignature += constRefify(parameterType);
+ slotNamedSignature += " ";
+ slotNamedSignature += parameterSplit.at(i);
+ if (defaultArguments >= signatureSplit.count() - i) {
+ slotNamedSignature += " = ";
+ slotNamedSignature += parameterType + "()";
+ }
+ if (i + 1 < signatureSplit.count())
+ slotNamedSignature += ", ";
+ }
+ slotNamedSignature += ')';
+ }
+
+ out << indent << "inline ";
+
+ if (!slotTag.isEmpty())
+ out << slotTag << " ";
+ if (slotType.isEmpty())
+ out << "void ";
+ else
+ out << slotType << " ";
+ if (category & OnlyInlines)
+ out << className << "::";
+
+ // Update function name in case of conflicts with QAxBase public virtual functions.
+ int parnIdx = slotNamedSignature.indexOf('(');
+ QByteArray slotOriginalName = slotNamedSignature.left(parnIdx);
+ if (axBase_vfuncs.contains(slotOriginalName)) {
+ QByteArray newSignature = className + "_" + slotOriginalName;
+ newSignature += slotNamedSignature.mid(parnIdx);
+ qWarning("function name conflits with QAXBase %s changed to %s", slotNamedSignature.constData(), newSignature.constData());
+ slotNamedSignature = newSignature;
+ }
+
+ out << slotNamedSignature;
+
+ if (category & NoInlines) {
+ out << ";" << endl;
+ } else {
+ out << endl;
+ out << indent << "{" << endl;
+
+ if (!slotType.isEmpty()) {
+ out << indent << " " << slotType << " qax_result";
+ if (slotType.endsWith('*'))
+ out << " = 0";
+ out << ";" << endl;
+ if (qax_qualified_usertypes.contains(simpleSlotType)) {
+ out << indent << " qRegisterMetaType(\"" << simpleSlotType << "*\", &qax_result);" << endl;
+ bool foreignNamespace = simpleSlotType.contains("::");
+ if (foreignNamespace)
+ out << "#ifdef QAX_DUMPCPP_" << simpleSlotType.left(simpleSlotType.indexOf(':')).toUpper() << "_H" << endl;
+ out << indent << " qRegisterMetaType(\"" << simpleSlotType << "\", qax_result);" << endl;
+ if (foreignNamespace)
+ out << "#endif" << endl;
+ }
+ }
+ out << indent << " void *_a[] = {";
+ if (!slotType.isEmpty())
+ out << "(void*)&qax_result";
+ else
+ out << "0";
+ if (!slotParameters.isEmpty()) {
+ out << ", (void*)&";
+ out << slotParameters.replace(",", ", (void*)&");
+ }
+ out << "};" << endl;
+
+ out << indent << " qt_metacall(QMetaObject::InvokeMetaMethod, " << islot << ", _a);" << endl;
+ if (!slotType.isEmpty())
+ out << indent << " return qax_result;" << endl;
+ out << indent << "}" << endl;
+ }
+
+ out << endl;
+ defaultArguments = 0;
+ }
+
+ if (!(category & OnlyInlines)) {
+ if (!(category & NoMetaObject)) {
+ out << "// meta object functions" << endl;
+ out << " static const QMetaObject staticMetaObject;" << endl;
+ out << " virtual const QMetaObject *metaObject() const { return &staticMetaObject; }" << endl;
+ out << " virtual void *qt_metacast(const char *);" << endl;
+ }
+
+ out << "};" << endl;
+ }
+}
+
+#define addString(string, stringData) \
+ out << stringDataLength << ", "; \
+ stringData += string; \
+ stringDataLength += qstrlen(string); \
+ stringData += "\\0"; \
+ lineLength += qstrlen(string) + 1; \
+ if (lineLength > 200) { stringData += "\"\n \""; lineLength = 0; } \
+ ++stringDataLength;
+
+void generateClassImpl(QTextStream &out, const QMetaObject *mo, const QByteArray &className, const QByteArray &nameSpace, ObjectCategory category)
+{
+ QByteArray qualifiedClassName;
+ if (!nameSpace.isEmpty())
+ qualifiedClassName = nameSpace + "::";
+ qualifiedClassName += className;
+
+ QByteArray stringData(qualifiedClassName);
+ int stringDataLength = stringData.length();
+ stringData += "\\0\"\n";
+ ++stringDataLength;
+ int lineLength = 0;
+
+ int classInfoCount = mo->classInfoCount() - mo->classInfoOffset();
+ int enumCount = mo->enumeratorCount() - mo->enumeratorOffset();
+ int methodCount = mo->methodCount() - mo->methodOffset();
+ int propertyCount = mo->propertyCount() - mo->propertyOffset();
+ int enumStart = 10;
+
+ out << "static const uint qt_meta_data_" << qualifiedClassName.replace(':', '_') << "[] = {" << endl;
+ out << endl;
+ out << " // content:" << endl;
+ out << " 1, // revision" << endl;
+ out << " 0, // classname" << endl;
+ out << " " << classInfoCount << ", " << (classInfoCount ? enumStart : 0) << ", // classinfo" << endl;
+ enumStart += classInfoCount * 2;
+ out << " " << methodCount << ", " << (methodCount ? enumStart : 0) << ", // methods" << endl;
+ enumStart += methodCount * 5;
+ out << " " << propertyCount << ", " << (propertyCount ? enumStart : 0) << ", // properties" << endl;
+ enumStart += propertyCount * 3;
+ out << " " << enumCount << ", " << (enumCount ? enumStart : 0)
+ << ", // enums/sets" << endl;
+ out << endl;
+
+ if (classInfoCount) {
+ out << " // classinfo: key, value" << endl;
+ stringData += " \"";
+ for (int i = 0; i < classInfoCount; ++i) {
+ QMetaClassInfo classInfo = mo->classInfo(i + mo->classInfoOffset());
+ out << " ";
+ addString(classInfo.name(), stringData);
+ addString(classInfo.value(), stringData);
+ out << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+ }
+ if (methodCount) {
+ out << " // signals: signature, parameters, type, tag, flags" << endl;
+ stringData += " \"";
+ for (int i = 0; i < methodCount; ++i) {
+ const QMetaMethod signal(mo->method(i + mo->methodOffset()));
+ if (signal.methodType() != QMetaMethod::Signal)
+ continue;
+ out << " ";
+ addString(signal.signature(), stringData);
+ addString(joinParameterNames(signal.parameterNames()), stringData);
+ addString(signal.typeName(), stringData);
+ addString(signal.tag(), stringData);
+ out << (AccessProtected | signal.attributes() | MemberSignal) << "," << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+
+ out << " // slots: signature, parameters, type, tag, flags" << endl;
+ stringData += " \"";
+ for (int i = 0; i < methodCount; ++i) {
+ const QMetaMethod slot(mo->method(i + mo->methodOffset()));
+ if (slot.methodType() != QMetaMethod::Slot)
+ continue;
+ out << " ";
+ addString(slot.signature(), stringData);
+ addString(joinParameterNames(slot.parameterNames()), stringData);
+ addString(slot.typeName(), stringData);
+ addString(slot.tag(), stringData);
+ out << (0x01 | slot.attributes() | MemberSlot) << "," << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+ }
+ if (propertyCount) {
+ out << " // properties: name, type, flags" << endl;
+ stringData += " \"";
+ for (int i = 0; i < propertyCount; ++i) {
+ QMetaProperty property = mo->property(i + mo->propertyOffset());
+ out << " ";
+ addString(property.name(), stringData);
+ addString(property.typeName(), stringData);
+
+ uint flags = 0;
+ uint vartype = property.type();
+ if (vartype != QVariant::Invalid && vartype != QVariant::UserType)
+ flags = vartype << 24;
+ else if (QByteArray(property.typeName()) == "QVariant")
+ flags |= 0xff << 24;
+
+ if (property.isReadable())
+ flags |= Readable;
+ if (property.isWritable())
+ flags |= Writable;
+ if (property.isEnumType())
+ flags |= EnumOrFlag;
+ if (property.isDesignable())
+ flags |= Designable;
+ if (property.isScriptable())
+ flags |= Scriptable;
+ if (property.isStored())
+ flags |= Stored;
+ if (property.isEditable())
+ flags |= Editable;
+
+ out << "0x" << QString::number(flags, 16).rightJustified(8, '0') << ", \t\t // " << property.typeName() << " " << property.name();
+ out << endl;
+ }
+ stringData += "\"\n";
+ out << endl;
+ }
+
+ QByteArray enumStringData;
+ if (enumCount) {
+ out << " // enums: name, flags, count, data" << endl;
+ enumStringData += " \"";
+ enumStart += enumCount * 4;
+ for (int i = 0; i < enumCount; ++i) {
+ QMetaEnum enumerator = mo->enumerator(i + mo->enumeratorOffset());
+ out << " ";
+ addString(enumerator.name(), enumStringData);
+ out << (enumerator.isFlag() ? "0x1" : "0x0") << ", " << enumerator.keyCount() << ", " << enumStart << ", " << endl;
+ enumStart += enumerator.keyCount() * 2;
+ }
+ enumStringData += "\"\n";
+ out << endl;
+
+ out << " // enum data: key, value" << endl;
+ for (int i = 0; i < enumCount; ++i) {
+ enumStringData += " \"";
+ QMetaEnum enumerator = mo->enumerator(i + mo->enumeratorOffset());
+ for (int j = 0; j < enumerator.keyCount(); ++j) {
+ out << " ";
+ addString(enumerator.key(j), enumStringData);
+ if (nameSpace.isEmpty())
+ out << className << "::";
+ else
+ out << nameSpace << "::";
+ out << enumerator.key(j) << "," << endl;
+ }
+ enumStringData += "\"\n";
+ }
+ out << endl;
+ }
+ out << " 0 // eod" << endl;
+ out << "};" << endl;
+ out << endl;
+
+ QByteArray stringGenerator;
+
+ if (!nameSpace.isEmpty()) {
+ static bool firstStringData = true;
+ if (firstStringData) { // print enums only once
+ firstStringData = false;
+ if (!enumStringData.isEmpty()) {
+ // Maximum string length supported is 64K
+ int maxStringLength = 65535;
+ if (enumStringData.size() < maxStringLength) {
+ out << "static const char qt_meta_enumstringdata_" << nameSpace << "[] = {" << endl;
+ out << enumStringData << endl;
+ out << "};" << endl;
+ out << endl;
+ } else {
+ // split the string into fragments of 64k
+ int fragments = (enumStringData.size() / maxStringLength);
+ fragments += (enumStringData.size() % maxStringLength) ? 1 : 0;
+ int i, index;
+ // define the fragments (qt_meta_enumstringdata_<nameSpace>fragment#)
+ for (i = 0 , index = 0; i < fragments; i++, index += maxStringLength) {
+ out << "static const char qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) << "[] = {" << endl;
+ QByteArray fragment = enumStringData.mid(index, maxStringLength);
+ if (!(fragment[0] == ' ' || fragment[0] == '\n' || fragment[0] == '\"'))
+ out << "\"";
+ out << fragment;
+ int endIx = fragment.size() - 1;
+ if (!(fragment[endIx] == ' ' || fragment[endIx] == '\n' || fragment[endIx] == '\"' || fragment[endIx] == '\0'))
+ out << "\"" << endl;
+ else
+ out << endl;
+ out << "};" << endl;
+ }
+ // original array definition, size will be the combined size of the arrays defined above
+ out << "static char qt_meta_enumstringdata_" << nameSpace << "[" << endl;
+ for (i = 0; i < fragments; i++, index += maxStringLength) {
+ out << " ";
+ if (i)
+ out << "+ ";
+ out << "sizeof(qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) <<")" << endl;
+ }
+ out << "] = {0};" << endl << endl;
+ // this class will initializes the original array in constructor
+ out << "class qt_meta_enumstringdata_" << nameSpace << "_init " << endl <<"{" <<endl;
+ out << "public:"<<endl;
+ out << " qt_meta_enumstringdata_" << nameSpace << "_init() " << endl <<" {" <<endl;
+ out << " int index = 0;" << endl;
+ for (i = 0; i < fragments; i++, index += maxStringLength) {
+ out << " memcpy(qt_meta_enumstringdata_" << nameSpace << " + index, " <<"qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i);
+ out << ", sizeof(qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) <<") - 1);" << endl;
+ out << " index += sizeof(qt_meta_enumstringdata_" << nameSpace << "fragment"<< QString::number(i) <<") - 1;" << endl;
+ }
+ out << " }" << endl << "};" << endl;
+ // a global variable of the class
+ out << "static qt_meta_enumstringdata_" << nameSpace << "_init qt_meta_enumstringdata_" << nameSpace << "_init_instance;" << endl << endl;
+ }
+ }
+ }
+ stringGenerator = "qt_meta_stringdata_" + qualifiedClassName.replace(':','_') + "()";
+ out << "static const char *" << stringGenerator << " {" << endl;
+ QList<QByteArray> splitStrings;
+
+ // workaround for compilers that can't handle string literals longer than 64k
+ int splitCount = 0;
+ do {
+ int lastNewline = stringData.lastIndexOf('\n', 64000);
+ QByteArray splitString = stringData.left(lastNewline);
+
+ splitStrings << splitString;
+ out << " static const char stringdata" << splitCount << "[] = {" << endl;
+ out << " \"" << splitString << endl;
+ out << " };" << endl;
+ stringData = stringData.mid(lastNewline + 1);
+ if (stringData.startsWith(" \""))
+ stringData = stringData.mid(5);
+ ++splitCount;
+ } while (!stringData.isEmpty());
+
+ out << " static char data[";
+ for (int i = 0; i < splitCount; ++i) {
+ out << "sizeof(stringdata" << i << ") + ";
+ }
+ if (!enumStringData.isEmpty()) {
+ out << "sizeof(qt_meta_enumstringdata_" << nameSpace << ")";
+ } else {
+ out << "0";
+ }
+ out << "];" << endl;
+ out << " if (!data[0]) {" << endl;
+ out << " int index = 0;" << endl;
+
+ int dataIndex = 0;
+ for (int i = 0; i < splitCount; ++i) {
+ out << " memcpy(data + index";
+ out << ", stringdata" << i << ", sizeof(stringdata" << i << ") - 1);" << endl;
+ out << " index += sizeof(stringdata" << i << ") - 1;" << endl;
+ dataIndex += splitStrings.at(i).length();
+ }
+ if (!enumStringData.isEmpty()) {
+ out << " memcpy(data + index, qt_meta_enumstringdata_" << nameSpace << ", sizeof(qt_meta_enumstringdata_" << nameSpace << "));" << endl;
+ }
+ out << " }" << endl;
+ out << endl;
+ out << " return data;" << endl;
+ out << "};" << endl;
+ out << endl;
+ } else {
+ stringData += enumStringData;
+ stringGenerator = "qt_meta_stringdata_" + qualifiedClassName.replace(':','_');
+ out << "static const char qt_meta_stringdata_" << stringGenerator << "[] = {" << endl;
+ out << " \"" << stringData << endl;
+ out << "};" << endl;
+ out << endl;
+ }
+
+ out << "const QMetaObject " << className << "::staticMetaObject = {" << endl;
+ if (category & ActiveX)
+ out << "{ &QWidget::staticMetaObject," << endl;
+ else
+ out << "{ &QObject::staticMetaObject," << endl;
+ out << stringGenerator << "," << endl;
+ out << "qt_meta_data_" << qualifiedClassName.replace(':','_') << " }" << endl;
+ out << "};" << endl;
+ out << endl;
+
+ out << "void *" << className << "::qt_metacast(const char *_clname)" << endl;
+ out << "{" << endl;
+ out << " if (!_clname) return 0;" << endl;
+ out << " if (!strcmp(_clname, " << stringGenerator << "))" << endl;
+ out << " return static_cast<void*>(const_cast<" << className << "*>(this));" << endl;
+ if (category & ActiveX)
+ out << " return QAxWidget::qt_metacast(_clname);" << endl;
+ else
+ out << " return QAxObject::qt_metacast(_clname);" << endl;
+ out << "}" << endl;
+}
+
+bool generateClass(QAxObject *object, const QByteArray &className, const QByteArray &nameSpace, const QByteArray &outname, ObjectCategory category)
+{
+ IOleControl *control = 0;
+ object->queryInterface(IID_IOleControl, (void**)&control);
+ if (control) {
+ category = ActiveX;
+ control->Release();
+ }
+
+ const QMetaObject *mo = object->metaObject();
+
+ if (!nameSpace.isEmpty() && !(category & NoDeclaration)) {
+ QFile outfile(QString::fromLatin1(nameSpace.toLower().constData()) + QLatin1String(".h"));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(outfile.fileName()));
+ return false;
+ }
+ QTextStream out(&outfile);
+
+ out << "/****************************************************************************" << endl;
+ out << "**" << endl;
+ out << "** Namespace " << nameSpace << " generated by dumpcpp" << endl;
+ out << "**" << endl;
+ out << "****************************************************************************/" << endl;
+ out << endl;
+
+ writeHeader(out, nameSpace);
+ generateNameSpace(out, mo, nameSpace);
+
+ // close namespace file
+ out << "};" << endl;
+ out << endl;
+
+ out << "#endif" << endl;
+ out << endl;
+ }
+
+ if (!(category & NoDeclaration)) {
+ QFile outfile(QString::fromLatin1(outname.constData()) + QLatin1String(".h"));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(outfile.fileName()));
+ return false;
+ }
+ QTextStream out(&outfile);
+
+ out << "/****************************************************************************" << endl;
+ out << "**" << endl;
+ out << "** Class declaration generated by dumpcpp" << endl;
+ out << "**" << endl;
+ out << "****************************************************************************/" << endl;
+ out << endl;
+
+ out << "#include <qdatetime.h>" << endl;
+ if (category & ActiveX)
+ out << "#include <qaxwidget.h>" << endl;
+ else
+ out << "#include <qaxobject.h>" << endl;
+ out << endl;
+
+ out << "struct IDispatch;" << endl,
+ out << endl;
+
+ if (!nameSpace.isEmpty()) {
+ out << "#include \"" << nameSpace.toLower() << ".h\"" << endl;
+ out << endl;
+ out << "namespace " << nameSpace << " {" << endl;
+ }
+
+ generateClassDecl(out, object->control(), mo, className, nameSpace, category);
+
+ if (!nameSpace.isEmpty()) {
+ out << endl;
+ out << "};" << endl;
+ }
+ }
+
+ if (!(category & (NoMetaObject|NoImplementation))) {
+ QFile outfile(QString::fromLatin1(outname.constData()) + QLatin1String(".cpp"));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(outfile.fileName()));
+ return false;
+ }
+ QTextStream out(&outfile);
+
+ out << "#include <qmetaobject.h>" << endl;
+ out << "#include \"" << outname << ".h\"" << endl;
+ out << endl;
+
+ if (!nameSpace.isEmpty()) {
+ out << "using namespace " << nameSpace << ";" << endl;
+ out << endl;
+ }
+
+ generateClassImpl(out, mo, className, nameSpace, category);
+ }
+
+ return true;
+}
+
+bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, ObjectCategory category)
+{
+ QString typeLibFile(QString::fromLatin1(typeLib.constData()));
+ typeLibFile = typeLibFile.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ QString cppFile(QString::fromLatin1(outname.constData()));
+
+ ITypeLib *typelib;
+ LoadTypeLibEx(reinterpret_cast<const wchar_t *>(typeLibFile.utf16()), REGKIND_NONE, &typelib);
+ if (!typelib) {
+ qWarning("dumpcpp: loading '%s' as a type library failed", qPrintable(typeLibFile));
+ return false;
+ }
+
+ QString libName;
+ BSTR nameString;
+ typelib->GetDocumentation(-1, &nameString, 0, 0, 0);
+ libName = QString::fromUtf16((const ushort *)nameString);
+ SysFreeString(nameString);
+ if (!nameSpace.isEmpty())
+ libName = QString(nameSpace);
+
+ QString libVersion(QLatin1String("1.0"));
+
+ TLIBATTR *tlibattr = 0;
+ typelib->GetLibAttr(&tlibattr);
+ if (tlibattr) {
+ libVersion = QString::fromLatin1("%1.%2").arg(tlibattr->wMajorVerNum).arg(tlibattr->wMinorVerNum);
+ typelib->ReleaseTLibAttr(tlibattr);
+ }
+
+ if (cppFile.isEmpty())
+ cppFile = libName.toLower();
+
+ if (cppFile.isEmpty()) {
+ qWarning("dumpcpp: no output filename provided, and cannot deduce output filename");
+ return false;
+ }
+
+ QMetaObject *namespaceObject = qax_readEnumInfo(typelib, 0);
+
+ QFile implFile(cppFile + QLatin1String(".cpp"));
+ QTextStream implOut(&implFile);
+ if (!(category & (NoMetaObject|NoImplementation))) {
+ if (!implFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(implFile.fileName()));
+ return false;
+ }
+
+ implOut << "/****************************************************************************" << endl;
+ implOut << "**" << endl;
+ implOut << "** Metadata for " << libName << " generated by dumpcpp from type library" << endl;
+ implOut << "** " << typeLibFile << endl;
+ implOut << "**" << endl;
+ implOut << "****************************************************************************/" << endl;
+ implOut << endl;
+
+ implOut << "#define QAX_DUMPCPP_" << libName.toUpper() << "_NOINLINES" << endl;
+
+ implOut << "#include \"" << cppFile << ".h\"" << endl;
+ implOut << endl;
+ implOut << "using namespace " << libName << ";" << endl;
+ implOut << endl;
+ }
+
+ QFile declFile(cppFile + QLatin1String(".h"));
+ QTextStream declOut(&declFile);
+ QByteArray classes;
+ QTextStream classesOut(&classes, QIODevice::WriteOnly);
+ QByteArray inlines;
+ QTextStream inlinesOut(&inlines, QIODevice::WriteOnly);
+
+ QMap<QByteArray, QList<QByteArray> > namespaces;
+
+ if(!(category & NoDeclaration)) {
+ if (!declFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpcpp: Could not open output file '%s'", qPrintable(declFile.fileName()));
+ return false;
+ }
+
+ declOut << "/****************************************************************************" << endl;
+ declOut << "**" << endl;
+ declOut << "** Namespace " << libName << " generated by dumpcpp from type library" << endl;
+ declOut << "** " << typeLibFile << endl;
+ declOut << "**" << endl;
+ declOut << "****************************************************************************/" << endl;
+ declOut << endl;
+
+ writeHeader(declOut, libName.toLatin1());
+
+ UINT typeCount = typelib->GetTypeInfoCount();
+ if (declFile.isOpen()) {
+ declOut << endl;
+ declOut << "// Referenced namespace" << endl;
+ for (UINT index = 0; index < typeCount; ++index) {
+ ITypeInfo *typeinfo = 0;
+ typelib->GetTypeInfo(index, &typeinfo);
+ if (!typeinfo)
+ continue;
+
+ TYPEATTR *typeattr;
+ typeinfo->GetTypeAttr(&typeattr);
+ if (!typeattr) {
+ typeinfo->Release();
+ continue;
+ }
+
+ TYPEKIND typekind;
+ typelib->GetTypeInfoType(index, &typekind);
+
+ QMetaObject *metaObject = 0;
+
+ // trigger meta object to collect references to other type libraries
+ switch (typekind) {
+ case TKIND_COCLASS:
+ if (category & ActiveX)
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_DISPATCH:
+ if (category & ActiveX)
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_RECORD:
+ case TKIND_ENUM:
+ case TKIND_INTERFACE: // only for forward declarations
+ {
+ QByteArray className;
+ BSTR bstr;
+ if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0))
+ break;
+ className = QString::fromUtf16((const ushort *)bstr).toLatin1();
+ SysFreeString(bstr);
+ switch (typekind) {
+ case TKIND_RECORD:
+ className = "struct " + className;
+ break;
+ case TKIND_ENUM:
+ className = "enum " + className;
+ break;
+ default:
+ break;
+ }
+ namespaces[libName.toLatin1()].append(className);
+ if (!qax_qualified_usertypes.contains(className))
+ qax_qualified_usertypes << className;
+ }
+ break;
+ default:
+ break;
+ }
+
+ delete metaObject;
+ typeinfo->ReleaseTypeAttr(typeattr);
+ typeinfo->Release();
+ }
+
+ for (int i = 0; i < qax_qualified_usertypes.count(); ++i) {
+ QByteArray refType = qax_qualified_usertypes.at(i);
+ QByteArray refTypeLib;
+ if (refType.contains("::")) {
+ refTypeLib = refType;
+ refType = refType.mid(refType.lastIndexOf("::") + 2);
+ if (refTypeLib.contains(' ')) {
+ refType = refTypeLib.left(refTypeLib.indexOf(' ')) + ' ' + refType;
+ }
+ refTypeLib = refTypeLib.left(refTypeLib.indexOf("::"));
+ refTypeLib = refTypeLib.mid(refTypeLib.lastIndexOf(' ') + 1);
+ namespaces[refTypeLib].append(refType);
+ } else {
+ namespaces[libName.toLatin1()].append(refType);
+ }
+ }
+
+ QList<QByteArray> keys = namespaces.keys();
+ for (int n = 0; n < keys.count(); ++n) {
+ QByteArray nspace = keys.at(n);
+ if (QString::fromLatin1(nspace.constData()) != libName) {
+ declOut << "namespace " << nspace << " {" << endl;
+ QList<QByteArray> classList = namespaces.value(nspace);
+ for (int c = 0; c < classList.count(); ++c) {
+ QByteArray className = classList.at(c);
+ if (className.contains(' ')) {
+ declOut << " " << className << ";" << endl;
+ namespaceForType.insert(className.mid(className.indexOf(' ') + 1), nspace);
+ } else {
+ declOut << " class " << className << ";" << endl;
+ namespaceForType.insert(className, nspace);
+ namespaceForType.insert(className + "*", nspace);
+ }
+ }
+ declOut << "}" << endl << endl;
+ }
+ }
+
+ declOut << endl;
+ }
+ generateNameSpace(declOut, namespaceObject, libName.toLatin1());
+
+ QList<QByteArray> classList = namespaces.value(libName.toLatin1());
+ if (classList.count())
+ declOut << "// forward declarations" << endl;
+ for (int c = 0; c < classList.count(); ++c) {
+ QByteArray className = classList.at(c);
+ if (className.contains(' ')) {
+ declOut << " " << className << ";" << endl;
+ namespaceForType.insert(className.mid(className.indexOf(' ') + 1), libName.toLatin1());
+ } else {
+ declOut << " class " << className << ";" << endl;
+ namespaceForType.insert(className, libName.toLatin1());
+ namespaceForType.insert(className + "*", libName.toLatin1());
+ }
+ }
+
+ declOut << endl;
+ }
+
+ QList<QByteArray> subtypes;
+
+ UINT typeCount = typelib->GetTypeInfoCount();
+ for (UINT index = 0; index < typeCount; ++index) {
+ ITypeInfo *typeinfo = 0;
+ typelib->GetTypeInfo(index, &typeinfo);
+ if (!typeinfo)
+ continue;
+
+ TYPEATTR *typeattr;
+ typeinfo->GetTypeAttr(&typeattr);
+ if (!typeattr) {
+ typeinfo->Release();
+ continue;
+ }
+
+ TYPEKIND typekind;
+ typelib->GetTypeInfoType(index, &typekind);
+
+ uint object_category = category;
+ if (!(typeattr->wTypeFlags & TYPEFLAG_FCANCREATE))
+ object_category |= SubObject;
+ else if (typeattr->wTypeFlags & TYPEFLAG_FCONTROL)
+ object_category |= ActiveX;
+
+ QMetaObject *metaObject = 0;
+ QUuid guid(typeattr->guid);
+
+ if (!(object_category & ActiveX)) {
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID\\") + guid.toString(), QSettings::NativeFormat);
+ if (settings.childGroups().contains(QLatin1String("Control"))) {
+ object_category |= ActiveX;
+ object_category &= ~SubObject;
+ }
+ }
+
+ switch (typekind) {
+ case TKIND_COCLASS:
+ if (object_category & ActiveX)
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readClassInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_DISPATCH:
+ if (object_category & ActiveX)
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QWidget::staticMetaObject);
+ else
+ metaObject = qax_readInterfaceInfo(typelib, typeinfo, &QObject::staticMetaObject);
+ break;
+ case TKIND_INTERFACE: // only stub
+ {
+ QByteArray className;
+ BSTR bstr;
+ if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0))
+ break;
+ className = QString::fromUtf16((const ushort *)bstr).toLatin1();
+ SysFreeString(bstr);
+
+ declOut << "// stub for vtable-only interface" << endl;
+ declOut << "class " << className << " : public QAxObject {};" << endl << endl;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (metaObject) {
+ currentTypeInfo = typeinfo;
+ QByteArray className(metaObject->className());
+ if (!(typeattr->wTypeFlags & TYPEFLAG_FDUAL)
+ && (metaObject->propertyCount() - metaObject->propertyOffset()) == 1
+ && className.contains("Events")) {
+ declOut << "// skipping event interface " << className << endl << endl;
+ } else {
+ if (declFile.isOpen()) {
+ if (typeattr->wTypeFlags & TYPEFLAG_FLICENSED)
+ object_category |= Licensed;
+ if (typekind == TKIND_COCLASS) { // write those later...
+ generateClassDecl(classesOut, guid.toString(), metaObject, className, libName.toLatin1(), (ObjectCategory)(object_category|NoInlines));
+ classesOut << endl;
+ } else {
+ generateClassDecl(declOut, guid.toString(), metaObject, className, libName.toLatin1(), (ObjectCategory)(object_category|NoInlines));
+ declOut << endl;
+ }
+ subtypes << className;
+ generateClassDecl(inlinesOut, guid.toString(), metaObject, className, libName.toLatin1(), (ObjectCategory)(object_category|OnlyInlines));
+ inlinesOut << endl;
+ }
+ if (implFile.isOpen()) {
+ generateClassImpl(implOut, metaObject, className, libName.toLatin1(), (ObjectCategory)object_category);
+ implOut << endl;
+ }
+ }
+ currentTypeInfo = 0;
+ }
+
+ delete metaObject;
+
+ typeinfo->ReleaseTypeAttr(typeattr);
+ typeinfo->Release();
+ }
+
+ delete namespaceObject;
+
+ classesOut.flush();
+ inlinesOut.flush();
+
+ if (declFile.isOpen()) {
+ if (classes.size()) {
+ declOut << "// Actual coclasses" << endl;
+ declOut << classes;
+ }
+ if (inlines.size()) {
+ declOut << "// member function implementation" << endl;
+ declOut << "#ifndef QAX_DUMPCPP_" << libName.toUpper() << "_NOINLINES" << endl;
+ declOut << inlines << endl;
+ declOut << "#endif" << endl << endl;
+ }
+ // close namespace
+ declOut << "}" << endl;
+ declOut << endl;
+
+ // partial template specialization for qMetaTypeConstructHelper
+ for (int t = 0; t < subtypes.count(); ++t) {
+ QByteArray subType(subtypes.at(t));
+ declOut << "template<>" << endl;
+ declOut << "inline void *qMetaTypeConstructHelper(const " << libName << "::" << subType << " *t)" << endl;
+ declOut << "{ Q_ASSERT(!t); return new " << libName << "::" << subType << "; }" << endl;
+ declOut << endl;
+ }
+
+ declOut << "#endif" << endl;
+ declOut << endl;
+ }
+
+ typelib->Release();
+ return true;
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ qax_dispatchEqualsIDispatch = false;
+
+ CoInitialize(0);
+
+ uint category = DefaultObject;
+
+ enum State {
+ Default = 0,
+ Output,
+ NameSpace,
+ GetTypeLib
+ } state;
+ state = Default;
+
+ QByteArray outname;
+ QByteArray typeLib;
+
+ for (int a = 1; a < argc; ++a) {
+ QByteArray arg(argv[a]);
+ const char first = arg[0];
+ switch(state) {
+ case Default:
+ if (first == '-' || first == '/') {
+ arg = arg.mid(1);
+ arg.toLower();
+
+ if (arg == "o") {
+ state = Output;
+ } else if (arg == "n") {
+ state = NameSpace;
+ } else if (arg == "v") {
+ qWarning("dumpcpp: Version 1.0");
+ return 0;
+ } else if (arg == "nometaobject") {
+ category |= NoMetaObject;
+ } else if (arg == "impl") {
+ category |= NoDeclaration;
+ } else if (arg == "decl") {
+ category |= NoImplementation;
+ } else if (arg == "donothing") {
+ category = DoNothing;
+ break;
+ } else if (arg == "compat") {
+ qax_dispatchEqualsIDispatch = true;
+ break;
+ } else if (arg == "getfile") {
+ state = GetTypeLib;
+ break;
+ } else if (arg == "h") {
+ qWarning("dumpcpp Version1.0\n\n"
+ "Generate a C++ namespace from a type library.\n\n"
+ "Usage:\n"
+ "dumpcpp input [-[-n <namespace>] [-o <filename>]\n\n"
+ " input: A type library file, type library ID, ProgID or CLSID\n\n"
+ "Optional parameters:\n"
+ " namespace: The name of the generated C++ namespace\n"
+ " filename: The file name (without extension) of the generated files\n"
+ "\n"
+ "Other parameters:\n"
+ " -nometaobject Don't generate meta object information (no .cpp file)\n"
+ " -impl Only generate the .cpp file\n"
+ " -decl Only generate the .h file\n"
+ " -compat Treat all coclass parameters as IDispatch\n"
+ "\n"
+ "Examples:\n"
+ " dumpcpp Outlook.Application -o outlook\n"
+ " dumpcpp {3B756301-0075-4E40-8BE8-5A81DE2426B7}\n"
+ "\n");
+ return 0;
+ }
+ } else {
+ typeLib = arg;
+ }
+ break;
+
+ case Output:
+ outname = arg;
+ state = Default;
+ break;
+
+ case NameSpace:
+ nameSpace = arg;
+ state = Default;
+ break;
+
+ case GetTypeLib:
+ typeLib = arg;
+ state = Default;
+ category = TypeLibID;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (category == TypeLibID) {
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes\\TypeLib\\") +
+ QString::fromLatin1(typeLib.constData()), QSettings::NativeFormat);
+ typeLib = QByteArray();
+ QStringList codes = settings.childGroups();
+ for (int c = 0; c < codes.count(); ++c) {
+ typeLib = settings.value(QLatin1String("/") + codes.at(c) + QLatin1String("/0/win32/.")).toByteArray();
+ if (QFile::exists(QString::fromLatin1(typeLib))) {
+ break;
+ }
+ }
+
+ if (!typeLib.isEmpty())
+ fprintf(stdout, "\"%s\"\n", typeLib.data());
+ return 0;
+ }
+
+ if (category == DoNothing)
+ return 0;
+
+ if (typeLib.isEmpty()) {
+ qWarning("dumpcpp: No object class or type library name provided.\n"
+ " Use -h for help.");
+ return -1;
+ }
+
+ // not a file - search registry
+ if (!QFile::exists(QString::fromLatin1(typeLib.constData()))) {
+ bool isObject = false;
+ QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Classes"), QSettings::NativeFormat);
+
+ // regular string and not a file - must be ProgID
+ if (typeLib.at(0) != '{') {
+ CLSID clsid;
+ if (CLSIDFromProgID(reinterpret_cast<const wchar_t *>(QString(QLatin1String(typeLib)).utf16()), &clsid) != S_OK) {
+ qWarning("dumpcpp: '%s' is not a type library and not a registered ProgID", typeLib.constData());
+ return -2;
+ }
+ QUuid uuid(clsid);
+ typeLib = uuid.toString().toLatin1();
+ isObject = true;
+ }
+
+ // check if CLSID
+ if (!isObject) {
+ QVariant test = settings.value(QLatin1String("/CLSID/") +
+ QString::fromLatin1(typeLib.constData()) + QLatin1String("/."));
+ isObject = test.isValid();
+ }
+
+ // search typelib ID for CLSID
+ if (isObject)
+ typeLib = settings.value(QLatin1String("/CLSID/") +
+ QString::fromLatin1(typeLib.constData()) + QLatin1String("/Typelib/.")).toByteArray();
+
+ // interpret input as type library ID
+ QString key = QLatin1String("/TypeLib/") + QLatin1String(typeLib);
+ settings.beginGroup(key);
+ QStringList versions = settings.childGroups();
+ QStringList codes;
+ if (versions.count()) {
+ settings.beginGroup(QLatin1String("/") + versions.last());
+ codes = settings.childGroups();
+ key += QLatin1String("/") + versions.last();
+ settings.endGroup();
+ }
+ settings.endGroup();
+
+ for (int c = 0; c < codes.count(); ++c) {
+ typeLib = settings.value(key + QLatin1String("/") + codes.at(c) + QLatin1String("/win32/.")).toByteArray();
+ if (QFile::exists(QString::fromLatin1(typeLib.constData()))) {
+ break;
+ }
+ }
+ }
+
+ if (!QFile::exists(QString::fromLatin1(typeLib.constData()))) {
+ qWarning("dumpcpp: type library '%s' not found", typeLib.constData());
+ return -2;
+ }
+
+ if (!generateTypeLibrary(typeLib, outname, (ObjectCategory)category)) {
+ qWarning("dumpcpp: error processing type library '%s'", typeLib.constData());
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tools/activeqt/dumpdoc/dumpdoc.pro b/tools/activeqt/dumpdoc/dumpdoc.pro
new file mode 100644
index 0000000000..3c93525708
--- /dev/null
+++ b/tools/activeqt/dumpdoc/dumpdoc.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+
+CONFIG += console qaxcontainer
+
+SOURCES += main.cpp
diff --git a/tools/activeqt/dumpdoc/main.cpp b/tools/activeqt/dumpdoc/main.cpp
new file mode 100644
index 0000000000..87b9540fb3
--- /dev/null
+++ b/tools/activeqt/dumpdoc/main.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QAxObject>
+#include <QFile>
+#include <QTextStream>
+#include <qt_windows.h>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ CoInitialize(0);
+
+ enum State {
+ Default = 0,
+ OutOption
+ } state;
+ state = Default;
+
+ QByteArray outname;
+ QByteArray object;
+
+ for (int a = 1; a < argc; ++a) {
+ QByteArray arg(argv[a]);
+ const char first = arg[0];
+ switch(state) {
+ case Default:
+ if (first == '-' || first == '/') {
+ arg = arg.mid(1);
+ arg.toLower();
+ if (arg == "o")
+ state = OutOption;
+ else if (arg == "v") {
+ qWarning("dumpdoc: Version 1.0");
+ return 0;
+ } else if (arg == "h") {
+ qWarning("dumpdoc Usage:\n\tdumpdoc object [-o <file>]"
+ " \n\tobject : object[/subobject]*"
+ " \n\tsubobject: property\n"
+ " \nexample:\n\tdumpdoc Outlook.Application/Session/CurrentUser -o outlook.html");
+ return 0;
+ }
+ } else {
+ object = arg;
+ }
+ break;
+ case OutOption:
+ outname = arg;
+ state = Default;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (object.isEmpty()) {
+ qWarning("dumpdoc: No object name provided.\n"
+ " Use -h for help.");
+ return -1;
+ }
+ QFile outfile;
+ if (!outname.isEmpty()) {
+ outfile.setFileName(QString::fromLatin1(outname.constData()));
+ if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("dumpdoc: Could not open output file '%s'", outname.data());
+ }
+ } else {
+ outfile.open(stdout, QIODevice::WriteOnly);
+ }
+ QTextStream out(&outfile);
+
+ QByteArray subobject = object;
+ int index = subobject.indexOf('/');
+ if (index != -1)
+ subobject = subobject.left(index);
+
+ QAxObject topobject(QString::fromLatin1(subobject.constData()));
+
+ if (topobject.isNull()) {
+ qWarning("dumpdoc: Could not instantiate COM object '%s'", subobject.data());
+ return -2;
+ }
+
+ QAxObject *axobject = &topobject;
+ while (index != -1 && axobject) {
+ index++;
+ subobject = object.mid(index);
+ if (object.indexOf('/', index) != -1) {
+ int oldindex = index;
+ index = object.indexOf('/', index);
+ subobject = object.mid(oldindex, index-oldindex);
+ } else {
+ index = -1;
+ }
+
+ axobject = axobject->querySubObject(subobject);
+ }
+ if (!axobject || axobject->isNull()) {
+ qWarning("dumpdoc: Subobject '%s' does not exist in '%s'", subobject.data(), object.data());
+ return -3;
+ }
+
+ QString docu = axobject->generateDocumentation();
+ out << docu;
+ return 0;
+}
diff --git a/tools/activeqt/testcon/ambientproperties.cpp b/tools/activeqt/testcon/ambientproperties.cpp
new file mode 100644
index 0000000000..8e284d869c
--- /dev/null
+++ b/tools/activeqt/testcon/ambientproperties.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ambientproperties.h"
+
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+
+AmbientProperties::AmbientProperties(QWidget *parent)
+: QDialog(parent), container(0)
+{
+ setupUi(this);
+
+ connect(buttonClose, SIGNAL(clicked()), this, SLOT(close()));
+}
+
+void AmbientProperties::setControl(QWidget *widget)
+{
+ container = widget;
+
+ QColor c = container->palette().color(container->backgroundRole());
+ QPalette p = backSample->palette(); p.setColor(backSample->backgroundRole(), c); backSample->setPalette(p);
+
+ c = container->palette().color(container->foregroundRole());
+ p = foreSample->palette(); p.setColor(foreSample->backgroundRole(), c); foreSample->setPalette(p);
+
+ fontSample->setFont( container->font() );
+ buttonEnabled->setChecked( container->isEnabled() );
+ enabledSample->setEnabled( container->isEnabled() );
+}
+
+void AmbientProperties::on_buttonBackground_clicked()
+{
+ QColor c = QColorDialog::getColor(backSample->palette().color(backSample->backgroundRole()), this);
+ QPalette p = backSample->palette(); p.setColor(backSample->backgroundRole(), c); backSample->setPalette(p);
+ p = container->palette(); p.setColor(container->backgroundRole(), c); container->setPalette(p);
+
+ if (QWorkspace *ws = qobject_cast<QWorkspace*>(container)) {
+ QWidgetList list( ws->windowList() );
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ p = widget->palette(); p.setColor(widget->backgroundRole(), c); widget->setPalette(p);
+ }
+ }
+}
+
+void AmbientProperties::on_buttonForeground_clicked()
+{
+ QColor c = QColorDialog::getColor(foreSample->palette().color(foreSample->backgroundRole()), this);
+ QPalette p = foreSample->palette(); p.setColor(foreSample->backgroundRole(), c); foreSample->setPalette(p);
+ p = container->palette(); p.setColor(container->foregroundRole(), c); container->setPalette(p);
+
+ if (QWorkspace *ws = qobject_cast<QWorkspace*>(container)) {
+ QWidgetList list( ws->windowList() );
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ p = widget->palette(); p.setColor(widget->foregroundRole(), c); widget->setPalette(p);
+ }
+ }
+}
+
+void AmbientProperties::on_buttonFont_clicked()
+{
+ bool ok;
+ QFont f = QFontDialog::getFont( &ok, fontSample->font(), this );
+ if ( !ok )
+ return;
+ fontSample->setFont( f );
+ container->setFont( f );
+
+ if (QWorkspace *ws = qobject_cast<QWorkspace*>(container)) {
+ QWidgetList list( ws->windowList() );
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ widget->setFont( f );
+ }
+ }
+}
+
+void AmbientProperties::on_buttonEnabled_toggled(bool on)
+{
+ enabledSample->setEnabled( on );
+ container->setEnabled( on );
+}
+
+QT_END_NAMESPACE
diff --git a/tools/activeqt/testcon/ambientproperties.h b/tools/activeqt/testcon/ambientproperties.h
new file mode 100644
index 0000000000..fa151589a2
--- /dev/null
+++ b/tools/activeqt/testcon/ambientproperties.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AMBIENTPROPERTIES_H
+#define AMBIENTPROPERTIES_H
+
+#include <QtCore/qglobal.h>
+
+#include "ui_ambientproperties.h"
+
+QT_BEGIN_NAMESPACE
+
+class AmbientProperties : public QDialog, Ui::AmbientProperties
+{
+ Q_OBJECT
+public:
+ AmbientProperties(QWidget *parent);
+
+ void setControl(QWidget *widget);
+
+public slots:
+ void on_buttonBackground_clicked();
+ void on_buttonForeground_clicked();
+ void on_buttonFont_clicked();
+ void on_buttonEnabled_toggled(bool on);
+
+private:
+ QWidget *container;
+};
+
+QT_END_NAMESPACE
+
+#endif // AMBIENTPROPERTIES_H
diff --git a/tools/activeqt/testcon/ambientproperties.ui b/tools/activeqt/testcon/ambientproperties.ui
new file mode 100644
index 0000000000..5c68825705
--- /dev/null
+++ b/tools/activeqt/testcon/ambientproperties.ui
@@ -0,0 +1,299 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>AmbientProperties</class>
+ <widget class="QDialog" name="AmbientProperties" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>185</width>
+ <height>173</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Change Ambient Properties</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="boxProperties" >
+ <property name="title" >
+ <string>&amp;Properties</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="text" >
+ <string>Background:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="TextLabel2" >
+ <property name="text" >
+ <string>Foreground:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="TextLabel3" >
+ <property name="text" >
+ <string>Font:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="TextLabel4" >
+ <property name="text" >
+ <string>Enabled:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QFrame" name="foreSample" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QFrame" name="backSample" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QToolButton" name="buttonBackground" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QToolButton" name="buttonForeground" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QToolButton" name="buttonFont" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QFrame" name="Frame6" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="enabledSample" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>&lt;sample></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="2" >
+ <widget class="QToolButton" name="buttonEnabled" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QFrame" name="fontSample" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="TextLabel6" >
+ <property name="text" >
+ <string>&lt;sample></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>1</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>AmbientProperties</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>141</x>
+ <y>150</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>51</x>
+ <y>141</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/activeqt/testcon/changeproperties.cpp b/tools/activeqt/testcon/changeproperties.cpp
new file mode 100644
index 0000000000..64387cc897
--- /dev/null
+++ b/tools/activeqt/testcon/changeproperties.cpp
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "changeproperties.h"
+
+#include <QtGui>
+#include <qt_windows.h>
+#include <ActiveQt/ActiveQt>
+
+QT_BEGIN_NAMESPACE
+
+ChangeProperties::ChangeProperties(QWidget *parent)
+: QDialog(parent), activex(0)
+{
+ setupUi(this);
+
+ listProperties->setColumnCount(3);
+ listProperties->headerItem()->setText(0, QLatin1String("Name"));
+ listProperties->headerItem()->setText(1, QLatin1String("Type"));
+ listProperties->headerItem()->setText(2, QLatin1String("Value"));
+
+ listEditRequests->setColumnCount(1);
+ listEditRequests->headerItem()->setText(0, QLatin1String("Name"));
+}
+
+void ChangeProperties::setControl(QAxWidget *ax)
+{
+ activex = ax;
+ updateProperties();
+}
+
+void ChangeProperties::on_listProperties_currentItemChanged(QTreeWidgetItem *current)
+{
+ editValue->setEnabled(current != 0);
+ buttonSet->setEnabled(current != 0);
+ valueLabel->setEnabled(current != 0);
+
+ if (!current)
+ return;
+
+ editValue->setText(current->text(2));
+ QString prop = current->text(0);
+ valueLabel->setText(prop + QLatin1String(" ="));
+
+ const QMetaObject *mo = activex->metaObject();
+ const QMetaProperty property = mo->property(mo->indexOfProperty(prop.toLatin1()));
+
+ valueLabel->setEnabled(property.isWritable());
+ editValue->setEnabled(property.isWritable());
+ buttonSet->setEnabled(property.isWritable());
+}
+
+void ChangeProperties::on_buttonSet_clicked()
+{
+ QTreeWidgetItem *item = listProperties->currentItem();
+ if (!item)
+ return;
+
+ QString prop = item->text(0);
+ QVariant value = activex->property(prop.toLatin1());
+ QVariant::Type type = value.type();
+ if (!value.isValid()) {
+ const QMetaObject *mo = activex->metaObject();
+ const QMetaProperty property = mo->property(mo->indexOfProperty(prop.toLatin1()));
+ type = QVariant::nameToType(property.typeName());
+ }
+ switch (type) {
+ case QVariant::Color:
+ {
+ QColor col;
+ col.setNamedColor(editValue->text());
+ if (col.isValid()) {
+ value = qVariantFromValue(col);
+ } else {
+ QMessageBox::warning(this, tr("Can't parse input"),
+ QString(tr("Failed to create a color from %1\n"
+ "The string has to be a valid color name (e.g. 'red')\n"
+ "or a RGB triple of format '#rrggbb'."
+ ).arg(editValue->text())));
+ }
+ }
+ break;
+ case QVariant::Font:
+ {
+ QFont fnt;
+ if (fnt.fromString(editValue->text())) {
+ value = qVariantFromValue(fnt);
+ } else {
+ QMessageBox::warning(this, tr("Can't parse input"),
+ (tr("Failed to create a font from %1\n"
+ "The string has to have a format family,<point size> or\n"
+ "family,pointsize,stylehint,weight,italic,underline,strikeout,fixedpitch,rawmode."
+ ).arg(editValue->text())));
+ }
+ }
+ break;
+ case QVariant::Pixmap:
+ {
+ QString fileName = editValue->text();
+ if (fileName.isEmpty())
+ fileName = QFileDialog::getOpenFileName(this);
+ QPixmap pm(fileName);
+ if (pm.isNull())
+ return;
+
+ value = qVariantFromValue(pm);
+ }
+ break;
+ case QVariant::Bool:
+ {
+ QString txt = editValue->text().toLower();
+ value = QVariant(txt != QLatin1String("0") && txt != QLatin1String("false"));
+ }
+ break;
+ case QVariant::List:
+ {
+ QStringList txtList = editValue->text().split(QRegExp(QLatin1String("[,;]")));
+ QList<QVariant> varList;
+ for (int i = 0; i < txtList.count(); ++i) {
+ QVariant svar(txtList.at(i));
+ QString str = svar.toString();
+ str = str.trimmed();
+ bool ok;
+ int n = str.toInt(&ok);
+ if (ok) {
+ varList << n;
+ continue;
+ }
+ double d = str.toDouble(&ok);
+ if (ok) {
+ varList << d;
+ continue;
+ }
+ varList << str;
+ }
+ value = varList;
+ }
+ break;
+
+ default:
+ value = editValue->text();
+ break;
+ }
+
+ Q_ASSERT(activex->setProperty(prop.toLatin1(), value));
+ updateProperties();
+ listProperties->setCurrentItem(listProperties->findItems(prop, Qt::MatchExactly).at(0));
+}
+
+void ChangeProperties::on_listEditRequests_itemChanged(QTreeWidgetItem *item)
+{
+ if (!item)
+ return;
+
+ QString property = item->text(0);
+ activex->setPropertyWritable(property.toLatin1(), item->checkState(0) == Qt::Checked);
+}
+
+
+void ChangeProperties::updateProperties()
+{
+ bool hasControl = activex && !activex->isNull();
+ tabWidget->setEnabled(hasControl);
+
+ listProperties->clear();
+ listEditRequests->clear();
+ if (hasControl) {
+ const QMetaObject *mo = activex->metaObject();
+ const int numprops = mo->propertyCount();
+ for (int i = mo->propertyOffset(); i < numprops; ++i) {
+ const QMetaProperty property = mo->property(i);
+ QTreeWidgetItem *item = new QTreeWidgetItem(listProperties);
+ item->setText(0, QString::fromLatin1(property.name()));
+ item->setText(1, QString::fromLatin1(property.typeName()));
+ if (!property.isDesignable()) {
+ item->setTextColor(0, Qt::gray);
+ item->setTextColor(1, Qt::gray);
+ item->setTextColor(2, Qt::gray);
+ }
+ QVariant var = activex->property(property.name());
+
+ switch (var.type()) {
+ case QVariant::Color:
+ {
+ QColor col = qvariant_cast<QColor>(var);
+ item->setText(2, col.name());
+ }
+ break;
+ case QVariant::Font:
+ {
+ QFont fnt = qvariant_cast<QFont>(var);
+ item->setText(2, fnt.toString());
+ }
+ break;
+ case QVariant::Bool:
+ {
+ item->setText(2, var.toBool() ? QLatin1String("true") : QLatin1String("false"));
+ }
+ break;
+ case QVariant::Pixmap:
+ {
+ QPixmap pm = qvariant_cast<QPixmap>(var);
+ item->setIcon(2, pm);
+ }
+ break;
+ case QVariant::List:
+ {
+ QList<QVariant> varList = var.toList();
+ QStringList strList;
+ for (int i = 0; i < varList.count(); ++i) {
+ QVariant var = varList.at(i);
+ strList << var.toString();
+ }
+ item->setText(2, strList.join(QLatin1String(", ")));
+ }
+ break;
+ case QVariant::Int:
+ if (property.isEnumType()) {
+ const QMetaEnum enumerator = mo->enumerator(mo->indexOfEnumerator(property.typeName()));
+ item->setText(2, QString::fromLatin1(enumerator.valueToKey(var.toInt())));
+ break;
+ }
+ //FALLTHROUGH
+ default:
+ item->setText(2, var.toString());
+ break;
+ }
+
+ bool requesting = false;
+#if 0
+ {
+ void *argv[] = { &requesting };
+ activex->qt_metacall(QMetaObject::Call(0x10000000) /*RequestingEdit*/, i, argv);
+ }
+#endif
+ if (requesting) {
+ QTreeWidgetItem *check = new QTreeWidgetItem(listEditRequests);
+ check->setText(0, QString::fromLatin1(property.name()));
+ check->setCheckState(0, activex->propertyWritable(property.name()) ? Qt::Checked : Qt::Unchecked);
+ }
+ }
+ listProperties->setCurrentItem(listProperties->topLevelItem(0));
+ } else {
+ editValue->clear();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/activeqt/testcon/changeproperties.h b/tools/activeqt/testcon/changeproperties.h
new file mode 100644
index 0000000000..5bb053ad7e
--- /dev/null
+++ b/tools/activeqt/testcon/changeproperties.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CHANGEPROPERTIES_H
+#define CHANGEPROPERTIES_H
+
+#include <QtCore/qglobal.h>
+#include "ui_changeproperties.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAxWidget;
+
+class ChangeProperties : public QDialog, Ui::ChangeProperties
+{
+ Q_OBJECT
+public:
+ ChangeProperties(QWidget *parent);
+
+ void setControl(QAxWidget *control);
+
+public slots:
+ void updateProperties();
+
+protected slots:
+ void on_listProperties_currentItemChanged(QTreeWidgetItem *current);
+ void on_listEditRequests_itemChanged(QTreeWidgetItem *item);
+ void on_buttonSet_clicked();
+
+private:
+ QAxWidget *activex;
+};
+
+QT_END_NAMESPACE
+
+#endif // CHANGEPROPERTIES_H
diff --git a/tools/activeqt/testcon/changeproperties.ui b/tools/activeqt/testcon/changeproperties.ui
new file mode 100644
index 0000000000..2714b991f9
--- /dev/null
+++ b/tools/activeqt/testcon/changeproperties.ui
@@ -0,0 +1,211 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>ChangeProperties</class>
+ <widget class="QDialog" name="ChangeProperties" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>728</width>
+ <height>584</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Change Control Properties</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget" >
+ <widget class="QWidget" name="propertiesTab" >
+ <attribute name="title" >
+ <string>&amp;Properties</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listProperties" >
+ <property name="rootIsDecorated" >
+ <bool>false</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Property</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Type</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="valueLabel" >
+ <property name="text" >
+ <string>Property &amp;Value:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>editValue</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="editValue" />
+ </item>
+ <item>
+ <widget class="QToolButton" name="buttonSet" >
+ <property name="text" >
+ <string>&amp;Set</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="requestTab" >
+ <attribute name="title" >
+ <string>Property Edit &amp;Requests</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listEditRequests" >
+ <column>
+ <property name="text" >
+ <string>Property</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>1</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>ChangeProperties</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>669</x>
+ <y>558</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>566</x>
+ <y>551</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/activeqt/testcon/controlinfo.cpp b/tools/activeqt/testcon/controlinfo.cpp
new file mode 100644
index 0000000000..8c76448c37
--- /dev/null
+++ b/tools/activeqt/testcon/controlinfo.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "controlinfo.h"
+
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+
+ControlInfo::ControlInfo(QWidget *parent)
+ : QDialog(parent)
+{
+ setupUi(this);
+
+ listInfo->setColumnCount(2);
+ listInfo->headerItem()->setText(0, tr("Item"));
+ listInfo->headerItem()->setText(1, tr("Details"));
+}
+
+void ControlInfo::setControl(QWidget *activex)
+{
+ listInfo->clear();
+
+ const QMetaObject *mo = activex->metaObject();
+ QTreeWidgetItem *group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Class Info"));
+ group->setText(1, QString::number(mo->classInfoCount()));
+
+ QTreeWidgetItem *item = 0;
+ int i;
+ int count;
+ for (i = mo->classInfoOffset(); i < mo->classInfoCount(); ++i) {
+ const QMetaClassInfo info = mo->classInfo(i);
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(info.name()));
+ item->setText(1, QString::fromLatin1(info.value()));
+ }
+ group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Signals"));
+
+ count = 0;
+ for (i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Signal) {
+ ++count;
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(method.signature()));
+ }
+ }
+ group->setText(1, QString::number(count));
+
+ group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Slots"));
+
+ count = 0;
+ for (i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Slot) {
+ ++count;
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(method.signature()));
+ }
+ }
+ group->setText(1, QString::number(count));
+
+ group = new QTreeWidgetItem(listInfo);
+ group->setText(0, tr("Properties"));
+
+ count = 0;
+ for (i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
+ ++count;
+ const QMetaProperty property = mo->property(i);
+ item = new QTreeWidgetItem(group);
+ item->setText(0, QString::fromLatin1(property.name()));
+ item->setText(1, QString::fromLatin1(property.typeName()));
+ if (!property.isDesignable()) {
+ item->setTextColor(0, Qt::gray);
+ item->setTextColor(1, Qt::gray);
+ }
+ }
+ group->setText(1, QString::number(count));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/activeqt/testcon/controlinfo.h b/tools/activeqt/testcon/controlinfo.h
new file mode 100644
index 0000000000..11235bb75f
--- /dev/null
+++ b/tools/activeqt/testcon/controlinfo.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONTROLINFO_H
+#define CONTROLINFO_H
+
+#include <QtCore/qglobal.h>
+#include "ui_controlinfo.h"
+
+QT_BEGIN_NAMESPACE
+
+class ControlInfo : public QDialog, Ui::ControlInfo
+{
+ Q_OBJECT
+public:
+ ControlInfo(QWidget *parent);
+
+ void setControl(QWidget *activex);
+};
+
+QT_END_NAMESPACE
+
+#endif // CONTROLINFO_H
diff --git a/tools/activeqt/testcon/controlinfo.ui b/tools/activeqt/testcon/controlinfo.ui
new file mode 100644
index 0000000000..3aeaf58cba
--- /dev/null
+++ b/tools/activeqt/testcon/controlinfo.ui
@@ -0,0 +1,134 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>ControlInfo</class>
+ <widget class="QDialog" name="ControlInfo" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Control Details</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listInfo" >
+ <column>
+ <property name="text" >
+ <string>Item</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>1</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>ControlInfo</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>536</x>
+ <y>457</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>428</x>
+ <y>449</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/activeqt/testcon/docuwindow.cpp b/tools/activeqt/testcon/docuwindow.cpp
new file mode 100644
index 0000000000..b0b2d81dd4
--- /dev/null
+++ b/tools/activeqt/testcon/docuwindow.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "docuwindow.h"
+#include <QTextBrowser>
+#include <QTextDocument>
+#include <QToolBar>
+#include <QToolButton>
+#include <QFileDialog>
+#include <QFile>
+#include <QStatusBar>
+#include <QPrinter>
+#include <QPainter>
+#include <QPrintDialog>
+#include <QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+static const char *filesave[] = {
+" 14 14 4 1",
+". c #040404",
+"# c #808304",
+"a c #bfc2bf",
+"b c None",
+"..............",
+".#.aaaaaaaa.a.",
+".#.aaaaaaaa...",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".#.aaaaaaaa.#.",
+".##........##.",
+".############.",
+".##.........#.",
+".##......aa.#.",
+".##......aa.#.",
+".##......aa.#.",
+"b............."
+};
+
+static const char *fileprint[] = {
+" 16 14 6 1",
+". c #000000",
+"# c #848284",
+"a c #c6c3c6",
+"b c #ffff00",
+"c c #ffffff",
+"d c None",
+"ddddd.........dd",
+"dddd.cccccccc.dd",
+"dddd.c.....c.ddd",
+"ddd.cccccccc.ddd",
+"ddd.c.....c....d",
+"dd.cccccccc.a.a.",
+"d..........a.a..",
+".aaaaaaaaaa.a.a.",
+".............aa.",
+".aaaaaa###aa.a.d",
+".aaaaaabbbaa...d",
+".............a.d",
+"d.aaaaaaaaa.a.dd",
+"dd...........ddd"
+};
+
+
+DocuWindow::DocuWindow(const QString& docu, QWidget *parent, QWidget *source)
+ : QMainWindow(parent)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ setWindowTitle(tr("%1 - Documentation").arg(source->windowTitle()));
+
+ browser = new QTextBrowser(this);
+ browser->setHtml(docu);
+
+ setCentralWidget(browser);
+
+ QToolBar *fileTools = new QToolBar(tr("File Operations"), this);
+ fileTools->addAction(QPixmap(filesave), tr("Save File"), this, SLOT(save()));
+ fileTools->addAction(QPixmap(fileprint), tr("Print"), this, SLOT(print()));
+
+ addToolBar(fileTools);
+ statusBar();
+}
+
+void DocuWindow::save()
+{
+ QString filename = QFileDialog::getSaveFileName(this);
+
+ if (filename.isEmpty())
+ return;
+
+ QString text = browser->document()->toHtml();
+ QFile f(filename);
+ if (!f.open(QIODevice::WriteOnly)) {
+ statusBar()->showMessage(tr("Could not write to %1").arg(filename), 2000);
+ return;
+ }
+
+ QTextStream t(&f);
+ t << text;
+ f.close();
+
+ statusBar()->showMessage(tr("File %1 saved").arg(filename), 2000);
+}
+
+void DocuWindow::print()
+{
+ QPrinter printer;
+ if (printer.printerName().isEmpty()) {
+ statusBar()->showMessage(tr("No printer installed"), 2000);
+ return;
+ }
+
+ QPrintDialog printDialog(&printer, this);
+ if (!printDialog.exec()) {
+ statusBar()->showMessage(tr("Printing aborted"), 2000);
+ return;
+ }
+
+ browser->document()->print(&printer);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/activeqt/testcon/docuwindow.h b/tools/activeqt/testcon/docuwindow.h
new file mode 100644
index 0000000000..99d0286a50
--- /dev/null
+++ b/tools/activeqt/testcon/docuwindow.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DOCUWINDOW_H
+#define DOCUWINDOW_H
+
+#include <QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+class QTextBrowser;
+
+class DocuWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ DocuWindow( const QString& docu, QWidget *parent, QWidget *source );
+
+public slots:
+ void save();
+ void print();
+
+private:
+ QTextBrowser *browser;
+};
+
+QT_END_NAMESPACE
+
+#endif // DOCUWINDOW_H
diff --git a/tools/activeqt/testcon/invokemethod.cpp b/tools/activeqt/testcon/invokemethod.cpp
new file mode 100644
index 0000000000..7319adc17c
--- /dev/null
+++ b/tools/activeqt/testcon/invokemethod.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "invokemethod.h"
+
+#include <qt_windows.h>
+#include <ActiveQt/ActiveQt>
+
+QT_BEGIN_NAMESPACE
+
+InvokeMethod::InvokeMethod(QWidget *parent)
+: QDialog(parent), activex(0)
+{
+ setupUi(this);
+
+ listParameters->setColumnCount(3);
+ listParameters->headerItem()->setText(0, tr("Parameter"));
+ listParameters->headerItem()->setText(1, tr("Type"));
+ listParameters->headerItem()->setText(2, tr("Value"));
+}
+
+void InvokeMethod::setControl(QAxBase *ax)
+{
+ activex = ax;
+ bool hasControl = activex && !activex->isNull();
+ labelMethods->setEnabled(hasControl);
+ comboMethods->setEnabled(hasControl);
+ buttonInvoke->setEnabled(hasControl);
+ boxParameters->setEnabled(hasControl);
+
+ comboMethods->clear();
+ listParameters->clear();
+
+ if (!hasControl) {
+ editValue->clear();
+ return;
+ }
+
+ const QMetaObject *mo = activex->metaObject();
+ if (mo->methodCount()) {
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ const QMetaMethod method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Slot)
+ comboMethods->addItem(QString::fromLatin1(method.signature()));
+ }
+ comboMethods->model()->sort(0);
+
+ on_comboMethods_activated(comboMethods->currentText());
+ }
+}
+
+void InvokeMethod::on_buttonInvoke_clicked()
+{
+ if (!activex)
+ return;
+
+ on_buttonSet_clicked();
+ QString method = comboMethods->currentText();
+ QList<QVariant> vars;
+
+ int itemCount = listParameters->topLevelItemCount();
+ for (int i = 0; i < itemCount; ++i) {
+ QTreeWidgetItem *parameter = listParameters->topLevelItem(i);
+ vars << parameter->text(2);
+ }
+ QVariant result = activex->dynamicCall(method.toLatin1(), vars);
+
+ int v = 0;
+ for (int i = 0; i < itemCount; ++i) {
+ QTreeWidgetItem *parameter = listParameters->topLevelItem(i);
+ parameter->setText(2, vars[v++].toString());
+ }
+
+ QString resString = result.toString();
+ QString resType = QString::fromLatin1(result.typeName());
+ editReturn->setText(resType + QLatin1String(" ") + resString);
+}
+
+void InvokeMethod::on_comboMethods_activated(const QString &method)
+{
+ if (!activex)
+ return;
+ listParameters->clear();
+
+ const QMetaObject *mo = activex->metaObject();
+ const QMetaMethod slot = mo->method(mo->indexOfSlot(method.toLatin1()));
+ QString signature = QString::fromLatin1(slot.signature());
+ signature = signature.mid(signature.indexOf(QLatin1Char('(')) + 1);
+ signature.truncate(signature.length()-1);
+
+ QList<QByteArray> pnames = slot.parameterNames();
+ QList<QByteArray> ptypes = slot.parameterTypes();
+
+ for (int p = 0; p < ptypes.count(); ++p) {
+ QString ptype(QString::fromLatin1(ptypes.at(p)));
+ if (ptype.isEmpty())
+ continue;
+ QString pname(QString::fromLatin1(pnames.at(p).constData()));
+ if (pname.isEmpty())
+ pname = QString::fromLatin1("<unnamed %1>").arg(p);
+ QTreeWidgetItem *item = new QTreeWidgetItem(listParameters);
+ item->setText(0, pname);
+ item->setText(1, ptype);
+ }
+
+ if (listParameters->topLevelItemCount())
+ listParameters->setCurrentItem(listParameters->topLevelItem(0));
+ editReturn->setText(QString::fromLatin1(slot.typeName()));
+}
+
+void InvokeMethod::on_listParameters_currentItemChanged(QTreeWidgetItem *item)
+{
+ if (!activex)
+ return;
+ editValue->setEnabled(item != 0);
+ buttonSet->setEnabled(item != 0);
+ if (!item)
+ return;
+ editValue->setText(item->text(2));
+}
+
+void InvokeMethod::on_buttonSet_clicked()
+{
+ if (!activex)
+ return;
+ QTreeWidgetItem *item = listParameters->currentItem();
+ if (!item)
+ return;
+ item->setText(2, editValue->text());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/activeqt/testcon/invokemethod.h b/tools/activeqt/testcon/invokemethod.h
new file mode 100644
index 0000000000..c374bad5f7
--- /dev/null
+++ b/tools/activeqt/testcon/invokemethod.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INVOKEMETHOD_H
+#define INVOKEMETHOD_H
+
+#include <QtCore/qglobal.h>
+#include "ui_invokemethod.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAxBase;
+
+class InvokeMethod : public QDialog, Ui::InvokeMethod
+{
+ Q_OBJECT
+public:
+ InvokeMethod(QWidget *parent);
+
+ void setControl(QAxBase *ax);
+
+protected slots:
+ void on_buttonInvoke_clicked();
+ void on_buttonSet_clicked();
+
+ void on_comboMethods_activated(const QString &method);
+ void on_listParameters_currentItemChanged(QTreeWidgetItem *item);
+
+private:
+ QAxBase *activex;
+};
+
+QT_END_NAMESPACE
+
+#endif // INVOKEMETHOD_H
diff --git a/tools/activeqt/testcon/invokemethod.ui b/tools/activeqt/testcon/invokemethod.ui
new file mode 100644
index 0000000000..c92ab0c32f
--- /dev/null
+++ b/tools/activeqt/testcon/invokemethod.ui
@@ -0,0 +1,270 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>InvokeMethod</class>
+ <widget class="QDialog" name="InvokeMethod" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>503</width>
+ <height>416</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Invoke Methods</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="1" column="0" colspan="2" >
+ <widget class="QGroupBox" name="boxParameters" >
+ <property name="title" >
+ <string>&amp;Parameter List</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" colspan="3" >
+ <widget class="QTreeWidget" name="listParameters" >
+ <property name="rootIsDecorated" >
+ <bool>false</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Parameter</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Type</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QToolButton" name="buttonSet" >
+ <property name="text" >
+ <string>&amp;Set</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="editValue" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="TextLabel3" >
+ <property name="text" >
+ <string>Parameter &amp;Value:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>editValue</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2" >
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="editReturn" >
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QComboBox" name="comboMethods" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable" >
+ <bool>true</bool>
+ </property>
+ <property name="insertPolicy" >
+ <enum>QComboBox::NoInsert</enum>
+ </property>
+ <property name="autoCompletion" >
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="labelMethods" >
+ <property name="text" >
+ <string>&amp;Method Name:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>comboMethods</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Preferred</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="text" >
+ <string>Returned Value:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" >
+ <widget class="QPushButton" name="buttonInvoke" >
+ <property name="text" >
+ <string>&amp;Invoke</string>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>111</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>361</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QPushButton" name="buttonClose" >
+ <property name="text" >
+ <string>C&amp;lose</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>InvokeMethod</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>453</x>
+ <y>396</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>327</x>
+ <y>384</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/activeqt/testcon/main.cpp b/tools/activeqt/testcon/main.cpp
new file mode 100644
index 0000000000..1800fcbf42
--- /dev/null
+++ b/tools/activeqt/testcon/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QAxFactory>
+
+QAXFACTORY_DEFAULT(MainWindow,
+ QLatin1String("{5f5ce700-48a8-47b1-9b06-3b7f79e41d7c}"),
+ QLatin1String("{3fc86f5f-8b15-4428-8f6b-482bae91f1ae}"),
+ QLatin1String("{02a268cd-24b4-4fd9-88ff-b01b683ef39d}"),
+ QLatin1String("{4a43e44d-9d1d-47e5-a1e5-58fe6f7be0a4}"),
+ QLatin1String("{16ee5998-77d2-412f-ad91-8596e29f123f}"))
+
+QT_USE_NAMESPACE
+
+int main( int argc, char **argv )
+{
+ QApplication app( argc, argv );
+
+ MainWindow mw;
+ mw.show();
+
+ return app.exec();;
+}
diff --git a/tools/activeqt/testcon/mainwindow.cpp b/tools/activeqt/testcon/mainwindow.cpp
new file mode 100644
index 0000000000..15f9d4c87b
--- /dev/null
+++ b/tools/activeqt/testcon/mainwindow.cpp
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "changeproperties.h"
+#include "invokemethod.h"
+#include "ambientproperties.h"
+#include "controlinfo.h"
+#include "docuwindow.h"
+
+#include <QtGui>
+#include <qt_windows.h>
+#include <ActiveQt/ActiveQt>
+
+QT_BEGIN_NAMESPACE
+
+QAxObject *ax_mainWindow = 0;
+
+static QTextEdit *debuglog = 0;
+
+static void redirectDebugOutput(QtMsgType type, const char*msg)
+{
+ Q_UNUSED(type);
+ debuglog->append(QLatin1String(msg));
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+{
+ setupUi(this);
+ setObjectName(QLatin1String("MainWindow"));
+
+ QAxScriptManager::registerEngine(QLatin1String("PerlScript"), QLatin1String(".pl"));
+ QAxScriptManager::registerEngine(QLatin1String("Python"), QLatin1String(".py"));
+
+ dlgInvoke = 0;
+ dlgProperties = 0;
+ dlgAmbient = 0;
+ scripts = 0;
+ debuglog = logDebug;
+ oldDebugHandler = qInstallMsgHandler(redirectDebugOutput);
+ QHBoxLayout *layout = new QHBoxLayout(Workbase);
+ workspace = new QWorkspace(Workbase);
+ layout->addWidget(workspace);
+ layout->setMargin(0);
+
+ connect(workspace, SIGNAL(windowActivated(QWidget*)), this, SLOT(updateGUI()));
+ connect(actionFileExit, SIGNAL(triggered()), qApp, SLOT(quit()));
+}
+
+MainWindow::~MainWindow()
+{
+ qInstallMsgHandler(oldDebugHandler);
+ debuglog = 0;
+}
+
+
+void MainWindow::on_actionFileNew_triggered()
+{
+ QAxSelect select(this);
+ if (select.exec()) {
+ QAxWidget *container = new QAxWidget(workspace);
+ container->setAttribute(Qt::WA_DeleteOnClose);
+ container->setControl(select.clsid());
+ container->setObjectName(container->windowTitle());
+ workspace->addWindow(container);
+ container->show();
+ }
+ updateGUI();
+}
+
+void MainWindow::on_actionFileLoad_triggered()
+{
+ QString fname = QFileDialog::getOpenFileName(this, tr("Load"), QString(), QLatin1String("*.qax"));
+ if (fname.isEmpty())
+ return;
+
+ QFile file(fname);
+ if (!file.open(QIODevice::ReadOnly)) {
+ QMessageBox::information(this, tr("Error Loading File"), tr("The file could not be opened for reading.\n%1").arg(fname));
+ return;
+ }
+
+ QAxWidget *container = new QAxWidget(workspace);
+ workspace->addWindow(container);
+
+ QDataStream d(&file);
+ d >> *container;
+
+ container->setObjectName(container->windowTitle());
+ container->show();
+
+ updateGUI();
+}
+
+void MainWindow::on_actionFileSave_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QString fname = QFileDialog::getSaveFileName(this, tr("Save"), QString(), QLatin1String("*.qax"));
+ if (fname.isEmpty())
+ return;
+
+ QFile file(fname);
+ if (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox::information(this, tr("Error Saving File"), tr("The file could not be opened for writing.\n%1").arg(fname));
+ return;
+ }
+ QDataStream d(&file);
+ d << *container;
+}
+
+
+void MainWindow::on_actionContainerSet_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QAxSelect select(this);
+ if (select.exec())
+ container->setControl(select.clsid());
+ updateGUI();
+}
+
+void MainWindow::on_actionContainerClear_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (container)
+ container->clear();
+ updateGUI();
+}
+
+void MainWindow::on_actionContainerProperties_triggered()
+{
+ if (!dlgAmbient) {
+ dlgAmbient = new AmbientProperties(this);
+ dlgAmbient->setControl(workspace);
+ }
+ dlgAmbient->show();
+}
+
+
+void MainWindow::on_actionControlInfo_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ ControlInfo info(this);
+ info.setControl(container);
+ info.exec();
+}
+
+void MainWindow::on_actionControlProperties_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ if (!dlgProperties) {
+ dlgProperties = new ChangeProperties(this);
+ connect(container, SIGNAL(propertyChanged(const QString&)), dlgProperties, SLOT(updateProperties()));
+ }
+ dlgProperties->setControl(container);
+ dlgProperties->show();
+}
+
+void MainWindow::on_actionControlMethods_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ if (!dlgInvoke)
+ dlgInvoke = new InvokeMethod(this);
+ dlgInvoke->setControl(container);
+ dlgInvoke->show();
+}
+
+void MainWindow::on_VerbMenu_aboutToShow()
+{
+ VerbMenu->clear();
+
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QStringList verbs = container->verbs();
+ for (int i = 0; i < verbs.count(); ++i) {
+ VerbMenu->addAction(verbs.at(i));
+ }
+
+ if (!verbs.count()) { // no verbs?
+ VerbMenu->addAction(tr("-- Object does not support any verbs --"))->setEnabled(false);
+ }
+}
+
+void MainWindow::on_VerbMenu_triggered(QAction *action)
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ container->doVerb(action->text());
+}
+
+void MainWindow::on_actionControlDocumentation_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QString docu = container->generateDocumentation();
+ if (docu.isEmpty())
+ return;
+
+ DocuWindow *docwindow = new DocuWindow(docu, workspace, container);
+ workspace->addWindow(docwindow);
+ docwindow->show();
+}
+
+
+void MainWindow::on_actionControlPixmap_triggered()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QPixmap pm = QPixmap::grabWidget(container);
+
+ QLabel *label = new QLabel(workspace);
+ label->setAttribute(Qt::WA_DeleteOnClose);
+ label->setPixmap(pm);
+ label->setWindowTitle(tr("%1 - Pixmap").arg(container->windowTitle()));
+
+ workspace->addWindow(label);
+ label->show();
+}
+
+void MainWindow::on_actionScriptingRun_triggered()
+{
+#ifndef QT_NO_QAXSCRIPT
+ if (!scripts)
+ return;
+
+ // If we have only one script loaded we can use the cool dialog
+ QStringList scriptList = scripts->scriptNames();
+ if (scriptList.count() == 1) {
+ InvokeMethod scriptInvoke(this);
+ scriptInvoke.setWindowTitle(tr("Execute Script Function"));
+ scriptInvoke.setControl(scripts->script(scriptList[0])->scriptEngine());
+ scriptInvoke.exec();
+ return;
+ }
+
+ bool ok = false;
+ QStringList macroList = scripts->functions(QAxScript::FunctionNames);
+ QString macro = QInputDialog::getItem(this, tr("Select Macro"), tr("Macro:"), macroList, 0, true, &ok);
+
+ if (!ok)
+ return;
+
+ QVariant result = scripts->call(macro);
+ if (result.isValid())
+ logMacros->append(tr("Return value of %1: %2").arg(macro).arg(result.toString()));
+#endif
+}
+
+void MainWindow::on_actionScriptingLoad_triggered()
+{
+#ifndef QT_NO_QAXSCRIPT
+ QString file = QFileDialog::getOpenFileName(this, tr("Open Script"), QString(), QAxScriptManager::scriptFileFilter());
+
+ if (file.isEmpty())
+ return;
+
+ if (!scripts) {
+ scripts = new QAxScriptManager(this);
+ scripts->addObject(this);
+ }
+
+ QWidgetList widgets = workspace->windowList();
+ QWidgetList::Iterator it(widgets.begin());
+ while (it != widgets.end()) {
+ QAxBase *ax = (QAxBase*)(*it)->qt_metacast("QAxBase");
+ ++it;
+ if (!ax)
+ continue;
+ scripts->addObject(ax);
+ }
+
+ QAxScript *script = scripts->load(file, file);
+ if (script) {
+ connect(script, SIGNAL(error(int, const QString&, int, const QString&)),
+ this, SLOT(logMacro(int, const QString&, int, const QString&)));
+ actionScriptingRun->setEnabled(true);
+ }
+#else
+ QMessageBox::information(this, tr("Function not available"),
+ tr("QAxScript functionality is not available with this compiler."));
+#endif
+}
+
+void MainWindow::updateGUI()
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+
+ bool hasControl = container && !container->isNull();
+ actionFileNew->setEnabled(true);
+ actionFileLoad->setEnabled(true);
+ actionFileSave->setEnabled(hasControl);
+ actionContainerSet->setEnabled(container != 0);
+ actionContainerClear->setEnabled(hasControl);
+ actionControlProperties->setEnabled(hasControl);
+ actionControlMethods->setEnabled(hasControl);
+ actionControlInfo->setEnabled(hasControl);
+ actionControlDocumentation->setEnabled(hasControl);
+ actionControlPixmap->setEnabled(hasControl);
+ VerbMenu->setEnabled(hasControl);
+ if (dlgInvoke)
+ dlgInvoke->setControl(hasControl ? container : 0);
+ if (dlgProperties)
+ dlgProperties->setControl(hasControl ? container : 0);
+
+ QWidgetList list = workspace->windowList();
+ QWidgetList::Iterator it = list.begin();
+ while (it != list.end()) {
+ QWidget *container = *it;
+
+ QAxWidget *ax = qobject_cast<QAxWidget*>(container);
+ if (ax) {
+ container->disconnect(SIGNAL(signal(const QString&, int, void*)));
+ if (actionLogSignals->isChecked())
+ connect(container, SIGNAL(signal(const QString&, int, void*)), this, SLOT(logSignal(const QString&, int, void*)));
+
+ container->disconnect(SIGNAL(exception(int,const QString&,const QString&,const QString&)));
+ connect(container, SIGNAL(exception(int,const QString&,const QString&,const QString&)),
+ this, SLOT(logException(int,const QString&,const QString&,const QString&)));
+
+ container->disconnect(SIGNAL(propertyChanged(const QString&)));
+ if (actionLogProperties->isChecked())
+ connect(container, SIGNAL(propertyChanged(const QString&)), this, SLOT(logPropertyChanged(const QString&)));
+ container->blockSignals(actionFreezeEvents->isChecked());
+ }
+
+ ++it;
+ }
+}
+
+
+void MainWindow::logPropertyChanged(const QString &prop)
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QVariant var = container->property(prop.toLatin1());
+ logProperties->append(tr("%1: Property Change: %2 - { %3 }").arg(container->windowTitle(), prop, var.toString()));
+}
+
+void MainWindow::logSignal(const QString &signal, int argc, void *argv)
+{
+ QAxWidget *container = qobject_cast<QAxWidget*>(workspace->activeWindow());
+ if (!container)
+ return;
+
+ QString paramlist;
+ VARIANT *params = (VARIANT*)argv;
+ for (int a = argc-1; a >= 0; --a) {
+ if (a == argc-1)
+ paramlist = QLatin1String(" - {");
+ QVariant qvar = VARIANTToQVariant(params[a], 0);
+ paramlist += QLatin1String(" ") + qvar.toString();
+ if (a > 0)
+ paramlist += QLatin1String(",");
+ else
+ paramlist += QLatin1String(" ");
+ }
+ if (argc)
+ paramlist += QLatin1String("}");
+ logSignals->append(container->windowTitle() + QLatin1String(": ") + signal + paramlist);
+}
+
+void MainWindow::logException(int code, const QString&source, const QString&desc, const QString&help)
+{
+ Q_UNUSED(desc);
+ QAxWidget *container = qobject_cast<QAxWidget*>(sender());
+ if (!container)
+ return;
+
+ QString str = tr("%1: Exception code %2 thrown by %3").
+ arg(container->windowTitle()).arg(code).arg(source);
+ logDebug->append(str);
+ logDebug->append(tr("\tDescription: %1").arg(desc));
+
+ if (!help.isEmpty())
+ logDebug->append(tr("\tHelp available at %1").arg(help));
+ else
+ logDebug->append(tr("\tNo help available."));
+}
+
+void MainWindow::logMacro(int code, const QString &description, int sourcePosition, const QString &sourceText)
+{
+ /* FIXME This needs to be rewritten to not use string concatentation, such
+ * that it can be translated in a sane way. */
+ QString message = tr("Script: ");
+ if (code)
+ message += QString::number(code) + QLatin1String(" ");
+ message += QLatin1String("'") + description + QLatin1String("'");
+ if (sourcePosition)
+ message += tr(" at position ") + QString::number(sourcePosition);
+ if (!sourceText.isEmpty())
+ message += QLatin1String(" '") + sourceText + QLatin1String("'");
+
+ logMacros->append(message);
+}
diff --git a/tools/activeqt/testcon/mainwindow.h b/tools/activeqt/testcon/mainwindow.h
new file mode 100644
index 0000000000..abab47eef2
--- /dev/null
+++ b/tools/activeqt/testcon/mainwindow.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "ui_mainwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+class InvokeMethod;
+class ChangeProperties;
+class AmbientProperties;
+class QAxScriptManager;
+
+class QWorkspace;
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+
+class MainWindow : public QMainWindow, public Ui::MainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+protected slots:
+ void on_actionFileNew_triggered();
+ void on_actionFileLoad_triggered();
+ void on_actionFileSave_triggered();
+
+ void on_actionContainerSet_triggered();
+ void on_actionContainerClear_triggered();
+ void on_actionContainerProperties_triggered();
+
+ void on_actionControlInfo_triggered();
+ void on_actionControlDocumentation_triggered();
+ void on_actionControlPixmap_triggered();
+ void on_actionControlProperties_triggered();
+ void on_actionControlMethods_triggered();
+ void on_VerbMenu_aboutToShow();
+
+ void on_actionScriptingLoad_triggered();
+ void on_actionScriptingRun_triggered();
+
+private:
+ InvokeMethod *dlgInvoke;
+ ChangeProperties *dlgProperties;
+ AmbientProperties *dlgAmbient;
+ QAxScriptManager *scripts;
+ QWorkspace *workspace;
+
+ QtMsgHandler oldDebugHandler;
+
+private slots:
+ void updateGUI();
+ void logPropertyChanged(const QString &prop);
+ void logSignal(const QString &signal, int argc, void *argv);
+ void logException(int code, const QString&source, const QString&desc, const QString&help);
+ void logMacro(int code, const QString &description, int sourcePosition, const QString &sourceText);
+
+ void on_VerbMenu_triggered(QAction *action);
+};
+
+#endif // MAINWINDOW_H
diff --git a/tools/activeqt/testcon/mainwindow.ui b/tools/activeqt/testcon/mainwindow.ui
new file mode 100644
index 0000000000..96fe7bd1f6
--- /dev/null
+++ b/tools/activeqt/testcon/mainwindow.ui
@@ -0,0 +1,682 @@
+<ui version="4.0" stdsetdef="1" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="objectName" >
+ <string notr="true" >MainWindow</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>929</width>
+ <height>620</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>ActiveX Control Test Container</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="Frame" >
+ <property name="objectName" >
+ <string notr="true" >Frame</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>Sunken</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSplitter" name="Splitter2" >
+ <property name="objectName" >
+ <string notr="true" >Splitter2</string>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <widget class="QFrame" name="Workbase" >
+ <property name="objectName" >
+ <string notr="true" >Workbase</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>Raised</enum>
+ </property>
+ </widget>
+ <widget class="QTabWidget" name="TabWidget2" >
+ <property name="objectName" >
+ <string notr="true" >TabWidget2</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget" name="logSignalsTab" >
+ <property name="objectName" >
+ <string notr="true" >logSignalsTab</string>
+ </property>
+ <attribute name="title" >
+ <string>Signal log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logSignals" >
+ <property name="objectName" >
+ <string notr="true" >logSignals</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="logPropertiesTab" >
+ <property name="objectName" >
+ <string notr="true" >logPropertiesTab</string>
+ </property>
+ <attribute name="title" >
+ <string>Property log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logProperties" >
+ <property name="objectName" >
+ <string notr="true" >logProperties</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="TabPage" >
+ <property name="objectName" >
+ <string notr="true" >TabPage</string>
+ </property>
+ <attribute name="title" >
+ <string>Macro Log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logMacros" >
+ <property name="objectName" >
+ <string notr="true" >logMacros</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="logDebugTab" >
+ <property name="objectName" >
+ <string notr="true" >logDebugTab</string>
+ </property>
+ <attribute name="title" >
+ <string>Debug log</string>
+ </attribute>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="logDebug" >
+ <property name="objectName" >
+ <string notr="true" >logDebug</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolBar" name="Toolbar_2" >
+ <property name="objectName" >
+ <string notr="true" >Toolbar_2</string>
+ </property>
+ <property name="windowTitle" >
+ <string>Toolbar_2</string>
+ </property>
+ <addaction name="actionFileNew" />
+ <addaction name="actionControlMethods" />
+ <addaction name="actionControlProperties" />
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="objectName" >
+ <string notr="true" >menubar</string>
+ </property>
+ <widget class="QMenu" name="FileMenu" >
+ <property name="objectName" >
+ <string notr="true" >FileMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;File</string>
+ </property>
+ <addaction name="actionFileNew" />
+ <addaction name="actionFileLoad" />
+ <addaction name="actionFileSave" />
+ <addaction name="separator" />
+ <addaction name="actionFileExit" />
+ </widget>
+ <widget class="QMenu" name="ContainerMenu" >
+ <property name="objectName" >
+ <string notr="true" >ContainerMenu</string>
+ </property>
+ <property name="title" >
+ <string>Con&amp;tainer</string>
+ </property>
+ <addaction name="actionContainerSet" />
+ <addaction name="actionContainerClear" />
+ <addaction name="separator" />
+ <addaction name="actionContainerProperties" />
+ </widget>
+ <widget class="QMenu" name="ControlMenu" >
+ <property name="objectName" >
+ <string notr="true" >ControlMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Control</string>
+ </property>
+ <widget class="QMenu" name="VerbMenu" >
+ <property name="objectName" >
+ <string notr="true" >VerbMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Verbs...</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ <addaction name="actionControlMethods" />
+ <addaction name="actionControlProperties" />
+ <addaction name="VerbMenu" />
+ <addaction name="separator" />
+ <addaction name="actionControlInfo" />
+ <addaction name="actionControlDocumentation" />
+ <addaction name="actionControlPixmap" />
+ </widget>
+ <widget class="QMenu" name="ScriptMenu" >
+ <property name="objectName" >
+ <string notr="true" >ScriptMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Scripting</string>
+ </property>
+ <addaction name="actionScriptingLoad" />
+ <addaction name="actionScriptingRun" />
+ </widget>
+ <widget class="QMenu" name="OptionsMenu" >
+ <property name="objectName" >
+ <string notr="true" >OptionsMenu</string>
+ </property>
+ <property name="title" >
+ <string>&amp;Options</string>
+ </property>
+ <widget class="QMenu" name="LoggingMenu" >
+ <property name="objectName" >
+ <string notr="true" >LoggingMenu</string>
+ </property>
+ <property name="title" >
+ <string>Log...</string>
+ </property>
+ <addaction name="actionLogSignals" />
+ <addaction name="actionLogProperties" />
+ </widget>
+ <addaction name="actionFreezeEvents" />
+ <addaction name="actionGroupLogging" />
+ <addaction name="LoggingMenu" />
+ </widget>
+ <addaction name="FileMenu" />
+ <addaction name="ContainerMenu" />
+ <addaction name="ControlMenu" />
+ <addaction name="ScriptMenu" />
+ <addaction name="OptionsMenu" />
+ </widget>
+ <action name="actionFileExit" >
+ <property name="objectName" >
+ <string>actionFileExit</string>
+ </property>
+ <property name="iconText" >
+ <string>Exit</string>
+ </property>
+ <property name="text" >
+ <string>E&amp;xit</string>
+ </property>
+ </action>
+ <action name="actionContainerSet" >
+ <property name="objectName" >
+ <string>actionContainerSet</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Set Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Set Control</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+S</string>
+ </property>
+ </action>
+ <action name="actionControlMethods" >
+ <property name="objectName" >
+ <string>actionControlMethods</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="icon" >
+ <iconset>image0</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Invoke Methods</string>
+ </property>
+ <property name="text" >
+ <string>Invoke &amp;Methods</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+M</string>
+ </property>
+ </action>
+ <action name="actionControlProperties" >
+ <property name="objectName" >
+ <string>actionControlProperties</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="icon" >
+ <iconset>image1</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Change Properties</string>
+ </property>
+ <property name="text" >
+ <string>Change &amp;Properties</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+P</string>
+ </property>
+ </action>
+ <action name="actionContainerClear" >
+ <property name="objectName" >
+ <string>actionContainerClear</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Clear Control</string>
+ </property>
+ <property name="text" >
+ <string>C&amp;lear Control</string>
+ </property>
+ <property name="shortcut" >
+ <string/>
+ </property>
+ </action>
+ <action name="actionContainerProperties" >
+ <property name="objectName" >
+ <string>actionContainerProperties</string>
+ </property>
+ <property name="iconText" >
+ <string>Ambient Properties</string>
+ </property>
+ <property name="text" >
+ <string>Ambient &amp;Properties</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+A</string>
+ </property>
+ </action>
+ <action name="actionControlInfo" >
+ <property name="objectName" >
+ <string>actionControlInfo</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Details</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Details</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+I</string>
+ </property>
+ </action>
+ <action name="actionFileSave" >
+ <property name="objectName" >
+ <string>actionFileSave</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Save Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Save Control</string>
+ </property>
+ </action>
+ <action name="actionFileLoad" >
+ <property name="objectName" >
+ <string>actionFileLoad</string>
+ </property>
+ <property name="iconText" >
+ <string>Load Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Load Control</string>
+ </property>
+ </action>
+ <action name="actionFreezeEvents" >
+ <property name="objectName" >
+ <string>actionFreezeEvents</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="iconText" >
+ <string>Freeze Events</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Freeze Events</string>
+ </property>
+ </action>
+ <action name="actionFileNew" >
+ <property name="objectName" >
+ <string>actionFileNew</string>
+ </property>
+ <property name="icon" >
+ <iconset>image2</iconset>
+ </property>
+ <property name="iconText" >
+ <string>Insert Control</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Insert Control</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <action name="actionControlDocumentation" >
+ <property name="objectName" >
+ <string>actionControlDocumentation</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Show Documentation</string>
+ </property>
+ <property name="text" >
+ <string>Show D&amp;ocumentation</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ <action name="actionControlPixmap" >
+ <property name="objectName" >
+ <string>actionControlPixmap</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Render to Pixmap</string>
+ </property>
+ <property name="text" >
+ <string>Render to Pi&amp;xmap</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+X</string>
+ </property>
+ </action>
+ <action name="actionScriptingLoad" >
+ <property name="objectName" >
+ <string>actionScriptingLoad</string>
+ </property>
+ <property name="iconText" >
+ <string>Load Script</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Load Script</string>
+ </property>
+ </action>
+ <action name="actionScriptingRun" >
+ <property name="objectName" >
+ <string>actionScriptingRun</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="iconText" >
+ <string>Run Macro</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Run Macro...</string>
+ </property>
+ </action>
+ <actiongroup name="actionGroupLogging" >
+ <action name="actionLogSignals" >
+ <property name="objectName" >
+ <string>actionLogSignals</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="iconText" >
+ <string>Signals</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Signals</string>
+ </property>
+ </action>
+ <action name="actionLogProperties" >
+ <property name="objectName" >
+ <string>actionLogProperties</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="iconText" >
+ <string>Properties</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Properties</string>
+ </property>
+ </action>
+ <property name="objectName" >
+ <string>actionGroupLogging</string>
+ </property>
+ <property name="exclusive" >
+ <bool>false</bool>
+ </property>
+ </actiongroup>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <pixmapfunction></pixmapfunction>
+ <images>
+ <image name="image0" >
+ <data format="XPM.GZ" length="3502" >789cdd95c96e1c371086ef7a8a81eb6604e56e92bd21c84192175996648d6559b2831cd85cb4ef23d95290770fe72f36e3003ee41220485373f8543f975a587cf17c76b8bb3d7bfe62e56e6117276ee68eededecb9bfbfb878fcf5b75f7e5f79a6d42cfdd54d3553cf7e5a79365fccdc6ce7ea322cc19e26a0aa51aaeb964c31b3ee46d8a9b05b32b7994d27f3178523ecbb99bbbe87fdaef000be06b7ca0e067c9b791c5af04d6637c87e8f99fde0c11edc6935c2193e01f7dab91a1cc083314ef4c7e0b15141ece29f6b4c68c047998720fb7d01473d8e60b24bae2b1d1cf416faba36cacbfe1b99b597f5e04f6d4c081af335b86f5c80ff74091eda3a20beb40376ad8b381fbd0487ce44890f83a3a92cf6a3fd25abca682beb7d15ee42141ec0e90016fed366e6c6223ff498b91d2b30ceab5462d93f1416ff9accdd28e741bc9531e388fcd3c7c292fff7e0c67827febf05b74de5e47c3db84b2cfedf64ae9dc4df1496fc55e0bed15eceb75758ce578387a6f1a81fda288cfa639db9f5d89f55610b7d07b64defc51f3f71407c18f95163aa0fd9ff43662bf543a867e51b9ff3391696fa719943107f241ea189926f96fc84b68a92df3785113fdece5c47a9af77e09818fef2566615e5bea1de75ddb6c284fbaa753b487df03770d34ef532070f5d9bf90aecbb18253ec8bf317d88f08f719f4d3ba8cca83f330c5d147f5f67ee33239fc60e6366ec6fc6c10933fa87f1b6ca7c9fb98e12af0770b05a98d05f4cb42633eaade9c6364afe5e816d2a47e94fb86f9dafea0af1b617e05018fe76b1f0f9927b5df80c1c2a55213f16fd607085d14f6c5d18f7c7b6f5584b3da03e6d5718f567fb494f5bc2c5be061e26b6a847ebea3460477c6c2c8cfa18abb2de2ab8ae7d2df15907ab625f084f768bfa1c4d61d4ef38d4a196787e02db693e8bbef84f88d718ea584b7f417cdd5fe7c1fbe14a7c08f7d9a9e581c088af3385515fae298cfcbbb6d295f49327e1c9ce9fc1dd6467dc1fd7173dfab9f3aa5672dfd06f5c2c76f4575fa9f481b19eaf0be37df46a623e04ebc2e8b7de28ad64ff03705318f7c1b73a7d60c4d35b6514fa29a19ffa7162467ff7ae30f2e17d39afecef8b1dfdd7c7c2a8ff6074aba53f20fea1cc679bd954a2473f0d41754ade7ff497d8a85e49ffc47b145b6db5f403f817fb62477ca29dd623f49fe8d4a0a4dff4994725fde25a58a701463f8d5e375afadb7ae6c9be96396aa92fbcbf3198f4c1de656e8ccc9f67b606e7e5d5ccde483fb9126efa46ce7f29dc9a56d6bbc8dcb4b21eea2dc6f41ccbfb762edca6171b7c26dc990ef3e78b7f3efe2f7a26b6e9473cb24be43970e4a3328ef9e47b3d9ff2199ff3055ff2155ff34dfacf2ddff182eff901e32b7fe3c7499f567d4ada555ee3757ec9aff835bf493336f82d6ff23bde4a639b77f83def66bde5397fe03dfec8fb697ce2033ee4cf69c617aeb866958666c30db765fd8efbac9619437285e60bb2349223bfd453a038e9e9888e8b7a9f4ee894cee89c2ed28c4bbaa26bd67443b73fd6d3091fd01d2de89e1e92fe2b7d4b3e2cf58f3fd243fd44abb446eb49fd925ed16b7a431bf496368b7ee4757af737f5166d27f50ebda75d9ad307daa38fb43fe9e9131dd0217d4e3e7ea12aa96b5249adc950432d75d427f560d9d2942f6be9c98ed6d1c27a1b6c5ac71ed9e3149b3d7b92e2b249fb497dfa7d3dd8337b6e2fd2b8b45789aeed8dbdb5777661693952b3a0ff763dff6bfa3f7e5ef9138fb14e09</data>
+ </image>
+ <image name="image1" >
+ <data format="XPM.GZ" length="2493" >789ca59459531b391446dff9152ef4464dddb8dbbd566a1eb2af10c84a929a87de8c0dd86c76623235ff3dfa8eb0878c3309a9e850a64fe9d3b5a4967c6babb7bfbbdddbbab57131ab66e3a6d78caaf3de563b9f4c2e3ffef5e7df1b9b71dcf37f45de8b37ffd8d8dc9bf59adecec9b493d8dc8bebd3f0311e09fc151e0b7c07af05fe146f84dca9b88b1241ff17794cc347782ac89fc90791a07f8a27026ff042e043bc128c3fc51b417f8db7028ff14ee0bbc1b3a62af177f850e07bc1b3b60aeb3b90277d81bfc0a33caac37c3b9c86bfc67381b77821f00778990f9bd09fe0b5c01fe26d91b561bf2a79da17acf7088f044e7db693bc9be003c1f847c1cb7e17fad9ff341178a84f23ff12cf04fe18cfcbbc633f1dfb91760277f2ac2fc8e7782ce83fc60782fe90e70be83fc77dbbdaef27782ee83fc40b814f975e87fdb8c0ebacaec3f933bc13f878e94d582fe7271b0afc64e94da8cff9c9fdfb6dc2f9e1fbf381c039df795aa55d78df255e0abcc03b81bf97737cc378e65b1455d186f1295e099cfd28ea2a6d42bd7dbc15cc8ffb500e04fd039c463ff7b96c05fd91bc4a05fe1c2f57f7611baf57e7bf8fb702ff20e7ba87f7fb0c4f933809e7330b2ef0b7f850e097f22616cc8ffbc2750df35fe089c0efe079522661fdbc9fa62cea229c8f37782df0bbf2364eda24cc77125ce0fc3eb449e11bfe19678138e7b3ed047e4fdec5abfbc3ef5397e4691ed6c7fdeb0a817fc22b81df970fe3b44ccbf0637b737e276fce2aabadf14fad7536bc7a3ab0918dd7f376684776ec99d8d44e3ca776e69fce3d1736b3f9b7799ffe649f6de1b9f47cb13b76d7eed97dfff4c01eda237b1c4684bc3df1b5437a39e2a93db3e7b6edd9b117b66b7b9ef92affd2cf63710d8d187b5e79c6365fb2cabffe4f5e23deb09a7f797b2dff6e2d2ff6ed3dff3f58df7f46d7f2f177f3034b2cb5cc726c3d5f58e9cc3957b93a8c708d1f915c8dfe79fd856b9577ddffe44b3774076ee419933ef4335fb8237774d3fadfb09677c77ee6233771ad9b527f0427eb7977fa6bf5dd19f54757d55b774efd095c7c273ffbc5f9cffddb8e7e8cbb767e18f1537ef73ede28ffcfed8daf804d6c7a</data>
+ </image>
+ <image name="image2" >
+ <data format="XPM.GZ" length="1232" >789ccdd24b4fe2501c86f13d9fa2811d99a8ad9442cc2c44f082327169625c1c4e5b4f552e721398cc771f9f570907837bff0f8bfef226400287d5e0eeb617540f4bd399991536b0ce4c826a3a1f0c56f70fbfff96ca5114bcbf6a6110967f95ca07810dfe8c8619cfeefdb972a483e7306c107c84518de0293c360473312598c15a83602a1a8256b404fb30d64103eb09c10a4c9a047bb019119c8931c12e3475821dd88f094ec53ac1b5a8834bd1127c13738237d08604afc498e0b5a88313982604dba221f82a5a82633127b882594470211e137c116382976242f0496c121c8929c10b3127f80cf3238267624870282604e76293604bd4978603516f0d0b51a7ffd8dedb2c15d3b7699ae58feecb522936e7dcee62b6cb93db59fadbe5f9c5f98bdd0c03371c8d9db7a4dee770fb96e275329ded5f8af9e2eddb65f9a396cc5f566b6f392d8ad6fcf3ceda1d6f396f5d5c2e3e6ed5beea7a8b1b5fdf2c3f6edde9f6bce5c0ed9cff6b7fff3fd8b3fc3b29fd07f8c43cbd</data>
+ </image>
+ </images>
+</ui>
diff --git a/tools/activeqt/testcon/scripts/javascript.js b/tools/activeqt/testcon/scripts/javascript.js
new file mode 100644
index 0000000000..e2bd54b47b
--- /dev/null
+++ b/tools/activeqt/testcon/scripts/javascript.js
@@ -0,0 +1,25 @@
+function QAxWidget2::Click()
+{
+ QAxWidget2.lineWidth++;
+ MainWindow.logMacro(0, "Hello from JavaScript: QAxWidget2::Click", 0, "");
+}
+
+function fatLines()
+{
+ QAxWidget2.lineWidth = 25;
+}
+
+function thinLines()
+{
+ QAxWidget2.lineWidth = 1;
+}
+
+function setLineWidth(width)
+{
+ QAxWidget2.lineWidth = width;
+}
+
+function getLineWidth()
+{
+ return(QAxWidget2.lineWidth)
+}
diff --git a/tools/activeqt/testcon/scripts/perlscript.pl b/tools/activeqt/testcon/scripts/perlscript.pl
new file mode 100644
index 0000000000..029bdc264c
--- /dev/null
+++ b/tools/activeqt/testcon/scripts/perlscript.pl
@@ -0,0 +1,24 @@
+sub QAxWidget2_Click {
+ $QAxWidget2->{'lineWidth'} = $QAxWidget2->{'lineWidth'} + 1;
+ $MainWindow->logMacro(0, "Hello from Perl: QAxWidget2_Click", 0, "");
+}
+
+sub fatLines
+{
+ $QAxWidget2->{'lineWidth'} = 25;
+}
+
+sub thinLines
+{
+ $QAxWidget2->{'lineWidth'} = 1;
+}
+
+sub setLineWidth(width)
+{
+ $QAxWidget2->{'lineWidth'} = width;
+}
+
+sub getLineWidth()
+{
+ return $QAxWidget2->{'lineWidth'};
+}
diff --git a/tools/activeqt/testcon/scripts/pythonscript.py b/tools/activeqt/testcon/scripts/pythonscript.py
new file mode 100644
index 0000000000..79bca87b6c
--- /dev/null
+++ b/tools/activeqt/testcon/scripts/pythonscript.py
@@ -0,0 +1,15 @@
+def QAxWidget2_Click():
+ QAxWidget2.lineWidth = QAxWidget2.lineWidth + 1;
+ MainWindow.logMacro(0, "Hello from Python: QAxWidget2_Click", 0, "");
+
+def fatLines():
+ QAxWidget2.lineWidth = 25;
+
+def thinLines():
+ QAxWidget2.lineWidth = 1;
+
+def setLineWidth(width):
+ QAxWidget2.lineWidth = width;
+
+def getLineWidth():
+ return QAxWidget2.lineWidth;
diff --git a/tools/activeqt/testcon/scripts/vbscript.vbs b/tools/activeqt/testcon/scripts/vbscript.vbs
new file mode 100644
index 0000000000..bd29f19f78
--- /dev/null
+++ b/tools/activeqt/testcon/scripts/vbscript.vbs
@@ -0,0 +1,20 @@
+Sub QAxWidget2_Click
+ QAxWidget2.lineWidth = QAxWidget2.lineWidth + 1
+ MainWindow.logMacro 0, "Hello from VBScript: QAxWidget2_Click", 0, ""
+End Sub
+
+Sub fatLines
+ QAxWidget2.lineWidth = 25
+End Sub
+
+Sub thinLines
+ QAxWidget2.lineWidth = 1
+End Sub
+
+Sub setLineWidth(width)
+ QAxWidget2.lineWidth = width
+End Sub
+
+Public Function getLineWidth
+ getLineWidth = QAxWidget2.lineWidth
+End Function
diff --git a/tools/activeqt/testcon/testcon.idl b/tools/activeqt/testcon/testcon.idl
new file mode 100644
index 0000000000..7dd88a5ec4
--- /dev/null
+++ b/tools/activeqt/testcon/testcon.idl
@@ -0,0 +1,44 @@
+/****************************************************************************
+** Interface definition generated for ActiveQt project
+**
+** 'C:\depot\qt\3.3\extensions\activeqt\tools\testcon\testcon.exe'
+**
+** Created: Fr 31. Okt 15:33:50 2003
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+
+import "ocidl.idl";
+#include <olectl.h>
+
+[
+ uuid(4A43E44D-9D1D-47E5-A1E5-58FE6F7BE0A4),
+ version(1.0),
+ helpstring("testcon 1.0 Type Library")
+]
+library testconLib
+{
+ importlib("stdole32.tlb");
+ importlib("stdole2.tlb");
+
+ [
+ uuid(3FC86F5F-8B15-4428-8F6B-482BAE91F1AE),
+ helpstring("MainWindow Interface")
+ ]
+ dispinterface IMainWindow
+ {
+ properties:
+ methods:
+ [id(7)] void logMacro( [in] int p_code, [in] BSTR p_description, [in] int p_sourcePosition, [in] BSTR p_sourceText);
+ };
+
+ [
+ aggregatable,
+ helpstring("MainWindow Class"),
+ uuid(5F5CE700-48A8-47B1-9B06-3B7F79E41D7C)
+ ]
+ coclass MainWindow
+ {
+ [default] dispinterface IMainWindow;
+ };
+};
diff --git a/tools/activeqt/testcon/testcon.pro b/tools/activeqt/testcon/testcon.pro
new file mode 100644
index 0000000000..dc982185a0
--- /dev/null
+++ b/tools/activeqt/testcon/testcon.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+
+CONFIG += qaxserver qaxserver_no_postlink qaxcontainer
+# QT += qt3support
+
+# ui_qaxselect.h
+INCLUDEPATH += $$QT_SOURCE_TREE/tools/activeqt/container/debug \
+ $$QT_SOURCE_TREE/tools/activeqt/container/release \
+ $$QT_BUILD_TREE/src/activeqt/container \
+
+SOURCES = main.cpp docuwindow.cpp mainwindow.cpp invokemethod.cpp changeproperties.cpp ambientproperties.cpp controlinfo.cpp
+HEADERS = docuwindow.h mainwindow.h invokemethod.h changeproperties.h ambientproperties.h controlinfo.h
+FORMS = mainwindow.ui invokemethod.ui changeproperties.ui ambientproperties.ui controlinfo.ui
+RC_FILE = testcon.rc
+
+win32-borland {
+ QMAKE_POST_LINK = -midl $$QT_SOURCE_TREE/tools/activeqt/testcon/testcon.idl
+} else {
+ !win32-g++:QMAKE_POST_LINK = midl $$QT_SOURCE_TREE/tools/activeqt/testcon/testcon.idl && move testcon.tlb $(TARGETDIR)
+
+}
diff --git a/tools/activeqt/testcon/testcon.rc b/tools/activeqt/testcon/testcon.rc
new file mode 100644
index 0000000000..6fe403699f
--- /dev/null
+++ b/tools/activeqt/testcon/testcon.rc
@@ -0,0 +1,35 @@
+#ifndef Q_CC_BOR
+#include <winver.h>
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 3, 2, 0, 0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "Nokia Corporation and/or its subsidiary(-ies)\0"
+ VALUE "FileDescription", "ActiveQt Test Container\0"
+ VALUE "FileVersion", "1,0,0,1\0"
+ VALUE "InternalName", "testcon\0"
+ VALUE "LegalCopyright", "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "testcon.exe\0"
+ VALUE "ProductName", "ActiveQt Test Container\0"
+ VALUE "ProductVersion", "3, 2, 0, 0\0"
+ END
+ END
+ END
+/* End of Version info */
+
diff --git a/tools/assistant/assistant.pro b/tools/assistant/assistant.pro
new file mode 100644
index 0000000000..08d0d4b8f1
--- /dev/null
+++ b/tools/assistant/assistant.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS += lib/fulltextsearch \
+ lib \
+ tools \
+ compat \
+ compat/lib \ \ No newline at end of file
diff --git a/tools/assistant/compat/Info_mac.plist b/tools/assistant/compat/Info_mac.plist
new file mode 100644
index 0000000000..b1e6336fb0
--- /dev/null
+++ b/tools/assistant/compat/Info_mac.plist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.trolltech.assistant-compat</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+</dict>
+</plist>
diff --git a/tools/assistant/compat/LICENSE.GPL b/tools/assistant/compat/LICENSE.GPL
new file mode 100644
index 0000000000..b6e1c33e04
--- /dev/null
+++ b/tools/assistant/compat/LICENSE.GPL
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/tools/assistant/compat/assistant.icns b/tools/assistant/compat/assistant.icns
new file mode 100644
index 0000000000..6291dd3975
--- /dev/null
+++ b/tools/assistant/compat/assistant.icns
Binary files differ
diff --git a/tools/assistant/compat/assistant.ico b/tools/assistant/compat/assistant.ico
new file mode 100644
index 0000000000..9e1b83f1b6
--- /dev/null
+++ b/tools/assistant/compat/assistant.ico
Binary files differ
diff --git a/tools/assistant/compat/assistant.pro b/tools/assistant/compat/assistant.pro
new file mode 100644
index 0000000000..e865d6b7a6
--- /dev/null
+++ b/tools/assistant/compat/assistant.pro
@@ -0,0 +1,84 @@
+include($$QT_SOURCE_TREE/tools/shared/fontpanel/fontpanel.pri)
+
+TEMPLATE = app
+LANGUAGE = C++
+TARGET = assistant_adp
+
+CONFIG += qt warn_on
+
+unix:contains(QT_CONFIG, dbus):QT += dbus
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+QT += xml network
+
+PROJECTNAME = Assistant
+DESTDIR = ../../../bin
+
+FORMS += helpdialog.ui \
+ mainwindow.ui \
+ tabbedbrowser.ui \
+ topicchooser.ui
+
+SOURCES += main.cpp \
+ helpwindow.cpp \
+ topicchooser.cpp \
+ docuparser.cpp \
+ index.cpp \
+ profile.cpp \
+ config.cpp \
+ helpdialog.cpp \
+ mainwindow.cpp \
+ tabbedbrowser.cpp \
+ fontsettingsdialog.cpp
+
+HEADERS += helpwindow.h \
+ topicchooser.h \
+ docuparser.h \
+ index.h \
+ profile.h \
+ helpdialog.h \
+ mainwindow.h \
+ tabbedbrowser.h \
+ config.h \
+ fontsettingsdialog.h
+
+RESOURCES += assistant.qrc
+
+contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE
+DEFINES += QT_KEYWORDS
+#DEFINES += QT_PALMTOPCENTER_DOCS
+
+win32 {
+ !wince*:LIBS += -lshell32
+ RC_FILE = assistant.rc
+}
+
+mac {
+ ICON = assistant.icns
+ TARGET = Assistant_adp
+ QMAKE_INFO_PLIST = Info_mac.plist
+}
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+TRANSLATIONS = assistant_de.ts
+
+unix:!contains(QT_CONFIG, zlib):LIBS += -lz
+
+contains(CONFIG, static): {
+ win32 {
+ exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.lib) {
+ QTPLUGIN += qjpeg
+ DEFINES += USE_STATIC_JPEG_PLUGIN
+ }
+ } else {
+ exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.a) {
+ QTPLUGIN += qjpeg
+ DEFINES += USE_STATIC_JPEG_PLUGIN
+ }
+ }
+}
diff --git a/tools/assistant/compat/assistant.qrc b/tools/assistant/compat/assistant.qrc
new file mode 100644
index 0000000000..dae1f48ad0
--- /dev/null
+++ b/tools/assistant/compat/assistant.qrc
@@ -0,0 +1,37 @@
+<RCC>
+ <qresource prefix="/trolltech/assistant" >
+ <file>images/assistant-128.png</file>
+ <file>images/assistant.png</file>
+ <file>images/close.png</file>
+ <file>images/designer.png</file>
+ <file>images/linguist.png</file>
+ <file>images/mac/addtab.png</file>
+ <file>images/mac/book.png</file>
+ <file>images/mac/closetab.png</file>
+ <file>images/mac/editcopy.png</file>
+ <file>images/mac/find.png</file>
+ <file>images/mac/home.png</file>
+ <file>images/mac/next.png</file>
+ <file>images/mac/prev.png</file>
+ <file>images/mac/print.png</file>
+ <file>images/mac/synctoc.png</file>
+ <file>images/mac/whatsthis.png</file>
+ <file>images/mac/zoomin.png</file>
+ <file>images/mac/zoomout.png</file>
+ <file>images/qt.png</file>
+ <file>images/win/addtab.png</file>
+ <file>images/win/book.png</file>
+ <file>images/win/closetab.png</file>
+ <file>images/win/editcopy.png</file>
+ <file>images/win/find.png</file>
+ <file>images/win/home.png</file>
+ <file>images/win/next.png</file>
+ <file>images/win/previous.png</file>
+ <file>images/win/print.png</file>
+ <file>images/win/synctoc.png</file>
+ <file>images/win/whatsthis.png</file>
+ <file>images/win/zoomin.png</file>
+ <file>images/win/zoomout.png</file>
+ <file>images/wrap.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/assistant/compat/assistant.rc b/tools/assistant/compat/assistant.rc
new file mode 100644
index 0000000000..b4786ceaaf
--- /dev/null
+++ b/tools/assistant/compat/assistant.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "assistant.ico"
diff --git a/tools/assistant/compat/compat.pro b/tools/assistant/compat/compat.pro
new file mode 100644
index 0000000000..1086f4c825
--- /dev/null
+++ b/tools/assistant/compat/compat.pro
@@ -0,0 +1,84 @@
+include($$QT_SOURCE_TREE/tools/shared/fontpanel/fontpanel.pri)
+
+TEMPLATE = app
+LANGUAGE = C++
+TARGET = assistant_adp
+
+CONFIG += qt warn_on
+
+unix:contains(QT_CONFIG, dbus):QT += dbus
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+QT += xml network
+
+PROJECTNAME = Assistant
+DESTDIR = ../../../bin
+
+FORMS += helpdialog.ui \
+ mainwindow.ui \
+ tabbedbrowser.ui \
+ topicchooser.ui
+
+SOURCES += main.cpp \
+ helpwindow.cpp \
+ topicchooser.cpp \
+ docuparser.cpp \
+ index.cpp \
+ profile.cpp \
+ config.cpp \
+ helpdialog.cpp \
+ mainwindow.cpp \
+ tabbedbrowser.cpp \
+ fontsettingsdialog.cpp
+
+HEADERS += helpwindow.h \
+ topicchooser.h \
+ docuparser.h \
+ index.h \
+ profile.h \
+ helpdialog.h \
+ mainwindow.h \
+ tabbedbrowser.h \
+ config.h \
+ fontsettingsdialog.h
+
+RESOURCES += assistant.qrc
+
+contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE
+DEFINES += QT_KEYWORDS
+#DEFINES += QT_PALMTOPCENTER_DOCS
+
+win32 {
+ LIBS += -lshell32
+ RC_FILE = assistant.rc
+}
+
+mac {
+ ICON = assistant.icns
+ TARGET = Assistant_adp
+# QMAKE_INFO_PLIST = Info_mac.plist
+}
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+TRANSLATIONS = assistant_de.ts
+
+unix:!contains(QT_CONFIG, zlib):LIBS += -lz
+
+contains(CONFIG, static): {
+ win32 {
+ exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.lib) {
+ QTPLUGIN += qjpeg
+ DEFINES += USE_STATIC_JPEG_PLUGIN
+ }
+ } else {
+ exists($$[QT_INSTALL_PLUGINS]/imageformats/qjpeg.a) {
+ QTPLUGIN += qjpeg
+ DEFINES += USE_STATIC_JPEG_PLUGIN
+ }
+ }
+}
diff --git a/tools/assistant/compat/config.cpp b/tools/assistant/compat/config.cpp
new file mode 100644
index 0000000000..b2eba11570
--- /dev/null
+++ b/tools/assistant/compat/config.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "profile.h"
+#include "docuparser.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QLibraryInfo>
+#include <QFont>
+#include <QFontInfo>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QSettings>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+static Config *static_configuration = 0;
+
+inline QString getVersionString()
+{
+ return QString::number( (QT_VERSION >> 16) & 0xff )
+ + QLatin1String(".") + QString::number( (QT_VERSION >> 8) & 0xff );
+}
+
+Config::Config()
+ : profil( 0 ), hideSidebar( false ), rebuildDocs(true)
+{
+ if( !static_configuration ) {
+ static_configuration = this;
+ } else {
+ qWarning( "Multiple configurations not allowed!" );
+ }
+}
+
+Config *Config::loadConfig(const QString &profileFileName)
+{
+ Config *config = new Config();
+
+ if (profileFileName.isEmpty()) { // no profile
+ if (!config->defaultProfileExists()) {
+ config->profil = Profile::createDefaultProfile();
+ config->saveProfile(config->profil);
+ } else {
+ config->profil = new Profile();
+ }
+ config->loadDefaultProfile();
+ config->load();
+ return config;
+ }
+
+ QFile file(profileFileName);
+ if (!file.exists()) {
+ qWarning( "File does not exist: %s", qPrintable(profileFileName) );
+ return 0;
+ }
+ DocuParser *parser = DocuParser::createParser( profileFileName );
+ if (!parser) {
+ qWarning( "Failed to create parser for file: %s", qPrintable(profileFileName) );
+ return 0;
+ }
+ if (parser->parserVersion() < DocuParser::Qt320) {
+ qWarning( "File does not contain profile information" );
+ return 0;
+ }
+ DocuParser320 *profileParser = static_cast<DocuParser320*>(parser);
+ parser->parse(&file);
+ config->profil = profileParser->profile();
+ if (!config->profil) {
+ qWarning( "Config::loadConfig(), no profile in: %s", qPrintable(profileFileName) );
+ return 0;
+ }
+ config->profil->setProfileType(Profile::UserProfile);
+ config->profil->setDocuParser(profileParser);
+ config->load();
+ return config;
+}
+
+Config *Config::configuration()
+{
+ Q_ASSERT( static_configuration );
+ return static_configuration;
+}
+
+void Config::load()
+{
+ const QString key = getVersionString() + QLatin1String("/");
+
+ bool isDefaultProfile = profil->props[QLatin1String("name")] == QLatin1String("default");
+ const QString pKey = isDefaultProfile ? QString::fromLatin1(QT_VERSION_STR)
+ : getVersionString();
+
+ const QString profkey = pKey + QLatin1String("/Profile/") + profil->props[QLatin1String("name")] + QLatin1String("/");
+
+ QSettings settings;
+
+ home = profil->props[QLatin1String("startpage")];;
+ if (home.isEmpty() && isDefaultProfile)
+ home = QLibraryInfo::location(QLibraryInfo::DocumentationPath) + QLatin1String("/html/index.html");
+ src = settings.value( profkey + QLatin1String("Source") ).toStringList();
+ sideBar = settings.value( key + QLatin1String("SideBarPage") ).toInt();
+ if (qApp->type() != QApplication::Tty)
+ winGeometry = settings.value(key + QLatin1String("windowGeometry")).toByteArray();
+
+ mainWinState = settings.value(key + QLatin1String("MainWindowState")).toByteArray();
+ pointFntSize = settings.value(key + QLatin1String("FontSize"), qApp->font().pointSizeF()).toDouble();
+ rebuildDocs = settings.value( key + QLatin1String("RebuildDocDB"), true ).toBool();
+
+ profileNames = settings.value( key + QLatin1String("Profile") ).toStringList();
+
+ m_fontSettings.windowFont = qVariantValue<QFont>(settings.value(key + QLatin1String("windowfont"), qApp->font()));
+ m_fontSettings.browserFont = qVariantValue<QFont>(settings.value(key + QLatin1String("browserfont"), qApp->font()));
+ m_fontSettings.useWindowFont = settings.value(key + QLatin1String("usewindowfont"), false).toBool();
+ m_fontSettings.useBrowserFont = settings.value(key + QLatin1String("usebrowserfont"), false).toBool();
+ m_fontSettings.windowWritingSystem = static_cast<QFontDatabase::WritingSystem>(
+ settings.value(key + QLatin1String("windowwritingsystem"), QFontDatabase::Latin).toInt());
+ m_fontSettings.browserWritingSystem = static_cast<QFontDatabase::WritingSystem>(
+ settings.value(key + QLatin1String("browserwritingsystem"), QFontDatabase::Latin).toInt());
+
+ m_fontSettings.browserFont.setPointSizeF(pointFntSize);
+}
+
+void Config::save()
+{
+ saveSettings();
+ saveProfile( profil );
+}
+
+void Config::saveSettings()
+{
+ const QString key = getVersionString() + QLatin1String("/");
+
+ const QString pKey = (profil->props[QLatin1String("name")] == QLatin1String("default"))
+ ? QString::fromLatin1(QT_VERSION_STR)
+ : getVersionString();
+
+ const QString profkey = pKey + QLatin1String("/Profile/") + profil->props[QLatin1String("name")] + QLatin1String("/");
+
+ QSettings settings;
+
+ settings.setValue( profkey + QLatin1String("Source"), src );
+ settings.setValue( key + QLatin1String("SideBarPage"), sideBarPage() );
+ if (qApp->type() != QApplication::Tty)
+ settings.setValue(key + QLatin1String("windowGeometry"), winGeometry);
+
+ settings.setValue( key + QLatin1String("MainWindowState"), mainWinState );
+ settings.setValue( key + QLatin1String("FontSize"), pointFntSize);
+ settings.setValue( key + QLatin1String("RebuildDocDB"), rebuildDocs );
+
+ settings.setValue(key + QLatin1String("windowfont"), m_fontSettings.windowFont);
+ settings.setValue(key + QLatin1String("browserfont"), m_fontSettings.browserFont);
+ settings.setValue(key + QLatin1String("usewindowfont"), m_fontSettings.useWindowFont);
+ settings.setValue(key + QLatin1String("usebrowserfont"), m_fontSettings.useBrowserFont);
+ settings.setValue(key + QLatin1String("windowwritingsystem"), m_fontSettings.windowWritingSystem);
+ settings.setValue(key + QLatin1String("browserwritingsystem"), m_fontSettings.browserWritingSystem);
+}
+
+#ifdef ASSISTANT_DEBUG
+static void dumpmap( const QMap<QString,QString> &m, const QString &header )
+{
+ qDebug( header );
+ QMap<QString,QString>::ConstIterator it = m.begin();
+ while (it != m.end()) {
+ qDebug( " " + it.key() + ":\t\t" + *it );
+ ++it;
+ }
+}
+#endif
+
+bool Config::defaultProfileExists()
+{
+ QSettings settings;
+ const QString profKey = QLatin1String(QT_VERSION_STR) + QLatin1String("/Profile/default/");
+
+ if (settings.contains(profKey + QLatin1String("DocFiles"))
+ && settings.contains(profKey + QLatin1String("Titles"))
+ && settings.contains(profKey + QLatin1String("ImageDirs"))) {
+ QStringList dcfs = settings.value(profKey + QLatin1String("DocFiles") ).toStringList();
+ foreach (QString file, dcfs) {
+ if (file == Profile::storableFilePath(file))
+ return true;
+ }
+ }
+ return false;
+}
+
+void Config::loadDefaultProfile()
+{
+ QSettings settings;
+ const QString profKey = QLatin1String(QT_VERSION_STR) + QLatin1String("/Profile/default/");
+
+ if (!defaultProfileExists())
+ return;
+
+ // Override the defaults with settings in registry.
+ profil->icons.clear();
+ profil->indexPages.clear();
+ profil->imageDirs.clear();
+ profil->docs.clear();
+ profil->dcfTitles.clear();
+
+ QStringList titles = settings.value( profKey + QLatin1String("Titles") ).toStringList();
+ QStringList iconLst = settings.value( profKey + QLatin1String("DocIcons") ).toStringList();
+ QStringList indexLst = settings.value( profKey + QLatin1String("IndexPages") ).toStringList();
+ QStringList imgDirLst = settings.value( profKey + QLatin1String("ImageDirs") ).toStringList();
+ QStringList dcfs = settings.value( profKey + QLatin1String("DocFiles") ).toStringList();
+ profil->props[QLatin1String("name")] = QLatin1String("default");
+
+ QString filePath;
+ QStringList::ConstIterator it = titles.constBegin();
+ QStringList::ConstIterator iconIt = iconLst.constBegin();
+ QStringList::ConstIterator indexIt = indexLst.constBegin();
+ QStringList::ConstIterator imageIt = imgDirLst.constBegin();
+ QStringList::ConstIterator dcfIt = dcfs.constBegin();
+ while((it != titles.constEnd())
+ && (iconIt != iconLst.constEnd())
+ && (indexIt != indexLst.constEnd())
+ && (imageIt != imgDirLst.constEnd())
+ && (dcfIt != dcfs.constEnd())) {
+ profil->addDCFIcon( *it, *iconIt );
+ profil->addDCFIndexPage(*it, Profile::loadableFilePath(*indexIt));
+ profil->addDCFImageDir( *it, *imageIt );
+ profil->addDCFTitle(Profile::loadableFilePath(*dcfIt), *it);
+ ++it, ++iconIt, ++indexIt, ++imageIt, ++dcfIt;
+ }
+#if ASSISTANT_DEBUG
+ dumpmap( profil->icons, QLatin1String("Icons") );
+ dumpmap( profil->indexPages, QLatin1String("IndexPages") );
+ dumpmap( profil->imageDirs, QLatin1String("ImageDirs") );
+ dumpmap( profil->dcfTitles, QLatin1String("dcfTitles") );
+ qDebug( "Docfiles: \n " + profil->docs.join( "\n " ) );
+#endif
+}
+
+void Config::saveProfile( Profile *profile )
+{
+ if (profil->profileType() == Profile::UserProfile)
+ return;
+
+ const QString key = (profile->props[QLatin1String("name")] == QLatin1String("default"))
+ ? QString::fromLatin1(QT_VERSION_STR)
+ : getVersionString();
+
+ const QString profKey = key + QLatin1String("/Profile/") + profile->props[QLatin1String("name")] + QLatin1String("/");
+
+ QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath).replace(QLatin1String("\\"), QLatin1String("/"));
+ QStringList indexes, icons, imgDirs, dcfs;
+ QStringList titles = profile->dcfTitles.keys();
+ QStringList::ConstIterator it = titles.constBegin();
+ QString filePath;
+ for ( ; it != titles.constEnd(); ++it ) {
+
+ indexes << Profile::storableFilePath(profile->indexPages[*it]);
+ icons << profile->icons[*it];
+ imgDirs << profile->imageDirs[*it];
+ dcfs << Profile::storableFilePath(profile->dcfTitles[*it]);
+ }
+
+ QSettings settings;
+ settings.setValue( profKey + QLatin1String("Titles"), titles );
+ settings.setValue( profKey + QLatin1String("DocFiles"), dcfs );
+ settings.setValue( profKey + QLatin1String("IndexPages"), indexes );
+ settings.setValue( profKey + QLatin1String("DocIcons"), icons );
+ settings.setValue( profKey + QLatin1String("ImageDirs"), imgDirs );
+
+#if ASSISTANT_DEBUG
+ qDebug() << "Titles:\n - " << ((QStringList*)&titles)->join("\n - ");
+ qDebug() << "Docfiles:\n - " << dcfs.join("\n - " );
+ qDebug() << "IndexPages:\n - " << indexes.join("\n - ");
+ qDebug() << "DocIcons:\n - " << icons.join("\n - " );
+ qDebug() << "ImageDirs:\n - " << imgDirs.join("\n - " );
+#endif
+}
+
+QStringList Config::mimePaths()
+{
+ static QStringList lst;
+
+ if( lst.count() > 0 )
+ return lst;
+
+ for (QMap<QString,QString>::ConstIterator it = profil->dcfTitles.constBegin();
+ it != profil->dcfTitles.constEnd(); ++it ) {
+
+ // Mime source for .dcf file path
+ QFileInfo info( *it );
+ QString dcfPath = info.absolutePath();
+ if (!lst.contains(dcfPath))
+ lst << dcfPath;
+
+ // Image dir for .dcf
+ QString imgDir = QDir::toNativeSeparators( dcfPath + QDir::separator()
+ + profil->imageDirs[it.key()] );
+ if (!lst.contains(imgDir))
+ lst << imgDir;
+ }
+ return lst;
+}
+
+QStringList Config::profiles() const
+{
+ return profileNames;
+}
+
+QString Config::title() const
+{
+ QString s = profil->props[QLatin1String("title")];
+ if (s.isEmpty())
+ s = QObject::tr("Qt Assistant by Nokia");
+ return s;
+}
+
+QString Config::aboutApplicationMenuText() const
+{
+ return profil->props[QLatin1String("aboutmenutext")];
+}
+
+QString Config::aboutURL() const
+{
+ return profil->props[QLatin1String("abouturl")];
+}
+
+QString Config::homePage() const
+{
+ return home.isEmpty() ? profil->props[QLatin1String("startpage")] : home;
+}
+
+QStringList Config::source() const
+{
+ return src.size() == 0 ? QStringList(profil->props[QLatin1String("startpage")]) : src;
+}
+
+QStringList Config::docFiles() const
+{
+ return profil->docs;
+}
+
+QPixmap Config::docIcon( const QString &title ) const
+{
+ // ### To allow qdoc generated dcf files to reference the doc icons from qmake_image_col
+ QString name = profil->icons[title];
+ QString resName = QLatin1String(":/trolltech/assistant/images/") + name;
+
+ if (QFile::exists(resName))
+ return QPixmap(resName);
+
+ if (name.startsWith(QLatin1String("file:")))
+ name = name.mid(5);
+ return QPixmap(name);
+}
+
+QPixmap Config::applicationIcon() const
+{
+ QString name = profil->props[QLatin1String("applicationicon")];
+ QString resName = QLatin1String(":/trolltech/assistant/images/") + name;
+
+ if (QFile::exists(resName))
+ return QPixmap(resName);
+
+ if (name.startsWith(QLatin1String("file:")))
+ name = name.mid(5);
+ return QPixmap(name);
+}
+
+QStringList Config::docTitles() const
+{
+ return QStringList(profil->indexPages.keys());
+}
+
+QString Config::docImageDir( const QString &docfile ) const
+{
+ return profil->imageDirs[docfile];
+}
+
+QString Config::indexPage( const QString &title ) const
+{
+ return profil->indexPages[title];
+}
+
+void Config::hideSideBar( bool b )
+{
+ hideSidebar = b;
+}
+
+bool Config::sideBarHidden() const
+{
+ return hideSidebar;
+}
+
+QString Config::assistantDocPath() const
+{
+ return profil->props[QLatin1String("assistantdocs")].isEmpty()
+ ? QLibraryInfo::location(QLibraryInfo::DocumentationPath) + QLatin1String("/html")
+ : profil->props[QLatin1String("assistantdocs")];
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/config.h b/tools/assistant/compat/config.h
new file mode 100644
index 0000000000..0858ad88a6
--- /dev/null
+++ b/tools/assistant/compat/config.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "profile.h"
+
+#include <QString>
+#include <QStringList>
+#include <QPixmap>
+#include <QMap>
+
+#include <QtGui/QFont>
+#include <QtGui/QFontDatabase>
+
+QT_BEGIN_NAMESPACE
+
+class Profile;
+
+struct FontSettings
+{
+ FontSettings() : useWindowFont(false), useBrowserFont(false),
+ windowWritingSystem(QFontDatabase::Latin), browserWritingSystem(QFontDatabase::Latin)
+ { }
+
+ QFont windowFont;
+ QFont browserFont;
+
+ bool useWindowFont;
+ bool useBrowserFont;
+
+ QFontDatabase::WritingSystem windowWritingSystem;
+ QFontDatabase::WritingSystem browserWritingSystem;
+};
+
+class Config
+{
+public:
+
+ Config();
+
+ void load();
+ void save();
+ Profile *profile() const { return profil; }
+ QString profileName() const { return profil->props[QLatin1String("name")]; }
+ bool validProfileName() const;
+ void hideSideBar( bool b );
+ bool sideBarHidden() const;
+ QStringList mimePaths();
+
+ // From profile, read only
+ QStringList docFiles() const;
+ QStringList docTitles() const;
+ QString indexPage( const QString &title ) const;
+ QString docImageDir( const QString &title ) const;
+ QPixmap docIcon( const QString &title ) const;
+
+ QStringList profiles() const;
+ QString title() const;
+ QString aboutApplicationMenuText() const;
+ QString aboutURL() const;
+ QPixmap applicationIcon() const;
+
+ // From QSettings, read / write
+ QString homePage() const;
+ void setHomePage( const QString &hom ) { home = hom; }
+
+ QStringList source() const;
+ void setSource( const QStringList &s ) { src = s; }
+
+ int sideBarPage() const { return sideBar; }
+ void setSideBarPage( int sbp ) { sideBar = sbp; }
+
+ QByteArray windowGeometry() const { return winGeometry; }
+ void setWindowGeometry( const QByteArray &geometry ) { winGeometry = geometry; }
+
+ QByteArray mainWindowState() const { return mainWinState; }
+ void setMainWindowState( const QByteArray &state ) { mainWinState = state; }
+
+ qreal fontPointSize() const { return pointFntSize; }
+ void setFontPointSize(qreal size)
+ {
+ pointFntSize = size;
+ m_fontSettings.useBrowserFont = true;
+ m_fontSettings.browserFont.setPointSizeF(size);
+ }
+
+ FontSettings fontSettings() { return m_fontSettings; }
+ void setFontSettings(const FontSettings &settings) { m_fontSettings = settings; }
+
+ QString assistantDocPath() const;
+
+ bool docRebuild() const { return rebuildDocs; }
+ void setDocRebuild( bool rb ) { rebuildDocs = rb; }
+
+ void saveProfile( Profile *profile );
+ void loadDefaultProfile();
+ bool defaultProfileExists();
+
+ static Config *configuration();
+ static Config *loadConfig(const QString &profileFileName);
+
+private:
+ Config( const Config &c );
+ Config& operator=( const Config &c );
+
+ void saveSettings();
+
+private:
+ Profile *profil;
+
+ QStringList profileNames;
+ QString home;
+ QStringList src;
+ QByteArray mainWinState;
+ QByteArray winGeometry;
+ qreal pointFntSize;
+ int sideBar;
+ bool hideSidebar;
+ bool rebuildDocs;
+ FontSettings m_fontSettings;
+};
+
+QT_END_NAMESPACE
+
+#endif // CONFIG_H
diff --git a/tools/assistant/compat/docuparser.cpp b/tools/assistant/compat/docuparser.cpp
new file mode 100644
index 0000000000..31e10407fd
--- /dev/null
+++ b/tools/assistant/compat/docuparser.cpp
@@ -0,0 +1,433 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "docuparser.h"
+#include "profile.h"
+
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QRegExp>
+#include <QString>
+#include <QDataStream>
+
+QT_BEGIN_NAMESPACE
+
+QDataStream &operator>>(QDataStream &s, ContentItem &ci)
+{
+ s >> ci.title;
+ s >> ci.reference;
+ s >> ci.depth;
+ return s;
+}
+
+QDataStream &operator<<(QDataStream &s, const ContentItem &ci)
+{
+ s << ci.title;
+ s << ci.reference;
+ s << ci.depth;
+ return s;
+}
+
+const QString DocuParser::DocumentKey = QLatin1String("/Qt Assistant/") + QLatin1String(QT_VERSION_STR) + QLatin1String("/");
+
+DocuParser *DocuParser::createParser(const QString &fileName)
+{
+ QFile file(fileName);
+ if(!file.open(QFile::ReadOnly)) {
+ return 0;
+ }
+
+ QString str;
+ int maxlen = 1024;
+ int majVer = 0, minVer = 0, serVer = 0;
+ static QRegExp re(QLatin1String("assistantconfig +version=\"(\\d)\\.(\\d)\\.(\\d)\""), Qt::CaseInsensitive);
+ Q_ASSERT(re.isValid());
+ while(!(str = QLatin1String(file.readLine(maxlen))).isEmpty()) {
+ if(re.indexIn(str) >= 0) {
+ majVer = re.cap(1).toInt();
+ minVer = re.cap(2).toInt();
+ serVer = re.cap(3).toInt();
+ break;
+ }
+ }
+
+ if (majVer < 3 || (majVer == 3 && minVer < 2)) {
+ return new DocuParser310;
+ }
+
+ return new DocuParser320;
+}
+
+
+bool DocuParser::parse(QFile *file)
+{
+ QXmlInputSource source(file);
+ QXmlSimpleReader reader;
+ reader.setContentHandler(this);
+ reader.setErrorHandler(this);
+ setFileName(QFileInfo(*file).absoluteFilePath());
+ return reader.parse(source);
+}
+
+
+QString DocuParser::errorProtocol() const
+{
+ return errorProt;
+}
+
+
+QList<ContentItem> DocuParser::getContentItems()
+{
+ return contentList;
+}
+
+
+QList<IndexItem*> DocuParser::getIndexItems()
+{
+ return indexList;
+}
+
+QString DocuParser::absolutify(const QString &name, bool makeUrl) const
+{
+ if (!name.isEmpty()) {
+ QString s = name;
+ s.replace(QLatin1String("\\"), QLatin1String("/"));
+ QFileInfo orgPath(name);
+ if(orgPath.isRelative())
+ s = QFileInfo(fname).path() + QLatin1Char('/') + name;
+ if (makeUrl)
+ s.prepend(QLatin1String("file:"));
+ return s;
+ }
+ return name;
+}
+
+
+void DocuParser310::addTo(Profile *p)
+{
+ p->addDCFTitle(fname, docTitle);
+ p->addDCFIcon(docTitle, iconName);
+ p->addDCFIndexPage(docTitle, conURL);
+}
+
+
+bool DocuParser310::startDocument()
+{
+ state = StateInit;
+ errorProt = QLatin1String("");
+
+ contentRef = QLatin1String("");
+ indexRef = QLatin1String("");
+ depth = 0;
+
+ contentList.clear();
+ qDeleteAll(indexList);
+ indexList.clear();
+
+ return true;
+}
+
+
+bool DocuParser310::startElement(const QString &, const QString &,
+ const QString &qname,
+ const QXmlAttributes &attr)
+{
+ if (qname == QLatin1String("DCF") && state == StateInit) {
+ state = StateContent;
+ contentRef = absolutify(attr.value(QLatin1String("ref")), false);
+ conURL = contentRef;
+ docTitle = attr.value(QLatin1String("title"));
+ iconName = absolutify(attr.value(QLatin1String("icon")), false);
+ contentList.append(ContentItem(docTitle, absolutify(contentRef), depth));
+ } else if (qname == QLatin1String("section") && (state == StateContent || state == StateSect)) {
+ state = StateSect;
+ contentRef = absolutify(attr.value(QLatin1String("ref")));
+ title = attr.value(QLatin1String("title"));
+ depth++;
+ contentList.append(ContentItem(title, contentRef, depth));
+ } else if (qname == QLatin1String("keyword") && state == StateSect) {
+ state = StateKeyword;
+ indexRef = absolutify(attr.value(QLatin1String("ref")));
+ } else
+ return false;
+ return true;
+}
+
+bool DocuParser310::endElement(const QString &nameSpace, const QString &localName,
+ const QString &qName)
+{
+ Q_UNUSED(nameSpace);
+ Q_UNUSED(localName);
+ Q_UNUSED(qName);
+
+ switch(state) {
+ case StateInit:
+ break;
+ case StateContent:
+ state = StateInit;
+ break;
+ case StateSect:
+ state = --depth ? StateSect : StateContent;
+ break;
+ case StateKeyword:
+ state = StateSect;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+
+bool DocuParser310::characters(const QString& ch)
+{
+ QString str = ch.simplified();
+ if (str.isEmpty())
+ return true;
+
+ switch (state) {
+ case StateInit:
+ case StateContent:
+ case StateSect:
+ return false;
+ break;
+ case StateKeyword:
+ indexList.append(new IndexItem(str, indexRef));
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+bool DocuParser310::fatalError(const QXmlParseException& exception)
+{
+ errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n")
+ .arg(exception.message())
+ .arg(exception.lineNumber())
+ .arg(exception.columnNumber());
+
+ return QXmlDefaultHandler::fatalError(exception);
+}
+
+
+DocuParser320::DocuParser320()
+ : prof(new Profile)
+{
+}
+
+
+void DocuParser320::addTo(Profile *p)
+{
+ QMap<QString,QString>::ConstIterator it;
+
+ for (it = prof->dcfTitles.constBegin(); it != prof->dcfTitles.constEnd(); ++it)
+ p->dcfTitles[it.key()] = *it;
+
+ for (it = prof->icons.constBegin(); it != prof->icons.constEnd(); ++it)
+ p->icons[it.key()] = *it;
+
+ for (it = prof->indexPages.constBegin(); it != prof->indexPages.constEnd(); ++it)
+ p->indexPages[it.key()] = *it;
+}
+
+
+bool DocuParser320::startDocument()
+{
+ state = StateInit;
+ errorProt = QLatin1String("");
+
+ contentRef = QLatin1String("");
+ indexRef = QLatin1String("");
+ depth = 0;
+ contentList.clear();
+ indexList.clear();
+
+ prof->addDCF(fname);
+
+ return true;
+}
+
+bool DocuParser320::startElement(const QString &, const QString &,
+ const QString &qname,
+ const QXmlAttributes &attr)
+{
+ QString lower = qname.toLower();
+
+ switch(state) {
+
+ case StateInit:
+ if(lower == QLatin1String("assistantconfig"))
+ state = StateDocRoot;
+ break;
+
+ case StateDocRoot:
+ if(lower == QLatin1String("dcf")) {
+ state = StateContent;
+ contentRef = absolutify(attr.value(QLatin1String("ref")));
+ conURL = contentRef;
+ docTitle = attr.value(QLatin1String("title"));
+ iconName = absolutify(attr.value(QLatin1String("icon")));
+ contentList.append(ContentItem(docTitle, contentRef, depth));
+ } else if(lower == QLatin1String("profile")) {
+ state = StateProfile;
+ }
+ break;
+
+ case StateSect:
+ if (lower == QLatin1String("keyword") && state == StateSect) {
+ state = StateKeyword;
+ indexRef = absolutify(attr.value(QLatin1String("ref")));
+ break;
+ } // else if (lower == "section")
+ case StateContent:
+ if(lower == QLatin1String("section")) {
+ state = StateSect;
+ contentRef = absolutify(attr.value(QLatin1String("ref")));
+ title = attr.value(QLatin1String("title"));
+ depth++;
+ contentList.append(ContentItem(title, contentRef, depth));
+ }
+ break;
+
+ case StateProfile:
+ if(lower == QLatin1String("property")) {
+ state = StateProperty;
+ propertyName = attr.value(QLatin1String("name"));
+ }
+ break;
+
+ case StateProperty:
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool DocuParser320::endElement(const QString &nameSpace,
+ const QString &localName,
+ const QString &qName)
+{
+ Q_UNUSED(nameSpace);
+ Q_UNUSED(localName);
+ Q_UNUSED(qName);
+
+ switch(state) {
+ case StateInit:
+ break;
+ case StateDocRoot:
+ state = StateInit;
+ break;
+ case StateProfile:
+ state = StateDocRoot;
+ break;
+ case StateProperty:
+ state = StateProfile;
+ if(propertyName.isEmpty() || propertyValue.isEmpty())
+ return false;
+ {
+ static const QStringList lst = QStringList()
+ << QLatin1String("startpage") << QLatin1String("abouturl")
+ << QLatin1String("applicationicon") << QLatin1String("assistantdocs");
+
+ if (lst.contains(propertyName))
+ propertyValue = absolutify(propertyValue);
+ }
+ prof->addProperty(propertyName, propertyValue);
+ break;
+ case StateContent:
+ if(!iconName.isEmpty())
+ prof->addDCFIcon(docTitle, iconName);
+ if(contentRef.isEmpty())
+ return false;
+ prof->addDCFIndexPage(docTitle, conURL);
+ prof->addDCFTitle(fname, docTitle);
+ state = StateDocRoot;
+ break;
+ case StateSect:
+ state = --depth ? StateSect : StateContent;
+ break;
+ case StateKeyword:
+ state = StateSect;
+ break;
+ }
+ return true;
+}
+
+bool DocuParser320::characters(const QString& ch)
+{
+ QString str = ch.simplified();
+ if (str.isEmpty())
+ return true;
+
+ switch (state) {
+ case StateInit:
+ case StateContent:
+ case StateSect:
+ return false;
+ break;
+ case StateKeyword:
+ indexList.append(new IndexItem(str, indexRef));
+ break;
+ case StateProperty:
+ propertyValue = ch;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool DocuParser320::fatalError(const QXmlParseException& exception)
+{
+ errorProt += QString::fromLatin1("fatal parsing error: %1 in line %2, column %3\n")
+ .arg(exception.message())
+ .arg(exception.lineNumber())
+ .arg(exception.columnNumber());
+ return QXmlDefaultHandler::fatalError(exception);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/docuparser.h b/tools/assistant/compat/docuparser.h
new file mode 100644
index 0000000000..181a8f1e70
--- /dev/null
+++ b/tools/assistant/compat/docuparser.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DOCUPARSER_H
+#define DOCUPARSER_H
+
+#include <QList>
+#include <QMap>
+#include <QXmlDefaultHandler>
+#include <QXmlAttributes>
+#include <QXmlParseException>
+
+QT_BEGIN_NAMESPACE
+
+class Profile;
+
+struct ContentItem {
+ ContentItem()
+ : title( QString() ), reference( QString() ), depth( 0 ) {}
+ ContentItem( const QString &t, const QString &r, int d )
+ : title( t ), reference( r ), depth( d ) {}
+ QString title;
+ QString reference;
+ int depth;
+ Q_DUMMY_COMPARISON_OPERATOR(ContentItem)
+};
+
+QDataStream &operator>>( QDataStream &s, ContentItem &ci );
+QDataStream &operator<<( QDataStream &s, const ContentItem &ci );
+
+struct IndexItem {
+ IndexItem( const QString &k, const QString &r )
+ : keyword( k ), reference( r ) {}
+ QString keyword;
+ QString reference;
+};
+
+
+
+class DocuParser : public QXmlDefaultHandler
+{
+public:
+ enum ParserVersion { Qt310, Qt320 };
+ // Since We don't want problems with documentation
+ // from version to version, this string stores the correct
+ // version string to save documents.
+ static const QString DocumentKey;
+
+ static DocuParser *createParser( const QString &fileName );
+
+ virtual bool parse( QFile *file );
+
+ QList<ContentItem> getContentItems();
+ QList<IndexItem*> getIndexItems();
+
+ QString errorProtocol() const;
+ QString contentsURL() const { return conURL; }
+
+ virtual ParserVersion parserVersion() const = 0;
+ virtual void addTo( Profile *p ) = 0;
+
+ QString fileName() const { return fname; }
+ void setFileName( const QString &file ) { fname = file; }
+
+protected:
+ QString absolutify( const QString &input, bool makeUrl = true ) const;
+
+ QString contentRef, indexRef, errorProt, conURL;
+ QString docTitle, title, iconName;
+ QList<ContentItem> contentList;
+ QList<IndexItem*> indexList;
+ QString fname;
+};
+
+
+class DocuParser310 : public DocuParser
+{
+public:
+ enum States{ StateInit, StateContent, StateSect, StateKeyword };
+
+ bool startDocument();
+ bool startElement( const QString&, const QString&, const QString& ,
+ const QXmlAttributes& );
+ bool endElement( const QString&, const QString&, const QString& );
+ bool characters( const QString & );
+ bool fatalError( const QXmlParseException& exception );
+
+ virtual ParserVersion parserVersion() const { return Qt310; }
+ virtual void addTo( Profile *p );
+
+private:
+ States state;
+ int depth;
+};
+
+
+class DocuParser320 : public DocuParser
+{
+public:
+ enum States { StateInit, StateDocRoot, StateProfile, StateProperty,
+ StateContent, StateSect, StateKeyword };
+
+ DocuParser320();
+
+ bool startDocument();
+ bool startElement( const QString&, const QString&, const QString& ,
+ const QXmlAttributes& );
+ bool endElement( const QString&, const QString&, const QString& );
+ bool characters( const QString & );
+ bool fatalError( const QXmlParseException& exception );
+
+ virtual ParserVersion parserVersion() const { return Qt320; }
+ virtual void addTo( Profile *p );
+ Profile *profile() const { return prof; }
+
+private:
+
+ States state;
+ int depth;
+ int docfileCounter;
+ QString propertyValue;
+ QString propertyName;
+ Profile *prof;
+};
+
+QT_END_NAMESPACE
+
+#endif // DOCUPARSER_H
diff --git a/tools/assistant/compat/fontsettingsdialog.cpp b/tools/assistant/compat/fontsettingsdialog.cpp
new file mode 100644
index 0000000000..cd0cc06328
--- /dev/null
+++ b/tools/assistant/compat/fontsettingsdialog.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "fontsettingsdialog.h"
+#include "fontpanel.h"
+#include "config.h"
+
+#include <QtGui/QLabel>
+#include <QtGui/QComboBox>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QDialogButtonBox>
+
+QT_BEGIN_NAMESPACE
+
+FontSettingsDialog::FontSettingsDialog(QWidget *parent)
+ : QDialog(parent)
+ , m_windowFontPanel(new FontPanel(this))
+ , m_browserFontPanel(new FontPanel(this))
+ , m_dialogButtonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel))
+{
+ setModal(true);
+ setWindowTitle(tr("Font Settings"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QVBoxLayout *mainVLayout = new QVBoxLayout(this);
+ QHBoxLayout *hboxLayout = new QHBoxLayout;
+ mainVLayout->addLayout(hboxLayout);
+
+ QLabel *label = new QLabel(tr("Font settings for:"), this);
+ label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
+ hboxLayout->addWidget(label);
+ QComboBox *comboBox = new QComboBox(this);
+ comboBox->addItem(tr("Browser"));
+ comboBox->addItem(tr("Application"));
+ hboxLayout->addWidget(comboBox);
+
+ m_windowFontPanel->setCheckable(true);
+ m_browserFontPanel->setCheckable(true);
+
+ const QString customSettings(tr("Use custom settings"));
+ m_windowFontPanel->setTitle(customSettings);
+ m_browserFontPanel->setTitle(customSettings);
+
+ QStackedWidget *stackWidget = new QStackedWidget(this);
+ stackWidget->addWidget(m_browserFontPanel);
+ stackWidget->addWidget(m_windowFontPanel);
+
+ mainVLayout->addWidget(stackWidget);
+ mainVLayout->addWidget(m_dialogButtonBox);
+
+ connect(m_dialogButtonBox , SIGNAL(rejected()), this, SLOT(reject()));
+ connect(m_dialogButtonBox , SIGNAL(accepted()), this, SLOT(accept()));
+ connect(comboBox, SIGNAL(activated(int)), stackWidget, SLOT(setCurrentIndex(int)));
+}
+
+FontSettingsDialog::~FontSettingsDialog()
+{
+ // nothing todo
+}
+
+bool FontSettingsDialog::showDialog(FontSettings *settings)
+{
+ setupFontSettingsDialog(settings);
+
+ if (exec() != Accepted)
+ return false;
+
+ updateFontSettings(settings);
+ return true;
+}
+
+void FontSettingsDialog::updateFontSettings(FontSettings *settings)
+{
+ settings->useWindowFont = m_windowFontPanel->isChecked();
+ settings->useBrowserFont = m_browserFontPanel->isChecked();
+
+ settings->windowFont = settings->useWindowFont ? m_windowFontPanel->selectedFont() : qApp->font();
+ settings->browserFont = settings->useBrowserFont ? m_browserFontPanel->selectedFont() : qApp->font();
+
+ settings->windowWritingSystem = settings->useWindowFont ? m_windowFontPanel->writingSystem() : QFontDatabase::Latin;
+ settings->browserWritingSystem = settings->useBrowserFont ? m_browserFontPanel->writingSystem() : QFontDatabase::Latin;
+}
+
+void FontSettingsDialog::setupFontSettingsDialog(const FontSettings *settings)
+{
+ m_windowFontPanel->setSelectedFont(settings->windowFont);
+ m_browserFontPanel->setSelectedFont(settings->browserFont);
+
+ m_windowFontPanel->setWritingSystem(settings->windowWritingSystem);
+ m_browserFontPanel->setWritingSystem(settings->browserWritingSystem);
+
+ m_windowFontPanel->setChecked(settings->useWindowFont);
+ m_browserFontPanel->setChecked(settings->useBrowserFont);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/fontsettingsdialog.h b/tools/assistant/compat/fontsettingsdialog.h
new file mode 100644
index 0000000000..e4607aa786
--- /dev/null
+++ b/tools/assistant/compat/fontsettingsdialog.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef _FONT_SETTINGS_DIALOG_H_
+#define _FONT_SETTINGS_DIALOG_H_
+
+#include <QtCore/QObject>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class FontPanel;
+struct FontSettings;
+class QDialogButtonBox;
+
+class FontSettingsDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ FontSettingsDialog(QWidget *parent = 0);
+ ~FontSettingsDialog();
+
+ bool showDialog(FontSettings *settings);
+
+private:
+ void updateFontSettings(FontSettings *settings);
+ void setupFontSettingsDialog(const FontSettings *settings);
+
+private:
+ FontPanel *m_windowFontPanel;
+ FontPanel *m_browserFontPanel;
+ QDialogButtonBox *m_dialogButtonBox;
+};
+
+#endif // _FONT_SETTINGS_DIALOG_H_
+
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/helpdialog.cpp b/tools/assistant/compat/helpdialog.cpp
new file mode 100644
index 0000000000..4ea97d0ec8
--- /dev/null
+++ b/tools/assistant/compat/helpdialog.cpp
@@ -0,0 +1,1331 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "helpdialog.h"
+#include "helpwindow.h"
+#include "topicchooser.h"
+#include "docuparser.h"
+#include "mainwindow.h"
+#include "config.h"
+#include "tabbedbrowser.h"
+
+#include <QtGui>
+#include <QtDebug>
+#include <QtCore/QVarLengthArray>
+
+#include <stdlib.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+enum
+{
+ LinkRole = Qt::UserRole + 1000
+};
+
+static bool verifyDirectory(const QString &str)
+{
+ QFileInfo dirInfo(str);
+ if (!dirInfo.exists())
+ return QDir().mkdir(str);
+ if (!dirInfo.isDir()) {
+ qWarning("'%s' exists but is not a directory", str.toLatin1().constData());
+ return false;
+ }
+ return true;
+}
+
+struct IndexKeyword {
+ IndexKeyword(const QString &kw, const QString &l)
+ : keyword(kw), link(l) {}
+ IndexKeyword() : keyword(QString()), link(QString()) {}
+ bool operator<(const IndexKeyword &ik) const {
+ return keyword.toLower() < ik.keyword.toLower();
+ }
+ bool operator<=(const IndexKeyword &ik) const {
+ return keyword.toLower() <= ik.keyword.toLower();
+ }
+ bool operator>(const IndexKeyword &ik) const {
+ return keyword.toLower() > ik.keyword.toLower();
+ }
+ Q_DUMMY_COMPARISON_OPERATOR(IndexKeyword)
+ QString keyword;
+ QString link;
+};
+
+QDataStream &operator>>(QDataStream &s, IndexKeyword &ik)
+{
+ s >> ik.keyword;
+ s >> ik.link;
+ return s;
+}
+
+QDataStream &operator<<(QDataStream &s, const IndexKeyword &ik)
+{
+ s << ik.keyword;
+ s << ik.link;
+ return s;
+}
+
+QValidator::State SearchValidator::validate(QString &str, int &) const
+{
+ for (int i = 0; i < (int) str.length(); ++i) {
+ QChar c = str[i];
+ if (!c.isLetterOrNumber() && c != QLatin1Char('\'') && c != QLatin1Char('`')
+ && c != QLatin1Char('\"') && c != QLatin1Char(' ') && c != QLatin1Char('-') && c != QLatin1Char('_')
+ && c!= QLatin1Char('*'))
+ return QValidator::Invalid;
+ }
+ return QValidator::Acceptable;
+}
+
+class IndexListModel: public QStringListModel
+{
+public:
+ IndexListModel(QObject *parent = 0)
+ : QStringListModel(parent) {}
+
+ void clear() { contents.clear(); setStringList(QStringList()); }
+
+ QString description(int index) const { return stringList().at(index); }
+ QStringList links(int index) const { return contents.values(stringList().at(index)); }
+ void addLink(const QString &description, const QString &link) { contents.insert(description, link); }
+
+ void publish() { filter(QString(), QString()); }
+
+ QModelIndex filter(const QString &s, const QString &real);
+
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const
+ { return QStringListModel::flags(index) & ~Qt::ItemIsEditable; }
+
+private:
+ QMultiMap<QString, QString> contents;
+};
+
+bool caseInsensitiveLessThan(const QString &as, const QString &bs)
+{
+ const QChar *a = as.unicode();
+ const QChar *b = bs.unicode();
+ if (a == 0)
+ return true;
+ if (b == 0)
+ return false;
+ if (a == b)
+ return false;
+ int l=qMin(as.length(),bs.length());
+ while (l-- && QChar::toLower(a->unicode()) == QChar::toLower(b->unicode()))
+ a++,b++;
+ if (l==-1)
+ return (as.length() < bs.length());
+ return QChar::toLower(a->unicode()) < QChar::toLower(b->unicode());
+}
+
+/**
+ * \a real is kinda a hack for the smart search, need a way to match a regexp to an item
+ * How would you say the best match for Q.*Wiget is QWidget?
+ */
+QModelIndex IndexListModel::filter(const QString &s, const QString &real)
+{
+ QStringList list;
+
+ int goodMatch = -1;
+ int perfectMatch = -1;
+ if (s.isEmpty())
+ perfectMatch = 0;
+
+ const QRegExp regExp(s, Qt::CaseInsensitive);
+ QMultiMap<QString, QString>::iterator it = contents.begin();
+ QString lastKey;
+ for (; it != contents.end(); ++it) {
+ if (it.key() == lastKey)
+ continue;
+ lastKey = it.key();
+ const QString key = it.key();
+ if (key.contains(regExp) || key.contains(s, Qt::CaseInsensitive)) {
+ list.append(key);
+ if (perfectMatch == -1 && (key.startsWith(real, Qt::CaseInsensitive))) {
+ if (goodMatch == -1)
+ goodMatch = list.count() - 1;
+ if (real.length() == key.length()){
+ perfectMatch = list.count() - 1;
+ }
+ } else if (perfectMatch > -1 && s == key) {
+ perfectMatch = list.count() - 1;
+ }
+ }
+ }
+
+ int bestMatch = perfectMatch;
+ if (bestMatch == -1)
+ bestMatch = goodMatch;
+ bestMatch = qMax(0, bestMatch);
+
+ // sort the new list
+ QString match;
+ if (bestMatch >= 0 && list.count() > bestMatch)
+ match = list[bestMatch];
+ qSort(list.begin(), list.end(), caseInsensitiveLessThan);
+ setStringList(list);
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i) == match){
+ bestMatch = i;
+ break;
+ }
+ }
+ return index(bestMatch, 0, QModelIndex());
+}
+
+HelpNavigationListItem::HelpNavigationListItem(QListWidget *ls, const QString &txt)
+ : QListWidgetItem(txt, ls)
+{
+}
+
+void HelpNavigationListItem::addLink(const QString &link)
+{
+ QString lnk = HelpDialog::removeAnchorFromLink(link);
+ if (linkList.filter(lnk, Qt::CaseInsensitive).count() > 0)
+ return;
+ linkList << link;
+}
+
+HelpDialog::HelpDialog(QWidget *parent, MainWindow *h)
+ : QWidget(parent), lwClosed(false), help(h)
+{
+ ui.setupUi(this);
+ ui.listContents->setUniformRowHeights(true);
+ ui.listContents->header()->setStretchLastSection(false);
+ ui.listContents->header()->setResizeMode(QHeaderView::ResizeToContents);
+ ui.listBookmarks->setUniformRowHeights(true);
+ ui.listBookmarks->header()->setStretchLastSection(false);
+ ui.listBookmarks->header()->setResizeMode(QHeaderView::ResizeToContents);
+
+ indexModel = new IndexListModel(this);
+ ui.listIndex->setModel(indexModel);
+ ui.listIndex->setLayoutMode(QListView::Batched);
+ ui.listBookmarks->setItemHidden(ui.listBookmarks->headerItem(), true);
+ ui.listContents->setItemHidden(ui.listContents->headerItem(), true);
+ ui.searchButton->setShortcut(QKeySequence(Qt::ALT|Qt::SHIFT|Qt::Key_S));
+}
+
+void HelpDialog::initialize()
+{
+ connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
+
+ connect(ui.listContents, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(showTopic(QTreeWidgetItem*)));
+ connect(ui.listContents, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showTreeItemMenu(QPoint)));
+ ui.listContents->viewport()->installEventFilter(this);
+
+ connect(ui.editIndex, SIGNAL(returnPressed()), this, SLOT(showTopic()));
+ connect(ui.editIndex, SIGNAL(textEdited(QString)), this, SLOT(searchInIndex(QString)));
+
+ connect(ui.listIndex, SIGNAL(activated(QModelIndex)), this, SLOT(showTopic()));
+ connect(ui.listIndex, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showIndexItemMenu(QPoint)));
+
+ connect(ui.listBookmarks, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(showTopic(QTreeWidgetItem*)));
+ connect(ui.listBookmarks, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showTreeItemMenu(QPoint)));
+
+ connect(ui.termsEdit, SIGNAL(textChanged(const QString&)), this, SLOT(updateSearchButton(const QString&)));
+
+ connect(ui.resultBox, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showListItemMenu(QPoint)));
+
+ cacheFilesPath = QDir::homePath() + QLatin1String("/.assistant"); //### Find a better location for the dbs
+
+ ui.editIndex->installEventFilter(this);
+
+ ui.framePrepare->hide();
+ connect(qApp, SIGNAL(lastWindowClosed()), SLOT(lastWinClosed()));
+
+ ui.termsEdit->setValidator(new SearchValidator(ui.termsEdit));
+
+ actionOpenCurrentTab = new QAction(this);
+ actionOpenCurrentTab->setText(tr("Open Link in Current Tab"));
+
+ actionOpenLinkInNewWindow = new QAction(this);
+ actionOpenLinkInNewWindow->setText(tr("Open Link in New Window"));
+
+ actionOpenLinkInNewTab = new QAction(this);
+ actionOpenLinkInNewTab->setText(tr("Open Link in New Tab"));
+
+ itemPopup = new QMenu(this);
+ itemPopup->addAction(actionOpenCurrentTab);
+ itemPopup->addAction(actionOpenLinkInNewWindow);
+ itemPopup->addAction(actionOpenLinkInNewTab);
+
+ ui.tabWidget->setElideMode(Qt::ElideNone);
+
+ contentList.clear();
+
+ initDoneMsgShown = false;
+ fullTextIndex = 0;
+ indexDone = false;
+ titleMapDone = false;
+ contentsInserted = false;
+ bookmarksInserted = false;
+ setupTitleMap();
+
+}
+
+void HelpDialog::processEvents()
+{
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
+}
+
+
+void HelpDialog::lastWinClosed()
+{
+ lwClosed = true;
+}
+
+void HelpDialog::removeOldCacheFiles(bool onlyFulltextSearchIndex)
+{
+ if (!verifyDirectory(cacheFilesPath)) {
+ qWarning("Failed to created assistant directory");
+ return;
+ }
+ QString pname = QLatin1String(".") + Config::configuration()->profileName();
+
+ QStringList fileList;
+ fileList << QLatin1String("indexdb40.dict")
+ << QLatin1String("indexdb40.doc");
+
+ if (!onlyFulltextSearchIndex)
+ fileList << QLatin1String("indexdb40") << QLatin1String("contentdb40");
+
+ QStringList::iterator it = fileList.begin();
+ for (; it != fileList.end(); ++it) {
+ if (QFile::exists(cacheFilesPath + QDir::separator() + *it + pname)) {
+ QFile f(cacheFilesPath + QDir::separator() + *it + pname);
+ f.remove();
+ }
+ }
+}
+
+void HelpDialog::timerEvent(QTimerEvent *e)
+{
+ Q_UNUSED(e);
+ static int opacity = 255;
+ help->setWindowOpacity((opacity-=4)/255.0);
+ if (opacity<=0)
+ qApp->quit();
+}
+
+
+void HelpDialog::loadIndexFile()
+{
+ if (indexDone)
+ return;
+
+ setCursor(Qt::WaitCursor);
+ indexDone = true;
+ ui.labelPrepare->setText(tr("Prepare..."));
+ ui.framePrepare->show();
+ processEvents();
+
+ QProgressBar *bar = ui.progressPrepare;
+ bar->setMaximum(100);
+ bar->setValue(0);
+
+ keywordDocuments.clear();
+ QList<IndexKeyword> lst;
+ QFile indexFile(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.") +
+ Config::configuration()->profileName());
+ if (!indexFile.open(QFile::ReadOnly)) {
+ buildKeywordDB();
+ processEvents();
+ if (lwClosed)
+ return;
+ if (!indexFile.open(QFile::ReadOnly)) {
+ QMessageBox::warning(help, tr("Qt Assistant"), tr("Failed to load keyword index file\n"
+ "Assistant will not work!"));
+#if defined Q_WS_WIN || defined Q_WS_MACX
+ startTimer(50);
+#endif
+ return;
+ }
+ }
+
+ QDataStream ds(&indexFile);
+ quint32 fileAges;
+ ds >> fileAges;
+ if (fileAges != getFileAges()) {
+ indexFile.close();
+ buildKeywordDB();
+ if (!indexFile.open(QFile::ReadOnly)) {
+ QMessageBox::warning(help, tr("Qt Assistant"),
+ tr("Cannot open the index file %1").arg(QFileInfo(indexFile).absoluteFilePath()));
+ return;
+ }
+ ds.setDevice(&indexFile);
+ ds >> fileAges;
+ }
+ ds >> lst;
+ indexFile.close();
+
+ bar->setValue(bar->maximum());
+ processEvents();
+
+ for (int i=0; i<lst.count(); ++i) {
+ const IndexKeyword &idx = lst.at(i);
+ indexModel->addLink(idx.keyword, idx.link);
+
+ keywordDocuments << HelpDialog::removeAnchorFromLink(idx.link);
+ }
+
+ indexModel->publish();
+
+ ui.framePrepare->hide();
+ showInitDoneMessage();
+ setCursor(Qt::ArrowCursor);
+}
+
+quint32 HelpDialog::getFileAges()
+{
+ QStringList addDocuFiles = Config::configuration()->docFiles();
+ QStringList::const_iterator i = addDocuFiles.constBegin();
+
+ quint32 fileAges = 0;
+ for (; i != addDocuFiles.constEnd(); ++i) {
+ QFileInfo fi(*i);
+ if (fi.exists())
+ fileAges += fi.lastModified().toTime_t();
+ }
+
+ return fileAges;
+}
+
+void HelpDialog::buildKeywordDB()
+{
+ QStringList addDocuFiles = Config::configuration()->docFiles();
+ QStringList::iterator i = addDocuFiles.begin();
+
+ // Set up an indeterminate progress bar.
+ ui.labelPrepare->setText(tr("Prepare..."));
+ ui.progressPrepare->setMaximum(0);
+ ui.progressPrepare->setMinimum(0);
+ ui.progressPrepare->setValue(0);
+ processEvents();
+
+ QList<IndexKeyword> lst;
+ quint32 fileAges = 0;
+ for (i = addDocuFiles.begin(); i != addDocuFiles.end(); ++i) {
+ QFile file(*i);
+ if (!file.exists()) {
+ QMessageBox::warning(this, tr("Warning"),
+ tr("Documentation file %1 does not exist!\n"
+ "Skipping file.").arg(QFileInfo(file).absoluteFilePath()));
+ continue;
+ }
+ fileAges += QFileInfo(file).lastModified().toTime_t();
+ DocuParser *handler = DocuParser::createParser(*i);
+ bool ok = handler->parse(&file);
+ file.close();
+ if (!ok){
+ QString msg = QString::fromLatin1("In file %1:\n%2")
+ .arg(QFileInfo(file).absoluteFilePath())
+ .arg(handler->errorProtocol());
+ QMessageBox::critical(this, tr("Parse Error"), tr(msg.toUtf8()));
+ delete handler;
+ continue;
+ }
+
+ QList<IndexItem*> indLst = handler->getIndexItems();
+ int counter = 0;
+ foreach (IndexItem *indItem, indLst) {
+ QFileInfo fi(indItem->reference);
+ lst.append(IndexKeyword(indItem->keyword, indItem->reference));
+
+ if (++counter%100 == 0) {
+ if (ui.progressPrepare)
+ ui.progressPrepare->setValue(counter);
+ processEvents();
+ if (lwClosed) {
+ return;
+ }
+ }
+ }
+ delete handler;
+ }
+ if (!lst.isEmpty())
+ qSort(lst);
+
+ QFile indexout(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.")
+ + Config::configuration()->profileName());
+ if (verifyDirectory(cacheFilesPath) && indexout.open(QFile::WriteOnly)) {
+ QDataStream s(&indexout);
+ s << fileAges;
+ s << lst;
+ indexout.close();
+ }
+}
+
+void HelpDialog::setupTitleMap()
+{
+ if (titleMapDone)
+ return;
+
+ bool needRebuild = false;
+ if (Config::configuration()->profileName() == QLatin1String("default")) {
+ const QStringList docuFiles = Config::configuration()->docFiles();
+ for (QStringList::ConstIterator it = docuFiles.begin(); it != docuFiles.end(); ++it) {
+ if (!QFile::exists(*it)) {
+ Config::configuration()->saveProfile(Profile::createDefaultProfile());
+ Config::configuration()->loadDefaultProfile();
+ needRebuild = true;
+ break;
+ }
+ }
+ }
+
+ if (Config::configuration()->docRebuild() || needRebuild) {
+ removeOldCacheFiles();
+ Config::configuration()->setDocRebuild(false);
+ Config::configuration()->saveProfile(Config::configuration()->profile());
+ }
+ if (contentList.isEmpty())
+ getAllContents();
+
+ titleMapDone = true;
+ titleMap.clear();
+ for (QList<QPair<QString, ContentList> >::Iterator it = contentList.begin(); it != contentList.end(); ++it) {
+ ContentList lst = (*it).second;
+ foreach (ContentItem item, lst) {
+ titleMap[item.reference] = item.title.trimmed();
+ }
+ }
+ processEvents();
+}
+
+void HelpDialog::getAllContents()
+{
+ QFile contentFile(cacheFilesPath + QDir::separator() + QLatin1String("contentdb40.")
+ + Config::configuration()->profileName());
+ contentList.clear();
+ if (!contentFile.open(QFile::ReadOnly)) {
+ buildContentDict();
+ return;
+ }
+
+ QDataStream ds(&contentFile);
+ quint32 fileAges;
+ ds >> fileAges;
+ if (fileAges != getFileAges()) {
+ contentFile.close();
+ removeOldCacheFiles(true);
+ buildContentDict();
+ return;
+ }
+ QString key;
+ QList<ContentItem> lst;
+ while (!ds.atEnd()) {
+ ds >> key;
+ ds >> lst;
+ contentList += qMakePair(key, QList<ContentItem>(lst));
+ }
+ contentFile.close();
+ processEvents();
+
+}
+
+void HelpDialog::buildContentDict()
+{
+ QStringList docuFiles = Config::configuration()->docFiles();
+
+ quint32 fileAges = 0;
+ for (QStringList::iterator it = docuFiles.begin(); it != docuFiles.end(); ++it) {
+ QFile file(*it);
+ if (!file.exists()) {
+ QMessageBox::warning(this, tr("Warning"),
+ tr("Documentation file %1 does not exist!\n"
+ "Skipping file.").arg(QFileInfo(file).absoluteFilePath()));
+ continue;
+ }
+ fileAges += QFileInfo(file).lastModified().toTime_t();
+ DocuParser *handler = DocuParser::createParser(*it);
+ if (!handler) {
+ QMessageBox::warning(this, tr("Warning"),
+ tr("Documentation file %1 is not compatible!\n"
+ "Skipping file.").arg(QFileInfo(file).absoluteFilePath()));
+ continue;
+ }
+ bool ok = handler->parse(&file);
+ file.close();
+ if (ok) {
+ contentList += qMakePair(*it, QList<ContentItem>(handler->getContentItems()));
+ delete handler;
+ } else {
+ QString msg = QString::fromLatin1("In file %1:\n%2")
+ .arg(QFileInfo(file).absoluteFilePath())
+ .arg(handler->errorProtocol());
+ QMessageBox::critical(this, tr("Parse Error"), tr(msg.toUtf8()));
+ continue;
+ }
+ }
+
+ QFile contentOut(cacheFilesPath + QDir::separator() + QLatin1String("contentdb40.")
+ + Config::configuration()->profileName());
+ if (contentOut.open(QFile::WriteOnly)) {
+ QDataStream s(&contentOut);
+ s << fileAges;
+ for (QList<QPair<QString, ContentList> >::Iterator it = contentList.begin(); it != contentList.end(); ++it) {
+ s << *it;
+ }
+ contentOut.close();
+ }
+}
+
+void HelpDialog::currentTabChanged(int index)
+{
+ QString s = ui.tabWidget->widget(index)->objectName();
+ if (s == QLatin1String("indexPage"))
+ QTimer::singleShot(0, this, SLOT(loadIndexFile()));
+ else if (s == QLatin1String("bookmarkPage"))
+ insertBookmarks();
+ else if (s == QLatin1String("contentPage"))
+ QTimer::singleShot(0, this, SLOT(insertContents()));
+ else if (s == QLatin1String("searchPage"))
+ QTimer::singleShot(0, this, SLOT(setupFullTextIndex()));
+}
+
+void HelpDialog::showInitDoneMessage()
+{
+ if (initDoneMsgShown)
+ return;
+ initDoneMsgShown = true;
+ help->statusBar()->showMessage(tr("Done"), 3000);
+}
+
+void HelpDialog::showTopic(QTreeWidgetItem *item)
+{
+ if (item)
+ showTopic();
+}
+
+void HelpDialog::showTopic()
+{
+ QString tabName = ui.tabWidget->currentWidget()->objectName();
+
+ if (tabName == QLatin1String("indexPage"))
+ showIndexTopic();
+ else if (tabName == QLatin1String("bookmarkPage"))
+ showBookmarkTopic();
+ else if (tabName == QLatin1String("contentPage"))
+ showContentsTopic();
+}
+
+void HelpDialog::showIndexTopic()
+{
+ int row = ui.listIndex->currentIndex().row();
+ if (row == -1 || row >= indexModel->rowCount())
+ return;
+
+ QString description = indexModel->description(row);
+ QStringList links = indexModel->links(row);
+
+ bool blocked = ui.editIndex->blockSignals(true);
+ ui.editIndex->setText(description);
+ ui.editIndex->blockSignals(blocked);
+
+ if (links.count() == 1) {
+ emit showLink(links.first());
+ } else {
+ qSort(links);
+ QStringList::Iterator it = links.begin();
+ QStringList linkList;
+ QStringList linkNames;
+ for (; it != links.end(); ++it) {
+ linkList << *it;
+ linkNames << titleOfLink(*it);
+ }
+ QString link = TopicChooser::getLink(this, linkNames, linkList, description);
+ if (!link.isEmpty())
+ emit showLink(link);
+ }
+
+ ui.listIndex->setCurrentIndex(indexModel->index(indexModel->stringList().indexOf(description)));
+ ui.listIndex->scrollTo(ui.listIndex->currentIndex(), QAbstractItemView::PositionAtTop);
+}
+
+void HelpDialog::searchInIndex(const QString &searchString)
+{
+ QRegExp atoz(QLatin1String("[A-Z]"));
+ int matches = searchString.count(atoz);
+ if (matches > 0 && !searchString.contains(QLatin1String(".*")))
+ {
+ int start = 0;
+ QString newSearch;
+ for (; matches > 0; --matches) {
+ int match = searchString.indexOf(atoz, start+1);
+ if (match <= start)
+ continue;
+ newSearch += searchString.mid(start, match-start);
+ newSearch += QLatin1String(".*");
+ start = match;
+ }
+ newSearch += searchString.mid(start);
+ ui.listIndex->setCurrentIndex(indexModel->filter(newSearch, searchString));
+ }
+ else
+ ui.listIndex->setCurrentIndex(indexModel->filter(searchString, searchString));
+}
+
+QString HelpDialog::titleOfLink(const QString &link)
+{
+ QString s = HelpDialog::removeAnchorFromLink(link);
+ s = titleMap[s];
+ if (s.isEmpty())
+ return link;
+ return s;
+}
+
+bool HelpDialog::eventFilter(QObject * o, QEvent * e)
+{
+ if (o == ui.editIndex && e->type() == QEvent::KeyPress) {
+ switch (static_cast<QKeyEvent*>(e)->key()) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_PageDown:
+ case Qt::Key_PageUp:
+ QApplication::sendEvent(ui.listIndex, e);
+ break;
+
+ default:
+ break;
+ }
+ } else if (o == ui.listContents->viewport()) {
+ if (e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ if (me->button() == Qt::LeftButton) {
+ QTreeWidgetItem *item = ui.listContents->itemAt(me->pos());
+ QRect vRect = ui.listContents->visualItemRect(item);
+
+ // only show topic if we clicked an item
+ if (item && vRect.contains(me->pos()))
+ showTopic(item);
+ }
+ }
+ }
+
+ return QWidget::eventFilter(o, e);
+}
+
+void HelpDialog::addBookmark()
+{
+ if (!bookmarksInserted)
+ insertBookmarks();
+ QString link = help->browsers()->currentBrowser()->source().toString();
+ QString title = help->browsers()->currentBrowser()->documentTitle();
+ if (title.isEmpty())
+ title = titleOfLink(link);
+
+ QTreeWidgetItem *i = new QTreeWidgetItem(ui.listBookmarks, 0);
+ i->setText(0, title);
+ i->setData(0, LinkRole, link);
+ ui.buttonRemove->setEnabled(true);
+ saveBookmarks();
+ help->updateBookmarkMenu();
+}
+
+void HelpDialog::on_buttonAdd_clicked()
+{
+ addBookmark();
+}
+
+void HelpDialog::on_buttonRemove_clicked()
+{
+ if (!ui.listBookmarks->currentItem())
+ return;
+
+ delete ui.listBookmarks->currentItem();
+ saveBookmarks();
+ if (ui.listBookmarks->topLevelItemCount() != 0) {
+ ui.listBookmarks->setCurrentItem(ui.listBookmarks->topLevelItem(0));
+ }
+ ui.buttonRemove->setEnabled(ui.listBookmarks->topLevelItemCount() > 0);
+ help->updateBookmarkMenu();
+}
+
+void HelpDialog::insertBookmarks()
+{
+ if (bookmarksInserted)
+ return;
+ bookmarksInserted = true;
+ ui.listBookmarks->clear();
+ QFile f(cacheFilesPath + QDir::separator() + QLatin1String("bookmarks.")
+ + Config::configuration()->profileName());
+ if (!f.open(QFile::ReadOnly))
+ return;
+ QTextStream ts(&f);
+ while (!ts.atEnd()) {
+ QTreeWidgetItem *i = new QTreeWidgetItem(ui.listBookmarks, 0);
+ i->setText(0, ts.readLine());
+ i->setData(0, LinkRole, ts.readLine());
+ }
+ ui.buttonRemove->setEnabled(ui.listBookmarks->topLevelItemCount() > 0);
+ help->updateBookmarkMenu();
+ showInitDoneMessage();
+}
+
+void HelpDialog::showBookmarkTopic()
+{
+ if (!ui.listBookmarks->currentItem())
+ return;
+
+ QTreeWidgetItem *i = (QTreeWidgetItem*)ui.listBookmarks->currentItem();
+ emit showLink(i->data(0, LinkRole).toString());
+}
+
+static void store(QTreeWidgetItem *i, QTextStream &ts)
+{
+ ts << i->text(0) << endl;
+ ts << i->data(0, LinkRole).toString() << endl;
+
+ for (int index = 0; index < i->childCount(); ++index)
+ store(i->child(index), ts);
+}
+
+static void store(QTreeWidget *tw, QTextStream &ts)
+{
+ for (int index = 0; index < tw->topLevelItemCount(); ++index)
+ store(tw->topLevelItem(index), ts);
+}
+
+void HelpDialog::saveBookmarks()
+{
+ QFile f(cacheFilesPath + QDir::separator() + QLatin1String("bookmarks.")
+ + Config::configuration()->profileName());
+ if (!f.open(QFile::WriteOnly))
+ return;
+
+ QTextStream ts(&f);
+ store(ui.listBookmarks, ts);
+ f.close();
+}
+
+void HelpDialog::insertContents()
+{
+#ifdef Q_WS_MAC
+ static const QLatin1String IconPath(":/trolltech/assistant/images/mac/book.png");
+#else
+ static const QLatin1String IconPath(":/trolltech/assistant/images/win/book.png");
+#endif
+ if (contentsInserted)
+ return;
+
+ if (contentList.isEmpty())
+ getAllContents();
+
+ contentsInserted = true;
+ ui.listContents->clear();
+ setCursor(Qt::WaitCursor);
+ if (!titleMapDone)
+ setupTitleMap();
+
+#if 0 // ### port me
+ ui.listContents->setSorting(-1);
+#endif
+
+ for (QList<QPair<QString, ContentList> >::Iterator it = contentList.begin(); it != contentList.end(); ++it) {
+ QTreeWidgetItem *newEntry = 0;
+
+ QTreeWidgetItem *contentEntry = 0;
+ QStack<QTreeWidgetItem*> stack;
+ stack.clear();
+ int depth = 0;
+ bool root = false;
+
+ const int depthSize = 32;
+ QVarLengthArray<QTreeWidgetItem*, depthSize> lastItem(depthSize);
+
+ ContentList lst = (*it).second;
+ for (ContentList::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
+ ContentItem item = *it;
+ if (item.depth == 0) {
+ lastItem[0] = 0;
+ newEntry = new QTreeWidgetItem(ui.listContents, 0);
+ newEntry->setIcon(0, QIcon(IconPath));
+ newEntry->setText(0, item.title);
+ newEntry->setData(0, LinkRole, item.reference);
+ stack.push(newEntry);
+ depth = 1;
+ root = true;
+ }
+ else{
+ if ((item.depth > depth) && root) {
+ depth = item.depth;
+ stack.push(contentEntry);
+ }
+ if (item.depth == depth) {
+ if (lastItem.capacity() == depth)
+ lastItem.resize(depth + depthSize);
+ contentEntry = new QTreeWidgetItem(stack.top(), lastItem[ depth ]);
+ lastItem[ depth ] = contentEntry;
+ contentEntry->setText(0, item.title);
+ contentEntry->setData(0, LinkRole, item.reference);
+ }
+ else if (item.depth < depth) {
+ stack.pop();
+ depth--;
+ item = *(--it);
+ }
+ }
+ }
+ processEvents();
+ }
+ setCursor(Qt::ArrowCursor);
+ showInitDoneMessage();
+}
+
+void HelpDialog::showContentsTopic()
+{
+ QTreeWidgetItem *i = (QTreeWidgetItem*)ui.listContents->currentItem();
+ if (!i)
+ return;
+ emit showLink(i->data(0, LinkRole).toString());
+}
+
+QTreeWidgetItem * HelpDialog::locateLink(QTreeWidgetItem *item, const QString &link)
+{
+ QTreeWidgetItem *child = 0;
+#ifdef Q_OS_WIN
+ Qt::CaseSensitivity checkCase = Qt::CaseInsensitive;
+#else
+ Qt::CaseSensitivity checkCase = Qt::CaseSensitive;
+#endif
+ for (int i = 0, childCount = item->childCount(); i<childCount; i++) {
+ child = item->child(i);
+ ///check whether it is this item
+ if (link.startsWith(child->data(0, LinkRole).toString(), checkCase))
+ break;
+ //check if the link is a child of this item
+ else if (child->childCount()) {
+ child = locateLink(child, link);
+ if (child)
+ break;
+ }
+ child = 0;
+ }
+ return child;
+}
+
+void HelpDialog::locateContents(const QString &link)
+{
+ //ensure the TOC is filled
+ if (!contentsInserted)
+ insertContents();
+#ifdef Q_OS_WIN
+ Qt::CaseSensitivity checkCase = Qt::CaseInsensitive;
+#else
+ Qt::CaseSensitivity checkCase = Qt::CaseSensitive;
+#endif
+ QString findLink(link);
+ //Installations on a windows local drive will give the 'link' as <file:///C:/xxx>
+ //and the contents in the TOC will be <file:C:/xxx>.
+ //But on others the 'link' of format <file:///root/xxx>
+ //and the contents in the TOC will be <file:/root/xxx>.
+ if (findLink.contains(QLatin1String("file:///"))) {
+ if (findLink[9] == QLatin1Char(':')) //on windows drives
+ findLink.replace(0, 8, QLatin1String("file:"));
+ else
+ findLink.replace(0, 8, QLatin1String("file:/"));
+ }
+
+ bool topLevel = false;
+ QTreeWidgetItem *item = 0;
+ int totalItems = ui.listContents->topLevelItemCount();
+
+ for (int i = 0; i < totalItems; i++ ) {
+ // first see if we are one of the top level items
+ item = (QTreeWidgetItem*)ui.listContents->topLevelItem(i);
+ if (findLink.startsWith(item->data(0, LinkRole).toString(), checkCase)) {
+ topLevel = true;
+ break;
+ }
+ }
+
+ if (!topLevel) {
+ // now try to find it in the sublevel items
+ for (int n = 0; n < totalItems; ++n) {
+ item = (QTreeWidgetItem*)ui.listContents->topLevelItem(n);
+ item = locateLink(item, findLink);
+ if (item)
+ break;
+ }
+ }
+
+ //remove the old selection
+ QList<QTreeWidgetItem *> selected = ui.listContents->selectedItems();
+ foreach(QTreeWidgetItem *sel, selected)
+ ui.listContents->setItemSelected(sel, false);
+
+ //set the TOC item and show
+ ui.listContents->setCurrentItem(item);
+ ui.listContents->setItemSelected(item, true);
+ ui.listContents->scrollToItem(item);
+}
+
+void HelpDialog::toggleContents()
+{
+ if (!isVisible() || ui.tabWidget->currentIndex() != 0) {
+ ui.tabWidget->setCurrentIndex(0);
+ parentWidget()->show();
+ }
+ else
+ parentWidget()->hide();
+}
+
+void HelpDialog::toggleIndex()
+{
+ if (!isVisible() || ui.tabWidget->currentIndex() != 1 || !ui.editIndex->hasFocus()) {
+ ui.tabWidget->setCurrentIndex(1);
+ parentWidget()->show();
+ ui.editIndex->setFocus();
+ }
+ else
+ parentWidget()->hide();
+}
+
+void HelpDialog::toggleBookmarks()
+{
+ if (!isVisible() || ui.tabWidget->currentIndex() != 2) {
+ ui.tabWidget->setCurrentIndex(2);
+ parentWidget()->show();
+ }
+ else
+ parentWidget()->hide();
+}
+
+void HelpDialog::toggleSearch()
+{
+ if (!isVisible() || ui.tabWidget->currentIndex() != 3) {
+ ui.tabWidget->setCurrentIndex(3);
+ parentWidget()->show();
+ }
+ else
+ parentWidget()->hide();
+}
+
+void HelpDialog::setupFullTextIndex()
+{
+ if (fullTextIndex)
+ return;
+
+ QString pname = Config::configuration()->profileName();
+ fullTextIndex = new Index(QStringList(), QDir::homePath()); // ### Is this correct ?
+ if (!verifyDirectory(cacheFilesPath)) {
+ QMessageBox::warning(help, tr("Qt Assistant"),
+ tr("Failed to save fulltext search index\n"
+ "Assistant will not work!"));
+ return;
+ }
+ fullTextIndex->setDictionaryFile(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.dict.") + pname);
+ fullTextIndex->setDocListFile(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.doc.") + pname);
+ processEvents();
+
+ connect(fullTextIndex, SIGNAL(indexingProgress(int)),
+ this, SLOT(setIndexingProgress(int)));
+ QFile f(cacheFilesPath + QDir::separator() + QLatin1String("indexdb40.dict.") + pname);
+ if (!f.exists()) {
+ QString doc;
+ QSet<QString> documentSet;
+ QMap<QString, QString>::ConstIterator it = titleMap.constBegin();
+ for (; it != titleMap.constEnd(); ++it) {
+ doc = HelpDialog::removeAnchorFromLink(it.key());
+ if (!doc.isEmpty())
+ documentSet.insert(doc);
+ }
+ loadIndexFile();
+ for ( QStringList::Iterator it = keywordDocuments.begin(); it != keywordDocuments.end(); ++it ) {
+ if (!(*it).isEmpty())
+ documentSet.insert(*it);
+ }
+ fullTextIndex->setDocList( documentSet.toList() );
+
+ help->statusBar()->clearMessage();
+ setCursor(Qt::WaitCursor);
+ ui.labelPrepare->setText(tr("Indexing files..."));
+ ui.progressPrepare->setMaximum(100);
+ ui.progressPrepare->reset();
+ ui.progressPrepare->show();
+ ui.framePrepare->show();
+ processEvents();
+ if (fullTextIndex->makeIndex() == -1)
+ return;
+ fullTextIndex->writeDict();
+ ui.progressPrepare->setValue(100);
+ ui.framePrepare->hide();
+ setCursor(Qt::ArrowCursor);
+ showInitDoneMessage();
+ } else {
+ setCursor(Qt::WaitCursor);
+ help->statusBar()->showMessage(tr("Reading dictionary..."));
+ processEvents();
+ fullTextIndex->readDict();
+ help->statusBar()->showMessage(tr("Done"), 3000);
+ setCursor(Qt::ArrowCursor);
+ }
+ keywordDocuments.clear();
+}
+
+void HelpDialog::setIndexingProgress(int prog)
+{
+ ui.progressPrepare->setValue(prog);
+ processEvents();
+}
+
+void HelpDialog::startSearch()
+{
+ QString str = ui.termsEdit->text();
+ str = str.simplified();
+ str = str.replace(QLatin1String("\'"), QLatin1String("\""));
+ str = str.replace(QLatin1String("`"), QLatin1String("\""));
+ QString buf = str;
+ str = str.replace(QLatin1String("-"), QLatin1String(" "));
+ str = str.replace(QRegExp(QLatin1String("\\s[\\S]?\\s")), QLatin1String(" "));
+ terms = str.split(QLatin1Char(' '));
+ QStringList termSeq;
+ QStringList seqWords;
+ QStringList::iterator it = terms.begin();
+ for (; it != terms.end(); ++it) {
+ (*it) = (*it).simplified();
+ (*it) = (*it).toLower();
+ (*it) = (*it).replace(QLatin1String("\""), QLatin1String(""));
+ }
+ if (str.contains(QLatin1Char('\"'))) {
+ if ((str.count(QLatin1Char('\"')))%2 == 0) {
+ int beg = 0;
+ int end = 0;
+ QString s;
+ beg = str.indexOf(QLatin1Char('\"'), beg);
+ while (beg != -1) {
+ beg++;
+ end = str.indexOf(QLatin1Char('\"'), beg);
+ s = str.mid(beg, end - beg);
+ s = s.toLower();
+ s = s.simplified();
+ if (s.contains(QLatin1Char('*'))) {
+ QMessageBox::warning(this, tr("Full Text Search"),
+ tr("Using a wildcard within phrases is not allowed."));
+ return;
+ }
+ seqWords += s.split(QLatin1Char(' '));
+ termSeq << s;
+ beg = str.indexOf(QLatin1Char('\"'), end + 1);
+ }
+ } else {
+ QMessageBox::warning(this, tr("Full Text Search"),
+ tr("The closing quotation mark is missing."));
+ return;
+ }
+ }
+ setCursor(Qt::WaitCursor);
+ foundDocs.clear();
+ foundDocs = fullTextIndex->query(terms, termSeq, seqWords);
+ QString msg = tr("%n document(s) found.", "", foundDocs.count());
+ help->statusBar()->showMessage(tr(msg.toUtf8()), 3000);
+ ui.resultBox->clear();
+ for (it = foundDocs.begin(); it != foundDocs.end(); ++it)
+ ui.resultBox->addItem(fullTextIndex->getDocumentTitle(*it));
+
+ terms.clear();
+ bool isPhrase = false;
+ QString s;
+ for (int i = 0; i < (int)buf.length(); ++i) {
+ if (buf[i] == QLatin1Char('\"')) {
+ isPhrase = !isPhrase;
+ s = s.simplified();
+ if (!s.isEmpty())
+ terms << s;
+ s = QLatin1String("");
+ } else if (buf[i] == QLatin1Char(' ') && !isPhrase) {
+ s = s.simplified();
+ if (!s.isEmpty())
+ terms << s;
+ s = QLatin1String("");
+ } else
+ s += buf[i];
+ }
+ if (!s.isEmpty())
+ terms << s;
+
+ setCursor(Qt::ArrowCursor);
+}
+
+void HelpDialog::on_helpButton_clicked()
+{
+ emit showLink(MainWindow::urlifyFileName(
+ Config::configuration()->assistantDocPath() +
+ QLatin1String("/assistant-manual.html#full-text-searching")));
+}
+
+void HelpDialog::on_resultBox_itemActivated(QListWidgetItem *item)
+{
+ showResultPage(item);
+}
+
+void HelpDialog::showResultPage(QListWidgetItem *item)
+{
+ if (item)
+ emit showSearchLink(foundDocs[ui.resultBox->row(item)], terms);
+}
+
+void HelpDialog::showIndexItemMenu(const QPoint &pos)
+{
+ QListView *listView = qobject_cast<QListView*>(sender());
+ if (!listView)
+ return;
+
+ QModelIndex idx = listView->indexAt(pos);
+ if (!idx.isValid())
+ return;
+
+ QAction *action = itemPopup->exec(listView->viewport()->mapToGlobal(pos));
+ if (action == actionOpenCurrentTab) {
+ showTopic();
+ } else if (action) {
+ HelpWindow *hw = help->browsers()->currentBrowser();
+ QString itemName = idx.data().toString();
+ ui.editIndex->setText(itemName);
+ QStringList links = indexModel->links(idx.row());
+ if (links.count() == 1) {
+ if (action == actionOpenLinkInNewWindow)
+ hw->openLinkInNewWindow(links.first());
+ else
+ hw->openLinkInNewPage(links.first());
+ } else {
+ QStringList::Iterator it = links.begin();
+ QStringList linkList;
+ QStringList linkNames;
+ for (; it != links.end(); ++it) {
+ linkList << *it;
+ linkNames << titleOfLink(*it);
+ }
+ QString link = TopicChooser::getLink(this, linkNames, linkList, itemName);
+ if (!link.isEmpty()) {
+ if (action == actionOpenLinkInNewWindow)
+ hw->openLinkInNewWindow(link);
+ else
+ hw->openLinkInNewPage(link);
+ }
+ }
+ }
+}
+
+void HelpDialog::showListItemMenu(const QPoint &pos)
+{
+ QListWidget *listWidget = qobject_cast<QListWidget*>(sender());
+ if (!listWidget)
+ return;
+ QListWidgetItem *item = listWidget->itemAt(pos);
+ if (!item)
+ return;
+
+ QAction *action = itemPopup->exec(listWidget->viewport()->mapToGlobal(pos));
+ if (action == actionOpenCurrentTab) {
+ showResultPage(item);
+ } else if (action) {
+ HelpWindow *hw = help->browsers()->currentBrowser();
+ QString link = foundDocs[ui.resultBox->row(item)];
+ if (action == actionOpenLinkInNewWindow)
+ hw->openLinkInNewWindow(link);
+ else
+ hw->openLinkInNewPage(link);
+ }
+}
+
+void HelpDialog::showTreeItemMenu(const QPoint &pos)
+{
+ QTreeWidget *treeWidget = qobject_cast<QTreeWidget*>(sender());
+
+ if (!treeWidget)
+ return;
+
+ QTreeWidgetItem *item = treeWidget->itemAt(pos);
+
+ if (!item)
+ return;
+
+ QAction *action = itemPopup->exec(treeWidget->viewport()->mapToGlobal(pos));
+ if (action == actionOpenCurrentTab) {
+ if (ui.tabWidget->currentWidget()->objectName() == QLatin1String("contentPage"))
+ showContentsTopic();
+ else
+ showBookmarkTopic();
+ } else if (action) {
+ QTreeWidgetItem *i = (QTreeWidgetItem*)item;
+ if (action == actionOpenLinkInNewWindow)
+ help->browsers()->currentBrowser()->openLinkInNewWindow(i->data(0, LinkRole).toString());
+ else
+ help->browsers()->currentBrowser()->openLinkInNewPage(i->data(0, LinkRole).toString());
+ }
+}
+
+void HelpDialog::on_termsEdit_returnPressed()
+{
+ startSearch();
+}
+
+void HelpDialog::updateSearchButton(const QString &txt)
+{
+ ui.searchButton->setDisabled(txt.isEmpty());
+}
+
+void HelpDialog::on_searchButton_clicked()
+{
+ startSearch();
+}
+
+QString HelpDialog::removeAnchorFromLink(const QString &link)
+{
+ int i = link.length();
+ int j = link.lastIndexOf(QLatin1Char('/'));
+ int l = link.lastIndexOf(QDir::separator());
+ if (l > j)
+ j = l;
+ if (j > -1) {
+ QString fileName = link.mid(j+1);
+ int k = fileName.lastIndexOf(QLatin1Char('#'));
+ if (k > -1)
+ i = j + k + 1;
+ }
+ return link.left(i);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/helpdialog.h b/tools/assistant/compat/helpdialog.h
new file mode 100644
index 0000000000..29d77d9cb7
--- /dev/null
+++ b/tools/assistant/compat/helpdialog.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HELPDIALOG_H
+#define HELPDIALOG_H
+
+#include "ui_helpdialog.h"
+#include "index.h"
+#include "helpwindow.h"
+#include "docuparser.h"
+
+#include <QList>
+#include <QPair>
+#include <QListWidget>
+#include <QTreeWidget>
+#include <QMap>
+#include <QStringList>
+#include <QValidator>
+#include <qmenu.h>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QProgressBar;
+class MainWindow;
+class QTextBrowser;
+class IndexListModel;
+
+class HelpNavigationListItem : public QListWidgetItem
+{
+public:
+ HelpNavigationListItem(QListWidget *ls, const QString &txt);
+
+ void addLink(const QString &link);
+ QStringList links() const { return linkList; }
+private:
+ QStringList linkList;
+
+};
+
+class SearchValidator : public QValidator
+{
+ Q_OBJECT
+public:
+ SearchValidator(QObject *parent)
+ : QValidator(parent) {}
+ ~SearchValidator() {}
+ QValidator::State validate(QString &str, int &) const;
+};
+
+class HelpDialog : public QWidget
+{
+ Q_OBJECT
+public:
+ HelpDialog(QWidget *parent, MainWindow *h);
+
+ inline QTabWidget *tabWidget() const
+ { return ui.tabWidget; }
+
+ QString titleOfLink(const QString &link);
+ bool eventFilter(QObject *, QEvent *);
+ bool lastWindowClosed() { return lwClosed; }
+
+ void timerEvent(QTimerEvent *e);
+ static QString removeAnchorFromLink(const QString &link);
+
+signals:
+ void showLink(const QString &s);
+ void showSearchLink(const QString &s, const QStringList &terms);
+
+public slots:
+ void initialize();
+ void startSearch();
+ void addBookmark();
+ void currentTabChanged(int index);
+ void locateContents(const QString &link);
+
+private slots:
+ void on_buttonAdd_clicked();
+ void on_buttonRemove_clicked();
+ void on_termsEdit_returnPressed();
+ void on_helpButton_clicked();
+ void on_searchButton_clicked();
+ void on_resultBox_itemActivated(QListWidgetItem*);
+ void updateSearchButton(const QString &txt);
+
+ void showResultPage(QListWidgetItem *);
+
+ void showTopic(QTreeWidgetItem *);
+ void loadIndexFile();
+ void insertContents();
+ void setupFullTextIndex();
+ void showTopic();
+ void searchInIndex(const QString &s);
+ void toggleContents();
+ void toggleIndex();
+ void toggleBookmarks();
+ void toggleSearch();
+ void lastWinClosed();
+ void setIndexingProgress(int prog);
+ void showListItemMenu(const QPoint &pos);
+ void showIndexItemMenu(const QPoint &pos);
+ void showTreeItemMenu(const QPoint &pos);
+ void insertBookmarks();
+ void processEvents();
+
+private:
+ typedef QList<ContentItem> ContentList;
+ void removeOldCacheFiles(bool onlyFulltextSearchIndex = false);
+ void buildKeywordDB();
+ quint32 getFileAges();
+ void showIndexTopic();
+ void showBookmarkTopic();
+ void setupTitleMap();
+ void saveBookmarks();
+ void showContentsTopic();
+ void showInitDoneMessage();
+ void buildContentDict();
+ QTreeWidgetItem * locateLink(QTreeWidgetItem *item, const QString &link);
+
+private:
+ Ui::HelpDialog ui;
+
+ IndexListModel *indexModel;
+ QMap<QString, QString> titleMap;
+ bool indexDone, bookmarksInserted, titleMapDone, contentsInserted;
+ bool lwClosed;
+ MainWindow *help;
+ QString documentationPath;
+ Index *fullTextIndex;
+ QStringList terms, foundDocs;
+ bool initDoneMsgShown;
+ void getAllContents();
+ QList<QPair<QString, ContentList> > contentList;
+ QMenu *itemPopup;
+ QString cacheFilesPath;
+ QStringList keywordDocuments;
+
+ QAction *actionOpenCurrentTab;
+ QAction *actionOpenLinkInNewWindow;
+ QAction *actionOpenLinkInNewTab;
+};
+
+QT_END_NAMESPACE
+
+#endif // HELPDIALOG_H
diff --git a/tools/assistant/compat/helpdialog.ui b/tools/assistant/compat/helpdialog.ui
new file mode 100644
index 0000000000..acd1372f0c
--- /dev/null
+++ b/tools/assistant/compat/helpdialog.ui
@@ -0,0 +1,404 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>HelpDialog</class>
+ <widget class="QWidget" name="HelpDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>274</width>
+ <height>417</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Help</string>
+ </property>
+ <property name="whatsThis" >
+ <string>&lt;b>Help&lt;/b>&lt;p>Choose the topic you want help on from the contents list, or search the index for keywords.&lt;/p></string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="whatsThis" >
+ <string>Displays help topics organized by category, index or bookmarks. Another tab inherits the full text search.</string>
+ </property>
+ <widget class="QWidget" name="contentPage" >
+ <attribute name="title" >
+ <string>Con&amp;tents</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>5</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listContents" >
+ <property name="contextMenuPolicy" >
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="whatsThis" >
+ <string>&lt;b>Help topics organized by category.&lt;/b>&lt;p>Double-click an item to see the topics in that category. To view a topic, just double-click it.&lt;/p></string>
+ </property>
+ <property name="rootIsDecorated" >
+ <bool>true</bool>
+ </property>
+ <property name="uniformRowHeights" >
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>column 1</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="indexPage" >
+ <attribute name="title" >
+ <string>&amp;Index</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>5</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="text" >
+ <string>&amp;Look For:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>editIndex</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="editIndex" >
+ <property name="toolTip" >
+ <string>Enter keyword</string>
+ </property>
+ <property name="whatsThis" >
+ <string>&lt;b>Enter a keyword.&lt;/b>&lt;p>The list will select an item that matches the entered string best.&lt;/p></string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListView" name="listIndex" >
+ <property name="contextMenuPolicy" >
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="whatsThis" >
+ <string>&lt;b>List of available help topics.&lt;/b>&lt;p>Double-click on an item to open its help page. If more than one is found, you must specify which page you want.&lt;/p></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="bookmarkPage" >
+ <attribute name="title" >
+ <string>&amp;Bookmarks</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>5</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="listBookmarks" >
+ <property name="contextMenuPolicy" >
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="whatsThis" >
+ <string>Displays the list of bookmarks.</string>
+ </property>
+ <property name="uniformRowHeights" >
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>column 1</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonAdd" >
+ <property name="toolTip" >
+ <string>Add new bookmark</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Add the currently displayed page as a new bookmark.</string>
+ </property>
+ <property name="text" >
+ <string>&amp;New</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonRemove" >
+ <property name="toolTip" >
+ <string>Delete bookmark</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Delete the selected bookmark.</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Delete</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="searchPage" >
+ <attribute name="title" >
+ <string>&amp;Search</string>
+ </attribute>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>5</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="3" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="TextLabel1_2" >
+ <property name="text" >
+ <string>Searching f&amp;or:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>termsEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLineEdit" name="termsEdit" >
+ <property name="toolTip" >
+ <string>Enter searchword(s).</string>
+ </property>
+ <property name="whatsThis" >
+ <string>&lt;b>Enter search word(s).&lt;/b>&lt;p>Enter here the word(s) you are looking for. The words may contain wildcards (*). For a sequence of words quote them.&lt;/p></string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QListWidget" name="resultBox" >
+ <property name="contextMenuPolicy" >
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="whatsThis" >
+ <string>&lt;b>Found documents&lt;/b>&lt;p>This list contains all found documents from the last search. The documents are ordered, i.e. the first document has the most matches.&lt;/p></string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="TextLabel2" >
+ <property name="text" >
+ <string>Found &amp;Documents:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>resultBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>1</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="helpButton" >
+ <property name="toolTip" >
+ <string>Display the help page.</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Display the help page for the full text search.</string>
+ </property>
+ <property name="text" >
+ <string>He&amp;lp</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>61</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="searchButton" >
+ <property name="toolTip" >
+ <string>Start searching.</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Pressing this button starts the search.</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Search</string>
+ </property>
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="framePrepare" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>3</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="labelPrepare" >
+ <property name="text" >
+ <string>Preparing...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="progressPrepare" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <tabstops>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>listContents</tabstop>
+ <tabstop>editIndex</tabstop>
+ <tabstop>listIndex</tabstop>
+ <tabstop>listBookmarks</tabstop>
+ <tabstop>buttonAdd</tabstop>
+ <tabstop>buttonRemove</tabstop>
+ <tabstop>termsEdit</tabstop>
+ <tabstop>searchButton</tabstop>
+ <tabstop>helpButton</tabstop>
+ <tabstop>resultBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/compat/helpwindow.cpp b/tools/assistant/compat/helpwindow.cpp
new file mode 100644
index 0000000000..d3ddc29bd1
--- /dev/null
+++ b/tools/assistant/compat/helpwindow.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "helpwindow.h"
+#include "mainwindow.h"
+#include "tabbedbrowser.h"
+#include "helpdialog.h"
+#include "config.h"
+
+#include <QApplication>
+#include <QClipboard>
+#include <QUrl>
+#include <QMessageBox>
+#include <QDir>
+#include <QFile>
+#include <QProcess>
+#include <QAction>
+#include <QFileInfo>
+#include <QFont>
+#include <QtEvents>
+#include <QTextStream>
+#include <QTextCodec>
+#include <QStatusBar>
+#include <QTextCursor>
+#include <QTextObject>
+#include <QTextLayout>
+#include <QtDebug>
+#include <qdesktopservices.h>
+
+#include <QtGui/QClipboard>
+#include <QtGui/QApplication>
+
+#if defined(Q_OS_WIN32)
+# include <windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+HelpWindow::HelpWindow(MainWindow *w, QWidget *parent)
+ : QTextBrowser(parent)
+ , mw(w)
+ , blockScroll(false)
+ , shiftPressed(false)
+ , newWindow(false)
+{
+ FontSettings settings = Config::configuration()->fontSettings();
+ setFont(settings.browserFont);
+
+ connect(this, SIGNAL(copyAvailable(bool)), w, SLOT(copyAvailable(bool)));
+}
+
+void HelpWindow::setSource(const QUrl &name)
+{
+ if (name.isValid()) {
+ if (name.scheme() == QLatin1String("http") || name.scheme() == QLatin1String("ftp")
+ || name.scheme() == QLatin1String("mailto") || name.path().endsWith(QLatin1String("pdf"))) {
+ bool launched = QDesktopServices::openUrl(name);
+ if (!launched) {
+ QMessageBox::information(mw, tr("Help"),
+ tr("Unable to launch web browser.\n"),
+ tr("OK"));
+ }
+ return;
+ }
+
+ QFileInfo fi(name.toLocalFile());
+ if (name.scheme() == QLatin1String("file") && fi.exists()) {
+ if (newWindow || (shiftPressed && hasFocus())) {
+ shiftPressed = false;
+ mw->saveSettings();
+ MainWindow *nmw = new MainWindow;
+ nmw->move(mw->geometry().topLeft());
+ nmw->show();
+
+ if (mw->isMaximized())
+ nmw->showMaximized();
+
+ nmw->setup();
+ nmw->showLink(name.toString());
+ } else {
+ QTextBrowser::setSource(name);
+ QTextBrowser::scrollToAnchor(name.fragment());
+ }
+ return;
+ }
+ }
+
+ mw->statusBar()->showMessage(tr("Failed to open link: '%1'").arg(name.toString()), 5000);
+ setHtml(tr("<div align=\"center\"><h1>The page could not be found</h1><br>"
+ "<h3>'%1'</h3></div>").arg(name.toString()));
+ mw->browsers()->updateTitle(tr("Error..."));
+}
+
+void HelpWindow::openLinkInNewWindow()
+{
+ if (lastAnchor.isEmpty())
+ return;
+ newWindow = true;
+ setSource(lastAnchor);
+ newWindow = false;
+}
+
+void HelpWindow::openLinkInNewWindow(const QString &link)
+{
+ lastAnchor = link;
+ openLinkInNewWindow();
+}
+
+void HelpWindow::openLinkInNewPage()
+{
+ if(lastAnchor.isEmpty())
+ return;
+ mw->browsers()->newTab(lastAnchor);
+ lastAnchor.clear();
+}
+
+void HelpWindow::openLinkInNewPage(const QString &link)
+{
+ lastAnchor = link;
+ openLinkInNewPage();
+}
+
+bool HelpWindow::hasAnchorAt(const QPoint& pos)
+{
+ lastAnchor = anchorAt(pos);
+ if (lastAnchor.isEmpty())
+ return false;
+ lastAnchor = source().resolved(lastAnchor).toString();
+ if (lastAnchor.at(0) == QLatin1Char('#')) {
+ QString src = source().toString();
+ int hsh = src.indexOf(QLatin1Char('#'));
+ lastAnchor = (hsh>=0 ? src.left(hsh) : src) + lastAnchor;
+ }
+ return true;
+}
+
+void HelpWindow::contextMenuEvent(QContextMenuEvent *e)
+{
+ QMenu menu(QLatin1String(""), 0);
+
+ QUrl link;
+ QAction *copyAnchorAction = 0;
+ if (hasAnchorAt(e->pos())) {
+ link = anchorAt(e->pos());
+ if (link.isRelative())
+ link = source().resolved(link);
+ copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
+ copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid());
+
+ menu.addAction(tr("Open Link in New Tab"),
+ this, SLOT(openLinkInNewPage()));
+ menu.addAction(tr("Open Link in New Window\tShift+LMB"),
+ this, SLOT(openLinkInNewWindow()));
+ }
+ mw->setupPopupMenu(&menu);
+ QAction *action = menu.exec(e->globalPos());
+ if (action == copyAnchorAction)
+ QApplication::clipboard()->setText(link.toString());
+}
+
+void HelpWindow::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() == Qt::XButton1) {
+ QTextBrowser::backward();
+ return;
+ }
+
+ if (e->button() == Qt::XButton2) {
+ QTextBrowser::forward();
+ return;
+ }
+
+ if (e->button() == Qt::MidButton && hasAnchorAt(e->pos())) {
+ openLinkInNewPage();
+ return;
+ }
+ QTextBrowser::mouseReleaseEvent(e);
+}
+
+void HelpWindow::blockScrolling(bool b)
+{
+ blockScroll = b;
+}
+
+void HelpWindow::ensureCursorVisible()
+{
+ if (!blockScroll)
+ QTextBrowser::ensureCursorVisible();
+}
+
+void HelpWindow::mousePressEvent(QMouseEvent *e)
+{
+ shiftPressed = e->modifiers() & Qt::ShiftModifier;
+ if (!(shiftPressed && hasAnchorAt(e->pos())))
+ QTextBrowser::mousePressEvent(e);
+}
+
+void HelpWindow::keyPressEvent(QKeyEvent *e)
+{
+ shiftPressed = e->modifiers() & Qt::ShiftModifier;
+ QTextBrowser::keyPressEvent(e);
+}
+
+bool HelpWindow::isKDERunning() const
+{
+ return !qgetenv("KDE_FULL_SESSION").isEmpty();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/helpwindow.h b/tools/assistant/compat/helpwindow.h
new file mode 100644
index 0000000000..f1327b5c07
--- /dev/null
+++ b/tools/assistant/compat/helpwindow.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HELPWINDOW_H
+#define HELPWINDOW_H
+
+#include <QTextBrowser>
+
+QT_BEGIN_NAMESPACE
+
+class MainWindow;
+class QKeyEvent;
+class QMime;
+class QMouseEvent;
+class QMenu;
+
+class HelpWindow : public QTextBrowser
+{
+ Q_OBJECT
+public:
+ HelpWindow( MainWindow *m, QWidget *parent = 0);
+ void setSource( const QUrl &name );
+ void blockScrolling( bool b );
+ void openLinkInNewWindow( const QString &link );
+ void openLinkInNewPage( const QString &link );
+ void addMimePath( const QString &path );
+
+ void mousePressEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *);
+
+signals:
+ void chooseWebBrowser();
+ void choosePDFReader();
+
+protected:
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+
+protected slots:
+ void ensureCursorVisible();
+
+private slots:
+ void openLinkInNewWindow();
+ void openLinkInNewPage();
+
+ bool isKDERunning() const;
+
+private:
+ bool hasAnchorAt(const QPoint& pos);
+
+ MainWindow *mw;
+ QString lastAnchor;
+ bool blockScroll;
+ bool shiftPressed;
+ bool newWindow;
+ bool fwdAvail;
+ bool backAvail;
+};
+
+QT_END_NAMESPACE
+
+#endif // HELPWINDOW_H
diff --git a/tools/assistant/compat/images/assistant-128.png b/tools/assistant/compat/images/assistant-128.png
new file mode 100644
index 0000000000..f05949f6d8
--- /dev/null
+++ b/tools/assistant/compat/images/assistant-128.png
Binary files differ
diff --git a/tools/assistant/compat/images/assistant.png b/tools/assistant/compat/images/assistant.png
new file mode 100644
index 0000000000..ea4d1e70c1
--- /dev/null
+++ b/tools/assistant/compat/images/assistant.png
Binary files differ
diff --git a/tools/assistant/compat/images/close.png b/tools/assistant/compat/images/close.png
new file mode 100644
index 0000000000..540694eae3
--- /dev/null
+++ b/tools/assistant/compat/images/close.png
Binary files differ
diff --git a/tools/assistant/compat/images/designer.png b/tools/assistant/compat/images/designer.png
new file mode 100644
index 0000000000..72c42e73e4
--- /dev/null
+++ b/tools/assistant/compat/images/designer.png
Binary files differ
diff --git a/tools/assistant/compat/images/linguist.png b/tools/assistant/compat/images/linguist.png
new file mode 100644
index 0000000000..d388cbd0ba
--- /dev/null
+++ b/tools/assistant/compat/images/linguist.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/addtab.png b/tools/assistant/compat/images/mac/addtab.png
new file mode 100644
index 0000000000..20928fb402
--- /dev/null
+++ b/tools/assistant/compat/images/mac/addtab.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/book.png b/tools/assistant/compat/images/mac/book.png
new file mode 100644
index 0000000000..7a3204c870
--- /dev/null
+++ b/tools/assistant/compat/images/mac/book.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/closetab.png b/tools/assistant/compat/images/mac/closetab.png
new file mode 100644
index 0000000000..ab9d669eee
--- /dev/null
+++ b/tools/assistant/compat/images/mac/closetab.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/editcopy.png b/tools/assistant/compat/images/mac/editcopy.png
new file mode 100644
index 0000000000..f551364464
--- /dev/null
+++ b/tools/assistant/compat/images/mac/editcopy.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/find.png b/tools/assistant/compat/images/mac/find.png
new file mode 100644
index 0000000000..3561745f01
--- /dev/null
+++ b/tools/assistant/compat/images/mac/find.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/home.png b/tools/assistant/compat/images/mac/home.png
new file mode 100644
index 0000000000..78d94da18d
--- /dev/null
+++ b/tools/assistant/compat/images/mac/home.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/next.png b/tools/assistant/compat/images/mac/next.png
new file mode 100644
index 0000000000..a585cab80c
--- /dev/null
+++ b/tools/assistant/compat/images/mac/next.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/prev.png b/tools/assistant/compat/images/mac/prev.png
new file mode 100644
index 0000000000..612fb34dce
--- /dev/null
+++ b/tools/assistant/compat/images/mac/prev.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/print.png b/tools/assistant/compat/images/mac/print.png
new file mode 100644
index 0000000000..10ca56c82a
--- /dev/null
+++ b/tools/assistant/compat/images/mac/print.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/synctoc.png b/tools/assistant/compat/images/mac/synctoc.png
new file mode 100644
index 0000000000..067fa941b5
--- /dev/null
+++ b/tools/assistant/compat/images/mac/synctoc.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/whatsthis.png b/tools/assistant/compat/images/mac/whatsthis.png
new file mode 100644
index 0000000000..5b7078fffd
--- /dev/null
+++ b/tools/assistant/compat/images/mac/whatsthis.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/zoomin.png b/tools/assistant/compat/images/mac/zoomin.png
new file mode 100644
index 0000000000..d46f5aff0d
--- /dev/null
+++ b/tools/assistant/compat/images/mac/zoomin.png
Binary files differ
diff --git a/tools/assistant/compat/images/mac/zoomout.png b/tools/assistant/compat/images/mac/zoomout.png
new file mode 100644
index 0000000000..46326566d1
--- /dev/null
+++ b/tools/assistant/compat/images/mac/zoomout.png
Binary files differ
diff --git a/tools/assistant/compat/images/qt.png b/tools/assistant/compat/images/qt.png
new file mode 100644
index 0000000000..2dc67161c1
--- /dev/null
+++ b/tools/assistant/compat/images/qt.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/addtab.png b/tools/assistant/compat/images/win/addtab.png
new file mode 100644
index 0000000000..4bb0feb92d
--- /dev/null
+++ b/tools/assistant/compat/images/win/addtab.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/book.png b/tools/assistant/compat/images/win/book.png
new file mode 100644
index 0000000000..09ec4d33f7
--- /dev/null
+++ b/tools/assistant/compat/images/win/book.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/closetab.png b/tools/assistant/compat/images/win/closetab.png
new file mode 100644
index 0000000000..ef9e02086c
--- /dev/null
+++ b/tools/assistant/compat/images/win/closetab.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/editcopy.png b/tools/assistant/compat/images/win/editcopy.png
new file mode 100644
index 0000000000..1121b47d8b
--- /dev/null
+++ b/tools/assistant/compat/images/win/editcopy.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/find.png b/tools/assistant/compat/images/win/find.png
new file mode 100644
index 0000000000..6ea35e930d
--- /dev/null
+++ b/tools/assistant/compat/images/win/find.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/home.png b/tools/assistant/compat/images/win/home.png
new file mode 100644
index 0000000000..b1c6ae1913
--- /dev/null
+++ b/tools/assistant/compat/images/win/home.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/next.png b/tools/assistant/compat/images/win/next.png
new file mode 100644
index 0000000000..8df4127a00
--- /dev/null
+++ b/tools/assistant/compat/images/win/next.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/previous.png b/tools/assistant/compat/images/win/previous.png
new file mode 100644
index 0000000000..0780bc23dd
--- /dev/null
+++ b/tools/assistant/compat/images/win/previous.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/print.png b/tools/assistant/compat/images/win/print.png
new file mode 100644
index 0000000000..ba7c02dc18
--- /dev/null
+++ b/tools/assistant/compat/images/win/print.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/synctoc.png b/tools/assistant/compat/images/win/synctoc.png
new file mode 100644
index 0000000000..da301bc599
--- /dev/null
+++ b/tools/assistant/compat/images/win/synctoc.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/whatsthis.png b/tools/assistant/compat/images/win/whatsthis.png
new file mode 100644
index 0000000000..623cad6876
--- /dev/null
+++ b/tools/assistant/compat/images/win/whatsthis.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/zoomin.png b/tools/assistant/compat/images/win/zoomin.png
new file mode 100644
index 0000000000..2e586fc7bf
--- /dev/null
+++ b/tools/assistant/compat/images/win/zoomin.png
Binary files differ
diff --git a/tools/assistant/compat/images/win/zoomout.png b/tools/assistant/compat/images/win/zoomout.png
new file mode 100644
index 0000000000..a736d39343
--- /dev/null
+++ b/tools/assistant/compat/images/win/zoomout.png
Binary files differ
diff --git a/tools/assistant/compat/images/wrap.png b/tools/assistant/compat/images/wrap.png
new file mode 100644
index 0000000000..90f18d9f77
--- /dev/null
+++ b/tools/assistant/compat/images/wrap.png
Binary files differ
diff --git a/tools/assistant/compat/index.cpp b/tools/assistant/compat/index.cpp
new file mode 100644
index 0000000000..e98b00bacf
--- /dev/null
+++ b/tools/assistant/compat/index.cpp
@@ -0,0 +1,581 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "index.h"
+
+#include <QFile>
+#include <QDir>
+#include <QStringList>
+#include <QApplication>
+#include <QByteArray>
+#include <QTextStream>
+#include <QtAlgorithms>
+#include <QUrl>
+#include <QTextCodec>
+#include <ctype.h>
+#include <QTextDocument>
+
+QT_BEGIN_NAMESPACE
+
+struct Term {
+ Term() : frequency(-1) {}
+ Term( const QString &t, int f, QVector<Document> l ) : term( t ), frequency( f ), documents( l ) {}
+ QString term;
+ int frequency;
+ QVector<Document>documents;
+ bool operator<( const Term &i2 ) const { return frequency < i2.frequency; }
+};
+
+QDataStream &operator>>( QDataStream &s, Document &l )
+{
+ s >> l.docNumber;
+ s >> l.frequency;
+ return s;
+}
+
+QDataStream &operator<<( QDataStream &s, const Document &l )
+{
+ s << (qint16)l.docNumber;
+ s << (qint16)l.frequency;
+ return s;
+}
+
+Index::Index( const QString &dp, const QString &hp )
+ : QObject( 0 ), docPath( dp )
+{
+ Q_UNUSED(hp);
+
+ alreadyHaveDocList = false;
+ lastWindowClosed = false;
+ connect( qApp, SIGNAL(lastWindowClosed()),
+ this, SLOT(setLastWinClosed()) );
+}
+
+Index::Index( const QStringList &dl, const QString &hp )
+ : QObject( 0 )
+{
+ Q_UNUSED(hp);
+ docList = dl;
+ alreadyHaveDocList = true;
+ lastWindowClosed = false;
+ connect( qApp, SIGNAL(lastWindowClosed()),
+ this, SLOT(setLastWinClosed()) );
+}
+
+void Index::setLastWinClosed()
+{
+ lastWindowClosed = true;
+}
+
+void Index::setDictionaryFile( const QString &f )
+{
+ dictFile = f;
+}
+
+void Index::setDocListFile( const QString &f )
+{
+ docListFile = f;
+}
+
+void Index::setDocList( const QStringList &lst )
+{
+ docList = lst;
+}
+
+int Index::makeIndex()
+{
+ if ( !alreadyHaveDocList )
+ setupDocumentList();
+ if ( docList.isEmpty() )
+ return 1;
+ QStringList::Iterator it = docList.begin();
+ int steps = docList.count() / 100;
+ if ( !steps )
+ steps++;
+ int prog = 0;
+ for ( int i = 0; it != docList.end(); ++it, ++i ) {
+ if ( lastWindowClosed ) {
+ return -1;
+ }
+ QUrl url(*it);
+ parseDocument( url.toLocalFile(), i );
+ if ( i%steps == 0 ) {
+ prog++;
+ emit indexingProgress( prog );
+ }
+ }
+ return 0;
+}
+
+void Index::setupDocumentList()
+{
+ QDir d( docPath );
+ QStringList filters;
+ filters.append(QLatin1String("*.html"));
+ QStringList lst = d.entryList(filters);
+ QStringList::ConstIterator it = lst.constBegin();
+ for ( ; it != lst.constEnd(); ++it )
+ docList.append( QLatin1String("file:") + docPath + QLatin1String("/") + *it );
+}
+
+void Index::insertInDict( const QString &str, int docNum )
+{
+ if ( str == QLatin1String("amp") || str == QLatin1String("nbsp"))
+ return;
+ Entry *e = 0;
+ if ( dict.count() )
+ e = dict[ str ];
+
+ if ( e ) {
+ if ( e->documents.last().docNumber != docNum )
+ e->documents.append( Document(docNum, 1 ) );
+ else
+ e->documents.last().frequency++;
+ } else {
+ dict.insert( str, new Entry( docNum ) );
+ }
+}
+
+QString Index::getCharsetForDocument(QFile *file)
+{
+ QTextStream s(file);
+ QString contents = s.readAll();
+
+ QString encoding;
+ int start = contents.indexOf(QLatin1String("<meta"), 0, Qt::CaseInsensitive);
+ if (start > 0) {
+ int end = contents.indexOf(QLatin1String(">"), start);
+ QString meta = contents.mid(start+5, end-start);
+ meta = meta.toLower();
+ QRegExp r(QLatin1String("charset=([^\"\\s]+)"));
+ if (r.indexIn(meta) != -1) {
+ encoding = r.cap(1);
+ }
+ }
+
+ file->seek(0);
+ if (encoding.isEmpty())
+ return QLatin1String("utf-8");
+ return encoding;
+}
+
+void Index::parseDocument( const QString &filename, int docNum )
+{
+ QFile file( filename );
+ if ( !file.open(QFile::ReadOnly) ) {
+ qWarning( "can not open file %s", qPrintable(filename) );
+ return;
+ }
+
+ QTextStream s(&file);
+ QString en = getCharsetForDocument(&file);
+ s.setCodec(QTextCodec::codecForName(en.toLatin1().constData()));
+
+ QString text = s.readAll();
+ if (text.isNull())
+ return;
+
+ bool valid = true;
+ const QChar *buf = text.unicode();
+ QChar str[64];
+ QChar c = buf[0];
+ int j = 0;
+ int i = 0;
+ while ( j < text.length() ) {
+ if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) {
+ valid = false;
+ if ( i > 1 )
+ insertInDict( QString(str,i), docNum );
+ i = 0;
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) {
+ valid = true;
+ c = buf[++j];
+ continue;
+ }
+ if ( !valid ) {
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) {
+ str[i] = c.toLower();
+ ++i;
+ } else {
+ if ( i > 1 )
+ insertInDict( QString(str,i), docNum );
+ i = 0;
+ }
+ c = buf[++j];
+ }
+ if ( i > 1 )
+ insertInDict( QString(str,i), docNum );
+ file.close();
+}
+
+void Index::writeDict()
+{
+ QFile f( dictFile );
+ if ( !f.open(QFile::WriteOnly ) )
+ return;
+ QDataStream s( &f );
+ for(QHash<QString, Entry *>::Iterator it = dict.begin(); it != dict.end(); ++it) {
+ s << it.key();
+ s << it.value()->documents.count();
+ s << it.value()->documents;
+ }
+ f.close();
+ writeDocumentList();
+}
+
+void Index::writeDocumentList()
+{
+ QFile f( docListFile );
+ if ( !f.open(QFile::WriteOnly ) )
+ return;
+ QDataStream s( &f );
+ s << docList;
+}
+
+void Index::readDict()
+{
+ QFile f( dictFile );
+ if ( !f.open(QFile::ReadOnly ) )
+ return;
+
+ dict.clear();
+ QDataStream s( &f );
+ QString key;
+ int numOfDocs;
+ QVector<Document> docs;
+ while ( !s.atEnd() ) {
+ s >> key;
+ s >> numOfDocs;
+ docs.resize(numOfDocs);
+ s >> docs;
+ dict.insert( key, new Entry( docs ) );
+ }
+ f.close();
+ readDocumentList();
+}
+
+void Index::readDocumentList()
+{
+ QFile f( docListFile );
+ if ( !f.open(QFile::ReadOnly ) )
+ return;
+ QDataStream s( &f );
+ s >> docList;
+}
+
+QStringList Index::query( const QStringList &terms, const QStringList &termSeq, const QStringList &seqWords )
+{
+ QList<Term> termList;
+ for (QStringList::ConstIterator it = terms.begin(); it != terms.end(); ++it ) {
+ Entry *e = 0;
+ if ( (*it).contains(QLatin1Char('*')) ) {
+ QVector<Document> wcts = setupDummyTerm( getWildcardTerms( *it ) );
+ termList.append( Term(QLatin1String("dummy"), wcts.count(), wcts ) );
+ } else if ( dict[ *it ] ) {
+ e = dict[ *it ];
+ termList.append( Term( *it, e->documents.count(), e->documents ) );
+ } else {
+ return QStringList();
+ }
+ }
+ if ( !termList.count() )
+ return QStringList();
+ qSort(termList);
+
+ QVector<Document> minDocs = termList.takeFirst().documents;
+ for(QList<Term>::Iterator it = termList.begin(); it != termList.end(); ++it) {
+ Term *t = &(*it);
+ QVector<Document> docs = t->documents;
+ for(QVector<Document>::Iterator minDoc_it = minDocs.begin(); minDoc_it != minDocs.end(); ) {
+ bool found = false;
+ for (QVector<Document>::ConstIterator doc_it = docs.constBegin(); doc_it != docs.constEnd(); ++doc_it ) {
+ if ( (*minDoc_it).docNumber == (*doc_it).docNumber ) {
+ (*minDoc_it).frequency += (*doc_it).frequency;
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ minDoc_it = minDocs.erase( minDoc_it );
+ else
+ ++minDoc_it;
+ }
+ }
+
+ QStringList results;
+ qSort( minDocs );
+ if ( termSeq.isEmpty() ) {
+ for(QVector<Document>::Iterator it = minDocs.begin(); it != minDocs.end(); ++it)
+ results << docList.at((int)(*it).docNumber);
+ return results;
+ }
+
+ QString fileName;
+ for(QVector<Document>::Iterator it = minDocs.begin(); it != minDocs.end(); ++it) {
+ fileName = docList[ (int)(*it).docNumber ];
+ if ( searchForPattern( termSeq, seqWords, fileName ) )
+ results << fileName;
+ }
+ return results;
+}
+
+QString Index::getDocumentTitle( const QString &fullFileName )
+{
+ QUrl url(fullFileName);
+ QString fileName = url.toLocalFile();
+
+ if (documentTitleCache.contains(fileName))
+ return documentTitleCache.value(fileName);
+
+ QFile file( fileName );
+ if ( !file.open( QFile::ReadOnly ) ) {
+ qWarning( "cannot open file %s", qPrintable(fileName) );
+ return fileName;
+ }
+ QTextStream s( &file );
+ QString text = s.readAll();
+
+ int start = text.indexOf(QLatin1String("<title>"), 0, Qt::CaseInsensitive) + 7;
+ int end = text.indexOf(QLatin1String("</title>"), 0, Qt::CaseInsensitive);
+
+ QString title = tr("Untitled");
+ if (end - start > 0) {
+ title = text.mid(start, end - start);
+ if (Qt::mightBeRichText(title)) {
+ QTextDocument doc;
+ doc.setHtml(title);
+ title = doc.toPlainText();
+ }
+ }
+ documentTitleCache.insert(fileName, title);
+ return title;
+}
+
+QStringList Index::getWildcardTerms( const QString &term )
+{
+ QStringList lst;
+ QStringList terms = split( term );
+ QStringList::Iterator iter;
+
+ for(QHash<QString, Entry*>::Iterator it = dict.begin(); it != dict.end(); ++it) {
+ int index = 0;
+ bool found = false;
+ QString text( it.key() );
+ for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
+ if ( *iter == QLatin1String("*") ) {
+ found = true;
+ continue;
+ }
+ if ( iter == terms.begin() && (*iter)[0] != text[0] ) {
+ found = false;
+ break;
+ }
+ index = text.indexOf( *iter, index );
+ if ( *iter == terms.last() && index != (int)text.length()-1 ) {
+ index = text.lastIndexOf( *iter );
+ if ( index != (int)text.length() - (int)(*iter).length() ) {
+ found = false;
+ break;
+ }
+ }
+ if ( index != -1 ) {
+ found = true;
+ index += (*iter).length();
+ continue;
+ } else {
+ found = false;
+ break;
+ }
+ }
+ if ( found )
+ lst << text;
+ }
+
+ return lst;
+}
+
+QStringList Index::split( const QString &str )
+{
+ QStringList lst;
+ int j = 0;
+ int i = str.indexOf(QLatin1Char('*'), j );
+
+ if (str.startsWith(QLatin1String("*")))
+ lst << QLatin1String("*");
+
+ while ( i != -1 ) {
+ if ( i > j && i <= (int)str.length() ) {
+ lst << str.mid( j, i - j );
+ lst << QLatin1String("*");
+ }
+ j = i + 1;
+ i = str.indexOf(QLatin1Char('*'), j );
+ }
+
+ int l = str.length() - 1;
+ if ( str.mid( j, l - j + 1 ).length() > 0 )
+ lst << str.mid( j, l - j + 1 );
+
+ return lst;
+}
+
+QVector<Document> Index::setupDummyTerm( const QStringList &terms )
+{
+ QList<Term> termList;
+ for (QStringList::ConstIterator it = terms.begin(); it != terms.end(); ++it) {
+ Entry *e = 0;
+ if ( dict[ *it ] ) {
+ e = dict[ *it ];
+ termList.append( Term( *it, e->documents.count(), e->documents ) );
+ }
+ }
+ QVector<Document> maxList(0);
+ if ( !termList.count() )
+ return maxList;
+ qSort(termList);
+
+ maxList = termList.takeLast().documents;
+ for(QList<Term>::Iterator it = termList.begin(); it != termList.end(); ++it) {
+ Term *t = &(*it);
+ QVector<Document> docs = t->documents;
+ for (QVector<Document>::iterator docIt = docs.begin(); docIt != docs.end(); ++docIt ) {
+ if ( maxList.indexOf( *docIt ) == -1 )
+ maxList.append( *docIt );
+ }
+ }
+ return maxList;
+}
+
+void Index::buildMiniDict( const QString &str )
+{
+ if ( miniDict[ str ] )
+ miniDict[ str ]->positions.append( wordNum );
+ ++wordNum;
+}
+
+bool Index::searchForPattern( const QStringList &patterns, const QStringList &words, const QString &fileName )
+{
+ QUrl url(fileName);
+ QString fName = url.toLocalFile();
+ QFile file( fName );
+ if ( !file.open( QFile::ReadOnly ) ) {
+ qWarning( "cannot open file %s", qPrintable(fName) );
+ return false;
+ }
+
+ wordNum = 3;
+ miniDict.clear();
+ QStringList::ConstIterator cIt = words.begin();
+ for ( ; cIt != words.end(); ++cIt )
+ miniDict.insert( *cIt, new PosEntry( 0 ) );
+
+ QTextStream s( &file );
+ QString text = s.readAll();
+ bool valid = true;
+ const QChar *buf = text.unicode();
+ QChar str[64];
+ QChar c = buf[0];
+ int j = 0;
+ int i = 0;
+ while ( j < text.length() ) {
+ if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) {
+ valid = false;
+ if ( i > 1 )
+ buildMiniDict( QString(str,i) );
+ i = 0;
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) {
+ valid = true;
+ c = buf[++j];
+ continue;
+ }
+ if ( !valid ) {
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) {
+ str[i] = c.toLower();
+ ++i;
+ } else {
+ if ( i > 1 )
+ buildMiniDict( QString(str,i) );
+ i = 0;
+ }
+ c = buf[++j];
+ }
+ if ( i > 1 )
+ buildMiniDict( QString(str,i) );
+ file.close();
+
+ QStringList::ConstIterator patIt = patterns.begin();
+ QStringList wordLst;
+ QList<uint> a, b;
+ QList<uint>::iterator aIt;
+ for ( ; patIt != patterns.end(); ++patIt ) {
+ wordLst = (*patIt).split(QLatin1Char(' '));
+ a = miniDict[ wordLst[0] ]->positions;
+ for ( int j = 1; j < (int)wordLst.count(); ++j ) {
+ b = miniDict[ wordLst[j] ]->positions;
+ aIt = a.begin();
+ while ( aIt != a.end() ) {
+ if ( b.contains( *aIt + 1 )) {
+ (*aIt)++;
+ ++aIt;
+ } else {
+ aIt = a.erase( aIt );
+ }
+ }
+ }
+ }
+ if ( a.count() )
+ return true;
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/index.h b/tools/assistant/compat/index.h
new file mode 100644
index 0000000000..9fc30afa7d
--- /dev/null
+++ b/tools/assistant/compat/index.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INDEX_H
+#define INDEX_H
+
+#include <QStringList>
+#include <QHash>
+#include <QDataStream>
+#include <QObject>
+#include <QList>
+#include <QFile>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+struct Document {
+ Document( int d, int f ) : docNumber( d ), frequency( f ) {}
+ Document() : docNumber( -1 ), frequency( 0 ) {}
+ bool operator==( const Document &doc ) const {
+ return docNumber == doc.docNumber;
+ }
+ bool operator<( const Document &doc ) const {
+ return frequency > doc.frequency;
+ }
+ bool operator<=( const Document &doc ) const {
+ return frequency >= doc.frequency;
+ }
+ bool operator>( const Document &doc ) const {
+ return frequency < doc.frequency;
+ }
+ qint16 docNumber;
+ qint16 frequency;
+};
+
+QDataStream &operator>>( QDataStream &s, Document &l );
+QDataStream &operator<<( QDataStream &s, const Document &l );
+
+class Index : public QObject
+{
+ Q_OBJECT
+public:
+ struct Entry {
+ Entry( int d ) { documents.append( Document( d, 1 ) ); }
+ Entry( QVector<Document> l ) : documents( l ) {}
+ QVector<Document> documents;
+ };
+ struct PosEntry {
+ PosEntry( int p ) { positions.append( p ); }
+ QList<uint> positions;
+ };
+
+ Index( const QString &dp, const QString &hp );
+ Index( const QStringList &dl, const QString &hp );
+ void writeDict();
+ void readDict();
+ int makeIndex();
+ QStringList query( const QStringList&, const QStringList&, const QStringList& );
+ QString getDocumentTitle( const QString& );
+ void setDictionaryFile( const QString& );
+ void setDocListFile( const QString& );
+ void setDocList( const QStringList & );
+
+signals:
+ void indexingProgress( int );
+
+private slots:
+ void setLastWinClosed();
+
+private:
+ void setupDocumentList();
+ void parseDocument( const QString&, int );
+ void insertInDict( const QString&, int );
+ void writeDocumentList();
+ void readDocumentList();
+ QStringList getWildcardTerms( const QString& );
+ QStringList split( const QString& );
+ QVector<Document> setupDummyTerm( const QStringList& );
+ bool searchForPattern( const QStringList&, const QStringList&, const QString& );
+ void buildMiniDict( const QString& );
+ QString getCharsetForDocument(QFile *);
+ QStringList docList;
+ QHash<QString, Entry*> dict;
+ QHash<QString, PosEntry*> miniDict;
+ uint wordNum;
+ QString docPath;
+ QString dictFile, docListFile;
+ bool alreadyHaveDocList;
+ bool lastWindowClosed;
+ QHash<QString, QString> documentTitleCache;
+};
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/lib/lib.pro b/tools/assistant/compat/lib/lib.pro
new file mode 100644
index 0000000000..d4b5a47b2a
--- /dev/null
+++ b/tools/assistant/compat/lib/lib.pro
@@ -0,0 +1,78 @@
+TEMPLATE = lib
+QT += network
+TARGET = QtAssistantClient
+isEmpty(QT_MAJOR_VERSION) {
+ VERSION=4.3.0
+} else {
+ VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}
+}
+
+CONFIG += qt warn_on
+mac|win32:CONFIG += debug_and_release
+mac:unix:CONFIG += explicitlib
+CONFIG -= dll
+
+HEADERS = qassistantclient.h \
+ qassistantclient_global.h
+SOURCES = qassistantclient.cpp
+
+DESTDIR = ../../../../lib
+DLLDESTDIR = ../../../../bin
+
+unix {
+ QMAKE_CFLAGS += $$QMAKE_CFLAGS_SHLIB
+ QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_SHLIB
+}
+
+DEFINES += QT_ASSISTANT_CLIENT_LIBRARY
+contains(CONFIG, static) {
+ DEFINES += QT_ASSISTANT_CLIENT_STATIC
+}
+
+#load up the headers info
+CONFIG += qt_install_headers
+HEADERS_PRI = $$QT_BUILD_TREE/include/QtAssistant/headers.pri
+include($$HEADERS_PRI)|clear(HEADERS_PRI)
+
+#mac frameworks
+mac:!static:contains(QT_CONFIG, qt_framework) {
+ TARGET = QtAssistant # Change the name to match the headers
+ QMAKE_FRAMEWORK_BUNDLE_NAME = $$TARGET
+ CONFIG += lib_bundle qt_no_framework_direct_includes qt_framework
+ CONFIG(debug, debug|release) {
+ !build_pass:CONFIG += build_all
+ } else { #release
+ !debug_and_release|build_pass {
+ CONFIG -= qt_install_headers #no need to install these as well
+ FRAMEWORK_HEADERS.version = Versions
+ FRAMEWORK_HEADERS.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES
+ FRAMEWORK_HEADERS.path = Headers
+ }
+ QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS
+ }
+}
+
+TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #done towards the end
+
+target.path=$$[QT_INSTALL_LIBS]
+INSTALLS += target
+win32 {
+ dlltarget.path=$$[QT_INSTALL_BINS]
+ INSTALLS += dlltarget
+}
+
+qt_install_headers {
+ assistant_headers.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES
+ assistant_headers.path = $$[QT_INSTALL_HEADERS]/QtAssistant
+ INSTALLS += assistant_headers
+}
+
+unix {
+ CONFIG += create_pc
+ QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS]
+ QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/QtAssistant
+ QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS]
+ QMAKE_PKGCONFIG_DESTDIR = pkgconfig
+ QMAKE_PKGCONFIG_REQUIRES += QtNetwork
+}
+
diff --git a/tools/assistant/compat/lib/qassistantclient.cpp b/tools/assistant/compat/lib/qassistantclient.cpp
new file mode 100644
index 0000000000..25fbd6c399
--- /dev/null
+++ b/tools/assistant/compat/lib/qassistantclient.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qassistantclient.h"
+
+#include <qtcpsocket.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+#include <qfileinfo.h>
+#include <qmap.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAssistantClientPrivate
+{
+ friend class QAssistantClient;
+ QStringList arguments;
+};
+
+static QMap<const QAssistantClient*,QAssistantClientPrivate*> *dpointers = 0;
+
+static QAssistantClientPrivate *data( const QAssistantClient *client, bool create=false )
+{
+ if( !dpointers )
+ dpointers = new QMap<const QAssistantClient*,QAssistantClientPrivate*>;
+ QAssistantClientPrivate *d = (*dpointers)[client];
+ if( !d && create ) {
+ d = new QAssistantClientPrivate;
+ dpointers->insert( client, d );
+ }
+ return d;
+}
+
+/*!
+ \class QAssistantClient
+ \obsolete
+ \brief The QAssistantClient class provides a means of using Qt
+ Assistant as an application's help tool.
+
+ \inmodule QtAssistant
+ \ingroup helpsystem
+
+ \bold{Note:} \e{This class is obsolete and only required when using
+ the old Qt Assistant, now called assistant_adp. If you want to use
+ the new Qt Assistant as a remote help viewer, simple create a
+ QProcess instance and specify \tt{assistant} as its executable.
+ The following code shows how to start Qt Assistant and request a
+ certain page to be shown:}
+
+ \snippet doc/src/snippets/code/tools_assistant_compat_lib_qassistantclient.cpp 0
+
+ \e{For a complete example using the Qt Assistant remotely, see the \l
+ {help/remotecontrol}{Remote Control} example.}
+
+ In order to make Qt Assistant act as a customized help tool for
+ your application, you must provide your application with a
+ QAssistantClient object in addition to a \l
+ {assistant-manual.html} {Qt Assistant Document Profile} (\c .adp
+ file) and the associated documentation.
+
+ Note that the QAssistantClient class is not included in the Qt
+ library. To use it you must add the following line to your pro
+ file:
+
+ \snippet doc/src/snippets/code/tools_assistant_compat_lib_qassistantclient.cpp 1
+
+ A QAssistantClient instance can open or close Qt Assistant
+ whenever it is required.
+
+ Once you have created a QAssistantClient instance, specifying the
+ path to the Qt Assistant executable, using Qt Assistant is
+ simple: You can either call the openAssistant() slot to show the
+ defined start page of the documentation, or you can call the
+ showPage() slot to show a particular help page. When you call
+ openAssistant() and showPage(), Qt Assistant will be launched if
+ it isn't already running. When Qt Assistant is running, the
+ isOpen() function returns true.
+
+ When calling showPage() the Qt Assistant instance will also be
+ brought to the foreground if its hidden. The showPage() slot can
+ be called multiple times, while calling openAssistant() several
+ times without closing the application in between, will have no
+ effect.
+
+ You can close Qt Assistant at any time using the closeAssistant()
+ slot. When you call openAssistant(), or you call showPage()
+ without a previous call to openAssistant(), the assistantOpened()
+ signal is emitted. Similarly when closeAssistant() is called,
+ assistantClosed() is emitted. In either case, if an error occurs,
+ error() is emitted.
+
+ One QAssistantClient instance interacts with one Qt Assistant
+ instance, so every time you call openAssistant(), showPage() or
+ closeAssistant() they are applied to the particular Qt Assistant
+ instance associated with the QAssistantClient.
+
+ Qt Assistant's documentation set can be altered using the command
+ line arguments that are passed to the application when it is
+ launched. When started without any options, Qt Assistant displays
+ a default set of documentation. When Qt is installed, the default
+ documentation set in Qt Assistant contains the Qt reference
+ documentation as well as the tools that come with Qt, such as \QD
+ and \c qmake.
+
+ Use the setArguments() function to specify the command line
+ arguments. You can add or remove documentation from Qt Assistant
+ by adding and removing the relevant content files: The command
+ line arguments are \c {-addContentFile file.dcf} and \c
+ {-removeContentFile file.dcf} respectively. You can make Qt
+ Assistant run customized documentation sets that are separate from
+ the Qt documentation, by specifying a profile: \c {-profile
+ myapplication.adp}. The profile format can also be used to alter
+ several of Qt Assistant's properties such as its title and
+ startpage.
+
+ The Documentation Content File (\c .dcf) and Qt Assistant
+ Documentation Profile (\c .adp) formats are documented in the \l
+ {assistant-manual.html}{Qt Assistant Manual}.
+
+ For a complete example using the QAssistantClient class, see the
+ \e{Simple Text Viewer} example. The example shows how you can make
+ Qt Assistant act as a customized help tool for your application
+ using the QAssistantClient class combined with a Qt Assistant
+ Document Profile.
+
+ \sa {Qt Assistant Manual}, {Simple Text Viewer Example}
+*/
+
+/*!
+ \fn void QAssistantClient::assistantOpened()
+
+ This signal is emitted when Qt Assistant is opened and the
+ client-server communication is set up.
+
+ \sa openAssistant(), showPage()
+*/
+
+/*!
+ \fn void QAssistantClient::assistantClosed()
+
+ This signal is emitted when the connection to Qt Assistant is
+ closed. This happens when the user exits Qt Assistant, if an
+ error in the server or client occurs, or if closeAssistant() is
+ called.
+
+ \sa closeAssistant()
+*/
+
+/*!
+ \fn void QAssistantClient::error( const QString &message )
+
+ This signal is emitted if Qt Assistant cannot be started, or if an
+ error occurs during the initialization of the connection between
+ Qt Assistant and the calling application. The \a message provides an
+ explanation of the error.
+*/
+
+/*!
+ Constructs an assistant client with the specified \a parent. For
+ systems other than Mac OS, \a path specifies the path to the Qt
+ Assistant executable. For Mac OS, \a path specifies a directory
+ containing a valid assistant.app bundle. If \a path is the empty
+ string, the system path (\c{%PATH%} or \c $PATH) is used.
+*/
+QAssistantClient::QAssistantClient( const QString &path, QObject *parent )
+ : QObject( parent ), host ( QLatin1String("localhost") )
+{
+#if defined(Q_OS_MAC)
+ const QString assistant = QLatin1String("Assistant_adp");
+#else
+ const QString assistant = QLatin1String("assistant_adp");
+#endif
+
+ if ( path.isEmpty() )
+ assistantCommand = assistant;
+ else {
+ QFileInfo fi( path );
+ if ( fi.isDir() )
+ assistantCommand = path + QLatin1String("/") + assistant;
+ else
+ assistantCommand = path;
+ }
+
+#if defined(Q_OS_MAC)
+ assistantCommand += QLatin1String(".app/Contents/MacOS/Assistant_adp");
+#endif
+
+ socket = new QTcpSocket( this );
+ connect( socket, SIGNAL(connected()),
+ SLOT(socketConnected()) );
+ connect( socket, SIGNAL(disconnected()),
+ SLOT(socketConnectionClosed()) );
+ connect( socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ SLOT(socketError()) );
+ opened = false;
+ proc = new QProcess( this );
+ port = 0;
+ pageBuffer = QLatin1String("");
+ connect( proc, SIGNAL(readyReadStandardError()),
+ this, SLOT(readStdError()) );
+ connect( proc, SIGNAL(error(QProcess::ProcessError)),
+ this, SLOT(procError(QProcess::ProcessError)) );
+}
+
+/*!
+ Destroys the assistant client object.
+*/
+QAssistantClient::~QAssistantClient()
+{
+ if ( proc->state() == QProcess::Running )
+ proc->terminate();
+
+ if( dpointers ) {
+ QAssistantClientPrivate *d = (*dpointers)[ this ];
+ if ( d ) {
+ dpointers->remove(this);
+ delete d;
+ if( dpointers->isEmpty() ) {
+ delete dpointers;
+ dpointers = 0;
+ }
+ }
+ }
+}
+
+/*!
+ Opens Qt Assistant, i.e. sets up the client-server communication
+ between the application and Qt Assistant, and shows the start page
+ specified by the current \l {assistant-manual.html}
+ {Qt Assistant Document Profile}. If there is no specfied profile,
+ and Qt is installed, the default start page is the Qt Reference
+ Documentation's index page.
+
+ If the connection is already established, this function does
+ nothing. Use the showPage() function to show another page. If an
+ error occurs, the error() signal is emitted.
+
+ \sa showPage(), assistantOpened()
+*/
+void QAssistantClient::openAssistant()
+{
+ if ( proc->state() == QProcess::Running )
+ return;
+
+ QStringList args;
+ args.append(QLatin1String("-server"));
+ if( !pageBuffer.isEmpty() ) {
+ args.append( QLatin1String("-file") );
+ args.append( pageBuffer );
+ }
+
+ QAssistantClientPrivate *d = data( this );
+ if( d ) {
+ QStringList::ConstIterator it = d->arguments.constBegin();
+ while( it!=d->arguments.constEnd() ) {
+ args.append( *it );
+ ++it;
+ }
+ }
+
+ connect( proc, SIGNAL(readyReadStandardOutput()),
+ this, SLOT(readPort()) );
+
+ proc->start(assistantCommand, args);
+}
+
+void QAssistantClient::procError(QProcess::ProcessError err)
+{
+ switch (err)
+ {
+ case QProcess::FailedToStart:
+ emit error( tr( "Failed to start Qt Assistant." ) );
+ break;
+ case QProcess::Crashed:
+ emit error( tr( "Qt Assistant crashed." ) );
+ break;
+ default:
+ emit error( tr( "Error while running Qt Assistant." ) );
+ }
+}
+
+void QAssistantClient::readPort()
+{
+ QString p(QString::fromLatin1(proc->readAllStandardOutput()));
+ quint16 port = p.toUShort();
+ if ( port == 0 ) {
+ emit error( tr( "Cannot connect to Qt Assistant." ) );
+ return;
+ }
+ socket->connectToHost( host, port );
+ disconnect( proc, SIGNAL(readyReadStandardOutput()),
+ this, SLOT(readPort()) );
+}
+
+/*!
+ Closes the Qt Assistant instance.
+
+ \sa openAssistant(), assistantClosed()
+*/
+void QAssistantClient::closeAssistant()
+{
+ if ( !opened )
+ return;
+
+ bool blocked = proc->blockSignals(true);
+ proc->terminate();
+ if (!proc->waitForFinished(2000)) {
+ // If the process hasn't died after 2 seconds,
+ // we kill it, causing it to exit immediately.
+ proc->kill();
+ }
+ proc->blockSignals(blocked);
+}
+
+/*!
+ Brings Qt Assistant to the foreground showing the given \a page.
+ The \a page parameter is a path to an HTML file
+ (e.g., QLatin1String("/home/pasquale/superproduct/docs/html/intro.html")).
+
+ If Qt Assistant hasn't been opened yet, this function will call
+ the openAssistant() slot with the specified page as the start
+ page.
+
+ \note The first time Qt Assistant is started, its window will open
+ in front of the application's windows. Subsequent calls to this function
+ will only load the specified pages in Qt Assistant and will not display
+ its window in front of the application's windows.
+
+ \sa openAssistant()
+*/
+void QAssistantClient::showPage( const QString &page )
+{
+ if (opened) {
+ QTextStream os( socket );
+ os << page << QLatin1String("\n");
+ } else {
+ pageBuffer = page;
+
+ if (proc->state() == QProcess::NotRunning) {
+ openAssistant();
+ pageBuffer.clear();
+ return;
+ }
+ }
+}
+
+/*!
+ \property QAssistantClient::open
+ \brief whether Qt Assistant is open
+
+*/
+bool QAssistantClient::isOpen() const
+{
+ return opened;
+}
+
+void QAssistantClient::socketConnected()
+{
+ opened = true;
+ if ( !pageBuffer.isEmpty() )
+ showPage( pageBuffer );
+ emit assistantOpened();
+}
+
+void QAssistantClient::socketConnectionClosed()
+{
+ opened = false;
+ emit assistantClosed();
+}
+
+void QAssistantClient::socketError()
+{
+ QAbstractSocket::SocketError err = socket->error();
+ if (err == QTcpSocket::ConnectionRefusedError)
+ emit error( tr( "Could not connect to Assistant: Connection refused" ) );
+ else if (err == QTcpSocket::HostNotFoundError)
+ emit error( tr( "Could not connect to Assistant: Host not found" ) );
+ else if (err != QTcpSocket::RemoteHostClosedError)
+ emit error( tr( "Communication error" ) );
+}
+
+void QAssistantClient::readStdError()
+{
+ QString errmsg = QString::fromLatin1(proc->readAllStandardError());
+
+ if (!errmsg.isEmpty())
+ emit error( errmsg.simplified() );
+}
+
+/*!
+ \fn void QAssistantClient::setArguments(const QStringList &arguments)
+
+ Sets the command line \a arguments that are passed to Qt Assistant
+ when it is launched.
+
+ The command line arguments can be used to alter Qt Assistant's
+ documentation set. When started without any options, Qt Assistant
+ displays a default set of documentation. When Qt is installed, the
+ default documentation set in Qt Assistant contains the Qt
+ reference documentation as well as the tools that come with Qt,
+ such as Qt Designer and qmake.
+*/
+void QAssistantClient::setArguments( const QStringList &args )
+{
+ QAssistantClientPrivate *d = data( this, true );
+ d->arguments = args;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/lib/qassistantclient.h b/tools/assistant/compat/lib/qassistantclient.h
new file mode 100644
index 0000000000..d76246f0b6
--- /dev/null
+++ b/tools/assistant/compat/lib/qassistantclient.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QASSISTANTCLIENT_H
+#define QASSISTANTCLIENT_H
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QProcess>
+#include <QtCore/qglobal.h>
+#include <QtAssistant/qassistantclient_global.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QTcpSocket;
+
+class QT_ASSISTANT_CLIENT_EXPORT QAssistantClient : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY( bool open READ isOpen )
+
+public:
+ QAssistantClient( const QString &path, QObject *parent = 0);
+ ~QAssistantClient();
+
+ bool isOpen() const;
+
+ void setArguments( const QStringList &args );
+
+public Q_SLOTS:
+ virtual void openAssistant();
+ virtual void closeAssistant();
+ virtual void showPage( const QString &page );
+
+Q_SIGNALS:
+ void assistantOpened();
+ void assistantClosed();
+ void error( const QString &msg );
+
+private Q_SLOTS:
+ void socketConnected();
+ void socketConnectionClosed();
+ void readPort();
+ void procError(QProcess::ProcessError err);
+ void socketError();
+ void readStdError();
+
+private:
+ QTcpSocket *socket;
+ QProcess *proc;
+ quint16 port;
+ QString host, assistantCommand, pageBuffer;
+ bool opened;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/assistant/compat/lib/qassistantclient_global.h b/tools/assistant/compat/lib/qassistantclient_global.h
new file mode 100644
index 0000000000..3ae8bb29c8
--- /dev/null
+++ b/tools/assistant/compat/lib/qassistantclient_global.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QASSISTANTCLIENT_GLOBAL_H
+#define QASSISTANTCLIENT_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_ASSISTANT_CLIENT_STATIC) || (!defined(QT_SHARED) && !defined(QT_DLL))
+# define QT_ASSISTANT_CLIENT_EXPORT
+#elif defined(QT_ASSISTANT_CLIENT_LIBRARY)
+# define QT_ASSISTANT_CLIENT_EXPORT Q_DECL_EXPORT
+#else
+# define QT_ASSISTANT_CLIENT_EXPORT Q_DECL_IMPORT
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/assistant/compat/main.cpp b/tools/assistant/compat/main.cpp
new file mode 100644
index 0000000000..66095729c6
--- /dev/null
+++ b/tools/assistant/compat/main.cpp
@@ -0,0 +1,465 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "helpdialog.h"
+#include "config.h"
+
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QApplication>
+#include <QPixmap>
+#include <QStringList>
+#include <QDir>
+#include <QMessageBox>
+#include <QPointer>
+#include <QTranslator>
+#include <QLibraryInfo>
+#include <QLocale>
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(USE_STATIC_JPEG_PLUGIN)
+ #include <QtPlugin>
+ Q_IMPORT_PLUGIN(qjpeg)
+#endif
+
+#define INDEX_CHECK( text ) if( i+1 >= argc ) { fprintf(stderr, "%s\n", text); return 1; }
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusAbstractAdaptor>
+#include <QtDBus/QDBusObjectPath>
+#include "tabbedbrowser.h"
+QT_END_INCLUDE_NAMESPACE
+
+class HelpWindowAdaptor : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpWindow")
+
+ Q_PROPERTY(QString source READ source WRITE setSource)
+
+public:
+ HelpWindowAdaptor(HelpWindow *w) : QDBusAbstractAdaptor(w), helpWindow(w)
+ {
+ setAutoRelaySignals(true);
+ }
+
+public Q_SLOTS:
+ inline QString source() const { return helpWindow->source().toString(); }
+ inline void setSource(const QString &src) { helpWindow->setSource(src); }
+
+ inline void clearHistory() { helpWindow->clearHistory(); }
+ inline void backward() { helpWindow->backward(); }
+ inline void forward() { helpWindow->forward(); }
+ inline void reload() { helpWindow->reload(); }
+ inline void home() { helpWindow->home(); }
+
+private:
+ HelpWindow *helpWindow;
+};
+
+class AssistantAdaptor : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.Assistant.HelpViewer")
+
+public:
+ AssistantAdaptor(MainWindow *mw) : QDBusAbstractAdaptor(mw), mw(mw)
+ {
+ QDBusConnection connection = QDBusConnection::sessionBus();
+ connection.registerService(QLatin1String("com.trolltech.Assistant"));
+ connection.registerObject(QLatin1String("/Assistant"), mw);
+ }
+
+public slots:
+ void showLink(const QString &link) { mw->showLink(link); }
+ QDBusObjectPath createNewTab();
+ QDBusObjectPath currentTab();
+
+private:
+ QDBusObjectPath pathForBrowser(HelpWindow *window);
+ MainWindow *mw;
+};
+
+QDBusObjectPath AssistantAdaptor::createNewTab()
+{
+ HelpWindow *window = mw->browsers()->newBackgroundTab();
+ return pathForBrowser(window);
+}
+
+QDBusObjectPath AssistantAdaptor::currentTab()
+{
+ HelpWindow *window = mw->browsers()->currentBrowser();
+ return pathForBrowser(window);
+}
+
+QDBusObjectPath AssistantAdaptor::pathForBrowser(HelpWindow *window)
+{
+ int index = mw->browsers()->browsers().indexOf(window);
+ if (index == -1)
+ return QDBusObjectPath();
+
+ QString name(QLatin1String("/Assistant/Tabs/"));
+ name += QString::number(index);
+ QDBusObjectPath path(name);
+
+ if (!window->findChild<HelpWindowAdaptor *>()) {
+ (void)new HelpWindowAdaptor(window);
+ QDBusConnection::sessionBus().registerObject(name, window);
+ }
+
+ return path;
+}
+
+#endif // QT_NO_DBUS
+
+class AssistantSocket : public QTcpSocket
+{
+ Q_OBJECT
+public:
+ AssistantSocket( int sock, QObject *parent = 0 );
+ ~AssistantSocket() {}
+
+signals:
+ void showLinkRequest( const QString& );
+
+private slots:
+ void readClient();
+ void connectionClosed();
+};
+
+
+class AssistantServer : public QTcpServer
+{
+ Q_OBJECT
+public:
+ AssistantServer( QObject* parent = 0 );
+ quint16 getPort() const;
+
+signals:
+ void showLinkRequest( const QString& );
+ void newConnect();
+
+public slots:
+ virtual void incomingConnection( int socket );
+
+private:
+ quint16 p;
+};
+
+AssistantSocket::AssistantSocket( int sock, QObject *parent )
+ : QTcpSocket( parent )
+{
+ connect( this, SIGNAL(readyRead()), SLOT(readClient()) );
+ connect( this, SIGNAL(disconnected()), SLOT(connectionClosed()) );
+ setSocketDescriptor( sock );
+}
+
+void AssistantSocket::readClient()
+{
+ QString link = QString();
+ while ( canReadLine() )
+ link = QLatin1String(readLine());
+ if ( !link.isNull() ) {
+ link = link.replace(QLatin1String("\n"), QLatin1String(""));
+ link = link.replace(QLatin1String("\r"), QLatin1String(""));
+ QFileInfo fi(link);
+ link = fi.absoluteFilePath();
+ emit showLinkRequest( link );
+ }
+}
+
+void AssistantSocket::connectionClosed()
+{
+ deleteLater();
+}
+
+AssistantServer::AssistantServer( QObject *parent )
+ : QTcpServer( parent )
+{
+ listen(QHostAddress::LocalHost, 0);
+ if ( !isListening() ) {
+ QMessageBox::critical( 0, tr( "Qt Assistant" ),
+ tr( "Failed to bind to port %1" ).arg( serverPort() ) );
+ exit( 1 );
+ }
+ p = serverPort();
+}
+
+quint16 AssistantServer::getPort() const
+{
+ return p;
+}
+
+void AssistantServer::incomingConnection( int socket )
+{
+ AssistantSocket *as = new AssistantSocket( socket, this );
+ connect( as, SIGNAL(showLinkRequest(QString)),
+ this, SIGNAL(showLinkRequest(QString)) );
+ emit newConnect();
+}
+
+int runAssistant( int argc, char ** argv )
+{
+ bool withGUI = true;
+#ifndef Q_WS_WIN
+ if ( argc > 1 ) {
+ QString arg = QString::fromLocal8Bit(argv[1]);
+ arg = arg.toLower();
+ if ( arg == QLatin1String("-addcontentfile")
+ || arg == QLatin1String("-removecontentfile")
+ || arg == QLatin1String("-help")
+ || arg == QLatin1String("/?")
+ )
+ withGUI = false;
+ }
+#endif
+ QApplication a(argc, argv, withGUI);
+ a.setOrganizationName(QLatin1String("Trolltech"));
+ a.setApplicationName(QLatin1String("Assistant"));
+
+ QString resourceDir;
+ AssistantServer *as = 0;
+ QStringList catlist;
+ QString file, profileName, aDocPath;
+ bool server = false;
+ bool hideSidebar = false;
+ bool configLoaded = false;
+ if ( argc == 2 ) {
+ file = QString::fromLocal8Bit(argv[1]);
+ if (file.startsWith(QLatin1String("-")) || file == QLatin1String("/?")) {
+ file.clear();
+ } else {
+ QFileInfo fi(file);
+ file = fi.absoluteFilePath();
+ file = MainWindow::urlifyFileName(file);
+ }
+ }
+ if ( file.isEmpty() ) {
+ for ( int i = 1; i < argc; i++ ) {
+ QString opt = QString::fromLocal8Bit(argv[i]).toLower();
+ if ( opt == QLatin1String("-file") ) {
+ INDEX_CHECK( "Missing file argument!" );
+ i++;
+ file = QFile::decodeName(argv[i]);
+ } else if ( opt == QLatin1String("-server") ) {
+ server = true;
+ } else if ( opt == QLatin1String("-profile") ) {
+ INDEX_CHECK( "Missing profile argument!" );
+ profileName = QFile::decodeName(argv[++i]);
+ } else if ( opt == QLatin1String("-addcontentfile") ) {
+ INDEX_CHECK( "Missing content file!" );
+ Config *c = Config::loadConfig(QString());
+ QFileInfo file( QFile::decodeName(argv[i+1]) );
+ if( !file.exists() ) {
+ fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath()));
+ return 1;
+ }
+ DocuParser *parser = DocuParser::createParser( file.absoluteFilePath() );
+ if( parser ) {
+ QFile f( QFile::decodeName(argv[i+1]) );
+ if( !parser->parse( &f ) ) {
+ fprintf(stderr, "Failed to parse file: %s\n", qPrintable(file.absoluteFilePath()));
+ return 1;
+ }
+ parser->addTo( c->profile() );
+ c->setDocRebuild( true );
+ c->save();
+ }
+ return 0;
+ } else if ( opt == QLatin1String("-removecontentfile") ) {
+ INDEX_CHECK("Missing content file!");
+ Config *c = Config::loadConfig(QString());
+ Profile *profile = c->profile();
+ QString contentFile = QString::fromLocal8Bit(argv[i+i]);
+ QStringList entries;
+#ifdef Q_WS_WIN
+ contentFile.replace(QLatin1Char('\\'), QLatin1Char('/'));
+ entries = profile->docs.filter(contentFile, Qt::CaseInsensitive);
+#else
+ entries = profile->docs.filter(contentFile);
+#endif
+ if (entries.count() == 0) {
+ fprintf(stderr, "Could not locate content file: %s\n", qPrintable(contentFile));
+ return 1;
+ } else if (entries.count() > 1) {
+ fprintf(stderr, "More than one entry matching file name found, "
+ "please specify full path to file");
+ return 1;
+ } else {
+ QFileInfo file(entries[0]);
+ if( !file.exists() ) {
+ fprintf(stderr, "Could not locate content file: %s\n", qPrintable(file.absoluteFilePath()));
+ return 1;
+ }
+ profile->removeDocFileEntry( file.absoluteFilePath() );
+ c->setDocRebuild( true );
+ c->save();
+ }
+ return 0;
+ } else if ( QString( QLatin1String(argv[i]) ).toLower() == QLatin1String("-docpath") ) {
+ INDEX_CHECK( "Missing path!" );
+ QDir dir(QString::fromLocal8Bit(argv[i+1]));
+ if ( dir.exists() ) {
+ Config *c = Config::loadConfig(QString());
+ c->saveProfile(Profile::createDefaultProfile(dir.absolutePath()));
+ c->loadDefaultProfile();
+ c->setDocRebuild(true);
+ c->save();
+ configLoaded = true;
+ ++i;
+ } else {
+ fprintf(stderr, "The specified path does not exist!\n");
+ return 1;
+ }
+ } else if ( opt == QLatin1String("-hidesidebar") ) {
+ hideSidebar = true;
+ } else if ( opt == QLatin1String("-help") || opt == QLatin1String("/?") ) {
+ QString helpText = QLatin1String( "Usage: assistant [option]\n"
+ "Options:\n"
+ " -file Filename assistant opens the specified file\n"
+ " -server reads commands from a socket after\n"
+ " assistant has started\n"
+ " -profile fileName starts assistant and displays the\n"
+ " profile specified in the file fileName.\n"
+ " -addContentFile file adds the content file 'file' to the set of\n"
+ " documentation available by default\n"
+ " -removeContentFile file removes the content file 'file' from the\n"
+ " documentation available by default\n"
+ " -docPath path sets the Qt documentation root path to\n"
+ " 'path' and starts assistant\n"
+ " -hideSidebar assistant will hide the sidebar.\n"
+ " -resourceDir assistant will load translations from\n"
+ " this directory.\n"
+ " -help shows this help.");
+#ifdef Q_WS_WIN
+ QMessageBox::information( 0, QLatin1String("Qt Assistant"),
+ QLatin1String("<pre>") + helpText + QLatin1String("</pre>") );
+#else
+ fprintf(stdout, "%s\n", qPrintable(helpText));
+#endif
+ exit( 0 );
+ } else if ( opt == QLatin1String("-resourcedir") ) {
+ INDEX_CHECK( "Missing resource directory argument!" );
+ resourceDir = QFile::decodeName( argv[++i] );
+ } else {
+ fprintf(stderr, "Unrecognized option %s. Try -help to get help.\n", qPrintable(opt));
+ return 1;
+ }
+ }
+ }
+
+ if( resourceDir.isNull() )
+ resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+
+ QTranslator translator( 0 );
+ translator.load( QLatin1String("assistant_adp_") + QLocale::system().name(), resourceDir );
+ a.installTranslator( &translator );
+
+ QTranslator qtTranslator( 0 );
+ qtTranslator.load( QLatin1String("qt_") + QLocale::system().name(), resourceDir );
+ a.installTranslator( &qtTranslator );
+
+ Config *conf = 0;
+ if (configLoaded)
+ conf = Config::configuration();
+ else
+ conf = Config::loadConfig( profileName );
+ if (!conf) {
+ fprintf( stderr, "Profile '%s' does not exist!\n", profileName.toLatin1().constData() );
+ fflush( stderr );
+ return -1;
+ }
+
+ QStringList links = conf->source();
+ conf->hideSideBar( hideSidebar );
+
+ QPointer<MainWindow> mw = new MainWindow();
+ mw->setObjectName(QLatin1String("Assistant"));
+
+ if ( server ) {
+ as = new AssistantServer();
+ printf("%d\n", as->serverPort() );
+ fflush( stdout );
+ as->connect( as, SIGNAL(showLinkRequest(QString)),
+ mw, SLOT(showLinkFromClient(QString)) );
+ }
+
+#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX)
+ new AssistantAdaptor(mw);
+#endif // QT_NO_DBUS
+
+ FontSettings settings = conf->fontSettings();
+ if (mw->font() != settings.windowFont)
+ a.setFont(settings.windowFont, "QWidget");
+
+#ifdef Q_WS_MAC
+ // Make sure AssitantClient shows the window in front.
+ mw->raise();
+#endif
+ mw->show();
+
+ if (!file.isEmpty())
+ mw->showLink( MainWindow::urlifyFileName(file) );
+ else if (file.isEmpty())
+ mw->showLinks( links );
+
+ a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) );
+
+ int appExec = a.exec();
+ delete (MainWindow*)mw;
+ return appExec;
+}
+
+QT_END_NAMESPACE
+
+int main( int argc, char ** argv )
+{
+ Q_INIT_RESOURCE(assistant);
+ return QT_PREPEND_NAMESPACE(runAssistant)(argc, argv);
+}
+
+#include "main.moc"
diff --git a/tools/assistant/compat/mainwindow.cpp b/tools/assistant/compat/mainwindow.cpp
new file mode 100644
index 0000000000..65759ade6c
--- /dev/null
+++ b/tools/assistant/compat/mainwindow.cpp
@@ -0,0 +1,901 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "tabbedbrowser.h"
+#include "helpdialog.h"
+#include "config.h"
+#include "fontsettingsdialog.h"
+
+#include <QDockWidget>
+#include <QDir>
+#include <QTimer>
+#include <QStatusBar>
+#include <QShortcut>
+#include <QMessageBox>
+#include <QPainter>
+#include <QEventLoop>
+#include <QtEvents>
+#include <QFontDatabase>
+#include <QWhatsThis>
+#include <QTextDocumentFragment>
+#include <QLibraryInfo>
+#include <QPrinter>
+#include <QPrintDialog>
+#include <QAbstractTextDocumentLayout>
+#include <QTextDocument>
+#include <QTextObject>
+#include <QFileDialog>
+#include <QThread>
+
+QT_BEGIN_NAMESPACE
+
+QList<MainWindow*> MainWindow::windows;
+
+#if defined(Q_WS_WIN)
+extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
+#endif
+
+MainWindow::MainWindow()
+{
+ setUnifiedTitleAndToolBarOnMac(true);
+ ui.setupUi(this);
+
+#if defined(Q_WS_WIN)
+ // Workaround for QMimeSourceFactory failing in QFileInfo::isReadable() for
+ // certain user configs. See task: 34372
+ qt_ntfs_permission_lookup = 0;
+#endif
+ setupCompleted = false;
+
+ goActions = QList<QAction*>();
+ goActionDocFiles = new QMap<QAction*,QString>;
+
+ windows.append(this);
+ tabs = new TabbedBrowser(this);
+ connect(tabs, SIGNAL(tabCountChanged(int)), this, SLOT(updateTabActions(int)));
+ setCentralWidget(tabs);
+
+ Config *config = Config::configuration();
+
+ updateProfileSettings();
+
+ dw = new QDockWidget(this);
+ dw->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ dw->setWindowTitle(tr("Sidebar"));
+ dw->setObjectName(QLatin1String("sidebar"));
+ helpDock = new HelpDialog(dw, this);
+ dw->setWidget(helpDock);
+
+ addDockWidget(Qt::LeftDockWidgetArea, dw);
+
+ // read geometry configuration
+ setupGoActions();
+
+ restoreGeometry(config->windowGeometry());
+ restoreState(config->mainWindowState());
+ if (config->sideBarHidden())
+ dw->hide();
+
+ tabs->setup();
+ QTimer::singleShot(0, this, SLOT(setup()));
+#if defined(Q_WS_MAC)
+ QMenu *windowMenu = new QMenu(tr("&Window"), this);
+ menuBar()->insertMenu(ui.helpMenu->menuAction(), windowMenu);
+ windowMenu->addAction(tr("Minimize"), this,
+ SLOT(showMinimized()), QKeySequence(tr("Ctrl+M")));
+ // Use the same forward and backward browser shortcuts as Safari and Internet Explorer do
+ // on the Mac. This means that if you have access to one of those cool Intellimice, the thing
+ // works just fine, since that's how Microsoft hacked it.
+ ui.actionGoPrevious->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Left));
+ ui.actionGoNext->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Right));
+
+ static const QLatin1String MacIconPath(":/trolltech/assistant/images/mac");
+ ui.actionGoNext->setIcon(QIcon(MacIconPath + QLatin1String("/next.png")));
+ ui.actionGoPrevious->setIcon(QIcon(MacIconPath + QLatin1String("/prev.png")));
+ ui.actionGoHome->setIcon(QIcon(MacIconPath + QLatin1String("/home.png")));
+ ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png")));
+ ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png")));
+ ui.actionEditFind->setIcon(QIcon(MacIconPath + QLatin1String("/find.png")));
+ ui.actionFilePrint->setIcon(QIcon(MacIconPath + QLatin1String("/print.png")));
+ ui.actionZoomOut->setIcon(QIcon(MacIconPath + QLatin1String("/zoomout.png")));
+ ui.actionZoomIn->setIcon(QIcon(MacIconPath + QLatin1String("/zoomin.png")));
+ ui.actionSyncToc->setIcon(QIcon(MacIconPath + QLatin1String("/synctoc.png")));
+ ui.actionHelpWhatsThis->setIcon(QIcon(MacIconPath + QLatin1String("/whatsthis.png")));
+#endif
+}
+
+MainWindow::~MainWindow()
+{
+ windows.removeAll(this);
+ delete goActionDocFiles;
+}
+
+void MainWindow::setup()
+{
+ if(setupCompleted)
+ return;
+
+ qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+ statusBar()->showMessage(tr("Initializing Qt Assistant..."));
+ setupCompleted = true;
+ helpDock->initialize();
+ connect(ui.actionGoPrevious, SIGNAL(triggered()), tabs, SLOT(backward()));
+ connect(ui.actionGoNext, SIGNAL(triggered()), tabs, SLOT(forward()));
+ connect(ui.actionEditCopy, SIGNAL(triggered()), tabs, SLOT(copy()));
+ connect(ui.actionFileExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
+ connect(ui.actionAddBookmark, SIGNAL(triggered()),
+ helpDock, SLOT(addBookmark()));
+ connect(helpDock, SIGNAL(showLink(QString)),
+ this, SLOT(showLink(QString)));
+ connect(helpDock, SIGNAL(showSearchLink(QString,QStringList)),
+ this, SLOT(showSearchLink(QString,QStringList)));
+
+ connect(ui.bookmarkMenu, SIGNAL(triggered(QAction*)),
+ this, SLOT(showBookmark(QAction*)));
+ connect(ui.actionZoomIn, SIGNAL(triggered()), tabs, SLOT(zoomIn()));
+ connect(ui.actionZoomOut, SIGNAL(triggered()), tabs, SLOT(zoomOut()));
+
+ connect(ui.actionOpenPage, SIGNAL(triggered()), tabs, SLOT(newTab()));
+ connect(ui.actionClosePage, SIGNAL(triggered()), tabs, SLOT(closeTab()));
+ connect(ui.actionNextPage, SIGNAL(triggered()), tabs, SLOT(nextTab()));
+ connect(ui.actionPrevPage, SIGNAL(triggered()), tabs, SLOT(previousTab()));
+
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64)
+ QShortcut *acc = new QShortcut(tr("SHIFT+CTRL+="), this);
+ connect(acc, SIGNAL(activated()), ui.actionZoomIn, SIGNAL(triggered()));
+#endif
+
+ connect(new QShortcut(tr("Ctrl+T"), this), SIGNAL(activated()), helpDock, SLOT(toggleContents()));
+ connect(new QShortcut(tr("Ctrl+I"), this), SIGNAL(activated()), helpDock, SLOT(toggleIndex()));
+ connect(new QShortcut(tr("Ctrl+B"), this), SIGNAL(activated()), helpDock, SLOT(toggleBookmarks()));
+ connect(new QShortcut(tr("Ctrl+S"), this), SIGNAL(activated()), helpDock, SLOT(toggleSearch()));
+ connect(new QShortcut(tr("Ctrl+]"), this), SIGNAL(activated()), tabs, SLOT(nextTab()));
+ connect(new QShortcut(tr("Ctrl+["), this), SIGNAL(activated()), tabs, SLOT(previousTab()));
+
+ Config *config = Config::configuration();
+
+ setupBookmarkMenu();
+
+ QAction *viewsAction = createPopupMenu()->menuAction();
+ viewsAction->setText(tr("Views"));
+ ui.viewMenu->addAction(viewsAction);
+
+ const int tabIndex = config->sideBarPage();
+ helpDock->tabWidget()->setCurrentIndex(tabIndex);
+ // The tab index is 0 by default, so we need to force an upate
+ // to poulate the contents in this case.
+ if (tabIndex == 0)
+ helpDock->currentTabChanged(tabIndex);
+
+ ui.actionEditFind->setShortcut(QKeySequence::Find);
+ ui.actionEditFindNext->setShortcut(QKeySequence::FindNext);
+ ui.actionEditFindPrev->setShortcut(QKeySequence::FindPrevious);
+
+ QObject::connect(ui.actionEditFind, SIGNAL(triggered()), tabs, SLOT(find()));
+ QObject::connect(ui.actionEditFindNext, SIGNAL(triggered()), tabs, SLOT(findNext()));
+ QObject::connect(ui.actionEditFindPrev, SIGNAL(triggered()), tabs, SLOT(findPrevious()));
+ connect(ui.actionEditFont_Settings, SIGNAL(triggered()), this, SLOT(showFontSettingsDialog()));
+
+ qApp->restoreOverrideCursor();
+ ui.actionGoPrevious->setEnabled(false);
+ ui.actionGoNext->setEnabled(false);
+ ui.actionEditCopy->setEnabled(false);
+
+ // set the current selected item in the treeview
+ helpDialog()->locateContents(tabs->currentBrowser()->source().toString());
+ connect(tabs, SIGNAL(browserUrlChanged(QString)), helpDock, SLOT(locateContents(QString)));
+}
+
+void MainWindow::browserTabChanged()
+{
+ HelpWindow *win = tabs->currentBrowser();
+ if (win) {
+ QTextCursor cursor(win->textCursor());
+ ui.actionEditCopy->setEnabled(cursor.hasSelection());
+ ui.actionGoPrevious->setEnabled(win->isBackwardAvailable());
+ ui.actionGoNext->setEnabled(win->isForwardAvailable());
+ }
+}
+
+void MainWindow::copyAvailable(bool yes)
+{
+ ui.actionEditCopy->setEnabled(yes);
+}
+
+void MainWindow::updateTabActions(int index)
+{
+ bool enabled = (index > 1) ? true : false;
+ ui.actionPrevPage->setEnabled(enabled);
+ ui.actionNextPage->setEnabled(enabled);
+ ui.actionClosePage->setEnabled(enabled);
+}
+
+void MainWindow::setupGoActions()
+{
+ Config *config = Config::configuration();
+ QStringList titles = config->docTitles();
+ QAction *action = 0;
+
+ static bool separatorInserted = false;
+
+ foreach (QAction *a, goActions) {
+ ui.goMenu->removeAction(a);
+ ui.goActionToolbar->removeAction(a);
+ }
+ qDeleteAll(goActions);
+ goActions.clear();
+ goActionDocFiles->clear();
+
+ int addCount = 0;
+
+ foreach (QString title, titles) {
+ QPixmap pix = config->docIcon(title);
+ if(!pix.isNull()) {
+ if(!separatorInserted) {
+ ui.goMenu->addSeparator();
+ separatorInserted = true;
+ }
+ action = new QAction(this);
+ action->setText(title);
+ action->setWhatsThis(tr("Displays the main page of a specific documentation set."));
+ action->setIcon(QIcon(pix));
+ ui.goMenu->addAction(action);
+ ui.goActionToolbar->addAction(action);
+ goActions.append(action);
+ goActionDocFiles->insert(action, config->indexPage(title));
+ connect(action, SIGNAL(triggered()),
+ this, SLOT(showGoActionLink()));
+ ++addCount;
+ }
+ }
+ if(!addCount)
+ ui.goActionToolbar->hide();
+ else
+ ui.goActionToolbar->show();
+
+}
+
+bool MainWindow::insertActionSeparator()
+{
+ ui.goMenu->addSeparator();
+ ui.Toolbar->addSeparator();
+ return true;
+}
+
+void MainWindow::closeEvent(QCloseEvent *e)
+{
+ saveSettings();
+ e->accept();
+}
+
+void MainWindow::about()
+{
+ QMessageBox box(this);
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ QString edition = tr("Open Source Edition");
+ QString info = tr("This version of Qt Assistant is part of the Qt Open Source Edition, for use "
+ "in the development of Open Source applications. "
+ "Qt is a comprehensive C++ framework for cross-platform application "
+ "development.");
+ QString moreInfo = tr("You need a commercial Qt license for development of proprietary (closed "
+ "source) applications. Please see <a href=\"http://qtsoftware.com/company/model"
+ "\">qtsoftware.com/company/model</a> for an overview of Qt licensing.");
+#elif defined(QT_PRODUCT_LICENSE)
+ QString edition;
+ QString info;
+ QString moreInfo(tr("This program is licensed to you under the terms of the "
+ "Qt %1 License Agreement. For details, see the license file "
+ "that came with this software distribution.").arg(QLatin1String(QT_PRODUCT_LICENSE)));
+#else
+ QString edition;
+ QString info;
+ QString moreInfo(tr("This program is licensed to you under the terms of the "
+ "Qt Commercial License Agreement. For details, see the file LICENSE "
+ "that came with this software distribution."));
+
+#endif
+
+ box.setText(QString::fromLatin1("<center><img src=\":/trolltech/assistant/images/assistant-128.png\">"
+ "<h3>%1</h3>"
+ "<p>Version %2 %3</p></center>"
+ "<p>%4</p>"
+ "<p>%5</p>"
+ "<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>"
+ "<p>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
+ " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
+ " PARTICULAR PURPOSE.<p/>")
+ .arg(tr("Qt Assistant")).arg(QLatin1String(QT_VERSION_STR)).arg(edition).arg(info).arg(moreInfo));
+ box.setWindowTitle(tr("Qt Assistant"));
+ box.setIcon(QMessageBox::NoIcon);
+ box.exec();
+}
+
+void MainWindow::on_actionAboutApplication_triggered()
+{
+ QString url = Config::configuration()->aboutURL();
+ if (url == QLatin1String("about_qt")) {
+ QMessageBox::aboutQt(this, QLatin1String("Qt Assistant"));
+ return;
+ }
+ QString text;
+ if (url.startsWith(QLatin1String("file:")))
+ url = url.mid(5);
+ QFile file(url);
+ if(file.exists() && file.open(QFile::ReadOnly))
+ text = QString::fromUtf8(file.readAll());
+ if(text.isNull())
+ text = tr("Failed to open about application contents in file: '%1'").arg(url);
+
+ QFileInfo fi(file);
+ QString path = QDir::cleanPath(fi.absolutePath());
+ if (!QDir::searchPaths(QLatin1String("aboutImages")).contains(path))
+ QDir::addSearchPath(QLatin1String("aboutImages"), path);
+
+ QMessageBox box(this);
+ box.setText(text);
+ box.setWindowTitle(Config::configuration()->aboutApplicationMenuText());
+ box.setIcon(QMessageBox::NoIcon);
+ box.exec();
+}
+
+void MainWindow::on_actionAboutAssistant_triggered()
+{
+ about();
+}
+
+void MainWindow::on_actionGoHome_triggered()
+{
+ QString home = MainWindow::urlifyFileName(Config::configuration()->homePage());
+ showLink(home);
+}
+
+QString MainWindow::urlifyFileName(const QString &fileName)
+{
+ QString name = fileName;
+ QUrl url(name);
+
+#if defined(Q_OS_WIN32)
+ if (!url.isValid() || url.scheme().isEmpty() || url.scheme().toLower() != QLatin1String("file:")) {
+ int i = name.indexOf(QLatin1Char('#'));
+ QString anchor = name.mid(i);
+ name = name.toLower();
+ if (i > -1)
+ name.replace(i, anchor.length(), anchor);
+ name.replace(QLatin1Char('\\'), QLatin1Char('/'));
+ foreach (QFileInfo drive, QDir::drives()) {
+ if (name.startsWith(drive.absolutePath().toLower())) {
+ name = QLatin1String("file:") + name;
+ break;
+ }
+ }
+ }
+#else
+ if (!url.isValid() || url.scheme().isEmpty())
+ name.prepend(QLatin1String("file:"));
+#endif
+ return name;
+}
+
+class PrintThread : public QThread
+{
+ QPrinter _printer;
+ QTextDocument *_document;
+
+public:
+ PrintThread(QObject *parent)
+ : QThread(parent), _printer(QPrinter::HighResolution), _document(0)
+ {
+ }
+ ~PrintThread()
+ {
+ wait();
+ }
+
+ QPrinter *printer()
+ {
+ return &_printer;
+ }
+
+ void start(QTextDocument *document)
+ {
+ _document = document->clone();
+ _document->moveToThread(this);
+ QThread::start();
+ }
+
+protected:
+ void run()
+ {
+ _document->print(printer());
+ delete _document;
+ _document = 0;
+ }
+};
+
+void MainWindow::on_actionFilePrint_triggered()
+{
+#ifndef QT_NO_PRINTER
+ if (!QFontDatabase::supportsThreadedFontRendering()) {
+ QPrinter printer(QPrinter::HighResolution);
+
+ QPrintDialog dlg(&printer, this);
+ if (dlg.exec() == QDialog::Accepted) {
+ qApp->setOverrideCursor(Qt::WaitCursor);
+ tabs->currentBrowser()->document()->print(&printer);
+ qApp->restoreOverrideCursor();
+ }
+ return;
+ }
+
+ PrintThread *thread = new PrintThread(this);
+
+ QPrintDialog dlg(thread->printer(), this);
+ if (dlg.exec() == QDialog::Accepted) {
+ connect(thread, SIGNAL(finished()), SLOT(printingFinished()));
+ connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
+
+ qApp->setOverrideCursor(Qt::BusyCursor);
+ thread->start(tabs->currentBrowser()->document());
+ } else {
+ delete thread;
+ }
+#else
+ Q_ASSERT("No printing support");
+#endif
+}
+
+void MainWindow::printingFinished()
+{
+ qApp->restoreOverrideCursor();
+}
+
+void MainWindow::updateBookmarkMenu()
+{
+ for(QList<MainWindow*>::Iterator it = windows.begin(); it != windows.end(); ++it)
+ (*it)->setupBookmarkMenu();
+}
+
+void MainWindow::setupBookmarkMenu()
+{
+ ui.bookmarkMenu->clear();
+ bookmarks.clear();
+ ui.bookmarkMenu->addAction(ui.actionAddBookmark);
+
+ QFile f(QDir::homePath() + QLatin1String("/.assistant/bookmarks.") +
+ Config::configuration()->profileName());
+ if (!f.open(QFile::ReadOnly))
+ return;
+ QTextStream ts(&f);
+ ui.bookmarkMenu->addSeparator();
+ while (!ts.atEnd()) {
+ QString title = ts.readLine();
+ QString link = ts.readLine();
+ bookmarks.insert(ui.bookmarkMenu->addAction(title), link);
+ }
+}
+
+void MainWindow::showBookmark(QAction *action)
+{
+ if (bookmarks.contains(action))
+ showLink(bookmarks.value(action));
+}
+
+void MainWindow::showLinkFromClient(const QString &link)
+{
+ setWindowState(windowState() & ~Qt::WindowMinimized);
+ raise();
+ activateWindow();
+ QString l = MainWindow::urlifyFileName(link);
+ showLink(l);
+ if (isMinimized())
+ showNormal();
+}
+
+void MainWindow::showLink(const QString &link)
+{
+ if(link.isEmpty())
+ qWarning("The link is empty!");
+
+ // don't fill the history with the same url more then once
+ if (link == tabs->currentBrowser()->source().toString())
+ return;
+
+ QUrl url(link);
+ QFileInfo fi(url.toLocalFile());
+ tabs->setSource(url.toString());
+ tabs->currentBrowser()->setFocus();
+}
+
+void MainWindow::showLinks(const QStringList &links)
+{
+ if (links.size() == 0) {
+ qWarning("MainWindow::showLinks() - Empty link");
+ return;
+ }
+
+ if (links.size() == 1) {
+ showLink(MainWindow::urlifyFileName(links.first()));
+ return;
+ }
+
+ QStringList::ConstIterator it = links.begin();
+ // Initial showing, The tab is empty so update that without creating it first
+ if (!tabs->currentBrowser()->source().isValid()) {
+ QPair<HelpWindow*, QString> browser;
+ browser.first = tabs->currentBrowser();
+ browser.second = links.first();
+ pendingBrowsers.append(browser);
+ tabs->setTitle(tabs->currentBrowser(), tr("..."));
+ }
+ ++it;
+
+ while(it != links.end()) {
+ QPair<HelpWindow*, QString> browser;
+ browser.first = tabs->newBackgroundTab();
+ browser.second = *it;
+ pendingBrowsers.append(browser);
+ ++it;
+ }
+
+ startTimer(50);
+ return;
+}
+
+void MainWindow::removePendingBrowser(HelpWindow *win)
+{
+ if (!pendingBrowsers.count())
+ return;
+
+ QMutableListIterator<QPair<HelpWindow*, QString> > it(pendingBrowsers);
+ while (it.hasNext()) {
+ QPair<HelpWindow*, QString> browser = it.next();
+ if (browser.first == win) {
+ it.remove();
+ break;
+ }
+ }
+}
+
+void MainWindow::timerEvent(QTimerEvent *e)
+{
+ QPair<HelpWindow*, QString> browser = pendingBrowsers.first();
+ pendingBrowsers.pop_front();
+
+ if (pendingBrowsers.size() == 0)
+ killTimer(e->timerId());
+
+ browser.first->setSource(MainWindow::urlifyFileName(browser.second));
+}
+
+void MainWindow::showQtHelp()
+{
+ showLink(QLibraryInfo::location(QLibraryInfo::DocumentationPath) +
+ QLatin1String("/html/index.html"));
+}
+
+MainWindow* MainWindow::newWindow()
+{
+ saveSettings();
+ MainWindow *mw = new MainWindow;
+ mw->move(geometry().topLeft());
+ if (isMaximized())
+ mw->showMaximized();
+ else
+ mw->show();
+ mw->on_actionGoHome_triggered();
+ return mw;
+}
+
+void MainWindow::saveSettings()
+{
+ Config *config = Config::configuration();
+
+ config->setSideBarPage(helpDock->tabWidget()->currentIndex());
+ config->setWindowGeometry(saveGeometry());
+ config->setMainWindowState(saveState());
+
+ // Create list of the tab urls
+ QStringList lst;
+ QList<HelpWindow*> browsers = tabs->browsers();
+ foreach (HelpWindow *browser, browsers)
+ lst << browser->source().toString();
+ config->setSource(lst);
+ config->save();
+}
+
+TabbedBrowser* MainWindow::browsers() const
+{
+ return tabs;
+}
+
+void MainWindow::showSearchLink(const QString &link, const QStringList &terms)
+{
+ HelpWindow * hw = tabs->currentBrowser();
+ hw->blockScrolling(true);
+ hw->setCursor(Qt::WaitCursor);
+ if (hw->source() == link)
+ hw->reload();
+ else
+ showLink(link);
+ hw->setCursor(Qt::ArrowCursor);
+
+ hw->viewport()->setUpdatesEnabled(false);
+
+ QTextCharFormat marker;
+ marker.setForeground(Qt::red);
+
+ QTextCursor firstHit;
+
+ QTextCursor c = hw->textCursor();
+ c.beginEditBlock();
+ foreach (QString term, terms) {
+ c.movePosition(QTextCursor::Start);
+ hw->setTextCursor(c);
+
+ bool found = hw->find(term, QTextDocument::FindWholeWords);
+ while (found) {
+ QTextCursor hit = hw->textCursor();
+ if (firstHit.isNull() || hit.position() < firstHit.position())
+ firstHit = hit;
+
+ hit.mergeCharFormat(marker);
+ found = hw->find(term, QTextDocument::FindWholeWords);
+ }
+ }
+
+ if (firstHit.isNull()) {
+ firstHit = hw->textCursor();
+ firstHit.movePosition(QTextCursor::Start);
+ }
+ firstHit.clearSelection();
+ c.endEditBlock();
+ hw->setTextCursor(firstHit);
+
+ hw->blockScrolling(false);
+ hw->viewport()->setUpdatesEnabled(true);
+}
+
+
+void MainWindow::showGoActionLink()
+{
+ const QObject *origin = sender();
+ if(!origin ||
+ QString::fromLatin1(origin->metaObject()->className()) != QString::fromLatin1("QAction"))
+ return;
+
+ QAction *action = (QAction*) origin;
+ QString docfile = *(goActionDocFiles->find(action));
+ showLink(MainWindow::urlifyFileName(docfile));
+}
+
+void MainWindow::on_actionHelpAssistant_triggered()
+{
+ showLink(Config::configuration()->assistantDocPath() + QLatin1String("/assistant-manual.html"));
+}
+
+HelpDialog* MainWindow::helpDialog() const
+{
+ return helpDock;
+}
+
+void MainWindow::backwardAvailable(bool enable)
+{
+ ui.actionGoPrevious->setEnabled(enable);
+}
+
+void MainWindow::forwardAvailable(bool enable)
+{
+ ui.actionGoNext->setEnabled(enable);
+}
+
+void MainWindow::updateProfileSettings()
+{
+ Config *config = Config::configuration();
+#ifndef Q_WS_MAC
+ setWindowIcon(config->applicationIcon());
+#endif
+ ui.helpMenu->clear();
+ //ui.helpMenu->addAction(ui.actionHelpAssistant);
+ //ui.helpMenu->addSeparator();
+ ui.helpMenu->addAction(ui.actionAboutAssistant);
+ if (!config->aboutApplicationMenuText().isEmpty())
+ ui.helpMenu->addAction(ui.actionAboutApplication);
+ ui.helpMenu->addSeparator();
+ ui.helpMenu->addAction(ui.actionHelpWhatsThis);
+
+ ui.actionAboutApplication->setText(config->aboutApplicationMenuText());
+
+ if(!config->title().isNull())
+ setWindowTitle(config->title());
+}
+
+void MainWindow::setupPopupMenu(QMenu *m)
+{
+ m->addAction(ui.actionNewWindow);
+ m->addAction(ui.actionOpenPage);
+ m->addAction(ui.actionClosePage);
+ m->addSeparator();
+ m->addAction(ui.actionSaveAs);
+ m->addSeparator();
+ m->addAction(ui.actionGoPrevious);
+ m->addAction(ui.actionGoNext);
+ m->addAction(ui.actionGoHome);
+ m->addSeparator();
+ m->addAction(ui.actionZoomIn);
+ m->addAction(ui.actionZoomOut);
+ m->addSeparator();
+ m->addAction(ui.actionEditCopy);
+ m->addAction(ui.actionEditFind);
+}
+
+void MainWindow::on_actionSyncToc_triggered()
+{
+ HelpWindow *w = tabs->currentBrowser();
+ if(w) {
+ qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+ QString link = w->source().toString();
+ helpDock->locateContents(link);
+ helpDock->tabWidget()->setCurrentIndex(0);
+ qApp->restoreOverrideCursor();
+ }
+}
+
+void MainWindow::on_actionNewWindow_triggered()
+{
+ newWindow()->show();
+}
+
+void MainWindow::on_actionClose_triggered()
+{
+ close();
+}
+
+void MainWindow::on_actionHelpWhatsThis_triggered()
+{
+ QWhatsThis::enterWhatsThisMode();
+}
+
+void MainWindow::on_actionSaveAs_triggered()
+{
+ QString fileName;
+ QUrl url = tabs->currentBrowser()->source();
+ if (url.isValid()) {
+ QFileInfo fi(url.toLocalFile());
+ fileName = fi.fileName();
+ }
+ fileName = QFileDialog::getSaveFileName(this, tr("Save Page"), fileName);
+ if (fileName.isEmpty())
+ return;
+
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox::critical(this, tr("Save Page"), tr("Cannot open file for writing!"));
+ return;
+ }
+
+ QFileInfo fi(fileName);
+ QString fn = fi.fileName();
+ int i = fn.lastIndexOf(QLatin1Char('.'));
+ if (i > -1)
+ fn = fn.left(i);
+ QString relativeDestPath = fn + QLatin1String("_images");
+ QDir destDir(fi.absolutePath() + QDir::separator() + relativeDestPath);
+ bool imgDirAvailable = destDir.exists();
+ if (!imgDirAvailable)
+ imgDirAvailable = destDir.mkdir(destDir.absolutePath());
+
+ // save images
+ QTextDocument *doc = tabs->currentBrowser()->document()->clone();
+ if (url.isValid() && imgDirAvailable) {
+ QTextBlock::iterator it;
+ for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) {
+ for (it = block.begin(); !(it.atEnd()); ++it) {
+ QTextFragment fragment = it.fragment();
+ if (fragment.isValid()) {
+ QTextImageFormat fm = fragment.charFormat().toImageFormat();
+ if (fm.isValid() && !fm.name().isEmpty()) {
+ QUrl imagePath = tabs->currentBrowser()->source().resolved(fm.name());
+ if (!imagePath.isValid())
+ continue;
+ QString from = imagePath.toLocalFile();
+ QString destName = fm.name();
+ int j = destName.lastIndexOf(QLatin1Char('/'));
+ if (j > -1)
+ destName = destName.mid(j+1);
+ QFileInfo info(from);
+ if (info.exists()) {
+ if (!QFile::copy(from, destDir.absolutePath()
+ + QDir::separator() + destName))
+ continue;
+ fm.setName(QLatin1String("./") + relativeDestPath + QLatin1String("/") + destName);
+ QTextCursor cursor(doc);
+ cursor.setPosition(fragment.position());
+ cursor.setPosition(fragment.position() + fragment.length(),
+ QTextCursor::KeepAnchor);
+ cursor.setCharFormat(fm);
+ }
+ }
+ }
+ }
+ }
+ }
+ QString src = doc->toHtml(QByteArray("utf-8"));
+ QTextStream s(&file);
+ s.setCodec("utf-8");
+ s << src;
+ s.flush();
+ file.close();
+}
+
+void MainWindow::showFontSettingsDialog()
+{
+ Config *config = Config::configuration();
+ FontSettings settings = config->fontSettings();
+
+ { // It is important that the dialog be deleted before UI mode changes.
+ FontSettingsDialog dialog;
+ if (!dialog.showDialog(&settings))
+ return;
+ }
+
+ config->setFontPointSize(settings.browserFont.pointSizeF());
+ config->setFontSettings(settings);
+
+ updateApplicationFontSettings(settings);
+}
+
+void MainWindow::updateApplicationFontSettings(FontSettings &settings)
+{
+ QFont font = settings.windowFont;
+ if (this->font() != font)
+ qApp->setFont(font, "QWidget");
+
+ font = settings.browserFont;
+ QList<HelpWindow*> browsers = tabs->browsers();
+ foreach (HelpWindow *browser, browsers) {
+ if (browser->font() != font)
+ browser->setFont(font);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/mainwindow.h b/tools/assistant/compat/mainwindow.h
new file mode 100644
index 0000000000..2073f0d210
--- /dev/null
+++ b/tools/assistant/compat/mainwindow.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "ui_mainwindow.h"
+#include "config.h"
+
+#include <QPointer>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class TabbedBrowser;
+class HelpDialog;
+class HelpWindow;
+class QMenu;
+class QDockWidget;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow();
+ virtual ~MainWindow();
+
+ TabbedBrowser *browsers() const;
+ HelpDialog *helpDialog() const;
+
+ void setupPopupMenu(QMenu *menu);
+ static QString urlifyFileName(const QString &fileName);
+
+ void removePendingBrowser(HelpWindow *win);
+
+public slots:
+ MainWindow *newWindow();
+
+ void setup();
+ void showLink(const QString &link);
+ void showLinks(const QStringList &links);
+ void saveSettings();
+ void updateBookmarkMenu();
+ void printingFinished();
+
+private slots:
+ void on_actionNewWindow_triggered();
+ void on_actionGoHome_triggered();
+ void on_actionFilePrint_triggered();
+ void on_actionClose_triggered();
+ void on_actionHelpWhatsThis_triggered();
+ void on_actionHelpAssistant_triggered();
+ void on_actionAboutApplication_triggered();
+ void on_actionAboutAssistant_triggered();
+ void on_actionSaveAs_triggered();
+ void on_actionSyncToc_triggered();
+
+ void about();
+ void setupBookmarkMenu();
+ void showBookmark(QAction *action);
+ void showLinkFromClient(const QString &link);
+ void showQtHelp();
+ void showSearchLink(const QString &link, const QStringList &terms);
+ void showGoActionLink();
+ void updateProfileSettings();
+ void backwardAvailable(bool);
+ void forwardAvailable(bool);
+
+ void browserTabChanged();
+ void copyAvailable(bool yes);
+ void updateTabActions(int index);
+ void showFontSettingsDialog();
+
+protected:
+ void closeEvent(QCloseEvent *);
+ void timerEvent(QTimerEvent *);
+
+private:
+ void setupGoActions();
+ bool insertActionSeparator();
+ void updateApplicationFontSettings(FontSettings &settings);
+
+private:
+ Ui::MainWindow ui;
+
+ QList<QAction*> goActions;
+ uint setupCompleted:1;
+ TabbedBrowser *tabs;
+ QMap<QAction*, QString> bookmarks;
+ HelpDialog *helpDock;
+ QDockWidget *dw;
+ static QList<MainWindow*> windows;
+ QMap<QAction*,QString> *goActionDocFiles;
+ QList<QPair<HelpWindow*,QString> > pendingBrowsers;
+};
+
+#endif // MAINWINDOW_H
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/mainwindow.ui b/tools/assistant/compat/mainwindow.ui
new file mode 100644
index 0000000000..803a4dc04d
--- /dev/null
+++ b/tools/assistant/compat/mainwindow.ui
@@ -0,0 +1,459 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+*********************************************************************</comment>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>949</width>
+ <height>670</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Qt Assistant by Nokia</string>
+ </property>
+ <widget class="QWidget" name="__qt_central_widget" />
+ <widget class="QToolBar" name="Toolbar" >
+ <property name="windowTitle" >
+ <string>Toolbar</string>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <attribute name="toolBarArea" >
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak" >
+ <bool>false</bool>
+ </attribute>
+ <addaction name="actionGoPrevious" />
+ <addaction name="actionGoNext" />
+ <addaction name="actionGoHome" />
+ <addaction name="actionSyncToc" />
+ <addaction name="separator" />
+ <addaction name="actionEditCopy" />
+ <addaction name="actionEditFind" />
+ <addaction name="actionFilePrint" />
+ <addaction name="separator" />
+ <addaction name="actionZoomIn" />
+ <addaction name="actionZoomOut" />
+ <addaction name="separator" />
+ <addaction name="actionHelpWhatsThis" />
+ </widget>
+ <widget class="QToolBar" name="goActionToolbar" >
+ <property name="windowTitle" >
+ <string>Go</string>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <attribute name="toolBarArea" >
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak" >
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>949</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="helpMenu" >
+ <property name="title" >
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="actionHelpAssistant" />
+ <addaction name="separator" />
+ <addaction name="actionAboutAssistant" />
+ <addaction name="actionAboutApplication" />
+ <addaction name="separator" />
+ <addaction name="actionHelpWhatsThis" />
+ </widget>
+ <widget class="QMenu" name="fileMenu" >
+ <property name="title" >
+ <string>&amp;File</string>
+ </property>
+ <addaction name="actionNewWindow" />
+ <addaction name="actionOpenPage" />
+ <addaction name="actionClosePage" />
+ <addaction name="separator" />
+ <addaction name="actionSaveAs" />
+ <addaction name="separator" />
+ <addaction name="actionFilePrint" />
+ <addaction name="separator" />
+ <addaction name="actionClose" />
+ <addaction name="actionFileExit" />
+ </widget>
+ <widget class="QMenu" name="bookmarkMenu" >
+ <property name="title" >
+ <string>Boo&amp;kmarks</string>
+ </property>
+ </widget>
+ <widget class="QMenu" name="goMenu" >
+ <property name="title" >
+ <string>&amp;Go</string>
+ </property>
+ <addaction name="actionGoPrevious" />
+ <addaction name="actionGoNext" />
+ <addaction name="actionGoHome" />
+ <addaction name="actionSyncToc" />
+ <addaction name="separator" />
+ <addaction name="actionNextPage" />
+ <addaction name="actionPrevPage" />
+ </widget>
+ <widget class="QMenu" name="viewMenu" >
+ <property name="title" >
+ <string>&amp;View</string>
+ </property>
+ <addaction name="actionZoomIn" />
+ <addaction name="actionZoomOut" />
+ </widget>
+ <widget class="QMenu" name="editMenu" >
+ <property name="title" >
+ <string>&amp;Edit</string>
+ </property>
+ <addaction name="actionEditCopy" />
+ <addaction name="actionEditFind" />
+ <addaction name="actionEditFindNext" />
+ <addaction name="actionEditFindPrev" />
+ <addaction name="separator" />
+ <addaction name="actionEditFont_Settings" />
+ </widget>
+ <addaction name="fileMenu" />
+ <addaction name="editMenu" />
+ <addaction name="viewMenu" />
+ <addaction name="goMenu" />
+ <addaction name="bookmarkMenu" />
+ <addaction name="helpMenu" />
+ </widget>
+ <action name="actionFilePrint" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/print.png</iconset>
+ </property>
+ <property name="text" >
+ <string>&amp;Print...</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Print the currently displayed page.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+P</string>
+ </property>
+ </action>
+ <action name="actionFileExit" >
+ <property name="text" >
+ <string>E&amp;xit</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Quit Qt Assistant.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+Q</string>
+ </property>
+ <property name="menuRole" >
+ <enum>QAction::QuitRole</enum>
+ </property>
+ </action>
+ <action name="actionEditCopy" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/editcopy.png</iconset>
+ </property>
+ <property name="text" >
+ <string>&amp;Copy</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Copy the selected text to the clipboard.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+C</string>
+ </property>
+ </action>
+ <action name="actionEditFind" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/find.png</iconset>
+ </property>
+ <property name="text" >
+ <string>&amp;Find in Text...</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Open the Find dialog. Qt Assistant will search the currently displayed page for the text you enter.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+F</string>
+ </property>
+ </action>
+ <action name="actionEditFindNext" >
+ <property name="text" >
+ <string>Find &amp;Next</string>
+ </property>
+ <property name="shortcut" >
+ <string>F3</string>
+ </property>
+ </action>
+ <action name="actionEditFindPrev" >
+ <property name="text" >
+ <string>Find &amp;Previous</string>
+ </property>
+ <property name="shortcut" >
+ <string>Shift+F3</string>
+ </property>
+ </action>
+ <action name="actionGoHome" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/home.png</iconset>
+ </property>
+ <property name="text" >
+ <string>&amp;Home</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Go to the home page. Qt Assistant's home page is the Qt Reference Documentation.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+Home</string>
+ </property>
+ </action>
+ <action name="actionGoPrevious" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/previous.png</iconset>
+ </property>
+ <property name="text" >
+ <string>&amp;Previous</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Go to the previous page.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Alt+Left</string>
+ </property>
+ </action>
+ <action name="actionGoNext" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/next.png</iconset>
+ </property>
+ <property name="text" >
+ <string>&amp;Next</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Go to the next page.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Alt+Right</string>
+ </property>
+ </action>
+ <action name="actionAboutAssistant" >
+ <property name="text" >
+ <string>About Qt Assistant</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Display further information about Qt Assistant.</string>
+ </property>
+ <property name="menuRole" >
+ <enum>QAction::AboutRole</enum>
+ </property>
+ </action>
+ <action name="actionAboutApplication" >
+ <property name="text" >
+ <string>About Qt</string>
+ </property>
+ <property name="menuRole" >
+ <enum>QAction::AboutQtRole</enum>
+ </property>
+ </action>
+ <action name="actionZoomIn" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/zoomin.png</iconset>
+ </property>
+ <property name="text" >
+ <string>Zoom &amp;in</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Zoom in on the document, i.e. increase the font size.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl++</string>
+ </property>
+ </action>
+ <action name="actionZoomOut" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/zoomout.png</iconset>
+ </property>
+ <property name="text" >
+ <string>Zoom &amp;out</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Zoom out on the document, i.e. decrease the font size.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+-</string>
+ </property>
+ </action>
+ <action name="actionNewWindow" >
+ <property name="text" >
+ <string>New Window</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Open a new window.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+N</string>
+ </property>
+ </action>
+ <action name="actionClose" >
+ <property name="text" >
+ <string>&amp;Close</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Close the current window.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+W</string>
+ </property>
+ </action>
+ <action name="actionAddBookmark" >
+ <property name="text" >
+ <string>&amp;Add Bookmark</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Add the currently displayed page as a new bookmark.</string>
+ </property>
+ </action>
+ <action name="actionHelpWhatsThis" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/whatsthis.png</iconset>
+ </property>
+ <property name="text" >
+ <string>What's This?</string>
+ </property>
+ <property name="statusTip" >
+ <string>"What's This?" context sensitive help.</string>
+ </property>
+ <property name="whatsThis" >
+ <string>"What's This?" context sensitive help.</string>
+ </property>
+ <property name="shortcut" >
+ <string>Shift+F1</string>
+ </property>
+ </action>
+ <action name="actionOpenPage" >
+ <property name="text" >
+ <string>Add Tab</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+Alt+N</string>
+ </property>
+ </action>
+ <action name="actionNextPage" >
+ <property name="text" >
+ <string>Next Tab</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+Alt+Right</string>
+ </property>
+ </action>
+ <action name="actionPrevPage" >
+ <property name="text" >
+ <string>Previous Tab</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+Alt+Left</string>
+ </property>
+ </action>
+ <action name="actionClosePage" >
+ <property name="text" >
+ <string>Close Tab</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+Alt+Q</string>
+ </property>
+ </action>
+ <action name="actionHelpAssistant" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/assistant.png</iconset>
+ </property>
+ <property name="text" >
+ <string>Qt Assistant Manual</string>
+ </property>
+ <property name="shortcut" >
+ <string>F1</string>
+ </property>
+ </action>
+ <action name="actionSaveAs" >
+ <property name="text" >
+ <string>Save Page As...</string>
+ </property>
+ <property name="shortcut" >
+ <string>Ctrl+Alt+S</string>
+ </property>
+ </action>
+ <action name="actionSyncToc" >
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/synctoc.png</iconset>
+ </property>
+ <property name="text" >
+ <string>Sync with Table of Contents</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Select the page in contents tab.</string>
+ </property>
+ </action>
+ <action name="actionEditFont_Settings" >
+ <property name="text" >
+ <string>Font Settings...</string>
+ </property>
+ <property name="menuRole" >
+ <enum>QAction::PreferencesRole</enum>
+ </property>
+ </action>
+ </widget>
+ <resources>
+ <include location="assistant.qrc" />
+ </resources>
+ <connections/>
+</ui>
diff --git a/tools/assistant/compat/profile.cpp b/tools/assistant/compat/profile.cpp
new file mode 100644
index 0000000000..10b1737c94
--- /dev/null
+++ b/tools/assistant/compat/profile.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "profile.h"
+#include <QTextCodec>
+#include <QFileInfo>
+#include <QRegExp>
+#include <QDir>
+#include <QList>
+#include <QLibraryInfo>
+
+QT_BEGIN_NAMESPACE
+
+#define QT_TITLE QLatin1String("Qt Reference Documentation")
+#define DESIGNER_TITLE QLatin1String("Qt Designer Manual")
+#define ASSISTANT_TITLE QLatin1String("Qt Assistant Manual")
+#define LINGUIST_TITLE QLatin1String("Qt Linguist Manual")
+#define QMAKE_TITLE QLatin1String("qmake Manual")
+
+Profile *Profile::createDefaultProfile(const QString &docPath)
+{
+ QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath);
+ if (!docPath.isEmpty())
+ path = docPath;
+ path = QDir::cleanPath(path) + QLatin1String("/html/");
+
+ Profile *profile = new Profile;
+ profile->valid = true;
+ profile->type = DefaultProfile;
+ profile->props[QLatin1String("name")] = QLatin1String("default");
+ profile->props[QLatin1String("applicationicon")] = QLatin1String("assistant.png");
+ profile->props[QLatin1String("aboutmenutext")] = QLatin1String("About Qt");
+ profile->props[QLatin1String("abouturl")] = QLatin1String("about_qt");
+ profile->props[QLatin1String("basepath")] = path;
+ profile->props[QLatin1String("startpage")] = path + QLatin1String("index.html");
+
+ profile->addDCFTitle( path + QLatin1String("qt.dcf"), QT_TITLE );
+ profile->addDCFTitle( path + QLatin1String("designer.dcf"), DESIGNER_TITLE );
+ profile->addDCFTitle( path + QLatin1String("assistant.dcf"), ASSISTANT_TITLE );
+ profile->addDCFTitle( path + QLatin1String("linguist.dcf"), LINGUIST_TITLE );
+ profile->addDCFTitle( path + QLatin1String("qmake.dcf"), QMAKE_TITLE );
+
+ profile->addDCFIcon( QT_TITLE, QLatin1String("qt.png") );
+ profile->addDCFIcon( DESIGNER_TITLE, QLatin1String("designer.png") );
+ profile->addDCFIcon( ASSISTANT_TITLE, QLatin1String("assistant.png") );
+ profile->addDCFIcon( LINGUIST_TITLE, QLatin1String("linguist.png") );
+
+ profile->addDCFIndexPage( QT_TITLE, path + QLatin1String("index.html") );
+ profile->addDCFIndexPage( DESIGNER_TITLE, path + QLatin1String("designer-manual.html") );
+ profile->addDCFIndexPage( ASSISTANT_TITLE, path + QLatin1String("assistant-manual.html") );
+ profile->addDCFIndexPage( LINGUIST_TITLE, path + QLatin1String("linguist-manual.html") );
+ profile->addDCFIndexPage( QMAKE_TITLE, path + QLatin1String("qmake-manual.html") );
+
+ profile->addDCFImageDir( QT_TITLE, QLatin1String("../../gif/") );
+ profile->addDCFImageDir( DESIGNER_TITLE, QLatin1String("../../gif/") );
+ profile->addDCFImageDir( ASSISTANT_TITLE, QLatin1String("../../gif/") );
+ profile->addDCFImageDir( LINGUIST_TITLE, QLatin1String("../../gif/") );
+ profile->addDCFImageDir( QMAKE_TITLE, QLatin1String("../../gif/") );
+
+ return profile;
+}
+
+Profile::Profile()
+ : valid( true ), dparser( 0 )
+{
+ type = DefaultProfile;
+}
+
+bool Profile::isValid() const
+{
+ return valid;
+}
+
+void Profile::addDCFTitle(const QString &dcf, const QString &title)
+{
+ QString absdcf = QFileInfo(dcf).absoluteFilePath();
+ dcfTitles[title] = absdcf;
+ if (!docs.contains(absdcf))
+ docs << absdcf;
+}
+
+void Profile::addDCF(const QString &docfile)
+{
+ if( !docs.contains( docfile ) == 0 )
+ docs << docfile;
+}
+
+void Profile::addDCFIcon(const QString docfile, const QString &icon)
+{
+ icons[docfile] = icon;
+}
+
+void Profile::addDCFIndexPage(const QString title, const QString &indexPage)
+{
+ indexPages[title] = indexPage;
+}
+
+void Profile::addDCFImageDir(const QString docfile, const QString &imgDir)
+{
+ imageDirs[docfile] = imgDir;
+}
+
+void Profile::addProperty(const QString &name, const QString &value)
+{
+ props[name] = value;
+}
+
+bool Profile::hasDocFile(const QString &name)
+{
+ return docs.contains( name );
+}
+
+void Profile::removeDocFileEntry(const QString &docfile)
+{
+ docs.removeAll(docfile);
+ QStringList titles;
+
+ for( QMap<QString,QString>::Iterator it = dcfTitles.begin();
+ it != dcfTitles.end(); ++it ) {
+ if( (*it) == docfile ) {
+ indexPages.remove( *it );
+ icons.remove( *it );
+ imageDirs.remove( *it );
+ titles << it.key();
+ }
+ }
+
+ for( QStringList::ConstIterator title = titles.constBegin();
+ title != titles.constEnd(); ++title )
+ dcfTitles.remove( *title );
+
+#ifdef ASSISTANT_DEBUG
+ qDebug() << "docs:\n - " << docs.join("\n - ");
+ qDebug() << "titles:\n - " << titles.join("\n - ");
+ qDebug() << "keys:\n - " << ((QStringList*)&(dcfTitles.keys()))->join("\n - ");
+ qDebug() << "values:\n - " << ((QStringList*)&(dcfTitles.values()))->join("\n - ");
+#endif
+}
+
+QString Profile::storableFilePath(const QString &fileName)
+{
+ QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath).replace(QLatin1String("\\"), QLatin1String("/"));
+ QString fName = fileName;
+ if (fName.startsWith(path))
+ fName.replace(0, path.length(), QLatin1String("$DOCPATH$"));
+ return fName;
+}
+
+QString Profile::loadableFilePath(const QString &fileName)
+{
+ QString path = QLibraryInfo::location(QLibraryInfo::DocumentationPath).replace(QLatin1String("\\"), QLatin1String("/"));
+ QString fName = fileName;
+ if (fName.startsWith(QLatin1String("$DOCPATH$")))
+ fName.replace(0, 9, path);
+ return fName;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/profile.h b/tools/assistant/compat/profile.h
new file mode 100644
index 0000000000..24aef3e878
--- /dev/null
+++ b/tools/assistant/compat/profile.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROFILE_H
+#define PROFILE_H
+
+#include <QFileInfo>
+#include <QString>
+#include <QStringList>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class DocuParser;
+
+class Profile
+{
+public:
+ enum ProfileType { DefaultProfile, UserProfile };
+ Profile();
+
+ bool isValid() const;
+
+ void addDCF( const QString &docfile );
+ void addDCFIcon( const QString title, const QString &icon );
+ void addDCFIndexPage( const QString title, const QString &indexPage );
+ void addDCFImageDir( const QString title, const QString &imgDir );
+ void addDCFTitle( const QString &dcf, const QString &title );
+ void addProperty( const QString &name, const QString &value );
+ bool hasDocFile( const QString &docFile );
+ void removeDocFileEntry( const QString &title );
+
+ ProfileType profileType() const { return type; }
+ void setProfileType( ProfileType t ) { type = t; }
+
+ DocuParser *docuParser() const { return dparser; }
+ void setDocuParser( DocuParser *dp ) { dparser = dp; }
+
+ static Profile* createDefaultProfile(const QString &docPath = QString());
+ static QString makeRelativePath(const QString &base, const QString &path);
+ static QString storableFilePath(const QString &fileName);
+ static QString loadableFilePath(const QString &fileName);
+
+ uint valid:1;
+ ProfileType type;
+ DocuParser *dparser;
+ QMap<QString,QString> props;
+ QMap<QString,QString> icons;
+ QMap<QString,QString> indexPages;
+ QMap<QString,QString> imageDirs;
+ QMap<QString,QString> dcfTitles;
+ QStringList docs;
+};
+
+QT_END_NAMESPACE
+
+#endif // PROFILE_H
diff --git a/tools/assistant/compat/tabbedbrowser.cpp b/tools/assistant/compat/tabbedbrowser.cpp
new file mode 100644
index 0000000000..198be4a3e4
--- /dev/null
+++ b/tools/assistant/compat/tabbedbrowser.cpp
@@ -0,0 +1,530 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tabbedbrowser.h"
+#include "mainwindow.h"
+#include "helpwindow.h"
+#include "config.h"
+
+#include <QStyleOptionTab>
+#include <QToolTip>
+#include <QFileInfo>
+#include <QToolButton>
+#include <QPixmap>
+#include <QIcon>
+#include <QStyle>
+#include <QTimer>
+#include <QStackedWidget>
+#include <QTimer>
+#include <QTextBlock>
+#include <QKeyEvent>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_WS_MAC
+const QLatin1String ImageLocation(":trolltech/assistant/images/mac/");
+#else
+const QLatin1String ImageLocation(":trolltech/assistant/images/win/");
+#endif
+
+TabbedBrowser::TabbedBrowser(MainWindow *parent)
+ : QWidget(parent)
+{
+ ui.setupUi(this);
+ init();
+
+ QStackedWidget *stack = qFindChild<QStackedWidget*>(ui.tab);
+ Q_ASSERT(stack);
+ stack->setContentsMargins(0, 0, 0, 0);
+ connect(stack, SIGNAL(currentChanged(int)), parent, SLOT(browserTabChanged()));
+
+ QPalette p = palette();
+ p.setColor(QPalette::Inactive, QPalette::Highlight,
+ p.color(QPalette::Active, QPalette::Highlight));
+ p.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ p.color(QPalette::Active, QPalette::HighlightedText));
+ setPalette(p);
+}
+
+TabbedBrowser::~TabbedBrowser()
+{
+}
+
+MainWindow *TabbedBrowser::mainWindow() const
+{
+ return static_cast<MainWindow*>(parentWidget());
+}
+
+void TabbedBrowser::forward()
+{
+ currentBrowser()->forward();
+ emit browserUrlChanged(currentBrowser()->source().toString());
+}
+
+void TabbedBrowser::backward()
+{
+ currentBrowser()->backward();
+ emit browserUrlChanged(currentBrowser()->source().toString());
+}
+
+void TabbedBrowser::setSource( const QString &ref )
+{
+ HelpWindow * win = currentBrowser();
+ win->setSource(ref);
+}
+
+void TabbedBrowser::reload()
+{
+ currentBrowser()->reload();
+}
+
+void TabbedBrowser::home()
+{
+ currentBrowser()->home();
+}
+
+HelpWindow *TabbedBrowser::currentBrowser() const
+{
+ return static_cast<HelpWindow*>(ui.tab->currentWidget());
+}
+
+void TabbedBrowser::nextTab()
+{
+ if(ui.tab->currentIndex()<=ui.tab->count()-1)
+ ui.tab->setCurrentIndex(ui.tab->currentIndex()+1);
+}
+
+void TabbedBrowser::previousTab()
+{
+ int idx = ui.tab->currentIndex()-1;
+ if(idx>=0)
+ ui.tab->setCurrentIndex(idx);
+}
+
+HelpWindow *TabbedBrowser::createHelpWindow()
+{
+ MainWindow *mainWin = mainWindow();
+ HelpWindow *win = new HelpWindow(mainWin, 0);
+ win->setFrameStyle(QFrame::NoFrame);
+ win->setPalette(palette());
+ win->setSearchPaths(Config::configuration()->mimePaths());
+ ui.tab->addTab(win, tr("..."));
+ connect(win, SIGNAL(highlighted(QString)),
+ (const QObject*) (mainWin->statusBar()), SLOT(showMessage(QString)));
+ connect(win, SIGNAL(backwardAvailable(bool)),
+ mainWin, SLOT(backwardAvailable(bool)));
+ connect(win, SIGNAL(forwardAvailable(bool)),
+ mainWin, SLOT(forwardAvailable(bool)));
+ connect(win, SIGNAL(sourceChanged(QUrl)), this, SLOT(sourceChanged()));
+
+ ui.tab->cornerWidget(Qt::TopRightCorner)->setEnabled(ui.tab->count() > 1);
+ win->installEventFilter(this);
+ win->viewport()->installEventFilter(this);
+ ui.editFind->installEventFilter(this);
+ return win;
+}
+
+HelpWindow *TabbedBrowser::newBackgroundTab()
+{
+ HelpWindow *win = createHelpWindow();
+ emit tabCountChanged(ui.tab->count());
+ return win;
+}
+
+void TabbedBrowser::newTab(const QString &lnk)
+{
+ QString link(lnk);
+ if(link.isNull()) {
+ HelpWindow *w = currentBrowser();
+ if(w)
+ link = w->source().toString();
+ }
+ HelpWindow *win = createHelpWindow();
+ ui.tab->setCurrentIndex(ui.tab->indexOf(win));
+ if(!link.isNull()) {
+ win->setSource(link);
+ }
+
+ emit tabCountChanged(ui.tab->count());
+}
+
+void TabbedBrowser::zoomIn()
+{
+ currentBrowser()->zoomIn();
+ Config::configuration()->setFontPointSize(currentBrowser()->font().pointSizeF());
+}
+
+void TabbedBrowser::zoomOut()
+{
+ currentBrowser()->zoomOut();
+ Config::configuration()->setFontPointSize(currentBrowser()->font().pointSizeF());
+}
+
+void TabbedBrowser::init()
+{
+
+ lastCurrentTab = 0;
+ while(ui.tab->count()) {
+ QWidget *page = ui.tab->widget(0);
+ ui.tab->removeTab(0);
+ delete page;
+ }
+
+ connect(ui.tab, SIGNAL(currentChanged(int)),
+ this, SLOT(transferFocus()));
+
+ QTabBar *tabBar = qFindChild<QTabBar*>(ui.tab);
+ QStyleOptionTab opt;
+ if (tabBar) {
+ opt.init(tabBar);
+ opt.shape = tabBar->shape();
+ tabBar->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(tabBar, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(openTabMenu(const QPoint&)));
+ }
+
+ // workaround for sgi style
+ QPalette pal = palette();
+ pal.setColor(QPalette::Active, QPalette::Button, pal.color(QPalette::Active, QPalette::Window));
+ pal.setColor(QPalette::Disabled, QPalette::Button, pal.color(QPalette::Disabled, QPalette::Window));
+ pal.setColor(QPalette::Inactive, QPalette::Button, pal.color(QPalette::Inactive, QPalette::Window));
+
+ QToolButton *newTabButton = new QToolButton(this);
+ ui.tab->setCornerWidget(newTabButton, Qt::TopLeftCorner);
+ newTabButton->setCursor(Qt::ArrowCursor);
+ newTabButton->setAutoRaise(true);
+ newTabButton->setIcon(QIcon(ImageLocation + QLatin1String("addtab.png")));
+ QObject::connect(newTabButton, SIGNAL(clicked()), this, SLOT(newTab()));
+ newTabButton->setToolTip(tr("Add page"));
+
+ QToolButton *closeTabButton = new QToolButton(this);
+ closeTabButton->setPalette(pal);
+ ui.tab->setCornerWidget(closeTabButton, Qt::TopRightCorner);
+ closeTabButton->setCursor(Qt::ArrowCursor);
+ closeTabButton->setAutoRaise(true);
+ closeTabButton->setIcon(QIcon(ImageLocation + QLatin1String("closetab.png")));
+ QObject::connect(closeTabButton, SIGNAL(clicked()), this, SLOT(closeTab()));
+ closeTabButton->setToolTip(tr("Close page"));
+ closeTabButton->setEnabled(false);
+
+ QObject::connect(ui.toolClose, SIGNAL(clicked()), ui.frameFind, SLOT(hide()));
+ QObject::connect(ui.toolPrevious, SIGNAL(clicked()), this, SLOT(findPrevious()));
+ QObject::connect(ui.toolNext, SIGNAL(clicked()), this, SLOT(findNext()));
+ QObject::connect(ui.editFind, SIGNAL(returnPressed()), this, SLOT(findNext()));
+ QObject::connect(ui.editFind, SIGNAL(textEdited(const QString&)),
+ this, SLOT(find(QString)));
+ ui.frameFind->setVisible(false);
+ ui.labelWrapped->setVisible(false);
+ autoHideTimer = new QTimer(this);
+ autoHideTimer->setInterval(5000);
+ autoHideTimer->setSingleShot(true);
+ QObject::connect(autoHideTimer, SIGNAL(timeout()), ui.frameFind, SLOT(hide()));
+}
+
+void TabbedBrowser::updateTitle(const QString &title)
+{
+ ui.tab->setTabText(ui.tab->indexOf(currentBrowser()), title.trimmed());
+}
+
+void TabbedBrowser::newTab()
+{
+ newTab(QString());
+}
+
+void TabbedBrowser::transferFocus()
+{
+ if(currentBrowser()) {
+ currentBrowser()->setFocus();
+ }
+ mainWindow()->setWindowTitle(Config::configuration()->title()
+ + QLatin1String(" - ")
+ + currentBrowser()->documentTitle());
+}
+
+void TabbedBrowser::initHelpWindow(HelpWindow * /*win*/)
+{
+}
+
+void TabbedBrowser::setup()
+{
+ newTab(QString());
+}
+
+void TabbedBrowser::copy()
+{
+ currentBrowser()->copy();
+}
+
+void TabbedBrowser::closeTab()
+{
+ if(ui.tab->count()==1)
+ return;
+ HelpWindow *win = currentBrowser();
+ mainWindow()->removePendingBrowser(win);
+ ui.tab->removeTab(ui.tab->indexOf(win));
+ QTimer::singleShot(0, win, SLOT(deleteLater()));
+ ui.tab->cornerWidget(Qt::TopRightCorner)->setEnabled(ui.tab->count() > 1);
+ emit tabCountChanged(ui.tab->count());
+}
+
+QStringList TabbedBrowser::sources() const
+{
+ QStringList lst;
+ int cnt = ui.tab->count();
+ for(int i=0; i<cnt; i++) {
+ lst.append(((QTextBrowser*) ui.tab->widget(i))->source().toString());
+ }
+ return lst;
+}
+
+QList<HelpWindow*> TabbedBrowser::browsers() const
+{
+ QList<HelpWindow*> list;
+ for (int i=0; i<ui.tab->count(); ++i) {
+ Q_ASSERT(qobject_cast<HelpWindow*>(ui.tab->widget(i)));
+ list.append(static_cast<HelpWindow*>(ui.tab->widget(i)));
+ }
+ return list;
+}
+
+void TabbedBrowser::sourceChanged()
+{
+ HelpWindow *win = qobject_cast<HelpWindow *>(QObject::sender());
+ Q_ASSERT(win);
+ QString docTitle(win->documentTitle());
+ if (docTitle.isEmpty())
+ docTitle = QLatin1String("...");
+ // Make the classname in the title a bit more visible (otherwise
+ // we just see the "Qt 4.0 : Q..." which isn't really helpful ;-)
+ QString qtTitle = QLatin1String("Qt ") + QString::number( (QT_VERSION >> 16) & 0xff )
+ + QLatin1String(".") + QString::number( (QT_VERSION >> 8) & 0xff )
+ + QLatin1String(": ");
+ if (docTitle.startsWith(qtTitle))
+ docTitle = docTitle.mid(qtTitle.length());
+ setTitle(win, docTitle);
+ ui.frameFind->hide();
+ ui.labelWrapped->hide();
+ win->setTextCursor(win->cursorForPosition(QPoint(0, 0)));
+}
+
+void TabbedBrowser::setTitle(HelpWindow *win, const QString &title)
+{
+ const QString tt = title.trimmed();
+ ui.tab->setTabText(ui.tab->indexOf(win), tt);
+ if (win == currentBrowser())
+ mainWindow()->setWindowTitle(Config::configuration()->title() + QLatin1String(" - ") + tt);
+}
+
+void TabbedBrowser::keyPressEvent(QKeyEvent *e)
+{
+ int key = e->key();
+ QString ttf = ui.editFind->text();
+ QString text = e->text();
+
+ if (ui.frameFind->isVisible()) {
+ switch (key) {
+ case Qt::Key_Escape:
+ ui.frameFind->hide();
+ ui.labelWrapped->hide();
+ return;
+ case Qt::Key_Backspace:
+ ttf.chop(1);
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ // Return/Enter key events are not accepted by QLineEdit
+ return;
+ default:
+ if (text.isEmpty()) {
+ QWidget::keyPressEvent(e);
+ return;
+ }
+ ttf += text;
+ }
+ } else {
+ if (text.isEmpty() || text[0].isSpace() || !text[0].isPrint()) {
+ QWidget::keyPressEvent(e);
+ return;
+ }
+ if (text.startsWith(QLatin1Char('/'))) {
+ ui.editFind->clear();
+ find();
+ return;
+ }
+ ttf = text;
+ ui.frameFind->show();
+ }
+
+ ui.editFind->setText(ttf);
+ find(ttf, false, false);
+}
+
+void TabbedBrowser::findNext()
+{
+ find(ui.editFind->text(), true, false);
+}
+
+void TabbedBrowser::findPrevious()
+{
+ find(ui.editFind->text(), false, true);
+}
+
+void TabbedBrowser::find()
+{
+ ui.frameFind->show();
+ ui.editFind->setFocus(Qt::ShortcutFocusReason);
+ ui.editFind->selectAll();
+ autoHideTimer->stop();
+}
+
+void TabbedBrowser::find(QString ttf, bool forward, bool backward)
+{
+ HelpWindow *browser = currentBrowser();
+ QTextDocument *doc = browser->document();
+ QString oldText = ui.editFind->text();
+ QTextCursor c = browser->textCursor();
+ QTextDocument::FindFlags options;
+ QPalette p = ui.editFind->palette();
+ p.setColor(QPalette::Active, QPalette::Base, Qt::white);
+
+ if (c.hasSelection())
+ c.setPosition(forward ? c.position() : c.anchor(), QTextCursor::MoveAnchor);
+
+ QTextCursor newCursor = c;
+
+ if (!ttf.isEmpty()) {
+ if (backward)
+ options |= QTextDocument::FindBackward;
+
+ if (ui.checkCase->isChecked())
+ options |= QTextDocument::FindCaseSensitively;
+
+ if (ui.checkWholeWords->isChecked())
+ options |= QTextDocument::FindWholeWords;
+
+ newCursor = doc->find(ttf, c, options);
+ ui.labelWrapped->hide();
+
+ if (newCursor.isNull()) {
+ QTextCursor ac(doc);
+ ac.movePosition(options & QTextDocument::FindBackward
+ ? QTextCursor::End : QTextCursor::Start);
+ newCursor = doc->find(ttf, ac, options);
+ if (newCursor.isNull()) {
+ p.setColor(QPalette::Active, QPalette::Base, QColor(255, 102, 102));
+ newCursor = c;
+ } else
+ ui.labelWrapped->show();
+ }
+ }
+
+ if (!ui.frameFind->isVisible())
+ ui.frameFind->show();
+ browser->setTextCursor(newCursor);
+ ui.editFind->setPalette(p);
+ if (!ui.editFind->hasFocus())
+ autoHideTimer->start();
+}
+
+bool TabbedBrowser::eventFilter(QObject *o, QEvent *e)
+{
+ if (o == ui.editFind) {
+ if (e->type() == QEvent::FocusIn && autoHideTimer->isActive())
+ autoHideTimer->stop();
+ } else if (e->type() == QEvent::KeyPress && ui.frameFind->isVisible()) { // assume textbrowser
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
+ if (ke->key() == Qt::Key_Space) {
+ keyPressEvent(ke);
+ return true;
+ }
+ }
+
+ return QWidget::eventFilter(o, e);
+}
+
+void TabbedBrowser::openTabMenu(const QPoint& pos)
+{
+ QTabBar *tabBar = qFindChild<QTabBar*>(ui.tab);
+
+ QMenu m(QLatin1String(""), tabBar);
+ QAction *new_action = m.addAction(tr("New Tab"));
+ QAction *close_action = m.addAction(tr("Close Tab"));
+ QAction *close_others_action = m.addAction(tr("Close Other Tabs"));
+
+ if (tabBar->count() == 1) {
+ close_action->setEnabled(false);
+ close_others_action->setEnabled(false);
+ }
+
+ QAction *action_picked = m.exec(tabBar->mapToGlobal(pos));
+ if (!action_picked)
+ return;
+
+ if (action_picked == new_action) {
+ newTab();
+ return;
+ }
+
+ QList<HelpWindow*> windowList = browsers();
+ for (int i = 0; i < tabBar->count(); ++i) {
+ if (tabBar->tabRect(i).contains(pos)) {
+ HelpWindow *win = static_cast<HelpWindow*>(ui.tab->widget(i));
+ if (action_picked == close_action) {
+ mainWindow()->removePendingBrowser(win);
+ QTimer::singleShot(0, win, SLOT(deleteLater()));
+ }
+ windowList.removeOne(win);
+ break;
+ }
+ }
+
+ if (action_picked == close_others_action) {
+ foreach (HelpWindow* win, windowList) {
+ mainWindow()->removePendingBrowser(win);
+ QTimer::singleShot(0, win, SLOT(deleteLater()));
+ windowList.removeOne(win);
+ }
+ }
+
+ ui.tab->cornerWidget(Qt::TopRightCorner)->setEnabled(windowList.count() > 1);
+ emit tabCountChanged(windowList.count());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/tabbedbrowser.h b/tools/assistant/compat/tabbedbrowser.h
new file mode 100644
index 0000000000..0e26bede07
--- /dev/null
+++ b/tools/assistant/compat/tabbedbrowser.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABBEDBROWSER_H
+#define TABBEDBROWSER_H
+
+#include "ui_tabbedbrowser.h"
+
+QT_BEGIN_NAMESPACE
+
+class MainWindow;
+class HelpWindow;
+class QStyleSheet;
+class QMimeSourceFactory;
+class QTimer;
+
+class TabbedBrowser : public QWidget
+{
+ Q_OBJECT
+public:
+ TabbedBrowser(MainWindow *parent);
+ virtual ~TabbedBrowser();
+
+ MainWindow *mainWindow() const;
+ HelpWindow *currentBrowser() const;
+ QStringList sources() const;
+ QList<HelpWindow*> browsers() const;
+
+ HelpWindow* newBackgroundTab();
+ HelpWindow* createHelpWindow();
+
+ void setTitle(HelpWindow*, const QString &);
+
+signals:
+ void tabCountChanged(int count);
+ void browserUrlChanged(const QString &link);
+
+protected:
+ void keyPressEvent(QKeyEvent *);
+ bool eventFilter(QObject *o, QEvent *e);
+
+public slots:
+ void init();
+ void forward();
+ void backward();
+ void setSource(const QString &ref);
+ void reload();
+ void home();
+ void nextTab();
+ void previousTab();
+ void newTab(const QString &lnk);
+ void zoomIn();
+ void zoomOut();
+ void updateTitle(const QString &title);
+ void newTab();
+ void transferFocus();
+ void initHelpWindow(HelpWindow *win);
+ void setup();
+ void copy();
+ void closeTab();
+ void sourceChanged();
+
+ void find();
+ void findNext();
+ void findPrevious();
+
+private slots:
+ void find(QString, bool forward = false, bool backward = false);
+ void openTabMenu(const QPoint& pos);
+
+private:
+ Ui::TabbedBrowser ui;
+ QWidget *lastCurrentTab;
+ QFont tabFont;
+
+ QString fixedFontFam;
+ QColor lnkColor;
+ bool underlineLnk;
+ QTimer *autoHideTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // TABBEDBROWSER_H
diff --git a/tools/assistant/compat/tabbedbrowser.ui b/tools/assistant/compat/tabbedbrowser.ui
new file mode 100644
index 0000000000..acb38f3bf0
--- /dev/null
+++ b/tools/assistant/compat/tabbedbrowser.ui
@@ -0,0 +1,233 @@
+<ui version="4.0" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>TabbedBrowser</class>
+ <widget class="QWidget" name="TabbedBrowser" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>710</width>
+ <height>664</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>TabbedBrowser</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTabWidget" name="tab" >
+ <widget class="QWidget" name="frontpage" >
+ <attribute name="title" >
+ <string>Untitled</string>
+ </attribute>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="frameFind" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="toolClose" >
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/close.png</iconset>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="editFind" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>150</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="toolPrevious" >
+ <property name="text" >
+ <string>Previous</string>
+ </property>
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/previous.png</iconset>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="toolNext" >
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>Next</string>
+ </property>
+ <property name="icon" >
+ <iconset resource="assistant.qrc" >:/trolltech/assistant/images/win/next.png</iconset>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ <property name="arrowType" >
+ <enum>Qt::NoArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkCase" >
+ <property name="text" >
+ <string>Case Sensitive</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkWholeWords" >
+ <property name="text" >
+ <string>Whole words</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelWrapped" >
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>105</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>&lt;img src=":/trolltech/assistant/images/wrap.png">&amp;nbsp;Search wrapped</string>
+ </property>
+ <property name="textFormat" >
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="scaledContents" >
+ <bool>true</bool>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>81</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources>
+ <include location="assistant.qrc" />
+ </resources>
+ <connections/>
+</ui>
diff --git a/tools/assistant/compat/topicchooser.cpp b/tools/assistant/compat/topicchooser.cpp
new file mode 100644
index 0000000000..7333cb38c5
--- /dev/null
+++ b/tools/assistant/compat/topicchooser.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "topicchooser.h"
+
+#include <QLabel>
+#include <QListWidget>
+#include <QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+TopicChooser::TopicChooser(QWidget *parent, const QStringList &lnkNames,
+ const QStringList &lnks, const QString &title)
+ : QDialog(parent), links(lnks), linkNames(lnkNames)
+{
+ ui.setupUi(this);
+
+ ui.label->setText(tr("Choose a topic for <b>%1</b>").arg(title));
+ ui.listbox->addItems(linkNames);
+ if (ui.listbox->count() != 0)
+ ui.listbox->setCurrentRow(0);
+ ui.listbox->setFocus();
+}
+
+QString TopicChooser::link() const
+{
+ if (ui.listbox->currentRow() == -1)
+ return QString();
+ QString s = ui.listbox->item(ui.listbox->currentRow())->text();
+ if (s.isEmpty())
+ return s;
+ int i = linkNames.indexOf(s);
+ return links[i];
+}
+
+QString TopicChooser::getLink(QWidget *parent, const QStringList &lnkNames,
+ const QStringList &lnks, const QString &title)
+{
+ TopicChooser *dlg = new TopicChooser(parent, lnkNames, lnks, title);
+ QString lnk;
+ if (dlg->exec() == QDialog::Accepted)
+ lnk = dlg->link();
+ delete dlg;
+ return lnk;
+}
+
+void TopicChooser::on_buttonDisplay_clicked()
+{
+ accept();
+}
+
+void TopicChooser::on_buttonCancel_clicked()
+{
+ reject();
+}
+
+void TopicChooser::on_listbox_itemActivated(QListWidgetItem *item)
+{
+ Q_UNUSED(item);
+ accept();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/topicchooser.h b/tools/assistant/compat/topicchooser.h
new file mode 100644
index 0000000000..122a233308
--- /dev/null
+++ b/tools/assistant/compat/topicchooser.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOPICCHOOSER_H
+#define TOPICCHOOSER_H
+
+#include "ui_topicchooser.h"
+
+#include <QDialog>
+#include <QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class TopicChooser : public QDialog
+{
+ Q_OBJECT
+public:
+ TopicChooser(QWidget *parent, const QStringList &lnkNames,
+ const QStringList &lnks, const QString &title);
+
+ QString link() const;
+
+ static QString getLink(QWidget *parent, const QStringList &lnkNames,
+ const QStringList &lnks, const QString &title);
+
+private slots:
+ void on_buttonDisplay_clicked();
+ void on_buttonCancel_clicked();
+ void on_listbox_itemActivated(QListWidgetItem *item);
+
+private:
+ Ui::TopicChooser ui;
+ QString theLink;
+ QStringList links, linkNames;
+};
+
+#endif // TOPICCHOOSER_H
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/compat/topicchooser.ui b/tools/assistant/compat/topicchooser.ui
new file mode 100644
index 0000000000..a26eeb8d63
--- /dev/null
+++ b/tools/assistant/compat/topicchooser.ui
@@ -0,0 +1,162 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>TopicChooser</class>
+ <widget class="QDialog" name="TopicChooser" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>391</width>
+ <height>223</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Choose Topic</string>
+ </property>
+ <property name="whatsThis" >
+ <string>Select a topic from the list and click the &lt;b>Display&lt;/b>-button to open the online help.</string>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>11</number>
+ </property>
+ <property name="topMargin" >
+ <number>11</number>
+ </property>
+ <property name="rightMargin" >
+ <number>11</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>11</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>&amp;Topics</string>
+ </property>
+ <property name="buddy" >
+ <cstring>listbox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listbox" >
+ <property name="whatsThis" >
+ <string>Displays a list of available help topics for the keyword.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonDisplay" >
+ <property name="whatsThis" >
+ <string>Open the topic selected in the list.</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Display</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonCancel" >
+ <property name="whatsThis" >
+ <string>Close the Dialog.</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Close</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/compat/translations/translations.pro b/tools/assistant/compat/translations/translations.pro
new file mode 100644
index 0000000000..19fcc06a6d
--- /dev/null
+++ b/tools/assistant/compat/translations/translations.pro
@@ -0,0 +1,34 @@
+# Include those manually as they do not contain any directory specification
+
+FORMS += ../helpdialog.ui \
+ ../mainwindow.ui \
+ ../tabbedbrowser.ui \
+ ../topicchooser.ui
+
+SOURCES += ../main.cpp \
+ ../helpwindow.cpp \
+ ../topicchooser.cpp \
+ ../docuparser.cpp \
+ ../index.cpp \
+ ../profile.cpp \
+ ../config.cpp \
+ ../helpdialog.cpp \
+ ../mainwindow.cpp \
+ ../tabbedbrowser.cpp \
+ ../fontsettingsdialog.cpp
+
+SOURCES += ../../../shared/fontpanel/fontpanel.cpp
+
+HEADERS += ../helpwindow.h \
+ ../topicchooser.h \
+ ../docuparser.h \
+ ../index.h \
+ ../profile.h \
+ ../helpdialog.h \
+ ../mainwindow.h \
+ ../tabbedbrowser.h \
+ ../config.h \
+ ../fontsettingsdialog.h
+
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/assistant_de.ts $$[QT_INSTALL_TRANSLATIONS]/assistant_untranslated.ts
diff --git a/tools/assistant/lib/fulltextsearch/fulltextsearch.pri b/tools/assistant/lib/fulltextsearch/fulltextsearch.pri
new file mode 100644
index 0000000000..134678feb6
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/fulltextsearch.pri
@@ -0,0 +1,161 @@
+DEFINES += _BUILD_FOR_QT_ LUCENE_DISABLE_MEMTRACKING
+win32:DEFINES += _CRT_SECURE_NO_DEPRECATE _MT
+
+CLUCENEDIR = ../../../../src/3rdparty/clucene/src/CLucene
+
+INCLUDEPATH += . .. \
+ $$CLUCENEDIR \
+ $$CLUCENEDIR/../ \
+ $$CLUCENEDIR/analysis \
+ $$CLUCENEDIR/analysis/standard \
+ $$CLUCENEDIR/config \
+ $$CLUCENEDIR/debug \
+ $$CLUCENEDIR/document \
+ $$CLUCENEDIR/index \
+ $$CLUCENEDIR/queryParser \
+ $$CLUCENEDIR/search \
+ $$CLUCENEDIR/store \
+ $$CLUCENEDIR/util
+
+
+SOURCES += $$CLUCENEDIR/StdHeader.cpp \
+ $$CLUCENEDIR/analysis/AnalysisHeader.cpp \
+ $$CLUCENEDIR/analysis/Analyzers.cpp \
+ $$CLUCENEDIR/config/gunichartables.cpp \
+ $$CLUCENEDIR/config/repl_lltot.cpp \
+ $$CLUCENEDIR/config/repl_tcscasecmp.cpp \
+ $$CLUCENEDIR/config/repl_tcslwr.cpp \
+ $$CLUCENEDIR/config/repl_tcstod.cpp \
+ $$CLUCENEDIR/config/repl_tcstoll.cpp \
+ $$CLUCENEDIR/config/repl_tprintf.cpp \
+ $$CLUCENEDIR/config/threads.cpp \
+ $$CLUCENEDIR/config/utf8.cpp \
+ $$CLUCENEDIR/debug/condition.cpp \
+ $$CLUCENEDIR/debug/error.cpp \
+ $$CLUCENEDIR/debug/memtracking.cpp \
+ $$CLUCENEDIR/document/DateField.cpp \
+ $$CLUCENEDIR/document/Document.cpp \
+ $$CLUCENEDIR/document/Field.cpp \
+ $$CLUCENEDIR/index/CompoundFile.cpp \
+ $$CLUCENEDIR/index/DocumentWriter.cpp \
+ $$CLUCENEDIR/index/FieldInfos.cpp \
+ $$CLUCENEDIR/index/FieldsReader.cpp \
+ $$CLUCENEDIR/index/FieldsWriter.cpp \
+ $$CLUCENEDIR/index/IndexModifier.cpp \
+ $$CLUCENEDIR/index/IndexReader.cpp \
+ $$CLUCENEDIR/index/IndexWriter.cpp \
+ $$CLUCENEDIR/index/MultiReader.cpp \
+ $$CLUCENEDIR/index/SegmentInfos.cpp \
+ $$CLUCENEDIR/index/SegmentMergeInfo.cpp \
+ $$CLUCENEDIR/index/SegmentMergeQueue.cpp \
+ $$CLUCENEDIR/index/SegmentMerger.cpp \
+ $$CLUCENEDIR/index/SegmentReader.cpp \
+ $$CLUCENEDIR/index/SegmentTermDocs.cpp \
+ $$CLUCENEDIR/index/SegmentTermEnum.cpp \
+ $$CLUCENEDIR/index/SegmentTermPositions.cpp \
+ $$CLUCENEDIR/index/SegmentTermVector.cpp \
+ $$CLUCENEDIR/index/Term.cpp \
+ $$CLUCENEDIR/index/TermInfo.cpp \
+ $$CLUCENEDIR/index/TermInfosReader.cpp \
+ $$CLUCENEDIR/index/TermInfosWriter.cpp \
+ $$CLUCENEDIR/index/TermVectorReader.cpp \
+ $$CLUCENEDIR/index/TermVectorWriter.cpp \
+ $$CLUCENEDIR/queryParser/Lexer.cpp \
+ $$CLUCENEDIR/queryParser/MultiFieldQueryParser.cpp \
+ $$CLUCENEDIR/queryParser/QueryParser.cpp \
+ $$CLUCENEDIR/queryParser/QueryParserBase.cpp \
+ $$CLUCENEDIR/queryParser/QueryToken.cpp \
+ $$CLUCENEDIR/queryParser/TokenList.cpp \
+ $$CLUCENEDIR/search/BooleanQuery.cpp \
+ $$CLUCENEDIR/search/BooleanScorer.cpp \
+ $$CLUCENEDIR/search/CachingWrapperFilter.cpp \
+ $$CLUCENEDIR/search/ChainedFilter.cpp \
+ $$CLUCENEDIR/search/ConjunctionScorer.cpp \
+ $$CLUCENEDIR/search/DateFilter.cpp \
+ $$CLUCENEDIR/search/ExactPhraseScorer.cpp \
+ $$CLUCENEDIR/search/Explanation.cpp \
+ $$CLUCENEDIR/search/FieldCache.cpp \
+ $$CLUCENEDIR/search/FieldCacheImpl.cpp \
+ $$CLUCENEDIR/search/FieldDocSortedHitQueue.cpp \
+ $$CLUCENEDIR/search/FieldSortedHitQueue.cpp \
+ $$CLUCENEDIR/search/FilteredTermEnum.cpp \
+ $$CLUCENEDIR/search/FuzzyQuery.cpp \
+ $$CLUCENEDIR/search/HitQueue.cpp \
+ $$CLUCENEDIR/search/Hits.cpp \
+ $$CLUCENEDIR/search/IndexSearcher.cpp \
+ $$CLUCENEDIR/search/MultiSearcher.cpp \
+ $$CLUCENEDIR/search/MultiTermQuery.cpp \
+ $$CLUCENEDIR/search/PhrasePositions.cpp \
+ $$CLUCENEDIR/search/PhraseQuery.cpp \
+ $$CLUCENEDIR/search/PhraseScorer.cpp \
+ $$CLUCENEDIR/search/PrefixQuery.cpp \
+ $$CLUCENEDIR/search/QueryFilter.cpp \
+ $$CLUCENEDIR/search/RangeFilter.cpp \
+ $$CLUCENEDIR/search/RangeQuery.cpp \
+ $$CLUCENEDIR/search/SearchHeader.cpp \
+ $$CLUCENEDIR/search/Similarity.cpp \
+ $$CLUCENEDIR/search/SloppyPhraseScorer.cpp \
+ $$CLUCENEDIR/search/Sort.cpp \
+ $$CLUCENEDIR/search/TermQuery.cpp \
+ $$CLUCENEDIR/search/TermScorer.cpp \
+ $$CLUCENEDIR/search/WildcardQuery.cpp \
+ $$CLUCENEDIR/search/WildcardTermEnum.cpp \
+ $$CLUCENEDIR/store/FSDirectory.cpp \
+ $$CLUCENEDIR/store/IndexInput.cpp \
+ $$CLUCENEDIR/store/IndexOutput.cpp \
+ $$CLUCENEDIR/store/Lock.cpp \
+ $$CLUCENEDIR/store/MMapInput.cpp \
+ $$CLUCENEDIR/store/RAMDirectory.cpp \
+ $$CLUCENEDIR/store/TransactionalRAMDirectory.cpp \
+ $$CLUCENEDIR/util/BitSet.cpp \
+ $$CLUCENEDIR/util/Equators.cpp \
+ $$CLUCENEDIR/util/FastCharStream.cpp \
+ $$CLUCENEDIR/util/fileinputstream.cpp \
+ $$CLUCENEDIR/util/Misc.cpp \
+ $$CLUCENEDIR/util/Reader.cpp \
+ $$CLUCENEDIR/util/StringBuffer.cpp \
+ $$CLUCENEDIR/util/StringIntern.cpp \
+ $$CLUCENEDIR/util/ThreadLocal.cpp \
+ $$CLUCENEDIR/analysis/standard/StandardAnalyzer.cpp \
+ $$CLUCENEDIR/analysis/standard/StandardFilter.cpp \
+ $$CLUCENEDIR/analysis/standard/StandardTokenizer.cpp
+
+
+#Header files
+HEADERS += qclucene_global_p.h \
+ qclucene-config_p.h \
+ qanalyzer_p.h \
+ qtokenizer_p.h \
+ qtoken_p.h \
+ qtokenstream_p.h \
+ qdocument_p.h \
+ qfield_p.h \
+ qindexreader_p.h \
+ qindexwriter_p.h \
+ qterm_p.h \
+ qqueryparser_p.h \
+ qfilter_p.h \
+ qhits_p.h \
+ qsearchable_p.h \
+ qsort_p.h \
+ qquery_p.h \
+ qreader_p.h
+
+
+#Source files
+SOURCES += qanalyzer.cpp \
+ qtokenizer.cpp \
+ qtoken.cpp \
+ qtokenstream.cpp \
+ qdocument.cpp \
+ qfield.cpp \
+ qindexreader.cpp \
+ qindexwriter.cpp \
+ qterm.cpp \
+ qqueryparser.cpp \
+ qfilter.cpp \
+ qhits.cpp \
+ qsearchable.cpp \
+ qsort.cpp \
+ qquery.cpp \
+ qreader.cpp
diff --git a/tools/assistant/lib/fulltextsearch/fulltextsearch.pro b/tools/assistant/lib/fulltextsearch/fulltextsearch.pro
new file mode 100644
index 0000000000..e0cd13a821
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/fulltextsearch.pro
@@ -0,0 +1,50 @@
+
+QMAKE_TARGET_PRODUCT = QtCLucene
+QMAKE_TARGET_DESCRIPTION = QtCLucene full text search library wrapper.
+#if qt is built with frameworks in debug, we must build QtCLucene in debug and release
+#that's a similar logic as in qbase.pri
+mac:!static:contains(QT_CONFIG, qt_framework) {
+ CONFIG(debug, debug|release) {
+ !build_pass:CONFIG += build_all
+ }
+}
+QT_CONFIG -= qt_framework
+QT -= gui
+TEMPLATE = lib
+TARGET = QtCLucene
+DEFINES += QHELP_LIB
+include(../../../../src/qbase.pri)
+include(fulltextsearch.pri)
+
+CONFIG += qt warn_off
+contains(QT_CONFIG, reduce_exports) {
+ CONFIG += hide_symbols
+ # workaround for compiler errors on Ubuntu
+ linux*-g++*:DEFINES += _GLIBCXX_EXTERN_TEMPLATE=0
+}
+
+unix:QMAKE_PKGCONFIG_REQUIRES = QtCore
+
+# impossible to disable exceptions in clucene atm
+CONFIG(exceptions_off) {
+ CONFIG -= exceptions_off
+ CONFIG += exceptions
+ !win32|win32-g++ {
+ QMAKE_CFLAGS -= -fno-exceptions
+ QMAKE_CXXFLAGS -= -fno-exceptions
+ QMAKE_LFLAGS -= -fno-exceptions
+ QMAKE_CFLAGS += -fexceptions
+ QMAKE_CXXFLAGS += -fexceptions
+ QMAKE_LFLAGS += -fexceptions
+ }
+}
+
+win32-msvc.net | win32-msvc2* {
+ QMAKE_CFLAGS_RELEASE -= -O2
+ QMAKE_CXXFLAGS_RELEASE -= -O2
+}
+
+# the following define could be set globally in case we need it elsewhere
+solaris* {
+ DEFINES += Q_SOLARIS_VERSION=$$system(uname -r | sed -e 's/5\.//')
+}
diff --git a/tools/assistant/lib/fulltextsearch/license.txt b/tools/assistant/lib/fulltextsearch/license.txt
new file mode 100644
index 0000000000..9ef3d701d1
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/license.txt
@@ -0,0 +1,503 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
diff --git a/tools/assistant/lib/fulltextsearch/qanalyzer.cpp b/tools/assistant/lib/fulltextsearch/qanalyzer.cpp
new file mode 100644
index 0000000000..e19a0758f0
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qanalyzer.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qanalyzer_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/analysis/AnalysisHeader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneAnalyzerPrivate::QCLuceneAnalyzerPrivate()
+ : QSharedData()
+{
+ analyzer = 0;
+ deleteCLuceneAnalyzer = true;
+}
+
+QCLuceneAnalyzerPrivate::QCLuceneAnalyzerPrivate(const QCLuceneAnalyzerPrivate &other)
+ : QSharedData()
+{
+ analyzer = _CL_POINTER(other.analyzer);
+}
+
+QCLuceneAnalyzerPrivate::~QCLuceneAnalyzerPrivate()
+{
+ if (deleteCLuceneAnalyzer)
+ _CLDECDELETE(analyzer);
+}
+
+
+QCLuceneAnalyzer::QCLuceneAnalyzer()
+ : d(new QCLuceneAnalyzerPrivate())
+{
+ //nothing todo, private
+}
+
+QCLuceneAnalyzer::~QCLuceneAnalyzer()
+{
+ // nothing todo
+}
+
+qint32 QCLuceneAnalyzer::positionIncrementGap(const QString &fieldName) const
+{
+ Q_UNUSED(fieldName);
+ return 0;
+}
+
+QCLuceneTokenStream QCLuceneAnalyzer::tokenStream(const QString &fieldName,
+ const QCLuceneReader &reader) const
+{
+ TCHAR *fName = QStringToTChar(fieldName);
+ QCLuceneTokenStream tokenStream;
+ tokenStream.d->tokenStream = d->analyzer->tokenStream(fName, reader.d->reader);
+ delete [] fName;
+
+ return tokenStream;
+}
+
+
+QCLuceneStandardAnalyzer::QCLuceneStandardAnalyzer()
+ : QCLuceneAnalyzer()
+{
+ d->analyzer = new lucene::analysis::standard::StandardAnalyzer();
+}
+
+QCLuceneStandardAnalyzer::~QCLuceneStandardAnalyzer()
+{
+ // nothing todo
+}
+
+QCLuceneStandardAnalyzer::QCLuceneStandardAnalyzer(const QStringList &stopWords)
+{
+ const TCHAR **tArray = new const TCHAR*[stopWords.count() +1];
+
+ for(int i = 0; i < stopWords.count(); ++i) {
+ TCHAR *stopWord = QStringToTChar(stopWords.at(i));
+ tArray[i] = STRDUP_TtoT(stopWord);
+ delete [] stopWord;
+ }
+ tArray[stopWords.count()] = 0;
+
+ d->analyzer = new lucene::analysis::standard::StandardAnalyzer(tArray);
+}
+
+
+QCLuceneWhitespaceAnalyzer::QCLuceneWhitespaceAnalyzer()
+ : QCLuceneAnalyzer()
+{
+ d->analyzer = new lucene::analysis::WhitespaceAnalyzer();
+}
+
+QCLuceneWhitespaceAnalyzer::~QCLuceneWhitespaceAnalyzer()
+{
+ // nothing todo
+}
+
+
+QCLuceneSimpleAnalyzer::QCLuceneSimpleAnalyzer()
+ : QCLuceneAnalyzer()
+{
+ d->analyzer = new lucene::analysis::SimpleAnalyzer();
+}
+
+QCLuceneSimpleAnalyzer::~QCLuceneSimpleAnalyzer()
+{
+ // nothing todo
+}
+
+
+QCLuceneStopAnalyzer::QCLuceneStopAnalyzer()
+ : QCLuceneAnalyzer()
+{
+ d->analyzer = new lucene::analysis::StopAnalyzer();
+}
+
+QCLuceneStopAnalyzer::~QCLuceneStopAnalyzer()
+{
+ // nothing todo
+}
+
+QCLuceneStopAnalyzer::QCLuceneStopAnalyzer(const QStringList &stopWords)
+ : QCLuceneAnalyzer()
+{
+ const TCHAR **tArray = new const TCHAR*[stopWords.count() +1];
+
+ for(int i = 0; i < stopWords.count(); ++i) {
+ TCHAR *stopWord = QStringToTChar(stopWords.at(i));
+ tArray[i] = STRDUP_TtoT(stopWord);
+ delete [] stopWord;
+ }
+ tArray[stopWords.count()] = 0;
+
+ d->analyzer = new lucene::analysis::StopAnalyzer(tArray);
+}
+
+QStringList QCLuceneStopAnalyzer::englishStopWords() const
+{
+ QStringList stopWordList;
+
+ const TCHAR** stopWords = lucene::analysis::StopAnalyzer::ENGLISH_STOP_WORDS;
+ for (qint32 i = 0; stopWords[i] != 0; ++i)
+ stopWordList.append(TCharToQString(stopWords[i]));
+
+ return stopWordList;
+}
+
+
+QCLuceneKeywordAnalyzer::QCLuceneKeywordAnalyzer()
+ : QCLuceneAnalyzer()
+{
+ d->analyzer = new lucene::analysis::KeywordAnalyzer();
+}
+
+QCLuceneKeywordAnalyzer::~QCLuceneKeywordAnalyzer()
+{
+ // nothing todo
+}
+
+
+QCLucenePerFieldAnalyzerWrapper::QCLucenePerFieldAnalyzerWrapper(
+ QCLuceneAnalyzer *defaultAnalyzer)
+ : QCLuceneAnalyzer()
+{
+ d->analyzer = new
+ lucene::analysis::PerFieldAnalyzerWrapper(defaultAnalyzer->d->analyzer);
+
+ analyzers.append(defaultAnalyzer);
+ defaultAnalyzer->d->deleteCLuceneAnalyzer = false;
+}
+
+QCLucenePerFieldAnalyzerWrapper::~QCLucenePerFieldAnalyzerWrapper()
+{
+ qDeleteAll(analyzers);
+}
+
+void QCLucenePerFieldAnalyzerWrapper::addAnalyzer(const QString &fieldName,
+ QCLuceneAnalyzer *analyzer)
+{
+ lucene::analysis::PerFieldAnalyzerWrapper *analyzerWrapper =
+ static_cast<lucene::analysis::PerFieldAnalyzerWrapper*> (d->analyzer);
+
+ if (analyzerWrapper == 0)
+ return;
+
+ analyzers.append(analyzer);
+ analyzer->d->deleteCLuceneAnalyzer = false;
+
+ TCHAR *fName = QStringToTChar(fieldName);
+ analyzerWrapper->addAnalyzer(fName, analyzer->d->analyzer);
+ delete [] fName;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qanalyzer_p.h b/tools/assistant/lib/fulltextsearch/qanalyzer_p.h
new file mode 100644
index 0000000000..c0b94f4069
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qanalyzer_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QANALYZER_P_H
+#define QANALYZER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qreader_p.h"
+#include "qtokenstream_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(analysis)
+ class Analyzer;
+CL_NS_END
+CL_NS_USE(analysis)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneIndexWriter;
+class QCLuceneQueryParser;
+class QCLuceneStopAnalyzer;
+class QCLuceneSimpleAnalyzer;
+class QCLuceneKeywordAnalyzer;
+class QCLuceneStandardAnalyzer;
+class QCLuceneWhitespaceAnalyzer;
+class QCLucenePerFieldAnalyzerWrapper;
+
+class QHELP_EXPORT QCLuceneAnalyzerPrivate : public QSharedData
+{
+public:
+ QCLuceneAnalyzerPrivate();
+ QCLuceneAnalyzerPrivate(const QCLuceneAnalyzerPrivate &other);
+
+ ~QCLuceneAnalyzerPrivate();
+
+ Analyzer *analyzer;
+ bool deleteCLuceneAnalyzer;
+
+private:
+ QCLuceneAnalyzerPrivate &operator=(const QCLuceneAnalyzerPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneAnalyzer
+{
+public:
+ virtual ~QCLuceneAnalyzer();
+
+ qint32 positionIncrementGap(const QString &fieldName) const;
+ QCLuceneTokenStream tokenStream(const QString &fieldName,
+ const QCLuceneReader &reader) const;
+
+protected:
+ friend class QCLuceneIndexWriter;
+ friend class QCLuceneQueryParser;
+ friend class QCLuceneStopAnalyzer;
+ friend class QCLuceneSimpleAnalyzer;
+ friend class QCLuceneKeywordAnalyzer;
+ friend class QCLuceneStandardAnalyzer;
+ friend class QCLuceneWhitespaceAnalyzer;
+ friend class QCLucenePerFieldAnalyzerWrapper;
+ QSharedDataPointer<QCLuceneAnalyzerPrivate> d;
+
+private:
+ QCLuceneAnalyzer();
+};
+
+class QHELP_EXPORT QCLuceneStandardAnalyzer : public QCLuceneAnalyzer
+{
+public:
+ QCLuceneStandardAnalyzer();
+ QCLuceneStandardAnalyzer(const QStringList &stopWords);
+
+ ~QCLuceneStandardAnalyzer();
+};
+
+class QHELP_EXPORT QCLuceneWhitespaceAnalyzer : public QCLuceneAnalyzer
+{
+public:
+ QCLuceneWhitespaceAnalyzer();
+ ~QCLuceneWhitespaceAnalyzer();
+};
+
+class QHELP_EXPORT QCLuceneSimpleAnalyzer : public QCLuceneAnalyzer
+{
+public:
+ QCLuceneSimpleAnalyzer();
+ ~QCLuceneSimpleAnalyzer();
+};
+
+class QHELP_EXPORT QCLuceneStopAnalyzer : public QCLuceneAnalyzer
+{
+public:
+ QCLuceneStopAnalyzer();
+ QCLuceneStopAnalyzer(const QStringList &stopWords);
+
+ ~QCLuceneStopAnalyzer();
+
+ QStringList englishStopWords() const;
+};
+
+class QHELP_EXPORT QCLuceneKeywordAnalyzer : public QCLuceneAnalyzer
+{
+public:
+ QCLuceneKeywordAnalyzer();
+ ~QCLuceneKeywordAnalyzer();
+};
+
+class QHELP_EXPORT QCLucenePerFieldAnalyzerWrapper : public QCLuceneAnalyzer
+{
+public:
+ QCLucenePerFieldAnalyzerWrapper(QCLuceneAnalyzer *defaultAnalyzer);
+ ~QCLucenePerFieldAnalyzerWrapper();
+
+ void addAnalyzer(const QString &fieldName, QCLuceneAnalyzer *analyzer);
+
+private:
+ QList<QCLuceneAnalyzer*> analyzers;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANALYZER_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qclucene-config_p.h b/tools/assistant/lib/fulltextsearch/qclucene-config_p.h
new file mode 100644
index 0000000000..b3befbec5e
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qclucene-config_p.h
@@ -0,0 +1,552 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QCLUCENE_CONFIG_P_H
+#define QCLUCENE_CONFIG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#ifndef _SRC_CLUCENE_CLUCENE_CONFIG_H
+#define _SRC_CLUCENE_CLUCENE_CONFIG_H 1
+
+/*
+src/CLucene/clucene-config.h.
+Generated
+automatically
+at
+end
+of
+configure.
+*/
+/* config.h.tmp. Generated by configure. */
+/* config.h.tmp.in. Generated from configure.ac by autoheader. */
+
+/* Disable multithreading */
+/* #undef _CL_DISABLE_MULTITHREADING */
+
+/* Define to 1 if you have the <algorithm> header file. */
+#ifndef _CL_HAVE_ALGORITHM
+#define _CL_HAVE_ALGORITHM 1
+#endif
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#ifndef _CL_HAVE_CTYPE_H
+#define _CL_HAVE_CTYPE_H 1
+#endif
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#ifndef _CL_HAVE_DIRENT_H
+#define _CL_HAVE_DIRENT_H 1
+#endif
+
+#if !defined (__MINGW32__)
+ /* Define to 1 if you have the <dlfcn.h> header file. */
+# ifndef _CL_HAVE_DLFCN_H
+# define _CL_HAVE_DLFCN_H 1
+# endif
+#endif
+
+/* Define to 1 if you have the <errno.h> header file. */
+#ifndef _CL_HAVE_ERRNO_H
+#define _CL_HAVE_ERRNO_H 1
+#endif
+
+#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C)
+ /* Define to 1 if you have the <ext/hash_map> header file. */
+# ifndef _CL_HAVE_EXT_HASH_MAP
+# define _CL_HAVE_EXT_HASH_MAP 1
+# endif
+
+ /* Define to 1 if you have the <ext/hash_set> header file. */
+# ifndef _CL_HAVE_EXT_HASH_SET
+# define _CL_HAVE_EXT_HASH_SET 1
+# endif
+#endif
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#ifndef _CL_HAVE_FCNTL_H
+#define _CL_HAVE_FCNTL_H 1
+#endif
+
+#if !defined(__xlC__) && !defined(__xlc__) && !defined (__MINGW32__) && \
+ !defined(__HP_aCC) && !defined(__SUNPRO_C) && !defined(__SUNPRO_CC) || \
+ defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x550) || (defined(__HP_aCC) && defined(__ia64))
+ /* Define to 1 if the system has the type `float_t'. */
+# ifndef _CL_HAVE_FLOAT_T
+# define _CL_HAVE_FLOAT_T 1
+# endif
+#endif
+
+/* Define to 1 if you have the <functional> header file. */
+#ifndef _CL_HAVE_FUNCTIONAL
+#define _CL_HAVE_FUNCTIONAL 1
+#endif
+
+/* Does not support new float byte<->float conversions */
+#ifndef _CL_HAVE_FUNCTIONING_FLOAT_BYTE
+#define _CL_HAVE_FUNCTIONING_FLOAT_BYTE
+#endif
+
+/* Define to 1 if you have the `getpagesize' function. */
+#ifndef _CL_HAVE_GETPAGESIZE
+#define _CL_HAVE_GETPAGESIZE 1
+#endif
+
+/* Define to 1 if you have the <hash_map> header file. */
+/* #undef _CL_HAVE_HASH_MAP */
+
+/* Define to 1 if you have the <hash_set> header file. */
+/* #undef _CL_HAVE_HASH_SET */
+
+/* Define to 1 if the system has the type `intptr_t'. */
+#ifndef _CL_HAVE_INTPTR_T
+#define _CL_HAVE_INTPTR_T 1
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifndef _CL_HAVE_INTTYPES_H
+#define _CL_HAVE_INTTYPES_H 1
+#endif
+
+/* Define to 1 if you have the <list> header file. */
+#ifndef _CL_HAVE_LIST
+#define _CL_HAVE_LIST 1
+#endif
+
+/* Define to 1 if you have the `lltoa' function. */
+/* #undef _CL_HAVE_LLTOA */
+
+#if defined(__MINGW32__)
+ /* Define to 1 if you have the `lltow' function. */
+# ifndef _CL_HAVE_LLTOW
+# define _CL_HAVE_LLTOW 1
+# endif
+#endif
+
+#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__xlC__) && !defined(__xlc__)
+ /* Define to 1 if long double works and has more range or precision than double. */
+# ifndef _CL_HAVE_LONG_DOUBLE
+# define _CL_HAVE_LONG_DOUBLE 1
+# endif
+#endif
+
+/* Define to 1 if you have the <map> header file. */
+#ifndef _CL_HAVE_MAP
+#define _CL_HAVE_MAP 1
+#endif
+
+/* Define to 1 if you have the <math.h> header file. */
+#ifndef _CL_HAVE_MATH_H
+#define _CL_HAVE_MATH_H 1
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef _CL_HAVE_MEMORY_H
+#define _CL_HAVE_MEMORY_H 1
+#endif
+
+#if !defined(__MINGW32__) && !defined(__HP_aCC) && !defined(__xlC__) && !defined(__xlc__)
+ /* Define to 1 if you have a working `mmap' system call. */
+# ifndef _CL_HAVE_MMAP
+# define _CL_HAVE_MMAP 1
+# endif
+#endif
+
+/* define if the compiler implements namespaces */
+#ifndef _CL_HAVE_NAMESPACES
+#define _CL_HAVE_NAMESPACES
+#endif
+
+#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) || defined(__HP_aCC) || defined(__xlC__) || defined(__xlc__)
+ /* Define if you have the nanosleep function */
+# ifndef _CL_HAVE_NANOSLEEP
+# define _CL_HAVE_NANOSLEEP 1
+# endif
+#endif
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef _CL_HAVE_NDIR_H */
+
+/* Does not support new float byte<->float conversions */
+/* #undef _CL_HAVE_NO_FLOAT_BYTE */
+
+/* Does not support try/catch blocks */
+/* #undef _CL_HAVE_NO_FUNCTION_TRY_BLOCKS */
+
+/* Define to 1 if you have the `printf' function. */
+#ifndef _CL_HAVE_PRINTF
+#define _CL_HAVE_PRINTF 1
+#endif
+
+#if !defined(__MINGW32__)
+ /* Define if you have POSIX threads libraries and header files. */
+# ifndef _CL_HAVE_PTHREAD
+# define _CL_HAVE_PTHREAD 1
+# endif
+#endif
+
+/* Define if recursive pthread mutexes are available */
+/* #undef _CL_HAVE_PTHREAD_MUTEX_RECURSIVE */
+
+/* Define to 1 if you have the <set> header file. */
+#ifndef _CL_HAVE_SET
+#define _CL_HAVE_SET 1
+#endif
+
+/* Define to 1 if you have the `snprintf' function. */
+#ifndef _CL_HAVE_SNPRINTF
+#define _CL_HAVE_SNPRINTF 1
+#endif
+
+/* Defined if the snprintf overflow test fails */
+/* #undef _CL_HAVE_SNPRINTF_BUG */
+
+/* Define to 1 if you have the `snwprintf' function. */
+/* #undef _CL_HAVE_SNWPRINTF */
+
+#if !defined(__HP_aCC) && !defined(__SUNPRO_CC) && !defined(__SUNPRO_C)
+ /* define if the compiler supports ISO C++ standard library */
+# ifndef _CL_HAVE_STD
+# define _CL_HAVE_STD
+# endif
+#endif
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#ifndef _CL_HAVE_STDARG_H
+#define _CL_HAVE_STDARG_H 1
+#endif
+
+/* x */
+#ifndef _CL_HAVE_STDEXCEPT
+#define _CL_HAVE_STDEXCEPT
+#endif
+
+#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__HP_aCC) && \
+ !defined(__xlC__) && !defined(__xlc__)
+ /* Define to 1 if you have the <stdint.h> header file. */
+# ifndef _CL_HAVE_STDINT_H
+# define _CL_HAVE_STDINT_H 1
+# endif
+#endif
+
+#if !defined(__HP_aCC)
+ /* Define to 1 if you have the <stdlib.h> header file. */
+# ifndef _CL_HAVE_STDLIB_H
+# define _CL_HAVE_STDLIB_H 1
+# endif
+
+ /* define if the compiler supports Standard Template Library */
+# ifndef _CL_HAVE_STL
+# define _CL_HAVE_STL
+# endif
+#endif
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef _CL_HAVE_STRINGS_H
+#define _CL_HAVE_STRINGS_H 1
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef _CL_HAVE_STRING_H
+#define _CL_HAVE_STRING_H 1
+#endif
+
+/* Define to 1 if you have the `strlwr' function. */
+/* #undef _CL_HAVE_STRLWR */
+
+/* Define to 1 if you have the `strtoll' function. */
+/* #undef _CL_HAVE_STRTOLL */
+
+/* Define to 1 if you have the `strupr' function. */
+/* #undef _CL_HAVE_STRUPR */
+
+/* Defined if the swprintf test fails */
+#ifndef _CL_HAVE_SWPRINTF_BUG
+#define _CL_HAVE_SWPRINTF_BUG
+#endif
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef _CL_HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef _CL_HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifndef _CL_HAVE_SYS_STAT_H
+#define _CL_HAVE_SYS_STAT_H 1
+#endif
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#ifndef _CL_HAVE_SYS_TIMEB_H
+#define _CL_HAVE_SYS_TIMEB_H 1
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifndef _CL_HAVE_SYS_TYPES_H
+#define _CL_HAVE_SYS_TYPES_H 1
+#endif
+
+// Do not use the tchar.h that ships with mingw, this causes the qt build to
+// fail (211547, 211401, etc...), reuse the replacement as with any other compiler
+// #if defined(__MINGW32__)
+// /* Define to 1 if you have the <tchar.h> header file. */
+// # ifndef _CL_HAVE_TCHAR_H
+// # define _CL_HAVE_TCHAR_H 1
+// # endif
+// #endif
+
+#if defined(__MINGW32__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)
+ /* Define to 1 if you have the `tell' function. */
+# ifndef _CL_HAVE_TELL
+# define _CL_HAVE_TELL 1
+# endif
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef _CL_HAVE_UNISTD_H
+#define _CL_HAVE_UNISTD_H 1
+#endif
+
+/* Define to 1 if you have the <vector> header file. */
+#ifndef _CL_HAVE_VECTOR
+#define _CL_HAVE_VECTOR 1
+#endif
+
+/* Define to 1 if you have the `vsnwprintf' function. */
+/* #undef _CL_HAVE_VSNWPRINTF */
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#ifndef _CL_HAVE_WCHAR_H
+#define _CL_HAVE_WCHAR_H 1
+#endif
+
+/* Define to 1 if the system has the type `wchar_t'. */
+#ifndef _CL_HAVE_WCHAR_T
+#define _CL_HAVE_WCHAR_T 1
+#endif
+
+#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__MINGW32__) && \
+ !defined(Q_OS_MAC) && !defined(__HP_aCC)
+ /* Define to 1 if you have the `wcscasecmp' function. */
+# ifndef _CL_HAVE_WCSCASECMP
+# define _CL_HAVE_WCSCASECMP 1
+# endif
+#endif
+
+/* Define to 1 if you have the `wcscat' function. */
+#ifndef _CL_HAVE_WCSCAT
+#define _CL_HAVE_WCSCAT 1
+#endif
+
+/* Define to 1 if you have the `wcschr' function. */
+#ifndef _CL_HAVE_WCSCHR
+#define _CL_HAVE_WCSCHR 1
+#endif
+
+/* Define to 1 if you have the `wcscmp' function. */
+#ifndef _CL_HAVE_WCSCMP
+#define _CL_HAVE_WCSCMP 1
+#endif
+
+/* Define to 1 if you have the `wcscpy' function. */
+#ifndef _CL_HAVE_WCSCPY
+#define _CL_HAVE_WCSCPY 1
+#endif
+
+/* Define to 1 if you have the `wcscspn' function. */
+#ifndef _CL_HAVE_WCSCSPN
+#define _CL_HAVE_WCSCSPN 1
+#endif
+
+#if defined(__MINGW32__)
+ /* Define to 1 if you have the `wcsicmp' function. */
+# ifndef _CL_HAVE_WCSICMP
+# define _CL_HAVE_WCSICMP 1
+# endif
+#endif
+
+/* Define to 1 if you have the `wcslen' function. */
+#ifndef _CL_HAVE_WCSLEN
+#define _CL_HAVE_WCSLEN 1
+#endif
+
+/* Define to 1 if you have the `wcsncmp' function. */
+#ifndef _CL_HAVE_WCSNCMP
+#define _CL_HAVE_WCSNCMP 1
+#endif
+
+/* Define to 1 if you have the `wcsncpy' function. */
+#ifndef _CL_HAVE_WCSNCPY
+#define _CL_HAVE_WCSNCPY 1
+#endif
+
+/* Define to 1 if you have the `wcsstr' function. */
+#ifndef _CL_HAVE_WCSSTR
+#define _CL_HAVE_WCSSTR 1
+#endif
+
+/* Define to 1 if you have the `wcstod' function. */
+#ifndef _CL_HAVE_WCSTOD
+#define _CL_HAVE_WCSTOD 1
+#endif
+
+#if !defined(__SUNPRO_CC) && !defined(__SUNPRO_C) && !defined(__HP_aCC)
+ /* Define to 1 if you have the `wcstoll' function. */
+# ifndef _CL_HAVE_WCSTOLL
+# define _CL_HAVE_WCSTOLL 1
+# endif
+#endif
+
+#if defined(__MINGW32__)
+ /* Define to 1 if you have the `wcsupr' function. */
+# ifndef _CL_HAVE_WCSUPR
+# define _CL_HAVE_WCSUPR 1
+# endif
+#endif
+
+#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) || defined(__HP_aCC)
+ /* Define to 1 if you have a functioning <wchar.h> header file. */
+# ifndef _CL_HAVE_WCTYPE_H
+# define _CL_HAVE_WCTYPE_H
+# endif
+#endif
+
+/* Define to 1 if you have the `wprintf' function. */
+/* #undef _CL_HAVE_WPRINTF */
+
+#if defined(__MINGW32__)
+ /* Define to 1 if you have the `_filelength' function. */
+# ifndef _CL_HAVE__FILELENGTH
+# define _CL_HAVE__FILELENGTH 1
+# endif
+#endif
+
+/* How to define a static const in a class */
+#ifndef LUCENE_STATIC_CONSTANT_SYNTAX
+#define LUCENE_STATIC_CONSTANT_SYNTAX 1
+#endif
+
+/* Name of package */
+#ifndef _CL_PACKAGE
+#define _CL_PACKAGE "clucene-core"
+#endif
+
+/* Define to the address where bug reports for this package should be sent. */
+#ifndef _CL_PACKAGE_BUGREPORT
+#define _CL_PACKAGE_BUGREPORT ""
+#endif
+
+/* Define to the full name of this package. */
+#ifndef _CL_PACKAGE_NAME
+#define _CL_PACKAGE_NAME ""
+#endif
+
+/* Define to the full name and version of this package. */
+#ifndef _CL_PACKAGE_STRING
+#define _CL_PACKAGE_STRING ""
+#endif
+
+/* Define to the one symbol short name of this package. */
+#ifndef _CL_PACKAGE_TARNAME
+#define _CL_PACKAGE_TARNAME ""
+#endif
+
+/* Define to the version of this package. */
+#ifndef _CL_PACKAGE_VERSION
+#define _CL_PACKAGE_VERSION ""
+#endif
+
+/* Define to the necessary symbol if this constant uses a non-standard name on
+ your system. */
+/* #undef _CL_PTHREAD_CREATE_JOINABLE */
+
+/* The size of a `unsigned char', as computed by sizeof. */
+/* #undef _CL_SIZEOF_UNSIGNED_CHAR */
+
+/* The size of a `unsigned int', as computed by sizeof. */
+/* #undef _CL_SIZEOF_UNSIGNED_INT */
+
+/* The size of a `unsigned long', as computed by sizeof. */
+/* #undef _CL_SIZEOF_UNSIGNED_LONG */
+
+/* The size of a `unsigned long long', as computed by sizeof. */
+/* #undef _CL_SIZEOF_UNSIGNED_LONG_LONG */
+
+/* The size of a `unsigned __int64', as computed by sizeof. */
+/* #undef _CL_SIZEOF_UNSIGNED___INT64 */
+
+/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef _CL_STAT_MACROS_BROKEN */
+
+#if !defined(__HP_aCC)
+ /* Define to 1 if you have the ANSI C header files. */
+# ifndef _CL_STDC_HEADERS
+# define _CL_STDC_HEADERS 1
+# endif
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+# ifndef _CL_TIME_WITH_SYS_TIME
+# define _CL_TIME_WITH_SYS_TIME 1
+# endif
+#endif
+
+/* Version number of package */
+#ifndef _CL_VERSION
+#define _CL_VERSION "0.9.17"
+#endif
+
+/* Forces into Ascii mode */
+/* #undef _ASCII */
+
+/* Conditional Debugging */
+/* #undef _CL__CND_DEBUG */
+
+/* debuging option */
+/* #undef _DEBUG */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* If not already defined, then define as a datatype of *exactly* 32 bits. */
+/* #undef uint32_t */
+
+/* If not already defined, then define as a datatype of *exactly* 64 bits. */
+/* #undef uint64_t */
+
+/* If not already defined, then define as a datatype of *exactly* 8 bits. */
+/* #undef uint8_t */
+
+/* once:
+_SRC_CLUCENE_CLUCENE_CONFIG_H
+*/
+#endif
+
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+# define LUCENE_NO_STDC_NAMESPACE
+#endif
+
+
+#endif // QCLUCENE_CONFIG_P_H
+
diff --git a/tools/assistant/lib/fulltextsearch/qclucene_global_p.h b/tools/assistant/lib/fulltextsearch/qclucene_global_p.h
new file mode 100644
index 0000000000..2a9d146848
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qclucene_global_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QCLUCENE_GLOBAL_P_H
+#define QCLUCENE_GLOBAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#if !defined(_MSC_VER)
+# include "qclucene-config_p.h"
+#endif
+
+#include <QtCore/QChar>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_SHARED) && !defined(QT_DLL)
+# define QHELP_EXPORT
+#elif defined(QHELP_LIB)
+# define QHELP_EXPORT Q_DECL_EXPORT
+#else
+# define QHELP_EXPORT Q_DECL_IMPORT
+#endif
+
+//
+// W A R N I N G
+// -------------
+//
+// adjustments here, need to be done in
+// QTDIR/src/3rdparty/clucene/src/CLucene/StdHeader.h as well
+//
+#if defined(_LUCENE_DONTIMPLEMENT_NS_MACROS)
+
+#elif !defined(DISABLE_NAMESPACE)
+# ifdef QT_NAMESPACE
+# define CL_NS_DEF(sub) namespace QT_NAMESPACE { namespace lucene{ namespace sub{
+# define CL_NS_DEF2(sub,sub2) namespace QT_NAMESPACE { namespace lucene{ namespace sub{ namespace sub2 {
+
+# define CL_NS_END }}}
+# define CL_NS_END2 }}}}
+
+# define CL_NS_USE(sub) using namespace QT_NAMESPACE::lucene::sub;
+# define CL_NS_USE2(sub,sub2) using namespace QT_NAMESPACE::lucene::sub::sub2;
+
+# define CL_NS(sub) QT_NAMESPACE::lucene::sub
+# define CL_NS2(sub,sub2) QT_NAMESPACE::lucene::sub::sub2
+# else
+# define CL_NS_DEF(sub) namespace lucene{ namespace sub{
+# define CL_NS_DEF2(sub,sub2) namespace lucene{ namespace sub{ namespace sub2 {
+
+# define CL_NS_END }}
+# define CL_NS_END2 }}}
+
+# define CL_NS_USE(sub) using namespace lucene::sub;
+# define CL_NS_USE2(sub,sub2) using namespace lucene::sub::sub2;
+
+# define CL_NS(sub) lucene::sub
+# define CL_NS2(sub,sub2) lucene::sub::sub2
+# endif
+#else
+# define CL_NS_DEF(sub)
+# define CL_NS_DEF2(sub, sub2)
+# define CL_NS_END
+# define CL_NS_END2
+# define CL_NS_USE(sub)
+# define CL_NS_USE2(sub,sub2)
+# define CL_NS(sub)
+# define CL_NS2(sub,sub2)
+#endif
+
+#if !defined(_MSC_VER) && defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T)
+# if !defined(TCHAR)
+# define TCHAR wchar_t
+# endif
+#else
+# include <windows.h>
+#endif
+
+namespace {
+ TCHAR* QStringToTChar(const QString &str)
+ {
+ TCHAR *string = new TCHAR[(str.length() +1) * sizeof(TCHAR)];
+ memset(string, 0, (str.length() +1) * sizeof(TCHAR));
+ #if defined(UNICODE) || defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T)
+ str.toWCharArray(string);
+ #else
+ const QByteArray ba = str.toAscii();
+ strcpy(string, ba.constData());
+ #endif
+ return string;
+ }
+
+ QString TCharToQString(const TCHAR *string)
+ {
+ #if defined(UNICODE) || defined(_CL_HAVE_WCHAR_H) && defined(_CL_HAVE_WCHAR_T)
+ QString retValue = QString::fromWCharArray(string);
+ return retValue;
+ #else
+ return QString(QLatin1String(string));
+ #endif
+ }
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCLUCENE_GLOBAL_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qdocument.cpp b/tools/assistant/lib/fulltextsearch/qdocument.cpp
new file mode 100644
index 0000000000..7e0f6d9b35
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qdocument.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qdocument_p.h"
+#include "qreader_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/util/Reader.h>
+#include <CLucene/document/Document.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneDocumentPrivate::QCLuceneDocumentPrivate()
+ : QSharedData()
+{
+ document = 0;
+ deleteCLuceneDocument = true;
+}
+
+QCLuceneDocumentPrivate::QCLuceneDocumentPrivate(const QCLuceneDocumentPrivate &other)
+ : QSharedData()
+{
+ document = _CL_POINTER(other.document);
+}
+
+QCLuceneDocumentPrivate::~QCLuceneDocumentPrivate()
+{
+ if (deleteCLuceneDocument)
+ _CLDECDELETE(document);
+}
+
+
+QCLuceneDocument::QCLuceneDocument()
+ : d(new QCLuceneDocumentPrivate())
+{
+ // nothing todo
+ d->document = new lucene::document::Document();
+}
+
+QCLuceneDocument::~QCLuceneDocument()
+{
+ qDeleteAll(fieldList);
+ fieldList.clear();
+}
+
+void QCLuceneDocument::add(QCLuceneField *field)
+{
+ field->d->deleteCLuceneField = false;
+ d->document->add(*field->d->field);
+ fieldList.append(field);
+}
+
+QCLuceneField* QCLuceneDocument::getField(const QString &name) const
+{
+ QCLuceneField* field = 0;
+ foreach (field, fieldList) {
+ if (field->name() == name && field->d->field != 0)
+ return field;
+ }
+
+ field = 0;
+ TCHAR *fieldName = QStringToTChar(name);
+ lucene::document::Field *f = d->document->getField(fieldName);
+ if (f) {
+ field = new QCLuceneField();
+ field->d->field = f;
+ fieldList.append(field);
+ field->d->deleteCLuceneField = false;
+
+ lucene::util::Reader *r = f->readerValue();
+ if (r) {
+ field->reader->d->reader = r;
+ field->reader->d->deleteCLuceneReader = false;
+ }
+ }
+ delete [] fieldName;
+
+ return field;
+}
+
+QString QCLuceneDocument::get(const QString &name) const
+{
+ QCLuceneField* field = getField(name);
+ if (field)
+ return field->stringValue();
+
+ return QString();
+}
+
+QString QCLuceneDocument::toString() const
+{
+ return TCharToQString(d->document->toString());
+}
+
+void QCLuceneDocument::setBoost(qreal boost)
+{
+ d->document->setBoost(qreal(boost));
+}
+
+qreal QCLuceneDocument::getBoost() const
+{
+ return qreal(d->document->getBoost());
+}
+
+void QCLuceneDocument::removeField(const QString &name)
+{
+ TCHAR *fieldName = QStringToTChar(name);
+ d->document->removeField(fieldName);
+ delete [] fieldName;
+
+ QList<QCLuceneField*> tmp;
+ lucene::document::DocumentFieldEnumeration *dfe = d->document->fields();
+ while (dfe->hasMoreElements()) {
+ const lucene::document::Field* f = dfe->nextElement();
+ foreach (QCLuceneField* field, fieldList) {
+ if (f == field->d->field) {
+ tmp.append(field);
+ break;
+ }
+ }
+ }
+ _CLDELETE(dfe);
+ fieldList = tmp;
+}
+
+void QCLuceneDocument::removeFields(const QString &name)
+{
+ for (qint32 i = fieldList.count() -1; i >= 0; --i) {
+ QCLuceneField* field = fieldList.at(i);
+ if (field->name() == name)
+ delete fieldList.takeAt(i);
+ }
+
+ TCHAR *fieldName = QStringToTChar(name);
+ d->document->removeFields(fieldName);
+ delete [] fieldName;
+}
+
+QStringList QCLuceneDocument::getValues(const QString &name) const
+{
+ TCHAR *fieldName = QStringToTChar(name);
+ TCHAR **values = d->document->getValues(fieldName);
+
+ QStringList retValue;
+ if (values) {
+ for (qint32 i = 0; 0 != values[i]; ++i) {
+ retValue.append(TCharToQString((const TCHAR*)values[i]));
+ delete [] values[i]; values[i] = 0;
+ }
+ delete values;
+ }
+
+ delete [] fieldName;
+ return retValue;
+}
+
+void QCLuceneDocument::clear()
+{
+ d->document->clear();
+ qDeleteAll(fieldList);
+ fieldList.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qdocument_p.h b/tools/assistant/lib/fulltextsearch/qdocument_p.h
new file mode 100644
index 0000000000..45f3d00cb1
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qdocument_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QDOCUMENT_P_H
+#define QDOCUMENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qfield_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(document)
+ class Document;
+CL_NS_END
+CL_NS_USE(document)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneHits;
+class QCLuceneIndexReader;
+class QCLuceneIndexWriter;
+class QCLuceneIndexSearcher;
+class QCLuceneMultiSearcher;
+
+class QHELP_EXPORT QCLuceneDocumentPrivate : public QSharedData
+{
+public:
+ QCLuceneDocumentPrivate();
+ QCLuceneDocumentPrivate(const QCLuceneDocumentPrivate &other);
+
+ ~QCLuceneDocumentPrivate();
+
+ Document *document;
+ bool deleteCLuceneDocument;
+
+private:
+ QCLuceneDocumentPrivate &operator=(const QCLuceneDocumentPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneDocument
+{
+public:
+ QCLuceneDocument();
+ ~QCLuceneDocument();
+
+ void add(QCLuceneField *field);
+ QCLuceneField* getField(const QString &name) const;
+ QString get(const QString &name) const;
+ QString toString() const;
+ void setBoost(qreal boost);
+ qreal getBoost() const;
+ void removeField(const QString &name);
+ void removeFields(const QString &name);
+ QStringList getValues(const QString &name) const;
+ void clear();
+
+protected:
+ friend class QCLuceneHits;
+ friend class QCLuceneIndexReader;
+ friend class QCLuceneIndexWriter;
+ friend class QCLuceneIndexSearcher;
+ friend class QCLuceneMultiSearcher;
+ QSharedDataPointer<QCLuceneDocumentPrivate> d;
+
+private:
+ mutable QList<QCLuceneField*> fieldList;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDOCUMENT_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qfield.cpp b/tools/assistant/lib/fulltextsearch/qfield.cpp
new file mode 100644
index 0000000000..0c64fa8c7d
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qfield.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qfield_p.h"
+#include "qreader_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/document/Field.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneFieldPrivate::QCLuceneFieldPrivate()
+ : QSharedData()
+{
+ field = 0;
+ deleteCLuceneField = true;
+}
+
+QCLuceneFieldPrivate::QCLuceneFieldPrivate(const QCLuceneFieldPrivate &other)
+ : QSharedData()
+{
+ field = _CL_POINTER(other.field);
+}
+
+QCLuceneFieldPrivate::~QCLuceneFieldPrivate()
+{
+ if (deleteCLuceneField)
+ _CLDECDELETE(field);
+}
+
+
+QCLuceneField::QCLuceneField()
+ : d(new QCLuceneFieldPrivate())
+ , reader(0)
+{
+ // nothing todo
+}
+
+QCLuceneField::QCLuceneField(const QString &name, const QString &value, int configs)
+ : d(new QCLuceneFieldPrivate())
+ , reader(0)
+{
+ TCHAR* fieldName = QStringToTChar(name);
+ TCHAR* fieldValue = QStringToTChar(value);
+
+ d->field = new lucene::document::Field(fieldName, fieldValue, configs);
+
+ delete [] fieldName;
+ delete [] fieldValue;
+}
+
+QCLuceneField::QCLuceneField(const QString &name, QCLuceneReader *reader,
+ int configs)
+ : d(new QCLuceneFieldPrivate())
+ , reader(reader)
+{
+ TCHAR* fieldName = QStringToTChar(name);
+
+ reader->d->deleteCLuceneReader = false; // clucene takes ownership
+ d->field = new lucene::document::Field(fieldName, reader->d->reader, configs);
+
+ delete [] fieldName;
+}
+
+QCLuceneField::~QCLuceneField()
+{
+ delete reader;
+}
+
+QString QCLuceneField::name() const
+{
+ return TCharToQString(d->field->name());
+}
+
+QString QCLuceneField::stringValue() const
+{
+ return TCharToQString((const TCHAR*)d->field->stringValue());
+}
+
+QCLuceneReader* QCLuceneField::readerValue() const
+{
+ return reader;
+}
+
+bool QCLuceneField::isStored() const
+{
+ return d->field->isStored();
+}
+
+bool QCLuceneField::isIndexed() const
+{
+ return d->field->isIndexed();
+}
+
+bool QCLuceneField::isTokenized() const
+{
+ return d->field->isTokenized();
+}
+
+bool QCLuceneField::isCompressed() const
+{
+ return d->field->isCompressed();
+}
+
+void QCLuceneField::setConfig(int termVector)
+{
+ d->field->setConfig(termVector);
+}
+
+bool QCLuceneField::isTermVectorStored() const
+{
+ return d->field->isTermVectorStored();
+}
+
+bool QCLuceneField::isStoreOffsetWithTermVector() const
+{
+ return d->field->isStoreOffsetWithTermVector();
+}
+
+bool QCLuceneField::isStorePositionWithTermVector() const
+{
+ return d->field->isStorePositionWithTermVector();
+}
+
+qreal QCLuceneField::getBoost() const
+{
+ return qreal(d->field->getBoost());
+}
+
+void QCLuceneField::setBoost(qreal value)
+{
+ d->field->setBoost(qreal(value));
+}
+
+bool QCLuceneField::isBinary() const
+{
+ return d->field->isBinary();
+}
+
+bool QCLuceneField::getOmitNorms() const
+{
+ return d->field->getOmitNorms();
+}
+
+void QCLuceneField::setOmitNorms(bool omitNorms)
+{
+ d->field->setOmitNorms(omitNorms);
+}
+
+QString QCLuceneField::toString() const
+{
+ return TCharToQString(d->field->toString());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qfield_p.h b/tools/assistant/lib/fulltextsearch/qfield_p.h
new file mode 100644
index 0000000000..86b6440ff4
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qfield_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QFIELD_P_H
+#define QFIELD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qclucene_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(document)
+ class Field;
+CL_NS_END
+CL_NS_USE(document)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneReader;
+class QCLuceneDocument;
+
+class QHELP_EXPORT QCLuceneFieldPrivate : public QSharedData
+{
+public:
+ QCLuceneFieldPrivate();
+ QCLuceneFieldPrivate(const QCLuceneFieldPrivate &other);
+
+ ~QCLuceneFieldPrivate();
+
+ Field *field;
+ bool deleteCLuceneField;
+
+private:
+ QCLuceneFieldPrivate &operator=(const QCLuceneFieldPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneField
+{
+public:
+ enum Store {
+ STORE_YES = 1,
+ STORE_NO = 2,
+ STORE_COMPRESS = 4
+ };
+
+ enum Index {
+ INDEX_NO = 16,
+ INDEX_TOKENIZED = 32,
+ INDEX_UNTOKENIZED = 64,
+ INDEX_NONORMS = 128
+ };
+
+ enum TermVector {
+ TERMVECTOR_NO = 256,
+ TERMVECTOR_YES = 512,
+ TERMVECTOR_WITH_POSITIONS = 1024,
+ TERMVECTOR_WITH_OFFSETS = 2048
+ };
+
+ QCLuceneField(const QString &name, const QString &value, int configs);
+ QCLuceneField(const QString &name, QCLuceneReader *reader, int configs);
+ ~QCLuceneField();
+
+ QString name() const;
+ QString stringValue() const;
+ QCLuceneReader* readerValue() const;
+ bool isStored() const;
+ bool isIndexed() const;
+ bool isTokenized() const;
+ bool isCompressed() const;
+ void setConfig(int termVector);
+ bool isTermVectorStored() const;
+ bool isStoreOffsetWithTermVector() const;
+ bool isStorePositionWithTermVector() const;
+ qreal getBoost() const;
+ void setBoost(qreal value);
+ bool isBinary() const;
+ bool getOmitNorms() const;
+ void setOmitNorms(bool omitNorms);
+ QString toString() const;
+
+protected:
+ QCLuceneField();
+ friend class QCLuceneDocument;
+ QSharedDataPointer<QCLuceneFieldPrivate> d;
+
+private:
+ QCLuceneReader* reader;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFIELD_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qfilter.cpp b/tools/assistant/lib/fulltextsearch/qfilter.cpp
new file mode 100644
index 0000000000..24373399fb
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qfilter.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qfilter_p.h"
+
+#include <CLucene.h>
+#include <CLucene/search/Filter.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneFilterPrivate::QCLuceneFilterPrivate()
+ : QSharedData()
+{
+ filter = 0;
+ deleteCLuceneFilter = true;
+}
+
+QCLuceneFilterPrivate::QCLuceneFilterPrivate(const QCLuceneFilterPrivate &other)
+ : QSharedData()
+{
+ filter = _CL_POINTER(other.filter);
+}
+
+QCLuceneFilterPrivate::~QCLuceneFilterPrivate ()
+{
+ if (deleteCLuceneFilter)
+ _CLDECDELETE(filter);
+}
+
+
+QCLuceneFilter::QCLuceneFilter()
+ : d(new QCLuceneFilterPrivate())
+{
+ // nothing todo
+}
+
+QCLuceneFilter::~QCLuceneFilter()
+{
+ // nothing todo
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qfilter_p.h b/tools/assistant/lib/fulltextsearch/qfilter_p.h
new file mode 100644
index 0000000000..fcc0674485
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qfilter_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QFilter_P_H
+#define QFilter_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qclucene_global_p.h"
+
+#include <QtCore/QSharedData>
+#include <QtCore/QSharedDataPointer>
+
+CL_NS_DEF(search)
+ class Filter;
+CL_NS_END
+CL_NS_USE(search)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneHits;
+class QCLuceneSearcher;
+
+class QHELP_EXPORT QCLuceneFilterPrivate : public QSharedData
+{
+public:
+ QCLuceneFilterPrivate();
+ QCLuceneFilterPrivate(const QCLuceneFilterPrivate &other);
+
+ ~QCLuceneFilterPrivate ();
+
+ Filter *filter;
+ bool deleteCLuceneFilter;
+
+private:
+ QCLuceneFilterPrivate &operator=(const QCLuceneFilterPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneFilter
+{
+ QCLuceneFilter();
+ virtual ~QCLuceneFilter();
+
+protected:
+ friend class QCLuceneHits;
+ friend class QCLuceneSearcher;
+ QSharedDataPointer<QCLuceneFilterPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFilter_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qhits.cpp b/tools/assistant/lib/fulltextsearch/qhits.cpp
new file mode 100644
index 0000000000..b3dbea7b67
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qhits.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qhits_p.h"
+#include "qsearchable_p.h"
+
+#include <CLucene.h>
+#include <CLucene/search/SearchHeader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneHitsPrivate::QCLuceneHitsPrivate()
+ : QSharedData()
+{
+ hits = 0;
+ deleteCLuceneHits = true;
+}
+
+QCLuceneHitsPrivate::QCLuceneHitsPrivate(const QCLuceneHitsPrivate &other)
+ : QSharedData()
+{
+ hits = _CL_POINTER(other.hits);
+}
+
+QCLuceneHitsPrivate::~QCLuceneHitsPrivate()
+{
+ if (deleteCLuceneHits)
+ _CLDECDELETE(hits);
+}
+
+
+QCLuceneHits::QCLuceneHits(const QCLuceneSearcher &searcher,
+ const QCLuceneQuery &query, const QCLuceneFilter &filter)
+ : d(new QCLuceneHitsPrivate())
+{
+ d->hits = new lucene::search::Hits(searcher.d->searchable, query.d->query,
+ filter.d->filter);
+}
+
+QCLuceneHits::QCLuceneHits(const QCLuceneSearcher &searcher, const QCLuceneQuery &query,
+ const QCLuceneFilter &filter, const QCLuceneSort &sort)
+ : d(new QCLuceneHitsPrivate())
+{
+ d->hits = new lucene::search::Hits(searcher.d->searchable, query.d->query,
+ filter.d->filter, sort.d->sort);
+}
+
+QCLuceneHits::~QCLuceneHits()
+{
+ // nothing todo
+}
+
+QCLuceneDocument QCLuceneHits::document(const qint32 index)
+{
+ // TODO: check this
+ QCLuceneDocument document;
+ document.d->deleteCLuceneDocument = false;
+ lucene::document::Document &doc = d->hits->doc(int32_t(index));
+ document.d->document = &doc;
+
+ return document;
+}
+
+qint32 QCLuceneHits::length() const
+{
+ return qint32(d->hits->length());
+}
+
+qint32 QCLuceneHits::id(const qint32 index)
+{
+ return qint32(d->hits->id(int32_t(index)));
+}
+
+qreal QCLuceneHits::score(const qint32 index)
+{
+ return qreal(d->hits->score(int32_t(index)));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qhits_p.h b/tools/assistant/lib/fulltextsearch/qhits_p.h
new file mode 100644
index 0000000000..fb6666b22e
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qhits_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QHITS_P_H
+#define QHITS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsort_p.h"
+#include "qquery_p.h"
+#include "qfilter_p.h"
+#include "qdocument_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(search)
+ class Hits;
+CL_NS_END
+CL_NS_USE(search)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneSearcher;
+
+class QHELP_EXPORT QCLuceneHitsPrivate : public QSharedData
+{
+public:
+ QCLuceneHitsPrivate();
+ QCLuceneHitsPrivate(const QCLuceneHitsPrivate &other);
+
+ ~QCLuceneHitsPrivate();
+
+ Hits *hits;
+ bool deleteCLuceneHits;
+
+private:
+ QCLuceneHitsPrivate &operator=(const QCLuceneHitsPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneHits
+{
+public:
+ QCLuceneHits(const QCLuceneSearcher &searcher, const QCLuceneQuery &query,
+ const QCLuceneFilter &filter);
+ QCLuceneHits(const QCLuceneSearcher &searcher, const QCLuceneQuery &query,
+ const QCLuceneFilter &filter, const QCLuceneSort &sort);
+ virtual ~QCLuceneHits();
+
+ QCLuceneDocument document(const qint32 index);
+ qint32 length() const;
+ qint32 id (const qint32 index);
+ qreal score(const qint32 index);
+
+protected:
+ friend class QCLuceneSearcher;
+ QSharedDataPointer<QCLuceneHitsPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QHITS_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qindexreader.cpp b/tools/assistant/lib/fulltextsearch/qindexreader.cpp
new file mode 100644
index 0000000000..5f967cce68
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qindexreader.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qindexreader_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/index/IndexReader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneIndexReaderPrivate::QCLuceneIndexReaderPrivate()
+ : QSharedData()
+{
+ reader = 0;
+ deleteCLuceneIndexReader = true;
+}
+
+QCLuceneIndexReaderPrivate::QCLuceneIndexReaderPrivate(const QCLuceneIndexReaderPrivate &other)
+ : QSharedData()
+{
+ reader = _CL_POINTER(other.reader);
+}
+
+QCLuceneIndexReaderPrivate::~QCLuceneIndexReaderPrivate()
+{
+ if (deleteCLuceneIndexReader)
+ _CLDECDELETE(reader);
+}
+
+
+QCLuceneIndexReader::QCLuceneIndexReader()
+ : d(new QCLuceneIndexReaderPrivate())
+{
+ // nothing todo, private
+}
+
+QCLuceneIndexReader::~QCLuceneIndexReader()
+{
+ // nothing todo
+}
+
+bool QCLuceneIndexReader::isLuceneFile(const QString &filename)
+{
+ using namespace lucene::index;
+
+ return IndexReader::isLuceneFile(filename);
+}
+
+bool QCLuceneIndexReader::indexExists(const QString &directory)
+{
+ using namespace lucene::index;
+ return IndexReader::indexExists(directory);
+}
+
+QCLuceneIndexReader QCLuceneIndexReader::open(const QString &path)
+{
+ using namespace lucene::index;
+
+ QCLuceneIndexReader indexReader;
+ indexReader.d->reader = IndexReader::open(path);
+
+ return indexReader;
+}
+
+void QCLuceneIndexReader::unlock(const QString &path)
+{
+ using namespace lucene::index;
+ IndexReader::unlock(path);
+}
+
+bool QCLuceneIndexReader::isLocked(const QString &directory)
+{
+ using namespace lucene::index;
+ return IndexReader::isLocked(directory);
+}
+
+quint64 QCLuceneIndexReader::lastModified(const QString &directory)
+{
+ using namespace lucene::index;
+ return quint64(IndexReader::lastModified(directory));
+}
+
+qint64 QCLuceneIndexReader::getCurrentVersion(const QString &directory)
+{
+ using namespace lucene::index;
+ return qint64(IndexReader::getCurrentVersion(directory));
+}
+
+void QCLuceneIndexReader::close()
+{
+ d->reader->close();
+}
+
+bool QCLuceneIndexReader::isCurrent()
+{
+ return d->reader->isCurrent();
+}
+
+void QCLuceneIndexReader::undeleteAll()
+{
+ d->reader->undeleteAll();
+}
+
+qint64 QCLuceneIndexReader::getVersion()
+{
+ return qint64(d->reader->getVersion());
+}
+
+void QCLuceneIndexReader::deleteDocument(qint32 docNum)
+{
+ d->reader->deleteDocument(int32_t(docNum));
+}
+
+bool QCLuceneIndexReader::hasNorms(const QString &field)
+{
+ TCHAR *fieldName = QStringToTChar(field);
+ bool retValue = d->reader->hasNorms(fieldName);
+ delete [] fieldName;
+
+ return retValue;
+}
+
+qint32 QCLuceneIndexReader::deleteDocuments(const QCLuceneTerm &term)
+{
+ return d->reader->deleteDocuments(term.d->term);
+}
+
+bool QCLuceneIndexReader::document(qint32 index, QCLuceneDocument &document)
+{
+ if (!document.d->document)
+ document.d->document = new lucene::document::Document();
+
+ if (d->reader->document(int32_t(index), document.d->document))
+ return true;
+
+ return false;
+}
+
+void QCLuceneIndexReader::setNorm(qint32 doc, const QString &field, qreal value)
+{
+ TCHAR *fieldName = QStringToTChar(field);
+ d->reader->setNorm(int32_t(doc), fieldName, qreal(value));
+ delete [] fieldName;
+}
+
+void QCLuceneIndexReader::setNorm(qint32 doc, const QString &field, quint8 value)
+{
+ TCHAR *fieldName = QStringToTChar(field);
+ d->reader->setNorm(int32_t(doc), fieldName, uint8_t(value));
+ delete [] fieldName;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qindexreader_p.h b/tools/assistant/lib/fulltextsearch/qindexreader_p.h
new file mode 100644
index 0000000000..4a7330def3
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qindexreader_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QINDEXREADER_P_H
+#define QINDEXREADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qterm_p.h"
+#include "qdocument_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(index)
+ class IndexReader;
+CL_NS_END
+CL_NS_USE(index)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneIndexWriter;
+class QCLuceneIndexSearcher;
+
+class QHELP_EXPORT QCLuceneIndexReaderPrivate : public QSharedData
+{
+public:
+ QCLuceneIndexReaderPrivate();
+ QCLuceneIndexReaderPrivate(const QCLuceneIndexReaderPrivate &other);
+
+ ~QCLuceneIndexReaderPrivate();
+
+ IndexReader *reader;
+ bool deleteCLuceneIndexReader;
+
+private:
+ QCLuceneIndexReaderPrivate &operator=(const QCLuceneIndexReaderPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneIndexReader
+{
+public:
+ enum FieldOption {
+ ALL = 1,
+ INDEXED = 2,
+ UNINDEXED = 4,
+ INDEXED_WITH_TERMVECTOR = 8,
+ INDEXED_NO_TERMVECTOR = 16,
+ TERMVECTOR = 32,
+ TERMVECTOR_WITH_POSITION = 64,
+ TERMVECTOR_WITH_OFFSET = 128,
+ TERMVECTOR_WITH_POSITION_OFFSET = 256
+ };
+
+ virtual ~QCLuceneIndexReader();
+
+ static bool isLuceneFile(const QString &filename);
+ static bool indexExists(const QString &directory);
+ static QCLuceneIndexReader open(const QString &path);
+
+ static void unlock(const QString &path);
+ static bool isLocked(const QString &directory);
+
+ static quint64 lastModified(const QString &directory);
+ static qint64 getCurrentVersion(const QString &directory);
+
+ void close();
+ bool isCurrent();
+ void undeleteAll();
+ qint64 getVersion();
+ void deleteDocument(qint32 docNum);
+ bool hasNorms(const QString &field);
+ qint32 deleteDocuments(const QCLuceneTerm &term);
+ bool document(qint32 index, QCLuceneDocument &document);
+ void setNorm(qint32 doc, const QString &field, qreal value);
+ void setNorm(qint32 doc, const QString &field, quint8 value);
+
+protected:
+ friend class QCLuceneIndexWriter;
+ friend class QCLuceneIndexSearcher;
+ QSharedDataPointer<QCLuceneIndexReaderPrivate> d;
+
+private:
+ QCLuceneIndexReader();
+};
+
+QT_END_NAMESPACE
+
+#endif // QINDEXREADER_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qindexwriter.cpp b/tools/assistant/lib/fulltextsearch/qindexwriter.cpp
new file mode 100644
index 0000000000..890cc67c8d
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qindexwriter.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qindexwriter_p.h"
+#include "qindexreader_p.h"
+
+#include <CLucene.h>
+#include <CLucene/index/IndexWriter.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneIndexWriterPrivate::QCLuceneIndexWriterPrivate()
+ : QSharedData()
+{
+ writer = 0;
+ deleteCLuceneIndexWriter = true;
+}
+
+QCLuceneIndexWriterPrivate::QCLuceneIndexWriterPrivate(const QCLuceneIndexWriterPrivate &other)
+ : QSharedData()
+{
+ writer = _CL_POINTER(other.writer);
+}
+
+QCLuceneIndexWriterPrivate::~QCLuceneIndexWriterPrivate()
+{
+ if (deleteCLuceneIndexWriter)
+ _CLDECDELETE(writer);
+}
+
+
+QCLuceneIndexWriter::QCLuceneIndexWriter(const QString &path,
+ QCLuceneAnalyzer &analyzer,
+ bool create, bool closeDir)
+ : d(new QCLuceneIndexWriterPrivate())
+ , analyzer(analyzer)
+{
+ d->writer = new lucene::index::IndexWriter(path,
+ analyzer.d->analyzer, create, closeDir);
+}
+
+QCLuceneIndexWriter::~QCLuceneIndexWriter()
+{
+ // nothing todo
+}
+
+void QCLuceneIndexWriter::close()
+{
+ d->writer->close();
+}
+
+void QCLuceneIndexWriter::optimize()
+{
+ d->writer->optimize();
+}
+
+qint32 QCLuceneIndexWriter::docCount()
+{
+ return qint32(d->writer->docCount());
+}
+
+QCLuceneAnalyzer QCLuceneIndexWriter::getAnalyzer()
+{
+ return analyzer;
+}
+
+void QCLuceneIndexWriter::addIndexes(const QList<QCLuceneIndexReader*> &readers)
+{
+ using namespace lucene::index;
+ IndexReader** readerArray = new IndexReader*[readers.count()];
+
+ for (int i = 0; i < readers.count(); ++i)
+ readerArray[i] = (readers.at(i))->d->reader;
+
+ d->writer->addIndexes(readerArray);
+ delete readerArray;
+}
+
+void QCLuceneIndexWriter::addDocument(QCLuceneDocument &doc,
+ QCLuceneAnalyzer &analyzer)
+{
+ if (doc.d->document)
+ d->writer->addDocument(doc.d->document, analyzer.d->analyzer);
+}
+
+qint32 QCLuceneIndexWriter::getMaxFieldLength() const
+{
+ return qint32(d->writer->getMaxFieldLength());
+}
+
+void QCLuceneIndexWriter::setMaxFieldLength(qint32 value)
+{
+ d->writer->setMaxFieldLength(int32_t(value));
+}
+
+qint32 QCLuceneIndexWriter::getMaxBufferedDocs() const
+{
+ return qint32(d->writer->getMaxBufferedDocs());
+}
+
+void QCLuceneIndexWriter::setMaxBufferedDocs(qint32 value)
+{
+ d->writer->setMaxBufferedDocs(int32_t(value));
+}
+
+qint64 QCLuceneIndexWriter::getWriteLockTimeout() const
+{
+ return qint64(d->writer->getWriteLockTimeout());
+}
+
+void QCLuceneIndexWriter::setWriteLockTimeout(qint64 writeLockTimeout)
+{
+ d->writer->setWriteLockTimeout(int64_t(writeLockTimeout));
+}
+
+qint64 QCLuceneIndexWriter::getCommitLockTimeout() const
+{
+ return qint64(d->writer->getCommitLockTimeout());
+}
+
+void QCLuceneIndexWriter::setCommitLockTimeout(qint64 commitLockTimeout)
+{
+ d->writer->setCommitLockTimeout(int64_t(commitLockTimeout));
+}
+
+qint32 QCLuceneIndexWriter::getMergeFactor() const
+{
+ return qint32(d->writer->getMergeFactor());
+}
+
+void QCLuceneIndexWriter::setMergeFactor(qint32 value)
+{
+ d->writer->setMergeFactor(int32_t(value));
+}
+
+qint32 QCLuceneIndexWriter::getTermIndexInterval() const
+{
+ return qint32(d->writer->getTermIndexInterval());
+}
+
+void QCLuceneIndexWriter::setTermIndexInterval(qint32 interval)
+{
+ d->writer->setTermIndexInterval(int32_t(interval));
+}
+
+qint32 QCLuceneIndexWriter::getMinMergeDocs() const
+{
+ return qint32(d->writer->getMinMergeDocs());
+}
+
+void QCLuceneIndexWriter::setMinMergeDocs(qint32 value)
+{
+ d->writer->setMinMergeDocs(int32_t(value));
+}
+
+qint32 QCLuceneIndexWriter::getMaxMergeDocs() const
+{
+ return qint32(d->writer->getMaxMergeDocs());
+}
+
+void QCLuceneIndexWriter::setMaxMergeDocs(qint32 value)
+{
+ d->writer->setMaxMergeDocs(int32_t(value));
+}
+
+bool QCLuceneIndexWriter::getUseCompoundFile() const
+{
+ return d->writer->getUseCompoundFile();
+}
+
+void QCLuceneIndexWriter::setUseCompoundFile(bool value)
+{
+ d->writer->setUseCompoundFile(value);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qindexwriter_p.h b/tools/assistant/lib/fulltextsearch/qindexwriter_p.h
new file mode 100644
index 0000000000..e793494d95
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qindexwriter_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QINDEXWRITER_P_H
+#define QINDEXWRITER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qanalyzer_p.h"
+#include "qdocument_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(index)
+ class IndexWriter;
+CL_NS_END
+CL_NS_USE(index)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneIndexReader;
+
+class QHELP_EXPORT QCLuceneIndexWriterPrivate : public QSharedData
+{
+public:
+ QCLuceneIndexWriterPrivate();
+ QCLuceneIndexWriterPrivate(const QCLuceneIndexWriterPrivate &other);
+
+ ~QCLuceneIndexWriterPrivate();
+
+ IndexWriter *writer;
+ bool deleteCLuceneIndexWriter;
+
+private:
+ QCLuceneIndexWriterPrivate &operator=(const QCLuceneIndexWriterPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneIndexWriter
+{
+public:
+ enum {
+ DEFAULT_MERGE_FACTOR = 10,
+ COMMIT_LOCK_TIMEOUT = 10000,
+ DEFAULT_MAX_BUFFERED_DOCS = 10,
+ DEFAULT_MAX_FIELD_LENGTH = 10000,
+ DEFAULT_TERM_INDEX_INTERVAL = 128,
+ DEFAULT_MAX_MERGE_DOCS = 0x7FFFFFFFL
+ };
+
+ QCLuceneIndexWriter(const QString &path, QCLuceneAnalyzer &analyzer,
+ bool create, bool closeDir = true);
+ virtual ~QCLuceneIndexWriter();
+
+ void close();
+ void optimize();
+ qint32 docCount();
+ QCLuceneAnalyzer getAnalyzer();
+
+ void addIndexes(const QList<QCLuceneIndexReader*> &readers);
+ void addDocument(QCLuceneDocument &doc, QCLuceneAnalyzer &analyzer);
+
+ qint32 getMaxFieldLength() const;
+ void setMaxFieldLength(qint32 value);
+
+ qint32 getMaxBufferedDocs() const;
+ void setMaxBufferedDocs(qint32 value);
+
+ qint64 getWriteLockTimeout() const;
+ void setWriteLockTimeout(qint64 writeLockTimeout);
+
+ qint64 getCommitLockTimeout() const;
+ void setCommitLockTimeout(qint64 commitLockTimeout);
+
+ qint32 getMergeFactor() const;
+ void setMergeFactor(qint32 value);
+
+ qint32 getTermIndexInterval() const;
+ void setTermIndexInterval(qint32 interval);
+
+ qint32 getMinMergeDocs() const;
+ void setMinMergeDocs(qint32 value);
+
+ qint32 getMaxMergeDocs() const;
+ void setMaxMergeDocs(qint32 value);
+
+ bool getUseCompoundFile() const;
+ void setUseCompoundFile(bool value);
+
+protected:
+ QSharedDataPointer<QCLuceneIndexWriterPrivate> d;
+
+private:
+ QCLuceneAnalyzer analyzer;
+};
+
+QT_END_NAMESPACE
+
+#endif // QINDEXWRITER_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qquery.cpp b/tools/assistant/lib/fulltextsearch/qquery.cpp
new file mode 100644
index 0000000000..2210220978
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qquery.cpp
@@ -0,0 +1,350 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qquery_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/search/PhraseQuery.h>
+#include <CLucene/search/SearchHeader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneQueryPrivate::QCLuceneQueryPrivate()
+ : QSharedData()
+{
+ query = 0;
+ deleteCLuceneQuery = true;
+}
+
+QCLuceneQueryPrivate::QCLuceneQueryPrivate(const QCLuceneQueryPrivate &other)
+ : QSharedData()
+{
+ query = _CL_POINTER(other.query);
+}
+
+QCLuceneQueryPrivate::~QCLuceneQueryPrivate()
+{
+ if (deleteCLuceneQuery)
+ _CLDECDELETE(query);
+}
+
+
+QCLuceneQuery::QCLuceneQuery()
+ : d(new QCLuceneQueryPrivate())
+{
+ // nothing todo, private
+}
+
+QCLuceneQuery::~QCLuceneQuery()
+{
+ // nothing todo
+}
+
+void QCLuceneQuery::setBoost(qreal boost)
+{
+ d->query->setBoost(qreal(boost));
+}
+
+qreal QCLuceneQuery::getBoost() const
+{
+ return qreal(d->query->getBoost());
+}
+
+QString QCLuceneQuery::getQueryName() const
+{
+ return TCharToQString(d->query->getQueryName());
+}
+
+bool QCLuceneQuery::instanceOf(const QString &other) const
+{
+ if (other == getQueryName())
+ return true;
+
+ return false;
+}
+
+QString QCLuceneQuery::toString(const QString &field) const
+{
+ TCHAR *fieldName = QStringToTChar(field);
+ QString retValue = TCharToQString(d->query->toString(fieldName));
+ delete [] fieldName;
+
+ return retValue;
+}
+
+quint32 QCLuceneQuery::hashCode() const
+{
+ return quint32(d->query->hashCode());
+}
+
+QString QCLuceneQuery::toString() const
+{
+ return TCharToQString(d->query->toString());
+}
+
+bool QCLuceneQuery::equals(const QCLuceneQuery &other) const
+{
+ return d->query->equals(other.d->query);
+}
+
+
+QCLucenePrefixQuery::QCLucenePrefixQuery(const QCLuceneTerm &prefix)
+ : QCLuceneQuery()
+ , prefix(prefix)
+{
+ d->query = new lucene::search::PrefixQuery(prefix.d->term);
+}
+
+QCLucenePrefixQuery::~QCLucenePrefixQuery()
+{
+ // nothing todo
+}
+
+QString QCLucenePrefixQuery::getClassName()
+{
+ return TCharToQString(lucene::search::PrefixQuery::getClassName());
+}
+
+QCLuceneTerm QCLucenePrefixQuery::getPrefix() const
+{
+ return prefix;
+}
+
+
+QCLuceneRangeQuery::QCLuceneRangeQuery(const QCLuceneTerm &lowerTerm,
+ const QCLuceneTerm &upperTerm,
+ bool inclusive)
+ : QCLuceneQuery()
+ , lowerTerm(lowerTerm)
+ , upperTerm(upperTerm)
+{
+ d->query = new lucene::search::RangeQuery(lowerTerm.d->term,
+ upperTerm.d->term, inclusive);
+}
+
+QCLuceneRangeQuery::~QCLuceneRangeQuery()
+{
+ // nothing todo
+}
+
+QString QCLuceneRangeQuery::getClassName()
+{
+ return TCharToQString(lucene::search::RangeQuery::getClassName());
+}
+
+QCLuceneTerm QCLuceneRangeQuery::getLowerTerm() const
+{
+ return lowerTerm;
+}
+
+QCLuceneTerm QCLuceneRangeQuery::getUpperTerm() const
+{
+ return upperTerm;
+}
+
+bool QCLuceneRangeQuery::isInclusive() const
+{
+ lucene::search::RangeQuery *query =
+ static_cast<lucene::search::RangeQuery*> (d->query);
+
+ if (query == 0)
+ return false;
+
+ return query->isInclusive();
+}
+
+QString QCLuceneRangeQuery::getField() const
+{
+ lucene::search::RangeQuery *query =
+ static_cast<lucene::search::RangeQuery*> (d->query);
+
+ if (query == 0)
+ return QString();
+
+ return TCharToQString(query->getField());
+}
+
+
+QCLuceneTermQuery::QCLuceneTermQuery(const QCLuceneTerm &term)
+ : QCLuceneQuery()
+ , term(term)
+{
+ d->query = new lucene::search::TermQuery(term.d->term);
+}
+
+QCLuceneTermQuery::~QCLuceneTermQuery()
+{
+ // nothing todo
+}
+
+QString QCLuceneTermQuery::getClassName()
+{
+ return TCharToQString(lucene::search::TermQuery::getClassName());
+}
+
+QCLuceneTerm QCLuceneTermQuery::getTerm() const
+{
+ return term;
+}
+
+
+QCLuceneBooleanQuery::QCLuceneBooleanQuery()
+ : QCLuceneQuery()
+{
+ d->query = new lucene::search::BooleanQuery();
+}
+
+QCLuceneBooleanQuery::~QCLuceneBooleanQuery()
+{
+ qDeleteAll(queries);
+}
+
+QString QCLuceneBooleanQuery::getClassName()
+{
+ return TCharToQString(lucene::search::BooleanQuery::getClassName());
+}
+
+quint32 QCLuceneBooleanQuery::getClauseCount() const
+{
+ lucene::search::BooleanQuery *query =
+ static_cast<lucene::search::BooleanQuery*> (d->query);
+
+ if (query == 0)
+ return 1024;
+
+ return quint32(query->getClauseCount());
+}
+
+quint32 QCLuceneBooleanQuery::getMaxClauseCount() const
+{
+ lucene::search::BooleanQuery *query =
+ static_cast<lucene::search::BooleanQuery*> (d->query);
+
+ if (query == 0)
+ return 1024;
+
+ return quint32(query->getMaxClauseCount());
+}
+
+void QCLuceneBooleanQuery::setMaxClauseCount(quint32 maxClauseCount)
+{
+ lucene::search::BooleanQuery *query =
+ static_cast<lucene::search::BooleanQuery*> (d->query);
+
+ if (query == 0)
+ return;
+
+ query->setMaxClauseCount(size_t(maxClauseCount));
+}
+
+void QCLuceneBooleanQuery::add(QCLuceneQuery *query, bool required, bool prohibited)
+{
+ add(query, false, required, prohibited);
+}
+
+void QCLuceneBooleanQuery::add(QCLuceneQuery *query, bool delQuery,
+ bool required, bool prohibited)
+{
+ lucene::search::BooleanQuery *booleanQuery =
+ static_cast<lucene::search::BooleanQuery*> (d->query);
+
+ if (booleanQuery == 0)
+ return;
+
+ booleanQuery->add(query->d->query, delQuery, required, prohibited);
+
+ if (delQuery) {
+ queries.append(query);
+ query->d->deleteCLuceneQuery = false;
+ }
+}
+
+
+QCLucenePhraseQuery::QCLucenePhraseQuery()
+ : QCLuceneQuery()
+{
+ d->query = new lucene::search::PhraseQuery();
+}
+
+QCLucenePhraseQuery::~QCLucenePhraseQuery()
+{
+ termList.clear();
+}
+
+QString QCLucenePhraseQuery::getClassName()
+{
+ return TCharToQString(lucene::search::RangeQuery::getClassName());
+}
+
+qint32 QCLucenePhraseQuery::getSlop() const
+{
+ lucene::search::PhraseQuery *phraseQuery =
+ static_cast<lucene::search::PhraseQuery*> (d->query);
+
+ if (phraseQuery == 0)
+ return 0;
+
+ return qint32(phraseQuery->getSlop());
+}
+
+void QCLucenePhraseQuery::setSlop(const qint32 slop)
+{
+ lucene::search::PhraseQuery *phraseQuery =
+ static_cast<lucene::search::PhraseQuery*> (d->query);
+
+ if (phraseQuery == 0)
+ return;
+
+ phraseQuery->setSlop(int32_t(slop));
+}
+
+void QCLucenePhraseQuery::addTerm(const QCLuceneTerm &term)
+{
+ lucene::search::PhraseQuery *phraseQuery =
+ static_cast<lucene::search::PhraseQuery*> (d->query);
+
+ if (phraseQuery == 0)
+ return;
+
+ termList.append(term);
+ phraseQuery->add(term.d->term);
+}
+
+void QCLucenePhraseQuery::addTerm(const QCLuceneTerm &term, qint32 position)
+{
+ lucene::search::PhraseQuery *phraseQuery =
+ static_cast<lucene::search::PhraseQuery*> (d->query);
+
+ if (phraseQuery == 0)
+ return;
+
+ termList.insert(position, term);
+ phraseQuery->add(term.d->term, int32_t(position));
+
+}
+
+QString QCLucenePhraseQuery::getFieldName() const
+{
+ lucene::search::PhraseQuery *phraseQuery =
+ static_cast<lucene::search::PhraseQuery*> (d->query);
+
+ if (phraseQuery == 0)
+ return QString();
+
+ return TCharToQString(phraseQuery->getFieldName());
+}
+
+QList<QCLuceneTerm> QCLucenePhraseQuery::getTerms() const
+{
+ return termList;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qquery_p.h b/tools/assistant/lib/fulltextsearch/qquery_p.h
new file mode 100644
index 0000000000..42eaf07b0d
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qquery_p.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QQUERY_P_H
+#define QQUERY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qterm_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(search)
+ class Query;
+CL_NS_END
+CL_NS_USE(search)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneHits;
+class QCLuceneTermQuery;
+class QCLuceneRangeQuery;
+class QCLuceneQueryParser;
+class QCLucenePrefixQuery;
+class QCLuceneBooleanQuery;
+class QCLucenePhraseQuery;
+
+class QHELP_EXPORT QCLuceneQueryPrivate : public QSharedData
+{
+public:
+ QCLuceneQueryPrivate();
+ QCLuceneQueryPrivate(const QCLuceneQueryPrivate &other);
+
+ ~QCLuceneQueryPrivate();
+
+ Query *query;
+ bool deleteCLuceneQuery;
+
+private:
+ QCLuceneQueryPrivate &operator=(const QCLuceneQueryPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneQuery
+{
+public:
+ virtual ~QCLuceneQuery();
+
+ void setBoost(qreal boost);
+ qreal getBoost() const;
+ QString getQueryName() const;
+ bool instanceOf(const QString &other) const;
+ QString toString(const QString &field) const;
+ quint32 hashCode() const;
+ QString toString() const;
+ bool equals(const QCLuceneQuery &other) const;
+
+protected:
+ friend class QCLuceneHits;
+ friend class QCLuceneTermQuery;
+ friend class QCLuceneRangeQuery;
+ friend class QCLucenePrefixQuery;
+ friend class QCLuceneQueryParser;
+ friend class QCLuceneBooleanQuery;
+ friend class QCLucenePhraseQuery;
+ QSharedDataPointer<QCLuceneQueryPrivate> d;
+
+private:
+ QCLuceneQuery();
+};
+
+class QHELP_EXPORT QCLucenePrefixQuery : public QCLuceneQuery
+{
+public:
+ QCLucenePrefixQuery(const QCLuceneTerm &prefix);
+ ~QCLucenePrefixQuery();
+
+ static QString getClassName();
+
+ QCLuceneTerm getPrefix() const;
+
+private:
+ QCLuceneTerm prefix;
+};
+
+class QHELP_EXPORT QCLuceneRangeQuery : public QCLuceneQuery
+{
+public:
+ QCLuceneRangeQuery(const QCLuceneTerm &lowerTerm,
+ const QCLuceneTerm &upperTerm, bool inclusive);
+ ~QCLuceneRangeQuery();
+
+ static QString getClassName();
+
+ QCLuceneTerm getLowerTerm() const;
+ QCLuceneTerm getUpperTerm() const;
+
+ bool isInclusive() const;
+ QString getField() const;
+
+private:
+ QCLuceneTerm lowerTerm;
+ QCLuceneTerm upperTerm;
+};
+
+class QHELP_EXPORT QCLuceneTermQuery : public QCLuceneQuery
+{
+public:
+ QCLuceneTermQuery(const QCLuceneTerm &term);
+ ~QCLuceneTermQuery();
+
+ static QString getClassName();
+
+ QCLuceneTerm getTerm() const;
+
+private:
+ QCLuceneTerm term;
+};
+
+class QHELP_EXPORT QCLuceneBooleanQuery : public QCLuceneQuery
+{
+public:
+ QCLuceneBooleanQuery();
+ ~QCLuceneBooleanQuery();
+
+ static QString getClassName();
+
+ quint32 getClauseCount() const;
+ quint32 getMaxClauseCount() const;
+ void setMaxClauseCount(quint32 maxClauseCount);
+
+ void add(QCLuceneQuery *query, bool required, bool prohibited);
+ void add(QCLuceneQuery *query, bool delQuery, bool required, bool prohibited);
+
+private:
+ QList<QCLuceneQuery*> queries;
+};
+
+class QHELP_EXPORT QCLucenePhraseQuery : public QCLuceneQuery
+{
+public:
+ QCLucenePhraseQuery();
+ ~QCLucenePhraseQuery();
+
+ static QString getClassName();
+
+ qint32 getSlop() const;
+ void setSlop(const qint32 slop);
+
+ void addTerm(const QCLuceneTerm &term);
+ void addTerm(const QCLuceneTerm &term, qint32 position);
+
+ QString getFieldName() const;
+ QList<QCLuceneTerm> getTerms() const;
+
+private:
+ QList<QCLuceneTerm> termList;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUERY_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qqueryparser.cpp b/tools/assistant/lib/fulltextsearch/qqueryparser.cpp
new file mode 100644
index 0000000000..ce1b512454
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qqueryparser.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qqueryparser_p.h"
+#include "qquery_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/queryParser/QueryParser.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneQueryParserPrivate::QCLuceneQueryParserPrivate()
+ : QSharedData()
+{
+ queryParser = 0;
+ deleteCLuceneQueryParser = true;
+}
+
+QCLuceneQueryParserPrivate::QCLuceneQueryParserPrivate(const QCLuceneQueryParserPrivate &other)
+ : QSharedData()
+{
+ queryParser = _CL_POINTER(other.queryParser);
+}
+
+QCLuceneQueryParserPrivate::~QCLuceneQueryParserPrivate()
+{
+ if (deleteCLuceneQueryParser)
+ _CLDECDELETE(queryParser);
+}
+
+
+QCLuceneQueryParser::QCLuceneQueryParser(const QString &field,
+ QCLuceneAnalyzer &analyzer)
+ : d(new QCLuceneQueryParserPrivate())
+ , field(field)
+ , analyzer(analyzer)
+{
+ TCHAR *fieldName = QStringToTChar(field);
+
+ d->queryParser = new lucene::queryParser::QueryParser(fieldName,
+ analyzer.d->analyzer);
+
+ delete [] fieldName;
+}
+
+QCLuceneQueryParser::~QCLuceneQueryParser()
+{
+ // nothing todo
+}
+
+QCLuceneQuery* QCLuceneQueryParser::parse(const QString &query)
+{
+ TCHAR *string = QStringToTChar(query);
+
+ QCLuceneQuery *retValue = 0;
+ lucene::search::Query* q = d->queryParser->parse(string);
+ if (q) {
+ retValue = new QCLuceneQuery();
+ retValue->d->query = q;
+ }
+
+ delete [] string;
+ return retValue;
+}
+
+QCLuceneQuery* QCLuceneQueryParser::parse(QCLuceneReader &reader)
+{
+ QCLuceneQuery *retValue = 0;
+ lucene::search::Query* q = d->queryParser->parse(reader.d->reader);
+ if (q) {
+ retValue = new QCLuceneQuery();
+ retValue->d->query = q;
+ }
+
+ return retValue;
+}
+
+QCLuceneQuery* QCLuceneQueryParser::parse(const QString &query, const QString &field,
+ QCLuceneAnalyzer &analyzer)
+{
+ QCLuceneQueryParser parser(field, analyzer);
+ return parser.parse(query);
+}
+
+QCLuceneAnalyzer QCLuceneQueryParser::getAnalyzer()
+{
+ return analyzer;
+}
+
+QString QCLuceneQueryParser::getField()
+{
+ return field;
+}
+
+
+QCLuceneMultiFieldQueryParser::QCLuceneMultiFieldQueryParser(
+ const QStringList &fieldList, QCLuceneAnalyzer &analyzer)
+ : QCLuceneQueryParser(QLatin1String(""), analyzer)
+{
+ Q_UNUSED(fieldList)
+}
+
+QCLuceneMultiFieldQueryParser::~QCLuceneMultiFieldQueryParser()
+{
+ // nothing todo
+}
+
+QCLuceneQuery* QCLuceneMultiFieldQueryParser::parse(const QString &query,
+ const QStringList &fieldList,
+ QCLuceneAnalyzer &analyzer)
+{
+ QCLuceneBooleanQuery *retValue = new QCLuceneBooleanQuery();
+ foreach (const QString &field, fieldList) {
+ QCLuceneQuery *q = QCLuceneQueryParser::parse(query, field, analyzer);
+ if (!q) {
+ delete retValue;
+ retValue = 0; break;
+ } else {
+ retValue->add(q, true, false, false);
+ }
+ }
+
+ return retValue;
+}
+
+QCLuceneQuery* QCLuceneMultiFieldQueryParser::parse(const QString &query,
+ const QStringList &fieldList,
+ QList<FieldFlags> flags,
+ QCLuceneAnalyzer &analyzer)
+{
+ QCLuceneBooleanQuery *retValue = new QCLuceneBooleanQuery();
+ qint32 i = 0;
+ foreach (const QString &field, fieldList) {
+ QCLuceneQuery *q = QCLuceneQueryParser::parse(query, field, analyzer);
+ if (q) {
+ qint32 flag = flags.at(i);
+ switch (flag) {
+ case QCLuceneMultiFieldQueryParser::REQUIRED_FIELD: {
+ retValue->add(q, true, true, false);
+ } break;
+
+ case QCLuceneMultiFieldQueryParser::PROHIBITED_FIELD: {
+ retValue->add(q, true, false, true);
+ } break;
+
+ default: {
+ retValue->add(q, true, false, false);
+ } break;
+ }
+
+ ++i;
+ } else {
+ delete retValue;
+ retValue = 0; break;
+ }
+ }
+ return retValue;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qqueryparser_p.h b/tools/assistant/lib/fulltextsearch/qqueryparser_p.h
new file mode 100644
index 0000000000..976ee63b72
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qqueryparser_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QQUERYPARSER_P_H
+#define QQUERYPARSER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qreader_p.h"
+#include "qanalyzer_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(queryParser)
+ class QueryParser;
+CL_NS_END
+CL_NS_USE(queryParser)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneQuery;
+class QCLuceneMultiFieldQueryParser;
+
+class QHELP_EXPORT QCLuceneQueryParserPrivate : public QSharedData
+{
+public:
+ QCLuceneQueryParserPrivate();
+ QCLuceneQueryParserPrivate(const QCLuceneQueryParserPrivate &other);
+
+ ~QCLuceneQueryParserPrivate();
+
+ QueryParser *queryParser;
+ bool deleteCLuceneQueryParser;
+
+private:
+ QCLuceneQueryParserPrivate &operator=(const QCLuceneQueryParserPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneQueryParser
+{
+public:
+ QCLuceneQueryParser(const QString &field, QCLuceneAnalyzer &analyzer);
+ virtual ~QCLuceneQueryParser();
+
+ QCLuceneQuery* parse(const QString &query);
+ QCLuceneQuery* parse(QCLuceneReader &reader);
+ static QCLuceneQuery* parse(const QString &query, const QString &field,
+ QCLuceneAnalyzer &analyzer);
+ QCLuceneAnalyzer getAnalyzer();
+ QString getField();
+
+protected:
+ friend class QCLuceneMultiFieldQueryParser;
+ QSharedDataPointer<QCLuceneQueryParserPrivate> d;
+
+private:
+ QString field;
+ QCLuceneAnalyzer analyzer;
+};
+
+class QHELP_EXPORT QCLuceneMultiFieldQueryParser : public QCLuceneQueryParser
+{
+public:
+ enum FieldFlags {
+ NORMAL_FIELD = 0,
+ REQUIRED_FIELD = 1,
+ PROHIBITED_FIELD = 2
+ };
+
+ QCLuceneMultiFieldQueryParser(const QStringList &fieldList,
+ QCLuceneAnalyzer &analyzer);
+ ~QCLuceneMultiFieldQueryParser();
+
+ static QCLuceneQuery *parse(const QString &query, const QStringList &fieldList,
+ QCLuceneAnalyzer &analyzer);
+ static QCLuceneQuery *parse(const QString &query, const QStringList &fieldList,
+ QList<FieldFlags> flags, QCLuceneAnalyzer &analyzer);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUERYPARSER_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qreader.cpp b/tools/assistant/lib/fulltextsearch/qreader.cpp
new file mode 100644
index 0000000000..792056d130
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qreader.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qreader_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/util/Reader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneReaderPrivate::QCLuceneReaderPrivate()
+ : QSharedData()
+{
+ reader = 0;
+ deleteCLuceneReader = true;
+}
+
+QCLuceneReaderPrivate::QCLuceneReaderPrivate(const QCLuceneReaderPrivate &other)
+ : QSharedData()
+{
+ reader = _CL_POINTER(other.reader);
+}
+
+QCLuceneReaderPrivate::~QCLuceneReaderPrivate()
+{
+ if (deleteCLuceneReader)
+ _CLDECDELETE(reader);
+}
+
+
+QCLuceneReader::QCLuceneReader()
+ : d(new QCLuceneReaderPrivate())
+{
+ // nothing todo
+}
+
+QCLuceneReader::~QCLuceneReader()
+{
+ // nothing todo
+}
+
+
+QCLuceneStringReader::QCLuceneStringReader(const QString &value)
+ : QCLuceneReader()
+ , string(QStringToTChar(value))
+{
+ d->reader = new lucene::util::StringReader(string);
+}
+
+QCLuceneStringReader::QCLuceneStringReader(const QString &value, qint32 length)
+ : QCLuceneReader()
+ , string(QStringToTChar(value))
+{
+ d->reader = new lucene::util::StringReader(string, int32_t(length));
+}
+
+QCLuceneStringReader::QCLuceneStringReader(const QString &value, qint32 length,
+ bool copyData)
+ : QCLuceneReader()
+ , string(QStringToTChar(value))
+{
+ d->reader = new lucene::util::StringReader(string, int32_t(length), copyData);
+}
+
+QCLuceneStringReader::~QCLuceneStringReader()
+{
+ delete [] string;
+}
+
+
+QCLuceneFileReader::QCLuceneFileReader(const QString &path, const QString &encoding,
+ qint32 cacheLength, qint32 cacheBuffer)
+ : QCLuceneReader()
+{
+ const QByteArray tmpPath = path.toLocal8Bit();
+ const QByteArray tmpEncoding = encoding.toAscii();
+ d->reader = new lucene::util::FileReader(tmpPath.constData(),
+ tmpEncoding.constData(), int32_t(cacheLength), int32_t(cacheBuffer));
+}
+
+QCLuceneFileReader::~QCLuceneFileReader()
+{
+ // nothing todo
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qreader_p.h b/tools/assistant/lib/fulltextsearch/qreader_p.h
new file mode 100644
index 0000000000..77c80077da
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qreader_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QREADER_P_H
+#define QREADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qclucene_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(util)
+ class Reader;
+CL_NS_END
+CL_NS_USE(util)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneField;
+class QCLuceneAnalyzer;
+class QCLuceneDocument;
+class QCLuceneQueryParser;
+class QCLuceneStandardTokenizer;
+
+class QHELP_EXPORT QCLuceneReaderPrivate : public QSharedData
+{
+public:
+ QCLuceneReaderPrivate();
+ QCLuceneReaderPrivate(const QCLuceneReaderPrivate &other);
+
+ ~QCLuceneReaderPrivate();
+
+ Reader* reader;
+ bool deleteCLuceneReader;
+
+private:
+ QCLuceneReaderPrivate &operator=(const QCLuceneReaderPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneReader
+{
+public:
+ QCLuceneReader();
+ virtual ~QCLuceneReader();
+
+protected:
+ friend class QCLuceneField;
+ friend class QCLuceneAnalyzer;
+ friend class QCLuceneDocument;
+ friend class QCLuceneQueryParser;
+ friend class QCLuceneStandardTokenizer;
+ QSharedDataPointer<QCLuceneReaderPrivate> d;
+};
+
+class QCLuceneStringReader : public QCLuceneReader
+{
+public:
+ QCLuceneStringReader(const QString &value);
+ QCLuceneStringReader(const QString &value, qint32 length);
+ QCLuceneStringReader(const QString &value, qint32 length, bool copyData);
+
+ ~QCLuceneStringReader();
+
+private:
+ TCHAR *string;
+};
+
+class QHELP_EXPORT QCLuceneFileReader : public QCLuceneReader
+{
+public:
+ QCLuceneFileReader(const QString &path, const QString &encoding,
+ qint32 cacheLength = 13, qint32 cacheBuffer = 14);
+ ~QCLuceneFileReader();
+};
+
+QT_END_NAMESPACE
+
+#endif // QREADER_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qsearchable.cpp b/tools/assistant/lib/fulltextsearch/qsearchable.cpp
new file mode 100644
index 0000000000..2d76b02de3
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qsearchable.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qsearchable_p.h"
+
+#include <CLucene.h>
+#include <CLucene/search/SearchHeader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneSearchablePrivate::QCLuceneSearchablePrivate()
+ : QSharedData()
+{
+ searchable = 0;
+ deleteCLuceneSearchable = true;
+}
+
+QCLuceneSearchablePrivate::QCLuceneSearchablePrivate(const QCLuceneSearchablePrivate &other)
+ : QSharedData()
+{
+ searchable = _CL_POINTER(other.searchable);
+}
+
+QCLuceneSearchablePrivate::~QCLuceneSearchablePrivate()
+{
+ if (deleteCLuceneSearchable)
+ _CLDECDELETE(searchable);
+}
+
+
+QCLuceneSearchable::QCLuceneSearchable()
+ : d(new QCLuceneSearchablePrivate())
+{
+ // nothing todo
+}
+
+QCLuceneSearchable::~QCLuceneSearchable()
+{
+ // nothing todo
+}
+
+
+QCLuceneSearcher::QCLuceneSearcher()
+ : QCLuceneSearchable()
+{
+ // nothing todo
+}
+
+QCLuceneSearcher::~QCLuceneSearcher()
+{
+ // nothing todo;
+}
+
+QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query)
+{
+ return search(query, QCLuceneFilter());
+}
+
+QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query,
+ const QCLuceneFilter &filter)
+{
+ return QCLuceneHits(*this, query, filter);
+}
+
+QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query,
+ const QCLuceneSort &sort)
+{
+ return QCLuceneHits(*this, query, QCLuceneFilter(), sort);
+}
+
+QCLuceneHits QCLuceneSearcher::search(const QCLuceneQuery &query,
+ const QCLuceneFilter &filter,
+ const QCLuceneSort &sort)
+{
+ return QCLuceneHits(*this, query, filter, sort);
+}
+
+
+QCLuceneIndexSearcher::QCLuceneIndexSearcher(const QString &path)
+ : QCLuceneSearcher()
+{
+ lucene::search::IndexSearcher *searcher =
+ new lucene::search::IndexSearcher(path);
+
+ reader.d->reader = searcher->getReader();
+ reader.d->deleteCLuceneIndexReader = false;
+
+ d->searchable = searcher;
+}
+
+QCLuceneIndexSearcher::QCLuceneIndexSearcher(const QCLuceneIndexReader &reader)
+ : QCLuceneSearcher()
+ , reader(reader)
+{
+ d->searchable = new lucene::search::IndexSearcher(reader.d->reader);
+}
+
+QCLuceneIndexSearcher::~QCLuceneIndexSearcher()
+{
+ // nothing todo
+}
+
+void QCLuceneIndexSearcher::close()
+{
+ d->searchable->close();
+}
+
+qint32 QCLuceneIndexSearcher::maxDoc() const
+{
+ return qint32(d->searchable->maxDoc());
+}
+
+QCLuceneIndexReader QCLuceneIndexSearcher::getReader()
+{
+ return reader;
+}
+
+bool QCLuceneIndexSearcher::doc(qint32 i, QCLuceneDocument &document)
+{
+ return d->searchable->doc(int32_t(i), document.d->document);
+}
+
+
+QCLuceneMultiSearcher::QCLuceneMultiSearcher(const QList<QCLuceneSearchable> searchables)
+: QCLuceneSearcher()
+{
+ lucene::search::Searchable** list=
+ _CL_NEWARRAY(lucene::search::Searchable*, searchables.count());
+
+ d->searchable = new lucene::search::MultiSearcher(list);
+
+ _CLDELETE_ARRAY(list);
+}
+
+QCLuceneMultiSearcher::~QCLuceneMultiSearcher()
+{
+ // nothing todo
+}
+
+void QCLuceneMultiSearcher::close()
+{
+ d->searchable->close();
+}
+
+qint32 QCLuceneMultiSearcher::maxDoc() const
+{
+ return qint32(d->searchable->maxDoc());
+}
+
+qint32 QCLuceneMultiSearcher::subDoc(qint32 index) const
+{
+ lucene::search::MultiSearcher *searcher =
+ static_cast<lucene::search::MultiSearcher*> (d->searchable);
+
+ if (searcher == 0)
+ return 0;
+
+ return qint32(searcher->subDoc(int32_t(index)));
+}
+
+qint32 QCLuceneMultiSearcher::subSearcher(qint32 index) const
+{
+ lucene::search::MultiSearcher *searcher =
+ static_cast<lucene::search::MultiSearcher*> (d->searchable);
+
+ if (searcher == 0)
+ return 0;
+
+ return qint32(searcher->subSearcher(int32_t(index)));
+}
+
+qint32 QCLuceneMultiSearcher::searcherIndex(qint32 index) const
+{
+ lucene::search::MultiSearcher *searcher =
+ static_cast<lucene::search::MultiSearcher*> (d->searchable);
+
+ if (searcher == 0)
+ return 0;
+
+ return qint32(searcher->searcherIndex(int32_t(index)));
+}
+
+bool QCLuceneMultiSearcher::doc(qint32 i, QCLuceneDocument &document)
+{
+ return d->searchable->doc(int32_t(i), document.d->document);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qsearchable_p.h b/tools/assistant/lib/fulltextsearch/qsearchable_p.h
new file mode 100644
index 0000000000..8e4da4443f
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qsearchable_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QSEARCHABLE_P_H
+#define QSEARCHABLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhits_p.h"
+#include "qsort_p.h"
+#include "qquery_p.h"
+#include "qfilter_p.h"
+#include "qdocument_p.h"
+#include "qindexreader_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(search)
+ class Searcher;
+CL_NS_END
+CL_NS_USE(search)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneHits;
+class QCLuceneSearcher;
+class QCLuceneIndexSearcher;
+class QCLuceneMultiSearcher;
+
+class QHELP_EXPORT QCLuceneSearchablePrivate : public QSharedData
+{
+public:
+ QCLuceneSearchablePrivate();
+ QCLuceneSearchablePrivate(const QCLuceneSearchablePrivate &other);
+
+ ~QCLuceneSearchablePrivate();
+
+ Searcher *searchable;
+ bool deleteCLuceneSearchable;
+
+private:
+ QCLuceneSearchablePrivate &operator=(const QCLuceneSearchablePrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneSearchable
+{
+public:
+ virtual ~QCLuceneSearchable();
+
+protected:
+ friend class QCLuceneSearcher;
+ friend class QCLuceneIndexSearcher;
+ friend class QCLuceneMultiSearcher;
+ QSharedDataPointer<QCLuceneSearchablePrivate> d;
+
+private:
+ QCLuceneSearchable();
+};
+
+class QHELP_EXPORT QCLuceneSearcher : public QCLuceneSearchable
+{
+public:
+ QCLuceneSearcher();
+ virtual ~QCLuceneSearcher();
+
+ QCLuceneHits search(const QCLuceneQuery &query);
+ QCLuceneHits search(const QCLuceneQuery &query, const QCLuceneFilter &filter);
+ QCLuceneHits search(const QCLuceneQuery &query, const QCLuceneSort &sort);
+ QCLuceneHits search(const QCLuceneQuery &query, const QCLuceneFilter &filter,
+ const QCLuceneSort &sort);
+
+protected:
+ friend class QCLuceneHits;
+};
+
+class QHELP_EXPORT QCLuceneIndexSearcher : public QCLuceneSearcher
+{
+public:
+ QCLuceneIndexSearcher(const QString &path);
+ QCLuceneIndexSearcher(const QCLuceneIndexReader &reader);
+ ~QCLuceneIndexSearcher();
+
+ void close();
+ qint32 maxDoc() const;
+ QCLuceneIndexReader getReader();
+ bool doc(qint32 i, QCLuceneDocument &document);
+
+private:
+ QCLuceneIndexReader reader;
+};
+
+class QHELP_EXPORT QCLuceneMultiSearcher : public QCLuceneSearcher
+{
+public:
+ QCLuceneMultiSearcher(const QList<QCLuceneSearchable> searchables);
+ ~QCLuceneMultiSearcher();
+
+ void close();
+ qint32 maxDoc() const;
+ qint32 subDoc(qint32 index) const;
+ qint32 subSearcher(qint32 index) const;
+ qint32 searcherIndex(qint32 index) const;
+ bool doc(qint32 i, QCLuceneDocument &document);
+};
+
+QT_END_NAMESPACE
+
+#endif // QSEARCHABLE_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qsort.cpp b/tools/assistant/lib/fulltextsearch/qsort.cpp
new file mode 100644
index 0000000000..06d7276259
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qsort.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qsort_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/search/Sort.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneSortPrivate::QCLuceneSortPrivate()
+ : QSharedData()
+{
+ sort = 0;
+ deleteCLuceneSort = true;
+}
+
+QCLuceneSortPrivate::QCLuceneSortPrivate (const QCLuceneSortPrivate &other)
+ : QSharedData()
+{
+ sort = _CL_POINTER(other.sort);
+}
+
+QCLuceneSortPrivate::~QCLuceneSortPrivate()
+{
+ if (deleteCLuceneSort)
+ _CLDECDELETE(sort);
+}
+
+
+QCLuceneSort::QCLuceneSort()
+ : d(new QCLuceneSortPrivate())
+{
+ d->sort = new lucene::search::Sort();
+}
+
+QCLuceneSort::QCLuceneSort(const QStringList &fieldNames)
+ : d(new QCLuceneSortPrivate())
+{
+ d->sort = new lucene::search::Sort();
+ setSort(fieldNames);
+}
+
+QCLuceneSort::QCLuceneSort(const QString &field, bool reverse)
+ : d(new QCLuceneSortPrivate())
+{
+ d->sort = new lucene::search::Sort();
+ setSort(field, reverse);
+}
+
+QCLuceneSort::~QCLuceneSort()
+{
+ // nothing todo
+}
+
+QString QCLuceneSort::toString() const
+{
+ return TCharToQString(d->sort->toString());
+}
+
+void QCLuceneSort::setSort(const QStringList &fieldNames)
+{
+ TCHAR **nameArray = new TCHAR*[fieldNames.count()];
+ for (int i = 0; i < fieldNames.count(); ++i)
+ nameArray[i] = QStringToTChar(fieldNames.at(i));
+
+ d->sort->setSort((const TCHAR**)nameArray);
+
+ for (int i = 0; i < fieldNames.count(); ++i)
+ delete [] nameArray[i];
+ delete nameArray;
+}
+
+void QCLuceneSort::setSort(const QString &field, bool reverse)
+{
+ TCHAR *name = QStringToTChar(field);
+ d->sort->setSort(name, reverse);
+ delete [] name;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qsort_p.h b/tools/assistant/lib/fulltextsearch/qsort_p.h
new file mode 100644
index 0000000000..5ec2a06f02
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qsort_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QSORT_P_H
+#define QSORT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qclucene_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(search)
+ class Sort;
+CL_NS_END
+CL_NS_USE(search)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneHits;
+class QCLuceneField;
+
+class QHELP_EXPORT QCLuceneSortPrivate : public QSharedData
+{
+public:
+ QCLuceneSortPrivate();
+ QCLuceneSortPrivate (const QCLuceneSortPrivate &other);
+
+ ~QCLuceneSortPrivate();
+
+ Sort *sort;
+ bool deleteCLuceneSort;
+
+private:
+ QCLuceneSortPrivate &operator=(const QCLuceneSortPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneSort
+{
+public:
+ QCLuceneSort();
+ QCLuceneSort(const QStringList &fieldNames);
+ QCLuceneSort(const QString &field, bool reverse = false);
+
+ virtual ~QCLuceneSort();
+
+ QString toString() const;
+ void setSort(const QStringList &fieldNames);
+ void setSort(const QString &field, bool reverse = false);
+
+protected:
+ friend class QCLuceneHits;
+ QSharedDataPointer<QCLuceneSortPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSORT_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qterm.cpp b/tools/assistant/lib/fulltextsearch/qterm.cpp
new file mode 100644
index 0000000000..156586f645
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qterm.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qterm_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/index/IndexReader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneTermPrivate::QCLuceneTermPrivate()
+ : QSharedData()
+{
+ term = 0;
+ deleteCLuceneTerm = true;
+}
+
+QCLuceneTermPrivate::QCLuceneTermPrivate(const QCLuceneTermPrivate &other)
+ : QSharedData()
+{
+ term = _CL_POINTER(other.term);
+}
+
+QCLuceneTermPrivate::~QCLuceneTermPrivate()
+{
+ if (deleteCLuceneTerm)
+ _CLDECDELETE(term);
+}
+
+
+QCLuceneTerm::QCLuceneTerm()
+ : d(new QCLuceneTermPrivate())
+{
+ d->term = new lucene::index::Term();
+}
+
+QCLuceneTerm::QCLuceneTerm(const QString &field, const QString &text)
+ : d(new QCLuceneTermPrivate())
+{
+ TCHAR *fieldName = QStringToTChar(field);
+ TCHAR *termText = QStringToTChar(text);
+
+ d->term = new lucene::index::Term(fieldName, termText);
+
+ delete [] fieldName;
+ delete [] termText;
+}
+
+QCLuceneTerm::QCLuceneTerm(const QCLuceneTerm &fieldTerm, const QString &text)
+ : d(new QCLuceneTermPrivate())
+{
+ TCHAR *termText = QStringToTChar(text);
+ d->term = new lucene::index::Term(fieldTerm.d->term, termText);
+ delete [] termText;
+}
+
+QCLuceneTerm::~QCLuceneTerm()
+{
+ // nothing todo
+}
+
+QString QCLuceneTerm::field() const
+{
+ return TCharToQString(d->term->field());
+}
+
+QString QCLuceneTerm::text() const
+{
+ return TCharToQString(d->term->text());
+}
+
+void QCLuceneTerm::set(const QString &field, const QString &text)
+{
+ set(field, text, true);
+}
+
+void QCLuceneTerm::set(const QCLuceneTerm &fieldTerm, const QString &text)
+{
+ set(fieldTerm.field(), text, false);
+}
+
+void QCLuceneTerm::set(const QString &field, const QString &text, bool internField)
+{
+ TCHAR *fieldName = QStringToTChar(field);
+ TCHAR *termText = QStringToTChar(text);
+
+ d->term->set(fieldName, termText, internField);
+
+ delete [] fieldName;
+ delete [] termText;
+}
+
+bool QCLuceneTerm::equals(const QCLuceneTerm &other) const
+{
+ return d->term->equals(other.d->term);
+}
+
+qint32 QCLuceneTerm::compareTo(const QCLuceneTerm &other) const
+{
+ return quint32(d->term->compareTo(other.d->term));
+}
+
+QString QCLuceneTerm::toString() const
+{
+ return TCharToQString(d->term->toString());
+}
+
+quint32 QCLuceneTerm::hashCode() const
+{
+ return quint32(d->term->hashCode());
+}
+
+quint32 QCLuceneTerm::textLength() const
+{
+ return quint32(d->term->textLength());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qterm_p.h b/tools/assistant/lib/fulltextsearch/qterm_p.h
new file mode 100644
index 0000000000..474c909f3a
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qterm_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QTERM_P_H
+#define QTERM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qclucene_global_p.h"
+
+#include <QtCore/QSharedData>
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+
+CL_NS_DEF(index)
+ class Term;
+CL_NS_END
+CL_NS_USE(index)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneTermQuery;
+class QCLuceneRangeQuery;
+class QCLucenePrefixQuery;
+class QCLuceneIndexReader;
+class QCLucenePhraseQuery;
+
+class QHELP_EXPORT QCLuceneTermPrivate : public QSharedData
+{
+public:
+ QCLuceneTermPrivate();
+ QCLuceneTermPrivate(const QCLuceneTermPrivate &other);
+
+ ~QCLuceneTermPrivate();
+
+ Term *term;
+ bool deleteCLuceneTerm;
+
+private:
+ QCLuceneTermPrivate &operator=(const QCLuceneTermPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneTerm
+{
+public:
+ QCLuceneTerm();
+ QCLuceneTerm(const QString &field, const QString &text);
+ QCLuceneTerm(const QCLuceneTerm &fieldTerm, const QString &text);
+
+ virtual ~QCLuceneTerm();
+
+ QString field() const;
+ QString text() const;
+
+ void set(const QString &field, const QString &text);
+ void set(const QCLuceneTerm &fieldTerm, const QString &text);
+ void set(const QString &field, const QString &text, bool internField);
+
+ bool equals(const QCLuceneTerm &other) const;
+ qint32 compareTo(const QCLuceneTerm &other) const;
+
+ QString toString() const;
+ quint32 hashCode() const;
+ quint32 textLength() const;
+
+protected:
+ friend class QCLuceneTermQuery;
+ friend class QCLuceneRangeQuery;
+ friend class QCLucenePrefixQuery;
+ friend class QCLuceneIndexReader;
+ friend class QCLucenePhraseQuery;
+ QSharedDataPointer<QCLuceneTermPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTERM_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qtoken.cpp b/tools/assistant/lib/fulltextsearch/qtoken.cpp
new file mode 100644
index 0000000000..fa5d62a518
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qtoken.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qtoken_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/analysis/AnalysisHeader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneTokenPrivate::QCLuceneTokenPrivate()
+ : QSharedData()
+{
+ token = 0;
+ deleteCLuceneToken = true;
+}
+
+QCLuceneTokenPrivate::QCLuceneTokenPrivate(const QCLuceneTokenPrivate &other)
+ : QSharedData()
+{
+ token = _CL_POINTER(other.token);
+}
+
+QCLuceneTokenPrivate::~QCLuceneTokenPrivate()
+{
+ if (deleteCLuceneToken)
+ _CLDECDELETE(token);
+}
+
+
+QCLuceneToken::QCLuceneToken()
+ : d(new QCLuceneTokenPrivate())
+ , tokenText(0)
+ , tokenType(0)
+{
+ d->token = new lucene::analysis::Token();
+}
+
+QCLuceneToken::QCLuceneToken(const QString &text, qint32 startOffset,
+ qint32 endOffset, const QString &defaultTyp)
+ : d(new QCLuceneTokenPrivate())
+ , tokenText(QStringToTChar(text))
+ , tokenType(QStringToTChar(defaultTyp))
+{
+ d->token = new lucene::analysis::Token(tokenText, int32_t(startOffset),
+ int32_t(endOffset), tokenType);
+}
+
+QCLuceneToken::~QCLuceneToken()
+{
+ delete [] tokenText;
+ delete [] tokenType;
+}
+
+quint32 QCLuceneToken::bufferLength() const
+{
+ return quint32(d->token->bufferLength());
+}
+
+void QCLuceneToken::growBuffer(quint32 size)
+{
+ d->token->growBuffer(size_t(size));
+}
+
+qint32 QCLuceneToken::positionIncrement() const
+{
+ return qint32(d->token->getPositionIncrement());
+}
+
+void QCLuceneToken::setPositionIncrement(qint32 positionIncrement)
+{
+ d->token->setPositionIncrement(int32_t(positionIncrement));
+}
+
+QString QCLuceneToken::termText() const
+{
+ return TCharToQString(d->token->termText());
+}
+
+void QCLuceneToken::setTermText(const QString &text)
+{
+ delete [] tokenText;
+ tokenText = QStringToTChar(text);
+ d->token->setText(tokenText);
+}
+
+quint32 QCLuceneToken::termTextLength() const
+{
+ return quint32(d->token->termTextLength());
+}
+
+void QCLuceneToken::resetTermTextLength() const
+{
+ d->token->resetTermTextLen();
+}
+
+qint32 QCLuceneToken::startOffset() const
+{
+ return quint32(d->token->startOffset());
+}
+
+void QCLuceneToken::setStartOffset(qint32 value)
+{
+ d->token->setStartOffset(int32_t(value));
+}
+
+qint32 QCLuceneToken::endOffset() const
+{
+ return quint32(d->token->endOffset());
+}
+
+void QCLuceneToken::setEndOffset(qint32 value)
+{
+ d->token->setEndOffset(int32_t(value));
+}
+
+QString QCLuceneToken::type() const
+{
+ return TCharToQString(d->token->type());
+}
+
+void QCLuceneToken::setType(const QString &type)
+{
+ delete [] tokenType;
+ tokenType = QStringToTChar(type);
+ d->token->setType(tokenType);
+}
+
+QString QCLuceneToken::toString() const
+{
+ return TCharToQString(d->token->toString());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qtoken_p.h b/tools/assistant/lib/fulltextsearch/qtoken_p.h
new file mode 100644
index 0000000000..1802f991b0
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qtoken_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QTOKEN_P_H
+#define QTOKEN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qclucene_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(analysis)
+ class Token;
+CL_NS_END
+CL_NS_USE(analysis)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneTokenizer;
+class QCLuceneTokenStream;
+class QCLuceneStandardTokenizer;
+
+class QHELP_EXPORT QCLuceneTokenPrivate : public QSharedData
+{
+public:
+ QCLuceneTokenPrivate();
+ QCLuceneTokenPrivate(const QCLuceneTokenPrivate &other);
+
+ ~QCLuceneTokenPrivate();
+
+ Token *token;
+ bool deleteCLuceneToken;
+
+private:
+ QCLuceneTokenPrivate &operator=(const QCLuceneTokenPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneToken
+{
+public:
+ QCLuceneToken();
+ QCLuceneToken(const QString &text, qint32 startOffset,
+ qint32 endOffset, const QString &defaultTyp = QLatin1String("word"));
+
+ virtual ~QCLuceneToken();
+
+ void set(const QString &text, qint32 startOffset,
+ qint32 endOffset, const QString &defaultTyp = QLatin1String("word"));
+
+ quint32 bufferLength() const;
+ void growBuffer(quint32 size);
+
+ qint32 positionIncrement() const;
+ void setPositionIncrement(qint32 positionIncrement);
+
+ QString termText() const;
+ void setTermText(const QString &text);
+
+ quint32 termTextLength() const;
+ void resetTermTextLength() const;
+
+ qint32 startOffset() const;
+ void setStartOffset(qint32 value);
+
+ qint32 endOffset() const;
+ void setEndOffset(qint32 value);
+
+ QString type() const;
+ void setType(const QString &type);
+
+ QString toString() const;
+
+protected:
+ friend class QCLuceneTokenizer;
+ friend class QCLuceneTokenStream;
+ friend class QCLuceneStandardTokenizer;
+ QSharedDataPointer<QCLuceneTokenPrivate> d;
+
+private:
+ TCHAR *tokenText;
+ TCHAR *tokenType;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTOKEN_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qtokenizer.cpp b/tools/assistant/lib/fulltextsearch/qtokenizer.cpp
new file mode 100644
index 0000000000..9a07387a6f
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qtokenizer.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qtokenizer_p.h"
+#include "qclucene_global_p.h"
+
+#include <CLucene.h>
+#include <CLucene/analysis/AnalysisHeader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneTokenizer::QCLuceneTokenizer()
+ : QCLuceneTokenStream()
+{
+ // nothing todo
+}
+
+QCLuceneTokenizer::QCLuceneTokenizer(const QCLuceneReader &reader)
+ : QCLuceneTokenStream()
+ , reader(reader)
+{
+ // nothing todo
+}
+
+QCLuceneTokenizer::~QCLuceneTokenizer()
+{
+ close();
+}
+
+void QCLuceneTokenizer::close()
+{
+ d->tokenStream->close();
+}
+
+bool QCLuceneTokenizer::next(QCLuceneToken &token)
+{
+ return d->tokenStream->next(token.d->token);
+}
+
+
+QCLuceneStandardTokenizer::QCLuceneStandardTokenizer(const QCLuceneReader &reader)
+ : QCLuceneTokenizer(reader)
+{
+ d->tokenStream =
+ new lucene::analysis::standard::StandardTokenizer(reader.d->reader);
+}
+
+QCLuceneStandardTokenizer::~QCLuceneStandardTokenizer()
+{
+ // nothing todo
+}
+
+bool QCLuceneStandardTokenizer::readApostrophe(const QString &string,
+ QCLuceneToken &token)
+{
+ lucene::analysis::standard::StandardTokenizer *stdTokenizer =
+ static_cast<lucene::analysis::standard::StandardTokenizer*> (d->tokenStream);
+
+ if (stdTokenizer == 0)
+ return false;
+
+ TCHAR* value = QStringToTChar(string);
+ lucene::util::StringBuffer buffer(value);
+ bool retValue = stdTokenizer->ReadApostrophe(&buffer, token.d->token);
+ delete [] value;
+
+ return retValue;
+}
+
+bool QCLuceneStandardTokenizer::readAt(const QString &string, QCLuceneToken &token)
+{
+ lucene::analysis::standard::StandardTokenizer *stdTokenizer =
+ static_cast<lucene::analysis::standard::StandardTokenizer*> (d->tokenStream);
+
+ if (stdTokenizer == 0)
+ return false;
+
+ TCHAR* value = QStringToTChar(string);
+ lucene::util::StringBuffer buffer(value);
+ bool retValue = stdTokenizer->ReadAt(&buffer, token.d->token);
+ delete [] value;
+
+ return retValue;
+}
+
+bool QCLuceneStandardTokenizer::readCompany(const QString &string,
+ QCLuceneToken &token)
+{
+ lucene::analysis::standard::StandardTokenizer *stdTokenizer =
+ static_cast<lucene::analysis::standard::StandardTokenizer*> (d->tokenStream);
+
+ if (stdTokenizer == 0)
+ return false;
+
+ TCHAR* value = QStringToTChar(string);
+ lucene::util::StringBuffer buffer(value);
+ bool retValue = stdTokenizer->ReadCompany(&buffer, token.d->token);
+ delete [] value;
+
+ return retValue;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/fulltextsearch/qtokenizer_p.h b/tools/assistant/lib/fulltextsearch/qtokenizer_p.h
new file mode 100644
index 0000000000..1e7916c111
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qtokenizer_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QTOKENIZER_P_H
+#define QTOKENIZER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtoken_p.h"
+#include "qreader_p.h"
+#include "qtokenstream_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QChar>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QHELP_EXPORT QCLuceneTokenizer : public QCLuceneTokenStream
+{
+public:
+ QCLuceneTokenizer(const QCLuceneReader &reader);
+ virtual ~QCLuceneTokenizer();
+
+ void close();
+ bool next(QCLuceneToken &token);
+
+protected:
+ friend class QCLuceneStandardTokenizer;
+
+private:
+ QCLuceneTokenizer();
+ QCLuceneReader reader;
+};
+
+class QHELP_EXPORT QCLuceneStandardTokenizer : public QCLuceneTokenizer
+{
+public:
+ QCLuceneStandardTokenizer(const QCLuceneReader &reader);
+ ~QCLuceneStandardTokenizer();
+
+ bool readApostrophe(const QString &string, QCLuceneToken &token);
+ bool readAt(const QString &string, QCLuceneToken &token);
+ bool readCompany(const QString &string, QCLuceneToken &token);
+};
+
+class QCLuceneCharTokenizer : public QCLuceneTokenizer
+{
+
+};
+
+class QCLuceneLetterTokenizer : public QCLuceneCharTokenizer
+{
+
+};
+
+class QCLuceneLowerCaseTokenizer : public QCLuceneLetterTokenizer
+{
+
+};
+
+class QCLuceneWhitespaceTokenizer : public QCLuceneCharTokenizer
+{
+
+};
+
+class QCLuceneKeywordTokenizer : public QCLuceneTokenizer
+{
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QTOKENIZER_P_H
diff --git a/tools/assistant/lib/fulltextsearch/qtokenstream.cpp b/tools/assistant/lib/fulltextsearch/qtokenstream.cpp
new file mode 100644
index 0000000000..957a0c2c88
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qtokenstream.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#include "qtokenstream_p.h"
+
+#include <CLucene.h>
+#include <CLucene/analysis/AnalysisHeader.h>
+
+QT_BEGIN_NAMESPACE
+
+QCLuceneTokenStreamPrivate::QCLuceneTokenStreamPrivate()
+ : QSharedData()
+{
+ tokenStream = 0;
+ deleteCLuceneTokenStream = true;
+}
+
+QCLuceneTokenStreamPrivate::QCLuceneTokenStreamPrivate(const QCLuceneTokenStreamPrivate &other)
+ : QSharedData()
+{
+ tokenStream = _CL_POINTER(other.tokenStream);
+}
+
+QCLuceneTokenStreamPrivate::~QCLuceneTokenStreamPrivate()
+{
+ if (deleteCLuceneTokenStream)
+ _CLDECDELETE(tokenStream);
+}
+
+
+QCLuceneTokenStream::QCLuceneTokenStream()
+ : d(new QCLuceneTokenStreamPrivate())
+{
+ // nothing todo
+}
+
+QCLuceneTokenStream::~QCLuceneTokenStream()
+{
+ // nothing todo
+}
+
+void QCLuceneTokenStream::close()
+{
+ d->tokenStream->close();
+}
+
+bool QCLuceneTokenStream::next(QCLuceneToken &token)
+{
+ return d->tokenStream->next(token.d->token);
+}
+
+QT_END_NAMESPACE \ No newline at end of file
diff --git a/tools/assistant/lib/fulltextsearch/qtokenstream_p.h b/tools/assistant/lib/fulltextsearch/qtokenstream_p.h
new file mode 100644
index 0000000000..ef6e71585f
--- /dev/null
+++ b/tools/assistant/lib/fulltextsearch/qtokenstream_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QCLucene library and is distributable under
+** the terms of the LGPL license as specified in the license.txt file.
+**
+****************************************************************************/
+
+#ifndef QTOKENSTREAM_P_H
+#define QTOKENSTREAM_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtoken_p.h"
+#include "qclucene_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QSharedData>
+
+CL_NS_DEF(analysis)
+ class TokenStream;
+CL_NS_END
+CL_NS_USE(analysis)
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneAnalyzer;
+class QCLuceneTokenizer;
+class QCLuceneStopAnalyzer;
+class QCLuceneSimpleAnalyzer;
+class QCLuceneKeywordAnalyzer;
+class QCLuceneStandardAnalyzer;
+class QCLuceneWhitespaceAnalyzer;
+class QCLucenePerFieldAnalyzerWrapper;
+
+class QHELP_EXPORT QCLuceneTokenStreamPrivate : public QSharedData
+{
+public:
+ QCLuceneTokenStreamPrivate();
+ QCLuceneTokenStreamPrivate(const QCLuceneTokenStreamPrivate &other);
+
+ ~QCLuceneTokenStreamPrivate();
+
+ TokenStream *tokenStream;
+ bool deleteCLuceneTokenStream;
+
+private:
+ QCLuceneTokenStreamPrivate &operator=(const QCLuceneTokenStreamPrivate &other);
+};
+
+class QHELP_EXPORT QCLuceneTokenStream
+{
+public:
+ virtual ~QCLuceneTokenStream();
+
+ void close();
+ bool next(QCLuceneToken &token);
+
+protected:
+ friend class QCLuceneAnalyzer;
+ friend class QCLuceneTokenizer;
+ friend class QCLuceneStopAnalyzer;
+ friend class QCLuceneSimpleAnalyzer;
+ friend class QCLuceneKeywordAnalyzer;
+ friend class QCLuceneStandardAnalyzer;
+ friend class QCLuceneWhitespaceAnalyzer;
+ friend class QCLucenePerFieldAnalyzerWrapper;
+ QSharedDataPointer<QCLuceneTokenStreamPrivate> d;
+
+private:
+ QCLuceneTokenStream();
+};
+
+QT_END_NAMESPACE
+
+#endif // QTOKENSTREAM_P_H
diff --git a/tools/assistant/lib/helpsystem.qrc b/tools/assistant/lib/helpsystem.qrc
new file mode 100644
index 0000000000..10efc6df18
--- /dev/null
+++ b/tools/assistant/lib/helpsystem.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/trolltech/assistant" >
+ <file>images/1leftarrow.png</file>
+ <file>images/1rightarrow.png</file>
+ <file>images/3leftarrow.png</file>
+ <file>images/3rightarrow.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/assistant/lib/images/1leftarrow.png b/tools/assistant/lib/images/1leftarrow.png
new file mode 100644
index 0000000000..bd1a5a2499
--- /dev/null
+++ b/tools/assistant/lib/images/1leftarrow.png
Binary files differ
diff --git a/tools/assistant/lib/images/1rightarrow.png b/tools/assistant/lib/images/1rightarrow.png
new file mode 100644
index 0000000000..0c0c44ae6f
--- /dev/null
+++ b/tools/assistant/lib/images/1rightarrow.png
Binary files differ
diff --git a/tools/assistant/lib/images/3leftarrow.png b/tools/assistant/lib/images/3leftarrow.png
new file mode 100644
index 0000000000..8d38b0f578
--- /dev/null
+++ b/tools/assistant/lib/images/3leftarrow.png
Binary files differ
diff --git a/tools/assistant/lib/images/3rightarrow.png b/tools/assistant/lib/images/3rightarrow.png
new file mode 100644
index 0000000000..c2faf501cc
--- /dev/null
+++ b/tools/assistant/lib/images/3rightarrow.png
Binary files differ
diff --git a/tools/assistant/lib/lib.pro b/tools/assistant/lib/lib.pro
new file mode 100644
index 0000000000..bd9ed5370e
--- /dev/null
+++ b/tools/assistant/lib/lib.pro
@@ -0,0 +1,65 @@
+QT += sql xml network
+TEMPLATE = lib
+TARGET = QtHelp
+DEFINES += QHELP_LIB QT_CLUCENE_SUPPORT
+CONFIG += qt warn_on
+
+include(../../../src/qbase.pri)
+
+QMAKE_TARGET_PRODUCT = Help
+QMAKE_TARGET_DESCRIPTION = Help application framework.
+DEFINES -= QT_ASCII_CAST_WARNINGS
+
+qclucene = QtCLucene$${QT_LIBINFIX}
+if(!debug_and_release|build_pass):CONFIG(debug, debug|release) {
+ mac:qclucene = $${qclucene}_debug
+ win32:qclucene = $${qclucene}d
+}
+linux-lsb-g++:LIBS += --lsb-shared-libs=$$qclucene
+unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork QtSql QtXml
+LIBS += -l$$qclucene
+unix:QMAKE_PKGCONFIG_REQUIRES += QtNetwork QtSql QtXml
+
+RESOURCES += helpsystem.qrc
+
+SOURCES += qhelpenginecore.cpp \
+ qhelpengine.cpp \
+ qhelpdbreader.cpp \
+ qhelpcontentwidget.cpp \
+ qhelpindexwidget.cpp \
+ qhelpgenerator.cpp \
+ qhelpdatainterface.cpp \
+ qhelpprojectdata.cpp \
+ qhelpcollectionhandler.cpp \
+ qhelpsearchengine.cpp \
+ qhelpsearchquerywidget.cpp \
+ qhelpsearchresultwidget.cpp \
+ qhelpsearchindex_default.cpp \
+ qhelpsearchindexwriter_default.cpp \
+ qhelpsearchindexreader_default.cpp
+
+# access to clucene
+SOURCES += qhelpsearchindexwriter_clucene.cpp \
+ qhelpsearchindexreader_clucene.cpp
+
+HEADERS += qhelpenginecore.h \
+ qhelpengine.h \
+ qhelpengine_p.h \
+ qhelp_global.h \
+ qhelpdbreader_p.h \
+ qhelpcontentwidget.h \
+ qhelpindexwidget.h \
+ qhelpgenerator_p.h \
+ qhelpdatainterface_p.h \
+ qhelpprojectdata_p.h \
+ qhelpcollectionhandler_p.h \
+ qhelpsearchengine.h \
+ qhelpsearchquerywidget.h \
+ qhelpsearchresultwidget.h \
+ qhelpsearchindex_default_p.h \
+ qhelpsearchindexwriter_default_p.h \
+ qhelpsearchindexreader_default_p.h
+
+# access to clucene
+HEADERS += qhelpsearchindexwriter_clucene_p.h \
+ qhelpsearchindexreader_clucene_p.h
diff --git a/tools/assistant/lib/qhelp_global.h b/tools/assistant/lib/qhelp_global.h
new file mode 100644
index 0000000000..5f09a0807d
--- /dev/null
+++ b/tools/assistant/lib/qhelp_global.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELP_GLOBAL_H
+#define QHELP_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QString>
+#include <QtCore/QObject>
+#include <QtCore/QRegExp>
+#include <QtCore/QMutexLocker>
+#include <QtGui/QTextDocument>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+#if !defined(QT_SHARED) && !defined(QT_DLL)
+# define QHELP_EXPORT
+#elif defined(QHELP_LIB)
+# define QHELP_EXPORT Q_DECL_EXPORT
+#else
+# define QHELP_EXPORT Q_DECL_IMPORT
+#endif
+
+class QHelpGlobal {
+public:
+ static QString uniquifyConnectionName(const QString &name, void *pointer)
+ {
+ static int counter = 0;
+ static QMutex mutex;
+
+ QMutexLocker locker(&mutex);
+ if (++counter > 1000)
+ counter = 0;
+
+ return QString::fromLatin1("%1-%2-%3")
+ .arg(name).arg(long(pointer)).arg(counter);
+ };
+
+ static QString documentTitle(const QString &content)
+ {
+ QString title = QObject::tr("Untitled");
+ if (!content.isEmpty()) {
+ int start = content.indexOf(QLatin1String("<title>"), 0, Qt::CaseInsensitive) + 7;
+ int end = content.indexOf(QLatin1String("</title>"), 0, Qt::CaseInsensitive);
+ if ((end - start) > 0) {
+ title = content.mid(start, end - start);
+ if (Qt::mightBeRichText(title) || title.contains(QLatin1Char('&'))) {
+ QTextDocument doc;
+ doc.setHtml(title);
+ title = doc.toPlainText();
+ }
+ }
+ }
+ return title;
+ };
+
+ static QString charsetFromData(const QByteArray &data)
+ {
+ QString content = QString::fromUtf8(data.constData(), data.size());
+ int start =
+ content.indexOf(QLatin1String("<meta"), 0, Qt::CaseInsensitive);
+ if (start > 0) {
+ int end;
+ QRegExp r(QLatin1String("charset=([^\"\\s]+)"));
+ while (start != -1) {
+ end = content.indexOf(QLatin1Char('>'), start) + 1;
+ const QString &meta = content.mid(start, end - start).toLower();
+ if (r.indexIn(meta) != -1)
+ return r.cap(1);
+ start = content.indexOf(QLatin1String("<meta"), end,
+ Qt::CaseInsensitive);
+ }
+ }
+ return QLatin1String("utf-8");
+ }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QHELP_GLOBAL_H
diff --git a/tools/assistant/lib/qhelpcollectionhandler.cpp b/tools/assistant/lib/qhelpcollectionhandler.cpp
new file mode 100644
index 0000000000..235659193f
--- /dev/null
+++ b/tools/assistant/lib/qhelpcollectionhandler.cpp
@@ -0,0 +1,595 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpcollectionhandler_p.h"
+#include "qhelp_global.h"
+#include "qhelpdbreader_p.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+
+#include <QtSql/QSqlError>
+#include <QtSql/QSqlDriver>
+
+QT_BEGIN_NAMESPACE
+
+QHelpCollectionHandler::QHelpCollectionHandler(const QString &collectionFile, QObject *parent)
+ : QObject(parent)
+ , m_dbOpened(false)
+ , m_collectionFile(collectionFile)
+ , m_connectionName(QString())
+{
+ QFileInfo fi(m_collectionFile);
+ if (!fi.isAbsolute())
+ m_collectionFile = fi.absoluteFilePath();
+ m_query.clear();
+}
+
+QHelpCollectionHandler::~QHelpCollectionHandler()
+{
+ m_query.clear();
+ if (m_dbOpened)
+ QSqlDatabase::removeDatabase(m_connectionName);
+}
+
+bool QHelpCollectionHandler::isDBOpened()
+{
+ if (m_dbOpened)
+ return true;
+ emit error(tr("The collection file is not set up yet!"));
+ return false;
+}
+
+QString QHelpCollectionHandler::collectionFile() const
+{
+ return m_collectionFile;
+}
+
+bool QHelpCollectionHandler::openCollectionFile()
+{
+ if (m_dbOpened)
+ return m_dbOpened;
+
+ m_connectionName = QHelpGlobal::uniquifyConnectionName(
+ QLatin1String("QHelpCollectionHandler"), this);
+ bool openingOk = true;
+ {
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"),
+ m_connectionName);
+ if (db.driver()
+ && db.driver()->lastError().type() == QSqlError::ConnectionError) {
+ emit error(tr("Cannot load sqlite database driver!"));
+ return false;
+ }
+
+ db.setDatabaseName(collectionFile());
+ openingOk = db.open();
+ if (openingOk)
+ m_query = QSqlQuery(db);
+ }
+ if (!openingOk) {
+ QSqlDatabase::removeDatabase(m_connectionName);
+ emit error(tr("Cannot open collection file: %1").arg(collectionFile()));
+ return false;
+ }
+
+ m_query.exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'"
+ "AND Name=\'NamespaceTable\'"));
+ m_query.next();
+ if (m_query.value(0).toInt() < 1) {
+ if (!createTables(&m_query)) {
+ emit error(tr("Cannot create tables in file %1!").arg(collectionFile()));
+ return false;
+ }
+ }
+
+ m_dbOpened = true;
+ return m_dbOpened;
+}
+
+bool QHelpCollectionHandler::copyCollectionFile(const QString &fileName)
+{
+ if (!m_dbOpened)
+ return false;
+
+ QFileInfo fi(fileName);
+ if (fi.exists()) {
+ emit error(tr("The specified collection file already exists!"));
+ return false;
+ }
+
+ if (!fi.absoluteDir().exists() && !QDir().mkpath(fi.absolutePath())) {
+ emit error(tr("Cannot create directory: %1").arg(fi.absolutePath()));
+ return false;
+ }
+
+ QString colFile = fi.absoluteFilePath();
+ QString connectionName = QHelpGlobal::uniquifyConnectionName(
+ QLatin1String("QHelpCollectionHandlerCopy"), this);
+ QSqlQuery *copyQuery = 0;
+ bool openingOk = true;
+ {
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), connectionName);
+ db.setDatabaseName(colFile);
+ openingOk = db.open();
+ if (openingOk)
+ copyQuery = new QSqlQuery(db);
+ }
+
+ if (!openingOk) {
+ emit error(tr("Cannot open collection file: %1").arg(colFile));
+ return false;
+ }
+
+ if (!createTables(copyQuery)) {
+ emit error(tr("Cannot copy collection file: %1").arg(colFile));
+ return false;
+ }
+
+ QString oldBaseDir = QFileInfo(collectionFile()).absolutePath();
+ QString oldFilePath;
+ QFileInfo newColFi(colFile);
+ m_query.exec(QLatin1String("SELECT Name, FilePath FROM NamespaceTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ oldFilePath = m_query.value(1).toString();
+ if (!QDir::isAbsolutePath(oldFilePath))
+ oldFilePath = oldBaseDir + QDir::separator() + oldFilePath;
+ copyQuery->bindValue(1, newColFi.absoluteDir().relativeFilePath(oldFilePath));
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT NamespaceId, Name FROM FolderTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->bindValue(1, m_query.value(1).toString());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT NameId, FilterAttributeId FROM FilterTable"));
+ while (m_query.next()) {
+ copyQuery->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toInt());
+ copyQuery->bindValue(1, m_query.value(1).toInt());
+ copyQuery->exec();
+ }
+
+ m_query.exec(QLatin1String("SELECT Key, Value FROM SettingsTable"));
+ while (m_query.next()) {
+ if (m_query.value(0).toString() == QLatin1String("CluceneSearchNamespaces"))
+ continue;
+ copyQuery->prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)"));
+ copyQuery->bindValue(0, m_query.value(0).toString());
+ copyQuery->bindValue(1, m_query.value(1));
+ copyQuery->exec();
+ }
+
+ copyQuery->clear();
+ delete copyQuery;
+ QSqlDatabase::removeDatabase(connectionName);
+ return true;
+}
+
+bool QHelpCollectionHandler::createTables(QSqlQuery *query)
+{
+ QStringList tables;
+ tables << QLatin1String("CREATE TABLE NamespaceTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT, "
+ "FilePath TEXT )")
+ << QLatin1String("CREATE TABLE FolderTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "NamespaceId INTEGER, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterAttributeTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterNameTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterTable ("
+ "NameId INTEGER, "
+ "FilterAttributeId INTEGER )")
+ << QLatin1String("CREATE TABLE SettingsTable ("
+ "Key TEXT PRIMARY KEY, "
+ "Value BLOB )");
+
+ foreach (QString q, tables) {
+ if (!query->exec(q))
+ return false;
+ }
+ return true;
+}
+
+QStringList QHelpCollectionHandler::customFilters() const
+{
+ QStringList list;
+ if (m_dbOpened) {
+ m_query.exec(QLatin1String("SELECT Name FROM FilterNameTable"));
+ while (m_query.next())
+ list.append(m_query.value(0).toString());
+ }
+ return list;
+}
+
+bool QHelpCollectionHandler::removeCustomFilter(const QString &filterName)
+{
+ if (!isDBOpened() || filterName.isEmpty())
+ return false;
+
+ int filterNameId = -1;
+ m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
+ m_query.bindValue(0, filterName);
+ m_query.exec();
+ if (m_query.next())
+ filterNameId = m_query.value(0).toInt();
+
+ if (filterNameId < 0) {
+ emit error(tr("Unknown filter!"));
+ return false;
+ }
+
+ m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
+ m_query.bindValue(0, filterNameId);
+ m_query.exec();
+
+ m_query.prepare(QLatin1String("DELETE FROM FilterNameTable WHERE Id=?"));
+ m_query.bindValue(0, filterNameId);
+ m_query.exec();
+
+ return true;
+}
+
+bool QHelpCollectionHandler::addCustomFilter(const QString &filterName,
+ const QStringList &attributes)
+{
+ if (!isDBOpened() || filterName.isEmpty())
+ return false;
+
+ int nameId = -1;
+ m_query.prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
+ m_query.bindValue(0, filterName);
+ m_query.exec();
+ while (m_query.next()) {
+ nameId = m_query.value(0).toInt();
+ break;
+ }
+
+ m_query.exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable"));
+ QStringList idsToInsert = attributes;
+ QMap<QString, int> attributeMap;
+ while (m_query.next()) {
+ attributeMap.insert(m_query.value(1).toString(),
+ m_query.value(0).toInt());
+ if (idsToInsert.contains(m_query.value(1).toString()))
+ idsToInsert.removeAll(m_query.value(1).toString());
+ }
+
+ foreach (QString id, idsToInsert) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ m_query.bindValue(0, id);
+ m_query.exec();
+ attributeMap.insert(id, m_query.lastInsertId().toInt());
+ }
+
+ if (nameId < 0) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
+ m_query.bindValue(0, filterName);
+ if (m_query.exec())
+ nameId = m_query.lastInsertId().toInt();
+ }
+
+ if (nameId < 0) {
+ emit error(tr("Cannot register filter %1!").arg(filterName));
+ return false;
+ }
+
+ m_query.prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
+ m_query.bindValue(0, nameId);
+ m_query.exec();
+
+ foreach (QString att, attributes) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
+ m_query.bindValue(0, nameId);
+ m_query.bindValue(1, attributeMap[att]);
+ if (!m_query.exec())
+ return false;
+ }
+ return true;
+}
+
+QHelpCollectionHandler::DocInfoList QHelpCollectionHandler::registeredDocumentations() const
+{
+ DocInfoList list;
+ if (m_dbOpened) {
+ m_query.exec(QLatin1String("SELECT a.Name, a.FilePath, b.Name "
+ "FROM NamespaceTable a, FolderTable b WHERE a.Id=b.NamespaceId"));
+
+ while (m_query.next()) {
+ DocInfo info;
+ info.fileName = m_query.value(1).toString();
+ info.folderName = m_query.value(2).toString();
+ info.namespaceName = m_query.value(0).toString();
+ list.append(info);
+ }
+ }
+ return list;
+}
+
+bool QHelpCollectionHandler::registerDocumentation(const QString &fileName)
+{
+ if (!isDBOpened())
+ return false;
+
+ QHelpDBReader reader(fileName, QHelpGlobal::uniquifyConnectionName(
+ QLatin1String("QHelpCollectionHandler"), this), 0);
+ if (!reader.init()) {
+ emit error(tr("Cannot open documentation file %1!").arg(fileName));
+ return false;
+ }
+
+ QString ns = reader.namespaceName();
+ if (ns.isEmpty()) {
+ emit error(tr("Invalid documentation file!"));
+ return false;
+ }
+
+ int nsId = registerNamespace(ns, fileName);
+ if (nsId < 1)
+ return false;
+
+ if (!registerVirtualFolder(reader.virtualFolder(), nsId))
+ return false;
+
+ addFilterAttributes(reader.filterAttributes());
+ foreach (QString filterName, reader.customFilters())
+ addCustomFilter(filterName, reader.filterAttributes(filterName));
+
+ optimizeDatabase(fileName);
+
+ return true;
+}
+
+bool QHelpCollectionHandler::unregisterDocumentation(const QString &namespaceName)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name=?"));
+ m_query.bindValue(0, namespaceName);
+ m_query.exec();
+
+ int nsId = -1;
+ if (m_query.next())
+ nsId = m_query.value(0).toInt();
+
+ if (nsId < 0) {
+ emit error(tr("The namespace %1 was not registered!").arg(namespaceName));
+ return false;
+ }
+
+ m_query.prepare(QLatin1String("DELETE FROM NamespaceTable WHERE Id=?"));
+ m_query.bindValue(0, nsId);
+ m_query.exec();
+
+ m_query.prepare(QLatin1String("DELETE FROM FolderTable WHERE NamespaceId=?"));
+ m_query.bindValue(0, nsId);
+ return m_query.exec();
+}
+
+bool QHelpCollectionHandler::removeCustomValue(const QString &key)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.prepare(QLatin1String("DELETE FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ return m_query.exec();
+}
+
+QVariant QHelpCollectionHandler::customValue(const QString &key,
+ const QVariant &defaultValue) const
+{
+ QVariant value = defaultValue;
+ if (m_dbOpened) {
+ m_query.prepare(QLatin1String("SELECT COUNT(Key) FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ if (!m_query.exec() || !m_query.next() || !m_query.value(0).toInt()) {
+ m_query.clear();
+ return defaultValue;
+ }
+
+ m_query.clear();
+ m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ if (m_query.exec() && m_query.next())
+ value = m_query.value(0);
+ m_query.clear();
+ }
+ return value;
+}
+
+bool QHelpCollectionHandler::setCustomValue(const QString &key,
+ const QVariant &value)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.prepare(QLatin1String("SELECT Value FROM SettingsTable WHERE Key=?"));
+ m_query.bindValue(0, key);
+ m_query.exec();
+ if (m_query.next()) {
+ m_query.prepare(QLatin1String("UPDATE SettingsTable SET Value=? where Key=?"));
+ m_query.bindValue(0, value);
+ m_query.bindValue(1, key);
+ }
+ else {
+ m_query.prepare(QLatin1String("INSERT INTO SettingsTable VALUES(?, ?)"));
+ m_query.bindValue(0, key);
+ m_query.bindValue(1, value);
+ }
+ return m_query.exec();
+}
+
+bool QHelpCollectionHandler::addFilterAttributes(const QStringList &attributes)
+{
+ if (!isDBOpened())
+ return false;
+
+ m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ QSet<QString> atts;
+ while (m_query.next())
+ atts.insert(m_query.value(0).toString());
+
+ foreach (QString s, attributes) {
+ if (!atts.contains(s)) {
+ m_query.prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ m_query.bindValue(0, s);
+ m_query.exec();
+ }
+ }
+ return true;
+}
+
+QStringList QHelpCollectionHandler::filterAttributes() const
+{
+ QStringList list;
+ if (m_dbOpened) {
+ m_query.exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ while (m_query.next())
+ list.append(m_query.value(0).toString());
+ }
+ return list;
+}
+
+QStringList QHelpCollectionHandler::filterAttributes(const QString &filterName) const
+{
+ QStringList list;
+ if (m_dbOpened) {
+ m_query.prepare(QLatin1String("SELECT a.Name FROM FilterAttributeTable a, "
+ "FilterTable b, FilterNameTable c WHERE a.Id=b.FilterAttributeId "
+ "AND b.NameId=c.Id AND c.Name=?"));
+ m_query.bindValue(0, filterName);
+ m_query.exec();
+ while (m_query.next())
+ list.append(m_query.value(0).toString());
+ }
+ return list;
+}
+
+int QHelpCollectionHandler::registerNamespace(const QString &nspace, const QString &fileName)
+{
+ m_query.prepare(QLatin1String("SELECT COUNT(Id) FROM NamespaceTable WHERE Name=?"));
+ m_query.bindValue(0, nspace);
+ m_query.exec();
+ while (m_query.next()) {
+ if (m_query.value(0).toInt() > 0) {
+ emit error(tr("Namespace %1 already exists!").arg(nspace));
+ return -1;
+ }
+ }
+
+ QFileInfo fi(m_collectionFile);
+ m_query.prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?, ?)"));
+ m_query.bindValue(0, nspace);
+ m_query.bindValue(1, fi.absoluteDir().relativeFilePath(fileName));
+ int namespaceId = -1;
+ if (m_query.exec())
+ namespaceId = m_query.lastInsertId().toInt();
+ if (namespaceId < 1) {
+ emit error(tr("Cannot register namespace!"));
+ return -1;
+ }
+ return namespaceId;
+}
+
+bool QHelpCollectionHandler::registerVirtualFolder(const QString &folderName, int namespaceId)
+{
+ m_query.prepare(QLatin1String("INSERT INTO FolderTable VALUES(NULL, ?, ?)"));
+ m_query.bindValue(0, namespaceId);
+ m_query.bindValue(1, folderName);
+ return m_query.exec();
+}
+
+void QHelpCollectionHandler::optimizeDatabase(const QString &fileName)
+{
+ if (!QFile::exists(fileName))
+ return;
+
+ { // according to removeDatabase() documentation
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("optimize"));
+ db.setDatabaseName(fileName);
+ if (!db.open()) {
+ QSqlDatabase::removeDatabase(QLatin1String("optimize"));
+ emit error(tr("Cannot open database to optimize!"));
+ return;
+ }
+
+ QSqlQuery query(db);
+ db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS NameIndex ON IndexTable(Name)"));
+ db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileNameIndex ON FileNameTable(Name)"));
+ db.exec(QLatin1String("CREATE INDEX IF NOT EXISTS FileIdIndex ON FileNameTable(FileId)"));
+
+ db.close();
+ }
+
+ QSqlDatabase::removeDatabase(QLatin1String("optimize"));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpcollectionhandler_p.h b/tools/assistant/lib/qhelpcollectionhandler_p.h
new file mode 100644
index 0000000000..2520694493
--- /dev/null
+++ b/tools/assistant/lib/qhelpcollectionhandler_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPCOLLECTIONHANDLER_H
+#define QHELPCOLLECTIONHANDLER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+#include <QtCore/QStringList>
+
+#include <QtSql/QSqlQuery>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpCollectionHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ struct DocInfo
+ {
+ QString fileName;
+ QString folderName;
+ QString namespaceName;
+ };
+ typedef QList<DocInfo> DocInfoList;
+
+ QHelpCollectionHandler(const QString &collectionFile, QObject *parent = 0);
+ ~QHelpCollectionHandler();
+
+ QString collectionFile() const;
+
+ bool openCollectionFile();
+ bool copyCollectionFile(const QString &fileName);
+
+ QStringList customFilters() const;
+ bool removeCustomFilter(const QString &filterName);
+ bool addCustomFilter(const QString &filterName,
+ const QStringList &attributes);
+
+ DocInfoList registeredDocumentations() const;
+ bool registerDocumentation(const QString &fileName);
+ bool unregisterDocumentation(const QString &namespaceName);
+
+ bool removeCustomValue(const QString &key);
+ QVariant customValue(const QString &key, const QVariant &defaultValue) const;
+ bool setCustomValue(const QString &key, const QVariant &value);
+
+ bool addFilterAttributes(const QStringList &attributes);
+ QStringList filterAttributes() const;
+ QStringList filterAttributes(const QString &filterName) const;
+
+ int registerNamespace(const QString &nspace, const QString &fileName);
+ bool registerVirtualFolder(const QString &folderName, int namespaceId);
+ void optimizeDatabase(const QString &fileName);
+
+signals:
+ void error(const QString &msg);
+
+private:
+ bool isDBOpened();
+ bool createTables(QSqlQuery *query);
+
+ bool m_dbOpened;
+ QString m_collectionFile;
+ QString m_connectionName;
+ mutable QSqlQuery m_query;
+};
+
+QT_END_NAMESPACE
+
+#endif //QHELPCOLLECTIONHANDLER_H
diff --git a/tools/assistant/lib/qhelpcontentwidget.cpp b/tools/assistant/lib/qhelpcontentwidget.cpp
new file mode 100644
index 0000000000..c70aef3ec7
--- /dev/null
+++ b/tools/assistant/lib/qhelpcontentwidget.cpp
@@ -0,0 +1,585 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpcontentwidget.h"
+#include "qhelpenginecore.h"
+#include "qhelpengine_p.h"
+#include "qhelpdbreader_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QStack>
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtGui/QHeaderView>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpContentItemPrivate
+{
+public:
+ QHelpContentItemPrivate(const QString &t, const QString &l,
+ QHelpDBReader *r, QHelpContentItem *p)
+ {
+ parent = p;
+ title = t;
+ link = l;
+ helpDBReader = r;
+ }
+
+ QList<QHelpContentItem*> childItems;
+ QHelpContentItem *parent;
+ QString title;
+ QString link;
+ QHelpDBReader *helpDBReader;
+};
+
+class QHelpContentProvider : public QThread
+{
+public:
+ QHelpContentProvider(QHelpEnginePrivate *helpEngine);
+ ~QHelpContentProvider();
+ void collectContents(const QString &customFilterName);
+ void stopCollecting();
+ QHelpContentItem *rootItem();
+ int nextChildCount() const;
+
+private:
+ void run();
+
+ QHelpEnginePrivate *m_helpEngine;
+ QHelpContentItem *m_rootItem;
+ QStringList m_filterAttributes;
+ QQueue<QHelpContentItem*> m_rootItems;
+ QMutex m_mutex;
+ bool m_abort;
+};
+
+class QHelpContentModelPrivate
+{
+public:
+ QHelpContentItem *rootItem;
+ QHelpContentProvider *qhelpContentProvider;
+};
+
+
+
+/*!
+ \class QHelpContentItem
+ \inmodule QtHelp
+ \brief The QHelpContentItem class provides an item for use with QHelpContentModel.
+ \since 4.4
+*/
+
+QHelpContentItem::QHelpContentItem(const QString &name, const QString &link,
+ QHelpDBReader *reader, QHelpContentItem *parent)
+{
+ d = new QHelpContentItemPrivate(name, link, reader, parent);
+}
+
+/*!
+ Destroys the help content item.
+*/
+QHelpContentItem::~QHelpContentItem()
+{
+ qDeleteAll(d->childItems);
+ delete d;
+}
+
+void QHelpContentItem::appendChild(QHelpContentItem *item)
+{
+ d->childItems.append(item);
+}
+
+/*!
+ Returns the child of the content item in the give \a row.
+
+ \sa parent()
+*/
+QHelpContentItem *QHelpContentItem::child(int row) const
+{
+ if (row >= childCount())
+ return 0;
+ return d->childItems.value(row);
+}
+
+/*!
+ Returns the number of child items.
+*/
+int QHelpContentItem::childCount() const
+{
+ return d->childItems.count();
+}
+
+/*!
+ Returns the row of this item from its parents view.
+*/
+int QHelpContentItem::row() const
+{
+ if (d->parent)
+ return d->parent->d->childItems.indexOf(const_cast<QHelpContentItem*>(this));
+ return 0;
+}
+
+/*!
+ Returns the title of the content item.
+*/
+QString QHelpContentItem::title() const
+{
+ return d->title;
+}
+
+/*!
+ Returns the URL of this content item.
+*/
+QUrl QHelpContentItem::url() const
+{
+ return d->helpDBReader->urlOfPath(d->link);
+}
+
+/*!
+ Returns the parent content item.
+*/
+QHelpContentItem *QHelpContentItem::parent() const
+{
+ return d->parent;
+}
+
+/*!
+ Returns the position of a given \a child.
+*/
+int QHelpContentItem::childPosition(QHelpContentItem *child) const
+{
+ return d->childItems.indexOf(child);
+}
+
+
+
+QHelpContentProvider::QHelpContentProvider(QHelpEnginePrivate *helpEngine)
+ : QThread(helpEngine)
+{
+ m_helpEngine = helpEngine;
+ m_rootItem = 0;
+ m_abort = false;
+}
+
+QHelpContentProvider::~QHelpContentProvider()
+{
+ stopCollecting();
+}
+
+void QHelpContentProvider::collectContents(const QString &customFilterName)
+{
+ m_mutex.lock();
+ m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName);
+ m_mutex.unlock();
+ if (!isRunning()) {
+ start(LowPriority);
+ } else {
+ stopCollecting();
+ start(LowPriority);
+ }
+}
+
+void QHelpContentProvider::stopCollecting()
+{
+ if (!isRunning())
+ return;
+ m_mutex.lock();
+ m_abort = true;
+ m_mutex.unlock();
+ wait();
+}
+
+QHelpContentItem *QHelpContentProvider::rootItem()
+{
+ QMutexLocker locker(&m_mutex);
+ return m_rootItems.dequeue();
+}
+
+int QHelpContentProvider::nextChildCount() const
+{
+ return m_rootItems.head()->childCount();
+}
+
+void QHelpContentProvider::run()
+{
+ QString title;
+ QString link;
+ int depth = 0;
+ QHelpContentItem *item = 0;
+
+ m_mutex.lock();
+ m_rootItem = new QHelpContentItem(QString(), QString(), 0);
+ m_rootItems.enqueue(m_rootItem);
+ QStringList atts = m_filterAttributes;
+ const QStringList fileNames = m_helpEngine->orderedFileNameList;
+ m_mutex.unlock();
+
+ foreach (QString dbFileName, fileNames) {
+ m_mutex.lock();
+ if (m_abort) {
+ m_abort = false;
+ m_mutex.unlock();
+ break;
+ }
+ m_mutex.unlock();
+ QHelpDBReader reader(dbFileName,
+ QHelpGlobal::uniquifyConnectionName(dbFileName +
+ QLatin1String("FromQHelpContentProvider"),
+ QThread::currentThread()), 0);
+ if (!reader.init())
+ continue;
+ foreach (const QByteArray& ba, reader.contentsForFilter(atts)) {
+ if (ba.size() < 1)
+ continue;
+
+ int _depth = 0;
+ bool _root = false;
+ QStack<QHelpContentItem*> stack;
+
+ QDataStream s(ba);
+ for (;;) {
+ s >> depth;
+ s >> link;
+ s >> title;
+ if (title.isEmpty())
+ break;
+CHECK_DEPTH:
+ if (depth == 0) {
+ m_mutex.lock();
+ item = new QHelpContentItem(title, link,
+ m_helpEngine->fileNameReaderMap.value(dbFileName), m_rootItem);
+ m_rootItem->appendChild(item);
+ m_mutex.unlock();
+ stack.push(item);
+ _depth = 1;
+ _root = true;
+ } else {
+ if (depth > _depth && _root) {
+ _depth = depth;
+ stack.push(item);
+ }
+ if (depth == _depth) {
+ item = new QHelpContentItem(title, link,
+ m_helpEngine->fileNameReaderMap.value(dbFileName), stack.top());
+ stack.top()->appendChild(item);
+ } else if (depth < _depth) {
+ stack.pop();
+ --_depth;
+ goto CHECK_DEPTH;
+ }
+ }
+ }
+ }
+ }
+ m_mutex.lock();
+ m_abort = false;
+ m_mutex.unlock();
+}
+
+
+
+/*!
+ \class QHelpContentModel
+ \inmodule QtHelp
+ \brief The QHelpContentModel class provides a model that supplies content to views.
+ \since 4.4
+*/
+
+/*!
+ \fn void QHelpContentModel::contentsCreationStarted()
+
+ This signal is emitted when the creation of the contents has
+ started. The current contents are invalid from this point on
+ until the signal contentsCreated() is emitted.
+
+ \sa isCreatingContents()
+*/
+
+/*!
+ \fn void QHelpContentModel::contentsCreated()
+
+ This signal is emitted when the contents have been created.
+*/
+
+QHelpContentModel::QHelpContentModel(QHelpEnginePrivate *helpEngine)
+ : QAbstractItemModel(helpEngine)
+{
+ d = new QHelpContentModelPrivate();
+ d->rootItem = 0;
+ d->qhelpContentProvider = new QHelpContentProvider(helpEngine);
+
+ connect(d->qhelpContentProvider, SIGNAL(finished()),
+ this, SLOT(insertContents()), Qt::QueuedConnection);
+ connect(helpEngine->q, SIGNAL(setupStarted()), this, SLOT(invalidateContents()));
+}
+
+/*!
+ Destroys the help content model.
+*/
+QHelpContentModel::~QHelpContentModel()
+{
+ delete d->rootItem;
+ delete d;
+}
+
+void QHelpContentModel::invalidateContents(bool onShutDown)
+{
+ if (onShutDown)
+ disconnect(this, SLOT(insertContents()));
+ d->qhelpContentProvider->stopCollecting();
+ if (d->rootItem) {
+ delete d->rootItem;
+ d->rootItem = 0;
+ }
+ reset();
+}
+
+/*!
+ Creates new contents by querying the help system
+ for contents specified for the \a customFilterName.
+*/
+void QHelpContentModel::createContents(const QString &customFilterName)
+{
+ d->qhelpContentProvider->collectContents(customFilterName);
+ emit contentsCreationStarted();
+}
+
+void QHelpContentModel::insertContents()
+{
+ int count;
+ if (d->rootItem) {
+ count = d->rootItem->childCount() - 1;
+ beginRemoveRows(QModelIndex(), 0, count > 0 ? count : 0);
+ delete d->rootItem;
+ d->rootItem = 0;
+ endRemoveRows();
+ }
+
+ count = d->qhelpContentProvider->nextChildCount() - 1;
+ beginInsertRows(QModelIndex(), 0, count > 0 ? count : 0);
+ d->rootItem = d->qhelpContentProvider->rootItem();
+ endInsertRows();
+ reset();
+ emit contentsCreated();
+}
+
+/*!
+ Returns true if the contents are currently rebuilt, otherwise
+ false.
+*/
+bool QHelpContentModel::isCreatingContents() const
+{
+ return d->qhelpContentProvider->isRunning();
+}
+
+/*!
+ Returns the help content item at the model index position
+ \a index.
+*/
+QHelpContentItem *QHelpContentModel::contentItemAt(const QModelIndex &index) const
+{
+ if (index.isValid())
+ return static_cast<QHelpContentItem*>(index.internalPointer());
+ else
+ return d->rootItem;
+}
+
+/*!
+ Returns the index of the item in the model specified by
+ the given \a row, \a column and \a parent index.
+*/
+QModelIndex QHelpContentModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!d->rootItem)
+ return QModelIndex();
+
+ QHelpContentItem *parentItem = contentItemAt(parent);
+ QHelpContentItem *item = parentItem->child(row);
+ if (!item)
+ return QModelIndex();
+ return createIndex(row, column, item);
+}
+
+/*!
+ Returns the parent of the model item with the given
+ \a index, or QModelIndex() if it has no parent.
+*/
+QModelIndex QHelpContentModel::parent(const QModelIndex &index) const
+{
+ QHelpContentItem *item = contentItemAt(index);
+ if (!item)
+ return QModelIndex();
+
+ QHelpContentItem *parentItem = static_cast<QHelpContentItem*>(item->parent());
+ if (!parentItem)
+ return QModelIndex();
+
+ QHelpContentItem *grandparentItem = static_cast<QHelpContentItem*>(parentItem->parent());
+ if (!grandparentItem)
+ return QModelIndex();
+
+ int row = grandparentItem->childPosition(parentItem);
+ return createIndex(row, index.column(), parentItem);
+}
+
+/*!
+ Returns the number of rows under the given \a parent.
+*/
+int QHelpContentModel::rowCount(const QModelIndex &parent) const
+{
+ QHelpContentItem *parentItem = contentItemAt(parent);
+ if (!parentItem)
+ return 0;
+ return parentItem->childCount();
+}
+
+/*!
+ Returns the number of columns under the given \a parent. Currently returns always 1.
+*/
+int QHelpContentModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+
+ return 1;
+}
+
+/*!
+ Returns the data stored under the given \a role for
+ the item referred to by the \a index.
+*/
+QVariant QHelpContentModel::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ QHelpContentItem *item = contentItemAt(index);
+ if (!item)
+ return QVariant();
+ return item->title();
+}
+
+
+
+/*!
+ \class QHelpContentWidget
+ \inmodule QtHelp
+ \brief The QHelpContentWidget class provides a tree view for displaying help content model items.
+ \since 4.4
+*/
+
+/*!
+ \fn void QHelpContentWidget::linkActivated(const QUrl &link)
+
+ This signal is emitted when a content item is activated and
+ its associated \a link should be shown.
+*/
+
+QHelpContentWidget::QHelpContentWidget()
+ : QTreeView(0)
+{
+ header()->hide();
+ setUniformRowHeights(true);
+ connect(this, SIGNAL(activated(const QModelIndex&)),
+ this, SLOT(showLink(const QModelIndex&)));
+}
+
+/*!
+ Returns the index of the content item with the \a link.
+ An invalid index is returned if no such an item exists.
+*/
+QModelIndex QHelpContentWidget::indexOf(const QUrl &link)
+{
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(model());
+ if (!contentModel || link.scheme() != QLatin1String("qthelp"))
+ return QModelIndex();
+
+ m_syncIndex = QModelIndex();
+ for (int i=0; i<contentModel->rowCount(); ++i) {
+ QHelpContentItem *itm =
+ contentModel->contentItemAt(contentModel->index(i, 0));
+ if (itm && itm->url().host() == link.host()) {
+ QString path = link.path();
+ if (path.startsWith(QLatin1Char('/')))
+ path = path.mid(1);
+ if (searchContentItem(contentModel, contentModel->index(i, 0), path)) {
+ return m_syncIndex;
+ }
+ }
+ }
+ return QModelIndex();
+}
+
+bool QHelpContentWidget::searchContentItem(QHelpContentModel *model,
+ const QModelIndex &parent, const QString &path)
+{
+ QHelpContentItem *parentItem = model->contentItemAt(parent);
+ if (!parentItem)
+ return false;
+
+ if (QDir::cleanPath(parentItem->url().path()) == path) {
+ m_syncIndex = parent;
+ return true;
+ }
+
+ for (int i=0; i<parentItem->childCount(); ++i) {
+ if (searchContentItem(model, model->index(i, 0, parent), path))
+ return true;
+ }
+ return false;
+}
+
+void QHelpContentWidget::showLink(const QModelIndex &index)
+{
+ QHelpContentModel *contentModel = qobject_cast<QHelpContentModel*>(model());
+ if (!contentModel)
+ return;
+
+ QHelpContentItem *item = contentModel->contentItemAt(index);
+ if (!item)
+ return;
+ QUrl url = item->url();
+ if (url.isValid())
+ emit linkActivated(url);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpcontentwidget.h b/tools/assistant/lib/qhelpcontentwidget.h
new file mode 100644
index 0000000000..ceab7fe5d6
--- /dev/null
+++ b/tools/assistant/lib/qhelpcontentwidget.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPCONTENTWIDGET_H
+#define QHELPCONTENTWIDGET_H
+
+#include <QtHelp/qhelp_global.h>
+
+#include <QtCore/QQueue>
+#include <QtCore/QString>
+#include <QtGui/QTreeView>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+class QHelpEnginePrivate;
+class QHelpDBReader;
+class QHelpContentItemPrivate;
+class QHelpContentModelPrivate;
+class QHelpEngine;
+class QHelpContentProvider;
+
+class QHELP_EXPORT QHelpContentItem
+{
+public:
+ ~QHelpContentItem();
+
+ QHelpContentItem *child(int row) const;
+ int childCount() const;
+ QString title() const;
+ QUrl url() const;
+ int row() const;
+ QHelpContentItem *parent() const;
+ int childPosition(QHelpContentItem *child) const;
+
+private:
+ QHelpContentItem(const QString &name, const QString &link,
+ QHelpDBReader *reader, QHelpContentItem *parent = 0);
+ void appendChild(QHelpContentItem *child);
+
+ QHelpContentItemPrivate *d;
+ friend class QHelpContentProvider;
+};
+
+class QHELP_EXPORT QHelpContentModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ ~QHelpContentModel();
+
+ void createContents(const QString &customFilterName);
+ QHelpContentItem *contentItemAt(const QModelIndex &index) const;
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QModelIndex index(int row, int column,
+ const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &index) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ bool isCreatingContents() const;
+
+Q_SIGNALS:
+ void contentsCreationStarted();
+ void contentsCreated();
+
+private Q_SLOTS:
+ void insertContents();
+ void invalidateContents(bool onShutDown = false);
+
+private:
+ QHelpContentModel(QHelpEnginePrivate *helpEngine);
+ QHelpContentModelPrivate *d;
+ friend class QHelpEnginePrivate;
+};
+
+class QHELP_EXPORT QHelpContentWidget : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ QModelIndex indexOf(const QUrl &link);
+
+Q_SIGNALS:
+ void linkActivated(const QUrl &link);
+
+private Q_SLOTS:
+ void showLink(const QModelIndex &index);
+
+private:
+ bool searchContentItem(QHelpContentModel *model,
+ const QModelIndex &parent, const QString &path);
+ QModelIndex m_syncIndex;
+
+private:
+ QHelpContentWidget();
+ friend class QHelpEngine;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
+
diff --git a/tools/assistant/lib/qhelpdatainterface.cpp b/tools/assistant/lib/qhelpdatainterface.cpp
new file mode 100644
index 0000000000..001c059cba
--- /dev/null
+++ b/tools/assistant/lib/qhelpdatainterface.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpdatainterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QHelpDataContentItem
+ \since 4.4
+ \brief The QHelpDataContentItem class provides an item which represents
+ a topic or section of the contents.
+
+ Every item holds several pieces of information, most notably the title
+ which can later be displayed in a contents overview. The reference is used
+ to store a relative file link to the corresponding section in the
+ documentation.
+*/
+
+/*!
+ Constructs a new content item with \a parent as parent item.
+ The constucted item has the title \a title and links to the
+ location specified by \a reference.
+*/
+QHelpDataContentItem::QHelpDataContentItem(QHelpDataContentItem *parent,
+ const QString &title, const QString &reference)
+ : m_title(title), m_reference(reference)
+{
+ if (parent)
+ parent->m_children.append(this);
+}
+
+/*!
+ Destructs the item and its children.
+*/
+QHelpDataContentItem::~QHelpDataContentItem()
+{
+ qDeleteAll(m_children);
+}
+
+/*!
+ Returns the title of the item.
+*/
+QString QHelpDataContentItem::title() const
+{
+ return m_title;
+}
+
+/*!
+ Returns the file reference of the item.
+*/
+QString QHelpDataContentItem::reference() const
+{
+ return m_reference;
+}
+
+/*!
+ Returns a list of all its child items.
+*/
+QList<QHelpDataContentItem*> QHelpDataContentItem::children() const
+{
+ return m_children;
+}
+
+bool QHelpDataIndexItem::operator==(const QHelpDataIndexItem & other) const
+{
+ return (other.name == name)
+ && (other.reference == reference);
+}
+
+
+
+/*!
+ \internal
+ \class QHelpDataFilterSection
+ \since 4.4
+*/
+
+/*!
+ Constructs a help data filter section.
+*/
+QHelpDataFilterSection::QHelpDataFilterSection()
+{
+ d = new QHelpDataFilterSectionData();
+}
+
+/*!
+ Adds the filter attribute \a filter to the filter attributes of
+ this section.
+*/
+void QHelpDataFilterSection::addFilterAttribute(const QString &filter)
+{
+ d->filterAttributes.append(filter);
+}
+
+/*!
+ Returns a list of all filter attributes defined for this section.
+*/
+QStringList QHelpDataFilterSection::filterAttributes() const
+{
+ return d->filterAttributes;
+}
+
+/*!
+ Adds the index item \a index to the list of indices.
+*/
+void QHelpDataFilterSection::addIndex(const QHelpDataIndexItem &index)
+{
+ d->indices.append(index);
+}
+
+/*!
+ Sets the filter sections list of indices to \a indices.
+*/
+void QHelpDataFilterSection::setIndices(const QList<QHelpDataIndexItem> &indices)
+{
+ d->indices = indices;
+}
+
+/*!
+ Returns the list of indices.
+*/
+QList<QHelpDataIndexItem> QHelpDataFilterSection::indices() const
+{
+ return d->indices;
+}
+
+/*!
+ Adds the top level content item \a content to the filter section.
+*/
+void QHelpDataFilterSection::addContent(QHelpDataContentItem *content)
+{
+ d->contents.append(content);
+}
+
+/*!
+ Sets the list of top level content items of the filter section to
+ \a contents.
+*/
+void QHelpDataFilterSection::setContents(const QList<QHelpDataContentItem*> &contents)
+{
+ qDeleteAll(d->contents);
+ d->contents = contents;
+}
+
+/*!
+ Returns a list of top level content items.
+*/
+QList<QHelpDataContentItem*> QHelpDataFilterSection::contents() const
+{
+ return d->contents;
+}
+
+/*!
+ Adds the file \a file to the filter section.
+*/
+void QHelpDataFilterSection::addFile(const QString &file)
+{
+ d->files.append(file);
+}
+
+/*!
+ Set the list of files to \a files.
+*/
+void QHelpDataFilterSection::setFiles(const QStringList &files)
+{
+ d->files = files;
+}
+
+/*!
+ Returns the list of files.
+*/
+QStringList QHelpDataFilterSection::files() const
+{
+ return d->files;
+}
+
+/*!
+ \internal
+ \class QHelpDataInterface
+ \since 4.4
+*/
+
+/*!
+ \fn QHelpDataInterface::QHelpDataInterface()
+
+ Constructs a new help data interface.
+*/
+
+/*!
+ \fn QHelpDataInterface::~QHelpDataInterface()
+
+ Destroys the help data interface.
+*/
+
+/*!
+ \fn QString QHelpDataInterface::namespaceName() const = 0
+
+ Returns the namespace name of the help data set.
+*/
+
+/*!
+ \fn QString QHelpDataInterface::virtualFolder() const = 0
+
+ Returns the virtual folder of the help data set.
+*/
+
+/*!
+ \fn QList<QHelpDataCustomFilter> QHelpDataInterface::customFilters () const = 0
+
+ Returns a list of custom filters. Defining custom filters is optional.
+*/
+
+/*!
+ \fn QList<QHelpDataFilterSection> QHelpDataInterface::filterSections() const = 0
+
+ Returns a list of filter sections.
+*/
+
+/*!
+ \fn QMap<QString, QVariant> QHelpDataInterface::metaData() const = 0
+
+ Returns a map of meta data. A meta data item can hold almost any data
+ and is identified by its name.
+*/
+
+/*!
+ \fn QString QHelpDataInterface::rootPath() const = 0
+
+ Returns the root file path of the documentation data. All referenced file
+ path or links of content items are relative to this path.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpdatainterface_p.h b/tools/assistant/lib/qhelpdatainterface_p.h
new file mode 100644
index 0000000000..2d05cc6335
--- /dev/null
+++ b/tools/assistant/lib/qhelpdatainterface_p.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPDATAINTERFACE_H
+#define QHELPDATAINTERFACE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhelp_global.h"
+
+#include <QtCore/QStringList>
+#include <QtCore/QSharedData>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QHELP_EXPORT QHelpDataContentItem
+{
+public:
+ QHelpDataContentItem(QHelpDataContentItem *parent, const QString &title,
+ const QString &reference);
+ ~QHelpDataContentItem();
+
+ QString title() const;
+ QString reference() const;
+ QList<QHelpDataContentItem*> children() const;
+
+private:
+ QString m_title;
+ QString m_reference;
+ QList<QHelpDataContentItem*> m_children;
+};
+
+struct QHELP_EXPORT QHelpDataIndexItem {
+ QHelpDataIndexItem() {}
+ QHelpDataIndexItem(const QString &n, const QString &id, const QString &r)
+ : name(n), identifier(id), reference(r) {}
+
+ QString name;
+ QString identifier;
+ QString reference;
+
+ bool operator==(const QHelpDataIndexItem & other) const;
+};
+
+class QHelpDataFilterSectionData : public QSharedData
+{
+public:
+ ~QHelpDataFilterSectionData()
+ {
+ qDeleteAll(contents);
+ }
+
+ QStringList filterAttributes;
+ QList<QHelpDataIndexItem> indices;
+ QList<QHelpDataContentItem*> contents;
+ QStringList files;
+};
+
+class QHELP_EXPORT QHelpDataFilterSection
+{
+public:
+ QHelpDataFilterSection();
+
+ void addFilterAttribute(const QString &filter);
+ QStringList filterAttributes() const;
+
+ void addIndex(const QHelpDataIndexItem &index);
+ void setIndices(const QList<QHelpDataIndexItem> &indices);
+ QList<QHelpDataIndexItem> indices() const;
+
+ void addContent(QHelpDataContentItem *content);
+ void setContents(const QList<QHelpDataContentItem*> &contents);
+ QList<QHelpDataContentItem*> contents() const;
+
+ void addFile(const QString &file);
+ void setFiles(const QStringList &files);
+ QStringList files() const;
+
+private:
+ QSharedDataPointer<QHelpDataFilterSectionData> d;
+};
+
+struct QHELP_EXPORT QHelpDataCustomFilter {
+ QStringList filterAttributes;
+ QString name;
+};
+
+class QHELP_EXPORT QHelpDataInterface
+{
+public:
+ QHelpDataInterface() {}
+ virtual ~QHelpDataInterface() {}
+
+ virtual QString namespaceName() const = 0;
+ virtual QString virtualFolder() const = 0;
+ virtual QList<QHelpDataCustomFilter> customFilters() const = 0;
+ virtual QList<QHelpDataFilterSection> filterSections() const = 0;
+ virtual QMap<QString, QVariant> metaData() const = 0;
+ virtual QString rootPath() const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QHELPDATAINTERFACE_H
diff --git a/tools/assistant/lib/qhelpdbreader.cpp b/tools/assistant/lib/qhelpdbreader.cpp
new file mode 100644
index 0000000000..76994a759f
--- /dev/null
+++ b/tools/assistant/lib/qhelpdbreader.cpp
@@ -0,0 +1,580 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpdbreader_p.h"
+#include "qhelp_global.h"
+
+#include <QtCore/QVariant>
+#include <QtCore/QFile>
+#include <QtSql/QSqlError>
+#include <QtSql/QSqlQuery>
+
+QT_BEGIN_NAMESPACE
+
+QHelpDBReader::QHelpDBReader(const QString &dbName)
+ : QObject(0)
+{
+ initObject(dbName,
+ QHelpGlobal::uniquifyConnectionName(QLatin1String("QHelpDBReader"),
+ this));
+}
+
+QHelpDBReader::QHelpDBReader(const QString &dbName, const QString &uniqueId,
+ QObject *parent)
+ : QObject(parent)
+{
+ initObject(dbName, uniqueId);
+}
+
+void QHelpDBReader::initObject(const QString &dbName, const QString &uniqueId)
+{
+ m_dbName = dbName;
+ m_uniqueId = uniqueId;
+ m_initDone = false;
+ m_query = 0;
+ m_useAttributesCache = false;
+}
+
+QHelpDBReader::~QHelpDBReader()
+{
+ if (m_initDone) {
+ delete m_query;
+ QSqlDatabase::removeDatabase(m_uniqueId);
+ }
+}
+
+bool QHelpDBReader::init()
+{
+ if (m_initDone)
+ return true;
+
+ if (!QFile::exists(m_dbName))
+ return false;
+
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), m_uniqueId);
+ db.setDatabaseName(m_dbName);
+ if (!db.open()) {
+ m_error = tr("Cannot open database '%1' '%2': %3").arg(m_dbName, m_uniqueId, db.lastError().text());
+ QSqlDatabase::removeDatabase(m_uniqueId);
+ return false;
+ }
+
+ m_initDone = true;
+ m_query = new QSqlQuery(db);
+
+ return true;
+}
+
+QString QHelpDBReader::databaseName() const
+{
+ return m_dbName;
+}
+
+QString QHelpDBReader::errorMessage() const
+{
+ return m_error;
+}
+
+QString QHelpDBReader::namespaceName() const
+{
+ if (!m_namespace.isEmpty())
+ return m_namespace;
+ if (m_query) {
+ m_query->exec(QLatin1String("SELECT Name FROM NamespaceTable"));
+ if (m_query->next())
+ m_namespace = m_query->value(0).toString();
+ }
+ return m_namespace;
+}
+
+QString QHelpDBReader::virtualFolder() const
+{
+ if (m_query) {
+ m_query->exec(QLatin1String("SELECT Name FROM FolderTable WHERE Id=1"));
+ if (m_query->next())
+ return m_query->value(0).toString();
+ }
+ return QString();
+}
+
+QList<QStringList> QHelpDBReader::filterAttributeSets() const
+{
+ QList<QStringList> result;
+ if (m_query) {
+ m_query->exec(QLatin1String("SELECT a.Id, b.Name FROM FileAttributeSetTable a, "
+ "FilterAttributeTable b WHERE a.FilterAttributeId=b.Id ORDER BY a.Id"));
+ int oldId = -1;
+ while (m_query->next()) {
+ int id = m_query->value(0).toInt();
+ if (id != oldId) {
+ result.append(QStringList());
+ oldId = id;
+ }
+ result.last().append(m_query->value(1).toString());
+ }
+ }
+ return result;
+}
+
+bool QHelpDBReader::fileExists(const QString &virtualFolder,
+ const QString &filePath,
+ const QStringList &filterAttributes) const
+{
+ if (virtualFolder.isEmpty() || filePath.isEmpty() || !m_query)
+ return false;
+
+//SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b, FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id AND b.Name='qtdoc' AND a.Name='qstring.html' AND a.FileId=c.FileId AND c.FilterAttributeId=d.Id AND d.Name='qtrefdoc'
+
+ QString query;
+ namespaceName();
+ if (filterAttributes.isEmpty()) {
+ query = QString(QLatin1String("SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b "
+ "WHERE a.FolderId=b.Id AND b.Name=\'%1\' AND a.Name=\'%2\'")).arg(quote(virtualFolder)).arg(quote(filePath));
+ } else {
+ query = QString(QLatin1String("SELECT COUNT(a.Name) FROM FileNameTable a, FolderTable b, "
+ "FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id "
+ "AND b.Name=\'%1\' AND a.Name=\'%2\' AND a.FileId=c.FileId AND "
+ "c.FilterAttributeId=d.Id AND d.Name=\'%3\'"))
+ .arg(quote(virtualFolder)).arg(quote(filePath))
+ .arg(quote(filterAttributes.first()));
+ for (int i=1; i<filterAttributes.count(); ++i) {
+ query.append(QString(QLatin1String(" INTERSECT SELECT COUNT(a.Name) FROM FileNameTable a, "
+ "FolderTable b, FileFilterTable c, FilterAttributeTable d WHERE a.FolderId=b.Id "
+ "AND b.Name=\'%1\' AND a.Name=\'%2\' AND a.FileId=c.FileId AND "
+ "c.FilterAttributeId=d.Id AND d.Name=\'%3\'"))
+ .arg(quote(virtualFolder)).arg(quote(filePath))
+ .arg(quote(filterAttributes.at(i))));
+ }
+ }
+ m_query->exec(query);
+ if (m_query->next() && m_query->isValid() && m_query->value(0).toInt())
+ return true;
+ return false;
+}
+
+QByteArray QHelpDBReader::fileData(const QString &virtualFolder,
+ const QString &filePath) const
+{
+ QByteArray ba;
+ if (virtualFolder.isEmpty() || filePath.isEmpty() || !m_query)
+ return ba;
+
+ namespaceName();
+ m_query->prepare(QLatin1String("SELECT a.Data FROM FileDataTable a, FileNameTable b, FolderTable c, "
+ "NamespaceTable d WHERE a.Id=b.FileId AND (b.Name=? OR b.Name=?) AND b.FolderId=c.Id "
+ "AND c.Name=? AND c.NamespaceId=d.Id AND d.Name=?"));
+ m_query->bindValue(0, filePath);
+ m_query->bindValue(1, QLatin1String("./") + filePath);
+ m_query->bindValue(2, virtualFolder);
+ m_query->bindValue(3, m_namespace);
+ m_query->exec();
+ if (m_query->next() && m_query->isValid())
+ ba = qUncompress(m_query->value(0).toByteArray());
+ return ba;
+}
+
+QStringList QHelpDBReader::customFilters() const
+{
+ QStringList lst;
+ if (m_query) {
+ m_query->exec(QLatin1String("SELECT Name FROM FilterNameTable"));
+ while (m_query->next())
+ lst.append(m_query->value(0).toString());
+ }
+ return lst;
+}
+
+QStringList QHelpDBReader::filterAttributes(const QString &filterName) const
+{
+ QStringList lst;
+ if (m_query) {
+ if (filterName.isEmpty()) {
+ m_query->prepare(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ } else {
+ m_query->prepare(QLatin1String("SELECT a.Name FROM FilterAttributeTable a, "
+ "FilterTable b, FilterNameTable c WHERE c.Name=? "
+ "AND c.Id=b.NameId AND b.FilterAttributeId=a.Id"));
+ m_query->bindValue(0, filterName);
+ }
+ m_query->exec();
+ while (m_query->next())
+ lst.append(m_query->value(0).toString());
+ }
+ return lst;
+}
+
+QStringList QHelpDBReader::indicesForFilter(const QStringList &filterAttributes) const
+{
+ QStringList indices;
+ if (!m_query)
+ return indices;
+
+ //SELECT DISTINCT a.Name FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId AND b.FilterAttributeId=c.Id AND c.Name in ('4.2.3', 'qt')
+
+ QString query;
+ if (filterAttributes.isEmpty()) {
+ query = QLatin1String("SELECT DISTINCT Name FROM IndexTable");
+ } else {
+ query = QString(QLatin1String("SELECT DISTINCT a.Name FROM IndexTable a, "
+ "IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId "
+ "AND b.FilterAttributeId=c.Id AND c.Name='%1'")).arg(quote(filterAttributes.first()));
+ for (int i=1; i<filterAttributes.count(); ++i) {
+ query.append(QString(QLatin1String(" INTERSECT SELECT DISTINCT a.Name FROM IndexTable a, "
+ "IndexFilterTable b, FilterAttributeTable c WHERE a.Id=b.IndexId "
+ "AND b.FilterAttributeId=c.Id AND c.Name='%1'"))
+ .arg(quote(filterAttributes.at(i))));
+ }
+ }
+
+ m_query->exec(query);
+ while (m_query->next()) {
+ if (!m_query->value(0).toString().isEmpty())
+ indices.append(m_query->value(0).toString());
+ }
+ return indices;
+}
+
+void QHelpDBReader::linksForKeyword(const QString &keyword, const QStringList &filterAttributes,
+ QMap<QString, QUrl> &linkMap) const
+{
+ if (!m_query)
+ return;
+
+ QString query;
+ if (filterAttributes.isEmpty()) {
+ query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
+ "FROM IndexTable a, FileNameTable d, "
+ "FolderTable e, NamespaceTable f WHERE "
+ "a.FileId=d.FileId AND d.FolderId=e.Id AND a.NamespaceId=f.Id "
+ "AND a.Name='%1'")).arg(quote(keyword));
+ } else if (m_useAttributesCache) {
+ query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor, a.Id "
+ "FROM IndexTable a, "
+ "FileNameTable d, FolderTable e, NamespaceTable f WHERE "
+ "a.FileId=d.FileId AND d.FolderId=e.Id "
+ "AND a.NamespaceId=f.Id AND a.Name='%1'"))
+ .arg(quote(keyword));
+ m_query->exec(query);
+ while (m_query->next()) {
+ if (m_indicesCache.contains(m_query->value(5).toInt())) {
+ linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(),
+ m_query->value(2).toString(), m_query->value(3).toString(),
+ m_query->value(4).toString()));
+ }
+ }
+ return;
+ } else {
+ query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
+ "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, "
+ "FileNameTable d, FolderTable e, NamespaceTable f "
+ "WHERE a.FileId=d.FileId AND d.FolderId=e.Id "
+ "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id "
+ "AND a.Name='%1' AND c.Name='%2'")).arg(quote(keyword))
+ .arg(quote(filterAttributes.first()));
+ for (int i=1; i<filterAttributes.count(); ++i) {
+ query.append(QString(QLatin1String(" INTERSECT SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
+ "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, "
+ "FileNameTable d, FolderTable e, NamespaceTable f "
+ "WHERE a.FileId=d.FileId AND d.FolderId=e.Id "
+ "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id "
+ "AND a.Name='%1' AND c.Name='%2'")).arg(quote(keyword))
+ .arg(quote(filterAttributes.at(i))));
+ }
+ }
+
+ QString title;
+ m_query->exec(query);
+ while (m_query->next()) {
+ title = m_query->value(0).toString();
+ if (title.isEmpty()) // generate a title + corresponding path
+ title = keyword + QLatin1String(" : ") + m_query->value(3).toString();
+ linkMap.insertMulti(title, buildQUrl(m_query->value(1).toString(),
+ m_query->value(2).toString(), m_query->value(3).toString(),
+ m_query->value(4).toString()));
+ }
+}
+
+void QHelpDBReader::linksForIdentifier(const QString &id,
+ const QStringList &filterAttributes,
+ QMap<QString, QUrl> &linkMap) const
+{
+ if (!m_query)
+ return;
+
+ QString query;
+ if (filterAttributes.isEmpty()) {
+ query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
+ "FROM IndexTable a, FileNameTable d, FolderTable e, "
+ "NamespaceTable f WHERE a.FileId=d.FileId AND "
+ "d.FolderId=e.Id AND a.NamespaceId=f.Id AND a.Identifier='%1'"))
+ .arg(quote(id));
+ } else if (m_useAttributesCache) {
+ query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor, a.Id "
+ "FROM IndexTable a,"
+ "FileNameTable d, FolderTable e, NamespaceTable f WHERE "
+ "a.FileId=d.FileId AND d.FolderId=e.Id "
+ "AND a.NamespaceId=f.Id AND a.Identifier='%1'"))
+ .arg(quote(id));
+ m_query->exec(query);
+ while (m_query->next()) {
+ if (m_indicesCache.contains(m_query->value(5).toInt())) {
+ linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(),
+ m_query->value(2).toString(), m_query->value(3).toString(),
+ m_query->value(4).toString()));
+ }
+ }
+ return;
+ } else {
+ query = QString(QLatin1String("SELECT d.Title, f.Name, e.Name, d.Name, a.Anchor "
+ "FROM IndexTable a, IndexFilterTable b, FilterAttributeTable c, "
+ "FileNameTable d, FolderTable e, NamespaceTable f "
+ "WHERE a.FileId=d.FileId AND d.FolderId=e.Id "
+ "AND a.NamespaceId=f.Id AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id "
+ "AND a.Identifier='%1' AND c.Name='%2'")).arg(quote(id))
+ .arg(quote(filterAttributes.first()));
+ for (int i=0; i<filterAttributes.count(); ++i) {
+ query.append(QString(QLatin1String(" INTERSECT SELECT d.Title, f.Name, e.Name, "
+ "d.Name, a.Anchor FROM IndexTable a, IndexFilterTable b, "
+ "FilterAttributeTable c, FileNameTable d, "
+ "FolderTable e, NamespaceTable f WHERE "
+ "a.FileId=d.FileId AND d.FolderId=e.Id AND a.NamespaceId=f.Id "
+ "AND b.IndexId=a.Id AND b.FilterAttributeId=c.Id AND "
+ "a.Identifier='%1' AND c.Name='%2'")).arg(quote(id))
+ .arg(quote(filterAttributes.at(i))));
+ }
+ }
+
+ m_query->exec(query);
+ while (m_query->next()) {
+ linkMap.insertMulti(m_query->value(0).toString(), buildQUrl(m_query->value(1).toString(),
+ m_query->value(2).toString(), m_query->value(3).toString(),
+ m_query->value(4).toString()));
+ }
+}
+
+QUrl QHelpDBReader::buildQUrl(const QString &ns, const QString &folder,
+ const QString &relFileName, const QString &anchor) const
+{
+ QUrl url;
+ url.setScheme(QLatin1String("qthelp"));
+ url.setAuthority(ns);
+ url.setPath(folder + QLatin1Char('/') + relFileName);
+ url.setFragment(anchor);
+ return url;
+}
+
+QList<QByteArray> QHelpDBReader::contentsForFilter(const QStringList &filterAttributes) const
+{
+ QList<QByteArray> contents;
+ if (!m_query)
+ return contents;
+
+ //SELECT DISTINCT a.Data FROM ContentsTable a, ContentsFilterTable b, FilterAttributeTable c WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id AND c.Name='qt' INTERSECT SELECT DISTINCT a.Data FROM ContentsTable a, ContentsFilterTable b, FilterAttributeTable c WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id AND c.Name='3.3.8';
+
+ QString query;
+ if (filterAttributes.isEmpty()) {
+ query = QLatin1String("SELECT Data from ContentsTable");
+ } else {
+ query = QString(QLatin1String("SELECT a.Data FROM ContentsTable a, "
+ "ContentsFilterTable b, FilterAttributeTable c "
+ "WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id "
+ "AND c.Name='%1'")).arg(quote(filterAttributes.first()));
+ for (int i=1; i<filterAttributes.count(); ++i) {
+ query.append(QString(QLatin1String(" INTERSECT SELECT a.Data FROM ContentsTable a, "
+ "ContentsFilterTable b, FilterAttributeTable c "
+ "WHERE a.Id=b.ContentsId AND b.FilterAttributeId=c.Id "
+ "AND c.Name='%1'")).arg(quote(filterAttributes.at(i))));
+ }
+ }
+
+ m_query->exec(query);
+ while (m_query->next()) {
+ contents.append(m_query->value(0).toByteArray());
+ }
+ return contents;
+}
+
+QUrl QHelpDBReader::urlOfPath(const QString &relativePath) const
+{
+ QUrl url;
+ if (!m_query)
+ return url;
+
+ m_query->exec(QLatin1String("SELECT a.Name, b.Name FROM NamespaceTable a, "
+ "FolderTable b WHERE a.id=b.NamespaceId and a.Id=1"));
+ if (m_query->next()) {
+ QString rp = relativePath;
+ QString anchor;
+ int i = rp.indexOf(QLatin1Char('#'));
+ if (i > -1) {
+ rp = relativePath.left(i);
+ anchor = relativePath.mid(i+1);
+ }
+ url = buildQUrl(m_query->value(0).toString(),
+ m_query->value(1).toString(), rp, anchor);
+ }
+ return url;
+}
+
+QStringList QHelpDBReader::files(const QStringList &filterAttributes,
+ const QString &extensionFilter) const
+{
+ QStringList lst;
+ if (!m_query)
+ return lst;
+
+ QString query;
+ QString extension;
+ if (!extensionFilter.isEmpty())
+ extension = QString(QLatin1String("AND b.Name like \'%.%1\'")).arg(extensionFilter);
+
+ if (filterAttributes.isEmpty()) {
+ query = QString(QLatin1String("SELECT a.Name, b.Name FROM FolderTable a, "
+ "FileNameTable b WHERE b.FolderId=a.Id %1"))
+ .arg(extension);
+ } else {
+ query = QString(QLatin1String("SELECT a.Name, b.Name FROM FolderTable a, "
+ "FileNameTable b, FileFilterTable c, FilterAttributeTable d "
+ "WHERE b.FolderId=a.Id AND b.FileId=c.FileId "
+ "AND c.FilterAttributeId=d.Id AND d.Name=\'%1\' %2"))
+ .arg(quote(filterAttributes.first())).arg(extension);
+ for (int i=1; i<filterAttributes.count(); ++i) {
+ query.append(QString(QLatin1String(" INTERSECT SELECT a.Name, b.Name FROM "
+ "FolderTable a, FileNameTable b, FileFilterTable c, "
+ "FilterAttributeTable d WHERE b.FolderId=a.Id AND "
+ "b.FileId=c.FileId AND c.FilterAttributeId=d.Id AND "
+ "d.Name=\'%1\' %2")).arg(quote(filterAttributes.at(i)))
+ .arg(extension));
+ }
+ }
+ m_query->exec(query);
+ while (m_query->next()) {
+ lst.append(m_query->value(0).toString() + QLatin1Char('/')
+ + m_query->value(1).toString());
+ }
+
+ return lst;
+}
+
+QVariant QHelpDBReader::metaData(const QString &name) const
+{
+ QVariant v;
+ if (!m_query)
+ return v;
+
+ m_query->prepare(QLatin1String("SELECT COUNT(Value), Value FROM MetaDataTable "
+ "WHERE Name=?"));
+ m_query->bindValue(0, name);
+ if (m_query->exec() && m_query->next()
+ && m_query->value(0).toInt() == 1)
+ v = m_query->value(1);
+ return v;
+}
+
+QString QHelpDBReader::mergeList(const QStringList &list) const
+{
+ QString str;
+ foreach (QString s, list)
+ str.append(QLatin1Char('\'') + quote(s) + QLatin1String("\', "));
+ if (str.endsWith(QLatin1String(", ")))
+ str = str.left(str.length()-2);
+ return str;
+}
+
+QString QHelpDBReader::quote(const QString &string) const
+{
+ QString s = string;
+ s.replace(QLatin1Char('\''), QLatin1String("\'\'"));
+ return s;
+}
+
+QSet<int> QHelpDBReader::indexIds(const QStringList &attributes) const
+{
+ QSet<int> ids;
+
+ if (attributes.isEmpty())
+ return ids;
+
+ QString query = QString(QLatin1String("SELECT a.IndexId FROM IndexFilterTable a, "
+ "FilterAttributeTable b WHERE a.FilterAttributeId=b.Id "
+ "AND b.Name='%1'")).arg(attributes.first());
+ for (int i=0; i<attributes.count(); ++i) {
+ query.append(QString(QLatin1String(" INTERSECT SELECT a.IndexId FROM "
+ "IndexFilterTable a, FilterAttributeTable b WHERE "
+ "a.FilterAttributeId=b.Id AND b.Name='%1'"))
+ .arg(attributes.at(i)));
+ }
+
+ if (!m_query->exec(query))
+ return ids;
+
+ while (m_query->next())
+ ids.insert(m_query->value(0).toInt());
+
+ return ids;
+}
+
+bool QHelpDBReader::createAttributesCache(const QStringList &attributes,
+ const QSet<int> &indexIds)
+{
+ m_useAttributesCache = false;
+
+ if (attributes.count() < 2) {
+ m_viewAttributes.clear();
+ return true;
+ }
+
+ bool needUpdate = !m_viewAttributes.count();
+
+ foreach (QString s, attributes)
+ m_viewAttributes.remove(s);
+
+ if (m_viewAttributes.count() || needUpdate) {
+ m_viewAttributes.clear();
+ m_indicesCache = indexIds;
+ }
+ foreach (QString s, attributes)
+ m_viewAttributes.insert(s);
+ m_useAttributesCache = true;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpdbreader_p.h b/tools/assistant/lib/qhelpdbreader_p.h
new file mode 100644
index 0000000000..08fc382b86
--- /dev/null
+++ b/tools/assistant/lib/qhelpdbreader_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPDBREADER_H
+#define QHELPDBREADER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+#include <QtCore/QByteArray>
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+class QSqlQuery;
+
+class QHelpDBReader : public QObject
+{
+ Q_OBJECT
+
+public:
+ QHelpDBReader(const QString &dbName);
+ QHelpDBReader(const QString &dbName, const QString &uniqueId,
+ QObject *parent);
+ ~QHelpDBReader();
+
+ bool init();
+
+ QString errorMessage() const;
+
+ QString databaseName() const;
+ QString namespaceName() const;
+ QString virtualFolder() const;
+ QList<QStringList> filterAttributeSets() const;
+ QStringList files(const QStringList &filterAttributes,
+ const QString &extensionFilter = QString()) const;
+ bool fileExists(const QString &virtualFolder, const QString &filePath,
+ const QStringList &filterAttributes = QStringList()) const;
+ QByteArray fileData(const QString &virtualFolder,
+ const QString &filePath) const;
+
+ QStringList customFilters() const;
+ QStringList filterAttributes(const QString &filterName = QString()) const;
+ QStringList indicesForFilter(const QStringList &filterAttributes) const;
+ void linksForKeyword(const QString &keyword, const QStringList &filterAttributes,
+ QMap<QString, QUrl> &linkMap) const;
+
+ void linksForIdentifier(const QString &id, const QStringList &filterAttributes,
+ QMap<QString, QUrl> &linkMap) const;
+
+ QList<QByteArray> contentsForFilter(const QStringList &filterAttributes) const;
+ QUrl urlOfPath(const QString &relativePath) const;
+
+ QSet<int> indexIds(const QStringList &attributes) const;
+ bool createAttributesCache(const QStringList &attributes,
+ const QSet<int> &indexIds);
+ QVariant metaData(const QString &name) const;
+
+private:
+ void initObject(const QString &dbName, const QString &uniqueId);
+ QUrl buildQUrl(const QString &ns, const QString &folder,
+ const QString &relFileName, const QString &anchor) const;
+ QString mergeList(const QStringList &list) const;
+ QString quote(const QString &string) const;
+
+ bool m_initDone;
+ QString m_dbName;
+ QString m_uniqueId;
+ QString m_error;
+ QSqlQuery *m_query;
+ mutable QString m_namespace;
+ QSet<QString> m_viewAttributes;
+ bool m_useAttributesCache;
+ QSet<int> m_indicesCache;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/lib/qhelpengine.cpp b/tools/assistant/lib/qhelpengine.cpp
new file mode 100644
index 0000000000..6a603b7284
--- /dev/null
+++ b/tools/assistant/lib/qhelpengine.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpengine.h"
+#include "qhelpengine_p.h"
+#include "qhelpdbreader_p.h"
+#include "qhelpcontentwidget.h"
+#include "qhelpindexwidget.h"
+#include "qhelpsearchengine.h"
+#include "qhelpcollectionhandler_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QLibrary>
+#include <QtCore/QPluginLoader>
+#include <QtGui/QApplication>
+#include <QtSql/QSqlQuery>
+
+QT_BEGIN_NAMESPACE
+
+QHelpEnginePrivate::QHelpEnginePrivate()
+ : QHelpEngineCorePrivate()
+ , contentModel(0)
+ , contentWidget(0)
+ , indexModel(0)
+ , indexWidget(0)
+ , searchEngine(0)
+{
+}
+
+QHelpEnginePrivate::~QHelpEnginePrivate()
+{
+}
+
+void QHelpEnginePrivate::init(const QString &collectionFile,
+ QHelpEngineCore *helpEngineCore)
+{
+ QHelpEngineCorePrivate::init(collectionFile, helpEngineCore);
+
+ contentModel = new QHelpContentModel(this);
+ indexModel = new QHelpIndexModel(this);
+
+ connect(helpEngineCore, SIGNAL(setupFinished()),
+ this, SLOT(applyCurrentFilter()));
+ connect(helpEngineCore, SIGNAL(currentFilterChanged(const QString&)),
+ this, SLOT(applyCurrentFilter()));
+
+}
+
+void QHelpEnginePrivate::applyCurrentFilter()
+{
+ if (!error.isEmpty())
+ return;
+ contentModel->createContents(currentFilter);
+ indexModel->createIndex(currentFilter);
+}
+
+void QHelpEnginePrivate::setContentsWidgetBusy()
+{
+ contentWidget->setCursor(Qt::WaitCursor);
+}
+
+void QHelpEnginePrivate::unsetContentsWidgetBusy()
+{
+ contentWidget->unsetCursor();
+}
+
+void QHelpEnginePrivate::setIndexWidgetBusy()
+{
+ indexWidget->setCursor(Qt::WaitCursor);
+}
+
+void QHelpEnginePrivate::unsetIndexWidgetBusy()
+{
+ indexWidget->unsetCursor();
+}
+
+void QHelpEnginePrivate::stopDataCollection()
+{
+ contentModel->invalidateContents(true);
+ indexModel->invalidateIndex(true);
+}
+
+
+
+/*!
+ \class QHelpEngine
+ \since 4.4
+ \inmodule QtHelp
+ \brief The QHelpEngine class provides access to contents and
+ indices of the help engine.
+
+
+*/
+
+/*!
+ Constructs a new help engine with the given \a parent. The help
+ engine uses the information stored in the \a collectionFile for
+ providing help. If the collection file does not already exist,
+ it will be created.
+*/
+QHelpEngine::QHelpEngine(const QString &collectionFile, QObject *parent)
+ : QHelpEngineCore(d = new QHelpEnginePrivate(), parent)
+{
+ d->init(collectionFile, this);
+}
+
+/*!
+ Destroys the help engine object.
+*/
+QHelpEngine::~QHelpEngine()
+{
+ d->stopDataCollection();
+}
+
+/*!
+ Returns the content model.
+*/
+QHelpContentModel *QHelpEngine::contentModel() const
+{
+ return d->contentModel;
+}
+
+/*!
+ Returns the index model.
+*/
+QHelpIndexModel *QHelpEngine::indexModel() const
+{
+ return d->indexModel;
+}
+
+/*!
+ Returns the content widget.
+*/
+QHelpContentWidget *QHelpEngine::contentWidget()
+{
+ if (!d->contentWidget) {
+ d->contentWidget = new QHelpContentWidget();
+ d->contentWidget->setModel(d->contentModel);
+ connect(d->contentModel, SIGNAL(contentsCreationStarted()),
+ d, SLOT(setContentsWidgetBusy()));
+ connect(d->contentModel, SIGNAL(contentsCreated()),
+ d, SLOT(unsetContentsWidgetBusy()));
+ }
+ return d->contentWidget;
+}
+
+/*!
+ Returns the index widget.
+*/
+QHelpIndexWidget *QHelpEngine::indexWidget()
+{
+ if (!d->indexWidget) {
+ d->indexWidget = new QHelpIndexWidget();
+ d->indexWidget->setModel(d->indexModel);
+ connect(d->indexModel, SIGNAL(indexCreationStarted()),
+ d, SLOT(setIndexWidgetBusy()));
+ connect(d->indexModel, SIGNAL(indexCreated()),
+ d, SLOT(unsetIndexWidgetBusy()));
+ }
+ return d->indexWidget;
+}
+
+/*!
+ Returns the default search engine.
+*/
+QHelpSearchEngine* QHelpEngine::searchEngine()
+{
+ if (!d->searchEngine)
+ d->searchEngine = new QHelpSearchEngine(this, this);
+ return d->searchEngine;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpengine.h b/tools/assistant/lib/qhelpengine.h
new file mode 100644
index 0000000000..9c80ff312d
--- /dev/null
+++ b/tools/assistant/lib/qhelpengine.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPENGINE_H
+#define QHELPENGINE_H
+
+#include <QtHelp/qhelpenginecore.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+class QHelpContentModel;
+class QHelpContentWidget;
+class QHelpIndexModel;
+class QHelpIndexWidget;
+class QHelpEnginePrivate;
+class QHelpSearchEngine;
+
+class QHELP_EXPORT QHelpEngine : public QHelpEngineCore
+{
+ Q_OBJECT
+
+public:
+ QHelpEngine(const QString &collectionFile, QObject *parent = 0);
+ ~QHelpEngine();
+
+ QHelpContentModel *contentModel() const;
+ QHelpIndexModel *indexModel() const;
+
+ QHelpContentWidget *contentWidget();
+ QHelpIndexWidget *indexWidget();
+
+ QHelpSearchEngine *searchEngine();
+
+private:
+ QHelpEnginePrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/assistant/lib/qhelpengine_p.h b/tools/assistant/lib/qhelpengine_p.h
new file mode 100644
index 0000000000..287329aeeb
--- /dev/null
+++ b/tools/assistant/lib/qhelpengine_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPENGINE_P_H
+#define QHELPENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QMap>
+#include <QtCore/QStringList>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QSqlQuery;
+
+class QHelpEngineCore;
+class QHelpDBReader;
+class QHelpContentModel;
+class QHelpContentWidget;
+class QHelpIndexModel;
+class QHelpIndexWidget;
+class QHelpSearchEngine;
+class QHelpCollectionHandler;
+
+class QHelpEngineCorePrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QHelpEngineCorePrivate();
+ virtual ~QHelpEngineCorePrivate();
+
+ virtual void init(const QString &collectionFile,
+ QHelpEngineCore *helpEngineCore);
+
+ void clearMaps();
+ bool setup();
+
+ QMap<QString, QHelpDBReader*> readerMap;
+ QMap<QString, QHelpDBReader*> fileNameReaderMap;
+ QMultiMap<QString, QHelpDBReader*> virtualFolderMap;
+ QStringList orderedFileNameList;
+
+ QHelpCollectionHandler *collectionHandler;
+ QString currentFilter;
+ QString error;
+ bool needsSetup;
+ bool autoSaveFilter;
+
+protected:
+ QHelpEngineCore *q;
+
+private slots:
+ void errorReceived(const QString &msg);
+};
+
+
+class QHelpEnginePrivate : public QHelpEngineCorePrivate
+{
+ Q_OBJECT
+
+public:
+ QHelpEnginePrivate();
+ ~QHelpEnginePrivate();
+
+ void init(const QString &collectionFile,
+ QHelpEngineCore *helpEngineCore);
+
+ QHelpContentModel *contentModel;
+ QHelpContentWidget *contentWidget;
+
+ QHelpIndexModel *indexModel;
+ QHelpIndexWidget *indexWidget;
+
+ QHelpSearchEngine *searchEngine;
+
+ void stopDataCollection();
+
+ friend class QHelpContentProvider;
+ friend class QHelpContentModel;
+ friend class QHelpIndexProvider;
+ friend class QHelpIndexModel;
+
+public slots:
+ void setContentsWidgetBusy();
+ void unsetContentsWidgetBusy();
+ void setIndexWidgetBusy();
+ void unsetIndexWidgetBusy();
+
+private slots:
+ void applyCurrentFilter();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/lib/qhelpenginecore.cpp b/tools/assistant/lib/qhelpenginecore.cpp
new file mode 100644
index 0000000000..85bd9fd8a4
--- /dev/null
+++ b/tools/assistant/lib/qhelpenginecore.cpp
@@ -0,0 +1,727 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpenginecore.h"
+#include "qhelpengine_p.h"
+#include "qhelpdbreader_p.h"
+#include "qhelpcollectionhandler_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QLibrary>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QFileInfo>
+#include <QtCore/QThread>
+#include <QtGui/QApplication>
+#include <QtSql/QSqlQuery>
+
+QT_BEGIN_NAMESPACE
+
+QHelpEngineCorePrivate::QHelpEngineCorePrivate()
+{
+ QHelpGlobal::uniquifyConnectionName(QString(), this);
+ autoSaveFilter = true;
+}
+
+void QHelpEngineCorePrivate::init(const QString &collectionFile,
+ QHelpEngineCore *helpEngineCore)
+{
+ q = helpEngineCore;
+ collectionHandler = new QHelpCollectionHandler(collectionFile, helpEngineCore);
+ connect(collectionHandler, SIGNAL(error(const QString&)),
+ this, SLOT(errorReceived(const QString&)));
+ needsSetup = true;
+}
+
+QHelpEngineCorePrivate::~QHelpEngineCorePrivate()
+{
+ delete collectionHandler;
+ clearMaps();
+}
+
+void QHelpEngineCorePrivate::clearMaps()
+{
+ QMap<QString, QHelpDBReader*>::iterator it = readerMap.begin();
+ while (it != readerMap.end()) {
+ delete it.value();
+ ++it;
+ }
+ readerMap.clear();
+ fileNameReaderMap.clear();
+ virtualFolderMap.clear();
+ orderedFileNameList.clear();
+}
+
+bool QHelpEngineCorePrivate::setup()
+{
+ error.clear();
+ if (!needsSetup)
+ return true;
+
+ needsSetup = false;
+ emit q->setupStarted();
+ clearMaps();
+
+ if (!collectionHandler->openCollectionFile()) {
+ emit q->setupFinished();
+ return false;
+ }
+
+ const QHelpCollectionHandler::DocInfoList docList =
+ collectionHandler->registeredDocumentations();
+ QFileInfo fi(collectionHandler->collectionFile());
+ QString absFileName;
+ foreach(const QHelpCollectionHandler::DocInfo &info, docList) {
+ if (QDir::isAbsolutePath(info.fileName)) {
+ absFileName = info.fileName;
+ } else {
+ absFileName = QFileInfo(fi.absolutePath() + QDir::separator() + info.fileName)
+ .absoluteFilePath();
+ }
+ QHelpDBReader *reader = new QHelpDBReader(absFileName,
+ QHelpGlobal::uniquifyConnectionName(info.fileName, this), this);
+ if (!reader->init()) {
+ emit q->warning(tr("Cannot open documentation file %1: %2!")
+ .arg(absFileName, reader->errorMessage()));
+ continue;
+ }
+
+ readerMap.insert(info.namespaceName, reader);
+ fileNameReaderMap.insert(absFileName, reader);
+ virtualFolderMap.insert(info.folderName, reader);
+ orderedFileNameList.append(absFileName);
+ }
+ q->currentFilter();
+ emit q->setupFinished();
+ return true;
+}
+
+void QHelpEngineCorePrivate::errorReceived(const QString &msg)
+{
+ error = msg;
+}
+
+
+
+/*!
+ \class QHelpEngineCore
+ \since 4.4
+ \inmodule QtHelp
+ \brief The QHelpEngineCore class provides the core functionality
+ of the help system.
+
+ Before the help engine can be used, it must be initialized by
+ calling setupData(). At the beginning of the setup process the
+ signal setupStarted() is emitted. From this point on until
+ the signal setupFinished() is emitted, is the help data in an
+ undefined meaning unusable state.
+
+ The core help engine can be used to perform different tasks.
+ By calling linksForIdentifier() the engine returns
+ urls specifying the file locations inside the help system. The
+ actual file data can then be retrived by calling fileData(). In
+ contrast to all other functions in this class, linksForIdentifier()
+ depends on the currently set custom filter. Depending on the filter,
+ the function may return different hits.
+
+ Every help engine can contain any number of custom filters. A custom
+ filter is defined by a name and set of filter attributes and can be
+ added to the help engine by calling addCustomFilter(). Analogous,
+ it is removed by calling removeCustomFilter(). customFilters() returns
+ all defined filters.
+
+ The help engine also offers the possiblity to set and read values
+ in a persistant way comparable to ini files or Windows registry
+ entries. For more information see setValue() or value().
+
+ This class does not offer any GUI components or functionality for
+ indices or contents. If you need one of those use QHelpEngine
+ instead.
+*/
+
+/*!
+ \fn void QHelpEngineCore::setupStarted()
+
+ This signal is emitted when setup is started.
+*/
+
+/*!
+ \fn void QHelpEngineCore::setupFinished()
+
+ This signal is emitted when the setup is complete.
+*/
+
+/*!
+ \fn void QHelpEngineCore::currentFilterChanged(const QString &newFilter)
+
+ This signal is emitted when the current filter is changed to
+ \a newFilter.
+*/
+
+/*!
+ \fn void QHelpEngineCore::warning(const QString &msg)
+
+ This signal is emitted when a non critical error occurs.
+ The warning message is stored in \a msg.
+*/
+
+/*!
+ Constructs a new core help engine with a \a parent. The help engine
+ uses the information stored in the \a collectionFile to provide help.
+ If the collection file does not exist yet, it'll be created.
+*/
+QHelpEngineCore::QHelpEngineCore(const QString &collectionFile, QObject *parent)
+ : QObject(parent)
+{
+ d = new QHelpEngineCorePrivate();
+ d->init(collectionFile, this);
+}
+
+/*!
+ \internal
+*/
+QHelpEngineCore::QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate,
+ QObject *parent)
+ : QObject(parent)
+{
+ d = helpEngineCorePrivate;
+}
+
+/*!
+ Destructs the help engine.
+*/
+QHelpEngineCore::~QHelpEngineCore()
+{
+ delete d;
+}
+
+/*!
+ \property QHelpEngineCore::collectionFile
+ \brief the absolute file name of the collection file currently used.
+ \since 4.5
+
+ Setting this property leaves the help engine in an invalid state. It is
+ important to invoke setupData() or any getter function in order to setup
+ the help engine again.
+*/
+QString QHelpEngineCore::collectionFile() const
+{
+ return d->collectionHandler->collectionFile();
+}
+
+void QHelpEngineCore::setCollectionFile(const QString &fileName)
+{
+ if (fileName == collectionFile())
+ return;
+
+ if (d->collectionHandler) {
+ delete d->collectionHandler;
+ d->collectionHandler = 0;
+ d->clearMaps();
+ }
+ d->init(fileName, this);
+ d->needsSetup = true;
+}
+
+/*!
+ Sets up the help engine by processing the information found
+ in the collection file and returns true if successful; otherwise
+ returns false.
+
+ By calling the function, the help
+ engine is forced to initialize itself immediately. Most of
+ the times, this function does not have to be called
+ explicitly because getter functions which depend on a correctly
+ set up help engine do that themselves.
+
+ \note \c{qsqlite4.dll} needs to be deployed with the application as the
+ help system uses the sqlite driver when loading help collections.
+*/
+bool QHelpEngineCore::setupData()
+{
+ d->needsSetup = true;
+ return d->setup();
+}
+
+/*!
+ Creates the file \a fileName and copies all contents from
+ the current collection file into the newly created file,
+ and returns true if successful; otherwise returns false.
+
+ The copying process makes sure that file references to Qt
+ Collection files (\c{.qch}) files are updated accordingly.
+*/
+bool QHelpEngineCore::copyCollectionFile(const QString &fileName)
+{
+ if (!d->setup())
+ return false;
+ return d->collectionHandler->copyCollectionFile(fileName);
+}
+
+/*!
+ Returns the namespace name defined for the Qt compressed help file (.qch)
+ specified by its \a documentationFileName. If the file is not valid, an
+ empty string is returned.
+
+ \sa documentationFileName()
+*/
+QString QHelpEngineCore::namespaceName(const QString &documentationFileName)
+{
+ QHelpDBReader reader(documentationFileName,
+ QHelpGlobal::uniquifyConnectionName(QLatin1String("GetNamespaceName"),
+ QThread::currentThread()), 0);
+ if (reader.init())
+ return reader.namespaceName();
+ return QString();
+}
+
+/*!
+ Registers the Qt compressed help file (.qch) contained in the file
+ \a documentationFileName. One compressed help file, uniquely
+ identified by its namespace can only be registered once.
+ True is returned if the registration was successful, otherwise
+ false.
+
+ \sa unregisterDocumentation(), error()
+*/
+bool QHelpEngineCore::registerDocumentation(const QString &documentationFileName)
+{
+ d->error.clear();
+ d->needsSetup = true;
+ return d->collectionHandler->registerDocumentation(documentationFileName);
+}
+
+/*!
+ Unregisters the Qt compressed help file (.qch) identified by its
+ \a namespaceName from the help collection. Returns true
+ on success, otherwise false.
+
+ \sa registerDocumentation(), error()
+*/
+bool QHelpEngineCore::unregisterDocumentation(const QString &namespaceName)
+{
+ d->error.clear();
+ d->needsSetup = true;
+ return d->collectionHandler->unregisterDocumentation(namespaceName);
+}
+
+/*!
+ Returns the absolute file name of the Qt compressed help file (.qch)
+ identified by the \a namespaceName. If there is no Qt compressed help file
+ with the specified namespace registered, an empty string is returned.
+
+ \sa namespaceName()
+*/
+QString QHelpEngineCore::documentationFileName(const QString &namespaceName)
+{
+ QString res;
+ if (!d->setup())
+ return res;
+ const QHelpCollectionHandler::DocInfoList docList = d->collectionHandler->registeredDocumentations();
+ foreach(const QHelpCollectionHandler::DocInfo info, docList) {
+ if (info.namespaceName == namespaceName) {
+ QFileInfo fi(d->collectionHandler->collectionFile());
+ fi.setFile(fi.absolutePath() + QDir::separator() + info.fileName);
+ res = QDir::cleanPath(fi.absoluteFilePath());
+ break;
+ }
+ }
+ return res;
+}
+
+/*!
+ Returns a list of all registered Qt compressed help files of the current collection file.
+ The returned names are the namespaces of the registered Qt compressed help files (.qch).
+*/
+QStringList QHelpEngineCore::registeredDocumentations() const
+{
+ QStringList list;
+ if (!d->setup())
+ return list;
+ const QHelpCollectionHandler::DocInfoList docList = d->collectionHandler->registeredDocumentations();
+ foreach(const QHelpCollectionHandler::DocInfo info, docList) {
+ list.append(info.namespaceName);
+ }
+ return list;
+}
+
+/*!
+ Returns a list of custom filters.
+
+ \sa addCustomFilter(), removeCustomFilter()
+*/
+QStringList QHelpEngineCore::customFilters() const
+{
+ if (!d->setup())
+ return QStringList();
+ return d->collectionHandler->customFilters();
+}
+
+/*!
+ Adds the new custom filter \a filterName. The filter attributes
+ are specified by \a attributes. The function returns false if
+ the filter can not be added, e.g. when the filter already exists.
+
+ \sa customFilters(), removeCustomFilter()
+*/
+bool QHelpEngineCore::addCustomFilter(const QString &filterName,
+ const QStringList &attributes)
+{
+ d->error.clear();
+ d->needsSetup = true;
+ return d->collectionHandler->addCustomFilter(filterName,
+ attributes);
+}
+
+/*!
+ Returns true if the filter \a filterName was removed successfully,
+ otherwise false.
+
+ \sa addCustomFilter(), customFilters()
+*/
+bool QHelpEngineCore::removeCustomFilter(const QString &filterName)
+{
+ d->error.clear();
+ d->needsSetup = true;
+ return d->collectionHandler->removeCustomFilter(filterName);
+}
+
+/*!
+ Returns a list of all defined filter attributes.
+*/
+QStringList QHelpEngineCore::filterAttributes() const
+{
+ if (!d->setup())
+ return QStringList();
+ return d->collectionHandler->filterAttributes();
+}
+
+/*!
+ Returns a list of filter attributes used by the custom
+ filter \a filterName.
+*/
+QStringList QHelpEngineCore::filterAttributes(const QString &filterName) const
+{
+ if (!d->setup())
+ return QStringList();
+ return d->collectionHandler->filterAttributes(filterName);
+}
+
+/*!
+ \property QHelpEngineCore::currentFilter
+ \brief the name of the custom filter currently applied.
+ \since 4.5
+
+ Setting this property will save the new custom filter permanently in the
+ help collection file. To set a custom filter without saving it
+ permanently, disable the auto save filter mode.
+
+ \sa autoSaveFilter()
+*/
+QString QHelpEngineCore::currentFilter() const
+{
+ if (!d->setup())
+ return QString();
+
+ if (d->currentFilter.isEmpty()) {
+ QString filter =
+ d->collectionHandler->customValue(QLatin1String("CurrentFilter"),
+ QString()).toString();
+ if (!filter.isEmpty()
+ && d->collectionHandler->customFilters().contains(filter))
+ d->currentFilter = filter;
+ }
+ return d->currentFilter;
+}
+
+void QHelpEngineCore::setCurrentFilter(const QString &filterName)
+{
+ if (!d->setup() || filterName == d->currentFilter)
+ return;
+ d->currentFilter = filterName;
+ if (d->autoSaveFilter) {
+ d->collectionHandler->setCustomValue(QLatin1String("CurrentFilter"),
+ d->currentFilter);
+ }
+ emit currentFilterChanged(d->currentFilter);
+}
+
+/*!
+ Returns a list of filter attributes for the different filter sections
+ defined in the Qt compressed help file with the given namespace
+ \a namespaceName.
+*/
+QList<QStringList> QHelpEngineCore::filterAttributeSets(const QString &namespaceName) const
+{
+ if (d->setup()) {
+ QHelpDBReader *reader = d->readerMap.value(namespaceName);
+ if (reader)
+ return reader->filterAttributeSets();
+ }
+ return QList<QStringList>();
+}
+
+/*!
+ Returns a list of files contained in the Qt compressed help file \a
+ namespaceName. The files can be filtered by \a filterAttributes as
+ well as by their extension \a extensionFilter (e.g. 'html').
+*/
+QList<QUrl> QHelpEngineCore::files(const QString namespaceName,
+ const QStringList &filterAttributes,
+ const QString &extensionFilter)
+{
+ QList<QUrl> res;
+ if (!d->setup())
+ return res;
+ QHelpDBReader *reader = d->readerMap.value(namespaceName);
+ if (!reader) {
+ d->error = tr("The specified namespace does not exist!");
+ return res;
+ }
+
+ QUrl url;
+ url.setScheme(QLatin1String("qthelp"));
+ url.setAuthority(namespaceName);
+
+ const QStringList files = reader->files(filterAttributes, extensionFilter);
+ foreach (const QString file, files) {
+ url.setPath(QLatin1String("/") + file);
+ res.append(url);
+ }
+ return res;
+}
+
+/*!
+ Returns an invalid URL if the file \a url cannot be found.
+ If the file exists, either the same url is returned or a
+ different url if the file is located in a different namespace
+ which is merged via a common virtual folder.
+*/
+QUrl QHelpEngineCore::findFile(const QUrl &url) const
+{
+ QUrl res;
+ if (!d->setup() || !url.isValid() || url.toString().count(QLatin1Char('/')) < 4
+ || url.scheme() != QLatin1String("qthelp"))
+ return res;
+
+ QString ns = url.authority();
+ QString filePath = QDir::cleanPath(url.path());
+ if (filePath.startsWith(QLatin1Char('/')))
+ filePath = filePath.mid(1);
+ QString virtualFolder = filePath.mid(0, filePath.indexOf(QLatin1Char('/'), 1));
+ filePath = filePath.mid(virtualFolder.length()+1);
+
+ QHelpDBReader *defaultReader = 0;
+ if (d->readerMap.contains(ns)) {
+ defaultReader = d->readerMap.value(ns);
+ if (defaultReader->fileExists(virtualFolder, filePath))
+ return url;
+ }
+
+ QStringList filterAtts = filterAttributes(currentFilter());
+ foreach (QHelpDBReader *reader, d->virtualFolderMap.values(virtualFolder)) {
+ if (reader == defaultReader)
+ continue;
+ if (reader->fileExists(virtualFolder, filePath, filterAtts)) {
+ res = url;
+ res.setAuthority(reader->namespaceName());
+ return res;
+ }
+ }
+
+ foreach (QHelpDBReader *reader, d->virtualFolderMap.values(virtualFolder)) {
+ if (reader == defaultReader)
+ continue;
+ if (reader->fileExists(virtualFolder, filePath)) {
+ res = url;
+ res.setAuthority(reader->namespaceName());
+ break;
+ }
+ }
+
+ return res;
+}
+
+/*!
+ Returns the data of the file specified by \a url. If the
+ file does not exist, an empty QByteArray is returned.
+
+ \sa findFile()
+*/
+QByteArray QHelpEngineCore::fileData(const QUrl &url) const
+{
+ if (!d->setup() || !url.isValid() || url.toString().count(QLatin1Char('/')) < 4
+ || url.scheme() != QLatin1String("qthelp"))
+ return QByteArray();
+
+ QString ns = url.authority();
+ QString filePath = QDir::cleanPath(url.path());
+ if (filePath.startsWith(QLatin1Char('/')))
+ filePath = filePath.mid(1);
+ QString virtualFolder = filePath.mid(0, filePath.indexOf(QLatin1Char('/'), 1));
+ filePath = filePath.mid(virtualFolder.length()+1);
+
+ QByteArray ba;
+ QHelpDBReader *defaultReader = 0;
+ if (d->readerMap.contains(ns)) {
+ defaultReader = d->readerMap.value(ns);
+ ba = defaultReader->fileData(virtualFolder, filePath);
+ }
+
+ if (ba.isEmpty()) {
+ foreach (QHelpDBReader *reader, d->virtualFolderMap.values(virtualFolder)) {
+ if (reader == defaultReader)
+ continue;
+ ba = reader->fileData(virtualFolder, filePath);
+ if (!ba.isEmpty())
+ return ba;
+ }
+ }
+ return ba;
+}
+
+/*!
+ Returns a map of hits found for the \a id. A hit contains the
+ title of the document and the url where the keyword is located.
+ The result depends on the current filter, meaning only the keywords
+ registered for the current filter will be returned.
+*/
+QMap<QString, QUrl> QHelpEngineCore::linksForIdentifier(const QString &id) const
+{
+ QMap<QString, QUrl> linkMap;
+ if (!d->setup())
+ return linkMap;
+
+ QStringList atts = filterAttributes(d->currentFilter);
+ foreach (QHelpDBReader *reader, d->readerMap)
+ reader->linksForIdentifier(id, atts, linkMap);
+
+ return linkMap;
+}
+
+/*!
+ Removes the \a key from the settings section in the
+ collection file. Returns true if the value was removed
+ successfully, otherwise false.
+
+ \sa customValue(), setCustomValue()
+*/
+bool QHelpEngineCore::removeCustomValue(const QString &key)
+{
+ d->error.clear();
+ return d->collectionHandler->removeCustomValue(key);
+}
+
+/*!
+ Returns the value assigned to the \a key. If the requested
+ key does not exist, the specified \a defaultValue is
+ returned.
+
+ \sa setCustomValue(), removeCustomValue()
+*/
+QVariant QHelpEngineCore::customValue(const QString &key, const QVariant &defaultValue) const
+{
+ if (!d->setup())
+ return QVariant();
+ return d->collectionHandler->customValue(key, defaultValue);
+}
+
+/*!
+ Save the \a value under the \a key. If the key already exist,
+ the value will be overwritten. Returns true if the value was
+ saved successfully, otherwise false.
+
+ \sa customValue(), removeCustomValue()
+*/
+bool QHelpEngineCore::setCustomValue(const QString &key, const QVariant &value)
+{
+ d->error.clear();
+ return d->collectionHandler->setCustomValue(key, value);
+}
+
+/*!
+ Returns the meta data for the Qt compressed help file \a
+ documentationFileName. If there is no data available for
+ \a name, an invalid QVariant() is returned. The meta
+ data is defined when creating the Qt compressed help file and
+ cannot be modified later. Common meta data includes e.g.
+ the author of the documentation.
+*/
+QVariant QHelpEngineCore::metaData(const QString &documentationFileName,
+ const QString &name)
+{
+ QHelpDBReader reader(documentationFileName, QLatin1String("GetMetaData"), 0);
+
+ if (reader.init())
+ return reader.metaData(name);
+ return QVariant();
+}
+
+/*!
+ Returns a description of the last error that occured.
+*/
+QString QHelpEngineCore::error() const
+{
+ return d->error;
+}
+
+/*!
+ \property QHelpEngineCore::autoSaveFilter
+ \brief whether QHelpEngineCore is in auto save filter mode or not.
+ \since 4.5
+
+ If QHelpEngineCore is in auto save filter mode, the current filter is
+ automatically saved when it is changed by the setCurrentFilter()
+ function. The filter is saved persistently in the help collection file.
+
+ By default, this mode is on.
+*/
+void QHelpEngineCore::setAutoSaveFilter(bool save)
+{
+ d->autoSaveFilter = save;
+}
+
+bool QHelpEngineCore::autoSaveFilter() const
+{
+ return d->autoSaveFilter;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpenginecore.h b/tools/assistant/lib/qhelpenginecore.h
new file mode 100644
index 0000000000..92ba2fd703
--- /dev/null
+++ b/tools/assistant/lib/qhelpenginecore.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPENGINECORE_H
+#define QHELPENGINECORE_H
+
+#include <QtHelp/qhelp_global.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QMap>
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+class QHelpEngineCorePrivate;
+
+class QHELP_EXPORT QHelpEngineCore : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool autoSaveFilter READ autoSaveFilter WRITE setAutoSaveFilter)
+ Q_PROPERTY(QString collectionFile READ collectionFile WRITE setCollectionFile)
+ Q_PROPERTY(QString currentFilter READ currentFilter WRITE setCurrentFilter)
+
+public:
+ QHelpEngineCore(const QString &collectionFile, QObject *parent = 0);
+ virtual ~QHelpEngineCore();
+
+ bool setupData();
+
+ QString collectionFile() const;
+ void setCollectionFile(const QString &fileName);
+
+ bool copyCollectionFile(const QString &fileName);
+
+ static QString namespaceName(const QString &documentationFileName);
+ bool registerDocumentation(const QString &documentationFileName);
+ bool unregisterDocumentation(const QString &namespaceName);
+ QString documentationFileName(const QString &namespaceName);
+
+ QStringList customFilters() const;
+ bool removeCustomFilter(const QString &filterName);
+ bool addCustomFilter(const QString &filterName,
+ const QStringList &attributes);
+
+ QStringList filterAttributes() const;
+ QStringList filterAttributes(const QString &filterName) const;
+
+ QString currentFilter() const;
+ void setCurrentFilter(const QString &filterName);
+
+ QStringList registeredDocumentations() const;
+ QList<QStringList> filterAttributeSets(const QString &namespaceName) const;
+ QList<QUrl> files(const QString namespaceName,
+ const QStringList &filterAttributes,
+ const QString &extensionFilter = QString());
+ QUrl findFile(const QUrl &url) const;
+ QByteArray fileData(const QUrl &url) const;
+
+ QMap<QString, QUrl> linksForIdentifier(const QString &id) const;
+
+ bool removeCustomValue(const QString &key);
+ QVariant customValue(const QString &key,
+ const QVariant &defaultValue = QVariant()) const;
+ bool setCustomValue(const QString &key, const QVariant &value);
+
+ static QVariant metaData(const QString &documentationFileName,
+ const QString &name);
+
+ QString error() const;
+
+ void setAutoSaveFilter(bool save);
+ bool autoSaveFilter() const;
+
+Q_SIGNALS:
+ void setupStarted();
+ void setupFinished();
+ void currentFilterChanged(const QString &newFilter);
+ void warning(const QString &msg);
+
+protected:
+ QHelpEngineCore(QHelpEngineCorePrivate *helpEngineCorePrivate,
+ QObject *parent);
+
+private:
+ QHelpEngineCorePrivate *d;
+ friend class QHelpEngineCorePrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QHELPENGINECORE_H
diff --git a/tools/assistant/lib/qhelpgenerator.cpp b/tools/assistant/lib/qhelpgenerator.cpp
new file mode 100644
index 0000000000..03df3cc524
--- /dev/null
+++ b/tools/assistant/lib/qhelpgenerator.cpp
@@ -0,0 +1,823 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpgenerator_p.h"
+#include "qhelpdatainterface_p.h"
+
+#include <math.h>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QVariant>
+#include <QtCore/QDateTime>
+#include <QtCore/QTextCodec>
+#include <QtSql/QSqlQuery>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpGeneratorPrivate
+{
+public:
+ QHelpGeneratorPrivate();
+ ~QHelpGeneratorPrivate();
+
+ QString error;
+ QSqlQuery *query;
+
+ int namespaceId;
+ int virtualFolderId;
+
+ QMap<QString, int> fileMap;
+ QMap<int, QSet<int> > fileFilterMap;
+
+ double progress;
+ double oldProgress;
+ double contentStep;
+ double fileStep;
+ double indexStep;
+};
+
+QHelpGeneratorPrivate::QHelpGeneratorPrivate()
+{
+ query = 0;
+ namespaceId = -1;
+ virtualFolderId = -1;
+}
+
+QHelpGeneratorPrivate::~QHelpGeneratorPrivate()
+{
+}
+
+
+
+/*!
+ \internal
+ \class QHelpGenerator
+ \since 4.4
+ \brief The QHelpGenerator class generates a new
+ Qt compressed help file (.qch).
+
+ The help generator takes a help data structure as
+ input for generating a new Qt compressed help files. Since
+ the generation may takes some time, the generator emits
+ various signals to inform about its current state.
+*/
+
+/*!
+ \fn void QHelpGenerator::statusChanged(const QString &msg)
+
+ This signal is emitted when the generation status changes.
+ The status is basically a specific task like inserting
+ files or building up the keyword index. The parameter
+ \a msg contains the detailed status description.
+*/
+
+/*!
+ \fn void QHelpGenerator::progressChanged(double progress)
+
+ This signal is emitted when the progress changes. The
+ \a progress ranges from 0 to 100.
+*/
+
+/*!
+ \fn void QHelpGenerator::warning(const QString &msg)
+
+ This signal is emitted when a non critical error occurs,
+ e.g. when a referenced file cannot be found. \a msg
+ contains the exact warning message.
+*/
+
+/*!
+ Constructs a new help generator with the give \a parent.
+*/
+QHelpGenerator::QHelpGenerator(QObject *parent)
+ : QObject(parent)
+{
+ d = new QHelpGeneratorPrivate;
+}
+
+/*!
+ Destructs the help generator.
+*/
+QHelpGenerator::~QHelpGenerator()
+{
+ delete d;
+}
+
+/*!
+ Takes the \a helpData and generates a new documentation
+ set from it. The Qt compressed help file is written to \a
+ outputFileName. Returns true on success, otherwise false.
+*/
+bool QHelpGenerator::generate(QHelpDataInterface *helpData,
+ const QString &outputFileName)
+{
+ emit progressChanged(0);
+ d->error.clear();
+ if (!helpData || helpData->namespaceName().isEmpty()) {
+ d->error = tr("Invalid help data!");
+ return false;
+ }
+
+ QString outFileName = outputFileName;
+ if (outFileName.isEmpty()) {
+ d->error = tr("No output file name specified!");
+ return false;
+ }
+
+ QFileInfo fi(outFileName);
+ if (fi.exists()) {
+ if (!fi.dir().remove(fi.fileName())) {
+ d->error = tr("The file %1 cannot be overwritten!").arg(outFileName);
+ return false;
+ }
+ }
+
+ setupProgress(helpData);
+
+ emit statusChanged(tr("Building up file structure..."));
+ bool openingOk = true;
+ {
+ QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("builder"));
+ db.setDatabaseName(outFileName);
+ openingOk = db.open();
+ if (openingOk)
+ d->query = new QSqlQuery(db);
+ }
+
+ if (!openingOk) {
+ d->error = tr("Cannot open data base file %1!").arg(outFileName);
+ cleanupDB();
+ return false;
+ }
+
+ addProgress(1.0);
+ createTables();
+ insertFileNotFoundFile();
+ insertMetaData(helpData->metaData());
+
+ if (!registerVirtualFolder(helpData->virtualFolder(), helpData->namespaceName())) {
+ d->error = tr("Cannot register namespace %1!").arg(helpData->namespaceName());
+ cleanupDB();
+ return false;
+ }
+ addProgress(1.0);
+
+ emit statusChanged(tr("Insert custom filters..."));
+ foreach (QHelpDataCustomFilter f, helpData->customFilters()) {
+ if (!registerCustomFilter(f.name, f.filterAttributes, true)) {
+ cleanupDB();
+ return false;
+ }
+ }
+ addProgress(1.0);
+
+ int i = 1;
+ QList<QHelpDataFilterSection>::const_iterator it = helpData->filterSections().constBegin();
+ while (it != helpData->filterSections().constEnd()) {
+ emit statusChanged(tr("Insert help data for filter section (%1 of %2)...")
+ .arg(i++).arg(helpData->filterSections().count()));
+ insertFilterAttributes((*it).filterAttributes());
+ QByteArray ba;
+ QDataStream s(&ba, QIODevice::WriteOnly);
+ foreach (QHelpDataContentItem *itm, (*it).contents())
+ writeTree(s, itm, 0);
+ if (!insertFiles((*it).files(), helpData->rootPath(), (*it).filterAttributes())
+ || !insertContents(ba, (*it).filterAttributes())
+ || !insertKeywords((*it).indices(), (*it).filterAttributes())) {
+ cleanupDB();
+ return false;
+ }
+ ++it;
+ }
+
+ cleanupDB();
+ emit progressChanged(100);
+ emit statusChanged(tr("Documentation successfully generated."));
+ return true;
+}
+
+void QHelpGenerator::setupProgress(QHelpDataInterface *helpData)
+{
+ d->progress = 0;
+ d->oldProgress = 0;
+
+ int numberOfFiles = 0;
+ int numberOfIndices = 0;
+ QList<QHelpDataFilterSection>::const_iterator it = helpData->filterSections().constBegin();
+ while (it != helpData->filterSections().constEnd()) {
+ numberOfFiles += (*it).files().count();
+ numberOfIndices += (*it).indices().count();
+ ++it;
+ }
+ // init 2%
+ // filters 1%
+ // contents 10%
+ // files 60%
+ // indices 27%
+ d->contentStep = 10.0/(double)helpData->customFilters().count();
+ d->fileStep = 60.0/(double)numberOfFiles;
+ d->indexStep = 27.0/(double)numberOfIndices;
+}
+
+void QHelpGenerator::addProgress(double step)
+{
+ d->progress += step;
+ if ((d->progress-d->oldProgress) >= 1.0 && d->progress <= 100.0) {
+ d->oldProgress = d->progress;
+ emit progressChanged(ceil(d->progress));
+ }
+}
+
+void QHelpGenerator::cleanupDB()
+{
+ if (d->query) {
+ d->query->clear();
+ delete d->query;
+ d->query = 0;
+ }
+ QSqlDatabase::removeDatabase(QLatin1String("builder"));
+}
+
+void QHelpGenerator::writeTree(QDataStream &s, QHelpDataContentItem *item, int depth)
+{
+ QString fReference = QDir::cleanPath(item->reference());
+ if (fReference.startsWith(QLatin1String("./")))
+ fReference = fReference.mid(2);
+
+ s << depth;
+ s << fReference;
+ s << item->title();
+ foreach (QHelpDataContentItem *i, item->children())
+ writeTree(s, i, depth+1);
+}
+
+/*!
+ Returns the last error message.
+*/
+QString QHelpGenerator::error() const
+{
+ return d->error;
+}
+
+bool QHelpGenerator::createTables()
+{
+ if (!d->query)
+ return false;
+
+ d->query->exec(QLatin1String("SELECT COUNT(*) FROM sqlite_master WHERE TYPE=\'table\'"
+ "AND Name=\'NamespaceTable\'"));
+ d->query->next();
+ if (d->query->value(0).toInt() > 0) {
+ d->error = tr("Some tables already exist!");
+ return false;
+ }
+
+ QStringList tables;
+ tables << QLatin1String("CREATE TABLE NamespaceTable ("
+ "Id INTEGER PRIMARY KEY,"
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterAttributeTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterNameTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT )")
+ << QLatin1String("CREATE TABLE FilterTable ("
+ "NameId INTEGER, "
+ "FilterAttributeId INTEGER )")
+ << QLatin1String("CREATE TABLE IndexTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Name TEXT, "
+ "Identifier TEXT, "
+ "NamespaceId INTEGER, "
+ "FileId INTEGER, "
+ "Anchor TEXT )")
+ << QLatin1String("CREATE TABLE IndexItemTable ("
+ "Id INTEGER, "
+ "IndexId INTEGER )")
+ << QLatin1String("CREATE TABLE IndexFilterTable ("
+ "FilterAttributeId INTEGER, "
+ "IndexId INTEGER )")
+ << QLatin1String("CREATE TABLE ContentsTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "NamespaceId INTEGER, "
+ "Data BLOB )")
+ << QLatin1String("CREATE TABLE ContentsFilterTable ("
+ "FilterAttributeId INTEGER, "
+ "ContentsId INTEGER )")
+ << QLatin1String("CREATE TABLE FileAttributeSetTable ("
+ "Id INTEGER, "
+ "FilterAttributeId INTEGER )")
+ << QLatin1String("CREATE TABLE FileDataTable ("
+ "Id INTEGER PRIMARY KEY, "
+ "Data BLOB )")
+ << QLatin1String("CREATE TABLE FileFilterTable ("
+ "FilterAttributeId INTEGER, "
+ "FileId INTEGER )")
+ << QLatin1String("CREATE TABLE FileNameTable ("
+ "FolderId INTEGER, "
+ "Name TEXT, "
+ "FileId INTEGER, "
+ "Title TEXT )")
+ << QLatin1String("CREATE TABLE FolderTable("
+ "Id INTEGER PRIMARY KEY, "
+ "Name Text, "
+ "NamespaceID INTEGER )")
+ << QLatin1String("CREATE TABLE MetaDataTable("
+ "Name Text, "
+ "Value BLOB )");
+
+ foreach (QString q, tables) {
+ if (!d->query->exec(q)) {
+ d->error = tr("Cannot create tables!");
+ return false;
+ }
+ }
+
+ d->query->exec(QLatin1String("INSERT INTO MetaDataTable VALUES('qchVersion', '1.0')"));
+
+ d->query->prepare(QLatin1String("INSERT INTO MetaDataTable VALUES('CreationDate', ?)"));
+ d->query->bindValue(0, QDateTime::currentDateTime().toString(Qt::ISODate));
+ d->query->exec();
+
+ return true;
+}
+
+bool QHelpGenerator::insertFileNotFoundFile()
+{
+ if (!d->query)
+ return false;
+
+ d->query->exec(QLatin1String("SELECT id FROM FileNameTable WHERE Name=\'\'"));
+ if (d->query->next() && d->query->isValid())
+ return true;
+
+ d->query->prepare(QLatin1String("INSERT INTO FileDataTable VALUES (Null, ?)"));
+ d->query->bindValue(0, QByteArray());
+ if (!d->query->exec())
+ return false;
+
+ int fileId = d->query->lastInsertId().toInt();
+ d->query->prepare(QLatin1String("INSERT INTO FileNameTable (FolderId, Name, FileId, Title) "
+ " VALUES (0, '', ?, '')"));
+ d->query->bindValue(0, fileId);
+ if (fileId > -1 && d->query->exec()) {
+ d->fileMap.insert(QString(), fileId);
+ return true;
+ }
+ return false;
+}
+
+bool QHelpGenerator::registerVirtualFolder(const QString &folderName, const QString &ns)
+{
+ if (!d->query || folderName.isEmpty() || ns.isEmpty())
+ return false;
+
+ d->query->prepare(QLatin1String("SELECT Id FROM FolderTable WHERE Name=?"));
+ d->query->bindValue(0, folderName);
+ d->query->exec();
+ d->query->next();
+ if (d->query->isValid() && d->query->value(0).toInt() > 0)
+ return true;
+
+ d->namespaceId = -1;
+ d->query->prepare(QLatin1String("SELECT Id FROM NamespaceTable WHERE Name=?"));
+ d->query->bindValue(0, ns);
+ d->query->exec();
+ while (d->query->next()) {
+ d->namespaceId = d->query->value(0).toInt();
+ break;
+ }
+
+ if (d->namespaceId < 0) {
+ d->query->prepare(QLatin1String("INSERT INTO NamespaceTable VALUES(NULL, ?)"));
+ d->query->bindValue(0, ns);
+ if (d->query->exec())
+ d->namespaceId = d->query->lastInsertId().toInt();
+ }
+
+ if (d->namespaceId > 0) {
+ d->query->prepare(QLatin1String("SELECT Id FROM FolderTable WHERE Name=?"));
+ d->query->bindValue(0, folderName);
+ d->query->exec();
+ while (d->query->next())
+ d->virtualFolderId = d->query->value(0).toInt();
+
+ if (d->virtualFolderId > 0)
+ return true;
+
+ d->query->prepare(QLatin1String("INSERT INTO FolderTable (NamespaceId, Name) "
+ "VALUES (?, ?)"));
+ d->query->bindValue(0, d->namespaceId);
+ d->query->bindValue(1, folderName);
+ if (d->query->exec()) {
+ d->virtualFolderId = d->query->lastInsertId().toInt();
+ return d->virtualFolderId > 0;
+ }
+ }
+ d->error = tr("Cannot register virtual folder!");
+ return false;
+}
+
+bool QHelpGenerator::insertFiles(const QStringList &files, const QString &rootPath,
+ const QStringList &filterAttributes)
+{
+ if (!d->query)
+ return false;
+
+ emit statusChanged(tr("Insert files..."));
+ QList<int> filterAtts;
+ foreach (QString filterAtt, filterAttributes) {
+ d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable WHERE Name=?"));
+ d->query->bindValue(0, filterAtt);
+ d->query->exec();
+ if (d->query->next())
+ filterAtts.append(d->query->value(0).toInt());
+ }
+
+ int filterSetId = -1;
+ d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileAttributeSetTable"));
+ if (d->query->next())
+ filterSetId = d->query->value(0).toInt();
+ if (filterSetId < 0)
+ return false;
+ ++filterSetId;
+ foreach (int attId, filterAtts) {
+ d->query->prepare(QLatin1String("INSERT INTO FileAttributeSetTable VALUES(?, ?)"));
+ d->query->bindValue(0, filterSetId);
+ d->query->bindValue(1, attId);
+ d->query->exec();
+ }
+
+ QString title;
+ QString charSet;
+ QMap<int, QSet<int> > tmpFileFilterMap;
+ QList<FileNameTableData> fileNameDataList;
+ QList<QByteArray> fileDataList;
+
+ int tableFileId = 1;
+ d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable"));
+ if (d->query->next())
+ tableFileId = d->query->value(0).toInt() + 1;
+
+ FileNameTableData fileNameData;
+
+ int i = 0;
+ foreach (QString file, files) {
+ QFileInfo fi(rootPath + QDir::separator() + file);
+ if (!fi.exists()) {
+ emit warning(tr("The file %1 does not exist! Skipping it.")
+ .arg(fi.absoluteFilePath()));
+ continue;
+ }
+
+ QFile f(fi.absoluteFilePath());
+ if (!f.open(QIODevice::ReadOnly)) {
+ emit warning(tr("Cannot open file %1! Skipping it.")
+ .arg(fi.absoluteFilePath()));
+ continue;
+ }
+
+ title.clear();
+ QByteArray data;
+ data = f.readAll();
+
+ if (fi.suffix() == QLatin1String("html") || fi.suffix() == QLatin1String("htm")) {
+ charSet = QHelpGlobal::charsetFromData(data);
+ QTextStream stream(&data);
+ stream.setCodec(QTextCodec::codecForName(charSet.toLatin1().constData()));
+ title = QHelpGlobal::documentTitle(stream.readAll());
+ } else {
+ title = fi.fileName();
+ }
+
+ QString fName = QDir::cleanPath(file);
+ if (fName.startsWith(QLatin1String("./")))
+ fName = fName.mid(2);
+
+ int fileId = -1;
+ if (!d->fileMap.contains(fName)) {
+ fileDataList.append(qCompress(data));
+
+ fileNameData.name = fName;
+ fileNameData.fileId = tableFileId;
+ fileNameData.title = title;
+ fileNameDataList.append(fileNameData);
+
+ d->fileMap.insert(fName, tableFileId);
+ d->fileFilterMap.insert(tableFileId, filterAtts.toSet());
+ tmpFileFilterMap.insert(tableFileId, filterAtts.toSet());
+
+ ++tableFileId;
+ } else {
+ fileId = d->fileMap.value(fName);
+ foreach (int filter, filterAtts) {
+ if (!d->fileFilterMap.value(fileId).contains(filter)
+ && !tmpFileFilterMap.value(fileId).contains(filter)) {
+ d->fileFilterMap[fileId].insert(filter);
+ tmpFileFilterMap[fileId].insert(filter);
+ }
+ }
+ }
+ }
+
+ if (tmpFileFilterMap.count()) {
+ d->query->exec(QLatin1String("BEGIN"));
+ QMap<int, QSet<int> >::const_iterator it = tmpFileFilterMap.constBegin();
+ while (it != tmpFileFilterMap.constEnd()) {
+ QSet<int>::const_iterator i = it.value().constBegin();
+ while (i != it.value().constEnd()) {
+ d->query->prepare(QLatin1String("INSERT INTO FileFilterTable VALUES(?, ?)"));
+ d->query->bindValue(0, *i);
+ d->query->bindValue(1, it.key());
+ d->query->exec();
+ ++i;
+ }
+ ++it;
+ }
+
+ QList<QByteArray>::const_iterator fileIt = fileDataList.constBegin();
+ while (fileIt != fileDataList.constEnd()) {
+ d->query->prepare(QLatin1String("INSERT INTO FileDataTable VALUES (Null, ?)"));
+ d->query->bindValue(0, *fileIt);
+ d->query->exec();
+ ++fileIt;
+ if (++i%20 == 0)
+ addProgress(d->fileStep*20.0);
+ }
+
+ QList<FileNameTableData>::const_iterator fileNameIt = fileNameDataList.constBegin();
+ while (fileNameIt != fileNameDataList.constEnd()) {
+ d->query->prepare(QLatin1String("INSERT INTO FileNameTable (FolderId, Name, FileId, Title) "
+ " VALUES (?, ?, ?, ?)"));
+ d->query->bindValue(0, 1);
+ d->query->bindValue(1, (*fileNameIt).name);
+ d->query->bindValue(2, (*fileNameIt).fileId);
+ d->query->bindValue(3, (*fileNameIt).title);
+ d->query->exec();
+ ++fileNameIt;
+ }
+ d->query->exec(QLatin1String("COMMIT"));
+ }
+
+ d->query->exec(QLatin1String("SELECT MAX(Id) FROM FileDataTable"));
+ if (d->query->next()
+ && d->query->value(0).toInt() == tableFileId-1) {
+ addProgress(d->fileStep*(i%20));
+ return true;
+ }
+ return false;
+}
+
+bool QHelpGenerator::registerCustomFilter(const QString &filterName, const QStringList &filterAttribs,
+ bool forceUpdate)
+{
+ if (!d->query)
+ return false;
+
+ d->query->exec(QLatin1String("SELECT Id, Name FROM FilterAttributeTable"));
+ QStringList idsToInsert = filterAttribs;
+ QMap<QString, int> attributeMap;
+ while (d->query->next()) {
+ attributeMap.insert(d->query->value(1).toString(),
+ d->query->value(0).toInt());
+ if (idsToInsert.contains(d->query->value(1).toString()))
+ idsToInsert.removeAll(d->query->value(1).toString());
+ }
+
+ foreach (QString id, idsToInsert) {
+ d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ d->query->bindValue(0, id);
+ d->query->exec();
+ attributeMap.insert(id, d->query->lastInsertId().toInt());
+ }
+
+ int nameId = -1;
+ d->query->prepare(QLatin1String("SELECT Id FROM FilterNameTable WHERE Name=?"));
+ d->query->bindValue(0, filterName);
+ d->query->exec();
+ while (d->query->next()) {
+ nameId = d->query->value(0).toInt();
+ break;
+ }
+
+ if (nameId < 0) {
+ d->query->prepare(QLatin1String("INSERT INTO FilterNameTable VALUES(NULL, ?)"));
+ d->query->bindValue(0, filterName);
+ if (d->query->exec())
+ nameId = d->query->lastInsertId().toInt();
+ } else if (!forceUpdate) {
+ d->error = tr("The filter %1 is already registered!").arg(filterName);
+ return false;
+ }
+
+ if (nameId < 0) {
+ d->error = tr("Cannot register filter %1!").arg(filterName);
+ return false;
+ }
+
+ d->query->prepare(QLatin1String("DELETE FROM FilterTable WHERE NameId=?"));
+ d->query->bindValue(0, nameId);
+ d->query->exec();
+
+ foreach (QString att, filterAttribs) {
+ d->query->prepare(QLatin1String("INSERT INTO FilterTable VALUES(?, ?)"));
+ d->query->bindValue(0, nameId);
+ d->query->bindValue(1, attributeMap[att]);
+ if (!d->query->exec())
+ return false;
+ }
+ return true;
+}
+
+bool QHelpGenerator::insertKeywords(const QList<QHelpDataIndexItem> keywords,
+ const QStringList &filterAttributes)
+{
+ if (!d->query)
+ return false;
+
+ emit statusChanged(tr("Insert indices..."));
+ int indexId = 1;
+ d->query->exec(QLatin1String("SELECT MAX(Id) FROM IndexTable"));
+ if (d->query->next())
+ indexId = d->query->value(0).toInt() + 1;
+
+ QList<int> filterAtts;
+ foreach (QString filterAtt, filterAttributes) {
+ d->query->prepare(QLatin1String("SELECT Id FROM FilterAttributeTable WHERE Name=?"));
+ d->query->bindValue(0, filterAtt);
+ d->query->exec();
+ if (d->query->next())
+ filterAtts.append(d->query->value(0).toInt());
+ }
+
+ int pos = -1;
+ QString fileName;
+ QString anchor;
+ QString fName;
+ int fileId = 1;
+ QList<int> indexFilterTable;
+
+ int i = 0;
+ d->query->exec(QLatin1String("BEGIN"));
+ foreach (QHelpDataIndexItem itm, keywords) {
+ pos = itm.reference.indexOf(QLatin1Char('#'));
+ fileName = itm.reference.left(pos);
+ if (pos > -1)
+ anchor = itm.reference.mid(pos+1);
+ else
+ anchor.clear();
+
+ fName = QDir::cleanPath(fileName);
+ if (fName.startsWith(QLatin1String("./")))
+ fName = fName.mid(2);
+
+ if (d->fileMap.contains(fName))
+ fileId = d->fileMap.value(fName);
+ else
+ fileId = 1;
+
+ d->query->prepare(QLatin1String("INSERT INTO IndexTable (Name, Identifier, NamespaceId, FileId, Anchor) "
+ "VALUES(?, ?, ?, ?, ?)"));
+ d->query->bindValue(0, itm.name);
+ d->query->bindValue(1, itm.identifier);
+ d->query->bindValue(2, d->namespaceId);
+ d->query->bindValue(3, fileId);
+ d->query->bindValue(4, anchor);
+ d->query->exec();
+
+ indexFilterTable.append(indexId++);
+ if (++i%100 == 0)
+ addProgress(d->indexStep*100.0);
+ }
+ d->query->exec(QLatin1String("COMMIT"));
+
+ d->query->exec(QLatin1String("BEGIN"));
+ foreach (int idx, indexFilterTable) {
+ foreach (int a, filterAtts) {
+ d->query->prepare(QLatin1String("INSERT INTO IndexFilterTable (FilterAttributeId, IndexId) "
+ "VALUES(?, ?)"));
+ d->query->bindValue(0, a);
+ d->query->bindValue(1, idx);
+ d->query->exec();
+ }
+ }
+ d->query->exec(QLatin1String("COMMIT"));
+
+ d->query->exec(QLatin1String("SELECT COUNT(Id) FROM IndexTable"));
+ if (d->query->next() && d->query->value(0).toInt() >= keywords.count())
+ return true;
+ return false;
+}
+
+bool QHelpGenerator::insertContents(const QByteArray &ba,
+ const QStringList &filterAttributes)
+{
+ if (!d->query)
+ return false;
+
+ emit statusChanged(tr("Insert contents..."));
+ d->query->prepare(QLatin1String("INSERT INTO ContentsTable (NamespaceId, Data) "
+ "VALUES(?, ?)"));
+ d->query->bindValue(0, d->namespaceId);
+ d->query->bindValue(1, ba);
+ d->query->exec();
+ int contentId = d->query->lastInsertId().toInt();
+ if (contentId < 1) {
+ d->error = tr("Cannot insert contents!");
+ return false;
+ }
+
+ // associate the filter attributes
+ foreach (QString filterAtt, filterAttributes) {
+ d->query->prepare(QLatin1String("INSERT INTO ContentsFilterTable (FilterAttributeId, ContentsId) "
+ "SELECT Id, ? FROM FilterAttributeTable WHERE Name=?"));
+ d->query->bindValue(0, contentId);
+ d->query->bindValue(1, filterAtt);
+ d->query->exec();
+ if (!d->query->isActive()) {
+ d->error = tr("Cannot register contents!");
+ return false;
+ }
+ }
+ addProgress(d->contentStep);
+ return true;
+}
+
+bool QHelpGenerator::insertFilterAttributes(const QStringList &attributes)
+{
+ if (!d->query)
+ return false;
+
+ d->query->exec(QLatin1String("SELECT Name FROM FilterAttributeTable"));
+ QSet<QString> atts;
+ while (d->query->next())
+ atts.insert(d->query->value(0).toString());
+
+ foreach (QString s, attributes) {
+ if (!atts.contains(s)) {
+ d->query->prepare(QLatin1String("INSERT INTO FilterAttributeTable VALUES(NULL, ?)"));
+ d->query->bindValue(0, s);
+ d->query->exec();
+ }
+ }
+ return true;
+}
+
+bool QHelpGenerator::insertMetaData(const QMap<QString, QVariant> &metaData)
+{
+ if (!d->query)
+ return false;
+
+ QMap<QString, QVariant>::const_iterator it = metaData.constBegin();
+ while (it != metaData.constEnd()) {
+ d->query->prepare(QLatin1String("INSERT INTO MetaDataTable VALUES(?, ?)"));
+ d->query->bindValue(0, it.key());
+ d->query->bindValue(1, it.value());
+ d->query->exec();
+ ++it;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpgenerator_p.h b/tools/assistant/lib/qhelpgenerator_p.h
new file mode 100644
index 0000000000..ddf2aed466
--- /dev/null
+++ b/tools/assistant/lib/qhelpgenerator_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPGENERATOR_H
+#define QHELPGENERATOR_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhelp_global.h"
+#include "qhelpdatainterface_p.h"
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QHelpGeneratorPrivate;
+
+class QHELP_EXPORT QHelpGenerator : public QObject
+{
+ Q_OBJECT
+
+public:
+ QHelpGenerator(QObject *parent = 0);
+ ~QHelpGenerator();
+
+ bool generate(QHelpDataInterface *helpData,
+ const QString &outputFileName);
+ QString error() const;
+
+Q_SIGNALS:
+ void statusChanged(const QString &msg);
+ void progressChanged(double progress);
+ void warning(const QString &msg);
+
+private:
+ struct FileNameTableData
+ {
+ QString name;
+ int fileId;
+ QString title;
+ };
+
+ void writeTree(QDataStream &s, QHelpDataContentItem *item, int depth);
+ bool createTables();
+ bool insertFileNotFoundFile();
+ bool registerCustomFilter(const QString &filterName,
+ const QStringList &filterAttribs, bool forceUpdate = false);
+ bool registerVirtualFolder(const QString &folderName, const QString &ns);
+ bool insertFilterAttributes(const QStringList &attributes);
+ bool insertKeywords(const QList<QHelpDataIndexItem> keywords,
+ const QStringList &filterAttributes);
+ bool insertFiles(const QStringList &files, const QString &rootPath,
+ const QStringList &filterAttributes);
+ bool insertContents(const QByteArray &ba,
+ const QStringList &filterAttributes);
+ bool insertMetaData(const QMap<QString, QVariant> &metaData);
+ void cleanupDB();
+ void setupProgress(QHelpDataInterface *helpData);
+ void addProgress(double step);
+
+ QHelpGeneratorPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/assistant/lib/qhelpindexwidget.cpp b/tools/assistant/lib/qhelpindexwidget.cpp
new file mode 100644
index 0000000000..7db9867584
--- /dev/null
+++ b/tools/assistant/lib/qhelpindexwidget.cpp
@@ -0,0 +1,445 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpindexwidget.h"
+#include "qhelpenginecore.h"
+#include "qhelpengine_p.h"
+#include "qhelpdbreader_p.h"
+
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtGui/QListView>
+#include <QtGui/QHeaderView>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpIndexProvider : public QThread
+{
+public:
+ QHelpIndexProvider(QHelpEnginePrivate *helpEngine);
+ ~QHelpIndexProvider();
+ void collectIndices(const QString &customFilterName);
+ void stopCollecting();
+ QStringList indices() const;
+ QList<QHelpDBReader*> activeReaders() const;
+ QSet<int> indexIds(QHelpDBReader *reader) const;
+
+private:
+ void run();
+
+ QHelpEnginePrivate *m_helpEngine;
+ QStringList m_indices;
+ QList<QHelpDBReader*> m_activeReaders;
+ QMap<QHelpDBReader*, QSet<int> > m_indexIds;
+ QStringList m_filterAttributes;
+ mutable QMutex m_mutex;
+ bool m_abort;
+};
+
+class QHelpIndexModelPrivate
+{
+public:
+ QHelpIndexModelPrivate(QHelpEnginePrivate *hE)
+ {
+ helpEngine = hE;
+ indexProvider = new QHelpIndexProvider(helpEngine);
+ insertedRows = 0;
+ }
+
+ QHelpEnginePrivate *helpEngine;
+ QHelpIndexProvider *indexProvider;
+ QStringList indices;
+ int insertedRows;
+ QString currentFilter;
+ QList<QHelpDBReader*> activeReaders;
+};
+
+static bool caseInsensitiveLessThan(const QString &as, const QString &bs)
+{
+ return QString::compare(as, bs, Qt::CaseInsensitive) < 0;
+}
+
+QHelpIndexProvider::QHelpIndexProvider(QHelpEnginePrivate *helpEngine)
+ : QThread(helpEngine)
+{
+ m_helpEngine = helpEngine;
+ m_abort = false;
+}
+
+QHelpIndexProvider::~QHelpIndexProvider()
+{
+ stopCollecting();
+}
+
+void QHelpIndexProvider::collectIndices(const QString &customFilterName)
+{
+ m_mutex.lock();
+ m_filterAttributes = m_helpEngine->q->filterAttributes(customFilterName);
+ m_mutex.unlock();
+ if (!isRunning()) {
+ start(LowPriority);
+ } else {
+ stopCollecting();
+ start(LowPriority);
+ }
+}
+
+void QHelpIndexProvider::stopCollecting()
+{
+ if (!isRunning())
+ return;
+ m_mutex.lock();
+ m_abort = true;
+ m_mutex.unlock();
+ wait();
+}
+
+QStringList QHelpIndexProvider::indices() const
+{
+ QMutexLocker lck(&m_mutex);
+ return m_indices;
+}
+
+QList<QHelpDBReader*> QHelpIndexProvider::activeReaders() const
+{
+ QMutexLocker lck(&m_mutex);
+ return m_activeReaders;
+}
+
+QSet<int> QHelpIndexProvider::indexIds(QHelpDBReader *reader) const
+{
+ QMutexLocker lck(&m_mutex);
+ if (m_indexIds.contains(reader))
+ return m_indexIds.value(reader);
+ return QSet<int>();
+}
+
+void QHelpIndexProvider::run()
+{
+ m_mutex.lock();
+ QStringList atts = m_filterAttributes;
+ m_indices.clear();
+ m_activeReaders.clear();
+ QSet<QString> indicesSet;
+ m_mutex.unlock();
+
+ foreach (QString dbFileName, m_helpEngine->fileNameReaderMap.keys()) {
+ m_mutex.lock();
+ if (m_abort) {
+ m_abort = false;
+ m_mutex.unlock();
+ return;
+ }
+ m_mutex.unlock();
+ QHelpDBReader reader(dbFileName,
+ QHelpGlobal::uniquifyConnectionName(dbFileName +
+ QLatin1String("FromIndexProvider"),
+ QThread::currentThread()), 0);
+ if (!reader.init())
+ continue;
+ QStringList lst = reader.indicesForFilter(atts);
+ if (!lst.isEmpty()) {
+ m_mutex.lock();
+ foreach (QString s, lst)
+ indicesSet.insert(s);
+ if (m_abort) {
+ m_abort = false;
+ m_mutex.unlock();
+ return;
+ }
+ QHelpDBReader *orgReader = m_helpEngine->fileNameReaderMap.value(dbFileName);
+ m_indexIds.insert(orgReader, reader.indexIds(atts));
+ m_activeReaders.append(orgReader);
+ m_mutex.unlock();
+ }
+ }
+ m_mutex.lock();
+ m_indices = indicesSet.values();
+ qSort(m_indices.begin(), m_indices.end(), caseInsensitiveLessThan);
+ m_abort = false;
+ m_mutex.unlock();
+}
+
+
+
+/*!
+ \class QHelpIndexModel
+ \since 4.4
+ \inmodule QtHelp
+ \brief The QHelpIndexModel class provides a model that
+ supplies index keywords to views.
+
+
+*/
+
+/*!
+ \fn void QHelpIndexModel::indexCreationStarted()
+
+ This signal is emitted when the creation of a new index
+ has started. The current index is invalid from this
+ point on until the signal indexCreated() is emitted.
+
+ \sa isCreatingIndex()
+*/
+
+/*!
+ \fn void QHelpIndexModel::indexCreated()
+
+ This signal is emitted when the index has been created.
+*/
+
+QHelpIndexModel::QHelpIndexModel(QHelpEnginePrivate *helpEngine)
+ : QStringListModel(helpEngine)
+{
+ d = new QHelpIndexModelPrivate(helpEngine);
+
+ connect(d->indexProvider, SIGNAL(finished()), this, SLOT(insertIndices()));
+ connect(helpEngine->q, SIGNAL(setupStarted()), this, SLOT(invalidateIndex()));
+}
+
+QHelpIndexModel::~QHelpIndexModel()
+{
+ delete d;
+}
+
+void QHelpIndexModel::invalidateIndex(bool onShutDown)
+{
+ if (onShutDown)
+ disconnect(this, SLOT(insertIndices()));
+ d->indexProvider->stopCollecting();
+ d->indices.clear();
+ filter(QString());
+}
+
+/*!
+ Creates a new index by querying the help system for
+ keywords for the specified \a customFilterName.
+*/
+void QHelpIndexModel::createIndex(const QString &customFilterName)
+{
+ d->currentFilter = customFilterName;
+ d->indexProvider->collectIndices(customFilterName);
+ emit indexCreationStarted();
+}
+
+void QHelpIndexModel::insertIndices()
+{
+ d->indices = d->indexProvider->indices();
+ d->activeReaders = d->indexProvider->activeReaders();
+ QStringList attributes = d->helpEngine->q->filterAttributes(d->currentFilter);
+ if (attributes.count() > 1) {
+ foreach (QHelpDBReader *r, d->activeReaders)
+ r->createAttributesCache(attributes, d->indexProvider->indexIds(r));
+ }
+ filter(QString());
+ emit indexCreated();
+}
+
+/*!
+ Returns true if the index is currently built up, otherwise
+ false.
+*/
+bool QHelpIndexModel::isCreatingIndex() const
+{
+ return d->indexProvider->isRunning();
+}
+
+/*!
+ Returns all hits found for the \a keyword. A hit consists of
+ the URL and the document title.
+*/
+QMap<QString, QUrl> QHelpIndexModel::linksForKeyword(const QString &keyword) const
+{
+ QMap<QString, QUrl> linkMap;
+ QStringList filterAttributes = d->helpEngine->q->filterAttributes(d->currentFilter);
+ foreach (QHelpDBReader *reader, d->activeReaders)
+ reader->linksForKeyword(keyword, filterAttributes, linkMap);
+ return linkMap;
+}
+
+/*!
+ Filters the indices and returns the model index of the best
+ matching keyword. In a first step, only the keywords containing
+ \a filter are kept in the model's index list. Analogously, if
+ \a wildcard is not empty, only the keywords matched are left
+ in the index list. In a second step, the best match is
+ determined and its index model returned. When specifying a
+ wildcard expression, the \a filter string is used to
+ search for the best match.
+*/
+QModelIndex QHelpIndexModel::filter(const QString &filter, const QString &wildcard)
+{
+ if (filter.isEmpty()) {
+ setStringList(d->indices);
+ return index(-1, 0, QModelIndex());
+ }
+
+ QStringList lst;
+ int goodMatch = -1;
+ int perfectMatch = -1;
+
+ if (!wildcard.isEmpty()) {
+ QRegExp regExp(wildcard, Qt::CaseInsensitive);
+ regExp.setPatternSyntax(QRegExp::Wildcard);
+ foreach (QString index, d->indices) {
+ if (index.contains(regExp)) {
+ lst.append(index);
+ if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) {
+ if (goodMatch == -1)
+ goodMatch = lst.count()-1;
+ if (filter.length() == index.length()){
+ perfectMatch = lst.count()-1;
+ }
+ } else if (perfectMatch > -1 && index == filter) {
+ perfectMatch = lst.count()-1;
+ }
+ }
+ }
+ } else {
+ foreach (QString index, d->indices) {
+ if (index.contains(filter, Qt::CaseInsensitive)) {
+ lst.append(index);
+ if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) {
+ if (goodMatch == -1)
+ goodMatch = lst.count()-1;
+ if (filter.length() == index.length()){
+ perfectMatch = lst.count()-1;
+ }
+ } else if (perfectMatch > -1 && index == filter) {
+ perfectMatch = lst.count()-1;
+ }
+ }
+ }
+
+ }
+
+ if (perfectMatch == -1)
+ perfectMatch = qMax(0, goodMatch);
+
+ setStringList(lst);
+ return index(perfectMatch, 0, QModelIndex());
+}
+
+
+
+/*!
+ \class QHelpIndexWidget
+ \inmodule QtHelp
+ \since 4.4
+ \brief The QHelpIndexWidget class provides a list view
+ displaying the QHelpIndexModel.
+*/
+
+/*!
+ \fn void QHelpIndexWidget::linkActivated(const QUrl &link,
+ const QString &keyword)
+
+ This signal is emitted when an item is activated and its
+ associated \a link should be shown. To know where the link
+ belongs to, the \a keyword is given as a second paremeter.
+*/
+
+/*!
+ \fn void QHelpIndexWidget::linksActivated(const QMap<QString, QUrl> &links,
+ const QString &keyword)
+
+ This signal is emitted when the item representing the \a keyword
+ is activated and the item has more than one link associated.
+ The \a links consist of the document title and their URL.
+*/
+
+QHelpIndexWidget::QHelpIndexWidget()
+ : QListView(0)
+{
+ setEditTriggers(QAbstractItemView::NoEditTriggers);
+ setUniformItemSizes(true);
+ connect(this, SIGNAL(activated(const QModelIndex&)),
+ this, SLOT(showLink(const QModelIndex&)));
+}
+
+void QHelpIndexWidget::showLink(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return;
+
+ QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel*>(model());
+ if (!indexModel)
+ return;
+ QVariant v = indexModel->data(index, Qt::DisplayRole);
+ QString name;
+ if (v.isValid())
+ name = v.toString();
+
+ QMap<QString, QUrl> links = indexModel->linksForKeyword(name);
+ if (links.count() == 1) {
+ emit linkActivated(links.constBegin().value(), name);
+ } else if (links.count() > 1) {
+ emit linksActivated(links, name);
+ }
+}
+
+/*!
+ Activates the current item which will result eventually in
+ the emitting of a linkActivated() or linksActivated()
+ signal.
+*/
+void QHelpIndexWidget::activateCurrentItem()
+{
+ showLink(currentIndex());
+}
+
+/*!
+ Filters the indices according to \a filter or \a wildcard.
+ The item with the best match is set as current item.
+
+ \sa QHelpIndexModel::filter()
+*/
+void QHelpIndexWidget::filterIndices(const QString &filter, const QString &wildcard)
+{
+ QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel*>(model());
+ if (!indexModel)
+ return;
+ QModelIndex idx = indexModel->filter(filter, wildcard);
+ if (idx.isValid())
+ setCurrentIndex(idx);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpindexwidget.h b/tools/assistant/lib/qhelpindexwidget.h
new file mode 100644
index 0000000000..46b9e4c95c
--- /dev/null
+++ b/tools/assistant/lib/qhelpindexwidget.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPINDEXWIDGET_H
+#define QHELPINDEXWIDGET_H
+
+#include <QtHelp/qhelp_global.h>
+
+#include <QtCore/QUrl>
+#include <QtGui/QStringListModel>
+#include <QtGui/QListView>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+class QHelpEnginePrivate;
+class QHelpIndexModelPrivate;
+
+class QHELP_EXPORT QHelpIndexModel : public QStringListModel
+{
+ Q_OBJECT
+
+public:
+ void createIndex(const QString &customFilterName);
+ QModelIndex filter(const QString &filter,
+ const QString &wildcard = QString());
+
+ QMap<QString, QUrl> linksForKeyword(const QString &keyword) const;
+ bool isCreatingIndex() const;
+
+Q_SIGNALS:
+ void indexCreationStarted();
+ void indexCreated();
+
+private Q_SLOTS:
+ void insertIndices();
+ void invalidateIndex(bool onShutDown = false);
+
+private:
+ QHelpIndexModel(QHelpEnginePrivate *helpEngine);
+ ~QHelpIndexModel();
+
+ QHelpIndexModelPrivate *d;
+ friend class QHelpEnginePrivate;
+};
+
+class QHELP_EXPORT QHelpIndexWidget : public QListView
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void linkActivated(const QUrl &link, const QString &keyword);
+ void linksActivated(const QMap<QString, QUrl> &links,
+ const QString &keyword);
+
+public Q_SLOTS:
+ void filterIndices(const QString &filter,
+ const QString &wildcard = QString());
+ void activateCurrentItem();
+
+private Q_SLOTS:
+ void showLink(const QModelIndex &index);
+
+private:
+ QHelpIndexWidget();
+ friend class QHelpEngine;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/assistant/lib/qhelpprojectdata.cpp b/tools/assistant/lib/qhelpprojectdata.cpp
new file mode 100644
index 0000000000..fcb8cf6753
--- /dev/null
+++ b/tools/assistant/lib/qhelpprojectdata.cpp
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpprojectdata_p.h"
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QStack>
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+#include <QtXml/QXmlStreamReader>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpProjectDataPrivate : public QXmlStreamReader
+{
+public:
+ void readData(const QByteArray &contents);
+
+ QString virtualFolder;
+ QString namespaceName;
+ QString rootPath;
+
+ QStringList fileList;
+ QList<QHelpDataCustomFilter> customFilterList;
+ QList<QHelpDataFilterSection> filterSectionList;
+ QMap<QString, QVariant> metaData;
+
+ QString errorMsg;
+
+private:
+ void readProject();
+ void readCustomFilter();
+ void readFilterSection();
+ void readTOC();
+ void readKeywords();
+ void readFiles();
+ void raiseUnknownTokenError();
+};
+
+void QHelpProjectDataPrivate::raiseUnknownTokenError()
+{
+ raiseError(QObject::tr("Unknown token."));
+}
+
+void QHelpProjectDataPrivate::readData(const QByteArray &contents)
+{
+ addData(contents);
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("QtHelpProject")
+ && attributes().value(QLatin1String("version")) == QLatin1String("1.0"))
+ readProject();
+ else
+ raiseError(QObject::tr("Unknown token. Expected \"QtHelpProject\"!"));
+ }
+ }
+
+ if (hasError()) {
+ raiseError(QObject::tr("Error in line %1: %2").arg(lineNumber())
+ .arg(errorString()));
+ }
+}
+
+void QHelpProjectDataPrivate::readProject()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("virtualFolder")) {
+ virtualFolder = readElementText();
+ if (virtualFolder.contains(QLatin1String("/")))
+ raiseError(QObject::tr("A virtual folder must not contain a \'/\' character!"));
+ } else if (name() == QLatin1String("namespace")) {
+ namespaceName = readElementText();
+ if (namespaceName.contains(QLatin1String("/")))
+ raiseError(QObject::tr("A namespace must not contain a \'/\' character!"));
+ } else if (name() == QLatin1String("customFilter")) {
+ readCustomFilter();
+ } else if (name() == QLatin1String("filterSection")) {
+ readFilterSection();
+ } else if (name() == QLatin1String("metaData")) {
+ QString n = attributes().value(QLatin1String("name")).toString();
+ if (!metaData.contains(n))
+ metaData[n] = attributes().value(QLatin1String("value")).toString();
+ else
+ metaData.insert(n, attributes().value(QLatin1String("value")).toString());
+ } else {
+ raiseUnknownTokenError();
+ }
+ } else if (isEndElement() && name() == QLatin1String("QtHelpProject")) {
+ if (namespaceName.isEmpty())
+ raiseError(QObject::tr("Missing namespace in QtHelpProject."));
+ else if (virtualFolder.isEmpty())
+ raiseError(QObject::tr("Missing virtual folder in QtHelpProject"));
+ break;
+ }
+ }
+}
+
+void QHelpProjectDataPrivate::readCustomFilter()
+{
+ QHelpDataCustomFilter filter;
+ filter.name = attributes().value(QLatin1String("name")).toString();
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("filterAttribute"))
+ filter.filterAttributes.append(readElementText());
+ else
+ raiseUnknownTokenError();
+ } else if (isEndElement() && name() == QLatin1String("customFilter")) {
+ break;
+ }
+ }
+ customFilterList.append(filter);
+}
+
+void QHelpProjectDataPrivate::readFilterSection()
+{
+ filterSectionList.append(QHelpDataFilterSection());
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("filterAttribute"))
+ filterSectionList.last().addFilterAttribute(readElementText());
+ else if (name() == QLatin1String("toc"))
+ readTOC();
+ else if (name() == QLatin1String("keywords"))
+ readKeywords();
+ else if (name() == QLatin1String("files"))
+ readFiles();
+ else
+ raiseUnknownTokenError();
+ } else if (isEndElement() && name() == QLatin1String("filterSection")) {
+ break;
+ }
+ }
+}
+
+void QHelpProjectDataPrivate::readTOC()
+{
+ QStack<QHelpDataContentItem*> contentStack;
+ QHelpDataContentItem *itm = 0;
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("section")) {
+ QString title = attributes().value(QLatin1String("title")).toString();
+ QString ref = attributes().value(QLatin1String("ref")).toString();
+ if (contentStack.isEmpty()) {
+ itm = new QHelpDataContentItem(0, title, ref);
+ filterSectionList.last().addContent(itm);
+ } else {
+ itm = new QHelpDataContentItem(contentStack.top(), title, ref);
+ }
+ contentStack.push(itm);
+ } else {
+ raiseUnknownTokenError();
+ }
+ } else if (isEndElement()) {
+ if (name() == QLatin1String("section")) {
+ contentStack.pop();
+ continue;
+ } else if (name() == QLatin1String("toc") && contentStack.isEmpty()) {
+ break;
+ } else {
+ raiseUnknownTokenError();
+ }
+ }
+ }
+}
+
+void QHelpProjectDataPrivate::readKeywords()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("keyword")) {
+ if (attributes().value(QLatin1String("ref")).toString().isEmpty()
+ || (attributes().value(QLatin1String("name")).toString().isEmpty()
+ && attributes().value(QLatin1String("id")).toString().isEmpty()))
+ raiseError(QObject::tr("Missing attribute in keyword at line %1.")
+ .arg(lineNumber()));
+ filterSectionList.last().addIndex(
+ QHelpDataIndexItem(attributes().value(QLatin1String("name")).toString(),
+ attributes().value(QLatin1String("id")).toString(),
+ attributes().value(QLatin1String("ref")).toString()));
+ } else {
+ raiseUnknownTokenError();
+ }
+ } else if (isEndElement()) {
+ if (name() == QLatin1String("keyword"))
+ continue;
+ else if (name() == QLatin1String("keywords"))
+ break;
+ else
+ raiseUnknownTokenError();
+ }
+ }
+}
+
+void QHelpProjectDataPrivate::readFiles()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("file"))
+ filterSectionList.last().addFile(readElementText());
+ else
+ raiseUnknownTokenError();
+ } else if (isEndElement()) {
+ if (name() == QLatin1String("file"))
+ continue;
+ else if (name() == QLatin1String("files"))
+ break;
+ else
+ raiseUnknownTokenError();
+ }
+ }
+}
+
+
+
+/*!
+ \internal
+ \class QHelpProjectData
+ \since 4.4
+ \brief The QHelpProjectData class stores all information found
+ in a Qt help project file.
+
+ The structure is filled with data by calling readData(). The
+ specified file has to have the Qt help project file format in
+ order to be read successfully. Possible reading errors can be
+ retrieved by calling errorMessage().
+*/
+
+/*!
+ Constructs a Qt help project data structure.
+*/
+QHelpProjectData::QHelpProjectData()
+{
+ d = new QHelpProjectDataPrivate;
+}
+
+/*!
+ Destroys the help project data.
+*/
+QHelpProjectData::~QHelpProjectData()
+{
+ delete d;
+}
+
+/*!
+ Reads the file \a fileName and stores the help data. The file has to
+ have the Qt help project file format. Returns true if the file
+ was successfully read, otherwise false.
+
+ \sa errorMessage()
+*/
+bool QHelpProjectData::readData(const QString &fileName)
+{
+ d->rootPath = QFileInfo(fileName).absolutePath();
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly)) {
+ d->errorMsg = QObject::tr("The input file %1 could not be opened!")
+ .arg(fileName);
+ return false;
+ }
+
+ d->readData(file.readAll());
+ return !d->hasError();
+}
+
+/*!
+ Returns an error message if the reading of the Qt help project
+ file failed. Otherwise, an empty QString is returned.
+
+ \sa readData()
+*/
+QString QHelpProjectData::errorMessage() const
+{
+ if (d->hasError())
+ return d->errorString();
+ return d->errorMsg;
+}
+
+/*!
+ \reimp
+*/
+QString QHelpProjectData::namespaceName() const
+{
+ return d->namespaceName;
+}
+
+/*!
+ \reimp
+*/
+QString QHelpProjectData::virtualFolder() const
+{
+ return d->virtualFolder;
+}
+
+/*!
+ \reimp
+*/
+QList<QHelpDataCustomFilter> QHelpProjectData::customFilters() const
+{
+ return d->customFilterList;
+}
+
+/*!
+ \reimp
+*/
+QList<QHelpDataFilterSection> QHelpProjectData::filterSections() const
+{
+ return d->filterSectionList;
+}
+
+/*!
+ \reimp
+*/
+QMap<QString, QVariant> QHelpProjectData::metaData() const
+{
+ return d->metaData;
+}
+
+/*!
+ \reimp
+*/
+QString QHelpProjectData::rootPath() const
+{
+ return d->rootPath;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpprojectdata_p.h b/tools/assistant/lib/qhelpprojectdata_p.h
new file mode 100644
index 0000000000..52eb723537
--- /dev/null
+++ b/tools/assistant/lib/qhelpprojectdata_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPPROJECTDATA_H
+#define QHELPPROJECTDATA_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhelp_global.h"
+#include "qhelpdatainterface_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QHelpProjectDataPrivate;
+
+class QHELP_EXPORT QHelpProjectData : public QHelpDataInterface
+{
+public:
+ QHelpProjectData();
+ ~QHelpProjectData();
+
+ bool readData(const QString &fileName);
+ QString errorMessage() const;
+
+ QString namespaceName() const;
+ QString virtualFolder() const;
+ QList<QHelpDataCustomFilter> customFilters() const;
+ QList<QHelpDataFilterSection> filterSections() const;
+ QMap<QString, QVariant> metaData() const;
+ QString rootPath() const;
+
+private:
+ QHelpProjectDataPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/assistant/lib/qhelpsearchengine.cpp b/tools/assistant/lib/qhelpsearchengine.cpp
new file mode 100644
index 0000000000..9025f4f692
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchengine.cpp
@@ -0,0 +1,445 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpenginecore.h"
+#include "qhelpsearchengine.h"
+#include "qhelpsearchquerywidget.h"
+#include "qhelpsearchresultwidget.h"
+
+#if defined(QT_CLUCENE_SUPPORT)
+# include "qhelpsearchindexreader_clucene_p.h"
+# include "qhelpsearchindexwriter_clucene_p.h"
+#else
+# include "qhelpsearchindexreader_default_p.h"
+# include "qhelpsearchindexwriter_default_p.h"
+#endif
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QVariant>
+#include <QtCore/QThread>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_CLUCENE_SUPPORT)
+ using namespace qt::fulltextsearch::clucene;
+#else
+ using namespace qt::fulltextsearch::std;
+#endif
+
+class QHelpSearchEnginePrivate : public QObject
+{
+ Q_OBJECT
+
+signals:
+ void indexingStarted();
+ void indexingFinished();
+
+ void searchingStarted();
+ void searchingFinished(int hits);
+
+private:
+ QHelpSearchEnginePrivate(QHelpEngineCore *helpEngine)
+ : queryWidget(0)
+ , resultWidget(0)
+ , helpEngine(helpEngine)
+ {
+ hitList.clear();
+ indexReader = 0;
+ indexWriter = 0;
+ }
+
+ ~QHelpSearchEnginePrivate()
+ {
+ hitList.clear();
+ delete indexReader;
+ delete indexWriter;
+ }
+
+ int hitsCount() const
+ {
+ int count = 0;
+ if (indexReader)
+ count = indexReader->hitsCount();
+
+ return count;
+ }
+
+ QList<QHelpSearchEngine::SearchHit> hits(int start, int end) const
+ {
+ QList<QHelpSearchEngine::SearchHit> returnValue;
+ if (indexReader) {
+ for (int i = start; i < end && i < hitsCount(); ++i)
+ returnValue.append(indexReader->hit(i));
+ }
+ return returnValue;
+ }
+
+ void updateIndex(bool reindex = false)
+ {
+ if (helpEngine.isNull())
+ return;
+
+ if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path()))
+ return;
+
+ if (!indexWriter) {
+ indexWriter = new QHelpSearchIndexWriter();
+
+ connect(indexWriter, SIGNAL(indexingStarted()), this, SIGNAL(indexingStarted()));
+ connect(indexWriter, SIGNAL(indexingFinished()), this, SIGNAL(indexingFinished()));
+ connect(indexWriter, SIGNAL(indexingFinished()), this, SLOT(optimizeIndex()));
+ }
+
+ if (indexWriter) {
+ indexWriter->cancelIndexing();
+ indexWriter->updateIndex(helpEngine->collectionFile(),
+ indexFilesFolder(), reindex);
+ }
+ }
+
+ void cancelIndexing()
+ {
+ if (indexWriter)
+ indexWriter->cancelIndexing();
+ }
+
+ void search(const QList<QHelpSearchQuery> &queryList)
+ {
+ if (helpEngine.isNull())
+ return;
+
+ if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path()))
+ return;
+
+ if (!indexReader) {
+ indexReader = new QHelpSearchIndexReader();
+
+ connect(indexReader, SIGNAL(searchingStarted()), this, SIGNAL(searchingStarted()));
+ connect(indexReader, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int)));
+ }
+
+ if (indexReader) {
+ m_queryList = queryList;
+ indexReader->cancelSearching();
+ indexReader->search(helpEngine->collectionFile(), indexFilesFolder(), queryList);
+ }
+ }
+
+ void cancelSearching()
+ {
+ if (indexReader)
+ indexReader->cancelSearching();
+ }
+
+ QString indexFilesFolder() const
+ {
+ QString indexFilesFolder = QLatin1String(".fulltextsearch");
+ if (helpEngine && !helpEngine->collectionFile().isEmpty()) {
+ QFileInfo fi(helpEngine->collectionFile());
+ indexFilesFolder = fi.absolutePath() + QDir::separator()
+ + QLatin1Char('.')
+ + fi.fileName().left(fi.fileName().lastIndexOf(QLatin1String(".qhc")));
+ }
+ return indexFilesFolder;
+ }
+
+private slots:
+ void optimizeIndex()
+ {
+#if defined(QT_CLUCENE_SUPPORT)
+ if (indexWriter && !helpEngine.isNull()) {
+ indexWriter->optimizeIndex();
+ }
+#endif
+ }
+
+private:
+ friend class QHelpSearchEngine;
+
+ QHelpSearchQueryWidget *queryWidget;
+ QHelpSearchResultWidget *resultWidget;
+
+ QHelpSearchIndexReader *indexReader;
+ QHelpSearchIndexWriter *indexWriter;
+
+ QPointer<QHelpEngineCore> helpEngine;
+ QList<QHelpSearchEngine::SearchHit> hitList;
+
+ QList<QHelpSearchQuery> m_queryList;
+};
+
+#include "qhelpsearchengine.moc"
+
+
+/*!
+ \class QHelpSearchQuery
+ \since 4.4
+ \inmodule QtHelp
+ \brief The QHelpSearchQuery class contains the field name and the associated
+ search term
+
+ The QHelpSearchQuery class contains the field name and the associated search
+ term. Depending on the field the search term might get split up into seperate
+ terms to be parsed differently by the search engine.
+
+ \sa QHelpSearchQueryWidget
+*/
+
+/*!
+ \fn QHelpSearchQuery::QHelpSearchQuery()
+
+ Constructs a new empty QHelpSearchQuery.
+*/
+
+/*!
+ \fn QHelpSearchQuery::QHelpSearchQuery(FieldName field, const QStringList &wordList)
+
+ Constructs a new QHelpSearchQuery and initializes it with the given \a field and \a wordList.
+*/
+
+/*!
+ \enum QHelpSearchQuery::FieldName
+ This enum type specifies the field names that are handled by the search engine.
+
+ \value DEFAULT the default field provided by the search widget, several terms should be
+ splitted and stored in the wordlist except search terms enclosed in quotes.
+ \value FUZZY a field only provided in use with clucene. Terms should be split in seperate
+ words and passed to the search engine.
+ \value WITHOUT a field only provided in use with clucene. Terms should be split in seperate
+ words and passed to the search engine.
+ \value PHRASE a field only provided in use with clucene. Terms should not be split in seperate
+ words.
+ \value ALL a field only provided in use with clucene. Terms should be split in seperate
+ words and passed to the search engine
+ \value ATLEAST a field only provided in use with clucene. Terms should be split in seperate
+ words and passed to the search engine
+*/
+
+/*!
+ \class QHelpSearchEngine
+ \since 4.4
+ \inmodule QtHelp
+ \brief The QHelpSearchEngine class provides access to widgets reusable
+ to integrate fulltext search as well as to index and search documentation.
+
+ Before the search engine can be used, one has to instantiate at least a
+ QHelpEngineCore object that needs to be passed to the search engines constructor.
+ This is required as the search engine needs to be connected to the help
+ engines setupFinished() signal to know when it can start to index documentation.
+
+ After starting the indexing process the signal indexingStarted() is emitted and
+ on the end of the indexing process the indexingFinished() is emited. To stop
+ the indexing one can call cancelIndexing().
+
+ While the indexing process has finished, the search engine can now be used to search
+ thru its index for a given term. To do this one may use the possibility of creating the
+ QHelpSearchQuery list by self or reuse the QHelpSearchQueryWidget which has the inbuild
+ functionality to set up a proper search querys list that get's passed to the search engines
+ search() function.
+
+ After the list of querys has been passed to the search engine, the signal searchingStarted()
+ is emited and after the search has finished the searchingFinished() signal is emited. The
+ search process can be stopped by calling cancelSearching().
+
+ If the search succeeds, the searchingFinished() will be called with the search hits count,
+ which can be reused to fetch the search hits from the search engine. Calling the hits()
+ function with the range of hits you would like to get will return a list of the requested
+ SearchHits. They basically constist at the moment of a pair of strings where the values
+ of that pair are the documentation file path and the page title.
+
+ To display the given hits use the QHelpSearchResultWidget or build up your own one if you need
+ more advanced functionality. Note that the QHelpSearchResultWidget can not be instantiated
+ directly, you must retrieve the widget from the search engine in use as all connections will be
+ established for you by the widget itself.
+*/
+
+/*!
+ \fn void QHelpSearchEngine::indexingStarted()
+
+ This signal is emitted when indexing process is started.
+*/
+
+/*!
+ \fn void QHelpSearchEngine::indexingFinished()
+
+ This signal is emitted when the indexing process is complete.
+*/
+
+/*!
+ \fn void QHelpSearchEngine::searchingStarted()
+
+ This signal is emitted when the search process is started.
+*/
+
+/*!
+ \fn void QHelpSearchEngine::searchingFinished(int hits)
+
+ This signal is emitted when the search process is complete.
+ The hit count is stored in \a hits.
+*/
+
+/*!
+ Constructs a new search engine with the given \a parent. The search engine
+ uses the given \a helpEngine to access the documentation that needs to be indexed.
+ The QHelpEngine's setupFinished() signal is automatically connected to the
+ QHelpSearchEngine's indexing function, so that new documentation will be indexed
+ after the signal is emited.
+*/
+QHelpSearchEngine::QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *parent)
+ : QObject(parent)
+{
+ d = new QHelpSearchEnginePrivate(helpEngine);
+
+ connect(helpEngine, SIGNAL(setupFinished()), this, SLOT(indexDocumentation()));
+
+ connect(d, SIGNAL(indexingStarted()), this, SIGNAL(indexingStarted()));
+ connect(d, SIGNAL(indexingFinished()), this, SIGNAL(indexingFinished()));
+ connect(d, SIGNAL(searchingStarted()), this, SIGNAL(searchingStarted()));
+ connect(d, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int)));
+}
+
+/*!
+ Destructs the search engine.
+*/
+QHelpSearchEngine::~QHelpSearchEngine()
+{
+ delete d;
+}
+
+/*!
+ Returns a widget to use as input widget. Depending on your search engine
+ configuration you will get a different widget with more or less subwidgets.
+*/
+QHelpSearchQueryWidget* QHelpSearchEngine::queryWidget()
+{
+ if (!d->queryWidget)
+ d->queryWidget = new QHelpSearchQueryWidget();
+
+ return d->queryWidget;
+}
+
+/*!
+ Returns a widget that can hold and display the search results.
+*/
+QHelpSearchResultWidget* QHelpSearchEngine::resultWidget()
+{
+ if (!d->resultWidget)
+ d->resultWidget = new QHelpSearchResultWidget(this);
+
+ return d->resultWidget;
+}
+
+/*!
+ Returns the amount of hits the search engine found.
+*/
+int QHelpSearchEngine::hitsCount() const
+{
+ return d->hitsCount();
+}
+
+/*!
+ \typedef QHelpSearchEngine::SearchHit
+
+ Typedef for QPair<QString, QString>.
+ The values of that pair are the documentation file path and the page title.
+
+ \sa hits()
+*/
+
+/*!
+ Returns a list of search hits within the range of \a start \a end.
+*/
+QList<QHelpSearchEngine::SearchHit> QHelpSearchEngine::hits(int start, int end) const
+{
+ return d->hits(start, end);
+}
+
+/*!
+ Returns the list of queries last searched for.
+ \since 4.5
+*/
+QList<QHelpSearchQuery> QHelpSearchEngine::query() const
+{
+ return d->m_queryList;
+}
+
+/*!
+ Forces the search engine to reindex all documentation files.
+*/
+void QHelpSearchEngine::reindexDocumentation()
+{
+ d->updateIndex(true);
+}
+
+/*!
+ Stops the indexing process.
+*/
+void QHelpSearchEngine::cancelIndexing()
+{
+ d->cancelIndexing();
+}
+
+/*!
+ Stops the search process.
+*/
+void QHelpSearchEngine::cancelSearching()
+{
+ d->cancelSearching();
+}
+
+/*!
+ Starts the search process using the given list of querys \a queryList
+ build by the search field name and the values to search for.
+*/
+void QHelpSearchEngine::search(const QList<QHelpSearchQuery> &queryList)
+{
+ d->search(queryList);
+}
+
+void QHelpSearchEngine::indexDocumentation()
+{
+ d->updateIndex();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchengine.h b/tools/assistant/lib/qhelpsearchengine.h
new file mode 100644
index 0000000000..bd14d3ef83
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchengine.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHENGINE_H
+#define QHELPSEARCHENGINE_H
+
+#include <QtHelp/qhelp_global.h>
+
+#include <QtCore/QMap>
+#include <QtCore/QUrl>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+class QHelpEngineCore;
+class QHelpSearchQueryWidget;
+class QHelpSearchResultWidget;
+class QHelpSearchEnginePrivate;
+
+class QHELP_EXPORT QHelpSearchQuery
+{
+public:
+ enum FieldName { DEFAULT = 0, FUZZY, WITHOUT, PHRASE, ALL, ATLEAST };
+
+ QHelpSearchQuery()
+ : fieldName(DEFAULT) { wordList.clear(); }
+ QHelpSearchQuery(FieldName field, const QStringList &wordList)
+ : fieldName(field), wordList(wordList) {}
+
+ FieldName fieldName;
+ QStringList wordList;
+};
+
+class QHELP_EXPORT QHelpSearchEngine : public QObject
+{
+ Q_OBJECT
+
+public:
+ QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *parent = 0);
+ ~QHelpSearchEngine();
+
+ QHelpSearchQueryWidget* queryWidget();
+ QHelpSearchResultWidget* resultWidget();
+
+ int hitsCount() const;
+
+ typedef QPair<QString, QString> SearchHit;
+ QList<SearchHit> hits(int start, int end) const;
+
+ QList<QHelpSearchQuery> query() const;
+
+public Q_SLOTS:
+ void reindexDocumentation();
+ void cancelIndexing();
+
+ void search(const QList<QHelpSearchQuery> &queryList);
+ void cancelSearching();
+
+Q_SIGNALS:
+ void indexingStarted();
+ void indexingFinished();
+
+ void searchingStarted();
+ void searchingFinished(int hits);
+
+private Q_SLOTS:
+ void indexDocumentation();
+
+private:
+ QHelpSearchEnginePrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QHELPSEARCHENGINE_H
diff --git a/tools/assistant/lib/qhelpsearchindex_default.cpp b/tools/assistant/lib/qhelpsearchindex_default.cpp
new file mode 100644
index 0000000000..defba91955
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindex_default.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpsearchindex_default_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDataStream &operator>>(QDataStream &s, Document &l)
+{
+ s >> l.docNumber;
+ s >> l.frequency;
+ return s;
+}
+
+QDataStream &operator<<(QDataStream &s, const Document &l)
+{
+ s << qint16(l.docNumber);
+ s << qint16(l.frequency);
+ return s;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchindex_default_p.h b/tools/assistant/lib/qhelpsearchindex_default_p.h
new file mode 100644
index 0000000000..b9ada2d725
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindex_default_p.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHINDEXDEFAULT_H
+#define QHELPSEARCHINDEXDEFAULT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtCore/QDataStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtHelpInternal {
+
+struct Document {
+ Document(qint16 d, qint16 f)
+ : docNumber(d), frequency(f) {}
+
+ Document()
+ : docNumber(-1), frequency(0) {}
+
+ bool operator==(const Document &doc) const {
+ return docNumber == doc.docNumber;
+ }
+ bool operator<(const Document &doc) const {
+ return frequency > doc.frequency;
+ }
+ bool operator<=(const Document &doc) const {
+ return frequency >= doc.frequency;
+ }
+ bool operator>(const Document &doc) const {
+ return frequency < doc.frequency;
+ }
+
+ qint16 docNumber;
+ qint16 frequency;
+};
+
+struct DocumentInfo : public Document {
+ DocumentInfo()
+ : Document(-1, 0), documentTitle(QString()), documentUrl(QString()) {}
+
+ DocumentInfo(qint16 d, qint16 f, const QString &title, const QString &url)
+ : Document(d, f), documentTitle(title), documentUrl(url) {}
+
+ DocumentInfo(const Document &document, const QString &title, const QString &url)
+ : Document(document.docNumber, document.frequency), documentTitle(title), documentUrl(url) {}
+
+ QString documentTitle;
+ QString documentUrl;
+};
+
+struct Entry {
+ Entry(qint16 d) { documents.append(Document(d, 1)); }
+ Entry(QVector<Document> l) : documents(l) {}
+
+ QVector<Document> documents;
+};
+
+struct PosEntry {
+ PosEntry(int p) { positions.append(p); }
+ QList<uint> positions;
+};
+
+struct Term {
+ Term() : frequency(-1) {}
+ Term(const QString &t, int f, QVector<Document> l) : term(t), frequency(f), documents(l) {}
+ QString term;
+ int frequency;
+ QVector<Document>documents;
+ bool operator<(const Term &i2) const { return frequency < i2.frequency; }
+};
+
+struct TermInfo {
+ TermInfo() : frequency(-1) {}
+ TermInfo(const QString &t, int f, QVector<DocumentInfo> l)
+ : term(t), frequency(f), documents(l) {}
+
+ bool operator<(const TermInfo &i2) const { return frequency < i2.frequency; }
+
+ QString term;
+ int frequency;
+ QVector<DocumentInfo>documents;
+};
+
+} // namespace QtHelpInternal
+
+using QtHelpInternal::Document;
+using QtHelpInternal::DocumentInfo;
+using QtHelpInternal::Entry;
+using QtHelpInternal::PosEntry;
+using QtHelpInternal::Term;
+using QtHelpInternal::TermInfo;
+
+QDataStream &operator>>(QDataStream &s, Document &l);
+QDataStream &operator<<(QDataStream &s, const Document &l);
+
+QT_END_NAMESPACE
+
+#endif // QHELPSEARCHINDEXDEFAULT_H
diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp
new file mode 100644
index 0000000000..82a3a17d3f
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp
@@ -0,0 +1,392 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpenginecore.h"
+#include "fulltextsearch/qsearchable_p.h"
+#include "fulltextsearch/qqueryparser_p.h"
+#include "fulltextsearch/qindexreader_p.h"
+#include "qhelpsearchindexreader_clucene_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QSet>
+#include <QtCore/QString>
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringList>
+#include <QtCore/QTextStream>
+#include <QtCore/QMutexLocker>
+
+QT_BEGIN_NAMESPACE
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace clucene {
+
+QHelpSearchIndexReader::QHelpSearchIndexReader()
+ : QThread()
+ , m_cancel(false)
+{
+ // nothing todo
+}
+
+QHelpSearchIndexReader::~QHelpSearchIndexReader()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ waitCondition.wakeOne();
+ mutex.unlock();
+
+ wait();
+}
+
+void QHelpSearchIndexReader::cancelSearching()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ mutex.unlock();
+}
+
+void QHelpSearchIndexReader::search(const QString &collectionFile,
+ const QString &indexFilesFolder,
+ const QList<QHelpSearchQuery> &queryList)
+{
+ QMutexLocker lock(&mutex);
+
+ this->hitList.clear();
+ this->m_cancel = false;
+ this->m_query = queryList;
+ this->m_collectionFile = collectionFile;
+ this->m_indexFilesFolder = indexFilesFolder;
+
+ start(QThread::NormalPriority);
+}
+
+int QHelpSearchIndexReader::hitsCount() const
+{
+ return hitList.count();
+}
+
+QHelpSearchEngine::SearchHit QHelpSearchIndexReader::hit(int index) const
+{
+ return hitList.at(index);
+}
+
+void QHelpSearchIndexReader::run()
+{
+ mutex.lock();
+
+ if (m_cancel) {
+ mutex.unlock();
+ return;
+ }
+
+ const QString collectionFile(this->m_collectionFile);
+ const QList<QHelpSearchQuery> &queryList = this->m_query;
+ const QString indexPath(m_indexFilesFolder);
+
+ mutex.unlock();
+
+ QHelpEngineCore engine(collectionFile, 0);
+ if (!engine.setupData())
+ return;
+
+ QFileInfo fInfo(indexPath);
+ if (fInfo.exists() && !fInfo.isWritable()) {
+ qWarning("Full Text Search, could not read index (missing permissions).");
+ return;
+ }
+
+ if(QCLuceneIndexReader::indexExists(indexPath)) {
+ mutex.lock();
+ if (m_cancel) {
+ mutex.unlock();
+ return;
+ }
+ mutex.unlock();
+
+ emit searchingStarted();
+
+#if !defined(QT_NO_EXCEPTIONS)
+ try {
+#endif
+ QCLuceneBooleanQuery booleanQuery;
+ if (!buildQuery(booleanQuery, queryList)) {
+ emit searchingFinished(0);
+ return;
+ }
+
+ const QStringList attribList = engine.filterAttributes(engine.currentFilter());
+ if (!attribList.isEmpty()) {
+ QCLuceneStandardAnalyzer analyzer;
+ QCLuceneQuery* query = QCLuceneQueryParser::parse(QLatin1String("+")
+ + attribList.join(QLatin1String(" +")), QLatin1String("attribute"),
+ analyzer);
+
+ if (!query) {
+ emit searchingFinished(0);
+ return;
+ }
+ booleanQuery.add(query, true, true, false);
+ }
+
+ QCLuceneIndexSearcher indexSearcher(indexPath);
+ QCLuceneHits hits = indexSearcher.search(booleanQuery);
+ const QStringList namespaceList = engine.registeredDocumentations();
+
+ QSet<QString> pathSet;
+ QCLuceneDocument document;
+ for (qint32 i = 0; i < hits.length(); i++) {
+ document = hits.document(i);
+ const QString path = document.get(QLatin1String("path"));
+ if (!pathSet.contains(path) && namespaceList.contains(
+ document.get(QLatin1String("namespace")), Qt::CaseInsensitive)) {
+ pathSet.insert(path);
+ hitList.append(qMakePair(path, document.get(QLatin1String("title"))));
+ }
+ document.clear();
+
+ mutex.lock();
+ if (m_cancel) {
+ mutex.unlock();
+ emit searchingFinished(0);
+ return;
+ }
+ mutex.unlock();
+ }
+
+ indexSearcher.close();
+ int count = hitList.count();
+ if (count > 0)
+ boostSearchHits(engine, hitList, queryList);
+ emit searchingFinished(hitList.count());
+
+#if !defined(QT_NO_EXCEPTIONS)
+ } catch(...) {
+ hitList.clear();
+ emit searchingFinished(0);
+ }
+#endif
+ }
+}
+
+bool QHelpSearchIndexReader::defaultQuery(const QString &term,
+ QCLuceneBooleanQuery &booleanQuery)
+{
+ QCLuceneStandardAnalyzer analyzer;
+
+ const QLatin1String c("content");
+ const QLatin1String t("titleTokenized");
+
+ QCLuceneQuery *query = QCLuceneQueryParser::parse(term, c, analyzer);
+ QCLuceneQuery *query2 = QCLuceneQueryParser::parse(term, t, analyzer);
+ if (query && query2) {
+ booleanQuery.add(query, true, false, false);
+ booleanQuery.add(query2, true, false, false);
+ return true;
+ }
+
+ return false;
+}
+
+bool QHelpSearchIndexReader::buildQuery(QCLuceneBooleanQuery &booleanQuery,
+ const QList<QHelpSearchQuery> &queryList)
+{
+ foreach (const QHelpSearchQuery query, queryList) {
+ switch (query.fieldName) {
+ case QHelpSearchQuery::FUZZY: {
+ const QLatin1String fuzzy("~");
+ foreach (const QString term, query.wordList) {
+ if (term.isEmpty() || !defaultQuery(term.toLower() + fuzzy, booleanQuery))
+ return false;
+ }
+ } break;
+
+ case QHelpSearchQuery::WITHOUT: {
+ QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords();
+ foreach (const QString term, query.wordList) {
+ if (stopWords.contains(term, Qt::CaseInsensitive))
+ continue;
+
+ QCLuceneQuery *query = new QCLuceneTermQuery(QCLuceneTerm(
+ QLatin1String("content"), term.toLower()));
+ QCLuceneQuery *query2 = new QCLuceneTermQuery(QCLuceneTerm(
+ QLatin1String("titleTokenized"), term.toLower()));
+
+ if (query && query2) {
+ booleanQuery.add(query, true, false, true);
+ booleanQuery.add(query2, true, false, true);
+ } else {
+ return false;
+ }
+ }
+ } break;
+
+ case QHelpSearchQuery::PHRASE: {
+ const QString term = query.wordList.at(0).toLower();
+ if (term.contains(QLatin1Char(' '))) {
+ QStringList termList = term.split(QLatin1String(" "));
+ QCLucenePhraseQuery *q = new QCLucenePhraseQuery();
+ QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords();
+ foreach (const QString t, termList) {
+ if (!stopWords.contains(t, Qt::CaseInsensitive))
+ q->addTerm(QCLuceneTerm(QLatin1String("content"), t.toLower()));
+ }
+ booleanQuery.add(q, true, true, false);
+ } else {
+ QCLuceneQuery *query = new QCLuceneTermQuery(QCLuceneTerm(
+ QLatin1String("content"), term.toLower()));
+ QCLuceneQuery *query2 = new QCLuceneTermQuery(QCLuceneTerm(
+ QLatin1String("titleTokenized"), term.toLower()));
+
+ if (query && query2) {
+ booleanQuery.add(query, true, true, false);
+ booleanQuery.add(query2, true, false, false);
+ } else {
+ return false;
+ }
+ }
+ } break;
+
+ case QHelpSearchQuery::ALL: {
+ QStringList stopWords = QCLuceneStopAnalyzer().englishStopWords();
+ foreach (const QString term, query.wordList) {
+ if (stopWords.contains(term, Qt::CaseInsensitive))
+ continue;
+
+ QCLuceneQuery *query = new QCLuceneTermQuery(QCLuceneTerm(
+ QLatin1String("content"), term.toLower()));
+
+ if (query) {
+ booleanQuery.add(query, true, true, false);
+ } else {
+ return false;
+ }
+ }
+ } break;
+
+ case QHelpSearchQuery::DEFAULT: {
+ QCLuceneStandardAnalyzer analyzer;
+ foreach (const QString t, query.wordList) {
+ QCLuceneQuery *query = QCLuceneQueryParser::parse(t.toLower(),
+ QLatin1String("content"), analyzer);
+
+ if (query)
+ booleanQuery.add(query, true, true, false);
+ }
+ } break;
+
+ case QHelpSearchQuery::ATLEAST: {
+ foreach (const QString term, query.wordList) {
+ if (term.isEmpty() || !defaultQuery(term.toLower(), booleanQuery))
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+void QHelpSearchIndexReader::boostSearchHits(const QHelpEngineCore &engine,
+ QList<QHelpSearchEngine::SearchHit> &hitList,
+ const QList<QHelpSearchQuery> &queryList)
+{
+ foreach (const QHelpSearchQuery query, queryList) {
+ if (query.fieldName != QHelpSearchQuery::DEFAULT)
+ continue;
+
+ QString joinedQuery = query.wordList.join(QLatin1String(" "));
+
+ QCLuceneStandardAnalyzer analyzer;
+ QCLuceneQuery *parsedQuery = QCLuceneQueryParser::parse(
+ joinedQuery, QLatin1String("content"), analyzer);
+
+ if (parsedQuery) {
+ joinedQuery = parsedQuery->toString();
+ delete parsedQuery;
+ }
+
+ int length = QString(QLatin1String("content:")).length();
+ int index = joinedQuery.indexOf(QLatin1String("content:"));
+
+ QString term;
+ int nextIndex = 0;
+ QStringList searchTerms;
+ while (index != -1) {
+ nextIndex = joinedQuery.indexOf(QLatin1String("content:"), index + 1);
+ term = joinedQuery.mid(index + length, nextIndex - (length + index))
+ .simplified();
+ if (term.startsWith(QLatin1String("\""))
+ && term.endsWith(QLatin1String("\""))) {
+ searchTerms.append(term.remove(QLatin1String("\"")));
+ } else {
+ searchTerms += term.split(QLatin1Char(' '));
+ }
+ index = nextIndex;
+ }
+ searchTerms.removeDuplicates();
+
+ int count = qMin(75, hitList.count());
+ QMap<int, QHelpSearchEngine::SearchHit> hitMap;
+ for (int i = 0; i < count; ++i) {
+ const QHelpSearchEngine::SearchHit &hit = hitList.at(i);
+ QString data = QString::fromUtf8(engine.fileData(hit.first));
+
+ int counter = 0;
+ foreach (const QString& term, searchTerms)
+ counter += data.count(term, Qt::CaseInsensitive);
+ hitMap.insertMulti(counter, hit);
+ }
+
+ QList<QHelpSearchEngine::SearchHit> boostedList;
+ QMap<int, QHelpSearchEngine::SearchHit>::const_iterator i;
+ for (i = hitMap.constEnd(), --i; i != hitMap.constBegin(); --i)
+ boostedList.append(i.value());
+ boostedList += hitList.mid(count - 1, hitList.count());
+
+ hitList = boostedList;
+ }
+}
+
+ } // namespace clucene
+ } // namespace fulltextsearch
+} // namespace qt
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h
new file mode 100644
index 0000000000..892c4e67fd
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHINDEXREADERCLUCENE_H
+#define QHELPSEARCHINDEXREADERCLUCENE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhelpsearchengine.h"
+#include "fulltextsearch/qquery_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QThread>
+#include <QtCore/QWaitCondition>
+
+class QHelpEngineCore;
+
+QT_BEGIN_NAMESPACE
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace clucene {
+
+class QHelpSearchIndexReader : public QThread
+{
+ Q_OBJECT
+
+public:
+ QHelpSearchIndexReader();
+ ~QHelpSearchIndexReader();
+
+ void cancelSearching();
+ void search(const QString &collectionFile,
+ const QString &indexFilesFolder,
+ const QList<QHelpSearchQuery> &queryList);
+
+ int hitsCount() const;
+ QHelpSearchEngine::SearchHit hit(int index) const;
+
+signals:
+ void searchingStarted();
+ void searchingFinished(int hits);
+
+private:
+ void run();
+ bool defaultQuery(const QString &term,
+ QCLuceneBooleanQuery &booleanQuery);
+ bool buildQuery(QCLuceneBooleanQuery &booleanQuery,
+ const QList<QHelpSearchQuery> &queryList);
+ void boostSearchHits(const QHelpEngineCore &engine,
+ QList<QHelpSearchEngine::SearchHit> &hitList,
+ const QList<QHelpSearchQuery> &queryList);
+
+private:
+ QMutex mutex;
+ QList<QHelpSearchEngine::SearchHit> hitList;
+ QWaitCondition waitCondition;
+
+ bool m_cancel;
+ QString m_collectionFile;
+ QList<QHelpSearchQuery> m_query;
+ QString m_indexFilesFolder;
+};
+
+ } // namespace clucene
+ } // namespace fulltextsearch
+} // namespace qt
+
+QT_END_NAMESPACE
+
+#endif // QHELPSEARCHINDEXREADERCLUCENE_H
diff --git a/tools/assistant/lib/qhelpsearchindexreader_default.cpp b/tools/assistant/lib/qhelpsearchindexreader_default.cpp
new file mode 100644
index 0000000000..617d0d2d62
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexreader_default.cpp
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpenginecore.h"
+#include "qhelpsearchindexreader_default_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QUrl>
+#include <QtCore/QFile>
+#include <QtCore/QVariant>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDataStream>
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace std {
+
+namespace {
+ QStringList split( const QString &str )
+ {
+ QStringList lst;
+ int j = 0;
+ int i = str.indexOf(QLatin1Char('*'), j );
+
+ if (str.startsWith(QLatin1String("*")))
+ lst << QLatin1String("*");
+
+ while ( i != -1 ) {
+ if ( i > j && i <= (int)str.length() ) {
+ lst << str.mid( j, i - j );
+ lst << QLatin1String("*");
+ }
+ j = i + 1;
+ i = str.indexOf(QLatin1Char('*'), j );
+ }
+
+ int l = str.length() - 1;
+ if ( str.mid( j, l - j + 1 ).length() > 0 )
+ lst << str.mid( j, l - j + 1 );
+
+ return lst;
+ }
+}
+
+
+Reader::Reader()
+ : indexPath(QString())
+ , indexFile(QString())
+ , documentFile(QString())
+{
+ termList.clear();
+ indexTable.clear();
+ searchIndexTable.clear();
+}
+
+Reader::~Reader()
+{
+ reset();
+ searchIndexTable.clear();
+}
+
+bool Reader::readIndex()
+{
+ if (indexTable.contains(indexFile))
+ return true;
+
+ QFile idxFile(indexFile);
+ if (!idxFile.open(QFile::ReadOnly))
+ return false;
+
+ QString key;
+ int numOfDocs;
+ EntryTable entryTable;
+ QVector<Document> docs;
+ QDataStream dictStream(&idxFile);
+ while (!dictStream.atEnd()) {
+ dictStream >> key;
+ dictStream >> numOfDocs;
+ docs.resize(numOfDocs);
+ dictStream >> docs;
+ entryTable.insert(key, new Entry(docs));
+ }
+ idxFile.close();
+
+ if (entryTable.isEmpty())
+ return false;
+
+ QFile docFile(documentFile);
+ if (!docFile.open(QFile::ReadOnly))
+ return false;
+
+ QString title, url;
+ DocumentList documentList;
+ QDataStream docStream(&docFile);
+ while (!docStream.atEnd()) {
+ docStream >> title;
+ docStream >> url;
+ documentList.append(QStringList(title) << url);
+ }
+ docFile.close();
+
+ if (documentList.isEmpty()) {
+ cleanupIndex(entryTable);
+ return false;
+ }
+
+ indexTable.insert(indexFile, Index(entryTable, documentList));
+ return true;
+}
+
+bool Reader::initCheck() const
+{
+ return !searchIndexTable.isEmpty();
+}
+
+void Reader::setIndexPath(const QString &path)
+{
+ indexPath = path;
+}
+
+void Reader::filterFilesForAttributes(const QStringList &attributes)
+{
+ searchIndexTable.clear();
+ for(IndexTable::ConstIterator it = indexTable.begin(); it != indexTable.end(); ++it) {
+ const QString fileName = it.key();
+ bool containsAll = true;
+ QStringList split = fileName.split(QLatin1String("@"));
+ foreach (const QString attribute, attributes) {
+ if (!split.contains(attribute, Qt::CaseInsensitive)) {
+ containsAll = false;
+ break;
+ }
+ }
+
+ if (containsAll)
+ searchIndexTable.insert(fileName, it.value());
+ }
+}
+
+void Reader::setIndexFile(const QString &namespaceName, const QString &attributes)
+{
+ QString extention = namespaceName + QLatin1String("@") + attributes;
+ indexFile = indexPath + QLatin1String("/indexdb40.") + extention;
+ documentFile = indexPath + QLatin1String("/indexdoc40.") + extention;
+}
+
+bool Reader::splitSearchTerm(const QString &searchTerm, QStringList *terms,
+ QStringList *termSeq, QStringList *seqWords)
+{
+ QString term = searchTerm;
+
+ term = term.simplified();
+ term = term.replace(QLatin1String("\'"), QLatin1String("\""));
+ term = term.replace(QLatin1String("`"), QLatin1String("\""));
+ term = term.replace(QLatin1String("-"), QLatin1String(" "));
+ term = term.replace(QRegExp(QLatin1String("\\s[\\S]?\\s")), QLatin1String(" "));
+
+ *terms = term.split(QLatin1Char(' '));
+ QStringList::iterator it = terms->begin();
+ for (; it != terms->end(); ++it) {
+ (*it) = (*it).simplified();
+ (*it) = (*it).toLower();
+ (*it) = (*it).replace(QLatin1String("\""), QLatin1String(""));
+ }
+
+ if (term.contains(QLatin1Char('\"'))) {
+ if ((term.count(QLatin1Char('\"')))%2 == 0) {
+ int beg = 0;
+ int end = 0;
+ QString s;
+ beg = term.indexOf(QLatin1Char('\"'), beg);
+ while (beg != -1) {
+ beg++;
+ end = term.indexOf(QLatin1Char('\"'), beg);
+ s = term.mid(beg, end - beg);
+ s = s.toLower();
+ s = s.simplified();
+ if (s.contains(QLatin1Char('*'))) {
+ qWarning("Full Text Search, using a wildcard within phrases is not allowed.");
+ return false;
+ }
+ *seqWords += s.split(QLatin1Char(' '));
+ *termSeq << s;
+ beg = term.indexOf(QLatin1Char('\"'), end + 1);
+ }
+ } else {
+ qWarning("Full Text Search, the closing quotation mark is missing.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void Reader::searchInIndex(const QStringList &terms)
+{
+ foreach (const QString term, terms) {
+ QVector<Document> documents;
+
+ for(IndexTable::ConstIterator it = searchIndexTable.begin();
+ it != searchIndexTable.end(); ++it) {
+ EntryTable entryTable = it.value().first;
+ DocumentList documentList = it.value().second;
+
+ if (term.contains(QLatin1Char('*')))
+ documents = setupDummyTerm(getWildcardTerms(term, entryTable), entryTable);
+ else if (entryTable.value(term))
+ documents = entryTable.value(term)->documents;
+ else
+ continue;
+
+ if (!documents.isEmpty()) {
+ DocumentInfo info;
+ QString title, url;
+ QVector<DocumentInfo> documentsInfo;
+ foreach(const Document doc, documents) {
+ info.docNumber = doc.docNumber;
+ info.frequency = doc.frequency;
+ info.documentUrl = documentList.at(doc.docNumber).at(1);
+ info.documentTitle = documentList.at(doc.docNumber).at(0);
+ documentsInfo.append(info);
+ }
+
+ bool found = false;
+ for(QList<TermInfo>::Iterator tit = termList.begin();
+ tit != termList.end(); ++tit) {
+ TermInfo *t = &(*tit);
+ if(t->term == term) {
+ t->documents += documentsInfo;
+ t->frequency += documentsInfo.count();
+ found = true; break;
+ }
+ }
+ if (!found)
+ termList.append(TermInfo(term, documentsInfo.count(), documentsInfo));
+ }
+ }
+ }
+ qSort(termList);
+}
+
+QVector<DocumentInfo> Reader::hits()
+{
+ QVector<DocumentInfo> documents;
+ if (!termList.count())
+ return documents;
+
+ documents = termList.takeFirst().documents;
+ for(QList<TermInfo>::Iterator it = termList.begin(); it != termList.end(); ++it) {
+ TermInfo *t = &(*it);
+ QVector<DocumentInfo> docs = t->documents;
+ for(QVector<DocumentInfo>::Iterator minDoc_it = documents.begin();
+ minDoc_it != documents.end(); ) {
+ bool found = false;
+ for (QVector<DocumentInfo>::ConstIterator doc_it = docs.constBegin();
+ doc_it != docs.constEnd(); ++doc_it ) {
+ if ( (*minDoc_it).docNumber == (*doc_it).docNumber ) {
+ (*minDoc_it).frequency += (*doc_it).frequency;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ minDoc_it = documents.erase(minDoc_it);
+ else
+ ++minDoc_it;
+ }
+ }
+
+ qSort(documents);
+ return documents;
+}
+
+bool Reader::searchForPattern(const QStringList &patterns, const QStringList &words,
+ const QByteArray &data)
+{
+ if (data.isEmpty())
+ return false;
+
+ for(QHash<QString, PosEntry*>::ConstIterator mit =
+ miniIndex.begin(); mit != miniIndex.end(); ++mit) {
+ delete mit.value();
+ }
+ miniIndex.clear();
+
+ wordNum = 3;
+ QStringList::ConstIterator cIt = words.begin();
+ for ( ; cIt != words.end(); ++cIt )
+ miniIndex.insert(*cIt, new PosEntry(0));
+
+ QTextStream s(data);
+ QString text = s.readAll();
+ bool valid = true;
+ const QChar *buf = text.unicode();
+ QChar str[64];
+ QChar c = buf[0];
+ int j = 0;
+ int i = 0;
+ while ( j < text.length() ) {
+ if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) {
+ valid = false;
+ if ( i > 1 )
+ buildMiniIndex( QString(str,i) );
+ i = 0;
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) {
+ valid = true;
+ c = buf[++j];
+ continue;
+ }
+ if ( !valid ) {
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) {
+ str[i] = c.toLower();
+ ++i;
+ } else {
+ if ( i > 1 )
+ buildMiniIndex( QString(str,i) );
+ i = 0;
+ }
+ c = buf[++j];
+ }
+ if ( i > 1 )
+ buildMiniIndex( QString(str,i) );
+
+ QStringList::ConstIterator patIt = patterns.begin();
+ QStringList wordLst;
+ QList<uint> a, b;
+ QList<uint>::iterator aIt;
+ for ( ; patIt != patterns.end(); ++patIt ) {
+ wordLst = (*patIt).split(QLatin1Char(' '));
+ a = miniIndex[ wordLst[0] ]->positions;
+ for ( int j = 1; j < (int)wordLst.count(); ++j ) {
+ b = miniIndex[ wordLst[j] ]->positions;
+ aIt = a.begin();
+ while ( aIt != a.end() ) {
+ if ( b.contains( *aIt + 1 )) {
+ (*aIt)++;
+ ++aIt;
+ } else {
+ aIt = a.erase( aIt );
+ }
+ }
+ }
+ }
+ if ( a.count() )
+ return true;
+ return false;
+}
+
+QVector<Document> Reader::setupDummyTerm(const QStringList &terms,
+ const EntryTable &entryTable)
+{
+ QList<Term> termList;
+ for (QStringList::ConstIterator it = terms.begin(); it != terms.end(); ++it) {
+ if (entryTable.value(*it)) {
+ Entry *e = entryTable.value(*it);
+ termList.append(Term(*it, e->documents.count(), e->documents ) );
+ }
+ }
+ QVector<Document> maxList(0);
+ if ( !termList.count() )
+ return maxList;
+ qSort(termList);
+
+ maxList = termList.takeLast().documents;
+ for(QList<Term>::Iterator it = termList.begin(); it != termList.end(); ++it) {
+ Term *t = &(*it);
+ QVector<Document> docs = t->documents;
+ for (QVector<Document>::iterator docIt = docs.begin(); docIt != docs.end(); ++docIt ) {
+ if ( maxList.indexOf( *docIt ) == -1 )
+ maxList.append( *docIt );
+ }
+ }
+ return maxList;
+}
+
+QStringList Reader::getWildcardTerms(const QString &term,
+ const EntryTable &entryTable)
+{
+ QStringList lst;
+ QStringList terms = split(term);
+ QStringList::Iterator iter;
+
+ for(EntryTable::ConstIterator it = entryTable.begin();
+ it != entryTable.end(); ++it) {
+ int index = 0;
+ bool found = false;
+ QString text( it.key() );
+ for ( iter = terms.begin(); iter != terms.end(); ++iter ) {
+ if ( *iter == QLatin1String("*") ) {
+ found = true;
+ continue;
+ }
+ if ( iter == terms.begin() && (*iter)[0] != text[0] ) {
+ found = false;
+ break;
+ }
+ index = text.indexOf( *iter, index );
+ if ( *iter == terms.last() && index != (int)text.length()-1 ) {
+ index = text.lastIndexOf( *iter );
+ if ( index != (int)text.length() - (int)(*iter).length() ) {
+ found = false;
+ break;
+ }
+ }
+ if ( index != -1 ) {
+ found = true;
+ index += (*iter).length();
+ continue;
+ } else {
+ found = false;
+ break;
+ }
+ }
+ if (found)
+ lst << text;
+ }
+
+ return lst;
+}
+
+void Reader::buildMiniIndex(const QString &string)
+{
+ if (miniIndex[string])
+ miniIndex[string]->positions.append(wordNum);
+ ++wordNum;
+}
+
+void Reader::reset()
+{
+ for(IndexTable::Iterator it = indexTable.begin();
+ it != indexTable.end(); ++it) {
+ cleanupIndex(it.value().first);
+ it.value().second.clear();
+ }
+}
+
+void Reader::cleanupIndex(EntryTable &entryTable)
+{
+ for(EntryTable::ConstIterator it =
+ entryTable.begin(); it != entryTable.end(); ++it) {
+ delete it.value();
+ }
+
+ entryTable.clear();
+}
+
+
+QHelpSearchIndexReader::QHelpSearchIndexReader()
+ : QThread()
+ , m_cancel(false)
+{
+ // nothing todo
+}
+
+QHelpSearchIndexReader::~QHelpSearchIndexReader()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ waitCondition.wakeOne();
+ mutex.unlock();
+
+ wait();
+}
+
+void QHelpSearchIndexReader::cancelSearching()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ mutex.unlock();
+}
+
+void QHelpSearchIndexReader::search(const QString &collectionFile,
+ const QString &indexFilesFolder,
+ const QList<QHelpSearchQuery> &queryList)
+{
+ QMutexLocker lock(&mutex);
+
+ this->hitList.clear();
+ this->m_cancel = false;
+ this->m_query = queryList;
+ this->m_collectionFile = collectionFile;
+ this->m_indexFilesFolder = indexFilesFolder;
+
+ start(QThread::NormalPriority);
+}
+
+int QHelpSearchIndexReader::hitsCount() const
+{
+ return hitList.count();
+}
+
+QHelpSearchEngine::SearchHit QHelpSearchIndexReader::hit(int index) const
+{
+ return hitList.at(index);
+}
+
+void QHelpSearchIndexReader::run()
+{
+ mutex.lock();
+
+ if (m_cancel) {
+ mutex.unlock();
+ return;
+ }
+
+ const QList<QHelpSearchQuery> &queryList = this->m_query;
+ const QLatin1String key("DefaultSearchNamespaces");
+ const QString collectionFile(this->m_collectionFile);
+ const QString indexPath = m_indexFilesFolder;
+
+ mutex.unlock();
+
+ QString queryTerm;
+ foreach (const QHelpSearchQuery query, queryList) {
+ if (query.fieldName == QHelpSearchQuery::DEFAULT) {
+ queryTerm = query.wordList.at(0);
+ break;
+ }
+ }
+
+ if (queryTerm.isEmpty())
+ return;
+
+ QHelpEngineCore engine(collectionFile, 0);
+ if (!engine.setupData())
+ return;
+
+ const QStringList registeredDocs = engine.registeredDocumentations();
+ const QStringList indexedNamespaces = engine.customValue(key).toString().
+ split(QLatin1String("|"), QString::SkipEmptyParts);
+
+ emit searchingStarted();
+
+ // setup the reader
+ m_reader.setIndexPath(indexPath);
+ foreach(const QString namespaceName, registeredDocs) {
+ mutex.lock();
+ if (m_cancel) {
+ mutex.unlock();
+ searchingFinished(0); // TODO: check this ???
+ return;
+ }
+ mutex.unlock();
+
+ const QList<QStringList> attributeSets =
+ engine.filterAttributeSets(namespaceName);
+
+ foreach (QStringList attributes, attributeSets) {
+ // read all index files
+ m_reader.setIndexFile(namespaceName, attributes.join(QLatin1String("@")));
+ if (!m_reader.readIndex()) {
+ qWarning("Full Text Search, could not read file for namespace: %s.",
+ namespaceName.toUtf8().constData());
+ }
+ }
+ }
+
+ // get the current filter attributes and minimize the index files table
+ m_reader.filterFilesForAttributes(engine.filterAttributes(engine.currentFilter()));
+
+ hitList.clear();
+ QStringList terms, termSeq, seqWords;
+ if (m_reader.initCheck() && // check if we could read anything
+ m_reader.splitSearchTerm(queryTerm, &terms, &termSeq, &seqWords) ) {
+
+ // search for term(s)
+ m_reader.searchInIndex(terms); // TODO: should this be interruptible as well ???
+
+ QVector<DocumentInfo> hits = m_reader.hits();
+ if (!hits.isEmpty()) {
+ if (termSeq.isEmpty()) {
+ foreach (const DocumentInfo docInfo, hits) {
+ mutex.lock();
+ if (m_cancel) {
+ mutex.unlock();
+ searchingFinished(0); // TODO: check this, speed issue while locking???
+ return;
+ }
+ mutex.unlock();
+ hitList.append(qMakePair(docInfo.documentTitle, docInfo.documentUrl));
+ }
+ } else {
+ foreach (const DocumentInfo docInfo, hits) {
+ mutex.lock();
+ if (m_cancel) {
+ mutex.unlock();
+ searchingFinished(0); // TODO: check this, speed issue while locking???
+ return;
+ }
+ mutex.unlock();
+
+ if (m_reader.searchForPattern(termSeq, seqWords, engine.fileData(docInfo.documentUrl))) // TODO: should this be interruptible as well ???
+ hitList.append(qMakePair(docInfo.documentTitle, docInfo.documentUrl));
+ }
+ }
+ }
+ }
+
+ emit searchingFinished(hitList.count());
+}
+
+ } // namespace std
+ } // namespace fulltextsearch
+} // namespace qt
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchindexreader_default_p.h b/tools/assistant/lib/qhelpsearchindexreader_default_p.h
new file mode 100644
index 0000000000..22480f7956
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexreader_default_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHINDEXREADERDEFAULT_H
+#define QHELPSEARCHINDEXREADERDEFAULT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhelpsearchindex_default_p.h"
+#include "qhelpsearchengine.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include <QtCore/QString>
+#include <QtCore/QThread>
+#include <QtCore/QObject>
+#include <QtCore/QVector>
+#include <QtCore/QByteArray>
+#include <QtCore/QStringList>
+#include <QtCore/QWaitCondition>
+
+QT_BEGIN_NAMESPACE
+
+struct Entry;
+struct PosEntry;
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace std {
+
+class Reader
+{
+ typedef QList<QStringList> DocumentList;
+ typedef QHash<QString, Entry*> EntryTable;
+ typedef QPair<EntryTable, DocumentList> Index;
+ typedef QHash<QString, Index> IndexTable;
+
+public:
+ Reader();
+ ~Reader();
+
+ bool readIndex();
+ bool initCheck() const;
+ void setIndexPath(const QString &path);
+ void filterFilesForAttributes(const QStringList &attributes);
+ void setIndexFile(const QString &namespaceName, const QString &attributes);
+ bool splitSearchTerm(const QString &searchTerm, QStringList *terms,
+ QStringList *termSeq, QStringList *seqWords);
+
+ void searchInIndex(const QStringList &terms);
+ QVector<DocumentInfo> hits();
+ bool searchForPattern(const QStringList &patterns,
+ const QStringList &words, const QByteArray &data);
+
+private:
+ QVector<Document> setupDummyTerm(const QStringList &terms, const EntryTable &entryTable);
+ QStringList getWildcardTerms(const QString &term, const EntryTable &entryTable);
+ void buildMiniIndex(const QString &string);
+ void reset();
+ void cleanupIndex(EntryTable &entryTable);
+
+private:
+ uint wordNum;
+ QString indexPath;
+ QString indexFile;
+ QString documentFile;
+
+ IndexTable indexTable;
+ QList<TermInfo> termList;
+ IndexTable searchIndexTable;
+ QHash<QString, PosEntry*> miniIndex;
+};
+
+
+class QHelpSearchIndexReader : public QThread
+{
+ Q_OBJECT
+
+public:
+ QHelpSearchIndexReader();
+ ~QHelpSearchIndexReader();
+
+ void cancelSearching();
+ void search(const QString &collectionFile,
+ const QString &indexFilesFolder,
+ const QList<QHelpSearchQuery> &queryList);
+
+ int hitsCount() const;
+ QHelpSearchEngine::SearchHit hit(int index) const;
+
+signals:
+ void searchingStarted();
+ void searchingFinished(int hits);
+
+private:
+ void run();
+
+private:
+ QMutex mutex;
+ Reader m_reader;
+ QWaitCondition waitCondition;
+ QList<QHelpSearchEngine::SearchHit> hitList;
+
+ bool m_cancel;
+ QList<QHelpSearchQuery> m_query;
+ QString m_collectionFile;
+ QString m_indexFilesFolder;
+};
+
+ } // namespace std
+ } // namespace fulltextsearch
+} // namespace qt
+
+QT_END_NAMESPACE
+
+#endif // QHELPSEARCHINDEXREADERDEFAULT_H
diff --git a/tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp b/tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp
new file mode 100644
index 0000000000..e53bbaecdf
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexwriter_clucene.cpp
@@ -0,0 +1,481 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpenginecore.h"
+#include "qhelp_global.h"
+#include "fulltextsearch/qhits_p.h"
+#include "fulltextsearch/qquery_p.h"
+#include "fulltextsearch/qanalyzer_p.h"
+#include "fulltextsearch/qdocument_p.h"
+#include "fulltextsearch/qsearchable_p.h"
+#include "fulltextsearch/qindexreader_p.h"
+#include "fulltextsearch/qindexwriter_p.h"
+#include "qhelpsearchindexwriter_clucene_p.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QString>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+#include <QtNetwork/QLocalSocket>
+#include <QtNetwork/QLocalServer>
+
+QT_BEGIN_NAMESPACE
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace clucene {
+
+class DocumentHelper
+{
+public:
+ DocumentHelper(const QString& fileName, const QByteArray &data)
+ : fileName(fileName) , data(readData(data)) {}
+ ~DocumentHelper() {}
+
+ bool addFieldsToDocument(QCLuceneDocument *document,
+ const QString &namespaceName, const QString &attributes = QString())
+ {
+ if (!document)
+ return false;
+
+ if(!data.isEmpty()) {
+ QString parsedData = parseData();
+ QString parsedTitle = QHelpGlobal::documentTitle(data);
+
+ if(!parsedData.isEmpty()) {
+ document->add(new QCLuceneField(QLatin1String("content"),
+ parsedData,QCLuceneField::INDEX_TOKENIZED));
+ document->add(new QCLuceneField(QLatin1String("path"), fileName,
+ QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED));
+ document->add(new QCLuceneField(QLatin1String("title"), parsedTitle,
+ QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED));
+ document->add(new QCLuceneField(QLatin1String("titleTokenized"), parsedTitle,
+ QCLuceneField::STORE_YES | QCLuceneField::INDEX_TOKENIZED));
+ document->add(new QCLuceneField(QLatin1String("namespace"), namespaceName,
+ QCLuceneField::STORE_YES | QCLuceneField::INDEX_UNTOKENIZED));
+ document->add(new QCLuceneField(QLatin1String("attribute"), attributes,
+ QCLuceneField::STORE_YES | QCLuceneField::INDEX_TOKENIZED));
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+private:
+ QString readData(const QByteArray &data)
+ {
+ QTextStream textStream(data);
+ QByteArray charSet = QHelpGlobal::charsetFromData(data).toLatin1();
+ textStream.setCodec(QTextCodec::codecForName(charSet.constData()));
+
+ QString stream = textStream.readAll();
+ if (stream.isNull() || stream.isEmpty())
+ return QString();
+
+ return stream;
+ }
+
+ QString parseData() const
+ {
+ const int length = data.length();
+ const QChar *buf = data.unicode();
+
+ QString parsedContent;
+ parsedContent.reserve(length);
+
+ bool valid = true;
+ int j = 0, count = 0;
+
+ QChar c;
+ while (j < length) {
+ c = buf[j++];
+ if (c == QLatin1Char('<') || c == QLatin1Char('&')) {
+ if (count > 1)
+ parsedContent.append(QLatin1Char(' '));
+ count = 0;
+ valid = false;
+ continue;
+ }
+ if ((c == QLatin1Char('>') || c == QLatin1Char(';')) && !valid) {
+ valid = true;
+ continue;
+ }
+ if (!valid)
+ continue;
+
+ if (c.isLetterOrNumber() || c.isPrint()) {
+ ++count;
+ parsedContent.append(c.toLower());
+ } else {
+ if (count > 1)
+ parsedContent.append(QLatin1Char(' '));
+ count = 0;
+ }
+ }
+
+ return parsedContent;
+ }
+
+private:
+ QString fileName;
+ QString data;
+};
+
+
+QHelpSearchIndexWriter::QHelpSearchIndexWriter()
+ : QThread(0)
+ , m_cancel(false)
+{
+ // nothing todo
+}
+
+QHelpSearchIndexWriter::~QHelpSearchIndexWriter()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ waitCondition.wakeOne();
+ mutex.unlock();
+
+ wait();
+}
+
+void QHelpSearchIndexWriter::cancelIndexing()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ mutex.unlock();
+}
+
+void QHelpSearchIndexWriter::updateIndex(const QString &collectionFile,
+ const QString &indexFilesFolder, bool reindex)
+{
+ mutex.lock();
+ this->m_cancel = false;
+ this->m_reindex = reindex;
+ this->m_collectionFile = collectionFile;
+ this->m_indexFilesFolder = indexFilesFolder;
+ mutex.unlock();
+
+ start(QThread::NormalPriority);
+}
+
+void QHelpSearchIndexWriter::optimizeIndex()
+{
+ if (QCLuceneIndexReader::indexExists(m_indexFilesFolder)) {
+ if (QCLuceneIndexReader::isLocked(m_indexFilesFolder))
+ return;
+
+ QCLuceneStandardAnalyzer analyzer;
+ QCLuceneIndexWriter writer(m_indexFilesFolder, analyzer, false);
+ writer.optimize();
+ writer.close();
+ }
+}
+
+void QHelpSearchIndexWriter::run()
+{
+ QMutexLocker mutexLocker(&mutex);
+
+ if (m_cancel)
+ return;
+
+ const bool reindex = this->m_reindex;
+ const QString collectionFile(this->m_collectionFile);
+
+ mutexLocker.unlock();
+
+ QHelpEngineCore engine(collectionFile, 0);
+ if (!engine.setupData())
+ return;
+
+ const QLatin1String key("CluceneIndexedNamespaces");
+ if (reindex)
+ engine.setCustomValue(key, QLatin1String(""));
+
+ QMap<QString, QDateTime> indexMap;
+ const QLatin1String oldKey("CluceneSearchNamespaces");
+ if (!engine.customValue(oldKey, QString()).isNull()) {
+ // old style qhc file < 4.4.2, need to convert...
+ const QStringList indexedNamespaces = engine.customValue(oldKey).
+ toString().split(QLatin1String("|"), QString::SkipEmptyParts);
+ foreach (const QString& nameSpace, indexedNamespaces)
+ indexMap.insert(nameSpace, QDateTime());
+ engine.removeCustomValue(oldKey);
+ } else {
+ QDataStream dataStream(engine.customValue(key).toByteArray());
+ dataStream >> indexMap;
+ }
+
+ QString indexPath = m_indexFilesFolder;
+
+ QFileInfo fInfo(indexPath);
+ if (fInfo.exists() && !fInfo.isWritable()) {
+ qWarning("Full Text Search, could not create index (missing permissions).");
+ return;
+ }
+
+ emit indexingStarted();
+
+ QCLuceneIndexWriter *writer = 0;
+ QCLuceneStandardAnalyzer analyzer;
+ const QStringList registeredDocs = engine.registeredDocumentations();
+
+ QLocalSocket localSocket;
+ localSocket.connectToServer(QString(QLatin1String("QtAssistant%1"))
+ .arg(QLatin1String(QT_VERSION_STR)));
+
+ QLocalServer localServer;
+ bool otherInstancesRunning = true;
+ if (!localSocket.waitForConnected()) {
+ otherInstancesRunning = false;
+ localServer.listen(QString(QLatin1String("QtAssistant%1"))
+ .arg(QLatin1String(QT_VERSION_STR)));
+ }
+
+#if !defined(QT_NO_EXCEPTIONS)
+ try {
+#endif
+ // check if it's locked, and if the other instance is running
+ if (!otherInstancesRunning && QCLuceneIndexReader::isLocked(indexPath))
+ QCLuceneIndexReader::unlock(indexPath);
+
+ if (QCLuceneIndexReader::isLocked(indexPath)) {
+ // poll unless indexing finished to fake progress
+ while (QCLuceneIndexReader::isLocked(indexPath)) {
+ mutexLocker.relock();
+ if (m_cancel)
+ break;
+ mutexLocker.unlock();
+ this->sleep(1);
+ }
+ emit indexingFinished();
+ return;
+ }
+
+ if (QCLuceneIndexReader::indexExists(indexPath) && !reindex) {
+ foreach(const QString& namespaceName, registeredDocs) {
+ mutexLocker.relock();
+ if (m_cancel) {
+ emit indexingFinished();
+ return;
+ }
+ mutexLocker.unlock();
+
+ if (!indexMap.contains(namespaceName)) {
+ // make sure we remove some partly indexed stuff
+ removeDocuments(indexPath, namespaceName);
+ } else {
+ QString path = engine.documentationFileName(namespaceName);
+ if (indexMap.value(namespaceName) < QFileInfo(path).lastModified()) {
+ // make sure we remove some outdated indexed stuff
+ indexMap.remove(namespaceName);
+ removeDocuments(indexPath, namespaceName);
+ }
+
+ if (indexMap.contains(namespaceName)) {
+ // make sure we really have content indexed for namespace
+ // NOTE: Extra variable just for GCC 3.3.5
+ QLatin1String key("namespace");
+ QCLuceneTermQuery query(QCLuceneTerm(key, namespaceName));
+ QCLuceneIndexSearcher indexSearcher(indexPath);
+ QCLuceneHits hits = indexSearcher.search(query);
+ if (hits.length() <= 0)
+ indexMap.remove(namespaceName);
+ }
+ }
+ }
+ writer = new QCLuceneIndexWriter(indexPath, analyzer, false);
+ } else {
+ indexMap.clear();
+ writer = new QCLuceneIndexWriter(indexPath, analyzer, true);
+ }
+#if !defined(QT_NO_EXCEPTIONS)
+ } catch (...) {
+ qWarning("Full Text Search, could not create index writer.");
+ return;
+ }
+#endif
+
+ writer->setMergeFactor(100);
+ writer->setMinMergeDocs(1000);
+ writer->setMaxFieldLength(QCLuceneIndexWriter::DEFAULT_MAX_FIELD_LENGTH);
+
+ QStringList namespaces;
+ foreach(const QString& namespaceName, registeredDocs) {
+ mutexLocker.relock();
+ if (m_cancel) {
+ writer->close();
+ delete writer;
+ emit indexingFinished();
+ return;
+ }
+ mutexLocker.unlock();
+
+ namespaces.append(namespaceName);
+ if (indexMap.contains(namespaceName))
+ continue;
+
+ const QList<QStringList> attributeSets =
+ engine.filterAttributeSets(namespaceName);
+
+ if (attributeSets.isEmpty()) {
+ const QList<QUrl> docFiles = indexableFiles(&engine, namespaceName,
+ QStringList());
+ if (!addDocuments(docFiles, engine, QStringList(), namespaceName,
+ writer, analyzer))
+ break;
+ } else {
+ bool bail = false;
+ foreach (const QStringList& attributes, attributeSets) {
+ const QList<QUrl> docFiles = indexableFiles(&engine,
+ namespaceName, attributes);
+ if (!addDocuments(docFiles, engine, attributes, namespaceName,
+ writer, analyzer)) {
+ bail = true;
+ break;
+ }
+ }
+ if (bail)
+ break;
+ }
+
+ mutexLocker.relock();
+ if (!m_cancel) {
+ QString path(engine.documentationFileName(namespaceName));
+ indexMap.insert(namespaceName, QFileInfo(path).lastModified());
+ writeIndexMap(engine, indexMap);
+ }
+ mutexLocker.unlock();
+ }
+
+ writer->close();
+ delete writer;
+
+ mutexLocker.relock();
+ if (!m_cancel) {
+ mutexLocker.unlock();
+
+ QStringList indexedNamespaces = indexMap.keys();
+ foreach(const QString& namespaceName, indexedNamespaces) {
+ mutexLocker.relock();
+ if (m_cancel)
+ break;
+ mutexLocker.unlock();
+
+ if (!namespaces.contains(namespaceName)) {
+ indexMap.remove(namespaceName);
+ writeIndexMap(engine, indexMap);
+ removeDocuments(indexPath, namespaceName);
+ }
+ }
+ }
+ emit indexingFinished();
+}
+
+bool QHelpSearchIndexWriter::addDocuments(const QList<QUrl> docFiles,
+ const QHelpEngineCore &engine, const QStringList &attributes,
+ const QString &namespaceName, QCLuceneIndexWriter *writer,
+ QCLuceneAnalyzer &analyzer)
+{
+ QMutexLocker locker(&mutex);
+ const QString attrList = attributes.join(QLatin1String(" "));
+
+ locker.unlock();
+ foreach(const QUrl& url, docFiles) {
+ QCLuceneDocument document;
+ DocumentHelper helper(url.toString(), engine.fileData(url));
+ if (helper.addFieldsToDocument(&document, namespaceName, attrList))
+ writer->addDocument(document, analyzer);
+
+ locker.relock();
+ if (m_cancel)
+ return false;
+ locker.unlock();
+ }
+
+ return true;
+}
+
+void QHelpSearchIndexWriter::removeDocuments(const QString &indexPath,
+ const QString &namespaceName)
+{
+ if (namespaceName.isEmpty() || QCLuceneIndexReader::isLocked(indexPath))
+ return;
+
+ QCLuceneIndexReader reader = QCLuceneIndexReader::open(indexPath);
+ reader.deleteDocuments(QCLuceneTerm(QLatin1String("namespace"),
+ namespaceName));
+
+ reader.close();
+}
+
+bool QHelpSearchIndexWriter::writeIndexMap(QHelpEngineCore& engine,
+ const QMap<QString, QDateTime>& indexMap)
+{
+ QByteArray bArray;
+
+ QDataStream data(&bArray, QIODevice::ReadWrite);
+ data << indexMap;
+
+ return engine.setCustomValue(QLatin1String("CluceneIndexedNamespaces"),
+ bArray);
+}
+
+QList<QUrl> QHelpSearchIndexWriter::indexableFiles(QHelpEngineCore *helpEngine,
+ const QString &namespaceName, const QStringList &attributes) const
+{
+ QList<QUrl> docFiles = helpEngine->files(namespaceName, attributes,
+ QLatin1String("html"));
+ docFiles += helpEngine->files(namespaceName, attributes, QLatin1String("htm"));
+ docFiles += helpEngine->files(namespaceName, attributes, QLatin1String("txt"));
+
+ return docFiles;
+}
+
+
+ } // namespace clucene
+ } // namespace fulltextsearch
+} // namespace qt
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchindexwriter_clucene_p.h b/tools/assistant/lib/qhelpsearchindexwriter_clucene_p.h
new file mode 100644
index 0000000000..55c852b86f
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexwriter_clucene_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHINDEXWRITERCLUCENE_H
+#define QHELPSEARCHINDEXWRITERCLUCENE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhelpenginecore.h"
+#include "fulltextsearch/qanalyzer_p.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QDateTime>
+#include <QtCore/QStringList>
+#include <QtCore/QWaitCondition>
+
+QT_BEGIN_NAMESPACE
+
+class QCLuceneIndexWriter;
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace clucene {
+
+class QHelpSearchIndexWriter : public QThread
+{
+ Q_OBJECT
+
+public:
+ QHelpSearchIndexWriter();
+ ~QHelpSearchIndexWriter();
+
+ void cancelIndexing();
+ void updateIndex(const QString &collectionFile,
+ const QString &indexFilesFolder, bool reindex);
+ void optimizeIndex();
+
+signals:
+ void indexingStarted();
+ void indexingFinished();
+
+private:
+ void run();
+
+ bool addDocuments(const QList<QUrl> docFiles, const QHelpEngineCore &engine,
+ const QStringList &attributes, const QString &namespaceName,
+ QCLuceneIndexWriter *writer, QCLuceneAnalyzer &analyzer);
+ void removeDocuments(const QString &indexPath, const QString &namespaceName);
+
+ bool writeIndexMap(QHelpEngineCore& engine,
+ const QMap<QString, QDateTime>& indexMap);
+
+ QList<QUrl> indexableFiles(QHelpEngineCore *helpEngine,
+ const QString &namespaceName, const QStringList &attributes) const;
+
+private:
+ QMutex mutex;
+ QWaitCondition waitCondition;
+
+ bool m_cancel;
+ bool m_reindex;
+ QString m_collectionFile;
+ QString m_indexFilesFolder;
+};
+
+ } // namespace clucene
+ } // namespace fulltextsearch
+} // namespace clucene
+
+QT_END_NAMESPACE
+
+#endif // QHELPSEARCHINDEXWRITERCLUCENE_H
diff --git a/tools/assistant/lib/qhelpsearchindexwriter_default.cpp b/tools/assistant/lib/qhelpsearchindexwriter_default.cpp
new file mode 100644
index 0000000000..d55b984bcd
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexwriter_default.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpsearchindexwriter_default_p.h"
+#include "qhelp_global.h"
+#include "qhelpenginecore.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QSet>
+#include <QtCore/QUrl>
+#include <QtCore/QFile>
+#include <QtCore/QRegExp>
+#include <QtCore/QVariant>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace std {
+
+Writer::Writer(const QString &path)
+ : indexPath(path)
+ , indexFile(QString())
+ , documentFile(QString())
+{
+ // nothing todo
+}
+
+Writer::~Writer()
+{
+ reset();
+}
+
+void Writer::reset()
+{
+ for(QHash<QString, Entry*>::ConstIterator it =
+ index.begin(); it != index.end(); ++it) {
+ delete it.value();
+ }
+
+ index.clear();
+ documentList.clear();
+}
+
+bool Writer::writeIndex() const
+{
+ bool status;
+ QFile idxFile(indexFile);
+ if (!(status = idxFile.open(QFile::WriteOnly)))
+ return status;
+
+ QDataStream indexStream(&idxFile);
+ for(QHash<QString, Entry*>::ConstIterator it =
+ index.begin(); it != index.end(); ++it) {
+ indexStream << it.key();
+ indexStream << it.value()->documents.count();
+ indexStream << it.value()->documents;
+ }
+ idxFile.close();
+
+ QFile docFile(documentFile);
+ if (!(status = docFile.open(QFile::WriteOnly)))
+ return status;
+
+ QDataStream docStream(&docFile);
+ foreach(const QStringList list, documentList) {
+ docStream << list.at(0);
+ docStream << list.at(1);
+ }
+ docFile.close();
+
+ return status;
+}
+
+void Writer::removeIndex() const
+{
+ QFile idxFile(indexFile);
+ if (idxFile.exists())
+ idxFile.remove();
+
+ QFile docFile(documentFile);
+ if (docFile.exists())
+ docFile.remove();
+}
+
+void Writer::setIndexFile(const QString &namespaceName, const QString &attributes)
+{
+ QString extention = namespaceName + QLatin1String("@") + attributes;
+ indexFile = indexPath + QLatin1String("/indexdb40.") + extention;
+ documentFile = indexPath + QLatin1String("/indexdoc40.") + extention;
+}
+
+void Writer::insertInIndex(const QString &string, int docNum)
+{
+ if (string == QLatin1String("amp") || string == QLatin1String("nbsp"))
+ return;
+
+ Entry *entry = 0;
+ if (index.count())
+ entry = index[string];
+
+ if (entry) {
+ if (entry->documents.last().docNumber != docNum)
+ entry->documents.append(Document(docNum, 1));
+ else
+ entry->documents.last().frequency++;
+ } else {
+ index.insert(string, new Entry(docNum));
+ }
+}
+
+void Writer::insertInDocumentList(const QString &title, const QString &url)
+{
+ documentList.append(QStringList(title) << url);
+}
+
+
+QHelpSearchIndexWriter::QHelpSearchIndexWriter()
+ : QThread()
+ , m_cancel(false)
+{
+ // nothing todo
+}
+
+QHelpSearchIndexWriter::~QHelpSearchIndexWriter()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ waitCondition.wakeOne();
+ mutex.unlock();
+
+ wait();
+}
+
+void QHelpSearchIndexWriter::cancelIndexing()
+{
+ mutex.lock();
+ this->m_cancel = true;
+ mutex.unlock();
+}
+
+void QHelpSearchIndexWriter::updateIndex(const QString &collectionFile,
+ const QString &indexFilesFolder,
+ bool reindex)
+{
+ QMutexLocker lock(&mutex);
+
+ this->m_cancel = false;
+ this->m_reindex = reindex;
+ this->m_collectionFile = collectionFile;
+ this->m_indexFilesFolder = indexFilesFolder;
+
+ start(QThread::NormalPriority);
+}
+
+void QHelpSearchIndexWriter::run()
+{
+ mutex.lock();
+
+ if (m_cancel) {
+ mutex.unlock();
+ return;
+ }
+
+ const bool reindex(this->m_reindex);
+ const QLatin1String key("DefaultSearchNamespaces");
+ const QString collectionFile(this->m_collectionFile);
+ const QString indexPath = m_indexFilesFolder;
+
+ mutex.unlock();
+
+ QHelpEngineCore engine(collectionFile, 0);
+ if (!engine.setupData())
+ return;
+
+ if (reindex)
+ engine.setCustomValue(key, QLatin1String(""));
+
+ const QStringList registeredDocs = engine.registeredDocumentations();
+ const QStringList indexedNamespaces = engine.customValue(key).toString().
+ split(QLatin1String("|"), QString::SkipEmptyParts);
+
+ emit indexingStarted();
+
+ QStringList namespaces;
+ Writer writer(indexPath);
+ foreach(const QString namespaceName, registeredDocs) {
+ mutex.lock();
+ if (m_cancel) {
+ mutex.unlock();
+ return;
+ }
+ mutex.unlock();
+
+ // if indexed, continue
+ namespaces.append(namespaceName);
+ if (indexedNamespaces.contains(namespaceName))
+ continue;
+
+ const QList<QStringList> attributeSets =
+ engine.filterAttributeSets(namespaceName);
+
+ foreach (QStringList attributes, attributeSets) {
+ // cleanup maybe old or unfinished files
+ writer.setIndexFile(namespaceName, attributes.join(QLatin1String("@")));
+ writer.removeIndex();
+
+ QSet<QString> documentsSet;
+ const QList<QUrl> docFiles = engine.files(namespaceName, attributes);
+ foreach(QUrl url, docFiles) {
+ if (m_cancel)
+ return;
+
+ // get rid of duplicated files
+ if (url.hasFragment())
+ url.setFragment(QString());
+
+ QString s = url.toString();
+ if (s.endsWith(QLatin1String(".html"))
+ || s.endsWith(QLatin1String(".htm"))
+ || s.endsWith(QLatin1String(".txt")))
+ documentsSet.insert(s);
+ }
+
+ int docNum = 0;
+ const QStringList documentsList(documentsSet.toList());
+ foreach(const QString url, documentsList) {
+ if (m_cancel)
+ return;
+
+ QByteArray data(engine.fileData(url));
+ if (data.isEmpty())
+ continue;
+
+ QTextStream s(data);
+ QString en = QHelpGlobal::charsetFromData(data);
+ s.setCodec(QTextCodec::codecForName(en.toLatin1().constData()));
+
+ QString text = s.readAll();
+ if (text.isNull())
+ continue;
+
+ QString title = QHelpGlobal::documentTitle(text);
+
+ int j = 0;
+ int i = 0;
+ bool valid = true;
+ const QChar *buf = text.unicode();
+ QChar str[64];
+ QChar c = buf[0];
+
+ while ( j < text.length() ) {
+ if (m_cancel)
+ return;
+
+ if ( c == QLatin1Char('<') || c == QLatin1Char('&') ) {
+ valid = false;
+ if ( i > 1 )
+ writer.insertInIndex(QString(str,i), docNum);
+ i = 0;
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c == QLatin1Char('>') || c == QLatin1Char(';') ) && !valid ) {
+ valid = true;
+ c = buf[++j];
+ continue;
+ }
+ if ( !valid ) {
+ c = buf[++j];
+ continue;
+ }
+ if ( ( c.isLetterOrNumber() || c == QLatin1Char('_') ) && i < 63 ) {
+ str[i] = c.toLower();
+ ++i;
+ } else {
+ if ( i > 1 )
+ writer.insertInIndex(QString(str,i), docNum);
+ i = 0;
+ }
+ c = buf[++j];
+ }
+ if ( i > 1 )
+ writer.insertInIndex(QString(str,i), docNum);
+
+ docNum++;
+ writer.insertInDocumentList(title, url);
+ }
+
+ if (writer.writeIndex()) {
+ engine.setCustomValue(key, addNamespace(
+ engine.customValue(key).toString(), namespaceName));
+ }
+
+ writer.reset();
+ }
+ }
+
+ QStringListIterator qsli(indexedNamespaces);
+ while (qsli.hasNext()) {
+ const QString namespaceName = qsli.next();
+ if (namespaces.contains(namespaceName))
+ continue;
+
+ const QList<QStringList> attributeSets =
+ engine.filterAttributeSets(namespaceName);
+
+ foreach (QStringList attributes, attributeSets) {
+ writer.setIndexFile(namespaceName, attributes.join(QLatin1String("@")));
+ writer.removeIndex();
+ }
+
+ engine.setCustomValue(key, removeNamespace(
+ engine.customValue(key).toString(), namespaceName));
+ }
+
+ emit indexingFinished();
+}
+
+QString QHelpSearchIndexWriter::addNamespace(const QString namespaces,
+ const QString &namespaceName)
+{
+ QString value = namespaces;
+ if (!value.contains(namespaceName))
+ value.append(namespaceName).append(QLatin1String("|"));
+
+ return value;
+}
+
+QString QHelpSearchIndexWriter::removeNamespace(const QString namespaces,
+ const QString &namespaceName)
+{
+ QString value = namespaces;
+ if (value.contains(namespaceName))
+ value.remove(namespaceName + QLatin1String("|"));
+
+ return value;
+}
+
+ } // namespace std
+ } // namespace fulltextsearch
+} // namespace qt
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchindexwriter_default_p.h b/tools/assistant/lib/qhelpsearchindexwriter_default_p.h
new file mode 100644
index 0000000000..015eb5a2d4
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchindexwriter_default_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHINDEXWRITERDEFAULT_H
+#define QHELPSEARCHINDEXWRITERDEFAULT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the help generator tools. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qhelpsearchindex_default_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QMutex>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QThread>
+#include <QtCore/QStringList>
+#include <QtCore/QWaitCondition>
+
+QT_BEGIN_NAMESPACE
+
+namespace qt {
+ namespace fulltextsearch {
+ namespace std {
+
+class Writer
+{
+public:
+ Writer(const QString &path);
+ ~Writer();
+
+ void reset();
+ bool writeIndex() const;
+ void removeIndex() const;
+ void setIndexFile(const QString &namespaceName, const QString &attributes);
+ void insertInIndex(const QString &string, int docNum);
+ void insertInDocumentList(const QString &title, const QString &url);
+
+private:
+ QString indexPath;
+ QString indexFile;
+ QString documentFile;
+
+ QHash<QString, Entry*> index;
+ QList<QStringList> documentList;
+};
+
+
+class QHelpSearchIndexWriter : public QThread
+{
+ Q_OBJECT
+
+public:
+ QHelpSearchIndexWriter();
+ ~QHelpSearchIndexWriter();
+
+ void cancelIndexing();
+ void updateIndex(const QString &collectionFile,
+ const QString &indexFilesFolder, bool reindex);
+
+signals:
+ void indexingStarted();
+ void indexingFinished();
+
+private:
+ void run();
+ QString addNamespace(const QString namespaces, const QString &namespaceName);
+ QString removeNamespace(const QString namespaces, const QString &namespaceName);
+
+private:
+ QMutex mutex;
+ QWaitCondition waitCondition;
+
+ bool m_cancel;
+ bool m_reindex;
+ QString m_collectionFile;
+ QString m_indexFilesFolder;
+};
+
+ } // namespace std
+ } // namespace fulltextsearch
+} // namespace qt
+
+QT_END_NAMESPACE
+
+#endif // QHELPSEARCHINDEXWRITERDEFAULT_H
diff --git a/tools/assistant/lib/qhelpsearchquerywidget.cpp b/tools/assistant/lib/qhelpsearchquerywidget.cpp
new file mode 100644
index 0000000000..c018ffc64c
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchquerywidget.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpsearchquerywidget.h"
+
+#include <QtCore/QDebug>
+
+#include <QtCore/QObject>
+#include <QtCore/QStringList>
+
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QLineEdit>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QPushButton>
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpSearchQueryWidgetPrivate : public QObject
+{
+ Q_OBJECT
+
+private:
+ QHelpSearchQueryWidgetPrivate()
+ : QObject()
+ {
+ searchButton = 0;
+ advancedSearchWidget = 0;
+ showHideAdvancedSearchButton = 0;
+ defaultQuery = 0;
+ exactQuery = 0;
+ similarQuery = 0;
+ withoutQuery = 0;
+ allQuery = 0;
+ atLeastQuery = 0;
+ }
+
+ ~QHelpSearchQueryWidgetPrivate()
+ {
+ // nothing todo
+ }
+
+ QString escapeString(const QString &text)
+ {
+ QString retValue = text;
+ const QString escape(QLatin1String("\\"));
+ QStringList escapableCharsList;
+ escapableCharsList << QLatin1String("\\") << QLatin1String("+")
+ << QLatin1String("-") << QLatin1String("!") << QLatin1String("(")
+ << QLatin1String(")") << QLatin1String(":") << QLatin1String("^")
+ << QLatin1String("[") << QLatin1String("]") << QLatin1String("{")
+ << QLatin1String("}") << QLatin1String("~");
+
+ // make sure we won't end up with an empty string
+ foreach (const QString escapeChar, escapableCharsList) {
+ if (retValue.contains(escapeChar))
+ retValue.replace(escapeChar, QLatin1String(""));
+ }
+ if (retValue.trimmed().isEmpty())
+ return retValue;
+
+ retValue = text; // now realy escape the string...
+ foreach (const QString escapeChar, escapableCharsList) {
+ if (retValue.contains(escapeChar))
+ retValue.replace(escapeChar, escape + escapeChar);
+ }
+ return retValue;
+ }
+
+ QStringList buildTermList(const QString query)
+ {
+ bool s = false;
+ QString phrase;
+ QStringList wordList;
+ QString searchTerm = query;
+
+ for (int i = 0; i < searchTerm.length(); ++i) {
+ if (searchTerm[i] == QLatin1Char('\"') && !s) {
+ s = true;
+ phrase = searchTerm[i];
+ continue;
+ }
+ if (searchTerm[i] != QLatin1Char('\"') && s)
+ phrase += searchTerm[i];
+ if (searchTerm[i] == QLatin1Char('\"') && s) {
+ s = false;
+ phrase += searchTerm[i];
+ wordList.append(phrase);
+ searchTerm.remove(phrase);
+ }
+ }
+ if (s)
+ searchTerm.replace(phrase, phrase.mid(1));
+
+ const QRegExp exp(QLatin1String("\\s+"));
+ wordList += searchTerm.split(exp, QString::SkipEmptyParts);
+ return wordList;
+ }
+
+private slots:
+ void showHideAdvancedSearch()
+ {
+ bool hidden = advancedSearchWidget->isHidden();
+ if (hidden) {
+ advancedSearchWidget->show();
+ showHideAdvancedSearchButton->setText((QLatin1String("-")));
+ } else {
+ advancedSearchWidget->hide();
+ showHideAdvancedSearchButton->setText((QLatin1String("+")));
+ }
+
+ defaultQuery->setEnabled(!hidden);
+ }
+
+private:
+ friend class QHelpSearchQueryWidget;
+
+ QPushButton *searchButton;
+ QWidget* advancedSearchWidget;
+ QToolButton *showHideAdvancedSearchButton;
+ QLineEdit *defaultQuery;
+ QLineEdit *exactQuery;
+ QLineEdit *similarQuery;
+ QLineEdit *withoutQuery;
+ QLineEdit *allQuery;
+ QLineEdit *atLeastQuery;
+};
+
+#include "qhelpsearchquerywidget.moc"
+
+
+/*!
+ \class QHelpSearchQueryWidget
+ \since 4.4
+ \inmodule QtHelp
+ \brief The QHelpSearchQueryWidget class provides a simple line edit or
+ an advanced widget to enable the user to input a search term in a
+ standardized input mask.
+*/
+
+/*!
+ \fn void QHelpSearchQueryWidget::search()
+
+ This signal is emitted when a the user has the search button invoked.
+ After reciving the signal you can ask the QHelpSearchQueryWidget for the build list
+ of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's search() function.
+*/
+
+/*!
+ Constructs a new search query widget with the given \a parent.
+*/
+QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ d = new QHelpSearchQueryWidgetPrivate();
+
+ QVBoxLayout *vLayout = new QVBoxLayout(this);
+ vLayout->setMargin(0);
+
+ QHBoxLayout* hBoxLayout = new QHBoxLayout();
+ QLabel *label = new QLabel(tr("Search for:"), this);
+ d->defaultQuery = new QLineEdit(this);
+ d->searchButton = new QPushButton(tr("Search"), this);
+ hBoxLayout->addWidget(label);
+ hBoxLayout->addWidget(d->defaultQuery);
+ hBoxLayout->addWidget(d->searchButton);
+
+ vLayout->addLayout(hBoxLayout);
+
+ connect(d->searchButton, SIGNAL(clicked()), this, SIGNAL(search()));
+ connect(d->defaultQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
+
+#if defined(QT_CLUCENE_SUPPORT)
+ hBoxLayout = new QHBoxLayout();
+ d->showHideAdvancedSearchButton = new QToolButton(this);
+ d->showHideAdvancedSearchButton->setText(QLatin1String("+"));
+ d->showHideAdvancedSearchButton->setMinimumSize(25, 20);
+
+ label = new QLabel(tr("Advanced search"), this);
+ QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
+ sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
+ label->setSizePolicy(sizePolicy);
+
+ QFrame* hLine = new QFrame(this);
+ hLine->setFrameStyle(QFrame::HLine);
+ hBoxLayout->addWidget(d->showHideAdvancedSearchButton);
+ hBoxLayout->addWidget(label);
+ hBoxLayout->addWidget(hLine);
+
+ vLayout->addLayout(hBoxLayout);
+
+ // setup advanced search layout
+ d->advancedSearchWidget = new QWidget(this);
+ QGridLayout *gLayout = new QGridLayout(d->advancedSearchWidget);
+ gLayout->setMargin(0);
+
+ label = new QLabel(tr("words <B>similar</B> to:"), this);
+ gLayout->addWidget(label, 0, 0);
+ d->similarQuery = new QLineEdit(this);
+ gLayout->addWidget(d->similarQuery, 0, 1);
+
+ label = new QLabel(tr("<B>without</B> the words:"), this);
+ gLayout->addWidget(label, 1, 0);
+ d->withoutQuery = new QLineEdit(this);
+ gLayout->addWidget(d->withoutQuery, 1, 1);
+
+ label = new QLabel(tr("with <B>exact phrase</B>:"), this);
+ gLayout->addWidget(label, 2, 0);
+ d->exactQuery = new QLineEdit(this);
+ gLayout->addWidget(d->exactQuery, 2, 1);
+
+ label = new QLabel(tr("with <B>all</B> of the words:"), this);
+ gLayout->addWidget(label, 3, 0);
+ d->allQuery = new QLineEdit(this);
+ gLayout->addWidget(d->allQuery, 3, 1);
+
+ label = new QLabel(tr("with <B>at least one</B> of the words:"), this);
+ gLayout->addWidget(label, 4, 0);
+ d->atLeastQuery = new QLineEdit(this);
+ gLayout->addWidget(d->atLeastQuery, 4, 1);
+
+ vLayout->addWidget(d->advancedSearchWidget);
+ d->advancedSearchWidget->hide();
+
+ connect(d->exactQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
+ connect(d->similarQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
+ connect(d->withoutQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
+ connect(d->allQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
+ connect(d->atLeastQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
+ connect(d->showHideAdvancedSearchButton, SIGNAL(clicked()),
+ d, SLOT(showHideAdvancedSearch()));
+#endif
+}
+
+/*!
+ Destroys the search query widget.
+*/
+QHelpSearchQueryWidget::~QHelpSearchQueryWidget()
+{
+ delete d;
+}
+
+/*!
+ Returns a list of querys to use in combination with the search engines
+ search(QList<QHelpSearchQuery> &query) function.
+*/
+QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const
+{
+#if !defined(QT_CLUCENE_SUPPORT)
+ QList<QHelpSearchQuery> queryList;
+ queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
+ QStringList(d->defaultQuery->text())));
+
+ return queryList;
+#else
+ QList<QHelpSearchQuery> queryList;
+ if (d->defaultQuery->isEnabled()) {
+ queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
+ d->buildTermList(d->escapeString(d->defaultQuery->text()))));
+ } else {
+ const QRegExp exp(QLatin1String("\\s+"));
+ QStringList lst = d->similarQuery->text().split(exp, QString::SkipEmptyParts);
+ if (!lst.isEmpty()) {
+ QStringList fuzzy;
+ foreach (const QString term, lst)
+ fuzzy += d->buildTermList(d->escapeString(term));
+ queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, fuzzy));
+ }
+
+ lst = d->withoutQuery->text().split(exp, QString::SkipEmptyParts);
+ if (!lst.isEmpty()) {
+ QStringList without;
+ foreach (const QString term, lst)
+ without.append(d->escapeString(term));
+ queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, without));
+ }
+
+ if (!d->exactQuery->text().isEmpty()) {
+ QString phrase = d->exactQuery->text().remove(QLatin1Char('\"'));
+ phrase = d->escapeString(phrase.simplified());
+ queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, QStringList(phrase)));
+ }
+
+ lst = d->allQuery->text().split(exp, QString::SkipEmptyParts);
+ if (!lst.isEmpty()) {
+ QStringList all;
+ foreach (const QString term, lst)
+ all.append(d->escapeString(term));
+ queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all));
+ }
+
+ lst = d->atLeastQuery->text().split(exp, QString::SkipEmptyParts);
+ if (!lst.isEmpty()) {
+ QStringList atLeast;
+ foreach (const QString term, lst)
+ atLeast += d->buildTermList(d->escapeString(term));
+ queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, atLeast));
+ }
+ }
+ return queryList;
+#endif
+}
+
+/*! \reimp
+*/
+void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent)
+{
+ if (focusEvent->reason() != Qt::MouseFocusReason) {
+ d->defaultQuery->selectAll();
+ d->defaultQuery->setFocus();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchquerywidget.h b/tools/assistant/lib/qhelpsearchquerywidget.h
new file mode 100644
index 0000000000..f4bcf3e7d7
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchquerywidget.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHQUERYWIDGET_H
+#define QHELPSEARCHQUERYWIDGET_H
+
+#include <QtHelp/qhelp_global.h>
+#include <QtHelp/qhelpsearchengine.h>
+
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+class QFocusEvent;
+class QHelpSearchQueryWidgetPrivate;
+
+class QHELP_EXPORT QHelpSearchQueryWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QHelpSearchQueryWidget(QWidget *parent = 0);
+ ~QHelpSearchQueryWidget();
+
+ QList<QHelpSearchQuery> query() const;
+
+Q_SIGNALS:
+ void search();
+
+private:
+ void focusInEvent(QFocusEvent *focusEvent);
+
+private:
+ QHelpSearchQueryWidgetPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QHELPSEARCHQUERYWIDGET_H
diff --git a/tools/assistant/lib/qhelpsearchresultwidget.cpp b/tools/assistant/lib/qhelpsearchresultwidget.cpp
new file mode 100644
index 0000000000..e72cf97ba3
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchresultwidget.cpp
@@ -0,0 +1,439 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhelpsearchresultwidget.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QPointer>
+#include <QtCore/QStringList>
+
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QHeaderView>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QToolButton>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QTextBrowser>
+#include <QtGui/QTreeWidgetItem>
+
+QT_BEGIN_NAMESPACE
+
+class QDefaultResultWidget : public QTreeWidget
+{
+ Q_OBJECT
+
+public:
+ QDefaultResultWidget(QWidget *parent = 0)
+ : QTreeWidget(parent)
+ {
+ header()->hide();
+ connect(this, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
+ this, SLOT(itemActivated(QTreeWidgetItem*, int)));
+ }
+
+ void showResultPage(const QList<QHelpSearchEngine::SearchHit> hits)
+ {
+ foreach (const QHelpSearchEngine::SearchHit hit, hits)
+ new QTreeWidgetItem(this, QStringList(hit.first) << hit.second);
+ }
+
+signals:
+ void requestShowLink(const QUrl &url);
+
+private slots:
+ void itemActivated(QTreeWidgetItem *item, int /* column */)
+ {
+ if (item) {
+ QString data = item->data(1, Qt::DisplayRole).toString();
+ emit requestShowLink(data);
+ }
+ }
+};
+
+
+class QCLuceneResultWidget : public QTextBrowser
+{
+ Q_OBJECT
+
+public:
+ QCLuceneResultWidget(QWidget *parent = 0)
+ : QTextBrowser(parent)
+ {
+ connect(this, SIGNAL(anchorClicked(const QUrl&)),
+ this, SIGNAL(requestShowLink(const QUrl&)));
+ setContextMenuPolicy(Qt::NoContextMenu);
+ }
+
+ void showResultPage(const QList<QHelpSearchEngine::SearchHit> hits, bool isIndexing)
+ {
+ QString htmlFile = QString(QLatin1String("<html><head><title>%1</title></head><body>"))
+ .arg(tr("Search Results"));
+
+ int count = hits.count();
+ if (count != 0) {
+ if (isIndexing)
+ htmlFile += QString(QLatin1String("<div style=\"text-align:left; font-weight:bold; color:red\">"
+ "%1&nbsp;<span style=\"font-weight:normal; color:black\">"
+ "%2</span></div></div><br>")).arg(tr("Note:"))
+ .arg(tr("The search results may not be complete since the "
+ "documentation is still being indexed!"));
+
+ foreach (const QHelpSearchEngine::SearchHit hit, hits) {
+ htmlFile += QString(QLatin1String("<div style=\"text-align:left; font-weight:bold\""
+ "><a href=\"%1\">%2</a><div style=\"color:green; font-weight:normal;"
+ " margin:5px\">%1</div></div><p></p>"))
+ .arg(hit.first).arg(hit.second);
+ }
+ } else {
+ htmlFile += QLatin1String("<div align=\"center\"><br><br><h2>")
+ + tr("Your search did not match any documents.")
+ + QLatin1String("</h2><div>");
+ if (isIndexing)
+ htmlFile += QLatin1String("<div align=\"center\"><h3>")
+ + tr("(The reason for this might be that the documentation "
+ "is still being indexed.)")
+ + QLatin1String("</h3><div>");
+ }
+
+ htmlFile += QLatin1String("</body></html>");
+
+ setHtml(htmlFile);
+ }
+
+signals:
+ void requestShowLink(const QUrl &url);
+
+private slots:
+ void setSource(const QUrl & /* name */) {}
+};
+
+
+class QHelpSearchResultWidgetPrivate : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void setResults(int hitsCount)
+ {
+ if (!searchEngine.isNull()) {
+#if defined(QT_CLUCENE_SUPPORT)
+ showFirstResultPage();
+ updateNextButtonState(((hitsCount > 20) ? true : false));
+#else
+ resultTreeWidget->clear();
+ resultTreeWidget->showResultPage(searchEngine->hits(0, hitsCount));
+#endif
+ }
+ }
+
+ void showNextResultPage()
+ {
+ if (!searchEngine.isNull()
+ && resultLastToShow < searchEngine->hitsCount()) {
+ resultLastToShow += 20;
+ resultFirstToShow += 20;
+
+ resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
+ resultLastToShow), isIndexing);
+ if (resultLastToShow >= searchEngine->hitsCount())
+ updateNextButtonState(false);
+ }
+ updateHitRange();
+ }
+
+ void showLastResultPage()
+ {
+ if (!searchEngine.isNull()) {
+ resultLastToShow = searchEngine->hitsCount();
+ resultFirstToShow = resultLastToShow - (resultLastToShow % 20);
+
+ if (resultFirstToShow == resultLastToShow)
+ resultFirstToShow -= 20;
+
+ resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
+ resultLastToShow), isIndexing);
+ updateNextButtonState(false);
+ }
+ updateHitRange();
+ }
+
+ void showFirstResultPage()
+ {
+ if (!searchEngine.isNull()) {
+ resultLastToShow = 20;
+ resultFirstToShow = 0;
+
+ resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
+ resultLastToShow), isIndexing);
+ updatePrevButtonState(false);
+ }
+ updateHitRange();
+ }
+
+ void showPreviousResultPage()
+ {
+ if (!searchEngine.isNull()) {
+ int count = resultLastToShow % 20;
+ if (count == 0 || resultLastToShow != searchEngine->hitsCount())
+ count = 20;
+
+ resultLastToShow -= count;
+ resultFirstToShow = resultLastToShow -20;
+
+ resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
+ resultLastToShow), isIndexing);
+ if (resultFirstToShow == 0)
+ updatePrevButtonState(false);
+ }
+ updateHitRange();
+ }
+
+ void updatePrevButtonState(bool state = true)
+ {
+ firstResultPage->setEnabled(state);
+ previousResultPage->setEnabled(state);
+ }
+
+ void updateNextButtonState(bool state = true)
+ {
+ nextResultPage->setEnabled(state);
+ lastResultPage->setEnabled(state);
+ }
+
+ void indexingStarted()
+ {
+ isIndexing = true;
+ }
+
+ void indexingFinished()
+ {
+ isIndexing = false;
+ }
+
+private:
+ QHelpSearchResultWidgetPrivate(QHelpSearchEngine *engine)
+ : QObject()
+ , searchEngine(engine)
+ , isIndexing(false)
+ {
+ resultTreeWidget = 0;
+ resultTextBrowser = 0;
+
+ resultLastToShow = 20;
+ resultFirstToShow = 0;
+
+ firstResultPage = 0;
+ previousResultPage = 0;
+ hitsLabel = 0;
+ nextResultPage = 0;
+ lastResultPage = 0;
+
+ connect(searchEngine, SIGNAL(indexingStarted()),
+ this, SLOT(indexingStarted()));
+ connect(searchEngine, SIGNAL(indexingFinished()),
+ this, SLOT(indexingFinished()));
+ }
+
+ ~QHelpSearchResultWidgetPrivate()
+ {
+ delete searchEngine;
+ }
+
+ QToolButton* setupToolButton(const QString &iconPath)
+ {
+ QToolButton *button = new QToolButton();
+ button->setEnabled(false);
+ button->setAutoRaise(true);
+ button->setIcon(QIcon(iconPath));
+ button->setIconSize(QSize(12, 12));
+ button->setMaximumSize(QSize(16, 16));
+
+ return button;
+ }
+
+ void updateHitRange()
+ {
+ int last = 0;
+ int first = 0;
+ int count = 0;
+
+ if (!searchEngine.isNull()) {
+ count = searchEngine->hitsCount();
+ if (count > 0) {
+ first = resultFirstToShow +1;
+ last = resultLastToShow > count ? count : resultLastToShow;
+ }
+ }
+ hitsLabel->setText(tr("%1 - %2 of %3 Hits").arg(first).arg(last).arg(count));
+ }
+
+private:
+ friend class QHelpSearchResultWidget;
+
+ QPointer<QHelpSearchEngine> searchEngine;
+
+ QDefaultResultWidget *resultTreeWidget;
+ QCLuceneResultWidget *resultTextBrowser;
+
+ int resultLastToShow;
+ int resultFirstToShow;
+ bool isIndexing;
+
+ QToolButton *firstResultPage;
+ QToolButton *previousResultPage;
+ QLabel *hitsLabel;
+ QToolButton *nextResultPage;
+ QToolButton *lastResultPage;
+};
+
+#include "qhelpsearchresultwidget.moc"
+
+
+/*!
+ \class QHelpSearchResultWidget
+ \since 4.4
+ \inmodule QtHelp
+ \brief The QHelpSearchResultWidget class provides either a tree
+ widget or a text browser depending on the used search engine to display
+ the hits found by the search.
+*/
+
+/*!
+ \fn void QHelpSearchResultWidget::requestShowLink(const QUrl &link)
+
+ This signal is emitted when a item is activated and its associated
+ \a link should be shown.
+*/
+
+QHelpSearchResultWidget::QHelpSearchResultWidget(QHelpSearchEngine *engine)
+ : QWidget(0)
+ , d(new QHelpSearchResultWidgetPrivate(engine))
+{
+ QVBoxLayout *vLayout = new QVBoxLayout(this);
+ vLayout->setMargin(0);
+ vLayout->setSpacing(0);
+
+#if defined(QT_CLUCENE_SUPPORT)
+ QHBoxLayout *hBoxLayout = new QHBoxLayout();
+#ifndef Q_OS_MAC
+ hBoxLayout->setMargin(0);
+ hBoxLayout->setSpacing(0);
+#endif
+ hBoxLayout->addWidget(d->firstResultPage = d->setupToolButton(
+ QString::fromUtf8(":/trolltech/assistant/images/3leftarrow.png")));
+
+ hBoxLayout->addWidget(d->previousResultPage = d->setupToolButton(
+ QString::fromUtf8(":/trolltech/assistant/images/1leftarrow.png")));
+
+ d->hitsLabel = new QLabel(tr("0 - 0 of 0 Hits"), this);
+ d->hitsLabel->setEnabled(false);
+ hBoxLayout->addWidget(d->hitsLabel);
+ d->hitsLabel->setAlignment(Qt::AlignCenter);
+ d->hitsLabel->setMinimumSize(QSize(150, d->hitsLabel->height()));
+
+ hBoxLayout->addWidget(d->nextResultPage = d->setupToolButton(
+ QString::fromUtf8(":/trolltech/assistant/images/1rightarrow.png")));
+
+ hBoxLayout->addWidget(d->lastResultPage = d->setupToolButton(
+ QString::fromUtf8(":/trolltech/assistant/images/3rightarrow.png")));
+
+ QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ hBoxLayout->addItem(spacer);
+
+ vLayout->addLayout(hBoxLayout);
+
+ d->resultTextBrowser = new QCLuceneResultWidget(this);
+ vLayout->addWidget(d->resultTextBrowser);
+
+ connect(d->resultTextBrowser, SIGNAL(requestShowLink(const QUrl&)), this,
+ SIGNAL(requestShowLink(const QUrl&)));
+
+ connect(d->nextResultPage, SIGNAL(clicked()), d, SLOT(showNextResultPage()));
+ connect(d->lastResultPage, SIGNAL(clicked()), d, SLOT(showLastResultPage()));
+ connect(d->firstResultPage, SIGNAL(clicked()), d, SLOT(showFirstResultPage()));
+ connect(d->previousResultPage, SIGNAL(clicked()), d, SLOT(showPreviousResultPage()));
+
+ connect(d->firstResultPage, SIGNAL(clicked()), d, SLOT(updateNextButtonState()));
+ connect(d->previousResultPage, SIGNAL(clicked()), d, SLOT(updateNextButtonState()));
+ connect(d->nextResultPage, SIGNAL(clicked()), d, SLOT(updatePrevButtonState()));
+ connect(d->lastResultPage, SIGNAL(clicked()), d, SLOT(updatePrevButtonState()));
+
+#else
+ d->resultTreeWidget = new QDefaultResultWidget(this);
+ vLayout->addWidget(d->resultTreeWidget);
+ connect(d->resultTreeWidget, SIGNAL(requestShowLink(const QUrl&)), this,
+ SIGNAL(requestShowLink(const QUrl&)));
+#endif
+
+ connect(engine, SIGNAL(searchingFinished(int)), d, SLOT(setResults(int)));
+}
+
+/*!
+ Destroys the search result widget.
+*/
+QHelpSearchResultWidget::~QHelpSearchResultWidget()
+{
+ delete d;
+}
+
+/*!
+ Returns a reference of the URL that the item at \a point owns, or an
+ empty URL if no item exists at that point.
+*/
+QUrl QHelpSearchResultWidget::linkAt(const QPoint &point)
+{
+ QUrl url;
+#if defined(QT_CLUCENE_SUPPORT)
+ if (d->resultTextBrowser)
+ url = d->resultTextBrowser->anchorAt(point);
+#else
+ if (d->resultTreeWidget) {
+ QTreeWidgetItem *item = d->resultTreeWidget->itemAt(point);
+ if (item)
+ url = item->data(1, Qt::DisplayRole).toString();
+ }
+#endif
+ return url;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/lib/qhelpsearchresultwidget.h b/tools/assistant/lib/qhelpsearchresultwidget.h
new file mode 100644
index 0000000000..26bc1d97a5
--- /dev/null
+++ b/tools/assistant/lib/qhelpsearchresultwidget.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHELPSEARCHRESULTWIDGET_H
+#define QHELPSEARCHRESULTWIDGET_H
+
+#include <QtHelp/qhelpsearchengine.h>
+#include <QtHelp/qhelp_global.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QPoint>
+#include <QtCore/QObject>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Help)
+
+class QHelpSearchResultWidgetPrivate;
+
+class QHELP_EXPORT QHelpSearchResultWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ~QHelpSearchResultWidget();
+ QUrl linkAt(const QPoint &point);
+
+Q_SIGNALS:
+ void requestShowLink(const QUrl &url);
+
+private:
+ friend class QHelpSearchEngine;
+
+ QHelpSearchResultWidgetPrivate *d;
+ QHelpSearchResultWidget(QHelpSearchEngine *engine);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QHELPSEARCHRESULTWIDGET_H
diff --git a/tools/assistant/tools/assistant/Info_mac.plist b/tools/assistant/tools/assistant/Info_mac.plist
new file mode 100644
index 0000000000..76369a1c51
--- /dev/null
+++ b/tools/assistant/tools/assistant/Info_mac.plist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.trolltech.assistant</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+</dict>
+</plist>
diff --git a/tools/assistant/tools/assistant/aboutdialog.cpp b/tools/assistant/tools/assistant/aboutdialog.cpp
new file mode 100644
index 0000000000..629f249bf2
--- /dev/null
+++ b/tools/assistant/tools/assistant/aboutdialog.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QBuffer>
+
+#include <QtGui/QLabel>
+#include <QtGui/QPushButton>
+#include <QtGui/QLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QMessageBox>
+#include <QtGui/QDesktopServices>
+
+#include "aboutdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+AboutLabel::AboutLabel(QWidget *parent)
+ : QTextBrowser(parent)
+{
+ setFrameStyle(QFrame::NoFrame);
+ QPalette p;
+ p.setColor(QPalette::Base, p.color(QPalette::Background));
+ setPalette(p);
+}
+
+void AboutLabel::setText(const QString &text, const QByteArray &resources)
+{
+ QDataStream in(resources);
+ in >> m_resourceMap;
+
+ QTextBrowser::setText(text);
+}
+
+QSize AboutLabel::minimumSizeHint() const
+{
+ QTextDocument *doc = document();
+ doc->adjustSize();
+ return QSize(int(doc->size().width()), int(doc->size().height()));
+}
+
+QVariant AboutLabel::loadResource(int type, const QUrl &name)
+{
+ if (type == 2 || type == 3) {
+ if (m_resourceMap.contains(name.toString())) {
+ return m_resourceMap.value(name.toString());
+ }
+ }
+ return QVariant();
+}
+
+void AboutLabel::setSource(const QUrl &url)
+{
+ if (url.isValid()
+ && (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("ftp")
+ || url.scheme() == QLatin1String("mailto") || url.path().endsWith(QLatin1String("pdf")))) {
+ if (!QDesktopServices::openUrl(url)) {
+ QMessageBox::warning(this, tr("Warning"),
+ tr("Unable to launch external application.\n"),
+ tr("OK"));
+ }
+ }
+}
+
+AboutDialog::AboutDialog(QWidget *parent)
+ : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint|Qt::WindowTitleHint|Qt::WindowSystemMenuHint)
+{
+ m_pixmapLabel = 0;
+ m_aboutLabel = new AboutLabel();
+
+ m_closeButton = new QPushButton();
+ m_closeButton->setText(tr("&Close"));
+ connect(m_closeButton, SIGNAL(clicked()),
+ this, SLOT(close()));
+
+ m_layout = new QGridLayout(this);
+ m_layout->addWidget(m_aboutLabel, 1, 0, 1, -1);
+ m_layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum, QSizePolicy::Fixed), 2, 1, 1, 1);
+ m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding), 3, 0, 1, 1);
+ m_layout->addWidget(m_closeButton, 3, 1, 1, 1);
+ m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding), 3, 2, 1, 1);
+}
+
+void AboutDialog::setText(const QString &text, const QByteArray &resources)
+{
+ m_aboutLabel->setText(text, resources);
+ updateSize();
+}
+
+void AboutDialog::setPixmap(const QPixmap &pixmap)
+{
+ if (!m_pixmapLabel) {
+ m_pixmapLabel = new QLabel();
+ m_layout->addWidget(m_pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+ }
+ m_pixmapLabel->setPixmap(pixmap);
+ updateSize();
+}
+
+QString AboutDialog::documentTitle() const
+{
+ return m_aboutLabel->documentTitle();
+}
+
+void AboutDialog::updateSize()
+{
+ QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
+ int limit = qMin(screenSize.width()/2, 500);
+
+#ifdef Q_WS_MAC
+ limit = qMin(screenSize.width()/2, 420);
+#endif
+
+ layout()->activate();
+ int width = layout()->totalMinimumSize().width();
+
+ if (width > limit)
+ width = limit;
+
+ QFontMetrics fm(qApp->font("QWorkspaceTitleBar"));
+ int windowTitleWidth = qMin(fm.width(windowTitle()) + 50, limit);
+ if (windowTitleWidth > width)
+ width = windowTitleWidth;
+
+ layout()->activate();
+ int height = (layout()->hasHeightForWidth())
+ ? layout()->totalHeightForWidth(width)
+ : layout()->totalMinimumSize().height();
+ setFixedSize(width, height);
+ QCoreApplication::removePostedEvents(this, QEvent::LayoutRequest);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/aboutdialog.h b/tools/assistant/tools/assistant/aboutdialog.h
new file mode 100644
index 0000000000..d62a220dce
--- /dev/null
+++ b/tools/assistant/tools/assistant/aboutdialog.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABOUTDIALOG_H
+#define ABOUTDIALOG_H
+
+#include <QtGui/QTextBrowser>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QLabel;
+class QPushButton;
+class QGridLayout;
+
+class AboutLabel : public QTextBrowser
+{
+ Q_OBJECT
+
+public:
+ AboutLabel(QWidget *parent = 0);
+ void setText(const QString &text, const QByteArray &resources);
+ QSize minimumSizeHint() const;
+
+private:
+ QVariant loadResource(int type, const QUrl &name);
+ void setSource(const QUrl &url);
+
+ QMap<QString, QByteArray> m_resourceMap;
+};
+
+class AboutDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ AboutDialog(QWidget *parent = 0);
+ void setText(const QString &text, const QByteArray &resources);
+ void setPixmap(const QPixmap &pixmap);
+ QString documentTitle() const;
+
+private:
+ void updateSize();
+
+ QLabel *m_pixmapLabel;
+ AboutLabel *m_aboutLabel;
+ QPushButton *m_closeButton;
+ QGridLayout *m_layout;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/assistant/assistant.icns b/tools/assistant/tools/assistant/assistant.icns
new file mode 100644
index 0000000000..6291dd3975
--- /dev/null
+++ b/tools/assistant/tools/assistant/assistant.icns
Binary files differ
diff --git a/tools/assistant/tools/assistant/assistant.ico b/tools/assistant/tools/assistant/assistant.ico
new file mode 100644
index 0000000000..9e1b83f1b6
--- /dev/null
+++ b/tools/assistant/tools/assistant/assistant.ico
Binary files differ
diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro
new file mode 100644
index 0000000000..1cbd1d32db
--- /dev/null
+++ b/tools/assistant/tools/assistant/assistant.pro
@@ -0,0 +1,89 @@
+include($$QT_SOURCE_TREE/tools/shared/fontpanel/fontpanel.pri)
+
+TEMPLATE = app
+LANGUAGE = C++
+TARGET = assistant
+
+DEFINES += QT_CLUCENE_SUPPORT
+
+contains(QT_CONFIG, webkit) {
+ QT += webkit
+}
+
+CONFIG += qt warn_on help
+
+QT += network
+
+PROJECTNAME = Assistant
+DESTDIR = ../../../../bin
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+### Work around a qmake issue when statically linking to
+### not-yet-installed plugins
+LIBS += -L$$QT_BUILD_TREE/plugins/sqldrivers
+
+HEADERS += helpviewer.h \
+ mainwindow.h \
+ indexwindow.h \
+ topicchooser.h \
+ contentwindow.h \
+ searchwidget.h \
+ preferencesdialog.h \
+ filternamedialog.h \
+ centralwidget.h \
+ installdialog.h \
+ bookmarkmanager.h \
+ remotecontrol.h \
+ cmdlineparser.h \
+ aboutdialog.h \
+ qtdocinstaller.h
+
+win32 {
+ HEADERS += remotecontrol_win.h
+}
+
+SOURCES += helpviewer.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ indexwindow.cpp \
+ topicchooser.cpp \
+ contentwindow.cpp \
+ searchwidget.cpp \
+ preferencesdialog.cpp \
+ filternamedialog.cpp \
+ centralwidget.cpp \
+ installdialog.cpp \
+ bookmarkmanager.cpp \
+ remotecontrol.cpp \
+ cmdlineparser.cpp \
+ aboutdialog.cpp \
+ qtdocinstaller.cpp
+
+FORMS += topicchooser.ui \
+ preferencesdialog.ui \
+ filternamedialog.ui \
+ installdialog.ui \
+ bookmarkdialog.ui
+
+RESOURCES += assistant.qrc assistant_images.qrc
+
+win32 {
+ !wince*:LIBS += -lshell32
+ RC_FILE = assistant.rc
+}
+
+mac {
+ ICON = assistant.icns
+ TARGET = Assistant
+ QMAKE_INFO_PLIST = Info_mac.plist
+}
+
+contains(CONFIG, static): {
+ SQLPLUGINS = $$unique(sql-plugins)
+ contains(SQLPLUGINS, sqlite): {
+ QTPLUGIN += qsqlite
+ DEFINES += USE_STATIC_SQLITE_PLUGIN
+ }
+}
diff --git a/tools/assistant/tools/assistant/assistant.qch b/tools/assistant/tools/assistant/assistant.qch
new file mode 100644
index 0000000000..550cd898fb
--- /dev/null
+++ b/tools/assistant/tools/assistant/assistant.qch
Binary files differ
diff --git a/tools/assistant/tools/assistant/assistant.qrc b/tools/assistant/tools/assistant/assistant.qrc
new file mode 100644
index 0000000000..dddf1be759
--- /dev/null
+++ b/tools/assistant/tools/assistant/assistant.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/assistant" >
+ <file>assistant.qch</file>
+ </qresource>
+</RCC>
diff --git a/tools/assistant/tools/assistant/assistant.rc b/tools/assistant/tools/assistant/assistant.rc
new file mode 100644
index 0000000000..b4786ceaaf
--- /dev/null
+++ b/tools/assistant/tools/assistant/assistant.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "assistant.ico"
diff --git a/tools/assistant/tools/assistant/assistant_images.qrc b/tools/assistant/tools/assistant/assistant_images.qrc
new file mode 100644
index 0000000000..58e03b54dd
--- /dev/null
+++ b/tools/assistant/tools/assistant/assistant_images.qrc
@@ -0,0 +1,36 @@
+<RCC>
+ <qresource prefix="/trolltech/assistant" >
+ <file>images/trolltech-logo.png</file>
+ <file>images/assistant-128.png</file>
+ <file>images/assistant.png</file>
+ <file>images/wrap.png</file>
+#mac
+ <file>images/mac/addtab.png</file>
+ <file>images/mac/book.png</file>
+ <file>images/mac/closetab.png</file>
+ <file>images/mac/editcopy.png</file>
+ <file>images/mac/find.png</file>
+ <file>images/mac/home.png</file>
+ <file>images/mac/next.png</file>
+ <file>images/mac/previous.png</file>
+ <file>images/mac/print.png</file>
+ <file>images/mac/synctoc.png</file>
+ <file>images/mac/zoomin.png</file>
+ <file>images/mac/zoomout.png</file>
+ <file>images/mac/resetzoom.png</file>
+#win
+ <file>images/win/addtab.png</file>
+ <file>images/win/book.png</file>
+ <file>images/win/closetab.png</file>
+ <file>images/win/editcopy.png</file>
+ <file>images/win/find.png</file>
+ <file>images/win/home.png</file>
+ <file>images/win/next.png</file>
+ <file>images/win/previous.png</file>
+ <file>images/win/print.png</file>
+ <file>images/win/synctoc.png</file>
+ <file>images/win/zoomin.png</file>
+ <file>images/win/zoomout.png</file>
+ <file>images/win/resetzoom.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/assistant/tools/assistant/bookmarkdialog.ui b/tools/assistant/tools/assistant/bookmarkdialog.ui
new file mode 100644
index 0000000000..7a878f9656
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkdialog.ui
@@ -0,0 +1,146 @@
+<ui version="4.0" >
+ <class>BookmarkDialog</class>
+ <widget class="QDialog" name="BookmarkDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>450</width>
+ <height>135</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle" >
+ <string>Add Bookmark</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3" >
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2" >
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Bookmark:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Add in Folder:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <widget class="QLineEdit" name="bookmarkEdit" />
+ </item>
+ <item>
+ <widget class="QComboBox" name="bookmarkFolders" />
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3" >
+ <item>
+ <widget class="QToolButton" name="toolButton" >
+ <property name="minimumSize" >
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTreeView" name="treeView" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Ignored" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4" >
+ <item>
+ <widget class="QPushButton" name="newFolderButton" >
+ <property name="text" >
+ <string>New Folder</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>BookmarkDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>BookmarkDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp
new file mode 100644
index 0000000000..6f5732ff4b
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp
@@ -0,0 +1,874 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "bookmarkmanager.h"
+#include "centralwidget.h"
+
+#include <QtGui/QMenu>
+#include <QtGui/QIcon>
+#include <QtGui/QStyle>
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtCore/QEvent>
+#include <QtGui/QComboBox>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QLineEdit>
+#include <QtGui/QMessageBox>
+#include <QtGui/QHeaderView>
+#include <QtGui/QToolButton>
+#include <QtGui/QPushButton>
+#include <QtGui/QApplication>
+#include <QtHelp/QHelpEngineCore>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QSortFilterProxyModel>
+
+QT_BEGIN_NAMESPACE
+
+BookmarkDialog::BookmarkDialog(BookmarkManager *manager, const QString &title,
+ const QString &url, QWidget *parent)
+ : QDialog(parent)
+ , m_url(url)
+ , m_title(title)
+ , bookmarkManager(manager)
+{
+ installEventFilter(this);
+
+ ui.setupUi(this);
+ ui.bookmarkEdit->setText(title);
+ ui.newFolderButton->setVisible(false);
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
+ ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
+
+ proxyModel = new QSortFilterProxyModel(this);
+ proxyModel->setFilterKeyColumn(0);
+ proxyModel->setDynamicSortFilter(true);
+ proxyModel->setFilterRole(Qt::UserRole + 10);
+ proxyModel->setSourceModel(bookmarkManager->treeBookmarkModel());
+ proxyModel->setFilterRegExp(QRegExp(QLatin1String("Folder"),
+ Qt::CaseSensitive, QRegExp::FixedString));
+ ui.treeView->setModel(proxyModel);
+
+ ui.treeView->expandAll();
+ ui.treeView->setVisible(false);
+ ui.treeView->header()->setVisible(false);
+ ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(addAccepted()));
+ connect(ui.newFolderButton, SIGNAL(clicked()), this, SLOT(addNewFolder()));
+ connect(ui.toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked()));
+ connect(ui.bookmarkEdit, SIGNAL(textChanged(const QString&)), this,
+ SLOT(textChanged(const QString&)));
+
+ connect(bookmarkManager->treeBookmarkModel(), SIGNAL(itemChanged(QStandardItem*)),
+ this, SLOT(itemChanged(QStandardItem*)));
+
+ connect(ui.bookmarkFolders, SIGNAL(currentIndexChanged(const QString&)), this,
+ SLOT(selectBookmarkFolder(const QString&)));
+
+ connect(ui.treeView, SIGNAL(customContextMenuRequested(const QPoint&)), this,
+ SLOT(customContextMenuRequested(const QPoint&)));
+
+ connect(ui.treeView->selectionModel(),
+ SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
+ this, SLOT(currentChanged(const QModelIndex&, const QModelIndex&)));
+}
+
+BookmarkDialog::~BookmarkDialog()
+{
+}
+
+void BookmarkDialog::addAccepted()
+{
+ const QItemSelection selection = ui.treeView->selectionModel()->selection();
+ const QModelIndexList list = selection.indexes();
+
+ QModelIndex index;
+ if (!list.isEmpty())
+ index = proxyModel->mapToSource(list.at(0));
+
+ bookmarkManager->addNewBookmark(index, ui.bookmarkEdit->text(), m_url);
+ accept();
+}
+
+void BookmarkDialog::addNewFolder()
+{
+ const QItemSelection selection = ui.treeView->selectionModel()->selection();
+ const QModelIndexList list = selection.indexes();
+
+ QModelIndex index;
+ if (!list.isEmpty())
+ index = list.at(0);
+
+ QModelIndex newFolder =
+ bookmarkManager->addNewFolder(proxyModel->mapToSource(index));
+ if (newFolder.isValid()) {
+ ui.treeView->expand(index);
+ const QModelIndex &index = proxyModel->mapFromSource(newFolder);
+ ui.treeView->selectionModel()->setCurrentIndex(index,
+ QItemSelectionModel::ClearAndSelect);
+
+ ui.bookmarkFolders->clear();
+ ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
+
+ const QString name = index.data().toString();
+ ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
+ }
+ ui.treeView->setFocus();
+}
+
+void BookmarkDialog::toolButtonClicked()
+{
+ bool visible = !ui.treeView->isVisible();
+ ui.treeView->setVisible(visible);
+ ui.newFolderButton->setVisible(visible);
+
+ if (visible) {
+ resize(QSize(width(), 400));
+ ui.toolButton->setText(QLatin1String("-"));
+ } else {
+ resize(width(), minimumHeight());
+ ui.toolButton->setText(QLatin1String("+"));
+ }
+}
+
+void BookmarkDialog::itemChanged(QStandardItem *item)
+{
+ if (renameItem != item) {
+ renameItem = item;
+ oldText = item->text();
+ return;
+ }
+
+ if (item->text() != oldText) {
+ ui.bookmarkFolders->clear();
+ ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
+
+ QString name = tr("Bookmarks");
+ const QModelIndex& index = ui.treeView->currentIndex();
+ if (index.isValid())
+ name = index.data().toString();
+ ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
+ }
+}
+
+void BookmarkDialog::textChanged(const QString& string)
+{
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!string.isEmpty());
+}
+
+void BookmarkDialog::selectBookmarkFolder(const QString &folderName)
+{
+ if (folderName.isEmpty())
+ return;
+
+ if (folderName == tr("Bookmarks")) {
+ ui.treeView->clearSelection();
+ return;
+ }
+
+ QStandardItemModel *model = bookmarkManager->treeBookmarkModel();
+ QList<QStandardItem*> list = model->findItems(folderName,
+ Qt::MatchCaseSensitive | Qt::MatchRecursive, 0);
+ if (!list.isEmpty()) {
+ QModelIndex index = model->indexFromItem(list.at(0));
+ ui.treeView->selectionModel()->setCurrentIndex(
+ proxyModel->mapFromSource(index), QItemSelectionModel::ClearAndSelect);
+ }
+}
+
+void BookmarkDialog::customContextMenuRequested(const QPoint &point)
+{
+ QModelIndex index = ui.treeView->indexAt(point);
+ if (!index.isValid())
+ return;
+
+ QMenu menu(QLatin1String(""), this);
+
+ QAction *removeItem = menu.addAction(tr("Delete Folder"));
+ QAction *renameItem = menu.addAction(tr("Rename Folder"));
+
+ QAction *picked_action = menu.exec(ui.treeView->mapToGlobal(point));
+ if (!picked_action)
+ return;
+
+ if (picked_action == removeItem) {
+ bookmarkManager->removeBookmarkItem(ui.treeView,
+ proxyModel->mapToSource(index));
+ ui.bookmarkFolders->clear();
+ ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
+
+ QString name = tr("Bookmarks");
+ index = ui.treeView->currentIndex();
+ if (index.isValid())
+ name = index.data().toString();
+ ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
+ }
+ else if (picked_action == renameItem) {
+ QStandardItem *item = bookmarkManager->treeBookmarkModel()->
+ itemFromIndex(proxyModel->mapToSource(index));
+ if (item) {
+ item->setEditable(true);
+ ui.treeView->edit(index);
+ item->setEditable(false);
+ }
+ }
+}
+
+void BookmarkDialog::currentChanged(const QModelIndex& current,
+ const QModelIndex& previous)
+{
+ Q_UNUSED(previous)
+
+ if (!current.isValid()) {
+ ui.bookmarkFolders->setCurrentIndex(
+ ui.bookmarkFolders->findText(tr("Bookmarks")));
+ return;
+ }
+
+ ui.bookmarkFolders->setCurrentIndex(
+ ui.bookmarkFolders->findText(current.data().toString()));
+}
+
+bool BookmarkDialog::eventFilter(QObject *object, QEvent *e)
+{
+ if (object == this && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+
+ QModelIndex index = ui.treeView->currentIndex();
+ switch (ke->key()) {
+ case Qt::Key_F2: {
+ const QModelIndex& source = proxyModel->mapToSource(index);
+ QStandardItem *item =
+ bookmarkManager->treeBookmarkModel()->itemFromIndex(source);
+ if (item) {
+ item->setEditable(true);
+ ui.treeView->edit(index);
+ item->setEditable(false);
+ }
+ } break;
+
+ case Qt::Key_Delete: {
+ bookmarkManager->removeBookmarkItem(ui.treeView,
+ proxyModel->mapToSource(index));
+ ui.bookmarkFolders->clear();
+ ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
+
+ QString name = tr("Bookmarks");
+ index = ui.treeView->currentIndex();
+ if (index.isValid())
+ name = index.data().toString();
+ ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
+ } break;
+
+ default:
+ break;
+ }
+ }
+ return QObject::eventFilter(object, e);
+}
+
+
+
+
+BookmarkWidget::BookmarkWidget(BookmarkManager *manager, QWidget *parent,
+ bool showButtons)
+ : QWidget(parent)
+ , addButton(0)
+ , removeButton(0)
+ , bookmarkManager(manager)
+{
+ setup(showButtons);
+ installEventFilter(this);
+}
+
+BookmarkWidget::~BookmarkWidget()
+{
+}
+
+void BookmarkWidget::removeClicked()
+{
+ const QModelIndex& index = treeView->currentIndex();
+ if (searchField->text().isEmpty()) {
+ bookmarkManager->removeBookmarkItem(treeView,
+ filterBookmarkModel->mapToSource(index));
+ }
+}
+
+void BookmarkWidget::filterChanged()
+{
+ bool searchBookmarks = searchField->text().isEmpty();
+ if (!searchBookmarks) {
+ regExp.setPattern(searchField->text());
+ filterBookmarkModel->setSourceModel(bookmarkManager->listBookmarkModel());
+ } else {
+ regExp.setPattern(QLatin1String(""));
+ filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel());
+ }
+
+ if (addButton)
+ addButton->setEnabled(searchBookmarks);
+
+ if (removeButton)
+ removeButton->setEnabled(searchBookmarks);
+
+ filterBookmarkModel->setFilterRegExp(regExp);
+
+ QModelIndex index = treeView->indexAt(QPoint(1, 1));
+ if (index.isValid())
+ treeView->setCurrentIndex(index);
+
+ if (searchBookmarks)
+ expandItems();
+}
+
+void BookmarkWidget::expand(const QModelIndex& index)
+{
+ const QModelIndex& source = filterBookmarkModel->mapToSource(index);
+ QStandardItem *item = bookmarkManager->treeBookmarkModel()->itemFromIndex(source);
+ if (item)
+ item->setData(treeView->isExpanded(index), Qt::UserRole + 11);
+}
+
+void BookmarkWidget::activated(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return;
+
+ QString data = index.data(Qt::UserRole + 10).toString();
+ if (data != QLatin1String("Folder"))
+ emit requestShowLink(data);
+}
+
+void BookmarkWidget::customContextMenuRequested(const QPoint &point)
+{
+ QModelIndex index = treeView->indexAt(point);
+ if (!index.isValid())
+ return;
+
+ QAction *showItem = 0;
+ QAction *removeItem = 0;
+ QAction *renameItem = 0;
+ QAction *showItemNewTab = 0;
+
+ QMenu menu(QLatin1String(""), this);
+ QString data = index.data(Qt::UserRole + 10).toString();
+ if (data == QLatin1String("Folder")) {
+ removeItem = menu.addAction(tr("Delete Folder"));
+ renameItem = menu.addAction(tr("Rename Folder"));
+ } else {
+ showItem = menu.addAction(tr("Show Bookmark"));
+ showItemNewTab = menu.addAction(tr("Show Bookmark in New Tab"));
+ if (searchField->text().isEmpty()) {
+ menu.addSeparator();
+ removeItem = menu.addAction(tr("Delete Bookmark"));
+ renameItem = menu.addAction(tr("Rename Bookmark"));
+ }
+ }
+
+ QAction *picked_action = menu.exec(treeView->mapToGlobal(point));
+ if (!picked_action)
+ return;
+
+ if (picked_action == showItem) {
+ emit requestShowLink(data);
+ }
+ else if (picked_action == showItemNewTab) {
+ CentralWidget::instance()->setSourceInNewTab(data);
+ }
+ else if (picked_action == removeItem) {
+ bookmarkManager->removeBookmarkItem(treeView,
+ filterBookmarkModel->mapToSource(index));
+ }
+ else if (picked_action == renameItem) {
+ const QModelIndex& source = filterBookmarkModel->mapToSource(index);
+ QStandardItem *item =
+ bookmarkManager->treeBookmarkModel()->itemFromIndex(source);
+ if (item) {
+ item->setEditable(true);
+ treeView->edit(index);
+ item->setEditable(false);
+ }
+ }
+}
+
+void BookmarkWidget::setup(bool showButtons)
+{
+ regExp.setPatternSyntax(QRegExp::FixedString);
+ regExp.setCaseSensitivity(Qt::CaseInsensitive);
+
+ QLayout *vlayout = new QVBoxLayout(this);
+ vlayout->setMargin(4);
+
+ QLabel *label = new QLabel(tr("Filter:"), this);
+ vlayout->addWidget(label);
+
+ searchField = new QLineEdit(this);
+ vlayout->addWidget(searchField);
+ connect(searchField, SIGNAL(textChanged(const QString &)), this,
+ SLOT(filterChanged()));
+
+ treeView = new TreeView(this);
+ vlayout->addWidget(treeView);
+
+ QString system = QLatin1String("win");
+#ifdef Q_OS_MAC
+ system = QLatin1String("mac");
+#endif
+
+ if (showButtons) {
+ QLayout *hlayout = new QHBoxLayout();
+ vlayout->addItem(hlayout);
+
+ hlayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding));
+
+ addButton = new QToolButton(this);
+ addButton->setText(tr("Add"));
+ addButton->setIcon(QIcon(QString::fromUtf8(
+ ":/trolltech/assistant/images/%1/addtab.png").arg(system)));
+ addButton->setAutoRaise(true);
+ addButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ hlayout->addWidget(addButton);
+ connect(addButton, SIGNAL(clicked()), this, SIGNAL(addBookmark()));
+
+ removeButton = new QToolButton(this);
+ removeButton->setText(tr("Remove"));
+ removeButton->setIcon(QIcon(QString::fromUtf8(
+ ":/trolltech/assistant/images/%1/closetab.png").arg(system)));
+ removeButton->setAutoRaise(true);
+ removeButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ hlayout->addWidget(removeButton);
+ connect(removeButton, SIGNAL(clicked()), this, SLOT(removeClicked()));
+ }
+
+ filterBookmarkModel = new QSortFilterProxyModel(this);
+ treeView->setModel(filterBookmarkModel);
+
+ treeView->setDragEnabled(true);
+ treeView->setAcceptDrops(true);
+ treeView->setAutoExpandDelay(1000);
+ treeView->setDropIndicatorShown(true);
+ treeView->header()->setVisible(false);
+ treeView->viewport()->installEventFilter(this);
+ treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(treeView, SIGNAL(expanded(const QModelIndex&)), this,
+ SLOT(expand(const QModelIndex&)));
+
+ connect(treeView, SIGNAL(collapsed(const QModelIndex&)), this,
+ SLOT(expand(const QModelIndex&)));
+
+ connect(treeView, SIGNAL(activated(const QModelIndex&)), this,
+ SLOT(activated(const QModelIndex&)));
+
+ connect(treeView, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(customContextMenuRequested(const QPoint&)));
+
+ filterBookmarkModel->setFilterKeyColumn(0);
+ filterBookmarkModel->setDynamicSortFilter(true);
+ filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel());
+
+ expandItems();
+}
+
+void BookmarkWidget::expandItems()
+{
+ QStandardItemModel *model = bookmarkManager->treeBookmarkModel();
+ QList<QStandardItem*>list = model->findItems(QLatin1String("*"),
+ Qt::MatchWildcard | Qt::MatchRecursive, 0);
+ foreach (const QStandardItem* item, list) {
+ const QModelIndex& index = model->indexFromItem(item);
+ treeView->setExpanded(filterBookmarkModel->mapFromSource(index),
+ item->data(Qt::UserRole + 11).toBool());
+ }
+}
+
+void BookmarkWidget::focusInEvent(QFocusEvent *e)
+{
+ if (e->reason() != Qt::MouseFocusReason) {
+ searchField->selectAll();
+ searchField->setFocus();
+
+ QModelIndex index = treeView->indexAt(QPoint(1, 1));
+ if (index.isValid())
+ treeView->setCurrentIndex(index);
+
+ }
+}
+
+bool BookmarkWidget::eventFilter(QObject *object, QEvent *e)
+{
+ if (object == this && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ QModelIndex index = treeView->currentIndex();
+ switch (ke->key()) {
+ if (index.isValid() && searchField->text().isEmpty()) {
+ case Qt::Key_F2: {
+ const QModelIndex& source = filterBookmarkModel->mapToSource(index);
+ QStandardItem *item =
+ bookmarkManager->treeBookmarkModel()->itemFromIndex(source);
+ if (item) {
+ item->setEditable(true);
+ treeView->edit(index);
+ item->setEditable(false);
+ }
+ } break;
+
+ case Qt::Key_Delete: {
+ bookmarkManager->removeBookmarkItem(treeView,
+ filterBookmarkModel->mapToSource(index));
+ } break;
+ }
+
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ treeView->subclassKeyPressEvent(ke);
+ break;
+
+ case Qt::Key_Enter: {
+ case Qt::Key_Return:
+ index = treeView->selectionModel()->currentIndex();
+ if (index.isValid()) {
+ QString data = index.data(Qt::UserRole + 10).toString();
+ if (!data.isEmpty() && data != QLatin1String("Folder"))
+ emit requestShowLink(data);
+ }
+ } break;
+
+ case Qt::Key_Escape:
+ emit escapePressed();
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (object == treeView->viewport() && e->type() == QEvent::MouseButtonRelease) {
+ const QModelIndex& index = treeView->currentIndex();
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ if (index.isValid() && (me->button() == Qt::MidButton)) {
+ QString data = index.data(Qt::UserRole + 10).toString();
+ if (!data.isEmpty() && data != QLatin1String("Folder"))
+ CentralWidget::instance()->setSourceInNewTab(data);
+ }
+ }
+ return QWidget::eventFilter(object, e);
+}
+
+
+
+
+BookmarkModel::BookmarkModel(int rows, int columns, QObject * parent)
+ : QStandardItemModel(rows, columns, parent)
+{
+}
+
+BookmarkModel::~BookmarkModel()
+{
+}
+
+Qt::DropActions BookmarkModel::supportedDropActions() const
+{
+ return Qt::MoveAction;
+}
+
+Qt::ItemFlags BookmarkModel::flags(const QModelIndex &index) const
+{
+ Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index);
+ if (index.data(Qt::UserRole + 10).toString() == QLatin1String("Folder"))
+ return (Qt::ItemIsDropEnabled | defaultFlags) &~ Qt::ItemIsDragEnabled;
+
+ return (Qt::ItemIsDragEnabled | defaultFlags) &~ Qt::ItemIsDropEnabled;
+}
+
+
+
+
+BookmarkManager::BookmarkManager(QHelpEngineCore* _helpEngine)
+ : treeModel(new BookmarkModel(0, 1, this))
+ , listModel(new BookmarkModel(0, 1, this))
+ , helpEngine(_helpEngine)
+{
+ folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon);
+ treeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Bookmark"));
+ listModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Bookmark"));
+
+ connect(treeModel, SIGNAL(itemChanged(QStandardItem*)), this,
+ SLOT(itemChanged(QStandardItem*)));
+}
+
+BookmarkManager::~BookmarkManager()
+{
+ treeModel->clear();
+ listModel->clear();
+}
+
+BookmarkModel* BookmarkManager::treeBookmarkModel()
+{
+ return treeModel;
+}
+
+BookmarkModel* BookmarkManager::listBookmarkModel()
+{
+ return listModel;
+}
+
+void BookmarkManager::saveBookmarks()
+{
+ qint32 depth = 0;
+ QByteArray bookmarks;
+ QDataStream stream(&bookmarks, QIODevice::WriteOnly);
+ QStandardItem *root = treeModel->invisibleRootItem();
+
+ for (int i = 0; i < root->rowCount(); ++i) {
+ const QStandardItem *item = root->child(i);
+ stream << depth; // root
+ stream << item->data(Qt::DisplayRole).toString();
+ stream << item->data(Qt::UserRole + 10).toString();
+ stream << item->data(Qt::UserRole + 11).toBool();
+
+ if (item->rowCount() > 0) {
+ readBookmarksRecursive(item, stream, (depth +1));
+ }
+ }
+ helpEngine->setCustomValue(QLatin1String("Bookmarks"), bookmarks);
+}
+
+QStringList BookmarkManager::bookmarkFolders() const
+{
+ QStringList folders(tr("Bookmarks"));
+
+ QList<QStandardItem*>list = treeModel->findItems(QLatin1String("*"),
+ Qt::MatchWildcard | Qt::MatchRecursive, 0);
+
+ QString data;
+ foreach (const QStandardItem *item, list) {
+ data = item->data(Qt::UserRole + 10).toString();
+ if (data == QLatin1String("Folder"))
+ folders << item->data(Qt::DisplayRole).toString();
+ }
+ return folders;
+}
+
+QModelIndex BookmarkManager::addNewFolder(const QModelIndex& index)
+{
+ QStandardItem *item = new QStandardItem(uniqueFolderName());
+ item->setEditable(false);
+ item->setData(false, Qt::UserRole + 11);
+ item->setData(QLatin1String("Folder"), Qt::UserRole + 10);
+ item->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon));
+
+ if (index.isValid()) {
+ treeModel->itemFromIndex(index)->appendRow(item);
+ } else {
+ treeModel->appendRow(item);
+ }
+ return treeModel->indexFromItem(item);
+}
+
+void BookmarkManager::removeBookmarkItem(QTreeView *treeView, const QModelIndex& index)
+{
+ QStandardItem *item = treeModel->itemFromIndex(index);
+ if (item) {
+ QString data = index.data(Qt::UserRole + 10).toString();
+ if (data == QLatin1String("Folder") && item->rowCount() > 0) {
+ int value = QMessageBox::question(treeView, tr("Remove"),
+ tr("You are going to delete a Folder, this will also<br>"
+ "remove it's content. Are you sure to continue?"),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
+
+ if (value == QMessageBox::Cancel)
+ return;
+ }
+
+ if (data != QLatin1String("Folder")) {
+ QList<QStandardItem*>itemList = listModel->findItems(item->text());
+ foreach (const QStandardItem *i, itemList) {
+ if (i->data(Qt::UserRole + 10) == data) {
+ listModel->removeRow(i->row());
+ break;
+ }
+ }
+ } else {
+ removeBookmarkFolderItems(item);
+ }
+ treeModel->removeRow(item->row(), index.parent());
+ }
+}
+
+void BookmarkManager::showBookmarkDialog(QWidget* parent, const QString &name,
+ const QString &url)
+{
+ BookmarkDialog dialog(this, name, url, parent);
+ dialog.exec();
+}
+
+void BookmarkManager::addNewBookmark(const QModelIndex& index,
+ const QString &name, const QString &url)
+{
+ QStandardItem *item = new QStandardItem(name);
+ item->setEditable(false);
+ item->setData(false, Qt::UserRole + 11);
+ item->setData(url, Qt::UserRole + 10);
+
+ if (index.isValid()) {
+ treeModel->itemFromIndex(index)->appendRow(item);
+ listModel->appendRow(item->clone());
+ } else {
+ treeModel->appendRow(item);
+ listModel->appendRow(item->clone());
+ }
+}
+
+void BookmarkManager::itemChanged(QStandardItem *item)
+{
+ if (renameItem != item) {
+ renameItem = item;
+ oldText = item->text();
+ return;
+ }
+
+ if (item->text() != oldText) {
+ if (item->data(Qt::UserRole + 10).toString() != QLatin1String("Folder")) {
+ QList<QStandardItem*>itemList = listModel->findItems(oldText);
+ if (itemList.count() > 0)
+ itemList.at(0)->setText(item->text());
+ }
+ }
+}
+
+void BookmarkManager::setupBookmarkModels()
+{
+ treeModel->clear();
+ listModel->clear();
+
+ qint32 depth;
+ bool expanded;
+ QString name, type;
+ QList<int> lastDepths;
+ QList<QStandardItem*> parents;
+
+ QByteArray ba = helpEngine->customValue(QLatin1String("Bookmarks")).toByteArray();
+ QDataStream stream(ba);
+ while (!stream.atEnd()) {
+ stream >> depth >> name >> type >> expanded;
+
+ QStandardItem *item = new QStandardItem(name);
+ item->setEditable(false);
+ item->setData(type, Qt::UserRole + 10);
+ item->setData(expanded, Qt::UserRole + 11);
+ if (depth == 0) {
+ parents.clear(); lastDepths.clear();
+ treeModel->appendRow(item);
+ parents << item; lastDepths << depth;
+ } else {
+ if (depth <= lastDepths.last()) {
+ while (depth <= lastDepths.last() && parents.count() > 0) {
+ parents.pop_back(); lastDepths.pop_back();
+ }
+ }
+ parents.last()->appendRow(item);
+ if (type == QLatin1String("Folder")) {
+ parents << item; lastDepths << depth;
+ }
+ }
+
+ if (type == QLatin1String("Folder"))
+ item->setIcon(folderIcon);
+ else
+ listModel->appendRow(item->clone());
+ }
+}
+
+QString BookmarkManager::uniqueFolderName() const
+{
+ QString folderName = tr("New Folder");
+ QList<QStandardItem*> list = treeModel->findItems(folderName,
+ Qt::MatchContains | Qt::MatchRecursive, 0);
+ if (!list.isEmpty()) {
+ QStringList names;
+ foreach (const QStandardItem *item, list)
+ names << item->text();
+
+ for (int i = 1; i <= names.count(); ++i) {
+ folderName = (tr("New Folder") + QLatin1String(" %1")).arg(i);
+ if (!names.contains(folderName))
+ break;
+ }
+ }
+ return folderName;
+}
+
+void BookmarkManager::removeBookmarkFolderItems(QStandardItem *item)
+{
+ for (int j = 0; j < item->rowCount(); ++j) {
+ QStandardItem *child = item->child(j);
+ if (child->rowCount() > 0)
+ removeBookmarkFolderItems(child);
+
+ QString data = child->data(Qt::UserRole + 10).toString();
+ QList<QStandardItem*>itemList = listModel->findItems(child->text());
+ foreach (const QStandardItem *i, itemList) {
+ if (i->data(Qt::UserRole + 10) == data) {
+ listModel->removeRow(i->row());
+ break;
+ }
+ }
+ }
+}
+
+void BookmarkManager::readBookmarksRecursive(const QStandardItem *item,
+ QDataStream &stream,
+ const qint32 depth) const
+{
+ for (int j = 0; j < item->rowCount(); ++j) {
+ const QStandardItem *child = item->child(j);
+ stream << depth;
+ stream << child->data(Qt::DisplayRole).toString();
+ stream << child->data(Qt::UserRole + 10).toString();
+ stream << child->data(Qt::UserRole + 11).toBool();
+
+ if (child->rowCount() > 0)
+ readBookmarksRecursive(child, stream, (depth +1));
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/bookmarkmanager.h b/tools/assistant/tools/assistant/bookmarkmanager.h
new file mode 100644
index 0000000000..ab905d13e5
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkmanager.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BOOKMARKMANAGER_H
+#define BOOKMARKMANAGER_H
+
+#include "ui_bookmarkdialog.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+#include <QtCore/QDataStream>
+
+#include <QtGui/QIcon>
+#include <QtGui/QDialog>
+#include <QtGui/QWidget>
+#include <QtGui/QTreeView>
+#include <QtGui/QStandardItemModel>
+
+QT_BEGIN_NAMESPACE
+
+class QEvent;
+class QLineEdit;
+class QTreeView;
+class QToolButton;
+class QStandardItem;
+class QHelpEngineCore;
+class QAbstractItemModel;
+class QSortFilterProxyModel;
+
+class BookmarkManager;
+
+class BookmarkDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ BookmarkDialog(BookmarkManager *manager, const QString &title,
+ const QString &url, QWidget *parent = 0);
+ ~BookmarkDialog();
+
+private slots:
+ void addAccepted();
+ void addNewFolder();
+ void toolButtonClicked();
+ void itemChanged(QStandardItem *item);
+ void textChanged(const QString& string);
+ void selectBookmarkFolder(const QString &folderName);
+ void customContextMenuRequested(const QPoint &point);
+ void currentChanged(const QModelIndex& current, const QModelIndex& previous);
+
+private:
+ bool eventFilter(QObject *object, QEvent *e);
+
+private:
+ QString m_url;
+ QString m_title;
+
+ QString oldText;
+ QStandardItem *renameItem;
+
+ Ui::BookmarkDialog ui;
+ BookmarkManager *bookmarkManager;
+ QSortFilterProxyModel *proxyModel;
+};
+
+class TreeView : public QTreeView {
+ Q_OBJECT
+public:
+ TreeView(QWidget* parent = 0) : QTreeView(parent) {}
+ void subclassKeyPressEvent(QKeyEvent* event)
+ {
+ QTreeView::keyPressEvent(event);
+ }
+};
+
+class BookmarkWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ BookmarkWidget(BookmarkManager *manager, QWidget *parent = 0,
+ bool showButtons = true);
+ ~BookmarkWidget();
+
+signals:
+ void addBookmark();
+ void requestShowLink(const QUrl &url);
+ void escapePressed();
+
+private slots:
+ void removeClicked();
+ void filterChanged();
+ void expand(const QModelIndex& index);
+ void activated(const QModelIndex &index);
+ void customContextMenuRequested(const QPoint &point);
+
+private:
+ void setup(bool showButtons);
+ void expandItems();
+ void focusInEvent(QFocusEvent *e);
+ bool eventFilter(QObject *object, QEvent *event);
+
+private:
+ QRegExp regExp;
+ TreeView *treeView;
+ QLineEdit *searchField;
+ QToolButton *addButton;
+ QToolButton *removeButton;
+ BookmarkManager *bookmarkManager;
+ QSortFilterProxyModel* filterBookmarkModel;
+};
+
+class BookmarkModel : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ BookmarkModel(int rows, int columns, QObject *parent = 0);
+ ~BookmarkModel();
+
+ Qt::DropActions supportedDropActions() const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+};
+
+class BookmarkManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ BookmarkManager(QHelpEngineCore* helpEngine);
+ ~BookmarkManager();
+
+ BookmarkModel* treeBookmarkModel();
+ BookmarkModel* listBookmarkModel();
+
+ void saveBookmarks();
+ QStringList bookmarkFolders() const;
+ QModelIndex addNewFolder(const QModelIndex& index);
+ void removeBookmarkItem(QTreeView *treeView, const QModelIndex& index);
+ void showBookmarkDialog(QWidget* parent, const QString &name, const QString &url);
+ void addNewBookmark(const QModelIndex& index, const QString &name, const QString &url);
+ void setupBookmarkModels();
+
+private slots:
+ void itemChanged(QStandardItem *item);
+
+private:
+ QString uniqueFolderName() const;
+ void removeBookmarkFolderItems(QStandardItem *item);
+ void readBookmarksRecursive(const QStandardItem *item, QDataStream &stream,
+ const qint32 depth) const;
+
+private:
+ QString oldText;
+ QIcon folderIcon;
+
+ BookmarkModel *treeModel;
+ BookmarkModel *listModel;
+ QStandardItem *renameItem;
+ QHelpEngineCore *helpEngine;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp
new file mode 100644
index 0000000000..1b0e6712ff
--- /dev/null
+++ b/tools/assistant/tools/assistant/centralwidget.cpp
@@ -0,0 +1,1080 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "centralwidget.h"
+#include "helpviewer.h"
+#include "searchwidget.h"
+#include "mainwindow.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QEvent>
+#include <QtCore/QTimer>
+
+#include <QtGui/QMenu>
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QPrinter>
+#include <QtGui/QLineEdit>
+#include <QtGui/QCheckBox>
+#include <QtGui/QTabBar>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolButton>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QTextCursor>
+#include <QtGui/QPrintDialog>
+#include <QtGui/QApplication>
+#include <QtGui/QTextDocumentFragment>
+#include <QtGui/QPrintPreviewDialog>
+#include <QtGui/QPageSetupDialog>
+
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpSearchEngine>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ HelpViewer* helpViewerFromTabPosition(const QTabWidget *widget, const QPoint &point)
+ {
+ QTabBar *tabBar = qFindChild<QTabBar*>(widget);
+ for (int i = 0; i < tabBar->count(); ++i) {
+ if (tabBar->tabRect(i).contains(point))
+ return qobject_cast<HelpViewer*>(widget->widget(i));
+ }
+ return 0;
+ }
+ CentralWidget *staticCentralWidget = 0;
+}
+
+FindWidget::FindWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ QString system = QLatin1String("win");
+ QHBoxLayout *hboxLayout = new QHBoxLayout(this);
+#ifdef Q_OS_MAC
+ system = QLatin1String("mac");
+#else
+ hboxLayout->setSpacing(6);
+ hboxLayout->setMargin(0);
+#endif
+
+ toolClose = new QToolButton(this);
+ toolClose->setIcon(QIcon(QString::fromUtf8(":/trolltech/assistant/images/%1/closetab.png").arg(system)));
+ toolClose->setAutoRaise(true);
+ hboxLayout->addWidget(toolClose);
+
+ editFind = new QLineEdit(this);
+ editFind->setMinimumSize(QSize(150, 0));
+ connect(editFind, SIGNAL(textChanged(const QString&)),
+ this, SLOT(updateButtons()));
+ hboxLayout->addWidget(editFind);
+
+ toolPrevious = new QToolButton(this);
+ toolPrevious->setAutoRaise(true);
+ toolPrevious->setText(tr("Previous"));
+ toolPrevious->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ toolPrevious->setIcon(QIcon(QString::fromUtf8(":/trolltech/assistant/images/%1/previous.png").arg(system)));
+ hboxLayout->addWidget(toolPrevious);
+
+ toolNext = new QToolButton(this);
+ toolNext->setAutoRaise(true);
+ toolNext->setText(tr("Next"));
+ toolNext->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ toolNext->setIcon(QIcon(QString::fromUtf8(":/trolltech/assistant/images/%1/next.png").arg(system)));
+ hboxLayout->addWidget(toolNext);
+
+ checkCase = new QCheckBox(tr("Case Sensitive"), this);
+ hboxLayout->addWidget(checkCase);
+
+ checkWholeWords = new QCheckBox(tr("Whole words"), this);
+ hboxLayout->addWidget(checkWholeWords);
+#if !defined(QT_NO_WEBKIT)
+ checkWholeWords->hide();
+#endif
+
+ labelWrapped = new QLabel(this);
+ labelWrapped->setMinimumSize(QSize(0, 20));
+ labelWrapped->setMaximumSize(QSize(105, 20));
+ labelWrapped->setTextFormat(Qt::RichText);
+ labelWrapped->setScaledContents(true);
+ labelWrapped->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter);
+ labelWrapped->setText(tr("<img src=\":/trolltech/assistant/images/wrap.png\">&nbsp;Search wrapped"));
+ hboxLayout->addWidget(labelWrapped);
+
+ QSpacerItem *spacerItem = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ hboxLayout->addItem(spacerItem);
+ setMinimumWidth(minimumSizeHint().width());
+ labelWrapped->hide();
+
+ updateButtons();
+}
+
+FindWidget::~FindWidget()
+{
+}
+
+void FindWidget::updateButtons()
+{
+ if (editFind->text().isEmpty()) {
+ toolPrevious->setEnabled(false);
+ toolNext->setEnabled(false);
+ } else {
+ toolPrevious->setEnabled(true);
+ toolNext->setEnabled(true);
+ }
+}
+
+
+CentralWidget::CentralWidget(QHelpEngine *engine, MainWindow *parent)
+ : QWidget(parent)
+ , findBar(0)
+ , tabWidget(0)
+ , helpEngine(engine)
+ , printer(0)
+ , m_searchWidget(0)
+{
+ staticCentralWidget = this;
+
+ lastTabPage = 0;
+ globalActionList.clear();
+ collectionFile = helpEngine->collectionFile();
+ usesDefaultCollection = parent->usesDefaultCollection();
+
+ QString system = QLatin1String("win");
+ QVBoxLayout *vboxLayout = new QVBoxLayout(this);
+
+#ifdef Q_OS_MAC
+ system = QLatin1String("mac");
+#else
+ vboxLayout->setMargin(0);
+#endif
+
+ tabWidget = new QTabWidget(this);
+ connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentPageChanged(int)));
+
+ QToolButton *newTabButton = new QToolButton(this);
+ newTabButton->setAutoRaise(true);
+ newTabButton->setToolTip(tr("Add new page"));
+ newTabButton->setIcon(QIcon(QString::fromUtf8(":/trolltech/assistant/images/%1/addtab.png").arg(system)));
+
+ tabWidget->setCornerWidget(newTabButton, Qt::TopLeftCorner);
+ connect(newTabButton, SIGNAL(clicked()), this, SLOT(newTab()));
+
+ QToolButton *closeTabButton = new QToolButton(this);
+ closeTabButton->setEnabled(false);
+ closeTabButton->setAutoRaise(true);
+ closeTabButton->setToolTip(tr("Close current page"));
+ closeTabButton->setIcon(QIcon(QString::fromUtf8(":/trolltech/assistant/images/%1/closetab.png").arg(system)));
+
+ tabWidget->setCornerWidget(closeTabButton, Qt::TopRightCorner);
+ connect(closeTabButton, SIGNAL(clicked()), this, SLOT(closeTab()));
+
+ vboxLayout->addWidget(tabWidget);
+
+ findBar = new QWidget(this);
+ findWidget = new FindWidget(findBar);
+ findBar->setMinimumHeight(findWidget->minimumSizeHint().height());
+ findWidget->move(0, 0);
+ vboxLayout->addWidget(findBar);
+ findBar->hide();
+ findWidget->editFind->installEventFilter(this);
+ connect(findWidget->toolClose, SIGNAL(clicked()), findBar, SLOT(hide()));
+
+ connect(findWidget->toolNext, SIGNAL(clicked()), this, SLOT(findNext()));
+ connect(findWidget->editFind, SIGNAL(returnPressed()), this, SLOT(findNext()));
+ connect(findWidget->editFind, SIGNAL(textChanged(const QString&)), this, SLOT(findCurrentText(const QString&)));
+ connect(findWidget->toolPrevious, SIGNAL(clicked()), this, SLOT(findPrevious()));
+
+ QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget);
+ if (tabBar) {
+ tabBar->installEventFilter(this);
+ tabBar->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(tabBar, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(showTabBarContextMenu(const QPoint&)));
+ }
+
+ QPalette p = qApp->palette();
+ p.setColor(QPalette::Inactive, QPalette::Highlight,
+ p.color(QPalette::Active, QPalette::Highlight));
+ p.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ p.color(QPalette::Active, QPalette::HighlightedText));
+ qApp->setPalette(p);
+}
+
+CentralWidget::~CentralWidget()
+{
+ QHelpEngineCore engine(collectionFile, 0);
+ if (!engine.setupData())
+ return;
+
+ QString zoomCount;
+ QString currentPages;
+ QLatin1Char sep('|');
+ for (int i = 1; i < tabWidget->count(); ++i) {
+ HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i));
+ if (viewer && viewer->source().isValid()) {
+ currentPages.append(viewer->source().toString()).append(sep);
+#if !defined(QT_NO_WEBKIT)
+ zoomCount.append(QString::number(viewer->textSizeMultiplier())).
+ append(sep);
+#else
+ zoomCount.append(QString::number(viewer->zoom())).append(sep);
+#endif
+ }
+ }
+ engine.setCustomValue(QLatin1String("LastTabPage"), lastTabPage);
+ engine.setCustomValue(QLatin1String("LastShownPages"), currentPages);
+#if !defined(QT_NO_WEBKIT)
+ engine.setCustomValue(QLatin1String("LastPagesZoomWebView"), zoomCount);
+#else
+ engine.setCustomValue(QLatin1String("LastPagesZoomTextBrowser"), zoomCount);
+#endif
+}
+
+CentralWidget *CentralWidget::instance()
+{
+ return staticCentralWidget;
+}
+
+void CentralWidget::newTab()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ setSourceInNewTab(viewer->source());
+}
+
+void CentralWidget::zoomIn()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ viewer->zoomIn();
+
+ if (tabWidget->currentWidget() == m_searchWidget)
+ m_searchWidget->zoomIn();
+}
+
+void CentralWidget::zoomOut()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ viewer->zoomOut();
+
+ if (tabWidget->currentWidget() == m_searchWidget)
+ m_searchWidget->zoomOut();
+}
+
+void CentralWidget::findNext()
+{
+ find(findWidget->editFind->text(), true, false);
+}
+
+void CentralWidget::nextPage()
+{
+ if(tabWidget->currentIndex() < tabWidget->count() -1)
+ tabWidget->setCurrentIndex(tabWidget->currentIndex() +1);
+ else
+ tabWidget->setCurrentIndex(0);
+}
+
+void CentralWidget::resetZoom()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ viewer->resetZoom();
+
+ if (tabWidget->currentWidget() == m_searchWidget)
+ m_searchWidget->resetZoom();
+}
+
+void CentralWidget::previousPage()
+{
+ int index = tabWidget->currentIndex() -1;
+ if(index >= 0)
+ tabWidget->setCurrentIndex(index);
+ else
+ tabWidget->setCurrentIndex(tabWidget->count() -1);
+}
+
+void CentralWidget::findPrevious()
+{
+ find(findWidget->editFind->text(), false, true);
+}
+
+void CentralWidget::closeTab()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (!viewer|| tabWidget->count() == 1)
+ return;
+
+ tabWidget->removeTab(tabWidget->indexOf(viewer));
+ QTimer::singleShot(0, viewer, SLOT(deleteLater()));
+}
+
+void CentralWidget::setSource(const QUrl &url)
+{
+ HelpViewer* viewer = currentHelpViewer();
+ HelpViewer* lastViewer = qobject_cast<HelpViewer*>(tabWidget->widget(lastTabPage));
+
+ if (!viewer && !lastViewer) {
+ viewer = new HelpViewer(helpEngine, this);
+ viewer->installEventFilter(this);
+ lastTabPage = tabWidget->addTab(viewer, QString());
+ tabWidget->setCurrentIndex(lastTabPage);
+ connectSignals();
+ } else
+ viewer = lastViewer;
+
+ viewer->setSource(url);
+ currentPageChanged(lastTabPage);
+ viewer->setFocus(Qt::OtherFocusReason);
+ tabWidget->setCurrentIndex(lastTabPage);
+ tabWidget->setTabText(lastTabPage, quoteTabTitle(viewer->documentTitle()));
+}
+
+void CentralWidget::setLastShownPages()
+{
+#if !defined(QT_NO_WEBKIT)
+ QLatin1String zoom("LastPagesZoomWebView");
+#else
+ QLatin1String zoom("LastPagesZoomTextBrowser");
+#endif
+
+ const QStringList lastShownPageList =
+ helpEngine->customValue(QLatin1String("LastShownPages")).toString().
+ split(QLatin1Char('|'), QString::SkipEmptyParts);
+
+ if (!lastShownPageList.isEmpty()) {
+ QVector<QString>zoomList = helpEngine->customValue(zoom).toString().
+ split(QLatin1Char('|'), QString::SkipEmptyParts).toVector();
+ if (zoomList.isEmpty())
+ zoomList.fill(QLatin1String("0.0"), lastShownPageList.size());
+ else if(zoomList.count() < lastShownPageList.count()) {
+ zoomList.insert(zoomList.count(),
+ lastShownPageList.count() - zoomList.count(), QLatin1String("0.0"));
+ }
+
+ QVector<QString>::const_iterator zIt = zoomList.constBegin();
+ QStringList::const_iterator it = lastShownPageList.constBegin();
+ for (; it != lastShownPageList.constEnd(); ++it, ++zIt)
+ setSourceInNewTab((*it), (*zIt).toFloat());
+
+ tabWidget->setCurrentIndex(helpEngine->customValue(
+ QLatin1String("LastTabPage"), 1).toInt());
+ } else {
+ if (usesDefaultCollection)
+ setSource(QUrl(QLatin1String("help")));
+ }
+}
+
+bool CentralWidget::hasSelection() const
+{
+ const HelpViewer* viewer = currentHelpViewer();
+ return viewer ? viewer->hasSelection() : false;
+}
+
+QUrl CentralWidget::currentSource() const
+{
+ const HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ return viewer->source();
+
+ return QUrl();
+}
+
+QString CentralWidget::currentTitle() const
+{
+ const HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ return viewer->documentTitle();
+
+ return QString();
+}
+
+void CentralWidget::copySelection()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ viewer->copy();
+}
+
+void CentralWidget::showTextSearch()
+{
+ findBar->show();
+ findWidget->editFind->selectAll();
+ findWidget->editFind->setFocus(Qt::ShortcutFocusReason);
+}
+
+void CentralWidget::initPrinter()
+{
+#ifndef QT_NO_PRINTER
+ if (!printer)
+ printer = new QPrinter(QPrinter::HighResolution);
+#endif
+}
+
+void CentralWidget::print()
+{
+#ifndef QT_NO_PRINTER
+ HelpViewer* viewer = currentHelpViewer();
+ if (!viewer)
+ return;
+
+ initPrinter();
+
+ QPrintDialog *dlg = new QPrintDialog(printer, this);
+#if defined(QT_NO_WEBKIT)
+ if (viewer->textCursor().hasSelection())
+ dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection);
+#endif
+ dlg->addEnabledOption(QAbstractPrintDialog::PrintPageRange);
+ dlg->addEnabledOption(QAbstractPrintDialog::PrintCollateCopies);
+ dlg->setWindowTitle(tr("Print Document"));
+ if (dlg->exec() == QDialog::Accepted) {
+ viewer->print(printer);
+ }
+ delete dlg;
+#endif
+}
+
+void CentralWidget::printPreview()
+{
+#ifndef QT_NO_PRINTER
+ initPrinter();
+ QPrintPreviewDialog preview(printer, this);
+ connect(&preview, SIGNAL(paintRequested(QPrinter *)), SLOT(printPreview(QPrinter *)));
+ preview.exec();
+#endif
+}
+
+void CentralWidget::printPreview(QPrinter *p)
+{
+#ifndef QT_NO_PRINTER
+ HelpViewer *viewer = currentHelpViewer();
+ if (viewer)
+ viewer->print(p);
+#endif
+}
+
+void CentralWidget::pageSetup()
+{
+#ifndef QT_NO_PRINTER
+ initPrinter();
+ QPageSetupDialog dlg(printer);
+ dlg.exec();
+#endif
+}
+
+bool CentralWidget::isHomeAvailable() const
+{
+ return currentHelpViewer() ? true : false;
+}
+
+void CentralWidget::home()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ viewer->home();
+}
+
+bool CentralWidget::isForwardAvailable() const
+{
+ const HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ return viewer->isForwardAvailable();
+
+ return false;
+}
+
+void CentralWidget::forward()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ viewer->forward();
+}
+
+bool CentralWidget::isBackwardAvailable() const
+{
+ const HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ return viewer->isBackwardAvailable();
+
+ return false;
+}
+
+void CentralWidget::backward()
+{
+ HelpViewer* viewer = currentHelpViewer();
+ if (viewer)
+ viewer->backward();
+}
+
+
+QList<QAction*> CentralWidget::globalActions() const
+{
+ return globalActionList;
+}
+
+void CentralWidget::setGlobalActions(const QList<QAction*> &actions)
+{
+ globalActionList = actions;
+}
+
+void CentralWidget::setSourceInNewTab(const QUrl &url, qreal zoom)
+{
+ HelpViewer* viewer;
+
+#if defined(QT_NO_WEBKIT)
+ viewer = currentHelpViewer();
+ if (viewer && viewer->launchedWithExternalApp(url))
+ return;
+#endif
+
+ viewer = new HelpViewer(helpEngine, this);
+ viewer->installEventFilter(this);
+ viewer->setSource(url);
+ viewer->setFocus(Qt::OtherFocusReason);
+ tabWidget->setCurrentIndex(tabWidget->addTab(viewer,
+ quoteTabTitle(viewer->documentTitle())));
+
+ QFont font = qApp->font();
+ bool userFont = helpEngine->customValue(QLatin1String("useBrowserFont")).toBool();
+ if (userFont) {
+ font = qVariantValue<QFont>(helpEngine->customValue(
+ QLatin1String("browserFont")));
+ }
+
+#if !defined(QT_NO_WEBKIT)
+ QWebSettings* settings = QWebSettings::globalSettings();
+ if (!userFont) {
+ int fontSize = settings->fontSize(QWebSettings::DefaultFontSize);
+ QString fontFamily = settings->fontFamily(QWebSettings::StandardFont);
+ font = QFont(fontFamily, fontSize);
+ }
+
+ QWebView* view = qobject_cast<QWebView*> (viewer);
+ if (view) {
+ settings = view->settings();
+ settings->setFontFamily(QWebSettings::StandardFont, font.family());
+ settings->setFontSize(QWebSettings::DefaultFontSize, font.pointSize());
+ } else if (viewer) {
+ viewer->setFont(font);
+ }
+ viewer->setTextSizeMultiplier(zoom == 0.0 ? 1.0 : zoom);
+#else
+ font.setPointSize((int)(font.pointSize() + zoom));
+ viewer->setFont(font);
+ viewer->setZoom((int)zoom);
+#endif
+
+ connectSignals();
+}
+
+HelpViewer *CentralWidget::newEmptyTab()
+{
+ HelpViewer* viewer = new HelpViewer(helpEngine, this);
+ viewer->installEventFilter(this);
+ viewer->setFocus(Qt::OtherFocusReason);
+#if defined(QT_NO_WEBKIT)
+ viewer->setDocumentTitle(tr("unknown"));
+#endif
+ tabWidget->setCurrentIndex(tabWidget->addTab(viewer, tr("unknown")));
+
+ connectSignals();
+ return viewer;
+}
+
+void CentralWidget::findCurrentText(const QString &text)
+{
+ find(text, false, false);
+}
+
+void CentralWidget::connectSignals()
+{
+ const HelpViewer* viewer = currentHelpViewer();
+ if (viewer) {
+ connect(viewer, SIGNAL(copyAvailable(bool)), this, SIGNAL(copyAvailable(bool)));
+ connect(viewer, SIGNAL(forwardAvailable(bool)), this, SIGNAL(forwardAvailable(bool)));
+ connect(viewer, SIGNAL(backwardAvailable(bool)), this, SIGNAL(backwardAvailable(bool)));
+ connect(viewer, SIGNAL(sourceChanged(const QUrl&)), this, SIGNAL(sourceChanged(const QUrl&)));
+ connect(viewer, SIGNAL(highlighted(const QString&)), this, SIGNAL(highlighted(const QString&)));
+
+ connect(viewer, SIGNAL(sourceChanged(const QUrl&)), this, SLOT(setTabTitle(const QUrl&)));
+ }
+}
+
+HelpViewer *CentralWidget::currentHelpViewer() const
+{
+ return qobject_cast<HelpViewer*>(tabWidget->currentWidget());
+}
+
+void CentralWidget::activateTab(bool onlyHelpViewer)
+{
+ if (currentHelpViewer()) {
+ currentHelpViewer()->setFocus();
+ } else {
+ int idx = 0;
+ if (onlyHelpViewer)
+ idx = lastTabPage;
+ tabWidget->setCurrentIndex(idx);
+ tabWidget->currentWidget()->setFocus();
+ }
+}
+
+void CentralWidget::setTabTitle(const QUrl& url)
+{
+ int tab = lastTabPage;
+ HelpViewer* viewer = currentHelpViewer();
+
+#if !defined(QT_NO_WEBKIT)
+ if (!viewer || viewer->source() != url) {
+ QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget);
+ for (tab = 0; tab < tabBar->count(); ++tab) {
+ viewer = qobject_cast<HelpViewer*>(tabWidget->widget(tab));
+ if (viewer && viewer->source() == url)
+ break;
+ }
+ }
+#else
+ Q_UNUSED(url)
+#endif
+
+ if (viewer) {
+ tabWidget->setTabText(tab,
+ quoteTabTitle(viewer->documentTitle().trimmed()));
+ }
+}
+
+void CentralWidget::currentPageChanged(int index)
+{
+ const HelpViewer *viewer = currentHelpViewer();
+
+ if (viewer || tabWidget->count() == 1)
+ lastTabPage = index;
+
+ bool enabled = false;
+ if (viewer) {
+ enabled = true;
+ if (!m_searchWidget)
+ enabled = tabWidget->count() > 1;
+ }
+
+ tabWidget->cornerWidget(Qt::TopRightCorner)->setEnabled(enabled);
+ tabWidget->cornerWidget(Qt::TopLeftCorner)->setEnabled(m_searchWidget ? enabled : true);
+
+ emit currentViewerChanged();
+}
+
+void CentralWidget::showTabBarContextMenu(const QPoint &point)
+{
+ HelpViewer* viewer = helpViewerFromTabPosition(tabWidget, point);
+ if (!viewer)
+ return;
+
+ QTabBar *tabBar = qFindChild<QTabBar*>(tabWidget);
+
+ QMenu menu(QLatin1String(""), tabBar);
+ QAction *new_page = menu.addAction(tr("Add New Page"));
+ QAction *close_page = menu.addAction(tr("Close This Page"));
+ QAction *close_pages = menu.addAction(tr("Close Other Pages"));
+ menu.addSeparator();
+ QAction *newBookmark = menu.addAction(tr("Add Bookmark for this Page..."));
+
+ if (tabBar->count() == 1) {
+ close_page->setEnabled(false);
+ close_pages->setEnabled(false);
+ } else if (m_searchWidget && tabBar->count() == 2) {
+ close_pages->setEnabled(false);
+ }
+
+ QAction *picked_action = menu.exec(tabBar->mapToGlobal(point));
+ if (!picked_action)
+ return;
+
+ if (picked_action == new_page)
+ setSourceInNewTab(viewer->source());
+
+ if (picked_action == close_page) {
+ tabWidget->removeTab(tabWidget->indexOf(viewer));
+ QTimer::singleShot(0, viewer, SLOT(deleteLater()));
+ }
+
+ if (picked_action == close_pages) {
+ int currentPage = tabWidget->indexOf(viewer);
+ for (int i = tabBar->count() -1; i >= 0; --i) {
+ viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i));
+ if (i != currentPage && viewer) {
+ tabWidget->removeTab(i);
+ QTimer::singleShot(0, viewer, SLOT(deleteLater()));
+
+ if (i < currentPage)
+ --currentPage;
+ }
+ }
+ }
+
+ if (picked_action == newBookmark)
+ emit addNewBookmark(viewer->documentTitle(), viewer->source().toString());
+}
+
+bool CentralWidget::eventFilter(QObject *object, QEvent *e)
+{
+ if (currentHelpViewer() == object && e->type() == QEvent::KeyPress){
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Backspace) {
+ HelpViewer *viewer = currentHelpViewer();
+#if defined(QT_NO_WEBKIT)
+ if (viewer && viewer->isBackwardAvailable()) {
+#else
+ if (viewer && viewer->isBackwardAvailable() && !viewer->hasFocus()) {
+#endif
+ viewer->backward();
+ return true;
+ }
+ }
+ }
+
+ QTabBar *tabBar = qobject_cast<QTabBar*>(object);
+ bool mousRel = e->type() == QEvent::MouseButtonRelease;
+ bool dblClick = e->type() == QEvent::MouseButtonDblClick;
+
+ if (tabBar && (mousRel || dblClick)) {
+ QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(e);
+ HelpViewer *viewer = helpViewerFromTabPosition(tabWidget, mouseEvent->pos());
+ if (!m_searchWidget && tabWidget->count() <= 1)
+ return QWidget::eventFilter(object, e);
+
+ if (viewer && (mouseEvent->button() == Qt::MidButton || dblClick)) {
+ tabWidget->removeTab(tabWidget->indexOf(viewer));
+ QTimer::singleShot(0, viewer, SLOT(deleteLater()));
+ currentPageChanged(tabWidget->currentIndex());
+ return true;
+ }
+ } else if (object == findWidget->editFind && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Escape) {
+ findBar->hide();
+ HelpViewer *hv = currentHelpViewer();
+ if (hv)
+ hv->setFocus();
+ }
+ }
+ return QWidget::eventFilter(object, e);
+}
+
+void CentralWidget::keyPressEvent(QKeyEvent *e)
+{
+ QString text = e->text();
+ if (text.startsWith(QLatin1Char('/'))) {
+ if (!findBar->isVisible()) {
+ findBar->show();
+ findWidget->editFind->clear();
+ } else {
+ findWidget->editFind->selectAll();
+ }
+ findWidget->editFind->setFocus();
+ return;
+ }
+ QWidget::keyPressEvent(e);
+}
+
+void CentralWidget::find(QString ttf, bool forward, bool backward)
+{
+ QTextCursor cursor;
+ QTextDocument *doc = 0;
+ QTextBrowser *browser = 0;
+
+ HelpViewer* viewer = currentHelpViewer();
+ QPalette p = findWidget->editFind->palette();
+ p.setColor(QPalette::Active, QPalette::Base, Qt::white);
+
+#if !defined(QT_NO_WEBKIT)
+ Q_UNUSED(forward)
+ Q_UNUSED(doc)
+ Q_UNUSED(browser)
+
+ if (viewer) {
+ QWebPage::FindFlags options;
+ if (backward)
+ options |= QWebPage::FindBackward;
+
+ if (findWidget->checkCase->isChecked())
+ options |= QWebPage::FindCaseSensitively;
+
+ bool found = viewer->findText(ttf, options);
+ findWidget->labelWrapped->hide();
+
+ if (!found) {
+ options |= QWebPage::FindWrapsAroundDocument;
+ found = viewer->findText(ttf, options);
+
+ if (!found) {
+ p.setColor(QPalette::Active, QPalette::Base, QColor(255, 102, 102));
+ } else {
+ findWidget->labelWrapped->show();
+ }
+ }
+ }
+#else
+ if (viewer) {
+ doc = viewer->document();
+ cursor = viewer->textCursor();
+ browser = qobject_cast<QTextBrowser*>(viewer);
+ }
+
+ if (tabWidget->currentWidget() == m_searchWidget) {
+ QTextBrowser* browser = qFindChild<QTextBrowser*>(m_searchWidget);
+ if (browser) {
+ doc = browser->document();
+ cursor = browser->textCursor();
+ }
+ }
+
+ if (!browser || !doc || cursor.isNull())
+ return;
+
+ QTextDocument::FindFlags options;
+
+ if (cursor.hasSelection())
+ cursor.setPosition(forward ? cursor.position() : cursor.anchor(), QTextCursor::MoveAnchor);
+
+ QTextCursor newCursor = cursor;
+
+ if (!ttf.isEmpty()) {
+ if (backward)
+ options |= QTextDocument::FindBackward;
+
+ if (findWidget->checkCase->isChecked())
+ options |= QTextDocument::FindCaseSensitively;
+
+ if (findWidget->checkWholeWords->isChecked())
+ options |= QTextDocument::FindWholeWords;
+
+ newCursor = doc->find(ttf, cursor, options);
+ findWidget->labelWrapped->hide();
+
+ if (newCursor.isNull()) {
+ QTextCursor ac(doc);
+ ac.movePosition(options & QTextDocument::FindBackward
+ ? QTextCursor::End : QTextCursor::Start);
+ newCursor = doc->find(ttf, ac, options);
+ if (newCursor.isNull()) {
+ p.setColor(QPalette::Active, QPalette::Base, QColor(255, 102, 102));
+ newCursor = cursor;
+ } else {
+ findWidget->labelWrapped->show();
+ }
+ }
+ }
+#endif
+
+ if (!findWidget->isVisible())
+ findWidget->show();
+
+#if defined(QT_NO_WEBKIT)
+ if (browser)
+ browser->setTextCursor(newCursor);
+#endif
+ findWidget->editFind->setPalette(p);
+}
+
+void CentralWidget::activateSearch()
+{
+ if (tabWidget->widget(0) != m_searchWidget)
+ createSearchWidget(helpEngine->searchEngine());
+
+ tabWidget->setCurrentWidget(m_searchWidget);
+ m_searchWidget->setFocus();
+}
+
+void CentralWidget::updateBrowserFont()
+{
+ QFont font = qApp->font();
+ bool userFont = helpEngine->customValue(QLatin1String("useBrowserFont")).toBool();
+ if (userFont) {
+ font = qVariantValue<QFont>(helpEngine->customValue(
+ QLatin1String("browserFont")));
+ }
+
+#if !defined(QT_NO_WEBKIT)
+ QWebSettings* settings = QWebSettings::globalSettings();
+ if (!userFont) {
+ int fontSize = settings->fontSize(QWebSettings::DefaultFontSize);
+ QString fontFamily = settings->fontFamily(QWebSettings::StandardFont);
+ font = QFont(fontFamily, fontSize);
+ }
+#endif
+
+ QWidget* widget = 0;
+ for (int i = 0; i < tabWidget->count(); ++i) {
+ widget = tabWidget->widget(i);
+#if !defined(QT_NO_WEBKIT)
+ QWebView* view = qobject_cast<QWebView*> (widget);
+ if (view) {
+ settings = view->settings();
+ settings->setFontFamily(QWebSettings::StandardFont, font.family());
+ settings->setFontSize(QWebSettings::DefaultFontSize, font.pointSize());
+ } else if (widget) {
+ if (!userFont)
+ font = qApp->font();
+ widget->setFont(font);
+ }
+#else
+ if (widget && widget->font() != font)
+ widget->setFont(font);
+#endif
+ }
+}
+
+void CentralWidget::createSearchWidget(QHelpSearchEngine *searchEngine)
+{
+ if (!m_searchWidget) {
+ m_searchWidget = new SearchWidget(searchEngine, this);
+ connect(m_searchWidget, SIGNAL(requestShowLink(const QUrl&)), this,
+ SLOT(setSourceFromSearch(const QUrl&)));
+ connect(m_searchWidget, SIGNAL(requestShowLinkInNewTab(const QUrl&)), this,
+ SLOT(setSourceFromSearchInNewTab(const QUrl&)));
+ }
+ tabWidget->insertTab(0, m_searchWidget, tr("Search"));
+}
+
+void CentralWidget::removeSearchWidget()
+{
+ tabWidget->removeTab(0);
+}
+
+QString CentralWidget::quoteTabTitle(const QString &title) const
+{
+ QString s = title;
+ return s.replace(QLatin1Char('&'), QLatin1String("&&"));
+}
+
+void
+CentralWidget::setSourceFromSearch(const QUrl &url)
+{
+ setSource(url);
+ highlightSearchTerms();
+}
+
+void
+CentralWidget::setSourceFromSearchInNewTab(const QUrl &url)
+{
+ setSourceInNewTab(url);
+ highlightSearchTerms();
+}
+
+void
+CentralWidget::highlightSearchTerms()
+{
+#if defined(QT_NO_WEBKIT)
+ HelpViewer *viewer = currentHelpViewer();
+ if (!viewer)
+ return;
+
+ QHelpSearchEngine* searchEngine = helpEngine->searchEngine();
+ QList<QHelpSearchQuery> queryList = searchEngine->query();
+
+ QStringList terms;
+ foreach (QHelpSearchQuery query, queryList) {
+ switch (query.fieldName) {
+ default: break;
+ case QHelpSearchQuery::ALL: {
+ case QHelpSearchQuery::PHRASE:
+ case QHelpSearchQuery::DEFAULT:
+ case QHelpSearchQuery::ATLEAST:
+ foreach (QString term, query.wordList)
+ terms.append(term.remove(QLatin1String("\"")));
+ }
+ }
+ }
+
+ viewer->viewport()->setUpdatesEnabled(false);
+
+ QTextCharFormat marker;
+ marker.setForeground(Qt::red);
+
+ QTextCursor firstHit;
+
+ QTextCursor c = viewer->textCursor();
+ c.beginEditBlock();
+ foreach (const QString& term, terms) {
+ c.movePosition(QTextCursor::Start);
+ viewer->setTextCursor(c);
+
+ while (viewer->find(term, QTextDocument::FindWholeWords)) {
+ QTextCursor hit = viewer->textCursor();
+ if (firstHit.isNull() || hit.position() < firstHit.position())
+ firstHit = hit;
+
+ hit.mergeCharFormat(marker);
+ }
+ }
+
+ if (firstHit.isNull()) {
+ firstHit = viewer->textCursor();
+ firstHit.movePosition(QTextCursor::Start);
+ }
+ firstHit.clearSelection();
+ c.endEditBlock();
+ viewer->setTextCursor(firstHit);
+
+ viewer->viewport()->setUpdatesEnabled(true);
+#endif
+}
+
+void CentralWidget::closeTabAt(int index)
+{
+ HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(index));
+ tabWidget->removeTab(index);
+ QTimer::singleShot(0, viewer, SLOT(deleteLater()));
+}
+
+QMap<int, QString> CentralWidget::currentSourceFileList() const
+{
+ QMap<int, QString> sourceList;
+ for (int i = 1; i < tabWidget->count(); ++i) {
+ HelpViewer *viewer = qobject_cast<HelpViewer*>(tabWidget->widget(i));
+ if (viewer && viewer->source().isValid())
+ sourceList.insert(i, viewer->source().host());
+ }
+ return sourceList;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/centralwidget.h b/tools/assistant/tools/assistant/centralwidget.h
new file mode 100644
index 0000000000..75bd8be7d6
--- /dev/null
+++ b/tools/assistant/tools/assistant/centralwidget.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CENTRALWIDGET_H
+#define CENTRALWIDGET_H
+
+#include <QtCore/QUrl>
+#include <QtCore/QPoint>
+#include <QtCore/QObject>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QEvent;
+class QLabel;
+class QAction;
+class QCheckBox;
+class QLineEdit;
+class QToolButton;
+
+class HelpViewer;
+class QTabWidget;
+class QHelpEngine;
+class CentralWidget;
+class PrintHelper;
+class MainWindow;
+
+class SearchWidget;
+class QHelpSearchEngine;
+
+class FindWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ FindWidget(QWidget *parent = 0);
+ ~FindWidget();
+
+signals:
+ void findNext();
+ void findPrevious();
+
+private slots:
+ void updateButtons();
+
+private:
+ QLineEdit *editFind;
+ QCheckBox *checkCase;
+ QLabel *labelWrapped;
+ QToolButton *toolNext;
+ QToolButton *toolClose;
+ QToolButton *toolPrevious;
+ QCheckBox *checkWholeWords;
+
+ friend class CentralWidget;
+};
+
+class CentralWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ CentralWidget(QHelpEngine *engine, MainWindow *parent);
+ ~CentralWidget();
+
+ void setLastShownPages();
+ bool hasSelection() const;
+ QUrl currentSource() const;
+ QString currentTitle() const;
+ bool isHomeAvailable() const;
+ bool isForwardAvailable() const;
+ bool isBackwardAvailable() const;
+ QList<QAction*> globalActions() const;
+ void setGlobalActions(const QList<QAction*> &actions);
+ HelpViewer *currentHelpViewer() const;
+ void activateTab(bool onlyHelpViewer = false);
+ void activateSearch();
+ void createSearchWidget(QHelpSearchEngine *searchEngine);
+ void removeSearchWidget();
+
+ void closeTabAt(int index);
+ QMap<int, QString> currentSourceFileList() const;
+
+ static CentralWidget *instance();
+
+public slots:
+ void zoomIn();
+ void zoomOut();
+ void findNext();
+ void nextPage();
+ void resetZoom();
+ void previousPage();
+ void findPrevious();
+ void copySelection();
+ void showTextSearch();
+ void print();
+ void pageSetup();
+ void printPreview();
+ void updateBrowserFont();
+ void setSource(const QUrl &url);
+ void setSourceInNewTab(const QUrl &url, qreal zoom = 0.0);
+ void findCurrentText(const QString &text);
+ HelpViewer *newEmptyTab();
+ void home();
+ void forward();
+ void backward();
+
+signals:
+ void currentViewerChanged();
+ void copyAvailable(bool yes);
+ void sourceChanged(const QUrl &url);
+ void highlighted(const QString &link);
+ void forwardAvailable(bool available);
+ void backwardAvailable(bool available);
+ void addNewBookmark(const QString &title, const QString &url);
+
+protected:
+ void keyPressEvent(QKeyEvent *);
+
+private slots:
+ void newTab();
+ void closeTab();
+ void setTabTitle(const QUrl& url);
+ void currentPageChanged(int index);
+ void showTabBarContextMenu(const QPoint &point);
+ void printPreview(QPrinter *printer);
+ void setSourceFromSearch(const QUrl &url);
+ void setSourceFromSearchInNewTab(const QUrl &url);
+
+private:
+ void connectSignals();
+ bool eventFilter(QObject *object, QEvent *e);
+ void find(QString ttf, bool forward, bool backward);
+ void initPrinter();
+ QString quoteTabTitle(const QString &title) const;
+ void highlightSearchTerms();
+
+private:
+ int lastTabPage;
+ QString collectionFile;
+ QList<QAction*> globalActionList;
+
+ QWidget *findBar;
+ QTabWidget* tabWidget;
+ FindWidget *findWidget;
+ QHelpEngine *helpEngine;
+ QPrinter *printer;
+ bool usesDefaultCollection;
+
+ SearchWidget* m_searchWidget;
+};
+
+QT_END_NAMESPACE
+
+#endif // CENTRALWIDGET_H
diff --git a/tools/assistant/tools/assistant/cmdlineparser.cpp b/tools/assistant/tools/assistant/cmdlineparser.cpp
new file mode 100644
index 0000000000..0dae785404
--- /dev/null
+++ b/tools/assistant/tools/assistant/cmdlineparser.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFileInfo>
+#include <QtGui/QMessageBox>
+
+#include "cmdlineparser.h"
+
+QT_BEGIN_NAMESPACE
+
+#define CHECK_NEXT_ARG \
+ ++i < arguments.count() && !arguments.at(i).startsWith(QLatin1String("-"))
+
+CmdLineParser::CmdLineParser()
+ : m_enableRemoteControl(false),
+ m_contents(Untouched),
+ m_index(Untouched),
+ m_bookmarks(Untouched),
+ m_search(Untouched),
+ m_register(None),
+ m_copy(false),
+ m_quiet(false)
+{
+ m_helpMessage = QLatin1String(
+ "Usage: assistant [Options]\n\n"
+ "-collectionFile file Uses the specified collection\n"
+ " file instead of the default one\n"
+ "-showUrl url Shows the document with the\n"
+ " url.\n"
+ "-enableRemoteControl Enables Assistant to be\n"
+ " remotely controlled.\n"
+ "-show widget Shows the specified dockwidget\n"
+ " which can be \"contents\", \"index\",\n"
+ " \"bookmarks\" or \"search\".\n"
+ "-activate widget Activates the specified dockwidget\n"
+ " which can be \"contents\", \"index\",\n"
+ " \"bookmarks\" or \"search\".\n"
+ "-hide widget Hides the specified dockwidget\n"
+ " which can be \"contents\", \"index\"\n"
+ " \"bookmarks\" or \"search\".\n"
+ "-register helpFile Registers the specified help file\n"
+ " (.qch) in the given collection\n"
+ " file.\n"
+ "-unregister helpFile Unregisters the specified help file\n"
+ " (.qch) from the give collection\n"
+ " file.\n"
+ "-setCurrentFilter filter Set the filter as the active filter.\n"
+ "-quiet Does not display any error or\n"
+ " status message.\n"
+ "-help Displays this help.\n"
+ );
+}
+
+CmdLineParser::Result CmdLineParser::parse(const QStringList &arguments)
+{
+ QString error;
+ bool showHelp = false;
+
+ for (int j=1; j<arguments.count(); ++j) {
+ if (arguments.at(j).toLower() == QLatin1String("-quiet")) {
+ m_quiet = true;
+ break;
+ }
+ }
+
+ for (int i=1; i<arguments.count(); ++i) {
+ QString arg = arguments.at(i).toLower();
+ if (arg == QLatin1String("-collectionfile")) {
+ if (CHECK_NEXT_ARG) {
+ m_collectionFile = getFileName(arguments.at(i));
+ if (m_collectionFile.isEmpty()) {
+ error = QObject::tr("The specified collection file does not exist!");
+ break;
+ }
+ } else {
+ error = QObject::tr("Missing collection file!");
+ break;
+ }
+ } else if (arg == QLatin1String("-showurl")) {
+ if (CHECK_NEXT_ARG) {
+ QUrl url(arguments.at(i));
+ if (url.isValid()) {
+ m_url = url;
+ } else {
+ error = QObject::tr("Invalid URL!");
+ break;
+ }
+ } else {
+ error = QObject::tr("Missing URL!");
+ break;
+ }
+ } else if (arg == QLatin1String("-enableremotecontrol")) {
+ m_enableRemoteControl = true;
+ } else if (arg == QLatin1String("-show")) {
+ if (CHECK_NEXT_ARG) {
+ arg = arguments.at(i).toLower();
+ if (arg == QLatin1String("contents")) {
+ m_contents = Show;
+ } else if (arg == QLatin1String("index")) {
+ m_index = Show;
+ } else if (arg == QLatin1String("bookmarks")) {
+ m_bookmarks = Show;
+ } else if (arg == QLatin1String("search")) {
+ m_search = Show;
+ } else {
+ error = QObject::tr("Unknown widget: %1").arg(arg);
+ break;
+ }
+ } else {
+ error = QObject::tr("Missing widget!");
+ break;
+ }
+ } else if (arg == QLatin1String("-hide")) {
+ if (CHECK_NEXT_ARG) {
+ arg = arguments.at(i).toLower();
+ if (arg == QLatin1String("contents")) {
+ m_contents = Hide;
+ } else if (arg == QLatin1String("index")) {
+ m_index = Hide;
+ } else if (arg == QLatin1String("bookmarks")) {
+ m_bookmarks = Hide;
+ } else if (arg == QLatin1String("search")) {
+ m_search = Hide;
+ } else {
+ error = QObject::tr("Unknown widget: %1").arg(arg);
+ break;
+ }
+ } else {
+ error = QObject::tr("Missing widget!");
+ break;
+ }
+ } else if (arg == QLatin1String("-activate")) {
+ if (CHECK_NEXT_ARG) {
+ arg = arguments.at(i).toLower();
+ if (arg == QLatin1String("contents")) {
+ m_contents = Activate;
+ } else if (arg == QLatin1String("index")) {
+ m_index = Activate;
+ } else if (arg == QLatin1String("bookmarks")) {
+ m_bookmarks = Activate;
+ } else if (arg == QLatin1String("search")) {
+ m_search = Activate;
+ } else {
+ error = QObject::tr("Unknown widget: %1").arg(arg);
+ break;
+ }
+ } else {
+ error = QObject::tr("Missing widget!");
+ break;
+ }
+ } else if (arg == QLatin1String("-register")) {
+ if (CHECK_NEXT_ARG) {
+ m_helpFile = getFileName(arguments.at(i));
+ if (m_helpFile.isEmpty()) {
+ error = QObject::tr("The specified Qt help file does not exist!");
+ break;
+ }
+ m_register = Register;
+ } else {
+ error = QObject::tr("Missing help file!");
+ break;
+ }
+ } else if (arg == QLatin1String("-unregister")) {
+ if (CHECK_NEXT_ARG) {
+ m_helpFile = getFileName(arguments.at(i));
+ if (m_helpFile.isEmpty()) {
+ error = QObject::tr("The specified Qt help file does not exist!");
+ break;
+ }
+ m_register = Unregister;
+ } else {
+ error = QObject::tr("Missing help file!");
+ break;
+ }
+ } else if (arg == QLatin1String("-setcurrentfilter")) {
+ if (CHECK_NEXT_ARG) {
+ m_currentFilter = arguments.at(i);
+ } else {
+ error = QObject::tr("Missing filter argument!");
+ break;
+ }
+ } else if (arg == QLatin1String("-quiet")) {
+ continue;
+ } else if (arg == QLatin1String("-help")) {
+ showHelp = true;
+ } else if (arg == QLatin1String("-copy")) {
+ m_copy = true;
+ } else {
+ error = QObject::tr("Unknown option: %1").arg(arg);
+ break;
+ }
+ }
+
+ if (!error.isEmpty()) {
+ showMessage(error + QLatin1String("\n\n\n") + m_helpMessage, true);
+ return Error;
+ } else if (showHelp) {
+ showMessage(m_helpMessage, false);
+ return Help;
+ }
+ return Ok;
+}
+
+QString CmdLineParser::getFileName(const QString &fileName)
+{
+ QFileInfo fi(fileName);
+ if (!fi.exists())
+ return QString();
+ return fi.absoluteFilePath();
+}
+
+void CmdLineParser::showMessage(const QString &msg, bool error)
+{
+ if (m_quiet)
+ return;
+#ifdef Q_OS_WIN
+ QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>");
+ if (error)
+ QMessageBox::critical(0, QObject::tr("Qt Assistant"), s);
+ else
+ QMessageBox::information(0, QObject::tr("Qt Assistant"), s);
+#else
+ fprintf(error ? stderr : stdout, "%s\n", qPrintable(msg));
+#endif
+}
+
+void CmdLineParser::setCollectionFile(const QString &file)
+{
+ m_collectionFile = file;
+}
+
+QString CmdLineParser::collectionFile() const
+{
+ return m_collectionFile;
+}
+
+QUrl CmdLineParser::url() const
+{
+ return m_url;
+}
+
+bool CmdLineParser::enableRemoteControl() const
+{
+ return m_enableRemoteControl;
+}
+
+CmdLineParser::ShowState CmdLineParser::contents() const
+{
+ return m_contents;
+}
+
+CmdLineParser::ShowState CmdLineParser::index() const
+{
+ return m_index;
+}
+
+CmdLineParser::ShowState CmdLineParser::bookmarks() const
+{
+ return m_bookmarks;
+}
+
+CmdLineParser::ShowState CmdLineParser::search() const
+{
+ return m_search;
+}
+
+QString CmdLineParser::currentFilter() const
+{
+ return m_currentFilter;
+}
+
+CmdLineParser::RegisterState CmdLineParser::registerRequest() const
+{
+ return m_register;
+}
+
+QString CmdLineParser::helpFile() const
+{
+ return m_helpFile;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/cmdlineparser.h b/tools/assistant/tools/assistant/cmdlineparser.h
new file mode 100644
index 0000000000..332d46468a
--- /dev/null
+++ b/tools/assistant/tools/assistant/cmdlineparser.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CMDLINEPARSER_H
+#define CMDLINEPARSER_H
+
+#include <QtCore/QStringList>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class CmdLineParser
+{
+public:
+ enum Result {Ok, Help, Error};
+ enum ShowState {Untouched, Show, Hide, Activate};
+ enum RegisterState {None, Register, Unregister};
+
+ CmdLineParser();
+ Result parse(const QStringList &arguments);
+
+ void setCollectionFile(const QString &file);
+ QString collectionFile() const;
+ QString cloneFile() const;
+ QUrl url() const;
+ bool enableRemoteControl() const;
+ ShowState contents() const;
+ ShowState index() const;
+ ShowState bookmarks() const;
+ ShowState search() const;
+ QString currentFilter() const;
+ RegisterState registerRequest() const;
+ QString helpFile() const;
+
+ bool copy() const { return m_copy; }
+
+ void showMessage(const QString &msg, bool error);
+
+private:
+ QString getFileName(const QString &fileName);
+
+ QString m_helpMessage;
+ QString m_collectionFile;
+ QString m_cloneFile;
+ QString m_helpFile;
+ QUrl m_url;
+ bool m_enableRemoteControl;
+
+ ShowState m_contents;
+ ShowState m_index;
+ ShowState m_bookmarks;
+ ShowState m_search;
+ RegisterState m_register;
+ QString m_currentFilter;
+ bool m_copy;
+ bool m_quiet;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/assistant/contentwindow.cpp b/tools/assistant/tools/assistant/contentwindow.cpp
new file mode 100644
index 0000000000..ef272e8ca7
--- /dev/null
+++ b/tools/assistant/tools/assistant/contentwindow.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "contentwindow.h"
+#include "centralwidget.h"
+
+#include <QtGui/QLayout>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QMenu>
+
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpContentWidget>
+
+QT_BEGIN_NAMESPACE
+
+ContentWindow::ContentWindow(QHelpEngine *helpEngine)
+ : m_helpEngine(helpEngine)
+ , m_contentWidget(0)
+ , m_expandDepth(-2)
+{
+ m_contentWidget = m_helpEngine->contentWidget();
+ m_contentWidget->viewport()->installEventFilter(this);
+ m_contentWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(4);
+ layout->addWidget(m_contentWidget);
+
+ connect(m_contentWidget, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(showContextMenu(QPoint)));
+ connect(m_contentWidget, SIGNAL(linkActivated(QUrl)), this,
+ SIGNAL(linkActivated(QUrl)));
+
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+ connect(contentModel, SIGNAL(contentsCreated()), this, SLOT(expandTOC()));
+}
+
+ContentWindow::~ContentWindow()
+{
+}
+
+bool ContentWindow::syncToContent(const QUrl& url)
+{
+ QModelIndex idx = m_contentWidget->indexOf(url);
+ if (!idx.isValid())
+ return false;
+ m_contentWidget->setCurrentIndex(idx);
+ return true;
+}
+
+void ContentWindow::expandTOC()
+{
+ if (m_expandDepth > -2) {
+ expandToDepth(m_expandDepth);
+ m_expandDepth = -2;
+ }
+}
+
+void ContentWindow::expandToDepth(int depth)
+{
+ m_expandDepth = depth;
+ if (depth == -1)
+ m_contentWidget->expandAll();
+ else
+ m_contentWidget->expandToDepth(depth);
+}
+
+void ContentWindow::focusInEvent(QFocusEvent *e)
+{
+ if (e->reason() != Qt::MouseFocusReason)
+ m_contentWidget->setFocus();
+}
+
+void ContentWindow::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Escape)
+ emit escapePressed();
+}
+
+bool ContentWindow::eventFilter(QObject *o, QEvent *e)
+{
+ if (m_contentWidget && o == m_contentWidget->viewport() && e->type()
+ == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ if (m_contentWidget->indexAt(me->pos()).isValid()
+ && me->button() == Qt::LeftButton) {
+ itemClicked(m_contentWidget->currentIndex());
+ } else if (m_contentWidget->indexAt(me->pos()).isValid()
+ && me->button() == Qt::MidButton) {
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+ QHelpContentItem *itm =
+ contentModel->contentItemAt(m_contentWidget->currentIndex());
+ CentralWidget::instance()->setSourceInNewTab(itm->url());
+ }
+ }
+ return QWidget::eventFilter(o, e);
+}
+
+void ContentWindow::showContextMenu(const QPoint &pos)
+{
+ if (!m_contentWidget->indexAt(pos).isValid())
+ return;
+
+ QMenu menu;
+ QAction *curTab = menu.addAction(tr("Open Link"));
+ QAction *newTab = menu.addAction(tr("Open Link in New Tab"));
+ menu.move(m_contentWidget->mapToGlobal(pos));
+
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+ QHelpContentItem *itm =
+ contentModel->contentItemAt(m_contentWidget->currentIndex());
+
+ QAction *action = menu.exec();
+ if (curTab == action)
+ emit linkActivated(itm->url());
+ else if (newTab == action)
+ CentralWidget::instance()->setSourceInNewTab(itm->url());
+}
+
+void ContentWindow::itemClicked(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return;
+ QHelpContentModel *contentModel =
+ qobject_cast<QHelpContentModel*>(m_contentWidget->model());
+ QHelpContentItem *itm =
+ contentModel->contentItemAt(index);
+ if (itm)
+ emit linkActivated(itm->url());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/contentwindow.h b/tools/assistant/tools/assistant/contentwindow.h
new file mode 100644
index 0000000000..ab8f8ddeb6
--- /dev/null
+++ b/tools/assistant/tools/assistant/contentwindow.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONTENTWINDOW_H
+#define CONTENTWINDOW_H
+
+#include <QtCore/QUrl>
+#include <QtCore/QModelIndex>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpEngine;
+class QHelpContentWidget;
+
+class ContentWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ContentWindow(QHelpEngine *helpEngine);
+ ~ContentWindow();
+
+ bool syncToContent(const QUrl &url);
+ void expandToDepth(int depth);
+
+signals:
+ void linkActivated(const QUrl &link);
+ void escapePressed();
+
+private slots:
+ void showContextMenu(const QPoint &pos);
+ void expandTOC();
+ void itemClicked(const QModelIndex &index);
+
+private:
+ void focusInEvent(QFocusEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ bool eventFilter(QObject *o, QEvent *e);
+
+ QHelpEngine *m_helpEngine;
+ QHelpContentWidget *m_contentWidget;
+ int m_expandDepth;
+};
+
+QT_END_NAMESPACE
+
+#endif // CONTENTWINDOW_H
diff --git a/tools/assistant/tools/assistant/doc/HOWTO b/tools/assistant/tools/assistant/doc/HOWTO
new file mode 100644
index 0000000000..0e5b67b6e8
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/HOWTO
@@ -0,0 +1,17 @@
+How to build/ update a new assistant.qch for Assistant internal help
+
+- in case of update:
+ - open assistant.qdocconf, update year and qt version
+
+- all other cases:
+ - ..\..\..\..\qdoc3\debug\qdoc3.exe assistant.qdocconf
+ will generate an folder html containing all required stuff
+
+ - cp assistant.qhp to generated html folder
+ - run qhelpgenerator html\assistant.qhp -o ..\assistant.qch
+
+ - rebuild assistant
+
+- to test you changes:
+ - remove assistant.qch in your cache directory
+ - restart assistant
diff --git a/tools/assistant/tools/assistant/doc/assistant.qdoc b/tools/assistant/tools/assistant/doc/assistant.qdoc
new file mode 100644
index 0000000000..0d13490655
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/assistant.qdoc
@@ -0,0 +1,434 @@
+/*!
+ \page assistant.html
+ \title Qt Assistant
+
+ \chapter Introduction
+
+ This document introduces \e{Qt Assistant}, a tool for presenting on-line
+ documentation. It also introduces the Qt Reference Documentation which
+ is accessible using \e{Qt Assistant}, or with a web browser. The document is
+ divided into the following sections:
+
+ Table of contents:
+
+ \list
+ \o \l{Introduction}
+ \o \l{The One-Minute Guide to Using Qt Assistant}
+ \o \l{Introduction to the Qt Reference Documentation}
+ \o \l{Qt Assistant in More Detail}
+ \o \l{Full Text Searching}
+ \endlist
+
+ \chapter The One-Minute Guide to Using Qt Assistant
+
+ Once you have installed Qt, \QA should be ready to run:
+
+ \list
+ \o On Windows, \QA is available as a menu option on the Qt menu.
+ \o On Mac OS X, \QA is installed in the /Developer/Applications/Qt directory.
+ \o On Unix/Linux, open a terminal, type \c{assistant} and press \key{Enter}.
+ \endlist
+
+ When you start up \QA, you will be presented with a standard main window
+ application, with a menu bar and toolbar. Below these, on the left hand
+ side are navigation windows called \e{Contents}, \e{Index} and \e{Bookmarks}.
+ On the right, taking up most of the space, is the \e{Documentation} window.
+ By default, \QA loads the Qt reference documentation along with the manuals
+ of other Qt tools, like \QD or \QL.
+
+ \QA works in a similar way to a Web browser. If you click hyperlinks
+ (cross-references), the \e{Documentation} window will present the relevant
+ page. You can bookmark pages of particular interest and you can click the
+ \gui{Previous} and \gui{Next} toolbar buttons to navigate within the pages
+ you have visited.
+
+ Although \QA can be used just like a Web browser to navigate through
+ the documentation, \QA offers a powerful means of navigation that Web
+ browsers do not provide. \QA uses an advanced full text search engine
+ to index all the pages in each compressed help file so that you can
+ search for particular words and phrases.
+
+ To perform an index search, click the \gui{Index} tab on the Sidebar
+ (or press \key{Alt+I}). In the \gui{'Look For'} line edit enter a word;
+ e.g., 'homedirpath'. As you type, words are found and highlighted in a list
+ beneath the line edit. If the highlighted text matches what you're
+ looking for, double click it, (or press \key{Enter}) and the
+ \e{Documentation} window will display the relevant page. You rarely have
+ to type in the whole word before \QA finds a match. Note that for some
+ words there may be more than one possible page that is relevant.
+
+ \QA also provides full text searching for finding specific words in
+ the documentation. To activate the full text search, either press \key(Alt+S)
+ or click on the \gui{Search} tab in the \e{Documentation} window. Then
+ enter the term you're looking for and hit the \gui{Search} button. All
+ documents containing the specified term will then be listed in the list box
+ below.
+
+ \chapter Introduction to the Qt Reference Documentation
+
+ The documentation for the Qt library is written in-line in the \c
+ .cpp files by the developers themselves. The documentation team
+ revises the documentation to ensure that it is accurate and usable,
+ and to provide quality control. The documentation team also writes the
+ larger texts, such as the class descriptions that introduce a class
+ along with the concepts the class uses, as well as introducing the
+ functions and properties that the class provides.
+
+ The documentation focuses on the API rather than the internals, since
+ we make great efforts to keep our API consistent and compatible with
+ each new version, but we may change the internals considerably to improve
+ performance and enhance functionality.
+
+ The Qt Reference Documentation consists of almost 1,500 HTML pages
+ (over 2,500 printed pages). The overwhelming majority of pages
+ document Qt classes. Since developers differ in the way they
+ think and work we provide a variety of approaches to navigating the
+ documentation set:
+
+ \list
+ \i The \menu{Qt's Classes} page lists every class
+ in Qt's public API, and consists of several hundred classes.
+ \i The \menu{Qt's Main Classes} page lists the
+ classes you're most likely to use most often, and provides a much
+ shorter and more managable list than the All Classes list.
+ \i The \menu{Grouped Classes} page presents a list
+ of groups, each of which leads to a list of related classes, for
+ example, the \menu{Advanced Widgets} list.
+ \i The \menu{Class Inheritance Hierarchy} page
+ presents a list of classes in terms of the hierarchy of Qt classes.
+ \i The \menu{Member Function Index} page lists all the
+ functions provided by Qt classes, each one with links to the class(es)
+ in which it appears.
+ \endlist
+
+ No matter where you find yourself in the Qt documentation, you will
+ find extensive cross-referencing. Even snippets of example code
+ contain clickable links, so that for example, if you come across a
+ class declaration in a code example, the class name will be a
+ clickable link to the class's documentation.
+
+ In addition to the class documentation some of Qt's modules have
+ extensive descriptions, and there are many overview documents which
+ describe various aspects of the Qt library; all these are linked from
+ the reference documentation home page. There are also two tutorials
+ and numerous example programs in the examples subdirectory of the Qt
+ distribution.
+
+ \chapter Qt Assistant in More Detail
+
+ \img assistant-assistant.png
+
+ \section1 Command Line Options
+
+ \QA handles the following command line options:
+
+ \table
+ \header
+ \o Command Line Option
+ \o Brief Description
+ \row
+ \o -collectionFile <file.qhc>
+ \o Uses the specified collection file instead of the default one.
+ \row
+ \o -showUrl URL
+ \o Shows the document referenced by URL.
+ \row
+ \o -enableRemoteControl
+ \o Enables \QA to be remotly controlled.
+ \row
+ \o -show <widget>
+ \o Shows the specified dockwidget which can be "contents", "index",
+ "bookmarks" or "search".
+ \row
+ \o -hide <widget>
+ \o Hides the specified dockwidget which can be "contents", "index",
+ "bookmarks" or "search.
+ \row
+ \o -activate <widget>
+ \o Activates the specified dockwidget which can be "contents",
+ "index", "bookmarks" or "search.
+ \row
+ \o -register <doc.qch>
+ \o Registers the specified compressed help file in the given help
+ collection.
+ \row
+ \o -unregister <doc.qch>
+ \o Unregisters the specified compressed help file from the given
+ collection file.
+ \row
+ \o -quiet
+ \o Doesn't show any error, warning or success messages.
+ \endtable
+
+ \section1 Tool Windows
+
+ \img assistant-dockwidgets.png
+
+ The tool windows provide four ways to navigate the documentation:
+
+ \list
+ \o The \gui{Contents} window presents a table of contents implemented as a
+ tree view for the documentation that is available. If you click an item,
+ its documentation will appear in the \e{Documentation} window. If you double
+ click an item or click on the control to the left of it, the item's sub-items
+ will appear. Click a sub-item to make its page appear in the \e{Documentation}
+ window. Click on the control next to an open item to hide its sub-items.
+ \o The \gui{Index} window is used to look up key words or phrases.
+ See \l{The One-Minute Guide to Using Qt Assistant} for how to use this
+ window.
+ \o The \gui{Bookmarks} window lists any bookmarks you have made. Double
+ click a bookmark to make its page appear in the \e{Documentation} window.
+ The \gui{Bookmarks} window provides a context menu with \gui{Show Item},
+ \gui{Delete Item} as well as \gui{Rename Item}. Click in the main menu
+ \menu{Bookmark|Add Bookmark...} (or press \key{Ctrl+B}) to bookmark the
+ page that is currently showing in the \e{Documentation} window. Right click
+ a bookmark in the list to rename or delete the highlighted bookmark.
+ \endlist
+
+ If you want the \gui{Documentation} window to use as much space as possible,
+ you can easily group, move or hide the tool windows. To group the windows,
+ drag one on top of the other and release the mouse. If one or all tool
+ windows are not shown, press \key{Alt+C}, \key{Alt+I} or \key{Alt+O} to show
+ the required window.
+
+ The tool windows can be docked into the main window, so you can drag them
+ to the top, left, right or bottom of \e{Qt Assistant's} window, or you can
+ drag them outside \QA to float them as independent windows.
+
+ \section1 Documentation Window
+
+ \img assistant-docwindow.png
+
+ The \gui{Documentation} window lets you create a tab for each
+ documentation page that you view. Click the \gui{Add Tab} button and a new
+ tab will appear with the page name as the tab's caption. This makes it
+ convenient to switch between pages when you are working with different
+ documentation. You can delete a tab by clicking the \gui{Close Tab} button
+ located on the right side of the \gui{Documentation} window.
+
+ \section1 Toolbars
+
+ \img assistant-toolbar.png
+
+ The main toolbar provides fast access to the most common actions.
+
+ \table
+ \header \o Action \o Description \o Menu Item \o Shortcut
+ \row \o \gui{Previous} \o Takes you to the previous page in the history.
+ \o \menu{Go|Previous} \o \key{Alt+Left Arrow}
+ \row \o \gui{Next} \o Takes you to the next page in the history.
+ \o \menu{Go|Next} \o \key{Alt+Right Arrow}
+ \row \o \gui{Home}
+ \o Takes you to the home page as specified in the Preferences Dialog.
+ \o \menu{Go|Home} \o \key{Ctrl+Home}.
+ \row \o \gui{Sync with Table of Contents}
+ \o Synchronizes the \gui{Contents} tool window with the page currently
+ shown in the \gui{Documentation} window.
+ \o \menu{Go|Sync with Table of Contents} \o
+ \row \o \gui{Copy} \o Copies any selected text to the clipboard.
+ \o \menu{Edit|Copy} \o \key{Ctrl+C}
+ \row \o \gui{Print} \o Opens the \gui{Print} dialog.
+ \o \menu{File|Print} \o \key{Ctrl+P}
+ \row \o \gui{Find in Text} \o Opens the \gui{Find Text} dialog.
+ \o \menu{Edit|Find in Text} \o \key{Ctrl+F}
+ \row \o \gui{Zoom in}
+ \o Increases the font size used to display text in the current tab.
+ \o \menu{View|Zoom in} \o \key{Ctrl++}
+ \row \o \gui{Zoom out}
+ \o Decreases the font size used to display text in the current tab.
+ \o \menu{View|Zoom out} \o \key{Ctrl+-}
+ \row \o \gui{Normal Size}
+ \o Resets the font size to its normal size in the current tab.
+ \o \menu{View|Normal Size} \o \key{Ctrl+0}
+ \endtable
+
+ \img assistant-address-toolbar.png
+
+ The address toolbar provides a fast way to enter a specific URL for a
+ documentation file. By default, the address toolbar is not shown, so it
+ has to be activated via \menu{View|Toolbars|Address Toolbar}.
+
+ \img assistant-filter-toolbar.png
+
+ The filter toolbar allows you to apply a filter to the currently installed
+ documentation. As with the address toolbar, the filter toolbar is not visible
+ by default and has to be activated via \menu{View|Toolbars|Filter Toolbar}.
+
+ \section1 Menus
+
+ \section2 File Menu
+
+ \list
+ \o \menu{File|Page Setup...} invokes a dialog allowing you to define
+ page layout properties, such as margin sizes, page orientation and paper size.
+ \o \menu{File|Print Preview...} provides a preview of the printed pages.
+ \o \menu{File|Print...} opens the \l{#Print Dialog}{\gui{Print} dialog}.
+ \o \menu{File|New Tab} opens a new empty tab in the \gui{Documentation}
+ window.
+ \o \menu{File|Close Tab} closes the current tab of the
+ \gui{Documentation} window.
+ \o \menu{File|Exit} closes the \QA application.
+ \endlist
+
+ \section2 Edit Menu
+
+ \list
+ \o \menu{Edit|Copy} copies any selected text to the clipboard.
+ \o \menu{Edit|Find in Text} invokes the \l{#Find Text Control}{\gui{Find Text}
+ control} at the lower end of the \gui{Documentation} window.
+ \o \menu{Edit|Find Next} looks for the next occurance of the specified
+ text in the \gui{Find Text} control.
+ \o \menu{Edit|Find Previous} looks for the previous occurance of
+ the specified text in the \l{#Find Text Control}{\gui{Find Text} control}.
+ \o \menu{Edit|Preferences} invokes the \l{#Preferences Dialog}{\gui{Preferences} dialog}.
+ \endlist
+
+ \section2 View Menu
+
+ \list
+ \o \menu{View|Zoom in} increases the font size in the current tab.
+ \o \menu{View|Zoom out} decreases the font size in the current tab.
+ \o \menu{View|Normal Size} resets the font size in the current tab.
+ \o \menu{View|Contents} toggles the display of the \gui{Contents} tool window.
+ \o \menu{View|Index} toggles the display of the \gui{Index} tool window.
+ \o \menu{View|Bookmarks} toggles the display of the \gui{Bookmarks} tool window.
+ \o \menu{View|Search} toggles the display of the Search in the \gui{Documentation} window.
+ \endlist
+
+ \section2 Go Menu
+
+ \list
+ \o \menu{Go|Home} goes to the home page.
+ \o \menu{Go|Back} displays the previous page in the history.
+ \o \menu{Go|Forward} displays the next page in the history.
+ \o \menu{Go|Sync with Table of Contents} syncs the \gui{Contents} tool window to the currently shown page.
+ \o \menu{Go|Next Page} selects the next tab in the \gui{Documentation} window.
+ \o \menu{Go|Previous Page} selects the previous tab in the \gui{Documentation} window.
+ \endlist
+
+ \section2 Bookmarks Menu
+
+ \list
+ \o \menu{Bookmarks|Add} adds the current page to the list of bookmarks.
+ \endlist
+
+ \section1 Dialogs
+
+ \section2 Print Dialog
+
+ This dialog is platform-specific. It gives access to various printer
+ options and can be used to print the document shown in the current tab.
+
+ \section2 Preferences Dialog
+
+ \img assistant-preferences-fonts.png
+
+ The \menu{Fonts} page allows you to change the font family and font sizes of the
+ browser window displaying the documentation or the application itself.
+
+ \img assistant-preferences-filters.png
+
+ The \menu{Filters} page lets you create and remove documentation
+ filters. To add a new filter, click the \gui{Add} button, specify a
+ filter name in the pop-up dialog and click \gui{OK}, then select
+ the filter attributes in the list box on the right hand side.
+ You can delete a filter by selecting it and clicking the \gui{Remove}
+ button.
+
+ \img assistant-preferences-documentation.png
+
+ The \menu{Documentation} page lets you install and remove compressed help
+ files. Click the \gui{Install} button and choose the path of the compressed
+ help file (*.qch) you would like to install.
+ To delete a help file, select a documentation set in the list and click
+ \gui{Remove}.
+
+ \img assistant-preferences-options.png
+
+ The \menu{Options} page lets you specify the homepage \QA will display when
+ you click the \gui{Home} button in \QA's main user interface. You can specify
+ the hompage by typing it here or clicking on one of the buttons below the
+ textbox. \gui{Current Page} sets the currently displayed page as your home
+ page while \gui{Restore to default} will reset your home page to the default
+ home page.
+
+ \section1 Find Text Control
+
+ This control is used to find text in the current page. Enter the text you want
+ to find in the line edit. The search is incremental, meaning that the most
+ relevant result is shown as you enter characters into the line edit.
+
+ If you check the \gui{Whole words only} checkbox, the search will only consider
+ whole words; for example, if you search for "spin" with this checkbox checked it will
+ not match "spinbox", but will match "spin". If you check the \gui{Case sensitive}
+ checkbox then, for example, "spin" will match "spin" but not "Spin". You can
+ search forwards or backwards from your current position in the page by clicking
+ the \gui{Previous} or \gui{Next} buttons. To hide the find control, either click the
+ \gui{Close} button or hit the \key{Esc} key.
+
+ \section1 Filtering Help Contents
+
+ \QA allows you to install any kind of documentation as long as it is organized
+ in Qt compressed help files (*.qch). For example, it is possible to install the
+ Qt reference documentation for Qt 4.4.0 and Qt 4.4.1 at the same time. In many
+ respects, this is very convenient since only one version of \QA is needed.
+ However, at the same time it becomes more complicated when performing tasks like
+ searching the index because nearly every keyword is defined in Qt 4.4.0 as well
+ as in Qt 4.4.1. This means that \QA will always ask the user to choose which one
+ should be displayed.
+
+ We use documentation filters to solve this issue. A filter is identified by its
+ name, and contains a list of filter attributes. An attribute is just a string and
+ can be freely chosen. Attributes are defined by the documentation itself, this
+ means that every documentation set usually has one or more attributes.
+
+ For example, the Qt 4.4.0 \QA documentation defines the attributes \c {assistant},
+ \c{tools} and \c{4.4.0}, \QD defines \c{designer}, \c{tools} and \c{4.4.0}.
+ The filter to display all tools would then define only the attribute
+ \c{tools} since this attribute is part of both documentation sets.
+ Adding the attribute \c{assistant} to the filter would then only show \QA
+ documentation since the \QD documentation does not contain this
+ attribute. Having an empty list of attributes in a filter will match all
+ documentation; i.e., it is equivalent to requesting unfiltered documentation.
+
+ \section1 Full Text Searching
+
+ \img assistant-search.png
+
+ \QA provides a powerful full text search engine. To search
+ for certain words or text, click the \gui{Search} tab in the \gui{Documentation}
+ window. Then enter the text you want to look for and press \key{Enter}
+ or click the \gui{Search} button. The search is not case sensitive, so,
+ for example, Foo, fOo and FOO are all treated as the same. The following are
+ examples of common search patterns:
+
+ \list
+ \o \c deep -- lists all the documents that contain the word 'deep'
+ \o \c{deep*} -- lists all the documents that contain a word beginning
+ with 'deep'
+ \o \c{deep copy} -- lists all documents that contain both 'deep' \e
+ and 'copy'
+ \o \c{"deep copy"} -- list all documents that contain the phrase 'deep copy'
+ \endlist
+
+ It is also possible to use the \gui{Advanced search} to get more flexibility.
+ You can specify some words so that hits containing these are excluded from the
+ result, or you can search for an exact phrase. Searching for similar words will
+ give results like these:
+
+ \list
+ \o \c{QStin} -- lists all the documents with titles that are similar, such as \c{QString}
+ \o \c{QSting} -- lists all the documents with titles that are similar, such as \c{QString}
+ \o \c{QStrin} -- lists all the documents with titles that are similar, such as \c{QString}
+ \endlist
+
+ Options can be combined to improve the search results.
+
+ The list of documents found is ordered according to the number of
+ occurrences of the search text which they contain, with those containing
+ the highest number of occurrences appearing first. Simply click any
+ document in the list to display it in the \gui{Documentation} window.
+
+ If the documentation has changed \mdash for example, if documents have been added
+ or removed \mdash \QA will index them again.
+*/
diff --git a/tools/assistant/tools/assistant/doc/assistant.qdocconf b/tools/assistant/tools/assistant/doc/assistant.qdocconf
new file mode 100644
index 0000000000..50f18c0e76
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/assistant.qdocconf
@@ -0,0 +1,17 @@
+include(../../../../qdoc3/test/qt.qdocconf)
+
+version =
+
+sourcedirs = $QTDIR/tools/assistant/tools/assistant/doc
+imagedirs = $QTDIR/tools/assistant/tools/assistant/doc/images
+outputdir = $QTDIR/tools/assistant/tools/assistant/doc/html
+project = assistant
+description = "Qt Assistant"
+HTML.{postheader,address} = ""
+HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
+ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
+ "<td width=\"30%\" align=\"left\">Copyright &copy; 2008 Nokia Corporation " \
+ "and/or its subsidiary(-ies)</td>\n" \
+ "<td width=\"40%\" align=\"center\">Trademarks</td>\n" \
+ "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt 4.5.0</div></td>\n" \
+ "</tr></table></div></address>"
diff --git a/tools/assistant/tools/assistant/doc/assistant.qhp b/tools/assistant/tools/assistant/doc/assistant.qhp
new file mode 100644
index 0000000000..7a26101859
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/assistant.qhp
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<QtHelpProject version="1.0">
+ <virtualFolder>assistant</virtualFolder>
+ <namespace>com.trolltech.com.assistantinternal_1.0.0</namespace>
+ <filterSection>
+ <files>
+ <file>assistant.html</file>
+ <file>classic.css</file>
+ <file>images/assistant-address-toolbar.png</file>
+ <file>images/assistant-assistant.png</file>
+ <file>images/assistant-dockwidgets.png</file>
+ <file>images/assistant-docwindow.png</file>
+ <file>images/assistant-filter-toolbar.png</file>
+ <file>images/assistant-preferences-documentation.png</file>
+ <file>images/assistant-preferences-filters.png</file>
+ <file>images/assistant-preferences-fonts.png</file>
+ <file>images/assistant-preferences-options.png</file>
+ <file>images/assistant-search.png</file>
+ <file>images/assistant-toolbar.png</file>
+ </files>
+ </filterSection>
+</QtHelpProject>
diff --git a/tools/assistant/tools/assistant/doc/classic.css b/tools/assistant/tools/assistant/doc/classic.css
new file mode 100644
index 0000000000..911354035c
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/classic.css
@@ -0,0 +1,92 @@
+h3.fn,span.fn
+{
+ margin-left: 1cm;
+ text-indent: -1cm;
+}
+
+a:link
+{
+ color: #004faf;
+ text-decoration: none
+}
+
+a:visited
+{
+ color: #672967;
+ text-decoration: none
+}
+
+td.postheader
+{
+ font-family: sans-serif
+}
+
+tr.address
+{
+ font-family: sans-serif
+}
+
+body
+{
+ background: #ffffff;
+ color: black
+}
+
+table tr.odd {
+ background: #f0f0f0;
+ color: black;
+}
+
+table tr.even {
+ background: #e4e4e4;
+ color: black;
+}
+
+table.annotated th {
+ padding: 3px;
+ text-align: left
+}
+
+table.annotated td {
+ padding: 3px;
+}
+
+table tr pre
+{
+ padding-top: none;
+ padding-bottom: none;
+ padding-left: none;
+ padding-right: none;
+ border: none;
+ background: none
+}
+
+tr.qt-style
+{
+ background: #a2c511;
+ color: black
+}
+
+body pre
+{
+ padding: 0.2em;
+ border: #e7e7e7 1px solid;
+ background: #f1f1f1;
+ color: black
+}
+
+span.preprocessor, span.preprocessor a
+{
+ color: darkblue;
+}
+
+span.comment
+{
+ color: darkred;
+ font-style: italic
+}
+
+span.string,span.char
+{
+ color: darkgreen;
+}
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-address-toolbar.png b/tools/assistant/tools/assistant/doc/images/assistant-address-toolbar.png
new file mode 100644
index 0000000000..847b7debba
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-address-toolbar.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-assistant.png b/tools/assistant/tools/assistant/doc/images/assistant-assistant.png
new file mode 100644
index 0000000000..b825de0987
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-assistant.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-dockwidgets.png b/tools/assistant/tools/assistant/doc/images/assistant-dockwidgets.png
new file mode 100644
index 0000000000..17bc064c53
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-dockwidgets.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-docwindow.png b/tools/assistant/tools/assistant/doc/images/assistant-docwindow.png
new file mode 100644
index 0000000000..c5bac581f6
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-docwindow.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-examples.png b/tools/assistant/tools/assistant/doc/images/assistant-examples.png
new file mode 100644
index 0000000000..47c01bcda7
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-examples.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-filter-toolbar.png b/tools/assistant/tools/assistant/doc/images/assistant-filter-toolbar.png
new file mode 100644
index 0000000000..4e89a79b9f
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-filter-toolbar.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-preferences-documentation.png b/tools/assistant/tools/assistant/doc/images/assistant-preferences-documentation.png
new file mode 100644
index 0000000000..790fd9a1a7
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-preferences-documentation.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-preferences-filters.png b/tools/assistant/tools/assistant/doc/images/assistant-preferences-filters.png
new file mode 100644
index 0000000000..7453dd66d6
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-preferences-filters.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-preferences-fonts.png b/tools/assistant/tools/assistant/doc/images/assistant-preferences-fonts.png
new file mode 100644
index 0000000000..d42d190d00
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-preferences-fonts.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-preferences-options.png b/tools/assistant/tools/assistant/doc/images/assistant-preferences-options.png
new file mode 100644
index 0000000000..d6624151ad
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-preferences-options.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-search.png b/tools/assistant/tools/assistant/doc/images/assistant-search.png
new file mode 100644
index 0000000000..ef75c3329f
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-search.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/doc/images/assistant-toolbar.png b/tools/assistant/tools/assistant/doc/images/assistant-toolbar.png
new file mode 100644
index 0000000000..1b41825c64
--- /dev/null
+++ b/tools/assistant/tools/assistant/doc/images/assistant-toolbar.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/filternamedialog.cpp b/tools/assistant/tools/assistant/filternamedialog.cpp
new file mode 100644
index 0000000000..fc137ed96a
--- /dev/null
+++ b/tools/assistant/tools/assistant/filternamedialog.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QPushButton>
+
+#include "filternamedialog.h"
+
+QT_BEGIN_NAMESPACE
+
+FilterNameDialog::FilterNameDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ m_ui.setupUi(this);
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Ok),
+ SIGNAL(clicked()), this, SLOT(accept()));
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel),
+ SIGNAL(clicked()), this, SLOT(reject()));
+ connect(m_ui.lineEdit, SIGNAL(textChanged(QString)),
+ this, SLOT(updateOkButton()));
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
+
+}
+
+QString FilterNameDialog::filterName() const
+{
+ return m_ui.lineEdit->text();
+}
+
+void FilterNameDialog::updateOkButton()
+{
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)
+ ->setDisabled(m_ui.lineEdit->text().isEmpty());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/filternamedialog.h b/tools/assistant/tools/assistant/filternamedialog.h
new file mode 100644
index 0000000000..32e849c41b
--- /dev/null
+++ b/tools/assistant/tools/assistant/filternamedialog.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILTERNAMEDIALOG_H
+#define FILTERNAMEDIALOG_H
+
+#include <QtGui/QDialog>
+#include "ui_filternamedialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class FilterNameDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ FilterNameDialog(QWidget *parent = 0);
+ QString filterName() const;
+
+private slots:
+ void updateOkButton();
+
+private:
+ Ui::FilterNameDialogClass m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif // FILTERNAMEDIALOG_H
diff --git a/tools/assistant/tools/assistant/filternamedialog.ui b/tools/assistant/tools/assistant/filternamedialog.ui
new file mode 100644
index 0000000000..755a934799
--- /dev/null
+++ b/tools/assistant/tools/assistant/filternamedialog.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>FilterNameDialogClass</class>
+ <widget class="QDialog" name="FilterNameDialogClass" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>312</width>
+ <height>95</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Add Filter Name</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Filter Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <widget class="QLineEdit" name="lineEdit" />
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="Line" name="line" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp
new file mode 100644
index 0000000000..9817f23dae
--- /dev/null
+++ b/tools/assistant/tools/assistant/helpviewer.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "helpviewer.h"
+#include "centralwidget.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QEvent>
+#include <QtCore/QVariant>
+#include <QtCore/QByteArray>
+#include <QtCore/QTimer>
+
+#include <QtGui/QMenu>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QClipboard>
+#include <QtGui/QApplication>
+#include <QtGui/QMessageBox>
+#include <QtGui/QDesktopServices>
+
+#include <QtHelp/QHelpEngine>
+
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_WEBKIT)
+
+class HelpNetworkReply : public QNetworkReply
+{
+public:
+ HelpNetworkReply(const QNetworkRequest &request, const QByteArray &fileData,
+ const QString &mimeType);
+
+ virtual void abort();
+
+ virtual qint64 bytesAvailable() const
+ { return data.length() + QNetworkReply::bytesAvailable(); }
+
+protected:
+ virtual qint64 readData(char *data, qint64 maxlen);
+
+private:
+ QByteArray data;
+ qint64 origLen;
+};
+
+HelpNetworkReply::HelpNetworkReply(const QNetworkRequest &request,
+ const QByteArray &fileData, const QString& mimeType)
+ : data(fileData), origLen(fileData.length())
+{
+ setRequest(request);
+ setOpenMode(QIODevice::ReadOnly);
+
+ setHeader(QNetworkRequest::ContentTypeHeader, mimeType);
+ setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(origLen));
+ QTimer::singleShot(0, this, SIGNAL(metaDataChanged()));
+ QTimer::singleShot(0, this, SIGNAL(readyRead()));
+}
+
+void HelpNetworkReply::abort()
+{
+ // nothing to do
+}
+
+qint64 HelpNetworkReply::readData(char *buffer, qint64 maxlen)
+{
+ qint64 len = qMin(qint64(data.length()), maxlen);
+ if (len) {
+ qMemCopy(buffer, data.constData(), len);
+ data.remove(0, len);
+ }
+ if (!data.length())
+ QTimer::singleShot(0, this, SIGNAL(finished()));
+ return len;
+}
+
+class HelpNetworkAccessManager : public QNetworkAccessManager
+{
+public:
+ HelpNetworkAccessManager(QHelpEngine *engine, QObject *parent);
+
+protected:
+ virtual QNetworkReply *createRequest(Operation op,
+ const QNetworkRequest &request, QIODevice *outgoingData = 0);
+
+private:
+ QHelpEngine *helpEngine;
+};
+
+HelpNetworkAccessManager::HelpNetworkAccessManager(QHelpEngine *engine,
+ QObject *parent)
+ : QNetworkAccessManager(parent), helpEngine(engine)
+{
+}
+
+QNetworkReply *HelpNetworkAccessManager::createRequest(Operation op,
+ const QNetworkRequest &request, QIODevice *outgoingData)
+{
+ const QString& scheme = request.url().scheme();
+ if (scheme == QLatin1String("qthelp") || scheme == QLatin1String("about")) {
+ const QUrl& url = request.url();
+ QString mimeType = url.toString();
+ if (mimeType.endsWith(QLatin1String(".svg"))
+ || mimeType.endsWith(QLatin1String(".svgz"))) {
+ mimeType = QLatin1String("image/svg+xml");
+ }
+ else if (mimeType.endsWith(QLatin1String(".css"))) {
+ mimeType = QLatin1String("text/css");
+ }
+ else if (mimeType.endsWith(QLatin1String(".js"))) {
+ mimeType = QLatin1String("text/javascript");
+ } else {
+ mimeType = QLatin1String("text/html");
+ }
+ return new HelpNetworkReply(request, helpEngine->fileData(url), mimeType);
+ }
+ return QNetworkAccessManager::createRequest(op, request, outgoingData);
+}
+
+class HelpPage : public QWebPage
+{
+public:
+ HelpPage(CentralWidget *central, QHelpEngine *engine, QObject *parent);
+
+protected:
+ virtual QWebPage *createWindow(QWebPage::WebWindowType);
+
+ virtual bool acceptNavigationRequest(QWebFrame *frame,
+ const QNetworkRequest &request, NavigationType type);
+
+private:
+ CentralWidget *centralWidget;
+ QHelpEngine *helpEngine;
+};
+
+HelpPage::HelpPage(CentralWidget *central, QHelpEngine *engine, QObject *parent)
+ : QWebPage(parent), centralWidget(central), helpEngine(engine)
+{
+}
+
+QWebPage *HelpPage::createWindow(QWebPage::WebWindowType)
+{
+ return centralWidget->newEmptyTab()->page();
+}
+
+static bool isLocalUrl(const QUrl &url)
+{
+ const QString scheme = url.scheme();
+ if (scheme.isEmpty()
+ || scheme == QLatin1String("file")
+ || scheme == QLatin1String("qrc")
+ || scheme == QLatin1String("data")
+ || scheme == QLatin1String("qthelp")
+ || scheme == QLatin1String("about"))
+ return true;
+ return false;
+}
+
+bool HelpPage::acceptNavigationRequest(QWebFrame *,
+ const QNetworkRequest &request, QWebPage::NavigationType)
+{
+ const QUrl &url = request.url();
+ if (isLocalUrl(url)) {
+ if (url.path().endsWith(QLatin1String("pdf"))) {
+ QString fileName = url.toString();
+ fileName = QDir::tempPath() + QDir::separator() + fileName.right
+ (fileName.length() - fileName.lastIndexOf(QChar('/')));
+
+ QFile tmpFile(QDir::cleanPath(fileName));
+ if (tmpFile.open(QIODevice::ReadWrite)) {
+ tmpFile.write(helpEngine->fileData(url));
+ tmpFile.close();
+ }
+ QDesktopServices::openUrl(QUrl(tmpFile.fileName()));
+ return false;
+ }
+ return true;
+ }
+
+ QDesktopServices::openUrl(url);
+ return false;
+}
+
+HelpViewer::HelpViewer(QHelpEngine *engine, CentralWidget *parent)
+ : QWebView(parent), helpEngine(engine), parentWidget(parent)
+{
+ setAcceptDrops(false);
+
+ setPage(new HelpPage(parent, helpEngine, this));
+
+ page()->setNetworkAccessManager(new HelpNetworkAccessManager(engine, this));
+
+ QAction* action = pageAction(QWebPage::OpenLinkInNewWindow);
+ action->setText(tr("Open Link in New Tab"));
+ if (!parent)
+ action->setVisible(false);
+
+ pageAction(QWebPage::DownloadLinkToDisk)->setVisible(false);
+ pageAction(QWebPage::DownloadImageToDisk)->setVisible(false);
+ pageAction(QWebPage::OpenImageInNewWindow)->setVisible(false);
+
+ connect(pageAction(QWebPage::Copy), SIGNAL(changed()), this,
+ SLOT(actionChanged()));
+ connect(pageAction(QWebPage::Back), SIGNAL(changed()), this,
+ SLOT(actionChanged()));
+ connect(pageAction(QWebPage::Forward), SIGNAL(changed()), this,
+ SLOT(actionChanged()));
+ connect(page(), SIGNAL(linkHovered(QString, QString, QString)), this,
+ SIGNAL(highlighted(QString)));
+ connect(this, SIGNAL(urlChanged(QUrl)), this, SIGNAL(sourceChanged(QUrl)));
+}
+
+void HelpViewer::setSource(const QUrl &url)
+{
+ if (url.toString() == QLatin1String("help")) {
+ load(QUrl(QLatin1String("qthelp://com.trolltech.com."
+ "assistantinternal_1.0.0/assistant/assistant.html")));
+ } else {
+ load(url);
+ }
+}
+
+void HelpViewer::resetZoom()
+{
+ setTextSizeMultiplier(1.0);
+}
+
+void HelpViewer::zoomIn(qreal range)
+{
+ setTextSizeMultiplier(textSizeMultiplier() + range / 10.0);
+}
+
+void HelpViewer::zoomOut(qreal range)
+{
+ setTextSizeMultiplier(qMax(0.0, textSizeMultiplier() - range / 10.0));
+}
+
+void HelpViewer::home()
+{
+ QString homepage = helpEngine->customValue(QLatin1String("homepage"),
+ QLatin1String("")).toString();
+
+ if (homepage.isEmpty()) {
+ homepage = helpEngine->customValue(QLatin1String("defaultHomepage"),
+ QLatin1String("help")).toString();
+ }
+
+ setSource(homepage);
+}
+
+void HelpViewer::wheelEvent(QWheelEvent *e)
+{
+ if (e->modifiers() & Qt::ControlModifier) {
+ const int delta = e->delta();
+ if (delta > 0)
+ zoomIn(delta / 120);
+ else if (delta < 0)
+ zoomOut(-delta / 120);
+ e->accept();
+ return;
+ }
+ QWebView::wheelEvent(e);
+}
+
+void HelpViewer::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() == Qt::XButton1) {
+ triggerPageAction(QWebPage::Back);
+ return;
+ }
+
+ if (e->button() == Qt::XButton2) {
+ triggerPageAction(QWebPage::Forward);
+ return;
+ }
+
+ QWebView::mouseReleaseEvent(e);
+}
+
+void HelpViewer::actionChanged()
+{
+ QAction *a = qobject_cast<QAction *>(sender());
+ if (a == pageAction(QWebPage::Copy))
+ emit copyAvailable(a->isEnabled());
+ else if (a == pageAction(QWebPage::Back))
+ emit backwardAvailable(a->isEnabled());
+ else if (a == pageAction(QWebPage::Forward))
+ emit forwardAvailable(a->isEnabled());
+}
+
+#else // !defined(QT_NO_WEBKIT)
+
+HelpViewer::HelpViewer(QHelpEngine *engine, CentralWidget *parent)
+ : QTextBrowser(parent)
+ , zoomCount(0)
+ , controlPressed(false)
+ , lastAnchor(QString())
+ , helpEngine(engine)
+ , parentWidget(parent)
+{
+ document()->setDocumentMargin(8);
+}
+
+void HelpViewer::setSource(const QUrl &url)
+{
+ bool help = url.toString() == QLatin1String("help");
+ if (url.isValid() && !help) {
+ if (launchedWithExternalApp(url))
+ return;
+
+ QUrl u = helpEngine->findFile(url);
+ if (u.isValid()) {
+ QTextBrowser::setSource(u);
+ return;
+ }
+ }
+
+ if (help) {
+ QTextBrowser::setSource(QUrl(QLatin1String("qthelp://com.trolltech.com."
+ "assistantinternal_1.0.0/assistant/assistant.html")));
+ } else {
+ QTextBrowser::setSource(url);
+ setHtml(tr("<title>Error 404...</title><div align=\"center\"><br><br>"
+ "<h1>The page could not be found</h1><br><h3>'%1'</h3></div>")
+ .arg(url.toString()));
+ emit sourceChanged(url);
+ }
+}
+
+void HelpViewer::resetZoom()
+{
+ if (zoomCount == 0)
+ return;
+
+ QTextBrowser::zoomOut(zoomCount);
+ zoomCount = 0;
+}
+
+void HelpViewer::zoomIn(int range)
+{
+ if (zoomCount == 10)
+ return;
+
+ QTextBrowser::zoomIn(range);
+ zoomCount++;
+}
+
+void HelpViewer::zoomOut(int range)
+{
+ if (zoomCount == -5)
+ return;
+
+ QTextBrowser::zoomOut(range);
+ zoomCount--;
+}
+
+bool HelpViewer::launchedWithExternalApp(const QUrl &url)
+{
+ bool isPdf = url.path().endsWith(QLatin1String("pdf"));
+ if (url.scheme() == QLatin1String("http")
+ || url.scheme() == QLatin1String("ftp")
+ || url.scheme() == QLatin1String("mailto") || isPdf) {
+ bool launched = false;
+ if (isPdf && url.scheme() == QLatin1String("qthelp")) {
+ QString fileName = url.toString();
+ fileName = QDir::tempPath() + QDir::separator() + fileName.right
+ (fileName.length() - fileName.lastIndexOf(QLatin1Char('/')));
+
+ QFile tmpFile(QDir::cleanPath(fileName));
+ if (tmpFile.open(QIODevice::ReadWrite)) {
+ tmpFile.write(helpEngine->fileData(url));
+ tmpFile.close();
+ }
+ launched = QDesktopServices::openUrl(QUrl(tmpFile.fileName()));
+ } else {
+ launched = QDesktopServices::openUrl(url);
+ }
+
+ if (!launched) {
+ QMessageBox::information(this, tr("Help"),
+ tr("Unable to launch external application.\n"), tr("OK"));
+ }
+ return true;
+ }
+ return false;
+}
+
+QVariant HelpViewer::loadResource(int type, const QUrl &name)
+{
+ QByteArray ba;
+ if (type < 4) {
+ ba = helpEngine->fileData(name);
+ if (name.toString().endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)) {
+ QImage image;
+ image.loadFromData(ba, "svg");
+ if (!image.isNull())
+ return image;
+ }
+ }
+ return ba;
+}
+
+void HelpViewer::openLinkInNewTab()
+{
+ if(lastAnchor.isEmpty())
+ return;
+
+ parentWidget->setSourceInNewTab(QUrl(lastAnchor));
+ lastAnchor.clear();
+}
+
+void HelpViewer::openLinkInNewTab(const QString &link)
+{
+ lastAnchor = link;
+ openLinkInNewTab();
+}
+
+bool HelpViewer::hasAnchorAt(const QPoint& pos)
+{
+ lastAnchor = anchorAt(pos);
+ if (lastAnchor.isEmpty())
+ return false;
+
+ lastAnchor = source().resolved(lastAnchor).toString();
+ if (lastAnchor.at(0) == QLatin1Char('#')) {
+ QString src = source().toString();
+ int hsh = src.indexOf(QLatin1Char('#'));
+ lastAnchor = (hsh>=0 ? src.left(hsh) : src) + lastAnchor;
+ }
+
+ return true;
+}
+
+void HelpViewer::contextMenuEvent(QContextMenuEvent *e)
+{
+ QMenu menu(QLatin1String(""), 0);
+
+ QUrl link;
+ QAction *copyAnchorAction = 0;
+ if (hasAnchorAt(e->pos())) {
+ link = anchorAt(e->pos());
+ if (link.isRelative())
+ link = source().resolved(link);
+ copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
+ copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid());
+
+ menu.addAction(tr("Open Link in New Tab\tCtrl+LMB"), this,
+ SLOT(openLinkInNewTab()));
+ menu.addSeparator();
+ }
+ menu.addActions(parentWidget->globalActions());
+ QAction *action = menu.exec(e->globalPos());
+ if (action == copyAnchorAction)
+ QApplication::clipboard()->setText(link.toString());
+}
+
+void HelpViewer::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() == Qt::XButton1) {
+ QTextBrowser::backward();
+ return;
+ }
+
+ if (e->button() == Qt::XButton2) {
+ QTextBrowser::forward();
+ return;
+ }
+
+ controlPressed = e->modifiers() & Qt::ControlModifier;
+ if ((controlPressed && hasAnchorAt(e->pos())) ||
+ (e->button() == Qt::MidButton && hasAnchorAt(e->pos()))) {
+ openLinkInNewTab();
+ return;
+ }
+
+ QTextBrowser::mouseReleaseEvent(e);
+}
+
+void HelpViewer::keyPressEvent(QKeyEvent *e)
+{
+ if ((e->key() == Qt::Key_Home && e->modifiers() != Qt::NoModifier)
+ || (e->key() == Qt::Key_End && e->modifiers() != Qt::NoModifier)) {
+ QKeyEvent* event = new QKeyEvent(e->type(), e->key(), Qt::NoModifier,
+ e->text(), e->isAutoRepeat(), e->count());
+ e = event;
+ }
+ QTextBrowser::keyPressEvent(e);
+}
+
+void HelpViewer::home()
+{
+ QString homepage = helpEngine->customValue(QLatin1String("homepage"),
+ QLatin1String("")).toString();
+
+ if (homepage.isEmpty()) {
+ homepage = helpEngine->customValue(QLatin1String("defaultHomepage"),
+ QLatin1String("help")).toString();
+ }
+
+ setSource(homepage);
+}
+
+void HelpViewer::wheelEvent(QWheelEvent *e)
+{
+ if (e->modifiers() == Qt::CTRL) {
+ e->accept();
+ (e->delta() > 0) ? zoomIn() : zoomOut();
+ } else {
+ e->ignore();
+ QTextBrowser::wheelEvent(e);
+ }
+}
+
+#endif // !defined(QT_NO_WEBKIT)
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/helpviewer.h b/tools/assistant/tools/assistant/helpviewer.h
new file mode 100644
index 0000000000..af5c1976cf
--- /dev/null
+++ b/tools/assistant/tools/assistant/helpviewer.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HELPVIEWER_H
+#define HELPVIEWER_H
+
+#include <QtCore/QUrl>
+#include <QtCore/QVariant>
+#include <QtGui/QTextBrowser>
+#include <QtGui/QAction>
+
+#if !defined(QT_NO_WEBKIT)
+#include <QWebView>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QHelpEngine;
+class CentralWidget;
+
+class QPoint;
+class QString;
+class QKeyEvent;
+class QMouseEvent;
+class QContextMenuEvent;
+
+#if !defined(QT_NO_WEBKIT)
+
+class HelpViewer : public QWebView
+{
+ Q_OBJECT
+
+public:
+ HelpViewer(QHelpEngine *helpEngine, CentralWidget *parent);
+ void setSource(const QUrl &url);
+
+ inline QUrl source() const
+ { return url(); }
+
+ inline QString documentTitle() const
+ { return title(); }
+
+ inline bool hasSelection() const
+ { return !selectedText().isEmpty(); } // ### this is suboptimal
+
+ void resetZoom();
+ void zoomIn(qreal range = 1);
+ void zoomOut(qreal range = 1);
+
+ inline void copy()
+ { return triggerPageAction(QWebPage::Copy); }
+
+ inline bool isForwardAvailable() const
+ { return pageAction(QWebPage::Forward)->isEnabled(); }
+ inline bool isBackwardAvailable() const
+ { return pageAction(QWebPage::Back)->isEnabled(); }
+
+public Q_SLOTS:
+ void home();
+ void backward() { back(); }
+
+Q_SIGNALS:
+ void copyAvailable(bool enabled);
+ void forwardAvailable(bool enabled);
+ void backwardAvailable(bool enabled);
+ void highlighted(const QString &);
+ void sourceChanged(const QUrl &);
+
+protected:
+ virtual void wheelEvent(QWheelEvent *);
+ void mouseReleaseEvent(QMouseEvent *e);
+
+private Q_SLOTS:
+ void actionChanged();
+
+private:
+ QHelpEngine *helpEngine;
+ CentralWidget* parentWidget;
+};
+
+#else
+
+class HelpViewer : public QTextBrowser
+{
+ Q_OBJECT
+
+public:
+ HelpViewer(QHelpEngine *helpEngine, CentralWidget *parent);
+ void setSource(const QUrl &url);
+
+ void resetZoom();
+ void zoomIn(int range = 1);
+ void zoomOut(int range = 1);
+ int zoom() const { return zoomCount; }
+ void setZoom(int zoom) { zoomCount = zoom; }
+
+ inline bool hasSelection() const
+ { return textCursor().hasSelection(); }
+
+ bool launchedWithExternalApp(const QUrl &url);
+
+public Q_SLOTS:
+ void home();
+
+protected:
+ void wheelEvent(QWheelEvent *e);
+
+private:
+ QVariant loadResource(int type, const QUrl &name);
+ void openLinkInNewTab(const QString &link);
+ bool hasAnchorAt(const QPoint& pos);
+ void contextMenuEvent(QContextMenuEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+
+private slots:
+ void openLinkInNewTab();
+
+private:
+ int zoomCount;
+ bool controlPressed;
+ QString lastAnchor;
+ QHelpEngine *helpEngine;
+ CentralWidget* parentWidget;
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/assistant/images/assistant-128.png b/tools/assistant/tools/assistant/images/assistant-128.png
new file mode 100644
index 0000000000..f05949f6d8
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/assistant-128.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/assistant.png b/tools/assistant/tools/assistant/images/assistant.png
new file mode 100644
index 0000000000..ea4d1e70c1
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/assistant.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/addtab.png b/tools/assistant/tools/assistant/images/mac/addtab.png
new file mode 100644
index 0000000000..20928fb402
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/addtab.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/book.png b/tools/assistant/tools/assistant/images/mac/book.png
new file mode 100644
index 0000000000..7a3204c870
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/book.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/closetab.png b/tools/assistant/tools/assistant/images/mac/closetab.png
new file mode 100644
index 0000000000..ab9d669eee
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/closetab.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/editcopy.png b/tools/assistant/tools/assistant/images/mac/editcopy.png
new file mode 100644
index 0000000000..f551364464
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/editcopy.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/find.png b/tools/assistant/tools/assistant/images/mac/find.png
new file mode 100644
index 0000000000..3561745f01
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/find.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/home.png b/tools/assistant/tools/assistant/images/mac/home.png
new file mode 100644
index 0000000000..78d94da18d
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/home.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/next.png b/tools/assistant/tools/assistant/images/mac/next.png
new file mode 100644
index 0000000000..a585cab80c
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/next.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/previous.png b/tools/assistant/tools/assistant/images/mac/previous.png
new file mode 100644
index 0000000000..612fb34dce
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/previous.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/print.png b/tools/assistant/tools/assistant/images/mac/print.png
new file mode 100644
index 0000000000..10ca56c82a
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/print.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/resetzoom.png b/tools/assistant/tools/assistant/images/mac/resetzoom.png
new file mode 100644
index 0000000000..759b382968
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/resetzoom.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/synctoc.png b/tools/assistant/tools/assistant/images/mac/synctoc.png
new file mode 100644
index 0000000000..067fa941b5
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/synctoc.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/zoomin.png b/tools/assistant/tools/assistant/images/mac/zoomin.png
new file mode 100644
index 0000000000..d46f5aff0d
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/zoomin.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/mac/zoomout.png b/tools/assistant/tools/assistant/images/mac/zoomout.png
new file mode 100644
index 0000000000..46326566d1
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/mac/zoomout.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/trolltech-logo.png b/tools/assistant/tools/assistant/images/trolltech-logo.png
new file mode 100644
index 0000000000..c53e744cab
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/trolltech-logo.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/addtab.png b/tools/assistant/tools/assistant/images/win/addtab.png
new file mode 100644
index 0000000000..4bb0feb92d
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/addtab.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/book.png b/tools/assistant/tools/assistant/images/win/book.png
new file mode 100644
index 0000000000..09ec4d33f7
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/book.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/closetab.png b/tools/assistant/tools/assistant/images/win/closetab.png
new file mode 100644
index 0000000000..ef9e02086c
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/closetab.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/editcopy.png b/tools/assistant/tools/assistant/images/win/editcopy.png
new file mode 100644
index 0000000000..1121b47d8b
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/editcopy.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/find.png b/tools/assistant/tools/assistant/images/win/find.png
new file mode 100644
index 0000000000..6ea35e930d
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/find.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/home.png b/tools/assistant/tools/assistant/images/win/home.png
new file mode 100644
index 0000000000..b1c6ae1913
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/home.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/next.png b/tools/assistant/tools/assistant/images/win/next.png
new file mode 100644
index 0000000000..8df4127a00
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/next.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/previous.png b/tools/assistant/tools/assistant/images/win/previous.png
new file mode 100644
index 0000000000..0780bc23dd
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/previous.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/print.png b/tools/assistant/tools/assistant/images/win/print.png
new file mode 100644
index 0000000000..ba7c02dc18
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/print.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/resetzoom.png b/tools/assistant/tools/assistant/images/win/resetzoom.png
new file mode 100644
index 0000000000..b69ae4e7fe
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/resetzoom.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/synctoc.png b/tools/assistant/tools/assistant/images/win/synctoc.png
new file mode 100644
index 0000000000..da301bc599
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/synctoc.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/zoomin.png b/tools/assistant/tools/assistant/images/win/zoomin.png
new file mode 100644
index 0000000000..2e586fc7bf
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/zoomin.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/win/zoomout.png b/tools/assistant/tools/assistant/images/win/zoomout.png
new file mode 100644
index 0000000000..a736d39343
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/win/zoomout.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/images/wrap.png b/tools/assistant/tools/assistant/images/wrap.png
new file mode 100644
index 0000000000..90f18d9f77
--- /dev/null
+++ b/tools/assistant/tools/assistant/images/wrap.png
Binary files differ
diff --git a/tools/assistant/tools/assistant/indexwindow.cpp b/tools/assistant/tools/assistant/indexwindow.cpp
new file mode 100644
index 0000000000..e7575fa140
--- /dev/null
+++ b/tools/assistant/tools/assistant/indexwindow.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "indexwindow.h"
+#include "centralwidget.h"
+#include "topicchooser.h"
+
+#include <QtGui/QLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QListWidgetItem>
+
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpIndexWidget>
+
+QT_BEGIN_NAMESPACE
+
+IndexWindow::IndexWindow(QHelpEngine *helpEngine, QWidget *parent)
+ : QWidget(parent)
+ , m_searchLineEdit(0)
+ , m_indexWidget(0)
+ , m_helpEngine(helpEngine)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ QLabel *l = new QLabel(tr("&Look for:"));
+ layout->addWidget(l);
+
+ m_searchLineEdit = new QLineEdit();
+ l->setBuddy(m_searchLineEdit);
+ connect(m_searchLineEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(filterIndices(QString)));
+ m_searchLineEdit->installEventFilter(this);
+ layout->setMargin(4);
+ layout->addWidget(m_searchLineEdit);
+
+ m_indexWidget = m_helpEngine->indexWidget();
+ m_indexWidget->installEventFilter(this);
+ connect(m_helpEngine->indexModel(), SIGNAL(indexCreationStarted()), this,
+ SLOT(disableSearchLineEdit()));
+ connect(m_helpEngine->indexModel(), SIGNAL(indexCreated()), this,
+ SLOT(enableSearchLineEdit()));
+ connect(m_indexWidget, SIGNAL(linkActivated(QUrl, QString)), this,
+ SIGNAL(linkActivated(QUrl)));
+ connect(m_indexWidget, SIGNAL(linksActivated(QMap<QString, QUrl>, QString)),
+ this, SIGNAL(linksActivated(QMap<QString, QUrl>, QString)));
+ connect(m_searchLineEdit, SIGNAL(returnPressed()), m_indexWidget,
+ SLOT(activateCurrentItem()));
+ layout->addWidget(m_indexWidget);
+
+ m_indexWidget->viewport()->installEventFilter(this);
+}
+
+IndexWindow::~IndexWindow()
+{
+}
+
+void IndexWindow::filterIndices(const QString &filter)
+{
+ if (filter.contains(QLatin1Char('*')))
+ m_indexWidget->filterIndices(filter, filter);
+ else
+ m_indexWidget->filterIndices(filter, QString());
+}
+
+bool IndexWindow::eventFilter(QObject *obj, QEvent *e)
+{
+ if (obj == m_searchLineEdit && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ QModelIndex idx = m_indexWidget->currentIndex();
+ switch (ke->key()) {
+ case Qt::Key_Up:
+ idx = m_indexWidget->model()->index(idx.row()-1,
+ idx.column(), idx.parent());
+ if (idx.isValid())
+ m_indexWidget->setCurrentIndex(idx);
+ break;
+ case Qt::Key_Down:
+ idx = m_indexWidget->model()->index(idx.row()+1,
+ idx.column(), idx.parent());
+ if (idx.isValid())
+ m_indexWidget->setCurrentIndex(idx);
+ break;
+ case Qt::Key_Escape:
+ emit escapePressed();
+ break;
+ default:
+ ;
+ }
+ } else if (obj == m_indexWidget && e->type() == QEvent::ContextMenu) {
+ QContextMenuEvent *ctxtEvent = static_cast<QContextMenuEvent*>(e);
+ QModelIndex idx = m_indexWidget->indexAt(ctxtEvent->pos());
+ if (idx.isValid()) {
+ QMenu menu;
+ QAction *curTab = menu.addAction(tr("Open Link"));
+ QAction *newTab = menu.addAction(tr("Open Link in New Tab"));
+ menu.move(m_indexWidget->mapToGlobal(ctxtEvent->pos()));
+
+ QAction *action = menu.exec();
+ if (curTab == action)
+ m_indexWidget->activateCurrentItem();
+ else if (newTab == action) {
+ QHelpIndexModel *model =
+ qobject_cast<QHelpIndexModel*>(m_indexWidget->model());
+ QString keyword = model->data(idx, Qt::DisplayRole).toString();
+ if (model) {
+ QMap<QString, QUrl> links = model->linksForKeyword(keyword);
+ if (links.count() == 1) {
+ CentralWidget::instance()->
+ setSourceInNewTab(links.constBegin().value());
+ } else {
+ TopicChooser tc(this, keyword, links);
+ if (tc.exec() == QDialog::Accepted) {
+ CentralWidget::instance()->setSourceInNewTab(tc.link());
+ }
+ }
+ }
+ }
+ }
+ } else if (m_indexWidget && obj == m_indexWidget->viewport()
+ && e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
+ QModelIndex idx = m_indexWidget->indexAt(mouseEvent->pos());
+ if (idx.isValid() && mouseEvent->button()==Qt::MidButton) {
+ QHelpIndexModel *model =
+ qobject_cast<QHelpIndexModel*>(m_indexWidget->model());
+ QString keyword = model->data(idx, Qt::DisplayRole).toString();
+ if (model) {
+ QMap<QString, QUrl> links = model->linksForKeyword(keyword);
+ if (links.count() > 1) {
+ TopicChooser tc(this, keyword, links);
+ if (tc.exec() == QDialog::Accepted) {
+ CentralWidget::instance()->setSourceInNewTab(tc.link());
+ }
+ } else if (links.count() == 1) {
+ CentralWidget::instance()->
+ setSourceInNewTab(links.constBegin().value());
+ }
+ }
+ }
+ }
+#ifdef Q_OS_MAC
+ else if (obj == m_indexWidget && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)
+ m_indexWidget->activateCurrentItem();
+ }
+#endif
+ return QWidget::eventFilter(obj, e);
+}
+
+void IndexWindow::enableSearchLineEdit()
+{
+ m_searchLineEdit->setDisabled(false);
+ filterIndices(m_searchLineEdit->text());
+}
+
+void IndexWindow::disableSearchLineEdit()
+{
+ m_searchLineEdit->setDisabled(true);
+}
+
+void IndexWindow::setSearchLineEditText(const QString &text)
+{
+ m_searchLineEdit->setText(text);
+}
+
+void IndexWindow::focusInEvent(QFocusEvent *e)
+{
+ if (e->reason() != Qt::MouseFocusReason) {
+ m_searchLineEdit->selectAll();
+ m_searchLineEdit->setFocus();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/indexwindow.h b/tools/assistant/tools/assistant/indexwindow.h
new file mode 100644
index 0000000000..f1f57f9442
--- /dev/null
+++ b/tools/assistant/tools/assistant/indexwindow.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INDEXWINDOW_H
+#define INDEXWINDOW_H
+
+#include <QtCore/QUrl>
+#include <QtGui/QWidget>
+#include <QtGui/QLineEdit>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpIndexWidget;
+class QHelpEngine;
+
+class IndexWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ IndexWindow(QHelpEngine *helpEngine, QWidget *parent = 0);
+ ~IndexWindow();
+
+ void setSearchLineEditText(const QString &text);
+ QString searchLineEditText() const
+ {
+ return m_searchLineEdit->text();
+ }
+
+signals:
+ void linkActivated(const QUrl &link);
+ void linksActivated(const QMap<QString, QUrl> &links,
+ const QString &keyword);
+ void escapePressed();
+
+private slots:
+ void filterIndices(const QString &filter);
+ void enableSearchLineEdit();
+ void disableSearchLineEdit();
+
+private:
+ bool eventFilter(QObject *obj, QEvent *e);
+ void focusInEvent(QFocusEvent *e);
+
+ QLineEdit *m_searchLineEdit;
+ QHelpIndexWidget *m_indexWidget;
+ QHelpEngine *m_helpEngine;
+};
+
+QT_END_NAMESPACE
+
+#endif // INDEXWINDOW_H
diff --git a/tools/assistant/tools/assistant/installdialog.cpp b/tools/assistant/tools/assistant/installdialog.cpp
new file mode 100644
index 0000000000..1f02ac1b1c
--- /dev/null
+++ b/tools/assistant/tools/assistant/installdialog.cpp
@@ -0,0 +1,338 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "installdialog.h"
+
+#include <QtCore/QTimer>
+#include <QtCore/QUrl>
+#include <QtCore/QBuffer>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QCryptographicHash>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QFileDialog>
+
+#include <QtHelp/QHelpEngineCore>
+
+#include <QtNetwork/QHttp>
+
+QT_BEGIN_NAMESPACE
+
+#define QCH_FILENAME 92943
+#define QCH_NAMESPACE 92944
+#define QCH_CHECKSUM 92945
+
+InstallDialog::InstallDialog(QHelpEngineCore *helpEngine, QWidget *parent,
+ const QString &host, int port)
+ : QDialog(parent), m_helpEngine(helpEngine), m_host(host), m_port(port)
+{
+ m_ui.setupUi(this);
+
+ m_ui.installButton->setEnabled(false);
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.pathLineEdit->setText(QFileInfo(m_helpEngine->collectionFile()).absolutePath());
+ m_ui.progressBar->hide();
+
+ m_windowTitle = tr("Install Documentation");
+
+ m_http = new QHttp(this);
+ connect(m_http, SIGNAL(requestFinished(int, bool)),
+ this, SLOT(httpRequestFinished(int, bool)));
+ connect(m_http, SIGNAL(dataReadProgress(int, int)),
+ this, SLOT(updateDataReadProgress(int, int)));
+ connect(m_http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
+ this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
+ connect(m_ui.installButton, SIGNAL(clicked()), this, SLOT(install()));
+ connect(m_ui.cancelButton, SIGNAL(clicked()), this, SLOT(cancelDownload()));
+ connect(m_ui.browseButton, SIGNAL(clicked()), this, SLOT(browseDirectories()));
+
+ connect(m_ui.listWidget, SIGNAL(itemChanged(QListWidgetItem*)),
+ this, SLOT(updateInstallButton()));
+
+ QTimer::singleShot(0, this, SLOT(init()));
+}
+
+InstallDialog::~InstallDialog()
+{
+}
+
+QStringList InstallDialog::installedDocumentations() const
+{
+ return m_installedDocumentations;
+}
+
+void InstallDialog::init()
+{
+ m_ui.statusLabel->setText(tr("Downloading documentation info..."));
+ m_ui.progressBar->show();
+
+ QUrl url(QLatin1String("http://doc.trolltech.com/assistantdocs/docs.txt"));
+ m_buffer = new QBuffer();
+ m_buffer->open(QBuffer::ReadWrite);
+
+ if (m_port > -1)
+ m_http->setProxy(m_host, m_port);
+ m_http->setHost(url.host());
+ m_httpAborted = false;
+ m_docInfoId = m_http->get(url.path(), m_buffer);
+
+ m_ui.cancelButton->setEnabled(true);
+ m_ui.closeButton->setEnabled(false);
+}
+
+void InstallDialog::updateInstallButton()
+{
+ QListWidgetItem *item = 0;
+ for (int i=0; i<m_ui.listWidget->count(); ++i) {
+ item = m_ui.listWidget->item(i);
+ if (item->checkState() == Qt::Checked
+ && item->flags() & Qt::ItemIsEnabled) {
+ m_ui.installButton->setEnabled(true);
+ return;
+ }
+ }
+ m_ui.installButton->setEnabled(false);
+}
+
+void InstallDialog::updateDocItemList()
+{
+ QStringList registeredDocs = m_helpEngine->registeredDocumentations();
+ QListWidgetItem *item = 0;
+ for (int i=0; i<m_ui.listWidget->count(); ++i) {
+ item = m_ui.listWidget->item(i);
+ QString ns = item->data(QCH_NAMESPACE).toString();
+ if (!ns.isEmpty() && registeredDocs.contains(ns)) {
+ item->setFlags(Qt::ItemIsUserCheckable);
+ item->setCheckState(Qt::Checked);
+ }
+ item->setCheckState(Qt::Unchecked);
+ }
+}
+
+void InstallDialog::cancelDownload()
+{
+ m_ui.statusLabel->setText(tr("Download canceled."));
+ m_httpAborted = true;
+ m_itemsToInstall.clear();
+ m_http->abort();
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.closeButton->setEnabled(true);
+ updateInstallButton();
+}
+
+void InstallDialog::install()
+{
+ QListWidgetItem *item = 0;
+ for (int i=0; i<m_ui.listWidget->count(); ++i) {
+ item = m_ui.listWidget->item(i);
+ if (item->checkState() == Qt::Checked)
+ m_itemsToInstall.append(item);
+ }
+ m_ui.installButton->setEnabled(false);
+ downloadNextFile();
+}
+
+void InstallDialog::downloadNextFile()
+{
+ if (!m_itemsToInstall.count()) {
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.closeButton->setEnabled(true);
+ m_ui.statusLabel->setText(tr("Done."));
+ m_ui.progressBar->hide();
+ updateDocItemList();
+ updateInstallButton();
+ return;
+ }
+
+ QListWidgetItem *item = m_itemsToInstall.dequeue();
+ m_currentCheckSum = item->data(QCH_CHECKSUM).toString();
+ QString fileName = item->data(QCH_FILENAME).toString();
+ QString saveFileName = m_ui.pathLineEdit->text() + QDir::separator()
+ + fileName;
+
+ if (QFile::exists(saveFileName)
+ && QMessageBox::information(this, m_windowTitle,
+ tr("The file %1 already exists. Do you want to overwrite it?")
+ .arg(saveFileName), QMessageBox::Yes | QMessageBox::No,
+ QMessageBox::Yes) == QMessageBox::No) {
+ installFile(saveFileName);
+ downloadNextFile();
+ return;
+ }
+
+ m_file = new QFile(saveFileName);
+ if (!m_file->open(QIODevice::WriteOnly|QIODevice::Truncate)) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Unable to save the file %1: %2.")
+ .arg(saveFileName).arg(m_file->errorString()));
+ delete m_file;
+ m_file = 0;
+ downloadNextFile();
+ return;
+ }
+
+ m_ui.statusLabel->setText(tr("Downloading %1...").arg(fileName));
+ m_ui.progressBar->show();
+
+ QLatin1String urlStr("http://doc.trolltech.com/assistantdocs/%1");
+ QUrl url(QString(urlStr).arg(fileName));
+
+ m_httpAborted = false;
+ m_docId = m_http->get(url.path(), m_file);
+
+ m_ui.cancelButton->setEnabled(true);
+ m_ui.closeButton->setEnabled(false);
+}
+
+void InstallDialog::httpRequestFinished(int requestId, bool error)
+{
+ if (requestId == m_docInfoId && m_buffer) {
+ m_ui.progressBar->hide();
+ if (error) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Download failed: %1.")
+ .arg(m_http->errorString()));
+ } else if (!m_httpAborted) {
+ QStringList registeredDocs = m_helpEngine->registeredDocumentations();
+ m_buffer->seek(0);
+ while (m_buffer->canReadLine()) {
+ QByteArray ba = m_buffer->readLine();
+ QStringList lst = QString::fromAscii(ba.constData()).split(QLatin1Char('|'));
+ if (lst.count() != 4) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Documentation info file is corrupt!"));
+ } else {
+ QListWidgetItem *item = new QListWidgetItem(m_ui.listWidget);
+ item->setText(lst.at(2).trimmed());
+ item->setData(QCH_FILENAME, lst.first());
+ item->setData(QCH_NAMESPACE, lst.at(1));
+ item->setData(QCH_CHECKSUM, lst.last().trimmed());
+ }
+ }
+ updateDocItemList();
+ }
+ if (m_buffer)
+ m_buffer->close();
+ delete m_buffer;
+ m_buffer = 0;
+ m_ui.statusLabel->setText(tr("Done."));
+ m_ui.cancelButton->setEnabled(false);
+ m_ui.closeButton->setEnabled(true);
+ updateInstallButton();
+ } else if (requestId == m_docId) {
+ m_file->close();
+ if (!m_httpAborted) {
+ QString checkSum;
+ if (m_file->open(QIODevice::ReadOnly)) {
+ QByteArray digest = QCryptographicHash::hash(m_file->readAll(),
+ QCryptographicHash::Md5);
+ m_file->close();
+ checkSum = QString::fromLatin1(digest.toHex());
+ }
+ if (error) {
+ m_file->remove();
+ QMessageBox::warning(this, m_windowTitle,
+ tr("Download failed: %1.")
+ .arg(m_http->errorString()));
+ } else if (checkSum.isEmpty() || m_currentCheckSum != checkSum) {
+ m_file->remove();
+ QMessageBox::warning(this, m_windowTitle,
+ tr("Download failed: Downloaded file is corrupted."));
+ } else {
+ m_ui.statusLabel->setText(tr("Installing documentation %1...")
+ .arg(QFileInfo(m_file->fileName()).fileName()));
+ m_ui.progressBar->setMaximum(0);
+ m_ui.statusLabel->setText(tr("Done."));
+ installFile(m_file->fileName());
+ }
+ } else {
+ m_file->remove();
+ }
+ delete m_file;
+ m_file = 0;
+ downloadNextFile();
+ }
+}
+
+void InstallDialog::installFile(const QString &fileName)
+{
+ if (m_helpEngine->registerDocumentation(fileName)) {
+ m_installedDocumentations
+ .append(QHelpEngineCore::namespaceName(fileName));
+ } else {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Error while installing documentation:\n%1")
+ .arg(m_helpEngine->error()));
+ }
+}
+
+void InstallDialog::readResponseHeader(const QHttpResponseHeader &responseHeader)
+{
+ if (responseHeader.statusCode() != 200) {
+ QMessageBox::information(this, m_windowTitle,
+ tr("Download failed: %1.")
+ .arg(responseHeader.reasonPhrase()));
+ m_httpAborted = true;
+ m_ui.progressBar->hide();
+ m_http->abort();
+ return;
+ }
+}
+
+void InstallDialog::updateDataReadProgress(int bytesRead, int totalBytes)
+{
+ if (m_httpAborted)
+ return;
+
+ m_ui.progressBar->setMaximum(totalBytes);
+ m_ui.progressBar->setValue(bytesRead);
+}
+
+void InstallDialog::browseDirectories()
+{
+ QString dir = QFileDialog::getExistingDirectory(this, m_windowTitle,
+ m_ui.pathLineEdit->text());
+ if (!dir.isEmpty())
+ m_ui.pathLineEdit->setText(dir);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/installdialog.h b/tools/assistant/tools/assistant/installdialog.h
new file mode 100644
index 0000000000..88c882ca7c
--- /dev/null
+++ b/tools/assistant/tools/assistant/installdialog.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INSTALLDIALOG_H
+#define INSTALLDIALOG_H
+
+#include <QtCore/QQueue>
+#include <QtGui/QDialog>
+#include <QtNetwork/QHttpResponseHeader>
+#include "ui_installdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class QHttp;
+class QBuffer;
+class QFile;
+class QHelpEngineCore;
+
+class InstallDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ InstallDialog(QHelpEngineCore *helpEngine, QWidget *parent = 0,
+ const QString &host = QString(), int port = -1);
+ ~InstallDialog();
+
+ QStringList installedDocumentations() const;
+
+private slots:
+ void init();
+ void cancelDownload();
+ void install();
+ void httpRequestFinished(int requestId, bool error);
+ void readResponseHeader(const QHttpResponseHeader &responseHeader);
+ void updateDataReadProgress(int bytesRead, int totalBytes);
+ void updateInstallButton();
+ void browseDirectories();
+
+private:
+ void downloadNextFile();
+ void updateDocItemList();
+ void installFile(const QString &fileName);
+
+ Ui::InstallDialog m_ui;
+ QHelpEngineCore *m_helpEngine;
+ QHttp *m_http;
+ QBuffer *m_buffer;
+ QFile *m_file;
+ bool m_httpAborted;
+ int m_docInfoId;
+ int m_docId;
+ QQueue<QListWidgetItem*> m_itemsToInstall;
+ QString m_currentCheckSum;
+ QString m_windowTitle;
+ QStringList m_installedDocumentations;
+ QString m_host;
+ int m_port;
+};
+
+QT_END_NAMESPACE
+
+#endif // INSTALLDIALOG_H
diff --git a/tools/assistant/tools/assistant/installdialog.ui b/tools/assistant/tools/assistant/installdialog.ui
new file mode 100644
index 0000000000..21a05da77e
--- /dev/null
+++ b/tools/assistant/tools/assistant/installdialog.ui
@@ -0,0 +1,118 @@
+<ui version="4.0" >
+ <class>InstallDialog</class>
+ <widget class="QDialog" name="InstallDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>436</width>
+ <height>245</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Install Documentation</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="4" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Available Documentation:</string>
+ </property>
+ </widget>
+ </item>
+ <item rowspan="4" row="1" column="0" colspan="4" >
+ <widget class="QListWidget" name="listWidget" />
+ </item>
+ <item row="1" column="4" >
+ <widget class="QPushButton" name="installButton" >
+ <property name="text" >
+ <string>Install</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="4" >
+ <widget class="QPushButton" name="cancelButton" >
+ <property name="text" >
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4" >
+ <widget class="QPushButton" name="closeButton" >
+ <property name="text" >
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="4" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>56</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_4" >
+ <property name="text" >
+ <string>Installation Path:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2" >
+ <widget class="QLineEdit" name="pathLineEdit" />
+ </item>
+ <item row="5" column="3" >
+ <widget class="QToolButton" name="browseButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0" colspan="5" >
+ <widget class="Line" name="line" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0" colspan="2" >
+ <widget class="QLabel" name="statusLabel" />
+ </item>
+ <item row="7" column="2" colspan="3" >
+ <widget class="QProgressBar" name="progressBar" >
+ <property name="value" >
+ <number>0</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>closeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>InstallDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>330</x>
+ <y>107</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>332</x>
+ <y>158</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp
new file mode 100644
index 0000000000..794be02a69
--- /dev/null
+++ b/tools/assistant/tools/assistant/main.cpp
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QLocale>
+#include <QtCore/QTranslator>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QUrl>
+#include <QtCore/QStringList>
+
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopServices>
+
+#include <QtHelp/QHelpEngineCore>
+
+#include <QtSql/QSqlDatabase>
+
+#include "mainwindow.h"
+#include "cmdlineparser.h"
+
+QT_USE_NAMESPACE
+
+#if defined(USE_STATIC_SQLITE_PLUGIN)
+ #include <QtPlugin>
+ Q_IMPORT_PLUGIN(qsqlite)
+#endif
+
+void
+updateLastPagesOnUnregister(QHelpEngineCore& helpEngine, const QString& nsName)
+{
+ int lastPage = helpEngine.customValue(QLatin1String("LastTabPage")).toInt();
+
+ QLatin1String sep("|");
+ QLatin1String pages("LastShownPages");
+#if !defined(QT_NO_WEBKIT)
+ QLatin1String zoom("LastPagesZoomWebView");
+#else
+ QLatin1String zoom("LastPagesZoomTextBrowser");
+#endif
+
+ QStringList currentPages =
+ helpEngine.customValue(pages).toString().
+ split(QLatin1Char('|'), QString::SkipEmptyParts);
+
+ if (!currentPages.isEmpty()) {
+ QVector<QString>zoomList = helpEngine.customValue(zoom).toString().
+ split(sep, QString::SkipEmptyParts).toVector();
+ if (zoomList.isEmpty())
+ zoomList.fill(QLatin1String("0.0"), currentPages.size());
+ else if(zoomList.count() < currentPages.count()) {
+ zoomList.insert(zoomList.count(),
+ currentPages.count() - zoomList.count(), QLatin1String("0.0"));
+ }
+
+ for (int i = currentPages.count(); --i >= 0;) {
+ if (QUrl(currentPages.at(i)).host() == nsName) {
+ zoomList.remove(i);
+ currentPages.removeAt(i);
+ lastPage = (lastPage == (i + 1)) ? 1 : lastPage;
+ }
+ }
+
+ helpEngine.setCustomValue(pages, currentPages.join(sep));
+ helpEngine.setCustomValue(QLatin1String("LastTabPage"), lastPage);
+ helpEngine.setCustomValue(zoom, QStringList(zoomList.toList()).join(sep));
+ }
+}
+
+bool
+updateUserCollection(QHelpEngineCore& user, const QHelpEngineCore& caller)
+{
+ const uint callerCollectionCreationTime = caller.
+ customValue(QLatin1String("CreationTime"), 0).toUInt();
+ const uint userCollectionCreationTime = user.
+ customValue(QLatin1String("CreationTime"), 1).toUInt();
+
+ if (callerCollectionCreationTime == userCollectionCreationTime)
+ return false;
+
+ user.setCustomValue(QLatin1String("CreationTime"),
+ callerCollectionCreationTime);
+ user.setCustomValue(QLatin1String("WindowTitle"),
+ caller.customValue(QLatin1String("WindowTitle")));
+ user.setCustomValue(QLatin1String("LastShownPages"),
+ caller.customValue(QLatin1String("LastShownPages")));
+ user.setCustomValue(QLatin1String("CurrentFilter"),
+ caller.customValue(QLatin1String("CurrentFilter")));
+ user.setCustomValue(QLatin1String("CacheDirectory"),
+ caller.customValue(QLatin1String("CacheDirectory")));
+ user.setCustomValue(QLatin1String("EnableFilterFunctionality"),
+ caller.customValue(QLatin1String("EnableFilterFunctionality")));
+ user.setCustomValue(QLatin1String("HideFilterFunctionality"),
+ caller.customValue(QLatin1String("HideFilterFunctionality")));
+ user.setCustomValue(QLatin1String("EnableDocumentationManager"),
+ caller.customValue(QLatin1String("EnableDocumentationManager")));
+ user.setCustomValue(QLatin1String("EnableAddressBar"),
+ caller.customValue(QLatin1String("EnableAddressBar")));
+ user.setCustomValue(QLatin1String("HideAddressBar"),
+ caller.customValue(QLatin1String("HideAddressBar")));
+ user.setCustomValue(QLatin1String("ApplicationIcon"),
+ caller.customValue(QLatin1String("ApplicationIcon")));
+ user.setCustomValue(QLatin1String("AboutMenuTexts"),
+ caller.customValue(QLatin1String("AboutMenuTexts")));
+ user.setCustomValue(QLatin1String("AboutIcon"),
+ caller.customValue(QLatin1String("AboutIcon")));
+ user.setCustomValue(QLatin1String("AboutTexts"),
+ caller.customValue(QLatin1String("AboutTexts")));
+ user.setCustomValue(QLatin1String("AboutImages"),
+ caller.customValue(QLatin1String("AboutImages")));
+
+ return true;
+}
+
+bool
+referencedHelpFilesExistAll(QHelpEngineCore& user, QStringList& nameSpaces)
+{
+ QFileInfo fi;
+ int counter = nameSpaces.count();
+ for (int i = counter; --i >= 0;) {
+ const QString& nameSpace = nameSpaces.at(i);
+ fi.setFile(user.documentationFileName(nameSpace));
+ if (!fi.exists() || !fi.isFile()) {
+ user.unregisterDocumentation(nameSpace);
+ nameSpaces.removeAll(nameSpace);
+ }
+ }
+ return (counter != nameSpaces.count()) ? false : true;
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ a.addLibraryPath(a.applicationDirPath() + QLatin1String("/plugins"));
+
+ CmdLineParser cmd;
+ CmdLineParser::Result res = cmd.parse(a.arguments());
+ if (res == CmdLineParser::Help)
+ return 0;
+ else if (res == CmdLineParser::Error)
+ return -1;
+
+ QString cmdCollectionFile = cmd.collectionFile();
+ if (cmd.registerRequest() != CmdLineParser::None) {
+ if (cmdCollectionFile.isEmpty())
+ cmdCollectionFile = MainWindow::defaultHelpCollectionFileName();
+ QHelpEngineCore help(cmdCollectionFile);
+ help.setupData();
+ if (cmd.registerRequest() == CmdLineParser::Register) {
+ if (!help.registerDocumentation(cmd.helpFile())) {
+ cmd.showMessage(
+ QObject::tr("Could not register documentation file\n%1\n\nReason:\n%2")
+ .arg(cmd.helpFile()).arg(help.error()), true);
+ return -1;
+ } else {
+ cmd.showMessage(QObject::tr("Documentation successfully registered."),
+ false);
+ }
+ } else {
+ QString nsName = QHelpEngineCore::namespaceName(cmd.helpFile());
+ if (help.unregisterDocumentation(nsName)) {
+ updateLastPagesOnUnregister(help, nsName);
+ cmd.showMessage(
+ QObject::tr("Documentation successfully unregistered."),
+ false);
+ } else {
+ cmd.showMessage(QObject::tr("Could not unregister documentation"
+ " file\n%1\n\nReason:\n%2").arg(cmd.helpFile()).
+ arg(help.error()), true);
+ return -1;
+ }
+ }
+ help.setCustomValue(QLatin1String("DocUpdate"), true);
+ return 0;
+ }
+
+ {
+ QSqlDatabase db;
+ QStringList sqlDrivers(db.drivers());
+ if (sqlDrivers.isEmpty()
+ || !sqlDrivers.contains(QLatin1String("QSQLITE"))) {
+ cmd.showMessage(QObject::tr("Cannot load sqlite database driver!"),
+ true);
+ return -1;
+ }
+ }
+
+ if (!cmdCollectionFile.isEmpty()) {
+ QHelpEngineCore caller(cmdCollectionFile);
+ if (!caller.setupData()) {
+ cmd.showMessage(QObject::tr("The specified collection file could "
+ "not be read!"), true);
+ return -1;
+ }
+
+ QString fileName = QFileInfo(cmdCollectionFile).fileName();
+ QString dir = MainWindow::collectionFileDirectory(false,
+ caller.customValue(QLatin1String("CacheDirectory"),
+ QString()).toString());
+
+ bool collectionFileExists = true;
+ QFileInfo fi(dir + QDir::separator() + fileName);
+ if (!fi.exists()) {
+ collectionFileExists = false;
+ if (!caller.copyCollectionFile(fi.absoluteFilePath())) {
+ cmd.showMessage(caller.error(), true);
+ return -1;
+ }
+ }
+
+ if (collectionFileExists) {
+ QHelpEngineCore user(fi.absoluteFilePath());
+ if (user.setupData()) {
+ // some docs might have been un/registered
+ bool docUpdate = caller.
+ customValue(QLatin1String("DocUpdate"), false).toBool();
+
+ // update in case the passed collection file changed
+ if (updateUserCollection(user, caller))
+ docUpdate = true;
+
+ QStringList userDocs = user.registeredDocumentations();
+ // update user collection file, docs might have been (re)moved
+ if (!referencedHelpFilesExistAll(user, userDocs))
+ docUpdate = true;
+
+ if (docUpdate) {
+ QStringList callerDocs = caller.registeredDocumentations();
+ foreach (const QString &doc, callerDocs) {
+ if (!userDocs.contains(doc)) {
+ user.registerDocumentation(
+ caller.documentationFileName(doc));
+ }
+ }
+
+ QLatin1String intern("com.trolltech.com.assistantinternal_");
+ foreach (const QString &doc, userDocs) {
+ if (!callerDocs.contains(doc) && !doc.startsWith(intern))
+ user.unregisterDocumentation(doc);
+ }
+
+ caller.setCustomValue(QLatin1String("DocUpdate"), false);
+ }
+ }
+ }
+ cmd.setCollectionFile(fi.absoluteFilePath());
+ }
+
+ if (!cmd.currentFilter().isEmpty()) {
+ QString collectionFile;
+ if (cmdCollectionFile.isEmpty()) {
+ MainWindow::collectionFileDirectory(true);
+ cmdCollectionFile = MainWindow::defaultHelpCollectionFileName();
+ }
+
+ QHelpEngineCore user(cmdCollectionFile);
+ if (user.setupData())
+ user.setCurrentFilter(cmd.currentFilter());
+ }
+
+ const QString& locale = QLocale::system().name();
+ QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+
+ QTranslator translator(0);
+ translator.load(QLatin1String("assistant_") + locale, resourceDir);
+ a.installTranslator(&translator);
+
+ QTranslator qtTranslator(0);
+ qtTranslator.load(QLatin1String("qt_") + locale, resourceDir);
+ a.installTranslator(&qtTranslator);
+
+ QTranslator qtHelpTranslator(0);
+ qtHelpTranslator.load(QLatin1String("qt_help_") + locale, resourceDir);
+ a.installTranslator(&qtHelpTranslator);
+
+ MainWindow w(&cmd);
+ w.show();
+ a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
+ return a.exec();
+}
diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp
new file mode 100644
index 0000000000..0f246bead0
--- /dev/null
+++ b/tools/assistant/tools/assistant/mainwindow.cpp
@@ -0,0 +1,1008 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "centralwidget.h"
+#include "helpviewer.h"
+#include "indexwindow.h"
+#include "topicchooser.h"
+#include "contentwindow.h"
+#include "preferencesdialog.h"
+#include "bookmarkmanager.h"
+#include "remotecontrol.h"
+#include "cmdlineparser.h"
+#include "aboutdialog.h"
+#include "searchwidget.h"
+#include "qtdocinstaller.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+#include <QtCore/QResource>
+#include <QtCore/QByteArray>
+#include <QtCore/QTextStream>
+#include <QtCore/QCoreApplication>
+
+#include <QtGui/QMenuBar>
+#include <QtGui/QAction>
+#include <QtGui/QToolBar>
+#include <QtGui/QStatusBar>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QLayout>
+#include <QtGui/QDockWidget>
+#include <QtGui/QTreeView>
+#include <QtGui/QMessageBox>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QComboBox>
+#include <QtGui/QProgressBar>
+#include <QtGui/QDesktopServices>
+#include <QtGui/QToolButton>
+
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpSearchEngine>
+#include <QtHelp/QHelpContentModel>
+#include <QtHelp/QHelpIndexModel>
+
+QT_BEGIN_NAMESPACE
+
+MainWindow::MainWindow(CmdLineParser *cmdLine, QWidget *parent)
+ : QMainWindow(parent)
+ , m_toolBarMenu(0)
+ , m_cmdLine(cmdLine)
+ , m_searchWidget(0)
+ , m_progressWidget(0)
+ , m_qtDocInstaller(0)
+ , m_connectedInitSignals(false)
+{
+ if (usesDefaultCollection()) {
+ MainWindow::collectionFileDirectory(true);
+ m_helpEngine = new QHelpEngine(MainWindow::defaultHelpCollectionFileName(),
+ this);
+ } else {
+ m_helpEngine = new QHelpEngine(cmdLine->collectionFile(), this);
+ }
+
+ m_centralWidget = new CentralWidget(m_helpEngine, this);
+ setCentralWidget(m_centralWidget);
+
+ m_indexWindow = new IndexWindow(m_helpEngine);
+ QDockWidget *indexDock = new QDockWidget(tr("Index"), this);
+ indexDock->setObjectName(QLatin1String("IndexWindow"));
+ indexDock->setWidget(m_indexWindow);
+ addDockWidget(Qt::LeftDockWidgetArea, indexDock);
+
+ m_contentWindow = new ContentWindow(m_helpEngine);
+ QDockWidget *contentDock = new QDockWidget(tr("Contents"), this);
+ contentDock->setObjectName(QLatin1String("ContentWindow"));
+ contentDock->setWidget(m_contentWindow);
+ addDockWidget(Qt::LeftDockWidgetArea, contentDock);
+
+ QDockWidget *bookmarkDock = new QDockWidget(tr("Bookmarks"), this);
+ bookmarkDock->setObjectName(QLatin1String("BookmarkWindow"));
+ bookmarkDock->setWidget(setupBookmarkWidget());
+ addDockWidget(Qt::LeftDockWidgetArea, bookmarkDock);
+
+ QHelpSearchEngine *searchEngine = m_helpEngine->searchEngine();
+ connect(searchEngine, SIGNAL(indexingStarted()), this, SLOT(indexingStarted()));
+ connect(searchEngine, SIGNAL(indexingFinished()), this, SLOT(indexingFinished()));
+
+#ifdef QT_CLUCENE_SUPPORT
+ m_centralWidget->createSearchWidget(searchEngine);
+#else
+ QDockWidget *dock = new QDockWidget(tr("Search"), this);
+ dock->setObjectName(QLatin1String("SearchWindow"));
+ m_searchWidget = new SearchWidget(searchEngine, this);
+ dock->setWidget(m_searchWidget);
+ addDockWidget(Qt::LeftDockWidgetArea, dock);
+
+ connect(m_searchWidget, SIGNAL(requestShowLink(const QUrl&)),
+ m_centralWidget, SLOT(setSource(const QUrl&)));
+ connect(m_searchWidget, SIGNAL(requestShowLinkInNewTab(const QUrl&)),
+ m_centralWidget, SLOT(setSourceInNewTab(const QUrl&)));
+#endif
+
+ QString defWindowTitle = tr("Qt Assistant");
+ setWindowTitle(defWindowTitle);
+
+ setupActions();
+ statusBar()->show();
+
+ if (initHelpDB()) {
+ setupFilterToolbar();
+ setupAddressToolbar();
+ m_bookmarkManager->setupBookmarkModels();
+
+ setWindowTitle(m_helpEngine->customValue(QLatin1String("WindowTitle"),
+ defWindowTitle).toString());
+ QByteArray iconArray = m_helpEngine->customValue(QLatin1String("ApplicationIcon"),
+ QByteArray()).toByteArray();
+ if (iconArray.size() > 0) {
+ QPixmap pix;
+ pix.loadFromData(iconArray);
+ QIcon appIcon(pix);
+ qApp->setWindowIcon(appIcon);
+ } else {
+ QIcon appIcon(QLatin1String(":/trolltech/assistant/images/assistant-128.png"));
+ qApp->setWindowIcon(appIcon);
+ }
+
+ // Show the widget here, otherwise the restore geometry and state won't work
+ // on x11.
+ show();
+ QByteArray ba(m_helpEngine->customValue(QLatin1String("MainWindow")).toByteArray());
+ if (!ba.isEmpty())
+ restoreState(ba);
+
+ ba = m_helpEngine->customValue(QLatin1String("MainWindowGeometry")).toByteArray();
+ if (!ba.isEmpty()) {
+ restoreGeometry(ba);
+ } else {
+ tabifyDockWidget(contentDock, indexDock);
+ tabifyDockWidget(indexDock, bookmarkDock);
+ contentDock->raise();
+ resize(QSize(800, 600));
+ }
+
+ if (!m_helpEngine->customValue(QLatin1String("useAppFont")).isValid()) {
+ m_helpEngine->setCustomValue(QLatin1String("useAppFont"), false);
+ m_helpEngine->setCustomValue(QLatin1String("useBrowserFont"), false);
+ m_helpEngine->setCustomValue(QLatin1String("appFont"), qApp->font());
+ m_helpEngine->setCustomValue(QLatin1String("appWritingSystem"), QFontDatabase::Latin);
+ m_helpEngine->setCustomValue(QLatin1String("browserFont"), qApp->font());
+ m_helpEngine->setCustomValue(QLatin1String("browserWritingSystem"), QFontDatabase::Latin);
+ } else {
+ updateApplicationFont();
+ }
+
+ updateAboutMenuText();
+
+ QTimer::singleShot(0, this, SLOT(insertLastPages()));
+ if (m_cmdLine->enableRemoteControl())
+ (void)new RemoteControl(this, m_helpEngine);
+
+ if (m_cmdLine->contents() == CmdLineParser::Show)
+ showContents();
+ else if (m_cmdLine->contents() == CmdLineParser::Hide)
+ hideContents();
+
+ if (m_cmdLine->index() == CmdLineParser::Show)
+ showIndex();
+ else if (m_cmdLine->index() == CmdLineParser::Hide)
+ hideIndex();
+
+ if (m_cmdLine->bookmarks() == CmdLineParser::Show)
+ showBookmarks();
+ else if (m_cmdLine->bookmarks() == CmdLineParser::Hide)
+ hideBookmarks();
+
+ if (m_cmdLine->search() == CmdLineParser::Show)
+ showSearch();
+ else if (m_cmdLine->search() == CmdLineParser::Hide)
+ hideSearch();
+
+ if (m_cmdLine->contents() == CmdLineParser::Activate)
+ showContents();
+ else if (m_cmdLine->index() == CmdLineParser::Activate)
+ showIndex();
+ else if (m_cmdLine->bookmarks() == CmdLineParser::Activate)
+ showBookmarks();
+
+ if (usesDefaultCollection())
+ QTimer::singleShot(0, this, SLOT(lookForNewQtDocumentation()));
+ else
+ checkInitState();
+ }
+}
+
+MainWindow::~MainWindow()
+{
+ if (m_qtDocInstaller)
+ delete m_qtDocInstaller;
+}
+
+bool MainWindow::usesDefaultCollection() const
+{
+ return m_cmdLine->collectionFile().isEmpty();
+}
+
+void MainWindow::closeEvent(QCloseEvent *e)
+{
+ m_bookmarkManager->saveBookmarks();
+ m_helpEngine->setCustomValue(QLatin1String("MainWindow"), saveState());
+ m_helpEngine->setCustomValue(QLatin1String("MainWindowGeometry"),
+ saveGeometry());
+
+ QMainWindow::closeEvent(e);
+}
+
+bool MainWindow::initHelpDB()
+{
+ if (!m_helpEngine->setupData())
+ return false;
+
+ bool assistantInternalDocRegistered = false;
+ QString intern(QLatin1String("com.trolltech.com.assistantinternal_"));
+ foreach (const QString &ns, m_helpEngine->registeredDocumentations()) {
+ if (ns.startsWith(intern)) {
+ intern = ns;
+ assistantInternalDocRegistered = true;
+ break;
+ }
+ }
+
+ const QString &collectionFile = m_helpEngine->collectionFile();
+
+ QFileInfo fi(collectionFile);
+ QString helpFile;
+ QTextStream(&helpFile) << fi.absolutePath() << QDir::separator()
+ << QLatin1String("assistant.qch.") << (QT_VERSION >> 16)
+ << QLatin1Char('.') << ((QT_VERSION >> 8) & 0xFF);
+
+ bool needsSetup = false;
+ if (!assistantInternalDocRegistered || !QFile::exists(helpFile)) {
+ QFile file(helpFile);
+ if (file.open(QIODevice::WriteOnly)) {
+ QResource res(QLatin1String(":/trolltech/assistant/assistant.qch"));
+ if (file.write((const char*)res.data(), res.size()) != res.size())
+ qDebug() << QLatin1String("could not write assistant.qch...");
+
+ file.close();
+ }
+ QHelpEngineCore hc(fi.absoluteFilePath());
+ hc.setupData();
+ hc.unregisterDocumentation(intern);
+ hc.registerDocumentation(helpFile);
+ needsSetup = true;
+ }
+
+ const QLatin1String unfiltered("UnfilteredFilterInserted");
+ if (1 != m_helpEngine->customValue(unfiltered).toInt()) {
+ {
+ QHelpEngineCore hc(collectionFile);
+ hc.setupData();
+ hc.addCustomFilter(tr("Unfiltered"), QStringList());
+ hc.setCustomValue(unfiltered, 1);
+ }
+ m_helpEngine->blockSignals(true);
+ m_helpEngine->setCurrentFilter(tr("Unfiltered"));
+ m_helpEngine->blockSignals(false);
+ needsSetup = true;
+ }
+
+ if (needsSetup)
+ m_helpEngine->setupData();
+ return true;
+}
+
+void MainWindow::lookForNewQtDocumentation()
+{
+ m_qtDocInstaller = new QtDocInstaller(m_helpEngine->collectionFile());
+ connect(m_qtDocInstaller, SIGNAL(errorMessage(const QString&)),
+ this, SLOT(displayInstallationError(const QString&)));
+ connect(m_qtDocInstaller, SIGNAL(docsInstalled(bool)),
+ this, SLOT(qtDocumentationInstalled(bool)));
+
+ QString versionKey = QString(QLatin1String("qtVersion%1$$$qt")).
+ arg(QLatin1String(QT_VERSION_STR));
+ if (m_helpEngine->customValue(versionKey, 0).toInt() != 1)
+ statusBar()->showMessage(tr("Looking for Qt Documentation..."));
+ m_qtDocInstaller->installDocs();
+}
+
+void MainWindow::displayInstallationError(const QString &errorMessage)
+{
+ QMessageBox::warning(this, tr("Qt Assistant"), errorMessage);
+}
+
+void MainWindow::qtDocumentationInstalled(bool newDocsInstalled)
+{
+ if (newDocsInstalled)
+ m_helpEngine->setupData();
+ statusBar()->clearMessage();
+ checkInitState();
+}
+
+void MainWindow::checkInitState()
+{
+ if (!m_cmdLine->enableRemoteControl())
+ return;
+
+ if (m_helpEngine->contentModel()->isCreatingContents()
+ || m_helpEngine->indexModel()->isCreatingIndex()) {
+ if (!m_connectedInitSignals) {
+ connect(m_helpEngine->contentModel(), SIGNAL(contentsCreated()),
+ this, SLOT(checkInitState()));
+ connect(m_helpEngine->indexModel(), SIGNAL(indexCreated()),
+ this, SLOT(checkInitState()));
+ m_connectedInitSignals = true;
+ }
+ } else {
+ if (m_connectedInitSignals) {
+ disconnect(m_helpEngine->contentModel(), 0, this, 0);
+ disconnect(m_helpEngine->indexModel(), 0, this, 0);
+ }
+ emit initDone();
+ }
+}
+
+void MainWindow::insertLastPages()
+{
+ if (m_cmdLine->url().isValid())
+ m_centralWidget->setSource(m_cmdLine->url());
+ else
+ m_centralWidget->setLastShownPages();
+
+ if (m_cmdLine->search() == CmdLineParser::Activate)
+ showSearch();
+}
+
+void MainWindow::setupActions()
+{
+ QString system = QLatin1String("win");
+#ifdef Q_OS_MAC
+ system = QLatin1String("mac");
+ setUnifiedTitleAndToolBarOnMac(true);
+#endif
+
+ QMenu *menu = menuBar()->addMenu(tr("&File"));
+
+ m_pageSetupAction = menu->addAction(tr("Page Set&up..."), m_centralWidget, SLOT(pageSetup()));
+ m_printPreviewAction = menu->addAction(tr("Print Preview..."), m_centralWidget, SLOT(printPreview()));
+ m_printAction = menu->addAction(tr("&Print..."), m_centralWidget, SLOT(print()));
+ m_printAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/print.png").arg(system)));
+ m_printAction->setShortcut(tr("CTRL+P"));
+
+ menu->addSeparator();
+
+ m_newTabAction = menu->addAction(tr("New &Tab"), m_centralWidget, SLOT(newTab()));
+ m_newTabAction->setShortcut(tr("CTRL+T"));
+ m_closeTabAction = menu->addAction(tr("&Close Tab"), m_centralWidget, SLOT(closeTab()));
+ m_closeTabAction->setShortcut(tr("CTRL+W"));
+
+ QAction *tmp = menu->addAction(tr("&Quit"), this, SLOT(close()));
+ tmp->setShortcut(tr("CTRL+Q"));
+ tmp->setMenuRole(QAction::QuitRole);
+
+ menu = menuBar()->addMenu(tr("&Edit"));
+ m_copyAction = menu->addAction(tr("&Copy selected Text"),
+ m_centralWidget, SLOT(copySelection()));
+ m_copyAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/editcopy.png").arg(system)));
+ m_copyAction->setShortcut(tr("Ctrl+C"));
+ m_copyAction->setEnabled(false);
+
+ m_findAction = menu->addAction(tr("&Find in Text..."),
+ m_centralWidget, SLOT(showTextSearch()));
+ m_findAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/find.png").arg(system)));
+ m_findAction->setShortcut(tr("Ctrl+F"));
+ m_findAction->setShortcut(QKeySequence::Find);
+
+ QAction *findNextAction = menu->addAction(tr("Find &Next"),
+ m_centralWidget, SLOT(findNext()));
+ findNextAction->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("F3"))
+ << QKeySequence(tr("CTRL+G")));
+
+ QAction *findPreviousAction = menu->addAction(tr("Find &Previous"),
+ m_centralWidget, SLOT(findPrevious()));
+ findPreviousAction->setShortcuts(QList<QKeySequence>() <<
+ QKeySequence(tr("Shift+F3")) << QKeySequence(tr("CTRL+SHIFT+G")));
+
+ menu->addSeparator();
+ tmp = menu->addAction(tr("Preferences..."), this, SLOT(showPreferences()));
+ tmp->setMenuRole(QAction::PreferencesRole);
+
+ m_viewMenu = menuBar()->addMenu(tr("&View"));
+ m_zoomInAction = m_viewMenu->addAction(tr("Zoom &in"),
+ m_centralWidget, SLOT(zoomIn()));
+ m_zoomInAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/zoomin.png").arg(system)));
+ m_zoomInAction->setShortcut(tr("Ctrl++"));
+
+ m_zoomOutAction = m_viewMenu->addAction(tr("Zoom &out"),
+ m_centralWidget, SLOT(zoomOut()));
+ m_zoomOutAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/zoomout.png").arg(system)));
+ m_zoomOutAction->setShortcut(tr("Ctrl+-"));
+
+ m_resetZoomAction = m_viewMenu->addAction(tr("Normal &Size"),
+ m_centralWidget, SLOT(resetZoom()));
+ m_resetZoomAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/resetzoom.png").arg(system)));
+ m_resetZoomAction->setShortcut(tr("Ctrl+0"));
+
+ m_viewMenu->addSeparator();
+
+ m_viewMenu->addAction(tr("Contents"), this,
+ SLOT(showContents()), QKeySequence(tr("ALT+C")));
+ m_viewMenu->addAction(tr("Index"), this,
+ SLOT(showIndex()), QKeySequence(tr("ALT+I")));
+ m_viewMenu->addAction(tr("Bookmarks"), this,
+ SLOT(showBookmarks()), QKeySequence(tr("ALT+O")));
+ m_viewMenu->addAction(tr("Search"), this,
+ SLOT(showSearch()), QKeySequence(tr("ALT+S")));
+
+ menu = menuBar()->addMenu(tr("&Go"));
+ m_homeAction = menu->addAction(tr("&Home"),
+ m_centralWidget, SLOT(home()));
+ m_homeAction->setShortcut(tr("Ctrl+Home"));
+ m_homeAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/home.png").arg(system)));
+
+ m_backAction = menu->addAction(tr("&Back"),
+ m_centralWidget, SLOT(backward()));
+ m_backAction->setEnabled(false);
+ m_backAction->setShortcuts(QList<QKeySequence>()
+ << QKeySequence(Qt::CTRL|Qt::Key_Left) << QKeySequence::Back);
+ m_backAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/previous.png").arg(system)));
+
+ m_nextAction = menu->addAction(tr("&Forward"),
+ m_centralWidget, SLOT(forward()));
+ m_nextAction->setEnabled(false);
+ m_nextAction->setShortcuts(QList<QKeySequence>()
+ << QKeySequence(Qt::CTRL|Qt::Key_Right) << QKeySequence::Forward);
+ m_nextAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/next.png").arg(system)));
+
+ m_syncAction = menu->addAction(tr("Sync with Table of Contents"),
+ this, SLOT(syncContents()));
+ m_syncAction->setIcon(QIcon(
+ QString::fromUtf8(":/trolltech/assistant/images/%1/synctoc.png").arg(system)));
+
+ menu->addSeparator();
+
+ tmp = menu->addAction(tr("Next Page"), m_centralWidget, SLOT(nextPage()));
+ tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Right"))
+ << QKeySequence(Qt::CTRL + Qt::Key_PageDown));
+
+ tmp = menu->addAction(tr("Previous Page"),
+ m_centralWidget, SLOT(previousPage()));
+ tmp->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Alt+Left"))
+ << QKeySequence(Qt::CTRL + Qt::Key_PageUp));
+
+ menu = menuBar()->addMenu(tr("&Bookmarks"));
+ tmp = menu->addAction(tr("Add Bookmark..."), this, SLOT(addBookmark()));
+ tmp->setShortcut(tr("CTRL+D"));
+
+ menu = menuBar()->addMenu(tr("&Help"));
+ m_aboutAction = menu->addAction(tr("About..."), this, SLOT(showAboutDialog()));
+ m_aboutAction->setMenuRole(QAction::AboutRole);
+
+ QToolBar *navigationBar = addToolBar(tr("Navigation Toolbar"));
+ navigationBar->setObjectName(QLatin1String("NavigationToolBar"));
+ navigationBar->addAction(m_backAction);
+ navigationBar->addAction(m_nextAction);
+ navigationBar->addAction(m_homeAction);
+ navigationBar->addAction(m_syncAction);
+ QAction *sep = navigationBar->addSeparator();
+ navigationBar->addAction(m_copyAction);
+ navigationBar->addAction(m_printAction);
+ navigationBar->addAction(m_findAction);
+ QAction *sep2 = navigationBar->addSeparator();
+ navigationBar->addAction(m_zoomInAction);
+ navigationBar->addAction(m_zoomOutAction);
+ navigationBar->addAction(m_resetZoomAction);
+
+ QList<QAction*> actionList;
+ actionList << m_backAction << m_nextAction << m_homeAction;
+ actionList << sep << m_zoomInAction << m_zoomOutAction;
+ actionList << sep2 << m_copyAction << m_printAction << m_findAction;
+ m_centralWidget->setGlobalActions(actionList);
+
+#if defined(Q_WS_MAC)
+ QMenu *windowMenu = new QMenu(tr("&Window"), this);
+ menuBar()->insertMenu(menu->menuAction(), windowMenu);
+ windowMenu->addAction(tr("Minimize"), this,
+ SLOT(showMinimized()), QKeySequence(tr("Ctrl+M")));
+ windowMenu->addAction(tr("Zoom"), this,
+ SLOT(showMaximized()));
+#endif
+
+ // content viewer connections
+ connect(m_centralWidget, SIGNAL(copyAvailable(bool)),
+ this, SLOT(copyAvailable(bool)));
+ connect(m_centralWidget, SIGNAL(currentViewerChanged()),
+ this, SLOT(updateNavigationItems()));
+ connect(m_centralWidget, SIGNAL(forwardAvailable(bool)),
+ this, SLOT(updateNavigationItems()));
+ connect(m_centralWidget, SIGNAL(backwardAvailable(bool)),
+ this, SLOT(updateNavigationItems()));
+ connect(m_centralWidget, SIGNAL(highlighted(const QString&)),
+ statusBar(), SLOT(showMessage(const QString&)));
+ connect(m_centralWidget, SIGNAL(addNewBookmark(const QString&,
+ const QString&)), this, SLOT(addNewBookmark(const QString&, const QString&)));
+
+ // bookmarks
+ connect(m_bookmarkWidget, SIGNAL(requestShowLink(const QUrl&)),
+ m_centralWidget, SLOT(setSource(const QUrl&)));
+ connect(m_bookmarkWidget, SIGNAL(escapePressed()),
+ this, SLOT(activateCurrentCentralWidgetTab()));
+
+ // index window
+ connect(m_indexWindow, SIGNAL(linkActivated(const QUrl&)),
+ m_centralWidget, SLOT(setSource(const QUrl&)));
+ connect(m_indexWindow, SIGNAL(linksActivated(const QMap<QString, QUrl>&, const QString&)),
+ this, SLOT(showTopicChooser(const QMap<QString, QUrl>&, const QString&)));
+ connect(m_indexWindow, SIGNAL(escapePressed()),
+ this, SLOT(activateCurrentCentralWidgetTab()));
+
+ // content window
+ connect(m_contentWindow, SIGNAL(linkActivated(const QUrl&)),
+ m_centralWidget, SLOT(setSource(const QUrl&)));
+ connect(m_contentWindow, SIGNAL(escapePressed()),
+ this, SLOT(activateCurrentCentralWidgetTab()));
+
+#if defined(QT_NO_PRINTER)
+ m_pageSetupAction->setVisible(false);
+ m_printPreviewAction->setVisible(false);
+ m_printAction->setVisible(false);
+#endif
+}
+
+QMenu *MainWindow::toolBarMenu()
+{
+ if (!m_toolBarMenu) {
+ m_viewMenu->addSeparator();
+ m_toolBarMenu = m_viewMenu->addMenu(tr("Toolbars"));
+ }
+ return m_toolBarMenu;
+}
+
+void MainWindow::setupFilterToolbar()
+{
+ if (!m_helpEngine->
+ customValue(QLatin1String("EnableFilterFunctionality"), true).toBool())
+ return;
+
+ m_filterCombo = new QComboBox(this);
+ m_filterCombo->setMinimumWidth(QFontMetrics(QFont()).
+ width(QLatin1String("MakeTheComboBoxWidthEnough")));
+
+ QToolBar *filterToolBar = addToolBar(tr("Filter Toolbar"));
+ filterToolBar->setObjectName(QLatin1String("FilterToolBar"));
+ filterToolBar->addWidget(new QLabel(tr("Filtered by:").append(QLatin1String(" ")), this));
+ filterToolBar->addWidget(m_filterCombo);
+
+ if (m_helpEngine->customValue(QLatin1String("HideFilterFunctionality"), true).toBool())
+ filterToolBar->hide();
+ toolBarMenu()->addAction(filterToolBar->toggleViewAction());
+
+ connect(m_helpEngine, SIGNAL(setupFinished()),
+ this, SLOT(setupFilterCombo()));
+ connect(m_filterCombo, SIGNAL(activated(const QString&)),
+ this, SLOT(filterDocumentation(const QString&)));
+
+ setupFilterCombo();
+}
+
+void MainWindow::setupAddressToolbar()
+{
+ if (!m_helpEngine->customValue(QLatin1String("EnableAddressBar"), true).toBool())
+ return;
+
+ m_addressLineEdit = new QLineEdit(this);
+ QToolBar *addressToolBar = addToolBar(tr("Address Toolbar"));
+ addressToolBar->setObjectName(QLatin1String("AddressToolBar"));
+ insertToolBarBreak(addressToolBar);
+
+ addressToolBar->addWidget(new QLabel(tr("Address:").append(QLatin1String(" ")), this));
+ addressToolBar->addWidget(m_addressLineEdit);
+
+ if (m_helpEngine->customValue(QLatin1String("HideAddressBar"), true).toBool())
+ addressToolBar->hide();
+ toolBarMenu()->addAction(addressToolBar->toggleViewAction());
+
+ // address lineedit
+ connect(m_addressLineEdit, SIGNAL(returnPressed()),
+ this, SLOT(gotoAddress()));
+ connect(m_centralWidget, SIGNAL(currentViewerChanged()),
+ this, SLOT(showNewAddress()));
+ connect(m_centralWidget, SIGNAL(sourceChanged(const QUrl&)),
+ this, SLOT(showNewAddress(const QUrl&)));
+}
+
+void MainWindow::updateAboutMenuText()
+{
+ if (m_helpEngine) {
+ QByteArray ba = m_helpEngine->customValue(QLatin1String("AboutMenuTexts"),
+ QByteArray()).toByteArray();
+ if (ba.size() > 0) {
+ QString lang;
+ QString str;
+ QString trStr;
+ QString currentLang = QLocale::system().name();
+ int i = currentLang.indexOf(QLatin1Char('_'));
+ if (i > -1)
+ currentLang = currentLang.left(i);
+ QDataStream s(&ba, QIODevice::ReadOnly);
+ while (!s.atEnd()) {
+ s >> lang;
+ s >> str;
+ if (lang == QLatin1String("default") && trStr.isEmpty()) {
+ trStr = str;
+ } else if (lang == currentLang) {
+ trStr = str;
+ break;
+ }
+ }
+ if (!trStr.isEmpty())
+ m_aboutAction->setText(trStr);
+ }
+ }
+}
+
+void MainWindow::showNewAddress()
+{
+ showNewAddress(m_centralWidget->currentSource());
+}
+
+void MainWindow::showNewAddress(const QUrl &url)
+{
+ m_addressLineEdit->setText(url.toString());
+}
+
+void MainWindow::addBookmark()
+{
+ addNewBookmark(m_centralWidget->currentTitle(), m_centralWidget->currentSource().toString());
+}
+
+void MainWindow::gotoAddress()
+{
+ m_centralWidget->setSource(m_addressLineEdit->text());
+}
+
+void MainWindow::updateNavigationItems()
+{
+ bool hasCurrentViewer = m_centralWidget->isHomeAvailable();
+ m_copyAction->setEnabled(m_centralWidget->hasSelection());
+ m_homeAction->setEnabled(hasCurrentViewer);
+ m_syncAction->setEnabled(hasCurrentViewer);
+ m_printPreviewAction->setEnabled(hasCurrentViewer);
+ m_printAction->setEnabled(hasCurrentViewer);
+ m_nextAction->setEnabled(m_centralWidget->isForwardAvailable());
+ m_backAction->setEnabled(m_centralWidget->isBackwardAvailable());
+ m_closeTabAction->setEnabled(hasCurrentViewer);
+ m_newTabAction->setEnabled(hasCurrentViewer);
+}
+
+void MainWindow::showTopicChooser(const QMap<QString, QUrl> &links,
+ const QString &keyword)
+{
+ TopicChooser tc(this, keyword, links);
+ if (tc.exec() == QDialog::Accepted) {
+ m_centralWidget->setSource(tc.link());
+ }
+}
+
+void MainWindow::showPreferences()
+{
+ PreferencesDialog dia(m_helpEngine, this);
+
+ connect(&dia, SIGNAL(updateApplicationFont()),
+ this, SLOT(updateApplicationFont()));
+ connect(&dia, SIGNAL(updateBrowserFont()),
+ m_centralWidget, SLOT(updateBrowserFont()));
+
+ dia.showDialog();
+}
+
+void MainWindow::syncContents()
+{
+ qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+ const QUrl url = m_centralWidget->currentSource();
+ showContents();
+ if (!m_contentWindow->syncToContent(url))
+ statusBar()->showMessage(
+ tr("Could not find the associated content item."), 3000);
+ qApp->restoreOverrideCursor();
+}
+
+void MainWindow::copyAvailable(bool yes)
+{
+ m_copyAction->setEnabled(yes);
+}
+
+void MainWindow::addNewBookmark(const QString &title, const QString &url)
+{
+ if (url.isEmpty())
+ return;
+
+ m_bookmarkManager->showBookmarkDialog(this, title, url);
+}
+
+void MainWindow::showAboutDialog()
+{
+ QByteArray contents;
+ if (m_helpEngine) {
+ QByteArray ba = m_helpEngine->customValue(QLatin1String("AboutTexts"),
+ QByteArray()).toByteArray();
+ if (!ba.isEmpty()) {
+ QString lang;
+ QByteArray cba;
+ QString currentLang = QLocale::system().name();
+ int i = currentLang.indexOf(QLatin1Char('_'));
+ if (i > -1)
+ currentLang = currentLang.left(i);
+ QDataStream s(&ba, QIODevice::ReadOnly);
+ while (!s.atEnd()) {
+ s >> lang;
+ s >> cba;
+ if (lang == QLatin1String("default") && contents.isEmpty()) {
+ contents = cba;
+ } else if (lang == currentLang) {
+ contents = cba;
+ break;
+ }
+ }
+ }
+ }
+
+ AboutDialog aboutDia(this);
+
+ QByteArray iconArray;
+ if (!contents.isEmpty()) {
+ iconArray = m_helpEngine->customValue(QLatin1String("AboutIcon"),
+ QByteArray()).toByteArray();
+ QByteArray resources = m_helpEngine->customValue(QLatin1String("AboutImages"),
+ QByteArray()).toByteArray();
+ QPixmap pix;
+ pix.loadFromData(iconArray);
+ aboutDia.setText(QString::fromUtf8(contents), resources);
+ if (!pix.isNull())
+ aboutDia.setPixmap(pix);
+ aboutDia.setWindowTitle(aboutDia.documentTitle());
+ } else {
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ QString edition = tr("Open Source Edition");
+ QString info = tr("This version of Qt Assistant is part of the Qt Open Source Edition, for use "
+ "in the development of Open Source applications. "
+ "Qt is a comprehensive C++ framework for cross-platform application "
+ "development.");
+ QString moreInfo = tr("You need a commercial Qt license for development of proprietary (closed "
+ "source) applications. Please see <a href=\"http://qtsoftware.com/company/about/businessmodel"
+ "\">http://qtsoftware.com/company/about/businessmodel</a> for an overview of Qt licensing.");
+#else
+ QString edition;
+ QString info;
+ QString moreInfo(tr("This program is licensed to you under the terms of the "
+ "Qt Commercial License Agreement. For details, see the file LICENSE "
+ "that came with this software distribution."));
+
+#endif
+ QByteArray resources;
+ aboutDia.setText(QString::fromLatin1("<center>"
+ "<h3>%1</h3>"
+ "<p>Version %2 %3</p></center>"
+ "<p>%4</p>"
+ "<p>%5</p>"
+ "<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>"
+ "<p>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
+ " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
+ " PARTICULAR PURPOSE.<p/>")
+ .arg(tr("Qt Assistant")).arg(QLatin1String(QT_VERSION_STR))
+ .arg(edition).arg(info).arg(moreInfo), resources);
+ aboutDia.setPixmap(QString::fromLatin1(":/trolltech/assistant/images/assistant-128.png"));
+ }
+ if (aboutDia.windowTitle().isEmpty())
+ aboutDia.setWindowTitle(tr("About %1").arg(windowTitle()));
+ aboutDia.exec();
+}
+
+void MainWindow::showContents()
+{
+ activateDockWidget(m_contentWindow);
+}
+
+void MainWindow::showIndex()
+{
+ activateDockWidget(m_indexWindow);
+}
+
+void MainWindow::showBookmarks()
+{
+ activateDockWidget(m_bookmarkWidget);
+}
+
+void MainWindow::activateDockWidget(QWidget *w)
+{
+ w->parentWidget()->show();
+ w->parentWidget()->raise();
+ w->setFocus();
+}
+
+void MainWindow::hideContents()
+{
+ m_contentWindow->parentWidget()->hide();
+}
+
+void MainWindow::hideIndex()
+{
+ m_indexWindow->parentWidget()->hide();
+}
+
+void MainWindow::hideBookmarks()
+{
+ m_bookmarkWidget->parentWidget()->hide();
+}
+
+void MainWindow::setIndexString(const QString &str)
+{
+ m_indexWindow->setSearchLineEditText(str);
+}
+
+void MainWindow::activateCurrentBrowser()
+{
+ CentralWidget *cw = CentralWidget::instance();
+ if (cw) {
+ cw->activateTab(true);
+ }
+}
+
+void MainWindow::activateCurrentCentralWidgetTab()
+{
+ m_centralWidget->activateTab();
+}
+
+void MainWindow::showSearch()
+{
+ if (m_searchWidget)
+ activateDockWidget(m_searchWidget);
+ else
+ m_centralWidget->activateSearch();
+}
+
+void MainWindow::hideSearch()
+{
+ if (m_searchWidget) {
+ m_searchWidget->parentWidget()->parentWidget()->hide();
+ } else {
+ m_centralWidget->removeSearchWidget();
+ }
+}
+
+void MainWindow::updateApplicationFont()
+{
+ QFont font = qApp->font();
+ if (m_helpEngine->customValue(QLatin1String("useAppFont")).toBool())
+ font = qVariantValue<QFont>(m_helpEngine->customValue(QLatin1String("appFont")));
+
+ qApp->setFont(font, "QWidget");
+}
+
+void MainWindow::setupFilterCombo()
+{
+ QString curFilter = m_filterCombo->currentText();
+ if (curFilter.isEmpty())
+ curFilter = m_helpEngine->currentFilter();
+ m_filterCombo->clear();
+ m_filterCombo->addItems(m_helpEngine->customFilters());
+ int idx = m_filterCombo->findText(curFilter);
+ if (idx < 0)
+ idx = 0;
+ m_filterCombo->setCurrentIndex(idx);
+}
+
+void MainWindow::filterDocumentation(const QString &customFilter)
+{
+ m_helpEngine->setCurrentFilter(customFilter);
+}
+
+void MainWindow::expandTOC(int depth)
+{
+ m_contentWindow->expandToDepth(depth);
+}
+
+void MainWindow::indexingStarted()
+{
+ m_progressWidget = new QWidget();
+ QLayout* hlayout = new QHBoxLayout(m_progressWidget);
+
+ QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
+
+ QLabel *label = new QLabel(tr("Updating search index"));
+ label->setSizePolicy(sizePolicy);
+ hlayout->addWidget(label);
+
+ QProgressBar *progressBar = new QProgressBar();
+ progressBar->setRange(0, 0);
+ progressBar->setTextVisible(false);
+ progressBar->setSizePolicy(sizePolicy);
+
+ hlayout->setSpacing(6);
+ hlayout->setMargin(0);
+ hlayout->addWidget(progressBar);
+
+ statusBar()->addPermanentWidget(m_progressWidget);
+}
+
+void MainWindow::indexingFinished()
+{
+ statusBar()->removeWidget(m_progressWidget);
+ delete m_progressWidget;
+ m_progressWidget = 0;
+}
+
+QWidget* MainWindow::setupBookmarkWidget()
+{
+ m_bookmarkManager = new BookmarkManager(m_helpEngine);
+ m_bookmarkWidget = new BookmarkWidget(m_bookmarkManager, this);
+ connect(m_bookmarkWidget, SIGNAL(addBookmark()),
+ this, SLOT(addBookmark()));
+ return m_bookmarkWidget;
+}
+
+QString MainWindow::collectionFileDirectory(bool createDir, const QString &cacheDir)
+{
+ QString collectionPath = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
+ if (collectionPath.isEmpty()) {
+ if (cacheDir.isEmpty())
+ collectionPath = QDir::homePath() + QDir::separator()
+ + QLatin1String(".assistant");
+ else
+ collectionPath = QDir::homePath() + QLatin1String("/.")
+ + cacheDir;
+ } else {
+ if (cacheDir.isEmpty())
+ collectionPath = collectionPath + QLatin1String("/Trolltech/Assistant");
+ else
+ collectionPath = collectionPath + QDir::separator()
+ + cacheDir;
+ }
+ collectionPath = QDir::cleanPath(collectionPath);
+ if (createDir) {
+ QDir dir;
+ if (!dir.exists(collectionPath))
+ dir.mkpath(collectionPath);
+ }
+ return collectionPath;
+}
+
+QString MainWindow::defaultHelpCollectionFileName()
+{
+ return collectionFileDirectory() + QDir::separator() +
+ QString(QLatin1String("qthelpcollection_%1.qhc")).
+ arg(QLatin1String(QT_VERSION_STR));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/mainwindow.h b/tools/assistant/tools/assistant/mainwindow.h
new file mode 100644
index 0000000000..8b87b7b9ea
--- /dev/null
+++ b/tools/assistant/tools/assistant/mainwindow.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtCore/QUrl>
+#include <QtGui/QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QLineEdit;
+class QComboBox;
+class QMenu;
+
+class IndexWindow;
+class QHelpEngineCore;
+class QHelpEngine;
+class CentralWidget;
+class ContentWindow;
+class BookmarkManager;
+class BookmarkWidget;
+class CmdLineParser;
+class QtDocInstaller;
+
+class SearchWidget;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow(CmdLineParser *cmdLine, QWidget *parent = 0);
+ ~MainWindow();
+
+ static void activateCurrentBrowser();
+ static QString collectionFileDirectory(bool createDir = false,
+ const QString &cacheDir = QString());
+ static QString defaultHelpCollectionFileName();
+
+public:
+ void hideContents();
+ void hideIndex();
+ void hideBookmarks();
+ void hideSearch();
+ void setIndexString(const QString &str);
+ void expandTOC(int depth);
+ bool usesDefaultCollection() const;
+
+signals:
+ void initDone();
+
+public slots:
+ void showContents();
+ void showIndex();
+ void showBookmarks();
+ void showSearch();
+ void syncContents();
+ void activateCurrentCentralWidgetTab();
+
+private slots:
+ void insertLastPages();
+ void addBookmark();
+ void gotoAddress();
+ void showPreferences();
+ void showNewAddress();
+ void showAboutDialog();
+ void copyAvailable(bool yes);
+ void updateNavigationItems();
+ void showNewAddress(const QUrl &url);
+ void addNewBookmark(const QString &title, const QString &url);
+ void showTopicChooser(const QMap<QString, QUrl> &links, const QString &keyword);
+ void updateApplicationFont();
+ void filterDocumentation(const QString &customFilter);
+ void setupFilterCombo();
+ void lookForNewQtDocumentation();
+ void indexingStarted();
+ void indexingFinished();
+ void displayInstallationError(const QString &errorMessage);
+ void qtDocumentationInstalled(bool newDocsInstalled);
+ void checkInitState();
+
+private:
+ bool initHelpDB();
+ void setupActions();
+ void closeEvent(QCloseEvent *e);
+ void activateDockWidget(QWidget *w);
+ void updateAboutMenuText();
+ void setupFilterToolbar();
+ void setupAddressToolbar();
+ QMenu *toolBarMenu();
+ QWidget *setupBookmarkWidget();
+
+ QHelpEngine *m_helpEngine;
+ CentralWidget *m_centralWidget;
+ IndexWindow *m_indexWindow;
+ ContentWindow *m_contentWindow;
+ BookmarkWidget *m_bookmarkWidget;
+ BookmarkManager *m_bookmarkManager;
+ QLineEdit *m_addressLineEdit;
+ QComboBox *m_filterCombo;
+
+ QAction *m_backAction;
+ QAction *m_nextAction;
+ QAction *m_homeAction;
+ QAction *m_syncAction;
+ QAction *m_copyAction;
+ QAction *m_findAction;
+ QAction *m_printAction;
+ QAction *m_printPreviewAction;
+ QAction *m_pageSetupAction;
+ QAction *m_zoomInAction;
+ QAction *m_zoomOutAction;
+ QAction *m_resetZoomAction;
+ QAction *m_aboutAction;
+ QAction *m_closeTabAction;
+ QAction *m_newTabAction;
+
+ QMenu *m_viewMenu;
+ QMenu *m_toolBarMenu;
+
+ CmdLineParser *m_cmdLine;
+ SearchWidget *m_searchWidget;
+
+ QWidget *m_progressWidget;
+ QtDocInstaller *m_qtDocInstaller;
+
+ bool m_connectedInitSignals;
+};
+
+QT_END_NAMESPACE
+
+#endif // MAINWINDOW_H
diff --git a/tools/assistant/tools/assistant/preferencesdialog.cpp b/tools/assistant/tools/assistant/preferencesdialog.cpp
new file mode 100644
index 0000000000..094bd9c02c
--- /dev/null
+++ b/tools/assistant/tools/assistant/preferencesdialog.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "preferencesdialog.h"
+#include "filternamedialog.h"
+#include "installdialog.h"
+#include "fontpanel.h"
+#include "centralwidget.h"
+
+#include <QtAlgorithms>
+
+#include <QtGui/QHeaderView>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QMenu>
+#include <QtGui/QFontDatabase>
+
+#include <QtHelp/QHelpEngineCore>
+
+QT_BEGIN_NAMESPACE
+
+PreferencesDialog::PreferencesDialog(QHelpEngineCore *helpEngine, QWidget *parent)
+ : QDialog(parent)
+ , m_appFontChanged(false)
+ , m_browserFontChanged(false)
+{
+ m_helpEngine = helpEngine;
+ m_ui.setupUi(this);
+
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Ok),
+ SIGNAL(clicked()), this, SLOT(applyChanges()));
+ connect(m_ui.buttonBox->button(QDialogButtonBox::Cancel),
+ SIGNAL(clicked()), this, SLOT(reject()));
+
+ m_hideFiltersTab = !m_helpEngine->customValue(QLatin1String("EnableFilterFunctionality"),
+ true).toBool();
+ m_hideDocsTab = !m_helpEngine->customValue(QLatin1String("EnableDocumentationManager"),
+ true).toBool();
+
+ if (!m_hideFiltersTab) {
+ m_ui.attributeWidget->header()->hide();
+ m_ui.attributeWidget->setRootIsDecorated(false);
+ connect(m_ui.attributeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
+ this, SLOT(updateFilterMap()));
+
+ connect(m_ui.filterWidget,
+ SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
+ this, SLOT(updateAttributes(QListWidgetItem*)));
+
+ connect(m_ui.filterAddButton, SIGNAL(clicked()),
+ this, SLOT(addFilter()));
+ connect(m_ui.filterRemoveButton, SIGNAL(clicked()),
+ this, SLOT(removeFilter()));
+
+ updateFilterPage();
+ } else {
+ m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.filtersTab));
+ }
+
+ if (!m_hideDocsTab) {
+ connect(m_ui.docAddButton, SIGNAL(clicked()), this,
+ SLOT(addDocumentationLocal()));
+ connect(m_ui.docRemoveButton, SIGNAL(clicked()), this,
+ SLOT(removeDocumentation()));
+
+ m_docsBackup = m_helpEngine->registeredDocumentations();
+ m_ui.registeredDocsListWidget->addItems(m_docsBackup);
+ } else {
+ m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.docsTab));
+ }
+ updateFontSettingsPage();
+ updateOptionsPage();
+}
+
+PreferencesDialog::~PreferencesDialog()
+{
+ if (m_appFontChanged) {
+ m_helpEngine->setCustomValue(QLatin1String("appFont"), m_appFontPanel->selectedFont());
+ m_helpEngine->setCustomValue(QLatin1String("useAppFont"), m_appFontPanel->isChecked());
+ m_helpEngine->setCustomValue(QLatin1String("appWritingSystem"), m_appFontPanel->writingSystem());
+ }
+
+ if (m_browserFontChanged) {
+ m_helpEngine->setCustomValue(QLatin1String("browserFont"), m_browserFontPanel->selectedFont());
+ m_helpEngine->setCustomValue(QLatin1String("useBrowserFont"), m_browserFontPanel->isChecked());
+ m_helpEngine->setCustomValue(QLatin1String("browserWritingSystem"), m_browserFontPanel->writingSystem());
+ }
+
+ if (m_appFontChanged || m_browserFontChanged) {
+ emit updateApplicationFont();
+ emit updateBrowserFont();
+ }
+
+ if (!m_ui.homePageLineEdit->text().isEmpty())
+ m_helpEngine->setCustomValue(QLatin1String("homepage"), m_ui.homePageLineEdit->text());
+}
+
+void PreferencesDialog::showDialog()
+{
+ if (exec() != Accepted)
+ m_appFontChanged = m_browserFontChanged = false;
+}
+
+void PreferencesDialog::updateFilterPage()
+{
+ if (!m_helpEngine)
+ return;
+
+ m_ui.filterWidget->clear();
+ m_ui.attributeWidget->clear();
+
+ QHelpEngineCore help(m_helpEngine->collectionFile(), 0);
+ help.setupData();
+ m_filterMapBackup.clear();
+ const QStringList filters = help.customFilters();
+ foreach (const QString &filter, filters) {
+ QStringList atts = help.filterAttributes(filter);
+ m_filterMapBackup.insert(filter, atts);
+ if (!m_filterMap.contains(filter))
+ m_filterMap.insert(filter, atts);
+ }
+
+ m_ui.filterWidget->addItems(m_filterMap.keys());
+
+ foreach (const QString &a, help.filterAttributes())
+ new QTreeWidgetItem(m_ui.attributeWidget, QStringList() << a);
+
+ if (m_filterMap.keys().count())
+ m_ui.filterWidget->setCurrentRow(0);
+}
+
+void PreferencesDialog::updateAttributes(QListWidgetItem *item)
+{
+ QStringList checkedList;
+ if (item)
+ checkedList = m_filterMap.value(item->text());
+ QTreeWidgetItem *itm;
+ for (int i=0; i<m_ui.attributeWidget->topLevelItemCount(); ++i) {
+ itm = m_ui.attributeWidget->topLevelItem(i);
+ if (checkedList.contains(itm->text(0)))
+ itm->setCheckState(0, Qt::Checked);
+ else
+ itm->setCheckState(0, Qt::Unchecked);
+ }
+}
+
+void PreferencesDialog::updateFilterMap()
+{
+ if (!m_ui.filterWidget->currentItem())
+ return;
+ QString filter = m_ui.filterWidget->currentItem()->text();
+ if (!m_filterMap.contains(filter))
+ return;
+
+ QStringList newAtts;
+ QTreeWidgetItem *itm = 0;
+ for (int i=0; i<m_ui.attributeWidget->topLevelItemCount(); ++i) {
+ itm = m_ui.attributeWidget->topLevelItem(i);
+ if (itm->checkState(0) == Qt::Checked)
+ newAtts.append(itm->text(0));
+ }
+ m_filterMap[filter] = newAtts;
+}
+
+void PreferencesDialog::addFilter()
+{
+ FilterNameDialog dia(this);
+ if (dia.exec() == QDialog::Rejected)
+ return;
+
+ QString filterName = dia.filterName();
+ if (!m_filterMap.contains(filterName)) {
+ m_filterMap.insert(filterName, QStringList());
+ m_ui.filterWidget->addItem(filterName);
+ }
+
+ QList<QListWidgetItem*> lst = m_ui.filterWidget
+ ->findItems(filterName, Qt::MatchCaseSensitive);
+ m_ui.filterWidget->setCurrentItem(lst.first());
+}
+
+void PreferencesDialog::removeFilter()
+{
+ QListWidgetItem *item = m_ui.filterWidget
+ ->takeItem(m_ui.filterWidget->currentRow());
+ if (!item)
+ return;
+
+ m_filterMap.remove(item->text());
+ m_removedFilters.append(item->text());
+ delete item;
+ if (m_ui.filterWidget->count())
+ m_ui.filterWidget->setCurrentRow(0);
+}
+
+void PreferencesDialog::addDocumentationLocal()
+{
+ const QStringList fileNames = QFileDialog::getOpenFileNames(this,
+ tr("Add Documentation"), QString(), tr("Qt Compressed Help Files (*.qch)"));
+ if (fileNames.isEmpty())
+ return;
+
+ foreach (const QString &fileName, fileNames) {
+ const QString ns = QHelpEngineCore::namespaceName(fileName);
+ if (ns.isEmpty()) {
+ QMessageBox::warning(this, tr("Add Documentation"),
+ tr("The specified file is not a valid Qt Help File!"));
+ continue;
+ }
+
+ if (m_ui.registeredDocsListWidget->findItems(ns, Qt::MatchFixedString).count()) {
+ QMessageBox::warning(this, tr("Add Documentation"),
+ tr("The namespace %1 is already registered!").arg(ns));
+ continue;
+ }
+
+ m_helpEngine->registerDocumentation(fileName);
+ m_ui.registeredDocsListWidget->addItem(ns);
+ m_regDocs.append(ns);
+ m_unregDocs.removeAll(ns);
+ }
+ updateFilterPage();
+}
+
+void PreferencesDialog::removeDocumentation()
+{
+ bool foundBefore = false;
+ CentralWidget* widget = CentralWidget::instance();
+ QMap<int, QString> openedDocList = widget->currentSourceFileList();
+ QStringList values(openedDocList.values());
+
+ QList<QListWidgetItem*> l = m_ui.registeredDocsListWidget->selectedItems();
+ foreach (QListWidgetItem* item, l) {
+ const QString& ns = item->text();
+ if (!foundBefore && values.contains(ns)) {
+ if (0 == QMessageBox::information(this, tr("Remove Documentation"),
+ tr("Some documents currently opened in Assistant reference the "
+ "documentation you are attempting to remove. Removing the "
+ "documentation will close those documents."), tr("Cancel"),
+ tr("OK"))) return;
+ foundBefore = true;
+ }
+
+ m_unregDocs.append(ns);
+ m_TabsToClose += openedDocList.keys(ns);
+ delete m_ui.registeredDocsListWidget->takeItem(
+ m_ui.registeredDocsListWidget->row(item));
+ }
+
+ if (m_ui.registeredDocsListWidget->count()) {
+ m_ui.registeredDocsListWidget->setCurrentRow(0,
+ QItemSelectionModel::ClearAndSelect);
+ }
+}
+
+void PreferencesDialog::applyChanges()
+{
+ bool filtersWereChanged = false;
+ if (!m_hideFiltersTab) {
+ if (m_filterMap.count() != m_filterMapBackup.count()) {
+ filtersWereChanged = true;
+ } else {
+ QMapIterator<QString, QStringList> it(m_filterMapBackup);
+ while (it.hasNext() && !filtersWereChanged) {
+ it.next();
+ if (!m_filterMap.contains(it.key())) {
+ filtersWereChanged = true;
+ } else {
+ QStringList a = it.value();
+ QStringList b = m_filterMap.value(it.key());
+ if (a.count() != b.count()) {
+ filtersWereChanged = true;
+ } else {
+ QStringList::const_iterator i(a.constBegin());
+ while (i != a.constEnd()) {
+ if (!b.contains(*i)) {
+ filtersWereChanged = true;
+ break;
+ }
+ ++i;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (filtersWereChanged) {
+ foreach (const QString &filter, m_removedFilters)
+ m_helpEngine->removeCustomFilter(filter);
+ QMapIterator<QString, QStringList> it(m_filterMap);
+ while (it.hasNext()) {
+ it.next();
+ m_helpEngine->addCustomFilter(it.key(), it.value());
+ }
+ }
+
+ qSort(m_TabsToClose);
+ CentralWidget* widget = CentralWidget::instance();
+ for (int i = m_TabsToClose.count(); --i >= 0;)
+ widget->closeTabAt(m_TabsToClose.at(i));
+
+ if (m_unregDocs.count()) {
+ foreach (const QString &doc, m_unregDocs)
+ m_helpEngine->unregisterDocumentation(doc);
+ }
+
+ if (filtersWereChanged || m_regDocs.count() || m_unregDocs.count())
+ m_helpEngine->setupData();
+
+ accept();
+}
+
+void PreferencesDialog::updateFontSettingsPage()
+{
+ m_browserFontPanel = new FontPanel(this);
+ m_browserFontPanel->setCheckable(true);
+ m_ui.stackedWidget_2->insertWidget(0, m_browserFontPanel);
+
+ m_appFontPanel = new FontPanel(this);
+ m_appFontPanel->setCheckable(true);
+ m_ui.stackedWidget_2->insertWidget(1, m_appFontPanel);
+
+ m_ui.stackedWidget_2->setCurrentIndex(0);
+
+ const QString customSettings(tr("Use custom settings"));
+ QFont font = qVariantValue<QFont>(m_helpEngine->customValue(QLatin1String("appFont")));
+ QFontDatabase::WritingSystem writingSystem = static_cast<QFontDatabase::WritingSystem>
+ (m_helpEngine->customValue(QLatin1String("appWritingSystem")).toInt());
+
+ m_appFontPanel->setTitle(customSettings);
+ m_appFontPanel->setSelectedFont(font);
+ m_appFontPanel->setWritingSystem(writingSystem);
+ m_appFontPanel->setChecked(m_helpEngine->customValue(QLatin1String("useAppFont")).toBool());
+
+ QFont font2 = qVariantValue<QFont>(m_helpEngine->customValue(QLatin1String("browserFont")));
+ writingSystem = static_cast<QFontDatabase::WritingSystem>
+ (m_helpEngine->customValue(QLatin1String("browserWritingSystem")).toInt());
+
+ m_browserFontPanel->setTitle(customSettings);
+ m_browserFontPanel->setSelectedFont(font2);
+ m_browserFontPanel->setWritingSystem(writingSystem);
+ m_browserFontPanel->setChecked(m_helpEngine->customValue(QLatin1String("useBrowserFont")).toBool());
+
+ connect(m_appFontPanel, SIGNAL(toggled(bool)), this, SLOT(appFontSettingToggled(bool)));
+ connect(m_browserFontPanel, SIGNAL(toggled(bool)), this, SLOT(browserFontSettingToggled(bool)));
+
+ QList<QComboBox*> allCombos = qFindChildren<QComboBox*>(m_appFontPanel);
+ foreach (QComboBox* box, allCombos)
+ connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(appFontSettingChanged(int)));
+
+ allCombos.clear();
+ allCombos = qFindChildren<QComboBox*>(m_browserFontPanel);
+ foreach (QComboBox* box, allCombos)
+ connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(browserFontSettingChanged(int)));
+}
+
+void PreferencesDialog::appFontSettingToggled(bool on)
+{
+ Q_UNUSED(on)
+ m_appFontChanged = true;
+}
+
+void PreferencesDialog::appFontSettingChanged(int index)
+{
+ Q_UNUSED(index)
+ m_appFontChanged = true;
+}
+
+void PreferencesDialog::browserFontSettingToggled(bool on)
+{
+ Q_UNUSED(on)
+ m_browserFontChanged = true;
+}
+
+void PreferencesDialog::browserFontSettingChanged(int index)
+{
+ Q_UNUSED(index)
+ m_browserFontChanged = true;
+}
+
+void PreferencesDialog::updateOptionsPage()
+{
+ QString homepage = m_helpEngine->customValue(QLatin1String("homepage"),
+ QLatin1String("")).toString();
+
+ if (homepage.isEmpty()) {
+ homepage = m_helpEngine->customValue(QLatin1String("defaultHomepage"),
+ QLatin1String("help")).toString();
+ }
+
+ m_ui.homePageLineEdit->setText(homepage);
+ connect(m_ui.currentPageButton, SIGNAL(pressed()), this,
+ SLOT(currentHomepageChanged()));
+ connect(m_ui.restoreDefaultHomePageButton, SIGNAL(pressed()), this,
+ SLOT(restoreDefaultHomepage()));
+}
+
+void PreferencesDialog::restoreDefaultHomepage()
+{
+ QString homepage = m_helpEngine->customValue(
+ QLatin1String("defaultHomepage"), QLatin1String("help")).toString();
+ m_ui.homePageLineEdit->setText(homepage);
+}
+
+void PreferencesDialog::currentHomepageChanged()
+{
+ QString homepage = CentralWidget::instance()->currentSource().toString();
+ if (homepage.isEmpty())
+ homepage = QLatin1String("help");
+
+ m_ui.homePageLineEdit->setText(homepage);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/preferencesdialog.h b/tools/assistant/tools/assistant/preferencesdialog.h
new file mode 100644
index 0000000000..a890500d76
--- /dev/null
+++ b/tools/assistant/tools/assistant/preferencesdialog.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREFERENCESDIALOG_H
+#define PREFERENCESDIALOG_H
+
+#include <QtGui/QDialog>
+#include "ui_preferencesdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class FontPanel;
+class QHelpEngineCore;
+
+class PreferencesDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ PreferencesDialog(QHelpEngineCore *helpEngine, QWidget *parent = 0);
+ ~PreferencesDialog();
+
+ void showDialog();
+
+private slots:
+ void updateAttributes(QListWidgetItem *item);
+ void updateFilterMap();
+ void addFilter();
+ void removeFilter();
+ void addDocumentationLocal();
+ void removeDocumentation();
+ void applyChanges();
+ void appFontSettingToggled(bool on);
+ void appFontSettingChanged(int index);
+ void browserFontSettingToggled(bool on);
+ void browserFontSettingChanged(int index);
+ void restoreDefaultHomepage();
+ void currentHomepageChanged();
+
+signals:
+ void updateBrowserFont();
+ void updateApplicationFont();
+
+private:
+ void updateFilterPage();
+ void updateFontSettingsPage();
+ void updateOptionsPage();
+
+ Ui::PreferencesDialogClass m_ui;
+ QHelpEngineCore *m_helpEngine;
+ bool m_hideFiltersTab;
+ bool m_hideDocsTab;
+ QMap<QString, QStringList> m_filterMapBackup;
+ QMap<QString, QStringList> m_filterMap;
+ QStringList m_removedFilters;
+ QStringList m_docsBackup;
+ QStringList m_regDocs;
+ QStringList m_unregDocs;
+ QList<int> m_TabsToClose;
+ FontPanel *m_appFontPanel;
+ FontPanel *m_browserFontPanel;
+ bool m_appFontChanged;
+ bool m_browserFontChanged;
+};
+
+QT_END_NAMESPACE
+
+#endif // SETTINGSDIALOG_H
diff --git a/tools/assistant/tools/assistant/preferencesdialog.ui b/tools/assistant/tools/assistant/preferencesdialog.ui
new file mode 100644
index 0000000000..d848b498d2
--- /dev/null
+++ b/tools/assistant/tools/assistant/preferencesdialog.ui
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesDialogClass</class>
+ <widget class="QDialog" name="PreferencesDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>359</width>
+ <height>266</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Preferences</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="fontsTab">
+ <attribute name="title">
+ <string>Fonts</string>
+ </attribute>
+ <layout class="QGridLayout">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLabel" name="fontLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Font settings:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboBox">
+ <item>
+ <property name="text">
+ <string>Browser</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Application</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QStackedWidget" name="stackedWidget_2">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="page_4"/>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="filtersTab">
+ <attribute name="title">
+ <string>Filters</string>
+ </attribute>
+ <layout class="QGridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_2">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="text">
+ <string>Attributes:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QListWidget" name="filterWidget"/>
+ </item>
+ <item row="1" column="2" rowspan="2">
+ <widget class="QTreeWidget" name="attributeWidget">
+ <column>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="filterAddButton">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="filterRemoveButton">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="docsTab">
+ <attribute name="title">
+ <string>Documentation</string>
+ </attribute>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Registered Documentation:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListWidget" name="registeredDocsListWidget">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::ExtendedSelection</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="docAddButton">
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="docRemoveButton">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="optionsTab">
+ <attribute name="title">
+ <string>Options</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Homepage</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="homePageLineEdit"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="currentPageButton">
+ <property name="text">
+ <string>Current Page</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="restoreDefaultHomePageButton">
+ <property name="text">
+ <string>Restore to default</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>72</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>comboBox</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>stackedWidget_2</receiver>
+ <slot>setCurrentIndex(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>375</x>
+ <y>32</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>347</x>
+ <y>125</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/assistant/tools/assistant/qtdocinstaller.cpp b/tools/assistant/tools/assistant/qtdocinstaller.cpp
new file mode 100644
index 0000000000..9063847053
--- /dev/null
+++ b/tools/assistant/tools/assistant/qtdocinstaller.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDir>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDateTime>
+#include <QtHelp/QHelpEngineCore>
+#include "qtdocinstaller.h"
+
+QT_BEGIN_NAMESPACE
+
+QtDocInstaller::QtDocInstaller(const QString &collectionFile)
+{
+ m_abort = false;
+ m_collectionFile = collectionFile;
+}
+
+QtDocInstaller::~QtDocInstaller()
+{
+ if (!isRunning())
+ return;
+ m_mutex.lock();
+ m_abort = true;
+ m_mutex.unlock();
+ wait();
+}
+
+void QtDocInstaller::installDocs()
+{
+ start(LowPriority);
+}
+
+void QtDocInstaller::run()
+{
+ QHelpEngineCore *helpEngine = new QHelpEngineCore(m_collectionFile);
+ helpEngine->setupData();
+ bool changes = false;
+
+ QStringList docs;
+ docs << QLatin1String("assistant")
+ << QLatin1String("designer")
+ << QLatin1String("linguist")
+ << QLatin1String("qmake")
+ << QLatin1String("qt");
+
+ foreach (const QString &doc, docs) {
+ changes |= installDoc(doc, helpEngine);
+ m_mutex.lock();
+ if (m_abort) {
+ delete helpEngine;
+ m_mutex.unlock();
+ return;
+ }
+ m_mutex.unlock();
+ }
+ delete helpEngine;
+ emit docsInstalled(changes);
+}
+
+bool QtDocInstaller::installDoc(const QString &name, QHelpEngineCore *helpEngine)
+{
+ QString versionKey = QString(QLatin1String("qtVersion%1$$$%2")).
+ arg(QLatin1String(QT_VERSION_STR)).arg(name);
+
+ QString info = helpEngine->customValue(versionKey, QString()).toString();
+ QStringList lst = info.split(QLatin1String("|"));
+
+ QDateTime dt;
+ if (lst.count() && !lst.first().isEmpty())
+ dt = QDateTime::fromString(lst.first(), Qt::ISODate);
+
+ QString qchFile;
+ if (lst.count() == 2)
+ qchFile = lst.last();
+
+ QDir dir(QLibraryInfo::location(QLibraryInfo::DocumentationPath)
+ + QDir::separator() + QLatin1String("qch"));
+
+ const QStringList files = dir.entryList(QStringList() << QLatin1String("*.qch"));
+ if (files.isEmpty()) {
+ helpEngine->setCustomValue(versionKey, QDateTime().toString(Qt::ISODate)
+ + QLatin1String("|"));
+ return false;
+ }
+ foreach (const QString &f, files) {
+ if (f.startsWith(name)) {
+ QFileInfo fi(dir.absolutePath() + QDir::separator() + f);
+ if (dt.isValid() && fi.lastModified().toString(Qt::ISODate) == dt.toString(Qt::ISODate)
+ && qchFile == fi.absoluteFilePath())
+ return false;
+
+ QString namespaceName = QHelpEngineCore::namespaceName(fi.absoluteFilePath());
+ if (namespaceName.isEmpty())
+ continue;
+
+ if (helpEngine->registeredDocumentations().contains(namespaceName))
+ helpEngine->unregisterDocumentation(namespaceName);
+
+ if (!helpEngine->registerDocumentation(fi.absoluteFilePath())) {
+ emit errorMessage(
+ tr("The file %1 could not be registered successfully!\n\nReason: %2")
+ .arg(fi.absoluteFilePath()).arg(helpEngine->error()));
+ }
+
+ helpEngine->setCustomValue(versionKey, fi.lastModified().toString(Qt::ISODate)
+ + QLatin1String("|") + fi.absoluteFilePath());
+ return true;
+ }
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/qtdocinstaller.h b/tools/assistant/tools/assistant/qtdocinstaller.h
new file mode 100644
index 0000000000..a8a98fac0a
--- /dev/null
+++ b/tools/assistant/tools/assistant/qtdocinstaller.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTDOCINSTALLER
+#define QTDOCINSTALLER
+
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpEngineCore;
+
+class QtDocInstaller : public QThread
+{
+ Q_OBJECT
+
+public:
+ QtDocInstaller(const QString &collectionFile);
+ ~QtDocInstaller();
+ void installDocs();
+
+signals:
+ void errorMessage(const QString &msg);
+ void docsInstalled(bool newDocsInstalled);
+
+private:
+ void run();
+ bool installDoc(const QString &name,
+ QHelpEngineCore *helpEngine);
+
+ bool m_abort;
+ QString m_collectionFile;
+ QMutex m_mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/assistant/remotecontrol.cpp b/tools/assistant/tools/assistant/remotecontrol.cpp
new file mode 100644
index 0000000000..f3745380de
--- /dev/null
+++ b/tools/assistant/tools/assistant/remotecontrol.cpp
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "remotecontrol.h"
+#include "mainwindow.h"
+#include "centralwidget.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QThread>
+#include <QtCore/QTextStream>
+#include <QtCore/QSocketNotifier>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QApplication>
+
+#include <QtHelp/QHelpEngine>
+#include <QtHelp/QHelpIndexWidget>
+
+#ifdef Q_OS_WIN
+# include "remotecontrol_win.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+
+StdInListenerWin::StdInListenerWin(QObject *parent)
+ : QThread(parent)
+{
+}
+
+StdInListenerWin::~StdInListenerWin()
+{
+ terminate();
+ wait();
+}
+
+void StdInListenerWin::run()
+{
+ bool ok = true;
+ char chBuf[4096];
+ DWORD dwRead;
+ HANDLE hStdin, hStdinDup;
+
+ hStdin = GetStdHandle(STD_INPUT_HANDLE);
+ if (hStdin == INVALID_HANDLE_VALUE)
+ return;
+
+ DuplicateHandle(GetCurrentProcess(), hStdin,
+ GetCurrentProcess(), &hStdinDup,
+ 0, false, DUPLICATE_SAME_ACCESS);
+
+ CloseHandle(hStdin);
+
+ while (ok) {
+ ok = ReadFile(hStdinDup, chBuf, 4096, &dwRead, NULL);
+ if (ok && dwRead != 0)
+ emit receivedCommand(QString::fromLocal8Bit(chBuf));
+ }
+}
+#endif
+
+RemoteControl::RemoteControl(MainWindow *mainWindow, QHelpEngine *helpEngine)
+ : QObject(mainWindow)
+ , m_mainWindow(mainWindow)
+ , m_helpEngine(helpEngine)
+ , m_debug(false)
+ , m_caching(true)
+ , m_syncContents(false)
+ , m_expandTOC(-3)
+
+{
+ connect(m_mainWindow, SIGNAL(initDone()), this, SLOT(applyCache()));
+#ifdef Q_OS_WIN
+ StdInListenerWin *l = new StdInListenerWin(this);
+ connect(l, SIGNAL(receivedCommand(const QString&)),
+ this, SLOT(handleCommandString(const QString&)));
+ l->start();
+#else
+ QSocketNotifier *notifier = new QSocketNotifier(fileno(stdin),
+ QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(receivedData()));
+ notifier->setEnabled(true);
+#endif
+}
+
+void RemoteControl::receivedData()
+{
+ QByteArray ba;
+ while (true) {
+ char c = getc(stdin);
+ if (c == EOF || c == '\0')
+ break;
+ if (c)
+ ba.append(c);
+ if (c == '\n')
+ break;
+ }
+ handleCommandString(QString::fromLocal8Bit(ba));
+}
+
+void RemoteControl::handleCommandString(const QString &cmdString)
+{
+ QStringList cmds = cmdString.split(QLatin1Char(';'));
+ QStringList::const_iterator it = cmds.constBegin();
+ QString cmdLine, cmd, arg;
+ while (it != cmds.constEnd()) {
+ cmdLine = (*it).trimmed();
+ cmd = cmdLine;
+ arg.clear();
+ int i = cmdLine.indexOf(QLatin1Char(' '));
+ if (i > 0) {
+ cmd = cmdLine.left(i);
+ arg = cmdLine.mid(i+1);
+ }
+ cmd = cmd.toLower();
+
+ if (m_debug)
+ QMessageBox::information(0, tr("Debugging Remote Control"),
+ tr("Received Command: %1 %2").arg(cmd).arg(arg));
+
+ if (cmd == QLatin1String("debug")) {
+ if (arg == QLatin1String("on"))
+ m_debug = true;
+ else
+ m_debug = false;
+ } else if (cmd == QLatin1String("show")) {
+ if (arg.toLower() == QLatin1String("contents")) {
+ m_mainWindow->showContents();
+ } else if (arg.toLower() == QLatin1String("index")) {
+ m_mainWindow->showIndex();
+ } else if (arg.toLower() == QLatin1String("bookmarks")) {
+ m_mainWindow->showBookmarks();
+ } else if (arg.toLower() == QLatin1String("search")) {
+ m_mainWindow->showSearch();
+ }
+ } else if (cmd == QLatin1String("hide")) {
+ if (arg.toLower() == QLatin1String("contents")) {
+ m_mainWindow->hideContents();
+ } else if (arg.toLower() == QLatin1String("index")) {
+ m_mainWindow->hideIndex();
+ } else if (arg.toLower() == QLatin1String("bookmarks")) {
+ m_mainWindow->hideBookmarks();
+ } else if (arg.toLower() == QLatin1String("search")) {
+ m_mainWindow->hideSearch();
+ }
+ } else if (cmd == QLatin1String("setsource")) {
+ QUrl url(arg);
+ if (url.isValid()) {
+ if (url.isRelative())
+ url = CentralWidget::instance()->currentSource().resolved(url);
+ if (m_caching) {
+ clearCache();
+ m_setSource = url;
+ } else {
+ CentralWidget::instance()->setSource(url);
+ }
+ }
+ } else if (cmd == QLatin1String("synccontents")) {
+ if (m_caching)
+ m_syncContents = true;
+ else
+ m_mainWindow->syncContents();
+ } else if (cmd == QLatin1String("activatekeyword")) {
+ if (m_caching) {
+ clearCache();
+ m_activateKeyword = arg;
+ } else {
+ m_mainWindow->setIndexString(arg);
+ if (!arg.isEmpty())
+ m_helpEngine->indexWidget()->activateCurrentItem();
+ }
+ } else if (cmd == QLatin1String("activateidentifier")) {
+ if (m_caching) {
+ clearCache();
+ m_activateIdentifier = arg;
+ } else {
+ QMap<QString, QUrl> links =
+ m_helpEngine->linksForIdentifier(arg);
+ if (links.count())
+ CentralWidget::instance()->setSource(links.constBegin().value());
+ }
+ } else if (cmd == QLatin1String("expandtoc")) {
+ bool ok = false;
+ int depth = -1;
+ if (!arg.isEmpty())
+ depth = arg.toInt(&ok);
+ if (!ok)
+ depth = -1;
+
+ if (m_caching)
+ m_expandTOC = depth;
+ else
+ m_mainWindow->expandTOC(depth);
+ } else if (cmd == QLatin1String("setcurrentfilter")) {
+ if (m_caching) {
+ clearCache();
+ m_currentFilter = arg;
+ } else {
+ m_helpEngine->setCurrentFilter(arg);
+ }
+ } else {
+ return;
+ }
+ ++it;
+ }
+ m_mainWindow->raise();
+ m_mainWindow->activateWindow();
+}
+
+void RemoteControl::applyCache()
+{
+ if (m_setSource.isValid()) {
+ CentralWidget::instance()->setSource(m_setSource);
+ } else if (!m_activateKeyword.isEmpty()) {
+ m_mainWindow->setIndexString(m_activateKeyword);
+ m_helpEngine->indexWidget()->activateCurrentItem();
+ } else if (!m_activateIdentifier.isEmpty()) {
+ QMap<QString, QUrl> links =
+ m_helpEngine->linksForIdentifier(m_activateIdentifier);
+ if (links.count())
+ CentralWidget::instance()->setSource(links.constBegin().value());
+ } else if (!m_currentFilter.isEmpty()) {
+ m_helpEngine->setCurrentFilter(m_currentFilter);
+ }
+
+ if (m_syncContents)
+ m_mainWindow->syncContents();
+
+ if (m_expandTOC != -3)
+ m_mainWindow->expandTOC(m_expandTOC);
+
+ m_caching = false;
+}
+
+void RemoteControl::clearCache()
+{
+ m_currentFilter.clear();
+ m_setSource.clear();
+ m_syncContents = false;
+ m_activateKeyword.clear();
+ m_activateIdentifier.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/remotecontrol.h b/tools/assistant/tools/assistant/remotecontrol.h
new file mode 100644
index 0000000000..3c7c6c5fde
--- /dev/null
+++ b/tools/assistant/tools/assistant/remotecontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REMOTECONTROL_H
+#define REMOTECONTROL_H
+
+#include <QtCore/QObject>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+class MainWindow;
+class QHelpEngine;
+
+class RemoteControl : public QObject
+{
+ Q_OBJECT
+
+public:
+ RemoteControl(MainWindow *mainWindow, QHelpEngine *helpEngine);
+
+private slots:
+ void receivedData();
+ void handleCommandString(const QString &cmdString);
+ void applyCache();
+
+private:
+ void clearCache();
+
+private:
+ MainWindow *m_mainWindow;
+ QHelpEngine *m_helpEngine;
+ bool m_debug;
+
+ bool m_caching;
+ QUrl m_setSource;
+ bool m_syncContents;
+ QString m_activateKeyword;
+ QString m_activateIdentifier;
+ int m_expandTOC;
+ QString m_currentFilter;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/assistant/remotecontrol_win.h b/tools/assistant/tools/assistant/remotecontrol_win.h
new file mode 100644
index 0000000000..081eb25f66
--- /dev/null
+++ b/tools/assistant/tools/assistant/remotecontrol_win.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REMOTECONTROL_WIN_H
+#define REMOTECONTROL_WIN_H
+
+#include <windows.h>
+#include <QtCore/QThread>
+
+QT_BEGIN_NAMESPACE
+
+class StdInListenerWin : public QThread
+{
+ Q_OBJECT
+
+public:
+ StdInListenerWin(QObject *parent);
+ ~StdInListenerWin();
+
+signals:
+ void receivedCommand(const QString &cmd);
+
+private:
+ void run();
+ bool ok;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/assistant/searchwidget.cpp b/tools/assistant/tools/assistant/searchwidget.cpp
new file mode 100644
index 0000000000..000c73daf7
--- /dev/null
+++ b/tools/assistant/tools/assistant/searchwidget.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "searchwidget.h"
+
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+#include <QtGui/QMenu>
+#include <QtGui/QLayout>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QClipboard>
+#include <QtGui/QApplication>
+#include <QtGui/QTextBrowser>
+
+#include <QtHelp/QHelpSearchEngine>
+#include <QtHelp/QHelpSearchQueryWidget>
+#include <QtHelp/QHelpSearchResultWidget>
+
+QT_BEGIN_NAMESPACE
+
+SearchWidget::SearchWidget(QHelpSearchEngine *engine, QWidget *parent)
+ : QWidget(parent)
+ , zoomCount(0)
+ , searchEngine(engine)
+{
+ QVBoxLayout *vLayout = new QVBoxLayout(this);
+
+ resultWidget = searchEngine->resultWidget();
+ QHelpSearchQueryWidget *queryWidget = searchEngine->queryWidget();
+
+ vLayout->addWidget(queryWidget);
+ vLayout->addWidget(resultWidget);
+
+ setFocusProxy(queryWidget);
+
+ connect(queryWidget, SIGNAL(search()), this, SLOT(search()));
+ connect(resultWidget, SIGNAL(requestShowLink(const QUrl&)),
+ this, SIGNAL(requestShowLink(const QUrl&)));
+
+ connect(searchEngine, SIGNAL(searchingStarted()), this, SLOT(searchingStarted()));
+ connect(searchEngine, SIGNAL(searchingFinished(int)), this, SLOT(searchingFinished(int)));
+
+ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
+ browser->viewport()->installEventFilter(this);
+}
+
+SearchWidget::~SearchWidget()
+{
+ // nothing todo
+}
+
+void SearchWidget::zoomIn()
+{
+#ifndef QT_CLUCENE_SUPPORT
+ return;
+#endif
+
+ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
+ if (browser && zoomCount != 10) {
+ zoomCount++;
+ browser->zoomIn();
+ }
+}
+
+void SearchWidget::zoomOut()
+{
+#ifndef QT_CLUCENE_SUPPORT
+ return;
+#endif
+
+ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
+ if (browser && zoomCount != -5) {
+ zoomCount--;
+ browser->zoomOut();
+ }
+}
+
+void SearchWidget::resetZoom()
+{
+#ifndef QT_CLUCENE_SUPPORT
+ return;
+#endif
+
+ if (zoomCount == 0)
+ return;
+
+ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
+ if (browser) {
+ browser->zoomOut(zoomCount);
+ zoomCount = 0;
+ }
+}
+
+void SearchWidget::search() const
+{
+ QList<QHelpSearchQuery> query = searchEngine->queryWidget()->query();
+ searchEngine->search(query);
+}
+
+void SearchWidget::searchingStarted()
+{
+ qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+}
+
+void SearchWidget::searchingFinished(int hits)
+{
+ Q_UNUSED(hits)
+ qApp->restoreOverrideCursor();
+}
+
+bool SearchWidget::eventFilter(QObject* o, QEvent *e)
+{
+ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
+ if (browser && o == browser->viewport() && e->type() == QEvent::MouseButtonRelease){
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ QUrl link = resultWidget->linkAt(me->pos());
+ if (!link.isEmpty() || link.isValid()) {
+ bool controlPressed = me->modifiers() & Qt::ControlModifier;
+ if((me->button() == Qt::LeftButton && controlPressed)
+ || (me->button() == Qt::MidButton)) {
+ emit requestShowLinkInNewTab(link);
+ }
+ }
+ }
+ return QWidget::eventFilter(o,e);
+}
+
+void SearchWidget::keyPressEvent(QKeyEvent *keyEvent)
+{
+ if (keyEvent->key() == Qt::Key_Escape)
+ MainWindow::activateCurrentBrowser();
+ else
+ keyEvent->ignore();
+}
+
+void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent)
+{
+ QMenu menu;
+ QPoint point = contextMenuEvent->globalPos();
+
+#ifdef QT_CLUCENE_SUPPORT
+ QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
+ if (!browser)
+ return;
+
+ point = browser->mapFromGlobal(point);
+ if (!browser->rect().contains(point, true))
+ return;
+
+ QUrl link = browser->anchorAt(point);
+
+ QAction *copyAction = menu.addAction(tr("&Copy") +
+ QString(QLatin1String("\t") + QString(QKeySequence(Qt::CTRL | Qt::Key_C))));
+ copyAction->setEnabled(QTextCursor(browser->textCursor()).hasSelection());
+
+ QAction *copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
+ copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid());
+
+ QAction *newTabAction = menu.addAction(tr("Open Link in New Tab") +
+ QString(QLatin1String("\t") + QString(QKeySequence(Qt::CTRL))) +
+ QLatin1String("LMB"));
+ newTabAction->setEnabled(!link.isEmpty() && link.isValid());
+
+ menu.addSeparator();
+
+ QAction *selectAllAction = menu.addAction(tr("Select All") +
+ QString(QLatin1String("\t") + QString(QKeySequence(Qt::CTRL | Qt::Key_A))));
+
+ QAction *usedAction = menu.exec(mapToGlobal(contextMenuEvent->pos()));
+ if (usedAction == copyAction) {
+ QTextCursor cursor = browser->textCursor();
+ if (!cursor.isNull() && cursor.hasSelection()) {
+ QString selectedText = cursor.selectedText();
+ QMimeData *data = new QMimeData();
+ data->setText(selectedText);
+ QApplication::clipboard()->setMimeData(data);
+ }
+ }
+ else if (usedAction == copyAnchorAction) {
+ QApplication::clipboard()->setText(link.toString());
+ }
+ else if (usedAction == newTabAction) {
+ emit requestShowLinkInNewTab(link);
+ }
+ else if (usedAction == selectAllAction) {
+ browser->selectAll();
+ }
+#else
+ point = resultWidget->mapFromGlobal(point);
+ QUrl link = resultWidget->linkAt(point);
+ if (link.isEmpty() || !link.isValid())
+ return;
+
+ QAction *curTab = menu.addAction(tr("Open Link"));
+ QAction *newTab = menu.addAction(tr("Open Link in New Tab"));
+
+ QAction *action = menu.exec(mapToGlobal(contextMenuEvent->pos()));
+ if (curTab == action)
+ emit requestShowLink(link);
+ else if (newTab == action)
+ emit requestShowLinkInNewTab(link);
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/searchwidget.h b/tools/assistant/tools/assistant/searchwidget.h
new file mode 100644
index 0000000000..22fe80d823
--- /dev/null
+++ b/tools/assistant/tools/assistant/searchwidget.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SEARCHWIDGET_H
+#define SEARCHWIDGET_H
+
+#include <QtCore/QUrl>
+#include <QtCore/QPoint>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QMouseEvent;
+class QHelpSearchEngine;
+class QHelpSearchResultWidget;
+
+class SearchWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ SearchWidget(QHelpSearchEngine *engine, QWidget *parent = 0);
+ ~SearchWidget();
+
+ void zoomIn();
+ void zoomOut();
+ void resetZoom();
+
+signals:
+ void requestShowLink(const QUrl &url);
+ void requestShowLinkInNewTab(const QUrl &url);
+
+private slots:
+ void search() const;
+ void searchingStarted();
+ void searchingFinished(int hits);
+
+private:
+ bool eventFilter(QObject* o, QEvent *e);
+ void keyPressEvent(QKeyEvent *keyEvent);
+ void contextMenuEvent(QContextMenuEvent *contextMenuEvent);
+
+private:
+ int zoomCount;
+ QHelpSearchEngine *searchEngine;
+ QHelpSearchResultWidget *resultWidget;
+};
+
+QT_END_NAMESPACE
+
+#endif // SEARCHWIDGET_H
diff --git a/tools/assistant/tools/assistant/topicchooser.cpp b/tools/assistant/tools/assistant/topicchooser.cpp
new file mode 100644
index 0000000000..3f30417ea5
--- /dev/null
+++ b/tools/assistant/tools/assistant/topicchooser.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QMap>
+#include <QtCore/QUrl>
+
+#include "topicchooser.h"
+
+QT_BEGIN_NAMESPACE
+
+TopicChooser::TopicChooser(QWidget *parent, const QString &keyword,
+ const QMap<QString, QUrl> &links)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+ ui.label->setText(tr("Choose a topic for <b>%1</b>:").arg(keyword));
+
+ m_links = links;
+ QMap<QString, QUrl>::const_iterator it = m_links.constBegin();
+ for (; it != m_links.constEnd(); ++it)
+ ui.listWidget->addItem(it.key());
+
+ if (ui.listWidget->count() != 0)
+ ui.listWidget->setCurrentRow(0);
+ ui.listWidget->setFocus();
+
+ connect(ui.buttonDisplay, SIGNAL(clicked()),
+ this, SLOT(accept()));
+ connect(ui.buttonCancel, SIGNAL(clicked()),
+ this, SLOT(reject()));
+ connect(ui.listWidget, SIGNAL(itemActivated(QListWidgetItem*)),
+ this, SLOT(accept()));
+}
+
+QUrl TopicChooser::link() const
+{
+ QListWidgetItem *item = ui.listWidget->currentItem();
+ if (!item)
+ return QUrl();
+
+ QString title = item->text();
+ if (title.isEmpty() || !m_links.contains(title))
+ return QUrl();
+
+ return m_links.value(title);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/topicchooser.h b/tools/assistant/tools/assistant/topicchooser.h
new file mode 100644
index 0000000000..58b3796f4c
--- /dev/null
+++ b/tools/assistant/tools/assistant/topicchooser.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOPICCHOOSER_H
+#define TOPICCHOOSER_H
+
+#include "ui_topicchooser.h"
+
+#include <QUrl>
+#include <QMap>
+#include <QString>
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class TopicChooser : public QDialog
+{
+ Q_OBJECT
+
+public:
+ TopicChooser(QWidget *parent, const QString &keyword,
+ const QMap<QString, QUrl> &links);
+
+ QUrl link() const;
+
+private:
+ Ui::TopicChooser ui;
+ QMap<QString, QUrl> m_links;
+};
+
+QT_END_NAMESPACE
+
+#endif // TOPICCHOOSER_H
diff --git a/tools/assistant/tools/assistant/topicchooser.ui b/tools/assistant/tools/assistant/topicchooser.ui
new file mode 100644
index 0000000000..d4c90bb4b3
--- /dev/null
+++ b/tools/assistant/tools/assistant/topicchooser.ui
@@ -0,0 +1,116 @@
+<UI version="4.0" stdsetdef="1" >
+ <class>TopicChooser</class>
+ <widget class="QDialog" name="TopicChooser" >
+ <property name="objectName" >
+ <string notr="true">TopicChooser</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>391</width>
+ <height>223</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Choose Topic</string>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true">unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="objectName" >
+ <string notr="true">label</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Topics</string>
+ </property>
+ <property name="buddy" stdset="0" >
+ <cstring>listWidget</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listWidget" >
+ <property name="objectName" >
+ <string notr="true">listWidget</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="Layout16" >
+ <property name="objectName" >
+ <string notr="true">Layout16</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true">unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer name="Horizontal Spacing2" >
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="sizeType" >
+ <enum>Expanding</enum>
+ </property>
+ <property name="orientation" >
+ <enum>Horizontal</enum>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonDisplay" >
+ <property name="objectName" >
+ <string notr="true">buttonDisplay</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Display</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonCancel" >
+ <property name="objectName" >
+ <string notr="true">buttonCancel</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Close</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+</UI>
diff --git a/tools/assistant/tools/qcollectiongenerator/main.cpp b/tools/assistant/tools/qcollectiongenerator/main.cpp
new file mode 100644
index 0000000000..68db53ff63
--- /dev/null
+++ b/tools/assistant/tools/qcollectiongenerator/main.cpp
@@ -0,0 +1,559 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/helpgenerator.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QMap>
+#include <QtCore/QFileInfo>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDateTime>
+#include <QtCore/QBuffer>
+
+#include <private/qhelpgenerator_p.h>
+#include <private/qhelpprojectdata_p.h>
+#include <QtHelp/QHelpEngineCore>
+
+#include <QtXml/QXmlStreamReader>
+
+QT_USE_NAMESPACE
+
+class CollectionConfigReader : public QXmlStreamReader
+{
+public:
+ void readData(const QByteArray &contents);
+
+ QString title() const { return m_title; }
+ QString homePage() const { return m_homePage; }
+ QString startPage() const { return m_startPage; }
+ QString applicationIcon() const { return m_applicationIcon; }
+ QString currentFilter() const { return m_currentFilter; }
+ bool enableFilterFunctionality() const
+ { return m_enableFilterFunctionality; }
+ bool hideFilterFunctionality() const
+ { return m_hideFilterFunctionality; }
+ bool enableAddressBar() const { return m_enableAddressBar; }
+ bool hideAddressBar() const { return m_hideAddressBar; }
+ bool enableDocumentationManager() const
+ { return m_enableDocumentationManager; }
+
+ QMap<QString, QString> aboutMenuTexts() const
+ { return m_aboutMenuTexts; }
+ QString aboutIcon() const { return m_aboutIcon; }
+ QMap<QString, QString> aboutTextFiles() const
+ { return m_aboutTextFiles; }
+
+ QMap<QString, QString> filesToGenerate() const
+ { return m_filesToGenerate; }
+
+ QStringList filesToRegister() const { return m_filesToRegister; }
+
+ QString cacheDirectory() const { return m_cacheDirectory; }
+
+private:
+ void raiseErrorWithLine();
+ void readConfig();
+ void readAssistantSettings();
+ void readMenuTexts();
+ void readAboutDialog();
+ void readDocFiles();
+ void readGenerate();
+ void readFiles();
+ void readRegister();
+
+ QString m_title;
+ QString m_homePage;
+ QString m_startPage;
+ QString m_applicationIcon;
+ QString m_currentFilter;
+ bool m_enableFilterFunctionality;
+ bool m_hideFilterFunctionality;
+ bool m_enableAddressBar;
+ bool m_hideAddressBar;
+ bool m_enableDocumentationManager;
+ QMap<QString, QString> m_aboutMenuTexts;
+ QString m_aboutIcon;
+ QMap<QString, QString> m_aboutTextFiles;
+ QMap<QString, QString> m_filesToGenerate;
+ QStringList m_filesToRegister;
+ QString m_cacheDirectory;
+};
+
+void CollectionConfigReader::raiseErrorWithLine()
+{
+ raiseError(QObject::tr("Unknown token at line %1.")
+ .arg(lineNumber()));
+}
+
+void CollectionConfigReader::readData(const QByteArray &contents)
+{
+ m_enableFilterFunctionality = true;
+ m_hideFilterFunctionality = true;
+ m_enableAddressBar = true;
+ m_hideAddressBar = true;
+ m_enableDocumentationManager = true;
+
+ addData(contents);
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("QHelpCollectionProject")
+ && attributes().value(QLatin1String("version")) == QLatin1String("1.0"))
+ readConfig();
+ else
+ raiseError(QObject::tr("Unknown token at line %1. Expected \"QtHelpCollectionProject\"!")
+ .arg(lineNumber()));
+ }
+ }
+}
+
+void CollectionConfigReader::readConfig()
+{
+ bool ok = false;
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("assistant"))
+ readAssistantSettings();
+ else if (name() == QLatin1String("docFiles"))
+ readDocFiles();
+ else
+ raiseErrorWithLine();
+ } else if (isEndElement() && name() == QLatin1String("QHelpCollectionProject")) {
+ ok = true;
+ }
+ }
+ if (!ok && !hasError())
+ raiseError(QLatin1String("Missing end tags."));
+}
+
+void CollectionConfigReader::readAssistantSettings()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("title")) {
+ m_title = readElementText();
+ } else if (name() == QLatin1String("homePage")) {
+ m_homePage = readElementText();
+ } else if (name() == QLatin1String("startPage")) {
+ m_startPage = readElementText();
+ } else if (name() == QLatin1String("currentFilter")) {
+ m_currentFilter = readElementText();
+ } else if (name() == QLatin1String("applicationIcon")) {
+ m_applicationIcon = readElementText();
+ } else if (name() == QLatin1String("enableFilterFunctionality")) {
+ if (attributes().value(QLatin1String("visible")) == QLatin1String("true"))
+ m_hideFilterFunctionality = false;
+ if (readElementText() == QLatin1String("false"))
+ m_enableFilterFunctionality = false;
+ } else if (name() == QLatin1String("enableDocumentationManager")) {
+ if (readElementText() == QLatin1String("false"))
+ m_enableDocumentationManager = false;
+ } else if (name() == QLatin1String("enableAddressBar")) {
+ if (attributes().value(QLatin1String("visible")) == QLatin1String("true"))
+ m_hideAddressBar = false;
+ if (readElementText() == QLatin1String("false"))
+ m_enableAddressBar = false;
+ } else if (name() == QLatin1String("aboutMenuText")) {
+ readMenuTexts();
+ } else if (name() == QLatin1String("aboutDialog")) {
+ readAboutDialog();
+ } else if (name() == "cacheDirectory") {
+ m_cacheDirectory = readElementText();
+ } else {
+ raiseErrorWithLine();
+ }
+ } else if (isEndElement() && name() == QLatin1String("assistant")) {
+ break;
+ }
+ }
+}
+
+void CollectionConfigReader::readMenuTexts()
+{
+ while (!atEnd())
+ {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("text")) {
+ QString lang = attributes().value(QLatin1String("language")).toString();
+ if (lang.isEmpty())
+ lang = QLatin1String("default");
+ m_aboutMenuTexts.insert(lang, readElementText());
+ } else {
+ raiseErrorWithLine();
+ }
+ } else if (isEndElement() && name() == QLatin1String("aboutMenuText")) {
+ break;
+ }
+ }
+}
+
+void CollectionConfigReader::readAboutDialog()
+{
+ while (!atEnd())
+ {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("file")) {
+ QString lang = attributes().value(QLatin1String("language")).toString();
+ if (lang.isEmpty())
+ lang = QLatin1String("default");
+ m_aboutTextFiles.insert(lang, readElementText());
+ } else if (name() == QLatin1String("icon")) {
+ m_aboutIcon = readElementText();
+ } else {
+ raiseErrorWithLine();
+ }
+ } else if (isEndElement() && name() == QLatin1String("aboutDialog")) {
+ break;
+ }
+ }
+}
+
+void CollectionConfigReader::readDocFiles()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("generate")) {
+ readGenerate();
+ } else if (name() == QLatin1String("register")) {
+ readRegister();
+ } else {
+ raiseErrorWithLine();
+ }
+ } else if (isEndElement() && name() == QLatin1String("docFiles")) {
+ break;
+ }
+ }
+}
+
+void CollectionConfigReader::readGenerate()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("file"))
+ readFiles();
+ else
+ raiseErrorWithLine();
+ } else if (isEndElement() && name() == QLatin1String("generate")) {
+ break;
+ }
+ }
+}
+
+void CollectionConfigReader::readFiles()
+{
+ QString input;
+ QString output;
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("input"))
+ input = readElementText();
+ else if (name() == QLatin1String("output"))
+ output = readElementText();
+ else
+ raiseErrorWithLine();
+ } else if (isEndElement() && name() == QLatin1String("file")) {
+ break;
+ }
+ }
+ if (input.isEmpty() || output.isEmpty()) {
+ raiseError(QLatin1String("Missing input or output file for help file generation!"));
+ return;
+ }
+ m_filesToGenerate.insert(input, output);
+}
+
+void CollectionConfigReader::readRegister()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("file"))
+ m_filesToRegister.append(readElementText());
+ else
+ raiseErrorWithLine();
+ } else if (isEndElement() && name() == QLatin1String("register")) {
+ break;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ QString error;
+ QString arg;
+ QString collectionFile;
+ QString configFile;
+ QString basePath;
+ bool showHelp = false;
+ bool showVersion = false;
+
+ for (int i=1; i<argc; ++i) {
+ arg = QString::fromLocal8Bit(argv[i]);
+ if (arg == QLatin1String("-o")) {
+ if (++i < argc) {
+ QFileInfo fi(QString::fromLocal8Bit(argv[i]));
+ collectionFile = fi.absoluteFilePath();
+ } else {
+ error = QObject::tr("Missing output file name!");
+ }
+ } else if (arg == QLatin1String("-h")) {
+ showHelp = true;
+ } else if (arg == QLatin1String("-v")) {
+ showVersion = true;
+ } else {
+ QFileInfo fi(arg);
+ configFile = fi.absoluteFilePath();
+ basePath = fi.absolutePath();
+ }
+ }
+
+ if (showVersion) {
+ fprintf(stdout, "Qt Collection Generator version 1.0 (Qt %s)\n", QT_VERSION_STR);
+ return 0;
+ }
+
+ if (configFile.isEmpty() && !showHelp)
+ error = QObject::tr("Missing collection config file!");
+
+ QString help = QObject::tr("\nUsage:\n\n"
+ "qcollectiongenerator <collection-config-file> [options]\n\n"
+ " -o <collection-file> Generates a collection file\n"
+ " called <collection-file>. If\n"
+ " this option is not specified\n"
+ " a default name will be used.\n"
+ " -v Displays the version of\n"
+ " qcollectiongenerator.\n\n");
+
+ if (showHelp) {
+ fprintf(stdout, "%s", qPrintable(help));
+ return 0;
+ }else if (!error.isEmpty()) {
+ fprintf(stderr, "%s\n\n%s", qPrintable(error), qPrintable(help));
+ return -1;
+ }
+
+ QFile file(configFile);
+ if (!file.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "Could not open %s!\n", qPrintable(configFile));
+ return -1;
+ }
+
+ if (collectionFile.isEmpty()) {
+ QFileInfo fi(configFile);
+ collectionFile = basePath + QDir::separator()
+ + fi.baseName() + QLatin1String(".qhc");
+ }
+
+ QCoreApplication app(argc, argv);
+
+ fprintf(stdout, "Reading collection config file...\n");
+ CollectionConfigReader config;
+ config.readData(file.readAll());
+ if (config.hasError()) {
+ fprintf(stderr, "Collection config file error: %s\n", qPrintable(config.errorString()));
+ return -1;
+ }
+
+ QMap<QString, QString>::const_iterator it = config.filesToGenerate().constBegin();
+ while (it != config.filesToGenerate().constEnd()) {
+ fprintf(stdout, "Generating help for %s...\n", qPrintable(it.key()));
+ QHelpProjectData helpData;
+ if (!helpData.readData(basePath + QDir::separator() + it.key())) {
+ fprintf(stderr, "%s\n", qPrintable(helpData.errorMessage()));
+ return -1;
+ }
+
+ HelpGenerator helpGenerator;
+ if (!helpGenerator.generate(&helpData, basePath + QDir::separator() + it.value())) {
+ fprintf(stderr, "%s\n", qPrintable(helpGenerator.error()));
+ return -1;
+ }
+ ++it;
+ }
+
+ fprintf(stdout, "Creating collection file...\n");
+
+ QFileInfo colFi(collectionFile);
+ if (colFi.exists()) {
+ if (!colFi.dir().remove(colFi.fileName())) {
+ fprintf(stderr, "The file %s cannot be overwritten!\n", qPrintable(collectionFile));
+ return -1;
+ }
+ }
+
+ QHelpEngineCore helpEngine(collectionFile);
+ if (!helpEngine.setupData()) {
+ fprintf(stderr, "%s\n", qPrintable(helpEngine.error()));
+ return -1;
+ }
+
+ foreach (const QString &file, config.filesToRegister()) {
+ if (!helpEngine.registerDocumentation(basePath + QDir::separator() + file)) {
+ fprintf(stderr, "%s\n", qPrintable(helpEngine.error()));
+ return -1;
+ }
+ }
+
+ if (!config.title().isEmpty())
+ helpEngine.setCustomValue(QLatin1String("WindowTitle"), config.title());
+
+ if (!config.homePage().isEmpty()) {
+ helpEngine.setCustomValue(QLatin1String("defaultHomepage"),
+ config.homePage());
+ }
+
+ if (!config.startPage().isEmpty())
+ helpEngine.setCustomValue(QLatin1String("LastShownPages"), config.startPage());
+
+ if (!config.currentFilter().isEmpty())
+ helpEngine.setCustomValue(QLatin1String("CurrentFilter"), config.currentFilter());
+
+ if (!config.cacheDirectory().isEmpty())
+ helpEngine.setCustomValue(QLatin1String("CacheDirectory"), config.cacheDirectory());
+
+ helpEngine.setCustomValue(QLatin1String("EnableFilterFunctionality"),
+ config.enableFilterFunctionality());
+ helpEngine.setCustomValue(QLatin1String("HideFilterFunctionality"),
+ config.hideFilterFunctionality());
+ helpEngine.setCustomValue(QLatin1String("EnableDocumentationManager"),
+ config.enableDocumentationManager());
+ helpEngine.setCustomValue(QLatin1String("EnableAddressBar"),
+ config.enableAddressBar());
+ helpEngine.setCustomValue(QLatin1String("HideAddressBar"),
+ config.hideAddressBar());
+ helpEngine.setCustomValue(QLatin1String("CreationTime"),
+ QDateTime::currentDateTime().toTime_t());
+
+ if (!config.applicationIcon().isEmpty()) {
+ QFile icon(basePath + QDir::separator() + config.applicationIcon());
+ if (!icon.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "Cannot open %s!\n", qPrintable(icon.fileName()));
+ return -1;
+ }
+ helpEngine.setCustomValue(QLatin1String("ApplicationIcon"), icon.readAll());
+ }
+
+ if (config.aboutMenuTexts().count()) {
+ QByteArray ba;
+ QDataStream s(&ba, QIODevice::WriteOnly);
+ QMap<QString, QString>::const_iterator it = config.aboutMenuTexts().constBegin();
+ while (it != config.aboutMenuTexts().constEnd()) {
+ s << it.key();
+ s << it.value();
+ ++it;
+ }
+ helpEngine.setCustomValue(QLatin1String("AboutMenuTexts"), ba);
+ }
+
+ if (!config.aboutIcon().isEmpty()) {
+ QFile icon(basePath + QDir::separator() + config.aboutIcon());
+ if (!icon.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "Cannot open %s!\n", qPrintable(icon.fileName()));
+ return -1;
+ }
+ helpEngine.setCustomValue(QLatin1String("AboutIcon"), icon.readAll());
+ }
+
+ if (config.aboutTextFiles().count()) {
+ QByteArray ba;
+ QDataStream s(&ba, QIODevice::WriteOnly);
+ QMap<QString, QString>::const_iterator it = config.aboutTextFiles().constBegin();
+ QMap<QString, QByteArray> imgData;
+
+ QRegExp srcRegExp(QLatin1String("src=(\"(.+)\"|([^\"\\s]+)).*>"));
+ srcRegExp.setMinimal(true);
+ QRegExp imgRegExp(QLatin1String("(<img[^>]+>)"));
+ imgRegExp.setMinimal(true);
+
+ while (it != config.aboutTextFiles().constEnd()) {
+ s << it.key();
+ QFileInfo fi(basePath + QDir::separator() + it.value());
+ QFile f(fi.absoluteFilePath());
+ if (!f.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "Cannot open %s!\n", qPrintable(f.fileName()));
+ return -1;
+ }
+ QByteArray data = f.readAll();
+ s << data;
+
+ QString contents = QString::fromUtf8(data);
+ int pos = 0;
+ while ((pos = imgRegExp.indexIn(contents, pos)) != -1) {
+ QString imgTag = imgRegExp.cap(1);
+ pos += imgRegExp.matchedLength();
+
+ if (srcRegExp.indexIn(imgTag, 0) != -1) {
+ QString src = srcRegExp.cap(2);
+ if (src.isEmpty())
+ src = srcRegExp.cap(3);
+
+ QFile img(fi.absolutePath() + QDir::separator() + src);
+ if (img.open(QIODevice::ReadOnly)) {
+ if (!imgData.contains(src))
+ imgData.insert(src, img.readAll());
+ } else {
+ fprintf(stderr, "Cannot open referenced image file %s!\n",
+ qPrintable(img.fileName()));
+ }
+ }
+ }
+ ++it;
+ }
+ helpEngine.setCustomValue(QLatin1String("AboutTexts"), ba);
+ if (imgData.count()) {
+ QByteArray imageData;
+ QBuffer buffer(&imageData);
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream out(&buffer);
+ out << imgData;
+ helpEngine.setCustomValue(QLatin1String("AboutImages"), imageData);
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro b/tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro
new file mode 100644
index 0000000000..cf70e48b9b
--- /dev/null
+++ b/tools/assistant/tools/qcollectiongenerator/qcollectiongenerator.pro
@@ -0,0 +1,14 @@
+QT += xml network
+TEMPLATE = app
+DESTDIR = ../../../../bin
+TARGET = qcollectiongenerator
+CONFIG += qt warn_on help console
+CONFIG -= app_bundle
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+SOURCES += ../shared/helpgenerator.cpp \
+ main.cpp
+
+HEADERS += ../shared/helpgenerator.h
diff --git a/tools/assistant/tools/qhelpconverter/adpreader.cpp b/tools/assistant/tools/qhelpconverter/adpreader.cpp
new file mode 100644
index 0000000000..930417a26d
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/adpreader.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "adpreader.h"
+
+QT_BEGIN_NAMESPACE
+
+void AdpReader::readData(const QByteArray &contents)
+{
+ clear();
+ m_contents.clear();
+ m_keywords.clear();
+ m_properties.clear();
+ m_files.clear();
+ addData(contents);
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name().toString().toLower() == QLatin1String("assistantconfig")
+ && attributes().value(QLatin1String("version")) == QLatin1String("3.2.0")) {
+ readProject();
+ } else if (name().toString().toLower() == QLatin1String("dcf")) {
+ QString ref = attributes().value(QLatin1String("ref")).toString();
+ addFile(ref);
+ m_contents.append(ContentItem(attributes().value(QLatin1String("title")).toString(),
+ ref, 0));
+ readDCF();
+ } else {
+ raiseError();
+ }
+ }
+ }
+}
+
+QList<ContentItem> AdpReader::contents() const
+{
+ return m_contents;
+}
+
+QList<KeywordItem> AdpReader::keywords() const
+{
+ return m_keywords;
+}
+
+QSet<QString> AdpReader::files() const
+{
+ return m_files;
+}
+
+QMap<QString, QString> AdpReader::properties() const
+{
+ return m_properties;
+}
+
+void AdpReader::readProject()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ QString s = name().toString().toLower();
+ if (s == QLatin1String("profile")) {
+ readProfile();
+ } else if (s == QLatin1String("dcf")) {
+ QString ref = attributes().value(QLatin1String("ref")).toString();
+ addFile(ref);
+ m_contents.append(ContentItem(attributes().value(QLatin1String("title")).toString(),
+ ref, 0));
+ readDCF();
+ } else {
+ raiseError();
+ }
+ }
+ }
+}
+
+void AdpReader::readProfile()
+{
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name().toString().toLower() == QLatin1String("property")) {
+ QString prop = attributes().value(QLatin1String("name")).toString().toLower();
+ m_properties[prop] = readElementText();
+ } else {
+ raiseError();
+ }
+ } else if (isEndElement()) {
+ break;
+ }
+ }
+}
+
+void AdpReader::readDCF()
+{
+ int depth = 0;
+ while (!atEnd()) {
+ readNext();
+ QString str = name().toString().toLower();
+ if (isStartElement()) {
+ if (str == QLatin1String("section")) {
+ QString ref = attributes().value(QLatin1String("ref")).toString();
+ addFile(ref);
+ m_contents.append(ContentItem(attributes().value(QLatin1String("title")).toString(),
+ ref, ++depth));
+ } else if (str == QLatin1String("keyword")) {
+ QString ref = attributes().value(QLatin1String("ref")).toString();
+ addFile(ref);
+ m_keywords.append(KeywordItem(readElementText(), ref));
+ } else {
+ raiseError();
+ }
+ } else if (isEndElement()) {
+ if (str == QLatin1String("section"))
+ --depth;
+ else if (str == QLatin1String("dcf"))
+ break;
+ }
+ }
+}
+
+void AdpReader::addFile(const QString &file)
+{
+ QString s = file;
+ if (s.startsWith(QLatin1String("./")))
+ s = s.mid(2);
+ int i = s.indexOf(QLatin1Char('#'));
+ if (i > -1)
+ s = s.left(i);
+ if (!m_files.contains(s))
+ m_files.insert(s);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/adpreader.h b/tools/assistant/tools/qhelpconverter/adpreader.h
new file mode 100644
index 0000000000..a7fa606c44
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/adpreader.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ADPREADER_H
+#define ADPREADER_H
+
+#include <QtCore/QMap>
+#include <QtCore/QSet>
+#include <QtXml/QXmlStreamReader>
+
+QT_BEGIN_NAMESPACE
+
+struct ContentItem {
+ ContentItem(const QString &t, const QString &r, int d)
+ : title(t), reference(r), depth(d) {}
+ QString title;
+ QString reference;
+ int depth;
+};
+
+struct KeywordItem {
+ KeywordItem(const QString &k, const QString &r)
+ : keyword(k), reference(r) {}
+ QString keyword;
+ QString reference;
+};
+
+class AdpReader : public QXmlStreamReader
+{
+public:
+ void readData(const QByteArray &contents);
+ QList<ContentItem> contents() const;
+ QList<KeywordItem> keywords() const;
+ QSet<QString> files() const;
+
+ QMap<QString, QString> properties() const;
+
+private:
+ void readProject();
+ void readProfile();
+ void readDCF();
+ void addFile(const QString &file);
+
+ QMap<QString, QString> m_properties;
+ QList<ContentItem> m_contents;
+ QList<KeywordItem> m_keywords;
+ QSet<QString> m_files;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/assistant-128.png b/tools/assistant/tools/qhelpconverter/assistant-128.png
new file mode 100644
index 0000000000..f05949f6d8
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/assistant-128.png
Binary files differ
diff --git a/tools/assistant/tools/qhelpconverter/assistant.png b/tools/assistant/tools/qhelpconverter/assistant.png
new file mode 100644
index 0000000000..ea4d1e70c1
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/assistant.png
Binary files differ
diff --git a/tools/assistant/tools/qhelpconverter/conversionwizard.cpp b/tools/assistant/tools/qhelpconverter/conversionwizard.cpp
new file mode 100644
index 0000000000..c3fe94a000
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/conversionwizard.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QVariant>
+#include <QtCore/QTimer>
+#include <QtGui/QApplication>
+#include <QtGui/QMouseEvent>
+
+#include "conversionwizard.h"
+#include "inputpage.h"
+#include "generalpage.h"
+#include "filterpage.h"
+#include "identifierpage.h"
+#include "pathpage.h"
+#include "filespage.h"
+#include "outputpage.h"
+#include "finishpage.h"
+#include "qhpwriter.h"
+#include "qhcpwriter.h"
+#include "helpwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+ConversionWizard::ConversionWizard()
+{
+ setWindowIcon(QIcon(QLatin1String(":/trolltech/qhelpconverter/assistant.png")));
+ setWindowTitle(tr("Help Conversion Wizard"));
+ setPixmap(QWizard::WatermarkPixmap,
+ QPixmap(QLatin1String(":/trolltech/qhelpconverter/assistant-128.png"))) ;
+ setOptions(QWizard::IndependentPages|QWizard::NoBackButtonOnLastPage
+ |QWizard::HaveHelpButton);
+
+ m_inputPage = new InputPage(&m_adpReader);
+ setPage(Input_Page, m_inputPage);
+
+ m_generalPage = new GeneralPage();
+ setPage(General_Page, m_generalPage);
+
+ m_filterPage = new FilterPage();
+ setPage(Filter_Page, m_filterPage);
+ m_filterPage->setMaximumHeight(240);
+
+ m_identifierPage = new IdentifierPage();
+ setPage(Identifier_Page, m_identifierPage);
+
+ m_pathPage = new PathPage();
+ setPage(Path_Page, m_pathPage);
+ m_pathPage->setMaximumHeight(240);
+
+ m_filesPage = new FilesPage();
+ setPage(Files_Page, m_filesPage);
+ m_filesPage->setMaximumHeight(240);
+
+ m_outputPage = new OutputPage();
+ setPage(Output_Page, m_outputPage);
+ m_outputPage->setMaximumHeight(240);
+
+ m_finishPage = new FinishPage();
+ setPage(Finish_Page, m_finishPage);
+ m_finishPage->setMaximumHeight(240);
+
+ connect(this, SIGNAL(currentIdChanged(int)),
+ this, SLOT(pageChanged(int)));
+
+ m_helpWindow = 0;
+ qApp->installEventFilter(this);
+
+ QAbstractButton *btn = button(QWizard::HelpButton);
+ btn->setCheckable(true);
+ connect(btn, SIGNAL(toggled(bool)), this, SLOT(showHelp(bool)));
+}
+
+void ConversionWizard::setAdpFileName(const QString &fileName)
+{
+ setField(QLatin1String("adpFileName"), fileName);
+}
+
+void ConversionWizard::initializePage(int id)
+{
+ switch (id) {
+ case Path_Page: {
+ QFileInfo fi(field(QLatin1String("adpFileName")).toString());
+ m_pathPage->setPath(fi.absolutePath());
+ break;
+ }
+ case Output_Page: {
+ QFileInfo fi(field(QLatin1String("adpFileName")).toString());
+ m_outputPage->setPath(fi.absolutePath());
+ setField(QLatin1String("ProjectFileName"), fi.baseName()
+ + QLatin1String(".qhp"));
+ setField(QLatin1String("CollectionFileName"), fi.baseName()
+ + QLatin1String(".qhcp"));
+ break;
+ }
+ }
+}
+
+void ConversionWizard::pageChanged(int id)
+{
+ if (id == Files_Page) {
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_files.clear();
+ QFileInfo fi(field(QLatin1String("adpFileName")).toString());
+ QDir rootDir = fi.absolutePath();
+ foreach (const QString &p, m_pathPage->paths()) {
+ QDir dir(p);
+ QString rel = rootDir.relativeFilePath(dir.absolutePath());
+ if (!rel.isEmpty())
+ rel.append(QLatin1Char('/'));
+ foreach (const QString &f, dir.entryList(m_pathPage->filters()))
+ m_files.append(rel + f);
+ }
+ m_filesPage->setFilesToRemove(getUnreferencedFiles(m_files));
+ QApplication::restoreOverrideCursor();
+ } else if (id == Output_Page) {
+ m_outputPage->setCollectionComponentEnabled(
+ !m_adpReader.properties().isEmpty());
+ } else if (id == Finish_Page) {
+ QTimer::singleShot(300, this, SLOT(convert()));
+ }
+}
+
+void ConversionWizard::showHelp(bool toggle)
+{
+ int w = 180;
+ int h = 180;
+ if (!m_helpWindow) {
+ m_helpWindow = new HelpWindow(this);
+ m_helpWindow->setMaximumWidth(w);
+ m_helpWindow->setMaximumHeight(h);
+ m_helpWindow->setMinimumHeight(h);
+ }
+
+ if (toggle) {
+ m_helpWindow->setHelp(currentPage()->objectName());
+ QAbstractButton *btn = button(QWizard::HelpButton);
+ QPoint p = btn->pos();
+ int x = p.x();
+ if (btn->pos().x() > w)
+ x = p.x() + btn->width() - w;
+ m_helpWindow->move(x, p.y()-h);
+ m_helpWindow->show();
+ } else {
+ m_helpWindow->hide();
+ }
+}
+
+bool ConversionWizard::eventFilter(QObject *obj, QEvent *e)
+{
+ if (m_helpWindow && m_helpWindow->isVisible()) {
+ if (obj != button(QWizard::HelpButton)
+ && e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(e);
+ if (!m_helpWindow->geometry().contains(mapFromParent(me->globalPos()))) {
+ m_helpWindow->hide();
+ button(QWizard::HelpButton)->setChecked(false);
+ }
+ } else if (e->type() == QEvent::KeyPress) {
+ m_helpWindow->hide();
+ button(QWizard::HelpButton)->setChecked(false);
+ }
+ }
+ return QWizard::eventFilter(obj, e);
+}
+
+QStringList ConversionWizard::getUnreferencedFiles(const QStringList &files)
+{
+ QStringList lst;
+ QSet<QString> adpFiles = m_adpReader.files();
+ foreach (const QString &s, files) {
+ if (!adpFiles.contains(s))
+ lst.append(s);
+ }
+ return lst;
+}
+
+void ConversionWizard::convert()
+{
+ QFileInfo fi(field(QLatin1String("adpFileName")).toString());
+ m_finishPage->appendMessage(tr("Converting %1...")
+ .arg(fi.fileName()));
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ QString qhpFileName = field(QLatin1String("ProjectFileName")).toString();
+ QhpWriter qhpWriter(field(QLatin1String("namespaceName")).toString(),
+ field(QLatin1String("virtualFolder")).toString());
+ qhpWriter.setAdpReader(&m_adpReader);
+ qhpWriter.setFilterAttributes(m_filterPage->filterAttributes());
+ qhpWriter.setCustomFilters(m_filterPage->customFilters());
+
+ foreach (const QString &f, m_filesPage->filesToRemove())
+ m_files.removeAll(f);
+ qhpWriter.setFiles(m_files);
+
+ if (field(QLatin1String("createIdentifier")).toBool()) {
+ if (field(QLatin1String("fileNamePrefix")).toBool())
+ qhpWriter.generateIdentifiers(QhpWriter::FilePrefix);
+ else
+ qhpWriter.generateIdentifiers(QhpWriter::GlobalPrefix,
+ field(QLatin1String("globalPrefix")).toString());
+ } else {
+ qhpWriter.generateIdentifiers(QhpWriter::SkipAll);
+ }
+
+ qhpWriter.writeFile(fi.absolutePath() + QDir::separator()
+ + qhpFileName);
+
+ m_finishPage->appendMessage(tr("Writing help collection file..."));
+
+ if (!m_adpReader.properties().isEmpty()) {
+ QhcpWriter qhcpWriter;
+ qhcpWriter.setHelpProjectFile(qhpFileName);
+ qhcpWriter.setProperties(m_adpReader.properties());
+ qhcpWriter.setTitlePath(QLatin1String("qthelp://")
+ + field(QLatin1String("namespaceName")).toString()
+ + QLatin1String("/")
+ +field(QLatin1String("virtualFolder")).toString());
+ qhcpWriter.writeFile(fi.absolutePath() + QDir::separator()
+ + field(QLatin1String("CollectionFileName")).toString());
+ }
+
+ m_finishPage->appendMessage(tr("Done."));
+ QApplication::restoreOverrideCursor();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/conversionwizard.h b/tools/assistant/tools/qhelpconverter/conversionwizard.h
new file mode 100644
index 0000000000..4c8fb02740
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/conversionwizard.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONVERSIONWIZARD_H
+#define CONVERSIONWIZARD_H
+
+#include <QtGui/QWizard>
+#include "adpreader.h"
+
+QT_BEGIN_NAMESPACE
+
+class InputPage;
+class GeneralPage;
+class FilterPage;
+class IdentifierPage;
+class PathPage;
+class FilesPage;
+class OutputPage;
+class FinishPage;
+class HelpWindow;
+
+class ConversionWizard : public QWizard
+{
+ Q_OBJECT
+
+public:
+ ConversionWizard();
+ void setAdpFileName(const QString &fileName);
+
+private slots:
+ void pageChanged(int id);
+ void showHelp(bool toggle);
+ void convert();
+
+private:
+ enum Pages {Input_Page, General_Page, Filter_Page,
+ Identifier_Page, Path_Page, Files_Page, Output_Page,
+ Finish_Page};
+ void initializePage(int id);
+ QStringList getUnreferencedFiles(const QStringList &files);
+ bool eventFilter(QObject *obj, QEvent *e);
+
+ AdpReader m_adpReader;
+ InputPage *m_inputPage;
+ GeneralPage *m_generalPage;
+ FilterPage *m_filterPage;
+ IdentifierPage *m_identifierPage;
+ PathPage *m_pathPage;
+ FilesPage *m_filesPage;
+ OutputPage *m_outputPage;
+ FinishPage *m_finishPage;
+ QStringList m_files;
+ HelpWindow *m_helpWindow;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/doc/filespage.html b/tools/assistant/tools/qhelpconverter/doc/filespage.html
new file mode 100644
index 0000000000..a7aac18da5
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/doc/filespage.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<p>Sometimes it can happen that the previously specified paths contain
+more or other files than actually needed for the documentation.</p>
+<p>This page lists all files which are likely to be unused because they
+are neither referenced by any keyword nor be the TOC.</p>
+</body>
+</html>
diff --git a/tools/assistant/tools/qhelpconverter/doc/filterpage.html b/tools/assistant/tools/qhelpconverter/doc/filterpage.html
new file mode 100644
index 0000000000..7b3781bd5b
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/doc/filterpage.html
@@ -0,0 +1,13 @@
+<html>
+<body>
+<p>The help system offers the possibility to filter all installed documentations
+for certain <b>attributes</b>. Commonly specified attributes are e.g. the company
+and product name as well as the product version.</p>
+<p>The help engine and Assistant use <b>custom filters</b> to do the actual
+documentation filtering. A custom filter is basically just a alias name for a
+list of filter attributes. So, if e.g. the custom filter "MyFilter" lists
+the attributes "mycompany, myproduct" then only the documentation with those
+attributes will be shown.</p>
+<p><b>Warning:</b> The filter attributes are case sensitive!</p>
+</body>
+</html>
diff --git a/tools/assistant/tools/qhelpconverter/doc/generalpage.html b/tools/assistant/tools/qhelpconverter/doc/generalpage.html
new file mode 100644
index 0000000000..8d106bec11
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/doc/generalpage.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+<p>The <b>namespace</b> is needed to identify this documentation when having
+several documentation sets installed in a collection.</p>
+<p><b>Virtual</b> folders are used to enable file references between all
+documents. Thereby, the virtual folder acts as the root path of all
+documents, even if those are part of different documentation sets,
+meaning listed under different namespaces.</p>
+</body>
+</html>
diff --git a/tools/assistant/tools/qhelpconverter/doc/identifierpage.html b/tools/assistant/tools/qhelpconverter/doc/identifierpage.html
new file mode 100644
index 0000000000..952b88de81
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/doc/identifierpage.html
@@ -0,0 +1,17 @@
+<html>
+<body>
+<p><b>Identifiers</b> are mostly used to make keywords unique, but they can also
+be used to specify keywords which should not be shown in the index. Identifiers
+are especially help full when using context sensitive help and one keyword has
+more links assigned to it.</p>
+<p>E.g. consider the keyword "replace" in Qt. It is
+included, among others, in QString and QList. To be able to retrieve the proper
+documentation, there is an identifier "QString::replace" and one
+"QList::replace".</p>
+<p>A <b>global prefix</b>, e.g. "MyApp::" is set for all keywords independent
+where they are located. When <b>inheriting</b> the prefix from the file name,
+the keywords get the prefix "[filename]::" where the file name is taken from the
+reference of the keyword. The file name is just the base name, i.e. without any
+directory or extension.</p>
+</body>
+</html>
diff --git a/tools/assistant/tools/qhelpconverter/doc/inputpage.html b/tools/assistant/tools/qhelpconverter/doc/inputpage.html
new file mode 100644
index 0000000000..4054c54729
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/doc/inputpage.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<p>Both, a .adp or .dcf file can be specified. If an .adp file is detected,
+the wizard generates a Qt help collection file in addition to the help
+project file.</p>
+</body>
+</html>
diff --git a/tools/assistant/tools/qhelpconverter/doc/outputpage.html b/tools/assistant/tools/qhelpconverter/doc/outputpage.html
new file mode 100644
index 0000000000..332ef69fcc
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/doc/outputpage.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<p>The specified output files will be located in the same directory as the
+.adp or .dcf file. The collection file will only be generated if the input
+file was an .adp file.</p>
+</body>
+</html>
diff --git a/tools/assistant/tools/qhelpconverter/doc/pathpage.html b/tools/assistant/tools/qhelpconverter/doc/pathpage.html
new file mode 100644
index 0000000000..95449b3c38
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/doc/pathpage.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<p>The new help system uses, in contrast to the old Qt Assistant, compressed
+help files containing all files (html files, images, stylesheets, ...)
+necessary to display the documentation correctly.</p>
+<p>To be able to find all those files, the source paths have to be given.</p>
+</body>
+</html>
diff --git a/tools/assistant/tools/qhelpconverter/filespage.cpp b/tools/assistant/tools/qhelpconverter/filespage.cpp
new file mode 100644
index 0000000000..29631557a7
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/filespage.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QKeyEvent>
+#include "filespage.h"
+
+QT_BEGIN_NAMESPACE
+
+FilesPage::FilesPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Unreferenced Files"));
+ setSubTitle(tr("Remove files which are neither referenced "
+ "by a keyword nor by the TOC."));
+
+ m_ui.setupUi(this);
+ m_ui.fileListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ m_ui.fileListWidget->installEventFilter(this);
+ connect(m_ui.removeButton, SIGNAL(clicked()),
+ this, SLOT(removeFile()));
+ connect(m_ui.removeAllButton, SIGNAL(clicked()),
+ this, SLOT(removeAllFiles()));
+
+ m_ui.fileLabel->setText(tr("<p><b>Warning:</b> Be aware "
+ "when removing images or stylesheets since those files "
+ "are not directly referenced by the .adp or .dcf "
+ "file.</p>"));
+}
+
+void FilesPage::setFilesToRemove(const QStringList &files)
+{
+ m_files = files;
+ m_ui.fileListWidget->clear();
+ m_ui.fileListWidget->addItems(files);
+}
+
+QStringList FilesPage::filesToRemove() const
+{
+ return m_filesToRemove;
+}
+
+void FilesPage::removeFile()
+{
+ int row = m_ui.fileListWidget->currentRow()
+ - m_ui.fileListWidget->selectedItems().count() + 1;
+ foreach (const QListWidgetItem *item, m_ui.fileListWidget->selectedItems()) {
+ m_filesToRemove.append(item->text());
+ delete item;
+ }
+ if (m_ui.fileListWidget->count() > row && row >= 0)
+ m_ui.fileListWidget->setCurrentRow(row);
+ else
+ m_ui.fileListWidget->setCurrentRow(m_ui.fileListWidget->count());
+}
+
+void FilesPage::removeAllFiles()
+{
+ m_ui.fileListWidget->clear();
+ m_filesToRemove = m_files;
+}
+
+bool FilesPage::eventFilter(QObject *obj, QEvent *event)
+{
+ if (obj == m_ui.fileListWidget && event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ if (ke->key() == Qt::Key_Delete) {
+ removeFile();
+ return true;
+ }
+ }
+ return QWizardPage::eventFilter(obj, event);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/filespage.h b/tools/assistant/tools/qhelpconverter/filespage.h
new file mode 100644
index 0000000000..584af873e2
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/filespage.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILESPAGE_H
+#define FILESPAGE_H
+
+#include <QtGui/QWizardPage>
+#include "ui_filespage.h"
+
+QT_BEGIN_NAMESPACE
+
+class FilesPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ FilesPage(QWidget *parent = 0);
+ void setFilesToRemove(const QStringList &files);
+ QStringList filesToRemove() const;
+
+private slots:
+ void removeFile();
+ void removeAllFiles();
+
+private:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+ Ui::FilesPage m_ui;
+ QStringList m_files;
+ QStringList m_filesToRemove;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/filespage.ui b/tools/assistant/tools/qhelpconverter/filespage.ui
new file mode 100644
index 0000000000..d308b96646
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/filespage.ui
@@ -0,0 +1,79 @@
+<ui version="4.0" >
+ <class>FilesPage</class>
+ <widget class="QWidget" name="FilesPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>417</width>
+ <height>242</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="2" >
+ <widget class="QLabel" name="fileLabel" >
+ <property name="text" >
+ <string>Files:</string>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item rowspan="3" row="1" column="0" >
+ <widget class="QListWidget" name="fileListWidget" />
+ </item>
+ <item row="1" column="1" >
+ <widget class="QPushButton" name="removeButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QPushButton" name="removeAllButton" >
+ <property name="text" >
+ <string>Remove All</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>75</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/tools/qhelpconverter/filterpage.cpp b/tools/assistant/tools/qhelpconverter/filterpage.cpp
new file mode 100644
index 0000000000..9f7e3038c8
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/filterpage.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QMessageBox>
+#include "filterpage.h"
+
+QT_BEGIN_NAMESPACE
+
+FilterPage::FilterPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Filter Settings"));
+ setSubTitle(tr("Specify the filter attributes for the "
+ "documentation. If filter attributes are used, "
+ "also define a custom filter for it. Both, the "
+ "filter attributes and the custom filters are "
+ "optional."));
+
+ m_ui.setupUi(this);
+ m_ui.customFilterWidget->headerItem()->setText(0, tr("Filter Name"));
+ m_ui.customFilterWidget->headerItem()->setText(1, tr("Filter Attributes"));
+ m_ui.customFilterWidget->setRootIsDecorated(false);
+ m_ui.removeButton->setDisabled(true);
+ connect(m_ui.addButton, SIGNAL(clicked()),
+ this, SLOT(addFilter()));
+ connect(m_ui.removeButton, SIGNAL(clicked()),
+ this, SLOT(removeFilter()));
+}
+
+bool FilterPage::validatePage()
+{
+ m_filterAttributes.clear();
+ foreach (const QString &f, m_ui.filterLineEdit->text().split(QLatin1Char(','))) {
+ if (!f.trimmed().isEmpty())
+ m_filterAttributes.append(f.trimmed());
+ }
+
+ m_customFilters.clear();
+ QSet<QString> names;
+ QSet<QString> atts;
+ QString str;
+ CustomFilter customFilter;
+ QTreeWidgetItem *item = 0;
+ for (int i=0; i<m_ui.customFilterWidget->topLevelItemCount(); ++i) {
+ item = m_ui.customFilterWidget->topLevelItem(i);
+ str = item->text(0);
+ if (str.isEmpty() || names.contains(str)) {
+ QMessageBox::critical(this, tr("Custom Filters"),
+ tr("The custom filter \'%1\' is defined multiple times.")
+ .arg(str));
+ return false;
+ }
+ names.insert(str);
+ customFilter.name = str;
+
+ str.clear();
+ QStringList lst;
+ foreach (const QString &s, item->text(1).split(QLatin1Char(','))) {
+ const QString st = s.trimmed();
+ if (!st.isEmpty()) {
+ str += QLatin1Char(',') + st;
+ lst.append(st);
+ }
+ }
+ if (atts.contains(str)) {
+ QMessageBox::critical(this, tr("Custom Filters"),
+ tr("The attributes for custom filter \'%1\' are defined multiple times.")
+ .arg(customFilter.name));
+ return false;
+ }
+ atts.insert(str);
+ customFilter.filterAttributes = lst;
+ m_customFilters.append(customFilter);
+ }
+ return true;
+}
+
+QStringList FilterPage::filterAttributes() const
+{
+ return m_filterAttributes;
+}
+
+QList<CustomFilter> FilterPage::customFilters() const
+{
+ return m_customFilters;
+}
+
+void FilterPage::addFilter()
+{
+ QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.customFilterWidget);
+ item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable|Qt::ItemIsSelectable);
+ item->setText(0, QLatin1String("unfiltered"));
+ item->setText(1, QLatin1String(""));
+ m_ui.customFilterWidget->editItem(item, 0);
+ m_ui.removeButton->setDisabled(false);
+}
+
+void FilterPage::removeFilter()
+{
+ QModelIndex idx = m_ui.customFilterWidget->currentIndex();
+ if (!idx.isValid())
+ return;
+ QTreeWidgetItem *item = m_ui.customFilterWidget->takeTopLevelItem(idx.row());
+ delete item;
+ if (!m_ui.customFilterWidget->topLevelItemCount())
+ m_ui.removeButton->setDisabled(true);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/filterpage.h b/tools/assistant/tools/qhelpconverter/filterpage.h
new file mode 100644
index 0000000000..5f0e1b1ef6
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/filterpage.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILTERPAGE_H
+#define FILTERPAGE_H
+
+#include <QtGui/QWizardPage>
+#include "ui_filterpage.h"
+
+QT_BEGIN_NAMESPACE
+
+struct CustomFilter
+{
+ QString name;
+ QStringList filterAttributes;
+};
+
+class FilterPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ FilterPage(QWidget *parent = 0);
+ QStringList filterAttributes() const;
+ QList<CustomFilter> customFilters() const;
+
+private slots:
+ void addFilter();
+ void removeFilter();
+
+private:
+ bool validatePage();
+
+ Ui::FilterPage m_ui;
+ QStringList m_filterAttributes;
+ QList<CustomFilter> m_customFilters;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/filterpage.ui b/tools/assistant/tools/qhelpconverter/filterpage.ui
new file mode 100644
index 0000000000..7cda3d9bed
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/filterpage.ui
@@ -0,0 +1,125 @@
+<ui version="4.0" >
+ <class>FilterPage</class>
+ <widget class="QWidget" name="FilterPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>419</width>
+ <height>243</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Filter attributes for current documentation (comma separated list):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLineEdit" name="filterLineEdit" />
+ </item>
+ <item row="4" column="0" >
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Custom Filters</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item rowspan="3" row="0" column="0" >
+ <widget class="QTreeWidget" name="customFilterWidget" >
+ <property name="columnCount" >
+ <number>2</number>
+ </property>
+ <column>
+ <property name="text" >
+ <string>1</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>2</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QPushButton" name="addButton" >
+ <property name="text" >
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QPushButton" name="removeButton" >
+ <property name="text" >
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="5" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/tools/qhelpconverter/finishpage.cpp b/tools/assistant/tools/qhelpconverter/finishpage.cpp
new file mode 100644
index 0000000000..0b3c33fe75
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/finishpage.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QTextEdit>
+#include <QtGui/QLayout>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QApplication>
+
+#include "finishpage.h"
+
+QT_BEGIN_NAMESPACE
+
+FinishPage::FinishPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Converting File"));
+ setSubTitle(QLatin1String("Creating the new Qt help files from the "
+ "old .adp file."));
+ setFinalPage(true);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum,
+ QSizePolicy::Fixed));
+
+ m_textEdit = new QTextEdit();
+ layout->addWidget(m_textEdit);
+
+ layout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum,
+ QSizePolicy::Expanding));
+}
+
+void FinishPage::appendMessage(const QString &msg)
+{
+ m_textEdit->append(msg);
+ qApp->processEvents();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/finishpage.h b/tools/assistant/tools/qhelpconverter/finishpage.h
new file mode 100644
index 0000000000..7a4689d1d9
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/finishpage.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FINISHPAGE_H
+#define FINISHPAGE_H
+
+#include <QtGui/QWizardPage>
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+
+class FinishPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ FinishPage(QWidget *parent = 0);
+ void appendMessage(const QString &msg);
+
+private:
+ QTextEdit *m_textEdit;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/generalpage.cpp b/tools/assistant/tools/qhelpconverter/generalpage.cpp
new file mode 100644
index 0000000000..f59be49adc
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/generalpage.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QMessageBox>
+#include "generalpage.h"
+
+QT_BEGIN_NAMESPACE
+
+GeneralPage::GeneralPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("General Settings"));
+ setSubTitle(tr("Specify the namespace and the virtual "
+ "folder for the documentation."));
+
+ m_ui.setupUi(this);
+ connect(m_ui.namespaceLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(completeChanged()));
+ connect(m_ui.folderLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(completeChanged()));
+
+ m_ui.namespaceLineEdit->setText(QLatin1String("mycompany.com"));
+ m_ui.folderLineEdit->setText(QLatin1String("product_1.0"));
+
+ registerField(QLatin1String("namespaceName"), m_ui.namespaceLineEdit);
+ registerField(QLatin1String("virtualFolder"), m_ui.folderLineEdit);
+}
+
+bool GeneralPage::isComplete() const
+{
+ if (m_ui.namespaceLineEdit->text().isEmpty()
+ || m_ui.folderLineEdit->text().isEmpty())
+ return false;
+ return true;
+}
+
+bool GeneralPage::validatePage()
+{
+ QString s = m_ui.namespaceLineEdit->text();
+ if (s.contains(QLatin1Char('/')) || s.contains(QLatin1Char('\\'))) {
+ QMessageBox::critical(this, tr("Namespace Error"),
+ tr("The namespace contains some invalid characters."));
+ return false;
+ }
+ s = m_ui.folderLineEdit->text();
+ if (s.contains(QLatin1Char('/')) || s.contains(QLatin1Char('\\'))) {
+ QMessageBox::critical(this, tr("Virtual Folder Error"),
+ tr("The virtual folder contains some invalid characters."));
+ return false;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/generalpage.h b/tools/assistant/tools/qhelpconverter/generalpage.h
new file mode 100644
index 0000000000..c9d2b4dc16
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/generalpage.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GENERALPAGE_H
+#define GENERALPAGE_H
+
+#include <QtGui/QWizardPage>
+#include "ui_generalpage.h"
+
+QT_BEGIN_NAMESPACE
+
+class GeneralPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ GeneralPage(QWidget *parent = 0);
+
+private:
+ bool validatePage();
+ bool isComplete() const;
+
+ Ui::GeneralPage m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/generalpage.ui b/tools/assistant/tools/qhelpconverter/generalpage.ui
new file mode 100644
index 0000000000..9c2babb0ae
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/generalpage.ui
@@ -0,0 +1,69 @@
+<ui version="4.0" >
+ <class>GeneralPage</class>
+ <widget class="QWidget" name="GeneralPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>417</width>
+ <height>243</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Namespace:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="namespaceLineEdit" />
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Virtual Folder:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QLineEdit" name="folderLineEdit" />
+ </item>
+ <item row="0" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/tools/qhelpconverter/helpwindow.cpp b/tools/assistant/tools/qhelpconverter/helpwindow.cpp
new file mode 100644
index 0000000000..b41a410682
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/helpwindow.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QTextEdit>
+
+#include "helpwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+HelpWindow::HelpWindow(QWidget *parent)
+ : QWidget(parent, 0)
+{
+ setAutoFillBackground(true);
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(0);
+ QFrame *frame = new QFrame(this);
+ QPalette p = palette();
+ p.setColor(QPalette::Background, Qt::white);
+ setPalette(p);
+ frame->setFrameStyle(QFrame::Box | QFrame::Plain);
+ layout->addWidget(frame);
+
+ layout = new QVBoxLayout(frame);
+ layout->setMargin(2);
+ QLabel *l = new QLabel(QLatin1String("<center><b>Wizard Assistant</b></center>"));
+ layout->addWidget(l);
+ m_textEdit = new QTextEdit();
+ m_textEdit->setFrameStyle(QFrame::NoFrame);
+ m_textEdit->setReadOnly(true);
+ layout->addWidget(m_textEdit);
+}
+
+void HelpWindow::setHelp(const QString &topic)
+{
+ QLatin1String fileStr(":/trolltech/qhelpconverter/doc/%1.html");
+ QFile f(QString(fileStr).arg(topic.toLower()));
+ f.open(QIODevice::ReadOnly);
+ QTextStream s(&f);
+ m_textEdit->setText(s.readAll());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/helpwindow.h b/tools/assistant/tools/qhelpconverter/helpwindow.h
new file mode 100644
index 0000000000..9c0866a5cb
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/helpwindow.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HELPWINDOW_H
+#define HELPWINDOW_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+
+class HelpWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ HelpWindow(QWidget *parent = 0);
+ void setHelp(const QString &topic);
+
+private:
+ QTextEdit *m_textEdit;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/identifierpage.cpp b/tools/assistant/tools/qhelpconverter/identifierpage.cpp
new file mode 100644
index 0000000000..64a23a684c
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/identifierpage.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "identifierpage.h"
+
+QT_BEGIN_NAMESPACE
+
+IdentifierPage::IdentifierPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Identifiers"));
+ setSubTitle(tr("This page allows you to create identifiers from "
+ "the keywords found in the .adp or .dcf file."));
+
+ m_ui.setupUi(this);
+
+ connect(m_ui.identifierCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(setupButtons(bool)));
+
+ registerField(QLatin1String("createIdentifier"), m_ui.identifierCheckBox);
+ registerField(QLatin1String("globalPrefix"), m_ui.prefixLineEdit);
+ registerField(QLatin1String("fileNamePrefix"), m_ui.fileNameButton);
+}
+
+void IdentifierPage::setupButtons(bool checked)
+{
+ m_ui.globalButton->setEnabled(checked);
+ m_ui.fileNameButton->setEnabled(checked);
+ m_ui.prefixLineEdit->setEnabled(checked
+ && m_ui.globalButton->isChecked());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/identifierpage.h b/tools/assistant/tools/qhelpconverter/identifierpage.h
new file mode 100644
index 0000000000..fcebb496bc
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/identifierpage.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef IDENTIFIERPAGE_H
+#define IDENTIFIERPAGE_H
+
+#include <QtGui/QWizardPage>
+#include "ui_identifierpage.h"
+
+QT_BEGIN_NAMESPACE
+
+class IdentifierPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ IdentifierPage(QWidget *parent = 0);
+
+private slots:
+ void setupButtons(bool checked);
+
+private:
+ Ui::IdentifierPage m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/identifierpage.ui b/tools/assistant/tools/qhelpconverter/identifierpage.ui
new file mode 100644
index 0000000000..cd0df75638
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/identifierpage.ui
@@ -0,0 +1,132 @@
+<ui version="4.0" >
+ <class>IdentifierPage</class>
+ <widget class="QWidget" name="IdentifierPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>417</width>
+ <height>242</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="QCheckBox" name="identifierCheckBox" >
+ <property name="text" >
+ <string>Create identifiers</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>161</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QRadioButton" name="globalButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Global prefix:</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QLineEdit" name="prefixLineEdit" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" colspan="2" >
+ <widget class="QRadioButton" name="fileNameButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Inherit prefix from file names</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>globalButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>prefixLineEdit</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>122</x>
+ <y>72</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>161</x>
+ <y>71</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/assistant/tools/qhelpconverter/inputpage.cpp b/tools/assistant/tools/qhelpconverter/inputpage.cpp
new file mode 100644
index 0000000000..5872523c5e
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/inputpage.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFile>
+#include <QtCore/QVariant>
+
+#include <QtGui/QLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QToolButton>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QApplication>
+
+#include "inputpage.h"
+#include "adpreader.h"
+
+QT_BEGIN_NAMESPACE
+
+InputPage::InputPage(AdpReader *reader, QWidget *parent)
+ : QWizardPage(parent)
+{
+ m_adpReader = reader;
+ setTitle(tr("Input File"));
+ setSubTitle(tr("Specify the .adp or .dcf file you want "
+ "to convert to the new Qt help project format and/or "
+ "collection format."));
+
+ m_ui.setupUi(this);
+ connect(m_ui.browseButton, SIGNAL(clicked()),
+ this, SLOT(getFileName()));
+
+ registerField(QLatin1String("adpFileName"), m_ui.fileLineEdit);
+}
+
+void InputPage::getFileName()
+{
+ QString f = QFileDialog::getOpenFileName(this, tr("Open file"), QString(),
+ tr("Qt Help Files (*.adp *.dcf)"));
+ if (!f.isEmpty())
+ m_ui.fileLineEdit->setText(f);
+}
+
+bool InputPage::validatePage()
+{
+ QFile f(m_ui.fileLineEdit->text().trimmed());
+ if (!f.exists() || !f.open(QIODevice::ReadOnly)) {
+ QMessageBox::critical(this, tr("File Open Error"),
+ tr("The specified file could not be opened!"));
+ return false;
+ }
+
+ QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+ m_adpReader->readData(f.readAll());
+ QApplication::restoreOverrideCursor();
+ if (m_adpReader->hasError()) {
+ QMessageBox::critical(this, tr("File Parsing Error"),
+ tr("Parsing error in line %1!").arg(m_adpReader->lineNumber()));
+ return false;
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/inputpage.h b/tools/assistant/tools/qhelpconverter/inputpage.h
new file mode 100644
index 0000000000..dddf80d84f
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/inputpage.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INPUTPAGE_H
+#define INPUTPAGE_H
+
+#include <QtGui/QWizardPage>
+#include "ui_inputpage.h"
+
+QT_BEGIN_NAMESPACE
+
+class AdpReader;
+
+class InputPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ InputPage(AdpReader *reader, QWidget *parent = 0);
+
+private slots:
+ void getFileName();
+
+private:
+ bool validatePage();
+
+ Ui::InputPage m_ui;
+ AdpReader *m_adpReader;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/inputpage.ui b/tools/assistant/tools/qhelpconverter/inputpage.ui
new file mode 100644
index 0000000000..e7cd3a0fad
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/inputpage.ui
@@ -0,0 +1,79 @@
+<ui version="4.0" >
+ <class>InputPage</class>
+ <widget class="QWidget" name="InputPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>417</width>
+ <height>242</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>File name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2" >
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="fileLineEdit" />
+ </item>
+ <item>
+ <widget class="QToolButton" name="browseButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/tools/qhelpconverter/main.cpp b/tools/assistant/tools/qhelpconverter/main.cpp
new file mode 100644
index 0000000000..2b0f60243b
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/main.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFileInfo>
+#include <QtGui/QApplication>
+
+#include "conversionwizard.h"
+
+QT_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ ConversionWizard w;
+ if (argc == 2) {
+ QFileInfo fi(QString::fromLocal8Bit(argv[1]));
+ if (fi.exists())
+ w.setAdpFileName(fi.absoluteFilePath());
+ }
+ w.show();
+ return app.exec();
+}
+
diff --git a/tools/assistant/tools/qhelpconverter/outputpage.cpp b/tools/assistant/tools/qhelpconverter/outputpage.cpp
new file mode 100644
index 0000000000..77cbf4cb0a
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/outputpage.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtGui/QMessageBox>
+
+#include "outputpage.h"
+
+QT_BEGIN_NAMESPACE
+
+OutputPage::OutputPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Output File Names"));
+ setSubTitle(tr("Specify the file names for the output files."));
+ setButtonText(QWizard::NextButton, tr("Convert..."));
+
+ m_ui.setupUi(this);
+ connect(m_ui.projectLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(completeChanged()));
+ connect(m_ui.collectionLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SIGNAL(completeChanged()));
+
+ registerField(QLatin1String("ProjectFileName"),
+ m_ui.projectLineEdit);
+ registerField(QLatin1String("CollectionFileName"),
+ m_ui.collectionLineEdit);
+}
+
+void OutputPage::setPath(const QString &path)
+{
+ m_path = path;
+}
+
+void OutputPage::setCollectionComponentEnabled(bool enabled)
+{
+ m_ui.collectionLineEdit->setEnabled(enabled);
+ m_ui.label_2->setEnabled(enabled);
+}
+
+bool OutputPage::isComplete() const
+{
+ if (m_ui.projectLineEdit->text().isEmpty()
+ || m_ui.collectionLineEdit->text().isEmpty())
+ return false;
+ return true;
+}
+
+bool OutputPage::validatePage()
+{
+ return checkFile(m_ui.projectLineEdit->text(),
+ tr("Qt Help Project File"))
+ && checkFile(m_ui.collectionLineEdit->text(),
+ tr("Qt Help Collection Project File"));
+}
+
+bool OutputPage::checkFile(const QString &fileName, const QString &title)
+{
+ QFile fi(m_path + QDir::separator() + fileName);
+ if (!fi.exists())
+ return true;
+
+ if (QMessageBox::warning(this, title,
+ tr("The specified file %1 already exist.\n\nDo you want to remove it?")
+ .arg(fileName), tr("Remove"), tr("Cancel")) == 0) {
+ return fi.remove();
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/outputpage.h b/tools/assistant/tools/qhelpconverter/outputpage.h
new file mode 100644
index 0000000000..3907ae5a4e
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/outputpage.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OUTPUTPAGE_H
+#define OUTPUTPAGE_H
+
+#include <QtGui/QWizardPage>
+#include "ui_outputpage.h"
+
+QT_BEGIN_NAMESPACE
+
+class OutputPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ OutputPage(QWidget *parent = 0);
+ void setPath(const QString &path);
+ void setCollectionComponentEnabled(bool enabled);
+
+private:
+ bool isComplete() const;
+ bool validatePage();
+ bool checkFile(const QString &fileName,
+ const QString &title);
+
+ Ui::OutputPage m_ui;
+ QString m_path;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/outputpage.ui b/tools/assistant/tools/qhelpconverter/outputpage.ui
new file mode 100644
index 0000000000..755f818085
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/outputpage.ui
@@ -0,0 +1,95 @@
+<ui version="4.0" >
+ <class>OutputPage</class>
+ <widget class="QWidget" name="OutputPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>417</width>
+ <height>242</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Project file name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="projectLineEdit" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Collection file name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QLineEdit" name="collectionLineEdit" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/tools/qhelpconverter/pathpage.cpp b/tools/assistant/tools/qhelpconverter/pathpage.cpp
new file mode 100644
index 0000000000..83019d63ff
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/pathpage.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QFileDialog>
+
+#include "pathpage.h"
+
+QT_BEGIN_NAMESPACE
+
+PathPage::PathPage(QWidget *parent)
+ : QWizardPage(parent)
+{
+ setTitle(tr("Source File Paths"));
+ setSubTitle(tr("Specify the paths where the sources files "
+ "are located. By default, all files in those directories "
+ "matched by the file filter will be included."));
+
+ m_ui.setupUi(this);
+ connect(m_ui.addButton, SIGNAL(clicked()),
+ this, SLOT(addPath()));
+ connect(m_ui.removeButton, SIGNAL(clicked()),
+ this, SLOT(removePath()));
+
+ m_ui.filterLineEdit->setText(QLatin1String("*.html, *.htm, *.png, *.jpg, *.css"));
+
+ registerField(QLatin1String("sourcePathList"), m_ui.pathListWidget);
+ m_firstTime = true;
+}
+
+void PathPage::setPath(const QString &path)
+{
+ if (!m_firstTime)
+ return;
+
+ m_ui.pathListWidget->addItem(path);
+ m_firstTime = false;
+ m_ui.pathListWidget->setCurrentRow(0);
+}
+
+QStringList PathPage::paths() const
+{
+ QStringList lst;
+ for (int i = 0; i<m_ui.pathListWidget->count(); ++i)
+ lst.append(m_ui.pathListWidget->item(i)->text());
+ return lst;
+}
+
+QStringList PathPage::filters() const
+{
+ QStringList lst;
+ foreach (const QString &s, m_ui.filterLineEdit->text().split(QLatin1Char(','))) {
+ lst.append(s.trimmed());
+ }
+ return lst;
+}
+
+void PathPage::addPath()
+{
+ QString dir = QFileDialog::getExistingDirectory(this,
+ tr("Source File Path"));
+ if (!dir.isEmpty())
+ m_ui.pathListWidget->addItem(dir);
+}
+
+void PathPage::removePath()
+{
+ QListWidgetItem *i = m_ui.pathListWidget
+ ->takeItem(m_ui.pathListWidget->currentRow());
+ delete i;
+ if (!m_ui.pathListWidget->count())
+ m_ui.removeButton->setEnabled(false);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/pathpage.h b/tools/assistant/tools/qhelpconverter/pathpage.h
new file mode 100644
index 0000000000..e081b73dec
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/pathpage.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PATHPAGE_H
+#define PATHPAGE_H
+
+#include <QtGui/QWizardPage>
+#include "ui_pathpage.h"
+
+QT_BEGIN_NAMESPACE
+
+class PathPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ PathPage(QWidget *parent = 0);
+ void setPath(const QString &path);
+ QStringList paths() const;
+ QStringList filters() const;
+
+private slots:
+ void addPath();
+ void removePath();
+
+private:
+ Ui::PathPage m_ui;
+ bool m_firstTime;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/pathpage.ui b/tools/assistant/tools/qhelpconverter/pathpage.ui
new file mode 100644
index 0000000000..89083915dd
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/pathpage.ui
@@ -0,0 +1,114 @@
+<ui version="4.0" >
+ <class>PathPage</class>
+ <widget class="QWidget" name="PathPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>417</width>
+ <height>243</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>File filters:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <widget class="QLineEdit" name="filterLineEdit" />
+ </item>
+ <item row="1" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0" colspan="3" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Documentation source file paths:</string>
+ </property>
+ </widget>
+ </item>
+ <item rowspan="3" row="3" column="0" colspan="3" >
+ <widget class="QListWidget" name="pathListWidget" />
+ </item>
+ <item row="3" column="3" >
+ <widget class="QPushButton" name="addButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3" >
+ <widget class="QPushButton" name="removeButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="3" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="6" column="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/assistant/tools/qhelpconverter/qhcpwriter.cpp b/tools/assistant/tools/qhelpconverter/qhcpwriter.cpp
new file mode 100644
index 0000000000..55a1b1265c
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/qhcpwriter.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFile>
+
+#include "qhcpwriter.h"
+
+QT_BEGIN_NAMESPACE
+
+QhcpWriter::QhcpWriter()
+{
+ setAutoFormatting(true);
+}
+
+void QhcpWriter::setHelpProjectFile(const QString &qhpFile)
+{
+ m_qhpFile = qhpFile;
+}
+
+void QhcpWriter::setProperties(const QMap<QString, QString> props)
+{
+ m_properties = props;
+}
+
+void QhcpWriter::setTitlePath(const QString &path)
+{
+ m_titlePath = path;
+}
+
+bool QhcpWriter::writeFile(const QString &fileName)
+{
+ QFile out(fileName);
+ if (!out.open(QIODevice::WriteOnly))
+ return false;
+
+ setDevice(&out);
+ writeStartDocument();
+ writeStartElement(QLatin1String("QHelpCollectionProject"));
+ writeAttribute(QLatin1String("version"), QLatin1String("1.0"));
+ writeAssistantSettings();
+ writeDocuments();
+ writeEndDocument();
+ return true;
+}
+
+void QhcpWriter::writeAssistantSettings()
+{
+ if (m_properties.isEmpty())
+ return;
+
+ writeStartElement(QLatin1String("assistant"));
+
+ if (m_properties.contains(QLatin1String("title")))
+ writeTextElement(QLatin1String("title"), m_properties.value(QLatin1String("title")));
+ if (m_properties.contains(QLatin1String("applicationicon")))
+ writeTextElement(QLatin1String("applicationIcon"),
+ m_properties.value(QLatin1String("applicationicon")));
+ if (m_properties.contains(QLatin1String("startpage")))
+ writeTextElement(QLatin1String("startPage"), m_titlePath + QLatin1String("/")
+ + m_properties.value(QLatin1String("startpage")));
+ if (m_properties.contains(QLatin1String("aboutmenutext"))) {
+ writeStartElement(QLatin1String("aboutMenuText"));
+ writeTextElement(QLatin1String("text"),
+ m_properties.value(QLatin1String("aboutmenutext")));
+ writeEndElement();
+ }
+ if (m_properties.contains(QLatin1String("abouturl"))) {
+ writeStartElement(QLatin1String("aboutDialog"));
+ writeTextElement(QLatin1String("file"), m_properties.value(QLatin1String("abouturl")));
+ writeEndElement();
+ }
+ if (m_properties.contains(QLatin1String("name"))) {
+ writeTextElement(QLatin1String("cacheDirectory"),
+ QLatin1String(".") + m_properties.value(QLatin1String("name")));
+ }
+
+ writeEndElement();
+}
+
+void QhcpWriter::writeDocuments()
+{
+ if (m_qhpFile.isEmpty())
+ return;
+
+ QString out = m_qhpFile;
+ int i = out.indexOf(QLatin1Char('.'));
+ if (i > -1)
+ out = out.left(i);
+ out.append(QLatin1String(".qch"));
+
+ writeStartElement(QLatin1String("docFiles"));
+
+ writeStartElement(QLatin1String("generate"));
+ writeStartElement(QLatin1String("file"));
+ writeTextElement(QLatin1String("input"), m_qhpFile);
+ writeTextElement(QLatin1String("output"), out);
+ writeEndElement();
+ writeEndElement();
+
+ writeStartElement(QLatin1String("register"));
+ writeTextElement(QLatin1String("file"), out);
+ writeEndElement();
+
+ writeEndElement();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/qhcpwriter.h b/tools/assistant/tools/qhelpconverter/qhcpwriter.h
new file mode 100644
index 0000000000..ba448a50a0
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/qhcpwriter.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHCPWRITER_H
+#define QHCPWRITER_H
+
+#include <QtXml/QXmlStreamWriter>
+#include "adpreader.h"
+
+QT_BEGIN_NAMESPACE
+
+class QhcpWriter : public QXmlStreamWriter
+{
+public:
+ QhcpWriter();
+ bool writeFile(const QString &fileName);
+ void setHelpProjectFile(const QString &qhpFile);
+ void setProperties(const QMap<QString, QString> props);
+ void setTitlePath(const QString &path);
+
+private:
+ void writeAssistantSettings();
+ void writeDocuments();
+
+ QString m_qhpFile;
+ QMap<QString, QString> m_properties;
+ QString m_titlePath;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpconverter/qhelpconverter.pro b/tools/assistant/tools/qhelpconverter/qhelpconverter.pro
new file mode 100644
index 0000000000..341faf346e
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/qhelpconverter.pro
@@ -0,0 +1,47 @@
+QT += xml
+TEMPLATE = app
+TARGET = qhelpconverter
+DESTDIR = ../../../../bin
+CONFIG += qt warn_on help
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+SOURCES += conversionwizard.cpp \
+ inputpage.cpp \
+ generalpage.cpp \
+ filterpage.cpp \
+ identifierpage.cpp \
+ pathpage.cpp \
+ filespage.cpp \
+ outputpage.cpp \
+ finishpage.cpp \
+ adpreader.cpp \
+ qhpwriter.cpp \
+ qhcpwriter.cpp \
+ helpwindow.cpp \
+ main.cpp
+
+HEADERS += conversionwizard.h \
+ inputpage.h \
+ generalpage.h \
+ filterpage.h \
+ identifierpage.h \
+ pathpage.h \
+ filespage.h \
+ outputpage.h \
+ finishpage.h \
+ adpreader.h \
+ qhcpwriter.h \
+ qhpwriter.h \
+ helpwindow.h
+
+FORMS += inputpage.ui \
+ generalpage.ui \
+ filterpage.ui \
+ identifierpage.ui \
+ pathpage.ui \
+ filespage.ui \
+ outputpage.ui
+
+RESOURCES += qhelpconverter.qrc
diff --git a/tools/assistant/tools/qhelpconverter/qhelpconverter.qrc b/tools/assistant/tools/qhelpconverter/qhelpconverter.qrc
new file mode 100644
index 0000000000..e2a68ab433
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/qhelpconverter.qrc
@@ -0,0 +1,13 @@
+<RCC>
+ <qresource prefix="/trolltech/qhelpconverter" >
+ <file>assistant-128.png</file>
+ <file>assistant.png</file>
+ <file>doc/inputpage.html</file>
+ <file>doc/generalpage.html</file>
+ <file>doc/filterpage.html</file>
+ <file>doc/identifierpage.html</file>
+ <file>doc/pathpage.html</file>
+ <file>doc/filespage.html</file>
+ <file>doc/outputpage.html</file>
+ </qresource>
+</RCC>
diff --git a/tools/assistant/tools/qhelpconverter/qhpwriter.cpp b/tools/assistant/tools/qhelpconverter/qhpwriter.cpp
new file mode 100644
index 0000000000..cd5453792e
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/qhpwriter.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFile>
+
+#include "qhpwriter.h"
+#include "adpreader.h"
+
+QT_BEGIN_NAMESPACE
+
+QhpWriter::QhpWriter(const QString &namespaceName,
+ const QString &virtualFolder)
+{
+ m_namespaceName = namespaceName;
+ m_virtualFolder = virtualFolder;
+ setAutoFormatting(true);
+}
+
+void QhpWriter::setAdpReader(AdpReader *reader)
+{
+ m_adpReader = reader;
+}
+
+void QhpWriter::setFilterAttributes(const QStringList &attributes)
+{
+ m_filterAttributes = attributes;
+}
+
+void QhpWriter::setCustomFilters(const QList<CustomFilter> filters)
+{
+ m_customFilters = filters;
+}
+
+void QhpWriter::setFiles(const QStringList &files)
+{
+ m_files = files;
+}
+
+void QhpWriter::generateIdentifiers(IdentifierPrefix prefix,
+ const QString prefixString)
+{
+ m_prefix = prefix;
+ m_prefixString = prefixString;
+}
+
+bool QhpWriter::writeFile(const QString &fileName)
+{
+ QFile out(fileName);
+ if (!out.open(QIODevice::WriteOnly))
+ return false;
+
+ setDevice(&out);
+ writeStartDocument();
+ writeStartElement(QLatin1String("QtHelpProject"));
+ writeAttribute(QLatin1String("version"), QLatin1String("1.0"));
+ writeTextElement(QLatin1String("namespace"), m_namespaceName);
+ writeTextElement(QLatin1String("virtualFolder"), m_virtualFolder);
+ writeCustomFilters();
+ writeFilterSection();
+ writeEndDocument();
+
+ out.close();
+ return true;
+}
+
+void QhpWriter::writeCustomFilters()
+{
+ if (!m_customFilters.count())
+ return;
+
+ foreach (const CustomFilter &f, m_customFilters) {
+ writeStartElement(QLatin1String("customFilter"));
+ writeAttribute(QLatin1String("name"), f.name);
+ foreach (const QString &a, f.filterAttributes)
+ writeTextElement(QLatin1String("filterAttribute"), a);
+ writeEndElement();
+ }
+}
+
+void QhpWriter::writeFilterSection()
+{
+ writeStartElement(QLatin1String("filterSection"));
+ foreach (const QString &a, m_filterAttributes)
+ writeTextElement(QLatin1String("filterAttribute"), a);
+
+ writeToc();
+ writeKeywords();
+ writeFiles();
+ writeEndElement();
+}
+
+void QhpWriter::writeToc()
+{
+ QList<ContentItem> lst = m_adpReader->contents();
+ if (lst.isEmpty())
+ return;
+
+ int depth = -1;
+ writeStartElement(QLatin1String("toc"));
+ foreach (const ContentItem &i, lst) {
+ while (depth-- >= i.depth)
+ writeEndElement();
+ writeStartElement(QLatin1String("section"));
+ writeAttribute(QLatin1String("title"), i.title);
+ writeAttribute(QLatin1String("ref"), i.reference);
+ depth = i.depth;
+ }
+ while (depth-- >= -1)
+ writeEndElement();
+}
+
+void QhpWriter::writeKeywords()
+{
+ QList<KeywordItem> lst = m_adpReader->keywords();
+ if (lst.isEmpty())
+ return;
+
+ writeStartElement(QLatin1String("keywords"));
+ foreach (const KeywordItem &i, lst) {
+ writeEmptyElement(QLatin1String("keyword"));
+ writeAttribute(QLatin1String("name"), i.keyword);
+ writeAttribute(QLatin1String("ref"), i.reference);
+ if (m_prefix == FilePrefix) {
+ QString str = i.reference.mid(
+ i.reference.lastIndexOf(QLatin1Char('/'))+1);
+ str = str.left(str.lastIndexOf(QLatin1Char('.')));
+ writeAttribute(QLatin1String("id"), str + QLatin1String("::") + i.keyword);
+ } else if (m_prefix == GlobalPrefix) {
+ writeAttribute(QLatin1String("id"), m_prefixString + i.keyword);
+ }
+ }
+ writeEndElement();
+}
+
+void QhpWriter::writeFiles()
+{
+ if (m_files.isEmpty())
+ return;
+
+ writeStartElement(QLatin1String("files"));
+ foreach (const QString &f, m_files)
+ writeTextElement(QLatin1String("file"), f);
+ writeEndElement();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/qhelpconverter/qhpwriter.h b/tools/assistant/tools/qhelpconverter/qhpwriter.h
new file mode 100644
index 0000000000..bba3fcb705
--- /dev/null
+++ b/tools/assistant/tools/qhelpconverter/qhpwriter.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHPWRITER_H
+#define QHPWRITER_H
+
+#include <QtXml/QXmlStreamWriter>
+#include "filterpage.h"
+
+QT_BEGIN_NAMESPACE
+
+class AdpReader;
+
+class QhpWriter : public QXmlStreamWriter
+{
+public:
+ enum IdentifierPrefix {SkipAll, FilePrefix, GlobalPrefix};
+ QhpWriter(const QString &namespaceName,
+ const QString &virtualFolder);
+ void setAdpReader(AdpReader *reader);
+ void setFilterAttributes(const QStringList &attributes);
+ void setCustomFilters(const QList<CustomFilter> filters);
+ void setFiles(const QStringList &files);
+ void generateIdentifiers(IdentifierPrefix prefix,
+ const QString prefixString = QString());
+ bool writeFile(const QString &fileName);
+
+private:
+ void writeCustomFilters();
+ void writeFilterSection();
+ void writeToc();
+ void writeKeywords();
+ void writeFiles();
+
+ QString m_namespaceName;
+ QString m_virtualFolder;
+ AdpReader *m_adpReader;
+ QStringList m_filterAttributes;
+ QList<CustomFilter> m_customFilters;
+ QStringList m_files;
+ IdentifierPrefix m_prefix;
+ QString m_prefixString;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/qhelpgenerator/main.cpp b/tools/assistant/tools/qhelpgenerator/main.cpp
new file mode 100644
index 0000000000..42a15950b2
--- /dev/null
+++ b/tools/assistant/tools/qhelpgenerator/main.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/helpgenerator.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QCoreApplication>
+
+#include <private/qhelpprojectdata_p.h>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ QString error;
+ QString arg;
+ QString compressedFile;
+ QString projectFile;
+ QString basePath;
+ bool showHelp = false;
+ bool showVersion = false;
+
+ for (int i = 1; i < argc; ++i) {
+ arg = QString::fromLocal8Bit(argv[i]);
+ if (arg == QLatin1String("-o")) {
+ if (++i < argc) {
+ QFileInfo fi(QString::fromLocal8Bit(argv[i]));
+ compressedFile = fi.absoluteFilePath();
+ } else {
+ error = QObject::tr("Missing output file name!");
+ }
+ } else if (arg == QLatin1String("-v")) {
+ showVersion = true;
+ } else if (arg == QLatin1String("-h")) {
+ showHelp = true;
+ } else {
+ QFileInfo fi(arg);
+ projectFile = fi.absoluteFilePath();
+ basePath = fi.absolutePath();
+ }
+ }
+
+ if (showVersion) {
+ fprintf(stdout, "Qt Help Generator version 1.0 (Qt %s)\n", QT_VERSION_STR);
+ return 0;
+ }
+
+ if (projectFile.isEmpty() && !showHelp)
+ error = QObject::tr("Missing Qt help project file!");
+
+ QString help = QObject::tr("\nUsage:\n\n"
+ "qhelpgenerator <help-project-file> [options]\n\n"
+ " -o <compressed-file> Generates a Qt compressed help\n"
+ " file called <compressed-file>.\n"
+ " If this option is not specified\n"
+ " a default name will be used.\n"
+ " -v Displays the version of \n"
+ " qhelpgenerator.\n\n");
+
+ if (showHelp) {
+ fprintf(stdout, "%s", qPrintable(help));
+ return 0;
+ }else if (!error.isEmpty()) {
+ fprintf(stderr, "%s\n\n%s", qPrintable(error), qPrintable(help));
+ return -1;
+ }
+
+ QFile file(projectFile);
+ if (!file.open(QIODevice::ReadOnly)) {
+ fprintf(stderr, "Could not open %s!\n", qPrintable(projectFile));
+ return -1;
+ }
+
+ if (compressedFile.isEmpty()) {
+ QFileInfo fi(projectFile);
+ compressedFile = basePath + QDir::separator()
+ + fi.baseName() + QLatin1String(".qch");
+ } else {
+ // check if the output dir exists -- create if it doesn't
+ QFileInfo fi(compressedFile);
+ QDir parentDir = fi.dir();
+ if (!parentDir.exists()) {
+ if (!parentDir.mkpath(QLatin1String("."))) {
+ fprintf(stderr, "Could not create output directory: %s\n",
+ qPrintable(parentDir.path()));
+ }
+ }
+ }
+
+ QHelpProjectData *helpData = new QHelpProjectData();
+ if (!helpData->readData(projectFile)) {
+ fprintf(stderr, "%s\n", qPrintable(helpData->errorMessage()));
+ return -1;
+ }
+
+ QCoreApplication app(argc, argv);
+ HelpGenerator generator;
+ bool success = generator.generate(helpData, compressedFile);
+ delete helpData;
+ if (!success) {
+ fprintf(stderr, "%s\n", qPrintable(generator.error()));
+ return -1;
+ }
+ return 0;
+}
diff --git a/tools/assistant/tools/qhelpgenerator/qhelpgenerator.pro b/tools/assistant/tools/qhelpgenerator/qhelpgenerator.pro
new file mode 100644
index 0000000000..68efcf5932
--- /dev/null
+++ b/tools/assistant/tools/qhelpgenerator/qhelpgenerator.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+TARGET = qhelpgenerator
+DESTDIR = ../../../../bin
+CONFIG += qt warn_on help console
+CONFIG -= app_bundle
+QT += network
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+SOURCES += ../shared/helpgenerator.cpp \
+ main.cpp
+
+HEADERS += ../shared/helpgenerator.h
diff --git a/tools/assistant/tools/shared/helpgenerator.cpp b/tools/assistant/tools/shared/helpgenerator.cpp
new file mode 100644
index 0000000000..a40cc4dff8
--- /dev/null
+++ b/tools/assistant/tools/shared/helpgenerator.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "helpgenerator.h"
+
+#include <private/qhelpgenerator_p.h>
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+HelpGenerator::HelpGenerator()
+{
+ generator = new QHelpGenerator(this);
+ connect(generator, SIGNAL(statusChanged(const QString&)),
+ this, SLOT(printStatus(const QString&)));
+ connect(generator, SIGNAL(warning(const QString&)),
+ this, SLOT(printWarning(const QString&)));
+}
+
+bool HelpGenerator::generate(QHelpDataInterface *helpData,
+ const QString &outputFileName)
+{
+ return generator->generate(helpData, outputFileName);
+}
+
+QString HelpGenerator::error() const
+{
+ return generator->error();
+}
+
+void HelpGenerator::printStatus(const QString &msg)
+{
+ fprintf(stdout, "%s\n", qPrintable(msg));
+}
+
+void HelpGenerator::printWarning(const QString &msg)
+{
+ fprintf(stdout, "Warning: %s\n", qPrintable(msg));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/shared/helpgenerator.h b/tools/assistant/tools/shared/helpgenerator.h
new file mode 100644
index 0000000000..ba8a47968f
--- /dev/null
+++ b/tools/assistant/tools/shared/helpgenerator.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HELPGENERATOR_H
+#define HELPGENERATOR_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QHelpDataInterface;
+class QHelpGenerator;
+
+class HelpGenerator : public QObject
+{
+ Q_OBJECT
+
+public:
+ HelpGenerator();
+ bool generate(QHelpDataInterface *helpData,
+ const QString &outputFileName);
+ QString error() const;
+
+private slots:
+ void printStatus(const QString &msg);
+ void printWarning(const QString &msg);
+
+private:
+ QHelpGenerator *generator;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/assistant/tools/tools.pro b/tools/assistant/tools/tools.pro
new file mode 100644
index 0000000000..8bb8cd7006
--- /dev/null
+++ b/tools/assistant/tools/tools.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS += assistant \
+ qhelpgenerator \
+ qcollectiongenerator \
+ qhelpconverter
+
diff --git a/tools/assistant/translations/qt_help.pro b/tools/assistant/translations/qt_help.pro
new file mode 100644
index 0000000000..1684ac5b9d
--- /dev/null
+++ b/tools/assistant/translations/qt_help.pro
@@ -0,0 +1,49 @@
+# Include those manually as they do not contain any directory specification
+
+SOURCES += ../lib/qhelpcollectionhandler.cpp \
+ ../lib/qhelpcontentwidget.cpp \
+ ../lib/qhelpdatainterface.cpp \
+ ../lib/qhelpdbreader.cpp \
+ ../lib/qhelpengine.cpp \
+ ../lib/qhelpenginecore.cpp \
+ ../lib/qhelpgenerator.cpp \
+ ../lib/qhelpindexwidget.cpp \
+ ../lib/qhelpprojectdata.cpp \
+ ../lib/qhelpsearchengine.cpp \
+ ../lib/qhelpsearchindexreader_clucene.cpp \
+ ../lib/qhelpsearchindexreader_default.cpp \
+ ../lib/qhelpsearchindexwriter_clucene.cpp \
+ ../lib/qhelpsearchindexwriter_default.cpp \
+ ../lib/qhelpsearchindex_default.cpp \
+ ../lib/qhelpsearchquerywidget.cpp \
+ ../lib/qhelpsearchresultwidget.cpp
+
+HEADERS += ../lib/qhelpcollectionhandler_p.h \
+ ../lib/qhelpcontentwidget.h \
+ ../lib/qhelpdatainterface_p.h \
+ ../lib/qhelpdbreader_p.h \
+ ../lib/qhelpengine.h \
+ ../lib/qhelpenginecore.h \
+ ../lib/qhelpengine_p.h \
+ ../lib/qhelpgenerator_p.h \
+ ../lib/qhelpindexwidget.h \
+ ../lib/qhelpprojectdata_p.h \
+ ../lib/qhelpsearchengine.h \
+ ../lib/qhelpsearchindexreader_clucene_p.h \
+ ../lib/qhelpsearchindexreader_default_p.h \
+ ../lib/qhelpsearchindexwriter_clucene_p.h \
+ ../lib/qhelpsearchindexwriter_default_p.h \
+ ../lib/qhelpsearchindex_default_p.h \
+ ../lib/qhelpsearchquerywidget.h \
+ ../lib/qhelpsearchresultwidget.h \
+ ../lib/qhelp_global.h
+
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/qt_help_de.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qt_help_ja.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qt_help_pl.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qt_help_untranslated.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qt_help_tr_TR.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qt_help_zh_CN.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qt_help_zh_TW.ts
+error("This is a dummy profile to be used for translations ONLY.")
diff --git a/tools/assistant/translations/translations.pro b/tools/assistant/translations/translations.pro
new file mode 100644
index 0000000000..84bde8c0b6
--- /dev/null
+++ b/tools/assistant/translations/translations.pro
@@ -0,0 +1,49 @@
+# Include those manually as they do not contain any directory specification
+
+FORMS += ../tools/assistant/filternamedialog.ui \
+ ../tools/assistant/installdialog.ui \
+ ../tools/assistant/preferencesdialog.ui \
+ ../tools/assistant/topicchooser.ui \
+ ../tools/assistant/bookmarkdialog.ui
+
+SOURCES += ../tools/assistant/aboutdialog.cpp \
+ ../tools/assistant/bookmarkmanager.cpp \
+ ../tools/assistant/centralwidget.cpp \
+ ../tools/assistant/cmdlineparser.cpp \
+ ../tools/assistant/contentwindow.cpp \
+ ../tools/assistant/filternamedialog.cpp \
+ ../tools/assistant/helpviewer.cpp \
+ ../tools/assistant/indexwindow.cpp \
+ ../tools/assistant/installdialog.cpp \
+ ../tools/assistant/main.cpp \
+ ../tools/assistant/mainwindow.cpp \
+ ../tools/assistant/preferencesdialog.cpp \
+ ../tools/assistant/remotecontrol.cpp \
+ ../tools/assistant/searchwidget.cpp \
+ ../tools/assistant/topicchooser.cpp \
+
+SOURCES += ../../shared/fontpanel/fontpanel.cpp
+
+HEADERS += ../tools/assistant/aboutdialog.h \
+ ../tools/assistant/bookmarkmanager.h \
+ ../tools/assistant/centralwidget.h \
+ ../tools/assistant/cmdlineparser.h \
+ ../tools/assistant/contentwindow.h \
+ ../tools/assistant/filternamedialog.h \
+ ../tools/assistant/helpviewer.h \
+ ../tools/assistant/indexwindow.h \
+ ../tools/assistant/installdialog.h \
+ ../tools/assistant/mainwindow.h \
+ ../tools/assistant/preferencesdialog.h \
+ ../tools/assistant/remotecontrol.h \
+ ../tools/assistant/remotecontrol_win.h \
+ ../tools/assistant/searchwidget.h \
+ ../tools/assistant/topicchooser.h \
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/assistant_de.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_ja.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_pl.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_untranslated.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_tr_TR.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_zh_CN.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_zh_TW.ts
diff --git a/tools/assistant/translations/translations_adp.pro b/tools/assistant/translations/translations_adp.pro
new file mode 100644
index 0000000000..f6ab62ed16
--- /dev/null
+++ b/tools/assistant/translations/translations_adp.pro
@@ -0,0 +1,41 @@
+# Include those manually as they do not contain any directory specification
+
+FORMS += ../compat/helpdialog.ui \
+ ../compat/mainwindow.ui \
+ ../compat/tabbedbrowser.ui \
+ ../compat/topicchooser.ui
+
+SOURCES += ../compat/main.cpp \
+ ../compat/helpwindow.cpp \
+ ../compat/topicchooser.cpp \
+ ../compat/docuparser.cpp \
+ ../compat/index.cpp \
+ ../compat/profile.cpp \
+ ../compat/config.cpp \
+ ../compat/helpdialog.cpp \
+ ../compat/mainwindow.cpp \
+ ../compat/tabbedbrowser.cpp \
+ ../compat/fontsettingsdialog.cpp
+
+SOURCES += ../../shared/fontpanel/fontpanel.cpp
+
+HEADERS += ../compat/helpwindow.h \
+ ../compat/topicchooser.h \
+ ../compat/docuparser.h \
+ ../compat/index.h \
+ ../compat/profile.h \
+ ../compat/helpdialog.h \
+ ../compat/mainwindow.h \
+ ../compat/tabbedbrowser.h \
+ ../compat/config.h \
+ ../compat/fontsettingsdialog.h
+
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/assistant_adp_de.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_adp_ja.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_adp_pl.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_adp_untranslated.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_adp_tr_TR.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_adp_zh_CN.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/assistant_adp_zh_TW.ts
+error("This is a dummy profile to be used for translations ONLY.")
diff --git a/tools/checksdk/README b/tools/checksdk/README
new file mode 100644
index 0000000000..7eba1db489
--- /dev/null
+++ b/tools/checksdk/README
@@ -0,0 +1,3 @@
+checkSDK is used to build Qt/WinCE successfully. It parses the Visual
+Studio configuration and sets up the environment for cross-compilation.
+
diff --git a/tools/checksdk/cesdkhandler.cpp b/tools/checksdk/cesdkhandler.cpp
new file mode 100644
index 0000000000..c1dd6abd2c
--- /dev/null
+++ b/tools/checksdk/cesdkhandler.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "cesdkhandler.h"
+#include <QtCore/QFile>
+#include <QtCore/QDebug>
+#include <QtCore/QXmlStreamReader>
+
+CeSdkInfo::CeSdkInfo() : m_major(0) , m_minor(0)
+{
+}
+
+QStringList CeSdkInfo::environment()
+{
+ QStringList result;
+ QString argument = QLatin1String("PATH=");
+ argument += m_bin;
+ result.append(argument);
+ argument = QLatin1String("INCLUDE=");
+ argument += m_include;
+ result.append(argument);
+ argument = QLatin1String("LIB=");
+ argument += m_lib;
+ result.append(argument);
+ return result;
+}
+
+CeSdkHandler::CeSdkHandler()
+{
+}
+
+bool CeSdkHandler::parse()
+{
+ // look at the file at %VCInstallDir%/vcpackages/WCE.VCPlatform.config
+ // and scan through all installed sdks...
+ m_list.clear();
+ VCInstallDir = qgetenv("VCInstallDir");
+ VCInstallDir += QLatin1String("\\");
+ VSInstallDir = qgetenv("VSInstallDir");
+ VSInstallDir += QLatin1String("\\");
+ if (VCInstallDir.isEmpty() || VSInstallDir.isEmpty())
+ return false;
+
+ QDir vStudioDir(VCInstallDir);
+ if (!vStudioDir.cd("vcpackages"))
+ return false;
+
+ QFile configFile(vStudioDir.absoluteFilePath(QLatin1String("WCE.VCPlatform.config")));
+ if (!configFile.exists() || !configFile.open(QIODevice::ReadOnly))
+ return false;
+
+ QString currentElement;
+ CeSdkInfo currentItem;
+ QXmlStreamReader xml(&configFile);
+ while (!xml.atEnd()) {
+ xml.readNext();
+ if (xml.isStartElement()) {
+ currentElement = xml.name().toString();
+ if (currentElement == QLatin1String("Platform"))
+ currentItem = CeSdkInfo();
+ else if (currentElement == QLatin1String("Directories")) {
+ QXmlStreamAttributes attr = xml.attributes();
+ currentItem.m_include = fixPaths(attr.value(QLatin1String("Include")).toString());
+ currentItem.m_lib = fixPaths(attr.value(QLatin1String("Library")).toString());
+ currentItem.m_bin = fixPaths(attr.value(QLatin1String("Path")).toString());
+ }
+ } else if (xml.isEndElement()) {
+ if (xml.name().toString() == QLatin1String("Platform"))
+ m_list.append(currentItem);
+ } else if (xml.isCharacters() && !xml.isWhitespace()) {
+ if (currentElement == QLatin1String("PlatformName"))
+ currentItem.m_name = xml.text().toString();
+ else if (currentElement == QLatin1String("OSMajorVersion"))
+ currentItem.m_major = xml.text().toString().toInt();
+ else if (currentElement == QLatin1String("OSMinorVersion"))
+ currentItem.m_minor = xml.text().toString().toInt();
+ }
+ }
+
+ if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
+ qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
+ return false;
+ }
+ return m_list.size() > 0 ? true : false;
+}
+
+CeSdkInfo CeSdkHandler::find(const QString &name)
+{
+ for (QList<CeSdkInfo>::iterator it = m_list.begin(); it != m_list.end(); ++it) {
+ if (it->name() == name)
+ return *it;
+ }
+ return CeSdkInfo();
+}
diff --git a/tools/checksdk/cesdkhandler.h b/tools/checksdk/cesdkhandler.h
new file mode 100644
index 0000000000..22a3e0e247
--- /dev/null
+++ b/tools/checksdk/cesdkhandler.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef CE_SDK_HANDLER_INCL
+#define CE_SDK_HANDLER_INCL
+
+#include <QStringList>
+#include <QDir>
+
+QT_USE_NAMESPACE
+
+#define VCINSTALL_MACRO "$(VCInstallDir)"
+#define VSINSTALL_MACRO "$(VSInstallDir)"
+
+class CeSdkInfo
+{
+public:
+ CeSdkInfo();
+ inline QString name();
+ inline QString binPath();
+ inline QString includePath();
+ inline QString libPath();
+ QStringList environment();
+ inline bool isValid();
+ inline int majorVersion();
+ inline int minorVersion();
+ inline bool isSupported();
+private:
+ friend class CeSdkHandler;
+ QString m_name;
+ QString m_bin;
+ QString m_include;
+ QString m_lib;
+ int m_major;
+ int m_minor;
+};
+
+inline QString CeSdkInfo::name(){ return m_name; }
+inline QString CeSdkInfo::binPath(){ return m_bin; }
+inline QString CeSdkInfo::includePath(){ return m_include; }
+inline QString CeSdkInfo::libPath(){ return m_lib; }
+inline bool CeSdkInfo::isValid(){ return !m_name.isEmpty() && !m_bin.isEmpty() && !m_include.isEmpty() && !m_lib.isEmpty(); }
+inline int CeSdkInfo::majorVersion(){ return m_major; }
+inline int CeSdkInfo::minorVersion(){ return m_minor; }
+inline bool CeSdkInfo::isSupported() { return m_major >= 5; }
+
+class CeSdkHandler
+{
+public:
+ CeSdkHandler();
+ bool parse();
+ inline QList<CeSdkInfo> listAll() const;
+ CeSdkInfo find(const QString &name);
+private:
+ inline QString fixPaths(QString path) const;
+ QList<CeSdkInfo> m_list;
+ QString VCInstallDir;
+ QString VSInstallDir;
+};
+
+inline QList<CeSdkInfo> CeSdkHandler::listAll() const
+{
+ return m_list;
+}
+
+inline QString CeSdkHandler::fixPaths(QString path) const
+{
+ QString str = QDir::toNativeSeparators(QDir::cleanPath(path.replace(VCINSTALL_MACRO, VCInstallDir).replace(VSINSTALL_MACRO, VSInstallDir).replace(QLatin1String("$(PATH)"), QLatin1String("%PATH%"))));
+ if (str.endsWith(';'))
+ str.truncate(str.length() - 1);
+ return str;
+}
+
+#endif
diff --git a/tools/checksdk/checksdk.pro b/tools/checksdk/checksdk.pro
new file mode 100644
index 0000000000..e364f26f38
--- /dev/null
+++ b/tools/checksdk/checksdk.pro
@@ -0,0 +1,71 @@
+TEMPLATE = app
+DESTDIR = ../../bin
+TARGET = checksdk
+DEPENDPATH += .
+INCLUDEPATH += .
+QT =
+CONFIG += console
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+DEFINES += QT_BOOTSTRAPPED QT_NO_CODECS QT_LITE_UNICODE QT_NO_LIBRARY \
+ QT_NO_STL QT_NO_COMPRESS QT_NO_DATASTREAM \
+ QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_NO_THREAD \
+ QT_NO_SYSTEMLOCALE QT_NO_GEOM_VARIANT \
+ QT_NODLL QT_NO_QOBJECT
+
+INCLUDEPATH = \
+ $$QT_BUILD_TREE/src/corelib/arch \
+ $$QT_BUILD_TREE/include \
+ $$QT_BUILD_TREE/include/QtCore
+
+DEPENDPATH += $$INCLUDEPATH $$QT_BUILD_TREE/src/corelib/base $$QT_BUILD_TREE/src/corelib/tools $$QT_BUILD_TREE/src/corelib/io
+
+# Input
+SOURCES += \
+ main.cpp \
+ cesdkhandler.cpp
+
+HEADERS += \
+ cesdkhandler.h
+
+# Bootstrapped Input
+SOURCES += \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qmetatype.cpp \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstring.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qbuffer.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qurl.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearray.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearraymatcher.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvector.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvsnprintf.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlistdata.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qhash.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qglobal.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qmalloc.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qnumeric.cpp \
+ $$QT_SOURCE_TREE/src/corelib/xml/qxmlstream.cpp \
+ $$QT_SOURCE_TREE/src/corelib/xml/qxmlutils.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qregexp.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \
+ $$QT_BUILD_TREE/src/corelib/global/qconfig.cpp
diff --git a/tools/checksdk/main.cpp b/tools/checksdk/main.cpp
new file mode 100644
index 0000000000..1d4b616e84
--- /dev/null
+++ b/tools/checksdk/main.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "cesdkhandler.h"
+#include <QtCore/QStringList>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+
+void usage()
+{
+ qDebug() << "SDK Scanner - Convenience Tool to setup your environment";
+ qDebug() << " for crosscompilation to Windows CE";
+ qDebug() << "Options:";
+ qDebug() << "-help This output";
+ qDebug() << "-list List all available SDKs";
+ qDebug() << "-sdk <name> Select specified SDK.";
+ qDebug() << " Note: SDK names with spaces need to be";
+ qDebug() << " specified in parenthesis";
+ qDebug() << " default: Windows Mobile 5.0 Pocket PC SDK (ARMV4I)";
+ qDebug() << "-script <file> Create a script file which can be launched";
+ qDebug() << " to setup your environment for specified SDK";
+}
+
+int main(int argc, char **argv)
+{
+ if (argc == 1) {
+ usage();
+ return 0;
+ }
+ QString sdkName;
+ bool operationList = false;
+ QString scriptFile;
+
+ QStringList arguments;
+ for (int i=0; i < argc; ++i)
+ arguments.append(QLatin1String(argv[i]));
+ for (int i=1; i < arguments.size(); ++i) {
+ if (arguments[i].toLower() == QLatin1String("-help")) {
+ usage();
+ return 0;
+ } else if (arguments[i].toLower() == QLatin1String("-list")) {
+ operationList = true;
+ } else if (arguments[i].toLower() == QLatin1String("-sdk")) {
+ if (i+1 >= arguments.size()) {
+ qWarning("No SDK specified.");
+ return -1;
+ }
+ sdkName = arguments[++i];
+ } else if (arguments[i].toLower() == QLatin1String("-script")) {
+ if (i+1 >= arguments.size()) {
+ qWarning("No scriptfile specified.");
+ return -1;
+ }
+ scriptFile = arguments[++i];
+ } else {
+ qWarning("Unknown option:%s", qPrintable(arguments[i]));
+ usage();
+ return -1;
+ }
+ }
+
+ // Check for SDK Name, otherwise use Windows Mobile as default
+ if (sdkName.isEmpty()) {
+ qWarning("No SDK specified: Defaulting to Windows Mobile 5.0 Pocket PC SDK");
+ sdkName = QString::fromLatin1("Windows Mobile 5.0 Pocket PC SDK (ARMV4I)");
+ }
+
+ CeSdkHandler handler;
+ if (!handler.parse()) {
+ qWarning("Could not find any installed SDK, aborting!");
+ return -1;
+ }
+
+ QList<CeSdkInfo> list = handler.listAll();
+
+ if (operationList) {
+ qDebug() << "Available SDKs:";
+ for (QList<CeSdkInfo>::iterator it = list.begin(); it != list.end(); ++it)
+ qDebug() << "SDK Name:" << it->name();
+ return 0;
+ }
+
+ // finally find the given SDK and prompt out the environment to be set
+ for (QList<CeSdkInfo>::iterator it = list.begin(); it != list.end(); ++it ) {
+ if (sdkName == it->name()) {
+ if (!it->isValid()) {
+ qWarning("Selected SDK is not valid!");
+ return -1;
+ } else if (!it->isSupported()) {
+ qWarning("Selected SDK is not officially supported and might not work");
+ }
+ QString binPath, includePath, libPath;
+ binPath = QString::fromLatin1("PATH=") + it->binPath();
+ includePath = QString::fromLatin1("INCLUDE=") + it->includePath();
+ libPath = QString::fromLatin1("LIB=") + it->libPath();
+ if (scriptFile.isEmpty()) {
+ qDebug() << "Please set up your environment with the following paths:";
+ qDebug() << qPrintable(binPath);
+ qDebug() << qPrintable(includePath);
+ qDebug() << qPrintable(libPath);
+ return 0;
+ } else {
+ QFile file(scriptFile);
+ if (!file.open(QIODevice::WriteOnly)) {
+ qWarning("Could not open target script file");
+ return -1;
+ }
+ QString content;
+ content += QLatin1String("@echo off\n");
+ content += QLatin1String("echo Environment Selection:") + sdkName + QLatin1String("\n");
+ content += QLatin1String("set ") + binPath + QLatin1String("\n");
+ content += QLatin1String("set ") + includePath + QLatin1String("\n");
+ content += QLatin1String("set ") + libPath + QLatin1String("\n");
+ file.write(content.toLatin1());
+ return 0;
+ }
+ }
+ }
+ qWarning("Could not find specified SDK: %s" , qPrintable(sdkName));
+ return 0;
+} \ No newline at end of file
diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro
new file mode 100644
index 0000000000..1ce9a1bea1
--- /dev/null
+++ b/tools/configure/configure.pro
@@ -0,0 +1,106 @@
+TARGET = configure
+DESTDIR = ../..
+
+CONFIG += console flat
+CONFIG -= moc qt
+DEFINES = QT_NODLL QT_NO_CODECS QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_LITE_COMPONENT QT_NO_STL QT_NO_COMPRESS QT_BUILD_QMAKE QT_NO_THREAD QT_NO_QOBJECT _CRT_SECURE_NO_DEPRECATE
+
+
+win32 : LIBS += -lole32 -ladvapi32
+win32-msvc.net | win32-msvc2* : QMAKE_CXXFLAGS += /EHsc
+win32-g++ : LIBS += -luuid
+
+win32-msvc* {
+ QMAKE_CFLAGS_RELEASE -= -MD
+ QMAKE_CFLAGS_DEBUG -= -MDd
+ QMAKE_CXXFLAGS_RELEASE -= -MD
+ QMAKE_CXXFLAGS_DEBUG -= -MDd
+}
+
+PRECOMPILED_HEADER = configure_pch.h
+
+INCPATH += $$QT_SOURCE_TREE/src/corelib/arch/generic \
+ $$QT_SOURCE_TREE/src/corelib/global \
+ $$QT_BUILD_TREE/include \
+ $$QT_BUILD_TREE/include/QtCore \
+
+HEADERS = configureapp.h environment.h tools.h\
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearray.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearraymatcher.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qchar.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qhash.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlist.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvector.h \
+ $$QT_SOURCE_TREE/src/corelib/codecs/qtextcodec.h \
+ $$QT_SOURCE_TREE/src/corelib/global/qglobal.h \
+ $$QT_SOURCE_TREE/src/corelib/global/qnumeric.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qbuffer.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qdatastream.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qdir.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qfile.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_p.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.h \
+ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qmap.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qregexp.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstring.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstringmatcher.h \
+ $$QT_SOURCE_TREE/src/corelib/tools/qunicodetables_p.h
+
+
+SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearray.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearraymatcher.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qchar.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qhash.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlistdata.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvector.cpp \
+ $$QT_SOURCE_TREE/src/corelib/codecs/qtextcodec.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qglobal.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qnumeric.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qbuffer.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdatastream.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qregexp.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstring.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstringmatcher.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qunicodetables.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvsnprintf.cpp \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qurl.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qline.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qsize.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qpoint.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qrect.cpp \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qmetatype.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qmalloc.cpp
+
+win32:SOURCES += $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp
+
+DEFINES += COMMERCIAL_VERSION
+
+INCLUDEPATH += $$QT_SOURCE_TREE/src/corelib/arch/generic \
+ $$QT_SOURCE_TREE/include/QtCore \
diff --git a/tools/configure/configure_pch.h b/tools/configure/configure_pch.h
new file mode 100644
index 0000000000..24eac4f092
--- /dev/null
+++ b/tools/configure/configure_pch.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if (defined(_WIN32) || defined(__NT__))
+# define QT_UNDEF_MACROS_IN_PCH
+# define _WINSCARD_H_
+# define _POSIX_ /* Make sure PATH_MAX et al. are defined */
+# include <limits.h>
+# undef _POSIX_ /* Don't polute */
+
+ /* Make sure IP v6 is defined first of all, before windows.h */
+# ifndef QT_NO_IPV6
+# include <winsock2.h>
+# endif
+# include <stdlib.h>
+#endif
+
+#if defined __cplusplus
+#include <qglobal.h>
+#include <qlist.h>
+#include <qvariant.h> // All moc genereated code has this include
+#include <qplatformdefs.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+
+#include <limits.h>
+#include <stdlib.h>
+#endif
+
+#if defined(QT_UNDEF_MACROS_IN_PCH)
+# undef max /* These are defined in windef.h, but */
+# undef min /* we don't want them when building Qt */
+# undef _WINSCARD_H_
+#endif
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
new file mode 100644
index 0000000000..8c0dc39f48
--- /dev/null
+++ b/tools/configure/configureapp.cpp
@@ -0,0 +1,3586 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "configureapp.h"
+#include "environment.h"
+#ifdef COMMERCIAL_VERSION
+# include "tools.h"
+#endif
+
+#include <QDate>
+#include <qdir.h>
+#include <qtemporaryfile.h>
+#include <qstack.h>
+#include <qdebug.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <qhash.h>
+
+#include <iostream>
+#include <windows.h>
+#include <conio.h>
+
+QT_BEGIN_NAMESPACE
+
+std::ostream &operator<<( std::ostream &s, const QString &val ) {
+ s << val.toLocal8Bit().data();
+ return s;
+}
+
+
+using namespace std;
+
+// Macros to simplify options marking
+#define MARK_OPTION(x,y) ( dictionary[ #x ] == #y ? "*" : " " )
+
+
+bool writeToFile(const char* text, const QString &filename)
+{
+ QByteArray symFile(text);
+ QFile file(filename);
+ QDir dir(QFileInfo(file).absoluteDir());
+ if (!dir.exists())
+ dir.mkpath(dir.absolutePath());
+ if (!file.open(QFile::WriteOnly)) {
+ cout << "Couldn't write to " << qPrintable(filename) << ": " << qPrintable(file.errorString())
+ << endl;
+ return false;
+ }
+ file.write(symFile);
+ return true;
+}
+
+Configure::Configure( int& argc, char** argv )
+{
+ useUnixSeparators = false;
+ // Default values for indentation
+ optionIndent = 4;
+ descIndent = 25;
+ outputWidth = 0;
+ // Get console buffer output width
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (GetConsoleScreenBufferInfo(hStdout, &info))
+ outputWidth = info.dwSize.X - 1;
+ outputWidth = qMin(outputWidth, 79); // Anything wider gets unreadable
+ if (outputWidth < 35) // Insanely small, just use 79
+ outputWidth = 79;
+ int i;
+
+ /*
+ ** Set up the initial state, the default
+ */
+ dictionary[ "CONFIGCMD" ] = argv[ 0 ];
+
+ for ( i = 1; i < argc; i++ )
+ configCmdLine += argv[ i ];
+
+
+ // Get the path to the executable
+ QFileInfo sourcePathInfo;
+ QT_WA({
+ unsigned short module_name[256];
+ GetModuleFileNameW(0, reinterpret_cast<wchar_t *>(module_name), sizeof(module_name));
+ sourcePathInfo = QString::fromUtf16(module_name);
+ }, {
+ char module_name[256];
+ GetModuleFileNameA(0, module_name, sizeof(module_name));
+ sourcePathInfo = QString::fromLocal8Bit(module_name);
+ });
+ sourcePath = sourcePathInfo.absolutePath();
+ sourceDir = sourcePathInfo.dir();
+ buildPath = QDir::currentPath();
+#if 0
+ const QString installPath = QString("C:\\Qt\\%1").arg(QT_VERSION_STR);
+#else
+ const QString installPath = buildPath;
+#endif
+ if(sourceDir != buildDir) { //shadow builds!
+ if (!findFile("perl") && !findFile("perl.exe")) {
+ cout << "Error: Creating a shadow build of Qt requires" << endl
+ << "perl to be in the PATH environment";
+ exit(0); // Exit cleanly for Ctrl+C
+ }
+
+ cout << "Preparing build tree..." << endl;
+ QDir(buildPath).mkpath("bin");
+
+ { //duplicate qmake
+ QStack<QString> qmake_dirs;
+ qmake_dirs.push("qmake");
+ while(!qmake_dirs.isEmpty()) {
+ QString dir = qmake_dirs.pop();
+ QString od(buildPath + "/" + dir);
+ QString id(sourcePath + "/" + dir);
+ QFileInfoList entries = QDir(id).entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries);
+ for(int i = 0; i < entries.size(); ++i) {
+ QFileInfo fi(entries.at(i));
+ if(fi.isDir()) {
+ qmake_dirs.push(dir + "/" + fi.fileName());
+ QDir().mkpath(od + "/" + fi.fileName());
+ } else {
+ QDir().mkpath(od );
+ bool justCopy = true;
+ const QString fname = fi.fileName();
+ const QString outFile(od + "/" + fname), inFile(id + "/" + fname);
+ if(fi.fileName() == "Makefile") { //ignore
+ } else if(fi.suffix() == "h" || fi.suffix() == "cpp") {
+ QTemporaryFile tmpFile;
+ if(tmpFile.open()) {
+ QTextStream stream(&tmpFile);
+ stream << "#include \"" << inFile << "\"" << endl;
+ justCopy = false;
+ stream.flush();
+ tmpFile.flush();
+ if(filesDiffer(tmpFile.fileName(), outFile)) {
+ QFile::remove(outFile);
+ tmpFile.copy(outFile);
+ }
+ }
+ }
+ if(justCopy && filesDiffer(inFile, outFile))
+ QFile::copy(inFile, outFile);
+ }
+ }
+ }
+ }
+
+ { //make a syncqt script(s) that can be used in the shadow
+ QFile syncqt(buildPath + "/bin/syncqt");
+ if(syncqt.open(QFile::WriteOnly)) {
+ QTextStream stream(&syncqt);
+ stream << "#!/usr/bin/perl -w" << endl
+ << "require \"" << sourcePath + "/bin/syncqt\";" << endl;
+ }
+ QFile syncqt_bat(buildPath + "/bin/syncqt.bat");
+ if(syncqt_bat.open(QFile::WriteOnly)) {
+ QTextStream stream(&syncqt_bat);
+ stream << "@echo off" << endl
+ << "set QTDIR=" << QDir::toNativeSeparators(sourcePath) << endl
+ << "call " << fixSeparators(sourcePath) << fixSeparators("/bin/syncqt.bat -outdir \"") << fixSeparators(buildPath) << "\"" << endl
+ << "set QTDIR=" << QDir::toNativeSeparators(buildPath) << endl;
+ syncqt_bat.close();
+ }
+ }
+
+ // For Windows CE and shadow builds we need to copy these to the
+ // build directory.
+ QFile::copy(sourcePath + "/bin/setcepaths.bat" , buildPath + "/bin/setcepaths.bat");
+
+ //copy the mkspecs
+ buildDir.mkpath("mkspecs");
+ if(!Environment::cpdir(sourcePath + "/mkspecs", buildPath + "/mkspecs")){
+ cout << "Couldn't copy mkspecs!" << sourcePath << " " << buildPath << endl;
+ dictionary["DONE"] = "error";
+ return;
+ }
+ }
+
+ dictionary[ "QT_SOURCE_TREE" ] = fixSeparators(sourcePath);
+ dictionary[ "QT_BUILD_TREE" ] = fixSeparators(buildPath);
+ dictionary[ "QT_INSTALL_PREFIX" ] = fixSeparators(installPath);
+
+ dictionary[ "QMAKESPEC" ] = getenv("QMAKESPEC");
+ if (dictionary[ "QMAKESPEC" ].size() == 0) {
+ dictionary[ "QMAKESPEC" ] = Environment::detectQMakeSpec();
+ dictionary[ "QMAKESPEC_FROM" ] = "detected";
+ } else {
+ dictionary[ "QMAKESPEC_FROM" ] = "env";
+ }
+
+ dictionary[ "ARCHITECTURE" ] = "windows";
+ dictionary[ "QCONFIG" ] = "full";
+ dictionary[ "EMBEDDED" ] = "no";
+ dictionary[ "BUILD_QMAKE" ] = "yes";
+ dictionary[ "DSPFILES" ] = "yes";
+ dictionary[ "VCPROJFILES" ] = "yes";
+ dictionary[ "QMAKE_INTERNAL" ] = "no";
+ dictionary[ "FAST" ] = "no";
+ dictionary[ "NOPROCESS" ] = "no";
+ dictionary[ "STL" ] = "yes";
+ dictionary[ "EXCEPTIONS" ] = "yes";
+ dictionary[ "RTTI" ] = "yes";
+ dictionary[ "MMX" ] = "auto";
+ dictionary[ "3DNOW" ] = "auto";
+ dictionary[ "SSE" ] = "auto";
+ dictionary[ "SSE2" ] = "auto";
+ dictionary[ "IWMMXT" ] = "auto";
+ dictionary[ "SYNCQT" ] = "auto";
+ dictionary[ "CE_CRT" ] = "no";
+ dictionary[ "CETEST" ] = "auto";
+ dictionary[ "CE_SIGNATURE" ] = "no";
+ dictionary[ "SCRIPTTOOLS" ] = "yes";
+ dictionary[ "XMLPATTERNS" ] = "auto";
+ dictionary[ "PHONON" ] = "auto";
+ dictionary[ "PHONON_BACKEND" ] = "yes";
+ dictionary[ "DIRECTSHOW" ] = "no";
+ dictionary[ "WEBKIT" ] = "auto";
+ dictionary[ "PLUGIN_MANIFESTS" ] = "yes";
+
+ QString version;
+ QFile qglobal_h(sourcePath + "/src/corelib/global/qglobal.h");
+ if (qglobal_h.open(QFile::ReadOnly)) {
+ QTextStream read(&qglobal_h);
+ QRegExp version_regexp("^# *define *QT_VERSION_STR *\"([^\"]*)\"");
+ QString line;
+ while (!read.atEnd()) {
+ line = read.readLine();
+ if (version_regexp.exactMatch(line)) {
+ version = version_regexp.cap(1).trimmed();
+ if (!version.isEmpty())
+ break;
+ }
+ }
+ qglobal_h.close();
+ }
+
+ if (version.isEmpty())
+ version = QString("%1.%2.%3").arg(QT_VERSION>>16).arg(((QT_VERSION>>8)&0xff)).arg(QT_VERSION&0xff);
+
+ dictionary[ "VERSION" ] = version;
+ {
+ QRegExp version_re("([0-9]*)\\.([0-9]*)\\.([0-9]*)(|-.*)");
+ if(version_re.exactMatch(version)) {
+ dictionary[ "VERSION_MAJOR" ] = version_re.cap(1);
+ dictionary[ "VERSION_MINOR" ] = version_re.cap(2);
+ dictionary[ "VERSION_PATCH" ] = version_re.cap(3);
+ }
+ }
+
+ dictionary[ "REDO" ] = "no";
+ dictionary[ "DEPENDENCIES" ] = "no";
+
+ dictionary[ "BUILD" ] = "debug";
+ dictionary[ "BUILDALL" ] = "auto"; // Means yes, but not explicitly
+
+ dictionary[ "BUILDTYPE" ] = "none";
+
+ dictionary[ "BUILDDEV" ] = "no";
+ dictionary[ "BUILDNOKIA" ] = "no";
+
+ dictionary[ "SHARED" ] = "yes";
+
+ dictionary[ "ZLIB" ] = "auto";
+
+ dictionary[ "GIF" ] = "auto";
+ dictionary[ "TIFF" ] = "auto";
+ dictionary[ "JPEG" ] = "auto";
+ dictionary[ "PNG" ] = "auto";
+ dictionary[ "MNG" ] = "auto";
+ dictionary[ "LIBTIFF" ] = "auto";
+ dictionary[ "LIBJPEG" ] = "auto";
+ dictionary[ "LIBPNG" ] = "auto";
+ dictionary[ "LIBMNG" ] = "auto";
+
+ dictionary[ "QT3SUPPORT" ] = "yes";
+ dictionary[ "ACCESSIBILITY" ] = "yes";
+ dictionary[ "OPENGL" ] = "yes";
+ dictionary[ "DIRECT3D" ] = "auto";
+ dictionary[ "IPV6" ] = "yes"; // Always, dynamicly loaded
+ dictionary[ "OPENSSL" ] = "auto";
+ dictionary[ "DBUS" ] = "auto";
+
+ dictionary[ "STYLE_WINDOWS" ] = "yes";
+ dictionary[ "STYLE_WINDOWSXP" ] = "auto";
+ dictionary[ "STYLE_WINDOWSVISTA" ] = "auto";
+ dictionary[ "STYLE_PLASTIQUE" ] = "yes";
+ dictionary[ "STYLE_CLEANLOOKS" ]= "yes";
+ dictionary[ "STYLE_WINDOWSCE" ] = "no";
+ dictionary[ "STYLE_WINDOWSMOBILE" ] = "no";
+ dictionary[ "STYLE_MOTIF" ] = "yes";
+ dictionary[ "STYLE_CDE" ] = "yes";
+ dictionary[ "STYLE_GTK" ] = "no";
+
+ dictionary[ "SQL_MYSQL" ] = "no";
+ dictionary[ "SQL_ODBC" ] = "no";
+ dictionary[ "SQL_OCI" ] = "no";
+ dictionary[ "SQL_PSQL" ] = "no";
+ dictionary[ "SQL_TDS" ] = "no";
+ dictionary[ "SQL_DB2" ] = "no";
+ dictionary[ "SQL_SQLITE" ] = "auto";
+ dictionary[ "SQL_SQLITE_LIB" ] = "qt";
+ dictionary[ "SQL_SQLITE2" ] = "no";
+ dictionary[ "SQL_IBASE" ] = "no";
+ dictionary[ "GRAPHICS_SYSTEM" ] = "raster";
+
+ QString tmp = dictionary[ "QMAKESPEC" ];
+ if (tmp.contains("\\")) {
+ tmp = tmp.mid( tmp.lastIndexOf( "\\" ) + 1 );
+ } else {
+ tmp = tmp.mid( tmp.lastIndexOf("/") + 1 );
+ }
+ dictionary[ "QMAKESPEC" ] = tmp;
+
+ dictionary[ "INCREDIBUILD_XGE" ] = "auto";
+}
+
+Configure::~Configure()
+{
+ for (int i=0; i<3; ++i) {
+ QList<MakeItem*> items = makeList[i];
+ for (int j=0; j<items.size(); ++j)
+ delete items[j];
+ }
+}
+
+QString Configure::fixSeparators(QString somePath)
+{
+ return useUnixSeparators ?
+ QDir::fromNativeSeparators(somePath) :
+ QDir::toNativeSeparators(somePath);
+}
+
+// We could use QDir::homePath() + "/.qt-license", but
+// that will only look in the first of $HOME,$USERPROFILE
+// or $HOMEDRIVE$HOMEPATH. So, here we try'em all to be
+// more forgiving for the end user..
+QString Configure::firstLicensePath()
+{
+ QStringList allPaths;
+ allPaths << "./.qt-license"
+ << QString::fromLocal8Bit(getenv("HOME")) + "/.qt-license"
+ << QString::fromLocal8Bit(getenv("USERPROFILE")) + "/.qt-license"
+ << QString::fromLocal8Bit(getenv("HOMEDRIVE")) + QString::fromLocal8Bit(getenv("HOMEPATH")) + "/.qt-license";
+ for (int i = 0; i< allPaths.count(); ++i)
+ if (QFile::exists(allPaths.at(i)))
+ return allPaths.at(i);
+ return QString();
+}
+
+
+// #### somehow I get a compiler error about vc++ reaching the nesting limit without
+// undefining the ansi for scoping.
+#ifdef for
+#undef for
+#endif
+
+void Configure::parseCmdLine()
+{
+ int argCount = configCmdLine.size();
+ int i = 0;
+
+#if !defined(EVAL)
+ if (argCount < 1) // skip rest if no arguments
+ ;
+ else if( configCmdLine.at(i) == "-redo" ) {
+ dictionary[ "REDO" ] = "yes";
+ configCmdLine.clear();
+ reloadCmdLine();
+ }
+ else if( configCmdLine.at(i) == "-loadconfig" ) {
+ ++i;
+ if (i != argCount) {
+ dictionary[ "REDO" ] = "yes";
+ dictionary[ "CUSTOMCONFIG" ] = "_" + configCmdLine.at(i);
+ configCmdLine.clear();
+ reloadCmdLine();
+ } else {
+ dictionary[ "HELP" ] = "yes";
+ }
+ i = 0;
+ }
+ argCount = configCmdLine.size();
+#endif
+
+ // Look first for XQMAKESPEC
+ for(int j = 0 ; j < argCount; ++j)
+ {
+ if( configCmdLine.at(j) == "-xplatform") {
+ ++j;
+ if (j == argCount)
+ break;
+ dictionary["XQMAKESPEC"] = configCmdLine.at(j);
+ if (!dictionary[ "XQMAKESPEC" ].isEmpty())
+ applySpecSpecifics();
+ }
+ }
+
+ for( ; i<configCmdLine.size(); ++i ) {
+ bool continueElse = false;
+ if( configCmdLine.at(i) == "-help"
+ || configCmdLine.at(i) == "-h"
+ || configCmdLine.at(i) == "-?" )
+ dictionary[ "HELP" ] = "yes";
+
+#if !defined(EVAL)
+ else if( configCmdLine.at(i) == "-qconfig" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ dictionary[ "QCONFIG" ] = configCmdLine.at(i);
+ }
+
+ else if ( configCmdLine.at(i) == "-buildkey" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ dictionary[ "USER_BUILD_KEY" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-release" ) {
+ dictionary[ "BUILD" ] = "release";
+ if (dictionary[ "BUILDALL" ] == "auto")
+ dictionary[ "BUILDALL" ] = "no";
+ } else if( configCmdLine.at(i) == "-debug" ) {
+ dictionary[ "BUILD" ] = "debug";
+ if (dictionary[ "BUILDALL" ] == "auto")
+ dictionary[ "BUILDALL" ] = "no";
+ } else if( configCmdLine.at(i) == "-debug-and-release" )
+ dictionary[ "BUILDALL" ] = "yes";
+
+ else if( configCmdLine.at(i) == "-shared" )
+ dictionary[ "SHARED" ] = "yes";
+ else if( configCmdLine.at(i) == "-static" )
+ dictionary[ "SHARED" ] = "no";
+ else if( configCmdLine.at(i) == "-developer-build" )
+ dictionary[ "BUILDDEV" ] = "yes";
+ else if( configCmdLine.at(i) == "-nokia-developer" ) {
+ dictionary[ "BUILDNOKIA" ] = "yes";
+ dictionary[ "BUILDDEV" ] = "yes";
+ dictionary["LICENSE_CONFIRMED"] = "yes";
+ }
+ else if( configCmdLine.at(i) == "-opensource" ) {
+ dictionary[ "BUILDTYPE" ] = "opensource";
+ }
+ else if( configCmdLine.at(i) == "-commercial" ) {
+ dictionary[ "BUILDTYPE" ] = "commercial";
+ }
+#endif
+
+ else if( configCmdLine.at(i) == "-platform" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ dictionary[ "QMAKESPEC" ] = configCmdLine.at(i);
+ dictionary[ "QMAKESPEC_FROM" ] = "commandline";
+ } else if( configCmdLine.at(i) == "-arch" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ dictionary[ "ARCHITECTURE" ] = configCmdLine.at(i);
+ if (configCmdLine.at(i) == "boundschecker") {
+ dictionary[ "ARCHITECTURE" ] = "generic"; // Boundschecker uses the generic arch,
+ qtConfig += "boundschecker"; // but also needs this CONFIG option
+ }
+ } else if( configCmdLine.at(i) == "-embedded" ) {
+ dictionary[ "EMBEDDED" ] = "yes";
+ } else if( configCmdLine.at(i) == "-xplatform") {
+ ++i;
+ // do nothing
+ }
+
+
+#if !defined(EVAL)
+ else if( configCmdLine.at(i) == "-no-zlib" ) {
+ // No longer supported since Qt 4.4.0
+ // But save the information for later so that we can print a warning
+ //
+ // If you REALLY really need no zlib support, you can still disable
+ // it by doing the following:
+ // add "no-zlib" to mkspecs/qconfig.pri
+ // #define QT_NO_COMPRESS (probably by adding to src/corelib/global/qconfig.h)
+ //
+ // There's no guarantee that Qt will build under those conditions
+
+ dictionary[ "ZLIB_FORCED" ] = "yes";
+ } else if( configCmdLine.at(i) == "-qt-zlib" ) {
+ dictionary[ "ZLIB" ] = "qt";
+ } else if( configCmdLine.at(i) == "-system-zlib" ) {
+ dictionary[ "ZLIB" ] = "system";
+ }
+
+ // Image formats --------------------------------------------
+ else if( configCmdLine.at(i) == "-no-gif" )
+ dictionary[ "GIF" ] = "no";
+ else if( configCmdLine.at(i) == "-qt-gif" )
+ dictionary[ "GIF" ] = "auto";
+
+ else if( configCmdLine.at(i) == "-no-libtiff" ) {
+ dictionary[ "TIFF"] = "no";
+ dictionary[ "LIBTIFF" ] = "no";
+ } else if( configCmdLine.at(i) == "-qt-libtiff" ) {
+ dictionary[ "TIFF" ] = "plugin";
+ dictionary[ "LIBTIFF" ] = "qt";
+ } else if( configCmdLine.at(i) == "-system-libtiff" ) {
+ dictionary[ "TIFF" ] = "plugin";
+ dictionary[ "LIBTIFF" ] = "system";
+ }
+
+ else if( configCmdLine.at(i) == "-no-libjpeg" ) {
+ dictionary[ "JPEG" ] = "no";
+ dictionary[ "LIBJPEG" ] = "no";
+ } else if( configCmdLine.at(i) == "-qt-libjpeg" ) {
+ dictionary[ "JPEG" ] = "plugin";
+ dictionary[ "LIBJPEG" ] = "qt";
+ } else if( configCmdLine.at(i) == "-system-libjpeg" ) {
+ dictionary[ "JPEG" ] = "plugin";
+ dictionary[ "LIBJPEG" ] = "system";
+ }
+
+ else if( configCmdLine.at(i) == "-no-libpng" ) {
+ dictionary[ "PNG" ] = "no";
+ dictionary[ "LIBPNG" ] = "no";
+ } else if( configCmdLine.at(i) == "-qt-libpng" ) {
+ dictionary[ "PNG" ] = "qt";
+ dictionary[ "LIBPNG" ] = "qt";
+ } else if( configCmdLine.at(i) == "-system-libpng" ) {
+ dictionary[ "PNG" ] = "qt";
+ dictionary[ "LIBPNG" ] = "system";
+ }
+
+ else if( configCmdLine.at(i) == "-no-libmng" ) {
+ dictionary[ "MNG" ] = "no";
+ dictionary[ "LIBMNG" ] = "no";
+ } else if( configCmdLine.at(i) == "-qt-libmng" ) {
+ dictionary[ "MNG" ] = "qt";
+ dictionary[ "LIBMNG" ] = "qt";
+ } else if( configCmdLine.at(i) == "-system-libmng" ) {
+ dictionary[ "MNG" ] = "qt";
+ dictionary[ "LIBMNG" ] = "system";
+ }
+ // CE- C runtime --------------------------------------------
+ else if( configCmdLine.at(i) == "-crt" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ QDir cDir(configCmdLine.at(i));
+ if (!cDir.exists())
+ cout << "WARNING: Could not find directory (" << qPrintable(configCmdLine.at(i)) << ")for C runtime deployment" << endl;
+ else
+ dictionary[ "CE_CRT" ] = QDir::toNativeSeparators(cDir.absolutePath());
+ } else if (configCmdLine.at(i) == "-qt-crt") {
+ dictionary[ "CE_CRT" ] = "yes";
+ } else if (configCmdLine.at(i) == "-no-crt") {
+ dictionary[ "CE_CRT" ] = "no";
+ }
+ // cetest ---------------------------------------------------
+ else if (configCmdLine.at(i) == "-no-cetest") {
+ dictionary[ "CETEST" ] = "no";
+ } else if (configCmdLine.at(i) == "-cetest") {
+ // although specified to use it, we stay at "auto" state
+ // this is because checkAvailability() adds variables
+ // we need for crosscompilation
+ }
+ // Qt/CE - signing tool -------------------------------------
+ else if( configCmdLine.at(i) == "-signature") {
+ ++i;
+ if (i==argCount)
+ break;
+ QFileInfo info(configCmdLine.at(i));
+ if (!info.exists())
+ cout << "WARNING: Could not find signature file (" << qPrintable(configCmdLine.at(i)) << ")" << endl;
+ else
+ dictionary[ "CE_SIGNATURE" ] = QDir::toNativeSeparators(info.absoluteFilePath());
+ }
+ // Styles ---------------------------------------------------
+ else if( configCmdLine.at(i) == "-qt-style-windows" )
+ dictionary[ "STYLE_WINDOWS" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-windows" )
+ dictionary[ "STYLE_WINDOWS" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-style-windowsce" )
+ dictionary[ "STYLE_WINDOWSCE" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-windowsce" )
+ dictionary[ "STYLE_WINDOWSCE" ] = "no";
+ else if( configCmdLine.at(i) == "-qt-style-windowsmobile" )
+ dictionary[ "STYLE_WINDOWSMOBILE" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-windowsmobile" )
+ dictionary[ "STYLE_WINDOWSMOBILE" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-style-windowsxp" )
+ dictionary[ "STYLE_WINDOWSXP" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-windowsxp" )
+ dictionary[ "STYLE_WINDOWSXP" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-style-windowsvista" )
+ dictionary[ "STYLE_WINDOWSVISTA" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-windowsvista" )
+ dictionary[ "STYLE_WINDOWSVISTA" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-style-plastique" )
+ dictionary[ "STYLE_PLASTIQUE" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-plastique" )
+ dictionary[ "STYLE_PLASTIQUE" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-style-cleanlooks" )
+ dictionary[ "STYLE_CLEANLOOKS" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-cleanlooks" )
+ dictionary[ "STYLE_CLEANLOOKS" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-style-motif" )
+ dictionary[ "STYLE_MOTIF" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-motif" )
+ dictionary[ "STYLE_MOTIF" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-style-cde" )
+ dictionary[ "STYLE_CDE" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-style-cde" )
+ dictionary[ "STYLE_CDE" ] = "no";
+
+ // Qt 3 Support ---------------------------------------------
+ else if( configCmdLine.at(i) == "-no-qt3support" )
+ dictionary[ "QT3SUPPORT" ] = "no";
+
+ // Work around compiler nesting limitation
+ else
+ continueElse = true;
+ if (!continueElse) {
+ }
+
+ // OpenGL Support -------------------------------------------
+ else if( configCmdLine.at(i) == "-no-opengl" ) {
+ dictionary[ "OPENGL" ] = "no";
+ } else if ( configCmdLine.at(i) == "-opengl-es-cm" ) {
+ dictionary[ "OPENGL" ] = "yes";
+ dictionary[ "OPENGL_ES_CM" ] = "yes";
+ } else if ( configCmdLine.at(i) == "-opengl-es-cl" ) {
+ dictionary[ "OPENGL" ] = "yes";
+ dictionary[ "OPENGL_ES_CL" ] = "yes";
+ }
+ // Databases ------------------------------------------------
+ else if( configCmdLine.at(i) == "-qt-sql-mysql" )
+ dictionary[ "SQL_MYSQL" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-mysql" )
+ dictionary[ "SQL_MYSQL" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-mysql" )
+ dictionary[ "SQL_MYSQL" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-sql-odbc" )
+ dictionary[ "SQL_ODBC" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-odbc" )
+ dictionary[ "SQL_ODBC" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-odbc" )
+ dictionary[ "SQL_ODBC" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-sql-oci" )
+ dictionary[ "SQL_OCI" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-oci" )
+ dictionary[ "SQL_OCI" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-oci" )
+ dictionary[ "SQL_OCI" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-sql-psql" )
+ dictionary[ "SQL_PSQL" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-psql" )
+ dictionary[ "SQL_PSQL" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-psql" )
+ dictionary[ "SQL_PSQL" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-sql-tds" )
+ dictionary[ "SQL_TDS" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-tds" )
+ dictionary[ "SQL_TDS" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-tds" )
+ dictionary[ "SQL_TDS" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-sql-db2" )
+ dictionary[ "SQL_DB2" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-db2" )
+ dictionary[ "SQL_DB2" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-db2" )
+ dictionary[ "SQL_DB2" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-sql-sqlite" )
+ dictionary[ "SQL_SQLITE" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-sqlite" )
+ dictionary[ "SQL_SQLITE" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-sqlite" )
+ dictionary[ "SQL_SQLITE" ] = "no";
+ else if( configCmdLine.at(i) == "-system-sqlite" )
+ dictionary[ "SQL_SQLITE_LIB" ] = "system";
+ else if( configCmdLine.at(i) == "-qt-sql-sqlite2" )
+ dictionary[ "SQL_SQLITE2" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-sqlite2" )
+ dictionary[ "SQL_SQLITE2" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-sqlite2" )
+ dictionary[ "SQL_SQLITE2" ] = "no";
+
+ else if( configCmdLine.at(i) == "-qt-sql-ibase" )
+ dictionary[ "SQL_IBASE" ] = "yes";
+ else if( configCmdLine.at(i) == "-plugin-sql-ibase" )
+ dictionary[ "SQL_IBASE" ] = "plugin";
+ else if( configCmdLine.at(i) == "-no-sql-ibase" )
+ dictionary[ "SQL_IBASE" ] = "no";
+#endif
+ // IDE project generation -----------------------------------
+ else if( configCmdLine.at(i) == "-no-dsp" )
+ dictionary[ "DSPFILES" ] = "no";
+ else if( configCmdLine.at(i) == "-dsp" )
+ dictionary[ "DSPFILES" ] = "yes";
+
+ else if( configCmdLine.at(i) == "-no-vcp" )
+ dictionary[ "VCPFILES" ] = "no";
+ else if( configCmdLine.at(i) == "-vcp" )
+ dictionary[ "VCPFILES" ] = "yes";
+
+ else if( configCmdLine.at(i) == "-no-vcproj" )
+ dictionary[ "VCPROJFILES" ] = "no";
+ else if( configCmdLine.at(i) == "-vcproj" )
+ dictionary[ "VCPROJFILES" ] = "yes";
+
+ else if( configCmdLine.at(i) == "-no-incredibuild-xge" )
+ dictionary[ "INCREDIBUILD_XGE" ] = "no";
+ else if( configCmdLine.at(i) == "-incredibuild-xge" )
+ dictionary[ "INCREDIBUILD_XGE" ] = "yes";
+#if !defined(EVAL)
+ // Others ---------------------------------------------------
+ else if (configCmdLine.at(i) == "-fast" )
+ dictionary[ "FAST" ] = "yes";
+ else if (configCmdLine.at(i) == "-no-fast" )
+ dictionary[ "FAST" ] = "no";
+
+ else if( configCmdLine.at(i) == "-stl" )
+ dictionary[ "STL" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-stl" )
+ dictionary[ "STL" ] = "no";
+
+ else if ( configCmdLine.at(i) == "-exceptions" )
+ dictionary[ "EXCEPTIONS" ] = "yes";
+ else if ( configCmdLine.at(i) == "-no-exceptions" )
+ dictionary[ "EXCEPTIONS" ] = "no";
+
+ else if ( configCmdLine.at(i) == "-rtti" )
+ dictionary[ "RTTI" ] = "yes";
+ else if ( configCmdLine.at(i) == "-no-rtti" )
+ dictionary[ "RTTI" ] = "no";
+
+ else if( configCmdLine.at(i) == "-accessibility" )
+ dictionary[ "ACCESSIBILITY" ] = "yes";
+ else if( configCmdLine.at(i) == "-no-accessibility" ) {
+ dictionary[ "ACCESSIBILITY" ] = "no";
+ cout << "Setting accessibility to NO" << endl;
+ }
+
+ else if (configCmdLine.at(i) == "-no-mmx")
+ dictionary[ "MMX" ] = "no";
+ else if (configCmdLine.at(i) == "-mmx")
+ dictionary[ "MMX" ] = "yes";
+ else if (configCmdLine.at(i) == "-no-3dnow")
+ dictionary[ "3DNOW" ] = "no";
+ else if (configCmdLine.at(i) == "-3dnow")
+ dictionary[ "3DNOW" ] = "yes";
+ else if (configCmdLine.at(i) == "-no-sse")
+ dictionary[ "SSE" ] = "no";
+ else if (configCmdLine.at(i) == "-sse")
+ dictionary[ "SSE" ] = "yes";
+ else if (configCmdLine.at(i) == "-no-sse2")
+ dictionary[ "SSE2" ] = "no";
+ else if (configCmdLine.at(i) == "-sse2")
+ dictionary[ "SSE2" ] = "yes";
+ else if (configCmdLine.at(i) == "-no-iwmmxt")
+ dictionary[ "IWMMXT" ] = "no";
+ else if (configCmdLine.at(i) == "-iwmmxt")
+ dictionary[ "IWMMXT" ] = "yes";
+
+ else if (configCmdLine.at(i) == "-no-direct3d") {
+ dictionary["DIRECT3D"] = "no";
+ }else if (configCmdLine.at(i) == "-direct3d") {
+ dictionary["DIRECT3D"] = "auto"; // have to pass auto detection to enable Direct3D
+ } else if( configCmdLine.at(i) == "-no-openssl" ) {
+ dictionary[ "OPENSSL"] = "no";
+ } else if( configCmdLine.at(i) == "-openssl" ) {
+ dictionary[ "OPENSSL" ] = "yes";
+ } else if( configCmdLine.at(i) == "-openssl-linked" ) {
+ dictionary[ "OPENSSL" ] = "linked";
+ } else if( configCmdLine.at(i) == "-no-qdbus" ) {
+ dictionary[ "DBUS" ] = "no";
+ } else if( configCmdLine.at(i) == "-qdbus" ) {
+ dictionary[ "DBUS" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-dbus" ) {
+ dictionary[ "DBUS" ] = "no";
+ } else if( configCmdLine.at(i) == "-dbus" ) {
+ dictionary[ "DBUS" ] = "yes";
+ } else if( configCmdLine.at(i) == "-dbus-linked" ) {
+ dictionary[ "DBUS" ] = "linked";
+ } else if( configCmdLine.at(i) == "-no-scripttools" ) {
+ dictionary[ "SCRIPTTOOLS" ] = "no";
+ } else if( configCmdLine.at(i) == "-scripttools" ) {
+ dictionary[ "SCRIPTTOOLS" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-xmlpatterns" ) {
+ dictionary[ "XMLPATTERNS" ] = "no";
+ } else if( configCmdLine.at(i) == "-xmlpatterns" ) {
+ dictionary[ "XMLPATTERNS" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-phonon" ) {
+ dictionary[ "PHONON" ] = "no";
+ } else if( configCmdLine.at(i) == "-phonon" ) {
+ dictionary[ "PHONON" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-phonon-backend" ) {
+ dictionary[ "PHONON_BACKEND" ] = "no";
+ } else if( configCmdLine.at(i) == "-phonon-backend" ) {
+ dictionary[ "PHONON_BACKEND" ] = "yes";
+ } else if( configCmdLine.at(i) == "-phonon-wince-ds9" ) {
+ dictionary[ "DIRECTSHOW" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-webkit" ) {
+ dictionary[ "WEBKIT" ] = "no";
+ } else if( configCmdLine.at(i) == "-webkit" ) {
+ dictionary[ "WEBKIT" ] = "yes";
+ } else if( configCmdLine.at(i) == "-no-plugin-manifests" ) {
+ dictionary[ "PLUGIN_MANIFESTS" ] = "no";
+ } else if( configCmdLine.at(i) == "-plugin-manifests" ) {
+ dictionary[ "PLUGIN_MANIFESTS" ] = "yes";
+ }
+
+ else if( configCmdLine.at(i) == "-internal" )
+ dictionary[ "QMAKE_INTERNAL" ] = "yes";
+
+ else if( configCmdLine.at(i) == "-no-qmake" )
+ dictionary[ "BUILD_QMAKE" ] = "no";
+ else if( configCmdLine.at(i) == "-qmake" )
+ dictionary[ "BUILD_QMAKE" ] = "yes";
+
+ else if( configCmdLine.at(i) == "-dont-process" )
+ dictionary[ "NOPROCESS" ] = "yes";
+ else if( configCmdLine.at(i) == "-process" )
+ dictionary[ "NOPROCESS" ] = "no";
+
+ else if( configCmdLine.at(i) == "-no-qmake-deps" )
+ dictionary[ "DEPENDENCIES" ] = "no";
+ else if( configCmdLine.at(i) == "-qmake-deps" )
+ dictionary[ "DEPENDENCIES" ] = "yes";
+
+
+ else if( configCmdLine.at(i) == "-qtnamespace" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ qmakeDefines += "QT_NAMESPACE="+configCmdLine.at(i);
+ } else if( configCmdLine.at(i) == "-D" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ qmakeDefines += configCmdLine.at(i);
+ } else if( configCmdLine.at(i) == "-I" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ qmakeIncludes += configCmdLine.at(i);
+ } else if( configCmdLine.at(i) == "-L" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ QFileInfo check(configCmdLine.at(i));
+ if (!check.isDir()) {
+ cout << "Argument passed to -L option is not a directory path. Did you mean the -l option?" << endl;
+ dictionary[ "DONE" ] = "error";
+ break;
+ }
+ qmakeLibs += QString("-L" + configCmdLine.at(i));
+ } else if( configCmdLine.at(i) == "-l" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ qmakeLibs += QString("-l" + configCmdLine.at(i));
+ } else if (configCmdLine.at(i).startsWith("OPENSSL_LIBS=")) {
+ opensslLibs = configCmdLine.at(i);
+ }
+
+ else if( ( configCmdLine.at(i) == "-override-version" ) || ( configCmdLine.at(i) == "-version-override" ) ){
+ ++i;
+ if (i==argCount)
+ break;
+ dictionary[ "VERSION" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-saveconfig" ) {
+ ++i;
+ if (i==argCount)
+ break;
+ dictionary[ "CUSTOMCONFIG" ] = "_" + configCmdLine.at(i);
+ }
+
+ else if (configCmdLine.at(i) == "-confirm-license") {
+ dictionary["LICENSE_CONFIRMED"] = "yes";
+ }
+
+ else if (configCmdLine.at(i) == "-nomake") {
+ ++i;
+ if (i==argCount)
+ break;
+ disabledBuildParts += configCmdLine.at(i);
+ }
+
+ // Directories ----------------------------------------------
+ else if( configCmdLine.at(i) == "-prefix" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_PREFIX" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-bindir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_BINS" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-libdir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_LIBS" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-docdir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_DOCS" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-headerdir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_HEADERS" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-plugindir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_PLUGINS" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-datadir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_DATA" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-translationdir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_TRANSLATIONS" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-examplesdir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_EXAMPLES" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-demosdir" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_INSTALL_DEMOS" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-hostprefix" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "QT_HOST_PREFIX" ] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i) == "-make" ) {
+ ++i;
+ if(i==argCount)
+ break;
+ dictionary[ "MAKE" ] = configCmdLine.at(i);
+ }
+
+ else if (configCmdLine.at(i) == "-graphicssystem") {
+ ++i;
+ if (i == argCount)
+ break;
+ QString system = configCmdLine.at(i);
+ if (system == QLatin1String("raster") || system == QLatin1String("opengl"))
+ dictionary["GRAPHICS_SYSTEM"] = configCmdLine.at(i);
+ }
+
+ else if( configCmdLine.at(i).indexOf( QRegExp( "^-(en|dis)able-" ) ) != -1 ) {
+ // Scan to see if any specific modules and drivers are enabled or disabled
+ for( QStringList::Iterator module = modules.begin(); module != modules.end(); ++module ) {
+ if( configCmdLine.at(i) == QString( "-enable-" ) + (*module) ) {
+ enabledModules += (*module);
+ break;
+ }
+ else if( configCmdLine.at(i) == QString( "-disable-" ) + (*module) ) {
+ disabledModules += (*module);
+ break;
+ }
+ }
+ }
+
+ else {
+ dictionary[ "HELP" ] = "yes";
+ cout << "Unknown option " << configCmdLine.at(i) << endl;
+ break;
+ }
+
+#endif
+ }
+
+ // Ensure that QMAKESPEC exists in the mkspecs folder
+ QDir mkspec_dir = fixSeparators(sourcePath + "/mkspecs");
+ QStringList mkspecs = mkspec_dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
+
+ if (dictionary["QMAKESPEC"].toLower() == "features"
+ || !mkspecs.contains(dictionary["QMAKESPEC"], Qt::CaseInsensitive)) {
+ dictionary[ "HELP" ] = "yes";
+ if (dictionary ["QMAKESPEC_FROM"] == "commandline") {
+ cout << "Invalid option \"" << dictionary["QMAKESPEC"] << "\" for -platform." << endl;
+ } else if (dictionary ["QMAKESPEC_FROM"] == "env") {
+ cout << "QMAKESPEC environment variable is set to \"" << dictionary["QMAKESPEC"]
+ << "\" which is not a supported platform" << endl;
+ } else { // was autodetected from environment
+ cout << "Unable to detect the platform from environment. Use -platform command line"
+ "argument or set the QMAKESPEC environment variable and run configure again" << endl;
+ }
+ cout << "See the README file for a list of supported operating systems and compilers." << endl;
+ } else {
+ if( dictionary[ "QMAKESPEC" ].endsWith( "-icc" ) ||
+ dictionary[ "QMAKESPEC" ].endsWith( "-msvc" ) ||
+ dictionary[ "QMAKESPEC" ].endsWith( "-msvc.net" ) ||
+ dictionary[ "QMAKESPEC" ].endsWith( "-msvc2002" ) ||
+ dictionary[ "QMAKESPEC" ].endsWith( "-msvc2003" ) ||
+ dictionary[ "QMAKESPEC" ].endsWith( "-msvc2005" ) ||
+ dictionary[ "QMAKESPEC" ].endsWith( "-msvc2008" )) {
+ if ( dictionary[ "MAKE" ].isEmpty() ) dictionary[ "MAKE" ] = "nmake";
+ dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32";
+ } else if ( dictionary[ "QMAKESPEC" ] == QString( "win32-g++" ) ) {
+ if ( dictionary[ "MAKE" ].isEmpty() ) dictionary[ "MAKE" ] = "mingw32-make";
+ if (Environment::detectExecutable("sh.exe")) {
+ dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32-g++-sh";
+ } else {
+ dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32-g++";
+ }
+ } else {
+ if ( dictionary[ "MAKE" ].isEmpty() ) dictionary[ "MAKE" ] = "make";
+ dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32";
+ }
+ }
+
+ // Ensure that -spec (XQMAKESPEC) exists in the mkspecs folder as well
+ if (dictionary.contains("XQMAKESPEC") &&
+ !mkspecs.contains(dictionary["XQMAKESPEC"], Qt::CaseInsensitive)) {
+ dictionary["HELP"] = "yes";
+ cout << "Invalid option \"" << dictionary["XQMAKESPEC"] << "\" for -xplatform." << endl;
+ }
+
+ // Ensure that the crt to be deployed can be found
+ if (dictionary["CE_CRT"] != QLatin1String("yes") && dictionary["CE_CRT"] != QLatin1String("no")) {
+ QDir cDir(dictionary["CE_CRT"]);
+ QStringList entries = cDir.entryList();
+ bool hasDebug = entries.contains("msvcr80.dll");
+ bool hasRelease = entries.contains("msvcr80d.dll");
+ if ((dictionary["BUILDALL"] == "auto") && (!hasDebug || !hasRelease)) {
+ cout << "Could not find debug and release c-runtime." << endl;
+ cout << "You need to have msvcr80.dll and msvcr80d.dll in" << endl;
+ cout << "the path specified. Setting to -no-crt";
+ dictionary[ "CE_CRT" ] = "no";
+ } else if ((dictionary["BUILD"] == "debug") && !hasDebug) {
+ cout << "Could not find debug c-runtime (msvcr80d.dll) in the directory specified." << endl;
+ cout << "Setting c-runtime automatic deployment to -no-crt" << endl;
+ dictionary[ "CE_CRT" ] = "no";
+ } else if ((dictionary["BUILD"] == "release") && !hasRelease) {
+ cout << "Could not find release c-runtime (msvcr80.dll) in the directory specified." << endl;
+ cout << "Setting c-runtime automatic deployment to -no-crt" << endl;
+ dictionary[ "CE_CRT" ] = "no";
+ }
+ }
+
+ useUnixSeparators = (dictionary["QMAKESPEC"] == "win32-g++");
+
+
+#if !defined(EVAL)
+ for( QStringList::Iterator dis = disabledModules.begin(); dis != disabledModules.end(); ++dis ) {
+ modules.removeAll( (*dis) );
+ }
+ for( QStringList::Iterator ena = enabledModules.begin(); ena != enabledModules.end(); ++ena ) {
+ if( modules.indexOf( (*ena) ) == -1 )
+ modules += (*ena);
+ }
+ qtConfig += modules;
+
+ for( QStringList::Iterator it = disabledModules.begin(); it != disabledModules.end(); ++it )
+ qtConfig.removeAll(*it);
+
+ if( ( dictionary[ "REDO" ] != "yes" ) && ( dictionary[ "HELP" ] != "yes" ) )
+ saveCmdLine();
+#endif
+}
+
+#if !defined(EVAL)
+void Configure::validateArgs()
+{
+ QStringList configs;
+ // Validate the specified config
+
+ QDir dir;
+ QStringList filters;
+ filters << "qconfig-*.h";
+ dir.setNameFilters(filters);
+ dir.setPath(sourcePath + "/src/corelib/global/");
+
+ QStringList stringList = dir.entryList();
+
+ QStringList::Iterator it;
+ for( it = stringList.begin(); it != stringList.end(); ++it )
+ allConfigs << it->remove("qconfig-").remove(".h");
+ allConfigs << "full";
+
+ QStringList::Iterator config;
+ for( config = allConfigs.begin(); config != allConfigs.end(); ++config ) {
+ configs += (*config) + "-config";
+ if( (*config) == dictionary[ "QCONFIG" ] )
+ break;
+ }
+ if( config == allConfigs.end() ) {
+ dictionary[ "HELP" ] = "yes";
+ cout << "No such configuration \"" << qPrintable(dictionary[ "QCONFIG" ]) << "\"" << endl ;
+ }
+ else
+ qmakeConfig += configs;
+}
+#endif
+
+
+// Output helper functions --------------------------------[ Start ]-
+/*!
+ Determines the length of a string token.
+*/
+static int tokenLength(const char *str)
+{
+ if (*str == 0)
+ return 0;
+
+ const char *nextToken = strpbrk(str, " _/\n\r");
+ if (nextToken == str || !nextToken)
+ return 1;
+
+ return int(nextToken - str);
+}
+
+/*!
+ Prints out a string which starts at position \a startingAt, and
+ indents each wrapped line with \a wrapIndent characters.
+ The wrap point is set to the console width, unless that width
+ cannot be determined, or is too small.
+*/
+void Configure::desc(const char *description, int startingAt, int wrapIndent)
+{
+ int linePos = startingAt;
+
+ bool firstLine = true;
+ const char *nextToken = description;
+ while (*nextToken) {
+ int nextTokenLen = tokenLength(nextToken);
+ if (*nextToken == '\n' // Wrap on newline, duh
+ || (linePos + nextTokenLen > outputWidth)) // Wrap at outputWidth
+ {
+ printf("\n");
+ linePos = 0;
+ firstLine = false;
+ if (*nextToken == '\n')
+ ++nextToken;
+ continue;
+ }
+ if (!firstLine && linePos < wrapIndent) { // Indent to wrapIndent
+ printf("%*s", wrapIndent , "");
+ linePos = wrapIndent;
+ if (*nextToken == ' ') {
+ ++nextToken;
+ continue;
+ }
+ }
+ printf("%.*s", nextTokenLen, nextToken);
+ linePos += nextTokenLen;
+ nextToken += nextTokenLen;
+ }
+}
+
+/*!
+ Prints out an option with its description wrapped at the
+ description starting point. If \a skipIndent is true, the
+ indentation to the option is not outputted (used by marked option
+ version of desc()). Extra spaces between option and its
+ description is filled with\a fillChar, if there's available
+ space.
+*/
+void Configure::desc(const char *option, const char *description, bool skipIndent, char fillChar)
+{
+ if (!skipIndent)
+ printf("%*s", optionIndent, "");
+
+ int remaining = descIndent - optionIndent - strlen(option);
+ int wrapIndent = descIndent + qMax(0, 1 - remaining);
+ printf("%s", option);
+
+ if (remaining > 2) {
+ printf(" "); // Space in front
+ for (int i = remaining; i > 2; --i)
+ printf("%c", fillChar); // Fill, if available space
+ }
+ printf(" "); // Space between option and description
+
+ desc(description, wrapIndent, wrapIndent);
+ printf("\n");
+}
+
+/*!
+ Same as above, except it also marks an option with an '*', if
+ the option is default action.
+*/
+void Configure::desc(const char *mark_option, const char *mark, const char *option, const char *description, char fillChar)
+{
+ const QString markedAs = dictionary.value(mark_option);
+ if (markedAs == "auto" && markedAs == mark) // both "auto", always => +
+ printf(" + ");
+ else if (markedAs == "auto") // setting marked as "auto" and option is default => +
+ printf(" %c " , (defaultTo(mark_option) == QLatin1String(mark))? '+' : ' ');
+ else if (QLatin1String(mark) == "auto" && markedAs != "no") // description marked as "auto" and option is available => +
+ printf(" %c " , checkAvailability(mark_option) ? '+' : ' ');
+ else // None are "auto", (markedAs == mark) => *
+ printf(" %c " , markedAs == QLatin1String(mark) ? '*' : ' ');
+
+ desc(option, description, true, fillChar);
+}
+
+/*!
+ Modifies the default configuration based on given -platform option.
+ Eg. switches to different default styles for Windows CE.
+*/
+void Configure::applySpecSpecifics()
+{
+ if (dictionary[ "XQMAKESPEC" ].startsWith("wince")) {
+ dictionary[ "STYLE_WINDOWSXP" ] = "no";
+ dictionary[ "STYLE_WINDOWSVISTA" ] = "no";
+ dictionary[ "STYLE_PLASTIQUE" ] = "no";
+ dictionary[ "STYLE_CLEANLOOKS" ] = "no";
+ dictionary[ "STYLE_WINDOWSCE" ] = "yes";
+ dictionary[ "STYLE_WINDOWSMOBILE" ] = "yes";
+ dictionary[ "STYLE_MOTIF" ] = "no";
+ dictionary[ "STYLE_CDE" ] = "no";
+ dictionary[ "QT3SUPPORT" ] = "no";
+ dictionary[ "OPENGL" ] = "no";
+ dictionary[ "OPENSSL" ] = "no";
+ dictionary[ "STL" ] = "no";
+ dictionary[ "EXCEPTIONS" ] = "no";
+ dictionary[ "RTTI" ] = "no";
+ dictionary[ "ARCHITECTURE" ] = "windowsce";
+ dictionary[ "3DNOW" ] = "no";
+ dictionary[ "SSE" ] = "no";
+ dictionary[ "SSE2" ] = "no";
+ dictionary[ "MMX" ] = "no";
+ dictionary[ "IWMMXT" ] = "no";
+ dictionary[ "CE_CRT" ] = "yes";
+ dictionary[ "DIRECT3D" ] = "no";
+ dictionary[ "WEBKIT" ] = "no";
+ dictionary[ "PHONON" ] = "yes";
+ dictionary[ "DIRECTSHOW" ] = "no";
+ // We only apply MMX/IWMMXT for mkspecs we know they work
+ if (dictionary[ "XQMAKESPEC" ].startsWith("wincewm")) {
+ dictionary[ "MMX" ] = "yes";
+ dictionary[ "IWMMXT" ] = "yes";
+ dictionary[ "DIRECTSHOW" ] = "yes";
+ }
+ dictionary[ "QT_HOST_PREFIX" ] = dictionary[ "QT_INSTALL_PREFIX" ];
+ dictionary[ "QT_INSTALL_PREFIX" ] = "";
+
+ } else if(dictionary[ "XQMAKESPEC" ].startsWith("linux")) { //TODO actually wrong.
+ //TODO
+ dictionary[ "STYLE_WINDOWSXP" ] = "no";
+ dictionary[ "STYLE_WINDOWSVISTA" ] = "no";
+ dictionary[ "KBD_DRIVERS" ] = "tty";
+ dictionary[ "GFX_DRIVERS" ] = "linuxfb vnc";
+ dictionary[ "MOUSE_DRIVERS" ] = "pc linuxtp";
+ dictionary[ "QT3SUPPORT" ] = "no";
+ dictionary[ "OPENGL" ] = "no";
+ dictionary[ "EXCEPTIONS" ] = "no";
+ dictionary[ "DBUS"] = "no";
+ dictionary[ "QT_QWS_DEPTH" ] = "4 8 16 24 32";
+ dictionary[ "QT_SXE" ] = "no";
+ dictionary[ "QT_INOTIFY" ] = "no";
+ dictionary[ "QT_LPR" ] = "no";
+ dictionary[ "QT_CUPS" ] = "no";
+ dictionary[ "QT_GLIB" ] = "no";
+ dictionary[ "QT_ICONV" ] = "no";
+
+ dictionary["DECORATIONS"] = "default windows styled";
+ dictionary[ "QMAKEADDITIONALARGS" ] = "-unix";
+ }
+}
+
+QString Configure::locateFileInPaths(const QString &fileName, const QStringList &paths)
+{
+ QDir d;
+ for( QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it ) {
+ // Remove any leading or trailing ", this is commonly used in the environment
+ // variables
+ QString path = (*it);
+ if ( path.startsWith( "\"" ) )
+ path = path.right( path.length() - 1 );
+ if ( path.endsWith( "\"" ) )
+ path = path.left( path.length() - 1 );
+ if( d.exists(path + QDir::separator() + fileName) ) {
+ return (path);
+ }
+ }
+ return QString();
+}
+
+QString Configure::locateFile( const QString &fileName )
+{
+ QString file = fileName.toLower();
+ QStringList paths;
+#if defined(Q_OS_WIN32)
+ QRegExp splitReg("[;,]");
+#else
+ QRegExp splitReg("[:]");
+#endif
+ if (file.endsWith(".h"))
+ paths = QString::fromLocal8Bit(getenv("INCLUDE")).split(splitReg, QString::SkipEmptyParts);
+ else if ( file.endsWith( ".lib" ) )
+ paths = QString::fromLocal8Bit(getenv("LIB")).split(splitReg, QString::SkipEmptyParts);
+ else
+ paths = QString::fromLocal8Bit(getenv("PATH")).split(splitReg, QString::SkipEmptyParts);
+ return locateFileInPaths(file, paths);
+}
+
+// Output helper functions ---------------------------------[ Stop ]-
+
+
+bool Configure::displayHelp()
+{
+ if( dictionary[ "HELP" ] == "yes" ) {
+ desc("Usage: configure [-buildkey <key>]\n"
+// desc("Usage: configure [-prefix dir] [-bindir <dir>] [-libdir <dir>]\n"
+// "[-docdir <dir>] [-headerdir <dir>] [-plugindir <dir>]\n"
+// "[-datadir <dir>] [-translationdir <dir>]\n"
+// "[-examplesdir <dir>] [-demosdir <dir>][-buildkey <key>]\n"
+ "[-release] [-debug] [-debug-and-release] [-shared] [-static]\n"
+ "[-no-fast] [-fast] [-no-exceptions] [-exceptions]\n"
+ "[-no-accessibility] [-accessibility] [-no-rtti] [-rtti]\n"
+ "[-no-stl] [-stl] [-no-sql-<driver>] [-qt-sql-<driver>]\n"
+ "[-plugin-sql-<driver>] [-system-sqlite] [-arch <arch>]\n"
+ "[-D <define>] [-I <includepath>] [-L <librarypath>]\n"
+ "[-help] [-no-dsp] [-dsp] [-no-vcproj] [-vcproj]\n"
+ "[-no-qmake] [-qmake] [-dont-process] [-process]\n"
+ "[-no-style-<style>] [-qt-style-<style>] [-redo]\n"
+ "[-saveconfig <config>] [-loadconfig <config>]\n"
+ "[-qt-zlib] [-system-zlib] [-no-gif] [-qt-gif] [-no-libpng]\n"
+ "[-qt-libpng] [-system-libpng] [-no-libtiff] [-qt-libtiff]\n"
+ "[-system-libtiff] [-no-libjpeg] [-qt-libjpeg] [-system-libjpeg]\n"
+ "[-no-libmng] [-qt-libmng] [-system-libmng] [-no-qt3support] [-mmx]\n"
+ "[-no-mmx] [-3dnow] [-no-3dnow] [-sse] [-no-sse] [-sse2] [-no-sse2]\n"
+ "[-no-iwmmxt] [-iwmmxt] [-direct3d] [-openssl] [-openssl-linked]\n"
+ "[-no-openssl] [-no-dbus] [-dbus] [-dbus-linked] [-platform <spec>]\n"
+ "[-qtnamespace <namespace>] [-no-phonon] [-phonon]\n"
+ "[-no-phonon-backend] [-phonon-backend]\n"
+ "[-no-webkit] [-webkit]\n"
+ "[-no-scripttools] [-scripttools]\n"
+ "[-graphicssystem raster|opengl]\n\n", 0, 7);
+
+ desc("Installation options:\n\n");
+
+#if !defined(EVAL)
+/*
+ desc(" These are optional, but you may specify install directories.\n\n", 0, 1);
+
+ desc( "-prefix dir", "This will install everything relative to dir\n(default $QT_INSTALL_PREFIX)\n");
+
+ desc(" You may use these to separate different parts of the install:\n\n", 0, 1);
+
+ desc( "-bindir <dir>", "Executables will be installed to dir\n(default PREFIX/bin)");
+ desc( "-libdir <dir>", "Libraries will be installed to dir\n(default PREFIX/lib)");
+ desc( "-docdir <dir>", "Documentation will be installed to dir\n(default PREFIX/doc)");
+ desc( "-headerdir <dir>", "Headers will be installed to dir\n(default PREFIX/include)");
+ desc( "-plugindir <dir>", "Plugins will be installed to dir\n(default PREFIX/plugins)");
+ desc( "-datadir <dir>", "Data used by Qt programs will be installed to dir\n(default PREFIX)");
+ desc( "-translationdir <dir>","Translations of Qt programs will be installed to dir\n(default PREFIX/translations)\n");
+ desc( "-examplesdir <dir>", "Examples will be installed to dir\n(default PREFIX/examples)");
+ desc( "-demosdir <dir>", "Demos will be installed to dir\n(default PREFIX/demos)");
+*/
+ desc(" You may use these options to turn on strict plugin loading:\n\n", 0, 1);
+
+ desc( "-buildkey <key>", "Build the Qt library and plugins using the specified <key>. "
+ "When the library loads plugins, it will only load those that have a matching <key>.\n");
+
+ desc("Configure options:\n\n");
+
+ desc(" The defaults (*) are usually acceptable. A plus (+) denotes a default value"
+ " that needs to be evaluated. If the evaluation succeeds, the feature is"
+ " included. Here is a short explanation of each option:\n\n", 0, 1);
+
+ desc("BUILD", "release","-release", "Compile and link Qt with debugging turned off.");
+ desc("BUILD", "debug", "-debug", "Compile and link Qt with debugging turned on.");
+ desc("BUILDALL", "yes", "-debug-and-release", "Compile and link two Qt libraries, with and without debugging turned on.\n");
+
+ desc("OPENSOURCE", "opensource", "-opensource", "Compile and link the Open-Source Edition of Qt.");
+ desc("COMMERCIAL", "commercial", "-commercial", "Compile and link the Commercial Edition of Qt.\n");
+
+ desc("BUILDDEV", "yes", "-developer-build", "Compile and link Qt with Qt developer options (including auto-tests exporting)\n");
+
+ desc("SHARED", "yes", "-shared", "Create and use shared Qt libraries.");
+ desc("SHARED", "no", "-static", "Create and use static Qt libraries.\n");
+
+ desc("FAST", "no", "-no-fast", "Configure Qt normally by generating Makefiles for all project files.");
+ desc("FAST", "yes", "-fast", "Configure Qt quickly by generating Makefiles only for library and "
+ "subdirectory targets. All other Makefiles are created as wrappers "
+ "which will in turn run qmake\n");
+
+ desc("EXCEPTIONS", "no", "-no-exceptions", "Disable exceptions on platforms that support it.");
+ desc("EXCEPTIONS", "yes","-exceptions", "Enable exceptions on platforms that support it.\n");
+
+ desc("ACCESSIBILITY", "no", "-no-accessibility", "Do not compile Windows Active Accessibility support.");
+ desc("ACCESSIBILITY", "yes", "-accessibility", "Compile Windows Active Accessibility support.\n");
+
+ desc("STL", "no", "-no-stl", "Do not compile STL support.");
+ desc("STL", "yes", "-stl", "Compile STL support.\n");
+
+ desc( "-no-sql-<driver>", "Disable SQL <driver> entirely, by default none are turned on.");
+ desc( "-qt-sql-<driver>", "Enable a SQL <driver> in the Qt Library.");
+ desc( "-plugin-sql-<driver>", "Enable SQL <driver> as a plugin to be linked to at run time.\n"
+ "Available values for <driver>:");
+ desc("SQL_MYSQL", "auto", "", " mysql", ' ');
+ desc("SQL_PSQL", "auto", "", " psql", ' ');
+ desc("SQL_OCI", "auto", "", " oci", ' ');
+ desc("SQL_ODBC", "auto", "", " odbc", ' ');
+ desc("SQL_TDS", "auto", "", " tds", ' ');
+ desc("SQL_DB2", "auto", "", " db2", ' ');
+ desc("SQL_SQLITE", "auto", "", " sqlite", ' ');
+ desc("SQL_SQLITE2", "auto", "", " sqlite2", ' ');
+ desc("SQL_IBASE", "auto", "", " ibase", ' ');
+ desc( "", "(drivers marked with a '+' have been detected as available on this system)\n", false, ' ');
+
+ desc( "-system-sqlite", "Use sqlite from the operating system.\n");
+
+ desc("QT3SUPPORT", "no","-no-qt3support", "Disables the Qt 3 support functionality.\n");
+ desc("OPENGL", "no","-no-opengl", "Disables OpenGL functionality\n");
+
+#endif
+ desc( "-platform <spec>", "The operating system and compiler you are building on.\n(default %QMAKESPEC%)\n");
+ desc( "-xplatform <spec>", "The operating system and compiler you are cross compiling to.\n");
+ desc( "", "See the README file for a list of supported operating systems and compilers.\n", false, ' ');
+
+#if !defined(EVAL)
+ desc( "-qtnamespace <namespace>", "Wraps all Qt library code in 'namespace name {...}\n");
+ desc( "-D <define>", "Add an explicit define to the preprocessor.");
+ desc( "-I <includepath>", "Add an explicit include path.");
+ desc( "-L <librarypath>", "Add an explicit library path.");
+ desc( "-l <libraryname>", "Add an explicit library name, residing in a librarypath.\n");
+#endif
+ desc( "-graphicssystem <sys>", "Specify which graphicssystem should be used.\n"
+ "Available values for <sys>:");
+ desc("GRAPHICS_SYSTEM", "raster", "", " raster - Software rasterizer", ' ');
+ desc("GRAPHICS_SYSTEM", "opengl", "", " opengl - Using OpenGL accelleration, experimental!", ' ');
+
+
+ desc( "-help, -h, -?", "Display this information.\n");
+
+#if !defined(EVAL)
+ // 3rd party stuff options go below here --------------------------------------------------------------------------------
+ desc("Third Party Libraries:\n\n");
+
+ desc("ZLIB", "qt", "-qt-zlib", "Use the zlib bundled with Qt.");
+ desc("ZLIB", "system", "-system-zlib", "Use zlib from the operating system.\nSee http://www.gzip.org/zlib\n");
+
+ desc("GIF", "no", "-no-gif", "Do not compile the plugin for GIF reading support.");
+ desc("GIF", "auto", "-qt-gif", "Compile the plugin for GIF reading support.\nSee also src/plugins/imageformats/gif/qgifhandler.h\n");
+
+ desc("LIBPNG", "no", "-no-libpng", "Do not compile in PNG support.");
+ desc("LIBPNG", "qt", "-qt-libpng", "Use the libpng bundled with Qt.");
+ desc("LIBPNG", "system","-system-libpng", "Use libpng from the operating system.\nSee http://www.libpng.org/pub/png\n");
+
+ desc("LIBMNG", "no", "-no-libmng", "Do not compile in MNG support.");
+ desc("LIBMNG", "qt", "-qt-libmng", "Use the libmng bundled with Qt.");
+ desc("LIBMNG", "system","-system-libmng", "Use libmng from the operating system.\nSee See http://www.libmng.com\n");
+
+ desc("LIBTIFF", "no", "-no-libtiff", "Do not compile the plugin for TIFF support.");
+ desc("LIBTIFF", "qt", "-qt-libtiff", "Use the libtiff bundled with Qt.");
+ desc("LIBTIFF", "system","-system-libtiff", "Use libtiff from the operating system.\nSee http://www.libtiff.org\n");
+
+ desc("LIBJPEG", "no", "-no-libjpeg", "Do not compile the plugin for JPEG support.");
+ desc("LIBJPEG", "qt", "-qt-libjpeg", "Use the libjpeg bundled with Qt.");
+ desc("LIBJPEG", "system","-system-libjpeg", "Use libjpeg from the operating system.\nSee http://www.ijg.org\n");
+
+#endif
+ // Qt\Windows only options go below here --------------------------------------------------------------------------------
+ desc("Qt for Windows only:\n\n");
+
+ desc("DSPFILES", "no", "-no-dsp", "Do not generate VC++ .dsp files.");
+ desc("DSPFILES", "yes", "-dsp", "Generate VC++ .dsp files, only if spec \"win32-msvc\".\n");
+
+ desc("VCPROJFILES", "no", "-no-vcproj", "Do not generate VC++ .vcproj files.");
+ desc("VCPROJFILES", "yes", "-vcproj", "Generate VC++ .vcproj files, only if platform \"win32-msvc.net\".\n");
+
+ desc("INCREDIBUILD_XGE", "no", "-no-incredibuild-xge", "Do not add IncrediBuild XGE distribution commands to custom build steps.");
+ desc("INCREDIBUILD_XGE", "yes", "-incredibuild-xge", "Add IncrediBuild XGE distribution commands to custom build steps. This will distribute MOC and UIC steps, and other custom buildsteps which are added to the INCREDIBUILD_XGE variable.\n(The IncrediBuild distribution commands are only added to Visual Studio projects)\n");
+
+ desc("PLUGIN_MANIFESTS", "no", "-no-plugin-manifests", "Do not embed manifests in plugins.");
+ desc("PLUGIN_MANIFESTS", "yes", "-plugin-manifests", "Embed manifests in plugins.\n");
+
+#if !defined(EVAL)
+ desc("BUILD_QMAKE", "no", "-no-qmake", "Do not compile qmake.");
+ desc("BUILD_QMAKE", "yes", "-qmake", "Compile qmake.\n");
+
+ desc("NOPROCESS", "yes", "-dont-process", "Do not generate Makefiles/Project files. This will override -no-fast if specified.");
+ desc("NOPROCESS", "no", "-process", "Generate Makefiles/Project files.\n");
+
+ desc("RTTI", "no", "-no-rtti", "Do not compile runtime type information.");
+ desc("RTTI", "yes", "-rtti", "Compile runtime type information.\n");
+ desc("MMX", "no", "-no-mmx", "Do not compile with use of MMX instructions");
+ desc("MMX", "yes", "-mmx", "Compile with use of MMX instructions");
+ desc("3DNOW", "no", "-no-3dnow", "Do not compile with use of 3DNOW instructions");
+ desc("3DNOW", "yes", "-3dnow", "Compile with use of 3DNOW instructions");
+ desc("SSE", "no", "-no-sse", "Do not compile with use of SSE instructions");
+ desc("SSE", "yes", "-sse", "Compile with use of SSE instructions");
+ desc("SSE2", "no", "-no-sse2", "Do not compile with use of SSE2 instructions");
+ desc("SSE2", "yes", "-sse2", "Compile with use of SSE2 instructions");
+ desc("DIRECT3D", "yes", "-direct3d", "Compile in Direct3D support (experimental - see INSTALL for more info)");
+ desc("OPENSSL", "no", "-no-openssl", "Do not compile in OpenSSL support");
+ desc("OPENSSL", "yes", "-openssl", "Compile in run-time OpenSSL support");
+ desc("OPENSSL", "linked","-openssl-linked", "Compile in linked OpenSSL support");
+ desc("DBUS", "no", "-no-dbus", "Do not compile in D-Bus support");
+ desc("DBUS", "yes", "-dbus", "Compile in D-Bus support and load libdbus-1 dynamically");
+ desc("DBUS", "linked", "-dbus-linked", "Compile in D-Bus support and link to libdbus-1");
+ desc("PHONON", "no", "-no-phonon", "Do not compile in the Phonon module");
+ desc("PHONON", "yes", "-phonon", "Compile the Phonon module (Phonon is built if a decent C++ compiler is used.)");
+ desc("PHONON_BACKEND","no", "-no-phonon-backend","Do not compile the platform-specific Phonon backend-plugin");
+ desc("PHONON_BACKEND","yes","-phonon-backend", "Compile in the platform-specific Phonon backend-plugin");
+ desc("WEBKIT", "no", "-no-webkit", "Do not compile in the WebKit module");
+ desc("WEBKIT", "yes", "-webkit", "Compile in the WebKit module (WebKit is built if a decent C++ compiler is used.)");
+ desc("SCRIPTTOOLS", "no", "-no-scripttools", "Do not build the QtScriptTools module.");
+ desc("SCRIPTTOOLS", "yes", "-scripttools", "Build the QtScriptTools module.");
+
+ desc( "-arch <arch>", "Specify an architecture.\n"
+ "Available values for <arch>:");
+ desc("ARCHITECTURE","windows", "", " windows", ' ');
+ desc("ARCHITECTURE","windowsce", "", " windowsce", ' ');
+ desc("ARCHITECTURE","boundschecker", "", " boundschecker", ' ');
+ desc("ARCHITECTURE","generic", "", " generic\n", ' ');
+
+ desc( "-no-style-<style>", "Disable <style> entirely.");
+ desc( "-qt-style-<style>", "Enable <style> in the Qt Library.\nAvailable styles: ");
+
+ desc("STYLE_WINDOWS", "yes", "", " windows", ' ');
+ desc("STYLE_WINDOWSXP", "auto", "", " windowsxp", ' ');
+ desc("STYLE_WINDOWSVISTA", "auto", "", " windowsvista", ' ');
+ desc("STYLE_PLASTIQUE", "yes", "", " plastique", ' ');
+ desc("STYLE_CLEANLOOKS", "yes", "", " cleanlooks", ' ');
+ desc("STYLE_MOTIF", "yes", "", " motif", ' ');
+ desc("STYLE_CDE", "yes", "", " cde", ' ');
+ desc("STYLE_WINDOWSCE", "yes", "", " windowsce", ' ');
+ desc("STYLE_WINDOWSMOBILE" , "yes", "", " windowsmobile\n", ' ');
+
+/* We do not support -qconfig on Windows yet
+
+ desc( "-qconfig <local>", "Use src/tools/qconfig-local.h rather than the default.\nPossible values for local:");
+ for (int i=0; i<allConfigs.size(); ++i)
+ desc( "", qPrintable(QString(" %1").arg(allConfigs.at(i))), false, ' ');
+ printf("\n");
+*/
+#endif
+ desc( "-loadconfig <config>", "Run configure with the parameters from file configure_<config>.cache.");
+ desc( "-saveconfig <config>", "Run configure and save the parameters in file configure_<config>.cache.");
+ desc( "-redo", "Run configure with the same parameters as last time.\n");
+
+ // Qt\Windows CE only options go below here -----------------------------------------------------------------------------
+ desc("Qt for Windows CE only:\n\n");
+ desc("IWMMXT", "no", "-no-iwmmxt", "Do not compile with use of IWMMXT instructions");
+ desc("IWMMXT", "yes", "-iwmmxt", "Do compile with use of IWMMXT instructions (Qt for Windows CE on Arm only)");
+ desc("CE_CRT", "no", "-no-crt" , "Do not add the C runtime to default deployment rules");
+ desc("CE_CRT", "yes", "-qt-crt", "Qt identifies C runtime during project generation");
+ desc( "-crt <path>", "Specify path to C runtime used for project generation.");
+ desc("CETEST", "no", "-no-cetest", "Do not compile Windows CE remote test application");
+ desc("CETEST", "yes", "-cetest", "Compile Windows CE remote test application");
+ desc( "-signature <file>", "Use file for signing the target project");
+ desc("OPENGL_ES_CM", "no", "-opengl-es-cm", "Enable support for OpenGL ES Common");
+ desc("OPENGL_ES_CL", "no", "-opengl-es-cl", "Enable support for OpenGL ES Common Lite");
+ desc("DIRECTSHOW", "no", "-phonon-wince-ds9", "Enable Phonon Direct Show 9 backend for Windows CE");
+
+ return true;
+ }
+ return false;
+}
+
+bool Configure::findFileInPaths(const QString &fileName, const QStringList &paths)
+{
+ QDir d;
+ for( QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it ) {
+ // Remove any leading or trailing ", this is commonly used in the environment
+ // variables
+ QString path = (*it);
+ if ( path.startsWith( "\"" ) )
+ path = path.right( path.length() - 1 );
+ if ( path.endsWith( "\"" ) )
+ path = path.left( path.length() - 1 );
+ if( d.exists( path + QDir::separator() + fileName ) )
+ return true;
+ }
+ return false;
+}
+
+bool Configure::findFile( const QString &fileName )
+{
+ QString file = fileName.toLower();
+ QStringList paths;
+#if defined(Q_OS_WIN32)
+ QRegExp splitReg("[;,]");
+#else
+ QRegExp splitReg("[:]");
+#endif
+ if (file.endsWith(".h"))
+ paths = QString::fromLocal8Bit(getenv("INCLUDE")).split(splitReg, QString::SkipEmptyParts);
+ else if ( file.endsWith( ".lib" ) )
+ paths = QString::fromLocal8Bit(getenv("LIB")).split(splitReg, QString::SkipEmptyParts);
+ else
+ paths = QString::fromLocal8Bit(getenv("PATH")).split(splitReg, QString::SkipEmptyParts);
+ return findFileInPaths(file, paths);
+}
+
+/*!
+ Default value for options marked as "auto" if the test passes.
+ (Used both by the autoDetection() below, and the desc() function
+ to mark (+) the default option of autodetecting options.
+*/
+QString Configure::defaultTo(const QString &option)
+{
+ // We prefer using the system version of the 3rd party libs
+ if (option == "ZLIB"
+ || option == "LIBJPEG"
+ || option == "LIBPNG"
+ || option == "LIBMNG"
+ || option == "LIBTIFF")
+ return "system";
+
+ // We want PNG built-in
+ if (option == "PNG")
+ return "qt";
+
+ // The JPEG image library can only be a plugin
+ if (option == "JPEG"
+ || option == "MNG" || option == "TIFF")
+ return "plugin";
+
+ // GIF off by default
+ if (option == "GIF") {
+ if (dictionary["SHARED"] == "yes")
+ return "plugin";
+ else
+ return "yes";
+ }
+
+ // By default we do not want to compile OCI driver when compiling with
+ // MinGW, due to lack of such support from Oracle. It prob. wont work.
+ // (Customer may force the use though)
+ if (dictionary["QMAKESPEC"].endsWith("-g++")
+ && option == "SQL_OCI")
+ return "no";
+
+ if (option == "SQL_MYSQL"
+ || option == "SQL_MYSQL"
+ || option == "SQL_ODBC"
+ || option == "SQL_OCI"
+ || option == "SQL_PSQL"
+ || option == "SQL_TDS"
+ || option == "SQL_DB2"
+ || option == "SQL_SQLITE"
+ || option == "SQL_SQLITE2"
+ || option == "SQL_IBASE")
+ return "plugin";
+
+ if (option == "SYNCQT"
+ && (!QFile::exists(sourcePath + "/bin/syncqt") ||
+ !QFile::exists(sourcePath + "/bin/syncqt.bat")))
+ return "no";
+
+ return "yes";
+}
+
+/*!
+ Checks the system for the availability of a feature.
+ Returns true if the feature is available, else false.
+*/
+bool Configure::checkAvailability(const QString &part)
+{
+ bool available = false;
+ if (part == "STYLE_WINDOWSXP")
+ available = (dictionary.value("QMAKESPEC") == "win32-g++" || findFile("uxtheme.h"));
+
+ else if (part == "ZLIB")
+ available = findFile("zlib.h");
+
+ else if (part == "LIBJPEG")
+ available = findFile("jpeglib.h");
+ else if (part == "LIBPNG")
+ available = findFile("png.h");
+ else if (part == "LIBMNG")
+ available = findFile("libmng.h");
+ else if (part == "LIBTIFF")
+ available = findFile("tiffio.h");
+ else if (part == "SQL_MYSQL")
+ available = findFile("mysql.h") && findFile("libmySQL.lib");
+ else if (part == "SQL_ODBC")
+ available = findFile("sql.h") && findFile("sqlext.h") && findFile("odbc32.lib");
+ else if (part == "SQL_OCI")
+ available = findFile("oci.h") && findFile("oci.lib");
+ else if (part == "SQL_PSQL")
+ available = findFile("libpq-fe.h") && findFile("libpq.lib") && findFile("ws2_32.lib") && findFile("advapi32.lib");
+ else if (part == "SQL_TDS")
+ available = findFile("sybfront.h") && findFile("sybdb.h") && findFile("ntwdblib.lib");
+ else if (part == "SQL_DB2")
+ available = findFile("sqlcli.h") && findFile("sqlcli1.h") && findFile("db2cli.lib");
+ else if (part == "SQL_SQLITE")
+ available = true; // Built in, we have a fork
+ else if (part == "SQL_SQLITE_LIB") {
+ if (dictionary[ "SQL_SQLITE_LIB" ] == "system") {
+ available = findFile("sqlite3.h") && findFile("sqlite3.lib");
+ if (available)
+ dictionary[ "QT_LFLAGS_SQLITE" ] += "sqlite3.lib";
+ } else
+ available = true;
+ } else if (part == "SQL_SQLITE2")
+ available = findFile("sqlite.h") && findFile("sqlite.lib");
+ else if (part == "SQL_IBASE")
+ available = findFile("ibase.h") && (findFile("gds32_ms.lib") || findFile("gds32.lib"));
+ else if (part == "IWMMXT")
+ available = (dictionary[ "ARCHITECTURE" ] == "windowsce");
+ else if (part == "OPENGL_ES_CM")
+ available = (dictionary[ "ARCHITECTURE" ] == "windowsce");
+ else if (part == "OPENGL_ES_CL")
+ available = (dictionary[ "ARCHITECTURE" ] == "windowsce");
+ else if (part == "DIRECTSHOW")
+ available = (dictionary[ "ARCHITECTURE" ] == "windowsce");
+ else if (part == "SSE2")
+ available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-g++");
+ else if (part == "3DNOW" )
+ available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-icc") && findFile("mm3dnow.h") && (dictionary.value("QMAKESPEC") != "win32-g++");
+ else if (part == "MMX" || part == "SSE")
+ available = (dictionary.value("QMAKESPEC") != "win32-msvc") && (dictionary.value("QMAKESPEC") != "win32-g++");
+ else if (part == "OPENSSL")
+ available = findFile("openssl\\ssl.h");
+ else if (part == "DBUS")
+ available = findFile("dbus\\dbus.h");
+ else if (part == "CETEST") {
+ QString rapiHeader = locateFile("rapi.h");
+ QString rapiLib = locateFile("rapi.lib");
+ available = (dictionary[ "ARCHITECTURE" ] == "windowsce") && !rapiHeader.isEmpty() && !rapiLib.isEmpty();
+ if (available) {
+ dictionary[ "QT_CE_RAPI_INC" ] += QLatin1String("\"") + rapiHeader + QLatin1String("\"");
+ dictionary[ "QT_CE_RAPI_LIB" ] += QLatin1String("\"") + rapiLib + QLatin1String("\"");
+ }
+ }
+ else if (part == "INCREDIBUILD_XGE")
+ available = findFile("BuildConsole.exe") && findFile("xgConsole.exe");
+ else if (part == "XMLPATTERNS")
+ {
+ /* MSVC 6.0 and MSVC 2002/7.0 has too poor C++ support for QtXmlPatterns. */
+ return dictionary.value("QMAKESPEC") != "win32-msvc"
+ && dictionary.value("QMAKESPEC") != "win32-msvc.net" // Leave for now, since we can't be sure if they are using 2002 or 2003 with this spec
+ && dictionary.value("QMAKESPEC") != "win32-msvc2002"
+ && dictionary.value("EXCEPTIONS") == "yes";
+ } else if (part == "DIRECT3D") {
+ QString sdk_dir(QString::fromLocal8Bit(getenv("DXSDK_DIR")));
+ QDir dir;
+ bool has_d3d = false;
+
+ if (!sdk_dir.isEmpty() && dir.exists(sdk_dir))
+ has_d3d = true;
+
+ if (has_d3d && !QFile::exists(sdk_dir + QLatin1String("\\include\\d3d9.h"))) {
+ cout << "No Direct3D version 9 SDK found." << endl;
+ has_d3d = false;
+ }
+
+ // find the first dxguid.lib in the current LIB paths, if it is NOT
+ // the D3D SDK one, we're most likely in trouble..
+ if (has_d3d) {
+ has_d3d = false;
+ QString env_lib(QString::fromLocal8Bit(getenv("LIB")));
+ QStringList lib_paths = env_lib.split(';');
+ for (int i=0; i<lib_paths.size(); ++i) {
+ QString lib_path = lib_paths.at(i);
+ if (QFile::exists(lib_path + QLatin1String("\\dxguid.lib")))
+ {
+ if (lib_path.startsWith(sdk_dir)) {
+ has_d3d = true;
+ } else {
+ cout << "Your D3D/Platform SDK library paths seem to appear in the wrong order." << endl;
+ }
+ break;
+ }
+ }
+ }
+
+ available = has_d3d;
+ if (!has_d3d) {
+ cout << "Setting Direct3D to NO, since the proper Direct3D SDK was not detected." << endl
+ << "Make sure you have the Direct3D SDK installed, and that you have run" << endl
+ << "the <path to SDK>\\Utilities\\Bin\\dx_setenv.cmd script." << endl
+ << "The D3D SDK library path *needs* to appear before the Platform SDK library" << endl
+ << "path in your LIB environment variable." << endl;
+ }
+ } else if (part == "PHONON") {
+ available = findFile("vmr9.h") && findFile("dshow.h") && findFile("strmiids.lib") &&
+ findFile("dmoguids.lib") && findFile("msdmo.lib") && findFile("d3d9.h");
+
+ if (!available) {
+ cout << "All the required DirectShow/Direct3D files couldn't be found." << endl
+ << "Make sure you have either the platform SDK AND the DirectX SDK or the Windows SDK installed." << endl
+ << "If you have the DirectX SDK installed, please make sure that you have run the <path to SDK>\\SetEnv.Cmd script." << endl;
+ }
+ } else if (part == "WEBKIT") {
+ available = (dictionary.value("QMAKESPEC") == "win32-msvc2005") || (dictionary.value("QMAKESPEC") == "win32-msvc2008") || (dictionary.value("QMAKESPEC") == "win32-g++");
+ } else if (part == "SCRIPTTOOLS") {
+ available = true;
+ }
+
+ return available;
+}
+
+/*
+ Autodetect options marked as "auto".
+*/
+void Configure::autoDetection()
+{
+ // Style detection
+ if (dictionary["STYLE_WINDOWSXP"] == "auto")
+ dictionary["STYLE_WINDOWSXP"] = checkAvailability("STYLE_WINDOWSXP") ? defaultTo("STYLE_WINDOWSXP") : "no";
+ if (dictionary["STYLE_WINDOWSVISTA"] == "auto") // Vista style has the same requirements as XP style
+ dictionary["STYLE_WINDOWSVISTA"] = checkAvailability("STYLE_WINDOWSXP") ? defaultTo("STYLE_WINDOWSVISTA") : "no";
+
+ // Compression detection
+ if (dictionary["ZLIB"] == "auto")
+ dictionary["ZLIB"] = checkAvailability("ZLIB") ? defaultTo("ZLIB") : "qt";
+
+ // Image format detection
+ if (dictionary["GIF"] == "auto")
+ dictionary["GIF"] = defaultTo("GIF");
+ if (dictionary["JPEG"] == "auto")
+ dictionary["JPEG"] = defaultTo("JPEG");
+ if (dictionary["PNG"] == "auto")
+ dictionary["PNG"] = defaultTo("PNG");
+ if (dictionary["MNG"] == "auto")
+ dictionary["MNG"] = defaultTo("MNG");
+ if (dictionary["TIFF"] == "auto")
+ dictionary["TIFF"] = dictionary["ZLIB"] == "no" ? "no" : defaultTo("TIFF");
+ if (dictionary["LIBJPEG"] == "auto")
+ dictionary["LIBJPEG"] = checkAvailability("LIBJPEG") ? defaultTo("LIBJPEG") : "qt";
+ if (dictionary["LIBPNG"] == "auto")
+ dictionary["LIBPNG"] = checkAvailability("LIBPNG") ? defaultTo("LIBPNG") : "qt";
+ if (dictionary["LIBMNG"] == "auto")
+ dictionary["LIBMNG"] = checkAvailability("LIBMNG") ? defaultTo("LIBMNG") : "qt";
+ if (dictionary["LIBTIFF"] == "auto")
+ dictionary["LIBTIFF"] = checkAvailability("LIBTIFF") ? defaultTo("LIBTIFF") : "qt";
+
+ // SQL detection (not on by default)
+ if (dictionary["SQL_MYSQL"] == "auto")
+ dictionary["SQL_MYSQL"] = checkAvailability("SQL_MYSQL") ? defaultTo("SQL_MYSQL") : "no";
+ if (dictionary["SQL_ODBC"] == "auto")
+ dictionary["SQL_ODBC"] = checkAvailability("SQL_ODBC") ? defaultTo("SQL_ODBC") : "no";
+ if (dictionary["SQL_OCI"] == "auto")
+ dictionary["SQL_OCI"] = checkAvailability("SQL_OCI") ? defaultTo("SQL_OCI") : "no";
+ if (dictionary["SQL_PSQL"] == "auto")
+ dictionary["SQL_PSQL"] = checkAvailability("SQL_PSQL") ? defaultTo("SQL_PSQL") : "no";
+ if (dictionary["SQL_TDS"] == "auto")
+ dictionary["SQL_TDS"] = checkAvailability("SQL_TDS") ? defaultTo("SQL_TDS") : "no";
+ if (dictionary["SQL_DB2"] == "auto")
+ dictionary["SQL_DB2"] = checkAvailability("SQL_DB2") ? defaultTo("SQL_DB2") : "no";
+ if (dictionary["SQL_SQLITE"] == "auto")
+ dictionary["SQL_SQLITE"] = checkAvailability("SQL_SQLITE") ? defaultTo("SQL_SQLITE") : "no";
+ if (dictionary["SQL_SQLITE_LIB"] == "system")
+ if (!checkAvailability("SQL_SQLITE_LIB"))
+ dictionary["SQL_SQLITE_LIB"] = "no";
+ if (dictionary["SQL_SQLITE2"] == "auto")
+ dictionary["SQL_SQLITE2"] = checkAvailability("SQL_SQLITE2") ? defaultTo("SQL_SQLITE2") : "no";
+ if (dictionary["SQL_IBASE"] == "auto")
+ dictionary["SQL_IBASE"] = checkAvailability("SQL_IBASE") ? defaultTo("SQL_IBASE") : "no";
+ if (dictionary["MMX"] == "auto")
+ dictionary["MMX"] = checkAvailability("MMX") ? "yes" : "no";
+ if (dictionary["3DNOW"] == "auto")
+ dictionary["3DNOW"] = checkAvailability("3DNOW") ? "yes" : "no";
+ if (dictionary["SSE"] == "auto")
+ dictionary["SSE"] = checkAvailability("SSE") ? "yes" : "no";
+ if (dictionary["SSE2"] == "auto")
+ dictionary["SSE2"] = checkAvailability("SSE2") ? "yes" : "no";
+ if (dictionary["IWMMXT"] == "auto")
+ dictionary["IWMMXT"] = checkAvailability("IWMMXT") ? "yes" : "no";
+ if (dictionary["OPENSSL"] == "auto")
+ dictionary["OPENSSL"] = checkAvailability("OPENSSL") ? "yes" : "no";
+ if (dictionary["DBUS"] == "auto")
+ dictionary["DBUS"] = checkAvailability("DBUS") ? "yes" : "no";
+ if (dictionary["SCRIPTTOOLS"] == "auto")
+ dictionary["SCRIPTTOOLS"] = checkAvailability("SCRIPTTOOLS") ? "yes" : "no";
+ if (dictionary["XMLPATTERNS"] == "auto")
+ dictionary["XMLPATTERNS"] = checkAvailability("XMLPATTERNS") ? "yes" : "no";
+ if (dictionary["DIRECT3D"] == "auto")
+ dictionary["DIRECT3D"] = checkAvailability("DIRECT3D") ? "yes" : "no";
+ if (dictionary["PHONON"] == "auto")
+ dictionary["PHONON"] = checkAvailability("PHONON") ? "yes" : "no";
+ if (dictionary["WEBKIT"] == "auto")
+ dictionary["WEBKIT"] = checkAvailability("WEBKIT") ? "yes" : "no";
+
+ // Qt/WinCE remote test application
+ if (dictionary["CETEST"] == "auto")
+ dictionary["CETEST"] = checkAvailability("CETEST") ? "yes" : "no";
+
+ // Detection of IncrediBuild buildconsole
+ if (dictionary["INCREDIBUILD_XGE"] == "auto")
+ dictionary["INCREDIBUILD_XGE"] = checkAvailability("INCREDIBUILD_XGE") ? "yes" : "no";
+
+ // Mark all unknown "auto" to the default value..
+ for (QMap<QString,QString>::iterator i = dictionary.begin(); i != dictionary.end(); ++i) {
+ if (i.value() == "auto")
+ i.value() = defaultTo(i.key());
+ }
+}
+
+bool Configure::verifyConfiguration()
+{
+ if (dictionary["SQL_SQLITE_LIB"] == "no" && dictionary["SQL_SQLITE"] != "no") {
+ cout << "WARNING: Configure could not detect the presence of a system SQLite3 lib." << endl
+ << "Configure will therefore continue with the SQLite3 lib bundled with Qt." << endl
+ << "(Press any key to continue..)";
+ if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout)
+ exit(0); // Exit cleanly for Ctrl+C
+
+ dictionary["SQL_SQLITE_LIB"] = "qt"; // Set to Qt's bundled lib an continue
+ }
+ if (dictionary["QMAKESPEC"].endsWith("-g++")
+ && dictionary["SQL_OCI"] != "no") {
+ cout << "WARNING: Qt does not support compiling the Oracle database driver with" << endl
+ << "MinGW, due to lack of such support from Oracle. Consider disabling the" << endl
+ << "Oracle driver, as the current build will most likely fail." << endl;
+ cout << "(Press any key to continue..)";
+ if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout)
+ exit(0); // Exit cleanly for Ctrl+C
+ }
+ if (dictionary["QMAKESPEC"].endsWith("win32-msvc.net")) {
+ cout << "WARNING: The makespec win32-msvc.net is deprecated. Consider using" << endl
+ << "win32-msvc2002 or win32-msvc2003 instead." << endl;
+ cout << "(Press any key to continue..)";
+ if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout)
+ exit(0); // Exit cleanly for Ctrl+C
+ }
+
+ return true;
+}
+
+/*
+ Things that affect the Qt API/ABI:
+ Options:
+ minimal-config small-config medium-config large-config full-config
+
+ Options:
+ debug release
+ stl
+
+ Things that do not affect the Qt API/ABI:
+ system-jpeg no-jpeg jpeg
+ system-mng no-mng mng
+ system-png no-png png
+ system-zlib no-zlib zlib
+ system-tiff no-tiff tiff
+ no-gif gif
+ dll staticlib
+
+ internal
+ nocrosscompiler
+ GNUmake
+ largefile
+ nis
+ nas
+ tablet
+ ipv6
+
+ X11 : x11sm xinerama xcursor xfixes xrandr xrender fontconfig xkb
+ Embedded: embedded freetype
+*/
+void Configure::generateBuildKey()
+{
+ QString spec = dictionary["QMAKESPEC"];
+
+ QString compiler = "msvc"; // ICC is compatible
+ if (spec.endsWith("-g++"))
+ compiler = "mingw";
+ else if (spec.endsWith("-borland"))
+ compiler = "borland";
+
+ // Build options which changes the Qt API/ABI
+ QStringList build_options;
+ if (!dictionary["QCONFIG"].isEmpty())
+ build_options += dictionary["QCONFIG"] + "-config ";
+ if (dictionary["STL"] == "no")
+ build_options += "no-stl";
+ build_options.sort();
+
+ // Sorted defines that start with QT_NO_
+ QStringList build_defines = qmakeDefines.filter(QRegExp("^QT_NO_"));
+ build_defines.sort();
+
+ // Build up the QT_BUILD_KEY ifdef
+ QString buildKey = "QT_BUILD_KEY \"";
+ if (!dictionary["USER_BUILD_KEY"].isEmpty())
+ buildKey += dictionary["USER_BUILD_KEY"] + " ";
+
+ QString build32Key = buildKey + "Windows " + compiler + " %1 " + build_options.join(" ") + " " + build_defines.join(" ");
+ QString build64Key = buildKey + "Windows x64 " + compiler + " %1 " + build_options.join(" ") + " " + build_defines.join(" ");
+ build32Key = build32Key.simplified();
+ build64Key = build64Key.simplified();
+ build32Key.prepend("# define ");
+ build64Key.prepend("# define ");
+
+ QString buildkey = // Debug builds
+ "#if (defined(_DEBUG) || defined(DEBUG))\n"
+ "# if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))\n"
+ + build64Key.arg("debug") + "\"\n"
+ "# else\n"
+ + build32Key.arg("debug") + "\"\n"
+ "# endif\n"
+ "#else\n"
+ // Release builds
+ "# if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))\n"
+ + build64Key.arg("release") + "\"\n"
+ "# else\n"
+ + build32Key.arg("release") + "\"\n"
+ "# endif\n"
+ "#endif\n";
+
+ dictionary["BUILD_KEY"] = buildkey;
+}
+
+void Configure::generateOutputVars()
+{
+ // Generate variables for output
+ // Build key ----------------------------------------------------
+ if ( dictionary.contains("BUILD_KEY") ) {
+ qmakeVars += dictionary.value("BUILD_KEY");
+ }
+
+ QString build = dictionary[ "BUILD" ];
+ bool buildAll = (dictionary[ "BUILDALL" ] == "yes");
+ if ( build == "debug") {
+ if (buildAll)
+ qtConfig += "release";
+ qtConfig += "debug";
+ } else if (build == "release") {
+ if (buildAll)
+ qtConfig += "debug";
+ qtConfig += "release";
+ }
+
+ // Compression --------------------------------------------------
+ if( dictionary[ "ZLIB" ] == "qt" )
+ qtConfig += "zlib";
+ else if( dictionary[ "ZLIB" ] == "system" )
+ qtConfig += "system-zlib";
+
+ // Image formates -----------------------------------------------
+ if( dictionary[ "GIF" ] == "no" )
+ qtConfig += "no-gif";
+ else if( dictionary[ "GIF" ] == "yes" )
+ qtConfig += "gif";
+ else if( dictionary[ "GIF" ] == "plugin" )
+ qmakeFormatPlugins += "gif";
+
+ if( dictionary[ "TIFF" ] == "no" )
+ qtConfig += "no-tiff";
+ else if( dictionary[ "TIFF" ] == "plugin" )
+ qmakeFormatPlugins += "tiff";
+ if( dictionary[ "LIBTIFF" ] == "system" )
+ qtConfig += "system-tiff";
+
+ if( dictionary[ "JPEG" ] == "no" )
+ qtConfig += "no-jpeg";
+ else if( dictionary[ "JPEG" ] == "plugin" )
+ qmakeFormatPlugins += "jpeg";
+ if( dictionary[ "LIBJPEG" ] == "system" )
+ qtConfig += "system-jpeg";
+
+ if( dictionary[ "PNG" ] == "no" )
+ qtConfig += "no-png";
+ else if( dictionary[ "PNG" ] == "qt" )
+ qtConfig += "png";
+ if( dictionary[ "LIBPNG" ] == "system" )
+ qtConfig += "system-png";
+
+ if( dictionary[ "MNG" ] == "no" )
+ qtConfig += "no-mng";
+ else if( dictionary[ "MNG" ] == "qt" )
+ qtConfig += "mng";
+ if( dictionary[ "LIBMNG" ] == "system" )
+ qtConfig += "system-mng";
+
+ // Styles -------------------------------------------------------
+ if ( dictionary[ "STYLE_WINDOWS" ] == "yes" )
+ qmakeStyles += "windows";
+
+ if ( dictionary[ "STYLE_PLASTIQUE" ] == "yes" )
+ qmakeStyles += "plastique";
+
+ if ( dictionary[ "STYLE_CLEANLOOKS" ] == "yes" )
+ qmakeStyles += "cleanlooks";
+
+ if ( dictionary[ "STYLE_WINDOWSXP" ] == "yes" )
+ qmakeStyles += "windowsxp";
+
+ if ( dictionary[ "STYLE_WINDOWSVISTA" ] == "yes" )
+ qmakeStyles += "windowsvista";
+
+ if ( dictionary[ "STYLE_MOTIF" ] == "yes" )
+ qmakeStyles += "motif";
+
+ if ( dictionary[ "STYLE_SGI" ] == "yes" )
+ qmakeStyles += "sgi";
+
+ if ( dictionary[ "STYLE_WINDOWSCE" ] == "yes" )
+ qmakeStyles += "windowsce";
+
+ if ( dictionary[ "STYLE_WINDOWSMOBILE" ] == "yes" )
+ qmakeStyles += "windowsmobile";
+
+ if ( dictionary[ "STYLE_CDE" ] == "yes" )
+ qmakeStyles += "cde";
+
+ // Databases ----------------------------------------------------
+ if ( dictionary[ "SQL_MYSQL" ] == "yes" )
+ qmakeSql += "mysql";
+ else if ( dictionary[ "SQL_MYSQL" ] == "plugin" )
+ qmakeSqlPlugins += "mysql";
+
+ if ( dictionary[ "SQL_ODBC" ] == "yes" )
+ qmakeSql += "odbc";
+ else if ( dictionary[ "SQL_ODBC" ] == "plugin" )
+ qmakeSqlPlugins += "odbc";
+
+ if ( dictionary[ "SQL_OCI" ] == "yes" )
+ qmakeSql += "oci";
+ else if ( dictionary[ "SQL_OCI" ] == "plugin" )
+ qmakeSqlPlugins += "oci";
+
+ if ( dictionary[ "SQL_PSQL" ] == "yes" )
+ qmakeSql += "psql";
+ else if ( dictionary[ "SQL_PSQL" ] == "plugin" )
+ qmakeSqlPlugins += "psql";
+
+ if ( dictionary[ "SQL_TDS" ] == "yes" )
+ qmakeSql += "tds";
+ else if ( dictionary[ "SQL_TDS" ] == "plugin" )
+ qmakeSqlPlugins += "tds";
+
+ if ( dictionary[ "SQL_DB2" ] == "yes" )
+ qmakeSql += "db2";
+ else if ( dictionary[ "SQL_DB2" ] == "plugin" )
+ qmakeSqlPlugins += "db2";
+
+ if ( dictionary[ "SQL_SQLITE" ] == "yes" )
+ qmakeSql += "sqlite";
+ else if ( dictionary[ "SQL_SQLITE" ] == "plugin" )
+ qmakeSqlPlugins += "sqlite";
+
+ if ( dictionary[ "SQL_SQLITE_LIB" ] == "system" )
+ qmakeConfig += "system-sqlite";
+
+ if ( dictionary[ "SQL_SQLITE2" ] == "yes" )
+ qmakeSql += "sqlite2";
+ else if ( dictionary[ "SQL_SQLITE2" ] == "plugin" )
+ qmakeSqlPlugins += "sqlite2";
+
+ if ( dictionary[ "SQL_IBASE" ] == "yes" )
+ qmakeSql += "ibase";
+ else if ( dictionary[ "SQL_IBASE" ] == "plugin" )
+ qmakeSqlPlugins += "ibase";
+
+ // Other options ------------------------------------------------
+ if( dictionary[ "BUILDALL" ] == "yes" ) {
+ qmakeConfig += "build_all";
+ }
+ qmakeConfig += dictionary[ "BUILD" ];
+ dictionary[ "QMAKE_OUTDIR" ] = dictionary[ "BUILD" ];
+
+ if ( dictionary[ "SHARED" ] == "yes" ) {
+ QString version = dictionary[ "VERSION" ];
+ if (!version.isEmpty()) {
+ qmakeVars += "QMAKE_QT_VERSION_OVERRIDE = " + version.left(version.indexOf("."));
+ version.remove(QLatin1Char('.'));
+ }
+ dictionary[ "QMAKE_OUTDIR" ] += "_shared";
+ } else {
+ dictionary[ "QMAKE_OUTDIR" ] += "_static";
+ }
+
+ if( dictionary[ "ACCESSIBILITY" ] == "yes" )
+ qtConfig += "accessibility";
+
+ if( !qmakeLibs.isEmpty() )
+ qmakeVars += "LIBS += " + qmakeLibs.join( " " );
+
+ if( !dictionary["QT_LFLAGS_SQLITE"].isEmpty() )
+ qmakeVars += "QT_LFLAGS_SQLITE += " + dictionary["QT_LFLAGS_SQLITE"];
+
+ if (dictionary[ "QT3SUPPORT" ] == "yes")
+ qtConfig += "qt3support";
+
+ if (dictionary[ "OPENGL" ] == "yes")
+ qtConfig += "opengl";
+
+ if ( dictionary["OPENGL_ES_CM"] == "yes" ) {
+ qtConfig += "opengles1";
+ }
+
+ if ( dictionary["OPENGL_ES_CL"] == "yes" ) {
+ qtConfig += "opengles1cl";
+ }
+
+ if ( dictionary["DIRECTSHOW"] == "yes" )
+ qtConfig += "directshow";
+
+ if (dictionary[ "DIRECT3D" ] == "yes")
+ qtConfig += "direct3d";
+
+ if (dictionary[ "OPENSSL" ] == "yes")
+ qtConfig += "openssl";
+ else if (dictionary[ "OPENSSL" ] == "linked")
+ qtConfig += "openssl-linked";
+
+ if (dictionary[ "DBUS" ] == "yes")
+ qtConfig += "dbus";
+ else if (dictionary[ "DBUS" ] == "linked")
+ qtConfig += "dbus dbus-linked";
+
+ if (dictionary["IPV6"] == "yes")
+ qtConfig += "ipv6";
+ else if (dictionary["IPV6"] == "no")
+ qtConfig += "no-ipv6";
+
+ if (dictionary[ "CETEST" ] == "yes")
+ qtConfig += "cetest";
+
+ if (dictionary[ "SCRIPTTOOLS" ] == "yes")
+ qtConfig += "scripttools";
+
+ if (dictionary[ "XMLPATTERNS" ] == "yes")
+ qtConfig += "xmlpatterns";
+
+ if (dictionary["PHONON"] == "yes") {
+ qtConfig += "phonon";
+ if (dictionary["PHONON_BACKEND"] == "yes")
+ qtConfig += "phonon-backend";
+ }
+
+ if (dictionary["WEBKIT"] == "yes")
+ qtConfig += "webkit";
+
+ // We currently have no switch for QtSvg, so add it unconditionally.
+ qtConfig += "svg";
+
+ // Add config levels --------------------------------------------
+ QStringList possible_configs = QStringList()
+ << "minimal"
+ << "small"
+ << "medium"
+ << "large"
+ << "full";
+
+ QString set_config = dictionary["QCONFIG"];
+ if (possible_configs.contains(set_config)) {
+ foreach(QString cfg, possible_configs) {
+ qtConfig += (cfg + "-config");
+ if (cfg == set_config)
+ break;
+ }
+ }
+
+ // Directories and settings for .qmake.cache --------------------
+
+ // if QT_INSTALL_* have not been specified on commandline, define them now from QT_INSTALL_PREFIX
+ // if prefix is empty (WINCE), make all of them empty, if they aren't set
+ bool qipempty = false;
+ if(dictionary[ "QT_INSTALL_PREFIX" ].isEmpty())
+ qipempty = true;
+
+ if( !dictionary[ "QT_INSTALL_DOCS" ].size() )
+ dictionary[ "QT_INSTALL_DOCS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/doc" );
+ if( !dictionary[ "QT_INSTALL_HEADERS" ].size() )
+ dictionary[ "QT_INSTALL_HEADERS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/include" );
+ if( !dictionary[ "QT_INSTALL_LIBS" ].size() )
+ dictionary[ "QT_INSTALL_LIBS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/lib" );
+ if( !dictionary[ "QT_INSTALL_BINS" ].size() )
+ dictionary[ "QT_INSTALL_BINS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/bin" );
+ if( !dictionary[ "QT_INSTALL_PLUGINS" ].size() )
+ dictionary[ "QT_INSTALL_PLUGINS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/plugins" );
+ if( !dictionary[ "QT_INSTALL_DATA" ].size() )
+ dictionary[ "QT_INSTALL_DATA" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] );
+ if( !dictionary[ "QT_INSTALL_TRANSLATIONS" ].size() )
+ dictionary[ "QT_INSTALL_TRANSLATIONS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/translations" );
+ if( !dictionary[ "QT_INSTALL_EXAMPLES" ].size() )
+ dictionary[ "QT_INSTALL_EXAMPLES" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/examples");
+ if( !dictionary[ "QT_INSTALL_DEMOS" ].size() )
+ dictionary[ "QT_INSTALL_DEMOS" ] = qipempty ? "" : fixSeparators( dictionary[ "QT_INSTALL_PREFIX" ] + "/demos" );
+
+ if(dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("linux"))
+ dictionary[ "QMAKE_RPATHDIR" ] = dictionary[ "QT_INSTALL_LIBS" ];
+
+ qmakeVars += QString("OBJECTS_DIR = ") + fixSeparators( "tmp/obj/" + dictionary[ "QMAKE_OUTDIR" ] );
+ qmakeVars += QString("MOC_DIR = ") + fixSeparators( "tmp/moc/" + dictionary[ "QMAKE_OUTDIR" ] );
+ qmakeVars += QString("RCC_DIR = ") + fixSeparators("tmp/rcc/" + dictionary["QMAKE_OUTDIR"]);
+
+ if (!qmakeDefines.isEmpty())
+ qmakeVars += QString("DEFINES += ") + qmakeDefines.join( " " );
+ if (!qmakeIncludes.isEmpty())
+ qmakeVars += QString("INCLUDEPATH += ") + qmakeIncludes.join( " " );
+ if (!opensslLibs.isEmpty())
+ qmakeVars += opensslLibs;
+ else if (dictionary[ "OPENSSL" ] == "linked")
+ qmakeVars += QString("OPENSSL_LIBS = -lssleay32 -llibeay32");
+ if (!qmakeSql.isEmpty())
+ qmakeVars += QString("sql-drivers += ") + qmakeSql.join( " " );
+ if (!qmakeSqlPlugins.isEmpty())
+ qmakeVars += QString("sql-plugins += ") + qmakeSqlPlugins.join( " " );
+ if (!qmakeStyles.isEmpty())
+ qmakeVars += QString("styles += ") + qmakeStyles.join( " " );
+ if (!qmakeStylePlugins.isEmpty())
+ qmakeVars += QString("style-plugins += ") + qmakeStylePlugins.join( " " );
+ if (!qmakeFormatPlugins.isEmpty())
+ qmakeVars += QString("imageformat-plugins += ") + qmakeFormatPlugins.join( " " );
+
+ if (dictionary["QMAKESPEC"].endsWith("-g++")) {
+ QString includepath = qgetenv("INCLUDE");
+ bool hasSh = Environment::detectExecutable("sh.exe");
+ QChar separator = (!includepath.contains(":\\") && hasSh ? QChar(':') : QChar(';'));
+ qmakeVars += QString("TMPPATH = $$quote($$(INCLUDE))");
+ qmakeVars += QString("QMAKE_INCDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator);
+ qmakeVars += QString("TMPPATH = $$quote($$(LIB))");
+ qmakeVars += QString("QMAKE_LIBDIR_POST += $$split(TMPPATH,\"%1\")").arg(separator);
+ }
+
+ if( !dictionary[ "QMAKESPEC" ].length() ) {
+ cout << "Configure could not detect your compiler. QMAKESPEC must either" << endl
+ << "be defined as an environment variable, or specified as an" << endl
+ << "argument with -platform" << endl;
+ dictionary[ "HELP" ] = "yes";
+
+ QStringList winPlatforms;
+ QDir mkspecsDir( sourcePath + "/mkspecs" );
+ const QFileInfoList &specsList = mkspecsDir.entryInfoList();
+ for(int i = 0; i < specsList.size(); ++i) {
+ const QFileInfo &fi = specsList.at(i);
+ if( fi.fileName().left( 5 ) == "win32" ) {
+ winPlatforms += fi.fileName();
+ }
+ }
+ cout << "Available platforms are: " << qPrintable(winPlatforms.join( ", " )) << endl;
+ dictionary[ "DONE" ] = "error";
+ }
+}
+
+#if !defined(EVAL)
+void Configure::generateCachefile()
+{
+ // Generate .qmake.cache
+ QFile cacheFile( buildPath + "/.qmake.cache" );
+ if( cacheFile.open( QFile::WriteOnly | QFile::Text ) ) { // Truncates any existing file.
+ QTextStream cacheStream( &cacheFile );
+ for( QStringList::Iterator var = qmakeVars.begin(); var != qmakeVars.end(); ++var ) {
+ cacheStream << (*var) << endl;
+ }
+ cacheStream << "CONFIG += " << qmakeConfig.join( " " ) << " incremental create_prl link_prl depend_includepath QTDIR_build" << endl;
+
+ QStringList buildParts;
+ buildParts << "libs" << "tools" << "examples" << "demos" << "docs" << "translations";
+ foreach(QString item, disabledBuildParts) {
+ buildParts.removeAll(item);
+ }
+ cacheStream << "QT_BUILD_PARTS = " << buildParts.join( " " ) << endl;
+
+ QString targetSpec = dictionary.contains("XQMAKESPEC") ? dictionary[ "XQMAKESPEC" ] : dictionary[ "QMAKESPEC" ];
+ QString mkspec_path = fixSeparators(sourcePath + "/mkspecs/" + targetSpec);
+ if(QFile::exists(mkspec_path))
+ cacheStream << "QMAKESPEC = " << mkspec_path << endl;
+ else
+ cacheStream << "QMAKESPEC = " << fixSeparators(targetSpec) << endl;
+ cacheStream << "ARCH = " << fixSeparators(dictionary[ "ARCHITECTURE" ]) << endl;
+ cacheStream << "QT_BUILD_TREE = " << fixSeparators(dictionary[ "QT_BUILD_TREE" ]) << endl;
+ cacheStream << "QT_SOURCE_TREE = " << fixSeparators(dictionary[ "QT_SOURCE_TREE" ]) << endl;
+
+ if (dictionary["QT_EDITION"] != "QT_EDITION_OPENSOURCE")
+ cacheStream << "DEFINES *= QT_EDITION=QT_EDITION_DESKTOP" << endl;
+
+ //so that we can build without an install first (which would be impossible)
+ cacheStream << "QMAKE_MOC = $$QT_BUILD_TREE" << fixSeparators("/bin/moc.exe") << endl;
+ cacheStream << "QMAKE_UIC = $$QT_BUILD_TREE" << fixSeparators("/bin/uic.exe") << endl;
+ cacheStream << "QMAKE_UIC3 = $$QT_BUILD_TREE" << fixSeparators("/bin/uic3.exe") << endl;
+ cacheStream << "QMAKE_RCC = $$QT_BUILD_TREE" << fixSeparators("/bin/rcc.exe") << endl;
+ cacheStream << "QMAKE_DUMPCPP = $$QT_BUILD_TREE" << fixSeparators("/bin/dumpcpp.exe") << endl;
+ cacheStream << "QMAKE_INCDIR_QT = $$QT_BUILD_TREE" << fixSeparators("/include") << endl;
+ cacheStream << "QMAKE_LIBDIR_QT = $$QT_BUILD_TREE" << fixSeparators("/lib") << endl;
+ if (dictionary["CETEST"] == "yes") {
+ cacheStream << "QT_CE_RAPI_INC = " << fixSeparators(dictionary[ "QT_CE_RAPI_INC" ]) << endl;
+ cacheStream << "QT_CE_RAPI_LIB = " << fixSeparators(dictionary[ "QT_CE_RAPI_LIB" ]) << endl;
+ }
+
+ // embedded
+ if( !dictionary["KBD_DRIVERS"].isEmpty())
+ cacheStream << "kbd-drivers += "<< dictionary["KBD_DRIVERS"]<<endl;
+ if( !dictionary["GFX_DRIVERS"].isEmpty())
+ cacheStream << "gfx-drivers += "<< dictionary["GFX_DRIVERS"]<<endl;
+ if( !dictionary["MOUSE_DRIVERS"].isEmpty())
+ cacheStream << "mouse-drivers += "<< dictionary["MOUSE_DRIVERS"]<<endl;
+ if( !dictionary["DECORATIONS"].isEmpty())
+ cacheStream << "decorations += "<<dictionary["DECORATIONS"]<<endl;
+
+ if( !dictionary["QMAKE_RPATHDIR"].isEmpty() )
+ cacheStream << "QMAKE_RPATHDIR += "<<dictionary["QMAKE_RPATHDIR"];
+
+ cacheStream.flush();
+ cacheFile.close();
+ }
+ QFile configFile( dictionary[ "QT_BUILD_TREE" ] + "/mkspecs/qconfig.pri" );
+ if( configFile.open( QFile::WriteOnly | QFile::Text ) ) { // Truncates any existing file.
+ QTextStream configStream( &configFile );
+ configStream << "CONFIG+= ";
+ configStream << dictionary[ "BUILD" ];
+ if( dictionary[ "SHARED" ] == "yes" )
+ configStream << " shared";
+ else
+ configStream << " static";
+
+ if( dictionary[ "STL" ] == "yes" )
+ configStream << " stl";
+ if ( dictionary[ "EXCEPTIONS" ] == "yes" )
+ configStream << " exceptions";
+ if ( dictionary[ "EXCEPTIONS" ] == "no" )
+ configStream << " exceptions_off";
+ if ( dictionary[ "RTTI" ] == "yes" )
+ configStream << " rtti";
+ if ( dictionary[ "MMX" ] == "yes" )
+ configStream << " mmx";
+ if ( dictionary[ "3DNOW" ] == "yes" )
+ configStream << " 3dnow";
+ if ( dictionary[ "SSE" ] == "yes" )
+ configStream << " sse";
+ if ( dictionary[ "SSE2" ] == "yes" )
+ configStream << " sse2";
+ if ( dictionary[ "IWMMXT" ] == "yes" )
+ configStream << " iwmmxt";
+ if ( dictionary["INCREDIBUILD_XGE"] == "yes" )
+ configStream << " incredibuild_xge";
+ if ( dictionary["PLUGIN_MANIFESTS"] == "no" )
+ configStream << " no_plugin_manifest";
+
+ configStream << endl;
+ configStream << "QT_ARCH = " << dictionary[ "ARCHITECTURE" ] << endl;
+ if (dictionary["QT_EDITION"].contains("OPENSOURCE"))
+ configStream << "QT_EDITION = " << QLatin1String("OpenSource") << endl;
+ else
+ configStream << "QT_EDITION = " << dictionary["EDITION"] << endl;
+ configStream << "QT_CONFIG += " << qtConfig.join(" ") << endl;
+
+ configStream << "#versioning " << endl
+ << "QT_VERSION = " << dictionary["VERSION"] << endl
+ << "QT_MAJOR_VERSION = " << dictionary["VERSION_MAJOR"] << endl
+ << "QT_MINOR_VERSION = " << dictionary["VERSION_MINOR"] << endl
+ << "QT_PATCH_VERSION = " << dictionary["VERSION_PATCH"] << endl;
+
+ configStream << "#Qt for Windows CE c-runtime deployment" << endl
+ << "QT_CE_C_RUNTIME = " << fixSeparators(dictionary[ "CE_CRT" ]) << endl;
+
+ if(dictionary["CE_SIGNATURE"] != QLatin1String("no"))
+ configStream << "DEFAULT_SIGNATURE=" << dictionary["CE_SIGNATURE"] << endl;
+
+ if(!dictionary["QMAKE_RPATHDIR"].isEmpty())
+ configStream<<"QMAKE_RPATHDIR += "<<dictionary["QMAKE_RPATHDIR"];
+
+ configStream.flush();
+ configFile.close();
+ }
+}
+#endif
+
+QString Configure::addDefine(QString def)
+{
+ QString result, defNeg, defD = def;
+
+ defD.replace(QRegExp("=.*"), "");
+ def.replace(QRegExp("="), " ");
+
+ if(def.startsWith("QT_NO_")) {
+ defNeg = defD;
+ defNeg.replace("QT_NO_", "QT_");
+ } else if(def.startsWith("QT_")) {
+ defNeg = defD;
+ defNeg.replace("QT_", "QT_NO_");
+ }
+
+ if (defNeg.isEmpty()) {
+ result = "#ifndef $DEFD\n"
+ "# define $DEF\n"
+ "#endif\n\n";
+ } else {
+ result = "#if defined($DEFD) && defined($DEFNEG)\n"
+ "# undef $DEFD\n"
+ "#elif !defined($DEFD)\n"
+ "# define $DEF\n"
+ "#endif\n\n";
+ }
+ result.replace("$DEFNEG", defNeg);
+ result.replace("$DEFD", defD);
+ result.replace("$DEF", def);
+ return result;
+}
+
+#if !defined(EVAL)
+void Configure::generateConfigfiles()
+{
+ QDir(buildPath).mkpath("src/corelib/global");
+ QString outName( buildPath + "/src/corelib/global/qconfig.h" );
+ QTemporaryFile tmpFile;
+ QTextStream tmpStream;
+
+ if(tmpFile.open()) {
+ tmpStream.setDevice(&tmpFile);
+
+ if( dictionary[ "QCONFIG" ] == "full" ) {
+ tmpStream << "/* Everything */" << endl;
+ } else {
+ QString configName( "qconfig-" + dictionary[ "QCONFIG" ] + ".h" );
+ tmpStream << "/* Copied from " << configName << "*/" << endl;
+ tmpStream << "#ifndef QT_BOOTSTRAPPED" << endl;
+ QFile inFile( sourcePath + "/src/corelib/global/" + configName );
+ if( inFile.open( QFile::ReadOnly ) ) {
+ QByteArray buffer = inFile.readAll();
+ tmpFile.write( buffer.constData(), buffer.size() );
+ inFile.close();
+ }
+ tmpStream << "#endif // QT_BOOTSTRAPPED" << endl;
+ }
+ tmpStream << endl;
+
+ if( dictionary[ "SHARED" ] == "yes" ) {
+ tmpStream << "#ifndef QT_DLL" << endl;
+ tmpStream << "#define QT_DLL" << endl;
+ tmpStream << "#endif" << endl;
+ }
+ tmpStream << endl;
+ tmpStream << "/* License information */" << endl;
+ tmpStream << "#define QT_PRODUCT_LICENSEE \"" << licenseInfo[ "LICENSEE" ] << "\"" << endl;
+ tmpStream << "#define QT_PRODUCT_LICENSE \"" << dictionary[ "EDITION" ] << "\"" << endl;
+ tmpStream << endl;
+ tmpStream << "// Qt Edition" << endl;
+ tmpStream << "#ifndef QT_EDITION" << endl;
+ tmpStream << "# define QT_EDITION " << dictionary["QT_EDITION"] << endl;
+ tmpStream << "#endif" << endl;
+ tmpStream << endl;
+ tmpStream << dictionary["BUILD_KEY"];
+ tmpStream << endl;
+ if (dictionary["BUILDDEV"] == "yes") {
+ dictionary["QMAKE_INTERNAL"] = "yes";
+ tmpStream << "/* Used for example to export symbols for the certain autotests*/" << endl;
+ tmpStream << "#define QT_BUILD_INTERNAL" << endl;
+ tmpStream << endl;
+ }
+ tmpStream << "/* Machine byte-order */" << endl;
+ tmpStream << "#define Q_BIG_ENDIAN 4321" << endl;
+ tmpStream << "#define Q_LITTLE_ENDIAN 1234" << endl;
+ if ( QSysInfo::ByteOrder == QSysInfo::BigEndian )
+ tmpStream << "#define Q_BYTE_ORDER Q_BIG_ENDIAN" << endl;
+ else
+ tmpStream << "#define Q_BYTE_ORDER Q_LITTLE_ENDIAN" << endl;
+
+ tmpStream << endl << "// Compile time features" << endl;
+ tmpStream << "#define QT_ARCH_" << dictionary["ARCHITECTURE"].toUpper() << endl;
+ QStringList qconfigList;
+ if(dictionary["STL"] == "no") qconfigList += "QT_NO_STL";
+ if(dictionary["STYLE_WINDOWS"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWS";
+ if(dictionary["STYLE_PLASTIQUE"] != "yes") qconfigList += "QT_NO_STYLE_PLASTIQUE";
+ if(dictionary["STYLE_CLEANLOOKS"] != "yes") qconfigList += "QT_NO_STYLE_CLEANLOOKS";
+ if(dictionary["STYLE_WINDOWSXP"] != "yes" && dictionary["STYLE_WINDOWSVISTA"] != "yes")
+ qconfigList += "QT_NO_STYLE_WINDOWSXP";
+ if(dictionary["STYLE_WINDOWSVISTA"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSVISTA";
+ if(dictionary["STYLE_MOTIF"] != "yes") qconfigList += "QT_NO_STYLE_MOTIF";
+ if(dictionary["STYLE_CDE"] != "yes") qconfigList += "QT_NO_STYLE_CDE";
+ if(dictionary["STYLE_WINDOWSCE"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSCE";
+ if(dictionary["STYLE_WINDOWSMOBILE"] != "yes") qconfigList += "QT_NO_STYLE_WINDOWSMOBILE";
+ if(dictionary["STYLE_GTK"] != "yes") qconfigList += "QT_NO_STYLE_GTK";
+
+ if(dictionary["GIF"] == "yes") qconfigList += "QT_BUILTIN_GIF_READER=1";
+ if(dictionary["PNG"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_PNG";
+ if(dictionary["MNG"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_MNG";
+ if(dictionary["JPEG"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_JPEG";
+ if(dictionary["TIFF"] == "no") qconfigList += "QT_NO_IMAGEFORMAT_TIFF";
+ if(dictionary["ZLIB"] == "no") {
+ qconfigList += "QT_NO_ZLIB";
+ qconfigList += "QT_NO_COMPRESS";
+ }
+
+ if(dictionary["QT3SUPPORT"] == "no") qconfigList += "QT_NO_QT3SUPPORT";
+ if(dictionary["ACCESSIBILITY"] == "no") qconfigList += "QT_NO_ACCESSIBILITY";
+ if(dictionary["EXCEPTIONS"] == "no") qconfigList += "QT_NO_EXCEPTIONS";
+ if(dictionary["OPENGL"] == "no") qconfigList += "QT_NO_OPENGL";
+ if(dictionary["DIRECT3D"] == "no") qconfigList += "QT_NO_DIRECT3D";
+ if(dictionary["OPENSSL"] == "no") qconfigList += "QT_NO_OPENSSL";
+ if(dictionary["OPENSSL"] == "linked") qconfigList += "QT_LINKED_OPENSSL";
+ if(dictionary["DBUS"] == "no") qconfigList += "QT_NO_DBUS";
+ if(dictionary["IPV6"] == "no") qconfigList += "QT_NO_IPV6";
+ if(dictionary["WEBKIT"] == "no") qconfigList += "QT_NO_WEBKIT";
+ if(dictionary["PHONON"] == "no") qconfigList += "QT_NO_PHONON";
+ if(dictionary["XMLPATTERNS"] == "no") qconfigList += "QT_NO_XMLPATTERNS";
+ if(dictionary["SCRIPTTOOLS"] == "no") qconfigList += "QT_NO_SCRIPTTOOLS";
+
+ if(dictionary["OPENGL_ES_CM"] == "yes" ||
+ dictionary["OPENGL_ES_CL"] == "yes") qconfigList += "QT_OPENGL_ES";
+
+ if(dictionary["OPENGL_ES_CM"] == "yes") qconfigList += "QT_OPENGL_ES_1";
+ if(dictionary["OPENGL_ES_CL"] == "yes") qconfigList += "QT_OPENGL_ES_1_CL";
+
+ if(dictionary["SQL_MYSQL"] == "yes") qconfigList += "QT_SQL_MYSQL";
+ if(dictionary["SQL_ODBC"] == "yes") qconfigList += "QT_SQL_ODBC";
+ if(dictionary["SQL_OCI"] == "yes") qconfigList += "QT_SQL_OCI";
+ if(dictionary["SQL_PSQL"] == "yes") qconfigList += "QT_SQL_PSQL";
+ if(dictionary["SQL_TDS"] == "yes") qconfigList += "QT_SQL_TDS";
+ if(dictionary["SQL_DB2"] == "yes") qconfigList += "QT_SQL_DB2";
+ if(dictionary["SQL_SQLITE"] == "yes") qconfigList += "QT_SQL_SQLITE";
+ if(dictionary["SQL_SQLITE2"] == "yes") qconfigList += "QT_SQL_SQLITE2";
+ if(dictionary["SQL_IBASE"] == "yes") qconfigList += "QT_SQL_IBASE";
+
+ if (dictionary["GRAPHICS_SYSTEM"] == "opengl") qconfigList += "QT_GRAPHICSSYSTEM_OPENGL";
+ if (dictionary["GRAPHICS_SYSTEM"] == "raster") qconfigList += "QT_GRAPHICSSYSTEM_RASTER";
+
+ qconfigList.sort();
+ for (int i = 0; i < qconfigList.count(); ++i)
+ tmpStream << addDefine(qconfigList.at(i));
+
+ if(dictionary["EMBEDDED"] == "yes")
+ {
+ // Check for keyboard, mouse, gfx.
+ QStringList kbdDrivers = dictionary["KBD_DRIVERS"].split(" ");;
+ QStringList allKbdDrivers;
+ allKbdDrivers<<"tty"<<"usb"<<"sl5000"<<"yopy"<<"vr41xx"<<"qvfb"<<"um";
+ foreach(QString kbd, allKbdDrivers) {
+ if( !kbdDrivers.contains(kbd))
+ tmpStream<<"#define QT_NO_QWS_KBD_"<<kbd.toUpper()<<endl;
+ }
+
+ QStringList mouseDrivers = dictionary["MOUSE_DRIVERS"].split(" ");
+ QStringList allMouseDrivers;
+ allMouseDrivers << "pc"<<"bus"<<"linuxtp"<<"yopy"<<"vr41xx"<<"tslib"<<"qvfb";
+ foreach(QString mouse, allMouseDrivers) {
+ if( !mouseDrivers.contains(mouse) )
+ tmpStream<<"#define QT_NO_QWS_MOUSE_"<<mouse.toUpper()<<endl;
+ }
+
+ QStringList gfxDrivers = dictionary["GFX_DRIVERS"].split(" ");
+ QStringList allGfxDrivers;
+ allGfxDrivers<<"linuxfb"<<"transformed"<<"qvfb"<<"vnc"<<"multiscreen"<<"ahi";
+ foreach(QString gfx, allGfxDrivers) {
+ if( !gfxDrivers.contains(gfx))
+ tmpStream<<"#define QT_NO_QWS_"<<gfx.toUpper()<<endl;
+ }
+
+ tmpStream<<"#define Q_WS_QWS"<<endl;
+
+ QStringList depths = dictionary[ "QT_QWS_DEPTH" ].split(" ");
+ foreach(QString depth, depths)
+ tmpStream<<"#define QT_QWS_DEPTH_"+depth<<endl;
+ }
+
+ if( dictionary[ "QT_CUPS" ] == "no")
+ tmpStream<<"#define QT_NO_CUPS"<<endl;
+
+ if( dictionary[ "QT_ICONV" ] == "no")
+ tmpStream<<"#define QT_NO_ICONV"<<endl;
+
+ if(dictionary[ "QT_GLIB" ] == "no")
+ tmpStream<<"#define QT_NO_GLIB"<<endl;
+
+ if(dictionary[ "QT_LPR" ] == "no")
+ tmpStream<<"#define QT_NO_LPR"<<endl;
+
+ if(dictionary[ "QT_INOTIFY" ] == "no" )
+ tmpStream<<"#define QT_NO_INOTIFY"<<endl;
+
+ if(dictionary[ "QT_SXE" ] == "no")
+ tmpStream<<"#define QT_NO_SXE"<<endl;
+
+ tmpStream.flush();
+ tmpFile.flush();
+
+ // Replace old qconfig.h with new one
+ ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL);
+ QFile::remove(outName);
+ tmpFile.copy(outName);
+ tmpFile.close();
+
+ if(!QFile::exists(buildPath + "/include/QtCore/qconfig.h")) {
+ if (!writeToFile("#include \"../../src/corelib/global/qconfig.h\"\n",
+ buildPath + "/include/QtCore/qconfig.h")
+ || !writeToFile("#include \"../../src/corelib/global/qconfig.h\"\n",
+ buildPath + "/include/Qt/qconfig.h")) {
+ dictionary["DONE"] = "error";
+ return;
+ }
+ }
+ }
+
+ // Copy configured mkspec to default directory, but remove the old one first, if there is any
+ QString defSpec = buildPath + "/mkspecs/default";
+ QFileInfo defSpecInfo(defSpec);
+ if (defSpecInfo.exists()) {
+ if (!Environment::rmdir(defSpec)) {
+ cout << "Couldn't update default mkspec! Are files in " << qPrintable(defSpec) << " read-only?" << endl;
+ dictionary["DONE"] = "error";
+ return;
+ }
+ }
+
+ QString spec = dictionary.contains("XQMAKESPEC") ? dictionary["XQMAKESPEC"] : dictionary["QMAKESPEC"];
+ QString pltSpec = sourcePath + "/mkspecs/" + spec;
+ if (!Environment::cpdir(pltSpec, defSpec)) {
+ cout << "Couldn't update default mkspec! Does " << qPrintable(pltSpec) << " exist?" << endl;
+ dictionary["DONE"] = "error";
+ return;
+ }
+
+ outName = defSpec + "/qmake.conf";
+ ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL );
+ QFile qmakeConfFile(outName);
+ if (qmakeConfFile.open(QFile::Append | QFile::WriteOnly | QFile::Text)) {
+ QTextStream qmakeConfStream;
+ qmakeConfStream.setDevice(&qmakeConfFile);
+ qmakeConfStream << endl << "QMAKESPEC_ORIGINAL=" << pltSpec << endl;
+ qmakeConfStream.flush();
+ qmakeConfFile.close();
+ }
+
+ // Generate the new qconfig.cpp file
+ QDir(buildPath).mkpath("src/corelib/global");
+ outName = buildPath + "/src/corelib/global/qconfig.cpp";
+
+ QTemporaryFile tmpFile2;
+ if (tmpFile2.open()) {
+ tmpStream.setDevice(&tmpFile2);
+ tmpStream << "/* Licensed */" << endl
+ << "static const char qt_configure_licensee_str [512 + 12] = \"qt_lcnsuser=" << licenseInfo["LICENSEE"] << "\";" << endl
+ << "static const char qt_configure_licensed_products_str [512 + 12] = \"qt_lcnsprod=" << dictionary["EDITION"] << "\";" << endl;
+ if(!dictionary[ "QT_HOST_PREFIX" ].isNull())
+ tmpStream << "#if !defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE)" << endl;
+ tmpStream << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << QString(dictionary["QT_INSTALL_PREFIX"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_documentation_path_str[512 + 12] = \"qt_docspath=" << QString(dictionary["QT_INSTALL_DOCS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_headers_path_str [512 + 12] = \"qt_hdrspath=" << QString(dictionary["QT_INSTALL_HEADERS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_libraries_path_str [512 + 12] = \"qt_libspath=" << QString(dictionary["QT_INSTALL_LIBS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_binaries_path_str [512 + 12] = \"qt_binspath=" << QString(dictionary["QT_INSTALL_BINS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_plugins_path_str [512 + 12] = \"qt_plugpath=" << QString(dictionary["QT_INSTALL_PLUGINS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_data_path_str [512 + 12] = \"qt_datapath=" << QString(dictionary["QT_INSTALL_DATA"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_translations_path_str [512 + 12] = \"qt_trnspath=" << QString(dictionary["QT_INSTALL_TRANSLATIONS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_examples_path_str [512 + 12] = \"qt_xmplpath=" << QString(dictionary["QT_INSTALL_EXAMPLES"]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_demos_path_str [512 + 12] = \"qt_demopath=" << QString(dictionary["QT_INSTALL_DEMOS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ //<< "static const char qt_configure_settings_path_str [256] = \"qt_stngpath=" << QString(dictionary["QT_INSTALL_SETTINGS"]).replace( "\\", "\\\\" ) << "\";" << endl
+ ;
+ if(!dictionary[ "QT_HOST_PREFIX" ].isNull()) {
+ tmpStream << "#else" << endl
+ << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << QString(dictionary[ "QT_HOST_PREFIX" ]).replace( "\\", "\\\\" ) << "\";" << endl
+ << "static const char qt_configure_documentation_path_str[512 + 12] = \"qt_docspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/doc").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_headers_path_str [512 + 12] = \"qt_hdrspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/include").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_libraries_path_str [512 + 12] = \"qt_libspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/lib").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_binaries_path_str [512 + 12] = \"qt_binspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/bin").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_plugins_path_str [512 + 12] = \"qt_plugpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/plugins").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_data_path_str [512 + 12] = \"qt_datapath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ]).replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_translations_path_str [512 + 12] = \"qt_trnspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/translations").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_examples_path_str [512 + 12] = \"qt_xmplpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/example").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "static const char qt_configure_demos_path_str [512 + 12] = \"qt_demopath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/demos").replace( "\\", "\\\\" ) <<"\";" << endl
+ << "#endif //QT_BOOTSTRAPPED" << endl;
+ }
+ tmpStream << "/* strlen( \"qt_lcnsxxxx\" ) == 12 */" << endl
+ << "#define QT_CONFIGURE_LICENSEE qt_configure_licensee_str + 12;" << endl
+ << "#define QT_CONFIGURE_LICENSED_PRODUCTS qt_configure_licensed_products_str + 12;" << endl
+ << "#define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_DOCUMENTATION_PATH qt_configure_documentation_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_HEADERS_PATH qt_configure_headers_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_LIBRARIES_PATH qt_configure_libraries_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_BINARIES_PATH qt_configure_binaries_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_PLUGINS_PATH qt_configure_plugins_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_DATA_PATH qt_configure_data_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_TRANSLATIONS_PATH qt_configure_translations_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_EXAMPLES_PATH qt_configure_examples_path_str + 12;" << endl
+ << "#define QT_CONFIGURE_DEMOS_PATH qt_configure_demos_path_str + 12;" << endl
+ //<< "#define QT_CONFIGURE_SETTINGS_PATH qt_configure_settings_path_str + 12;" << endl
+ << endl;
+
+ tmpStream.flush();
+ tmpFile2.flush();
+
+ // Replace old qconfig.cpp with new one
+ ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL );
+ QFile::remove( outName );
+ tmpFile2.copy(outName);
+ tmpFile2.close();
+ }
+}
+#endif
+
+#if !defined(EVAL)
+void Configure::displayConfig()
+{
+ // Give some feedback
+ cout << "Environment:" << endl;
+ QString env = QString::fromLocal8Bit(getenv("INCLUDE")).replace(QRegExp("[;,]"), "\r\n ");
+ if (env.isEmpty())
+ env = "Unset";
+ cout << " INCLUDE=\r\n " << env << endl;
+ env = QString::fromLocal8Bit(getenv("LIB")).replace(QRegExp("[;,]"), "\r\n ");
+ if (env.isEmpty())
+ env = "Unset";
+ cout << " LIB=\r\n " << env << endl;
+ env = QString::fromLocal8Bit(getenv("PATH")).replace(QRegExp("[;,]"), "\r\n ");
+ if (env.isEmpty())
+ env = "Unset";
+ cout << " PATH=\r\n " << env << endl;
+
+ if (dictionary["EDITION"] == "OpenSource") {
+ cout << "You are licensed to use this software under the terms of the GNU GPL version 3.";
+ cout << "You are licensed to use this software under the terms of the Lesser GNU LGPL version 2.1." << endl;
+ cout << "See " << dictionary["LICENSE FILE"] << "3" << endl << endl
+ << " or " << dictionary["LICENSE FILE"] << "L" << endl << endl;
+ } else {
+ QString l1 = licenseInfo[ "LICENSEE" ];
+ QString l2 = licenseInfo[ "LICENSEID" ];
+ QString l3 = dictionary["EDITION"] + ' ' + "Edition";
+ QString l4 = licenseInfo[ "EXPIRYDATE" ];
+ cout << "Licensee...................." << (l1.isNull() ? "" : l1) << endl;
+ cout << "License ID.................." << (l2.isNull() ? "" : l2) << endl;
+ cout << "Product license............." << (l3.isNull() ? "" : l3) << endl;
+ cout << "Expiry Date................." << (l4.isNull() ? "" : l4) << endl << endl;
+ }
+
+ cout << "Configuration:" << endl;
+ cout << " " << qmakeConfig.join( "\r\n " ) << endl;
+ cout << "Qt Configuration:" << endl;
+ cout << " " << qtConfig.join( "\r\n " ) << endl;
+ cout << endl;
+
+ if (dictionary.contains("XQMAKESPEC"))
+ cout << "QMAKESPEC..................." << dictionary[ "XQMAKESPEC" ] << " (" << dictionary["QMAKESPEC_FROM"] << ")" << endl;
+ else
+ cout << "QMAKESPEC..................." << dictionary[ "QMAKESPEC" ] << " (" << dictionary["QMAKESPEC_FROM"] << ")" << endl;
+ cout << "Architecture................" << dictionary[ "ARCHITECTURE" ] << endl;
+ cout << "Maketool...................." << dictionary[ "MAKE" ] << endl;
+ cout << "Debug symbols..............." << (dictionary[ "BUILD" ] == "debug" ? "yes" : "no") << endl;
+ cout << "Accessibility support......." << dictionary[ "ACCESSIBILITY" ] << endl;
+ cout << "STL support................." << dictionary[ "STL" ] << endl;
+ cout << "Exception support..........." << dictionary[ "EXCEPTIONS" ] << endl;
+ cout << "RTTI support................" << dictionary[ "RTTI" ] << endl;
+ cout << "MMX support................." << dictionary[ "MMX" ] << endl;
+ cout << "3DNOW support..............." << dictionary[ "3DNOW" ] << endl;
+ cout << "SSE support................." << dictionary[ "SSE" ] << endl;
+ cout << "SSE2 support................" << dictionary[ "SSE2" ] << endl;
+ cout << "IWMMXT support.............." << dictionary[ "IWMMXT" ] << endl;
+ cout << "OpenGL support.............." << dictionary[ "OPENGL" ] << endl;
+ cout << "Direct3D support............" << dictionary[ "DIRECT3D" ] << endl;
+ cout << "OpenSSL support............." << dictionary[ "OPENSSL" ] << endl;
+ cout << "QtDBus support.............." << dictionary[ "DBUS" ] << endl;
+ cout << "QtXmlPatterns support......." << dictionary[ "XMLPATTERNS" ] << endl;
+ cout << "Phonon support.............." << dictionary[ "PHONON" ] << endl;
+ cout << "WebKit support.............." << dictionary[ "WEBKIT" ] << endl;
+ cout << "QtScriptTools support......." << dictionary[ "SCRIPTTOOLS" ] << endl;
+ cout << "Graphics System............." << dictionary[ "GRAPHICS_SYSTEM" ] << endl;
+ cout << "Qt3 compatibility..........." << dictionary[ "QT3SUPPORT" ] << endl << endl;
+
+ cout << "Third Party Libraries:" << endl;
+ cout << " ZLIB support............" << dictionary[ "ZLIB" ] << endl;
+ cout << " GIF support............." << dictionary[ "GIF" ] << endl;
+ cout << " TIFF support............" << dictionary[ "TIFF" ] << endl;
+ cout << " JPEG support............" << dictionary[ "JPEG" ] << endl;
+ cout << " PNG support............." << dictionary[ "PNG" ] << endl;
+ cout << " MNG support............." << dictionary[ "MNG" ] << endl << endl;
+
+ cout << "Styles:" << endl;
+ cout << " Windows................." << dictionary[ "STYLE_WINDOWS" ] << endl;
+ cout << " Windows XP.............." << dictionary[ "STYLE_WINDOWSXP" ] << endl;
+ cout << " Windows Vista..........." << dictionary[ "STYLE_WINDOWSVISTA" ] << endl;
+ cout << " Plastique..............." << dictionary[ "STYLE_PLASTIQUE" ] << endl;
+ cout << " Cleanlooks.............." << dictionary[ "STYLE_CLEANLOOKS" ] << endl;
+ cout << " Motif..................." << dictionary[ "STYLE_MOTIF" ] << endl;
+ cout << " CDE....................." << dictionary[ "STYLE_CDE" ] << endl;
+ cout << " Windows CE.............." << dictionary[ "STYLE_WINDOWSCE" ] << endl;
+ cout << " Windows Mobile.........." << dictionary[ "STYLE_WINDOWSMOBILE" ] << endl << endl;
+
+ cout << "Sql Drivers:" << endl;
+ cout << " ODBC...................." << dictionary[ "SQL_ODBC" ] << endl;
+ cout << " MySQL..................." << dictionary[ "SQL_MYSQL" ] << endl;
+ cout << " OCI....................." << dictionary[ "SQL_OCI" ] << endl;
+ cout << " PostgreSQL.............." << dictionary[ "SQL_PSQL" ] << endl;
+ cout << " TDS....................." << dictionary[ "SQL_TDS" ] << endl;
+ cout << " DB2....................." << dictionary[ "SQL_DB2" ] << endl;
+ cout << " SQLite.................." << dictionary[ "SQL_SQLITE" ] << " (" << dictionary[ "SQL_SQLITE_LIB" ] << ")" << endl;
+ cout << " SQLite2................." << dictionary[ "SQL_SQLITE2" ] << endl;
+ cout << " InterBase..............." << dictionary[ "SQL_IBASE" ] << endl << endl;
+
+ cout << "Sources are in.............." << dictionary[ "QT_SOURCE_TREE" ] << endl;
+ cout << "Build is done in............" << dictionary[ "QT_BUILD_TREE" ] << endl;
+ cout << "Install prefix.............." << dictionary[ "QT_INSTALL_PREFIX" ] << endl;
+ cout << "Headers installed to........" << dictionary[ "QT_INSTALL_HEADERS" ] << endl;
+ cout << "Libraries installed to......" << dictionary[ "QT_INSTALL_LIBS" ] << endl;
+ cout << "Plugins installed to........" << dictionary[ "QT_INSTALL_PLUGINS" ] << endl;
+ cout << "Binaries installed to......." << dictionary[ "QT_INSTALL_BINS" ] << endl;
+ cout << "Docs installed to..........." << dictionary[ "QT_INSTALL_DOCS" ] << endl;
+ cout << "Data installed to..........." << dictionary[ "QT_INSTALL_DATA" ] << endl;
+ cout << "Translations installed to..." << dictionary[ "QT_INSTALL_TRANSLATIONS" ] << endl;
+ cout << "Examples installed to......." << dictionary[ "QT_INSTALL_EXAMPLES" ] << endl;
+ cout << "Demos installed to.........." << dictionary[ "QT_INSTALL_DEMOS" ] << endl << endl;
+
+ if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith(QLatin1String("wince"))) {
+ cout << "Using c runtime detection..." << dictionary[ "CE_CRT" ] << endl;
+ cout << "Cetest support.............." << dictionary[ "CETEST" ] << endl;
+ cout << "Signature..................." << dictionary[ "CE_SIGNATURE"] << endl << endl;
+ }
+
+ if(dictionary["ASSISTANT_WEBKIT"] == "yes")
+ cout << "Using WebKit as html rendering engine in Qt Assistant." << endl;
+
+ if(checkAvailability("INCREDIBUILD_XGE"))
+ cout << "Using IncrediBuild XGE......" << dictionary["INCREDIBUILD_XGE"] << endl;
+ if( !qmakeDefines.isEmpty() ) {
+ cout << "Defines.....................";
+ for( QStringList::Iterator defs = qmakeDefines.begin(); defs != qmakeDefines.end(); ++defs )
+ cout << (*defs) << " ";
+ cout << endl;
+ }
+ if( !qmakeIncludes.isEmpty() ) {
+ cout << "Include paths...............";
+ for( QStringList::Iterator incs = qmakeIncludes.begin(); incs != qmakeIncludes.end(); ++incs )
+ cout << (*incs) << " ";
+ cout << endl;
+ }
+ if( !qmakeLibs.isEmpty() ) {
+ cout << "Additional libraries........";
+ for( QStringList::Iterator libs = qmakeLibs.begin(); libs != qmakeLibs.end(); ++libs )
+ cout << (*libs) << " ";
+ cout << endl;
+ }
+ if( dictionary[ "QMAKE_INTERNAL" ] == "yes" ) {
+ cout << "Using internal configuration." << endl;
+ }
+ if( dictionary[ "SHARED" ] == "no" ) {
+ cout << "WARNING: Using static linking will disable the use of plugins." << endl;
+ cout << " Make sure you compile ALL needed modules into the library." << endl;
+ }
+ if( dictionary[ "OPENSSL" ] == "linked" && opensslLibs.isEmpty() ) {
+ cout << "NOTE: When linking against OpenSSL, you can override the default" << endl;
+ cout << "library names through OPENSSL_LIBS." << endl;
+ cout << "For example:" << endl;
+ cout << " configure -openssl-linked OPENSSL_LIBS='-lssleay32 -llibeay32'" << endl;
+ }
+ if( dictionary[ "ZLIB_FORCED" ] == "yes" ) {
+ QString which_zlib = "supplied";
+ if( dictionary[ "ZLIB" ] == "system")
+ which_zlib = "system";
+
+ cout << "NOTE: The -no-zlib option was supplied but is no longer supported." << endl
+ << endl
+ << "Qt now requires zlib support in all builds, so the -no-zlib" << endl
+ << "option was ignored. Qt will be built using the " << which_zlib
+ << "zlib" << endl;
+ }
+}
+#endif
+
+#if !defined(EVAL)
+void Configure::generateHeaders()
+{
+ if (dictionary["SYNCQT"] == "yes"
+ && findFile("perl.exe")) {
+ cout << "Running syncqt..." << endl;
+ QStringList args;
+ args += buildPath + "/bin/syncqt.bat";
+ QStringList env;
+ env += QString("QTDIR=" + sourcePath);
+ env += QString("PATH=" + buildPath + "/bin/;" + qgetenv("PATH"));
+ Environment::execute(args, env, QStringList());
+ }
+}
+
+void Configure::buildQmake()
+{
+ if( dictionary[ "BUILD_QMAKE" ] == "yes" ) {
+ QStringList args;
+
+ // Build qmake
+ QString pwd = QDir::currentPath();
+ QDir::setCurrent(buildPath + "/qmake" );
+
+ QString makefile = "Makefile";
+ {
+ QFile out(makefile);
+ if(out.open(QFile::WriteOnly | QFile::Text)) {
+ QTextStream stream(&out);
+ stream << "#AutoGenerated by configure.exe" << endl
+ << "BUILD_PATH = " << QDir::convertSeparators(buildPath) << endl
+ << "SOURCE_PATH = " << QDir::convertSeparators(sourcePath) << endl;
+ stream << "QMAKESPEC = " << dictionary["QMAKESPEC"] << endl;
+
+ if (dictionary["EDITION"] == "OpenSource" ||
+ dictionary["QT_EDITION"].contains("OPENSOURCE"))
+ stream << "QMAKE_OPENSOURCE_EDITION = yes" << endl;
+ stream << "\n\n";
+
+ QFile in(sourcePath + "/qmake/" + dictionary["QMAKEMAKEFILE"]);
+ if(in.open(QFile::ReadOnly | QFile::Text)) {
+ QString d = in.readAll();
+ //### need replaces (like configure.sh)? --Sam
+ stream << d << endl;
+ }
+ stream.flush();
+ out.close();
+ }
+ }
+
+ args += dictionary[ "MAKE" ];
+ args += "-f";
+ args += makefile;
+
+ cout << "Creating qmake..." << endl;
+ int exitCode = 0;
+ if( exitCode = Environment::execute(args, QStringList(), QStringList()) ) {
+ args.clear();
+ args += dictionary[ "MAKE" ];
+ args += "-f";
+ args += makefile;
+ args += "clean";
+ if( exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ cout << "Cleaning qmake failed, return code " << exitCode << endl << endl;
+ dictionary[ "DONE" ] = "error";
+ } else {
+ args.clear();
+ args += dictionary[ "MAKE" ];
+ args += "-f";
+ args += makefile;
+ if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ cout << "Building qmake failed, return code " << exitCode << endl << endl;
+ dictionary[ "DONE" ] = "error";
+ }
+ }
+ }
+ QDir::setCurrent( pwd );
+ }
+}
+#endif
+
+void Configure::buildHostTools()
+{
+ if (!dictionary.contains("XQMAKESPEC"))
+ return;
+
+ QString pwd = QDir::currentPath();
+ QStringList hostToolsDirs;
+ hostToolsDirs
+ << "src/tools/bootstrap"
+ << "src/tools/moc"
+ << "src/tools/rcc"
+ << "src/tools/uic"
+ << "tools/checksdk";
+
+ if (dictionary[ "CETEST" ] == "yes")
+ hostToolsDirs << "tools/qtestlib/wince/cetest";
+
+ for (int i = 0; i < hostToolsDirs.count(); ++i) {
+ cout << "Creating " << hostToolsDirs.at(i) << " ..." << endl;
+ QString toolBuildPath = buildPath + "/" + hostToolsDirs.at(i);
+ QString toolSourcePath = sourcePath + "/" + hostToolsDirs.at(i);
+
+ // generate Makefile
+ QStringList args;
+ args << QDir::toNativeSeparators(buildPath + "/bin/qmake");
+ args << "-spec" << dictionary["QMAKESPEC"] << "-r";
+ args << "-o" << QDir::toNativeSeparators(toolBuildPath + "/Makefile");
+
+ QDir().mkpath(toolBuildPath);
+ QDir::setCurrent(toolSourcePath);
+ int exitCode = 0;
+ if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ cout << "qmake failed, return code " << exitCode << endl << endl;
+ dictionary["DONE"] = "error";
+ break;
+ }
+
+ // build app
+ args.clear();
+ args += dictionary["MAKE"];
+ QDir::setCurrent(toolBuildPath);
+ if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ args.clear();
+ args += dictionary["MAKE"];
+ args += "clean";
+ if(exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ cout << "Cleaning " << hostToolsDirs.at(i) << " failed, return code " << exitCode << endl << endl;
+ dictionary["DONE"] = "error";
+ break;
+ } else {
+ args.clear();
+ args += dictionary["MAKE"];
+ if (exitCode = Environment::execute(args, QStringList(), QStringList())) {
+ cout << "Building " << hostToolsDirs.at(i) << " failed, return code " << exitCode << endl << endl;
+ dictionary["DONE"] = "error";
+ break;
+ }
+ }
+ }
+ }
+ QDir::setCurrent(pwd);
+}
+
+void Configure::findProjects( const QString& dirName )
+{
+ if( dictionary[ "NOPROCESS" ] == "no" ) {
+ QDir dir( dirName );
+ QString entryName;
+ int makeListNumber;
+ ProjectType qmakeTemplate;
+ const QFileInfoList &list = dir.entryInfoList(QStringList(QLatin1String("*.pro")),
+ QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
+ for(int i = 0; i < list.size(); ++i) {
+ const QFileInfo &fi = list.at(i);
+ if(fi.fileName() != "qmake.pro") {
+ entryName = dirName + "/" + fi.fileName();
+ if(fi.isDir()) {
+ findProjects( entryName );
+ } else {
+ qmakeTemplate = projectType( fi.absoluteFilePath() );
+ switch ( qmakeTemplate ) {
+ case Lib:
+ case Subdirs:
+ makeListNumber = 1;
+ break;
+ default:
+ makeListNumber = 2;
+ break;
+ }
+ makeList[makeListNumber].append(new MakeItem(sourceDir.relativeFilePath(fi.absolutePath()),
+ fi.fileName(),
+ "Makefile",
+ qmakeTemplate));
+ }
+ }
+
+ }
+ }
+}
+
+void Configure::appendMakeItem(int inList, const QString &item)
+{
+ QString dir;
+ if (item != "src")
+ dir = "/" + item;
+ dir.prepend("/src");
+ makeList[inList].append(new MakeItem(sourcePath + dir,
+ item + ".pro", buildPath + dir + "/Makefile", Lib ) );
+ if( dictionary[ "DSPFILES" ] == "yes" ) {
+ makeList[inList].append( new MakeItem(sourcePath + dir,
+ item + ".pro", buildPath + dir + "/" + item + ".dsp", Lib ) );
+ }
+ if( dictionary[ "VCPFILES" ] == "yes" ) {
+ makeList[inList].append( new MakeItem(sourcePath + dir,
+ item + ".pro", buildPath + dir + "/" + item + ".vcp", Lib ) );
+ }
+ if( dictionary[ "VCPROJFILES" ] == "yes" ) {
+ makeList[inList].append( new MakeItem(sourcePath + dir,
+ item + ".pro", buildPath + dir + "/" + item + ".vcproj", Lib ) );
+ }
+}
+
+void Configure::generateMakefiles()
+{
+ if( dictionary[ "NOPROCESS" ] == "no" ) {
+#if !defined(EVAL)
+ cout << "Creating makefiles in src..." << endl;
+#endif
+
+ QString spec = dictionary.contains("XQMAKESPEC") ? dictionary[ "XQMAKESPEC" ] : dictionary[ "QMAKESPEC" ];
+ if( spec != "win32-msvc" )
+ dictionary[ "DSPFILES" ] = "no";
+
+ if( spec != "win32-msvc.net" && !spec.startsWith("win32-msvc2") && !spec.startsWith(QLatin1String("wince")))
+ dictionary[ "VCPROJFILES" ] = "no";
+
+ int i = 0;
+ QString pwd = QDir::currentPath();
+ if (dictionary["FAST"] != "yes") {
+ QString dirName;
+ bool generate = true;
+ bool doDsp = (dictionary["DSPFILES"] == "yes" || dictionary["VCPFILES"] == "yes"
+ || dictionary["VCPROJFILES"] == "yes");
+ while (generate) {
+ QString pwd = QDir::currentPath();
+ QString dirPath = fixSeparators(buildPath + dirName);
+ QStringList args;
+
+ args << fixSeparators( buildPath + "/bin/qmake" );
+
+ if (doDsp) {
+ if( dictionary[ "DEPENDENCIES" ] == "no" )
+ args << "-nodepend";
+ args << "-tp" << "vc";
+ doDsp = false; // DSP files will be done
+ printf("Generating Visual Studio project files...\n");
+ } else {
+ printf("Generating Makefiles...\n");
+ generate = false; // Now Makefiles will be done
+ }
+ args << "-spec";
+ args << spec;
+ args << "-r";
+ args << (sourcePath + "/projects.pro");
+ args << "-o";
+ args << buildPath;
+ if(!dictionary[ "QMAKEADDITIONALARGS" ].isEmpty())
+ args << dictionary[ "QMAKEADDITIONALARGS" ];
+
+ QDir::setCurrent( fixSeparators( dirPath ) );
+ if( int exitCode = Environment::execute(args, QStringList(), QStringList()) ) {
+ cout << "Qmake failed, return code " << exitCode << endl << endl;
+ dictionary[ "DONE" ] = "error";
+ }
+ }
+ } else {
+ findProjects(sourcePath);
+ for ( i=0; i<3; i++ ) {
+ for ( int j=0; j<makeList[i].size(); ++j) {
+ MakeItem *it=makeList[i][j];
+ QString dirPath = fixSeparators( it->directory + "/" );
+ QString projectName = it->proFile;
+ QString makefileName = buildPath + "/" + dirPath + it->target;
+
+ // For shadowbuilds, we need to create the path first
+ QDir buildPathDir(buildPath);
+ if (sourcePath != buildPath && !buildPathDir.exists(dirPath))
+ buildPathDir.mkpath(dirPath);
+
+ QStringList args;
+
+ args << fixSeparators( buildPath + "/bin/qmake" );
+ args << sourcePath + "/" + dirPath + projectName;
+ args << dictionary[ "QMAKE_ALL_ARGS" ];
+
+ cout << "For " << qPrintable(dirPath + projectName) << endl;
+ args << "-o";
+ args << it->target;
+ args << "-spec";
+ args << spec;
+ if(!dictionary[ "QMAKEADDITIONALARGS" ].isEmpty())
+ args << dictionary[ "QMAKEADDITIONALARGS" ];
+
+ QDir::setCurrent( fixSeparators( dirPath ) );
+
+ QFile file(makefileName);
+ if (!file.open(QFile::WriteOnly)) {
+ printf("failed on dirPath=%s, makefile=%s\n",
+ qPrintable(dirPath), qPrintable(makefileName));
+ continue;
+ }
+ QTextStream txt(&file);
+ txt << "all:\n";
+ txt << "\t" << args.join(" ") << "\n";
+ txt << "\t" << dictionary[ "MAKE" ] << " -f " << it->target << "\n";
+ txt << "first: all\n";
+ txt << "qmake:\n";
+ txt << "\t" << args.join(" ") << "\n";
+ }
+ }
+ }
+ QDir::setCurrent( pwd );
+ } else {
+ cout << "Processing of project files have been disabled." << endl;
+ cout << "Only use this option if you really know what you're doing." << endl << endl;
+ dictionary[ "DONE" ] = "yes";
+ return;
+ }
+}
+
+void Configure::showSummary()
+{
+ QString make = dictionary[ "MAKE" ];
+ cout << endl << endl << "Qt is now configured for building. Just run " << qPrintable(make) << "." << endl;
+ cout << "To reconfigure, run " << qPrintable(make) << " confclean and configure." << endl << endl;
+}
+
+Configure::ProjectType Configure::projectType( const QString& proFileName )
+{
+ QFile proFile( proFileName );
+ if( proFile.open( QFile::ReadOnly ) ) {
+ QString buffer = proFile.readLine(1024);
+ while (!buffer.isEmpty()) {
+ QStringList segments = buffer.split(QRegExp( "\\s" ));
+ QStringList::Iterator it = segments.begin();
+
+ if(segments.size() >= 3) {
+ QString keyword = (*it++);
+ QString operation = (*it++);
+ QString value = (*it++);
+
+ if( keyword == "TEMPLATE" ) {
+ if( value == "lib" )
+ return Lib;
+ else if( value == "subdirs" )
+ return Subdirs;
+ }
+ }
+ // read next line
+ buffer = proFile.readLine(1024);
+ }
+ proFile.close();
+ }
+ // Default to app handling
+ return App;
+}
+
+#if !defined(EVAL)
+
+bool Configure::showLicense(QString orgLicenseFile)
+{
+ if (dictionary["LICENSE_CONFIRMED"] == "yes") {
+ cout << "You have already accepted the terms of the license." << endl << endl;
+ return true;
+ }
+
+ QString licenseFile = orgLicenseFile;
+ QString theLicense;
+ if (dictionary["EDITION"] == "OpenSource" || dictionary["EDITION"] == "Snapshot") {
+ theLicense = "GNU General Public License (GPL) version 3 \nor the GNU Lesser General Public License (LGPL) version 2.1";
+ } else {
+ // the first line of the license file tells us which license it is
+ QFile file(licenseFile);
+ if (!file.open(QFile::ReadOnly)) {
+ cout << "Failed to load LICENSE file" << endl;
+ return false;
+ }
+ theLicense = file.readLine().trimmed();
+ }
+
+ forever {
+ char accept = '?';
+ cout << "You are licensed to use this software under the terms of" << endl
+ << "the " << theLicense << "." << endl
+ << endl;
+ if (dictionary["EDITION"] == "OpenSource" || dictionary["EDITION"] == "Snapshot") {
+ cout << "Type '3' to view the GNU General Public License version 3 (GPLv3)." << endl;
+ cout << "Type 'L' to view the Lesser GNU General Public License version 2.1 (LGPLv2.1)." << endl;
+ } else {
+ cout << "Type '?' to view the " << theLicense << "." << endl;
+ }
+ cout << "Type 'y' to accept this license offer." << endl
+ << "Type 'n' to decline this license offer." << endl
+ << endl
+ << "Do you accept the terms of the license?" << endl;
+ cin >> accept;
+ accept = tolower(accept);
+
+ if (accept == 'y') {
+ return true;
+ } else if (accept == 'n') {
+ return false;
+ } else {
+ if (dictionary["EDITION"] == "OpenSource" || dictionary["EDITION"] == "Snapshot") {
+ if (accept == '3')
+ licenseFile = orgLicenseFile + "/LICENSE.GPL3";
+ else
+ licenseFile = orgLicenseFile + "/LICENSE.LGPL";
+ }
+ // Get console line height, to fill the screen properly
+ int i = 0, screenHeight = 25; // default
+ CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
+ HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (GetConsoleScreenBufferInfo(stdOut, &consoleInfo))
+ screenHeight = consoleInfo.srWindow.Bottom
+ - consoleInfo.srWindow.Top
+ - 1; // Some overlap for context
+
+ // Prompt the license content to the user
+ QFile file(licenseFile);
+ if (!file.open(QFile::ReadOnly)) {
+ cout << "Failed to load LICENSE file" << licenseFile << endl;
+ return false;
+ }
+ QStringList licenseContent = QString(file.readAll()).split('\n');
+ while(i < licenseContent.size()) {
+ cout << licenseContent.at(i) << endl;
+ if (++i % screenHeight == 0) {
+ cout << "(Press any key for more..)";
+ if(_getch() == 3) // _Any_ keypress w/no echo(eat <Enter> for stdout)
+ exit(0); // Exit cleanly for Ctrl+C
+ cout << "\r"; // Overwrite text above
+ }
+ }
+ }
+ }
+}
+
+void Configure::readLicense()
+{
+ dictionary[ "PLATFORM NAME" ] = (QFile::exists(dictionary["QT_SOURCE_TREE"] + "/src/corelib/kernel/qfunctions_wince.h")
+ && (dictionary.value("QMAKESPEC").startsWith("wince") || dictionary.value("XQMAKESPEC").startsWith("wince")))
+ ? "Qt for Windows CE" : "Qt for Windows";
+ bool openSource = false;
+ if (dictionary["BUILDNOKIA"] == "yes" || dictionary["BUILDTYPE"] == "commercial") {
+ openSource = false;
+ } else if (dictionary["BUILDTYPE"] == "opensource") {
+ openSource = true;
+ } else {
+ forever {
+ char accept = '?';
+ cout << "Which edition of Qt do you want to use ?" << endl;
+ cout << "Type 'c' if you want to use the Commercial Edition." << endl;
+ cout << "Type 'o' if you want to use the Open Source Edition." << endl;
+ cin >> accept;
+ accept = tolower(accept);
+
+ if (accept == 'c') {
+ openSource = false;
+ break;
+ } else if (accept == 'o') {
+ openSource = true;
+ break;
+ }
+ }
+ }
+ if (openSource) {
+ dictionary["LICENSE FILE"] = sourcePath;
+ if (QFile::exists(dictionary["LICENSE FILE"] + "/LICENSE.GPL3") || QFile::exists(dictionary["LICENSE FILE"] + "/LICENSE.LGPL")) {
+ cout << endl << "This is the " << dictionary["PLATFORM NAME"] << " Open Source Edition." << endl;
+ licenseInfo["LICENSEE"] = "Open Source";
+ dictionary["EDITION"] = "OpenSource";
+ dictionary["QT_EDITION"] = "QT_EDITION_OPENSOURCE";
+ cout << endl;
+ if (!showLicense(dictionary["LICENSE FILE"])) {
+ cout << "Configuration aborted since license was not accepted";
+ dictionary["DONE"] = "error";
+ return;
+ }
+ return;
+ }
+#ifndef COMMERCIAL_VERSION
+ else {
+ cout << endl << "Cannot find the GPL license files!" << endl;
+ dictionary["DONE"] = "error";
+ }
+#else
+ } else {
+ Tools::checkLicense(dictionary, licenseInfo, firstLicensePath());
+ if (dictionary["DONE"] != "error") {
+ // give the user some feedback, and prompt for license acceptance
+ cout << endl << "This is the " << dictionary["PLATFORM NAME"] << " " << dictionary["EDITION"] << " Edition."<< endl << endl;
+ if (!showLicense(dictionary["LICENSE FILE"])) {
+ cout << "Configuration aborted since license was not accepted";
+ dictionary["DONE"] = "error";
+ return;
+ }
+ }
+ }
+#endif // COMMERCIAL_VERSION
+}
+
+void Configure::reloadCmdLine()
+{
+ if( dictionary[ "REDO" ] == "yes" ) {
+ QFile inFile( buildPath + "/configure" + dictionary[ "CUSTOMCONFIG" ] + ".cache" );
+ if( inFile.open( QFile::ReadOnly ) ) {
+ QTextStream inStream( &inFile );
+ QString buffer;
+ inStream >> buffer;
+ while( buffer.length() ) {
+ configCmdLine += buffer;
+ inStream >> buffer;
+ }
+ inFile.close();
+ }
+ }
+}
+
+void Configure::saveCmdLine()
+{
+ if( dictionary[ "REDO" ] != "yes" ) {
+ QFile outFile( buildPath + "/configure" + dictionary[ "CUSTOMCONFIG" ] + ".cache" );
+ if( outFile.open( QFile::WriteOnly | QFile::Text ) ) {
+ QTextStream outStream( &outFile );
+ for( QStringList::Iterator it = configCmdLine.begin(); it != configCmdLine.end(); ++it ) {
+ outStream << (*it) << " " << endl;
+ }
+ outStream.flush();
+ outFile.close();
+ }
+ }
+}
+#endif // !EVAL
+
+bool Configure::isDone()
+{
+ return !dictionary["DONE"].isEmpty();
+}
+
+bool Configure::isOk()
+{
+ return (dictionary[ "DONE" ] != "error");
+}
+
+bool
+Configure::filesDiffer(const QString &fn1, const QString &fn2)
+{
+ QFile file1(fn1), file2(fn2);
+ if(!file1.open(QFile::ReadOnly) || !file2.open(QFile::ReadOnly))
+ return true;
+ const int chunk = 2048;
+ int used1 = 0, used2 = 0;
+ char b1[chunk], b2[chunk];
+ while(!file1.atEnd() && !file2.atEnd()) {
+ if(!used1)
+ used1 = file1.read(b1, chunk);
+ if(!used2)
+ used2 = file2.read(b2, chunk);
+ if(used1 > 0 && used2 > 0) {
+ const int cmp = qMin(used1, used2);
+ if(memcmp(b1, b2, cmp))
+ return true;
+ if((used1 -= cmp))
+ memcpy(b1, b1+cmp, used1);
+ if((used2 -= cmp))
+ memcpy(b2, b2+cmp, used2);
+ }
+ }
+ return !file1.atEnd() || !file2.atEnd();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h
new file mode 100644
index 0000000000..e09ac569c8
--- /dev/null
+++ b/tools/configure/configureapp.h
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmap.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qlist.h>
+#include <qtextstream.h>
+#include <qdir.h>
+
+QT_BEGIN_NAMESPACE
+
+class MakeItem;
+
+class Configure
+{
+public:
+ Configure( int& argc, char** argv );
+ ~Configure();
+
+ void parseCmdLine();
+#if !defined(EVAL)
+ void validateArgs();
+#endif
+ bool displayHelp();
+
+ QString defaultTo(const QString &option);
+ bool checkAvailability(const QString &part);
+ void autoDetection();
+ bool verifyConfiguration();
+
+ void generateOutputVars();
+#if !defined(EVAL)
+ void generateHeaders();
+ void generateBuildKey();
+ void generateCachefile();
+ void displayConfig();
+ void buildQmake();
+ void buildHostTools();
+#endif
+ void generateMakefiles();
+ void appendMakeItem(int inList, const QString &item);
+#if !defined(EVAL)
+ void generateConfigfiles();
+#endif
+ void showSummary();
+ void findProjects( const QString& dirName );
+ QString firstLicensePath();
+
+#if !defined(EVAL)
+ bool showLicense(QString licenseFile);
+ void readLicense();
+#endif
+
+ QString addDefine(QString def);
+
+ enum ProjectType {
+ App,
+ Lib,
+ Subdirs
+ };
+
+ ProjectType projectType( const QString& proFileName );
+ bool isDone();
+ bool isOk();
+private:
+ // Our variable dictionaries
+ QMap<QString,QString> dictionary;
+ QStringList licensedModules;
+ QStringList allSqlDrivers;
+ QStringList allConfigs;
+ QStringList disabledModules;
+ QStringList enabledModules;
+ QStringList modules;
+ QStringList disabledBuildParts;
+// QStringList sqlDrivers;
+ QStringList configCmdLine;
+ QStringList qmakeConfig;
+ QStringList qtConfig;
+
+ QStringList qmakeSql;
+ QStringList qmakeSqlPlugins;
+
+ QStringList qmakeStyles;
+ QStringList qmakeStylePlugins;
+
+ QStringList qmakeFormatPlugins;
+
+ QStringList qmakeVars;
+ QStringList qmakeDefines;
+ // makeList[0] for qt and qtmain
+ // makeList[1] for subdirs and libs
+ // makeList[2] for the rest
+ QList<MakeItem*> makeList[3];
+ QStringList qmakeIncludes;
+ QStringList qmakeLibs;
+ QString opensslLibs;
+
+ QMap<QString,QString> licenseInfo;
+ QString outputLine;
+
+ QTextStream outStream;
+ QString sourcePath, buildPath;
+ QDir sourceDir, buildDir;
+
+ // Variables for usage output
+ int optionIndent;
+ int descIndent;
+ int outputWidth;
+
+ bool useUnixSeparators;
+ QString fixSeparators(QString somePath);
+ bool filesDiffer(const QString &file1, const QString &file2);
+
+ static bool findFile(const QString &fileName);
+ static bool findFileInPaths(const QString &fileName, const QStringList &paths);
+#if !defined(EVAL)
+ void reloadCmdLine();
+ void saveCmdLine();
+#endif
+
+ void desc(const char *description, int startingAt = 0, int wrapIndent = 0);
+ void desc(const char *option, const char *description, bool skipIndent = false, char fillChar = '.');
+ void desc(const char *mark_option, const char *mark, const char *option, const char *description, char fillChar = '.');
+ void applySpecSpecifics();
+ static QString locateFile(const QString &fileName);
+ static QString locateFileInPaths(const QString &fileName, const QStringList &paths);
+};
+
+class MakeItem
+{
+public:
+ MakeItem( const QString &d, const QString &p, const QString &t, Configure::ProjectType qt )
+ : directory( d ),
+ proFile( p ),
+ target( t ),
+ qmakeTemplate( qt )
+ { }
+
+ QString directory;
+ QString proFile;
+ QString target;
+ Configure::ProjectType qmakeTemplate;
+};
+
+
+QT_END_NAMESPACE
diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp
new file mode 100644
index 0000000000..589b954c83
--- /dev/null
+++ b/tools/configure/environment.cpp
@@ -0,0 +1,686 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "environment.h"
+
+#include <process.h>
+#include <iostream>
+#include <qdebug.h>
+#include <QDir>
+#include <QStringList>
+#include <QMap>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+
+//#define CONFIGURE_DEBUG_EXECUTE
+//#define CONFIGURE_DEBUG_CP_DIR
+
+using namespace std;
+
+#ifdef Q_OS_WIN32
+#include <qt_windows.h>
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+struct CompilerInfo{
+ Compiler compiler;
+ const char *compilerStr;
+ const char *regKey;
+ const char *executable;
+} compiler_info[] = {
+ // The compilers here are sorted in a reversed-preferred order
+ {CC_BORLAND, "Borland C++", 0, "bcc32.exe"},
+ {CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "mingw32-gcc.exe"},
+ {CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe
+ {CC_MSVC6, "Microsoft (R) 32-bit C/C++ Optimizing Compiler (6.x)", "Software\\Microsoft\\VisualStudio\\6.0\\Setup\\Microsoft Visual C++\\ProductDir", "cl.exe"}, // link.exe, lib.exe
+ {CC_NET2002, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
+ {CC_NET2003, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
+ {CC_NET2005, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2005 (8.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe
+ {CC_NET2008, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2008 (9.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe
+ {CC_UNKNOWN, "Unknown", 0, 0},
+};
+
+
+// Initialize static variables
+Compiler Environment::detectedCompiler = CC_UNKNOWN;
+
+/*!
+ Returns the pointer to the CompilerInfo for a \a compiler.
+*/
+CompilerInfo *Environment::compilerInfo(Compiler compiler)
+{
+ int i = 0;
+ while(compiler_info[i].compiler != compiler && compiler_info[i].compiler != CC_UNKNOWN)
+ ++i;
+ return &(compiler_info[i]);
+}
+
+/*!
+ Returns the path part of a registry key.
+ Ei.
+ For a key
+ "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
+ it returns
+ "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\"
+*/
+QString Environment::keyPath(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ if (idx == -1)
+ return QString();
+ return rKey.left(idx + 1);
+}
+
+/*!
+ Returns the name part of a registry key.
+ Ei.
+ For a key
+ "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
+ it returns
+ "ProductDir"
+*/
+QString Environment::keyName(const QString &rKey)
+{
+ int idx = rKey.lastIndexOf(QLatin1Char('\\'));
+ if (idx == -1)
+ return rKey;
+
+ QString res(rKey.mid(idx + 1));
+ if (res == "Default" || res == ".")
+ res = "";
+ return res;
+}
+
+/*!
+ Returns a registry keys value in string form.
+ If the registry key does not exist, or cannot be accessed, a
+ QString() is returned.
+*/
+QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey)
+{
+#ifndef Q_OS_WIN32
+ return QString();
+#else
+ QString rSubkeyName = keyName(rSubkey);
+ QString rSubkeyPath = keyPath(rSubkey);
+
+ HKEY handle = 0;
+ LONG res;
+ QT_WA( {
+ res = RegOpenKeyExW(parentHandle, (WCHAR*)rSubkeyPath.utf16(),
+ 0, KEY_READ, &handle);
+ } , {
+ res = RegOpenKeyExA(parentHandle, rSubkeyPath.toLocal8Bit(),
+ 0, KEY_READ, &handle);
+ } );
+
+ if (res != ERROR_SUCCESS)
+ return QString();
+
+ // get the size and type of the value
+ DWORD dataType;
+ DWORD dataSize;
+ QT_WA( {
+ res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize);
+ }, {
+ res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize);
+ } );
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(handle);
+ return QString();
+ }
+
+ // get the value
+ QByteArray data(dataSize, 0);
+ QT_WA( {
+ res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, 0,
+ reinterpret_cast<unsigned char*>(data.data()), &dataSize);
+ }, {
+ res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0,
+ reinterpret_cast<unsigned char*>(data.data()), &dataSize);
+ } );
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(handle);
+ return QString();
+ }
+
+ QString result;
+ switch (dataType) {
+ case REG_EXPAND_SZ:
+ case REG_SZ: {
+ QT_WA( {
+ result = QString::fromUtf16(((const ushort*)data.constData()));
+ }, {
+ result = QString::fromLatin1(data.constData());
+ } );
+ break;
+ }
+
+ case REG_MULTI_SZ: {
+ QStringList l;
+ int i = 0;
+ for (;;) {
+ QString s;
+ QT_WA( {
+ s = QString::fromUtf16((const ushort*)data.constData() + i);
+ }, {
+ s = QString::fromLatin1(data.constData() + i);
+ } );
+ i += s.length() + 1;
+
+ if (s.isEmpty())
+ break;
+ l.append(s);
+ }
+ result = l.join(", ");
+ break;
+ }
+
+ case REG_NONE:
+ case REG_BINARY: {
+ QT_WA( {
+ result = QString::fromUtf16((const ushort*)data.constData(), data.size()/2);
+ }, {
+ result = QString::fromLatin1(data.constData(), data.size());
+ } );
+ break;
+ }
+
+ case REG_DWORD_BIG_ENDIAN:
+ case REG_DWORD: {
+ Q_ASSERT(data.size() == sizeof(int));
+ int i;
+ memcpy((char*)&i, data.constData(), sizeof(int));
+ result = QString::number(i);
+ break;
+ }
+
+ default:
+ qWarning("QSettings: unknown data %d type in windows registry", dataType);
+ break;
+ }
+
+ RegCloseKey(handle);
+ return result;
+#endif
+}
+
+/*!
+ Returns the qmakespec for the compiler detected on the system.
+*/
+QString Environment::detectQMakeSpec()
+{
+ QString spec;
+ switch (detectCompiler()) {
+ case CC_NET2008:
+ spec = "win32-msvc2008";
+ break;
+ case CC_NET2005:
+ spec = "win32-msvc2005";
+ break;
+ case CC_NET2003:
+ spec = "win32-msvc2003";
+ break;
+ case CC_NET2002:
+ spec = "win32-msvc2002";
+ break;
+ case CC_MSVC4:
+ case CC_MSVC5:
+ case CC_MSVC6:
+ spec = "win32-msvc";
+ break;
+ case CC_INTEL:
+ spec = "win32-icc";
+ break;
+ case CC_MINGW:
+ spec = "win32-g++";
+ break;
+ case CC_BORLAND:
+ spec = "win32-borland";
+ break;
+ default:
+ break;
+ }
+
+ return spec;
+}
+
+/*!
+ Returns the enum of the compiler which was detected on the system.
+ The compilers are detected in the order as entered into the
+ compiler_info list.
+
+ If more than one compiler is found, CC_UNKNOWN is returned.
+*/
+Compiler Environment::detectCompiler()
+{
+#ifndef Q_OS_WIN32
+ return MSVC6; // Always generate MSVC 6.0 versions on other platforms
+#else
+ if(detectedCompiler != CC_UNKNOWN)
+ return detectedCompiler;
+
+ int installed = 0;
+
+ // Check for compilers in registry first, to see which version is in PATH
+ QString paths = qgetenv("PATH");
+ QStringList pathlist = paths.toLower().split(";");
+ for(int i = 0; compiler_info[i].compiler; ++i) {
+ QString productPath = readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey).toLower();
+ if (productPath.length()) {
+ QStringList::iterator it;
+ for(it = pathlist.begin(); it != pathlist.end(); ++it) {
+ if((*it).contains(productPath)) {
+ ++installed;
+ detectedCompiler = compiler_info[i].compiler;
+ break;
+ }
+ }
+ }
+ }
+
+ // Now just go looking for the executables, and accept any executable as the lowest version
+ if (!installed) {
+ for(int i = 0; compiler_info[i].compiler; ++i) {
+ QString executable = QString(compiler_info[i].executable).toLower();
+ if (executable.length() && Environment::detectExecutable(executable)) {
+ ++installed;
+ detectedCompiler = compiler_info[i].compiler;
+ break;
+ }
+ }
+ }
+
+ if (installed > 1) {
+ cout << "Found more than one known compiler! Using \"" << compilerInfo(detectedCompiler)->compilerStr << "\"" << endl;
+ detectedCompiler = CC_UNKNOWN;
+ }
+ return detectedCompiler;
+#endif
+};
+
+/*!
+ Returns true if the \a executable could be loaded, else false.
+ This means that the executable either is in the current directory
+ or in the PATH.
+*/
+bool Environment::detectExecutable(const QString &executable)
+{
+ PROCESS_INFORMATION procInfo;
+ memset(&procInfo, 0, sizeof(procInfo));
+
+ bool couldExecute;
+ QT_WA({
+ // Unicode version
+ STARTUPINFOW startInfo;
+ memset(&startInfo, 0, sizeof(startInfo));
+ startInfo.cb = sizeof(startInfo);
+
+ couldExecute = CreateProcessW(0, (WCHAR*)executable.utf16(),
+ 0, 0, false,
+ CREATE_NO_WINDOW | CREATE_SUSPENDED,
+ 0, 0, &startInfo, &procInfo);
+
+ }, {
+ // Ansi version
+ STARTUPINFOA startInfo;
+ memset(&startInfo, 0, sizeof(startInfo));
+ startInfo.cb = sizeof(startInfo);
+
+ couldExecute = CreateProcessA(0, executable.toLocal8Bit().data(),
+ 0, 0, false,
+ CREATE_NO_WINDOW | CREATE_SUSPENDED,
+ 0, 0, &startInfo, &procInfo);
+ })
+
+ if (couldExecute) {
+ CloseHandle(procInfo.hThread);
+ TerminateProcess(procInfo.hProcess, 0);
+ CloseHandle(procInfo.hProcess);
+ }
+ return couldExecute;
+}
+
+/*!
+ Creates a commandling from \a program and it \a arguments,
+ escaping characters that needs it.
+*/
+static QString qt_create_commandline(const QString &program, const QStringList &arguments)
+{
+ QString programName = program;
+ if (!programName.startsWith("\"") && !programName.endsWith("\"") && programName.contains(" "))
+ programName = "\"" + programName + "\"";
+ programName.replace("/", "\\");
+
+ QString args;
+ // add the prgram as the first arrg ... it works better
+ args = programName + " ";
+ for (int i=0; i<arguments.size(); ++i) {
+ QString tmp = arguments.at(i);
+ // in the case of \" already being in the string the \ must also be escaped
+ tmp.replace( "\\\"", "\\\\\"" );
+ // escape a single " because the arguments will be parsed
+ tmp.replace( "\"", "\\\"" );
+ if (tmp.isEmpty() || tmp.contains(' ') || tmp.contains('\t')) {
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ QString endQuote("\"");
+ int i = tmp.length();
+ while (i>0 && tmp.at(i-1) == '\\') {
+ --i;
+ endQuote += "\\";
+ }
+ args += QString(" \"") + tmp.left(i) + endQuote;
+ } else {
+ args += ' ' + tmp;
+ }
+ }
+ return args;
+}
+
+/*!
+ Creates a QByteArray of the \a environment in either UNICODE or
+ ansi representation.
+*/
+static QByteArray qt_create_environment(const QStringList &environment)
+{
+ QByteArray envlist;
+ if (!environment.isEmpty()) {
+ int pos = 0;
+ // add PATH if necessary (for DLL loading)
+ QByteArray path = qgetenv("PATH");
+ QT_WA({
+ if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty()
+ && !path.isNull()) {
+ QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path));
+ uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
+ envlist.resize(envlist.size() + tmpSize );
+ memcpy(envlist.data()+pos, tmp.utf16(), tmpSize);
+ pos += tmpSize;
+ }
+ // add the user environment
+ for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++ ) {
+ QString tmp = *it;
+ uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
+ envlist.resize(envlist.size() + tmpSize);
+ memcpy(envlist.data()+pos, tmp.utf16(), tmpSize);
+ pos += tmpSize;
+ }
+ // add the 2 terminating 0 (actually 4, just to be on the safe side)
+ envlist.resize( envlist.size()+4 );
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ }, {
+ if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) {
+ QByteArray tmp = QString("PATH=%1").arg(QString::fromLocal8Bit(path)).toLocal8Bit();
+ uint tmpSize = tmp.length() + 1;
+ envlist.resize(envlist.size() + tmpSize);
+ memcpy(envlist.data()+pos, tmp.data(), tmpSize);
+ pos += tmpSize;
+ }
+ // add the user environment
+ for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++) {
+ QByteArray tmp = (*it).toLocal8Bit();
+ uint tmpSize = tmp.length() + 1;
+ envlist.resize(envlist.size() + tmpSize);
+ memcpy(envlist.data()+pos, tmp.data(), tmpSize);
+ pos += tmpSize;
+ }
+ // add the terminating 0 (actually 2, just to be on the safe side)
+ envlist.resize(envlist.size()+2);
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ })
+ }
+
+ return envlist;
+}
+
+/*!
+ Executes the command described in \a arguments, in the
+ environment inherited from the parent process, with the
+ \a additionalEnv settings applied.
+ \a removeEnv removes the specified environment variables from
+ the environment of the executed process.
+
+ Returns the exit value of the process, or -1 if the command could
+ not be executed.
+
+ This function uses _(w)spawnvpe to spawn a process by searching
+ through the PATH environment variable.
+*/
+int Environment::execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv)
+{
+#ifdef CONFIGURE_DEBUG_EXECUTE
+ qDebug() << "About to Execute: " << arguments;
+ qDebug() << " " << QDir::currentPath();
+ qDebug() << " " << additionalEnv;
+ qDebug() << " " << removeEnv;
+#endif
+// GetEnvironmentStrings is defined to GetEnvironmentStringsW when
+// UNICODE is defined. We cannot use that, since we need to
+// destinguish between unicode and ansi versions of the functions.
+#if defined(UNICODE) && defined(GetEnvironmentStrings)
+#undef GetEnvironmentStrings
+#endif
+
+ // Create the full environment from the current environment and
+ // the additionalEnv strings, then remove all variables defined
+ // in removeEnv
+ QMap<QString, QString> fullEnvMap;
+ QT_WA({
+ LPWSTR envStrings = GetEnvironmentStringsW();
+ if (envStrings) {
+ int strLen = 0;
+ for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) {
+ strLen = wcslen(envString);
+ QString str = QString((const QChar*)envString, strLen);
+ if (!str.startsWith("=")) { // These are added by the system
+ int sepIndex = str.indexOf('=');
+ fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
+ }
+ }
+ }
+ FreeEnvironmentStringsW(envStrings);
+ }, {
+ LPSTR envStrings = GetEnvironmentStrings();
+ if (envStrings) {
+ int strLen = 0;
+ for (LPSTR envString = envStrings; *(envString); envString += strLen + 1) {
+ strLen = strlen(envString);
+ QString str = QLatin1String(envString);
+ if (!str.startsWith("=")) { // These are added by the system
+ int sepIndex = str.indexOf('=');
+ fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
+ }
+ }
+ }
+ FreeEnvironmentStringsA(envStrings);
+ })
+ // Add additionalEnv variables
+ for (int i = 0; i < additionalEnv.count(); ++i) {
+ const QString &str = additionalEnv.at(i);
+ int sepIndex = str.indexOf('=');
+ fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
+ }
+
+ // Remove removeEnv variables
+ for (int j = 0; j < removeEnv.count(); ++j)
+ fullEnvMap.remove(removeEnv.at(j).toUpper());
+
+ // Add all variables to a QStringList
+ QStringList fullEnv;
+ QMapIterator<QString, QString> it(fullEnvMap);
+ while (it.hasNext()) {
+ it.next();
+ fullEnv += QString(it.key() + "=" + it.value());
+ }
+
+ // ----------------------------
+ QString program = arguments.takeAt(0);
+ QString args = qt_create_commandline(program, arguments);
+ QByteArray envlist = qt_create_environment(fullEnv);
+
+ DWORD exitCode = -1;
+ PROCESS_INFORMATION procInfo;
+ memset(&procInfo, 0, sizeof(procInfo));
+
+ bool couldExecute;
+ QT_WA({
+ // Unicode version
+ STARTUPINFOW startInfo;
+ memset(&startInfo, 0, sizeof(startInfo));
+ startInfo.cb = sizeof(startInfo);
+
+ couldExecute = CreateProcessW(0, (WCHAR*)args.utf16(),
+ 0, 0, true, CREATE_UNICODE_ENVIRONMENT,
+ envlist.isEmpty() ? 0 : envlist.data(),
+ 0, &startInfo, &procInfo);
+ }, {
+ // Ansi version
+ STARTUPINFOA startInfo;
+ memset(&startInfo, 0, sizeof(startInfo));
+ startInfo.cb = sizeof(startInfo);
+
+ couldExecute = CreateProcessA(0, args.toLocal8Bit().data(),
+ 0, 0, true, 0,
+ envlist.isEmpty() ? 0 : envlist.data(),
+ 0, &startInfo, &procInfo);
+ })
+
+ if (couldExecute) {
+ WaitForSingleObject(procInfo.hProcess, INFINITE);
+ GetExitCodeProcess(procInfo.hProcess, &exitCode);
+ CloseHandle(procInfo.hThread);
+ CloseHandle(procInfo.hProcess);
+ }
+
+
+ if (exitCode == -1) {
+ switch(GetLastError()) {
+ case E2BIG:
+ cerr << "execute: Argument list exceeds 1024 bytes" << endl;
+ foreach(QString arg, arguments)
+ cerr << " (" << arg.toLocal8Bit().constData() << ")" << endl;
+ break;
+ case ENOENT:
+ cerr << "execute: File or path is not found (" << program.toLocal8Bit().constData() << ")" << endl;
+ break;
+ case ENOEXEC:
+ cerr << "execute: Specified file is not executable or has invalid executable-file format (" << program.toLocal8Bit().constData() << ")" << endl;
+ break;
+ case ENOMEM:
+ cerr << "execute: Not enough memory is available to execute new process." << endl;
+ break;
+ default:
+ cerr << "execute: Unknown error" << endl;
+ foreach(QString arg, arguments)
+ cerr << " (" << arg.toLocal8Bit().constData() << ")" << endl;
+ break;
+ }
+ }
+ return exitCode;
+}
+
+bool Environment::cpdir(const QString &srcDir, const QString &destDir)
+{
+ QString cleanSrcName = QDir::cleanPath(srcDir);
+ QString cleanDstName = QDir::cleanPath(destDir);
+#ifdef CONFIGURE_DEBUG_CP_DIR
+ qDebug() << "Attempt to cpdir " << cleanSrcName << "->" << cleanDstName;
+#endif
+ if(!QFile::exists(cleanDstName) && !QDir().mkpath(cleanDstName)) {
+ qDebug() << "cpdir: Failure to create " << cleanDstName;
+ return false;
+ }
+
+ bool result = true;
+ QDir dir = QDir(cleanSrcName);
+ QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
+ for (int i = 0; result && (i < allEntries.count()); ++i) {
+ QFileInfo entry = allEntries.at(i);
+ bool intermediate = true;
+ if (entry.isDir()) {
+ intermediate = cpdir(QString("%1/%2").arg(cleanSrcName).arg(entry.fileName()),
+ QString("%1/%2").arg(cleanDstName).arg(entry.fileName()));
+ } else {
+ QString destFile = QString("%1/%2").arg(cleanDstName).arg(entry.fileName());
+#ifdef CONFIGURE_DEBUG_CP_DIR
+ qDebug() << "About to cp (file)" << entry.absoluteFilePath() << "->" << destFile;
+#endif
+ QFile::remove(destFile);
+ intermediate = QFile::copy(entry.absoluteFilePath(), destFile);
+ SetFileAttributesA(destFile.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL);
+ }
+ if(!intermediate) {
+ qDebug() << "cpdir: Failure for " << entry.fileName() << entry.isDir();
+ result = false;
+ }
+ }
+ return result;
+}
+
+bool Environment::rmdir(const QString &name)
+{
+ bool result = true;
+ QString cleanName = QDir::cleanPath(name);
+
+ QDir dir = QDir(cleanName);
+ QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
+ for (int i = 0; result && (i < allEntries.count()); ++i) {
+ QFileInfo entry = allEntries.at(i);
+ if (entry.isDir()) {
+ result &= rmdir(entry.absoluteFilePath());
+ } else {
+ result &= QFile::remove(entry.absoluteFilePath());
+ }
+ }
+ result &= dir.rmdir(cleanName);
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/configure/environment.h b/tools/configure/environment.h
new file mode 100644
index 0000000000..08cff4ccdc
--- /dev/null
+++ b/tools/configure/environment.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qstring.h>
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+
+enum Compiler {
+ CC_UNKNOWN = 0,
+ CC_BORLAND = 0x01,
+ CC_MINGW = 0x02,
+ CC_INTEL = 0x03,
+ CC_MSVC4 = 0x40,
+ CC_MSVC5 = 0x50,
+ CC_MSVC6 = 0x60,
+ CC_NET2002 = 0x70,
+ CC_NET2003 = 0x71,
+ CC_NET2005 = 0x80,
+ CC_NET2008 = 0x90
+};
+
+struct CompilerInfo;
+class Environment
+{
+public:
+ static Compiler detectCompiler();
+ static QString detectQMakeSpec();
+ static bool detectExecutable(const QString &executable);
+
+ static int execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv);
+ static bool cpdir(const QString &srcDir, const QString &destDir);
+ static bool rmdir(const QString &name);
+
+private:
+ static Compiler detectedCompiler;
+
+ static CompilerInfo *compilerInfo(Compiler compiler);
+ static QString keyPath(const QString &rKey);
+ static QString keyName(const QString &rKey);
+ static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey);
+};
+
+
+QT_END_NAMESPACE
diff --git a/tools/configure/main.cpp b/tools/configure/main.cpp
new file mode 100644
index 0000000000..d91e124f6f
--- /dev/null
+++ b/tools/configure/main.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+** Configure tool
+**
+*/
+
+#include "configureapp.h"
+
+QT_BEGIN_NAMESPACE
+
+int runConfigure( int argc, char** argv )
+{
+ Configure app( argc, argv );
+ if (!app.isOk())
+ return 3;
+
+ app.parseCmdLine();
+#if !defined(EVAL)
+ app.validateArgs();
+#endif
+ if( app.displayHelp() )
+ return 1;
+
+ // Read license now, and exit if it doesn't pass.
+ // This lets the user see the command-line options of configure
+ // without having to load and parse the license file.
+ app.readLicense();
+ if (!app.isOk())
+ return 3;
+
+ // Auto-detect modules and settings.
+ app.autoDetection();
+
+ // After reading all command-line arguments, and doing all the
+ // auto-detection, it's time to do some last minute validation.
+ // If the validation fails, we cannot continue.
+ if (!app.verifyConfiguration())
+ return 3;
+
+ app.generateOutputVars();
+
+#if !defined(EVAL)
+ if( !app.isDone() )
+ app.generateCachefile();
+ if( !app.isDone() )
+ app.generateBuildKey();
+ if( !app.isDone() )
+ app.generateConfigfiles();
+ if( !app.isDone() )
+ app.displayConfig();
+ if( !app.isDone() )
+ app.generateHeaders();
+ if( !app.isDone() )
+ app.buildQmake();
+ if( !app.isOk() )
+ return 2;
+#endif
+ if( !app.isDone() )
+ app.generateMakefiles();
+ if( app.isOk() )
+ app.buildHostTools();
+ if( !app.isDone() )
+ app.showSummary();
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+int main( int argc, char** argv )
+{
+ QT_USE_NAMESPACE
+ return runConfigure(argc, argv);
+}
diff --git a/tools/configure/tools.cpp b/tools/configure/tools.cpp
new file mode 100644
index 0000000000..ae1ecdadcd
--- /dev/null
+++ b/tools/configure/tools.cpp
@@ -0,0 +1,172 @@
+#include "tools.h"
+
+#include <QDir>
+#include <QFile>
+#include <QByteArray>
+
+
+// std stuff ------------------------------------
+#include <iostream>
+#include <windows.h>
+#include <conio.h>
+#define NUMBER_OF_PARTS 7
+
+std::ostream &operator<<(std::ostream &s, const QString &val); // defined in configureapp.cpp
+using namespace std;
+
+void Tools::checkLicense(QMap<QString,QString> &dictionary, QMap<QString,QString> &licenseInfo,
+ const QString &path)
+{
+ QString tpLicense = dictionary["QT_SOURCE_TREE"] + "/LICENSE.PREVIEW.OPENSOURCE";
+ if (QFile::exists(tpLicense)) {
+ dictionary["EDITION"] = "Preview";
+ dictionary["LICENSE FILE"] = tpLicense;
+ dictionary["QT_EDITION"] = "QT_EDITION_OPENSOURCE";
+ return; // No license key checking in Tech Preview
+ }
+ tpLicense = dictionary["QT_SOURCE_TREE"] + "/LICENSE.PREVIEW.COMMERCIAL";
+ if (QFile::exists(tpLicense)) {
+ dictionary["EDITION"] = "Preview";
+ dictionary["LICENSE FILE"] = tpLicense;
+ dictionary["QT_EDITION"] = "QT_EDITION_DESKTOP";
+ return; // No license key checking in Tech Preview
+ }
+
+ // Read in the license file
+ QFile licenseFile(path);
+ if( !path.isEmpty() && licenseFile.open( QFile::ReadOnly ) ) {
+ cout << "Reading license file in....." << qPrintable(path) << endl;
+
+ QString buffer = licenseFile.readLine(1024);
+ while (!buffer.isEmpty()) {
+ if( buffer[ 0 ] != '#' ) {
+ QStringList components = buffer.split( '=' );
+ if ( components.size() >= 2 ) {
+ QStringList::Iterator it = components.begin();
+ QString key = (*it++).trimmed().replace( "\"", QString() ).toUpper();
+ QString value = (*it++).trimmed().replace( "\"", QString() );
+ licenseInfo[ key ] = value;
+ }
+ }
+ // read next line
+ buffer = licenseFile.readLine(1024);
+ }
+ licenseFile.close();
+ } else {
+ cout << "License file not found in " << QDir::homePath() << endl;
+ cout << "Please put the Qt license file, '.qt-license' in your home "
+ << "directory and run configure again.";
+ dictionary["DONE"] = "error";
+ return;
+ }
+
+ // Verify license info...
+ QString licenseKey = licenseInfo["LICENSEKEYEXT"];
+ const char * clicenseKey = licenseKey.toLatin1();
+ //We check the licence
+#ifndef _WIN32_WCE
+ char *buffer = strdup(clicenseKey);
+#else
+ char *buffer = (char*) malloc(strlen(clicenseKey) + 1);
+ strcpy(buffer, clicenseKey);
+#endif
+ static const char * const SEP = "-";
+ char *licenseParts[NUMBER_OF_PARTS];
+ int partNumber = 0;
+ for (char *part = strtok(buffer, SEP); part != 0; part = strtok(0, SEP))
+ licenseParts[partNumber++] = part;
+ if (partNumber < (NUMBER_OF_PARTS-1)) {
+ dictionary["DONE"] = "error";
+ cout << "License file does not contain proper license key." <<partNumber<< endl;
+ free(buffer);
+ return;
+ }
+
+ char products = licenseParts[0][0];
+ char platforms = licenseParts[1][0];
+ char* licenseSchema = licenseParts[2];
+ char licenseFeatures = licenseParts[3][0];
+
+ // Determine edition ---------------------------------------------------------------------------
+ QString licenseType;
+ if (strcmp(licenseSchema,"F4M") == 0) {
+ licenseType = "Commercial";
+ if (products == 'F') {
+ dictionary["EDITION"] = "Universal";
+ dictionary["QT_EDITION"] = "QT_EDITION_UNIVERSAL";
+ } else if (products == 'B') {
+ dictionary["EDITION"] = "FullFramework";
+ dictionary["QT_EDITION"] = "QT_EDITION_DESKTOP";
+ } else {
+ dictionary["EDITION"] = "GUIFramework";
+ dictionary["QT_EDITION"] = "QT_EDITION_DESKTOPLIGHT";
+ }
+ } else if (strcmp(licenseSchema,"Z4M") == 0 || strcmp(licenseSchema,"R4M") == 0 || strcmp(licenseSchema,"Q4M") == 0) {
+ if (products == 'B') {
+ dictionary["EDITION"] = "Evaluation";
+ dictionary["QT_EDITION"] = "QT_EDITION_EVALUATION";
+ }
+ }
+
+ // Determine license extension -----------------------------------------------------------------
+ if (QFile::exists(dictionary["QT_SOURCE_TREE"] + "/.LICENSE")) {
+ // Generic, no-suffix license
+ dictionary["LICENSE_EXTENSION"] = QString();
+ } else if (platforms == 'X') {
+ dictionary["LICENSE_EXTENSION"] = "-ALLOS";
+ } else if (/*Windows CE */platforms == '6' || /*Embedded */ platforms == '8' || /*Embedded + Windows CE*/platforms == 'K' || /*Windows + Windows CE*/ platforms == 'H') {
+ dictionary["LICENSE_EXTENSION"] = "-EMBEDDED";
+ } else if (/*Windows*/ platforms == 'R' || /*Mac+X11+Windows*/ platforms == 'F') {
+ dictionary["LICENSE_EXTENSION"] = "-DESKTOP";
+ } else if (dictionary["EDITION"] == "Evaluation") {
+ dictionary["LICENSE_EXTENSION"] = "-EVALUATION";
+ }
+ if (licenseType.isEmpty()
+ || dictionary["EDITION"].isEmpty()
+ || dictionary["QT_EDITION"].isEmpty()) {
+ cout << "License file does not contain proper license key." << endl;
+ dictionary["DONE"] = "error";
+ return;
+ }
+
+ // verify that we are licensed to use Qt for Windows
+ if (dictionary["PLATFORM NAME"].contains("Windows CE")) {
+ // verify that we are licensed to use Qt for Windows AND Qt for Windows CE
+ if (platforms != 'H') {
+ cout << "You are not licensed for the " << dictionary["PLATFORM NAME"] << " platform." << endl << endl;
+ cout << "Please contact sales@trolltech.com to upgrade your license" << endl;
+ cout << "to include the " << dictionary["PLATFORM NAME"] << " platform, or install the" << endl;
+ cout << "Qt Open Source Edition if you intend to develop free software." << endl;
+ dictionary["DONE"] = "error";
+ return;
+ }
+ } else {
+ if (!( platforms == 'R' || ( platforms == '6' )|| platforms == '8' )) {
+ cout << "You are not licensed for the " << dictionary["PLATFORM NAME"] << " platform." << endl << endl;
+ cout << "Please contact sales@trolltech.com to upgrade your license" << endl;
+ cout << "to include the " << dictionary["PLATFORM NAME"] << " platform, or install the" << endl;
+ cout << "Qt Open Source Edition if you intend to develop free software." << endl;
+ dictionary["DONE"] = "error";
+ return;
+ }
+ }
+
+ // copy one of .LICENSE-*(-US) to LICENSE
+ QString toLicenseFile = dictionary["QT_SOURCE_TREE"] + "/LICENSE";
+ QString fromLicenseFile = dictionary["QT_SOURCE_TREE"] + "/.LICENSE" + dictionary["LICENSE_EXTENSION"];
+ if (licenseFeatures == 'G') //US
+ fromLicenseFile += "-US";
+
+ if (licenseFeatures == '5') //Floating
+ dictionary["METERED LICENSE"] = "true";
+
+ if (!CopyFileA(QDir::toNativeSeparators(fromLicenseFile).toLocal8Bit(),
+ QDir::toNativeSeparators(toLicenseFile).toLocal8Bit(), FALSE)) {
+ cout << "Failed to copy license file (" << fromLicenseFile << ")";
+ dictionary["DONE"] = "error";
+ return;
+ }
+ dictionary["LICENSE FILE"] = toLicenseFile;
+ free(buffer);
+}
+
diff --git a/tools/configure/tools.h b/tools/configure/tools.h
new file mode 100644
index 0000000000..e95ff13f08
--- /dev/null
+++ b/tools/configure/tools.h
@@ -0,0 +1,17 @@
+#ifndef _TOOLS_H_
+#define _TOOLS_H_
+
+#include <QString>
+#include <QStringList>
+#include <QMap>
+
+
+class Tools
+{
+public:
+ static void checkLicense(QMap<QString,QString> &dictionary, QMap<QString,QString> &licenseInfo,
+ const QString &path);
+};
+
+#endif // _TOOLS_H_
+
diff --git a/tools/designer/data/generate_header.xsl b/tools/designer/data/generate_header.xsl
new file mode 100644
index 0000000000..e3dae9e672
--- /dev/null
+++ b/tools/designer/data/generate_header.xsl
@@ -0,0 +1,465 @@
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY endl "&#10;">
+]>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xsl:output method="text"/>
+
+ <xsl:include href="generate_shared.xsl"/>
+
+<!-- Forward declaration -->
+
+ <xsl:template name="class-forward-declaration">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/attribute::name)"/>
+
+ <xsl:text>class </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>;&endl;</xsl:text>
+ </xsl:template>
+
+<!-- Class declaration: child element accessors -->
+
+ <xsl:template name="child-element-accessors">
+ <xsl:param name="node"/>
+
+ <xsl:variable name="isChoice" select="name($node)='xs:choice'"/>
+
+ <xsl:if test="$isChoice">
+ <xsl:text> enum Kind { Unknown = 0</xsl:text>
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:text>, </xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ </xsl:for-each>
+ <xsl:text> };&endl;</xsl:text>
+ <xsl:text> inline Kind kind() const { return m_kind; }&endl;&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="array" select="@maxOccurs='unbounded'"/>
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="return-cpp-type">
+ <xsl:call-template name="xs-type-to-cpp-return-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="$array"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="argument-cpp-type">
+ <xsl:call-template name="xs-type-to-cpp-argument-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="$array"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="$array"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> inline </xsl:text>
+ <xsl:value-of select="$return-cpp-type"/>
+ <xsl:text> element</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>() const { return m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>; }&endl;</xsl:text>
+
+ <xsl:if test="$xs-type-cat = 'pointer'">
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$return-cpp-type"/>
+ <xsl:text> takeElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>();&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:text> void setElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$argument-cpp-type"/>
+ <xsl:text> a);&endl;</xsl:text>
+
+ <xsl:if test="not($isChoice) and not(@maxOccurs='unbounded')">
+ <xsl:text> inline bool hasElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>() const { return m_children &amp; </xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>; }&endl;</xsl:text>
+ <xsl:text> void clearElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>();&endl;</xsl:text>
+ </xsl:if>
+ <xsl:text>&endl;</xsl:text>
+
+ </xsl:for-each>
+ </xsl:template>
+
+<!-- Class declaration: child element data -->
+
+ <xsl:template name="child-element-data">
+ <xsl:param name="node"/>
+
+ <xsl:variable name="isChoice" select="$node[name()='xs:choice']"/>
+
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cpp-type">
+ <xsl:call-template name="xs-type-to-cpp-return-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="@maxOccurs='unbounded'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$cpp-type"/>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ </xsl:for-each>
+
+ <xsl:if test="not($isChoice) and not(@macOccurs='unbounded')">
+ <xsl:text> enum Child {&endl;</xsl:text>
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> </xsl:text>
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ <xsl:text> = </xsl:text>
+ <xsl:call-template name="powers-of-two">
+ <xsl:with-param name="num" select="position() - 1"/>
+ </xsl:call-template>
+ <xsl:if test="position()!=last()">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+ <xsl:text>&endl;</xsl:text>
+
+ </xsl:for-each>
+ <xsl:text> };&endl;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+<!-- Class declaration: attribute accessors -->
+
+ <xsl:template name="attribute-accessors">
+ <xsl:param name="node"/>
+
+ <xsl:for-each select="$node/xs:attribute">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cpp-return-type">
+ <xsl:call-template name="xs-type-to-cpp-return-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cpp-argument-type">
+ <xsl:call-template name="xs-type-to-cpp-argument-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> inline bool hasAttribute</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>() const { return m_has_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>; }&endl;</xsl:text>
+
+ <xsl:text> inline </xsl:text>
+ <xsl:value-of select="$cpp-return-type"/>
+ <xsl:text> attribute</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>() const { return m_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>; }&endl;</xsl:text>
+
+ <xsl:text> inline void setAttribute</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$cpp-argument-type"/>
+ <xsl:text> a) { m_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = a; m_has_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = true; }&endl;</xsl:text>
+
+ <xsl:text> inline void clearAttribute</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>() { m_has_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = false; }&endl;&endl;</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+
+<!-- Class declaration -->
+
+ <xsl:template name="class-declaration">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+<!-- <xsl:variable name="hasText" select="$node[@mixed='true']"/>-->
+ <xsl:variable name="hasText" select="true()"/>
+
+ <xsl:text>class QDESIGNER_UILIB_EXPORT </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text> {&endl;</xsl:text>
+ <xsl:text>public:&endl;</xsl:text>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>();&endl;</xsl:text>
+ <xsl:text> ~</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>();&endl;&endl;</xsl:text>
+
+ <xsl:text> void read(QXmlStreamReader &amp;reader);&endl;</xsl:text>
+ <xsl:text>#ifdef QUILOADER_QDOM_READ&endl;</xsl:text>
+ <xsl:text> void read(const QDomElement &amp;node);&endl;</xsl:text>
+ <xsl:text>#endif&endl;</xsl:text>
+ <xsl:text> void write(QXmlStreamWriter &amp;writer, const QString &amp;tagName = QString()) const;&endl;</xsl:text>
+
+ <xsl:if test="$hasText">
+ <xsl:text> inline QString text() const { return m_text; }&endl;</xsl:text>
+ <xsl:text> inline void setText(const QString &amp;s) { m_text = s; }&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:text>&endl;</xsl:text>
+
+ <xsl:text> // attribute accessors&endl;</xsl:text>
+ <xsl:call-template name="attribute-accessors">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:text> // child element accessors&endl;</xsl:text>
+
+ <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+ <xsl:call-template name="child-element-accessors">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text>private:&endl;</xsl:text>
+
+ <xsl:if test="$hasText">
+ <xsl:text> QString m_text;&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:text> void clear(bool clear_all = true);&endl;&endl;</xsl:text>
+
+ <xsl:text> // attribute data&endl;</xsl:text>
+ <xsl:for-each select="$node/xs:attribute">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cpp-type">
+ <xsl:call-template name="xs-type-to-cpp-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$cpp-type"/>
+ <xsl:text> m_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ <xsl:text> bool m_has_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>;&endl;&endl;</xsl:text>
+ </xsl:for-each>
+
+ <xsl:text> // child element data&endl;</xsl:text>
+ <xsl:if test="boolean($node/xs:choice)">
+ <xsl:text> Kind m_kind;&endl;</xsl:text>
+ </xsl:if>
+ <xsl:if test="not($node/xs:choice)">
+ <!-- TODO: if there are no elements with maxOccurs='1', m_children is never used-->
+ <xsl:text> uint m_children;&endl;</xsl:text>
+ </xsl:if>
+ <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+ <xsl:call-template name="child-element-data">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text>&endl;</xsl:text>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>(const </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text> &amp;other);&endl;</xsl:text>
+ <xsl:text> void operator = (const </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>&amp;other);&endl;</xsl:text>
+
+ <xsl:text>};&endl;&endl;</xsl:text>
+ </xsl:template>
+
+<!-- Root -->
+
+ <xsl:template match="xs:schema">
+
+<xsl:text>/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// THIS FILE IS AUTOMATICALLY GENERATED
+
+#ifndef UI4_H
+#define UI4_H
+
+#include &lt;QtCore/QList&gt;
+#include &lt;QtCore/QString&gt;
+#include &lt;QtCore/QStringList&gt;
+#include &lt;QtCore/QXmlStreamReader&gt;
+#include &lt;QtCore/QXmlStreamWriter&gt;
+#include &lt;QtCore/qglobal.h&gt;
+
+#if defined(QT_UIC3)
+ #define QUILOADER_QDOM_READ
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QUILOADER_QDOM_READ
+ class QDomElement;
+#endif
+
+
+#define QDESIGNER_UILIB_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_UILIB_IMPORT Q_DECL_IMPORT
+
+#if defined(QT_DESIGNER_STATIC) || defined(QT_UIC) || defined(QT_UIC3)
+# define QDESIGNER_UILIB_EXPORT
+#elif defined(QDESIGNER_UILIB_LIBRARY)
+# define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_EXTERN
+#else
+# define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_IMPORT
+#endif
+
+#ifndef QDESIGNER_UILIB_EXPORT
+# define QDESIGNER_UILIB_EXPORT
+#endif
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+</xsl:text>
+
+ <xsl:text>&endl;</xsl:text>
+ <xsl:text>/*******************************************************************************&endl;</xsl:text>
+ <xsl:text>** Forward declarations&endl;</xsl:text>
+ <xsl:text>*/&endl;&endl;</xsl:text>
+
+ <xsl:for-each select="xs:complexType">
+ <xsl:call-template name="class-forward-declaration">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text>&endl;</xsl:text>
+ <xsl:text>/*******************************************************************************&endl;</xsl:text>
+ <xsl:text>** Declarations&endl;</xsl:text>
+ <xsl:text>*/&endl;&endl;</xsl:text>
+
+ <xsl:for-each select="xs:complexType">
+ <xsl:call-template name="class-declaration">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+ <xsl:text>
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // UI4_H
+</xsl:text>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tools/designer/data/generate_impl.xsl b/tools/designer/data/generate_impl.xsl
new file mode 100644
index 0000000000..2dfbb15268
--- /dev/null
+++ b/tools/designer/data/generate_impl.xsl
@@ -0,0 +1,1161 @@
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY endl "&#10;">
+]>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xsl:output method="text"/>
+
+ <xsl:include href="generate_shared.xsl"/>
+
+<!-- Implementation: constructor -->
+
+ <xsl:template name="ctor-init-attributes">
+ <xsl:param name="node"/>
+ <xsl:for-each select="$node/xs:attribute">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:text> m_has_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = false;&endl;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="@type = 'xs:integer'">
+ <xsl:text> m_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0;&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type = 'xs:double'">
+ <xsl:text> m_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0.0;&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type = 'xs:float'">
+ <xsl:text> m_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0.0;&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type = 'xs:boolean'">
+ <xsl:text> m_attr_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = false;&endl;</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="ctor-init-child-elements">
+ <xsl:param name="node"/>
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="array" select="@maxOccurs='unbounded'"/>
+ <xsl:if test="not($array)">
+ <xsl:variable name="cpp-type">
+ <xsl:call-template name="xs-type-to-cpp-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="$array"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="@type = 'xs:integer'">
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0;&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type = 'xs:float'">
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0.0;&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type = 'xs:boolean'">
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = false;&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@type = 'xs:string'"></xsl:when>
+ <xsl:otherwise>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0;&endl;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="ctor-init-members">
+ <xsl:param name="node"/>
+
+ <xsl:if test="boolean($node/xs:choice)">
+ <xsl:text> m_kind = Unknown;&endl;&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:if test="not($node/xs:choice)">
+ <xsl:text> m_children = 0;&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:call-template name="ctor-init-attributes">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+
+ <xsl:if test="$node[@mixed='true']">
+ <xsl:text> m_text = QLatin1String("");&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+ <xsl:call-template name="ctor-init-child-elements">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="ctor-impl">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+ <xsl:value-of select="$name"/>
+ <xsl:text>::</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>()&endl;</xsl:text>
+ <xsl:text>{&endl;</xsl:text>
+ <xsl:call-template name="ctor-init-members">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+ <xsl:text>}&endl;&endl;</xsl:text>
+ </xsl:template>
+
+<!-- Implementation: destructor -->
+
+ <xsl:template name="dtor-delete-members">
+ <xsl:param name="node"/>
+
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="@maxOccurs='unbounded'">
+ <xsl:if test="$xs-type-cat = 'pointer'">
+ <xsl:text> qDeleteAll(m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:if>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>.clear();&endl;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$xs-type-cat = 'pointer'">
+ <xsl:text> delete m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="dtor-impl">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+ <xsl:value-of select="$name"/>
+ <xsl:text>::~</xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>()&endl;</xsl:text>
+ <xsl:text>{&endl;</xsl:text>
+
+ <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+ <xsl:call-template name="dtor-delete-members">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text>}&endl;&endl;</xsl:text>
+ </xsl:template>
+
+<!-- Implementation: clear() -->
+
+ <xsl:template name="clear-impl">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+ <xsl:text>void </xsl:text><xsl:value-of select="$name"/>
+ <xsl:text>::clear(bool clear_all)&endl;</xsl:text>
+ <xsl:text>{&endl;</xsl:text>
+
+ <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+ <xsl:call-template name="dtor-delete-members">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text>&endl; if (clear_all) {&endl;</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="$node[@mixed='true']">
+ <xsl:text> m_text = QLatin1String("");&endl;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> m_text.clear();&endl;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:call-template name="ctor-init-attributes">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ <xsl:text> }&endl;&endl;</xsl:text>
+
+ <xsl:if test="boolean($node/xs:choice)">
+ <xsl:text> m_kind = Unknown;&endl;&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:if test="not($node/xs:choice)">
+ <xsl:text> m_children = 0;&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+ <xsl:call-template name="ctor-init-child-elements">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text>}&endl;&endl;</xsl:text>
+
+ </xsl:template>
+
+ <!-- Format a string constant as QString(QLatin1Char('X')) or QLatin1String("foo"), respectively -->
+ <xsl:template name="string-constant">
+ <xsl:param name="literal"/>
+ <xsl:choose>
+ <xsl:when test="string-length($literal) &lt; 2">
+ <xsl:text>QString(QLatin1Char('</xsl:text>
+ <xsl:value-of select="$literal"/>
+ <xsl:text>'))</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>QLatin1String("</xsl:text>
+ <xsl:value-of select="$literal"/>
+ <xsl:text>")</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+<!-- Implementation: read(QXmlStreamReader) -->
+
+ <xsl:template name="read-impl-load-attributes">
+ <xsl:param name="node"/>
+
+ <xsl:if test="$node/xs:attribute">
+ <xsl:text>&endl;</xsl:text>
+ <xsl:text> foreach (const QXmlStreamAttribute &amp;attribute, reader.attributes()) {&endl;</xsl:text>
+ <xsl:text> QStringRef name = attribute.name();&endl;</xsl:text>
+
+ <xsl:for-each select="$node/xs:attribute">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-from-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val">
+ <xsl:text>attribute.value().toString()</xsl:text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> if (name == </xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>) {&endl;</xsl:text>
+ <xsl:text> setAttribute</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ <xsl:text> continue;&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:for-each>
+
+ <xsl:text> reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="read-impl-load-child-element">
+ <xsl:param name="node"/>
+
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="lower-name">
+ <xsl:call-template name="lower-text">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="array" select="@maxOccurs = 'unbounded'"/>
+
+ <xsl:text> if (tag == </xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+ <xsl:text>) {&endl;</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="not($array) and $xs-type-cat = 'value'">
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-from-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="'reader.readElementText()'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> setElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'value'">
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-from-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="'reader.readElementText()'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>.append(</xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="not(@maxOccurs='unbounded') and $xs-type-cat = 'pointer'">
+ <xsl:text> Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text> *v = new Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text>();&endl;</xsl:text>
+ <xsl:text> v->read(reader);&endl;</xsl:text>
+ <xsl:text> setElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(v);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'pointer'">
+ <xsl:text> Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text> *v = new Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text>();&endl;</xsl:text>
+ <xsl:text> v->read(reader);&endl;</xsl:text>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>.append(v);&endl;</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:text> continue;&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="read-impl">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+ <xsl:text>void </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>::read(QXmlStreamReader &amp;reader)&endl;</xsl:text>
+
+ <xsl:text>{&endl;</xsl:text>
+
+ <xsl:call-template name="read-impl-load-attributes">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:text>&endl;</xsl:text>
+
+ <xsl:text> for (bool finished = false; !finished &amp;&amp; !reader.hasError();) {&endl;</xsl:text>
+ <xsl:text> switch (reader.readNext()) {&endl;</xsl:text>
+ <xsl:text> case QXmlStreamReader::StartElement : {&endl;</xsl:text>
+ <xsl:text> const QString tag = reader.name().toString().toLower();&endl;</xsl:text>
+
+ <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+ <xsl:call-template name="read-impl-load-child-element">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text> reader.raiseError(QLatin1String("Unexpected element ") + tag);&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ <xsl:text> break;&endl;</xsl:text>
+ <xsl:text> case QXmlStreamReader::EndElement :&endl;</xsl:text>
+ <xsl:text> finished = true;&endl;</xsl:text>
+ <xsl:text> break;&endl;</xsl:text>
+ <xsl:text> case QXmlStreamReader::Characters :&endl;</xsl:text>
+ <xsl:text> if (!reader.isWhitespace())&endl;</xsl:text>
+ <xsl:text> m_text.append(reader.text().toString());&endl;</xsl:text>
+ <xsl:text> break;&endl;</xsl:text>
+ <xsl:text> default :&endl;</xsl:text>
+ <xsl:text> break;&endl;</xsl:text>
+
+ <xsl:text> }&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ <xsl:text>}&endl;&endl;</xsl:text>
+ </xsl:template>
+
+<!-- Implementation: read(QDomElement) -->
+
+ <xsl:template name="read-impl-qdom-load-attributes">
+ <xsl:param name="node"/>
+
+ <xsl:if test="$node/xs:attribute">
+ <xsl:text>&endl;</xsl:text>
+
+ <xsl:for-each select="$node/xs:attribute">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-from-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val">
+ <xsl:text>node.attribute(</xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>)</xsl:text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> if (node.hasAttribute(</xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="@name"/>
+ </xsl:call-template>
+ <xsl:text>))&endl;</xsl:text>
+ <xsl:text> setAttribute</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="read-impl-qdom-load-child-element">
+ <xsl:param name="node"/>
+
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="lower-name">
+ <xsl:call-template name="lower-text">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="array" select="@maxOccurs = 'unbounded'"/>
+
+ <xsl:text> if (tag == </xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+ <xsl:text>) {&endl;</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="not($array) and $xs-type-cat = 'value'">
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-from-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="'e.text()'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> setElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'value'">
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-from-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="'e.text()'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>.append(</xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="not(@maxOccurs='unbounded') and $xs-type-cat = 'pointer'">
+ <xsl:text> Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text> *v = new Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text>();&endl;</xsl:text>
+ <xsl:text> v->read(e);&endl;</xsl:text>
+ <xsl:text> setElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(v);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="@maxOccurs='unbounded' and $xs-type-cat = 'pointer'">
+ <xsl:text> Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text> *v = new Dom</xsl:text>
+ <xsl:value-of select="@type"/>
+ <xsl:text>();&endl;</xsl:text>
+ <xsl:text> v->read(e);&endl;</xsl:text>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>.append(v);&endl;</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:text> continue;&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="read-impl-qdom">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+ <xsl:text>#ifdef QUILOADER_QDOM_READ&endl;</xsl:text>
+
+ <xsl:text>void </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>::read(const QDomElement &amp;node)&endl;</xsl:text>
+
+ <xsl:text>{</xsl:text>
+
+ <xsl:call-template name="read-impl-qdom-load-attributes">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:text>&endl;</xsl:text>
+
+ <xsl:text> for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {&endl;</xsl:text>
+ <xsl:text> if (!n.isElement())&endl;</xsl:text>
+ <xsl:text> continue;&endl;</xsl:text>
+ <xsl:text> QDomElement e = n.toElement();&endl;</xsl:text>
+ <xsl:text> QString tag = e.tagName().toLower();&endl;</xsl:text>
+
+ <xsl:for-each select="$node//xs:sequence | $node//xs:choice | $node//xs:all">
+ <xsl:call-template name="read-impl-qdom-load-child-element">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text> }&endl;</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="$node[@mixed='true']">
+ <xsl:text> m_text = QLatin1String("");&endl;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> m_text.clear();&endl;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:text> for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {&endl;</xsl:text>
+ <xsl:text> if (child.isText())&endl;</xsl:text>
+ <xsl:text> m_text.append(child.nodeValue());&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+
+ <xsl:text>}&endl;</xsl:text>
+ <xsl:text>#endif&endl;</xsl:text>
+ <xsl:text>&endl;</xsl:text>
+ </xsl:template>
+<!-- Implementation: write() -->
+
+ <xsl:template name="write-impl-save-attributes">
+ <xsl:param name="node"/>
+
+ <xsl:for-each select="$node/xs:attribute">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="lower-name">
+ <xsl:call-template name="lower-text">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> if (hasAttribute</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>())&endl;</xsl:text>
+ <xsl:text> writer.writeAttribute(</xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+
+ <xsl:text>, </xsl:text>
+
+ <xsl:call-template name="xs-type-to-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="concat('attribute', $cap-name, '()')"/>
+ </xsl:call-template>
+
+ <xsl:text>);&endl;&endl;</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="write-impl-save-choice-child-element">
+ <xsl:param name="node"/>
+ <xsl:variable name="have-kind" select="name($node) = 'xs:choice'"/>
+
+ <xsl:text> switch (kind()) {&endl;</xsl:text>
+
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="lower-name">
+ <xsl:call-template name="lower-text">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> case </xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>: {&endl;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$xs-type-cat = 'value'">
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-to-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="concat('element', $cap-name, '()')"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> writer.writeTextElement(</xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$camel-case-name"/>
+ </xsl:call-template>
+ <xsl:text>, </xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type-cat = 'pointer'">
+ <xsl:variable name="cpp-return-type">
+ <xsl:call-template name="xs-type-to-cpp-return-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$cpp-return-type"/>
+ <xsl:text> v = element</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>();&endl;</xsl:text>
+ <xsl:text> if (v != 0) {&endl;</xsl:text>
+ <xsl:text> v->write(writer, </xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+ <xsl:text>);&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:text> break;&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:for-each>
+
+ <xsl:text> default:&endl;</xsl:text>
+ <xsl:text> break;&endl;</xsl:text>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:template>
+
+ <xsl:template name="write-impl-save-sequence-child-element">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="lower-name">
+ <xsl:call-template name="lower-text">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cpp-return-type">
+ <xsl:call-template name="xs-type-to-cpp-return-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="@maxOccurs='unbounded'">
+ <xsl:text> for (int i = 0; i &lt; m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>.size(); ++i) {&endl;</xsl:text>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$cpp-return-type"/>
+ <xsl:text> v = m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>[i];&endl;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$xs-type-cat = 'pointer'">
+ <xsl:text> v->write(writer, </xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-to-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="'v'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text> writer.writeTextElement(</xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+ <xsl:text>, </xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> }&endl;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> if (m_children &amp; </xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>) {&endl;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$xs-type-cat = 'pointer'">
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>->write(writer, </xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="qstring-func">
+ <xsl:call-template name="xs-type-to-qstring-func">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="val" select="concat('m_', $camel-case-name)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:text> writer.writeTextElement(</xsl:text>
+ <xsl:call-template name="string-constant">
+ <xsl:with-param name="literal" select="$lower-name"/>
+ </xsl:call-template>
+ <xsl:text>, </xsl:text>
+ <xsl:value-of select="$qstring-func"/>
+ <xsl:text>);&endl;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text> }&endl;&endl;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="write-impl">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+ <xsl:variable name="lower-name">
+ <xsl:call-template name="lower-text">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text>void </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>::write(QXmlStreamWriter &amp;writer, const QString &amp;tagName) const&endl;</xsl:text>
+ <xsl:text>{&endl;</xsl:text>
+
+ <xsl:text> writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("</xsl:text>
+ <xsl:value-of select="$lower-name"/>
+ <xsl:text>") : tagName.toLower());&endl;&endl;</xsl:text>
+
+ <xsl:call-template name="write-impl-save-attributes">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:for-each select="$node//xs:choice">
+ <xsl:call-template name="write-impl-save-choice-child-element">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:for-each select="$node//xs:sequence | $node//xs:all">
+ <xsl:call-template name="write-impl-save-sequence-child-element">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <xsl:text> if (!m_text.isEmpty())&endl;</xsl:text>
+ <xsl:text> writer.writeCharacters(m_text);&endl;&endl;</xsl:text>
+
+ <xsl:text> writer.writeEndElement();&endl;</xsl:text>
+ <xsl:text>}&endl;&endl;</xsl:text>
+ </xsl:template>
+
+<!-- Implementation: child element setters -->
+
+ <xsl:template name="child-setter-impl-helper">
+ <xsl:param name="node"/>
+ <xsl:param name="name"/>
+ <xsl:variable name="make-kind-enum" select="name($node)='xs:choice'"/>
+ <xsl:variable name="isChoice" select="name($node)='xs:choice'"/>
+
+ <xsl:for-each select="$node/xs:element">
+ <xsl:variable name="array" select="@maxOccurs = 'unbounded'"/>
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="return-cpp-type">
+ <xsl:call-template name="xs-type-to-cpp-return-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="$array"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="argument-cpp-type">
+ <xsl:call-template name="xs-type-to-cpp-argument-type">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="$array"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="$array"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:if test="$xs-type-cat = 'pointer'">
+ <xsl:value-of select="$return-cpp-type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>::takeElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>() &endl;{&endl;</xsl:text>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$return-cpp-type"/>
+ <xsl:text> a = m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0;&endl;</xsl:text>
+ <xsl:if test="not($isChoice)">
+ <xsl:text> m_children ^= </xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ </xsl:if>
+ <xsl:text> return a;&endl;</xsl:text>
+ <xsl:text>}&endl;&endl;</xsl:text>
+ </xsl:if>
+
+ <xsl:text>void </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>::setElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$argument-cpp-type"/>
+ <xsl:text> a)&endl;</xsl:text>
+ <xsl:text>{&endl;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$make-kind-enum">
+ <xsl:text> clear(false);&endl;</xsl:text>
+ <xsl:text> m_kind = </xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type-cat = 'pointer'">
+ <xsl:text> delete </xsl:text>
+ <xsl:text>m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="not($isChoice)">
+ <xsl:text> m_children |= </xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ </xsl:if>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = a;&endl;</xsl:text>
+ <xsl:text>}&endl;&endl;</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="child-setter-impl">
+ <xsl:param name="node"/>
+ <xsl:variable name="name" select="concat('Dom', $node/@name)"/>
+
+ <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+ <xsl:call-template name="child-setter-impl-helper">
+ <xsl:with-param name="node" select="."/>
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="child-clear-impl">
+ <xsl:param name="node"/>
+
+ <xsl:variable name="name" select="concat('Dom', @name)"/>
+ <xsl:for-each select="$node/xs:sequence | $node/xs:choice | $node/xs:all">
+ <xsl:variable name="isChoice" select="name()='xs:choice'"/>
+ <xsl:variable name="make-child-enum" select="boolean(xs:sequence) and not(@maxOccurs='unbounded')"/>
+
+ <xsl:for-each select="xs:element">
+ <xsl:if test="not($isChoice) and not(@maxOccurs='unbounded')">
+ <xsl:variable name="camel-case-name">
+ <xsl:call-template name="camel-case">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cap-name">
+ <xsl:call-template name="cap-first-char">
+ <xsl:with-param name="text" select="$camel-case-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="xs-type-cat">
+ <xsl:call-template name="xs-type-category">
+ <xsl:with-param name="xs-type" select="@type"/>
+ <xsl:with-param name="array" select="@maxOccurs='unbounded'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:text>void </xsl:text>
+ <xsl:value-of select="$name"/>
+ <xsl:text>::clearElement</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>()&endl;</xsl:text>
+ <xsl:text>{&endl;</xsl:text>
+ <xsl:if test="$xs-type-cat = 'pointer'">
+ <xsl:text> delete m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ <xsl:text> m_</xsl:text>
+ <xsl:value-of select="$camel-case-name"/>
+ <xsl:text> = 0;&endl;</xsl:text>
+ </xsl:if>
+ <xsl:text> m_children &amp;= ~</xsl:text>
+ <xsl:value-of select="$cap-name"/>
+ <xsl:text>;&endl;</xsl:text>
+ <xsl:text>}&endl;&endl;</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+
+
+<!-- Implementation -->
+
+ <xsl:template name="class-implementation">
+ <xsl:param name="node"/>
+
+ <xsl:call-template name="clear-impl">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="ctor-impl">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="dtor-impl">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="read-impl">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="read-impl-qdom">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="write-impl">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="child-setter-impl">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ <xsl:call-template name="child-clear-impl">
+ <xsl:with-param name="node" select="$node"/>
+ </xsl:call-template>
+
+ </xsl:template>
+
+<!-- Root -->
+
+ <xsl:template match="xs:schema">
+
+<xsl:text>/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+</xsl:text>
+ <xsl:text>#include "ui4_p.h"&endl;</xsl:text>
+ <xsl:text>&endl;</xsl:text>
+ <xsl:text>#ifdef QUILOADER_QDOM_READ&endl;</xsl:text>
+ <xsl:text>#include &lt;QtXml/QDomElement&gt;&endl;</xsl:text>
+ <xsl:text>#endif&endl;</xsl:text>
+ <xsl:text>&endl;</xsl:text>
+ <xsl:text>QT_BEGIN_NAMESPACE&endl;</xsl:text>
+
+ <xsl:text>#ifdef QFORMINTERNAL_NAMESPACE&endl;</xsl:text>
+ <xsl:text>using namespace QFormInternal;&endl;</xsl:text>
+ <xsl:text>#endif&endl;</xsl:text>
+ <xsl:text>&endl;</xsl:text>
+
+ <xsl:text>/*******************************************************************************&endl;</xsl:text>
+ <xsl:text>** Implementations&endl;</xsl:text>
+ <xsl:text>*/&endl;&endl;</xsl:text>
+
+ <xsl:for-each select="xs:complexType">
+ <xsl:call-template name="class-implementation">
+ <xsl:with-param name="node" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+ <xsl:text>QT_END_NAMESPACE&endl;</xsl:text>
+
+ <xsl:text>&endl;</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tools/designer/data/generate_shared.xsl b/tools/designer/data/generate_shared.xsl
new file mode 100644
index 0000000000..f7859cdce0
--- /dev/null
+++ b/tools/designer/data/generate_shared.xsl
@@ -0,0 +1,331 @@
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY endl "&#10;">
+]>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+<!-- Hack to make names camel case
+ All names in ui files are lowercase, while the element names are
+ capital case. To make the ui files conforming to the xsd file + keep
+ the DOM interface we rename them here -->
+ <xsl:template name="camel-case">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="$text='exportmacro'">exportMacro</xsl:when>
+ <xsl:when test="$text='layoutdefault'">layoutDefault</xsl:when>
+ <xsl:when test="$text='layoutfunction'">layoutFunction</xsl:when>
+ <xsl:when test="$text='pixmapfunction'">pixmapFunction</xsl:when>
+ <xsl:when test="$text='customwidgets'">customWidgets</xsl:when>
+ <xsl:when test="$text='tabstops'">tabStops</xsl:when>
+ <xsl:when test="$text='tabstop'">tabStop</xsl:when>
+ <xsl:when test="$text='buttongroups'">buttonGroups</xsl:when>
+ <xsl:when test="$text='exportmacro'">exportMacro</xsl:when>
+ <xsl:when test="$text='actiongroup'">actionGroup</xsl:when>
+ <xsl:when test="$text='buttongroup'">buttonGroup</xsl:when>
+ <xsl:when test="$text='customwidget'">customWidget</xsl:when>
+ <xsl:when test="$text='sizehint'">sizeHint</xsl:when>
+ <xsl:when test="$text='addpagemethod'">addPageMethod</xsl:when>
+ <xsl:when test="$text='sizepolicy'">sizePolicy</xsl:when>
+ <xsl:when test="$text='hordata'">horData</xsl:when>
+ <xsl:when test="$text='verdata'">verData</xsl:when>
+ <xsl:when test="$text='rowspan'">rowSpan</xsl:when>
+ <xsl:when test="$text='colspan'">colSpan</xsl:when>
+ <xsl:when test="$text='addaction'">addAction</xsl:when>
+ <xsl:when test="$text='zorder'">zOrder</xsl:when>
+ <xsl:when test="$text='startx'">startX</xsl:when>
+ <xsl:when test="$text='starty'">startY</xsl:when>
+ <xsl:when test="$text='endx'">endX</xsl:when>
+ <xsl:when test="$text='endy'">endY</xsl:when>
+ <xsl:when test="$text='centralx'">centralX</xsl:when>
+ <xsl:when test="$text='centraly'">centralY</xsl:when>
+ <xsl:when test="$text='focalx'">focalX</xsl:when>
+ <xsl:when test="$text='focaly'">focalY</xsl:when>
+ <xsl:when test="$text='widgetdata'">widgetData</xsl:when>
+ <xsl:when test="$text='coordinatemode'">coordinateMode</xsl:when>
+ <xsl:when test="$text='brushstyle'">brushStyle</xsl:when>
+ <xsl:when test="$text='colorrole'">colorRole</xsl:when>
+ <xsl:when test="$text='pointsize'">pointSize</xsl:when>
+ <xsl:when test="$text='strikeout'">strikeOut</xsl:when>
+ <xsl:when test="$text='stylestrategy'">styleStrategy</xsl:when>
+ <xsl:when test="$text='hsizetype'">hSizeType</xsl:when>
+ <xsl:when test="$text='vsizetype'">vSizeType</xsl:when>
+ <xsl:when test="$text='horstretch'">horStretch</xsl:when>
+ <xsl:when test="$text='verstretch'">verStretch</xsl:when>
+ <xsl:when test="$text='normaloff'">normalOff</xsl:when>
+ <xsl:when test="$text='normalon'">normalOn</xsl:when>
+ <xsl:when test="$text='disabledoff'">disabledOff</xsl:when>
+ <xsl:when test="$text='disabledon'">disabledOn</xsl:when>
+ <xsl:when test="$text='activeoff'">activeOff</xsl:when>
+ <xsl:when test="$text='activeon'">activeOn</xsl:when>
+ <xsl:when test="$text='selectedoff'">selectedOff</xsl:when>
+ <xsl:when test="$text='selectedon'">selectedOn</xsl:when>
+ <xsl:when test="$text='cursorshape'">cursorShape</xsl:when>
+ <xsl:when test="$text='iconset'">iconSet</xsl:when>
+ <xsl:when test="$text='stringlist'">stringList</xsl:when>
+ <xsl:when test="$text='datetime'">dateTime</xsl:when>
+ <xsl:when test="$text='pointf'">pointF</xsl:when>
+ <xsl:when test="$text='rectf'">rectF</xsl:when>
+ <xsl:when test="$text='sizef'">sizeF</xsl:when>
+ <xsl:when test="$text='longlong'">longLong</xsl:when>
+ <xsl:when test="$text='uint'">UInt</xsl:when>
+ <xsl:when test="$text='ulonglong'">uLongLong</xsl:when>
+ <xsl:when test="$text='rowstretch'">rowStretch</xsl:when>
+ <xsl:when test="$text='columnstretch'">columnStretch</xsl:when>
+ <xsl:when test="$text='rowminimumheight'">rowMinimumHeight</xsl:when>
+ <xsl:when test="$text='columnminimumwidth'">columnMinimumWidth</xsl:when>
+ <xsl:when test="$text='extracomment'">extraComment</xsl:when>
+ <xsl:otherwise><xsl:value-of select="$text"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+<!-- Convenience templates -->
+
+ <xsl:template name="cap-first-char">
+ <xsl:param name="text"/>
+ <xsl:value-of select="concat(translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring($text, 2))" />
+ </xsl:template>
+
+ <xsl:template name="lower-text">
+ <xsl:param name="text"/>
+
+ <xsl:if test="boolean($text)">
+ <xsl:variable name="head" select="substring($text, 1, 1)"/>
+ <xsl:variable name="tail" select="substring($text, 2)"/>
+ <xsl:variable name="lower-head" select="translate($text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
+ <xsl:variable name="lower-tail">
+ <xsl:call-template name="lower-text">
+ <xsl:with-param name="text" select="tail"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select='concat($lower-head, $lower-tail)'/>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="powers-of-two">
+ <xsl:param name="num"/>
+
+ <xsl:choose>
+ <xsl:when test="$num=0">1</xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="x">
+ <xsl:call-template name="powers-of-two">
+ <xsl:with-param name="num" select="$num - 1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="2*$x"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+<!-- Convenience templates: xs-types to c++ types conversions -->
+
+ <xsl:template name="xs-type-from-qstring-func">
+ <xsl:param name="xs-type"/>
+ <xsl:param name="val"/>
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">
+ <xsl:value-of select="$val"/>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">
+ <xsl:value-of select="$val"/>
+ <xsl:text>.toInt()</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:float'">
+ <xsl:value-of select="$val"/>
+ <xsl:text>.toFloat()</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:double'">
+ <xsl:value-of select="$val"/>
+ <xsl:text>.toDouble()</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text> == QLatin1String("true") ? true : false)</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:long'">
+ <xsl:value-of select="$val"/>
+ <xsl:text>.toLongLong()</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">
+ <xsl:value-of select="$val"/>
+ <xsl:text>.toUInt()</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">
+ <xsl:value-of select="$val"/>
+ <xsl:text>.toULongLong()</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>### BZZZZT! ###</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="xs-type-to-qstring-func">
+ <xsl:param name="xs-type"/>
+ <xsl:param name="val"/>
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">
+ <xsl:value-of select="$val"/>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">
+ <xsl:text>QString::number(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text>)</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:long'">
+ <xsl:text>QString::number(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text>)</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">
+ <xsl:text>QString::number(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text>)</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">
+ <xsl:text>QString::number(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text>)</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:float'">
+ <xsl:text>QString::number(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text>, 'f', 8)</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:double'">
+ <xsl:text>QString::number(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text>, 'f', 15)</xsl:text>
+ </xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$val"/>
+ <xsl:text> ? QLatin1String("true") : QLatin1String("false"))</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>### BZZZZT! ###</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="xs-type-category">
+ <xsl:param name="xs-type"/>
+ <xsl:param name="array" select="false"/>
+ <xsl:choose>
+ <xsl:when test="$array">value</xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">value</xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">value</xsl:when>
+ <xsl:when test="$xs-type='xs:float'">value</xsl:when>
+ <xsl:when test="$xs-type='xs:double'">value</xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">value</xsl:when>
+ <xsl:when test="$xs-type='xs:long'">value</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">value</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">value</xsl:when>
+ <xsl:otherwise>pointer</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="xs-type-to-cpp-type">
+ <xsl:param name="xs-type"/>
+ <xsl:param name="array" select="false"/>
+ <xsl:choose>
+ <xsl:when test="$array">
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">QStringList</xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">QList&lt;int&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:float'">QList&lt;float&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:double'">QList&lt;double&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">QList&lt;bool&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:long'">QList&lt;qlonglong&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">QList&lt;uint&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">QList&lt;qulonglong&gt;</xsl:when>
+ <xsl:otherwise>QList&lt;Dom<xsl:value-of select="$xs-type"/>*&gt;</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">QString</xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">int</xsl:when>
+ <xsl:when test="$xs-type='xs:float'">float</xsl:when>
+ <xsl:when test="$xs-type='xs:double'">double</xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">bool</xsl:when>
+ <xsl:when test="$xs-type='xs:long'">qlonglong</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">uint</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">qulonglong</xsl:when>
+ <xsl:otherwise>Dom<xsl:value-of select="$xs-type"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="xs-type-to-cpp-return-type">
+ <xsl:param name="xs-type"/>
+ <xsl:param name="array" select="false"/>
+ <xsl:choose>
+ <xsl:when test="$array">
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">QStringList</xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">QList&lt;int&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:float'">QList&lt;float&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:double'">QList&lt;double&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">QList&lt;bool&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:long'">QList&lt;qlonglong&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">QList&lt;uint&gt;</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">QList&lt;qulonglong&gt;</xsl:when>
+ <xsl:otherwise>QList&lt;Dom<xsl:value-of select="$xs-type"/>*&gt;</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">QString</xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">int</xsl:when>
+ <xsl:when test="$xs-type='xs:float'">float</xsl:when>
+ <xsl:when test="$xs-type='xs:double'">double</xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">bool</xsl:when>
+ <xsl:when test="$xs-type='xs:long'">qlonglong</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">uint</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">qulonglong</xsl:when>
+ <xsl:otherwise>Dom<xsl:value-of select="$xs-type"/>*</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="xs-type-to-cpp-argument-type">
+ <xsl:param name="xs-type"/>
+ <xsl:param name="array" select="false"/>
+ <xsl:choose>
+ <xsl:when test="$array">
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">const QStringList&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">const QList&lt;int&gt;&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:float'">const QList&lt;float&gt;&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:double'">const QList&lt;double&gt;&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">const QList&lt;bool&gt;&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:long'">const QList&lt;qlonglong&gt;&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">const QList&lt;uint&gt;&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">const QList&lt;qulonglong&gt;&amp;</xsl:when>
+ <xsl:otherwise>const QList&lt;Dom<xsl:value-of select="$xs-type"/>*&gt;&amp;</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$xs-type='xs:string'">const QString&amp;</xsl:when>
+ <xsl:when test="$xs-type='xs:integer'">int</xsl:when>
+ <xsl:when test="$xs-type='xs:float'">float</xsl:when>
+ <xsl:when test="$xs-type='xs:double'">double</xsl:when>
+ <xsl:when test="$xs-type='xs:boolean'">bool</xsl:when>
+ <xsl:when test="$xs-type='xs:long'">qlonglong</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedInt'">uint</xsl:when>
+ <xsl:when test="$xs-type='xs:unsignedLong'">qulonglong</xsl:when>
+ <xsl:otherwise>Dom<xsl:value-of select="$xs-type"/>*</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+</xsl:stylesheet>
diff --git a/tools/designer/data/ui3.xsd b/tools/designer/data/ui3.xsd
new file mode 100644
index 0000000000..06f325ef31
--- /dev/null
+++ b/tools/designer/data/ui3.xsd
@@ -0,0 +1,353 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="UI">
+ <xs:complexType>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="actions">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="property" type="property" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="author" type="xs:string" />
+ <xs:element name="class" type="xs:string" />
+ <xs:element name="comment" type="xs:string" />
+ <xs:element name="connections">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="connection">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="sender" type="xs:string" />
+ <xs:element name="signal" type="xs:string" />
+ <xs:element name="receiver" type="xs:string" />
+ <xs:element name="slot" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="customWidgets" type="xs:string" />
+ <xs:element name="exportmacro" type="xs:string" />
+ <xs:element name="forwards">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="forward" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="images">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="image">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="data">
+ <xs:complexType>
+ <xs:sequence />
+ <xs:attribute name="format" type="xs:string" />
+ <xs:attribute name="length" type="xs:integer" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="includes">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="include">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="location" type="xs:string" />
+ <xs:attribute name="impldecl" type="xs:string" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="layoutDefaults">
+ <xs:complexType>
+ <xs:sequence />
+ <xs:attribute name="spacing" type="xs:integer" />
+ <xs:attribute name="margin" type="xs:integer" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="layoutFunctions">
+ <xs:complexType>
+ <xs:sequence />
+ <xs:attribute name="spacing" type="xs:string" />
+ <xs:attribute name="margin" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="menubar">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="property" type="property" />
+ <xs:element name="item">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence />
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="item">
+ </xs:element>
+ <xs:element name="separator" type="xs:string" />
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="text" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:element name="class" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pixmapfunction" type="xs:string" />
+ <xs:element name="signals">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="signal" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="slots">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="slot">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="access" type="xs:string" />
+ <xs:attribute name="specifier" type="xs:string" />
+ <xs:attribute name="language" type="xs:string" />
+ <xs:attribute name="returnType" type="xs:string" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tabstops">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="tabstop" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="toolbars">
+ <xs:complexType>
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="toolbar">
+ <xs:complexType>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="property" type="property" />
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence />
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="separator" type="xs:string" />
+ </xs:choice>
+ <xs:attribute name="dock" type="xs:integer" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="variables">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="variable">
+ <xs:complexType>
+ <xs:sequence />
+ <xs:attribute name="access" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="widget" type="widget" />
+ <xs:element name="include" type="xs:string" />
+ <xs:element name="variable" type="xs:string" />
+ </xs:choice>
+ <xs:attribute name="version" type="xs:string" />
+ <xs:attribute name="stdsetdef" type="xs:integer" />
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="layout">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="property" type="property" />
+ <xs:element name="widget" type="widget" />
+ <xs:element name="spacer" type="spacer" />
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name="widget">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="class" type="xs:string" />
+ <xs:element name="property" type="property" />
+ <xs:element name="hbox" type="layout" />
+ <xs:element name="vbox" type="layout" />
+ <xs:element name="grid" type="layout" />
+ <xs:element name="widget" type="widget" />
+ </xs:choice>
+ <xs:attribute name="class" type="xs:string" />
+ <xs:attribute name="row" type="xs:integer" /> <!-- ### remove me -->
+ <xs:attribute name="column" type="xs:integer" /> <!-- ### remove me -->
+ </xs:complexType>
+
+ <xs:complexType name="spacer">
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="property" type="property" />
+ </xs:sequence>
+ <xs:attribute name="row" type="xs:integer" /> <!-- ### remove me -->
+ <xs:attribute name="column" type="xs:integer" /> <!-- ### remove me -->
+ <xs:attribute name="rowspan" type="xs:integer" /> <!-- ### remove me -->
+ <xs:attribute name="colspan" type="xs:integer" /> <!-- ### remove me -->
+ </xs:complexType>
+
+ <xs:complexType name="color">
+ <xs:sequence>
+ <xs:element name="red" type="xs:integer" />
+ <xs:element name="green" type="xs:integer" />
+ <xs:element name="blue" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="colorGroup">
+ <xs:choice maxOccurs="unbounded">
+ <xs:element name="color" type="color" />
+ <xs:element name="pixmap" type="xs:string" />
+ </xs:choice>
+ </xs:complexType>
+
+ <xs:complexType name="palette">
+ <xs:sequence>
+ <xs:element name="active" type="colorGroup" />
+ <xs:element name="inactive" type="colorGroup" />
+ <xs:element name="disabled" type="colorGroup" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="font">
+ <xs:sequence>
+ <xs:element name="family" type="xs:string" />
+ <xs:element name="pointSize" type="xs:integer" />
+ <xs:element name="weight" type="xs:integer" />
+ <xs:element name="italic" type="xs:boolean" />
+ <xs:element name="bold" type="xs:boolean" />
+ <xs:element name="underline" type="xs:boolean" />
+ <xs:element name="strikeout" type="xs:boolean" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="point">
+ <xs:sequence>
+ <xs:element name="x" type="xs:integer" />
+ <xs:element name="y" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="rect">
+ <xs:sequence>
+ <xs:element name="x" type="xs:integer" />
+ <xs:element name="y" type="xs:integer" />
+ <xs:element name="width" type="xs:integer" />
+ <xs:element name="height" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="sizePolicy">
+ <xs:sequence>
+ <xs:element name="hsizetype" type="xs:integer" />
+ <xs:element name="vsizetype" type="xs:integer" />
+ <xs:element name="horstretch" type="xs:integer" />
+ <xs:element name="verstretch" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="size">
+ <xs:sequence>
+ <xs:element name="width" type="xs:integer" />
+ <xs:element name="height" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="date">
+ <xs:sequence>
+ <xs:element name="year" type="xs:integer" />
+ <xs:element name="month" type="xs:integer" />
+ <xs:element name="day" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="time">
+ <xs:sequence>
+ <xs:element name="hour" type="xs:integer" />
+ <xs:element name="minute" type="xs:integer" />
+ <xs:element name="second" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="dateTime">
+ <xs:sequence>
+ <xs:element name="hour" type="xs:integer" />
+ <xs:element name="minute" type="xs:integer" />
+ <xs:element name="second" type="xs:integer" />
+ <xs:element name="year" type="xs:integer" />
+ <xs:element name="month" type="xs:integer" />
+ <xs:element name="day" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="property">
+ <xs:choice>
+ <xs:element name="bool" type="xs:boolean" />
+ <xs:element name="color" type="color" />
+ <xs:element name="cstring" type="xs:string" />
+ <xs:element name="cursor" type="xs:integer" />
+ <xs:element name="enum" type="xs:string" />
+ <xs:element name="font" type ="font" />
+ <xs:element name="iconset" type="xs:string" />
+ <xs:element name="palette" type="palette" />
+ <xs:element name="point" type="point" />
+ <xs:element name="rect" type="rect" />
+ <xs:element name="set" type="xs:string" />
+ <xs:element name="sizePolicy" type="sizePolicy" />
+ <xs:element name="size" type="size" />
+ <xs:element name="string" type="xs:string" />
+ <xs:element name="number" type="xs:integer" />
+ <xs:element name="date" type="date" />
+ <xs:element name="time" type="time" />
+ <xs:element name="dateTime" type="dateTime" />
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="stdset" type="xs:integer" />
+ </xs:complexType>
+
+</xs:schema> \ No newline at end of file
diff --git a/tools/designer/data/ui4.xsd b/tools/designer/data/ui4.xsd
new file mode 100644
index 0000000000..703e497789
--- /dev/null
+++ b/tools/designer/data/ui4.xsd
@@ -0,0 +1,574 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="ui" type="UI"/>
+
+ <xs:complexType name="UI">
+ <xs:all>
+ <xs:element name="author" type="xs:string" minOccurs="0" />
+ <xs:element name="comment" type="xs:string" minOccurs="0" />
+ <xs:element name="exportmacro" type="xs:string" minOccurs="0" />
+ <xs:element name="class" type="xs:string" />
+ <xs:element name="widget" type="Widget" />
+ <xs:element name="layoutdefault" type="LayoutDefault" minOccurs="0" />
+ <xs:element name="layoutfunction" type="LayoutFunction" minOccurs="0" />
+ <xs:element name="pixmapfunction" type="xs:string" minOccurs="0" />
+ <xs:element name="customwidgets" type="CustomWidgets" minOccurs="0" />
+ <xs:element name="tabstops" type="TabStops" minOccurs="0" />
+ <xs:element name="images" type="Images" minOccurs="0" />
+ <xs:element name="includes" type="Includes" minOccurs="0" />
+ <xs:element name="resources" type="Resources" minOccurs="0" />
+ <xs:element name="connections" type="Connections" minOccurs="0" />
+ <xs:element name="designerdata" type="DesignerData" minOccurs="0" />
+ <xs:element name="slots" type="Slots" minOccurs="0" />
+ <xs:element name="buttongroups" type="ButtonGroups" minOccurs="0" />
+ </xs:all>
+ <xs:attribute name="version" type="xs:string" use="required" />
+ <xs:attribute name="language" type="xs:string" />
+ <xs:attribute name="displayname" type="xs:string" />
+<!-- Legacy attribute generated by uic3 -->
+ <xs:attribute name="stdsetdef" type="xs:integer" />
+<!-- Legacy attribute generated by the VS integration -->
+ <xs:attribute name="stdSetDef" type="xs:integer" />
+ </xs:complexType>
+
+<!-- include begin -->
+ <xs:complexType name="Includes">
+ <xs:sequence>
+ <xs:element name="include" type="Include" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Include" mixed="true" >
+ <xs:attribute name="location" type="xs:string" use="required" />
+ <xs:attribute name="impldecl" type="xs:string" />
+ </xs:complexType>
+<!-- include end -->
+
+<!-- resource begin -->
+ <xs:complexType name="Resources">
+ <xs:sequence>
+ <xs:element name="include" type="Resource" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="Resource">
+ <xs:attribute name="location" type="xs:string" use="required" />
+ </xs:complexType>
+<!-- resource end -->
+
+<!-- actions begin -->
+ <xs:complexType name="ActionGroup">
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="action" type="Action" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="actiongroup" type="ActionGroup" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="Action">
+ <xs:sequence maxOccurs="unbounded" >
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="menu" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="ActionRef">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:complexType>
+<!-- actions end -->
+
+<!-- button groups begin -->
+ <xs:complexType name="ButtonGroup">
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="ButtonGroups">
+ <xs:sequence>
+ <xs:element name="buttongroup" type="ButtonGroup" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+<!-- button groups end -->
+
+<!-- images begin -->
+ <xs:complexType name="Images">
+ <xs:sequence>
+ <xs:element name="image" type="Image" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Image">
+ <xs:sequence>
+ <xs:element name="data" type="ImageData" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="ImageData" mixed="true" >
+ <xs:attribute name="format" type="xs:string" use="required" />
+ <xs:attribute name="length" type="xs:integer" use="required" />
+ </xs:complexType>
+<!-- images end -->
+
+<!-- custom widget support begin -->
+ <xs:complexType name="CustomWidgets">
+ <xs:sequence>
+ <xs:element name="customwidget" type="CustomWidget" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Header" mixed="true" >
+ <xs:attribute name="location" type="xs:string" /> <!-- local or global -->
+ </xs:complexType>
+
+ <xs:complexType name="CustomWidget">
+ <xs:all>
+ <xs:element name="class" type="xs:string" />
+ <xs:element name="extends" type="xs:string" />
+ <xs:element name="header" type="Header" />
+ <xs:element name="sizehint" type="Size" minOccurs="0" />
+ <xs:element name="addpagemethod" type="xs:string" minOccurs="0" />
+ <xs:element name="container" type="xs:integer" minOccurs="0" />
+ <xs:element name="sizepolicy" type="SizePolicyData" minOccurs="0" />
+ <xs:element name="pixmap" type="xs:string" minOccurs="0" />
+ <xs:element name="script" type="Script" minOccurs="0" />
+ <xs:element name="properties" type="Properties" minOccurs="0" />
+ <xs:element name="slots" type="Slots" minOccurs="0" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Properties">
+ <xs:sequence>
+ <xs:element name="property" type="PropertyData" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="PropertyData">
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="SizePolicyData">
+ <xs:all>
+ <xs:element name="hordata" type="xs:integer" />
+ <xs:element name="verdata" type="xs:integer" />
+ </xs:all>
+ </xs:complexType>
+
+<!-- custom widget support end -->
+
+ <xs:complexType name="LayoutDefault">
+ <xs:attribute name="spacing" type="xs:integer" use="required" />
+ <xs:attribute name="margin" type="xs:integer" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="LayoutFunction">
+ <xs:attribute name="spacing" type="xs:string" use="required" />
+ <xs:attribute name="margin" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="TabStops">
+ <xs:sequence>
+ <xs:element name="tabstop" type="xs:string" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Layout">
+ <xs:sequence maxOccurs="unbounded" >
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="item" type="LayoutItem" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="class" type="xs:string" use="required" />
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="stretch" type="xs:string" />
+ <xs:attribute name="rowstretch" type="xs:string" />
+ <xs:attribute name="columnstretch" type="xs:string" />
+ <xs:attribute name="rowminimumheight" type="xs:string" />
+ <xs:attribute name="columnminimumwidth" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="LayoutItem">
+ <xs:choice>
+ <xs:element name="widget" type="Widget" />
+ <xs:element name="layout" type="Layout" />
+ <xs:element name="spacer" type="Spacer" />
+ </xs:choice>
+ <xs:attribute name="row" type="xs:integer" />
+ <xs:attribute name="column" type="xs:integer" />
+ <xs:attribute name="rowspan" type="xs:integer" />
+ <xs:attribute name="colspan" type="xs:integer" />
+ </xs:complexType>
+
+<!-- item view begin -->
+ <xs:complexType name="Row">
+ <xs:sequence>
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Column">
+ <xs:sequence>
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Item">
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="item" type="Item" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="row" type="xs:integer" />
+ <xs:attribute name="column" type="xs:integer" />
+ </xs:complexType>
+<!-- item view end -->
+
+ <xs:complexType name="Widget">
+ <!-- Order does not matter (cannot use xs:all here
+ because of unbounded row, column, item -->
+ <xs:sequence>
+ <xs:element name="class" type="xs:string" minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+ <xs:element name="property" type="Property" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="script" type="Script" minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+ <xs:element name="widgetdata" type="WidgetData" minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+ <xs:element name="attribute" type="Property" minOccurs="0" maxOccurs="unbounded" />
+<!-- item view begin -->
+ <xs:element name="row" type="Row" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="column" type="Column" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="item" type="Item" minOccurs="0" maxOccurs="unbounded" />
+<!-- item view end -->
+ <xs:element name="layout" type="Layout" minOccurs="0" maxOccurs="unbounded" /> <!-- unbounded kept for compatibility reasons -->
+ <xs:element name="widget" type="Widget" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="action" type="Action" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="actiongroup" type="ActionGroup" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="addaction" type="ActionRef" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="zorder" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="class" type="xs:string" use="required" />
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="native" type="xs:boolean" />
+ </xs:complexType>
+
+ <xs:complexType name="Spacer">
+ <xs:sequence>
+ <xs:element name="property" type="Property" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="Color">
+ <xs:all>
+ <xs:element name="red" type="xs:integer" />
+ <xs:element name="green" type="xs:integer" />
+ <xs:element name="blue" type="xs:integer" />
+ </xs:all>
+ <xs:attribute name="alpha" type="xs:integer" />
+ </xs:complexType>
+
+ <xs:complexType name="GradientStop">
+ <xs:sequence>
+ <xs:element name="color" type="Color" />
+ </xs:sequence>
+ <xs:attribute name="position" type="xs:double" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="Gradient">
+ <xs:sequence>
+ <xs:element name="gradientStop" type="GradientStop" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="startx" type="xs:double" use="required" />
+ <xs:attribute name="starty" type="xs:double" use="required" />
+ <xs:attribute name="endx" type="xs:double" use="required" />
+ <xs:attribute name="endy" type="xs:double" use="required" />
+ <xs:attribute name="centralx" type="xs:double" use="required" />
+ <xs:attribute name="centraly" type="xs:double" use="required" />
+ <xs:attribute name="focalx" type="xs:double" use="required" />
+ <xs:attribute name="focaly" type="xs:double" use="required" />
+ <xs:attribute name="radius" type="xs:double" use="required" />
+ <xs:attribute name="angle" type="xs:double" use="required" />
+ <xs:attribute name="type" type="xs:string" use="required" />
+ <xs:attribute name="spread" type="xs:string" use="required" />
+ <xs:attribute name="coordinatemode" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="Brush">
+ <xs:choice>
+ <xs:element name="color" type="Color" />
+ <xs:element name="texture" type="Property" />
+ <xs:element name="gradient" type="Gradient" />
+ </xs:choice>
+ <xs:attribute name="brushstyle" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="ColorRole">
+ <xs:sequence>
+ <xs:element name="brush" type="Brush" />
+ </xs:sequence>
+ <xs:attribute name="role" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="ColorGroup">
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="colorrole" type="ColorRole" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="color" type="Color" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Palette">
+ <xs:all>
+ <xs:element name="active" type="ColorGroup" />
+ <xs:element name="inactive" type="ColorGroup" />
+ <xs:element name="disabled" type="ColorGroup" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Font">
+ <xs:all>
+ <xs:element name="family" type="xs:string" minOccurs="0" />
+ <xs:element name="pointsize" type="xs:integer" minOccurs="0" />
+ <xs:element name="weight" type="xs:integer" minOccurs="0" />
+ <xs:element name="italic" type="xs:boolean" minOccurs="0" />
+ <xs:element name="bold" type="xs:boolean" minOccurs="0" />
+ <xs:element name="underline" type="xs:boolean" minOccurs="0" />
+ <xs:element name="strikeout" type="xs:boolean" minOccurs="0" />
+ <xs:element name="antialiasing" type="xs:boolean" minOccurs="0" />
+ <xs:element name="stylestrategy" type="xs:string" minOccurs="0" />
+ <xs:element name="kerning" type="xs:boolean" minOccurs="0" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Point">
+ <xs:all>
+ <xs:element name="x" type="xs:integer" />
+ <xs:element name="y" type="xs:integer" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Rect">
+ <xs:all>
+ <xs:element name="x" type="xs:integer" />
+ <xs:element name="y" type="xs:integer" />
+ <xs:element name="width" type="xs:integer" />
+ <xs:element name="height" type="xs:integer" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Locale">
+ <xs:attribute name="language" type="xs:string" use="required" />
+ <xs:attribute name="country" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="SizePolicy">
+ <xs:all>
+ <xs:element name="hsizetype" type="xs:integer" minOccurs="0" />
+ <xs:element name="vsizetype" type="xs:integer" minOccurs="0" />
+ <xs:element name="horstretch" type="xs:integer" />
+ <xs:element name="verstretch" type="xs:integer" />
+ </xs:all>
+ <xs:attribute name="hsizetype" type="xs:string" />
+ <xs:attribute name="vsizetype" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="Size">
+ <xs:all>
+ <xs:element name="width" type="xs:integer" />
+ <xs:element name="height" type="xs:integer" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Date">
+ <xs:all>
+ <xs:element name="year" type="xs:integer" />
+ <xs:element name="month" type="xs:integer" />
+ <xs:element name="day" type="xs:integer" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Time">
+ <xs:all>
+ <xs:element name="hour" type="xs:integer" />
+ <xs:element name="minute" type="xs:integer" />
+ <xs:element name="second" type="xs:integer" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="DateTime">
+ <xs:all>
+ <xs:element name="hour" type="xs:integer" />
+ <xs:element name="minute" type="xs:integer" />
+ <xs:element name="second" type="xs:integer" />
+ <xs:element name="year" type="xs:integer" />
+ <xs:element name="month" type="xs:integer" />
+ <xs:element name="day" type="xs:integer" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="StringList">
+ <xs:sequence>
+ <xs:element name="string" type="xs:string" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ResourcePixmap" mixed="true">
+ <xs:attribute name="resource" type="xs:string" />
+ <xs:attribute name="alias" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="ResourceIcon" mixed="true">
+ <xs:all>
+ <xs:element name="normaloff" type="ResourcePixmap" minOccurs="0" />
+ <xs:element name="normalon" type="ResourcePixmap" minOccurs="0" />
+ <xs:element name="disabledoff" type="ResourcePixmap" minOccurs="0" />
+ <xs:element name="disabledon" type="ResourcePixmap" minOccurs="0" />
+ <xs:element name="activeoff" type="ResourcePixmap" minOccurs="0" />
+ <xs:element name="activeon" type="ResourcePixmap" minOccurs="0" />
+ <xs:element name="selectedoff" type="ResourcePixmap" minOccurs="0" />
+ <xs:element name="selectedon" type="ResourcePixmap" minOccurs="0" />
+ </xs:all>
+ <xs:attribute name="resource" type="xs:string" /> <!-- pre 4.4 legacy support -->
+ </xs:complexType>
+
+ <xs:complexType name="String" mixed="true">
+ <xs:attribute name="notr" type="xs:string" />
+ <xs:attribute name="comment" type="xs:string" />
+ <xs:attribute name="extracomment" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="PointF">
+ <xs:all>
+ <xs:element name="x" type="xs:double" />
+ <xs:element name="y" type="xs:double" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="RectF">
+ <xs:all>
+ <xs:element name="x" type="xs:double" />
+ <xs:element name="y" type="xs:double" />
+ <xs:element name="width" type="xs:double" />
+ <xs:element name="height" type="xs:double" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="SizeF">
+ <xs:all>
+ <xs:element name="width" type="xs:double" />
+ <xs:element name="height" type="xs:double" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="Char">
+ <xs:sequence>
+ <xs:element name="unicode" type="xs:integer" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Url">
+ <xs:sequence>
+ <xs:element name="string" type="String" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Property">
+ <xs:choice>
+ <xs:element name="bool" type="xs:string" />
+ <xs:element name="color" type="Color" />
+ <xs:element name="cstring" type="xs:string" />
+ <xs:element name="cursor" type="xs:integer" />
+ <xs:element name="cursorshape" type="xs:string" />
+ <xs:element name="enum" type="xs:string" />
+ <xs:element name="font" type ="Font" />
+ <xs:element name="iconset" type="ResourceIcon"/>
+ <xs:element name="pixmap" type="ResourcePixmap" />
+ <xs:element name="palette" type="Palette" />
+ <xs:element name="point" type="Point" />
+ <xs:element name="rect" type="Rect" />
+ <xs:element name="set" type="xs:string" />
+ <xs:element name="locale" type="Locale" />
+ <xs:element name="sizepolicy" type="SizePolicy" />
+ <xs:element name="size" type="Size" />
+ <xs:element name="string" type="String" />
+ <xs:element name="stringlist" type="StringList" />
+ <xs:element name="number" type="xs:integer" />
+ <xs:element name="float" type="xs:float" />
+ <xs:element name="double" type="xs:double" />
+ <xs:element name="date" type="Date" />
+ <xs:element name="time" type="Time" />
+ <xs:element name="datetime" type="DateTime" />
+ <xs:element name="pointf" type="PointF" />
+ <xs:element name="rectf" type="RectF" />
+ <xs:element name="sizef" type="SizeF" />
+ <xs:element name="longlong" type="xs:long" />
+ <xs:element name="char" type="Char" />
+ <xs:element name="url" type="Url" />
+ <xs:element name="uint" type="xs:unsignedInt" />
+ <xs:element name="ulonglong" type="xs:unsignedLong" />
+ <xs:element name="brush" type="Brush" />
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="stdset" type="xs:integer" />
+ </xs:complexType>
+
+ <xs:complexType name="Connections">
+ <xs:sequence>
+ <xs:element name="connection" type="Connection" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Connection">
+ <xs:all>
+ <xs:element name="sender" type="xs:string" />
+ <xs:element name="signal" type="xs:string" />
+ <xs:element name="receiver" type="xs:string" />
+ <xs:element name="slot" type="xs:string" />
+ <xs:element name="hints" type="ConnectionHints" minOccurs="0" />
+ </xs:all>
+ </xs:complexType>
+
+ <xs:complexType name="ConnectionHints">
+ <xs:sequence>
+ <xs:element name="hint" type="ConnectionHint" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ConnectionHint">
+ <xs:all>
+ <xs:element name="x" type="xs:integer"/>
+ <xs:element name="y" type="xs:integer"/>
+ </xs:all>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="Script">
+ <xs:attribute name="source" type="xs:string" use="required" />
+ <xs:attribute name="language" type="xs:string" use="required" />
+ </xs:complexType>
+
+ <xs:complexType name="WidgetData">
+ <xs:sequence>
+ <xs:element name="property" type="Property" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="DesignerData">
+ <xs:sequence>
+ <xs:element name="property" type="Property" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Slots">
+ <xs:sequence maxOccurs="unbounded">
+ <xs:element name="signal" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="slot" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+</xs:schema>
diff --git a/tools/designer/designer.pro b/tools/designer/designer.pro
new file mode 100644
index 0000000000..721c4fc42e
--- /dev/null
+++ b/tools/designer/designer.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+CONFIG += qt
+
+SUBDIRS = src
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor.cpp b/tools/designer/src/components/buddyeditor/buddyeditor.cpp
new file mode 100644
index 0000000000..f5c93fadde
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::BuddyEditor
+*/
+
+#include "buddyeditor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <qdesigner_command_p.h>
+#include <qdesigner_propertycommand_p.h>
+#include <qdesigner_utils_p.h>
+#include <qlayout_widget_p.h>
+#include <connectionedit_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtGui/QLabel>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+static const char *buddyPropertyC = "buddy";
+
+static bool canBeBuddy(QWidget *w, QDesignerFormWindowInterface *form)
+{
+ if (qobject_cast<const QLayoutWidget*>(w) || qobject_cast<const QLabel*>(w))
+ return false;
+ if (w == form->mainContainer() || w->isHidden() )
+ return false;
+
+ QExtensionManager *ext = form->core()->extensionManager();
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(ext, w)) {
+ const int index = sheet->indexOf(QLatin1String("focusPolicy"));
+ if (index != -1) {
+ bool ok = false;
+ const Qt::FocusPolicy q = static_cast<Qt::FocusPolicy>(qdesigner_internal::Utils::valueOf(sheet->property(index), &ok));
+ return ok && q != Qt::NoFocus;
+ }
+ }
+ return false;
+}
+
+static QString buddy(QLabel *label, QDesignerFormEditorInterface *core)
+{
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), label);
+ if (sheet == 0)
+ return QString();
+ const int prop_idx = sheet->indexOf(QLatin1String(buddyPropertyC));
+ if (prop_idx == -1)
+ return QString();
+ return sheet->property(prop_idx).toString();
+}
+
+typedef QList<QLabel*> LabelList;
+
+namespace qdesigner_internal {
+
+/*******************************************************************************
+** BuddyEditor
+*/
+
+BuddyEditor::BuddyEditor(QDesignerFormWindowInterface *form, QWidget *parent) :
+ ConnectionEdit(parent, form),
+ m_formWindow(form),
+ m_updating(false)
+{
+}
+
+
+QWidget *BuddyEditor::widgetAt(const QPoint &pos) const
+{
+ QWidget *w = ConnectionEdit::widgetAt(pos);
+
+ while (w != 0 && !m_formWindow->isManaged(w))
+ w = w->parentWidget();
+ if (!w)
+ return w;
+
+ if (state() == Editing) {
+ QLabel *label = qobject_cast<QLabel*>(w);
+ if (label == 0)
+ return 0;
+ const int cnt = connectionCount();
+ for (int i = 0; i < cnt; ++i) {
+ Connection *con = connection(i);
+ if (con->widget(EndPoint::Source) == w)
+ return 0;
+ }
+ } else {
+ if (!canBeBuddy(w, m_formWindow))
+ return 0;
+ }
+
+ return w;
+}
+
+Connection *BuddyEditor::createConnection(QWidget *source, QWidget *destination)
+{
+ return new Connection(this, source, destination);
+}
+
+QDesignerFormWindowInterface *BuddyEditor::formWindow() const
+{
+ return m_formWindow;
+}
+
+void BuddyEditor::updateBackground()
+{
+ if (m_updating || background() == 0)
+ return;
+ ConnectionEdit::updateBackground();
+
+ m_updating = true;
+ QList<Connection *> newList;
+ const LabelList label_list = qFindChildren<QLabel*>(background());
+ foreach (QLabel *label, label_list) {
+ const QString buddy_name = buddy(label, m_formWindow->core());
+ if (buddy_name.isEmpty())
+ continue;
+
+ const QList<QWidget *> targets = qFindChildren<QWidget*>(background(), buddy_name);
+ if (targets.isEmpty())
+ continue;
+
+ QWidget *target = 0;
+
+ QListIterator<QWidget *> it(targets);
+ while (it.hasNext()) {
+ QWidget *widget = it.next();
+ if (widget && !widget->isHidden()) {
+ target = widget;
+ break;
+ }
+ }
+
+ if (target == 0)
+ continue;
+
+ Connection *con = new Connection(this);
+ con->setEndPoint(EndPoint::Source, label, widgetRect(label).center());
+ con->setEndPoint(EndPoint::Target, target, widgetRect(target).center());
+ newList.append(con);
+ }
+
+ QList<Connection *> toRemove;
+
+ const int c = connectionCount();
+ for (int i = 0; i < c; i++) {
+ Connection *con = connection(i);
+ QObject *source = con->object(EndPoint::Source);
+ QObject *target = con->object(EndPoint::Target);
+ bool found = false;
+ QListIterator<Connection *> it(newList);
+ while (it.hasNext()) {
+ Connection *newConn = it.next();
+ if (newConn->object(EndPoint::Source) == source && newConn->object(EndPoint::Target) == target) {
+ found = true;
+ break;
+ }
+ }
+ if (found == false)
+ toRemove.append(con);
+ }
+ if (!toRemove.isEmpty()) {
+ DeleteConnectionsCommand command(this, toRemove);
+ command.redo();
+ foreach (Connection *con, toRemove)
+ delete takeConnection(con);
+ }
+
+ QListIterator<Connection *> it(newList);
+ while (it.hasNext()) {
+ Connection *newConn = it.next();
+
+ bool found = false;
+ const int c = connectionCount();
+ for (int i = 0; i < c; i++) {
+ Connection *con = connection(i);
+ if (con->object(EndPoint::Source) == newConn->object(EndPoint::Source) &&
+ con->object(EndPoint::Target) == newConn->object(EndPoint::Target)) {
+ found = true;
+ break;
+ }
+ }
+ if (found == false) {
+ AddConnectionCommand command(this, newConn);
+ command.redo();
+ } else {
+ delete newConn;
+ }
+ }
+ m_updating = false;
+}
+
+void BuddyEditor::setBackground(QWidget *background)
+{
+ clear();
+ ConnectionEdit::setBackground(background);
+
+ const LabelList label_list = qFindChildren<QLabel*>(background);
+ foreach (QLabel *label, label_list) {
+ const QString buddy_name = buddy(label, m_formWindow->core());
+ if (buddy_name.isEmpty())
+ continue;
+ QWidget *target = qFindChild<QWidget*>(background, buddy_name);
+ if (target == 0)
+ continue;
+
+ Connection *con = new Connection(this);
+ con->setEndPoint(EndPoint::Source, label, widgetRect(label).center());
+ con->setEndPoint(EndPoint::Target, target, widgetRect(target).center());
+ addConnection(con);
+ }
+}
+
+static QUndoCommand *createBuddyCommand(QDesignerFormWindowInterface *fw, QLabel *label, QWidget *buddy)
+{
+ SetPropertyCommand *command = new SetPropertyCommand(fw);
+ command->init(label, QLatin1String(buddyPropertyC), buddy->objectName());
+ command->setText(BuddyEditor::tr("Add buddy"));
+ return command;
+}
+
+void BuddyEditor::endConnection(QWidget *target, const QPoint &pos)
+{
+ Connection *tmp_con = newlyAddedConnection();
+ Q_ASSERT(tmp_con != 0);
+
+ tmp_con->setEndPoint(EndPoint::Target, target, pos);
+
+ QWidget *source = tmp_con->widget(EndPoint::Source);
+ Q_ASSERT(source != 0);
+ Q_ASSERT(target != 0);
+ setEnabled(false);
+ Connection *new_con = createConnection(source, target);
+ setEnabled(true);
+ if (new_con != 0) {
+ new_con->setEndPoint(EndPoint::Source, source, tmp_con->endPointPos(EndPoint::Source));
+ new_con->setEndPoint(EndPoint::Target, target, tmp_con->endPointPos(EndPoint::Target));
+
+ selectNone();
+ addConnection(new_con);
+ QLabel *source = qobject_cast<QLabel*>(new_con->widget(EndPoint::Source));
+ QWidget *target = new_con->widget(EndPoint::Target);
+ if (source) {
+ undoStack()->push(createBuddyCommand(m_formWindow, source, target));
+ } else {
+ qDebug("BuddyEditor::endConnection(): not a label");
+ }
+ setSelected(new_con, true);
+ }
+
+ clearNewlyAddedConnection();
+ findObjectsUnderMouse(mapFromGlobal(QCursor::pos()));
+}
+
+void BuddyEditor::widgetRemoved(QWidget *widget)
+{
+ QList<QWidget*> child_list = qFindChildren<QWidget*>(widget);
+ child_list.prepend(widget);
+
+ ConnectionSet remove_set;
+ foreach (QWidget *w, child_list) {
+ const ConnectionList &cl = connectionList();
+ foreach (Connection *con, cl) {
+ if (con->widget(EndPoint::Source) == w || con->widget(EndPoint::Target) == w)
+ remove_set.insert(con, con);
+ }
+ }
+
+ if (!remove_set.isEmpty()) {
+ undoStack()->beginMacro(tr("Remove buddies"));
+ foreach (Connection *con, remove_set) {
+ setSelected(con, false);
+ con->update();
+ QWidget *source = con->widget(EndPoint::Source);
+ if (qobject_cast<QLabel*>(source) == 0) {
+ qDebug("BuddyConnection::widgetRemoved(): not a label");
+ } else {
+ ResetPropertyCommand *command = new ResetPropertyCommand(formWindow());
+ command->init(source, QLatin1String(buddyPropertyC));
+ undoStack()->push(command);
+ }
+ delete takeConnection(con);
+ }
+ undoStack()->endMacro();
+ }
+}
+
+void BuddyEditor::deleteSelected()
+{
+ const ConnectionSet selectedConnections = selection(); // want copy for unselect
+ if (selectedConnections.isEmpty())
+ return;
+
+ undoStack()->beginMacro(tr("Remove %n buddies", 0, selectedConnections.size()));
+ foreach (Connection *con, selectedConnections) {
+ setSelected(con, false);
+ con->update();
+ QWidget *source = con->widget(EndPoint::Source);
+ if (qobject_cast<QLabel*>(source) == 0) {
+ qDebug("BuddyConnection::deleteSelected(): not a label");
+ } else {
+ ResetPropertyCommand *command = new ResetPropertyCommand(formWindow());
+ command->init(source, QLatin1String(buddyPropertyC));
+ undoStack()->push(command);
+ }
+ delete takeConnection(con);
+ }
+ undoStack()->endMacro();
+}
+
+void BuddyEditor::autoBuddy()
+{
+ // Any labels?
+ LabelList labelList = qFindChildren<QLabel*>(background());
+ if (labelList.empty())
+ return;
+ // Find already used buddies
+ QWidgetList usedBuddies;
+ const ConnectionList &beforeConnections = connectionList();
+ foreach (const Connection *c, beforeConnections)
+ usedBuddies.push_back(c->widget(EndPoint::Target));
+ // Find potential new buddies, keep lists in sync
+ QWidgetList buddies;
+ for (LabelList::iterator it = labelList.begin(); it != labelList.end(); ) {
+ QLabel *label = *it;
+ QWidget *newBuddy = 0;
+ if (m_formWindow->isManaged(label)) {
+ const QString buddy_name = buddy(label, m_formWindow->core());
+ if (buddy_name.isEmpty())
+ newBuddy = findBuddy(label, usedBuddies);
+ }
+ if (newBuddy) {
+ buddies.push_back(newBuddy);
+ usedBuddies.push_back(newBuddy);
+ ++it;
+ } else {
+ it = labelList.erase(it);
+ }
+ }
+ // Add the list in one go.
+ if (labelList.empty())
+ return;
+ const int count = labelList.size();
+ Q_ASSERT(count == buddies.size());
+ undoStack()->beginMacro(tr("Add %n buddies", 0, count));
+ for (int i = 0; i < count; i++)
+ undoStack()->push(createBuddyCommand(m_formWindow, labelList.at(i), buddies.at(i)));
+ undoStack()->endMacro();
+ // Now select all new ones
+ const ConnectionList &connections = connectionList();
+ foreach (Connection *con, connections)
+ setSelected(con, buddies.contains(con->widget(EndPoint::Target)));
+}
+
+// Geometrically find a potential buddy for label by checking neighbouring children of parent
+QWidget *BuddyEditor::findBuddy(QLabel *l, const QWidgetList &existingBuddies) const
+{
+ enum { DeltaX = 5 };
+ const QWidget *parent = l->parentWidget();
+ // Try to find next managed neighbour on horizontal line
+ const QRect geom = l->geometry();
+ const int y = geom.center().y();
+ QWidget *neighbour = 0;
+ switch (QApplication::layoutDirection()) {
+ case Qt::LeftToRight: { // Walk right to find next managed neighbour
+ const int xEnd = parent->size().width();
+ for (int x = geom.right() + 1; x < xEnd; x += DeltaX)
+ if (QWidget *c = parent->childAt (x, y))
+ if (m_formWindow->isManaged(c)) {
+ neighbour = c;
+ break;
+ }
+ }
+ break;
+ case Qt::RightToLeft: // Walk left to find next managed neighbour
+ for (int x = geom.x() - 1; x >= 0; x -= DeltaX)
+ if (QWidget *c = parent->childAt (x, y))
+ if (m_formWindow->isManaged(c)) {
+ neighbour = c;
+ break;
+ }
+ break;
+ }
+ if (neighbour && !existingBuddies.contains(neighbour) && canBeBuddy(neighbour, m_formWindow))
+ return neighbour;
+
+ return 0;
+}
+
+void BuddyEditor::createContextMenu(QMenu &menu)
+{
+ QAction *autoAction = menu.addAction(tr("Set automatically"));
+ connect(autoAction, SIGNAL(triggered()), this, SLOT(autoBuddy()));
+ menu.addSeparator();
+ ConnectionEdit::createContextMenu(menu);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor.h b/tools/designer/src/components/buddyeditor/buddyeditor.h
new file mode 100644
index 0000000000..4f8f8d4c96
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUDDYEDITOR_H
+#define BUDDYEDITOR_H
+
+#include "buddyeditor_global.h"
+
+#include <connectionedit_p.h>
+#include <QtCore/QPointer>
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+class QLabel;
+
+namespace qdesigner_internal {
+
+class QT_BUDDYEDITOR_EXPORT BuddyEditor : public ConnectionEdit
+{
+ Q_OBJECT
+
+public:
+ BuddyEditor(QDesignerFormWindowInterface *form, QWidget *parent);
+
+ QDesignerFormWindowInterface *formWindow() const;
+ virtual void setBackground(QWidget *background);
+ virtual void deleteSelected();
+
+public slots:
+ virtual void updateBackground();
+ virtual void widgetRemoved(QWidget *w);
+ void autoBuddy();
+
+protected:
+ virtual QWidget *widgetAt(const QPoint &pos) const;
+ virtual Connection *createConnection(QWidget *source, QWidget *destination);
+ virtual void endConnection(QWidget *target, const QPoint &pos);
+ virtual void createContextMenu(QMenu &menu);
+
+private:
+ QWidget *findBuddy(QLabel *l, const QWidgetList &existingBuddies) const;
+
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ bool m_updating;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor.pri b/tools/designer/src/components/buddyeditor/buddyeditor.pri
new file mode 100644
index 0000000000..c507aa01dd
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor.pri
@@ -0,0 +1,16 @@
+
+QT += xml
+
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/buddyeditor.h \
+ $$PWD/buddyeditor_plugin.h \
+ $$PWD/buddyeditor_tool.h \
+ $$PWD/buddyeditor_global.h
+
+SOURCES += \
+ $$PWD/buddyeditor.cpp \
+ $$PWD/buddyeditor_tool.cpp \
+ $$PWD/buddyeditor_plugin.cpp \
+ $$PWD/buddyeditor_instance.cpp
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor_global.h b/tools/designer/src/components/buddyeditor/buddyeditor_global.h
new file mode 100644
index 0000000000..490f59185e
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUDDYEDITOR_GLOBAL_H
+#define BUDDYEDITOR_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN
+#ifdef QT_BUDDYEDITOR_LIBRARY
+# define QT_BUDDYEDITOR_EXPORT
+#else
+# define QT_BUDDYEDITOR_EXPORT
+#endif
+#else
+#define QT_BUDDYEDITOR_EXPORT
+#endif
+
+#endif // BUDDYEDITOR_GLOBAL_H
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor_instance.cpp b/tools/designer/src/components/buddyeditor/buddyeditor_instance.cpp
new file mode 100644
index 0000000000..bcfa415130
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor_instance.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qplugin.h>
+
+#include "buddyeditor_plugin.h"
+
+QT_USE_NAMESPACE
+
+using namespace qdesigner_internal;
+
+Q_EXPORT_PLUGIN(BuddyEditorPlugin)
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp b/tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp
new file mode 100644
index 0000000000..98fff8c243
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor_plugin.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::BuddyEditorPlugin
+*/
+
+#include <QtGui/QAction>
+
+#include "buddyeditor_plugin.h"
+#include "buddyeditor_tool.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+BuddyEditorPlugin::BuddyEditorPlugin()
+ : m_initialized(false)
+{
+}
+
+BuddyEditorPlugin::~BuddyEditorPlugin()
+{
+}
+
+bool BuddyEditorPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void BuddyEditorPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_ASSERT(!isInitialized());
+
+ m_action = new QAction(tr("Edit Buddies"), this);
+ m_action->setObjectName(QLatin1String("__qt_edit_buddies_action"));
+ m_action->setIcon(QIcon(core->resourceLocation() + QLatin1String("/buddytool.png")));
+ m_action->setIcon(QIcon(core->resourceLocation() + QLatin1String("/buddytool.png")));
+ m_action->setEnabled(false);
+
+ setParent(core);
+ m_core = core;
+ m_initialized = true;
+
+ connect(core->formWindowManager(), SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)),
+ this, SLOT(addFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(formWindowRemoved(QDesignerFormWindowInterface*)),
+ this, SLOT(removeFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
+}
+
+QDesignerFormEditorInterface *BuddyEditorPlugin::core() const
+{
+ return m_core;
+}
+
+void BuddyEditorPlugin::addFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tools.contains(formWindow) == false);
+
+ BuddyEditorTool *tool = new BuddyEditorTool(formWindow, this);
+ m_tools[formWindow] = tool;
+ connect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+ formWindow->registerTool(tool);
+}
+
+void BuddyEditorPlugin::removeFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tools.contains(formWindow) == true);
+
+ BuddyEditorTool *tool = m_tools.value(formWindow);
+ m_tools.remove(formWindow);
+ disconnect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+ // ### FIXME disable the tool
+
+ delete tool;
+}
+
+QAction *BuddyEditorPlugin::action() const
+{
+ return m_action;
+}
+
+void BuddyEditorPlugin::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+{
+ m_action->setEnabled(formWindow != 0);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor_plugin.h b/tools/designer/src/components/buddyeditor/buddyeditor_plugin.h
new file mode 100644
index 0000000000..79f3f4979c
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor_plugin.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUDDYEDITOR_PLUGIN_H
+#define BUDDYEDITOR_PLUGIN_H
+
+#include "buddyeditor_global.h"
+
+#include <QtDesigner/QDesignerFormEditorPluginInterface>
+
+#include <QtCore/QPointer>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QAction;
+
+namespace qdesigner_internal {
+
+class BuddyEditorTool;
+
+class QT_BUDDYEDITOR_EXPORT BuddyEditorPlugin: public QObject, public QDesignerFormEditorPluginInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerFormEditorPluginInterface)
+public:
+ BuddyEditorPlugin();
+ virtual ~BuddyEditorPlugin();
+
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ QAction *action() const;
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+public slots:
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+
+private slots:
+ void addFormWindow(QDesignerFormWindowInterface *formWindow);
+ void removeFormWindow(QDesignerFormWindowInterface *formWindow);
+
+private:
+ QPointer<QDesignerFormEditorInterface> m_core;
+ QHash<QDesignerFormWindowInterface*, BuddyEditorTool*> m_tools;
+ bool m_initialized;
+ QAction *m_action;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // BUDDYEDITOR_PLUGIN_H
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor_tool.cpp b/tools/designer/src/components/buddyeditor/buddyeditor_tool.cpp
new file mode 100644
index 0000000000..68a6030897
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor_tool.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::BuddyEditorTool
+*/
+
+#include "buddyeditor_tool.h"
+#include "buddyeditor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+BuddyEditorTool::BuddyEditorTool(QDesignerFormWindowInterface *formWindow, QObject *parent)
+ : QDesignerFormWindowToolInterface(parent),
+ m_formWindow(formWindow),
+ m_action(new QAction(tr("Edit Buddies"), this))
+{
+}
+
+BuddyEditorTool::~BuddyEditorTool()
+{
+}
+
+QDesignerFormEditorInterface *BuddyEditorTool::core() const
+{
+ return m_formWindow->core();
+}
+
+QDesignerFormWindowInterface *BuddyEditorTool::formWindow() const
+{
+ return m_formWindow;
+}
+
+bool BuddyEditorTool::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event)
+{
+ Q_UNUSED(widget);
+ Q_UNUSED(managedWidget);
+ Q_UNUSED(event);
+
+ return false;
+}
+
+QWidget *BuddyEditorTool::editor() const
+{
+ if (!m_editor) {
+ Q_ASSERT(formWindow() != 0);
+ m_editor = new BuddyEditor(formWindow(), 0);
+ connect(formWindow(), SIGNAL(mainContainerChanged(QWidget*)), m_editor, SLOT(setBackground(QWidget*)));
+ connect(formWindow(), SIGNAL(changed()),
+ m_editor, SLOT(updateBackground()));
+ }
+
+ return m_editor;
+}
+
+void BuddyEditorTool::activated()
+{
+ m_editor->enableUpdateBackground(true);
+}
+
+void BuddyEditorTool::deactivated()
+{
+ m_editor->enableUpdateBackground(false);
+}
+
+QAction *BuddyEditorTool::action() const
+{
+ return m_action;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/buddyeditor/buddyeditor_tool.h b/tools/designer/src/components/buddyeditor/buddyeditor_tool.h
new file mode 100644
index 0000000000..dee43a0a65
--- /dev/null
+++ b/tools/designer/src/components/buddyeditor/buddyeditor_tool.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUDDYEDITOR_TOOL_H
+#define BUDDYEDITOR_TOOL_H
+
+#include "buddyeditor_global.h"
+
+#include <QtCore/QPointer>
+
+#include <QtDesigner/QDesignerFormWindowToolInterface>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QAction;
+
+namespace qdesigner_internal {
+
+class BuddyEditor;
+
+class QT_BUDDYEDITOR_EXPORT BuddyEditorTool: public QDesignerFormWindowToolInterface
+{
+ Q_OBJECT
+public:
+ explicit BuddyEditorTool(QDesignerFormWindowInterface *formWindow, QObject *parent = 0);
+ virtual ~BuddyEditorTool();
+
+ virtual QDesignerFormEditorInterface *core() const;
+ virtual QDesignerFormWindowInterface *formWindow() const;
+
+ virtual QWidget *editor() const;
+ virtual QAction *action() const;
+
+ virtual void activated();
+ virtual void deactivated();
+
+ virtual bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event);
+
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+ mutable QPointer<BuddyEditor> m_editor;
+ QAction *m_action;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // BUDDYEDITOR_TOOL_H
diff --git a/tools/designer/src/components/component.pri b/tools/designer/src/components/component.pri
new file mode 100644
index 0000000000..c2fc10d9ec
--- /dev/null
+++ b/tools/designer/src/components/component.pri
@@ -0,0 +1,2 @@
+
+TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #do this towards the end
diff --git a/tools/designer/src/components/components.pro b/tools/designer/src/components/components.pro
new file mode 100644
index 0000000000..97d79b4bb4
--- /dev/null
+++ b/tools/designer/src/components/components.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS = lib
diff --git a/tools/designer/src/components/formeditor/brushmanagerproxy.cpp b/tools/designer/src/components/formeditor/brushmanagerproxy.cpp
new file mode 100644
index 0000000000..b1c056eeeb
--- /dev/null
+++ b/tools/designer/src/components/formeditor/brushmanagerproxy.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtbrushmanager.h"
+#include "brushmanagerproxy.h"
+#include "qsimpleresource_p.h"
+#include "qdesigner_utils_p.h"
+#include "ui4_p.h"
+
+#include <QtXml/QXmlStreamWriter>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class BrushManagerProxyPrivate
+{
+ BrushManagerProxy *q_ptr;
+ Q_DECLARE_PUBLIC(BrushManagerProxy)
+
+public:
+ BrushManagerProxyPrivate(BrushManagerProxy *bp, QDesignerFormEditorInterface *core);
+ void brushAdded(const QString &name, const QBrush &brush);
+ void brushRemoved(const QString &name);
+ QString uniqueBrushFileName(const QString &brushName) const;
+
+ QtBrushManager *m_Manager;
+ QString m_designerFolder;
+ const QString m_BrushFolder;
+ QString m_BrushPath;
+ QDesignerFormEditorInterface *m_Core;
+ QMap<QString, QString> m_FileToBrush;
+ QMap<QString, QString> m_BrushToFile;
+};
+
+BrushManagerProxyPrivate::BrushManagerProxyPrivate(BrushManagerProxy *bp, QDesignerFormEditorInterface *core) :
+ q_ptr(bp),
+ m_Manager(0),
+ m_BrushFolder(QLatin1String("brushes")),
+ m_Core(core)
+{
+ m_designerFolder = QDir::homePath();
+ m_designerFolder += QDir::separator();
+ m_designerFolder += QLatin1String(".designer");
+ m_BrushPath = m_designerFolder;
+ m_BrushPath += QDir::separator();
+ m_BrushPath += m_BrushFolder;
+}
+} // namespace qdesigner_internal
+
+using namespace qdesigner_internal;
+
+void BrushManagerProxyPrivate::brushAdded(const QString &name, const QBrush &brush)
+{
+ const QString filename = uniqueBrushFileName(name);
+
+ QDir designerDir(m_designerFolder);
+ if (!designerDir.exists(m_BrushFolder))
+ designerDir.mkdir(m_BrushFolder);
+
+ QFile file(m_BrushPath + QDir::separator() +filename);
+ if (file.open(QIODevice::WriteOnly)) {
+ QSimpleResource resource(m_Core);
+
+ DomBrush *dom = resource.saveBrush(brush);
+
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ writer.writeStartElement(QLatin1String("description"));
+ writer.writeAttribute(QLatin1String("name"), name);
+ dom->write(writer);
+ writer.writeEndElement();
+ writer.writeEndDocument();
+
+ delete dom;
+ file.close();
+
+ m_FileToBrush[filename] = name;
+ m_BrushToFile[name] = filename;
+ }
+}
+
+void BrushManagerProxyPrivate::brushRemoved(const QString &name)
+{
+ QDir brushDir(m_BrushPath);
+
+ QString filename = m_BrushToFile[name];
+ brushDir.remove(filename);
+ m_BrushToFile.remove(name);
+ m_FileToBrush.remove(filename);
+}
+
+QString BrushManagerProxyPrivate::uniqueBrushFileName(const QString &brushName) const
+{
+ const QString extension = QLatin1String(".br");
+ QString filename = brushName.toLower();
+ filename += extension;
+ int i = 0;
+ while (m_FileToBrush.contains(filename)) {
+ filename = brushName.toLower();
+ filename += QString::number(++i);
+ filename += extension;
+ }
+ return filename;
+}
+
+
+BrushManagerProxy::BrushManagerProxy(QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent)
+{
+ d_ptr = new BrushManagerProxyPrivate(this, core);
+}
+
+BrushManagerProxy::~BrushManagerProxy()
+{
+ delete d_ptr;
+}
+
+void BrushManagerProxy::setBrushManager(QtBrushManager *manager)
+{
+ if (d_ptr->m_Manager == manager)
+ return;
+
+ if (d_ptr->m_Manager) {
+ disconnect(d_ptr->m_Manager, SIGNAL(brushAdded(const QString &, const QBrush &)),
+ this, SLOT(brushAdded(const QString &, const QBrush &)));
+ disconnect(d_ptr->m_Manager, SIGNAL(brushRemoved(const QString &)),
+ this, SLOT(brushRemoved(const QString &)));
+ }
+
+ d_ptr->m_Manager = manager;
+
+ if (!d_ptr->m_Manager)
+ return;
+
+ // clear the manager
+ QMap<QString, QBrush> brushes = d_ptr->m_Manager->brushes();
+ QMap<QString, QBrush>::ConstIterator it = brushes.constBegin();
+ while (it != brushes.constEnd()) {
+ QString name = it.key();
+ d_ptr->m_Manager->removeBrush(name);
+
+ it++;
+ }
+
+ // fill up the manager from compiled resources or from brush folder here
+ const QString nameAttribute = QLatin1String("name");
+ const QString brush = QLatin1String("brush");
+ const QString description = QLatin1String("description");
+
+ QDir brushDir(d_ptr->m_BrushPath);
+ bool customBrushesExist = brushDir.exists();
+ if (customBrushesExist) {
+ // load brushes from brush folder
+ QStringList nameFilters;
+ nameFilters.append(QLatin1String("*.br"));
+
+ QFileInfoList infos = brushDir.entryInfoList(nameFilters);
+ QListIterator<QFileInfo> it(infos);
+ while (it.hasNext()) {
+ const QFileInfo fi = it.next();
+
+ QString filename = fi.absoluteFilePath();
+
+ QFile file(filename);
+ if (file.open(QIODevice::ReadOnly)) {
+ QXmlStreamReader reader(&file);
+
+ //<description name="black" >
+ // <brush brushstyle="SolidPattern" >
+ // <color alpha="255" .../>
+ // </brush>
+ //</description>
+
+ QString descname;
+ while (!reader.atEnd()) {
+ if (reader.readNext() == QXmlStreamReader::StartElement) {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == description) {
+ if (!reader.attributes().hasAttribute(nameAttribute))
+ reader.raiseError(tr("The element '%1' is missing the required attribute '%2'.")
+ .arg(tag, nameAttribute));
+ else
+ descname = reader.attributes().value(nameAttribute).toString();
+ continue;
+ }
+ if (tag == brush) {
+ DomBrush brush;
+ brush.read(reader);
+
+ if (descname.isEmpty()) {
+ reader.raiseError(tr("Empty brush name encountered."));
+ } else {
+ QSimpleResource resource(d_ptr->m_Core);
+ QBrush br = resource.setupBrush(&brush);
+ d_ptr->m_Manager->addBrush(descname, br);
+ d_ptr->m_FileToBrush[filename] = descname;
+ d_ptr->m_BrushToFile[descname] = filename;
+ }
+ continue;
+ }
+ reader.raiseError(tr("An unexpected element '%1' was encountered.").arg(tag));
+ }
+ }
+
+ file.close();
+
+ if (reader.hasError()) {
+ qdesigner_internal::designerWarning(tr("An error occurred when reading the brush definition file '%1' at line line %2, column %3: %4")
+ .arg(fi.fileName())
+ .arg(reader.lineNumber())
+ .arg(reader.columnNumber())
+ .arg(reader.errorString()));
+ continue;
+ }
+ }
+ }
+ }
+
+ connect(d_ptr->m_Manager, SIGNAL(brushAdded(QString,QBrush)),
+ this, SLOT(brushAdded(QString, QBrush)));
+ connect(d_ptr->m_Manager, SIGNAL(brushRemoved(QString)),
+ this, SLOT(brushRemoved(QString)));
+
+ if (!customBrushesExist) {
+ // load brushes from resources
+ QFile qrcFile(QLatin1String(":trolltech/brushes/defaultbrushes.xml"));
+ if (!qrcFile.open(QIODevice::ReadOnly))
+ Q_ASSERT(0);
+
+ QXmlStreamReader reader(&qrcFile);
+
+ while (!reader.atEnd()) {
+ if (reader.readNext() == QXmlStreamReader::StartElement) {
+ if (reader.name().toString().toLower() == QLatin1String("description")) {
+ const QString name = reader.attributes().value(nameAttribute).toString();
+ do { // forward to <brush> element, which DomBrush expects
+ reader.readNext();
+ } while (!reader.atEnd() && reader.tokenType() != QXmlStreamReader::StartElement);
+ DomBrush brushDom;
+ brushDom.read(reader);
+ if (!reader.hasError()) {
+ QSimpleResource resource(d_ptr->m_Core);
+ QBrush br = resource.setupBrush(&brushDom);
+ d_ptr->m_Manager->addBrush(name, br);
+ }
+ }
+ }
+ }
+ if (reader.hasError()) {
+ // Should never happen
+ qdesigner_internal::designerWarning(tr("An error occurred when reading the resource file '%1' at line %2, column %3: %4")
+ .arg(qrcFile.fileName())
+ .arg(reader.lineNumber())
+ .arg(reader.columnNumber())
+ .arg(reader.errorString()));
+ }
+
+ qrcFile.close();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_brushmanagerproxy.cpp"
diff --git a/tools/designer/src/components/formeditor/brushmanagerproxy.h b/tools/designer/src/components/formeditor/brushmanagerproxy.h
new file mode 100644
index 0000000000..cbe50ae5e7
--- /dev/null
+++ b/tools/designer/src/components/formeditor/brushmanagerproxy.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BRUSHMANAGERPROXY_H
+#define BRUSHMANAGERPROXY_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class QtBrushManager;
+class BrushManagerProxyPrivate;
+
+class BrushManagerProxy : public QObject
+{
+ Q_OBJECT
+public:
+ explicit BrushManagerProxy(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ ~BrushManagerProxy();
+
+ void setBrushManager(QtBrushManager *manager);
+
+private:
+ BrushManagerProxyPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(BrushManagerProxy)
+ Q_DISABLE_COPY(BrushManagerProxy)
+ Q_PRIVATE_SLOT(d_func(), void brushAdded(const QString &, const QBrush &))
+ Q_PRIVATE_SLOT(d_func(), void brushRemoved(const QString &name))
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/components/formeditor/default_actionprovider.cpp b/tools/designer/src/components/formeditor/default_actionprovider.cpp
new file mode 100644
index 0000000000..49bf095b8c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/default_actionprovider.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "default_actionprovider.h"
+#include "invisible_widget_p.h"
+#include "qdesigner_toolbar_p.h"
+
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtCore/QRect>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ------------ ActionProviderBase:
+// Draws the drag indicator when dragging an action over a widget
+// that receives action Dnd, such as ToolBar, Menu or MenuBar.
+ActionProviderBase::ActionProviderBase(QWidget *widget) :
+ m_indicator(new InvisibleWidget(widget))
+{
+ Q_ASSERT(widget != 0);
+
+ m_indicator->setAutoFillBackground(true);
+ m_indicator->setBackgroundRole(QPalette::Window);
+
+ QPalette p;
+ p.setColor(m_indicator->backgroundRole(), Qt::red);
+ m_indicator->setPalette(p);
+ m_indicator->hide();
+}
+
+enum { indicatorSize = 2 };
+
+// Position an indicator horizontally over the rectangle, indicating
+// 'Insert before' (left or right according to layout direction)
+static inline QRect horizontalIndicatorRect(const QRect &rect)
+{
+ const Qt::LayoutDirection layoutDirection = QApplication::layoutDirection();
+ // Position right?
+ QRect rc = QRect(rect.x(), 0, indicatorSize, rect.height() - 1);
+ if (layoutDirection == Qt::RightToLeft)
+ rc.moveLeft(rc.x() + rect.width() - indicatorSize);
+ return rc;
+}
+
+// Position an indicator vertically over the rectangle, indicating 'Insert before' (top)
+static inline QRect verticalIndicatorRect(const QRect &rect)
+{
+ return QRect(0, rect.top(), rect.width() - 1, indicatorSize);
+}
+
+// Determine the geometry of the indicator by retrieving
+// the action under mouse and positioning the bar within its geometry.
+QRect ActionProviderBase::indicatorGeometry(const QPoint &pos) const
+{
+ QAction *action = actionAt(pos);
+ if (!action)
+ return QRect();
+ QRect rc = actionGeometry(action);
+ return orientation() == Qt::Horizontal ? horizontalIndicatorRect(rc) : verticalIndicatorRect(rc);
+}
+
+// Adjust the indicator while dragging. (-1,1) is called to finish a DND operation
+void ActionProviderBase::adjustIndicator(const QPoint &pos)
+{
+ if (pos == QPoint(-1, -1)) {
+ m_indicator->hide();
+ return;
+ }
+ const QRect ig = indicatorGeometry(pos);
+ if (ig.isValid()) {
+ m_indicator->setGeometry(ig);
+ QPalette p = m_indicator->palette();
+ if (p.color(m_indicator->backgroundRole()) != Qt::red) {
+ p.setColor(m_indicator->backgroundRole(), Qt::red);
+ m_indicator->setPalette(p);
+ }
+ m_indicator->show();
+ m_indicator->raise();
+ } else {
+ m_indicator->hide();
+ }
+}
+
+// ------------- QToolBarActionProvider
+QToolBarActionProvider::QToolBarActionProvider(QToolBar *widget, QObject *parent) :
+ QObject(parent),
+ ActionProviderBase(widget),
+ m_widget(widget)
+{
+}
+
+QRect QToolBarActionProvider::actionGeometry(QAction *action) const
+{
+ return m_widget->actionGeometry(action);
+}
+
+QAction *QToolBarActionProvider::actionAt(const QPoint &pos) const
+{
+ return ToolBarEventFilter::actionAt(m_widget, pos);
+}
+
+Qt::Orientation QToolBarActionProvider::orientation() const
+{
+ return m_widget->orientation();
+}
+
+QRect QToolBarActionProvider::indicatorGeometry(const QPoint &pos) const
+{
+ const QRect actionRect = ActionProviderBase::indicatorGeometry(pos);
+ if (actionRect.isValid())
+ return actionRect;
+ // Toolbar differs in that is has no dummy placeholder to 'insert before'
+ // when intending to append. Check the free area.
+ const QRect freeArea = ToolBarEventFilter::freeArea(m_widget);
+ if (!freeArea.contains(pos))
+ return QRect();
+ return orientation() == Qt::Horizontal ? horizontalIndicatorRect(freeArea) : verticalIndicatorRect(freeArea);
+}
+
+// ------------- QMenuBarActionProvider
+QMenuBarActionProvider::QMenuBarActionProvider(QMenuBar *widget, QObject *parent) :
+ QObject(parent),
+ ActionProviderBase(widget),
+ m_widget(widget)
+{
+}
+
+QRect QMenuBarActionProvider::actionGeometry(QAction *action) const
+{
+ return m_widget->actionGeometry(action);
+}
+
+QAction *QMenuBarActionProvider::actionAt(const QPoint &pos) const
+{
+ return m_widget->actionAt(pos);
+}
+
+Qt::Orientation QMenuBarActionProvider::orientation() const
+{
+ return Qt::Horizontal;
+}
+
+// ------------- QMenuActionProvider
+QMenuActionProvider::QMenuActionProvider(QMenu *widget, QObject *parent) :
+ QObject(parent),
+ ActionProviderBase(widget),
+ m_widget(widget)
+{
+}
+
+QRect QMenuActionProvider::actionGeometry(QAction *action) const
+{
+ return m_widget->actionGeometry(action);
+}
+
+QAction *QMenuActionProvider::actionAt(const QPoint &pos) const
+{
+ return m_widget->actionAt(pos);
+}
+
+Qt::Orientation QMenuActionProvider::orientation() const
+{
+ return Qt::Vertical;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/default_actionprovider.h b/tools/designer/src/components/formeditor/default_actionprovider.h
new file mode 100644
index 0000000000..6c81ec6b1a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/default_actionprovider.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_ACTIONPROVIDER_H
+#define DEFAULT_ACTIONPROVIDER_H
+
+#include "formeditor_global.h"
+#include "actionprovider_p.h"
+#include <extensionfactory_p.h>
+
+#include <QtGui/QMenu>
+#include <QtGui/QMenuBar>
+#include <QtGui/QToolBar>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class FormWindow;
+
+class QT_FORMEDITOR_EXPORT ActionProviderBase: public QDesignerActionProviderExtension
+{
+protected:
+ explicit ActionProviderBase(QWidget *widget);
+
+public:
+ virtual void adjustIndicator(const QPoint &pos);
+ virtual Qt::Orientation orientation() const = 0;
+
+protected:
+ virtual QRect indicatorGeometry(const QPoint &pos) const;
+
+private:
+ QWidget *m_indicator;
+};
+
+class QT_FORMEDITOR_EXPORT QToolBarActionProvider: public QObject, public ActionProviderBase
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerActionProviderExtension)
+public:
+ explicit QToolBarActionProvider(QToolBar *widget, QObject *parent = 0);
+
+ virtual QRect actionGeometry(QAction *action) const;
+ virtual QAction *actionAt(const QPoint &pos) const;
+ Qt::Orientation orientation() const;
+
+protected:
+ virtual QRect indicatorGeometry(const QPoint &pos) const;
+
+private:
+ QToolBar *m_widget;
+};
+
+class QT_FORMEDITOR_EXPORT QMenuBarActionProvider: public QObject, public ActionProviderBase
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerActionProviderExtension)
+public:
+ explicit QMenuBarActionProvider(QMenuBar *widget, QObject *parent = 0);
+
+ virtual QRect actionGeometry(QAction *action) const;
+ virtual QAction *actionAt(const QPoint &pos) const;
+ Qt::Orientation orientation() const;
+
+private:
+ QMenuBar *m_widget;
+};
+
+class QT_FORMEDITOR_EXPORT QMenuActionProvider: public QObject, public ActionProviderBase
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerActionProviderExtension)
+public:
+ explicit QMenuActionProvider(QMenu *widget, QObject *parent = 0);
+
+ virtual QRect actionGeometry(QAction *action) const;
+ virtual QAction *actionAt(const QPoint &pos) const;
+ Qt::Orientation orientation() const;
+
+private:
+ QMenu *m_widget;
+};
+
+typedef ExtensionFactory<QDesignerActionProviderExtension, QToolBar, QToolBarActionProvider> QToolBarActionProviderFactory;
+typedef ExtensionFactory<QDesignerActionProviderExtension, QMenuBar, QMenuBarActionProvider> QMenuBarActionProviderFactory;
+typedef ExtensionFactory<QDesignerActionProviderExtension, QMenu, QMenuActionProvider> QMenuActionProviderFactory;
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DEFAULT_ACTIONPROVIDER_H
diff --git a/tools/designer/src/components/formeditor/default_container.cpp b/tools/designer/src/components/formeditor/default_container.cpp
new file mode 100644
index 0000000000..eb3cd4feea
--- /dev/null
+++ b/tools/designer/src/components/formeditor/default_container.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "default_container.h"
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+template <class Container>
+static inline void setCurrentContainerIndex(int index, Container *container)
+{
+ const bool blocked = container->signalsBlocked();
+ container->blockSignals(true);
+ container->setCurrentIndex(index);
+ container->blockSignals(blocked);
+}
+
+static inline void ensureNoParent(QWidget *widget)
+{
+ if (widget->parentWidget())
+ widget->setParent(0);
+}
+
+static const char *PageLabel = "Page";
+
+namespace qdesigner_internal {
+
+// --------- QStackedWidgetContainer
+QStackedWidgetContainer::QStackedWidgetContainer(QStackedWidget *widget, QObject *parent) :
+ QObject(parent),
+ m_widget(widget)
+{
+}
+
+void QStackedWidgetContainer::setCurrentIndex(int index)
+{
+ setCurrentContainerIndex(index, m_widget);
+}
+
+void QStackedWidgetContainer::addWidget(QWidget *widget)
+{
+ ensureNoParent(widget);
+ m_widget->addWidget(widget);
+}
+
+void QStackedWidgetContainer::insertWidget(int index, QWidget *widget)
+{
+ ensureNoParent(widget);
+ m_widget->insertWidget(index, widget);
+}
+
+void QStackedWidgetContainer::remove(int index)
+{
+ m_widget->removeWidget(widget(index));
+}
+
+// --------- QTabWidgetContainer
+QTabWidgetContainer::QTabWidgetContainer(QTabWidget *widget, QObject *parent) :
+ QObject(parent),
+ m_widget(widget)
+{
+}
+
+void QTabWidgetContainer::setCurrentIndex(int index)
+{
+ setCurrentContainerIndex(index, m_widget);
+}
+
+void QTabWidgetContainer::addWidget(QWidget *widget)
+{
+ ensureNoParent(widget);
+ m_widget->addTab(widget, QString::fromUtf8(PageLabel));
+}
+
+void QTabWidgetContainer::insertWidget(int index, QWidget *widget)
+{
+ ensureNoParent(widget);
+ m_widget->insertTab(index, widget, QString::fromUtf8(PageLabel));
+}
+
+void QTabWidgetContainer::remove(int index)
+{
+ m_widget->removeTab(index);
+}
+
+// ------------------- QToolBoxContainer
+QToolBoxContainer::QToolBoxContainer(QToolBox *widget, QObject *parent) :
+ QObject(parent),
+ m_widget(widget)
+{
+}
+
+void QToolBoxContainer::setCurrentIndex(int index)
+{
+ setCurrentContainerIndex(index, m_widget);
+}
+
+void QToolBoxContainer::addWidget(QWidget *widget)
+{
+ ensureNoParent(widget);
+ m_widget->addItem(widget, QString::fromUtf8(PageLabel));
+}
+
+void QToolBoxContainer::insertWidget(int index, QWidget *widget)
+{
+ ensureNoParent(widget);
+ m_widget->insertItem(index, widget, QString::fromUtf8(PageLabel));
+}
+
+void QToolBoxContainer::remove(int index)
+{
+ m_widget->removeItem(index);
+}
+
+// ------------------- QScrollAreaContainer
+// We pass on active=true only if there are no children yet.
+// If there are children, it is a legacy custom widget QScrollArea that has an internal,
+// unmanaged child, in which case we deactivate the extension (otherwise we crash).
+// The child will then not show up in the task menu
+
+QScrollAreaContainer::QScrollAreaContainer(QScrollArea *widget, QObject *parent) :
+ QObject(parent),
+ SingleChildContainer<QScrollArea>(widget, widget->widget() == 0)
+{
+}
+// ------------------- QDockWidgetContainer
+QDockWidgetContainer::QDockWidgetContainer(QDockWidget *widget, QObject *parent) :
+ QObject(parent),
+ SingleChildContainer<QDockWidget>(widget)
+{
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/default_container.h b/tools/designer/src/components/formeditor/default_container.h
new file mode 100644
index 0000000000..e8547638cc
--- /dev/null
+++ b/tools/designer/src/components/formeditor/default_container.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_CONTAINER_H
+#define DEFAULT_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/extension.h>
+#include <extensionfactory_p.h>
+
+#include <QtGui/QStackedWidget>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QScrollArea>
+#include <QtGui/QDockWidget>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ------------ QStackedWidgetContainer
+class QStackedWidgetContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QStackedWidgetContainer(QStackedWidget *widget, QObject *parent = 0);
+
+ virtual int count() const { return m_widget->count(); }
+ virtual QWidget *widget(int index) const { return m_widget->widget(index); }
+
+ virtual int currentIndex() const { return m_widget->currentIndex(); }
+ virtual void setCurrentIndex(int index);
+
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ QStackedWidget *m_widget;
+};
+
+// ------------ QTabWidgetContainer
+class QTabWidgetContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QTabWidgetContainer(QTabWidget *widget, QObject *parent = 0);
+
+ virtual int count() const { return m_widget->count(); }
+ virtual QWidget *widget(int index) const { return m_widget->widget(index); }
+
+ virtual int currentIndex() const { return m_widget->currentIndex(); }
+ virtual void setCurrentIndex(int index);
+
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ QTabWidget *m_widget;
+};
+
+// ------------ QToolBoxContainer
+class QToolBoxContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QToolBoxContainer(QToolBox *widget, QObject *parent = 0);
+
+ virtual int count() const { return m_widget->count(); }
+ virtual QWidget *widget(int index) const { return m_widget->widget(index); }
+
+ virtual int currentIndex() const { return m_widget->currentIndex(); }
+ virtual void setCurrentIndex(int index);
+
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ QToolBox *m_widget;
+};
+
+// ------------ SingleChildContainer:
+// Template for containers that have a single child widget using widget()/setWidget().
+
+template <class Container>
+class SingleChildContainer: public QDesignerContainerExtension
+{
+protected:
+ explicit SingleChildContainer(Container *widget, bool active = true);
+public:
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int /*index*/) {}
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int /*index*/) {}
+
+private:
+ const bool m_active;
+ Container *m_container;
+};
+
+template <class Container>
+SingleChildContainer<Container>::SingleChildContainer(Container *widget, bool active) :
+ m_active(active),
+ m_container(widget)
+{
+}
+
+template <class Container>
+int SingleChildContainer<Container>::count() const
+{
+ return m_active && m_container->widget() ? 1 : 0;
+}
+
+template <class Container>
+QWidget *SingleChildContainer<Container>::widget(int /* index */) const
+{
+ return m_container->widget();
+}
+
+template <class Container>
+int SingleChildContainer<Container>::currentIndex() const
+{
+ return m_active && m_container->widget() ? 0 : -1;
+}
+
+template <class Container>
+void SingleChildContainer<Container>::addWidget(QWidget *widget)
+{
+ Q_ASSERT(m_container->widget() == 0);
+ widget->setParent(m_container);
+ m_container->setWidget(widget);
+}
+
+template <class Container>
+void SingleChildContainer<Container>::insertWidget(int /* index */, QWidget *widget)
+{
+ addWidget(widget);
+}
+
+// ------------ QScrollAreaContainer
+class QScrollAreaContainer: public QObject, public SingleChildContainer<QScrollArea>
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QScrollAreaContainer(QScrollArea *widget, QObject *parent = 0);
+};
+
+// --------------- QDockWidgetContainer
+class QDockWidgetContainer: public QObject, public SingleChildContainer<QDockWidget>
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QDockWidgetContainer(QDockWidget *widget, QObject *parent = 0);
+};
+
+typedef ExtensionFactory<QDesignerContainerExtension, QStackedWidget, QStackedWidgetContainer> QDesignerStackedWidgetContainerFactory;
+typedef ExtensionFactory<QDesignerContainerExtension, QTabWidget, QTabWidgetContainer> QDesignerTabWidgetContainerFactory;
+typedef ExtensionFactory<QDesignerContainerExtension, QToolBox, QToolBoxContainer> QDesignerToolBoxContainerFactory;
+typedef ExtensionFactory<QDesignerContainerExtension, QScrollArea, QScrollAreaContainer> QScrollAreaContainerFactory;
+typedef ExtensionFactory<QDesignerContainerExtension, QDockWidget, QDockWidgetContainer> QDockWidgetContainerFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DEFAULT_CONTAINER_H
diff --git a/tools/designer/src/components/formeditor/default_layoutdecoration.cpp b/tools/designer/src/components/formeditor/default_layoutdecoration.cpp
new file mode 100644
index 0000000000..555806801e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/default_layoutdecoration.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "default_layoutdecoration.h"
+#include "qlayout_widget_p.h"
+
+#include <layoutinfo_p.h>
+
+#include <QtDesigner/QDesignerMetaDataBaseItemInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ---- QDesignerLayoutDecorationFactory ----
+QDesignerLayoutDecorationFactory::QDesignerLayoutDecorationFactory(QExtensionManager *parent)
+ : QExtensionFactory(parent)
+{
+}
+
+QObject *QDesignerLayoutDecorationFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (!object->isWidgetType() || iid != Q_TYPEID(QDesignerLayoutDecorationExtension))
+ return 0;
+
+ QWidget *widget = qobject_cast<QWidget*>(object);
+
+ if (const QLayoutWidget *layoutWidget = qobject_cast<const QLayoutWidget*>(widget))
+ return QLayoutSupport::createLayoutSupport(layoutWidget->formWindow(), widget, parent);
+
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(widget))
+ if (LayoutInfo::managedLayout(fw->core(), widget))
+ return QLayoutSupport::createLayoutSupport(fw, widget, parent);
+
+ return 0;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/default_layoutdecoration.h b/tools/designer/src/components/formeditor/default_layoutdecoration.h
new file mode 100644
index 0000000000..770372fa94
--- /dev/null
+++ b/tools/designer/src/components/formeditor/default_layoutdecoration.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_LAYOUTDECORATION_H
+#define DEFAULT_LAYOUTDECORATION_H
+
+#include "formeditor_global.h"
+#include <QtDesigner/QDesignerLayoutDecorationExtension>
+#include <QtDesigner/default_extensionfactory.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+class QDesignerLayoutDecorationFactory: public QExtensionFactory
+{
+ Q_OBJECT
+ Q_INTERFACES(QAbstractExtensionFactory)
+public:
+ explicit QDesignerLayoutDecorationFactory(QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DEFAULT_LAYOUTDECORATION_H
diff --git a/tools/designer/src/components/formeditor/defaultbrushes.xml b/tools/designer/src/components/formeditor/defaultbrushes.xml
new file mode 100644
index 0000000000..88035c3a68
--- /dev/null
+++ b/tools/designer/src/components/formeditor/defaultbrushes.xml
@@ -0,0 +1,542 @@
+<brushes>
+ <description name="French" >
+ <brush brushstyle="LinearGradientPattern" >
+ <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="1" coordinatemode="StretchToDeviceMode" endy="0" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.323" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.343" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.656" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.676" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="German" >
+ <brush brushstyle="LinearGradientPattern" >
+ <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.323" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.343" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.656" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.676" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="Greek" >
+ <brush brushstyle="LinearGradientPattern" >
+ <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.09" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.105" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.205" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.22" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.32" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.335" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.435" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.45" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.55" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.565" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.665" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.68" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.78" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.795" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.895" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.91" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>176</green>
+ <blue>221</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="Italian" >
+ <brush brushstyle="LinearGradientPattern" >
+ <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="1" coordinatemode="StretchToDeviceMode" endy="0" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>60</red>
+ <green>160</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.323" >
+ <color alpha="255" >
+ <red>60</red>
+ <green>160</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.343" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.656" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.676" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="Japanese" >
+ <brush brushstyle="RadialGradientPattern" >
+ <gradient focalx="0.5" focaly="0.5" radius="0.5" spread="PadSpread" type="RadialGradient" coordinatemode="StretchToDeviceMode" centralx="0.5" centraly="0.5" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.49" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.51" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="Norwegian" >
+ <brush brushstyle="LinearGradientPattern" >
+ <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="1" coordinatemode="StretchToDeviceMode" endy="0" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.225" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.25" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.275" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.3" >
+ <color alpha="255" >
+ <red>5</red>
+ <green>0</green>
+ <blue>70</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.4" >
+ <color alpha="255" >
+ <red>5</red>
+ <green>0</green>
+ <blue>70</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.425" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.45" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.475" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="Polish" >
+ <brush brushstyle="LinearGradientPattern" >
+ <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.475" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.525" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="Spanish" >
+ <brush brushstyle="LinearGradientPattern" >
+ <gradient spread="PadSpread" startx="0" starty="0" type="LinearGradient" endx="0" coordinatemode="StretchToDeviceMode" endy="1" >
+ <gradientstop position="0" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.24" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.26" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.74" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="0.76" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ <gradientstop position="1" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </gradientstop>
+ </gradient>
+ </brush>
+ </description>
+ <description name="black" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </description>
+ <description name="blue" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </description>
+ <description name="cyan" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </description>
+ <description name="green" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </description>
+ <description name="magenta" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </description>
+ <description name="red" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </description>
+ <description name="white" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </description>
+ <description name="yellow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </description>
+</brushes>
diff --git a/tools/designer/src/components/formeditor/deviceprofiledialog.cpp b/tools/designer/src/components/formeditor/deviceprofiledialog.cpp
new file mode 100644
index 0000000000..995bc3f23a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/deviceprofiledialog.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deviceprofiledialog.h"
+#include "ui_deviceprofiledialog.h"
+
+#include <abstractdialoggui_p.h>
+#include <deviceprofile_p.h>
+
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QStyleFactory>
+#include <QtGui/QFontDatabase>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QFile>
+
+QT_BEGIN_NAMESPACE
+
+static const char *profileExtensionC = "qdp";
+
+static inline QString fileFilter()
+{
+ return qdesigner_internal::DeviceProfileDialog::tr("Device Profiles (*.%1)").arg(QLatin1String(profileExtensionC));
+}
+
+// Populate a combo with a sequence of integers, also set them as data.
+template <class IntIterator>
+ static void populateNumericCombo(IntIterator i1, IntIterator i2, QComboBox *cb)
+{
+ QString s;
+ cb->setEditable(false);
+ for ( ; i1 != i2 ; ++i1) {
+ const int n = *i1;
+ s.setNum(n);
+ cb->addItem(s, QVariant(n));
+ }
+}
+
+namespace qdesigner_internal {
+
+DeviceProfileDialog::DeviceProfileDialog(QDesignerDialogGuiInterface *dlgGui, QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::DeviceProfileDialog),
+ m_dlgGui(dlgGui)
+{
+ setModal(true);
+ m_ui->setupUi(this);
+
+ const QList<int> standardFontSizes = QFontDatabase::standardSizes();
+ populateNumericCombo(standardFontSizes.constBegin(), standardFontSizes.constEnd(), m_ui->m_systemFontSizeCombo);
+
+ // Styles
+ const QStringList styles = QStyleFactory::keys();
+ m_ui->m_styleCombo->addItem(tr("Default"), QVariant(QString()));
+ const QStringList::const_iterator cend = styles.constEnd();
+ for (QStringList::const_iterator it = styles.constBegin(); it != cend; ++it)
+ m_ui->m_styleCombo->addItem(*it, *it);
+
+ connect(m_ui->m_nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(nameChanged(QString)));
+ connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(m_ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept()));
+ // Note that Load/Save emit accepted() of the button box..
+ connect(m_ui->buttonBox->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(save()));
+ connect(m_ui->buttonBox->button(QDialogButtonBox::Open), SIGNAL(clicked()), this, SLOT(open()));
+}
+
+DeviceProfileDialog::~DeviceProfileDialog()
+{
+ delete m_ui;
+}
+
+DeviceProfile DeviceProfileDialog::deviceProfile() const
+{
+ DeviceProfile rc;
+ rc.setName(m_ui->m_nameLineEdit->text());
+ rc.setFontFamily(m_ui->m_systemFontComboBox->currentFont().family());
+ rc.setFontPointSize(m_ui->m_systemFontSizeCombo->itemData(m_ui->m_systemFontSizeCombo->currentIndex()).toInt());
+
+ int dpiX, dpiY;
+ m_ui->m_dpiChooser->getDPI(&dpiX, &dpiY);
+ rc.setDpiX(dpiX);
+ rc.setDpiY(dpiY);
+
+ rc.setStyle(m_ui->m_styleCombo->itemData(m_ui->m_styleCombo->currentIndex()).toString());
+
+ return rc;
+}
+
+void DeviceProfileDialog::setDeviceProfile(const DeviceProfile &s)
+{
+ m_ui->m_nameLineEdit->setText(s.name());
+ m_ui->m_systemFontComboBox->setCurrentFont(QFont(s.fontFamily()));
+ const int fontSizeIndex = m_ui->m_systemFontSizeCombo->findData(QVariant(s.fontPointSize()));
+ m_ui->m_systemFontSizeCombo->setCurrentIndex(fontSizeIndex != -1 ? fontSizeIndex : 0);
+ m_ui->m_dpiChooser->setDPI(s.dpiX(), s.dpiY());
+ const int styleIndex = m_ui->m_styleCombo->findData(s.style());
+ m_ui->m_styleCombo->setCurrentIndex(styleIndex != -1 ? styleIndex : 0);
+}
+
+void DeviceProfileDialog::setOkButtonEnabled(bool v)
+{
+ m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(v);
+}
+
+bool DeviceProfileDialog::showDialog(const QStringList &existingNames)
+{
+ m_existingNames = existingNames;
+ m_ui->m_nameLineEdit->setFocus(Qt::OtherFocusReason);
+ nameChanged(m_ui->m_nameLineEdit->text());
+ return exec() == Accepted;
+}
+
+void DeviceProfileDialog::nameChanged(const QString &name)
+{
+ const bool invalid = name.isEmpty() || m_existingNames.indexOf(name) != -1;
+ setOkButtonEnabled(!invalid);
+}
+
+void DeviceProfileDialog::save()
+{
+ QString fn = m_dlgGui->getSaveFileName(this, tr("Save Profile"), QString(), fileFilter());
+ if (fn.isEmpty())
+ return;
+ if (QFileInfo(fn).completeSuffix().isEmpty()) {
+ fn += QLatin1Char('.');
+ fn += QLatin1String(profileExtensionC);
+ }
+
+ QFile file(fn);
+ if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) {
+ critical(tr("Save Profile - Error"), tr("Unable to open the file '%1' for writing: %2").arg(fn, file.errorString()));
+ return;
+ }
+ file.write(deviceProfile().toXml().toUtf8());
+}
+
+void DeviceProfileDialog::open()
+{
+ const QString fn = m_dlgGui->getOpenFileName(this, tr("Open profile"), QString(), fileFilter());
+ if (fn.isEmpty())
+ return;
+
+ QFile file(fn);
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ critical(tr("Open Profile - Error"), tr("Unable to open the file '%1' for reading: %2").arg(fn, file.errorString()));
+ return;
+ }
+ QString errorMessage;
+ DeviceProfile newSettings;
+ if (!newSettings.fromXml(QString::fromUtf8(file.readAll()), &errorMessage)) {
+ critical(tr("Open Profile - Error"), tr("'%1' is not a valid profile: %2").arg(fn, errorMessage));
+ return;
+ }
+ setDeviceProfile(newSettings);
+}
+
+void DeviceProfileDialog::critical(const QString &title, const QString &msg)
+{
+ m_dlgGui->message(this, QDesignerDialogGuiInterface::OtherMessage, QMessageBox::Critical, title, msg);
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/deviceprofiledialog.h b/tools/designer/src/components/formeditor/deviceprofiledialog.h
new file mode 100644
index 0000000000..dafcd77f72
--- /dev/null
+++ b/tools/designer/src/components/formeditor/deviceprofiledialog.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SYSTEMSETTINGSDIALOG_H
+#define SYSTEMSETTINGSDIALOG_H
+
+#include <QtGui/QDialog>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+ class DeviceProfileDialog;
+}
+
+class QDesignerDialogGuiInterface;
+
+class QDialogButtonBox;
+
+namespace qdesigner_internal {
+
+class DeviceProfile;
+
+/* DeviceProfileDialog: Widget to edit system settings for embedded design */
+
+class DeviceProfileDialog : public QDialog
+{
+ Q_DISABLE_COPY(DeviceProfileDialog)
+ Q_OBJECT
+public:
+ explicit DeviceProfileDialog(QDesignerDialogGuiInterface *dlgGui, QWidget *parent = 0);
+ ~DeviceProfileDialog();
+
+ DeviceProfile deviceProfile() const;
+ void setDeviceProfile(const DeviceProfile &s);
+
+ bool showDialog(const QStringList &existingNames);
+
+private slots:
+ void setOkButtonEnabled(bool);
+ void nameChanged(const QString &name);
+ void save();
+ void open();
+
+private:
+ void critical(const QString &title, const QString &msg);
+ Ui::DeviceProfileDialog *m_ui;
+ QDesignerDialogGuiInterface *m_dlgGui;
+ QStringList m_existingNames;
+};
+}
+
+QT_END_NAMESPACE
+
+#endif // SYSTEMSETTINGSDIALOG_H
diff --git a/tools/designer/src/components/formeditor/deviceprofiledialog.ui b/tools/designer/src/components/formeditor/deviceprofiledialog.ui
new file mode 100644
index 0000000000..3186c5716a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/deviceprofiledialog.ui
@@ -0,0 +1,100 @@
+<ui version="4.0" >
+ <class>DeviceProfileDialog</class>
+ <widget class="QDialog" name="dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>348</width>
+ <height>209</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <widget class="QWidget" native="1" name="SystemSettingsWidget" >
+ <layout class="QFormLayout" name="formLayout" >
+ <item row="1" column="0" >
+ <widget class="QLabel" name="m_systemFontFamilyLabel" >
+ <property name="text" >
+ <string>&amp;Family</string>
+ </property>
+ <property name="buddy" >
+ <cstring>m_systemFontComboBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QFontComboBox" name="m_systemFontComboBox" />
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="m_systemFontSizeLabel" >
+ <property name="text" >
+ <string>&amp;Point Size</string>
+ </property>
+ <property name="buddy" >
+ <cstring>m_systemFontSizeCombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QComboBox" name="m_systemFontSizeCombo" />
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="m_styleLabel" >
+ <property name="text" >
+ <string>Style</string>
+ </property>
+ <property name="buddy" >
+ <cstring>m_styleCombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QComboBox" name="m_styleCombo" />
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="m_systemDPILabel" >
+ <property name="text" >
+ <string>Device DPI</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" >
+ <widget class="qdesigner_internal::DPI_Chooser" native="1" name="m_dpiChooser" />
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="m_nameLabel" >
+ <property name="text" >
+ <string>Name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="m_nameLineEdit" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Open|QDialogButtonBox::Save</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>qdesigner_internal::DPI_Chooser</class>
+ <extends>QWidget</extends>
+ <header>dpi_chooser.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/components/formeditor/dpi_chooser.cpp b/tools/designer/src/components/formeditor/dpi_chooser.cpp
new file mode 100644
index 0000000000..d766e31020
--- /dev/null
+++ b/tools/designer/src/components/formeditor/dpi_chooser.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "dpi_chooser.h"
+
+#include <deviceprofile_p.h>
+
+#include <QtGui/QComboBox>
+#include <QtGui/QSpinBox>
+#include <QtGui/QLabel>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QCheckBox>
+
+QT_BEGIN_NAMESPACE
+
+enum { minDPI = 50, maxDPI = 400 };
+
+namespace qdesigner_internal {
+
+// Entry struct for predefined values
+struct DPI_Entry {
+ int dpiX;
+ int dpiY;
+ const char *description;
+};
+
+const struct DPI_Entry dpiEntries[] = {
+ //: Embedded device standard screen resolution
+ { 96, 96, QT_TRANSLATE_NOOP("DPI_Chooser", "Standard (96 x 96)") },
+ //: Embedded device screen resolution
+ { 179, 185, QT_TRANSLATE_NOOP("DPI_Chooser", "Greenphone (179 x 185)") },
+ //: Embedded device high definition screen resolution
+ { 192, 192, QT_TRANSLATE_NOOP("DPI_Chooser", "High (192 x 192)") }
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(const struct qdesigner_internal::DPI_Entry*);
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ------------- DPI_Chooser
+
+DPI_Chooser::DPI_Chooser(QWidget *parent) :
+ QWidget(parent),
+ m_systemEntry(new DPI_Entry),
+ m_predefinedCombo(new QComboBox),
+ m_dpiXSpinBox(new QSpinBox),
+ m_dpiYSpinBox(new QSpinBox)
+{
+ // Predefined settings: System
+ DeviceProfile::systemResolution(&(m_systemEntry->dpiX), &(m_systemEntry->dpiY));
+ m_systemEntry->description = 0;
+ const struct DPI_Entry *systemEntry = m_systemEntry;
+ //: System resolution
+ m_predefinedCombo->addItem(tr("System (%1 x %2)").arg(m_systemEntry->dpiX).arg(m_systemEntry->dpiY), qVariantFromValue(systemEntry));
+ // Devices. Exclude the system values as not to duplicate the entries
+ const int predefinedCount = sizeof(dpiEntries)/sizeof(DPI_Entry);
+ const struct DPI_Entry *ecend = dpiEntries + predefinedCount;
+ for (const struct DPI_Entry *it = dpiEntries; it < ecend; ++it)
+ if (it->dpiX != m_systemEntry->dpiX || it->dpiY != m_systemEntry->dpiY)
+ m_predefinedCombo->addItem(tr(it->description), qVariantFromValue(it));
+ m_predefinedCombo->addItem(tr("User defined"));
+
+ setFocusProxy(m_predefinedCombo);
+ m_predefinedCombo->setEditable(false);
+ m_predefinedCombo->setCurrentIndex(0);
+ connect(m_predefinedCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(syncSpinBoxes()));
+ // top row with predefined settings
+ QVBoxLayout *vBoxLayout = new QVBoxLayout;
+ vBoxLayout->setMargin(0);
+ vBoxLayout->addWidget(m_predefinedCombo);
+ // Spin box row
+ QHBoxLayout *hBoxLayout = new QHBoxLayout;
+ hBoxLayout->setMargin(0);
+
+ m_dpiXSpinBox->setMinimum(minDPI);
+ m_dpiXSpinBox->setMaximum(maxDPI);
+ hBoxLayout->addWidget(m_dpiXSpinBox);
+ //: DPI X/Y separator
+ hBoxLayout->addWidget(new QLabel(tr(" x ")));
+
+ m_dpiYSpinBox->setMinimum(minDPI);
+ m_dpiYSpinBox->setMaximum(maxDPI);
+ hBoxLayout->addWidget(m_dpiYSpinBox);
+
+ hBoxLayout->addStretch();
+ vBoxLayout->addLayout(hBoxLayout);
+ setLayout(vBoxLayout);
+
+ syncSpinBoxes();
+}
+
+DPI_Chooser::~DPI_Chooser()
+{
+ delete m_systemEntry;
+}
+
+void DPI_Chooser::getDPI(int *dpiX, int *dpiY) const
+{
+ *dpiX = m_dpiXSpinBox->value();
+ *dpiY = m_dpiYSpinBox->value();
+}
+
+void DPI_Chooser::setDPI(int dpiX, int dpiY)
+{
+ // Default to system if it is something weird
+ const bool valid = dpiX >= minDPI && dpiX <= maxDPI && dpiY >= minDPI && dpiY <= maxDPI;
+ if (!valid) {
+ m_predefinedCombo->setCurrentIndex(0);
+ return;
+ }
+ // Try to find the values among the predefined settings
+ const int count = m_predefinedCombo->count();
+ int predefinedIndex = -1;
+ for (int i = 0; i < count; i++) {
+ const QVariant data = m_predefinedCombo->itemData(i);
+ if (data.type() != QVariant::Invalid) {
+ const struct DPI_Entry *entry = qvariant_cast<const struct DPI_Entry *>(data);
+ if (entry->dpiX == dpiX && entry->dpiY == dpiY) {
+ predefinedIndex = i;
+ break;
+ }
+ }
+ }
+ if (predefinedIndex != -1) {
+ m_predefinedCombo->setCurrentIndex(predefinedIndex); // triggers syncSpinBoxes()
+ } else {
+ setUserDefinedValues(dpiX, dpiY);
+ }
+}
+
+void DPI_Chooser::setUserDefinedValues(int dpiX, int dpiY)
+{
+ const bool blocked = m_predefinedCombo->blockSignals(true);
+ m_predefinedCombo->setCurrentIndex(m_predefinedCombo->count() - 1);
+ m_predefinedCombo->blockSignals(blocked);
+
+ m_dpiXSpinBox->setEnabled(true);
+ m_dpiYSpinBox->setEnabled(true);
+ m_dpiXSpinBox->setValue(dpiX);
+ m_dpiYSpinBox->setValue(dpiY);
+}
+
+void DPI_Chooser::syncSpinBoxes()
+{
+ const int predefIdx = m_predefinedCombo->currentIndex();
+ const QVariant data = m_predefinedCombo->itemData(predefIdx);
+
+ // Predefined mode in which spin boxes are disabled or user defined?
+ const bool userSetting = data.type() == QVariant::Invalid;
+ m_dpiXSpinBox->setEnabled(userSetting);
+ m_dpiYSpinBox->setEnabled(userSetting);
+
+ if (!userSetting) {
+ const struct DPI_Entry *entry = qvariant_cast<const struct DPI_Entry *>(data);
+ m_dpiXSpinBox->setValue(entry->dpiX);
+ m_dpiYSpinBox->setValue(entry->dpiY);
+ }
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/dpi_chooser.h b/tools/designer/src/components/formeditor/dpi_chooser.h
new file mode 100644
index 0000000000..f8ca81043a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/dpi_chooser.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef DPICHOOSER_H
+#define DPICHOOSER_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QSpinBox;
+class QComboBox;
+
+namespace qdesigner_internal {
+
+struct DPI_Entry;
+
+/* Let the user choose a DPI settings */
+class DPI_Chooser : public QWidget {
+ Q_DISABLE_COPY(DPI_Chooser)
+ Q_OBJECT
+
+public:
+ explicit DPI_Chooser(QWidget *parent = 0);
+ ~DPI_Chooser();
+
+ void getDPI(int *dpiX, int *dpiY) const;
+ void setDPI(int dpiX, int dpiY);
+
+private slots:
+ void syncSpinBoxes();
+
+private:
+ void setUserDefinedValues(int dpiX, int dpiY);
+
+ struct DPI_Entry *m_systemEntry;
+ QComboBox *m_predefinedCombo;
+ QSpinBox *m_dpiXSpinBox;
+ QSpinBox *m_dpiYSpinBox;
+};
+}
+
+QT_END_NAMESPACE
+
+#endif // DPICHOOSER_H
diff --git a/tools/designer/src/components/formeditor/embeddedoptionspage.cpp b/tools/designer/src/components/formeditor/embeddedoptionspage.cpp
new file mode 100644
index 0000000000..bf3f3f1ab0
--- /dev/null
+++ b/tools/designer/src/components/formeditor/embeddedoptionspage.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::EmbeddedOptionsControl
+*/
+
+#include "embeddedoptionspage.h"
+#include "deviceprofiledialog.h"
+#include "widgetfactory_p.h"
+#include "formwindowmanager.h"
+
+#include <deviceprofile_p.h>
+#include <iconloader_p.h>
+#include <shared_settings_p.h>
+#include <abstractdialoggui_p.h>
+#include <formwindowbase_p.h>
+
+
+// SDK
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <QtGui/QLabel>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QComboBox>
+#include <QtGui/QToolButton>
+#include <QtGui/QMessageBox>
+#include <QtGui/QLabel>
+#include <QtGui/QGroupBox>
+
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+typedef QList<DeviceProfile> DeviceProfileList;
+
+enum { profileComboIndexOffset = 1 };
+
+// Sort by name. Used by template, do not make it static!
+bool deviceProfileLessThan(const DeviceProfile &d1, const DeviceProfile &d2)
+{
+ return d1.name().toLower() < d2.name().toLower();
+}
+
+static bool ask(QWidget *parent,
+ QDesignerDialogGuiInterface *dlgui,
+ const QString &title,
+ const QString &what)
+{
+ return dlgui->message(parent, QDesignerDialogGuiInterface::OtherMessage,
+ QMessageBox::Question, title, what,
+ QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes;
+}
+
+// ------------ EmbeddedOptionsControlPrivate
+class EmbeddedOptionsControlPrivate {
+ Q_DISABLE_COPY(EmbeddedOptionsControlPrivate)
+public:
+ EmbeddedOptionsControlPrivate(QDesignerFormEditorInterface *core);
+ void init(EmbeddedOptionsControl *q);
+
+ bool isDirty() const { return m_dirty; }
+
+ void loadSettings();
+ void saveSettings();
+ void slotAdd();
+ void slotEdit();
+ void slotDelete();
+ void slotProfileIndexChanged(int);
+
+private:
+ QStringList existingProfileNames() const;
+ void sortAndPopulateProfileCombo();
+ void updateState();
+ void updateDescriptionLabel();
+
+ QDesignerFormEditorInterface *m_core;
+ QComboBox *m_profileCombo;
+ QToolButton *m_addButton;
+ QToolButton *m_editButton;
+ QToolButton *m_deleteButton;
+ QLabel *m_descriptionLabel;
+
+ DeviceProfileList m_sortedProfiles;
+ EmbeddedOptionsControl *m_q;
+ bool m_dirty;
+ QSet<QString> m_usedProfiles;
+};
+
+EmbeddedOptionsControlPrivate::EmbeddedOptionsControlPrivate(QDesignerFormEditorInterface *core) :
+ m_core(core),
+ m_profileCombo(new QComboBox),
+ m_addButton(new QToolButton),
+ m_editButton(new QToolButton),
+ m_deleteButton(new QToolButton),
+ m_descriptionLabel(new QLabel),
+ m_q(0),
+ m_dirty(false)
+{
+ m_descriptionLabel->setMinimumHeight(80);
+ // Determine used profiles to lock them
+ const QDesignerFormWindowManagerInterface *fwm = core->formWindowManager();
+ if (const int fwCount = fwm->formWindowCount()) {
+ for (int i = 0; i < fwCount; i++)
+ if (const FormWindowBase *fwb = qobject_cast<const FormWindowBase *>(fwm->formWindow(i))) {
+ const QString deviceProfileName = fwb->deviceProfileName();
+ if (!deviceProfileName.isEmpty())
+ m_usedProfiles.insert(deviceProfileName);
+ }
+ }
+}
+
+void EmbeddedOptionsControlPrivate::init(EmbeddedOptionsControl *q)
+{
+ m_q = q;
+ QVBoxLayout *vLayout = new QVBoxLayout;
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ m_profileCombo->setMinimumWidth(200);
+ m_profileCombo->setEditable(false);
+ hLayout->addWidget(m_profileCombo);
+ m_profileCombo->addItem(EmbeddedOptionsControl::tr("None"));
+ EmbeddedOptionsControl::connect(m_profileCombo, SIGNAL(currentIndexChanged(int)), m_q, SLOT(slotProfileIndexChanged(int)));
+
+ m_addButton->setIcon(createIconSet(QString::fromUtf8("plus.png")));
+ m_addButton->setToolTip(EmbeddedOptionsControl::tr("Add a profile"));
+ EmbeddedOptionsControl::connect(m_addButton, SIGNAL(clicked()), m_q, SLOT(slotAdd()));
+ hLayout->addWidget(m_addButton);
+
+ EmbeddedOptionsControl::connect(m_editButton, SIGNAL(clicked()), m_q, SLOT(slotEdit()));
+ m_editButton->setIcon(createIconSet(QString::fromUtf8("edit.png")));
+ m_editButton->setToolTip(EmbeddedOptionsControl::tr("Edit the selected profile"));
+ hLayout->addWidget(m_editButton);
+
+ m_deleteButton->setIcon(createIconSet(QString::fromUtf8("minus.png")));
+ m_deleteButton->setToolTip(EmbeddedOptionsControl::tr("Delete the selected profile"));
+ EmbeddedOptionsControl::connect(m_deleteButton, SIGNAL(clicked()), m_q, SLOT(slotDelete()));
+ hLayout->addWidget(m_deleteButton);
+
+ hLayout->addStretch();
+ vLayout->addLayout(hLayout);
+ vLayout->addWidget(m_descriptionLabel);
+ m_q->setLayout(vLayout);
+}
+
+QStringList EmbeddedOptionsControlPrivate::existingProfileNames() const
+{
+ QStringList rc;
+ const DeviceProfileList::const_iterator dcend = m_sortedProfiles.constEnd();
+ for (DeviceProfileList::const_iterator it = m_sortedProfiles.constBegin(); it != dcend; ++it)
+ rc.push_back(it->name());
+ return rc;
+}
+
+void EmbeddedOptionsControlPrivate::slotAdd()
+{
+ DeviceProfileDialog dlg(m_core->dialogGui(), m_q);
+ dlg.setWindowTitle(EmbeddedOptionsControl::tr("Add Profile"));
+ // Create a new profile with a new, unique name
+ DeviceProfile settings;
+ settings.fromSystem();
+ dlg.setDeviceProfile(settings);
+
+ const QStringList names = existingProfileNames();
+ const QString newNamePrefix = EmbeddedOptionsControl::tr("New profile");
+ QString newName = newNamePrefix;
+ for (int i = 2; names.contains(newName); i++) {
+ newName = newNamePrefix;
+ newName += QString::number(i);
+ }
+
+ settings.setName(newName);
+ dlg.setDeviceProfile(settings);
+ if (dlg.showDialog(names)) {
+ const DeviceProfile newProfile = dlg.deviceProfile();
+ m_sortedProfiles.push_back(newProfile);
+ // Maintain sorted order
+ sortAndPopulateProfileCombo();
+ const int index = m_profileCombo->findText(newProfile.name());
+ m_profileCombo->setCurrentIndex(index);
+ m_dirty = true;
+ }
+}
+
+void EmbeddedOptionsControlPrivate::slotEdit()
+{
+ const int index = m_profileCombo->currentIndex() - profileComboIndexOffset;
+ if (index < 0)
+ return;
+
+ // Edit the profile, compile a list of existing names
+ // excluding current one. re-insert if changed,
+ // re-sort if name changed.
+ const DeviceProfile oldProfile = m_sortedProfiles.at(index);
+ const QString oldName = oldProfile.name();
+ QStringList names = existingProfileNames();
+ names.removeAll(oldName);
+
+ DeviceProfileDialog dlg(m_core->dialogGui(), m_q);
+ dlg.setWindowTitle(EmbeddedOptionsControl::tr("Edit Profile"));
+ dlg.setDeviceProfile(oldProfile);
+ if (dlg.showDialog(names)) {
+ const DeviceProfile newProfile = dlg.deviceProfile();
+ if (newProfile != oldProfile) {
+ m_dirty = true;
+ m_sortedProfiles[index] = newProfile;
+ if (newProfile.name() != oldName) {
+ sortAndPopulateProfileCombo();
+ const int index = m_profileCombo->findText(newProfile.name());
+ m_profileCombo->setCurrentIndex(index);
+ } else {
+ updateDescriptionLabel();
+ }
+
+ }
+ }
+}
+
+void EmbeddedOptionsControlPrivate::slotDelete()
+{
+ const int index = m_profileCombo->currentIndex() - profileComboIndexOffset;
+ if (index < 0)
+ return;
+ const QString name = m_sortedProfiles.at(index).name();
+ if (ask(m_q, m_core->dialogGui(),
+ EmbeddedOptionsControl::tr("Delete Profile"),
+ EmbeddedOptionsControl::tr("Would you like to delete the profile '%1'?").arg(name))) {
+ m_profileCombo->setCurrentIndex(0);
+ m_sortedProfiles.removeAt(index);
+ m_profileCombo->removeItem(index + profileComboIndexOffset);
+ m_dirty = true;
+ }
+}
+
+void EmbeddedOptionsControlPrivate::sortAndPopulateProfileCombo()
+{
+ // Clear items until only "None" is left
+ for (int i = m_profileCombo->count() - 1; i > 0; i--)
+ m_profileCombo->removeItem(i);
+ if (!m_sortedProfiles.empty()) {
+ qSort(m_sortedProfiles.begin(), m_sortedProfiles.end(), deviceProfileLessThan);
+ m_profileCombo->addItems(existingProfileNames());
+ }
+}
+
+void EmbeddedOptionsControlPrivate::loadSettings()
+{
+ const QDesignerSharedSettings settings(m_core);
+ m_sortedProfiles = settings.deviceProfiles();
+ sortAndPopulateProfileCombo();
+ // Index: 0 is "None"
+ const int settingsIndex = settings.currentDeviceProfileIndex();
+ const int profileIndex = settingsIndex >= 0 && settingsIndex < m_sortedProfiles.size() ? settingsIndex + profileComboIndexOffset : 0;
+ m_profileCombo->setCurrentIndex(profileIndex);
+ updateState();
+ m_dirty = false;
+}
+
+void EmbeddedOptionsControlPrivate::saveSettings()
+{
+ QDesignerSharedSettings settings(m_core);
+ settings.setDeviceProfiles(m_sortedProfiles);
+ // Index: 0 is "None"
+ settings.setCurrentDeviceProfileIndex(m_profileCombo->currentIndex() - profileComboIndexOffset);
+ m_dirty = false;
+}
+
+//: Format embedded device profile description
+static const char *descriptionFormat = QT_TRANSLATE_NOOP("EmbeddedOptionsControl",
+"<html>"
+"<table>"
+"<tr><td><b>Font</b></td><td>%1, %2</td></tr>"
+"<tr><td><b>Style</b></td><td>%3</td></tr>"
+"<tr><td><b>Resolution</b></td><td>%4 x %5</td></tr>"
+"</table>"
+"</html>");
+
+static inline QString description(const DeviceProfile& p)
+{
+ QString styleName = p.style();
+ if (styleName.isEmpty())
+ styleName = EmbeddedOptionsControl::tr("Default");
+ return EmbeddedOptionsControl::tr(descriptionFormat).
+ arg(p.fontFamily()).arg(p.fontPointSize()).arg(styleName).arg(p.dpiX()).arg(p.dpiY());
+}
+
+void EmbeddedOptionsControlPrivate::updateDescriptionLabel()
+{
+ const int profileIndex = m_profileCombo->currentIndex() - profileComboIndexOffset;
+ if (profileIndex >= 0) {
+ m_descriptionLabel->setText(description(m_sortedProfiles.at(profileIndex)));
+ } else {
+ m_descriptionLabel->clear();
+ }
+}
+
+void EmbeddedOptionsControlPrivate::updateState()
+{
+ const int profileIndex = m_profileCombo->currentIndex() - profileComboIndexOffset;
+ // Allow for changing/deleting only if it is not in use
+ bool modifyEnabled = false;
+ if (profileIndex >= 0)
+ modifyEnabled = !m_usedProfiles.contains(m_sortedProfiles.at(profileIndex).name());
+ m_editButton->setEnabled(modifyEnabled);
+ m_deleteButton->setEnabled(modifyEnabled);
+ updateDescriptionLabel();
+}
+
+void EmbeddedOptionsControlPrivate::slotProfileIndexChanged(int)
+{
+ updateState();
+ m_dirty = true;
+}
+
+// ------------- EmbeddedOptionsControl
+EmbeddedOptionsControl::EmbeddedOptionsControl(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QWidget(parent),
+ m_d(new EmbeddedOptionsControlPrivate(core))
+{
+ m_d->init(this);
+}
+
+EmbeddedOptionsControl::~EmbeddedOptionsControl()
+{
+ delete m_d;
+}
+
+void EmbeddedOptionsControl::slotAdd()
+{
+ m_d->slotAdd();
+}
+
+void EmbeddedOptionsControl::slotEdit()
+{
+ m_d->slotEdit();
+}
+
+void EmbeddedOptionsControl::slotDelete()
+{
+ m_d->slotDelete();
+}
+
+void EmbeddedOptionsControl::loadSettings()
+{
+ m_d->loadSettings();
+}
+
+void EmbeddedOptionsControl::saveSettings()
+{
+ m_d->saveSettings();
+}
+
+void EmbeddedOptionsControl::slotProfileIndexChanged(int i)
+{
+ m_d->slotProfileIndexChanged(i);
+}
+
+bool EmbeddedOptionsControl::isDirty() const
+{
+ return m_d->isDirty();
+}
+
+// EmbeddedOptionsPage:
+EmbeddedOptionsPage::EmbeddedOptionsPage(QDesignerFormEditorInterface *core) :
+ m_core(core)
+{
+}
+
+QString EmbeddedOptionsPage::name() const
+{
+ //: Tab in preferences dialog
+ return QCoreApplication::translate("EmbeddedOptionsPage", "Embedded Design");
+}
+
+QWidget *EmbeddedOptionsPage::createPage(QWidget *parent)
+{
+ QWidget *optionsWidget = new QWidget(parent);
+
+ QVBoxLayout *optionsVLayout = new QVBoxLayout();
+
+ //: EmbeddedOptionsControl group box"
+ QGroupBox *gb = new QGroupBox(QCoreApplication::translate("EmbeddedOptionsPage", "Device Profiles"));
+ QVBoxLayout *gbVLayout = new QVBoxLayout();
+ m_embeddedOptionsControl = new EmbeddedOptionsControl(m_core);
+ m_embeddedOptionsControl->loadSettings();
+ gbVLayout->addWidget(m_embeddedOptionsControl);
+ gb->setLayout(gbVLayout);
+ optionsVLayout->addWidget(gb);
+
+ optionsVLayout->addStretch(1);
+
+ // Outer layout to give it horizontal stretch
+ QHBoxLayout *optionsHLayout = new QHBoxLayout();
+ optionsHLayout->addLayout(optionsVLayout);
+ optionsHLayout->addStretch(1);
+ optionsWidget->setLayout(optionsHLayout);
+ return optionsWidget;
+}
+
+void EmbeddedOptionsPage::apply()
+{
+ if (!m_embeddedOptionsControl || !m_embeddedOptionsControl->isDirty())
+ return;
+
+ m_embeddedOptionsControl->saveSettings();
+ if (FormWindowManager *fw = qobject_cast<qdesigner_internal::FormWindowManager *>(m_core->formWindowManager()))
+ fw->deviceProfilesChanged();
+}
+
+void EmbeddedOptionsPage::finish()
+{
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/embeddedoptionspage.h b/tools/designer/src/components/formeditor/embeddedoptionspage.h
new file mode 100644
index 0000000000..6b76d38bcb
--- /dev/null
+++ b/tools/designer/src/components/formeditor/embeddedoptionspage.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EMBEDDEDOPTIONSPAGE_H
+#define EMBEDDEDOPTIONSPAGE_H
+
+#include <QtDesigner/private/abstractoptionspage_p.h>
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class EmbeddedOptionsControlPrivate;
+
+/* EmbeddedOptions Control. Presents the user with a list of embedded
+ * device profiles he can modify/add/delete. */
+class EmbeddedOptionsControl : public QWidget {
+ Q_DISABLE_COPY(EmbeddedOptionsControl)
+ Q_OBJECT
+public:
+ explicit EmbeddedOptionsControl(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ ~EmbeddedOptionsControl();
+
+ bool isDirty() const;
+
+public slots:
+ void loadSettings();
+ void saveSettings();
+
+private slots:
+ void slotAdd();
+ void slotEdit();
+ void slotDelete();
+ void slotProfileIndexChanged(int);
+
+private:
+ EmbeddedOptionsControlPrivate *m_d;
+};
+
+// EmbeddedOptionsPage
+class EmbeddedOptionsPage : public QDesignerOptionsPageInterface
+{
+ Q_DISABLE_COPY(EmbeddedOptionsPage)
+public:
+ explicit EmbeddedOptionsPage(QDesignerFormEditorInterface *core);
+
+ QString name() const;
+ QWidget *createPage(QWidget *parent);
+ virtual void finish();
+ virtual void apply();
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ QPointer<EmbeddedOptionsControl> m_embeddedOptionsControl;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // EMBEDDEDOPTIONSPAGE_H
diff --git a/tools/designer/src/components/formeditor/formeditor.cpp b/tools/designer/src/components/formeditor/formeditor.cpp
new file mode 100644
index 0000000000..b09ffabaa4
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formeditor.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formeditor.h"
+#include "formeditor_optionspage.h"
+#include "embeddedoptionspage.h"
+#include "templateoptionspage.h"
+#include "metadatabase_p.h"
+#include "widgetdatabase_p.h"
+#include "widgetfactory_p.h"
+#include "formwindowmanager.h"
+#include "qmainwindow_container.h"
+#include "qworkspace_container.h"
+#include "qmdiarea_container.h"
+#include "qwizard_container.h"
+#include "default_container.h"
+#include "default_layoutdecoration.h"
+#include "default_actionprovider.h"
+#include "qlayoutwidget_propertysheet.h"
+#include "spacer_propertysheet.h"
+#include "line_propertysheet.h"
+#include "layout_propertysheet.h"
+#include "qdesigner_stackedbox_p.h"
+#include "qdesigner_toolbox_p.h"
+#include "qdesigner_tabwidget_p.h"
+#include "qtbrushmanager.h"
+#include "brushmanagerproxy.h"
+#include "iconcache.h"
+#include "qtresourcemodel_p.h"
+#include "qdesigner_integration_p.h"
+#include "itemview_propertysheet.h"
+
+// sdk
+#include <QtDesigner/QExtensionManager>
+
+// shared
+#include <pluginmanager_p.h>
+#include <qdesigner_taskmenu_p.h>
+#include <qdesigner_membersheet_p.h>
+#include <qdesigner_promotion_p.h>
+#include <dialoggui_p.h>
+#include <qdesigner_introspection_p.h>
+#include <qdesigner_qsettings_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+FormEditor::FormEditor(QObject *parent)
+ : QDesignerFormEditorInterface(parent)
+{
+ setIntrospection(new QDesignerIntrospection);
+ setDialogGui(new DialogGui);
+ QDesignerPluginManager *pluginManager = new QDesignerPluginManager(this);
+ setPluginManager(pluginManager);
+
+ WidgetDataBase *widgetDatabase = new WidgetDataBase(this, this);
+ setWidgetDataBase(widgetDatabase);
+
+ MetaDataBase *metaDataBase = new MetaDataBase(this, this);
+ setMetaDataBase(metaDataBase);
+
+ WidgetFactory *widgetFactory = new WidgetFactory(this, this);
+ setWidgetFactory(widgetFactory);
+
+ FormWindowManager *formWindowManager = new FormWindowManager(this, this);
+ setFormManager(formWindowManager);
+ connect(formWindowManager, SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)), widgetFactory, SLOT(formWindowAdded(QDesignerFormWindowInterface*)));
+ connect(formWindowManager, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)), widgetFactory, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
+
+ QExtensionManager *mgr = new QExtensionManager(this);
+ const QString containerExtensionId = Q_TYPEID(QDesignerContainerExtension);
+
+ QDesignerStackedWidgetContainerFactory::registerExtension(mgr, containerExtensionId);
+ QDesignerTabWidgetContainerFactory::registerExtension(mgr, containerExtensionId);
+ QDesignerToolBoxContainerFactory::registerExtension(mgr, containerExtensionId);
+ QMainWindowContainerFactory::registerExtension(mgr, containerExtensionId);
+ QDockWidgetContainerFactory::registerExtension(mgr, containerExtensionId);
+ QScrollAreaContainerFactory::registerExtension(mgr, containerExtensionId);
+ QWorkspaceContainerFactory::registerExtension(mgr, containerExtensionId);
+ QMdiAreaContainerFactory::registerExtension(mgr, containerExtensionId);
+ QWizardContainerFactory::registerExtension(mgr, containerExtensionId);
+
+ mgr->registerExtensions(new QDesignerLayoutDecorationFactory(mgr),
+ Q_TYPEID(QDesignerLayoutDecorationExtension));
+
+ const QString actionProviderExtensionId = Q_TYPEID(QDesignerActionProviderExtension);
+ QToolBarActionProviderFactory::registerExtension(mgr, actionProviderExtensionId);
+ QMenuBarActionProviderFactory::registerExtension(mgr, actionProviderExtensionId);
+ QMenuActionProviderFactory::registerExtension(mgr, actionProviderExtensionId);
+
+ QDesignerDefaultPropertySheetFactory::registerExtension(mgr);
+ QLayoutWidgetPropertySheetFactory::registerExtension(mgr);
+ SpacerPropertySheetFactory::registerExtension(mgr);
+ LinePropertySheetFactory::registerExtension(mgr);
+ LayoutPropertySheetFactory::registerExtension(mgr);
+ QStackedWidgetPropertySheetFactory::registerExtension(mgr);
+ QToolBoxWidgetPropertySheetFactory::registerExtension(mgr);
+ QTabWidgetPropertySheetFactory::registerExtension(mgr);
+ QMdiAreaPropertySheetFactory::registerExtension(mgr);
+ QWorkspacePropertySheetFactory::registerExtension(mgr);
+ QWizardPagePropertySheetFactory::registerExtension(mgr);
+ QWizardPropertySheetFactory::registerExtension(mgr);
+
+ QTreeViewPropertySheetFactory::registerExtension(mgr);
+ QTableViewPropertySheetFactory::registerExtension(mgr);
+
+ const QString internalTaskMenuId = QLatin1String("QDesignerInternalTaskMenuExtension");
+ QDesignerTaskMenuFactory::registerExtension(mgr, internalTaskMenuId);
+
+ mgr->registerExtensions(new QDesignerMemberSheetFactory(mgr),
+ Q_TYPEID(QDesignerMemberSheetExtension));
+
+ setExtensionManager(mgr);
+
+ setIconCache(new IconCache(this));
+
+ QtBrushManager *brushManager = new QtBrushManager(this);
+ setBrushManager(brushManager);
+
+ BrushManagerProxy *brushProxy = new BrushManagerProxy(this, this);
+ brushProxy->setBrushManager(brushManager);
+ setPromotion(new QDesignerPromotion(this));
+
+ QtResourceModel *resourceModel = new QtResourceModel(this);
+ setResourceModel(resourceModel);
+ connect(resourceModel, SIGNAL(qrcFileModifiedExternally(const QString &)),
+ this, SLOT(slotQrcFileChangedExternally(const QString &)));
+
+ QList<QDesignerOptionsPageInterface*> optionsPages;
+ optionsPages << new TemplateOptionsPage(this) << new FormEditorOptionsPage(this) << new EmbeddedOptionsPage(this);
+ setOptionsPages(optionsPages);
+
+ setSettingsManager(new QDesignerQSettings());
+}
+
+FormEditor::~FormEditor()
+{
+}
+
+void FormEditor::slotQrcFileChangedExternally(const QString &path)
+{
+ QDesignerIntegration *designerIntegration = qobject_cast<QDesignerIntegration *>(integration());
+ if (!designerIntegration)
+ return;
+
+ QDesignerIntegration::ResourceFileWatcherBehaviour behaviour = designerIntegration->resourceFileWatcherBehaviour();
+ if (behaviour == QDesignerIntegration::NoWatcher) {
+ return;
+ } else if (behaviour == QDesignerIntegration::PromptAndReload) {
+ QMessageBox::StandardButton button = dialogGui()->message(topLevel(), QDesignerDialogGuiInterface::FileChangedMessage, QMessageBox::Warning,
+ tr("Resource File Changed"),
+ tr("The file \"%1\" has changed outside Designer. Do you want to reload it?").arg(path),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+
+ if (button != QMessageBox::Yes)
+ return;
+ }
+
+ resourceModel()->reload(path);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formeditor.h b/tools/designer/src/components/formeditor/formeditor.h
new file mode 100644
index 0000000000..2e0b819e92
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formeditor.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMEDITOR_H
+#define FORMEDITOR_H
+
+#include "formeditor_global.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+
+namespace qdesigner_internal {
+
+class QT_FORMEDITOR_EXPORT FormEditor: public QDesignerFormEditorInterface
+{
+ Q_OBJECT
+public:
+ FormEditor(QObject *parent = 0);
+ virtual ~FormEditor();
+public slots:
+ void slotQrcFileChangedExternally(const QString &path);
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMEDITOR_H
diff --git a/tools/designer/src/components/formeditor/formeditor.pri b/tools/designer/src/components/formeditor/formeditor.pri
new file mode 100644
index 0000000000..bbe96d5ca8
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formeditor.pri
@@ -0,0 +1,75 @@
+
+QT += xml
+
+INCLUDEPATH += $$PWD
+
+FORMS += $$PWD/deviceprofiledialog.ui \
+ $$PWD/formwindowsettings.ui \
+ $$PWD/templateoptionspage.ui
+
+HEADERS += $$PWD/qdesigner_resource.h \
+ $$PWD/formwindow.h \
+ $$PWD/formwindow_widgetstack.h \
+ $$PWD/formwindow_dnditem.h \
+ $$PWD/formwindowcursor.h \
+ $$PWD/widgetselection.h \
+ $$PWD/formwindowmanager.h \
+ $$PWD/formeditor.h \
+ $$PWD/formeditor_global.h \
+ $$PWD/qlayoutwidget_propertysheet.h \
+ $$PWD/layout_propertysheet.h \
+ $$PWD/spacer_propertysheet.h \
+ $$PWD/line_propertysheet.h \
+ $$PWD/default_container.h \
+ $$PWD/default_actionprovider.h \
+ $$PWD/qmainwindow_container.h \
+ $$PWD/qworkspace_container.h \
+ $$PWD/qmdiarea_container.h \
+ $$PWD/qwizard_container.h \
+ $$PWD/default_layoutdecoration.h \
+ $$PWD/qtbrushmanager.h \
+ $$PWD/brushmanagerproxy.h \
+ $$PWD/iconcache.h \
+ $$PWD/tool_widgeteditor.h \
+ $$PWD/formeditor_optionspage.h \
+ $$PWD/embeddedoptionspage.h \
+ $$PWD/formwindowsettings.h \
+ $$PWD/deviceprofiledialog.h \
+ $$PWD/dpi_chooser.h \
+ $$PWD/previewactiongroup.h \
+ $$PWD/itemview_propertysheet.h \
+ $$PWD/templateoptionspage.h
+
+SOURCES += $$PWD/qdesigner_resource.cpp \
+ $$PWD/formwindow.cpp \
+ $$PWD/formwindow_widgetstack.cpp \
+ $$PWD/formwindow_dnditem.cpp \
+ $$PWD/formwindowcursor.cpp \
+ $$PWD/widgetselection.cpp \
+ $$PWD/formwindowmanager.cpp \
+ $$PWD/formeditor.cpp \
+ $$PWD/qlayoutwidget_propertysheet.cpp \
+ $$PWD/layout_propertysheet.cpp \
+ $$PWD/spacer_propertysheet.cpp \
+ $$PWD/line_propertysheet.cpp \
+ $$PWD/qmainwindow_container.cpp \
+ $$PWD/qworkspace_container.cpp \
+ $$PWD/qmdiarea_container.cpp \
+ $$PWD/qwizard_container.cpp \
+ $$PWD/default_container.cpp \
+ $$PWD/default_layoutdecoration.cpp \
+ $$PWD/default_actionprovider.cpp \
+ $$PWD/tool_widgeteditor.cpp \
+ $$PWD/qtbrushmanager.cpp \
+ $$PWD/brushmanagerproxy.cpp \
+ $$PWD/iconcache.cpp \
+ $$PWD/formeditor_optionspage.cpp \
+ $$PWD/embeddedoptionspage.cpp \
+ $$PWD/formwindowsettings.cpp \
+ $$PWD/deviceprofiledialog.cpp \
+ $$PWD/dpi_chooser.cpp \
+ $$PWD/previewactiongroup.cpp \
+ $$PWD/itemview_propertysheet.cpp \
+ $$PWD/templateoptionspage.cpp
+
+RESOURCES += $$PWD/formeditor.qrc
diff --git a/tools/designer/src/components/formeditor/formeditor.qrc b/tools/designer/src/components/formeditor/formeditor.qrc
new file mode 100644
index 0000000000..83cc9c789d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formeditor.qrc
@@ -0,0 +1,173 @@
+<RCC>
+ <qresource prefix="/trolltech/formeditor">
+ <file>images/submenu.png</file>
+ <file>images/cursors/arrow.png</file>
+ <file>images/cursors/busy.png</file>
+ <file>images/cursors/closedhand.png</file>
+ <file>images/cursors/cross.png</file>
+ <file>images/cursors/hand.png</file>
+ <file>images/cursors/hsplit.png</file>
+ <file>images/cursors/ibeam.png</file>
+ <file>images/cursors/no.png</file>
+ <file>images/cursors/openhand.png</file>
+ <file>images/cursors/sizeall.png</file>
+ <file>images/cursors/sizeb.png</file>
+ <file>images/cursors/sizef.png</file>
+ <file>images/cursors/sizeh.png</file>
+ <file>images/cursors/sizev.png</file>
+ <file>images/cursors/uparrow.png</file>
+ <file>images/cursors/vsplit.png</file>
+ <file>images/cursors/wait.png</file>
+ <file>images/cursors/whatsthis.png</file>
+ <file>images/emptyicon.png</file>
+ <file>images/filenew-16.png</file>
+ <file>images/fileopen-16.png</file>
+ <file>images/editdelete-16.png</file>
+ <file>images/plus-16.png</file>
+ <file>images/minus-16.png</file>
+ <file>images/prefix-add.png</file>
+ <file>images/downplus.png</file>
+ <file>images/leveldown.png</file>
+ <file>images/levelup.png</file>
+ <file>images/mac/adjustsize.png</file>
+ <file>images/mac/widgettool.png</file>
+ <file>images/mac/signalslottool.png</file>
+ <file>images/mac/tabordertool.png</file>
+ <file>images/mac/buddytool.png</file>
+ <file>images/mac/editbreaklayout.png</file>
+ <file>images/mac/editcopy.png</file>
+ <file>images/mac/editcut.png</file>
+ <file>images/mac/editdelete.png</file>
+ <file>images/mac/editgrid.png</file>
+ <file>images/mac/editform.png</file>
+ <file>images/mac/edithlayout.png</file>
+ <file>images/mac/edithlayoutsplit.png</file>
+ <file>images/mac/editlower.png</file>
+ <file>images/mac/editpaste.png</file>
+ <file>images/mac/editraise.png</file>
+ <file>images/mac/editvlayout.png</file>
+ <file>images/mac/editvlayoutsplit.png</file>
+ <file>images/mac/filenew.png</file>
+ <file>images/mac/insertimage.png</file>
+ <file>images/mac/undo.png</file>
+ <file>images/mac/redo.png</file>
+ <file>images/mac/fileopen.png</file>
+ <file>images/mac/filesave.png</file>
+ <file>images/mac/resourceeditortool.png</file>
+ <file>images/mac/plus.png</file>
+ <file>images/mac/minus.png</file>
+ <file>images/mac/back.png</file>
+ <file>images/mac/forward.png</file>
+ <file>images/mac/down.png</file>
+ <file>images/mac/up.png</file>
+ <file>images/qtlogo.png</file>
+ <file>images/qt3logo.png</file>
+ <file>images/resetproperty.png</file>
+ <file>images/sort.png</file>
+ <file>images/edit.png</file>
+ <file>images/reload.png</file>
+ <file>images/configure.png</file>
+ <file>images/color.png</file>
+ <file>images/dropdownbutton.png</file>
+ <file>images/widgets/calendarwidget.png</file>
+ <file>images/widgets/checkbox.png</file>
+ <file>images/widgets/columnview.png</file>
+ <file>images/widgets/combobox.png</file>
+ <file>images/widgets/commandlinkbutton.png</file>
+ <file>images/widgets/dateedit.png</file>
+ <file>images/widgets/datetimeedit.png</file>
+ <file>images/widgets/dial.png</file>
+ <file>images/widgets/dialogbuttonbox.png</file>
+ <file>images/widgets/dockwidget.png</file>
+ <file>images/widgets/doublespinbox.png</file>
+ <file>images/widgets/fontcombobox.png</file>
+ <file>images/widgets/frame.png</file>
+ <file>images/widgets/graphicsview.png</file>
+ <file>images/widgets/groupbox.png</file>
+ <file>images/widgets/hscrollbar.png</file>
+ <file>images/widgets/hslider.png</file>
+ <file>images/widgets/hsplit.png</file>
+ <file>images/widgets/label.png</file>
+ <file>images/widgets/lcdnumber.png</file>
+ <file>images/widgets/line.png</file>
+ <file>images/widgets/lineedit.png</file>
+ <file>images/widgets/listbox.png</file>
+ <file>images/widgets/listview.png</file>
+ <file>images/widgets/mdiarea.png</file>
+ <file>images/widgets/plaintextedit.png</file>
+ <file>images/widgets/progress.png</file>
+ <file>images/widgets/pushbutton.png</file>
+ <file>images/widgets/radiobutton.png</file>
+ <file>images/widgets/scrollarea.png</file>
+ <file>images/widgets/spacer.png</file>
+ <file>images/widgets/spinbox.png</file>
+ <file>images/widgets/table.png</file>
+ <file>images/widgets/tabwidget.png</file>
+ <file>images/widgets/textedit.png</file>
+ <file>images/widgets/timeedit.png</file>
+ <file>images/widgets/toolbox.png</file>
+ <file>images/widgets/toolbutton.png</file>
+ <file>images/widgets/vline.png</file>
+ <file>images/widgets/vscrollbar.png</file>
+ <file>images/widgets/vslider.png</file>
+ <file>images/widgets/vspacer.png</file>
+ <file>images/widgets/widget.png</file>
+ <file>images/widgets/widget.png</file>
+ <file>images/widgets/widgetstack.png</file>
+ <file>images/widgets/wizard.png</file>
+ <file>images/win/adjustsize.png</file>
+ <file>images/win/widgettool.png</file>
+ <file>images/win/signalslottool.png</file>
+ <file>images/win/tabordertool.png</file>
+ <file>images/win/buddytool.png</file>
+ <file>images/win/editbreaklayout.png</file>
+ <file>images/win/editcopy.png</file>
+ <file>images/win/editcut.png</file>
+ <file>images/win/editdelete.png</file>
+ <file>images/win/editgrid.png</file>
+ <file>images/win/editform.png</file>
+ <file>images/win/edithlayout.png</file>
+ <file>images/win/edithlayoutsplit.png</file>
+ <file>images/win/editlower.png</file>
+ <file>images/win/editpaste.png</file>
+ <file>images/win/editraise.png</file>
+ <file>images/win/editvlayout.png</file>
+ <file>images/win/editvlayoutsplit.png</file>
+ <file>images/win/filenew.png</file>
+ <file>images/win/insertimage.png</file>
+ <file>images/win/undo.png</file>
+ <file>images/win/redo.png</file>
+ <file>images/win/fileopen.png</file>
+ <file>images/win/filesave.png</file>
+ <file>images/win/resourceeditortool.png</file>
+ <file>images/win/plus.png</file>
+ <file>images/win/minus.png</file>
+ <file>images/win/textanchor.png</file>
+ <file>images/win/textbold.png</file>
+ <file>images/win/textitalic.png</file>
+ <file>images/win/textunder.png</file>
+ <file>images/win/textleft.png</file>
+ <file>images/win/textcenter.png</file>
+ <file>images/win/textright.png</file>
+ <file>images/win/textjustify.png</file>
+ <file>images/win/textsuperscript.png</file>
+ <file>images/win/textsubscript.png</file>
+ <file>images/win/back.png</file>
+ <file>images/win/forward.png</file>
+ <file>images/win/down.png</file>
+ <file>images/win/up.png</file>
+ <file>images/mac/textanchor.png</file>
+ <file>images/mac/textbold.png</file>
+ <file>images/mac/textitalic.png</file>
+ <file>images/mac/textunder.png</file>
+ <file>images/mac/textleft.png</file>
+ <file>images/mac/textcenter.png</file>
+ <file>images/mac/textright.png</file>
+ <file>images/mac/textjustify.png</file>
+ <file>images/mac/textsuperscript.png</file>
+ <file>images/mac/textsubscript.png</file>
+ </qresource>
+ <qresource prefix="/trolltech/brushes">
+ <file>defaultbrushes.xml</file>
+ </qresource>
+</RCC>
diff --git a/tools/designer/src/components/formeditor/formeditor_global.h b/tools/designer/src/components/formeditor/formeditor_global.h
new file mode 100644
index 0000000000..0195f1bcce
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formeditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMEDITOR_GLOBAL_H
+#define FORMEDITOR_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN
+#ifdef QT_FORMEDITOR_LIBRARY
+# define QT_FORMEDITOR_EXPORT
+#else
+# define QT_FORMEDITOR_EXPORT
+#endif
+#else
+#define QT_FORMEDITOR_EXPORT
+#endif
+
+#endif // FORMEDITOR_GLOBAL_H
diff --git a/tools/designer/src/components/formeditor/formeditor_optionspage.cpp b/tools/designer/src/components/formeditor/formeditor_optionspage.cpp
new file mode 100644
index 0000000000..0b205317a6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formeditor_optionspage.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formeditor_optionspage.h"
+
+// shared
+#include "formwindowbase_p.h"
+#include "gridpanel_p.h"
+#include "grid_p.h"
+#include "previewconfigurationwidget_p.h"
+#include "shared_settings_p.h"
+#include "zoomwidget_p.h"
+
+// SDK
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <QtCore/QString>
+#include <QtCore/QCoreApplication>
+#include <QtGui/QGroupBox>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/QComboBox>
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<int> IntList;
+
+namespace qdesigner_internal {
+
+// Zoom, currently for preview only
+class ZoomSettingsWidget : public QGroupBox {
+ Q_DISABLE_COPY(ZoomSettingsWidget)
+public:
+ explicit ZoomSettingsWidget(QWidget *parent = 0);
+
+ void fromSettings(const QDesignerSharedSettings &s);
+ void toSettings(QDesignerSharedSettings &s) const;
+
+private:
+ QComboBox *m_zoomCombo;
+};
+
+ZoomSettingsWidget::ZoomSettingsWidget(QWidget *parent) :
+ QGroupBox(parent),
+ m_zoomCombo(new QComboBox)
+{
+ m_zoomCombo->setEditable(false);
+ const IntList zoomValues = ZoomMenu::zoomValues();
+ const IntList::const_iterator cend = zoomValues.constEnd();
+ //: Zoom percentage
+ for (IntList::const_iterator it = zoomValues.constBegin(); it != cend; ++it)
+ m_zoomCombo->addItem(QCoreApplication::translate("FormEditorOptionsPage", "%1 %").arg(*it), QVariant(*it));
+
+ // Layout
+ setCheckable(true);
+ setTitle(QCoreApplication::translate("FormEditorOptionsPage", "Preview Zoom"));
+ QFormLayout *lt = new QFormLayout;
+ lt->addRow(QCoreApplication::translate("FormEditorOptionsPage", "Default Zoom"), m_zoomCombo);
+ setLayout(lt);
+}
+
+void ZoomSettingsWidget::fromSettings(const QDesignerSharedSettings &s)
+{
+ setChecked(s.zoomEnabled());
+ const int idx = m_zoomCombo->findData(QVariant(s.zoom()));
+ m_zoomCombo->setCurrentIndex(qMax(0, idx));
+}
+
+void ZoomSettingsWidget::toSettings(QDesignerSharedSettings &s) const
+{
+ s.setZoomEnabled(isChecked());
+ const int zoom = m_zoomCombo->itemData(m_zoomCombo->currentIndex()).toInt();
+ s.setZoom(zoom);
+}
+
+
+
+// FormEditorOptionsPage:
+FormEditorOptionsPage::FormEditorOptionsPage(QDesignerFormEditorInterface *core)
+ : m_core(core)
+{
+}
+
+QString FormEditorOptionsPage::name() const
+{
+ //: Tab in preferences dialog
+ return QCoreApplication::translate("FormEditorOptionsPage", "Forms");
+}
+
+QWidget *FormEditorOptionsPage::createPage(QWidget *parent)
+{
+ QWidget *optionsWidget = new QWidget(parent);
+
+ const QDesignerSharedSettings settings(m_core);
+ m_previewConf = new PreviewConfigurationWidget(m_core);
+ m_zoomSettingsWidget = new ZoomSettingsWidget;
+ m_zoomSettingsWidget->fromSettings(settings);
+
+ m_defaultGridConf = new GridPanel();
+ m_defaultGridConf->setTitle(QCoreApplication::translate("FormEditorOptionsPage", "Default Grid"));
+ m_defaultGridConf->setGrid(settings.defaultGrid());
+
+ QVBoxLayout *optionsVLayout = new QVBoxLayout();
+ optionsVLayout->addWidget(m_defaultGridConf);
+ optionsVLayout->addWidget(m_previewConf);
+ optionsVLayout->addWidget(m_zoomSettingsWidget);
+ optionsVLayout->addStretch(1);
+
+ // Outer layout to give it horizontal stretch
+ QHBoxLayout *optionsHLayout = new QHBoxLayout();
+ optionsHLayout->addLayout(optionsVLayout);
+ optionsHLayout->addStretch(1);
+ optionsWidget->setLayout(optionsHLayout);
+
+ return optionsWidget;
+}
+
+void FormEditorOptionsPage::apply()
+{
+ QDesignerSharedSettings settings(m_core);
+ if (m_defaultGridConf) {
+ const Grid defaultGrid = m_defaultGridConf->grid();
+ settings.setDefaultGrid(defaultGrid);
+
+ FormWindowBase::setDefaultDesignerGrid(defaultGrid);
+ // Update grid settings in all existing form windows
+ QDesignerFormWindowManagerInterface *fwm = m_core->formWindowManager();
+ if (const int numWindows = fwm->formWindowCount()) {
+ for (int i = 0; i < numWindows; i++)
+ if (qdesigner_internal::FormWindowBase *fwb
+ = qobject_cast<qdesigner_internal::FormWindowBase *>( fwm->formWindow(i)))
+ if (!fwb->hasFormGrid())
+ fwb->setDesignerGrid(defaultGrid);
+ }
+ }
+ if (m_previewConf) {
+ m_previewConf->saveState();
+ }
+
+ if (m_zoomSettingsWidget)
+ m_zoomSettingsWidget->toSettings(settings);
+}
+
+void FormEditorOptionsPage::finish()
+{
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formeditor_optionspage.h b/tools/designer/src/components/formeditor/formeditor_optionspage.h
new file mode 100644
index 0000000000..4aeda6ac17
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formeditor_optionspage.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMEDITOR_OPTIONSPAGE_H
+#define FORMEDITOR_OPTIONSPAGE_H
+
+#include <QtDesigner/private/abstractoptionspage_p.h>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class PreviewConfigurationWidget;
+class GridPanel;
+class ZoomSettingsWidget;
+
+class FormEditorOptionsPage : public QDesignerOptionsPageInterface
+{
+public:
+ explicit FormEditorOptionsPage(QDesignerFormEditorInterface *core);
+
+ QString name() const;
+ QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ QPointer<PreviewConfigurationWidget> m_previewConf;
+ QPointer<GridPanel> m_defaultGridConf;
+ QPointer<ZoomSettingsWidget> m_zoomSettingsWidget;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMEDITOR_OPTIONSPAGE_H
diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp
new file mode 100644
index 0000000000..48efcde189
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindow.cpp
@@ -0,0 +1,2921 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::FormWindow
+*/
+
+#include "formwindow.h"
+#include "formeditor.h"
+#include "formwindow_dnditem.h"
+#include "formwindow_widgetstack.h"
+#include "formwindowcursor.h"
+#include "formwindowmanager.h"
+#include "tool_widgeteditor.h"
+#include "widgetselection.h"
+#include "qtresourcemodel_p.h"
+#include "widgetfactory_p.h"
+
+// shared
+#include <metadatabase_p.h>
+#include <qdesigner_tabwidget_p.h>
+#include <qdesigner_toolbox_p.h>
+#include <qdesigner_stackedbox_p.h>
+#include <qdesigner_resource.h>
+#include <qdesigner_command_p.h>
+#include <qdesigner_command2_p.h>
+#include <qdesigner_propertycommand_p.h>
+#include <qdesigner_taskmenu_p.h>
+#include <qdesigner_widget_p.h>
+#include <qdesigner_utils_p.h>
+#include <qlayout_widget_p.h>
+#include <spacer_widget_p.h>
+#include <invisible_widget_p.h>
+#include <layoutinfo_p.h>
+#include <qdesigner_objectinspector_p.h>
+#include <connectionedit_p.h>
+#include <actionprovider_p.h>
+#include <ui4_p.h>
+#include <deviceprofile_p.h>
+#include <shared_settings_p.h>
+#include <grid_p.h>
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerTaskMenuExtension>
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+#include <abstractdialoggui_p.h>
+
+#include <QtCore/QtDebug>
+#include <QtCore/QBuffer>
+#include <QtCore/QTimer>
+#include <QtCore/QXmlStreamReader>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QClipboard>
+#include <QtGui/QUndoGroup>
+#include <QtGui/QScrollArea>
+#include <QtGui/QRubberBand>
+#include <QtGui/QApplication>
+#include <QtGui/QSplitter>
+#include <QtGui/QPainter>
+#include <QtGui/QGroupBox>
+#include <QtGui/QDockWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QTabWidget>
+#include <QtGui/QButtonGroup>
+
+Q_DECLARE_METATYPE(QWidget*)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+class BlockSelection
+{
+public:
+ BlockSelection(qdesigner_internal::FormWindow *fw)
+ : m_formWindow(fw),
+ m_blocked(m_formWindow->blockSelectionChanged(true))
+ {
+ }
+
+ ~BlockSelection()
+ {
+ if (m_formWindow)
+ m_formWindow->blockSelectionChanged(m_blocked);
+ }
+
+private:
+ QPointer<qdesigner_internal::FormWindow> m_formWindow;
+ const bool m_blocked;
+};
+
+enum { debugFormWindow = 0 };
+}
+
+namespace qdesigner_internal {
+
+// ------------------------ FormWindow::Selection
+// Maintains a pool of WidgetSelections to be used for selected widgets.
+
+class FormWindow::Selection
+{
+public:
+ Selection();
+ ~Selection();
+
+ // Clear
+ void clear();
+
+ // Also clear out the pool. Call if reparenting of the main container occurs.
+ void clearSelectionPool();
+
+ void repaintSelection(QWidget *w);
+ void repaintSelection();
+
+ bool isWidgetSelected(QWidget *w) const;
+ QWidgetList selectedWidgets() const;
+
+ WidgetSelection *addWidget(FormWindow* fw, QWidget *w);
+ // remove widget, return new current widget or 0
+ QWidget* removeWidget(QWidget *w);
+
+ void raiseList(const QWidgetList& l);
+ void raiseWidget(QWidget *w);
+
+ void updateGeometry(QWidget *w);
+
+ void hide(QWidget *w);
+ void show(QWidget *w);
+
+private:
+
+ typedef QList<WidgetSelection *> SelectionPool;
+ SelectionPool m_selectionPool;
+
+ typedef QHash<QWidget *, WidgetSelection *> SelectionHash;
+ SelectionHash m_usedSelections;
+};
+
+FormWindow::Selection::Selection()
+{
+}
+
+FormWindow::Selection::~Selection()
+{
+ clearSelectionPool();
+}
+
+void FormWindow::Selection::clear()
+{
+ if (!m_usedSelections.empty()) {
+ const SelectionHash::iterator mend = m_usedSelections.end();
+ for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) {
+ it.value()->setWidget(0);
+ }
+ m_usedSelections.clear();
+ }
+}
+
+void FormWindow::Selection::clearSelectionPool()
+{
+ clear();
+ qDeleteAll(m_selectionPool);
+ m_selectionPool.clear();
+}
+
+WidgetSelection *FormWindow::Selection::addWidget(FormWindow* fw, QWidget *w)
+{
+ WidgetSelection *rc = m_usedSelections.value(w);
+ if (rc != 0) {
+ rc->show();
+ rc->updateActive();
+ return rc;
+ }
+ // find a free one in the pool
+ const SelectionPool::iterator pend = m_selectionPool.end();
+ for (SelectionPool::iterator it = m_selectionPool.begin(); it != pend; ++it) {
+ if (! (*it)->isUsed()) {
+ rc = *it;
+ break;
+ }
+ }
+
+ if (rc == 0) {
+ rc = new WidgetSelection(fw);
+ m_selectionPool.push_back(rc);
+ }
+
+ m_usedSelections.insert(w, rc);
+ rc->setWidget(w);
+ return rc;
+}
+
+QWidget* FormWindow::Selection::removeWidget(QWidget *w)
+{
+ WidgetSelection *s = m_usedSelections.value(w);
+ if (!s)
+ return w;
+
+ s->setWidget(0);
+ m_usedSelections.remove(w);
+
+ if (m_usedSelections.isEmpty())
+ return 0;
+
+ return (*m_usedSelections.begin())->widget();
+}
+
+void FormWindow::Selection::repaintSelection(QWidget *w)
+{
+ if (WidgetSelection *s = m_usedSelections.value(w))
+ s->update();
+}
+
+void FormWindow::Selection::repaintSelection()
+{
+ const SelectionHash::iterator mend = m_usedSelections.end();
+ for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) {
+ it.value()->update();
+ }
+}
+
+bool FormWindow::Selection::isWidgetSelected(QWidget *w) const{
+ return m_usedSelections.contains(w);
+}
+
+QWidgetList FormWindow::Selection::selectedWidgets() const
+{
+ return m_usedSelections.keys();
+}
+
+void FormWindow::Selection::raiseList(const QWidgetList& l)
+{
+ const SelectionHash::iterator mend = m_usedSelections.end();
+ for (SelectionHash::iterator it = m_usedSelections.begin(); it != mend; ++it) {
+ WidgetSelection *w = it.value();
+ if (l.contains(w->widget()))
+ w->show();
+ }
+}
+
+void FormWindow::Selection::raiseWidget(QWidget *w)
+{
+ if (WidgetSelection *s = m_usedSelections.value(w))
+ s->show();
+}
+
+void FormWindow::Selection::updateGeometry(QWidget *w)
+{
+ if (WidgetSelection *s = m_usedSelections.value(w)) {
+ s->updateGeometry();
+ }
+}
+
+void FormWindow::Selection::hide(QWidget *w)
+{
+ if (WidgetSelection *s = m_usedSelections.value(w))
+ s->hide();
+}
+
+void FormWindow::Selection::show(QWidget *w)
+{
+ if (WidgetSelection *s = m_usedSelections.value(w))
+ s->show();
+}
+
+// ------------------------ FormWindow
+FormWindow::FormWindow(FormEditor *core, QWidget *parent, Qt::WindowFlags flags) :
+ FormWindowBase(core, parent, flags),
+ m_mouseState(NoMouseState),
+ m_core(core),
+ m_selection(new Selection),
+ m_widgetStack(new FormWindowWidgetStack(this)),
+ m_contextMenuPosition(-1, -1)
+{
+ // Apply settings to formcontainer
+ deviceProfile().apply(core, m_widgetStack->formContainer(), qdesigner_internal::DeviceProfile::ApplyFormParent);
+
+ setLayout(m_widgetStack->layout());
+ init();
+
+ m_cursor = new FormWindowCursor(this, this);
+
+ core->formWindowManager()->addFormWindow(this);
+
+ setDirty(false);
+ setAcceptDrops(true);
+}
+
+FormWindow::~FormWindow()
+{
+ Q_ASSERT(core() != 0);
+ Q_ASSERT(core()->metaDataBase() != 0);
+ Q_ASSERT(core()->formWindowManager() != 0);
+
+ core()->formWindowManager()->removeFormWindow(this);
+ core()->metaDataBase()->remove(this);
+
+ QWidgetList l = widgets();
+ foreach (QWidget *w, l)
+ core()->metaDataBase()->remove(w);
+
+ m_widgetStack = 0;
+ m_rubberBand = 0;
+ if (resourceSet())
+ core()->resourceModel()->removeResourceSet(resourceSet());
+ delete m_selection;
+}
+
+QDesignerFormEditorInterface *FormWindow::core() const
+{
+ return m_core;
+}
+
+QDesignerFormWindowCursorInterface *FormWindow::cursor() const
+{
+ return m_cursor;
+}
+
+void FormWindow::updateWidgets()
+{
+ if (!m_mainContainer)
+ return;
+}
+
+int FormWindow::widgetDepth(const QWidget *w)
+{
+ int d = -1;
+ while (w && !w->isWindow()) {
+ d++;
+ w = w->parentWidget();
+ }
+
+ return d;
+}
+
+bool FormWindow::isChildOf(const QWidget *c, const QWidget *p)
+{
+ while (c) {
+ if (c == p)
+ return true;
+ c = c->parentWidget();
+ }
+ return false;
+}
+
+void FormWindow::setCursorToAll(const QCursor &c, QWidget *start)
+{
+#ifndef QT_NO_CURSOR
+ start->setCursor(c);
+ const QWidgetList widgets = qFindChildren<QWidget*>(start);
+ foreach (QWidget *widget, widgets) {
+ if (!qobject_cast<WidgetHandle*>(widget)) {
+ widget->setCursor(c);
+ }
+ }
+#endif
+}
+
+void FormWindow::init()
+{
+ if (FormWindowManager *manager = qobject_cast<FormWindowManager*> (core()->formWindowManager())) {
+ m_commandHistory = new QUndoStack(this);
+ manager->undoGroup()->addStack(m_commandHistory);
+ }
+
+ m_blockSelectionChanged = false;
+
+ m_defaultMargin = INT_MIN;
+ m_defaultSpacing = INT_MIN;
+
+ connect(m_widgetStack, SIGNAL(currentToolChanged(int)), this, SIGNAL(toolChanged(int)));
+
+ m_selectionChangedTimer = new QTimer(this);
+ m_selectionChangedTimer->setSingleShot(true);
+ connect(m_selectionChangedTimer, SIGNAL(timeout()), this, SLOT(selectionChangedTimerDone()));
+
+ m_checkSelectionTimer = new QTimer(this);
+ m_checkSelectionTimer->setSingleShot(true);
+ connect(m_checkSelectionTimer, SIGNAL(timeout()), this, SLOT(checkSelectionNow()));
+
+ m_geometryChangedTimer = new QTimer(this);
+ m_geometryChangedTimer->setSingleShot(true);
+ connect(m_geometryChangedTimer, SIGNAL(timeout()), this, SIGNAL(geometryChanged()));
+
+ m_rubberBand = 0;
+
+ setFocusPolicy(Qt::StrongFocus);
+
+ m_mainContainer = 0;
+ m_currentWidget = 0;
+
+ connect(m_commandHistory, SIGNAL(indexChanged(int)), this, SLOT(updateDirty()));
+ connect(m_commandHistory, SIGNAL(indexChanged(int)), this, SIGNAL(changed()));
+ connect(m_commandHistory, SIGNAL(indexChanged(int)), this, SLOT(checkSelection()));
+
+ core()->metaDataBase()->add(this);
+
+ initializeCoreTools();
+
+ QAction *a = new QAction(this);
+ a->setText(tr("Edit contents"));
+ a->setShortcut(tr("F2"));
+ connect(a, SIGNAL(triggered()), this, SLOT(editContents()));
+ addAction(a);
+}
+
+QWidget *FormWindow::mainContainer() const
+{
+ return m_mainContainer;
+}
+
+
+void FormWindow::clearMainContainer()
+{
+ if (m_mainContainer) {
+ setCurrentTool(0);
+ m_widgetStack->setMainContainer(0);
+ core()->metaDataBase()->remove(m_mainContainer);
+ unmanageWidget(m_mainContainer);
+ delete m_mainContainer;
+ m_mainContainer = 0;
+ }
+}
+
+void FormWindow::setMainContainer(QWidget *w)
+{
+ if (w == m_mainContainer) {
+ // nothing to do
+ return;
+ }
+
+ clearMainContainer();
+
+ m_mainContainer = w;
+ const QSize sz = m_mainContainer->size();
+
+ m_widgetStack->setMainContainer(m_mainContainer);
+ m_widgetStack->setCurrentTool(m_widgetEditor);
+
+ setCurrentWidget(m_mainContainer);
+ manageWidget(m_mainContainer);
+
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), m_mainContainer)) {
+ sheet->setVisible(sheet->indexOf(QLatin1String("windowTitle")), true);
+ sheet->setVisible(sheet->indexOf(QLatin1String("windowIcon")), true);
+ sheet->setVisible(sheet->indexOf(QLatin1String("windowModality")), true);
+ sheet->setVisible(sheet->indexOf(QLatin1String("windowFilePath")), true);
+ // ### generalize
+ }
+
+ m_mainContainer->setFocusPolicy(Qt::StrongFocus);
+ m_mainContainer->resize(sz);
+
+ emit mainContainerChanged(m_mainContainer);
+}
+
+QWidget *FormWindow::findTargetContainer(QWidget *widget) const
+{
+ Q_ASSERT(widget);
+
+ while (QWidget *parentWidget = widget->parentWidget()) {
+ if (LayoutInfo::layoutType(m_core, parentWidget) == LayoutInfo::NoLayout && isManaged(widget))
+ return widget;
+
+ widget = parentWidget;
+ }
+
+ return mainContainer();
+}
+
+static inline void clearObjectInspectorSelection(const QDesignerFormEditorInterface *core)
+{
+ if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(core->objectInspector()))
+ oi->clearSelection();
+}
+
+// Find a parent of a desired selection state
+static QWidget *findSelectedParent(QDesignerFormWindowInterface *fw, const QWidget *w, bool selected)
+{
+ const QDesignerFormWindowCursorInterface *cursor = fw->cursor();
+ QWidget *mainContainer = fw->mainContainer();
+ for (QWidget *p = w->parentWidget(); p && p != mainContainer; p = p->parentWidget())
+ if (fw->isManaged(p))
+ if (cursor->isWidgetSelected(p) == selected)
+ return p;
+ return 0;
+}
+
+// Mouse modifiers.
+
+enum MouseFlags { ToggleSelectionModifier = 0x1, CycleParentModifier=0x2, CopyDragModifier=0x4 };
+
+static inline unsigned mouseFlags(Qt::KeyboardModifiers mod)
+{
+ switch (mod) {
+ case Qt::ShiftModifier:
+ return CycleParentModifier;
+ break;
+#ifdef Q_WS_MAC
+ case Qt::AltModifier: // "Alt" or "option" key on Mac means copy
+ return CopyDragModifier;
+#endif
+ case Qt::ControlModifier:
+ return CopyDragModifier|ToggleSelectionModifier;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+// Handle the click selection: Do toggling/cycling
+// of parents according to the modifiers.
+void FormWindow::handleClickSelection(QWidget *managedWidget, unsigned mouseMode)
+{
+ const bool sameWidget = managedWidget == m_lastClickedWidget;
+ m_lastClickedWidget = managedWidget;
+
+ const bool selected = isWidgetSelected(managedWidget);
+ if (debugFormWindow)
+ qDebug() << "handleClickSelection" << managedWidget << " same=" << sameWidget << " mouse= " << mouseMode << " selected=" << selected;
+
+ // // toggle selection state of widget
+ if (mouseMode & ToggleSelectionModifier) {
+ selectWidget(managedWidget, !selected);
+ return;
+ }
+
+ QWidget *selectionCandidate = 0;
+ // Hierarchy cycling: If the same widget clicked again: Attempt to cycle
+ // trough the hierarchy. Find the next currently selected parent
+ if (sameWidget && (mouseMode & CycleParentModifier))
+ if (QWidget *currentlySelectedParent = selected ? managedWidget : findSelectedParent(this, managedWidget, true))
+ selectionCandidate = findSelectedParent(this, currentlySelectedParent, false);
+ // Not the same widget, list wrapped over or there was no unselected parent
+ if (!selectionCandidate && !selected)
+ selectionCandidate = managedWidget;
+
+ if (selectionCandidate)
+ selectSingleWidget(selectionCandidate);
+}
+
+void FormWindow::selectSingleWidget(QWidget *w)
+{
+ clearSelection(false);
+ selectWidget(w, true);
+ raiseChildSelections(w);
+}
+
+bool FormWindow::handleMousePressEvent(QWidget * widget, QWidget *managedWidget, QMouseEvent *e)
+{
+ m_mouseState = NoMouseState;
+ m_startPos = QPoint();
+ e->accept();
+
+ BlockSelection blocker(this);
+
+ if (core()->formWindowManager()->activeFormWindow() != this)
+ core()->formWindowManager()->setActiveFormWindow(this);
+
+ const Qt::MouseButtons buttons = e->buttons();
+ if (buttons != Qt::LeftButton && buttons != Qt::MidButton)
+ return true;
+
+ m_startPos = mapFromGlobal(e->globalPos());
+
+ if (debugFormWindow)
+ qDebug() << "handleMousePressEvent:" << widget << ',' << managedWidget;
+
+ if (buttons == Qt::MidButton || isMainContainer(managedWidget) == true) { // press was on the formwindow
+ clearObjectInspectorSelection(m_core); // We might have a toolbar or non-widget selected in the object inspector.
+ clearSelection(false);
+
+ m_mouseState = MouseDrawRubber;
+ m_currRect = QRect();
+ startRectDraw(mapFromGlobal(e->globalPos()), this, Rubber);
+ return true;
+ }
+ if (buttons != Qt::LeftButton)
+ return true;
+
+ const unsigned mouseMode = mouseFlags(e->modifiers());
+
+ /* Normally, we want to be able to click /select-on-press to drag away
+ * the widget in the next step. However, in the case of a widget which
+ * itself or whose parent is selected, we defer the selection to the
+ * release event.
+ * This is to prevent children from being dragged away from layouts
+ * when their layouts are selected and one wants to move the layout.
+ * Note that toggle selection is only deferred if the widget is already
+ * selected, so, it is still possible to just Ctrl+Click and CopyDrag. */
+ const bool deferSelection = isWidgetSelected(managedWidget) || findSelectedParent(this, managedWidget, true);
+ if (deferSelection) {
+ m_mouseState = MouseDeferredSelection;
+ } else {
+ // Cycle the parent unless we explicitly want toggle
+ const unsigned effectiveMouseMode = (mouseMode & ToggleSelectionModifier) ? mouseMode : static_cast<unsigned>(CycleParentModifier);
+ handleClickSelection(managedWidget, effectiveMouseMode);
+ }
+ return true;
+}
+
+// We can drag widget in managed layouts except splitter.
+static bool canDragWidgetInLayout(const QDesignerFormEditorInterface *core, QWidget *w)
+{
+ bool managed;
+ const LayoutInfo::Type type = LayoutInfo::laidoutWidgetType(core ,w, &managed);
+ if (!managed)
+ return false;
+ switch (type) {
+ case LayoutInfo::NoLayout:
+ case LayoutInfo::HSplitter:
+ case LayoutInfo::VSplitter:
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool FormWindow::handleMouseMoveEvent(QWidget *, QWidget *, QMouseEvent *e)
+{
+ e->accept();
+ if (m_startPos.isNull())
+ return true;
+
+ const QPoint pos = mapFromGlobal(e->globalPos());
+
+ switch (m_mouseState) {
+ case MouseDrawRubber: // Rubber band with left/middle mouse
+ continueRectDraw(pos, this, Rubber);
+ return true;
+ case MouseMoveDrag: // Spurious move event after drag started?
+ return true;
+ default:
+ break;
+ }
+
+ if (e->buttons() != Qt::LeftButton)
+ return true;
+
+ const bool canStartDrag = (m_startPos - pos).manhattanLength() > QApplication::startDragDistance();
+
+ if (canStartDrag == false) {
+ // nothing to do
+ return true;
+ }
+
+ m_mouseState = MouseMoveDrag;
+ const bool blocked = blockSelectionChanged(true);
+
+ QWidgetList sel = selectedWidgets();
+ simplifySelection(&sel);
+
+ QSet<QWidget*> widget_set;
+
+ foreach (QWidget *child, sel) { // Move parent layout or container?
+ QWidget *current = child;
+
+ bool done = false;
+ while (!isMainContainer(current) && !done) {
+ if (!isManaged(current)) {
+ current = current->parentWidget();
+ continue;
+ } else if (LayoutInfo::isWidgetLaidout(core(), current)) {
+ // Go up to parent of layout if shift pressed, else do that only for splitters
+ if (!canDragWidgetInLayout(core(), current)) {
+ current = current->parentWidget();
+ continue;
+ }
+ }
+ done = true;
+ }
+
+ if (current == mainContainer())
+ continue;
+
+ widget_set.insert(current);
+ }
+
+ sel = widget_set.toList();
+ QDesignerFormWindowCursorInterface *c = cursor();
+ QWidget *current = c->current();
+ if (sel.contains(current)) {
+ sel.removeAll(current);
+ sel.prepend(current);
+ }
+
+ QList<QDesignerDnDItemInterface*> item_list;
+ const QPoint globalPos = mapToGlobal(m_startPos);
+ const QDesignerDnDItemInterface::DropType dropType = (mouseFlags(e->modifiers()) & CopyDragModifier) ?
+ QDesignerDnDItemInterface::CopyDrop : QDesignerDnDItemInterface::MoveDrop;
+ foreach (QWidget *widget, sel) {
+ item_list.append(new FormWindowDnDItem(dropType, this, widget, globalPos));
+ if (dropType == QDesignerDnDItemInterface::MoveDrop) {
+ m_selection->hide(widget);
+ widget->hide();
+ }
+ }
+
+ blockSelectionChanged(blocked);
+
+ if (!sel.empty()) // reshow selection?
+ if (QDesignerMimeData::execDrag(item_list, core()->topLevel()) == Qt::IgnoreAction && dropType == QDesignerDnDItemInterface::MoveDrop)
+ foreach (QWidget *widget, sel)
+ m_selection->show(widget);
+
+ m_startPos = QPoint();
+
+ return true;
+}
+
+bool FormWindow::handleMouseReleaseEvent(QWidget *w, QWidget *mw, QMouseEvent *e)
+{
+ const MouseState oldState = m_mouseState;
+ m_mouseState = NoMouseState;
+
+ if (debugFormWindow)
+ qDebug() << "handleMouseeleaseEvent:" << w << ',' << mw << "state=" << oldState;
+
+ if (oldState == MouseDoubleClicked)
+ return true;
+
+ e->accept();
+
+ switch (oldState) {
+ case MouseDrawRubber: { // we were drawing a rubber selection
+ endRectDraw(); // get rid of the rectangle
+ const bool blocked = blockSelectionChanged(true);
+ selectWidgets(); // select widgets which intersect the rect
+ blockSelectionChanged(blocked);
+ }
+ break;
+ // Deferred select: Select the child here unless the parent was moved.
+ case MouseDeferredSelection:
+ handleClickSelection(mw, mouseFlags(e->modifiers()));
+ break;
+ default:
+ break;
+ }
+
+ m_startPos = QPoint();
+
+ /* Inform about selection changes (left/mid or context menu). Also triggers
+ * in the case of an empty rubber drag that cleared the selection in
+ * MousePressEvent. */
+ switch (e->button()) {
+ case Qt::LeftButton:
+ case Qt::MidButton:
+ case Qt::RightButton:
+ emitSelectionChanged();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void FormWindow::checkPreviewGeometry(QRect &r)
+{
+ if (!rect().contains(r)) {
+ if (r.left() < rect().left())
+ r.moveTopLeft(QPoint(0, r.top()));
+ if (r.right() > rect().right())
+ r.moveBottomRight(QPoint(rect().right(), r.bottom()));
+ if (r.top() < rect().top())
+ r.moveTopLeft(QPoint(r.left(), rect().top()));
+ if (r.bottom() > rect().bottom())
+ r.moveBottomRight(QPoint(r.right(), rect().bottom()));
+ }
+}
+
+void FormWindow::startRectDraw(const QPoint &pos, QWidget *, RectType t)
+{
+ m_rectAnchor = (t == Insert) ? designerGrid().snapPoint(pos) : pos;
+
+ m_currRect = QRect(m_rectAnchor, QSize(0, 0));
+ if (!m_rubberBand)
+ m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
+ m_rubberBand->setGeometry(m_currRect);
+ m_rubberBand->show();
+}
+
+void FormWindow::continueRectDraw(const QPoint &pos, QWidget *, RectType t)
+{
+ const QPoint p2 = (t == Insert) ? designerGrid().snapPoint(pos) : pos;
+
+ QRect r(m_rectAnchor, p2);
+ r = r.normalized();
+
+ if (m_currRect == r)
+ return;
+
+ if (r.width() > 1 || r.height() > 1) {
+ m_currRect = r;
+ if (m_rubberBand)
+ m_rubberBand->setGeometry(m_currRect);
+ }
+}
+
+void FormWindow::endRectDraw()
+{
+ if (m_rubberBand) {
+ delete m_rubberBand;
+ m_rubberBand = 0;
+ }
+}
+
+QWidget *FormWindow::currentWidget() const
+{
+ return m_currentWidget;
+}
+
+bool FormWindow::setCurrentWidget(QWidget *currentWidget)
+{
+ if (debugFormWindow)
+ qDebug() << "setCurrentWidget:" << m_currentWidget << " --> " << currentWidget;
+ if (currentWidget == m_currentWidget)
+ return false;
+ // repaint the old widget unless it is the main window
+ if (m_currentWidget && m_currentWidget != mainContainer()) {
+ m_selection->repaintSelection(m_currentWidget);
+ }
+ // set new and repaint
+ m_currentWidget = currentWidget;
+ if (m_currentWidget && m_currentWidget != mainContainer()) {
+ m_selection->repaintSelection(m_currentWidget);
+ }
+ return true;
+}
+
+void FormWindow::selectWidget(QWidget* w, bool select)
+{
+ if (trySelectWidget(w, select))
+ emitSelectionChanged();
+}
+
+// Selects a widget and determines the new current one. Returns true if a change occurs.
+bool FormWindow::trySelectWidget(QWidget *w, bool select)
+{
+ if (debugFormWindow)
+ qDebug() << "trySelectWidget:" << w << select;
+ if (!isManaged(w) && !isCentralWidget(w))
+ return false;
+
+ if (!select && !isWidgetSelected(w))
+ return false;
+
+ if (!mainContainer())
+ return false;
+
+ if (isMainContainer(w) || isCentralWidget(w)) {
+ setCurrentWidget(mainContainer());
+ return true;
+ }
+
+ if (select) {
+ setCurrentWidget(w);
+ m_selection->addWidget(this, w);
+ } else {
+ QWidget *newCurrent = m_selection->removeWidget(w);
+ if (!newCurrent)
+ newCurrent = mainContainer();
+ setCurrentWidget(newCurrent);
+ }
+ return true;
+}
+
+void FormWindow::clearSelection(bool changePropertyDisplay)
+{
+ if (debugFormWindow)
+ qDebug() << "clearSelection(" << changePropertyDisplay << ')';
+ // At all events, we need a current widget.
+ m_selection->clear();
+ setCurrentWidget(mainContainer());
+
+ if (changePropertyDisplay)
+ emitSelectionChanged();
+}
+
+void FormWindow::emitSelectionChanged()
+{
+ if (m_blockSelectionChanged == true) {
+ // nothing to do
+ return;
+ }
+
+ m_selectionChangedTimer->start(0);
+}
+
+void FormWindow::selectionChangedTimerDone()
+{
+ emit selectionChanged();
+}
+
+bool FormWindow::isWidgetSelected(QWidget *w) const
+{
+ return m_selection->isWidgetSelected(w);
+}
+
+bool FormWindow::isMainContainer(const QWidget *w) const
+{
+ return w && (w == this || w == mainContainer());
+}
+
+void FormWindow::updateChildSelections(QWidget *w)
+{
+ const QWidgetList l = qFindChildren<QWidget*>(w);
+ if (!l.empty()) {
+ const QWidgetList::const_iterator lcend = l.constEnd();
+ for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it) {
+ QWidget *w = *it;
+ if (isManaged(w))
+ updateSelection(w);
+ }
+ }
+}
+
+void FormWindow::repaintSelection()
+{
+ m_selection->repaintSelection();
+}
+
+void FormWindow::raiseSelection(QWidget *w)
+{
+ m_selection->raiseWidget(w);
+}
+
+void FormWindow::updateSelection(QWidget *w)
+{
+ if (!w->isVisibleTo(this)) {
+ selectWidget(w, false);
+ } else {
+ m_selection->updateGeometry(w);
+ }
+}
+
+QWidget *FormWindow::designerWidget(QWidget *w) const
+{
+ while ((w && !isMainContainer(w) && !isManaged(w)) || isCentralWidget(w))
+ w = w->parentWidget();
+
+ return w;
+}
+
+bool FormWindow::isCentralWidget(QWidget *w) const
+{
+ if (QMainWindow *mainWindow = qobject_cast<QMainWindow*>(mainContainer()))
+ return w == mainWindow->centralWidget();
+
+ return false;
+}
+
+void FormWindow::ensureUniqueObjectName(QObject *object)
+{
+ QString name = object->objectName();
+ if (name.isEmpty()) {
+ QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase();
+ if (QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(object)))
+ name = qdesigner_internal::qtify(item->name());
+ }
+ unify(object, name, true);
+ object->setObjectName(name);
+}
+
+template <class Iterator>
+static inline void insertNames(const QDesignerMetaDataBaseInterface *metaDataBase,
+ Iterator it, const Iterator &end,
+ QObject *excludedObject, QSet<QString> &nameSet)
+{
+ for ( ; it != end; ++it)
+ if (excludedObject != *it && metaDataBase->item(*it))
+ nameSet.insert((*it)->objectName());
+}
+
+static QSet<QString> languageKeywords()
+{
+ static QSet<QString> keywords;
+ if (keywords.isEmpty()) {
+ // C++ keywords
+ keywords.insert(QLatin1String("asm"));
+ keywords.insert(QLatin1String("auto"));
+ keywords.insert(QLatin1String("bool"));
+ keywords.insert(QLatin1String("break"));
+ keywords.insert(QLatin1String("case"));
+ keywords.insert(QLatin1String("catch"));
+ keywords.insert(QLatin1String("char"));
+ keywords.insert(QLatin1String("class"));
+ keywords.insert(QLatin1String("const"));
+ keywords.insert(QLatin1String("const_cast"));
+ keywords.insert(QLatin1String("continue"));
+ keywords.insert(QLatin1String("default"));
+ keywords.insert(QLatin1String("delete"));
+ keywords.insert(QLatin1String("do"));
+ keywords.insert(QLatin1String("double"));
+ keywords.insert(QLatin1String("dynamic_cast"));
+ keywords.insert(QLatin1String("else"));
+ keywords.insert(QLatin1String("enum"));
+ keywords.insert(QLatin1String("explicit"));
+ keywords.insert(QLatin1String("export"));
+ keywords.insert(QLatin1String("extern"));
+ keywords.insert(QLatin1String("false"));
+ keywords.insert(QLatin1String("float"));
+ keywords.insert(QLatin1String("for"));
+ keywords.insert(QLatin1String("friend"));
+ keywords.insert(QLatin1String("goto"));
+ keywords.insert(QLatin1String("if"));
+ keywords.insert(QLatin1String("inline"));
+ keywords.insert(QLatin1String("int"));
+ keywords.insert(QLatin1String("long"));
+ keywords.insert(QLatin1String("mutable"));
+ keywords.insert(QLatin1String("namespace"));
+ keywords.insert(QLatin1String("new"));
+ keywords.insert(QLatin1String("NULL"));
+ keywords.insert(QLatin1String("operator"));
+ keywords.insert(QLatin1String("private"));
+ keywords.insert(QLatin1String("protected"));
+ keywords.insert(QLatin1String("public"));
+ keywords.insert(QLatin1String("register"));
+ keywords.insert(QLatin1String("reinterpret_cast"));
+ keywords.insert(QLatin1String("return"));
+ keywords.insert(QLatin1String("short"));
+ keywords.insert(QLatin1String("signed"));
+ keywords.insert(QLatin1String("sizeof"));
+ keywords.insert(QLatin1String("static"));
+ keywords.insert(QLatin1String("static_cast"));
+ keywords.insert(QLatin1String("struct"));
+ keywords.insert(QLatin1String("switch"));
+ keywords.insert(QLatin1String("template"));
+ keywords.insert(QLatin1String("this"));
+ keywords.insert(QLatin1String("throw"));
+ keywords.insert(QLatin1String("true"));
+ keywords.insert(QLatin1String("try"));
+ keywords.insert(QLatin1String("typedef"));
+ keywords.insert(QLatin1String("typeid"));
+ keywords.insert(QLatin1String("typename"));
+ keywords.insert(QLatin1String("union"));
+ keywords.insert(QLatin1String("unsigned"));
+ keywords.insert(QLatin1String("using"));
+ keywords.insert(QLatin1String("virtual"));
+ keywords.insert(QLatin1String("void"));
+ keywords.insert(QLatin1String("volatile"));
+ keywords.insert(QLatin1String("wchar_t"));
+ keywords.insert(QLatin1String("while"));
+
+ // java keywords
+ keywords.insert(QLatin1String("abstract"));
+ keywords.insert(QLatin1String("assert"));
+ keywords.insert(QLatin1String("boolean"));
+ keywords.insert(QLatin1String("break"));
+ keywords.insert(QLatin1String("byte"));
+ keywords.insert(QLatin1String("case"));
+ keywords.insert(QLatin1String("catch"));
+ keywords.insert(QLatin1String("char"));
+ keywords.insert(QLatin1String("class"));
+ keywords.insert(QLatin1String("const"));
+ keywords.insert(QLatin1String("continue"));
+ keywords.insert(QLatin1String("default"));
+ keywords.insert(QLatin1String("do"));
+ keywords.insert(QLatin1String("double"));
+ keywords.insert(QLatin1String("else"));
+ keywords.insert(QLatin1String("enum"));
+ keywords.insert(QLatin1String("extends"));
+ keywords.insert(QLatin1String("false"));
+ keywords.insert(QLatin1String("final"));
+ keywords.insert(QLatin1String("finality"));
+ keywords.insert(QLatin1String("float"));
+ keywords.insert(QLatin1String("for"));
+ keywords.insert(QLatin1String("goto"));
+ keywords.insert(QLatin1String("if"));
+ keywords.insert(QLatin1String("implements"));
+ keywords.insert(QLatin1String("import"));
+ keywords.insert(QLatin1String("instanceof"));
+ keywords.insert(QLatin1String("int"));
+ keywords.insert(QLatin1String("interface"));
+ keywords.insert(QLatin1String("long"));
+ keywords.insert(QLatin1String("native"));
+ keywords.insert(QLatin1String("new"));
+ keywords.insert(QLatin1String("null"));
+ keywords.insert(QLatin1String("package"));
+ keywords.insert(QLatin1String("private"));
+ keywords.insert(QLatin1String("protected"));
+ keywords.insert(QLatin1String("public"));
+ keywords.insert(QLatin1String("return"));
+ keywords.insert(QLatin1String("short"));
+ keywords.insert(QLatin1String("static"));
+ keywords.insert(QLatin1String("strictfp"));
+ keywords.insert(QLatin1String("super"));
+ keywords.insert(QLatin1String("switch"));
+ keywords.insert(QLatin1String("synchronized"));
+ keywords.insert(QLatin1String("this"));
+ keywords.insert(QLatin1String("throw"));
+ keywords.insert(QLatin1String("throws"));
+ keywords.insert(QLatin1String("transient"));
+ keywords.insert(QLatin1String("true"));
+ keywords.insert(QLatin1String("try"));
+ keywords.insert(QLatin1String("void"));
+ keywords.insert(QLatin1String("volatile"));
+ keywords.insert(QLatin1String("while"));
+ }
+ return keywords;
+}
+
+bool FormWindow::unify(QObject *w, QString &s, bool changeIt)
+{
+ typedef QSet<QString> StringSet;
+
+ QWidget *main = mainContainer();
+ if (!main)
+ return true;
+
+ StringSet existingNames = languageKeywords();
+ // build a set of existing names of other widget excluding self
+ if (!(w->isWidgetType() && isMainContainer(qobject_cast<QWidget*>(w))))
+ existingNames.insert(main->objectName());
+
+ const QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase();
+ const QWidgetList widgetChildren = qFindChildren<QWidget*>(main);
+ if (!widgetChildren.empty())
+ insertNames(metaDataBase, widgetChildren.constBegin(), widgetChildren.constEnd(), w, existingNames);
+
+ const QList<QLayout *> layoutChildren = qFindChildren<QLayout*>(main);
+ if (!layoutChildren.empty())
+ insertNames(metaDataBase, layoutChildren.constBegin(), layoutChildren.constEnd(), w, existingNames);
+
+ const QList<QAction *> actionChildren = qFindChildren<QAction*>(main);
+ if (!actionChildren.empty())
+ insertNames(metaDataBase, actionChildren.constBegin(), actionChildren.constEnd(), w, existingNames);
+
+ const QList<QButtonGroup *> buttonGroupChildren = qFindChildren<QButtonGroup*>(main);
+ if (!buttonGroupChildren.empty())
+ insertNames(metaDataBase, buttonGroupChildren.constBegin(), buttonGroupChildren.constEnd(), w, existingNames);
+
+ const StringSet::const_iterator enEnd = existingNames.constEnd();
+ if (existingNames.constFind(s) == enEnd)
+ return true;
+ else
+ if (!changeIt)
+ return false;
+
+ // split 'name_number'
+ qlonglong num = 0;
+ qlonglong factor = 1;
+ int idx = s.length()-1;
+ const ushort zeroUnicode = QLatin1Char('0').unicode();
+ for ( ; idx > 0 && s.at(idx).isDigit(); --idx) {
+ num += (s.at(idx).unicode() - zeroUnicode) * factor;
+ factor *= 10;
+ }
+ // Position index past '_'.
+ const QChar underscore = QLatin1Char('_');
+ if (idx >= 0 && s.at(idx) == underscore) {
+ idx++;
+ } else {
+ num = 1;
+ s += underscore;
+ idx = s.length();
+ }
+ // try 'name_n', 'name_n+1'
+ for (num++ ; ;num++) {
+ s.truncate(idx);
+ s += QString::number(num);
+ if (existingNames.constFind(s) == enEnd)
+ break;
+ }
+ return false;
+}
+/* already_in_form is true when we are moving a widget from one parent to another inside the same
+ * form. All this means is that InsertWidgetCommand::undo() must not unmanage it. */
+
+void FormWindow::insertWidget(QWidget *w, const QRect &rect, QWidget *container, bool already_in_form)
+{
+ clearSelection(false);
+
+ beginCommand(tr("Insert widget '%1'").arg(WidgetFactory::classNameOf(m_core, w))); // ### use the WidgetDatabaseItem
+
+ /* Reparenting into a QSplitter automatically adjusts child's geometry. We create the geometry
+ * command before we push the reparent command, so that the geometry command has the original
+ * geometry of the widget. */
+ QRect r = rect;
+ Q_ASSERT(r.isValid());
+ SetPropertyCommand *geom_cmd = new SetPropertyCommand(this);
+ geom_cmd->init(w, QLatin1String("geometry"), r); // ### use rc.size()
+
+ if (w->parentWidget() != container) {
+ ReparentWidgetCommand *cmd = new ReparentWidgetCommand(this);
+ cmd->init(w, container);
+ m_commandHistory->push(cmd);
+ }
+
+ m_commandHistory->push(geom_cmd);
+
+ InsertWidgetCommand *cmd = new InsertWidgetCommand(this);
+ cmd->init(w, already_in_form);
+ m_commandHistory->push(cmd);
+
+ endCommand();
+
+ w->show();
+}
+
+QWidget *FormWindow::createWidget(DomUI *ui, const QRect &rc, QWidget *target)
+{
+ QWidget *container = findContainer(target, false);
+ if (!container)
+ return 0;
+ if (isMainContainer(container)) {
+ if (QMainWindow *mw = qobject_cast<QMainWindow*>(container)) {
+ Q_ASSERT(mw->centralWidget() != 0);
+ container = mw->centralWidget();
+ }
+ }
+ QDesignerResource resource(this);
+ const FormBuilderClipboard clipboard = resource.paste(ui, container);
+ if (clipboard.m_widgets.size() != 1) // multiple-paste from DomUI not supported yet
+ return 0;
+ QWidget *widget = clipboard.m_widgets.first();
+ insertWidget(widget, rc, container);
+ return widget;
+}
+
+#ifndef QT_NO_DEBUG
+static bool isDescendant(const QWidget *parent, const QWidget *child)
+{
+ for (; child != 0; child = child->parentWidget()) {
+ if (child == parent)
+ return true;
+ }
+ return false;
+}
+#endif
+
+void FormWindow::resizeWidget(QWidget *widget, const QRect &geometry)
+{
+ Q_ASSERT(isDescendant(this, widget));
+
+ QRect r = geometry;
+ if (m_lastIndex > m_commandHistory->index())
+ m_lastIndex = -1;
+ SetPropertyCommand *cmd = new SetPropertyCommand(this);
+ cmd->init(widget, QLatin1String("geometry"), r);
+ cmd->setText(tr("Resize"));
+ m_commandHistory->push(cmd);
+}
+
+void FormWindow::raiseChildSelections(QWidget *w)
+{
+ const QWidgetList l = qFindChildren<QWidget*>(w);
+ if (l.isEmpty())
+ return;
+ m_selection->raiseList(l);
+}
+
+QWidget *FormWindow::containerAt(const QPoint &pos, QWidget *notParentOf)
+{
+ QWidget *container = 0;
+ int depth = -1;
+ const QWidgetList selected = selectedWidgets();
+ if (rect().contains(mapFromGlobal(pos))) {
+ container = mainContainer();
+ depth = widgetDepth(container);
+ }
+
+ QListIterator<QWidget*> it(m_widgets);
+ while (it.hasNext()) {
+ QWidget *wit = it.next();
+ if (qobject_cast<QLayoutWidget*>(wit) || qobject_cast<QSplitter*>(wit))
+ continue;
+ if (!wit->isVisibleTo(this))
+ continue;
+ if (selected.indexOf(wit) != -1)
+ continue;
+ if (!core()->widgetDataBase()->isContainer(wit) &&
+ wit != mainContainer())
+ continue;
+
+ // the rectangles of all ancestors of the container must contain the insert position
+ QWidget *w = wit;
+ while (w && !w->isWindow()) {
+ if (!w->rect().contains((w->mapFromGlobal(pos))))
+ break;
+ w = w->parentWidget();
+ }
+ if (!(w == 0 || w->isWindow()))
+ continue; // we did not get through the full while loop
+
+ int wd = widgetDepth(wit);
+ if (wd == depth && container) {
+ if (wit->parentWidget()->children().indexOf(wit) >
+ container->parentWidget()->children().indexOf(container))
+ wd++;
+ }
+ if (wd > depth && !isChildOf(wit, notParentOf)) {
+ depth = wd;
+ container = wit;
+ }
+ }
+ return container;
+}
+
+QWidgetList FormWindow::selectedWidgets() const
+{
+ return m_selection->selectedWidgets();
+}
+
+void FormWindow::selectWidgets()
+{
+ bool selectionChanged = false;
+ const QWidgetList l = qFindChildren<QWidget*>(mainContainer());
+ QListIterator <QWidget*> it(l);
+ const QRect selRect(mapToGlobal(m_currRect.topLeft()), m_currRect.size());
+ while (it.hasNext()) {
+ QWidget *w = it.next();
+ if (w->isVisibleTo(this) && isManaged(w)) {
+ const QPoint p = w->mapToGlobal(QPoint(0,0));
+ const QRect r(p, w->size());
+ if (r.intersects(selRect) && !r.contains(selRect) && trySelectWidget(w, true))
+ selectionChanged = true;
+ }
+ }
+
+ if (selectionChanged)
+ emitSelectionChanged();
+}
+
+bool FormWindow::handleKeyPressEvent(QWidget *widget, QWidget *, QKeyEvent *e)
+{
+ if (qobject_cast<const FormWindow*>(widget) || qobject_cast<const QMenu*>(widget))
+ return false;
+
+ e->accept(); // we always accept!
+
+ switch (e->key()) {
+ default: break; // we don't care about the other keys
+
+ case Qt::Key_Delete:
+ case Qt::Key_Backspace:
+ if (e->modifiers() == Qt::NoModifier)
+ deleteWidgets();
+ break;
+
+ case Qt::Key_Tab:
+ if (e->modifiers() == Qt::NoModifier)
+ cursor()->movePosition(QDesignerFormWindowCursorInterface::Next);
+ break;
+
+ case Qt::Key_Backtab:
+ if (e->modifiers() == Qt::NoModifier)
+ cursor()->movePosition(QDesignerFormWindowCursorInterface::Prev);
+ break;
+
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ handleArrowKeyEvent(e->key(), e->modifiers());
+ break;
+ }
+
+ return true;
+}
+
+int FormWindow::getValue(const QRect &rect, int key, bool size) const
+{
+ if (size) {
+ if (key == Qt::Key_Left || key == Qt::Key_Right)
+ return rect.width();
+ return rect.height();
+ }
+ if (key == Qt::Key_Left || key == Qt::Key_Right)
+ return rect.x();
+ return rect.y();
+}
+
+int FormWindow::calcValue(int val, bool forward, bool snap, int snapOffset) const
+{
+ if (snap) {
+ const int rest = val % snapOffset;
+ if (rest) {
+ const int offset = forward ? snapOffset : 0;
+ const int newOffset = rest < 0 ? offset - snapOffset : offset;
+ return val + newOffset - rest;
+ }
+ return (forward ? val + snapOffset : val - snapOffset);
+ }
+ return (forward ? val + 1 : val - 1);
+}
+
+QRect FormWindow::applyValue(const QRect &rect, int val, int key, bool size) const
+{
+ QRect r = rect;
+ if (size) {
+ if (key == Qt::Key_Left || key == Qt::Key_Right)
+ r.setWidth(val);
+ else
+ r.setHeight(val);
+ } else {
+ if (key == Qt::Key_Left || key == Qt::Key_Right)
+ r.moveLeft(val);
+ else
+ r.moveTop(val);
+ }
+ return r;
+}
+
+void FormWindow::handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers)
+{
+ bool startMacro = false;
+ const QDesignerFormWindowCursorInterface *c = cursor();
+ if (!c->hasSelection())
+ return;
+
+ QWidgetList selection;
+
+ // check if a laid out widget is selected
+ const int count = c->selectedWidgetCount();
+ for (int index = 0; index < count; ++index) {
+ QWidget *w = c->selectedWidget(index);
+ if (!LayoutInfo::isWidgetLaidout(m_core, w))
+ selection.append(w);
+ }
+
+ if (selection.isEmpty())
+ return;
+
+ QWidget *current = c->current();
+ if (!current || LayoutInfo::isWidgetLaidout(m_core, current)) {
+ current = selection.first();
+ }
+
+ const bool size = modifiers & Qt::ShiftModifier;
+
+ const bool snap = !(modifiers & Qt::ControlModifier);
+ const bool forward = (key == Qt::Key_Right || key == Qt::Key_Down);
+ const int snapPoint = (key == Qt::Key_Left || key == Qt::Key_Right) ? grid().x() : grid().y();
+
+ const int oldValue = getValue(current->geometry(), key, size);
+
+ const int newValue = calcValue(oldValue, forward, snap, snapPoint);
+
+ const int offset = newValue - oldValue;
+
+ const int selCount = selection.count();
+ // check if selection is the same as last time
+ if (selCount != m_moveSelection.count() ||
+ m_lastUndoIndex != m_commandHistory->index()) {
+ m_moveSelection.clear();
+ startMacro = true;
+ } else {
+ for (int index = 0; index < selCount; ++index) {
+ if (m_moveSelection[index]->object() != selection.at(index)) {
+ m_moveSelection.clear();
+ startMacro = true;
+ break;
+ }
+ }
+ }
+
+ if (startMacro)
+ beginCommand(tr("Key Move"));
+
+ for (int index = 0; index < selCount; ++index) {
+ QWidget *w = selection.at(index);
+ const QRect oldGeom = w->geometry();
+ const QRect geom = applyValue(oldGeom, getValue(oldGeom, key, size) + offset, key, size);
+
+ SetPropertyCommand *cmd = 0;
+
+ if (m_moveSelection.count() > index)
+ cmd = m_moveSelection[index];
+
+ if (!cmd) {
+ cmd = new SetPropertyCommand(this);
+ cmd->init(w, QLatin1String("geometry"), geom);
+ cmd->setText(tr("Key Move"));
+ m_commandHistory->push(cmd);
+
+ if (m_moveSelection.count() > index)
+ m_moveSelection.replace(index, cmd);
+ else
+ m_moveSelection.append(cmd);
+ } else {
+ cmd->setNewValue(geom);
+ cmd->redo();
+ }
+ }
+
+ if (startMacro) {
+ endCommand();
+ m_lastUndoIndex = m_commandHistory->index();
+ }
+}
+
+bool FormWindow::handleKeyReleaseEvent(QWidget *, QWidget *, QKeyEvent *e)
+{
+ e->accept();
+ return true;
+}
+
+void FormWindow::selectAll()
+{
+ bool selectionChanged = false;
+ foreach (QWidget *widget, m_widgets) {
+ if (widget->isVisibleTo(this) && trySelectWidget(widget, true))
+ selectionChanged = true;
+ }
+ if (selectionChanged)
+ emitSelectionChanged();
+}
+
+void FormWindow::createLayout(int type, QWidget *container)
+{
+ if (container) {
+ layoutContainer(container, type);
+ } else {
+ LayoutCommand *cmd = new LayoutCommand(this);
+ cmd->init(mainContainer(), selectedWidgets(), static_cast<LayoutInfo::Type>(type));
+ commandHistory()->push(cmd);
+ }
+}
+
+void FormWindow::morphLayout(QWidget *container, int newType)
+{
+ MorphLayoutCommand *cmd = new MorphLayoutCommand(this);
+ if (cmd->init(container, newType)) {
+ commandHistory()->push(cmd);
+ } else {
+ qDebug() << "** WARNING Unable to morph layout.";
+ delete cmd;
+ }
+}
+
+void FormWindow::deleteWidgets()
+{
+ QWidgetList selection = selectedWidgets();
+ simplifySelection(&selection);
+
+ deleteWidgetList(selection);
+}
+
+QString FormWindow::fileName() const
+{
+ return m_fileName;
+}
+
+void FormWindow::setFileName(const QString &fileName)
+{
+ if (m_fileName == fileName)
+ return;
+
+ m_fileName = fileName;
+ emit fileNameChanged(fileName);
+}
+
+QString FormWindow::contents() const
+{
+ QBuffer b;
+ if (!mainContainer() || !b.open(QIODevice::WriteOnly))
+ return QString();
+
+ QDesignerResource resource(const_cast<FormWindow*>(this));
+ resource.save(&b, mainContainer());
+
+ return QString::fromUtf8(b.buffer());
+}
+
+void FormWindow::copy()
+{
+ QBuffer b;
+ if (!b.open(QIODevice::WriteOnly))
+ return;
+
+ FormBuilderClipboard clipboard;
+ QDesignerResource resource(this);
+ resource.setSaveRelative(false);
+ clipboard.m_widgets = selectedWidgets();
+ simplifySelection(&clipboard.m_widgets);
+ resource.copy(&b, clipboard);
+
+ qApp->clipboard()->setText(QString::fromUtf8(b.buffer()), QClipboard::Clipboard);
+}
+
+void FormWindow::cut()
+{
+ copy();
+ deleteWidgets();
+}
+
+// for cases like QMainWindow (central widget is an inner container) or QStackedWidget (page is an inner container)
+QWidget *FormWindow::innerContainer(QWidget *outerContainer) const
+{
+ bool isContainer = m_core->widgetDataBase()->isContainer(outerContainer);
+ if (isContainer)
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), outerContainer))
+ return container->widget(container->currentIndex());
+ return outerContainer;
+}
+
+QWidget *FormWindow::containerForPaste() const
+{
+ QWidget *w = mainContainer();
+ if (!w)
+ return 0;
+ do {
+ // Try to find a close parent, for example a non-laid-out
+ // QFrame/QGroupBox when a widget within it is selected.
+ QWidgetList selection = selectedWidgets();
+ if (selection.empty())
+ break;
+ simplifySelection(&selection);
+
+ QWidget *containerOfW = findContainer(selection.first(), /* exclude layouts */ true);
+ if (!containerOfW || containerOfW == mainContainer())
+ break;
+ // No layouts, must be container
+ containerOfW = innerContainer(containerOfW);
+ if (LayoutInfo::layoutType(m_core, containerOfW) != LayoutInfo::NoLayout || !m_core->widgetDataBase()->isContainer(containerOfW))
+ break;
+ w = containerOfW;
+ } while (false);
+ // First check for layout (note that it does not cover QMainWindow
+ // and the like as the central widget has the layout).
+
+ w = innerContainer(w);
+ if (LayoutInfo::layoutType(m_core, w) != LayoutInfo::NoLayout)
+ return 0;
+ // Go up via container extension (also includes step from QMainWindow to its central widget)
+ w = m_core->widgetFactory()->containerOfWidget(w);
+ if (w == 0 || LayoutInfo::layoutType(m_core, w) != LayoutInfo::NoLayout)
+ return 0;
+
+ if (debugFormWindow)
+ qDebug() <<"containerForPaste() " << w;
+ return w;
+}
+
+void FormWindow::paste()
+{
+ paste(PasteAll);
+}
+
+// Construct DomUI from clipboard (paste) and determine number of widgets/actions.
+static inline DomUI *domUIFromClipboard(int *widgetCount, int *actionCount)
+{
+ *widgetCount = *actionCount = 0;
+ const QString clipboardText = qApp->clipboard()->text();
+ if (clipboardText.isEmpty() || clipboardText.indexOf(QLatin1Char('<')) == -1)
+ return 0;
+
+ QXmlStreamReader reader(clipboardText);
+ DomUI *ui = 0;
+ const QString uiElement = QLatin1String("ui");
+ while (!reader.atEnd()) {
+ if (reader.readNext() == QXmlStreamReader::StartElement) {
+ if (reader.name().compare(uiElement, Qt::CaseInsensitive) == 0 && !ui) {
+ ui = new DomUI();
+ ui->read(reader);
+ break;
+ } else {
+ reader.raiseError(QCoreApplication::translate("FormWindow", "Unexpected element <%1>").arg(reader.name().toString()));
+ }
+ }
+ }
+ if (reader.hasError()) {
+ delete ui;
+ ui = 0;
+ designerWarning(QCoreApplication::translate("FormWindow", "Error while pasting clipboard contents at line %1, column %2: %3").
+ arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()));
+ return 0;
+ }
+
+ if (const DomWidget *topLevel = ui->elementWidget()) {
+ *widgetCount = topLevel->elementWidget().size();
+ *actionCount = topLevel->elementAction().size();
+ }
+ if (*widgetCount == 0 && *actionCount == 0) {
+ delete ui;
+ return 0;
+ }
+ return ui;
+}
+
+static inline QString pasteCommandDescription(int widgetCount, int actionCount)
+{
+ if (widgetCount == 0)
+ return FormWindow::tr("Paste %n action(s)", 0, actionCount);
+ if (actionCount == 0)
+ return FormWindow::tr("Paste %n widget(s)", 0, widgetCount);
+ return FormWindow::tr("Paste (%1 widgets, %2 actions)").arg(widgetCount).arg(actionCount);
+}
+
+static void positionPastedWidgetsAtMousePosition(FormWindow *fw, const QPoint &contextMenuPosition, QWidget *parent, const QWidgetList &l)
+{
+ // Try to position pasted widgets at mouse position (current mouse position for Ctrl-V or position of context menu)
+ // if it fits. If it is completely outside, force it to 0,0
+ // If it fails, the old coordinates relative to the previous parent will be used.
+ QPoint currentPos = contextMenuPosition.x() >=0 ? parent->mapFrom(fw, contextMenuPosition) : parent->mapFromGlobal(QCursor::pos());
+ const Grid &grid = fw->designerGrid();
+ QPoint cursorPos = grid.snapPoint(currentPos);
+ const QRect parentGeometry = QRect(QPoint(0, 0), parent->size());
+ const bool outside = !parentGeometry.contains(cursorPos);
+ if (outside)
+ cursorPos = grid.snapPoint(QPoint(0, 0));
+ // Determine area of pasted widgets
+ QRect pasteArea;
+ const QWidgetList::const_iterator lcend = l.constEnd();
+ for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it)
+ pasteArea =pasteArea.isNull() ? (*it)->geometry() : pasteArea.united((*it)->geometry());
+
+ // Mouse on some child? (try to position bottomRight on a free spot to
+ // get the stacked-offset effect of Designer 4.3, that is, offset by grid if Ctrl-V is pressed continuously
+ do {
+ const QPoint bottomRight = cursorPos + QPoint(pasteArea.width(), pasteArea.height()) - QPoint(1, 1);
+ if (bottomRight.y() > parentGeometry.bottom() || parent->childAt(bottomRight) == 0)
+ break;
+ cursorPos += QPoint(grid.deltaX(), grid.deltaY());
+ } while (true);
+ // Move.
+ const QPoint offset = cursorPos - pasteArea.topLeft();
+ for (QWidgetList::const_iterator it = l.constBegin(); it != lcend; ++it)
+ (*it)->move((*it)->pos() + offset);
+}
+
+void FormWindow::paste(PasteMode pasteMode)
+{
+ // Avoid QDesignerResource constructing widgets that are not used as
+ // QDesignerResource manages the widgets it creates (creating havoc if one remains unused)
+ DomUI *ui = 0;
+ do {
+ int widgetCount;
+ int actionCount;
+ ui = domUIFromClipboard(&widgetCount, &actionCount);
+ if (!ui)
+ break;
+
+ // Check for actions
+ if (pasteMode == PasteActionsOnly)
+ if (widgetCount != 0 || actionCount == 0)
+ break;
+
+ // Check for widgets: need a container
+ QWidget *pasteContainer = widgetCount ? containerForPaste() : 0;
+ if (widgetCount && pasteContainer == 0) {
+
+ const QString message = tr("Cannot paste widgets. Designer could not find a container "
+ "without a layout to paste into.");
+ const QString infoMessage = tr("Break the layout of the "
+ "container you want to paste into, select this container "
+ "and then paste again.");
+ core()->dialogGui()->message(this, QDesignerDialogGuiInterface::FormEditorMessage, QMessageBox::Information,
+ tr("Paste error"), message, infoMessage, QMessageBox::Ok);
+ break;
+ }
+
+ QDesignerResource resource(this);
+ // Note that the widget factory must be able to locate the
+ // form window (us) via parent, otherwise, it will not able to construct QLayoutWidgets
+ // (It will then default to widgets) among other issues.
+ const FormBuilderClipboard clipboard = resource.paste(ui, pasteContainer, this);
+
+ clearSelection(false);
+ // Create command sequence
+ beginCommand(pasteCommandDescription(widgetCount, actionCount));
+
+ if (widgetCount) {
+ positionPastedWidgetsAtMousePosition(this, m_contextMenuPosition, pasteContainer, clipboard.m_widgets);
+ foreach (QWidget *w, clipboard.m_widgets) {
+ InsertWidgetCommand *cmd = new InsertWidgetCommand(this);
+ cmd->init(w);
+ m_commandHistory->push(cmd);
+ selectWidget(w);
+ }
+ }
+
+ if (actionCount)
+ foreach (QAction *a, clipboard.m_actions) {
+ ensureUniqueObjectName(a);
+ AddActionCommand *cmd = new AddActionCommand(this);
+ cmd->init(a);
+ m_commandHistory->push(cmd);
+ }
+ endCommand();
+ } while (false);
+ delete ui;
+}
+
+// Draw a dotted frame around containers
+bool FormWindow::frameNeeded(QWidget *w) const
+{
+ if (!core()->widgetDataBase()->isContainer(w))
+ return false;
+ if (qobject_cast<QGroupBox *>(w))
+ return false;
+ if (qobject_cast<QToolBox *>(w))
+ return false;
+ if (qobject_cast<QTabWidget *>(w))
+ return false;
+ if (qobject_cast<QStackedWidget *>(w))
+ return false;
+ if (qobject_cast<QDockWidget *>(w))
+ return false;
+ if (qobject_cast<QDesignerWidget *>(w))
+ return false;
+ if (qobject_cast<QMainWindow *>(w))
+ return false;
+ if (qobject_cast<QDialog *>(w))
+ return false;
+ if (qobject_cast<QLayoutWidget *>(w))
+ return false;
+ return true;
+}
+
+bool FormWindow::eventFilter(QObject *watched, QEvent *event)
+{
+ const bool ret = FormWindowBase::eventFilter(watched, event);
+ if (event->type() != QEvent::Paint)
+ return ret;
+
+ Q_ASSERT(watched->isWidgetType());
+ QWidget *w = static_cast<QWidget *>(watched);
+ QPaintEvent *pe = static_cast<QPaintEvent*>(event);
+ const QRect widgetRect = w->rect();
+ const QRect paintRect = pe->rect();
+ // Does the paint rectangle touch the borders of the widget rectangle
+ if (paintRect.x() > widgetRect.x() && paintRect.y() > widgetRect.y() &&
+ paintRect.right() < widgetRect.right() && paintRect.bottom() < widgetRect.bottom())
+ return ret;
+ QPainter p(w);
+ const QPen pen(QColor(0, 0, 0, 32), 0, Qt::DotLine);
+ p.setPen(pen);
+ p.setBrush(QBrush(Qt::NoBrush));
+ p.drawRect(widgetRect.adjusted(0, 0, -1, -1));
+ return ret;
+}
+
+void FormWindow::manageWidget(QWidget *w)
+{
+ if (isManaged(w))
+ return;
+
+ Q_ASSERT(qobject_cast<QMenu*>(w) == 0);
+
+ if (w->hasFocus())
+ setFocus();
+
+ core()->metaDataBase()->add(w);
+
+ m_insertedWidgets.insert(w);
+ m_widgets.append(w);
+
+#ifndef QT_NO_CURSOR
+ setCursorToAll(Qt::ArrowCursor, w);
+#endif
+
+ emit changed();
+ emit widgetManaged(w);
+
+ if (frameNeeded(w))
+ w->installEventFilter(this);
+}
+
+void FormWindow::unmanageWidget(QWidget *w)
+{
+ if (!isManaged(w))
+ return;
+
+ m_selection->removeWidget(w);
+
+ emit aboutToUnmanageWidget(w);
+
+ if (w == m_currentWidget)
+ setCurrentWidget(mainContainer());
+
+ core()->metaDataBase()->remove(w);
+
+ m_insertedWidgets.remove(w);
+ m_widgets.removeAt(m_widgets.indexOf(w));
+
+ emit changed();
+ emit widgetUnmanaged(w);
+
+ if (frameNeeded(w))
+ w->removeEventFilter(this);
+}
+
+bool FormWindow::isManaged(QWidget *w) const
+{
+ return m_insertedWidgets.contains(w);
+}
+
+void FormWindow::breakLayout(QWidget *w)
+{
+ if (w == this)
+ w = mainContainer();
+ // Find the first-order managed child widgets
+ QWidgetList widgets;
+
+ const QObjectList children = w->children();
+ const QObjectList::const_iterator cend = children.constEnd();
+ const QDesignerMetaDataBaseInterface *mdb = core()->metaDataBase();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it)
+ if ( (*it)->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(*it);
+ if (mdb->item(w))
+ widgets.push_back(w);
+ }
+
+ BreakLayoutCommand *cmd = new BreakLayoutCommand(this);
+ cmd->init(widgets, w);
+ commandHistory()->push(cmd);
+ clearSelection(false);
+}
+
+void FormWindow::beginCommand(const QString &description)
+{
+ if (m_lastIndex > m_commandHistory->index())
+ m_lastIndex = -1;
+ m_commandHistory->beginMacro(description);
+}
+
+void FormWindow::endCommand()
+{
+ m_commandHistory->endMacro();
+}
+
+void FormWindow::raiseWidgets()
+{
+ QWidgetList widgets = selectedWidgets();
+ simplifySelection(&widgets);
+
+ if (widgets.isEmpty())
+ return;
+
+ beginCommand(tr("Raise widgets"));
+ foreach (QWidget *widget, widgets) {
+ RaiseWidgetCommand *cmd = new RaiseWidgetCommand(this);
+ cmd->init(widget);
+ m_commandHistory->push(cmd);
+ }
+ endCommand();
+}
+
+void FormWindow::lowerWidgets()
+{
+ QWidgetList widgets = selectedWidgets();
+ simplifySelection(&widgets);
+
+ if (widgets.isEmpty())
+ return;
+
+ beginCommand(tr("Lower widgets"));
+ foreach (QWidget *widget, widgets) {
+ LowerWidgetCommand *cmd = new LowerWidgetCommand(this);
+ cmd->init(widget);
+ m_commandHistory->push(cmd);
+ }
+ endCommand();
+}
+
+bool FormWindow::handleMouseButtonDblClickEvent(QWidget *w, QWidget *managedWidget, QMouseEvent *e)
+{
+ if (debugFormWindow)
+ qDebug() << "handleMouseButtonDblClickEvent:" << w << ',' << managedWidget << "state=" << m_mouseState;
+
+ e->accept();
+
+ // Might be out of sync due cycling of the parent selection
+ // In that case, do nothing
+ if (isWidgetSelected(managedWidget))
+ emit activated(managedWidget);
+
+ m_mouseState = MouseDoubleClicked;
+ return true;
+}
+
+
+QMenu *FormWindow::initializePopupMenu(QWidget *managedWidget)
+{
+ if (!isManaged(managedWidget) || currentTool())
+ return 0;
+
+ // Make sure the managedWidget is selected and current since
+ // the SetPropertyCommands must use the right reference
+ // object obtained from the property editor for the property group
+ // of a multiselection to be correct.
+ const bool selected = isWidgetSelected(managedWidget);
+ bool update = false;
+ if (selected == false) {
+ clearObjectInspectorSelection(m_core); // We might have a toolbar or non-widget selected in the object inspector.
+ clearSelection(false);
+ update = trySelectWidget(managedWidget, true);
+ raiseChildSelections(managedWidget); // raise selections and select widget
+ } else {
+ update = setCurrentWidget(managedWidget);
+ }
+
+ if (update) {
+ emitSelectionChanged();
+ QMetaObject::invokeMethod(core()->formWindowManager(), "slotUpdateActions");
+ }
+
+ QWidget *contextMenuWidget = 0;
+
+ if (isMainContainer(managedWidget)) { // press on a child widget
+ contextMenuWidget = mainContainer();
+ } else { // press on a child widget
+ // if widget is laid out, find the first non-laid out super-widget
+ QWidget *realWidget = managedWidget; // but store the original one
+ QMainWindow *mw = qobject_cast<QMainWindow*>(mainContainer());
+
+ if (mw && mw->centralWidget() == realWidget) {
+ contextMenuWidget = managedWidget;
+ } else {
+ contextMenuWidget = realWidget;
+ }
+ }
+
+ if (!contextMenuWidget)
+ return 0;
+
+ QMenu *contextMenu = createPopupMenu(contextMenuWidget);
+ if (!contextMenu)
+ return 0;
+
+ emit contextMenuRequested(contextMenu, contextMenuWidget);
+ return contextMenu;
+}
+
+bool FormWindow::handleContextMenu(QWidget *, QWidget *managedWidget, QContextMenuEvent *e)
+{
+ QMenu *contextMenu = initializePopupMenu(managedWidget);
+ if (!contextMenu)
+ return false;
+ const QPoint globalPos = e->globalPos();
+ m_contextMenuPosition = mapFromGlobal (globalPos);
+ contextMenu->exec(globalPos);
+ delete contextMenu;
+ e->accept();
+ m_contextMenuPosition = QPoint(-1, -1);
+ return true;
+}
+
+void FormWindow::setContents(QIODevice *dev)
+{
+ UpdateBlocker ub(this);
+ clearSelection();
+ m_selection->clearSelectionPool();
+ m_insertedWidgets.clear();
+ m_widgets.clear();
+ // The main container is cleared as otherwise
+ // the names of the newly loaded objects will be unified.
+ clearMainContainer();
+ emit changed();
+
+ QDesignerResource r(this);
+ QWidget *w = r.load(dev, formContainer());
+ setMainContainer(w);
+ emit changed();
+}
+
+void FormWindow::setContents(const QString &contents)
+{
+ QByteArray data = contents.toUtf8();
+ QBuffer b(&data);
+ if (b.open(QIODevice::ReadOnly))
+ setContents(&b);
+}
+
+void FormWindow::layoutContainer(QWidget *w, int type)
+{
+ if (w == this)
+ w = mainContainer();
+
+ w = core()->widgetFactory()->containerOfWidget(w);
+
+ const QObjectList l = w->children();
+ if (l.isEmpty())
+ return;
+ // find managed widget children
+ QWidgetList widgets;
+ const QObjectList::const_iterator ocend = l.constEnd();
+ for (QObjectList::const_iterator it = l.constBegin(); it != l.constEnd(); ++it)
+ if ( (*it)->isWidgetType() ) {
+ QWidget *widget = static_cast<QWidget*>(*it);
+ if (widget->isVisibleTo(this) && isManaged(widget))
+ widgets.append(widget);
+ }
+
+ LayoutCommand *cmd = new LayoutCommand(this);
+ cmd->init(mainContainer(), widgets, static_cast<LayoutInfo::Type>(type), w);
+ clearSelection(false);
+ commandHistory()->push(cmd);
+}
+
+bool FormWindow::hasInsertedChildren(QWidget *widget) const // ### move
+{
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) {
+ widget = container->widget(container->currentIndex());
+ }
+
+ const QWidgetList l = widgets(widget);
+
+ foreach (QWidget *child, l) {
+ if (isManaged(child) && !LayoutInfo::isWidgetLaidout(core(), child) && child->isVisibleTo(const_cast<FormWindow*>(this)))
+ return true;
+ }
+
+ return false;
+}
+
+// "Select Ancestor" sub menu code
+void FormWindow::slotSelectWidget(QAction *a)
+{
+ if (QWidget *w = qvariant_cast<QWidget*>(a->data()))
+ selectSingleWidget(w);
+}
+
+static inline QString objectNameOf(const QWidget *w)
+{
+ if (const QLayoutWidget *lw = qobject_cast<const QLayoutWidget *>(w)) {
+ const QLayout *layout = lw->layout();
+ const QString rc = layout->objectName();
+ if (!rc.isEmpty())
+ return rc;
+ // Fall thru for 4.3 forms which have a name on the widget: Display the class name
+ return QString::fromUtf8(layout->metaObject()->className());
+ }
+ return w->objectName();
+}
+
+QAction *FormWindow::createSelectAncestorSubMenu(QWidget *w)
+{
+ // Find the managed, unselected parents
+ QWidgetList parents;
+ QWidget *mc = mainContainer();
+ for (QWidget *p = w->parentWidget(); p && p != mc; p = p->parentWidget())
+ if (isManaged(p) && !isWidgetSelected(p))
+ parents.push_back(p);
+ if (parents.empty())
+ return 0;
+ // Create a submenu listing the managed, unselected parents
+ QMenu *menu = new QMenu;
+ QActionGroup *ag = new QActionGroup(menu);
+ QObject::connect(ag, SIGNAL(triggered(QAction*)), this, SLOT(slotSelectWidget(QAction*)));
+ const int size = parents.size();
+ for (int i = 0; i < size; i++) {
+ QWidget *w = parents.at(i);
+ QAction *a = ag->addAction(objectNameOf(w));
+ a->setData(qVariantFromValue(w));
+ menu->addAction(a);
+ }
+ QAction *ma = new QAction(tr("Select Ancestor"), 0);
+ ma->setMenu(menu);
+ return ma;
+}
+
+QMenu *FormWindow::createPopupMenu(QWidget *w)
+{
+ QMenu *popup = createExtensionTaskMenu(this, w, true);
+ if (!popup)
+ popup = new QMenu;
+ // if w doesn't have a QDesignerTaskMenu as a child create one and make it a child.
+ // insert actions from QDesignerTaskMenu
+
+ QDesignerFormWindowManagerInterface *manager = core()->formWindowManager();
+ const bool isFormWindow = qobject_cast<const FormWindow*>(w);
+
+ // Check for special containers and obtain the page menu from them to add layout actions.
+ if (!isFormWindow) {
+ if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(w)) {
+ QStackedWidgetEventFilter::addStackedWidgetContextMenuActions(stackedWidget, popup);
+ } else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(w)) {
+ QTabWidgetEventFilter::addTabWidgetContextMenuActions(tabWidget, popup);
+ } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(w)) {
+ QToolBoxHelper::addToolBoxContextMenuActions(toolBox, popup);
+ }
+
+ popup->addAction(manager->actionCut());
+ popup->addAction(manager->actionCopy());
+ }
+
+ popup->addAction(manager->actionPaste());
+
+ if (QAction *selectAncestorAction = createSelectAncestorSubMenu(w))
+ popup->addAction(selectAncestorAction);
+ popup->addAction(manager->actionSelectAll());
+
+ if (!isFormWindow) {
+ popup->addAction(manager->actionDelete());
+ }
+
+ popup->addSeparator();
+ QMenu *layoutMenu = popup->addMenu(tr("Lay out"));
+ layoutMenu->addAction(manager->actionAdjustSize());
+ layoutMenu->addAction(manager->actionHorizontalLayout());
+ layoutMenu->addAction(manager->actionVerticalLayout());
+ layoutMenu->addAction(manager->actionGridLayout());
+ layoutMenu->addAction(manager->actionFormLayout());
+ if (!isFormWindow) {
+ layoutMenu->addAction(manager->actionSplitHorizontal());
+ layoutMenu->addAction(manager->actionSplitVertical());
+ }
+ layoutMenu->addAction(manager->actionBreakLayout());
+ layoutMenu->addAction(manager->actionSimplifyLayout());
+
+ return popup;
+}
+
+void FormWindow::resizeEvent(QResizeEvent *e)
+{
+ m_geometryChangedTimer->start(10);
+
+ QWidget::resizeEvent(e);
+}
+
+/*!
+ Maps \a pos in \a w's coordinates to the form's coordinate system.
+
+ This is the equivalent to mapFromGlobal(w->mapToGlobal(pos)) but
+ avoids the two roundtrips to the X-Server on Unix/X11.
+ */
+QPoint FormWindow::mapToForm(const QWidget *w, const QPoint &pos) const
+{
+ QPoint p = pos;
+ const QWidget* i = w;
+ while (i && !i->isWindow() && !isMainContainer(i)) {
+ p = i->mapToParent(p);
+ i = i->parentWidget();
+ }
+
+ return mapFromGlobal(w->mapToGlobal(pos));
+}
+
+bool FormWindow::canBeBuddy(QWidget *w) const // ### rename me.
+{
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), w)) {
+ const int index = sheet->indexOf(QLatin1String("focusPolicy"));
+ if (index != -1) {
+ bool ok = false;
+ const Qt::FocusPolicy q = static_cast<Qt::FocusPolicy>(Utils::valueOf(sheet->property(index), &ok));
+ return ok && q != Qt::NoFocus;
+ }
+ }
+
+ return false;
+}
+
+QWidget *FormWindow::findContainer(QWidget *w, bool excludeLayout) const
+{
+ if (!isChildOf(w, this)
+ || const_cast<const QWidget *>(w) == this)
+ return 0;
+
+ QDesignerWidgetFactoryInterface *widgetFactory = core()->widgetFactory();
+ QDesignerWidgetDataBaseInterface *widgetDataBase = core()->widgetDataBase();
+ QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase();
+
+ QWidget *container = widgetFactory->containerOfWidget(mainContainer()); // default parent for new widget is the formwindow
+ if (!isMainContainer(w)) { // press was not on formwindow, check if we can find another parent
+ while (w) {
+ if (qobject_cast<InvisibleWidget*>(w) || !metaDataBase->item(w)) {
+ w = w->parentWidget();
+ continue;
+ }
+
+ const bool isContainer = widgetDataBase->isContainer(w, true) || w == mainContainer();
+
+ if (!isContainer || (excludeLayout && qobject_cast<QLayoutWidget*>(w))) { // ### skip QSplitter
+ w = w->parentWidget();
+ } else {
+ container = w;
+ break;
+ }
+ }
+ }
+
+ return container;
+}
+
+void FormWindow::simplifySelection(QWidgetList *sel) const
+{
+ if (sel->size() < 2)
+ return;
+ // Figure out which widgets should be removed from selection.
+ // We want to remove those whose parent widget is also in the
+ // selection (because the child widgets are contained by
+ // their parent, they shouldn't be in the selection --
+ // they are "implicitly" selected).
+ QWidget *mainC = mainContainer(); // Quick check for main container first
+ if (sel->contains(mainC)) {
+ sel->clear();
+ sel->push_back(mainC);
+ return;
+ }
+ typedef QVector<QWidget *> WidgetVector;
+ WidgetVector toBeRemoved;
+ toBeRemoved.reserve(sel->size());
+ const QWidgetList::const_iterator scend = sel->constEnd();
+ for (QWidgetList::const_iterator it = sel->constBegin(); it != scend; ++it) {
+ QWidget *child = *it;
+ for (QWidget *w = child; true ; ) { // Is any of the parents also selected?
+ QWidget *parent = w->parentWidget();
+ if (!parent || parent == mainC)
+ break;
+ if (sel->contains(parent)) {
+ toBeRemoved.append(child);
+ break;
+ }
+ w = parent;
+ }
+ }
+ // Now we can actually remove the widgets that were marked
+ // for removal in the previous pass.
+ if (!toBeRemoved.isEmpty()) {
+ const WidgetVector::const_iterator rcend = toBeRemoved.constEnd();
+ for (WidgetVector::const_iterator it = toBeRemoved.constBegin(); it != rcend; ++it)
+ sel->removeAll(*it);
+ }
+}
+
+FormWindow *FormWindow::findFormWindow(QWidget *w)
+{
+ return qobject_cast<FormWindow*>(QDesignerFormWindowInterface::findFormWindow(w));
+}
+
+bool FormWindow::isDirty() const
+{
+ return m_dirty;
+}
+
+void FormWindow::setDirty(bool dirty)
+{
+ m_dirty = dirty;
+
+ if (!m_dirty)
+ m_lastIndex = m_commandHistory->index();
+}
+
+void FormWindow::updateDirty()
+{
+ m_dirty = m_commandHistory->index() != m_lastIndex;
+}
+
+QWidget *FormWindow::containerAt(const QPoint &pos)
+{
+ QWidget *widget = widgetAt(pos);
+ return findContainer(widget, true);
+}
+
+static QWidget *childAt_SkipDropLine(QWidget *w, QPoint pos)
+{
+ const QObjectList child_list = w->children();
+ for (int i = child_list.size() - 1; i >= 0; --i) {
+ QObject *child_obj = child_list[i];
+ if (qobject_cast<WidgetHandle*>(child_obj) != 0)
+ continue;
+ QWidget *child = qobject_cast<QWidget*>(child_obj);
+ if (!child || child->isWindow() || !child->isVisible() ||
+ !child->geometry().contains(pos) || child->testAttribute(Qt::WA_TransparentForMouseEvents))
+ continue;
+ const QPoint childPos = child->mapFromParent(pos);
+ if (QWidget *res = childAt_SkipDropLine(child, childPos))
+ return res;
+ if (child->testAttribute(Qt::WA_MouseNoMask) || child->mask().contains(pos)
+ || child->mask().isEmpty())
+ return child;
+ }
+
+ return 0;
+}
+
+QWidget *FormWindow::widgetAt(const QPoint &pos)
+{
+ QWidget *w = childAt(pos);
+ if (qobject_cast<const WidgetHandle*>(w) != 0)
+ w = childAt_SkipDropLine(this, pos);
+ return (w == 0 || w == formContainer()) ? this : w;
+}
+
+void FormWindow::highlightWidget(QWidget *widget, const QPoint &pos, HighlightMode mode)
+{
+ Q_ASSERT(widget);
+
+ if (QMainWindow *mainWindow = qobject_cast<QMainWindow*> (widget)) {
+ widget = mainWindow->centralWidget();
+ }
+
+ QWidget *container = findContainer(widget, false);
+
+ if (container == 0 || core()->metaDataBase()->item(container) == 0)
+ return;
+
+ if (QDesignerActionProviderExtension *g = qt_extension<QDesignerActionProviderExtension*>(core()->extensionManager(), container)) {
+ if (mode == Restore) {
+ g->adjustIndicator(QPoint());
+ } else {
+ const QPoint pt = widget->mapTo(container, pos);
+ g->adjustIndicator(pt);
+ }
+ } else if (QDesignerLayoutDecorationExtension *g = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), container)) {
+ if (mode == Restore) {
+ g->adjustIndicator(QPoint(), -1);
+ } else {
+ const QPoint pt = widget->mapTo(container, pos);
+ const int index = g->findItemAt(pt);
+ g->adjustIndicator(pt, index);
+ }
+ }
+
+ QMainWindow *mw = qobject_cast<QMainWindow*> (container);
+ if (container == mainContainer() || (mw && mw->centralWidget() && mw->centralWidget() == container))
+ return;
+
+ if (mode == Restore) {
+ const WidgetPaletteMap::iterator pit = m_palettesBeforeHighlight.find(container);
+ if (pit != m_palettesBeforeHighlight.end()) {
+ container->setPalette(pit.value().first);
+ container->setAutoFillBackground(pit.value().second);
+ m_palettesBeforeHighlight.erase(pit);
+ }
+ } else {
+ QPalette p = container->palette();
+ if (!m_palettesBeforeHighlight.contains(container)) {
+ PaletteAndFill paletteAndFill;
+ if (container->testAttribute(Qt::WA_SetPalette))
+ paletteAndFill.first = p;
+ paletteAndFill.second = container->autoFillBackground();
+ m_palettesBeforeHighlight.insert(container, paletteAndFill);
+ }
+
+ p.setColor(backgroundRole(), p.midlight().color());
+ container->setPalette(p);
+ container->setAutoFillBackground(true);
+ }
+}
+
+QWidgetList FormWindow::widgets(QWidget *widget) const
+{
+ const QObjectList children = widget->children();
+ if (children.empty())
+ return QWidgetList();
+ QWidgetList rc;
+ const QObjectList::const_iterator cend = children.constEnd();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it)
+ if ((*it)->isWidgetType()) {
+ QWidget *w = qobject_cast<QWidget*>(*it);
+ if (isManaged(w))
+ rc.push_back(w);
+ }
+ return rc;
+}
+
+int FormWindow::toolCount() const
+{
+ return m_widgetStack->count();
+}
+
+QDesignerFormWindowToolInterface *FormWindow::tool(int index) const
+{
+ return m_widgetStack->tool(index);
+}
+
+void FormWindow::registerTool(QDesignerFormWindowToolInterface *tool)
+{
+ Q_ASSERT(tool != 0);
+
+ m_widgetStack->addTool(tool);
+
+ if (m_mainContainer)
+ m_mainContainer->update();
+}
+
+void FormWindow::setCurrentTool(int index)
+{
+ m_widgetStack->setCurrentTool(index);
+}
+
+int FormWindow::currentTool() const
+{
+ return m_widgetStack->currentIndex();
+}
+
+bool FormWindow::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event)
+{
+ if (m_widgetStack == 0)
+ return false;
+
+ QDesignerFormWindowToolInterface *tool = m_widgetStack->currentTool();
+ if (tool == 0)
+ return false;
+
+ return tool->handleEvent(widget, managedWidget, event);
+}
+
+void FormWindow::initializeCoreTools()
+{
+ m_widgetEditor = new WidgetEditorTool(this);
+ registerTool(m_widgetEditor);
+}
+
+void FormWindow::checkSelection()
+{
+ m_checkSelectionTimer->start(0);
+}
+
+void FormWindow::checkSelectionNow()
+{
+ m_checkSelectionTimer->stop();
+
+ foreach (QWidget *widget, selectedWidgets()) {
+ updateSelection(widget);
+
+ if (LayoutInfo::layoutType(core(), widget) != LayoutInfo::NoLayout)
+ updateChildSelections(widget);
+ }
+}
+
+QString FormWindow::author() const
+{
+ return m_author;
+}
+
+QString FormWindow::comment() const
+{
+ return m_comment;
+}
+
+void FormWindow::setAuthor(const QString &author)
+{
+ m_author = author;
+}
+
+void FormWindow::setComment(const QString &comment)
+{
+ m_comment = comment;
+}
+
+void FormWindow::editWidgets()
+{
+ m_widgetEditor->action()->trigger();
+}
+
+QStringList FormWindow::resourceFiles() const
+{
+ return m_resourceFiles;
+}
+
+void FormWindow::addResourceFile(const QString &path)
+{
+ if (!m_resourceFiles.contains(path)) {
+ m_resourceFiles.append(path);
+ setDirty(true);
+ emit resourceFilesChanged();
+ }
+}
+
+void FormWindow::removeResourceFile(const QString &path)
+{
+ if (m_resourceFiles.removeAll(path) > 0) {
+ setDirty(true);
+ emit resourceFilesChanged();
+ }
+}
+
+bool FormWindow::blockSelectionChanged(bool b)
+{
+ const bool blocked = m_blockSelectionChanged;
+ m_blockSelectionChanged = b;
+ return blocked;
+}
+
+void FormWindow::editContents()
+{
+ const QWidgetList sel = selectedWidgets();
+ if (sel.count() == 1) {
+ QWidget *widget = sel.first();
+
+ if (QAction *a = preferredEditAction(core(), widget))
+ a->trigger();
+ }
+}
+
+void FormWindow::dragWidgetWithinForm(QWidget *widget, const QRect &targetGeometry, QWidget *targetContainer)
+{
+ const bool fromLayout = canDragWidgetInLayout(core(), widget);
+ const QDesignerLayoutDecorationExtension *targetDeco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), targetContainer);
+ const bool toLayout = targetDeco != 0;
+
+ if (fromLayout) {
+ // Drag from Layout: We need to delete the widget properly to store the layout state
+ // Do not simplify the layout when dragging onto a layout
+ // as this might invalidate the insertion position if it is the same layout
+ DeleteWidgetCommand *cmd = new DeleteWidgetCommand(this);
+ unsigned deleteFlags = DeleteWidgetCommand::DoNotUnmanage;
+ if (toLayout)
+ deleteFlags |= DeleteWidgetCommand::DoNotSimplifyLayout;
+ cmd->init(widget, deleteFlags);
+ commandHistory()->push(cmd);
+ }
+
+ if (toLayout) {
+ // Drag from form to layout: just insert. Do not manage
+ insertWidget(widget, targetGeometry, targetContainer, true);
+ } else {
+ // into container without layout
+ if (targetContainer != widget->parent()) { // different parent
+ ReparentWidgetCommand *cmd = new ReparentWidgetCommand(this);
+ cmd->init(widget, targetContainer );
+ commandHistory()->push(cmd);
+ }
+ resizeWidget(widget, targetGeometry);
+ selectWidget(widget, true);
+ widget->show();
+ }
+}
+
+static Qt::DockWidgetArea detectDropArea(QMainWindow *mainWindow, const QRect &area, const QPoint &drop)
+{
+ QPoint offset = area.topLeft();
+ QRect rect = area;
+ rect.moveTopLeft(QPoint(0, 0));
+ QPoint point = drop - offset;
+ const int x = point.x();
+ const int y = point.y();
+ const int w = rect.width();
+ const int h = rect.height();
+
+ if (rect.contains(point)) {
+ bool topRight = false;
+ bool topLeft = false;
+ if (w * y < h * x) // top and right, oterwise bottom and left
+ topRight = true;
+ if (w * y < h * (w - x)) // top and left, otherwise bottom and right
+ topLeft = true;
+
+ if (topRight && topLeft)
+ return Qt::TopDockWidgetArea;
+ else if (topRight && !topLeft)
+ return Qt::RightDockWidgetArea;
+ else if (!topRight && topLeft)
+ return Qt::LeftDockWidgetArea;
+ return Qt::BottomDockWidgetArea;
+ }
+
+ if (x < 0) {
+ if (y < 0)
+ return mainWindow->corner(Qt::TopLeftCorner);
+ else if (y > h)
+ return mainWindow->corner(Qt::BottomLeftCorner);
+ else
+ return Qt::LeftDockWidgetArea;
+ } else if (x > w) {
+ if (y < 0)
+ return mainWindow->corner(Qt::TopRightCorner);
+ else if (y > h)
+ return mainWindow->corner(Qt::BottomRightCorner);
+ else
+ return Qt::RightDockWidgetArea;
+ } else {
+ if (y < 0)
+ return Qt::TopDockWidgetArea;
+ else
+ return Qt::BottomDockWidgetArea;
+ }
+ return Qt::LeftDockWidgetArea;
+}
+
+bool FormWindow::dropDockWidget(QDesignerDnDItemInterface *item, const QPoint &global_mouse_pos)
+{
+ DomUI *dom_ui = item->domUi();
+
+ QMainWindow *mw = qobject_cast<QMainWindow *>(mainContainer());
+ if (!mw)
+ return false;
+
+ QDesignerResource resource(this);
+ const FormBuilderClipboard clipboard = resource.paste(dom_ui, mw);
+ if (clipboard.m_widgets.size() != 1) // multiple-paste from DomUI not supported yet
+ return false;
+
+ QWidget *centralWidget = mw->centralWidget();
+ QPoint localPos = centralWidget->mapFromGlobal(global_mouse_pos);
+ const QRect centralWidgetAreaRect = centralWidget->rect();
+ Qt::DockWidgetArea area = detectDropArea(mw, centralWidgetAreaRect, localPos);
+
+ beginCommand(tr("Drop widget"));
+
+ clearSelection(false);
+ highlightWidget(mw, QPoint(0, 0), FormWindow::Restore);
+
+ QWidget *widget = clipboard.m_widgets.first();
+
+ insertWidget(widget, QRect(0, 0, 1, 1), mw);
+
+ selectWidget(widget, true);
+ mw->setFocus(Qt::MouseFocusReason); // in case focus was in e.g. object inspector
+
+ core()->formWindowManager()->setActiveFormWindow(this);
+ mainContainer()->activateWindow();
+
+ QDesignerPropertySheetExtension *propertySheet = qobject_cast<QDesignerPropertySheetExtension*>(m_core->extensionManager()->extension(widget, Q_TYPEID(QDesignerPropertySheetExtension)));
+ if (propertySheet) {
+ const QString dockWidgetAreaName = QLatin1String("dockWidgetArea");
+ PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(propertySheet->property(propertySheet->indexOf(dockWidgetAreaName)));
+ e.value = area;
+ QVariant v;
+ qVariantSetValue(v, e);
+ SetPropertyCommand *cmd = new SetPropertyCommand(this);
+ cmd->init(widget, dockWidgetAreaName, v);
+ m_commandHistory->push(cmd);
+ }
+
+ endCommand();
+ return true;
+}
+
+bool FormWindow::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, QWidget *target,
+ const QPoint &global_mouse_pos)
+{
+
+ QWidget *parent = target;
+ if (parent == 0)
+ parent = mainContainer();
+ // You can only drop stuff onto the central widget of a QMainWindow
+ // ### generalize to use container extension
+ if (QMainWindow *main_win = qobject_cast<QMainWindow*>(target)) {
+ if (!main_win->centralWidget()) {
+ designerWarning(tr("A QMainWindow-based form does not contain a central widget."));
+ return false;
+ }
+ const QPoint main_win_pos = main_win->mapFromGlobal(global_mouse_pos);
+ const QRect central_wgt_geo = main_win->centralWidget()->geometry();
+ if (!central_wgt_geo.contains(main_win_pos))
+ return false;
+ }
+
+ QWidget *container = findContainer(parent, false);
+ if (container == 0)
+ return false;
+
+ beginCommand(tr("Drop widget"));
+
+ clearSelection(false);
+ highlightWidget(target, target->mapFromGlobal(global_mouse_pos), FormWindow::Restore);
+
+ QPoint offset;
+ QDesignerDnDItemInterface *current = 0;
+ QDesignerFormWindowCursorInterface *c = cursor();
+ foreach (QDesignerDnDItemInterface *item, item_list) {
+ QWidget *w = item->widget();
+ if (!current)
+ current = item;
+ if (c->current() == w) {
+ current = item;
+ break;
+ }
+ }
+ if (current) {
+ QRect geom = current->decoration()->geometry();
+ QPoint topLeft = container->mapFromGlobal(geom.topLeft());
+ offset = designerGrid().snapPoint(topLeft) - topLeft;
+ }
+
+ foreach (QDesignerDnDItemInterface *item, item_list) {
+ DomUI *dom_ui = item->domUi();
+ QRect geometry = item->decoration()->geometry();
+ Q_ASSERT(dom_ui != 0);
+
+ geometry.moveTopLeft(container->mapFromGlobal(geometry.topLeft()) + offset);
+ if (item->type() == QDesignerDnDItemInterface::CopyDrop) { // from widget box or CTRL + mouse move
+ QWidget *widget = createWidget(dom_ui, geometry, parent);
+ if (!widget) {
+ endCommand();
+ return false;
+ }
+ selectWidget(widget, true);
+ mainContainer()->setFocus(Qt::MouseFocusReason); // in case focus was in e.g. object inspector
+ } else { // same form move
+ QWidget *widget = item->widget();
+ Q_ASSERT(widget != 0);
+ QDesignerFormWindowInterface *dest = findFormWindow(widget);
+ if (dest == this) {
+ dragWidgetWithinForm(widget, geometry, container);
+ } else { // from other form
+ FormWindow *source = qobject_cast<FormWindow*>(item->source());
+ Q_ASSERT(source != 0);
+
+ source->deleteWidgetList(QWidgetList() << widget);
+ QWidget *new_widget = createWidget(dom_ui, geometry, parent);
+
+ selectWidget(new_widget, true);
+ }
+ }
+ }
+
+ core()->formWindowManager()->setActiveFormWindow(this);
+ mainContainer()->activateWindow();
+ endCommand();
+ return true;
+}
+
+QDir FormWindow::absoluteDir() const
+{
+ if (fileName().isEmpty())
+ return QDir::current();
+
+ return QFileInfo(fileName()).absoluteDir();
+}
+
+void FormWindow::layoutDefault(int *margin, int *spacing)
+{
+ *margin = m_defaultMargin;
+ *spacing = m_defaultSpacing;
+}
+
+void FormWindow::setLayoutDefault(int margin, int spacing)
+{
+ m_defaultMargin = margin;
+ m_defaultSpacing = spacing;
+}
+
+void FormWindow::layoutFunction(QString *margin, QString *spacing)
+{
+ *margin = m_marginFunction;
+ *spacing = m_spacingFunction;
+}
+
+void FormWindow::setLayoutFunction(const QString &margin, const QString &spacing)
+{
+ m_marginFunction = margin;
+ m_spacingFunction = spacing;
+}
+
+QString FormWindow::pixmapFunction() const
+{
+ return m_pixmapFunction;
+}
+
+void FormWindow::setPixmapFunction(const QString &pixmapFunction)
+{
+ m_pixmapFunction = pixmapFunction;
+}
+
+QStringList FormWindow::includeHints() const
+{
+ return m_includeHints;
+}
+
+void FormWindow::setIncludeHints(const QStringList &includeHints)
+{
+ m_includeHints = includeHints;
+}
+
+QString FormWindow::exportMacro() const
+{
+ return m_exportMacro;
+}
+
+void FormWindow::setExportMacro(const QString &exportMacro)
+{
+ m_exportMacro = exportMacro;
+}
+
+QEditorFormBuilder *FormWindow::createFormBuilder()
+{
+ return new QDesignerResource(this);
+}
+
+QWidget *FormWindow::formContainer() const
+{
+ return m_widgetStack->formContainer();
+}
+
+} // namespace
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formwindow.h b/tools/designer/src/components/formeditor/formwindow.h
new file mode 100644
index 0000000000..7e50ca2f8d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindow.h
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOW_H
+#define FORMWINDOW_H
+
+#include "formeditor_global.h"
+#include <formwindowbase_p.h>
+
+// Qt
+#include <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QSet>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerDnDItemInterface;
+class QDesignerTaskMenuExtension;
+class DomConnections;
+
+class QWidget;
+class QAction;
+class QLabel;
+class QTimer;
+class QAction;
+class QMenu;
+class QUndoStack;
+class QRubberBand;
+
+namespace qdesigner_internal {
+
+class FormEditor;
+class FormWindowCursor;
+class WidgetEditorTool;
+class FormWindowWidgetStack;
+class FormWindowManager;
+class FormWindowDnDItem;
+class SetPropertyCommand;
+
+class QT_FORMEDITOR_EXPORT FormWindow: public FormWindowBase
+{
+ Q_OBJECT
+
+public:
+ explicit FormWindow(FormEditor *core, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~FormWindow();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual QDesignerFormWindowCursorInterface *cursor() const;
+
+ // Overwritten: FormWindowBase
+ virtual QWidget *formContainer() const;
+
+ virtual int toolCount() const;
+ virtual int currentTool() const;
+ virtual void setCurrentTool(int index);
+ virtual QDesignerFormWindowToolInterface *tool(int index) const;
+ virtual void registerTool(QDesignerFormWindowToolInterface *tool);
+
+ virtual QString author() const;
+ virtual void setAuthor(const QString &author);
+
+ virtual QString comment() const;
+ virtual void setComment(const QString &comment);
+
+ virtual void layoutDefault(int *margin, int *spacing);
+ virtual void setLayoutDefault(int margin, int spacing);
+
+ virtual void layoutFunction(QString *margin, QString *spacing);
+ virtual void setLayoutFunction(const QString &margin, const QString &spacing);
+
+ virtual QString pixmapFunction() const;
+ virtual void setPixmapFunction(const QString &pixmapFunction);
+
+ virtual QString exportMacro() const;
+ virtual void setExportMacro(const QString &exportMacro);
+
+ virtual QStringList includeHints() const;
+ virtual void setIncludeHints(const QStringList &includeHints);
+
+ virtual QString fileName() const;
+ virtual void setFileName(const QString &fileName);
+
+ virtual QString contents() const;
+ virtual void setContents(const QString &contents);
+ virtual void setContents(QIODevice *dev);
+
+ virtual QDir absoluteDir() const;
+
+ virtual void simplifySelection(QWidgetList *sel) const;
+
+ virtual void ensureUniqueObjectName(QObject *object);
+
+ virtual QWidget *mainContainer() const;
+ void setMainContainer(QWidget *mainContainer);
+ bool isMainContainer(const QWidget *w) const;
+
+ QWidget *currentWidget() const;
+
+ bool hasInsertedChildren(QWidget *w) const;
+
+ QList<QWidget *> selectedWidgets() const;
+ void clearSelection(bool changePropertyDisplay=true);
+ bool isWidgetSelected(QWidget *w) const;
+ void selectWidget(QWidget *w, bool select=true);
+
+ void selectWidgets();
+ void repaintSelection();
+ void updateSelection(QWidget *w);
+ void updateChildSelections(QWidget *w);
+ void raiseChildSelections(QWidget *w);
+ void raiseSelection(QWidget *w);
+
+ inline const QList<QWidget *>& widgets() const { return m_widgets; }
+ inline int widgetCount() const { return m_widgets.count(); }
+ inline QWidget *widgetAt(int index) const { return m_widgets.at(index); }
+
+ QList<QWidget *> widgets(QWidget *widget) const;
+
+ QWidget *createWidget(DomUI *ui, const QRect &rect, QWidget *target);
+
+ bool isManaged(QWidget *w) const;
+
+ void manageWidget(QWidget *w);
+ void unmanageWidget(QWidget *w);
+
+ inline QUndoStack *commandHistory() const
+ { return m_commandHistory; }
+
+ void beginCommand(const QString &description);
+ void endCommand();
+
+ virtual bool blockSelectionChanged(bool blocked);
+ virtual void emitSelectionChanged();
+
+ bool unify(QObject *w, QString &s, bool changeIt);
+
+ bool isDirty() const;
+ void setDirty(bool dirty);
+
+ static FormWindow *findFormWindow(QWidget *w);
+
+ virtual QWidget *containerAt(const QPoint &pos);
+ virtual QWidget *widgetAt(const QPoint &pos);
+ virtual void highlightWidget(QWidget *w, const QPoint &pos,
+ HighlightMode mode = Highlight);
+
+ void updateOrderIndicators();
+
+ bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event);
+
+ QStringList resourceFiles() const;
+ void addResourceFile(const QString &path);
+ void removeResourceFile(const QString &path);
+
+ void resizeWidget(QWidget *widget, const QRect &geometry);
+
+ bool dropDockWidget(QDesignerDnDItemInterface *item, const QPoint &global_mouse_pos);
+ bool dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, QWidget *target,
+ const QPoint &global_mouse_pos);
+
+ virtual QWidget *findContainer(QWidget *w, bool excludeLayout) const;
+ // for WidgetSelection only.
+ QWidget *designerWidget(QWidget *w) const;
+
+ // Initialize and return a popup menu for a managed widget
+ QMenu *initializePopupMenu(QWidget *managedWidget);
+
+ virtual void paste(PasteMode pasteMode);
+ virtual QEditorFormBuilder *createFormBuilder();
+
+ bool eventFilter(QObject *watched, QEvent *event);
+
+signals:
+ void contextMenuRequested(QMenu *menu, QWidget *widget);
+
+public slots:
+ void deleteWidgets();
+ void raiseWidgets();
+ void lowerWidgets();
+ void copy();
+ void cut();
+ void paste();
+ void selectAll();
+
+ void createLayout(int type, QWidget *container = 0);
+ void morphLayout(QWidget *container, int newType);
+ void breakLayout(QWidget *w);
+
+ void editContents();
+
+protected:
+ virtual QMenu *createPopupMenu(QWidget *w);
+ virtual void resizeEvent(QResizeEvent *e);
+
+ void insertWidget(QWidget *w, const QRect &rect, QWidget *target, bool already_in_form = false);
+
+private slots:
+ void selectionChangedTimerDone();
+ void updateDirty();
+ void checkSelection();
+ void checkSelectionNow();
+ void slotSelectWidget(QAction *);
+
+private:
+ enum MouseState {
+ NoMouseState,
+ // Double click received
+ MouseDoubleClicked,
+ // Drawing selection rubber band rectangle
+ MouseDrawRubber,
+ // Started a move operation
+ MouseMoveDrag,
+ // Click on a widget whose parent is selected. Defer selection to release
+ MouseDeferredSelection
+ };
+ MouseState m_mouseState;
+ QPointer<QWidget> m_lastClickedWidget;
+
+ void init();
+ void initializeCoreTools();
+
+ int getValue(const QRect &rect, int key, bool size) const;
+ int calcValue(int val, bool forward, bool snap, int snapOffset) const;
+ QRect applyValue(const QRect &rect, int val, int key, bool size) const;
+ void handleClickSelection(QWidget *managedWidget, unsigned mouseFlags);
+
+ bool frameNeeded(QWidget *w) const;
+
+ enum RectType { Insert, Rubber };
+
+ void startRectDraw(const QPoint &global, QWidget *, RectType t);
+ void continueRectDraw(const QPoint &global, QWidget *, RectType t);
+ void endRectDraw();
+
+ QWidget *containerAt(const QPoint &pos, QWidget *notParentOf);
+
+ void checkPreviewGeometry(QRect &r);
+
+ void finishContextMenu(QWidget *w, QWidget *menuParent, QContextMenuEvent *e);
+
+ bool handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e);
+ bool handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleMouseMoveEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleMouseReleaseEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleKeyPressEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e);
+ bool handleKeyReleaseEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e);
+
+ bool isCentralWidget(QWidget *w) const;
+
+ bool setCurrentWidget(QWidget *currentWidget);
+ bool trySelectWidget(QWidget *w, bool select);
+
+ void dragWidgetWithinForm(QWidget *widget, const QRect &targetGeometry, QWidget *targetContainer);
+
+ void setCursorToAll(const QCursor &c, QWidget *start);
+
+ QPoint mapToForm(const QWidget *w, const QPoint &pos) const;
+ bool canBeBuddy(QWidget *w) const;
+
+ QWidget *findTargetContainer(QWidget *widget) const;
+
+ void clearMainContainer();
+
+ static int widgetDepth(const QWidget *w);
+ static bool isChildOf(const QWidget *c, const QWidget *p);
+
+ void editWidgets();
+
+ void updateWidgets();
+
+ void handleArrowKeyEvent(int key, Qt::KeyboardModifiers modifiers);
+
+ void layoutSelection(int type);
+ void layoutContainer(QWidget *w, int type);
+
+private:
+ QWidget *innerContainer(QWidget *outerContainer) const;
+ QWidget *containerForPaste() const;
+ QAction *createSelectAncestorSubMenu(QWidget *w);
+ void selectSingleWidget(QWidget *w);
+
+ FormEditor *m_core;
+ FormWindowCursor *m_cursor;
+ QWidget *m_mainContainer;
+ QWidget *m_currentWidget;
+
+ bool m_blockSelectionChanged;
+
+ QPoint m_rectAnchor;
+ QRect m_currRect;
+
+ QWidgetList m_widgets;
+ QSet<QWidget*> m_insertedWidgets;
+
+ class Selection;
+ Selection *m_selection;
+
+ QPoint m_startPos;
+
+ QUndoStack *m_commandHistory;
+
+ QString m_fileName;
+
+ typedef QPair<QPalette ,bool> PaletteAndFill;
+ typedef QMap<QWidget*, PaletteAndFill> WidgetPaletteMap;
+ WidgetPaletteMap m_palettesBeforeHighlight;
+
+ QRubberBand *m_rubberBand;
+
+ QTimer *m_selectionChangedTimer;
+ QTimer *m_checkSelectionTimer;
+ QTimer *m_geometryChangedTimer;
+
+ int m_dirty;
+ int m_lastIndex;
+
+ FormWindowWidgetStack *m_widgetStack;
+ WidgetEditorTool *m_widgetEditor;
+
+ QStringList m_resourceFiles;
+
+ QString m_comment;
+ QString m_author;
+ QString m_pixmapFunction;
+ int m_defaultMargin, m_defaultSpacing;
+ QString m_marginFunction, m_spacingFunction;
+ QString m_exportMacro;
+ QStringList m_includeHints;
+
+ QList<SetPropertyCommand*> m_moveSelection;
+ int m_lastUndoIndex;
+ QPoint m_contextMenuPosition;
+
+private:
+ friend class WidgetEditorTool;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOW_H
diff --git a/tools/designer/src/components/formeditor/formwindow_dnditem.cpp b/tools/designer/src/components/formeditor/formwindow_dnditem.cpp
new file mode 100644
index 0000000000..3af5343d8d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindow_dnditem.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formwindow_dnditem.h"
+#include "formwindow.h"
+
+#include <ui4_p.h>
+#include <qdesigner_resource.h>
+#include <qtresourcemodel_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QLabel>
+#include <QtGui/QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+static QWidget *decorationFromWidget(QWidget *w)
+{
+ QLabel *label = new QLabel(0, Qt::ToolTip);
+ QPixmap pm = QPixmap::grabWidget(w);
+ label->setPixmap(pm);
+ label->resize(pm.size());
+
+ return label;
+}
+
+static DomUI *widgetToDom(QWidget *widget, FormWindow *form)
+{
+ QDesignerResource builder(form);
+ builder.setSaveRelative(false);
+ return builder.copy(FormBuilderClipboard(widget));
+}
+
+FormWindowDnDItem::FormWindowDnDItem(QDesignerDnDItemInterface::DropType type, FormWindow *form,
+ QWidget *widget, const QPoint &global_mouse_pos)
+ : QDesignerDnDItem(type, form)
+{
+ QWidget *decoration = decorationFromWidget(widget);
+ QPoint pos = widget->mapToGlobal(QPoint(0, 0));
+ decoration->move(pos);
+
+ init(0, widget, decoration, global_mouse_pos);
+}
+
+DomUI *FormWindowDnDItem::domUi() const
+{
+ DomUI *result = QDesignerDnDItem::domUi();
+ if (result != 0)
+ return result;
+ FormWindow *form = qobject_cast<FormWindow*>(source());
+ if (widget() == 0 || form == 0)
+ return 0;
+
+ QtResourceModel *resourceModel = form->core()->resourceModel();
+ QtResourceSet *currentResourceSet = resourceModel->currentResourceSet();
+ /* Short:
+ * We need to activate the original resourceSet associated with a form
+ * to properly generate the dom resource includes.
+ * Long:
+ * widgetToDom() calls copy() on QDesignerResource. It generates the
+ * Dom structure. In order to create DomResources properly we need to
+ * have the associated ResourceSet active (QDesignerResource::saveResources()
+ * queries the resource model for a qrc path for the given resource file:
+ * qrcFile = m_core->resourceModel()->qrcPath(ri->text());
+ * This works only when the resource file comes from the active
+ * resourceSet */
+ resourceModel->setCurrentResourceSet(form->resourceSet());
+
+ result = widgetToDom(widget(), form);
+ const_cast<FormWindowDnDItem*>(this)->setDomUi(result);
+ resourceModel->setCurrentResourceSet(currentResourceSet);
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formwindow_dnditem.h b/tools/designer/src/components/formeditor/formwindow_dnditem.h
new file mode 100644
index 0000000000..c6e74791fa
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindow_dnditem.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOW_DNDITEM_H
+#define FORMWINDOW_DNDITEM_H
+
+#include <qdesigner_dnditem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class FormWindow;
+
+class FormWindowDnDItem : public QDesignerDnDItem
+{
+public:
+ FormWindowDnDItem(QDesignerDnDItemInterface::DropType type, FormWindow *form,
+ QWidget *widget, const QPoint &global_mouse_pos);
+ virtual DomUI *domUi() const;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOW_DNDITEM_H
diff --git a/tools/designer/src/components/formeditor/formwindow_widgetstack.cpp b/tools/designer/src/components/formeditor/formwindow_widgetstack.cpp
new file mode 100644
index 0000000000..72706280aa
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindow_widgetstack.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formwindow_widgetstack.h"
+#include <QtDesigner/QDesignerFormWindowToolInterface>
+
+#include <QtGui/QWidget>
+#include <QtGui/qevent.h>
+#include <QtGui/QAction>
+#include <QtGui/QStackedLayout>
+#include <QtGui/QVBoxLayout>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+FormWindowWidgetStack::FormWindowWidgetStack(QObject *parent) :
+ QObject(parent),
+ m_formContainer(new QWidget),
+ m_formContainerLayout(new QVBoxLayout),
+ m_layout(new QStackedLayout)
+{
+ m_layout->setMargin(0);
+ m_layout->setSpacing(0);
+ m_layout->setStackingMode(QStackedLayout::StackAll);
+
+ m_formContainerLayout->setMargin(0);
+ m_formContainer->setObjectName(QLatin1String("formContainer"));
+ m_formContainer->setLayout(m_formContainerLayout);
+ // System settings might have different background colors, autofill them
+ // (affects for example mainwindow status bars)
+ m_formContainer->setAutoFillBackground(true);
+}
+
+FormWindowWidgetStack::~FormWindowWidgetStack()
+{
+}
+
+int FormWindowWidgetStack::count() const
+{
+ return m_tools.count();
+}
+
+QDesignerFormWindowToolInterface *FormWindowWidgetStack::currentTool() const
+{
+ return tool(currentIndex());
+}
+
+void FormWindowWidgetStack::setCurrentTool(int index)
+{
+ const int cnt = count();
+ if (index < 0 || index >= cnt) {
+ qDebug("FormWindowWidgetStack::setCurrentTool(): invalid index: %d", index);
+ return;
+ }
+
+ const int cur = currentIndex();
+ if (index == cur)
+ return;
+
+ if (cur != -1)
+ m_tools.at(cur)->deactivated();
+
+
+ m_layout->setCurrentIndex(index);
+ // Show the widget editor and the current tool
+ for (int i = 0; i < cnt; i++)
+ m_tools.at(i)->editor()->setVisible(i == 0 || i == index);
+
+ QDesignerFormWindowToolInterface *tool = m_tools.at(index);
+ tool->activated();
+
+ emit currentToolChanged(index);
+}
+
+void FormWindowWidgetStack::setSenderAsCurrentTool()
+{
+ QDesignerFormWindowToolInterface *tool = 0;
+ QAction *action = qobject_cast<QAction*>(sender());
+ if (action == 0) {
+ qDebug("FormWindowWidgetStack::setSenderAsCurrentTool(): sender is not a QAction");
+ return;
+ }
+
+ foreach (QDesignerFormWindowToolInterface *t, m_tools) {
+ if (action == t->action()) {
+ tool = t;
+ break;
+ }
+ }
+
+ if (tool == 0) {
+ qDebug("FormWindowWidgetStack::setSenderAsCurrentTool(): unknown tool");
+ return;
+ }
+
+ setCurrentTool(tool);
+}
+
+int FormWindowWidgetStack::indexOf(QDesignerFormWindowToolInterface *tool) const
+{
+ return m_tools.indexOf(tool);
+}
+
+void FormWindowWidgetStack::setCurrentTool(QDesignerFormWindowToolInterface *tool)
+{
+ int index = indexOf(tool);
+ if (index == -1) {
+ qDebug("FormWindowWidgetStack::setCurrentTool(): unknown tool");
+ return;
+ }
+
+ setCurrentTool(index);
+}
+
+void FormWindowWidgetStack::setMainContainer(QWidget *w)
+{
+ // This code is triggered once by the formwindow and
+ // by integrations doing "revert to saved". Anything changing?
+ const int previousCount = m_formContainerLayout->count();
+ QWidget *previousMainContainer = previousCount ? m_formContainerLayout->itemAt(0)->widget() : static_cast<QWidget*>(0);
+ if (previousMainContainer == w)
+ return;
+ // Swap
+ if (previousCount)
+ delete m_formContainerLayout->takeAt(0);
+ if (w)
+ m_formContainerLayout->addWidget(w);
+}
+
+void FormWindowWidgetStack::addTool(QDesignerFormWindowToolInterface *tool)
+{
+ if (QWidget *w = tool->editor()) {
+ w->setVisible(m_layout->count() == 0); // Initially only form editor is visible
+ m_layout->addWidget(w);
+ } else {
+ // The form editor might not have a tool initially, use dummy. Assert on anything else
+ Q_ASSERT(m_tools.empty());
+ m_layout->addWidget(m_formContainer);
+ }
+
+ m_tools.append(tool);
+
+ connect(tool->action(), SIGNAL(triggered()), this, SLOT(setSenderAsCurrentTool()));
+}
+
+QDesignerFormWindowToolInterface *FormWindowWidgetStack::tool(int index) const
+{
+ if (index < 0 || index >= count())
+ return 0;
+
+ return m_tools.at(index);
+}
+
+int FormWindowWidgetStack::currentIndex() const
+{
+ return m_layout->currentIndex();
+}
+
+QWidget *FormWindowWidgetStack::defaultEditor() const
+{
+ if (m_tools.isEmpty())
+ return 0;
+
+ return m_tools.at(0)->editor();
+}
+
+QLayout *FormWindowWidgetStack::layout() const
+{
+ return m_layout;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formwindow_widgetstack.h b/tools/designer/src/components/formeditor/formwindow_widgetstack.h
new file mode 100644
index 0000000000..92323c5a63
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindow_widgetstack.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOW_WIDGETSTACK_H
+#define FORMWINDOW_WIDGETSTACK_H
+
+#include "formeditor_global.h"
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowToolInterface;
+
+class QStackedLayout;
+class QVBoxLayout;
+class QWidget;
+
+namespace qdesigner_internal {
+
+class QT_FORMEDITOR_EXPORT FormWindowWidgetStack: public QObject
+{
+ Q_OBJECT
+public:
+ FormWindowWidgetStack(QObject *parent = 0);
+ virtual ~FormWindowWidgetStack();
+
+ QLayout *layout() const;
+
+ int count() const;
+ QDesignerFormWindowToolInterface *tool(int index) const;
+ QDesignerFormWindowToolInterface *currentTool() const;
+ int currentIndex() const;
+ int indexOf(QDesignerFormWindowToolInterface *tool) const;
+
+ void setMainContainer(QWidget *w = 0);
+
+ // Return the widget containing the form which can be used to apply embedded design settings to.
+ // These settings should not affect the other editing tools.
+ QWidget *formContainer() const { return m_formContainer; }
+
+signals:
+ void currentToolChanged(int index);
+
+public slots:
+ void addTool(QDesignerFormWindowToolInterface *tool);
+ void setCurrentTool(QDesignerFormWindowToolInterface *tool);
+ void setCurrentTool(int index);
+ void setSenderAsCurrentTool();
+
+protected:
+ QWidget *defaultEditor() const;
+
+private:
+ QList<QDesignerFormWindowToolInterface*> m_tools;
+ QWidget *m_formContainer;
+ QVBoxLayout *m_formContainerLayout;
+ QStackedLayout *m_layout;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOW_WIDGETSTACK_H
diff --git a/tools/designer/src/components/formeditor/formwindowcursor.cpp b/tools/designer/src/components/formeditor/formwindowcursor.cpp
new file mode 100644
index 0000000000..5b4aee1888
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindowcursor.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::FormWindowCursor
+*/
+
+#include "formwindowcursor.h"
+#include "formwindow.h"
+
+// sdk
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/QExtensionManager>
+#include <qdesigner_propertycommand_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+FormWindowCursor::FormWindowCursor(FormWindow *fw, QObject *parent)
+ : QObject(parent),
+ m_formWindow(fw)
+{
+ update();
+ connect(fw, SIGNAL(changed()), this, SLOT(update()));
+}
+
+FormWindowCursor::~FormWindowCursor()
+{
+}
+
+QDesignerFormWindowInterface *FormWindowCursor::formWindow() const
+{
+ return m_formWindow;
+}
+
+bool FormWindowCursor::movePosition(MoveOperation op, MoveMode mode)
+{
+ if (widgetCount() == 0)
+ return false;
+
+ int iterator = position();
+
+ if (mode == MoveAnchor)
+ m_formWindow->clearSelection(false);
+
+ switch (op) {
+ case Next:
+ ++iterator;
+ if (iterator >= widgetCount())
+ iterator = 0;
+
+ m_formWindow->selectWidget(m_formWindow->widgetAt(iterator), true);
+ return true;
+
+ case Prev:
+ --iterator;
+ if (iterator < 0)
+ iterator = widgetCount() - 1;
+
+ if (iterator < 0)
+ return false;
+
+ m_formWindow->selectWidget(m_formWindow->widgetAt(iterator), true);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+int FormWindowCursor::position() const
+{
+ const int index = m_formWindow->widgets().indexOf(current());
+ return index == -1 ? 0 : index;
+}
+
+void FormWindowCursor::setPosition(int pos, MoveMode mode)
+{
+ if (!widgetCount())
+ return;
+
+ if (mode == MoveAnchor)
+ m_formWindow->clearSelection(false);
+
+ if (pos >= widgetCount())
+ pos = 0;
+
+ m_formWindow->selectWidget(m_formWindow->widgetAt(pos), true);
+}
+
+QWidget *FormWindowCursor::current() const
+{
+ return m_formWindow->currentWidget();
+}
+
+bool FormWindowCursor::hasSelection() const
+{
+ return !m_formWindow->selectedWidgets().isEmpty();
+}
+
+int FormWindowCursor::selectedWidgetCount() const
+{
+ int N = m_formWindow->selectedWidgets().count();
+ return N ? N : 1;
+}
+
+QWidget *FormWindowCursor::selectedWidget(int index) const
+{
+ return hasSelection()
+ ? m_formWindow->selectedWidgets().at(index)
+ : m_formWindow->mainContainer();
+}
+
+void FormWindowCursor::update()
+{
+ // ### todo
+}
+
+int FormWindowCursor::widgetCount() const
+{
+ return m_formWindow->widgetCount();
+}
+
+QWidget *FormWindowCursor::widget(int index) const
+{
+ return m_formWindow->widgetAt(index);
+}
+
+void FormWindowCursor::setProperty(const QString &name, const QVariant &value)
+{
+
+ // build selection
+ const int N = selectedWidgetCount();
+ Q_ASSERT(N);
+
+ SetPropertyCommand::ObjectList selection;
+ for (int i=0; i<N; ++i)
+ selection.push_back(selectedWidget(i));
+
+
+ SetPropertyCommand* setPropertyCommand = new SetPropertyCommand(m_formWindow);
+ if (setPropertyCommand->init(selection, name, value, current())) {
+ m_formWindow->commandHistory()->push(setPropertyCommand);
+ } else {
+ delete setPropertyCommand;
+ qDebug() << "Unable to set property " << name << '.';
+ }
+}
+
+void FormWindowCursor::setWidgetProperty(QWidget *widget, const QString &name, const QVariant &value)
+{
+ SetPropertyCommand *cmd = new SetPropertyCommand(m_formWindow);
+ if (cmd->init(widget, name, value)) {
+ m_formWindow->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ qDebug() << "Unable to set property " << name << '.';
+ }
+}
+
+void FormWindowCursor::resetWidgetProperty(QWidget *widget, const QString &name)
+{
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(m_formWindow);
+ if (cmd->init(widget, name)) {
+ m_formWindow->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ qDebug() << "Unable to reset property " << name << '.';
+ }
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formwindowcursor.h b/tools/designer/src/components/formeditor/formwindowcursor.h
new file mode 100644
index 0000000000..716743250e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindowcursor.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOWCURSOR_H
+#define FORMWINDOWCURSOR_H
+
+#include "formeditor_global.h"
+#include "formwindow.h"
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QT_FORMEDITOR_EXPORT FormWindowCursor: public QObject, public QDesignerFormWindowCursorInterface
+{
+ Q_OBJECT
+public:
+ explicit FormWindowCursor(FormWindow *fw, QObject *parent = 0);
+ virtual ~FormWindowCursor();
+
+ virtual QDesignerFormWindowInterface *formWindow() const;
+
+ virtual bool movePosition(MoveOperation op, MoveMode mode);
+
+ virtual int position() const;
+ virtual void setPosition(int pos, MoveMode mode);
+
+ virtual QWidget *current() const;
+
+ virtual int widgetCount() const;
+ virtual QWidget *widget(int index) const;
+
+ virtual bool hasSelection() const;
+ virtual int selectedWidgetCount() const;
+ virtual QWidget *selectedWidget(int index) const;
+
+ virtual void setProperty(const QString &name, const QVariant &value);
+ virtual void setWidgetProperty(QWidget *widget, const QString &name, const QVariant &value);
+ virtual void resetWidgetProperty(QWidget *widget, const QString &name);
+
+public slots:
+ void update();
+
+private:
+ FormWindow *m_formWindow;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOWCURSOR_H
diff --git a/tools/designer/src/components/formeditor/formwindowmanager.cpp b/tools/designer/src/components/formeditor/formwindowmanager.cpp
new file mode 100644
index 0000000000..69fb4a3fbf
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindowmanager.cpp
@@ -0,0 +1,1020 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::FormWindowManager
+*/
+
+// components/formeditor
+#include "formwindowmanager.h"
+#include "formwindow_dnditem.h"
+#include "formwindow.h"
+#include "formeditor.h"
+#include "widgetselection.h"
+#include "previewactiongroup.h"
+#include "formwindowsettings.h"
+
+// shared
+#include <widgetdatabase_p.h>
+#include <iconloader_p.h>
+#include <connectionedit_p.h>
+#include <qtresourcemodel_p.h>
+#include <qdesigner_dnditem_p.h>
+#include <qdesigner_command_p.h>
+#include <qdesigner_command2_p.h>
+#include <layoutinfo_p.h>
+#include <qlayout_widget_p.h>
+#include <qdesigner_objectinspector_p.h>
+#include <actioneditor_p.h>
+#include <shared_settings_p.h>
+#include <previewmanager_p.h>
+#include <abstractdialoggui_p.h>
+#include <widgetfactory_p.h>
+#include <spacer_widget_p.h>
+
+// SDK
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+#include <QtDesigner/QDesignerIntegrationInterface>
+
+#include <QtGui/QUndoGroup>
+#include <QtGui/QAction>
+#include <QtGui/QSplitter>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QApplication>
+#include <QtGui/QSizeGrip>
+#include <QtGui/QClipboard>
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QMessageBox>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { debugFWM = 0 };
+}
+
+static inline QString whatsThisFrom(const QString &str) { /// ### implement me!
+ return str;
+}
+
+// find the first child of w in a sequence
+template <class Iterator>
+static inline Iterator findFirstChildOf(Iterator it,Iterator end, const QWidget *w)
+{
+ for (;it != end; ++it) {
+ if (w->isAncestorOf(*it))
+ return it;
+ }
+ return it;
+}
+
+namespace qdesigner_internal {
+
+FormWindowManager::FormWindowManager(QDesignerFormEditorInterface *core, QObject *parent) :
+ QDesignerFormWindowManager(parent),
+ m_core(core),
+ m_activeFormWindow(0),
+ m_previewManager(new PreviewManager(PreviewManager::SingleFormNonModalPreview, this)),
+ m_createLayoutContext(LayoutContainer),
+ m_morphLayoutContainer(0),
+ m_actionGroupPreviewInStyle(0),
+ m_actionShowFormWindowSettingsDialog(0)
+{
+ setupActions();
+ qApp->installEventFilter(this);
+}
+
+FormWindowManager::~FormWindowManager()
+{
+ qDeleteAll(m_formWindows);
+}
+
+QDesignerFormEditorInterface *FormWindowManager::core() const
+{
+ return m_core;
+}
+
+QDesignerFormWindowInterface *FormWindowManager::activeFormWindow() const
+{
+ return m_activeFormWindow;
+}
+
+int FormWindowManager::formWindowCount() const
+{
+ return m_formWindows.size();
+}
+
+QDesignerFormWindowInterface *FormWindowManager::formWindow(int index) const
+{
+ return m_formWindows.at(index);
+}
+
+bool FormWindowManager::eventFilter(QObject *o, QEvent *e)
+{
+ if (!o->isWidgetType())
+ return false;
+
+ // If we don't have an active form, we only listen for WindowActivate to speed up integrations
+ const QEvent::Type eventType = e->type();
+ if (m_activeFormWindow == 0 && eventType != QEvent::WindowActivate)
+ return false;
+
+ switch (eventType) { // Uninteresting events
+ case QEvent::Create:
+ case QEvent::Destroy:
+ case QEvent::AccessibilityDescription:
+ case QEvent::AccessibilityHelp:
+ case QEvent::AccessibilityPrepare:
+ case QEvent::ActionAdded:
+ case QEvent::ActionChanged:
+ case QEvent::ActionRemoved:
+ case QEvent::ChildAdded:
+ case QEvent::ChildPolished:
+ case QEvent::ChildRemoved:
+ case QEvent::Clipboard:
+ case QEvent::ContentsRectChange:
+ case QEvent::DeferredDelete:
+ case QEvent::FileOpen:
+ case QEvent::LanguageChange:
+ case QEvent::MetaCall:
+ case QEvent::ModifiedChange:
+ case QEvent::Paint:
+ case QEvent::PaletteChange:
+ case QEvent::ParentAboutToChange:
+ case QEvent::ParentChange:
+ case QEvent::Polish:
+ case QEvent::PolishRequest:
+ case QEvent::QueryWhatsThis:
+ case QEvent::StatusTip:
+ case QEvent::StyleChange:
+ case QEvent::Timer:
+ case QEvent::ToolBarChange:
+ case QEvent::ToolTip:
+ case QEvent::WhatsThis:
+ case QEvent::WhatsThisClicked:
+ case QEvent::DynamicPropertyChange:
+ case QEvent::HoverEnter:
+ case QEvent::HoverLeave:
+ case QEvent::HoverMove:
+ return false;
+ default:
+ break;
+ }
+
+ QWidget *widget = static_cast<QWidget*>(o);
+
+ if (qobject_cast<WidgetHandle*>(widget)) { // ### remove me
+ return false;
+ }
+
+ FormWindow *fw = FormWindow::findFormWindow(widget);
+ if (fw == 0) {
+ return false;
+ }
+
+ if (QWidget *managedWidget = findManagedWidget(fw, widget)) {
+ // Prevent MDI and QWorkspace subwindows from being closed by clicking at the title bar
+ if (managedWidget != widget && eventType == QEvent::Close) {
+ e->ignore();
+ return true;
+ }
+ switch (eventType) {
+
+ case QEvent::WindowActivate: {
+ if (fw->parentWidget()->isWindow() && fw->isMainContainer(managedWidget) && activeFormWindow() != fw) {
+ setActiveFormWindow(fw);
+ }
+ } break;
+
+ case QEvent::WindowDeactivate: {
+ if (o == fw && o == activeFormWindow())
+ fw->repaintSelection();
+ } break;
+
+ case QEvent::KeyPress: {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Escape) {
+ ke->accept();
+ return true;
+ }
+ }
+ // don't break...
+ // Embedded Design: Drop on different form: Make sure the right form
+ // window/device is active before having the widget created by the factory
+ case QEvent::Drop:
+ if (activeFormWindow() != fw)
+ setActiveFormWindow(fw);
+ // don't break...
+ default: {
+ if (fw->handleEvent(widget, managedWidget, e)) {
+ return true;
+ }
+ } break;
+
+ } // end switch
+ }
+
+ return false;
+}
+
+void FormWindowManager::addFormWindow(QDesignerFormWindowInterface *w)
+{
+ FormWindow *formWindow = qobject_cast<FormWindow*>(w);
+ if (!formWindow || m_formWindows.contains(formWindow))
+ return;
+
+ connect(formWindow, SIGNAL(selectionChanged()), this, SLOT(slotUpdateActions()));
+ connect(formWindow->commandHistory(), SIGNAL(indexChanged(int)), this, SLOT(slotUpdateActions()));
+ connect(formWindow, SIGNAL(toolChanged(int)), this, SLOT(slotUpdateActions()));
+
+ if (ActionEditor *ae = qobject_cast<ActionEditor *>(m_core->actionEditor()))
+ connect(w, SIGNAL(mainContainerChanged(QWidget*)), ae, SLOT(mainContainerChanged()));
+ if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(m_core->objectInspector()))
+ connect(w, SIGNAL(mainContainerChanged(QWidget*)), oi, SLOT(mainContainerChanged()));
+
+ m_formWindows.append(formWindow);
+ emit formWindowAdded(formWindow);
+}
+
+void FormWindowManager::removeFormWindow(QDesignerFormWindowInterface *w)
+{
+ FormWindow *formWindow = qobject_cast<FormWindow*>(w);
+
+ int idx = m_formWindows.indexOf(formWindow);
+ if (!formWindow || idx == -1)
+ return;
+
+ formWindow->disconnect(this);
+ m_formWindows.removeAt(idx);
+ emit formWindowRemoved(formWindow);
+
+ if (formWindow == m_activeFormWindow)
+ setActiveFormWindow(0);
+
+ if (m_formWindows.size() == 0
+ && m_core->widgetBox()) {
+ // Make sure that widget box is enabled by default
+ m_core->widgetBox()->setEnabled(true);
+ }
+
+}
+
+void FormWindowManager::setActiveFormWindow(QDesignerFormWindowInterface *w)
+{
+ FormWindow *formWindow = qobject_cast<FormWindow*>(w);
+
+ if (formWindow == m_activeFormWindow)
+ return;
+
+ FormWindow *old = m_activeFormWindow;
+
+ m_activeFormWindow = formWindow;
+
+ QtResourceSet *resourceSet = 0;
+ if (formWindow)
+ resourceSet = formWindow->resourceSet();
+ m_core->resourceModel()->setCurrentResourceSet(resourceSet);
+
+ slotUpdateActions();
+
+ if (m_activeFormWindow) {
+ m_activeFormWindow->repaintSelection();
+ if (old)
+ old->repaintSelection();
+ }
+
+ emit activeFormWindowChanged(m_activeFormWindow);
+
+ if (m_activeFormWindow) {
+ m_activeFormWindow->emitSelectionChanged();
+ m_activeFormWindow->commandHistory()->setActive();
+ // Trigger setActiveSubWindow on mdi area unless we are in toplevel mode
+ QMdiSubWindow *mdiSubWindow = 0;
+ if (QWidget *formwindow = m_activeFormWindow->parentWidget()) {
+ mdiSubWindow = qobject_cast<QMdiSubWindow *>(formwindow->parentWidget());
+ }
+ if (mdiSubWindow) {
+ for (QWidget *parent = mdiSubWindow->parentWidget(); parent; parent = parent->parentWidget()) {
+ if (QMdiArea *mdiArea = qobject_cast<QMdiArea*>(parent)) {
+ mdiArea->setActiveSubWindow(mdiSubWindow);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void FormWindowManager::closeAllPreviews()
+{
+ m_previewManager->closeAllPreviews();
+}
+
+QWidget *FormWindowManager::findManagedWidget(FormWindow *fw, QWidget *w)
+{
+ while (w && w != fw) {
+ if (fw->isManaged(w))
+ break;
+ w = w->parentWidget();
+ }
+ return w;
+}
+
+void FormWindowManager::setupActions()
+{
+ m_actionCut = new QAction(createIconSet(QLatin1String("editcut.png")), tr("Cu&t"), this);
+ m_actionCut->setObjectName(QLatin1String("__qt_cut_action"));
+ m_actionCut->setShortcut(QKeySequence::Cut);
+ m_actionCut->setStatusTip(tr("Cuts the selected widgets and puts them on the clipboard"));
+ m_actionCut->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Cut")));
+ connect(m_actionCut, SIGNAL(triggered()), this, SLOT(slotActionCutActivated()));
+ m_actionCut->setEnabled(false);
+
+ m_actionCopy = new QAction(createIconSet(QLatin1String("editcopy.png")), tr("&Copy"), this);
+ m_actionCopy->setObjectName(QLatin1String("__qt_copy_action"));
+ m_actionCopy->setShortcut(QKeySequence::Copy);
+ m_actionCopy->setStatusTip(tr("Copies the selected widgets to the clipboard"));
+ m_actionCopy->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Copy")));
+ connect(m_actionCopy, SIGNAL(triggered()), this, SLOT(slotActionCopyActivated()));
+ m_actionCopy->setEnabled(false);
+
+ m_actionPaste = new QAction(createIconSet(QLatin1String("editpaste.png")), tr("&Paste"), this);
+ m_actionPaste->setObjectName(QLatin1String("__qt_paste_action"));
+ m_actionPaste->setShortcut(QKeySequence::Paste);
+ m_actionPaste->setStatusTip(tr("Pastes the clipboard's contents"));
+ m_actionPaste->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Paste")));
+ connect(m_actionPaste, SIGNAL(triggered()), this, SLOT(slotActionPasteActivated()));
+ m_actionPaste->setEnabled(false);
+
+ m_actionDelete = new QAction(tr("&Delete"), this);
+ m_actionDelete->setObjectName(QLatin1String("__qt_delete_action"));
+ m_actionDelete->setStatusTip(tr("Deletes the selected widgets"));
+ m_actionDelete->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Delete")));
+ connect(m_actionDelete, SIGNAL(triggered()), this, SLOT(slotActionDeleteActivated()));
+ m_actionDelete->setEnabled(false);
+
+ m_actionSelectAll = new QAction(tr("Select &All"), this);
+ m_actionSelectAll->setObjectName(QLatin1String("__qt_select_all_action"));
+ m_actionSelectAll->setShortcut(QKeySequence::SelectAll);
+ m_actionSelectAll->setStatusTip(tr("Selects all widgets"));
+ m_actionSelectAll->setWhatsThis(whatsThisFrom(QLatin1String("Edit|Select All")));
+ connect(m_actionSelectAll, SIGNAL(triggered()), this, SLOT(slotActionSelectAllActivated()));
+ m_actionSelectAll->setEnabled(false);
+
+ m_actionRaise = new QAction(createIconSet(QLatin1String("editraise.png")), tr("Bring to &Front"), this);
+ m_actionRaise->setObjectName(QLatin1String("__qt_raise_action"));
+ m_actionRaise->setShortcut(Qt::CTRL + Qt::Key_L);
+ m_actionRaise->setStatusTip(tr("Raises the selected widgets"));
+ m_actionRaise->setWhatsThis(tr("Raises the selected widgets"));
+ connect(m_actionRaise, SIGNAL(triggered()), this, SLOT(slotActionRaiseActivated()));
+ m_actionRaise->setEnabled(false);
+
+ m_actionLower = new QAction(createIconSet(QLatin1String("editlower.png")), tr("Send to &Back"), this);
+ m_actionLower->setObjectName(QLatin1String("__qt_lower_action"));
+ m_actionLower->setShortcut(Qt::CTRL + Qt::Key_K);
+ m_actionLower->setStatusTip(tr("Lowers the selected widgets"));
+ m_actionLower->setWhatsThis(tr("Lowers the selected widgets"));
+ connect(m_actionLower, SIGNAL(triggered()), this, SLOT(slotActionLowerActivated()));
+ m_actionLower->setEnabled(false);
+
+ m_actionAdjustSize = new QAction(createIconSet(QLatin1String("adjustsize.png")), tr("Adjust &Size"), this);
+ m_actionAdjustSize->setObjectName(QLatin1String("__qt_adjust_size_action"));
+ m_actionAdjustSize->setShortcut(Qt::CTRL + Qt::Key_J);
+ m_actionAdjustSize->setStatusTip(tr("Adjusts the size of the selected widget"));
+ m_actionAdjustSize->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Adjust Size")));
+ connect(m_actionAdjustSize, SIGNAL(triggered()), this, SLOT(slotActionAdjustSizeActivated()));
+ m_actionAdjustSize->setEnabled(false);
+
+
+ m_actionHorizontalLayout = new QAction(createIconSet(QLatin1String("edithlayout.png")), tr("Lay Out &Horizontally"), this);
+ m_actionHorizontalLayout->setObjectName(QLatin1String("__qt_horizontal_layout_action"));
+ m_actionHorizontalLayout->setShortcut(Qt::CTRL + Qt::Key_1);
+ m_actionHorizontalLayout->setStatusTip(tr("Lays out the selected widgets horizontally"));
+ m_actionHorizontalLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Horizontally")));
+ m_actionHorizontalLayout->setData(LayoutInfo::HBox);
+ m_actionHorizontalLayout->setEnabled(false);
+ connect(m_actionHorizontalLayout, SIGNAL(triggered()), this, SLOT(createLayout()));
+
+ m_actionVerticalLayout = new QAction(createIconSet(QLatin1String("editvlayout.png")), tr("Lay Out &Vertically"), this);
+ m_actionVerticalLayout->setObjectName(QLatin1String("__qt_vertical_layout_action"));
+ m_actionVerticalLayout->setShortcut(Qt::CTRL + Qt::Key_2);
+ m_actionVerticalLayout->setStatusTip(tr("Lays out the selected widgets vertically"));
+ m_actionVerticalLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Vertically")));
+ m_actionVerticalLayout->setData(LayoutInfo::VBox);
+ m_actionVerticalLayout->setEnabled(false);
+ connect(m_actionVerticalLayout, SIGNAL(triggered()), this, SLOT(createLayout()));
+
+ QAction *actionFormLayout = new QAction(createIconSet(QLatin1String("editform.png")), tr("Lay Out in a &Form Layout"), this);
+ actionFormLayout->setObjectName(QLatin1String("__qt_form_layout_action"));
+ actionFormLayout->setShortcut(Qt::CTRL + Qt::Key_6);
+ actionFormLayout->setStatusTip(tr("Lays out the selected widgets in a form layout"));
+ actionFormLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out in a Form")));
+ actionFormLayout->setData(LayoutInfo::Form);
+ actionFormLayout->setEnabled(false);
+ setActionFormLayout(actionFormLayout);
+ connect(actionFormLayout, SIGNAL(triggered()), this, SLOT(createLayout()));
+
+ m_actionGridLayout = new QAction(createIconSet(QLatin1String("editgrid.png")), tr("Lay Out in a &Grid"), this);
+ m_actionGridLayout->setObjectName(QLatin1String("__qt_grid_layout_action"));
+ m_actionGridLayout->setShortcut(Qt::CTRL + Qt::Key_5);
+ m_actionGridLayout->setStatusTip(tr("Lays out the selected widgets in a grid"));
+ m_actionGridLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out in a Grid")));
+ m_actionGridLayout->setData(LayoutInfo::Grid);
+ m_actionGridLayout->setEnabled(false);
+ connect(m_actionGridLayout, SIGNAL(triggered()), this, SLOT(createLayout()));
+
+ m_actionSplitHorizontal = new QAction(createIconSet(QLatin1String("edithlayoutsplit.png")),
+ tr("Lay Out Horizontally in S&plitter"), this);
+ m_actionSplitHorizontal->setObjectName(QLatin1String("__qt_split_horizontal_action"));
+ m_actionSplitHorizontal->setShortcut(Qt::CTRL + Qt::Key_3);
+ m_actionSplitHorizontal->setStatusTip(tr("Lays out the selected widgets horizontally in a splitter"));
+ m_actionSplitHorizontal->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Horizontally in Splitter")));
+ m_actionSplitHorizontal->setData(LayoutInfo::HSplitter);
+ m_actionSplitHorizontal->setEnabled(false);
+ connect(m_actionSplitHorizontal, SIGNAL(triggered()), this, SLOT(createLayout()));
+
+ m_actionSplitVertical = new QAction(createIconSet(QLatin1String("editvlayoutsplit.png")),
+ tr("Lay Out Vertically in Sp&litter"), this);
+ m_actionSplitVertical->setObjectName(QLatin1String("__qt_split_vertical_action"));
+ m_actionSplitVertical->setShortcut(Qt::CTRL + Qt::Key_4);
+ m_actionSplitVertical->setStatusTip(tr("Lays out the selected widgets vertically in a splitter"));
+ m_actionSplitVertical->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Lay Out Vertically in Splitter")));
+ connect(m_actionSplitVertical, SIGNAL(triggered()), this, SLOT(createLayout()));
+ m_actionSplitVertical->setData(LayoutInfo::VSplitter);
+
+ m_actionSplitVertical->setEnabled(false);
+
+ m_actionBreakLayout = new QAction(createIconSet(QLatin1String("editbreaklayout.png")), tr("&Break Layout"), this);
+ m_actionBreakLayout->setObjectName(QLatin1String("__qt_break_layout_action"));
+ m_actionBreakLayout->setShortcut(Qt::CTRL + Qt::Key_0);
+ m_actionBreakLayout->setStatusTip(tr("Breaks the selected layout"));
+ m_actionBreakLayout->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Break Layout")));
+ connect(m_actionBreakLayout, SIGNAL(triggered()), this, SLOT(slotActionBreakLayoutActivated()));
+ m_actionBreakLayout->setEnabled(false);
+
+ QAction *simplifyLayoutAction = new QAction(tr("Si&mplify Grid Layout"), this);
+ simplifyLayoutAction->setObjectName(QLatin1String("__qt_simplify_layout_action"));
+ simplifyLayoutAction->setStatusTip(tr("Removes empty columns and rows"));
+ simplifyLayoutAction->setWhatsThis(whatsThisFrom(QLatin1String("Layout|Simplify Layout")));
+ connect(simplifyLayoutAction, SIGNAL(triggered()), this, SLOT(slotActionSimplifyLayoutActivated()));
+ simplifyLayoutAction->setEnabled(false);
+ setActionSimplifyLayout(simplifyLayoutAction);
+
+ m_actionDefaultPreview = new QAction(tr("&Preview..."), this);
+ m_actionDefaultPreview->setObjectName(QLatin1String("__qt_default_preview_action"));
+ m_actionDefaultPreview->setStatusTip(tr("Preview current form"));
+ m_actionDefaultPreview->setWhatsThis(whatsThisFrom(QLatin1String("Form|Preview")));
+ connect(m_actionDefaultPreview, SIGNAL(triggered()),
+ this, SLOT(slotActionDefaultPreviewActivated()));
+
+ m_undoGroup = new QUndoGroup(this);
+
+ m_actionUndo = m_undoGroup->createUndoAction(this);
+ m_actionUndo->setEnabled(false);
+ m_actionUndo->setIcon(createIconSet(QLatin1String("undo.png")));
+ m_actionRedo = m_undoGroup->createRedoAction(this);
+ m_actionRedo->setEnabled(false);
+ m_actionRedo->setIcon(createIconSet(QLatin1String("redo.png")));
+
+ m_actionShowFormWindowSettingsDialog = new QAction(tr("Form &Settings..."), this);
+ m_actionShowFormWindowSettingsDialog->setObjectName(QLatin1String("__qt_form_settings_action"));
+ connect(m_actionShowFormWindowSettingsDialog, SIGNAL(triggered()), this, SLOT(slotActionShowFormWindowSettingsDialog()));
+ m_actionShowFormWindowSettingsDialog->setEnabled(false);
+}
+
+void FormWindowManager::slotActionCutActivated()
+{
+ m_activeFormWindow->cut();
+}
+
+void FormWindowManager::slotActionCopyActivated()
+{
+ m_activeFormWindow->copy();
+ slotUpdateActions();
+}
+
+void FormWindowManager::slotActionPasteActivated()
+{
+ m_activeFormWindow->paste();
+}
+
+void FormWindowManager::slotActionDeleteActivated()
+{
+ m_activeFormWindow->deleteWidgets();
+}
+
+void FormWindowManager::slotActionLowerActivated()
+{
+ m_activeFormWindow->lowerWidgets();
+}
+
+void FormWindowManager::slotActionRaiseActivated()
+{
+ m_activeFormWindow->raiseWidgets();
+}
+
+static inline QWidget *findLayoutContainer(const FormWindow *fw)
+{
+ QList<QWidget*> l(fw->selectedWidgets());
+ fw->simplifySelection(&l);
+ return l.empty() ? fw->mainContainer() : l.front();
+}
+
+void FormWindowManager::createLayout()
+{
+ QAction *a = qobject_cast<QAction *>(sender());
+ if (!a)
+ return;
+ const int type = a->data().toInt();
+ switch (m_createLayoutContext) {
+ case LayoutContainer:
+ // Cannot create a splitter on a container
+ if (type != LayoutInfo::HSplitter && type != LayoutInfo::VSplitter)
+ m_activeFormWindow->createLayout(type, findLayoutContainer(m_activeFormWindow));
+ break;
+ case LayoutSelection:
+ m_activeFormWindow->createLayout(type);
+ break;
+ case MorphLayout:
+ m_activeFormWindow->morphLayout(m_morphLayoutContainer, type);
+ break;
+ }
+}
+
+void FormWindowManager::slotActionBreakLayoutActivated()
+{
+ const QList<QWidget *> layouts = layoutsToBeBroken();
+ if (layouts.isEmpty())
+ return;
+
+ if (debugFWM) {
+ qDebug() << "slotActionBreakLayoutActivated: " << layouts.size();
+ foreach (QWidget *w, layouts) {
+ qDebug() << w;
+ }
+ }
+
+ m_activeFormWindow->beginCommand(tr("Break Layout"));
+ foreach (QWidget *layout, layouts) {
+ m_activeFormWindow->breakLayout(layout);
+ }
+ m_activeFormWindow->endCommand();
+}
+
+void FormWindowManager::slotActionSimplifyLayoutActivated()
+{
+ Q_ASSERT(m_activeFormWindow != 0);
+ QWidgetList selectedWidgets = m_activeFormWindow->selectedWidgets();
+ m_activeFormWindow->simplifySelection(&selectedWidgets);
+ if (selectedWidgets.size() != 1)
+ return;
+ SimplifyLayoutCommand *cmd = new SimplifyLayoutCommand(m_activeFormWindow);
+ if (cmd->init(selectedWidgets.front())) {
+ m_activeFormWindow->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ }
+}
+
+void FormWindowManager::slotActionAdjustSizeActivated()
+{
+ Q_ASSERT(m_activeFormWindow != 0);
+
+ m_activeFormWindow->beginCommand(tr("Adjust Size"));
+
+ QList<QWidget*> selectedWidgets = m_activeFormWindow->selectedWidgets();
+ m_activeFormWindow->simplifySelection(&selectedWidgets);
+
+ if (selectedWidgets.isEmpty()) {
+ Q_ASSERT(m_activeFormWindow->mainContainer() != 0);
+ selectedWidgets.append(m_activeFormWindow->mainContainer());
+ }
+
+ // Always count the main container as unlaid-out
+ foreach (QWidget *widget, selectedWidgets) {
+ bool unlaidout = LayoutInfo::layoutType(core(), widget->parentWidget()) == LayoutInfo::NoLayout;
+ bool isMainContainer = m_activeFormWindow->isMainContainer(widget);
+
+ if (unlaidout || isMainContainer) {
+ AdjustWidgetSizeCommand *cmd = new AdjustWidgetSizeCommand(m_activeFormWindow);
+ cmd->init(widget);
+ m_activeFormWindow->commandHistory()->push(cmd);
+ }
+ }
+
+ m_activeFormWindow->endCommand();
+}
+
+void FormWindowManager::slotActionSelectAllActivated()
+{
+ m_activeFormWindow->selectAll();
+}
+
+void FormWindowManager::slotActionDefaultPreviewActivated()
+{
+ slotActionGroupPreviewInStyle(QString(), -1);
+}
+
+void FormWindowManager::slotActionGroupPreviewInStyle(const QString &style, int deviceProfileIndex)
+{
+ QDesignerFormWindowInterface *fw = activeFormWindow();
+ if (!fw)
+ return;
+
+ QString errorMessage;
+ if (!m_previewManager->showPreview(fw, style, deviceProfileIndex, &errorMessage)) {
+ const QString title = tr("Could not create form preview", "Title of warning message box");
+ core()->dialogGui()->message(fw, QDesignerDialogGuiInterface::FormEditorMessage, QMessageBox::Warning,
+ title, errorMessage);
+ }
+}
+
+// The user might click on a layout child or the actual layout container.
+QWidgetList FormWindowManager::layoutsToBeBroken(QWidget *w) const
+{
+ if (!w)
+ return QList<QWidget *>();
+
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: " << w;
+
+ QWidget *parent = w->parentWidget();
+ if (m_activeFormWindow->isMainContainer(w))
+ parent = 0;
+
+ QWidget *widget = core()->widgetFactory()->containerOfWidget(w);
+
+ // maybe we want to remove following block
+ const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase();
+ const QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(widget));
+ if (!item) {
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: Don't have an item, recursing for parent";
+ return layoutsToBeBroken(parent);
+ }
+
+ const bool layoutContainer = (item->isContainer() || m_activeFormWindow->isMainContainer(widget));
+
+ if (!layoutContainer) {
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: Not a container, recursing for parent";
+ return layoutsToBeBroken(parent);
+ }
+
+ QLayout *widgetLayout = widget->layout();
+ QLayout *managedLayout = LayoutInfo::managedLayout(m_core, widgetLayout);
+ if (!managedLayout) {
+ if (qobject_cast<const QSplitter *>(widget)) {
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: Splitter special";
+ QList<QWidget *> list = layoutsToBeBroken(parent);
+ list.append(widget);
+ return list;
+ }
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: Is a container but doesn't have a managed layout (has an internal layout), returning 0";
+ return QList<QWidget *>();
+ }
+
+ if (managedLayout) {
+ QList<QWidget *> list;
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: Is a container and has a layout";
+ if (qobject_cast<const QLayoutWidget *>(widget)) {
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: red layout special case";
+ list = layoutsToBeBroken(parent);
+ }
+ list.append(widget);
+ return list;
+ }
+ if (debugFWM)
+ qDebug() << "layoutsToBeBroken: Is a container but doesn't have a layout at all, returning 0";
+ return QList<QWidget *>();
+
+}
+
+QMap<QWidget *, bool> FormWindowManager::getUnsortedLayoutsToBeBroken(bool firstOnly) const
+{
+ // Return a set of layouts to be broken.
+ QMap<QWidget *, bool> layouts;
+
+ QList<QWidget *> selection = m_activeFormWindow->selectedWidgets();
+ if (selection.isEmpty() && m_activeFormWindow->mainContainer())
+ selection.append(m_activeFormWindow->mainContainer());
+
+ const QList<QWidget *>::const_iterator scend = selection.constEnd();
+ for (QList<QWidget *>::const_iterator sit = selection.constBegin(); sit != scend; ++sit) {
+ // find all layouts
+ const QList<QWidget *> list = layoutsToBeBroken(*sit);
+ if (!list.empty()) {
+ const QList<QWidget *>::const_iterator lbcend = list.constEnd();
+ for (QList<QWidget *>::const_iterator lbit = list.constBegin(); lbit != lbcend; ++lbit) {
+ layouts.insert(*lbit, true);
+ }
+ if (firstOnly)
+ return layouts;
+ }
+ }
+ return layouts;
+}
+
+bool FormWindowManager::hasLayoutsToBeBroken() const
+{
+ // Quick check for layouts to be broken
+ return !getUnsortedLayoutsToBeBroken(true).isEmpty();
+}
+
+QWidgetList FormWindowManager::layoutsToBeBroken() const
+{
+ // Get all layouts. This is a list of all 'red' layouts (QLayoutWidgets)
+ // up to the first 'real' widget with a layout in hierarchy order.
+ QMap<QWidget *, bool> unsortedLayouts = getUnsortedLayoutsToBeBroken(false);
+ // Sort in order of hierarchy
+ QList<QWidget *> orderedLayoutList;
+ const QMap<QWidget *, bool>::const_iterator lscend = unsortedLayouts.constEnd();
+ for (QMap<QWidget *, bool>::const_iterator itLay = unsortedLayouts.constBegin(); itLay != lscend; ++itLay) {
+ QWidget *wToBeInserted = itLay.key();
+ if (!orderedLayoutList.contains(wToBeInserted)) {
+ // try to find first child, use as insertion position, else append
+ const QList<QWidget *>::iterator firstChildPos = findFirstChildOf(orderedLayoutList.begin(), orderedLayoutList.end(), wToBeInserted);
+ if (firstChildPos == orderedLayoutList.end()) {
+ orderedLayoutList.push_back(wToBeInserted);
+ } else {
+ orderedLayoutList.insert(firstChildPos, wToBeInserted);
+ }
+ }
+ }
+ return orderedLayoutList;
+}
+
+static inline bool hasManagedLayoutItems(const QDesignerFormEditorInterface *core, QWidget *w)
+{
+ if (const QLayout *ml = LayoutInfo::managedLayout(core, w)) {
+ // Try to find managed items, ignore dummy grid spacers
+ const int count = ml->count();
+ for (int i = 0; i < count; i++)
+ if (!LayoutInfo::isEmptyItem(ml->itemAt(i)))
+ return true;
+ }
+ return false;
+}
+
+void FormWindowManager::slotUpdateActions()
+{
+ m_createLayoutContext = LayoutSelection;
+ m_morphLayoutContainer = 0;
+ bool canMorphIntoVBoxLayout = false;
+ bool canMorphIntoHBoxLayout = false;
+ bool canMorphIntoGridLayout = false;
+ bool canMorphIntoFormLayout = false;
+ int selectedWidgetCount = 0;
+ int laidoutWidgetCount = 0;
+ int unlaidoutWidgetCount = 0;
+ bool pasteAvailable = false;
+ bool layoutAvailable = false;
+ bool breakAvailable = false;
+ bool simplifyAvailable = false;
+ bool layoutContainer = false;
+ bool canChangeZOrder = true;
+
+ do {
+ if (m_activeFormWindow == 0 || m_activeFormWindow->currentTool() != 0)
+ break;
+
+ breakAvailable = hasLayoutsToBeBroken();
+
+ QWidgetList simplifiedSelection = m_activeFormWindow->selectedWidgets();
+
+ selectedWidgetCount = simplifiedSelection.count();
+ pasteAvailable = qApp->clipboard()->mimeData() && qApp->clipboard()->mimeData()->hasText();
+
+ m_activeFormWindow->simplifySelection(&simplifiedSelection);
+ QWidget *mainContainer = m_activeFormWindow->mainContainer();
+ if (simplifiedSelection.isEmpty() && mainContainer)
+ simplifiedSelection.append(mainContainer);
+
+ // Always count the main container as unlaid-out
+ const QWidgetList::const_iterator cend = simplifiedSelection.constEnd();
+ for (QWidgetList::const_iterator it = simplifiedSelection.constBegin(); it != cend; ++it) {
+ if (*it != mainContainer && LayoutInfo::isWidgetLaidout(m_core, *it)) {
+ ++laidoutWidgetCount;
+ } else {
+ ++unlaidoutWidgetCount;
+ }
+ if (qobject_cast<const QLayoutWidget *>(*it) || qobject_cast<const Spacer *>(*it))
+ canChangeZOrder = false;
+ }
+
+ // Figure out layouts: Looking at a group of dangling widgets
+ if (simplifiedSelection.count() != 1) {
+ layoutAvailable = unlaidoutWidgetCount > 1;
+ //breakAvailable = false;
+ break;
+ }
+ // Manipulate layout of a single widget
+ m_createLayoutContext = LayoutSelection;
+ QWidget *widget = core()->widgetFactory()->containerOfWidget(simplifiedSelection.first());
+ if (widget == 0) // We are looking at a page-based container with 0 pages
+ break;
+
+ const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase();
+ const QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(widget));
+ if (!item)
+ break;
+
+ QLayout *widgetLayout = LayoutInfo::internalLayout(widget);
+ QLayout *managedLayout = LayoutInfo::managedLayout(m_core, widgetLayout);
+ // We don't touch a layout createds by a custom widget
+ if (widgetLayout && !managedLayout)
+ break;
+
+ layoutContainer = (item->isContainer() || m_activeFormWindow->isMainContainer(widget));
+
+ layoutAvailable = layoutContainer && m_activeFormWindow->hasInsertedChildren(widget) && managedLayout == 0;
+ simplifyAvailable = SimplifyLayoutCommand::canSimplify(m_core, widget);
+ if (layoutAvailable) {
+ m_createLayoutContext = LayoutContainer;
+ } else {
+ /* Cannot create a layout, have some layouts to be broken and
+ * exactly one, non-empty layout with selected: check the morph layout options
+ * (Note that there might be > 1 layouts to broken if the selection
+ * is a red layout, however, we want the inner-most layout here). */
+ if (breakAvailable && simplifiedSelection.size() == 1
+ && hasManagedLayoutItems(m_core, widget)) {
+ int type;
+ m_morphLayoutContainer = widget; // Was: page of first selected
+ m_createLayoutContext = MorphLayout;
+ if (MorphLayoutCommand::canMorph(m_activeFormWindow, m_morphLayoutContainer, &type)) {
+ canMorphIntoVBoxLayout = type != LayoutInfo::VBox;
+ canMorphIntoHBoxLayout = type != LayoutInfo::HBox;
+ canMorphIntoGridLayout = type != LayoutInfo::Grid;
+ canMorphIntoFormLayout = type != LayoutInfo::Form;
+ }
+ }
+ }
+ } while(false);
+
+ m_actionCut->setEnabled(selectedWidgetCount > 0);
+ m_actionCopy->setEnabled(selectedWidgetCount > 0);
+ m_actionDelete->setEnabled(selectedWidgetCount > 0);
+ m_actionLower->setEnabled(canChangeZOrder && selectedWidgetCount > 0);
+ m_actionRaise->setEnabled(canChangeZOrder && selectedWidgetCount > 0);
+
+ m_actionPaste->setEnabled(pasteAvailable);
+
+ m_actionSelectAll->setEnabled(m_activeFormWindow != 0);
+
+ m_actionAdjustSize->setEnabled(unlaidoutWidgetCount > 0);
+
+ m_actionHorizontalLayout->setEnabled(layoutAvailable || canMorphIntoHBoxLayout);
+ m_actionVerticalLayout->setEnabled(layoutAvailable || canMorphIntoVBoxLayout);
+ m_actionSplitHorizontal->setEnabled(layoutAvailable && !layoutContainer);
+ m_actionSplitVertical->setEnabled(layoutAvailable && !layoutContainer);
+ actionFormLayout()->setEnabled(layoutAvailable || canMorphIntoFormLayout);
+ m_actionGridLayout->setEnabled(layoutAvailable || canMorphIntoGridLayout);
+
+ m_actionBreakLayout->setEnabled(breakAvailable);
+ actionSimplifyLayout()->setEnabled(simplifyAvailable);
+ m_actionShowFormWindowSettingsDialog->setEnabled(m_activeFormWindow != 0);
+}
+
+QDesignerFormWindowInterface *FormWindowManager::createFormWindow(QWidget *parentWidget, Qt::WindowFlags flags)
+{
+ FormWindow *formWindow = new FormWindow(qobject_cast<FormEditor*>(core()), parentWidget, flags);
+ formWindow->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true));
+ addFormWindow(formWindow);
+ return formWindow;
+}
+
+QPixmap FormWindowManager::createPreviewPixmap(QString *errorMessage)
+{
+ QPixmap pixmap;
+ QDesignerFormWindowInterface *fw = activeFormWindow();
+ if (!fw)
+ return pixmap;
+
+ pixmap = m_previewManager->createPreviewPixmap(fw, QString(), errorMessage);
+ return pixmap;
+}
+
+QAction *FormWindowManager::actionUndo() const
+{
+ return m_actionUndo;
+}
+
+QAction *FormWindowManager::actionRedo() const
+{
+ return m_actionRedo;
+}
+
+QActionGroup *FormWindowManager::actionGroupPreviewInStyle() const
+{
+ if (m_actionGroupPreviewInStyle == 0) {
+ // Wish we could make the 'this' pointer mutable ;-)
+ QObject *parent = const_cast<FormWindowManager*>(this);
+ m_actionGroupPreviewInStyle = new PreviewActionGroup(m_core, parent);
+ connect(m_actionGroupPreviewInStyle, SIGNAL(preview(QString,int)),
+ this, SLOT(slotActionGroupPreviewInStyle(QString,int)));
+ }
+ return m_actionGroupPreviewInStyle;
+}
+
+void FormWindowManager::deviceProfilesChanged()
+{
+ if (m_actionGroupPreviewInStyle)
+ m_actionGroupPreviewInStyle->updateDeviceProfiles();
+}
+
+// DnD stuff
+
+void FormWindowManager::dragItems(const QList<QDesignerDnDItemInterface*> &item_list)
+{
+ QDesignerMimeData::execDrag(item_list, m_core->topLevel());
+}
+
+QUndoGroup *FormWindowManager::undoGroup() const
+{
+ return m_undoGroup;
+}
+
+QAction *FormWindowManager::actionShowFormWindowSettingsDialog() const
+{
+ return m_actionShowFormWindowSettingsDialog;
+}
+
+void FormWindowManager::slotActionShowFormWindowSettingsDialog()
+{
+ QDesignerFormWindowInterface *fw = activeFormWindow();
+ if (!fw)
+ return;
+
+ QDialog *settingsDialog = 0;
+ const bool wasDirty = fw->isDirty();
+
+ // Ask the language extension for a dialog. If not, create our own
+ if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension*>(m_core->extensionManager(), m_core))
+ settingsDialog = lang->createFormWindowSettingsDialog(fw, /*parent=*/ 0);
+
+ if (!settingsDialog)
+ settingsDialog = new FormWindowSettings(fw);
+
+ QString title = QFileInfo(fw->fileName()).fileName();
+ if (title.isEmpty()) // Grab the title from the outer window if no filename
+ if (const QWidget *window = m_core->integration()->containerWindow(fw))
+ title = window->windowTitle();
+
+ settingsDialog->setWindowTitle(tr("Form Settings - %1").arg(title));
+ if (settingsDialog->exec())
+ if (fw->isDirty() != wasDirty)
+ emit formWindowSettingsChanged(fw);
+
+ delete settingsDialog;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formwindowmanager.h b/tools/designer/src/components/formeditor/formwindowmanager.h
new file mode 100644
index 0000000000..d81ec2d4f5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindowmanager.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOWMANAGER_H
+#define FORMWINDOWMANAGER_H
+
+#include "formeditor_global.h"
+
+#include <QtDesigner/private/qdesigner_formwindowmanager_p.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+#include <QtCore/QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QActionGroup;
+class QUndoGroup;
+class QDesignerFormEditorInterface;
+class QDesignerWidgetBoxInterface;
+
+namespace qdesigner_internal {
+
+class FormWindow;
+class PreviewManager;
+class PreviewActionGroup;
+
+class QT_FORMEDITOR_EXPORT FormWindowManager
+ : public QDesignerFormWindowManager
+{
+ Q_OBJECT
+public:
+ explicit FormWindowManager(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ virtual ~FormWindowManager();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ inline QAction *actionCut() const { return m_actionCut; }
+ inline QAction *actionCopy() const { return m_actionCopy; }
+ inline QAction *actionPaste() const { return m_actionPaste; }
+ inline QAction *actionDelete() const { return m_actionDelete; }
+ inline QAction *actionSelectAll() const { return m_actionSelectAll; }
+ inline QAction *actionLower() const { return m_actionLower; }
+ inline QAction *actionRaise() const { return m_actionRaise; }
+ QAction *actionUndo() const;
+ QAction *actionRedo() const;
+
+ inline QAction *actionHorizontalLayout() const { return m_actionHorizontalLayout; }
+ inline QAction *actionVerticalLayout() const { return m_actionVerticalLayout; }
+ inline QAction *actionSplitHorizontal() const { return m_actionSplitHorizontal; }
+ inline QAction *actionSplitVertical() const { return m_actionSplitVertical; }
+ inline QAction *actionGridLayout() const { return m_actionGridLayout; }
+ inline QAction *actionBreakLayout() const { return m_actionBreakLayout; }
+ inline QAction *actionAdjustSize() const { return m_actionAdjustSize; }
+
+ inline QAction *actionDefaultPreview() const { return m_actionDefaultPreview; }
+ QActionGroup *actionGroupPreviewInStyle() const;
+ virtual QAction *actionShowFormWindowSettingsDialog() const;
+
+ QDesignerFormWindowInterface *activeFormWindow() const;
+
+ int formWindowCount() const;
+ QDesignerFormWindowInterface *formWindow(int index) const;
+
+ QDesignerFormWindowInterface *createFormWindow(QWidget *parentWidget = 0, Qt::WindowFlags flags = 0);
+
+ QPixmap createPreviewPixmap(QString *errorMessage);
+
+ bool eventFilter(QObject *o, QEvent *e);
+
+ void dragItems(const QList<QDesignerDnDItemInterface*> &item_list);
+
+ QUndoGroup *undoGroup() const;
+
+ virtual PreviewManager *previewManager() const { return m_previewManager; }
+
+public slots:
+ void addFormWindow(QDesignerFormWindowInterface *formWindow);
+ void removeFormWindow(QDesignerFormWindowInterface *formWindow);
+ void setActiveFormWindow(QDesignerFormWindowInterface *formWindow);
+ void closeAllPreviews();
+ void deviceProfilesChanged();
+
+private slots:
+ void slotActionCutActivated();
+ void slotActionCopyActivated();
+ void slotActionPasteActivated();
+ void slotActionDeleteActivated();
+ void slotActionSelectAllActivated();
+ void slotActionLowerActivated();
+ void slotActionRaiseActivated();
+ void createLayout();
+ void slotActionBreakLayoutActivated();
+ void slotActionAdjustSizeActivated();
+ void slotActionSimplifyLayoutActivated();
+ void slotActionDefaultPreviewActivated();
+ void slotActionGroupPreviewInStyle(const QString &style, int deviceProfileIndex);
+ void slotActionShowFormWindowSettingsDialog();
+
+ void slotUpdateActions();
+
+private:
+ void setupActions();
+ FormWindow *findFormWindow(QWidget *w);
+ QWidget *findManagedWidget(FormWindow *fw, QWidget *w);
+
+ void setCurrentUndoStack(QUndoStack *stack);
+
+private:
+ enum CreateLayoutContext { LayoutContainer, LayoutSelection, MorphLayout };
+
+ QDesignerFormEditorInterface *m_core;
+ FormWindow *m_activeFormWindow;
+ QList<FormWindow*> m_formWindows;
+
+ PreviewManager *m_previewManager;
+
+ /* Context of the layout actions and base for morphing layouts. Determined
+ * in slotUpdateActions() and used later on in the action slots. */
+ CreateLayoutContext m_createLayoutContext;
+ QWidget *m_morphLayoutContainer;
+
+ // edit actions
+ QAction *m_actionCut;
+ QAction *m_actionCopy;
+ QAction *m_actionPaste;
+ QAction *m_actionSelectAll;
+ QAction *m_actionDelete;
+ QAction *m_actionLower;
+ QAction *m_actionRaise;
+ // layout actions
+ QAction *m_actionHorizontalLayout;
+ QAction *m_actionVerticalLayout;
+ QAction *m_actionSplitHorizontal;
+ QAction *m_actionSplitVertical;
+ QAction *m_actionGridLayout;
+ QAction *m_actionBreakLayout;
+ QAction *m_actionAdjustSize;
+ // preview actions
+ QAction *m_actionDefaultPreview;
+ mutable PreviewActionGroup *m_actionGroupPreviewInStyle;
+ QAction *m_actionShowFormWindowSettingsDialog;
+
+ QAction *m_actionUndo;
+ QAction *m_actionRedo;
+
+ QMap<QWidget *,bool> getUnsortedLayoutsToBeBroken(bool firstOnly) const;
+ bool hasLayoutsToBeBroken() const;
+ QWidgetList layoutsToBeBroken(QWidget *w) const;
+ QWidgetList layoutsToBeBroken() const;
+
+ QUndoGroup *m_undoGroup;
+
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOWMANAGER_H
diff --git a/tools/designer/src/components/formeditor/formwindowsettings.cpp b/tools/designer/src/components/formeditor/formwindowsettings.cpp
new file mode 100644
index 0000000000..1f6d5ddb63
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindowsettings.cpp
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formwindowsettings.h"
+#include "ui_formwindowsettings.h"
+
+#include <formwindowbase_p.h>
+#include <grid_p.h>
+
+#include <QtGui/QStyle>
+
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// Data structure containing form dialog data providing comparison
+struct FormWindowData {
+ FormWindowData();
+
+ bool equals(const FormWindowData&) const;
+
+ void fromFormWindow(FormWindowBase* fw);
+ void applyToFormWindow(FormWindowBase* fw) const;
+
+ bool layoutDefaultEnabled;
+ int defaultMargin;
+ int defaultSpacing;
+
+ bool layoutFunctionsEnabled;
+ QString marginFunction;
+ QString spacingFunction;
+
+ QString pixFunction;
+
+ QString author;
+
+ QStringList includeHints;
+
+ bool hasFormGrid;
+ Grid grid;
+};
+
+inline bool operator==(const FormWindowData &fd1, const FormWindowData &fd2) { return fd1.equals(fd2); }
+inline bool operator!=(const FormWindowData &fd1, const FormWindowData &fd2) { return !fd1.equals(fd2); }
+
+QDebug operator<<(QDebug str, const FormWindowData &d)
+{
+ str.nospace() << "LayoutDefault=" << d.layoutDefaultEnabled << ',' << d.defaultMargin
+ << ',' << d.defaultSpacing << " LayoutFunctions=" << d.layoutFunctionsEnabled << ','
+ << d.marginFunction << ',' << d.spacingFunction << " PixFunction="
+ << d.pixFunction << " Author=" << d.author << " Hints=" << d.includeHints
+ << " Grid=" << d.hasFormGrid << d.grid.deltaX() << d.grid.deltaY() << '\n';
+ return str;
+}
+
+FormWindowData::FormWindowData() :
+ layoutDefaultEnabled(false),
+ defaultMargin(0),
+ defaultSpacing(0),
+ layoutFunctionsEnabled(false),
+ hasFormGrid(false)
+{
+}
+
+bool FormWindowData::equals(const FormWindowData &rhs) const
+{
+ return layoutDefaultEnabled == rhs.layoutDefaultEnabled &&
+ defaultMargin == rhs.defaultMargin &&
+ defaultSpacing == rhs.defaultSpacing &&
+ layoutFunctionsEnabled == rhs.layoutFunctionsEnabled &&
+ marginFunction == rhs.marginFunction &&
+ spacingFunction == rhs.spacingFunction &&
+ pixFunction == rhs.pixFunction &&
+ author == rhs.author &&
+ includeHints == rhs.includeHints &&
+ hasFormGrid == rhs.hasFormGrid &&
+ grid == rhs.grid;
+}
+
+void FormWindowData::fromFormWindow(FormWindowBase* fw)
+{
+ defaultMargin = defaultSpacing = INT_MIN;
+ fw->layoutDefault(&defaultMargin, &defaultSpacing);
+
+ QStyle *style = fw->formContainer()->style();
+ layoutDefaultEnabled = defaultMargin != INT_MIN || defaultMargin != INT_MIN;
+ if (defaultMargin == INT_MIN)
+ defaultMargin = style->pixelMetric(QStyle::PM_DefaultChildMargin, 0);
+ if (defaultSpacing == INT_MIN)
+ defaultSpacing = style->pixelMetric(QStyle::PM_DefaultLayoutSpacing, 0);
+
+
+ marginFunction.clear();
+ spacingFunction.clear();
+ fw->layoutFunction(&marginFunction, &spacingFunction);
+ layoutFunctionsEnabled = !marginFunction.isEmpty() || !spacingFunction.isEmpty();
+
+ pixFunction = fw->pixmapFunction();
+
+ author = fw->author();
+
+ includeHints = fw->includeHints();
+ includeHints.removeAll(QString());
+
+ hasFormGrid = fw->hasFormGrid();
+ grid = hasFormGrid ? fw->designerGrid() : FormWindowBase::defaultDesignerGrid();
+}
+
+void FormWindowData::applyToFormWindow(FormWindowBase* fw) const
+{
+ fw->setAuthor(author);
+ fw->setPixmapFunction(pixFunction);
+
+ if (layoutDefaultEnabled) {
+ fw->setLayoutDefault(defaultMargin, defaultSpacing);
+ } else {
+ fw->setLayoutDefault(INT_MIN, INT_MIN);
+ }
+
+ if (layoutFunctionsEnabled) {
+ fw->setLayoutFunction(marginFunction, spacingFunction);
+ } else {
+ fw->setLayoutFunction(QString(), QString());
+ }
+
+ fw->setIncludeHints(includeHints);
+
+ const bool hadFormGrid = fw->hasFormGrid();
+ fw->setHasFormGrid(hasFormGrid);
+ if (hasFormGrid || hadFormGrid != hasFormGrid)
+ fw->setDesignerGrid(hasFormGrid ? grid : FormWindowBase::defaultDesignerGrid());
+}
+
+// -------------------------- FormWindowSettings
+
+FormWindowSettings::FormWindowSettings(QDesignerFormWindowInterface *parent) :
+ QDialog(parent),
+ m_ui(new ::Ui::FormWindowSettings),
+ m_formWindow(qobject_cast<FormWindowBase*>(parent)),
+ m_oldData(new FormWindowData)
+{
+ Q_ASSERT(m_formWindow);
+
+ m_ui->setupUi(this);
+ m_ui->gridPanel->setCheckable(true);
+ m_ui->gridPanel->setResetButtonVisible(false);
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QString deviceProfileName = m_formWindow->deviceProfileName();
+ if (deviceProfileName.isEmpty())
+ deviceProfileName = tr("None");
+ m_ui->deviceProfileLabel->setText(tr("Device Profile: %1").arg(deviceProfileName));
+
+ m_oldData->fromFormWindow(m_formWindow);
+ setData(*m_oldData);
+}
+
+FormWindowSettings::~FormWindowSettings()
+{
+ delete m_oldData;
+ delete m_ui;
+}
+
+FormWindowData FormWindowSettings::data() const
+{
+ FormWindowData rc;
+ rc.author = m_ui->authorLineEdit->text();
+
+ if (m_ui->pixmapFunctionGroupBox->isChecked()) {
+ rc.pixFunction = m_ui->pixmapFunctionLineEdit->text();
+ } else {
+ rc.pixFunction.clear();
+ }
+
+ rc.layoutDefaultEnabled = m_ui->layoutDefaultGroupBox->isChecked();
+ rc.defaultMargin = m_ui->defaultMarginSpinBox->value();
+ rc.defaultSpacing = m_ui->defaultSpacingSpinBox->value();
+
+ rc.layoutFunctionsEnabled = m_ui->layoutFunctionGroupBox->isChecked();
+ rc.marginFunction = m_ui->marginFunctionLineEdit->text();
+ rc.spacingFunction = m_ui->spacingFunctionLineEdit->text();
+
+ const QString hints = m_ui->includeHintsTextEdit->toPlainText();
+ if (!hints.isEmpty()) {
+ rc.includeHints = hints.split(QString(QLatin1Char('\n')));
+ // Purge out any lines consisting of blanks only
+ const QRegExp blankLine = QRegExp(QLatin1String("^\\s*$"));
+ Q_ASSERT(blankLine.isValid());
+ for (QStringList::iterator it = rc.includeHints.begin(); it != rc.includeHints.end(); )
+ if (blankLine.exactMatch(*it)) {
+ it = rc.includeHints.erase(it);
+ } else {
+ ++it;
+ }
+ rc.includeHints.removeAll(QString());
+ }
+
+ rc.hasFormGrid = m_ui->gridPanel->isChecked();
+ rc.grid = m_ui->gridPanel->grid();
+ return rc;
+}
+
+void FormWindowSettings::setData(const FormWindowData &data)
+{
+ m_ui->layoutDefaultGroupBox->setChecked(data.layoutDefaultEnabled);
+ m_ui->defaultMarginSpinBox->setValue(data.defaultMargin);
+ m_ui->defaultSpacingSpinBox->setValue(data.defaultSpacing);
+
+ m_ui->layoutFunctionGroupBox->setChecked(data.layoutFunctionsEnabled);
+ m_ui->marginFunctionLineEdit->setText(data.marginFunction);
+ m_ui->spacingFunctionLineEdit->setText(data.spacingFunction);
+
+ m_ui->pixmapFunctionLineEdit->setText(data.pixFunction);
+ m_ui->pixmapFunctionGroupBox->setChecked(!data.pixFunction.isEmpty());
+
+ m_ui->authorLineEdit->setText(data.author);
+
+ if (data.includeHints.empty()) {
+ m_ui->includeHintsTextEdit->clear();
+ } else {
+ m_ui->includeHintsTextEdit->setText(data.includeHints.join(QLatin1String("\n")));
+ }
+
+ m_ui->gridPanel->setChecked(data.hasFormGrid);
+ m_ui->gridPanel->setGrid(data.grid);
+}
+
+void FormWindowSettings::accept()
+{
+ // Anything changed? -> Apply and set dirty
+ const FormWindowData newData = data();
+ if (newData != *m_oldData) {
+ newData.applyToFormWindow(m_formWindow);
+ m_formWindow->setDirty(true);
+ }
+
+ QDialog::accept();
+}
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/formwindowsettings.h b/tools/designer/src/components/formeditor/formwindowsettings.h
new file mode 100644
index 0000000000..4289f4290c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindowsettings.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMWINDOWSETTINGS_H
+#define FORMWINDOWSETTINGS_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+ class FormWindowSettings;
+}
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+struct FormWindowData;
+class FormWindowBase;
+
+/* Dialog to edit the settings of a QDesignerFormWindowInterface.
+ * It sets the dirty flag on the form window if something was changed. */
+
+class FormWindowSettings: public QDialog
+{
+ Q_DISABLE_COPY(FormWindowSettings)
+ Q_OBJECT
+public:
+ explicit FormWindowSettings(QDesignerFormWindowInterface *formWindow);
+ virtual ~FormWindowSettings();
+
+ virtual void accept();
+
+private:
+ FormWindowData data() const;
+ void setData(const FormWindowData&);
+
+ Ui::FormWindowSettings *m_ui;
+ FormWindowBase *m_formWindow;
+ FormWindowData *m_oldData;
+};
+}
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOWSETTINGS_H
diff --git a/tools/designer/src/components/formeditor/formwindowsettings.ui b/tools/designer/src/components/formeditor/formwindowsettings.ui
new file mode 100644
index 0000000000..4e56365b1c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/formwindowsettings.ui
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>FormWindowSettings</class>
+ <widget class="QDialog" name="FormWindowSettings">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>470</width>
+ <height>466</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form Settings</string>
+ </property>
+ <layout class="QGridLayout">
+ <item row="3" column="0" colspan="2">
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="layoutDefaultGroupBox">
+ <property name="title">
+ <string>Layout &amp;Default</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>&amp;Spacing:</string>
+ </property>
+ <property name="buddy">
+ <cstring>defaultSpacingSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>&amp;Margin:</string>
+ </property>
+ <property name="buddy">
+ <cstring>defaultMarginSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="defaultSpacingSpinBox"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="defaultMarginSpinBox"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="layoutFunctionGroupBox">
+ <property name="title">
+ <string>&amp;Layout Function</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="spacingFunctionLineEdit"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="marginFunctionLineEdit"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Ma&amp;rgin:</string>
+ </property>
+ <property name="buddy">
+ <cstring>marginFunctionLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3_2">
+ <property name="text">
+ <string>Spa&amp;cing:</string>
+ </property>
+ <property name="buddy">
+ <cstring>spacingFunctionLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="4" column="1">
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="pixmapFunctionGroupBox">
+ <property name="title">
+ <string>&amp;Pixmap Function</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="pixmapFunctionLineEdit"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="5" column="1">
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>111</width>
+ <height>115</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="7" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0" colspan="2">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" rowspan="2">
+ <widget class="QGroupBox" name="includeHintsGroupBox">
+ <property name="title">
+ <string>&amp;Include Hints</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="includeHintsTextEdit"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="qdesigner_internal::GridPanel" name="gridPanel">
+ <property name="title">
+ <string>Grid</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QGroupBox" name="embeddedGroupBox">
+ <property name="title">
+ <string>Embedded Design</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="deviceProfileLabel">
+ <property name="text">
+ <string notr="true">TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QGroupBox" name="pixmapFunctionGroupBox_2">
+ <property name="title">
+ <string>&amp;Author</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="authorLineEdit"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>qdesigner_internal::GridPanel</class>
+ <extends>QGroupBox</extends>
+ <header location="global">gridpanel_p.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>authorLineEdit</tabstop>
+ <tabstop>defaultMarginSpinBox</tabstop>
+ <tabstop>defaultSpacingSpinBox</tabstop>
+ <tabstop>marginFunctionLineEdit</tabstop>
+ <tabstop>spacingFunctionLineEdit</tabstop>
+ <tabstop>pixmapFunctionLineEdit</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>FormWindowSettings</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>294</x>
+ <y>442</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>150</x>
+ <y>459</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>FormWindowSettings</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>373</x>
+ <y>444</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>357</x>
+ <y>461</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/components/formeditor/iconcache.cpp b/tools/designer/src/components/formeditor/iconcache.cpp
new file mode 100644
index 0000000000..a256bf846a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/iconcache.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "iconcache.h"
+#include <QtGui/QPixmap>
+#include <QtGui/QIcon>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+IconCache::IconCache(QObject *parent)
+ : QDesignerIconCacheInterface(parent)
+{
+}
+
+QIcon IconCache::nameToIcon(const QString &path, const QString &resourcePath)
+{
+ Q_UNUSED(path)
+ Q_UNUSED(resourcePath)
+ qWarning() << "IconCache::nameToIcon(): IconCache is obsoleted";
+ return QIcon();
+}
+
+QString IconCache::iconToFilePath(const QIcon &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "IconCache::iconToFilePath(): IconCache is obsoleted";
+ return QString();
+}
+
+QString IconCache::iconToQrcPath(const QIcon &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "IconCache::iconToQrcPath(): IconCache is obsoleted";
+ return QString();
+}
+
+QPixmap IconCache::nameToPixmap(const QString &path, const QString &resourcePath)
+{
+ Q_UNUSED(path)
+ Q_UNUSED(resourcePath)
+ qWarning() << "IconCache::nameToPixmap(): IconCache is obsoleted";
+ return QPixmap();
+}
+
+QString IconCache::pixmapToFilePath(const QPixmap &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "IconCache::pixmapToFilePath(): IconCache is obsoleted";
+ return QString();
+}
+
+QString IconCache::pixmapToQrcPath(const QPixmap &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "IconCache::pixmapToQrcPath(): IconCache is obsoleted";
+ return QString();
+}
+
+QList<QPixmap> IconCache::pixmapList() const
+{
+ qWarning() << "IconCache::pixmapList(): IconCache is obsoleted";
+ return QList<QPixmap>();
+}
+
+QList<QIcon> IconCache::iconList() const
+{
+ qWarning() << "IconCache::iconList(): IconCache is obsoleted";
+ return QList<QIcon>();
+}
+
+QString IconCache::resolveQrcPath(const QString &filePath, const QString &qrcPath, const QString &wd) const
+{
+ Q_UNUSED(filePath)
+ Q_UNUSED(qrcPath)
+ Q_UNUSED(wd)
+ qWarning() << "IconCache::resolveQrcPath(): IconCache is obsoleted";
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/iconcache.h b/tools/designer/src/components/formeditor/iconcache.h
new file mode 100644
index 0000000000..24d36e2499
--- /dev/null
+++ b/tools/designer/src/components/formeditor/iconcache.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ICONCACHE_H
+#define ICONCACHE_H
+
+#include "formeditor_global.h"
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QT_FORMEDITOR_EXPORT IconCache : public QDesignerIconCacheInterface
+{
+ Q_OBJECT
+public:
+ explicit IconCache(QObject *parent);
+
+ virtual QIcon nameToIcon(const QString &path, const QString &resourcePath = QString());
+ virtual QString iconToFilePath(const QIcon &pm) const;
+ virtual QString iconToQrcPath(const QIcon &pm) const;
+ virtual QPixmap nameToPixmap(const QString &path, const QString &resourcePath = QString());
+ virtual QString pixmapToFilePath(const QPixmap &pm) const;
+ virtual QString pixmapToQrcPath(const QPixmap &pm) const;
+
+ virtual QList<QPixmap> pixmapList() const;
+ virtual QList<QIcon> iconList() const;
+
+ virtual QString resolveQrcPath(const QString &filePath, const QString &qrcPath, const QString &workingDirectory = QString()) const;
+
+private:
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ICONCACHE_H
diff --git a/tools/designer/src/components/formeditor/images/color.png b/tools/designer/src/components/formeditor/images/color.png
new file mode 100644
index 0000000000..54b7ebcdee
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/color.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/configure.png b/tools/designer/src/components/formeditor/images/configure.png
new file mode 100644
index 0000000000..d9f2fd8c07
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/configure.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/arrow.png b/tools/designer/src/components/formeditor/images/cursors/arrow.png
new file mode 100644
index 0000000000..a69ef4eb61
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/arrow.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/busy.png b/tools/designer/src/components/formeditor/images/cursors/busy.png
new file mode 100644
index 0000000000..53717e4992
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/busy.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/closedhand.png b/tools/designer/src/components/formeditor/images/cursors/closedhand.png
new file mode 100644
index 0000000000..b78dd1dac5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/closedhand.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/cross.png b/tools/designer/src/components/formeditor/images/cursors/cross.png
new file mode 100644
index 0000000000..fe38e74480
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/cross.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/hand.png b/tools/designer/src/components/formeditor/images/cursors/hand.png
new file mode 100644
index 0000000000..d2004aefa7
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/hand.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/hsplit.png b/tools/designer/src/components/formeditor/images/cursors/hsplit.png
new file mode 100644
index 0000000000..a5667e3ffb
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/hsplit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/ibeam.png b/tools/designer/src/components/formeditor/images/cursors/ibeam.png
new file mode 100644
index 0000000000..097fc5fa72
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/ibeam.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/no.png b/tools/designer/src/components/formeditor/images/cursors/no.png
new file mode 100644
index 0000000000..2b08c4e2a3
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/no.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/openhand.png b/tools/designer/src/components/formeditor/images/cursors/openhand.png
new file mode 100644
index 0000000000..9181c859ed
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/openhand.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/sizeall.png b/tools/designer/src/components/formeditor/images/cursors/sizeall.png
new file mode 100644
index 0000000000..69f13eb347
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/sizeall.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/sizeb.png b/tools/designer/src/components/formeditor/images/cursors/sizeb.png
new file mode 100644
index 0000000000..3b127a05d3
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/sizeb.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/sizef.png b/tools/designer/src/components/formeditor/images/cursors/sizef.png
new file mode 100644
index 0000000000..f37d7b91e8
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/sizef.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/sizeh.png b/tools/designer/src/components/formeditor/images/cursors/sizeh.png
new file mode 100644
index 0000000000..a9f40cbc3d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/sizeh.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/sizev.png b/tools/designer/src/components/formeditor/images/cursors/sizev.png
new file mode 100644
index 0000000000..1edbab27a5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/sizev.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/uparrow.png b/tools/designer/src/components/formeditor/images/cursors/uparrow.png
new file mode 100644
index 0000000000..d3e70ef4c2
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/uparrow.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/vsplit.png b/tools/designer/src/components/formeditor/images/cursors/vsplit.png
new file mode 100644
index 0000000000..1beda2570e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/vsplit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/wait.png b/tools/designer/src/components/formeditor/images/cursors/wait.png
new file mode 100644
index 0000000000..69056c479e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/wait.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/cursors/whatsthis.png b/tools/designer/src/components/formeditor/images/cursors/whatsthis.png
new file mode 100644
index 0000000000..b47601c378
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/cursors/whatsthis.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/downplus.png b/tools/designer/src/components/formeditor/images/downplus.png
new file mode 100644
index 0000000000..1e384a72d6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/downplus.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/dropdownbutton.png b/tools/designer/src/components/formeditor/images/dropdownbutton.png
new file mode 100644
index 0000000000..5dd964946c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/dropdownbutton.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/edit.png b/tools/designer/src/components/formeditor/images/edit.png
new file mode 100644
index 0000000000..a5e49adf99
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/edit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/editdelete-16.png b/tools/designer/src/components/formeditor/images/editdelete-16.png
new file mode 100644
index 0000000000..ef5c799c15
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/editdelete-16.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/emptyicon.png b/tools/designer/src/components/formeditor/images/emptyicon.png
new file mode 100644
index 0000000000..897220e213
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/emptyicon.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/filenew-16.png b/tools/designer/src/components/formeditor/images/filenew-16.png
new file mode 100644
index 0000000000..eefb3c5207
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/filenew-16.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/fileopen-16.png b/tools/designer/src/components/formeditor/images/fileopen-16.png
new file mode 100644
index 0000000000..d832c621cc
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/fileopen-16.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/leveldown.png b/tools/designer/src/components/formeditor/images/leveldown.png
new file mode 100644
index 0000000000..742b7fb84b
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/leveldown.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/levelup.png b/tools/designer/src/components/formeditor/images/levelup.png
new file mode 100644
index 0000000000..48b3e89223
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/levelup.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/adjustsize.png b/tools/designer/src/components/formeditor/images/mac/adjustsize.png
new file mode 100644
index 0000000000..c4d884c8b2
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/adjustsize.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/back.png b/tools/designer/src/components/formeditor/images/mac/back.png
new file mode 100644
index 0000000000..e58177f43c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/back.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/buddytool.png b/tools/designer/src/components/formeditor/images/mac/buddytool.png
new file mode 100644
index 0000000000..2a4287089b
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/buddytool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/down.png b/tools/designer/src/components/formeditor/images/mac/down.png
new file mode 100644
index 0000000000..29d1d4439a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/down.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editbreaklayout.png b/tools/designer/src/components/formeditor/images/mac/editbreaklayout.png
new file mode 100644
index 0000000000..dc005590bf
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editbreaklayout.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editcopy.png b/tools/designer/src/components/formeditor/images/mac/editcopy.png
new file mode 100644
index 0000000000..f551364464
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editcopy.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editcut.png b/tools/designer/src/components/formeditor/images/mac/editcut.png
new file mode 100644
index 0000000000..a784fd5709
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editcut.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editdelete.png b/tools/designer/src/components/formeditor/images/mac/editdelete.png
new file mode 100644
index 0000000000..201b31cdb1
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editdelete.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editform.png b/tools/designer/src/components/formeditor/images/mac/editform.png
new file mode 100644
index 0000000000..4fc2e40dc5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editform.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editgrid.png b/tools/designer/src/components/formeditor/images/mac/editgrid.png
new file mode 100644
index 0000000000..bba4a695bc
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editgrid.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/edithlayout.png b/tools/designer/src/components/formeditor/images/mac/edithlayout.png
new file mode 100644
index 0000000000..ec880bb5cb
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/edithlayout.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/edithlayoutsplit.png b/tools/designer/src/components/formeditor/images/mac/edithlayoutsplit.png
new file mode 100644
index 0000000000..227d0115fe
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/edithlayoutsplit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editlower.png b/tools/designer/src/components/formeditor/images/mac/editlower.png
new file mode 100644
index 0000000000..347806fc0f
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editlower.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editpaste.png b/tools/designer/src/components/formeditor/images/mac/editpaste.png
new file mode 100644
index 0000000000..64c0b2d6ab
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editpaste.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editraise.png b/tools/designer/src/components/formeditor/images/mac/editraise.png
new file mode 100644
index 0000000000..09cbbd7d5a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editraise.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editvlayout.png b/tools/designer/src/components/formeditor/images/mac/editvlayout.png
new file mode 100644
index 0000000000..63b26cdb2d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editvlayout.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/editvlayoutsplit.png b/tools/designer/src/components/formeditor/images/mac/editvlayoutsplit.png
new file mode 100644
index 0000000000..5a02c944e0
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/editvlayoutsplit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/filenew.png b/tools/designer/src/components/formeditor/images/mac/filenew.png
new file mode 100644
index 0000000000..9dcba42844
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/filenew.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/fileopen.png b/tools/designer/src/components/formeditor/images/mac/fileopen.png
new file mode 100644
index 0000000000..c12bcd5079
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/fileopen.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/filesave.png b/tools/designer/src/components/formeditor/images/mac/filesave.png
new file mode 100644
index 0000000000..b41ecf5319
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/filesave.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/forward.png b/tools/designer/src/components/formeditor/images/mac/forward.png
new file mode 100644
index 0000000000..34b91f09fa
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/forward.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/insertimage.png b/tools/designer/src/components/formeditor/images/mac/insertimage.png
new file mode 100644
index 0000000000..b8673e13bc
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/insertimage.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/minus.png b/tools/designer/src/components/formeditor/images/mac/minus.png
new file mode 100644
index 0000000000..8d2eaed523
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/minus.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/plus.png b/tools/designer/src/components/formeditor/images/mac/plus.png
new file mode 100644
index 0000000000..1ee45423e3
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/plus.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/redo.png b/tools/designer/src/components/formeditor/images/mac/redo.png
new file mode 100644
index 0000000000..8875bf246c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/redo.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/resetproperty.png b/tools/designer/src/components/formeditor/images/mac/resetproperty.png
new file mode 100644
index 0000000000..9048252ec2
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/resetproperty.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/resourceeditortool.png b/tools/designer/src/components/formeditor/images/mac/resourceeditortool.png
new file mode 100644
index 0000000000..7ef511c2b1
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/resourceeditortool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/signalslottool.png b/tools/designer/src/components/formeditor/images/mac/signalslottool.png
new file mode 100644
index 0000000000..71c9b07a8d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/signalslottool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/tabordertool.png b/tools/designer/src/components/formeditor/images/mac/tabordertool.png
new file mode 100644
index 0000000000..f54faf9abe
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/tabordertool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textanchor.png b/tools/designer/src/components/formeditor/images/mac/textanchor.png
new file mode 100644
index 0000000000..baa9dda52d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textanchor.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textbold.png b/tools/designer/src/components/formeditor/images/mac/textbold.png
new file mode 100644
index 0000000000..38400bd1f6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textbold.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textcenter.png b/tools/designer/src/components/formeditor/images/mac/textcenter.png
new file mode 100644
index 0000000000..2ef5b2ee6f
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textcenter.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textitalic.png b/tools/designer/src/components/formeditor/images/mac/textitalic.png
new file mode 100644
index 0000000000..0170ee26a6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textitalic.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textjustify.png b/tools/designer/src/components/formeditor/images/mac/textjustify.png
new file mode 100644
index 0000000000..39cd6c1a9d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textjustify.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textleft.png b/tools/designer/src/components/formeditor/images/mac/textleft.png
new file mode 100644
index 0000000000..83a66d5535
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textleft.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textright.png b/tools/designer/src/components/formeditor/images/mac/textright.png
new file mode 100644
index 0000000000..e7c04645cf
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textright.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textsubscript.png b/tools/designer/src/components/formeditor/images/mac/textsubscript.png
new file mode 100644
index 0000000000..ff431f396d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textsubscript.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textsuperscript.png b/tools/designer/src/components/formeditor/images/mac/textsuperscript.png
new file mode 100644
index 0000000000..cb67a33d01
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textsuperscript.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/textunder.png b/tools/designer/src/components/formeditor/images/mac/textunder.png
new file mode 100644
index 0000000000..968bac5e90
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/textunder.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/undo.png b/tools/designer/src/components/formeditor/images/mac/undo.png
new file mode 100644
index 0000000000..a3bd5e0bf2
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/undo.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/up.png b/tools/designer/src/components/formeditor/images/mac/up.png
new file mode 100644
index 0000000000..e437312217
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/up.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/mac/widgettool.png b/tools/designer/src/components/formeditor/images/mac/widgettool.png
new file mode 100644
index 0000000000..e1aa353dbf
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/mac/widgettool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/minus-16.png b/tools/designer/src/components/formeditor/images/minus-16.png
new file mode 100644
index 0000000000..745b445722
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/minus-16.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/plus-16.png b/tools/designer/src/components/formeditor/images/plus-16.png
new file mode 100644
index 0000000000..ef43788e67
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/plus-16.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/prefix-add.png b/tools/designer/src/components/formeditor/images/prefix-add.png
new file mode 100644
index 0000000000..cfbb053f42
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/prefix-add.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/qt3logo.png b/tools/designer/src/components/formeditor/images/qt3logo.png
new file mode 100644
index 0000000000..720285001f
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/qt3logo.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/qtlogo.png b/tools/designer/src/components/formeditor/images/qtlogo.png
new file mode 100644
index 0000000000..038fa2cc3b
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/qtlogo.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/reload.png b/tools/designer/src/components/formeditor/images/reload.png
new file mode 100644
index 0000000000..18c752e146
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/reload.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/resetproperty.png b/tools/designer/src/components/formeditor/images/resetproperty.png
new file mode 100644
index 0000000000..9048252ec2
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/resetproperty.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/sort.png b/tools/designer/src/components/formeditor/images/sort.png
new file mode 100644
index 0000000000..883bfa9de5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/sort.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/submenu.png b/tools/designer/src/components/formeditor/images/submenu.png
new file mode 100644
index 0000000000..3deb28e3a8
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/submenu.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/calendarwidget.png b/tools/designer/src/components/formeditor/images/widgets/calendarwidget.png
new file mode 100644
index 0000000000..26737b8838
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/calendarwidget.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/checkbox.png b/tools/designer/src/components/formeditor/images/widgets/checkbox.png
new file mode 100644
index 0000000000..ab6f53e02c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/checkbox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/columnview.png b/tools/designer/src/components/formeditor/images/widgets/columnview.png
new file mode 100644
index 0000000000..4132ee6b1d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/columnview.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/combobox.png b/tools/designer/src/components/formeditor/images/widgets/combobox.png
new file mode 100644
index 0000000000..bf3ed79f7e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/combobox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/commandlinkbutton.png b/tools/designer/src/components/formeditor/images/widgets/commandlinkbutton.png
new file mode 100644
index 0000000000..6bbd84a972
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/commandlinkbutton.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/dateedit.png b/tools/designer/src/components/formeditor/images/widgets/dateedit.png
new file mode 100644
index 0000000000..6827fa742e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/dateedit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/datetimeedit.png b/tools/designer/src/components/formeditor/images/widgets/datetimeedit.png
new file mode 100644
index 0000000000..7d8e6fe6d5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/datetimeedit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/dial.png b/tools/designer/src/components/formeditor/images/widgets/dial.png
new file mode 100644
index 0000000000..050d1dbd01
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/dial.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png b/tools/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png
new file mode 100644
index 0000000000..b1f89fbb36
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/dialogbuttonbox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/dockwidget.png b/tools/designer/src/components/formeditor/images/widgets/dockwidget.png
new file mode 100644
index 0000000000..9eee04f701
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/dockwidget.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/doublespinbox.png b/tools/designer/src/components/formeditor/images/widgets/doublespinbox.png
new file mode 100644
index 0000000000..5686ac89b3
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/doublespinbox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/fontcombobox.png b/tools/designer/src/components/formeditor/images/widgets/fontcombobox.png
new file mode 100644
index 0000000000..6848f15c2e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/fontcombobox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/frame.png b/tools/designer/src/components/formeditor/images/widgets/frame.png
new file mode 100644
index 0000000000..68f5da0a36
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/frame.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/graphicsview.png b/tools/designer/src/components/formeditor/images/widgets/graphicsview.png
new file mode 100644
index 0000000000..93fe7603ae
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/graphicsview.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/groupbox.png b/tools/designer/src/components/formeditor/images/widgets/groupbox.png
new file mode 100644
index 0000000000..4025b4dc51
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/groupbox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png b/tools/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png
new file mode 100644
index 0000000000..62fd1ad56c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/groupboxcollapsible.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/hscrollbar.png b/tools/designer/src/components/formeditor/images/widgets/hscrollbar.png
new file mode 100644
index 0000000000..466c58de5b
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/hscrollbar.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/hslider.png b/tools/designer/src/components/formeditor/images/widgets/hslider.png
new file mode 100644
index 0000000000..525bd1cabd
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/hslider.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/hsplit.png b/tools/designer/src/components/formeditor/images/widgets/hsplit.png
new file mode 100644
index 0000000000..1ea8f2ac0e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/hsplit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/label.png b/tools/designer/src/components/formeditor/images/widgets/label.png
new file mode 100644
index 0000000000..5d7d7b4cc9
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/label.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/lcdnumber.png b/tools/designer/src/components/formeditor/images/widgets/lcdnumber.png
new file mode 100644
index 0000000000..c3cac18265
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/lcdnumber.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/line.png b/tools/designer/src/components/formeditor/images/widgets/line.png
new file mode 100644
index 0000000000..5c64dfb591
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/line.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/lineedit.png b/tools/designer/src/components/formeditor/images/widgets/lineedit.png
new file mode 100644
index 0000000000..75fc890f40
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/lineedit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/listbox.png b/tools/designer/src/components/formeditor/images/widgets/listbox.png
new file mode 100644
index 0000000000..367e67ff57
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/listbox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/listview.png b/tools/designer/src/components/formeditor/images/widgets/listview.png
new file mode 100644
index 0000000000..d1308d5758
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/listview.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/mdiarea.png b/tools/designer/src/components/formeditor/images/widgets/mdiarea.png
new file mode 100644
index 0000000000..7783dd527a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/mdiarea.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/plaintextedit.png b/tools/designer/src/components/formeditor/images/widgets/plaintextedit.png
new file mode 100644
index 0000000000..077bf16cb9
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/plaintextedit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/progress.png b/tools/designer/src/components/formeditor/images/widgets/progress.png
new file mode 100644
index 0000000000..44ae094e7c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/progress.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/pushbutton.png b/tools/designer/src/components/formeditor/images/widgets/pushbutton.png
new file mode 100644
index 0000000000..61f779ce2b
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/pushbutton.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/radiobutton.png b/tools/designer/src/components/formeditor/images/widgets/radiobutton.png
new file mode 100644
index 0000000000..10c1d8c3ef
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/radiobutton.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/scrollarea.png b/tools/designer/src/components/formeditor/images/widgets/scrollarea.png
new file mode 100644
index 0000000000..651ea24c0e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/scrollarea.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/spacer.png b/tools/designer/src/components/formeditor/images/widgets/spacer.png
new file mode 100644
index 0000000000..8a0931bf8d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/spacer.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/spinbox.png b/tools/designer/src/components/formeditor/images/widgets/spinbox.png
new file mode 100644
index 0000000000..cdd9fe1413
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/spinbox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/tabbar.png b/tools/designer/src/components/formeditor/images/widgets/tabbar.png
new file mode 100644
index 0000000000..d5d37836b5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/tabbar.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/table.png b/tools/designer/src/components/formeditor/images/widgets/table.png
new file mode 100644
index 0000000000..4bbd9c2d08
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/table.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/tabwidget.png b/tools/designer/src/components/formeditor/images/widgets/tabwidget.png
new file mode 100644
index 0000000000..1254bb63a6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/tabwidget.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/textedit.png b/tools/designer/src/components/formeditor/images/widgets/textedit.png
new file mode 100644
index 0000000000..32e897d972
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/textedit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/timeedit.png b/tools/designer/src/components/formeditor/images/widgets/timeedit.png
new file mode 100644
index 0000000000..c66d91b2f7
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/timeedit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/toolbox.png b/tools/designer/src/components/formeditor/images/widgets/toolbox.png
new file mode 100644
index 0000000000..2ab71dc743
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/toolbox.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/toolbutton.png b/tools/designer/src/components/formeditor/images/widgets/toolbutton.png
new file mode 100644
index 0000000000..0bff069a5d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/toolbutton.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/vline.png b/tools/designer/src/components/formeditor/images/widgets/vline.png
new file mode 100644
index 0000000000..35a7300a58
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/vline.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/vscrollbar.png b/tools/designer/src/components/formeditor/images/widgets/vscrollbar.png
new file mode 100644
index 0000000000..28b7c40c6e
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/vscrollbar.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/vslider.png b/tools/designer/src/components/formeditor/images/widgets/vslider.png
new file mode 100644
index 0000000000..59f06bae4a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/vslider.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/vspacer.png b/tools/designer/src/components/formeditor/images/widgets/vspacer.png
new file mode 100644
index 0000000000..ce5e8bd7dc
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/vspacer.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/widget.png b/tools/designer/src/components/formeditor/images/widgets/widget.png
new file mode 100644
index 0000000000..1cf960e61b
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/widget.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/widgetstack.png b/tools/designer/src/components/formeditor/images/widgets/widgetstack.png
new file mode 100644
index 0000000000..2c6964e3ed
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/widgetstack.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/widgets/wizard.png b/tools/designer/src/components/formeditor/images/widgets/wizard.png
new file mode 100644
index 0000000000..7c0e107aea
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/widgets/wizard.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/adjustsize.png b/tools/designer/src/components/formeditor/images/win/adjustsize.png
new file mode 100644
index 0000000000..3cda333713
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/adjustsize.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/back.png b/tools/designer/src/components/formeditor/images/win/back.png
new file mode 100644
index 0000000000..e58177f43c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/back.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/buddytool.png b/tools/designer/src/components/formeditor/images/win/buddytool.png
new file mode 100644
index 0000000000..4cd968bbf5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/buddytool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/down.png b/tools/designer/src/components/formeditor/images/win/down.png
new file mode 100644
index 0000000000..29d1d4439a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/down.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editbreaklayout.png b/tools/designer/src/components/formeditor/images/win/editbreaklayout.png
new file mode 100644
index 0000000000..07c5fae696
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editbreaklayout.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editcopy.png b/tools/designer/src/components/formeditor/images/win/editcopy.png
new file mode 100644
index 0000000000..1121b47d8b
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editcopy.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editcut.png b/tools/designer/src/components/formeditor/images/win/editcut.png
new file mode 100644
index 0000000000..4b6c82c7a7
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editcut.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editdelete.png b/tools/designer/src/components/formeditor/images/win/editdelete.png
new file mode 100644
index 0000000000..5a4251402d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editdelete.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editform.png b/tools/designer/src/components/formeditor/images/win/editform.png
new file mode 100644
index 0000000000..452fcd8878
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editform.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editgrid.png b/tools/designer/src/components/formeditor/images/win/editgrid.png
new file mode 100644
index 0000000000..789bf7d960
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editgrid.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/edithlayout.png b/tools/designer/src/components/formeditor/images/win/edithlayout.png
new file mode 100644
index 0000000000..4dd3f0ce46
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/edithlayout.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/edithlayoutsplit.png b/tools/designer/src/components/formeditor/images/win/edithlayoutsplit.png
new file mode 100644
index 0000000000..2dcc690291
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/edithlayoutsplit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editlower.png b/tools/designer/src/components/formeditor/images/win/editlower.png
new file mode 100644
index 0000000000..ba630944ca
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editlower.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editpaste.png b/tools/designer/src/components/formeditor/images/win/editpaste.png
new file mode 100644
index 0000000000..ffab15aaf8
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editpaste.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editraise.png b/tools/designer/src/components/formeditor/images/win/editraise.png
new file mode 100644
index 0000000000..bb8362c1f1
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editraise.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editvlayout.png b/tools/designer/src/components/formeditor/images/win/editvlayout.png
new file mode 100644
index 0000000000..7ad28fdeab
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editvlayout.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/editvlayoutsplit.png b/tools/designer/src/components/formeditor/images/win/editvlayoutsplit.png
new file mode 100644
index 0000000000..720e18bb32
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/editvlayoutsplit.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/filenew.png b/tools/designer/src/components/formeditor/images/win/filenew.png
new file mode 100644
index 0000000000..af5d122141
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/filenew.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/fileopen.png b/tools/designer/src/components/formeditor/images/win/fileopen.png
new file mode 100644
index 0000000000..fc6f17e977
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/fileopen.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/filesave.png b/tools/designer/src/components/formeditor/images/win/filesave.png
new file mode 100644
index 0000000000..8feec99bee
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/filesave.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/forward.png b/tools/designer/src/components/formeditor/images/win/forward.png
new file mode 100644
index 0000000000..34b91f09fa
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/forward.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/insertimage.png b/tools/designer/src/components/formeditor/images/win/insertimage.png
new file mode 100644
index 0000000000..cfab6375f7
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/insertimage.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/minus.png b/tools/designer/src/components/formeditor/images/win/minus.png
new file mode 100644
index 0000000000..c0dc274bb4
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/minus.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/plus.png b/tools/designer/src/components/formeditor/images/win/plus.png
new file mode 100644
index 0000000000..ecf0589415
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/plus.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/redo.png b/tools/designer/src/components/formeditor/images/win/redo.png
new file mode 100644
index 0000000000..686ad141c6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/redo.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/resourceeditortool.png b/tools/designer/src/components/formeditor/images/win/resourceeditortool.png
new file mode 100644
index 0000000000..cc9cb5851c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/resourceeditortool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/signalslottool.png b/tools/designer/src/components/formeditor/images/win/signalslottool.png
new file mode 100644
index 0000000000..e80fd1caa6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/signalslottool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/tabordertool.png b/tools/designer/src/components/formeditor/images/win/tabordertool.png
new file mode 100644
index 0000000000..7e6e2de716
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/tabordertool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textanchor.png b/tools/designer/src/components/formeditor/images/win/textanchor.png
new file mode 100644
index 0000000000..1911ab0d5a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textanchor.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textbold.png b/tools/designer/src/components/formeditor/images/win/textbold.png
new file mode 100644
index 0000000000..9cbc7138b9
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textbold.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textcenter.png b/tools/designer/src/components/formeditor/images/win/textcenter.png
new file mode 100644
index 0000000000..11efb4b852
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textcenter.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textitalic.png b/tools/designer/src/components/formeditor/images/win/textitalic.png
new file mode 100644
index 0000000000..b30ce14c14
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textitalic.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textjustify.png b/tools/designer/src/components/formeditor/images/win/textjustify.png
new file mode 100644
index 0000000000..9de0c88085
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textjustify.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textleft.png b/tools/designer/src/components/formeditor/images/win/textleft.png
new file mode 100644
index 0000000000..16f80bc325
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textleft.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textright.png b/tools/designer/src/components/formeditor/images/win/textright.png
new file mode 100644
index 0000000000..16872df62a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textright.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textsubscript.png b/tools/designer/src/components/formeditor/images/win/textsubscript.png
new file mode 100644
index 0000000000..d86347d839
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textsubscript.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textsuperscript.png b/tools/designer/src/components/formeditor/images/win/textsuperscript.png
new file mode 100644
index 0000000000..910996560c
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textsuperscript.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/textunder.png b/tools/designer/src/components/formeditor/images/win/textunder.png
new file mode 100644
index 0000000000..c72eff53fb
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/textunder.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/undo.png b/tools/designer/src/components/formeditor/images/win/undo.png
new file mode 100644
index 0000000000..c3b8c51368
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/undo.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/up.png b/tools/designer/src/components/formeditor/images/win/up.png
new file mode 100644
index 0000000000..e437312217
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/up.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/images/win/widgettool.png b/tools/designer/src/components/formeditor/images/win/widgettool.png
new file mode 100644
index 0000000000..a52224e068
--- /dev/null
+++ b/tools/designer/src/components/formeditor/images/win/widgettool.png
Binary files differ
diff --git a/tools/designer/src/components/formeditor/itemview_propertysheet.cpp b/tools/designer/src/components/formeditor/itemview_propertysheet.cpp
new file mode 100644
index 0000000000..609ce84a2a
--- /dev/null
+++ b/tools/designer/src/components/formeditor/itemview_propertysheet.cpp
@@ -0,0 +1,291 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "itemview_propertysheet.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QHeaderView>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+struct Property {
+ Property() : m_sheet(0),m_id(-1) {}
+ Property(QDesignerPropertySheetExtension *sheet, int id)
+ : m_sheet(sheet), m_id(id) {}
+ bool operator==(const Property &p) { return m_sheet == p.m_sheet && m_id == p.m_id; }
+ uint qHash() {
+ return ((int)(m_sheet-(QDesignerPropertySheetExtension*)(0))) & m_id;
+ }
+
+ QDesignerPropertySheetExtension *m_sheet;
+ int m_id;
+};
+
+class ItemViewPropertySheetPrivate {
+
+public:
+ ItemViewPropertySheetPrivate(QHeaderView *horizontalHeader,
+ QHeaderView *verticalHeader,
+ QObject *parent);
+
+ inline void createMapping(int fakeId, QHeaderView *header, const QString &headerName);
+ inline QStringList realPropertyNames();
+ inline QString fakePropertyName(const QString &prefix, const QString &realName);
+
+ QDesignerFormEditorInterface *m_core;
+
+ // Maps index of fake property
+ // to index of real property in respective sheet
+ QHash<int, Property> m_propertyIdMap;
+
+ // Maps name of fake property
+ // to name of real property
+ QHash<QString, QString> m_propertyNameMap;
+
+private:
+ static QDesignerFormEditorInterface *formEditorForObject(QObject *o);
+
+ QHeaderView *m_hHeader;
+ QHeaderView *m_vHeader;
+ QHash<QHeaderView *, QDesignerPropertySheetExtension *> m_propertySheet;
+ QStringList m_realPropertyNames;
+};
+
+// Name of the fake group
+static const char *headerGroup = "Header";
+
+// Name of the real properties
+static const char *visibleProperty = "visible";
+static const char *cascadingSectionResizesProperty = "cascadingSectionResizes";
+static const char *defaultSectionSizeProperty = "defaultSectionSize";
+static const char *highlightSectionsProperty = "highlightSections";
+static const char *minimumSectionSizeProperty = "minimumSectionSize";
+static const char *showSortIndicatorProperty = "showSortIndicator";
+static const char *stretchLastSectionProperty = "stretchLastSection";
+} // namespace qdesigner_internal
+
+using namespace qdesigner_internal;
+
+
+/***************** ItemViewPropertySheetPrivate *********************/
+
+ItemViewPropertySheetPrivate::ItemViewPropertySheetPrivate(QHeaderView *horizontalHeader,
+ QHeaderView *verticalHeader,
+ QObject *parent)
+ : m_core(formEditorForObject(parent)),
+ m_hHeader(horizontalHeader),
+ m_vHeader(verticalHeader)
+{
+ if (horizontalHeader)
+ m_propertySheet.insert(horizontalHeader,
+ qt_extension<QDesignerPropertySheetExtension*>
+ (m_core->extensionManager(), horizontalHeader));
+ if (verticalHeader)
+ m_propertySheet.insert(verticalHeader,
+ qt_extension<QDesignerPropertySheetExtension*>
+ (m_core->extensionManager(), verticalHeader));
+}
+
+// Find the form editor in the hierarchy.
+// We know that the parent of the sheet is the extension manager
+// whose parent is the core.
+QDesignerFormEditorInterface *ItemViewPropertySheetPrivate::formEditorForObject(QObject *o)
+{
+ do {
+ if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(o))
+ return core;
+ o = o->parent();
+ } while(o);
+ Q_ASSERT(o);
+ return 0;
+}
+
+void ItemViewPropertySheetPrivate::createMapping(int fakeId, QHeaderView *header,
+ const QString &headerName)
+{
+ const int realPropertyId = m_propertySheet.value(header)->indexOf(headerName);
+ QDesignerPropertySheetExtension *propertySheet = m_propertySheet.value(header);
+ m_propertyIdMap.insert(fakeId, Property(propertySheet, realPropertyId));
+}
+
+QStringList ItemViewPropertySheetPrivate::realPropertyNames()
+{
+ if (m_realPropertyNames.isEmpty())
+ m_realPropertyNames
+ << QLatin1String(visibleProperty)
+ << QLatin1String(cascadingSectionResizesProperty)
+ << QLatin1String(defaultSectionSizeProperty)
+ << QLatin1String(highlightSectionsProperty)
+ << QLatin1String(minimumSectionSizeProperty)
+ << QLatin1String(showSortIndicatorProperty)
+ << QLatin1String(stretchLastSectionProperty);
+ return m_realPropertyNames;
+}
+
+QString ItemViewPropertySheetPrivate::fakePropertyName(const QString &prefix,
+ const QString &realName)
+{
+ // prefix = "header", realPropertyName = "isVisible" returns "headerIsVisible"
+ QString fakeName = prefix + realName.at(0).toUpper() + realName.mid(1);
+ m_propertyNameMap.insert(fakeName, realName);
+ return fakeName;
+}
+
+/***************** ItemViewPropertySheet *********************/
+
+/*!
+ \class qdesigner_internal::ItemViewPropertySheet
+
+ \brief
+ Adds header fake properties to QTreeView and QTableView objects
+
+ QHeaderView objects are currently not shown in the object inspector.
+ This class adds some fake properties to the property sheet
+ of QTreeView and QTableView objects that nevertheless allow the manipulation
+ of the headers attached to the item view object.
+
+ Currently the defaultAlignment property is not shown because the property sheet
+ would only show integers, instead of the Qt::Alignment enumeration.
+
+ The fake properties here need special handling in QDesignerResource, uiloader and uic.
+ */
+
+ItemViewPropertySheet::ItemViewPropertySheet(QTreeView *treeViewObject, QObject *parent)
+ : QDesignerPropertySheet(treeViewObject, parent),
+ d(new ItemViewPropertySheetPrivate(treeViewObject->header(), 0, parent))
+{
+ QHeaderView *hHeader = treeViewObject->header();
+
+ foreach (const QString &realPropertyName, d->realPropertyNames()) {
+ const QString fakePropertyName
+ = d->fakePropertyName(QLatin1String("header"), realPropertyName);
+ d->createMapping(createFakeProperty(fakePropertyName, 0), hHeader, realPropertyName);
+ }
+
+ foreach (int id, d->m_propertyIdMap.keys()) {
+ setAttribute(id, true);
+ setPropertyGroup(id, QLatin1String(headerGroup));
+ }
+}
+
+
+ItemViewPropertySheet::ItemViewPropertySheet(QTableView *tableViewObject, QObject *parent)
+ : QDesignerPropertySheet(tableViewObject, parent),
+ d(new ItemViewPropertySheetPrivate(tableViewObject->horizontalHeader(),
+ tableViewObject->verticalHeader(), parent))
+{
+ QHeaderView *hHeader = tableViewObject->horizontalHeader();
+ QHeaderView *vHeader = tableViewObject->verticalHeader();
+
+ foreach (const QString &realPropertyName, d->realPropertyNames()) {
+ const QString fakePropertyName
+ = d->fakePropertyName(QLatin1String("horizontalHeader"), realPropertyName);
+ d->createMapping(createFakeProperty(fakePropertyName, 0), hHeader, realPropertyName);
+ }
+ foreach (const QString &realPropertyName, d->realPropertyNames()) {
+ const QString fakePropertyName
+ = d->fakePropertyName(QLatin1String("verticalHeader"), realPropertyName);
+ d->createMapping(createFakeProperty(fakePropertyName, 0), vHeader, realPropertyName);
+ }
+
+ foreach (int id, d->m_propertyIdMap.keys()) {
+ setAttribute(id, true);
+ setPropertyGroup(id, QLatin1String(headerGroup));
+ }
+}
+
+ItemViewPropertySheet::~ItemViewPropertySheet()
+{
+ delete d;
+}
+
+/*!
+ Returns the mapping of fake property names to real property names
+ */
+QHash<QString,QString> ItemViewPropertySheet::propertyNameMap() const
+{
+ return d->m_propertyNameMap;
+}
+
+QVariant ItemViewPropertySheet::property(int index) const
+{
+ if (d->m_propertyIdMap.contains(index)) {
+ Property realProperty = d->m_propertyIdMap.value(index);
+ return realProperty.m_sheet->property(realProperty.m_id);
+ } else {
+ return QDesignerPropertySheet::property(index);
+ }
+}
+
+void ItemViewPropertySheet::setProperty(int index, const QVariant &value)
+{
+ if (d->m_propertyIdMap.contains(index)) {
+ Property realProperty = d->m_propertyIdMap.value(index);
+ realProperty.m_sheet->setProperty(realProperty.m_id, value);
+ } else {
+ QDesignerPropertySheet::setProperty(index, value);
+ }
+}
+
+void ItemViewPropertySheet::setChanged(int index, bool changed)
+{
+ if (d->m_propertyIdMap.contains(index)) {
+ Property realProperty = d->m_propertyIdMap.value(index);
+ realProperty.m_sheet->setChanged(realProperty.m_id, changed);
+ }
+ QDesignerPropertySheet::setChanged(index, changed);
+}
+
+bool ItemViewPropertySheet::reset(int index)
+{
+ if (d->m_propertyIdMap.contains(index)) {
+ Property realProperty = d->m_propertyIdMap.value(index);
+ return realProperty.m_sheet->reset(realProperty.m_id);
+ } else {
+ return QDesignerPropertySheet::reset(index);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/itemview_propertysheet.h b/tools/designer/src/components/formeditor/itemview_propertysheet.h
new file mode 100644
index 0000000000..e4c80dd347
--- /dev/null
+++ b/tools/designer/src/components/formeditor/itemview_propertysheet.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ITEMVIEW_PROPERTYSHEET_H
+#define ITEMVIEW_PROPERTYSHEET_H
+
+#include <qdesigner_propertysheet_p.h>
+#include <extensionfactory_p.h>
+
+#include <QtGui/QTreeView>
+#include <QtGui/QTableView>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class ItemViewPropertySheetPrivate;
+
+class ItemViewPropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension)
+public:
+ explicit ItemViewPropertySheet(QTreeView *treeViewObject, QObject *parent = 0);
+ explicit ItemViewPropertySheet(QTableView *tableViewObject, QObject *parent = 0);
+ ~ItemViewPropertySheet();
+
+ QHash<QString,QString> propertyNameMap() const;
+
+ // QDesignerPropertySheet
+ QVariant property(int index) const;
+ void setProperty(int index, const QVariant &value);
+
+ void setChanged(int index, bool changed);
+
+ bool reset(int index);
+
+private:
+ ItemViewPropertySheetPrivate *d;
+};
+
+typedef QDesignerPropertySheetFactory<QTreeView, ItemViewPropertySheet>
+ QTreeViewPropertySheetFactory;
+typedef QDesignerPropertySheetFactory<QTableView, ItemViewPropertySheet>
+ QTableViewPropertySheetFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ITEMVIEW_PROPERTYSHEET_H
diff --git a/tools/designer/src/components/formeditor/layout_propertysheet.cpp b/tools/designer/src/components/formeditor/layout_propertysheet.cpp
new file mode 100644
index 0000000000..a304c6a47f
--- /dev/null
+++ b/tools/designer/src/components/formeditor/layout_propertysheet.cpp
@@ -0,0 +1,546 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "layout_propertysheet.h"
+
+// sdk
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+// shared
+#include <ui4_p.h>
+#include <qlayout_widget_p.h>
+#include <formbuilderextra_p.h>
+
+#include <QtGui/QFormLayout>
+
+#include <QtCore/QHash>
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+#include <QtCore/QByteArray>
+#include <QtCore/QRegExp> // Remove once there is an editor for lists
+
+QT_BEGIN_NAMESPACE
+
+#define USE_LAYOUT_SIZE_CONSTRAINT
+
+static const char *leftMargin = "leftMargin";
+static const char *topMargin = "topMargin";
+static const char *rightMargin = "rightMargin";
+static const char *bottomMargin = "bottomMargin";
+static const char *horizontalSpacing = "horizontalSpacing";
+static const char *verticalSpacing = "verticalSpacing";
+static const char *spacing = "spacing";
+static const char *margin = "margin";
+static const char *sizeConstraint = "sizeConstraint";
+static const char *boxStretchPropertyC = "stretch";
+static const char *gridRowStretchPropertyC = "rowStretch";
+static const char *gridColumnStretchPropertyC = "columnStretch";
+static const char *gridRowMinimumHeightPropertyC = "rowMinimumHeight";
+static const char *gridColumnMinimumWidthPropertyC = "columnMinimumWidth";
+
+namespace {
+ enum LayoutPropertyType {
+ LayoutPropertyNone,
+ LayoutPropertyMargin, // Deprecated
+ LayoutPropertyLeftMargin,
+ LayoutPropertyTopMargin,
+ LayoutPropertyRightMargin,
+ LayoutPropertyBottomMargin,
+ LayoutPropertySpacing,
+ LayoutPropertyHorizontalSpacing,
+ LayoutPropertyVerticalSpacing,
+ LayoutPropertySizeConstraint,
+ LayoutPropertyBoxStretch,
+ LayoutPropertyGridRowStretch,
+ LayoutPropertyGridColumnStretch,
+ LayoutPropertyGridRowMinimumHeight,
+ LayoutPropertyGridColumnMinimumWidth
+ };
+}
+
+// Check for a comma-separated list of integers. Used for
+// per-cell stretch properties and grid per row/column properties.
+// As it works now, they are passed as QByteArray strings. The
+// property sheet refuses all invalid values. This could be
+// replaced by lists once the property editor can handle them.
+
+static bool isIntegerList(const QString &s)
+{
+ // Check for empty string or comma-separated list of integers
+ static const QRegExp re(QLatin1String("[0-9]+(,[0-9]+)+"));
+ Q_ASSERT(re.isValid());
+ return s.isEmpty() || re.exactMatch(s);
+}
+
+// Quick lookup by name
+static LayoutPropertyType layoutPropertyType(const QString &name)
+{
+ static QHash<QString, LayoutPropertyType> namePropertyMap;
+ if (namePropertyMap.empty()) {
+ namePropertyMap.insert(QLatin1String(leftMargin), LayoutPropertyLeftMargin);
+ namePropertyMap.insert(QLatin1String(topMargin), LayoutPropertyTopMargin);
+ namePropertyMap.insert(QLatin1String(rightMargin), LayoutPropertyRightMargin);
+ namePropertyMap.insert(QLatin1String(bottomMargin), LayoutPropertyBottomMargin);
+ namePropertyMap.insert(QLatin1String(horizontalSpacing), LayoutPropertyHorizontalSpacing);
+ namePropertyMap.insert(QLatin1String(verticalSpacing), LayoutPropertyVerticalSpacing);
+ namePropertyMap.insert(QLatin1String(spacing), LayoutPropertySpacing);
+ namePropertyMap.insert(QLatin1String(margin), LayoutPropertyMargin);
+ namePropertyMap.insert(QLatin1String(sizeConstraint), LayoutPropertySizeConstraint);
+ namePropertyMap.insert(QLatin1String(boxStretchPropertyC ), LayoutPropertyBoxStretch);
+ namePropertyMap.insert(QLatin1String(gridRowStretchPropertyC), LayoutPropertyGridRowStretch);
+ namePropertyMap.insert(QLatin1String(gridColumnStretchPropertyC), LayoutPropertyGridColumnStretch);
+ namePropertyMap.insert(QLatin1String(gridRowMinimumHeightPropertyC), LayoutPropertyGridRowMinimumHeight);
+ namePropertyMap.insert(QLatin1String(gridColumnMinimumWidthPropertyC), LayoutPropertyGridColumnMinimumWidth);
+ }
+ return namePropertyMap.value(name, LayoutPropertyNone);
+}
+
+// return the layout margin if it is margin
+static int getLayoutMargin(const QLayout *l, LayoutPropertyType type)
+{
+ int left, top, right, bottom;
+ l->getContentsMargins(&left, &top, &right, &bottom);
+ switch (type) {
+ case LayoutPropertyLeftMargin:
+ return left;
+ case LayoutPropertyTopMargin:
+ return top;
+ case LayoutPropertyRightMargin:
+ return right;
+ case LayoutPropertyBottomMargin:
+ return bottom;
+ default:
+ Q_ASSERT(0);
+ break;
+ }
+ return 0;
+}
+
+// return the layout margin if it is margin
+static void setLayoutMargin(QLayout *l, LayoutPropertyType type, int margin)
+{
+ int left, top, right, bottom;
+ l->getContentsMargins(&left, &top, &right, &bottom);
+ switch (type) {
+ case LayoutPropertyLeftMargin:
+ left = margin;
+ break;
+ case LayoutPropertyTopMargin:
+ top = margin;
+ break;
+ case LayoutPropertyRightMargin:
+ right = margin;
+ break;
+ case LayoutPropertyBottomMargin:
+ bottom = margin;
+ break;
+ default:
+ Q_ASSERT(0);
+ break;
+ }
+ l->setContentsMargins(left, top, right, bottom);
+}
+
+namespace qdesigner_internal {
+
+// ---------- LayoutPropertySheet: This sheet is never visible in
+// the property editor. Rather, the sheet pulled for QLayoutWidget
+// forwards all properties to it. Some properties (grid spacings) must be handled
+// manually, as they are QDOC_PROPERTY only and not visible to introspection. Ditto
+// for the 4 margins.
+
+LayoutPropertySheet::LayoutPropertySheet(QLayout *l, QObject *parent)
+ : QDesignerPropertySheet(l, parent), m_layout(l)
+{
+ const QString layoutGroup = QLatin1String("Layout");
+ int pindex = createFakeProperty(QLatin1String(leftMargin), 0);
+ setPropertyGroup(pindex, layoutGroup);
+
+ pindex = createFakeProperty(QLatin1String(topMargin), 0);
+ setPropertyGroup(pindex, layoutGroup);
+
+ pindex = createFakeProperty(QLatin1String(rightMargin), 0);
+ setPropertyGroup(pindex, layoutGroup);
+
+ pindex = createFakeProperty(QLatin1String(bottomMargin), 0);
+ setPropertyGroup(pindex, layoutGroup);
+
+ const int visibleMask = LayoutProperties::visibleProperties(m_layout);
+ if (visibleMask & LayoutProperties::HorizSpacingProperty) {
+ pindex = createFakeProperty(QLatin1String(horizontalSpacing), 0);
+ setPropertyGroup(pindex, layoutGroup);
+
+ pindex = createFakeProperty(QLatin1String(verticalSpacing), 0);
+ setPropertyGroup(pindex, layoutGroup);
+
+ setAttribute(indexOf(QLatin1String(spacing)), true);
+ }
+
+ setAttribute(indexOf(QLatin1String(margin)), true);
+ // Stretch
+ if (visibleMask & LayoutProperties::BoxStretchProperty) {
+ pindex = createFakeProperty(QLatin1String(boxStretchPropertyC), QByteArray());
+ setPropertyGroup(pindex, layoutGroup);
+ setAttribute(pindex, true);
+ } else {
+ // Add the grid per-row/column stretch and size limits
+ if (visibleMask & LayoutProperties::GridColumnStretchProperty) {
+ const QByteArray empty;
+ pindex = createFakeProperty(QLatin1String(gridRowStretchPropertyC), empty);
+ setPropertyGroup(pindex, layoutGroup);
+ setAttribute(pindex, true);
+ pindex = createFakeProperty(QLatin1String(gridColumnStretchPropertyC), empty);
+ setPropertyGroup(pindex, layoutGroup);
+ setAttribute(pindex, true);
+ pindex = createFakeProperty(QLatin1String(gridRowMinimumHeightPropertyC), empty);
+ setPropertyGroup(pindex, layoutGroup);
+ setAttribute(pindex, true);
+ pindex = createFakeProperty(QLatin1String(gridColumnMinimumWidthPropertyC), empty);
+ setPropertyGroup(pindex, layoutGroup);
+ setAttribute(pindex, true);
+ }
+ }
+#ifdef USE_LAYOUT_SIZE_CONSTRAINT
+ // SizeConstraint cannot possibly be handled as a real property
+ // as it affects the layout parent widget and thus
+ // conflicts with Designer's special layout widget.
+ // It will take effect on the preview only.
+ pindex = createFakeProperty(QLatin1String(sizeConstraint));
+ setPropertyGroup(pindex, layoutGroup);
+#endif
+}
+
+LayoutPropertySheet::~LayoutPropertySheet()
+{
+}
+
+void LayoutPropertySheet::setProperty(int index, const QVariant &value)
+{
+ const LayoutPropertyType type = layoutPropertyType(propertyName(index));
+ if (QLayoutWidget *lw = qobject_cast<QLayoutWidget *>(m_layout->parent())) {
+ switch (type) {
+ case LayoutPropertyLeftMargin:
+ lw->setLayoutLeftMargin(value.toInt());
+ return;
+ case LayoutPropertyTopMargin:
+ lw->setLayoutTopMargin(value.toInt());
+ return;
+ case LayoutPropertyRightMargin:
+ lw->setLayoutRightMargin(value.toInt());
+ return;
+ case LayoutPropertyBottomMargin:
+ lw->setLayoutBottomMargin(value.toInt());
+ return;
+ case LayoutPropertyMargin: {
+ const int v = value.toInt();
+ lw->setLayoutLeftMargin(v);
+ lw->setLayoutTopMargin(v);
+ lw->setLayoutRightMargin(v);
+ lw->setLayoutBottomMargin(v);
+ }
+ return;
+ default:
+ break;
+ }
+ }
+ switch (type) {
+ case LayoutPropertyLeftMargin:
+ case LayoutPropertyTopMargin:
+ case LayoutPropertyRightMargin:
+ case LayoutPropertyBottomMargin:
+ setLayoutMargin(m_layout, type, value.toInt());
+ return;
+ case LayoutPropertyHorizontalSpacing:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) {
+ grid->setHorizontalSpacing(value.toInt());
+ return;
+ }
+ if (QFormLayout *form = qobject_cast<QFormLayout *>(m_layout)) {
+ form->setHorizontalSpacing(value.toInt());
+ return;
+ }
+ break;
+ case LayoutPropertyVerticalSpacing:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) {
+ grid->setVerticalSpacing(value.toInt());
+ return;
+ }
+ if (QFormLayout *form = qobject_cast<QFormLayout *>(m_layout)) {
+ form->setVerticalSpacing(value.toInt());
+ return;
+ }
+ break;
+ case LayoutPropertyBoxStretch:
+ // TODO: Remove the regexp check once a proper editor for integer
+ // lists is in place?
+ if (QBoxLayout *box = qobject_cast<QBoxLayout *>(m_layout)) {
+ const QString stretch = value.toString();
+ if (isIntegerList(stretch))
+ QFormBuilderExtra::setBoxLayoutStretch(value.toString(), box);
+ }
+ break;
+ case LayoutPropertyGridRowStretch:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) {
+ const QString stretch = value.toString();
+ if (isIntegerList(stretch))
+ QFormBuilderExtra::setGridLayoutRowStretch(stretch, grid);
+ }
+ break;
+ case LayoutPropertyGridColumnStretch:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) {
+ const QString stretch = value.toString();
+ if (isIntegerList(stretch))
+ QFormBuilderExtra::setGridLayoutColumnStretch(value.toString(), grid);
+ }
+ break;
+ case LayoutPropertyGridRowMinimumHeight:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) {
+ const QString minSize = value.toString();
+ if (isIntegerList(minSize))
+ QFormBuilderExtra::setGridLayoutRowMinimumHeight(minSize, grid);
+ }
+ break;
+ case LayoutPropertyGridColumnMinimumWidth:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout)) {
+ const QString minSize = value.toString();
+ if (isIntegerList(minSize))
+ QFormBuilderExtra::setGridLayoutColumnMinimumWidth(minSize, grid);
+ }
+ break;
+ default:
+ break;
+ }
+ QDesignerPropertySheet::setProperty(index, value);
+}
+
+QVariant LayoutPropertySheet::property(int index) const
+{
+ const LayoutPropertyType type = layoutPropertyType(propertyName(index));
+ if (const QLayoutWidget *lw = qobject_cast<QLayoutWidget *>(m_layout->parent())) {
+ switch (type) {
+ case LayoutPropertyLeftMargin:
+ return lw->layoutLeftMargin();
+ case LayoutPropertyTopMargin:
+ return lw->layoutTopMargin();
+ case LayoutPropertyRightMargin:
+ return lw->layoutRightMargin();
+ case LayoutPropertyBottomMargin:
+ return lw->layoutBottomMargin();
+ default:
+ break;
+ }
+ }
+ switch (type) {
+ case LayoutPropertyLeftMargin:
+ case LayoutPropertyTopMargin:
+ case LayoutPropertyRightMargin:
+ case LayoutPropertyBottomMargin:
+ return getLayoutMargin(m_layout, type);
+ case LayoutPropertyHorizontalSpacing:
+ if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ return grid->horizontalSpacing();
+ if (const QFormLayout *form = qobject_cast<QFormLayout *>(m_layout))
+ return form->horizontalSpacing();
+ break;
+ case LayoutPropertyVerticalSpacing:
+ if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ return grid->verticalSpacing();
+ if (const QFormLayout *form = qobject_cast<QFormLayout *>(m_layout))
+ return form->verticalSpacing();
+ case LayoutPropertyBoxStretch:
+ if (const QBoxLayout *box = qobject_cast<QBoxLayout *>(m_layout))
+ return QVariant(QByteArray(QFormBuilderExtra::boxLayoutStretch(box).toUtf8()));
+ break;
+ case LayoutPropertyGridRowStretch:
+ if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ return QVariant(QByteArray(QFormBuilderExtra::gridLayoutRowStretch(grid).toUtf8()));
+ break;
+ case LayoutPropertyGridColumnStretch:
+ if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ return QVariant(QByteArray(QFormBuilderExtra::gridLayoutColumnStretch(grid).toUtf8()));
+ break;
+ case LayoutPropertyGridRowMinimumHeight:
+ if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ return QVariant(QByteArray(QFormBuilderExtra::gridLayoutRowMinimumHeight(grid).toUtf8()));
+ break;
+ case LayoutPropertyGridColumnMinimumWidth:
+ if (const QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ return QVariant(QByteArray(QFormBuilderExtra::gridLayoutColumnMinimumWidth(grid).toUtf8()));
+ break;
+ default:
+ break;
+ }
+ return QDesignerPropertySheet::property(index);
+}
+
+bool LayoutPropertySheet::reset(int index)
+{
+ int left, top, right, bottom;
+ m_layout->getContentsMargins(&left, &top, &right, &bottom);
+ const LayoutPropertyType type = layoutPropertyType(propertyName(index));
+ bool rc = true;
+ switch (type) {
+ case LayoutPropertyLeftMargin:
+ m_layout->setContentsMargins(-1, top, right, bottom);
+ break;
+ case LayoutPropertyTopMargin:
+ m_layout->setContentsMargins(left, -1, right, bottom);
+ break;
+ case LayoutPropertyRightMargin:
+ m_layout->setContentsMargins(left, top, -1, bottom);
+ break;
+ case LayoutPropertyBottomMargin:
+ m_layout->setContentsMargins(left, top, right, -1);
+ break;
+ case LayoutPropertyBoxStretch:
+ if (QBoxLayout *box = qobject_cast<QBoxLayout *>(m_layout))
+ QFormBuilderExtra::clearBoxLayoutStretch(box);
+ break;
+ case LayoutPropertyGridRowStretch:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ QFormBuilderExtra::clearGridLayoutRowStretch(grid);
+ break;
+ case LayoutPropertyGridColumnStretch:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ QFormBuilderExtra::clearGridLayoutColumnStretch(grid);
+ break;
+ case LayoutPropertyGridRowMinimumHeight:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ QFormBuilderExtra::clearGridLayoutRowMinimumHeight(grid);
+ break;
+ case LayoutPropertyGridColumnMinimumWidth:
+ if (QGridLayout *grid = qobject_cast<QGridLayout *>(m_layout))
+ QFormBuilderExtra::clearGridLayoutColumnMinimumWidth(grid);
+ break;
+ default:
+ rc = QDesignerPropertySheet::reset(index);
+ break;
+ }
+ return rc;
+}
+
+void LayoutPropertySheet::setChanged(int index, bool changed)
+{
+ const LayoutPropertyType type = layoutPropertyType(propertyName(index));
+ switch (type) {
+ case LayoutPropertySpacing:
+ if (LayoutProperties::visibleProperties(m_layout) & LayoutProperties::HorizSpacingProperty) {
+ setChanged(indexOf(QLatin1String(horizontalSpacing)), changed);
+ setChanged(indexOf(QLatin1String(verticalSpacing)), changed);
+ }
+ break;
+ case LayoutPropertyMargin:
+ setChanged(indexOf(QLatin1String(leftMargin)), changed);
+ setChanged(indexOf(QLatin1String(topMargin)), changed);
+ setChanged(indexOf(QLatin1String(rightMargin)), changed);
+ setChanged(indexOf(QLatin1String(bottomMargin)), changed);
+ break;
+ default:
+ break;
+ }
+ QDesignerPropertySheet::setChanged(index, changed);
+}
+
+void LayoutPropertySheet::stretchAttributesToDom(QDesignerFormEditorInterface *core, QLayout *lt, DomLayout *domLayout)
+{
+ // Check if the respective stretch properties of the layout are changed.
+ // If so, set them to the DOM
+ const int visibleMask = LayoutProperties::visibleProperties(lt);
+ if (!(visibleMask & (LayoutProperties::BoxStretchProperty|LayoutProperties::GridColumnStretchProperty|LayoutProperties::GridRowStretchProperty)))
+ return;
+ const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), lt);
+ Q_ASSERT(sheet);
+
+ // Stretch
+ if (visibleMask & LayoutProperties::BoxStretchProperty) {
+ const int index = sheet->indexOf(QLatin1String(boxStretchPropertyC));
+ Q_ASSERT(index != -1);
+ if (sheet->isChanged(index))
+ domLayout->setAttributeStretch(sheet->property(index).toString());
+ }
+ if (visibleMask & LayoutProperties::GridColumnStretchProperty) {
+ const int index = sheet->indexOf(QLatin1String(gridColumnStretchPropertyC));
+ Q_ASSERT(index != -1);
+ if (sheet->isChanged(index))
+ domLayout->setAttributeColumnStretch(sheet->property(index).toString());
+ }
+ if (visibleMask & LayoutProperties::GridRowStretchProperty) {
+ const int index = sheet->indexOf(QLatin1String(gridRowStretchPropertyC));
+ Q_ASSERT(index != -1);
+ if (sheet->isChanged(index))
+ domLayout->setAttributeRowStretch(sheet->property(index).toString());
+ }
+ if (visibleMask & LayoutProperties::GridRowMinimumHeightProperty) {
+ const int index = sheet->indexOf(QLatin1String(gridRowMinimumHeightPropertyC));
+ Q_ASSERT(index != -1);
+ if (sheet->isChanged(index))
+ domLayout->setAttributeRowMinimumHeight(sheet->property(index).toString());
+ }
+ if (visibleMask & LayoutProperties::GridColumnMinimumWidthProperty) {
+ const int index = sheet->indexOf(QLatin1String(gridColumnMinimumWidthPropertyC));
+ Q_ASSERT(index != -1);
+ if (sheet->isChanged(index))
+ domLayout->setAttributeColumnMinimumWidth(sheet->property(index).toString());
+ }
+}
+
+void LayoutPropertySheet::markChangedStretchProperties(QDesignerFormEditorInterface *core, QLayout *lt, const DomLayout *domLayout)
+{
+ // While the actual values are applied by the form builder, we still need
+ // to mark them as 'changed'.
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), lt);
+ Q_ASSERT(sheet);
+ if (!domLayout->attributeStretch().isEmpty())
+ sheet->setChanged(sheet->indexOf(QLatin1String(boxStretchPropertyC)), true);
+ if (!domLayout->attributeRowStretch().isEmpty())
+ sheet->setChanged(sheet->indexOf(QLatin1String(gridRowStretchPropertyC)), true);
+ if (!domLayout->attributeColumnStretch().isEmpty())
+ sheet->setChanged(sheet->indexOf(QLatin1String(gridColumnStretchPropertyC)), true);
+ if (!domLayout->attributeColumnMinimumWidth().isEmpty())
+ sheet->setChanged(sheet->indexOf(QLatin1String(gridColumnMinimumWidthPropertyC)), true);
+ if (!domLayout->attributeRowMinimumHeight().isEmpty())
+ sheet->setChanged(sheet->indexOf(QLatin1String(gridRowMinimumHeightPropertyC)), true);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/layout_propertysheet.h b/tools/designer/src/components/formeditor/layout_propertysheet.h
new file mode 100644
index 0000000000..bb2b7852b9
--- /dev/null
+++ b/tools/designer/src/components/formeditor/layout_propertysheet.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LAYOUT_PROPERTYSHEET_H
+#define LAYOUT_PROPERTYSHEET_H
+
+#include <qdesigner_propertysheet_p.h>
+#include <extensionfactory_p.h>
+
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class DomLayout;
+
+namespace qdesigner_internal {
+
+class LayoutPropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension)
+public:
+ explicit LayoutPropertySheet(QLayout *object, QObject *parent = 0);
+ virtual ~LayoutPropertySheet();
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual QVariant property(int index) const;
+ virtual bool reset(int index);
+ void setChanged(int index, bool changed);
+
+ static void stretchAttributesToDom(QDesignerFormEditorInterface *core, QLayout *lt, DomLayout *domLayout);
+ static void markChangedStretchProperties(QDesignerFormEditorInterface *core, QLayout *lt, const DomLayout *domLayout);
+
+private:
+ QLayout *m_layout;
+};
+
+typedef QDesignerPropertySheetFactory<QLayout, LayoutPropertySheet> LayoutPropertySheetFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LAYOUT_PROPERTYSHEET_H
diff --git a/tools/designer/src/components/formeditor/line_propertysheet.cpp b/tools/designer/src/components/formeditor/line_propertysheet.cpp
new file mode 100644
index 0000000000..d13779e032
--- /dev/null
+++ b/tools/designer/src/components/formeditor/line_propertysheet.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "line_propertysheet.h"
+#include "formwindow.h"
+
+// sdk
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QLayout>
+#include <QtCore/QMetaObject>
+#include <QtCore/QMetaProperty>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+LinePropertySheet::LinePropertySheet(Line *object, QObject *parent)
+ : QDesignerPropertySheet(object, parent)
+{
+ clearFakeProperties();
+}
+
+LinePropertySheet::~LinePropertySheet()
+{
+}
+
+bool LinePropertySheet::isVisible(int index) const
+{
+ const QString name = propertyName(index);
+
+ if (name == QLatin1String("frameShape"))
+ return false;
+ return QDesignerPropertySheet::isVisible(index);
+}
+
+void LinePropertySheet::setProperty(int index, const QVariant &value)
+{
+ QDesignerPropertySheet::setProperty(index, value);
+}
+
+QString LinePropertySheet::propertyGroup(int index) const
+{
+ return QDesignerPropertySheet::propertyGroup(index);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/line_propertysheet.h b/tools/designer/src/components/formeditor/line_propertysheet.h
new file mode 100644
index 0000000000..5149cacef4
--- /dev/null
+++ b/tools/designer/src/components/formeditor/line_propertysheet.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LINE_PROPERTYSHEET_H
+#define LINE_PROPERTYSHEET_H
+
+#include <qdesigner_propertysheet_p.h>
+#include <qdesigner_widget_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class LinePropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension)
+public:
+ explicit LinePropertySheet(Line *object, QObject *parent = 0);
+ virtual ~LinePropertySheet();
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual bool isVisible(int index) const;
+ virtual QString propertyGroup(int index) const;
+};
+
+typedef QDesignerPropertySheetFactory<Line, LinePropertySheet> LinePropertySheetFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LINE_PROPERTYSHEET_H
diff --git a/tools/designer/src/components/formeditor/previewactiongroup.cpp b/tools/designer/src/components/formeditor/previewactiongroup.cpp
new file mode 100644
index 0000000000..aa52872912
--- /dev/null
+++ b/tools/designer/src/components/formeditor/previewactiongroup.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "previewactiongroup.h"
+
+#include <deviceprofile_p.h>
+#include <shared_settings_p.h>
+
+#include <QtGui/QStyleFactory>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+enum { MaxDeviceActions = 20 };
+
+namespace qdesigner_internal {
+
+PreviewActionGroup::PreviewActionGroup(QDesignerFormEditorInterface *core, QObject *parent) :
+ QActionGroup(parent),
+ m_core(core)
+{
+ /* Create a list of up to MaxDeviceActions invisible actions to be
+ * populated with device profiles (actiondata: index) followed by the
+ * standard style actions (actiondata: style name). */
+ connect(this, SIGNAL(triggered(QAction*)), this, SLOT(slotTriggered(QAction*)));
+ setExclusive(true);
+
+ const QString objNamePostfix = QLatin1String("_action");
+ // Create invisible actions for devices. Set index as action data.
+ QString objNamePrefix = QLatin1String("__qt_designer_device_");
+ for (int i = 0; i < MaxDeviceActions; i++) {
+ QAction *a = new QAction(this);
+ QString objName = objNamePrefix;
+ objName += QString::number(i);
+ objName += objNamePostfix;
+ a->setObjectName(objName);
+ a->setVisible(false);
+ a->setData(i);
+ addAction(a);
+ }
+ // Create separator at index MaxDeviceActions
+ QAction *sep = new QAction(this);
+ sep->setObjectName(QLatin1String("__qt_designer_deviceseparator"));
+ sep->setSeparator(true);
+ sep->setVisible(false);
+ addAction(sep);
+ // Populate devices
+ updateDeviceProfiles();
+
+ // Add style actions
+ const QStringList styles = QStyleFactory::keys();
+ const QStringList::const_iterator cend = styles.constEnd();
+ // Make sure ObjectName is unique in case toolbar solution is used.
+ objNamePrefix = QLatin1String("__qt_designer_style_");
+ // Create styles. Set style name string as action data.
+ for (QStringList::const_iterator it = styles.constBegin(); it != cend ;++it) {
+ QAction *a = new QAction(tr("%1 Style").arg(*it), this);
+ QString objName = objNamePrefix;
+ objName += *it;
+ objName += objNamePostfix;
+ a->setObjectName(objName);
+ a->setData(*it);
+ addAction(a);
+ }
+}
+
+void PreviewActionGroup::updateDeviceProfiles()
+{
+ typedef QList<DeviceProfile> DeviceProfileList;
+ typedef QList<QAction *> ActionList;
+
+ const QDesignerSharedSettings settings(m_core);
+ const DeviceProfileList profiles = settings.deviceProfiles();
+ const ActionList al = actions();
+ // Separator?
+ const bool hasProfiles = !profiles.empty();
+ al.at(MaxDeviceActions)->setVisible(hasProfiles);
+ int index = 0;
+ if (hasProfiles) {
+ // Make actions visible
+ const int maxIndex = qMin(static_cast<int>(MaxDeviceActions), profiles.size());
+ for (; index < maxIndex; index++) {
+ const QString name = profiles.at(index).name();
+ al.at(index)->setText(name);
+ al.at(index)->setVisible(true);
+ }
+ }
+ // Hide rest
+ for ( ; index < MaxDeviceActions; index++)
+ al.at(index)->setVisible(false);
+}
+
+void PreviewActionGroup::slotTriggered(QAction *a)
+{
+ // Device or style according to data.
+ const QVariant data = a->data();
+ switch (data.type()) {
+ case QVariant::String:
+ emit preview(data.toString(), -1);
+ break;
+ case QVariant::Int:
+ emit preview(QString(), data.toInt());
+ break;
+ default:
+ break;
+ }
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/previewactiongroup.h b/tools/designer/src/components/formeditor/previewactiongroup.h
new file mode 100644
index 0000000000..851f554cbe
--- /dev/null
+++ b/tools/designer/src/components/formeditor/previewactiongroup.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PREVIEWACTIONGROUP_H
+#define PREVIEWACTIONGROUP_H
+
+#include <QtGui/QActionGroup>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+/* PreviewActionGroup: To be used as a submenu for 'Preview in...'
+ * Offers a menu of styles and device profiles. */
+
+class PreviewActionGroup : public QActionGroup
+{
+ Q_DISABLE_COPY(PreviewActionGroup)
+ Q_OBJECT
+public:
+ explicit PreviewActionGroup(QDesignerFormEditorInterface *core, QObject *parent = 0);
+
+signals:
+ void preview(const QString &style, int deviceProfileIndex);
+
+public slots:
+ void updateDeviceProfiles();
+
+private slots:
+ void slotTriggered(QAction *);
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+}
+
+QT_END_NAMESPACE
+
+#endif // PREVIEWACTIONGROUP_H
diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.cpp b/tools/designer/src/components/formeditor/qdesigner_resource.cpp
new file mode 100644
index 0000000000..75a53b7bd8
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qdesigner_resource.cpp
@@ -0,0 +1,2665 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_resource.h"
+#include "formwindow.h"
+#include "dynamicpropertysheet.h"
+#include "qdesigner_tabwidget_p.h"
+#include "qdesigner_toolbox_p.h"
+#include "qdesigner_stackedbox_p.h"
+#include "qdesigner_toolbar_p.h"
+#include "qdesigner_dockwidget_p.h"
+#include "qdesigner_menu_p.h"
+#include "qdesigner_menubar_p.h"
+#include "qdesigner_membersheet_p.h"
+#include "qtresourcemodel_p.h"
+#include "qmdiarea_container.h"
+#include "qwizard_container.h"
+#include "itemview_propertysheet.h"
+#include "layout_propertysheet.h"
+
+#include <ui4_p.h>
+#include <formbuilderextra_p.h>
+#include <resourcebuilder_p.h>
+#include <textbuilder_p.h>
+#include <qdesigner_widgetitem_p.h>
+
+// shared
+#include <widgetdatabase_p.h>
+#include <metadatabase_p.h>
+#include <layout_p.h>
+#include <layoutinfo_p.h>
+#include <spacer_widget_p.h>
+#include <pluginmanager_p.h>
+#include <widgetfactory_p.h>
+#include <abstractlanguage.h>
+#include <abstractintrospection_p.h>
+
+#include <qlayout_widget_p.h>
+#include <qdesigner_utils_p.h>
+#include <ui4_p.h>
+
+// sdk
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormWindowToolInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <abstractdialoggui_p.h>
+
+#include <QtGui/QMenu>
+#include <QtGui/QMessageBox>
+#include <QtGui/QLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QToolBar>
+#include <QtGui/QTabBar>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QApplication>
+#include <QtGui/QMainWindow>
+#include <QtGui/QSplitter>
+#include <QtGui/QMdiArea>
+#include <QtGui/QWorkspace>
+#include <QtGui/QMenuBar>
+#include <QtGui/QFileDialog>
+#include <QtGui/QHeaderView>
+#include <QtGui/QTreeView>
+#include <QtGui/QTableView>
+#include <QtGui/QWizardPage>
+#include <private/qlayoutengine_p.h>
+
+#include <QtCore/QBuffer>
+#include <QtCore/QDir>
+#include <QtCore/QMetaProperty>
+#include <QtCore/qdebug.h>
+#include <QtCore/QXmlStreamWriter>
+
+Q_DECLARE_METATYPE(QWidgetList)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ typedef QList<DomProperty*> DomPropertyList;
+}
+
+static const char *currentUiVersion = "4.0";
+static const char *clipboardObjectName = "__qt_fake_top_level";
+
+#define OLD_RESOURCE_FORMAT // Support pre 4.4 format.
+
+namespace qdesigner_internal {
+
+// -------------------- QDesignerResourceBuilder: A resource builder that works on the property sheet icon types.
+class QDesignerResourceBuilder : public QResourceBuilder
+{
+public:
+ QDesignerResourceBuilder(QDesignerFormEditorInterface *core, DesignerPixmapCache *pixmapCache, DesignerIconCache *iconCache);
+
+ void setPixmapCache(DesignerPixmapCache *pixmapCache) { m_pixmapCache = pixmapCache; }
+ void setIconCache(DesignerIconCache *iconCache) { m_iconCache = iconCache; }
+ bool isSaveRelative() const { return m_saveRelative; }
+ void setSaveRelative(bool relative) { m_saveRelative = relative; }
+ QStringList usedQrcFiles() const { return m_usedQrcFiles.keys(); }
+#ifdef OLD_RESOURCE_FORMAT
+ QStringList loadedQrcFiles() const { return m_loadedQrcFiles.keys(); } // needed only for loading old resource attribute of <iconset> tag.
+#endif
+
+ virtual QVariant loadResource(const QDir &workingDirectory, const DomProperty *icon) const;
+
+ virtual QVariant toNativeValue(const QVariant &value) const;
+
+ virtual DomProperty *saveResource(const QDir &workingDirectory, const QVariant &value) const;
+
+ virtual bool isResourceType(const QVariant &value) const;
+private:
+
+ QDesignerFormEditorInterface *m_core;
+ DesignerPixmapCache *m_pixmapCache;
+ DesignerIconCache *m_iconCache;
+ bool m_saveRelative;
+ mutable QMap<QString, bool> m_usedQrcFiles;
+ mutable QMap<QString, bool> m_loadedQrcFiles;
+};
+
+QDesignerResourceBuilder::QDesignerResourceBuilder(QDesignerFormEditorInterface *core, DesignerPixmapCache *pixmapCache, DesignerIconCache *iconCache) :
+ m_core(core),
+ m_pixmapCache(pixmapCache),
+ m_iconCache(iconCache),
+ m_saveRelative(true)
+{
+}
+
+static inline void setIconPixmap(QIcon::Mode m, QIcon::State s, const QDir &workingDirectory, const QString &v, PropertySheetIconValue &icon)
+{
+ icon.setPixmap(m, s, PropertySheetPixmapValue(QFileInfo(workingDirectory, v).absoluteFilePath()));
+}
+
+QVariant QDesignerResourceBuilder::loadResource(const QDir &workingDirectory, const DomProperty *property) const
+{
+ switch (property->kind()) {
+ case DomProperty::Pixmap: {
+ PropertySheetPixmapValue pixmap;
+ DomResourcePixmap *dp = property->elementPixmap();
+ if (!dp->text().isEmpty()) {
+ pixmap.setPath(QFileInfo(workingDirectory, dp->text()).absoluteFilePath());
+#ifdef OLD_RESOURCE_FORMAT
+ if (dp->hasAttributeResource())
+ m_loadedQrcFiles.insert(QFileInfo(workingDirectory, dp->attributeResource()).absoluteFilePath(), false);
+#endif
+ }
+ return qVariantFromValue(pixmap);
+ }
+
+ case DomProperty::IconSet: {
+ PropertySheetIconValue icon;
+ DomResourceIcon *di = property->elementIconSet();
+ if (const int flags = iconStateFlags(di)) { // new, post 4.4 format
+ if (flags & NormalOff)
+ setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->elementNormalOff()->text(), icon);
+ if (flags & NormalOn)
+ setIconPixmap(QIcon::Normal, QIcon::On, workingDirectory, di->elementNormalOn()->text(), icon);
+ if (flags & DisabledOff)
+ setIconPixmap(QIcon::Disabled, QIcon::Off, workingDirectory, di->elementDisabledOff()->text(), icon);
+ if (flags & DisabledOn)
+ setIconPixmap(QIcon::Disabled, QIcon::On, workingDirectory, di->elementDisabledOn()->text(), icon);
+ if (flags & ActiveOff)
+ setIconPixmap(QIcon::Active, QIcon::Off, workingDirectory, di->elementActiveOff()->text(), icon);
+ if (flags & ActiveOn)
+ setIconPixmap(QIcon::Active, QIcon::On, workingDirectory, di->elementActiveOn()->text(), icon);
+ if (flags & SelectedOff)
+ setIconPixmap(QIcon::Selected, QIcon::Off, workingDirectory, di->elementSelectedOff()->text(), icon);
+ if (flags & SelectedOn)
+ setIconPixmap(QIcon::Selected, QIcon::On, workingDirectory, di->elementSelectedOn()->text(), icon);
+ } else {
+#ifdef OLD_RESOURCE_FORMAT
+ setIconPixmap(QIcon::Normal, QIcon::Off, workingDirectory, di->text(), icon);
+ if (di->hasAttributeResource())
+ m_loadedQrcFiles.insert(QFileInfo(workingDirectory, di->attributeResource()).absoluteFilePath(), false);
+#endif
+ }
+ return qVariantFromValue(icon);
+ }
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+QVariant QDesignerResourceBuilder::toNativeValue(const QVariant &value) const
+{
+ if (qVariantCanConvert<PropertySheetPixmapValue>(value)) {
+ if (m_pixmapCache)
+ return m_pixmapCache->pixmap(qVariantValue<PropertySheetPixmapValue>(value));
+ } else if (qVariantCanConvert<PropertySheetIconValue>(value)) {
+ if (m_iconCache)
+ return m_iconCache->icon(qVariantValue<PropertySheetIconValue>(value));
+ }
+ return value;
+}
+
+DomProperty *QDesignerResourceBuilder::saveResource(const QDir &workingDirectory, const QVariant &value) const
+{
+ DomProperty *p = new DomProperty;
+ if (qVariantCanConvert<PropertySheetPixmapValue>(value)) {
+ const PropertySheetPixmapValue pix = qvariant_cast<PropertySheetPixmapValue>(value);
+ DomResourcePixmap *rp = new DomResourcePixmap;
+ const QString pixPath = pix.path();
+ switch (pix.pixmapSource(m_core)) {
+ case PropertySheetPixmapValue::LanguageResourcePixmap:
+ rp->setText(pixPath);
+ break;
+ case PropertySheetPixmapValue::ResourcePixmap: {
+ rp->setText(pixPath);
+ const QString qrcFile = m_core->resourceModel()->qrcPath(pixPath);
+ if (!qrcFile.isEmpty()) {
+ m_usedQrcFiles.insert(qrcFile, false);
+#ifdef OLD_RESOURCE_FORMAT // Legacy: Add qrc path
+ rp->setAttributeResource(workingDirectory.relativeFilePath(qrcFile));
+#endif
+ }
+ }
+ break;
+ case PropertySheetPixmapValue::FilePixmap:
+ rp->setText(m_saveRelative ? workingDirectory.relativeFilePath(pixPath) : pixPath);
+ break;
+ }
+ p->setElementPixmap(rp);
+ return p;
+ } else if (qVariantCanConvert<PropertySheetIconValue>(value)) {
+ const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(value);
+ const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> pixmaps = icon.paths();
+ if (!pixmaps.isEmpty()) {
+ DomResourceIcon *ri = new DomResourceIcon;
+ QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPix(pixmaps);
+ while (itPix.hasNext()) {
+ const QIcon::Mode mode = itPix.next().key().first;
+ const QIcon::State state = itPix.key().second;
+ DomResourcePixmap *rp = new DomResourcePixmap;
+ const PropertySheetPixmapValue pix = itPix.value();
+ const PropertySheetPixmapValue::PixmapSource ps = pix.pixmapSource(m_core);
+ const QString pixPath = pix.path();
+ rp->setText(ps == PropertySheetPixmapValue::FilePixmap && m_saveRelative ? workingDirectory.relativeFilePath(pixPath) : pixPath);
+ if (state == QIcon::Off) {
+ switch (mode) {
+ case QIcon::Normal:
+ ri->setElementNormalOff(rp);
+#ifdef OLD_RESOURCE_FORMAT // Legacy: Set Normal off as text/path in old format.
+ ri->setText(rp->text());
+#endif
+ if (ps == PropertySheetPixmapValue::ResourcePixmap) {
+ // Be sure that ri->text() file comes from active resourceSet (i.e. make appropriate
+ // resourceSet active before calling this method).
+ const QString qrcFile = m_core->resourceModel()->qrcPath(ri->text());
+ if (!qrcFile.isEmpty()) {
+ m_usedQrcFiles.insert(qrcFile, false);
+#ifdef OLD_RESOURCE_FORMAT // Legacy: Set Normal off as text/path in old format.
+ ri->setAttributeResource(workingDirectory.relativeFilePath(qrcFile));
+#endif
+ }
+ }
+ break;
+ case QIcon::Disabled: ri->setElementDisabledOff(rp); break;
+ case QIcon::Active: ri->setElementActiveOff(rp); break;
+ case QIcon::Selected: ri->setElementSelectedOff(rp); break;
+ }
+ } else {
+ switch (mode) {
+ case QIcon::Normal: ri->setElementNormalOn(rp); break;
+ case QIcon::Disabled: ri->setElementDisabledOn(rp); break;
+ case QIcon::Active: ri->setElementActiveOn(rp); break;
+ case QIcon::Selected: ri->setElementSelectedOn(rp); break;
+ }
+ }
+ }
+ p->setElementIconSet(ri);
+ return p;
+ }
+ }
+ delete p;
+ return 0;
+}
+
+bool QDesignerResourceBuilder::isResourceType(const QVariant &value) const
+{
+ if (qVariantCanConvert<PropertySheetPixmapValue>(value) || qVariantCanConvert<PropertySheetIconValue>(value))
+ return true;
+ return false;
+}
+// ------------------------- QDesignerTextBuilder
+class QDesignerTextBuilder : public QTextBuilder
+{
+public:
+ QDesignerTextBuilder() {}
+
+ virtual QVariant loadText(const DomProperty *icon) const;
+
+ virtual QVariant toNativeValue(const QVariant &value) const;
+
+ virtual DomProperty *saveText(const QVariant &value) const;
+};
+
+QVariant QDesignerTextBuilder::loadText(const DomProperty *text) const
+{
+ const DomString *str = text->elementString();
+ PropertySheetStringValue strVal(str->text());
+ if (str->hasAttributeComment()) {
+ strVal.setDisambiguation(str->attributeComment());
+ }
+ if (str->hasAttributeExtraComment()) {
+ strVal.setComment(str->attributeExtraComment());
+ }
+ if (str->hasAttributeNotr()) {
+ const QString notr = str->attributeNotr();
+ const bool translatable = !(notr == QLatin1String("true") || notr == QLatin1String("yes"));
+ if (!translatable)
+ strVal.setTranslatable(translatable);
+ }
+ return qVariantFromValue(strVal);
+}
+
+QVariant QDesignerTextBuilder::toNativeValue(const QVariant &value) const
+{
+ if (qVariantCanConvert<PropertySheetStringValue>(value))
+ return qVariantFromValue(qVariantValue<PropertySheetStringValue>(value).value());
+ return value;
+}
+
+DomProperty *QDesignerTextBuilder::saveText(const QVariant &value) const
+{
+ if (!qVariantCanConvert<PropertySheetStringValue>(value) && !qVariantCanConvert<QString>(value))
+ return 0;
+
+ DomProperty *property = new DomProperty();
+ DomString *domStr = new DomString();
+
+ if (qVariantCanConvert<PropertySheetStringValue>(value)) {
+ PropertySheetStringValue str = qVariantValue<PropertySheetStringValue>(value);
+
+ domStr->setText(str.value());
+
+ const QString property_comment = str.disambiguation();
+ if (!property_comment.isEmpty())
+ domStr->setAttributeComment(property_comment);
+ const QString property_extraComment = str.comment();
+ if (!property_extraComment.isEmpty())
+ domStr->setAttributeExtraComment(property_extraComment);
+ const bool property_translatable = str.translatable();
+ if (!property_translatable)
+ domStr->setAttributeNotr(QLatin1String("true"));
+ } else {
+ domStr->setText(value.toString());
+ }
+
+ property->setElementString(domStr);
+ return property;
+}
+
+QDesignerResource::QDesignerResource(FormWindow *formWindow) :
+ QEditorFormBuilder(formWindow->core()),
+ m_formWindow(formWindow),
+ m_topLevelSpacerCount(0),
+ m_copyWidget(false),
+ m_selected(0),
+ m_resourceBuilder(new QDesignerResourceBuilder(m_formWindow->core(), m_formWindow->pixmapCache(), m_formWindow->iconCache()))
+{
+ setWorkingDirectory(formWindow->absoluteDir());
+ setResourceBuilder(m_resourceBuilder);
+ setTextBuilder(new QDesignerTextBuilder());
+
+ // ### generalise
+ const QString designerWidget = QLatin1String("QDesignerWidget");
+ const QString layoutWidget = QLatin1String("QLayoutWidget");
+ const QString widget = QLatin1String("QWidget");
+ m_internal_to_qt.insert(layoutWidget, widget);
+ m_internal_to_qt.insert(designerWidget, widget);
+ m_internal_to_qt.insert(QLatin1String("QDesignerDialog"), QLatin1String("QDialog"));
+ m_internal_to_qt.insert(QLatin1String("QDesignerMenuBar"), QLatin1String("QMenuBar"));
+ m_internal_to_qt.insert(QLatin1String("QDesignerMenu"), QLatin1String("QMenu"));
+ m_internal_to_qt.insert(QLatin1String("QDesignerDockWidget"), QLatin1String("QDockWidget"));
+ m_internal_to_qt.insert(QLatin1String("QDesignerQ3WidgetStack"), QLatin1String("Q3WidgetStack"));
+
+ // invert
+ QHash<QString, QString>::const_iterator cend = m_internal_to_qt.constEnd();
+ for (QHash<QString, QString>::const_iterator it = m_internal_to_qt.constBegin();it != cend; ++it ) {
+ if (it.value() != designerWidget && it.value() != layoutWidget)
+ m_qt_to_internal.insert(it.value(), it.key());
+
+ }
+}
+
+QDesignerResource::~QDesignerResource()
+{
+}
+
+static inline QString messageBoxTitle()
+{
+ return QApplication::translate("Designer", "Qt Designer");
+}
+
+void QDesignerResource::save(QIODevice *dev, QWidget *widget)
+{
+ m_topLevelSpacerCount = 0;
+
+ QAbstractFormBuilder::save(dev, widget);
+
+ if (QSimpleResource::warningsEnabled() && m_topLevelSpacerCount != 0) {
+ const QString message = QApplication::translate("Designer", "This file contains top level spacers.<br>"
+ "They have <b>NOT</b> been saved into the form.");
+ const QString infoMessage = QApplication::translate("Designer", "Perhaps you forgot to create a layout?");
+
+ core()->dialogGui()->message(widget->window(), QDesignerDialogGuiInterface::TopLevelSpacerMessage,
+ QMessageBox::Warning, messageBoxTitle(), message, infoMessage,
+ QMessageBox::Ok);
+ }
+}
+
+void QDesignerResource::saveDom(DomUI *ui, QWidget *widget)
+{
+ QAbstractFormBuilder::saveDom(ui, widget);
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget);
+ Q_ASSERT(sheet != 0);
+
+ const QVariant classVar = sheet->property(sheet->indexOf(QLatin1String("objectName")));
+ QString classStr;
+ if (classVar.canConvert(QVariant::String))
+ classStr = classVar.toString();
+ else
+ classStr = qVariantValue<PropertySheetStringValue>(classVar).value();
+ ui->setElementClass(classStr);
+
+ for (int index = 0; index < m_formWindow->toolCount(); ++index) {
+ QDesignerFormWindowToolInterface *tool = m_formWindow->tool(index);
+ Q_ASSERT(tool != 0);
+ tool->saveToDom(ui, widget);
+ }
+
+ const QString author = m_formWindow->author();
+ if (!author.isEmpty()) {
+ ui->setElementAuthor(author);
+ }
+
+ const QString comment = m_formWindow->comment();
+ if (!comment.isEmpty()) {
+ ui->setElementComment(comment);
+ }
+
+ const QString exportMacro = m_formWindow->exportMacro();
+ if (!exportMacro.isEmpty()) {
+ ui->setElementExportMacro(exportMacro);
+ }
+
+ const QVariantMap designerFormData = m_formWindow->formData();
+ if (!designerFormData.empty()) {
+ DomPropertyList domPropertyList;
+ const QVariantMap::const_iterator cend = designerFormData.constEnd();
+ for (QVariantMap::const_iterator it = designerFormData.constBegin(); it != cend; ++it) {
+ if (DomProperty *prop = variantToDomProperty(this, widget->metaObject(), it.key(), it.value()))
+ domPropertyList += prop;
+ }
+ if (!domPropertyList.empty()) {
+ DomDesignerData* domDesignerFormData = new DomDesignerData;
+ domDesignerFormData->setElementProperty(domPropertyList);
+ ui->setElementDesignerdata(domDesignerFormData);
+ }
+ }
+
+ if (!m_formWindow->includeHints().isEmpty()) {
+ const QString local = QLatin1String("local");
+ const QString global = QLatin1String("global");
+ QList<DomInclude*> ui_includes;
+ foreach (QString includeHint, m_formWindow->includeHints()) {
+ if (includeHint.isEmpty())
+ continue;
+ DomInclude *incl = new DomInclude;
+ const QString location = includeHint.at(0) == QLatin1Char('<') ? global : local;
+ includeHint.remove(QLatin1Char('"'));
+ includeHint.remove(QLatin1Char('<'));
+ includeHint.remove(QLatin1Char('>'));
+ incl->setAttributeLocation(location);
+ incl->setText(includeHint);
+ ui_includes.append(incl);
+ }
+
+ DomIncludes *includes = new DomIncludes;
+ includes->setElementInclude(ui_includes);
+ ui->setElementIncludes(includes);
+ }
+
+ int defaultMargin = INT_MIN, defaultSpacing = INT_MIN;
+ m_formWindow->layoutDefault(&defaultMargin, &defaultSpacing);
+
+ if (defaultMargin != INT_MIN || defaultSpacing != INT_MIN) {
+ DomLayoutDefault *def = new DomLayoutDefault;
+ if (defaultMargin != INT_MIN)
+ def->setAttributeMargin(defaultMargin);
+ if (defaultSpacing != INT_MIN)
+ def->setAttributeSpacing(defaultSpacing);
+ ui->setElementLayoutDefault(def);
+ }
+
+ QString marginFunction, spacingFunction;
+ m_formWindow->layoutFunction(&marginFunction, &spacingFunction);
+ if (!marginFunction.isEmpty() || !spacingFunction.isEmpty()) {
+ DomLayoutFunction *def = new DomLayoutFunction;
+
+ if (!marginFunction.isEmpty())
+ def->setAttributeMargin(marginFunction);
+ if (!spacingFunction.isEmpty())
+ def->setAttributeSpacing(spacingFunction);
+ ui->setElementLayoutFunction(def);
+ }
+
+ QString pixFunction = m_formWindow->pixmapFunction();
+ if (!pixFunction.isEmpty()) {
+ ui->setElementPixmapFunction(pixFunction);
+ }
+
+ if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(core()->extensionManager(), core()))
+ extra->saveUiExtraInfo(ui);
+
+ if (MetaDataBase *metaDataBase = qobject_cast<MetaDataBase *>(core()->metaDataBase())) {
+ const MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(m_formWindow->mainContainer());
+ const QStringList fakeSlots = item->fakeSlots();
+ const QStringList fakeSignals =item->fakeSignals();
+ if (!fakeSlots.empty() || !fakeSignals.empty()) {
+ DomSlots *domSlots = new DomSlots();
+ domSlots->setElementSlot(fakeSlots);
+ domSlots->setElementSignal(fakeSignals);
+ ui->setElementSlots(domSlots);
+ }
+ }
+}
+
+namespace {
+ enum LoadPreCheck { LoadPreCheckFailed, LoadPreCheckVersion3, LoadPreCheckVersionMismatch, LoadPreCheckOk };
+ // Pair of major, minor
+ typedef QPair<int, int> UiVersion;
+}
+
+static UiVersion uiVersion(const QString &attr)
+{
+ const QStringList versions = attr.split(QLatin1Char('.'));
+ if (versions.empty())
+ return UiVersion(-1, -1);
+
+ bool ok = false;
+ UiVersion rc(versions.at(0).toInt(&ok), 0);
+
+ if (!ok)
+ return UiVersion(-1, -1);
+
+ if (versions.size() > 1) {
+ const int minorVersion = versions.at(1).toInt(&ok);
+ if (ok)
+ rc.second = minorVersion;
+ }
+ return rc;
+}
+
+// Read version and language attributes of an <UI> element.
+static bool readUiAttributes(QIODevice *dev, QString *errorMessage,
+ QString *version,
+ QString *language)
+{
+ const QString uiElement = QLatin1String("ui");
+ const QString versionAttribute = QLatin1String("version");
+ const QString languageAttribute = QLatin1String("language");
+ QXmlStreamReader reader(dev);
+ // Read up to first element
+ while (!reader.atEnd()) {
+ if (reader.readNext() == QXmlStreamReader::StartElement) {
+ const QStringRef tag = reader.name();
+ if (reader.name().compare(uiElement, Qt::CaseInsensitive) == 0) {
+ const QXmlStreamAttributes attributes = reader.attributes();
+ if (attributes.hasAttribute(versionAttribute))
+ *version = attributes.value(versionAttribute).toString();
+ if (attributes.hasAttribute(languageAttribute))
+ *language = attributes.value(languageAttribute).toString();
+ return true;
+ } else {
+ *errorMessage = QCoreApplication::translate("Designer", "Invalid ui file: The root element <ui> is missing.");
+ return false;
+
+ }
+ }
+ }
+ *errorMessage = QCoreApplication::translate("Designer", "An error has occurred while reading the ui file at line %1, column %2: %3")
+ .arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString());
+ return false;
+}
+
+// While loading a file, check language, version and extra extension
+static LoadPreCheck loadPrecheck(QDesignerFormEditorInterface *core,
+ QIODevice *dev,
+ QString *errorMessage, QString *versionString)
+{
+ QString language;
+ // Read attributes of <ui> and rewind
+ if (!readUiAttributes(dev, errorMessage, versionString, &language)) {
+ // XML error: Mimick the behaviour occurring if an XML error is
+ // detected later on, report to warning log and have embedding
+ // application display a dialog.
+ designerWarning(*errorMessage);
+ errorMessage->clear();
+ return LoadPreCheckFailed;
+ }
+ dev->seek(0);
+
+ // Check language unless extension present (Jambi)
+ if (!language.isEmpty() && !qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core)) {
+ if (language.toLower() != QLatin1String("c++")) {
+ // Jambi?!
+ *errorMessage = QApplication::translate("Designer", "This file cannot be read because it was created using %1.").arg(language);
+ return LoadPreCheckFailed;
+ }
+ }
+
+ // Version
+ if (!versionString->isEmpty()) {
+ const UiVersion version = uiVersion(*versionString);
+ switch (version.first) {
+ case 3:
+ return LoadPreCheckVersion3;
+ case 4:
+ break;
+ default:
+ *errorMessage = QApplication::translate("Designer", "This file was created using Designer from Qt-%1 and cannot be read.").arg(*versionString);
+ return LoadPreCheckVersionMismatch;
+ }
+ }
+ return LoadPreCheckOk;
+}
+
+QWidget *QDesignerResource::load(QIODevice *dev, QWidget *parentWidget)
+{
+ // Run loadPreCheck for version and language
+ QString errorMessage;
+ QString version;
+ switch (loadPrecheck(core(), dev, &errorMessage, &version)) {
+ case LoadPreCheckFailed:
+ case LoadPreCheckVersionMismatch:
+ if (!errorMessage.isEmpty())
+ core()->dialogGui()->message(parentWidget->window(), QDesignerDialogGuiInterface::FormLoadFailureMessage,
+ QMessageBox::Warning, messageBoxTitle(), errorMessage, QMessageBox::Ok);
+ return 0;
+ case LoadPreCheckVersion3: {
+ QWidget *w = 0;
+ QByteArray ba;
+ if (runUIC( m_formWindow->fileName(), UIC_ConvertV3, ba, errorMessage)) {
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::ReadOnly);
+ w = load(&buffer, parentWidget);
+ if (w) {
+ // Force the form to pop up a save file dialog
+ m_formWindow->setFileName(QString());
+ } else {
+ errorMessage = QApplication::translate("Designer", "The converted file could not be read.");
+ }
+ }
+ if (w) {
+ const QString message = QApplication::translate("Designer",
+ "This file was created using Designer from Qt-%1 and"
+ " will be converted to a new form by Qt Designer.").arg(version);
+ const QString infoMessage = QApplication::translate("Designer",
+ "The old form has not been touched, but you will have to save the form"
+ " under a new name.");
+
+ core()->dialogGui()->message(parentWidget->window(),
+ QDesignerDialogGuiInterface::UiVersionMismatchMessage,
+ QMessageBox::Information, messageBoxTitle(), message, infoMessage,
+ QMessageBox::Ok);
+ return w;
+ }
+
+ const QString message = QApplication::translate("Designer",
+ "This file was created using Designer from Qt-%1 and "
+ "could not be read:\n%2").arg(version).arg(errorMessage);
+ const QString infoMessage = QApplication::translate("Designer",
+ "Please run it through <b>uic3&nbsp;-convert</b> to convert "
+ "it to Qt-4's ui format.");
+ core()->dialogGui()->message(parentWidget->window(), QDesignerDialogGuiInterface::FormLoadFailureMessage,
+ QMessageBox::Warning, messageBoxTitle(), message, infoMessage,
+ QMessageBox::Ok);
+ return 0;
+ }
+
+ case LoadPreCheckOk:
+ break;
+ }
+ return QEditorFormBuilder::load(dev, parentWidget);
+}
+
+bool QDesignerResource::saveRelative() const
+{
+ return m_resourceBuilder->isSaveRelative();
+}
+
+void QDesignerResource::setSaveRelative(bool relative)
+{
+ m_resourceBuilder->setSaveRelative(relative);
+}
+
+static bool addFakeMethods(const DomSlots *domSlots, QStringList &fakeSlots, QStringList &fakeSignals)
+{
+ if (!domSlots)
+ return false;
+
+ bool rc = false;
+ foreach (const QString &fakeSlot, domSlots->elementSlot())
+ if (fakeSlots.indexOf(fakeSlot) == -1) {
+ fakeSlots += fakeSlot;
+ rc = true;
+ }
+
+ foreach (const QString &fakeSignal, domSlots->elementSignal())
+ if (fakeSignals.indexOf(fakeSignal) == -1) {
+ fakeSignals += fakeSignal;
+ rc = true;
+ }
+ return rc;
+}
+
+QWidget *QDesignerResource::create(DomUI *ui, QWidget *parentWidget)
+{
+ // Load extra info extension. This is used by Jambi for preventing
+ // C++ ui files from being loaded
+ if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(core()->extensionManager(), core())) {
+ if (!extra->loadUiExtraInfo(ui)) {
+ const QString errorMessage = QApplication::translate("Designer", "This file cannot be read because the extra info extension failed to load.");
+ core()->dialogGui()->message(parentWidget->window(), QDesignerDialogGuiInterface::FormLoadFailureMessage,
+ QMessageBox::Warning, messageBoxTitle(), errorMessage, QMessageBox::Ok);
+ return 0;
+ }
+ }
+
+ qdesigner_internal::WidgetFactory *factory = qobject_cast<qdesigner_internal::WidgetFactory*>(core()->widgetFactory());
+ Q_ASSERT(factory != 0);
+
+ QDesignerFormWindowInterface *previousFormWindow = factory->currentFormWindow(m_formWindow);
+
+ m_isMainWidget = true;
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ QWidget *mainWidget = QAbstractFormBuilder::create(ui, parentWidget);
+
+ if (mainWidget && m_formWindow) {
+ m_formWindow->setAuthor(ui->elementAuthor());
+ m_formWindow->setComment(ui->elementComment());
+ m_formWindow->setExportMacro(ui->elementExportMacro());
+
+ // Designer data
+ QVariantMap designerFormData;
+ if (ui->hasElementDesignerdata()) {
+ const DomPropertyList domPropertyList = ui->elementDesignerdata()->elementProperty();
+ const DomPropertyList::const_iterator cend = domPropertyList.constEnd();
+ for (DomPropertyList::const_iterator it = domPropertyList.constBegin(); it != cend; ++it) {
+ const QVariant vprop = domPropertyToVariant(this, mainWidget->metaObject(), *it);
+ if (vprop.type() != QVariant::Invalid)
+ designerFormData.insert((*it)->attributeName(), vprop);
+ }
+ }
+ m_formWindow->setFormData(designerFormData);
+
+ m_formWindow->setPixmapFunction(ui->elementPixmapFunction());
+
+ if (DomLayoutDefault *def = ui->elementLayoutDefault()) {
+ m_formWindow->setLayoutDefault(def->attributeMargin(), def->attributeSpacing());
+ }
+
+ if (DomLayoutFunction *fun = ui->elementLayoutFunction()) {
+ m_formWindow->setLayoutFunction(fun->attributeMargin(), fun->attributeSpacing());
+ }
+
+ if (DomIncludes *includes = ui->elementIncludes()) {
+ const QString global = QLatin1String("global");
+ QStringList includeHints;
+ foreach (DomInclude *incl, includes->elementInclude()) {
+ QString text = incl->text();
+
+ if (text.isEmpty())
+ continue;
+
+ if (incl->hasAttributeLocation() && incl->attributeLocation() == global ) {
+ text = text.prepend(QLatin1Char('<')).append(QLatin1Char('>'));
+ } else {
+ text = text.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
+ }
+
+ includeHints.append(text);
+ }
+
+ m_formWindow->setIncludeHints(includeHints);
+ }
+
+ // Register all button groups the form builder adds as children of the main container for them to be found
+ // in the signal slot editor
+ const QObjectList mchildren = mainWidget->children();
+ if (!mchildren.empty()) {
+ QDesignerMetaDataBaseInterface *mdb = core()->metaDataBase();
+ const QObjectList::const_iterator cend = mchildren.constEnd();
+ for (QObjectList::const_iterator it = mchildren.constBegin(); it != cend; ++it)
+ if (QButtonGroup *bg = qobject_cast<QButtonGroup*>(*it))
+ mdb->add(bg);
+ }
+ // Load tools
+ for (int index = 0; index < m_formWindow->toolCount(); ++index) {
+ QDesignerFormWindowToolInterface *tool = m_formWindow->tool(index);
+ Q_ASSERT(tool != 0);
+ tool->loadFromDom(ui, mainWidget);
+ }
+ }
+
+ factory->currentFormWindow(previousFormWindow);
+
+ if (const DomSlots *domSlots = ui->elementSlots()) {
+ if (MetaDataBase *metaDataBase = qobject_cast<MetaDataBase *>(core()->metaDataBase())) {
+ QStringList fakeSlots;
+ QStringList fakeSignals;
+ if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) {
+ MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(mainWidget);
+ item->setFakeSlots(fakeSlots);
+ item->setFakeSignals(fakeSignals);
+ }
+ }
+ }
+ if (mainWidget) {
+ // Initialize the mainwindow geometry. Has it been explicitly specified?
+ bool hasExplicitGeometry = false;
+ const QList<DomProperty *> properties = ui->elementWidget()->elementProperty();
+ if (!properties.empty()) {
+ const QString geometry = QLatin1String("geometry");
+ foreach (const DomProperty *p, properties)
+ if (p->attributeName() == geometry) {
+ hasExplicitGeometry = true;
+ break;
+ }
+ }
+ if (hasExplicitGeometry) {
+ // Geometry was specified explicitly: Verify that smartMinSize is respected
+ // (changed fonts, label wrapping policies, etc). This does not happen automatically in docked mode.
+ const QSize size = mainWidget->size();
+ const QSize minSize = size.expandedTo(qSmartMinSize(mainWidget));
+ if (minSize != size)
+ mainWidget->resize(minSize);
+ } else {
+ // No explicit Geometry: perform an adjustSize() to resize the form correctly before embedding it into a container
+ // (which might otherwise squeeze the form)
+ mainWidget->adjustSize();
+ }
+ // Some integration wizards create forms with main containers
+ // based on derived classes of QWidget and load them into Designer
+ // without the plugin existing. This will trigger the auto-promotion
+ // mechanism of Designer, which will set container=false for
+ // QWidgets. For the main container, force container=true and warn.
+ const QDesignerWidgetDataBaseInterface *wdb = core()->widgetDataBase();
+ const int wdbIndex = wdb->indexOfObject(mainWidget);
+ if (wdbIndex != -1) {
+ QDesignerWidgetDataBaseItemInterface *item = wdb->item(wdbIndex);
+ // Promoted main container that is not of container type
+ if (item->isPromoted() && !item->isContainer()) {
+ item->setContainer(true);
+ qWarning("** WARNING The form's main container is an unknown custom widget '%s'."
+ " Defaulting to a promoted instance of '%s', assuming container.",
+ item->name().toUtf8().constData(), item->extends().toUtf8().constData());
+ }
+ }
+ }
+ return mainWidget;
+}
+
+QWidget *QDesignerResource::create(DomWidget *ui_widget, QWidget *parentWidget)
+{
+ const QString className = ui_widget->attributeClass();
+ if (!m_isMainWidget && className == QLatin1String("QWidget") && ui_widget->elementLayout().size() &&
+ !ui_widget->hasAttributeNative()) {
+ // ### check if elementLayout.size() == 1
+
+ QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), parentWidget);
+
+ if (container == 0) {
+ // generate a QLayoutWidget iff the parent is not an QDesignerContainerExtension.
+ ui_widget->setAttributeClass(QLatin1String("QLayoutWidget"));
+ }
+ }
+
+ // save the actions
+ const QList<DomActionRef*> actionRefs = ui_widget->elementAddAction();
+ ui_widget->setElementAddAction(QList<DomActionRef*>());
+
+ QWidget *w = QAbstractFormBuilder::create(ui_widget, parentWidget);
+
+ // restore the actions
+ ui_widget->setElementAddAction(actionRefs);
+
+ if (w == 0)
+ return 0;
+
+ // ### generalize using the extension manager
+ QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(w);
+ QDesignerMenuBar *menuBar = qobject_cast<QDesignerMenuBar*>(w);
+
+ if (menu) {
+ menu->interactive(false);
+ menu->hide();
+ } else if (menuBar) {
+ menuBar->interactive(false);
+ }
+
+ foreach (DomActionRef *ui_action_ref, actionRefs) {
+ const QString name = ui_action_ref->attributeName();
+ if (name == QLatin1String("separator")) {
+ QAction *sep = new QAction(w);
+ sep->setSeparator(true);
+ w->addAction(sep);
+ addMenuAction(sep);
+ } else if (QAction *a = m_actions.value(name)) {
+ w->addAction(a);
+ } else if (QActionGroup *g = m_actionGroups.value(name)) {
+ w->addActions(g->actions());
+ } else if (QMenu *menu = qFindChild<QMenu*>(w, name)) {
+ w->addAction(menu->menuAction());
+ addMenuAction(menu->menuAction());
+ }
+ }
+
+ if (menu) {
+ menu->interactive(true);
+ menu->adjustSpecialActions();
+ } else if (menuBar) {
+ menuBar->interactive(true);
+ menuBar->adjustSpecialActions();
+ }
+
+ ui_widget->setAttributeClass(className); // fix the class name
+ applyExtensionDataFromDOM(this, core(), ui_widget, w, true);
+
+ // store user-defined scripts
+ if (MetaDataBase *metaDataBase = qobject_cast<MetaDataBase *>(core()->metaDataBase())) {
+ const QString designerSource = QLatin1String("designer");
+ const DomScripts domScripts = ui_widget->elementScript();
+ if (!domScripts.empty()) {
+ foreach (const DomScript *script, domScripts) {
+ if (script->hasAttributeSource() && script->attributeSource() == designerSource) {
+ metaDataBase->metaDataBaseItem(w)->setScript(script->text());
+ }
+ }
+ }
+ }
+
+ return w;
+}
+
+QLayout *QDesignerResource::create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget)
+{
+ QLayout *l = QAbstractFormBuilder::create(ui_layout, layout, parentWidget);
+
+ if (QGridLayout *gridLayout = qobject_cast<QGridLayout*>(l)) {
+ QLayoutSupport::createEmptyCells(gridLayout);
+ } else {
+ if (QFormLayout *formLayout = qobject_cast<QFormLayout*>(l))
+ QLayoutSupport::createEmptyCells(formLayout);
+ }
+ // While the actual values are applied by the form builder, we still need
+ // to mark them as 'changed'.
+ LayoutPropertySheet::markChangedStretchProperties(core(), l, ui_layout);
+ return l;
+}
+
+QLayoutItem *QDesignerResource::create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget)
+{
+ if (ui_layoutItem->kind() == DomLayoutItem::Spacer) {
+ const DomSpacer *domSpacer = ui_layoutItem->elementSpacer();
+ const QHash<QString, DomProperty*> properties = propertyMap(domSpacer->elementProperty());
+ Spacer *spacer = static_cast<Spacer*>(core()->widgetFactory()->createWidget(QLatin1String("Spacer"), parentWidget));
+ if (domSpacer->hasAttributeName())
+ changeObjectName(spacer, domSpacer->attributeName());
+ core()->metaDataBase()->add(spacer);
+
+ spacer->setInteractiveMode(false);
+ applyProperties(spacer, ui_layoutItem->elementSpacer()->elementProperty());
+ spacer->setInteractiveMode(true);
+
+ if (m_formWindow) {
+ m_formWindow->manageWidget(spacer);
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), spacer))
+ sheet->setChanged(sheet->indexOf(QLatin1String("orientation")), true);
+ }
+
+ return new QWidgetItem(spacer);
+ } else if (ui_layoutItem->kind() == DomLayoutItem::Layout && parentWidget) {
+ DomLayout *ui_layout = ui_layoutItem->elementLayout();
+ QLayoutWidget *layoutWidget = new QLayoutWidget(m_formWindow, parentWidget);
+ core()->metaDataBase()->add(layoutWidget);
+ if (m_formWindow)
+ m_formWindow->manageWidget(layoutWidget);
+ (void) create(ui_layout, 0, layoutWidget);
+ return new QWidgetItem(layoutWidget);
+ }
+ return QAbstractFormBuilder::create(ui_layoutItem, layout, parentWidget);
+}
+
+void QDesignerResource::changeObjectName(QObject *o, QString objName)
+{
+ m_formWindow->unify(o, objName, true);
+ o->setObjectName(objName);
+
+}
+
+/* If the property is a enum or flag value, retrieve
+ * the existing enum/flag via property sheet and use it to convert */
+
+static bool readDomEnumerationValue(const DomProperty *p,
+ const QDesignerPropertySheetExtension* sheet, int index,
+ QVariant &v)
+{
+ switch (p->kind()) {
+ case DomProperty::Set: {
+ const QVariant sheetValue = sheet->property(index);
+ if (qVariantCanConvert<PropertySheetFlagValue>(sheetValue)) {
+ const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue);
+ bool ok = false;
+ v = f.metaFlags.parseFlags(p->elementSet(), &ok);
+ if (!ok)
+ designerWarning(f.metaFlags.messageParseFailed(p->elementSet()));
+ return true;
+ }
+ }
+ break;
+ case DomProperty::Enum: {
+ const QVariant sheetValue = sheet->property(index);
+ if (qVariantCanConvert<PropertySheetEnumValue>(sheetValue)) {
+ const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue);
+ bool ok = false;
+ v = e.metaEnum.parseEnum(p->elementEnum(), &ok);
+ if (!ok)
+ designerWarning(e.metaEnum.messageParseFailed(p->elementEnum()));
+ return true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void QDesignerResource::applyProperties(QObject *o, const QList<DomProperty*> &properties)
+{
+ if (properties.empty())
+ return;
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), o);
+ if (!sheet)
+ return;
+
+ QFormBuilderExtra *formBuilderExtra = QFormBuilderExtra::instance(this);
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), o);
+ const bool dynamicPropertiesAllowed = dynamicSheet && dynamicSheet->dynamicPropertiesAllowed();
+
+ const QString objectNameProperty = QLatin1String("objectName");
+ const DomPropertyList::const_iterator cend = properties.constEnd();
+ for (DomPropertyList::const_iterator it = properties.constBegin(); it != cend; ++it) {
+ const DomProperty *p = *it;
+ const QString propertyName = p->attributeName();
+ const int index = sheet->indexOf(propertyName);
+ QVariant v;
+ if (!readDomEnumerationValue(p, sheet, index, v))
+ v = toVariant(o->metaObject(), *it);
+
+ if (p->kind() == DomProperty::String) {
+ if (index != -1 && sheet->property(index).userType() == qMetaTypeId<PropertySheetKeySequenceValue>()) {
+ const DomString *key = p->elementString();
+ PropertySheetKeySequenceValue keyVal(QKeySequence(key->text()));
+ if (key->hasAttributeComment())
+ keyVal.setDisambiguation(key->attributeComment());
+ if (key->hasAttributeExtraComment())
+ keyVal.setComment(key->attributeExtraComment());
+ if (key->hasAttributeNotr()) {
+ const QString notr = key->attributeNotr();
+ const bool translatable = !(notr == QLatin1String("true") || notr == QLatin1String("yes"));
+ if (!translatable)
+ keyVal.setTranslatable(translatable);
+ }
+ v = qVariantFromValue(keyVal);
+ } else {
+ const DomString *str = p->elementString();
+ PropertySheetStringValue strVal(v.toString());
+ if (str->hasAttributeComment())
+ strVal.setDisambiguation(str->attributeComment());
+ if (str->hasAttributeExtraComment())
+ strVal.setComment(str->attributeExtraComment());
+ if (str->hasAttributeNotr()) {
+ const QString notr = str->attributeNotr();
+ const bool translatable = !(notr == QLatin1String("true") || notr == QLatin1String("yes"));
+ if (!translatable)
+ strVal.setTranslatable(translatable);
+ }
+ v = qVariantFromValue(strVal);
+ }
+ }
+
+ formBuilderExtra->applyPropertyInternally(o, propertyName, v);
+ if (index != -1) {
+ sheet->setProperty(index, v);
+ sheet->setChanged(index, true);
+ } else if (dynamicPropertiesAllowed) {
+ QVariant defaultValue = QVariant(v.type());
+ bool isDefault = (v == defaultValue);
+ if (qVariantCanConvert<PropertySheetIconValue>(v)) {
+ defaultValue = QVariant(QVariant::Icon);
+ isDefault = (qVariantValue<PropertySheetIconValue>(v) == PropertySheetIconValue());
+ } else if (qVariantCanConvert<PropertySheetPixmapValue>(v)) {
+ defaultValue = QVariant(QVariant::Pixmap);
+ isDefault = (qVariantValue<PropertySheetPixmapValue>(v) == PropertySheetPixmapValue());
+ } else if (qVariantCanConvert<PropertySheetStringValue>(v)) {
+ defaultValue = QVariant(QVariant::String);
+ isDefault = (qVariantValue<PropertySheetStringValue>(v) == PropertySheetStringValue());
+ } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(v)) {
+ defaultValue = QVariant(QVariant::KeySequence);
+ isDefault = (qVariantValue<PropertySheetKeySequenceValue>(v) == PropertySheetKeySequenceValue());
+ }
+ if (defaultValue.type() != QVariant::UserType) {
+ const int idx = dynamicSheet->addDynamicProperty(p->attributeName(), defaultValue);
+ if (idx != -1) {
+ sheet->setProperty(idx, v);
+ sheet->setChanged(idx, !isDefault);
+ }
+ }
+ }
+
+ if (propertyName == objectNameProperty)
+ changeObjectName(o, o->objectName());
+ }
+}
+
+QWidget *QDesignerResource::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &_name)
+{
+ QString name = _name;
+ QString className = widgetName;
+ if (m_isMainWidget)
+ m_isMainWidget = false;
+
+ QWidget *w = core()->widgetFactory()->createWidget(className, parentWidget);
+ if (!w)
+ return 0;
+
+ if (name.isEmpty()) {
+ QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase();
+ if (QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfObject(w)))
+ name = qtify(item->name());
+ }
+
+ changeObjectName(w, name);
+
+ QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), parentWidget);
+ if (!qobject_cast<QMenu*>(w) && (!parentWidget || !container)) {
+ m_formWindow->manageWidget(w);
+ if (parentWidget) {
+ QList<QWidget *> list = qVariantValue<QWidgetList>(parentWidget->property("_q_widgetOrder"));
+ list.append(w);
+ parentWidget->setProperty("_q_widgetOrder", qVariantFromValue(list));
+ QList<QWidget *> zOrder = qVariantValue<QWidgetList>(parentWidget->property("_q_zOrder"));
+ zOrder.append(w);
+ parentWidget->setProperty("_q_zOrder", qVariantFromValue(list));
+ }
+ } else {
+ core()->metaDataBase()->add(w);
+ }
+
+ w->setWindowFlags(w->windowFlags() & ~Qt::Window);
+ // Make sure it is non-modal (for example, KDialog calls setModal(true) in the constructor).
+ w->setWindowModality(Qt::NonModal);
+
+ return w;
+}
+
+QLayout *QDesignerResource::createLayout(const QString &layoutName, QObject *parent, const QString &name)
+{
+ QWidget *layoutBase = 0;
+ QLayout *layout = qobject_cast<QLayout*>(parent);
+
+ if (parent->isWidgetType())
+ layoutBase = static_cast<QWidget*>(parent);
+ else {
+ Q_ASSERT( layout != 0 );
+ layoutBase = layout->parentWidget();
+ }
+
+ LayoutInfo::Type layoutType = LayoutInfo::layoutType(layoutName);
+ if (layoutType == LayoutInfo::NoLayout) {
+ designerWarning(QCoreApplication::translate("QDesignerResource", "The layout type '%1' is not supported, defaulting to grid.").arg(layoutName));
+ layoutType = LayoutInfo::Grid;
+ }
+ QLayout *lay = core()->widgetFactory()->createLayout(layoutBase, layout, layoutType);
+ if (lay != 0)
+ changeObjectName(lay, name);
+
+ return lay;
+}
+
+// save
+DomWidget *QDesignerResource::createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive)
+{
+ QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(widget);
+ if (!item)
+ return 0;
+
+ if (qobject_cast<Spacer*>(widget) && m_copyWidget == false) {
+ ++m_topLevelSpacerCount;
+ return 0;
+ }
+
+ const QDesignerWidgetDataBaseInterface *wdb = core()->widgetDataBase();
+ QDesignerWidgetDataBaseItemInterface *widgetInfo = 0;
+ const int widgetInfoIndex = wdb->indexOfObject(widget, false);
+ if (widgetInfoIndex != -1) {
+ widgetInfo = wdb->item(widgetInfoIndex);
+ // Recursively add all dependent custom widgets
+ QDesignerWidgetDataBaseItemInterface *customInfo = widgetInfo;
+ while (customInfo && customInfo->isCustom()) {
+ m_usedCustomWidgets.insert(customInfo, true);
+ const QString extends = customInfo->extends();
+ if (extends == customInfo->name()) {
+ break; // There are faulty files around that have name==extends
+ } else {
+ const int extendsIndex = wdb->indexOfClassName(customInfo->extends());
+ customInfo = extendsIndex != -1 ? wdb->item(extendsIndex) : static_cast<QDesignerWidgetDataBaseItemInterface *>(0);
+ }
+ }
+ }
+
+ DomWidget *w = 0;
+
+ if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(widget))
+ w = saveWidget(tabWidget, ui_parentWidget);
+ else if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget))
+ w = saveWidget(stackedWidget, ui_parentWidget);
+ else if (QToolBox *toolBox = qobject_cast<QToolBox*>(widget))
+ w = saveWidget(toolBox, ui_parentWidget);
+ else if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget))
+ w = saveWidget(toolBar, ui_parentWidget);
+ else if (QDesignerDockWidget *dockWidget = qobject_cast<QDesignerDockWidget*>(widget))
+ w = saveWidget(dockWidget, ui_parentWidget);
+ else if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget))
+ w = saveWidget(widget, container, ui_parentWidget);
+ else if (QTreeView *treeView = qobject_cast<QTreeView*>(widget))
+ w = saveWidget(treeView, ui_parentWidget);
+ else if (QTableView *tableView = qobject_cast<QTableView*>(widget))
+ w = saveWidget(tableView, ui_parentWidget);
+ else if (QWizardPage *wizardPage = qobject_cast<QWizardPage*>(widget))
+ w = saveWidget(wizardPage, ui_parentWidget);
+ else
+ w = QAbstractFormBuilder::createDom(widget, ui_parentWidget, recursive);
+
+ Q_ASSERT( w != 0 );
+
+ if (!qobject_cast<QLayoutWidget*>(widget) && w->attributeClass() == QLatin1String("QWidget")) {
+ w->setAttributeNative(true);
+ }
+
+ const QString className = w->attributeClass();
+ if (m_internal_to_qt.contains(className))
+ w->setAttributeClass(m_internal_to_qt.value(className));
+
+ w->setAttributeName(widget->objectName());
+
+ if (isPromoted( core(), widget)) { // is promoted?
+ Q_ASSERT(widgetInfo != 0);
+
+ w->setAttributeName(widget->objectName());
+ w->setAttributeClass(widgetInfo->name());
+
+ QList<DomProperty*> prop_list = w->elementProperty();
+ foreach (DomProperty *prop, prop_list) {
+ if (prop->attributeName() == QLatin1String("geometry")) {
+ if (DomRect *rect = prop->elementRect()) {
+ rect->setElementX(widget->x());
+ rect->setElementY(widget->y());
+ }
+ break;
+ }
+ }
+ } else if (widgetInfo != 0 && m_usedCustomWidgets.contains(widgetInfo)) {
+ if (widgetInfo->name() != w->attributeClass())
+ w->setAttributeClass(widgetInfo->name());
+ }
+ addExtensionDataToDOM(this, core(), w, widget);
+
+ addUserDefinedScripts(widget, w);
+ return w;
+}
+
+DomLayout *QDesignerResource::createDom(QLayout *layout, DomLayout *ui_parentLayout, DomWidget *ui_parentWidget)
+{
+ QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(layout);
+
+ if (item == 0) {
+ layout = qFindChild<QLayout*>(layout);
+ // refresh the meta database item
+ item = core()->metaDataBase()->item(layout);
+ }
+
+ if (item == 0) {
+ // nothing to do.
+ return 0;
+ }
+
+ if (qobject_cast<QSplitter*>(layout->parentWidget()) != 0) {
+ // nothing to do.
+ return 0;
+ }
+
+ m_chain.push(layout);
+
+ DomLayout *l = QAbstractFormBuilder::createDom(layout, ui_parentLayout, ui_parentWidget);
+ Q_ASSERT(l != 0);
+ LayoutPropertySheet::stretchAttributesToDom(core(), layout, l);
+
+ m_chain.pop();
+
+ return l;
+}
+
+DomLayoutItem *QDesignerResource::createDom(QLayoutItem *item, DomLayout *ui_layout, DomWidget *ui_parentWidget)
+{
+ DomLayoutItem *ui_item = 0;
+
+ if (Spacer *s = qobject_cast<Spacer*>(item->widget())) {
+ if (!core()->metaDataBase()->item(s))
+ return 0;
+
+ DomSpacer *spacer = new DomSpacer();
+ const QString objectName = s->objectName();
+ if (!objectName.isEmpty())
+ spacer->setAttributeName(objectName);
+ const QList<DomProperty*> properties = computeProperties(item->widget());
+ // ### filter the properties
+ spacer->setElementProperty(properties);
+
+ ui_item = new DomLayoutItem();
+ ui_item->setElementSpacer(spacer);
+ m_laidout.insert(item->widget(), true);
+ } else if (QLayoutWidget *layoutWidget = qobject_cast<QLayoutWidget*>(item->widget())) {
+ // Do not save a QLayoutWidget if it is within a layout (else it is saved as "QWidget"
+ Q_ASSERT(layoutWidget->layout());
+ DomLayout *l = createDom(layoutWidget->layout(), ui_layout, ui_parentWidget);
+ ui_item = new DomLayoutItem();
+ ui_item->setElementLayout(l);
+ m_laidout.insert(item->widget(), true);
+ } else if (!item->spacerItem()) { // we use spacer as fake item in the Designer
+ ui_item = QAbstractFormBuilder::createDom(item, ui_layout, ui_parentWidget);
+ } else {
+ return 0;
+ }
+
+ if (m_chain.size() && item->widget()) {
+ if (QGridLayout *grid = qobject_cast<QGridLayout*>(m_chain.top())) {
+ const int index = Utils::indexOfWidget(grid, item->widget());
+
+ int row, column, rowspan, colspan;
+ grid->getItemPosition(index, &row, &column, &rowspan, &colspan);
+ ui_item->setAttributeRow(row);
+ ui_item->setAttributeColumn(column);
+
+ if (colspan != 1)
+ ui_item->setAttributeColSpan(colspan);
+
+ if (rowspan != 1)
+ ui_item->setAttributeRowSpan(rowspan);
+ } else {
+ if (QFormLayout *form = qobject_cast<QFormLayout*>(m_chain.top())) {
+ const int index = Utils::indexOfWidget(form, item->widget());
+ int row, column, colspan;
+ getFormLayoutItemPosition(form, index, &row, &column, 0, &colspan);
+ ui_item->setAttributeRow(row);
+ ui_item->setAttributeColumn(column);
+ if (colspan != 1)
+ ui_item->setAttributeColSpan(colspan);
+ }
+ }
+ }
+
+ return ui_item;
+}
+
+static void addFakeMethodsToWidgetDataBase(const DomCustomWidget *domCustomWidget, WidgetDataBaseItem *item)
+{
+ const DomSlots *domSlots = domCustomWidget->elementSlots();
+ if (!domSlots)
+ return;
+
+ // Merge in new slots, signals
+ QStringList fakeSlots = item->fakeSlots();
+ QStringList fakeSignals = item->fakeSignals();
+ if (addFakeMethods(domSlots, fakeSlots, fakeSignals)) {
+ item->setFakeSlots(fakeSlots);
+ item->setFakeSignals(fakeSignals);
+ }
+}
+
+void QDesignerResource::addCustomWidgetsToWidgetDatabase(DomCustomWidgetList& custom_widget_list)
+{
+ // Perform one iteration of adding the custom widgets to the database,
+ // looking up the base class and inheriting its data.
+ // Remove the succeeded custom widgets from the list.
+ // Classes whose base class could not be found are left in the list.
+ QDesignerWidgetDataBaseInterface *db = m_formWindow->core()->widgetDataBase();
+ for (int i=0; i < custom_widget_list.size(); ) {
+ bool classInserted = false;
+ DomCustomWidget *custom_widget = custom_widget_list[i];
+ const QString customClassName = custom_widget->elementClass();
+ const QString base_class = custom_widget->elementExtends();
+ QString includeFile;
+ IncludeType includeType = IncludeLocal;
+ if (const DomHeader *header = custom_widget->elementHeader()) {
+ includeFile = header->text();
+ if (header->hasAttributeLocation() && header->attributeLocation() == QLatin1String("global"))
+ includeType = IncludeGlobal;
+ }
+ const bool domIsContainer = custom_widget->elementContainer();
+ // Append a new item
+ if (base_class.isEmpty()) {
+ WidgetDataBaseItem *item = new WidgetDataBaseItem(customClassName);
+ item->setPromoted(false);
+ item->setGroup(QApplication::translate("Designer", "Custom Widgets"));
+ item->setIncludeFile(buildIncludeFile(includeFile, includeType));
+ item->setContainer(domIsContainer);
+ item->setCustom(true);
+ addFakeMethodsToWidgetDataBase(custom_widget, item);
+ db->append(item);
+ custom_widget_list.removeAt(i);
+ classInserted = true;
+ } else {
+ // Create a new entry cloned from base class. Note that this will ignore existing
+ // classes, eg, plugin custom widgets.
+ QDesignerWidgetDataBaseItemInterface *item =
+ appendDerived(db, customClassName, QApplication::translate("Designer", "Promoted Widgets"),
+ base_class,
+ buildIncludeFile(includeFile, includeType),
+ true,true);
+ // Ok, base class found.
+ if (item) {
+ // Hack to accommodate for old UI-files in which "contains" is not set properly:
+ // Apply "contains" from DOM only if true (else, eg classes from QFrame might not accept
+ // dropping child widgets on them as container=false). This also allows for
+ // QWidget-derived stacked pages.
+ if (domIsContainer)
+ item->setContainer(domIsContainer);
+
+ addFakeMethodsToWidgetDataBase(custom_widget, static_cast<WidgetDataBaseItem*>(item));
+ custom_widget_list.removeAt(i);
+ classInserted = true;
+ }
+ }
+ // Skip failed item.
+ if (!classInserted)
+ i++;
+ }
+
+}
+void QDesignerResource::createCustomWidgets(DomCustomWidgets *dom_custom_widgets)
+{
+ if (dom_custom_widgets == 0)
+ return;
+ DomCustomWidgetList custom_widget_list = dom_custom_widgets->elementCustomWidget();
+ // Attempt to insert each item derived from its base class.
+ // This should at most require two iterations in the event that the classes are out of order
+ // (derived first, max depth: promoted custom plugin = 2)
+ for (int iteration = 0; iteration < 2; iteration++) {
+ addCustomWidgetsToWidgetDatabase(custom_widget_list);
+ if (custom_widget_list.empty())
+ return;
+ }
+ // Oops, there are classes left whose base class could not be found.
+ // Default them to QWidget with warnings.
+ const QString fallBackBaseClass = QLatin1String("QWidget");
+ for (int i=0; i < custom_widget_list.size(); i++ ) {
+ DomCustomWidget *custom_widget = custom_widget_list[i];
+ const QString customClassName = custom_widget->elementClass();
+ const QString base_class = custom_widget->elementExtends();
+ qDebug() << "** WARNING The base class " << base_class << " of the custom widget class " << customClassName
+ << " could not be found. Defaulting to " << fallBackBaseClass << '.';
+ custom_widget->setElementExtends(fallBackBaseClass);
+ }
+ // One more pass.
+ addCustomWidgetsToWidgetDatabase(custom_widget_list);
+ Q_ASSERT(custom_widget_list.empty());
+}
+
+DomTabStops *QDesignerResource::saveTabStops()
+{
+ QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(m_formWindow);
+ Q_ASSERT(item);
+
+ QStringList tabStops;
+ foreach (QWidget *widget, item->tabOrder()) {
+ if (m_formWindow->mainContainer()->isAncestorOf(widget))
+ tabStops.append(widget->objectName());
+ }
+
+ if (tabStops.count()) {
+ DomTabStops *dom = new DomTabStops;
+ dom->setElementTabStop(tabStops);
+ return dom;
+ }
+
+ return 0;
+}
+
+void QDesignerResource::applyTabStops(QWidget *widget, DomTabStops *tabStops)
+{
+ if (!tabStops)
+ return;
+
+ QList<QWidget*> tabOrder;
+ foreach (QString widgetName, tabStops->elementTabStop()) {
+ if (QWidget *w = qFindChild<QWidget*>(widget, widgetName)) {
+ tabOrder.append(w);
+ }
+ }
+
+ QDesignerMetaDataBaseItemInterface *item = core()->metaDataBase()->item(m_formWindow);
+ Q_ASSERT(item);
+ item->setTabOrder(tabOrder);
+}
+
+/* Unmanaged container pages occur when someone adds a page in a custom widget
+ * constructor. They don't have a meta DB entry which causes createDom
+ * to return 0. */
+inline QString msgUnmanagedPage(QDesignerFormEditorInterface *core,
+ QWidget *container, int index, QWidget *page)
+{
+ return QCoreApplication::translate("QDesignerResource",
+"The container extension of the widget '%1' (%2) returned a widget not managed by Designer '%3' (%4) when queried for page #%5.\n"
+"Container pages should only be added by specifying them in XML returned by the domXml() method of the custom widget.").
+ arg(container->objectName(), WidgetFactory::classNameOf(core, container),
+ page->objectName(), WidgetFactory::classNameOf(core, page)).
+ arg(index);
+}
+
+DomWidget *QDesignerResource::saveWidget(QWidget *widget, QDesignerContainerExtension *container, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false);
+ QList<DomWidget*> ui_widget_list;
+
+ for (int i=0; i<container->count(); ++i) {
+ QWidget *page = container->widget(i);
+ Q_ASSERT(page);
+
+ if (DomWidget *ui_page = createDom(page, ui_widget)) {
+ ui_widget_list.append(ui_page);
+ } else {
+ if (QSimpleResource::warningsEnabled())
+ designerWarning(msgUnmanagedPage(core(), widget, i, page));
+ }
+ }
+
+ ui_widget->setElementWidget(ui_widget_list);
+
+ return ui_widget;
+}
+
+DomWidget *QDesignerResource::saveWidget(QStackedWidget *widget, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false);
+ QList<DomWidget*> ui_widget_list;
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) {
+ for (int i=0; i<container->count(); ++i) {
+ QWidget *page = container->widget(i);
+ Q_ASSERT(page);
+ if (DomWidget *ui_page = createDom(page, ui_widget)) {
+ ui_widget_list.append(ui_page);
+ } else {
+ if (QSimpleResource::warningsEnabled())
+ designerWarning(msgUnmanagedPage(core(), widget, i, page));
+ }
+ }
+ }
+
+ ui_widget->setElementWidget(ui_widget_list);
+
+ return ui_widget;
+}
+
+DomWidget *QDesignerResource::saveWidget(QToolBar *toolBar, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(toolBar, ui_parentWidget, false);
+ if (const QMainWindow *mainWindow = qobject_cast<QMainWindow*>(toolBar->parentWidget())) {
+ const bool toolBarBreak = mainWindow->toolBarBreak(toolBar);
+ const Qt::ToolBarArea area = mainWindow->toolBarArea(toolBar);
+
+ QList<DomProperty*> attributes = ui_widget->elementAttribute();
+
+ DomProperty *attr = new DomProperty();
+ attr->setAttributeName(QLatin1String("toolBarArea"));
+ attr->setElementEnum(QLatin1String(toolBarAreaMetaEnum().valueToKey(area)));
+ attributes << attr;
+
+ attr = new DomProperty();
+ attr->setAttributeName(QLatin1String("toolBarBreak"));
+ attr->setElementBool(toolBarBreak ? QLatin1String("true") : QLatin1String("false"));
+ attributes << attr;
+ ui_widget->setElementAttribute(attributes);
+ }
+
+ return ui_widget;
+}
+
+DomWidget *QDesignerResource::saveWidget(QDesignerDockWidget *dockWidget, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(dockWidget, ui_parentWidget, true);
+ if (QMainWindow *mainWindow = qobject_cast<QMainWindow*>(dockWidget->parentWidget())) {
+ const Qt::DockWidgetArea area = mainWindow->dockWidgetArea(dockWidget);
+ DomProperty *attr = new DomProperty();
+ attr->setAttributeName(QLatin1String("dockWidgetArea"));
+ attr->setElementNumber(int(area));
+ ui_widget->setElementAttribute(ui_widget->elementAttribute() << attr);
+ }
+
+ return ui_widget;
+}
+
+DomWidget *QDesignerResource::saveWidget(QTreeView *treeView, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(treeView, ui_parentWidget, true);
+
+ QDesignerPropertySheetExtension *sheet
+ = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), treeView);
+ ItemViewPropertySheet *itemViewSheet = static_cast<ItemViewPropertySheet*>(sheet);
+
+ if (itemViewSheet) {
+ QHash<QString,QString> nameMap = itemViewSheet->propertyNameMap();
+ foreach (const QString &fakeName, nameMap.keys()) {
+ int index = itemViewSheet->indexOf(fakeName);
+ if (sheet->isChanged(index)) {
+ DomProperty *domAttr = createProperty(treeView->header(), nameMap.value(fakeName),
+ itemViewSheet->property(index));
+ domAttr->setAttributeName(fakeName);
+ ui_widget->setElementAttribute(ui_widget->elementAttribute() << domAttr);
+ }
+ }
+ }
+
+ return ui_widget;
+}
+
+DomWidget *QDesignerResource::saveWidget(QTableView *tableView, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(tableView, ui_parentWidget, true);
+
+ QDesignerPropertySheetExtension *sheet
+ = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), tableView);
+ ItemViewPropertySheet *itemViewSheet = static_cast<ItemViewPropertySheet*>(sheet);
+
+ if (itemViewSheet) {
+ QHash<QString,QString> nameMap = itemViewSheet->propertyNameMap();
+ foreach (const QString &fakeName, nameMap.keys()) {
+ int index = itemViewSheet->indexOf(fakeName);
+ if (sheet->isChanged(index)) {
+ DomProperty *domAttr;
+ if (fakeName.startsWith(QLatin1String("horizontal"))) {
+ domAttr = createProperty(tableView->horizontalHeader(), nameMap.value(fakeName),
+ itemViewSheet->property(index));
+ } else {
+ domAttr = createProperty(tableView->verticalHeader(), nameMap.value(fakeName),
+ itemViewSheet->property(index));
+ }
+ domAttr->setAttributeName(fakeName);
+ ui_widget->setElementAttribute(ui_widget->elementAttribute() << domAttr);
+ }
+ }
+ }
+
+ return ui_widget;
+}
+
+static void saveStringProperty(DomProperty *property, const PropertySheetStringValue &value)
+{
+ DomString *str = new DomString();
+ str->setText(value.value());
+
+ const QString property_comment = value.disambiguation();
+ if (!property_comment.isEmpty())
+ str->setAttributeComment(property_comment);
+ const QString property_extraComment = value.comment();
+ if (!property_extraComment.isEmpty())
+ str->setAttributeExtraComment(property_extraComment);
+ const bool property_translatable = value.translatable();
+ if (!property_translatable)
+ str->setAttributeNotr(QLatin1String("true"));
+
+ property->setElementString(str);
+}
+
+static void saveKeySequenceProperty(DomProperty *property, const PropertySheetKeySequenceValue &value)
+{
+ DomString *str = new DomString();
+ str->setText(value.value().toString());
+
+ const QString property_comment = value.disambiguation();
+ if (!property_comment.isEmpty())
+ str->setAttributeComment(property_comment);
+ const QString property_extraComment = value.comment();
+ if (!property_extraComment.isEmpty())
+ str->setAttributeExtraComment(property_extraComment);
+ const bool property_translatable = value.translatable();
+ if (!property_translatable)
+ str->setAttributeNotr(QLatin1String("true"));
+
+ property->setElementString(str);
+}
+
+DomWidget *QDesignerResource::saveWidget(QTabWidget *widget, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false);
+ QList<DomWidget*> ui_widget_list;
+
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) {
+ const int current = widget->currentIndex();
+ for (int i=0; i<container->count(); ++i) {
+ QWidget *page = container->widget(i);
+ Q_ASSERT(page);
+
+ DomWidget *ui_page = createDom(page, ui_widget);
+ if (!ui_page) {
+ if (QSimpleResource::warningsEnabled())
+ designerWarning(msgUnmanagedPage(core(), widget, i, page));
+ continue;
+ }
+ QList<DomProperty*> ui_attribute_list;
+
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ // attribute `icon'
+ widget->setCurrentIndex(i);
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget);
+ PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentTabIcon"))));
+ DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon));
+ if (p) {
+ p->setAttributeName(strings.iconAttribute);
+ ui_attribute_list.append(p);
+ }
+ // attribute `title'
+ p = textBuilder()->saveText(sheet->property(sheet->indexOf(QLatin1String("currentTabText"))));
+ if (p) {
+ p->setAttributeName(strings.titleAttribute);
+ ui_attribute_list.append(p);
+ }
+
+ // attribute `toolTip'
+ QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentTabToolTip")));
+ if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) {
+ p = textBuilder()->saveText(v);
+ if (p) {
+ p->setAttributeName(strings.toolTipAttribute);
+ ui_attribute_list.append(p);
+ }
+ }
+
+ // attribute `whatsThis'
+ v = sheet->property(sheet->indexOf(QLatin1String("currentTabWhatsThis")));
+ if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) {
+ p = textBuilder()->saveText(v);
+ if (p) {
+ p->setAttributeName(strings.whatsThisAttribute);
+ ui_attribute_list.append(p);
+ }
+ }
+
+ ui_page->setElementAttribute(ui_attribute_list);
+
+ ui_widget_list.append(ui_page);
+ }
+ widget->setCurrentIndex(current);
+ }
+
+ ui_widget->setElementWidget(ui_widget_list);
+
+ return ui_widget;
+}
+
+DomWidget *QDesignerResource::saveWidget(QToolBox *widget, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(widget, ui_parentWidget, false);
+ QList<DomWidget*> ui_widget_list;
+
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), widget)) {
+ const int current = widget->currentIndex();
+ for (int i=0; i<container->count(); ++i) {
+ QWidget *page = container->widget(i);
+ Q_ASSERT(page);
+
+ DomWidget *ui_page = createDom(page, ui_widget);
+ if (!ui_page) {
+ if (QSimpleResource::warningsEnabled())
+ designerWarning(msgUnmanagedPage(core(), widget, i, page));
+ continue;
+ }
+
+ // attribute `label'
+ QList<DomProperty*> ui_attribute_list;
+
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+
+ // attribute `icon'
+ widget->setCurrentIndex(i);
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), widget);
+ PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String("currentItemIcon"))));
+ DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), qVariantFromValue(icon));
+ if (p) {
+ p->setAttributeName(strings.iconAttribute);
+ ui_attribute_list.append(p);
+ }
+ p = textBuilder()->saveText(sheet->property(sheet->indexOf(QLatin1String("currentItemText"))));
+ if (p) {
+ p->setAttributeName(strings.labelAttribute);
+ ui_attribute_list.append(p);
+ }
+
+ // attribute `toolTip'
+ QVariant v = sheet->property(sheet->indexOf(QLatin1String("currentItemToolTip")));
+ if (!qVariantValue<PropertySheetStringValue>(v).value().isEmpty()) {
+ p = textBuilder()->saveText(v);
+ if (p) {
+ p->setAttributeName(strings.toolTipAttribute);
+ ui_attribute_list.append(p);
+ }
+ }
+
+ ui_page->setElementAttribute(ui_attribute_list);
+
+ ui_widget_list.append(ui_page);
+ }
+ widget->setCurrentIndex(current);
+ }
+
+ ui_widget->setElementWidget(ui_widget_list);
+
+ return ui_widget;
+}
+
+DomWidget *QDesignerResource::saveWidget(QWizardPage *wizardPage, DomWidget *ui_parentWidget)
+{
+ DomWidget *ui_widget = QAbstractFormBuilder::createDom(wizardPage, ui_parentWidget, true);
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), wizardPage);
+ // Save the page id (string) attribute, append to existing attributes
+ const QString pageIdPropertyName = QLatin1String(QWizardPagePropertySheet::pageIdProperty);
+ const int pageIdIndex = sheet->indexOf(pageIdPropertyName);
+ if (pageIdIndex != -1 && sheet->isChanged(pageIdIndex)) {
+ DomProperty *property = variantToDomProperty(this, wizardPage->metaObject(), pageIdPropertyName, sheet->property(pageIdIndex));
+ Q_ASSERT(property);
+ property->elementString()->setAttributeNotr(QLatin1String("true"));
+ DomPropertyList attributes = ui_widget->elementAttribute();
+ attributes.push_back(property);
+ ui_widget->setElementAttribute(attributes);
+ }
+ return ui_widget;
+}
+
+// Do not save the 'currentTabName' properties of containers
+static inline bool checkContainerProperty(const QWidget *w, const QString &propertyName)
+{
+ if (qobject_cast<const QToolBox *>(w))
+ return QToolBoxWidgetPropertySheet::checkProperty(propertyName);
+ if (qobject_cast<const QTabWidget *>(w))
+ return QTabWidgetPropertySheet::checkProperty(propertyName);
+ if (qobject_cast<const QStackedWidget *>(w))
+ return QStackedWidgetPropertySheet::checkProperty(propertyName);
+ if (qobject_cast<const QMdiArea *>(w) || qobject_cast<const QWorkspace *>(w))
+ return QMdiAreaPropertySheet::checkProperty(propertyName);
+ return true;
+}
+
+bool QDesignerResource::checkProperty(QObject *obj, const QString &prop) const
+{
+ const QDesignerMetaObjectInterface *meta = core()->introspection()->metaObject(obj);
+
+ const int pindex = meta->indexOfProperty(prop);
+ if (pindex != -1 && !(meta->property(pindex)->attributes(obj) & QDesignerMetaPropertyInterface::StoredAttribute))
+ return false;
+
+ if (prop == QLatin1String("objectName") || prop == QLatin1String("spacerName")) // ### don't store the property objectName
+ return false;
+
+ QWidget *check_widget = 0;
+ if (obj->isWidgetType())
+ check_widget = static_cast<QWidget*>(obj);
+
+ if (check_widget && prop == QLatin1String("geometry")) {
+ if (check_widget == m_formWindow->mainContainer())
+ return true; // Save although maincontainer is technically laid-out by embedding container
+ if (m_selected && m_selected == check_widget)
+ return true;
+
+ return !LayoutInfo::isWidgetLaidout(core(), check_widget);
+ }
+
+ if (check_widget && !checkContainerProperty(check_widget, prop))
+ return false;
+
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), obj)) {
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), obj);
+ const int pindex = sheet->indexOf(prop);
+ if (sheet->isAttribute(pindex))
+ return false;
+
+ if (!dynamicSheet || !dynamicSheet->isDynamicProperty(pindex))
+ return sheet->isChanged(pindex);
+ if (!sheet->isVisible(pindex))
+ return false;
+ return true;
+ }
+
+ return false;
+}
+
+bool QDesignerResource::addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout)
+{
+ if (item->widget() == 0) {
+ return false;
+ }
+
+ QGridLayout *grid = qobject_cast<QGridLayout*>(layout);
+ QBoxLayout *box = qobject_cast<QBoxLayout*>(layout);
+
+ if (grid != 0) {
+ const int rowSpan = ui_item->hasAttributeRowSpan() ? ui_item->attributeRowSpan() : 1;
+ const int colSpan = ui_item->hasAttributeColSpan() ? ui_item->attributeColSpan() : 1;
+ grid->addWidget(item->widget(), ui_item->attributeRow(), ui_item->attributeColumn(), rowSpan, colSpan, item->alignment());
+ return true;
+ } else if (box != 0) {
+ box->addItem(item);
+ return true;
+ }
+
+ return QAbstractFormBuilder::addItem(ui_item, item, layout);
+}
+
+bool QDesignerResource::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ core()->metaDataBase()->add(widget); // ensure the widget is in the meta database
+
+ if (! QAbstractFormBuilder::addItem(ui_widget, widget, parentWidget) || qobject_cast<QMainWindow*> (parentWidget)) {
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), parentWidget))
+ container->addWidget(widget);
+ }
+
+ if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(parentWidget)) {
+ const int tabIndex = tabWidget->count() - 1;
+ const int current = tabWidget->currentIndex();
+
+ tabWidget->setCurrentIndex(tabIndex);
+
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+
+ const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), parentWidget);
+ if (DomProperty *picon = attributes.value(strings.iconAttribute)) {
+ QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentTabIcon")), v);
+ }
+ if (DomProperty *ptext = attributes.value(strings.titleAttribute)) {
+ QVariant v = textBuilder()->loadText(ptext);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentTabText")), v);
+ }
+ if (DomProperty *ptext = attributes.value(strings.toolTipAttribute)) {
+ QVariant v = textBuilder()->loadText(ptext);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentTabToolTip")), v);
+ }
+ if (DomProperty *ptext = attributes.value(strings.whatsThisAttribute)) {
+ QVariant v = textBuilder()->loadText(ptext);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentTabWhatsThis")), v);
+ }
+ tabWidget->setCurrentIndex(current);
+ } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(parentWidget)) {
+ const int itemIndex = toolBox->count() - 1;
+ const int current = toolBox->currentIndex();
+
+ toolBox->setCurrentIndex(itemIndex);
+
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+
+ const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), parentWidget);
+ if (DomProperty *picon = attributes.value(strings.iconAttribute)) {
+ QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentItemIcon")), v);
+ }
+ if (DomProperty *ptext = attributes.value(strings.labelAttribute)) {
+ QVariant v = textBuilder()->loadText(ptext);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentItemText")), v);
+ }
+ if (DomProperty *ptext = attributes.value(strings.toolTipAttribute)) {
+ QVariant v = textBuilder()->loadText(ptext);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentItemToolTip")), v);
+ }
+ toolBox->setCurrentIndex(current);
+ }
+
+ return true;
+}
+
+bool QDesignerResource::copy(QIODevice *dev, const FormBuilderClipboard &selection)
+{
+ m_copyWidget = true;
+
+ DomUI *ui = copy(selection);
+
+ m_laidout.clear();
+ m_copyWidget = false;
+
+ if (!ui)
+ return false;
+
+ QXmlStreamWriter writer(dev);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ ui->write(writer);
+ writer.writeEndDocument();
+ delete ui;
+ return true;
+}
+
+DomUI *QDesignerResource::copy(const FormBuilderClipboard &selection)
+{
+ if (selection.empty())
+ return 0;
+
+ m_copyWidget = true;
+
+ DomWidget *ui_widget = new DomWidget();
+ ui_widget->setAttributeName(QLatin1String(clipboardObjectName));
+ bool hasItems = false;
+ // Widgets
+ if (!selection.m_widgets.empty()) {
+ QList<DomWidget*> ui_widget_list;
+ const int size = selection.m_widgets.size();
+ for (int i=0; i< size; ++i) {
+ QWidget *w = selection.m_widgets.at(i);
+ m_selected = w;
+ DomWidget *ui_child = createDom(w, ui_widget);
+ m_selected = 0;
+ if (ui_child)
+ ui_widget_list.append(ui_child);
+ }
+ if (!ui_widget_list.empty()) {
+ ui_widget->setElementWidget(ui_widget_list);
+ hasItems = true;
+ }
+ }
+ // actions
+ if (!selection.m_actions.empty()) {
+ QList<DomAction*> domActions;
+ foreach(QAction* action, selection.m_actions)
+ if (DomAction *domAction = createDom(action))
+ domActions += domAction;
+ if (!domActions.empty()) {
+ ui_widget-> setElementAction(domActions);
+ hasItems = true;
+ }
+ }
+
+ m_laidout.clear();
+ m_copyWidget = false;
+
+ if (!hasItems) {
+ delete ui_widget;
+ return 0;
+ }
+ // UI
+ DomUI *ui = new DomUI();
+ ui->setAttributeVersion(QLatin1String(currentUiVersion));
+ ui->setElementWidget(ui_widget);
+ ui->setElementResources(saveResources(m_resourceBuilder->usedQrcFiles()));
+ if (DomCustomWidgets *cws = saveCustomWidgets())
+ ui->setElementCustomWidgets(cws);
+ return ui;
+}
+
+FormBuilderClipboard QDesignerResource::paste(DomUI *ui, QWidget *widgetParent, QObject *actionParent)
+{
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ const int saved = m_isMainWidget;
+ m_isMainWidget = false;
+
+ FormBuilderClipboard rc;
+
+ // Widgets
+ const DomWidget *topLevel = ui->elementWidget();
+ initialize(ui);
+ const QList<DomWidget*> domWidgets = topLevel->elementWidget();
+ if (!domWidgets.empty()) {
+ const QPoint offset = m_formWindow->grid();
+ foreach (DomWidget* domWidget, domWidgets) {
+ if (QWidget *w = create(domWidget, widgetParent)) {
+ w->move(w->pos() + offset);
+ // ### change the init properties of w
+ rc.m_widgets.append(w);
+ }
+ }
+ }
+ const QList<DomAction*> domActions = topLevel->elementAction();
+ if (!domActions.empty())
+ foreach (DomAction *domAction, domActions)
+ if (QAction *a = create(domAction, actionParent))
+ rc.m_actions .append(a);
+
+ m_isMainWidget = saved;
+
+ if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(core()->extensionManager(), core()))
+ extra->loadUiExtraInfo(ui);
+
+ createResources(ui->elementResources());
+
+ return rc;
+}
+
+FormBuilderClipboard QDesignerResource::paste(QIODevice *dev, QWidget *widgetParent, QObject *actionParent)
+{
+ DomUI ui;
+ QXmlStreamReader reader(dev);
+ bool uiInitialized = false;
+
+ const QString uiElement = QLatin1String("ui");
+ while (!reader.atEnd()) {
+ if (reader.readNext() == QXmlStreamReader::StartElement) {
+ if (reader.name().compare(uiElement, Qt::CaseInsensitive)) {
+ ui.read(reader);
+ uiInitialized = true;
+ } else {
+ //: Parsing clipboard contents
+ reader.raiseError(QCoreApplication::translate("QDesignerResource", "Unexpected element <%1>").arg(reader.name().toString()));
+ }
+ }
+ }
+ if (reader.hasError()) {
+ //: Parsing clipboard contents
+ designerWarning(QCoreApplication::translate("QDesignerResource", "Error while pasting clipboard contents at line %1, column %2: %3")
+ .arg(reader.lineNumber()).arg(reader.columnNumber())
+ .arg(reader.errorString()));
+ uiInitialized = false;
+ } else if (uiInitialized == false) {
+ //: Parsing clipboard contents
+ designerWarning(QCoreApplication::translate("QDesignerResource", "Error while pasting clipboard contents: The root element <ui> is missing."));
+ }
+
+ if (!uiInitialized)
+ return FormBuilderClipboard();
+
+ FormBuilderClipboard clipBoard = paste(&ui, widgetParent, actionParent);
+
+ return clipBoard;
+}
+
+void QDesignerResource::layoutInfo(DomLayout *layout, QObject *parent, int *margin, int *spacing)
+{
+ QAbstractFormBuilder::layoutInfo(layout, parent, margin, spacing);
+}
+
+DomCustomWidgets *QDesignerResource::saveCustomWidgets()
+{
+ if (m_usedCustomWidgets.isEmpty())
+ return 0;
+
+ // We would like the list to be in order of the widget database indexes
+ // to ensure that base classes come first (nice optics)
+ QDesignerFormEditorInterface *core = m_formWindow->core();
+ QDesignerWidgetDataBaseInterface *db = core->widgetDataBase();
+ const bool isInternalWidgetDataBase = qobject_cast<const WidgetDataBase *>(db);
+ typedef QMap<int,DomCustomWidget*> OrderedDBIndexDomCustomWidgetMap;
+ OrderedDBIndexDomCustomWidgetMap orderedMap;
+
+ const QString global = QLatin1String("global");
+ foreach (QDesignerWidgetDataBaseItemInterface *item, m_usedCustomWidgets.keys()) {
+ const QString name = item->name();
+ DomCustomWidget *custom_widget = new DomCustomWidget;
+
+ custom_widget->setElementClass(name);
+ if (item->isContainer())
+ custom_widget->setElementContainer(item->isContainer());
+
+ if (!item->includeFile().isEmpty()) {
+ DomHeader *header = new DomHeader;
+ const IncludeSpecification spec = includeSpecification(item->includeFile());
+ header->setText(spec.first);
+ if (spec.second == IncludeGlobal) {
+ header->setAttributeLocation(global);
+ }
+ custom_widget->setElementHeader(header);
+ custom_widget->setElementExtends(item->extends());
+ }
+
+ if (isInternalWidgetDataBase) {
+ WidgetDataBaseItem *internalItem = static_cast<WidgetDataBaseItem *>(item);
+ const QStringList fakeSlots = internalItem->fakeSlots();
+ const QStringList fakeSignals = internalItem->fakeSignals();
+ if (!fakeSlots.empty() || !fakeSignals.empty()) {
+ DomSlots *domSlots = new DomSlots();
+ domSlots->setElementSlot(fakeSlots);
+ domSlots->setElementSignal(fakeSignals);
+ custom_widget->setElementSlots(domSlots);
+ }
+ const QString addPageMethod = internalItem->addPageMethod();
+ if (!addPageMethod.isEmpty())
+ custom_widget->setElementAddPageMethod(addPageMethod);
+ }
+
+ // Look up static per-class scripts of designer
+ if (DomScript *domScript = createScript(customWidgetScript(core, name), ScriptCustomWidgetPlugin))
+ custom_widget->setElementScript(domScript);
+
+ orderedMap.insert(db->indexOfClassName(name), custom_widget);
+ }
+
+ DomCustomWidgets *customWidgets = new DomCustomWidgets;
+ customWidgets->setElementCustomWidget(orderedMap.values());
+ return customWidgets;
+}
+
+bool QDesignerResource::canCompressMargins(QObject *object) const
+{
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), object)) {
+ if (qobject_cast<QLayout *>(object)) {
+ const int l = sheet->property(sheet->indexOf(QLatin1String("leftMargin"))).toInt();
+ const int t = sheet->property(sheet->indexOf(QLatin1String("topMargin"))).toInt();
+ const int r = sheet->property(sheet->indexOf(QLatin1String("rightMargin"))).toInt();
+ const int b = sheet->property(sheet->indexOf(QLatin1String("bottomMargin"))).toInt();
+ if (l == t && l == r && l == b)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QDesignerResource::canCompressSpacings(QObject *object) const
+{
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), object)) {
+ if (qobject_cast<QGridLayout *>(object)) {
+ const int h = sheet->property(sheet->indexOf(QLatin1String("horizontalSpacing"))).toInt();
+ const int v = sheet->property(sheet->indexOf(QLatin1String("verticalSpacing"))).toInt();
+ if (h == v)
+ return true;
+ }
+ }
+ return false;
+}
+
+QList<DomProperty*> QDesignerResource::computeProperties(QObject *object)
+{
+ QList<DomProperty*> properties;
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), object)) {
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), object);
+ const int count = sheet->count();
+ QList<DomProperty *> marginProperties;
+ QList<DomProperty *> spacingProperties;
+ const bool compressMargins = canCompressMargins(object);
+ const bool compressSpacings = canCompressSpacings(object);
+ for (int index = 0; index < count; ++index) {
+ if (!sheet->isChanged(index) && (!dynamicSheet || !dynamicSheet->isDynamicProperty(index)))
+ continue;
+
+ const QString propertyName = sheet->propertyName(index);
+ // Suppress windowModality in legacy forms that have it set on child widgets
+ if (propertyName == QLatin1String("windowModality") && !sheet->isVisible(index))
+ continue;
+
+ const QVariant value = sheet->property(index);
+ if (DomProperty *p = createProperty(object, propertyName, value)) {
+ if (compressMargins && (propertyName == QLatin1String("leftMargin")
+ || propertyName == QLatin1String("rightMargin")
+ || propertyName == QLatin1String("topMargin")
+ || propertyName == QLatin1String("bottomMargin"))) {
+ marginProperties.append(p);
+ } else if (compressSpacings && (propertyName == QLatin1String("horizontalSpacing")
+ || propertyName == QLatin1String("verticalSpacing"))) {
+ spacingProperties.append(p);
+ } else {
+ properties.append(p);
+ }
+ }
+ }
+ if (compressMargins) {
+ if (marginProperties.count() == 4) { // if we have 3 it means one is reset so we can't compress
+ DomProperty *marginProperty = marginProperties.at(0);
+ marginProperty->setAttributeName(QLatin1String("margin"));
+ properties.append(marginProperty);
+ delete marginProperties.at(1);
+ delete marginProperties.at(2);
+ delete marginProperties.at(3);
+ } else {
+ properties += marginProperties;
+ }
+ }
+ if (compressSpacings) {
+ if (spacingProperties.count() == 2) {
+ DomProperty *spacingProperty = spacingProperties.at(0);
+ spacingProperty->setAttributeName(QLatin1String("spacing"));
+ properties.append(spacingProperty);
+ delete spacingProperties.at(1);
+ } else {
+ properties += spacingProperties;
+ }
+ }
+ }
+ return properties;
+}
+
+DomProperty *QDesignerResource::applyProperStdSetAttribute(QObject *object, const QString &propertyName, DomProperty *property)
+{
+ if (!property)
+ return 0;
+
+ QExtensionManager *mgr = core()->extensionManager();
+ if (const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(mgr, object)) {
+ const QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(mgr, object);
+ const QDesignerPropertySheet *designerSheet = qobject_cast<QDesignerPropertySheet*>(core()->extensionManager()->extension(object, Q_TYPEID(QDesignerPropertySheetExtension)));
+ const int index = sheet->indexOf(propertyName);
+ if ((dynamicSheet && dynamicSheet->isDynamicProperty(index)) || (designerSheet && designerSheet->isDefaultDynamicProperty(index)))
+ property->setAttributeStdset(0);
+ }
+ return property;
+}
+
+// Optimistic check for a standard setter function
+static inline bool hasSetter(QDesignerFormEditorInterface *core, QObject *object, const QString &propertyName)
+{
+ const QDesignerMetaObjectInterface *meta = core->introspection()->metaObject(object);
+ const int pindex = meta->indexOfProperty(propertyName);
+ if (pindex == -1)
+ return true;
+ return meta->property(pindex)->hasSetter();
+}
+
+DomProperty *QDesignerResource::createProperty(QObject *object, const QString &propertyName, const QVariant &value)
+{
+ if (!checkProperty(object, propertyName)) {
+ return 0;
+ }
+
+ if (qVariantCanConvert<PropertySheetFlagValue>(value)) {
+ const PropertySheetFlagValue f = qVariantValue<PropertySheetFlagValue>(value);
+ const QString flagString = f.metaFlags.toString(f.value, DesignerMetaFlags::FullyQualified);
+ if (flagString.isEmpty())
+ return 0;
+
+ DomProperty *p = new DomProperty;
+ // check if we have a standard cpp set function
+ if (!hasSetter(core(), object, propertyName))
+ p->setAttributeStdset(0);
+ p->setAttributeName(propertyName);
+ p->setElementSet(flagString);
+ return applyProperStdSetAttribute(object, propertyName, p);
+ } else if (qVariantCanConvert<PropertySheetEnumValue>(value)) {
+ const PropertySheetEnumValue e = qVariantValue<PropertySheetEnumValue>(value);
+ bool ok;
+ const QString id = e.metaEnum.toString(e.value, DesignerMetaEnum::FullyQualified, &ok);
+ if (!ok)
+ designerWarning(e.metaEnum.messageToStringFailed(e.value));
+ if (id.isEmpty())
+ return 0;
+
+ DomProperty *p = new DomProperty;
+ // check if we have a standard cpp set function
+ if (!hasSetter(core(), object, propertyName))
+ p->setAttributeStdset(0);
+ p->setAttributeName(propertyName);
+ p->setElementEnum(id);
+ return applyProperStdSetAttribute(object, propertyName, p);
+ } else if (qVariantCanConvert<PropertySheetStringValue>(value)) {
+ const PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(value);
+ DomProperty *p = new DomProperty;
+ if (!hasSetter(core(), object, propertyName))
+ p->setAttributeStdset(0);
+
+ p->setAttributeName(propertyName);
+
+ saveStringProperty(p, strVal);
+
+ return applyProperStdSetAttribute(object, propertyName, p);
+ } else if (qVariantCanConvert<PropertySheetKeySequenceValue>(value)) {
+ const PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(value);
+ DomProperty *p = new DomProperty;
+ if (!hasSetter(core(), object, propertyName))
+ p->setAttributeStdset(0);
+
+ p->setAttributeName(propertyName);
+
+ saveKeySequenceProperty(p, keyVal);
+
+ return applyProperStdSetAttribute(object, propertyName, p);
+ }
+
+ return applyProperStdSetAttribute(object, propertyName, QAbstractFormBuilder::createProperty(object, propertyName, value));
+}
+
+QStringList QDesignerResource::mergeWithLoadedPaths(const QStringList &paths) const
+{
+ QStringList newPaths = paths;
+#ifdef OLD_RESOURCE_FORMAT
+ QStringList loadedPaths = m_resourceBuilder->loadedQrcFiles();
+ QStringListIterator it(loadedPaths);
+ while (it.hasNext()) {
+ const QString path = it.next();
+ if (!newPaths.contains(path))
+ newPaths << path;
+ }
+#endif
+ return newPaths;
+}
+
+
+void QDesignerResource::createResources(DomResources *resources)
+{
+ QStringList paths;
+ if (resources != 0) {
+ const QList<DomResource*> dom_include = resources->elementInclude();
+ foreach (DomResource *res, dom_include) {
+ QString path = QDir::cleanPath(m_formWindow->absoluteDir().absoluteFilePath(res->attributeLocation()));
+ while (!QFile::exists(path)) {
+ QWidget *dialogParent = m_formWindow->core()->topLevel();
+ const QString promptTitle = QApplication::translate("qdesigner_internal::QDesignerResource", "Loading qrc file", 0, QApplication::UnicodeUTF8);
+ const QString prompt = QApplication::translate("qdesigner_internal::QDesignerResource", "The specified qrc file <p><b>%1</b></p><p>could not be found. Do you want to update the file location?</p>", 0, QApplication::UnicodeUTF8).arg(path);
+
+ const QMessageBox::StandardButton answer = core()->dialogGui()->message(dialogParent, QDesignerDialogGuiInterface::ResourceLoadFailureMessage,
+ QMessageBox::Warning, promptTitle, prompt, QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
+ if (answer == QMessageBox::Yes) {
+ const QFileInfo fi(path);
+ const QString fileDialogTitle = QApplication::translate("qdesigner_internal::QDesignerResource", "New location for %1", 0, QApplication::UnicodeUTF8).arg(fi.fileName());
+ const QString fileDialogPattern = QApplication::translate("qdesigner_internal::QDesignerResource", "Resource files (*.qrc)", 0, QApplication::UnicodeUTF8);
+ path = core()->dialogGui()->getOpenFileName(dialogParent, fileDialogTitle, fi.absolutePath(), fileDialogPattern);
+ if (path.isEmpty())
+ break;
+ } else {
+ break;
+ }
+ }
+ if (!path.isEmpty()) {
+ paths << path;
+ m_formWindow->addResourceFile(path);
+ }
+ }
+ }
+
+#ifdef OLD_RESOURCE_FORMAT
+ paths = mergeWithLoadedPaths(paths);
+#endif
+
+ QtResourceSet *resourceSet = m_formWindow->resourceSet();
+ if (resourceSet) {
+ QStringList oldPaths = resourceSet->activeQrcPaths();
+ QStringList newPaths = oldPaths;
+ QStringListIterator it(paths);
+ while (it.hasNext()) {
+ const QString path = it.next();
+ if (!newPaths.contains(path))
+ newPaths << path;
+ }
+ resourceSet->activateQrcPaths(newPaths);
+ } else {
+ resourceSet = m_formWindow->core()->resourceModel()->addResourceSet(paths);
+ m_formWindow->setResourceSet(resourceSet);
+ QObject::connect(m_formWindow->core()->resourceModel(), SIGNAL(resourceSetActivated(QtResourceSet *, bool)),
+ m_formWindow, SLOT(resourceSetActivated(QtResourceSet *, bool)));
+ }
+}
+
+DomResources *QDesignerResource::saveResources()
+{
+ QStringList paths;
+ if (m_formWindow->saveResourcesBehaviour() == FormWindowBase::SaveAll) {
+ QtResourceSet *resourceSet = m_formWindow->resourceSet();
+ QList<DomResource*> dom_include;
+ if (resourceSet)
+ paths = resourceSet->activeQrcPaths();
+ } else if (m_formWindow->saveResourcesBehaviour() == FormWindowBase::SaveOnlyUsedQrcFiles) {
+ paths = m_resourceBuilder->usedQrcFiles();
+ }
+
+ return saveResources(paths);
+}
+
+DomResources *QDesignerResource::saveResources(const QStringList &qrcPaths)
+{
+ QtResourceSet *resourceSet = m_formWindow->resourceSet();
+ QList<DomResource*> dom_include;
+ if (resourceSet) {
+ const QStringList activePaths = resourceSet->activeQrcPaths();
+ foreach (QString path, activePaths) {
+ if (qrcPaths.contains(path)) {
+ DomResource *dom_res = new DomResource;
+ QString conv_path = path;
+ if (m_resourceBuilder->isSaveRelative())
+ conv_path = m_formWindow->absoluteDir().relativeFilePath(path);
+ dom_res->setAttributeLocation(conv_path.replace(QDir::separator(), QLatin1Char('/')));
+ dom_include.append(dom_res);
+ }
+ }
+ }
+
+ DomResources *dom_resources = new DomResources;
+ dom_resources->setElementInclude(dom_include);
+
+ return dom_resources;
+}
+
+DomAction *QDesignerResource::createDom(QAction *action)
+{
+ if (!core()->metaDataBase()->item(action) || action->menu())
+ return 0;
+
+ return QAbstractFormBuilder::createDom(action);
+}
+
+DomActionGroup *QDesignerResource::createDom(QActionGroup *actionGroup)
+{
+ if (core()->metaDataBase()->item(actionGroup) != 0) {
+ return QAbstractFormBuilder::createDom(actionGroup);
+ }
+
+ return 0;
+}
+
+QAction *QDesignerResource::create(DomAction *ui_action, QObject *parent)
+{
+ if (QAction *action = QAbstractFormBuilder::create(ui_action, parent)) {
+ core()->metaDataBase()->add(action);
+ return action;
+ }
+
+ return 0;
+}
+
+QActionGroup *QDesignerResource::create(DomActionGroup *ui_action_group, QObject *parent)
+{
+ if (QActionGroup *actionGroup = QAbstractFormBuilder::create(ui_action_group, parent)) {
+ core()->metaDataBase()->add(actionGroup);
+ return actionGroup;
+ }
+
+ return 0;
+}
+
+DomActionRef *QDesignerResource::createActionRefDom(QAction *action)
+{
+ if (!core()->metaDataBase()->item(action)
+ || (!action->isSeparator() && !action->menu() && action->objectName().isEmpty()))
+ return 0;
+
+ return QAbstractFormBuilder::createActionRefDom(action);
+}
+
+void QDesignerResource::addMenuAction(QAction *action)
+{
+ core()->metaDataBase()->add(action);
+}
+
+QAction *QDesignerResource::createAction(QObject *parent, const QString &name)
+{
+ if (QAction *action = QAbstractFormBuilder::createAction(parent, name)) {
+ core()->metaDataBase()->add(action);
+ return action;
+ }
+
+ return 0;
+}
+
+QActionGroup *QDesignerResource::createActionGroup(QObject *parent, const QString &name)
+{
+ if (QActionGroup *actionGroup = QAbstractFormBuilder::createActionGroup(parent, name)) {
+ core()->metaDataBase()->add(actionGroup);
+ return actionGroup;
+ }
+
+ return 0;
+}
+
+/* Apply the attributes to a widget via property sheet where appropriate,
+ * that is, the sheet handles attributive fake properties */
+void QDesignerResource::applyAttributesToPropertySheet(const DomWidget *ui_widget, QWidget *widget)
+{
+ const DomPropertyList attributes = ui_widget->elementAttribute();
+ if (attributes.empty())
+ return;
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(m_formWindow->core()->extensionManager(), widget);
+ const DomPropertyList::const_iterator acend = attributes.constEnd();
+ for (DomPropertyList::const_iterator it = attributes.constBegin(); it != acend; ++it) {
+ const QString name = (*it)->attributeName();
+ const int index = sheet->indexOf(name);
+ if (index == -1) {
+ const QString msg = QString::fromUtf8("Unable to apply attributive property '%1' to '%2'. It does not exist.").arg(name, widget->objectName());
+ designerWarning(msg);
+ } else {
+ sheet->setProperty(index, domPropertyToVariant(this, widget->metaObject(), *it));
+ sheet->setChanged(index, true);
+ }
+ }
+}
+
+void QDesignerResource::loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ QAbstractFormBuilder::loadExtraInfo(ui_widget, widget, parentWidget);
+ // Apply the page id attribute of a QWizardPage (which is an attributive fake property)
+ if (qobject_cast<const QWizardPage*>(widget))
+ applyAttributesToPropertySheet(ui_widget, widget);
+}
+
+// Add user defined scripts (dialog box) belonging to QWidget to DomWidget.
+void QDesignerResource::addUserDefinedScripts(QWidget *w, DomWidget *ui_widget)
+{
+ QDesignerFormEditorInterface *core = m_formWindow->core();
+ DomScripts domScripts = ui_widget->elementScript();
+ // Look up user-defined scripts of designer
+ if (const qdesigner_internal::MetaDataBase *metaDataBase = qobject_cast<const qdesigner_internal::MetaDataBase *>(core->metaDataBase())) {
+ if (const qdesigner_internal::MetaDataBaseItem *metaItem = metaDataBase->metaDataBaseItem(w)) {
+ addScript(metaItem->script(), ScriptDesigner, domScripts);
+ }
+ }
+ if (!domScripts.empty())
+ ui_widget->setElementScript(domScripts);
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/qdesigner_resource.h b/tools/designer/src/components/formeditor/qdesigner_resource.h
new file mode 100644
index 0000000000..3d6a8427b7
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qdesigner_resource.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_RESOURCE_H
+#define QDESIGNER_RESOURCE_H
+
+#include "formeditor_global.h"
+#include "qsimpleresource_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QStack>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class DomCustomWidget;
+class DomCustomWidgets;
+class DomResource;
+
+class QDesignerContainerExtension;
+class QDesignerFormEditorInterface;
+class QDesignerCustomWidgetInterface;
+class QDesignerWidgetDataBaseItemInterface;
+
+class QTabWidget;
+class QStackedWidget;
+class QToolBox;
+class QToolBar;
+class QTreeView;
+class QTableView;
+class QDesignerDockWidget;
+class QLayoutWidget;
+class QWizardPage;
+
+namespace qdesigner_internal {
+
+class FormWindow;
+
+class QT_FORMEDITOR_EXPORT QDesignerResource : public QEditorFormBuilder
+{
+public:
+ explicit QDesignerResource(FormWindow *fw);
+ virtual ~QDesignerResource();
+
+ virtual void save(QIODevice *dev, QWidget *widget);
+
+ virtual bool copy(QIODevice *dev, const FormBuilderClipboard &selection);
+ virtual DomUI *copy(const FormBuilderClipboard &selection);
+
+ virtual FormBuilderClipboard paste(DomUI *ui, QWidget *widgetParent, QObject *actionParent = 0);
+ virtual FormBuilderClipboard paste(QIODevice *dev, QWidget *widgetParent, QObject *actionParent = 0);
+
+ bool saveRelative() const;
+ void setSaveRelative(bool relative);
+
+ virtual QWidget *load(QIODevice *dev, QWidget *parentWidget = 0);
+
+protected:
+ using QEditorFormBuilder::create;
+ using QEditorFormBuilder::createDom;
+
+ virtual void saveDom(DomUI *ui, QWidget *widget);
+ virtual QWidget *create(DomUI *ui, QWidget *parentWidget);
+ virtual QWidget *create(DomWidget *ui_widget, QWidget *parentWidget);
+ virtual QLayout *create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget);
+ virtual QLayoutItem *create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget);
+ virtual void applyProperties(QObject *o, const QList<DomProperty*> &properties);
+ virtual QList<DomProperty*> computeProperties(QObject *obj);
+ virtual DomProperty *createProperty(QObject *object, const QString &propertyName, const QVariant &value);
+
+ virtual QWidget *createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name);
+ virtual QLayout *createLayout(const QString &layoutName, QObject *parent, const QString &name);
+ virtual void createCustomWidgets(DomCustomWidgets *);
+ virtual void createResources(DomResources*);
+ virtual void applyTabStops(QWidget *widget, DomTabStops *tabStops);
+
+ virtual bool addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout);
+ virtual bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+
+ virtual DomWidget *createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive = true);
+ virtual DomLayout *createDom(QLayout *layout, DomLayout *ui_layout, DomWidget *ui_parentWidget);
+ virtual DomLayoutItem *createDom(QLayoutItem *item, DomLayout *ui_layout, DomWidget *ui_parentWidget);
+
+ virtual QAction *create(DomAction *ui_action, QObject *parent);
+ virtual QActionGroup *create(DomActionGroup *ui_action_group, QObject *parent);
+ virtual void addMenuAction(QAction *action);
+
+ virtual DomAction *createDom(QAction *action);
+ virtual DomActionGroup *createDom(QActionGroup *actionGroup);
+ virtual DomActionRef *createActionRefDom(QAction *action);
+
+ virtual QAction *createAction(QObject *parent, const QString &name);
+ virtual QActionGroup *createActionGroup(QObject *parent, const QString &name);
+
+ virtual bool checkProperty(QObject *obj, const QString &prop) const;
+
+ DomWidget *saveWidget(QTabWidget *widget, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QStackedWidget *widget, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QToolBox *widget, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QWidget *widget, QDesignerContainerExtension *container, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QToolBar *toolBar, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QDesignerDockWidget *dockWidget, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QTreeView *treeView, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QTableView *tableView, DomWidget *ui_parentWidget);
+ DomWidget *saveWidget(QWizardPage *wizardPage, DomWidget *ui_parentWidget);
+
+ virtual DomCustomWidgets *saveCustomWidgets();
+ virtual DomTabStops *saveTabStops();
+ virtual DomResources *saveResources();
+
+ virtual void layoutInfo(DomLayout *layout, QObject *parent, int *margin, int *spacing);
+
+ virtual void loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+
+ void changeObjectName(QObject *o, QString name);
+ DomProperty *applyProperStdSetAttribute(QObject *object, const QString &propertyName, DomProperty *property);
+
+private:
+ void addUserDefinedScripts(QWidget *w, DomWidget *ui_widget);
+ DomResources *saveResources(const QStringList &qrcPaths);
+ bool canCompressMargins(QObject *object) const;
+ bool canCompressSpacings(QObject *object) const;
+ QStringList mergeWithLoadedPaths(const QStringList &paths) const;
+ void applyAttributesToPropertySheet(const DomWidget *ui_widget, QWidget *widget);
+
+ typedef QList<DomCustomWidget*> DomCustomWidgetList;
+ void addCustomWidgetsToWidgetDatabase(DomCustomWidgetList& list);
+ FormWindow *m_formWindow;
+ bool m_isMainWidget;
+ QHash<QString, QString> m_internal_to_qt;
+ QHash<QString, QString> m_qt_to_internal;
+ QStack<QLayout*> m_chain;
+ QHash<QDesignerWidgetDataBaseItemInterface*, bool> m_usedCustomWidgets;
+ int m_topLevelSpacerCount;
+ bool m_copyWidget;
+ QWidget *m_selected;
+ class QDesignerResourceBuilder *m_resourceBuilder;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_RESOURCE_H
diff --git a/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp
new file mode 100644
index 0000000000..e3e4a97e36
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlayoutwidget_propertysheet.h"
+#include "qlayout_widget_p.h"
+#include "formwindow.h"
+#include "formeditor.h"
+
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+QLayoutWidgetPropertySheet::QLayoutWidgetPropertySheet(QLayoutWidget *object, QObject *parent)
+ : QDesignerPropertySheet(object, parent)
+{
+ clearFakeProperties();
+}
+
+QLayoutWidgetPropertySheet::~QLayoutWidgetPropertySheet()
+{
+}
+
+bool QLayoutWidgetPropertySheet::isVisible(int index) const
+{
+ static const QString layoutPropertyGroup = QLatin1String("Layout");
+ if (propertyGroup(index) == layoutPropertyGroup)
+ return QDesignerPropertySheet::isVisible(index);
+ return false;
+}
+
+void QLayoutWidgetPropertySheet::setProperty(int index, const QVariant &value)
+{
+ QDesignerPropertySheet::setProperty(index, value);
+}
+
+bool QLayoutWidgetPropertySheet::dynamicPropertiesAllowed() const
+{
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.h b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.h
new file mode 100644
index 0000000000..e96adaf583
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qlayoutwidget_propertysheet.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLAYOUTWIDGET_PROPERTYSHEET_H
+#define QLAYOUTWIDGET_PROPERTYSHEET_H
+
+#include <qdesigner_propertysheet_p.h>
+#include <extensionfactory_p.h>
+#include <qlayout_widget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QLayoutWidgetPropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension)
+public:
+ explicit QLayoutWidgetPropertySheet(QLayoutWidget *object, QObject *parent = 0);
+ virtual ~QLayoutWidgetPropertySheet();
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual bool isVisible(int index) const;
+
+ virtual bool dynamicPropertiesAllowed() const;
+};
+
+typedef QDesignerPropertySheetFactory<QLayoutWidget, QLayoutWidgetPropertySheet> QLayoutWidgetPropertySheetFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QLAYOUTWIDGET_PROPERTYSHEET_H
diff --git a/tools/designer/src/components/formeditor/qmainwindow_container.cpp b/tools/designer/src/components/formeditor/qmainwindow_container.cpp
new file mode 100644
index 0000000000..7fd21d1ed8
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qmainwindow_container.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmainwindow_container.h"
+#include "qdesigner_toolbar_p.h"
+#include "formwindow.h"
+
+#include <QtCore/qdebug.h>
+
+#include <QtGui/QLayout>
+#include <QtGui/QMenuBar>
+#include <QtGui/QToolBar>
+#include <QtGui/QStatusBar>
+#include <QtGui/QDockWidget>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+QMainWindowContainer::QMainWindowContainer(QMainWindow *widget, QObject *parent)
+ : QObject(parent),
+ m_mainWindow(widget)
+{
+}
+
+int QMainWindowContainer::count() const
+{
+ return m_widgets.count();
+}
+
+QWidget *QMainWindowContainer::widget(int index) const
+{
+ if (index == -1)
+ return 0;
+
+ return m_widgets.at(index);
+}
+
+int QMainWindowContainer::currentIndex() const
+{
+ return m_mainWindow->centralWidget() ? 0 : -1;
+}
+
+void QMainWindowContainer::setCurrentIndex(int index)
+{
+ Q_UNUSED(index);
+}
+
+
+namespace {
+ // Pair of <area,break_before>
+ typedef QPair<Qt::ToolBarArea,bool> ToolBarData;
+
+ ToolBarData toolBarData(QToolBar *me) {
+ const QMainWindow *mw = qobject_cast<const QMainWindow*>(me->parentWidget());
+ if (!mw || !mw->layout() || mw->layout()->indexOf(me) == -1)
+ return ToolBarData(Qt::TopToolBarArea,false);
+ return ToolBarData(mw->toolBarArea(me), mw->toolBarBreak(me));
+ }
+
+Qt::DockWidgetArea dockWidgetArea(QDockWidget *me)
+{
+ if (const QMainWindow *mw = qobject_cast<const QMainWindow*>(me->parentWidget())) {
+ // Make sure that me is actually managed by mw, otherwise
+ // QMainWindow::dockWidgetArea() will be VERY upset
+ QList<QLayout*> candidates;
+ if (mw->layout()) {
+ candidates.append(mw->layout());
+ candidates += qFindChildren<QLayout*>(mw->layout());
+ }
+ foreach (QLayout *l, candidates) {
+ if (l->indexOf(me) != -1) {
+ return mw->dockWidgetArea(me);
+ }
+ }
+ }
+ return Qt::LeftDockWidgetArea;
+}
+}
+
+void QMainWindowContainer::addWidget(QWidget *widget)
+{
+ // remove all the occurrences of widget
+ m_widgets.removeAll(widget);
+
+ // the
+ if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
+ m_widgets.append(widget);
+ const ToolBarData data = toolBarData(toolBar);
+ m_mainWindow->addToolBar(data.first, toolBar);
+ if (data.second) m_mainWindow->insertToolBarBreak(toolBar);
+ toolBar->show();
+ }
+
+ else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(widget)) {
+ if (menuBar != m_mainWindow->menuBar())
+ m_mainWindow->setMenuBar(menuBar);
+
+ m_widgets.append(widget);
+ menuBar->show();
+ }
+
+ else if (QStatusBar *statusBar = qobject_cast<QStatusBar*>(widget)) {
+ if (statusBar != m_mainWindow->statusBar())
+ m_mainWindow->setStatusBar(statusBar);
+
+ m_widgets.append(widget);
+ statusBar->show();
+ }
+
+ else if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(widget)) {
+ m_widgets.append(widget);
+ m_mainWindow->addDockWidget(dockWidgetArea(dockWidget), dockWidget);
+ dockWidget->show();
+
+ if (FormWindow *fw = FormWindow::findFormWindow(m_mainWindow)) {
+ fw->manageWidget(widget);
+ }
+ }
+
+ else if (widget) {
+ m_widgets.prepend(widget);
+
+ if (widget != m_mainWindow->centralWidget()) {
+ // note that qmainwindow will delete the current central widget if you
+ // call setCentralWidget(), we end up with dangeling pointers in m_widgets list
+ m_widgets.removeAll(m_mainWindow->centralWidget());
+
+ widget->setParent(m_mainWindow);
+ m_mainWindow->setCentralWidget(widget);
+ }
+ }
+}
+
+void QMainWindowContainer::insertWidget(int index, QWidget *widget)
+{
+ Q_UNUSED(index);
+
+ addWidget(widget);
+}
+
+void QMainWindowContainer::remove(int index)
+{
+ QWidget *widget = m_widgets.at(index);
+ if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
+ m_mainWindow->removeToolBar(toolBar);
+ } else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(widget)) {
+ menuBar->hide();
+ menuBar->setParent(0);
+ m_mainWindow->setMenuBar(0);
+ } else if (QStatusBar *statusBar = qobject_cast<QStatusBar*>(widget)) {
+ statusBar->hide();
+ statusBar->setParent(0);
+ m_mainWindow->setStatusBar(0);
+ } else if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(widget)) {
+ m_mainWindow->removeDockWidget(dockWidget);
+ }
+ m_widgets.removeAt(index);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/qmainwindow_container.h b/tools/designer/src/components/formeditor/qmainwindow_container.h
new file mode 100644
index 0000000000..aaf942f7e2
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qmainwindow_container.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMAINWINDOW_CONTAINER_H
+#define QMAINWINDOW_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionFactory>
+
+#include <extensionfactory_p.h>
+
+#include <QtGui/QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QMainWindowContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QMainWindowContainer(QMainWindow *widget, QObject *parent = 0);
+
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int index);
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ QMainWindow *m_mainWindow;
+ QList<QWidget*> m_widgets;
+};
+
+typedef ExtensionFactory<QDesignerContainerExtension, QMainWindow, QMainWindowContainer> QMainWindowContainerFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QMAINWINDOW_CONTAINER_H
diff --git a/tools/designer/src/components/formeditor/qmdiarea_container.cpp b/tools/designer/src/components/formeditor/qmdiarea_container.cpp
new file mode 100644
index 0000000000..fdeef030bc
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qmdiarea_container.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmdiarea_container.h"
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QMdiAreaContainer::QMdiAreaContainer(QMdiArea *widget, QObject *parent)
+ : QObject(parent),
+ m_mdiArea(widget)
+{
+}
+
+int QMdiAreaContainer::count() const
+{
+ return m_mdiArea->subWindowList(QMdiArea::CreationOrder).count();
+}
+
+QWidget *QMdiAreaContainer::widget(int index) const
+{
+ if (index < 0)
+ return 0;
+ return m_mdiArea->subWindowList(QMdiArea::CreationOrder).at(index)->widget();
+}
+
+int QMdiAreaContainer::currentIndex() const
+{
+ if (QMdiSubWindow *sub = m_mdiArea->activeSubWindow())
+ return m_mdiArea->subWindowList(QMdiArea::CreationOrder).indexOf(sub);
+ return -1;
+}
+
+void QMdiAreaContainer::setCurrentIndex(int index)
+{
+ if (index < 0) {
+ qDebug() << "** WARNING Attempt to QMdiAreaContainer::setCurrentIndex(-1)";
+ return;
+ }
+ QMdiSubWindow *frame = m_mdiArea->subWindowList(QMdiArea::CreationOrder).at(index);
+ m_mdiArea->setActiveSubWindow(frame);
+}
+
+void QMdiAreaContainer::addWidget(QWidget *widget)
+{
+ QMdiSubWindow *frame = m_mdiArea->addSubWindow(widget, Qt::Window);
+ frame->show();
+ m_mdiArea->cascadeSubWindows();
+ positionNewMdiChild(m_mdiArea, frame);
+}
+
+// Semi-smart positioning of new windows: Make child fill the whole MDI window below
+// cascaded other windows
+void QMdiAreaContainer::positionNewMdiChild(const QWidget *area, QWidget *mdiChild)
+{
+ enum { MinSize = 20 };
+ const QPoint pos = mdiChild->pos();
+ const QSize areaSize = area->size();
+ switch (QApplication::layoutDirection()) {
+ case Qt::LeftToRight: {
+ const QSize fullSize = QSize(areaSize.width() - pos.x(), areaSize.height() - pos.y());
+ if (fullSize.width() > MinSize && fullSize.height() > MinSize)
+ mdiChild->resize(fullSize);
+ }
+ break;
+ case Qt::RightToLeft: {
+ const QSize fullSize = QSize(pos.x() + mdiChild->width(), areaSize.height() - pos.y());
+ if (fullSize.width() > MinSize && fullSize.height() > MinSize) {
+ mdiChild->move(0, pos.y());
+ mdiChild->resize(fullSize);
+ }
+ }
+ break;
+ }
+}
+
+void QMdiAreaContainer::insertWidget(int, QWidget *widget)
+{
+ addWidget(widget);
+}
+
+void QMdiAreaContainer::remove(int index)
+{
+ QList<QMdiSubWindow *> subWins = m_mdiArea->subWindowList(QMdiArea::CreationOrder);
+ if (index >= 0 && index < subWins.size()) {
+ QMdiSubWindow *f = subWins.at(index);
+ m_mdiArea->removeSubWindow(f->widget());
+ delete f;
+ }
+}
+
+// ---------- MdiAreaPropertySheet, creates fake properties:
+// 1) window name (object name of child)
+// 2) title (windowTitle of child).
+
+static const char *subWindowTitleC = "activeSubWindowTitle";
+static const char *subWindowNameC = "activeSubWindowName";
+
+QMdiAreaPropertySheet::QMdiAreaPropertySheet(QWidget *mdiArea, QObject *parent) :
+ QDesignerPropertySheet(mdiArea, parent),
+ m_windowTitleProperty(QLatin1String("windowTitle"))
+{
+ createFakeProperty(QLatin1String(subWindowNameC), QString());
+ createFakeProperty(QLatin1String(subWindowTitleC), QString());
+}
+
+QMdiAreaPropertySheet::MdiAreaProperty QMdiAreaPropertySheet::mdiAreaProperty(const QString &name)
+{
+ typedef QHash<QString, MdiAreaProperty> MdiAreaPropertyHash;
+ static MdiAreaPropertyHash mdiAreaPropertyHash;
+ if (mdiAreaPropertyHash.empty()) {
+ mdiAreaPropertyHash.insert(QLatin1String(subWindowNameC), MdiAreaSubWindowName);
+ mdiAreaPropertyHash.insert(QLatin1String(subWindowTitleC), MdiAreaSubWindowTitle);
+ }
+ return mdiAreaPropertyHash.value(name,MdiAreaNone);
+}
+
+void QMdiAreaPropertySheet::setProperty(int index, const QVariant &value)
+{
+ switch (mdiAreaProperty(propertyName(index))) {
+ case MdiAreaSubWindowName:
+ if (QWidget *w = currentWindow())
+ w->setObjectName(value.toString());
+ break;
+ case MdiAreaSubWindowTitle: // Forward to window title of subwindow
+ if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) {
+ const int index = cws->indexOf(m_windowTitleProperty);
+ cws->setProperty(index, value);
+ cws->setChanged(index, true);
+ }
+ break;
+ default:
+ QDesignerPropertySheet::setProperty(index, value);
+ break;
+ }
+}
+
+bool QMdiAreaPropertySheet::reset(int index)
+{
+ bool rc = true;
+ switch (mdiAreaProperty(propertyName(index))) {
+ case MdiAreaSubWindowName:
+ setProperty(index, QVariant(QString()));
+ setChanged(index, false);
+ break;
+ case MdiAreaSubWindowTitle: // Forward to window title of subwindow
+ if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) {
+ const int index = cws->indexOf(m_windowTitleProperty);
+ rc = cws->reset(index);
+ }
+ break;
+ default:
+ rc = QDesignerPropertySheet::reset(index);
+ break;
+ }
+ return rc;
+}
+
+QVariant QMdiAreaPropertySheet::property(int index) const
+{
+ switch (mdiAreaProperty(propertyName(index))) {
+ case MdiAreaSubWindowName:
+ if (QWidget *w = currentWindow())
+ return w->objectName();
+ return QVariant(QString());
+ case MdiAreaSubWindowTitle:
+ if (QWidget *w = currentWindow())
+ return w->windowTitle();
+ return QVariant(QString());
+ case MdiAreaNone:
+ break;
+ }
+ return QDesignerPropertySheet::property(index);
+}
+
+bool QMdiAreaPropertySheet::isEnabled(int index) const
+{
+ switch (mdiAreaProperty(propertyName(index))) {
+ case MdiAreaSubWindowName:
+ case MdiAreaSubWindowTitle:
+ return currentWindow() != 0;
+ case MdiAreaNone:
+ break;
+ }
+ return QDesignerPropertySheet::isEnabled(index);
+}
+
+bool QMdiAreaPropertySheet::isChanged(int index) const
+{
+ bool rc = false;
+ switch (mdiAreaProperty(propertyName(index))) {
+ case MdiAreaSubWindowName:
+ rc = currentWindow() != 0;
+ break;
+ case MdiAreaSubWindowTitle:
+ if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) {
+ const int index = cws->indexOf(m_windowTitleProperty);
+ rc = cws->isChanged(index);
+ }
+ break;
+ default:
+ rc = QDesignerPropertySheet::isChanged(index);
+ break;
+ }
+ return rc;
+}
+
+QWidget *QMdiAreaPropertySheet::currentWindow() const
+{
+ if (const QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), object())) {
+ const int ci = c->currentIndex();
+ if (ci < 0)
+ return 0;
+ return c->widget(ci);
+ }
+ return 0;
+}
+
+QDesignerPropertySheetExtension *QMdiAreaPropertySheet::currentWindowSheet() const
+{
+ QWidget *cw = currentWindow();
+ if (cw == 0)
+ return 0;
+ return qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), cw);
+}
+
+bool QMdiAreaPropertySheet::checkProperty(const QString &propertyName)
+{
+ return mdiAreaProperty(propertyName) == MdiAreaNone;
+}
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/qmdiarea_container.h b/tools/designer/src/components/formeditor/qmdiarea_container.h
new file mode 100644
index 0000000000..462c11f1e7
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qmdiarea_container.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMDIAREA_CONTAINER_H
+#define QMDIAREA_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+
+
+#include <qdesigner_propertysheet_p.h>
+#include <extensionfactory_p.h>
+
+#include <QtGui/QMdiArea>
+#include <QtGui/QWorkspace>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// Container for QMdiArea
+class QMdiAreaContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QMdiAreaContainer(QMdiArea *widget, QObject *parent = 0);
+
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int index);
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+ // Semismart positioning of a new MDI child after cascading
+ static void positionNewMdiChild(const QWidget *area, QWidget *mdiChild);
+
+private:
+ QMdiArea *m_mdiArea;
+};
+
+// PropertySheet for QMdiArea: Fakes window title and name.
+// Also works for a QWorkspace as it relies on the container extension.
+
+class QMdiAreaPropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension)
+public:
+ explicit QMdiAreaPropertySheet(QWidget *mdiArea, QObject *parent = 0);
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual bool reset(int index);
+ virtual bool isEnabled(int index) const;
+ virtual bool isChanged(int index) const;
+ virtual QVariant property(int index) const;
+
+ // Check whether the property is to be saved. Returns false for the page
+ // properties (as the property sheet has no concept of 'stored')
+ static bool checkProperty(const QString &propertyName);
+
+private:
+ const QString m_windowTitleProperty;
+ QWidget *currentWindow() const;
+ QDesignerPropertySheetExtension *currentWindowSheet() const;
+
+ enum MdiAreaProperty { MdiAreaSubWindowName, MdiAreaSubWindowTitle, MdiAreaNone };
+ static MdiAreaProperty mdiAreaProperty(const QString &name);
+};
+
+// Factories
+
+typedef ExtensionFactory<QDesignerContainerExtension, QMdiArea, QMdiAreaContainer> QMdiAreaContainerFactory;
+typedef QDesignerPropertySheetFactory<QMdiArea, QMdiAreaPropertySheet> QMdiAreaPropertySheetFactory;
+typedef QDesignerPropertySheetFactory<QWorkspace, QMdiAreaPropertySheet> QWorkspacePropertySheetFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QMDIAREA_CONTAINER_H
diff --git a/tools/designer/src/components/formeditor/qtbrushmanager.cpp b/tools/designer/src/components/formeditor/qtbrushmanager.cpp
new file mode 100644
index 0000000000..c28c6b9bab
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qtbrushmanager.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtbrushmanager.h"
+#include <QtGui/QPixmap>
+#include <QtGui/QPainter>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QtBrushManagerPrivate
+{
+ QtBrushManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtBrushManager)
+public:
+ QMap<QString, QBrush> theBrushMap;
+ QString theCurrentBrush;
+};
+
+QtBrushManager::QtBrushManager(QObject *parent)
+ : QDesignerBrushManagerInterface(parent)
+{
+ d_ptr = new QtBrushManagerPrivate;
+ d_ptr->q_ptr = this;
+
+}
+
+QtBrushManager::~QtBrushManager()
+{
+ delete d_ptr;
+}
+
+QBrush QtBrushManager::brush(const QString &name) const
+{
+ if (d_ptr->theBrushMap.contains(name))
+ return d_ptr->theBrushMap[name];
+ return QBrush();
+}
+
+QMap<QString, QBrush> QtBrushManager::brushes() const
+{
+ return d_ptr->theBrushMap;
+}
+
+QString QtBrushManager::currentBrush() const
+{
+ return d_ptr->theCurrentBrush;
+}
+
+QString QtBrushManager::addBrush(const QString &name, const QBrush &brush)
+{
+ if (name.isNull())
+ return QString();
+
+ QString newName = name;
+ QString nameBase = newName;
+ int i = 0;
+ while (d_ptr->theBrushMap.contains(newName)) {
+ newName = nameBase + QString::number(++i);
+ }
+ d_ptr->theBrushMap[newName] = brush;
+ emit brushAdded(newName, brush);
+
+ return newName;
+}
+
+void QtBrushManager::removeBrush(const QString &name)
+{
+ if (!d_ptr->theBrushMap.contains(name))
+ return;
+ if (currentBrush() == name)
+ setCurrentBrush(QString());
+ emit brushRemoved(name);
+ d_ptr->theBrushMap.remove(name);
+}
+
+void QtBrushManager::setCurrentBrush(const QString &name)
+{
+ QBrush newBrush;
+ if (!name.isNull()) {
+ if (d_ptr->theBrushMap.contains(name))
+ newBrush = d_ptr->theBrushMap[name];
+ else
+ return;
+ }
+ d_ptr->theCurrentBrush = name;
+ emit currentBrushChanged(name, newBrush);
+}
+
+QPixmap QtBrushManager::brushPixmap(const QBrush &brush) const
+{
+ int w = 64;
+ int h = 64;
+
+ QImage img(w, h, QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(QRect(0, 0, w, h), brush);
+ return QPixmap::fromImage(img);
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/qtbrushmanager.h b/tools/designer/src/components/formeditor/qtbrushmanager.h
new file mode 100644
index 0000000000..f8f1b8ab80
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qtbrushmanager.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTBRUSHMANAGER_H
+#define QTBRUSHMANAGER_H
+
+#include <QtDesigner/QDesignerBrushManagerInterface>
+#include "formeditor_global.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+#include <QtGui/QBrush>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QtBrushManagerPrivate;
+
+class QT_FORMEDITOR_EXPORT QtBrushManager : public QDesignerBrushManagerInterface
+{
+ Q_OBJECT
+public:
+ QtBrushManager(QObject *parent = 0);
+ ~QtBrushManager();
+
+ QBrush brush(const QString &name) const;
+ QMap<QString, QBrush> brushes() const;
+ QString currentBrush() const;
+
+ QString addBrush(const QString &name, const QBrush &brush);
+ void removeBrush(const QString &name);
+ void setCurrentBrush(const QString &name);
+
+ QPixmap brushPixmap(const QBrush &brush) const;
+signals:
+ void brushAdded(const QString &name, const QBrush &brush);
+ void brushRemoved(const QString &name);
+ void currentBrushChanged(const QString &name, const QBrush &brush);
+
+private:
+ QtBrushManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtBrushManager)
+ Q_DISABLE_COPY(QtBrushManager)
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/components/formeditor/qwizard_container.cpp b/tools/designer/src/components/formeditor/qwizard_container.cpp
new file mode 100644
index 0000000000..669f71a19d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qwizard_container.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwizard_container.h"
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QWizard>
+#include <QtGui/QWizardPage>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<int> IdList;
+typedef QList<QWizardPage *> WizardPageList;
+
+namespace qdesigner_internal {
+
+QWizardContainer::QWizardContainer(QWizard *widget, QObject *parent) :
+ QObject(parent),
+ m_wizard(widget)
+{
+}
+
+int QWizardContainer::count() const
+{
+ return m_wizard->pageIds().size();
+}
+
+QWidget *QWizardContainer::widget(int index) const
+{
+ QWidget *rc = 0;
+ if (index >= 0) {
+ const IdList idList = m_wizard->pageIds();
+ if (index < idList.size())
+ rc = m_wizard->page(idList.at(index));
+ }
+ return rc;
+}
+
+int QWizardContainer::currentIndex() const
+{
+ const IdList idList = m_wizard->pageIds();
+ const int currentId = m_wizard->currentId();
+ const int rc = idList.empty() ? -1 : idList.indexOf(currentId);
+ return rc;
+}
+
+void QWizardContainer::setCurrentIndex(int index)
+{
+ if (index < 0 || m_wizard->pageIds().empty())
+ return;
+
+ int currentIdx = currentIndex();
+
+ if (currentIdx == -1) {
+ m_wizard->restart();
+ currentIdx = currentIndex();
+ }
+
+ if (currentIdx == index)
+ return;
+
+ const int d = qAbs(index - currentIdx);
+ if (index > currentIdx) {
+ for (int i = 0; i < d; i++)
+ m_wizard->next();
+ } else {
+ for (int i = 0; i < d; i++)
+ m_wizard->back();
+ }
+}
+
+static const char *msgWrongType = "** WARNING Attempt to add oject that is not of class WizardPage to a QWizard";
+
+void QWizardContainer::addWidget(QWidget *widget)
+{
+ QWizardPage *page = qobject_cast<QWizardPage *>(widget);
+ if (!page) {
+ qWarning("%s", msgWrongType);
+ return;
+ }
+ m_wizard->addPage(page);
+ // Might be -1 after adding the first page
+ setCurrentIndex(m_wizard->pageIds().size() - 1);
+}
+
+void QWizardContainer::insertWidget(int index, QWidget *widget)
+{
+ enum { delta = 5 };
+
+ QWizardPage *newPage = qobject_cast<QWizardPage *>(widget);
+ if (!newPage) {
+ qWarning("%s", msgWrongType);
+ return;
+ }
+
+ const IdList idList = m_wizard->pageIds();
+ const int pageCount = idList.size();
+ if (index >= pageCount) {
+ addWidget(widget);
+ return;
+ }
+
+ // Insert before, reshuffle ids if required
+ const int idBefore = idList.at(index);
+ const int newId = idBefore - 1;
+ const bool needsShuffle =
+ (index == 0 && newId < 0) // At start: QWizard refuses to insert id -1
+ || (index > 0 && idList.at(index - 1) == newId); // In-between
+ if (needsShuffle) {
+ // Create a gap by shuffling pages
+ WizardPageList pageList;
+ pageList.push_back(newPage);
+ for (int i = index; i < pageCount; i++) {
+ pageList.push_back(m_wizard->page(idList.at(i)));
+ m_wizard->removePage(idList.at(i));
+ }
+ int newId = idBefore + delta;
+ const WizardPageList::const_iterator wcend = pageList.constEnd();
+ for (WizardPageList::const_iterator it = pageList.constBegin(); it != wcend; ++it) {
+ m_wizard->setPage(newId, *it);
+ newId += delta;
+ }
+ } else {
+ // Gap found, just insert
+ m_wizard->setPage(newId, newPage);
+ }
+ // Might be at -1 after adding the first page
+ setCurrentIndex(index);
+}
+
+void QWizardContainer::remove(int index)
+{
+ if (index < 0)
+ return;
+
+ const IdList idList = m_wizard->pageIds();
+ if (index >= idList.size())
+ return;
+
+ m_wizard->removePage(idList.at(index));
+ // goto next page, preferably
+ const int newSize = idList.size() - 1;
+ if (index < newSize) {
+ setCurrentIndex(index);
+ } else {
+ if (newSize > 0)
+ setCurrentIndex(newSize - 1);
+ }
+}
+
+// ---------------- QWizardPagePropertySheet
+const char *QWizardPagePropertySheet::pageIdProperty = "pageId";
+
+QWizardPagePropertySheet::QWizardPagePropertySheet(QWizardPage *object, QObject *parent) :
+ QDesignerPropertySheet(object, parent),
+ m_pageIdIndex(createFakeProperty(QLatin1String(pageIdProperty), QString()))
+{
+ setAttribute(m_pageIdIndex, true);
+}
+
+bool QWizardPagePropertySheet::reset(int index)
+{
+ if (index == m_pageIdIndex) {
+ setProperty(index, QString());
+ return true;
+ }
+ return QDesignerPropertySheet::reset(index);
+}
+
+// ---------------- QWizardPropertySheet
+QWizardPropertySheet::QWizardPropertySheet(QWizard *object, QObject *parent) :
+ QDesignerPropertySheet(object, parent),
+ m_startId(QLatin1String("startId"))
+{
+}
+
+bool QWizardPropertySheet::isVisible(int index) const
+{
+ if (propertyName(index) == m_startId)
+ return false;
+ return QDesignerPropertySheet::isVisible(index);
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/qwizard_container.h b/tools/designer/src/components/formeditor/qwizard_container.h
new file mode 100644
index 0000000000..6667a1d44d
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qwizard_container.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWIZARD_CONTAINER_H
+#define QWIZARD_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+
+#include <qdesigner_propertysheet_p.h>
+#include <extensionfactory_p.h>
+
+#include <QtGui/QWizard>
+#include <QtGui/QWizardPage>
+
+QT_BEGIN_NAMESPACE
+
+class QWizardPage;
+
+namespace qdesigner_internal {
+
+// Container for QWizard. Care must be taken to position
+// the QWizard at some valid page after removal/insertion
+// as it is not used to having its pages ripped out.
+class QWizardContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QWizardContainer(QWizard *widget, QObject *parent = 0);
+
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int index);
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ QWizard *m_wizard;
+};
+
+// QWizardPagePropertySheet: Introduces a attribute string fake property
+// "pageId" that allows for specifying enumeration values (uic only).
+// This breaks the pattern of having a "currentSth" property for the
+// container, but was deemed to make sense here since the Page has
+// its own "title" properties.
+class QWizardPagePropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+public:
+ explicit QWizardPagePropertySheet(QWizardPage *object, QObject *parent = 0);
+
+ virtual bool reset(int index);
+
+ static const char *pageIdProperty;
+
+private:
+ const int m_pageIdIndex;
+};
+
+// QWizardPropertySheet: Hides the "startId" property. It cannot be used
+// as QWizard cannot handle setting it as a property before the actual
+// page is added.
+
+class QWizardPropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+public:
+ explicit QWizardPropertySheet(QWizard *object, QObject *parent = 0);
+ virtual bool isVisible(int index) const;
+
+private:
+ const QString m_startId;
+};
+
+// Factories
+typedef QDesignerPropertySheetFactory<QWizard, QWizardPropertySheet> QWizardPropertySheetFactory;
+typedef QDesignerPropertySheetFactory<QWizardPage, QWizardPagePropertySheet> QWizardPagePropertySheetFactory;
+typedef ExtensionFactory<QDesignerContainerExtension, QWizard, QWizardContainer> QWizardContainerFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QWIZARD_CONTAINER_H
diff --git a/tools/designer/src/components/formeditor/qworkspace_container.cpp b/tools/designer/src/components/formeditor/qworkspace_container.cpp
new file mode 100644
index 0000000000..03cb3826b8
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qworkspace_container.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qworkspace_container.h"
+#include "qmdiarea_container.h"
+
+#include <QtGui/QWorkspace>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QWorkspaceContainer::QWorkspaceContainer(QWorkspace *widget, QObject *parent)
+ : QObject(parent),
+ m_workspace(widget)
+{
+}
+
+int QWorkspaceContainer::count() const
+{
+ return m_workspace->windowList(QWorkspace::CreationOrder).count();
+}
+
+QWidget *QWorkspaceContainer::widget(int index) const
+{
+ if (index < 0)
+ return 0;
+ return m_workspace->windowList(QWorkspace::CreationOrder).at(index);
+}
+
+int QWorkspaceContainer::currentIndex() const
+{
+ if (QWidget *aw = m_workspace->activeWindow())
+ return m_workspace->windowList(QWorkspace::CreationOrder).indexOf(aw);
+ return -1;
+}
+
+void QWorkspaceContainer::setCurrentIndex(int index)
+{
+ m_workspace->setActiveWindow(m_workspace->windowList(QWorkspace::CreationOrder).at(index));
+}
+
+void QWorkspaceContainer::addWidget(QWidget *widget)
+{
+ QWidget *frame = m_workspace->addWindow(widget, Qt::Window);
+ frame->show();
+ m_workspace->cascade();
+ QMdiAreaContainer::positionNewMdiChild(m_workspace, frame);
+}
+
+void QWorkspaceContainer::insertWidget(int, QWidget *widget)
+{
+ addWidget(widget);
+}
+
+void QWorkspaceContainer::remove(int /* index */)
+{
+ // nothing to do here, reparenting to formwindow is apparently sufficient
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/qworkspace_container.h b/tools/designer/src/components/formeditor/qworkspace_container.h
new file mode 100644
index 0000000000..fa1e66cfed
--- /dev/null
+++ b/tools/designer/src/components/formeditor/qworkspace_container.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWORKSPACE_CONTAINER_H
+#define QWORKSPACE_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionFactory>
+
+#include <extensionfactory_p.h>
+#include <QtGui/QWorkspace>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QWorkspaceContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit QWorkspaceContainer(QWorkspace *widget, QObject *parent = 0);
+
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int index);
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ QWorkspace *m_workspace;
+};
+
+typedef ExtensionFactory<QDesignerContainerExtension, QWorkspace, QWorkspaceContainer> QWorkspaceContainerFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QWORKSPACE_CONTAINER_H
diff --git a/tools/designer/src/components/formeditor/spacer_propertysheet.cpp b/tools/designer/src/components/formeditor/spacer_propertysheet.cpp
new file mode 100644
index 0000000000..16dd69deb4
--- /dev/null
+++ b/tools/designer/src/components/formeditor/spacer_propertysheet.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "spacer_propertysheet.h"
+#include "qdesigner_widget_p.h"
+#include "formwindow.h"
+#include "spacer_widget_p.h"
+
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal
+{
+SpacerPropertySheet::SpacerPropertySheet(Spacer *object, QObject *parent)
+ : QDesignerPropertySheet(object, parent)
+{
+ clearFakeProperties();
+}
+
+SpacerPropertySheet::~SpacerPropertySheet()
+{
+}
+
+bool SpacerPropertySheet::isVisible(int index) const
+{
+ static const QString spacerGroup = QLatin1String("Spacer");
+ return propertyGroup(index) == spacerGroup;
+}
+
+void SpacerPropertySheet::setProperty(int index, const QVariant &value)
+{
+ QDesignerPropertySheet::setProperty(index, value);
+}
+
+bool SpacerPropertySheet::dynamicPropertiesAllowed() const
+{
+ return false;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/spacer_propertysheet.h b/tools/designer/src/components/formeditor/spacer_propertysheet.h
new file mode 100644
index 0000000000..a83e3d1925
--- /dev/null
+++ b/tools/designer/src/components/formeditor/spacer_propertysheet.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SPACER_PROPERTYSHEET_H
+#define SPACER_PROPERTYSHEET_H
+
+#include <qdesigner_propertysheet_p.h>
+#include <extensionfactory_p.h>
+#include <spacer_widget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class SpacerPropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension)
+public:
+ explicit SpacerPropertySheet(Spacer *object, QObject *parent = 0);
+ virtual ~SpacerPropertySheet();
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual bool isVisible(int index) const;
+
+ virtual bool dynamicPropertiesAllowed() const;
+};
+
+typedef QDesignerPropertySheetFactory<Spacer, SpacerPropertySheet> SpacerPropertySheetFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SPACER_PROPERTYSHEET_H
diff --git a/tools/designer/src/components/formeditor/templateoptionspage.cpp b/tools/designer/src/components/formeditor/templateoptionspage.cpp
new file mode 100644
index 0000000000..dacd0d3272
--- /dev/null
+++ b/tools/designer/src/components/formeditor/templateoptionspage.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "templateoptionspage.h"
+#include "ui_templateoptionspage.h"
+
+#include <shared_settings_p.h>
+#include <iconloader_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <abstractdialoggui_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ----------------- TemplateOptionsWidget
+TemplateOptionsWidget::TemplateOptionsWidget(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QWidget(parent),
+ m_core(core),
+ m_ui(new Ui::TemplateOptionsWidget)
+{
+ m_ui->setupUi(this);
+
+ m_ui->m_addTemplatePathButton->setIcon(
+ qdesigner_internal::createIconSet(QString::fromUtf8("plus.png")));
+ m_ui->m_removeTemplatePathButton->setIcon(
+ qdesigner_internal::createIconSet(QString::fromUtf8("minus.png")));
+
+ connect(m_ui->m_templatePathListWidget, SIGNAL(itemSelectionChanged()),
+ this, SLOT(templatePathSelectionChanged()));
+ connect(m_ui->m_addTemplatePathButton, SIGNAL(clicked()), this, SLOT(addTemplatePath()));
+ connect(m_ui->m_removeTemplatePathButton, SIGNAL(clicked()), this, SLOT(removeTemplatePath()));
+}
+
+TemplateOptionsWidget::~TemplateOptionsWidget()
+{
+ delete m_ui;
+}
+
+QStringList TemplateOptionsWidget::templatePaths() const
+{
+ QStringList rc;
+ const int count = m_ui->m_templatePathListWidget->count();
+ for (int i = 0; i < count; i++) {
+ rc += m_ui->m_templatePathListWidget->item(i)->text();
+ }
+ return rc;
+}
+
+void TemplateOptionsWidget::setTemplatePaths(const QStringList &l)
+{
+ // add paths and select 0
+ m_ui->m_templatePathListWidget->clear();
+ if (l.empty()) {
+ // disable button
+ templatePathSelectionChanged();
+ } else {
+ const QStringList::const_iterator cend = l.constEnd();
+ for (QStringList::const_iterator it = l.constBegin(); it != cend; ++it)
+ m_ui->m_templatePathListWidget->addItem(*it);
+ m_ui->m_templatePathListWidget->setCurrentItem(m_ui->m_templatePathListWidget->item(0));
+ }
+}
+
+void TemplateOptionsWidget::addTemplatePath()
+{
+ const QString templatePath = chooseTemplatePath(m_core, this);
+ if (templatePath.isEmpty())
+ return;
+
+ const QList<QListWidgetItem *> existing
+ = m_ui->m_templatePathListWidget->findItems(templatePath, Qt::MatchExactly);
+ if (!existing.empty())
+ return;
+
+ QListWidgetItem *newItem = new QListWidgetItem(templatePath);
+ m_ui->m_templatePathListWidget->addItem(newItem);
+ m_ui->m_templatePathListWidget->setCurrentItem(newItem);
+}
+
+void TemplateOptionsWidget::removeTemplatePath()
+{
+ const QList<QListWidgetItem *> selectedPaths
+ = m_ui->m_templatePathListWidget->selectedItems();
+ if (selectedPaths.empty())
+ return;
+ delete selectedPaths.front();
+}
+
+void TemplateOptionsWidget::templatePathSelectionChanged()
+{
+ const QList<QListWidgetItem *> selectedPaths = m_ui->m_templatePathListWidget->selectedItems();
+ m_ui->m_removeTemplatePathButton->setEnabled(!selectedPaths.empty());
+}
+
+QString TemplateOptionsWidget::chooseTemplatePath(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ QString rc = core->dialogGui()->getExistingDirectory(parent,
+ tr("Pick a directory to save templates in"));
+ if (rc.isEmpty())
+ return rc;
+
+ if (rc.endsWith(QDir::separator()))
+ rc.remove(rc.size() - 1, 1);
+ return rc;
+}
+
+// ----------------- TemplateOptionsPage
+TemplateOptionsPage::TemplateOptionsPage(QDesignerFormEditorInterface *core) :
+ m_core(core)
+{
+}
+
+QString TemplateOptionsPage::name() const
+{
+ //: Tab in preferences dialog
+ return QCoreApplication::translate("TemplateOptionsPage", "Template Paths");
+}
+
+QWidget *TemplateOptionsPage::createPage(QWidget *parent)
+{
+ m_widget = new TemplateOptionsWidget(m_core, parent);
+ m_initialTemplatePaths = QDesignerSharedSettings(m_core).additionalFormTemplatePaths();
+ m_widget->setTemplatePaths(m_initialTemplatePaths);
+ return m_widget;
+}
+
+void TemplateOptionsPage::apply()
+{
+ if (m_widget) {
+ const QStringList newTemplatePaths = m_widget->templatePaths();
+ if (newTemplatePaths != m_initialTemplatePaths) {
+ QDesignerSharedSettings settings(m_core);
+ settings.setAdditionalFormTemplatePaths(newTemplatePaths);
+ m_initialTemplatePaths = newTemplatePaths;
+ }
+ }
+}
+
+void TemplateOptionsPage::finish()
+{
+}
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/templateoptionspage.h b/tools/designer/src/components/formeditor/templateoptionspage.h
new file mode 100644
index 0000000000..2f17141ae1
--- /dev/null
+++ b/tools/designer/src/components/formeditor/templateoptionspage.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_TEMPLATEOPTIONS_H
+#define QDESIGNER_TEMPLATEOPTIONS_H
+
+#include <QtDesigner/private/abstractoptionspage_p.h>
+
+#include <QtCore/QPointer>
+#include <QtCore/QStringList>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+namespace Ui {
+ class TemplateOptionsWidget;
+}
+
+/* Present the user with a list of form template paths to save
+ * form templates. */
+class TemplateOptionsWidget : public QWidget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(TemplateOptionsWidget)
+public:
+ explicit TemplateOptionsWidget(QDesignerFormEditorInterface *core,
+ QWidget *parent = 0);
+ ~TemplateOptionsWidget();
+
+
+ QStringList templatePaths() const;
+ void setTemplatePaths(const QStringList &l);
+
+ static QString chooseTemplatePath(QDesignerFormEditorInterface *core, QWidget *parent);
+
+private slots:
+ void addTemplatePath();
+ void removeTemplatePath();
+ void templatePathSelectionChanged();
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ Ui::TemplateOptionsWidget *m_ui;
+};
+
+class TemplateOptionsPage : public QDesignerOptionsPageInterface
+{
+ Q_DISABLE_COPY(TemplateOptionsPage)
+public:
+ explicit TemplateOptionsPage(QDesignerFormEditorInterface *core);
+
+ virtual QString name() const;
+ virtual QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ QStringList m_initialTemplatePaths;
+ QPointer<TemplateOptionsWidget> m_widget;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TEMPLATEOPTIONS_H
diff --git a/tools/designer/src/components/formeditor/templateoptionspage.ui b/tools/designer/src/components/formeditor/templateoptionspage.ui
new file mode 100644
index 0000000000..3427ffeb80
--- /dev/null
+++ b/tools/designer/src/components/formeditor/templateoptionspage.ui
@@ -0,0 +1,59 @@
+<ui version="4.0" >
+ <class>qdesigner_internal::TemplateOptionsWidget</class>
+ <widget class="QWidget" name="qdesigner_internal::TemplateOptionsWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>376</width>
+ <height>387</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="m_templatePathGroupBox" >
+ <property name="title" >
+ <string>Additional Template Paths</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="3" >
+ <widget class="QListWidget" name="m_templatePathListWidget" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QToolButton" name="m_addTemplatePathButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QToolButton" name="m_removeTemplatePathButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/components/formeditor/tool_widgeteditor.cpp b/tools/designer/src/components/formeditor/tool_widgeteditor.cpp
new file mode 100644
index 0000000000..3a59543622
--- /dev/null
+++ b/tools/designer/src/components/formeditor/tool_widgeteditor.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::WidgetEditorTool
+*/
+
+#include "tool_widgeteditor.h"
+#include "formwindow.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+
+#include <layoutinfo_p.h>
+#include <qdesigner_dnditem_p.h>
+#include <qdesigner_resource.h>
+
+#include <QtGui/qevent.h>
+#include <QtGui/QAction>
+#include <QtGui/QMainWindow>
+#include <QtGui/QCursor>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+WidgetEditorTool::WidgetEditorTool(FormWindow *formWindow)
+ : QDesignerFormWindowToolInterface(formWindow),
+ m_formWindow(formWindow),
+ m_action(new QAction(tr("Edit Widgets"), this)),
+ m_specialDockDrag(false)
+{
+}
+
+QAction *WidgetEditorTool::action() const
+{
+ return m_action;
+}
+
+WidgetEditorTool::~WidgetEditorTool()
+{
+}
+
+QDesignerFormEditorInterface *WidgetEditorTool::core() const
+{
+ return m_formWindow->core();
+}
+
+QDesignerFormWindowInterface *WidgetEditorTool::formWindow() const
+{
+ return m_formWindow;
+}
+
+bool WidgetEditorTool::mainWindowSeparatorEvent(QWidget *widget, QEvent *event)
+{
+ QMainWindow *mw = qobject_cast<QMainWindow*>(widget);
+ if (mw == 0)
+ return false;
+
+ if (event->type() != QEvent::MouseButtonPress
+ && event->type() != QEvent::MouseMove
+ && event->type() != QEvent::MouseButtonRelease)
+ return false;
+
+ QMouseEvent *e = static_cast<QMouseEvent*>(event);
+
+ if (event->type() == QEvent::MouseButtonPress) {
+ if (mw->isSeparator(e->pos())) {
+ m_separator_drag_mw = mw;
+ return true;
+ }
+ return false;
+ }
+
+ if (event->type() == QEvent::MouseMove)
+ return m_separator_drag_mw == mw;
+
+ if (event->type() == QEvent::MouseButtonRelease) {
+ if (m_separator_drag_mw != mw)
+ return false;
+ m_separator_drag_mw = 0;
+ return true;
+ }
+
+ return false;
+}
+
+bool WidgetEditorTool::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event)
+{
+ const bool passive = core()->widgetFactory()->isPassiveInteractor(widget) != 0
+ || mainWindowSeparatorEvent(widget, event); // separators in QMainWindow
+ // are no longer widgets
+ switch (event->type()) {
+ case QEvent::Resize:
+ case QEvent::Move:
+ m_formWindow->updateSelection(widget);
+ break;
+
+ case QEvent::FocusOut:
+ case QEvent::FocusIn: // Popup cancelled over a form widget: Reset its focus frame
+ return !(passive || widget == m_formWindow || widget == m_formWindow->mainContainer());
+
+ case QEvent::Wheel: // Prevent spinboxes and combos from reacting
+ return !passive;
+
+ case QEvent::KeyPress:
+ return !passive && handleKeyPressEvent(widget, managedWidget, static_cast<QKeyEvent*>(event));
+
+ case QEvent::KeyRelease:
+ return !passive && handleKeyReleaseEvent(widget, managedWidget, static_cast<QKeyEvent*>(event));
+
+ case QEvent::MouseMove:
+ return !passive && handleMouseMoveEvent(widget, managedWidget, static_cast<QMouseEvent*>(event));
+
+ case QEvent::MouseButtonPress:
+ return !passive && handleMousePressEvent(widget, managedWidget, static_cast<QMouseEvent*>(event));
+
+ case QEvent::MouseButtonRelease:
+ return !passive && handleMouseReleaseEvent(widget, managedWidget, static_cast<QMouseEvent*>(event));
+
+ case QEvent::MouseButtonDblClick:
+ return !passive && handleMouseButtonDblClickEvent(widget, managedWidget, static_cast<QMouseEvent*>(event));
+
+ case QEvent::ContextMenu:
+ return !passive && handleContextMenu(widget, managedWidget, static_cast<QContextMenuEvent*>(event));
+
+ case QEvent::DragEnter:
+ return handleDragEnterMoveEvent(widget, managedWidget, static_cast<QDragEnterEvent *>(event), true);
+ case QEvent::DragMove:
+ return handleDragEnterMoveEvent(widget, managedWidget, static_cast<QDragEnterEvent *>(event), false);
+ case QEvent::DragLeave:
+ return handleDragLeaveEvent(widget, managedWidget, static_cast<QDragLeaveEvent *>(event));
+ case QEvent::Drop:
+ return handleDropEvent(widget, managedWidget, static_cast<QDropEvent *>(event));
+ default:
+ break;
+
+ } // end switch
+
+ return false;
+}
+
+// ### remove me
+
+bool WidgetEditorTool::handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e)
+{
+ return m_formWindow->handleContextMenu(widget, managedWidget, e);
+}
+
+bool WidgetEditorTool::handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e)
+{
+ return m_formWindow->handleMouseButtonDblClickEvent(widget, managedWidget, e);
+}
+
+bool WidgetEditorTool::handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e)
+{
+ return m_formWindow->handleMousePressEvent(widget, managedWidget, e);
+}
+
+bool WidgetEditorTool::handleMouseMoveEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e)
+{
+ return m_formWindow->handleMouseMoveEvent(widget, managedWidget, e);
+}
+
+bool WidgetEditorTool::handleMouseReleaseEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e)
+{
+ return m_formWindow->handleMouseReleaseEvent(widget, managedWidget, e);
+}
+
+bool WidgetEditorTool::handleKeyPressEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e)
+{
+ return m_formWindow->handleKeyPressEvent(widget, managedWidget, e);
+}
+
+bool WidgetEditorTool::handleKeyReleaseEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e)
+{
+ return m_formWindow->handleKeyReleaseEvent(widget, managedWidget, e);
+}
+
+bool WidgetEditorTool::handlePaintEvent(QWidget *widget, QWidget *managedWidget, QPaintEvent *e)
+{
+ Q_UNUSED(widget);
+ Q_UNUSED(managedWidget);
+ Q_UNUSED(e);
+
+ return false;
+}
+
+void WidgetEditorTool::detectDockDrag(const QDesignerMimeData *mimeData)
+{
+ m_specialDockDrag = false;
+ if (!mimeData)
+ return;
+
+ QMainWindow *mw = qobject_cast<QMainWindow*>(m_formWindow->mainContainer());
+ if (!mw)
+ return;
+
+ const QList<QDesignerDnDItemInterface*> item_list = mimeData->items();
+
+ foreach (QDesignerDnDItemInterface *item, item_list) {
+ if (item->decoration() && item->decoration()->property("_q_dockDrag").toBool())
+ m_specialDockDrag = true;
+
+ }
+}
+
+bool WidgetEditorTool::handleDragEnterMoveEvent(QWidget *widget, QWidget * /*managedWidget*/, QDragMoveEvent *e, bool isEnter)
+{
+ const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(e->mimeData());
+ if (!mimeData)
+ return false;
+
+ if (!m_formWindow->hasFeature(QDesignerFormWindowInterface::EditFeature)) {
+ e->ignore();
+ return true;
+ }
+
+ if (isEnter)
+ detectDockDrag(mimeData);
+
+
+ QPoint globalPos = QPoint(0, 0);
+ if (m_specialDockDrag) {
+ m_lastDropTarget = 0;
+ QMainWindow *mw = qobject_cast<QMainWindow*>(m_formWindow->mainContainer());
+ if (mw)
+ m_lastDropTarget = mw->centralWidget();
+ } else {
+ // If custom widgets have acceptDrops=true, the event occurs for them
+ const QPoint formPos = widget != m_formWindow ? widget->mapTo(m_formWindow, e->pos()) : e->pos();
+ globalPos = m_formWindow->mapToGlobal(formPos);
+ const FormWindowBase::WidgetUnderMouseMode wum = mimeData->items().size() == 1 ? FormWindowBase::FindSingleSelectionDropTarget : FormWindowBase::FindMultiSelectionDropTarget;
+ QWidget *dropTarget = m_formWindow->widgetUnderMouse(formPos, wum);
+ if (m_lastDropTarget && dropTarget != m_lastDropTarget)
+ m_formWindow->highlightWidget(m_lastDropTarget, m_lastDropTarget->mapFromGlobal(globalPos), FormWindow::Restore);
+ m_lastDropTarget = dropTarget;
+ }
+
+ if (m_lastDropTarget)
+ m_formWindow->highlightWidget(m_lastDropTarget, m_lastDropTarget->mapFromGlobal(globalPos), FormWindow::Highlight);
+
+ if (isEnter || m_lastDropTarget)
+ mimeData->acceptEvent(e);
+ else
+ e->ignore();
+ return true;
+}
+
+bool WidgetEditorTool::handleDropEvent(QWidget *widget, QWidget *, QDropEvent *e)
+{
+ const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(e->mimeData());
+ if (!mimeData)
+ return false;
+
+ if (!m_lastDropTarget ||
+ !m_formWindow->hasFeature(QDesignerFormWindowInterface::EditFeature)) {
+ e->ignore();
+ return true;
+ }
+ // FormWindow determines the position from the decoration.
+ const QPoint globalPos = widget->mapToGlobal(e->pos());
+ mimeData->moveDecoration(globalPos);
+ if (m_specialDockDrag) {
+ if (!m_formWindow->dropDockWidget(mimeData->items().at(0), globalPos)) {
+ e->ignore();
+ return true;
+ }
+ } else if (!m_formWindow->dropWidgets(mimeData->items(), m_lastDropTarget, globalPos)) {
+ e->ignore();
+ return true;
+ }
+ mimeData->acceptEvent(e);
+ return true;
+}
+
+bool WidgetEditorTool::restoreDropHighlighting()
+{
+ if (!m_lastDropTarget)
+ return false;
+
+ m_formWindow->highlightWidget(m_lastDropTarget, m_lastDropTarget->mapFromGlobal(QCursor::pos()), FormWindow::Restore);
+ m_lastDropTarget = 0;
+ return true;
+}
+
+bool WidgetEditorTool::handleDragLeaveEvent(QWidget *, QWidget *, QDragLeaveEvent *event)
+{
+ if (restoreDropHighlighting()) {
+ event->accept();
+ return true;
+ }
+ return false;
+}
+
+QWidget *WidgetEditorTool::editor() const
+{
+ Q_ASSERT(formWindow() != 0);
+ return formWindow()->mainContainer();
+}
+
+void WidgetEditorTool::activated()
+{
+ if (core()->widgetBox())
+ core()->widgetBox()->setEnabled(true);
+
+ if (m_formWindow == 0)
+ return;
+
+ QList<QWidget*> sel = m_formWindow->selectedWidgets();
+ foreach (QWidget *w, sel)
+ m_formWindow->raiseSelection(w);
+}
+
+void WidgetEditorTool::deactivated()
+{
+ if (core()->widgetBox())
+ core()->widgetBox()->setEnabled(false);
+
+ if (m_formWindow == 0)
+ return;
+
+ m_formWindow->clearSelection();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/tool_widgeteditor.h b/tools/designer/src/components/formeditor/tool_widgeteditor.h
new file mode 100644
index 0000000000..58df974d08
--- /dev/null
+++ b/tools/designer/src/components/formeditor/tool_widgeteditor.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOOL_WIDGETEDITOR_H
+#define TOOL_WIDGETEDITOR_H
+
+#include <QtDesigner/QDesignerFormWindowToolInterface>
+
+#include <QtGui/qevent.h>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QMainWindow;
+
+namespace qdesigner_internal {
+
+class FormWindow;
+class QDesignerMimeData;
+
+class WidgetEditorTool: public QDesignerFormWindowToolInterface
+{
+ Q_OBJECT
+public:
+ explicit WidgetEditorTool(FormWindow *formWindow);
+ virtual ~WidgetEditorTool();
+
+ virtual QDesignerFormEditorInterface *core() const;
+ virtual QDesignerFormWindowInterface *formWindow() const;
+ virtual QWidget *editor() const;
+ virtual QAction *action() const;
+
+ virtual void activated();
+ virtual void deactivated();
+
+ virtual bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event);
+
+ bool handleContextMenu(QWidget *widget, QWidget *managedWidget, QContextMenuEvent *e);
+ bool handleMouseButtonDblClickEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleMousePressEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleMouseMoveEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleMouseReleaseEvent(QWidget *widget, QWidget *managedWidget, QMouseEvent *e);
+ bool handleKeyPressEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e);
+ bool handleKeyReleaseEvent(QWidget *widget, QWidget *managedWidget, QKeyEvent *e);
+ bool handlePaintEvent(QWidget *widget, QWidget *managedWidget, QPaintEvent *e);
+
+ bool handleDragEnterMoveEvent(QWidget *widget, QWidget *managedWidget, QDragMoveEvent *e, bool isEnter);
+ bool handleDragLeaveEvent(QWidget *widget, QWidget *managedWidget, QDragLeaveEvent *e);
+ bool handleDropEvent(QWidget *widget, QWidget *managedWidget, QDropEvent *e);
+
+private:
+ bool restoreDropHighlighting();
+ void detectDockDrag(const QDesignerMimeData *mimeData);
+
+ FormWindow *m_formWindow;
+ QAction *m_action;
+
+ bool mainWindowSeparatorEvent(QWidget *widget, QEvent *event);
+ QPointer<QMainWindow> m_separator_drag_mw;
+ QPointer<QWidget> m_lastDropTarget;
+ bool m_specialDockDrag;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TOOL_WIDGETEDITOR_H
diff --git a/tools/designer/src/components/formeditor/widgetselection.cpp b/tools/designer/src/components/formeditor/widgetselection.cpp
new file mode 100644
index 0000000000..ce103ecef5
--- /dev/null
+++ b/tools/designer/src/components/formeditor/widgetselection.cpp
@@ -0,0 +1,746 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetselection.h"
+#include "formwindow.h"
+#include "formwindowmanager.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+// shared
+#include <qdesigner_command_p.h>
+#include <qdesigner_propertycommand_p.h>
+#include <layout_p.h>
+#include <layoutinfo_p.h>
+#include <formwindowbase_p.h>
+#include <grid_p.h>
+
+#include <QtGui/QMenu>
+#include <QtGui/QWidget>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QStylePainter>
+#include <QtGui/QGridLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/QStyleOptionToolButton>
+#include <QtGui/QApplication>
+
+#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+enum { debugWidgetSelection = 0 };
+
+// Return the layout the widget is in
+template <class Layout>
+static inline Layout *managedLayoutOf(const QDesignerFormEditorInterface *core,
+ QWidget *w,
+ const Layout * /* vs6dummy */ = 0)
+{
+ if (QWidget *p = w->parentWidget())
+ if (QLayout *l = LayoutInfo::managedLayout(core, p))
+ return qobject_cast<Layout*>(l);
+ return 0;
+}
+
+// ----------- WidgetHandle
+WidgetHandle::WidgetHandle(FormWindow *parent, WidgetHandle::Type t, WidgetSelection *s) :
+ InvisibleWidget(parent->mainContainer()),
+ m_widget(0),
+ m_type(t),
+ m_formWindow( parent),
+ m_sel(s),
+ m_active(true)
+{
+ setMouseTracking(false);
+ setAutoFillBackground(true);
+
+ setBackgroundRole(m_active ? QPalette::Text : QPalette::Dark);
+ setFixedSize(6, 6);
+
+ updateCursor();
+}
+
+void WidgetHandle::updateCursor()
+{
+#ifndef QT_NO_CURSOR
+ if (!m_active) {
+ setCursor(Qt::ArrowCursor);
+ return;
+ }
+
+ switch (m_type) {
+ case LeftTop:
+ setCursor(Qt::SizeFDiagCursor);
+ break;
+ case Top:
+ setCursor(Qt::SizeVerCursor);
+ break;
+ case RightTop:
+ setCursor(Qt::SizeBDiagCursor);
+ break;
+ case Right:
+ setCursor(Qt::SizeHorCursor);
+ break;
+ case RightBottom:
+ setCursor(Qt::SizeFDiagCursor);
+ break;
+ case Bottom:
+ setCursor(Qt::SizeVerCursor);
+ break;
+ case LeftBottom:
+ setCursor(Qt::SizeBDiagCursor);
+ break;
+ case Left:
+ setCursor(Qt::SizeHorCursor);
+ break;
+ default:
+ Q_ASSERT(0);
+ }
+#endif
+}
+
+QDesignerFormEditorInterface *WidgetHandle::core() const
+{
+ if (m_formWindow)
+ return m_formWindow->core();
+
+ return 0;
+}
+
+void WidgetHandle::setActive(bool a)
+{
+ m_active = a;
+ setBackgroundRole(m_active ? QPalette::Text : QPalette::Dark);
+ updateCursor();
+}
+
+void WidgetHandle::setWidget(QWidget *w)
+{
+ m_widget = w;
+}
+
+void WidgetHandle::paintEvent(QPaintEvent *)
+{
+ QDesignerFormWindowManagerInterface *m = m_formWindow->core()->formWindowManager();
+
+ QStylePainter p(this);
+ if (m_formWindow->currentWidget() == m_widget) {
+ p.setPen(m->activeFormWindow() == m_formWindow ? Qt::blue : Qt::red);
+ p.drawRect(0, 0, width() - 1, height() - 1);
+ }
+}
+
+void WidgetHandle::mousePressEvent(QMouseEvent *e)
+{
+ e->accept();
+
+ if (!m_formWindow->hasFeature(FormWindow::EditFeature))
+ return;
+
+ if (!(m_widget && e->button() == Qt::LeftButton))
+ return;
+
+ if (!(m_active))
+ return;
+
+ QWidget *container = m_widget->parentWidget();
+
+ m_origPressPos = container->mapFromGlobal(e->globalPos());
+ m_geom = m_origGeom = m_widget->geometry();
+}
+
+void WidgetHandle::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!(m_widget && m_active && e->buttons() & Qt::LeftButton))
+ return;
+
+ e->accept();
+
+ QWidget *container = m_widget->parentWidget();
+
+ const QPoint rp = container->mapFromGlobal(e->globalPos());
+ const QPoint d = rp - m_origPressPos;
+
+ const QRect pr = container->rect();
+
+ qdesigner_internal::Grid grid;
+ if (const qdesigner_internal::FormWindowBase *fwb = qobject_cast<const qdesigner_internal::FormWindowBase*>(m_formWindow))
+ grid = fwb->designerGrid();
+
+ switch (m_type) {
+
+ case LeftTop: {
+ if (rp.x() > pr.width() - 2 * width() || rp.y() > pr.height() - 2 * height())
+ return;
+
+ int w = m_origGeom.width() - d.x();
+ m_geom.setWidth(w);
+ w = grid.widgetHandleAdjustX(w);
+
+ int h = m_origGeom.height() - d.y();
+ m_geom.setHeight(h);
+ h = grid.widgetHandleAdjustY(h);
+
+ const int dx = m_widget->width() - w;
+ const int dy = m_widget->height() - h;
+
+ trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y() + dy, w, h);
+ } break;
+
+ case Top: {
+ if (rp.y() > pr.height() - 2 * height())
+ return;
+
+ int h = m_origGeom.height() - d.y();
+ m_geom.setHeight(h);
+ h = grid.widgetHandleAdjustY(h);
+
+ const int dy = m_widget->height() - h;
+ trySetGeometry(m_widget, m_widget->x(), m_widget->y() + dy, m_widget->width(), h);
+ } break;
+
+ case RightTop: {
+ if (rp.x() < 2 * width() || rp.y() > pr.height() - 2 * height())
+ return;
+
+ int h = m_origGeom.height() - d.y();
+ m_geom.setHeight(h);
+ h = grid.widgetHandleAdjustY(h);
+
+ const int dy = m_widget->height() - h;
+
+ int w = m_origGeom.width() + d.x();
+ m_geom.setWidth(w);
+ w = grid.widgetHandleAdjustX(w);
+
+ trySetGeometry(m_widget, m_widget->x(), m_widget->y() + dy, w, h);
+ } break;
+
+ case Right: {
+ if (rp.x() < 2 * width())
+ return;
+
+ int w = m_origGeom.width() + d.x();
+ m_geom.setWidth(w);
+ w = grid.widgetHandleAdjustX(w);
+
+ tryResize(m_widget, w, m_widget->height());
+ } break;
+
+ case RightBottom: {
+ if (rp.x() < 2 * width() || rp.y() < 2 * height())
+ return;
+
+ int w = m_origGeom.width() + d.x();
+ m_geom.setWidth(w);
+ w = grid.widgetHandleAdjustX(w);
+
+ int h = m_origGeom.height() + d.y();
+ m_geom.setHeight(h);
+ h = grid.widgetHandleAdjustY(h);
+
+ tryResize(m_widget, w, h);
+ } break;
+
+ case Bottom: {
+ if (rp.y() < 2 * height())
+ return;
+
+ int h = m_origGeom.height() + d.y();
+ m_geom.setHeight(h);
+ h = grid.widgetHandleAdjustY(h);
+
+ tryResize(m_widget, m_widget->width(), h);
+ } break;
+
+ case LeftBottom: {
+ if (rp.x() > pr.width() - 2 * width() || rp.y() < 2 * height())
+ return;
+
+ int w = m_origGeom.width() - d.x();
+ m_geom.setWidth(w);
+ w = grid.widgetHandleAdjustX(w);
+
+ int h = m_origGeom.height() + d.y();
+ m_geom.setHeight(h);
+ h = grid.widgetHandleAdjustY(h);
+
+ int dx = m_widget->width() - w;
+
+ trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y(), w, h);
+ } break;
+
+ case Left: {
+ if (rp.x() > pr.width() - 2 * width())
+ return;
+
+ int w = m_origGeom.width() - d.x();
+ m_geom.setWidth(w);
+ w = grid.widgetHandleAdjustX(w);
+
+ const int dx = m_widget->width() - w;
+
+ trySetGeometry(m_widget, m_widget->x() + dx, m_widget->y(), w, m_widget->height());
+ } break;
+
+ default: break;
+
+ } // end switch
+
+ m_sel->updateGeometry();
+
+ if (LayoutInfo::layoutType(m_formWindow->core(), m_widget) != LayoutInfo::NoLayout)
+ m_formWindow->updateChildSelections(m_widget);
+}
+
+void WidgetHandle::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton || !m_active)
+ return;
+
+ e->accept();
+
+ if (!m_formWindow->hasFeature(FormWindow::EditFeature))
+ return;
+
+ switch (WidgetSelection::widgetState(m_formWindow->core(), m_widget)) {
+ case WidgetSelection::UnlaidOut:
+ if (m_geom != m_widget->geometry()) {
+ SetPropertyCommand *cmd = new SetPropertyCommand(m_formWindow);
+ cmd->init(m_widget, QLatin1String("geometry"), m_widget->geometry());
+ cmd->setOldValue(m_origGeom);
+ m_formWindow->commandHistory()->push(cmd);
+ m_formWindow->emitSelectionChanged();
+ }
+ break;
+ case WidgetSelection::LaidOut:
+ break;
+ case WidgetSelection::ManagedGridLayout:
+ changeGridLayoutItemSpan();
+ break;
+ case WidgetSelection::ManagedFormLayout:
+ changeFormLayoutItemSpan();
+ break;
+ }
+}
+
+// Match the left/right widget handle mouse movements to form layout span-changing operations
+static inline int formLayoutLeftHandleOperation(int dx, unsigned possibleOperations)
+{
+ if (dx < 0) {
+ if (possibleOperations & ChangeFormLayoutItemRoleCommand::FieldToSpanning)
+ return ChangeFormLayoutItemRoleCommand::FieldToSpanning;
+ return 0;
+ }
+ if (possibleOperations & ChangeFormLayoutItemRoleCommand::SpanningToField)
+ return ChangeFormLayoutItemRoleCommand::SpanningToField;
+ return 0;
+}
+
+static inline int formLayoutRightHandleOperation(int dx, unsigned possibleOperations)
+{
+ if (dx < 0) {
+ if (possibleOperations & ChangeFormLayoutItemRoleCommand::SpanningToLabel)
+ return ChangeFormLayoutItemRoleCommand::SpanningToLabel;
+ return 0;
+ }
+ if (possibleOperations & ChangeFormLayoutItemRoleCommand::LabelToSpanning)
+ return ChangeFormLayoutItemRoleCommand::LabelToSpanning;
+ return 0;
+}
+
+// Change form layout item horizontal span
+void WidgetHandle::changeFormLayoutItemSpan()
+{
+ QUndoCommand *cmd = 0;
+ // Figure out command according to the movement
+ const int dx = m_widget->geometry().center().x() - m_origGeom.center().x();
+ if (qAbs(dx) >= QApplication::startDragDistance()) {
+ int operation = 0;
+ if (const unsigned possibleOperations = ChangeFormLayoutItemRoleCommand::possibleOperations(m_formWindow->core(), m_widget)) {
+ switch (m_type) {
+ case WidgetHandle::Left:
+ operation = formLayoutLeftHandleOperation(dx, possibleOperations);
+ break;
+ case WidgetHandle::Right:
+ operation = formLayoutRightHandleOperation(dx, possibleOperations);
+ break;
+ default:
+ break;
+ }
+ if (operation) {
+ ChangeFormLayoutItemRoleCommand *fcmd = new ChangeFormLayoutItemRoleCommand(m_formWindow);
+ fcmd->init(m_widget, static_cast<ChangeFormLayoutItemRoleCommand::Operation>(operation));
+ cmd = fcmd;
+ }
+ }
+ }
+ if (cmd) {
+ m_formWindow->commandHistory()->push(cmd);
+ } else {
+ // Cancelled/Invalid. Restore the size of the widget.
+ if (QFormLayout *form = managedLayoutOf<QFormLayout>(m_formWindow->core(), m_widget)) {
+ form->invalidate();
+ form->activate();
+ m_formWindow->clearSelection(false);
+ m_formWindow->selectWidget(m_widget);
+ }
+ }
+}
+
+void WidgetHandle::changeGridLayoutItemSpan()
+{
+ QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), m_widget->parentWidget());
+ if (!deco)
+ return;
+ QGridLayout *grid = managedLayoutOf<QGridLayout>(m_formWindow->core(), m_widget);
+ if (!grid)
+ return;
+
+ const QSize size = m_widget->parentWidget()->size();
+
+ const int index = deco->indexOf(m_widget);
+ const QRect info = deco->itemInfo(index);
+ const int top = deco->findItemAt(info.top() - 1, info.left());
+ const int left = deco->findItemAt(info.top(), info.left() - 1);
+ const int bottom = deco->findItemAt(info.bottom() + 1, info.left());
+ const int right = deco->findItemAt(info.top(), info.right() + 1);
+
+ const QPoint pt = m_origGeom.center() - m_widget->geometry().center();
+
+ ChangeLayoutItemGeometry *cmd = 0;
+
+ switch (m_type) {
+ default:
+ break;
+
+ case WidgetHandle::Top: {
+ if (pt.y() < 0 && info.height() > 1) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y() + 1, info.x(), info.height() - 1, info.width());
+ } else if (pt.y() > 0 && top != -1 && grid->itemAt(top)->spacerItem()) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y() - 1, info.x(), info.height() + 1, info.width());
+ }
+ }
+ break;
+
+ case WidgetHandle::Left: {
+ if (pt.x() < 0 && info.width() > 1) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y(), info.x() + 1, info.height(), info.width() - 1);
+ } else if (pt.x() > 0 && left != -1 && grid->itemAt(left)->spacerItem()) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y(), info.x() - 1, info.height(), info.width() + 1);
+ }
+ }
+ break;
+
+ case WidgetHandle::Right: {
+ if (pt.x() > 0 && info.width() > 1) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y(), info.x(), info.height(), info.width() - 1);
+ } else if (pt.x() < 0 && right != -1 && grid->itemAt(right)->spacerItem()) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y(), info.x(), info.height(), info.width() + 1);
+ }
+ }
+ break;
+
+ case WidgetHandle::Bottom: {
+ if (pt.y() > 0 && info.width() > 1) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y(), info.x(), info.height() - 1, info.width());
+ } else if (pt.y() < 0 && bottom != -1 && grid->itemAt(bottom)->spacerItem()) {
+ cmd = new ChangeLayoutItemGeometry(m_formWindow);
+ cmd->init(m_widget, info.y(), info.x(), info.height() + 1, info.width());
+ }
+ }
+ break;
+ }
+
+ if (cmd != 0) {
+ m_formWindow->commandHistory()->push(cmd);
+ } else {
+ grid->invalidate();
+ grid->activate();
+ m_formWindow->clearSelection(false);
+ m_formWindow->selectWidget(m_widget);
+ }
+}
+
+void WidgetHandle::trySetGeometry(QWidget *w, int x, int y, int width, int height)
+{
+ if (!m_formWindow->hasFeature(FormWindow::EditFeature))
+ return;
+
+ int minw = w->minimumSize().width();
+ minw = qMax(minw, 2 * m_formWindow->grid().x());
+
+ int minh = w->minimumSize().height();
+ minh = qMax(minh, 2 * m_formWindow->grid().y());
+
+ if (qMax(minw, width) > w->maximumWidth() ||
+ qMax(minh, height) > w->maximumHeight())
+ return;
+
+ if (width < minw && x != w->x())
+ x -= minw - width;
+
+ if (height < minh && y != w->y())
+ y -= minh - height;
+
+ w->setGeometry(x, y, qMax(minw, width), qMax(minh, height));
+}
+
+void WidgetHandle::tryResize(QWidget *w, int width, int height)
+{
+ int minw = w->minimumSize().width();
+ minw = qMax(minw, 16);
+
+ int minh = w->minimumSize().height();
+ minh = qMax(minh, 16);
+
+ w->resize(qMax(minw, width), qMax(minh, height));
+}
+
+// ------------------ WidgetSelection
+
+WidgetSelection::WidgetState WidgetSelection::widgetState(const QDesignerFormEditorInterface *core, QWidget *w)
+{
+ bool isManaged;
+ const LayoutInfo::Type lt = LayoutInfo::laidoutWidgetType(core, w, &isManaged);
+ if (lt == LayoutInfo::NoLayout)
+ return UnlaidOut;
+ if (!isManaged)
+ return LaidOut;
+ switch (lt) {
+ case LayoutInfo::Grid:
+ return ManagedGridLayout;
+ case LayoutInfo::Form:
+ return ManagedFormLayout;
+ default:
+ break;
+ }
+ return LaidOut;
+}
+
+WidgetSelection::WidgetSelection(FormWindow *parent) :
+ m_widget(0),
+ m_formWindow(parent)
+{
+ for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
+ m_handles[i] = new WidgetHandle(m_formWindow, static_cast<WidgetHandle::Type>(i), this);
+ hide();
+}
+
+void WidgetSelection::setWidget(QWidget *w)
+{
+ if (m_widget != 0)
+ m_widget->removeEventFilter(this);
+
+ if (w == 0) {
+ hide();
+ m_widget = 0;
+ return;
+ }
+
+ m_widget = w;
+
+ m_widget->installEventFilter(this);
+
+ updateActive();
+
+ updateGeometry();
+ show();
+}
+
+void WidgetSelection::updateActive()
+{
+ const WidgetState ws = widgetState(m_formWindow->core(), m_widget);
+ bool active[WidgetHandle::TypeCount];
+ qFill(active, active + WidgetHandle::TypeCount, false);
+ // Determine active handles
+ switch (ws) {
+ case UnlaidOut:
+ qFill(active, active + WidgetHandle::TypeCount, true);
+ break;
+ case ManagedGridLayout: // Grid: Allow changing span
+ active[WidgetHandle::Left] = active[WidgetHandle::Top] = active[WidgetHandle::Right] = active[WidgetHandle::Bottom] = true;
+ break;
+ case ManagedFormLayout: // Form: Allow changing column span
+ if (const unsigned operation = ChangeFormLayoutItemRoleCommand::possibleOperations(m_formWindow->core(), m_widget)) {
+ active[WidgetHandle::Left] = operation & (ChangeFormLayoutItemRoleCommand::SpanningToField|ChangeFormLayoutItemRoleCommand::FieldToSpanning);
+ active[WidgetHandle::Right] = operation & (ChangeFormLayoutItemRoleCommand::SpanningToLabel|ChangeFormLayoutItemRoleCommand::LabelToSpanning);
+ }
+ break;
+ default:
+ break;
+ }
+
+ for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i)
+ if (WidgetHandle *h = m_handles[i]) {
+ h->setWidget(m_widget);
+ h->setActive(active[i]);
+ }
+}
+
+bool WidgetSelection::isUsed() const
+{
+ return m_widget != 0;
+}
+
+void WidgetSelection::updateGeometry()
+{
+ if (!m_widget || !m_widget->parentWidget())
+ return;
+
+ QPoint p = m_widget->parentWidget()->mapToGlobal(m_widget->pos());
+ p = m_formWindow->mapFromGlobal(p);
+ const QRect r(p, m_widget->size());
+
+ const int w = 6;
+ const int h = 6;
+
+ for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
+ WidgetHandle *hndl = m_handles[ i ];
+ if (!hndl)
+ continue;
+ switch (i) {
+ case WidgetHandle::LeftTop:
+ hndl->move(r.x() - w / 2, r.y() - h / 2);
+ break;
+ case WidgetHandle::Top:
+ hndl->move(r.x() + r.width() / 2 - w / 2, r.y() - h / 2);
+ break;
+ case WidgetHandle::RightTop:
+ hndl->move(r.x() + r.width() - w / 2, r.y() - h / 2);
+ break;
+ case WidgetHandle::Right:
+ hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() / 2 - h / 2);
+ break;
+ case WidgetHandle::RightBottom:
+ hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() - h / 2);
+ break;
+ case WidgetHandle::Bottom:
+ hndl->move(r.x() + r.width() / 2 - w / 2, r.y() + r.height() - h / 2);
+ break;
+ case WidgetHandle::LeftBottom:
+ hndl->move(r.x() - w / 2, r.y() + r.height() - h / 2);
+ break;
+ case WidgetHandle::Left:
+ hndl->move(r.x() - w / 2, r.y() + r.height() / 2 - h / 2);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void WidgetSelection::hide()
+{
+ for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
+ WidgetHandle *h = m_handles[ i ];
+ if (h)
+ h->hide();
+ }
+}
+
+void WidgetSelection::show()
+{
+ for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
+ WidgetHandle *h = m_handles[ i ];
+ if (h) {
+ h->show();
+ h->raise();
+ }
+ }
+}
+
+void WidgetSelection::update()
+{
+ for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
+ WidgetHandle *h = m_handles[ i ];
+ if (h)
+ h->update();
+ }
+}
+
+QWidget *WidgetSelection::widget() const
+{
+ return m_widget;
+}
+
+QDesignerFormEditorInterface *WidgetSelection::core() const
+{
+ if (m_formWindow)
+ return m_formWindow->core();
+
+ return 0;
+}
+
+bool WidgetSelection::eventFilter(QObject *object, QEvent *event)
+{
+ if (object != widget())
+ return false;
+
+ switch (event->type()) {
+ default: break;
+
+ case QEvent::Move:
+ case QEvent::Resize:
+ updateGeometry();
+ break;
+ case QEvent::ZOrderChange:
+ show();
+ break;
+ } // end switch
+
+ return false;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/formeditor/widgetselection.h b/tools/designer/src/components/formeditor/widgetselection.h
new file mode 100644
index 0000000000..9099e895c6
--- /dev/null
+++ b/tools/designer/src/components/formeditor/widgetselection.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETSELECTION_H
+#define WIDGETSELECTION_H
+
+#include "formeditor_global.h"
+#include <invisible_widget_p.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QMouseEvent;
+class QPaintEvent;
+
+namespace qdesigner_internal {
+
+class FormWindow;
+class WidgetSelection;
+
+class QT_FORMEDITOR_EXPORT WidgetHandle: public InvisibleWidget
+{
+ Q_OBJECT
+public:
+ enum Type
+ {
+ LeftTop,
+ Top,
+ RightTop,
+ Right,
+ RightBottom,
+ Bottom,
+ LeftBottom,
+ Left,
+
+ TypeCount
+ };
+
+ WidgetHandle(FormWindow *parent, Type t, WidgetSelection *s);
+ void setWidget(QWidget *w);
+ void setActive(bool a);
+ void updateCursor();
+
+ void setEnabled(bool) {}
+
+ QDesignerFormEditorInterface *core() const;
+
+protected:
+ void paintEvent(QPaintEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+
+private:
+ void changeGridLayoutItemSpan();
+ void changeFormLayoutItemSpan();
+ void trySetGeometry(QWidget *w, int x, int y, int width, int height);
+ void tryResize(QWidget *w, int width, int height);
+
+private:
+ QWidget *m_widget;
+ const Type m_type;
+ QPoint m_origPressPos;
+ FormWindow *m_formWindow;
+ WidgetSelection *m_sel;
+ QRect m_geom, m_origGeom;
+ bool m_active;
+};
+
+class QT_FORMEDITOR_EXPORT WidgetSelection: public QObject
+{
+ Q_OBJECT
+public:
+ WidgetSelection(FormWindow *parent);
+
+ void setWidget(QWidget *w);
+ bool isUsed() const;
+
+ void updateActive();
+ void updateGeometry();
+ void hide();
+ void show();
+ void update();
+
+ QWidget *widget() const;
+
+ QDesignerFormEditorInterface *core() const;
+
+ virtual bool eventFilter(QObject *object, QEvent *event);
+
+ enum WidgetState { UnlaidOut, LaidOut, ManagedGridLayout, ManagedFormLayout };
+ static WidgetState widgetState(const QDesignerFormEditorInterface *core, QWidget *w);
+
+private:
+ WidgetHandle *m_handles[WidgetHandle::TypeCount];
+ QPointer<QWidget> m_widget;
+ FormWindow *m_formWindow;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETSELECTION_H
diff --git a/tools/designer/src/components/lib/lib.pro b/tools/designer/src/components/lib/lib.pro
new file mode 100644
index 0000000000..4515b66351
--- /dev/null
+++ b/tools/designer/src/components/lib/lib.pro
@@ -0,0 +1,74 @@
+TEMPLATE = lib
+TARGET = QtDesignerComponents
+contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
+CONFIG += qt depend_prl no_objective_c designer
+win32|mac: CONFIG += debug_and_release
+QTDIR_build {
+ DESTDIR = $$QT_BUILD_TREE/lib
+ !wince*:DLLDESTDIR = $$QT_BUILD_TREE/bin
+}
+
+# QtDesignerComponents uses
+DEFINES += QT_STATICPLUGIN
+
+isEmpty(QT_MAJOR_VERSION) {
+ VERSION=4.3.0
+} else {
+ VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}
+}
+
+include(../../../../../src/qt_targets.pri)
+QMAKE_TARGET_PRODUCT = Designer
+QMAKE_TARGET_DESCRIPTION = Graphical user interface designer.
+
+#load up the headers info
+CONFIG += qt_install_headers
+HEADERS_PRI = $$QT_BUILD_TREE/include/QtDesigner/headers.pri
+include($$HEADERS_PRI)|clear(HEADERS_PRI)
+
+#mac frameworks
+mac:!static:contains(QT_CONFIG, qt_framework) {
+ QMAKE_FRAMEWORK_BUNDLE_NAME = $$TARGET
+ CONFIG += lib_bundle qt_no_framework_direct_includes qt_framework
+ CONFIG(debug, debug|release):!build_pass:CONFIG += build_all
+}
+
+SOURCES += qdesigner_components.cpp
+
+!contains(CONFIG, static) {
+ DEFINES += QDESIGNER_COMPONENTS_LIBRARY
+ CONFIG += dll
+ LIBS += -lQtDesigner
+} else {
+ DEFINES += QT_DESIGNER_STATIC
+}
+
+INCLUDEPATH += . .. \
+ $$QT_SOURCE_TREE/tools/designer/src/lib/components \
+ $$QT_SOURCE_TREE/tools/designer/src/lib/sdk \
+ $$QT_SOURCE_TREE/tools/designer/src/lib/extension \
+ $$QT_SOURCE_TREE/tools/designer/src/lib/uilib \
+ $$QT_SOURCE_TREE/tools/designer/src/lib/shared
+
+include(../propertyeditor/propertyeditor.pri)
+include(../objectinspector/objectinspector.pri)
+include(../signalsloteditor/signalsloteditor.pri)
+include(../formeditor/formeditor.pri)
+include(../widgetbox/widgetbox.pri)
+include(../buddyeditor/buddyeditor.pri)
+include(../taskmenu/taskmenu.pri)
+include(../tabordereditor/tabordereditor.pri)
+
+PRECOMPILED_HEADER= lib_pch.h
+
+include(../../sharedcomponents.pri)
+include(../component.pri)
+
+unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtDesigner QtGui QtScript QtXml
+
+target.path=$$[QT_INSTALL_LIBS]
+INSTALLS += target
+win32 {
+ dlltarget.path=$$[QT_INSTALL_BINS]
+ INSTALLS += dlltarget
+}
diff --git a/tools/designer/src/components/lib/lib_pch.h b/tools/designer/src/components/lib/lib_pch.h
new file mode 100644
index 0000000000..9f47b2508e
--- /dev/null
+++ b/tools/designer/src/components/lib/lib_pch.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/QtDesigner>
+#include <QtDesigner/QExtensionManager>
diff --git a/tools/designer/src/components/lib/qdesigner_components.cpp b/tools/designer/src/components/lib/qdesigner_components.cpp
new file mode 100644
index 0000000000..42752d9212
--- /dev/null
+++ b/tools/designer/src/components/lib/qdesigner_components.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/QDesignerComponents>
+
+#include <actioneditor_p.h>
+#include <widgetdatabase_p.h>
+#include <widgetfactory_p.h>
+
+#include <formeditor/formeditor.h>
+#include <widgetbox/widgetbox.h>
+#include <propertyeditor/propertyeditor.h>
+#include <objectinspector/objectinspector.h>
+#include <taskmenu/taskmenu_component.h>
+#include "qtresourceview_p.h"
+#include <qdesigner_integration_p.h>
+#include <signalsloteditor/signalsloteditorwindow.h>
+
+#include <buddyeditor/buddyeditor_plugin.h>
+#include <signalsloteditor/signalsloteditor_plugin.h>
+#include <tabordereditor/tabordereditor_plugin.h>
+
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerResourceBrowserInterface>
+
+#include <QtCore/qplugin.h>
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+
+// ### keep it in sync with Q_IMPORT_PLUGIN in qplugin.h
+#define DECLARE_PLUGIN_INSTANCE(PLUGIN) \
+ extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \
+ class Static##PLUGIN##PluginInstance { public: \
+ Static##PLUGIN##PluginInstance() { \
+ QT_PREPEND_NAMESPACE(qRegisterStaticPluginInstanceFunction) \
+ (&qt_plugin_instance_##PLUGIN); \
+ } \
+ };
+
+#define INIT_PLUGIN_INSTANCE(PLUGIN) \
+ do { \
+ Static##PLUGIN##PluginInstance instance; \
+ Q_UNUSED(instance); \
+ } while (0)
+
+DECLARE_PLUGIN_INSTANCE(SignalSlotEditorPlugin)
+DECLARE_PLUGIN_INSTANCE(BuddyEditorPlugin)
+DECLARE_PLUGIN_INSTANCE(TabOrderEditorPlugin)
+
+static void initResources()
+{
+ // Q_INIT_RESOURCE only usable in functions in global namespace
+ Q_INIT_RESOURCE(formeditor);
+ Q_INIT_RESOURCE(widgetbox);
+ Q_INIT_RESOURCE(propertyeditor);
+}
+
+
+static void initInstances()
+{
+ static bool plugins_initialized = false;
+
+ if (!plugins_initialized) {
+ INIT_PLUGIN_INSTANCE(SignalSlotEditorPlugin);
+ INIT_PLUGIN_INSTANCE(BuddyEditorPlugin);
+ INIT_PLUGIN_INSTANCE(TabOrderEditorPlugin);
+ plugins_initialized = true;
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerComponents
+ \brief The QDesignerComponents class provides a central resource for the various components
+ used in the \QD user interface.
+ \inmodule QtDesigner
+ \internal
+
+ The QDesignerComponents class is a factory for each of the standard components present
+ in the \QD user interface. It is mostly useful for developers who want to implement
+ a standalone form editing environment using \QD's components, or who need to integrate
+ \QD's components into an existing integrated development environment (IDE).
+
+ \sa QDesignerFormEditorInterface, QDesignerObjectInspectorInterface,
+ QDesignerPropertyEditorInterface, QDesignerWidgetBoxInterface
+*/
+
+/*!
+ Initializes the resources used by the components.*/
+void QDesignerComponents::initializeResources()
+{
+ initResources();
+}
+
+/*!
+ Initializes the plugins used by the components.*/
+void QDesignerComponents::initializePlugins(QDesignerFormEditorInterface *core)
+{
+ qdesigner_internal::QDesignerIntegration::initializePlugins(core);
+}
+
+/*!
+ Constructs a form editor interface with the given \a parent.*/
+QDesignerFormEditorInterface *QDesignerComponents::createFormEditor(QObject *parent)
+{
+ initInstances();
+ return new qdesigner_internal::FormEditor(parent);
+}
+
+/*!
+ Returns a new task menu with the given \a parent for the \a core interface.*/
+QObject *QDesignerComponents::createTaskMenu(QDesignerFormEditorInterface *core, QObject *parent)
+{
+ return new qdesigner_internal::TaskMenuComponent(core, parent);
+}
+
+static inline int qtMajorVersion(int qtVersion) { return qtVersion >> 16; }
+static inline int qtMinorVersion(int qtVersion) { return (qtVersion >> 8) & 0xFF; }
+static inline void setMinorVersion(int minorVersion, int *qtVersion)
+{
+ *qtVersion &= ~0xFF00;
+ *qtVersion |= minorVersion << 8;
+}
+
+// Build the version-dependent name of the user widget box file, '$HOME.designer/widgetbox4.4.xml'
+static inline QString widgetBoxFileName(int qtVersion, const QDesignerLanguageExtension *lang = 0)
+{
+ QString rc; {
+ const QChar dot = QLatin1Char('.');
+ QTextStream str(&rc);
+ str << QDir::homePath() << QDir::separator() << QLatin1String(".designer") << QDir::separator()
+ << QLatin1String("widgetbox");
+ // The naming convention using the version was introduced with 4.4
+ const int major = qtMajorVersion(qtVersion);
+ const int minor = qtMinorVersion(qtVersion);
+ if (major >= 4 && minor >= 4)
+ str << major << dot << minor;
+ if (lang)
+ str << dot << lang->uiExtension();
+ str << QLatin1String(".xml");
+ }
+ return rc;
+}
+
+/*!
+ Returns a new widget box interface with the given \a parent for the \a core interface.*/
+QDesignerWidgetBoxInterface *QDesignerComponents::createWidgetBox(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ qdesigner_internal::WidgetBox *widgetBox = new qdesigner_internal::WidgetBox(core, parent);
+
+ const QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core);
+
+ do {
+ if (lang) {
+ const QString languageWidgetBox = lang->widgetBoxContents();
+ if (!languageWidgetBox.isEmpty()) {
+ widgetBox->loadContents(lang->widgetBoxContents());
+ break;
+ }
+ }
+
+ widgetBox->setFileName(QLatin1String(":/trolltech/widgetbox/widgetbox.xml"));
+ widgetBox->load();
+ } while (false);
+
+ const QString userWidgetBoxFile = widgetBoxFileName(QT_VERSION, lang);
+
+ widgetBox->setFileName(userWidgetBoxFile);
+ if (!QFileInfo(userWidgetBoxFile).exists()) {
+ // check previous version, that is, are we running the new version for the first time
+ // If so, try to copy the old widget box file
+ if (const int minv = qtMinorVersion(QT_VERSION)) {
+ int oldVersion = QT_VERSION;
+ setMinorVersion(minv - 1, &oldVersion);
+ const QString oldWidgetBoxFile = widgetBoxFileName(oldVersion, lang);
+ if (QFileInfo(oldWidgetBoxFile).exists())
+ QFile::copy(oldWidgetBoxFile, userWidgetBoxFile);
+ }
+ }
+ widgetBox->load();
+
+ return widgetBox;
+}
+
+/*!
+ Returns a new property editor interface with the given \a parent for the \a core interface.*/
+QDesignerPropertyEditorInterface *QDesignerComponents::createPropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ return new qdesigner_internal::PropertyEditor(core, parent);
+}
+
+/*!
+ Returns a new object inspector interface with the given \a parent for the \a core interface.*/
+QDesignerObjectInspectorInterface *QDesignerComponents::createObjectInspector(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ return new qdesigner_internal::ObjectInspector(core, parent);
+}
+
+/*!
+ Returns a new action editor interface with the given \a parent for the \a core interface.*/
+QDesignerActionEditorInterface *QDesignerComponents::createActionEditor(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ return new qdesigner_internal::ActionEditor(core, parent);
+}
+
+/*!
+ Returns a new resource editor with the given \a parent for the \a core interface.*/
+QWidget *QDesignerComponents::createResourceEditor(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core)) {
+ QWidget *w = lang->createResourceBrowser(parent);
+ if (w)
+ return w;
+ }
+ QtResourceView *resourceView = new QtResourceView(core, parent);
+ resourceView->setResourceModel(core->resourceModel());
+ resourceView->setSettingsKey(QLatin1String("ResourceBrowser"));
+ qdesigner_internal::QDesignerIntegration *designerIntegration = qobject_cast<qdesigner_internal::QDesignerIntegration *>(core->integration());
+ // Note for integrators: make sure you call createResourceEditor() after you instantiated your subclass of designer integration
+ // (designer doesn't do that since by default editing resources is enabled)
+ if (designerIntegration)
+ resourceView->setResourceEditingEnabled(designerIntegration->isResourceEditingEnabled());
+ return resourceView;
+}
+
+/*!
+ Returns a new signal-slot editor with the given \a parent for the \a core interface.*/
+QWidget *QDesignerComponents::createSignalSlotEditor(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ return new qdesigner_internal::SignalSlotEditorWindow(core, parent);
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/components/objectinspector/objectinspector.cpp b/tools/designer/src/components/objectinspector/objectinspector.cpp
new file mode 100644
index 0000000000..4e515be16c
--- /dev/null
+++ b/tools/designer/src/components/objectinspector/objectinspector.cpp
@@ -0,0 +1,839 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ObjectInspector
+*/
+
+#include "objectinspector.h"
+#include "objectinspectormodel_p.h"
+#include "formwindow.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerTaskMenuExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+
+// shared
+#include <qdesigner_utils_p.h>
+#include <formwindowbase_p.h>
+#include <itemviewfindwidget.h>
+#include <qdesigner_dnditem_p.h>
+#include <textpropertyeditor_p.h>
+#include <qdesigner_command_p.h>
+#include <grid_p.h>
+
+// Qt
+#include <QtGui/QApplication>
+#include <QtGui/QHeaderView>
+#include <QtGui/QScrollBar>
+#include <QtGui/QPainter>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QItemSelectionModel>
+#include <QtGui/QMenu>
+#include <QtGui/QTreeView>
+#include <QtGui/QItemDelegate>
+#include <QtGui/qevent.h>
+
+#include <QtCore/QVector>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ // Selections: Basically, ObjectInspector has to ensure a consistent
+ // selection, that is, either form-managed widgets (represented
+ // by the cursor interface selection), or unmanaged widgets/objects,
+ // for example actions, container pages, menu bars, tool bars
+ // and the like. The selection state of the latter is managed only in the object inspector.
+ // As soon as a managed widget is selected, unmanaged objects
+ // have to be unselected
+ // Normally, an empty selection is not allowed, the main container
+ // should be selected in this case (applyCursorSelection()).
+ // An exception is when clearSelection is called directly for example
+ // by the action editor that puts an unassociated action into the property
+ // editor. A hack exists to avoid the update in this case.
+
+ enum SelectionType {
+ NoSelection,
+ // A QObject that has a meta database entry
+ QObjectSelection,
+ // Unmanaged widget, menu bar or the like
+ UnmanagedWidgetSelection,
+ // A widget managed by the form window cursor
+ ManagedWidgetSelection };
+
+ typedef QVector<QObject*> QObjectVector;
+}
+
+static inline SelectionType selectionType(const QDesignerFormWindowInterface *fw, QObject *o)
+{
+ if (!o->isWidgetType())
+ return fw->core()->metaDataBase()->item(o) ? QObjectSelection : NoSelection;
+ return fw->isManaged(qobject_cast<QWidget *>(o)) ? ManagedWidgetSelection : UnmanagedWidgetSelection;
+}
+
+// Return an offset for dropping (when dropping widgets on the object
+// inspector, we fake a position on the form based on the widget dropped on).
+// Position the dropped widget with form grid offset to avoid overlapping unless we
+// drop on a layout. Position doesn't matter in the layout case
+// and this enables us to drop on a squeezed layout widget of size zero
+
+static inline QPoint dropPointOffset(const qdesigner_internal::FormWindowBase *fw, const QWidget *dropTarget)
+{
+ if (!dropTarget || dropTarget->layout())
+ return QPoint(0, 0);
+ return QPoint(fw->designerGrid().deltaX(), fw->designerGrid().deltaY());
+}
+
+namespace qdesigner_internal {
+// Delegate with object name validator for the object name column
+class ObjectInspectorDelegate : public QItemDelegate {
+public:
+ explicit ObjectInspectorDelegate(QObject *parent = 0);
+
+ virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+};
+
+ObjectInspectorDelegate::ObjectInspectorDelegate(QObject *parent) :
+ QItemDelegate(parent)
+{
+}
+
+QWidget *ObjectInspectorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option, const QModelIndex &index) const
+{
+ if (index.column() != ObjectInspectorModel::ObjectNameColumn)
+ return QItemDelegate::createEditor(parent, option, index);
+ // Object name editor
+ const bool isMainContainer = !index.parent().isValid();
+ return new TextPropertyEditor(parent, TextPropertyEditor::EmbeddingTreeView,
+ isMainContainer ? ValidationObjectNameScope : ValidationObjectName);
+}
+
+// ------------ ObjectInspectorTreeView:
+// - Makes the Space key start editing
+// - Suppresses a range selection by dragging or Shift-up/down, which does not really work due
+// to the need to maintain a consistent selection.
+
+class ObjectInspectorTreeView : public QTreeView {
+public:
+ ObjectInspectorTreeView(QWidget *parent = 0) : QTreeView(parent) {}
+
+protected:
+ virtual void mouseMoveEvent (QMouseEvent * event);
+ virtual void keyPressEvent(QKeyEvent *event);
+
+};
+
+void ObjectInspectorTreeView::mouseMoveEvent(QMouseEvent *event)
+{
+ event->ignore(); // suppress a range selection by dragging
+}
+
+void ObjectInspectorTreeView::keyPressEvent(QKeyEvent *event)
+{
+ bool handled = false;
+ switch (event->key()) {
+ case Qt::Key_Up:
+ case Qt::Key_Down: // suppress shift-up/down range selection
+ if (event->modifiers() & Qt::ShiftModifier) {
+ event->ignore();
+ handled = true;
+ }
+ break;
+ case Qt::Key_Space: { // Space pressed: Start editing
+ const QModelIndex index = currentIndex();
+ if (index.isValid() && index.column() == 0 && !model()->hasChildren(index) && model()->flags(index) & Qt::ItemIsEditable) {
+ event->accept();
+ handled = true;
+ edit(index);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (!handled)
+ QTreeView::keyPressEvent(event);
+}
+
+// ------------ ObjectInspectorPrivate
+
+class ObjectInspector::ObjectInspectorPrivate {
+public:
+ ObjectInspectorPrivate(QDesignerFormEditorInterface *core);
+ ~ObjectInspectorPrivate();
+
+ QTreeView *treeView() const { return m_treeView; }
+ ItemViewFindWidget *findWidget() const { return m_findWidget; }
+ QDesignerFormEditorInterface *core() const { return m_core; }
+ const QPointer<FormWindowBase> &formWindow() const { return m_formWindow; }
+
+ void clear();
+ void setFormWindow(QDesignerFormWindowInterface *fwi);
+
+ QWidget *managedWidgetAt(const QPoint &global_mouse_pos);
+
+ void restoreDropHighlighting();
+ void handleDragEnterMoveEvent(const QWidget *objectInspectorWidget, QDragMoveEvent * event, bool isDragEnter);
+ void dropEvent (QDropEvent * event);
+
+ void clearSelection();
+ bool selectObject(QObject *o);
+ void slotSelectionChanged(const QItemSelection & selected, const QItemSelection &deselected);
+ void getSelection(Selection &s) const;
+
+ void slotHeaderDoubleClicked(int column) { m_treeView->resizeColumnToContents(column); }
+ void slotPopupContextMenu(QWidget *parent, const QPoint &pos);
+
+private:
+ void setFormWindowBlocked(QDesignerFormWindowInterface *fwi);
+ void applyCursorSelection();
+ void synchronizeSelection(const QItemSelection & selected, const QItemSelection &deselected);
+ bool checkManagedWidgetSelection(const QModelIndexList &selection);
+ void showContainersCurrentPage(QWidget *widget);
+
+ enum SelectionFlags { AddToSelection = 1, MakeCurrent = 2};
+ void selectIndexRange(const QModelIndexList &indexes, unsigned flags);
+
+ QDesignerFormEditorInterface *m_core;
+ QTreeView *m_treeView;
+ ObjectInspectorModel *m_model;
+ ItemViewFindWidget *m_findWidget;
+ QPointer<FormWindowBase> m_formWindow;
+ QPointer<QWidget> m_formFakeDropTarget;
+ bool m_withinClearSelection;
+};
+
+ObjectInspector::ObjectInspectorPrivate::ObjectInspectorPrivate(QDesignerFormEditorInterface *core) :
+ m_core(core),
+ m_treeView(new ObjectInspectorTreeView),
+ m_model(new ObjectInspectorModel(m_treeView)),
+ m_findWidget(new ItemViewFindWidget(
+ ItemViewFindWidget::NarrowLayout | ItemViewFindWidget::NoWholeWords)),
+ m_withinClearSelection(false)
+{
+ m_treeView->setModel(m_model);
+ m_treeView->setItemDelegate(new ObjectInspectorDelegate);
+ m_treeView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ m_treeView->header()->setResizeMode(1, QHeaderView::Stretch);
+ m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ m_treeView->setAlternatingRowColors(true);
+ m_treeView->setTextElideMode (Qt::ElideMiddle);
+
+ m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+}
+
+ObjectInspector::ObjectInspectorPrivate::~ObjectInspectorPrivate()
+{
+ delete m_treeView->itemDelegate();
+}
+
+void ObjectInspector::ObjectInspectorPrivate::clearSelection()
+{
+ m_withinClearSelection = true;
+ m_treeView->clearSelection();
+ m_withinClearSelection = false;
+}
+
+QWidget *ObjectInspector::ObjectInspectorPrivate::managedWidgetAt(const QPoint &global_mouse_pos)
+{
+ if (!m_formWindow)
+ return 0;
+
+ const QPoint pos = m_treeView->viewport()->mapFromGlobal(global_mouse_pos);
+ QObject *o = m_model->objectAt(m_treeView->indexAt(pos));
+
+ if (!o || !o->isWidgetType())
+ return 0;
+
+ QWidget *rc = qobject_cast<QWidget *>(o);
+ if (!m_formWindow->isManaged(rc))
+ return 0;
+ return rc;
+}
+
+void ObjectInspector::ObjectInspectorPrivate::showContainersCurrentPage(QWidget *widget)
+{
+ if (!widget)
+ return;
+
+ FormWindow *fw = FormWindow::findFormWindow(widget);
+ if (!fw)
+ return;
+
+ QWidget *w = widget->parentWidget();
+ bool macroStarted = false;
+ // Find a multipage container (tab widgets, etc.) in the hierarchy and set the right page.
+ while (w != 0) {
+ if (fw->isManaged(w)) { // Rule out unmanaged internal scroll areas, for example, on QToolBoxes.
+ if (QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), w)) {
+ const int count = c->count();
+ if (count > 1 && !c->widget(c->currentIndex())->isAncestorOf(widget)) {
+ for (int i = 0; i < count; i++)
+ if (c->widget(i)->isAncestorOf(widget)) {
+ if (macroStarted == false) {
+ macroStarted = true;
+ fw->beginCommand(tr("Change Current Page"));
+ }
+ ChangeCurrentPageCommand *cmd = new ChangeCurrentPageCommand(fw);
+ cmd->init(w, i);
+ fw->commandHistory()->push(cmd);
+ break;
+ }
+ }
+ }
+ }
+ w = w->parentWidget();
+ }
+ if (macroStarted == true)
+ fw->endCommand();
+}
+
+void ObjectInspector::ObjectInspectorPrivate::restoreDropHighlighting()
+{
+ if (m_formFakeDropTarget) {
+ if (m_formWindow) {
+ m_formWindow->highlightWidget(m_formFakeDropTarget, QPoint(5, 5), FormWindow::Restore);
+ }
+ m_formFakeDropTarget = 0;
+ }
+}
+
+void ObjectInspector::ObjectInspectorPrivate::handleDragEnterMoveEvent(const QWidget *objectInspectorWidget, QDragMoveEvent * event, bool isDragEnter)
+{
+ if (!m_formWindow) {
+ event->ignore();
+ return;
+ }
+
+ const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(event->mimeData());
+ if (!mimeData) {
+ event->ignore();
+ return;
+ }
+
+ QWidget *dropTarget = 0;
+ QPoint fakeDropTargetOffset = QPoint(0, 0);
+ if (QWidget *managedWidget = managedWidgetAt(objectInspectorWidget->mapToGlobal(event->pos()))) {
+ fakeDropTargetOffset = dropPointOffset(m_formWindow, managedWidget);
+ // pretend we drag over the managed widget on the form
+ const QPoint fakeFormPos = m_formWindow->mapFromGlobal(managedWidget->mapToGlobal(fakeDropTargetOffset));
+ const FormWindowBase::WidgetUnderMouseMode wum = mimeData->items().size() == 1 ? FormWindowBase::FindSingleSelectionDropTarget : FormWindowBase::FindMultiSelectionDropTarget;
+ dropTarget = m_formWindow->widgetUnderMouse(fakeFormPos, wum);
+ }
+
+ if (m_formFakeDropTarget && dropTarget != m_formFakeDropTarget)
+ m_formWindow->highlightWidget(m_formFakeDropTarget, fakeDropTargetOffset, FormWindow::Restore);
+
+ m_formFakeDropTarget = dropTarget;
+ if (m_formFakeDropTarget)
+ m_formWindow->highlightWidget(m_formFakeDropTarget, fakeDropTargetOffset, FormWindow::Highlight);
+
+ // Do not refuse drag enter even if the area is not droppable
+ if (isDragEnter || m_formFakeDropTarget)
+ mimeData->acceptEvent(event);
+ else
+ event->ignore();
+}
+void ObjectInspector::ObjectInspectorPrivate::dropEvent (QDropEvent * event)
+{
+ if (!m_formWindow || !m_formFakeDropTarget) {
+ event->ignore();
+ return;
+ }
+
+ const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(event->mimeData());
+ if (!mimeData) {
+ event->ignore();
+ return;
+ }
+ const QPoint fakeGlobalDropFormPos = m_formFakeDropTarget->mapToGlobal(dropPointOffset(m_formWindow , m_formFakeDropTarget));
+ mimeData->moveDecoration(fakeGlobalDropFormPos + mimeData->hotSpot());
+ if (!m_formWindow->dropWidgets(mimeData->items(), m_formFakeDropTarget, fakeGlobalDropFormPos)) {
+ event->ignore();
+ return;
+ }
+ mimeData->acceptEvent(event);
+}
+
+bool ObjectInspector::ObjectInspectorPrivate::selectObject(QObject *o)
+{
+ if (!m_core->metaDataBase()->item(o))
+ return false;
+
+ typedef QSet<QModelIndex> ModelIndexSet;
+
+ const QModelIndexList objectIndexes = m_model->indexesOf(o);
+ if (objectIndexes.empty())
+ return false;
+
+ QItemSelectionModel *selectionModel = m_treeView->selectionModel();
+ const ModelIndexSet currentSelectedItems = selectionModel->selectedRows(0).toSet();
+
+ // Change in selection?
+ if (!currentSelectedItems.empty() && currentSelectedItems == objectIndexes.toSet())
+ return true;
+
+ // do select and update
+ selectIndexRange(objectIndexes, MakeCurrent);
+ return true;
+}
+
+void ObjectInspector::ObjectInspectorPrivate::selectIndexRange(const QModelIndexList &indexes, unsigned flags)
+{
+ if (indexes.empty())
+ return;
+
+ QItemSelectionModel::SelectionFlags selectFlags = QItemSelectionModel::Select|QItemSelectionModel::Rows;
+ if (!(flags & AddToSelection))
+ selectFlags |= QItemSelectionModel::Clear;
+ if (flags & MakeCurrent)
+ selectFlags |= QItemSelectionModel::Current;
+
+ QItemSelectionModel *selectionModel = m_treeView->selectionModel();
+ const QModelIndexList::const_iterator cend = indexes.constEnd();
+ for (QModelIndexList::const_iterator it = indexes.constBegin(); it != cend; ++it)
+ if (it->column() == 0) {
+ selectionModel->select(*it, selectFlags);
+ selectFlags &= ~(QItemSelectionModel::Clear|QItemSelectionModel::Current);
+ }
+ if (flags & MakeCurrent)
+ m_treeView->scrollTo(indexes.front(), QAbstractItemView::EnsureVisible);
+}
+
+void ObjectInspector::ObjectInspectorPrivate::clear()
+{
+ m_formFakeDropTarget = 0;
+ m_formWindow = 0;
+}
+
+// Form window cursor is in state 'main container only'
+static inline bool mainContainerIsCurrent(const QDesignerFormWindowInterface *fw)
+{
+ const QDesignerFormWindowCursorInterface *cursor = fw->cursor();
+ if (cursor->selectedWidgetCount() > 1)
+ return false;
+ const QWidget *current = cursor->current();
+ return current == fw || current == fw->mainContainer();
+}
+
+void ObjectInspector::ObjectInspectorPrivate::setFormWindow(QDesignerFormWindowInterface *fwi)
+{
+ const bool blocked = m_treeView->selectionModel()->blockSignals(true);
+ {
+ UpdateBlocker ub(m_treeView);
+ setFormWindowBlocked(fwi);
+ }
+
+ m_treeView->update();
+ m_treeView->selectionModel()->blockSignals(blocked);
+}
+
+void ObjectInspector::ObjectInspectorPrivate::setFormWindowBlocked(QDesignerFormWindowInterface *fwi)
+{
+ FormWindowBase *fw = qobject_cast<FormWindowBase *>(fwi);
+ const bool formWindowChanged = m_formWindow != fw;
+
+ m_formWindow = fw;
+
+ const int oldWidth = m_treeView->columnWidth(0);
+ const int xoffset = m_treeView->horizontalScrollBar()->value();
+ const int yoffset = m_treeView->verticalScrollBar()->value();
+
+ if (formWindowChanged)
+ m_formFakeDropTarget = 0;
+
+ switch (m_model->update(m_formWindow)) {
+ case ObjectInspectorModel::NoForm:
+ clear();
+ return;
+ case ObjectInspectorModel::Rebuilt: // Complete rebuild: Just apply cursor selection
+ applyCursorSelection();
+ m_treeView->expandAll();
+ if (formWindowChanged) {
+ m_treeView->resizeColumnToContents(0);
+ } else {
+ m_treeView->setColumnWidth(0, oldWidth);
+ m_treeView->horizontalScrollBar()->setValue(xoffset);
+ m_treeView->verticalScrollBar()->setValue(yoffset);
+ }
+ break;
+ case ObjectInspectorModel::Updated: {
+ // Same structure (property changed or click on the form)
+ // We maintain a selection of unmanaged objects
+ // only if the cursor is in state "mainContainer() == current".
+ // and we have a non-managed selection.
+ // Else we take over the cursor selection.
+ bool applySelection = !mainContainerIsCurrent(m_formWindow);
+ if (!applySelection) {
+ const QModelIndexList currentIndexes = m_treeView->selectionModel()->selectedRows(0);
+ if (currentIndexes.empty()) {
+ applySelection = true;
+ } else {
+ applySelection = selectionType(m_formWindow, m_model->objectAt(currentIndexes.front())) == ManagedWidgetSelection;
+ }
+ }
+ if (applySelection)
+ applyCursorSelection();
+ }
+ break;
+ }
+}
+
+// Apply selection of form window cursor to object inspector, set current
+void ObjectInspector::ObjectInspectorPrivate::applyCursorSelection()
+{
+ const QDesignerFormWindowCursorInterface *cursor = m_formWindow->cursor();
+ const int count = cursor->selectedWidgetCount();
+ if (!count)
+ return;
+
+ // Set the current widget first which also clears the selection
+ QWidget *currentWidget = cursor->current();
+ if (currentWidget)
+ selectIndexRange(m_model->indexesOf(currentWidget), MakeCurrent);
+ else
+ m_treeView->selectionModel()->clearSelection();
+
+ for (int i = 0;i < count; i++) {
+ QWidget *widget = cursor->selectedWidget(i);
+ if (widget != currentWidget)
+ selectIndexRange(m_model->indexesOf(widget), AddToSelection);
+ }
+}
+
+// Synchronize managed widget in the form (select in cursor). Block updates
+static int selectInCursor(FormWindowBase *fw, const QObjectVector &objects, bool value)
+{
+ int rc = 0;
+ const bool blocked = fw->blockSelectionChanged(true);
+ const QObjectVector::const_iterator ocend = objects.constEnd();
+ for (QObjectVector::const_iterator it = objects.constBegin(); it != ocend; ++it)
+ if (selectionType(fw, *it) == ManagedWidgetSelection) {
+ fw->selectWidget(static_cast<QWidget *>(*it), value);
+ rc++;
+ }
+ fw->blockSelectionChanged(blocked);
+ return rc;
+}
+
+void ObjectInspector::ObjectInspectorPrivate::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
+{
+ if (m_formWindow) {
+ synchronizeSelection(selected, deselected);
+ QMetaObject::invokeMethod(m_core->formWindowManager(), "slotUpdateActions");
+ }
+}
+
+// Convert indexes to object vectors taking into account that
+// some index lists are multicolumn ranges
+static inline QObjectVector indexesToObjects(const ObjectInspectorModel *model, const QModelIndexList &indexes)
+{
+ if (indexes.empty())
+ return QObjectVector();
+ QObjectVector rc;
+ rc.reserve(indexes.size());
+ const QModelIndexList::const_iterator icend = indexes.constEnd();
+ for (QModelIndexList::const_iterator it = indexes.constBegin(); it != icend; ++it)
+ if (it->column() == 0)
+ rc.push_back(model->objectAt(*it));
+ return rc;
+}
+
+// Check if any managed widgets are selected. If so, iterate over
+// selection and deselect all unmanaged objects
+bool ObjectInspector::ObjectInspectorPrivate::checkManagedWidgetSelection(const QModelIndexList &rowSelection)
+{
+ bool isManagedWidgetSelection = false;
+ QItemSelectionModel *selectionModel = m_treeView->selectionModel();
+ const QModelIndexList::const_iterator cscend = rowSelection.constEnd();
+ for (QModelIndexList::const_iterator it = rowSelection.constBegin(); it != cscend; ++it) {
+ QObject *object = m_model->objectAt(*it);
+ if (selectionType(m_formWindow, object) == ManagedWidgetSelection) {
+ isManagedWidgetSelection = true;
+ break;
+ }
+ }
+
+ if (!isManagedWidgetSelection)
+ return false;
+ // Need to unselect unmanaged ones
+ const bool blocked = selectionModel->blockSignals(true);
+ for (QModelIndexList::const_iterator it = rowSelection.constBegin(); it != cscend; ++it) {
+ QObject *object = m_model->objectAt(*it);
+ if (selectionType(m_formWindow, object) != ManagedWidgetSelection)
+ selectionModel->select(*it, QItemSelectionModel::Deselect|QItemSelectionModel::Rows);
+ }
+ selectionModel->blockSignals(blocked);
+ return true;
+}
+
+void ObjectInspector::ObjectInspectorPrivate::synchronizeSelection(const QItemSelection & selectedSelection, const QItemSelection &deselectedSelection)
+{
+ // Synchronize form window cursor.
+ const QObjectVector deselected = indexesToObjects(m_model, deselectedSelection.indexes());
+ const QObjectVector newlySelected = indexesToObjects(m_model, selectedSelection.indexes());
+
+ const QModelIndexList currentSelectedIndexes = m_treeView->selectionModel()->selectedRows(0);
+
+ int deselectedManagedWidgetCount = 0;
+ if (!deselected.empty())
+ deselectedManagedWidgetCount = selectInCursor(m_formWindow, deselected, false);
+
+ if (newlySelected.empty()) { // Nothing selected
+ if (currentSelectedIndexes.empty()) // Do not allow a null-selection, reset to main container
+ m_formWindow->clearSelection(!m_withinClearSelection);
+ return;
+ }
+
+ const int selectManagedWidgetCount = selectInCursor(m_formWindow, newlySelected, true);
+ // Check consistency: Make sure either managed widgets or unmanaged objects are selected.
+ // No newly-selected managed widgets: Unless there are ones in the (old) current selection,
+ // select the unmanaged object
+ if (selectManagedWidgetCount == 0) {
+ if (checkManagedWidgetSelection(currentSelectedIndexes)) {
+ // Managed selection exists, refuse and update if necessary
+ if (deselectedManagedWidgetCount != 0 || selectManagedWidgetCount != 0)
+ m_formWindow->emitSelectionChanged();
+ return;
+ }
+ // And now for the unmanaged selection
+ m_formWindow->clearSelection(false);
+ QObject *unmanagedObject = newlySelected.front();
+ m_core->propertyEditor()->setObject(unmanagedObject);
+ m_core->propertyEditor()->setEnabled(true);
+ // open container page if it is a single widget
+ if (newlySelected.size() == 1 && unmanagedObject->isWidgetType())
+ showContainersCurrentPage(static_cast<QWidget*>(unmanagedObject));
+ return;
+ }
+ // Open container page if it is a single widget
+ if (newlySelected.size() == 1) {
+ QObject *object = newlySelected.back();
+ if (object->isWidgetType())
+ showContainersCurrentPage(static_cast<QWidget*>(object));
+ }
+
+ // A managed widget was newly selected. Make sure there are no unmanaged objects
+ // in the whole unless just single selection
+ if (currentSelectedIndexes.size() > selectManagedWidgetCount)
+ checkManagedWidgetSelection(currentSelectedIndexes);
+ // Update form
+ if (deselectedManagedWidgetCount != 0 || selectManagedWidgetCount != 0)
+ m_formWindow->emitSelectionChanged();
+}
+
+
+void ObjectInspector::ObjectInspectorPrivate::getSelection(Selection &s) const
+{
+ s.clear();
+
+ if (!m_formWindow)
+ return;
+
+ const QModelIndexList currentSelectedIndexes = m_treeView->selectionModel()->selectedRows(0);
+ if (currentSelectedIndexes.empty())
+ return;
+
+ // sort objects
+ foreach (const QModelIndex &index, currentSelectedIndexes)
+ if (QObject *object = m_model->objectAt(index))
+ switch (selectionType(m_formWindow, object)) {
+ case NoSelection:
+ break;
+ case QObjectSelection:
+ // It is actually possible to select an action twice if it is in a menu bar
+ // and in a tool bar.
+ if (!s.objects.contains(object))
+ s.objects.push_back(object);
+ break;
+ case UnmanagedWidgetSelection:
+ s.unmanaged.push_back(qobject_cast<QWidget *>(object));
+ break;
+ case ManagedWidgetSelection:
+ s.managed.push_back(qobject_cast<QWidget *>(object));
+ break;
+ }
+}
+
+// Utility to create a task menu
+static inline QMenu *createTaskMenu(QObject *object, QDesignerFormWindowInterface *fw)
+{
+ // 1) Objects
+ if (!object->isWidgetType())
+ return FormWindowBase::createExtensionTaskMenu(fw, object, false);
+ // 2) Unmanaged widgets
+ QWidget *w = static_cast<QWidget *>(object);
+ if (!fw->isManaged(w))
+ return FormWindowBase::createExtensionTaskMenu(fw, w, false);
+ // 3) Mananaged widgets
+ if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase*>(fw))
+ return fwb->initializePopupMenu(w);
+ return 0;
+}
+
+void ObjectInspector::ObjectInspectorPrivate::slotPopupContextMenu(QWidget * /*parent*/, const QPoint &pos)
+{
+ if (m_formWindow == 0 || m_formWindow->currentTool() != 0)
+ return;
+
+ const QModelIndex index = m_treeView->indexAt (pos);
+ if (QObject *object = m_model->objectAt(m_treeView->indexAt(pos)))
+ if (QMenu *menu = createTaskMenu(object, m_formWindow)) {
+ menu->exec(m_treeView->viewport()->mapToGlobal(pos));
+ delete menu;
+ }
+}
+
+// ------------ ObjectInspector
+ObjectInspector::ObjectInspector(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QDesignerObjectInspector(parent),
+ m_impl(new ObjectInspectorPrivate(core))
+{
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ vbox->setMargin(0);
+
+ QTreeView *treeView = m_impl->treeView();
+ vbox->addWidget(treeView);
+
+ connect(treeView, SIGNAL(customContextMenuRequested(QPoint)),
+ this, SLOT(slotPopupContextMenu(QPoint)));
+
+ connect(treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)));
+
+ connect(treeView->header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(slotHeaderDoubleClicked(int)));
+ setAcceptDrops(true);
+
+ ItemViewFindWidget *findWidget = m_impl->findWidget();
+ vbox->addWidget(findWidget);
+
+ findWidget->setItemView(treeView);
+ QAction *findAction = new QAction(
+ ItemViewFindWidget::findIconSet(),
+ tr("&Find in Text..."),
+ this);
+ findAction->setShortcut(QKeySequence::Find);
+ findAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ addAction(findAction);
+ connect(findAction, SIGNAL(triggered(bool)), findWidget, SLOT(activate()));
+}
+
+ObjectInspector::~ObjectInspector()
+{
+ delete m_impl;
+}
+
+QDesignerFormEditorInterface *ObjectInspector::core() const
+{
+ return m_impl->core();
+}
+
+void ObjectInspector::slotPopupContextMenu(const QPoint &pos)
+{
+ m_impl->slotPopupContextMenu(this, pos);
+}
+
+void ObjectInspector::setFormWindow(QDesignerFormWindowInterface *fwi)
+{
+ m_impl->setFormWindow(fwi);
+}
+
+void ObjectInspector::slotSelectionChanged(const QItemSelection & selected, const QItemSelection &deselected)
+{
+ m_impl->slotSelectionChanged(selected, deselected);
+}
+
+void ObjectInspector::getSelection(Selection &s) const
+{
+ m_impl->getSelection(s);
+}
+
+bool ObjectInspector::selectObject(QObject *o)
+{
+ return m_impl->selectObject(o);
+}
+
+void ObjectInspector::clearSelection()
+{
+ m_impl->clearSelection();
+}
+
+void ObjectInspector::slotHeaderDoubleClicked(int column)
+{
+ m_impl->slotHeaderDoubleClicked(column);
+}
+
+void ObjectInspector::mainContainerChanged()
+{
+ // Invalidate references to objects kept in items
+ if (sender() == m_impl->formWindow())
+ setFormWindow(0);
+}
+
+void ObjectInspector::dragEnterEvent (QDragEnterEvent * event)
+{
+ m_impl->handleDragEnterMoveEvent(this, event, true);
+}
+
+void ObjectInspector::dragMoveEvent(QDragMoveEvent * event)
+{
+ m_impl->handleDragEnterMoveEvent(this, event, false);
+}
+
+void ObjectInspector::dragLeaveEvent(QDragLeaveEvent * /* event*/)
+{
+ m_impl->restoreDropHighlighting();
+}
+
+void ObjectInspector::dropEvent (QDropEvent * event)
+{
+ m_impl->dropEvent(event);
+
+QT_END_NAMESPACE
+}
+}
diff --git a/tools/designer/src/components/objectinspector/objectinspector.h b/tools/designer/src/components/objectinspector/objectinspector.h
new file mode 100644
index 0000000000..6b3b3d0c5b
--- /dev/null
+++ b/tools/designer/src/components/objectinspector/objectinspector.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OBJECTINSPECTOR_H
+#define OBJECTINSPECTOR_H
+
+#include "objectinspector_global.h"
+#include "qdesigner_objectinspector_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+class QItemSelection;
+
+namespace qdesigner_internal {
+
+class QT_OBJECTINSPECTOR_EXPORT ObjectInspector: public QDesignerObjectInspector
+{
+ Q_OBJECT
+public:
+ explicit ObjectInspector(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ virtual ~ObjectInspector();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual void getSelection(Selection &s) const;
+ virtual bool selectObject(QObject *o);
+ virtual void clearSelection();
+
+ void setFormWindow(QDesignerFormWindowInterface *formWindow);
+
+public slots:
+ virtual void mainContainerChanged();
+
+private slots:
+ void slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
+ void slotPopupContextMenu(const QPoint &pos);
+ void slotHeaderDoubleClicked(int column);
+
+protected:
+ virtual void dragEnterEvent (QDragEnterEvent * event);
+ virtual void dragMoveEvent(QDragMoveEvent * event);
+ virtual void dragLeaveEvent(QDragLeaveEvent * event);
+ virtual void dropEvent (QDropEvent * event);
+
+private:
+ class ObjectInspectorPrivate;
+ ObjectInspectorPrivate *m_impl;
+};
+
+} // namespace qdesigner_internal
+
+#endif // OBJECTINSPECTOR_H
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/objectinspector/objectinspector.pri b/tools/designer/src/components/objectinspector/objectinspector.pri
new file mode 100644
index 0000000000..280a1dc9e7
--- /dev/null
+++ b/tools/designer/src/components/objectinspector/objectinspector.pri
@@ -0,0 +1,10 @@
+include($$QT_SOURCE_TREE/tools/shared/findwidget/findwidget.pri)
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/objectinspector.h \
+ $$PWD/objectinspectormodel_p.h \
+ $$PWD/objectinspector_global.h
+
+SOURCES += $$PWD/objectinspector.cpp \
+ $$PWD/objectinspectormodel.cpp
diff --git a/tools/designer/src/components/objectinspector/objectinspector_global.h b/tools/designer/src/components/objectinspector/objectinspector_global.h
new file mode 100644
index 0000000000..b1aedc0245
--- /dev/null
+++ b/tools/designer/src/components/objectinspector/objectinspector_global.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef OBJECTINSPECTOR_GLOBAL_H
+#define OBJECTINSPECTOR_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+#ifdef QT_OBJECTINSPECTOR_LIBRARY
+# define QT_OBJECTINSPECTOR_EXPORT
+#else
+# define QT_OBJECTINSPECTOR_EXPORT
+#endif
+#else
+#define QT_OBJECTINSPECTOR_EXPORT
+#endif
+
+#endif // OBJECTINSPECTOR_GLOBAL_H
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/objectinspector/objectinspectormodel.cpp b/tools/designer/src/components/objectinspector/objectinspectormodel.cpp
new file mode 100644
index 0000000000..bc1ac0c5da
--- /dev/null
+++ b/tools/designer/src/components/objectinspector/objectinspectormodel.cpp
@@ -0,0 +1,520 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ObjectInspector
+*/
+
+#include "objectinspectormodel_p.h"
+
+#include <qlayout_widget_p.h>
+#include <layout_p.h>
+#include <qdesigner_propertycommand_p.h>
+#include <qdesigner_utils_p.h>
+#include <iconloader_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtGui/QLayout>
+#include <QtGui/QAction>
+#include <QtGui/QLayoutItem>
+#include <QtGui/QMenu>
+#include <QtGui/QButtonGroup>
+#include <QtCore/QSet>
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { DataRole = 1000 };
+}
+
+static inline QObject *objectOfItem(const QStandardItem *item) {
+ return qvariant_cast<QObject *>(item->data(DataRole));
+}
+
+static bool sortEntry(const QObject *a, const QObject *b)
+{
+ return a->objectName() < b->objectName();
+}
+
+static bool sameIcon(const QIcon &i1, const QIcon &i2)
+{
+ if (i1.isNull() && i2.isNull())
+ return true;
+ if (i1.isNull() != i2.isNull())
+ return false;
+ return i1.serialNumber() == i2.serialNumber();
+}
+
+static inline bool isNameColumnEditable(const QObject *)
+{
+ return true;
+}
+
+static qdesigner_internal::ObjectData::StandardItemList createModelRow(const QObject *o)
+{
+ qdesigner_internal::ObjectData::StandardItemList rc;
+ const Qt::ItemFlags baseFlags = Qt::ItemIsSelectable|Qt::ItemIsDropEnabled|Qt::ItemIsEnabled;
+ for (int i = 0; i < qdesigner_internal::ObjectInspectorModel::NumColumns; i++) {
+ QStandardItem *item = new QStandardItem;
+ Qt::ItemFlags flags = baseFlags;
+ if (i == qdesigner_internal::ObjectInspectorModel::ObjectNameColumn && isNameColumnEditable(o))
+ flags |= Qt::ItemIsEditable;
+ item->setFlags(flags);
+ rc += item;
+ }
+ return rc;
+}
+
+static inline bool isQLayoutWidget(const QObject *o)
+{
+ return o->metaObject() == &QLayoutWidget::staticMetaObject;
+}
+
+namespace qdesigner_internal {
+
+ // context kept while building a model, just there to reduce string allocations
+ struct ModelRecursionContext {
+ explicit ModelRecursionContext(QDesignerFormEditorInterface *core, const QString &sepName);
+
+ const QString designerPrefix;
+ const QString separator;
+
+ QDesignerFormEditorInterface *core;
+ const QDesignerWidgetDataBaseInterface *db;
+ const QDesignerMetaDataBaseInterface *mdb;
+ };
+
+ ModelRecursionContext::ModelRecursionContext(QDesignerFormEditorInterface *c, const QString &sepName) :
+ designerPrefix(QLatin1String("QDesigner")),
+ separator(sepName),
+ core(c),
+ db(c->widgetDataBase()),
+ mdb(c->metaDataBase())
+ {
+ }
+
+ // ------------ ObjectData/ ObjectModel:
+ // Whenever the selection changes, ObjectInspector::setFormWindow is
+ // called. To avoid rebuilding the tree every time (loosing expanded state)
+ // a model is first built from the object tree by recursion.
+ // As a tree is difficult to represent, a flat list of entries (ObjectData)
+ // containing object and parent object is used.
+ // ObjectData has an overloaded operator== that compares the object pointers.
+ // Structural changes which cause a rebuild can be detected by
+ // comparing the lists of ObjectData. If it is the same, only the item data (class name [changed by promotion],
+ // object name and icon) are checked and the existing items are updated.
+
+ ObjectData::ObjectData() :
+ m_parent(0),
+ m_object(0),
+ m_type(Object),
+ m_managedLayoutType(LayoutInfo::NoLayout)
+ {
+ }
+
+ ObjectData::ObjectData(QObject *parent, QObject *object, const ModelRecursionContext &ctx) :
+ m_parent(parent),
+ m_object(object),
+ m_type(Object),
+ m_className(QLatin1String(object->metaObject()->className())),
+ m_objectName(object->objectName()),
+ m_managedLayoutType(LayoutInfo::NoLayout)
+ {
+
+ // 1) set entry
+ if (object->isWidgetType()) {
+ initWidget(static_cast<QWidget*>(object), ctx);
+ } else {
+ initObject(ctx);
+ }
+ if (m_className.startsWith(ctx.designerPrefix))
+ m_className.remove(1, ctx.designerPrefix.size() - 1);
+ }
+
+ void ObjectData::initObject(const ModelRecursionContext &ctx)
+ {
+ // Check objects: Action?
+ if (const QAction *act = qobject_cast<const QAction*>(m_object)) {
+ if (act->isSeparator()) { // separator is reserved
+ m_objectName = ctx.separator;
+ m_type = SeparatorAction;
+ } else {
+ m_type = Action;
+ }
+ m_classIcon = act->icon();
+ } else {
+ m_type = Object;
+ }
+ }
+
+ void ObjectData::initWidget(QWidget *w, const ModelRecursionContext &ctx)
+ {
+ // Check for extension container, QLayoutwidget, or normal container
+ bool isContainer = false;
+ if (const QDesignerWidgetDataBaseItemInterface *widgetItem = ctx.db->item(ctx.db->indexOfObject(w, true))) {
+ m_classIcon = widgetItem->icon();
+ m_className = widgetItem->name();
+ isContainer = widgetItem->isContainer();
+ }
+
+ // We might encounter temporary states with no layouts when re-layouting.
+ // Just default to Widget handling for the moment.
+ if (isQLayoutWidget(w)) {
+ if (const QLayout *layout = w->layout()) {
+ m_type = LayoutWidget;
+ m_managedLayoutType = LayoutInfo::layoutType(ctx.core, layout);
+ m_className = QLatin1String(layout->metaObject()->className());
+ m_objectName = layout->objectName();
+ }
+ return;
+ }
+
+ if (qt_extension<QDesignerContainerExtension*>(ctx.core->extensionManager(), w)) {
+ m_type = ExtensionContainer;
+ return;
+ }
+ if (isContainer) {
+ m_type = LayoutableContainer;
+ m_managedLayoutType = LayoutInfo::managedLayoutType(ctx.core, w);
+ return;
+ }
+ m_type = ChildWidget;
+ }
+
+ bool ObjectData::equals(const ObjectData & me) const
+ {
+ return m_parent == me.m_parent && m_object == me.m_object;
+ }
+
+ unsigned ObjectData::compare(const ObjectData & rhs) const
+ {
+ unsigned rc = 0;
+ if (m_className != rhs.m_className)
+ rc |= ClassNameChanged;
+ if (m_objectName != rhs.m_objectName)
+ rc |= ObjectNameChanged;
+ if (!sameIcon(m_classIcon, rhs.m_classIcon))
+ rc |= ClassIconChanged;
+ if (m_type != rhs.m_type)
+ rc |= TypeChanged;
+ if (m_managedLayoutType != rhs.m_managedLayoutType)
+ rc |= LayoutTypeChanged;
+ return rc;
+ }
+
+ void ObjectData::setItemsDisplayData(const StandardItemList &row, const ObjectInspectorIcons &icons, unsigned mask) const
+ {
+ if (mask & ObjectNameChanged)
+ row[ObjectInspectorModel::ObjectNameColumn]->setText(m_objectName);
+ if (mask & ClassNameChanged) {
+ row[ObjectInspectorModel::ClassNameColumn]->setText(m_className);
+ row[ObjectInspectorModel::ClassNameColumn]->setToolTip(m_className);
+ }
+ // Set a layout icon only for containers. Note that QLayoutWidget don't have
+ // real class icons
+ if (mask & (ClassIconChanged|TypeChanged|LayoutTypeChanged)) {
+ switch (m_type) {
+ case LayoutWidget:
+ row[ObjectInspectorModel::ObjectNameColumn]->setIcon(icons.layoutIcons[m_managedLayoutType]);
+ row[ObjectInspectorModel::ClassNameColumn]->setIcon(icons.layoutIcons[m_managedLayoutType]);
+ break;
+ case LayoutableContainer:
+ row[ObjectInspectorModel::ObjectNameColumn]->setIcon(icons.layoutIcons[m_managedLayoutType]);
+ row[ObjectInspectorModel::ClassNameColumn]->setIcon(m_classIcon);
+ break;
+ default:
+ row[ObjectInspectorModel::ObjectNameColumn]->setIcon(QIcon());
+ row[ObjectInspectorModel::ClassNameColumn]->setIcon(m_classIcon);
+ break;
+ }
+ }
+ }
+
+ void ObjectData::setItems(const StandardItemList &row, const ObjectInspectorIcons &icons) const
+ {
+ const QVariant object = qVariantFromValue(m_object);
+ row[ObjectInspectorModel::ObjectNameColumn]->setData(object, DataRole);
+ row[ObjectInspectorModel::ClassNameColumn]->setData(object, DataRole);
+ setItemsDisplayData(row, icons, ClassNameChanged|ObjectNameChanged|ClassIconChanged|TypeChanged|LayoutTypeChanged);
+ }
+
+ typedef QList<ObjectData> ObjectModel;
+
+ // Recursive routine that creates the model by traversing the form window object tree.
+ void createModelRecursion(const QDesignerFormWindowInterface *fwi,
+ QObject *parent,
+ QObject *object,
+ ObjectModel &model,
+ const ModelRecursionContext &ctx)
+ {
+ typedef QList<QButtonGroup *> ButtonGroupList;
+ typedef QList<QAction *> ActionList;
+
+ // 1) Create entry
+ const ObjectData entry(parent, object, ctx);
+ model.push_back(entry);
+
+ // 2) recurse over widget children via container extension or children list
+ const QDesignerContainerExtension *containerExtension = 0;
+ if (entry.type() == ObjectData::ExtensionContainer) {
+ containerExtension = qt_extension<QDesignerContainerExtension*>(fwi->core()->extensionManager(), object);
+ Q_ASSERT(containerExtension);
+ const int count = containerExtension->count();
+ for (int i=0; i < count; ++i) {
+ QObject *page = containerExtension->widget(i);
+ Q_ASSERT(page != 0);
+ createModelRecursion(fwi, object, page, model, ctx);
+ }
+ }
+
+ QObjectList children = object->children();
+ if (!children.empty()) {
+ ButtonGroupList buttonGroups;
+ qSort(children.begin(), children.end(), sortEntry);
+ const QObjectList::const_iterator cend = children.constEnd();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
+ // Managed child widgets unless we had a container extension
+ if ((*it)->isWidgetType()) {
+ if (!containerExtension) {
+ QWidget *widget = qobject_cast<QWidget*>(*it);
+ if (fwi->isManaged(widget))
+ createModelRecursion(fwi, object, widget, model, ctx);
+ }
+ } else {
+ if (ctx.mdb->item(*it)) {
+ if (QButtonGroup *bg = qobject_cast<QButtonGroup*>(*it))
+ buttonGroups.push_back(bg);
+ } // Has MetaDataBase entry
+ }
+ }
+ // Add button groups
+ if (!buttonGroups.empty()) {
+ const ButtonGroupList::const_iterator bgcend = buttonGroups.constEnd();
+ for (ButtonGroupList::const_iterator bgit = buttonGroups.constBegin(); bgit != bgcend; ++bgit)
+ createModelRecursion(fwi, object, *bgit, model, ctx);
+ }
+ } // has children
+ if (object->isWidgetType()) {
+ // Add actions
+ const ActionList actions = static_cast<QWidget*>(object)->actions();
+ if (!actions.empty()) {
+ const ActionList::const_iterator cend = actions.constEnd();
+ for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
+ if (ctx.mdb->item(*it)) {
+ QAction *action = *it;
+ QObject *obj = action;
+ if (action->menu())
+ obj = action->menu();
+ createModelRecursion(fwi, object, obj, model, ctx);
+ }
+ }
+ }
+ }
+
+ // ------------ ObjectInspectorModel
+ ObjectInspectorModel::ObjectInspectorModel(QObject *parent) :
+ QStandardItemModel(0, NumColumns, parent)
+ {
+ QStringList headers;
+ headers += QCoreApplication::translate("ObjectInspectorModel", "Object");
+ headers += QCoreApplication::translate("ObjectInspectorModel", "Class");
+ Q_ASSERT(headers.size() == NumColumns);
+ setColumnCount(NumColumns);
+ setHorizontalHeaderLabels(headers);
+ // Icons
+ m_icons.layoutIcons[LayoutInfo::NoLayout] = createIconSet(QLatin1String("editbreaklayout.png"));
+ m_icons.layoutIcons[LayoutInfo::HSplitter] = createIconSet(QLatin1String("edithlayoutsplit.png"));
+ m_icons.layoutIcons[LayoutInfo::VSplitter] = createIconSet(QLatin1String("editvlayoutsplit.png"));
+ m_icons.layoutIcons[LayoutInfo::HBox] = createIconSet(QLatin1String("edithlayout.png"));
+ m_icons.layoutIcons[LayoutInfo::VBox] = createIconSet(QLatin1String("editvlayout.png"));
+ m_icons.layoutIcons[LayoutInfo::Grid] = createIconSet(QLatin1String("editgrid.png"));
+ m_icons.layoutIcons[LayoutInfo::Form] = createIconSet(QLatin1String("editform.png"));
+ }
+
+ void ObjectInspectorModel::clearItems()
+ {
+ m_objectIndexMultiMap.clear();
+ m_model.clear();
+ reset(); // force editors to be closed in views
+ removeRow(0);
+ }
+
+ ObjectInspectorModel::UpdateResult ObjectInspectorModel::update(QDesignerFormWindowInterface *fw)
+ {
+ QWidget *mainContainer = fw ? fw->mainContainer() : static_cast<QWidget*>(0);
+ if (!mainContainer) {
+ clearItems();
+ m_formWindow = 0;
+ return NoForm;
+ }
+ m_formWindow = fw;
+ // Build new model and compare to previous one. If the structure is
+ // identical, just update, else rebuild
+ ObjectModel newModel;
+
+ static const QString separator = QCoreApplication::translate("ObjectInspectorModel", "separator");
+ const ModelRecursionContext ctx(fw->core(), separator);
+ createModelRecursion(fw, 0, mainContainer, newModel, ctx);
+
+ if (newModel == m_model) {
+ updateItemContents(m_model, newModel);
+ return Updated;
+ }
+
+ rebuild(newModel);
+ m_model = newModel;
+ return Rebuilt;
+ }
+
+ QObject *ObjectInspectorModel::objectAt(const QModelIndex &index) const
+ {
+ if (index.isValid())
+ if (const QStandardItem *item = itemFromIndex(index))
+ return objectOfItem(item);
+ return 0;
+ }
+
+ // Missing Qt API: get a row
+ ObjectInspectorModel::StandardItemList ObjectInspectorModel::rowAt(QModelIndex index) const
+ {
+ StandardItemList rc;
+ while (true) {
+ rc += itemFromIndex(index);
+ const int nextColumn = index.column() + 1;
+ if (nextColumn >= NumColumns)
+ break;
+ index = index.sibling(index.row(), nextColumn);
+ }
+ return rc;
+ }
+
+ // Rebuild the tree in case the model has completely changed.
+ void ObjectInspectorModel::rebuild(const ObjectModel &newModel)
+ {
+ clearItems();
+ if (newModel.empty())
+ return;
+
+ const ObjectModel::const_iterator mcend = newModel.constEnd();
+ ObjectModel::const_iterator it = newModel.constBegin();
+ // Set up root element
+ StandardItemList rootRow = createModelRow(it->object());
+ it->setItems(rootRow, m_icons);
+ appendRow(rootRow);
+ m_objectIndexMultiMap.insert(it->object(), indexFromItem(rootRow.front()));
+ for (++it; it != mcend; ++it) {
+ // Add to parent item, found via map
+ const QModelIndex parentIndex = m_objectIndexMultiMap.value(it->parent(), QModelIndex());
+ Q_ASSERT(parentIndex.isValid());
+ QStandardItem *parentItem = itemFromIndex(parentIndex);
+ StandardItemList row = createModelRow(it->object());
+ it->setItems(row, m_icons);
+ parentItem->appendRow(row);
+ m_objectIndexMultiMap.insert(it->object(), indexFromItem(row.front()));
+ }
+ }
+
+ // Update item data in case the model has the same structure
+ void ObjectInspectorModel::updateItemContents(ObjectModel &oldModel, const ObjectModel &newModel)
+ {
+ // Change text and icon. Keep a set of changed object
+ // as for example actions might occur several times in the tree.
+ typedef QSet<QObject *> QObjectSet;
+
+ QObjectSet changedObjects;
+
+ const int size = newModel.size();
+ Q_ASSERT(oldModel.size() == size);
+ for (int i = 0; i < size; i++) {
+ const ObjectData &newEntry = newModel[i];
+ ObjectData &entry = oldModel[i];
+ // Has some data changed?
+ if (const unsigned changedMask = entry.compare(newEntry)) {
+ entry = newEntry;
+ QObject * o = entry.object();
+ if (!changedObjects.contains(o)) {
+ changedObjects.insert(o);
+ const QModelIndexList indexes = m_objectIndexMultiMap.values(o);
+ foreach (const QModelIndex &index, indexes)
+ entry.setItemsDisplayData(rowAt(index), m_icons, changedMask);
+ }
+ }
+ }
+ }
+
+ QVariant ObjectInspectorModel::data(const QModelIndex &index, int role) const
+ {
+ const QVariant rc = QStandardItemModel::data(index, role);
+ // Return <noname> if the string is empty for the display role
+ // only (else, editing starts with <noname>).
+ if (role == Qt::DisplayRole && rc.type() == QVariant::String) {
+ const QString s = rc.toString();
+ if (s.isEmpty()) {
+ static const QString noName = QCoreApplication::translate("ObjectInspectorModel", "<noname>");
+ return QVariant(noName);
+ }
+ }
+ return rc;
+ }
+
+ bool ObjectInspectorModel::setData(const QModelIndex &index, const QVariant &value, int role)
+ {
+ if (role != Qt::EditRole || !m_formWindow)
+ return false;
+
+ QObject *object = objectAt(index);
+ if (!object)
+ return false;
+ // Is this a layout widget?
+ const QString nameProperty = isQLayoutWidget(object) ? QLatin1String("layoutName") : QLatin1String("objectName");
+ m_formWindow->commandHistory()->push(createTextPropertyCommand(nameProperty, value.toString(), object, m_formWindow));
+ return true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/objectinspector/objectinspectormodel_p.h b/tools/designer/src/components/objectinspector/objectinspectormodel_p.h
new file mode 100644
index 0000000000..63bc025e2b
--- /dev/null
+++ b/tools/designer/src/components/objectinspector/objectinspectormodel_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef OBJECTINSPECTORMODEL_H
+#define OBJECTINSPECTORMODEL_H
+
+#include <layoutinfo_p.h>
+
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QIcon>
+#include <QtCore/QModelIndex>
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtCore/QMultiMap>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+ // Data structure containing the fixed item type icons
+ struct ObjectInspectorIcons {
+ QIcon layoutIcons[LayoutInfo::UnknownLayout + 1];
+ };
+
+ struct ModelRecursionContext;
+
+ // Data structure representing one item of the object inspector.
+ class ObjectData {
+ public:
+ enum Type {
+ Object,
+ Action,
+ SeparatorAction,
+ ChildWidget, // A child widget
+ LayoutableContainer, // A container that can be laid out
+ LayoutWidget, // A QLayoutWidget
+ ExtensionContainer // QTabWidget and the like, container extension
+ };
+
+ typedef QList<QStandardItem *> StandardItemList;
+
+ explicit ObjectData(QObject *parent, QObject *object, const ModelRecursionContext &ctx);
+ ObjectData();
+
+ inline Type type() const { return m_type; }
+ inline QObject *object() const { return m_object; }
+ inline QObject *parent() const { return m_parent; }
+ inline QString objectName() const { return m_objectName; }
+
+ bool equals(const ObjectData & me) const;
+
+ enum ChangedMask { ClassNameChanged = 1, ObjectNameChanged = 2,
+ ClassIconChanged = 4, TypeChanged = 8,
+ LayoutTypeChanged = 16};
+
+ unsigned compare(const ObjectData & me) const;
+
+ // Initially set up a row
+ void setItems(const StandardItemList &row, const ObjectInspectorIcons &icons) const;
+ // Update row data according to change mask
+ void setItemsDisplayData(const StandardItemList &row, const ObjectInspectorIcons &icons, unsigned mask) const;
+
+ private:
+ void initObject(const ModelRecursionContext &ctx);
+ void initWidget(QWidget *w, const ModelRecursionContext &ctx);
+
+ QObject *m_parent;
+ QObject *m_object;
+ Type m_type;
+ QString m_className;
+ QString m_objectName;
+ QIcon m_classIcon;
+ LayoutInfo::Type m_managedLayoutType;
+ };
+
+ inline bool operator==(const ObjectData &e1, const ObjectData &e2) { return e1.equals(e2); }
+ inline bool operator!=(const ObjectData &e1, const ObjectData &e2) { return !e1.equals(e2); }
+
+ typedef QList<ObjectData> ObjectModel;
+
+ // QStandardItemModel for ObjectInspector. Uses ObjectData/ObjectModel
+ // internally for its updates.
+ class ObjectInspectorModel : public QStandardItemModel {
+ public:
+ typedef QList<QStandardItem *> StandardItemList;
+ enum { ObjectNameColumn, ClassNameColumn, NumColumns };
+
+ explicit ObjectInspectorModel(QObject *parent);
+
+ enum UpdateResult { NoForm, Rebuilt, Updated };
+ UpdateResult update(QDesignerFormWindowInterface *fw);
+
+ const QModelIndexList indexesOf(QObject *o) const { return m_objectIndexMultiMap.values(o); }
+ QObject *objectAt(const QModelIndex &index) const;
+
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+ private:
+ typedef QMultiMap<QObject *,QModelIndex> ObjectIndexMultiMap;
+
+ void rebuild(const ObjectModel &newModel);
+ void updateItemContents(ObjectModel &oldModel, const ObjectModel &newModel);
+ void clearItems();
+ StandardItemList rowAt(QModelIndex index) const;
+
+ ObjectInspectorIcons m_icons;
+ ObjectIndexMultiMap m_objectIndexMultiMap;
+ ObjectModel m_model;
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ };
+} // namespace qdesigner_internal
+
+#endif // OBJECTINSPECTORMODEL_H
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp
new file mode 100644
index 0000000000..2a63ba6885
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "brushpropertymanager.h"
+#include "qtpropertymanager.h"
+#include "qtvariantproperty.h"
+#include "qtpropertybrowserutils_p.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QVariant>
+#include <QtCore/QString>
+
+static const char *brushStyles[] = {
+QT_TRANSLATE_NOOP("BrushPropertyManager", "No brush"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Solid"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 1"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 2"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 3"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 4"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 5"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 6"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 7"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Horizontal"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Vertical"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Cross"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Backward diagonal"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Forward diagonal"),
+QT_TRANSLATE_NOOP("BrushPropertyManager", "Crossing diagonal"),
+};
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+BrushPropertyManager::BrushPropertyManager()
+{
+}
+
+int BrushPropertyManager::brushStyleToIndex(Qt::BrushStyle st)
+{
+ switch (st) {
+ case Qt::NoBrush: return 0;
+ case Qt::SolidPattern: return 1;
+ case Qt::Dense1Pattern: return 2;
+ case Qt::Dense2Pattern: return 3;
+ case Qt::Dense3Pattern: return 4;
+ case Qt::Dense4Pattern: return 5;
+ case Qt::Dense5Pattern: return 6;
+ case Qt::Dense6Pattern: return 7;
+ case Qt::Dense7Pattern: return 8;
+ case Qt::HorPattern: return 9;
+ case Qt::VerPattern: return 10;
+ case Qt::CrossPattern: return 11;
+ case Qt::BDiagPattern: return 12;
+ case Qt::FDiagPattern: return 13;
+ case Qt::DiagCrossPattern: return 14;
+ default: break;
+ }
+ return 0;
+}
+
+Qt::BrushStyle BrushPropertyManager::brushStyleIndexToStyle(int brushStyleIndex)
+{
+ switch (brushStyleIndex) {
+ case 0: return Qt::NoBrush;
+ case 1: return Qt::SolidPattern;
+ case 2: return Qt::Dense1Pattern;
+ case 3: return Qt::Dense2Pattern;
+ case 4: return Qt::Dense3Pattern;
+ case 5: return Qt::Dense4Pattern;
+ case 6: return Qt::Dense5Pattern;
+ case 7: return Qt::Dense6Pattern;
+ case 8: return Qt::Dense7Pattern;
+ case 9: return Qt::HorPattern;
+ case 10: return Qt::VerPattern;
+ case 11: return Qt::CrossPattern;
+ case 12: return Qt::BDiagPattern;
+ case 13: return Qt::FDiagPattern;
+ case 14: return Qt::DiagCrossPattern;
+ }
+ return Qt::NoBrush;
+}
+
+const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons()
+{
+ // Create a map of icons for the brush style editor
+ static EnumIndexIconMap rc;
+ if (rc.empty()) {
+ const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *);
+ QBrush brush(Qt::black);
+ const QIcon solidIcon = QtPropertyBrowserUtils::brushValueIcon(brush);
+ for (int i = 0; i < brushStyleCount; i++) {
+ const Qt::BrushStyle style = brushStyleIndexToStyle(i);
+ brush.setStyle(style);
+ rc.insert(i, QtPropertyBrowserUtils::brushValueIcon(brush));
+ }
+ }
+ return rc;
+}
+
+QString BrushPropertyManager::brushStyleIndexToString(int brushStyleIndex)
+{
+ const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *);
+ return brushStyleIndex < brushStyleCount ? QCoreApplication::translate("BrushPropertyManager", brushStyles[brushStyleIndex]) : QString();
+}
+
+void BrushPropertyManager::initializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int enumTypeId)
+{
+ m_brushValues.insert(property, QBrush());
+ // style
+ QtVariantProperty *styleSubProperty = vm->addProperty(enumTypeId, QCoreApplication::translate("BrushPropertyManager", "Style"));
+ property->addSubProperty(styleSubProperty);
+ QStringList styles;
+ const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *);
+ for (int i = 0; i < brushStyleCount; i++)
+ styles.push_back(QCoreApplication::translate("BrushPropertyManager", brushStyles[i]));
+ styleSubProperty->setAttribute(QLatin1String("enumNames"), styles);
+ styleSubProperty->setAttribute(QLatin1String("enumIcons"), qVariantFromValue(brushStyleIcons()));
+ m_brushPropertyToStyleSubProperty.insert(property, styleSubProperty);
+ m_brushStyleSubPropertyToProperty.insert(styleSubProperty, property);
+ // color
+ QtVariantProperty *colorSubProperty = vm->addProperty(QVariant::Color, QCoreApplication::translate("BrushPropertyManager", "Color"));
+ property->addSubProperty(colorSubProperty);
+ m_brushPropertyToColorSubProperty.insert(property, colorSubProperty);
+ m_brushColorSubPropertyToProperty.insert(colorSubProperty, property);
+}
+
+bool BrushPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ const PropertyBrushMap::iterator brit = m_brushValues.find(property); // Brushes
+ if (brit == m_brushValues.end())
+ return false;
+ m_brushValues.erase(brit);
+ // style
+ PropertyToPropertyMap::iterator subit = m_brushPropertyToStyleSubProperty.find(property);
+ if (subit != m_brushPropertyToStyleSubProperty.end()) {
+ QtProperty *styleProp = subit.value();
+ m_brushStyleSubPropertyToProperty.remove(styleProp);
+ m_brushPropertyToStyleSubProperty.erase(subit);
+ delete styleProp;
+ }
+ // color
+ subit = m_brushPropertyToColorSubProperty.find(property);
+ if (subit != m_brushPropertyToColorSubProperty.end()) {
+ QtProperty *colorProp = subit.value();
+ m_brushColorSubPropertyToProperty.remove(colorProp);
+ m_brushPropertyToColorSubProperty.erase(subit);
+ delete colorProp;
+ }
+ return true;
+}
+
+void BrushPropertyManager::slotPropertyDestroyed(QtProperty *property)
+{
+ PropertyToPropertyMap::iterator subit = m_brushStyleSubPropertyToProperty.find(property);
+ if (subit != m_brushStyleSubPropertyToProperty.end()) {
+ m_brushPropertyToStyleSubProperty[subit.value()] = 0;
+ m_brushStyleSubPropertyToProperty.erase(subit);
+ }
+ subit = m_brushColorSubPropertyToProperty.find(property);
+ if (subit != m_brushColorSubPropertyToProperty.end()) {
+ m_brushPropertyToColorSubProperty[subit.value()] = 0;
+ m_brushColorSubPropertyToProperty.erase(subit);
+ }
+}
+
+
+BrushPropertyManager::ValueChangedResult BrushPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
+{
+ switch (value.type()) {
+ case QVariant::Int: // Style subproperty?
+ if (QtProperty *brushProperty = m_brushStyleSubPropertyToProperty.value(property, 0)) {
+ const QBrush oldValue = m_brushValues.value(brushProperty);
+ QBrush newBrush = oldValue;
+ const int index = value.toInt();
+ newBrush.setStyle(brushStyleIndexToStyle(index));
+ if (newBrush == oldValue)
+ return Unchanged;
+ vm->variantProperty(brushProperty)->setValue(newBrush);
+ return Changed;
+ }
+ break;
+ case QVariant::Color: // Color subproperty?
+ if (QtProperty *brushProperty = m_brushColorSubPropertyToProperty.value(property, 0)) {
+ const QBrush oldValue = m_brushValues.value(brushProperty);
+ QBrush newBrush = oldValue;
+ newBrush.setColor(qvariant_cast<QColor>(value));
+ if (newBrush == oldValue)
+ return Unchanged;
+ vm->variantProperty(brushProperty)->setValue(newBrush);
+ return Changed;
+ }
+ break;
+ default:
+ break;
+ }
+ return NoMatch;
+}
+
+BrushPropertyManager::ValueChangedResult BrushPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
+{
+ if (value.type() != QVariant::Brush)
+ return NoMatch;
+ const PropertyBrushMap::iterator brit = m_brushValues.find(property);
+ if (brit == m_brushValues.end())
+ return NoMatch;
+
+ const QBrush newBrush = qvariant_cast<QBrush>(value);
+ if (newBrush == brit.value())
+ return Unchanged;
+ brit.value() = newBrush;
+ if (QtProperty *styleProperty = m_brushPropertyToStyleSubProperty.value(property))
+ vm->variantProperty(styleProperty)->setValue(brushStyleToIndex(newBrush.style()));
+ if (QtProperty *colorProperty = m_brushPropertyToColorSubProperty.value(property))
+ vm->variantProperty(colorProperty)->setValue(newBrush.color());
+
+ return Changed;
+}
+
+bool BrushPropertyManager::valueText(const QtProperty *property, QString *text) const
+{
+ const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property));
+ if (brit == m_brushValues.constEnd())
+ return false;
+ const QBrush &brush = brit.value();
+ const QString styleName = brushStyleIndexToString(brushStyleToIndex(brush.style()));
+ *text = QCoreApplication::translate("BrushPropertyManager", "[%1, %2]").arg(styleName).arg(QtPropertyBrowserUtils::colorValueText(brush.color()));
+ return true;
+}
+
+bool BrushPropertyManager::valueIcon(const QtProperty *property, QIcon *icon) const
+{
+ const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property));
+ if (brit == m_brushValues.constEnd())
+ return false;
+ *icon = QtPropertyBrowserUtils::brushValueIcon(brit.value());
+ return true;
+}
+
+bool BrushPropertyManager::value(const QtProperty *property, QVariant *v) const
+{
+ const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property));
+ if (brit == m_brushValues.constEnd())
+ return false;
+ qVariantSetValue(*v, brit.value());
+ return true;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/brushpropertymanager.h b/tools/designer/src/components/propertyeditor/brushpropertymanager.h
new file mode 100644
index 0000000000..2bb4933ed5
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/brushpropertymanager.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BRUSHPROPERTYMANAGER_H
+#define BRUSHPROPERTYMANAGER_H
+
+#include <QtCore/QMap>
+#include <QtGui/QBrush>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+class QtProperty;
+class QtVariantPropertyManager;
+
+class QString;
+class QVariant;
+
+namespace qdesigner_internal {
+
+// BrushPropertyManager: A mixin for DesignerPropertyManager that manages brush properties.
+
+class BrushPropertyManager {
+ BrushPropertyManager(const BrushPropertyManager&);
+ BrushPropertyManager &operator=(const BrushPropertyManager&);
+
+public:
+ BrushPropertyManager();
+
+ void initializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int enumTypeId);
+ bool uninitializeProperty(QtProperty *property);
+
+ // Call from slotValueChanged().
+ enum ValueChangedResult { NoMatch, Unchanged, Changed };
+ ValueChangedResult valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value);
+ ValueChangedResult setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value);
+
+ bool valueText(const QtProperty *property, QString *text) const;
+ bool valueIcon(const QtProperty *property, QIcon *icon) const;
+ bool value(const QtProperty *property, QVariant *v) const;
+
+ // Call from QtPropertyManager's propertyDestroyed signal
+ void slotPropertyDestroyed(QtProperty *property);
+
+private:
+ static int brushStyleToIndex(Qt::BrushStyle st);
+ static Qt::BrushStyle brushStyleIndexToStyle(int brushStyleIndex);
+ static QString brushStyleIndexToString(int brushStyleIndex);
+
+ typedef QMap<int, QIcon> EnumIndexIconMap;
+ static const EnumIndexIconMap &brushStyleIcons();
+
+ typedef QMap<QtProperty *, QtProperty *> PropertyToPropertyMap;
+ PropertyToPropertyMap m_brushPropertyToStyleSubProperty;
+ PropertyToPropertyMap m_brushPropertyToColorSubProperty;
+ PropertyToPropertyMap m_brushStyleSubPropertyToProperty;
+ PropertyToPropertyMap m_brushColorSubPropertyToProperty;
+
+ typedef QMap<QtProperty *, QBrush> PropertyBrushMap;
+ PropertyBrushMap m_brushValues;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // BRUSHPROPERTYMANAGER_H
diff --git a/tools/designer/src/components/propertyeditor/defs.cpp b/tools/designer/src/components/propertyeditor/defs.cpp
new file mode 100644
index 0000000000..ebee40a738
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/defs.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "defs.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+int size_type_to_int( QSizePolicy::Policy t )
+{
+ if ( t == QSizePolicy::Fixed )
+ return 0;
+ if ( t == QSizePolicy::Minimum )
+ return 1;
+ if ( t == QSizePolicy::Maximum )
+ return 2;
+ if ( t == QSizePolicy::Preferred )
+ return 3;
+ if ( t == QSizePolicy::MinimumExpanding )
+ return 4;
+ if ( t == QSizePolicy::Expanding )
+ return 5;
+ if ( t == QSizePolicy::Ignored )
+ return 6;
+ return 0;
+}
+
+QString size_type_to_string( QSizePolicy::Policy t )
+{
+ if ( t == QSizePolicy::Fixed )
+ return QString::fromUtf8("Fixed");
+ if ( t == QSizePolicy::Minimum )
+ return QString::fromUtf8("Minimum");
+ if ( t == QSizePolicy::Maximum )
+ return QString::fromUtf8("Maximum");
+ if ( t == QSizePolicy::Preferred )
+ return QString::fromUtf8("Preferred");
+ if ( t == QSizePolicy::MinimumExpanding )
+ return QString::fromUtf8("MinimumExpanding");
+ if ( t == QSizePolicy::Expanding )
+ return QString::fromUtf8("Expanding");
+ if ( t == QSizePolicy::Ignored )
+ return QString::fromUtf8("Ignored");
+ return QString();
+}
+
+QSizePolicy::Policy int_to_size_type( int i )
+{
+ if ( i == 0 )
+ return QSizePolicy::Fixed;
+ if ( i == 1 )
+ return QSizePolicy::Minimum;
+ if ( i == 2 )
+ return QSizePolicy::Maximum;
+ if ( i == 3 )
+ return QSizePolicy::Preferred;
+ if ( i == 4 )
+ return QSizePolicy::MinimumExpanding;
+ if ( i == 5 )
+ return QSizePolicy::Expanding;
+ if ( i == 6 )
+ return QSizePolicy::Ignored;
+ return QSizePolicy::Preferred;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/defs.h b/tools/designer/src/components/propertyeditor/defs.h
new file mode 100644
index 0000000000..e7a48d66fa
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/defs.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFS_H
+#define DEFS_H
+
+#include <QtGui/QSizePolicy>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+int size_type_to_int(QSizePolicy::Policy t);
+QString size_type_to_string(QSizePolicy::Policy t);
+QSizePolicy::Policy int_to_size_type(int i);
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DEFS_H
diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp
new file mode 100644
index 0000000000..1b267aa7ae
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp
@@ -0,0 +1,2604 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "designerpropertymanager.h"
+#include "qtpropertymanager.h"
+#include "paletteeditorbutton.h"
+#include "qlonglongvalidator.h"
+#include "stringlisteditorbutton.h"
+#include "qtresourceview_p.h"
+#include "qtpropertybrowserutils_p.h"
+
+#include <formwindowbase_p.h>
+#include <textpropertyeditor_p.h>
+#include <stylesheeteditor_p.h>
+#include <richtexteditor_p.h>
+#include <plaintexteditor_p.h>
+#include <iconloader_p.h>
+#include <iconselector_p.h>
+#include <abstractdialoggui_p.h>
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+
+#include <QtGui/QLabel>
+#include <QtGui/QToolButton>
+#include <QtGui/QHBoxLayout>
+#include <QtCore/QFileInfo>
+#include <QtGui/QClipboard>
+#include <QtGui/QLineEdit>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QFileDialog>
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QApplication>
+#include <QtCore/QUrl>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+static const char *resettableAttributeC = "resettable";
+static const char *flagsAttributeC = "flags";
+static const char *validationModesAttributeC = "validationMode";
+static const char *superPaletteAttributeC = "superPalette";
+static const char *defaultResourceAttributeC = "defaultResource";
+static const char *fontAttributeC = "font";
+
+class DesignerFlagPropertyType
+{
+};
+
+
+class DesignerAlignmentPropertyType
+{
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(DesignerFlagPropertyType)
+Q_DECLARE_METATYPE(DesignerAlignmentPropertyType)
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ------------ TextEditor
+class TextEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ TextEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+
+ TextPropertyValidationMode textPropertyValidationMode() const;
+ void setTextPropertyValidationMode(TextPropertyValidationMode vm);
+
+ void setRichTextDefaultFont(const QFont &font) { m_richTextDefaultFont = font; }
+ QFont richTextDefaultFont() const { return m_richTextDefaultFont; }
+
+ void setSpacing(int spacing);
+
+ TextPropertyEditor::UpdateMode updateMode() const { return m_editor->updateMode(); }
+ void setUpdateMode(TextPropertyEditor::UpdateMode um) { m_editor->setUpdateMode(um); }
+
+public slots:
+ void setText(const QString &text);
+
+signals:
+ void textChanged(const QString &text);
+
+private slots:
+ void buttonClicked();
+ void resourceActionActivated();
+ void fileActionActivated();
+private:
+ TextPropertyEditor *m_editor;
+ QFont m_richTextDefaultFont;
+ QToolButton *m_button;
+ QMenu *m_menu;
+ QAction *m_resourceAction;
+ QAction *m_fileAction;
+ QHBoxLayout *m_layout;
+ QDesignerFormEditorInterface *m_core;
+};
+
+TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QWidget(parent),
+ m_editor(new TextPropertyEditor(this)),
+ m_richTextDefaultFont(QApplication::font()),
+ m_button(new QToolButton(this)),
+ m_menu(new QMenu(this)),
+ m_resourceAction(new QAction(tr("Choose Resource..."), this)),
+ m_fileAction(new QAction(tr("Choose File..."), this)),
+ m_layout(new QHBoxLayout(this)),
+ m_core(core)
+{
+ m_layout->addWidget(m_editor);
+ m_button->setText(tr("..."));
+ m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
+ m_button->setFixedWidth(20);
+ m_layout->addWidget(m_button);
+ m_layout->setMargin(0);
+ m_layout->setSpacing(0);
+
+ connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated()));
+ connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated()));
+ connect(m_editor, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString)));
+ connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ m_button->setVisible(false);
+ setFocusProxy(m_editor);
+
+ m_menu->addAction(m_resourceAction);
+ m_menu->addAction(m_fileAction);
+}
+
+void TextEditor::setSpacing(int spacing)
+{
+ m_layout->setSpacing(spacing);
+}
+
+TextPropertyValidationMode TextEditor::textPropertyValidationMode() const
+{
+ return m_editor->textPropertyValidationMode();
+}
+
+void TextEditor::setTextPropertyValidationMode(TextPropertyValidationMode vm)
+{
+ m_editor->setTextPropertyValidationMode(vm);
+ if (vm == ValidationURL) {
+ m_button->setMenu(m_menu);
+ m_button->setFixedWidth(30);
+ m_button->setPopupMode(QToolButton::MenuButtonPopup);
+ } else {
+ m_button->setMenu(0);
+ m_button->setFixedWidth(20);
+ m_button->setPopupMode(QToolButton::DelayedPopup);
+ }
+ m_button->setVisible(vm == ValidationStyleSheet || vm == ValidationRichText || vm == ValidationMultiLine || vm == ValidationURL);
+}
+
+void TextEditor::setText(const QString &text)
+{
+ m_editor->setText(text);
+}
+
+void TextEditor::buttonClicked()
+{
+ const QString oldText = m_editor->text();
+ QString newText;
+ switch (textPropertyValidationMode()) {
+ case ValidationStyleSheet: {
+ StyleSheetEditorDialog dlg(m_core, this);
+ dlg.setText(oldText);
+ if (dlg.exec() != QDialog::Accepted)
+ return;
+ newText = dlg.text();
+ }
+ break;
+ case ValidationRichText: {
+ RichTextEditorDialog dlg(m_core, this);
+ dlg.setDefaultFont(m_richTextDefaultFont);
+ dlg.setText(oldText);
+ if (dlg.showDialog() != QDialog::Accepted)
+ return;
+ newText = dlg.text(Qt::AutoText);
+ }
+ break;
+ case ValidationMultiLine: {
+ PlainTextEditorDialog dlg(m_core, this);
+ dlg.setDefaultFont(m_richTextDefaultFont);
+ dlg.setText(oldText);
+ if (dlg.showDialog() != QDialog::Accepted)
+ return;
+ newText = dlg.text();
+ }
+ break;
+ case ValidationURL: {
+ QString oldPath = oldText;
+ if (oldPath.isEmpty() || oldPath.startsWith(QLatin1String("qrc:")))
+ resourceActionActivated();
+ else
+ fileActionActivated();
+ }
+ return;
+ default:
+ return;
+ }
+ if (newText != oldText) {
+ m_editor->setText(newText);
+ emit textChanged(newText);
+ }
+}
+
+void TextEditor::resourceActionActivated()
+{
+ QString oldPath = m_editor->text();
+ if (oldPath.startsWith(QLatin1String("qrc:")))
+ oldPath = oldPath.mid(4);
+ const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this);
+ if (newPath.isEmpty() || newPath == oldPath)
+ return;
+ const QString newText = QLatin1String("qrc:") + newPath;
+ m_editor->setText(newText);
+ emit textChanged(newText);
+}
+
+void TextEditor::fileActionActivated()
+{
+ QString oldPath = m_editor->text();
+ if (oldPath.startsWith(QLatin1String("file:")))
+ oldPath = oldPath.mid(5);
+ const QString newPath = m_core->dialogGui()->getOpenFileName(this, tr("Choose a File"), oldPath);
+ if (newPath.isEmpty() || newPath == oldPath)
+ return;
+ const QString newText = QLatin1String("file:") + newPath;
+ m_editor->setText(newText);
+ emit textChanged(newText);
+}
+
+// ------------ PixmapEditor
+class PixmapEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+
+ void setSpacing(int spacing);
+ void setPixmapCache(DesignerPixmapCache *cache);
+public slots:
+ void setPath(const QString &path);
+ void setDefaultPixmap(const QPixmap &pixmap);
+
+signals:
+ void pathChanged(const QString &path);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event);
+
+private slots:
+ void defaultActionActivated();
+ void resourceActionActivated();
+ void fileActionActivated();
+ void copyActionActivated();
+ void pasteActionActivated();
+ void clipboardDataChanged();
+private:
+ QDesignerFormEditorInterface *m_core;
+ QLabel *m_pixmapLabel;
+ QLabel *m_pathLabel;
+ QToolButton *m_button;
+ QAction *m_resourceAction;
+ QAction *m_fileAction;
+ QAction *m_copyAction;
+ QAction *m_pasteAction;
+ QHBoxLayout *m_layout;
+ QPixmap m_defaultPixmap;
+ QString m_path;
+ DesignerPixmapCache *m_pixmapCache;
+};
+
+PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QWidget(parent),
+ m_core(core),
+ m_pixmapLabel(new QLabel(this)),
+ m_pathLabel(new QLabel(this)),
+ m_button(new QToolButton(this)),
+ m_resourceAction(new QAction(tr("Choose Resource..."), this)),
+ m_fileAction(new QAction(tr("Choose File..."), this)),
+ m_copyAction(new QAction(createIconSet(QLatin1String("editcopy.png")), tr("Copy Path"), this)),
+ m_pasteAction(new QAction(createIconSet(QLatin1String("editpaste.png")), tr("Paste Path"), this)),
+ m_layout(new QHBoxLayout(this)),
+ m_pixmapCache(0)
+{
+ m_layout->addWidget(m_pixmapLabel);
+ m_layout->addWidget(m_pathLabel);
+ m_button->setText(tr("..."));
+ m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
+ m_button->setFixedWidth(30);
+ m_button->setPopupMode(QToolButton::MenuButtonPopup);
+ m_layout->addWidget(m_button);
+ m_layout->setMargin(0);
+ m_layout->setSpacing(0);
+ m_pixmapLabel->setFixedWidth(16);
+ m_pixmapLabel->setAlignment(Qt::AlignCenter);
+ m_pathLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
+
+ QMenu *menu = new QMenu(this);
+ menu->addAction(m_resourceAction);
+ menu->addAction(m_fileAction);
+
+ m_button->setMenu(menu);
+ m_button->setText(tr("..."));
+
+ connect(m_button, SIGNAL(clicked()), this, SLOT(defaultActionActivated()));
+ connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated()));
+ connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated()));
+ connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copyActionActivated()));
+ connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(pasteActionActivated()));
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored));
+ setFocusProxy(m_button);
+
+ connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
+ clipboardDataChanged();
+}
+
+void PixmapEditor::setPixmapCache(DesignerPixmapCache *cache)
+{
+ m_pixmapCache = cache;
+}
+
+void PixmapEditor::setSpacing(int spacing)
+{
+ m_layout->setSpacing(spacing);
+}
+
+void PixmapEditor::setPath(const QString &path)
+{
+ m_path = path;
+ if (m_path.isEmpty()) {
+ m_pathLabel->setText(path);
+ m_pixmapLabel->setPixmap(m_defaultPixmap);
+ m_copyAction->setEnabled(false);
+ } else {
+ m_pathLabel->setText(QFileInfo(m_path).fileName());
+ if (m_pixmapCache)
+ m_pixmapLabel->setPixmap(QIcon(m_pixmapCache->pixmap(PropertySheetPixmapValue(path))).pixmap(16, 16));
+ m_copyAction->setEnabled(true);
+ }
+}
+
+void PixmapEditor::setDefaultPixmap(const QPixmap &pixmap)
+{
+ m_defaultPixmap = QIcon(pixmap).pixmap(16, 16);
+ if (m_path.isEmpty())
+ m_pixmapLabel->setPixmap(m_defaultPixmap);
+}
+
+void PixmapEditor::contextMenuEvent(QContextMenuEvent *event)
+{
+ QMenu menu(this);
+ menu.addAction(m_copyAction);
+ menu.addAction(m_pasteAction);
+ menu.exec(event->globalPos());
+ event->accept();
+}
+
+void PixmapEditor::defaultActionActivated()
+{
+ // Default to resource
+ const PropertySheetPixmapValue::PixmapSource ps = m_path.isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : PropertySheetPixmapValue::getPixmapSource(m_core, m_path);
+ switch (ps) {
+ case PropertySheetPixmapValue::LanguageResourcePixmap:
+ case PropertySheetPixmapValue::ResourcePixmap:
+ resourceActionActivated();
+ break;
+ case PropertySheetPixmapValue::FilePixmap:
+ fileActionActivated();
+ break;
+ }
+}
+
+void PixmapEditor::resourceActionActivated()
+{
+ const QString oldPath = m_path;
+ const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this);
+ if (!newPath.isEmpty() && newPath != oldPath) {
+ setPath(newPath);
+ emit pathChanged(newPath);
+ }
+}
+
+void PixmapEditor::fileActionActivated()
+{
+ const QString newPath = IconSelector::choosePixmapFile(m_path, m_core->dialogGui(), this);
+ if (!newPath.isEmpty() && newPath != m_path) {
+ setPath(newPath);
+ emit pathChanged(newPath);
+ }
+}
+
+void PixmapEditor::copyActionActivated()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setText(m_path);
+}
+
+void PixmapEditor::pasteActionActivated()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ QString subtype = QLatin1String("plain");
+ QString text = clipboard->text(subtype);
+ if (!text.isNull()) {
+ QStringList list = text.split(QLatin1Char('\n'));
+ if (list.size() > 0) {
+ text = list.at(0);
+ setPath(text);
+ emit pathChanged(text);
+ }
+ }
+}
+
+void PixmapEditor::clipboardDataChanged()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ QString subtype = QLatin1String("plain");
+ const QString text = clipboard->text(subtype);
+ m_pasteAction->setEnabled(!text.isNull());
+}
+
+// --------------- ResetWidget
+class ResetWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ResetWidget(QtProperty *property, QWidget *parent = 0);
+
+ void setWidget(QWidget *widget);
+ void setResetEnabled(bool enabled);
+ void setValueText(const QString &text);
+ void setValueIcon(const QIcon &icon);
+ void setSpacing(int spacing);
+signals:
+ void resetProperty(QtProperty *property);
+private slots:
+ void slotClicked();
+private:
+ QtProperty *m_property;
+ QLabel *m_textLabel;
+ QLabel *m_iconLabel;
+ QToolButton *m_button;
+ int m_spacing;
+};
+
+ResetWidget::ResetWidget(QtProperty *property, QWidget *parent) :
+ QWidget(parent),
+ m_property(property),
+ m_textLabel(new QLabel(this)),
+ m_iconLabel(new QLabel(this)),
+ m_button(new QToolButton(this)),
+ m_spacing(-1)
+{
+ m_textLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
+ m_iconLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ m_button->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ m_button->setIcon(createIconSet(QLatin1String("resetproperty.png")));
+ m_button->setIconSize(QSize(8,8));
+ m_button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
+ connect(m_button, SIGNAL(clicked()), this, SLOT(slotClicked()));
+ QLayout *layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->setSpacing(m_spacing);
+ layout->addWidget(m_iconLabel);
+ layout->addWidget(m_textLabel);
+ layout->addWidget(m_button);
+ setFocusProxy(m_textLabel);
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+}
+
+void ResetWidget::setSpacing(int spacing)
+{
+ m_spacing = spacing;
+ layout()->setSpacing(m_spacing);
+}
+
+void ResetWidget::setWidget(QWidget *widget)
+{
+ if (m_textLabel) {
+ delete m_textLabel;
+ m_textLabel = 0;
+ }
+ if (m_iconLabel) {
+ delete m_iconLabel;
+ m_iconLabel = 0;
+ }
+ delete layout();
+ QLayout *layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->setSpacing(m_spacing);
+ layout->addWidget(widget);
+ layout->addWidget(m_button);
+ setFocusProxy(widget);
+}
+
+void ResetWidget::setResetEnabled(bool enabled)
+{
+ m_button->setEnabled(enabled);
+}
+
+void ResetWidget::setValueText(const QString &text)
+{
+ if (m_textLabel)
+ m_textLabel->setText(text);
+}
+
+void ResetWidget::setValueIcon(const QIcon &icon)
+{
+ QPixmap pix = icon.pixmap(QSize(16, 16));
+ if (m_iconLabel) {
+ m_iconLabel->setVisible(!pix.isNull());
+ m_iconLabel->setPixmap(pix);
+ }
+}
+
+void ResetWidget::slotClicked()
+{
+ emit resetProperty(m_property);
+}
+
+
+// ------------ DesignerPropertyManager:
+
+DesignerPropertyManager::DesignerPropertyManager(QDesignerFormEditorInterface *core, QObject *parent) :
+ QtVariantPropertyManager(parent),
+ m_changingSubValue(false),
+ m_core(core),
+ m_sourceOfChange(0)
+{
+ connect(this, SIGNAL(valueChanged(QtProperty*,QVariant)), this, SLOT(slotValueChanged(QtProperty*, QVariant)));
+ connect(this, SIGNAL(propertyDestroyed(QtProperty*)), this, SLOT(slotPropertyDestroyed(QtProperty*)));
+}
+
+DesignerPropertyManager::~DesignerPropertyManager()
+{
+ clear();
+}
+
+int DesignerPropertyManager::bitCount(int mask) const
+{
+ int count = 0;
+ for (; mask; count++)
+ mask &= mask - 1; // clear the least significant bit set
+ return count;
+}
+
+int DesignerPropertyManager::alignToIndexH(uint align) const
+{
+ if (align & Qt::AlignLeft)
+ return 0;
+ if (align & Qt::AlignHCenter)
+ return 1;
+ if (align & Qt::AlignRight)
+ return 2;
+ if (align & Qt::AlignJustify)
+ return 3;
+ return 0;
+}
+
+int DesignerPropertyManager::alignToIndexV(uint align) const
+{
+ if (align & Qt::AlignTop)
+ return 0;
+ if (align & Qt::AlignVCenter)
+ return 1;
+ if (align & Qt::AlignBottom)
+ return 2;
+ return 1;
+}
+
+uint DesignerPropertyManager::indexHToAlign(int idx) const
+{
+ switch (idx) {
+ case 0: return Qt::AlignLeft;
+ case 1: return Qt::AlignHCenter;
+ case 2: return Qt::AlignRight;
+ case 3: return Qt::AlignJustify;
+ default: break;
+ }
+ return Qt::AlignLeft;
+}
+
+uint DesignerPropertyManager::indexVToAlign(int idx) const
+{
+ switch (idx) {
+ case 0: return Qt::AlignTop;
+ case 1: return Qt::AlignVCenter;
+ case 2: return Qt::AlignBottom;
+ default: break;
+ }
+ return Qt::AlignVCenter;
+}
+
+QString DesignerPropertyManager::indexHToString(int idx) const
+{
+ switch (idx) {
+ case 0: return tr("AlignLeft");
+ case 1: return tr("AlignHCenter");
+ case 2: return tr("AlignRight");
+ case 3: return tr("AlignJustify");
+ default: break;
+ }
+ return tr("AlignLeft");
+}
+
+QString DesignerPropertyManager::indexVToString(int idx) const
+{
+ switch (idx) {
+ case 0: return tr("AlignTop");
+ case 1: return tr("AlignVCenter");
+ case 2: return tr("AlignBottom");
+ default: break;
+ }
+ return tr("AlignVCenter");
+}
+
+void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVariant &value)
+{
+ if (m_changingSubValue)
+ return;
+ bool enableSubPropertyHandling = true;
+
+ if (QtProperty *flagProperty = m_flagToProperty.value(property, 0)) {
+ const QList<QtProperty *> subFlags = m_propertyToFlags.value(flagProperty);
+ const int subFlagCount = subFlags.count();
+ // flag changed
+ const bool subValue = variantProperty(property)->value().toBool();
+ const int subIndex = subFlags.indexOf(property);
+ if (subIndex < 0)
+ return;
+
+ uint newValue = 0;
+
+ m_changingSubValue = true;
+
+ FlagData data = m_flagValues.value(flagProperty);
+ const QList<uint> values = data.values;
+ // Compute new value, without including (additional) supermasks
+ if (values.at(subIndex) == 0) {
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ subFlag->setValue(i == subIndex);
+ }
+ } else {
+ if (subValue)
+ newValue = values.at(subIndex); // value mask of subValue
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ if (subFlag->value().toBool() && bitCount(values.at(i)) == 1)
+ newValue |= values.at(i);
+ }
+ if (newValue == 0) {
+ // Uncheck all items except 0-mask
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ subFlag->setValue(values.at(i) == 0);
+ }
+ } else if (newValue == data.val) {
+ if (!subValue && bitCount(values.at(subIndex)) > 1) {
+ // We unchecked something, but the original value still holds
+ variantProperty(property)->setValue(true);
+ }
+ } else {
+ // Make sure 0-mask is not selected
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ if (values.at(i) == 0)
+ subFlag->setValue(false);
+ }
+ // Check/uncheck proper masks
+ if (subValue) {
+ // Make sure submasks and supermasks are selected
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ const uint vi = values.at(i);
+ if ((vi != 0) && ((vi & newValue) == vi) && !subFlag->value().toBool())
+ subFlag->setValue(true);
+ }
+ } else {
+ // Make sure supermasks are not selected if they're no longer valid
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ const uint vi = values.at(i);
+ if (subFlag->value().toBool() && ((vi & newValue) != vi))
+ subFlag->setValue(false);
+ }
+ }
+ }
+ }
+ m_changingSubValue = false;
+ data.val = newValue;
+ QVariant v;
+ qVariantSetValue(v, data.val);
+ variantProperty(flagProperty)->setValue(v);
+ } else if (QtProperty *alignProperty = m_alignHToProperty.value(property, 0)) {
+ const uint v = m_alignValues.value(alignProperty);
+ const uint newValue = indexHToAlign(value.toInt()) | indexVToAlign(alignToIndexV(v));
+ if (v == newValue)
+ return;
+
+ variantProperty(alignProperty)->setValue(newValue);
+ } else if (QtProperty *alignProperty = m_alignVToProperty.value(property, 0)) {
+ const uint v = m_alignValues.value(alignProperty);
+ const uint newValue = indexVToAlign(value.toInt()) | indexHToAlign(alignToIndexH(v));
+ if (v == newValue)
+ return;
+
+ variantProperty(alignProperty)->setValue(newValue);
+ } else if (QtProperty *stringProperty = m_commentToString.value(property, 0)) {
+ const PropertySheetStringValue v = m_stringValues.value(stringProperty);
+ PropertySheetStringValue newValue = v;
+ newValue.setComment(value.toString());
+ if (v == newValue)
+ return;
+
+ variantProperty(stringProperty)->setValue(qVariantFromValue(newValue));
+ } else if (QtProperty *stringProperty = m_translatableToString.value(property, 0)) {
+ const PropertySheetStringValue v = m_stringValues.value(stringProperty);
+ PropertySheetStringValue newValue = v;
+ newValue.setTranslatable(value.toBool());
+ if (v == newValue)
+ return;
+
+ variantProperty(stringProperty)->setValue(qVariantFromValue(newValue));
+ } else if (QtProperty *stringProperty = m_disambiguationToString.value(property, 0)) {
+ const PropertySheetStringValue v = m_stringValues.value(stringProperty);
+ PropertySheetStringValue newValue = v;
+ newValue.setDisambiguation(value.toString());
+ if (v == newValue)
+ return;
+
+ variantProperty(stringProperty)->setValue(qVariantFromValue(newValue));
+ } else if (QtProperty *keySequenceProperty = m_commentToKeySequence.value(property, 0)) {
+ const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty);
+ PropertySheetKeySequenceValue newValue = v;
+ newValue.setComment(value.toString());
+ if (v == newValue)
+ return;
+
+ variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue));
+ } else if (QtProperty *keySequenceProperty = m_translatableToKeySequence.value(property, 0)) {
+ const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty);
+ PropertySheetKeySequenceValue newValue = v;
+ newValue.setTranslatable(value.toBool());
+ if (v == newValue)
+ return;
+
+ variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue));
+ } else if (QtProperty *keySequenceProperty = m_disambiguationToKeySequence.value(property, 0)) {
+ const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty);
+ PropertySheetKeySequenceValue newValue = v;
+ newValue.setDisambiguation(value.toString());
+ if (v == newValue)
+ return;
+
+ variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue));
+ } else if (QtProperty *iProperty = m_iconSubPropertyToProperty.value(property, 0)) {
+ QtVariantProperty *iconProperty = variantProperty(iProperty);
+ PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(iconProperty->value());
+ QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(property);
+ icon.setPixmap(pair.first, pair.second, qVariantValue<PropertySheetPixmapValue>(value));
+ QtProperty *origSourceOfChange = m_sourceOfChange;
+ if (!origSourceOfChange)
+ m_sourceOfChange = property;
+ iconProperty->setValue(qVariantFromValue(icon));
+ if (!origSourceOfChange)
+ m_sourceOfChange = origSourceOfChange;
+ } else if (m_iconValues.contains(property)) {
+ enableSubPropertyHandling = m_sourceOfChange;
+ } else {
+ if (m_brushManager.valueChanged(this, property, value) == BrushPropertyManager::Unchanged)
+ return;
+ if (m_fontManager.valueChanged(this, property, value) == FontPropertyManager::Unchanged)
+ return;
+ }
+
+ emit valueChanged(property, value, enableSubPropertyHandling);
+}
+
+void DesignerPropertyManager::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *flagProperty = m_flagToProperty.value(property, 0)) {
+ PropertyToPropertyListMap::iterator it = m_propertyToFlags.find(flagProperty);
+ QList<QtProperty *> &propertyList = it.value();
+ propertyList.replace(propertyList.indexOf(property), 0);
+ m_flagToProperty.remove(property);
+ } else if (QtProperty *alignProperty = m_alignHToProperty.value(property, 0)) {
+ m_propertyToAlignH.remove(alignProperty);
+ m_alignHToProperty.remove(property);
+ } else if (QtProperty *alignProperty = m_alignVToProperty.value(property, 0)) {
+ m_propertyToAlignV.remove(alignProperty);
+ m_alignVToProperty.remove(property);
+ } else if (QtProperty *stringCommentProperty = m_commentToString.value(property, 0)) {
+ m_stringToComment.remove(stringCommentProperty);
+ m_commentToString.remove(property);
+ } else if (QtProperty *stringTranslatableProperty = m_translatableToString.value(property, 0)) {
+ m_stringToTranslatable.remove(stringTranslatableProperty);
+ m_translatableToString.remove(property);
+ } else if (QtProperty *stringDisambiguationProperty = m_disambiguationToString.value(property, 0)) {
+ m_stringToDisambiguation.remove(stringDisambiguationProperty);
+ m_disambiguationToString.remove(property);
+ } else if (QtProperty *keySequenceCommentProperty = m_commentToKeySequence.value(property, 0)) {
+ m_keySequenceToComment.remove(keySequenceCommentProperty);
+ m_commentToKeySequence.remove(property);
+ } else if (QtProperty *keySequenceTranslatableProperty = m_translatableToKeySequence.value(property, 0)) {
+ m_keySequenceToTranslatable.remove(keySequenceTranslatableProperty);
+ m_translatableToKeySequence.remove(property);
+ } else if (QtProperty *keySequenceDisambiguationProperty = m_disambiguationToKeySequence.value(property, 0)) {
+ m_keySequenceToDisambiguation.remove(keySequenceDisambiguationProperty);
+ m_disambiguationToKeySequence.remove(property);
+ } else if (QtProperty *iconProperty = m_iconSubPropertyToProperty.value(property, 0)) {
+ QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> >::iterator it =
+ m_propertyToIconSubProperties.find(iconProperty);
+ QPair<QIcon::Mode, QIcon::State> state = m_iconSubPropertyToState.value(property);
+ QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> &propertyList = it.value();
+ propertyList.remove(state);
+ m_iconSubPropertyToState.remove(property);
+ m_iconSubPropertyToProperty.remove(property);
+ } else {
+ m_fontManager.slotPropertyDestroyed(property);
+ m_brushManager.slotPropertyDestroyed(property);
+ }
+}
+
+QStringList DesignerPropertyManager::attributes(int propertyType) const
+{
+ if (!isPropertyTypeSupported(propertyType))
+ return QStringList();
+
+ QStringList list = QtVariantPropertyManager::attributes(propertyType);
+ if (propertyType == designerFlagTypeId()) {
+ list.append(QLatin1String(flagsAttributeC));
+ } else if (propertyType == designerPixmapTypeId()) {
+ list.append(QLatin1String(defaultResourceAttributeC));
+ } else if (propertyType == designerIconTypeId()) {
+ list.append(QLatin1String(defaultResourceAttributeC));
+ } else if (propertyType == designerStringTypeId() || propertyType == QVariant::String) {
+ list.append(QLatin1String(validationModesAttributeC));
+ list.append(QLatin1String(fontAttributeC));
+ } else if (propertyType == QVariant::Palette) {
+ list.append(QLatin1String(superPaletteAttributeC));
+ }
+ list.append(QLatin1String(resettableAttributeC));
+ return list;
+}
+
+int DesignerPropertyManager::attributeType(int propertyType, const QString &attribute) const
+{
+ if (!isPropertyTypeSupported(propertyType))
+ return 0;
+
+ if (propertyType == designerFlagTypeId() && attribute == QLatin1String(flagsAttributeC))
+ return designerFlagListTypeId();
+ if (propertyType == designerPixmapTypeId() && attribute == QLatin1String(defaultResourceAttributeC))
+ return QVariant::Pixmap;
+ if (propertyType == designerIconTypeId() && attribute == QLatin1String(defaultResourceAttributeC))
+ return QVariant::Icon;
+ if (attribute == QLatin1String(resettableAttributeC))
+ return QVariant::Bool;
+ if (propertyType == designerStringTypeId() || propertyType == QVariant::String) {
+ if (attribute == QLatin1String(validationModesAttributeC))
+ return QVariant::Int;
+ if (attribute == QLatin1String(fontAttributeC))
+ return QVariant::Font;
+ }
+ if (propertyType == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC))
+ return QVariant::Palette;
+
+ return QtVariantPropertyManager::attributeType(propertyType, attribute);
+}
+
+QVariant DesignerPropertyManager::attributeValue(const QtProperty *property, const QString &attribute) const
+{
+ QtProperty *prop = const_cast<QtProperty *>(property);
+
+ if (attribute == QLatin1String(resettableAttributeC)) {
+ const PropertyBoolMap::const_iterator it = m_resetMap.constFind(prop);
+ if (it != m_resetMap.constEnd())
+ return it.value();
+ }
+
+ if (attribute == QLatin1String(flagsAttributeC)) {
+ PropertyFlagDataMap::const_iterator it = m_flagValues.constFind(prop);
+ if (it != m_flagValues.constEnd()) {
+ QVariant v;
+ qVariantSetValue(v, it.value().flags);
+ return v;
+ }
+ }
+ if (attribute == QLatin1String(validationModesAttributeC)) {
+ const PropertyIntMap::const_iterator it = m_stringAttributes.constFind(prop);
+ if (it != m_stringAttributes.constEnd())
+ return it.value();
+ }
+
+ if (attribute == QLatin1String(fontAttributeC)) {
+ const PropertyFontMap::const_iterator it = m_stringFontAttributes.constFind(prop);
+ if (it != m_stringFontAttributes.constEnd())
+ return it.value();
+ }
+
+ if (attribute == QLatin1String(superPaletteAttributeC)) {
+ PropertyPaletteDataMap::const_iterator it = m_paletteValues.constFind(prop);
+ if (it != m_paletteValues.constEnd())
+ return it.value().superPalette;
+ }
+
+ if (attribute == QLatin1String(defaultResourceAttributeC)) {
+ QMap<QtProperty *, QPixmap>::const_iterator itPix = m_defaultPixmaps.constFind(prop);
+ if (itPix != m_defaultPixmaps.constEnd())
+ return itPix.value();
+
+ QMap<QtProperty *, QIcon>::const_iterator itIcon = m_defaultIcons.constFind(prop);
+ if (itIcon != m_defaultIcons.constEnd())
+ return itIcon.value();
+ }
+
+ return QtVariantPropertyManager::attributeValue(property, attribute);
+}
+
+void DesignerPropertyManager::setAttribute(QtProperty *property,
+ const QString &attribute, const QVariant &value)
+{
+ if (attribute == QLatin1String(resettableAttributeC) && m_resetMap.contains(property)) {
+ if (value.userType() != QVariant::Bool)
+ return;
+ const bool val = value.toBool();
+ const PropertyBoolMap::iterator it = m_resetMap.find(property);
+ if (it.value() == val)
+ return;
+ it.value() = val;
+ emit attributeChanged(variantProperty(property), attribute, value);
+ return;
+ } else if (attribute == QLatin1String(flagsAttributeC) && m_flagValues.contains(property)) {
+ if (value.userType() != designerFlagListTypeId())
+ return;
+
+ const DesignerFlagList flags = qVariantValue<DesignerFlagList>(value);
+ PropertyFlagDataMap::iterator fit = m_flagValues.find(property);
+ FlagData data = fit.value();
+ if (data.flags == flags)
+ return;
+
+ PropertyToPropertyListMap::iterator pfit = m_propertyToFlags.find(property);
+ QListIterator<QtProperty *> itProp(pfit.value());
+ while (itProp.hasNext()) {
+ if (QtProperty *prop = itProp.next()) {
+ delete prop;
+ m_flagToProperty.remove(prop);
+ }
+ }
+ pfit.value().clear();
+
+ QList<uint> values;
+
+ QListIterator<QPair<QString, uint> > itFlag(flags);
+ while (itFlag.hasNext()) {
+ const QPair<QString, uint> pair = itFlag.next();
+ const QString flagName = pair.first;
+ QtProperty *prop = addProperty(QVariant::Bool);
+ prop->setPropertyName(flagName);
+ property->addSubProperty(prop);
+ m_propertyToFlags[property].append(prop);
+ m_flagToProperty[prop] = property;
+ values.append(pair.second);
+ }
+
+ data.val = 0;
+ data.flags = flags;
+ data.values = values;
+
+ fit.value() = data;
+
+ QVariant v;
+ qVariantSetValue(v, flags);
+ emit attributeChanged(property, attribute, v);
+
+ emit propertyChanged(property);
+ emit QtVariantPropertyManager::valueChanged(property, data.val);
+ } else if (attribute == QLatin1String(validationModesAttributeC) && m_stringAttributes.contains(property)) {
+ if (value.userType() != QVariant::Int)
+ return;
+
+ const PropertyIntMap::iterator it = m_stringAttributes.find(property);
+ const int oldValue = it.value();
+
+ const int newValue = value.toInt();
+
+ if (oldValue == newValue)
+ return;
+
+ it.value() = newValue;
+
+ emit attributeChanged(property, attribute, newValue);
+ } else if (attribute == QLatin1String(fontAttributeC) && m_stringFontAttributes.contains(property)) {
+ if (value.userType() != QVariant::Font)
+ return;
+
+ const PropertyFontMap::iterator it = m_stringFontAttributes.find(property);
+ const QFont oldValue = it.value();
+
+ const QFont newValue = qvariant_cast<QFont>(value);
+
+ if (oldValue == newValue)
+ return;
+
+ it.value() = newValue;
+
+ emit attributeChanged(property, attribute, newValue);
+ } else if (attribute == QLatin1String(superPaletteAttributeC) && m_paletteValues.contains(property)) {
+ if (value.userType() != QVariant::Palette)
+ return;
+
+ QPalette superPalette = qVariantValue<QPalette>(value);
+
+ const PropertyPaletteDataMap::iterator it = m_paletteValues.find(property);
+ PaletteData data = it.value();
+ if (data.superPalette == superPalette)
+ return;
+
+ data.superPalette = superPalette;
+ // resolve here
+ const uint mask = data.val.resolve();
+ data.val = data.val.resolve(superPalette);
+ data.val.resolve(mask);
+
+ it.value() = data;
+
+ QVariant v;
+ qVariantSetValue(v, superPalette);
+ emit attributeChanged(property, attribute, v);
+
+ emit propertyChanged(property);
+ emit QtVariantPropertyManager::valueChanged(property, data.val); // if resolve was done, this is also for consistency
+ } else if (attribute == QLatin1String(defaultResourceAttributeC) && m_defaultPixmaps.contains(property)) {
+ if (value.userType() != QVariant::Pixmap)
+ return;
+
+ QPixmap defaultPixmap = qVariantValue<QPixmap>(value);
+
+ const QMap<QtProperty *, QPixmap>::iterator it = m_defaultPixmaps.find(property);
+ QPixmap oldDefaultPixmap = it.value();
+ if (defaultPixmap.cacheKey() == oldDefaultPixmap.cacheKey())
+ return;
+
+ it.value() = defaultPixmap;
+
+ QVariant v = qVariantFromValue(defaultPixmap);
+ emit attributeChanged(property, attribute, v);
+
+ emit propertyChanged(property);
+ } else if (attribute == QLatin1String(defaultResourceAttributeC) && m_defaultIcons.contains(property)) {
+ if (value.userType() != QVariant::Icon)
+ return;
+
+ QIcon defaultIcon = qVariantValue<QIcon>(value);
+
+ const QMap<QtProperty *, QIcon>::iterator it = m_defaultIcons.find(property);
+ QIcon oldDefaultIcon = it.value();
+ if (defaultIcon.cacheKey() == oldDefaultIcon.cacheKey())
+ return;
+
+ it.value() = defaultIcon;
+
+ qdesigner_internal::PropertySheetIconValue icon = m_iconValues.value(property);
+ if (icon.paths().isEmpty()) {
+ QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subIconProperties = m_propertyToIconSubProperties.value(property);
+ QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itSub(subIconProperties);
+ while (itSub.hasNext()) {
+ QPair<QIcon::Mode, QIcon::State> pair = itSub.next().key();
+ QtProperty *subProp = itSub.value();
+ setAttribute(subProp, QLatin1String(defaultResourceAttributeC),
+ defaultIcon.pixmap(16, 16, pair.first, pair.second));
+ }
+ }
+
+ QVariant v = qVariantFromValue(defaultIcon);
+ emit attributeChanged(property, attribute, v);
+
+ emit propertyChanged(property);
+ }
+ QtVariantPropertyManager::setAttribute(property, attribute, value);
+}
+
+int DesignerPropertyManager::designerFlagTypeId()
+{
+ static const int rc = qMetaTypeId<DesignerFlagPropertyType>();
+ return rc;
+}
+
+int DesignerPropertyManager::designerFlagListTypeId()
+{
+ static const int rc = qMetaTypeId<DesignerFlagList>();
+ return rc;
+}
+
+int DesignerPropertyManager::designerAlignmentTypeId()
+{
+ static const int rc = qMetaTypeId<DesignerAlignmentPropertyType>();
+ return rc;
+}
+
+int DesignerPropertyManager::designerPixmapTypeId()
+{
+ return qMetaTypeId<PropertySheetPixmapValue>();
+}
+
+int DesignerPropertyManager::designerIconTypeId()
+{
+ return qMetaTypeId<PropertySheetIconValue>();
+}
+
+int DesignerPropertyManager::designerStringTypeId()
+{
+ return qMetaTypeId<PropertySheetStringValue>();
+}
+
+int DesignerPropertyManager::designerKeySequenceTypeId()
+{
+ return qMetaTypeId<PropertySheetKeySequenceValue>();
+}
+
+bool DesignerPropertyManager::isPropertyTypeSupported(int propertyType) const
+{
+ switch (propertyType) {
+ case QVariant::Palette:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Url:
+ case QVariant::ByteArray:
+ case QVariant::StringList:
+ case QVariant::Brush:
+ return true;
+ default:
+ break;
+ }
+
+ if (propertyType == designerFlagTypeId())
+ return true;
+ if (propertyType == designerAlignmentTypeId())
+ return true;
+ if (propertyType == designerPixmapTypeId())
+ return true;
+ if (propertyType == designerIconTypeId())
+ return true;
+ if (propertyType == designerStringTypeId())
+ return true;
+ if (propertyType == designerKeySequenceTypeId())
+ return true;
+ return QtVariantPropertyManager::isPropertyTypeSupported(propertyType);
+}
+
+QString DesignerPropertyManager::valueText(const QtProperty *property) const
+{
+ if (m_flagValues.contains(const_cast<QtProperty *>(property))) {
+ const FlagData data = m_flagValues.value(const_cast<QtProperty *>(property));
+ const uint v = data.val;
+ const QChar bar = QLatin1Char('|');
+ QString valueStr;
+ const QList<QPair<QString, uint> > flags = data.flags;
+ const QList<QPair<QString, uint> >::const_iterator fcend = flags.constEnd();
+ for (QList<QPair<QString, uint> >::const_iterator it = flags.constBegin(); it != fcend; ++it) {
+ const uint val = it->second;
+ const bool checked = (val == 0) ? (v == 0) : ((val & v) == val);
+ if (checked) {
+ if (!valueStr.isEmpty())
+ valueStr += bar;
+ valueStr += it->first;
+ }
+ }
+ return valueStr;
+ }
+ if (m_alignValues.contains(const_cast<QtProperty *>(property))) {
+ const uint v = m_alignValues.value(const_cast<QtProperty *>(property));
+ return tr("%1, %2").arg(indexHToString(alignToIndexH(v))).arg(indexVToString(alignToIndexV(v)));
+ }
+ if (m_paletteValues.contains(const_cast<QtProperty *>(property))) {
+ const PaletteData data = m_paletteValues.value(const_cast<QtProperty *>(property));
+ const uint mask = data.val.resolve();
+ if (mask)
+ return tr("Customized (%n roles)", 0, bitCount(mask));
+ static const QString inherited = tr("Inherited");
+ return inherited;
+ }
+ if (m_iconValues.contains(const_cast<QtProperty *>(property))) {
+ const PropertySheetIconValue::ModeStateToPixmapMap paths = m_iconValues.value(const_cast<QtProperty *>(property)).paths();
+ const PropertySheetIconValue::ModeStateToPixmapMap::const_iterator it = paths.constFind(qMakePair(QIcon::Normal, QIcon::Off));
+ if (it == paths.constEnd())
+ return QString();
+ return QFileInfo(it.value().path()).fileName();
+ }
+ if (m_pixmapValues.contains(const_cast<QtProperty *>(property))) {
+ const QString path = m_pixmapValues.value(const_cast<QtProperty *>(property)).path();
+ if (path.isEmpty())
+ return QString();
+ return QFileInfo(path).fileName();
+ }
+ if (m_uintValues.contains(const_cast<QtProperty *>(property))) {
+ return QString::number(m_uintValues.value(const_cast<QtProperty *>(property)));
+ }
+ if (m_longLongValues.contains(const_cast<QtProperty *>(property))) {
+ return QString::number(m_longLongValues.value(const_cast<QtProperty *>(property)));
+ }
+ if (m_uLongLongValues.contains(const_cast<QtProperty *>(property))) {
+ return QString::number(m_uLongLongValues.value(const_cast<QtProperty *>(property)));
+ }
+ if (m_urlValues.contains(const_cast<QtProperty *>(property))) {
+ return m_urlValues.value(const_cast<QtProperty *>(property)).toString();
+ }
+ if (m_byteArrayValues.contains(const_cast<QtProperty *>(property))) {
+ return QString::fromUtf8(m_byteArrayValues.value(const_cast<QtProperty *>(property)));
+ }
+ if (m_stringListValues.contains(const_cast<QtProperty *>(property))) {
+ return m_stringListValues.value(const_cast<QtProperty *>(property)).join(QLatin1String("; "));
+ }
+ if (QtVariantPropertyManager::valueType(property) == QVariant::String || QtVariantPropertyManager::valueType(property) == designerStringTypeId()) {
+ const QString str = (QtVariantPropertyManager::valueType(property) == QVariant::String) ? value(property).toString() : qVariantValue<PropertySheetStringValue>(value(property)).value();
+ const int validationMode = attributeValue(property, QLatin1String(validationModesAttributeC)).toInt();
+ return TextPropertyEditor::stringToEditorString(str, static_cast<TextPropertyValidationMode>(validationMode));
+ }
+ if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId()) {
+ return qVariantValue<PropertySheetKeySequenceValue>(value(property)).value();
+ }
+ if (QtVariantPropertyManager::valueType(property) == QVariant::Bool) {
+ return QString();
+ }
+
+ QString rc;
+ if (m_brushManager.valueText(property, &rc))
+ return rc;
+ return QtVariantPropertyManager::valueText(property);
+}
+
+void DesignerPropertyManager::reloadResourceProperties()
+{
+ DesignerIconCache *iconCache = 0;
+ QMapIterator<QtProperty *, qdesigner_internal::PropertySheetIconValue> itIcon(m_iconValues);
+ while (itIcon.hasNext()) {
+ QtProperty *property = itIcon.next().key();
+ PropertySheetIconValue icon = itIcon.value();
+
+ QIcon defaultIcon = m_defaultIcons.value(property);
+ if (!icon.paths().isEmpty()) {
+ if (!iconCache) {
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
+ qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow);
+ iconCache = fwb->iconCache();
+ }
+ if (iconCache)
+ defaultIcon = iconCache->icon(icon);
+ }
+
+ QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> iconPaths = icon.paths();
+
+ QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subProperties = m_propertyToIconSubProperties.value(property);
+ QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itSub(subProperties);
+ while (itSub.hasNext()) {
+ const QPair<QIcon::Mode, QIcon::State> pair = itSub.next().key();
+ QtVariantProperty *subProperty = variantProperty(itSub.value());
+ subProperty->setAttribute(QLatin1String(defaultResourceAttributeC),
+ defaultIcon.pixmap(16, 16, pair.first, pair.second));
+ }
+
+ emit propertyChanged(property);
+ emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itIcon.value()));
+ }
+ QMapIterator<QtProperty *, qdesigner_internal::PropertySheetPixmapValue> itPix(m_pixmapValues);
+ while (itPix.hasNext()) {
+ QtProperty *property = itPix.next().key();
+ emit propertyChanged(property);
+ emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itPix.value()));
+ }
+}
+
+QIcon DesignerPropertyManager::valueIcon(const QtProperty *property) const
+{
+ if (m_iconValues.contains(const_cast<QtProperty *>(property))) {
+ if (!property->isModified())
+ return m_defaultIcons.value(const_cast<QtProperty *>(property)).pixmap(16, 16);
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
+ qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow);
+ if (fwb)
+ return fwb->iconCache()->icon(m_iconValues.value(const_cast<QtProperty *>(property))).pixmap(16, 16);
+ } else if (m_pixmapValues.contains(const_cast<QtProperty *>(property))) {
+ if (!property->isModified())
+ return m_defaultPixmaps.value(const_cast<QtProperty *>(property));
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
+ qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow);
+ if (fwb)
+ return fwb->pixmapCache()->pixmap(m_pixmapValues.value(const_cast<QtProperty *>(property)));
+ } else {
+ QIcon rc;
+ if (m_brushManager.valueIcon(property, &rc))
+ return rc;
+ }
+
+ return QtVariantPropertyManager::valueIcon(property);
+}
+
+QVariant DesignerPropertyManager::value(const QtProperty *property) const
+{
+ if (m_flagValues.contains(const_cast<QtProperty *>(property)))
+ return m_flagValues.value(const_cast<QtProperty *>(property)).val;
+ if (m_alignValues.contains(const_cast<QtProperty *>(property)))
+ return m_alignValues.value(const_cast<QtProperty *>(property));
+ if (m_paletteValues.contains(const_cast<QtProperty *>(property)))
+ return m_paletteValues.value(const_cast<QtProperty *>(property)).val;
+ if (m_iconValues.contains(const_cast<QtProperty *>(property)))
+ return qVariantFromValue(m_iconValues.value(const_cast<QtProperty *>(property)));
+ if (m_pixmapValues.contains(const_cast<QtProperty *>(property)))
+ return qVariantFromValue(m_pixmapValues.value(const_cast<QtProperty *>(property)));
+ if (m_stringValues.contains(const_cast<QtProperty *>(property)))
+ return qVariantFromValue(m_stringValues.value(const_cast<QtProperty *>(property)));
+ if (m_keySequenceValues.contains(const_cast<QtProperty *>(property)))
+ return qVariantFromValue(m_keySequenceValues.value(const_cast<QtProperty *>(property)));
+ if (m_uintValues.contains(const_cast<QtProperty *>(property)))
+ return m_uintValues.value(const_cast<QtProperty *>(property));
+ if (m_longLongValues.contains(const_cast<QtProperty *>(property)))
+ return m_longLongValues.value(const_cast<QtProperty *>(property));
+ if (m_uLongLongValues.contains(const_cast<QtProperty *>(property)))
+ return m_uLongLongValues.value(const_cast<QtProperty *>(property));
+ if (m_urlValues.contains(const_cast<QtProperty *>(property)))
+ return m_urlValues.value(const_cast<QtProperty *>(property));
+ if (m_byteArrayValues.contains(const_cast<QtProperty *>(property)))
+ return m_byteArrayValues.value(const_cast<QtProperty *>(property));
+ if (m_stringListValues.contains(const_cast<QtProperty *>(property)))
+ return m_stringListValues.value(const_cast<QtProperty *>(property));
+
+ QVariant rc;
+ if (m_brushManager.value(property, &rc))
+ return rc;
+ return QtVariantPropertyManager::value(property);
+}
+
+int DesignerPropertyManager::valueType(int propertyType) const
+{
+ switch (propertyType) {
+ case QVariant::Palette:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Url:
+ case QVariant::ByteArray:
+ case QVariant::StringList:
+ case QVariant::Brush:
+ return propertyType;
+ default:
+ break;
+ }
+ if (propertyType == designerFlagTypeId())
+ return QVariant::UInt;
+ if (propertyType == designerAlignmentTypeId())
+ return QVariant::UInt;
+ if (propertyType == designerPixmapTypeId())
+ return propertyType;
+ if (propertyType == designerIconTypeId())
+ return propertyType;
+ if (propertyType == designerStringTypeId())
+ return propertyType;
+ if (propertyType == designerKeySequenceTypeId())
+ return propertyType;
+ return QtVariantPropertyManager::valueType(propertyType);
+}
+
+void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &value)
+{
+ const PropertyFlagDataMap::iterator fit = m_flagValues.find(property);
+
+ if (fit != m_flagValues.end()) {
+ if (value.type() != QVariant::UInt && !value.canConvert(QVariant::UInt))
+ return;
+
+ const uint v = value.toUInt();
+
+ FlagData data = fit.value();
+ if (data.val == v)
+ return;
+
+ // set Value
+
+ const QList<uint> values = data.values;
+ const QList<QtProperty *> subFlags = m_propertyToFlags.value(property);
+ const int subFlagCount = subFlags.count();
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ const uint val = values.at(i);
+ const bool checked = (val == 0) ? (v == 0) : ((val & v) == val);
+ subFlag->setValue(checked);
+ }
+
+ for (int i = 0; i < subFlagCount; ++i) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(i));
+ const uint val = values.at(i);
+ const bool checked = (val == 0) ? (v == 0) : ((val & v) == val);
+ bool enabled = true;
+ if (val == 0) {
+ if (checked)
+ enabled = false;
+ } else if (bitCount(val) > 1) {
+ // Disabled if all flags contained in the mask are checked
+ uint currentMask = 0;
+ for (int j = 0; j < subFlagCount; ++j) {
+ QtVariantProperty *subFlag = variantProperty(subFlags.at(j));
+ if (bitCount(values.at(j)) == 1)
+ currentMask |= subFlag->value().toBool() ? values.at(j) : 0;
+ }
+ if ((currentMask & values.at(i)) == values.at(i))
+ enabled = false;
+ }
+ subFlag->setEnabled(enabled);
+ }
+
+ data.val = v;
+ fit.value() = data;
+
+ emit QtVariantPropertyManager::valueChanged(property, data.val);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_alignValues.contains(property)) {
+ if (value.type() != QVariant::UInt && !value.canConvert(QVariant::UInt))
+ return;
+
+ const uint v = value.toUInt();
+
+ uint val = m_alignValues.value(property);
+
+ if (val == v)
+ return;
+
+ QtVariantProperty *alignH = variantProperty(m_propertyToAlignH.value(property));
+ QtVariantProperty *alignV = variantProperty(m_propertyToAlignV.value(property));
+
+ if (alignH)
+ alignH->setValue(alignToIndexH(v));
+ if (alignV)
+ alignV->setValue(alignToIndexV(v));
+
+ m_alignValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, v);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_stringValues.contains(property)) {
+ if (value.userType() != designerStringTypeId())
+ return;
+
+ const PropertySheetStringValue v = qVariantValue<PropertySheetStringValue>(value);
+
+ const PropertySheetStringValue val = m_stringValues.value(property);
+
+ if (val == v)
+ return;
+
+ QtVariantProperty *comment = variantProperty(m_stringToComment.value(property));
+ QtVariantProperty *translatable = variantProperty(m_stringToTranslatable.value(property));
+ QtVariantProperty *disambiguation = variantProperty(m_stringToDisambiguation.value(property));
+
+ if (comment)
+ comment->setValue(v.comment());
+ if (translatable)
+ translatable->setValue(v.translatable());
+ if (disambiguation)
+ disambiguation->setValue(v.disambiguation());
+
+ m_stringValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v));
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_keySequenceValues.contains(property)) {
+ if (value.userType() != designerKeySequenceTypeId())
+ return;
+
+ const PropertySheetKeySequenceValue v = qVariantValue<PropertySheetKeySequenceValue>(value);
+
+ const PropertySheetKeySequenceValue val = m_keySequenceValues.value(property);
+
+ if (val == v)
+ return;
+
+ QtVariantProperty *comment = variantProperty(m_keySequenceToComment.value(property));
+ QtVariantProperty *translatable = variantProperty(m_keySequenceToTranslatable.value(property));
+ QtVariantProperty *disambiguation = variantProperty(m_keySequenceToDisambiguation.value(property));
+
+ if (comment)
+ comment->setValue(v.comment());
+ if (translatable)
+ translatable->setValue(v.translatable());
+ if (disambiguation)
+ disambiguation->setValue(v.disambiguation());
+
+ m_keySequenceValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v));
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_paletteValues.contains(property)) {
+ if (value.type() != QVariant::Palette && !value.canConvert(QVariant::Palette))
+ return;
+
+ QPalette p = qVariantValue<QPalette>(value);
+
+ PaletteData data = m_paletteValues.value(property);
+
+ const uint mask = p.resolve();
+ p = p.resolve(data.superPalette);
+ p.resolve(mask);
+
+ if (data.val == p && data.val.resolve() == p.resolve())
+ return;
+
+ data.val = p;
+ m_paletteValues[property] = data;
+
+ emit QtVariantPropertyManager::valueChanged(property, data.val);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_iconValues.contains(property)) {
+ if (value.userType() != designerIconTypeId())
+ return;
+
+ const PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(value);
+
+ const PropertySheetIconValue oldIcon = m_iconValues.value(property);
+ if (icon == oldIcon)
+ return;
+
+ m_iconValues[property] = icon;
+
+ QIcon defaultIcon = m_defaultIcons.value(property);
+ if (!icon.paths().isEmpty()) {
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
+ qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow);
+ if (fwb)
+ defaultIcon = fwb->iconCache()->icon(icon);
+ }
+
+ QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> iconPaths = icon.paths();
+
+ QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subProperties = m_propertyToIconSubProperties.value(property);
+ QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itSub(subProperties);
+ while (itSub.hasNext()) {
+ const QPair<QIcon::Mode, QIcon::State> pair = itSub.next().key();
+ QtVariantProperty *subProperty = variantProperty(itSub.value());
+ bool hasPath = iconPaths.contains(pair);
+ subProperty->setModified(hasPath);
+ subProperty->setValue(qVariantFromValue(iconPaths.value(pair)));
+ subProperty->setAttribute(QLatin1String(defaultResourceAttributeC),
+ defaultIcon.pixmap(16, 16, pair.first, pair.second));
+ }
+
+ emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(icon));
+ emit propertyChanged(property);
+
+ QString toolTip;
+ const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue>::ConstIterator itNormalOff =
+ iconPaths.constFind(qMakePair(QIcon::Normal, QIcon::Off));
+ if (itNormalOff != iconPaths.constEnd())
+ toolTip = itNormalOff.value().path();
+ property->setToolTip(toolTip);
+
+ return;
+ } else if (m_pixmapValues.contains(property)) {
+ if (value.userType() != designerPixmapTypeId())
+ return;
+
+ const PropertySheetPixmapValue pixmap = qVariantValue<PropertySheetPixmapValue>(value);
+
+ const PropertySheetPixmapValue oldPixmap = m_pixmapValues.value(property);
+ if (pixmap == oldPixmap)
+ return;
+
+ m_pixmapValues[property] = pixmap;
+
+ emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(pixmap));
+ emit propertyChanged(property);
+
+ property->setToolTip(pixmap.path());
+
+ return;
+ } else if (m_uintValues.contains(property)) {
+ if (value.type() != QVariant::UInt && !value.canConvert(QVariant::UInt))
+ return;
+
+ const uint v = value.toUInt(0);
+
+ const uint oldValue = m_uintValues.value(property);
+ if (v == oldValue)
+ return;
+
+ m_uintValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, v);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_longLongValues.contains(property)) {
+ if (value.type() != QVariant::LongLong && !value.canConvert(QVariant::LongLong))
+ return;
+
+ const qlonglong v = value.toLongLong(0);
+
+ const qlonglong oldValue = m_longLongValues.value(property);
+ if (v == oldValue)
+ return;
+
+ m_longLongValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, v);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_uLongLongValues.contains(property)) {
+ if (value.type() != QVariant::ULongLong && !value.canConvert(QVariant::ULongLong))
+ return;
+
+ qulonglong v = value.toULongLong(0);
+
+ qulonglong oldValue = m_uLongLongValues.value(property);
+ if (v == oldValue)
+ return;
+
+ m_uLongLongValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, v);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_urlValues.contains(property)) {
+ if (value.type() != QVariant::Url && !value.canConvert(QVariant::Url))
+ return;
+
+ const QUrl v = value.toUrl();
+
+ const QUrl oldValue = m_urlValues.value(property);
+ if (v == oldValue)
+ return;
+
+ m_urlValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, v);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_byteArrayValues.contains(property)) {
+ if (value.type() != QVariant::ByteArray && !value.canConvert(QVariant::ByteArray))
+ return;
+
+ const QByteArray v = value.toByteArray();
+
+ const QByteArray oldValue = m_byteArrayValues.value(property);
+ if (v == oldValue)
+ return;
+
+ m_byteArrayValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, v);
+ emit propertyChanged(property);
+
+ return;
+ } else if (m_stringListValues.contains(property)) {
+ if (value.type() != QVariant::StringList && !value.canConvert(QVariant::StringList))
+ return;
+
+ const QStringList v = value.toStringList();
+
+ const QStringList oldValue = m_stringListValues.value(property);
+ if (v == oldValue)
+ return;
+
+ m_stringListValues[property] = v;
+
+ emit QtVariantPropertyManager::valueChanged(property, v);
+ emit propertyChanged(property);
+
+ return;
+ }
+ switch (m_brushManager.setValue(this, property, value)) {
+ case BrushPropertyManager::Unchanged:
+ return;
+ case BrushPropertyManager::Changed:
+ emit QtVariantPropertyManager::valueChanged(property, value);
+ emit propertyChanged(property);
+ return;
+ default:
+ break;
+ }
+ m_fontManager.setValue(this, property, value);
+ QtVariantPropertyManager::setValue(property, value);
+ if (QtVariantPropertyManager::valueType(property) == QVariant::String)
+ property->setToolTip(DesignerPropertyManager::value(property).toString());
+ else if (QtVariantPropertyManager::valueType(property) == designerStringTypeId())
+ property->setToolTip(qVariantValue<PropertySheetStringValue>(DesignerPropertyManager::value(property)).value());
+ else if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId())
+ property->setToolTip(qVariantValue<PropertySheetKeySequenceValue>(DesignerPropertyManager::value(property)).value());
+ else if (QtVariantPropertyManager::valueType(property) == QVariant::Bool)
+ property->setToolTip(QtVariantPropertyManager::valueText(property));
+}
+
+void DesignerPropertyManager::initializeProperty(QtProperty *property)
+{
+ m_resetMap[property] = false;
+
+ const int type = propertyType(property);
+ m_fontManager.preInitializeProperty(property, type, m_resetMap);
+ switch (type) {
+ case QVariant::Palette:
+ m_paletteValues[property] = PaletteData();
+ break;
+ case QVariant::String:
+ m_stringAttributes[property] = ValidationSingleLine;
+ m_stringFontAttributes[property] = QApplication::font();
+ break;
+ case QVariant::UInt:
+ m_uintValues[property] = 0;
+ break;
+ case QVariant::LongLong:
+ m_longLongValues[property] = 0;
+ break;
+ case QVariant::ULongLong:
+ m_uLongLongValues[property] = 0;
+ break;
+ case QVariant::Url:
+ m_urlValues[property] = QUrl();
+ break;
+ case QVariant::ByteArray:
+ m_byteArrayValues[property] = 0;
+ break;
+ case QVariant::StringList:
+ m_stringListValues[property] = QStringList();
+ break;
+ case QVariant::Brush:
+ m_brushManager.initializeProperty(this, property, enumTypeId());
+ break;
+ default:
+ if (type == designerFlagTypeId()) {
+ m_flagValues[property] = FlagData();
+ m_propertyToFlags[property] = QList<QtProperty *>();
+ } else if (type == designerAlignmentTypeId()) {
+ const uint align = Qt::AlignLeft | Qt::AlignVCenter;
+ m_alignValues[property] = align;
+
+ QtVariantProperty *alignH = addProperty(enumTypeId(), tr("Horizontal"));
+ QStringList namesH;
+ namesH << indexHToString(0) << indexHToString(1) << indexHToString(2) << indexHToString(3);
+ alignH->setAttribute(QLatin1String("enumNames"), namesH);
+ alignH->setValue(alignToIndexH(align));
+ m_propertyToAlignH[property] = alignH;
+ m_alignHToProperty[alignH] = property;
+ property->addSubProperty(alignH);
+
+ QtVariantProperty *alignV = addProperty(enumTypeId(), tr("Vertical"));
+ QStringList namesV;
+ namesV << indexVToString(0) << indexVToString(1) << indexVToString(2);
+ alignV->setAttribute(QLatin1String("enumNames"), namesV);
+ alignV->setValue(alignToIndexV(align));
+ m_propertyToAlignV[property] = alignV;
+ m_alignVToProperty[alignV] = property;
+ property->addSubProperty(alignV);
+ } else if (type == designerPixmapTypeId()) {
+ m_pixmapValues[property] = PropertySheetPixmapValue();
+ m_defaultPixmaps[property] = QPixmap();
+ } else if (type == designerIconTypeId()) {
+ m_iconValues[property] = PropertySheetIconValue();
+ m_defaultIcons[property] = QIcon();
+
+ createIconSubProperty(property, QIcon::Normal, QIcon::Off, tr("Normal Off"));
+ createIconSubProperty(property, QIcon::Normal, QIcon::On, tr("Normal On"));
+ createIconSubProperty(property, QIcon::Disabled, QIcon::Off, tr("Disabled Off"));
+ createIconSubProperty(property, QIcon::Disabled, QIcon::On, tr("Disabled On"));
+ createIconSubProperty(property, QIcon::Active, QIcon::Off, tr("Active Off"));
+ createIconSubProperty(property, QIcon::Active, QIcon::On, tr("Active On"));
+ createIconSubProperty(property, QIcon::Selected, QIcon::Off, tr("Selected Off"));
+ createIconSubProperty(property, QIcon::Selected, QIcon::On, tr("Selected On"));
+ } else if (type == designerStringTypeId()) {
+ PropertySheetStringValue val;
+ m_stringValues[property] = val;
+ m_stringAttributes[property] = ValidationMultiLine;
+ m_stringFontAttributes[property] = QApplication::font();
+
+ QtVariantProperty *translatable = addProperty(QVariant::Bool, tr("translatable"));
+ translatable->setValue(val.translatable());
+ m_stringToTranslatable[property] = translatable;
+ m_translatableToString[translatable] = property;
+ property->addSubProperty(translatable);
+
+ QtVariantProperty *disambiguation = addProperty(QVariant::String, tr("disambiguation"));
+ disambiguation->setValue(val.disambiguation());
+ m_stringToDisambiguation[property] = disambiguation;
+ m_disambiguationToString[disambiguation] = property;
+ property->addSubProperty(disambiguation);
+
+ QtVariantProperty *comment = addProperty(QVariant::String, tr("comment"));
+ comment->setValue(val.comment());
+ m_stringToComment[property] = comment;
+ m_commentToString[comment] = property;
+ property->addSubProperty(comment);
+ } else if (type == designerKeySequenceTypeId()) {
+ PropertySheetKeySequenceValue val;
+ m_keySequenceValues[property] = val;
+
+ QtVariantProperty *translatable = addProperty(QVariant::Bool, tr("translatable"));
+ translatable->setValue(val.translatable());
+ m_keySequenceToTranslatable[property] = translatable;
+ m_translatableToKeySequence[translatable] = property;
+ property->addSubProperty(translatable);
+
+ QtVariantProperty *disambiguation = addProperty(QVariant::String, tr("disambiguation"));
+ disambiguation->setValue(val.disambiguation());
+ m_keySequenceToDisambiguation[property] = disambiguation;
+ m_disambiguationToKeySequence[disambiguation] = property;
+ property->addSubProperty(disambiguation);
+
+ QtVariantProperty *comment = addProperty(QVariant::String, tr("comment"));
+ comment->setValue(val.comment());
+ m_keySequenceToComment[property] = comment;
+ m_commentToKeySequence[comment] = property;
+ property->addSubProperty(comment);
+ }
+ }
+
+ QtVariantPropertyManager::initializeProperty(property);
+ m_fontManager.postInitializeProperty(this, property, type, DesignerPropertyManager::enumTypeId());
+ if (type == QVariant::Double)
+ setAttribute(property, QLatin1String("decimals"), 6);
+}
+
+void DesignerPropertyManager::createIconSubProperty(QtProperty *iconProperty, QIcon::Mode mode, QIcon::State state, const QString &subName)
+{
+ QPair<QIcon::Mode, QIcon::State> pair = qMakePair(mode, state);
+ QtVariantProperty *subProp = addProperty(DesignerPropertyManager::designerPixmapTypeId(), subName);
+ m_propertyToIconSubProperties[iconProperty][pair] = subProp;
+ m_iconSubPropertyToState[subProp] = pair;
+ m_iconSubPropertyToProperty[subProp] = iconProperty;
+ m_resetMap[subProp] = true;
+ iconProperty->addSubProperty(subProp);
+}
+
+void DesignerPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ m_resetMap.remove(property);
+
+ QListIterator<QtProperty *> itProp(m_propertyToFlags[property]);
+ while (itProp.hasNext()) {
+ QtProperty *prop = itProp.next();
+ if (prop) {
+ delete prop;
+ m_flagToProperty.remove(prop);
+ }
+ }
+ m_propertyToFlags.remove(property);
+ m_flagValues.remove(property);
+
+ QtProperty *alignH = m_propertyToAlignH.value(property);
+ if (alignH) {
+ delete alignH;
+ m_alignHToProperty.remove(alignH);
+ }
+ QtProperty *alignV = m_propertyToAlignV.value(property);
+ if (alignV) {
+ delete alignV;
+ m_alignVToProperty.remove(alignV);
+ }
+
+ QtProperty *stringComment = m_stringToComment.value(property);
+ if (stringComment) {
+ delete stringComment;
+ m_stringToComment.remove(stringComment);
+ }
+
+ QtProperty *stringTranslatable = m_stringToTranslatable.value(property);
+ if (stringTranslatable) {
+ delete stringTranslatable;
+ m_stringToTranslatable.remove(stringTranslatable);
+ }
+
+ QtProperty *stringDisambiguation = m_stringToDisambiguation.value(property);
+ if (stringDisambiguation) {
+ delete stringDisambiguation;
+ m_stringToDisambiguation.remove(stringDisambiguation);
+ }
+
+ QtProperty *keySequenceComment = m_keySequenceToComment.value(property);
+ if (keySequenceComment) {
+ delete keySequenceComment;
+ m_keySequenceToComment.remove(keySequenceComment);
+ }
+
+ QtProperty *keySequenceTranslatable = m_keySequenceToTranslatable.value(property);
+ if (keySequenceTranslatable) {
+ delete keySequenceTranslatable;
+ m_keySequenceToTranslatable.remove(keySequenceTranslatable);
+ }
+
+ QtProperty *keySequenceDisambiguation = m_keySequenceToDisambiguation.value(property);
+ if (keySequenceDisambiguation) {
+ delete keySequenceDisambiguation;
+ m_keySequenceToDisambiguation.remove(keySequenceDisambiguation);
+ }
+
+ m_propertyToAlignH.remove(property);
+ m_propertyToAlignV.remove(property);
+
+ m_stringToComment.remove(property);
+ m_stringToTranslatable.remove(property);
+ m_stringToDisambiguation.remove(property);
+ m_stringValues.remove(property);
+ m_stringAttributes.remove(property);
+ m_stringFontAttributes.remove(property);
+
+ m_keySequenceToComment.remove(property);
+ m_keySequenceToTranslatable.remove(property);
+ m_keySequenceToDisambiguation.remove(property);
+ m_keySequenceValues.remove(property);
+
+ m_paletteValues.remove(property);
+
+ m_iconValues.remove(property);
+ m_defaultIcons.remove(property);
+
+ m_pixmapValues.remove(property);
+ m_defaultPixmaps.remove(property);
+
+ QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> iconSubProperties = m_propertyToIconSubProperties.value(property);
+ QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itIcon(iconSubProperties);
+ while (itIcon.hasNext()) {
+ QtProperty *subIcon = itIcon.next().value();
+ delete subIcon;
+ m_iconSubPropertyToState.remove(subIcon);
+ m_iconSubPropertyToProperty.remove(subIcon);
+ }
+ m_propertyToIconSubProperties.remove(property);
+ m_iconSubPropertyToState.remove(property);
+ m_iconSubPropertyToProperty.remove(property);
+
+ m_uintValues.remove(property);
+ m_longLongValues.remove(property);
+ m_uLongLongValues.remove(property);
+ m_urlValues.remove(property);
+ m_byteArrayValues.remove(property);
+ m_stringListValues.remove(property);
+
+ m_fontManager.uninitializeProperty(property);
+ m_brushManager.uninitializeProperty(property);
+
+ QtVariantPropertyManager::uninitializeProperty(property);
+}
+
+
+bool DesignerPropertyManager::resetFontSubProperty(QtProperty *property)
+{
+ return m_fontManager.resetFontSubProperty(this, property);
+}
+
+bool DesignerPropertyManager::resetIconSubProperty(QtProperty *property)
+{
+ if (!m_iconSubPropertyToProperty.contains(property))
+ return false;
+
+ if (!m_pixmapValues.contains(property))
+ return false;
+
+ QtVariantProperty *pixmapProperty = variantProperty(property);
+ pixmapProperty->setValue(qVariantFromValue(PropertySheetPixmapValue()));
+ return true;
+}
+
+// -------- DesignerEditorFactory
+DesignerEditorFactory::DesignerEditorFactory(QDesignerFormEditorInterface *core, QObject *parent) :
+ QtVariantEditorFactory(parent),
+ m_resetDecorator(new ResetDecorator(this)),
+ m_changingPropertyValue(false),
+ m_core(core),
+ m_spacing(-1)
+{
+ connect(m_resetDecorator, SIGNAL(resetProperty(QtProperty*)), this, SIGNAL(resetProperty(QtProperty*)));
+}
+
+DesignerEditorFactory::~DesignerEditorFactory()
+{
+}
+
+void DesignerEditorFactory::setSpacing(int spacing)
+{
+ m_spacing = spacing;
+ m_resetDecorator->setSpacing(spacing);
+}
+
+void DesignerEditorFactory::setFormWindowBase(qdesigner_internal::FormWindowBase *fwb)
+{
+ m_fwb = fwb;
+ DesignerPixmapCache *cache = 0;
+ if (fwb)
+ cache = fwb->pixmapCache();
+ QMapIterator<PixmapEditor *, QtProperty *> itPixmapEditor(m_editorToPixmapProperty);
+ while (itPixmapEditor.hasNext()) {
+ PixmapEditor *pe = itPixmapEditor.next().key();
+ pe->setPixmapCache(cache);
+ }
+ QMapIterator<PixmapEditor *, QtProperty *> itIconEditor(m_editorToIconProperty);
+ while (itIconEditor.hasNext()) {
+ PixmapEditor *pe = itIconEditor.next().key();
+ pe->setPixmapCache(cache);
+ }
+}
+
+void DesignerEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager)
+{
+ m_resetDecorator->connectPropertyManager(manager);
+ connect(manager, SIGNAL(attributeChanged(QtProperty*,QString,QVariant)),
+ this, SLOT(slotAttributeChanged(QtProperty*,QString,QVariant)));
+ connect(manager, SIGNAL(valueChanged(QtProperty*,QVariant)),
+ this, SLOT(slotValueChanged(QtProperty*,QVariant)));
+ connect(manager, SIGNAL(propertyChanged(QtProperty*)),
+ this, SLOT(slotPropertyChanged(QtProperty*)));
+ QtVariantEditorFactory::connectPropertyManager(manager);
+}
+
+void DesignerEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager)
+{
+ m_resetDecorator->disconnectPropertyManager(manager);
+ disconnect(manager, SIGNAL(attributeChanged(QtProperty*,QString,QVariant)),
+ this, SLOT(slotAttributeChanged(QtProperty*,QString,QVariant)));
+ disconnect(manager, SIGNAL(valueChanged(QtProperty*,QVariant)),
+ this, SLOT(slotValueChanged(QtProperty*,QVariant)));
+ disconnect(manager, SIGNAL(propertyChanged(QtProperty*)),
+ this, SLOT(slotPropertyChanged(QtProperty*)));
+ QtVariantEditorFactory::disconnectPropertyManager(manager);
+}
+
+// A helper that calls a setter with a value on a pointer list of editor objects.
+// Could use QList<Editor*> instead of EditorContainer/Editor, but that crashes VS 6.
+template <class EditorContainer, class Editor, class SetterParameter, class Value>
+static inline void applyToEditors(const EditorContainer &list, void (Editor::*setter)(SetterParameter), const Value &value)
+{
+ typedef Q_TYPENAME EditorContainer::const_iterator ListIterator;
+ if (list.empty()) {
+ return;
+ }
+ const ListIterator end = list.constEnd();
+ for (ListIterator it = list.constBegin(); it != end; ++it) {
+ Editor &editor = *(*it);
+ (editor.*setter)(value);
+ }
+}
+
+void DesignerEditorFactory::slotAttributeChanged(QtProperty *property, const QString &attribute, const QVariant &value)
+{
+ QtVariantPropertyManager *manager = propertyManager(property);
+ const int type = manager->propertyType(property);
+ if (type == DesignerPropertyManager::designerPixmapTypeId() && attribute == QLatin1String(defaultResourceAttributeC)) {
+ const QPixmap pixmap = qvariant_cast<QPixmap>(value);
+ applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setDefaultPixmap, pixmap);
+ } else if (type == DesignerPropertyManager::designerStringTypeId() || type == QVariant::String) {
+ if (attribute == QLatin1String(validationModesAttributeC)) {
+ const TextPropertyValidationMode validationMode = static_cast<TextPropertyValidationMode>(value.toInt());
+ applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setTextPropertyValidationMode, validationMode);
+ }
+ if (attribute == QLatin1String(fontAttributeC)) {
+ const QFont font = qvariant_cast<QFont>(value);
+ applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setRichTextDefaultFont, font);
+ }
+ } else if (type == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) {
+ const QPalette palette = qvariant_cast<QPalette>(value);
+ applyToEditors(m_palettePropertyToEditors.value(property), &PaletteEditorButton::setSuperPalette, palette);
+ }
+}
+
+void DesignerEditorFactory::slotPropertyChanged(QtProperty *property)
+{
+ QtVariantPropertyManager *manager = propertyManager(property);
+ const int type = manager->propertyType(property);
+ if (type == DesignerPropertyManager::designerIconTypeId()) {
+ QPixmap defaultPixmap;
+ if (!property->isModified())
+ defaultPixmap = qvariant_cast<QIcon>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC))).pixmap(16, 16);
+ else if (m_fwb)
+ defaultPixmap = m_fwb->iconCache()->icon(qVariantValue<PropertySheetIconValue>(manager->value(property))).pixmap(16, 16);
+ QList<PixmapEditor *> editors = m_iconPropertyToEditors.value(property);
+ QListIterator<PixmapEditor *> it(editors);
+ while (it.hasNext()) {
+ PixmapEditor *editor = it.next();
+ editor->setDefaultPixmap(defaultPixmap);
+ }
+ }
+}
+
+void DesignerEditorFactory::slotValueChanged(QtProperty *property, const QVariant &value)
+{
+ if (m_changingPropertyValue)
+ return;
+
+ QtVariantPropertyManager *manager = propertyManager(property);
+ const int type = manager->propertyType(property);
+ switch (type) {
+ case QVariant::String:
+ applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, value.toString());
+ break;
+ case QVariant::Palette:
+ applyToEditors(m_palettePropertyToEditors.value(property), &PaletteEditorButton::setPalette, qvariant_cast<QPalette>(value));
+ break;
+ case QVariant::UInt:
+ applyToEditors(m_uintPropertyToEditors.value(property), &QLineEdit::setText, QString::number(value.toUInt()));
+ break;
+ case QVariant::LongLong:
+ applyToEditors(m_longLongPropertyToEditors.value(property), &QLineEdit::setText, QString::number(value.toLongLong()));
+ break;
+ case QVariant::ULongLong:
+ applyToEditors(m_uLongLongPropertyToEditors.value(property), &QLineEdit::setText, QString::number(value.toULongLong()));
+ break;
+ case QVariant::Url:
+ applyToEditors(m_urlPropertyToEditors.value(property), &TextEditor::setText, value.toUrl().toString());
+ break;
+ case QVariant::ByteArray:
+ applyToEditors(m_byteArrayPropertyToEditors.value(property), &TextEditor::setText, QString::fromUtf8(value.toByteArray()));
+ break;
+ case QVariant::StringList:
+ applyToEditors(m_stringListPropertyToEditors.value(property), &StringListEditorButton::setStringList, value.toStringList());
+ break;
+ default:
+ if (type == DesignerPropertyManager::designerIconTypeId())
+ applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetIconValue>(value).pixmap(QIcon::Normal, QIcon::Off).path());
+ else if (type == DesignerPropertyManager::designerPixmapTypeId())
+ applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetPixmapValue>(value).path());
+ else if (type == DesignerPropertyManager::designerStringTypeId())
+ applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, qVariantValue<PropertySheetStringValue>(value).value());
+ else if (type == DesignerPropertyManager::designerKeySequenceTypeId())
+ applyToEditors(m_keySequencePropertyToEditors.value(property), &QtKeySequenceEdit::setKeySequence, qVariantValue<PropertySheetKeySequenceValue>(value).value());
+ break;
+ }
+}
+
+TextEditor *DesignerEditorFactory::createTextEditor(QWidget *parent, TextPropertyValidationMode vm, const QString &value)
+{
+ TextEditor *rc = new TextEditor(m_core, parent);
+ rc->setText(value);
+ rc->setSpacing(m_spacing);
+ rc->setTextPropertyValidationMode(vm);
+ connect(rc, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ return rc;
+}
+
+QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QWidget *editor = 0;
+ const int type = manager->propertyType(property);
+ switch (type) {
+ case QVariant::Bool: {
+ editor = QtVariantEditorFactory::createEditor(manager, property, parent);
+ QtBoolEdit *boolEdit = qobject_cast<QtBoolEdit *>(editor);
+ if (boolEdit)
+ boolEdit->setTextVisible(false);
+ }
+ break;
+ case QVariant::String: {
+ const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, QLatin1String(validationModesAttributeC)).toInt());
+ TextEditor *ed = createTextEditor(parent, tvm, manager->value(property).toString());
+ const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC));
+ if (richTextDefaultFont.type() == QVariant::Font)
+ ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont));
+ m_stringPropertyToEditors[property].append(ed);
+ m_editorToStringProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotStringTextChanged(QString)));
+ editor = ed;
+ }
+ break;
+ case QVariant::Palette: {
+ PaletteEditorButton *ed = new PaletteEditorButton(m_core, qvariant_cast<QPalette>(manager->value(property)), parent);
+ ed->setSuperPalette(qvariant_cast<QPalette>(manager->attributeValue(property, QLatin1String(superPaletteAttributeC))));
+ m_palettePropertyToEditors[property].append(ed);
+ m_editorToPaletteProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(ed, SIGNAL(paletteChanged(QPalette)), this, SLOT(slotPaletteChanged(QPalette)));
+ editor = ed;
+ }
+ break;
+ case QVariant::UInt: {
+ QLineEdit *ed = new QLineEdit(parent);
+ ed->setValidator(new QULongLongValidator(0, UINT_MAX, ed));
+ ed->setText(QString::number(manager->value(property).toUInt()));
+ m_uintPropertyToEditors[property].append(ed);
+ m_editorToUintProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotUintChanged(QString)));
+ editor = ed;
+ }
+ break;
+ case QVariant::LongLong: {
+ QLineEdit *ed = new QLineEdit(parent);
+ ed->setValidator(new QLongLongValidator(ed));
+ ed->setText(QString::number(manager->value(property).toLongLong()));
+ m_longLongPropertyToEditors[property].append(ed);
+ m_editorToLongLongProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotLongLongChanged(QString)));
+ editor = ed;
+ }
+ break;
+ case QVariant::ULongLong: {
+ QLineEdit *ed = new QLineEdit(parent);
+ ed->setValidator(new QULongLongValidator(ed));
+ ed->setText(QString::number(manager->value(property).toULongLong()));
+ m_uLongLongPropertyToEditors[property].append(ed);
+ m_editorToULongLongProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotULongLongChanged(QString)));
+ editor = ed;
+ }
+ break;
+ case QVariant::Url: {
+ TextEditor *ed = createTextEditor(parent, ValidationURL, manager->value(property).toUrl().toString());
+ ed->setUpdateMode(TextPropertyEditor::UpdateOnFinished);
+ m_urlPropertyToEditors[property].append(ed);
+ m_editorToUrlProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotUrlChanged(QString)));
+ editor = ed;
+ }
+ break;
+ case QVariant::ByteArray: {
+ TextEditor *ed = createTextEditor(parent, ValidationMultiLine, QString::fromUtf8(manager->value(property).toByteArray()));
+ m_byteArrayPropertyToEditors[property].append(ed);
+ m_editorToByteArrayProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotByteArrayChanged(QString)));
+ editor = ed;
+ }
+ break;
+ case QVariant::StringList: {
+ StringListEditorButton *ed = new StringListEditorButton(manager->value(property).toStringList(), parent);
+ m_stringListPropertyToEditors[property].append(ed);
+ m_editorToStringListProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(ed, SIGNAL(stringListChanged(QStringList)), this, SLOT(slotStringListChanged(QStringList)));
+ editor = ed;
+ }
+ break;
+ default:
+ if (type == DesignerPropertyManager::designerPixmapTypeId()) {
+ PixmapEditor *ed = new PixmapEditor(m_core, parent);
+ ed->setPixmapCache(m_fwb->pixmapCache());
+ ed->setPath(qvariant_cast<PropertySheetPixmapValue>(manager->value(property)).path());
+ ed->setDefaultPixmap(qvariant_cast<QPixmap>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC))));
+ ed->setSpacing(m_spacing);
+ m_pixmapPropertyToEditors[property].append(ed);
+ m_editorToPixmapProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ connect(ed, SIGNAL(pathChanged(const QString &)), this, SLOT(slotPixmapChanged(const QString &)));
+ editor = ed;
+ } else if (type == DesignerPropertyManager::designerIconTypeId()) {
+ PixmapEditor *ed = new PixmapEditor(m_core, parent);
+ ed->setPixmapCache(m_fwb->pixmapCache());
+ PropertySheetIconValue value = qvariant_cast<PropertySheetIconValue>(manager->value(property));
+ ed->setPath(value.pixmap(QIcon::Normal, QIcon::Off).path());
+ QPixmap defaultPixmap;
+ if (!property->isModified())
+ defaultPixmap = qvariant_cast<QIcon>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC))).pixmap(16, 16);
+ else if (m_fwb)
+ defaultPixmap = m_fwb->iconCache()->icon(value).pixmap(16, 16);
+ ed->setDefaultPixmap(defaultPixmap);
+ ed->setSpacing(m_spacing);
+ m_iconPropertyToEditors[property].append(ed);
+ m_editorToIconProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ connect(ed, SIGNAL(pathChanged(const QString &)), this, SLOT(slotIconChanged(const QString &)));
+ editor = ed;
+ } else if (type == DesignerPropertyManager::designerStringTypeId()) {
+ const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, QLatin1String(validationModesAttributeC)).toInt());
+ TextEditor *ed = createTextEditor(parent, tvm, qVariantValue<PropertySheetStringValue>(manager->value(property)).value());
+ const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC));
+ if (richTextDefaultFont.type() == QVariant::Font)
+ ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont));
+ m_stringPropertyToEditors[property].append(ed);
+ m_editorToStringProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotStringTextChanged(QString)));
+ editor = ed;
+ } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) {
+ QtKeySequenceEdit *ed = new QtKeySequenceEdit(parent);
+ ed->setKeySequence(qVariantValue<PropertySheetKeySequenceValue>(manager->value(property)).value());
+ m_keySequencePropertyToEditors[property].append(ed);
+ m_editorToKeySequenceProperty[ed] = property;
+ connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ connect(ed, SIGNAL(keySequenceChanged(QKeySequence)), this, SLOT(slotKeySequenceChanged(QKeySequence)));
+ editor = ed;
+ } else {
+ editor = QtVariantEditorFactory::createEditor(manager, property, parent);
+ }
+ break;
+ }
+ return m_resetDecorator->editor(editor,
+ manager->variantProperty(property)->attributeValue(QLatin1String(resettableAttributeC)).toBool(),
+ manager, property, parent);
+}
+
+template <class Editor>
+bool removeEditor(QObject *object,
+ QMap<QtProperty *, QList<Editor> > *propertyToEditors,
+ QMap<Editor, QtProperty *> *editorToProperty)
+{
+ if (!propertyToEditors)
+ return false;
+ if (!editorToProperty)
+ return false;
+ QMapIterator<Editor, QtProperty *> it(*editorToProperty);
+ while (it.hasNext()) {
+ Editor editor = it.next().key();
+ if (editor == object) {
+ QtProperty *prop = it.value();
+ (*propertyToEditors)[prop].removeAll(editor);
+ if ((*propertyToEditors)[prop].count() == 0)
+ propertyToEditors->remove(prop);
+ editorToProperty->remove(editor);
+ return true;
+ }
+ }
+ return false;
+}
+
+void DesignerEditorFactory::slotEditorDestroyed(QObject *object)
+{
+ if (removeEditor(object, &m_stringPropertyToEditors, &m_editorToStringProperty))
+ return;
+ if (removeEditor(object, &m_keySequencePropertyToEditors, &m_editorToKeySequenceProperty))
+ return;
+ if (removeEditor(object, &m_palettePropertyToEditors, &m_editorToPaletteProperty))
+ return;
+ if (removeEditor(object, &m_pixmapPropertyToEditors, &m_editorToPixmapProperty))
+ return;
+ if (removeEditor(object, &m_iconPropertyToEditors, &m_editorToIconProperty))
+ return;
+ if (removeEditor(object, &m_uintPropertyToEditors, &m_editorToUintProperty))
+ return;
+ if (removeEditor(object, &m_longLongPropertyToEditors, &m_editorToLongLongProperty))
+ return;
+ if (removeEditor(object, &m_uLongLongPropertyToEditors, &m_editorToULongLongProperty))
+ return;
+ if (removeEditor(object, &m_urlPropertyToEditors, &m_editorToUrlProperty))
+ return;
+ if (removeEditor(object, &m_byteArrayPropertyToEditors, &m_editorToByteArrayProperty))
+ return;
+ if (removeEditor(object, &m_stringListPropertyToEditors, &m_editorToStringListProperty))
+ return;
+}
+
+template<class Editor>
+bool updateManager(QtVariantEditorFactory *factory, bool *changingPropertyValue,
+ const QMap<Editor, QtProperty *> &editorToProperty, QWidget *editor, const QVariant &value)
+{
+ if (!editor)
+ return false;
+ QMapIterator<Editor, QtProperty *> it(editorToProperty);
+ while (it.hasNext()) {
+ if (it.next().key() == editor) {
+ QtProperty *prop = it.value();
+ QtVariantPropertyManager *manager = factory->propertyManager(prop);
+ *changingPropertyValue = true;
+ manager->variantProperty(prop)->setValue(value);
+ *changingPropertyValue = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+void DesignerEditorFactory::slotUintChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToUintProperty, qobject_cast<QWidget *>(sender()), value.toUInt());
+}
+
+void DesignerEditorFactory::slotLongLongChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToLongLongProperty, qobject_cast<QWidget *>(sender()), value.toLongLong());
+}
+
+void DesignerEditorFactory::slotULongLongChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToULongLongProperty, qobject_cast<QWidget *>(sender()), value.toULongLong());
+}
+
+void DesignerEditorFactory::slotUrlChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToUrlProperty, qobject_cast<QWidget *>(sender()), QUrl(value));
+}
+
+void DesignerEditorFactory::slotByteArrayChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToByteArrayProperty, qobject_cast<QWidget *>(sender()), value.toUtf8());
+}
+
+void DesignerEditorFactory::slotStringTextChanged(const QString &value)
+{
+ QMapIterator<TextEditor *, QtProperty *> it(m_editorToStringProperty);
+ while (it.hasNext()) {
+ if (it.next().key() == sender()) {
+ QtProperty *prop = it.value();
+ QtVariantPropertyManager *manager = propertyManager(prop);
+ QtVariantProperty *varProp = manager->variantProperty(prop);
+ QVariant val = varProp->value();
+ if (val.userType() == DesignerPropertyManager::designerStringTypeId()) {
+ PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(val);
+ strVal.setValue(value);
+ val = qVariantFromValue(strVal);
+ } else {
+ val = QVariant(value);
+ }
+ m_changingPropertyValue = true;
+ manager->variantProperty(prop)->setValue(val);
+ m_changingPropertyValue = false;
+ }
+ }
+}
+
+void DesignerEditorFactory::slotKeySequenceChanged(const QKeySequence &value)
+{
+ QMapIterator<QtKeySequenceEdit *, QtProperty *> it(m_editorToKeySequenceProperty);
+ while (it.hasNext()) {
+ if (it.next().key() == sender()) {
+ QtProperty *prop = it.value();
+ QtVariantPropertyManager *manager = propertyManager(prop);
+ QtVariantProperty *varProp = manager->variantProperty(prop);
+ QVariant val = varProp->value();
+ if (val.userType() == DesignerPropertyManager::designerKeySequenceTypeId()) {
+ PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(val);
+ keyVal.setValue(value);
+ val = qVariantFromValue(keyVal);
+ } else {
+ val = qVariantFromValue(value);
+ }
+ m_changingPropertyValue = true;
+ manager->variantProperty(prop)->setValue(val);
+ m_changingPropertyValue = false;
+ }
+ }
+}
+
+void DesignerEditorFactory::slotPaletteChanged(const QPalette &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToPaletteProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value));
+}
+
+void DesignerEditorFactory::slotPixmapChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToPixmapProperty, qobject_cast<QWidget *>(sender()),
+ qVariantFromValue(PropertySheetPixmapValue(value)));
+}
+
+void DesignerEditorFactory::slotIconChanged(const QString &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()),
+ qVariantFromValue(PropertySheetIconValue(PropertySheetPixmapValue(value))));
+}
+
+void DesignerEditorFactory::slotStringListChanged(const QStringList &value)
+{
+ updateManager(this, &m_changingPropertyValue, m_editorToStringListProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value));
+}
+
+ResetDecorator::~ResetDecorator()
+{
+ QList<ResetWidget *> editors = m_resetWidgetToProperty.keys();
+ QListIterator<ResetWidget *> it(editors);
+ while (it.hasNext())
+ delete it.next();
+}
+
+void ResetDecorator::connectPropertyManager(QtAbstractPropertyManager *manager)
+{
+ connect(manager, SIGNAL(propertyChanged(QtProperty *)),
+ this, SLOT(slotPropertyChanged(QtProperty *)));
+}
+
+void ResetDecorator::disconnectPropertyManager(QtAbstractPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(propertyChanged(QtProperty *)),
+ this, SLOT(slotPropertyChanged(QtProperty *)));
+}
+
+void ResetDecorator::setSpacing(int spacing)
+{
+ m_spacing = spacing;
+}
+
+QWidget *ResetDecorator::editor(QWidget *subEditor, bool resettable, QtAbstractPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ Q_UNUSED(manager)
+
+ ResetWidget *resetWidget = 0;
+ if (resettable) {
+ resetWidget = new ResetWidget(property, parent);
+ resetWidget->setSpacing(m_spacing);
+ resetWidget->setResetEnabled(property->isModified());
+ resetWidget->setValueText(property->valueText());
+ resetWidget->setValueIcon(property->valueIcon());
+ resetWidget->setAutoFillBackground(true);
+ connect(resetWidget, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*)));
+ connect(resetWidget, SIGNAL(resetProperty(QtProperty *)), this, SIGNAL(resetProperty(QtProperty *)));
+ m_createdResetWidgets[property].append(resetWidget);
+ m_resetWidgetToProperty[resetWidget] = property;
+ }
+ if (subEditor) {
+ if (resetWidget) {
+ subEditor->setParent(resetWidget);
+ resetWidget->setWidget(subEditor);
+ }
+ }
+ if (resetWidget)
+ return resetWidget;
+ return subEditor;
+}
+
+void ResetDecorator::slotPropertyChanged(QtProperty *property)
+{
+ QMap<QtProperty *, QList<ResetWidget *> >::ConstIterator prIt = m_createdResetWidgets.constFind(property);
+ if (prIt == m_createdResetWidgets.constEnd())
+ return;
+
+ const QList<ResetWidget *> editors = prIt.value();
+ const QList<ResetWidget *>::ConstIterator cend = editors.constEnd();
+ for (QList<ResetWidget *>::ConstIterator itEditor = editors.constBegin(); itEditor != cend; ++itEditor) {
+ ResetWidget *widget = *itEditor;
+ widget->setResetEnabled(property->isModified());
+ widget->setValueText(property->valueText());
+ widget->setValueIcon(property->valueIcon());
+ }
+}
+
+void ResetDecorator::slotEditorDestroyed(QObject *object)
+{
+ const QMap<ResetWidget *, QtProperty *>::ConstIterator rcend = m_resetWidgetToProperty.constEnd();
+ for (QMap<ResetWidget *, QtProperty *>::ConstIterator itEditor = m_resetWidgetToProperty.constBegin(); itEditor != rcend; ++itEditor) {
+ if (itEditor.key() == object) {
+ ResetWidget *editor = itEditor.key();
+ QtProperty *property = itEditor.value();
+ m_resetWidgetToProperty.remove(editor);
+ m_createdResetWidgets[property].removeAll(editor);
+ if (m_createdResetWidgets[property].isEmpty())
+ m_createdResetWidgets.remove(property);
+ return;
+ }
+ }
+}
+
+}
+
+QT_END_NAMESPACE
+
+#include "designerpropertymanager.moc"
diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.h b/tools/designer/src/components/propertyeditor/designerpropertymanager.h
new file mode 100644
index 0000000000..78ab8e6afd
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.h
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERPROPERTYMANAGER_H
+#define DESIGNERPROPERTYMANAGER_H
+
+#include "qtvariantproperty.h"
+#include "brushpropertymanager.h"
+#include "fontpropertymanager.h"
+
+#include <qdesigner_utils_p.h>
+#include <shared_enums_p.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QMap>
+#include <QtGui/QFont>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+typedef QPair<QString, uint> DesignerIntPair;
+typedef QList<DesignerIntPair> DesignerFlagList;
+
+class QDesignerFormEditorInterface;
+class QLineEdit;
+class QUrl;
+class QtKeySequenceEdit;
+
+namespace qdesigner_internal
+{
+
+class ResetWidget;
+
+class TextEditor;
+class PaletteEditorButton;
+class PixmapEditor;
+class StringListEditorButton;
+class FormWindowBase;
+
+class ResetDecorator : public QObject
+{
+ Q_OBJECT
+public:
+ ResetDecorator(QObject *parent = 0) : QObject(parent), m_spacing(-1) {}
+ ~ResetDecorator();
+
+ void connectPropertyManager(QtAbstractPropertyManager *manager);
+ QWidget *editor(QWidget *subEditor, bool resettable, QtAbstractPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtAbstractPropertyManager *manager);
+ void setSpacing(int spacing);
+signals:
+ void resetProperty(QtProperty *property);
+private slots:
+ void slotPropertyChanged(QtProperty *property);
+ void slotEditorDestroyed(QObject *object);
+private:
+ QMap<QtProperty *, QList<ResetWidget *> > m_createdResetWidgets;
+ QMap<ResetWidget *, QtProperty *> m_resetWidgetToProperty;
+ int m_spacing;
+};
+
+class DesignerPropertyManager : public QtVariantPropertyManager
+{
+ Q_OBJECT
+public:
+ DesignerPropertyManager(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ ~DesignerPropertyManager();
+
+ virtual QStringList attributes(int propertyType) const;
+ virtual int attributeType(int propertyType, const QString &attribute) const;
+
+ virtual QVariant attributeValue(const QtProperty *property, const QString &attribute) const;
+ virtual bool isPropertyTypeSupported(int propertyType) const;
+ virtual QVariant value(const QtProperty *property) const;
+ virtual int valueType(int propertyType) const;
+ virtual QString valueText(const QtProperty *property) const;
+ virtual QIcon valueIcon(const QtProperty *property) const;
+
+ bool resetFontSubProperty(QtProperty *property);
+ bool resetIconSubProperty(QtProperty *subProperty);
+
+ void reloadResourceProperties();
+
+ static int designerFlagTypeId();
+ static int designerFlagListTypeId();
+ static int designerAlignmentTypeId();
+ static int designerPixmapTypeId();
+ static int designerIconTypeId();
+ static int designerStringTypeId();
+ static int designerKeySequenceTypeId();
+
+ void setObject(QObject *object) { m_object = object; }
+
+public Q_SLOTS:
+ virtual void setAttribute(QtProperty *property,
+ const QString &attribute, const QVariant &value);
+ virtual void setValue(QtProperty *property, const QVariant &value);
+Q_SIGNALS:
+ // sourceOfChange - a subproperty (or just property) which caused a change
+ //void valueChanged(QtProperty *property, const QVariant &value, QtProperty *sourceOfChange);
+ void valueChanged(QtProperty *property, const QVariant &value, bool enableSubPropertyHandling);
+protected:
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private Q_SLOTS:
+ void slotValueChanged(QtProperty *property, const QVariant &value);
+ void slotPropertyDestroyed(QtProperty *property);
+private:
+ void createIconSubProperty(QtProperty *iconProperty, QIcon::Mode mode, QIcon::State state, const QString &subName);
+
+ typedef QMap<QtProperty *, bool> PropertyBoolMap;
+ PropertyBoolMap m_resetMap;
+
+ int bitCount(int mask) const;
+ struct FlagData
+ {
+ FlagData() : val(0) {}
+ uint val;
+ DesignerFlagList flags;
+ QList<uint> values;
+ };
+ typedef QMap<QtProperty *, FlagData> PropertyFlagDataMap;
+ PropertyFlagDataMap m_flagValues;
+ typedef QMap<QtProperty *, QList<QtProperty *> > PropertyToPropertyListMap;
+ PropertyToPropertyListMap m_propertyToFlags;
+ QMap<QtProperty *, QtProperty *> m_flagToProperty;
+
+ int alignToIndexH(uint align) const;
+ int alignToIndexV(uint align) const;
+ uint indexHToAlign(int idx) const;
+ uint indexVToAlign(int idx) const;
+ QString indexHToString(int idx) const;
+ QString indexVToString(int idx) const;
+ QMap<QtProperty *, uint> m_alignValues;
+ typedef QMap<QtProperty *, QtProperty *> PropertyToPropertyMap;
+ PropertyToPropertyMap m_propertyToAlignH;
+ PropertyToPropertyMap m_propertyToAlignV;
+ PropertyToPropertyMap m_alignHToProperty;
+ PropertyToPropertyMap m_alignVToProperty;
+
+ QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> > m_propertyToIconSubProperties;
+ QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> > m_iconSubPropertyToState;
+ PropertyToPropertyMap m_iconSubPropertyToProperty;
+
+ QMap<QtProperty *, qdesigner_internal::PropertySheetStringValue> m_stringValues;
+ QMap<QtProperty *, QtProperty *> m_stringToComment;
+ QMap<QtProperty *, QtProperty *> m_stringToTranslatable;
+ QMap<QtProperty *, QtProperty *> m_stringToDisambiguation;
+
+ QMap<QtProperty *, QtProperty *> m_commentToString;
+ QMap<QtProperty *, QtProperty *> m_translatableToString;
+ QMap<QtProperty *, QtProperty *> m_disambiguationToString;
+
+ QMap<QtProperty *, qdesigner_internal::PropertySheetKeySequenceValue> m_keySequenceValues;
+ QMap<QtProperty *, QtProperty *> m_keySequenceToComment;
+ QMap<QtProperty *, QtProperty *> m_keySequenceToTranslatable;
+ QMap<QtProperty *, QtProperty *> m_keySequenceToDisambiguation;
+
+ QMap<QtProperty *, QtProperty *> m_commentToKeySequence;
+ QMap<QtProperty *, QtProperty *> m_translatableToKeySequence;
+ QMap<QtProperty *, QtProperty *> m_disambiguationToKeySequence;
+
+ struct PaletteData
+ {
+ QPalette val;
+ QPalette superPalette;
+ };
+ typedef QMap<QtProperty *, PaletteData> PropertyPaletteDataMap;
+ PropertyPaletteDataMap m_paletteValues;
+
+ QMap<QtProperty *, qdesigner_internal::PropertySheetPixmapValue> m_pixmapValues;
+ QMap<QtProperty *, qdesigner_internal::PropertySheetIconValue> m_iconValues;
+
+ QMap<QtProperty *, uint> m_uintValues;
+ QMap<QtProperty *, qlonglong> m_longLongValues;
+ QMap<QtProperty *, qulonglong> m_uLongLongValues;
+ QMap<QtProperty *, QUrl> m_urlValues;
+ QMap<QtProperty *, QByteArray> m_byteArrayValues;
+ QMap<QtProperty *, QStringList> m_stringListValues;
+
+ typedef QMap<QtProperty *, int> PropertyIntMap;
+ PropertyIntMap m_stringAttributes;
+ typedef QMap<QtProperty *, QFont> PropertyFontMap;
+ PropertyFontMap m_stringFontAttributes;
+
+ BrushPropertyManager m_brushManager;
+ FontPropertyManager m_fontManager;
+
+ QMap<QtProperty *, QPixmap> m_defaultPixmaps;
+ QMap<QtProperty *, QIcon> m_defaultIcons;
+
+ bool m_changingSubValue;
+ QDesignerFormEditorInterface *m_core;
+
+ QObject *m_object;
+
+ QtProperty *m_sourceOfChange;
+};
+
+class DesignerEditorFactory : public QtVariantEditorFactory
+{
+ Q_OBJECT
+public:
+ explicit DesignerEditorFactory(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ ~DesignerEditorFactory();
+ void setSpacing(int spacing);
+ void setFormWindowBase(FormWindowBase *fwb);
+signals:
+ void resetProperty(QtProperty *property);
+protected:
+ void connectPropertyManager(QtVariantPropertyManager *manager);
+ QWidget *createEditor(QtVariantPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtVariantPropertyManager *manager);
+private slots:
+ void slotEditorDestroyed(QObject *object);
+ void slotAttributeChanged(QtProperty *property, const QString &attribute, const QVariant &value);
+ void slotPropertyChanged(QtProperty *property);
+ void slotValueChanged(QtProperty *property, const QVariant &value);
+ void slotStringTextChanged(const QString &value);
+ void slotKeySequenceChanged(const QKeySequence &value);
+ void slotPaletteChanged(const QPalette &value);
+ void slotPixmapChanged(const QString &value);
+ void slotIconChanged(const QString &value);
+ void slotUintChanged(const QString &value);
+ void slotLongLongChanged(const QString &value);
+ void slotULongLongChanged(const QString &value);
+ void slotUrlChanged(const QString &value);
+ void slotByteArrayChanged(const QString &value);
+ void slotStringListChanged(const QStringList &value);
+private:
+ TextEditor *createTextEditor(QWidget *parent, TextPropertyValidationMode vm, const QString &value);
+
+ ResetDecorator *m_resetDecorator;
+ bool m_changingPropertyValue;
+ QDesignerFormEditorInterface *m_core;
+ FormWindowBase *m_fwb;
+
+ int m_spacing;
+
+ QMap<QtProperty *, QList<TextEditor *> > m_stringPropertyToEditors;
+ QMap<TextEditor *, QtProperty *> m_editorToStringProperty;
+ QMap<QtProperty *, QList<QtKeySequenceEdit *> > m_keySequencePropertyToEditors;
+ QMap<QtKeySequenceEdit *, QtProperty *> m_editorToKeySequenceProperty;
+ QMap<QtProperty *, QList<PaletteEditorButton *> > m_palettePropertyToEditors;
+ QMap<PaletteEditorButton *, QtProperty *> m_editorToPaletteProperty;
+ QMap<QtProperty *, QList<PixmapEditor *> > m_pixmapPropertyToEditors;
+ QMap<PixmapEditor *, QtProperty *> m_editorToPixmapProperty;
+ QMap<QtProperty *, QList<PixmapEditor *> > m_iconPropertyToEditors;
+ QMap<PixmapEditor *, QtProperty *> m_editorToIconProperty;
+ QMap<QtProperty *, QList<QLineEdit *> > m_uintPropertyToEditors;
+ QMap<QLineEdit *, QtProperty *> m_editorToUintProperty;
+ QMap<QtProperty *, QList<QLineEdit *> > m_longLongPropertyToEditors;
+ QMap<QLineEdit *, QtProperty *> m_editorToLongLongProperty;
+ QMap<QtProperty *, QList<QLineEdit *> > m_uLongLongPropertyToEditors;
+ QMap<QLineEdit *, QtProperty *> m_editorToULongLongProperty;
+ QMap<QtProperty *, QList<TextEditor *> > m_urlPropertyToEditors;
+ QMap<TextEditor *, QtProperty *> m_editorToUrlProperty;
+ QMap<QtProperty *, QList<TextEditor *> > m_byteArrayPropertyToEditors;
+ QMap<TextEditor *, QtProperty *> m_editorToByteArrayProperty;
+ QMap<QtProperty *, QList<StringListEditorButton *> > m_stringListPropertyToEditors;
+ QMap<StringListEditorButton *, QtProperty *> m_editorToStringListProperty;
+};
+
+}
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(DesignerIntPair)
+Q_DECLARE_METATYPE(DesignerFlagList)
+
+#endif
+
diff --git a/tools/designer/src/components/propertyeditor/fontmapping.xml b/tools/designer/src/components/propertyeditor/fontmapping.xml
new file mode 100644
index 0000000000..c19f7a3af2
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/fontmapping.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+**************************************************************************-->
+
+<!DOCTYPE fontmapping
+[
+<!ENTITY ce "Windows CE" >
+<!ENTITY qe "Qt Embedded" >
+]>
+
+<fontmappings>
+<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping>
+<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping>
+<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping>
+<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping>
+<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping>
+<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping>
+<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping>
+<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping>
+<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping>
+<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping>
+<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping>
+<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Serif</family><display>Bitstream Vera Serif [&qe;]</display></mapping>
+<mapping><family>Bitstream Vera Serif</family><display>Bitstream Vera Serif [&qe;]</display></mapping>
+</fontmappings>
diff --git a/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp
new file mode 100644
index 0000000000..ab980aa9d2
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "fontpropertymanager.h"
+#include "qtpropertymanager.h"
+#include "qtvariantproperty.h"
+#include "qtpropertybrowserutils_p.h"
+
+#include <qdesigner_utils_p.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QVariant>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+#include <QtXml/QXmlStreamReader>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ static const char *aliasingC[] = {
+ QT_TRANSLATE_NOOP("FontPropertyManager", "PreferDefault"),
+ QT_TRANSLATE_NOOP("FontPropertyManager", "NoAntialias"),
+ QT_TRANSLATE_NOOP("FontPropertyManager", "PreferAntialias")
+ };
+
+ FontPropertyManager::FontPropertyManager() :
+ m_createdFontProperty(0)
+ {
+ const int nameCount = sizeof(aliasingC)/sizeof(const char *);
+ for (int i = 0; i < nameCount; i++)
+ m_aliasingEnumNames.push_back(QCoreApplication::translate("FontPropertyManager", aliasingC[i]));
+
+ QString errorMessage;
+ if (!readFamilyMapping(&m_familyMappings, &errorMessage)) {
+ designerWarning(errorMessage);
+ }
+
+ }
+
+ void FontPropertyManager::preInitializeProperty(QtProperty *property,
+ int type,
+ ResetMap &resetMap)
+ {
+ if (m_createdFontProperty) {
+ PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(m_createdFontProperty);
+ if (it == m_propertyToFontSubProperties.end())
+ it = m_propertyToFontSubProperties.insert(m_createdFontProperty, PropertyList());
+ const int index = it.value().size();
+ m_fontSubPropertyToFlag.insert(property, index);
+ it.value().push_back(property);
+ m_fontSubPropertyToProperty[property] = m_createdFontProperty;
+ resetMap[property] = true;
+ }
+
+ if (type == QVariant::Font)
+ m_createdFontProperty = property;
+ }
+
+ // Map the font family names to display names retrieved from the XML configuration
+ static QStringList designerFamilyNames(QStringList families, const FontPropertyManager::NameMap &nm)
+ {
+ if (nm.empty())
+ return families;
+
+ const FontPropertyManager::NameMap::const_iterator ncend = nm.constEnd();
+ const QStringList::iterator end = families.end();
+ for (QStringList::iterator it = families.begin(); it != end; ++it) {
+ const FontPropertyManager::NameMap::const_iterator nit = nm.constFind(*it);
+ if (nit != ncend)
+ *it = nit.value();
+ }
+ return families;
+ }
+
+ void FontPropertyManager::postInitializeProperty(QtVariantPropertyManager *vm,
+ QtProperty *property,
+ int type,
+ int enumTypeId)
+ {
+ if (type != QVariant::Font)
+ return;
+
+ // This will cause a recursion
+ QtVariantProperty *antialiasing = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "Antialiasing"));
+ const QFont font = qVariantValue<QFont>(vm->variantProperty(property)->value());
+
+ antialiasing->setAttribute(QLatin1String("enumNames"), m_aliasingEnumNames);
+ antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
+ property->addSubProperty(antialiasing);
+
+ m_propertyToAntialiasing[property] = antialiasing;
+ m_antialiasingToProperty[antialiasing] = property;
+ // Fiddle family names
+ if (!m_familyMappings.empty()) {
+ const PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(m_createdFontProperty);
+ QtVariantProperty *familyProperty = vm->variantProperty(it.value().front());
+ const QString enumNamesAttribute = QLatin1String("enumNames");
+ QStringList plainFamilyNames = familyProperty->attributeValue(enumNamesAttribute).toStringList();
+ // Did someone load fonts or something?
+ if (m_designerFamilyNames.size() != plainFamilyNames.size())
+ m_designerFamilyNames = designerFamilyNames(plainFamilyNames, m_familyMappings);
+ familyProperty->setAttribute(enumNamesAttribute, m_designerFamilyNames);
+ }
+ // Next
+ m_createdFontProperty = 0;
+ }
+
+ bool FontPropertyManager::uninitializeProperty(QtProperty *property)
+ {
+ const PropertyToPropertyMap::iterator ait = m_propertyToAntialiasing.find(property);
+ if (ait != m_propertyToAntialiasing.end()) {
+ QtProperty *antialiasing = ait.value();
+ m_antialiasingToProperty.remove(antialiasing);
+ m_propertyToAntialiasing.erase(ait);
+ delete antialiasing;
+ }
+
+ PropertyToSubPropertiesMap::iterator sit = m_propertyToFontSubProperties.find(property);
+ if (sit == m_propertyToFontSubProperties.end())
+ return false;
+
+ m_propertyToFontSubProperties.erase(sit);
+ m_fontSubPropertyToFlag.remove(property);
+ m_fontSubPropertyToProperty.remove(property);
+
+ return true;
+ }
+
+ void FontPropertyManager::slotPropertyDestroyed(QtProperty *property)
+ {
+ removeAntialiasingProperty(property);
+ }
+
+ void FontPropertyManager::removeAntialiasingProperty(QtProperty *property)
+ {
+ const PropertyToPropertyMap::iterator ait = m_antialiasingToProperty.find(property);
+ if (ait == m_antialiasingToProperty.end())
+ return;
+ m_propertyToAntialiasing[ait.value()] = 0;
+ m_antialiasingToProperty.erase(ait);
+ }
+
+ bool FontPropertyManager::resetFontSubProperty(QtVariantPropertyManager *vm, QtProperty *property)
+ {
+ const PropertyToPropertyMap::iterator it = m_fontSubPropertyToProperty.find(property);
+ if (it == m_fontSubPropertyToProperty.end())
+ return false;
+
+ QtVariantProperty *fontProperty = vm->variantProperty(it.value());
+
+ QVariant v = fontProperty->value();
+ QFont font = qvariant_cast<QFont>(v);
+ unsigned mask = font.resolve();
+ const unsigned flag = fontFlag(m_fontSubPropertyToFlag.value(property));
+
+ mask &= ~flag;
+ font.resolve(mask);
+ qVariantSetValue(v, font);
+ fontProperty->setValue(v);
+ return true;
+ }
+
+ int FontPropertyManager::antialiasingToIndex(QFont::StyleStrategy antialias)
+ {
+ switch (antialias) {
+ case QFont::PreferDefault: return 0;
+ case QFont::NoAntialias: return 1;
+ case QFont::PreferAntialias: return 2;
+ default: break;
+ }
+ return 0;
+ }
+
+ QFont::StyleStrategy FontPropertyManager::indexToAntialiasing(int idx)
+ {
+ switch (idx) {
+ case 0: return QFont::PreferDefault;
+ case 1: return QFont::NoAntialias;
+ case 2: return QFont::PreferAntialias;
+ }
+ return QFont::PreferDefault;
+ }
+
+ unsigned FontPropertyManager::fontFlag(int idx)
+ {
+ switch (idx) {
+ case 0: return QFont::FamilyResolved;
+ case 1: return QFont::SizeResolved;
+ case 2: return QFont::WeightResolved;
+ case 3: return QFont::StyleResolved;
+ case 4: return QFont::UnderlineResolved;
+ case 5: return QFont::StrikeOutResolved;
+ case 6: return QFont::KerningResolved;
+ case 7: return QFont::StyleStrategyResolved;
+ }
+ return 0;
+ }
+
+ FontPropertyManager::ValueChangedResult FontPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
+ {
+ QtProperty *antialiasingProperty = m_antialiasingToProperty.value(property, 0);
+ if (!antialiasingProperty) {
+ if (m_propertyToFontSubProperties.contains(property)) {
+ updateModifiedState(property, value);
+ }
+ return NoMatch;
+ }
+
+ QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty);
+ const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt());
+
+ QFont font = qVariantValue<QFont>(fontProperty->value());
+ const QFont::StyleStrategy oldValue = font.styleStrategy();
+ if (newValue == oldValue)
+ return Unchanged;
+
+ font.setStyleStrategy(newValue);
+ fontProperty->setValue(qVariantFromValue(font));
+ return Changed;
+ }
+
+ void FontPropertyManager::updateModifiedState(QtProperty *property, const QVariant &value)
+ {
+ const PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(property);
+ if (it == m_propertyToFontSubProperties.end())
+ return;
+
+ const PropertyList &subProperties = it.value();
+
+ QFont font = qVariantValue<QFont>(value);
+ const unsigned mask = font.resolve();
+
+ const int count = subProperties.size();
+ for (int index = 0; index < count; index++) {
+ const unsigned flag = fontFlag(index);
+ subProperties.at(index)->setModified(mask & flag);
+ }
+ }
+
+ void FontPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value)
+ {
+ updateModifiedState(property, value);
+
+ if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) {
+ QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty);
+ if (antialiasing) {
+ QFont font = qVariantValue<QFont>(value);
+ antialiasing->setValue(antialiasingToIndex(font.styleStrategy()));
+ }
+ }
+ }
+
+ /* Parse a mappings file of the form:
+ * <fontmappings>
+ * <mapping><family>DejaVu Sans</family><display>DejaVu Sans [CE]</display></mapping>
+ * ... which is used to display on which platforms fonts are available.*/
+
+ static const char *rootTagC = "fontmappings";
+ static const char *mappingTagC = "mapping";
+ static const char *familyTagC = "family";
+ static const char *displayTagC = "display";
+
+ static QString msgXmlError(const QXmlStreamReader &r, const QString& fileName)
+ {
+ return QString::fromUtf8("An error has been encountered at line %1 of %2: %3:").arg(r.lineNumber()).arg(fileName, r.errorString());
+ }
+
+ /* Switch stages when encountering a start element (state table) */
+ enum ParseStage { ParseBeginning, ParseWithinRoot, ParseWithinMapping, ParseWithinFamily,
+ ParseWithinDisplay, ParseError };
+
+ static ParseStage nextStage(ParseStage currentStage, const QStringRef &startElement)
+ {
+ switch (currentStage) {
+ case ParseBeginning:
+ return startElement == QLatin1String(rootTagC) ? ParseWithinRoot : ParseError;
+ case ParseWithinRoot:
+ case ParseWithinDisplay: // Next mapping, was in <display>
+ return startElement == QLatin1String(mappingTagC) ? ParseWithinMapping : ParseError;
+ case ParseWithinMapping:
+ return startElement == QLatin1String(familyTagC) ? ParseWithinFamily : ParseError;
+ case ParseWithinFamily:
+ return startElement == QLatin1String(displayTagC) ? ParseWithinDisplay : ParseError;
+ case ParseError:
+ break;
+ }
+ return ParseError;
+ }
+
+ bool FontPropertyManager::readFamilyMapping(NameMap *rc, QString *errorMessage)
+ {
+ rc->clear();
+ const QString fileName = QLatin1String(":/trolltech/propertyeditor/fontmapping.xml");
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly)) {
+ *errorMessage = QString::fromUtf8("Unable to open %1: %2").arg(fileName, file.errorString());
+ return false;
+ }
+
+ QXmlStreamReader reader(&file);
+ QXmlStreamReader::TokenType token;
+
+ QString family;
+ ParseStage stage = ParseBeginning;
+ do {
+ token = reader.readNext();
+ switch (token) {
+ case QXmlStreamReader::Invalid:
+ *errorMessage = msgXmlError(reader, fileName);
+ return false;
+ case QXmlStreamReader::StartElement:
+ stage = nextStage(stage, reader.name());
+ switch (stage) {
+ case ParseError:
+ reader.raiseError(QString::fromUtf8("Unexpected element <%1>.").arg(reader.name().toString()));
+ *errorMessage = msgXmlError(reader, fileName);
+ return false;
+ case ParseWithinFamily:
+ family = reader.readElementText();
+ break;
+ case ParseWithinDisplay:
+ rc->insert(family, reader.readElementText());
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ } while (token != QXmlStreamReader::EndDocument);
+ return true;
+ }
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/fontpropertymanager.h b/tools/designer/src/components/propertyeditor/fontpropertymanager.h
new file mode 100644
index 0000000000..915dcd9079
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/fontpropertymanager.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FONTPROPERTYMANAGER_H
+#define FONTPROPERTYMANAGER_H
+
+#include <QtCore/QMap>
+#include <QtCore/QStringList>
+#include <QtGui/QFont>
+
+QT_BEGIN_NAMESPACE
+
+class QtProperty;
+class QtVariantPropertyManager;
+
+class QString;
+class QVariant;
+
+namespace qdesigner_internal {
+
+/* FontPropertyManager: A mixin for DesignerPropertyManager that manages font
+ * properties. Adds an antialiasing subproperty and reset flags/mask handling
+ * for the other subproperties. It also modifies the font family
+ * enumeration names, which it reads from an XML mapping file that
+ * contains annotations indicating the platform the font is available on. */
+
+class FontPropertyManager {
+ Q_DISABLE_COPY(FontPropertyManager)
+
+public:
+ FontPropertyManager();
+
+ typedef QMap<QtProperty *, bool> ResetMap;
+ typedef QMap<QString, QString> NameMap;
+
+ // Call before QtVariantPropertyManager::initializeProperty.
+ void preInitializeProperty(QtProperty *property, int type, ResetMap &resetMap);
+ // Call after QtVariantPropertyManager::initializeProperty. This will trigger
+ // a recursion for the sub properties
+ void postInitializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int type, int enumTypeId);
+
+ bool uninitializeProperty(QtProperty *property);
+
+ // Call from QtPropertyManager's propertyDestroyed signal
+ void slotPropertyDestroyed(QtProperty *property);
+
+ bool resetFontSubProperty(QtVariantPropertyManager *vm, QtProperty *subProperty);
+
+ // Call from slotValueChanged().
+ enum ValueChangedResult { NoMatch, Unchanged, Changed };
+ ValueChangedResult valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value);
+
+ // Call from setValue() before calling setValue() on QtVariantPropertyManager.
+ void setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value);
+
+ static bool readFamilyMapping(NameMap *rc, QString *errorMessage);
+
+private:
+ typedef QMap<QtProperty *, QtProperty *> PropertyToPropertyMap;
+ typedef QList<QtProperty *> PropertyList;
+ typedef QMap<QtProperty *, PropertyList> PropertyToSubPropertiesMap;
+
+ void removeAntialiasingProperty(QtProperty *);
+ void updateModifiedState(QtProperty *property, const QVariant &value);
+ static int antialiasingToIndex(QFont::StyleStrategy antialias);
+ static QFont::StyleStrategy indexToAntialiasing(int idx);
+ static unsigned fontFlag(int idx);
+
+ PropertyToPropertyMap m_propertyToAntialiasing;
+ PropertyToPropertyMap m_antialiasingToProperty;
+
+ PropertyToSubPropertiesMap m_propertyToFontSubProperties;
+ QMap<QtProperty *, int> m_fontSubPropertyToFlag;
+ PropertyToPropertyMap m_fontSubPropertyToProperty;
+ QtProperty *m_createdFontProperty;
+ QStringList m_aliasingEnumNames;
+ // Font families with Designer annotations
+ QStringList m_designerFamilyNames;
+ NameMap m_familyMappings;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // FONTPROPERTYMANAGER_H
diff --git a/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp
new file mode 100644
index 0000000000..b9f0227a65
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "newdynamicpropertydialog.h"
+#include "ui_newdynamicpropertydialog.h"
+#include <abstractdialoggui_p.h>
+#include <qdesigner_propertysheet_p.h>
+
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+NewDynamicPropertyDialog::NewDynamicPropertyDialog(QDesignerDialogGuiInterface *dialogGui,
+ QWidget *parent) :
+ QDialog(parent),
+ m_dialogGui(dialogGui),
+ m_ui(new Ui::NewDynamicPropertyDialog)
+{
+ m_ui->setupUi(this);
+ connect(m_ui->m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(nameChanged(QString)));
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ m_ui->m_comboBox->addItem(QLatin1String("String"), QVariant(QVariant::String));
+ m_ui->m_comboBox->addItem(QLatin1String("StringList"), QVariant(QVariant::StringList));
+ m_ui->m_comboBox->addItem(QLatin1String("Char"), QVariant(QVariant::Char));
+ m_ui->m_comboBox->addItem(QLatin1String("ByteArray"), QVariant(QVariant::ByteArray));
+ m_ui->m_comboBox->addItem(QLatin1String("Url"), QVariant(QVariant::Url));
+ m_ui->m_comboBox->addItem(QLatin1String("Bool"), QVariant(QVariant::Bool));
+ m_ui->m_comboBox->addItem(QLatin1String("Int"), QVariant(QVariant::Int));
+ m_ui->m_comboBox->addItem(QLatin1String("UInt"), QVariant(QVariant::UInt));
+ m_ui->m_comboBox->addItem(QLatin1String("LongLong"), QVariant(QVariant::LongLong));
+ m_ui->m_comboBox->addItem(QLatin1String("ULongLong"), QVariant(QVariant::ULongLong));
+ m_ui->m_comboBox->addItem(QLatin1String("Double"), QVariant(QVariant::Double));
+ m_ui->m_comboBox->addItem(QLatin1String("Size"), QVariant(QVariant::Size));
+ m_ui->m_comboBox->addItem(QLatin1String("SizeF"), QVariant(QVariant::SizeF));
+ m_ui->m_comboBox->addItem(QLatin1String("Point"), QVariant(QVariant::Point));
+ m_ui->m_comboBox->addItem(QLatin1String("PointF"), QVariant(QVariant::PointF));
+ m_ui->m_comboBox->addItem(QLatin1String("Rect"), QVariant(QVariant::Rect));
+ m_ui->m_comboBox->addItem(QLatin1String("RectF"), QVariant(QVariant::RectF));
+ m_ui->m_comboBox->addItem(QLatin1String("Date"), QVariant(QVariant::Date));
+ m_ui->m_comboBox->addItem(QLatin1String("Time"), QVariant(QVariant::Time));
+ m_ui->m_comboBox->addItem(QLatin1String("DateTime"), QVariant(QVariant::DateTime));
+ m_ui->m_comboBox->addItem(QLatin1String("Font"), QVariant(QVariant::Font));
+ m_ui->m_comboBox->addItem(QLatin1String("Palette"), QVariant(QVariant::Palette));
+ m_ui->m_comboBox->addItem(QLatin1String("Color"), QVariant(QVariant::Color));
+ m_ui->m_comboBox->addItem(QLatin1String("Pixmap"), QVariant(QVariant::Pixmap));
+ m_ui->m_comboBox->addItem(QLatin1String("Icon"), QVariant(QVariant::Icon));
+ m_ui->m_comboBox->addItem(QLatin1String("Cursor"), QVariant(QVariant::Cursor));
+ m_ui->m_comboBox->addItem(QLatin1String("SizePolicy"), QVariant(QVariant::SizePolicy));
+ m_ui->m_comboBox->addItem(QLatin1String("KeySequence"), QVariant(QVariant::KeySequence));
+
+ m_ui->m_comboBox->setCurrentIndex(0); // String
+ setOkButtonEnabled(false);
+}
+
+void NewDynamicPropertyDialog::setOkButtonEnabled(bool e)
+{
+ m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(e);
+}
+
+NewDynamicPropertyDialog::~NewDynamicPropertyDialog()
+{
+ delete m_ui;
+}
+
+void NewDynamicPropertyDialog::setReservedNames(const QStringList &names)
+{
+ m_reservedNames = names;
+}
+
+void NewDynamicPropertyDialog::setPropertyType(QVariant::Type t)
+{
+ const int index = m_ui->m_comboBox->findData(QVariant(t));
+ if (index != -1)
+ m_ui->m_comboBox->setCurrentIndex(index);
+}
+
+QString NewDynamicPropertyDialog::propertyName() const
+{
+ return m_ui->m_lineEdit->text();
+}
+
+QVariant NewDynamicPropertyDialog::propertyValue() const
+{
+ const int index = m_ui->m_comboBox->currentIndex();
+ if (index == -1)
+ return QVariant();
+ return m_ui->m_comboBox->itemData(index);
+}
+
+void NewDynamicPropertyDialog::information(const QString &message)
+{
+ m_dialogGui->message(this, QDesignerDialogGuiInterface::PropertyEditorMessage, QMessageBox::Information, tr("Set Property Name"), message);
+}
+
+void NewDynamicPropertyDialog::nameChanged(const QString &s)
+{
+ setOkButtonEnabled(!s.isEmpty());
+}
+
+bool NewDynamicPropertyDialog::validatePropertyName(const QString& name)
+{
+ if (m_reservedNames.contains(name)) {
+ information(tr("The current object already has a property named '%1'.\nPlease select another, unique one.").arg(name));
+ return false;
+ }
+ if (!QDesignerPropertySheet::internalDynamicPropertiesEnabled() && name.startsWith(QLatin1String("_q_"))) {
+ information(tr("The '_q_' prefix is reserved for the Qt library.\nPlease select another name."));
+ return false;
+ }
+ return true;
+}
+
+void NewDynamicPropertyDialog::on_m_buttonBox_clicked(QAbstractButton *btn)
+{
+ const int role = m_ui->m_buttonBox->buttonRole(btn);
+ switch (role) {
+ case QDialogButtonBox::RejectRole:
+ reject();
+ break;
+ case QDialogButtonBox::AcceptRole:
+ if (validatePropertyName(propertyName()))
+ accept();
+ break;
+ }
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.h b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.h
new file mode 100644
index 0000000000..025f4fd80a
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NEWDYNAMICPROPERTYDIALOG_P_H
+#define NEWDYNAMICPROPERTYDIALOG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "propertyeditor_global.h"
+#include <QtGui/QDialog>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractButton;
+class QDesignerDialogGuiInterface;
+
+namespace qdesigner_internal {
+
+namespace Ui
+{
+ class NewDynamicPropertyDialog;
+}
+
+class QT_PROPERTYEDITOR_EXPORT NewDynamicPropertyDialog: public QDialog
+{
+ Q_OBJECT
+public:
+ explicit NewDynamicPropertyDialog(QDesignerDialogGuiInterface *dialogGui, QWidget *parent = 0);
+ ~NewDynamicPropertyDialog();
+
+ void setReservedNames(const QStringList &names);
+ void setPropertyType(QVariant::Type t);
+
+ QString propertyName() const;
+ QVariant propertyValue() const;
+
+private slots:
+
+ void on_m_buttonBox_clicked(QAbstractButton *btn);
+ void nameChanged(const QString &);
+
+private:
+ bool validatePropertyName(const QString& name);
+ void setOkButtonEnabled(bool e);
+ void information(const QString &message);
+
+ QDesignerDialogGuiInterface *m_dialogGui;
+ Ui::NewDynamicPropertyDialog *m_ui;
+ QStringList m_reservedNames;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // NEWDYNAMICPROPERTYDIALOG_P_H
diff --git a/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.ui b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.ui
new file mode 100644
index 0000000000..2aa91f3e9e
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.ui
@@ -0,0 +1,106 @@
+<ui version="4.0" >
+ <class>qdesigner_internal::NewDynamicPropertyDialog</class>
+ <widget class="QDialog" name="qdesigner_internal::NewDynamicPropertyDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>340</width>
+ <height>118</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Create Dynamic Property</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <layout class="QFormLayout" name="formLayout" >
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="m_lineEdit" >
+ <property name="minimumSize" >
+ <size>
+ <width>220</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Property Name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <widget class="QComboBox" name="m_comboBox" />
+ </item>
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="spacerName" stdset="0" >
+ <string>horizontalSpacer</string>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Property Type</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer>
+ <property name="spacerName" stdset="0" >
+ <string/>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="m_buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ <property name="centerButtons" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.cpp b/tools/designer/src/components/propertyeditor/paletteeditor.cpp
new file mode 100644
index 0000000000..b0dc82b35c
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/paletteeditor.cpp
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::PaletteEditor
+*/
+/*
+TRANSLATOR qdesigner_internal::PaletteModel
+*/
+
+#include "paletteeditor.h"
+
+#include <iconloader_p.h>
+#include <qtcolorbutton.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerIconCacheInterface>
+
+#include <QtCore/QMetaProperty>
+#include <QtGui/QPainter>
+#include <QtGui/QToolButton>
+#include <QtGui/QLabel>
+#include <QtGui/QHeaderView>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+enum { BrushRole = 33 };
+
+PaletteEditor::PaletteEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QDialog(parent),
+ m_currentColorGroup(QPalette::Active),
+ m_paletteModel(new PaletteModel(this)),
+ m_modelUpdated(false),
+ m_paletteUpdated(false),
+ m_compute(true),
+ m_core(core)
+{
+ ui.setupUi(this);
+ ui.paletteView->setModel(m_paletteModel);
+ updatePreviewPalette();
+ updateStyledButton();
+ ui.paletteView->setModel(m_paletteModel);
+ ColorDelegate *delegate = new ColorDelegate(core, this);
+ ui.paletteView->setItemDelegate(delegate);
+ ui.paletteView->setEditTriggers(QAbstractItemView::AllEditTriggers);
+ connect(m_paletteModel, SIGNAL(paletteChanged(const QPalette &)),
+ this, SLOT(paletteChanged(const QPalette &)));
+ ui.paletteView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ ui.paletteView->setDragEnabled(true);
+ ui.paletteView->setDropIndicatorShown(true);
+ ui.paletteView->setRootIsDecorated(false);
+ ui.paletteView->setColumnHidden(2, true);
+ ui.paletteView->setColumnHidden(3, true);
+}
+
+PaletteEditor::~PaletteEditor()
+{
+}
+
+QPalette PaletteEditor::palette() const
+{
+ return m_editPalette;
+}
+
+void PaletteEditor::setPalette(const QPalette &palette)
+{
+ m_editPalette = palette;
+ const uint mask = palette.resolve();
+ for (int i = 0; i < (int)QPalette::NColorRoles; i++) {
+ if (!(mask & (1 << i))) {
+ m_editPalette.setBrush(QPalette::Active, static_cast<QPalette::ColorRole>(i),
+ m_parentPalette.brush(QPalette::Active, static_cast<QPalette::ColorRole>(i)));
+ m_editPalette.setBrush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i),
+ m_parentPalette.brush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i)));
+ m_editPalette.setBrush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i),
+ m_parentPalette.brush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i)));
+ }
+ }
+ m_editPalette.resolve(mask);
+ updatePreviewPalette();
+ updateStyledButton();
+ m_paletteUpdated = true;
+ if (!m_modelUpdated)
+ m_paletteModel->setPalette(m_editPalette, m_parentPalette);
+ m_paletteUpdated = false;
+}
+
+void PaletteEditor::setPalette(const QPalette &palette, const QPalette &parentPalette)
+{
+ m_parentPalette = parentPalette;
+ setPalette(palette);
+}
+
+void PaletteEditor::on_buildButton_colorChanged(const QColor &)
+{
+ buildPalette();
+}
+
+void PaletteEditor::on_activeRadio_clicked()
+{
+ m_currentColorGroup = QPalette::Active;
+ updatePreviewPalette();
+}
+
+void PaletteEditor::on_inactiveRadio_clicked()
+{
+ m_currentColorGroup = QPalette::Inactive;
+ updatePreviewPalette();
+}
+
+void PaletteEditor::on_disabledRadio_clicked()
+{
+ m_currentColorGroup = QPalette::Disabled;
+ updatePreviewPalette();
+}
+
+void PaletteEditor::on_computeRadio_clicked()
+{
+ if (m_compute)
+ return;
+ ui.paletteView->setColumnHidden(2, true);
+ ui.paletteView->setColumnHidden(3, true);
+ m_compute = true;
+ m_paletteModel->setCompute(true);
+}
+
+void PaletteEditor::on_detailsRadio_clicked()
+{
+ if (!m_compute)
+ return;
+ const int w = ui.paletteView->columnWidth(1);
+ ui.paletteView->setColumnHidden(2, false);
+ ui.paletteView->setColumnHidden(3, false);
+ QHeaderView *header = ui.paletteView->header();
+ header->resizeSection(1, w / 3);
+ header->resizeSection(2, w / 3);
+ header->resizeSection(3, w / 3);
+ m_compute = false;
+ m_paletteModel->setCompute(false);
+}
+
+void PaletteEditor::paletteChanged(const QPalette &palette)
+{
+ m_modelUpdated = true;
+ if (!m_paletteUpdated)
+ setPalette(palette);
+ m_modelUpdated = false;
+}
+
+void PaletteEditor::buildPalette()
+{
+ const QColor btn = ui.buildButton->color();
+ const QPalette temp = QPalette(btn);
+ setPalette(temp);
+}
+
+void PaletteEditor::updatePreviewPalette()
+{
+ const QPalette::ColorGroup g = currentColorGroup();
+ // build the preview palette
+ const QPalette currentPalette = palette();
+ QPalette previewPalette;
+ for (int i = QPalette::WindowText; i < QPalette::NColorRoles; i++) {
+ const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(i);
+ const QBrush br = currentPalette.brush(g, r);
+ previewPalette.setBrush(QPalette::Active, r, br);
+ previewPalette.setBrush(QPalette::Inactive, r, br);
+ previewPalette.setBrush(QPalette::Disabled, r, br);
+ }
+ ui.previewFrame->setPreviewPalette(previewPalette);
+
+ const bool enabled = g != QPalette::Disabled;
+ ui.previewFrame->setEnabled(enabled);
+ ui.previewFrame->setSubWindowActive(g != QPalette::Inactive);
+}
+
+void PaletteEditor::updateStyledButton()
+{
+ ui.buildButton->setColor(palette().color(QPalette::Active, QPalette::Button));
+}
+
+QPalette PaletteEditor::getPalette(QDesignerFormEditorInterface *core, QWidget* parent, const QPalette &init,
+ const QPalette &parentPal, int *ok)
+{
+ PaletteEditor dlg(core, parent);
+ QPalette parentPalette(parentPal);
+ uint mask = init.resolve();
+ for (int i = 0; i < (int)QPalette::NColorRoles; i++) {
+ if (!(mask & (1 << i))) {
+ parentPalette.setBrush(QPalette::Active, static_cast<QPalette::ColorRole>(i),
+ init.brush(QPalette::Active, static_cast<QPalette::ColorRole>(i)));
+ parentPalette.setBrush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i),
+ init.brush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i)));
+ parentPalette.setBrush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i),
+ init.brush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i)));
+ }
+ }
+ dlg.setPalette(init, parentPalette);
+
+ const int result = dlg.exec();
+ if (ok) *ok = result;
+
+ return result == QDialog::Accepted ? dlg.palette() : init;
+}
+
+//////////////////////
+
+PaletteModel::PaletteModel(QObject *parent) :
+ QAbstractTableModel(parent),
+ m_compute(true)
+{
+ const QMetaObject *meta = metaObject();
+ const int index = meta->indexOfProperty("colorRole");
+ const QMetaProperty p = meta->property(index);
+ const QMetaEnum e = p.enumerator();
+ for (int r = QPalette::WindowText; r < QPalette::NColorRoles; r++) {
+ m_roleNames[static_cast<QPalette::ColorRole>(r)] = QLatin1String(e.key(r));
+ }
+}
+
+int PaletteModel::rowCount(const QModelIndex &) const
+{
+ return m_roleNames.count();
+}
+
+int PaletteModel::columnCount(const QModelIndex &) const
+{
+ return 4;
+}
+
+QVariant PaletteModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+ if (index.row() < 0 || index.row() >= QPalette::NColorRoles)
+ return QVariant();
+ if (index.column() < 0 || index.column() >= 4)
+ return QVariant();
+
+ if (index.column() == 0) {
+ if (role == Qt::DisplayRole)
+ return m_roleNames[static_cast<QPalette::ColorRole>(index.row())];
+ if (role == Qt::EditRole) {
+ const uint mask = m_palette.resolve();
+ if (mask & (1 << index.row()))
+ return true;
+ return false;
+ }
+ return QVariant();
+ }
+ if (role == BrushRole)
+ return m_palette.brush(columnToGroup(index.column()),
+ static_cast<QPalette::ColorRole>(index.row()));
+ return QVariant();
+}
+
+bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!index.isValid())
+ return false;
+
+ if (index.column() != 0 && role == BrushRole) {
+ const QBrush br = qVariantValue<QBrush>(value);
+ const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(index.row());
+ const QPalette::ColorGroup g = columnToGroup(index.column());
+ m_palette.setBrush(g, r, br);
+
+ QModelIndex idxBegin = PaletteModel::index(r, 0);
+ QModelIndex idxEnd = PaletteModel::index(r, 3);
+ if (m_compute) {
+ m_palette.setBrush(QPalette::Inactive, r, br);
+ switch (r) {
+ case QPalette::WindowText:
+ case QPalette::Text:
+ case QPalette::ButtonText:
+ case QPalette::Base:
+ break;
+ case QPalette::Dark:
+ m_palette.setBrush(QPalette::Disabled, QPalette::WindowText, br);
+ m_palette.setBrush(QPalette::Disabled, QPalette::Dark, br);
+ m_palette.setBrush(QPalette::Disabled, QPalette::Text, br);
+ m_palette.setBrush(QPalette::Disabled, QPalette::ButtonText, br);
+ idxBegin = PaletteModel::index(0, 0);
+ idxEnd = PaletteModel::index(m_roleNames.count() - 1, 3);
+ break;
+ case QPalette::Window:
+ m_palette.setBrush(QPalette::Disabled, QPalette::Base, br);
+ m_palette.setBrush(QPalette::Disabled, QPalette::Window, br);
+ idxBegin = PaletteModel::index(QPalette::Base, 0);
+ break;
+ case QPalette::Highlight:
+ //m_palette.setBrush(QPalette::Disabled, QPalette::Highlight, c.dark(120));
+ break;
+ default:
+ m_palette.setBrush(QPalette::Disabled, r, br);
+ break;
+ }
+ }
+ emit paletteChanged(m_palette);
+ emit dataChanged(idxBegin, idxEnd);
+ return true;
+ }
+ if (index.column() == 0 && role == Qt::EditRole) {
+ uint mask = m_palette.resolve();
+ const bool isMask = qVariantValue<bool>(value);
+ const int r = index.row();
+ if (isMask)
+ mask |= (1 << r);
+ else {
+ m_palette.setBrush(QPalette::Active, static_cast<QPalette::ColorRole>(r),
+ m_parentPalette.brush(QPalette::Active, static_cast<QPalette::ColorRole>(r)));
+ m_palette.setBrush(QPalette::Inactive, static_cast<QPalette::ColorRole>(r),
+ m_parentPalette.brush(QPalette::Inactive, static_cast<QPalette::ColorRole>(r)));
+ m_palette.setBrush(QPalette::Disabled, static_cast<QPalette::ColorRole>(r),
+ m_parentPalette.brush(QPalette::Disabled, static_cast<QPalette::ColorRole>(r)));
+
+ mask &= ~(1 << index.row());
+ }
+ m_palette.resolve(mask);
+ emit paletteChanged(m_palette);
+ const QModelIndex idxEnd = PaletteModel::index(r, 3);
+ emit dataChanged(index, idxEnd);
+ return true;
+ }
+ return false;
+}
+
+Qt::ItemFlags PaletteModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::ItemIsEnabled;
+ return Qt::ItemIsEditable | Qt::ItemIsEnabled;
+}
+
+QVariant PaletteModel::headerData(int section, Qt::Orientation orientation,
+ int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ if (section == 0)
+ return tr("Color Role");
+ if (section == groupToColumn(QPalette::Active))
+ return tr("Active");
+ if (section == groupToColumn(QPalette::Inactive))
+ return tr("Inactive");
+ if (section == groupToColumn(QPalette::Disabled))
+ return tr("Disabled");
+ }
+ return QVariant();
+}
+
+QPalette PaletteModel::getPalette() const
+{
+ return m_palette;
+}
+
+void PaletteModel::setPalette(const QPalette &palette, const QPalette &parentPalette)
+{
+ m_parentPalette = parentPalette;
+ m_palette = palette;
+ const QModelIndex idxBegin = index(0, 0);
+ const QModelIndex idxEnd = index(m_roleNames.count() - 1, 3);
+ emit dataChanged(idxBegin, idxEnd);
+}
+
+QPalette::ColorGroup PaletteModel::columnToGroup(int index) const
+{
+ if (index == 1)
+ return QPalette::Active;
+ if (index == 2)
+ return QPalette::Inactive;
+ return QPalette::Disabled;
+}
+
+int PaletteModel::groupToColumn(QPalette::ColorGroup group) const
+{
+ if (group == QPalette::Active)
+ return 1;
+ if (group == QPalette::Inactive)
+ return 2;
+ return 3;
+}
+
+//////////////////////////
+
+BrushEditor::BrushEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QWidget(parent),
+ m_button(new QtColorButton(this)),
+ m_changed(false),
+ m_core(core)
+{
+ QLayout *layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_button);
+ connect(m_button, SIGNAL(colorChanged(const QColor &)), this, SLOT(brushChanged()));
+ setFocusProxy(m_button);
+}
+
+void BrushEditor::setBrush(const QBrush &brush)
+{
+ m_button->setColor(brush.color());
+ m_changed = false;
+}
+
+QBrush BrushEditor::brush() const
+{
+ return QBrush(m_button->color());
+}
+
+void BrushEditor::brushChanged()
+{
+ m_changed = true;
+ emit changed(this);
+}
+
+bool BrushEditor::changed() const
+{
+ return m_changed;
+}
+
+//////////////////////////
+
+RoleEditor::RoleEditor(QWidget *parent) :
+ QWidget(parent),
+ m_label(new QLabel(this)),
+ m_edited(false)
+{
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->setSpacing(0);
+
+ layout->addWidget(m_label);
+ m_label->setAutoFillBackground(true);
+ m_label->setIndent(3); // ### hardcode it should have the same value of textMargin in QItemDelegate
+ setFocusProxy(m_label);
+
+ QToolButton *button = new QToolButton(this);
+ button->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ button->setIcon(createIconSet(QLatin1String("resetproperty.png")));
+ button->setIconSize(QSize(8,8));
+ button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
+ layout->addWidget(button);
+ connect(button, SIGNAL(clicked()), this, SLOT(emitResetProperty()));
+}
+
+void RoleEditor::setLabel(const QString &label)
+{
+ m_label->setText(label);
+}
+
+void RoleEditor::setEdited(bool on)
+{
+ QFont font;
+ if (on == true) {
+ font.setBold(on);
+ }
+ m_label->setFont(font);
+ m_edited = on;
+}
+
+bool RoleEditor::edited() const
+{
+ return m_edited;
+}
+
+void RoleEditor::emitResetProperty()
+{
+ setEdited(false);
+ emit changed(this);
+}
+
+//////////////////////////
+ColorDelegate::ColorDelegate(QDesignerFormEditorInterface *core, QObject *parent) :
+ QItemDelegate(parent),
+ m_core(core)
+{
+}
+
+QWidget *ColorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &,
+ const QModelIndex &index) const
+{
+ QWidget *ed = 0;
+ if (index.column() == 0) {
+ RoleEditor *editor = new RoleEditor(parent);
+ connect(editor, SIGNAL(changed(QWidget *)), this, SIGNAL(commitData(QWidget *)));
+ //editor->setFocusPolicy(Qt::NoFocus);
+ //editor->installEventFilter(const_cast<ColorDelegate *>(this));
+ ed = editor;
+ } else {
+ BrushEditor *editor = new BrushEditor(m_core, parent);
+ connect(editor, SIGNAL(changed(QWidget *)), this, SIGNAL(commitData(QWidget *)));
+ editor->setFocusPolicy(Qt::NoFocus);
+ editor->installEventFilter(const_cast<ColorDelegate *>(this));
+ ed = editor;
+ }
+ return ed;
+}
+
+void ColorDelegate::setEditorData(QWidget *ed, const QModelIndex &index) const
+{
+ if (index.column() == 0) {
+ const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole));
+ RoleEditor *editor = static_cast<RoleEditor *>(ed);
+ editor->setEdited(mask);
+ const QString colorName = qVariantValue<QString>(index.model()->data(index, Qt::DisplayRole));
+ editor->setLabel(colorName);
+ } else {
+ const QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole));
+ BrushEditor *editor = static_cast<BrushEditor *>(ed);
+ editor->setBrush(br);
+ }
+}
+
+void ColorDelegate::setModelData(QWidget *ed, QAbstractItemModel *model,
+ const QModelIndex &index) const
+{
+ if (index.column() == 0) {
+ RoleEditor *editor = static_cast<RoleEditor *>(ed);
+ const bool mask = editor->edited();
+ model->setData(index, mask, Qt::EditRole);
+ } else {
+ BrushEditor *editor = static_cast<BrushEditor *>(ed);
+ if (editor->changed()) {
+ QBrush br = editor->brush();
+ model->setData(index, br, BrushRole);
+ }
+ }
+}
+
+void ColorDelegate::updateEditorGeometry(QWidget *ed,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QItemDelegate::updateEditorGeometry(ed, option, index);
+ ed->setGeometry(ed->geometry().adjusted(0, 0, -1, -1));
+}
+
+void ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt,
+ const QModelIndex &index) const
+{
+ QStyleOptionViewItem option = opt;
+ const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole));
+ if (index.column() == 0 && mask) {
+ option.font.setBold(true);
+ }
+ QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole));
+ if (br.style() == Qt::LinearGradientPattern ||
+ br.style() == Qt::RadialGradientPattern ||
+ br.style() == Qt::ConicalGradientPattern) {
+ painter->save();
+ painter->translate(option.rect.x(), option.rect.y());
+ painter->scale(option.rect.width(), option.rect.height());
+ QGradient gr = *(br.gradient());
+ gr.setCoordinateMode(QGradient::LogicalMode);
+ br = QBrush(gr);
+ painter->fillRect(0, 0, 1, 1, br);
+ painter->restore();
+ } else {
+ painter->save();
+ painter->setBrushOrigin(option.rect.x(), option.rect.y());
+ painter->fillRect(option.rect, br);
+ painter->restore();
+ }
+ QItemDelegate::paint(painter, option, index);
+
+
+ const QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &option));
+ const QPen oldPen = painter->pen();
+ painter->setPen(QPen(color));
+
+ painter->drawLine(option.rect.right(), option.rect.y(),
+ option.rect.right(), option.rect.bottom());
+ painter->drawLine(option.rect.x(), option.rect.bottom(),
+ option.rect.right(), option.rect.bottom());
+ painter->setPen(oldPen);
+}
+
+QSize ColorDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const
+{
+ return QItemDelegate::sizeHint(opt, index) + QSize(4, 4);
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.h b/tools/designer/src/components/propertyeditor/paletteeditor.h
new file mode 100644
index 0000000000..f501968c6c
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/paletteeditor.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PALETTEEDITOR_H
+#define PALETTEEDITOR_H
+
+#include "ui_paletteeditor.h"
+#include <QtGui/QItemDelegate>
+
+QT_BEGIN_NAMESPACE
+
+class QListView;
+class QLabel;
+class QtColorButton;
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class PaletteEditor: public QDialog
+{
+ Q_OBJECT
+public:
+ virtual ~PaletteEditor();
+
+ static QPalette getPalette(QDesignerFormEditorInterface *core,
+ QWidget* parent, const QPalette &init = QPalette(),
+ const QPalette &parentPal = QPalette(), int *result = 0);
+
+ QPalette palette() const;
+ void setPalette(const QPalette &palette);
+ void setPalette(const QPalette &palette, const QPalette &parentPalette);
+
+private slots:
+
+ void on_buildButton_colorChanged(const QColor &);
+ void on_activeRadio_clicked();
+ void on_inactiveRadio_clicked();
+ void on_disabledRadio_clicked();
+ void on_computeRadio_clicked();
+ void on_detailsRadio_clicked();
+
+ void paletteChanged(const QPalette &palette);
+
+protected:
+
+private:
+ PaletteEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+ void buildPalette();
+
+ void updatePreviewPalette();
+ void updateStyledButton();
+
+ QPalette::ColorGroup currentColorGroup() const
+ { return m_currentColorGroup; }
+
+ Ui::PaletteEditor ui;
+ QPalette m_editPalette;
+ QPalette m_parentPalette;
+ QPalette::ColorGroup m_currentColorGroup;
+ class PaletteModel *m_paletteModel;
+ bool m_modelUpdated;
+ bool m_paletteUpdated;
+ bool m_compute;
+ QDesignerFormEditorInterface *m_core;
+};
+
+
+class PaletteModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(QPalette::ColorRole colorRole READ colorRole)
+public:
+ explicit PaletteModel(QObject *parent = 0);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+
+ QPalette getPalette() const;
+ void setPalette(const QPalette &palette, const QPalette &parentPalette);
+
+ QPalette::ColorRole colorRole() const { return QPalette::NoRole; }
+ void setCompute(bool on) { m_compute = on; }
+signals:
+ void paletteChanged(const QPalette &palette);
+private:
+
+ QPalette::ColorGroup columnToGroup(int index) const;
+ int groupToColumn(QPalette::ColorGroup group) const;
+
+ QPalette m_palette;
+ QPalette m_parentPalette;
+ QMap<QPalette::ColorRole, QString> m_roleNames;
+ bool m_compute;
+};
+
+class BrushEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit BrushEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+
+ void setBrush(const QBrush &brush);
+ QBrush brush() const;
+ bool changed() const;
+signals:
+ void changed(QWidget *widget);
+private slots:
+ void brushChanged();
+private:
+ QtColorButton *m_button;
+ bool m_changed;
+ QDesignerFormEditorInterface *m_core;
+};
+
+class RoleEditor : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit RoleEditor(QWidget *parent = 0);
+
+ void setLabel(const QString &label);
+ void setEdited(bool on);
+ bool edited() const;
+signals:
+ void changed(QWidget *widget);
+private slots:
+ void emitResetProperty();
+private:
+ QLabel *m_label;
+ bool m_edited;
+};
+
+class ColorDelegate : public QItemDelegate
+{
+ Q_OBJECT
+
+public:
+ explicit ColorDelegate(QDesignerFormEditorInterface *core, QObject *parent = 0);
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ void setEditorData(QWidget *ed, const QModelIndex &index) const;
+ void setModelData(QWidget *ed, QAbstractItemModel *model,
+ const QModelIndex &index) const;
+
+ void updateEditorGeometry(QWidget *ed,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &opt,
+ const QModelIndex &index) const;
+ virtual QSize sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const;
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PALETTEEDITOR_H
diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.ui b/tools/designer/src/components/propertyeditor/paletteeditor.ui
new file mode 100644
index 0000000000..55ef5ac690
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/paletteeditor.ui
@@ -0,0 +1,264 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::PaletteEditor</class>
+ <widget class="QDialog" name="qdesigner_internal::PaletteEditor" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>365</width>
+ <height>409</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle" >
+ <string>Edit Palette</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="advancedBox" >
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="title" >
+ <string>Tune Palette</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="1" >
+ <widget class="QtColorButton" name="buildButton" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>13</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="4" >
+ <widget class="QTreeView" name="paletteView" >
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>200</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" >
+ <widget class="QRadioButton" name="detailsRadio" >
+ <property name="text" >
+ <string>Show Details</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QRadioButton" name="computeRadio" >
+ <property name="text" >
+ <string>Compute Details</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Quick</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="GroupBox126" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Preview</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="2" >
+ <widget class="QRadioButton" name="disabledRadio" >
+ <property name="text" >
+ <string>Disabled</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QRadioButton" name="inactiveRadio" >
+ <property name="text" >
+ <string>Inactive</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QRadioButton" name="activeRadio" >
+ <property name="text" >
+ <string>Active</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3" >
+ <widget class="qdesigner_internal::PreviewFrame" native="1" name="previewFrame" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtColorButton</class>
+ <extends>QToolButton</extends>
+ <header>qtcolorbutton.h</header>
+ </customwidget>
+ <customwidget>
+ <class>qdesigner_internal::PreviewFrame</class>
+ <extends>QWidget</extends>
+ <header>previewframe.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>qdesigner_internal::PaletteEditor</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>180</x>
+ <y>331</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>134</x>
+ <y>341</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>qdesigner_internal::PaletteEditor</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>287</x>
+ <y>329</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>302</x>
+ <y>342</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/components/propertyeditor/paletteeditorbutton.cpp b/tools/designer/src/components/propertyeditor/paletteeditorbutton.cpp
new file mode 100644
index 0000000000..d7a76b9eee
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/paletteeditorbutton.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::PaletteEditorButton
+*/
+
+#include "paletteeditorbutton.h"
+#include "paletteeditor.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+PaletteEditorButton::PaletteEditorButton(QDesignerFormEditorInterface *core, const QPalette &palette, QWidget *parent)
+ : QToolButton(parent),
+ m_palette(palette)
+{
+ m_core = core;
+ setFocusPolicy(Qt::NoFocus);
+ setText(tr("Change Palette"));
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+
+ connect(this, SIGNAL(clicked()), this, SLOT(showPaletteEditor()));
+}
+
+PaletteEditorButton::~PaletteEditorButton()
+{
+}
+
+void PaletteEditorButton::setPalette(const QPalette &palette)
+{
+ m_palette = palette;
+}
+
+void PaletteEditorButton::setSuperPalette(const QPalette &palette)
+{
+ m_superPalette = palette;
+}
+
+void PaletteEditorButton::showPaletteEditor()
+{
+ int result;
+ QPalette p = QPalette();
+ QPalette pal = PaletteEditor::getPalette(m_core, 0, m_palette, m_superPalette, &result);
+ if (result == QDialog::Accepted) {
+ m_palette = pal;
+ emit paletteChanged(m_palette);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/paletteeditorbutton.h b/tools/designer/src/components/propertyeditor/paletteeditorbutton.h
new file mode 100644
index 0000000000..dea92219d0
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/paletteeditorbutton.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PALETTEEDITORBUTTON_H
+#define PALETTEEDITORBUTTON_H
+
+#include "propertyeditor_global.h"
+
+#include <QtGui/QPalette>
+#include <QtGui/QToolButton>
+
+#include "abstractformeditor.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QT_PROPERTYEDITOR_EXPORT PaletteEditorButton: public QToolButton
+{
+ Q_OBJECT
+public:
+ PaletteEditorButton(QDesignerFormEditorInterface *core, const QPalette &palette, QWidget *parent = 0);
+ virtual ~PaletteEditorButton();
+
+ void setSuperPalette(const QPalette &palette);
+ inline QPalette palette() const
+ { return m_palette; }
+
+signals:
+ void paletteChanged(const QPalette &palette);
+
+public slots:
+ void setPalette(const QPalette &palette);
+
+private slots:
+ void showPaletteEditor();
+
+private:
+ QPalette m_palette;
+ QPalette m_superPalette;
+ QDesignerFormEditorInterface *m_core;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PALETTEEDITORBUTTON_H
diff --git a/tools/designer/src/components/propertyeditor/previewframe.cpp b/tools/designer/src/components/propertyeditor/previewframe.cpp
new file mode 100644
index 0000000000..95d533d2f3
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/previewframe.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::PreviewWorkspace
+*/
+
+#include "previewframe.h"
+#include "previewwidget.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QPaintEvent>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ class PreviewMdiArea: public QMdiArea {
+ public:
+ PreviewMdiArea(QWidget *parent = 0) : QMdiArea(parent) {}
+ protected:
+ bool viewportEvent ( QEvent * event );
+ };
+
+ bool PreviewMdiArea::viewportEvent (QEvent * event) {
+ if (event->type() != QEvent::Paint)
+ return QMdiArea::viewportEvent (event);
+ QWidget *paintWidget = viewport();
+ QPainter p(paintWidget);
+ p.fillRect(rect(), paintWidget->palette().color(backgroundRole()).dark());
+ p.setPen(QPen(Qt::white));
+ p.drawText(0, height() / 2, width(), height(), Qt::AlignHCenter,
+ tr("The moose in the noose\nate the goose who was loose."));
+ return true;
+ }
+}
+
+namespace qdesigner_internal {
+
+PreviewFrame::PreviewFrame(QWidget *parent) :
+ QFrame(parent),
+ m_mdiArea(new PreviewMdiArea(this))
+{
+ m_mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ m_mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ setLineWidth(1);
+
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ vbox->setMargin(0);
+ vbox->addWidget(m_mdiArea);
+
+ setMinimumSize(ensureMdiSubWindow()->minimumSizeHint());
+}
+
+void PreviewFrame::setPreviewPalette(const QPalette &pal)
+{
+ ensureMdiSubWindow()->widget()->setPalette(pal);
+}
+
+void PreviewFrame::setSubWindowActive(bool active)
+{
+ m_mdiArea->setActiveSubWindow (active ? ensureMdiSubWindow() : static_cast<QMdiSubWindow *>(0));
+}
+
+QMdiSubWindow *PreviewFrame::ensureMdiSubWindow()
+{
+ if (!m_mdiSubWindow) {
+ PreviewWidget *previewWidget = new PreviewWidget(m_mdiArea);
+ m_mdiSubWindow = m_mdiArea->addSubWindow(previewWidget, Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
+ m_mdiSubWindow->move(10,10);
+ m_mdiSubWindow->showMaximized();
+ }
+
+ const Qt::WindowStates state = m_mdiSubWindow->windowState();
+ if (state & Qt::WindowMinimized)
+ m_mdiSubWindow->setWindowState(state & ~Qt::WindowMinimized);
+
+ return m_mdiSubWindow;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/previewframe.h b/tools/designer/src/components/propertyeditor/previewframe.h
new file mode 100644
index 0000000000..678a7ab54d
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/previewframe.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREVIEWFRAME_H
+#define PREVIEWFRAME_H
+
+#include <QtGui/QFrame>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QMdiArea;
+class QMdiSubWindow;
+
+namespace qdesigner_internal {
+
+class PreviewFrame: public QFrame
+{
+ Q_OBJECT
+public:
+ explicit PreviewFrame(QWidget *parent);
+
+ void setPreviewPalette(const QPalette &palette);
+ void setSubWindowActive(bool active);
+
+private:
+ // The user can on some platforms close the mdi child by invoking the system menu.
+ // Ensure a child is present.
+ QMdiSubWindow *ensureMdiSubWindow();
+ QMdiArea *m_mdiArea;
+ QPointer<QMdiSubWindow> m_mdiSubWindow;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/components/propertyeditor/previewwidget.cpp b/tools/designer/src/components/propertyeditor/previewwidget.cpp
new file mode 100644
index 0000000000..fa458e773e
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/previewwidget.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "previewwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+PreviewWidget::PreviewWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ ui.setupUi(this);
+}
+
+PreviewWidget::~PreviewWidget()
+{
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/previewwidget.h b/tools/designer/src/components/propertyeditor/previewwidget.h
new file mode 100644
index 0000000000..38690d5d37
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/previewwidget.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREVIEWWIDGET_H
+#define PREVIEWWIDGET_H
+
+#include "ui_previewwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class PreviewWidget: public QWidget
+{
+ Q_OBJECT
+public:
+ explicit PreviewWidget(QWidget *parent);
+ virtual ~PreviewWidget();
+
+private:
+ Ui::PreviewWidget ui;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PREVIEWWIDGET_H
diff --git a/tools/designer/src/components/propertyeditor/previewwidget.ui b/tools/designer/src/components/propertyeditor/previewwidget.ui
new file mode 100644
index 0000000000..c61f0d6305
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/previewwidget.ui
@@ -0,0 +1,238 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::PreviewWidget</class>
+ <widget class="QWidget" name="qdesigner_internal::PreviewWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>471</width>
+ <height>251</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle" >
+ <string>Preview Window</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="3" row="0" column="1" >
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="LineEdit1" >
+ <property name="text" >
+ <string>LineEdit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="ComboBox1" >
+ <item>
+ <property name="text" >
+ <string>ComboBox</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="SpinBox1" />
+ </item>
+ <item>
+ <widget class="QPushButton" name="PushButton1" >
+ <property name="text" >
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QScrollBar" name="ScrollBar1" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="Slider1" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listWidget" >
+ <property name="maximumSize" >
+ <size>
+ <width>32767</width>
+ <height>50</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="0" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QProgressBar" name="ProgressBar1" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QGroupBox" name="ButtonGroup2" >
+ <property name="title" >
+ <string>ButtonGroup2</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="CheckBox1" >
+ <property name="text" >
+ <string>CheckBox1</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="CheckBox2" >
+ <property name="text" >
+ <string>CheckBox2</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="ButtonGroup1" >
+ <property name="title" >
+ <string>ButtonGroup</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="RadioButton1" >
+ <property name="text" >
+ <string>RadioButton1</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="RadioButton2" >
+ <property name="text" >
+ <string>RadioButton2</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="RadioButton3" >
+ <property name="text" >
+ <string>RadioButton3</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.cpp b/tools/designer/src/components/propertyeditor/propertyeditor.cpp
new file mode 100644
index 0000000000..63b57d871b
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/propertyeditor.cpp
@@ -0,0 +1,1245 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "propertyeditor.h"
+
+#include "qttreepropertybrowser.h"
+#include "qtbuttonpropertybrowser.h"
+#include "qtvariantproperty.h"
+#include "designerpropertymanager.h"
+#include "qdesigner_propertysheet_p.h"
+#include "formwindowbase_p.h"
+#include "filterwidget_p.h" // For FilterWidget
+
+#include "newdynamicpropertydialog.h"
+#include "dynamicpropertysheet.h"
+#include "shared_enums_p.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/private/abstractsettings_p.h>
+// shared
+#include <qdesigner_utils_p.h>
+#include <qdesigner_propertycommand_p.h>
+#include <metadatabase_p.h>
+#include <iconloader_p.h>
+#ifdef Q_OS_WIN
+# include <widgetfactory_p.h>
+#endif
+#include <QtGui/QAction>
+#include <QtGui/QLineEdit>
+#include <QtGui/QMenu>
+#include <QtGui/QApplication>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QScrollArea>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QToolBar>
+#include <QtGui/QToolButton>
+#include <QtGui/QActionGroup>
+#include <QtGui/QLabel>
+
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+
+static const char *SettingsGroupC = "PropertyEditor";
+#if QT_VERSION >= 0x040500
+static const char *ViewKeyC = "View";
+#endif
+static const char *ColorKeyC = "Colored";
+static const char *SortedKeyC = "Sorted";
+static const char *ExpansionKeyC = "ExpandedItems";
+
+enum SettingsView { TreeView, ButtonView };
+
+QT_BEGIN_NAMESPACE
+
+// ---------------------------------------------------------------------------------
+
+namespace qdesigner_internal {
+// ----------- PropertyEditor::Strings
+
+PropertyEditor::Strings::Strings() :
+ m_fontProperty(QLatin1String("font")),
+ m_qLayoutWidget(QLatin1String("QLayoutWidget")),
+ m_designerPrefix(QLatin1String("QDesigner")),
+ m_layout(QLatin1String("Layout")),
+ m_validationModeAttribute(QLatin1String("validationMode")),
+ m_fontAttribute(QLatin1String("font")),
+ m_superPaletteAttribute(QLatin1String("superPalette")),
+ m_enumNamesAttribute(QLatin1String("enumNames")),
+ m_resettableAttribute(QLatin1String("resettable")),
+ m_flagsAttribute(QLatin1String("flags"))
+{
+ m_alignmentProperties.insert(QLatin1String("alignment"));
+ m_alignmentProperties.insert(QLatin1String("layoutLabelAlignment")); // QFormLayout
+ m_alignmentProperties.insert(QLatin1String("layoutFormAlignment"));
+}
+
+// ----------- PropertyEditor
+
+QDesignerMetaDataBaseItemInterface* PropertyEditor::metaDataBaseItem() const
+{
+ QObject *o = object();
+ if (!o)
+ return 0;
+ QDesignerMetaDataBaseInterface *db = core()->metaDataBase();
+ if (!db)
+ return 0;
+ return db->item(o);
+}
+
+void PropertyEditor::setupStringProperty(QtVariantProperty *property, bool isMainContainer)
+{
+ const StringPropertyParameters params = textPropertyValidationMode(core(), m_object, property->propertyName(), isMainContainer);
+ // Does a meta DB entry exist - add comment
+ const bool hasComment = params.second;
+ property->setAttribute(m_strings.m_validationModeAttribute, params.first);
+ // assuming comment cannot appear or disappear for the same property in different object instance
+ if (!hasComment) {
+ QList<QtProperty *> commentProperties = property->subProperties();
+ if (commentProperties.count() > 0)
+ delete commentProperties.at(0);
+ if (commentProperties.count() > 1)
+ delete commentProperties.at(1);
+ }
+}
+
+void PropertyEditor::setupPaletteProperty(QtVariantProperty *property)
+{
+ QPalette value = qvariant_cast<QPalette>(property->value());
+ QPalette superPalette = QPalette();
+ QWidget *currentWidget = qobject_cast<QWidget *>(m_object);
+ if (currentWidget) {
+ if (currentWidget->isWindow())
+ superPalette = QApplication::palette(currentWidget);
+ else {
+ if (currentWidget->parentWidget())
+ superPalette = currentWidget->parentWidget()->palette();
+ }
+ }
+ m_updatingBrowser = true;
+ property->setAttribute(m_strings.m_superPaletteAttribute, superPalette);
+ m_updatingBrowser = false;
+}
+
+static inline QToolButton *createDropDownButton(QAction *defaultAction, QWidget *parent = 0)
+{
+ QToolButton *rc = new QToolButton(parent);
+ rc->setDefaultAction(defaultAction);
+ rc->setPopupMode(QToolButton::InstantPopup);
+ return rc;
+}
+
+PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags) :
+ QDesignerPropertyEditor(parent, flags),
+ m_core(core),
+ m_propertySheet(0),
+ m_currentBrowser(0),
+ m_treeBrowser(0),
+ m_propertyManager(new DesignerPropertyManager(m_core, this)),
+ m_dynamicGroup(0),
+ m_updatingBrowser(false),
+ m_stackedWidget(new QStackedWidget),
+ m_filterWidget(new FilterWidget(0, FilterWidget::LayoutAlignNone)),
+ m_buttonIndex(-1),
+ m_treeIndex(-1),
+ m_addDynamicAction(new QAction(createIconSet(QLatin1String("plus.png")), tr("Add Dynamic Property..."), this)),
+ m_removeDynamicAction(new QAction(createIconSet(QLatin1String("minus.png")), tr("Remove Dynamic Property"), this)),
+ m_sortingAction(new QAction(createIconSet(QLatin1String("sort.png")), tr("Sorting"), this)),
+ m_coloringAction(new QAction(createIconSet(QLatin1String("color.png")), tr("Color Groups"), this)),
+ m_treeAction(new QAction(tr("Tree View"), this)),
+ m_buttonAction(new QAction(tr("Drop Down Button View"), this)),
+ m_classLabel(new QLabel),
+ m_sorting(false),
+ m_coloring(false),
+ m_brightness(false)
+{
+ QVector<QColor> colors;
+ colors.reserve(6);
+ colors.push_back(QColor(255, 230, 191));
+ colors.push_back(QColor(255, 255, 191));
+ colors.push_back(QColor(191, 255, 191));
+ colors.push_back(QColor(199, 255, 255));
+ colors.push_back(QColor(234, 191, 255));
+ colors.push_back(QColor(255, 191, 239));
+ m_colors.reserve(colors.count());
+ for (int i = 0; i < colors.count(); i++) {
+ QColor c = colors.at(i);
+ m_colors.push_back(qMakePair(c, c.darker(150)));
+ }
+ QColor dynamicColor(191, 207, 255);
+ QColor layoutColor(255, 191, 191);
+ m_dynamicColor = qMakePair(dynamicColor, dynamicColor.darker(150));
+ m_layoutColor = qMakePair(layoutColor, layoutColor.darker(150));
+
+ updateForegroundBrightness();
+
+ QActionGroup *actionGroup = new QActionGroup(this);
+
+ m_treeAction->setCheckable(true);
+ m_treeAction->setIcon(createIconSet(QLatin1String("widgets/listview.png")));
+ m_buttonAction->setCheckable(true);
+ m_buttonAction->setIcon(createIconSet(QLatin1String("dropdownbutton.png")));
+
+ actionGroup->addAction(m_treeAction);
+ actionGroup->addAction(m_buttonAction);
+ connect(actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotViewTriggered(QAction*)));
+
+ QWidget *classWidget = new QWidget;
+ QHBoxLayout *l = new QHBoxLayout(classWidget);
+ l->setContentsMargins(5, 0, 5, 0);
+ l->addWidget(m_classLabel);
+
+ // Add actions
+ QActionGroup *addDynamicActionGroup = new QActionGroup(this);
+ connect(addDynamicActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotAddDynamicProperty(QAction*)));
+
+ QMenu *addDynamicActionMenu = new QMenu(this);
+ m_addDynamicAction->setMenu(addDynamicActionMenu);
+ m_addDynamicAction->setEnabled(false);
+ QAction *addDynamicAction = addDynamicActionGroup->addAction(tr("String..."));
+ addDynamicAction->setData(static_cast<int>(QVariant::String));
+ addDynamicActionMenu->addAction(addDynamicAction);
+ addDynamicAction = addDynamicActionGroup->addAction(tr("Bool..."));
+ addDynamicAction->setData(static_cast<int>(QVariant::Bool));
+ addDynamicActionMenu->addAction(addDynamicAction);
+ addDynamicActionMenu->addSeparator();
+ addDynamicAction = addDynamicActionGroup->addAction(tr("Other..."));
+ addDynamicAction->setData(static_cast<int>(QVariant::Invalid));
+ addDynamicActionMenu->addAction(addDynamicAction);
+ // remove
+ m_removeDynamicAction->setEnabled(false);
+ connect(m_removeDynamicAction, SIGNAL(triggered()), this, SLOT(slotRemoveDynamicProperty()));
+ // Configure
+ QAction *configureAction = new QAction(tr("Configure Property Editor"), this);
+ configureAction->setIcon(createIconSet(QLatin1String("configure.png")));
+ QMenu *configureMenu = new QMenu(this);
+ configureAction->setMenu(configureMenu);
+
+ m_sortingAction->setCheckable(true);
+ connect(m_sortingAction, SIGNAL(toggled(bool)), this, SLOT(slotSorting(bool)));
+
+ m_coloringAction->setCheckable(true);
+ connect(m_coloringAction, SIGNAL(toggled(bool)), this, SLOT(slotColoring(bool)));
+
+ configureMenu->addAction(m_sortingAction);
+ configureMenu->addAction(m_coloringAction);
+#if QT_VERSION >= 0x040600
+ configureMenu->addSeparator();
+ configureMenu->addAction(m_treeAction);
+ configureMenu->addAction(m_buttonAction);
+#endif
+ // Assemble toolbar
+ QToolBar *toolBar = new QToolBar;
+ toolBar->addWidget(classWidget);
+ toolBar->addWidget(m_filterWidget);
+ toolBar->addWidget(createDropDownButton(m_addDynamicAction));
+ toolBar->addAction(m_removeDynamicAction);
+ toolBar->addWidget(createDropDownButton(configureAction));
+ // Views
+ QScrollArea *buttonScroll = new QScrollArea(m_stackedWidget);
+ m_buttonBrowser = new QtButtonPropertyBrowser(buttonScroll);
+ buttonScroll->setWidgetResizable(true);
+ buttonScroll->setWidget(m_buttonBrowser);
+ m_buttonIndex = m_stackedWidget->addWidget(buttonScroll);
+ connect(m_buttonBrowser, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentItemChanged(QtBrowserItem*)));
+
+ m_treeBrowser = new QtTreePropertyBrowser(m_stackedWidget);
+ m_treeBrowser->setRootIsDecorated(false);
+ m_treeBrowser->setPropertiesWithoutValueMarked(true);
+ m_treeBrowser->setResizeMode(QtTreePropertyBrowser::Interactive);
+ m_treeIndex = m_stackedWidget->addWidget(m_treeBrowser);
+ connect(m_treeBrowser, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentItemChanged(QtBrowserItem*)));
+ connect(m_filterWidget, SIGNAL(filterChanged(QString)), this, SLOT(setFilter(QString)));
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(toolBar);
+ layout->addWidget(m_stackedWidget);
+ layout->setMargin(0);
+ layout->setSpacing(0);
+
+ m_treeFactory = new DesignerEditorFactory(m_core, this);
+ m_treeFactory->setSpacing(0);
+ m_groupFactory = new DesignerEditorFactory(m_core, this);
+ QtVariantPropertyManager *variantManager = m_propertyManager;
+ m_buttonBrowser->setFactoryForManager(variantManager, m_groupFactory);
+ m_treeBrowser->setFactoryForManager(variantManager, m_treeFactory);
+
+ m_stackedWidget->setCurrentIndex(m_treeIndex);
+ m_currentBrowser = m_treeBrowser;
+ m_treeAction->setChecked(true);
+
+ connect(m_groupFactory, SIGNAL(resetProperty(QtProperty*)), this, SLOT(slotResetProperty(QtProperty*)));
+ connect(m_treeFactory, SIGNAL(resetProperty(QtProperty*)), this, SLOT(slotResetProperty(QtProperty*)));
+ connect(variantManager, SIGNAL(valueChanged(QtProperty*,QVariant,bool)), this, SLOT(slotValueChanged(QtProperty*,QVariant,bool)));
+
+ // retrieve initial settings
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(SettingsGroupC));
+#if QT_VERSION >= 0x040500
+ const SettingsView view = settings->value(QLatin1String(ViewKeyC), TreeView).toInt() == TreeView ? TreeView : ButtonView;
+#endif
+ // Coloring not available unless treeview and not sorted
+ m_sorting = settings->value(QLatin1String(SortedKeyC), false).toBool();
+ m_coloring = settings->value(QLatin1String(ColorKeyC), true).toBool();
+ const QVariantMap expansionState = settings->value(QLatin1String(ExpansionKeyC), QVariantMap()).toMap();
+ settings->endGroup();
+ // Apply settings
+ m_sortingAction->setChecked(m_sorting);
+ m_coloringAction->setChecked(m_coloring);
+#if QT_VERSION >= 0x040500
+ switch (view) {
+ case TreeView:
+ m_currentBrowser = m_treeBrowser;
+ m_stackedWidget->setCurrentIndex(m_treeIndex);
+ m_treeAction->setChecked(true);
+ break;
+ case ButtonView:
+ m_currentBrowser = m_buttonBrowser;
+ m_stackedWidget->setCurrentIndex(m_buttonIndex);
+ m_buttonAction->setChecked(true);
+ break;
+ }
+#endif
+ // Restore expansionState from QVariant map
+ if (!expansionState.empty()) {
+ const QVariantMap::const_iterator cend = expansionState.constEnd();
+ for (QVariantMap::const_iterator it = expansionState.constBegin(); it != cend; ++it)
+ m_expansionState.insert(it.key(), it.value().toBool());
+ }
+ updateActionsState();
+}
+
+PropertyEditor::~PropertyEditor()
+{
+ storeExpansionState();
+ saveSettings();
+}
+
+void PropertyEditor::saveSettings() const
+{
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(SettingsGroupC));
+#if QT_VERSION >= 0x040500
+ settings->setValue(QLatin1String(ViewKeyC), QVariant(m_treeAction->isChecked() ? TreeView : ButtonView));
+#endif
+ settings->setValue(QLatin1String(ColorKeyC), QVariant(m_coloring));
+ settings->setValue(QLatin1String(SortedKeyC), QVariant(m_sorting));
+ // Save last expansionState as QVariant map
+ QVariantMap expansionState;
+ if (!m_expansionState.empty()) {
+ const QMap<QString, bool>::const_iterator cend = m_expansionState.constEnd();
+ for (QMap<QString, bool>::const_iterator it = m_expansionState.constBegin(); it != cend; ++it)
+ expansionState.insert(it.key(), QVariant(it.value()));
+ }
+ settings->setValue(QLatin1String(ExpansionKeyC), expansionState);
+ settings->endGroup();
+}
+
+void PropertyEditor::setExpanded(QtBrowserItem *item, bool expanded)
+{
+ if (m_buttonBrowser == m_currentBrowser)
+ m_buttonBrowser->setExpanded(item, expanded);
+ else if (m_treeBrowser == m_currentBrowser)
+ m_treeBrowser->setExpanded(item, expanded);
+}
+
+bool PropertyEditor::isExpanded(QtBrowserItem *item) const
+{
+ if (m_buttonBrowser == m_currentBrowser)
+ return m_buttonBrowser->isExpanded(item);
+ else if (m_treeBrowser == m_currentBrowser)
+ return m_treeBrowser->isExpanded(item);
+ return false;
+}
+
+void PropertyEditor::setItemVisible(QtBrowserItem *item, bool visible)
+{
+ if (m_currentBrowser == m_treeBrowser) {
+ m_treeBrowser->setItemVisible(item, visible);
+ } else {
+ qWarning("** WARNING %s is not implemented for this browser.", Q_FUNC_INFO);
+ }
+}
+
+bool PropertyEditor::isItemVisible(QtBrowserItem *item) const
+{
+ return m_currentBrowser == m_treeBrowser ? m_treeBrowser->isItemVisible(item) : true;
+}
+
+/* Default handling of items not found in the map:
+ * - Top-level items (classes) are assumed to be expanded
+ * - Anything below (properties) is assumed to be collapsed
+ * That is, the map is required, the state cannot be stored in a set */
+
+void PropertyEditor::storePropertiesExpansionState(const QList<QtBrowserItem *> &items)
+{
+ const QChar bar = QLatin1Char('|');
+ QListIterator<QtBrowserItem *> itProperty(items);
+ while (itProperty.hasNext()) {
+ QtBrowserItem *propertyItem = itProperty.next();
+ if (!propertyItem->children().empty()) {
+ QtProperty *property = propertyItem->property();
+ const QString propertyName = property->propertyName();
+ const QMap<QtProperty *, QString>::const_iterator itGroup = m_propertyToGroup.constFind(property);
+ if (itGroup != m_propertyToGroup.constEnd()) {
+ QString key = itGroup.value();
+ key += bar;
+ key += propertyName;
+ m_expansionState[key] = isExpanded(propertyItem);
+ }
+ }
+ }
+}
+
+void PropertyEditor::storeExpansionState()
+{
+ const QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems();
+ if (m_sorting) {
+ storePropertiesExpansionState(items);
+ } else {
+ QListIterator<QtBrowserItem *> itGroup(items);
+ while (itGroup.hasNext()) {
+ QtBrowserItem *item = itGroup.next();
+ const QString groupName = item->property()->propertyName();
+ QList<QtBrowserItem *> propertyItems = item->children();
+ if (!propertyItems.empty())
+ m_expansionState[groupName] = isExpanded(item);
+
+ // properties stuff here
+ storePropertiesExpansionState(propertyItems);
+ }
+ }
+}
+
+void PropertyEditor::collapseAll()
+{
+ QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems();
+ QListIterator<QtBrowserItem *> itGroup(items);
+ while (itGroup.hasNext())
+ setExpanded(itGroup.next(), false);
+}
+
+void PropertyEditor::applyPropertiesExpansionState(const QList<QtBrowserItem *> &items)
+{
+ const QChar bar = QLatin1Char('|');
+ QListIterator<QtBrowserItem *> itProperty(items);
+ while (itProperty.hasNext()) {
+ const QMap<QString, bool>::const_iterator excend = m_expansionState.constEnd();
+ QtBrowserItem *propertyItem = itProperty.next();
+ QtProperty *property = propertyItem->property();
+ const QString propertyName = property->propertyName();
+ const QMap<QtProperty *, QString>::const_iterator itGroup = m_propertyToGroup.constFind(property);
+ if (itGroup != m_propertyToGroup.constEnd()) {
+ QString key = itGroup.value();
+ key += bar;
+ key += propertyName;
+ const QMap<QString, bool>::const_iterator pit = m_expansionState.constFind(key);
+ if (pit != excend)
+ setExpanded(propertyItem, pit.value());
+ else
+ setExpanded(propertyItem, false);
+ }
+ }
+}
+
+void PropertyEditor::applyExpansionState()
+{
+ const QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems();
+ if (m_sorting) {
+ applyPropertiesExpansionState(items);
+ } else {
+ QListIterator<QtBrowserItem *> itTopLevel(items);
+ const QMap<QString, bool>::const_iterator excend = m_expansionState.constEnd();
+ while (itTopLevel.hasNext()) {
+ QtBrowserItem *item = itTopLevel.next();
+ const QString groupName = item->property()->propertyName();
+ const QMap<QString, bool>::const_iterator git = m_expansionState.constFind(groupName);
+ if (git != excend)
+ setExpanded(item, git.value());
+ else
+ setExpanded(item, true);
+ // properties stuff here
+ applyPropertiesExpansionState(item->children());
+ }
+ }
+}
+
+int PropertyEditor::applyPropertiesFilter(const QList<QtBrowserItem *> &items)
+{
+ int showCount = 0;
+ const bool matchAll = m_filterPattern.isEmpty();
+ QListIterator<QtBrowserItem *> itProperty(items);
+ while (itProperty.hasNext()) {
+ QtBrowserItem *propertyItem = itProperty.next();
+ QtProperty *property = propertyItem->property();
+ const QString propertyName = property->propertyName();
+ const bool showProperty = matchAll || propertyName.contains(m_filterPattern, Qt::CaseInsensitive);
+ setItemVisible(propertyItem, showProperty);
+ if (showProperty)
+ showCount++;
+ }
+ return showCount;
+}
+
+void PropertyEditor::applyFilter()
+{
+ const QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems();
+ if (m_sorting) {
+ applyPropertiesFilter(items);
+ } else {
+ QListIterator<QtBrowserItem *> itTopLevel(items);
+ while (itTopLevel.hasNext()) {
+ QtBrowserItem *item = itTopLevel.next();
+ setItemVisible(item, applyPropertiesFilter(item->children()));
+ }
+ }
+}
+
+void PropertyEditor::clearView()
+{
+ m_currentBrowser->clear();
+}
+
+bool PropertyEditor::event(QEvent *event)
+{
+ if (event->type() == QEvent::PaletteChange)
+ updateForegroundBrightness();
+
+ return QDesignerPropertyEditor::event(event);
+}
+
+void PropertyEditor::updateForegroundBrightness()
+{
+ QColor c = palette().color(QPalette::Text);
+ bool newBrightness = qRound(0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF());
+
+ if (m_brightness == newBrightness)
+ return;
+
+ m_brightness = newBrightness;
+
+ updateColors();
+}
+
+QColor PropertyEditor::propertyColor(QtProperty *property) const
+{
+ if (!m_coloring)
+ return QColor();
+
+ QtProperty *groupProperty = property;
+
+ QMap<QtProperty *, QString>::ConstIterator itProp = m_propertyToGroup.constFind(property);
+ if (itProp != m_propertyToGroup.constEnd())
+ groupProperty = m_nameToGroup.value(itProp.value());
+
+ const int groupIdx = m_groups.indexOf(groupProperty);
+ QPair<QColor, QColor> pair;
+ if (groupIdx != -1) {
+ if (groupProperty == m_dynamicGroup)
+ pair = m_dynamicColor;
+ else if (isLayoutGroup(groupProperty))
+ pair = m_layoutColor;
+ else
+ pair = m_colors[groupIdx % m_colors.count()];
+ }
+ if (!m_brightness)
+ return pair.first;
+ return pair.second;
+}
+
+void PropertyEditor::fillView()
+{
+ if (m_sorting) {
+ QMapIterator<QString, QtVariantProperty *> itProperty(m_nameToProperty);
+ while (itProperty.hasNext()) {
+ QtVariantProperty *property = itProperty.next().value();
+ m_currentBrowser->addProperty(property);
+ }
+ } else {
+ QListIterator<QtProperty *> itGroup(m_groups);
+ while (itGroup.hasNext()) {
+ QtProperty *group = itGroup.next();
+ QtBrowserItem *item = m_currentBrowser->addProperty(group);
+ if (m_currentBrowser == m_treeBrowser)
+ m_treeBrowser->setBackgroundColor(item, propertyColor(group));
+ group->setModified(m_currentBrowser == m_treeBrowser);
+ }
+ }
+}
+
+bool PropertyEditor::isLayoutGroup(QtProperty *group) const
+{
+ return group->propertyName() == m_strings.m_layout;
+}
+
+void PropertyEditor::updateActionsState()
+{
+ m_coloringAction->setEnabled(m_treeAction->isChecked() && !m_sortingAction->isChecked());
+}
+
+void PropertyEditor::slotViewTriggered(QAction *action)
+{
+ storeExpansionState();
+ collapseAll();
+ {
+ UpdateBlocker ub(this);
+ clearView();
+ int idx = 0;
+ if (action == m_treeAction) {
+ m_currentBrowser = m_treeBrowser;
+ idx = m_treeIndex;
+ } else if (action == m_buttonAction) {
+ m_currentBrowser = m_buttonBrowser;
+ idx = m_buttonIndex;
+ }
+ fillView();
+ m_stackedWidget->setCurrentIndex(idx);
+ applyExpansionState();
+ applyFilter();
+ }
+ updateActionsState();
+}
+
+void PropertyEditor::slotSorting(bool sort)
+{
+ if (sort == m_sorting)
+ return;
+
+ storeExpansionState();
+ m_sorting = sort;
+ collapseAll();
+ {
+ UpdateBlocker ub(this);
+ clearView();
+ m_treeBrowser->setRootIsDecorated(sort);
+ fillView();
+ applyExpansionState();
+ applyFilter();
+ }
+ updateActionsState();
+}
+
+void PropertyEditor::updateColors()
+{
+ if (m_treeBrowser && m_currentBrowser == m_treeBrowser) {
+ QList<QtBrowserItem *> items = m_treeBrowser->topLevelItems();
+ QListIterator<QtBrowserItem *> itItem(items);
+ while (itItem.hasNext()) {
+ QtBrowserItem *item = itItem.next();
+ m_treeBrowser->setBackgroundColor(item, propertyColor(item->property()));
+ }
+ }
+}
+
+void PropertyEditor::slotColoring(bool coloring)
+{
+ if (coloring == m_coloring)
+ return;
+
+ m_coloring = coloring;
+
+ updateColors();
+}
+
+void PropertyEditor::slotAddDynamicProperty(QAction *action)
+{
+ if (!m_propertySheet)
+ return;
+
+ const QDesignerDynamicPropertySheetExtension *dynamicSheet =
+ qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object);
+
+ if (!dynamicSheet)
+ return;
+
+ QString newName;
+ QVariant newValue;
+ { // Make sure the dialog is closed before the signal is emitted.
+ const QVariant::Type type = static_cast<QVariant::Type>(action->data().toInt());
+ NewDynamicPropertyDialog dlg(core()->dialogGui(), m_currentBrowser);
+ if (type != QVariant::Invalid)
+ dlg.setPropertyType(type);
+
+ QStringList reservedNames;
+ const int propertyCount = m_propertySheet->count();
+ for (int i = 0; i < propertyCount; i++) {
+ if (!dynamicSheet->isDynamicProperty(i) || m_propertySheet->isVisible(i))
+ reservedNames.append(m_propertySheet->propertyName(i));
+ }
+ dlg.setReservedNames(reservedNames);
+ if (dlg.exec() == QDialog::Rejected)
+ return;
+ newName = dlg.propertyName();
+ newValue = dlg.propertyValue();
+ }
+ m_recentlyAddedDynamicProperty = newName;
+ emit addDynamicProperty(newName, newValue);
+}
+
+QDesignerFormEditorInterface *PropertyEditor::core() const
+{
+ return m_core;
+}
+
+bool PropertyEditor::isReadOnly() const
+{
+ return false;
+}
+
+void PropertyEditor::setReadOnly(bool /*readOnly*/)
+{
+ qDebug() << "PropertyEditor::setReadOnly() request";
+}
+
+void PropertyEditor::setPropertyValue(const QString &name, const QVariant &value, bool changed)
+{
+ const QMap<QString, QtVariantProperty*>::const_iterator it = m_nameToProperty.constFind(name);
+ if (it == m_nameToProperty.constEnd())
+ return;
+ QtVariantProperty *property = it.value();
+ updateBrowserValue(property, value);
+ property->setModified(changed);
+}
+
+/* Quick update that assumes the actual count of properties has not changed
+ * N/A when for example executing a layout command and margin properties appear. */
+void PropertyEditor::updatePropertySheet()
+{
+ if (!m_propertySheet)
+ return;
+
+ updateToolBarLabel();
+
+ const int propertyCount = m_propertySheet->count();
+ const QMap<QString, QtVariantProperty*>::const_iterator npcend = m_nameToProperty.constEnd();
+ for (int i = 0; i < propertyCount; ++i) {
+ const QString propertyName = m_propertySheet->propertyName(i);
+ QMap<QString, QtVariantProperty*>::const_iterator it = m_nameToProperty.constFind(propertyName);
+ if (it != npcend)
+ updateBrowserValue(it.value(), m_propertySheet->property(i));
+ }
+}
+
+static inline QLayout *layoutOfQLayoutWidget(QObject *o)
+{
+ if (o->isWidgetType() && !qstrcmp(o->metaObject()->className(), "QLayoutWidget"))
+ return static_cast<QWidget*>(o)->layout();
+ return 0;
+}
+
+void PropertyEditor::updateToolBarLabel()
+{
+ QString objectName;
+ QString className;
+ if (m_object) {
+ if (QLayout *l = layoutOfQLayoutWidget(m_object))
+ objectName = l->objectName();
+ else
+ objectName = m_object->objectName();
+ className = realClassName(m_object);
+ }
+
+ QString classLabelText = objectName;
+ classLabelText += QLatin1Char('\n');
+ classLabelText += className;
+ m_classLabel->setText(classLabelText);
+ m_classLabel->setToolTip(tr("Object: %1\nClass: %2").arg(objectName).arg(className));
+}
+
+void PropertyEditor::updateBrowserValue(QtVariantProperty *property, const QVariant &value)
+{
+ QVariant v = value;
+ const int type = property->propertyType();
+ if (type == QtVariantPropertyManager::enumTypeId()) {
+ const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(v);
+ v = e.metaEnum.keys().indexOf(e.metaEnum.valueToKey(e.value));
+ } else if (type == DesignerPropertyManager::designerFlagTypeId()) {
+ const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(v);
+ v = QVariant(f.value);
+ } else if (type == DesignerPropertyManager::designerAlignmentTypeId()) {
+ const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(v);
+ v = QVariant(f.value);
+ }
+ QDesignerPropertySheet *sheet = qobject_cast<QDesignerPropertySheet*>(m_core->extensionManager()->extension(m_object, Q_TYPEID(QDesignerPropertySheetExtension)));
+ int index = -1;
+ if (sheet)
+ index = sheet->indexOf(property->propertyName());
+ if (sheet && m_propertyToGroup.contains(property)) { // don't do it for comments since property sheet doesn't keep them
+ property->setEnabled(sheet->isEnabled(index));
+ }
+
+ // Rich text string property with comment: Store/Update the font the rich text editor dialog starts out with
+ if (type == QVariant::String && !property->subProperties().empty()) {
+ const int fontIndex = m_propertySheet->indexOf(m_strings.m_fontProperty);
+ if (fontIndex != -1)
+ property->setAttribute(m_strings.m_fontAttribute, m_propertySheet->property(fontIndex));
+ }
+
+ m_updatingBrowser = true;
+ property->setValue(v);
+ if (sheet && sheet->isResourceProperty(index))
+ property->setAttribute(QLatin1String("defaultResource"), sheet->defaultResourceProperty(index));
+ m_updatingBrowser = false;
+}
+
+int PropertyEditor::toBrowserType(const QVariant &value, const QString &propertyName) const
+{
+ if (qVariantCanConvert<PropertySheetFlagValue>(value)) {
+ if (m_strings.m_alignmentProperties.contains(propertyName))
+ return DesignerPropertyManager::designerAlignmentTypeId();
+ return DesignerPropertyManager::designerFlagTypeId();
+ }
+ if (qVariantCanConvert<PropertySheetEnumValue>(value))
+ return DesignerPropertyManager::enumTypeId();
+
+ return value.userType();
+}
+
+QString PropertyEditor::realClassName(QObject *object) const
+{
+ if (!object)
+ return QString();
+
+ QString className = QLatin1String(object->metaObject()->className());
+ const QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase();
+ if (QDesignerWidgetDataBaseItemInterface *widgetItem = db->item(db->indexOfObject(object, true))) {
+ className = widgetItem->name();
+
+ if (object->isWidgetType() && className == m_strings.m_qLayoutWidget
+ && static_cast<QWidget*>(object)->layout()) {
+ className = QLatin1String(static_cast<QWidget*>(object)->layout()->metaObject()->className());
+ }
+ }
+
+ if (className.startsWith(m_strings.m_designerPrefix))
+ className.remove(1, m_strings.m_designerPrefix.size() - 1);
+
+ return className;
+}
+
+static QString msgUnsupportedType(const QString &propertyName, unsigned type)
+{
+ QString rc;
+ QTextStream str(&rc);
+ str << "The property \"" << propertyName << "\" of type " << type;
+ if (type == QVariant::Invalid) {
+ str << " (invalid) ";
+ } else {
+ if (type < QVariant::UserType) {
+ if (const char *typeName = QVariant::typeToName(static_cast<QVariant::Type>(type)))
+ str << " (" << typeName << ") ";
+ } else {
+ str << " (user type) ";
+ }
+ }
+ str << " is not supported yet!";
+ return rc;
+}
+
+void PropertyEditor::setObject(QObject *object)
+{
+ QDesignerFormWindowInterface *oldFormWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
+ // In the first setObject() call following the addition of a dynamic property, focus and edit it.
+ const bool editNewDynamicProperty = object != 0 && m_object == object && !m_recentlyAddedDynamicProperty.isEmpty();
+ m_object = object;
+ m_propertyManager->setObject(object);
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
+ FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow);
+ m_treeFactory->setFormWindowBase(fwb);
+ m_groupFactory->setFormWindowBase(fwb);
+
+ storeExpansionState();
+
+ UpdateBlocker ub(this);
+
+ updateToolBarLabel();
+
+ QMap<QString, QtVariantProperty *> toRemove = m_nameToProperty;
+
+ const QDesignerDynamicPropertySheetExtension *dynamicSheet =
+ qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object);
+ const QDesignerPropertySheet *sheet = qobject_cast<QDesignerPropertySheet*>(m_core->extensionManager()->extension(m_object, Q_TYPEID(QDesignerPropertySheetExtension)));
+
+ // Optimizization: Instead of rebuilding the complete list every time, compile a list of properties to remove,
+ // remove them, traverse the sheet, in case property exists just set a value, otherwise - create it.
+ QExtensionManager *m = m_core->extensionManager();
+
+ m_propertySheet = qobject_cast<QDesignerPropertySheetExtension*>(m->extension(object, Q_TYPEID(QDesignerPropertySheetExtension)));
+ if (m_propertySheet) {
+ const int propertyCount = m_propertySheet->count();
+ for (int i = 0; i < propertyCount; ++i) {
+ if (!m_propertySheet->isVisible(i))
+ continue;
+
+ const QString propertyName = m_propertySheet->propertyName(i);
+ if (m_propertySheet->indexOf(propertyName) != i)
+ continue;
+ const QString groupName = m_propertySheet->propertyGroup(i);
+ const QMap<QString, QtVariantProperty *>::const_iterator rit = toRemove.constFind(propertyName);
+ if (rit != toRemove.constEnd()) {
+ QtVariantProperty *property = rit.value();
+ if (m_propertyToGroup.value(property) == groupName && toBrowserType(m_propertySheet->property(i), propertyName) == property->propertyType())
+ toRemove.remove(propertyName);
+ }
+ }
+ }
+
+ QMapIterator<QString, QtVariantProperty *> itRemove(toRemove);
+ while (itRemove.hasNext()) {
+ itRemove.next();
+
+ QtVariantProperty *property = itRemove.value();
+ m_nameToProperty.remove(itRemove.key());
+ m_propertyToGroup.remove(property);
+ delete property;
+ }
+
+ if (oldFormWindow != formWindow)
+ reloadResourceProperties();
+
+ bool isMainContainer = false;
+ if (QWidget *widget = qobject_cast<QWidget*>(object)) {
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(widget)) {
+ isMainContainer = (fw->mainContainer() == widget);
+ }
+ }
+ m_groups.clear();
+
+ if (m_propertySheet) {
+ QtProperty *lastProperty = 0;
+ QtProperty *lastGroup = 0;
+ const int propertyCount = m_propertySheet->count();
+ for (int i = 0; i < propertyCount; ++i) {
+ if (!m_propertySheet->isVisible(i))
+ continue;
+
+ const QString propertyName = m_propertySheet->propertyName(i);
+ if (m_propertySheet->indexOf(propertyName) != i)
+ continue;
+ const QVariant value = m_propertySheet->property(i);
+
+ const int type = toBrowserType(value, propertyName);
+
+ QtVariantProperty *property = m_nameToProperty.value(propertyName, 0);
+ bool newProperty = property == 0;
+ if (newProperty) {
+ property = m_propertyManager->addProperty(type, propertyName);
+ if (property) {
+ newProperty = true;
+ if (type == DesignerPropertyManager::enumTypeId()) {
+ const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(value);
+ QStringList names;
+ QStringListIterator it(e.metaEnum.keys());
+ while (it.hasNext())
+ names.append(it.next());
+ m_updatingBrowser = true;
+ property->setAttribute(m_strings.m_enumNamesAttribute, names);
+ m_updatingBrowser = false;
+ } else if (type == DesignerPropertyManager::designerFlagTypeId()) {
+ const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(value);
+ QList<QPair<QString, uint> > flags;
+ QStringListIterator it(f.metaFlags.keys());
+ while (it.hasNext()) {
+ const QString name = it.next();
+ const uint val = f.metaFlags.keyToValue(name);
+ flags.append(qMakePair(name, val));
+ }
+ m_updatingBrowser = true;
+ QVariant v;
+ qVariantSetValue(v, flags);
+ property->setAttribute(m_strings.m_flagsAttribute, v);
+ m_updatingBrowser = false;
+ }
+ }
+ }
+
+ if (property != 0) {
+ const bool dynamicProperty = (dynamicSheet && dynamicSheet->isDynamicProperty(i))
+ || (sheet && sheet->isDefaultDynamicProperty(i));
+ switch (type) {
+ case QVariant::Palette:
+ setupPaletteProperty(property);
+ break;
+ case QVariant::KeySequence:
+ //addCommentProperty(property, propertyName);
+ break;
+ default:
+ break;
+ }
+ if (type == QVariant::String || type == qMetaTypeId<PropertySheetStringValue>())
+ setupStringProperty(property, isMainContainer);
+ property->setAttribute(m_strings.m_resettableAttribute, m_propertySheet->hasReset(i));
+
+ const QString groupName = m_propertySheet->propertyGroup(i);
+ QtVariantProperty *groupProperty = 0;
+
+ if (newProperty) {
+ QMap<QString, QtVariantProperty*>::const_iterator itPrev = m_nameToProperty.insert(propertyName, property);
+ m_propertyToGroup[property] = groupName;
+ if (m_sorting) {
+ QtProperty *previous = 0;
+ if (itPrev != m_nameToProperty.constBegin())
+ previous = (--itPrev).value();
+ m_currentBrowser->insertProperty(property, previous);
+ }
+ }
+ const QMap<QString, QtVariantProperty*>::const_iterator gnit = m_nameToGroup.constFind(groupName);
+ if (gnit != m_nameToGroup.constEnd()) {
+ groupProperty = gnit.value();
+ } else {
+ groupProperty = m_propertyManager->addProperty(QtVariantPropertyManager::groupTypeId(), groupName);
+ QtBrowserItem *item = 0;
+ if (!m_sorting)
+ item = m_currentBrowser->insertProperty(groupProperty, lastGroup);
+ m_nameToGroup[groupName] = groupProperty;
+ m_groups.append(groupProperty);
+ if (dynamicProperty)
+ m_dynamicGroup = groupProperty;
+ if (m_currentBrowser == m_treeBrowser && item) {
+ m_treeBrowser->setBackgroundColor(item, propertyColor(groupProperty));
+ groupProperty->setModified(true);
+ }
+ }
+ /* Group changed or new group. Append to last subproperty of
+ * that group. Note that there are cases in which a derived
+ * property sheet appends fake properties for the class
+ * which will appear after the layout group properties
+ * (QWizardPage). To make them appear at the end of the
+ * actual class group, goto last element. */
+ if (lastGroup != groupProperty) {
+ lastGroup = groupProperty;
+ lastProperty = 0; // Append at end
+ const QList<QtProperty*> subProperties = lastGroup->subProperties();
+ if (!subProperties.empty())
+ lastProperty = subProperties.back();
+ lastGroup = groupProperty;
+ }
+ if (!m_groups.contains(groupProperty))
+ m_groups.append(groupProperty);
+ if (newProperty)
+ groupProperty->insertSubProperty(property, lastProperty);
+
+ lastProperty = property;
+
+ updateBrowserValue(property, value);
+
+ property->setModified(m_propertySheet->isChanged(i));
+ if (propertyName == QLatin1String("geometry") && type == QVariant::Rect) {
+ QList<QtProperty *> subProperties = property->subProperties();
+ foreach (QtProperty *subProperty, subProperties) {
+ const QString subPropertyName = subProperty->propertyName();
+ if (subPropertyName == QLatin1String("X") || subPropertyName == QLatin1String("Y"))
+ subProperty->setEnabled(!isMainContainer);
+ }
+ }
+ } else {
+ qWarning("%s", qPrintable(msgUnsupportedType(propertyName, type)));
+ }
+ }
+ }
+ QMap<QString, QtVariantProperty *> groups = m_nameToGroup;
+ QMapIterator<QString, QtVariantProperty *> itGroup(groups);
+ while (itGroup.hasNext()) {
+ QtVariantProperty *groupProperty = itGroup.next().value();
+ if (groupProperty->subProperties().empty()) {
+ if (groupProperty == m_dynamicGroup)
+ m_dynamicGroup = 0;
+ delete groupProperty;
+ m_nameToGroup.remove(itGroup.key());
+ }
+ }
+ const bool addEnabled = dynamicSheet ? dynamicSheet->dynamicPropertiesAllowed() : false;
+ m_addDynamicAction->setEnabled(addEnabled);
+ m_removeDynamicAction->setEnabled(false);
+ applyExpansionState();
+ applyFilter();
+ // In the first setObject() call following the addition of a dynamic property, focus and edit it.
+ if (editNewDynamicProperty) {
+ // Have QApplication process the events related to completely closing the modal 'add' dialog,
+ // otherwise, we cannot focus the property editor in docked mode.
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ editProperty(m_recentlyAddedDynamicProperty);
+ }
+ m_recentlyAddedDynamicProperty.clear();
+ m_filterWidget->setEnabled(object);
+}
+
+void PropertyEditor::reloadResourceProperties()
+{
+ m_updatingBrowser = true;
+ m_propertyManager->reloadResourceProperties();
+ m_updatingBrowser = false;
+}
+
+QtBrowserItem *PropertyEditor::nonFakePropertyBrowserItem(QtBrowserItem *item) const
+{
+ // Top-level properties are QObject/QWidget groups, etc. Find first item property below
+ // which should be nonfake
+ const QList<QtBrowserItem *> topLevelItems = m_currentBrowser->topLevelItems();
+ do {
+ if (topLevelItems.contains(item->parent()))
+ return item;
+ item = item->parent();
+ } while (item);
+ return 0;
+}
+
+QString PropertyEditor::currentPropertyName() const
+{
+ if (QtBrowserItem *browserItem = m_currentBrowser->currentItem())
+ if (QtBrowserItem *topLevelItem = nonFakePropertyBrowserItem(browserItem)) {
+ return topLevelItem->property()->propertyName();
+ }
+ return QString();
+}
+
+void PropertyEditor::slotResetProperty(QtProperty *property)
+{
+ QDesignerFormWindowInterface *form = m_core->formWindowManager()->activeFormWindow();
+ if (!form)
+ return;
+
+ if (m_propertyManager->resetFontSubProperty(property))
+ return;
+
+ if (m_propertyManager->resetIconSubProperty(property))
+ return;
+
+ if (!m_propertyToGroup.contains(property))
+ return;
+
+ emit resetProperty(property->propertyName());
+}
+
+void PropertyEditor::slotValueChanged(QtProperty *property, const QVariant &value, bool enableSubPropertyHandling)
+{
+ if (m_updatingBrowser)
+ return;
+
+ if (!m_propertySheet)
+ return;
+
+ QtVariantProperty *varProp = m_propertyManager->variantProperty(property);
+
+ if (!varProp)
+ return;
+
+ if (!m_propertyToGroup.contains(property))
+ return;
+
+ if (varProp->propertyType() == QtVariantPropertyManager::enumTypeId()) {
+ PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(m_propertySheet->property(m_propertySheet->indexOf(property->propertyName())));
+ const int val = value.toInt();
+ const QString valName = varProp->attributeValue(m_strings.m_enumNamesAttribute).toStringList().at(val);
+ bool ok = false;
+ e.value = e.metaEnum.parseEnum(valName, &ok);
+ Q_ASSERT(ok);
+ QVariant v;
+ qVariantSetValue(v, e);
+ emit propertyValueChanged(property->propertyName(), v, true);
+ return;
+ }
+
+ emit propertyValueChanged(property->propertyName(), value, enableSubPropertyHandling);
+}
+
+bool PropertyEditor::isDynamicProperty(const QtBrowserItem* item) const
+{
+ if (!item)
+ return false;
+
+ const QDesignerDynamicPropertySheetExtension *dynamicSheet =
+ qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object);
+
+ if (!dynamicSheet)
+ return false;
+
+ if (m_propertyToGroup.contains(item->property())
+ && dynamicSheet->isDynamicProperty(m_propertySheet->indexOf(item->property()->propertyName())))
+ return true;
+ return false;
+}
+
+void PropertyEditor::editProperty(const QString &name)
+{
+ // find the browser item belonging to the property, make it current and edit it
+ QtBrowserItem *browserItem = 0;
+ if (QtVariantProperty *property = m_nameToProperty.value(name, 0)) {
+ const QList<QtBrowserItem *> items = m_currentBrowser->items(property);
+ if (items.size() == 1)
+ browserItem = items.front();
+ }
+ if (browserItem == 0)
+ return;
+ m_currentBrowser->setFocus(Qt::OtherFocusReason);
+ if (m_currentBrowser == m_treeBrowser) { // edit is currently only supported in tree view
+ m_treeBrowser->editItem(browserItem);
+ } else {
+ m_currentBrowser->setCurrentItem(browserItem);
+ }
+}
+
+void PropertyEditor::slotCurrentItemChanged(QtBrowserItem *item)
+{
+ m_removeDynamicAction->setEnabled(isDynamicProperty(item));
+
+}
+
+void PropertyEditor::slotRemoveDynamicProperty()
+{
+ if (QtBrowserItem* item = m_currentBrowser->currentItem())
+ if (isDynamicProperty(item))
+ emit removeDynamicProperty(item->property()->propertyName());
+}
+
+void PropertyEditor::setFilter(const QString &pattern)
+{
+ m_filterPattern = pattern;
+ applyFilter();
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.h b/tools/designer/src/components/propertyeditor/propertyeditor.h
new file mode 100644
index 0000000000..21e81dde4f
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/propertyeditor.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROPERTYEDITOR_H
+#define PROPERTYEDITOR_H
+
+#include "propertyeditor_global.h"
+#include <qdesigner_propertyeditor_p.h>
+
+#include <QtCore/QPointer>
+#include <QtCore/QMap>
+#include <QtCore/QVector>
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+class DomProperty;
+class QDesignerMetaDataBaseItemInterface;
+class QDesignerPropertySheetExtension;
+
+class QtAbstractPropertyBrowser;
+class QtButtonPropertyBrowser;
+class QtTreePropertyBrowser;
+class QtProperty;
+class QtVariantProperty;
+class QtBrowserItem;
+
+class QStackedWidget;
+class QLabel;
+
+namespace qdesigner_internal {
+
+class StringProperty;
+class DesignerPropertyManager;
+class DesignerEditorFactory;
+class FilterWidget;
+
+class QT_PROPERTYEDITOR_EXPORT PropertyEditor: public QDesignerPropertyEditor
+{
+ Q_OBJECT
+public:
+ explicit PropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~PropertyEditor();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool isReadOnly() const;
+ virtual void setReadOnly(bool readOnly);
+ virtual void setPropertyValue(const QString &name, const QVariant &value, bool changed = true);
+ virtual void updatePropertySheet();
+
+ virtual void setObject(QObject *object);
+
+ void reloadResourceProperties();
+
+ virtual QObject *object() const
+ { return m_object; }
+
+ virtual QString currentPropertyName() const;
+
+protected:
+
+ bool event(QEvent *event);
+
+private slots:
+ void slotResetProperty(QtProperty *property);
+ void slotValueChanged(QtProperty *property, const QVariant &value, bool enableSubPropertyHandling);
+ void slotViewTriggered(QAction *action);
+ void slotAddDynamicProperty(QAction *action);
+ void slotRemoveDynamicProperty();
+ void slotSorting(bool sort);
+ void slotColoring(bool color);
+ void slotCurrentItemChanged(QtBrowserItem*);
+ void setFilter(const QString &pattern);
+
+private:
+ void updateBrowserValue(QtVariantProperty *property, const QVariant &value);
+ void updateToolBarLabel();
+ int toBrowserType(const QVariant &value, const QString &propertyName) const;
+ QString removeScope(const QString &value) const;
+ QDesignerMetaDataBaseItemInterface *metaDataBaseItem() const;
+ void setupStringProperty(QtVariantProperty *property, bool isMainContainer);
+ void setupPaletteProperty(QtVariantProperty *property);
+ QString realClassName(QObject *object) const;
+ void storeExpansionState();
+ void applyExpansionState();
+ void storePropertiesExpansionState(const QList<QtBrowserItem *> &items);
+ void applyPropertiesExpansionState(const QList<QtBrowserItem *> &items);
+ void applyFilter();
+ int applyPropertiesFilter(const QList<QtBrowserItem *> &items);
+ void setExpanded(QtBrowserItem *item, bool expanded);
+ bool isExpanded(QtBrowserItem *item) const;
+ void setItemVisible(QtBrowserItem *item, bool visible);
+ bool isItemVisible(QtBrowserItem *item) const;
+ void collapseAll();
+ void clearView();
+ void fillView();
+ bool isLayoutGroup(QtProperty *group) const;
+ void updateColors();
+ void updateForegroundBrightness();
+ QColor propertyColor(QtProperty *property) const;
+ void updateActionsState();
+ QtBrowserItem *nonFakePropertyBrowserItem(QtBrowserItem *item) const;
+ void saveSettings() const;
+ void editProperty(const QString &name);
+ bool isDynamicProperty(const QtBrowserItem* item) const;
+
+ struct Strings {
+ Strings();
+ QSet<QString> m_alignmentProperties;
+ const QString m_fontProperty;
+ const QString m_qLayoutWidget;
+ const QString m_designerPrefix;
+ const QString m_layout;
+ const QString m_validationModeAttribute;
+ const QString m_fontAttribute;
+ const QString m_superPaletteAttribute;
+ const QString m_enumNamesAttribute;
+ const QString m_resettableAttribute;
+ const QString m_flagsAttribute;
+ };
+
+ const Strings m_strings;
+ QDesignerFormEditorInterface *m_core;
+ QDesignerPropertySheetExtension *m_propertySheet;
+ QtAbstractPropertyBrowser *m_currentBrowser;
+ QtButtonPropertyBrowser *m_buttonBrowser;
+ QtTreePropertyBrowser *m_treeBrowser;
+ DesignerPropertyManager *m_propertyManager;
+ DesignerEditorFactory *m_treeFactory;
+ DesignerEditorFactory *m_groupFactory;
+ QPointer<QObject> m_object;
+ QMap<QString, QtVariantProperty*> m_nameToProperty;
+ QMap<QtProperty*, QString> m_propertyToGroup;
+ QMap<QString, QtVariantProperty*> m_nameToGroup;
+ QList<QtProperty *> m_groups;
+ QtProperty *m_dynamicGroup;
+ QString m_recentlyAddedDynamicProperty;
+ bool m_updatingBrowser;
+
+ QStackedWidget *m_stackedWidget;
+ FilterWidget *m_filterWidget;
+ int m_buttonIndex;
+ int m_treeIndex;
+ QAction *m_addDynamicAction;
+ QAction *m_removeDynamicAction;
+ QAction *m_sortingAction;
+ QAction *m_coloringAction;
+ QAction *m_treeAction;
+ QAction *m_buttonAction;
+ QLabel *m_classLabel;
+
+ bool m_sorting;
+ bool m_coloring;
+
+ QMap<QString, bool> m_expansionState;
+
+ QString m_filterPattern;
+ QVector<QPair<QColor, QColor> > m_colors;
+ QPair<QColor, QColor> m_dynamicColor;
+ QPair<QColor, QColor> m_layoutColor;
+
+ bool m_brightness;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PROPERTYEDITOR_H
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.pri b/tools/designer/src/components/propertyeditor/propertyeditor.pri
new file mode 100644
index 0000000000..d3e44a57b1
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/propertyeditor.pri
@@ -0,0 +1,47 @@
+#the next line prevents non-shadowbuilds from including the same directory twice
+#otherwise, the build command would be too long for some win32 shells.
+!exists($$QT_BUILD_TREE/tools/designer/src/components/propertyeditor/propertyeditor.h):INCLUDEPATH += $$QT_BUILD_TREE/tools/designer/src/components/propertyeditor
+
+INCLUDEPATH += $$PWD
+
+include($$QT_SOURCE_TREE/tools/shared/qtpropertybrowser/qtpropertybrowser.pri)
+include($$QT_SOURCE_TREE/tools/shared/qtgradienteditor/qtcolorbutton.pri)
+
+FORMS += $$PWD/paletteeditor.ui \
+ $$PWD/stringlisteditor.ui \
+ $$PWD/previewwidget.ui \
+ $$PWD/newdynamicpropertydialog.ui
+
+HEADERS += $$PWD/propertyeditor.h \
+ $$PWD/designerpropertymanager.h \
+ $$PWD/paletteeditor.h \
+ $$PWD/paletteeditorbutton.h \
+ $$PWD/stringlisteditor.h \
+ $$PWD/stringlisteditorbutton.h \
+ $$PWD/previewwidget.h \
+ $$PWD/previewframe.h \
+ $$PWD/newdynamicpropertydialog.h \
+ $$PWD/brushpropertymanager.h \
+ $$PWD/fontpropertymanager.h
+
+SOURCES += $$PWD/propertyeditor.cpp \
+ $$PWD/designerpropertymanager.cpp \
+ $$PWD/paletteeditor.cpp \
+ $$PWD/paletteeditorbutton.cpp \
+ $$PWD/stringlisteditor.cpp \
+ $$PWD/stringlisteditorbutton.cpp \
+ $$PWD/previewwidget.cpp \
+ $$PWD/previewframe.cpp \
+ $$PWD/newdynamicpropertydialog.cpp \
+ $$PWD/brushpropertymanager.cpp \
+ $$PWD/fontpropertymanager.cpp
+
+HEADERS += \
+ $$PWD/propertyeditor_global.h \
+ $$PWD/defs.h \
+ $$PWD/qlonglongvalidator.h
+
+SOURCES += $$PWD/defs.cpp \
+ $$PWD/qlonglongvalidator.cpp
+
+RESOURCES += $$PWD/propertyeditor.qrc
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.qrc b/tools/designer/src/components/propertyeditor/propertyeditor.qrc
new file mode 100644
index 0000000000..68008eca8b
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/propertyeditor.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/propertyeditor">
+ <file>fontmapping.xml</file>
+ </qresource>
+</RCC>
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor_global.h b/tools/designer/src/components/propertyeditor/propertyeditor_global.h
new file mode 100644
index 0000000000..c7c4780f21
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/propertyeditor_global.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROPERTYEDITOR_GLOBAL_H
+#define PROPERTYEDITOR_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+#ifdef QT_PROPERTYEDITOR_LIBRARY
+# define QT_PROPERTYEDITOR_EXPORT
+#else
+# define QT_PROPERTYEDITOR_EXPORT
+#endif
+#else
+#define QT_PROPERTYEDITOR_EXPORT
+#endif
+
+QT_END_NAMESPACE
+
+#endif // PROPERTYEDITOR_GLOBAL_H
diff --git a/tools/designer/src/components/propertyeditor/qlonglongvalidator.cpp b/tools/designer/src/components/propertyeditor/qlonglongvalidator.cpp
new file mode 100644
index 0000000000..a6663cf60d
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/qlonglongvalidator.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlonglongvalidator.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+// ----------------------------------------------------------------------------
+QLongLongValidator::QLongLongValidator(QObject * parent)
+ : QValidator(parent),
+ b(Q_UINT64_C(0x8000000000000000)), t(Q_UINT64_C(0x7FFFFFFFFFFFFFFF))
+{
+}
+
+QLongLongValidator::QLongLongValidator(qlonglong minimum, qlonglong maximum,
+ QObject * parent)
+ : QValidator(parent), b(minimum), t(maximum)
+{
+}
+
+QLongLongValidator::~QLongLongValidator()
+{
+ // nothing
+}
+
+QValidator::State QLongLongValidator::validate(QString & input, int &) const
+{
+ if (input.contains(QLatin1Char(' ')))
+ return Invalid;
+ if (input.isEmpty() || (b < 0 && input == QString(QLatin1Char('-'))))
+ return Intermediate;
+ bool ok;
+ qlonglong entered = input.toLongLong(&ok);
+ if (!ok || (entered < 0 && b >= 0)) {
+ return Invalid;
+ } else if (entered >= b && entered <= t) {
+ return Acceptable;
+ } else {
+ if (entered >= 0)
+ return (entered > t) ? Invalid : Intermediate;
+ else
+ return (entered < b) ? Invalid : Intermediate;
+ }
+}
+
+void QLongLongValidator::setRange(qlonglong bottom, qlonglong top)
+{
+ b = bottom;
+ t = top;
+}
+
+void QLongLongValidator::setBottom(qlonglong bottom)
+{
+ setRange(bottom, top());
+}
+
+void QLongLongValidator::setTop(qlonglong top)
+{
+ setRange(bottom(), top);
+}
+
+
+// ----------------------------------------------------------------------------
+QULongLongValidator::QULongLongValidator(QObject * parent)
+ : QValidator(parent),
+ b(0), t(Q_UINT64_C(0xFFFFFFFFFFFFFFFF))
+{
+}
+
+QULongLongValidator::QULongLongValidator(qulonglong minimum, qulonglong maximum,
+ QObject * parent)
+ : QValidator(parent), b(minimum), t(maximum)
+{
+}
+
+QULongLongValidator::~QULongLongValidator()
+{
+ // nothing
+}
+
+QValidator::State QULongLongValidator::validate(QString & input, int &) const
+{
+ if (input.isEmpty())
+ return Intermediate;
+
+ bool ok;
+ qulonglong entered = input.toULongLong(&ok);
+ if (input.contains(QLatin1Char(' ')) || input.contains(QLatin1Char('-')) || !ok)
+ return Invalid;
+
+ if (entered >= b && entered <= t)
+ return Acceptable;
+
+ return Invalid;
+}
+
+void QULongLongValidator::setRange(qulonglong bottom, qulonglong top)
+{
+ b = bottom;
+ t = top;
+}
+
+void QULongLongValidator::setBottom(qulonglong bottom)
+{
+ setRange(bottom, top());
+}
+
+void QULongLongValidator::setTop(qulonglong top)
+{
+ setRange(bottom(), top);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/qlonglongvalidator.h b/tools/designer/src/components/propertyeditor/qlonglongvalidator.h
new file mode 100644
index 0000000000..2b3174b3c8
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/qlonglongvalidator.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLONGLONGVALIDATOR_H
+#define QLONGLONGVALIDATOR_H
+
+#include <QtGui/QValidator>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QLongLongValidator : public QValidator
+{
+ Q_OBJECT
+ Q_PROPERTY(qlonglong bottom READ bottom WRITE setBottom)
+ Q_PROPERTY(qlonglong top READ top WRITE setTop)
+
+public:
+ explicit QLongLongValidator(QObject * parent);
+ QLongLongValidator(qlonglong bottom, qlonglong top, QObject * parent);
+ ~QLongLongValidator();
+
+ QValidator::State validate(QString &, int &) const;
+
+ void setBottom(qlonglong);
+ void setTop(qlonglong);
+ virtual void setRange(qlonglong bottom, qlonglong top);
+
+ qlonglong bottom() const { return b; }
+ qlonglong top() const { return t; }
+
+private:
+ Q_DISABLE_COPY(QLongLongValidator)
+
+ qlonglong b;
+ qlonglong t;
+};
+
+// ----------------------------------------------------------------------------
+class QULongLongValidator : public QValidator
+{
+ Q_OBJECT
+ Q_PROPERTY(qulonglong bottom READ bottom WRITE setBottom)
+ Q_PROPERTY(qulonglong top READ top WRITE setTop)
+
+public:
+ explicit QULongLongValidator(QObject * parent);
+ QULongLongValidator(qulonglong bottom, qulonglong top, QObject * parent);
+ ~QULongLongValidator();
+
+ QValidator::State validate(QString &, int &) const;
+
+ void setBottom(qulonglong);
+ void setTop(qulonglong);
+ virtual void setRange(qulonglong bottom, qulonglong top);
+
+ qulonglong bottom() const { return b; }
+ qulonglong top() const { return t; }
+
+private:
+ Q_DISABLE_COPY(QULongLongValidator)
+
+ qulonglong b;
+ qulonglong t;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QLONGLONGVALIDATOR_H
diff --git a/tools/designer/src/components/propertyeditor/stringlisteditor.cpp b/tools/designer/src/components/propertyeditor/stringlisteditor.cpp
new file mode 100644
index 0000000000..861e69985c
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/stringlisteditor.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "stringlisteditor.h"
+#include <iconloader_p.h>
+#include <QtGui/QStringListModel>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+StringListEditor::StringListEditor(QWidget *parent)
+ : QDialog(parent), m_model(new QStringListModel(this))
+{
+ setupUi(this);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ listView->setModel(m_model);
+
+ connect(listView->selectionModel(),
+ SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
+ this, SLOT(currentIndexChanged(const QModelIndex &, const QModelIndex &)));
+ connect(listView->itemDelegate(),
+ SIGNAL(closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint)),
+ this, SLOT(currentValueChanged()));
+
+ QIcon upIcon = createIconSet(QString::fromUtf8("up.png"));
+ QIcon downIcon = createIconSet(QString::fromUtf8("down.png"));
+ QIcon minusIcon = createIconSet(QString::fromUtf8("minus.png"));
+ QIcon plusIcon = createIconSet(QString::fromUtf8("plus.png"));
+ upButton->setIcon(upIcon);
+ downButton->setIcon(downIcon);
+ newButton->setIcon(plusIcon);
+ deleteButton->setIcon(minusIcon);
+
+ updateUi();
+}
+
+StringListEditor::~StringListEditor()
+{
+}
+
+QStringList StringListEditor::getStringList(QWidget *parent, const QStringList &init, int *result)
+{
+ StringListEditor dlg(parent);
+ dlg.setStringList(init);
+ int res = dlg.exec();
+ if (result)
+ *result = res;
+ return (res == QDialog::Accepted) ? dlg.stringList() : init;
+}
+
+void StringListEditor::setStringList(const QStringList &stringList)
+{
+ m_model->setStringList(stringList);
+ updateUi();
+}
+
+QStringList StringListEditor::stringList() const
+{
+ return m_model->stringList();
+}
+
+void StringListEditor::currentIndexChanged(const QModelIndex &current, const QModelIndex &previous)
+{
+ Q_UNUSED(previous);
+ setCurrentIndex(current.row());
+ updateUi();
+}
+
+void StringListEditor::currentValueChanged()
+{
+ setCurrentIndex(currentIndex());
+ updateUi();
+}
+
+void StringListEditor::on_upButton_clicked()
+{
+ int from = currentIndex();
+ int to = currentIndex() - 1;
+ QString value = stringAt(from);
+ removeString(from);
+ insertString(to, value);
+ setCurrentIndex(to);
+ updateUi();
+}
+
+void StringListEditor::on_downButton_clicked()
+{
+ int from = currentIndex();
+ int to = currentIndex() + 1;
+ QString value = stringAt(from);
+ removeString(from);
+ insertString(to, value);
+ setCurrentIndex(to);
+ updateUi();
+}
+
+void StringListEditor::on_newButton_clicked()
+{
+ int to = currentIndex();
+ if (to == -1)
+ to = count() - 1;
+ ++to;
+ insertString(to, QString());
+ setCurrentIndex(to);
+ updateUi();
+ editString(to);
+}
+
+void StringListEditor::on_deleteButton_clicked()
+{
+ removeString(currentIndex());
+ setCurrentIndex(currentIndex());
+ updateUi();
+}
+
+void StringListEditor::on_valueEdit_textEdited(const QString &text)
+{
+ setStringAt(currentIndex(), text);
+}
+
+void StringListEditor::updateUi()
+{
+ upButton->setEnabled((count() > 1) && (currentIndex() > 0));
+ downButton->setEnabled((count() > 1) && (currentIndex() >= 0) && (currentIndex() < (count() - 1)));
+ deleteButton->setEnabled(currentIndex() != -1);
+ valueEdit->setEnabled(currentIndex() != -1);
+}
+
+int StringListEditor::currentIndex() const
+{
+ return listView->currentIndex().row();
+}
+
+void StringListEditor::setCurrentIndex(int index)
+{
+ QModelIndex modelIndex = m_model->index(index, 0);
+ if (listView->currentIndex() != modelIndex)
+ listView->setCurrentIndex(modelIndex);
+ valueEdit->setText(stringAt(index));
+}
+
+int StringListEditor::count() const
+{
+ return m_model->rowCount();
+}
+
+QString StringListEditor::stringAt(int index) const
+{
+ return qvariant_cast<QString>(m_model->data(m_model->index(index, 0), Qt::DisplayRole));
+}
+
+void StringListEditor::setStringAt(int index, const QString &value)
+{
+ m_model->setData(m_model->index(index, 0), value);
+}
+
+void StringListEditor::removeString(int index)
+{
+ m_model->removeRows(index, 1);
+}
+
+void StringListEditor::insertString(int index, const QString &value)
+{
+ m_model->insertRows(index, 1);
+ m_model->setData(m_model->index(index, 0), value);
+}
+
+void StringListEditor::editString(int index)
+{
+ listView->edit(m_model->index(index, 0));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/stringlisteditor.h b/tools/designer/src/components/propertyeditor/stringlisteditor.h
new file mode 100644
index 0000000000..86b48ff254
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/stringlisteditor.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STRINGLISTEDITOR_H
+#define STRINGLISTEDITOR_H
+
+#include "ui_stringlisteditor.h"
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+class QStringListModel;
+
+namespace qdesigner_internal {
+
+class StringListEditor : public QDialog, private Ui::Dialog
+{
+ Q_OBJECT
+public:
+ ~StringListEditor();
+ void setStringList(const QStringList &stringList);
+ QStringList stringList() const;
+
+ static QStringList getStringList(
+ QWidget *parent, const QStringList &init = QStringList(), int *result = 0);
+
+private slots:
+ void on_upButton_clicked();
+ void on_downButton_clicked();
+ void on_newButton_clicked();
+ void on_deleteButton_clicked();
+ void on_valueEdit_textEdited(const QString &text);
+ void currentIndexChanged(const QModelIndex &current, const QModelIndex &previous);
+ void currentValueChanged();
+
+private:
+ StringListEditor(QWidget *parent = 0);
+ void updateUi();
+ int currentIndex() const;
+ void setCurrentIndex(int index);
+ int count() const;
+ QString stringAt(int index) const;
+ void setStringAt(int index, const QString &value);
+ void removeString(int index);
+ void insertString(int index, const QString &value);
+ void editString(int index);
+
+ QStringListModel *m_model;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // STRINGLISTEDITOR_H
diff --git a/tools/designer/src/components/propertyeditor/stringlisteditor.ui b/tools/designer/src/components/propertyeditor/stringlisteditor.ui
new file mode 100644
index 0000000000..fdcdabc79c
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/stringlisteditor.ui
@@ -0,0 +1,265 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::Dialog</class>
+ <widget class="QDialog" name="qdesigner_internal::Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>StringList</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="1" column="0" colspan="2" >
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="newButton" >
+ <property name="toolTip" >
+ <string>New String</string>
+ </property>
+ <property name="text" >
+ <string>&amp;New</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="deleteButton" >
+ <property name="toolTip" >
+ <string>Delete String</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Delete</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>&amp;Value:</string>
+ </property>
+ <property name="buddy" >
+ <cstring>valueEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="valueEdit" />
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="1" >
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QToolButton" name="upButton" >
+ <property name="toolTip" >
+ <string>Move String Up</string>
+ </property>
+ <property name="text" >
+ <string>Up</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="downButton" >
+ <property name="toolTip" >
+ <string>Move String Down</string>
+ </property>
+ <property name="text" >
+ <string>Down</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QListView" name="listView" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>qdesigner_internal::Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>258</x>
+ <y>283</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>138</x>
+ <y>294</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>qdesigner_internal::Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>350</x>
+ <y>284</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>369</x>
+ <y>295</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/components/propertyeditor/stringlisteditorbutton.cpp b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.cpp
new file mode 100644
index 0000000000..440015c565
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::StringListEditorButton
+*/
+
+#include "stringlisteditorbutton.h"
+#include "stringlisteditor.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+StringListEditorButton::StringListEditorButton(
+ const QStringList &stringList, QWidget *parent)
+ : QToolButton(parent), m_stringList(stringList)
+{
+ setFocusPolicy(Qt::NoFocus);
+ setText(tr("Change String List"));
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+
+ connect(this, SIGNAL(clicked()), this, SLOT(showStringListEditor()));
+}
+
+StringListEditorButton::~StringListEditorButton()
+{
+}
+
+void StringListEditorButton::setStringList(const QStringList &stringList)
+{
+ m_stringList = stringList;
+}
+
+void StringListEditorButton::showStringListEditor()
+{
+ int result;
+ QStringList lst = StringListEditor::getStringList(0, m_stringList, &result);
+ if (result == QDialog::Accepted) {
+ m_stringList = lst;
+ emit stringListChanged(m_stringList);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/propertyeditor/stringlisteditorbutton.h b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.h
new file mode 100644
index 0000000000..c843980649
--- /dev/null
+++ b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STRINGLISTEDITORBUTTON_H
+#define STRINGLISTEDITORBUTTON_H
+
+#include "propertyeditor_global.h"
+
+#include <QtCore/QStringList>
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QT_PROPERTYEDITOR_EXPORT StringListEditorButton: public QToolButton
+{
+ Q_OBJECT
+public:
+ explicit StringListEditorButton(const QStringList &stringList, QWidget *parent = 0);
+ virtual ~StringListEditorButton();
+
+ inline QStringList stringList() const
+ { return m_stringList; }
+
+signals:
+ void stringListChanged(const QStringList &stringList);
+
+public slots:
+ void setStringList(const QStringList &stringList);
+
+private slots:
+ void showStringListEditor();
+
+private:
+ QStringList m_stringList;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // STRINGLISTEDITORBUTTON_H
diff --git a/tools/designer/src/components/signalsloteditor/connectdialog.cpp b/tools/designer/src/components/signalsloteditor/connectdialog.cpp
new file mode 100644
index 0000000000..d9b8ed535b
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/connectdialog.cpp
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "connectdialog_p.h"
+#include "signalslot_utils_p.h"
+
+#include <signalslotdialog_p.h>
+#include <metadatabase_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerLanguageExtension>
+
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ typedef QList<QListWidgetItem*> ListWidgetItems;
+}
+
+static QString realClassName(QDesignerFormEditorInterface *core, QWidget *widget)
+{
+ QString class_name = QLatin1String(widget->metaObject()->className());
+ const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
+ const int idx = wdb->indexOfObject(widget);
+ if (idx != -1)
+ class_name = wdb->item(idx)->name();
+ return class_name;
+}
+
+static QString widgetLabel(QDesignerFormEditorInterface *core, QWidget *widget)
+{
+ return QString::fromUtf8("%1 (%2)")
+ .arg(qdesigner_internal::realObjectName(core, widget))
+ .arg(realClassName(core, widget));
+}
+
+namespace qdesigner_internal {
+
+ConnectDialog::ConnectDialog(QDesignerFormWindowInterface *formWindow,
+ QWidget *source, QWidget *destination,
+ QWidget *parent) :
+ QDialog(parent),
+ m_source(source),
+ m_destination(destination),
+ m_sourceMode(widgetMode(m_source, formWindow)),
+ m_destinationMode(widgetMode(m_destination, formWindow)),
+ m_formWindow(formWindow)
+{
+ m_ui.setupUi(this);
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ connect(m_ui.signalList, SIGNAL(itemClicked(QListWidgetItem*)),
+ this, SLOT(selectSignal(QListWidgetItem*)));
+ connect(m_ui.slotList, SIGNAL(itemClicked(QListWidgetItem*)),
+ this, SLOT(selectSlot(QListWidgetItem*)));
+ m_ui.slotList->setEnabled(false);
+
+ QPushButton *ok_button = okButton();
+ ok_button->setDefault(true);
+ ok_button->setEnabled(false);
+
+ connect(m_ui.showAllCheckBox, SIGNAL(toggled(bool)), this, SLOT(populateLists()));
+
+ QDesignerFormEditorInterface *core = m_formWindow->core();
+ m_ui.signalGroupBox->setTitle(widgetLabel(core, source));
+ m_ui.slotGroupBox->setTitle(widgetLabel(core, destination));
+
+ m_ui.editSignalsButton->setEnabled(m_sourceMode != NormalWidget);
+ connect(m_ui.editSignalsButton, SIGNAL(clicked()), this, SLOT(editSignals()));
+
+ m_ui.editSlotsButton->setEnabled(m_destinationMode != NormalWidget);
+ connect(m_ui.editSlotsButton, SIGNAL(clicked()), this, SLOT(editSlots()));
+
+ populateLists();
+}
+
+ConnectDialog::WidgetMode ConnectDialog::widgetMode(QWidget *w, QDesignerFormWindowInterface *formWindow)
+{
+ QDesignerFormEditorInterface *core = formWindow->core();
+ if (qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core))
+ return NormalWidget;
+
+ if (w == formWindow || formWindow->mainContainer() == w)
+ return MainContainer;
+
+ if (isPromoted(formWindow->core(), w))
+ return PromotedWidget;
+
+ return NormalWidget;
+}
+
+QPushButton *ConnectDialog::okButton()
+{
+ return m_ui.buttonBox->button(QDialogButtonBox::Ok);
+}
+
+void ConnectDialog::setOkButtonEnabled(bool e)
+{
+ okButton()->setEnabled(e);
+}
+
+void ConnectDialog::populateLists()
+{
+ populateSignalList();
+}
+
+void ConnectDialog::setSignalSlot(const QString &signal, const QString &slot)
+{
+ ListWidgetItems sigItems = m_ui.signalList->findItems(signal, Qt::MatchExactly);
+
+ if (sigItems.empty()) {
+ m_ui.showAllCheckBox->setChecked(true);
+ sigItems = m_ui.signalList->findItems(signal, Qt::MatchExactly);
+ }
+
+ if (!sigItems.empty()) {
+ selectSignal(sigItems.front());
+ ListWidgetItems slotItems = m_ui.slotList->findItems(slot, Qt::MatchExactly);
+ if (slotItems.empty()) {
+ m_ui.showAllCheckBox->setChecked(true);
+ slotItems = m_ui.slotList->findItems(slot, Qt::MatchExactly);
+ }
+ if (!slotItems.empty())
+ selectSlot(slotItems.front());
+ }
+}
+
+bool ConnectDialog::showAllSignalsSlots() const
+{
+ return m_ui.showAllCheckBox->isChecked();
+}
+
+void ConnectDialog::setShowAllSignalsSlots(bool showIt)
+{
+ m_ui.showAllCheckBox->setChecked(showIt);
+}
+
+void ConnectDialog::selectSignal(QListWidgetItem *item)
+{
+ if (item) {
+ m_ui.signalList->setCurrentItem(item);
+ populateSlotList(item->text());
+ m_ui.slotList->setEnabled(true);
+ setOkButtonEnabled(!m_ui.slotList->selectedItems().isEmpty());
+ } else {
+ m_ui.signalList->clearSelection();
+ populateSlotList();
+ m_ui.slotList->setEnabled(false);
+ setOkButtonEnabled(false);
+ }
+}
+
+void ConnectDialog::selectSlot(QListWidgetItem *item)
+{
+ if (item) {
+ m_ui.slotList->setCurrentItem(item);
+ } else {
+ m_ui.slotList->clearSelection();
+ }
+ setOkButtonEnabled(true);
+}
+
+QString ConnectDialog::signal() const
+{
+ const ListWidgetItems item_list = m_ui.signalList->selectedItems();
+ if (item_list.size() != 1)
+ return QString();
+ return item_list.at(0)->text();
+}
+
+QString ConnectDialog::slot() const
+{
+ const ListWidgetItems item_list = m_ui.slotList->selectedItems();
+ if (item_list.size() != 1)
+ return QString();
+ return item_list.at(0)->text();
+}
+
+void ConnectDialog::populateSlotList(const QString &signal)
+{
+ QString selectedName;
+ if (const QListWidgetItem * item = m_ui.slotList->currentItem())
+ selectedName = item->text();
+
+ m_ui.slotList->clear();
+
+ QMap<QString, QString> memberToClassName = getMatchingSlots(m_formWindow->core(), m_destination, signal, showAllSignalsSlots());
+
+ QFont font = QApplication::font();
+ font.setItalic(true);
+ QVariant variantFont = qVariantFromValue(font);
+
+ QListWidgetItem *curr = 0;
+ QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin();
+ const QMap<QString, QString>::ConstIterator itMemberEnd = memberToClassName.constEnd();
+ while (itMember != itMemberEnd) {
+ const QString member = itMember.key();
+ const bool qt3Slot = isQt3Slot(m_formWindow->core(), m_destination, member);
+
+ QListWidgetItem *item = new QListWidgetItem(m_ui.slotList);
+ item->setText(member);
+ if (member == selectedName)
+ curr = item;
+
+ if (qt3Slot) {
+ item->setData(Qt::FontRole, variantFont);
+ item->setData(Qt::ForegroundRole, Qt::red);
+ }
+ ++itMember;
+ }
+
+ if (curr)
+ m_ui.slotList->setCurrentItem(curr);
+
+ if (m_ui.slotList->selectedItems().isEmpty())
+ setOkButtonEnabled(false);
+}
+
+void ConnectDialog::populateSignalList()
+{
+ QString selectedName;
+ if (const QListWidgetItem *item = m_ui.signalList->currentItem())
+ selectedName = item->text();
+
+ m_ui.signalList->clear();
+
+ QMap<QString, QString> memberToClassName = getSignals(m_formWindow->core(), m_source, showAllSignalsSlots());
+
+ QFont font = QApplication::font();
+ font.setItalic(true);
+ QVariant variantFont = qVariantFromValue(font);
+
+ QListWidgetItem *curr = 0;
+ QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin();
+ const QMap<QString, QString>::ConstIterator itMemberEnd = memberToClassName.constEnd();
+ while (itMember != itMemberEnd) {
+ const QString member = itMember.key();
+ const bool qt3Signal = isQt3Signal(m_formWindow->core(), m_source, member);
+
+ QListWidgetItem *item = new QListWidgetItem(m_ui.signalList);
+ item->setText(member);
+ if (!selectedName.isEmpty() && member == selectedName)
+ curr = item;
+
+ if (qt3Signal) {
+ item->setData(Qt::FontRole, variantFont);
+ item->setData(Qt::ForegroundRole, Qt::red);
+ }
+ ++itMember;
+ }
+
+ if (curr) {
+ m_ui.signalList->setCurrentItem(curr);
+ } else {
+ selectedName.clear();
+ }
+
+ populateSlotList(selectedName);
+ if (!curr)
+ m_ui.slotList->setEnabled(false);
+}
+
+void ConnectDialog::editSignals()
+{
+ editSignalsSlots(m_source, m_sourceMode, SignalSlotDialog::FocusSignals);
+}
+
+void ConnectDialog::editSlots()
+{
+ editSignalsSlots(m_destination, m_destinationMode, SignalSlotDialog::FocusSlots);
+}
+
+void ConnectDialog::editSignalsSlots(QWidget *w, WidgetMode mode, int signalSlotDialogModeInt)
+{
+ const SignalSlotDialog::FocusMode signalSlotDialogMode = static_cast<SignalSlotDialog::FocusMode>(signalSlotDialogModeInt);
+ switch (mode) {
+ case NormalWidget:
+ break;
+ case MainContainer:
+ if (SignalSlotDialog::editMetaDataBase(m_formWindow, w, this, signalSlotDialogMode))
+ populateLists();
+ break;
+ case PromotedWidget:
+ if (SignalSlotDialog::editPromotedClass(m_formWindow->core(), w, this, signalSlotDialogMode))
+ populateLists();
+ break;
+ }
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/signalsloteditor/connectdialog.ui b/tools/designer/src/components/signalsloteditor/connectdialog.ui
new file mode 100644
index 0000000000..bd062ebaaf
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/connectdialog.ui
@@ -0,0 +1,150 @@
+<ui version="4.0" >
+ <class>ConnectDialog</class>
+ <widget class="QDialog" name="ConnectDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>585</width>
+ <height>361</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Configure Connection</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="2" >
+ <widget class="QGroupBox" name="signalGroupBox" >
+ <property name="title" >
+ <string>GroupBox</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QListWidget" name="signalList" >
+ <property name="textElideMode" >
+ <enum>Qt::ElideMiddle</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QToolButton" name="editSignalsButton" >
+ <property name="text" >
+ <string>Edit...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QGroupBox" name="slotGroupBox" >
+ <property name="title" >
+ <string>GroupBox</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QListWidget" name="slotList" >
+ <property name="textElideMode" >
+ <enum>Qt::ElideMiddle</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QToolButton" name="editSlotsButton" >
+ <property name="text" >
+ <string>Edit...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QCheckBox" name="showAllCheckBox" >
+ <property name="text" >
+ <string>Show signals and slots inherited from QWidget</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="2" >
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ConnectDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ConnectDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/components/signalsloteditor/connectdialog_p.h b/tools/designer/src/components/signalsloteditor/connectdialog_p.h
new file mode 100644
index 0000000000..8fdc0192ff
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/connectdialog_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONNECTDIALOG_H
+#define CONNECTDIALOG_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "ui_connectdialog.h"
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QPushButton;
+
+namespace qdesigner_internal {
+
+class ConnectDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ ConnectDialog(QDesignerFormWindowInterface *formWindow, QWidget *sender, QWidget *receiver, QWidget *parent = 0);
+
+ QString signal() const;
+ QString slot() const;
+
+ void setSignalSlot(const QString &signal, const QString &slot);
+
+ bool showAllSignalsSlots() const;
+ void setShowAllSignalsSlots(bool showIt);
+
+private slots:
+ void populateLists();
+ void selectSignal(QListWidgetItem *item);
+ void selectSlot(QListWidgetItem *item);
+ void populateSignalList();
+ void populateSlotList(const QString &signal = QString());
+ void editSignals();
+ void editSlots();
+
+private:
+ enum WidgetMode { NormalWidget, MainContainer, PromotedWidget };
+
+ static WidgetMode widgetMode(QWidget *w, QDesignerFormWindowInterface *formWindow);
+ QPushButton *okButton();
+ void setOkButtonEnabled(bool);
+ void editSignalsSlots(QWidget *w, WidgetMode mode, int signalSlotDialogMode);
+
+ QWidget *m_source;
+ QWidget *m_destination;
+ const WidgetMode m_sourceMode;
+ const WidgetMode m_destinationMode;
+ QDesignerFormWindowInterface *m_formWindow;
+ Ui::ConnectDialog m_ui;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // CONNECTDIALOG_H
diff --git a/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp
new file mode 100644
index 0000000000..f4c7693f78
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalslot_utils.cpp
@@ -0,0 +1,331 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "signalslot_utils_p.h"
+
+#include <qdesigner_membersheet_p.h>
+#include <widgetdatabase_p.h>
+#include <metadatabase_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerLanguageExtension>
+
+#include <QtCore/QPair>
+
+QT_BEGIN_NAMESPACE
+
+typedef QPair<QString, QString> ClassNameSignaturePair;
+
+// Find all member functions that match a predicate on the signature string
+// using the member sheet and the fake methods stored in the widget
+// database and the meta data base.
+// Assign a pair of <classname, signature> to OutputIterator.
+
+template <class SignaturePredicate, class OutputIterator>
+static void memberList(QDesignerFormEditorInterface *core,
+ QObject *object,
+ qdesigner_internal::MemberType member_type,
+ bool showAll,
+ SignaturePredicate predicate,
+ OutputIterator it)
+{
+ if (!object)
+ return;
+
+ // 1) member sheet
+ const QDesignerMemberSheetExtension *members = qt_extension<QDesignerMemberSheetExtension*>(core->extensionManager(), object);
+ Q_ASSERT(members != 0);
+ const int count = members->count();
+ for (int i = 0; i < count; ++i) {
+ if (!members->isVisible(i))
+ continue;
+
+ if (member_type == qdesigner_internal::SignalMember && !members->isSignal(i))
+ continue;
+
+ if (member_type == qdesigner_internal::SlotMember && !members->isSlot(i))
+ continue;
+
+ if (!showAll && members->inheritedFromWidget(i))
+ continue;
+
+ const QString signature = members->signature(i);
+ if (predicate(signature)) {
+ *it = ClassNameSignaturePair(members->declaredInClass(i), signature);
+ ++it;
+ }
+ }
+ // 2) fake slots from widget DB
+ const qdesigner_internal::WidgetDataBase *wdb = qobject_cast<qdesigner_internal::WidgetDataBase *>(core->widgetDataBase());
+ if (!wdb)
+ return;
+ const int idx = wdb->indexOfObject(object);
+ Q_ASSERT(idx != -1);
+ // get the promoted class name
+ const qdesigner_internal::WidgetDataBaseItem *wdbItem = static_cast<qdesigner_internal::WidgetDataBaseItem *>(wdb->item(idx));
+ const QString className = wdbItem->name();
+
+ const QStringList wdbFakeMethods = member_type == qdesigner_internal::SlotMember ? wdbItem->fakeSlots() : wdbItem->fakeSignals();
+ if (!wdbFakeMethods.empty())
+ foreach (const QString &fakeMethod, wdbFakeMethods)
+ if (predicate(fakeMethod)) {
+ *it = ClassNameSignaturePair(className, fakeMethod);
+ ++it;
+ }
+ // 3) fake slots from meta DB
+ qdesigner_internal::MetaDataBase *metaDataBase = qobject_cast<qdesigner_internal::MetaDataBase *>(core->metaDataBase());
+ if (!metaDataBase)
+ return;
+
+ const qdesigner_internal::MetaDataBaseItem *mdbItem = metaDataBase->metaDataBaseItem(object);
+ Q_ASSERT(mdbItem);
+ const QStringList mdbFakeMethods = member_type == qdesigner_internal::SlotMember ? mdbItem->fakeSlots() : mdbItem->fakeSignals();
+ if (!mdbFakeMethods.empty())
+ foreach (const QString &fakeMethod, mdbFakeMethods)
+ if (predicate(fakeMethod)) {
+ *it = ClassNameSignaturePair(className, fakeMethod);
+ ++it;
+ }
+}
+
+namespace {
+ // Predicate that matches the exact signature string
+ class EqualsPredicate {
+ public:
+ EqualsPredicate(const QString &pattern) : m_pattern(pattern) {}
+ bool operator()(const QString &s) const { return s == m_pattern; }
+ private:
+ const QString m_pattern;
+ };
+ // Predicate for a QString member signature that matches signals up with slots and vice versa
+ class SignalMatchesSlotPredicate {
+ public:
+ SignalMatchesSlotPredicate(QDesignerFormEditorInterface *core, const QString &peer, qdesigner_internal::MemberType memberType);
+ bool operator()(const QString &s) const;
+
+ private:
+ bool signalMatchesSlot(const QString &signal, const QString &slot) const;
+
+ const QString m_peer;
+ qdesigner_internal::MemberType m_memberType;
+ const QDesignerLanguageExtension *m_lang;
+ };
+
+ SignalMatchesSlotPredicate::SignalMatchesSlotPredicate(QDesignerFormEditorInterface *core, const QString &peer, qdesigner_internal::MemberType memberType) :
+ m_peer(peer),
+ m_memberType(memberType),
+ m_lang(qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core))
+ {
+ }
+
+ bool SignalMatchesSlotPredicate::operator()(const QString &s) const
+ {
+ return m_memberType == qdesigner_internal::SlotMember ? signalMatchesSlot(m_peer, s) : signalMatchesSlot(s, m_peer);
+ }
+
+ bool SignalMatchesSlotPredicate::signalMatchesSlot(const QString &signal, const QString &slot) const
+ {
+ if (m_lang)
+ return m_lang->signalMatchesSlot(signal, slot);
+
+ return QDesignerMemberSheet::signalMatchesSlot(signal, slot);
+ }
+
+ // Output iterator for a pair of pair of <classname, signature>
+ // that builds the reverse class list for reverseClassesMemberFunctions()
+ // (for the combos of the ToolWindow)
+ class ReverseClassesMemberIterator {
+ public:
+ ReverseClassesMemberIterator(qdesigner_internal::ClassesMemberFunctions *result);
+
+ ReverseClassesMemberIterator &operator*() { return *this; }
+ ReverseClassesMemberIterator &operator++(int) { return *this; }
+ ReverseClassesMemberIterator &operator++() { return *this; }
+ void operator=(const ClassNameSignaturePair &classNameSignature);
+
+ private:
+ qdesigner_internal::ClassesMemberFunctions *m_result;
+ QString m_lastClassName;
+ QStringList *m_memberList;
+ };
+
+ ReverseClassesMemberIterator::ReverseClassesMemberIterator(qdesigner_internal::ClassesMemberFunctions *result) :
+ m_result(result),
+ m_memberList(0)
+ {
+ }
+
+ void ReverseClassesMemberIterator::operator=(const ClassNameSignaturePair &classNameSignature)
+ {
+ // prepend a new entry if class changes
+ if (!m_memberList || classNameSignature.first != m_lastClassName) {
+ m_lastClassName = classNameSignature.first;
+ m_result->push_front(qdesigner_internal::ClassMemberFunctions(m_lastClassName));
+ m_memberList = &(m_result->front().m_memberList);
+ }
+ m_memberList->push_back(classNameSignature.second);
+ }
+
+ // Output iterator for a pair of pair of <classname, signature>
+ // that adds the signatures to a string list
+ class SignatureIterator {
+ public:
+ SignatureIterator(QMap<QString, QString> *result) : m_result(result) {}
+
+ SignatureIterator &operator*() { return *this; }
+ SignatureIterator &operator++(int) { return *this; }
+ SignatureIterator &operator++() { return *this; }
+ void operator=(const ClassNameSignaturePair &classNameSignature) {
+ m_result->insert(classNameSignature.second, classNameSignature.first);
+ }
+
+ private:
+ QMap<QString, QString> *m_result;
+ };
+}
+
+static inline bool truePredicate(const QString &) { return true; }
+
+namespace qdesigner_internal {
+
+ ClassMemberFunctions::ClassMemberFunctions(const QString &class_name) :
+ m_className(class_name)
+ {
+ }
+
+ bool signalMatchesSlot(QDesignerFormEditorInterface *core, const QString &signal, const QString &slot)
+ {
+ const SignalMatchesSlotPredicate predicate(core, signal, qdesigner_internal::SlotMember);
+ return predicate(slot);
+ }
+
+ // return classes and members in reverse class order to
+ // populate of the combo of the ToolWindow
+ ClassesMemberFunctions reverseClassesMemberFunctions(const QString &obj_name, MemberType member_type,
+ const QString &peer, QDesignerFormWindowInterface *form)
+ {
+ QObject *object = qFindChild<QObject*>(form, obj_name);
+ if (!object)
+ return ClassesMemberFunctions();
+
+ QDesignerFormEditorInterface *core = form->core();
+
+ ClassesMemberFunctions rc;
+ memberList(form->core(), object, member_type, true, SignalMatchesSlotPredicate(core, peer, member_type),
+ ReverseClassesMemberIterator(&rc));
+ return rc;
+ }
+
+ QMap<QString, QString> getSignals(QDesignerFormEditorInterface *core, QObject *object, bool showAll)
+ {
+ QMap<QString, QString> rc;
+ memberList(core, object, SignalMember, showAll, truePredicate, SignatureIterator(&rc));
+ return rc;
+ }
+
+ bool isQt3Signal(QDesignerFormEditorInterface *core,
+ QObject *object, const QString &signalSignature)
+ {
+ if (const QDesignerMemberSheetExtension *members
+ = qt_extension<QDesignerMemberSheetExtension*>(core->extensionManager(), object)) {
+ const int count = members->count();
+ for (int i = 0; i < count; ++i)
+ if (members->isSignal(i) && members->signature(i) == signalSignature) {
+ const QDesignerMemberSheet *memberSheet
+ = qobject_cast<QDesignerMemberSheet*>(core->extensionManager()->extension(object,
+ Q_TYPEID(QDesignerMemberSheetExtension)));
+ return memberSheet->isQt3Signal(i);
+ }
+ }
+
+ return false;
+ }
+
+ bool isQt3Slot(QDesignerFormEditorInterface *core,
+ QObject *object, const QString &slotSignature)
+ {
+ if (const QDesignerMemberSheetExtension *members
+ = qt_extension<QDesignerMemberSheetExtension*>(core->extensionManager(), object)) {
+ Q_ASSERT(members != 0);
+ const int count = members->count();
+ for (int i = 0; i < count; ++i)
+ if (members->isSlot(i) && members->signature(i) == slotSignature) {
+ const QDesignerMemberSheet *memberSheet
+ = qobject_cast<QDesignerMemberSheet*>(core->extensionManager()->extension(object,
+ Q_TYPEID(QDesignerMemberSheetExtension)));
+ return memberSheet->isQt3Slot(i);
+ }
+ }
+ return false;
+ }
+
+ QMap<QString, QString> getMatchingSlots(QDesignerFormEditorInterface *core, QObject *object, const QString &signalSignature, bool showAll)
+ {
+ QMap<QString, QString> rc;
+ memberList(core, object, SlotMember, showAll, SignalMatchesSlotPredicate(core, signalSignature, qdesigner_internal::SlotMember), SignatureIterator(&rc));
+ return rc;
+ }
+
+ bool memberFunctionListContains(QDesignerFormEditorInterface *core, QObject *object, MemberType type, const QString &signature)
+ {
+ QMap<QString, QString> rc;
+ memberList(core, object, type, true, EqualsPredicate(signature), SignatureIterator(&rc));
+ return !rc.empty();
+ }
+
+ // ### deprecated
+ QString realObjectName(QDesignerFormEditorInterface *core, QObject *object)
+ {
+ if (!object)
+ return QString();
+
+ const QDesignerMetaDataBaseInterface *mdb = core->metaDataBase();
+ if (const QDesignerMetaDataBaseItemInterface *item = mdb->item(object))
+ return item->name();
+
+ return object->objectName();
+ }
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/signalsloteditor/signalslot_utils_p.h b/tools/designer/src/components/signalsloteditor/signalslot_utils_p.h
new file mode 100644
index 0000000000..9b051e4653
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalslot_utils_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTUTILS_P_H
+#define SIGNALSLOTUTILS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+enum MemberType { SignalMember, SlotMember };
+
+// member to class name
+QMap<QString, QString> getSignals(QDesignerFormEditorInterface *core, QObject *object, bool showAll);
+QMap<QString, QString> getMatchingSlots(QDesignerFormEditorInterface *core, QObject *object,
+ const QString &signalSignature, bool showAll);
+
+bool memberFunctionListContains(QDesignerFormEditorInterface *core, QObject *object, MemberType type, const QString &signature);
+
+// Members functions listed by class they were inherited from
+struct ClassMemberFunctions
+{
+ ClassMemberFunctions() {}
+ ClassMemberFunctions(const QString &_class_name);
+
+ QString m_className;
+ QStringList m_memberList;
+};
+
+typedef QList<ClassMemberFunctions> ClassesMemberFunctions;
+
+// Return classes and members in reverse class order to
+// populate of the combo of the ToolWindow.
+
+ClassesMemberFunctions reverseClassesMemberFunctions(const QString &obj_name, MemberType member_type,
+ const QString &peer, QDesignerFormWindowInterface *form);
+
+bool signalMatchesSlot(QDesignerFormEditorInterface *core, const QString &signal, const QString &slot);
+
+QString realObjectName(QDesignerFormEditorInterface *core, QObject *object);
+
+bool isQt3Signal(QDesignerFormEditorInterface *core, QObject *object, const QString &signalSignature);
+bool isQt3Slot(QDesignerFormEditorInterface *core, QObject *object, const QString &signalSignature);
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SIGNALSLOTUTILS_P_H
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp
new file mode 100644
index 0000000000..511b91fd7b
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor.cpp
@@ -0,0 +1,528 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "signalsloteditor.h"
+#include "signalsloteditor_p.h"
+#include "connectdialog_p.h"
+#include "signalslot_utils_p.h"
+
+#include <metadatabase_p.h>
+#include <ui4_p.h>
+#include <qdesigner_formwindowcommand_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+
+#include <QtGui/QApplication>
+#include <QtGui/QUndoCommand>
+#include <QtGui/QMenu>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+/*******************************************************************************
+** SignalSlotConnection
+*/
+
+SignalSlotConnection::SignalSlotConnection(ConnectionEdit *edit, QWidget *source, QWidget *target)
+ : Connection(edit, source, target)
+{
+}
+
+DomConnection *SignalSlotConnection::toUi() const
+{
+ DomConnection *result = new DomConnection;
+
+ result->setElementSender(sender());
+ result->setElementSignal(signal());
+ result->setElementReceiver(receiver());
+ result->setElementSlot(slot());
+
+ DomConnectionHints *hints = new DomConnectionHints;
+ QList<DomConnectionHint*> list;
+
+ QPoint sp = endPointPos(EndPoint::Source);
+ QPoint tp = endPointPos(EndPoint::Target);
+
+ DomConnectionHint *hint = new DomConnectionHint;
+ hint->setAttributeType(QLatin1String("sourcelabel"));
+ hint->setElementX(sp.x());
+ hint->setElementY(sp.y());
+ list.append(hint);
+
+ hint = new DomConnectionHint;
+ hint->setAttributeType(QLatin1String("destinationlabel"));
+ hint->setElementX(tp.x());
+ hint->setElementY(tp.y());
+ list.append(hint);
+
+ hints->setElementHint(list);
+ result->setElementHints(hints);
+
+ return result;
+}
+
+void SignalSlotConnection::setSignal(const QString &signal)
+{
+ m_signal = signal;
+ setLabel(EndPoint::Source, m_signal);
+}
+
+void SignalSlotConnection::setSlot(const QString &slot)
+{
+ m_slot = slot;
+ setLabel(EndPoint::Target, m_slot);
+}
+
+QString SignalSlotConnection::sender() const
+{
+ QObject *source = object(EndPoint::Source);
+ if (!source)
+ return QString();
+
+ SignalSlotEditor *edit = qobject_cast<SignalSlotEditor*>(this->edit());
+ Q_ASSERT(edit != 0);
+
+ return realObjectName(edit->formWindow()->core(), source);
+}
+
+QString SignalSlotConnection::receiver() const
+{
+ QObject *sink = object(EndPoint::Target);
+ if (!sink)
+ return QString();
+
+ SignalSlotEditor *edit = qobject_cast<SignalSlotEditor*>(this->edit());
+ Q_ASSERT(edit != 0);
+ return realObjectName(edit->formWindow()->core(), sink);
+}
+
+void SignalSlotConnection::updateVisibility()
+{
+ Connection::updateVisibility();
+ if (isVisible() && (signal().isEmpty() || slot().isEmpty()))
+ setVisible(false);
+}
+
+QString SignalSlotConnection::toString() const
+{
+ return QCoreApplication::translate("SignalSlotConnection", "SENDER(%1), SIGNAL(%2), RECEIVER(%3), SLOT(%4)")
+ .arg(sender()).arg(signal()).arg(receiver()).arg(slot());
+}
+
+SignalSlotConnection::State SignalSlotConnection::isValid(const QWidget *background) const
+{
+ const QObject *source = object(EndPoint::Source);
+ if (!source)
+ return ObjectDeleted;
+
+ const QObject *target = object(EndPoint::Target);
+ if (!target)
+ return ObjectDeleted;
+
+ if (m_slot.isEmpty() || m_signal.isEmpty())
+ return InvalidMethod;
+
+ if (const QWidget *sourceWidget = qobject_cast<const QWidget*>(source))
+ if (!background->isAncestorOf(sourceWidget))
+ return NotAncestor;
+
+ if (const QWidget *targetWidget = qobject_cast<const QWidget*>(target))
+ if (!background->isAncestorOf(targetWidget))
+ return NotAncestor;
+
+ return Valid;
+}
+
+/*******************************************************************************
+** Commands
+*/
+
+class SetMemberCommand : public QUndoCommand, public CETypes
+{
+public:
+ SetMemberCommand(SignalSlotConnection *con, EndPoint::Type type,
+ const QString &member, SignalSlotEditor *editor);
+ virtual void redo();
+ virtual void undo();
+private:
+ const QString m_old_member;
+ const QString m_new_member;
+ const EndPoint::Type m_type;
+ SignalSlotConnection *m_con;
+ SignalSlotEditor *m_editor;
+};
+
+SetMemberCommand::SetMemberCommand(SignalSlotConnection *con, EndPoint::Type type,
+ const QString &member, SignalSlotEditor *editor) :
+ m_old_member(type == EndPoint::Source ? con->signal() : con->slot()),
+ m_new_member(member),
+ m_type(type),
+ m_con(con),
+ m_editor(editor)
+{
+ if (type == EndPoint::Source)
+ setText(QApplication::translate("Command", "Change signal"));
+ else
+ setText(QApplication::translate("Command", "Change slot"));
+}
+
+void SetMemberCommand::redo()
+{
+ m_con->update();
+ if (m_type == EndPoint::Source)
+ m_con->setSignal(m_new_member);
+ else
+ m_con->setSlot(m_new_member);
+ m_con->update();
+ emit m_editor->connectionChanged(m_con);
+}
+
+void SetMemberCommand::undo()
+{
+ m_con->update();
+ if (m_type == EndPoint::Source)
+ m_con->setSignal(m_old_member);
+ else
+ m_con->setSlot(m_old_member);
+ m_con->update();
+ emit m_editor->connectionChanged(m_con);
+}
+
+// Command to modify a connection
+class ModifyConnectionCommand : public QDesignerFormWindowCommand
+{
+public:
+ explicit ModifyConnectionCommand(QDesignerFormWindowInterface *form,
+ SignalSlotConnection *conn,
+ const QString &newSignal,
+ const QString &newSlot);
+ virtual void redo();
+ virtual void undo();
+
+private:
+ SignalSlotConnection *m_conn;
+ const QString m_oldSignal;
+ const QString m_oldSlot;
+ const QString m_newSignal;
+ const QString m_newSlot;
+};
+
+ModifyConnectionCommand::ModifyConnectionCommand(QDesignerFormWindowInterface *form,
+ SignalSlotConnection *conn,
+ const QString &newSignal,
+ const QString &newSlot) :
+ QDesignerFormWindowCommand(QCoreApplication::translate("Command", "Change signal-slot connection"), form),
+ m_conn(conn),
+ m_oldSignal(conn->signal()),
+ m_oldSlot(conn->slot()),
+ m_newSignal(newSignal),
+ m_newSlot(newSlot)
+{
+}
+
+void ModifyConnectionCommand::redo()
+{
+ m_conn->setSignal(m_newSignal);
+ m_conn->setSlot(m_newSlot);
+}
+
+void ModifyConnectionCommand::undo()
+{
+ m_conn->setSignal(m_oldSignal);
+ m_conn->setSlot(m_oldSlot);
+}
+
+/*******************************************************************************
+** SignalSlotEditor
+*/
+
+SignalSlotEditor::SignalSlotEditor(QDesignerFormWindowInterface *form_window, QWidget *parent) :
+ ConnectionEdit(parent, form_window),
+ m_form_window(form_window),
+ m_showAllSignalsSlots(false)
+{
+}
+
+void SignalSlotEditor::modifyConnection(Connection *con)
+{
+ SignalSlotConnection *sigslot_con = static_cast<SignalSlotConnection*>(con);
+ ConnectDialog dialog(m_form_window,
+ sigslot_con->widget(EndPoint::Source),
+ sigslot_con->widget(EndPoint::Target),
+ m_form_window->core()->topLevel());
+
+ dialog.setSignalSlot(sigslot_con->signal(), sigslot_con->slot());
+ dialog.setShowAllSignalsSlots(m_showAllSignalsSlots);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ const QString newSignal = dialog.signal();
+ const QString newSlot = dialog.slot();
+ if (sigslot_con->signal() != newSignal || sigslot_con->slot() != newSlot) {
+ ModifyConnectionCommand *cmd = new ModifyConnectionCommand(m_form_window, sigslot_con, newSignal, newSlot);
+ m_form_window->commandHistory()->push(cmd);
+ }
+ }
+
+ m_showAllSignalsSlots = dialog.showAllSignalsSlots();
+}
+
+Connection *SignalSlotEditor::createConnection(QWidget *source, QWidget *destination)
+{
+ SignalSlotConnection *con = 0;
+
+ Q_ASSERT(source != 0);
+ Q_ASSERT(destination != 0);
+
+ ConnectDialog dialog(m_form_window, source, destination, m_form_window->core()->topLevel());
+ dialog.setShowAllSignalsSlots(m_showAllSignalsSlots);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ con = new SignalSlotConnection(this, source, destination);
+ con->setSignal(dialog.signal());
+ con->setSlot(dialog.slot());
+ }
+
+ m_showAllSignalsSlots = dialog.showAllSignalsSlots();
+
+ return con;
+}
+
+DomConnections *SignalSlotEditor::toUi() const
+{
+ DomConnections *result = new DomConnections;
+ QList<DomConnection*> list;
+
+ const int count = connectionCount();
+ for (int i = 0; i < count; ++i) {
+ const SignalSlotConnection *con = static_cast<const SignalSlotConnection*>(connection(i));
+ Q_ASSERT(con != 0);
+
+ // If a widget's parent has been removed or moved to a different form,
+ // and the parent was not a managed widget
+ // (a page in a tab widget), we never get a widgetRemoved(). So we filter out
+ // these child widgets here (check QPointer and verify ancestor).
+ // Also, the user might demote a promoted widget or remove a fake
+ // slot in the editor, which causes the connection to become invalid
+ // once he doubleclicks on the method combo.
+ switch (con->isValid(background())) {
+ case SignalSlotConnection::Valid:
+ list.append(con->toUi());
+ break;
+ case SignalSlotConnection::ObjectDeleted:
+ case SignalSlotConnection::InvalidMethod:
+ case SignalSlotConnection::NotAncestor:
+ break;
+ }
+ }
+ result->setElementConnection(list);
+ return result;
+}
+
+QObject *SignalSlotEditor::objectByName(QWidget *topLevel, const QString &name) const
+{
+ if (name.isEmpty())
+ return 0;
+
+ Q_ASSERT(topLevel);
+ QObject *object = 0;
+ if (topLevel->objectName() == name)
+ object = topLevel;
+ else
+ object = qFindChild<QObject*>(topLevel, name);
+ const QDesignerMetaDataBaseInterface *mdb = formWindow()->core()->metaDataBase();
+ if (mdb->item(object))
+ return object;
+ return 0;
+}
+
+void SignalSlotEditor::fromUi(const DomConnections *connections, QWidget *parent)
+{
+ if (connections == 0)
+ return;
+
+ setBackground(parent);
+ clear();
+ const QList<DomConnection*> list = connections->elementConnection();
+ foreach (const DomConnection *dom_con, list) {
+ QObject *source = objectByName(parent, dom_con->elementSender());
+ if (source == 0) {
+ qDebug("SignalSlotEditor::fromUi(): no source widget called \"%s\"",
+ dom_con->elementSender().toUtf8().constData());
+ continue;
+ }
+ QObject *destination = objectByName(parent, dom_con->elementReceiver());
+ if (destination == 0) {
+ qDebug("SignalSlotEditor::fromUi(): no destination widget called \"%s\"",
+ dom_con->elementReceiver().toUtf8().constData());
+ continue;
+ }
+
+ QPoint sp = QPoint(20, 20), tp = QPoint(20, 20);
+ const DomConnectionHints *dom_hints = dom_con->elementHints();
+ if (dom_hints != 0) {
+ QList<DomConnectionHint*> list = dom_hints->elementHint();
+ foreach (DomConnectionHint *hint, list) {
+ QString attr_type = hint->attributeType();
+ QPoint p = QPoint(hint->elementX(), hint->elementY());
+ if (attr_type == QLatin1String("sourcelabel"))
+ sp = p;
+ else if (attr_type == QLatin1String("destinationlabel"))
+ tp = p;
+ }
+ }
+
+ SignalSlotConnection *con = new SignalSlotConnection(this);
+
+ con->setEndPoint(EndPoint::Source, source, sp);
+ con->setEndPoint(EndPoint::Target, destination, tp);
+ con->setSignal(dom_con->elementSignal());
+ con->setSlot(dom_con->elementSlot());
+ addConnection(con);
+ }
+}
+
+static bool skipWidget(const QWidget *w)
+{
+ const QString name = QLatin1String(w->metaObject()->className());
+ if (name == QLatin1String("QDesignerWidget"))
+ return true;
+ if (name == QLatin1String("QLayoutWidget"))
+ return true;
+ if (name == QLatin1String("qdesigner_internal::FormWindow"))
+ return true;
+ if (name == QLatin1String("Spacer"))
+ return true;
+ return false;
+}
+
+QWidget *SignalSlotEditor::widgetAt(const QPoint &pos) const
+{
+ QWidget *widget = ConnectionEdit::widgetAt(pos);
+
+ if (widget == m_form_window->mainContainer())
+ return widget;
+
+ for (; widget != 0; widget = widget->parentWidget()) {
+ QDesignerMetaDataBaseItemInterface *item = m_form_window->core()->metaDataBase()->item(widget);
+ if (item == 0)
+ continue;
+ if (skipWidget(widget))
+ continue;
+ break;
+ }
+
+ return widget;
+}
+
+void SignalSlotEditor::setSignal(SignalSlotConnection *con, const QString &member)
+{
+ if (member == con->signal())
+ return;
+
+ m_form_window->beginCommand(QApplication::translate("Command", "Change signal"));
+ undoStack()->push(new SetMemberCommand(con, EndPoint::Source, member, this));
+ if (!signalMatchesSlot(m_form_window->core(), member, con->slot()))
+ undoStack()->push(new SetMemberCommand(con, EndPoint::Target, QString(), this));
+ m_form_window->endCommand();
+}
+
+void SignalSlotEditor::setSlot(SignalSlotConnection *con, const QString &member)
+{
+ if (member == con->slot())
+ return;
+
+ m_form_window->beginCommand(QApplication::translate("Command", "Change slot"));
+ undoStack()->push(new SetMemberCommand(con, EndPoint::Target, member, this));
+ if (!signalMatchesSlot(m_form_window->core(), con->signal(), member))
+ undoStack()->push(new SetMemberCommand(con, EndPoint::Source, QString(), this));
+ m_form_window->endCommand();
+}
+
+void SignalSlotEditor::setSource(Connection *_con, const QString &obj_name)
+{
+ SignalSlotConnection *con = static_cast<SignalSlotConnection*>(_con);
+
+ if (con->sender() == obj_name)
+ return;
+
+ m_form_window->beginCommand(QApplication::translate("Command", "Change sender"));
+ ConnectionEdit::setSource(con, obj_name);
+
+ QObject *sourceObject = con->object(EndPoint::Source);
+
+ if (!memberFunctionListContains(m_form_window->core(), sourceObject, SignalMember, con->signal()))
+ undoStack()->push(new SetMemberCommand(con, EndPoint::Source, QString(), this));
+
+ m_form_window->endCommand();
+}
+
+void SignalSlotEditor::setTarget(Connection *_con, const QString &obj_name)
+{
+ SignalSlotConnection *con = static_cast<SignalSlotConnection*>(_con);
+
+ if (con->receiver() == obj_name)
+ return;
+
+ m_form_window->beginCommand(QApplication::translate("Command", "Change receiver"));
+ ConnectionEdit::setTarget(con, obj_name);
+
+ QObject *targetObject = con->object(EndPoint::Target);
+ if (!memberFunctionListContains(m_form_window->core(), targetObject, SlotMember, con->slot()))
+ undoStack()->push(new SetMemberCommand(con, EndPoint::Target, QString(), this));
+
+ m_form_window->endCommand();
+}
+
+void SignalSlotEditor::addEmptyConnection()
+{
+ SignalSlotConnection *con = new SignalSlotConnection(this);
+ undoStack()->push(new AddConnectionCommand(this, con));
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor.h b/tools/designer/src/components/signalsloteditor/signalsloteditor.h
new file mode 100644
index 0000000000..f330ca0075
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_H
+#define SIGNALSLOTEDITOR_H
+
+#include "signalsloteditor_global.h"
+
+#include <QtDesigner/private/connectionedit_p.h>
+
+#include <QtXml/QDomDocument>
+#include <QtXml/QDomElement>
+
+QT_BEGIN_NAMESPACE
+
+class DomConnections;
+
+namespace qdesigner_internal {
+
+class SignalSlotConnection;
+
+class QT_SIGNALSLOTEDITOR_EXPORT SignalSlotEditor : public ConnectionEdit
+{
+ Q_OBJECT
+
+public:
+ SignalSlotEditor(QDesignerFormWindowInterface *form_window, QWidget *parent);
+
+ virtual void setSignal(SignalSlotConnection *con, const QString &member);
+ virtual void setSlot(SignalSlotConnection *con, const QString &member);
+ virtual void setSource(Connection *con, const QString &obj_name);
+ virtual void setTarget(Connection *con, const QString &obj_name);
+
+ DomConnections *toUi() const;
+ void fromUi(const DomConnections *connections, QWidget *parent);
+
+ QDesignerFormWindowInterface *formWindow() const { return m_form_window; }
+
+ QObject *objectByName(QWidget *topLevel, const QString &name) const;
+
+ void addEmptyConnection();
+
+protected:
+ virtual QWidget *widgetAt(const QPoint &pos) const;
+
+private:
+ virtual Connection *createConnection(QWidget *source, QWidget *destination);
+ virtual void modifyConnection(Connection *con);
+
+ QDesignerFormWindowInterface *m_form_window;
+ bool m_showAllSignalsSlots;
+
+ friend class SetMemberCommand;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SIGNALSLOTEDITOR_H
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor.pri b/tools/designer/src/components/signalsloteditor/signalsloteditor.pri
new file mode 100644
index 0000000000..e903ce114b
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor.pri
@@ -0,0 +1,21 @@
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/signalslot_utils_p.h \
+ $$PWD/connectdialog_p.h \
+ $$PWD/signalsloteditor.h \
+ $$PWD/signalsloteditor_tool.h \
+ $$PWD/signalsloteditor_plugin.h \
+ $$PWD/signalsloteditor_global.h \
+ $$PWD/signalsloteditor_p.h \
+ $$PWD/signalsloteditorwindow.h
+
+SOURCES += $$PWD/signalslot_utils.cpp \
+ $$PWD/connectdialog.cpp \
+ $$PWD/signalsloteditor.cpp \
+ $$PWD/signalsloteditor_tool.cpp \
+ $$PWD/signalsloteditor_plugin.cpp \
+ $$PWD/signalsloteditor_instance.cpp \
+ $$PWD/signalsloteditorwindow.cpp
+
+FORMS += $$PWD/connectdialog.ui
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_global.h b/tools/designer/src/components/signalsloteditor/signalsloteditor_global.h
new file mode 100644
index 0000000000..399778ab79
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_GLOBAL_H
+#define SIGNALSLOTEDITOR_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN
+#ifdef QT_SIGNALSLOTEDITOR_LIBRARY
+# define QT_SIGNALSLOTEDITOR_EXPORT
+#else
+# define QT_SIGNALSLOTEDITOR_EXPORT
+#endif
+#else
+#define QT_SIGNALSLOTEDITOR_EXPORT
+#endif
+
+#endif // SIGNALSLOTEDITOR_GLOBAL_H
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp
new file mode 100644
index 0000000000..c7a799af6a
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_instance.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qplugin.h>
+
+#include "signalsloteditor_plugin.h"
+
+QT_USE_NAMESPACE
+
+using namespace qdesigner_internal;
+
+Q_EXPORT_PLUGIN(SignalSlotEditorPlugin)
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_p.h b/tools/designer/src/components/signalsloteditor/signalsloteditor_p.h
new file mode 100644
index 0000000000..8cec010750
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_p.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_P_H
+#define SIGNALSLOTEDITOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+#include <QtCore/QAbstractItemModel>
+
+#include <connectionedit_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+class DomConnection;
+
+namespace qdesigner_internal {
+
+class SignalSlotEditor;
+
+class SignalSlotConnection : public Connection
+{
+public:
+ explicit SignalSlotConnection(ConnectionEdit *edit, QWidget *source = 0, QWidget *target = 0);
+
+ void setSignal(const QString &signal);
+ void setSlot(const QString &slot);
+
+ QString sender() const;
+ QString receiver() const;
+ inline QString signal() const { return m_signal; }
+ inline QString slot() const { return m_slot; }
+
+ DomConnection *toUi() const;
+
+ virtual void updateVisibility();
+
+ enum State { Valid, ObjectDeleted, InvalidMethod, NotAncestor };
+ State isValid(const QWidget *background) const;
+
+ // format for messages, etc.
+ QString toString() const;
+
+private:
+ QString m_signal, m_slot;
+};
+
+class ConnectionModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ explicit ConnectionModel(QObject *parent = 0);
+ void setEditor(SignalSlotEditor *editor = 0);
+
+ virtual QModelIndex index(int row, int column,
+ const QModelIndex &parent = QModelIndex()) const;
+ virtual QModelIndex parent(const QModelIndex &child) const;
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ virtual bool setData(const QModelIndex &index, const QVariant &data, int role = Qt::DisplayRole);
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+ virtual QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+
+ QModelIndex connectionToIndex(Connection *con) const;
+ Connection *indexToConnection(const QModelIndex &index) const;
+ void updateAll();
+
+private slots:
+ void connectionAdded(Connection *con);
+ void connectionRemoved(int idx);
+ void aboutToRemoveConnection(Connection *con);
+ void aboutToAddConnection(int idx);
+ void connectionChanged(Connection *con);
+
+private:
+ QPointer<SignalSlotEditor> m_editor;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SIGNALSLOTEDITOR_P_H
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp
new file mode 100644
index 0000000000..311c843648
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::SignalSlotEditorPlugin
+*/
+
+#include "signalsloteditor_plugin.h"
+#include "signalsloteditor_tool.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <QtGui/QAction>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+SignalSlotEditorPlugin::SignalSlotEditorPlugin()
+ : m_initialized(false), m_action(0)
+{
+}
+
+SignalSlotEditorPlugin::~SignalSlotEditorPlugin()
+{
+}
+
+bool SignalSlotEditorPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void SignalSlotEditorPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_ASSERT(!isInitialized());
+
+ m_action = new QAction(tr("Edit Signals/Slots"), this);
+ m_action->setObjectName(QLatin1String("__qt_edit_signals_slots_action"));
+ m_action->setShortcut(tr("F4"));
+ QIcon icon(QIcon(core->resourceLocation() + QLatin1String("/signalslottool.png")));
+ m_action->setIcon(icon);
+ m_action->setEnabled(false);
+
+ setParent(core);
+ m_core = core;
+ m_initialized = true;
+
+ connect(core->formWindowManager(), SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)),
+ this, SLOT(addFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(formWindowRemoved(QDesignerFormWindowInterface*)),
+ this, SLOT(removeFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
+}
+
+QDesignerFormEditorInterface *SignalSlotEditorPlugin::core() const
+{
+ return m_core;
+}
+
+void SignalSlotEditorPlugin::addFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tools.contains(formWindow) == false);
+
+ SignalSlotEditorTool *tool = new SignalSlotEditorTool(formWindow, this);
+ connect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+ m_tools[formWindow] = tool;
+ formWindow->registerTool(tool);
+}
+
+void SignalSlotEditorPlugin::removeFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tools.contains(formWindow) == true);
+
+ SignalSlotEditorTool *tool = m_tools.value(formWindow);
+ m_tools.remove(formWindow);
+ disconnect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+ // ### FIXME disable the tool
+
+ delete tool;
+}
+
+QAction *SignalSlotEditorPlugin::action() const
+{
+ return m_action;
+}
+
+void SignalSlotEditorPlugin::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+{
+ m_action->setEnabled(formWindow != 0);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.h b/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.h
new file mode 100644
index 0000000000..546110de11
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_plugin.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_PLUGIN_H
+#define SIGNALSLOTEDITOR_PLUGIN_H
+
+#include "signalsloteditor_global.h"
+
+#include <QtDesigner/QDesignerFormEditorPluginInterface>
+
+#include <QtCore/QPointer>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class SignalSlotEditorTool;
+
+class QT_SIGNALSLOTEDITOR_EXPORT SignalSlotEditorPlugin: public QObject, public QDesignerFormEditorPluginInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerFormEditorPluginInterface)
+public:
+ SignalSlotEditorPlugin();
+ virtual ~SignalSlotEditorPlugin();
+
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QAction *action() const;
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+public slots:
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+
+private slots:
+ void addFormWindow(QDesignerFormWindowInterface *formWindow);
+ void removeFormWindow(QDesignerFormWindowInterface *formWindow);
+
+private:
+ QPointer<QDesignerFormEditorInterface> m_core;
+ QHash<QDesignerFormWindowInterface*, SignalSlotEditorTool*> m_tools;
+ bool m_initialized;
+ QAction *m_action;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SIGNALSLOTEDITOR_PLUGIN_H
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp
new file mode 100644
index 0000000000..973105c6ab
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_tool.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::SignalSlotEditorTool
+*/
+
+#include "signalsloteditor_tool.h"
+#include "signalsloteditor.h"
+#include "ui4_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+SignalSlotEditorTool::SignalSlotEditorTool(QDesignerFormWindowInterface *formWindow, QObject *parent)
+ : QDesignerFormWindowToolInterface(parent),
+ m_formWindow(formWindow),
+ m_action(new QAction(tr("Edit Signals/Slots"), this))
+{
+}
+
+SignalSlotEditorTool::~SignalSlotEditorTool()
+{
+}
+
+QDesignerFormEditorInterface *SignalSlotEditorTool::core() const
+{
+ return m_formWindow->core();
+}
+
+QDesignerFormWindowInterface *SignalSlotEditorTool::formWindow() const
+{
+ return m_formWindow;
+}
+
+bool SignalSlotEditorTool::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event)
+{
+ Q_UNUSED(widget);
+ Q_UNUSED(managedWidget);
+ Q_UNUSED(event);
+
+ return false;
+}
+
+QWidget *SignalSlotEditorTool::editor() const
+{
+ if (!m_editor) {
+ Q_ASSERT(formWindow() != 0);
+ m_editor = new qdesigner_internal::SignalSlotEditor(formWindow(), 0);
+ connect(formWindow(), SIGNAL(mainContainerChanged(QWidget*)), m_editor, SLOT(setBackground(QWidget*)));
+ connect(formWindow(), SIGNAL(changed()),
+ m_editor, SLOT(updateBackground()));
+ }
+
+ return m_editor;
+}
+
+QAction *SignalSlotEditorTool::action() const
+{
+ return m_action;
+}
+
+void SignalSlotEditorTool::activated()
+{
+ m_editor->enableUpdateBackground(true);
+}
+
+void SignalSlotEditorTool::deactivated()
+{
+ m_editor->enableUpdateBackground(false);
+}
+
+void SignalSlotEditorTool::saveToDom(DomUI *ui, QWidget*)
+{
+ ui->setElementConnections(m_editor->toUi());
+}
+
+void SignalSlotEditorTool::loadFromDom(DomUI *ui, QWidget *mainContainer)
+{
+ m_editor->fromUi(ui->elementConnections(), mainContainer);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditor_tool.h b/tools/designer/src/components/signalsloteditor/signalsloteditor_tool.h
new file mode 100644
index 0000000000..97ea831822
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditor_tool.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITOR_TOOL_H
+#define SIGNALSLOTEDITOR_TOOL_H
+
+#include "signalsloteditor_global.h"
+#include "signalsloteditor.h"
+
+#include <QtCore/QPointer>
+#include <QtDesigner/QDesignerFormWindowToolInterface>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QAction;
+
+namespace qdesigner_internal {
+
+class SignalSlotEditor;
+
+class QT_SIGNALSLOTEDITOR_EXPORT SignalSlotEditorTool: public QDesignerFormWindowToolInterface
+{
+ Q_OBJECT
+public:
+ explicit SignalSlotEditorTool(QDesignerFormWindowInterface *formWindow, QObject *parent = 0);
+ virtual ~SignalSlotEditorTool();
+
+ virtual QDesignerFormEditorInterface *core() const;
+ virtual QDesignerFormWindowInterface *formWindow() const;
+
+ virtual QWidget *editor() const;
+
+ QAction *action() const;
+
+ virtual void activated();
+ virtual void deactivated();
+
+ virtual bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event);
+
+ virtual void saveToDom(DomUI *ui, QWidget *mainContainer);
+ virtual void loadFromDom(DomUI *ui, QWidget *mainContainer);
+
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+ mutable QPointer<qdesigner_internal::SignalSlotEditor> m_editor;
+ QAction *m_action;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SIGNALSLOTEDITOR_TOOL_H
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp
new file mode 100644
index 0000000000..dc6b3c3313
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.cpp
@@ -0,0 +1,859 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ConnectionModel
+*/
+
+#include "signalsloteditorwindow.h"
+#include "signalsloteditor_p.h"
+#include "signalsloteditor.h"
+#include "qdesigner_integration_p.h"
+#include "signalslot_utils_p.h"
+
+#include <iconloader_p.h>
+#include <spacer_widget_p.h>
+#include <qlayout_widget_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <abstractdialoggui_p.h>
+
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QDebug>
+#include <QtGui/QAction>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QMenu>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QComboBox>
+#include <QtGui/QApplication>
+#include <QtGui/QItemDelegate>
+#include <QtGui/QItemEditorFactory>
+#include <QtGui/QTreeView>
+#include <QtGui/QHeaderView>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QToolButton>
+#include <QtGui/QButtonGroup>
+
+QT_BEGIN_NAMESPACE
+
+// Add suitable form widgets to a list of objects for the signal slot
+// editor. Prevent special widgets from showing up there.
+static void addWidgetToObjectList(const QWidget *w, QStringList &r)
+{
+ const QMetaObject *mo = w->metaObject();
+ if (mo != &QLayoutWidget::staticMetaObject && mo != &Spacer::staticMetaObject) {
+ const QString name = w->objectName().trimmed();
+ if (!name.isEmpty())
+ r.push_back(name);
+ }
+}
+
+static QStringList objectNameList(QDesignerFormWindowInterface *form)
+{
+ typedef QList<QAction*> ActionList;
+ typedef QList<QButtonGroup *> ButtonGroupList;
+
+ QStringList result;
+
+ QWidget *mainContainer = form->mainContainer();
+ if (!mainContainer)
+ return result;
+
+ // Add main container container pages (QStatusBar, QWizardPages) etc.
+ // to the list. Pages of containers on the form are not added, however.
+ if (const QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension *>(form->core()->extensionManager(), mainContainer)) {
+ const int count = c->count();
+ for (int i = 0 ; i < count; i++)
+ addWidgetToObjectList(c->widget(i), result);
+ }
+
+ const QDesignerFormWindowCursorInterface *cursor = form->cursor();
+ const int widgetCount = cursor->widgetCount();
+ for (int i = 0; i < widgetCount; ++i)
+ addWidgetToObjectList(cursor->widget(i), result);
+
+ const QDesignerMetaDataBaseInterface *mdb = form->core()->metaDataBase();
+
+ // Add managed actions and actions with managed menus
+ const ActionList actions = qFindChildren<QAction*>(mainContainer);
+ if (!actions.empty()) {
+ const ActionList::const_iterator cend = actions.constEnd();
+ for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) {
+ QAction *a = *it;
+ if (!a->isSeparator()) {
+ if (QMenu *menu = a->menu()) {
+ if (mdb->item(menu))
+ result.push_back(menu->objectName());
+ } else {
+ if (mdb->item(a))
+ result.push_back(a->objectName());
+ }
+ }
+ }
+ }
+
+ // Add managed buttons groups
+ const ButtonGroupList buttonGroups = qFindChildren<QButtonGroup *>(mainContainer);
+ if (!buttonGroups.empty()) {
+ const ButtonGroupList::const_iterator cend = buttonGroups.constEnd();
+ for (ButtonGroupList::const_iterator it = buttonGroups.constBegin(); it != cend; ++it)
+ if (mdb->item(*it))
+ result.append((*it)->objectName());
+ }
+
+ result.sort();
+ return result;
+}
+
+namespace qdesigner_internal {
+
+// ------------ ConnectionModel
+
+ConnectionModel::ConnectionModel(QObject *parent) :
+ QAbstractItemModel(parent)
+{
+}
+
+void ConnectionModel::setEditor(SignalSlotEditor *editor)
+{
+ if (m_editor == editor)
+ return;
+
+ if (m_editor) {
+ disconnect(m_editor, SIGNAL(connectionAdded(Connection*)),
+ this, SLOT(connectionAdded(Connection*)));
+ disconnect(m_editor, SIGNAL(connectionRemoved(int)),
+ this, SLOT(connectionRemoved(int)));
+ disconnect(m_editor, SIGNAL(aboutToRemoveConnection(Connection*)),
+ this, SLOT(aboutToRemoveConnection(Connection*)));
+ disconnect(m_editor, SIGNAL(aboutToAddConnection(int)),
+ this, SLOT(aboutToAddConnection(int)));
+ disconnect(m_editor, SIGNAL(connectionChanged(Connection*)),
+ this, SLOT(connectionChanged(Connection*)));
+ }
+ m_editor = editor;
+ if (m_editor) {
+ connect(m_editor, SIGNAL(connectionAdded(Connection*)),
+ this, SLOT(connectionAdded(Connection*)));
+ connect(m_editor, SIGNAL(connectionRemoved(int)),
+ this, SLOT(connectionRemoved(int)));
+ connect(m_editor, SIGNAL(aboutToRemoveConnection(Connection*)),
+ this, SLOT(aboutToRemoveConnection(Connection*)));
+ connect(m_editor, SIGNAL(aboutToAddConnection(int)),
+ this, SLOT(aboutToAddConnection(int)));
+ connect(m_editor, SIGNAL(connectionChanged(Connection*)),
+ this, SLOT(connectionChanged(Connection*)));
+ }
+ reset();
+}
+
+QVariant ConnectionModel::headerData(int section, Qt::Orientation orientation,
+ int role) const
+{
+ if (orientation == Qt::Vertical || role != Qt::DisplayRole)
+ return QVariant();
+
+ static const QVariant senderTitle = tr("Sender");
+ static const QVariant signalTitle = tr("Signal");
+ static const QVariant receiverTitle = tr("Receiver");
+ static const QVariant slotTitle = tr("Slot");
+
+ switch (section) {
+ case 0:
+ return senderTitle;
+ case 1:
+ return signalTitle;
+ case 2:
+ return receiverTitle;
+ case 3:
+ return slotTitle;
+ }
+ return QVariant();
+}
+
+QModelIndex ConnectionModel::index(int row, int column,
+ const QModelIndex &parent) const
+{
+ if (parent.isValid() || !m_editor)
+ return QModelIndex();
+ if (row < 0 || row >= m_editor->connectionCount())
+ return QModelIndex();
+ return createIndex(row, column);
+}
+
+Connection *ConnectionModel::indexToConnection(const QModelIndex &index) const
+{
+ if (!index.isValid() || !m_editor)
+ return 0;
+ if (index.row() < 0 || index.row() >= m_editor->connectionCount())
+ return 0;
+ return m_editor->connection(index.row());
+}
+
+QModelIndex ConnectionModel::connectionToIndex(Connection *con) const
+{
+ Q_ASSERT(m_editor);
+ return createIndex(m_editor->indexOfConnection(con), 0);
+}
+
+QModelIndex ConnectionModel::parent(const QModelIndex&) const
+{
+ return QModelIndex();
+}
+
+int ConnectionModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid() || !m_editor)
+ return 0;
+ return m_editor->connectionCount();
+}
+
+int ConnectionModel::columnCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return 4;
+}
+
+QVariant ConnectionModel::data(const QModelIndex &index, int role) const
+{
+ if ((role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::FontRole && role != Qt::ForegroundRole) || !m_editor)
+ return QVariant();
+
+ if (index.row() < 0 || index.row() >= m_editor->connectionCount()) {
+ return QVariant();
+ }
+
+ const SignalSlotConnection *con = static_cast<SignalSlotConnection*>(m_editor->connection(index.row()));
+ Q_ASSERT(con != 0);
+
+ if (role == Qt::FontRole || role == Qt::ForegroundRole) {
+ bool isQt3Member = false;
+ if (index.column() == 1) {
+ QDesignerFormEditorInterface *core = m_editor->formWindow()->core();
+ isQt3Member = isQt3Signal(core, con->object(CETypes::EndPoint::Source), con->signal());
+ } else if (index.column() == 3) {
+ QDesignerFormEditorInterface *core = m_editor->formWindow()->core();
+ isQt3Member = isQt3Signal(core, con->object(CETypes::EndPoint::Target), con->slot());
+ }
+ if (isQt3Member) {
+ if (role == Qt::ForegroundRole)
+ return Qt::red;
+ QFont font = QApplication::font();
+ font.setItalic(true);
+ return font;
+ }
+ return QVariant();
+ }
+
+ static const QVariant senderDefault = tr("<sender>");
+ static const QVariant signalDefault = tr("<signal>");
+ static const QVariant receiverDefault = tr("<receiver>");
+ static const QVariant slotDefault = tr("<slot>");
+
+ switch (index.column()) {
+ case 0: {
+ const QString sender = con->sender();
+ if (sender.isEmpty())
+ return senderDefault;
+ return sender;
+ }
+ case 1: {
+ const QString signal = con->signal();
+ if (signal.isEmpty())
+ return signalDefault;
+ return signal;
+ }
+ case 2: {
+ const QString receiver = con->receiver();
+ if (receiver.isEmpty())
+ return receiverDefault;
+ return receiver;
+ }
+ case 3: {
+ const QString slot = con->slot();
+ if (slot.isEmpty())
+ return slotDefault;
+ return slot;
+ }
+ }
+ return QVariant();
+}
+
+bool ConnectionModel::setData(const QModelIndex &index, const QVariant &data, int)
+{
+ if (!index.isValid() || !m_editor)
+ return false;
+ if (data.type() != QVariant::String)
+ return false;
+
+ SignalSlotConnection *con = static_cast<SignalSlotConnection*>(m_editor->connection(index.row()));
+ QDesignerFormWindowInterface *form = m_editor->formWindow();
+
+ QString s = data.toString();
+ switch (index.column()) {
+ case 0:
+ if (!s.isEmpty() && !objectNameList(form).contains(s))
+ s.clear();
+ m_editor->setSource(con, s);
+ break;
+ case 1:
+ if (!memberFunctionListContains(form->core(), con->object(CETypes::EndPoint::Source), SignalMember, s))
+ s.clear();
+ m_editor->setSignal(con, s);
+ break;
+ case 2:
+ if (!s.isEmpty() && !objectNameList(form).contains(s))
+ s.clear();
+ m_editor->setTarget(con, s);
+ break;
+ case 3:
+ if (!memberFunctionListContains(form->core(), con->object(CETypes::EndPoint::Target), SlotMember, s))
+ s.clear();
+ m_editor->setSlot(con, s);
+ break;
+ }
+
+ return true;
+}
+
+void ConnectionModel::connectionAdded(Connection*)
+{
+ endInsertRows();
+}
+
+void ConnectionModel::connectionRemoved(int)
+{
+ endRemoveRows();
+}
+
+void ConnectionModel::aboutToRemoveConnection(Connection *con)
+{
+ Q_ASSERT(m_editor);
+ int idx = m_editor->indexOfConnection(con);
+ beginRemoveRows(QModelIndex(), idx, idx);
+}
+
+void ConnectionModel::aboutToAddConnection(int idx)
+{
+ Q_ASSERT(m_editor);
+ beginInsertRows(QModelIndex(), idx, idx);
+}
+
+Qt::ItemFlags ConnectionModel::flags(const QModelIndex&) const
+{
+ return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
+}
+
+void ConnectionModel::connectionChanged(Connection *con)
+{
+ Q_ASSERT(m_editor);
+ const int idx = m_editor->indexOfConnection(con);
+ SignalSlotConnection *changedCon = static_cast<SignalSlotConnection*>(m_editor->connection(idx));
+ SignalSlotConnection *c = 0;
+ for (int i=0; i<m_editor->connectionCount(); ++i) {
+ if (i == idx)
+ continue;
+ c = static_cast<SignalSlotConnection*>(m_editor->connection(i));
+ if (c->sender() == changedCon->sender() && c->signal() == changedCon->signal()
+ && c->receiver() == changedCon->receiver() && c->slot() == changedCon->slot()) {
+ const QString message = tr("The connection already exists!<br>%1").arg(changedCon->toString());
+ m_editor->formWindow()->core()->dialogGui()->message(m_editor->parentWidget(), QDesignerDialogGuiInterface::SignalSlotEditorMessage,
+ QMessageBox::Warning, tr("Signal and Slot Editor"), message, QMessageBox::Ok);
+ break;
+ }
+ }
+ emit dataChanged(createIndex(idx, 0), createIndex(idx, 3));
+}
+
+void ConnectionModel::updateAll()
+{
+ emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
+}
+}
+
+namespace {
+// ---------------------- InlineEditorModel
+
+class InlineEditorModel : public QStandardItemModel
+{
+ Q_OBJECT
+public:
+ enum { TitleItem = 1 };
+
+ InlineEditorModel(int rows, int cols, QObject *parent = 0);
+
+ void addTitle(const QString &title);
+ void addTextList(const QMap<QString, bool> &text_list);
+ void addText(const QString &text);
+ bool isTitle(int idx) const;
+
+ int findText(const QString &text) const;
+
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+};
+
+InlineEditorModel::InlineEditorModel(int rows, int cols, QObject *parent)
+ : QStandardItemModel(rows, cols, parent)
+{
+}
+
+void InlineEditorModel::addTitle(const QString &title)
+{
+ const int cnt = rowCount();
+ insertRows(cnt, 1);
+ QModelIndex cat_idx = index(cnt, 0);
+ setData(cat_idx, title + QLatin1Char(':'), Qt::DisplayRole);
+ setData(cat_idx, TitleItem, Qt::UserRole);
+ QFont font = QApplication::font();
+ font.setBold(true);
+ setData(cat_idx, font, Qt::FontRole);
+}
+
+bool InlineEditorModel::isTitle(int idx) const
+{
+ if (idx == -1)
+ return false;
+
+ return data(index(idx, 0), Qt::UserRole).toInt() == TitleItem;
+}
+
+void InlineEditorModel::addText(const QString &text)
+{
+ const int cnt = rowCount();
+ insertRows(cnt, 1);
+ setData(index(cnt, 0), text, Qt::DisplayRole);
+}
+
+void InlineEditorModel::addTextList(const QMap<QString, bool> &text_list)
+{
+ int cnt = rowCount();
+ insertRows(cnt, text_list.size());
+ QFont font = QApplication::font();
+ font.setItalic(true);
+ QVariant fontVariant = qVariantFromValue(font);
+ QMap<QString, bool>::ConstIterator it = text_list.constBegin();
+ const QMap<QString, bool>::ConstIterator itEnd = text_list.constEnd();
+ while (it != itEnd) {
+ const QModelIndex text_idx = index(cnt++, 0);
+ setData(text_idx, it.key(), Qt::DisplayRole);
+ if (it.value()) {
+ setData(text_idx, fontVariant, Qt::FontRole);
+ setData(text_idx, Qt::red, Qt::ForegroundRole);
+ }
+ ++it;
+ }
+}
+
+Qt::ItemFlags InlineEditorModel::flags(const QModelIndex &index) const
+{
+ if (isTitle(index.row()))
+ return Qt::ItemIsEnabled;
+ else
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+int InlineEditorModel::findText(const QString &text) const
+{
+ const int cnt = rowCount();
+ for (int i = 0; i < cnt; ++i) {
+ const QModelIndex idx = index(i, 0);
+ if (data(idx, Qt::UserRole).toInt() == TitleItem)
+ continue;
+ if (data(idx, Qt::DisplayRole).toString() == text)
+ return i;
+ }
+ return -1;
+}
+
+// ------------ InlineEditor
+class InlineEditor : public QComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText USER true)
+public:
+ InlineEditor(QWidget *parent = 0);
+
+ QString text() const;
+ void setText(const QString &text);
+
+ void addTitle(const QString &title);
+ void addText(const QString &text);
+ void addTextList(const QMap<QString, bool> &text_list);
+
+private slots:
+ void checkSelection(int idx);
+
+private:
+ InlineEditorModel *m_model;
+ int m_idx;
+};
+
+InlineEditor::InlineEditor(QWidget *parent) :
+ QComboBox(parent),
+ m_idx(-1)
+{
+ setModel(m_model = new InlineEditorModel(0, 4, this));
+ setFrame(false);
+ m_idx = -1;
+ connect(this, SIGNAL(activated(int)), this, SLOT(checkSelection(int)));
+}
+
+void InlineEditor::checkSelection(int idx)
+{
+ if (idx == m_idx)
+ return;
+
+ if (m_model->isTitle(idx))
+ setCurrentIndex(m_idx);
+ else
+ m_idx = idx;
+}
+
+void InlineEditor::addTitle(const QString &title)
+{
+ m_model->addTitle(title);
+}
+
+void InlineEditor::addTextList(const QMap<QString, bool> &text_list)
+{
+ m_model->addTextList(text_list);
+}
+
+void InlineEditor::addText(const QString &text)
+{
+ m_model->addText(text);
+}
+
+QString InlineEditor::text() const
+{
+ return currentText();
+}
+
+void InlineEditor::setText(const QString &text)
+{
+ m_idx = m_model->findText(text);
+ if (m_idx == -1)
+ m_idx = 0;
+ setCurrentIndex(m_idx);
+}
+
+// ------------------ ConnectionDelegate
+
+class ConnectionDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ ConnectionDelegate(QWidget *parent = 0);
+
+ void setForm(QDesignerFormWindowInterface *form);
+
+ virtual QWidget *createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+private slots:
+ void emitCommitData();
+
+private:
+ QDesignerFormWindowInterface *m_form;
+};
+
+ConnectionDelegate::ConnectionDelegate(QWidget *parent)
+ : QItemDelegate(parent)
+{
+ m_form = 0;
+
+ static QItemEditorFactory *factory = 0;
+ if (factory == 0) {
+ factory = new QItemEditorFactory;
+ QItemEditorCreatorBase *creator
+ = new QItemEditorCreator<InlineEditor>("text");
+ factory->registerEditor(QVariant::String, creator);
+ }
+
+ setItemEditorFactory(factory);
+}
+
+void ConnectionDelegate::setForm(QDesignerFormWindowInterface *form)
+{
+ m_form = form;
+}
+
+QWidget *ConnectionDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (m_form == 0)
+ return 0;
+
+ QWidget *w = QItemDelegate::createEditor(parent, option, index);
+ InlineEditor *inline_editor = qobject_cast<InlineEditor*>(w);
+ Q_ASSERT(inline_editor != 0);
+ const QAbstractItemModel *model = index.model();
+
+ const QModelIndex obj_name_idx = model->index(index.row(), index.column() <= 1 ? 0 : 2);
+ const QString obj_name = model->data(obj_name_idx, Qt::DisplayRole).toString();
+
+ switch (index.column()) {
+ case 0:
+ case 2: { // object names
+ QStringList obj_name_list = objectNameList(m_form);
+ QMap<QString, bool> markedNameList;
+ markedNameList.insert(tr("<object>"), false);
+ inline_editor->addTextList(markedNameList);
+ markedNameList.clear();
+ foreach (const QString &name, obj_name_list)
+ markedNameList.insert(name, false);
+ inline_editor->addTextList(markedNameList);
+ }
+ break;
+ case 1:
+ case 3: { // signals, slots
+ const qdesigner_internal::MemberType type = index.column() == 1 ? qdesigner_internal::SignalMember : qdesigner_internal::SlotMember;
+ const QModelIndex peer_index = model->index(index.row(), type == qdesigner_internal::SignalMember ? 3 : 1);
+ const QString peer = model->data(peer_index, Qt::DisplayRole).toString();
+
+ const qdesigner_internal::ClassesMemberFunctions class_list = qdesigner_internal::reverseClassesMemberFunctions(obj_name, type, peer, m_form);
+
+ QObject *object = qFindChild<QObject*>(m_form, obj_name);
+
+ inline_editor->addText(type == qdesigner_internal::SignalMember ? tr("<signal>") : tr("<slot>"));
+ foreach (const qdesigner_internal::ClassMemberFunctions &class_info, class_list) {
+ if (class_info.m_className.isEmpty() || class_info.m_memberList.isEmpty())
+ continue;
+ QStringList memberList = class_info.m_memberList;
+ QMap<QString, bool> markedMemberList;
+ foreach (const QString &member, memberList) {
+ bool mark = false;
+ if (type == qdesigner_internal::SignalMember)
+ mark = qdesigner_internal::isQt3Signal(m_form->core(), object, member);
+ else
+ mark = qdesigner_internal::isQt3Slot(m_form->core(), object, member);
+
+ if (!mark)
+ markedMemberList.insert(member, mark);
+ }
+ inline_editor->addTitle(class_info.m_className);
+ inline_editor->addTextList(markedMemberList);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ connect(inline_editor, SIGNAL(activated(int)), this, SLOT(emitCommitData()));
+
+ return inline_editor;
+}
+
+void ConnectionDelegate::emitCommitData()
+{
+ InlineEditor *editor = qobject_cast<InlineEditor*>(sender());
+ emit commitData(editor);
+}
+
+}
+
+namespace qdesigner_internal {
+
+/*******************************************************************************
+** SignalSlotEditorWindow
+*/
+
+SignalSlotEditorWindow::SignalSlotEditorWindow(QDesignerFormEditorInterface *core,
+ QWidget *parent) :
+ QWidget(parent),
+ m_view(new QTreeView),
+ m_editor(0),
+ m_add_button(new QToolButton),
+ m_remove_button(new QToolButton),
+ m_core(core),
+ m_model(new ConnectionModel(this)),
+ m_handling_selection_change(false)
+{
+ m_view->setModel(m_model);
+ m_view->setItemDelegate(new ConnectionDelegate(this));
+ m_view->setEditTriggers(QAbstractItemView::DoubleClicked
+ | QAbstractItemView::EditKeyPressed);
+ m_view->setRootIsDecorated(false);
+ m_view->setTextElideMode (Qt::ElideMiddle);
+ connect(m_view, SIGNAL(activated(QModelIndex)), this, SLOT(updateUi()));
+ connect(m_view->header(), SIGNAL(sectionDoubleClicked(int)), m_view, SLOT(resizeColumnToContents(int)));
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_view);
+
+ QHBoxLayout *layout2 = new QHBoxLayout;
+ layout2->setMargin(3);
+ layout->addLayout(layout2);
+ layout2->addStretch();
+
+ m_remove_button->setIcon(createIconSet(QLatin1String("minus.png")));
+ connect(m_remove_button, SIGNAL(clicked()), this, SLOT(removeConnection()));
+ layout2->addWidget(m_remove_button);
+
+ m_add_button->setIcon(createIconSet(QLatin1String("plus.png")));
+ connect(m_add_button, SIGNAL(clicked()), this, SLOT(addConnection()));
+ layout2->addWidget(m_add_button);
+
+ connect(core->formWindowManager(),
+ SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(setActiveFormWindow(QDesignerFormWindowInterface*)));
+
+ updateUi();
+}
+
+void SignalSlotEditorWindow::setActiveFormWindow(QDesignerFormWindowInterface *form)
+{
+ QDesignerIntegration *integration = qobject_cast<QDesignerIntegration *>(m_core->integration());
+
+ if (!m_editor.isNull()) {
+ disconnect(m_view->selectionModel(),
+ SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ this, SLOT(updateEditorSelection(QModelIndex)));
+ disconnect(m_editor, SIGNAL(connectionSelected(Connection*)),
+ this, SLOT(updateDialogSelection(Connection*)));
+ if (integration) {
+ disconnect(integration, SIGNAL(objectNameChanged(QDesignerFormWindowInterface *, QObject *, QString, QString)),
+ this, SLOT(objectNameChanged(QDesignerFormWindowInterface *, QObject *, QString, QString)));
+ }
+ }
+
+ m_editor = qFindChild<SignalSlotEditor*>(form);
+ m_model->setEditor(m_editor);
+ if (!m_editor.isNull()) {
+ ConnectionDelegate *delegate
+ = qobject_cast<ConnectionDelegate*>(m_view->itemDelegate());
+ if (delegate != 0)
+ delegate->setForm(form);
+
+ connect(m_view->selectionModel(),
+ SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+ this, SLOT(updateEditorSelection(QModelIndex)));
+ connect(m_editor, SIGNAL(connectionSelected(Connection*)),
+ this, SLOT(updateDialogSelection(Connection*)));
+ if (integration) {
+ connect(integration, SIGNAL(objectNameChanged(QDesignerFormWindowInterface *, QObject *, QString, QString)),
+ this, SLOT(objectNameChanged(QDesignerFormWindowInterface *, QObject *, QString, QString)));
+ }
+ }
+
+ updateUi();
+}
+
+void SignalSlotEditorWindow::updateDialogSelection(Connection *con)
+{
+ if (m_handling_selection_change || m_editor == 0)
+ return;
+
+ QModelIndex index = m_model->connectionToIndex(con);
+ if (index == m_view->currentIndex())
+ return;
+ m_handling_selection_change = true;
+ m_view->setCurrentIndex(index);
+ m_handling_selection_change = false;
+
+ updateUi();
+}
+
+void SignalSlotEditorWindow::updateEditorSelection(const QModelIndex &index)
+{
+ if (m_handling_selection_change || m_editor == 0)
+ return;
+
+ if (m_editor == 0)
+ return;
+
+ Connection *con = m_model->indexToConnection(index);
+ if (m_editor->selected(con))
+ return;
+ m_handling_selection_change = true;
+ m_editor->selectNone();
+ m_editor->setSelected(con, true);
+ m_handling_selection_change = false;
+
+ updateUi();
+}
+
+void SignalSlotEditorWindow::objectNameChanged(QDesignerFormWindowInterface *, QObject *, const QString &, const QString &)
+{
+ if (m_editor)
+ m_model->updateAll();
+}
+
+void SignalSlotEditorWindow::addConnection()
+{
+ if (m_editor.isNull())
+ return;
+
+ m_editor->addEmptyConnection();
+ updateUi();
+}
+
+void SignalSlotEditorWindow::removeConnection()
+{
+ if (m_editor.isNull())
+ return;
+
+ m_editor->deleteSelected();
+ updateUi();
+}
+
+void SignalSlotEditorWindow::updateUi()
+{
+ m_add_button->setEnabled(!m_editor.isNull());
+ m_remove_button->setEnabled(!m_editor.isNull() && m_view->currentIndex().isValid());
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#include "signalsloteditorwindow.moc"
diff --git a/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.h b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.h
new file mode 100644
index 0000000000..417e44bf28
--- /dev/null
+++ b/tools/designer/src/components/signalsloteditor/signalsloteditorwindow.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIGNALSLOTEDITORWINDOW_H
+#define SIGNALSLOTEDITORWINDOW_H
+
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+class QModelIndex;
+class QTreeView;
+class QToolButton;
+
+namespace qdesigner_internal {
+
+class SignalSlotEditor;
+class ConnectionModel;
+class Connection;
+
+class SignalSlotEditorWindow : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit SignalSlotEditorWindow(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+
+public slots:
+ void setActiveFormWindow(QDesignerFormWindowInterface *form);
+
+private slots:
+ void updateDialogSelection(Connection *con);
+ void updateEditorSelection(const QModelIndex &index);
+
+ void objectNameChanged(QDesignerFormWindowInterface *formWindow, QObject *object, const QString &newName, const QString &oldName);
+
+ void addConnection();
+ void removeConnection();
+ void updateUi();
+
+private:
+ QTreeView *m_view;
+ QPointer<SignalSlotEditor> m_editor;
+ QToolButton *m_add_button, *m_remove_button;
+ QDesignerFormEditorInterface *m_core;
+ ConnectionModel *m_model;
+ bool m_handling_selection_change;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SIGNALSLOTEDITORWINDOW_H
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor.cpp b/tools/designer/src/components/tabordereditor/tabordereditor.cpp
new file mode 100644
index 0000000000..92f5ed11db
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor.cpp
@@ -0,0 +1,433 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tabordereditor.h"
+
+#include <metadatabase_p.h>
+#include <qdesigner_command_p.h>
+#include <qdesigner_utils_p.h>
+#include <qlayout_widget_p.h>
+#include <orderdialog_p.h>
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+
+#include <QtGui/QPainter>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QResizeEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QApplication>
+
+Q_DECLARE_METATYPE(QWidgetList)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { VBOX_MARGIN = 1, HBOX_MARGIN = 4, BG_ALPHA = 32 };
+}
+
+static QRect fixRect(const QRect &r)
+{
+ return QRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
+}
+
+namespace qdesigner_internal {
+
+TabOrderEditor::TabOrderEditor(QDesignerFormWindowInterface *form, QWidget *parent) :
+ QWidget(parent),
+ m_form_window(form),
+ m_bg_widget(0),
+ m_undo_stack(form->commandHistory()),
+ m_font_metrics(font()),
+ m_current_index(0),
+ m_beginning(true)
+{
+ connect(form, SIGNAL(widgetRemoved(QWidget*)), this, SLOT(widgetRemoved(QWidget*)));
+
+ QFont tabFont = font();
+ tabFont.setPointSize(tabFont.pointSize()*2);
+ tabFont.setBold(true);
+ setFont(tabFont);
+ m_font_metrics = QFontMetrics(tabFont);
+ setAttribute(Qt::WA_MouseTracking, true);
+}
+
+QDesignerFormWindowInterface *TabOrderEditor::formWindow() const
+{
+ return m_form_window;
+}
+
+void TabOrderEditor::setBackground(QWidget *background)
+{
+ if (background == m_bg_widget) {
+ return;
+ }
+
+ m_bg_widget = background;
+ updateBackground();
+}
+
+void TabOrderEditor::updateBackground()
+{
+ if (m_bg_widget == 0) {
+ // nothing to do
+ return;
+ }
+
+ initTabOrder();
+ update();
+}
+
+void TabOrderEditor::widgetRemoved(QWidget*)
+{
+ initTabOrder();
+}
+
+void TabOrderEditor::showEvent(QShowEvent *e)
+{
+ QWidget::showEvent(e);
+ updateBackground();
+}
+
+QRect TabOrderEditor::indicatorRect(int index) const
+{
+ if (index < 0 || index >= m_tab_order_list.size())
+ return QRect();
+
+ const QWidget *w = m_tab_order_list.at(index);
+ const QString text = QString::number(index + 1);
+
+ const QPoint tl = mapFromGlobal(w->mapToGlobal(w->rect().topLeft()));
+ const QSize size = m_font_metrics.size(Qt::TextSingleLine, text);
+ QRect r(tl - QPoint(size.width(), size.height())/2, size);
+ r = QRect(r.left() - HBOX_MARGIN, r.top() - VBOX_MARGIN,
+ r.width() + HBOX_MARGIN*2, r.height() + VBOX_MARGIN*2);
+
+ return r;
+}
+
+static bool isWidgetVisible(QWidget *widget)
+{
+ while (widget && widget->parentWidget()) {
+ if (!widget->isVisibleTo(widget->parentWidget()))
+ return false;
+
+ widget = widget->parentWidget();
+ }
+
+ return true;
+}
+
+void TabOrderEditor::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ p.setClipRegion(e->region());
+
+ int cur = m_current_index - 1;
+ if (m_beginning == false && cur < 0)
+ cur = m_tab_order_list.size() - 1;
+
+ for (int i = 0; i < m_tab_order_list.size(); ++i) {
+ QWidget *widget = m_tab_order_list.at(i);
+ if (!isWidgetVisible(widget))
+ continue;
+
+ const QRect r = indicatorRect(i);
+
+ QColor c = Qt::darkGreen;
+ if (i == cur)
+ c = Qt::red;
+ else if (i > cur)
+ c = Qt::blue;
+ p.setPen(c);
+ c.setAlpha(BG_ALPHA);
+ p.setBrush(c);
+ p.drawRect(fixRect(r));
+
+ p.setPen(Qt::white);
+ p.drawText(r, QString::number(i + 1), QTextOption(Qt::AlignCenter));
+ }
+}
+
+bool TabOrderEditor::skipWidget(QWidget *w) const
+{
+ if (qobject_cast<QLayoutWidget*>(w)
+ || w == formWindow()->mainContainer()
+ || w->isHidden())
+ return true;
+
+ if (!formWindow()->isManaged(w)) {
+ return true;
+ }
+
+ QExtensionManager *ext = formWindow()->core()->extensionManager();
+ if (const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(ext, w)) {
+ const int index = sheet->indexOf(QLatin1String("focusPolicy"));
+ if (index != -1) {
+ bool ok = false;
+ Qt::FocusPolicy q = (Qt::FocusPolicy) Utils::valueOf(sheet->property(index), &ok);
+ return !ok || q == Qt::NoFocus;
+ }
+ }
+
+ return true;
+}
+
+void TabOrderEditor::initTabOrder()
+{
+ m_tab_order_list.clear();
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+
+ if (const QDesignerMetaDataBaseItemInterface *item = core->metaDataBase()->item(formWindow())) {
+ m_tab_order_list = item->tabOrder();
+ }
+
+ // Remove any widgets that have been removed form the form
+ for (int i = 0; i < m_tab_order_list.size(); ) {
+ QWidget *w = m_tab_order_list.at(i);
+ if (!formWindow()->mainContainer()->isAncestorOf(w) || skipWidget(w))
+ m_tab_order_list.removeAt(i);
+ else
+ ++i;
+ }
+
+ // Append any widgets that are in the form but are not in the tab order
+ QList<QWidget *> childQueue;
+ childQueue.append(formWindow()->mainContainer());
+ while (!childQueue.isEmpty()) {
+ QWidget *child = childQueue.takeFirst();
+ childQueue += qVariantValue<QWidgetList>(child->property("_q_widgetOrder"));
+
+ if (skipWidget(child))
+ continue;
+
+ if (!m_tab_order_list.contains(child))
+ m_tab_order_list.append(child);
+ }
+
+ // Just in case we missed some widgets
+ QDesignerFormWindowCursorInterface *cursor = formWindow()->cursor();
+ for (int i = 0; i < cursor->widgetCount(); ++i) {
+
+ QWidget *widget = cursor->widget(i);
+ if (skipWidget(widget))
+ continue;
+
+ if (!m_tab_order_list.contains(widget))
+ m_tab_order_list.append(widget);
+ }
+
+ m_indicator_region = QRegion();
+ for (int i = 0; i < m_tab_order_list.size(); ++i) {
+ if (m_tab_order_list.at(i)->isVisible())
+ m_indicator_region |= indicatorRect(i);
+ }
+
+ if (m_current_index >= m_tab_order_list.size())
+ m_current_index = m_tab_order_list.size() - 1;
+ if (m_current_index < 0)
+ m_current_index = 0;
+}
+
+void TabOrderEditor::mouseMoveEvent(QMouseEvent *e)
+{
+ e->accept();
+#ifndef QT_NO_CURSOR
+ if (m_indicator_region.contains(e->pos()))
+ setCursor(Qt::PointingHandCursor);
+ else
+ setCursor(QCursor());
+#endif
+}
+
+int TabOrderEditor::widgetIndexAt(const QPoint &pos) const
+{
+ int target_index = -1;
+ for (int i = 0; i < m_tab_order_list.size(); ++i) {
+ if (!m_tab_order_list.at(i)->isVisible())
+ continue;
+ if (indicatorRect(i).contains(pos)) {
+ target_index = i;
+ break;
+ }
+ }
+
+ return target_index;
+}
+
+void TabOrderEditor::mousePressEvent(QMouseEvent *e)
+{
+ e->accept();
+
+ if (!m_indicator_region.contains(e->pos())) {
+ if (QWidget *child = m_bg_widget->childAt(e->pos())) {
+ QDesignerFormEditorInterface *core = m_form_window->core();
+ if (core->widgetFactory()->isPassiveInteractor(child)) {
+
+ QMouseEvent event(QEvent::MouseButtonPress,
+ child->mapFromGlobal(e->globalPos()),
+ e->button(), e->buttons(), e->modifiers());
+
+ qApp->sendEvent(child, &event);
+
+ QMouseEvent event2(QEvent::MouseButtonRelease,
+ child->mapFromGlobal(e->globalPos()),
+ e->button(), e->buttons(), e->modifiers());
+
+ qApp->sendEvent(child, &event2);
+
+ updateBackground();
+ }
+ }
+ return;
+ }
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ const int target_index = widgetIndexAt(e->pos());
+ if (target_index == -1)
+ return;
+
+ m_beginning = false;
+
+ if (e->modifiers() & Qt::ControlModifier) {
+ m_current_index = target_index + 1;
+ if (m_current_index >= m_tab_order_list.size())
+ m_current_index = 0;
+ update();
+ return;
+ }
+
+ if (m_current_index == -1)
+ return;
+
+ m_tab_order_list.swap(target_index, m_current_index);
+
+ ++m_current_index;
+ if (m_current_index == m_tab_order_list.size())
+ m_current_index = 0;
+
+ TabOrderCommand *cmd = new TabOrderCommand(formWindow());
+ cmd->init(m_tab_order_list);
+ formWindow()->commandHistory()->push(cmd);
+}
+
+void TabOrderEditor::contextMenuEvent(QContextMenuEvent *e)
+{
+ QMenu menu(this);
+ const int target_index = widgetIndexAt(e->pos());
+ QAction *setIndex = menu.addAction(tr("Start from Here"));
+ setIndex->setEnabled(target_index >= 0);
+
+ QAction *resetIndex = menu.addAction(tr("Restart"));
+ menu.addSeparator();
+ QAction *showDialog = menu.addAction(tr("Tab Order List..."));
+ showDialog->setEnabled(m_tab_order_list.size() > 1);
+
+ QAction *result = menu.exec(e->globalPos());
+ if (result == resetIndex) {
+ m_current_index = 0;
+ m_beginning = true;
+ update();
+ } else if (result == setIndex) {
+ m_beginning = false;
+ m_current_index = target_index + 1;
+ if (m_current_index >= m_tab_order_list.size())
+ m_current_index = 0;
+ update();
+ } else if (result == showDialog) {
+ showTabOrderDialog();
+ }
+}
+
+void TabOrderEditor::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ const int target_index = widgetIndexAt(e->pos());
+ if (target_index >= 0)
+ return;
+
+ m_beginning = true;
+ m_current_index = 0;
+ update();
+}
+
+void TabOrderEditor::resizeEvent(QResizeEvent *e)
+{
+ updateBackground();
+ QWidget::resizeEvent(e);
+}
+
+void TabOrderEditor::showTabOrderDialog()
+{
+ if (m_tab_order_list.size() < 2)
+ return;
+ OrderDialog dlg(this);
+ dlg.setWindowTitle(tr("Tab Order List"));
+ dlg.setDescription(tr("Tab Order"));
+ dlg.setFormat(OrderDialog::TabOrderFormat);
+ dlg.setPageList(m_tab_order_list);
+
+ if (dlg.exec() == QDialog::Rejected)
+ return;
+
+ const QWidgetList newOrder = dlg.pageList();
+ if (newOrder == m_tab_order_list)
+ return;
+
+ m_tab_order_list = newOrder;
+ TabOrderCommand *cmd = new TabOrderCommand(formWindow());
+ cmd->init(m_tab_order_list);
+ formWindow()->commandHistory()->push(cmd);
+ update();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor.h b/tools/designer/src/components/tabordereditor/tabordereditor.h
new file mode 100644
index 0000000000..ec7a81d286
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABORDEREDITOR_H
+#define TABORDEREDITOR_H
+
+#include "tabordereditor_global.h"
+
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+#include <QtGui/QRegion>
+#include <QtGui/QFont>
+#include <QtGui/QFontMetrics>
+
+QT_BEGIN_NAMESPACE
+
+class QUndoStack;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class QT_TABORDEREDITOR_EXPORT TabOrderEditor : public QWidget
+{
+ Q_OBJECT
+
+public:
+ TabOrderEditor(QDesignerFormWindowInterface *form, QWidget *parent);
+
+ QDesignerFormWindowInterface *formWindow() const;
+
+public slots:
+ void setBackground(QWidget *background);
+ void updateBackground();
+ void widgetRemoved(QWidget*);
+ void initTabOrder();
+
+private slots:
+ void showTabOrderDialog();
+
+protected:
+ virtual void paintEvent(QPaintEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void showEvent(QShowEvent *e);
+
+private:
+ QRect indicatorRect(int index) const;
+ int widgetIndexAt(const QPoint &pos) const;
+ bool skipWidget(QWidget *w) const;
+
+ QPointer<QDesignerFormWindowInterface> m_form_window;
+
+ QWidgetList m_tab_order_list;
+
+ QWidget *m_bg_widget;
+ QUndoStack *m_undo_stack;
+ QRegion m_indicator_region;
+
+ QFontMetrics m_font_metrics;
+ int m_current_index;
+ bool m_beginning;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor.pri b/tools/designer/src/components/tabordereditor/tabordereditor.pri
new file mode 100644
index 0000000000..786c6ae022
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor.pri
@@ -0,0 +1,16 @@
+
+QT += xml
+
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/tabordereditor.h \
+ $$PWD/tabordereditor_plugin.h \
+ $$PWD/tabordereditor_tool.h \
+ $$PWD/tabordereditor_global.h
+
+SOURCES += \
+ $$PWD/tabordereditor.cpp \
+ $$PWD/tabordereditor_tool.cpp \
+ $$PWD/tabordereditor_plugin.cpp \
+ $$PWD/tabordereditor_instance.cpp
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor_global.h b/tools/designer/src/components/tabordereditor/tabordereditor_global.h
new file mode 100644
index 0000000000..af40dbd5e5
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABORDEREDITOR_GLOBAL_H
+#define TABORDEREDITOR_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN
+#ifdef QT_TABORDEREDITOR_LIBRARY
+# define QT_TABORDEREDITOR_EXPORT
+#else
+# define QT_TABORDEREDITOR_EXPORT
+#endif
+#else
+#define QT_TABORDEREDITOR_EXPORT
+#endif
+
+#endif // TABORDEREDITOR_GLOBAL_H
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor_instance.cpp b/tools/designer/src/components/tabordereditor/tabordereditor_instance.cpp
new file mode 100644
index 0000000000..fe006ce224
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor_instance.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qplugin.h>
+
+#include "tabordereditor_plugin.h"
+
+QT_USE_NAMESPACE
+using namespace qdesigner_internal;
+
+Q_EXPORT_PLUGIN(TabOrderEditorPlugin)
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp b/tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp
new file mode 100644
index 0000000000..46bf3786d1
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor_plugin.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::TabOrderEditorPlugin
+*/
+
+#include <QtGui/QAction>
+
+#include "tabordereditor_plugin.h"
+#include "tabordereditor_tool.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+TabOrderEditorPlugin::TabOrderEditorPlugin()
+ : m_initialized(false)
+{
+}
+
+TabOrderEditorPlugin::~TabOrderEditorPlugin()
+{
+}
+
+bool TabOrderEditorPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void TabOrderEditorPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_ASSERT(!isInitialized());
+
+ m_action = new QAction(tr("Edit Tab Order"), this);
+ m_action->setObjectName(QLatin1String("_qt_edit_tab_order_action"));
+ m_action->setIcon(QIcon(core->resourceLocation() + QLatin1String("/tabordertool.png")));
+ m_action->setEnabled(false);
+
+ setParent(core);
+ m_core = core;
+ m_initialized = true;
+
+ connect(core->formWindowManager(), SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)),
+ this, SLOT(addFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(formWindowRemoved(QDesignerFormWindowInterface*)),
+ this, SLOT(removeFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
+}
+
+void TabOrderEditorPlugin::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+{
+ m_action->setEnabled(formWindow != 0);
+}
+
+QDesignerFormEditorInterface *TabOrderEditorPlugin::core() const
+{
+ return m_core;
+}
+
+void TabOrderEditorPlugin::addFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tools.contains(formWindow) == false);
+
+ TabOrderEditorTool *tool = new TabOrderEditorTool(formWindow, this);
+ m_tools[formWindow] = tool;
+ connect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+ formWindow->registerTool(tool);
+}
+
+void TabOrderEditorPlugin::removeFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tools.contains(formWindow) == true);
+
+ TabOrderEditorTool *tool = m_tools.value(formWindow);
+ m_tools.remove(formWindow);
+ disconnect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+ // ### FIXME disable the tool
+
+ delete tool;
+}
+
+QAction *TabOrderEditorPlugin::action() const
+{
+ return m_action;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor_plugin.h b/tools/designer/src/components/tabordereditor/tabordereditor_plugin.h
new file mode 100644
index 0000000000..e5ef762fb2
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor_plugin.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABORDEREDITOR_PLUGIN_H
+#define TABORDEREDITOR_PLUGIN_H
+
+#include "tabordereditor_global.h"
+
+#include <QtDesigner/QDesignerFormEditorPluginInterface>
+
+#include <QtCore/QPointer>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QAction;
+
+namespace qdesigner_internal {
+
+class TabOrderEditorTool;
+
+class QT_TABORDEREDITOR_EXPORT TabOrderEditorPlugin: public QObject, public QDesignerFormEditorPluginInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerFormEditorPluginInterface)
+public:
+ TabOrderEditorPlugin();
+ virtual ~TabOrderEditorPlugin();
+
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ QAction *action() const;
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+public slots:
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+
+private slots:
+ void addFormWindow(QDesignerFormWindowInterface *formWindow);
+ void removeFormWindow(QDesignerFormWindowInterface *formWindow);
+
+private:
+ QPointer<QDesignerFormEditorInterface> m_core;
+ QHash<QDesignerFormWindowInterface*, TabOrderEditorTool*> m_tools;
+ bool m_initialized;
+ QAction *m_action;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TABORDEREDITOR_PLUGIN_H
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor_tool.cpp b/tools/designer/src/components/tabordereditor/tabordereditor_tool.cpp
new file mode 100644
index 0000000000..4f291a1bb6
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor_tool.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::TabOrderEditorTool
+*/
+
+#include "tabordereditor_tool.h"
+#include "tabordereditor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtCore/QEvent>
+#include <QtGui/QAction>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+TabOrderEditorTool::TabOrderEditorTool(QDesignerFormWindowInterface *formWindow, QObject *parent)
+ : QDesignerFormWindowToolInterface(parent),
+ m_formWindow(formWindow),
+ m_action(new QAction(tr("Edit Tab Order"), this))
+{
+}
+
+TabOrderEditorTool::~TabOrderEditorTool()
+{
+}
+
+QDesignerFormEditorInterface *TabOrderEditorTool::core() const
+{
+ return m_formWindow->core();
+}
+
+QDesignerFormWindowInterface *TabOrderEditorTool::formWindow() const
+{
+ return m_formWindow;
+}
+
+bool TabOrderEditorTool::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event)
+{
+ Q_UNUSED(widget);
+ Q_UNUSED(managedWidget);
+
+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease)
+ return true;
+
+ return false;
+}
+
+QWidget *TabOrderEditorTool::editor() const
+{
+ if (!m_editor) {
+ Q_ASSERT(formWindow() != 0);
+ m_editor = new TabOrderEditor(formWindow(), 0);
+ connect(formWindow(), SIGNAL(mainContainerChanged(QWidget*)), m_editor, SLOT(setBackground(QWidget*)));
+ }
+
+ return m_editor;
+}
+
+void TabOrderEditorTool::activated()
+{
+ connect(formWindow(), SIGNAL(changed()),
+ m_editor, SLOT(updateBackground()));
+}
+
+void TabOrderEditorTool::deactivated()
+{
+ disconnect(formWindow(), SIGNAL(changed()),
+ m_editor, SLOT(updateBackground()));
+}
+
+QAction *TabOrderEditorTool::action() const
+{
+ return m_action;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/tabordereditor/tabordereditor_tool.h b/tools/designer/src/components/tabordereditor/tabordereditor_tool.h
new file mode 100644
index 0000000000..ea74da2461
--- /dev/null
+++ b/tools/designer/src/components/tabordereditor/tabordereditor_tool.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABORDEREDITOR_TOOL_H
+#define TABORDEREDITOR_TOOL_H
+
+#include "tabordereditor_global.h"
+
+#include <QtCore/QPointer>
+
+#include <QtDesigner/QDesignerFormWindowToolInterface>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QAction;
+
+namespace qdesigner_internal {
+
+class TabOrderEditor;
+
+class QT_TABORDEREDITOR_EXPORT TabOrderEditorTool: public QDesignerFormWindowToolInterface
+{
+ Q_OBJECT
+public:
+ explicit TabOrderEditorTool(QDesignerFormWindowInterface *formWindow, QObject *parent = 0);
+ virtual ~TabOrderEditorTool();
+
+ virtual QDesignerFormEditorInterface *core() const;
+ virtual QDesignerFormWindowInterface *formWindow() const;
+
+ virtual QWidget *editor() const;
+ virtual QAction *action() const;
+
+ virtual void activated();
+ virtual void deactivated();
+
+ virtual bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event);
+
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+ mutable QPointer<TabOrderEditor> m_editor;
+ QAction *m_action;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TABORDEREDITOR_TOOL_H
diff --git a/tools/designer/src/components/taskmenu/button_taskmenu.cpp b/tools/designer/src/components/taskmenu/button_taskmenu.cpp
new file mode 100644
index 0000000000..ced32ce5a5
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/button_taskmenu.cpp
@@ -0,0 +1,713 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ButtonTaskMenu
+*/
+
+#include "button_taskmenu.h"
+#include "inplace_editor.h"
+#include <qdesigner_formwindowcommand_p.h>
+#include <formwindowbase_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QMenu>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+#include <QtGui/QAbstractButton>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QApplication>
+#include <QtCore/QDebug>
+
+Q_DECLARE_METATYPE(QButtonGroup*)
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+enum { debugButtonMenu = 0 };
+
+typedef QList<QAbstractButton *> ButtonList;
+typedef QList<QButtonGroup *> ButtonGroupList;
+
+// ButtonGroupCommand: Base for commands handling button groups and button lists
+// addButtonsToGroup() and removeButtonsFromGroup() are low-level helpers for
+// adding/removing members to/from existing groups.
+//
+// createButtonGroup()/breakButtonGroup() create and remove the groups from scratch.
+// When using them in a command, the command must be executed within
+// a macro since it makes the form emit objectRemoved() which might cause other components
+// to add commands (for example, removal of signals and slots)
+class ButtonGroupCommand : public QDesignerFormWindowCommand {
+
+protected:
+ ButtonGroupCommand(const QString &description, QDesignerFormWindowInterface *formWindow);
+
+ void initialize(const ButtonList &bl, QButtonGroup *buttonGroup);
+
+ // Helper: Add the buttons to the group
+ void addButtonsToGroup();
+ // Helper; Remove the buttons
+ void removeButtonsFromGroup();
+
+ // Create the button group in Designer
+ void createButtonGroup();
+ // Remove the button group from Designer
+ void breakButtonGroup();
+
+public:
+ static QString nameList(const ButtonList& bl);
+ static ButtonGroupList managedButtonGroups(const QDesignerFormWindowInterface *formWindow);
+
+private:
+ ButtonList m_buttonList;
+ QButtonGroup *m_buttonGroup;
+};
+
+ButtonGroupCommand::ButtonGroupCommand(const QString &description, QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(description, formWindow),
+ m_buttonGroup(0)
+{
+}
+
+void ButtonGroupCommand::initialize(const ButtonList &bl, QButtonGroup *buttonGroup)
+{
+ m_buttonList = bl;
+ m_buttonGroup = buttonGroup;
+}
+
+void ButtonGroupCommand::addButtonsToGroup()
+{
+ if (debugButtonMenu)
+ qDebug() << "Adding " << m_buttonList << " to " << m_buttonGroup;
+ const ButtonList::const_iterator cend = m_buttonList.constEnd();
+ for (ButtonList::const_iterator it = m_buttonList.constBegin(); it != cend; ++it)
+ m_buttonGroup->addButton(*it);
+}
+
+void ButtonGroupCommand::removeButtonsFromGroup()
+{
+ if (debugButtonMenu)
+ qDebug() << "Removing " << m_buttonList << " from " << m_buttonGroup;
+ const ButtonList::const_iterator cend = m_buttonList.constEnd();
+ for (ButtonList::const_iterator it = m_buttonList.constBegin(); it != cend; ++it)
+ m_buttonGroup->removeButton(*it);
+}
+
+void ButtonGroupCommand::createButtonGroup()
+{
+ if (debugButtonMenu)
+ qDebug() << "Creating " << m_buttonGroup << " from " << m_buttonList;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ QDesignerFormEditorInterface *core = fw->core();
+ core->metaDataBase()->add(m_buttonGroup);
+ addButtonsToGroup();
+ // Make button group visible
+ core->objectInspector()->setFormWindow(fw);
+}
+
+void ButtonGroupCommand::breakButtonGroup()
+{
+ if (debugButtonMenu)
+ qDebug() << "Removing " << m_buttonGroup << " consisting of " << m_buttonList;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ QDesignerFormEditorInterface *core = fw->core();
+ // Button group was selected, that is, break was invoked via its context menu. Remove it from property editor, select the buttons
+ if (core->propertyEditor()->object() == m_buttonGroup) {
+ fw->clearSelection(false);
+ const ButtonList::const_iterator cend = m_buttonList.constEnd();
+ for (ButtonList::const_iterator it = m_buttonList.constBegin(); it != cend; ++it)
+ fw->selectWidget(*it, true);
+ }
+ // Now remove and refresh object inspector
+ removeButtonsFromGroup();
+ // Notify components (for example, signal slot editor)
+ if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(fw))
+ fwb->emitObjectRemoved(m_buttonGroup);
+ core->metaDataBase()->remove(m_buttonGroup);
+ core->objectInspector()->setFormWindow(fw);
+}
+
+QString ButtonGroupCommand::nameList(const ButtonList& bl)
+{
+ QString rc;
+ const QChar quote = QLatin1Char('\'');
+ const QString separator = QLatin1String(", ");
+ const int size = bl.size();
+ for (int i = 0; i < size; i++) {
+ if (i)
+ rc += separator;
+ rc += quote;
+ rc += bl[i]->objectName();
+ rc += quote;
+ }
+ return rc;
+
+}
+
+ButtonGroupList ButtonGroupCommand::managedButtonGroups(const QDesignerFormWindowInterface *formWindow)
+{
+ const QDesignerMetaDataBaseInterface *mdb = formWindow->core()->metaDataBase();
+ ButtonGroupList bl;
+ // Check 1st order children for managed button groups
+ const QObjectList children = formWindow->mainContainer()->children();
+ const QObjectList::const_iterator cend = children.constEnd();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
+ if (!(*it)->isWidgetType())
+ if (QButtonGroup *bg = qobject_cast<QButtonGroup *>(*it))
+ if (mdb->item(bg))
+ bl.push_back(bg);
+ }
+ return bl;
+}
+
+// --------------- CreateButtonGroupCommand
+// This command might be executed in a macro with a remove
+// command to move buttons from one group to a new one.
+class CreateButtonGroupCommand : public ButtonGroupCommand {
+public:
+ CreateButtonGroupCommand(QDesignerFormWindowInterface *formWindow);
+ bool init(const ButtonList &bl);
+
+ virtual void undo() { breakButtonGroup(); }
+ virtual void redo() { createButtonGroup(); }
+};
+
+CreateButtonGroupCommand::CreateButtonGroupCommand(QDesignerFormWindowInterface *formWindow) :
+ ButtonGroupCommand(QApplication::translate("Command", "Create button group"), formWindow)
+{
+}
+
+bool CreateButtonGroupCommand::init(const ButtonList &bl)
+{
+ if (bl.empty())
+ return false;
+ QDesignerFormWindowInterface *fw = formWindow();
+ QButtonGroup *buttonGroup = new QButtonGroup(fw->mainContainer());
+ buttonGroup->setObjectName(QLatin1String("buttonGroup"));
+ fw->ensureUniqueObjectName(buttonGroup);
+ initialize(bl, buttonGroup);
+ return true;
+}
+
+// --------------- BreakButtonGroupCommand
+class BreakButtonGroupCommand : public ButtonGroupCommand {
+public:
+ BreakButtonGroupCommand(QDesignerFormWindowInterface *formWindow);
+ bool init(QButtonGroup *group);
+
+ virtual void undo() { createButtonGroup(); }
+ virtual void redo() { breakButtonGroup(); }
+};
+
+BreakButtonGroupCommand::BreakButtonGroupCommand(QDesignerFormWindowInterface *formWindow) :
+ ButtonGroupCommand(QApplication::translate("Command", "Break button group"), formWindow)
+{
+}
+
+bool BreakButtonGroupCommand::init(QButtonGroup *group)
+{
+ if (!group)
+ return false;
+ initialize(group->buttons(), group);
+ setText(QApplication::translate("Command", "Break button group '%1'").arg(group->objectName()));
+ return true;
+}
+
+// --------------- AddButtonsToGroupCommand
+// This command might be executed in a macro with a remove
+// command to move buttons from one group to a new one.
+class AddButtonsToGroupCommand : public ButtonGroupCommand {
+public:
+ AddButtonsToGroupCommand(QDesignerFormWindowInterface *formWindow);
+ void init(const ButtonList &bl, QButtonGroup *group);
+
+ virtual void undo() { removeButtonsFromGroup(); }
+ virtual void redo() { addButtonsToGroup(); }
+};
+
+AddButtonsToGroupCommand::AddButtonsToGroupCommand(QDesignerFormWindowInterface *formWindow) :
+ ButtonGroupCommand(QApplication::translate("Command", "Add buttons to group"), formWindow)
+{
+}
+
+void AddButtonsToGroupCommand::init(const ButtonList &bl, QButtonGroup *group)
+{
+ initialize(bl, group);
+ //: Command description for adding buttons to a QButtonGroup
+ setText(QApplication::translate("Command", "Add '%1' to '%2'").arg(nameList(bl), group->objectName()));
+}
+
+//-------------------- RemoveButtonsFromGroupCommand
+class RemoveButtonsFromGroupCommand : public ButtonGroupCommand {
+public:
+ RemoveButtonsFromGroupCommand(QDesignerFormWindowInterface *formWindow);
+ bool init(const ButtonList &bl);
+
+ virtual void undo() { addButtonsToGroup(); }
+ virtual void redo() { removeButtonsFromGroup(); }
+};
+
+RemoveButtonsFromGroupCommand::RemoveButtonsFromGroupCommand(QDesignerFormWindowInterface *formWindow) :
+ ButtonGroupCommand(QApplication::translate("Command", "Remove buttons from group"), formWindow)
+{
+}
+
+bool RemoveButtonsFromGroupCommand::init(const ButtonList &bl)
+{
+ if (bl.empty())
+ return false;
+ QButtonGroup *group = bl.front()->group();
+ if (!group)
+ return false;
+ if (bl.size() >= group->buttons().size())
+ return false;
+ initialize(bl, group);
+ //: Command description for removing buttons from a QButtonGroup
+ setText(QApplication::translate("Command", "Remove '%1' from '%2'").arg(nameList(bl), group->objectName()));
+ return true;
+}
+
+// -------- ButtonGroupMenu
+ButtonGroupMenu::ButtonGroupMenu(QObject *parent) :
+ QObject(parent),
+ m_selectGroupAction(new QAction(tr("Select members"), this)),
+ m_breakGroupAction(new QAction(tr("Break"), this)),
+ m_formWindow(0),
+ m_buttonGroup(0),
+ m_currentButton(0)
+{
+ connect(m_breakGroupAction, SIGNAL(triggered()), this, SLOT(breakGroup()));
+ connect(m_selectGroupAction, SIGNAL(triggered()), this, SLOT(selectGroup()));
+}
+
+void ButtonGroupMenu::initialize(QDesignerFormWindowInterface *formWindow, QButtonGroup *buttonGroup, QAbstractButton *currentButton)
+{
+ m_buttonGroup = buttonGroup;
+ m_currentButton = currentButton;
+ m_formWindow = formWindow;
+ Q_ASSERT(m_formWindow);
+
+ const bool canBreak = buttonGroup != 0;
+ m_breakGroupAction->setEnabled(canBreak);
+ m_selectGroupAction->setEnabled(canBreak);
+}
+
+void ButtonGroupMenu::selectGroup()
+{
+ // Select and make current button "current" again by selecting it last (if there is any)
+ const ButtonList buttons = m_buttonGroup->buttons();
+ m_formWindow->clearSelection(false);
+ const ButtonList::const_iterator cend = buttons.constEnd();
+ for (ButtonList::const_iterator it = buttons.constBegin(); it != cend; ++it)
+ if (*it != m_currentButton)
+ m_formWindow->selectWidget(*it, true);
+ if (m_currentButton)
+ m_formWindow->selectWidget(m_currentButton, true);
+}
+
+void ButtonGroupMenu::breakGroup()
+{
+ BreakButtonGroupCommand *cmd = new BreakButtonGroupCommand(m_formWindow);
+ if (cmd->init(m_buttonGroup)) {
+ // Need a macro since the command might trigger additional commands
+ QUndoStack *history = m_formWindow->commandHistory();
+ history->beginMacro(cmd->text());
+ history->push(cmd);
+ history->endMacro();
+ } else {
+ qWarning("** WARNING Failed to initialize BreakButtonGroupCommand!");
+ delete cmd;
+ }
+}
+
+// ButtonGroupTaskMenu
+ButtonGroupTaskMenu::ButtonGroupTaskMenu(QButtonGroup *buttonGroup, QObject *parent) :
+ QObject(parent),
+ m_buttonGroup(buttonGroup)
+{
+ m_taskActions.push_back(m_menu.breakGroupAction());
+ m_taskActions.push_back(m_menu.selectGroupAction());
+}
+
+QAction *ButtonGroupTaskMenu::preferredEditAction() const
+{
+ return m_menu.selectGroupAction();
+}
+
+QList<QAction*> ButtonGroupTaskMenu::taskActions() const
+{
+ m_menu.initialize(QDesignerFormWindowInterface::findFormWindow(m_buttonGroup), m_buttonGroup);
+ return m_taskActions;
+}
+
+// -------- Text area editor
+class ButtonTextTaskMenuInlineEditor : public TaskMenuInlineEditor
+{
+public:
+ ButtonTextTaskMenuInlineEditor(QAbstractButton *button, QObject *parent);
+
+protected:
+ virtual QRect editRectangle() const;
+};
+
+ButtonTextTaskMenuInlineEditor::ButtonTextTaskMenuInlineEditor(QAbstractButton *button, QObject *parent) :
+ TaskMenuInlineEditor(button, ValidationMultiLine, QLatin1String("text"), parent)
+{
+}
+
+QRect ButtonTextTaskMenuInlineEditor::editRectangle() const
+{
+ QWidget *w = widget();
+ QStyleOptionButton opt;
+ opt.init(w);
+ return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
+}
+
+// -------- Command link button description editor
+class LinkDescriptionTaskMenuInlineEditor : public TaskMenuInlineEditor
+{
+public:
+ LinkDescriptionTaskMenuInlineEditor(QAbstractButton *button, QObject *parent);
+
+protected:
+ virtual QRect editRectangle() const;
+};
+
+LinkDescriptionTaskMenuInlineEditor::LinkDescriptionTaskMenuInlineEditor(QAbstractButton *button, QObject *parent) :
+ TaskMenuInlineEditor(button, ValidationMultiLine, QLatin1String("description"), parent)
+{
+}
+
+QRect LinkDescriptionTaskMenuInlineEditor::editRectangle() const
+{
+ QWidget *w = widget(); // TODO: What is the exact description area?
+ QStyleOptionButton opt;
+ opt.init(w);
+ return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
+}
+
+// ----------- ButtonTaskMenu:
+
+ButtonTaskMenu::ButtonTaskMenu(QAbstractButton *button, QObject *parent) :
+ QDesignerTaskMenu(button, parent),
+ m_assignGroupSubMenu(new QMenu),
+ m_assignActionGroup(0),
+ m_assignToGroupSubMenuAction(new QAction(tr("Assign to button group"), this)),
+ m_currentGroupSubMenu(new QMenu),
+ m_currentGroupSubMenuAction(new QAction(tr("Button group"), this)),
+ m_createGroupAction(new QAction(tr("New button group"), this)),
+ m_preferredEditAction(new QAction(tr("Change text..."), this)),
+ m_removeFromGroupAction(new QAction(tr("None"), this))
+{
+ connect(m_createGroupAction, SIGNAL(triggered()), this, SLOT(createGroup()));
+ TaskMenuInlineEditor *textEditor = new ButtonTextTaskMenuInlineEditor(button, this);
+ connect(m_preferredEditAction, SIGNAL(triggered()), textEditor, SLOT(editText()));
+ connect(m_removeFromGroupAction, SIGNAL(triggered()), this, SLOT(removeFromGroup()));
+
+ m_assignToGroupSubMenuAction->setMenu(m_assignGroupSubMenu);
+
+ m_currentGroupSubMenu->addAction(m_groupMenu.breakGroupAction());
+ m_currentGroupSubMenu->addAction(m_groupMenu.selectGroupAction());
+ m_currentGroupSubMenuAction->setMenu(m_currentGroupSubMenu);
+
+
+ m_taskActions.append(m_preferredEditAction);
+ m_taskActions.append(m_assignToGroupSubMenuAction);
+ m_taskActions.append(m_currentGroupSubMenuAction);
+ m_taskActions.append(createSeparator());
+}
+
+ButtonTaskMenu::~ButtonTaskMenu()
+{
+ delete m_assignGroupSubMenu;
+ delete m_currentGroupSubMenu;
+}
+
+QAction *ButtonTaskMenu::preferredEditAction() const
+{
+ return m_preferredEditAction;
+}
+
+bool ButtonTaskMenu::refreshAssignMenu(const QDesignerFormWindowInterface *fw, int buttonCount, SelectionType st, QButtonGroup *currentGroup)
+{
+ // clear
+ if (m_assignActionGroup) {
+ delete m_assignActionGroup;
+ m_assignActionGroup = 0;
+ }
+ m_assignGroupSubMenu->clear();
+ if (st == OtherSelection)
+ return false;
+
+
+ // Assign to new: Need several
+ const bool canAssignToNewGroup = buttonCount > 1;
+ m_createGroupAction->setEnabled(canAssignToNewGroup);
+ if (canAssignToNewGroup)
+ m_assignGroupSubMenu->addAction(m_createGroupAction);
+
+ // Assign to other
+ const ButtonGroupList bl = ButtonGroupCommand::managedButtonGroups(fw);
+ // Groups: Any groups to add to except the current?
+ const int groupCount = bl.size();
+ const bool hasAddGroups = groupCount > 1 || (groupCount == 1 && !bl.contains(currentGroup));
+ if (hasAddGroups) {
+ if (!m_assignGroupSubMenu->isEmpty())
+ m_assignGroupSubMenu->addSeparator();
+ // Create a new action group
+ m_assignActionGroup = new QActionGroup(this);
+ connect(m_assignActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(addToGroup(QAction*)));
+
+ const ButtonGroupList::const_iterator cend = bl.constEnd();
+ for (ButtonGroupList::const_iterator it = bl.constBegin(); it != cend; ++it) {
+ QButtonGroup *bg = *it;
+ if (*it != currentGroup) {
+ QAction *a = new QAction(bg->objectName(), m_assignGroupSubMenu);
+ a->setData(qVariantFromValue(bg));
+ m_assignActionGroup->addAction(a);
+ m_assignGroupSubMenu->addAction(a);
+ }
+ }
+ }
+ // Can remove: A homogenous selection of another group that does not completely break it.
+ const bool canRemoveFromGroup = st == GroupedButtonSelection;
+ m_removeFromGroupAction->setEnabled(canRemoveFromGroup);
+ if (canRemoveFromGroup) {
+ if (!m_assignGroupSubMenu->isEmpty())
+ m_assignGroupSubMenu->addSeparator();
+ m_assignGroupSubMenu->addAction(m_removeFromGroupAction);
+ }
+ return !m_assignGroupSubMenu->isEmpty();
+}
+
+QList<QAction*> ButtonTaskMenu::taskActions() const
+{
+ ButtonTaskMenu *ncThis = const_cast<ButtonTaskMenu*>(this);
+ QButtonGroup *buttonGroup;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ const SelectionType st = selectionType(fw->cursor(), &buttonGroup);
+
+ m_groupMenu.initialize(fw, buttonGroup, button());
+ const bool hasAssignOptions = ncThis->refreshAssignMenu(fw, fw->cursor()->selectedWidgetCount(), st, buttonGroup);
+ m_assignToGroupSubMenuAction->setVisible(hasAssignOptions);
+ // add/remove
+ switch (st) {
+ case UngroupedButtonSelection:
+ case OtherSelection:
+ m_currentGroupSubMenuAction->setVisible(false);
+ break;
+ case GroupedButtonSelection:
+ m_currentGroupSubMenuAction->setText(tr("Button group '%1'").arg(buttonGroup->objectName()));
+ m_currentGroupSubMenuAction->setVisible(true);
+ break;
+ }
+
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+
+void ButtonTaskMenu::insertAction(int index, QAction *a)
+{
+ m_taskActions.insert(index, a);
+}
+
+/* Create a button list from the cursor selection */
+static ButtonList buttonList(const QDesignerFormWindowCursorInterface *cursor)
+{
+ ButtonList rc;
+ const int selectionCount = cursor->selectedWidgetCount();
+ for (int i = 0; i < selectionCount; i++) {
+ QAbstractButton *ab = qobject_cast<QAbstractButton *>(cursor->selectedWidget(i));
+ Q_ASSERT(ab);
+ rc += ab;
+ }
+ return rc;
+}
+
+// Create a command to remove the buttons from their group
+// If it would leave an empty or 1-member group behind, create a break command instead
+
+static QUndoCommand *createRemoveButtonsCommand(QDesignerFormWindowInterface *fw, const ButtonList &bl)
+{
+
+ QButtonGroup *bg = bl.front()->group();
+ // Complete group or 1-member group?
+ if (bl.size() >= bg->buttons().size() - 1) {
+ BreakButtonGroupCommand *breakCmd = new BreakButtonGroupCommand(fw);
+ if (!breakCmd->init(bg)) {
+ qWarning("** WARNING Failed to initialize BreakButtonGroupCommand!");
+ delete breakCmd;
+ return 0;
+ }
+ return breakCmd;
+ }
+ // Just remove the buttons
+
+ RemoveButtonsFromGroupCommand *removeCmd = new RemoveButtonsFromGroupCommand(fw);
+ if (!removeCmd->init(bl)) {
+ qWarning("** WARNING Failed to initialize RemoveButtonsFromGroupCommand!");
+ delete removeCmd;
+ return 0;
+ }
+ return removeCmd;
+}
+
+void ButtonTaskMenu::createGroup()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ const ButtonList bl = buttonList(fw->cursor());
+ // Do we need to remove the buttons from an existing group?
+ QUndoCommand *removeCmd = 0;
+ if (bl.front()->group()) {
+ removeCmd = createRemoveButtonsCommand(fw, bl);
+ if (!removeCmd)
+ return;
+ }
+ // Add cmd
+ CreateButtonGroupCommand *addCmd = new CreateButtonGroupCommand(fw);
+ if (!addCmd->init(bl)) {
+ qWarning("** WARNING Failed to initialize CreateButtonGroupCommand!");
+ delete addCmd;
+ return;
+ }
+ // Need a macro [even if we only have the add command] since the command might trigger additional commands
+ QUndoStack *history = fw->commandHistory();
+ history->beginMacro(addCmd->text());
+ if (removeCmd)
+ history->push(removeCmd);
+ history->push(addCmd);
+ history->endMacro();
+}
+
+QAbstractButton *ButtonTaskMenu::button() const
+{
+ return qobject_cast<QAbstractButton *>(widget());
+}
+
+// Figure out if we have a homogenous selections (buttons of the same group or no group)
+ButtonTaskMenu::SelectionType ButtonTaskMenu::selectionType(const QDesignerFormWindowCursorInterface *cursor, QButtonGroup **ptrToGroup) const
+{
+ const int selectionCount = cursor->selectedWidgetCount();
+ if (!selectionCount)
+ return OtherSelection;
+
+ QButtonGroup *commonGroup = 0;
+ for (int i = 0; i < selectionCount; i++) {
+ if (const QAbstractButton *ab = qobject_cast<const QAbstractButton *>(cursor->selectedWidget(i))) {
+ QButtonGroup *buttonGroup = ab->group();
+ if (i) {
+ if (buttonGroup != commonGroup)
+ return OtherSelection;
+ } else {
+ commonGroup = buttonGroup;
+ }
+ } else {
+ return OtherSelection;
+ }
+ }
+
+ if (ptrToGroup)
+ *ptrToGroup = commonGroup;
+
+ return commonGroup ? GroupedButtonSelection : UngroupedButtonSelection;
+}
+
+void ButtonTaskMenu::addToGroup(QAction *a)
+{
+ QButtonGroup *bg = qvariant_cast<QButtonGroup *>(a->data());
+ Q_ASSERT(bg);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ const ButtonList bl = buttonList(fw->cursor());
+ // Do we need to remove the buttons from an existing group?
+ QUndoCommand *removeCmd = 0;
+ if (bl.front()->group()) {
+ removeCmd = createRemoveButtonsCommand(fw, bl);
+ if (!removeCmd)
+ return;
+ }
+ AddButtonsToGroupCommand *addCmd = new AddButtonsToGroupCommand(fw);
+ addCmd->init(bl, bg);
+
+ QUndoStack *history = fw->commandHistory();
+ if (removeCmd) {
+ history->beginMacro(addCmd->text());
+ history->push(removeCmd);
+ history->push(addCmd);
+ history->endMacro();
+ } else {
+ history->push(addCmd);
+ }
+}
+
+void ButtonTaskMenu::removeFromGroup()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (QUndoCommand *cmd = createRemoveButtonsCommand(fw, buttonList(fw->cursor())))
+ fw->commandHistory()->push(cmd);
+}
+
+// -------------- CommandLinkButtonTaskMenu
+
+CommandLinkButtonTaskMenu::CommandLinkButtonTaskMenu(QCommandLinkButton *button, QObject *parent) :
+ ButtonTaskMenu(button, parent)
+{
+ TaskMenuInlineEditor *descriptonEditor = new LinkDescriptionTaskMenuInlineEditor(button, this);
+ QAction *descriptionAction = new QAction(tr("Change description..."), this);
+ connect(descriptionAction, SIGNAL(triggered()), descriptonEditor, SLOT(editText()));
+ insertAction(1, descriptionAction);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/button_taskmenu.h b/tools/designer/src/components/taskmenu/button_taskmenu.h
new file mode 100644
index 0000000000..1681f347e1
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/button_taskmenu.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BUTTON_TASKMENU_H
+#define BUTTON_TASKMENU_H
+
+#include <QtGui/QAbstractButton>
+#include <QtGui/QCommandLinkButton>
+#include <QtGui/QButtonGroup>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMenu;
+class QActionGroup;
+class QDesignerFormWindowCursorInterface;
+
+namespace qdesigner_internal {
+
+// ButtonGroupMenu: Mixin menu for the 'select members'/'break group' options of
+// the task menu of buttons and button group
+class ButtonGroupMenu : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ButtonGroupMenu)
+public:
+ ButtonGroupMenu(QObject *parent = 0);
+
+ void initialize(QDesignerFormWindowInterface *formWindow,
+ QButtonGroup *buttonGroup = 0,
+ /* Current button for selection in ButtonMode */
+ QAbstractButton *currentButton = 0);
+
+ QAction *selectGroupAction() const { return m_selectGroupAction; }
+ QAction *breakGroupAction() const { return m_breakGroupAction; }
+
+private slots:
+ void selectGroup();
+ void breakGroup();
+
+private:
+ QAction *m_selectGroupAction;
+ QAction *m_breakGroupAction;
+
+ QDesignerFormWindowInterface *m_formWindow;
+ QButtonGroup *m_buttonGroup;
+ QAbstractButton *m_currentButton;
+};
+
+// Task menu extension of a QButtonGroup
+class ButtonGroupTaskMenu : public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ButtonGroupTaskMenu)
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit ButtonGroupTaskMenu(QButtonGroup *buttonGroup, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private:
+ QButtonGroup *m_buttonGroup;
+ QList<QAction*> m_taskActions;
+ mutable ButtonGroupMenu m_menu;
+};
+
+// Task menu extension of a QAbstractButton
+class ButtonTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ButtonTaskMenu)
+public:
+ explicit ButtonTaskMenu(QAbstractButton *button, QObject *parent = 0);
+ virtual ~ButtonTaskMenu();
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+ QAbstractButton *button() const;
+
+protected:
+ void insertAction(int index, QAction *a);
+
+private slots:
+ void createGroup();
+ void addToGroup(QAction *a);
+ void removeFromGroup();
+
+private:
+ enum SelectionType {
+ OtherSelection,
+ UngroupedButtonSelection,
+ GroupedButtonSelection
+ };
+
+ SelectionType selectionType(const QDesignerFormWindowCursorInterface *cursor, QButtonGroup ** ptrToGroup = 0) const;
+ bool refreshAssignMenu(const QDesignerFormWindowInterface *fw, int buttonCount, SelectionType st, QButtonGroup *currentGroup);
+ QMenu *createGroupSelectionMenu(const QDesignerFormWindowInterface *fw);
+
+ QList<QAction*> m_taskActions;
+ mutable ButtonGroupMenu m_groupMenu;
+ QMenu *m_assignGroupSubMenu;
+ QActionGroup *m_assignActionGroup;
+ QAction *m_assignToGroupSubMenuAction;
+ QMenu *m_currentGroupSubMenu;
+ QAction *m_currentGroupSubMenuAction;
+
+ QAction *m_createGroupAction;
+ QAction *m_preferredEditAction;
+ QAction *m_removeFromGroupAction;
+};
+
+// Task menu extension of a QCommandLinkButton
+class CommandLinkButtonTaskMenu: public ButtonTaskMenu
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(CommandLinkButtonTaskMenu)
+public:
+ explicit CommandLinkButtonTaskMenu(QCommandLinkButton *button, QObject *parent = 0);
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QButtonGroup, ButtonGroupTaskMenu> ButtonGroupTaskMenuFactory;
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QCommandLinkButton, CommandLinkButtonTaskMenu> CommandLinkButtonTaskMenuFactory;
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QAbstractButton, ButtonTaskMenu> ButtonTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // BUTTON_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/combobox_taskmenu.cpp b/tools/designer/src/components/taskmenu/combobox_taskmenu.cpp
new file mode 100644
index 0000000000..e3364cc564
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/combobox_taskmenu.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ComboBoxTaskMenu
+*/
+
+#include "combobox_taskmenu.h"
+#include "listwidgeteditor.h"
+#include "qdesigner_utils_p.h"
+#include <qdesigner_command_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QStyle>
+#include <QtGui/QLineEdit>
+#include <QtGui/QFontComboBox>
+#include <QtGui/QStyleOption>
+
+#include <QtCore/QEvent>
+#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+ComboBoxTaskMenu::ComboBoxTaskMenu(QComboBox *button, QObject *parent)
+ : QDesignerTaskMenu(button, parent),
+ m_comboBox(button)
+{
+ m_editItemsAction = new QAction(this);
+ m_editItemsAction->setText(tr("Edit Items..."));
+ connect(m_editItemsAction, SIGNAL(triggered()), this, SLOT(editItems()));
+ m_taskActions.append(m_editItemsAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+ComboBoxTaskMenu::~ComboBoxTaskMenu()
+{
+}
+
+QAction *ComboBoxTaskMenu::preferredEditAction() const
+{
+ return m_editItemsAction;
+}
+
+QList<QAction*> ComboBoxTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+void ComboBoxTaskMenu::editItems()
+{
+ m_formWindow = QDesignerFormWindowInterface::findFormWindow(m_comboBox);
+ if (m_formWindow.isNull())
+ return;
+
+ Q_ASSERT(m_comboBox != 0);
+
+ ListWidgetEditor dlg(m_formWindow, m_comboBox->window());
+ ListContents oldItems = dlg.fillContentsFromComboBox(m_comboBox);
+ if (dlg.exec() == QDialog::Accepted) {
+ ListContents items = dlg.contents();
+ if (items != oldItems) {
+ ChangeListContentsCommand *cmd = new ChangeListContentsCommand(m_formWindow);
+ cmd->init(m_comboBox, oldItems, items);
+ cmd->setText(tr("Change Combobox Contents"));
+ m_formWindow->commandHistory()->push(cmd);
+ }
+ }
+}
+
+ComboBoxTaskMenuFactory::ComboBoxTaskMenuFactory(const QString &iid, QExtensionManager *extensionManager) :
+ ExtensionFactory<QDesignerTaskMenuExtension, QComboBox, ComboBoxTaskMenu>(iid, extensionManager)
+{
+}
+
+QComboBox *ComboBoxTaskMenuFactory::checkObject(QObject *qObject) const
+{
+ QComboBox *combo = qobject_cast<QComboBox*>(qObject);
+ if (!combo)
+ return 0;
+ if (qobject_cast<QFontComboBox*>(combo))
+ return 0;
+ return combo;
+}
+
+void ComboBoxTaskMenu::updateSelection()
+{
+ if (m_editor)
+ m_editor->deleteLater();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/combobox_taskmenu.h b/tools/designer/src/components/taskmenu/combobox_taskmenu.h
new file mode 100644
index 0000000000..9f80e40a61
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/combobox_taskmenu.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COMBOBOX_TASKMENU_H
+#define COMBOBOX_TASKMENU_H
+
+#include <QtGui/QComboBox>
+#include <QtCore/QPointer>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QLineEdit;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class ComboBoxTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit ComboBoxTaskMenu(QComboBox *button,
+ QObject *parent = 0);
+ virtual ~ComboBoxTaskMenu();
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void editItems();
+ void updateSelection();
+
+private:
+ QComboBox *m_comboBox;
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ QPointer<QLineEdit> m_editor;
+ mutable QList<QAction*> m_taskActions;
+ QAction *m_editItemsAction;
+};
+
+class ComboBoxTaskMenuFactory : public ExtensionFactory<QDesignerTaskMenuExtension, QComboBox, ComboBoxTaskMenu>
+{
+public:
+ explicit ComboBoxTaskMenuFactory(const QString &iid, QExtensionManager *extensionManager);
+
+private:
+ virtual QComboBox *checkObject(QObject *qObject) const;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // COMBOBOX_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/containerwidget_taskmenu.cpp b/tools/designer/src/components/taskmenu/containerwidget_taskmenu.cpp
new file mode 100644
index 0000000000..b182ddf75e
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/containerwidget_taskmenu.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ContainerWidgetTaskMenu
+*/
+
+#include "containerwidget_taskmenu.h"
+
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerContainerExtension>
+
+#include <qdesigner_command_p.h>
+#include <qdesigner_dockwidget_p.h>
+#include <promotiontaskmenu_p.h>
+#include <widgetdatabase_p.h>
+
+#include <QtGui/QAction>
+#include <QtGui/QMainWindow>
+#include <QtGui/QToolBox>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QTabWidget>
+#include <QtGui/QScrollArea>
+#include <QtGui/QMdiArea>
+#include <QtGui/QWorkspace>
+#include <QtGui/QWizard>
+#include <QtGui/QMenu>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ContainerWidgetTaskMenu::ContainerWidgetTaskMenu(QWidget *widget, ContainerType type, QObject *parent) :
+ QDesignerTaskMenu(widget, parent),
+ m_type(type),
+ m_containerWidget(widget),
+ m_core(formWindow()->core()),
+ m_pagePromotionTaskMenu(new PromotionTaskMenu(0, PromotionTaskMenu::ModeSingleWidget, this)),
+ m_pageMenuAction(new QAction(this)),
+ m_pageMenu(new QMenu),
+ m_actionDeletePage(new QAction(tr("Delete"), this))
+{
+ Q_ASSERT(m_core);
+ m_taskActions.append(createSeparator());
+
+ connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
+
+ QAction *actionInsertPageAfter = new QAction(this);
+ connect(actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
+ // Empty Per-Page submenu, deletion and promotion. Updated on demand due to promotion state
+ switch (m_type) {
+ case WizardContainer:
+ case PageContainer:
+ m_taskActions.append(createSeparator()); // for the browse actions
+ break;
+ case MdiContainer:
+ break;
+ }
+ // submenu
+ m_pageMenuAction->setMenu(m_pageMenu);
+ m_taskActions.append(m_pageMenuAction);
+ // Insertion
+ switch (m_type) {
+ case WizardContainer:
+ case PageContainer: { // Before and after in a submenu
+ QAction *insertMenuAction = new QAction(tr("Insert"), this);
+ QMenu *insertMenu = new QMenu;
+ // before
+ QAction *actionInsertPage = new QAction(tr("Insert Page Before Current Page"), this);
+ connect(actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
+ insertMenu->addAction(actionInsertPage);
+ // after
+ actionInsertPageAfter->setText(tr("Insert Page After Current Page"));
+ insertMenu->addAction(actionInsertPageAfter);
+
+ insertMenuAction->setMenu(insertMenu);
+ m_taskActions.append(insertMenuAction);
+ }
+ break;
+ case MdiContainer: // No concept of order
+ actionInsertPageAfter->setText(tr("Add Subwindow"));
+ m_taskActions.append(actionInsertPageAfter);
+ break;
+ }
+}
+
+ContainerWidgetTaskMenu::~ContainerWidgetTaskMenu()
+{
+}
+
+QAction *ContainerWidgetTaskMenu::preferredEditAction() const
+{
+ return 0;
+}
+
+bool ContainerWidgetTaskMenu::canDeletePage() const
+{
+ switch (pageCount()) {
+ case 0:
+ return false;
+ case 1:
+ return m_type != PageContainer; // Do not delete last page of page-type container
+ default:
+ break;
+ }
+ return true;
+}
+
+int ContainerWidgetTaskMenu::pageCount() const
+{
+ if (const QDesignerContainerExtension *ce = containerExtension())
+ return ce->count();
+ return 0;
+}
+
+QString ContainerWidgetTaskMenu::pageMenuText(ContainerType ct, int index, int count)
+{
+ if (ct == MdiContainer)
+ return tr("Subwindow"); // No concept of order, same text everywhere
+ if (index < 0)
+ return tr("Page");
+ return tr("Page %1 of %2").arg(index + 1).arg(count);
+}
+
+QList<QAction*> ContainerWidgetTaskMenu::taskActions() const
+{
+ QList<QAction*> actions = QDesignerTaskMenu::taskActions();
+ actions += m_taskActions;
+ // Update the page submenu, deletion and promotion. Updated on demand due to promotion state.
+ m_pageMenu->clear();
+ m_pageMenu->addAction(m_actionDeletePage);
+ m_actionDeletePage->setEnabled(canDeletePage());
+ const QDesignerContainerExtension *ce = containerExtension();
+ const int index = ce->currentIndex();
+ m_pageMenuAction->setText(pageMenuText(m_type, index, ce->count()));
+ if (index != -1) { // Has a page
+ m_pageMenuAction->setEnabled(true);
+ m_pagePromotionTaskMenu->setWidget(ce->widget(index));
+ m_pagePromotionTaskMenu->addActions(PromotionTaskMenu::LeadingSeparator|PromotionTaskMenu::SuppressGlobalEdit, m_pageMenu);
+ } else { // No page
+ m_pageMenuAction->setEnabled(false);
+ }
+
+ return actions;
+}
+
+QDesignerFormWindowInterface *ContainerWidgetTaskMenu::formWindow() const
+{
+ return QDesignerFormWindowInterface::findFormWindow(m_containerWidget);
+}
+
+QDesignerContainerExtension *ContainerWidgetTaskMenu::containerExtension() const
+{
+ QExtensionManager *mgr = m_core->extensionManager();
+ return qt_extension<QDesignerContainerExtension*>(mgr, m_containerWidget);
+}
+
+void ContainerWidgetTaskMenu::removeCurrentPage()
+{
+ if (QDesignerContainerExtension *c = containerExtension()) {
+ if (c->currentIndex() == -1)
+ return;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ DeleteContainerWidgetPageCommand *cmd = new DeleteContainerWidgetPageCommand(fw);
+ cmd->init(m_containerWidget, m_type);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void ContainerWidgetTaskMenu::addPage()
+{
+ if (containerExtension()) {
+ QDesignerFormWindowInterface *fw = formWindow();
+ AddContainerWidgetPageCommand *cmd = new AddContainerWidgetPageCommand(fw);
+ cmd->init(m_containerWidget, m_type, AddContainerWidgetPageCommand::InsertBefore);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void ContainerWidgetTaskMenu::addPageAfter()
+{
+ if (containerExtension()) {
+ QDesignerFormWindowInterface *fw = formWindow();
+ AddContainerWidgetPageCommand *cmd = new AddContainerWidgetPageCommand(fw);
+ cmd->init(m_containerWidget, m_type, AddContainerWidgetPageCommand::InsertAfter);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+// -------------- WizardContainerWidgetTaskMenu
+WizardContainerWidgetTaskMenu::WizardContainerWidgetTaskMenu(QWizard *w, QObject *parent) :
+ ContainerWidgetTaskMenu(w, WizardContainer, parent),
+ m_nextAction(new QAction(tr("Next"), this)),
+ m_previousAction(new QAction(tr("Back"), this))
+{
+ connect(m_nextAction, SIGNAL(triggered()), w, SLOT(next()));
+ connect(m_previousAction, SIGNAL(triggered()), w, SLOT(back()));
+ QList<QAction*> &l = containerActions();
+ l.push_front(createSeparator());
+ l.push_front(m_nextAction);
+ l.push_front(m_previousAction);
+ l.push_front(createSeparator());
+}
+
+QList<QAction*> WizardContainerWidgetTaskMenu::taskActions() const
+{
+ // Enable
+ const QDesignerContainerExtension *ce = containerExtension();
+ const int index = ce->currentIndex();
+ m_previousAction->setEnabled(index > 0);
+ m_nextAction->setEnabled(index >= 0 && index < (ce->count() - 1));
+ return ContainerWidgetTaskMenu::taskActions();
+}
+
+// -------------- MdiContainerWidgetTaskMenu
+
+MdiContainerWidgetTaskMenu::MdiContainerWidgetTaskMenu(QMdiArea *m, QObject *parent) :
+ ContainerWidgetTaskMenu(m, MdiContainer, parent)
+{
+ initializeActions();
+ connect(m_nextAction, SIGNAL(triggered()), m, SLOT( activateNextSubWindow ()));
+ connect(m_previousAction, SIGNAL(triggered()), m , SLOT(activatePreviousSubWindow()));
+ connect(m_tileAction, SIGNAL(triggered()), m, SLOT(tileSubWindows()));
+ connect(m_cascadeAction, SIGNAL(triggered()), m, SLOT(cascadeSubWindows ()));
+}
+
+MdiContainerWidgetTaskMenu::MdiContainerWidgetTaskMenu(QWorkspace *m, QObject *parent) :
+ ContainerWidgetTaskMenu(m, MdiContainer, parent)
+{
+ initializeActions();
+ connect(m_nextAction, SIGNAL(triggered()), m, SLOT(activateNextWindow()));
+ connect(m_previousAction, SIGNAL(triggered()), m, SLOT(activatePreviousWindow()));
+ connect(m_tileAction, SIGNAL(triggered()),m , SLOT(tile()));
+ connect(m_cascadeAction, SIGNAL(triggered()), m, SLOT(cascade()));
+}
+
+void MdiContainerWidgetTaskMenu::initializeActions()
+{
+ m_nextAction =new QAction(tr("Next Subwindow"), this);
+ m_previousAction = new QAction(tr("Previous Subwindow"), this);
+ m_tileAction = new QAction(tr("Tile"), this);
+ m_cascadeAction = new QAction(tr("Cascade"), this);
+
+ QList<QAction*> &l = containerActions();
+ l.push_front(createSeparator());
+ l.push_front(m_tileAction);
+ l.push_front(m_cascadeAction);
+ l.push_front(m_previousAction);
+ l.push_front(m_nextAction);
+ l.push_front(createSeparator());
+}
+
+QList<QAction*> MdiContainerWidgetTaskMenu::taskActions() const
+{
+ const QList<QAction*> rc = ContainerWidgetTaskMenu::taskActions();
+ // Enable
+ const int count = pageCount();
+ m_nextAction->setEnabled(count > 1);
+ m_previousAction->setEnabled(count > 1);
+ m_tileAction->setEnabled(count);
+ m_cascadeAction->setEnabled(count);
+ return rc;
+}
+
+// -------------- ContainerWidgetTaskMenuFactory
+
+ContainerWidgetTaskMenuFactory::ContainerWidgetTaskMenuFactory(QDesignerFormEditorInterface *core, QExtensionManager *extensionManager) :
+ QExtensionFactory(extensionManager),
+ m_core(core)
+{
+}
+
+QObject *ContainerWidgetTaskMenuFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != QLatin1String("QDesignerInternalTaskMenuExtension") || !object->isWidgetType())
+ return 0;
+
+ QWidget *widget = qobject_cast<QWidget*>(object);
+
+ if (qobject_cast<QStackedWidget*>(widget)
+ || qobject_cast<QToolBox*>(widget)
+ || qobject_cast<QTabWidget*>(widget)
+ || qobject_cast<QDesignerDockWidget*>(widget)
+ || qobject_cast<QScrollArea*>(widget)
+ || qobject_cast<QMainWindow*>(widget)) {
+ // Are we using Designer's own container extensions and task menus or did
+ // someone provide an extra one with an addpage method, for example for a QScrollArea?
+ if (const WidgetDataBase *wb = qobject_cast<const WidgetDataBase *>(m_core->widgetDataBase())) {
+ const int idx = wb->indexOfObject(widget);
+ const WidgetDataBaseItem *item = static_cast<const WidgetDataBaseItem *>(wb->item(idx));
+ if (item->addPageMethod().isEmpty())
+ return 0;
+ }
+ }
+
+ if (qt_extension<QDesignerContainerExtension*>(extensionManager(), object) == 0)
+ return 0;
+
+ if (QMdiArea* ma = qobject_cast<QMdiArea*>(widget))
+ return new MdiContainerWidgetTaskMenu(ma, parent);
+ if (QWorkspace *ws = qobject_cast<QWorkspace*>(widget))
+ return new MdiContainerWidgetTaskMenu(ws, parent);
+ if (QWizard *wz = qobject_cast<QWizard *>(widget))
+ return new WizardContainerWidgetTaskMenu(wz, parent);
+ return new ContainerWidgetTaskMenu(widget, PageContainer, parent);
+}
+
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/containerwidget_taskmenu.h b/tools/designer/src/components/taskmenu/containerwidget_taskmenu.h
new file mode 100644
index 0000000000..25e24edbb0
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/containerwidget_taskmenu.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONTAINERWIDGER_TASKMENU_H
+#define CONTAINERWIDGER_TASKMENU_H
+
+#include <qdesigner_taskmenu_p.h>
+#include <shared_enums_p.h>
+
+#include <extensionfactory_p.h>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+class QDesignerContainerExtension;
+class QAction;
+class QMdiArea;
+class QWorkspace;
+class QMenu;
+class QWizard;
+
+namespace qdesigner_internal {
+
+class PromotionTaskMenu;
+
+// ContainerWidgetTaskMenu: Task menu for containers with extension
+
+class ContainerWidgetTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit ContainerWidgetTaskMenu(QWidget *widget, ContainerType type, QObject *parent = 0);
+ virtual ~ContainerWidgetTaskMenu();
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void removeCurrentPage();
+ void addPage();
+ void addPageAfter();
+
+protected:
+ QDesignerContainerExtension *containerExtension() const;
+ QList<QAction*> &containerActions() { return m_taskActions; }
+ int pageCount() const;
+
+private:
+ QDesignerFormWindowInterface *formWindow() const;
+
+private:
+ static QString pageMenuText(ContainerType ct, int index, int count);
+ bool canDeletePage() const;
+
+ const ContainerType m_type;
+ QWidget *m_containerWidget;
+ QDesignerFormEditorInterface *m_core;
+ PromotionTaskMenu *m_pagePromotionTaskMenu;
+ QAction *m_pageMenuAction;
+ QMenu *m_pageMenu;
+ QList<QAction*> m_taskActions;
+ QAction *m_actionDeletePage;
+};
+
+// WizardContainerWidgetTaskMenu: Provide next/back since QWizard
+// has modes in which the "Back" button is not visible.
+
+class WizardContainerWidgetTaskMenu : public ContainerWidgetTaskMenu {
+ Q_OBJECT
+public:
+ explicit WizardContainerWidgetTaskMenu(QWizard *w, QObject *parent = 0);
+
+ virtual QList<QAction*> taskActions() const;
+
+private:
+ QAction *m_nextAction;
+ QAction *m_previousAction;
+};
+
+
+// MdiContainerWidgetTaskMenu: Provide tile/cascade for MDI containers in addition
+
+class MdiContainerWidgetTaskMenu : public ContainerWidgetTaskMenu {
+ Q_OBJECT
+public:
+ explicit MdiContainerWidgetTaskMenu(QMdiArea *m, QObject *parent = 0);
+ explicit MdiContainerWidgetTaskMenu(QWorkspace *m, QObject *parent = 0);
+
+ virtual QList<QAction*> taskActions() const;
+private:
+ void initializeActions();
+
+ QAction *m_nextAction;
+ QAction *m_previousAction;
+ QAction *m_tileAction;
+ QAction *m_cascadeAction;
+};
+
+class ContainerWidgetTaskMenuFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ explicit ContainerWidgetTaskMenuFactory(QDesignerFormEditorInterface *core, QExtensionManager *extensionManager = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // CONTAINERWIDGER_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/groupbox_taskmenu.cpp b/tools/designer/src/components/taskmenu/groupbox_taskmenu.cpp
new file mode 100644
index 0000000000..bb973423c6
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/groupbox_taskmenu.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::GroupBoxTaskMenu
+*/
+
+#include "groupbox_taskmenu.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// -------- GroupBoxTaskMenuInlineEditor
+class GroupBoxTaskMenuInlineEditor : public TaskMenuInlineEditor
+{
+public:
+ GroupBoxTaskMenuInlineEditor(QGroupBox *button, QObject *parent);
+
+protected:
+ virtual QRect editRectangle() const;
+};
+
+GroupBoxTaskMenuInlineEditor::GroupBoxTaskMenuInlineEditor(QGroupBox *w, QObject *parent) :
+ TaskMenuInlineEditor(w, ValidationSingleLine, QLatin1String("title"), parent)
+{
+}
+
+QRect GroupBoxTaskMenuInlineEditor::editRectangle() const
+{
+ QWidget *w = widget();
+ QStyleOption opt; // ## QStyleOptionGroupBox
+ opt.init(w);
+ return QRect(QPoint(), QSize(w->width(),20));
+}
+
+// --------------- GroupBoxTaskMenu
+
+GroupBoxTaskMenu::GroupBoxTaskMenu(QGroupBox *groupbox, QObject *parent)
+ : QDesignerTaskMenu(groupbox, parent),
+ m_editTitleAction(new QAction(tr("Change title..."), this))
+
+{
+ TaskMenuInlineEditor *editor = new GroupBoxTaskMenuInlineEditor(groupbox, this);
+ connect(m_editTitleAction, SIGNAL(triggered()), editor, SLOT(editText()));
+ m_taskActions.append(m_editTitleAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+QList<QAction*> GroupBoxTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+QAction *GroupBoxTaskMenu::preferredEditAction() const
+{
+ return m_editTitleAction;
+}
+
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/groupbox_taskmenu.h b/tools/designer/src/components/taskmenu/groupbox_taskmenu.h
new file mode 100644
index 0000000000..8e2d36fc80
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/groupbox_taskmenu.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GROUPBOX_TASKMENU_H
+#define GROUPBOX_TASKMENU_H
+
+#include <QtGui/QGroupBox>
+#include <QtCore/QPointer>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+class InPlaceEditor;
+
+class GroupBoxTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit GroupBoxTaskMenu(QGroupBox *groupbox, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private:
+ QAction *m_editTitleAction;
+ QList<QAction*> m_taskActions;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QGroupBox, GroupBoxTaskMenu> GroupBoxTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // GROUPBOX_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/inplace_editor.cpp b/tools/designer/src/components/taskmenu/inplace_editor.cpp
new file mode 100644
index 0000000000..322d1ede66
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/inplace_editor.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindow.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ----------------- InPlaceEditor
+
+InPlaceEditor::InPlaceEditor(QWidget *widget,
+ TextPropertyValidationMode validationMode,
+ QDesignerFormWindowInterface *fw,
+ const QString& text,
+ const QRect& r) :
+ TextPropertyEditor(widget, EmbeddingInPlace, validationMode),
+ m_InPlaceWidgetHelper(this, widget, fw)
+{
+ setAlignment(m_InPlaceWidgetHelper.alignment());
+ setObjectName(QLatin1String("__qt__passive_m_editor"));
+
+ setText(text);
+ selectAll();
+
+ setGeometry(QRect(widget->mapTo(widget->window(), r.topLeft()), r.size()));
+ setFocus();
+ show();
+
+ connect(this, SIGNAL(editingFinished()),this, SLOT(close()));
+}
+
+
+// -------------- TaskMenuInlineEditor
+
+TaskMenuInlineEditor::TaskMenuInlineEditor(QWidget *w, TextPropertyValidationMode vm,
+ const QString &property, QObject *parent) :
+ QObject(parent),
+ m_vm(vm),
+ m_property(property),
+ m_widget(w),
+ m_managed(true)
+{
+}
+
+void TaskMenuInlineEditor::editText()
+{
+ m_formWindow = QDesignerFormWindowInterface::findFormWindow(m_widget);
+ if (m_formWindow.isNull())
+ return;
+ m_managed = m_formWindow->isManaged(m_widget);
+ // Close as soon as a different widget is selected
+ connect(m_formWindow, SIGNAL(selectionChanged()), this, SLOT(updateSelection()));
+
+ // get old value
+ QDesignerFormEditorInterface *core = m_formWindow->core();
+ const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), m_widget);
+ const int index = sheet->indexOf(m_property);
+ if (index == -1)
+ return;
+ m_value = qVariantValue<PropertySheetStringValue>(sheet->property(index));
+ const QString oldValue = m_value.value();
+
+ m_editor = new InPlaceEditor(m_widget, m_vm, m_formWindow, oldValue, editRectangle());
+ connect(m_editor, SIGNAL(textChanged(QString)), this, SLOT(updateText(QString)));
+}
+
+void TaskMenuInlineEditor::updateText(const QString &text)
+{
+ // In the [rare] event we are invoked on an unmanaged widget,
+ // do not use the cursor selection
+ m_value.setValue(text);
+ if (m_managed) {
+ m_formWindow->cursor()->setProperty(m_property, qVariantFromValue(m_value));
+ } else {
+ m_formWindow->cursor()->setWidgetProperty(m_widget, m_property, qVariantFromValue(m_value));
+ }
+}
+
+void TaskMenuInlineEditor::updateSelection()
+{
+ if (m_editor)
+ m_editor->deleteLater();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/inplace_editor.h b/tools/designer/src/components/taskmenu/inplace_editor.h
new file mode 100644
index 0000000000..8c59aeb1ca
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/inplace_editor.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INPLACE_EDITOR_H
+#define INPLACE_EDITOR_H
+
+#include <textpropertyeditor_p.h>
+#include <shared_enums_p.h>
+
+#include "inplace_widget_helper.h"
+#include <qdesigner_utils_p.h>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class InPlaceEditor: public TextPropertyEditor
+{
+ Q_OBJECT
+public:
+ InPlaceEditor(QWidget *widget,
+ TextPropertyValidationMode validationMode,
+ QDesignerFormWindowInterface *fw,
+ const QString& text,
+ const QRect& r);
+private:
+ InPlaceWidgetHelper m_InPlaceWidgetHelper;
+};
+
+// Base class for inline editor helpers to be embedded into a task menu.
+// Inline-edits a property on a multi-selection.
+// To use it for a particular widget/property, overwrite the method
+// returning the edit area.
+
+class TaskMenuInlineEditor : public QObject {
+ TaskMenuInlineEditor(const TaskMenuInlineEditor&);
+ TaskMenuInlineEditor &operator=(const TaskMenuInlineEditor&);
+ Q_OBJECT
+
+public slots:
+ void editText();
+
+private slots:
+ void updateText(const QString &text);
+ void updateSelection();
+
+protected:
+ TaskMenuInlineEditor(QWidget *w, TextPropertyValidationMode vm, const QString &property, QObject *parent);
+ // Overwrite to return the area for the inline editor.
+ virtual QRect editRectangle() const = 0;
+ QWidget *widget() const { return m_widget; }
+
+private:
+ const TextPropertyValidationMode m_vm;
+ const QString m_property;
+ QWidget *m_widget;
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ QPointer<InPlaceEditor> m_editor;
+ bool m_managed;
+ qdesigner_internal::PropertySheetStringValue m_value;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // INPLACE_EDITOR_H
diff --git a/tools/designer/src/components/taskmenu/inplace_widget_helper.cpp b/tools/designer/src/components/taskmenu/inplace_widget_helper.cpp
new file mode 100644
index 0000000000..5cf3df16ce
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/inplace_widget_helper.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindow.h"
+#include "inplace_widget_helper.h"
+
+#include <QtGui/QResizeEvent>
+#include <QtGui/QPushButton>
+#include <QtGui/QToolButton>
+#include <QtGui/QShortcut>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ InPlaceWidgetHelper::InPlaceWidgetHelper(QWidget *editorWidget, QWidget *parentWidget, QDesignerFormWindowInterface *fw)
+ : QObject(0),
+ m_editorWidget(editorWidget),
+ m_parentWidget(parentWidget),
+ m_noChildEvent(m_parentWidget->testAttribute(Qt::WA_NoChildEventsForParent))
+ {
+ m_editorWidget->setAttribute(Qt::WA_DeleteOnClose);
+ m_editorWidget->setParent(m_parentWidget->window());
+ m_parentWidget->installEventFilter(this);
+ m_editorWidget->installEventFilter(this);
+ connect(m_editorWidget, SIGNAL(destroyed()), fw->mainContainer(), SLOT(setFocus()));
+ }
+
+ InPlaceWidgetHelper::~InPlaceWidgetHelper()
+ {
+ m_parentWidget->setAttribute(Qt::WA_NoChildEventsForParent, m_noChildEvent);
+ }
+
+ Qt::Alignment InPlaceWidgetHelper::alignment() const {
+ if (m_parentWidget->metaObject()->indexOfProperty("alignment") != -1)
+ return Qt::Alignment(m_parentWidget->property("alignment").toInt());
+
+ if (qobject_cast<const QPushButton *>(m_parentWidget)
+ || qobject_cast<const QToolButton *>(m_parentWidget) /* tool needs to be more complex */)
+ return Qt::AlignHCenter;
+
+ return Qt::AlignJustify;
+ }
+
+
+ bool InPlaceWidgetHelper::eventFilter(QObject *object, QEvent *e)
+ {
+ if (object == m_parentWidget) {
+ if (e->type() == QEvent::Resize) {
+ const QResizeEvent *event = static_cast<const QResizeEvent*>(e);
+ const QPoint localPos = m_parentWidget->geometry().topLeft();
+ const QPoint globalPos = m_parentWidget->parentWidget() ? m_parentWidget->parentWidget()->mapToGlobal(localPos) : localPos;
+ const QPoint newPos = (m_editorWidget->parentWidget() ? m_editorWidget->parentWidget()->mapFromGlobal(globalPos) : globalPos)
+ + m_posOffset;
+ const QSize newSize = event->size() + m_sizeOffset;
+ m_editorWidget->setGeometry(QRect(newPos, newSize));
+ }
+ } else if (object == m_editorWidget) {
+ if (e->type() == QEvent::ShortcutOverride) {
+ if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
+ e->accept();
+ return false;
+ }
+ } else if (e->type() == QEvent::KeyPress) {
+ if (static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
+ e->accept();
+ m_editorWidget->close();
+ return true;
+ }
+ } else if (e->type() == QEvent::Show) {
+ const QPoint localPos = m_parentWidget->geometry().topLeft();
+ const QPoint globalPos = m_parentWidget->parentWidget() ? m_parentWidget->parentWidget()->mapToGlobal(localPos) : localPos;
+ const QPoint newPos = m_editorWidget->parentWidget() ? m_editorWidget->parentWidget()->mapFromGlobal(globalPos) : globalPos;
+ m_posOffset = m_editorWidget->geometry().topLeft() - newPos;
+ m_sizeOffset = m_editorWidget->size() - m_parentWidget->size();
+ }
+ }
+
+ return QObject::eventFilter(object, e);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/inplace_widget_helper.h b/tools/designer/src/components/taskmenu/inplace_widget_helper.h
new file mode 100644
index 0000000000..2b74d571dc
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/inplace_widget_helper.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef INPLACE_WIDGETHELPER_H
+#define INPLACE_WIDGETHELPER_H
+
+
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+#include <QtCore/QSize>
+#include <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+ // A helper class to make an editor widget suitable for form inline
+ // editing. Derive from the editor widget class and make InPlaceWidgetHelper a member.
+ //
+ // Sets "destructive close" on the editor widget and
+ // wires "ESC" to it.
+ // Installs an event filter on the parent to listen for
+ // resize events and passes them on to the child.
+ // You might want to connect editingFinished() to close() of the editor widget.
+ class InPlaceWidgetHelper: public QObject
+ {
+ Q_OBJECT
+ public:
+ InPlaceWidgetHelper(QWidget *editorWidget, QWidget *parentWidget, QDesignerFormWindowInterface *fw);
+ virtual ~InPlaceWidgetHelper();
+
+ virtual bool eventFilter(QObject *object, QEvent *event);
+
+ // returns a recommended alignment for the editor widget determined from the parent.
+ Qt::Alignment alignment() const;
+ private:
+ QWidget *m_editorWidget;
+ QWidget *m_parentWidget;
+ const bool m_noChildEvent;
+ QPoint m_posOffset;
+ QSize m_sizeOffset;
+ };
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // INPLACE_WIDGETHELPER_H
diff --git a/tools/designer/src/components/taskmenu/itemlisteditor.cpp b/tools/designer/src/components/taskmenu/itemlisteditor.cpp
new file mode 100644
index 0000000000..4e6940e719
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/itemlisteditor.cpp
@@ -0,0 +1,489 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "itemlisteditor.h"
+#include <abstractformbuilder.h>
+#include <iconloader_p.h>
+#include <formwindowbase_p.h>
+#include <designerpropertymanager.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <qttreepropertybrowser.h>
+
+#include <QtGui/QSplitter>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class ItemPropertyBrowser : public QtTreePropertyBrowser
+{
+public:
+ ItemPropertyBrowser()
+ {
+ setResizeMode(Interactive);
+ //: Sample string to determinate the width for the first column of the list item property browser
+ const QString widthSampleString = QCoreApplication::translate("ItemPropertyBrowser", "XX Icon Selected off");
+ m_width = fontMetrics().width(widthSampleString);
+ setSplitterPosition(m_width);
+ m_width += fontMetrics().width(QLatin1String("/this/is/some/random/path"));
+ }
+
+ virtual QSize sizeHint() const
+ {
+ return QSize(m_width, 1);
+ }
+
+private:
+ int m_width;
+};
+
+////////////////// Item editor ///////////////
+AbstractItemEditor::AbstractItemEditor(QDesignerFormWindowInterface *form, QWidget *parent)
+ : QDialog(parent),
+ m_iconCache(qobject_cast<FormWindowBase *>(form)->iconCache()),
+ m_updatingBrowser(false)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ m_propertyManager = new DesignerPropertyManager(form->core(), this);
+ m_editorFactory = new DesignerEditorFactory(form->core(), this);
+ m_editorFactory->setSpacing(0);
+ m_propertyBrowser = new ItemPropertyBrowser;
+ m_propertyBrowser->setFactoryForManager((QtVariantPropertyManager *)m_propertyManager,
+ m_editorFactory);
+
+ connect(m_editorFactory, SIGNAL(resetProperty(QtProperty*)),
+ SLOT(resetProperty(QtProperty*)));
+ connect(m_propertyManager, SIGNAL(valueChanged(QtProperty*,QVariant,bool)),
+ SLOT(propertyChanged(QtProperty*)));
+ connect(iconCache(), SIGNAL(reloaded()), this, SLOT(cacheReloaded()));
+}
+
+AbstractItemEditor::~AbstractItemEditor()
+{
+ m_propertyBrowser->unsetFactoryForManager(m_propertyManager);
+}
+
+void AbstractItemEditor::keyPressEvent(QKeyEvent *e)
+{
+ // Avoid that embedded dialogs react to enter and escape keys.
+ if (this == window())
+ QDialog::keyPressEvent(e);
+ else
+ QWidget::keyPressEvent(e);
+}
+
+static const char * const itemFlagNames[] = {
+ "Selectable",
+ "Editable",
+ "DragEnabled",
+ "DropEnabled",
+ "UserCheckable",
+ "Enabled",
+ "Tristate",
+ 0
+};
+
+static const char * const checkStateNames[] = {
+ "Unchecked",
+ "PartiallyChecked",
+ "Checked",
+ 0
+};
+
+static QStringList c2qStringList(const char * const in[])
+{
+ QStringList out;
+ for (int i = 0; in[i]; i++)
+ out << QLatin1String(in[i]);
+ return out;
+}
+
+void AbstractItemEditor::setupProperties(PropertyDefinition *propList)
+{
+ for (int i = 0; propList[i].name; i++) {
+ int type = propList[i].typeFunc ? propList[i].typeFunc() : propList[i].type;
+ int role = propList[i].role;
+ QtVariantProperty *prop = m_propertyManager->addProperty(type, QLatin1String(propList[i].name));
+ Q_ASSERT(prop);
+ if (role == Qt::ToolTipPropertyRole || role == Qt::WhatsThisPropertyRole)
+ prop->setAttribute(QLatin1String("validationMode"), ValidationRichText);
+ else if (role == Qt::DisplayPropertyRole)
+ prop->setAttribute(QLatin1String("validationMode"), ValidationMultiLine);
+ else if (role == Qt::StatusTipPropertyRole)
+ prop->setAttribute(QLatin1String("validationMode"), ValidationSingleLine);
+ else if (role == ItemFlagsShadowRole)
+ prop->setAttribute(QLatin1String("flagNames"), c2qStringList(itemFlagNames));
+ else if (role == Qt::CheckStateRole)
+ prop->setAttribute(QLatin1String("enumNames"), c2qStringList(checkStateNames));
+ prop->setAttribute(QLatin1String("resettable"), true);
+ m_properties.append(prop);
+ m_rootProperties.append(prop);
+ m_propertyToRole.insert(prop, role);
+ }
+}
+
+void AbstractItemEditor::setupObject(QWidget *object)
+{
+ m_propertyManager->setObject(object);
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(object);
+ FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow);
+ m_editorFactory->setFormWindowBase(fwb);
+}
+
+void AbstractItemEditor::setupEditor(QWidget *object, PropertyDefinition *propList)
+{
+ setupProperties(propList);
+ setupObject(object);
+}
+
+void AbstractItemEditor::propertyChanged(QtProperty *property)
+{
+ if (m_updatingBrowser)
+ return;
+
+
+ BoolBlocker block(m_updatingBrowser);
+ QtVariantProperty *prop = m_propertyManager->variantProperty(property);
+ int role;
+ if ((role = m_propertyToRole.value(prop, -1)) == -1)
+ // Subproperty
+ return;
+
+ if ((role == ItemFlagsShadowRole && prop->value().toInt() == (int)QListWidgetItem().flags())
+ || (role == Qt::DecorationPropertyRole && !qVariantValue<PropertySheetIconValue>(prop->value()).mask())
+ || (role == Qt::FontRole && !qVariantValue<QFont>(prop->value()).resolve())) {
+ prop->setModified(false);
+ setItemData(role, QVariant());
+ } else {
+ prop->setModified(true);
+ setItemData(role, prop->value());
+ }
+
+ switch (role) {
+ case Qt::DecorationPropertyRole:
+ setItemData(Qt::DecorationRole, qVariantFromValue(iconCache()->icon(qVariantValue<PropertySheetIconValue>(prop->value()))));
+ break;
+ case Qt::DisplayPropertyRole:
+ setItemData(Qt::EditRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value()));
+ break;
+ case Qt::ToolTipPropertyRole:
+ setItemData(Qt::ToolTipRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value()));
+ break;
+ case Qt::StatusTipPropertyRole:
+ setItemData(Qt::StatusTipRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value()));
+ break;
+ case Qt::WhatsThisPropertyRole:
+ setItemData(Qt::WhatsThisRole, qVariantFromValue(qVariantValue<PropertySheetStringValue>(prop->value()).value()));
+ break;
+ default:
+ break;
+ }
+
+ prop->setValue(getItemData(role));
+}
+
+void AbstractItemEditor::resetProperty(QtProperty *property)
+{
+ if (m_propertyManager->resetFontSubProperty(property))
+ return;
+
+ if (m_propertyManager->resetIconSubProperty(property))
+ return;
+
+ BoolBlocker block(m_updatingBrowser);
+
+ QtVariantProperty *prop = m_propertyManager->variantProperty(property);
+ int role = m_propertyToRole.value(prop);
+ if (role == ItemFlagsShadowRole)
+ prop->setValue(qVariantFromValue((int)QListWidgetItem().flags()));
+ else
+ prop->setValue(QVariant(prop->valueType(), (void *)0));
+ prop->setModified(false);
+
+ setItemData(role, QVariant());
+ if (role == Qt::DecorationPropertyRole)
+ setItemData(Qt::DecorationRole, qVariantFromValue(QIcon()));
+ if (role == Qt::DisplayPropertyRole)
+ setItemData(Qt::EditRole, qVariantFromValue(QString()));
+ if (role == Qt::ToolTipPropertyRole)
+ setItemData(Qt::ToolTipRole, qVariantFromValue(QString()));
+ if (role == Qt::StatusTipPropertyRole)
+ setItemData(Qt::StatusTipRole, qVariantFromValue(QString()));
+ if (role == Qt::WhatsThisPropertyRole)
+ setItemData(Qt::WhatsThisRole, qVariantFromValue(QString()));
+}
+
+void AbstractItemEditor::cacheReloaded()
+{
+ BoolBlocker block(m_updatingBrowser);
+ m_propertyManager->reloadResourceProperties();
+}
+
+void AbstractItemEditor::updateBrowser()
+{
+ BoolBlocker block(m_updatingBrowser);
+ foreach (QtVariantProperty *prop, m_properties) {
+ int role = m_propertyToRole.value(prop);
+ QVariant val = getItemData(role);
+ if (!val.isValid()) {
+ if (role == ItemFlagsShadowRole)
+ val = qVariantFromValue((int)QListWidgetItem().flags());
+ else
+ val = QVariant((int)prop->value().userType(), (void *)0);
+ prop->setModified(false);
+ } else {
+ prop->setModified(true);
+ }
+ prop->setValue(val);
+ }
+
+ if (m_propertyBrowser->topLevelItems().isEmpty())
+ foreach (QtVariantProperty *prop, m_rootProperties)
+ m_propertyBrowser->addProperty(prop);
+}
+
+void AbstractItemEditor::injectPropertyBrowser(QWidget *parent, QWidget *widget)
+{
+ // It is impossible to design a splitter with just one widget, so we do it by hand.
+ m_propertySplitter = new QSplitter;
+ m_propertySplitter->addWidget(widget);
+ m_propertySplitter->addWidget(m_propertyBrowser);
+ m_propertySplitter->setStretchFactor(0, 1);
+ m_propertySplitter->setStretchFactor(1, 0);
+ parent->layout()->addWidget(m_propertySplitter);
+}
+
+////////////////// List editor ///////////////
+ItemListEditor::ItemListEditor(QDesignerFormWindowInterface *form, QWidget *parent)
+ : AbstractItemEditor(form, parent),
+ m_updating(false)
+{
+ ui.setupUi(this);
+
+ injectPropertyBrowser(this, ui.widget);
+ connect(ui.showPropertiesButton, SIGNAL(clicked()),
+ this, SLOT(togglePropertyBrowser()));
+ togglePropertyBrowser();
+
+ QIcon upIcon = createIconSet(QString::fromUtf8("up.png"));
+ QIcon downIcon = createIconSet(QString::fromUtf8("down.png"));
+ QIcon minusIcon = createIconSet(QString::fromUtf8("minus.png"));
+ QIcon plusIcon = createIconSet(QString::fromUtf8("plus.png"));
+ ui.moveListItemUpButton->setIcon(upIcon);
+ ui.moveListItemDownButton->setIcon(downIcon);
+ ui.newListItemButton->setIcon(plusIcon);
+ ui.deleteListItemButton->setIcon(minusIcon);
+
+ connect(iconCache(), SIGNAL(reloaded()), this, SLOT(cacheReloaded()));
+}
+
+void ItemListEditor::setupEditor(QWidget *object, PropertyDefinition *propList)
+{
+ AbstractItemEditor::setupEditor(object, propList);
+
+ if (ui.listWidget->count() > 0)
+ ui.listWidget->setCurrentRow(0);
+ else
+ updateEditor();
+}
+
+void ItemListEditor::setCurrentIndex(int idx)
+{
+ m_updating = true;
+ ui.listWidget->setCurrentRow(idx);
+ m_updating = false;
+}
+
+void ItemListEditor::on_newListItemButton_clicked()
+{
+ int row = ui.listWidget->currentRow() + 1;
+
+ QListWidgetItem *item = new QListWidgetItem(m_newItemText);
+ item->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_newItemText)));
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+ if (row < ui.listWidget->count())
+ ui.listWidget->insertItem(row, item);
+ else
+ ui.listWidget->addItem(item);
+ emit itemInserted(row);
+
+ ui.listWidget->setCurrentItem(item);
+ ui.listWidget->editItem(item);
+}
+
+void ItemListEditor::on_deleteListItemButton_clicked()
+{
+ int row = ui.listWidget->currentRow();
+
+ if (row != -1) {
+ delete ui.listWidget->takeItem(row);
+ emit itemDeleted(row);
+ }
+
+ if (row == ui.listWidget->count())
+ row--;
+ if (row < 0)
+ updateEditor();
+ else
+ ui.listWidget->setCurrentRow(row);
+}
+
+void ItemListEditor::on_moveListItemUpButton_clicked()
+{
+ int row = ui.listWidget->currentRow();
+ if (row <= 0)
+ return; // nothing to do
+
+ ui.listWidget->insertItem(row - 1, ui.listWidget->takeItem(row));
+ ui.listWidget->setCurrentRow(row - 1);
+ emit itemMovedUp(row);
+}
+
+void ItemListEditor::on_moveListItemDownButton_clicked()
+{
+ int row = ui.listWidget->currentRow();
+ if (row == -1 || row == ui.listWidget->count() - 1)
+ return; // nothing to do
+
+ ui.listWidget->insertItem(row + 1, ui.listWidget->takeItem(row));
+ ui.listWidget->setCurrentRow(row + 1);
+ emit itemMovedDown(row);
+}
+
+void ItemListEditor::on_listWidget_currentRowChanged()
+{
+ updateEditor();
+ if (!m_updating)
+ emit indexChanged(ui.listWidget->currentRow());
+}
+
+void ItemListEditor::on_listWidget_itemChanged(QListWidgetItem *item)
+{
+ if (m_updatingBrowser)
+ return;
+
+ PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole));
+ val.setValue(item->text());
+ BoolBlocker block(m_updatingBrowser);
+ item->setData(Qt::DisplayPropertyRole, qVariantFromValue(val));
+
+ // The checkState could change, too, but if this signal is connected,
+ // checkState is not in the list anyway, as we are editing a header item.
+ emit itemChanged(ui.listWidget->currentRow(), Qt::DisplayPropertyRole,
+ qVariantFromValue(val));
+ updateBrowser();
+}
+
+void ItemListEditor::togglePropertyBrowser()
+{
+ // Always hide in case parent widget is not visible -> on startup
+ const bool isVisible =
+ !this->isVisible() ? true : m_propertyBrowser->isVisible();
+ if (isVisible)
+ ui.showPropertiesButton->setText(tr("Properties &<<"));
+ else
+ ui.showPropertiesButton->setText(tr("Properties &>>"));
+
+ m_propertyBrowser->setVisible(!isVisible);
+}
+
+void ItemListEditor::setItemData(int role, const QVariant &v)
+{
+ QListWidgetItem *item = ui.listWidget->currentItem();
+ bool reLayout = false;
+ if ((role == Qt::EditRole && (v.toString().count(QLatin1Char('\n')) != item->data(role).toString().count(QLatin1Char('\n'))))
+ || role == Qt::FontRole)
+ reLayout = true;
+ QVariant newValue = v;
+ if (role == Qt::FontRole && newValue.type() == QVariant::Font) {
+ QFont oldFont = ui.listWidget->font();
+ QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont);
+ newValue = qVariantFromValue(newFont);
+ item->setData(role, QVariant()); // force the right font with the current resolve mask is set (item view bug)
+ }
+ item->setData(role, newValue);
+ if (reLayout)
+ ui.listWidget->doItemsLayout();
+ emit itemChanged(ui.listWidget->currentRow(), role, newValue);
+}
+
+QVariant ItemListEditor::getItemData(int role) const
+{
+ return ui.listWidget->currentItem()->data(role);
+}
+
+void ItemListEditor::cacheReloaded()
+{
+ reloadIconResources(iconCache(), ui.listWidget);
+}
+
+void ItemListEditor::updateEditor()
+{
+ bool currentItemEnabled = false;
+
+ bool moveRowUpEnabled = false;
+ bool moveRowDownEnabled = false;
+
+ QListWidgetItem *item = ui.listWidget->currentItem();
+ if (item) {
+ currentItemEnabled = true;
+ int currentRow = ui.listWidget->currentRow();
+ if (currentRow > 0)
+ moveRowUpEnabled = true;
+ if (currentRow < ui.listWidget->count() - 1)
+ moveRowDownEnabled = true;
+ }
+
+ ui.moveListItemUpButton->setEnabled(moveRowUpEnabled);
+ ui.moveListItemDownButton->setEnabled(moveRowDownEnabled);
+ ui.deleteListItemButton->setEnabled(currentItemEnabled);
+
+ if (item)
+ updateBrowser();
+ else
+ m_propertyBrowser->clear();
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/itemlisteditor.h b/tools/designer/src/components/taskmenu/itemlisteditor.h
new file mode 100644
index 0000000000..347dcbb4ff
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/itemlisteditor.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ITEMLISTEDITOR_H
+#define ITEMLISTEDITOR_H
+
+#include "ui_itemlisteditor.h"
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QtProperty;
+class QtVariantProperty;
+class QtTreePropertyBrowser;
+class QSplitter;
+
+namespace qdesigner_internal {
+
+class DesignerIconCache;
+class DesignerPropertyManager;
+class DesignerEditorFactory;
+
+// Utility class that ensures a bool is true while in scope.
+// Courtesy of QBoolBlocker in qobject_p.h
+class BoolBlocker
+{
+public:
+ inline BoolBlocker(bool &b):block(b), reset(b){block = true;}
+ inline ~BoolBlocker(){block = reset; }
+private:
+ bool &block;
+ bool reset;
+};
+
+class AbstractItemEditor: public QDialog
+{
+ Q_OBJECT
+
+public:
+ AbstractItemEditor(QDesignerFormWindowInterface *form, QWidget *parent);
+ ~AbstractItemEditor();
+
+ DesignerIconCache *iconCache() const { return m_iconCache; }
+
+ struct PropertyDefinition {
+ int role;
+ int type;
+ int (*typeFunc)();
+ const char *name;
+ };
+
+private slots:
+ void propertyChanged(QtProperty *property);
+ void resetProperty(QtProperty *property);
+ void cacheReloaded();
+
+protected:
+ void keyPressEvent(QKeyEvent *e);
+ void setupProperties(PropertyDefinition *propDefs);
+ void setupObject(QWidget *object);
+ void setupEditor(QWidget *object, PropertyDefinition *propDefs);
+ void injectPropertyBrowser(QWidget *parent, QWidget *widget);
+ void updateBrowser();
+ virtual void setItemData(int role, const QVariant &v) = 0;
+ virtual QVariant getItemData(int role) const = 0;
+
+ DesignerIconCache *m_iconCache;
+ DesignerPropertyManager *m_propertyManager;
+ DesignerEditorFactory *m_editorFactory;
+ QSplitter *m_propertySplitter;
+ QtTreePropertyBrowser *m_propertyBrowser;
+ QList<QtVariantProperty*> m_properties;
+ QList<QtVariantProperty*> m_rootProperties;
+ QHash<QtVariantProperty*, int> m_propertyToRole;
+ bool m_updatingBrowser;
+};
+
+class ItemListEditor: public AbstractItemEditor
+{
+ Q_OBJECT
+
+public:
+ ItemListEditor(QDesignerFormWindowInterface *form, QWidget *parent);
+
+ void setupEditor(QWidget *object, PropertyDefinition *propDefs);
+ QListWidget *listWidget() const { return ui.listWidget; }
+ void setNewItemText(const QString &tpl) { m_newItemText = tpl; }
+ QString newItemText() const { return m_newItemText; }
+ void setCurrentIndex(int idx);
+
+signals:
+ void indexChanged(int idx);
+ void itemChanged(int idx, int role, const QVariant &v);
+ void itemInserted(int idx);
+ void itemDeleted(int idx);
+ void itemMovedUp(int idx);
+ void itemMovedDown(int idx);
+
+private slots:
+ void on_newListItemButton_clicked();
+ void on_deleteListItemButton_clicked();
+ void on_moveListItemUpButton_clicked();
+ void on_moveListItemDownButton_clicked();
+ void on_listWidget_currentRowChanged();
+ void on_listWidget_itemChanged(QListWidgetItem * item);
+ void togglePropertyBrowser();
+ void cacheReloaded();
+
+protected:
+ virtual void setItemData(int role, const QVariant &v);
+ virtual QVariant getItemData(int role) const;
+
+ void updateEditor();
+ Ui::ItemListEditor ui;
+ bool m_updating;
+ QString m_newItemText;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ITEMLISTEDITOR_H
diff --git a/tools/designer/src/components/taskmenu/itemlisteditor.ui b/tools/designer/src/components/taskmenu/itemlisteditor.ui
new file mode 100644
index 0000000000..62e5b274d4
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/itemlisteditor.ui
@@ -0,0 +1,156 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::ItemListEditor</class>
+ <widget class="QWidget" name="qdesigner_internal::ItemListEditor" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>550</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2" >
+ <item>
+ <widget class="QWidget" native="1" name="widget" >
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListWidget" name="listWidget" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" >
+ <string>Items List</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="buttonsLayout" >
+ <item>
+ <widget class="QToolButton" name="newListItemButton" >
+ <property name="toolTip" >
+ <string>New Item</string>
+ </property>
+ <property name="text" >
+ <string>&amp;New</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="deleteListItemButton" >
+ <property name="toolTip" >
+ <string>Delete Item</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Delete</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>16</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QToolButton" name="moveListItemUpButton" >
+ <property name="toolTip" >
+ <string>Move Item Up</string>
+ </property>
+ <property name="text" >
+ <string>U</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="moveListItemDownButton" >
+ <property name="toolTip" >
+ <string>Move Item Down</string>
+ </property>
+ <property name="text" >
+ <string>D</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="showPropertiesButton" >
+ <property name="text" >
+ <string>Properties &amp;>></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/components/taskmenu/label_taskmenu.cpp b/tools/designer/src/components/taskmenu/label_taskmenu.cpp
new file mode 100644
index 0000000000..77e5ed9213
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/label_taskmenu.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::LabelTaskMenu
+*/
+
+#include "label_taskmenu.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+#include <QtGui/QTextDocument>
+
+static const char *textPropertyC = "text";
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// -------- LabelTaskMenuInlineEditor
+class LabelTaskMenuInlineEditor : public TaskMenuInlineEditor
+{
+public:
+ LabelTaskMenuInlineEditor(QLabel *button, QObject *parent);
+
+protected:
+ virtual QRect editRectangle() const;
+};
+
+LabelTaskMenuInlineEditor::LabelTaskMenuInlineEditor(QLabel *w, QObject *parent) :
+ TaskMenuInlineEditor(w, ValidationRichText, QLatin1String(textPropertyC), parent)
+{
+}
+
+QRect LabelTaskMenuInlineEditor::editRectangle() const
+{
+ QStyleOptionButton opt;
+ opt.init(widget());
+ return opt.rect;
+}
+
+// --------------- LabelTaskMenu
+
+LabelTaskMenu::LabelTaskMenu(QLabel *label, QObject *parent)
+ : QDesignerTaskMenu(label, parent),
+ m_label(label),
+ m_editRichTextAction(new QAction(tr("Change rich text..."), this)),
+ m_editPlainTextAction(new QAction(tr("Change plain text..."), this))
+{
+ LabelTaskMenuInlineEditor *editor = new LabelTaskMenuInlineEditor(label, this);
+ connect(m_editPlainTextAction, SIGNAL(triggered()), editor, SLOT(editText()));
+ m_taskActions.append(m_editPlainTextAction);
+
+ connect(m_editRichTextAction, SIGNAL(triggered()), this, SLOT(editRichText()));
+ m_taskActions.append(m_editRichTextAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+QAction *LabelTaskMenu::preferredEditAction() const
+{
+ if (m_label->textFormat () == Qt::PlainText) return m_editPlainTextAction;
+ return Qt::mightBeRichText(m_label->text()) ? m_editRichTextAction : m_editPlainTextAction;
+}
+
+QList<QAction*> LabelTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+void LabelTaskMenu::editRichText()
+{
+ changeTextProperty(QLatin1String(textPropertyC), QString(), MultiSelectionMode, m_label->textFormat());
+}
+
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/label_taskmenu.h b/tools/designer/src/components/taskmenu/label_taskmenu.h
new file mode 100644
index 0000000000..0d7722b8c3
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/label_taskmenu.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LABEL_TASKMENU_H
+#define LABEL_TASKMENU_H
+
+#include <QtGui/QLabel>
+#include <QtCore/QPointer>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class LabelTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit LabelTaskMenu(QLabel *button, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void editRichText();
+
+private:
+ QLabel *m_label;
+ QList<QAction*> m_taskActions;
+ QAction *m_editRichTextAction;
+ QAction *m_editPlainTextAction;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QLabel, LabelTaskMenu> LabelTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LABEL_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/layouttaskmenu.cpp b/tools/designer/src/components/taskmenu/layouttaskmenu.cpp
new file mode 100644
index 0000000000..4a3aeec0b7
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/layouttaskmenu.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::LayoutWidgetTaskMenu
+*/
+
+#include "layouttaskmenu.h"
+#include <formlayoutmenu_p.h>
+#include <morphmenu_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+// ------------ LayoutWidgetTaskMenu
+LayoutWidgetTaskMenu::LayoutWidgetTaskMenu(QLayoutWidget *lw, QObject *parent) :
+ QObject(parent),
+ m_widget(lw),
+ m_morphMenu(new qdesigner_internal::MorphMenu(this)),
+ m_formLayoutMenu(new qdesigner_internal::FormLayoutMenu(this))
+{
+}
+
+QAction *LayoutWidgetTaskMenu::preferredEditAction() const
+{
+ return m_formLayoutMenu->preferredEditAction(m_widget, m_widget->formWindow());
+}
+
+QList<QAction*> LayoutWidgetTaskMenu::taskActions() const
+{
+ QList<QAction*> rc;
+ QDesignerFormWindowInterface *fw = m_widget->formWindow();
+ m_morphMenu->populate(m_widget, fw, rc);
+ m_formLayoutMenu->populate(m_widget, fw, rc);
+ return rc;
+}
+
+// ------------- SpacerTaskMenu
+SpacerTaskMenu::SpacerTaskMenu(Spacer *, QObject *parent) :
+ QObject(parent)
+{
+}
+
+QAction *SpacerTaskMenu::preferredEditAction() const
+{
+ return 0;
+}
+
+QList<QAction*> SpacerTaskMenu::taskActions() const
+{
+ return QList<QAction*>();
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/components/taskmenu/layouttaskmenu.h b/tools/designer/src/components/taskmenu/layouttaskmenu.h
new file mode 100644
index 0000000000..97fde9ce4d
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/layouttaskmenu.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LAYOUTTASKMENU_H
+#define LAYOUTTASKMENU_H
+
+#include <QtDesigner/QDesignerTaskMenuExtension>
+
+#include <qlayout_widget_p.h>
+#include <spacer_widget_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ class FormLayoutMenu;
+ class MorphMenu;
+}
+
+// Morph menu for QLayoutWidget.
+class LayoutWidgetTaskMenu : public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit LayoutWidgetTaskMenu(QLayoutWidget *w, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private:
+ QLayoutWidget *m_widget;
+ qdesigner_internal::MorphMenu *m_morphMenu;
+ qdesigner_internal::FormLayoutMenu *m_formLayoutMenu;
+};
+
+// Empty task menu for spacers.
+class SpacerTaskMenu : public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit SpacerTaskMenu(Spacer *bar, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+};
+
+typedef qdesigner_internal::ExtensionFactory<QDesignerTaskMenuExtension, QLayoutWidget, LayoutWidgetTaskMenu> LayoutWidgetTaskMenuFactory;
+typedef qdesigner_internal::ExtensionFactory<QDesignerTaskMenuExtension, Spacer, SpacerTaskMenu> SpacerTaskMenuFactory;
+
+QT_END_NAMESPACE
+
+#endif // LAYOUTTASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/lineedit_taskmenu.cpp b/tools/designer/src/components/taskmenu/lineedit_taskmenu.cpp
new file mode 100644
index 0000000000..baf4785574
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/lineedit_taskmenu.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::LineEditTaskMenu
+*/
+
+#include "lineedit_taskmenu.h"
+#include "inplace_editor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// -------- LineEditTaskMenuInlineEditor
+class LineEditTaskMenuInlineEditor : public TaskMenuInlineEditor
+{
+public:
+ LineEditTaskMenuInlineEditor(QLineEdit *button, QObject *parent);
+
+protected:
+ virtual QRect editRectangle() const;
+};
+
+LineEditTaskMenuInlineEditor::LineEditTaskMenuInlineEditor(QLineEdit *w, QObject *parent) :
+ TaskMenuInlineEditor(w, ValidationSingleLine, QLatin1String("text"), parent)
+{
+}
+
+QRect LineEditTaskMenuInlineEditor::editRectangle() const
+{
+ QStyleOption opt;
+ opt.init(widget());
+ return opt.rect;
+}
+
+// --------------- LineEditTaskMenu
+LineEditTaskMenu::LineEditTaskMenu(QLineEdit *lineEdit, QObject *parent) :
+ QDesignerTaskMenu(lineEdit, parent),
+ m_editTextAction(new QAction(tr("Change text..."), this))
+{
+ TaskMenuInlineEditor *editor = new LineEditTaskMenuInlineEditor(lineEdit, this);
+ connect(m_editTextAction, SIGNAL(triggered()), editor, SLOT(editText()));
+ m_taskActions.append(m_editTextAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+QAction *LineEditTaskMenu::preferredEditAction() const
+{
+ return m_editTextAction;
+}
+
+QList<QAction*> LineEditTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/lineedit_taskmenu.h b/tools/designer/src/components/taskmenu/lineedit_taskmenu.h
new file mode 100644
index 0000000000..f37fad8b6a
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/lineedit_taskmenu.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LINEEDIT_TASKMENU_H
+#define LINEEDIT_TASKMENU_H
+
+#include <QtGui/QLineEdit>
+#include <QtCore/QPointer>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class LineEditTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit LineEditTaskMenu(QLineEdit *button, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private:
+ QList<QAction*> m_taskActions;
+ QAction *m_editTextAction;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QLineEdit, LineEditTaskMenu> LineEditTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LINEEDIT_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/listwidget_taskmenu.cpp b/tools/designer/src/components/taskmenu/listwidget_taskmenu.cpp
new file mode 100644
index 0000000000..1a9ba361bb
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/listwidget_taskmenu.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ListWidgetTaskMenu
+*/
+
+#include "listwidget_taskmenu.h"
+#include "listwidgeteditor.h"
+#include "qdesigner_utils_p.h"
+#include <qdesigner_command_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QStyle>
+#include <QtGui/QLineEdit>
+#include <QtGui/QStyleOption>
+
+#include <QtCore/QEvent>
+#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+ListWidgetTaskMenu::ListWidgetTaskMenu(QListWidget *button, QObject *parent)
+ : QDesignerTaskMenu(button, parent),
+ m_listWidget(button)
+{
+ m_editItemsAction = new QAction(this);
+ m_editItemsAction->setText(tr("Edit Items..."));
+ connect(m_editItemsAction, SIGNAL(triggered()), this, SLOT(editItems()));
+ m_taskActions.append(m_editItemsAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+ListWidgetTaskMenu::~ListWidgetTaskMenu()
+{
+}
+
+QAction *ListWidgetTaskMenu::preferredEditAction() const
+{
+ return m_editItemsAction;
+}
+
+QList<QAction*> ListWidgetTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+void ListWidgetTaskMenu::editItems()
+{
+ m_formWindow = QDesignerFormWindowInterface::findFormWindow(m_listWidget);
+ if (m_formWindow.isNull())
+ return;
+
+ Q_ASSERT(m_listWidget != 0);
+
+ ListWidgetEditor dlg(m_formWindow, m_listWidget->window());
+ ListContents oldItems = dlg.fillContentsFromListWidget(m_listWidget);
+ if (dlg.exec() == QDialog::Accepted) {
+ ListContents items = dlg.contents();
+ if (items != oldItems) {
+ ChangeListContentsCommand *cmd = new ChangeListContentsCommand(m_formWindow);
+ cmd->init(m_listWidget, oldItems, items);
+ cmd->setText(tr("Change List Contents"));
+ m_formWindow->commandHistory()->push(cmd);
+ }
+ }
+}
+
+void ListWidgetTaskMenu::updateSelection()
+{
+ if (m_editor)
+ m_editor->deleteLater();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/listwidget_taskmenu.h b/tools/designer/src/components/taskmenu/listwidget_taskmenu.h
new file mode 100644
index 0000000000..6f730a293a
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/listwidget_taskmenu.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LISTWIDGET_TASKMENU_H
+#define LISTWIDGET_TASKMENU_H
+
+#include <QtGui/QListWidget>
+#include <QtCore/QPointer>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QLineEdit;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class ListWidgetTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit ListWidgetTaskMenu(QListWidget *button, QObject *parent = 0);
+ virtual ~ListWidgetTaskMenu();
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void editItems();
+ void updateSelection();
+
+private:
+ QListWidget *m_listWidget;
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ QPointer<QLineEdit> m_editor;
+ mutable QList<QAction*> m_taskActions;
+ QAction *m_editItemsAction;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QListWidget, ListWidgetTaskMenu> ListWidgetTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LISTWIDGET_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/listwidgeteditor.cpp b/tools/designer/src/components/taskmenu/listwidgeteditor.cpp
new file mode 100644
index 0000000000..2a8de52a93
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/listwidgeteditor.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ListWidgetEditor
+*/
+
+#include "listwidgeteditor.h"
+#include <designerpropertymanager.h>
+#include <abstractformbuilder.h>
+
+#include <QtDesigner/private/abstractsettings_p.h>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QComboBox>
+#include <QtGui/QGroupBox>
+#include <QtGui/QDialogButtonBox>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+ListWidgetEditor::ListWidgetEditor(QDesignerFormWindowInterface *form,
+ QWidget *parent)
+ : QDialog(parent)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ QDialogButtonBox *buttonBox = new QDialogButtonBox;
+ buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), SLOT(reject()));
+
+ m_itemsEditor = new ItemListEditor(form, 0);
+ m_itemsEditor->layout()->setMargin(0);
+ m_itemsEditor->setNewItemText(tr("New Item"));
+
+ QFrame *sep = new QFrame;
+ sep->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+
+ QBoxLayout *box = new QVBoxLayout(this);
+ box->addWidget(m_itemsEditor);
+ box->addWidget(sep);
+ box->addWidget(buttonBox);
+
+ // Numbers copied from itemlisteditor.ui
+ // (Automatic resizing doesn't work because ui has parent).
+ resize(550, 360);
+}
+
+static AbstractItemEditor::PropertyDefinition listBoxPropList[] = {
+ { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
+ { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
+ { Qt::ToolTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "toolTip" },
+ { Qt::StatusTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "statusTip" },
+ { Qt::WhatsThisPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "whatsThis" },
+ { Qt::FontRole, QVariant::Font, 0, "font" },
+ { Qt::TextAlignmentRole, 0, DesignerPropertyManager::designerAlignmentTypeId, "textAlignment" },
+ { Qt::BackgroundRole, QVariant::Brush, 0, "background" },
+ { Qt::ForegroundRole, QVariant::Brush, 0, "foreground" },
+ { ItemFlagsShadowRole, 0, QtVariantPropertyManager::flagTypeId, "flags" },
+ { Qt::CheckStateRole, 0, QtVariantPropertyManager::enumTypeId, "checkState" },
+ { 0, 0, 0, 0 }
+};
+
+ListContents ListWidgetEditor::fillContentsFromListWidget(QListWidget *listWidget)
+{
+ setWindowTitle(tr("Edit List Widget"));
+
+ ListContents retVal;
+ retVal.createFromListWidget(listWidget, false);
+ retVal.applyToListWidget(m_itemsEditor->listWidget(), m_itemsEditor->iconCache(), true);
+
+ m_itemsEditor->setupEditor(listWidget, listBoxPropList);
+
+ return retVal;
+}
+
+static AbstractItemEditor::PropertyDefinition comboBoxPropList[] = {
+ { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
+ { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
+ { 0, 0, 0, 0 }
+};
+
+ListContents ListWidgetEditor::fillContentsFromComboBox(QComboBox *comboBox)
+{
+ setWindowTitle(tr("Edit Combobox"));
+
+ ListContents retVal;
+ retVal.createFromComboBox(comboBox);
+ retVal.applyToListWidget(m_itemsEditor->listWidget(), m_itemsEditor->iconCache(), true);
+
+ m_itemsEditor->setupEditor(comboBox, comboBoxPropList);
+
+ return retVal;
+}
+
+ListContents ListWidgetEditor::contents() const
+{
+ ListContents retVal;
+ retVal.createFromListWidget(m_itemsEditor->listWidget(), true);
+ return retVal;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/listwidgeteditor.h b/tools/designer/src/components/taskmenu/listwidgeteditor.h
new file mode 100644
index 0000000000..c7fcdea56b
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/listwidgeteditor.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LISTWIDGETEDITOR_H
+#define LISTWIDGETEDITOR_H
+
+#include "itemlisteditor.h"
+#include <qdesigner_command_p.h>
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QListWidget;
+class QComboBox;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class ListWidgetEditor: public QDialog
+{
+ Q_OBJECT
+
+public:
+ ListWidgetEditor(QDesignerFormWindowInterface *form,
+ QWidget *parent);
+
+ ListContents fillContentsFromListWidget(QListWidget *listWidget);
+ ListContents fillContentsFromComboBox(QComboBox *comboBox);
+ ListContents contents() const;
+
+private:
+ ItemListEditor *m_itemsEditor;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LISTWIDGETEDITOR_H
diff --git a/tools/designer/src/components/taskmenu/menutaskmenu.cpp b/tools/designer/src/components/taskmenu/menutaskmenu.cpp
new file mode 100644
index 0000000000..52320ac681
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/menutaskmenu.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::MenuTaskMenu
+*/
+
+#include "menutaskmenu.h"
+
+#include <promotiontaskmenu_p.h>
+
+#include <QtGui/QAction>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ // ------------ MenuTaskMenu
+ MenuTaskMenu::MenuTaskMenu(QDesignerMenu *menu, QObject *parent) :
+ QObject(parent),
+ m_menu(menu),
+ m_removeAction(new QAction(tr("Remove"), this)),
+ m_promotionTaskMenu(new PromotionTaskMenu(menu, PromotionTaskMenu::ModeSingleWidget, this))
+ {
+ connect(m_removeAction, SIGNAL(triggered()), this, SLOT(removeMenu()));
+ }
+
+ QAction *MenuTaskMenu::preferredEditAction() const
+ {
+ return 0;
+ }
+
+ QList<QAction*> MenuTaskMenu::taskActions() const
+ {
+ QList<QAction*> rc;
+ rc.push_back(m_removeAction);
+ m_promotionTaskMenu->addActions(PromotionTaskMenu::LeadingSeparator, rc);
+ return rc;
+ }
+
+ void MenuTaskMenu::removeMenu()
+ {
+ // Are we on a menu bar or on a menu?
+ QWidget *pw = m_menu->parentWidget();
+ if (QDesignerMenuBar *mb = qobject_cast<QDesignerMenuBar *>(pw)) {
+ mb->deleteMenuAction(m_menu->menuAction());
+ return;
+ }
+ if (QDesignerMenu *m = qobject_cast<QDesignerMenu *>(pw)) {
+ m->deleteAction(m_menu->menuAction());
+ }
+ }
+
+ // ------------- MenuBarTaskMenu
+ MenuBarTaskMenu::MenuBarTaskMenu(QDesignerMenuBar *bar, QObject *parent) :
+ QObject(parent),
+ m_bar(bar)
+ {
+ }
+
+ QAction *MenuBarTaskMenu::preferredEditAction() const
+ {
+ return 0;
+ }
+
+ QList<QAction*> MenuBarTaskMenu::taskActions() const
+ {
+ return m_bar->contextMenuActions();
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/components/taskmenu/menutaskmenu.h b/tools/designer/src/components/taskmenu/menutaskmenu.h
new file mode 100644
index 0000000000..98ae3e197f
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/menutaskmenu.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MENUTASKMENU_H
+#define MENUTASKMENU_H
+
+#include <QtDesigner/QDesignerTaskMenuExtension>
+
+#include <qdesigner_menu_p.h>
+#include <qdesigner_menubar_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+ class PromotionTaskMenu;
+
+// The QMenu task menu provides promotion and a remove option. The actual
+// menu context options are not forwarded since they make only sense
+// when a menu is being edited/visible.
+
+class MenuTaskMenu : public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit MenuTaskMenu(QDesignerMenu *menu, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void removeMenu();
+
+private:
+ QDesignerMenu *m_menu;
+ QAction *m_removeAction;
+ PromotionTaskMenu *m_promotionTaskMenu;
+};
+
+// The QMenuBar task menu forwards the actions of QDesignerMenuBar,
+// making them available in the object inspector.
+
+class MenuBarTaskMenu : public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit MenuBarTaskMenu(QDesignerMenuBar *bar, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private:
+ QDesignerMenuBar *m_bar;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QDesignerMenu, MenuTaskMenu> MenuTaskMenuFactory;
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QDesignerMenuBar, MenuBarTaskMenu> MenuBarTaskMenuFactory;
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // MENUTASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp b/tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp
new file mode 100644
index 0000000000..5ef1f9c35c
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/tablewidget_taskmenu.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::TableWidgetTaskMenu
+*/
+
+#include "tablewidget_taskmenu.h"
+#include "tablewidgeteditor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QTableWidget>
+#include <QtGui/QAction>
+#include <QtGui/QLineEdit>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+
+#include <QtCore/QEvent>
+#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+TableWidgetTaskMenu::TableWidgetTaskMenu(QTableWidget *button, QObject *parent)
+ : QDesignerTaskMenu(button, parent),
+ m_tableWidget(button),
+ m_editItemsAction(new QAction(tr("Edit Items..."), this))
+{
+ connect(m_editItemsAction, SIGNAL(triggered()), this, SLOT(editItems()));
+ m_taskActions.append(m_editItemsAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+
+TableWidgetTaskMenu::~TableWidgetTaskMenu()
+{
+}
+
+QAction *TableWidgetTaskMenu::preferredEditAction() const
+{
+ return m_editItemsAction;
+}
+
+QList<QAction*> TableWidgetTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+void TableWidgetTaskMenu::editItems()
+{
+ m_formWindow = QDesignerFormWindowInterface::findFormWindow(m_tableWidget);
+ if (m_formWindow.isNull())
+ return;
+
+ Q_ASSERT(m_tableWidget != 0);
+
+ TableWidgetEditor dlg(m_formWindow, m_tableWidget->window());
+ TableWidgetContents oldCont = dlg.fillContentsFromTableWidget(m_tableWidget);
+ if (dlg.exec() == QDialog::Accepted) {
+ TableWidgetContents newCont = dlg.contents();
+ if (newCont != oldCont) {
+ ChangeTableContentsCommand *cmd = new ChangeTableContentsCommand(m_formWindow);
+ cmd->init(m_tableWidget, oldCont, newCont);
+ m_formWindow->commandHistory()->push(cmd);
+ }
+ }
+}
+
+void TableWidgetTaskMenu::updateSelection()
+{
+ if (m_editor)
+ m_editor->deleteLater();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/tablewidget_taskmenu.h b/tools/designer/src/components/taskmenu/tablewidget_taskmenu.h
new file mode 100644
index 0000000000..6ee9c26fc9
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/tablewidget_taskmenu.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABLEWIDGET_TASKMENU_H
+#define TABLEWIDGET_TASKMENU_H
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+#include <QtGui/QTableWidget>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QLineEdit;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class TableWidgetTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit TableWidgetTaskMenu(QTableWidget *button, QObject *parent = 0);
+ virtual ~TableWidgetTaskMenu();
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void editItems();
+ void updateSelection();
+
+private:
+ QTableWidget *m_tableWidget;
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ QPointer<QLineEdit> m_editor;
+ mutable QList<QAction*> m_taskActions;
+ QAction *m_editItemsAction;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QTableWidget, TableWidgetTaskMenu> TableWidgetTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TABLEWIDGET_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp b/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp
new file mode 100644
index 0000000000..0863847f87
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/tablewidgeteditor.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::TableWidgetEditor
+*/
+
+#include "tablewidgeteditor.h"
+#include <abstractformbuilder.h>
+#include <iconloader_p.h>
+#include <qdesigner_command_p.h>
+#include "formwindowbase_p.h"
+#include "qdesigner_utils_p.h"
+#include <designerpropertymanager.h>
+#include <qttreepropertybrowser.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtCore/QDir>
+#include <QtCore/QQueue>
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+TableWidgetEditor::TableWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent)
+ : AbstractItemEditor(form, parent), m_updatingBrowser(false)
+{
+ m_columnEditor = new ItemListEditor(form, this);
+ m_columnEditor->setObjectName(QLatin1String("columnEditor"));
+ m_columnEditor->setNewItemText(tr("New Column"));
+ m_rowEditor = new ItemListEditor(form, this);
+ m_rowEditor->setObjectName(QLatin1String("rowEditor"));
+ m_rowEditor->setNewItemText(tr("New Row"));
+ ui.setupUi(this);
+
+ injectPropertyBrowser(ui.itemsTab, ui.widget);
+ connect(ui.showPropertiesButton, SIGNAL(clicked()),
+ this, SLOT(togglePropertyBrowser()));
+ togglePropertyBrowser();
+
+ ui.tabWidget->insertTab(0, m_columnEditor, tr("&Columns"));
+ ui.tabWidget->insertTab(1, m_rowEditor, tr("&Rows"));
+ ui.tabWidget->setCurrentIndex(0);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ ui.tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+
+ connect(iconCache(), SIGNAL(reloaded()), this, SLOT(cacheReloaded()));
+}
+
+static AbstractItemEditor::PropertyDefinition tableHeaderPropList[] = {
+ { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
+ { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
+ { Qt::ToolTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "toolTip" },
+// { Qt::StatusTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "statusTip" },
+ { Qt::WhatsThisPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "whatsThis" },
+ { Qt::FontRole, QVariant::Font, 0, "font" },
+ { Qt::TextAlignmentRole, 0, DesignerPropertyManager::designerAlignmentTypeId, "textAlignment" },
+ { Qt::BackgroundRole, QVariant::Color, 0, "background" },
+ { Qt::ForegroundRole, QVariant::Brush, 0, "foreground" },
+ { 0, 0, 0, 0 }
+};
+
+static AbstractItemEditor::PropertyDefinition tableItemPropList[] = {
+ { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
+ { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
+ { Qt::ToolTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "toolTip" },
+// { Qt::StatusTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "statusTip" },
+ { Qt::WhatsThisPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "whatsThis" },
+ { Qt::FontRole, QVariant::Font, 0, "font" },
+ { Qt::TextAlignmentRole, 0, DesignerPropertyManager::designerAlignmentTypeId, "textAlignment" },
+ { Qt::BackgroundRole, QVariant::Brush, 0, "background" },
+ { Qt::ForegroundRole, QVariant::Brush, 0, "foreground" },
+ { ItemFlagsShadowRole, 0, QtVariantPropertyManager::flagTypeId, "flags" },
+ { Qt::CheckStateRole, 0, QtVariantPropertyManager::enumTypeId, "checkState" },
+ { 0, 0, 0, 0 }
+};
+
+TableWidgetContents TableWidgetEditor::fillContentsFromTableWidget(QTableWidget *tableWidget)
+{
+ TableWidgetContents tblCont;
+ tblCont.fromTableWidget(tableWidget, false);
+ tblCont.applyToTableWidget(ui.tableWidget, iconCache(), true);
+
+ tblCont.m_verticalHeader.applyToListWidget(m_rowEditor->listWidget(), iconCache(), true);
+ m_rowEditor->setupEditor(tableWidget, tableHeaderPropList);
+
+ tblCont.m_horizontalHeader.applyToListWidget(m_columnEditor->listWidget(), iconCache(), true);
+ m_columnEditor->setupEditor(tableWidget, tableHeaderPropList);
+
+ setupEditor(tableWidget, tableItemPropList);
+ if (ui.tableWidget->columnCount() > 0 && ui.tableWidget->rowCount() > 0)
+ ui.tableWidget->setCurrentCell(0, 0);
+
+ updateEditor();
+
+ return tblCont;
+}
+
+TableWidgetContents TableWidgetEditor::contents() const
+{
+ TableWidgetContents retVal;
+ retVal.fromTableWidget(ui.tableWidget, true);
+ return retVal;
+}
+
+void TableWidgetEditor::setItemData(int role, const QVariant &v)
+{
+ QTableWidgetItem *item = ui.tableWidget->currentItem();
+ BoolBlocker block(m_updatingBrowser);
+ if (!item) {
+ item = new QTableWidgetItem;
+ ui.tableWidget->setItem(ui.tableWidget->currentRow(), ui.tableWidget->currentColumn(), item);
+ }
+ QVariant newValue = v;
+ if (role == Qt::FontRole && newValue.type() == QVariant::Font) {
+ QFont oldFont = ui.tableWidget->font();
+ QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont);
+ newValue = qVariantFromValue(newFont);
+ item->setData(role, QVariant()); // force the right font with the current resolve mask is set (item view bug)
+ }
+ item->setData(role, newValue);
+}
+
+QVariant TableWidgetEditor::getItemData(int role) const
+{
+ QTableWidgetItem *item = ui.tableWidget->currentItem();
+ if (!item)
+ return QVariant();
+ return item->data(role);
+}
+
+void TableWidgetEditor::on_tableWidget_currentCellChanged(int currentRow, int currentCol, int, int /* XXX remove me */)
+{
+ m_rowEditor->setCurrentIndex(currentRow);
+ m_columnEditor->setCurrentIndex(currentCol);
+ updateBrowser();
+}
+
+void TableWidgetEditor::on_tableWidget_itemChanged(QTableWidgetItem *item)
+{
+ if (m_updatingBrowser)
+ return;
+
+ PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole));
+ val.setValue(item->text());
+ BoolBlocker block(m_updatingBrowser);
+ item->setData(Qt::DisplayPropertyRole, qVariantFromValue(val));
+
+ updateBrowser();
+}
+
+void TableWidgetEditor::on_columnEditor_indexChanged(int col)
+{
+ ui.tableWidget->setCurrentCell(ui.tableWidget->currentRow(), col);
+}
+
+void TableWidgetEditor::on_columnEditor_itemChanged(int idx, int role, const QVariant &v)
+{
+ ui.tableWidget->horizontalHeaderItem(idx)->setData(role, v);
+}
+
+void TableWidgetEditor::on_rowEditor_indexChanged(int col)
+{
+ ui.tableWidget->setCurrentCell(col, ui.tableWidget->currentColumn());
+}
+
+void TableWidgetEditor::on_rowEditor_itemChanged(int idx, int role, const QVariant &v)
+{
+ ui.tableWidget->verticalHeaderItem(idx)->setData(role, v);
+}
+
+void TableWidgetEditor::togglePropertyBrowser()
+{
+ // Always hide in case parent widget is not visible -> on startup
+ const bool isVisible =
+ !this->isVisible() ? true : m_propertyBrowser->isVisible();
+ if (isVisible)
+ ui.showPropertiesButton->setText(tr("Properties &<<"));
+ else
+ ui.showPropertiesButton->setText(tr("Properties &>>"));
+ m_propertyBrowser->setVisible(!isVisible);
+}
+
+void TableWidgetEditor::updateEditor()
+{
+ const bool wasEnabled = ui.tabWidget->isTabEnabled(2);
+ const bool isEnabled = ui.tableWidget->columnCount() && ui.tableWidget->rowCount();
+ ui.tabWidget->setTabEnabled(2, isEnabled);
+ if (!wasEnabled && isEnabled)
+ ui.tableWidget->setCurrentCell(0, 0);
+
+ QMetaObject::invokeMethod(ui.tableWidget, "updateGeometries");
+ ui.tableWidget->viewport()->update();
+}
+
+void TableWidgetEditor::moveColumnsLeft(int fromColumn, int toColumn)
+{
+ if (fromColumn >= toColumn)
+ return;
+
+ QTableWidgetItem *lastItem = ui.tableWidget->takeHorizontalHeaderItem(toColumn);
+ for (int i = toColumn; i > fromColumn; i--) {
+ ui.tableWidget->setHorizontalHeaderItem(i,
+ ui.tableWidget->takeHorizontalHeaderItem(i - 1));
+ }
+ ui.tableWidget->setHorizontalHeaderItem(fromColumn, lastItem);
+
+ for (int i = 0; i < ui.tableWidget->rowCount(); i++) {
+ QTableWidgetItem *lastItem = ui.tableWidget->takeItem(i, toColumn);
+ for (int j = toColumn; j > fromColumn; j--)
+ ui.tableWidget->setItem(i, j, ui.tableWidget->takeItem(i, j - 1));
+ ui.tableWidget->setItem(i, fromColumn, lastItem);
+ }
+}
+
+void TableWidgetEditor::moveColumnsRight(int fromColumn, int toColumn)
+{
+ if (fromColumn >= toColumn)
+ return;
+
+ QTableWidgetItem *lastItem = ui.tableWidget->takeHorizontalHeaderItem(fromColumn);
+ for (int i = fromColumn; i < toColumn; i++) {
+ ui.tableWidget->setHorizontalHeaderItem(i,
+ ui.tableWidget->takeHorizontalHeaderItem(i + 1));
+ }
+ ui.tableWidget->setHorizontalHeaderItem(toColumn, lastItem);
+
+ for (int i = 0; i < ui.tableWidget->rowCount(); i++) {
+ QTableWidgetItem *lastItem = ui.tableWidget->takeItem(i, fromColumn);
+ for (int j = fromColumn; j < toColumn; j++)
+ ui.tableWidget->setItem(i, j, ui.tableWidget->takeItem(i, j + 1));
+ ui.tableWidget->setItem(i, toColumn, lastItem);
+ }
+}
+
+void TableWidgetEditor::moveRowsDown(int fromRow, int toRow)
+{
+ if (fromRow >= toRow)
+ return;
+
+ QTableWidgetItem *lastItem = ui.tableWidget->takeVerticalHeaderItem(toRow);
+ for (int i = toRow; i > fromRow; i--) {
+ ui.tableWidget->setVerticalHeaderItem(i,
+ ui.tableWidget->takeVerticalHeaderItem(i - 1));
+ }
+ ui.tableWidget->setVerticalHeaderItem(fromRow, lastItem);
+
+ for (int i = 0; i < ui.tableWidget->columnCount(); i++) {
+ QTableWidgetItem *lastItem = ui.tableWidget->takeItem(toRow, i);
+ for (int j = toRow; j > fromRow; j--)
+ ui.tableWidget->setItem(j, i, ui.tableWidget->takeItem(j - 1, i));
+ ui.tableWidget->setItem(fromRow, i, lastItem);
+ }
+}
+
+void TableWidgetEditor::moveRowsUp(int fromRow, int toRow)
+{
+ if (fromRow >= toRow)
+ return;
+
+ QTableWidgetItem *lastItem = ui.tableWidget->takeVerticalHeaderItem(fromRow);
+ for (int i = fromRow; i < toRow; i++) {
+ ui.tableWidget->setVerticalHeaderItem(i,
+ ui.tableWidget->takeVerticalHeaderItem(i + 1));
+ }
+ ui.tableWidget->setVerticalHeaderItem(toRow, lastItem);
+
+ for (int i = 0; i < ui.tableWidget->columnCount(); i++) {
+ QTableWidgetItem *lastItem = ui.tableWidget->takeItem(fromRow, i);
+ for (int j = fromRow; j < toRow; j++)
+ ui.tableWidget->setItem(j, i, ui.tableWidget->takeItem(j + 1, i));
+ ui.tableWidget->setItem(toRow, i, lastItem);
+ }
+}
+
+void TableWidgetEditor::on_columnEditor_itemInserted(int idx)
+{
+ const int columnCount = ui.tableWidget->columnCount();
+ ui.tableWidget->setColumnCount(columnCount + 1);
+
+ QTableWidgetItem *newItem = new QTableWidgetItem(m_columnEditor->newItemText());
+ newItem->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_columnEditor->newItemText())));
+ ui.tableWidget->setHorizontalHeaderItem(columnCount, newItem);
+
+ moveColumnsLeft(idx, columnCount);
+
+ int row = ui.tableWidget->currentRow();
+ if (row >= 0)
+ ui.tableWidget->setCurrentCell(row, idx);
+
+ updateEditor();
+}
+
+void TableWidgetEditor::on_columnEditor_itemDeleted(int idx)
+{
+ const int columnCount = ui.tableWidget->columnCount();
+
+ moveColumnsRight(idx, columnCount - 1);
+ ui.tableWidget->setColumnCount(columnCount - 1);
+
+ updateEditor();
+}
+
+void TableWidgetEditor::on_columnEditor_itemMovedUp(int idx)
+{
+ moveColumnsRight(idx - 1, idx);
+
+ ui.tableWidget->setCurrentCell(ui.tableWidget->currentRow(), idx - 1);
+}
+
+void TableWidgetEditor::on_columnEditor_itemMovedDown(int idx)
+{
+ moveColumnsLeft(idx, idx + 1);
+
+ ui.tableWidget->setCurrentCell(ui.tableWidget->currentRow(), idx + 1);
+}
+
+void TableWidgetEditor::on_rowEditor_itemInserted(int idx)
+{
+ const int rowCount = ui.tableWidget->rowCount();
+ ui.tableWidget->setRowCount(rowCount + 1);
+
+ QTableWidgetItem *newItem = new QTableWidgetItem(m_rowEditor->newItemText());
+ newItem->setData(Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(m_rowEditor->newItemText())));
+ ui.tableWidget->setVerticalHeaderItem(rowCount, newItem);
+
+ moveRowsDown(idx, rowCount);
+
+ int col = ui.tableWidget->currentColumn();
+ if (col >= 0)
+ ui.tableWidget->setCurrentCell(idx, col);
+
+ updateEditor();
+}
+
+void TableWidgetEditor::on_rowEditor_itemDeleted(int idx)
+{
+ const int rowCount = ui.tableWidget->rowCount();
+
+ moveRowsUp(idx, rowCount - 1);
+ ui.tableWidget->setRowCount(rowCount - 1);
+
+ updateEditor();
+}
+
+void TableWidgetEditor::on_rowEditor_itemMovedUp(int idx)
+{
+ moveRowsUp(idx - 1, idx);
+
+ ui.tableWidget->setCurrentCell(idx - 1, ui.tableWidget->currentColumn());
+}
+
+void TableWidgetEditor::on_rowEditor_itemMovedDown(int idx)
+{
+ moveRowsDown(idx, idx + 1);
+
+ ui.tableWidget->setCurrentCell(idx + 1, ui.tableWidget->currentColumn());
+}
+
+void TableWidgetEditor::cacheReloaded()
+{
+ reloadIconResources(iconCache(), ui.tableWidget);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/tablewidgeteditor.h b/tools/designer/src/components/taskmenu/tablewidgeteditor.h
new file mode 100644
index 0000000000..a4f0b52c0d
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/tablewidgeteditor.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TABLEWIDGETEDITOR_H
+#define TABLEWIDGETEDITOR_H
+
+#include "ui_tablewidgeteditor.h"
+
+#include "listwidgeteditor.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTableWidget;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class FormWindowBase;
+class PropertySheetIconValue;
+
+class TableWidgetEditor: public AbstractItemEditor
+{
+ Q_OBJECT
+public:
+ TableWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent);
+
+ TableWidgetContents fillContentsFromTableWidget(QTableWidget *tableWidget);
+ TableWidgetContents contents() const;
+
+private slots:
+
+ void on_tableWidget_currentCellChanged(int currentRow, int currnetCol, int, int);
+ void on_tableWidget_itemChanged(QTableWidgetItem *item);
+
+ void on_columnEditor_indexChanged(int idx);
+ void on_columnEditor_itemChanged(int idx, int role, const QVariant &v);
+
+ void on_columnEditor_itemInserted(int idx);
+ void on_columnEditor_itemDeleted(int idx);
+ void on_columnEditor_itemMovedUp(int idx);
+ void on_columnEditor_itemMovedDown(int idx);
+
+ void on_rowEditor_indexChanged(int idx);
+ void on_rowEditor_itemChanged(int idx, int role, const QVariant &v);
+
+ void on_rowEditor_itemInserted(int idx);
+ void on_rowEditor_itemDeleted(int idx);
+ void on_rowEditor_itemMovedUp(int idx);
+ void on_rowEditor_itemMovedDown(int idx);
+
+ void togglePropertyBrowser();
+
+ void cacheReloaded();
+
+protected:
+ virtual void setItemData(int role, const QVariant &v);
+ virtual QVariant getItemData(int role) const;
+
+private:
+ void updateEditor();
+ void moveColumnsLeft(int fromColumn, int toColumn);
+ void moveColumnsRight(int fromColumn, int toColumn);
+ void moveRowsUp(int fromRow, int toRow);
+ void moveRowsDown(int fromRow, int toRow);
+
+ Ui::TableWidgetEditor ui;
+ ItemListEditor *m_rowEditor;
+ ItemListEditor *m_columnEditor;
+ bool m_updatingBrowser;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TABLEWIDGETEDITOR_H
diff --git a/tools/designer/src/components/taskmenu/tablewidgeteditor.ui b/tools/designer/src/components/taskmenu/tablewidgeteditor.ui
new file mode 100644
index 0000000000..be59fd295d
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/tablewidgeteditor.ui
@@ -0,0 +1,157 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::TableWidgetEditor</class>
+ <widget class="QDialog" name="qdesigner_internal::TableWidgetEditor" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>550</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Edit Table Widget</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="itemsTab" >
+ <attribute name="title" >
+ <string>&amp;Items</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2" >
+ <item>
+ <widget class="QWidget" native="1" name="widget" >
+ <layout class="QVBoxLayout" name="verticalLayout_3" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTableWidget" name="tableWidget" >
+ <property name="toolTip" >
+ <string>Table Items</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="buttonsLayout" >
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="showPropertiesButton" >
+ <property name="text" >
+ <string>Properties &amp;>></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>qdesigner_internal::TableWidgetEditor</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>431</x>
+ <y>351</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>373</x>
+ <y>362</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>qdesigner_internal::TableWidgetEditor</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>547</x>
+ <y>354</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>562</x>
+ <y>362</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/components/taskmenu/taskmenu.pri b/tools/designer/src/components/taskmenu/taskmenu.pri
new file mode 100644
index 0000000000..066b929808
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/taskmenu.pri
@@ -0,0 +1,50 @@
+INCLUDEPATH += $$PWD \
+ ../propertyeditor \
+ $$QT_BUILD_TREE/tools/designer/src/components/taskmenu \
+ $$QT_SOURCE_TREE/tools/shared/qtpropertybrowser
+
+FORMS += $$PWD/itemlisteditor.ui \
+ $$PWD/treewidgeteditor.ui \
+ $$PWD/tablewidgeteditor.ui
+
+HEADERS += $$PWD/button_taskmenu.h \
+ $$PWD/groupbox_taskmenu.h \
+ $$PWD/label_taskmenu.h \
+ $$PWD/lineedit_taskmenu.h \
+ $$PWD/listwidget_taskmenu.h \
+ $$PWD/treewidget_taskmenu.h \
+ $$PWD/tablewidget_taskmenu.h \
+ $$PWD/combobox_taskmenu.h \
+ $$PWD/textedit_taskmenu.h \
+ $$PWD/toolbar_taskmenu.h \
+ $$PWD/containerwidget_taskmenu.h \
+ $$PWD/inplace_editor.h \
+ $$PWD/taskmenu_component.h \
+ $$PWD/itemlisteditor.h \
+ $$PWD/listwidgeteditor.h \
+ $$PWD/treewidgeteditor.h \
+ $$PWD/tablewidgeteditor.h \
+ $$PWD/inplace_widget_helper.h \
+ $$PWD/menutaskmenu.h \
+ $$PWD/layouttaskmenu.h
+
+SOURCES += $$PWD/button_taskmenu.cpp \
+ $$PWD/groupbox_taskmenu.cpp \
+ $$PWD/label_taskmenu.cpp \
+ $$PWD/lineedit_taskmenu.cpp \
+ $$PWD/listwidget_taskmenu.cpp \
+ $$PWD/treewidget_taskmenu.cpp \
+ $$PWD/tablewidget_taskmenu.cpp \
+ $$PWD/combobox_taskmenu.cpp \
+ $$PWD/textedit_taskmenu.cpp \
+ $$PWD/toolbar_taskmenu.cpp \
+ $$PWD/containerwidget_taskmenu.cpp \
+ $$PWD/inplace_editor.cpp \
+ $$PWD/taskmenu_component.cpp \
+ $$PWD/itemlisteditor.cpp \
+ $$PWD/listwidgeteditor.cpp \
+ $$PWD/treewidgeteditor.cpp \
+ $$PWD/tablewidgeteditor.cpp \
+ $$PWD/inplace_widget_helper.cpp \
+ $$PWD/menutaskmenu.cpp \
+ $$PWD/layouttaskmenu.cpp
diff --git a/tools/designer/src/components/taskmenu/taskmenu_component.cpp b/tools/designer/src/components/taskmenu/taskmenu_component.cpp
new file mode 100644
index 0000000000..629fc8ae2f
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/taskmenu_component.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "taskmenu_component.h"
+#include "button_taskmenu.h"
+#include "groupbox_taskmenu.h"
+#include "label_taskmenu.h"
+#include "lineedit_taskmenu.h"
+#include "listwidget_taskmenu.h"
+#include "treewidget_taskmenu.h"
+#include "tablewidget_taskmenu.h"
+#include "containerwidget_taskmenu.h"
+#include "combobox_taskmenu.h"
+#include "textedit_taskmenu.h"
+#include "menutaskmenu.h"
+#include "toolbar_taskmenu.h"
+#include "layouttaskmenu.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+TaskMenuComponent::TaskMenuComponent(QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent),
+ m_core(core)
+{
+ Q_ASSERT(m_core != 0);
+
+ QExtensionManager *mgr = core->extensionManager();
+ const QString taskMenuId = QLatin1String("QDesignerInternalTaskMenuExtension");
+
+ ButtonTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ CommandLinkButtonTaskMenuFactory::registerExtension(mgr, taskMenuId); // Order!
+ ButtonGroupTaskMenuFactory::registerExtension(mgr, taskMenuId);
+
+ GroupBoxTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ LabelTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ LineEditTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ ListWidgetTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ TreeWidgetTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ TableWidgetTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ TextEditTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ PlainTextEditTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ MenuTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ MenuBarTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ ToolBarTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ StatusBarTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ LayoutWidgetTaskMenuFactory::registerExtension(mgr, taskMenuId);
+ SpacerTaskMenuFactory::registerExtension(mgr, taskMenuId);
+
+ mgr->registerExtensions(new ContainerWidgetTaskMenuFactory(core, mgr), taskMenuId);
+ mgr->registerExtensions(new ComboBoxTaskMenuFactory(taskMenuId, mgr), taskMenuId);
+}
+
+TaskMenuComponent::~TaskMenuComponent()
+{
+}
+
+QDesignerFormEditorInterface *TaskMenuComponent::core() const
+{
+ return m_core;
+
+}
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/components/taskmenu/taskmenu_component.h b/tools/designer/src/components/taskmenu/taskmenu_component.h
new file mode 100644
index 0000000000..56f3eaf30f
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/taskmenu_component.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TASKMENU_COMPONENT_H
+#define TASKMENU_COMPONENT_H
+
+#include "taskmenu_global.h"
+#include <QtDesigner/taskmenu.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class QT_TASKMENU_EXPORT TaskMenuComponent: public QObject
+{
+ Q_OBJECT
+public:
+ explicit TaskMenuComponent(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ virtual ~TaskMenuComponent();
+
+ QDesignerFormEditorInterface *core() const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TASKMENU_COMPONENT_H
diff --git a/tools/designer/src/components/taskmenu/taskmenu_global.h b/tools/designer/src/components/taskmenu/taskmenu_global.h
new file mode 100644
index 0000000000..418c849cfc
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/taskmenu_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TASKMENU_GLOBAL_H
+#define TASKMENU_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN
+#ifdef QT_TASKMENU_LIBRARY
+# define QT_TASKMENU_EXPORT
+#else
+# define QT_TASKMENU_EXPORT
+#endif
+#else
+#define QT_TASKMENU_EXPORT
+#endif
+
+#endif // TASKMENU_GLOBAL_H
diff --git a/tools/designer/src/components/taskmenu/textedit_taskmenu.cpp b/tools/designer/src/components/taskmenu/textedit_taskmenu.cpp
new file mode 100644
index 0000000000..feaec2cf75
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/textedit_taskmenu.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::TextEditTaskMenu
+*/
+
+#include "textedit_taskmenu.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtCore/QEvent>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+TextEditTaskMenu::TextEditTaskMenu(QTextEdit *textEdit, QObject *parent) :
+ QDesignerTaskMenu(textEdit, parent),
+ m_format(Qt::RichText),
+ m_property(QLatin1String("html")),
+ m_windowTitle(tr("Edit HTML")),
+ m_editTextAction(new QAction(tr("Change HTML..."), this))
+{
+ initialize();
+}
+
+TextEditTaskMenu::TextEditTaskMenu(QPlainTextEdit *textEdit, QObject *parent) :
+ QDesignerTaskMenu(textEdit, parent),
+ m_format(Qt::PlainText),
+ m_property(QLatin1String("plainText")),
+ m_windowTitle(tr("Edit Text")),
+ m_editTextAction(new QAction(tr("Change Plain Text..."), this))
+{
+ initialize();
+}
+
+
+void TextEditTaskMenu::initialize()
+{
+ connect(m_editTextAction, SIGNAL(triggered()), this, SLOT(editText()));
+ m_taskActions.append(m_editTextAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+TextEditTaskMenu::~TextEditTaskMenu()
+{
+}
+
+QAction *TextEditTaskMenu::preferredEditAction() const
+{
+ return m_editTextAction;
+}
+
+QList<QAction*> TextEditTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+void TextEditTaskMenu::editText()
+{
+ changeTextProperty(m_property, m_windowTitle, MultiSelectionMode, m_format);
+}
+
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/textedit_taskmenu.h b/tools/designer/src/components/taskmenu/textedit_taskmenu.h
new file mode 100644
index 0000000000..939e3ec7e9
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/textedit_taskmenu.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTEDIT_TASKMENU_H
+#define TEXTEDIT_TASKMENU_H
+
+#include <QtGui/QTextEdit>
+#include <QtGui/QPlainTextEdit>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class TextEditTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit TextEditTaskMenu(QTextEdit *button, QObject *parent = 0);
+ explicit TextEditTaskMenu(QPlainTextEdit *button, QObject *parent = 0);
+
+ virtual ~TextEditTaskMenu();
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void editText();
+
+private:
+ void initialize();
+
+ const Qt::TextFormat m_format;
+ const QString m_property;
+ const QString m_windowTitle;
+
+ mutable QList<QAction*> m_taskActions;
+ QAction *m_editTextAction;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QTextEdit, TextEditTaskMenu> TextEditTaskMenuFactory;
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QPlainTextEdit, TextEditTaskMenu> PlainTextEditTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TEXTEDIT_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/toolbar_taskmenu.cpp b/tools/designer/src/components/taskmenu/toolbar_taskmenu.cpp
new file mode 100644
index 0000000000..a15cd8a299
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/toolbar_taskmenu.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ToolBarTaskMenu
+*/
+
+#include "toolbar_taskmenu.h"
+#include "qdesigner_toolbar_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <promotiontaskmenu_p.h>
+#include <qdesigner_command_p.h>
+
+#include <QtGui/QAction>
+#include <QtGui/QUndoStack>
+
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ // ------------ ToolBarTaskMenu
+ ToolBarTaskMenu::ToolBarTaskMenu(QToolBar *tb, QObject *parent) :
+ QObject(parent),
+ m_toolBar(tb)
+ {
+ }
+
+ QAction *ToolBarTaskMenu::preferredEditAction() const
+ {
+ return 0;
+ }
+
+ QList<QAction*> ToolBarTaskMenu::taskActions() const
+ {
+ if (ToolBarEventFilter *ef = ToolBarEventFilter::eventFilterOf(m_toolBar))
+ return ef->contextMenuActions();
+ return QList<QAction*>();
+ }
+
+ // ------------ StatusBarTaskMenu
+ StatusBarTaskMenu::StatusBarTaskMenu(QStatusBar *sb, QObject *parent) :
+ QObject(parent),
+ m_statusBar(sb),
+ m_removeAction(new QAction(tr("Remove"), this)),
+ m_promotionTaskMenu(new PromotionTaskMenu(sb, PromotionTaskMenu::ModeSingleWidget, this))
+ {
+ connect(m_removeAction, SIGNAL(triggered()), this, SLOT(removeStatusBar()));
+ }
+
+ QAction *StatusBarTaskMenu::preferredEditAction() const
+ {
+ return 0;
+ }
+
+ QList<QAction*> StatusBarTaskMenu::taskActions() const
+ {
+ QList<QAction*> rc;
+ rc.push_back(m_removeAction);
+ m_promotionTaskMenu->addActions(PromotionTaskMenu::LeadingSeparator, rc);
+ return rc;
+ }
+
+ void StatusBarTaskMenu::removeStatusBar()
+ {
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_statusBar)) {
+ DeleteStatusBarCommand *cmd = new DeleteStatusBarCommand(fw);
+ cmd->init(m_statusBar);
+ fw->commandHistory()->push(cmd);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/components/taskmenu/toolbar_taskmenu.h b/tools/designer/src/components/taskmenu/toolbar_taskmenu.h
new file mode 100644
index 0000000000..4ae1994eb5
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/toolbar_taskmenu.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOOLBAR_TASKMENU_H
+#define TOOLBAR_TASKMENU_H
+
+#include <QtDesigner/QDesignerTaskMenuExtension>
+
+#include <extensionfactory_p.h>
+
+#include <QtGui/QToolBar>
+#include <QtGui/QStatusBar>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ class PromotionTaskMenu;
+
+// ToolBarTaskMenu forwards the actions of ToolBarEventFilter
+class ToolBarTaskMenu : public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit ToolBarTaskMenu(QToolBar *tb, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private:
+ QToolBar *m_toolBar;
+};
+
+// StatusBarTaskMenu provides promotion and deletion
+class StatusBarTaskMenu : public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit StatusBarTaskMenu(QStatusBar *tb, QObject *parent = 0);
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void removeStatusBar();
+
+private:
+ QStatusBar *m_statusBar;
+ QAction *m_removeAction;
+ PromotionTaskMenu *m_promotionTaskMenu;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QToolBar, ToolBarTaskMenu> ToolBarTaskMenuFactory;
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QStatusBar, StatusBarTaskMenu> StatusBarTaskMenuFactory;
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TOOLBAR_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp b/tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp
new file mode 100644
index 0000000000..b1c8c284d5
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/treewidget_taskmenu.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::TreeWidgetTaskMenu
+*/
+
+#include "treewidget_taskmenu.h"
+#include "treewidgeteditor.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QStyle>
+#include <QtGui/QLineEdit>
+#include <QtGui/QStyleOption>
+
+#include <QtCore/QEvent>
+#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+TreeWidgetTaskMenu::TreeWidgetTaskMenu(QTreeWidget *button, QObject *parent)
+ : QDesignerTaskMenu(button, parent),
+ m_treeWidget(button),
+ m_editItemsAction(new QAction(tr("Edit Items..."), this))
+{
+ connect(m_editItemsAction, SIGNAL(triggered()), this, SLOT(editItems()));
+ m_taskActions.append(m_editItemsAction);
+
+ QAction *sep = new QAction(this);
+ sep->setSeparator(true);
+ m_taskActions.append(sep);
+}
+
+
+TreeWidgetTaskMenu::~TreeWidgetTaskMenu()
+{
+}
+
+QAction *TreeWidgetTaskMenu::preferredEditAction() const
+{
+ return m_editItemsAction;
+}
+
+QList<QAction*> TreeWidgetTaskMenu::taskActions() const
+{
+ return m_taskActions + QDesignerTaskMenu::taskActions();
+}
+
+void TreeWidgetTaskMenu::editItems()
+{
+ m_formWindow = QDesignerFormWindowInterface::findFormWindow(m_treeWidget);
+ if (m_formWindow.isNull())
+ return;
+
+ Q_ASSERT(m_treeWidget != 0);
+
+ TreeWidgetEditor dlg(m_formWindow, m_treeWidget->window());
+ TreeWidgetContents oldCont = dlg.fillContentsFromTreeWidget(m_treeWidget);
+ if (dlg.exec() == QDialog::Accepted) {
+ TreeWidgetContents newCont = dlg.contents();
+ if (newCont != oldCont) {
+ ChangeTreeContentsCommand *cmd = new ChangeTreeContentsCommand(m_formWindow);
+ cmd->init(m_treeWidget, oldCont, newCont);
+ m_formWindow->commandHistory()->push(cmd);
+ }
+ }
+}
+
+void TreeWidgetTaskMenu::updateSelection()
+{
+ if (m_editor)
+ m_editor->deleteLater();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/treewidget_taskmenu.h b/tools/designer/src/components/taskmenu/treewidget_taskmenu.h
new file mode 100644
index 0000000000..dac4c205a3
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/treewidget_taskmenu.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TREEWIDGET_TASKMENU_H
+#define TREEWIDGET_TASKMENU_H
+
+#include <QtGui/QTreeWidget>
+#include <QtCore/QPointer>
+
+#include <qdesigner_taskmenu_p.h>
+#include <extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QLineEdit;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class TreeWidgetTaskMenu: public QDesignerTaskMenu
+{
+ Q_OBJECT
+public:
+ explicit TreeWidgetTaskMenu(QTreeWidget *button, QObject *parent = 0);
+ virtual ~TreeWidgetTaskMenu();
+
+ virtual QAction *preferredEditAction() const;
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void editItems();
+ void updateSelection();
+
+private:
+ QTreeWidget *m_treeWidget;
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ QPointer<QLineEdit> m_editor;
+ mutable QList<QAction*> m_taskActions;
+ QAction *m_editItemsAction;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QTreeWidget, TreeWidgetTaskMenu> TreeWidgetTaskMenuFactory;
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TREEWIDGET_TASKMENU_H
diff --git a/tools/designer/src/components/taskmenu/treewidgeteditor.cpp b/tools/designer/src/components/taskmenu/treewidgeteditor.cpp
new file mode 100644
index 0000000000..faf00f2e6a
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/treewidgeteditor.cpp
@@ -0,0 +1,607 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::TreeWidgetEditor
+*/
+
+#include "treewidgeteditor.h"
+#include <formwindowbase_p.h>
+#include <iconloader_p.h>
+#include <qdesigner_command_p.h>
+#include <qdesigner_utils_p.h>
+#include <abstractformbuilder.h>
+#include <designerpropertymanager.h>
+#include <qttreepropertybrowser.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtCore/QDir>
+#include <QtCore/QQueue>
+#include <QtGui/QHeaderView>
+#include <QtGui/QTreeWidgetItemIterator>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+TreeWidgetEditor::TreeWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent)
+ : AbstractItemEditor(form, parent), m_updatingBrowser(false)
+{
+ m_columnEditor = new ItemListEditor(form, this);
+ m_columnEditor->setObjectName(QLatin1String("columnEditor"));
+ m_columnEditor->setNewItemText(tr("New Column"));
+ ui.setupUi(this);
+
+ injectPropertyBrowser(ui.itemsTab, ui.widget);
+ connect(ui.showPropertiesButton, SIGNAL(clicked()),
+ this, SLOT(togglePropertyBrowser()));
+ togglePropertyBrowser();
+
+ ui.tabWidget->insertTab(0, m_columnEditor, tr("&Columns"));
+ ui.tabWidget->setCurrentIndex(0);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ ui.newItemButton->setIcon(createIconSet(QString::fromUtf8("plus.png")));
+ ui.newSubItemButton->setIcon(createIconSet(QString::fromUtf8("downplus.png")));
+ ui.deleteItemButton->setIcon(createIconSet(QString::fromUtf8("minus.png")));
+ ui.moveItemUpButton->setIcon(createIconSet(QString::fromUtf8("up.png")));
+ ui.moveItemDownButton->setIcon(createIconSet(QString::fromUtf8("down.png")));
+ ui.moveItemRightButton->setIcon(createIconSet(QString::fromUtf8("leveldown.png")));
+ ui.moveItemLeftButton->setIcon(createIconSet(QString::fromUtf8("levelup.png")));
+
+ ui.treeWidget->header()->setMovable(false);
+
+ connect(iconCache(), SIGNAL(reloaded()), this, SLOT(cacheReloaded()));
+}
+
+static AbstractItemEditor::PropertyDefinition treeHeaderPropList[] = {
+ { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
+ { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
+ { Qt::ToolTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "toolTip" },
+ { Qt::StatusTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "statusTip" },
+ { Qt::WhatsThisPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "whatsThis" },
+ { Qt::FontRole, QVariant::Font, 0, "font" },
+ { Qt::TextAlignmentRole, 0, DesignerPropertyManager::designerAlignmentTypeId, "textAlignment" },
+ { Qt::BackgroundRole, QVariant::Color, 0, "background" },
+ { Qt::ForegroundRole, QVariant::Brush, 0, "foreground" },
+ { 0, 0, 0, 0 }
+};
+
+static AbstractItemEditor::PropertyDefinition treeItemColumnPropList[] = {
+ { Qt::DisplayPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "text" },
+ { Qt::DecorationPropertyRole, 0, DesignerPropertyManager::designerIconTypeId, "icon" },
+ { Qt::ToolTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "toolTip" },
+ { Qt::StatusTipPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "statusTip" },
+ { Qt::WhatsThisPropertyRole, 0, DesignerPropertyManager::designerStringTypeId, "whatsThis" },
+ { Qt::FontRole, QVariant::Font, 0, "font" },
+ { Qt::TextAlignmentRole, 0, DesignerPropertyManager::designerAlignmentTypeId, "textAlignment" },
+ { Qt::BackgroundRole, QVariant::Brush, 0, "background" },
+ { Qt::ForegroundRole, QVariant::Brush, 0, "foreground" },
+ { Qt::CheckStateRole, 0, QtVariantPropertyManager::enumTypeId, "checkState" },
+ { 0, 0, 0, 0 }
+};
+
+static AbstractItemEditor::PropertyDefinition treeItemCommonPropList[] = {
+ { ItemFlagsShadowRole, 0, QtVariantPropertyManager::flagTypeId, "flags" },
+ { 0, 0, 0, 0 }
+};
+
+QtVariantProperty *TreeWidgetEditor::setupPropertyGroup(const QString &title, PropertyDefinition *propDefs)
+{
+ setupProperties(propDefs);
+ QtVariantProperty *groupProp = m_propertyManager->addProperty(QtVariantPropertyManager::groupTypeId(), title);
+ foreach (QtVariantProperty *prop, m_rootProperties)
+ groupProp->addSubProperty(prop);
+ m_rootProperties.clear();
+ return groupProp;
+}
+
+TreeWidgetContents TreeWidgetEditor::fillContentsFromTreeWidget(QTreeWidget *treeWidget)
+{
+ TreeWidgetContents treeCont;
+ treeCont.fromTreeWidget(treeWidget, false);
+ treeCont.applyToTreeWidget(ui.treeWidget, iconCache(), true);
+
+ treeCont.m_headerItem.applyToListWidget(m_columnEditor->listWidget(), iconCache(), true);
+ m_columnEditor->setupEditor(treeWidget, treeHeaderPropList);
+
+ QList<QtVariantProperty*> rootProperties;
+ rootProperties.append(setupPropertyGroup(tr("Per column properties"), treeItemColumnPropList));
+ rootProperties.append(setupPropertyGroup(tr("Common properties"), treeItemCommonPropList));
+ m_rootProperties = rootProperties;
+ m_propertyBrowser->setPropertiesWithoutValueMarked(true);
+ m_propertyBrowser->setRootIsDecorated(false);
+ setupObject(treeWidget);
+
+ if (ui.treeWidget->topLevelItemCount() > 0)
+ ui.treeWidget->setCurrentItem(ui.treeWidget->topLevelItem(0));
+
+ updateEditor();
+
+ return treeCont;
+}
+
+TreeWidgetContents TreeWidgetEditor::contents() const
+{
+ TreeWidgetContents retVal;
+ retVal.fromTreeWidget(ui.treeWidget, true);
+ return retVal;
+}
+
+void TreeWidgetEditor::setItemData(int role, const QVariant &v)
+{
+ const int col = (role == ItemFlagsShadowRole) ? 0 : ui.treeWidget->currentColumn();
+ QVariant newValue = v;
+ BoolBlocker block(m_updatingBrowser);
+ if (role == Qt::FontRole && newValue.type() == QVariant::Font) {
+ QFont oldFont = ui.treeWidget->font();
+ QFont newFont = qVariantValue<QFont>(newValue).resolve(oldFont);
+ newValue = qVariantFromValue(newFont);
+ ui.treeWidget->currentItem()->setData(col, role, QVariant()); // force the right font with the current resolve mask is set (item view bug)
+ }
+ ui.treeWidget->currentItem()->setData(col, role, newValue);
+}
+
+QVariant TreeWidgetEditor::getItemData(int role) const
+{
+ const int col = (role == ItemFlagsShadowRole) ? 0 : ui.treeWidget->currentColumn();
+ return ui.treeWidget->currentItem()->data(col, role);
+}
+
+void TreeWidgetEditor::on_newItemButton_clicked()
+{
+ QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
+ QTreeWidgetItem *newItem = 0;
+ ui.treeWidget->blockSignals(true);
+ if (curItem) {
+ if (curItem->parent())
+ newItem = new QTreeWidgetItem(curItem->parent(), curItem);
+ else
+ newItem = new QTreeWidgetItem(ui.treeWidget, curItem);
+ } else
+ newItem = new QTreeWidgetItem(ui.treeWidget);
+ const QString newItemText = tr("New Item");
+ newItem->setText(0, newItemText);
+ newItem->setData(0, Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(newItemText)));
+ newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+ ui.treeWidget->blockSignals(false);
+
+ ui.treeWidget->setCurrentItem(newItem, qMax(ui.treeWidget->currentColumn(), 0));
+ updateEditor();
+ ui.treeWidget->editItem(newItem, ui.treeWidget->currentColumn());
+}
+
+void TreeWidgetEditor::on_newSubItemButton_clicked()
+{
+ QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
+ if (!curItem)
+ return;
+
+ ui.treeWidget->blockSignals(true);
+ QTreeWidgetItem *newItem = new QTreeWidgetItem(curItem);
+ const QString newItemText = tr("New Subitem");
+ newItem->setText(0, newItemText);
+ newItem->setData(0, Qt::DisplayPropertyRole, qVariantFromValue(PropertySheetStringValue(newItemText)));
+ newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+ ui.treeWidget->blockSignals(false);
+
+ ui.treeWidget->setCurrentItem(newItem, ui.treeWidget->currentColumn());
+ updateEditor();
+ ui.treeWidget->editItem(newItem, ui.treeWidget->currentColumn());
+}
+
+void TreeWidgetEditor::on_deleteItemButton_clicked()
+{
+ QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
+ if (!curItem)
+ return;
+
+ QTreeWidgetItem *nextCurrent = 0;
+ if (curItem->parent()) {
+ int idx = curItem->parent()->indexOfChild(curItem);
+ if (idx == curItem->parent()->childCount() - 1)
+ idx--;
+ else
+ idx++;
+ if (idx < 0)
+ nextCurrent = curItem->parent();
+ else
+ nextCurrent = curItem->parent()->child(idx);
+ } else {
+ int idx = ui.treeWidget->indexOfTopLevelItem(curItem);
+ if (idx == ui.treeWidget->topLevelItemCount() - 1)
+ idx--;
+ else
+ idx++;
+ if (idx >= 0)
+ nextCurrent = ui.treeWidget->topLevelItem(idx);
+ }
+ closeEditors();
+ ui.treeWidget->blockSignals(true);
+ delete curItem;
+ ui.treeWidget->blockSignals(false);
+
+ if (nextCurrent)
+ ui.treeWidget->setCurrentItem(nextCurrent, ui.treeWidget->currentColumn());
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_moveItemUpButton_clicked()
+{
+ QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
+ if (!curItem)
+ return;
+
+ int idx;
+ if (curItem->parent())
+ idx = curItem->parent()->indexOfChild(curItem);
+ else
+ idx = ui.treeWidget->indexOfTopLevelItem(curItem);
+ if (idx == 0)
+ return;
+
+ QTreeWidgetItem *takenItem;
+ ui.treeWidget->blockSignals(true);
+ if (curItem->parent()) {
+ QTreeWidgetItem *parentItem = curItem->parent();
+ takenItem = parentItem->takeChild(idx);
+ parentItem->insertChild(idx - 1, takenItem);
+ } else {
+ takenItem = ui.treeWidget->takeTopLevelItem(idx);
+ ui.treeWidget->insertTopLevelItem(idx - 1, takenItem);
+ }
+ ui.treeWidget->blockSignals(false);
+
+ ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_moveItemDownButton_clicked()
+{
+ QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
+ if (!curItem)
+ return;
+
+ int idx, idxCount;
+ if (curItem->parent()) {
+ idx = curItem->parent()->indexOfChild(curItem);
+ idxCount = curItem->parent()->childCount();
+ } else {
+ idx = ui.treeWidget->indexOfTopLevelItem(curItem);
+ idxCount = ui.treeWidget->topLevelItemCount();
+ }
+ if (idx == idxCount - 1)
+ return;
+
+ QTreeWidgetItem *takenItem;
+ ui.treeWidget->blockSignals(true);
+ if (curItem->parent()) {
+ QTreeWidgetItem *parentItem = curItem->parent();
+ takenItem = parentItem->takeChild(idx);
+ parentItem->insertChild(idx + 1, takenItem);
+ } else {
+ takenItem = ui.treeWidget->takeTopLevelItem(idx);
+ ui.treeWidget->insertTopLevelItem(idx + 1, takenItem);
+ }
+ ui.treeWidget->blockSignals(false);
+
+ ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_moveItemLeftButton_clicked()
+{
+ QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
+ if (!curItem)
+ return;
+
+ QTreeWidgetItem *parentItem = curItem->parent();
+ if (!parentItem)
+ return;
+
+ ui.treeWidget->blockSignals(true);
+ QTreeWidgetItem *takenItem = parentItem->takeChild(parentItem->indexOfChild(curItem));
+ if (parentItem->parent()) {
+ int idx = parentItem->parent()->indexOfChild(parentItem);
+ parentItem->parent()->insertChild(idx, takenItem);
+ } else {
+ int idx = ui.treeWidget->indexOfTopLevelItem(parentItem);
+ ui.treeWidget->insertTopLevelItem(idx, takenItem);
+ }
+ ui.treeWidget->blockSignals(false);
+
+ ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_moveItemRightButton_clicked()
+{
+ QTreeWidgetItem *curItem = ui.treeWidget->currentItem();
+ if (!curItem)
+ return;
+
+ int idx, idxCount;
+ if (curItem->parent()) {
+ idx = curItem->parent()->indexOfChild(curItem);
+ idxCount = curItem->parent()->childCount();
+ } else {
+ idx = ui.treeWidget->indexOfTopLevelItem(curItem);
+ idxCount = ui.treeWidget->topLevelItemCount();
+ }
+ if (idx == idxCount - 1)
+ return;
+
+ QTreeWidgetItem *takenItem;
+ ui.treeWidget->blockSignals(true);
+ if (curItem->parent()) {
+ QTreeWidgetItem *parentItem = curItem->parent()->child(idx + 1);
+ takenItem = curItem->parent()->takeChild(idx);
+ parentItem->insertChild(0, takenItem);
+ } else {
+ QTreeWidgetItem *parentItem = ui.treeWidget->topLevelItem(idx + 1);
+ takenItem = ui.treeWidget->takeTopLevelItem(idx);
+ parentItem->insertChild(0, takenItem);
+ }
+ ui.treeWidget->blockSignals(false);
+
+ ui.treeWidget->setCurrentItem(takenItem, ui.treeWidget->currentColumn());
+ updateEditor();
+}
+
+void TreeWidgetEditor::togglePropertyBrowser()
+{
+ // Always hide in case parent widget is not visible -> on startup
+ const bool isVisible =
+ !this->isVisible() ? true : m_propertyBrowser->isVisible();
+ if (isVisible)
+ ui.showPropertiesButton->setText(tr("Properties &<<"));
+ else
+ ui.showPropertiesButton->setText(tr("Properties &>>"));
+
+ m_propertyBrowser->setVisible(!isVisible);
+}
+
+void TreeWidgetEditor::on_treeWidget_currentItemChanged()
+{
+ m_columnEditor->setCurrentIndex(ui.treeWidget->currentColumn());
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_treeWidget_itemChanged(QTreeWidgetItem *item, int column)
+{
+ if (m_updatingBrowser)
+ return;
+
+ PropertySheetStringValue val = qVariantValue<PropertySheetStringValue>(item->data(column, Qt::DisplayPropertyRole));
+ val.setValue(item->text(column));
+ BoolBlocker block(m_updatingBrowser);
+ item->setData(column, Qt::DisplayPropertyRole, qVariantFromValue(val));
+
+ updateBrowser();
+}
+
+void TreeWidgetEditor::on_columnEditor_indexChanged(int idx)
+{
+ if (QTreeWidgetItem *item = ui.treeWidget->currentItem())
+ ui.treeWidget->setCurrentItem(item, idx);
+}
+
+void TreeWidgetEditor::on_columnEditor_itemChanged(int idx, int role, const QVariant &v)
+{
+ if (role == Qt::DisplayPropertyRole)
+ ui.treeWidget->headerItem()->setData(idx, Qt::EditRole, qVariantValue<PropertySheetStringValue>(v).value());
+ ui.treeWidget->headerItem()->setData(idx, role, v);
+}
+
+void TreeWidgetEditor::updateEditor()
+{
+ QTreeWidgetItem *current = ui.treeWidget->currentItem();
+
+ bool itemsEnabled = false;
+ bool currentItemEnabled = false;
+ bool moveItemUpEnabled = false;
+ bool moveItemDownEnabled = false;
+ bool moveItemRightEnabled = false;
+ bool moveItemLeftEnabled = false;
+
+ if (ui.treeWidget->columnCount() > 0) {
+ itemsEnabled = true;
+ if (current) {
+ int idx;
+ int idxCount;
+ currentItemEnabled = true;
+ if (current->parent()) {
+ moveItemLeftEnabled = true;
+ idx = current->parent()->indexOfChild(current);
+ idxCount = current->parent()->childCount();
+ } else {
+ idx = ui.treeWidget->indexOfTopLevelItem(current);
+ idxCount = ui.treeWidget->topLevelItemCount();
+ }
+ if (idx > 0)
+ moveItemUpEnabled = true;
+ if (idx < idxCount - 1) {
+ moveItemDownEnabled = true;
+ moveItemRightEnabled = true;
+ }
+ }
+ }
+ ui.tabWidget->setTabEnabled(1, itemsEnabled);
+ ui.newSubItemButton->setEnabled(currentItemEnabled);
+ ui.deleteItemButton->setEnabled(currentItemEnabled);
+
+ ui.moveItemUpButton->setEnabled(moveItemUpEnabled);
+ ui.moveItemDownButton->setEnabled(moveItemDownEnabled);
+ ui.moveItemRightButton->setEnabled(moveItemRightEnabled);
+ ui.moveItemLeftButton->setEnabled(moveItemLeftEnabled);
+
+ if (current)
+ updateBrowser();
+ else
+ m_propertyBrowser->clear();
+}
+
+void TreeWidgetEditor::moveColumnItems(const PropertyDefinition *propList,
+ QTreeWidgetItem *item, int fromColumn, int toColumn, int step)
+{
+ BoolBlocker block(m_updatingBrowser);
+
+ QList<QVariant> saveCol;
+ for (int j = 0; propList[j].name; j++)
+ saveCol.append(item->data(toColumn, propList[j].role));
+ QVariant editVariant = item->data(toColumn, Qt::EditRole);
+ QVariant toolTipVariant = item->data(toColumn, Qt::ToolTipRole);
+ QVariant statusTipVariant = item->data(toColumn, Qt::StatusTipRole);
+ QVariant whatsThisVariant = item->data(toColumn, Qt::WhatsThisRole);
+ QVariant decorationVariant = item->data(toColumn, Qt::DecorationRole);
+ for (int i = toColumn; i != fromColumn; i += step) {
+ for (int j = 0; propList[j].name; j++)
+ item->setData(i, propList[j].role, item->data(i + step, propList[j].role));
+ item->setData(i, Qt::EditRole, item->data(i + step, Qt::EditRole));
+ item->setData(i, Qt::ToolTipRole, item->data(i + step, Qt::ToolTipRole));
+ item->setData(i, Qt::StatusTipRole, item->data(i + step, Qt::StatusTipRole));
+ item->setData(i, Qt::WhatsThisRole, item->data(i + step, Qt::WhatsThisRole));
+ item->setData(i, Qt::DecorationRole, item->data(i + step, Qt::DecorationRole));
+ }
+ for (int j = 0; propList[j].name; j++)
+ item->setData(fromColumn, propList[j].role, saveCol[j]);
+ item->setData(fromColumn, Qt::EditRole, editVariant);
+ item->setData(fromColumn, Qt::ToolTipRole, toolTipVariant);
+ item->setData(fromColumn, Qt::StatusTipRole, statusTipVariant);
+ item->setData(fromColumn, Qt::WhatsThisRole, whatsThisVariant);
+ item->setData(fromColumn, Qt::DecorationRole, decorationVariant);
+}
+
+void TreeWidgetEditor::moveColumns(int fromColumn, int toColumn, int step)
+{
+ ui.treeWidget->blockSignals(true);
+
+ moveColumnItems(treeHeaderPropList, ui.treeWidget->headerItem(), fromColumn, toColumn, step);
+
+ QQueue<QTreeWidgetItem *> pendingQueue;
+ for (int i = 0; i < ui.treeWidget->topLevelItemCount(); i++)
+ pendingQueue.enqueue(ui.treeWidget->topLevelItem(i));
+
+ while (!pendingQueue.isEmpty()) {
+ QTreeWidgetItem *item = pendingQueue.dequeue();
+ for (int i = 0; i < item->childCount(); i++)
+ pendingQueue.enqueue(item->child(i));
+
+ moveColumnItems(treeItemColumnPropList, item, fromColumn, toColumn, step);
+ }
+
+ ui.treeWidget->blockSignals(false);
+}
+
+void TreeWidgetEditor::moveColumnsLeft(int fromColumn, int toColumn)
+{
+ if (fromColumn >= toColumn)
+ return;
+
+ moveColumns(fromColumn, toColumn, -1);
+}
+
+void TreeWidgetEditor::moveColumnsRight(int fromColumn, int toColumn)
+{
+ if (fromColumn >= toColumn)
+ return;
+
+ moveColumns(toColumn, fromColumn, 1);
+}
+
+void TreeWidgetEditor::on_columnEditor_itemInserted(int idx)
+{
+ int columnCount = ui.treeWidget->columnCount();
+ ui.treeWidget->setColumnCount(columnCount + 1);
+ ui.treeWidget->headerItem()->setText(columnCount, m_columnEditor->newItemText());
+ moveColumnsLeft(idx, columnCount);
+
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_columnEditor_itemDeleted(int idx)
+{
+ closeEditors();
+
+ int columnCount = ui.treeWidget->columnCount() - 1;
+ if (!columnCount)
+ ui.treeWidget->clear();
+ else
+ moveColumnsRight(idx, columnCount);
+ ui.treeWidget->setColumnCount(columnCount);
+
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_columnEditor_itemMovedUp(int idx)
+{
+ moveColumnsRight(idx - 1, idx);
+
+ ui.treeWidget->setCurrentItem(ui.treeWidget->currentItem(), idx - 1);
+ updateEditor();
+}
+
+void TreeWidgetEditor::on_columnEditor_itemMovedDown(int idx)
+{
+ moveColumnsLeft(idx, idx + 1);
+
+ ui.treeWidget->setCurrentItem(ui.treeWidget->currentItem(), idx + 1);
+ updateEditor();
+}
+
+void TreeWidgetEditor::closeEditors()
+{
+ if (QTreeWidgetItem *cur = ui.treeWidget->currentItem() ) {
+ const int numCols = cur->columnCount ();
+ for (int i = 0; i < numCols; i++)
+ ui.treeWidget->closePersistentEditor (cur, i);
+ }
+}
+
+void TreeWidgetEditor::cacheReloaded()
+{
+ reloadIconResources(iconCache(), ui.treeWidget);
+}
+
+}
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/taskmenu/treewidgeteditor.h b/tools/designer/src/components/taskmenu/treewidgeteditor.h
new file mode 100644
index 0000000000..f4abc788bf
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/treewidgeteditor.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TREEWIDGETEDITOR_H
+#define TREEWIDGETEDITOR_H
+
+#include "ui_treewidgeteditor.h"
+
+#include "listwidgeteditor.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTreeWidget;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class FormWindowBase;
+class PropertySheetIconValue;
+
+class TreeWidgetEditor: public AbstractItemEditor
+{
+ Q_OBJECT
+public:
+ TreeWidgetEditor(QDesignerFormWindowInterface *form, QWidget *parent);
+
+ TreeWidgetContents fillContentsFromTreeWidget(QTreeWidget *treeWidget);
+ TreeWidgetContents contents() const;
+
+private slots:
+ void on_newItemButton_clicked();
+ void on_newSubItemButton_clicked();
+ void on_deleteItemButton_clicked();
+ void on_moveItemUpButton_clicked();
+ void on_moveItemDownButton_clicked();
+ void on_moveItemRightButton_clicked();
+ void on_moveItemLeftButton_clicked();
+
+ void on_treeWidget_currentItemChanged();
+ void on_treeWidget_itemChanged(QTreeWidgetItem *item, int column);
+
+ void on_columnEditor_indexChanged(int idx);
+ void on_columnEditor_itemChanged(int idx, int role, const QVariant &v);
+
+ void on_columnEditor_itemInserted(int idx);
+ void on_columnEditor_itemDeleted(int idx);
+ void on_columnEditor_itemMovedUp(int idx);
+ void on_columnEditor_itemMovedDown(int idx);
+
+ void togglePropertyBrowser();
+ void cacheReloaded();
+
+protected:
+ virtual void setItemData(int role, const QVariant &v);
+ virtual QVariant getItemData(int role) const;
+
+private:
+ QtVariantProperty *setupPropertyGroup(const QString &title, PropertyDefinition *propDefs);
+ void updateEditor();
+ void moveColumnItems(const PropertyDefinition *propList, QTreeWidgetItem *item, int fromColumn, int toColumn, int step);
+ void moveColumns(int fromColumn, int toColumn, int step);
+ void moveColumnsLeft(int fromColumn, int toColumn);
+ void moveColumnsRight(int fromColumn, int toColumn);
+ void closeEditors();
+
+ Ui::TreeWidgetEditor ui;
+ ItemListEditor *m_columnEditor;
+ bool m_updatingBrowser;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // TREEWIDGETEDITOR_H
diff --git a/tools/designer/src/components/taskmenu/treewidgeteditor.ui b/tools/designer/src/components/taskmenu/treewidgeteditor.ui
new file mode 100644
index 0000000000..d72b152248
--- /dev/null
+++ b/tools/designer/src/components/taskmenu/treewidgeteditor.ui
@@ -0,0 +1,257 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::TreeWidgetEditor</class>
+ <widget class="QDialog" name="qdesigner_internal::TreeWidgetEditor" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>700</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Edit Tree Widget</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="itemsTab" >
+ <attribute name="title" >
+ <string>&amp;Items</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3" >
+ <property name="leftMargin" >
+ <number>9</number>
+ </property>
+ <property name="topMargin" >
+ <number>9</number>
+ </property>
+ <property name="rightMargin" >
+ <number>9</number>
+ </property>
+ <item>
+ <widget class="QWidget" native="1" name="widget" >
+ <layout class="QVBoxLayout" name="verticalLayout_2" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="treeWidget" >
+ <property name="focusPolicy" >
+ <enum>Qt::WheelFocus</enum>
+ </property>
+ <property name="toolTip" >
+ <string>Tree Items</string>
+ </property>
+ <column>
+ <property name="text" >
+ <string>1</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="buttonsLayout" >
+ <item>
+ <widget class="QToolButton" name="newItemButton" >
+ <property name="toolTip" >
+ <string>New Item</string>
+ </property>
+ <property name="text" >
+ <string>&amp;New</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="newSubItemButton" >
+ <property name="toolTip" >
+ <string>New Subitem</string>
+ </property>
+ <property name="text" >
+ <string>New &amp;Subitem</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="deleteItemButton" >
+ <property name="toolTip" >
+ <string>Delete Item</string>
+ </property>
+ <property name="text" >
+ <string>&amp;Delete</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>28</width>
+ <height>23</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QToolButton" name="moveItemLeftButton" >
+ <property name="toolTip" >
+ <string>Move Item Left (before Parent Item)</string>
+ </property>
+ <property name="text" >
+ <string>L</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="moveItemRightButton" >
+ <property name="toolTip" >
+ <string>Move Item Right (as a First Subitem of the Next Sibling Item)</string>
+ </property>
+ <property name="text" >
+ <string>R</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="moveItemUpButton" >
+ <property name="toolTip" >
+ <string>Move Item Up</string>
+ </property>
+ <property name="text" >
+ <string>U</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="moveItemDownButton" >
+ <property name="toolTip" >
+ <string>Move Item Down</string>
+ </property>
+ <property name="text" >
+ <string>D</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="showPropertiesButton" >
+ <property name="text" >
+ <string>Properties &amp;>></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>qdesigner_internal::TreeWidgetEditor</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>440</x>
+ <y>335</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>373</x>
+ <y>362</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>qdesigner_internal::TreeWidgetEditor</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>556</x>
+ <y>335</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>562</x>
+ <y>362</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/components/widgetbox/widgetbox.cpp b/tools/designer/src/components/widgetbox/widgetbox.cpp
new file mode 100644
index 0000000000..d8c6aa37d7
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetbox.h"
+#include "widgetboxtreewidget.h"
+#include "widgetbox_dnditem.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <iconloader_p.h>
+#include <qdesigner_utils_p.h>
+#include <filterwidget_p.h>
+
+#include <QtGui/QDropEvent>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QToolBar>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+WidgetBox::WidgetBox(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags)
+ : QDesignerWidgetBox(parent, flags),
+ m_core(core),
+ m_view(new WidgetBoxTreeWidget(m_core))
+{
+
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->setMargin(0);
+ l->setSpacing(0);
+
+ // Prevent the filter from grabbing focus since Our view has Qt::NoFocus
+ FilterWidget *filterWidget = new FilterWidget(0, FilterWidget::LayoutAlignNone);
+ filterWidget->setRefuseFocus(true);
+ connect(filterWidget, SIGNAL(filterChanged(QString)), m_view, SLOT(filter(QString)));
+ l->addWidget(filterWidget);
+
+ // View
+ connect(m_view, SIGNAL(pressed(QString,QString,QPoint)),
+ this, SLOT(handleMousePress(QString,QString,QPoint)));
+ l->addWidget(m_view);
+
+ setAcceptDrops (true);
+}
+
+WidgetBox::~WidgetBox()
+{
+}
+
+QDesignerFormEditorInterface *WidgetBox::core() const
+{
+ return m_core;
+}
+
+void WidgetBox::handleMousePress(const QString &name, const QString &xml, const QPoint &global_mouse_pos)
+{
+ if (QApplication::mouseButtons() != Qt::LeftButton)
+ return;
+
+ DomUI *ui = xmlToUi(name, xml, true);
+ if (ui == 0)
+ return;
+ QList<QDesignerDnDItemInterface*> item_list;
+ item_list.append(new WidgetBoxDnDItem(core(), ui, global_mouse_pos));
+ m_core->formWindowManager()->dragItems(item_list);
+}
+
+int WidgetBox::categoryCount() const
+{
+ return m_view->categoryCount();
+}
+
+QDesignerWidgetBoxInterface::Category WidgetBox::category(int cat_idx) const
+{
+ return m_view->category(cat_idx);
+}
+
+void WidgetBox::addCategory(const Category &cat)
+{
+ m_view->addCategory(cat);
+}
+
+void WidgetBox::removeCategory(int cat_idx)
+{
+ m_view->removeCategory(cat_idx);
+}
+
+int WidgetBox::widgetCount(int cat_idx) const
+{
+ return m_view->widgetCount(cat_idx);
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBox::widget(int cat_idx, int wgt_idx) const
+{
+ return m_view->widget(cat_idx, wgt_idx);
+}
+
+void WidgetBox::addWidget(int cat_idx, const Widget &wgt)
+{
+ m_view->addWidget(cat_idx, wgt);
+}
+
+void WidgetBox::removeWidget(int cat_idx, int wgt_idx)
+{
+ m_view->removeWidget(cat_idx, wgt_idx);
+}
+
+void WidgetBox::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, const QPoint&)
+{
+ m_view->dropWidgets(item_list);
+}
+
+void WidgetBox::setFileName(const QString &file_name)
+{
+ m_view->setFileName(file_name);
+}
+
+QString WidgetBox::fileName() const
+{
+ return m_view->fileName();
+}
+
+bool WidgetBox::load()
+{
+ return m_view->load(loadMode());
+}
+
+bool WidgetBox::loadContents(const QString &contents)
+{
+ return m_view->loadContents(contents);
+}
+
+bool WidgetBox::save()
+{
+ return m_view->save();
+}
+
+static const QDesignerMimeData *checkDragEvent(QDropEvent * event,
+ bool acceptEventsFromWidgetBox)
+{
+ const QDesignerMimeData *mimeData = qobject_cast<const QDesignerMimeData *>(event->mimeData());
+ if (!mimeData) {
+ event->ignore();
+ return 0;
+ }
+ // If desired, ignore a widget box drag and drop, where widget==0.
+ if (!acceptEventsFromWidgetBox) {
+ const bool fromWidgetBox = !mimeData->items().first()->widget();
+ if (fromWidgetBox) {
+ event->ignore();
+ return 0;
+ }
+ }
+
+ mimeData->acceptEvent(event);
+ return mimeData;
+}
+
+void WidgetBox::dragEnterEvent (QDragEnterEvent * event)
+{
+ // We accept event originating from the widget box also here,
+ // because otherwise Windows will not show the DnD pixmap.
+ checkDragEvent(event, true);
+}
+
+void WidgetBox::dragMoveEvent(QDragMoveEvent * event)
+{
+ checkDragEvent(event, true);
+}
+
+void WidgetBox::dropEvent(QDropEvent * event)
+{
+ const QDesignerMimeData *mimeData = checkDragEvent(event, false);
+ if (!mimeData)
+ return;
+
+ dropWidgets(mimeData->items(), event->pos());
+ QDesignerMimeData::removeMovedWidgetsFromSourceForm(mimeData->items());
+}
+
+QIcon WidgetBox::iconForWidget(const QString &className, const QString &category) const
+{
+ Widget widgetData;
+ if (!findWidget(this, className, category, &widgetData))
+ return QIcon();
+ return m_view->iconForWidget(widgetData.iconName());
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetbox.h b/tools/designer/src/components/widgetbox/widgetbox.h
new file mode 100644
index 0000000000..e77c0ed89c
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOX_H
+#define WIDGETBOX_H
+
+#include "widgetbox_global.h"
+#include <qdesigner_widgetbox_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class WidgetBoxTreeWidget;
+
+class QT_WIDGETBOX_EXPORT WidgetBox : public QDesignerWidgetBox
+{
+ Q_OBJECT
+public:
+ explicit WidgetBox(QDesignerFormEditorInterface *core, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~WidgetBox();
+
+ QDesignerFormEditorInterface *core() const;
+
+ virtual int categoryCount() const;
+ virtual Category category(int cat_idx) const;
+ virtual void addCategory(const Category &cat);
+ virtual void removeCategory(int cat_idx);
+
+ virtual int widgetCount(int cat_idx) const;
+ virtual Widget widget(int cat_idx, int wgt_idx) const;
+ virtual void addWidget(int cat_idx, const Widget &wgt);
+ virtual void removeWidget(int cat_idx, int wgt_idx);
+
+ void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, const QPoint &global_mouse_pos);
+
+ virtual void setFileName(const QString &file_name);
+ virtual QString fileName() const;
+ virtual bool load();
+ virtual bool save();
+
+ virtual bool loadContents(const QString &contents);
+ virtual QIcon iconForWidget(const QString &className, const QString &category = QString()) const;
+
+protected:
+ virtual void dragEnterEvent (QDragEnterEvent * event);
+ virtual void dragMoveEvent(QDragMoveEvent * event);
+ virtual void dropEvent (QDropEvent * event);
+
+private slots:
+ void handleMousePress(const QString &name, const QString &xml, const QPoint &global_mouse_pos);
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ WidgetBoxTreeWidget *m_view;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOX_H
diff --git a/tools/designer/src/components/widgetbox/widgetbox.pri b/tools/designer/src/components/widgetbox/widgetbox.pri
new file mode 100644
index 0000000000..dd8ad002ec
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.pri
@@ -0,0 +1,14 @@
+
+INCLUDEPATH += $$PWD
+
+SOURCES += $$PWD/widgetboxcategorylistview.cpp \
+ $$PWD/widgetboxtreewidget.cpp \
+ $$PWD/widgetbox.cpp \
+ $$PWD/widgetbox_dnditem.cpp
+HEADERS += $$PWD/widgetboxcategorylistview.h \
+ $$PWD/widgetboxtreewidget.h \
+ $$PWD/widgetbox.h \
+ $$PWD/widgetbox_global.h \
+ $$PWD/widgetbox_dnditem.h
+
+RESOURCES += $$PWD/widgetbox.qrc
diff --git a/tools/designer/src/components/widgetbox/widgetbox.qrc b/tools/designer/src/components/widgetbox/widgetbox.qrc
new file mode 100644
index 0000000000..7ecf78c85f
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/widgetbox">
+ <file>widgetbox.xml</file>
+ </qresource>
+</RCC>
diff --git a/tools/designer/src/components/widgetbox/widgetbox.xml b/tools/designer/src/components/widgetbox/widgetbox.xml
new file mode 100644
index 0000000000..462ac7d525
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox.xml
@@ -0,0 +1,932 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+**************************************************************************-->
+<widgetbox version="4.2">
+ <category name="Layouts">
+
+ <categoryentry name="Vertical Layout" icon="win/editvlayout.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">verticalLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Layout" icon="win/edithlayout.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">horizontalLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Grid Layout" icon="win/editgrid.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">gridLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Form Layout" icon="win/editform.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="objectName">
+ <string notr="true">formLayoutWidget</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>160</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ </layout>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Spacers">
+
+ <categoryentry name="Horizontal Spacer" icon="widgets/spacer.png">
+ <ui>
+ <widget class="Spacer">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">horizontalSpacer</string>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Spacer" icon="widgets/vspacer.png">
+ <ui>
+ <widget class="Spacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">verticalSpacer</string>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Buttons">
+
+ <categoryentry name="Push Button" icon="widgets/pushbutton.png">
+ <ui>
+ <widget class="QPushButton">
+ <property name="text" >
+ <string>PushButton</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">pushButton</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tool Button" icon="widgets/toolbutton.png">
+ <ui>
+ <widget class="QToolButton">
+ <property name="objectName">
+ <string notr="true">toolButton</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Radio Button" icon="widgets/radiobutton.png">
+ <ui>
+ <widget class="QRadioButton">
+ <property name="text" >
+ <string>RadioButton</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">radioButton</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Check Box" icon="widgets/checkbox.png">
+ <ui>
+ <widget class="QCheckBox">
+ <property name="text" >
+ <string>CheckBox</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">checkBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Command Link Button" icon="widgets/commandlinkbutton.png">
+ <ui>
+ <widget class="QCommandLinkButton">
+ <property name="text" >
+ <string>CommandLinkButton</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">commandLinkButton</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Button Box" icon="widgets/dialogbuttonbox.png">
+ <ui>
+ <widget class="QDialogButtonBox">
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Ok|QDialogButtonBox::Cancel</set>
+ </property>
+ <property name="objectName">
+ <string notr="true">buttonBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Item Views (Model-Based)">
+
+ <categoryentry name="List View" icon="widgets/listbox.png">
+ <ui>
+ <widget class="QListView">
+ <property name="objectName">
+ <string notr="true">listView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tree View" icon="widgets/listview.png">
+ <ui>
+ <widget class="QTreeView">
+ <property name="objectName">
+ <string notr="true">treeView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Table View" icon="widgets/table.png">
+ <ui>
+ <widget class="QTableView">
+ <property name="objectName">
+ <string notr="true">tableView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Column View" icon="widgets/columnview.png">
+ <ui>
+ <widget class="QColumnView">
+ <property name="objectName">
+ <string notr="true">columnView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Item Widgets (Item-Based)">
+ <categoryentry name="List Widget" icon="widgets/listbox.png">
+ <ui>
+ <widget class="QListWidget">
+ <property name="objectName">
+ <string notr="true">listWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tree Widget" icon="widgets/listview.png">
+ <ui>
+ <widget class="QTreeWidget">
+ <property name="objectName">
+ <string notr="true">treeWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Table Widget" icon="widgets/table.png">
+ <ui>
+ <widget class="QTableWidget">
+ <property name="objectName">
+ <string notr="true">tableWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Containers">
+
+ <categoryentry name="Group Box" icon="widgets/groupbox.png">
+ <ui>
+ <widget class="QGroupBox">
+ <property name="title" >
+ <string>GroupBox</string>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">groupBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry icon="widgets/scrollarea.png" type="default" name="Scroll Area">
+ <ui>
+ <widget class="QScrollArea">
+ <property name="objectName" >
+ <string notr="true" >scrollArea</string>
+ </property>
+ <property name="widgetResizable" >
+ <bool>true</bool>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ </widget>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tool Box" icon="widgets/toolbox.png">
+ <ui>
+ <widget class="QToolBox">
+ <property name="currentIndex" >
+ <number>0</number>
+ </property>
+ <property name="objectName">
+ <string notr="true">toolBox</string>
+ </property>
+ <widget class="QWidget" name="page" >
+ <attribute name="label">
+ <string>Page 1</string>
+ </attribute>
+ </widget>
+ <widget class="QWidget" name="page" >
+ <attribute name="label">
+ <string>Page 2</string>
+ </attribute>
+ </widget>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Tab Widget" icon="widgets/tabwidget.png">
+ <ui>
+ <widget class="QTabWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">tabWidget</string>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ </widget>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Tab 2</string>
+ </attribute>
+ </widget>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Stacked Widget" icon="widgets/widgetstack.png">
+ <ui>
+ <widget class="QStackedWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">stackedWidget</string>
+ </property>
+ <widget class="QWidget" name="page" />
+ <widget class="QWidget" name="page" />
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Frame" icon="widgets/frame.png">
+ <ui>
+ <widget class="QFrame">
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">frame</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Widget" icon="widgets/widget.png">
+ <ui>
+ <widget class="QWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">widget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="MdiArea" icon="widgets/mdiarea.png">
+ <ui>
+ <widget class="QMdiArea">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>200</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">mdiArea</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Dock Widget" icon="widgets/dockwidget.png">
+ <ui>
+ <widget class="QDockWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>120</width>
+ <height>80</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dockWidget</string>
+ </property>
+ <widget class="QWidget" name="dockWidgetContents" />
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+ <category name="Input Widgets">
+
+ <categoryentry name="Combo Box" icon="widgets/combobox.png">
+ <ui>
+ <widget class="QComboBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>28</y>
+ <width>41</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">comboBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Font Combo Box" icon="widgets/fontcombobox.png">
+ <ui>
+ <widget class="QFontComboBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>28</y>
+ <width>41</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">fontComboBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Line Edit" icon="widgets/lineedit.png">
+ <ui>
+ <widget class="QLineEdit">
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>1</y>
+ <width>113</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">lineEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Text Edit" icon="widgets/textedit.png">
+ <ui>
+ <widget class="QTextEdit">
+ <property name="objectName">
+ <string notr="true">textEdit</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>104</width>
+ <height>64</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Plain Text Edit" icon="widgets/plaintextedit.png">
+ <ui>
+ <widget class="QPlainTextEdit">
+ <property name="objectName">
+ <string notr="true">plainTextEdit</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>104</width>
+ <height>64</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Spin Box" icon="widgets/spinbox.png">
+ <ui>
+ <widget class="QSpinBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>0</y>
+ <width>42</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">spinBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Double Spin Box" icon="widgets/doublespinbox.png">
+ <ui>
+ <widget class="QDoubleSpinBox">
+ <property name="geometry" >
+ <rect>
+ <x>119</x>
+ <y>0</y>
+ <width>62</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">doubleSpinBox</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Time Edit" icon="widgets/timeedit.png">
+ <ui>
+ <widget class="QTimeEdit">
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>28</y>
+ <width>118</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">timeEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Date Edit" icon="widgets/dateedit.png">
+ <ui>
+ <widget class="QDateEdit">
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>28</y>
+ <width>110</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dateEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Date/Time Edit" icon="widgets/datetimeedit.png">
+ <ui>
+ <widget class="QDateTimeEdit">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>28</y>
+ <width>194</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dateTimeEdit</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Dial" icon="widgets/dial.png">
+ <ui>
+ <widget class="QDial">
+ <property name="geometry" >
+ <rect>
+ <x>110</x>
+ <y>0</y>
+ <width>50</width>
+ <height>64</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">dial</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Scroll Bar" icon="widgets/hscrollbar.png">
+ <ui>
+ <widget class="QScrollBar">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>160</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">horizontalScrollBar</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Scroll Bar" icon="widgets/vscrollbar.png">
+ <ui>
+ <widget class="QScrollBar">
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>16</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">verticalScrollBar</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Slider" icon="widgets/hslider.png">
+ <ui>
+ <widget class="QSlider">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>160</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">horizontalSlider</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Slider" icon="widgets/vslider.png">
+ <ui>
+ <widget class="QSlider">
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>126</y>
+ <width>16</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">verticalSlider</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+
+
+ <category name="Display Widgets">
+
+ <categoryentry name="Label" icon="widgets/label.png">
+ <ui>
+ <widget class="QLabel">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ <property name="objectName">
+ <string notr="true">label</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Text Browser" icon="widgets/textedit.png">
+ <ui>
+ <widget class="QTextBrowser">
+ <property name="objectName">
+ <string notr="true">textBrowser</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Graphics View" icon="widgets/graphicsview.png">
+ <ui>
+ <widget class="QGraphicsView">
+ <property name="objectName">
+ <string notr="true">graphicsView</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Calendar" icon="widgets/calendarwidget.png">
+ <ui>
+ <widget class="QCalendarWidget">
+ <property name="objectName">
+ <string notr="true">calendarWidget</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="LCD Number" icon="widgets/lcdnumber.png">
+ <ui>
+ <widget class="QLCDNumber">
+ <property name="objectName">
+ <string notr="true">lcdNumber</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Progress Bar" icon="widgets/progress.png">
+ <ui>
+ <widget class="QProgressBar">
+ <property name="value" >
+ <number>24</number>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>9</x>
+ <y>38</y>
+ <width>118</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="objectName">
+ <string notr="true">progressBar</string>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Horizontal Line" icon="widgets/line.png">
+ <ui>
+ <widget class="Line">
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">line</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>9</x>
+ <y>67</y>
+ <width>118</width>
+ <height>3</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ <categoryentry name="Vertical Line" icon="widgets/vline.png">
+ <ui>
+ <widget class="Line">
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="objectName">
+ <string notr="true">line</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>133</x>
+ <y>9</y>
+ <width>3</width>
+ <height>61</height>
+ </rect>
+ </property>
+ </widget>
+ </ui>
+ </categoryentry>
+
+ </category>
+</widgetbox>
diff --git a/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp
new file mode 100644
index 0000000000..1dc63a5ea1
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox_dnditem.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetbox_dnditem.h"
+#include "ui4_p.h"
+
+#include <widgetfactory_p.h>
+#include <spacer_widget_p.h>
+#include <qdesigner_formbuilder_p.h>
+#include <qtresourcemodel_p.h>
+#include <formscriptrunner_p.h>
+#include <formwindowbase_p.h>
+#include <qdesigner_utils_p.h>
+#include <qdesigner_dockwidget_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <QtGui/QStyle>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+/*******************************************************************************
+** WidgetBoxResource
+*/
+
+static inline DeviceProfile currentDeviceProfile(const QDesignerFormEditorInterface *core)
+{
+ if (QDesignerFormWindowInterface *cfw = core->formWindowManager()->activeFormWindow())
+ if (const FormWindowBase *fwb = qobject_cast<const FormWindowBase *>(cfw))
+ return fwb->deviceProfile();
+ return DeviceProfile();
+}
+
+class WidgetBoxResource : public QDesignerFormBuilder
+{
+public:
+ WidgetBoxResource(QDesignerFormEditorInterface *core);
+
+ // protected->public
+ QWidget *createUI(DomUI *ui, QWidget *parents) { return QDesignerFormBuilder::create(ui, parents); }
+
+protected:
+
+ virtual QWidget *create(DomWidget *ui_widget, QWidget *parents);
+ virtual QWidget *createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name);
+};
+
+WidgetBoxResource::WidgetBoxResource(QDesignerFormEditorInterface *core) :
+ QDesignerFormBuilder(core, DisableScripts, currentDeviceProfile(core))
+{
+}
+
+
+QWidget *WidgetBoxResource::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name)
+{
+ if (widgetName == QLatin1String("Spacer")) {
+ Spacer *spacer = new Spacer(parentWidget);
+ spacer->setObjectName(name);
+ return spacer;
+ }
+
+ return QDesignerFormBuilder::createWidget(widgetName, parentWidget, name);
+}
+
+QWidget *WidgetBoxResource::create(DomWidget *ui_widget, QWidget *parent)
+{
+ QWidget *result = QDesignerFormBuilder::create(ui_widget, parent);
+ // It is possible to have a syntax error or something in custom
+ // widget XML, so, try to recover here by creating an artificial
+ // top level + widget.
+ if (!result) {
+ const QString msg = QApplication::translate("qdesigner_internal::WidgetBox", "Warning: Widget creation failed in the widget box. This could be caused by invalid custom widget XML.");
+ qdesigner_internal::designerWarning(msg);
+ result = new QWidget(parent);
+ new QWidget(result);
+ }
+ result->setFocusPolicy(Qt::NoFocus);
+ result->setObjectName(ui_widget->attributeName());
+ return result;
+}
+
+/*******************************************************************************
+** WidgetBoxResource
+*/
+
+static QSize geometryProp(const DomWidget *dw)
+{
+ const QList<DomProperty*> prop_list = dw->elementProperty();
+ const QString geometry = QLatin1String("geometry");
+ foreach (DomProperty *prop, prop_list) {
+ if (prop->attributeName() != geometry)
+ continue;
+ DomRect *dr = prop->elementRect();
+ if (dr == 0)
+ continue;
+ return QSize(dr->elementWidth(), dr->elementHeight());
+ }
+ return QSize();
+}
+
+static QSize domWidgetSize(const DomWidget *dw)
+{
+ QSize size = geometryProp(dw);
+ if (size.isValid())
+ return size;
+
+ foreach (const DomWidget *child, dw->elementWidget()) {
+ size = geometryProp(child);
+ if (size.isValid())
+ return size;
+ }
+
+ foreach (const DomLayout *dl, dw->elementLayout()) {
+ foreach (DomLayoutItem *item, dl->elementItem()) {
+ const DomWidget *child = item->elementWidget();
+ if (child == 0)
+ continue;
+ size = geometryProp(child);
+ if (size.isValid())
+ return size;
+ }
+ }
+
+ return QSize();
+}
+
+static QWidget *decorationFromDomWidget(DomUI *dom_ui, QDesignerFormEditorInterface *core)
+{
+ WidgetBoxResource builder(core);
+ // We have the builder create the articial QWidget fake top level as a tooltip
+ // because the size algorithm works better at weird DPI settings
+ // if the actual widget is created as a child of a container
+ QWidget *fakeTopLevel = builder.createUI(dom_ui, static_cast<QWidget*>(0));
+ fakeTopLevel->setParent(0, Qt::ToolTip); // Container
+ // Actual widget
+ const DomWidget *domW = dom_ui->elementWidget()->elementWidget().front();
+ QWidget *w = qFindChildren<QWidget*>(fakeTopLevel).front();
+ Q_ASSERT(w);
+ // hack begin;
+ // We set _q_dockDrag dynamic property which will be detected in drag enter event of form window.
+ // Dock drop is handled in special way (highlight goes to central widget of main window)
+ if (qobject_cast<QDesignerDockWidget *>(w))
+ fakeTopLevel->setProperty("_q_dockDrag", QVariant(true));
+ // hack end;
+ w->setAutoFillBackground(true); // Different style for embedded
+ QSize size = domWidgetSize(domW);
+ const QSize minimumSize = w->minimumSizeHint();
+ if (!size.isValid())
+ size = w->sizeHint();
+ if (size.width() < minimumSize.width())
+ size.setWidth(minimumSize.width());
+ if (size.height() < minimumSize.height())
+ size.setHeight(minimumSize.height());
+ // A QWidget might have size -1,-1 if no geometry property is specified in the widget box.
+ if (size.isEmpty())
+ size = size.expandedTo(QSize(16, 16));
+ w->setGeometry(QRect(QPoint(0, 0), size));
+ fakeTopLevel->resize(size);
+ return fakeTopLevel;
+}
+
+WidgetBoxDnDItem::WidgetBoxDnDItem(QDesignerFormEditorInterface *core,
+ DomUI *dom_ui,
+ const QPoint &global_mouse_pos) :
+ QDesignerDnDItem(CopyDrop)
+{
+ QWidget *decoration = decorationFromDomWidget(dom_ui, core);
+ decoration->move(global_mouse_pos - QPoint(5, 5));
+
+ init(dom_ui, 0, decoration, global_mouse_pos);
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetbox_dnditem.h b/tools/designer/src/components/widgetbox/widgetbox_dnditem.h
new file mode 100644
index 0000000000..0641f6954f
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox_dnditem.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOX_DNDITEM_H
+#define WIDGETBOX_DNDITEM_H
+
+#include <qdesigner_dnditem_p.h>
+#include "widgetbox_global.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class DomUI;
+
+namespace qdesigner_internal {
+
+class QT_WIDGETBOX_EXPORT WidgetBoxDnDItem : public QDesignerDnDItem
+{
+public:
+ WidgetBoxDnDItem(QDesignerFormEditorInterface *core,
+ DomUI *dom_ui,
+ const QPoint &global_mouse_pos);
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOX_DNDITEM_H
diff --git a/tools/designer/src/components/widgetbox/widgetbox_global.h b/tools/designer/src/components/widgetbox/widgetbox_global.h
new file mode 100644
index 0000000000..3e95063cb0
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetbox_global.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOX_GLOBAL_H
+#define WIDGETBOX_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_WIN
+#ifdef QT_WIDGETBOX_LIBRARY
+# define QT_WIDGETBOX_EXPORT
+#else
+# define QT_WIDGETBOX_EXPORT
+#endif
+#else
+#define QT_WIDGETBOX_EXPORT
+#endif
+
+#endif // WIDGETBOX_GLOBAL_H
diff --git a/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp
new file mode 100644
index 0000000000..fad13f201b
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.cpp
@@ -0,0 +1,494 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetboxcategorylistview.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtXml/QDomDocument>
+
+#include <QtGui/QIcon>
+#include <QtGui/QListView>
+#include <QtGui/QLineEdit>
+#include <QtGui/QItemDelegate>
+#include <QtGui/QSortFilterProxyModel>
+
+#include <QtCore/QAbstractListModel>
+#include <QtCore/QList>
+#include <QtCore/QTextStream>
+#include <QtCore/QRegExp>
+
+static const char *widgetElementC = "widget";
+static const char *nameAttributeC = "name";
+static const char *uiOpeningTagC = "<ui>";
+static const char *uiClosingTagC = "</ui>";
+
+QT_BEGIN_NAMESPACE
+
+enum { FilterRole = Qt::UserRole + 11 };
+
+static QString domToString(const QDomElement &elt)
+{
+ QString result;
+ QTextStream stream(&result, QIODevice::WriteOnly);
+ elt.save(stream, 2);
+ stream.flush();
+ return result;
+}
+
+static QDomDocument stringToDom(const QString &xml)
+{
+ QDomDocument result;
+ result.setContent(xml);
+ return result;
+}
+
+namespace qdesigner_internal {
+
+// Entry of the model list
+
+struct WidgetBoxCategoryEntry {
+ WidgetBoxCategoryEntry();
+ explicit WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable);
+
+ QDesignerWidgetBoxInterface::Widget widget;
+ QString toolTip;
+ QString whatsThis;
+ QIcon icon;
+ bool editable;
+};
+
+
+WidgetBoxCategoryEntry::WidgetBoxCategoryEntry() :
+ editable(false)
+{
+}
+
+WidgetBoxCategoryEntry::WidgetBoxCategoryEntry(const QDesignerWidgetBoxInterface::Widget &w, const QIcon &i, bool e) :
+ widget(w),
+ icon(i),
+ editable(e)
+{
+}
+
+/* WidgetBoxCategoryModel, representing a list of category entries. Uses a
+ * QAbstractListModel since the behaviour depends on the view mode of the list
+ * view, it does not return text in the case of IconMode. */
+
+class WidgetBoxCategoryModel : public QAbstractListModel {
+public:
+ explicit WidgetBoxCategoryModel(QDesignerFormEditorInterface *core, QObject *parent = 0);
+
+ // QAbstractListModel
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
+ virtual Qt::ItemFlags flags (const QModelIndex & index ) const;
+ virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+
+ // The model returns no text in icon mode, so, it also needs to know it
+ QListView::ViewMode viewMode() const;
+ void setViewMode(QListView::ViewMode vm);
+
+ void addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable);
+
+ QDesignerWidgetBoxInterface::Widget widgetAt(const QModelIndex & index) const;
+ QDesignerWidgetBoxInterface::Widget widgetAt(int row) const;
+
+ int indexOfWidget(const QString &name);
+
+ QDesignerWidgetBoxInterface::Category category() const;
+ bool removeCustomWidgets();
+
+private:
+ typedef QList<WidgetBoxCategoryEntry> WidgetBoxCategoryEntrys;
+
+ QDesignerFormEditorInterface *m_core;
+ WidgetBoxCategoryEntrys m_items;
+ QListView::ViewMode m_viewMode;
+};
+
+WidgetBoxCategoryModel::WidgetBoxCategoryModel(QDesignerFormEditorInterface *core, QObject *parent) :
+ QAbstractListModel(parent),
+ m_core(core),
+ m_viewMode(QListView::ListMode)
+{
+}
+
+QListView::ViewMode WidgetBoxCategoryModel::viewMode() const
+{
+ return m_viewMode;
+}
+
+void WidgetBoxCategoryModel::setViewMode(QListView::ViewMode vm)
+{
+ if (m_viewMode == vm)
+ return;
+ m_viewMode = vm;
+ if (!m_items.empty())
+ reset();
+}
+
+int WidgetBoxCategoryModel::indexOfWidget(const QString &name)
+{
+ const int count = m_items.size();
+ for (int i = 0; i < count; i++)
+ if (m_items.at(i).widget.name() == name)
+ return i;
+ return -1;
+}
+
+QDesignerWidgetBoxInterface::Category WidgetBoxCategoryModel::category() const
+{
+ QDesignerWidgetBoxInterface::Category rc;
+ const WidgetBoxCategoryEntrys::const_iterator cend = m_items.constEnd();
+ for (WidgetBoxCategoryEntrys::const_iterator it = m_items.constBegin(); it != cend; ++it)
+ rc.addWidget(it->widget);
+ return rc;
+}
+
+bool WidgetBoxCategoryModel::removeCustomWidgets()
+{
+ // Typically, we are a whole category of custom widgets, so, remove all
+ // and do reset.
+ bool changed = false;
+ for (WidgetBoxCategoryEntrys::iterator it = m_items.begin(); it != m_items.end(); )
+ if (it->widget.type() == QDesignerWidgetBoxInterface::Widget::Custom) {
+ it = m_items.erase(it);
+ changed = true;
+ } else {
+ ++it;
+ }
+ if (changed)
+ reset();
+ return changed;
+}
+
+void WidgetBoxCategoryModel::addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon,bool editable)
+{
+ // build item
+ WidgetBoxCategoryEntry item(widget, icon, editable);
+ const QDesignerWidgetDataBaseInterface *db = m_core->widgetDataBase();
+ const int dbIndex = db->indexOfClassName(widget.name());
+ if (dbIndex != -1) {
+ const QDesignerWidgetDataBaseItemInterface *dbItem = db->item(dbIndex);
+ const QString toolTip = dbItem->toolTip();
+ if (!toolTip.isEmpty())
+ item.toolTip = toolTip;
+ const QString whatsThis = dbItem->whatsThis();
+ if (!whatsThis.isEmpty())
+ item.whatsThis = whatsThis;
+ }
+ // insert
+ const int row = m_items.size();
+ beginInsertRows(QModelIndex(), row, row);
+ m_items.push_back(item);
+ endInsertRows();
+}
+
+QVariant WidgetBoxCategoryModel::data(const QModelIndex &index, int role) const
+{
+ const int row = index.row();
+ if (row < 0 || row >= m_items.size())
+ return QVariant();
+
+ const WidgetBoxCategoryEntry &item = m_items.at(row);
+ switch (role) {
+ case Qt::DisplayRole:
+ // No text in icon mode
+ return QVariant(m_viewMode == QListView::ListMode ? item.widget.name() : QString());
+ case Qt::DecorationRole:
+ return QVariant(item.icon);
+ case Qt::EditRole:
+ return QVariant(item.widget.name());
+ case Qt::ToolTipRole: {
+ if (m_viewMode == QListView::ListMode)
+ return QVariant(item.toolTip);
+ // Icon mode tooltip should contain the class name
+ QString tt = item.widget.name();
+ if (!item.toolTip.isEmpty()) {
+ tt += QLatin1Char('\n');
+ tt += item.toolTip;
+ }
+ return QVariant(tt);
+
+ }
+ case Qt::WhatsThisRole:
+ return QVariant(item.whatsThis);
+ case FilterRole:
+ return item.widget.name();
+ }
+ return QVariant();
+}
+
+bool WidgetBoxCategoryModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ const int row = index.row();
+ if (role != Qt::EditRole || row < 0 || row >= m_items.size() || value.type() != QVariant::String)
+ return false;
+ // Set name and adapt Xml
+ WidgetBoxCategoryEntry &item = m_items[row];
+ const QString newName = value.toString();
+ item.widget.setName(newName);
+
+ const QDomDocument doc = stringToDom(WidgetBoxCategoryListView::widgetDomXml(item.widget));
+ QDomElement widget_elt = doc.firstChildElement(QLatin1String(widgetElementC));
+ if (!widget_elt.isNull()) {
+ widget_elt.setAttribute(QLatin1String(nameAttributeC), newName);
+ item.widget.setDomXml(domToString(widget_elt));
+ }
+ emit dataChanged(index, index);
+ return true;
+}
+
+Qt::ItemFlags WidgetBoxCategoryModel::flags(const QModelIndex &index) const
+{
+ Qt::ItemFlags rc = Qt::ItemIsEnabled;
+ const int row = index.row();
+ if (row >= 0 && row < m_items.size())
+ if (m_items.at(row).editable) {
+ rc |= Qt::ItemIsSelectable;
+ // Can change name in list mode only
+ if (m_viewMode == QListView::ListMode)
+ rc |= Qt::ItemIsEditable;
+ }
+ return rc;
+}
+
+int WidgetBoxCategoryModel::rowCount(const QModelIndex & /*parent*/) const
+{
+ return m_items.size();
+}
+
+bool WidgetBoxCategoryModel::removeRows(int row, int count, const QModelIndex & parent)
+{
+ if (row < 0 || count < 1)
+ return false;
+ const int size = m_items.size();
+ const int last = row + count - 1;
+ if (row >= size || last >= size)
+ return false;
+ beginRemoveRows(parent, row, last);
+ for (int r = last; r >= row; r--)
+ m_items.removeAt(r);
+ endRemoveRows();
+ return true;
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryModel::widgetAt(const QModelIndex & index) const
+{
+ return widgetAt(index.row());
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryModel::widgetAt(int row) const
+{
+ if (row < 0 || row >= m_items.size())
+ return QDesignerWidgetBoxInterface::Widget();
+ return m_items.at(row).widget;
+}
+
+/* WidgetSubBoxItemDelegate, ensures a valid name using a regexp validator */
+
+class WidgetBoxCategoryEntryDelegate : public QItemDelegate
+{
+public:
+ explicit WidgetBoxCategoryEntryDelegate(QWidget *parent = 0) : QItemDelegate(parent) {}
+ QWidget *createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+};
+
+QWidget *WidgetBoxCategoryEntryDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QWidget *result = QItemDelegate::createEditor(parent, option, index);
+ if (QLineEdit *line_edit = qobject_cast<QLineEdit*>(result)) {
+ const QRegExp re = QRegExp(QLatin1String("[_a-zA-Z][_a-zA-Z0-9]*"));
+ Q_ASSERT(re.isValid());
+ line_edit->setValidator(new QRegExpValidator(re, line_edit));
+ }
+ return result;
+}
+
+// ---------------------- WidgetBoxCategoryListView
+
+WidgetBoxCategoryListView::WidgetBoxCategoryListView(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QListView(parent),
+ m_proxyModel(new QSortFilterProxyModel(this)),
+ m_model(new WidgetBoxCategoryModel(core, this))
+{
+ setFocusPolicy(Qt::NoFocus);
+ setFrameShape(QFrame::NoFrame);
+ setIconSize(QSize(22, 22));
+ setSpacing(1);
+ setTextElideMode(Qt::ElideMiddle);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setResizeMode(QListView::Adjust);
+ setUniformItemSizes(true);
+
+ setItemDelegate(new WidgetBoxCategoryEntryDelegate(this));
+
+ connect(this, SIGNAL(pressed(QModelIndex)), this, SLOT(slotPressed(QModelIndex)));
+ setEditTriggers(QAbstractItemView::AnyKeyPressed);
+
+ m_proxyModel->setSourceModel(m_model);
+ m_proxyModel->setFilterRole(FilterRole);
+ setModel(m_proxyModel);
+ connect(m_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SIGNAL(scratchPadChanged()));
+}
+
+void WidgetBoxCategoryListView::setViewMode(ViewMode vm)
+{
+ QListView::setViewMode(vm);
+ m_model->setViewMode(vm);
+}
+
+void WidgetBoxCategoryListView::setCurrentItem(AccessMode am, int row)
+{
+ const QModelIndex index = am == FilteredAccess ?
+ m_proxyModel->index(row, 0) :
+ m_proxyModel->mapFromSource(m_model->index(row, 0));
+
+ if (index.isValid())
+ setCurrentIndex(index);
+}
+
+void WidgetBoxCategoryListView::slotPressed(const QModelIndex &index)
+{
+ const QDesignerWidgetBoxInterface::Widget wgt = m_model->widgetAt(m_proxyModel->mapToSource(index));
+ if (wgt.isNull())
+ return;
+ emit pressed(wgt.name(), widgetDomXml(wgt), QCursor::pos());
+}
+
+void WidgetBoxCategoryListView::removeCurrentItem()
+{
+ const QModelIndex index = currentIndex();
+ if (!index.isValid() || !m_proxyModel->removeRow(index.row()))
+ return;
+
+ // We check the unfiltered item count here, we don't want to get removed if the
+ // filtered view is empty
+ if (m_model->rowCount()) {
+ emit itemRemoved();
+ } else {
+ emit lastItemRemoved();
+ }
+}
+
+void WidgetBoxCategoryListView::editCurrentItem()
+{
+ const QModelIndex index = currentIndex();
+ if (index.isValid())
+ edit(index);
+}
+
+int WidgetBoxCategoryListView::count(AccessMode am) const
+{
+ return am == FilteredAccess ? m_proxyModel->rowCount() : m_model->rowCount();
+}
+
+int WidgetBoxCategoryListView::mapRowToSource(int filterRow) const
+{
+ const QModelIndex filterIndex = m_proxyModel->index(filterRow, 0);
+ return m_proxyModel->mapToSource(filterIndex).row();
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryListView::widgetAt(AccessMode am, const QModelIndex & index) const
+{
+ const QModelIndex unfilteredIndex = am == FilteredAccess ? m_proxyModel->mapToSource(index) : index;
+ return m_model->widgetAt(unfilteredIndex);
+}
+
+QDesignerWidgetBoxInterface::Widget WidgetBoxCategoryListView::widgetAt(AccessMode am, int row) const
+{
+ return m_model->widgetAt(am == UnfilteredAccess ? row : mapRowToSource(row));
+}
+
+void WidgetBoxCategoryListView::removeRow(AccessMode am, int row)
+{
+ m_model->removeRow(am == UnfilteredAccess ? row : mapRowToSource(row));
+}
+
+bool WidgetBoxCategoryListView::containsWidget(const QString &name)
+{
+ return m_model->indexOfWidget(name) != -1;
+}
+
+void WidgetBoxCategoryListView::addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable)
+{
+ m_model->addWidget(widget, icon, editable);
+}
+
+QString WidgetBoxCategoryListView::widgetDomXml(const QDesignerWidgetBoxInterface::Widget &widget)
+{
+ QString domXml = widget.domXml();
+
+ if (domXml.isEmpty()) {
+ domXml = QLatin1String(uiOpeningTagC);
+ domXml += QLatin1String("<widget class=\"");
+ domXml += widget.name();
+ domXml += QLatin1String("\"/>");
+ domXml += QLatin1String(uiClosingTagC);
+ }
+ return domXml;
+}
+
+void WidgetBoxCategoryListView::filter(const QRegExp &re)
+{
+ m_proxyModel->setFilterRegExp(re);
+}
+
+QDesignerWidgetBoxInterface::Category WidgetBoxCategoryListView::category() const
+{
+ return m_model->category();
+}
+
+bool WidgetBoxCategoryListView::removeCustomWidgets()
+{
+ return m_model->removeCustomWidgets();
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetboxcategorylistview.h b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.h
new file mode 100644
index 0000000000..c8c5d3a8c8
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxcategorylistview.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOXCATEGORYLISTVIEW_H
+#define WIDGETBOXCATEGORYLISTVIEW_H
+
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+
+#include <QtGui/QListView>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerDnDItemInterface;
+
+class QSortFilterProxyModel;
+class QRegExp;
+
+namespace qdesigner_internal {
+
+class WidgetBoxCategoryModel;
+
+// List view of a category, switchable between icon and list mode.
+// Provides a filtered view.
+class WidgetBoxCategoryListView : public QListView
+{
+ Q_OBJECT
+public:
+ // Whether to access the filtered or unfiltered view
+ enum AccessMode { FilteredAccess, UnfilteredAccess };
+
+ explicit WidgetBoxCategoryListView(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ void setViewMode(ViewMode vm);
+
+ void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list);
+
+ using QListView::contentsSize;
+
+ // These methods operate on the filtered/unfiltered model according to accessmode
+ int count(AccessMode am) const;
+ QDesignerWidgetBoxInterface::Widget widgetAt(AccessMode am, const QModelIndex &index) const;
+ QDesignerWidgetBoxInterface::Widget widgetAt(AccessMode am, int row) const;
+ void removeRow(AccessMode am, int row);
+ void setCurrentItem(AccessMode am, int row);
+
+ // These methods operate on the unfiltered model and are used for serialization
+ void addWidget(const QDesignerWidgetBoxInterface::Widget &widget, const QIcon &icon, bool editable);
+ bool containsWidget(const QString &name);
+ QDesignerWidgetBoxInterface::Category category() const;
+ bool removeCustomWidgets();
+
+ // Helper: Ensure a <ui> tag in the case of empty XML
+ static QString widgetDomXml(const QDesignerWidgetBoxInterface::Widget &widget);
+
+signals:
+ void scratchPadChanged();
+ void pressed(const QString &name, const QString &xml, const QPoint &globalPos);
+ void itemRemoved();
+ void lastItemRemoved();
+
+public slots:
+ void filter(const QRegExp &re);
+
+private slots:
+ void slotPressed(const QModelIndex &index);
+ void removeCurrentItem();
+ void editCurrentItem();
+
+private:
+ int mapRowToSource(int filterRow) const;
+ QSortFilterProxyModel *m_proxyModel;
+ WidgetBoxCategoryModel *m_model;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOXCATEGORYLISTVIEW_H
diff --git a/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp b/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp
new file mode 100644
index 0000000000..799f96fb0a
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp
@@ -0,0 +1,998 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetboxtreewidget.h"
+#include "widgetboxcategorylistview.h"
+
+// shared
+#include <iconloader_p.h>
+#include <sheet_delegate_p.h>
+#include <QtDesigner/private/abstractsettings_p.h>
+#include <ui4_p.h>
+#include <qdesigner_utils_p.h>
+#include <pluginmanager_p.h>
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerDnDItemInterface>
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+#include <QtDesigner/private/abstractsettings_p.h>
+
+#include <QtGui/QHeaderView>
+#include <QtGui/QApplication>
+#include <QtGui/QTreeWidgetItem>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QMenu>
+
+#include <QtCore/QFile>
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+static const char *widgetBoxRootElementC = "widgetbox";
+static const char *widgetElementC = "widget";
+static const char *uiElementC = "ui";
+static const char *categoryElementC = "category";
+static const char *categoryEntryElementC = "categoryentry";
+static const char *nameAttributeC = "name";
+static const char *typeAttributeC = "type";
+static const char *iconAttributeC = "icon";
+static const char *defaultTypeValueC = "default";
+static const char *customValueC = "custom";
+static const char *iconPrefixC = "__qt_icon__";
+static const char *scratchPadValueC = "scratchpad";
+static const char *qtLogoC = "qtlogo.png";
+static const char *invisibleNameC = "[invisible]";
+
+enum TopLevelRole { NORMAL_ITEM, SCRATCHPAD_ITEM, CUSTOM_ITEM };
+
+QT_BEGIN_NAMESPACE
+
+static void setTopLevelRole(TopLevelRole tlr, QTreeWidgetItem *item)
+{
+ item->setData(0, Qt::UserRole, QVariant(tlr));
+}
+
+static TopLevelRole topLevelRole(const QTreeWidgetItem *item)
+{
+ return static_cast<TopLevelRole>(item->data(0, Qt::UserRole).toInt());
+}
+
+namespace qdesigner_internal {
+
+WidgetBoxTreeWidget::WidgetBoxTreeWidget(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QTreeWidget(parent),
+ m_core(core),
+ m_iconMode(false),
+ m_scratchPadDeleteTimer(0)
+{
+ setFocusPolicy(Qt::NoFocus);
+ setIndentation(0);
+ setRootIsDecorated(false);
+ setColumnCount(1);
+ header()->hide();
+ header()->setResizeMode(QHeaderView::Stretch);
+ setTextElideMode(Qt::ElideMiddle);
+ setVerticalScrollMode(ScrollPerPixel);
+
+ setItemDelegate(new SheetDelegate(this, this));
+
+ connect(this, SIGNAL(itemPressed(QTreeWidgetItem*,int)),
+ this, SLOT(handleMousePress(QTreeWidgetItem*)));
+}
+
+QIcon WidgetBoxTreeWidget::iconForWidget(QString iconName) const
+{
+ if (iconName.isEmpty())
+ iconName = QLatin1String(qtLogoC);
+
+ if (iconName.startsWith(QLatin1String(iconPrefixC))) {
+ const IconCache::const_iterator it = m_pluginIcons.constFind(iconName);
+ if (it != m_pluginIcons.constEnd())
+ return it.value();
+ }
+ return createIconSet(iconName);
+}
+
+WidgetBoxCategoryListView *WidgetBoxTreeWidget::categoryViewAt(int idx) const
+{
+ WidgetBoxCategoryListView *rc = 0;
+ if (QTreeWidgetItem *cat_item = topLevelItem(idx))
+ if (QTreeWidgetItem *embedItem = cat_item->child(0))
+ rc = qobject_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0));
+ Q_ASSERT(rc);
+ return rc;
+}
+
+void WidgetBoxTreeWidget::saveExpandedState() const
+{
+ QStringList closedCategories;
+ if (const int numCategories = categoryCount()) {
+ for (int i = 0; i < numCategories; ++i) {
+ const QTreeWidgetItem *cat_item = topLevelItem(i);
+ if (!isItemExpanded(cat_item))
+ closedCategories.append(cat_item->text(0));
+ }
+ }
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(widgetBoxRootElementC));
+ settings->setValue(QLatin1String("Closed categories"), closedCategories);
+ settings->setValue(QLatin1String("View mode"), m_iconMode);
+ settings->endGroup();
+}
+
+void WidgetBoxTreeWidget::restoreExpandedState()
+{
+ typedef QSet<QString> StringSet;
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ m_iconMode = settings->value(QLatin1String("WidgetBox/View mode")).toBool();
+ updateViewMode();
+ const StringSet closedCategories = settings->value(QLatin1String("WidgetBox/Closed categories"), QStringList()).toStringList().toSet();
+ expandAll();
+ if (closedCategories.empty())
+ return;
+
+ if (const int numCategories = categoryCount()) {
+ for (int i = 0; i < numCategories; ++i) {
+ QTreeWidgetItem *item = topLevelItem(i);
+ if (closedCategories.contains(item->text(0)))
+ item->setExpanded(false);
+ }
+ }
+}
+
+WidgetBoxTreeWidget::~WidgetBoxTreeWidget()
+{
+ saveExpandedState();
+}
+
+void WidgetBoxTreeWidget::setFileName(const QString &file_name)
+{
+ m_file_name = file_name;
+}
+
+QString WidgetBoxTreeWidget::fileName() const
+{
+ return m_file_name;
+}
+
+bool WidgetBoxTreeWidget::save()
+{
+ if (fileName().isEmpty())
+ return false;
+
+ QFile file(fileName());
+ if (!file.open(QIODevice::WriteOnly))
+ return false;
+
+ CategoryList cat_list;
+ const int count = categoryCount();
+ for (int i = 0; i < count; ++i)
+ cat_list.append(category(i));
+
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ writeCategories(writer, cat_list);
+ writer.writeEndDocument();
+
+ return true;
+}
+
+void WidgetBoxTreeWidget::slotSave()
+{
+ save();
+}
+
+void WidgetBoxTreeWidget::handleMousePress(QTreeWidgetItem *item)
+{
+ if (item == 0)
+ return;
+
+ if (QApplication::mouseButtons() != Qt::LeftButton)
+ return;
+
+ if (item->parent() == 0) {
+ setItemExpanded(item, !isItemExpanded(item));
+ return;
+ }
+}
+
+int WidgetBoxTreeWidget::ensureScratchpad()
+{
+ const int existingIndex = indexOfScratchpad();
+ if (existingIndex != -1)
+ return existingIndex;
+
+ QTreeWidgetItem *scratch_item = new QTreeWidgetItem(this);
+ scratch_item->setText(0, tr("Scratchpad"));
+ setTopLevelRole(SCRATCHPAD_ITEM, scratch_item);
+ addCategoryView(scratch_item, false); // Scratchpad in list mode.
+ return categoryCount() - 1;
+}
+
+WidgetBoxCategoryListView *WidgetBoxTreeWidget::addCategoryView(QTreeWidgetItem *parent, bool iconMode)
+{
+ QTreeWidgetItem *embed_item = new QTreeWidgetItem(parent);
+ embed_item->setFlags(Qt::ItemIsEnabled);
+ WidgetBoxCategoryListView *categoryView = new WidgetBoxCategoryListView(m_core, this);
+ categoryView->setViewMode(iconMode ? QListView::IconMode : QListView::ListMode);
+ connect(categoryView, SIGNAL(scratchPadChanged()), this, SLOT(slotSave()));
+ connect(categoryView, SIGNAL(pressed(QString,QString,QPoint)), this, SIGNAL(pressed(QString,QString,QPoint)));
+ connect(categoryView, SIGNAL(itemRemoved()), this, SLOT(slotScratchPadItemDeleted()));
+ connect(categoryView, SIGNAL(lastItemRemoved()), this, SLOT(slotLastScratchPadItemDeleted()));
+ setItemWidget(embed_item, 0, categoryView);
+ return categoryView;
+}
+
+int WidgetBoxTreeWidget::indexOfScratchpad() const
+{
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int i = numTopLevels - 1; i >= 0; --i) {
+ if (topLevelRole(topLevelItem(i)) == SCRATCHPAD_ITEM)
+ return i;
+ }
+ }
+ return -1;
+}
+
+int WidgetBoxTreeWidget::indexOfCategory(const QString &name) const
+{
+ const int topLevelCount = topLevelItemCount();
+ for (int i = 0; i < topLevelCount; ++i) {
+ if (topLevelItem(i)->text(0) == name)
+ return i;
+ }
+ return -1;
+}
+
+bool WidgetBoxTreeWidget::load(QDesignerWidgetBox::LoadMode loadMode)
+{
+ switch (loadMode) {
+ case QDesignerWidgetBox::LoadReplace:
+ clear();
+ break;
+ case QDesignerWidgetBox::LoadCustomWidgetsOnly:
+ addCustomCategories(true);
+ updateGeometries();
+ return true;
+ default:
+ break;
+ }
+
+ const QString name = fileName();
+
+ QFile f(name);
+ if (!f.open(QIODevice::ReadOnly)) // Might not exist at first startup
+ return false;
+
+ const QString contents = QString::fromUtf8(f.readAll());
+ return loadContents(contents);
+}
+
+bool WidgetBoxTreeWidget::loadContents(const QString &contents)
+{
+ QString errorMessage;
+ CategoryList cat_list;
+ if (!readCategories(m_file_name, contents, &cat_list, &errorMessage)) {
+ qdesigner_internal::designerWarning(errorMessage);
+ return false;
+ }
+
+ foreach(const Category &cat, cat_list)
+ addCategory(cat);
+
+ addCustomCategories(false);
+ // Restore which items are expanded
+ restoreExpandedState();
+ return true;
+}
+
+void WidgetBoxTreeWidget::addCustomCategories(bool replace)
+{
+ if (replace) {
+ // clear out all existing custom widgets
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int t = 0; t < numTopLevels ; ++t)
+ categoryViewAt(t)->removeCustomWidgets();
+ }
+ }
+ // re-add
+ const CategoryList customList = loadCustomCategoryList();
+ const CategoryList::const_iterator cend = customList.constEnd();
+ for (CategoryList::const_iterator it = customList.constBegin(); it != cend; ++it)
+ addCategory(*it);
+}
+
+static inline QString msgXmlError(const QString &fileName, const QXmlStreamReader &r)
+{
+ return QDesignerWidgetBox::tr("An error has been encountered at line %1 of %2: %3")
+ .arg(r.lineNumber()).arg(fileName, r.errorString());
+}
+
+bool WidgetBoxTreeWidget::readCategories(const QString &fileName, const QString &contents,
+ CategoryList *cats, QString *errorMessage)
+{
+ // Read widget box XML:
+ //
+ //<widgetbox version="4.5">
+ // <category name="Layouts">
+ // <categoryentry name="Vertical Layout" icon="win/editvlayout.png" type="default">
+ // <widget class="QListWidget" ...>
+ // ...
+
+ QXmlStreamReader reader(contents);
+
+
+ // Entries of category with name="invisible" should be ignored
+ bool ignoreEntries = false;
+
+ while (!reader.atEnd()) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement: {
+ const QStringRef tag = reader.name();
+ if (tag == QLatin1String(widgetBoxRootElementC)) {
+ //<widgetbox version="4.5">
+ continue;
+ }
+ if (tag == QLatin1String(categoryElementC)) {
+ // <category name="Layouts">
+ const QXmlStreamAttributes attributes = reader.attributes();
+ const QString categoryName = attributes.value(QLatin1String(nameAttributeC)).toString();
+ if (categoryName == QLatin1String(invisibleNameC)) {
+ ignoreEntries = true;
+ } else {
+ Category category(categoryName);
+ if (attributes.value(QLatin1String(typeAttributeC)) == QLatin1String(scratchPadValueC))
+ category.setType(Category::Scratchpad);
+ cats->push_back(category);
+ }
+ continue;
+ }
+ if (tag == QLatin1String(categoryEntryElementC)) {
+ // <categoryentry name="Vertical Layout" icon="win/editvlayout.png" type="default">
+ if (!ignoreEntries) {
+ QXmlStreamAttributes attr = reader.attributes();
+ const QString widgetName = attr.value(QLatin1String(nameAttributeC)).toString();
+ const QString widgetIcon = attr.value(QLatin1String(iconAttributeC)).toString();
+ const WidgetBoxTreeWidget::Widget::Type widgetType =
+ attr.value(QLatin1String(typeAttributeC)).toString()
+ == QLatin1String(customValueC) ?
+ WidgetBoxTreeWidget::Widget::Custom :
+ WidgetBoxTreeWidget::Widget::Default;
+
+ Widget w;
+ w.setName(widgetName);
+ w.setIconName(widgetIcon);
+ w.setType(widgetType);
+ if (!readWidget(&w, contents, reader))
+ continue;
+
+ cats->back().addWidget(w);
+ } // ignoreEntries
+ continue;
+ }
+ break;
+ }
+ case QXmlStreamReader::EndElement: {
+ const QStringRef tag = reader.name();
+ if (tag == QLatin1String(widgetBoxRootElementC)) {
+ continue;
+ }
+ if (tag == QLatin1String(categoryElementC)) {
+ ignoreEntries = false;
+ continue;
+ }
+ if (tag == QLatin1String(categoryEntryElementC)) {
+ continue;
+ }
+ break;
+ }
+ default: break;
+ }
+ }
+
+ if (reader.hasError()) {
+ *errorMessage = msgXmlError(fileName, reader);
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ * Read out a widget within a category. This can either be
+ * enclosed in a <ui> element or a (legacy) <widget> element which may
+ * contain nested <widget> elements.
+ *
+ * Examples:
+ *
+ * <ui language="c++">
+ * <widget class="MultiPageWidget" name="multipagewidget"> ... </widget>
+ * <customwidgets>...</customwidgets>
+ * <ui>
+ *
+ * or
+ *
+ * <widget>
+ * <widget> ... </widget>
+ * ...
+ * <widget>
+ *
+ * Returns true on success, false if end was reached or an error has been encountered
+ * in which case the reader has its error flag set. If successful, the current item
+ * of the reader will be the closing element (</ui> or </widget>)
+ */
+bool WidgetBoxTreeWidget::readWidget(Widget *w, const QString &xml, QXmlStreamReader &r)
+{
+ qint64 startTagPosition =0, endTagPosition = 0;
+
+ int nesting = 0;
+ bool endEncountered = false;
+ bool parsedWidgetTag = false;
+ QString outmostElement;
+ while (!endEncountered) {
+ const qint64 currentPosition = r.characterOffset();
+ switch(r.readNext()) {
+ case QXmlStreamReader::StartElement:
+ if (nesting++ == 0) {
+ // First element must be <ui> or (legacy) <widget>
+ const QStringRef name = r.name();
+ if (name == QLatin1String(uiElementC)) {
+ startTagPosition = currentPosition;
+ } else {
+ if (name == QLatin1String(widgetElementC)) {
+ startTagPosition = currentPosition;
+ parsedWidgetTag = true;
+ } else {
+ r.raiseError(QDesignerWidgetBox::tr("Unexpected element <%1> encountered when parsing for <widget> or <ui>").arg(name.toString()));
+ return false;
+ }
+ }
+ } else {
+ // We are within <ui> looking for the first <widget> tag
+ if (!parsedWidgetTag && r.name() == QLatin1String(widgetElementC)) {
+ parsedWidgetTag = true;
+ }
+ }
+ break;
+ case QXmlStreamReader::EndElement:
+ // Reached end of widget?
+ if (--nesting == 0) {
+ endTagPosition = r.characterOffset();
+ endEncountered = true;
+ }
+ break;
+ case QXmlStreamReader::EndDocument:
+ r.raiseError(QDesignerWidgetBox::tr("Unexpected end of file encountered when parsing widgets."));
+ return false;
+ case QXmlStreamReader::Invalid:
+ return false;
+ default:
+ break;
+ }
+ }
+ if (!parsedWidgetTag) {
+ r.raiseError(QDesignerWidgetBox::tr("A widget element could not be found."));
+ return false;
+ }
+ // Oddity: Startposition is 1 off
+ QString widgetXml = xml.mid(startTagPosition, endTagPosition - startTagPosition);
+ const QChar lessThan = QLatin1Char('<');
+ if (!widgetXml.startsWith(lessThan))
+ widgetXml.prepend(lessThan);
+ w->setDomXml(widgetXml);
+ return true;
+}
+
+void WidgetBoxTreeWidget::writeCategories(QXmlStreamWriter &writer, const CategoryList &cat_list) const
+{
+ const QString widgetbox = QLatin1String(widgetBoxRootElementC);
+ const QString name = QLatin1String(nameAttributeC);
+ const QString type = QLatin1String(typeAttributeC);
+ const QString icon = QLatin1String(iconAttributeC);
+ const QString defaultType = QLatin1String(defaultTypeValueC);
+ const QString category = QLatin1String(categoryElementC);
+ const QString categoryEntry = QLatin1String(categoryEntryElementC);
+ const QString iconPrefix = QLatin1String(iconPrefixC);
+ const QString widgetTag = QLatin1String(widgetElementC);
+
+ //
+ // <widgetbox>
+ // <category name="Layouts">
+ // <categoryEntry name="Vertical Layout" type="default" icon="win/editvlayout.png">
+ // <ui>
+ // ...
+ // </ui>
+ // </categoryEntry>
+ // ...
+ // </category>
+ // ...
+ // </widgetbox>
+ //
+
+ writer.writeStartElement(widgetbox);
+
+ foreach (const Category &cat, cat_list) {
+ writer.writeStartElement(category);
+ writer.writeAttribute(name, cat.name());
+ if (cat.type() == Category::Scratchpad)
+ writer.writeAttribute(type, QLatin1String(scratchPadValueC));
+
+ const int widgetCount = cat.widgetCount();
+ for (int i = 0; i < widgetCount; ++i) {
+ const Widget wgt = cat.widget(i);
+ if (wgt.type() == Widget::Custom)
+ continue;
+
+ writer.writeStartElement(categoryEntry);
+ writer.writeAttribute(name, wgt.name());
+ if (!wgt.iconName().startsWith(iconPrefix))
+ writer.writeAttribute(icon, wgt.iconName());
+ writer.writeAttribute(type, defaultType);
+
+ const DomUI *domUI = QDesignerWidgetBox::xmlToUi(wgt.name(), WidgetBoxCategoryListView::widgetDomXml(wgt), false);
+ if (domUI) {
+ domUI->write(writer);
+ delete domUI;
+ }
+
+ writer.writeEndElement(); // categoryEntry
+ }
+ writer.writeEndElement(); // categoryEntry
+ }
+
+ writer.writeEndElement(); // widgetBox
+}
+
+static int findCategory(const QString &name, const WidgetBoxTreeWidget::CategoryList &list)
+{
+ int idx = 0;
+ foreach (const WidgetBoxTreeWidget::Category &cat, list) {
+ if (cat.name() == name)
+ return idx;
+ ++idx;
+ }
+ return -1;
+}
+
+static inline bool isValidIcon(const QIcon &icon)
+{
+ if (!icon.isNull()) {
+ const QList<QSize> availableSizes = icon.availableSizes();
+ if (!availableSizes.empty())
+ return !availableSizes.front().isEmpty();
+ }
+ return false;
+}
+
+WidgetBoxTreeWidget::CategoryList WidgetBoxTreeWidget::loadCustomCategoryList() const
+{
+ CategoryList result;
+
+ const QDesignerPluginManager *pm = m_core->pluginManager();
+ const QDesignerPluginManager::CustomWidgetList customWidgets = pm->registeredCustomWidgets();
+ if (customWidgets.empty())
+ return result;
+
+ static const QString customCatName = tr("Custom Widgets");
+
+ const QString invisible = QLatin1String(invisibleNameC);
+ const QString iconPrefix = QLatin1String(iconPrefixC);
+
+ foreach(QDesignerCustomWidgetInterface *c, customWidgets) {
+ const QString dom_xml = c->domXml();
+ if (dom_xml.isEmpty())
+ continue;
+
+ const QString pluginName = c->name();
+ const QDesignerCustomWidgetData data = pm->customWidgetData(c);
+ QString displayName = data.xmlDisplayName();
+ if (displayName.isEmpty())
+ displayName = pluginName;
+
+ QString cat_name = c->group();
+ if (cat_name.isEmpty())
+ cat_name = customCatName;
+ else if (cat_name == invisible)
+ continue;
+
+ int idx = findCategory(cat_name, result);
+ if (idx == -1) {
+ result.append(Category(cat_name));
+ idx = result.size() - 1;
+ }
+ Category &cat = result[idx];
+
+ const QIcon icon = c->icon();
+
+ QString icon_name;
+ if (isValidIcon(icon)) {
+ icon_name = iconPrefix;
+ icon_name += pluginName;
+ m_pluginIcons.insert(icon_name, icon);
+ } else {
+ icon_name = QLatin1String(qtLogoC);
+ }
+
+ cat.addWidget(Widget(displayName, dom_xml, icon_name, Widget::Custom));
+ }
+
+ return result;
+}
+
+void WidgetBoxTreeWidget::adjustSubListSize(QTreeWidgetItem *cat_item)
+{
+ QTreeWidgetItem *embedItem = cat_item->child(0);
+ WidgetBoxCategoryListView *list_widget = static_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0));
+ list_widget->setFixedWidth(header()->width());
+ list_widget->doItemsLayout();
+ const int height = qMax(list_widget->contentsSize().height() ,1);
+ list_widget->setFixedHeight(height);
+ embedItem->setSizeHint(0, QSize(-1, height - 1));
+}
+
+int WidgetBoxTreeWidget::categoryCount() const
+{
+ return topLevelItemCount();
+}
+
+WidgetBoxTreeWidget::Category WidgetBoxTreeWidget::category(int cat_idx) const
+{
+ if (cat_idx >= topLevelItemCount())
+ return Category();
+
+ QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
+
+ QTreeWidgetItem *embedItem = cat_item->child(0);
+ WidgetBoxCategoryListView *categoryView = static_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0));
+
+ Category result = categoryView->category();
+ result.setName(cat_item->text(0));
+
+ switch (topLevelRole(cat_item)) {
+ case SCRATCHPAD_ITEM:
+ result.setType(Category::Scratchpad);
+ break;
+ default:
+ result.setType(Category::Default);
+ break;
+ }
+ return result;
+}
+
+void WidgetBoxTreeWidget::addCategory(const Category &cat)
+{
+ if (cat.widgetCount() == 0)
+ return;
+
+ const bool isScratchPad = cat.type() == Category::Scratchpad;
+ WidgetBoxCategoryListView *categoryView;
+ QTreeWidgetItem *cat_item;
+
+ if (isScratchPad) {
+ const int idx = ensureScratchpad();
+ categoryView = categoryViewAt(idx);
+ cat_item = topLevelItem(idx);
+ } else {
+ const int existingIndex = indexOfCategory(cat.name());
+ if (existingIndex == -1) {
+ cat_item = new QTreeWidgetItem();
+ cat_item->setText(0, cat.name());
+ setTopLevelRole(NORMAL_ITEM, cat_item);
+ // insert before scratchpad
+ const int scratchPadIndex = indexOfScratchpad();
+ if (scratchPadIndex == -1) {
+ addTopLevelItem(cat_item);
+ } else {
+ insertTopLevelItem(scratchPadIndex, cat_item);
+ }
+ setItemExpanded(cat_item, true);
+ categoryView = addCategoryView(cat_item, m_iconMode);
+ } else {
+ categoryView = categoryViewAt(existingIndex);
+ cat_item = topLevelItem(existingIndex);
+ }
+ }
+ // The same categories are read from the file $HOME, avoid duplicates
+ const int widgetCount = cat.widgetCount();
+ for (int i = 0; i < widgetCount; ++i) {
+ const Widget w = cat.widget(i);
+ if (!categoryView->containsWidget(w.name()))
+ categoryView->addWidget(w, iconForWidget(w.iconName()), isScratchPad);
+ }
+ adjustSubListSize(cat_item);
+}
+
+void WidgetBoxTreeWidget::removeCategory(int cat_idx)
+{
+ if (cat_idx >= topLevelItemCount())
+ return;
+ delete takeTopLevelItem(cat_idx);
+}
+
+int WidgetBoxTreeWidget::widgetCount(int cat_idx) const
+{
+ if (cat_idx >= topLevelItemCount())
+ return 0;
+ // SDK functions want unfiltered access
+ return categoryViewAt(cat_idx)->count(WidgetBoxCategoryListView::UnfilteredAccess);
+}
+
+WidgetBoxTreeWidget::Widget WidgetBoxTreeWidget::widget(int cat_idx, int wgt_idx) const
+{
+ if (cat_idx >= topLevelItemCount())
+ return Widget();
+ // SDK functions want unfiltered access
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(cat_idx);
+ return categoryView->widgetAt(WidgetBoxCategoryListView::UnfilteredAccess, wgt_idx);
+}
+
+void WidgetBoxTreeWidget::addWidget(int cat_idx, const Widget &wgt)
+{
+ if (cat_idx >= topLevelItemCount())
+ return;
+
+ QTreeWidgetItem *cat_item = topLevelItem(cat_idx);
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(cat_idx);
+
+ const bool scratch = topLevelRole(cat_item) == SCRATCHPAD_ITEM;
+ categoryView->addWidget(wgt, iconForWidget(wgt.iconName()), scratch);
+ adjustSubListSize(cat_item);
+}
+
+void WidgetBoxTreeWidget::removeWidget(int cat_idx, int wgt_idx)
+{
+ if (cat_idx >= topLevelItemCount())
+ return;
+
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(cat_idx);
+
+ // SDK functions want unfiltered access
+ const WidgetBoxCategoryListView::AccessMode am = WidgetBoxCategoryListView::UnfilteredAccess;
+ if (wgt_idx >= categoryView->count(am))
+ return;
+
+ categoryView->removeRow(am, wgt_idx);
+}
+
+void WidgetBoxTreeWidget::slotScratchPadItemDeleted()
+{
+ const int scratch_idx = indexOfScratchpad();
+ QTreeWidgetItem *scratch_item = topLevelItem(scratch_idx);
+ adjustSubListSize(scratch_item);
+ save();
+}
+
+void WidgetBoxTreeWidget::slotLastScratchPadItemDeleted()
+{
+ // Remove the scratchpad in the next idle loop
+ if (!m_scratchPadDeleteTimer) {
+ m_scratchPadDeleteTimer = new QTimer(this);
+ m_scratchPadDeleteTimer->setSingleShot(true);
+ m_scratchPadDeleteTimer->setInterval(0);
+ connect(m_scratchPadDeleteTimer, SIGNAL(timeout()), this, SLOT(deleteScratchpad()));
+ }
+ if (!m_scratchPadDeleteTimer->isActive())
+ m_scratchPadDeleteTimer->start();
+}
+
+void WidgetBoxTreeWidget::deleteScratchpad()
+{
+ const int idx = indexOfScratchpad();
+ if (idx == -1)
+ return;
+ delete takeTopLevelItem(idx);
+ save();
+}
+
+
+void WidgetBoxTreeWidget::slotListMode()
+{
+ m_iconMode = false;
+ updateViewMode();
+}
+
+void WidgetBoxTreeWidget::slotIconMode()
+{
+ m_iconMode = true;
+ updateViewMode();
+}
+
+void WidgetBoxTreeWidget::updateViewMode()
+{
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int i = numTopLevels - 1; i >= 0; --i) {
+ QTreeWidgetItem *topLevel = topLevelItem(i);
+ // Scratch pad stays in list mode.
+ const QListView::ViewMode viewMode = m_iconMode && (topLevelRole(topLevel) != SCRATCHPAD_ITEM) ? QListView::IconMode : QListView::ListMode;
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(i);
+ if (viewMode != categoryView->viewMode()) {
+ categoryView->setViewMode(viewMode);
+ adjustSubListSize(topLevelItem(i));
+ }
+ }
+ }
+
+ updateGeometries();
+}
+
+void WidgetBoxTreeWidget::resizeEvent(QResizeEvent *e)
+{
+ QTreeWidget::resizeEvent(e);
+ if (const int numTopLevels = topLevelItemCount()) {
+ for (int i = numTopLevels - 1; i >= 0; --i)
+ adjustSubListSize(topLevelItem(i));
+ }
+}
+
+void WidgetBoxTreeWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ QTreeWidgetItem *item = itemAt(e->pos());
+
+ const bool scratchpad_menu = item != 0
+ && item->parent() != 0
+ && topLevelRole(item->parent()) == SCRATCHPAD_ITEM;
+
+ QMenu menu;
+ menu.addAction(tr("Expand all"), this, SLOT(expandAll()));
+ menu.addAction(tr("Collapse all"), this, SLOT(collapseAll()));
+ menu.addSeparator();
+
+ QAction *listModeAction = menu.addAction(tr("List View"));
+ QAction *iconModeAction = menu.addAction(tr("Icon View"));
+ listModeAction->setCheckable(true);
+ iconModeAction->setCheckable(true);
+ QActionGroup *viewModeGroup = new QActionGroup(&menu);
+ viewModeGroup->addAction(listModeAction);
+ viewModeGroup->addAction(iconModeAction);
+ if (m_iconMode)
+ iconModeAction->setChecked(true);
+ else
+ listModeAction->setChecked(true);
+ connect(listModeAction, SIGNAL(triggered()), SLOT(slotListMode()));
+ connect(iconModeAction, SIGNAL(triggered()), SLOT(slotIconMode()));
+
+ if (scratchpad_menu) {
+ menu.addSeparator();
+ menu.addAction(tr("Remove"), itemWidget(item, 0), SLOT(removeCurrentItem()));
+ if (!m_iconMode)
+ menu.addAction(tr("Edit name"), itemWidget(item, 0), SLOT(editCurrentItem()));
+ }
+ e->accept();
+ menu.exec(mapToGlobal(e->pos()));
+}
+
+void WidgetBoxTreeWidget::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list)
+{
+ QTreeWidgetItem *scratch_item = 0;
+ WidgetBoxCategoryListView *categoryView = 0;
+ bool added = false;
+
+ foreach (QDesignerDnDItemInterface *item, item_list) {
+ QWidget *w = item->widget();
+ if (w == 0)
+ continue;
+
+ DomUI *dom_ui = item->domUi();
+ if (dom_ui == 0)
+ continue;
+
+ const int scratch_idx = ensureScratchpad();
+ scratch_item = topLevelItem(scratch_idx);
+ categoryView = categoryViewAt(scratch_idx);
+
+ // Temporarily remove the fake toplevel in-between
+ DomWidget *fakeTopLevel = dom_ui->takeElementWidget();
+ DomWidget *firstWidget = 0;
+ if (fakeTopLevel && !fakeTopLevel->elementWidget().isEmpty()) {
+ firstWidget = fakeTopLevel->elementWidget().first();
+ dom_ui->setElementWidget(firstWidget);
+ } else {
+ dom_ui->setElementWidget(fakeTopLevel);
+ continue;
+ }
+
+ // Serialize to XML
+ QString xml;
+ {
+ QXmlStreamWriter writer(&xml);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ dom_ui->write(writer);
+ writer.writeEndDocument();
+ }
+
+ // Insert fake toplevel again
+ dom_ui->takeElementWidget();
+ dom_ui->setElementWidget(fakeTopLevel);
+
+ const Widget wgt = Widget(w->objectName(), xml);
+ categoryView->addWidget(wgt, iconForWidget(wgt.iconName()), true);
+ setItemExpanded(scratch_item, true);
+ added = true;
+ }
+
+ if (added) {
+ save();
+ QApplication::setActiveWindow(this);
+ // Is the new item visible in filtered mode?
+ const WidgetBoxCategoryListView::AccessMode am = WidgetBoxCategoryListView::FilteredAccess;
+ if (const int count = categoryView->count(am))
+ categoryView->setCurrentItem(am, count - 1);
+ categoryView->adjustSize(); // XXX
+ adjustSubListSize(scratch_item);
+ }
+}
+
+void WidgetBoxTreeWidget::filter(const QString &f)
+{
+ const bool empty = f.isEmpty();
+ const QRegExp re = empty ? QRegExp() : QRegExp(f, Qt::CaseInsensitive, QRegExp::FixedString);
+ const int numTopLevels = topLevelItemCount();
+ bool changed = false;
+ for (int i = 0; i < numTopLevels; i++) {
+ QTreeWidgetItem *tl = topLevelItem(i);
+ WidgetBoxCategoryListView *categoryView = categoryViewAt(i);
+ // Anything changed? -> Enable the category
+ const int oldCount = categoryView->count(WidgetBoxCategoryListView::FilteredAccess);
+ categoryView->filter(re);
+ const int newCount = categoryView->count(WidgetBoxCategoryListView::FilteredAccess);
+ if (oldCount != newCount) {
+ changed = true;
+ const bool categoryEnabled = newCount > 0 || empty;
+ if (categoryEnabled) {
+ categoryView->adjustSize();
+ adjustSubListSize(tl);
+ }
+ setRowHidden (i, QModelIndex(), !categoryEnabled);
+ }
+ }
+ if (changed)
+ updateGeometries();
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/components/widgetbox/widgetboxtreewidget.h b/tools/designer/src/components/widgetbox/widgetboxtreewidget.h
new file mode 100644
index 0000000000..9282a0fd4e
--- /dev/null
+++ b/tools/designer/src/components/widgetbox/widgetboxtreewidget.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WIDGETBOXTREEWIDGET_H
+#define WIDGETBOXTREEWIDGET_H
+
+#include <qdesigner_widgetbox_p.h>
+
+#include <QtGui/QTreeWidget>
+#include <QtGui/QIcon>
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QXmlStreamReader> // Cannot forward declare them on Mac
+#include <QtCore/QXmlStreamWriter>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerDnDItemInterface;
+
+class QTimer;
+
+namespace qdesigner_internal {
+
+class WidgetBoxCategoryListView;
+
+// WidgetBoxTreeWidget: A tree of categories
+
+class WidgetBoxTreeWidget : public QTreeWidget
+{
+ Q_OBJECT
+
+public:
+ typedef QDesignerWidgetBoxInterface::Widget Widget;
+ typedef QDesignerWidgetBoxInterface::Category Category;
+ typedef QDesignerWidgetBoxInterface::CategoryList CategoryList;
+
+ explicit WidgetBoxTreeWidget(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ ~WidgetBoxTreeWidget();
+
+ int categoryCount() const;
+ Category category(int cat_idx) const;
+ void addCategory(const Category &cat);
+ void removeCategory(int cat_idx);
+
+ int widgetCount(int cat_idx) const;
+ Widget widget(int cat_idx, int wgt_idx) const;
+ void addWidget(int cat_idx, const Widget &wgt);
+ void removeWidget(int cat_idx, int wgt_idx);
+
+ void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list);
+
+ void setFileName(const QString &file_name);
+ QString fileName() const;
+ bool load(QDesignerWidgetBox::LoadMode loadMode);
+ bool loadContents(const QString &contents);
+ bool save();
+ QIcon iconForWidget(QString iconName) const;
+
+signals:
+ void pressed(const QString name, const QString dom_xml, const QPoint &global_mouse_pos);
+
+public slots:
+ void filter(const QString &);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *e);
+ void resizeEvent(QResizeEvent *e);
+
+private slots:
+ void slotSave();
+ void slotScratchPadItemDeleted();
+ void slotLastScratchPadItemDeleted();
+
+ void handleMousePress(QTreeWidgetItem *item);
+ void deleteScratchpad();
+ void slotListMode();
+ void slotIconMode();
+
+private:
+ WidgetBoxCategoryListView *addCategoryView(QTreeWidgetItem *parent, bool iconMode);
+ WidgetBoxCategoryListView *categoryViewAt(int idx) const;
+ void adjustSubListSize(QTreeWidgetItem *cat_item);
+
+ static bool readCategories(const QString &fileName, const QString &xml, CategoryList *cats, QString *errorMessage);
+ static bool readWidget(Widget *w, const QString &xml, QXmlStreamReader &r);
+
+ CategoryList loadCustomCategoryList() const;
+ void writeCategories(QXmlStreamWriter &writer, const CategoryList &cat_list) const;
+
+ int indexOfCategory(const QString &name) const;
+ int indexOfScratchpad() const;
+ int ensureScratchpad();
+ void addCustomCategories(bool replace);
+
+ void saveExpandedState() const;
+ void restoreExpandedState();
+ void updateViewMode();
+
+ QDesignerFormEditorInterface *m_core;
+ QString m_file_name;
+ typedef QHash<QString, QIcon> IconCache;
+ mutable IconCache m_pluginIcons;
+ bool m_iconMode;
+ QTimer *m_scratchPadDeleteTimer;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETBOXTREEWIDGET_H
diff --git a/tools/designer/src/designer/Info_mac.plist b/tools/designer/src/designer/Info_mac.plist
new file mode 100644
index 0000000000..8632a6df37
--- /dev/null
+++ b/tools/designer/src/designer/Info_mac.plist
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.trolltech.Designer</string>
+ <key>CFBundleSignature</key>
+ <string>ttxt</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>ui</string>
+ </array>
+ <key>CFBundleTypeIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSIsAppleDefaultForType</key>
+ <true/>
+ </dict>
+ </array>
+ <key>NOTE</key>
+ <string>Qt/Designer by Nokia Corporation and/or its subsidiary(-ies)</string>
+</dict>
+</plist>
diff --git a/tools/designer/src/designer/appfontdialog.cpp b/tools/designer/src/designer/appfontdialog.cpp
new file mode 100644
index 0000000000..d10cef81f4
--- /dev/null
+++ b/tools/designer/src/designer/appfontdialog.cpp
@@ -0,0 +1,429 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "appfontdialog.h"
+
+#include <iconloader_p.h>
+#include <abstractsettings_p.h>
+
+#include <QtGui/QTreeView>
+#include <QtGui/QToolButton>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QFileDialog>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QMessageBox>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QDialogButtonBox>
+
+#include <QtCore/QSettings>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
+#include <QtCore/QFileInfo>
+#include <QtCore/QtAlgorithms>
+#include <QtCore/QVector>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+enum {FileNameRole = Qt::UserRole + 1, IdRole = Qt::UserRole + 2 };
+enum { debugAppFontWidget = 0 };
+
+static const char fontFileKeyC[] = "fontFiles";
+
+// AppFontManager: Singleton that maintains the mapping of loaded application font
+// ids to the file names (which are not stored in QFontDatabase)
+// and provides API for loading/unloading fonts as well for saving/restoring settings.
+
+class AppFontManager
+{
+ Q_DISABLE_COPY(AppFontManager)
+ AppFontManager();
+public:
+ static AppFontManager &instance();
+
+ void save(QDesignerSettingsInterface *s, const QString &prefix) const;
+ void restore(const QDesignerSettingsInterface *s, const QString &prefix);
+
+ // Return id or -1
+ int add(const QString &fontFile, QString *errorMessage);
+
+ bool remove(int id, QString *errorMessage);
+ bool remove(const QString &fontFile, QString *errorMessage);
+ bool removeAt(int index, QString *errorMessage);
+
+ // Store loaded fonts as pair of file name and Id
+ typedef QPair<QString,int> FileNameFontIdPair;
+ typedef QList<FileNameFontIdPair> FileNameFontIdPairs;
+ const FileNameFontIdPairs &fonts() const;
+
+private:
+ FileNameFontIdPairs m_fonts;
+};
+
+AppFontManager::AppFontManager()
+{
+}
+
+AppFontManager &AppFontManager::instance()
+{
+ static AppFontManager rc;
+ return rc;
+}
+
+void AppFontManager::save(QDesignerSettingsInterface *s, const QString &prefix) const
+{
+ // Store as list of file names
+ QStringList fontFiles;
+ const FileNameFontIdPairs::const_iterator cend = m_fonts.constEnd();
+ for (FileNameFontIdPairs::const_iterator it = m_fonts.constBegin(); it != cend; ++it)
+ fontFiles.push_back(it->first);
+
+ s->beginGroup(prefix);
+ s->setValue(QLatin1String(fontFileKeyC), fontFiles);
+ s->endGroup();
+
+ if (debugAppFontWidget)
+ qDebug() << "AppFontManager::saved" << fontFiles.size() << "fonts under " << prefix;
+}
+
+void AppFontManager::restore(const QDesignerSettingsInterface *s, const QString &prefix)
+{
+ QString key = prefix;
+ key += QLatin1Char('/');
+ key += QLatin1String(fontFileKeyC);
+ const QStringList fontFiles = s->value(key, QStringList()).toStringList();
+
+ if (debugAppFontWidget)
+ qDebug() << "AppFontManager::restoring" << fontFiles.size() << "fonts from " << prefix;
+ if (!fontFiles.empty()) {
+ QString errorMessage;
+ const QStringList::const_iterator cend = fontFiles.constEnd();
+ for (QStringList::const_iterator it = fontFiles.constBegin(); it != cend; ++it)
+ if (add(*it, &errorMessage) == -1)
+ qWarning("%s", qPrintable(errorMessage));
+ }
+}
+
+int AppFontManager::add(const QString &fontFile, QString *errorMessage)
+{
+ const QFileInfo inf(fontFile);
+ if (!inf.isFile()) {
+ *errorMessage = QCoreApplication::translate("AppFontManager", "'%1' is not a file.").arg(fontFile);
+ return -1;
+ }
+ if (!inf.isReadable()) {
+ *errorMessage = QCoreApplication::translate("AppFontManager", "The font file '%1' does not have read permissions.").arg(fontFile);
+ return -1;
+ }
+ const QString fullPath = inf.absoluteFilePath();
+ // Check if already loaded
+ const FileNameFontIdPairs::const_iterator cend = m_fonts.constEnd();
+ for (FileNameFontIdPairs::const_iterator it = m_fonts.constBegin(); it != cend; ++it) {
+ if (it->first == fullPath) {
+ *errorMessage = QCoreApplication::translate("AppFontManager", "The font file '%1' is already loaded.").arg(fontFile);
+ return -1;
+ }
+ }
+
+ const int id = QFontDatabase::addApplicationFont(fullPath);
+ if (id == -1) {
+ *errorMessage = QCoreApplication::translate("AppFontManager", "The font file '%1' could not be loaded.").arg(fontFile);
+ return -1;
+ }
+
+ if (debugAppFontWidget)
+ qDebug() << "AppFontManager::add" << fontFile << id;
+ m_fonts.push_back(FileNameFontIdPair(fullPath, id));
+ return id;
+}
+
+bool AppFontManager::remove(int id, QString *errorMessage)
+{
+ const int count = m_fonts.size();
+ for (int i = 0; i < count; i++)
+ if (m_fonts[i].second == id)
+ return removeAt(i, errorMessage);
+
+ *errorMessage = QCoreApplication::translate("AppFontManager", "'%1' is not a valid font id.").arg(id);
+ return false;
+}
+
+bool AppFontManager::remove(const QString &fontFile, QString *errorMessage)
+{
+ const int count = m_fonts.size();
+ for (int i = 0; i < count; i++)
+ if (m_fonts[i].first == fontFile)
+ return removeAt(i, errorMessage);
+
+ *errorMessage = QCoreApplication::translate("AppFontManager", "There is no loaded font matching the id '%1'.").arg(fontFile);
+ return false;
+}
+
+bool AppFontManager::removeAt(int index, QString *errorMessage)
+{
+ Q_ASSERT(index >= 0 && index < m_fonts.size());
+
+ const QString fontFile = m_fonts[index].first;
+ const int id = m_fonts[index].second;
+
+ if (debugAppFontWidget)
+ qDebug() << "AppFontManager::removeAt" << index << '(' << fontFile << id << ')';
+
+ if (!QFontDatabase::removeApplicationFont(id)) {
+ *errorMessage = QCoreApplication::translate("AppFontManager", "The font '%1' (%2) could not be unloaded.").arg(fontFile).arg(id);
+ return false;
+ }
+ m_fonts.removeAt(index);
+ return true;
+}
+
+const AppFontManager::FileNameFontIdPairs &AppFontManager::fonts() const
+{
+ return m_fonts;
+}
+
+// ------------- AppFontModel
+class AppFontModel : public QStandardItemModel {
+ Q_DISABLE_COPY(AppFontModel)
+public:
+ AppFontModel(QObject *parent = 0);
+
+ void init(const AppFontManager &mgr);
+ void add(const QString &fontFile, int id);
+ int idAt(const QModelIndex &idx) const;
+};
+
+AppFontModel::AppFontModel(QObject * parent) :
+ QStandardItemModel(parent)
+{
+ setHorizontalHeaderLabels(QStringList(AppFontWidget::tr("Fonts")));
+}
+
+void AppFontModel::init(const AppFontManager &mgr)
+{
+ typedef AppFontManager::FileNameFontIdPairs FileNameFontIdPairs;
+
+ const FileNameFontIdPairs &fonts = mgr.fonts();
+ const FileNameFontIdPairs::const_iterator cend = fonts.constEnd();
+ for (FileNameFontIdPairs::const_iterator it = fonts.constBegin(); it != cend; ++it)
+ add(it->first, it->second);
+}
+
+void AppFontModel::add(const QString &fontFile, int id)
+{
+ const QFileInfo inf(fontFile);
+ // Root item with base name
+ QStandardItem *fileItem = new QStandardItem(inf.completeBaseName());
+ const QString fullPath = inf.absoluteFilePath();
+ fileItem->setData(fullPath, FileNameRole);
+ fileItem->setToolTip(fullPath);
+ fileItem->setData(id, IdRole);
+ fileItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
+
+ appendRow(fileItem);
+ const QStringList families = QFontDatabase::applicationFontFamilies(id);
+ const QStringList::const_iterator cend = families.constEnd();
+ for (QStringList::const_iterator it = families.constBegin(); it != cend; ++it) {
+ QStandardItem *familyItem = new QStandardItem(*it);
+ familyItem->setToolTip(fullPath);
+ familyItem->setFont(QFont(*it));
+ familyItem->setFlags(Qt::ItemIsEnabled);
+ fileItem->appendRow(familyItem);
+ }
+}
+
+int AppFontModel::idAt(const QModelIndex &idx) const
+{
+ if (const QStandardItem *item = itemFromIndex(idx))
+ return item->data(IdRole).toInt();
+ return -1;
+}
+
+// ------------- AppFontWidget
+AppFontWidget::AppFontWidget(QWidget *parent) :
+ QGroupBox(parent),
+ m_view(new QTreeView),
+ m_addButton(new QToolButton),
+ m_removeButton(new QToolButton),
+ m_removeAllButton(new QToolButton),
+ m_model(new AppFontModel(this))
+{
+ m_model->init(AppFontManager::instance());
+ m_view->setModel(m_model);
+ m_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ m_view->expandAll();
+ connect(m_view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
+
+ m_addButton->setToolTip(tr("Add font files"));
+ m_addButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("plus.png")));
+ connect(m_addButton, SIGNAL(clicked()), this, SLOT(addFiles()));
+
+ m_removeButton->setEnabled(false);
+ m_removeButton->setToolTip(tr("Remove current font file"));
+ m_removeButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("minus.png")));
+ connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemoveFiles()));
+
+ m_removeAllButton->setToolTip(tr("Remove all font files"));
+ m_removeAllButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("editdelete.png")));
+ connect(m_removeAllButton, SIGNAL(clicked()), this, SLOT(slotRemoveAll()));
+
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->addWidget(m_addButton);
+ hLayout->addWidget(m_removeButton);
+ hLayout->addWidget(m_removeAllButton);
+ hLayout->addItem(new QSpacerItem(0, 0,QSizePolicy::MinimumExpanding));
+
+ QVBoxLayout *vLayout = new QVBoxLayout;
+ vLayout->addWidget(m_view);
+ vLayout->addLayout(hLayout);
+ setLayout(vLayout);
+}
+
+void AppFontWidget::addFiles()
+{
+ const QStringList files =
+ QFileDialog::getOpenFileNames(this, tr("Add Font Files"), QString(),
+ tr("Font files (*.ttf)"));
+ if (files.empty())
+ return;
+
+ QString errorMessage;
+
+ AppFontManager &fmgr = AppFontManager::instance();
+ const QStringList::const_iterator cend = files.constEnd();
+ for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) {
+ const int id = fmgr.add(*it, &errorMessage);
+ if (id != -1) {
+ m_model->add(*it, id);
+ } else {
+ QMessageBox::critical(this, tr("Error Adding Fonts"), errorMessage);
+ }
+ }
+ m_view->expandAll();
+}
+
+static void removeFonts(const QModelIndexList &selectedIndexes, AppFontModel *model, QWidget *dialogParent)
+{
+ if (selectedIndexes.empty())
+ return;
+
+ // Reverse sort top level rows and remove
+ AppFontManager &fmgr = AppFontManager::instance();
+ QVector<int> rows;
+ rows.reserve(selectedIndexes.size());
+
+ QString errorMessage;
+ const QModelIndexList::const_iterator cend = selectedIndexes.constEnd();
+ for (QModelIndexList::const_iterator it = selectedIndexes.constBegin(); it != cend; ++it) {
+ const int id = model->idAt(*it);
+ if (id != -1) {
+ if (fmgr.remove(id, &errorMessage)) {
+ rows.push_back(it->row());
+ } else {
+ QMessageBox::critical(dialogParent, AppFontWidget::tr("Error Removing Fonts"), errorMessage);
+ }
+ }
+ }
+
+ qStableSort(rows.begin(), rows.end());
+ for (int i = rows.size() - 1; i >= 0; i--)
+ model->removeRow(rows[i]);
+}
+
+void AppFontWidget::slotRemoveFiles()
+{
+ removeFonts(m_view->selectionModel()->selectedIndexes(), m_model, this);
+}
+
+void AppFontWidget::slotRemoveAll()
+{
+ const int count = m_model->rowCount();
+ if (!count)
+ return;
+
+ const QMessageBox::StandardButton answer =
+ QMessageBox::question(this, tr("Remove Fonts"), tr("Would you like to remove all fonts?"),
+ QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+ if (answer == QMessageBox::No)
+ return;
+
+ QModelIndexList topLevels;
+ for (int i = 0; i < count; i++)
+ topLevels.push_back(m_model->index(i, 0));
+ removeFonts(topLevels, m_model, this);
+}
+
+void AppFontWidget::selectionChanged(const QItemSelection &selected, const QItemSelection & /*deselected*/)
+{
+ m_removeButton->setEnabled(!selected.indexes().empty());
+}
+
+void AppFontWidget::save(QDesignerSettingsInterface *s, const QString &prefix)
+{
+ AppFontManager::instance().save(s, prefix);
+}
+
+void AppFontWidget::restore(const QDesignerSettingsInterface *s, const QString &prefix)
+{
+ AppFontManager::instance().restore(s, prefix);
+}
+
+// ------------ AppFontDialog
+AppFontDialog::AppFontDialog(QWidget *parent) :
+ QDialog(parent),
+ m_appFontWidget(new AppFontWidget)
+{
+ setAttribute(Qt::WA_DeleteOnClose, true);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setWindowTitle(tr("Additional Fonts"));
+ setModal(false);
+ QVBoxLayout *vl = new QVBoxLayout;
+ vl->addWidget(m_appFontWidget);
+
+ QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Close);
+ QDialog::connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
+ vl->addWidget(bb);
+ setLayout(vl);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/appfontdialog.h b/tools/designer/src/designer/appfontdialog.h
new file mode 100644
index 0000000000..c6142f2564
--- /dev/null
+++ b/tools/designer/src/designer/appfontdialog.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_APPFONTWIDGET_H
+#define QDESIGNER_APPFONTWIDGET_H
+
+#include <QtGui/QGroupBox>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class AppFontModel;
+
+class QTreeView;
+class QToolButton;
+class QItemSelection;
+class QDesignerSettingsInterface;
+
+// AppFontWidget: Manages application fonts which the user can load and
+// provides API for saving/restoring them.
+
+class AppFontWidget : public QGroupBox
+{
+ Q_DISABLE_COPY(AppFontWidget)
+ Q_OBJECT
+public:
+ explicit AppFontWidget(QWidget *parent = 0);
+
+ QStringList fontFiles() const;
+
+ static void save(QDesignerSettingsInterface *s, const QString &prefix);
+ static void restore(const QDesignerSettingsInterface *s, const QString &prefix);
+
+private slots:
+ void addFiles();
+ void slotRemoveFiles();
+ void slotRemoveAll();
+ void selectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
+
+private:
+ QTreeView *m_view;
+ QToolButton *m_addButton;
+ QToolButton *m_removeButton;
+ QToolButton *m_removeAllButton;
+ AppFontModel *m_model;
+};
+
+// AppFontDialog: Non modal dialog for AppFontWidget which has Qt::WA_DeleteOnClose set.
+
+class AppFontDialog : public QDialog
+{
+ Q_DISABLE_COPY(AppFontDialog)
+ Q_OBJECT
+public:
+ explicit AppFontDialog(QWidget *parent = 0);
+
+private:
+ AppFontWidget *m_appFontWidget;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_APPFONTWIDGET_H
diff --git a/tools/designer/src/designer/assistantclient.cpp b/tools/designer/src/designer/assistantclient.cpp
new file mode 100644
index 0000000000..d3a388db8b
--- /dev/null
+++ b/tools/designer/src/designer/assistantclient.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "assistantclient.h"
+
+#include <QtCore/QString>
+#include <QtCore/QProcess>
+#include <QtCore/QDir>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
+#include <QtCore/QObject>
+#include <QtCore/QTextStream>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+enum { debugAssistantClient = 0 };
+
+AssistantClient::AssistantClient() :
+ m_process(0)
+{
+}
+
+AssistantClient::~AssistantClient()
+{
+ if (isRunning()) {
+ m_process->terminate();
+ m_process->waitForFinished();
+ }
+ delete m_process;
+}
+
+bool AssistantClient::showPage(const QString &path, QString *errorMessage)
+{
+ QString cmd = QLatin1String("SetSource ");
+ cmd += path;
+ return sendCommand(cmd, errorMessage);
+}
+
+bool AssistantClient::activateIdentifier(const QString &identifier, QString *errorMessage)
+{
+ QString cmd = QLatin1String("ActivateIdentifier ");
+ cmd += identifier;
+ return sendCommand(cmd, errorMessage);
+}
+
+bool AssistantClient::activateKeyword(const QString &keyword, QString *errorMessage)
+{
+ QString cmd = QLatin1String("ActivateKeyword ");
+ cmd += keyword;
+ return sendCommand(cmd, errorMessage);
+}
+
+bool AssistantClient::sendCommand(const QString &cmd, QString *errorMessage)
+{
+ if (debugAssistantClient)
+ qDebug() << "sendCommand " << cmd;
+ if (!ensureRunning(errorMessage))
+ return false;
+ if (!m_process->isWritable() || m_process->bytesToWrite() > 0) {
+ *errorMessage = QCoreApplication::translate("AssistantClient", "Unable to send request: Assistant is not responding.");
+ return false;
+ }
+ QTextStream str(m_process);
+ str << cmd << QLatin1Char('\0') << endl;
+ return true;
+}
+
+bool AssistantClient::isRunning() const
+{
+ return m_process && m_process->state() != QProcess::NotRunning;
+}
+
+QString AssistantClient::binary()
+{
+ QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator();
+#if !defined(Q_OS_MAC)
+ app += QLatin1String("assistant");
+#else
+ app += QLatin1String("Assistant.app/Contents/MacOS/Assistant");
+#endif
+
+#if defined(Q_OS_WIN)
+ app += QLatin1String(".exe");
+#endif
+
+ return app;
+}
+
+bool AssistantClient::ensureRunning(QString *errorMessage)
+{
+ if (isRunning())
+ return true;
+
+ if (!m_process)
+ m_process = new QProcess;
+
+ const QString app = binary();
+ if (!QFileInfo(app).isFile()) {
+ *errorMessage = QCoreApplication::translate("AssistantClient", "The binary '%1' does not exist.").arg(app);
+ return false;
+ }
+ if (debugAssistantClient)
+ qDebug() << "Running " << app;
+ // run
+ QStringList args(QLatin1String("-enableRemoteControl"));
+ m_process->start(app, args);
+ if (!m_process->waitForStarted()) {
+ *errorMessage = QCoreApplication::translate("AssistantClient", "Unable to launch assistant (%1).").arg(app);
+ return false;
+ }
+ return true;
+}
+
+QString AssistantClient::documentUrl(const QString &prefix, int qtVersion)
+{
+ if (qtVersion == 0)
+ qtVersion = QT_VERSION;
+ QString rc;
+ QTextStream(&rc) << QLatin1String("qthelp://com.trolltech.") << prefix << QLatin1Char('.')
+ << (qtVersion >> 16) << ((qtVersion >> 8) & 0xFF) << (qtVersion & 0xFF)
+ << QLatin1String("/qdoc/");
+ return rc;
+}
+
+QString AssistantClient::designerManualUrl(int qtVersion)
+{
+ return documentUrl(QLatin1String("designer"), qtVersion);
+}
+
+QString AssistantClient::qtReferenceManualUrl(int qtVersion)
+{
+ return documentUrl(QLatin1String("qt"), qtVersion);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/assistantclient.h b/tools/designer/src/designer/assistantclient.h
new file mode 100644
index 0000000000..ac3c9802a1
--- /dev/null
+++ b/tools/designer/src/designer/assistantclient.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ASSISTANTCLIENT_H
+#define ASSISTANTCLIENT_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QProcess;
+class QString;
+
+class AssistantClient
+{
+ AssistantClient(const AssistantClient &);
+ AssistantClient &operator=(const AssistantClient &);
+
+public:
+ AssistantClient();
+ ~AssistantClient();
+
+ bool showPage(const QString &path, QString *errorMessage);
+ bool activateIdentifier(const QString &identifier, QString *errorMessage);
+ bool activateKeyword(const QString &keyword, QString *errorMessage);
+
+ bool isRunning() const;
+
+ static QString documentUrl(const QString &prefix, int qtVersion = 0);
+ // Root of the Qt Designer documentation
+ static QString designerManualUrl(int qtVersion = 0);
+ // Root of the Qt Reference documentation
+ static QString qtReferenceManualUrl(int qtVersion = 0);
+
+private:
+ static QString binary();
+ bool sendCommand(const QString &cmd, QString *errorMessage);
+ bool ensureRunning(QString *errorMessage);
+
+ QProcess *m_process;
+};
+
+QT_END_NAMESPACE
+
+#endif // ASSISTANTCLIENT_H
diff --git a/tools/designer/src/designer/designer.icns b/tools/designer/src/designer/designer.icns
new file mode 100644
index 0000000000..9940214fc2
--- /dev/null
+++ b/tools/designer/src/designer/designer.icns
Binary files differ
diff --git a/tools/designer/src/designer/designer.ico b/tools/designer/src/designer/designer.ico
new file mode 100644
index 0000000000..ef667333d6
--- /dev/null
+++ b/tools/designer/src/designer/designer.ico
Binary files differ
diff --git a/tools/designer/src/designer/designer.pro b/tools/designer/src/designer/designer.pro
new file mode 100644
index 0000000000..e7fa038748
--- /dev/null
+++ b/tools/designer/src/designer/designer.pro
@@ -0,0 +1,89 @@
+
+DESTDIR = ../../../../bin
+QT += xml network script
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+INCLUDEPATH += \
+ ../lib/sdk \
+ ../lib/extension \
+ ../lib/shared \
+ ../lib/uilib \
+ extra
+
+LIBS += -L../../lib \
+ -L../../../../lib \
+ -lQtDesignerComponents \
+ -lQtDesigner
+
+RESOURCES += designer.qrc
+
+contains(CONFIG, static) {
+ DEFINES += QT_DESIGNER_STATIC
+}
+
+TARGET = designer
+
+include($$QT_SOURCE_TREE/tools/shared/fontpanel/fontpanel.pri)
+include($$QT_SOURCE_TREE/tools/shared/qttoolbardialog/qttoolbardialog.pri)
+
+HEADERS += \
+ qdesigner.h \
+ qdesigner_toolwindow.h \
+ qdesigner_formwindow.h \
+ qdesigner_workbench.h \
+ qdesigner_settings.h \
+ qdesigner_actions.h \
+ qdesigner_server.h \
+ qdesigner_appearanceoptions.h \
+ saveformastemplate.h \
+ newform.h \
+ versiondialog.h \
+ designer_enums.h \
+ appfontdialog.h \
+ preferencesdialog.h \
+ assistantclient.h \
+ mainwindow.h
+
+SOURCES += main.cpp \
+ qdesigner.cpp \
+ qdesigner_toolwindow.cpp \
+ qdesigner_formwindow.cpp \
+ qdesigner_workbench.cpp \
+ qdesigner_settings.cpp \
+ qdesigner_server.cpp \
+ qdesigner_actions.cpp \
+ qdesigner_appearanceoptions.cpp \
+ saveformastemplate.cpp \
+ newform.cpp \
+ versiondialog.cpp \
+ appfontdialog.cpp \
+ preferencesdialog.cpp \
+ assistantclient.cpp \
+ mainwindow.cpp
+
+PRECOMPILED_HEADER=qdesigner_pch.h
+
+FORMS += saveformastemplate.ui \
+ preferencesdialog.ui \
+ qdesigner_appearanceoptions.ui
+
+win32 {
+ RC_FILE = designer.rc
+}
+
+mac {
+ ICON = designer.icns
+ QMAKE_INFO_PLIST = Info_mac.plist
+ TARGET = Designer
+}
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+include(../sharedcomponents.pri)
+
+unix:!mac:LIBS += -lm
+TRANSLATIONS = designer_de.ts
diff --git a/tools/designer/src/designer/designer.qrc b/tools/designer/src/designer/designer.qrc
new file mode 100644
index 0000000000..fac8120d0c
--- /dev/null
+++ b/tools/designer/src/designer/designer.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource prefix="/trolltech/designer">
+ <file>images/designer.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/designer/src/designer/designer.rc b/tools/designer/src/designer/designer.rc
new file mode 100644
index 0000000000..4b6324be85
--- /dev/null
+++ b/tools/designer/src/designer/designer.rc
@@ -0,0 +1,2 @@
+IDI_ICON1 ICON DISCARDABLE "designer.ico"
+
diff --git a/tools/designer/src/designer/designer_enums.h b/tools/designer/src/designer/designer_enums.h
new file mode 100644
index 0000000000..25c3078cb0
--- /dev/null
+++ b/tools/designer/src/designer/designer_enums.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESIGNERENUMS_H
+#define DESIGNERENUMS_H
+
+enum UIMode
+{
+ NeutralMode,
+ TopLevelMode,
+ DockedMode
+};
+
+#endif // DESIGNERENUMS_H
diff --git a/tools/designer/src/designer/images/designer.png b/tools/designer/src/designer/images/designer.png
new file mode 100644
index 0000000000..0988fcee3f
--- /dev/null
+++ b/tools/designer/src/designer/images/designer.png
Binary files differ
diff --git a/tools/designer/src/designer/images/mdi.png b/tools/designer/src/designer/images/mdi.png
new file mode 100644
index 0000000000..5012ab304b
--- /dev/null
+++ b/tools/designer/src/designer/images/mdi.png
Binary files differ
diff --git a/tools/designer/src/designer/images/sdi.png b/tools/designer/src/designer/images/sdi.png
new file mode 100644
index 0000000000..7fff6e8b66
--- /dev/null
+++ b/tools/designer/src/designer/images/sdi.png
Binary files differ
diff --git a/tools/designer/src/designer/images/workbench.png b/tools/designer/src/designer/images/workbench.png
new file mode 100644
index 0000000000..06716a44fc
--- /dev/null
+++ b/tools/designer/src/designer/images/workbench.png
Binary files differ
diff --git a/tools/designer/src/designer/main.cpp b/tools/designer/src/designer/main.cpp
new file mode 100644
index 0000000000..2a56efe6e8
--- /dev/null
+++ b/tools/designer/src/designer/main.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner.h"
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDir>
+
+#include <stdlib.h>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char *argv[])
+{
+ Q_INIT_RESOURCE(designer);
+
+ // report Qt usage for commercial customers with a "metered license" (currently experimental)
+#if QT_EDITION != QT_EDITION_OPENSOURCE
+ QString reporterPath = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+ reporterPath += QDir::separator();
+ reporterPath += QLatin1String("qtusagereporter");
+#if defined(Q_OS_WIN)
+ reporterPath += QLatin1String(".exe");
+#endif
+#ifndef Q_OS_WINCE
+ if (QFile::exists(reporterPath))
+ ::system(qPrintable(reporterPath + QLatin1String(" designer")));
+#endif
+#endif
+
+ QDesigner app(argc, argv);
+ app.setQuitOnLastWindowClosed(false);
+
+ return app.exec();
+}
diff --git a/tools/designer/src/designer/mainwindow.cpp b/tools/designer/src/designer/mainwindow.cpp
new file mode 100644
index 0000000000..6384fa7f65
--- /dev/null
+++ b/tools/designer/src/designer/mainwindow.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "qdesigner.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_workbench.h"
+#include "qdesigner_formwindow.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_settings.h"
+#include "qttoolbardialog.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QToolBar>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QStatusBar>
+#include <QtGui/QMenu>
+#include <QtGui/QLayout>
+#include <QtGui/QDockWidget>
+
+#include <QtCore/QUrl>
+#include <QtCore/QDebug>
+
+static const char *uriListMimeFormatC = "text/uri-list";
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QAction *> ActionList;
+
+// Helpers for creating toolbars and menu
+
+static void addActionsToToolBar(const ActionList &actions, QToolBar *t)
+{
+ const ActionList::const_iterator cend = actions.constEnd();
+ for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) {
+ QAction *action = *it;
+ if (!action->icon().isNull())
+ t->addAction(action);
+ }
+}
+static QToolBar *createToolBar(const QString &title, const QString &objectName, const ActionList &actions)
+{
+ QToolBar *rc = new QToolBar;
+ rc->setObjectName(objectName);
+ rc->setWindowTitle(title);
+ addActionsToToolBar(actions, rc);
+ return rc;
+}
+
+// ---------------- MainWindowBase
+
+MainWindowBase::MainWindowBase(QWidget *parent, Qt::WindowFlags flags) :
+ QMainWindow(parent, flags),
+ m_policy(AcceptCloseEvents)
+{
+#ifndef Q_WS_MAC
+ setWindowIcon(qDesigner->windowIcon());
+#endif
+}
+
+void MainWindowBase::closeEvent(QCloseEvent *e)
+{
+ switch (m_policy) {
+ case AcceptCloseEvents:
+ QMainWindow::closeEvent(e);
+ break;
+ case EmitCloseEventSignal:
+ emit closeEventReceived(e);
+ break;
+ }
+}
+
+QList<QToolBar *> MainWindowBase::createToolBars(const QDesignerActions *actions, bool singleToolBar)
+{
+ QList<QToolBar *> rc;
+ if (singleToolBar) {
+ //: Not currently used (main tool bar)
+ QToolBar *main = createToolBar(tr("Main"), QLatin1String("mainToolBar"), actions->fileActions()->actions());
+ addActionsToToolBar(actions->editActions()->actions(), main);
+ addActionsToToolBar(actions->toolActions()->actions(), main);
+ addActionsToToolBar(actions->formActions()->actions(), main);
+ rc.push_back(main);
+ } else {
+ rc.push_back(createToolBar(tr("File"), QLatin1String("fileToolBar"), actions->fileActions()->actions()));
+ rc.push_back(createToolBar(tr("Edit"), QLatin1String("editToolBar"), actions->editActions()->actions()));
+ rc.push_back(createToolBar(tr("Tools"), QLatin1String("toolsToolBar"), actions->toolActions()->actions()));
+ rc.push_back(createToolBar(tr("Form"), QLatin1String("formToolBar"), actions->formActions()->actions()));
+ }
+ return rc;
+}
+
+QString MainWindowBase::mainWindowTitle()
+{
+ return tr("Qt Designer");
+}
+
+// Use the minor Qt version as settings versions to avoid conflicts
+int MainWindowBase::settingsVersion()
+{
+ const int version = QT_VERSION;
+ return (version & 0x00FF00) >> 8;
+}
+
+// ----------------- DockedMdiArea
+
+DockedMdiArea::DockedMdiArea(const QString &extension, QWidget *parent) :
+ QMdiArea(parent),
+ m_extension(extension)
+{
+ setAcceptDrops(true);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+}
+
+QStringList DockedMdiArea::uiFiles(const QMimeData *d) const
+{
+ // Extract dropped ui files from Mime data.
+ QStringList rc;
+ if (!d->hasFormat(QLatin1String(uriListMimeFormatC)))
+ return rc;
+ const QList<QUrl> urls = d->urls();
+ if (urls.empty())
+ return rc;
+ const QList<QUrl>::const_iterator cend = urls.constEnd();
+ for (QList<QUrl>::const_iterator it = urls.constBegin(); it != cend; ++it) {
+ const QString fileName = it->toLocalFile();
+ if (!fileName.isEmpty() && fileName.endsWith(m_extension))
+ rc.push_back(fileName);
+ }
+ return rc;
+}
+
+bool DockedMdiArea::event(QEvent *event)
+{
+ // Listen for desktop file manager drop and emit a signal once a file is
+ // dropped.
+ switch (event->type()) {
+ case QEvent::DragEnter: {
+ QDragEnterEvent *e = static_cast<QDragEnterEvent*>(event);
+ if (!uiFiles(e->mimeData()).empty()) {
+ e->acceptProposedAction();
+ return true;
+ }
+ }
+ break;
+ case QEvent::Drop: {
+ QDropEvent *e = static_cast<QDropEvent*>(event);
+ const QStringList files = uiFiles(e->mimeData());
+ const QStringList::const_iterator cend = files.constEnd();
+ for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) {
+ emit fileDropped(*it);
+ }
+ e->acceptProposedAction();
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return QMdiArea::event(event);
+}
+
+// ------------- ToolBarManager:
+
+static void addActionsToToolBarManager(const ActionList &al, const QString &title, QtToolBarManager *tbm)
+{
+ const ActionList::const_iterator cend = al.constEnd();
+ for (ActionList::const_iterator it = al.constBegin(); it != cend; ++it)
+ tbm->addAction(*it, title);
+}
+
+ToolBarManager::ToolBarManager(QMainWindow *configureableMainWindow,
+ QWidget *parent,
+ QMenu *toolBarMenu,
+ const QDesignerActions *actions,
+ const QList<QToolBar *> &toolbars,
+ const QList<QDesignerToolWindow*> &toolWindows) :
+ QObject(parent),
+ m_configureableMainWindow(configureableMainWindow),
+ m_parent(parent),
+ m_toolBarMenu(toolBarMenu),
+ m_manager(new QtToolBarManager(this)),
+ m_configureAction(new QAction(tr("Configure Toolbars..."), this)),
+ m_toolbars(toolbars)
+{
+ m_configureAction->setMenuRole(QAction::NoRole);
+ m_configureAction->setObjectName(QLatin1String("__qt_configure_tool_bars_action"));
+ connect(m_configureAction, SIGNAL(triggered()), this, SLOT(configureToolBars()));
+
+ m_manager->setMainWindow(configureableMainWindow);
+
+ foreach(QToolBar *tb, m_toolbars) {
+ const QString title = tb->windowTitle();
+ m_manager->addToolBar(tb, title);
+ addActionsToToolBarManager(tb->actions(), title, m_manager);
+ }
+
+ addActionsToToolBarManager(actions->windowActions()->actions(), tr("Window"), m_manager);
+ addActionsToToolBarManager(actions->helpActions()->actions(), tr("Help"), m_manager);
+
+ // Filter out the device profile preview actions which have int data().
+ ActionList previewActions = actions->styleActions()->actions();
+ ActionList::iterator it = previewActions.begin();
+ for ( ; (*it)->isSeparator() || (*it)->data().type() == QVariant::Int; ++it) ;
+ previewActions.erase(previewActions.begin(), it);
+ addActionsToToolBarManager(previewActions, tr("Style"), m_manager);
+
+ const QString dockTitle = tr("Dock views");
+ foreach (QDesignerToolWindow *tw, toolWindows) {
+ if (QAction *action = tw->action())
+ m_manager->addAction(action, dockTitle);
+ }
+
+ m_manager->addAction(m_configureAction, tr("Toolbars"));
+ updateToolBarMenu();
+}
+
+// sort function for sorting tool bars alphabetically by title [non-static since called from template]
+
+bool toolBarTitleLessThan(const QToolBar *t1, const QToolBar *t2)
+{
+ return t1->windowTitle() < t2->windowTitle();
+}
+
+void ToolBarManager::updateToolBarMenu()
+{
+ // Sort tool bars alphabetically by title
+ qStableSort(m_toolbars.begin(), m_toolbars.end(), toolBarTitleLessThan);
+ // add to menu
+ m_toolBarMenu->clear();
+ foreach (QToolBar *tb, m_toolbars)
+ m_toolBarMenu->addAction(tb->toggleViewAction());
+ m_toolBarMenu->addAction(m_configureAction);
+}
+
+void ToolBarManager::configureToolBars()
+{
+ QtToolBarDialog dlg(m_parent);
+ dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ dlg.setToolBarManager(m_manager);
+ dlg.exec();
+ updateToolBarMenu();
+}
+
+QByteArray ToolBarManager::saveState(int version) const
+{
+ return m_manager->saveState(version);
+}
+
+bool ToolBarManager::restoreState(const QByteArray &state, int version)
+{
+ return m_manager->restoreState(state, version);
+}
+
+// ---------- DockedMainWindow
+
+DockedMainWindow::DockedMainWindow(QDesignerWorkbench *wb,
+ QMenu *toolBarMenu,
+ const QList<QDesignerToolWindow*> &toolWindows) :
+ m_toolBarManager(0)
+{
+ setObjectName(QLatin1String("MDIWindow"));
+ setWindowTitle(mainWindowTitle());
+
+ const QList<QToolBar *> toolbars = createToolBars(wb->actionManager(), false);
+ foreach (QToolBar *tb, toolbars)
+ addToolBar(tb);
+ DockedMdiArea *dma = new DockedMdiArea(wb->actionManager()->uiExtension());
+ connect(dma, SIGNAL(fileDropped(QString)),
+ this, SIGNAL(fileDropped(QString)));
+ connect(dma, SIGNAL(subWindowActivated(QMdiSubWindow*)),
+ this, SLOT(slotSubWindowActivated(QMdiSubWindow*)));
+ setCentralWidget(dma);
+
+ QStatusBar *sb = statusBar();
+ Q_UNUSED(sb)
+
+ m_toolBarManager = new ToolBarManager(this, this, toolBarMenu, wb->actionManager(), toolbars, toolWindows);
+}
+
+QMdiArea *DockedMainWindow::mdiArea() const
+{
+ return static_cast<QMdiArea *>(centralWidget());
+}
+
+void DockedMainWindow::slotSubWindowActivated(QMdiSubWindow* subWindow)
+{
+ if (subWindow) {
+ QWidget *widget = subWindow->widget();
+ if (QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow*>(widget)) {
+ emit formWindowActivated(fw);
+ mdiArea()->setActiveSubWindow(subWindow);
+ }
+ }
+}
+
+// Create a MDI subwindow for the form.
+QMdiSubWindow *DockedMainWindow::createMdiSubWindow(QWidget *fw, Qt::WindowFlags f, const QKeySequence &designerCloseActionShortCut)
+{
+ QMdiSubWindow *rc = mdiArea()->addSubWindow(fw, f);
+ // Make action shortcuts respond only if focused to avoid conflicts with
+ // designer menu actions
+ if (designerCloseActionShortCut == QKeySequence(QKeySequence::Close)) {
+ const ActionList systemMenuActions = rc->systemMenu()->actions();
+ if (!systemMenuActions.empty()) {
+ const ActionList::const_iterator cend = systemMenuActions.constEnd();
+ for (ActionList::const_iterator it = systemMenuActions.constBegin(); it != cend; ++it) {
+ if ( (*it)->shortcut() == designerCloseActionShortCut) {
+ (*it)->setShortcutContext(Qt::WidgetShortcut);
+ break;
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+DockedMainWindow::DockWidgetList DockedMainWindow::addToolWindows(const DesignerToolWindowList &tls)
+{
+ DockWidgetList rc;
+ foreach (QDesignerToolWindow *tw, tls) {
+ QDockWidget *dockWidget = new QDockWidget;
+ dockWidget->setObjectName(tw->objectName() + QLatin1String("_dock"));
+ dockWidget->setWindowTitle(tw->windowTitle());
+ addDockWidget(tw->dockWidgetAreaHint(), dockWidget);
+ dockWidget->setWidget(tw);
+ rc.push_back(dockWidget);
+ }
+ return rc;
+}
+
+// Settings consist of MainWindow state and tool bar manager state
+void DockedMainWindow::restoreSettings(const QDesignerSettings &s, const DockWidgetList &dws, const QRect &desktopArea)
+{
+ const int version = settingsVersion();
+ m_toolBarManager->restoreState(s.toolBarsState(DockedMode), version);
+
+ // If there are no old geometry settings, show the window maximized
+ s.restoreGeometry(this, QRect(desktopArea.topLeft(), QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)));
+
+ const QByteArray mainWindowState = s.mainWindowState(DockedMode);
+ const bool restored = !mainWindowState.isEmpty() && restoreState(mainWindowState, version);
+ if (!restored) {
+ // Default: Tabify less relevant windows bottom/right.
+ tabifyDockWidget(dws.at(QDesignerToolWindow::SignalSlotEditor),
+ dws.at(QDesignerToolWindow::ActionEditor));
+ tabifyDockWidget(dws.at(QDesignerToolWindow::ActionEditor),
+ dws.at(QDesignerToolWindow::ResourceEditor));
+ }
+}
+
+void DockedMainWindow::saveSettings(QDesignerSettings &s) const
+{
+ const int version = settingsVersion();
+ s.setToolBarsState(DockedMode, m_toolBarManager->saveState(version));
+ s.saveGeometryFor(this);
+ s.setMainWindowState(DockedMode, saveState(version));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/mainwindow.h b/tools/designer/src/designer/mainwindow.h
new file mode 100644
index 0000000000..40ce863fb4
--- /dev/null
+++ b/tools/designer/src/designer/mainwindow.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtGui/QMainWindow>
+#include <QtCore/QList>
+#include <QtGui/QMdiArea>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerActions;
+class QDesignerWorkbench;
+class QDesignerToolWindow;
+class QDesignerFormWindow;
+class QDesignerSettings;
+
+class QtToolBarManager;
+class QToolBar;
+class QMdiArea;
+class QMenu;
+class QByteArray;
+class QMimeData;
+
+/* A main window that has a configureable policy on handling close events. If
+ * enabled, it can forward the close event to external handlers.
+ * Base class for windows that can switch roles between tool windows
+ * and main windows. */
+
+class MainWindowBase: public QMainWindow
+{
+ Q_DISABLE_COPY(MainWindowBase)
+ Q_OBJECT
+protected:
+ explicit MainWindowBase(QWidget *parent = 0, Qt::WindowFlags flags = Qt::Window);
+
+public:
+ enum CloseEventPolicy {
+ /* Always accept close events */
+ AcceptCloseEvents,
+ /* Emit a signal with the event, have it handled elsewhere */
+ EmitCloseEventSignal };
+
+ CloseEventPolicy closeEventPolicy() const { return m_policy; }
+ void setCloseEventPolicy(CloseEventPolicy pol) { m_policy = pol; }
+
+ static QList<QToolBar *> createToolBars(const QDesignerActions *actions, bool singleToolBar);
+ static QString mainWindowTitle();
+
+ // Use the minor Qt version as settings versions to avoid conflicts
+ static int settingsVersion();
+
+signals:
+ void closeEventReceived(QCloseEvent *e);
+
+protected:
+ virtual void closeEvent(QCloseEvent *e);
+private:
+ CloseEventPolicy m_policy;
+};
+
+/* An MdiArea that listens for desktop file manager file drop events and emits
+ * a signal to open a dropped file. */
+class DockedMdiArea : public QMdiArea
+{
+ Q_DISABLE_COPY(DockedMdiArea)
+ Q_OBJECT
+public:
+ explicit DockedMdiArea(const QString &extension, QWidget *parent = 0);
+
+signals:
+ void fileDropped(const QString &);
+
+protected:
+ bool event (QEvent *event);
+
+private:
+ QStringList uiFiles(const QMimeData *d) const;
+
+ const QString m_extension;
+};
+
+// Convenience class that manages a QtToolBarManager and an action to trigger
+// it on a mainwindow.
+class ToolBarManager : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ToolBarManager)
+public:
+ explicit ToolBarManager(QMainWindow *configureableMainWindow,
+ QWidget *parent,
+ QMenu *toolBarMenu,
+ const QDesignerActions *actions,
+ const QList<QToolBar *> &toolbars,
+ const QList<QDesignerToolWindow*> &toolWindows);
+
+ QByteArray saveState(int version = 0) const;
+ bool restoreState(const QByteArray &state, int version = 0);
+
+private slots:
+ void configureToolBars();
+ void updateToolBarMenu();
+
+private:
+ QMainWindow *m_configureableMainWindow;
+ QWidget *m_parent;
+ QMenu *m_toolBarMenu;
+ QtToolBarManager *m_manager;
+ QAction *m_configureAction;
+ QList<QToolBar *> m_toolbars;
+};
+
+/* Main window to be used for docked mode */
+class DockedMainWindow : public MainWindowBase {
+ Q_OBJECT
+ Q_DISABLE_COPY(DockedMainWindow)
+public:
+ typedef QList<QDesignerToolWindow*> DesignerToolWindowList;
+ typedef QList<QDockWidget *> DockWidgetList;
+
+ explicit DockedMainWindow(QDesignerWorkbench *wb,
+ QMenu *toolBarMenu,
+ const DesignerToolWindowList &toolWindows);
+
+ // Create a MDI subwindow for the form.
+ QMdiSubWindow *createMdiSubWindow(QWidget *fw, Qt::WindowFlags f, const QKeySequence &designerCloseActionShortCut);
+
+ QMdiArea *mdiArea() const;
+
+ DockWidgetList addToolWindows(const DesignerToolWindowList &toolWindows);
+
+ void restoreSettings(const QDesignerSettings &s, const DockWidgetList &dws, const QRect &desktopArea);
+ void saveSettings(QDesignerSettings &) const;
+
+signals:
+ void fileDropped(const QString &);
+ void formWindowActivated(QDesignerFormWindow *);
+
+private slots:
+ void slotSubWindowActivated(QMdiSubWindow*);
+
+private:
+ ToolBarManager *m_toolBarManager;
+};
+
+QT_END_NAMESPACE
+
+#endif // MAINWINDOW_H
diff --git a/tools/designer/src/designer/newform.cpp b/tools/designer/src/designer/newform.cpp
new file mode 100644
index 0000000000..70133c5a81
--- /dev/null
+++ b/tools/designer/src/designer/newform.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "newform.h"
+#include "qdesigner_workbench.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_formwindow.h"
+#include "qdesigner_settings.h"
+
+#include <newformwidget_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QTemporaryFile>
+
+#include <QtGui/QApplication>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QMenu>
+#include <QtGui/QCheckBox>
+#include <QtGui/QFrame>
+#include <QtGui/QMessageBox>
+
+QT_BEGIN_NAMESPACE
+
+NewForm::NewForm(QDesignerWorkbench *workbench, QWidget *parentWidget, const QString &fileName)
+ : QDialog(parentWidget,
+#ifdef Q_WS_MAC
+ Qt::Tool |
+#endif
+ Qt::WindowTitleHint | Qt::WindowSystemMenuHint),
+ m_fileName(fileName),
+ m_newFormWidget(QDesignerNewFormWidgetInterface::createNewFormWidget(workbench->core())),
+ m_workbench(workbench),
+ m_chkShowOnStartup(new QCheckBox(tr("Show this Dialog on Startup"))),
+ m_createButton(new QPushButton(QApplication::translate("NewForm", "C&reate", 0, QApplication::UnicodeUTF8))),
+ m_recentButton(new QPushButton(QApplication::translate("NewForm", "Recent", 0, QApplication::UnicodeUTF8))),
+ m_buttonBox(0)
+{
+ setWindowTitle(tr("New Form"));
+ QDesignerSettings settings(m_workbench->core());
+
+ QVBoxLayout *vBoxLayout = new QVBoxLayout;
+
+ connect(m_newFormWidget, SIGNAL(templateActivated()), this, SLOT(slotTemplateActivated()));
+ connect(m_newFormWidget, SIGNAL(currentTemplateChanged(bool)), this, SLOT(slotCurrentTemplateChanged(bool)));
+ vBoxLayout->addWidget(m_newFormWidget);
+
+ QFrame *horizontalLine = new QFrame;
+ horizontalLine->setFrameShape(QFrame::HLine);
+ horizontalLine->setFrameShadow(QFrame::Sunken);
+ vBoxLayout->addWidget(horizontalLine);
+
+ m_chkShowOnStartup->setChecked(settings.showNewFormOnStartup());
+ vBoxLayout->addWidget(m_chkShowOnStartup);
+
+ m_buttonBox = createButtonBox();
+ vBoxLayout->addWidget(m_buttonBox);
+ setLayout(vBoxLayout);
+
+ resize(500, 400);
+ slotCurrentTemplateChanged(m_newFormWidget->hasCurrentTemplate());
+}
+
+QDialogButtonBox *NewForm::createButtonBox()
+{
+ // Dialog buttons with 'recent files'
+ QDialogButtonBox *buttonBox = new QDialogButtonBox;
+ buttonBox->addButton(QApplication::translate("NewForm", "&Close", 0,
+ QApplication::UnicodeUTF8), QDialogButtonBox::RejectRole);
+ buttonBox->addButton(m_createButton, QDialogButtonBox::AcceptRole);
+ buttonBox->addButton(QApplication::translate("NewForm", "&Open...", 0,
+ QApplication::UnicodeUTF8), QDialogButtonBox::ActionRole);
+ buttonBox->addButton(m_recentButton, QDialogButtonBox::ActionRole);
+ QDesignerActions *da = m_workbench->actionManager();
+ QMenu *recentFilesMenu = new QMenu(tr("&Recent Forms"), m_recentButton);
+ // Pop the "Recent Files" stuff in here.
+ const QList<QAction *> recentActions = da->recentFilesActions()->actions();
+ if (!recentActions.empty()) {
+ const QList<QAction *>::const_iterator acend = recentActions.constEnd();
+ for (QList<QAction *>::const_iterator it = recentActions.constBegin(); it != acend; ++it) {
+ recentFilesMenu->addAction(*it);
+ connect(*it, SIGNAL(triggered()), this, SLOT(recentFileChosen()));
+ }
+ }
+ m_recentButton->setMenu(recentFilesMenu);
+ connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonBoxClicked(QAbstractButton*)));
+ return buttonBox;
+}
+
+NewForm::~NewForm()
+{
+ QDesignerSettings settings (m_workbench->core());
+ settings.setShowNewFormOnStartup(m_chkShowOnStartup->isChecked());
+}
+
+void NewForm::recentFileChosen()
+{
+ QAction *action = qobject_cast<QAction *>(sender());
+ if (!action)
+ return;
+ if (action->objectName() == QLatin1String("__qt_action_clear_menu_"))
+ return;
+ close();
+}
+
+void NewForm::slotCurrentTemplateChanged(bool templateSelected)
+{
+ if (templateSelected) {
+ m_createButton->setEnabled(true);
+ m_createButton->setDefault(true);
+ } else {
+ m_createButton->setEnabled(false);
+ }
+}
+
+void NewForm::slotTemplateActivated()
+{
+ m_createButton->animateClick(0);
+}
+
+void NewForm::slotButtonBoxClicked(QAbstractButton *btn)
+{
+ switch (m_buttonBox->buttonRole(btn)) {
+ case QDialogButtonBox::RejectRole:
+ reject();
+ break;
+ case QDialogButtonBox::ActionRole:
+ if (btn != m_recentButton) {
+ m_fileName.clear();
+ if (m_workbench->actionManager()->openForm(this))
+ accept();
+ }
+ break;
+ case QDialogButtonBox::AcceptRole: {
+ QString errorMessage;
+ if (openTemplate(&errorMessage)) {
+ accept();
+ } else {
+ QMessageBox::warning(this, tr("Read error"), errorMessage);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+bool NewForm::openTemplate(QString *ptrToErrorMessage)
+{
+ const QString contents = m_newFormWidget->currentTemplate(ptrToErrorMessage);
+ if (contents.isEmpty())
+ return false;
+ // Write to temporary file and open
+ QString tempPattern = QDir::tempPath();
+ if (!tempPattern.endsWith(QDir::separator())) // platform-dependant
+ tempPattern += QDir::separator();
+ tempPattern += QLatin1String("XXXXXX.ui");
+ QTemporaryFile tempFormFile(tempPattern);
+
+ tempFormFile.setAutoRemove(true);
+ if (!tempFormFile.open()) {
+ *ptrToErrorMessage = tr("A temporary form file could not be created in %1.").arg(QDir::tempPath());
+ return false;
+ }
+ const QString tempFormFileName = tempFormFile.fileName();
+ tempFormFile.write(contents.toUtf8());
+ if (!tempFormFile.flush()) {
+ *ptrToErrorMessage = tr("The temporary form file %1 could not be written.").arg(tempFormFileName);
+ return false;
+ }
+ tempFormFile.close();
+ return m_workbench->openTemplate(tempFormFileName, m_fileName, ptrToErrorMessage);
+}
+
+QImage NewForm::grabForm(QDesignerFormEditorInterface *core,
+ QIODevice &file,
+ const QString &workingDir,
+ const qdesigner_internal::DeviceProfile &dp)
+{
+ return qdesigner_internal::NewFormWidget::grabForm(core, file, workingDir, dp);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/newform.h b/tools/designer/src/designer/newform.h
new file mode 100644
index 0000000000..edcb1b410b
--- /dev/null
+++ b/tools/designer/src/designer/newform.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NEWFORM_H
+#define NEWFORM_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ class DeviceProfile;
+}
+
+class QDesignerFormEditorInterface;
+class QDesignerNewFormWidgetInterface;
+class QDesignerWorkbench;
+
+class QCheckBox;
+class QAbstractButton;
+class QPushButton;
+class QDialogButtonBox;
+class QImage;
+class QIODevice;
+
+class NewForm: public QDialog
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(NewForm)
+
+public:
+ NewForm(QDesignerWorkbench *workbench,
+ QWidget *parentWidget,
+ // Use that file name instead of a temporary one
+ const QString &fileName = QString());
+
+ virtual ~NewForm();
+
+ // Convenience for implementing file dialogs with preview
+ static QImage grabForm(QDesignerFormEditorInterface *core,
+ QIODevice &file,
+ const QString &workingDir,
+ const qdesigner_internal::DeviceProfile &dp);
+
+private slots:
+ void slotButtonBoxClicked(QAbstractButton *btn);
+ void recentFileChosen();
+ void slotCurrentTemplateChanged(bool templateSelected);
+ void slotTemplateActivated();
+
+private:
+ QDialogButtonBox *createButtonBox();
+ bool openTemplate(QString *ptrToErrorMessage);
+
+ QString m_fileName;
+ QDesignerNewFormWidgetInterface *m_newFormWidget;
+ QDesignerWorkbench *m_workbench;
+ QCheckBox *m_chkShowOnStartup;
+ QPushButton *m_createButton;
+ QPushButton *m_recentButton;
+ QDialogButtonBox *m_buttonBox;
+};
+
+QT_END_NAMESPACE
+
+#endif // NEWFORM_H
diff --git a/tools/designer/src/designer/preferencesdialog.cpp b/tools/designer/src/designer/preferencesdialog.cpp
new file mode 100644
index 0000000000..5a905346fc
--- /dev/null
+++ b/tools/designer/src/designer/preferencesdialog.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "preferencesdialog.h"
+#include "ui_preferencesdialog.h"
+#include "qdesigner_appearanceoptions.h"
+
+#include <QtDesigner/private/abstractoptionspage_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtGui/QFileDialog>
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+PreferencesDialog::PreferencesDialog(QDesignerFormEditorInterface *core, QWidget *parentWidget) :
+ QDialog(parentWidget),
+ m_ui(new Ui::PreferencesDialog()),
+ m_core(core)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ m_ui->setupUi(this);
+
+ m_optionsPages = core->optionsPages();
+
+ m_ui->m_optionTabWidget->clear();
+ foreach (QDesignerOptionsPageInterface *optionsPage, m_optionsPages) {
+ QWidget *page = optionsPage->createPage(this);
+ m_ui->m_optionTabWidget->addTab(page, optionsPage->name());
+ if (QDesignerAppearanceOptionsWidget *appearanceWidget = qobject_cast<QDesignerAppearanceOptionsWidget *>(page))
+ connect(appearanceWidget, SIGNAL(uiModeChanged(bool)), this, SLOT(slotUiModeChanged(bool)));
+ }
+
+ connect(m_ui->m_dialogButtonBox, SIGNAL(rejected()), this, SLOT(slotRejected()));
+ connect(m_ui->m_dialogButtonBox, SIGNAL(accepted()), this, SLOT(slotAccepted()));
+ connect(applyButton(), SIGNAL(clicked()), this, SLOT(slotApply()));
+}
+
+PreferencesDialog::~PreferencesDialog()
+{
+ delete m_ui;
+}
+
+QPushButton *PreferencesDialog::applyButton() const
+{
+ return m_ui->m_dialogButtonBox->button(QDialogButtonBox::Apply);
+}
+
+void PreferencesDialog::slotApply()
+{
+ foreach (QDesignerOptionsPageInterface *optionsPage, m_optionsPages)
+ optionsPage->apply();
+}
+
+void PreferencesDialog::slotAccepted()
+{
+ slotApply();
+ closeOptionPages();
+ accept();
+}
+
+void PreferencesDialog::slotRejected()
+{
+ closeOptionPages();
+ reject();
+}
+
+void PreferencesDialog::slotUiModeChanged(bool modified)
+{
+ // Cannot "apply" a ui mode change (destroy the dialogs parent)
+ applyButton()->setEnabled(!modified);
+}
+
+void PreferencesDialog::closeOptionPages()
+{
+ foreach (QDesignerOptionsPageInterface *optionsPage, m_optionsPages)
+ optionsPage->finish();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/preferencesdialog.h b/tools/designer/src/designer/preferencesdialog.h
new file mode 100644
index 0000000000..ef9d620af8
--- /dev/null
+++ b/tools/designer/src/designer/preferencesdialog.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREFERENCESDIALOG_H
+#define PREFERENCESDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QPushButton;
+class QDesignerFormEditorInterface;
+class QDesignerOptionsPageInterface;
+
+namespace Ui {
+ class PreferencesDialog;
+}
+
+class PreferencesDialog: public QDialog
+{
+ Q_OBJECT
+public:
+ explicit PreferencesDialog(QDesignerFormEditorInterface *core, QWidget *parentWidget = 0);
+ ~PreferencesDialog();
+
+
+private slots:
+ void slotAccepted();
+ void slotRejected();
+ void slotApply();
+ void slotUiModeChanged(bool modified);
+
+private:
+ QPushButton *applyButton() const;
+ void closeOptionPages();
+
+ Ui::PreferencesDialog *m_ui;
+ QDesignerFormEditorInterface *m_core;
+ QList<QDesignerOptionsPageInterface*> m_optionsPages;
+};
+
+QT_END_NAMESPACE
+
+#endif // PREFERENCESDIALOG_H
diff --git a/tools/designer/src/designer/preferencesdialog.ui b/tools/designer/src/designer/preferencesdialog.ui
new file mode 100644
index 0000000000..28d14bb838
--- /dev/null
+++ b/tools/designer/src/designer/preferencesdialog.ui
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreferencesDialog</class>
+ <widget class="QDialog" name="PreferencesDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>474</width>
+ <height>304</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Preferences</string>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="m_optionTabWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string notr="true">Tab 1</string>
+ </attribute>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="m_dialogButtonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Apply|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>m_dialogButtonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>PreferencesDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>m_dialogButtonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>PreferencesDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/designer/qdesigner.cpp b/tools/designer/src/designer/qdesigner.cpp
new file mode 100644
index 0000000000..6eb5198adf
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// designer
+#include "qdesigner.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_server.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_workbench.h"
+#include "mainwindow.h"
+
+#include <qdesigner_propertysheet_p.h>
+
+#include <QtGui/QFileOpenEvent>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QMessageBox>
+#include <QtGui/QIcon>
+#include <QtGui/QErrorMessage>
+#include <QtCore/QMetaObject>
+#include <QtCore/QFile>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QLocale>
+#include <QtCore/QTimer>
+#include <QtCore/QTranslator>
+#include <QtCore/QFileInfo>
+#include <QtCore/qdebug.h>
+
+#include <QtDesigner/QDesignerComponents>
+
+QT_BEGIN_NAMESPACE
+
+static const char *designerApplicationName = "Designer";
+static const char *designerWarningPrefix = "Designer: ";
+
+static void designerMessageHandler(QtMsgType type, const char *msg)
+{
+ // Only Designer warnings are displayed as box
+ QDesigner *designerApp = qDesigner;
+ if (type != QtWarningMsg || !designerApp || qstrncmp(designerWarningPrefix, msg, qstrlen(designerWarningPrefix))) {
+ qInstallMsgHandler(0);
+ qt_message_output(type, msg);
+ qInstallMsgHandler (designerMessageHandler);
+ return;
+ }
+ designerApp->showErrorMessage(msg);
+}
+
+QDesigner::QDesigner(int &argc, char **argv)
+ : QApplication(argc, argv),
+ m_server(0),
+ m_client(0),
+ m_workbench(0), m_suppressNewFormShow(false)
+{
+ setOrganizationName(QLatin1String("Trolltech"));
+ setApplicationName(QLatin1String(designerApplicationName));
+ QDesignerComponents::initializeResources();
+
+#ifndef Q_WS_MAC
+ setWindowIcon(QIcon(QLatin1String(":/trolltech/designer/images/designer.png")));
+#endif
+ initialize();
+}
+
+QDesigner::~QDesigner()
+{
+ if (m_workbench)
+ delete m_workbench;
+ if (m_server)
+ delete m_server;
+ if (m_client)
+ delete m_client;
+}
+
+void QDesigner::showErrorMessage(const char *message)
+{
+ // strip the prefix
+ const QString qMessage = QString::fromUtf8(message + qstrlen(designerWarningPrefix));
+ // If there is no main window yet, just store the message.
+ // The QErrorMessage would otherwise be hidden by the main window.
+ if (m_mainWindow) {
+ showErrorMessageBox(qMessage);
+ } else {
+ qInstallMsgHandler(0);
+ qt_message_output(QtWarningMsg, message); // just in case we crash
+ qInstallMsgHandler (designerMessageHandler);
+ m_initializationErrors += qMessage;
+ m_initializationErrors += QLatin1Char('\n');
+ }
+}
+
+void QDesigner::showErrorMessageBox(const QString &msg)
+{
+ // Manually suppress consecutive messages.
+ // This happens if for example sth is wrong with custom widget creation.
+ // The same warning will be displayed by Widget box D&D and form Drop
+ // while trying to create instance.
+ if (m_errorMessageDialog && m_lastErrorMessage == msg)
+ return;
+
+ if (!m_errorMessageDialog) {
+ m_lastErrorMessage.clear();
+ m_errorMessageDialog = new QErrorMessage(m_mainWindow);
+ const QString title = QCoreApplication::translate("QDesigner", "%1 - warning").arg(QLatin1String(designerApplicationName));
+ m_errorMessageDialog->setWindowTitle(title);
+ m_errorMessageDialog->setMinimumSize(QSize(600, 250));
+ m_errorMessageDialog->setWindowFlags(m_errorMessageDialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ }
+ m_errorMessageDialog->showMessage(msg);
+ m_lastErrorMessage = msg;
+}
+
+QDesignerWorkbench *QDesigner::workbench() const
+{
+ return m_workbench;
+}
+
+QDesignerServer *QDesigner::server() const
+{
+ return m_server;
+}
+
+bool QDesigner::parseCommandLineArgs(QStringList &fileNames, QString &resourceDir)
+{
+ const QStringList args = arguments();
+ const QStringList::const_iterator acend = args.constEnd();
+ QStringList::const_iterator it = args.constBegin();
+ for (++it; it != acend; ++it) {
+ const QString &argument = *it;
+ do {
+ // Arguments
+ if (!argument.startsWith(QLatin1Char('-'))) {
+ if (!fileNames.contains(argument))
+ fileNames.append(argument);
+ break;
+ }
+ // Options
+ if (argument == QLatin1String("-server")) {
+ m_server = new QDesignerServer();
+ printf("%d\n", m_server->serverPort());
+ fflush(stdout);
+ break;
+ }
+ if (argument == QLatin1String("-client")) {
+ bool ok = true;
+ if (++it == acend) {
+ qWarning("** WARNING The option -client requires an argument");
+ return false;
+ }
+ const quint16 port = it->toUShort(&ok);
+ if (ok) {
+ m_client = new QDesignerClient(port, this);
+ } else {
+ qWarning("** WARNING Non-numeric argument specified for -client");
+ return false;
+ }
+ break;
+ }
+ if (argument == QLatin1String("-resourcedir")) {
+ if (++it == acend) {
+ qWarning("** WARNING The option -resourcedir requires an argument");
+ return false;
+ }
+ resourceDir = QFile::decodeName(it->toLocal8Bit());
+ break;
+ }
+ if (argument == QLatin1String("-enableinternaldynamicproperties")) {
+ QDesignerPropertySheet::setInternalDynamicPropertiesEnabled(true);
+ break;
+ }
+ const QString msg = QString::fromUtf8("** WARNING Unknown option %1").arg(argument);
+ qWarning("%s", qPrintable(msg));
+ } while (false);
+ }
+ return true;
+}
+
+void QDesigner::initialize()
+{
+ // initialize the sub components
+ QStringList files;
+ QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+ parseCommandLineArgs(files, resourceDir);
+
+ QTranslator *translator = new QTranslator(this);
+ QTranslator *qtTranslator = new QTranslator(this);
+
+ const QString localSysName = QLocale::system().name();
+ QString translatorFileName = QLatin1String("designer_");
+ translatorFileName += localSysName;
+ translator->load(translatorFileName, resourceDir);
+
+ translatorFileName = QLatin1String("qt_");
+ translatorFileName += localSysName;
+ qtTranslator->load(translatorFileName, resourceDir);
+ installTranslator(translator);
+ installTranslator(qtTranslator);
+
+ if (QLibraryInfo::licensedProducts() == QLatin1String("Console")) {
+ QMessageBox::information(0, tr("Qt Designer"),
+ tr("This application cannot be used for the Console edition of Qt"));
+ QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection);
+ return;
+ }
+
+ m_workbench = new QDesignerWorkbench();
+
+ emit initialized();
+ qInstallMsgHandler(designerMessageHandler); // Warn when loading faulty forms
+
+ m_suppressNewFormShow = m_workbench->readInBackup();
+
+ if (!files.empty()) {
+ const QStringList::const_iterator cend = files.constEnd();
+ for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) {
+ // Ensure absolute paths for recent file list to be unique
+ QString fileName = *it;
+ const QFileInfo fi(fileName);
+ if (fi.exists() && fi.isRelative())
+ fileName = fi.absoluteFilePath();
+ m_workbench->readInForm(fileName);
+ }
+ }
+ if ( m_workbench->formWindowCount())
+ m_suppressNewFormShow = true;
+
+ // Show up error box with parent now if something went wrong
+ if (m_initializationErrors.isEmpty()) {
+ if (!m_suppressNewFormShow && QDesignerSettings(m_workbench->core()).showNewFormOnStartup())
+ QTimer::singleShot(100, this, SLOT(callCreateForm())); // won't show anything if suppressed
+ } else {
+ showErrorMessageBox(m_initializationErrors);
+ m_initializationErrors.clear();
+ }
+}
+
+bool QDesigner::event(QEvent *ev)
+{
+ bool eaten;
+ switch (ev->type()) {
+ case QEvent::FileOpen:
+ // Set it true first since, if it's a Qt 3 form, the messagebox from convert will fire the timer.
+ m_suppressNewFormShow = true;
+ if (!m_workbench->readInForm(static_cast<QFileOpenEvent *>(ev)->file()))
+ m_suppressNewFormShow = false;
+ eaten = true;
+ break;
+ case QEvent::Close: {
+ QCloseEvent *closeEvent = static_cast<QCloseEvent *>(ev);
+ closeEvent->setAccepted(m_workbench->handleClose());
+ if (closeEvent->isAccepted()) {
+ // We're going down, make sure that we don't get our settings saved twice.
+ if (m_mainWindow)
+ m_mainWindow->setCloseEventPolicy(MainWindowBase::AcceptCloseEvents);
+ eaten = QApplication::event(ev);
+ }
+ eaten = true;
+ break;
+ }
+ default:
+ eaten = QApplication::event(ev);
+ break;
+ }
+ return eaten;
+}
+
+void QDesigner::setMainWindow(MainWindowBase *tw)
+{
+ m_mainWindow = tw;
+}
+
+MainWindowBase *QDesigner::mainWindow() const
+{
+ return m_mainWindow;
+}
+
+void QDesigner::callCreateForm()
+{
+ if (!m_suppressNewFormShow)
+ m_workbench->actionManager()->createForm();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/qdesigner.h b/tools/designer/src/designer/qdesigner.h
new file mode 100644
index 0000000000..887037cfee
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_H
+#define QDESIGNER_H
+
+#include <QtCore/QPointer>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+#define qDesigner \
+ (static_cast<QDesigner*>(QCoreApplication::instance()))
+
+class QDesignerWorkbench;
+class QDesignerToolWindow;
+class MainWindowBase;
+class QDesignerServer;
+class QDesignerClient;
+class QErrorMessage;
+
+class QDesigner: public QApplication
+{
+ Q_OBJECT
+public:
+ QDesigner(int &argc, char **argv);
+ virtual ~QDesigner();
+
+ QDesignerWorkbench *workbench() const;
+ QDesignerServer *server() const;
+ MainWindowBase *mainWindow() const;
+ void setMainWindow(MainWindowBase *tw);
+
+protected:
+ bool event(QEvent *ev);
+
+signals:
+ void initialized();
+
+public slots:
+ void showErrorMessage(const char *message);
+
+private slots:
+ void initialize();
+ void callCreateForm();
+
+private:
+ bool parseCommandLineArgs(QStringList &fileNames, QString &resourceDir);
+ void showErrorMessageBox(const QString &);
+
+ QDesignerServer *m_server;
+ QDesignerClient *m_client;
+ QDesignerWorkbench *m_workbench;
+ QPointer<MainWindowBase> m_mainWindow;
+ QPointer<QErrorMessage> m_errorMessageDialog;
+
+ QString m_initializationErrors;
+ QString m_lastErrorMessage;
+ bool m_suppressNewFormShow;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_H
diff --git a/tools/designer/src/designer/qdesigner_actions.cpp b/tools/designer/src/designer/qdesigner_actions.cpp
new file mode 100644
index 0000000000..65e5937e23
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_actions.cpp
@@ -0,0 +1,1406 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_actions.h"
+#include "designer_enums.h"
+#include "qdesigner.h"
+#include "qdesigner_workbench.h"
+#include "qdesigner_formwindow.h"
+#include "newform.h"
+#include "versiondialog.h"
+#include "saveformastemplate.h"
+#include "qdesigner_toolwindow.h"
+#include "preferencesdialog.h"
+#include "appfontdialog.h"
+
+#include <pluginmanager_p.h>
+#include <qdesigner_formbuilder_p.h>
+#include <qdesigner_utils_p.h>
+#include <iconloader_p.h>
+#include <qsimpleresource_p.h>
+#include <previewmanager_p.h>
+#include <codedialog_p.h>
+#include <qdesigner_formwindowmanager_p.h>
+#include "qdesigner_integration_p.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerFormEditorPluginInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtDesigner/private/shared_settings_p.h>
+#include <QtDesigner/private/formwindowbase_p.h>
+
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QStyleFactory>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMenu>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QIcon>
+#include <QtGui/QImage>
+#include <QtGui/QPixmap>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QPrintDialog>
+#include <QtGui/QPainter>
+#include <QtGui/QTransform>
+#include <QtGui/QCursor>
+#include <QtCore/QSizeF>
+
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QBuffer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/qdebug.h>
+#include <QtCore/QTimer>
+#include <QtCore/QMetaObject>
+#include <QtCore/QFileInfo>
+#include <QtGui/QStatusBar>
+#include <QtGui/QDesktopWidget>
+#include <QtXml/QDomDocument>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+//#ifdef Q_WS_MAC
+# define NONMODAL_PREVIEW
+//#endif
+
+static QAction *createSeparator(QObject *parent) {
+ QAction * rc = new QAction(parent);
+ rc->setSeparator(true);
+ return rc;
+}
+
+static QActionGroup *createActionGroup(QObject *parent, bool exclusive = false) {
+ QActionGroup * rc = new QActionGroup(parent);
+ rc->setExclusive(exclusive);
+ return rc;
+}
+
+static inline QString savedMessage(const QString &fileName)
+{
+ return QDesignerActions::tr("Saved %1.").arg(fileName);
+}
+
+// Prompt for a file and make sure an extension is added
+// unless the user explicitly specifies another one.
+
+static QString getSaveFileNameWithExtension(QWidget *parent, const QString &title, QString dir, const QString &filter, const QString &extension)
+{
+ const QChar dot = QLatin1Char('.');
+
+ QString saveFile;
+ while (true) {
+ saveFile = QFileDialog::getSaveFileName(parent, title, dir, filter, 0, QFileDialog::DontConfirmOverwrite);
+ if (saveFile.isEmpty())
+ return saveFile;
+
+ const QFileInfo fInfo(saveFile);
+ if (fInfo.suffix().isEmpty() && !fInfo.fileName().endsWith(dot)) {
+ saveFile += dot;
+ saveFile += extension;
+ }
+
+ const QFileInfo fi(saveFile);
+ if (!fi.exists())
+ break;
+
+ const QString prompt = QDesignerActions::tr("%1 already exists.\nDo you want to replace it?").arg(fi.fileName());
+ if (QMessageBox::warning(parent, title, prompt, QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
+ break;
+
+ dir = saveFile;
+ }
+ return saveFile;
+}
+
+QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench)
+ : QObject(workbench),
+ m_workbench(workbench),
+ m_core(workbench->core()),
+ m_settings(workbench->core()),
+ m_backupTimer(new QTimer(this)),
+ m_fileActions(createActionGroup(this)),
+ m_recentFilesActions(createActionGroup(this)),
+ m_editActions(createActionGroup(this)),
+ m_formActions(createActionGroup(this)),
+ m_settingsActions(createActionGroup(this)),
+ m_windowActions(createActionGroup(this)),
+ m_toolActions(createActionGroup(this, true)),
+ m_helpActions(0),
+ m_styleActions(0),
+ m_editWidgetsAction(new QAction(tr("Edit Widgets"), this)),
+ m_newFormAction(new QAction(qdesigner_internal::createIconSet(QLatin1String("filenew.png")), tr("&New..."), this)),
+ m_openFormAction(new QAction(qdesigner_internal::createIconSet(QLatin1String("fileopen.png")), tr("&Open..."), this)),
+ m_saveFormAction(new QAction(qdesigner_internal::createIconSet(QLatin1String("filesave.png")), tr("&Save"), this)),
+ m_saveFormAsAction(new QAction(tr("Save &As..."), this)),
+ m_saveAllFormsAction(new QAction(tr("Save A&ll"), this)),
+ m_saveFormAsTemplateAction(new QAction(tr("Save As &Template..."), this)),
+ m_closeFormAction(new QAction(tr("&Close"), this)),
+ m_savePreviewImageAction(new QAction(tr("Save &Image..."), this)),
+ m_printPreviewAction(new QAction(tr("&Print..."), this)),
+ m_quitAction(new QAction(tr("&Quit"), this)),
+ m_previewFormAction(0),
+ m_viewCodeAction(new QAction(tr("View &Code..."), this)),
+ m_minimizeAction(new QAction(tr("&Minimize"), this)),
+ m_bringAllToFrontSeparator(createSeparator(this)),
+ m_bringAllToFrontAction(new QAction(tr("Bring All to Front"), this)),
+ m_windowListSeparatorAction(createSeparator(this)),
+ m_preferencesAction(new QAction(tr("Preferences..."), this)),
+ m_appFontAction(new QAction(tr("Additional Fonts..."), this)),
+ m_appFontDialog(0),
+#ifndef QT_NO_PRINTER
+ m_printer(0),
+#endif
+ m_previewManager(0)
+{
+ Q_ASSERT(m_core != 0);
+ qdesigner_internal::QDesignerFormWindowManager *ifwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager *>(m_core->formWindowManager());
+ Q_ASSERT(ifwm);
+ m_previewManager = ifwm->previewManager();
+ m_previewFormAction = ifwm->actionDefaultPreview();
+ m_styleActions = ifwm->actionGroupPreviewInStyle();
+ connect(ifwm, SIGNAL(formWindowSettingsChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(formWindowSettingsChanged(QDesignerFormWindowInterface*)));
+
+ m_editWidgetsAction->setObjectName(QLatin1String("__qt_edit_widgets_action"));
+ m_newFormAction->setObjectName(QLatin1String("__qt_new_form_action"));
+ m_openFormAction->setObjectName(QLatin1String("__qt_open_form_action"));
+ m_saveFormAction->setObjectName(QLatin1String("__qt_save_form_action"));
+ m_saveFormAsAction->setObjectName(QLatin1String("__qt_save_form_as_action"));
+ m_saveAllFormsAction->setObjectName(QLatin1String("__qt_save_all_forms_action"));
+ m_saveFormAsTemplateAction->setObjectName(QLatin1String("__qt_save_form_as_template_action"));
+ m_closeFormAction->setObjectName(QLatin1String("__qt_close_form_action"));
+ m_quitAction->setObjectName(QLatin1String("__qt_quit_action"));
+ m_previewFormAction->setObjectName(QLatin1String("__qt_preview_form_action"));
+ m_viewCodeAction->setObjectName(QLatin1String("__qt_preview_code_action"));
+ m_minimizeAction->setObjectName(QLatin1String("__qt_minimize_action"));
+ m_bringAllToFrontAction->setObjectName(QLatin1String("__qt_bring_all_to_front_action"));
+ m_preferencesAction->setObjectName(QLatin1String("__qt_preferences_action"));
+
+ m_helpActions = createHelpActions();
+
+ QDesignerFormWindowManagerInterface *formWindowManager = m_core->formWindowManager();
+ Q_ASSERT(formWindowManager != 0);
+
+//
+// file actions
+//
+ m_newFormAction->setShortcut(QKeySequence::New);
+ connect(m_newFormAction, SIGNAL(triggered()), this, SLOT(createForm()));
+ m_fileActions->addAction(m_newFormAction);
+
+ m_openFormAction->setShortcut(QKeySequence::Open);
+ connect(m_openFormAction, SIGNAL(triggered()), this, SLOT(slotOpenForm()));
+ m_fileActions->addAction(m_openFormAction);
+
+ m_fileActions->addAction(createRecentFilesMenu());
+ m_fileActions->addAction(createSeparator(this));
+
+ m_saveFormAction->setShortcut(QKeySequence::Save);
+ connect(m_saveFormAction, SIGNAL(triggered()), this, SLOT(saveForm()));
+ m_fileActions->addAction(m_saveFormAction);
+
+ connect(m_saveFormAsAction, SIGNAL(triggered()), this, SLOT(saveFormAs()));
+ m_fileActions->addAction(m_saveFormAsAction);
+
+#ifdef Q_OS_MAC
+ m_saveAllFormsAction->setShortcut(tr("ALT+CTRL+S"));
+#else
+ m_saveAllFormsAction->setShortcut(tr("CTRL+SHIFT+S")); // Commonly "Save As" on Mac
+#endif
+ connect(m_saveAllFormsAction, SIGNAL(triggered()), this, SLOT(saveAllForms()));
+ m_fileActions->addAction(m_saveAllFormsAction);
+
+ connect(m_saveFormAsTemplateAction, SIGNAL(triggered()), this, SLOT(saveFormAsTemplate()));
+ m_fileActions->addAction(m_saveFormAsTemplateAction);
+
+ m_fileActions->addAction(createSeparator(this));
+
+ m_printPreviewAction->setShortcut(QKeySequence::Print);
+ connect(m_printPreviewAction, SIGNAL(triggered()), this, SLOT(printPreviewImage()));
+ m_fileActions->addAction(m_printPreviewAction);
+ m_printPreviewAction->setObjectName(QLatin1String("__qt_print_action"));
+
+ connect(m_savePreviewImageAction, SIGNAL(triggered()), this, SLOT(savePreviewImage()));
+ m_savePreviewImageAction->setObjectName(QLatin1String("__qt_saveimage_action"));
+ m_fileActions->addAction(m_savePreviewImageAction);
+ m_fileActions->addAction(createSeparator(this));
+
+ m_closeFormAction->setShortcut(QKeySequence::Close);
+ connect(m_closeFormAction, SIGNAL(triggered()), this, SLOT(closeForm()));
+ m_fileActions->addAction(m_closeFormAction);
+ updateCloseAction();
+
+ m_fileActions->addAction(createSeparator(this));
+
+ m_quitAction->setShortcut(tr("CTRL+Q"));
+ m_quitAction->setMenuRole(QAction::QuitRole);
+ connect(m_quitAction, SIGNAL(triggered()), this, SLOT(shutdown()));
+ m_fileActions->addAction(m_quitAction);
+
+//
+// edit actions
+//
+ QAction *undoAction = formWindowManager->actionUndo();
+ undoAction->setObjectName(QLatin1String("__qt_undo_action"));
+ undoAction->setShortcut(QKeySequence::Undo);
+ m_editActions->addAction(undoAction);
+
+ QAction *redoAction = formWindowManager->actionRedo();
+ redoAction->setObjectName(QLatin1String("__qt_redo_action"));
+ redoAction->setShortcut(QKeySequence::Redo);
+ m_editActions->addAction(redoAction);
+
+ m_editActions->addAction(createSeparator(this));
+
+ m_editActions->addAction(formWindowManager->actionCut());
+ m_editActions->addAction(formWindowManager->actionCopy());
+ m_editActions->addAction(formWindowManager->actionPaste());
+ m_editActions->addAction(formWindowManager->actionDelete());
+
+ m_editActions->addAction(formWindowManager->actionSelectAll());
+
+ m_editActions->addAction(createSeparator(this));
+
+ m_editActions->addAction(formWindowManager->actionLower());
+ m_editActions->addAction(formWindowManager->actionRaise());
+
+//
+// edit mode actions
+//
+
+ m_editWidgetsAction->setCheckable(true);
+ QList<QKeySequence> shortcuts;
+ shortcuts.append(QKeySequence(Qt::Key_F3));
+#if QT_VERSION >= 0x040900 // "ESC" switching to edit mode: Activate once item delegates handle shortcut overrides for ESC.
+ shortcuts.append(QKeySequence(Qt::Key_Escape));
+#endif
+ m_editWidgetsAction->setShortcuts(shortcuts);
+ m_editWidgetsAction->setIcon(QIcon(m_core->resourceLocation() + QLatin1String("/widgettool.png")));
+ connect(m_editWidgetsAction, SIGNAL(triggered()), this, SLOT(editWidgetsSlot()));
+ m_editWidgetsAction->setChecked(true);
+ m_editWidgetsAction->setEnabled(false);
+ m_toolActions->addAction(m_editWidgetsAction);
+
+ connect(formWindowManager, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
+
+ QList<QObject*> builtinPlugins = QPluginLoader::staticInstances();
+ builtinPlugins += m_core->pluginManager()->instances();
+ foreach (QObject *plugin, builtinPlugins) {
+ if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
+ if (QAction *action = formEditorPlugin->action()) {
+ m_toolActions->addAction(action);
+ action->setCheckable(true);
+ }
+ }
+ }
+
+ connect(m_preferencesAction, SIGNAL(triggered()), this, SLOT(showPreferencesDialog()));
+ m_preferencesAction->setMenuRole(QAction::PreferencesRole);
+ m_settingsActions->addAction(m_preferencesAction);
+
+ connect(m_appFontAction, SIGNAL(triggered()), this, SLOT(showAppFontDialog()));
+ m_appFontAction->setMenuRole(QAction::PreferencesRole);
+ m_settingsActions->addAction(m_appFontAction);
+//
+// form actions
+//
+
+ m_formActions->addAction(formWindowManager->actionHorizontalLayout());
+ m_formActions->addAction(formWindowManager->actionVerticalLayout());
+ m_formActions->addAction(formWindowManager->actionSplitHorizontal());
+ m_formActions->addAction(formWindowManager->actionSplitVertical());
+ m_formActions->addAction(formWindowManager->actionGridLayout());
+ m_formActions->addAction(formWindowManager->actionFormLayout());
+ m_formActions->addAction(formWindowManager->actionBreakLayout());
+ m_formActions->addAction(formWindowManager->actionAdjustSize());
+ m_formActions->addAction(formWindowManager->actionSimplifyLayout());
+ m_formActions->addAction(createSeparator(this));
+
+ m_previewFormAction->setShortcut(tr("CTRL+R"));
+ m_formActions->addAction(m_previewFormAction);
+ connect(m_previewManager, SIGNAL(firstPreviewOpened()), this, SLOT(updateCloseAction()));
+ connect(m_previewManager, SIGNAL(lastPreviewClosed()), this, SLOT(updateCloseAction()));
+
+ connect(m_viewCodeAction, SIGNAL(triggered()), this, SLOT(viewCode()));
+ // Preview code only in Cpp
+ if (qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core) == 0)
+ m_formActions->addAction(m_viewCodeAction);
+
+ m_formActions->addAction(createSeparator(this));
+
+ m_formActions->addAction(ifwm->actionShowFormWindowSettingsDialog());
+//
+// window actions
+//
+ m_minimizeAction->setEnabled(false);
+ m_minimizeAction->setCheckable(true);
+ m_minimizeAction->setShortcut(tr("CTRL+M"));
+ connect(m_minimizeAction, SIGNAL(triggered()), m_workbench, SLOT(toggleFormMinimizationState()));
+ m_windowActions->addAction(m_minimizeAction);
+
+ m_windowActions->addAction(m_bringAllToFrontSeparator);
+ connect(m_bringAllToFrontAction, SIGNAL(triggered()), m_workbench, SLOT(bringAllToFront()));
+ m_windowActions->addAction(m_bringAllToFrontAction);
+ m_windowActions->addAction(m_windowListSeparatorAction);
+
+ setWindowListSeparatorVisible(false);
+
+//
+// connections
+//
+ fixActionContext();
+ activeFormWindowChanged(core()->formWindowManager()->activeFormWindow());
+
+ m_backupTimer->start(180000); // 3min
+ connect(m_backupTimer, SIGNAL(timeout()), this, SLOT(backupForms()));
+
+ // Enable application font action
+ connect(formWindowManager, SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)), this, SLOT(formWindowCountChanged()));
+ connect(formWindowManager, SIGNAL(formWindowRemoved(QDesignerFormWindowInterface*)), this, SLOT(formWindowCountChanged()));
+ formWindowCountChanged();
+}
+
+QActionGroup *QDesignerActions::createHelpActions()
+{
+ QActionGroup *helpActions = createActionGroup(this);
+
+#ifndef QT_JAMBI_BUILD
+ QAction *mainHelpAction = new QAction(tr("Qt Designer &Help"), this);
+ mainHelpAction->setObjectName(QLatin1String("__qt_designer_help_action"));
+ connect(mainHelpAction, SIGNAL(triggered()), this, SLOT(showDesignerHelp()));
+ mainHelpAction->setShortcut(Qt::CTRL + Qt::Key_Question);
+ helpActions->addAction(mainHelpAction);
+
+ helpActions->addAction(createSeparator(this));
+ QAction *widgetHelp = new QAction(tr("Current Widget Help"), this);
+ widgetHelp->setObjectName(QLatin1String("__qt_current_widget_help_action"));
+ widgetHelp->setShortcut(Qt::Key_F1);
+ connect(widgetHelp, SIGNAL(triggered()), this, SLOT(showWidgetSpecificHelp()));
+ helpActions->addAction(widgetHelp);
+
+ helpActions->addAction(createSeparator(this));
+ QAction *whatsNewAction = new QAction(tr("What's New in Qt Designer?"), this);
+ whatsNewAction->setObjectName(QLatin1String("__qt_whats_new_in_qt_designer_action"));
+ connect(whatsNewAction, SIGNAL(triggered()), this, SLOT(showWhatsNew()));
+ helpActions->addAction(whatsNewAction);
+#endif
+
+ helpActions->addAction(createSeparator(this));
+ QAction *aboutPluginsAction = new QAction(tr("About Plugins"), this);
+ aboutPluginsAction->setObjectName(QLatin1String("__qt_about_plugins_action"));
+ aboutPluginsAction->setMenuRole(QAction::ApplicationSpecificRole);
+ connect(aboutPluginsAction, SIGNAL(triggered()), m_core->formWindowManager(), SLOT(aboutPlugins()));
+ helpActions->addAction(aboutPluginsAction);
+
+ QAction *aboutDesignerAction = new QAction(tr("About Qt Designer"), this);
+ aboutDesignerAction->setMenuRole(QAction::AboutRole);
+ aboutDesignerAction->setObjectName(QLatin1String("__qt_about_designer_action"));
+ connect(aboutDesignerAction, SIGNAL(triggered()), this, SLOT(aboutDesigner()));
+ helpActions->addAction(aboutDesignerAction);
+
+ QAction *aboutQtAction = new QAction(tr("About Qt"), this);
+ aboutQtAction->setMenuRole(QAction::AboutQtRole);
+ aboutQtAction->setObjectName(QLatin1String("__qt_about_qt_action"));
+ connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ helpActions->addAction(aboutQtAction);
+ return helpActions;
+}
+
+QDesignerActions::~QDesignerActions()
+{
+#ifndef QT_NO_PRINTER
+ delete m_printer;
+#endif
+}
+
+QString QDesignerActions::uiExtension() const
+{
+ QDesignerLanguageExtension *lang
+ = qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core);
+ if (lang)
+ return lang->uiExtension();
+ return QLatin1String("ui");
+}
+
+QAction *QDesignerActions::createRecentFilesMenu()
+{
+ QMenu *menu = new QMenu;
+ QAction *act;
+ // Need to insert this into the QAction.
+ for (int i = 0; i < MaxRecentFiles; ++i) {
+ act = new QAction(this);
+ act->setVisible(false);
+ connect(act, SIGNAL(triggered()), this, SLOT(openRecentForm()));
+ m_recentFilesActions->addAction(act);
+ menu->addAction(act);
+ }
+ updateRecentFileActions();
+ menu->addSeparator();
+ act = new QAction(tr("Clear &Menu"), this);
+ act->setObjectName(QLatin1String("__qt_action_clear_menu_"));
+ connect(act, SIGNAL(triggered()), this, SLOT(clearRecentFiles()));
+ m_recentFilesActions->addAction(act);
+ menu->addAction(act);
+
+ act = new QAction(tr("&Recent Forms"), this);
+ act->setMenu(menu);
+ return act;
+}
+
+QActionGroup *QDesignerActions::toolActions() const
+{ return m_toolActions; }
+
+QDesignerWorkbench *QDesignerActions::workbench() const
+{ return m_workbench; }
+
+QDesignerFormEditorInterface *QDesignerActions::core() const
+{ return m_core; }
+
+QActionGroup *QDesignerActions::fileActions() const
+{ return m_fileActions; }
+
+QActionGroup *QDesignerActions::editActions() const
+{ return m_editActions; }
+
+QActionGroup *QDesignerActions::formActions() const
+{ return m_formActions; }
+
+QActionGroup *QDesignerActions::settingsActions() const
+{ return m_settingsActions; }
+
+QActionGroup *QDesignerActions::windowActions() const
+{ return m_windowActions; }
+
+QActionGroup *QDesignerActions::helpActions() const
+{ return m_helpActions; }
+
+QActionGroup *QDesignerActions::styleActions() const
+{ return m_styleActions; }
+
+QAction *QDesignerActions::previewFormAction() const
+{ return m_previewFormAction; }
+
+QAction *QDesignerActions::viewCodeAction() const
+{ return m_viewCodeAction; }
+
+
+void QDesignerActions::editWidgetsSlot()
+{
+ QDesignerFormWindowManagerInterface *formWindowManager = core()->formWindowManager();
+ for (int i=0; i<formWindowManager->formWindowCount(); ++i) {
+ QDesignerFormWindowInterface *formWindow = formWindowManager->formWindow(i);
+ formWindow->editWidgets();
+ }
+}
+
+void QDesignerActions::createForm()
+{
+ showNewFormDialog(QString());
+}
+
+void QDesignerActions::showNewFormDialog(const QString &fileName)
+{
+ closePreview();
+ NewForm *dlg = new NewForm(workbench(), workbench()->core()->topLevel(), fileName);
+
+ dlg->setAttribute(Qt::WA_DeleteOnClose);
+ dlg->setAttribute(Qt::WA_ShowModal);
+
+ dlg->setGeometry(fixDialogRect(dlg->rect()));
+ dlg->exec();
+}
+
+void QDesignerActions::slotOpenForm()
+{
+ openForm(core()->topLevel());
+}
+
+bool QDesignerActions::openForm(QWidget *parent)
+{
+ closePreview();
+ const QString extension = uiExtension();
+ const QStringList fileNames = QFileDialog::getOpenFileNames(parent, tr("Open Form"),
+ m_openDirectory, tr("Designer UI files (*.%1);;All Files (*)").arg(extension), 0, QFileDialog::DontUseSheet);
+
+ if (fileNames.isEmpty())
+ return false;
+
+ bool atLeastOne = false;
+ foreach (QString fileName, fileNames) {
+ if (readInForm(fileName) && !atLeastOne)
+ atLeastOne = true;
+ }
+
+ return atLeastOne;
+}
+
+bool QDesignerActions::saveFormAs(QDesignerFormWindowInterface *fw)
+{
+ const QString extension = uiExtension();
+
+ QString dir = fw->fileName();
+ if (dir.isEmpty()) {
+ do {
+ // Build untitled name
+ if (!m_saveDirectory.isEmpty()) {
+ dir = m_saveDirectory;
+ break;
+ }
+ if (!m_openDirectory.isEmpty()) {
+ dir = m_openDirectory;
+ break;
+ }
+ dir = QDir::current().absolutePath();
+ } while (false);
+ dir += QDir::separator();
+ dir += QLatin1String("untitled.");
+ dir += extension;
+ }
+
+ const QString saveFile = getSaveFileNameWithExtension(fw, tr("Save Form As"), dir, tr("Designer UI files (*.%1);;All Files (*)").arg(extension), extension);
+ if (saveFile.isEmpty())
+ return false;
+
+ fw->setFileName(saveFile);
+ return writeOutForm(fw, saveFile);
+}
+
+void QDesignerActions::saveForm()
+{
+ if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow()) {
+ if (saveForm(fw))
+ showStatusBarMessage(savedMessage(QFileInfo(fw->fileName()).fileName()));
+ }
+}
+
+void QDesignerActions::saveAllForms()
+{
+ QString fileNames;
+ QDesignerFormWindowManagerInterface *formWindowManager = core()->formWindowManager();
+ if (const int totalWindows = formWindowManager->formWindowCount()) {
+ const QString separator = QLatin1String(", ");
+ for (int i = 0; i < totalWindows; ++i) {
+ QDesignerFormWindowInterface *fw = formWindowManager->formWindow(i);
+ if (fw && fw->isDirty()) {
+ formWindowManager->setActiveFormWindow(fw);
+ if (saveForm(fw)) {
+ if (!fileNames.isEmpty())
+ fileNames += separator;
+ fileNames += QFileInfo(fw->fileName()).fileName();
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ if (!fileNames.isEmpty()) {
+ showStatusBarMessage(savedMessage(fileNames));
+ }
+}
+
+bool QDesignerActions::saveForm(QDesignerFormWindowInterface *fw)
+{
+ bool ret;
+ if (fw->fileName().isEmpty())
+ ret = saveFormAs(fw);
+ else
+ ret = writeOutForm(fw, fw->fileName());
+ return ret;
+}
+
+void QDesignerActions::closeForm()
+{
+ if (m_previewManager->previewCount()) {
+ closePreview();
+ return;
+ }
+
+ if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow())
+ if (QWidget *parent = fw->parentWidget()) {
+ if (QMdiSubWindow *mdiSubWindow = qobject_cast<QMdiSubWindow *>(parent->parentWidget())) {
+ mdiSubWindow->close();
+ } else {
+ parent->close();
+ }
+ }
+}
+
+void QDesignerActions::saveFormAs()
+{
+ if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow()) {
+ if (saveFormAs(fw))
+ showStatusBarMessage(savedMessage(fw->fileName()));
+ }
+}
+
+void QDesignerActions::saveFormAsTemplate()
+{
+ if (QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow()) {
+ SaveFormAsTemplate dlg(core(), fw, fw->window());
+ dlg.exec();
+ }
+}
+
+void QDesignerActions::notImplementedYet()
+{
+ QMessageBox::information(core()->topLevel(), tr("Designer"), tr("Feature not implemented yet!"));
+}
+
+void QDesignerActions::closePreview()
+{
+ m_previewManager->closeAllPreviews();
+}
+
+void QDesignerActions::viewCode()
+{
+ QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow();
+ if (!fw)
+ return;
+ QString errorMessage;
+ if (!qdesigner_internal::CodeDialog::showCodeDialog(fw, fw, &errorMessage))
+ QMessageBox::warning(fw, tr("Code generation failed"), errorMessage);
+}
+
+void QDesignerActions::fixActionContext()
+{
+ QList<QAction*> actions;
+ actions += m_fileActions->actions();
+ actions += m_editActions->actions();
+ actions += m_toolActions->actions();
+ actions += m_formActions->actions();
+ actions += m_windowActions->actions();
+ actions += m_helpActions->actions();
+
+ foreach (QAction *a, actions) {
+ a->setShortcutContext(Qt::ApplicationShortcut);
+ }
+}
+
+bool QDesignerActions::readInForm(const QString &fileName)
+{
+ QString fn = fileName;
+
+ // First make sure that we don't have this one open already.
+ QDesignerFormWindowManagerInterface *formWindowManager = core()->formWindowManager();
+ const int totalWindows = formWindowManager->formWindowCount();
+ for (int i = 0; i < totalWindows; ++i) {
+ QDesignerFormWindowInterface *w = formWindowManager->formWindow(i);
+ if (w->fileName() == fn) {
+ w->raise();
+ formWindowManager->setActiveFormWindow(w);
+ addRecentFile(fn);
+ return true;
+ }
+ }
+
+ // Otherwise load it.
+ do {
+ QString errorMessage;
+ if (workbench()->openForm(fn, &errorMessage)) {
+ addRecentFile(fn);
+ m_openDirectory = QFileInfo(fn).absolutePath();
+ return true;
+ } else {
+ // prompt to reload
+ QMessageBox box(QMessageBox::Warning, tr("Read error"),
+ tr("%1\nDo you want to update the file location or generate a new form?").arg(errorMessage),
+ QMessageBox::Cancel, core()->topLevel());
+
+ QPushButton *updateButton = box.addButton(tr("&Update"), QMessageBox::ActionRole);
+ QPushButton *newButton = box.addButton(tr("&New Form"), QMessageBox::ActionRole);
+ box.exec();
+ if (box.clickedButton() == box.button(QMessageBox::Cancel))
+ return false;
+
+ if (box.clickedButton() == updateButton) {
+ const QString extension = uiExtension();
+ fn = QFileDialog::getOpenFileName(core()->topLevel(),
+ tr("Open Form"), m_openDirectory,
+ tr("Designer UI files (*.%1);;All Files (*)").arg(extension), 0, QFileDialog::DontUseSheet);
+
+ if (fn.isEmpty())
+ return false;
+ } else if (box.clickedButton() == newButton) {
+ // If the file does not exist, but its directory, is valid, open the template with the editor file name set to it.
+ // (called from command line).
+ QString newFormFileName;
+ const QFileInfo fInfo(fn);
+ if (!fInfo.exists()) {
+ // Normalize file name
+ const QString directory = fInfo.absolutePath();
+ if (QDir(directory).exists()) {
+ newFormFileName = directory;
+ newFormFileName += QLatin1Char('/');
+ newFormFileName += fInfo.fileName();
+ }
+ }
+ showNewFormDialog(newFormFileName);
+ return false;
+ }
+ }
+ } while (true);
+ return true;
+}
+
+static QString createBackup(const QString &fileName)
+{
+ const QString suffix = QLatin1String(".bak");
+ QString backupFile = fileName + suffix;
+ QFileInfo fi(backupFile);
+ int i = 0;
+ while (fi.exists()) {
+ backupFile = fileName + suffix + QString::number(++i);
+ fi.setFile(backupFile);
+ }
+
+ if (QFile::copy(fileName, backupFile))
+ return backupFile;
+ return QString();
+}
+
+static void removeBackup(const QString &backupFile)
+{
+ if (!backupFile.isEmpty())
+ QFile::remove(backupFile);
+}
+
+bool QDesignerActions::writeOutForm(QDesignerFormWindowInterface *fw, const QString &saveFile)
+{
+ Q_ASSERT(fw && !saveFile.isEmpty());
+
+ QString backupFile;
+ QFileInfo fi(saveFile);
+ if (fi.exists())
+ backupFile = createBackup(saveFile);
+
+ QString contents = fw->contents();
+ if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(fw)) {
+ if (fwb->lineTerminatorMode() == qdesigner_internal::FormWindowBase::CRLFLineTerminator)
+ contents.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+ }
+ const QByteArray utf8Array = contents.toUtf8();
+ m_workbench->updateBackup(fw);
+
+ QFile f(saveFile);
+ while (!f.open(QFile::WriteOnly)) {
+ QMessageBox box(QMessageBox::Warning,
+ tr("Save Form?"),
+ tr("Could not open file"),
+ QMessageBox::NoButton, fw);
+
+ box.setWindowModality(Qt::WindowModal);
+ box.setInformativeText(tr("The file %1 could not be opened."
+ "\nReason: %2"
+ "\nWould you like to retry or select a different file?")
+ .arg(f.fileName()).arg(f.errorString()));
+ QPushButton *retryButton = box.addButton(QMessageBox::Retry);
+ retryButton->setDefault(true);
+ QPushButton *switchButton = box.addButton(tr("Select New File"), QMessageBox::AcceptRole);
+ QPushButton *cancelButton = box.addButton(QMessageBox::Cancel);
+ box.exec();
+
+ if (box.clickedButton() == cancelButton) {
+ removeBackup(backupFile);
+ return false;
+ } else if (box.clickedButton() == switchButton) {
+ QString extension = uiExtension();
+ const QString fileName = QFileDialog::getSaveFileName(fw, tr("Save Form As"),
+ QDir::current().absolutePath(),
+ QLatin1String("*.") + extension);
+ if (fileName.isEmpty()) {
+ removeBackup(backupFile);
+ return false;
+ }
+ if (f.fileName() != fileName) {
+ removeBackup(backupFile);
+ fi.setFile(fileName);
+ backupFile = QString();
+ if (fi.exists())
+ backupFile = createBackup(fileName);
+ }
+ f.setFileName(fileName);
+ fw->setFileName(fileName);
+ }
+ // loop back around...
+ }
+ while (f.write(utf8Array, utf8Array.size()) != utf8Array.size()) {
+ QMessageBox box(QMessageBox::Warning, tr("Save Form?"),
+ tr("Could not write file"),
+ QMessageBox::Retry|QMessageBox::Cancel, fw);
+ box.setWindowModality(Qt::WindowModal);
+ box.setInformativeText(tr("It was not possible to write the entire file %1 to disk."
+ "\nReason:%2\nWould you like to retry?")
+ .arg(f.fileName()).arg(f.errorString()));
+ box.setDefaultButton(QMessageBox::Retry);
+ switch (box.exec()) {
+ case QMessageBox::Retry:
+ f.resize(0);
+ break;
+ default:
+ return false;
+ }
+ }
+ f.close();
+ removeBackup(backupFile);
+ addRecentFile(saveFile);
+ m_saveDirectory = QFileInfo(f).absolutePath();
+
+ fw->setDirty(false);
+ fw->parentWidget()->setWindowModified(false);
+ return true;
+}
+
+void QDesignerActions::shutdown()
+{
+ // Follow the idea from the Mac, i.e. send the Application a close event
+ // and if it's accepted, quit.
+ QCloseEvent ev;
+ QApplication::sendEvent(qDesigner, &ev);
+ if (ev.isAccepted())
+ qDesigner->quit();
+}
+
+void QDesignerActions::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+{
+ const bool enable = formWindow != 0;
+ m_saveFormAction->setEnabled(enable);
+ m_saveFormAsAction->setEnabled(enable);
+ m_saveAllFormsAction->setEnabled(enable);
+ m_saveFormAsTemplateAction->setEnabled(enable);
+ m_closeFormAction->setEnabled(enable);
+ m_savePreviewImageAction->setEnabled(enable);
+ m_printPreviewAction->setEnabled(enable);
+
+ m_editWidgetsAction->setEnabled(enable);
+
+ m_previewFormAction->setEnabled(enable);
+ m_viewCodeAction->setEnabled(enable);
+ m_styleActions->setEnabled(enable);
+}
+
+void QDesignerActions::formWindowSettingsChanged(QDesignerFormWindowInterface *fw)
+{
+ if (QDesignerFormWindow *window = m_workbench->findFormWindow(fw))
+ window->updateChanged();
+}
+
+void QDesignerActions::updateRecentFileActions()
+{
+ QStringList files = m_settings.recentFilesList();
+ const int originalSize = files.size();
+ int numRecentFiles = qMin(files.size(), int(MaxRecentFiles));
+ const QList<QAction *> recentFilesActs = m_recentFilesActions->actions();
+
+ for (int i = 0; i < numRecentFiles; ++i) {
+ const QFileInfo fi(files[i]);
+ // If the file doesn't exist anymore, just remove it from the list so
+ // people don't get confused.
+ if (!fi.exists()) {
+ files.removeAt(i);
+ --i;
+ numRecentFiles = qMin(files.size(), int(MaxRecentFiles));
+ continue;
+ }
+ const QString text = fi.fileName();
+ recentFilesActs[i]->setText(text);
+ recentFilesActs[i]->setIconText(files[i]);
+ recentFilesActs[i]->setVisible(true);
+ }
+
+ for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
+ recentFilesActs[j]->setVisible(false);
+
+ // If there's been a change, right it back
+ if (originalSize != files.size())
+ m_settings.setRecentFilesList(files);
+}
+
+void QDesignerActions::openRecentForm()
+{
+ if (const QAction *action = qobject_cast<const QAction *>(sender())) {
+ if (!readInForm(action->iconText()))
+ updateRecentFileActions(); // File doesn't exist, remove it from settings
+ }
+}
+
+void QDesignerActions::clearRecentFiles()
+{
+ m_settings.setRecentFilesList(QStringList());
+ updateRecentFileActions();
+}
+
+QActionGroup *QDesignerActions::recentFilesActions() const
+{
+ return m_recentFilesActions;
+}
+
+void QDesignerActions::addRecentFile(const QString &fileName)
+{
+ QStringList files = m_settings.recentFilesList();
+ files.removeAll(fileName);
+ files.prepend(fileName);
+ while (files.size() > MaxRecentFiles)
+ files.removeLast();
+
+ m_settings.setRecentFilesList(files);
+ updateRecentFileActions();
+}
+
+QAction *QDesignerActions::openFormAction() const
+{
+ return m_openFormAction;
+}
+
+QAction *QDesignerActions::closeFormAction() const
+{
+ return m_closeFormAction;
+}
+
+QAction *QDesignerActions::minimizeAction() const
+{
+ return m_minimizeAction;
+}
+
+void QDesignerActions::showDesignerHelp()
+{
+ QString url = AssistantClient::designerManualUrl();
+ url += QLatin1String("designer-manual.html");
+ showHelp(url);
+}
+
+void QDesignerActions::showWhatsNew()
+{
+ QString url = AssistantClient::qtReferenceManualUrl();
+ url += QLatin1String("qt4-designer.html");
+ showHelp(url);
+}
+
+void QDesignerActions::helpRequested(const QString &manual, const QString &document)
+{
+ QString url = AssistantClient::documentUrl(manual);
+ url += document;
+ showHelp(url);
+}
+
+void QDesignerActions::showHelp(const QString &url)
+{
+ QString errorMessage;
+ if (!m_assistantClient.showPage(url, &errorMessage))
+ QMessageBox::warning(core()->topLevel(), tr("Assistant"), errorMessage);
+}
+
+void QDesignerActions::aboutDesigner()
+{
+ VersionDialog mb(core()->topLevel());
+ mb.setWindowTitle(tr("About Qt Designer"));
+ if (mb.exec()) {
+ QMessageBox messageBox(QMessageBox::Information, QLatin1String("Easter Egg"),
+ QLatin1String("Easter Egg"), QMessageBox::Ok, core()->topLevel());
+ messageBox.setInformativeText(QLatin1String("The Easter Egg has been removed."));
+ messageBox.exec();
+ }
+}
+
+QAction *QDesignerActions::editWidgets() const
+{
+ return m_editWidgetsAction;
+}
+
+void QDesignerActions::showWidgetSpecificHelp()
+{
+ QString helpId;
+ if (const qdesigner_internal::QDesignerIntegration *integration = qobject_cast<qdesigner_internal::QDesignerIntegration *>(core()->integration()))
+ helpId = integration->contextHelpId();
+
+ if (helpId.isEmpty()) {
+ showDesignerHelp();
+ return;
+ }
+
+ QString errorMessage;
+ const bool rc = m_assistantClient.activateIdentifier(helpId, &errorMessage);
+ if (!rc)
+ QMessageBox::warning(core()->topLevel(), tr("Assistant"), errorMessage);
+}
+
+void QDesignerActions::updateCloseAction()
+{
+ if (m_previewManager->previewCount()) {
+ m_closeFormAction->setText(tr("&Close Preview"));
+ } else {
+ m_closeFormAction->setText(tr("&Close"));
+ }
+}
+
+void QDesignerActions::backupForms()
+{
+ const int count = m_workbench->formWindowCount();
+ if (!count || !ensureBackupDirectories())
+ return;
+
+
+ QStringList tmpFiles;
+ QMap<QString, QString> backupMap;
+ QDir backupDir(m_backupPath);
+ const bool warningsEnabled = qdesigner_internal::QSimpleResource::setWarningsEnabled(false);
+ for (int i = 0; i < count; ++i) {
+ QDesignerFormWindow *fw = m_workbench->formWindow(i);
+ QDesignerFormWindowInterface *fwi = fw->editor();
+
+ QString formBackupName;
+ QTextStream(&formBackupName) << m_backupPath << QDir::separator()
+ << QLatin1String("backup") << i << QLatin1String(".bak");
+
+ QString fwn = QDir::convertSeparators(fwi->fileName());
+ if (fwn.isEmpty())
+ fwn = fw->windowTitle();
+
+ backupMap.insert(fwn, formBackupName);
+
+ QFile file(formBackupName.replace(m_backupPath, m_backupTmpPath));
+ if (file.open(QFile::WriteOnly)){
+ QString contents = fixResourceFileBackupPath(fwi, backupDir);
+ if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(fwi)) {
+ if (fwb->lineTerminatorMode() == qdesigner_internal::FormWindowBase::CRLFLineTerminator)
+ contents.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+ }
+ const QByteArray utf8Array = contents.toUtf8();
+ if (file.write(utf8Array, utf8Array.size()) != utf8Array.size()) {
+ backupMap.remove(fwn);
+ qdesigner_internal::designerWarning(tr("The backup file %1 could not be written.").arg(file.fileName()));
+ } else
+ tmpFiles.append(formBackupName);
+
+ file.close();
+ }
+ }
+ qdesigner_internal::QSimpleResource::setWarningsEnabled(warningsEnabled);
+ if(!tmpFiles.isEmpty()) {
+ const QStringList backupFiles = backupDir.entryList(QDir::Files);
+ if(!backupFiles.isEmpty()) {
+ QStringListIterator it(backupFiles);
+ while (it.hasNext())
+ backupDir.remove(it.next());
+ }
+
+ QStringListIterator it(tmpFiles);
+ while (it.hasNext()) {
+ const QString tmpName = it.next();
+ QString name(tmpName);
+ name.replace(m_backupTmpPath, m_backupPath);
+ QFile tmpFile(tmpName);
+ if (!tmpFile.copy(name))
+ qdesigner_internal::designerWarning(tr("The backup file %1 could not be written.").arg(name));
+ tmpFile.remove();
+ }
+
+ m_settings.setBackup(backupMap);
+ }
+}
+
+QString QDesignerActions::fixResourceFileBackupPath(QDesignerFormWindowInterface *fwi, const QDir& backupDir)
+{
+ const QString content = fwi->contents();
+ QDomDocument domDoc(QLatin1String("backup"));
+ if(!domDoc.setContent(content))
+ return content;
+
+ const QDomNodeList list = domDoc.elementsByTagName(QLatin1String("resources"));
+ if (list.isEmpty())
+ return content;
+
+ for (int i = 0; i < list.count(); i++) {
+ const QDomNode node = list.at(i);
+ if (!node.isNull()) {
+ const QDomElement element = node.toElement();
+ if(!element.isNull() && element.tagName() == QLatin1String("resources")) {
+ QDomNode childNode = element.firstChild();
+ while (!childNode.isNull()) {
+ QDomElement childElement = childNode.toElement();
+ if(!childElement.isNull() && childElement.tagName() == QLatin1String("include")) {
+ const QString attr = childElement.attribute(QLatin1String("location"));
+ const QString path = fwi->absoluteDir().absoluteFilePath(attr);
+ childElement.setAttribute(QLatin1String("location"), backupDir.relativeFilePath(path));
+ }
+ childNode = childNode.nextSibling();
+ }
+ }
+ }
+ }
+
+
+ return domDoc.toString();
+}
+
+QRect QDesignerActions::fixDialogRect(const QRect &rect) const
+{
+ QRect frameGeometry;
+ const QRect availableGeometry = QApplication::desktop()->availableGeometry(core()->topLevel());
+
+ if (workbench()->mode() == DockedMode) {
+ frameGeometry = core()->topLevel()->frameGeometry();
+ } else
+ frameGeometry = availableGeometry;
+
+ QRect dlgRect = rect;
+ dlgRect.moveCenter(frameGeometry.center());
+
+ // make sure that parts of the dialog are not outside of screen
+ dlgRect.moveBottom(qMin(dlgRect.bottom(), availableGeometry.bottom()));
+ dlgRect.moveRight(qMin(dlgRect.right(), availableGeometry.right()));
+ dlgRect.moveLeft(qMax(dlgRect.left(), availableGeometry.left()));
+ dlgRect.moveTop(qMax(dlgRect.top(), availableGeometry.top()));
+
+ return dlgRect;
+}
+
+void QDesignerActions::showStatusBarMessage(const QString &message) const
+{
+ if (workbench()->mode() == DockedMode) {
+ QStatusBar *bar = qDesigner->mainWindow()->statusBar();
+ if (bar && !bar->isHidden())
+ bar->showMessage(message, 3000);
+ }
+}
+
+void QDesignerActions::setBringAllToFrontVisible(bool visible)
+{
+ m_bringAllToFrontSeparator->setVisible(visible);
+ m_bringAllToFrontAction->setVisible(visible);
+}
+
+void QDesignerActions::setWindowListSeparatorVisible(bool visible)
+{
+ m_windowListSeparatorAction->setVisible(visible);
+}
+
+bool QDesignerActions::ensureBackupDirectories() {
+
+ if (m_backupPath.isEmpty()) {
+ // create names
+ m_backupPath = QDir::homePath();
+ m_backupPath += QDir::separator();
+ m_backupPath += QLatin1String(".designer");
+ m_backupPath += QDir::separator();
+ m_backupPath += QLatin1String("backup");
+ m_backupPath = QDir::convertSeparators(m_backupPath );
+
+ m_backupTmpPath = m_backupPath;
+ m_backupTmpPath += QDir::separator();
+ m_backupTmpPath += QLatin1String("tmp");
+ m_backupTmpPath = QDir::convertSeparators(m_backupTmpPath);
+ }
+
+ // ensure directories
+ const QDir backupDir(m_backupPath);
+ const QDir backupTmpDir(m_backupTmpPath);
+
+ if (!backupDir.exists()) {
+ if (!backupDir.mkpath(m_backupPath)) {
+ qdesigner_internal::designerWarning(tr("The backup directory %1 could not be created.").arg(m_backupPath));
+ return false;
+ }
+ }
+ if (!backupTmpDir.exists()) {
+ if (!backupTmpDir.mkpath(m_backupTmpPath)) {
+ qdesigner_internal::designerWarning(tr("The temporary backup directory %1 could not be created.").arg(m_backupTmpPath));
+ return false;
+ }
+ }
+ return true;
+}
+
+void QDesignerActions::showPreferencesDialog()
+{
+ PreferencesDialog preferencesDialog(workbench()->core(), m_core->topLevel());
+ preferencesDialog.exec();
+}
+
+void QDesignerActions::showAppFontDialog()
+{
+ if (!m_appFontDialog) // Might get deleted when switching ui modes
+ m_appFontDialog = new AppFontDialog(core()->topLevel());
+ m_appFontDialog->show();
+ m_appFontDialog->raise();
+}
+
+QPixmap QDesignerActions::createPreviewPixmap(QDesignerFormWindowInterface *fw)
+{
+ const QCursor oldCursor = core()->topLevel()->cursor();
+ core()->topLevel()->setCursor(Qt::WaitCursor);
+
+ QString errorMessage;
+ const QPixmap pixmap = m_previewManager->createPreviewPixmap(fw, QString(), &errorMessage);
+ core()->topLevel()->setCursor(oldCursor);
+ if (pixmap.isNull()) {
+ QMessageBox::warning(fw, tr("Preview failed"), errorMessage);
+ }
+ return pixmap;
+}
+
+qdesigner_internal::PreviewConfiguration QDesignerActions::previewConfiguration()
+{
+ qdesigner_internal::PreviewConfiguration pc;
+ QDesignerSharedSettings settings(core());
+ if (settings.isCustomPreviewConfigurationEnabled())
+ pc = settings.customPreviewConfiguration();
+ return pc;
+}
+
+void QDesignerActions::savePreviewImage()
+{
+ const char *format = "png";
+
+ QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow();
+ if (!fw)
+ return;
+
+ QImage image;
+ const QString extension = QString::fromAscii(format);
+ const QString filter = tr("Image files (*.%1)").arg(extension);
+
+ QString suggestion = fw->fileName();
+ if (!suggestion.isEmpty()) {
+ suggestion = QFileInfo(suggestion).baseName();
+ suggestion += QLatin1Char('.');
+ suggestion += extension;
+ }
+ do {
+ const QString fileName = getSaveFileNameWithExtension(fw, tr("Save Image"), suggestion, filter, extension);
+ if (fileName.isEmpty())
+ break;
+
+ if (image.isNull()) {
+ const QPixmap pixmap = createPreviewPixmap(fw);
+ if (pixmap.isNull())
+ break;
+
+ image = pixmap.toImage();
+ }
+
+ if (image.save(fileName, format)) {
+ showStatusBarMessage(tr("Saved image %1.").arg(QFileInfo(fileName).fileName()));
+ break;
+ }
+
+ QMessageBox box(QMessageBox::Warning, tr("Save Image"),
+ tr("The file %1 could not be written.").arg( fileName),
+ QMessageBox::Retry|QMessageBox::Cancel, fw);
+ if (box.exec() == QMessageBox::Cancel)
+ break;
+ } while (true);
+}
+
+void QDesignerActions::formWindowCountChanged()
+{
+ const bool enabled = m_core->formWindowManager()->formWindowCount() == 0;
+ /* Disable the application font action if there are form windows open
+ * as the reordering of the fonts sets font properties to 'changed'
+ * and overloaded fonts are not updated. */
+ static const QString disabledTip = tr("Please close all forms to enable the loading of additional fonts.");
+ m_appFontAction->setEnabled(enabled);
+ m_appFontAction->setStatusTip(enabled ? QString() : disabledTip);
+}
+
+void QDesignerActions::printPreviewImage()
+{
+#ifndef QT_NO_PRINTER
+ QDesignerFormWindowInterface *fw = core()->formWindowManager()->activeFormWindow();
+ if (!fw)
+ return;
+
+ if (!m_printer)
+ m_printer = new QPrinter(QPrinter::HighResolution);
+
+ m_printer->setFullPage(false);
+
+ // Grab the image to be able to a suggest suitable orientation
+ const QPixmap pixmap = createPreviewPixmap(fw);
+ if (pixmap.isNull())
+ return;
+
+ const QSizeF pixmapSize = pixmap.size();
+ m_printer->setOrientation( pixmapSize.width() > pixmapSize.height() ? QPrinter::Landscape : QPrinter::Portrait);
+
+ // Printer parameters
+ QPrintDialog dialog(m_printer, fw);
+ if (!dialog.exec())
+ return;
+
+ const QCursor oldCursor = core()->topLevel()->cursor();
+ core()->topLevel()->setCursor(Qt::WaitCursor);
+ // Estimate of required scaling to make form look the same on screen and printer.
+ const double suggestedScaling = static_cast<double>(m_printer->physicalDpiX()) / static_cast<double>(fw->physicalDpiX());
+
+ QPainter painter(m_printer);
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+
+ // Clamp to page
+ const QRectF page = painter.viewport();
+ const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
+ const double scaling = qMin(suggestedScaling, maxScaling);
+
+ const double xOffset = page.left() + qMax(0.0, (page.size().width() - scaling * pixmapSize.width()) / 2.0);
+ const double yOffset = page.top() + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
+
+ // Draw.
+ painter.translate(xOffset, yOffset);
+ painter.scale(scaling, scaling);
+ painter.drawPixmap(0, 0, pixmap);
+ core()->topLevel()->setCursor(oldCursor);
+
+ showStatusBarMessage(tr("Printed %1.").arg(QFileInfo(fw->fileName()).fileName()));
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/qdesigner_actions.h b/tools/designer/src/designer/qdesigner_actions.h
new file mode 100644
index 0000000000..1e203b293f
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_actions.h
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_ACTIONS_H
+#define QDESIGNER_ACTIONS_H
+
+#include "assistantclient.h"
+#include "qdesigner_settings.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtGui/QPrinter>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerWorkbench;
+
+class QDir;
+class QTimer;
+class QAction;
+class QActionGroup;
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class AppFontDialog;
+
+class QRect;
+class QWidget;
+class QPixmap;
+class QMenu;
+
+namespace qdesigner_internal {
+ class PreviewConfiguration;
+ class PreviewManager;
+}
+
+class QDesignerActions: public QObject
+{
+ Q_OBJECT
+public:
+ explicit QDesignerActions(QDesignerWorkbench *mainWindow);
+ virtual ~QDesignerActions();
+
+ QDesignerWorkbench *workbench() const;
+ QDesignerFormEditorInterface *core() const;
+
+ bool saveForm(QDesignerFormWindowInterface *fw);
+ bool readInForm(const QString &fileName);
+ bool writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName);
+
+ QActionGroup *fileActions() const;
+ QActionGroup *recentFilesActions() const;
+ QActionGroup *editActions() const;
+ QActionGroup *formActions() const;
+ QActionGroup *settingsActions() const;
+ QActionGroup *windowActions() const;
+ QActionGroup *toolActions() const;
+ QActionGroup *helpActions() const;
+ QActionGroup *uiMode() const;
+ QActionGroup *styleActions() const;
+ // file actions
+ QAction *openFormAction() const;
+ QAction *closeFormAction() const;
+ // window actions
+ QAction *minimizeAction() const;
+ // edit mode actions
+ QAction *editWidgets() const;
+ // form actions
+ QAction *previewFormAction() const;
+ QAction *viewCodeAction() const;
+
+ void setBringAllToFrontVisible(bool visible);
+ void setWindowListSeparatorVisible(bool visible);
+
+ bool openForm(QWidget *parent);
+
+ QString uiExtension() const;
+
+public slots:
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+ void createForm();
+ void slotOpenForm();
+ void helpRequested(const QString &manual, const QString &document);
+
+signals:
+ void useBigIcons(bool);
+
+private slots:
+ void saveForm();
+ void saveFormAs();
+ void saveAllForms();
+ void saveFormAsTemplate();
+ void viewCode();
+ void notImplementedYet();
+ void shutdown();
+ void editWidgetsSlot();
+ void openRecentForm();
+ void clearRecentFiles();
+ void closeForm();
+ void showDesignerHelp();
+ void showWhatsNew();
+ void aboutDesigner();
+ void showWidgetSpecificHelp();
+ void backupForms();
+ void showNewFormDialog(const QString &fileName);
+ void showPreferencesDialog();
+ void showAppFontDialog();
+ void savePreviewImage();
+ void printPreviewImage();
+ void updateCloseAction();
+ void formWindowCountChanged();
+ void formWindowSettingsChanged(QDesignerFormWindowInterface *fw);
+
+private:
+ QAction *createRecentFilesMenu();
+ bool saveFormAs(QDesignerFormWindowInterface *fw);
+ void fixActionContext();
+ void updateRecentFileActions();
+ void addRecentFile(const QString &fileName);
+ void showHelp(const QString &help);
+ void closePreview();
+ QRect fixDialogRect(const QRect &rect) const;
+ QString fixResourceFileBackupPath(QDesignerFormWindowInterface *fwi, const QDir& backupDir);
+ void showStatusBarMessage(const QString &message) const;
+ QActionGroup *createHelpActions();
+ bool ensureBackupDirectories();
+ QPixmap createPreviewPixmap(QDesignerFormWindowInterface *fw);
+ qdesigner_internal::PreviewConfiguration previewConfiguration();
+
+ enum { MaxRecentFiles = 10 };
+ QDesignerWorkbench *m_workbench;
+ QDesignerFormEditorInterface *m_core;
+ QDesignerSettings m_settings;
+ AssistantClient m_assistantClient;
+ QString m_openDirectory;
+ QString m_saveDirectory;
+
+
+ QString m_backupPath;
+ QString m_backupTmpPath;
+
+ QTimer* m_backupTimer;
+
+ QActionGroup *m_fileActions;
+ QActionGroup *m_recentFilesActions;
+ QActionGroup *m_editActions;
+ QActionGroup *m_formActions;
+ QActionGroup *m_settingsActions;
+ QActionGroup *m_windowActions;
+ QActionGroup *m_toolActions;
+ QActionGroup *m_helpActions;
+ QActionGroup *m_styleActions;
+
+ QAction *m_editWidgetsAction;
+
+ QAction *m_newFormAction;
+ QAction *m_openFormAction;
+ QAction *m_saveFormAction;
+ QAction *m_saveFormAsAction;
+ QAction *m_saveAllFormsAction;
+ QAction *m_saveFormAsTemplateAction;
+ QAction *m_closeFormAction;
+ QAction *m_savePreviewImageAction;
+ QAction *m_printPreviewAction;
+
+ QAction *m_quitAction;
+
+ QAction *m_previewFormAction;
+ QAction *m_viewCodeAction;
+
+ QAction *m_minimizeAction;
+ QAction *m_bringAllToFrontSeparator;
+ QAction *m_bringAllToFrontAction;
+ QAction *m_windowListSeparatorAction;
+
+ QAction *m_preferencesAction;
+ QAction *m_appFontAction;
+
+ QPointer<AppFontDialog> m_appFontDialog;
+
+#ifndef QT_NO_PRINTER
+ QPrinter *m_printer;
+#endif
+
+ qdesigner_internal::PreviewManager *m_previewManager;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_ACTIONS_H
diff --git a/tools/designer/src/designer/qdesigner_appearanceoptions.cpp b/tools/designer/src/designer/qdesigner_appearanceoptions.cpp
new file mode 100644
index 0000000000..a729d381b9
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_appearanceoptions.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_appearanceoptions.h"
+#include "ui_qdesigner_appearanceoptions.h"
+
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtCore/QTimer>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+// ---------------- AppearanceOptions
+AppearanceOptions::AppearanceOptions() :
+ uiMode(DockedMode)
+{
+}
+
+bool AppearanceOptions::equals(const AppearanceOptions &rhs) const
+{
+ return uiMode == rhs.uiMode && toolWindowFontSettings == rhs.toolWindowFontSettings;
+}
+
+void AppearanceOptions::toSettings(QDesignerSettings &settings) const
+{
+ settings.setUiMode(uiMode);
+ settings.setToolWindowFont(toolWindowFontSettings);
+}
+
+void AppearanceOptions::fromSettings(const QDesignerSettings &settings)
+{
+ uiMode = settings.uiMode();
+ toolWindowFontSettings = settings.toolWindowFont();
+}
+
+// ---------------- QDesignerAppearanceOptionsWidget
+QDesignerAppearanceOptionsWidget::QDesignerAppearanceOptionsWidget(QWidget *parent) :
+ QWidget(parent),
+ m_ui(new Ui::AppearanceOptionsWidget),
+ m_initialUIMode(NeutralMode)
+{
+ m_ui->setupUi(this);
+
+ m_ui->m_uiModeCombo->addItem(tr("Docked Window"), QVariant(DockedMode));
+ m_ui->m_uiModeCombo->addItem(tr("Multiple Top-Level Windows"), QVariant(TopLevelMode));
+ connect(m_ui->m_uiModeCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(slotUiModeComboChanged()));
+
+ m_ui->m_fontPanel->setCheckable(true);
+ m_ui->m_fontPanel->setTitle(tr("Toolwindow Font"));
+
+}
+
+QDesignerAppearanceOptionsWidget::~QDesignerAppearanceOptionsWidget()
+{
+ delete m_ui;
+}
+
+UIMode QDesignerAppearanceOptionsWidget::uiMode() const
+{
+ return static_cast<UIMode>(m_ui->m_uiModeCombo->itemData(m_ui->m_uiModeCombo->currentIndex()).toInt());
+}
+
+AppearanceOptions QDesignerAppearanceOptionsWidget::appearanceOptions() const
+{
+ AppearanceOptions rc;
+ rc.uiMode = uiMode();
+ rc.toolWindowFontSettings.m_font = m_ui->m_fontPanel->selectedFont();
+ rc.toolWindowFontSettings.m_useFont = m_ui->m_fontPanel->isChecked();
+ rc.toolWindowFontSettings.m_writingSystem = m_ui->m_fontPanel->writingSystem();
+ return rc;
+}
+
+void QDesignerAppearanceOptionsWidget::setAppearanceOptions(const AppearanceOptions &ao)
+{
+ m_initialUIMode = ao.uiMode;
+ m_ui->m_uiModeCombo->setCurrentIndex(m_ui->m_uiModeCombo->findData(QVariant(ao.uiMode)));
+ m_ui->m_fontPanel->setWritingSystem(ao.toolWindowFontSettings.m_writingSystem);
+ m_ui->m_fontPanel->setSelectedFont(ao.toolWindowFontSettings.m_font);
+ m_ui->m_fontPanel->setChecked(ao.toolWindowFontSettings.m_useFont);
+}
+
+void QDesignerAppearanceOptionsWidget::slotUiModeComboChanged()
+{
+ emit uiModeChanged(m_initialUIMode != uiMode());
+}
+
+// ----------- QDesignerAppearanceOptionsPage
+QDesignerAppearanceOptionsPage::QDesignerAppearanceOptionsPage(QDesignerFormEditorInterface *core) :
+ m_core(core)
+{
+}
+
+QString QDesignerAppearanceOptionsPage::name() const
+{
+ //: Tab in preferences dialog
+ return QCoreApplication::translate("QDesignerAppearanceOptionsPage", "Appearance");
+}
+
+QWidget *QDesignerAppearanceOptionsPage::createPage(QWidget *parent)
+{
+ m_widget = new QDesignerAppearanceOptionsWidget(parent);
+ m_initialOptions.fromSettings(QDesignerSettings(m_core));
+ m_widget->setAppearanceOptions(m_initialOptions);
+ return m_widget;
+}
+
+void QDesignerAppearanceOptionsPage::apply()
+{
+ if (m_widget) {
+ const AppearanceOptions newOptions = m_widget->appearanceOptions();
+ if (newOptions != m_initialOptions) {
+ QDesignerSettings settings(m_core);
+ newOptions.toSettings(settings);
+ QTimer::singleShot(0, this, SIGNAL(settingsChangedDelayed()));
+ m_initialOptions = newOptions;
+ }
+ }
+}
+
+void QDesignerAppearanceOptionsPage::finish()
+{
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/designer/qdesigner_appearanceoptions.h b/tools/designer/src/designer/qdesigner_appearanceoptions.h
new file mode 100644
index 0000000000..40f8c8bbde
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_appearanceoptions.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_APPEARANCEOPTIONS_H
+#define QDESIGNER_APPEARANCEOPTIONS_H
+
+#include "designer_enums.h"
+#include "qdesigner_toolwindow.h"
+
+#include <QtDesigner/private/abstractoptionspage_p.h>
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerSettings;
+
+namespace Ui {
+ class AppearanceOptionsWidget;
+}
+
+/* AppearanceOptions data */
+struct AppearanceOptions {
+ AppearanceOptions();
+ bool equals(const AppearanceOptions&) const;
+ void toSettings(QDesignerSettings &) const;
+ void fromSettings(const QDesignerSettings &);
+
+ UIMode uiMode;
+ ToolWindowFontSettings toolWindowFontSettings;
+};
+
+inline bool operator==(const AppearanceOptions &ao1, const AppearanceOptions &ao2)
+{
+ return ao1.equals(ao2);
+}
+
+inline bool operator!=(const AppearanceOptions &ao1, const AppearanceOptions &ao2)
+{
+ return !ao1.equals(ao2);
+}
+
+/* QDesignerAppearanceOptionsWidget: Let the user edit AppearanceOptions */
+class QDesignerAppearanceOptionsWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit QDesignerAppearanceOptionsWidget(QWidget *parent = 0);
+ ~QDesignerAppearanceOptionsWidget();
+
+ AppearanceOptions appearanceOptions() const;
+ void setAppearanceOptions(const AppearanceOptions &ao);
+
+signals:
+ void uiModeChanged(bool modified);
+
+private slots:
+ void slotUiModeComboChanged();
+
+private:
+ UIMode uiMode() const;
+
+ Ui::AppearanceOptionsWidget *m_ui;
+ UIMode m_initialUIMode;
+};
+
+/* The options page for appearance options. Emits a Timer-0 delayed changed
+ * signal to allow the preferences dialog to close (and be deleted) before a
+ * possible switch from docked mode to top-level mode happens. (The switch
+ * would delete the main window, which the preference dialog is a child of
+ * -> BOOM) */
+
+class QDesignerAppearanceOptionsPage : public QObject, public QDesignerOptionsPageInterface
+{
+ Q_OBJECT
+
+public:
+ QDesignerAppearanceOptionsPage(QDesignerFormEditorInterface *core);
+
+ QString name() const;
+ QWidget *createPage(QWidget *parent);
+ virtual void apply();
+ virtual void finish();
+
+signals:
+ void settingsChangedDelayed();
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ QPointer<QDesignerAppearanceOptionsWidget> m_widget;
+ AppearanceOptions m_initialOptions;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_APPEARANCEOPTIONS_H
diff --git a/tools/designer/src/designer/qdesigner_appearanceoptions.ui b/tools/designer/src/designer/qdesigner_appearanceoptions.ui
new file mode 100644
index 0000000000..a5582f2abd
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_appearanceoptions.ui
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AppearanceOptionsWidget</class>
+ <widget class="QWidget" name="AppearanceOptionsWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>325</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="m_uiModeGroupBox">
+ <property name="title">
+ <string>User Interface Mode</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QComboBox" name="m_uiModeCombo"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="FontPanel" name="m_fontPanel"/>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>FontPanel</class>
+ <extends>QGroupBox</extends>
+ <header>fontpanel.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/designer/qdesigner_formwindow.cpp b/tools/designer/src/designer/qdesigner_formwindow.cpp
new file mode 100644
index 0000000000..557db69521
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_formwindow.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_formwindow.h"
+#include "qdesigner_workbench.h"
+#include "formwindowbase_p.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerTaskMenuExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QEvent>
+#include <QtCore/QFile>
+
+#include <QtGui/QAction>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QUndoCommand>
+#include <QtGui/QWindowStateChangeEvent>
+
+QT_BEGIN_NAMESPACE
+
+QDesignerFormWindow::QDesignerFormWindow(QDesignerFormWindowInterface *editor, QDesignerWorkbench *workbench, QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags),
+ m_editor(editor),
+ m_workbench(workbench),
+ m_action(new QAction(this)),
+ m_initialized(false),
+ m_windowTitleInitialized(false)
+{
+ Q_ASSERT(workbench);
+
+ setMaximumSize(0xFFF, 0xFFF);
+ QDesignerFormEditorInterface *core = workbench->core();
+
+ if (m_editor) {
+ m_editor->setParent(this);
+ } else {
+ m_editor = core->formWindowManager()->createFormWindow(this);
+ }
+
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->setMargin(0);
+ l->addWidget(m_editor);
+
+ m_action->setCheckable(true);
+
+ connect(m_editor->commandHistory(), SIGNAL(indexChanged(int)), this, SLOT(updateChanged()));
+ connect(m_editor, SIGNAL(geometryChanged()), this, SLOT(geometryChanged()));
+ qdesigner_internal::FormWindowBase::setupDefaultAction(m_editor);
+}
+
+QDesignerFormWindow::~QDesignerFormWindow()
+{
+ if (workbench())
+ workbench()->removeFormWindow(this);
+}
+
+QAction *QDesignerFormWindow::action() const
+{
+ return m_action;
+}
+
+void QDesignerFormWindow::changeEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::WindowTitleChange:
+ m_action->setText(windowTitle().remove(QLatin1String("[*]")));
+ break;
+ case QEvent::WindowIconChange:
+ m_action->setIcon(windowIcon());
+ break;
+ case QEvent::WindowStateChange: {
+ const QWindowStateChangeEvent *wsce = static_cast<const QWindowStateChangeEvent *>(e);
+ const bool wasMinimized = Qt::WindowMinimized & wsce->oldState();
+ const bool isMinimizedNow = isMinimized();
+ if (wasMinimized != isMinimizedNow )
+ emit minimizationStateChanged(m_editor, isMinimizedNow);
+ }
+ break;
+ default:
+ break;
+ }
+ QWidget::changeEvent(e);
+}
+
+QRect QDesignerFormWindow::geometryHint() const
+{
+ const QPoint point(0, 0);
+ // If we have a container, we want to be just as big.
+ // QMdiSubWindow attempts to resize its children to sizeHint() when switching user interface modes.
+ if (QWidget *mainContainer = m_editor->mainContainer())
+ return QRect(point, mainContainer->size());
+
+ return QRect(point, sizeHint());
+}
+
+QDesignerFormWindowInterface *QDesignerFormWindow::editor() const
+{
+ return m_editor;
+}
+
+QDesignerWorkbench *QDesignerFormWindow::workbench() const
+{
+ return m_workbench;
+}
+
+void QDesignerFormWindow::firstShow()
+{
+ // Set up handling of file name changes and set initial title.
+ if (!m_windowTitleInitialized) {
+ m_windowTitleInitialized = true;
+ if (m_editor) {
+ connect(m_editor, SIGNAL(fileNameChanged(QString)), this, SLOT(updateWindowTitle(QString)));
+ updateWindowTitle(m_editor->fileName());
+ }
+ }
+ show();
+}
+
+int QDesignerFormWindow::getNumberOfUntitledWindows() const
+{
+ const int totalWindows = m_workbench->formWindowCount();
+ if (!totalWindows)
+ return 0;
+
+ int maxUntitled = 0;
+ // Find the number of untitled windows excluding ourselves.
+ // Do not fall for 'untitled.ui', match with modified place holder.
+ // This will cause some problems with i18n, but for now I need the string to be "static"
+ QRegExp rx(QLatin1String("untitled( (\\d+))?\\[\\*\\]"));
+ for (int i = 0; i < totalWindows; ++i) {
+ QDesignerFormWindow *fw = m_workbench->formWindow(i);
+ if (fw != this) {
+ const QString title = m_workbench->formWindow(i)->windowTitle();
+ if (rx.indexIn(title) != -1) {
+ if (maxUntitled == 0)
+ ++maxUntitled;
+ if (rx.numCaptures() > 1) {
+ const QString numberCapture = rx.cap(2);
+ if (!numberCapture.isEmpty())
+ maxUntitled = qMax(numberCapture.toInt(), maxUntitled);
+ }
+ }
+ }
+ }
+ return maxUntitled;
+}
+
+void QDesignerFormWindow::updateWindowTitle(const QString &fileName)
+{
+ if (!m_windowTitleInitialized) {
+ m_windowTitleInitialized = true;
+ if (m_editor)
+ connect(m_editor, SIGNAL(fileNameChanged(QString)), this, SLOT(updateWindowTitle(QString)));
+ }
+
+ QString fileNameTitle;
+ if (fileName.isEmpty()) {
+ fileNameTitle = QLatin1String("untitled");
+ if (const int maxUntitled = getNumberOfUntitledWindows()) {
+ fileNameTitle += QLatin1Char(' ');
+ fileNameTitle += QString::number(maxUntitled + 1);
+ }
+ } else {
+ fileNameTitle = QFileInfo(fileName).fileName();
+ }
+
+ if (const QWidget *mc = m_editor->mainContainer()) {
+ setWindowIcon(mc->windowIcon());
+ setWindowTitle(tr("%1 - %2[*]").arg(mc->windowTitle()).arg(fileNameTitle));
+ } else {
+ setWindowTitle(fileNameTitle);
+ }
+}
+
+void QDesignerFormWindow::closeEvent(QCloseEvent *ev)
+{
+ if (m_editor->isDirty()) {
+ raise();
+ QMessageBox box(QMessageBox::Information, tr("Save Form?"),
+ tr("Do you want to save the changes to this document before closing?"),
+ QMessageBox::Discard | QMessageBox::Cancel | QMessageBox::Save, m_editor);
+ box.setInformativeText(tr("If you don't save, your changes will be lost."));
+ box.setWindowModality(Qt::WindowModal);
+ static_cast<QPushButton *>(box.button(QMessageBox::Save))->setDefault(true);
+
+ switch (box.exec()) {
+ case QMessageBox::Save: {
+ bool ok = workbench()->saveForm(m_editor);
+ ev->setAccepted(ok);
+ m_editor->setDirty(!ok);
+ break;
+ }
+ case QMessageBox::Discard:
+ m_editor->setDirty(false); // Not really necessary, but stops problems if we get close again.
+ ev->accept();
+ break;
+ case QMessageBox::Cancel:
+ ev->ignore();
+ break;
+ }
+ }
+}
+
+void QDesignerFormWindow::updateChanged()
+{
+ // Sometimes called after form window destruction.
+ if (m_editor) {
+ setWindowModified(m_editor->isDirty());
+ updateWindowTitle(m_editor->fileName());
+ }
+}
+
+void QDesignerFormWindow::resizeEvent(QResizeEvent *rev)
+{
+ if(m_initialized) {
+ m_editor->setDirty(true);
+ setWindowModified(true);
+ }
+
+ m_initialized = true;
+ QWidget::resizeEvent(rev);
+}
+
+void QDesignerFormWindow::geometryChanged()
+{
+ // If the form window changes, re-update the geometry of the current widget in the property editor.
+ // Note that in the case of layouts, non-maincontainer widgets must also be updated,
+ // so, do not do it for the main container only
+ const QDesignerFormEditorInterface *core = m_editor->core();
+ QObject *object = core->propertyEditor()->object();
+ if (object == 0 || !object->isWidgetType())
+ return;
+ static const QString geometryProperty = QLatin1String("geometry");
+ const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), object);
+ const int geometryIndex = sheet->indexOf(geometryProperty);
+ if (geometryIndex == -1)
+ return;
+ core->propertyEditor()->setPropertyValue(geometryProperty, sheet->property(geometryIndex));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/qdesigner_formwindow.h b/tools/designer/src/designer/qdesigner_formwindow.h
new file mode 100644
index 0000000000..d9967a2991
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_formwindow.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_FORMWINDOW_H
+#define QDESIGNER_FORMWINDOW_H
+
+#include <QtCore/QPointer>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerWorkbench;
+class QDesignerFormWindowInterface;
+
+class QDesignerFormWindow: public QWidget
+{
+ Q_OBJECT
+public:
+ QDesignerFormWindow(QDesignerFormWindowInterface *formWindow, QDesignerWorkbench *workbench,
+ QWidget *parent = 0, Qt::WindowFlags flags = 0);
+
+ void firstShow();
+
+ virtual ~QDesignerFormWindow();
+
+ QAction *action() const;
+ QDesignerWorkbench *workbench() const;
+ QDesignerFormWindowInterface *editor() const;
+
+ QRect geometryHint() const;
+
+public slots:
+ void updateChanged();
+
+private slots:
+ void updateWindowTitle(const QString &fileName);
+ void geometryChanged();
+
+signals:
+ void minimizationStateChanged(QDesignerFormWindowInterface *formWindow, bool minimized);
+ void triggerAction();
+
+protected:
+ virtual void changeEvent(QEvent *e);
+ virtual void closeEvent(QCloseEvent *ev);
+ virtual void resizeEvent(QResizeEvent* rev);
+
+private:
+ int getNumberOfUntitledWindows() const;
+ QPointer<QDesignerFormWindowInterface> m_editor;
+ QPointer<QDesignerWorkbench> m_workbench;
+ QAction *m_action;
+ bool m_initialized;
+ bool m_windowTitleInitialized;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_FORMWINDOW_H
diff --git a/tools/designer/src/designer/qdesigner_pch.h b/tools/designer/src/designer/qdesigner_pch.h
new file mode 100644
index 0000000000..46f541c56d
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_pch.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if defined __cplusplus
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QSettings>
+#include <QtCore/qdebug.h>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QHeaderView>
+#include <QtGui/QMessageBox>
+#include <QtGui/QVBoxLayout>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+
+#include "qdesigner.h"
+#include "qdesigner_formwindow.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_workbench.h"
+#endif
diff --git a/tools/designer/src/designer/qdesigner_server.cpp b/tools/designer/src/designer/qdesigner_server.cpp
new file mode 100644
index 0000000000..98007ec4b3
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_server.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringList>
+
+#include <QtNetwork/QHostAddress>
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QTcpSocket>
+
+#include "qdesigner.h"
+#include "qdesigner_server.h"
+
+#include <qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+// ### review
+
+QDesignerServer::QDesignerServer(QObject *parent)
+ : QObject(parent)
+{
+ m_socket = 0;
+ m_server = new QTcpServer(this);
+ m_server->listen(QHostAddress::LocalHost, 0);
+ if (m_server->isListening())
+ {
+ connect(m_server, SIGNAL(newConnection()),
+ this, SLOT(handleNewConnection()));
+ }
+}
+
+QDesignerServer::~QDesignerServer()
+{
+}
+
+quint16 QDesignerServer::serverPort() const
+{
+ return m_server ? m_server->serverPort() : 0;
+}
+
+void QDesignerServer::sendOpenRequest(int port, const QStringList &files)
+{
+ QTcpSocket *sSocket = new QTcpSocket();
+ sSocket->connectToHost(QHostAddress::LocalHost, port);
+ if(sSocket->waitForConnected(3000))
+ {
+ foreach(QString file, files)
+ {
+ QFileInfo fi(file);
+ sSocket->write(fi.absoluteFilePath().toUtf8() + '\n');
+ }
+ sSocket->waitForBytesWritten(3000);
+ sSocket->close();
+ }
+ delete sSocket;
+}
+
+void QDesignerServer::readFromClient()
+{
+ QString file = QString();
+ while (m_socket->canReadLine()) {
+ file = QString::fromUtf8(m_socket->readLine());
+ if (!file.isNull()) {
+ file.remove(QLatin1Char('\n'));
+ file.remove(QLatin1Char('\r'));
+ qDesigner->postEvent(qDesigner, new QFileOpenEvent(file));
+ }
+ }
+}
+
+void QDesignerServer::socketClosed()
+{
+ m_socket = 0;
+}
+
+void QDesignerServer::handleNewConnection()
+{
+ // no need for more than one connection
+ if (m_socket == 0) {
+ m_socket = m_server->nextPendingConnection();
+ connect(m_socket, SIGNAL(readyRead()),
+ this, SLOT(readFromClient()));
+ connect(m_socket, SIGNAL(disconnected()),
+ this, SLOT(socketClosed()));
+ }
+}
+
+
+QDesignerClient::QDesignerClient(quint16 port, QObject *parent)
+: QObject(parent)
+{
+ m_socket = new QTcpSocket(this);
+ m_socket->connectToHost(QHostAddress::LocalHost, port);
+ connect(m_socket, SIGNAL(readyRead()),
+ this, SLOT(readFromSocket()));
+
+}
+
+QDesignerClient::~QDesignerClient()
+{
+ m_socket->close();
+ m_socket->flush();
+}
+
+void QDesignerClient::readFromSocket()
+{
+ QString file = QString();
+ while (m_socket->canReadLine()) {
+ QString file = QString::fromUtf8(m_socket->readLine());
+ if (!file.isNull()) {
+ file.remove(QLatin1Char('\n'));
+ file.remove(QLatin1Char('\r'));
+ if (QFile::exists(file))
+ qDesigner->postEvent(qDesigner, new QFileOpenEvent(file));
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/qdesigner_server.h b/tools/designer/src/designer/qdesigner_server.h
new file mode 100644
index 0000000000..482096689b
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_server.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_SERVER_H
+#define QDESIGNER_SERVER_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QTcpServer;
+class QTcpSocket;
+
+class QDesignerServer: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerServer(QObject *parent = 0);
+ virtual ~QDesignerServer();
+
+ quint16 serverPort() const;
+
+ static void sendOpenRequest(int port, const QStringList &files);
+
+private slots:
+ void handleNewConnection();
+ void readFromClient();
+ void socketClosed();
+
+private:
+ QTcpServer *m_server;
+ QTcpSocket *m_socket;
+};
+
+class QDesignerClient: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerClient(quint16 port, QObject *parent = 0);
+ virtual ~QDesignerClient();
+
+private slots:
+ void readFromSocket();
+
+private:
+ QTcpSocket *m_socket;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_SERVER_H
diff --git a/tools/designer/src/designer/qdesigner_settings.cpp b/tools/designer/src/designer/qdesigner_settings.cpp
new file mode 100644
index 0000000000..d9060b1d87
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_settings.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_workbench.h"
+
+#include <abstractformeditor.h>
+#include <abstractsettings_p.h>
+#include <qdesigner_utils_p.h>
+#include <previewmanager_p.h>
+
+#include <QtCore/QVariant>
+#include <QtCore/QDir>
+
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QStyle>
+#include <QtGui/QListView>
+
+#include <QtCore/qdebug.h>
+
+enum { debugSettings = 0 };
+
+QT_BEGIN_NAMESPACE
+
+static const char *newFormShowKey = "newFormDialog/ShowOnStartup";
+
+// Change the version whenever the arrangement changes significantly.
+static const char *mainWindowStateKey = "MainWindowState45";
+static const char *toolBarsStateKey = "ToolBarsState45";
+
+static const char *backupOrgListKey = "backup/fileListOrg";
+static const char *backupBakListKey = "backup/fileListBak";
+static const char *recentFilesListKey = "recentFilesList";
+
+QDesignerSettings::QDesignerSettings(QDesignerFormEditorInterface *core) :
+ qdesigner_internal::QDesignerSharedSettings(core)
+{
+}
+
+void QDesignerSettings::setValue(const QString &key, const QVariant &value)
+{
+ settings()->setValue(key, value);
+}
+
+QVariant QDesignerSettings::value(const QString &key, const QVariant &defaultValue) const
+{
+ return settings()->value(key, defaultValue);
+}
+
+static inline QChar modeChar(UIMode mode)
+{
+ return QLatin1Char(static_cast<char>(mode) + '0');
+}
+
+void QDesignerSettings::saveGeometryFor(const QWidget *w)
+{
+ Q_ASSERT(w && !w->objectName().isEmpty());
+ QDesignerSettingsInterface *s = settings();
+ const bool visible = w->isVisible();
+ if (debugSettings)
+ qDebug() << Q_FUNC_INFO << w << "visible=" << visible;
+ s->beginGroup(w->objectName());
+ s->setValue(QLatin1String("visible"), visible);
+ s->setValue(QLatin1String("geometry"), w->saveGeometry());
+ s->endGroup();
+}
+
+void QDesignerSettings::restoreGeometry(QWidget *w, QRect fallBack) const
+{
+ Q_ASSERT(w && !w->objectName().isEmpty());
+ const QString key = w->objectName();
+ const QByteArray ba(settings()->value(key + QLatin1String("/geometry")).toByteArray());
+ const bool visible = settings()->value(key + QLatin1String("/visible"), true).toBool();
+
+ if (debugSettings)
+ qDebug() << Q_FUNC_INFO << w << fallBack << "visible=" << visible;
+ if (ba.isEmpty()) {
+ /// Apply default geometry, check for null and maximal size
+ if (fallBack.isNull())
+ fallBack = QRect(QPoint(0, 0), w->sizeHint());
+ if (fallBack.size() == QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) {
+ w->setWindowState(w->windowState() | Qt::WindowMaximized);
+ } else {
+ w->move(fallBack.topLeft());
+ w->resize(fallBack.size());
+ }
+ } else {
+ w->restoreGeometry(ba);
+ }
+
+ if (visible)
+ w->show();
+}
+
+QStringList QDesignerSettings::recentFilesList() const
+{
+ return settings()->value(QLatin1String(recentFilesListKey)).toStringList();
+}
+
+void QDesignerSettings::setRecentFilesList(const QStringList &sl)
+{
+ settings()->setValue(QLatin1String(recentFilesListKey), sl);
+}
+
+void QDesignerSettings::setShowNewFormOnStartup(bool showIt)
+{
+ settings()->setValue(QLatin1String(newFormShowKey), showIt);
+}
+
+bool QDesignerSettings::showNewFormOnStartup() const
+{
+ return settings()->value(QLatin1String(newFormShowKey), true).toBool();
+}
+
+QByteArray QDesignerSettings::mainWindowState(UIMode mode) const
+{
+ return settings()->value(QLatin1String(mainWindowStateKey) + modeChar(mode)).toByteArray();
+}
+
+void QDesignerSettings::setMainWindowState(UIMode mode, const QByteArray &mainWindowState)
+{
+ settings()->setValue(QLatin1String(mainWindowStateKey) + modeChar(mode), mainWindowState);
+}
+
+QByteArray QDesignerSettings::toolBarsState(UIMode mode) const
+{
+ QString key = QLatin1String(toolBarsStateKey);
+ key += modeChar(mode);
+ return settings()->value(key).toByteArray();
+}
+
+void QDesignerSettings::setToolBarsState(UIMode mode, const QByteArray &toolBarsState)
+{
+ QString key = QLatin1String(toolBarsStateKey);
+ key += modeChar(mode);
+ settings()->setValue(key, toolBarsState);
+}
+
+void QDesignerSettings::clearBackup()
+{
+ QDesignerSettingsInterface *s = settings();
+ s->remove(QLatin1String(backupOrgListKey));
+ s->remove(QLatin1String(backupBakListKey));
+}
+
+void QDesignerSettings::setBackup(const QMap<QString, QString> &map)
+{
+ const QStringList org = map.keys();
+ const QStringList bak = map.values();
+
+ QDesignerSettingsInterface *s = settings();
+ s->setValue(QLatin1String(backupOrgListKey), org);
+ s->setValue(QLatin1String(backupBakListKey), bak);
+}
+
+QMap<QString, QString> QDesignerSettings::backup() const
+{
+ const QStringList org = settings()->value(QLatin1String(backupOrgListKey), QStringList()).toStringList();
+ const QStringList bak = settings()->value(QLatin1String(backupBakListKey), QStringList()).toStringList();
+
+ QMap<QString, QString> map;
+ const int orgCount = org.count();
+ for (int i = 0; i < orgCount; ++i)
+ map.insert(org.at(i), bak.at(i));
+
+ return map;
+}
+
+void QDesignerSettings::setUiMode(UIMode mode)
+{
+ QDesignerSettingsInterface *s = settings();
+ s->beginGroup(QLatin1String("UI"));
+ s->setValue(QLatin1String("currentMode"), mode);
+ s->endGroup();
+}
+
+UIMode QDesignerSettings::uiMode() const
+{
+#ifdef Q_WS_MAC
+ const UIMode defaultMode = TopLevelMode;
+#else
+ const UIMode defaultMode = DockedMode;
+#endif
+ UIMode uiMode = static_cast<UIMode>(value(QLatin1String("UI/currentMode"), defaultMode).toInt());
+ return uiMode;
+}
+
+void QDesignerSettings::setToolWindowFont(const ToolWindowFontSettings &fontSettings)
+{
+ QDesignerSettingsInterface *s = settings();
+ s->beginGroup(QLatin1String("UI"));
+ s->setValue(QLatin1String("font"), fontSettings.m_font);
+ s->setValue(QLatin1String("useFont"), fontSettings.m_useFont);
+ s->setValue(QLatin1String("writingSystem"), fontSettings.m_writingSystem);
+ s->endGroup();
+}
+
+ToolWindowFontSettings QDesignerSettings::toolWindowFont() const
+{
+ ToolWindowFontSettings fontSettings;
+ fontSettings.m_writingSystem =
+ static_cast<QFontDatabase::WritingSystem>(value(QLatin1String("UI/writingSystem"),
+ QFontDatabase::Any).toInt());
+ fontSettings.m_font = qVariantValue<QFont>(value(QLatin1String("UI/font")));
+ fontSettings.m_useFont =
+ settings()->value(QLatin1String("UI/useFont"), QVariant(false)).toBool();
+ return fontSettings;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/qdesigner_settings.h b/tools/designer/src/designer/qdesigner_settings.h
new file mode 100644
index 0000000000..33c5ca3e55
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_settings.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_SETTINGS_H
+#define QDESIGNER_SETTINGS_H
+
+#include "designer_enums.h"
+#include <shared_settings_p.h>
+#include <QtCore/QMap>
+#include <QtCore/QRect>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerSettingsInterface;
+struct ToolWindowFontSettings;
+
+class QDesignerSettings : public qdesigner_internal::QDesignerSharedSettings
+{
+public:
+ QDesignerSettings(QDesignerFormEditorInterface *core);
+
+ void setValue(const QString &key, const QVariant &value);
+ QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
+
+ void restoreGeometry(QWidget *w, QRect fallBack = QRect()) const;
+ void saveGeometryFor(const QWidget *w);
+
+ QStringList recentFilesList() const;
+ void setRecentFilesList(const QStringList &list);
+
+ void setShowNewFormOnStartup(bool showIt);
+ bool showNewFormOnStartup() const;
+
+ void setUiMode(UIMode mode);
+ UIMode uiMode() const;
+
+ void setToolWindowFont(const ToolWindowFontSettings &fontSettings);
+ ToolWindowFontSettings toolWindowFont() const;
+
+ QByteArray mainWindowState(UIMode mode) const;
+ void setMainWindowState(UIMode mode, const QByteArray &mainWindowState);
+
+ QByteArray toolBarsState(UIMode mode) const;
+ void setToolBarsState(UIMode mode, const QByteArray &mainWindowState);
+
+ void clearBackup();
+ void setBackup(const QMap<QString, QString> &map);
+ QMap<QString, QString> backup() const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_SETTINGS_H
diff --git a/tools/designer/src/designer/qdesigner_toolwindow.cpp b/tools/designer/src/designer/qdesigner_toolwindow.cpp
new file mode 100644
index 0000000000..c850ed64e1
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_toolwindow.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_workbench.h"
+
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerActionEditorInterface>
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+#include <QtDesigner/QDesignerComponents>
+
+#include <QtCore/QEvent>
+#include <QtCore/QDebug>
+#include <QtGui/QAction>
+#include <QtGui/QCloseEvent>
+
+enum { debugToolWindow = 0 };
+
+QT_BEGIN_NAMESPACE
+
+// ---------------- QDesignerToolWindowFontSettings
+ToolWindowFontSettings::ToolWindowFontSettings() :
+ m_writingSystem(QFontDatabase::Any),
+ m_useFont(false)
+{
+}
+
+bool ToolWindowFontSettings::equals(const ToolWindowFontSettings &rhs) const
+{
+ return m_useFont == rhs.m_useFont &&
+ m_writingSystem == rhs.m_writingSystem &&
+ m_font == rhs.m_font;
+}
+
+// ---------------- QDesignerToolWindow
+QDesignerToolWindow::QDesignerToolWindow(QDesignerWorkbench *workbench,
+ QWidget *w,
+ const QString &objectName,
+ const QString &title,
+ const QString &actionObjectName,
+ Qt::DockWidgetArea dockAreaHint,
+ QWidget *parent,
+ Qt::WindowFlags flags) :
+ MainWindowBase(parent, flags),
+ m_dockAreaHint(dockAreaHint),
+ m_workbench(workbench),
+ m_action(new QAction(this))
+{
+ setObjectName(objectName);
+ setCentralWidget(w);
+
+ setWindowTitle(title);
+
+ m_action->setObjectName(actionObjectName);
+ m_action->setShortcutContext(Qt::ApplicationShortcut);
+ m_action->setText(title);
+ m_action->setCheckable(true);
+ connect(m_action, SIGNAL(triggered(bool)), this, SLOT(showMe(bool)));
+}
+
+void QDesignerToolWindow::showMe(bool v)
+{
+ // Access the QMdiSubWindow in MDI mode.
+ if (QWidget *target = m_workbench->mode() == DockedMode ? parentWidget() : this) {
+ if (v)
+ target->setWindowState(target->windowState() & ~Qt::WindowMinimized);
+ target->setVisible(v);
+ }
+}
+
+void QDesignerToolWindow::showEvent(QShowEvent *e)
+{
+ Q_UNUSED(e);
+
+ bool blocked = m_action->blockSignals(true);
+ m_action->setChecked(true);
+ m_action->blockSignals(blocked);
+}
+
+void QDesignerToolWindow::hideEvent(QHideEvent *e)
+{
+ Q_UNUSED(e);
+
+ bool blocked = m_action->blockSignals(true);
+ m_action->setChecked(false);
+ m_action->blockSignals(blocked);
+}
+
+QAction *QDesignerToolWindow::action() const
+{
+ return m_action;
+}
+
+void QDesignerToolWindow::changeEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::WindowTitleChange:
+ m_action->setText(windowTitle());
+ break;
+ case QEvent::WindowIconChange:
+ m_action->setIcon(windowIcon());
+ break;
+ default:
+ break;
+ }
+ QMainWindow::changeEvent(e);
+}
+
+QDesignerWorkbench *QDesignerToolWindow::workbench() const
+{
+ return m_workbench;
+}
+
+QRect QDesignerToolWindow::geometryHint() const
+{
+ return QRect();
+}
+
+QRect QDesignerToolWindow::availableToolWindowGeometry() const
+{
+ return m_workbench->availableGeometry();
+}
+
+// ---------------------- PropertyEditorToolWindow
+
+static inline QWidget *createPropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+ QDesignerPropertyEditorInterface *widget = QDesignerComponents::createPropertyEditor(core, parent);
+ core->setPropertyEditor(widget);
+ return widget;
+}
+
+class PropertyEditorToolWindow : public QDesignerToolWindow
+{
+public:
+ explicit PropertyEditorToolWindow(QDesignerWorkbench *workbench);
+
+ virtual QRect geometryHint() const;
+
+protected:
+ virtual void showEvent(QShowEvent *event);
+};
+
+PropertyEditorToolWindow::PropertyEditorToolWindow(QDesignerWorkbench *workbench) :
+ QDesignerToolWindow(workbench,
+ createPropertyEditor(workbench->core()),
+ QLatin1String("qt_designer_propertyeditor"),
+ QDesignerToolWindow::tr("Property Editor"),
+ QLatin1String("__qt_property_editor_action"),
+ Qt::RightDockWidgetArea)
+{
+ action()->setShortcut(Qt::CTRL + Qt::Key_I);
+
+}
+
+QRect PropertyEditorToolWindow::geometryHint() const
+{
+ const QRect g = availableToolWindowGeometry();
+ const int margin = workbench()->marginHint();
+ const int spacing = 40;
+ const QSize sz(g.width() * 1/4, g.height() * 4/6);
+
+ const QRect rc = QRect((g.right() + 1 - sz.width() - margin),
+ (g.top() + margin + g.height() * 1/6) + spacing,
+ sz.width(), sz.height());
+ if (debugToolWindow)
+ qDebug() << Q_FUNC_INFO << rc;
+ return rc;
+}
+
+void PropertyEditorToolWindow::showEvent(QShowEvent *event)
+{
+ if (QDesignerPropertyEditorInterface *e = workbench()->core()->propertyEditor()) {
+ // workaround to update the propertyeditor when it is not visible!
+ e->setObject(e->object()); // ### remove me
+ }
+
+ QDesignerToolWindow::showEvent(event);
+}
+
+// ---------------------- ActionEditorToolWindow
+
+static inline QWidget *createActionEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+ QDesignerActionEditorInterface *widget = QDesignerComponents::createActionEditor(core, parent);
+ core->setActionEditor(widget);
+ return widget;
+}
+
+class ActionEditorToolWindow: public QDesignerToolWindow
+{
+public:
+ explicit ActionEditorToolWindow(QDesignerWorkbench *workbench);
+
+ virtual QRect geometryHint() const;
+};
+
+ActionEditorToolWindow::ActionEditorToolWindow(QDesignerWorkbench *workbench) :
+ QDesignerToolWindow(workbench,
+ createActionEditor(workbench->core()),
+ QLatin1String("qt_designer_actioneditor"),
+ QDesignerToolWindow::tr("Action Editor"),
+ QLatin1String("__qt_action_editor_tool_action"),
+ Qt::RightDockWidgetArea)
+{
+}
+
+QRect ActionEditorToolWindow::geometryHint() const
+{
+ const QRect g = availableToolWindowGeometry();
+ const int margin = workbench()->marginHint();
+
+ const QSize sz(g.width() * 1/4, g.height() * 1/6);
+
+ const QRect rc = QRect((g.right() + 1 - sz.width() - margin),
+ g.top() + margin,
+ sz.width(), sz.height());
+ if (debugToolWindow)
+ qDebug() << Q_FUNC_INFO << rc;
+ return rc;
+}
+
+// ---------------------- ObjectInspectorToolWindow
+
+static inline QWidget *createObjectInspector(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+ QDesignerObjectInspectorInterface *widget = QDesignerComponents::createObjectInspector(core, parent);
+ core->setObjectInspector(widget);
+ return widget;
+}
+
+class ObjectInspectorToolWindow: public QDesignerToolWindow
+{
+public:
+ explicit ObjectInspectorToolWindow(QDesignerWorkbench *workbench);
+
+ virtual QRect geometryHint() const;
+};
+
+ObjectInspectorToolWindow::ObjectInspectorToolWindow(QDesignerWorkbench *workbench) :
+ QDesignerToolWindow(workbench,
+ createObjectInspector(workbench->core()),
+ QLatin1String("qt_designer_objectinspector"),
+ QDesignerToolWindow::tr("Object Inspector"),
+ QLatin1String("__qt_object_inspector_tool_action"),
+ Qt::RightDockWidgetArea)
+{
+}
+
+QRect ObjectInspectorToolWindow::geometryHint() const
+{
+ const QRect g = availableToolWindowGeometry();
+ const int margin = workbench()->marginHint();
+
+ const QSize sz(g.width() * 1/4, g.height() * 1/6);
+
+ const QRect rc = QRect((g.right() + 1 - sz.width() - margin),
+ g.top() + margin,
+ sz.width(), sz.height());
+ if (debugToolWindow)
+ qDebug() << Q_FUNC_INFO << rc;
+ return rc;
+}
+
+// ---------------------- ResourceEditorToolWindow
+
+class ResourceEditorToolWindow: public QDesignerToolWindow
+{
+public:
+ explicit ResourceEditorToolWindow(QDesignerWorkbench *workbench);
+
+ virtual QRect geometryHint() const;
+};
+
+ResourceEditorToolWindow::ResourceEditorToolWindow(QDesignerWorkbench *workbench) :
+ QDesignerToolWindow(workbench,
+ QDesignerComponents::createResourceEditor(workbench->core(), 0),
+ QLatin1String("qt_designer_resourceeditor"),
+ QDesignerToolWindow::tr("Resource Browser"),
+ QLatin1String("__qt_resource_editor_tool_action"),
+ Qt::RightDockWidgetArea)
+{
+}
+
+QRect ResourceEditorToolWindow::geometryHint() const
+{
+ const QRect g = availableToolWindowGeometry();
+ const int margin = workbench()->marginHint();
+
+ const QSize sz(g.width() * 1/3, g.height() * 1/6);
+ QRect r(QPoint(0, 0), sz);
+ r.moveCenter(g.center());
+ r.moveBottom(g.bottom() - margin);
+ if (debugToolWindow)
+ qDebug() << Q_FUNC_INFO << r;
+ return r;
+}
+
+// ---------------------- SignalSlotEditorToolWindow
+
+class SignalSlotEditorToolWindow: public QDesignerToolWindow
+{
+public:
+ explicit SignalSlotEditorToolWindow(QDesignerWorkbench *workbench);
+
+ virtual QRect geometryHint() const;
+};
+
+SignalSlotEditorToolWindow::SignalSlotEditorToolWindow(QDesignerWorkbench *workbench) :
+ QDesignerToolWindow(workbench,
+ QDesignerComponents::createSignalSlotEditor(workbench->core(), 0),
+ QLatin1String("qt_designer_signalsloteditor"),
+ QDesignerToolWindow::tr("Signal/Slot Editor"),
+ QLatin1String("__qt_signal_slot_editor_tool_action"),
+ Qt::RightDockWidgetArea)
+{
+}
+
+QRect SignalSlotEditorToolWindow::geometryHint() const
+{
+ const QRect g = availableToolWindowGeometry();
+ const int margin = workbench()->marginHint();
+
+ const QSize sz(g.width() * 1/3, g.height() * 1/6);
+ QRect r(QPoint(0, 0), sz);
+ r.moveCenter(g.center());
+ r.moveTop(margin + g.top());
+ if (debugToolWindow)
+ qDebug() << Q_FUNC_INFO << r;
+ return r;
+}
+
+// ---------------------- WidgetBoxToolWindow
+
+static inline QWidget *createWidgetBox(QDesignerFormEditorInterface *core, QWidget *parent = 0)
+{
+ QDesignerWidgetBoxInterface *widget = QDesignerComponents::createWidgetBox(core, parent);
+ core->setWidgetBox(widget);
+ return widget;
+}
+
+class WidgetBoxToolWindow: public QDesignerToolWindow
+{
+public:
+ explicit WidgetBoxToolWindow(QDesignerWorkbench *workbench);
+
+ virtual QRect geometryHint() const;
+};
+
+WidgetBoxToolWindow::WidgetBoxToolWindow(QDesignerWorkbench *workbench) :
+ QDesignerToolWindow(workbench,
+ createWidgetBox(workbench->core()),
+ QLatin1String("qt_designer_widgetbox"),
+ QDesignerToolWindow::tr("Widget Box"),
+ QLatin1String("__qt_widget_box_tool_action"),
+ Qt::LeftDockWidgetArea)
+{
+}
+
+QRect WidgetBoxToolWindow::geometryHint() const
+{
+ const QRect g = availableToolWindowGeometry();
+ const int margin = workbench()->marginHint();
+ const QRect rc = QRect(g.left() + margin,
+ g.top() + margin,
+ g.width() * 1/4, g.height() * 5/6);
+ if (debugToolWindow)
+ qDebug() << Q_FUNC_INFO << rc;
+ return rc;
+}
+
+// -- Factory
+QDesignerToolWindow *QDesignerToolWindow::createStandardToolWindow(StandardToolWindow which,
+ QDesignerWorkbench *workbench)
+{
+ switch (which) {
+ case ActionEditor:
+ return new ActionEditorToolWindow(workbench);
+ case ResourceEditor:
+ return new ResourceEditorToolWindow(workbench);
+ case SignalSlotEditor:
+ return new SignalSlotEditorToolWindow(workbench);
+ case PropertyEditor:
+ return new PropertyEditorToolWindow(workbench);
+ case ObjectInspector:
+ return new ObjectInspectorToolWindow(workbench);
+ case WidgetBox:
+ return new WidgetBoxToolWindow(workbench);
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/qdesigner_toolwindow.h b/tools/designer/src/designer/qdesigner_toolwindow.h
new file mode 100644
index 0000000000..cf3942df7c
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_toolwindow.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_TOOLWINDOW_H
+#define QDESIGNER_TOOLWINDOW_H
+
+#include "mainwindow.h"
+
+#include <QtCore/QPointer>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+struct ToolWindowFontSettings {
+ ToolWindowFontSettings();
+ bool equals(const ToolWindowFontSettings &) const;
+
+ QFont m_font;
+ QFontDatabase::WritingSystem m_writingSystem;
+ bool m_useFont;
+};
+
+inline bool operator==(const ToolWindowFontSettings &tw1, const ToolWindowFontSettings &tw2)
+{
+ return tw1.equals(tw2);
+}
+
+inline bool operator!=(const ToolWindowFontSettings &tw1, const ToolWindowFontSettings &tw2)
+{
+ return !tw1.equals(tw2);
+}
+
+class QDesignerWorkbench;
+
+/* A tool window with an action that activates it. Note that in toplevel mode,
+ * the Widget box is a tool window as well as the applications' main window,
+ * So, we need to inherit from MainWindowBase. */
+
+class QDesignerToolWindow : public MainWindowBase
+{
+ Q_OBJECT
+protected:
+ explicit QDesignerToolWindow(QDesignerWorkbench *workbench,
+ QWidget *w,
+ const QString &objectName,
+ const QString &title,
+ const QString &actionObjectName,
+ Qt::DockWidgetArea dockAreaHint,
+ QWidget *parent = 0,
+ Qt::WindowFlags flags = Qt::Window);
+
+public:
+ // Note: The order influences the dock widget position.
+ enum StandardToolWindow { WidgetBox, ObjectInspector, PropertyEditor,
+ ResourceEditor, ActionEditor, SignalSlotEditor,
+ StandardToolWindowCount };
+
+ static QDesignerToolWindow *createStandardToolWindow(StandardToolWindow which, QDesignerWorkbench *workbench);
+
+ QDesignerWorkbench *workbench() const;
+ QAction *action() const;
+
+ Qt::DockWidgetArea dockWidgetAreaHint() const { return m_dockAreaHint; }
+ virtual QRect geometryHint() const;
+
+private slots:
+ void showMe(bool);
+
+protected:
+ virtual void showEvent(QShowEvent *e);
+ virtual void hideEvent(QHideEvent *e);
+ virtual void changeEvent(QEvent *e);
+
+ QRect availableToolWindowGeometry() const;
+
+private:
+ const Qt::DockWidgetArea m_dockAreaHint;
+ QDesignerWorkbench *m_workbench;
+ QAction *m_action;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TOOLWINDOW_H
diff --git a/tools/designer/src/designer/qdesigner_workbench.cpp b/tools/designer/src/designer/qdesigner_workbench.cpp
new file mode 100644
index 0000000000..7ab3e9447b
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_workbench.cpp
@@ -0,0 +1,1096 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_workbench.h"
+#include "qdesigner.h"
+#include "qdesigner_actions.h"
+#include "qdesigner_appearanceoptions.h"
+#include "qdesigner_settings.h"
+#include "qdesigner_toolwindow.h"
+#include "qdesigner_formwindow.h"
+#include "appfontdialog.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerFormEditorPluginInterface>
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+
+#include <QtDesigner/QDesignerComponents>
+#include <QtDesigner/private/qdesigner_integration_p.h>
+#include <QtDesigner/private/pluginmanager_p.h>
+#include <QtDesigner/private/formwindowbase_p.h>
+#include <QtDesigner/private/actioneditor_p.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QUrl>
+#include <QtCore/QTimer>
+#include <QtCore/QPluginLoader>
+#include <QtCore/qdebug.h>
+
+#include <QtGui/QActionGroup>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QDockWidget>
+#include <QtGui/QMenu>
+#include <QtGui/QMenuBar>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QToolBar>
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+static const char *appFontPrefixC = "AppFonts";
+
+typedef QList<QAction *> ActionList;
+
+static QMdiSubWindow *mdiSubWindowOf(const QWidget *w)
+{
+ QMdiSubWindow *rc = qobject_cast<QMdiSubWindow *>(w->parentWidget());
+ Q_ASSERT(rc);
+ return rc;
+}
+
+static QDockWidget *dockWidgetOf(const QWidget *w)
+{
+ for (QWidget *parentWidget = w->parentWidget(); parentWidget ; parentWidget = parentWidget->parentWidget()) {
+ if (QDockWidget *dw = qobject_cast<QDockWidget *>(parentWidget)) {
+ return dw;
+ }
+ }
+ Q_ASSERT("Dock widget not found");
+ return 0;
+}
+
+// ------------ QDesignerWorkbench::Position
+QDesignerWorkbench::Position::Position(const QMdiSubWindow *mdiSubWindow, const QPoint &mdiAreaOffset) :
+ m_minimized(mdiSubWindow->isShaded()),
+ m_position(mdiSubWindow->pos() + mdiAreaOffset)
+{
+}
+
+QDesignerWorkbench::Position::Position(const QDockWidget *dockWidget) :
+ m_minimized(dockWidget->isMinimized()),
+ m_position(dockWidget->pos())
+{
+}
+
+QDesignerWorkbench::Position::Position(const QWidget *topLevelWindow, const QPoint &desktopTopLeft)
+{
+ const QWidget *window =topLevelWindow->window ();
+ Q_ASSERT(window);
+ m_minimized = window->isMinimized();
+ m_position = window->pos() - desktopTopLeft;
+}
+
+void QDesignerWorkbench::Position::applyTo(QMdiSubWindow *mdiSubWindow,
+ const QPoint &mdiAreaOffset) const
+{
+ // QMdiSubWindow attempts to resize its children to sizeHint() when switching user interface modes.
+ // Restore old size
+ const QPoint mdiAreaPos = QPoint(qMax(0, m_position.x() - mdiAreaOffset.x()),
+ qMax(0, m_position.y() - mdiAreaOffset.y()));
+ mdiSubWindow->move(mdiAreaPos);
+ const QSize decorationSize = mdiSubWindow->size() - mdiSubWindow->contentsRect().size();
+ mdiSubWindow->resize(mdiSubWindow->widget()->size() + decorationSize);
+ mdiSubWindow->show();
+ if (m_minimized) {
+ mdiSubWindow->showShaded();
+ }
+}
+
+void QDesignerWorkbench::Position::applyTo(QWidget *topLevelWindow, const QPoint &desktopTopLeft) const
+{
+ QWidget *window = topLevelWindow->window ();
+ const QPoint newPos = m_position + desktopTopLeft;
+ window->move(newPos);
+ if ( m_minimized) {
+ topLevelWindow->showMinimized();
+ } else {
+ topLevelWindow->show();
+ }
+}
+
+void QDesignerWorkbench::Position::applyTo(QDockWidget *dockWidget) const
+{
+ dockWidget->widget()->setVisible(true);
+ dockWidget->setVisible(!m_minimized);
+}
+
+static inline void addActionsToMenu(QMenu *m, const ActionList &al)
+{
+ const ActionList::const_iterator cend = al.constEnd();
+ for (ActionList::const_iterator it = al.constBegin(); it != cend; ++it)
+ m->addAction(*it);
+}
+
+static inline QMenu *addMenu(QMenuBar *mb, const QString &title, const ActionList &al)
+{
+ QMenu *rc = mb->addMenu(title);
+ addActionsToMenu(rc, al);
+ return rc;
+}
+
+// -------- QDesignerWorkbench
+
+QDesignerWorkbench::QDesignerWorkbench() :
+ m_core(QDesignerComponents::createFormEditor(this)),
+ m_windowActions(new QActionGroup(this)),
+ m_globalMenuBar(new QMenuBar),
+ m_mode(NeutralMode),
+ m_dockedMainWindow(0),
+ m_state(StateInitializing)
+{
+ QDesignerSettings settings(m_core);
+
+ (void) QDesignerComponents::createTaskMenu(core(), this);
+
+ initializeCorePlugins();
+ QDesignerComponents::initializePlugins(core());
+ m_actionManager = new QDesignerActions(this); // accesses plugin components
+
+ m_windowActions->setExclusive(true);
+ connect(m_windowActions, SIGNAL(triggered(QAction*)), this, SLOT(formWindowActionTriggered(QAction*)));
+
+ // Build main menu bar
+ addMenu(m_globalMenuBar, tr("&File"), m_actionManager->fileActions()->actions());
+
+ QMenu *editMenu = addMenu(m_globalMenuBar, tr("Edit"), m_actionManager->editActions()->actions());
+ editMenu->addSeparator();
+ addActionsToMenu(editMenu, m_actionManager->toolActions()->actions());
+
+ QMenu *formMenu = addMenu(m_globalMenuBar, tr("F&orm"), m_actionManager->formActions()->actions());
+ QMenu *previewSubMenu = new QMenu(tr("Preview in"), formMenu);
+ formMenu->insertMenu(m_actionManager->previewFormAction(), previewSubMenu);
+ addActionsToMenu(previewSubMenu, m_actionManager->styleActions()->actions());
+
+ QMenu *viewMenu = m_globalMenuBar->addMenu(tr("&View"));
+
+ addMenu(m_globalMenuBar, tr("&Settings"), m_actionManager->settingsActions()->actions());
+
+ m_windowMenu = addMenu(m_globalMenuBar, tr("&Window"), m_actionManager->windowActions()->actions());
+
+ addMenu(m_globalMenuBar, tr("&Help"), m_actionManager->helpActions()->actions());
+
+ // Add the tools in view menu order
+ QActionGroup *viewActions = new QActionGroup(this);
+ viewActions->setExclusive(false);
+
+ for (int i = 0; i < QDesignerToolWindow::StandardToolWindowCount; i++) {
+ QDesignerToolWindow *toolWindow = QDesignerToolWindow::createStandardToolWindow(static_cast< QDesignerToolWindow::StandardToolWindow>(i), this);
+ m_toolWindows.push_back(toolWindow);
+ if (QAction *action = toolWindow->action()) {
+ viewMenu->addAction(action);
+ viewActions->addAction(action);
+ }
+ // The widget box becomes the main window in top level mode
+ if (i == QDesignerToolWindow::WidgetBox)
+ connect(toolWindow, SIGNAL(closeEventReceived(QCloseEvent*)), this, SLOT(handleCloseEvent(QCloseEvent*)));
+ }
+ // Integration
+ m_integration = new qdesigner_internal::QDesignerIntegration(m_core, this);
+ connect(m_integration, SIGNAL(helpRequested(QString,QString)), m_actionManager, SLOT(helpRequested(QString,QString)));
+
+ // remaining view options (config toolbars)
+ viewMenu->addSeparator();
+ m_toolbarMenu = viewMenu->addMenu(tr("Toolbars"));
+
+ emit initialized();
+
+ connect(m_core->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(updateWindowMenu(QDesignerFormWindowInterface*)));
+
+
+ { // Add application specific options pages
+ QDesignerAppearanceOptionsPage *appearanceOptions = new QDesignerAppearanceOptionsPage(m_core);
+ connect(appearanceOptions, SIGNAL(settingsChangedDelayed()), this, SLOT(restoreUISettings()));
+ QList<QDesignerOptionsPageInterface*> optionsPages = m_core->optionsPages();
+ optionsPages.push_front(appearanceOptions);
+ m_core->setOptionsPages(optionsPages);
+ }
+
+ restoreUISettings();
+ AppFontWidget::restore(m_core->settingsManager(), QLatin1String(appFontPrefixC));
+ m_state = StateUp;
+}
+
+QDesignerWorkbench::~QDesignerWorkbench()
+{
+ switch (m_mode) {
+ case NeutralMode:
+ case DockedMode:
+ qDeleteAll(m_toolWindows);
+ break;
+ case TopLevelMode: // Everything parented here
+ delete widgetBoxToolWindow();
+ break;
+ }
+}
+
+void QDesignerWorkbench::saveGeometriesForModeChange()
+{
+ m_Positions.clear();
+ switch (m_mode) {
+ case NeutralMode:
+ break;
+ case TopLevelMode: {
+ const QPoint desktopOffset = QApplication::desktop()->availableGeometry().topLeft();
+ foreach (QDesignerToolWindow *tw, m_toolWindows)
+ m_Positions.insert(tw, Position(tw, desktopOffset));
+ foreach (QDesignerFormWindow *fw, m_formWindows) {
+ m_Positions.insert(fw, Position(fw, desktopOffset));
+ }
+ }
+ break;
+ case DockedMode: {
+ const QPoint mdiAreaOffset = m_dockedMainWindow->mdiArea()->pos();
+ foreach (QDesignerToolWindow *tw, m_toolWindows) {
+ m_Positions.insert(tw, Position(dockWidgetOf(tw)));
+ }
+ foreach (QDesignerFormWindow *fw, m_formWindows) {
+ m_Positions.insert(fw, Position(mdiSubWindowOf(fw), mdiAreaOffset));
+ }
+ }
+ break;
+ }
+}
+
+UIMode QDesignerWorkbench::mode() const
+{
+ return m_mode;
+}
+
+void QDesignerWorkbench::addFormWindow(QDesignerFormWindow *formWindow)
+{
+ // ### Q_ASSERT(formWindow->windowTitle().isEmpty() == false);
+
+ m_formWindows.append(formWindow);
+
+
+ m_actionManager->setWindowListSeparatorVisible(true);
+
+ if (QAction *action = formWindow->action()) {
+ m_windowActions->addAction(action);
+ m_windowMenu->addAction(action);
+ action->setChecked(true);
+ }
+
+ m_actionManager->minimizeAction()->setEnabled(true);
+ m_actionManager->minimizeAction()->setChecked(false);
+ connect(formWindow, SIGNAL(minimizationStateChanged(QDesignerFormWindowInterface *, bool)),
+ this, SLOT(minimizationStateChanged(QDesignerFormWindowInterface *, bool)));
+
+ m_actionManager->editWidgets()->trigger();
+}
+
+Qt::WindowFlags QDesignerWorkbench::magicalWindowFlags(const QWidget *widgetForFlags) const
+{
+ switch (m_mode) {
+ case TopLevelMode: {
+#ifdef Q_WS_MAC
+ if (qobject_cast<const QDesignerToolWindow *>(widgetForFlags))
+ return Qt::Tool;
+#else
+ Q_UNUSED(widgetForFlags);
+#endif
+ return Qt::Window;
+ }
+ case DockedMode:
+ return Qt::Window | Qt::WindowShadeButtonHint | Qt::WindowSystemMenuHint | Qt::WindowTitleHint;
+ case NeutralMode:
+ return Qt::Window;
+ default:
+ Q_ASSERT(0);
+ return 0;
+ }
+}
+
+QWidget *QDesignerWorkbench::magicalParent(const QWidget *w) const
+{
+ switch (m_mode) {
+ case TopLevelMode: {
+ // Use widget box as parent for all windows except self. This will
+ // result in having just one entry in the MS Windows task bar.
+ QWidget *widgetBoxWrapper = widgetBoxToolWindow();
+ return w == widgetBoxWrapper ? 0 : widgetBoxWrapper;
+ }
+ case DockedMode:
+ return m_dockedMainWindow->mdiArea();
+ case NeutralMode:
+ return 0;
+ default:
+ Q_ASSERT(0);
+ return 0;
+ }
+}
+
+void QDesignerWorkbench::switchToNeutralMode()
+{
+ QDesignerSettings settings(m_core);
+ saveGeometries(settings);
+ saveGeometriesForModeChange();
+
+ if (m_mode == TopLevelMode) {
+ delete m_topLevelData.toolbarManager;
+ m_topLevelData.toolbarManager = 0;
+ qDeleteAll(m_topLevelData.toolbars);
+ m_topLevelData.toolbars.clear();
+ }
+
+ m_mode = NeutralMode;
+
+ foreach (QDesignerToolWindow *tw, m_toolWindows) {
+ tw->setCloseEventPolicy(MainWindowBase::AcceptCloseEvents);
+ tw->setParent(0);
+ }
+
+ foreach (QDesignerFormWindow *fw, m_formWindows) {
+ fw->setParent(0);
+ fw->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ }
+
+#ifndef Q_WS_MAC
+ m_globalMenuBar->setParent(0);
+#endif
+
+ m_core->setTopLevel(0);
+ qDesigner->setMainWindow(0);
+
+ delete m_dockedMainWindow;
+ m_dockedMainWindow = 0;
+}
+
+void QDesignerWorkbench::switchToDockedMode()
+{
+ if (m_mode == DockedMode)
+ return;
+
+ switchToNeutralMode();
+
+ m_mode = DockedMode;
+ const QDesignerSettings settings(m_core);
+ m_dockedMainWindow = new DockedMainWindow(this, m_toolbarMenu, m_toolWindows);
+ m_dockedMainWindow->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal);
+ connect(m_dockedMainWindow, SIGNAL(closeEventReceived(QCloseEvent*)), this, SLOT(handleCloseEvent(QCloseEvent*)));
+ connect(m_dockedMainWindow, SIGNAL(fileDropped(QString)), this, SLOT(slotFileDropped(QString)));
+ connect(m_dockedMainWindow, SIGNAL(formWindowActivated(QDesignerFormWindow*)), this, SLOT(slotFormWindowActivated(QDesignerFormWindow*)));
+ m_dockedMainWindow->restoreSettings(settings, m_dockedMainWindow->addToolWindows(m_toolWindows), desktopGeometry());
+
+ m_core->setTopLevel(m_dockedMainWindow);
+
+#ifndef Q_WS_MAC
+ m_dockedMainWindow->setMenuBar(m_globalMenuBar);
+ m_globalMenuBar->show();
+#endif
+ qDesigner->setMainWindow(m_dockedMainWindow);
+
+ foreach (QDesignerFormWindow *fw, m_formWindows) {
+ QMdiSubWindow *subwin = m_dockedMainWindow->createMdiSubWindow(fw, magicalWindowFlags(fw),
+ m_actionManager->closeFormAction()->shortcut());
+ subwin->hide();
+ if (QWidget *mainContainer = fw->editor()->mainContainer())
+ resizeForm(fw, mainContainer);
+ }
+
+ m_actionManager->setBringAllToFrontVisible(false);
+ m_dockedMainWindow->show();
+ // Trigger adjustMDIFormPositions() delayed as viewport size is not yet known.
+
+ if (m_state != StateInitializing)
+ QMetaObject::invokeMethod(this, "adjustMDIFormPositions", Qt::QueuedConnection);
+}
+
+void QDesignerWorkbench::adjustMDIFormPositions()
+{
+ const QPoint mdiAreaOffset = m_dockedMainWindow->mdiArea()->pos();
+
+ foreach (QDesignerFormWindow *fw, m_formWindows) {
+ const PositionMap::const_iterator pit = m_Positions.constFind(fw);
+ if (pit != m_Positions.constEnd())
+ pit->applyTo(mdiSubWindowOf(fw), mdiAreaOffset);
+ }
+}
+
+void QDesignerWorkbench::switchToTopLevelMode()
+{
+ if (m_mode == TopLevelMode)
+ return;
+
+ // make sure that the widgetbox is visible if it is different from neutral.
+ QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow();
+ Q_ASSERT(widgetBoxWrapper);
+ if (!widgetBoxWrapper->action()->isChecked())
+ widgetBoxWrapper->action()->trigger();
+
+ switchToNeutralMode();
+ const QPoint desktopOffset = desktopGeometry().topLeft();
+ m_mode = TopLevelMode;
+
+ // The widget box is special, it gets the menubar and gets to be the main widget.
+
+ m_core->setTopLevel(widgetBoxWrapper);
+#ifndef Q_WS_MAC
+ widgetBoxWrapper->setMenuBar(m_globalMenuBar);
+ widgetBoxWrapper->action()->setVisible(false);
+ widgetBoxWrapper->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal);
+ qDesigner->setMainWindow(widgetBoxWrapper);
+ widgetBoxWrapper->setWindowTitle(MainWindowBase::mainWindowTitle());
+#endif
+
+ const QDesignerSettings settings(m_core);
+ m_topLevelData.toolbars = MainWindowBase::createToolBars(m_actionManager, false);
+ m_topLevelData.toolbarManager = new ToolBarManager(widgetBoxWrapper, widgetBoxWrapper,
+ m_toolbarMenu, m_actionManager,
+ m_topLevelData.toolbars, m_toolWindows);
+ const int toolBarCount = m_topLevelData.toolbars.size();
+ for (int i = 0; i < toolBarCount; i++) {
+ widgetBoxWrapper->addToolBar(m_topLevelData.toolbars.at(i));
+ if (i == 3)
+ widgetBoxWrapper->insertToolBarBreak(m_topLevelData.toolbars.at(i));
+ }
+ m_topLevelData.toolbarManager->restoreState(settings.toolBarsState(m_mode), MainWindowBase::settingsVersion());
+ widgetBoxWrapper->restoreState(settings.mainWindowState(m_mode), MainWindowBase::settingsVersion());
+
+ bool found_visible_window = false;
+ foreach (QDesignerToolWindow *tw, m_toolWindows) {
+ tw->setParent(magicalParent(tw), magicalWindowFlags(tw));
+ settings.restoreGeometry(tw, tw->geometryHint());
+ tw->action()->setChecked(tw->isVisible());
+ found_visible_window |= tw->isVisible();
+ }
+
+ if (!widgetBoxWrapper->action()->isChecked())
+ widgetBoxWrapper->action()->trigger();
+
+ if (!m_toolWindows.isEmpty() && !found_visible_window)
+ m_toolWindows.first()->show();
+
+ m_actionManager->setBringAllToFrontVisible(true);
+
+ foreach (QDesignerFormWindow *fw, m_formWindows) {
+ fw->setParent(magicalParent(fw), magicalWindowFlags(fw));
+ fw->setAttribute(Qt::WA_DeleteOnClose, true);
+ const PositionMap::const_iterator pit = m_Positions.constFind(fw);
+ if (pit != m_Positions.constEnd()) pit->applyTo(fw, desktopOffset);
+ // Force an activate in order to refresh minimumSize, otherwise it will not be respected
+ if (QLayout *layout = fw->layout())
+ layout->invalidate();
+ if (QWidget *mainContainer = fw->editor()->mainContainer())
+ resizeForm(fw, mainContainer);
+ }
+}
+
+QDesignerFormWindowManagerInterface *QDesignerWorkbench::formWindowManager() const
+{
+ return m_core->formWindowManager();
+}
+
+QDesignerFormEditorInterface *QDesignerWorkbench::core() const
+{
+ return m_core;
+}
+
+int QDesignerWorkbench::toolWindowCount() const
+{
+ return m_toolWindows.count();
+}
+
+QDesignerToolWindow *QDesignerWorkbench::toolWindow(int index) const
+{
+ return m_toolWindows.at(index);
+}
+
+int QDesignerWorkbench::formWindowCount() const
+{
+ return m_formWindows.count();
+}
+
+QDesignerFormWindow *QDesignerWorkbench::formWindow(int index) const
+{
+ return m_formWindows.at(index);
+}
+
+QRect QDesignerWorkbench::desktopGeometry() const
+{
+ // Return geometry of the desktop designer is running in.
+ QWidget *widget = 0;
+ switch (m_mode) {
+ case DockedMode:
+ widget = m_dockedMainWindow;
+ break;
+ case TopLevelMode:
+ widget = widgetBoxToolWindow();
+ break;
+ case NeutralMode:
+ break;
+ }
+ const QDesktopWidget *desktop = qApp->desktop();
+ const int screenNumber = widget ? desktop->screenNumber(widget) : 0;
+ return desktop->availableGeometry(screenNumber);
+}
+
+QRect QDesignerWorkbench::availableGeometry() const
+{
+ if (m_mode == DockedMode)
+ return m_dockedMainWindow->mdiArea()->geometry();
+
+ const QDesktopWidget *desktop = qDesigner->desktop();
+ return desktop->availableGeometry(desktop->screenNumber(widgetBoxToolWindow()));
+}
+
+int QDesignerWorkbench::marginHint() const
+{ return 20;
+}
+
+void QDesignerWorkbench::slotFormWindowActivated(QDesignerFormWindow* fw)
+{
+ core()->formWindowManager()->setActiveFormWindow(fw->editor());
+}
+
+void QDesignerWorkbench::removeFormWindow(QDesignerFormWindow *formWindow)
+{
+ QDesignerFormWindowInterface *editor = formWindow->editor();
+ const bool loadOk = editor->mainContainer();
+ updateBackup(editor);
+ const int index = m_formWindows.indexOf(formWindow);
+ if (index != -1) {
+ m_formWindows.removeAt(index);
+ }
+
+ if (QAction *action = formWindow->action()) {
+ m_windowActions->removeAction(action);
+ m_windowMenu->removeAction(action);
+ }
+
+ if (m_formWindows.empty()) {
+ m_actionManager->setWindowListSeparatorVisible(false);
+ // Show up new form dialog unless closing
+ if (loadOk && m_state == StateUp
+ && QDesignerSettings(m_core).showNewFormOnStartup()) {
+ QTimer::singleShot(200, m_actionManager, SLOT(createForm()));
+ }
+ }
+}
+
+void QDesignerWorkbench::initializeCorePlugins()
+{
+ QList<QObject*> plugins = QPluginLoader::staticInstances();
+ plugins += core()->pluginManager()->instances();
+
+ foreach (QObject *plugin, plugins) {
+ if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
+ if (!formEditorPlugin->isInitialized())
+ formEditorPlugin->initialize(core());
+ }
+ }
+}
+
+void QDesignerWorkbench::saveSettings() const
+{
+ QDesignerSettings settings(m_core);
+ settings.clearBackup();
+ saveGeometries(settings);
+ AppFontWidget::save(m_core->settingsManager(), QLatin1String(appFontPrefixC));
+}
+
+void QDesignerWorkbench::saveGeometries(QDesignerSettings &settings) const
+{
+ switch (m_mode) {
+ case DockedMode:
+ m_dockedMainWindow->saveSettings(settings);
+ break;
+ case TopLevelMode:
+ settings.setToolBarsState(m_mode, m_topLevelData.toolbarManager->saveState(MainWindowBase::settingsVersion()));
+ settings.setMainWindowState(m_mode, widgetBoxToolWindow()->saveState(MainWindowBase::settingsVersion()));
+ foreach (const QDesignerToolWindow *tw, m_toolWindows)
+ settings.saveGeometryFor(tw);
+ break;
+ case NeutralMode:
+ break;
+ }
+}
+
+void QDesignerWorkbench::slotFileDropped(const QString &f)
+{
+ readInForm(f);
+}
+
+bool QDesignerWorkbench::readInForm(const QString &fileName) const
+{
+ return m_actionManager->readInForm(fileName);
+}
+
+bool QDesignerWorkbench::writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName) const
+{
+ return m_actionManager->writeOutForm(formWindow, fileName);
+}
+
+bool QDesignerWorkbench::saveForm(QDesignerFormWindowInterface *frm)
+{
+ return m_actionManager->saveForm(frm);
+}
+
+QDesignerFormWindow *QDesignerWorkbench::findFormWindow(QWidget *widget) const
+{
+ foreach (QDesignerFormWindow *formWindow, m_formWindows) {
+ if (formWindow->editor() == widget)
+ return formWindow;
+ }
+
+ return 0;
+}
+
+bool QDesignerWorkbench::handleClose()
+{
+ m_state = StateClosing;
+ QList<QDesignerFormWindow *> dirtyForms;
+ foreach (QDesignerFormWindow *w, m_formWindows) {
+ if (w->editor()->isDirty())
+ dirtyForms << w;
+ }
+
+ if (dirtyForms.size()) {
+ if (dirtyForms.size() == 1) {
+ if (!dirtyForms.at(0)->close()) {
+ m_state = StateUp;
+ return false;
+ }
+ } else {
+ int count = dirtyForms.size();
+ QMessageBox box(QMessageBox::Warning, tr("Save Forms?"),
+ tr("There are %n forms with unsaved changes."
+ " Do you want to review these changes before quitting?", "", count),
+ QMessageBox::Cancel | QMessageBox::Discard | QMessageBox::Save);
+ box.setInformativeText(tr("If you do not review your documents, all your changes will be lost."));
+ box.button(QMessageBox::Discard)->setText(tr("Discard Changes"));
+ QPushButton *save = static_cast<QPushButton *>(box.button(QMessageBox::Save));
+ save->setText(tr("Review Changes"));
+ box.setDefaultButton(save);
+ switch (box.exec()) {
+ case QMessageBox::Cancel:
+ m_state = StateUp;
+ return false;
+ case QMessageBox::Save:
+ foreach (QDesignerFormWindow *fw, dirtyForms) {
+ fw->show();
+ fw->raise();
+ if (!fw->close()) {
+ m_state = StateUp;
+ return false;
+ }
+ }
+ break;
+ case QMessageBox::Discard:
+ foreach (QDesignerFormWindow *fw, dirtyForms) {
+ fw->editor()->setDirty(false);
+ fw->setWindowModified(false);
+ }
+ break;
+ }
+ }
+ }
+
+ foreach (QDesignerFormWindow *fw, m_formWindows)
+ fw->close();
+
+ saveSettings();
+ return true;
+}
+
+QDesignerActions *QDesignerWorkbench::actionManager() const
+{
+ return m_actionManager;
+}
+
+void QDesignerWorkbench::updateWindowMenu(QDesignerFormWindowInterface *fwi)
+{
+ bool minimizeChecked = false;
+ bool minimizeEnabled = false;
+ QDesignerFormWindow *activeFormWindow = 0;
+ do {
+ if (!fwi)
+ break;
+ activeFormWindow = qobject_cast<QDesignerFormWindow *>(fwi->parentWidget());
+ if (!activeFormWindow)
+ break;
+
+ minimizeEnabled = true;
+ minimizeChecked = isFormWindowMinimized(activeFormWindow);
+ } while (false) ;
+
+ m_actionManager->minimizeAction()->setEnabled(minimizeEnabled);
+ m_actionManager->minimizeAction()->setChecked(minimizeChecked);
+
+ if (!m_formWindows.empty()) {
+ const QList<QDesignerFormWindow*>::const_iterator cend = m_formWindows.constEnd();
+ for (QList<QDesignerFormWindow*>::const_iterator it = m_formWindows.constBegin(); it != cend; ++it)
+ (*it)->action()->setChecked(*it == activeFormWindow);
+ }
+}
+
+void QDesignerWorkbench::formWindowActionTriggered(QAction *a)
+{
+ QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow *>(a->parentWidget());
+ Q_ASSERT(fw);
+
+ if (isFormWindowMinimized(fw))
+ setFormWindowMinimized(fw, false);
+
+ if (m_mode == DockedMode) {
+ if (QMdiSubWindow *subWindow = qobject_cast<QMdiSubWindow *>(fw->parent())) {
+ m_dockedMainWindow->mdiArea()->setActiveSubWindow(subWindow);
+ }
+ } else {
+ fw->activateWindow();
+ fw->raise();
+ }
+}
+
+void QDesignerWorkbench::closeAllToolWindows()
+{
+ foreach (QDesignerToolWindow *tw, m_toolWindows)
+ tw->hide();
+}
+
+bool QDesignerWorkbench::readInBackup()
+{
+ const QMap<QString, QString> backupFileMap = QDesignerSettings(m_core).backup();
+ if (backupFileMap.isEmpty())
+ return false;
+
+ const QMessageBox::StandardButton answer =
+ QMessageBox::question(0, tr("Backup Information"),
+ tr("The last session of Designer was not terminated correctly. "
+ "Backup files were left behind. Do you want to load them?"),
+ QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
+ if (answer == QMessageBox::No)
+ return false;
+
+ const QString modifiedPlaceHolder = QLatin1String("[*]");
+ QMapIterator<QString, QString> it(backupFileMap);
+ while(it.hasNext()) {
+ it.next();
+
+ QString fileName = it.key();
+ fileName.remove(modifiedPlaceHolder);
+
+ if(m_actionManager->readInForm(it.value()))
+ formWindowManager()->activeFormWindow()->setFileName(fileName);
+
+ }
+ return true;
+}
+
+void QDesignerWorkbench::updateBackup(QDesignerFormWindowInterface* fwi)
+{
+ QString fwn = QDir::convertSeparators(fwi->fileName());
+ if (fwn.isEmpty())
+ fwn = fwi->parentWidget()->windowTitle();
+
+ QDesignerSettings settings(m_core);
+ QMap<QString, QString> map = settings.backup();
+ map.remove(fwn);
+ settings.setBackup(map);
+}
+
+namespace {
+ void raiseWindow(QWidget *w) {
+ if (w->isMinimized())
+ w->setWindowState(w->windowState() & ~Qt::WindowMinimized);
+ w->raise();
+ }
+}
+
+void QDesignerWorkbench::bringAllToFront()
+{
+ if (m_mode != TopLevelMode)
+ return;
+ foreach(QDesignerToolWindow *tw, m_toolWindows)
+ raiseWindow(tw);
+ foreach(QDesignerFormWindow *dfw, m_formWindows)
+ raiseWindow(dfw);
+}
+
+// Resize a form window taking MDI decorations into account
+// Apply maximum size as there is no layout connection between
+// the form's main container and the integration's outer
+// container due to the tool widget stack.
+
+void QDesignerWorkbench::resizeForm(QDesignerFormWindow *fw, const QWidget *mainContainer) const
+{
+ const QSize containerSize = mainContainer->size();
+ const QSize containerMinimumSize = mainContainer->minimumSize();
+ const QSize containerMaximumSize = mainContainer->maximumSize();
+ if (m_mode != DockedMode) {
+ fw->resize(containerSize);
+ fw->setMaximumSize(containerMaximumSize);
+ return;
+ }
+ // get decorations and resize MDI
+ QMdiSubWindow *mdiSubWindow = qobject_cast<QMdiSubWindow *>(fw->parent());
+ Q_ASSERT(mdiSubWindow);
+ const QSize decorationSize = mdiSubWindow->geometry().size() - mdiSubWindow->contentsRect().size();
+ mdiSubWindow->resize(containerSize + decorationSize);
+ // In Qt::RightToLeft mode, the window can grow to be partially hidden by the right border.
+ const int mdiAreaWidth = m_dockedMainWindow->mdiArea()->width();
+ if (qApp->layoutDirection() == Qt::RightToLeft && mdiSubWindow->geometry().right() >= mdiAreaWidth)
+ mdiSubWindow->move(mdiAreaWidth - mdiSubWindow->width(), mdiSubWindow->pos().y());
+
+ if (containerMaximumSize == QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) {
+ mdiSubWindow->setMaximumSize(containerMaximumSize);
+ } else {
+ mdiSubWindow->setMaximumSize(containerMaximumSize + decorationSize);
+ }
+}
+
+
+// Load a form or return 0 and do cleanup. file name and editor file
+// name in case of loading a template file.
+
+QDesignerFormWindow * QDesignerWorkbench::loadForm(const QString &fileName,
+ bool detectLineTermiantorMode,
+ bool *uic3Converted,
+ QString *errorMessage)
+{
+ QFile file(fileName);
+
+ qdesigner_internal::FormWindowBase::LineTerminatorMode mode = qdesigner_internal::FormWindowBase::NativeLineTerminator;
+
+ if (detectLineTermiantorMode) {
+ if (file.open(QFile::ReadOnly)) {
+ const QString text = QString::fromUtf8(file.readLine());
+ file.close();
+
+ const int lf = text.indexOf(QLatin1Char('\n'));
+ if (lf > 0 && text.at(lf-1) == QLatin1Char('\r')) {
+ mode = qdesigner_internal::FormWindowBase::CRLFLineTerminator;
+ } else if (lf >= 0) {
+ mode = qdesigner_internal::FormWindowBase::LFLineTerminator;
+ }
+ }
+ }
+
+ if (!file.open(QFile::ReadOnly|QFile::Text)) {
+ *errorMessage = tr("The file <b>%1</b> could not be opened.").arg(file.fileName());
+ return 0;
+ }
+
+
+ // Create a form
+ QDesignerFormWindowManagerInterface *formWindowManager = m_core->formWindowManager();
+
+ QDesignerFormWindow *formWindow = new QDesignerFormWindow(/*formWindow=*/ 0, this);
+ addFormWindow(formWindow);
+ QDesignerFormWindowInterface *editor = formWindow->editor();
+ Q_ASSERT(editor);
+
+ // Temporarily set the file name. It is needed when converting a UIC 3 file.
+ // In this case, the file name will we be cleared on return to force a save box.
+ editor->setFileName(fileName);
+ editor->setContents(&file);
+
+ if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(editor))
+ fwb->setLineTerminatorMode(mode);
+
+ switch (m_mode) {
+ case DockedMode: {
+ // below code must be after above call to setContents(), because setContents() may popup warning dialogs which would cause
+ // mdi sub window activation (because of dialogs internal call to processEvent or such)
+ // That activation could have worse consequences, e.g. NULL resource set for active form) before the form is loaded
+ QMdiSubWindow *subWin = m_dockedMainWindow->createMdiSubWindow(formWindow, magicalWindowFlags(formWindow), m_actionManager->closeFormAction()->shortcut());
+ m_dockedMainWindow->mdiArea()->setActiveSubWindow(subWin);
+ }
+ break;
+ case TopLevelMode: {
+ const QRect formWindowGeometryHint = formWindow->geometryHint();
+ formWindow->setAttribute(Qt::WA_DeleteOnClose, true);
+ formWindow->setParent(magicalParent(formWindow), magicalWindowFlags(formWindow));
+ formWindow->resize(formWindowGeometryHint.size());
+ formWindow->move(availableGeometry().center() - formWindowGeometryHint.center());
+ }
+ break;
+ case NeutralMode:
+ break;
+ }
+
+ if (!editor->mainContainer()) {
+ removeFormWindow(formWindow);
+ formWindowManager->removeFormWindow(editor);
+ m_core->metaDataBase()->remove(editor);
+ *errorMessage = tr("The file <b>%1</b> is not a valid Designer ui file.").arg(file.fileName());
+ return 0;
+ }
+ *uic3Converted = editor->fileName().isEmpty();
+ editor->setDirty(false);
+ resizeForm(formWindow, editor->mainContainer());
+ formWindowManager->setActiveFormWindow(editor);
+ return formWindow;
+}
+
+
+QDesignerFormWindow * QDesignerWorkbench::openForm(const QString &fileName, QString *errorMessage)
+{
+ bool uic3Converted;
+ QDesignerFormWindow *rc =loadForm(fileName, true, &uic3Converted, errorMessage);
+ if (!rc)
+ return 0;
+
+ if (!uic3Converted)
+ rc->editor()->setFileName(fileName);
+ rc->firstShow();
+ return rc;
+}
+
+QDesignerFormWindow * QDesignerWorkbench::openTemplate(const QString &templateFileName,
+ const QString &editorFileName,
+ QString *errorMessage)
+{
+ bool uic3Converted;
+ QDesignerFormWindow *rc =loadForm(templateFileName, false, &uic3Converted, errorMessage);
+ if (!rc)
+ return 0;
+
+ if (!uic3Converted)
+ rc->editor()->setFileName(editorFileName);
+
+ rc->firstShow();
+ return rc;
+}
+
+void QDesignerWorkbench::minimizationStateChanged(QDesignerFormWindowInterface *formWindow, bool minimized)
+{
+ // refresh the minimize action state
+ if (core()->formWindowManager()->activeFormWindow() == formWindow) {
+ m_actionManager->minimizeAction()->setChecked(minimized);
+ }
+}
+
+void QDesignerWorkbench::toggleFormMinimizationState()
+{
+ QDesignerFormWindowInterface *fwi = core()->formWindowManager()->activeFormWindow();
+ if (!fwi || m_mode == NeutralMode)
+ return;
+ QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow *>(fwi->parentWidget());
+ Q_ASSERT(fw);
+ setFormWindowMinimized(fw, !isFormWindowMinimized(fw));
+}
+
+bool QDesignerWorkbench::isFormWindowMinimized(const QDesignerFormWindow *fw)
+{
+ switch (m_mode) {
+ case DockedMode:
+ return mdiSubWindowOf(fw)->isShaded();
+ case TopLevelMode:
+ return fw->window()->isMinimized();
+ default:
+ break;
+ }
+ return fw->isMinimized();
+}
+
+void QDesignerWorkbench::setFormWindowMinimized(QDesignerFormWindow *fw, bool minimized)
+{
+ switch (m_mode) {
+ case DockedMode: {
+ QMdiSubWindow *mdiSubWindow = mdiSubWindowOf(fw);
+ if (minimized) {
+ mdiSubWindow->showShaded();
+ } else {
+ mdiSubWindow->setWindowState(mdiSubWindow->windowState() & ~Qt::WindowMinimized);
+ }
+ }
+ break;
+ case TopLevelMode: {
+ QWidget *window = fw->window();
+ if (window->isMinimized()) {
+ window->setWindowState(window->windowState() & ~Qt::WindowMinimized);
+ } else {
+ window->showMinimized();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void QDesignerWorkbench::restoreUISettings()
+{
+ UIMode mode = QDesignerSettings(m_core).uiMode();
+ switch (mode) {
+ case TopLevelMode:
+ switchToTopLevelMode();
+ break;
+ case DockedMode:
+ switchToDockedMode();
+ break;
+
+ default: Q_ASSERT(0);
+ }
+
+ ToolWindowFontSettings fontSettings = QDesignerSettings(m_core).toolWindowFont();
+ const QFont &font = fontSettings.m_useFont ? fontSettings.m_font : qApp->font();
+
+ if (font == m_toolWindows.front()->font())
+ return;
+
+ foreach(QDesignerToolWindow *tw, m_toolWindows)
+ tw->setFont(font);
+}
+
+void QDesignerWorkbench::handleCloseEvent(QCloseEvent *ev)
+{
+ ev->setAccepted(handleClose());
+ if (ev->isAccepted())
+ QMetaObject::invokeMethod(qDesigner, "quit", Qt::QueuedConnection); // We're going down!
+}
+
+QDesignerToolWindow *QDesignerWorkbench::widgetBoxToolWindow() const
+{
+ return m_toolWindows.at(QDesignerToolWindow::WidgetBox);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/qdesigner_workbench.h b/tools/designer/src/designer/qdesigner_workbench.h
new file mode 100644
index 0000000000..0ac18af858
--- /dev/null
+++ b/tools/designer/src/designer/qdesigner_workbench.h
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_WORKBENCH_H
+#define QDESIGNER_WORKBENCH_H
+
+#include "designer_enums.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+#include <QtCore/QList>
+#include <QtCore/QRect>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerActions;
+class QDesignerToolWindow;
+class QDesignerFormWindow;
+class DockedMainWindow;
+class QDesignerSettings;
+
+class QAction;
+class QActionGroup;
+class QDockWidget;
+class QMenu;
+class QMenuBar;
+class QMainWindow;
+class QToolBar;
+class QMdiArea;
+class QMdiSubWindow;
+class QCloseEvent;
+class QFont;
+class QtToolBarManager;
+class ToolBarManager;
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QDesignerFormWindowManagerInterface;
+
+namespace qdesigner_internal {
+class QDesignerIntegration;
+}
+
+class QDesignerWorkbench: public QObject
+{
+ Q_OBJECT
+
+public:
+ QDesignerWorkbench();
+ virtual ~QDesignerWorkbench();
+
+ UIMode mode() const;
+
+ QDesignerFormEditorInterface *core() const;
+ QDesignerFormWindow *findFormWindow(QWidget *widget) const;
+
+ QDesignerFormWindow *openForm(const QString &fileName, QString *errorMessage);
+ QDesignerFormWindow *openTemplate(const QString &templateFileName,
+ const QString &editorFileName,
+ QString *errorMessage);
+
+ int toolWindowCount() const;
+ QDesignerToolWindow *toolWindow(int index) const;
+
+ int formWindowCount() const;
+ QDesignerFormWindow *formWindow(int index) const;
+
+ QDesignerActions *actionManager() const;
+
+ QActionGroup *modeActionGroup() const;
+
+ QRect availableGeometry() const;
+ QRect desktopGeometry() const;
+
+ int marginHint() const;
+
+ bool readInForm(const QString &fileName) const;
+ bool writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName) const;
+ bool saveForm(QDesignerFormWindowInterface *fw);
+ bool handleClose();
+ bool readInBackup();
+ void updateBackup(QDesignerFormWindowInterface* fwi);
+
+signals:
+ void modeChanged(UIMode mode);
+ void initialized();
+
+public slots:
+ void addFormWindow(QDesignerFormWindow *formWindow);
+ void removeFormWindow(QDesignerFormWindow *formWindow);
+ void bringAllToFront();
+ void toggleFormMinimizationState();
+
+private slots:
+ void switchToNeutralMode();
+ void switchToDockedMode();
+ void switchToTopLevelMode();
+ void initializeCorePlugins();
+ void handleCloseEvent(QCloseEvent *);
+ void slotFormWindowActivated(QDesignerFormWindow* fw);
+ void updateWindowMenu(QDesignerFormWindowInterface *fw);
+ void formWindowActionTriggered(QAction *a);
+ void adjustMDIFormPositions();
+ void minimizationStateChanged(QDesignerFormWindowInterface *formWindow, bool minimized);
+
+ void restoreUISettings();
+ void slotFileDropped(const QString &f);
+
+private:
+ QWidget *magicalParent(const QWidget *w) const;
+ Qt::WindowFlags magicalWindowFlags(const QWidget *widgetForFlags) const;
+ QDesignerFormWindowManagerInterface *formWindowManager() const;
+ void closeAllToolWindows();
+ QDesignerToolWindow *widgetBoxToolWindow() const;
+ QDesignerFormWindow *loadForm(const QString &fileName, bool detectLineTermiantorMode, bool *uic3Converted, QString *errorMessage);
+ void resizeForm(QDesignerFormWindow *fw, const QWidget *mainContainer) const;
+ void saveGeometriesForModeChange();
+ void saveGeometries(QDesignerSettings &settings) const;
+
+ bool isFormWindowMinimized(const QDesignerFormWindow *fw);
+ void setFormWindowMinimized(QDesignerFormWindow *fw, bool minimized);
+ void saveSettings() const;
+
+ QDesignerFormEditorInterface *m_core;
+ qdesigner_internal::QDesignerIntegration *m_integration;
+
+ QDesignerActions *m_actionManager;
+ QActionGroup *m_windowActions;
+
+ QMenu *m_windowMenu;
+
+ QMenuBar *m_globalMenuBar;
+
+ struct TopLevelData {
+ ToolBarManager *toolbarManager;
+ QList<QToolBar *> toolbars;
+ };
+ TopLevelData m_topLevelData;
+
+ UIMode m_mode;
+ DockedMainWindow *m_dockedMainWindow;
+
+ QList<QDesignerToolWindow*> m_toolWindows;
+ QList<QDesignerFormWindow*> m_formWindows;
+
+ QMenu *m_toolbarMenu;
+
+ // Helper class to remember the position of a window while switching user
+ // interface modes.
+ class Position {
+ public:
+ Position(const QDockWidget *dockWidget);
+ Position(const QMdiSubWindow *mdiSubWindow, const QPoint &mdiAreaOffset);
+ Position(const QWidget *topLevelWindow, const QPoint &desktopTopLeft);
+
+ void applyTo(QMdiSubWindow *mdiSubWindow, const QPoint &mdiAreaOffset) const;
+ void applyTo(QWidget *topLevelWindow, const QPoint &desktopTopLeft) const;
+ void applyTo(QDockWidget *dockWidget) const;
+
+ QPoint position() const { return m_position; }
+ private:
+ bool m_minimized;
+ // Position referring to top-left corner (desktop in top-level mode or
+ // main window in MDI mode)
+ QPoint m_position;
+ };
+ typedef QHash<QWidget*, Position> PositionMap;
+ PositionMap m_Positions;
+
+ enum State { StateInitializing, StateUp, StateClosing };
+ State m_state;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_WORKBENCH_H
diff --git a/tools/designer/src/designer/saveformastemplate.cpp b/tools/designer/src/designer/saveformastemplate.cpp
new file mode 100644
index 0000000000..ef8973169a
--- /dev/null
+++ b/tools/designer/src/designer/saveformastemplate.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "saveformastemplate.h"
+#include "qdesigner_settings.h"
+
+#include <QtCore/QFile>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/abstractformwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+SaveFormAsTemplate::SaveFormAsTemplate(QDesignerFormEditorInterface *core,
+ QDesignerFormWindowInterface *formWindow,
+ QWidget *parent)
+ : QDialog(parent, Qt::Sheet),
+ m_core(core),
+ m_formWindow(formWindow)
+{
+ ui.setupUi(this);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ ui.templateNameEdit->setText(formWindow->mainContainer()->objectName());
+ ui.templateNameEdit->selectAll();
+
+ ui.templateNameEdit->setFocus();
+
+ QStringList paths = QDesignerSettings(m_core).formTemplatePaths();
+ ui.categoryCombo->addItems(paths);
+ ui.categoryCombo->addItem(tr("Add path..."));
+ m_addPathIndex = ui.categoryCombo->count() - 1;
+ connect(ui.templateNameEdit, SIGNAL(textChanged(QString)),
+ this, SLOT(updateOKButton(QString)));
+ connect(ui.categoryCombo, SIGNAL(activated(int)), this, SLOT(checkToAddPath(int)));
+}
+
+SaveFormAsTemplate::~SaveFormAsTemplate()
+{
+}
+
+void SaveFormAsTemplate::accept()
+{
+ QString templateFileName = ui.categoryCombo->currentText();
+ templateFileName += QLatin1Char('/');
+ const QString name = ui.templateNameEdit->text();
+ templateFileName += name;
+ const QString extension = QLatin1String(".ui");
+ if (!templateFileName.endsWith(extension))
+ templateFileName.append(extension);
+ QFile file(templateFileName);
+
+ if (file.exists()) {
+ QMessageBox msgBox(QMessageBox::Information, tr("Template Exists"),
+ tr("A template with the name %1 already exists.\n"
+ "Do you want overwrite the template?").arg(name), QMessageBox::Cancel, m_formWindow);
+ msgBox.setDefaultButton(QMessageBox::Cancel);
+ QPushButton *overwriteButton = msgBox.addButton(tr("Overwrite Template"), QMessageBox::AcceptRole);
+ msgBox.exec();
+ if (msgBox.clickedButton() != overwriteButton)
+ return;
+ }
+
+ while (!file.open(QFile::WriteOnly)) {
+ if (QMessageBox::information(m_formWindow, tr("Open Error"),
+ tr("There was an error opening template %1 for writing. Reason: %2").arg(name).arg(file.errorString()),
+ QMessageBox::Retry|QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel) {
+ return;
+ }
+ }
+
+ const QString origName = m_formWindow->fileName();
+ // ensure m_formWindow->contents() will convert properly resource paths to relative paths
+ // (relative to template location, not to the current form location)
+ m_formWindow->setFileName(templateFileName);
+ QByteArray ba = m_formWindow->contents().toUtf8();
+ m_formWindow->setFileName(origName);
+ while (file.write(ba) != ba.size()) {
+ if (QMessageBox::information(m_formWindow, tr("Write Error"),
+ tr("There was an error writing the template %1 to disk. Reason: %2").arg(name).arg(file.errorString()),
+ QMessageBox::Retry|QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel) {
+ file.close();
+ file.remove();
+ return;
+ }
+ file.reset();
+ }
+ // update the list of places too...
+ QStringList sl;
+ for (int i = 0; i < m_addPathIndex; ++i)
+ sl << ui.categoryCombo->itemText(i);
+
+ QDesignerSettings(m_core).setFormTemplatePaths(sl);
+
+ QDialog::accept();
+}
+
+void SaveFormAsTemplate::updateOKButton(const QString &str)
+{
+ QPushButton *okButton = ui.buttonBox->button(QDialogButtonBox::Ok);
+ okButton->setEnabled(!str.isEmpty());
+}
+
+QString SaveFormAsTemplate::chooseTemplatePath(QWidget *parent)
+{
+ QString rc = QFileDialog::getExistingDirectory(parent,
+ tr("Pick a directory to save templates in"));
+ if (rc.isEmpty())
+ return rc;
+
+ if (rc.endsWith(QDir::separator()))
+ rc.remove(rc.size() - 1, 1);
+ return rc;
+}
+
+void SaveFormAsTemplate::checkToAddPath(int itemIndex)
+{
+ if (itemIndex != m_addPathIndex)
+ return;
+
+ const QString dir = chooseTemplatePath(this);
+ if (dir.isEmpty()) {
+ ui.categoryCombo->setCurrentIndex(0);
+ return;
+ }
+
+ ui.categoryCombo->insertItem(m_addPathIndex, dir);
+ ui.categoryCombo->setCurrentIndex(m_addPathIndex);
+ ++m_addPathIndex;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/designer/saveformastemplate.h b/tools/designer/src/designer/saveformastemplate.h
new file mode 100644
index 0000000000..3f62d15b25
--- /dev/null
+++ b/tools/designer/src/designer/saveformastemplate.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SAVEFORMASTEMPLATE_H
+#define SAVEFORMASTEMPLATE_H
+
+#include "ui_saveformastemplate.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+class SaveFormAsTemplate: public QDialog
+{
+ Q_OBJECT
+public:
+ explicit SaveFormAsTemplate(QDesignerFormEditorInterface *m_core,
+ QDesignerFormWindowInterface *formWindow,
+ QWidget *parent = 0);
+ virtual ~SaveFormAsTemplate();
+
+private slots:
+ void accept();
+ void updateOKButton(const QString &str);
+ void checkToAddPath(int itemIndex);
+
+private:
+ static QString chooseTemplatePath(QWidget *parent);
+
+ Ui::SaveFormAsTemplate ui;
+ QDesignerFormEditorInterface *m_core;
+ QDesignerFormWindowInterface *m_formWindow;
+ int m_addPathIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif // SAVEFORMASTEMPLATE_H
diff --git a/tools/designer/src/designer/saveformastemplate.ui b/tools/designer/src/designer/saveformastemplate.ui
new file mode 100644
index 0000000000..c721c5bbc8
--- /dev/null
+++ b/tools/designer/src/designer/saveformastemplate.ui
@@ -0,0 +1,166 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>SaveFormAsTemplate</class>
+ <widget class="QDialog" name="SaveFormAsTemplate" >
+ <property name="windowTitle" >
+ <string>Save Form As Template</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <layout class="QFormLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="frameShape" >
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="text" >
+ <string>&amp;Name:</string>
+ </property>
+ <property name="textFormat" >
+ <enum>Qt::AutoText</enum>
+ </property>
+ <property name="buddy" >
+ <cstring>templateNameEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="templateNameEdit" >
+ <property name="minimumSize" >
+ <size>
+ <width>222</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="echoMode" >
+ <enum>QLineEdit::Normal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="frameShape" >
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="text" >
+ <string>&amp;Category:</string>
+ </property>
+ <property name="textFormat" >
+ <enum>Qt::AutoText</enum>
+ </property>
+ <property name="buddy" >
+ <cstring>categoryCombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QComboBox" name="categoryCombo" />
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QFrame" name="horizontalLine" >
+ <property name="frameShape" >
+ <enum>QFrame::HLine</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Sunken</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>SaveFormAsTemplate</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>256</x>
+ <y>124</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>113</x>
+ <y>143</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>SaveFormAsTemplate</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>332</x>
+ <y>127</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>372</x>
+ <y>147</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/designer/versiondialog.cpp b/tools/designer/src/designer/versiondialog.cpp
new file mode 100644
index 0000000000..a129a4dde8
--- /dev/null
+++ b/tools/designer/src/designer/versiondialog.cpp
@@ -0,0 +1,218 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QVector>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QGridLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPainter>
+#include <QtGui/QPainterPath>
+#include <QtGui/QStyleOption>
+#include "versiondialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class VersionLabel : public QLabel
+{
+ Q_OBJECT
+public:
+ VersionLabel(QWidget *parent = 0);
+
+signals:
+ void triggered();
+
+protected:
+ void mousePressEvent(QMouseEvent *me);
+ void mouseMoveEvent(QMouseEvent *me);
+ void mouseReleaseEvent(QMouseEvent *me);
+ void paintEvent(QPaintEvent *pe);
+private:
+ QVector<QPoint> hitPoints;
+ QVector<QPoint> missPoints;
+ QPainterPath m_path;
+ bool secondStage;
+ bool m_pushed;
+};
+
+VersionLabel::VersionLabel(QWidget *parent)
+ : QLabel(parent), secondStage(false), m_pushed(false)
+{
+ setPixmap(QPixmap(QLatin1String(":/trolltech/designer/images/designer.png")));
+ hitPoints.append(QPoint(56, 25));
+ hitPoints.append(QPoint(29, 55));
+ hitPoints.append(QPoint(56, 87));
+ hitPoints.append(QPoint(82, 55));
+ hitPoints.append(QPoint(58, 56));
+
+ secondStage = false;
+ m_pushed = false;
+}
+
+void VersionLabel::mousePressEvent(QMouseEvent *me)
+{
+ if (me->button() == Qt::LeftButton) {
+ if (!secondStage) {
+ m_path = QPainterPath(me->pos());
+ } else {
+ m_pushed = true;
+ update();
+ }
+ }
+}
+
+void VersionLabel::mouseMoveEvent(QMouseEvent *me)
+{
+ if (me->buttons() & Qt::LeftButton)
+ if (!secondStage)
+ m_path.lineTo(me->pos());
+}
+
+void VersionLabel::mouseReleaseEvent(QMouseEvent *me)
+{
+ if (me->button() == Qt::LeftButton) {
+ if (!secondStage) {
+ m_path.lineTo(me->pos());
+ bool gotIt = true;
+ QPoint pt;
+ foreach(pt, hitPoints) {
+ if (!m_path.contains(pt)) {
+ gotIt = false;
+ break;
+ }
+ }
+ if (gotIt) {
+ foreach(pt, missPoints) {
+ if (m_path.contains(pt)) {
+ gotIt = false;
+ break;
+ }
+ }
+ }
+ if (gotIt && !secondStage) {
+ secondStage = true;
+ m_path = QPainterPath();
+ update();
+ }
+ } else {
+ m_pushed = false;
+ update();
+ emit triggered();
+ }
+ }
+}
+
+void VersionLabel::paintEvent(QPaintEvent *pe)
+{
+ if (secondStage) {
+ QPainter p(this);
+ QStyleOptionButton opt;
+ opt.init(this);
+ if (!m_pushed)
+ opt.state |= QStyle::State_Raised;
+ else
+ opt.state |= QStyle::State_Sunken;
+ opt.state &= ~QStyle::State_HasFocus;
+ style()->drawControl(QStyle::CE_PushButtonBevel, &opt, &p, this);
+ }
+ QLabel::paintEvent(pe);
+}
+
+VersionDialog::VersionDialog(QWidget *parent)
+ : QDialog(parent
+#ifdef Q_WS_MAC
+ , Qt::Tool
+#endif
+ )
+{
+ setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) | Qt::MSWindowsFixedSizeDialogHint);
+ QGridLayout *layout = new QGridLayout(this);
+ VersionLabel *label = new VersionLabel;
+ QLabel *lbl = new QLabel;
+ QString version = tr("<h3>%1</h3><br/><br/>Version %2");
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ QString open = tr(" Open Source Edition");
+ version.append(open);
+#endif
+ version = version.arg(tr("Qt Designer")).arg(QLatin1String(QT_VERSION_STR));
+ version.append(tr("<br/>Qt Designer is a graphical user interface designer for Qt applications.<br/>"));
+
+ QString edition =
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ tr("This version of Qt Designer is part of the Qt Open Source Edition, for use "
+ "in the development of Open Source applications. "
+ "Qt is a comprehensive C++ framework for cross-platform application "
+ "development.<br/><br/>"
+ "You need a commercial Qt license for development of proprietary (closed "
+ "source) applications. Please see <a href=\"http://qtsoftware.com/company/about/businessmodel\">http://qtsoftware.com/company/about/businessmodel"
+ ".html</a> for an overview of Qt licensing.<br/>");
+#elif defined(QT_PRODUCT_LICENSE)
+ tr("This program is licensed to you under the terms of the "
+ "Qt %1 License Agreement. For details, see the license file "
+ "that came with this software distribution.<br/>").arg(QT_PRODUCT_LICENSE);
+#else
+ tr("This program is licensed to you under the terms of the "
+ "Qt Commercial License Agreement. For details, see the file LICENSE "
+ "that came with this software distribution.<br/>");
+#endif
+
+ lbl->setText(tr("%1"
+ "<br/>%2"
+ "<br/>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)."
+ "<br/><br/>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
+ " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
+ " PARTICULAR PURPOSE.<br/> ").arg(version).arg(edition));
+
+ lbl->setWordWrap(true);
+ lbl->setOpenExternalLinks(true);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
+ connect(buttonBox , SIGNAL(rejected()), this, SLOT(reject()));
+ connect(label, SIGNAL(triggered()), this, SLOT(accept()));
+ layout->addWidget(label, 0, 0, 1, 1);
+ layout->addWidget(lbl, 0, 1, 4, 4);
+ layout->addWidget(buttonBox, 4, 2, 1, 1);
+}
+
+QT_END_NAMESPACE
+
+#include "versiondialog.moc"
diff --git a/tools/designer/src/designer/versiondialog.h b/tools/designer/src/designer/versiondialog.h
new file mode 100644
index 0000000000..2a380ec7f0
--- /dev/null
+++ b/tools/designer/src/designer/versiondialog.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VERSIONDIALOG_H
+#define VERSIONDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class VersionDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit VersionDialog(QWidget *parent);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/components/qdesigner_components.h b/tools/designer/src/lib/components/qdesigner_components.h
new file mode 100644
index 0000000000..e4cdef2376
--- /dev/null
+++ b/tools/designer/src/lib/components/qdesigner_components.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_COMPONENTS_H
+#define QDESIGNER_COMPONENTS_H
+
+#include <QtDesigner/qdesigner_components_global.h>
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QWidget;
+
+class QDesignerFormEditorInterface;
+class QDesignerWidgetBoxInterface;
+class QDesignerPropertyEditorInterface;
+class QDesignerObjectInspectorInterface;
+class QDesignerActionEditorInterface;
+
+class QDESIGNER_COMPONENTS_EXPORT QDesignerComponents
+{
+public:
+ static void initializeResources();
+ static void initializePlugins(QDesignerFormEditorInterface *core);
+
+ static QDesignerFormEditorInterface *createFormEditor(QObject *parent);
+ static QDesignerWidgetBoxInterface *createWidgetBox(QDesignerFormEditorInterface *core, QWidget *parent);
+ static QDesignerPropertyEditorInterface *createPropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+ static QDesignerObjectInspectorInterface *createObjectInspector(QDesignerFormEditorInterface *core, QWidget *parent);
+ static QDesignerActionEditorInterface *createActionEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+
+ static QObject *createTaskMenu(QDesignerFormEditorInterface *core, QObject *parent);
+ static QWidget *createResourceEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+ static QWidget *createSignalSlotEditor(QDesignerFormEditorInterface *core, QWidget *parent);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDESIGNER_COMPONENTS_H
diff --git a/tools/designer/src/lib/components/qdesigner_components_global.h b/tools/designer/src/lib/components/qdesigner_components_global.h
new file mode 100644
index 0000000000..0ae57b2898
--- /dev/null
+++ b/tools/designer/src/lib/components/qdesigner_components_global.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNER_COMPONENTS_GLOBAL_H
+#define QDESIGNER_COMPONENTS_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define QDESIGNER_COMPONENTS_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_COMPONENTS_IMPORT Q_DECL_IMPORT
+
+#ifdef QT_DESIGNER_STATIC
+# define QDESIGNER_COMPONENTS_EXPORT
+#elif defined(QDESIGNER_COMPONENTS_LIBRARY)
+# define QDESIGNER_COMPONENTS_EXPORT QDESIGNER_COMPONENTS_EXTERN
+#else
+# define QDESIGNER_COMPONENTS_EXPORT QDESIGNER_COMPONENTS_IMPORT
+#endif
+
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QDESIGNER_COMPONENTS_GLOBAL_H
diff --git a/tools/designer/src/lib/extension/default_extensionfactory.cpp b/tools/designer/src/lib/extension/default_extensionfactory.cpp
new file mode 100644
index 0000000000..a96783acd8
--- /dev/null
+++ b/tools/designer/src/lib/extension/default_extensionfactory.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/default_extensionfactory.h>
+#include "qextensionmanager.h"
+#include <qpointer.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QExtensionFactory
+
+ \brief The QExtensionFactory class allows you to create a factory
+ that is able to make instances of custom extensions in Qt
+ Designer.
+
+ \inmodule QtDesigner
+
+ In \QD the extensions are not created until they are required. For
+ that reason, when implementing a custom extension, you must also
+ create a QExtensionFactory, i.e. a class that is able to make an
+ instance of your extension, and register it using \QD's \l
+ {QExtensionManager}{extension manager}.
+
+ The QExtensionManager class provides extension management
+ facilities for Qt Designer. When an extension is required, Qt
+ Designer's \l {QExtensionManager}{extension manager} will run
+ through all its registered factories calling
+ QExtensionFactory::createExtension() for each until the first one
+ that is able to create a requested extension for the selected
+ object, is found. This factory will then make an instance of the
+ extension.
+
+ There are four available types of extensions in Qt Designer:
+ QDesignerContainerExtension , QDesignerMemberSheetExtension,
+ QDesignerPropertySheetExtension and QDesignerTaskMenuExtension. Qt
+ Designer's behavior is the same whether the requested extension is
+ associated with a multi page container, a member sheet, a property
+ sheet or a task menu.
+
+ You can either create a new QExtensionFactory and reimplement the
+ QExtensionFactory::createExtension() function. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_extension_default_extensionfactory.cpp 0
+
+ Or you can use an existing factory, expanding the
+ QExtensionFactory::createExtension() function to make the factory
+ able to create your extension as well. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_extension_default_extensionfactory.cpp 1
+
+ For a complete example using the QExtensionFactory class, see the
+ \l {designer/taskmenuextension}{Task Menu Extension example}. The
+ example shows how to create a custom widget plugin for Qt
+ Designer, and how to to use the QDesignerTaskMenuExtension class
+ to add custom items to Qt Designer's task menu.
+
+ \sa QExtensionManager, QAbstractExtensionFactory
+*/
+
+/*!
+ Constructs an extension factory with the given \a parent.
+*/
+QExtensionFactory::QExtensionFactory(QExtensionManager *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Returns the extension specified by \a iid for the given \a object.
+
+ \sa createExtension()
+*/
+
+QObject *QExtensionFactory::extension(QObject *object, const QString &iid) const
+{
+ if (!object)
+ return 0;
+ const IdObjectKey key = qMakePair(iid, object);
+
+ ExtensionMap::iterator it = m_extensions.find(key);
+ if (it == m_extensions.end()) {
+ if (QObject *ext = createExtension(object, iid, const_cast<QExtensionFactory*>(this))) {
+ connect(ext, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ it = m_extensions.insert(key, ext);
+ }
+ }
+
+ if (!m_extended.contains(object)) {
+ connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ m_extended.insert(object, true);
+ }
+
+ if (it == m_extensions.end())
+ return 0;
+
+ return it.value();
+}
+
+void QExtensionFactory::objectDestroyed(QObject *object)
+{
+ QMutableMapIterator< IdObjectKey, QObject*> it(m_extensions);
+ while (it.hasNext()) {
+ it.next();
+
+ QObject *o = it.key().second;
+ if (o == object || object == it.value()) {
+ it.remove();
+ }
+ }
+
+ m_extended.remove(object);
+}
+
+/*!
+ Creates an extension specified by \a iid for the given \a object.
+ The extension object is created as a child of the specified \a
+ parent.
+
+ \sa extension()
+*/
+QObject *QExtensionFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ Q_UNUSED(object);
+ Q_UNUSED(iid);
+ Q_UNUSED(parent);
+
+ return 0;
+}
+
+/*!
+ Returns the extension manager for the extension factory.
+*/
+QExtensionManager *QExtensionFactory::extensionManager() const
+{
+ return static_cast<QExtensionManager *>(parent());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/extension/default_extensionfactory.h b/tools/designer/src/lib/extension/default_extensionfactory.h
new file mode 100644
index 0000000000..1966c91fbd
--- /dev/null
+++ b/tools/designer/src/lib/extension/default_extensionfactory.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEFAULT_EXTENSIONFACTORY_H
+#define DEFAULT_EXTENSIONFACTORY_H
+
+#include <QtDesigner/extension_global.h>
+#include <QtDesigner/extension.h>
+
+#include <QtCore/QMap>
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QExtensionManager;
+
+class QDESIGNER_EXTENSION_EXPORT QExtensionFactory : public QObject, public QAbstractExtensionFactory
+{
+ Q_OBJECT
+ Q_INTERFACES(QAbstractExtensionFactory)
+public:
+ QExtensionFactory(QExtensionManager *parent = 0);
+
+ virtual QObject *extension(QObject *object, const QString &iid) const;
+ QExtensionManager *extensionManager() const;
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *object);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ typedef QPair<QString,QObject*> IdObjectKey;
+ typedef QMap< IdObjectKey, QObject*> ExtensionMap;
+ mutable ExtensionMap m_extensions;
+ typedef QHash<QObject*, bool> ExtendedSet;
+ mutable ExtendedSet m_extended;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // DEFAULT_EXTENSIONFACTORY_H
diff --git a/tools/designer/src/lib/extension/extension.cpp b/tools/designer/src/lib/extension/extension.cpp
new file mode 100644
index 0000000000..7ff13d0727
--- /dev/null
+++ b/tools/designer/src/lib/extension/extension.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/extension.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractExtensionFactory
+
+ \brief The QAbstractExtensionFactory class provides an interface
+ for extension factories in Qt Designer.
+
+ \inmodule QtDesigner
+
+ QAbstractExtensionFactory is not intended to be instantiated
+ directly; use the QExtensionFactory instead.
+
+ In \QD, extension factories are used to look up and create named
+ extensions as they are required. For that reason, when
+ implementing a custom extension, you must also create a
+ QExtensionFactory, i.e a class that is able to make an instance of
+ your extension, and register it using \QD's \l
+ {QExtensionManager}{extension manager}.
+
+ When an extension is required, \QD's \l
+ {QExtensionManager}{extension manager} will run through all its
+ registered factories calling QExtensionFactory::createExtension()
+ for each until the first one that is able to create the requested
+ extension for the selected object, is found. This factory will
+ then make an instance of the extension.
+
+ \sa QExtensionFactory, QExtensionManager
+*/
+
+/*!
+ \fn QAbstractExtensionFactory::~QAbstractExtensionFactory()
+
+ Destroys the extension factory.
+*/
+
+/*!
+ \fn QObject *QAbstractExtensionFactory::extension(QObject *object, const QString &iid) const
+
+ Returns the extension specified by \a iid for the given \a object.
+*/
+
+
+/*!
+ \class QAbstractExtensionManager
+
+ \brief The QAbstractExtensionManager class provides an interface
+ for extension managers in Qt Designer.
+
+ \inmodule QtDesigner
+
+ QAbstractExtensionManager is not intended to be instantiated
+ directly; use the QExtensionManager instead.
+
+ In \QD, extension are not created until they are required. For
+ that reason, when implementing a custom extension, you must also
+ create a QExtensionFactory, i.e a class that is able to make an
+ instance of your extension, and register it using \QD's \l
+ {QExtensionManager}{extension manager}.
+
+ When an extension is required, \QD's \l
+ {QExtensionManager}{extension manager} will run through all its
+ registered factories calling QExtensionFactory::createExtension()
+ for each until the first one that is able to create the requested
+ extension for the selected object, is found. This factory will
+ then make an instance of the extension.
+
+ \sa QExtensionManager, QExtensionFactory
+*/
+
+/*!
+ \fn QAbstractExtensionManager::~QAbstractExtensionManager()
+
+ Destroys the extension manager.
+*/
+
+/*!
+ \fn void QAbstractExtensionManager::registerExtensions(QAbstractExtensionFactory *factory, const QString &iid)
+
+ Register the given extension \a factory with the extension
+ specified by \a iid.
+*/
+
+/*!
+ \fn void QAbstractExtensionManager::unregisterExtensions(QAbstractExtensionFactory *factory, const QString &iid)
+
+ Unregister the given \a factory with the extension specified by \a
+ iid.
+*/
+
+/*!
+ \fn QObject *QAbstractExtensionManager::extension(QObject *object, const QString &iid) const
+
+ Returns the extension, specified by \a iid, for the given \a
+ object.
+*/
+
+/*!
+ \fn T qt_extension(QAbstractExtensionManager* manager, QObject *object)
+
+ \relates QExtensionManager
+
+ Returns the extension of the given \a object cast to type T if the
+ object is of type T (or of a subclass); otherwise returns 0. The
+ extension is retrieved using the given extension \a manager.
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_extension_extension.cpp 0
+
+ When implementing a custom widget plugin, a pointer to \QD's
+ current QDesignerFormEditorInterface object (\c formEditor) is
+ provided by the QDesignerCustomWidgetInterface::initialize()
+ function's parameter.
+
+ If the widget in the example above doesn't have a defined
+ QDesignerPropertySheetExtension, \c propertySheet will be a null
+ pointer.
+
+*/
+
+/*!
+ \macro Q_DECLARE_EXTENSION_INTERFACE(ExtensionName, Identifier)
+
+ \relates QExtensionManager
+
+ Associates the given \a Identifier (a string literal) to the
+ extension class called \a ExtensionName. The \a Identifier must be
+ unique. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_extension_extension.cpp 1
+
+ Using the company and product names is a good way to ensure
+ uniqueness of the identifier.
+
+ When implementing a custom extension class, you must use
+ Q_DECLARE_EXTENSION_INTERFACE() to enable usage of the
+ qt_extension() function. The macro is normally located right after the
+ class definition for \a ExtensionName, in the associated header
+ file.
+
+ \sa Q_DECLARE_INTERFACE()
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/extension/extension.h b/tools/designer/src/lib/extension/extension.h
new file mode 100644
index 0000000000..1ccd4efac2
--- /dev/null
+++ b/tools/designer/src/lib/extension/extension.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EXTENSION_H
+#define EXTENSION_H
+
+#include <QtCore/QString>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#define Q_TYPEID(IFace) QLatin1String(IFace##_iid)
+
+class QAbstractExtensionFactory
+{
+public:
+ virtual ~QAbstractExtensionFactory() {}
+
+ virtual QObject *extension(QObject *object, const QString &iid) const = 0;
+};
+Q_DECLARE_INTERFACE(QAbstractExtensionFactory, "com.trolltech.Qt.QAbstractExtensionFactory")
+
+class QAbstractExtensionManager
+{
+public:
+ virtual ~QAbstractExtensionManager() {}
+
+ virtual void registerExtensions(QAbstractExtensionFactory *factory, const QString &iid) = 0;
+ virtual void unregisterExtensions(QAbstractExtensionFactory *factory, const QString &iid) = 0;
+
+ virtual QObject *extension(QObject *object, const QString &iid) const = 0;
+};
+Q_DECLARE_INTERFACE(QAbstractExtensionManager, "com.trolltech.Qt.QAbstractExtensionManager")
+
+#if defined(Q_CC_MSVC) && (_MSC_VER < 1300)
+
+template <class T>
+inline T qt_extension_helper(QAbstractExtensionManager *, QObject *, T)
+{ return 0; }
+
+template <class T>
+inline T qt_extension(QAbstractExtensionManager* manager, QObject *object)
+{ return qt_extension_helper(manager, object, T(0)); }
+
+#define Q_DECLARE_EXTENSION_INTERFACE(IFace, IId) \
+const char * const IFace##_iid = IId; \
+Q_DECLARE_INTERFACE(IFace, IId) \
+template <> inline IFace *qt_extension_helper<IFace *>(QAbstractExtensionManager *manager, QObject *object, IFace *) \
+{ QObject *extension = manager->extension(object, Q_TYPEID(IFace)); return (IFace *)(extension ? extension->qt_metacast(IFace##_iid) : 0); }
+
+#else
+
+template <class T>
+inline T qt_extension(QAbstractExtensionManager* manager, QObject *object)
+{ return 0; }
+
+#define Q_DECLARE_EXTENSION_INTERFACE(IFace, IId) \
+const char * const IFace##_iid = IId; \
+Q_DECLARE_INTERFACE(IFace, IId) \
+template <> inline IFace *qt_extension<IFace *>(QAbstractExtensionManager *manager, QObject *object) \
+{ QObject *extension = manager->extension(object, Q_TYPEID(IFace)); return extension ? static_cast<IFace *>(extension->qt_metacast(IFace##_iid)) : static_cast<IFace *>(0); }
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // EXTENSION_H
diff --git a/tools/designer/src/lib/extension/extension.pri b/tools/designer/src/lib/extension/extension.pri
new file mode 100644
index 0000000000..d8ef658f25
--- /dev/null
+++ b/tools/designer/src/lib/extension/extension.pri
@@ -0,0 +1,12 @@
+# Input
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/default_extensionfactory.h \
+ $$PWD/extension.h \
+ $$PWD/qextensionmanager.h
+
+SOURCES += $$PWD/default_extensionfactory.cpp \
+ $$PWD/extension.cpp \
+ $$PWD/qextensionmanager.cpp
+
diff --git a/tools/designer/src/lib/extension/extension_global.h b/tools/designer/src/lib/extension/extension_global.h
new file mode 100644
index 0000000000..abd18d81d3
--- /dev/null
+++ b/tools/designer/src/lib/extension/extension_global.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EXTENSION_GLOBAL_H
+#define EXTENSION_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#define QDESIGNER_EXTENSION_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_EXTENSION_IMPORT Q_DECL_IMPORT
+
+#ifdef QT_DESIGNER_STATIC
+# define QDESIGNER_EXTENSION_EXPORT
+#elif defined(QDESIGNER_EXTENSION_LIBRARY)
+# define QDESIGNER_EXTENSION_EXPORT QDESIGNER_EXTENSION_EXTERN
+#else
+# define QDESIGNER_EXTENSION_EXPORT QDESIGNER_EXTENSION_IMPORT
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // EXTENSION_GLOBAL_H
diff --git a/tools/designer/src/lib/extension/qextensionmanager.cpp b/tools/designer/src/lib/extension/qextensionmanager.cpp
new file mode 100644
index 0000000000..686c0917d6
--- /dev/null
+++ b/tools/designer/src/lib/extension/qextensionmanager.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qextensionmanager.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QExtensionManager
+
+ \brief The QExtensionManager class provides extension management
+ facilities for Qt Designer.
+
+ \inmodule QtDesigner
+
+ In \QD the extensions are not created until they are required. For
+ that reason, when implementing an extension, you must also create
+ a QExtensionFactory, i.e a class that is able to make an instance
+ of your extension, and register it using \QD's extension manager.
+
+ The registration of an extension factory is typically made in the
+ QDesignerCustomWidgetInterface::initialize() function:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_extension_qextensionmanager.cpp 0
+
+ The QExtensionManager is not intended to be instantiated
+ directly. You can retrieve an interface to \QD's extension manager
+ using the QDesignerFormEditorInterface::extensionManager()
+ function. A pointer to \QD's current QDesignerFormEditorInterface
+ object (\c formEditor in the example above) is provided by the
+ QDesignerCustomWidgetInterface::initialize() function's
+ parameter. When implementing a custom widget plugin, you must
+ subclass the QDesignerCustomWidgetInterface to expose your plugin
+ to \QD.
+
+ Then, when an extension is required, \QD's extension manager will
+ run through all its registered factories calling
+ QExtensionFactory::createExtension() for each until the first one
+ that is able to create the requested extension for the selected
+ object, is found. This factory will then make an instance of the
+ extension.
+
+ There are four available types of extensions in \QD:
+ QDesignerContainerExtension , QDesignerMemberSheetExtension,
+ QDesignerPropertySheetExtension and
+ QDesignerTaskMenuExtension. \QD's behavior is the same whether the
+ requested extension is associated with a container, a member
+ sheet, a property sheet or a task menu.
+
+ For a complete example using the QExtensionManager class, see the
+ \l {designer/taskmenuextension}{Task Menu Extension example}. The
+ example shows how to create a custom widget plugin for Qt
+ Designer, and how to to use the QDesignerTaskMenuExtension class
+ to add custom items to \QD's task menu.
+
+ \sa QExtensionFactory, QAbstractExtensionManager
+*/
+
+/*!
+ Constructs an extension manager with the given \a parent.
+*/
+QExtensionManager::QExtensionManager(QObject *parent)
+ : QObject(parent)
+{
+}
+
+
+/*!
+ Destroys the extension manager
+*/
+QExtensionManager::~QExtensionManager()
+{
+}
+
+/*!
+ Register the extension specified by the given \a factory and
+ extension identifier \a iid.
+*/
+void QExtensionManager::registerExtensions(QAbstractExtensionFactory *factory, const QString &iid)
+{
+ if (iid.isEmpty()) {
+ m_globalExtension.prepend(factory);
+ return;
+ }
+
+ FactoryMap::iterator it = m_extensions.find(iid);
+ if (it == m_extensions.end())
+ it = m_extensions.insert(iid, FactoryList());
+
+ it.value().prepend(factory);
+}
+
+/*!
+ Unregister the extension specified by the given \a factory and
+ extension identifier \a iid.
+*/
+void QExtensionManager::unregisterExtensions(QAbstractExtensionFactory *factory, const QString &iid)
+{
+ if (iid.isEmpty()) {
+ m_globalExtension.removeAll(factory);
+ return;
+ }
+
+ const FactoryMap::iterator it = m_extensions.find(iid);
+ if (it == m_extensions.end())
+ return;
+
+ FactoryList &factories = it.value();
+ factories.removeAll(factory);
+
+ if (factories.isEmpty())
+ m_extensions.erase(it);
+}
+
+/*!
+ Returns the extension specified by \a iid, for the given \a
+ object.
+*/
+QObject *QExtensionManager::extension(QObject *object, const QString &iid) const
+{
+ const FactoryMap::const_iterator it = m_extensions.constFind(iid);
+ if (it != m_extensions.constEnd()) {
+ const FactoryList::const_iterator fcend = it.value().constEnd();
+ for (FactoryList::const_iterator fit = it.value().constBegin(); fit != fcend; ++fit)
+ if (QObject *ext = (*fit)->extension(object, iid))
+ return ext;
+ }
+ const FactoryList::const_iterator gfcend = m_globalExtension.constEnd();
+ for (FactoryList::const_iterator git = m_globalExtension.constBegin(); git != gfcend; ++git)
+ if (QObject *ext = (*git)->extension(object, iid))
+ return ext;
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/extension/qextensionmanager.h b/tools/designer/src/lib/extension/qextensionmanager.h
new file mode 100644
index 0000000000..a5b727f61a
--- /dev/null
+++ b/tools/designer/src/lib/extension/qextensionmanager.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEXTENSIONMANAGER_H
+#define QEXTENSIONMANAGER_H
+
+#include <QtDesigner/extension_global.h>
+#include <QtDesigner/extension.h>
+#include <QtCore/QHash>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QObject; // Fool syncqt
+
+class QDESIGNER_EXTENSION_EXPORT QExtensionManager: public QObject, public QAbstractExtensionManager
+{
+ Q_OBJECT
+ Q_INTERFACES(QAbstractExtensionManager)
+public:
+ QExtensionManager(QObject *parent = 0);
+ ~QExtensionManager();
+
+ virtual void registerExtensions(QAbstractExtensionFactory *factory, const QString &iid = QString());
+ virtual void unregisterExtensions(QAbstractExtensionFactory *factory, const QString &iid = QString());
+
+ virtual QObject *extension(QObject *object, const QString &iid) const;
+
+private:
+ typedef QList<QAbstractExtensionFactory*> FactoryList;
+ typedef QHash<QString, FactoryList> FactoryMap;
+ FactoryMap m_extensions;
+ FactoryList m_globalExtension;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QEXTENSIONMANAGER_H
diff --git a/tools/designer/src/lib/lib.pro b/tools/designer/src/lib/lib.pro
new file mode 100644
index 0000000000..e0f2f2357a
--- /dev/null
+++ b/tools/designer/src/lib/lib.pro
@@ -0,0 +1,78 @@
+TEMPLATE=lib
+TARGET=QtDesigner
+QT += xml
+contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
+CONFIG += qt
+win32|mac: CONFIG += debug_and_release
+DESTDIR = ../../../../lib
+!wince*:DLLDESTDIR = ../../../../bin
+
+isEmpty(QT_MAJOR_VERSION) {
+ VERSION=4.3.0
+} else {
+ VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}
+}
+
+unix:QMAKE_PKGCONFIG_REQUIRES += QtXml
+
+include(../../../../src/qt_targets.pri)
+QMAKE_TARGET_PRODUCT = Designer
+QMAKE_TARGET_DESCRIPTION = Graphical user interface designer.
+
+!contains(CONFIG, static) {
+ CONFIG += dll
+
+ DEFINES += \
+ QDESIGNER_SDK_LIBRARY \
+ QDESIGNER_EXTENSION_LIBRARY \
+ QDESIGNER_UILIB_LIBRARY \
+ QDESIGNER_SHARED_LIBRARY
+} else {
+ DEFINES += QT_DESIGNER_STATIC
+}
+
+#load up the headers info
+CONFIG += qt_install_headers
+HEADERS_PRI = $$QT_BUILD_TREE/include/QtDesigner/headers.pri
+include($$HEADERS_PRI)|clear(HEADERS_PRI)
+
+#mac frameworks
+mac:CONFIG += explicitlib
+mac:!static:contains(QT_CONFIG, qt_framework) {
+ QMAKE_FRAMEWORK_BUNDLE_NAME = $$TARGET
+ CONFIG += lib_bundle qt_no_framework_direct_includes qt_framework
+ CONFIG(debug, debug|release) {
+ !build_pass:CONFIG += build_all
+ } else { #release
+ !debug_and_release|build_pass {
+ CONFIG -= qt_install_headers #no need to install these as well
+ FRAMEWORK_HEADERS.version = Versions
+ FRAMEWORK_HEADERS.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES
+ FRAMEWORK_HEADERS.path = Headers
+ }
+ QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS
+ }
+}
+
+include(extension/extension.pri)
+include(sdk/sdk.pri)
+include(uilib/uilib.pri)
+include(shared/shared.pri)
+PRECOMPILED_HEADER=lib_pch.h
+
+include(../sharedcomponents.pri)
+include(../components/component.pri)
+
+target.path=$$[QT_INSTALL_LIBS]
+INSTALLS += target
+win32 {
+ dlltarget.path=$$[QT_INSTALL_BINS]
+ INSTALLS += dlltarget
+}
+
+
+qt_install_headers {
+ designer_headers.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES
+ designer_headers.path = $$[QT_INSTALL_HEADERS]/QtDesigner
+ INSTALLS += designer_headers
+}
diff --git a/tools/designer/src/lib/lib_pch.h b/tools/designer/src/lib/lib_pch.h
new file mode 100644
index 0000000000..27c5905ae3
--- /dev/null
+++ b/tools/designer/src/lib/lib_pch.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifdef __cplusplus
+#include "shared_global_p.h"
+#include <QtCore/qdebug.h>
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/sdk_global.h>
+#include <QtCore/QObject>
+#include <QtDesigner/qextensionmanager.h>
+#include <QtDesigner/abstractformwindow.h>
+#include <QtCore/QMap>
+#include <QtGui/QWidget>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/extension.h>
+#include <QtDesigner/abstractmetadatabase.h>
+#include <QtCore/QList>
+#include <QtDesigner/abstractwidgetfactory.h>
+#include <QtDesigner/abstractwidgetdatabase.h>
+#include <QtGui/QWidget>
+#include "qdesigner_widget_p.h"
+#include <QtGui/QPainter>
+#include <QtGui/QMainWindow>
+#include <QtCore/qglobal.h>
+#include <QtCore/QPointer>
+#include "layout_p.h"
+#endif
diff --git a/tools/designer/src/lib/sdk/abstractactioneditor.cpp b/tools/designer/src/lib/sdk/abstractactioneditor.cpp
new file mode 100644
index 0000000000..e3b870a134
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractactioneditor.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractactioneditor.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerActionEditorInterface
+
+ \brief The QDesignerActionEditorInterface class allows you to
+ change the focus of Qt Designer's action editor.
+
+ \inmodule QtDesigner
+
+ The QDesignerActionEditorInterface class is not intended to be
+ instantiated directly. You can retrieve an interface to \QD's
+ action editor using the
+ QDesignerFormEditorInterface::actionEditor() function.
+
+ You can control which actions that are available in the action
+ editor's window using the manageAction() and unmanageAction()
+ functions. An action that is managed by \QD is available in the
+ action editor while an unmanaged action is ignored.
+
+ QDesignerActionEditorInterface also provides the core() function
+ that you can use to retrieve a pointer to \QD's current
+ QDesignerFormEditorInterface object, and the setFormWindow()
+ function that enables you to change the currently selected form
+ window.
+
+ \sa QDesignerFormEditorInterface, QDesignerFormWindowInterface
+*/
+
+/*!
+ Constructs an action editor interface with the given \a parent and
+ the specified window \a flags.
+*/
+QDesignerActionEditorInterface::QDesignerActionEditorInterface(QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags)
+{
+}
+
+/*!
+ Destroys the action editor interface.
+*/
+QDesignerActionEditorInterface::~QDesignerActionEditorInterface()
+{
+}
+
+/*!
+ Returns a pointer to \QD's current QDesignerFormEditorInterface
+ object.
+*/
+QDesignerFormEditorInterface *QDesignerActionEditorInterface::core() const
+{
+ return 0;
+}
+
+/*!
+ \fn void QDesignerActionEditorInterface::setFormWindow(QDesignerFormWindowInterface *formWindow)
+
+ Sets the currently selected form window to \a formWindow.
+
+*/
+
+/*!
+ \fn void QDesignerActionEditorInterface::manageAction(QAction *action)
+
+ Instructs \QD to manage the specified \a action. An action that is
+ managed by \QD is available in the action editor.
+
+ \sa unmanageAction()
+*/
+
+/*!
+ \fn void QDesignerActionEditorInterface::unmanageAction(QAction *action)
+
+ Instructs \QD to ignore the specified \a action. An unmanaged
+ action is not available in the action editor.
+
+ \sa manageAction()
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractactioneditor.h b/tools/designer/src/lib/sdk/abstractactioneditor.h
new file mode 100644
index 0000000000..7408a52ec4
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractactioneditor.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTACTIONEDITOR_H
+#define ABSTRACTACTIONEDITOR_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerActionEditorInterface: public QWidget
+{
+ Q_OBJECT
+public:
+ QDesignerActionEditorInterface(QWidget *parent, Qt::WindowFlags flags = 0);
+ virtual ~QDesignerActionEditorInterface();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual void manageAction(QAction *action) = 0;
+ virtual void unmanageAction(QAction *action) = 0;
+
+public Q_SLOTS:
+ virtual void setFormWindow(QDesignerFormWindowInterface *formWindow) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTACTIONEDITOR_H
diff --git a/tools/designer/src/lib/sdk/abstractbrushmanager.h b/tools/designer/src/lib/sdk/abstractbrushmanager.h
new file mode 100644
index 0000000000..493ca25ff4
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractbrushmanager.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTBRUSHMANAGER_H
+#define ABSTRACTBRUSHMANAGER_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmap.h>
+#include <QtGui/qbrush.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+
+class QDESIGNER_SDK_EXPORT QDesignerBrushManagerInterface : public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerBrushManagerInterface(QObject *parentObject = 0) : QObject(parentObject) {}
+
+ virtual QBrush brush(const QString &name) const = 0;
+ virtual QMap<QString, QBrush> brushes() const = 0;
+ virtual QString currentBrush() const = 0;
+
+ virtual QString addBrush(const QString &name, const QBrush &brush) = 0;
+ virtual void removeBrush(const QString &name) = 0;
+ virtual void setCurrentBrush(const QString &name) = 0;
+
+ virtual QPixmap brushPixmap(const QBrush &brush) const = 0;
+Q_SIGNALS:
+ void brushAdded(const QString &name, const QBrush &brush);
+ void brushRemoved(const QString &name);
+ void currentBrushChanged(const QString &name, const QBrush &brush);
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/designer/src/lib/sdk/abstractdialoggui.cpp b/tools/designer/src/lib/sdk/abstractdialoggui.cpp
new file mode 100644
index 0000000000..690fb51392
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractdialoggui.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractdialoggui_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerDialogGuiInterface
+ \since 4.4
+ \internal
+
+ \brief The QDesignerDialogGuiInterface allows integrations of \QD to replace the
+ message boxes displayed by \QD by custom dialogs.
+
+ \inmodule QtDesigner
+
+ QDesignerDialogGuiInterface provides virtual functions that can be overwritten
+ to display message boxes and file dialogs.
+ \sa QMessageBox, QFileDialog
+*/
+
+/*!
+ \enum QDesignerDialogGuiInterface::Message
+
+ This enum specifies the context from within the message box is called.
+
+ \value FormLoadFailureMessage Loading of a form failed
+ \value UiVersionMismatchMessage Attempt to load a file created with an old version of Designer
+ \value ResourceLoadFailureMessage Resources specified in a file could not be found
+ \value TopLevelSpacerMessage Spacer items detected on a container without layout
+ \value PropertyEditorMessage Messages of the propert yeditor
+ \value SignalSlotEditorMessage Messages of the signal / slot editor
+ \value FormEditorMessage Messages of the form editor
+ \value PreviewFailureMessage A preview could not be created
+ \value PromotionErrorMessage Messages related to promotion of a widget
+ \value ResourceEditorMessage Messages of the resource editor
+ \value ScriptDialogMessage Messages of the script dialog
+ \value SignalSlotDialogMessage Messages of the signal slot dialog
+ \value OtherMessage Unspecified context
+*/
+
+/*!
+ Constructs a QDesignerDialogGuiInterface object.
+*/
+
+QDesignerDialogGuiInterface::QDesignerDialogGuiInterface()
+{
+}
+
+/*!
+ Destroys the QDesignerDialogGuiInterface object.
+*/
+QDesignerDialogGuiInterface::~QDesignerDialogGuiInterface()
+{
+}
+
+/*!
+ \fn QMessageBox::StandardButton QDesignerDialogGuiInterface::message(QWidget *parent, Message context, QMessageBox::Icon icon, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
+
+ Opens a message box as child of \a parent within the context \a context, using \a icon, \a title, \a text, \a buttons and \a defaultButton
+ and returns the button chosen by the user.
+*/
+
+/*!
+ \fn QString QDesignerDialogGuiInterface::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options)
+
+ Opens a file dialog as child of \a parent using the parameters \a caption, \a dir and \a options that prompts the
+ user for an existing directory. Returns a directory selected by the user.
+*/
+
+/*!
+ \fn QString QDesignerDialogGuiInterface::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options)
+
+ Opens a file dialog as child of \a parent using the parameters \a caption, \a dir, \a filter, \a selectedFilter and \a options
+ that prompts the user for an existing file. Returns a file selected by the user.
+*/
+
+/*!
+ \fn QStringList QDesignerDialogGuiInterface::getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options)
+
+ Opens a file dialog as child of \a parent using the parameters \a caption, \a dir, \a filter, \a selectedFilter and \a options
+ that prompts the user for a set of existing files. Returns one or more existing files selected by the user.
+*/
+
+/*!
+ Opens a file dialog with image browsing capabilities as child of \a parent using the parameters \a caption, \a dir, \a filter, \a selectedFilter and \a options
+ that prompts the user for an existing file. Returns a file selected by the user.
+
+ The default implementation simply calls getOpenFileName(). On platforms that do not support an image preview in the QFileDialog,
+ the function can be reimplemented to provide an image browser.
+
+ \since 4.5
+*/
+
+QString QDesignerDialogGuiInterface::getOpenImageFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
+{
+ return getOpenFileName(parent, caption, dir, filter, selectedFilter, options);
+}
+
+/*!
+ Opens a file dialog with image browsing capabilities as child of \a parent using the parameters \a caption, \a dir, \a filter, \a selectedFilter and \a options
+ that prompts the user for a set of existing files. Returns one or more existing files selected by the user.
+
+ The default implementation simply calls getOpenFileNames(). On platforms that do not support an image preview in the QFileDialog,
+ the function can be reimplemented to provide an image browser.
+
+ \since 4.5
+*/
+
+QStringList QDesignerDialogGuiInterface::getOpenImageFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
+{
+ return getOpenImageFileNames(parent, caption, dir, filter, selectedFilter, options);
+}
+
+/*!
+ \fn QString QDesignerDialogGuiInterface::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options)
+
+ Opens a file dialog as child of \a parent using the parameters \a caption, \a dir, \a filter, \a selectedFilter and \a options
+ that prompts the user for a file. Returns a file selected by the user. The file does not have to exist.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractdialoggui_p.h b/tools/designer/src/lib/sdk/abstractdialoggui_p.h
new file mode 100644
index 0000000000..faaa7e503f
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractdialoggui_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ABSTRACTDIALOGGUI_H
+#define ABSTRACTDIALOGGUI_H
+
+#include <QtDesigner/sdk_global.h>
+#include <QtGui/QMessageBox>
+#include <QtGui/QFileDialog>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+
+class QDESIGNER_SDK_EXPORT QDesignerDialogGuiInterface
+{
+ Q_DISABLE_COPY(QDesignerDialogGuiInterface)
+public:
+ QDesignerDialogGuiInterface();
+ virtual ~QDesignerDialogGuiInterface();
+
+ enum Message { FormLoadFailureMessage, UiVersionMismatchMessage, ResourceLoadFailureMessage,
+ TopLevelSpacerMessage, PropertyEditorMessage, SignalSlotEditorMessage, FormEditorMessage,
+ PreviewFailureMessage, PromotionErrorMessage, ResourceEditorMessage,
+ ScriptDialogMessage, SignalSlotDialogMessage, OtherMessage, FileChangedMessage };
+
+ virtual QMessageBox::StandardButton
+ message(QWidget *parent, Message context, QMessageBox::Icon icon,
+ const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
+ QMessageBox::StandardButton defaultButton = QMessageBox::NoButton) = 0;
+
+ virtual QMessageBox::StandardButton
+ message(QWidget *parent, Message context, QMessageBox::Icon icon,
+ const QString &title, const QString &text, const QString &informativeText,
+ QMessageBox::StandardButtons buttons = QMessageBox::Ok,
+ QMessageBox::StandardButton defaultButton = QMessageBox::NoButton) = 0;
+
+ virtual QMessageBox::StandardButton
+ message(QWidget *parent, Message context, QMessageBox::Icon icon,
+ const QString &title, const QString &text, const QString &informativeText, const QString &detailedText,
+ QMessageBox::StandardButtons buttons = QMessageBox::Ok,
+ QMessageBox::StandardButton defaultButton = QMessageBox::NoButton) = 0;
+
+ virtual QString getExistingDirectory(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), QFileDialog::Options options = QFileDialog::ShowDirsOnly)= 0;
+ virtual QString getOpenFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0)= 0;
+ virtual QString getOpenImageFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
+ virtual QStringList getOpenFileNames(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0)= 0;
+ virtual QStringList getOpenImageFileNames(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
+ virtual QString getSaveFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0)= 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTDIALOGGUI_H
diff --git a/tools/designer/src/lib/sdk/abstractdnditem.h b/tools/designer/src/lib/sdk/abstractdnditem.h
new file mode 100644
index 0000000000..fca12956ef
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractdnditem.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTDNDITEM_H
+#define ABSTRACTDNDITEM_H
+
+#include <QtDesigner/sdk_global.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DomUI;
+class QWidget;
+class QPoint;
+
+class QDESIGNER_SDK_EXPORT QDesignerDnDItemInterface
+{
+public:
+ enum DropType { MoveDrop, CopyDrop };
+
+ QDesignerDnDItemInterface() {}
+ virtual ~QDesignerDnDItemInterface() {}
+
+ virtual DomUI *domUi() const = 0;
+ virtual QWidget *widget() const = 0;
+ virtual QWidget *decoration() const = 0;
+ virtual QPoint hotSpot() const = 0;
+ virtual DropType type() const = 0;
+ virtual QWidget *source() const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTDNDITEM_H
diff --git a/tools/designer/src/lib/sdk/abstractformeditor.cpp b/tools/designer/src/lib/sdk/abstractformeditor.cpp
new file mode 100644
index 0000000000..17e93e769e
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformeditor.cpp
@@ -0,0 +1,621 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformeditor.h"
+#include "abstractdialoggui_p.h"
+#include "abstractintrospection_p.h"
+#include "abstractsettings_p.h"
+#include "abstractoptionspage_p.h"
+
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtDesigner/QDesignerBrushManagerInterface>
+#include <QtDesigner/QDesignerIntegrationInterface>
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerActionEditorInterface>
+#include <pluginmanager_p.h>
+#include <qtresourcemodel_p.h>
+#include <qtgradientmanager.h>
+#include <widgetfactory_p.h>
+#include <shared_settings_p.h>
+#include <formwindowbase_p.h>
+#include <grid_p.h>
+#include <QtDesigner/QDesignerPromotionInterface>
+
+static void initResources()
+{
+ Q_INIT_RESOURCE(shared);
+}
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterfacePrivate {
+public:
+ QDesignerFormEditorInterfacePrivate();
+ ~QDesignerFormEditorInterfacePrivate();
+
+
+ QPointer<QWidget> m_topLevel;
+ QPointer<QDesignerWidgetBoxInterface> m_widgetBox;
+ QPointer<QDesignerPropertyEditorInterface> m_propertyEditor;
+ QPointer<QDesignerFormWindowManagerInterface> m_formWindowManager;
+ QPointer<QExtensionManager> m_extensionManager;
+ QPointer<QDesignerMetaDataBaseInterface> m_metaDataBase;
+ QPointer<QDesignerWidgetDataBaseInterface> m_widgetDataBase;
+ QPointer<QDesignerWidgetFactoryInterface> m_widgetFactory;
+ QPointer<QDesignerObjectInspectorInterface> m_objectInspector;
+ QPointer<QDesignerBrushManagerInterface> m_brushManager;
+ QPointer<QDesignerIntegrationInterface> m_integration;
+ QPointer<QDesignerIconCacheInterface> m_iconCache;
+ QPointer<QDesignerActionEditorInterface> m_actionEditor;
+ QDesignerSettingsInterface *m_settingsManager;
+ QDesignerPluginManager *m_pluginManager;
+ QDesignerPromotionInterface *m_promotion;
+ QDesignerIntrospectionInterface *m_introspection;
+ QDesignerDialogGuiInterface *m_dialogGui;
+ QPointer<QtResourceModel> m_resourceModel;
+ QPointer<QtGradientManager> m_gradientManager; // instantiated and deleted by designer_integration
+ QList<QDesignerOptionsPageInterface*> m_optionsPages;
+};
+
+QDesignerFormEditorInterfacePrivate::QDesignerFormEditorInterfacePrivate() :
+ m_settingsManager(0),
+ m_pluginManager(0),
+ m_promotion(0),
+ m_introspection(0),
+ m_dialogGui(0),
+ m_resourceModel(0),
+ m_gradientManager(0)
+{
+}
+
+QDesignerFormEditorInterfacePrivate::~QDesignerFormEditorInterfacePrivate()
+{
+ delete m_settingsManager;
+ delete m_formWindowManager;
+ delete m_promotion;
+ delete m_introspection;
+ delete m_dialogGui;
+ delete m_resourceModel;
+ qDeleteAll(m_optionsPages);
+}
+
+/*!
+ \class QDesignerFormEditorInterface
+
+ \brief The QDesignerFormEditorInterface class allows you to access
+ Qt Designer's various components.
+
+ \inmodule QtDesigner
+
+ \QD's current QDesignerFormEditorInterface object holds
+ information about all \QD's components: The action editor, the
+ object inspector, the property editor, the widget box, and the
+ extension and form window managers. QDesignerFormEditorInterface
+ contains a collection of functions that provides interfaces to all
+ these components. They are typically used to query (and
+ manipulate) the respective component. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformeditor.cpp 0
+
+ QDesignerFormEditorInterface is not intended to be instantiated
+ directly. A pointer to \QD's current QDesignerFormEditorInterface
+ object (\c formEditor in the example above) is provided by the
+ QDesignerCustomWidgetInterface::initialize() function's
+ parameter. When implementing a custom widget plugin, you must
+ subclass the QDesignerCustomWidgetInterface to expose your plugin
+ to \QD.
+
+ QDesignerFormEditorInterface also provides functions that can set
+ the action editor, property editor, object inspector and widget
+ box. These are only useful if you want to provide your own custom
+ components.
+
+ If designer is embedded in another program, one could to provide its
+ own settings manager. The manager is used by the components of \QD
+ to store/retrieve persistent configuration settings. The default
+ manager uses QSettings as the backend.
+
+ Finally, QDesignerFormEditorInterface provides the topLevel()
+ function that returns \QD's top-level widget.
+
+ \sa QDesignerCustomWidgetInterface
+*/
+
+/*!
+ Constructs a QDesignerFormEditorInterface object with the given \a
+ parent.
+*/
+
+QDesignerFormEditorInterface::QDesignerFormEditorInterface(QObject *parent)
+ : QObject(parent),
+ d(new QDesignerFormEditorInterfacePrivate())
+{
+ initResources();
+}
+
+/*!
+ Destroys the QDesignerFormEditorInterface object.
+*/
+QDesignerFormEditorInterface::~QDesignerFormEditorInterface()
+{
+ delete d;
+}
+
+/*!
+ Returns an interface to \QD's widget box.
+
+ \sa setWidgetBox()
+*/
+QDesignerWidgetBoxInterface *QDesignerFormEditorInterface::widgetBox() const
+{
+ return d->m_widgetBox;
+}
+
+/*!
+ Sets \QD's widget box to be the specified \a widgetBox.
+
+ \sa widgetBox()
+*/
+void QDesignerFormEditorInterface::setWidgetBox(QDesignerWidgetBoxInterface *widgetBox)
+{
+ d->m_widgetBox = widgetBox;
+}
+
+/*!
+ Returns an interface to \QD's property editor.
+
+ \sa setPropertyEditor()
+*/
+QDesignerPropertyEditorInterface *QDesignerFormEditorInterface::propertyEditor() const
+{
+ return d->m_propertyEditor;
+}
+
+/*!
+ Sets \QD's property editor to be the specified \a propertyEditor.
+
+ \sa propertyEditor()
+*/
+void QDesignerFormEditorInterface::setPropertyEditor(QDesignerPropertyEditorInterface *propertyEditor)
+{
+ d->m_propertyEditor = propertyEditor;
+}
+
+/*!
+ Returns an interface to \QD's action editor.
+
+ \sa setActionEditor()
+*/
+QDesignerActionEditorInterface *QDesignerFormEditorInterface::actionEditor() const
+{
+ return d->m_actionEditor;
+}
+
+/*!
+ Sets \QD's action editor to be the specified \a actionEditor.
+
+ \sa actionEditor()
+*/
+void QDesignerFormEditorInterface::setActionEditor(QDesignerActionEditorInterface *actionEditor)
+{
+ d->m_actionEditor = actionEditor;
+}
+
+/*!
+ Returns \QD's top-level widget.
+*/
+QWidget *QDesignerFormEditorInterface::topLevel() const
+{
+ return d->m_topLevel;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setTopLevel(QWidget *topLevel)
+{
+ d->m_topLevel = topLevel;
+}
+
+/*!
+ Returns an interface to \QD's form window manager.
+*/
+QDesignerFormWindowManagerInterface *QDesignerFormEditorInterface::formWindowManager() const
+{
+ return d->m_formWindowManager;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setFormManager(QDesignerFormWindowManagerInterface *formWindowManager)
+{
+ d->m_formWindowManager = formWindowManager;
+}
+
+/*!
+ Returns an interface to \QD's extension manager.
+*/
+QExtensionManager *QDesignerFormEditorInterface::extensionManager() const
+{
+ return d->m_extensionManager;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setExtensionManager(QExtensionManager *extensionManager)
+{
+ d->m_extensionManager = extensionManager;
+}
+
+/*!
+ \internal
+
+ Returns an interface to the meta database used by the form editor.
+*/
+QDesignerMetaDataBaseInterface *QDesignerFormEditorInterface::metaDataBase() const
+{
+ return d->m_metaDataBase;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setMetaDataBase(QDesignerMetaDataBaseInterface *metaDataBase)
+{
+ d->m_metaDataBase = metaDataBase;
+}
+
+/*!
+ \internal
+
+ Returns an interface to the widget database used by the form editor.
+*/
+QDesignerWidgetDataBaseInterface *QDesignerFormEditorInterface::widgetDataBase() const
+{
+ return d->m_widgetDataBase;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setWidgetDataBase(QDesignerWidgetDataBaseInterface *widgetDataBase)
+{
+ d->m_widgetDataBase = widgetDataBase;
+}
+
+/*!
+ \internal
+
+ Returns an interface to the designer promotion handler.
+*/
+
+QDesignerPromotionInterface *QDesignerFormEditorInterface::promotion() const
+{
+ return d->m_promotion;
+}
+
+/*!
+ \internal
+
+ Sets the designer promotion handler.
+*/
+
+void QDesignerFormEditorInterface::setPromotion(QDesignerPromotionInterface *promotion)
+{
+ if (d->m_promotion)
+ delete d->m_promotion;
+ d->m_promotion = promotion;
+}
+
+/*!
+ \internal
+
+ Returns an interface to the widget factory used by the form editor
+ to create widgets for the form.
+*/
+QDesignerWidgetFactoryInterface *QDesignerFormEditorInterface::widgetFactory() const
+{
+ return d->m_widgetFactory;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setWidgetFactory(QDesignerWidgetFactoryInterface *widgetFactory)
+{
+ d->m_widgetFactory = widgetFactory;
+}
+
+/*!
+ Returns an interface to \QD's object inspector.
+*/
+QDesignerObjectInspectorInterface *QDesignerFormEditorInterface::objectInspector() const
+{
+ return d->m_objectInspector;
+}
+
+/*!
+ Sets \QD's object inspector to be the specified \a
+ objectInspector.
+
+ \sa objectInspector()
+*/
+void QDesignerFormEditorInterface::setObjectInspector(QDesignerObjectInspectorInterface *objectInspector)
+{
+ d->m_objectInspector = objectInspector;
+}
+
+/*!
+ \internal
+
+ Returns an interface to the brush manager used by the palette editor.
+*/
+QDesignerBrushManagerInterface *QDesignerFormEditorInterface::brushManager() const
+{
+ return d->m_brushManager;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setBrushManager(QDesignerBrushManagerInterface *brushManager)
+{
+ d->m_brushManager = brushManager;
+}
+
+/*!
+ \internal
+
+ Returns an interface to the integration.
+*/
+QDesignerIntegrationInterface *QDesignerFormEditorInterface::integration() const
+{
+ return d->m_integration;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setIntegration(QDesignerIntegrationInterface *integration)
+{
+ d->m_integration = integration;
+}
+
+/*!
+ \internal
+
+ Returns an interface to the icon cache used by the form editor to
+ manage icons.
+*/
+QDesignerIconCacheInterface *QDesignerFormEditorInterface::iconCache() const
+{
+ return d->m_iconCache;
+}
+
+/*!
+ \internal
+*/
+void QDesignerFormEditorInterface::setIconCache(QDesignerIconCacheInterface *cache)
+{
+ d->m_iconCache = cache;
+}
+
+/*!
+ \internal
+ \since 4.5
+ Returns the list of options pages that allow the user to configure \QD components.
+*/
+QList<QDesignerOptionsPageInterface*> QDesignerFormEditorInterface::optionsPages() const
+{
+ return d->m_optionsPages;
+}
+
+/*!
+ \internal
+ \since 4.5
+ Sets the list of options pages that allow the user to configure \QD components.
+*/
+void QDesignerFormEditorInterface::setOptionsPages(const QList<QDesignerOptionsPageInterface*> &optionsPages)
+{
+ d->m_optionsPages = optionsPages;
+}
+
+
+/*!
+ \internal
+
+ Returns the plugin manager used by the form editor.
+*/
+QDesignerPluginManager *QDesignerFormEditorInterface::pluginManager() const
+{
+ return d->m_pluginManager;
+}
+
+/*!
+ \internal
+
+ Sets the plugin manager used by the form editor to the specified
+ \a pluginManager.
+*/
+void QDesignerFormEditorInterface::setPluginManager(QDesignerPluginManager *pluginManager)
+{
+ d->m_pluginManager = pluginManager;
+}
+
+/*!
+ \internal
+ \since 4.4
+ Returns the resource model used by the form editor.
+*/
+QtResourceModel *QDesignerFormEditorInterface::resourceModel() const
+{
+ return d->m_resourceModel;
+}
+
+/*!
+ \internal
+
+ Sets the resource model used by the form editor to the specified
+ \a resourceModel.
+*/
+void QDesignerFormEditorInterface::setResourceModel(QtResourceModel *resourceModel)
+{
+ d->m_resourceModel = resourceModel;
+}
+
+/*!
+ \internal
+ \since 4.4
+ Returns the gradient manager used by the style sheet editor.
+*/
+QtGradientManager *QDesignerFormEditorInterface::gradientManager() const
+{
+ return d->m_gradientManager;
+}
+
+/*!
+ \internal
+
+ Sets the gradient manager used by the style sheet editor to the specified
+ \a gradientManager.
+*/
+void QDesignerFormEditorInterface::setGradientManager(QtGradientManager *gradientManager)
+{
+ d->m_gradientManager = gradientManager;
+}
+
+/*!
+ \internal
+ \since 4.5
+ Returns the settings manager used by the components to store persistent settings.
+*/
+QDesignerSettingsInterface *QDesignerFormEditorInterface::settingsManager() const
+{
+ return d->m_settingsManager;
+}
+
+/*!
+ \internal
+ \since 4.5
+ Sets the settings manager used to store/retrieve the persistent settings of the components.
+*/
+void QDesignerFormEditorInterface::setSettingsManager(QDesignerSettingsInterface *settingsManager)
+{
+ if (d->m_settingsManager)
+ delete d->m_settingsManager;
+ d->m_settingsManager = settingsManager;
+
+ // This is a (hopefully) safe place to perform settings-dependent
+ // initializations.
+ const qdesigner_internal::QDesignerSharedSettings settings(this);
+ qdesigner_internal::FormWindowBase::setDefaultDesignerGrid(settings.defaultGrid());
+}
+
+/*!
+ \internal
+ \since 4.4
+ Returns the introspection used by the form editor.
+*/
+QDesignerIntrospectionInterface *QDesignerFormEditorInterface::introspection() const
+{
+ return d->m_introspection;
+}
+
+/*!
+ \internal
+ \since 4.4
+
+ Sets the introspection used by the form editor to the specified \a introspection.
+*/
+void QDesignerFormEditorInterface::setIntrospection(QDesignerIntrospectionInterface *introspection)
+{
+ if (d->m_introspection)
+ delete d->m_introspection;
+ d->m_introspection = introspection;
+}
+
+/*!
+ \internal
+
+ Returns the path to the resources used by the form editor.
+*/
+QString QDesignerFormEditorInterface::resourceLocation() const
+{
+#ifdef Q_WS_MAC
+ return QLatin1String(":/trolltech/formeditor/images/mac");
+#else
+ return QLatin1String(":/trolltech/formeditor/images/win");
+#endif
+}
+
+/*!
+ \internal
+
+ Returns the dialog GUI used by the form editor.
+*/
+
+QDesignerDialogGuiInterface *QDesignerFormEditorInterface::dialogGui() const
+{
+ return d->m_dialogGui;
+}
+
+/*!
+ \internal
+
+ Sets the dialog GUI used by the form editor to the specified \a dialogGui.
+*/
+
+void QDesignerFormEditorInterface::setDialogGui(QDesignerDialogGuiInterface *dialogGui)
+{
+ delete d->m_dialogGui;
+ d->m_dialogGui = dialogGui;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractformeditor.h b/tools/designer/src/lib/sdk/abstractformeditor.h
new file mode 100644
index 0000000000..0625ce68fa
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformeditor.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMEDITOR_H
+#define ABSTRACTFORMEDITOR_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerWidgetBoxInterface;
+class QDesignerPropertyEditorInterface;
+class QDesignerFormWindowManagerInterface;
+class QDesignerWidgetDataBaseInterface;
+class QDesignerMetaDataBaseInterface;
+class QDesignerWidgetFactoryInterface;
+class QDesignerObjectInspectorInterface;
+class QDesignerPromotionInterface;
+class QDesignerBrushManagerInterface;
+class QDesignerIconCacheInterface;
+class QDesignerActionEditorInterface;
+class QDesignerIntegrationInterface;
+class QDesignerPluginManager;
+class QDesignerIntrospectionInterface;
+class QDesignerDialogGuiInterface;
+class QDesignerSettingsInterface;
+class QDesignerOptionsPageInterface;
+class QtResourceModel;
+class QtGradientManager;
+
+class QWidget;
+
+class QExtensionManager;
+
+class QDesignerFormEditorInterfacePrivate;
+
+class QDESIGNER_SDK_EXPORT QDesignerFormEditorInterface : public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerFormEditorInterface(QObject *parent = 0);
+ virtual ~QDesignerFormEditorInterface();
+
+ QExtensionManager *extensionManager() const;
+
+ QWidget *topLevel() const;
+ QDesignerWidgetBoxInterface *widgetBox() const;
+ QDesignerPropertyEditorInterface *propertyEditor() const;
+ QDesignerObjectInspectorInterface *objectInspector() const;
+ QDesignerFormWindowManagerInterface *formWindowManager() const;
+ QDesignerWidgetDataBaseInterface *widgetDataBase() const;
+ QDesignerMetaDataBaseInterface *metaDataBase() const;
+ QDesignerPromotionInterface *promotion() const;
+ QDesignerWidgetFactoryInterface *widgetFactory() const;
+ QDesignerBrushManagerInterface *brushManager() const;
+ QDesignerIconCacheInterface *iconCache() const;
+ QDesignerActionEditorInterface *actionEditor() const;
+ QDesignerIntegrationInterface *integration() const;
+ QDesignerPluginManager *pluginManager() const;
+ QDesignerIntrospectionInterface *introspection() const;
+ QDesignerDialogGuiInterface *dialogGui() const;
+ QDesignerSettingsInterface *settingsManager() const;
+ QString resourceLocation() const;
+ QtResourceModel *resourceModel() const;
+ QtGradientManager *gradientManager() const;
+ QList<QDesignerOptionsPageInterface*> optionsPages() const;
+
+ void setTopLevel(QWidget *topLevel);
+ void setWidgetBox(QDesignerWidgetBoxInterface *widgetBox);
+ void setPropertyEditor(QDesignerPropertyEditorInterface *propertyEditor);
+ void setObjectInspector(QDesignerObjectInspectorInterface *objectInspector);
+ void setPluginManager(QDesignerPluginManager *pluginManager);
+ void setActionEditor(QDesignerActionEditorInterface *actionEditor);
+ void setIntegration(QDesignerIntegrationInterface *integration);
+ void setIntrospection(QDesignerIntrospectionInterface *introspection);
+ void setDialogGui(QDesignerDialogGuiInterface *dialogGui);
+ void setSettingsManager(QDesignerSettingsInterface *settingsManager);
+ void setResourceModel(QtResourceModel *model);
+ void setGradientManager(QtGradientManager *manager);
+ void setOptionsPages(const QList<QDesignerOptionsPageInterface*> &optionsPages);
+
+protected:
+ void setFormManager(QDesignerFormWindowManagerInterface *formWindowManager);
+ void setMetaDataBase(QDesignerMetaDataBaseInterface *metaDataBase);
+ void setWidgetDataBase(QDesignerWidgetDataBaseInterface *widgetDataBase);
+ void setPromotion(QDesignerPromotionInterface *promotion);
+ void setWidgetFactory(QDesignerWidgetFactoryInterface *widgetFactory);
+ void setExtensionManager(QExtensionManager *extensionManager);
+ void setBrushManager(QDesignerBrushManagerInterface *brushManager);
+ void setIconCache(QDesignerIconCacheInterface *cache);
+
+private:
+ QPointer<QWidget> m_pad1;
+ QPointer<QDesignerWidgetBoxInterface> m_pad2;
+ QPointer<QDesignerPropertyEditorInterface> m_pad3;
+ QPointer<QDesignerFormWindowManagerInterface> m_pad4;
+ QPointer<QExtensionManager> m_pad5;
+ QPointer<QDesignerMetaDataBaseInterface> m_pad6;
+ QPointer<QDesignerWidgetDataBaseInterface> m_pad7;
+ QPointer<QDesignerWidgetFactoryInterface> m_pad8;
+ QPointer<QDesignerObjectInspectorInterface> m_pad9;
+ QPointer<QDesignerBrushManagerInterface> m_pad10;
+ QPointer<QDesignerIconCacheInterface> m_pad11;
+ QPointer<QDesignerActionEditorInterface> m_pad12;
+ QDesignerFormEditorInterfacePrivate *d;
+
+private:
+ QDesignerFormEditorInterface(const QDesignerFormEditorInterface &other);
+ void operator = (const QDesignerFormEditorInterface &other);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMEDITOR_H
diff --git a/tools/designer/src/lib/sdk/abstractformeditorplugin.cpp b/tools/designer/src/lib/sdk/abstractformeditorplugin.cpp
new file mode 100644
index 0000000000..f4ee89524c
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformeditorplugin.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/abstractformeditorplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QDesignerFormEditorPluginInterface
+ \brief The QDesignerFormEditorPluginInterface class provides an interface that is used to
+ manage plugins for Qt Designer's form editor component.
+ \inmodule QtDesigner
+
+ \sa QDesignerFormEditorInterface
+*/
+
+/*!
+ \fn virtual QDesignerFormEditorPluginInterface::~QDesignerFormEditorPluginInterface()
+
+ Destroys the plugin interface.
+*/
+
+/*!
+ \fn virtual bool QDesignerFormEditorPluginInterface::isInitialized() const = 0
+
+ Returns true if the plugin interface is initialized; otherwise returns false.
+*/
+
+/*!
+ \fn virtual void QDesignerFormEditorPluginInterface::initialize(QDesignerFormEditorInterface *core) = 0
+
+ Initializes the plugin interface for the specified \a core interface.
+*/
+
+/*!
+ \fn virtual QAction *QDesignerFormEditorPluginInterface::action() const = 0
+
+ Returns the action associated with this interface.
+*/
+
+/*!
+ \fn virtual QDesignerFormEditorInterface *QDesignerFormEditorPluginInterface::core() const = 0
+
+ Returns the core form editor interface associated with this component.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractformeditorplugin.h b/tools/designer/src/lib/sdk/abstractformeditorplugin.h
new file mode 100644
index 0000000000..628860252c
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformeditorplugin.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMEDITORPLUGIN_H
+#define ABSTRACTFORMEDITORPLUGIN_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QAction;
+
+class QDESIGNER_SDK_EXPORT QDesignerFormEditorPluginInterface
+{
+public:
+ virtual ~QDesignerFormEditorPluginInterface() {}
+
+ virtual bool isInitialized() const = 0;
+ virtual void initialize(QDesignerFormEditorInterface *core) = 0;
+ virtual QAction *action() const = 0;
+
+ virtual QDesignerFormEditorInterface *core() const = 0;
+};
+Q_DECLARE_INTERFACE(QDesignerFormEditorPluginInterface, "com.trolltech.Qt.Designer.QDesignerFormEditorPluginInterface")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMEDITORPLUGIN_H
diff --git a/tools/designer/src/lib/sdk/abstractformwindow.cpp b/tools/designer/src/lib/sdk/abstractformwindow.cpp
new file mode 100644
index 0000000000..3c05ff7179
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindow.cpp
@@ -0,0 +1,814 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindow.h"
+
+#include <widgetfactory_p.h>
+
+#include <QtGui/QTabBar>
+#include <QtGui/QSizeGrip>
+#include <QtGui/QAbstractButton>
+#include <QtGui/QToolBox>
+#include <QtGui/QMenuBar>
+#include <QtGui/QMainWindow>
+#include <QtGui/QDockWidget>
+#include <QtGui/QToolBar>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerFormWindowInterface
+
+ \brief The QDesignerFormWindowInterface class allows you to query
+ and manipulate form windows appearing in Qt Designer's workspace.
+
+ \inmodule QtDesigner
+
+ QDesignerFormWindowInterface provides information about
+ the associated form window as well as allowing its properties to be
+ altered. The interface is not intended to be instantiated
+ directly, but to provide access to \QD's current form windows
+ controlled by \QD's \l {QDesignerFormWindowManagerInterface}{form
+ window manager}.
+
+ If you are looking for the form window containing a specific
+ widget, you can use the static
+ QDesignerFormWindowInterface::findFormWindow() function:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.cpp 0
+
+ But in addition, you can access any of the current form windows
+ through \QD's form window manager: Use the
+ QDesignerFormEditorInterface::formWindowManager() function to
+ retrieve an interface to the manager. Once you have this
+ interface, you have access to all of \QD's current form windows
+ through the QDesignerFormWindowManagerInterface::formWindow()
+ function. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.cpp 1
+
+ The pointer to \QD's current QDesignerFormEditorInterface object
+ (\c formEditor in the example above) is provided by the
+ QDesignerCustomWidgetInterface::initialize() function's
+ parameter. When implementing a custom widget plugin, you must
+ subclass the QDesignerCustomWidgetInterface class to expose your
+ plugin to \QD.
+
+ Once you have the form window, you can query its properties. For
+ example, a plain custom widget plugin is managed by \QD only at
+ its top level, i.e. none of its child widgets can be resized in
+ \QD's workspace. But QDesignerFormWindowInterface provides you
+ with functions that enables you to control whether a widget should
+ be managed by \QD, or not:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindow.cpp 2
+
+ The complete list of functions concerning widget management is:
+ isManaged(), manageWidget() and unmanageWidget(). There is also
+ several associated signals: widgetManaged(), widgetRemoved(),
+ aboutToUnmanageWidget() and widgetUnmanaged().
+
+ In addition to controlling the management of widgets, you can
+ control the current selection in the form window using the
+ selectWidget(), clearSelection() and emitSelectionChanged()
+ functions, and the selectionChanged() signal.
+
+ You can also retrieve information about where the form is stored
+ using absoluteDir(), its include files using includeHints(), and
+ its layout and pixmap functions using layoutDefault(),
+ layoutFunction() and pixmapFunction(). You can find out whether
+ the form window has been modified (but not saved) or not, using
+ the isDirty() function. You can retrieve its author(), its
+ contents(), its fileName(), associated comment() and
+ exportMacro(), its mainContainer(), its features(), its grid() and
+ its resourceFiles().
+
+ The interface provides you with functions and slots allowing you
+ to alter most of this information as well. The exception is the
+ directory storing the form window. Finally, there is several
+ signals associated with changes to the information mentioned above
+ and to the form window in general.
+
+ \sa QDesignerFormWindowCursorInterface,
+ QDesignerFormEditorInterface, QDesignerFormWindowManagerInterface
+*/
+
+/*!
+ \enum QDesignerFormWindowInterface::FeatureFlag
+
+ This enum describes the features that are available and can be
+ controlled by the form window interface. These values are used
+ when querying the form window to determine which features it
+ supports:
+
+ \value EditFeature Form editing
+ \value GridFeature Grid display and snap-to-grid facilities for editing
+ \value TabOrderFeature Tab order management
+ \value DefaultFeature Support for default features (form editing and grid)
+
+ \sa hasFeature(), features()
+*/
+
+/*!
+ Constructs a form window interface with the given \a parent and
+ the specified window \a flags.
+*/
+QDesignerFormWindowInterface::QDesignerFormWindowInterface(QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags)
+{
+}
+
+/*!
+ Destroys the form window interface.
+*/
+QDesignerFormWindowInterface::~QDesignerFormWindowInterface()
+{
+}
+
+/*!
+ Returns a pointer to \QD's current QDesignerFormEditorInterface
+ object.
+*/
+QDesignerFormEditorInterface *QDesignerFormWindowInterface::core() const
+{
+ return 0;
+}
+
+/*!
+ \fn QDesignerFormWindowInterface *QDesignerFormWindowInterface::findFormWindow(QWidget *widget)
+
+ Returns the form window interface for the given \a widget.
+*/
+
+static inline bool stopFindAtTopLevel(const QObject *w, bool stopAtMenu)
+{
+ // Do we need to go beyond top levels when looking for the form window?
+ // 1) A dialog has a window attribute at the moment it is created
+ // before it is properly embedded into a form window. The property
+ // sheet queries the layout attributes precisely at this moment.
+ // 2) In the case of floating docks and toolbars, we also need to go beyond the top level window.
+ // 3) In the case of menu editing, we don't want to block events from the
+ // Designer menu, so, we say stop.
+ // Note that there must be no false positives for dialogs parented on
+ // the form (for example, the "change object name" dialog), else, its
+ // events will be blocked.
+
+ if (stopAtMenu && w->inherits("QDesignerMenu"))
+ return true;
+ return !qdesigner_internal::WidgetFactory::isFormEditorObject(w);
+}
+
+QDesignerFormWindowInterface *QDesignerFormWindowInterface::findFormWindow(QWidget *w)
+{
+ while (w != 0) {
+ if (QDesignerFormWindowInterface *fw = qobject_cast<QDesignerFormWindowInterface*>(w)) {
+ return fw;
+ } else {
+ if (w->isWindow() && stopFindAtTopLevel(w, true))
+ break;
+ }
+
+ w = w->parentWidget();
+ }
+
+ return 0;
+}
+
+/*!
+ \fn QDesignerFormWindowInterface *QDesignerFormWindowInterface::findFormWindow(QObject *object)
+
+ Returns the form window interface for the given \a object.
+
+ \since 4.4
+*/
+
+QDesignerFormWindowInterface *QDesignerFormWindowInterface::findFormWindow(QObject *object)
+{
+ while (object != 0) {
+ if (QDesignerFormWindowInterface *fw = qobject_cast<QDesignerFormWindowInterface*>(object)) {
+ return fw;
+ } else {
+ QWidget *w = qobject_cast<QWidget *>(object);
+ // QDesignerMenu is a window, so stopFindAtTopLevel(w) returns 0.
+ // However, we want to find the form window for QActions of a menu.
+ // If this check is inside stopFindAtTopLevel(w), it will break designer
+ // menu editing (e.g. when clicking on items inside an opened menu)
+ if (w && w->isWindow() && stopFindAtTopLevel(w, false))
+ break;
+
+ }
+
+ object = object->parent();
+ }
+
+ return 0;
+}
+
+/*!
+ \fn virtual QString QDesignerFormWindowInterface::fileName() const
+
+ Returns the file name of the .ui file that describes the form
+ currently being shown.
+
+ \sa setFileName()
+*/
+
+/*!
+ \fn virtual QDir QDesignerFormWindowInterface::absoluteDir() const
+
+ Returns the absolute location of the directory containing the form
+ shown in the form window.
+*/
+
+/*!
+ \fn virtual QString QDesignerFormWindowInterface::contents() const
+
+ Returns details of the contents of the form currently being
+ displayed in the window.
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setContents(QIODevice *device)
+
+ Sets the form's contents using data obtained from the given \a device.
+
+ Data can be read from QFile objects or any other subclass of QIODevice.
+*/
+
+/*!
+ \fn virtual Feature QDesignerFormWindowInterface::features() const
+
+ Returns a combination of the features provided by the form window
+ associated with the interface. The value returned can be tested
+ against the \l Feature enum values to determine which features are
+ supported by the window.
+
+ \sa setFeatures(), hasFeature()
+*/
+
+/*!
+ \fn virtual bool QDesignerFormWindowInterface::hasFeature(Feature feature) const
+
+ Returns true if the form window offers the specified \a feature;
+ otherwise returns false.
+
+ \sa features()
+*/
+
+/*!
+ \fn virtual QString QDesignerFormWindowInterface::author() const
+
+ Returns details of the author or creator of the form currently
+ being displayed in the window.
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setAuthor(const QString &author)
+
+ Sets the details for the author or creator of the form to the \a
+ author specified.
+*/
+
+/*!
+ \fn virtual QString QDesignerFormWindowInterface::comment() const
+
+ Returns comments about the form currently being displayed in the window.
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setComment(const QString &comment)
+
+ Sets the information about the form to the \a comment
+ specified. This information should be a human-readable comment
+ about the form.
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::layoutDefault(int *margin, int *spacing)
+
+ Fills in the default margin and spacing for the form's default
+ layout in the \a margin and \a spacing variables specified.
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setLayoutDefault(int margin, int spacing)
+
+ Sets the default \a margin and \a spacing for the form's layout.
+
+ \sa layoutDefault()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::layoutFunction(QString *margin, QString *spacing)
+
+ Fills in the current margin and spacing for the form's layout in
+ the \a margin and \a spacing variables specified.
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setLayoutFunction(const QString &margin, const QString &spacing)
+
+ Sets the \a margin and \a spacing for the form's layout.
+
+ The default layout properties will be replaced by the
+ corresponding layout functions when \c uic generates code for the
+ form, that is, if the functions are specified. This is useful when
+ different environments requires different layouts for the same
+ form.
+
+ \sa layoutFunction()
+*/
+
+/*!
+ \fn virtual QString QDesignerFormWindowInterface::pixmapFunction() const
+
+ Returns the name of the function used to load pixmaps into the
+ form window.
+
+ \sa setPixmapFunction()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setPixmapFunction(const QString &pixmapFunction)
+
+ Sets the function used to load pixmaps into the form window
+ to the given \a pixmapFunction.
+
+ \sa pixmapFunction()
+*/
+
+/*!
+ \fn virtual QString QDesignerFormWindowInterface::exportMacro() const
+
+ Returns the export macro associated with the form currently being
+ displayed in the window. The export macro is used when the form
+ is compiled to create a widget plugin.
+
+ \sa {Creating Custom Widgets for Qt Designer}
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setExportMacro(const QString &exportMacro)
+
+ Sets the form window's export macro to \a exportMacro. The export
+ macro is used when building a widget plugin to export the form's
+ interface to other components.
+*/
+
+/*!
+ \fn virtual QStringList QDesignerFormWindowInterface::includeHints() const
+
+ Returns a list of the header files that will be included in the
+ form window's associated \c .ui file.
+
+ Header files may be local, i.e. relative to the project's
+ directory,\c "mywidget.h", or global, i.e. part of Qt or the
+ compilers standard libraries:\c <QtGui/QWidget>.
+
+ \sa setIncludeHints()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setIncludeHints(const QStringList &includeHints)
+
+ Sets the header files that will be included in the form window's
+ associated \c .ui file to the specified \a includeHints.
+
+ Header files may be local, i.e. relative to the project's
+ directory,\c "mywidget.h", or global, i.e. part of Qt or the
+ compilers standard libraries:\c <QtGui/QWidget>.
+
+ \sa includeHints()
+*/
+
+/*!
+ \fn virtual QDesignerFormWindowCursorInterface *QDesignerFormWindowInterface::cursor() const
+
+ Returns the cursor interface used by the form window.
+*/
+
+/*!
+ \fn virtual int QDesignerFormWindowInterface::toolCount() const
+
+ Returns the number of tools available.
+
+ \internal
+*/
+
+/*!
+ \fn virtual int QDesignerFormWindowInterface::currentTool() const
+
+ Returns the index of the current tool in use.
+
+ \sa setCurrentTool()
+
+ \internal
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setCurrentTool(int index)
+
+ Sets the current tool to be the one with the given \a index.
+
+ \sa currentTool()
+
+ \internal
+*/
+
+/*!
+ \fn virtual QDesignerFormWindowToolInterface *QDesignerFormWindowInterface::tool(int index) const
+
+ Returns an interface to the tool with the given \a index.
+
+ \internal
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::registerTool(QDesignerFormWindowToolInterface *tool)
+
+ Registers the given \a tool with the form window.
+
+ \internal
+*/
+
+/*!
+ \fn virtual QPoint QDesignerFormWindowInterface::grid() const = 0
+
+ Returns the grid spacing used by the form window.
+
+ \sa setGrid()
+*/
+
+/*!
+ \fn virtual QWidget *QDesignerFormWindowInterface::mainContainer() const
+
+ Returns the main container widget for the form window.
+
+ \sa setMainContainer()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setMainContainer(QWidget *mainContainer)
+
+ Sets the main container widget on the form to the specified \a
+ mainContainer.
+
+ \sa mainContainer(), mainContainerChanged()
+*/
+
+/*!
+ \fn virtual bool QDesignerFormWindowInterface::isManaged(QWidget *widget) const
+
+ Returns true if the specified \a widget is managed by the form
+ window; otherwise returns false.
+
+ \sa manageWidget()
+*/
+
+/*!
+ \fn virtual bool QDesignerFormWindowInterface::isDirty() const
+
+ Returns true if the form window is "dirty" (modified but not
+ saved); otherwise returns false.
+
+ \sa setDirty()
+*/
+
+/*!
+ \fn virtual QUndoStack *QDesignerFormWindowInterface::commandHistory() const
+
+ Returns an object that can be used to obtain the commands used so
+ far in the construction of the form.
+
+ \internal
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::beginCommand(const QString &description)
+
+ Begins execution of a command with the given \a
+ description. Commands are executed between beginCommand() and
+ endCommand() function calls to ensure that they are recorded on
+ the undo stack.
+
+ \sa endCommand()
+
+ \internal
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::endCommand()
+
+ Ends execution of the current command.
+
+ \sa beginCommand()
+
+ \internal
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::simplifySelection(QList<QWidget*> *widgets) const
+
+ Simplifies the selection of widgets specified by \a widgets.
+
+ \sa selectionChanged()
+ \internal
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::emitSelectionChanged()
+
+ Emits the selectionChanged() signal.
+
+ \sa selectWidget(), clearSelection()
+*/
+
+/*!
+ \fn virtual QStringList QDesignerFormWindowInterface::resourceFiles() const
+
+ Returns a list of paths to resource files that are currently being
+ used by the form window.
+
+ \sa addResourceFile(), removeResourceFile()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::addResourceFile(const QString &path)
+
+ Adds the resource file at the given \a path to those used by the form.
+
+ \sa resourceFiles(), resourceFilesChanged()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::removeResourceFile(const QString &path)
+
+ Removes the resource file at the specified \a path from the list
+ of those used by the form.
+
+ \sa resourceFiles(), resourceFilesChanged()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::ensureUniqueObjectName(QObject *object)
+
+ Ensures that the specified \a object has a unique name amongst the
+ other objects on the form.
+
+ \internal
+*/
+
+// Slots
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::manageWidget(QWidget *widget)
+
+ Instructs the form window to manage the specified \a widget.
+
+ \sa isManaged(), unmanageWidget(), widgetManaged()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::unmanageWidget(QWidget *widget)
+
+ Instructs the form window not to manage the specified \a widget.
+
+ \sa aboutToUnmanageWidget(), widgetUnmanaged()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setFeatures(Feature features)
+
+ Enables the specified \a features for the form window.
+
+ \sa features(), featureChanged()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setDirty(bool dirty)
+
+ If \a dirty is true, the form window is marked as dirty, meaning
+ that it is modified but not saved. If \a dirty is false, the form
+ window is considered to be unmodified.
+
+ \sa isDirty()
+*/
+
+/*!
+\fn virtual void QDesignerFormWindowInterface::clearSelection(bool update)
+
+ Clears the current selection in the form window. If \a update is
+ true, the emitSelectionChanged() function is called, emitting the
+ selectionChanged() signal.
+
+ \sa selectWidget()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::selectWidget(QWidget *widget, bool select)
+
+ If \a select is true, the given \a widget is selected; otherwise
+ the \a widget is deselected.
+
+ \sa clearSelection(), selectionChanged()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setGrid(const QPoint &grid)
+
+ Sets the grid size for the form window to the point specified by
+ \a grid. In this function, the coordinates in the QPoint are used
+ to specify the dimensions of a rectangle in the grid.
+
+ \sa grid()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setFileName(const QString &fileName)
+
+ Sets the file name for the form to the given \a fileName.
+
+ \sa fileName(), fileNameChanged()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::setContents(const QString &contents)
+
+ Sets the contents of the form using data read from the specified
+ \a contents string.
+
+ \sa contents()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowInterface::editWidgets()
+
+ Switches the form window into editing mode.
+
+ \sa \l {Qt Designer's Form Editing Mode}
+
+ \internal
+*/
+
+// Signals
+
+/*!
+ \fn void QDesignerFormWindowInterface::mainContainerChanged(QWidget *mainContainer)
+
+ This signal is emitted whenever the main container changes.
+ The new container is specified by \a mainContainer.
+
+ \sa setMainContainer()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::toolChanged(int toolIndex)
+
+ This signal is emitted whenever the current tool changes.
+ The specified \a toolIndex is the index of the new tool in the list of
+ tools in the widget box.
+
+ \internal
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::fileNameChanged(const QString &fileName)
+
+ This signal is emitted whenever the file name of the form changes.
+ The new file name is specified by \a fileName.
+
+ \sa setFileName()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::featureChanged(Feature feature)
+
+ This signal is emitted whenever a feature changes in the form.
+ The new feature is specified by \a feature.
+
+ \sa setFeatures()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::selectionChanged()
+
+ This signal is emitted whenever the selection in the form changes.
+
+ \sa selectWidget(), clearSelection()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::geometryChanged()
+
+ This signal is emitted whenever the form's geometry changes.
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::resourceFilesChanged()
+
+ This signal is emitted whenever the list of resource files used by the
+ form changes.
+
+ \sa resourceFiles()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::widgetManaged(QWidget *widget)
+
+ This signal is emitted whenever a widget on the form becomes managed.
+ The newly managed widget is specified by \a widget.
+
+ \sa manageWidget()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::widgetUnmanaged(QWidget *widget)
+
+ This signal is emitted whenever a widget on the form becomes unmanaged.
+ The newly released widget is specified by \a widget.
+
+ \sa unmanageWidget(), aboutToUnmanageWidget()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::aboutToUnmanageWidget(QWidget *widget)
+
+ This signal is emitted whenever a widget on the form is about to
+ become unmanaged. When this signal is emitted, the specified \a
+ widget is still managed, and a widgetUnmanaged() signal will
+ follow, indicating when it is no longer managed.
+
+ \sa unmanageWidget(), isManaged()
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::activated(QWidget *widget)
+
+ This signal is emitted whenever a widget is activated on the form.
+ The activated widget is specified by \a widget.
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::changed()
+
+ This signal is emitted whenever a form is changed.
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::widgetRemoved(QWidget *widget)
+
+ This signal is emitted whenever a widget is removed from the form.
+ The widget that was removed is specified by \a widget.
+*/
+
+/*!
+ \fn void QDesignerFormWindowInterface::objectRemoved(QObject *object)
+
+ This signal is emitted whenever an object (such as
+ an action or a QButtonGroup) is removed from the form.
+ The object that was removed is specified by \a object.
+
+ \since 4.5
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractformwindow.h b/tools/designer/src/lib/sdk/abstractformwindow.h
new file mode 100644
index 0000000000..1fc37027cb
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindow.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMWINDOW_H
+#define ABSTRACTFORMWINDOW_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowCursorInterface;
+class QDesignerFormWindowToolInterface;
+class DomUI;
+class QUndoStack;
+class QDir;
+
+class QDESIGNER_SDK_EXPORT QDesignerFormWindowInterface: public QWidget
+{
+ Q_OBJECT
+public:
+ enum FeatureFlag
+ {
+ EditFeature = 0x01,
+ GridFeature = 0x02,
+ TabOrderFeature = 0x04,
+ DefaultFeature = EditFeature | GridFeature
+ };
+ Q_DECLARE_FLAGS(Feature, FeatureFlag)
+
+public:
+ QDesignerFormWindowInterface(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~QDesignerFormWindowInterface();
+
+ virtual QString fileName() const = 0;
+ virtual QDir absoluteDir() const = 0;
+
+ virtual QString contents() const = 0;
+ virtual void setContents(QIODevice *dev) = 0;
+
+ virtual Feature features() const = 0;
+ virtual bool hasFeature(Feature f) const = 0;
+
+ virtual QString author() const = 0;
+ virtual void setAuthor(const QString &author) = 0;
+
+ virtual QString comment() const = 0;
+ virtual void setComment(const QString &comment) = 0;
+
+ virtual void layoutDefault(int *margin, int *spacing) = 0;
+ virtual void setLayoutDefault(int margin, int spacing) = 0;
+
+ virtual void layoutFunction(QString *margin, QString *spacing) = 0;
+ virtual void setLayoutFunction(const QString &margin, const QString &spacing) = 0;
+
+ virtual QString pixmapFunction() const = 0;
+ virtual void setPixmapFunction(const QString &pixmapFunction) = 0;
+
+ virtual QString exportMacro() const = 0;
+ virtual void setExportMacro(const QString &exportMacro) = 0;
+
+ virtual QStringList includeHints() const = 0;
+ virtual void setIncludeHints(const QStringList &includeHints) = 0;
+
+ virtual QDesignerFormEditorInterface *core() const;
+ virtual QDesignerFormWindowCursorInterface *cursor() const = 0;
+
+ virtual int toolCount() const = 0;
+
+ virtual int currentTool() const = 0;
+ virtual void setCurrentTool(int index) = 0;
+
+ virtual QDesignerFormWindowToolInterface *tool(int index) const = 0;
+ virtual void registerTool(QDesignerFormWindowToolInterface *tool) = 0;
+
+ virtual QPoint grid() const = 0;
+
+ virtual QWidget *mainContainer() const = 0;
+ virtual void setMainContainer(QWidget *mainContainer) = 0;
+
+ virtual bool isManaged(QWidget *widget) const = 0;
+
+ virtual bool isDirty() const = 0;
+
+ static QDesignerFormWindowInterface *findFormWindow(QWidget *w);
+ static QDesignerFormWindowInterface *findFormWindow(QObject *obj);
+
+ virtual QUndoStack *commandHistory() const = 0;
+ virtual void beginCommand(const QString &description) = 0;
+ virtual void endCommand() = 0;
+
+ virtual void simplifySelection(QList<QWidget*> *widgets) const = 0;
+
+ // notifications
+ virtual void emitSelectionChanged() = 0;
+
+ virtual QStringList resourceFiles() const = 0;
+ virtual void addResourceFile(const QString &path) = 0;
+ virtual void removeResourceFile(const QString &path) = 0;
+
+ virtual void ensureUniqueObjectName(QObject *object) = 0;
+
+public Q_SLOTS:
+ virtual void manageWidget(QWidget *widget) = 0;
+ virtual void unmanageWidget(QWidget *widget) = 0;
+
+ virtual void setFeatures(Feature f) = 0;
+ virtual void setDirty(bool dirty) = 0;
+ virtual void clearSelection(bool changePropertyDisplay = true) = 0;
+ virtual void selectWidget(QWidget *w, bool select = true) = 0;
+ virtual void setGrid(const QPoint &grid) = 0;
+ virtual void setFileName(const QString &fileName) = 0;
+ virtual void setContents(const QString &contents) = 0;
+
+ virtual void editWidgets() = 0;
+
+Q_SIGNALS:
+ void mainContainerChanged(QWidget *mainContainer);
+ void toolChanged(int toolIndex);
+ void fileNameChanged(const QString &fileName);
+ void featureChanged(Feature f);
+ void selectionChanged();
+ void geometryChanged();
+
+ void resourceFilesChanged();
+
+ void widgetManaged(QWidget *widget);
+ void widgetUnmanaged(QWidget *widget);
+ void aboutToUnmanageWidget(QWidget *widget);
+ void activated(QWidget *widget);
+
+ void changed();
+ void widgetRemoved(QWidget *w);
+ void objectRemoved(QObject *o);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMWINDOW_H
diff --git a/tools/designer/src/lib/sdk/abstractformwindowcursor.cpp b/tools/designer/src/lib/sdk/abstractformwindowcursor.cpp
new file mode 100644
index 0000000000..2d2713385f
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindowcursor.cpp
@@ -0,0 +1,252 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindowcursor.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerFormWindowCursorInterface
+
+ \brief The QDesignerFormWindowCursorInterface class allows you to
+ query and modify a form window's widget selection, and in addition
+ modify the properties of all the form's widgets.
+
+ \inmodule QtDesigner
+
+ QDesignerFormWindowCursorInterface is a convenience class that
+ provides an interface to the associated form window's text cursor;
+ it provides a collection of functions that enables you to query a
+ given form window's selection and change the selection's focus
+ according to defined modes (MoveMode) and movements
+ (MoveOperation). You can also use the interface to query the
+ form's widgets and change their properties.
+
+ The interface is not intended to be instantiated directly, but to
+ provide access to the selections and widgets of \QD's current form
+ windows. QDesignerFormWindowInterface always provides an
+ associated cursor interface. The form window for a given widget
+ can be retrieved using the static
+ QDesignerFormWindowInterface::findFormWindow() functions. For
+ example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindowcursor.cpp 0
+
+ You can retrieve any of \QD's current form windows through
+ \QD's \l {QDesignerFormWindowManagerInterface}{form window
+ manager}.
+
+ Once you have a form window's cursor interface, you can check if
+ the form window has a selection at all using the hasSelection()
+ function. You can query the form window for its total
+ widgetCount() and selectedWidgetCount(). You can retrieve the
+ currently selected widget (or widgets) using the current() or
+ selectedWidget() functions.
+
+ You can retrieve any of the form window's widgets using the
+ widget() function, and check if a widget is selected using the
+ isWidgetSelected() function. You can use the setProperty()
+ function to set the selected widget's properties, and the
+ setWidgetProperty() or resetWidgetProperty() functions to modify
+ the properties of any given widget.
+
+ Finally, you can change the selection by changing the text
+ cursor's position() using the setPosition() and movePosition()
+ functions.
+
+ \sa QDesignerFormWindowInterface, QDesignerFormWindowManagerInterface
+*/
+
+/*!
+ \enum QDesignerFormWindowCursorInterface::MoveOperation
+
+ This enum describes the types of text cursor operation that can occur in a form window.
+
+ \value NoMove The cursor does not move.
+ \value Start Moves the cursor to the start of the focus chain.
+ \value End Moves the cursor to the end of the focus chain.
+ \value Next Moves the cursor to the next widget in the focus chain.
+ \value Prev Moves the cursor to the previous widget in the focus chain.
+ \value Left The cursor moves to the left.
+ \value Right The cursor moves to the right.
+ \value Up The cursor moves upwards.
+ \value Down The cursor moves downwards.
+*/
+
+/*!
+ \enum QDesignerFormWindowCursorInterface::MoveMode
+
+ This enum describes the different modes that are used when the text cursor moves.
+
+ \value MoveAnchor The anchor moves with the cursor to its new location.
+ \value KeepAnchor The anchor remains at the cursor's old location.
+*/
+
+/*!
+ Returns true if the specified \a widget is selected; otherwise
+ returns false.
+*/
+bool QDesignerFormWindowCursorInterface::isWidgetSelected(QWidget *widget) const
+{
+ for (int index=0; index<selectedWidgetCount(); ++index) {
+ if (selectedWidget(index) == widget)
+ return true;
+ }
+
+ return false;
+}
+
+/*!
+ \fn virtual QDesignerFormWindowCursorInterface::~QDesignerFormWindowCursorInterface()
+
+ Destroys the cursor interface.
+*/
+
+/*!
+ \fn virtual QDesignerFormWindowInterface *QDesignerFormWindowCursorInterface::formWindow() const
+
+ Returns the form window interface associated with this cursor interface.
+*/
+
+/*!
+ \fn virtual bool QDesignerFormWindowCursorInterface::movePosition(MoveOperation operation, MoveMode mode)
+
+ Performs the given \a operation on the cursor using the specified
+ \a mode, and returns true if it completed successfully; otherwise
+ returns false.
+
+ \sa position(), setPosition()
+*/
+
+/*!
+ \fn virtual int QDesignerFormWindowCursorInterface::position() const
+
+ Returns the cursor position.
+
+ \sa setPosition(), movePosition()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowCursorInterface::setPosition(int position, MoveMode mode = MoveAnchor)
+
+ Sets the position of the cursor to the given \a position using the
+ \a mode to specify how it is moved there.
+
+ \sa position(), movePosition()
+*/
+
+/*!
+ \fn virtual QWidget *QDesignerFormWindowCursorInterface::current() const
+
+ Returns the currently selected widget in the form window.
+
+ \sa selectedWidget()
+*/
+
+/*!
+ \fn virtual int QDesignerFormWindowCursorInterface::widgetCount() const
+
+ Returns the number of widgets in the form window.
+
+ \sa selectedWidgetCount()
+*/
+
+/*!
+ \fn virtual QWidget *QDesignerFormWindowCursorInterface::widget(int index) const
+
+ Returns the widget with the given \a index in the list of widgets
+ in the form window.
+
+ \sa selectedWidget()
+*/
+
+/*!
+ \fn virtual bool QDesignerFormWindowCursorInterface::hasSelection() const
+
+ Returns true if the form window contains a selection; otherwise
+ returns false.
+*/
+
+/*!
+ \fn virtual int QDesignerFormWindowCursorInterface::selectedWidgetCount() const
+
+ Returns the number of selected widgets in the form window.
+
+ \sa widgetCount()
+*/
+
+/*!
+ \fn virtual QWidget *QDesignerFormWindowCursorInterface::selectedWidget(int index) const
+
+ Returns the widget with the given \a index in the list of selected
+ widgets.
+
+ \sa current(), widget()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowCursorInterface::setProperty(const QString &name, const QVariant &value)
+
+ Sets the property with the given \a name for the currently
+ selected widget to the specified \a value.
+
+ \sa setWidgetProperty(), resetWidgetProperty()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowCursorInterface::setWidgetProperty(QWidget *widget, const QString &name, const QVariant &value)
+
+ Sets the property with the given \a name for the given \a widget
+ to the specified \a value.
+
+ \sa resetWidgetProperty(), setProperty()
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowCursorInterface::resetWidgetProperty(QWidget *widget, const QString &name)
+
+ Resets the property with the given \a name for the specified \a
+ widget to its default value.
+
+ \sa setProperty(), setWidgetProperty()
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractformwindowcursor.h b/tools/designer/src/lib/sdk/abstractformwindowcursor.h
new file mode 100644
index 0000000000..117bcac398
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindowcursor.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMWINDOWCURSOR_H
+#define ABSTRACTFORMWINDOWCURSOR_H
+
+#include <QtDesigner/sdk_global.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QWidget;
+class QVariant;
+class QString;
+
+class QDESIGNER_SDK_EXPORT QDesignerFormWindowCursorInterface
+{
+public:
+ enum MoveOperation
+ {
+ NoMove,
+
+ Start,
+ End,
+ Next,
+ Prev,
+ Left,
+ Right,
+ Up,
+ Down
+ };
+
+ enum MoveMode
+ {
+ MoveAnchor,
+ KeepAnchor
+ };
+
+public:
+ virtual ~QDesignerFormWindowCursorInterface() {}
+
+ virtual QDesignerFormWindowInterface *formWindow() const = 0;
+
+ virtual bool movePosition(MoveOperation op, MoveMode mode = MoveAnchor) = 0;
+
+ virtual int position() const = 0;
+ virtual void setPosition(int pos, MoveMode mode = MoveAnchor) = 0;
+
+ virtual QWidget *current() const = 0;
+
+ virtual int widgetCount() const = 0;
+ virtual QWidget *widget(int index) const = 0;
+
+ virtual bool hasSelection() const = 0;
+ virtual int selectedWidgetCount() const = 0;
+ virtual QWidget *selectedWidget(int index) const = 0;
+
+ virtual void setProperty(const QString &name, const QVariant &value) = 0;
+ virtual void setWidgetProperty(QWidget *widget, const QString &name, const QVariant &value) = 0;
+ virtual void resetWidgetProperty(QWidget *widget, const QString &name) = 0;
+
+ bool isWidgetSelected(QWidget *widget) const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMWINDOWCURSOR_H
diff --git a/tools/designer/src/lib/sdk/abstractformwindowmanager.cpp b/tools/designer/src/lib/sdk/abstractformwindowmanager.cpp
new file mode 100644
index 0000000000..526555276c
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindowmanager.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindowmanager.h"
+
+#include <QtCore/QMap>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerFormWindowManagerInterface
+
+ \brief The QDesignerFormWindowManagerInterface class allows you to
+ manipulate the collection of form windows in Qt Designer, and
+ control Qt Designer's form editing actions.
+
+ \inmodule QtDesigner
+
+ QDesignerFormWindowManagerInterface is not intended to be
+ instantiated directly. \QD uses the form window manager to
+ control the various form windows in its workspace. You can
+ retrieve an interface to \QD's form window manager using
+ the QDesignerFormEditorInterface::formWindowManager()
+ function. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractformwindowmanager.cpp 0
+
+ When implementing a custom widget plugin, a pointer to \QD's
+ current QDesignerFormEditorInterface object (\c formEditor in the
+ example above) is provided by the
+ QDesignerCustomWidgetInterface::initialize() function's parameter.
+ You must subclass the QDesignerCustomWidgetInterface to expose
+ your plugin to Qt Designer.
+
+ The form window manager interface provides the createFormWindow()
+ function that enables you to create a new form window which you
+ can add to the collection of form windows that the manager
+ maintains, using the addFormWindow() slot. It also provides the
+ formWindowCount() function returning the number of form windows
+ currently under the manager's control, the formWindow() function
+ returning the form window associated with a given index, and the
+ activeFormWindow() function returning the currently selected form
+ window. The removeFormWindow() slot allows you to reduce the
+ number of form windows the manager must maintain, and the
+ setActiveFormWindow() slot allows you to change the form window
+ focus in \QD's workspace.
+
+ In addition, QDesignerFormWindowManagerInterface contains a
+ collection of functions that enables you to intervene and control
+ \QD's form editing actions. All these functions return the
+ original action, making it possible to propagate the function
+ further after intervention.
+
+ Finally, the interface provides three signals which are emitted
+ when a form window is added, when the currently selected form
+ window changes, or when a form window is removed, respectively. All
+ the signals carry the form window in question as their parameter.
+
+ \sa QDesignerFormEditorInterface, QDesignerFormWindowInterface
+*/
+
+// ------------- QDesignerFormWindowManagerInterfacePrivate
+
+struct QDesignerFormWindowManagerInterfacePrivate {
+ QDesignerFormWindowManagerInterfacePrivate();
+ QAction *m_simplifyLayoutAction;
+ QAction *m_formLayoutAction;
+};
+
+QDesignerFormWindowManagerInterfacePrivate::QDesignerFormWindowManagerInterfacePrivate() :
+ m_simplifyLayoutAction(0),
+ m_formLayoutAction(0)
+{
+}
+
+typedef QMap<const QDesignerFormWindowManagerInterface *, QDesignerFormWindowManagerInterfacePrivate *> FormWindowManagerPrivateMap;
+
+Q_GLOBAL_STATIC(FormWindowManagerPrivateMap, g_FormWindowManagerPrivateMap)
+
+/*!
+ Constructs an interface with the given \a parent for the form window
+ manager.
+*/
+QDesignerFormWindowManagerInterface::QDesignerFormWindowManagerInterface(QObject *parent)
+ : QObject(parent)
+{
+ g_FormWindowManagerPrivateMap()->insert(this, new QDesignerFormWindowManagerInterfacePrivate);
+}
+
+/*!
+ Destroys the interface for the form window manager.
+*/
+QDesignerFormWindowManagerInterface::~QDesignerFormWindowManagerInterface()
+{
+ FormWindowManagerPrivateMap *fwmpm = g_FormWindowManagerPrivateMap();
+ const FormWindowManagerPrivateMap::iterator it = fwmpm->find(this);
+ Q_ASSERT(it != fwmpm->end());
+ delete it.value();
+ fwmpm->erase(it);
+}
+
+/*!
+ Allows you to intervene and control \QD's "cut" action. The function
+ returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionCut() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "copy" action. The
+ function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionCopy() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "paste" action. The
+ function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionPaste() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "delete" action. The function
+ returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionDelete() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "select all" action. The
+ function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionSelectAll() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control the action of lowering a form
+ window in \QD's workspace. The function returns the original
+ action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionLower() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control the action of raising of a
+ form window in \QD's workspace. The function returns the original
+ action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionRaise() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control a request for horizontal
+ layout for a form window in \QD's workspace. The function returns
+ the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionHorizontalLayout() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control a request for vertical layout
+ for a form window in \QD's workspace. The function returns the
+ original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionVerticalLayout() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "split horizontal"
+ action. The function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionSplitHorizontal() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "split vertical"
+ action. The function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionSplitVertical() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control a request for grid layout for
+ a form window in \QD's workspace. The function returns the
+ original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionGridLayout() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "form layout" action. The
+ function returns the original action.
+
+FormWindowManagerPrivateMap *fwmpm = g_FormWindowManagerPrivateMap(); \sa QAction
+ \since 4.4
+*/
+
+QAction *QDesignerFormWindowManagerInterface::actionFormLayout() const
+{
+ const QDesignerFormWindowManagerInterfacePrivate *d = g_FormWindowManagerPrivateMap()->value(this);
+ Q_ASSERT(d);
+ return d->m_formLayoutAction;
+}
+
+/*!
+ Sets the "form layout" action to \a action.
+
+ \internal
+ \since 4.4
+*/
+
+void QDesignerFormWindowManagerInterface::setActionFormLayout(QAction *action)
+{
+ QDesignerFormWindowManagerInterfacePrivate *d = g_FormWindowManagerPrivateMap()->value(this);
+ Q_ASSERT(d);
+ d->m_formLayoutAction = action;
+}
+
+/*!
+ Allows you to intervene and control \QD's "break layout" action. The
+ function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionBreakLayout() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "adjust size" action. The
+ function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionAdjustSize() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "simplify layout" action. The
+ function returns the original action.
+
+ \sa QAction
+ \since 4.4
+*/
+
+QAction *QDesignerFormWindowManagerInterface::actionSimplifyLayout() const
+{
+ const QDesignerFormWindowManagerInterfacePrivate *d = g_FormWindowManagerPrivateMap()->value(this);
+ Q_ASSERT(d);
+ return d->m_simplifyLayoutAction;
+}
+
+/*!
+ Sets the "simplify layout" action to \a action.
+
+ \internal
+ \since 4.4
+*/
+
+void QDesignerFormWindowManagerInterface::setActionSimplifyLayout(QAction *action)
+{
+ QDesignerFormWindowManagerInterfacePrivate *d = g_FormWindowManagerPrivateMap()->value(this);
+ Q_ASSERT(d);
+ d->m_simplifyLayoutAction = action;
+}
+
+/*!
+ Returns the currently active form window in \QD's workspace.
+
+ \sa setActiveFormWindow(), removeFormWindow()
+*/
+QDesignerFormWindowInterface *QDesignerFormWindowManagerInterface::activeFormWindow() const
+{
+ return 0;
+}
+
+/*!
+ Returns a pointer to \QD's current QDesignerFormEditorInterface
+ object.
+*/
+QDesignerFormEditorInterface *QDesignerFormWindowManagerInterface::core() const
+{
+ return 0;
+}
+
+/*!
+ Adds the given \a formWindow to the collection of windows that
+ \QD's form window manager maintains.
+
+ \sa formWindowAdded()
+*/
+void QDesignerFormWindowManagerInterface::addFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_UNUSED(formWindow);
+}
+
+/*!
+ Removes the given \a formWindow from the collection of windows that
+ \QD's form window manager maintains.
+
+ \sa formWindow(), formWindowRemoved()
+*/
+void QDesignerFormWindowManagerInterface::removeFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_UNUSED(formWindow);
+}
+
+/*!
+ Sets the given \a formWindow to be the currently active form window in
+ \QD's workspace.
+
+ \sa activeFormWindow(), activeFormWindowChanged()
+*/
+void QDesignerFormWindowManagerInterface::setActiveFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_UNUSED(formWindow);
+}
+
+/*!
+ Returns the number of form windows maintained by \QD's form window
+ manager.
+*/
+int QDesignerFormWindowManagerInterface::formWindowCount() const
+{
+ return 0;
+}
+
+/*!
+ Returns the form window at the given \a index.
+
+ \sa setActiveFormWindow(), removeFormWindow()
+*/
+QDesignerFormWindowInterface *QDesignerFormWindowManagerInterface::formWindow(int index) const
+{
+ Q_UNUSED(index);
+ return 0;
+}
+
+/*!
+ \fn QDesignerFormWindowInterface *QDesignerFormWindowManagerInterface::createFormWindow(QWidget *parent, Qt::WindowFlags flags)
+
+ Creates a form window with the given \a parent and the given window
+ \a flags.
+
+ \sa addFormWindow()
+*/
+QDesignerFormWindowInterface *QDesignerFormWindowManagerInterface::createFormWindow(QWidget *parentWidget, Qt::WindowFlags flags)
+{
+ Q_UNUSED(parentWidget);
+ Q_UNUSED(flags);
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "undo" action. The
+ function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionUndo() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's "redo" action. The
+ function returns the original action.
+
+ \sa QAction
+*/
+QAction *QDesignerFormWindowManagerInterface::actionRedo() const
+{
+ return 0;
+}
+
+/*!
+ \fn void QDesignerFormWindowManagerInterface::formWindowAdded(QDesignerFormWindowInterface *formWindow)
+
+ This signal is emitted when a new form window is added to the
+ collection of windows that \QD's form window manager maintains. A
+ pointer to the new \a formWindow is passed as an argument.
+
+ \sa addFormWindow(), setActiveFormWindow()
+*/
+
+/*!
+ \fn void QDesignerFormWindowManagerInterface::formWindowRemoved(QDesignerFormWindowInterface *formWindow)
+
+ This signal is emitted when a form window is removed from the
+ collection of windows that \QD's form window manager maintains. A
+ pointer to the removed \a formWindow is passed as an argument.
+
+ \sa removeFormWindow()
+*/
+
+/*!
+ \fn void QDesignerFormWindowManagerInterface::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+
+ This signal is emitted when the contents of the currently active
+ form window in \QD's workspace changed. A pointer to the currently
+ active \a formWindow is passed as an argument.
+
+ \sa activeFormWindow()
+*/
+
+/*!
+ \fn void QDesignerFormWindowManagerInterface::dragItems(const QList<QDesignerDnDItemInterface*> &item_list)
+
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractformwindowmanager.h b/tools/designer/src/lib/sdk/abstractformwindowmanager.h
new file mode 100644
index 0000000000..e3ac3dc08f
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindowmanager.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMWINDOWMANAGER_H
+#define ABSTRACTFORMWINDOWMANAGER_H
+
+#include <QtDesigner/sdk_global.h>
+#include <QtDesigner/abstractformwindow.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QActionGroup;
+class QDesignerFormEditorInterface;
+class DomUI;
+class QWidget;
+class QDesignerDnDItemInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerFormWindowManagerInterface: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerFormWindowManagerInterface(QObject *parent = 0);
+ virtual ~QDesignerFormWindowManagerInterface();
+
+ virtual QAction *actionCut() const;
+ virtual QAction *actionCopy() const;
+ virtual QAction *actionPaste() const;
+ virtual QAction *actionDelete() const;
+ virtual QAction *actionSelectAll() const;
+ virtual QAction *actionLower() const;
+ virtual QAction *actionRaise() const;
+ virtual QAction *actionUndo() const;
+ virtual QAction *actionRedo() const;
+
+ virtual QAction *actionHorizontalLayout() const;
+ virtual QAction *actionVerticalLayout() const;
+ virtual QAction *actionSplitHorizontal() const;
+ virtual QAction *actionSplitVertical() const;
+ virtual QAction *actionGridLayout() const;
+ QAction *actionFormLayout() const;
+ virtual QAction *actionBreakLayout() const;
+ virtual QAction *actionAdjustSize() const;
+ QAction *actionSimplifyLayout() const;
+
+ virtual QDesignerFormWindowInterface *activeFormWindow() const;
+
+ virtual int formWindowCount() const;
+ virtual QDesignerFormWindowInterface *formWindow(int index) const;
+
+ virtual QDesignerFormWindowInterface *createFormWindow(QWidget *parentWidget = 0, Qt::WindowFlags flags = 0);
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual void dragItems(const QList<QDesignerDnDItemInterface*> &item_list) = 0;
+
+Q_SIGNALS:
+ void formWindowAdded(QDesignerFormWindowInterface *formWindow);
+ void formWindowRemoved(QDesignerFormWindowInterface *formWindow);
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+
+public Q_SLOTS:
+ virtual void addFormWindow(QDesignerFormWindowInterface *formWindow);
+ virtual void removeFormWindow(QDesignerFormWindowInterface *formWindow);
+ virtual void setActiveFormWindow(QDesignerFormWindowInterface *formWindow);
+
+protected:
+ void setActionFormLayout(QAction *action);
+ void setActionSimplifyLayout(QAction *action);
+
+private:
+ QDesignerFormWindowManagerInterface(const QDesignerFormWindowManagerInterface &other);
+ QDesignerFormWindowManagerInterface &operator = (const QDesignerFormWindowManagerInterface &other);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMWINDOWMANAGER_H
diff --git a/tools/designer/src/lib/sdk/abstractformwindowtool.cpp b/tools/designer/src/lib/sdk/abstractformwindowtool.cpp
new file mode 100644
index 0000000000..9ef2e86f27
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindowtool.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractformwindowtool.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerFormWindowToolInterface
+
+ \brief The QDesignerFormWindowToolInterface class provides an
+ interface that enables tools to be used on items in a form window.
+
+ \inmodule QtDesigner
+
+ \internal
+*/
+
+/*!
+*/
+QDesignerFormWindowToolInterface::QDesignerFormWindowToolInterface(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+*/
+QDesignerFormWindowToolInterface::~QDesignerFormWindowToolInterface()
+{
+}
+
+/*!
+ \fn virtual QDesignerFormEditorInterface *QDesignerFormWindowToolInterface::core() const = 0
+*/
+
+/*!
+ \fn virtual QDesignerFormWindowInterface *QDesignerFormWindowToolInterface::formWindow() const = 0
+*/
+
+/*!
+ \fn virtual QWidget *QDesignerFormWindowToolInterface::editor() const = 0
+*/
+
+/*!
+ \fn virtual QAction *QDesignerFormWindowToolInterface::action() const = 0
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowToolInterface::activated() = 0
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowToolInterface::deactivated() = 0
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowToolInterface::saveToDom(DomUI*, QWidget*) {
+*/
+
+/*!
+ \fn virtual void QDesignerFormWindowToolInterface::loadFromDom(DomUI*, QWidget*) {
+*/
+
+/*!
+ \fn virtual bool QDesignerFormWindowToolInterface::handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event) = 0
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractformwindowtool.h b/tools/designer/src/lib/sdk/abstractformwindowtool.h
new file mode 100644
index 0000000000..a79731145b
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractformwindowtool.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMWINDOWTOOL_H
+#define ABSTRACTFORMWINDOWTOOL_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QWidget;
+class QAction;
+class DomUI;
+
+class QDESIGNER_SDK_EXPORT QDesignerFormWindowToolInterface: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerFormWindowToolInterface(QObject *parent = 0);
+ virtual ~QDesignerFormWindowToolInterface();
+
+ virtual QDesignerFormEditorInterface *core() const = 0;
+ virtual QDesignerFormWindowInterface *formWindow() const = 0;
+ virtual QWidget *editor() const = 0;
+
+ virtual QAction *action() const = 0;
+
+ virtual void activated() = 0;
+ virtual void deactivated() = 0;
+
+ virtual void saveToDom(DomUI*, QWidget*) {}
+ virtual void loadFromDom(DomUI*, QWidget*) {}
+
+ virtual bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMWINDOWTOOL_H
diff --git a/tools/designer/src/lib/sdk/abstracticoncache.h b/tools/designer/src/lib/sdk/abstracticoncache.h
new file mode 100644
index 0000000000..b0c827f0b1
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstracticoncache.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTICONCACHE_H
+#define ABSTRACTICONCACHE_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QIcon;
+class QPixmap;
+class QString;
+
+class QDESIGNER_SDK_EXPORT QDesignerIconCacheInterface : public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerIconCacheInterface(QObject *parent_)
+ : QObject(parent_) {}
+
+ virtual QIcon nameToIcon(const QString &filePath, const QString &qrcPath = QString()) = 0;
+ virtual QPixmap nameToPixmap(const QString &filePath, const QString &qrcPath = QString()) = 0;
+
+ virtual QString iconToFilePath(const QIcon &pm) const = 0;
+ virtual QString iconToQrcPath(const QIcon &pm) const = 0;
+
+ virtual QString pixmapToFilePath(const QPixmap &pm) const = 0;
+ virtual QString pixmapToQrcPath(const QPixmap &pm) const = 0;
+
+ virtual QList<QPixmap> pixmapList() const = 0;
+ virtual QList<QIcon> iconList() const = 0;
+
+ virtual QString resolveQrcPath(const QString &filePath, const QString &qrcPath, const QString &workingDirectory = QString()) const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTICONCACHE_H
diff --git a/tools/designer/src/lib/sdk/abstractintegration.cpp b/tools/designer/src/lib/sdk/abstractintegration.cpp
new file mode 100644
index 0000000000..3ef1810e91
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractintegration.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractintegration.h"
+#include "abstractformeditor.h"
+
+QT_BEGIN_NAMESPACE
+
+QDesignerIntegrationInterface::QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent),
+ m_core(core)
+{
+ core->setIntegration(this);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractintegration.h b/tools/designer/src/lib/sdk/abstractintegration.h
new file mode 100644
index 0000000000..8af5bfbe92
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractintegration.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTINTEGRATION_H
+#define ABSTRACTINTEGRATION_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerIntegrationInterface: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerIntegrationInterface(QDesignerFormEditorInterface *core, QObject *parent = 0);
+
+ inline QDesignerFormEditorInterface *core() const;
+
+ virtual QWidget *containerWindow(QWidget *widget) const = 0;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+inline QDesignerFormEditorInterface *QDesignerIntegrationInterface::core() const
+{ return m_core; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTINTEGRATION_H
diff --git a/tools/designer/src/lib/sdk/abstractintrospection.cpp b/tools/designer/src/lib/sdk/abstractintrospection.cpp
new file mode 100644
index 0000000000..70ff723e12
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractintrospection.cpp
@@ -0,0 +1,548 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractintrospection_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerMetaEnumInterface
+ \internal
+ \since 4.4
+
+ \brief QDesignerMetaEnumInterface is part of \QD's introspection interface and represents an enumeration.
+
+ \inmodule QtDesigner
+
+ The QDesignerMetaEnumInterface class provides meta-data about an enumerator.
+
+ \sa QDesignerMetaObjectInterface
+*/
+
+/*!
+ Constructs a QDesignerMetaEnumInterface object.
+*/
+
+QDesignerMetaEnumInterface::QDesignerMetaEnumInterface()
+{
+}
+
+/*!
+ Destroys the QDesignerMetaEnumInterface object.
+*/
+QDesignerMetaEnumInterface::~QDesignerMetaEnumInterface()
+{
+}
+
+/*!
+ \fn bool QDesignerMetaEnumInterface::isFlag() const
+
+ Returns true if this enumerator is used as a flag.
+*/
+
+/*!
+ \fn QString QDesignerMetaEnumInterface::key(int index) const
+
+ Returns the key with the given \a index.
+*/
+
+/*!
+ \fn int QDesignerMetaEnumInterface::keyCount() const
+
+ Returns the number of keys.
+*/
+
+/*!
+ \fn int QDesignerMetaEnumInterface::keyToValue(const QString &key) const
+
+ Returns the integer value of the given enumeration \a key, or -1 if \a key is not defined.
+*/
+
+/*!
+ \fn int QDesignerMetaEnumInterface::keysToValue(const QString &keys) const
+
+ Returns the value derived from combining together the values of the \a keys using the OR operator, or -1 if keys is not defined. Note that the strings in \a keys must be '|'-separated.
+*/
+
+/*!
+ \fn QString QDesignerMetaEnumInterface::name() const
+
+ Returns the name of the enumerator (without the scope).
+*/
+
+/*!
+ \fn QString QDesignerMetaEnumInterface::scope() const
+
+ Returns the scope this enumerator was declared in.
+*/
+
+/*!
+ \fn QString QDesignerMetaEnumInterface::separator() const
+
+ Returns the separator to be used when building enumeration names.
+*/
+
+/*!
+ \fn int QDesignerMetaEnumInterface::value(int index) const
+
+ Returns the value with the given \a index; or returns -1 if there is no such value.
+*/
+
+/*!
+ \fn QString QDesignerMetaEnumInterface::valueToKey(int value) const
+
+ Returns the string that is used as the name of the given enumeration \a value, or QString::null if value is not defined.
+*/
+
+/*!
+ \fn QString QDesignerMetaEnumInterface::valueToKeys(int value) const
+
+ Returns a byte array of '|'-separated keys that represents the given \a value.
+*/
+
+/*!
+ \class QDesignerMetaPropertyInterface
+ \internal
+ \since 4.4
+
+ \brief QDesignerMetaPropertyInterface is part of \QD's introspection interface and represents a property.
+
+ \inmodule QtDesigner
+
+ The QDesignerMetaPropertyInterface class provides meta-data about a property.
+
+ \sa QDesignerMetaObjectInterface
+*/
+
+/*!
+ Constructs a QDesignerMetaPropertyInterface object.
+*/
+
+QDesignerMetaPropertyInterface::QDesignerMetaPropertyInterface()
+{
+}
+
+/*!
+ Destroys the QDesignerMetaPropertyInterface object.
+*/
+
+QDesignerMetaPropertyInterface::~QDesignerMetaPropertyInterface()
+{
+}
+
+/*!
+ \enum QDesignerMetaPropertyInterface::Kind
+
+ This enum indicates whether the property is of a special type.
+
+ \value EnumKind The property is of an enumeration type
+ \value FlagKind The property is of an flag type
+ \value OtherKind The property is of another type
+ */
+
+/*!
+ \enum QDesignerMetaPropertyInterface::AccessFlag
+
+ These flags specify the access the property provides.
+
+ \value ReadAccess Property can be read
+ \value WriteAccess Property can be written
+ \value ResetAccess Property can be reset to a default value
+ */
+
+/*!
+ \enum QDesignerMetaPropertyInterface::Attribute
+
+ Various attributes of the property.
+
+ \value DesignableAttribute Property is designable (visible in \QD)
+ \value ScriptableAttribute Property is scriptable
+ \value StoredAttribute Property is stored, that is, not calculated
+ \value UserAttribute Property is the property that the user can edit for the QObject
+ */
+
+/*!
+ \fn const QDesignerMetaEnumInterface *QDesignerMetaPropertyInterface::enumerator() const
+
+ Returns the enumerator if this property's type is an enumerator type;
+*/
+
+/*!
+ \fn Kind QDesignerMetaPropertyInterface::kind() const
+
+ Returns the type of the property.
+*/
+
+/*!
+ \fn AccessFlags QDesignerMetaPropertyInterface::accessFlags() const
+
+ Returns a combination of access flags.
+*/
+
+/*!
+ \fn Attributes QDesignerMetaPropertyInterface::attributes(const QObject *object) const
+
+ Returns the attributes of the property for the gives \a object.
+*/
+
+/*!
+ \fn QVariant::Type QDesignerMetaPropertyInterface::type() const
+
+ Returns the type of the property.
+*/
+
+/*!
+ \fn QString QDesignerMetaPropertyInterface::name() const
+
+ Returns the name of the property.
+*/
+
+/*!
+ \fn QString QDesignerMetaPropertyInterface::typeName() const
+
+ Returns the name of this property's type.
+*/
+
+
+/*!
+ \fn int QDesignerMetaPropertyInterface::userType() const
+
+ Returns this property's user type.
+*/
+
+/*!
+ \fn bool QDesignerMetaPropertyInterface::hasSetter() const
+
+ Returns whether getter and setter methods exist for this property.
+*/
+
+/*!
+ \fn QVariant QDesignerMetaPropertyInterface::read(const QObject *object) const
+
+ Reads the property's value from the given \a object. Returns the value if it was able to read it; otherwise returns an invalid variant.
+*/
+
+/*!
+ \fn bool QDesignerMetaPropertyInterface::reset(QObject *object) const
+
+ Resets the property for the given \a object with a reset method. Returns true if the reset worked; otherwise returns false.
+*/
+
+/*!
+ \fn bool QDesignerMetaPropertyInterface::write(QObject *object, const QVariant &value) const
+
+ Writes \a value as the property's value to the given \a object. Returns true if the write succeeded; otherwise returns false.
+*/
+
+/*!
+ \class QDesignerMetaMethodInterface
+ \internal
+ \since 4.4
+
+ \brief QDesignerMetaMethodInterface is part of \QD's introspection interface and represents a member function.
+
+ \inmodule QtDesigner
+
+ The QDesignerMetaMethodInterface class provides meta-data about a member function.
+
+ \sa QDesignerMetaObjectInterface
+*/
+
+/*!
+ Constructs a QDesignerMetaMethodInterface object.
+*/
+
+QDesignerMetaMethodInterface::QDesignerMetaMethodInterface()
+{
+}
+
+/*!
+ Destroys the QDesignerMetaMethodInterface object.
+*/
+
+QDesignerMetaMethodInterface::~QDesignerMetaMethodInterface()
+{
+}
+
+/*!
+ \enum QDesignerMetaMethodInterface::MethodType
+
+ This enum specifies the type of the method
+
+ \value Method The function is a plain member function.
+ \value Signal The function is a signal.
+ \value Slot The function is a slot.
+ \value Constructor The function is a constructor.
+
+*/
+
+/*!
+ \enum QDesignerMetaMethodInterface::Access
+
+ This enum represents the access specification of the method
+
+ \value Private A private member function
+ \value Protected A protected member function
+ \value Public A public member function
+*/
+
+/*!
+ \fn QDesignerMetaMethodInterface::Access QDesignerMetaMethodInterface::access() const
+
+ Returns the access specification of this method.
+*/
+
+
+/*!
+ \fn QDesignerMetaMethodInterface::MethodType QDesignerMetaMethodInterface::methodType() const
+
+ Returns the type of this method.
+*/
+
+/*!
+ \fn QStringList QDesignerMetaMethodInterface::parameterNames() const
+
+ Returns a list of parameter names.
+*/
+
+/*!
+ \fn QStringList QDesignerMetaMethodInterface::parameterTypes() const
+
+ Returns a list of parameter types.
+*/
+
+/*!
+ \fn QString QDesignerMetaMethodInterface::signature() const
+
+ Returns the signature of this method.
+*/
+
+/*!
+ \fn QString QDesignerMetaMethodInterface::normalizedSignature() const
+
+ Returns the normalized signature of this method (suitable as signal/slot specification).
+*/
+
+
+/*!
+ \fn QString QDesignerMetaMethodInterface::tag() const
+
+ Returns the tag associated with this method.
+*/
+
+/*!
+ \fn QString QDesignerMetaMethodInterface::typeName() const
+
+ Returns the return type of this method, or an empty string if the return type is void.
+*/
+
+/*!
+ \class QDesignerMetaObjectInterface
+ \internal
+ \since 4.4
+
+ \brief QDesignerMetaObjectInterface is part of \QD's introspection interface and provides meta-information about Qt objects
+
+ \inmodule QtDesigner
+
+ The QDesignerMetaObjectInterface class provides meta-data about Qt objects. For a given object, it can be obtained
+ by querying QDesignerIntrospectionInterface.
+
+ \sa QDesignerIntrospectionInterface
+*/
+
+/*!
+ Constructs a QDesignerMetaObjectInterface object.
+*/
+
+QDesignerMetaObjectInterface::QDesignerMetaObjectInterface()
+{
+}
+
+/*!
+ Destroys the QDesignerMetaObjectInterface object.
+*/
+
+QDesignerMetaObjectInterface::~QDesignerMetaObjectInterface()
+{
+}
+
+/*!
+ \fn QString QDesignerMetaObjectInterface::className() const
+
+ Returns the class name.
+*/
+
+/*!
+ \fn const QDesignerMetaEnumInterface *QDesignerMetaObjectInterface::enumerator(int index) const
+
+ Returns the meta-data for the enumerator with the given \a index.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::enumeratorCount() const
+
+ Returns the number of enumerators in this class.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::enumeratorOffset() const
+
+ Returns the enumerator offset for this class; i.e. the index position of this class's first enumerator.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::indexOfEnumerator(const QString &name) const
+
+ Finds enumerator \a name and returns its index; otherwise returns -1.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::indexOfMethod(const QString &method) const
+
+ Finds \a method and returns its index; otherwise returns -1.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::indexOfProperty(const QString &name) const
+
+ Finds property \a name and returns its index; otherwise returns -1.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::indexOfSignal(const QString &signal) const
+
+ Finds \a signal and returns its index; otherwise returns -1.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::indexOfSlot(const QString &slot) const
+
+ Finds \a slot and returns its index; otherwise returns -1.
+*/
+
+/*!
+ \fn const QDesignerMetaMethodInterface *QDesignerMetaObjectInterface::method(int index) const
+
+ Returns the meta-data for the method with the given \a index.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::methodCount() const
+
+ Returns the number of methods in this class. These include ordinary methods, signals, and slots.
+*/
+
+/*!
+ \fn int QDesignerMetaObjectInterface::methodOffset() const
+
+ Returns the method offset for this class; i.e. the index position of this class's first member function.
+*/
+
+/*!
+ \fn const QDesignerMetaPropertyInterface *QDesignerMetaObjectInterface::property(int index) const
+
+ Returns the meta-data for the property with the given \a index.
+*/
+/*!
+ \fn int QDesignerMetaObjectInterface::propertyCount() const
+
+ Returns the number of properties in this class.
+*/
+/*!
+ \fn int QDesignerMetaObjectInterface::propertyOffset() const
+
+ Returns the property offset for this class; i.e. the index position of this class's first property.
+*/
+
+/*!
+ \fn const QDesignerMetaObjectInterface *QDesignerMetaObjectInterface::superClass() const
+
+ Returns the meta-object of the superclass, or 0 if there is no such object.
+*/
+
+/*!
+ \fn const QDesignerMetaPropertyInterface *QDesignerMetaObjectInterface::userProperty() const
+
+ Returns the property that has the USER flag set to true.
+*/
+
+/*!
+ \class QDesignerIntrospectionInterface
+ \internal
+ \since 4.4
+
+ \brief QDesignerIntrospectionInterface provides access to a QDesignerMetaObjectInterface for a given Qt object.
+
+ \inmodule QtDesigner
+
+ QDesignerIntrospectionInterface is the main class of \QD's introspection interface. These
+ interfaces provide a layer of abstraction around QMetaObject and related classes to allow for the integration
+ of other programming languages.
+
+ An instance of QDesignerIntrospectionInterface can be obtained from the core.
+
+ \sa QDesignerMetaObjectInterface
+*/
+
+/*!
+ Constructs a QDesignerIntrospectionInterface object.
+*/
+
+QDesignerIntrospectionInterface::QDesignerIntrospectionInterface()
+{
+}
+
+/*!
+ Destroys the QDesignerIntrospectionInterface object.
+*/
+
+QDesignerIntrospectionInterface::~QDesignerIntrospectionInterface()
+{
+}
+
+/*!
+ \fn const QDesignerMetaObjectInterface* QDesignerIntrospectionInterface::metaObject(const QObject *object) const
+
+ Returns the meta object of this \a object.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractintrospection_p.h b/tools/designer/src/lib/sdk/abstractintrospection_p.h
new file mode 100644
index 0000000000..52f680734b
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractintrospection_p.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ABSTRACTMETAOBJECT_H
+#define ABSTRACTMETAOBJECT_H
+
+#include <QtDesigner/sdk_global.h>
+#include <QtCore/QVariant>
+#include <QtCore/QFlags>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDESIGNER_SDK_EXPORT QDesignerMetaEnumInterface
+{
+public:
+ QDesignerMetaEnumInterface();
+ virtual ~QDesignerMetaEnumInterface();
+ virtual bool isFlag() const = 0;
+ virtual QString key(int index) const = 0;
+ virtual int keyCount() const = 0;
+ virtual int keyToValue(const QString &key) const = 0;
+ virtual int keysToValue(const QString &keys) const = 0;
+ virtual QString name() const = 0;
+ virtual QString scope() const = 0;
+ virtual QString separator() const = 0;
+ virtual int value(int index) const = 0;
+ virtual QString valueToKey(int value) const = 0;
+ virtual QString valueToKeys(int value) const = 0;
+};
+
+class QDESIGNER_SDK_EXPORT QDesignerMetaPropertyInterface
+{
+public:
+ enum Kind { EnumKind, FlagKind, OtherKind };
+ enum AccessFlag { ReadAccess = 0x0001, WriteAccess = 0x0002, ResetAccess = 0x0004 };
+ enum Attribute { DesignableAttribute = 0x0001, ScriptableAttribute = 0x0002, StoredAttribute = 0x0004, UserAttribute = 0x0008};
+ Q_DECLARE_FLAGS(Attributes, Attribute)
+ Q_DECLARE_FLAGS(AccessFlags, AccessFlag)
+
+ QDesignerMetaPropertyInterface();
+ virtual ~QDesignerMetaPropertyInterface();
+
+ virtual const QDesignerMetaEnumInterface *enumerator() const = 0;
+
+ virtual Kind kind() const = 0;
+ virtual AccessFlags accessFlags() const = 0;
+ virtual Attributes attributes(const QObject *object = 0) const = 0;
+
+ virtual QVariant::Type type() const = 0;
+ virtual QString name() const = 0;
+ virtual QString typeName() const = 0;
+ virtual int userType() const = 0;
+ virtual bool hasSetter() const = 0;
+
+ virtual QVariant read(const QObject *object) const = 0;
+ virtual bool reset(QObject *object) const = 0;
+ virtual bool write(QObject *object, const QVariant &value) const = 0;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDesignerMetaPropertyInterface::AccessFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDesignerMetaPropertyInterface::Attributes)
+
+class QDESIGNER_SDK_EXPORT QDesignerMetaMethodInterface
+{
+public:
+ QDesignerMetaMethodInterface();
+ virtual ~QDesignerMetaMethodInterface();
+
+ enum MethodType { Method, Signal, Slot, Constructor };
+ enum Access { Private, Protected, Public };
+
+ virtual Access access() const = 0;
+ virtual MethodType methodType() const = 0;
+ virtual QStringList parameterNames() const = 0;
+ virtual QStringList parameterTypes() const = 0;
+ virtual QString signature() const = 0;
+ virtual QString normalizedSignature() const = 0;
+ virtual QString tag() const = 0;
+ virtual QString typeName() const = 0;
+};
+
+class QDESIGNER_SDK_EXPORT QDesignerMetaObjectInterface {
+public:
+ QDesignerMetaObjectInterface();
+ virtual ~QDesignerMetaObjectInterface();
+
+ virtual QString className() const = 0;
+ virtual const QDesignerMetaEnumInterface *enumerator(int index) const = 0;
+ virtual int enumeratorCount() const = 0;
+ virtual int enumeratorOffset() const = 0;
+
+ virtual int indexOfEnumerator(const QString &name) const = 0;
+ virtual int indexOfMethod(const QString &method) const = 0;
+ virtual int indexOfProperty(const QString &name) const = 0;
+ virtual int indexOfSignal(const QString &signal) const = 0;
+ virtual int indexOfSlot(const QString &slot) const = 0;
+
+ virtual const QDesignerMetaMethodInterface *method(int index) const = 0;
+ virtual int methodCount() const = 0;
+ virtual int methodOffset() const = 0;
+
+ virtual const QDesignerMetaPropertyInterface *property(int index) const = 0;
+ virtual int propertyCount() const = 0;
+ virtual int propertyOffset() const = 0;
+
+ virtual const QDesignerMetaObjectInterface *superClass() const = 0;
+ virtual const QDesignerMetaPropertyInterface *userProperty() const = 0;
+};
+
+// To be obtained from core
+class QDESIGNER_SDK_EXPORT QDesignerIntrospectionInterface {
+public:
+ QDesignerIntrospectionInterface();
+ virtual ~QDesignerIntrospectionInterface();
+
+ virtual const QDesignerMetaObjectInterface* metaObject(const QObject *object) const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTMETAOBJECT_H
diff --git a/tools/designer/src/lib/sdk/abstractlanguage.h b/tools/designer/src/lib/sdk/abstractlanguage.h
new file mode 100644
index 0000000000..b997530d53
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractlanguage.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_ABTRACT_LANGUAGE_H
+#define QDESIGNER_ABTRACT_LANGUAGE_H
+
+#include <QtDesigner/extension.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDialog;
+class QWidget;
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+class QDesignerResourceBrowserInterface;
+
+class QDesignerLanguageExtension
+{
+public:
+ virtual ~QDesignerLanguageExtension() {}
+
+ virtual QDialog *createFormWindowSettingsDialog(QDesignerFormWindowInterface *formWindow, QWidget *parentWidget) = 0;
+ virtual QDesignerResourceBrowserInterface *createResourceBrowser(QWidget *parentWidget) = 0;
+
+ virtual QDialog *createPromotionDialog(QDesignerFormEditorInterface *formEditor, QWidget *parentWidget = 0) = 0;
+
+ virtual QDialog *createPromotionDialog(QDesignerFormEditorInterface *formEditor,
+ const QString &promotableWidgetClassName,
+ QString *promoteToClassName,
+ QWidget *parentWidget = 0) = 0;
+
+ virtual bool isLanguageResource(const QString &path) const = 0;
+
+ virtual QString classNameOf(QObject *object) const = 0;
+
+ virtual bool signalMatchesSlot(const QString &signal, const QString &slot) const = 0;
+
+ virtual QString widgetBoxContents() const = 0;
+
+ virtual QString uiExtension() const = 0;
+};
+
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerLanguageExtension, "com.trolltech.Qt.Designer.Language.3")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDESIGNER_ABTRACT_LANGUAGE_H
diff --git a/tools/designer/src/lib/sdk/abstractmetadatabase.cpp b/tools/designer/src/lib/sdk/abstractmetadatabase.cpp
new file mode 100644
index 0000000000..16bab34f50
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractmetadatabase.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// sdk
+#include "abstractmetadatabase.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerMetaDataBaseInterface
+ \brief The QDesignerMetaDataBaseInterface class provides an interface to Qt Designer's
+ object meta database.
+ \inmodule QtDesigner
+ \internal
+*/
+
+/*!
+ Constructs an interface to the meta database with the given \a parent.
+*/
+QDesignerMetaDataBaseInterface::QDesignerMetaDataBaseInterface(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the interface to the meta database.
+*/
+QDesignerMetaDataBaseInterface::~QDesignerMetaDataBaseInterface()
+{
+}
+
+/*!
+ \fn QDesignerMetaDataBaseItemInterface *QDesignerMetaDataBaseInterface::item(QObject *object) const
+
+ Returns the item in the meta database associated with the given \a object.
+*/
+
+/*!
+ \fn void QDesignerMetaDataBaseInterface::add(QObject *object)
+
+ Adds the specified \a object to the meta database.
+*/
+
+/*!
+ \fn void QDesignerMetaDataBaseInterface::remove(QObject *object)
+
+ Removes the specified \a object from the meta database.
+*/
+
+/*!
+ \fn QList<QObject*> QDesignerMetaDataBaseInterface::objects() const
+
+ Returns the list of objects that have corresponding items in the meta database.
+*/
+
+/*!
+ \fn QDesignerFormEditorInterface *QDesignerMetaDataBaseInterface::core() const
+
+ Returns the core interface that is associated with the meta database.
+*/
+
+
+// Doc: Interface only
+
+/*!
+ \class QDesignerMetaDataBaseItemInterface
+ \brief The QDesignerMetaDataBaseItemInterface class provides an interface to individual
+ items in Qt Designer's meta database.
+ \inmodule QtDesigner
+ \internal
+
+ This class allows individual items in \QD's meta-data database to be accessed and modified.
+ Use the QDesignerMetaDataBaseInterface class to change the properties of the database itself.
+*/
+
+/*!
+ \fn QDesignerMetaDataBaseItemInterface::~QDesignerMetaDataBaseItemInterface()
+
+ Destroys the item interface to the meta-data database.
+*/
+
+/*!
+ \fn QString QDesignerMetaDataBaseItemInterface::name() const
+
+ Returns the name of the item in the database.
+
+ \sa setName()
+*/
+
+/*!
+ \fn void QDesignerMetaDataBaseItemInterface::setName(const QString &name)
+
+ Sets the name of the item to the given \a name.
+
+ \sa name()
+*/
+
+/*!
+ \fn QList<QWidget*> QDesignerMetaDataBaseItemInterface::tabOrder() const
+
+ Returns a list of widgets in the order defined by the form's tab order.
+
+ \sa setTabOrder()
+*/
+
+
+/*!
+ \fn void QDesignerMetaDataBaseItemInterface::setTabOrder(const QList<QWidget*> &tabOrder)
+
+ Sets the tab order in the form using the list of widgets defined by \a tabOrder.
+
+ \sa tabOrder()
+*/
+
+
+/*!
+ \fn bool QDesignerMetaDataBaseItemInterface::enabled() const
+
+ Returns whether the item is enabled.
+
+ \sa setEnabled()
+*/
+
+/*!
+ \fn void QDesignerMetaDataBaseItemInterface::setEnabled(bool enabled)
+
+ If \a enabled is true, the item is enabled; otherwise it is disabled.
+
+ \sa enabled()
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractmetadatabase.h b/tools/designer/src/lib/sdk/abstractmetadatabase.h
new file mode 100644
index 0000000000..0c5dcc5cdc
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractmetadatabase.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTMETADATABASE_H
+#define ABSTRACTMETADATABASE_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QHash>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QCursor;
+class QWidget;
+
+class QDesignerFormEditorInterface;
+
+class QDesignerMetaDataBaseItemInterface
+{
+public:
+ virtual ~QDesignerMetaDataBaseItemInterface() {}
+
+ virtual QString name() const = 0;
+ virtual void setName(const QString &name) = 0;
+
+ virtual QList<QWidget*> tabOrder() const = 0;
+ virtual void setTabOrder(const QList<QWidget*> &tabOrder) = 0;
+
+ virtual bool enabled() const = 0;
+ virtual void setEnabled(bool b) = 0;
+};
+
+
+class QDESIGNER_SDK_EXPORT QDesignerMetaDataBaseInterface: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerMetaDataBaseInterface(QObject *parent = 0);
+ virtual ~QDesignerMetaDataBaseInterface();
+
+ virtual QDesignerMetaDataBaseItemInterface *item(QObject *object) const = 0;
+ virtual void add(QObject *object) = 0;
+ virtual void remove(QObject *object) = 0;
+
+ virtual QList<QObject*> objects() const = 0;
+
+ virtual QDesignerFormEditorInterface *core() const = 0;
+
+Q_SIGNALS:
+ void changed();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTMETADATABASE_H
diff --git a/tools/designer/src/lib/sdk/abstractnewformwidget.cpp b/tools/designer/src/lib/sdk/abstractnewformwidget.cpp
new file mode 100644
index 0000000000..ca1addea49
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractnewformwidget.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractnewformwidget_p.h"
+#include <newformwidget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerNewFormWidgetInterface
+ \since 4.5
+ \internal
+
+ \brief QDesignerNewFormWidgetInterface provides an interface for chooser
+ widgets that can be used within "New Form" dialogs and wizards.
+ It presents the user with a list of choices taken from built-in
+ templates, pre-defined template paths and suitable custom widgets.
+ It provides a static creation function that returns \QD's
+ implementation.
+
+ \inmodule QtDesigner
+*/
+
+/*!
+ Constructs a QDesignerNewFormWidgetInterface object.
+*/
+
+QDesignerNewFormWidgetInterface::QDesignerNewFormWidgetInterface(QWidget *parent) :
+ QWidget(parent)
+{
+}
+
+/*!
+ Destroys the QDesignerNewFormWidgetInterface object.
+*/
+
+QDesignerNewFormWidgetInterface::~QDesignerNewFormWidgetInterface()
+{
+}
+
+/*!
+ Creates an instance of the QDesignerNewFormWidgetInterface as a child
+ of \a parent using \a core.
+*/
+
+QDesignerNewFormWidgetInterface *QDesignerNewFormWidgetInterface::createNewFormWidget(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ return new qdesigner_internal::NewFormWidget(core, parent);
+}
+
+/*!
+ \fn bool QDesignerNewFormWidgetInterface::hasCurrentTemplate() const
+
+ Returns whether a form template is currently selected.
+*/
+
+/*!
+ \fn QString QDesignerNewFormWidgetInterface::currentTemplate(QString *errorMessage = 0)
+
+ Returns the contents of the currently selected template. If the method fails,
+ an empty string is returned and \a errorMessage receives an error message.
+*/
+
+// Signals
+
+/*!
+ \fn void QDesignerNewFormWidgetInterface::templateActivated()
+
+ This signal is emitted whenever the user activates a template by double-clicking.
+*/
+
+/*!
+ \fn void QDesignerNewFormWidgetInterface::currentTemplateChanged(bool templateSelected)
+
+ This signal is emitted whenever the user changes the current template.
+ \a templateSelected indicates whether a template is currently selected.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractnewformwidget_p.h b/tools/designer/src/lib/sdk/abstractnewformwidget_p.h
new file mode 100644
index 0000000000..df8020abdc
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractnewformwidget_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ABSTRACTNEWFORMWIDGET_H
+#define ABSTRACTNEWFORMWIDGET_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerNewFormWidgetInterface : public QWidget
+{
+ Q_DISABLE_COPY(QDesignerNewFormWidgetInterface)
+ Q_OBJECT
+public:
+ explicit QDesignerNewFormWidgetInterface(QWidget *parent = 0);
+ virtual ~QDesignerNewFormWidgetInterface();
+
+ virtual bool hasCurrentTemplate() const = 0;
+ virtual QString currentTemplate(QString *errorMessage = 0) = 0;
+
+ static QDesignerNewFormWidgetInterface *createNewFormWidget(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+
+Q_SIGNALS:
+ void templateActivated();
+ void currentTemplateChanged(bool templateSelected);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTNEWFORMWIDGET_H
diff --git a/tools/designer/src/lib/sdk/abstractobjectinspector.cpp b/tools/designer/src/lib/sdk/abstractobjectinspector.cpp
new file mode 100644
index 0000000000..61af96a4d1
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractobjectinspector.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractobjectinspector.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerObjectInspectorInterface
+
+ \brief The QDesignerObjectInspectorInterface class allows you to
+ change the focus of Qt Designer's object inspector.
+
+ \inmodule QtDesigner
+
+ You can use the QDesignerObjectInspectorInterface to change the
+ current form window selection. For example, when implementing a
+ custom widget plugin:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractobjectinspector.cpp 0
+
+ The QDesignerObjectInspectorInterface class is not intended to be
+ instantiated directly. You can retrieve an interface to \QD's
+ object inspector using the
+ QDesignerFormEditorInterface::objectInspector() function. A
+ pointer to \QD's current QDesignerFormEditorInterface object (\c
+ formEditor in the example above) is provided by the
+ QDesignerCustomWidgetInterface::initialize() function's
+ parameter. When implementing a custom widget plugin, you must
+ subclass the QDesignerCustomWidgetInterface to expose your plugin
+ to \QD.
+
+ The interface provides the core() function that you can use to
+ retrieve a pointer to \QD's current QDesignerFormEditorInterface
+ object, and the setFormWindow() function that enables you to
+ change the current form window selection.
+
+ \sa QDesignerFormEditorInterface, QDesignerFormWindowInterface
+*/
+
+/*!
+ Constructs an object inspector interface with the given \a parent
+ and the specified window \a flags.
+*/
+QDesignerObjectInspectorInterface::QDesignerObjectInspectorInterface(QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags)
+{
+}
+
+/*!
+ Destroys the object inspector interface.
+*/
+QDesignerObjectInspectorInterface::~QDesignerObjectInspectorInterface()
+{
+}
+
+/*!
+ Returns a pointer to \QD's current QDesignerFormEditorInterface
+ object.
+*/
+QDesignerFormEditorInterface *QDesignerObjectInspectorInterface::core() const
+{
+ return 0;
+}
+
+/*!
+ \fn void QDesignerObjectInspectorInterface::setFormWindow(QDesignerFormWindowInterface *formWindow)
+
+ Sets the currently selected form window to \a formWindow.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractobjectinspector.h b/tools/designer/src/lib/sdk/abstractobjectinspector.h
new file mode 100644
index 0000000000..39f13616e9
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractobjectinspector.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTOBJECTINSPECTOR_H
+#define ABSTRACTOBJECTINSPECTOR_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerObjectInspectorInterface: public QWidget
+{
+ Q_OBJECT
+public:
+ QDesignerObjectInspectorInterface(QWidget *parent, Qt::WindowFlags flags = 0);
+ virtual ~QDesignerObjectInspectorInterface();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+public Q_SLOTS:
+ virtual void setFormWindow(QDesignerFormWindowInterface *formWindow) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTOBJECTINSPECTOR_H
diff --git a/tools/designer/src/lib/sdk/abstractoptionspage_p.h b/tools/designer/src/lib/sdk/abstractoptionspage_p.h
new file mode 100644
index 0000000000..415cc834d9
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractoptionspage_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ABSTRACTOPTIONSPAGE_P_H
+#define ABSTRACTOPTIONSPAGE_P_H
+
+#include <QtDesigner/sdk_global.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QWidget;
+
+class QDESIGNER_SDK_EXPORT QDesignerOptionsPageInterface
+{
+public:
+ virtual ~QDesignerOptionsPageInterface() {}
+ virtual QString name() const = 0;
+ virtual QWidget *createPage(QWidget *parent) = 0;
+ virtual void apply() = 0;
+ virtual void finish() = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTOPTIONSPAGE_P_H
diff --git a/tools/designer/src/lib/sdk/abstractpromotioninterface.cpp b/tools/designer/src/lib/sdk/abstractpromotioninterface.cpp
new file mode 100644
index 0000000000..79fba01df1
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractpromotioninterface.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractpromotioninterface.h"
+
+QT_BEGIN_NAMESPACE
+
+QDesignerPromotionInterface::~QDesignerPromotionInterface()
+{
+}
+
+/*!
+ \class QDesignerPromotionInterface
+
+ \brief The QDesignerPromotionInterface provides functions for modifying
+ the promoted classes in Designer.
+ \inmodule QtDesigner
+ \internal
+ \since 4.3
+*/
+
+/*!
+ \class QDesignerPromotionInterface::PromotedClass
+ A pair of database items containing the base class and the promoted class.
+
+ \typedef QDesignerPromotionInterface::PromotedClasses
+ A list of PromotedClass items.
+
+ virtual QDesignerPromotionInterface::PromotedClasses promotedClasses() const
+
+ Returns a list of promoted classes along with their base classes in alphabetical order.
+ It can be used to populate tree models for editing promoted widgets.
+
+*/
+
+/*!
+ \fn virtual QSet<QString> QDesignerPromotionInterface::referencedPromotedClassNames() const
+
+ Returns a set of promoted classed that are referenced by the currently opened forms.
+*/
+
+/*!
+ \fn virtual bool QDesignerPromotionInterface::addPromotedClass(const QString &baseClass, const QString &className, const QString &includeFile, QString *errorMessage)
+
+ Add a promoted class named \a with the base class \a and include file \a includeFile. Returns \c true on success or \c false along
+ with an error message in \a errorMessage on failure.
+*/
+
+/*!
+ \fn virtual bool QDesignerPromotionInterface::removePromotedClass(const QString &className, QString *errorMessage)
+
+ Remove the promoted class named \a className unless it is referenced by a form. Returns \c true on success or \c false along
+ with an error message in \a errorMessage on failure.
+*/
+
+/*!
+ \fn virtual bool QDesignerPromotionInterface::changePromotedClassName(const QString &oldClassName, const QString &newClassName, QString *errorMessage)
+
+ Change the class name of a promoted class from \a oldClassName to \a newClassName. Returns \c true on success or \c false along
+ with an error message in \a errorMessage on failure.
+*/
+
+/*!
+ \fn virtual bool QDesignerPromotionInterface::setPromotedClassIncludeFile(const QString &className, const QString &includeFile, QString *errorMessage)
+
+ Change the include file of a promoted class named \a className to be \a includeFile. Returns \c true on success or \c false along
+ with an error message in \a errorMessage on failure.
+*/
+
+/*! \fn virtual QList<QDesignerWidgetDataBaseItemInterface *> QDesignerPromotionInterface::promotionBaseClasses() const
+
+ Return a list of base classes that are suitable for promotion.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractpromotioninterface.h b/tools/designer/src/lib/sdk/abstractpromotioninterface.h
new file mode 100644
index 0000000000..2acae74b3e
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractpromotioninterface.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTPROMOTIONINTERFACE_H
+#define ABSTRACTPROMOTIONINTERFACE_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QPair>
+#include <QtCore/QList>
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerWidgetDataBaseItemInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerPromotionInterface
+{
+public:
+ virtual ~QDesignerPromotionInterface();
+
+ struct PromotedClass {
+ QDesignerWidgetDataBaseItemInterface *baseItem;
+ QDesignerWidgetDataBaseItemInterface *promotedItem;
+ };
+
+ typedef QList<PromotedClass> PromotedClasses;
+
+ virtual PromotedClasses promotedClasses() const = 0;
+
+ virtual QSet<QString> referencedPromotedClassNames() const = 0;
+
+ virtual bool addPromotedClass(const QString &baseClass,
+ const QString &className,
+ const QString &includeFile,
+ QString *errorMessage) = 0;
+
+ virtual bool removePromotedClass(const QString &className, QString *errorMessage) = 0;
+
+ virtual bool changePromotedClassName(const QString &oldClassName, const QString &newClassName, QString *errorMessage) = 0;
+
+ virtual bool setPromotedClassIncludeFile(const QString &className, const QString &includeFile, QString *errorMessage) = 0;
+
+ virtual QList<QDesignerWidgetDataBaseItemInterface *> promotionBaseClasses() const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTPROMOTIONINTERFACE_H
diff --git a/tools/designer/src/lib/sdk/abstractpropertyeditor.cpp b/tools/designer/src/lib/sdk/abstractpropertyeditor.cpp
new file mode 100644
index 0000000000..f244a52231
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractpropertyeditor.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractpropertyeditor.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerPropertyEditorInterface
+
+ \brief The QDesignerPropertyEditorInterface class allows you to
+ query and manipulate the current state of Qt Designer's property
+ editor.
+
+ \inmodule QtDesigner
+
+ QDesignerPropertyEditorInterface contains a collection of
+ functions that is typically used to query the property editor for
+ its current state, and several slots manipulating it's state. The
+ interface also provide a signal, propertyChanged(), which is
+ emitted whenever a property changes in the property editor. The
+ signal's arguments are the property that changed and its new
+ value.
+
+ For example, when implementing a custom widget plugin, you can
+ connect the signal to a custom slot:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.cpp 0
+
+ Then the custom slot can check if the new value is within the
+ range we want when a specified property, belonging to a particular
+ widget, changes:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractpropertyeditor.cpp 1
+
+ The QDesignerPropertyEditorInterface class is not intended to be
+ instantiated directly. You can retrieve an interface to \QD's
+ property editor using the
+ QDesignerFormEditorInterface::propertyEditor() function. A pointer
+ to \QD's current QDesignerFormEditorInterface object (\c
+ formEditor in the examples above) is provided by the
+ QDesignerCustomWidgetInterface::initialize() function's
+ parameter. When implementing a custom widget plugin, you must
+ subclass the QDesignerCustomWidgetInterface to expose your plugin
+ to \QD.
+
+ The functions accessing the property editor are the core()
+ function that you can use to retrieve an interface to the form
+ editor, the currentPropertyName() function that returns the name
+ of the currently selected property in the property editor, the
+ object() function that returns the currently selected object in
+ \QD's workspace, and the isReadOnly() function that returns true
+ if the property editor is write proteced (otherwise false).
+
+ The slots manipulating the property editor's state are the
+ setObject() slot that you can use to change the currently selected
+ object in \QD's workspace, the setPropertyValue() slot that
+ changes the value of a given property and the setReadOnly() slot
+ that control the write protection of the property editor.
+
+ \sa QDesignerFormEditorInterface
+*/
+
+/*!
+ Constructs a property editor interface with the given \a parent and
+ the specified window \a flags.
+*/
+QDesignerPropertyEditorInterface::QDesignerPropertyEditorInterface(QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags)
+{
+}
+
+/*!
+ Destroys the property editor interface.
+*/
+QDesignerPropertyEditorInterface::~QDesignerPropertyEditorInterface()
+{
+}
+
+/*!
+ Returns a pointer to \QD's current QDesignerFormEditorInterface
+ object.
+*/
+QDesignerFormEditorInterface *QDesignerPropertyEditorInterface::core() const
+{
+ return 0;
+}
+
+/*!
+ \fn bool QDesignerPropertyEditorInterface::isReadOnly() const
+
+ Returns true if the property editor is write protected; otherwise
+ false.
+
+ \sa setReadOnly()
+*/
+
+/*!
+ \fn QObject *QDesignerPropertyEditorInterface::object() const
+
+ Returns the currently selected object in \QD's workspace.
+
+ \sa setObject()
+*/
+
+/*!
+ \fn QString QDesignerPropertyEditorInterface::currentPropertyName() const
+
+ Returns the name of the currently selected property in the
+ property editor.
+
+ \sa setPropertyValue()
+*/
+
+/*!
+ \fn void QDesignerPropertyEditorInterface::propertyChanged(const QString &name, const QVariant &value)
+
+ This signal is emitted whenever a property changes in the property
+ editor. The property that changed and its new value are specified
+ by \a name and \a value respectively.
+
+ \sa setPropertyValue()
+*/
+
+/*!
+ \fn void QDesignerPropertyEditorInterface::setObject(QObject *object)
+
+ Changes the currently selected object in \QD's workspace, to \a
+ object.
+
+ \sa object()
+*/
+
+/*!
+ \fn void QDesignerPropertyEditorInterface::setPropertyValue(const QString &name, const QVariant &value, bool changed = true)
+
+ Sets the value of the property specified by \a name to \a
+ value.
+
+ In addition, the property is marked as \a changed in the property
+ editor, i.e. its value is different from the default value.
+
+ \sa currentPropertyName(), propertyChanged()
+*/
+
+/*!
+ \fn void QDesignerPropertyEditorInterface::setReadOnly(bool readOnly)
+
+ If \a readOnly is true, the property editor is made write
+ protected; otherwise the write protection is removed.
+
+ \sa isReadOnly()
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractpropertyeditor.h b/tools/designer/src/lib/sdk/abstractpropertyeditor.h
new file mode 100644
index 0000000000..acdcd4f6b5
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractpropertyeditor.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTPROPERTYEDITOR_H
+#define ABSTRACTPROPERTYEDITOR_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QString;
+class QVariant;
+
+class QDESIGNER_SDK_EXPORT QDesignerPropertyEditorInterface: public QWidget
+{
+ Q_OBJECT
+public:
+ QDesignerPropertyEditorInterface(QWidget *parent, Qt::WindowFlags flags = 0);
+ virtual ~QDesignerPropertyEditorInterface();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool isReadOnly() const = 0;
+ virtual QObject *object() const = 0;
+
+ virtual QString currentPropertyName() const = 0;
+
+Q_SIGNALS:
+ void propertyChanged(const QString &name, const QVariant &value);
+
+public Q_SLOTS:
+ virtual void setObject(QObject *object) = 0;
+ virtual void setPropertyValue(const QString &name, const QVariant &value, bool changed = true) = 0;
+ virtual void setReadOnly(bool readOnly) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTPROPERTYEDITOR_H
diff --git a/tools/designer/src/lib/sdk/abstractresourcebrowser.cpp b/tools/designer/src/lib/sdk/abstractresourcebrowser.cpp
new file mode 100644
index 0000000000..1aed6da09f
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractresourcebrowser.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractresourcebrowser.h"
+
+QT_BEGIN_NAMESPACE
+
+QDesignerResourceBrowserInterface::QDesignerResourceBrowserInterface(QWidget *parent)
+ : QWidget(parent)
+{
+
+}
+
+QDesignerResourceBrowserInterface::~QDesignerResourceBrowserInterface()
+{
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractresourcebrowser.h b/tools/designer/src/lib/sdk/abstractresourcebrowser.h
new file mode 100644
index 0000000000..9f6b523f24
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractresourcebrowser.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTRESOURCEBROWSER_H
+#define ABSTRACTRESOURCEBROWSER_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QWidget; // FIXME: fool syncqt
+
+class QDESIGNER_SDK_EXPORT QDesignerResourceBrowserInterface: public QWidget
+{
+ Q_OBJECT
+public:
+ QDesignerResourceBrowserInterface(QWidget *parent = 0);
+ virtual ~QDesignerResourceBrowserInterface();
+
+ virtual void setCurrentPath(const QString &filePath) = 0;
+ virtual QString currentPath() const = 0;
+
+Q_SIGNALS:
+ void currentPathChanged(const QString &filePath);
+ void pathActivated(const QString &filePath);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMEDITOR_H
+
diff --git a/tools/designer/src/lib/sdk/abstractsettings_p.h b/tools/designer/src/lib/sdk/abstractsettings_p.h
new file mode 100644
index 0000000000..2117b49808
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractsettings_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ABSTRACTSETTINGS_P_H
+#define ABSTRACTSETTINGS_P_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+/*!
+ To be implemented by IDEs that want to control the way designer retrieves/stores its settings.
+ */
+class QDESIGNER_SDK_EXPORT QDesignerSettingsInterface
+{
+public:
+ virtual ~QDesignerSettingsInterface() {}
+
+ virtual void beginGroup(const QString &prefix) = 0;
+ virtual void endGroup() = 0;
+
+ virtual bool contains(const QString &key) const = 0;
+ virtual void setValue(const QString &key, const QVariant &value) = 0;
+ virtual QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const = 0;
+ virtual void remove(const QString &key) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTSETTINGS_P_H
diff --git a/tools/designer/src/lib/sdk/abstractwidgetbox.cpp b/tools/designer/src/lib/sdk/abstractwidgetbox.cpp
new file mode 100644
index 0000000000..a09f50eec0
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractwidgetbox.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractwidgetbox.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerWidgetBoxInterface
+
+ \brief The QDesignerWidgetBoxInterface class allows you to control
+ the contents of Qt Designer's widget box.
+
+ \inmodule QtDesigner
+
+ QDesignerWidgetBoxInterface contains a collection of functions
+ that is typically used to manipulate the contents of \QD's widget
+ box.
+
+ \QD uses an XML file to populate its widget box. The name of that
+ file is one of the widget box's properties, and you can retrieve
+ it using the fileName() function.
+
+ QDesignerWidgetBoxInterface also provides the save() function that
+ saves the contents of the widget box in the file specified by the
+ widget box's file name property. If you have made changes to the
+ widget box, for example by dropping a widget into the widget box,
+ without calling the save() function, the original content can be
+ restored by a simple invocation of the load() function:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractwidgetbox.cpp 0
+
+ The QDesignerWidgetBoxInterface class is not intended to be
+ instantiated directly. You can retrieve an interface to Qt
+ Designer's widget box using the
+ QDesignerFormEditorInterface::widgetBox() function. A pointer to
+ \QD's current QDesignerFormEditorInterface object (\c formEditor
+ in the example above) is provided by the
+ QDesignerCustomWidgetInterface::initialize() function's
+ parameter. When implementing a custom widget plugin, you must
+ subclass the QDesignerCustomWidgetInterface to expose your plugin
+ to \QD.
+
+ If you want to save your changes, and at the same time preserve
+ the original contents, you can use the save() function combined
+ with the setFileName() function to save your changes into another
+ file. Remember to store the name of the original file first:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractwidgetbox.cpp 1
+
+ Then you can restore the original contents of the widget box by
+ resetting the file name to the original file and calling load():
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractwidgetbox.cpp 2
+
+ In a similar way, you can later use your customized XML file:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_sdk_abstractwidgetbox.cpp 3
+
+
+ \sa QDesignerFormEditorInterface
+*/
+
+/*!
+ Constructs a widget box interface with the given \a parent and
+ the specified window \a flags.
+*/
+QDesignerWidgetBoxInterface::QDesignerWidgetBoxInterface(QWidget *parent, Qt::WindowFlags flags)
+ : QWidget(parent, flags)
+{
+}
+
+/*!
+ Destroys the widget box interface.
+*/
+QDesignerWidgetBoxInterface::~QDesignerWidgetBoxInterface()
+{
+}
+
+/*!
+ \internal
+*/
+int QDesignerWidgetBoxInterface::findOrInsertCategory(const QString &categoryName)
+{
+ int count = categoryCount();
+ for (int index=0; index<count; ++index) {
+ Category c = category(index);
+ if (c.name() == categoryName)
+ return index;
+ }
+
+ addCategory(Category(categoryName));
+ return count;
+}
+
+/*!
+ \internal
+ \fn int QDesignerWidgetBoxInterface::categoryCount() const
+*/
+
+/*!
+ \internal
+ \fn Category QDesignerWidgetBoxInterface::category(int cat_idx) const
+*/
+
+/*!
+ \internal
+ \fn void QDesignerWidgetBoxInterface::addCategory(const Category &cat)
+*/
+
+/*!
+ \internal
+ \fn void QDesignerWidgetBoxInterface::removeCategory(int cat_idx)
+*/
+
+/*!
+ \internal
+ \fn int QDesignerWidgetBoxInterface::widgetCount(int cat_idx) const
+*/
+
+/*!
+ \internal
+ \fn Widget QDesignerWidgetBoxInterface::widget(int cat_idx, int wgt_idx) const
+*/
+
+/*!
+ \internal
+ \fn void QDesignerWidgetBoxInterface::addWidget(int cat_idx, const Widget &wgt)
+*/
+
+/*!
+ \internal
+ \fn void QDesignerWidgetBoxInterface::removeWidget(int cat_idx, int wgt_idx)
+*/
+
+/*!
+ \internal
+ \fn void QDesignerWidgetBoxInterface::dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, const QPoint &global_mouse_pos)
+
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::setFileName(const QString &fileName)
+
+ Sets the XML file that \QD will use to populate its widget box, to
+ \a fileName. You must call load() to update the widget box with
+ the new XML file.
+
+ \sa fileName(), load()
+*/
+
+/*!
+ \fn QString QDesignerWidgetBoxInterface::fileName() const
+
+ Returns the name of the XML file \QD is currently using to
+ populate its widget box.
+
+ \sa setFileName()
+*/
+
+/*!
+ \fn bool QDesignerWidgetBoxInterface::load()
+
+ Populates \QD's widget box by loading (or reloading) the currently
+ specified XML file. Returns true if the file is successfully
+ loaded; otherwise false.
+
+ \sa setFileName()
+*/
+
+/*!
+ \fn bool QDesignerWidgetBoxInterface::save()
+
+ Saves the contents of \QD's widget box in the file specified by
+ the fileName() function. Returns true if the content is
+ successfully saved; otherwise false.
+
+ \sa fileName(), setFileName()
+*/
+
+
+/*!
+ \internal
+
+ \class QDesignerWidgetBoxInterface::Widget
+
+ \brief The Widget class specified a widget in Qt Designer's widget
+ box component.
+*/
+
+/*!
+ \enum QDesignerWidgetBoxInterface::Widget::Type
+
+ \value Default
+ \value Custom
+*/
+
+/*!
+ \fn QDesignerWidgetBoxInterface::Widget::Widget(const QString &aname, const QString &xml, const QString &icon_name, Type atype)
+*/
+
+/*!
+ \fn QString QDesignerWidgetBoxInterface::Widget::name() const
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Widget::setName(const QString &aname)
+*/
+
+/*!
+ \fn QString QDesignerWidgetBoxInterface::Widget::domXml() const
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Widget::setDomXml(const QString &xml)
+*/
+
+/*!
+ \fn QString QDesignerWidgetBoxInterface::Widget::iconName() const
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Widget::setIconName(const QString &icon_name)
+*/
+
+/*!
+ \fn Type QDesignerWidgetBoxInterface::Widget::type() const
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Widget::setType(Type atype)
+*/
+
+/*!
+ \fn bool QDesignerWidgetBoxInterface::Widget::isNull() const
+*/
+
+
+/*!
+ \class QDesignerWidgetBoxInterface::Category
+ \brief The Category class specifies a category in Qt Designer's widget box component.
+ \internal
+*/
+
+/*!
+ \enum QDesignerWidgetBoxInterface::Category::Type
+
+ \value Default
+ \value Scratchpad
+*/
+
+/*!
+ \fn QDesignerWidgetBoxInterface::Category::Category(const QString &aname, Type atype)
+*/
+
+/*!
+ \fn QString QDesignerWidgetBoxInterface::Category::name() const
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Category::setName(const QString &aname)
+*/
+
+/*!
+ \fn int QDesignerWidgetBoxInterface::Category::widgetCount() const
+*/
+
+/*!
+ \fn Widget QDesignerWidgetBoxInterface::Category::widget(int idx) const
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Category::removeWidget(int idx)
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Category::addWidget(const Widget &awidget)
+*/
+
+/*!
+ \fn Type QDesignerWidgetBoxInterface::Category::type() const
+*/
+
+/*!
+ \fn void QDesignerWidgetBoxInterface::Category::setType(Type atype)
+*/
+
+/*!
+ \fn bool QDesignerWidgetBoxInterface::Category::isNull() const
+*/
+
+/*!
+ \typedef QDesignerWidgetBoxInterface::CategoryList
+ \internal
+*/
+
+/*!
+ \typedef QDesignerWidgetBoxInterface::WidgetList
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractwidgetbox.h b/tools/designer/src/lib/sdk/abstractwidgetbox.h
new file mode 100644
index 0000000000..b5ccde1590
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractwidgetbox.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTWIDGETBOX_H
+#define ABSTRACTWIDGETBOX_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QMetaType>
+#include <QtGui/QWidget>
+#include <QtGui/QIcon>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DomUI;
+class QDesignerDnDItemInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerWidgetBoxInterface : public QWidget
+{
+ Q_OBJECT
+public:
+ class Widget {
+ public:
+ enum Type { Default, Custom };
+ Widget(const QString &aname = QString(), const QString &xml = QString(),
+ const QString &icon_name = QString(), Type atype = Default)
+ : m_name(aname), m_xml(xml), m_icon_name(icon_name), m_type(atype) {}
+ QString name() const { return m_name; }
+ void setName(const QString &aname) { m_name = aname; }
+ QString domXml() const { return m_xml; }
+ void setDomXml(const QString &xml) { m_xml = xml; }
+ QString iconName() const { return m_icon_name; }
+ void setIconName(const QString &icon_name) { m_icon_name = icon_name; }
+ Type type() const { return m_type; }
+ void setType(Type atype) { m_type = atype; }
+
+ bool isNull() const { return m_name.isEmpty(); }
+
+ private:
+ QString m_name;
+ QString m_xml;
+ QString m_icon_name;
+ Type m_type;
+ };
+ typedef QList<Widget> WidgetList;
+
+ class Category {
+ public:
+ enum Type { Default, Scratchpad };
+
+ Category(const QString &aname = QString(), Type atype = Default)
+ : m_name(aname), m_type(atype) {}
+
+ QString name() const { return m_name; }
+ void setName(const QString &aname) { m_name = aname; }
+ int widgetCount() const { return m_widget_list.size(); }
+ Widget widget(int idx) const { return m_widget_list.at(idx); }
+ void removeWidget(int idx) { m_widget_list.removeAt(idx); }
+ void addWidget(const Widget &awidget) { m_widget_list.append(awidget); }
+ Type type() const { return m_type; }
+ void setType(Type atype) { m_type = atype; }
+
+ bool isNull() const { return m_name.isEmpty(); }
+
+ private:
+ QString m_name;
+ Type m_type;
+ QList<Widget> m_widget_list;
+ };
+ typedef QList<Category> CategoryList;
+
+ QDesignerWidgetBoxInterface(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~QDesignerWidgetBoxInterface();
+
+ virtual int categoryCount() const = 0;
+ virtual Category category(int cat_idx) const = 0;
+ virtual void addCategory(const Category &cat) = 0;
+ virtual void removeCategory(int cat_idx) = 0;
+
+ virtual int widgetCount(int cat_idx) const = 0;
+ virtual Widget widget(int cat_idx, int wgt_idx) const = 0;
+ virtual void addWidget(int cat_idx, const Widget &wgt) = 0;
+ virtual void removeWidget(int cat_idx, int wgt_idx) = 0;
+
+ int findOrInsertCategory(const QString &categoryName);
+
+ virtual void dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list,
+ const QPoint &global_mouse_pos) = 0;
+
+ virtual void setFileName(const QString &file_name) = 0;
+ virtual QString fileName() const = 0;
+ virtual bool load() = 0;
+ virtual bool save() = 0;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QDesignerWidgetBoxInterface::Widget))
+
+QT_END_HEADER
+
+#endif // ABSTRACTWIDGETBOX_H
diff --git a/tools/designer/src/lib/sdk/abstractwidgetdatabase.cpp b/tools/designer/src/lib/sdk/abstractwidgetdatabase.cpp
new file mode 100644
index 0000000000..39b64fcf67
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractwidgetdatabase.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractwidgetdatabase.h"
+#include <QtCore/qdebug.h>
+#include <qalgorithms.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { debugWidgetDataBase = 0 };
+}
+
+/*!
+ \class QDesignerWidgetDataBaseInterface
+ \brief The QDesignerWidgetDataBaseInterface class provides an interface that is used to
+ access and modify Qt Designer's widget database.
+ \inmodule QtDesigner
+ \internal
+*/
+
+/*!
+ Constructs an interface to the widget database with the given \a parent.
+*/
+QDesignerWidgetDataBaseInterface::QDesignerWidgetDataBaseInterface(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the interface to the widget database.
+*/
+QDesignerWidgetDataBaseInterface::~QDesignerWidgetDataBaseInterface()
+{
+ qDeleteAll(m_items);
+}
+
+/*!
+
+*/
+int QDesignerWidgetDataBaseInterface::count() const
+{
+ return m_items.count();
+}
+
+/*!
+*/
+QDesignerWidgetDataBaseItemInterface *QDesignerWidgetDataBaseInterface::item(int index) const
+{
+ return index != -1 ? m_items.at(index) : 0;
+}
+
+/*!
+*/
+int QDesignerWidgetDataBaseInterface::indexOf(QDesignerWidgetDataBaseItemInterface *item) const
+{
+ return m_items.indexOf(item);
+}
+
+/*!
+*/
+void QDesignerWidgetDataBaseInterface::insert(int index, QDesignerWidgetDataBaseItemInterface *item)
+{
+ if (debugWidgetDataBase)
+ qDebug() << "insert at " << index << ' ' << item->name() << " derived from " << item->extends();
+
+ m_items.insert(index, item);
+}
+
+/*!
+*/
+void QDesignerWidgetDataBaseInterface::append(QDesignerWidgetDataBaseItemInterface *item)
+{
+ if (debugWidgetDataBase)
+ qDebug() << "append " << item->name() << " derived from " << item->extends();
+ m_items.append(item);
+}
+
+/*!
+*/
+QDesignerFormEditorInterface *QDesignerWidgetDataBaseInterface::core() const
+{
+ return 0;
+}
+
+/*!
+*/
+int QDesignerWidgetDataBaseInterface::indexOfClassName(const QString &name, bool) const
+{
+ const int itemCount = count();
+ for (int i=0; i<itemCount; ++i) {
+ const QDesignerWidgetDataBaseItemInterface *entry = item(i);
+ if (entry->name() == name)
+ return i;
+ }
+
+ return -1;
+}
+
+/*!
+*/
+int QDesignerWidgetDataBaseInterface::indexOfObject(QObject *object, bool) const
+{
+ if (!object)
+ return -1;
+
+ const QString className = QString::fromUtf8(object->metaObject()->className());
+ return indexOfClassName(className);
+}
+
+/*!
+*/
+bool QDesignerWidgetDataBaseInterface::isContainer(QObject *object, bool resolveName) const
+{
+ if (const QDesignerWidgetDataBaseItemInterface *i = item(indexOfObject(object, resolveName)))
+ return i->isContainer();
+ return false;
+}
+
+/*!
+*/
+bool QDesignerWidgetDataBaseInterface::isCustom(QObject *object, bool resolveName) const
+{
+ if (const QDesignerWidgetDataBaseItemInterface *i = item(indexOfObject(object, resolveName)))
+ return i->isCustom();
+ return false;
+}
+
+/*!
+ \fn void QDesignerWidgetDataBaseInterface::changed()
+
+ This signal is emitted ...
+*/
+
+
+// Doc: No implementation - an abstract class
+
+/*!
+ \class QDesignerWidgetDataBaseItemInterface
+ \brief The QDesignerWidgetDataBaseItemInterface class provides an interface that is used to
+ access individual items in Qt Designer's widget database.
+ \inmodule QtDesigner
+ \internal
+
+ This class enables individual items in the widget database to be accessed and modified.
+ Changes to the widget database itself are made through the QDesignerWidgetDataBaseInterface
+ class.
+*/
+
+/*!
+ \fn virtual QDesignerWidgetDataBaseItemInterface::~QDesignerWidgetDataBaseItemInterface()
+
+ Destroys the interface.
+*/
+
+/*!
+ \fn virtual QString QDesignerWidgetDataBaseItemInterface::name() const = 0
+
+ Returns the name of the widget.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setName(const QString &name) = 0
+*/
+
+/*!
+ \fn virtual QString QDesignerWidgetDataBaseItemInterface::group() const = 0
+
+ Returns the name of the group that the widget belongs to.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setGroup(const QString &group) = 0
+*/
+
+/*!
+ \fn virtual QString QDesignerWidgetDataBaseItemInterface::toolTip() const = 0
+
+ Returns the tool tip to be used by the widget.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setToolTip(const QString &toolTip) = 0
+*/
+
+/*!
+ \fn virtual QString QDesignerWidgetDataBaseItemInterface::whatsThis() const = 0
+
+ Returns the "What's This?" help for the widget.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setWhatsThis(const QString &whatsThis) = 0
+*/
+
+/*!
+ \fn virtual QString QDesignerWidgetDataBaseItemInterface::includeFile() const = 0
+
+ Returns the name of the include file that the widget needs when being built from source.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setIncludeFile(const QString &includeFile) = 0
+*/
+
+/*!
+ \fn virtual QIcon QDesignerWidgetDataBaseItemInterface::icon() const = 0
+
+ Returns the icon used to represent the item.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setIcon(const QIcon &icon) = 0
+*/
+
+/*!
+ \fn virtual bool QDesignerWidgetDataBaseItemInterface::isCompat() const = 0
+
+ Returns true if this type of widget is provided for compatibility purposes (e.g. Qt3Support
+ widgets); otherwise returns false.
+
+ \sa setCompat()
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setCompat(bool compat) = 0
+
+ If \a compat is true, the widget is handled as a compatibility widget; otherwise it is
+ handled normally by \QD.
+
+ \sa isCompat()
+*/
+
+/*!
+ \fn virtual bool QDesignerWidgetDataBaseItemInterface::isContainer() const = 0
+
+ Returns true if this widget is intended to be used to hold other widgets; otherwise returns
+ false.
+
+ \sa setContainer()
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setContainer(bool container) = 0
+
+ If \a container is true, the widget can be used to hold other widgets in \QD; otherwise
+ \QD will refuse to let the user place other widgets inside it.
+
+ \sa isContainer()
+*/
+
+/*!
+ \fn virtual bool QDesignerWidgetDataBaseItemInterface::isCustom() const = 0
+
+ Returns true if the widget is a custom widget; otherwise return false if it is a standard
+ Qt widget.
+
+ \sa setCustom()
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setCustom(bool custom) = 0
+
+ If \a custom is true, the widget is handled specially by \QD; otherwise it is handled as
+ a standard Qt widget.
+
+ \sa isCustom()
+*/
+
+/*!
+ \fn virtual QString QDesignerWidgetDataBaseItemInterface::pluginPath() const = 0
+
+ Returns the path to use for the widget plugin.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setPluginPath(const QString &path) = 0
+*/
+
+/*!
+ \fn virtual bool QDesignerWidgetDataBaseItemInterface::isPromoted() const = 0
+
+ Returns true if the widget is promoted; otherwise returns false.
+
+ Promoted widgets are those that represent custom widgets, but which are represented in
+ \QD by either standard Qt widgets or readily-available custom widgets.
+
+ \sa setPromoted()
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setPromoted(bool promoted) = 0
+
+ If \a promoted is true, the widget is handled as a promoted widget by \QD and will use
+ a placeholder widget to represent it; otherwise it is handled as a standard widget.
+
+ \sa isPromoted()
+*/
+
+/*!
+ \fn virtual QString QDesignerWidgetDataBaseItemInterface::extends() const = 0
+
+ Returns the name of the widget that the item extends.
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setExtends(const QString &s) = 0
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetDataBaseItemInterface::setDefaultPropertyValues(const QList<QVariant> &list) = 0
+
+ Sets the default property values for the widget to the given \a list.
+*/
+
+/*!
+ \fn virtual QList<QVariant> QDesignerWidgetDataBaseItemInterface::defaultPropertyValues() const = 0
+
+ Returns a list of default values to be used as properties for the item.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractwidgetdatabase.h b/tools/designer/src/lib/sdk/abstractwidgetdatabase.h
new file mode 100644
index 0000000000..7c6671006e
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractwidgetdatabase.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTWIDGETDATABASE_H
+#define ABSTRACTWIDGETDATABASE_H
+
+#include <QtDesigner/sdk_global.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QIcon;
+class QString;
+class QDesignerFormEditorInterface;
+class QDebug;
+
+class QDesignerWidgetDataBaseItemInterface
+{
+public:
+ virtual ~QDesignerWidgetDataBaseItemInterface() {}
+
+ virtual QString name() const = 0;
+ virtual void setName(const QString &name) = 0;
+
+ virtual QString group() const = 0;
+ virtual void setGroup(const QString &group) = 0;
+
+ virtual QString toolTip() const = 0;
+ virtual void setToolTip(const QString &toolTip) = 0;
+
+ virtual QString whatsThis() const = 0;
+ virtual void setWhatsThis(const QString &whatsThis) = 0;
+
+ virtual QString includeFile() const = 0;
+ virtual void setIncludeFile(const QString &includeFile) = 0;
+
+ virtual QIcon icon() const = 0;
+ virtual void setIcon(const QIcon &icon) = 0;
+
+ virtual bool isCompat() const = 0;
+ virtual void setCompat(bool compat) = 0;
+
+ virtual bool isContainer() const = 0;
+ virtual void setContainer(bool container) = 0;
+
+ virtual bool isCustom() const = 0;
+ virtual void setCustom(bool custom) = 0;
+
+ virtual QString pluginPath() const = 0;
+ virtual void setPluginPath(const QString &path) = 0;
+
+ virtual bool isPromoted() const = 0;
+ virtual void setPromoted(bool b) = 0;
+
+ virtual QString extends() const = 0;
+ virtual void setExtends(const QString &s) = 0;
+
+ virtual void setDefaultPropertyValues(const QList<QVariant> &list) = 0;
+ virtual QList<QVariant> defaultPropertyValues() const = 0;
+};
+
+class QDESIGNER_SDK_EXPORT QDesignerWidgetDataBaseInterface: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerWidgetDataBaseInterface(QObject *parent = 0);
+ virtual ~QDesignerWidgetDataBaseInterface();
+
+ virtual int count() const;
+ virtual QDesignerWidgetDataBaseItemInterface *item(int index) const;
+
+ virtual int indexOf(QDesignerWidgetDataBaseItemInterface *item) const;
+ virtual void insert(int index, QDesignerWidgetDataBaseItemInterface *item);
+ virtual void append(QDesignerWidgetDataBaseItemInterface *item);
+
+ virtual int indexOfObject(QObject *object, bool resolveName = true) const;
+ virtual int indexOfClassName(const QString &className, bool resolveName = true) const;
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ bool isContainer(QObject *object, bool resolveName = true) const;
+ bool isCustom(QObject *object, bool resolveName = true) const;
+
+Q_SIGNALS:
+ void changed();
+
+protected:
+ QList<QDesignerWidgetDataBaseItemInterface *> m_items;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTWIDGETDATABASE_H
diff --git a/tools/designer/src/lib/sdk/abstractwidgetfactory.cpp b/tools/designer/src/lib/sdk/abstractwidgetfactory.cpp
new file mode 100644
index 0000000000..88d310e660
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractwidgetfactory.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDesigner/abstractwidgetfactory.h>
+#include "abstractformeditor.h"
+#include "abstractwidgetdatabase.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerWidgetFactoryInterface
+ \brief The QDesignerWidgetFactoryInterface class provides an interface that is used to control
+ the widget factory used by Qt Designer.
+ \inmodule QtDesigner
+ \internal
+*/
+
+/*!
+ \fn QDesignerWidgetFactoryInterface::QDesignerWidgetFactoryInterface(QObject *parent)
+
+ Constructs an interface to a widget factory with the given \a parent.
+*/
+QDesignerWidgetFactoryInterface::QDesignerWidgetFactoryInterface(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ \fn virtual QDesignerWidgetFactoryInterface::~QDesignerWidgetFactoryInterface()
+*/
+QDesignerWidgetFactoryInterface::~QDesignerWidgetFactoryInterface()
+{
+}
+
+/*!
+ \fn virtual QDesignerFormEditorInterface *QDesignerWidgetFactoryInterface::core() const = 0
+
+ Returns the core form editor interface associated with this interface.
+*/
+
+/*!
+ \fn virtual QWidget* QDesignerWidgetFactoryInterface::containerOfWidget(QWidget *child) const = 0
+
+ Returns the widget that contains the specified \a child widget.
+*/
+
+/*!
+ \fn virtual QWidget* QDesignerWidgetFactoryInterface::widgetOfContainer(QWidget *container) const = 0
+
+
+*/
+
+/*!
+ \fn virtual QWidget *QDesignerWidgetFactoryInterface::createWidget(const QString &name, QWidget *parent) const = 0
+
+ Returns a new widget with the given \a name and \a parent widget. If no parent is specified,
+ the widget created will be a top-level widget.
+*/
+
+/*!
+ \fn virtual QLayout *QDesignerWidgetFactoryInterface::createLayout(QWidget *widget, QLayout *layout, int type) const = 0
+
+ Returns a new layout of the specified \a type for the given \a widget or \a layout.
+*/
+
+/*!
+ \fn virtual bool QDesignerWidgetFactoryInterface::isPassiveInteractor(QWidget *widget) = 0
+*/
+
+/*!
+ \fn virtual void QDesignerWidgetFactoryInterface::initialize(QObject *object) const = 0
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/abstractwidgetfactory.h b/tools/designer/src/lib/sdk/abstractwidgetfactory.h
new file mode 100644
index 0000000000..e2d4cde764
--- /dev/null
+++ b/tools/designer/src/lib/sdk/abstractwidgetfactory.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTWIDGETFACTORY_H
+#define ABSTRACTWIDGETFACTORY_H
+
+#include <QtDesigner/sdk_global.h>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QWidget;
+class QLayout;
+
+class QDESIGNER_SDK_EXPORT QDesignerWidgetFactoryInterface: public QObject
+{
+ Q_OBJECT
+public:
+ QDesignerWidgetFactoryInterface(QObject *parent = 0);
+ virtual ~QDesignerWidgetFactoryInterface();
+
+ virtual QDesignerFormEditorInterface *core() const = 0;
+
+ virtual QWidget* containerOfWidget(QWidget *w) const = 0;
+ virtual QWidget* widgetOfContainer(QWidget *w) const = 0;
+
+ virtual QWidget *createWidget(const QString &name, QWidget *parentWidget = 0) const = 0;
+ virtual QLayout *createLayout(QWidget *widget, QLayout *layout, int type) const = 0;
+
+ virtual bool isPassiveInteractor(QWidget *widget) = 0;
+ virtual void initialize(QObject *object) const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTWIDGETFACTORY_H
diff --git a/tools/designer/src/lib/sdk/dynamicpropertysheet.h b/tools/designer/src/lib/sdk/dynamicpropertysheet.h
new file mode 100644
index 0000000000..fa5eb4b5e5
--- /dev/null
+++ b/tools/designer/src/lib/sdk/dynamicpropertysheet.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef DYNAMICPROPERTYSHEET_H
+#define DYNAMICPROPERTYSHEET_H
+
+#include <QtDesigner/extension.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QString; // FIXME: fool syncqt
+
+class QDesignerDynamicPropertySheetExtension
+{
+public:
+ virtual ~QDesignerDynamicPropertySheetExtension() {}
+
+ virtual bool dynamicPropertiesAllowed() const = 0;
+ virtual int addDynamicProperty(const QString &propertyName, const QVariant &value) = 0;
+ virtual bool removeDynamicProperty(int index) = 0;
+ virtual bool isDynamicProperty(int index) const = 0;
+ virtual bool canAddDynamicProperty(const QString &propertyName) const = 0;
+};
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerDynamicPropertySheetExtension, "com.trolltech.Qt.Designer.DynamicPropertySheet")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // DYNAMICPROPERTYSHEET_H
diff --git a/tools/designer/src/lib/sdk/extrainfo.cpp b/tools/designer/src/lib/sdk/extrainfo.cpp
new file mode 100644
index 0000000000..ab57685274
--- /dev/null
+++ b/tools/designer/src/lib/sdk/extrainfo.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "extrainfo.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerExtraInfoExtension
+ \brief The QDesignerExtraInfoExtension class provides extra information about a widget in
+ Qt Designer.
+ \inmodule QtDesigner
+ \internal
+*/
+
+/*!
+ Returns the path to the working directory used by this extension.*/
+QString QDesignerExtraInfoExtension::workingDirectory() const
+{
+ return m_workingDirectory;
+}
+
+/*!
+ Sets the path to the working directory used by the extension to \a workingDirectory.*/
+void QDesignerExtraInfoExtension::setWorkingDirectory(const QString &workingDirectory)
+{
+ m_workingDirectory = workingDirectory;
+}
+
+/*!
+ \fn virtual QDesignerExtraInfoExtension::~QDesignerExtraInfoExtension()
+
+ Destroys the extension.
+*/
+
+/*!
+ \fn virtual QDesignerFormEditorInterface *QDesignerExtraInfoExtension::core() const = 0
+
+ \omit
+ ### Description required
+ \endomit
+*/
+
+/*!
+ \fn virtual QWidget *QDesignerExtraInfoExtension::widget() const = 0
+
+ Returns the widget described by this extension.
+*/
+
+/*!
+ \fn virtual bool QDesignerExtraInfoExtension::saveUiExtraInfo(DomUI *ui) = 0
+
+ Saves the information about the user interface specified by \a ui, and returns true if
+ successful; otherwise returns false.
+*/
+
+/*!
+ \fn virtual bool QDesignerExtraInfoExtension::loadUiExtraInfo(DomUI *ui) = 0
+
+ Loads extra information about the user interface specified by \a ui, and returns true if
+ successful; otherwise returns false.
+*/
+
+/*!
+ \fn virtual bool QDesignerExtraInfoExtension::saveWidgetExtraInfo(DomWidget *widget) = 0
+
+ Saves the information about the specified \a widget, and returns true if successful;
+ otherwise returns false.
+*/
+
+/*!
+ \fn virtual bool QDesignerExtraInfoExtension::loadWidgetExtraInfo(DomWidget *widget) = 0
+
+ Loads extra information about the specified \a widget, and returns true if successful;
+ otherwise returns false.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/extrainfo.h b/tools/designer/src/lib/sdk/extrainfo.h
new file mode 100644
index 0000000000..910dedb7a2
--- /dev/null
+++ b/tools/designer/src/lib/sdk/extrainfo.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef EXTRAINFO_H
+#define EXTRAINFO_H
+
+#include <QtDesigner/sdk_global.h>
+#include <QtDesigner/extension.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class DomWidget;
+class DomUI;
+class QWidget;
+
+class QDesignerFormEditorInterface;
+
+class QDESIGNER_SDK_EXPORT QDesignerExtraInfoExtension
+{
+public:
+ virtual ~QDesignerExtraInfoExtension() {}
+
+ virtual QDesignerFormEditorInterface *core() const = 0;
+ virtual QWidget *widget() const = 0;
+
+ virtual bool saveUiExtraInfo(DomUI *ui) = 0;
+ virtual bool loadUiExtraInfo(DomUI *ui) = 0;
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget) = 0;
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget) = 0;
+
+ QString workingDirectory() const;
+ void setWorkingDirectory(const QString &workingDirectory);
+
+private:
+ QString m_workingDirectory;
+};
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerExtraInfoExtension, "com.trolltech.Qt.Designer.ExtraInfo.2")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // EXTRAINFO_H
diff --git a/tools/designer/src/lib/sdk/layoutdecoration.h b/tools/designer/src/lib/sdk/layoutdecoration.h
new file mode 100644
index 0000000000..c99cae41e1
--- /dev/null
+++ b/tools/designer/src/lib/sdk/layoutdecoration.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LAYOUTDECORATION_H
+#define LAYOUTDECORATION_H
+
+#include <QtDesigner/extension.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QPoint;
+class QLayoutItem;
+class QWidget;
+class QRect;
+class QLayout;
+
+class QDesignerLayoutDecorationExtension
+{
+public:
+ enum InsertMode
+ {
+ InsertWidgetMode,
+ InsertRowMode,
+ InsertColumnMode
+ };
+
+ virtual ~QDesignerLayoutDecorationExtension() {}
+
+ virtual QList<QWidget*> widgets(QLayout *layout) const = 0;
+
+ virtual QRect itemInfo(int index) const = 0;
+ virtual int indexOf(QWidget *widget) const = 0;
+ virtual int indexOf(QLayoutItem *item) const = 0;
+
+ virtual InsertMode currentInsertMode() const = 0;
+ virtual int currentIndex() const = 0;
+ virtual QPair<int, int> currentCell() const = 0;
+ virtual void insertWidget(QWidget *widget, const QPair<int, int> &cell) = 0;
+ virtual void removeWidget(QWidget *widget) = 0;
+
+ virtual void insertRow(int row) = 0;
+ virtual void insertColumn(int column) = 0;
+ virtual void simplify() = 0;
+
+ virtual int findItemAt(const QPoint &pos) const = 0;
+ virtual int findItemAt(int row, int column) const = 0; // atm only for grid.
+
+ virtual void adjustIndicator(const QPoint &pos, int index) = 0;
+};
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerLayoutDecorationExtension, "com.trolltech.Qt.Designer.LayoutDecoration")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // LAYOUTDECORATION_H
diff --git a/tools/designer/src/lib/sdk/membersheet.h b/tools/designer/src/lib/sdk/membersheet.h
new file mode 100644
index 0000000000..14c4aba387
--- /dev/null
+++ b/tools/designer/src/lib/sdk/membersheet.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MEMBERSHEET_H
+#define MEMBERSHEET_H
+
+#include <QtDesigner/extension.h>
+
+#include <QtCore/QList>
+#include <QtCore/QByteArray>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QString; // FIXME: fool syncqt
+
+class QDesignerMemberSheetExtension
+{
+public:
+ virtual ~QDesignerMemberSheetExtension() {}
+
+ virtual int count() const = 0;
+
+ virtual int indexOf(const QString &name) const = 0;
+
+ virtual QString memberName(int index) const = 0;
+ virtual QString memberGroup(int index) const = 0;
+ virtual void setMemberGroup(int index, const QString &group) = 0;
+
+ virtual bool isVisible(int index) const = 0;
+ virtual void setVisible(int index, bool b) = 0;
+
+ virtual bool isSignal(int index) const = 0;
+ virtual bool isSlot(int index) const = 0;
+
+ virtual bool inheritedFromWidget(int index) const = 0;
+
+ virtual QString declaredInClass(int index) const = 0;
+
+ virtual QString signature(int index) const = 0;
+ virtual QList<QByteArray> parameterTypes(int index) const = 0;
+ virtual QList<QByteArray> parameterNames(int index) const = 0;
+};
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerMemberSheetExtension, "com.trolltech.Qt.Designer.MemberSheet")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // MEMBERSHEET_H
diff --git a/tools/designer/src/lib/sdk/propertysheet.h b/tools/designer/src/lib/sdk/propertysheet.h
new file mode 100644
index 0000000000..1104f9e165
--- /dev/null
+++ b/tools/designer/src/lib/sdk/propertysheet.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROPERTYSHEET_H
+#define PROPERTYSHEET_H
+
+#include <QtDesigner/extension.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QVariant;
+
+class QDesignerPropertySheetExtension
+{
+public:
+ virtual ~QDesignerPropertySheetExtension() {}
+
+ virtual int count() const = 0;
+
+ virtual int indexOf(const QString &name) const = 0;
+
+ virtual QString propertyName(int index) const = 0;
+ virtual QString propertyGroup(int index) const = 0;
+ virtual void setPropertyGroup(int index, const QString &group) = 0;
+
+ virtual bool hasReset(int index) const = 0;
+ virtual bool reset(int index) = 0;
+
+ virtual bool isVisible(int index) const = 0;
+ virtual void setVisible(int index, bool b) = 0;
+
+ virtual bool isAttribute(int index) const = 0;
+ virtual void setAttribute(int index, bool b) = 0;
+
+ virtual QVariant property(int index) const = 0;
+ virtual void setProperty(int index, const QVariant &value) = 0;
+
+ virtual bool isChanged(int index) const = 0;
+ virtual void setChanged(int index, bool changed) = 0;
+
+};
+
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerPropertySheetExtension,
+ "com.trolltech.Qt.Designer.PropertySheet")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // PROPERTYSHEET_H
diff --git a/tools/designer/src/lib/sdk/script.cpp b/tools/designer/src/lib/sdk/script.cpp
new file mode 100644
index 0000000000..cd34f2ae03
--- /dev/null
+++ b/tools/designer/src/lib/sdk/script.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "script_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDesignerScriptExtension
+ \brief The QDesignerScriptExtension class allows you to generate a
+ per-widget \l{QtScript} {Qt Script} snippet to be executed while
+ building the form.
+
+ \internal
+ \inmodule QtDesigner
+ \since 4.3
+
+ On saving the form, the extension is queried for a script snippet
+ to be associated with the widget while saving the \c .ui file.
+ This script is then run after creating the widget by \l uic or
+ QUiLoader.
+
+ As opposed to \l QDesignerCustomWidgetInterface::codeTemplate(),
+ it allows for applying an internal state of the widget
+ that can be manipulated using \QD.
+
+ Such a state might for example be the contents of a custom item view widget,
+ for which an editor is provided by the QDesignerTaskMenuExtension.
+
+ While saving the form, the state is serialized as a QVariantMap of
+ \QD-supported properties, which is stored in the \c .ui file. This is
+ handled by data() and setData().
+
+ For item view contents, there might be for example a key that determines
+ the number of items and other keys that contain the actual items following
+ a naming scheme (\c numItems, \c item1, \c item2, ...).
+
+ On saving, script() is invoked, which should return a script snippet that
+ applies the state to the widget while building the form.
+
+ \sa {Creating Custom Widgets for Qt Designer#Using Qt Script to Aid in Building Forms}{Creating Custom Widgets for Qt Designer}, QtScript
+*/
+
+/*!
+ Destroys the extension.
+*/
+
+QDesignerScriptExtension::~QDesignerScriptExtension()
+{
+}
+
+/*!
+ \fn virtual QString QDesignerScriptExtension::script() const
+
+ Returns a script snippet to be associated with the widget.
+*/
+
+/*!
+ \fn virtual QVariantMap QDesignerScriptExtension::data() const
+
+ Returns a map of variants describing the internal state to be
+ stored in the \c .ui file.
+*/
+
+/*!
+ \fn virtual void QDesignerScriptExtension::setData(const QVariantMap &data)
+
+ Applies the internal state stored in \a data to the widget while loading a form.
+*/
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/sdk/script_p.h b/tools/designer/src/lib/sdk/script_p.h
new file mode 100644
index 0000000000..a93fbfa6a4
--- /dev/null
+++ b/tools/designer/src/lib/sdk/script_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SCRIPT_H
+#define SCRIPT_H
+
+#include <QtDesigner/sdk_global.h>
+#include <QtDesigner/extension.h>
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QString; // FIXME: fool syncqt
+
+class QDESIGNER_SDK_EXPORT QDesignerScriptExtension
+{
+public:
+ virtual ~QDesignerScriptExtension();
+
+ virtual QVariantMap data() const = 0;
+ virtual void setData(const QVariantMap &data) = 0;
+
+ virtual QString script() const = 0;
+
+};
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerScriptExtension, "com.trolltech.Qt.Designer.Script")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SCRIPT_H
diff --git a/tools/designer/src/lib/sdk/sdk.pri b/tools/designer/src/lib/sdk/sdk.pri
new file mode 100644
index 0000000000..bc46a1edbc
--- /dev/null
+++ b/tools/designer/src/lib/sdk/sdk.pri
@@ -0,0 +1,58 @@
+# Input
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/abstractformeditor.h \
+ $$PWD/abstractintrospection_p.h \
+ $$PWD/abstractsettings_p.h \
+ $$PWD/abstractformeditorplugin.h \
+ $$PWD/abstractresourcebrowser.h \
+ $$PWD/abstractintegration.h \
+ $$PWD/abstractpropertyeditor.h \
+ $$PWD/abstractformwindow.h \
+ $$PWD/abstractformwindowtool.h \
+ $$PWD/abstractformwindowcursor.h \
+ $$PWD/abstractformwindowmanager.h \
+ $$PWD/abstractwidgetdatabase.h \
+ $$PWD/abstractmetadatabase.h \
+ $$PWD/abstractwidgetfactory.h \
+ $$PWD/abstractobjectinspector.h \
+ $$PWD/abstractactioneditor.h \
+ $$PWD/abstractbrushmanager.h \
+ $$PWD/abstracticoncache.h \
+ $$PWD/abstractlanguage.h \
+ $$PWD/abstractoptionspage_p.h \
+ $$PWD/propertysheet.h \
+ $$PWD/dynamicpropertysheet.h \
+ $$PWD/membersheet.h \
+ $$PWD/taskmenu.h \
+ $$PWD/extrainfo.h \
+ $$PWD/abstractwidgetbox.h \
+ $$PWD/layoutdecoration.h \
+ $$PWD/abstractdnditem.h \
+ $$PWD/abstractpromotioninterface.h \
+ $$PWD/abstractdialoggui_p.h \
+ $$PWD/script_p.h \
+ $$PWD/abstractnewformwidget_p.h
+
+SOURCES += $$PWD/abstractformeditor.cpp \
+ $$PWD/abstractintrospection.cpp \
+ $$PWD/abstractformeditorplugin.cpp \
+ $$PWD/abstractresourcebrowser.cpp \
+ $$PWD/abstractintegration.cpp \
+ $$PWD/abstractpropertyeditor.cpp \
+ $$PWD/abstractformwindow.cpp \
+ $$PWD/abstractformwindowtool.cpp \
+ $$PWD/abstractformwindowcursor.cpp \
+ $$PWD/abstractformwindowmanager.cpp \
+ $$PWD/abstractwidgetdatabase.cpp \
+ $$PWD/abstractmetadatabase.cpp \
+ $$PWD/abstractwidgetfactory.cpp \
+ $$PWD/abstractobjectinspector.cpp \
+ $$PWD/abstractactioneditor.cpp \
+ $$PWD/abstractwidgetbox.cpp \
+ $$PWD/extrainfo.cpp \
+ $$PWD/abstractpromotioninterface.cpp \
+ $$PWD/abstractdialoggui.cpp \
+ $$PWD/script.cpp \
+ $$PWD/abstractnewformwidget.cpp
diff --git a/tools/designer/src/lib/sdk/sdk_global.h b/tools/designer/src/lib/sdk/sdk_global.h
new file mode 100644
index 0000000000..679870a766
--- /dev/null
+++ b/tools/designer/src/lib/sdk/sdk_global.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SDK_GLOBAL_H
+#define SDK_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#define QDESIGNER_SDK_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_SDK_IMPORT Q_DECL_IMPORT
+
+#ifdef QT_DESIGNER_STATIC
+# define QDESIGNER_SDK_EXPORT
+#elif defined(QDESIGNER_SDK_LIBRARY)
+# define QDESIGNER_SDK_EXPORT QDESIGNER_SDK_EXTERN
+#else
+# define QDESIGNER_SDK_EXPORT QDESIGNER_SDK_IMPORT
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // SDK_GLOBAL_H
diff --git a/tools/designer/src/lib/sdk/taskmenu.h b/tools/designer/src/lib/sdk/taskmenu.h
new file mode 100644
index 0000000000..930fef6444
--- /dev/null
+++ b/tools/designer/src/lib/sdk/taskmenu.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TASKMENU_H
+#define TASKMENU_H
+
+#include <QtDesigner/extension.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+
+class QDesignerTaskMenuExtension
+{
+public:
+ virtual ~QDesignerTaskMenuExtension() {}
+
+ virtual QAction *preferredEditAction() const;
+
+ virtual QList<QAction*> taskActions() const = 0;
+};
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerTaskMenuExtension, "com.trolltech.Qt.Designer.TaskMenu")
+
+
+inline QAction *QDesignerTaskMenuExtension::preferredEditAction() const
+{ return 0; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // TASKMENU_H
diff --git a/tools/designer/src/lib/shared/actioneditor.cpp b/tools/designer/src/lib/shared/actioneditor.cpp
new file mode 100644
index 0000000000..6a664423e0
--- /dev/null
+++ b/tools/designer/src/lib/shared/actioneditor.cpp
@@ -0,0 +1,822 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ActionEditor
+*/
+
+#include "actioneditor_p.h"
+#include "filterwidget_p.h"
+#include "actionrepository_p.h"
+#include "iconloader_p.h"
+#include "newactiondialog_p.h"
+#include "qdesigner_menu_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "qdesigner_objectinspector_p.h"
+#include "qdesigner_utils_p.h"
+#include "qsimpleresource_p.h"
+#include "formwindowbase_p.h"
+#include "qdesigner_taskmenu_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/private/abstractsettings_p.h>
+
+#include <QtGui/QMenu>
+#include <QtGui/QToolBar>
+#include <QtGui/QSplitter>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QClipboard>
+#include <QtGui/QItemDelegate>
+#include <QtGui/QPainter>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QLineEdit>
+#include <QtGui/QLabel>
+#include <QtGui/QPushButton>
+#include <QtGui/QToolButton>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QItemSelection>
+
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+#include <QtCore/QSignalMapper>
+#include <QtCore/QBuffer>
+
+Q_DECLARE_METATYPE(QAction*)
+
+QT_BEGIN_NAMESPACE
+
+static const char *actionEditorViewModeKey = "ActionEditorViewMode";
+
+static const char *iconPropertyC = "icon";
+static const char *shortcutPropertyC = "shortcut";
+static const char *toolTipPropertyC = "toolTip";
+static const char *checkablePropertyC = "checkable";
+static const char *objectNamePropertyC = "objectName";
+static const char *textPropertyC = "text";
+
+namespace qdesigner_internal {
+//-------- ActionGroupDelegate
+class ActionGroupDelegate: public QItemDelegate
+{
+public:
+ ActionGroupDelegate(QObject *parent)
+ : QItemDelegate(parent) {}
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+ {
+ if (option.state & QStyle::State_Selected)
+ painter->fillRect(option.rect, option.palette.highlight());
+
+ QItemDelegate::paint(painter, option, index);
+ }
+
+ virtual void drawFocus(QPainter * /*painter*/, const QStyleOptionViewItem &/*option*/, const QRect &/*rect*/) const {}
+};
+
+//-------- ActionEditor
+ActionEditor::ActionEditor(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags) :
+ QDesignerActionEditorInterface(parent, flags),
+ m_core(core),
+ m_actionGroups(0),
+ m_actionView(new ActionView),
+ m_actionNew(new QAction(tr("New..."), this)),
+ m_actionEdit(new QAction(tr("Edit..."), this)),
+ m_actionNavigateToSlot(new QAction(tr("Go to slot..."), this)),
+ m_actionCopy(new QAction(tr("Copy"), this)),
+ m_actionCut(new QAction(tr("Cut"), this)),
+ m_actionPaste(new QAction(tr("Paste"), this)),
+ m_actionSelectAll(new QAction(tr("Select all"), this)),
+ m_actionDelete(new QAction(tr("Delete"), this)),
+ m_viewModeGroup(new QActionGroup(this)),
+ m_iconViewAction(0),
+ m_listViewAction(0),
+ m_filterWidget(0),
+ m_selectAssociatedWidgetsMapper(0)
+{
+ m_actionView->initialize(m_core);
+ m_actionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ setWindowTitle(tr("Actions"));
+
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->setMargin(0);
+ l->setSpacing(0);
+
+ QToolBar *toolbar = new QToolBar;
+ toolbar->setIconSize(QSize(22, 22));
+ toolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+ l->addWidget(toolbar);
+ // edit actions
+ m_actionNew->setIcon(createIconSet(QLatin1String("filenew.png")));
+ m_actionNew->setEnabled(false);
+ connect(m_actionNew, SIGNAL(triggered()), this, SLOT(slotNewAction()));
+ toolbar->addAction(m_actionNew);
+
+ connect(m_actionSelectAll, SIGNAL(triggered()), m_actionView, SLOT(selectAll()));
+
+ m_actionCut->setEnabled(false);
+ connect(m_actionCut, SIGNAL(triggered()), this, SLOT(slotCut()));
+ m_actionCut->setIcon(createIconSet(QLatin1String("editcut.png")));
+
+ m_actionCopy->setEnabled(false);
+ connect(m_actionCopy, SIGNAL(triggered()), this, SLOT(slotCopy()));
+ m_actionCopy->setIcon(createIconSet(QLatin1String("editcopy.png")));
+ toolbar->addAction(m_actionCopy);
+
+ connect(m_actionPaste, SIGNAL(triggered()), this, SLOT(slotPaste()));
+ m_actionPaste->setIcon(createIconSet(QLatin1String("editpaste.png")));
+ toolbar->addAction(m_actionPaste);
+
+ m_actionEdit->setEnabled(false);
+ connect(m_actionEdit, SIGNAL(triggered()), this, SLOT(editCurrentAction()));
+
+ connect(m_actionNavigateToSlot, SIGNAL(triggered()), this, SLOT(navigateToSlotCurrentAction()));
+
+ m_actionDelete->setIcon(createIconSet(QLatin1String("editdelete.png")));
+ m_actionDelete->setEnabled(false);
+ connect(m_actionDelete, SIGNAL(triggered()), this, SLOT(slotDelete()));
+ toolbar->addAction(m_actionDelete);
+
+ // Toolbutton with menu containing action group for detailed/icon view. Steal the icons from the file dialog.
+ //
+ QMenu *configureMenu;
+ toolbar->addWidget(createConfigureMenuButton(tr("Configure Action Editor"), &configureMenu));
+
+ connect(m_viewModeGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotViewMode(QAction*)));
+ m_iconViewAction = m_viewModeGroup->addAction(tr("Icon View"));
+ m_iconViewAction->setData(QVariant(ActionView::IconView));
+ m_iconViewAction->setCheckable(true);
+ m_iconViewAction->setIcon(style()->standardIcon (QStyle::SP_FileDialogListView));
+ configureMenu->addAction(m_iconViewAction);
+
+ m_listViewAction = m_viewModeGroup->addAction(tr("Detailed View"));
+ m_listViewAction->setData(QVariant(ActionView::DetailedView));
+ m_listViewAction->setCheckable(true);
+ m_listViewAction->setIcon(style()->standardIcon (QStyle::SP_FileDialogDetailedView));
+ configureMenu->addAction(m_listViewAction);
+ // filter
+ m_filterWidget = new FilterWidget(toolbar);
+ connect(m_filterWidget, SIGNAL(filterChanged(QString)), this, SLOT(setFilter(QString)));
+ m_filterWidget->setEnabled(false);
+ toolbar->addWidget(m_filterWidget);
+
+ // main layout
+ QSplitter *splitter = new QSplitter(Qt::Horizontal);
+ splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ splitter->addWidget(m_actionView);
+ l->addWidget(splitter);
+
+#if 0 // ### implement me
+ m_actionGroups = new QListWidget(splitter);
+ splitter->addWidget(m_actionGroups);
+ m_actionGroups->setItemDelegate(new ActionGroupDelegate(m_actionGroups));
+ m_actionGroups->setMovement(QListWidget::Static);
+ m_actionGroups->setResizeMode(QListWidget::Fixed);
+ m_actionGroups->setIconSize(QSize(48, 48));
+ m_actionGroups->setFlow(QListWidget::TopToBottom);
+ m_actionGroups->setViewMode(QListWidget::IconMode);
+ m_actionGroups->setWrapping(false);
+#endif
+
+ connect(m_actionView, SIGNAL(resourceImageDropped(QString,QAction*)),
+ this, SLOT(resourceImageDropped(QString,QAction*)));
+
+ connect(m_actionView, SIGNAL(currentChanged(QAction*)),this, SLOT(slotCurrentItemChanged(QAction*)));
+ // make it possible for vs integration to reimplement edit action dialog
+ connect(m_actionView, SIGNAL(activated(QAction*)), this, SIGNAL(itemActivated(QAction*)));
+
+ connect(m_actionView,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)));
+
+ connect(m_actionView, SIGNAL(contextMenuRequested(QContextMenuEvent*, QAction*)),
+ this, SLOT(slotContextMenuRequested(QContextMenuEvent*, QAction*)));
+
+ connect(this, SIGNAL(itemActivated(QAction*)), this, SLOT(editAction(QAction*)));
+
+ restoreSettings();
+ updateViewModeActions();
+}
+
+// Utility to create a configure button with menu for usage on toolbars
+QToolButton *ActionEditor::createConfigureMenuButton(const QString &t, QMenu **ptrToMenu)
+{
+ QToolButton *configureButton = new QToolButton;
+ QAction *configureAction = new QAction(t, configureButton);
+ configureAction->setIcon(createIconSet(QLatin1String("configure.png")));
+ QMenu *configureMenu = new QMenu;
+ configureAction->setMenu(configureMenu);
+ configureButton->setDefaultAction(configureAction);
+ configureButton->setPopupMode(QToolButton::InstantPopup);
+ *ptrToMenu = configureMenu;
+ return configureButton;
+}
+
+ActionEditor::~ActionEditor()
+{
+ saveSettings();
+}
+
+QAction *ActionEditor::actionNew() const
+{
+ return m_actionNew;
+}
+
+QAction *ActionEditor::actionDelete() const
+{
+ return m_actionDelete;
+}
+
+QDesignerFormWindowInterface *ActionEditor::formWindow() const
+{
+ return m_formWindow;
+}
+
+void ActionEditor::setFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ if (formWindow != 0 && formWindow->mainContainer() == 0)
+ formWindow = 0;
+
+ // we do NOT rely on this function to update the action editor
+ if (m_formWindow == formWindow)
+ return;
+
+ if (m_formWindow != 0) {
+ const ActionList actionList = qFindChildren<QAction*>(m_formWindow->mainContainer());
+ foreach (QAction *action, actionList)
+ disconnect(action, SIGNAL(changed()), this, SLOT(slotActionChanged()));
+ }
+
+ m_formWindow = formWindow;
+
+ m_actionView->model()->clearActions();
+
+ m_actionEdit->setEnabled(false);
+ m_actionCopy->setEnabled(false);
+ m_actionCut->setEnabled(false);
+ m_actionDelete->setEnabled(false);
+
+ if (!formWindow || !formWindow->mainContainer()) {
+ m_actionNew->setEnabled(false);
+ m_filterWidget->setEnabled(false);
+ return;
+ }
+
+ m_actionNew->setEnabled(true);
+ m_filterWidget->setEnabled(true);
+
+ const ActionList actionList = qFindChildren<QAction*>(formWindow->mainContainer());
+ foreach (QAction *action, actionList)
+ if (!action->isSeparator() && core()->metaDataBase()->item(action) != 0) {
+ // Show unless it has a menu. However, listen for change on menu actions also as it might be removed
+ if (!action->menu())
+ m_actionView->model()->addAction(action);
+ connect(action, SIGNAL(changed()), this, SLOT(slotActionChanged()));
+ }
+
+ setFilter(m_filter);
+}
+
+void ActionEditor::slotSelectionChanged(const QItemSelection& selected, const QItemSelection& /*deselected*/)
+{
+ const bool hasSelection = !selected.indexes().empty();
+ m_actionCopy->setEnabled(hasSelection);
+ m_actionCut->setEnabled(hasSelection);
+ m_actionDelete->setEnabled(hasSelection);
+}
+
+void ActionEditor::slotCurrentItemChanged(QAction *action)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+
+ const bool hasCurrentAction = action != 0;
+ m_actionEdit->setEnabled(hasCurrentAction);
+
+ if (!action) {
+ fw->clearSelection();
+ return;
+ }
+
+ QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(core()->objectInspector());
+
+ if (action->associatedWidgets().empty()) {
+ // Special case: action not in object tree. Deselect all and set in property editor
+ fw->clearSelection(false);
+ if (oi)
+ oi->clearSelection();
+ core()->propertyEditor()->setObject(action);
+ } else {
+ if (oi)
+ oi->selectObject(action);
+ }
+}
+
+void ActionEditor::slotActionChanged()
+{
+ QAction *action = qobject_cast<QAction*>(sender());
+ Q_ASSERT(action != 0);
+
+ ActionModel *model = m_actionView->model();
+ const int row = model->findAction(action);
+ if (row == -1) {
+ if (action->menu() == 0) // action got its menu deleted, create item
+ model->addAction(action);
+ } else if (action->menu() != 0) { // action got its menu created, remove item
+ model->removeRow(row);
+ } else {
+ // action text or icon changed, update item
+ model->update(row);
+ }
+}
+
+QDesignerFormEditorInterface *ActionEditor::core() const
+{
+ return m_core;
+}
+
+QString ActionEditor::filter() const
+{
+ return m_filter;
+}
+
+void ActionEditor::setFilter(const QString &f)
+{
+ m_filter = f;
+ m_actionView->filter(m_filter);
+}
+
+// Set changed state of icon property, reset when icon is cleared
+static void refreshIconPropertyChanged(const QAction *action, QDesignerPropertySheetExtension *sheet)
+{
+ sheet->setChanged(sheet->indexOf(QLatin1String(iconPropertyC)), !action->icon().isNull());
+}
+
+void ActionEditor::manageAction(QAction *action)
+{
+ action->setParent(formWindow()->mainContainer());
+ core()->metaDataBase()->add(action);
+
+ if (action->isSeparator() || action->menu() != 0)
+ return;
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), action);
+ sheet->setChanged(sheet->indexOf(QLatin1String(objectNamePropertyC)), true);
+ sheet->setChanged(sheet->indexOf(QLatin1String(textPropertyC)), true);
+ refreshIconPropertyChanged(action, sheet);
+
+ m_actionView->setCurrentIndex(m_actionView->model()->addAction(action));
+ connect(action, SIGNAL(changed()), this, SLOT(slotActionChanged()));
+}
+
+void ActionEditor::unmanageAction(QAction *action)
+{
+ core()->metaDataBase()->remove(action);
+ action->setParent(0);
+
+ disconnect(action, SIGNAL(changed()), this, SLOT(slotActionChanged()));
+
+ const int row = m_actionView->model()->findAction(action);
+ if (row != -1)
+ m_actionView->model()->remove(row);
+}
+
+// Set an intial property and mark it as changed in the sheet
+static void setInitialProperty(QDesignerPropertySheetExtension *sheet, const QString &name, const QVariant &value)
+{
+ const int index = sheet->indexOf(name);
+ Q_ASSERT(index != -1);
+ sheet->setProperty(index, value);
+ sheet->setChanged(index, true);
+}
+
+void ActionEditor::slotNewAction()
+{
+ NewActionDialog dlg(this);
+ dlg.setWindowTitle(tr("New action"));
+
+ if (dlg.exec() == QDialog::Accepted) {
+ const ActionData actionData = dlg.actionData();
+ m_actionView->clearSelection();
+
+ QAction *action = new QAction(formWindow());
+ action->setObjectName(actionData.name);
+ formWindow()->ensureUniqueObjectName(action);
+ action->setText(actionData.text);
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), action);
+ if (!actionData.toolTip.isEmpty())
+ setInitialProperty(sheet, QLatin1String(toolTipPropertyC), actionData.toolTip);
+
+ if (actionData.checkable)
+ setInitialProperty(sheet, QLatin1String(checkablePropertyC), QVariant(true));
+
+ if (!actionData.keysequence.isEmpty())
+ setInitialProperty(sheet, QLatin1String(shortcutPropertyC), qVariantFromValue(actionData.keysequence));
+
+ sheet->setProperty(sheet->indexOf(QLatin1String(iconPropertyC)), qVariantFromValue(actionData.icon));
+
+ AddActionCommand *cmd = new AddActionCommand(formWindow());
+ cmd->init(action);
+ formWindow()->commandHistory()->push(cmd);
+ }
+}
+
+static inline bool isSameIcon(const QIcon &i1, const QIcon &i2)
+{
+ return i1.serialNumber() == i2.serialNumber();
+}
+
+// return a FormWindow command to apply an icon or a reset command in case it
+// is empty.
+
+static QDesignerFormWindowCommand *setIconPropertyCommand(const PropertySheetIconValue &newIcon, QAction *action, QDesignerFormWindowInterface *fw)
+{
+ const QString iconProperty = QLatin1String(iconPropertyC);
+ if (newIcon.paths().isEmpty()) {
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
+ cmd->init(action, iconProperty);
+ return cmd;
+ }
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(action, iconProperty, qVariantFromValue(newIcon));
+ return cmd;
+}
+
+// return a FormWindow command to apply a QKeySequence or a reset command
+// in case it is empty.
+
+static QDesignerFormWindowCommand *setKeySequencePropertyCommand(const QKeySequence &ks, QAction *action, QDesignerFormWindowInterface *fw)
+{
+ const QString shortcutProperty = QLatin1String(shortcutPropertyC);
+ if (ks.isEmpty()) {
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
+ cmd->init(action, shortcutProperty);
+ return cmd;
+ }
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(action, shortcutProperty, qVariantFromValue(ks));
+ return cmd;
+}
+
+// return a FormWindow command to apply a POD value or reset command in case
+// it is equal to the default value.
+
+template <class T>
+QDesignerFormWindowCommand *setPropertyCommand(const QString &name, T value, T defaultValue,
+ QObject *o, QDesignerFormWindowInterface *fw)
+{
+ if (value == defaultValue) {
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
+ cmd->init(o, name);
+ return cmd;
+ }
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(o, name, QVariant(value));
+ return cmd;
+}
+
+// Return the text value of a string property via PropertySheetStringValue
+static inline QString textPropertyValue(const QDesignerPropertySheetExtension *sheet, const QString &name)
+{
+ const int index = sheet->indexOf(name);
+ Q_ASSERT(index != -1);
+ const PropertySheetStringValue ps = qVariantValue<PropertySheetStringValue>(sheet->property(index));
+ return ps.value();
+}
+
+void ActionEditor::editAction(QAction *action)
+{
+ if (!action)
+ return;
+
+ NewActionDialog dlg(this);
+ dlg.setWindowTitle(tr("Edit action"));
+
+ ActionData oldActionData;
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), action);
+ oldActionData.name = action->objectName();
+ oldActionData.text = action->text();
+ oldActionData.toolTip = textPropertyValue(sheet, QLatin1String(toolTipPropertyC));
+ oldActionData.icon = qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC))));
+ oldActionData.keysequence = qVariantValue<QKeySequence>(sheet->property(sheet->indexOf(QLatin1String(shortcutPropertyC))));
+ oldActionData.checkable = action->isCheckable();
+ dlg.setActionData(oldActionData);
+
+ if (!dlg.exec())
+ return;
+
+ // figure out changes and whether to start a macro
+ const ActionData newActionData = dlg.actionData();
+ const unsigned changeMask = newActionData.compare(oldActionData);
+ if (changeMask == 0u)
+ return;
+
+ const bool severalChanges = (changeMask != ActionData::TextChanged) && (changeMask != ActionData::NameChanged)
+ && (changeMask != ActionData::ToolTipChanged) && (changeMask != ActionData::IconChanged)
+ && (changeMask != ActionData::CheckableChanged) && (changeMask != ActionData::KeysequenceChanged);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ QUndoStack *undoStack = fw->commandHistory();
+ if (severalChanges)
+ fw->beginCommand(QLatin1String("Edit action"));
+
+ if (changeMask & ActionData::NameChanged)
+ undoStack->push(createTextPropertyCommand(QLatin1String(objectNamePropertyC), newActionData.name, action, fw));
+
+ if (changeMask & ActionData::TextChanged)
+ undoStack->push(createTextPropertyCommand(QLatin1String(textPropertyC), newActionData.text, action, fw));
+
+ if (changeMask & ActionData::ToolTipChanged)
+ undoStack->push(createTextPropertyCommand(QLatin1String(toolTipPropertyC), newActionData.toolTip, action, fw));
+
+ if (changeMask & ActionData::IconChanged)
+ undoStack->push(setIconPropertyCommand(newActionData.icon, action, fw));
+
+ if (changeMask & ActionData::CheckableChanged)
+ undoStack->push(setPropertyCommand(QLatin1String(checkablePropertyC), newActionData.checkable, false, action, fw));
+
+ if (changeMask & ActionData::KeysequenceChanged)
+ undoStack->push(setKeySequencePropertyCommand(newActionData.keysequence, action, fw));
+
+ if (severalChanges)
+ fw->endCommand();
+}
+
+void ActionEditor::editCurrentAction()
+{
+ if (QAction *a = m_actionView->currentAction())
+ editAction(a);
+}
+
+void ActionEditor::navigateToSlotCurrentAction()
+{
+ if (QAction *a = m_actionView->currentAction())
+ QDesignerTaskMenu::navigateToSlot(m_core, a, QLatin1String("triggered()"));
+}
+
+void ActionEditor::deleteActions(QDesignerFormWindowInterface *fw, const ActionList &actions)
+{
+ // We need a macro even in the case of single action because the commands might cause the
+ // scheduling of other commands (signal slots connections)
+ const QString description = actions.size() == 1 ?
+ tr("Remove action '%1'").arg(actions.front()->objectName()) : tr("Remove actions");
+ fw->beginCommand(description);
+ foreach(QAction *action, actions) {
+ RemoveActionCommand *cmd = new RemoveActionCommand(fw);
+ cmd->init(action);
+ fw->commandHistory()->push(cmd);
+ }
+ fw->endCommand();
+}
+
+void ActionEditor::copyActions(QDesignerFormWindowInterface *fwi, const ActionList &actions)
+{
+ FormWindowBase *fw = qobject_cast<FormWindowBase *>(fwi);
+ if (!fw )
+ return;
+
+ FormBuilderClipboard clipboard;
+ clipboard.m_actions = actions;
+
+ if (clipboard.empty())
+ return;
+
+ QEditorFormBuilder *formBuilder = fw->createFormBuilder();
+ Q_ASSERT(formBuilder);
+
+ QBuffer buffer;
+ if (buffer.open(QIODevice::WriteOnly))
+ if (formBuilder->copy(&buffer, clipboard))
+ qApp->clipboard()->setText(QString::fromUtf8(buffer.buffer()), QClipboard::Clipboard);
+ delete formBuilder;
+}
+
+void ActionEditor::slotDelete()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+
+ const ActionView::ActionList selection = m_actionView->selectedActions();
+ if (selection.empty())
+ return;
+
+ deleteActions(fw, selection);
+}
+
+QString ActionEditor::actionTextToName(const QString &text, const QString &prefix)
+{
+ QString name = text;
+ if (name.isEmpty())
+ return QString();
+
+ name[0] = name.at(0).toUpper();
+ name.prepend(prefix);
+ const QString underscore = QString(QLatin1Char('_'));
+ name.replace(QRegExp(QString(QLatin1String("[^a-zA-Z_0-9]"))), underscore);
+ name.replace(QRegExp(QLatin1String("__*")), underscore);
+ if (name.endsWith(underscore.at(0)))
+ name.truncate(name.size() - 1);
+
+ return name;
+}
+
+void ActionEditor::resourceImageDropped(const QString &path, QAction *action)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), action);
+ const PropertySheetIconValue oldIcon =
+ qVariantValue<PropertySheetIconValue>(sheet->property(sheet->indexOf(QLatin1String(iconPropertyC))));
+ PropertySheetIconValue newIcon;
+ newIcon.setPixmap(QIcon::Normal, QIcon::Off, PropertySheetPixmapValue(path));
+ if (newIcon.paths().isEmpty() || newIcon.paths() == oldIcon.paths())
+ return;
+
+ fw->commandHistory()->push(setIconPropertyCommand(newIcon , action, fw));
+}
+
+void ActionEditor::mainContainerChanged()
+{
+ // Invalidate references to objects kept in model
+ if (sender() == formWindow())
+ setFormWindow(0);
+}
+
+void ActionEditor::slotViewMode(QAction *a)
+{
+ m_actionView->setViewMode(a->data().toInt());
+ updateViewModeActions();
+}
+
+void ActionEditor::slotSelectAssociatedWidget(QWidget *w)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw )
+ return;
+
+ QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(core()->objectInspector());
+ if (!oi)
+ return;
+
+ fw->clearSelection(); // Actually, there are no widgets selected due to focus in event handling. Just to be sure.
+ oi->selectObject(w);
+}
+
+void ActionEditor::restoreSettings()
+{
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ m_actionView->setViewMode(settings->value(QLatin1String(actionEditorViewModeKey), 0).toInt());
+ updateViewModeActions();
+}
+
+void ActionEditor::saveSettings()
+{
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->setValue(QLatin1String(actionEditorViewModeKey), m_actionView->viewMode());
+}
+
+void ActionEditor::updateViewModeActions()
+{
+ switch (m_actionView->viewMode()) {
+ case ActionView::IconView:
+ m_iconViewAction->setChecked(true);
+ break;
+ case ActionView::DetailedView:
+ m_listViewAction->setChecked(true);
+ break;
+ }
+}
+
+void ActionEditor::slotCopy()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw )
+ return;
+
+ const ActionView::ActionList selection = m_actionView->selectedActions();
+ if (selection.empty())
+ return;
+
+ copyActions(fw, selection);
+}
+
+void ActionEditor::slotCut()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw )
+ return;
+
+ const ActionView::ActionList selection = m_actionView->selectedActions();
+ if (selection.empty())
+ return;
+
+ copyActions(fw, selection);
+ deleteActions(fw, selection);
+}
+
+void ActionEditor::slotPaste()
+{
+ FormWindowBase *fw = qobject_cast<FormWindowBase *>(formWindow());
+ if (!fw)
+ return;
+ m_actionView->clearSelection();
+ fw->paste(FormWindowBase::PasteActionsOnly);
+}
+
+void ActionEditor::slotContextMenuRequested(QContextMenuEvent *e, QAction *item)
+{
+ // set up signal mapper
+ if (!m_selectAssociatedWidgetsMapper) {
+ m_selectAssociatedWidgetsMapper = new QSignalMapper(this);
+ connect(m_selectAssociatedWidgetsMapper, SIGNAL(mapped(QWidget*)), this, SLOT(slotSelectAssociatedWidget(QWidget*)));
+ }
+
+ QMenu menu(this);
+ menu.addAction(m_actionNew);
+ menu.addSeparator();
+ menu.addAction(m_actionEdit);
+ if (QDesignerTaskMenu::isSlotNavigationEnabled(m_core))
+ menu.addAction(m_actionNavigateToSlot);
+
+ // Associated Widgets
+ if (QAction *action = m_actionView->currentAction()) {
+ const QWidgetList associatedWidgets = ActionModel::associatedWidgets(action);
+ if (!associatedWidgets.empty()) {
+ QMenu *associatedWidgetsSubMenu = menu.addMenu(tr("Used In"));
+ foreach (QWidget *w, associatedWidgets) {
+ QAction *action = associatedWidgetsSubMenu->addAction(w->objectName());
+ m_selectAssociatedWidgetsMapper->setMapping(action, w);
+ connect(action, SIGNAL(triggered()), m_selectAssociatedWidgetsMapper, SLOT(map()));
+ }
+ }
+ }
+
+ menu.addSeparator();
+ menu.addAction(m_actionCut);
+ menu.addAction(m_actionCopy);
+ menu.addAction(m_actionPaste);
+ menu.addAction(m_actionSelectAll);
+ menu.addAction(m_actionDelete);
+ menu.addSeparator();
+ menu.addAction(m_iconViewAction);
+ menu.addAction(m_listViewAction);
+
+ emit contextMenuRequested(&menu, item);
+
+ menu.exec(e->globalPos());
+ e->accept();
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/lib/shared/actioneditor_p.h b/tools/designer/src/lib/shared/actioneditor_p.h
new file mode 100644
index 0000000000..36baf50ea9
--- /dev/null
+++ b/tools/designer/src/lib/shared/actioneditor_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ACTIONEDITOR_H
+#define ACTIONEDITOR_H
+
+#include "shared_global_p.h"
+#include <QtDesigner/QDesignerActionEditorInterface>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerPropertyEditorInterface;
+class QDesignerSettingsInterface;
+class QMenu;
+class QActionGroup;
+class QSignalMapper;
+class QItemSelection;
+class QListWidget;
+class QPushButton;
+class QLineEdit;
+class QToolButton;
+
+namespace qdesigner_internal {
+
+class ActionView;
+class ResourceMimeData;
+
+class QDESIGNER_SHARED_EXPORT ActionEditor: public QDesignerActionEditorInterface
+{
+ Q_OBJECT
+public:
+ explicit ActionEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~ActionEditor();
+
+ QDesignerFormWindowInterface *formWindow() const;
+ virtual void setFormWindow(QDesignerFormWindowInterface *formWindow);
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ QAction *actionNew() const;
+ QAction *actionDelete() const;
+
+ QString filter() const;
+
+ virtual void manageAction(QAction *action);
+ virtual void unmanageAction(QAction *action);
+
+ static QString actionTextToName(const QString &text, const QString &prefix = QLatin1String("action"));
+
+ // Utility to create a configure button with menu for usage on toolbars
+ static QToolButton *createConfigureMenuButton(const QString &t, QMenu **ptrToMenu);
+
+public slots:
+ void setFilter(const QString &filter);
+ void mainContainerChanged();
+
+private slots:
+ void slotCurrentItemChanged(QAction *item);
+ void slotSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
+ void editAction(QAction *item);
+ void editCurrentAction();
+ void navigateToSlotCurrentAction();
+ void slotActionChanged();
+ void slotNewAction();
+ void slotDelete();
+ void resourceImageDropped(const QString &path, QAction *action);
+ void slotContextMenuRequested(QContextMenuEvent *, QAction *);
+ void slotViewMode(QAction *a);
+ void slotSelectAssociatedWidget(QWidget *w);
+ void slotCopy();
+ void slotCut();
+ void slotPaste();
+
+signals:
+ void itemActivated(QAction *item);
+ // Context menu for item or global menu if item == 0.
+ void contextMenuRequested(QMenu *menu, QAction *item);
+
+private:
+ typedef QList<QAction *> ActionList;
+ void deleteActions(QDesignerFormWindowInterface *formWindow, const ActionList &);
+ void copyActions(QDesignerFormWindowInterface *formWindow, const ActionList &);
+
+ void restoreSettings();
+ void saveSettings();
+
+ void updateViewModeActions();
+
+ QDesignerFormEditorInterface *m_core;
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+ QListWidget *m_actionGroups;
+
+ ActionView *m_actionView;
+
+ QAction *m_actionNew;
+ QAction *m_actionEdit;
+ QAction *m_actionNavigateToSlot;
+ QAction *m_actionCopy;
+ QAction *m_actionCut;
+ QAction *m_actionPaste;
+ QAction *m_actionSelectAll;
+ QAction *m_actionDelete;
+
+ QActionGroup *m_viewModeGroup;
+ QAction *m_iconViewAction;
+ QAction *m_listViewAction;
+
+ QString m_filter;
+ QWidget *m_filterWidget;
+ QSignalMapper *m_selectAssociatedWidgetsMapper;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ACTIONEDITOR_H
diff --git a/tools/designer/src/lib/shared/actionprovider_p.h b/tools/designer/src/lib/shared/actionprovider_p.h
new file mode 100644
index 0000000000..e358f61761
--- /dev/null
+++ b/tools/designer/src/lib/shared/actionprovider_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACTIONPROVIDER_H
+#define ACTIONPROVIDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDesigner/extension.h>
+#include <QtCore/QPoint>
+#include <QtCore/QRect>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+
+class QDesignerActionProviderExtension
+{
+public:
+ virtual ~QDesignerActionProviderExtension() {}
+
+ virtual QRect actionGeometry(QAction *action) const = 0;
+ virtual QAction *actionAt(const QPoint &pos) const = 0;
+
+ virtual void adjustIndicator(const QPoint &pos) = 0;
+};
+
+// Find action at the given position for a widget that has actionGeometry() (QToolBar,
+// QMenuBar, QMenu). They usually have actionAt(), but that fails since Designer usually sets
+// WA_TransparentForMouseEvents on the widgets.
+template <class Widget>
+ int actionIndexAt(const Widget *w, const QPoint &pos, Qt::Orientation orientation)
+{
+ const QList<QAction*> actions = w->actions();
+ const int actionCount = actions.count();
+ if (actionCount == 0)
+ return -1;
+ // actionGeometry() can be wrong sometimes; it returns a geometry that
+ // stretches to the end of the toolbar/menu bar. So, check from the beginning
+ // in the case of a horizontal right-to-left orientation.
+ const bool checkTopRight = orientation == Qt::Horizontal && QApplication::layoutDirection() == Qt::RightToLeft;
+ const QPoint topRight = QPoint(w->rect().width(), 0);
+ for (int index = 0; index < actionCount; ++index) {
+ QRect g = w->actionGeometry(actions.at(index));
+ if (checkTopRight)
+ g.setTopRight(topRight);
+ else
+ g.setTopLeft(QPoint(0, 0));
+
+ if (g.contains(pos))
+ return index;
+ }
+ return -1;
+}
+
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerActionProviderExtension, "com.trolltech.Qt.Designer.ActionProvider")
+
+QT_END_NAMESPACE
+
+#endif // ACTIONPROVIDER_H
diff --git a/tools/designer/src/lib/shared/actionrepository.cpp b/tools/designer/src/lib/shared/actionrepository.cpp
new file mode 100644
index 0000000000..941a9ba7cd
--- /dev/null
+++ b/tools/designer/src/lib/shared/actionrepository.cpp
@@ -0,0 +1,659 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "actionrepository_p.h"
+#include "qtresourceview_p.h"
+#include "iconloader_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QDrag>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QToolButton>
+#include <QtGui/QPixmap>
+#include <QtGui/QAction>
+#include <QtGui/QHeaderView>
+#include <QtGui/QToolBar>
+#include <QtGui/QMenu>
+#include <QtGui/qevent.h>
+#include <QtCore/QSet>
+#include <QtCore/QDebug>
+
+Q_DECLARE_METATYPE(QAction*)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { listModeIconSize = 16, iconModeIconSize = 24 };
+}
+
+static const char *actionMimeType = "action-repository/actions";
+static const char *plainTextMimeType = "text/plain";
+
+static inline QAction *actionOfItem(const QStandardItem* item)
+{
+ return qvariant_cast<QAction*>(item->data(qdesigner_internal::ActionModel::ActionRole));
+}
+
+static QIcon fixActionIcon(const QIcon &icon)
+{
+ if (icon.isNull())
+ return qdesigner_internal::emptyIcon();
+ return icon;
+}
+
+namespace qdesigner_internal {
+
+// ----------- ActionModel
+ActionModel::ActionModel(QWidget *parent ) :
+ QStandardItemModel(parent),
+ m_core(0)
+{
+ QStringList headers;
+ headers += tr("Name");
+ headers += tr("Used");
+ headers += tr("Text");
+ headers += tr("Shortcut");
+ headers += tr("Checkable");
+ headers += tr("ToolTip");
+ Q_ASSERT(NumColumns == headers.size());
+ setHorizontalHeaderLabels(headers);
+}
+
+void ActionModel::clearActions()
+{
+ removeRows(0, rowCount());
+}
+
+int ActionModel::findAction(QAction *action) const
+{
+ const int rows = rowCount();
+ for (int i = 0; i < rows; i++)
+ if (action == actionOfItem(item(i)))
+ return i;
+ return -1;
+}
+
+void ActionModel::update(int row)
+{
+ Q_ASSERT(m_core);
+ // need to create the row list ... grrr..
+ if (row >= rowCount())
+ return;
+
+ QStandardItemList list;
+ for (int i = 0; i < NumColumns; i++)
+ list += item(row, i);
+
+ setItems(m_core, actionOfItem(list.front()), list);
+}
+
+void ActionModel::remove(int row)
+{
+ qDeleteAll(takeRow(row));
+}
+
+QModelIndex ActionModel::addAction(QAction *action)
+{
+ Q_ASSERT(m_core);
+ QStandardItemList items;
+ const Qt::ItemFlags flags = Qt::ItemIsSelectable|Qt::ItemIsDropEnabled|Qt::ItemIsDragEnabled|Qt::ItemIsEnabled;
+
+ QVariant itemData;
+ qVariantSetValue(itemData, action);
+
+ for (int i = 0; i < NumColumns; i++) {
+ QStandardItem *item = new QStandardItem;
+ item->setData(itemData, ActionRole);
+ item->setFlags(flags);
+ items.push_back(item);
+ }
+ setItems(m_core, action, items);
+ appendRow(items);
+ return indexFromItem(items.front());
+}
+
+// Find the associated menus and toolbars, ignore toolbuttons
+QWidgetList ActionModel::associatedWidgets(const QAction *action)
+{
+ QWidgetList rc = action->associatedWidgets();
+ for (QWidgetList::iterator it = rc.begin(); it != rc.end(); )
+ if (qobject_cast<const QMenu *>(*it) || qobject_cast<const QToolBar *>(*it)) {
+ ++it;
+ } else {
+ it = rc.erase(it);
+ }
+ return rc;
+}
+
+// shortcut is a fake property, need to retrieve it via property sheet.
+static QString actionShortCut(QDesignerFormEditorInterface *core, QAction *action)
+{
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), action);
+ if (!sheet)
+ return QString();
+ const int index = sheet->indexOf(QLatin1String("shortcut"));
+ if (index == -1)
+ return QString();
+ const QKeySequence keysequence = qvariant_cast<QKeySequence>(sheet->property(index));
+ return keysequence.toString();
+}
+
+void ActionModel::setItems(QDesignerFormEditorInterface *core, QAction *action, QStandardItemList &sl)
+{
+
+ // Tooltip, mostly for icon view mode
+ QString firstTooltip = action->objectName();
+ const QString text = action->text();
+ if (!text.isEmpty()) {
+ firstTooltip += QLatin1Char('\n');
+ firstTooltip += text;
+ }
+
+ Q_ASSERT(sl.size() == NumColumns);
+
+ QStandardItem *item = sl[NameColumn];
+ item->setText(action->objectName());
+ item->setIcon(fixActionIcon(action->icon()));
+ item->setToolTip(firstTooltip);
+ item->setWhatsThis(firstTooltip);
+ // Used
+ const QWidgetList associatedDesignerWidgets = associatedWidgets(action);
+ const bool used = !associatedDesignerWidgets.empty();
+ item = sl[UsedColumn];
+ item->setCheckState(used ? Qt::Checked : Qt::Unchecked);
+ if (used) {
+ QString usedToolTip;
+ const QString separator = QLatin1String(", ");
+ const int count = associatedDesignerWidgets.size();
+ for (int i = 0; i < count; i++) {
+ if (i)
+ usedToolTip += separator;
+ usedToolTip += associatedDesignerWidgets.at(i)->objectName();
+ }
+ item->setToolTip(usedToolTip);
+ } else {
+ item->setToolTip(QString());
+ }
+ // text
+ item = sl[TextColumn];
+ item->setText(action->text());
+ item->setToolTip(action->text());
+ // shortcut
+ const QString shortcut = actionShortCut(core, action);
+ item = sl[ShortCutColumn];
+ item->setText(shortcut);
+ item->setToolTip(shortcut);
+ // checkable
+ sl[CheckedColumn]->setCheckState(action->isCheckable() ? Qt::Checked : Qt::Unchecked);
+ // ToolTip. This might be multi-line, rich text
+ QString toolTip = action->toolTip();
+ item = sl[ToolTipColumn];
+ item->setToolTip(toolTip);
+ item->setText(toolTip.replace(QLatin1Char('\n'), QLatin1Char(' ')));
+}
+
+QMimeData *ActionModel::mimeData(const QModelIndexList &indexes ) const
+{
+ ActionRepositoryMimeData::ActionList actionList;
+
+ QSet<QAction*> actions;
+ foreach (const QModelIndex &index, indexes)
+ if (QStandardItem *item = itemFromIndex(index))
+ if (QAction *action = actionOfItem(item))
+ actions.insert(action);
+ return new ActionRepositoryMimeData(actions.toList(), Qt::CopyAction);
+}
+
+// Resource images are plain text. The drag needs to be restricted, however.
+QStringList ActionModel::mimeTypes() const
+{
+ return QStringList(QLatin1String(plainTextMimeType));
+}
+
+QString ActionModel::actionName(int row) const
+{
+ return item(row, NameColumn)->text();
+}
+
+bool ActionModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &)
+{
+ if (action != Qt::CopyAction)
+ return false;
+
+ QStandardItem *droppedItem = item(row, column);
+ if (!droppedItem)
+ return false;
+
+
+ QtResourceView::ResourceType type;
+ QString path;
+ if (!QtResourceView::decodeMimeData(data, &type, &path) || type != QtResourceView::ResourceImage)
+ return false;
+
+ emit resourceImageDropped(path, actionOfItem(droppedItem));
+ return true;
+}
+
+QAction *ActionModel::actionAt(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return 0;
+ QStandardItem *i = itemFromIndex(index);
+ if (!i)
+ return 0;
+ return actionOfItem(i);
+}
+
+// helpers
+
+static bool handleImageDragEnterMoveEvent(QDropEvent *event)
+{
+ QtResourceView::ResourceType type;
+ const bool rc = QtResourceView::decodeMimeData(event->mimeData(), &type) && type == QtResourceView::ResourceImage;
+ if (rc)
+ event->acceptProposedAction();
+ else
+ event->ignore();
+ return rc;
+}
+
+static void handleImageDropEvent(const QAbstractItemView *iv, QDropEvent *event, ActionModel *am)
+{
+ const QModelIndex index = iv->indexAt(event->pos());
+ if (!index.isValid()) {
+ event->ignore();
+ return;
+ }
+
+ if (!handleImageDragEnterMoveEvent(event))
+ return;
+
+ am->dropMimeData(event->mimeData(), event->proposedAction(), index.row(), 0, iv->rootIndex());
+}
+
+// Basically mimic QAbstractItemView's startDrag routine, except that
+// another pixmap is used, we don't want the whole row.
+
+void startActionDrag(QWidget *dragParent, ActionModel *model, const QModelIndexList &indexes, Qt::DropActions supportedActions)
+{
+ if (indexes.empty())
+ return;
+
+ QDrag *drag = new QDrag(dragParent);
+ QMimeData *data = model->mimeData(indexes);
+ drag->setMimeData(data);
+ if (ActionRepositoryMimeData *actionMimeData = qobject_cast<ActionRepositoryMimeData *>(data))
+ drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap(actionMimeData->actionList().front()));
+
+ drag->start(supportedActions);
+}
+
+// ---------------- ActionTreeView:
+ActionTreeView::ActionTreeView(ActionModel *model, QWidget *parent) :
+ QTreeView(parent),
+ m_model(model)
+{
+ setDragEnabled(true);
+ setAcceptDrops(true);
+ setDropIndicatorShown(true);
+ setDragDropMode(DragDrop);
+ setModel(model);
+ setRootIsDecorated(false);
+ setTextElideMode(Qt::ElideMiddle);
+
+ setModel(model);
+ connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(slotActivated(QModelIndex)));
+ connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int)));
+
+ setIconSize(QSize(listModeIconSize, listModeIconSize));
+
+}
+
+QAction *ActionTreeView::currentAction() const
+{
+ return m_model->actionAt(currentIndex());
+}
+
+void ActionTreeView::filter(const QString &text)
+{
+ const int rowCount = m_model->rowCount();
+ const bool empty = text.isEmpty();
+ const QModelIndex parent = rootIndex();
+ for (int i = 0; i < rowCount; i++)
+ setRowHidden(i, parent, !empty && !m_model->actionName(i).contains(text, Qt::CaseInsensitive));
+}
+
+void ActionTreeView::dragEnterEvent(QDragEnterEvent *event)
+{
+ handleImageDragEnterMoveEvent(event);
+}
+
+void ActionTreeView::dragMoveEvent(QDragMoveEvent *event)
+{
+ handleImageDragEnterMoveEvent(event);
+}
+
+void ActionTreeView::dropEvent(QDropEvent *event)
+{
+ handleImageDropEvent(this, event, m_model);
+}
+
+void ActionTreeView::focusInEvent(QFocusEvent *event)
+{
+ QTreeView::focusInEvent(event);
+ // Make property editor display current action
+ if (QAction *a = currentAction())
+ emit currentChanged(a);
+}
+
+void ActionTreeView::contextMenuEvent(QContextMenuEvent *event)
+{
+ emit contextMenuRequested(event, m_model->actionAt(indexAt(event->pos())));
+}
+
+void ActionTreeView::currentChanged(const QModelIndex &current, const QModelIndex &/*previous*/)
+{
+ emit currentChanged(m_model->actionAt(current));
+}
+
+void ActionTreeView::slotActivated(const QModelIndex &index)
+{
+ emit activated(m_model->actionAt(index));
+}
+
+void ActionTreeView::startDrag(Qt::DropActions supportedActions)
+{
+ startActionDrag(this, m_model, selectedIndexes(), supportedActions);
+}
+
+// ---------------- ActionListView:
+ActionListView::ActionListView(ActionModel *model, QWidget *parent) :
+ QListView(parent),
+ m_model(model)
+{
+ setDragEnabled(true);
+ setAcceptDrops(true);
+ setDropIndicatorShown(true);
+ setDragDropMode(DragDrop);
+ setModel(model);
+ setTextElideMode(Qt::ElideMiddle);
+ connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(slotActivated(QModelIndex)));
+
+ // We actually want 'Static' as the user should be able to
+ // drag away actions only (not to rearrange icons).
+ // We emulate that by not accepting our own
+ // drag data. 'Static' causes the list view to disable drag and drop
+ // on the viewport.
+ setMovement(Snap);
+ setViewMode(IconMode);
+ setIconSize(QSize(iconModeIconSize, iconModeIconSize));
+ setGridSize(QSize(4 * iconModeIconSize, 2 * iconModeIconSize));
+ setSpacing(iconModeIconSize / 3);
+}
+
+QAction *ActionListView::currentAction() const
+{
+ return m_model->actionAt(currentIndex());
+}
+
+void ActionListView::filter(const QString &text)
+{
+ const int rowCount = m_model->rowCount();
+ const bool empty = text.isEmpty();
+ for (int i = 0; i < rowCount; i++)
+ setRowHidden(i, !empty && !m_model->actionName(i).contains(text, Qt::CaseInsensitive));
+}
+
+void ActionListView::dragEnterEvent(QDragEnterEvent *event)
+{
+ handleImageDragEnterMoveEvent(event);
+}
+
+void ActionListView::dragMoveEvent(QDragMoveEvent *event)
+{
+ handleImageDragEnterMoveEvent(event);
+}
+
+void ActionListView::dropEvent(QDropEvent *event)
+{
+ handleImageDropEvent(this, event, m_model);
+}
+
+void ActionListView::focusInEvent(QFocusEvent *event)
+{
+ QListView::focusInEvent(event);
+ // Make property editor display current action
+ if (QAction *a = currentAction())
+ emit currentChanged(a);
+}
+
+void ActionListView::contextMenuEvent(QContextMenuEvent *event)
+{
+ emit contextMenuRequested(event, m_model->actionAt(indexAt(event->pos())));
+}
+
+void ActionListView::currentChanged(const QModelIndex &current, const QModelIndex & /*previous*/)
+{
+ emit currentChanged(m_model->actionAt(current));
+}
+
+void ActionListView::slotActivated(const QModelIndex &index)
+{
+ emit activated(m_model->actionAt(index));
+}
+
+void ActionListView::startDrag(Qt::DropActions supportedActions)
+{
+ startActionDrag(this, m_model, selectedIndexes(), supportedActions);
+}
+
+// ActionView
+ActionView::ActionView(QWidget *parent) :
+ QStackedWidget(parent),
+ m_model(new ActionModel(this)),
+ m_actionTreeView(new ActionTreeView(m_model)),
+ m_actionListView(new ActionListView(m_model))
+{
+ addWidget(m_actionListView);
+ addWidget(m_actionTreeView);
+ // Wire signals
+ connect(m_actionTreeView, SIGNAL(contextMenuRequested(QContextMenuEvent*, QAction*)),
+ this, SIGNAL(contextMenuRequested(QContextMenuEvent*, QAction*)));
+ connect(m_actionListView, SIGNAL(contextMenuRequested(QContextMenuEvent*, QAction*)),
+ this, SIGNAL(contextMenuRequested(QContextMenuEvent*, QAction*)));
+
+ // make it possible for vs integration to reimplement edit action dialog
+ // [which it shouldn't do actually]
+ connect(m_actionListView, SIGNAL(activated(QAction*)), this, SIGNAL(activated(QAction*)));
+ connect(m_actionTreeView, SIGNAL(activated(QAction*)), this, SIGNAL(activated(QAction*)));
+
+ connect(m_actionListView, SIGNAL(currentChanged(QAction*)),this, SLOT(slotCurrentChanged(QAction*)));
+ connect(m_actionTreeView, SIGNAL(currentChanged(QAction*)),this, SLOT(slotCurrentChanged(QAction*)));
+
+ connect(m_model, SIGNAL(resourceImageDropped(QString,QAction*)),
+ this, SIGNAL(resourceImageDropped(QString,QAction*)));
+
+ // sync selection models
+ QItemSelectionModel *selectionModel = m_actionTreeView->selectionModel();
+ m_actionListView->setSelectionModel(selectionModel);
+ connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ this, SIGNAL(selectionChanged(QItemSelection,QItemSelection)));
+}
+
+int ActionView::viewMode() const
+{
+ return currentWidget() == m_actionListView ? IconView : DetailedView;
+}
+
+void ActionView::setViewMode(int lm)
+{
+ if (viewMode() == lm)
+ return;
+
+ switch (lm) {
+ case IconView:
+ setCurrentWidget(m_actionListView);
+ break;
+ case DetailedView:
+ setCurrentWidget(m_actionTreeView);
+ break;
+ default:
+ break;
+ }
+}
+
+void ActionView::slotCurrentChanged(QAction *action)
+{
+ // emit only for currently visible
+ if (sender() == currentWidget())
+ emit currentChanged(action);
+}
+
+void ActionView::filter(const QString &text)
+{
+ m_actionTreeView->filter(text);
+ m_actionListView->filter(text);
+}
+
+void ActionView::selectAll()
+{
+ m_actionTreeView->selectAll();
+}
+
+void ActionView::clearSelection()
+{
+ m_actionTreeView->selectionModel()->clearSelection();
+}
+
+void ActionView::setCurrentIndex(const QModelIndex &index)
+{
+ m_actionTreeView->setCurrentIndex(index);
+}
+
+QAction *ActionView::currentAction() const
+{
+ return m_actionListView->currentAction();
+}
+
+void ActionView::setSelectionMode(QAbstractItemView::SelectionMode sm)
+{
+ m_actionTreeView->setSelectionMode(sm);
+ m_actionListView->setSelectionMode(sm);
+}
+
+QAbstractItemView::SelectionMode ActionView::selectionMode() const
+{
+ return m_actionListView->selectionMode();
+}
+
+QItemSelection ActionView::selection() const
+{
+ return m_actionListView->selectionModel()->selection();
+}
+
+ActionView::ActionList ActionView::selectedActions() const
+{
+ ActionList rc;
+ foreach (const QModelIndex &index, selection().indexes())
+ if (index.column() == 0)
+ rc += actionOfItem(m_model->itemFromIndex(index));
+ return rc;
+}
+// ---------- ActionRepositoryMimeData
+ActionRepositoryMimeData::ActionRepositoryMimeData(QAction *a, Qt::DropAction dropAction) :
+ m_dropAction(dropAction)
+{
+ m_actionList += a;
+}
+
+ActionRepositoryMimeData::ActionRepositoryMimeData(const ActionList &al, Qt::DropAction dropAction) :
+ m_dropAction(dropAction),
+ m_actionList(al)
+{
+}
+
+QStringList ActionRepositoryMimeData::formats() const
+{
+ return QStringList(QLatin1String(actionMimeType));
+}
+
+QPixmap ActionRepositoryMimeData::actionDragPixmap(const QAction *action)
+{
+
+ // Try to find a suitable pixmap. Grab either widget or icon.
+ const QIcon icon = action->icon();
+ if (!icon.isNull())
+ return icon.pixmap(QSize(22, 22));
+
+ foreach (QWidget *w, action->associatedWidgets())
+ if (QToolButton *tb = qobject_cast<QToolButton *>(w))
+ return QPixmap::grabWidget(tb);
+
+ // Create a QToolButton
+ QToolButton *tb = new QToolButton;
+ tb->setText(action->text());
+ tb->setToolButtonStyle(Qt::ToolButtonTextOnly);
+#ifdef Q_WS_WIN // Force alien off to make adjustSize() take the system minimumsize into account.
+ tb->createWinId();
+#endif
+ tb->adjustSize();
+ const QPixmap rc = QPixmap::grabWidget(tb);
+ tb->deleteLater();
+ return rc;
+}
+
+void ActionRepositoryMimeData::accept(QDragMoveEvent *event) const
+{
+ if (event->proposedAction() == m_dropAction) {
+ event->acceptProposedAction();
+ } else {
+ event->setDropAction(m_dropAction);
+ event->accept();
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/actionrepository_p.h b/tools/designer/src/lib/shared/actionrepository_p.h
new file mode 100644
index 0000000000..9d1af5aadf
--- /dev/null
+++ b/tools/designer/src/lib/shared/actionrepository_p.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ACTIONREPOSITORY_H
+#define ACTIONREPOSITORY_H
+
+#include "shared_global_p.h"
+#include <QtCore/QMimeData>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QTreeView>
+#include <QtGui/QListView>
+#include <QtGui/QStackedWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QPixmap;
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+// Shared model of actions, to be used for several views (detailed/icon view).
+class QDESIGNER_SHARED_EXPORT ActionModel: public QStandardItemModel
+{
+ Q_OBJECT
+public:
+ enum Columns { NameColumn, UsedColumn, TextColumn, ShortCutColumn, CheckedColumn, ToolTipColumn, NumColumns };
+ enum { ActionRole = Qt::UserRole + 1000 };
+
+ explicit ActionModel(QWidget *parent = 0);
+ void initialize(QDesignerFormEditorInterface *core) { m_core = core; }
+
+ void clearActions();
+ QModelIndex addAction(QAction *a);
+ // remove row
+ void remove(int row);
+ // update the row from the underlying action
+ void update(int row);
+
+ // return row of action or -1.
+ int findAction(QAction *) const;
+
+ QString actionName(int row) const;
+ QAction *actionAt(const QModelIndex &index) const;
+
+ virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
+ virtual QStringList mimeTypes() const;
+ virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
+
+ // Find the associated menus and toolbars, ignore toolbuttons
+ static QWidgetList associatedWidgets(const QAction *action);
+
+signals:
+ void resourceImageDropped(const QString &path, QAction *action);
+
+private:
+ void initializeHeaders();
+
+ typedef QList<QStandardItem *> QStandardItemList;
+ static void setItems(QDesignerFormEditorInterface *core, QAction *a, QStandardItemList &sl);
+
+ QDesignerFormEditorInterface *m_core;
+};
+
+// Internal class that provides the detailed view of actions.
+class ActionTreeView: public QTreeView
+{
+ Q_OBJECT
+public:
+ explicit ActionTreeView(ActionModel *model, QWidget *parent = 0);
+ QAction *currentAction() const;
+
+public slots:
+ void filter(const QString &text);
+
+signals:
+ void contextMenuRequested(QContextMenuEvent *event, QAction *);
+ void currentChanged(QAction *action);
+ void activated(QAction *action);
+
+protected slots:
+ virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous);
+
+protected:
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dragMoveEvent(QDragMoveEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+ virtual void focusInEvent(QFocusEvent *event);
+ virtual void contextMenuEvent(QContextMenuEvent *event);
+ virtual void startDrag(Qt::DropActions supportedActions);
+
+private slots:
+ void slotActivated(const QModelIndex &);
+
+private:
+ ActionModel *m_model;
+};
+
+// Internal class that provides the icon view of actions.
+class ActionListView: public QListView
+{
+ Q_OBJECT
+public:
+ explicit ActionListView(ActionModel *model, QWidget *parent = 0);
+ QAction *currentAction() const;
+
+public slots:
+ void filter(const QString &text);
+
+signals:
+ void contextMenuRequested(QContextMenuEvent *event, QAction *);
+ void currentChanged(QAction *action);
+ void activated(QAction *action);
+
+protected slots:
+ virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous);
+
+protected:
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dragMoveEvent(QDragMoveEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+ virtual void focusInEvent(QFocusEvent *event);
+ virtual void contextMenuEvent(QContextMenuEvent *event);
+ virtual void startDrag(Qt::DropActions supportedActions);
+
+private slots:
+ void slotActivated(const QModelIndex &);
+
+private:
+ ActionModel *m_model;
+};
+
+// Action View that can be switched between detailed and icon view
+// using a QStackedWidget of ActionListView / ActionTreeView
+// that share the item model and the selection model.
+
+class ActionView : public QStackedWidget {
+ Q_OBJECT
+public:
+ // Separate initialize() function takes core argument to make this
+ // thing usable as promoted widget.
+ explicit ActionView(QWidget *parent = 0);
+ void initialize(QDesignerFormEditorInterface *core) { m_model->initialize(core); }
+
+ // View mode
+ enum { DetailedView, IconView };
+ int viewMode() const;
+ void setViewMode(int lm);
+
+ void setSelectionMode(QAbstractItemView::SelectionMode sm);
+ QAbstractItemView::SelectionMode selectionMode() const;
+
+ ActionModel *model() const { return m_model; }
+
+ QAction *currentAction() const;
+ void setCurrentIndex(const QModelIndex &index);
+
+ typedef QList<QAction*> ActionList;
+ ActionList selectedActions() const;
+ QItemSelection selection() const;
+
+public slots:
+ void filter(const QString &text);
+ void selectAll();
+ void clearSelection();
+
+signals:
+ void contextMenuRequested(QContextMenuEvent *event, QAction *);
+ void currentChanged(QAction *action);
+ void activated(QAction *action);
+ void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
+ void resourceImageDropped(const QString &data, QAction *action);
+
+private slots:
+ void slotCurrentChanged(QAction *action);
+
+private:
+ ActionModel *m_model;
+ ActionTreeView *m_actionTreeView;
+ ActionListView *m_actionListView;
+};
+
+class QDESIGNER_SHARED_EXPORT ActionRepositoryMimeData: public QMimeData
+{
+ Q_OBJECT
+public:
+ typedef QList<QAction*> ActionList;
+
+ ActionRepositoryMimeData(const ActionList &, Qt::DropAction dropAction);
+ ActionRepositoryMimeData(QAction *, Qt::DropAction dropAction);
+
+ const ActionList &actionList() const { return m_actionList; }
+ virtual QStringList formats() const;
+
+ static QPixmap actionDragPixmap(const QAction *action);
+
+ // Utility to accept with right action
+ void accept(QDragMoveEvent *event) const;
+private:
+ const Qt::DropAction m_dropAction;
+ ActionList m_actionList;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ACTIONREPOSITORY_H
diff --git a/tools/designer/src/lib/shared/addlinkdialog.ui b/tools/designer/src/lib/shared/addlinkdialog.ui
new file mode 100644
index 0000000000..3171159f97
--- /dev/null
+++ b/tools/designer/src/lib/shared/addlinkdialog.ui
@@ -0,0 +1,112 @@
+<ui version="4.0" >
+ <class>AddLinkDialog</class>
+ <widget class="QDialog" name="AddLinkDialog" >
+ <property name="windowTitle" >
+ <string>Insert Link</string>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>false</bool>
+ </property>
+ <property name="modal" >
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <layout class="QFormLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="titleInput" >
+ <property name="minimumSize" >
+ <size>
+ <width>337</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>URL:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="urlInput" />
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="Line" name="line" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AddLinkDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AddLinkDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/codedialog.cpp b/tools/designer/src/lib/shared/codedialog.cpp
new file mode 100644
index 0000000000..5a2db33f04
--- /dev/null
+++ b/tools/designer/src/lib/shared/codedialog.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::CodeDialog
+*/
+
+#include "codedialog_p.h"
+#include "qdesigner_utils_p.h"
+#include "iconloader_p.h"
+
+#include <texteditfindwidget.h>
+
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QClipboard>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QFileDialog>
+#include <QtGui/QIcon>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QTextEdit>
+#include <QtGui/QToolBar>
+#include <QtGui/QVBoxLayout>
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QTemporaryFile>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+// ----------------- CodeDialogPrivate
+struct CodeDialog::CodeDialogPrivate {
+ CodeDialogPrivate();
+
+ QTextEdit *m_textEdit;
+ TextEditFindWidget *m_findWidget;
+ QString m_formFileName;
+};
+
+CodeDialog::CodeDialogPrivate::CodeDialogPrivate()
+ : m_textEdit(new QTextEdit)
+ , m_findWidget(new TextEditFindWidget)
+{
+}
+
+// ----------------- CodeDialog
+CodeDialog::CodeDialog(QWidget *parent) :
+ QDialog(parent),
+ m_impl(new CodeDialogPrivate)
+{
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ QVBoxLayout *vBoxLayout = new QVBoxLayout;
+
+ // Edit tool bar
+ QToolBar *toolBar = new QToolBar;
+
+ const QIcon saveIcon = createIconSet(QLatin1String("filesave.png"));
+ QAction *saveAction = toolBar->addAction(saveIcon, tr("Save..."));
+ connect(saveAction, SIGNAL(triggered()), this, SLOT(slotSaveAs()));
+
+ const QIcon copyIcon = createIconSet(QLatin1String("editcopy.png"));
+ QAction *copyAction = toolBar->addAction(copyIcon, tr("Copy All"));
+ connect(copyAction, SIGNAL(triggered()), this, SLOT(copyAll()));
+
+ QAction *findAction = toolBar->addAction(
+ TextEditFindWidget::findIconSet(),
+ tr("&Find in Text..."),
+ m_impl->m_findWidget, SLOT(activate()));
+ findAction->setShortcut(QKeySequence::Find);
+
+ vBoxLayout->addWidget(toolBar);
+
+ // Edit
+ m_impl->m_textEdit->setReadOnly(true);
+ m_impl->m_textEdit->setMinimumSize(QSize(
+ m_impl->m_findWidget->minimumSize().width(),
+ 500));
+ vBoxLayout->addWidget(m_impl->m_textEdit);
+
+ // Find
+ m_impl->m_findWidget->setTextEdit(m_impl->m_textEdit);
+ vBoxLayout->addWidget(m_impl->m_findWidget);
+
+ // Button box
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ // Disable auto default
+ QPushButton *closeButton = buttonBox->button(QDialogButtonBox::Close);
+ closeButton->setAutoDefault(false);
+ vBoxLayout->addWidget(buttonBox);
+
+ setLayout(vBoxLayout);
+}
+
+CodeDialog::~CodeDialog()
+{
+ delete m_impl;
+}
+
+void CodeDialog::setCode(const QString &code)
+{
+ m_impl->m_textEdit->setPlainText(code);
+}
+
+QString CodeDialog::code() const
+{
+ return m_impl->m_textEdit->toPlainText();
+}
+
+void CodeDialog::setFormFileName(const QString &f)
+{
+ m_impl->m_formFileName = f;
+}
+
+QString CodeDialog::formFileName() const
+{
+ return m_impl->m_formFileName;
+}
+
+bool CodeDialog::generateCode(const QDesignerFormWindowInterface *fw,
+ QString *code,
+ QString *errorMessage)
+{
+ // Generate temporary file name similar to form file name
+ // (for header guards)
+ QString tempPattern = QDir::tempPath();
+ if (!tempPattern.endsWith(QDir::separator())) // platform-dependant
+ tempPattern += QDir::separator();
+ const QString fileName = fw->fileName();
+ if (fileName.isEmpty()) {
+ tempPattern += QLatin1String("designer");
+ } else {
+ tempPattern += QFileInfo(fileName).baseName();
+ }
+ tempPattern += QLatin1String("XXXXXX.ui");
+ // Write to temp file
+ QTemporaryFile tempFormFile(tempPattern);
+
+ tempFormFile.setAutoRemove(true);
+ if (!tempFormFile.open()) {
+ *errorMessage = tr("A temporary form file could not be created in %1.").arg(QDir::tempPath());
+ return false;
+ }
+ const QString tempFormFileName = tempFormFile.fileName();
+ tempFormFile.write(fw->contents().toUtf8());
+ if (!tempFormFile.flush()) {
+ *errorMessage = tr("The temporary form file %1 could not be written.").arg(tempFormFileName);
+ return false;
+ }
+ tempFormFile.close();
+ // Run uic
+ QByteArray rc;
+ if (!runUIC(tempFormFileName, UIC_GenerateCode, rc, *errorMessage))
+ return false;
+ *code = QString::fromUtf8(rc);
+ return true;
+}
+
+bool CodeDialog::showCodeDialog(const QDesignerFormWindowInterface *fw,
+ QWidget *parent,
+ QString *errorMessage)
+{
+ QString code;
+ if (!generateCode(fw, &code, errorMessage))
+ return false;
+
+ CodeDialog dialog(parent);
+ dialog.setWindowTitle(tr("%1 - [Code]").arg(fw->mainContainer()->windowTitle()));
+ dialog.setCode(code);
+ dialog.setFormFileName(fw->fileName());
+ dialog.exec();
+ return true;
+}
+
+void CodeDialog::slotSaveAs()
+{
+ // build the default relative name 'ui_sth.h'
+ const QString headerSuffix = QString(QLatin1Char('h'));
+ QString filter;
+ const QString uiFile = formFileName();
+
+ if (!uiFile.isEmpty()) {
+ filter = QLatin1String("ui_");
+ filter += QFileInfo(uiFile).baseName();
+ filter += QLatin1Char('.');
+ filter += headerSuffix;
+ }
+ // file dialog
+ while (true) {
+ const QString fileName =
+ QFileDialog::getSaveFileName (this, tr("Save Code"), filter, tr("Header Files (*.%1)").arg(headerSuffix));
+ if (fileName.isEmpty())
+ break;
+
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly|QIODevice::Text)) {
+ warning(tr("The file %1 could not be opened: %2").arg(fileName).arg(file.errorString()));
+ continue;
+ }
+ file.write(code().toUtf8());
+ if (!file.flush()) {
+ warning(tr("The file %1 could not be written: %2").arg(fileName).arg(file.errorString()));
+ continue;
+ }
+ file.close();
+ break;
+ }
+}
+
+void CodeDialog::warning(const QString &msg)
+{
+ QMessageBox::warning(
+ this, tr("%1 - Error").arg(windowTitle()),
+ msg, QMessageBox::Close);
+}
+
+void CodeDialog::copyAll()
+{
+ QApplication::clipboard()->setText(code());
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/codedialog_p.h b/tools/designer/src/lib/shared/codedialog_p.h
new file mode 100644
index 0000000000..89f5fa995a
--- /dev/null
+++ b/tools/designer/src/lib/shared/codedialog_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef CODEPREVIEWDIALOG_H
+#define CODEPREVIEWDIALOG_H
+
+#include "shared_global_p.h"
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+// Dialog for viewing code.
+class QDESIGNER_SHARED_EXPORT CodeDialog : public QDialog
+{
+ Q_OBJECT
+ explicit CodeDialog(QWidget *parent = 0);
+public:
+ virtual ~CodeDialog();
+
+ static bool generateCode(const QDesignerFormWindowInterface *fw,
+ QString *code,
+ QString *errorMessage);
+
+ static bool showCodeDialog(const QDesignerFormWindowInterface *fw,
+ QWidget *parent,
+ QString *errorMessage);
+
+private slots:
+ void slotSaveAs();
+ void copyAll();
+
+private:
+ void setCode(const QString &code);
+ QString code() const;
+ void setFormFileName(const QString &f);
+ QString formFileName() const;
+
+ void warning(const QString &msg);
+
+ struct CodeDialogPrivate;
+ CodeDialogPrivate *m_impl;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // CODEPREVIEWDIALOG_H
diff --git a/tools/designer/src/lib/shared/connectionedit.cpp b/tools/designer/src/lib/shared/connectionedit.cpp
new file mode 100644
index 0000000000..579a59e7a6
--- /dev/null
+++ b/tools/designer/src/lib/shared/connectionedit.cpp
@@ -0,0 +1,1612 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "connectionedit_p.h"
+
+#include <QtDesigner/abstractformwindow.h>
+
+#include <QtGui/QPainter>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QFontMetrics>
+#include <QtGui/QPixmap>
+#include <QtGui/QMatrix>
+#include <QtGui/QApplication>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+
+#include <QtCore/QMultiMap>
+
+QT_BEGIN_NAMESPACE
+
+static const int BG_ALPHA = 32;
+static const int LINE_PROXIMITY_RADIUS = 3;
+static const int LOOP_MARGIN = 20;
+static const int VLABEL_MARGIN = 1;
+static const int HLABEL_MARGIN = 3;
+static const int GROUND_W = 20;
+static const int GROUND_H = 25;
+
+/*******************************************************************************
+** Tools
+*/
+
+static QRect fixRect(const QRect &r)
+{
+ return QRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
+}
+
+static QRect expand(const QRect &r, int i)
+{
+ return QRect(r.x() - i, r.y() - i, r.width() + 2*i, r.height() + 2*i);
+}
+
+static QRect endPointRectHelper(const QPoint &pos)
+{
+ const QRect r(pos + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS),
+ QSize(2*LINE_PROXIMITY_RADIUS, 2*LINE_PROXIMITY_RADIUS));
+ return r;
+}
+
+static void paintGround(QPainter *p, QRect r)
+{
+ const QPoint mid = r.center();
+ p->drawLine(mid.x(), r.top(), mid.x(), mid.y());
+ p->drawLine(r.left(), mid.y(), r.right(), mid.y());
+ int y = r.top() + 4*r.height()/6;
+ int x = GROUND_W/6;
+ p->drawLine(r.left() + x, y, r.right() - x, y);
+ y = r.top() + 5*r.height()/6;
+ x = 2*GROUND_W/6;
+ p->drawLine(r.left() + x, y, r.right() - x, y);
+ p->drawLine(mid.x(), r.bottom(), mid.x() + 1, r.bottom());
+}
+
+static void paintEndPoint(QPainter *p, const QPoint &pos)
+{
+ const QRect r(pos + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS),
+ QSize(2*LINE_PROXIMITY_RADIUS, 2*LINE_PROXIMITY_RADIUS));
+ p->fillRect(fixRect(r), p->pen().color());
+}
+
+static qdesigner_internal::CETypes::LineDir classifyLine(const QPoint &p1, const QPoint &p2)
+{
+ if (p1.x() == p2.x())
+ return p1.y() < p2.y() ? qdesigner_internal::CETypes::DownDir : qdesigner_internal::CETypes::UpDir;
+ Q_ASSERT(p1.y() == p2.y());
+ return p1.x() < p2.x() ? qdesigner_internal::CETypes::RightDir : qdesigner_internal::CETypes::LeftDir;
+}
+
+static QPoint pointInsideRect(const QRect &r, QPoint p)
+{
+ if (p.x() < r.left())
+ p.setX(r.left());
+ else if (p.x() > r.right())
+ p.setX(r.right());
+
+ if (p.y() < r.top())
+ p.setY(r.top());
+ else if (p.y() > r.bottom())
+ p.setY(r.bottom());
+
+ return p;
+}
+
+namespace qdesigner_internal {
+
+/*******************************************************************************
+** Commands
+*/
+
+AddConnectionCommand::AddConnectionCommand(ConnectionEdit *edit, Connection *con)
+ : CECommand(edit), m_con(con)
+{
+ setText(QApplication::translate("Command", "Add connection"));
+}
+
+void AddConnectionCommand::redo()
+{
+ edit()->selectNone();
+ emit edit()->aboutToAddConnection(edit()->m_con_list.size());
+ edit()->m_con_list.append(m_con);
+ m_con->inserted();
+ edit()->setSelected(m_con, true);
+ emit edit()->connectionAdded(m_con);
+}
+
+void AddConnectionCommand::undo()
+{
+ const int idx = edit()->indexOfConnection(m_con);
+ emit edit()->aboutToRemoveConnection(m_con);
+ edit()->setSelected(m_con, false);
+ m_con->update();
+ m_con->removed();
+ edit()->m_con_list.removeAll(m_con);
+ emit edit()->connectionRemoved(idx);
+}
+
+class AdjustConnectionCommand : public CECommand
+{
+public:
+ AdjustConnectionCommand(ConnectionEdit *edit, Connection *con,
+ const QPoint &old_source_pos,
+ const QPoint &old_target_pos,
+ const QPoint &new_source_pos,
+ const QPoint &new_target_pos);
+ virtual void redo();
+ virtual void undo();
+private:
+ Connection *m_con;
+ const QPoint m_old_source_pos;
+ const QPoint m_old_target_pos;
+ const QPoint m_new_source_pos;
+ const QPoint m_new_target_pos;
+};
+
+AdjustConnectionCommand::AdjustConnectionCommand(ConnectionEdit *edit, Connection *con,
+ const QPoint &old_source_pos,
+ const QPoint &old_target_pos,
+ const QPoint &new_source_pos,
+ const QPoint &new_target_pos) :
+ CECommand(edit),
+ m_con(con),
+ m_old_source_pos(old_source_pos),
+ m_old_target_pos(old_target_pos),
+ m_new_source_pos(new_source_pos),
+ m_new_target_pos(new_target_pos)
+{
+ setText(QApplication::translate("Command", "Adjust connection"));
+}
+
+void AdjustConnectionCommand::undo()
+{
+ m_con->setEndPoint(EndPoint::Source, m_con->widget(EndPoint::Source), m_old_source_pos);
+ m_con->setEndPoint(EndPoint::Target, m_con->widget(EndPoint::Target), m_old_target_pos);
+}
+
+void AdjustConnectionCommand::redo()
+{
+ m_con->setEndPoint(EndPoint::Source, m_con->widget(EndPoint::Source), m_new_source_pos);
+ m_con->setEndPoint(EndPoint::Target, m_con->widget(EndPoint::Target), m_new_target_pos);
+}
+
+DeleteConnectionsCommand::DeleteConnectionsCommand(ConnectionEdit *edit,
+ const ConnectionList &con_list)
+ : CECommand(edit), m_con_list(con_list)
+{
+ setText(QApplication::translate("Command", "Delete connections"));
+}
+
+void DeleteConnectionsCommand::redo()
+{
+ foreach (Connection *con, m_con_list) {
+ const int idx = edit()->indexOfConnection(con);
+ emit edit()->aboutToRemoveConnection(con);
+ Q_ASSERT(edit()->m_con_list.contains(con));
+ edit()->setSelected(con, false);
+ con->update();
+ con->removed();
+ edit()->m_con_list.removeAll(con);
+ emit edit()->connectionRemoved(idx);
+ }
+}
+
+void DeleteConnectionsCommand::undo()
+{
+ foreach (Connection *con, m_con_list) {
+ Q_ASSERT(!edit()->m_con_list.contains(con));
+ emit edit()->aboutToAddConnection(edit()->m_con_list.size());
+ edit()->m_con_list.append(con);
+ edit()->setSelected(con, true);
+ con->update();
+ con->inserted();
+ emit edit()->connectionAdded(con);
+ }
+}
+
+class SetEndPointCommand : public CECommand
+{
+public:
+ SetEndPointCommand(ConnectionEdit *edit, Connection *con, EndPoint::Type type, QObject *object);
+ virtual void redo();
+ virtual void undo();
+private:
+ Connection *m_con;
+ const EndPoint::Type m_type;
+ QObject *m_old_widget, *m_new_widget;
+ const QPoint m_old_pos;
+ QPoint m_new_pos;
+};
+
+SetEndPointCommand::SetEndPointCommand(ConnectionEdit *edit, Connection *con,
+ EndPoint::Type type, QObject *object) :
+ CECommand(edit),
+ m_con(con),
+ m_type(type),
+ m_old_widget(con->object(type)),
+ m_new_widget(object),
+ m_old_pos(con->endPointPos(type))
+{
+ if (QWidget *widget = qobject_cast<QWidget*>(object)) {
+ m_new_pos = edit->widgetRect(widget).center();
+ }
+
+ if (m_type == EndPoint::Source)
+ setText(QApplication::translate("Command", "Change source"));
+ else
+ setText(QApplication::translate("Command", "Change target"));
+}
+
+void SetEndPointCommand::redo()
+{
+ m_con->setEndPoint(m_type, m_new_widget, m_new_pos);
+ emit edit()->connectionChanged(m_con);
+}
+
+void SetEndPointCommand::undo()
+{
+ m_con->setEndPoint(m_type, m_old_widget, m_old_pos);
+ emit edit()->connectionChanged(m_con);
+}
+
+/*******************************************************************************
+** Connection
+*/
+
+Connection::Connection(ConnectionEdit *edit) :
+ m_source_pos(QPoint(-1, -1)),
+ m_target_pos(QPoint(-1, -1)),
+ m_source(0),
+ m_target(0),
+ m_edit(edit),
+ m_visible(true)
+{
+
+}
+
+Connection::Connection(ConnectionEdit *edit, QObject *source, QObject *target) :
+ m_source_pos(QPoint(-1, -1)),
+ m_target_pos(QPoint(-1, -1)),
+ m_source(source),
+ m_target(target),
+ m_edit(edit),
+ m_visible(true)
+{
+}
+
+void Connection::setVisible(bool b)
+{
+ m_visible = b;
+}
+
+void Connection::updateVisibility()
+{
+ QWidget *source = widget(EndPoint::Source);
+ QWidget *target = widget(EndPoint::Target);
+
+ if (source == 0 || target == 0) {
+ setVisible(false);
+ return;
+ }
+
+ QWidget *w = source;
+ while (w && w->parentWidget()) {
+ if (!w->isVisibleTo(w->parentWidget())) {
+ setVisible(false);
+ return;
+ }
+ w = w->parentWidget();
+ }
+
+ w = target;
+ while (w && w->parentWidget()) {
+ if (!w->isVisibleTo(w->parentWidget())) {
+ setVisible(false);
+ return;
+ }
+ w = w->parentWidget();
+ }
+
+ setVisible(true);
+}
+
+bool Connection::isVisible() const
+{
+ return m_visible;
+}
+
+bool Connection::ground() const
+{
+ return m_target != 0 && m_target == m_edit->m_bg_widget;
+}
+
+QPoint Connection::endPointPos(EndPoint::Type type) const
+{
+ if (type == EndPoint::Source)
+ return m_source_pos;
+ else
+ return m_target_pos;
+}
+
+static QPoint lineEntryPos(const QPoint &p1, const QPoint &p2, const QRect &rect)
+{
+ QPoint result;
+
+ switch (classifyLine(p1, p2)) {
+ case CETypes::UpDir:
+ result = QPoint(p1.x(), rect.bottom());
+ break;
+ case CETypes::DownDir:
+ result = QPoint(p1.x(), rect.top());
+ break;
+ case CETypes::LeftDir:
+ result = QPoint(rect.right(), p1.y());
+ break;
+ case CETypes::RightDir:
+ result = QPoint(rect.left(), p1.y());
+ break;
+ }
+
+ return result;
+}
+
+static QPolygonF arrowHead(const QPoint &p1, const QPoint &p2)
+{
+ QPolygonF result;
+
+ switch (classifyLine(p1, p2)) {
+ case CETypes::UpDir:
+ result.append(p2 + QPoint(0, 1));
+ result.append(p2 + QPoint(LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS*2 + 1));
+ result.append(p2 + QPoint(-LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS*2 + 1));
+ break;
+ case CETypes::DownDir:
+ result.append(p2);
+ result.append(p2 + QPoint(LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS*2));
+ result.append(p2 + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS*2));
+ break;
+ case CETypes::LeftDir:
+ result.append(p2 + QPoint(1, 0));
+ result.append(p2 + QPoint(2*LINE_PROXIMITY_RADIUS + 1, -LINE_PROXIMITY_RADIUS));
+ result.append(p2 + QPoint(2*LINE_PROXIMITY_RADIUS + 1, LINE_PROXIMITY_RADIUS));
+ break;
+ case CETypes::RightDir:
+ result.append(p2);
+ result.append(p2 + QPoint(-2*LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS));
+ result.append(p2 + QPoint(-2*LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS));
+ break;
+ }
+
+ return result;
+}
+
+static CETypes::LineDir closestEdge(const QPoint &p, const QRect &r)
+{
+ CETypes::LineDir result = CETypes::UpDir;
+ int min = p.y() - r.top();
+
+ int d = p.x() - r.left();
+ if (d < min) {
+ min = d;
+ result = CETypes::LeftDir;
+ }
+
+ d = r.bottom() - p.y();
+ if (d < min) {
+ min = d;
+ result = CETypes::DownDir;
+ }
+
+ d = r.right() - p.x();
+ if (d < min) {
+ min = d;
+ result = CETypes::RightDir;
+ }
+
+ return result;
+}
+
+static bool pointAboveLine(const QPoint &l1, const QPoint &l2, const QPoint &p)
+{
+ if (l1.x() == l2.x())
+ return p.x() >= l1.x();
+ return p.y() <= l1.y() + (p.x() - l1.x())*(l2.y() - l1.y())/(l2.x() - l1.x());
+}
+
+void Connection::updateKneeList()
+{
+ const LineDir old_source_label_dir = labelDir(EndPoint::Source);
+ const LineDir old_target_label_dir = labelDir(EndPoint::Target);
+
+ QPoint s = endPointPos(EndPoint::Source);
+ QPoint t = endPointPos(EndPoint::Target);
+ const QRect sr = m_source_rect;
+ const QRect tr = m_target_rect;
+
+ m_knee_list.clear();
+ m_arrow_head.clear();
+
+ if (m_source == 0 || s == QPoint(-1, -1) || t == QPoint(-1, -1))
+ return;
+
+ const QRect r = sr | tr;
+
+ m_knee_list.append(s);
+ if (m_target == 0) {
+ m_knee_list.append(QPoint(t.x(), s.y()));
+ } else if (m_target == m_edit->m_bg_widget) {
+ m_knee_list.append(QPoint(s.x(), t.y()));
+ } else if (tr.contains(sr) || sr.contains(tr)) {
+/*
+ +------------------+
+ | +----------+ |
+ | | | |
+ | | o | |
+ | +---|------+ |
+ | | x |
+ +-----|-----|------+
+ +-----+
+
+ We find out which edge of the outer rectangle is closest to the target
+ point, and make a loop which exits and re-enters through that edge.
+*/
+ const LineDir dir = closestEdge(t, tr);
+ switch (dir) {
+ case UpDir:
+ m_knee_list.append(QPoint(s.x(), r.top() - LOOP_MARGIN));
+ m_knee_list.append(QPoint(t.x(), r.top() - LOOP_MARGIN));
+ break;
+ case DownDir:
+ m_knee_list.append(QPoint(s.x(), r.bottom() + LOOP_MARGIN));
+ m_knee_list.append(QPoint(t.x(), r.bottom() + LOOP_MARGIN));
+ break;
+ case LeftDir:
+ m_knee_list.append(QPoint(r.left() - LOOP_MARGIN, s.y()));
+ m_knee_list.append(QPoint(r.left() - LOOP_MARGIN, t.y()));
+ break;
+ case RightDir:
+ m_knee_list.append(QPoint(r.right() + LOOP_MARGIN, s.y()));
+ m_knee_list.append(QPoint(r.right() + LOOP_MARGIN, t.y()));
+ break;
+ }
+ } else {
+ if (r.height() < sr.height() + tr.height()) {
+ if ((s.y() >= tr.top() && s.y() <= tr.bottom()) || (t.y() >= sr.bottom() || t.y() <= sr.top())) {
+/*
+ +--------+
+ | | +--------+
+ | o--+---+--x |
+ | o | | |
+ +-----|--+ | |
+ +------+--x |
+ +--------+
+
+ When dragging one end point, move the other end point to the same y position,
+ if that does not cause it to exit it's rectangle.
+*/
+ if (m_edit->state() == ConnectionEdit::Dragging) {
+ if (m_edit->m_drag_end_point.type == EndPoint::Source) {
+ const QPoint p(t.x(), s.y());
+ m_knee_list.append(p);
+ if (tr.contains(p))
+ t = m_target_pos = p;
+ } else {
+ const QPoint p(s.x(), t.y());
+ m_knee_list.append(p);
+ if (sr.contains(p))
+ s = m_source_pos = p;
+ }
+ } else {
+ m_knee_list.append(QPoint(s.x(), t.y()));
+ }
+ } else {
+/*
+ +--------+
+ | o----+-------+
+ | | +---|----+
+ +--------+ | | |
+ | x |
+ +--------+
+*/
+ m_knee_list.append(QPoint(t.x(), s.y()));
+ }
+ } else if (r.width() < sr.width() + tr.width()) {
+ if ((s.x() >= tr.left() && s.x() <= tr.right()) || t.x() >= sr.right() || t.x() <= sr.left()) {
+/*
+ +--------+
+ | |
+ | o o+--+
+ +----|---+ |
+ +-|------|-+
+ | x x |
+ | |
+ +----------+
+
+ When dragging one end point, move the other end point to the same x position,
+ if that does not cause it to exit it's rectangle.
+*/
+ if (m_edit->state() == ConnectionEdit::Dragging) {
+ if (m_edit->m_drag_end_point.type == EndPoint::Source) {
+ const QPoint p(s.x(), t.y());
+ m_knee_list.append(p);
+ if (tr.contains(p))
+ t = m_target_pos = p;
+ } else {
+ const QPoint p(t.x(), s.y());
+ m_knee_list.append(p);
+ if (sr.contains(p))
+ s = m_source_pos = p;
+ }
+ } else {
+ m_knee_list.append(QPoint(t.x(), s.y()));
+ }
+ } else {
+/*
+ +--------+
+ | |
+ | o |
+ +--|-----+
+ | +--------+
+ +---+-x |
+ | |
+ +--------+
+
+*/
+ m_knee_list.append(QPoint(s.x(), t.y()));
+ }
+ } else {
+/*
+ +--------+
+ | |
+ | o o-+--------+
+ +--|-----+ |
+ | +-----|--+
+ | | x |
+ +--------+-x |
+ +--------+
+
+ The line enters the target rectangle through the closest edge.
+*/
+ if (sr.topLeft() == r.topLeft()) {
+ if (pointAboveLine(tr.topLeft(), tr.bottomRight(), t))
+ m_knee_list.append(QPoint(t.x(), s.y()));
+ else
+ m_knee_list.append(QPoint(s.x(), t.y()));
+ } else if (sr.topRight() == r.topRight()) {
+ if (pointAboveLine(tr.bottomLeft(), tr.topRight(), t))
+ m_knee_list.append(QPoint(t.x(), s.y()));
+ else
+ m_knee_list.append(QPoint(s.x(), t.y()));
+ } else if (sr.bottomRight() == r.bottomRight()) {
+ if (pointAboveLine(tr.topLeft(), tr.bottomRight(), t))
+ m_knee_list.append(QPoint(s.x(), t.y()));
+ else
+ m_knee_list.append(QPoint(t.x(), s.y()));
+ } else {
+ if (pointAboveLine(tr.bottomLeft(), tr.topRight(), t))
+ m_knee_list.append(QPoint(s.x(), t.y()));
+ else
+ m_knee_list.append(QPoint(t.x(), s.y()));
+ }
+ }
+ }
+ m_knee_list.append(t);
+
+ if (m_knee_list.size() == 2)
+ m_knee_list.clear();
+
+ trimLine();
+
+ const LineDir new_source_label_dir = labelDir(EndPoint::Source);
+ const LineDir new_target_label_dir = labelDir(EndPoint::Target);
+ if (new_source_label_dir != old_source_label_dir)
+ updatePixmap(EndPoint::Source);
+ if (new_target_label_dir != old_target_label_dir)
+ updatePixmap(EndPoint::Target);
+}
+
+void Connection::trimLine()
+{
+ if (m_source == 0 || m_source_pos == QPoint(-1, -1) || m_target_pos == QPoint(-1, -1))
+ return;
+ int cnt = m_knee_list.size();
+ if (cnt < 2)
+ return;
+
+ const QRect sr = m_source_rect;
+ const QRect tr = m_target_rect;
+
+ if (sr.contains(m_knee_list.at(1)))
+ m_knee_list.removeFirst();
+
+ cnt = m_knee_list.size();
+ if (cnt < 2)
+ return;
+
+ if (!tr.contains(sr) && tr.contains(m_knee_list.at(cnt - 2)))
+ m_knee_list.removeLast();
+
+ cnt = m_knee_list.size();
+ if (cnt < 2)
+ return;
+
+ if (sr.contains(m_knee_list.at(0)) && !sr.contains(m_knee_list.at(1)))
+ m_knee_list[0] = lineEntryPos(m_knee_list.at(1), m_knee_list.at(0), sr);
+
+ if (tr.contains(m_knee_list.at(cnt - 1)) && !tr.contains(m_knee_list.at(cnt - 2))) {
+ m_knee_list[cnt - 1]
+ = lineEntryPos(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1), tr);
+ m_arrow_head = arrowHead(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1));
+ }
+}
+
+void Connection::setSource(QObject *source, const QPoint &pos)
+{
+ if (source == m_source && m_source_pos == pos)
+ return;
+
+ update(false);
+
+ m_source = source;
+ if (QWidget *widget = qobject_cast<QWidget*>(source)) {
+ m_source_pos = pos;
+ m_source_rect = m_edit->widgetRect(widget);
+ updateKneeList();
+ }
+
+ update(false);
+}
+
+void Connection::setTarget(QObject *target, const QPoint &pos)
+{
+ if (target == m_target && m_target_pos == pos)
+ return;
+
+ update(false);
+
+ m_target = target;
+ if (QWidget *widget = qobject_cast<QWidget*>(target)) {
+ m_target_pos = pos;
+ m_target_rect = m_edit->widgetRect(widget);
+ updateKneeList();
+ }
+
+ update(false);
+}
+
+static QRect lineRect(const QPoint &a, const QPoint &b)
+{
+ const QPoint c(qMin(a.x(), b.x()), qMin(a.y(), b.y()));
+ const QPoint d(qMax(a.x(), b.x()), qMax(a.y(), b.y()));
+
+ QRect result(c, d);
+ return expand(result, LINE_PROXIMITY_RADIUS);
+}
+
+QRect Connection::groundRect() const
+{
+ if (!ground())
+ return QRect();
+ if (m_knee_list.isEmpty())
+ return QRect();
+
+ const QPoint p = m_knee_list.last();
+ return QRect(p.x() - GROUND_W/2, p.y(), GROUND_W, GROUND_H);
+}
+
+QRegion Connection::region() const
+{
+ QRegion result;
+
+ for (int i = 0; i < m_knee_list.size() - 1; ++i)
+ result = result.unite(lineRect(m_knee_list.at(i), m_knee_list.at(i + 1)));
+
+ if (!m_arrow_head.isEmpty()) {
+ QRect r = m_arrow_head.boundingRect().toRect();
+ r = expand(r, 1);
+ result = result.unite(r);
+ } else if (ground()) {
+ result = result.unite(groundRect());
+ }
+
+ result = result.unite(labelRect(EndPoint::Source));
+ result = result.unite(labelRect(EndPoint::Target));
+
+ return result;
+}
+
+void Connection::update(bool update_widgets) const
+{
+ m_edit->update(region());
+ if (update_widgets) {
+ if (m_source != 0)
+ m_edit->update(m_source_rect);
+ if (m_target != 0)
+ m_edit->update(m_target_rect);
+ }
+
+ m_edit->update(endPointRect(EndPoint::Source));
+ m_edit->update(endPointRect(EndPoint::Target));
+}
+
+void Connection::paint(QPainter *p) const
+{
+ for (int i = 0; i < m_knee_list.size() - 1; ++i)
+ p->drawLine(m_knee_list.at(i), m_knee_list.at(i + 1));
+
+ if (!m_arrow_head.isEmpty()) {
+ p->save();
+ p->setBrush(p->pen().color());
+ p->drawPolygon(m_arrow_head);
+ p->restore();
+ } else if (ground()) {
+ paintGround(p, groundRect());
+ }
+}
+
+bool Connection::contains(const QPoint &pos) const
+{
+ return region().contains(pos);
+}
+
+QRect Connection::endPointRect(EndPoint::Type type) const
+{
+ if (type == EndPoint::Source) {
+ if (m_source_pos != QPoint(-1, -1))
+ return endPointRectHelper(m_source_pos);
+ } else {
+ if (m_target_pos != QPoint(-1, -1))
+ return endPointRectHelper(m_target_pos);
+ }
+ return QRect();
+}
+
+CETypes::LineDir Connection::labelDir(EndPoint::Type type) const
+{
+ const int cnt = m_knee_list.size();
+ if (cnt < 2)
+ return RightDir;
+
+ LineDir dir;
+ if (type == EndPoint::Source)
+ dir = classifyLine(m_knee_list.at(0), m_knee_list.at(1));
+ else
+ dir = classifyLine(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1));
+
+ if (dir == LeftDir)
+ dir = RightDir;
+ if (dir == UpDir)
+ dir = DownDir;
+
+ return dir;
+}
+
+QRect Connection::labelRect(EndPoint::Type type) const
+{
+ const int cnt = m_knee_list.size();
+ if (cnt < 2)
+ return QRect();
+ const QString text = label(type);
+ if (text.isEmpty())
+ return QRect();
+
+ const QSize size = labelPixmap(type).size();
+ QPoint p1, p2;
+ if (type == EndPoint::Source) {
+ p1 = m_knee_list.at(0);
+ p2 = m_knee_list.at(1);
+ } else {
+ p1 = m_knee_list.at(cnt - 1);
+ p2 = m_knee_list.at(cnt - 2);
+ }
+ const LineDir dir = classifyLine(p1, p2);
+
+ QRect result;
+ switch (dir) {
+ case UpDir:
+ result = QRect(p1 + QPoint(-size.width()/2, 0), size);
+ break;
+ case DownDir:
+ result = QRect(p1 + QPoint(-size.width()/2, -size.height()), size);
+ break;
+ case LeftDir:
+ result = QRect(p1 + QPoint(0, -size.height()/2), size);
+ break;
+ case RightDir:
+ result = QRect(p1 + QPoint(-size.width(), -size.height()/2), size);
+ break;
+ }
+
+ return result;
+}
+
+void Connection::setLabel(EndPoint::Type type, const QString &text)
+{
+ if (text == label(type))
+ return;
+
+ if (type == EndPoint::Source)
+ m_source_label = text;
+ else
+ m_target_label = text;
+
+ updatePixmap(type);
+}
+
+void Connection::updatePixmap(EndPoint::Type type)
+{
+ QPixmap *pm = type == EndPoint::Source ? &m_source_label_pm : &m_target_label_pm;
+
+ const QString text = label(type);
+ if (text.isEmpty()) {
+ *pm = QPixmap();
+ return;
+ }
+
+ const QFontMetrics fm = m_edit->fontMetrics();
+ const QSize size = fm.size(Qt::TextSingleLine, text) + QSize(HLABEL_MARGIN*2, VLABEL_MARGIN*2);
+ *pm = QPixmap(size);
+ QColor color = m_edit->palette().color(QPalette::Normal, QPalette::Base);
+ color.setAlpha(190);
+ pm->fill(color);
+
+ QPainter p(pm);
+ p.setPen(m_edit->palette().color(QPalette::Normal, QPalette::Text));
+ p.drawText(-fm.leftBearing(text.at(0)) + HLABEL_MARGIN, fm.ascent() + VLABEL_MARGIN, text);
+ p.end();
+
+ const LineDir dir = labelDir(type);
+
+ if (dir == DownDir)
+ *pm = pm->transformed(QMatrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0));
+}
+
+void Connection::checkWidgets()
+{
+ bool changed = false;
+
+ if (QWidget *sourceWidget = qobject_cast<QWidget*>(m_source)) {
+ const QRect r = m_edit->widgetRect(sourceWidget);
+ if (r != m_source_rect) {
+ if (m_source_pos != QPoint(-1, -1) && !r.contains(m_source_pos)) {
+ QPoint offset = m_source_pos - m_source_rect.topLeft();
+ QPoint old_pos = m_source_pos;
+ m_source_pos = pointInsideRect(r, r.topLeft() + offset);
+ }
+ m_edit->update(m_source_rect);
+ m_source_rect = r;
+ changed = true;
+ }
+ }
+
+ if (QWidget *targetWidget = qobject_cast<QWidget*>(m_target)) {
+ const QRect r = m_edit->widgetRect(targetWidget);
+ if (r != m_target_rect) {
+ if (m_target_pos != QPoint(-1, -1) && !r.contains(m_target_pos)) {
+ const QPoint offset = m_target_pos - m_target_rect.topLeft();
+ const QPoint old_pos = m_target_pos;
+ m_target_pos = pointInsideRect(r, r.topLeft() + offset);
+ }
+ m_edit->update(m_target_rect);
+ m_target_rect = r;
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ update();
+ updateKneeList();
+ update();
+ }
+}
+
+/*******************************************************************************
+** ConnectionEdit
+*/
+
+ConnectionEdit::ConnectionEdit(QWidget *parent, QDesignerFormWindowInterface *form) :
+ QWidget(parent),
+ m_bg_widget(0),
+ m_undo_stack(form->commandHistory()),
+ m_enable_update_background(false),
+ m_tmp_con(0),
+ m_start_connection_on_drag(true),
+ m_widget_under_mouse(0),
+ m_inactive_color(Qt::blue),
+ m_active_color(Qt::red)
+{
+ setAttribute(Qt::WA_MouseTracking, true);
+ setFocusPolicy(Qt::ClickFocus);
+
+ connect(form, SIGNAL(widgetRemoved(QWidget*)), this, SLOT(widgetRemoved(QWidget*)));
+ connect(form, SIGNAL(objectRemoved(QObject*)), this, SLOT(objectRemoved(QObject*)));
+}
+
+ConnectionEdit::~ConnectionEdit()
+{
+ qDeleteAll(m_con_list);
+}
+
+void ConnectionEdit::clear()
+{
+ m_con_list.clear();
+ m_sel_con_set.clear();
+ m_bg_widget = 0;
+ m_widget_under_mouse = 0;
+ m_tmp_con = 0;
+}
+
+void ConnectionEdit::setBackground(QWidget *background)
+{
+ if (background == m_bg_widget) {
+ // nothing to do
+ return;
+ }
+
+ m_bg_widget = background;
+ updateBackground();
+}
+
+void ConnectionEdit::enableUpdateBackground(bool enable)
+{
+ m_enable_update_background = enable;
+ if (enable)
+ updateBackground();
+}
+
+void ConnectionEdit::updateBackground()
+{
+ // Might happen while reloading a form.
+ if (m_bg_widget == 0)
+ return;
+
+ if (!m_enable_update_background)
+ return;
+
+ foreach(Connection *c, m_con_list)
+ c->updateVisibility();
+
+ updateLines();
+ update();
+}
+
+QWidget *ConnectionEdit::widgetAt(const QPoint &pos) const
+{
+ if (m_bg_widget == 0)
+ return 0;
+ QWidget *widget = m_bg_widget->childAt(pos);
+ if (widget == 0)
+ widget = m_bg_widget;
+
+ return widget;
+}
+
+
+QRect ConnectionEdit::widgetRect(QWidget *w) const
+{
+ if (w == 0)
+ return QRect();
+ QRect r = w->geometry();
+ QPoint pos = w->mapToGlobal(QPoint(0, 0));
+ pos = mapFromGlobal(pos);
+ r.moveTopLeft(pos);
+ return r;
+}
+
+ConnectionEdit::State ConnectionEdit::state() const
+{
+ if (m_tmp_con != 0)
+ return Connecting;
+ if (!m_drag_end_point.isNull())
+ return Dragging;
+ return Editing;
+}
+
+void ConnectionEdit::paintLabel(QPainter *p, EndPoint::Type type, Connection *con)
+{
+ if (con->label(type).isEmpty())
+ return;
+
+ const bool heavy = selected(con) || con == m_tmp_con;
+ p->setPen(heavy ? m_active_color : m_inactive_color);
+ p->setBrush(Qt::NoBrush);
+ const QRect r = con->labelRect(type);
+ p->drawPixmap(r.topLeft(), con->labelPixmap(type));
+ p->drawRect(fixRect(r));
+}
+
+void ConnectionEdit::paintConnection(QPainter *p, Connection *con,
+ WidgetSet *heavy_highlight_set,
+ WidgetSet *light_highlight_set) const
+{
+ QWidget *source = con->widget(EndPoint::Source);
+ QWidget *target = con->widget(EndPoint::Target);
+
+ const bool heavy = selected(con) || con == m_tmp_con;
+ WidgetSet *set = heavy ? heavy_highlight_set : light_highlight_set;
+ p->setPen(heavy ? m_active_color : m_inactive_color);
+ con->paint(p);
+
+ if (source != 0 && source != m_bg_widget)
+ set->insert(source, source);
+
+ if (target != 0 && target != m_bg_widget)
+ set->insert(target, target);
+}
+
+void ConnectionEdit::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ p.setClipRegion(e->region());
+
+ WidgetSet heavy_highlight_set, light_highlight_set;
+
+ foreach (Connection *con, m_con_list) {
+ if (!con->isVisible())
+ continue;
+
+ paintConnection(&p, con, &heavy_highlight_set, &light_highlight_set);
+ }
+
+ if (m_tmp_con != 0)
+ paintConnection(&p, m_tmp_con, &heavy_highlight_set, &light_highlight_set);
+
+ if (!m_widget_under_mouse.isNull() && m_widget_under_mouse != m_bg_widget)
+ heavy_highlight_set.insert(m_widget_under_mouse, m_widget_under_mouse);
+
+ QColor c = m_active_color;
+ p.setPen(c);
+ c.setAlpha(BG_ALPHA);
+ p.setBrush(c);
+
+ foreach (QWidget *w, heavy_highlight_set) {
+ p.drawRect(fixRect(widgetRect(w)));
+ light_highlight_set.remove(w);
+ }
+
+ c = m_inactive_color;
+ p.setPen(c);
+ c.setAlpha(BG_ALPHA);
+ p.setBrush(c);
+
+ foreach (QWidget *w, light_highlight_set)
+ p.drawRect(fixRect(widgetRect(w)));
+
+ p.setBrush(palette().color(QPalette::Base));
+ p.setPen(palette().color(QPalette::Text));
+ foreach (Connection *con, m_con_list) {
+ if (!con->isVisible())
+ continue;
+
+ paintLabel(&p, EndPoint::Source, con);
+ paintLabel(&p, EndPoint::Target, con);
+ }
+
+ p.setPen(m_active_color);
+ p.setBrush(m_active_color);
+
+ foreach (Connection *con, m_con_list) {
+ if (!selected(con) || !con->isVisible())
+ continue;
+
+ paintEndPoint(&p, con->endPointPos(EndPoint::Source));
+
+ if (con->widget(EndPoint::Target) != 0)
+ paintEndPoint(&p, con->endPointPos(EndPoint::Target));
+ }
+}
+
+void ConnectionEdit::abortConnection()
+{
+ m_tmp_con->update();
+ delete m_tmp_con;
+ m_tmp_con = 0;
+#ifndef QT_NO_CURSOR
+ setCursor(QCursor());
+#endif
+ if (m_widget_under_mouse == m_bg_widget)
+ m_widget_under_mouse = 0;
+}
+
+void ConnectionEdit::mousePressEvent(QMouseEvent *e)
+{
+ // Right click only to cancel
+ const Qt::MouseButton button = e->button();
+ const State cstate = state();
+ if (button != Qt::LeftButton && !(button == Qt::RightButton && cstate == Connecting)) {
+ QWidget::mousePressEvent(e);
+ return;
+ }
+
+ e->accept();
+ // Prefer a non-background widget over the connection,
+ // otherwise, widgets covered by the connection labels cannot be accessed
+ Connection *con_under_mouse = 0;
+ if (!m_widget_under_mouse || m_widget_under_mouse == m_bg_widget)
+ con_under_mouse = connectionAt(e->pos());
+
+ m_start_connection_on_drag = false;
+ switch (cstate) {
+ case Connecting:
+ if (button == Qt::RightButton)
+ abortConnection();
+ break;
+ case Dragging:
+ break;
+ case Editing:
+ if (!m_end_point_under_mouse.isNull()) {
+ if (!(e->modifiers() & Qt::ShiftModifier)) {
+ startDrag(m_end_point_under_mouse, e->pos());
+ }
+ } else if (con_under_mouse != 0) {
+ if (!(e->modifiers() & Qt::ShiftModifier)) {
+ selectNone();
+ setSelected(con_under_mouse, true);
+ } else {
+ setSelected(con_under_mouse, !selected(con_under_mouse));
+ }
+ } else {
+ if (!(e->modifiers() & Qt::ShiftModifier)) {
+ selectNone();
+ if (!m_widget_under_mouse.isNull())
+ m_start_connection_on_drag = true;
+ }
+ }
+ break;
+ }
+}
+
+void ConnectionEdit::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton) {
+ QWidget::mouseDoubleClickEvent(e);
+ return;
+ }
+
+ e->accept();
+ switch (state()) {
+ case Connecting:
+ abortConnection();
+ break;
+ case Dragging:
+ break;
+ case Editing:
+ if (!m_widget_under_mouse.isNull()) {
+ emit widgetActivated(m_widget_under_mouse);
+ } else if (m_sel_con_set.size() == 1) {
+ Connection *con = m_sel_con_set.keys().first();
+ modifyConnection(con);
+ }
+ break;
+ }
+
+}
+
+void ConnectionEdit::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton) {
+ QWidget::mouseReleaseEvent(e);
+ return;
+ }
+ e->accept();
+
+ switch (state()) {
+ case Connecting:
+ if (m_widget_under_mouse.isNull())
+ abortConnection();
+ else
+ endConnection(m_widget_under_mouse, e->pos());
+#ifndef QT_NO_CURSOR
+ setCursor(QCursor());
+#endif
+ break;
+ case Editing:
+ break;
+ case Dragging:
+ endDrag(e->pos());
+ break;
+ }
+}
+
+
+void ConnectionEdit::findObjectsUnderMouse(const QPoint &pos)
+{
+ Connection *con_under_mouse = connectionAt(pos);
+
+ QWidget *w = widgetAt(pos);
+ // Prefer a non-background widget over the connection,
+ // otherwise, widgets covered by the connection labels cannot be accessed
+ if (w == m_bg_widget && con_under_mouse)
+ w = 0;
+ else
+ con_under_mouse = 0;
+
+ if (w != m_widget_under_mouse) {
+ if (!m_widget_under_mouse.isNull())
+ update(widgetRect(m_widget_under_mouse));
+ m_widget_under_mouse = w;
+ if (!m_widget_under_mouse.isNull())
+ update(widgetRect(m_widget_under_mouse));
+ }
+
+ const EndPoint hs = endPointAt(pos);
+ if (hs != m_end_point_under_mouse) {
+#ifndef QT_NO_CURSOR
+ if (m_end_point_under_mouse.isNull())
+ setCursor(Qt::PointingHandCursor);
+ else
+ setCursor(QCursor());
+#endif
+ m_end_point_under_mouse = hs;
+ }
+}
+
+void ConnectionEdit::mouseMoveEvent(QMouseEvent *e)
+{
+ findObjectsUnderMouse(e->pos());
+ switch (state()) {
+ case Connecting:
+ continueConnection(m_widget_under_mouse, e->pos());
+ break;
+ case Editing:
+ if ((e->buttons() & Qt::LeftButton)
+ && m_start_connection_on_drag
+ && !m_widget_under_mouse.isNull()) {
+ m_start_connection_on_drag = false;
+ startConnection(m_widget_under_mouse, e->pos());
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::CrossCursor);
+#endif
+ }
+ break;
+ case Dragging:
+ continueDrag(e->pos());
+ break;
+ }
+
+ e->accept();
+}
+
+void ConnectionEdit::keyPressEvent(QKeyEvent *e)
+{
+ switch (e->key()) {
+ case Qt::Key_Delete:
+ if (state() == Editing)
+ deleteSelected();
+ break;
+ case Qt::Key_Escape:
+ if (state() == Connecting)
+ abortConnection();
+ break;
+ }
+
+ e->accept();
+}
+
+void ConnectionEdit::startConnection(QWidget *source, const QPoint &pos)
+{
+ Q_ASSERT(m_tmp_con == 0);
+
+ m_tmp_con = new Connection(this);
+ m_tmp_con->setEndPoint(EndPoint::Source, source, pos);
+}
+
+void ConnectionEdit::endConnection(QWidget *target, const QPoint &pos)
+{
+ Q_ASSERT(m_tmp_con != 0);
+
+ m_tmp_con->setEndPoint(EndPoint::Target, target, pos);
+
+ QWidget *source = m_tmp_con->widget(EndPoint::Source);
+ Q_ASSERT(source != 0);
+ Q_ASSERT(target != 0);
+ setEnabled(false);
+ Connection *new_con = createConnection(source, target);
+ setEnabled(true);
+ if (new_con != 0) {
+ new_con->setEndPoint(EndPoint::Source, source, m_tmp_con->endPointPos(EndPoint::Source));
+ new_con->setEndPoint(EndPoint::Target, target, m_tmp_con->endPointPos(EndPoint::Target));
+ m_undo_stack->push(new AddConnectionCommand(this, new_con));
+ emit connectionChanged(new_con);
+ }
+
+ delete m_tmp_con;
+ m_tmp_con = 0;
+
+ findObjectsUnderMouse(mapFromGlobal(QCursor::pos()));
+}
+
+void ConnectionEdit::continueConnection(QWidget *target, const QPoint &pos)
+{
+ Q_ASSERT(m_tmp_con != 0);
+
+ m_tmp_con->setEndPoint(EndPoint::Target, target, pos);
+}
+
+void ConnectionEdit::modifyConnection(Connection *)
+{
+}
+
+Connection *ConnectionEdit::createConnection(QWidget *source, QWidget *target)
+{
+ Connection *con = new Connection(this, source, target);
+ return con;
+}
+
+// Find all connections which in which a sequence of objects is involved
+template <class ObjectIterator>
+static ConnectionEdit::ConnectionSet findConnectionsOf(const ConnectionEdit::ConnectionList &cl, ObjectIterator oi1, const ObjectIterator &oi2)
+{
+ ConnectionEdit::ConnectionSet rc;
+
+ const ConnectionEdit::ConnectionList::const_iterator ccend = cl.constEnd();
+ for ( ; oi1 != oi2; ++oi1) {
+ for (ConnectionEdit::ConnectionList::const_iterator cit = cl.constBegin(); cit != ccend; ++cit) {
+ Connection *con = *cit;
+ if (con->object(ConnectionEdit::EndPoint::Source) == *oi1 || con->object(ConnectionEdit::EndPoint::Target) == *oi1)
+ rc.insert(con, con);
+ }
+ }
+ return rc;
+}
+
+void ConnectionEdit::widgetRemoved(QWidget *widget)
+{
+ // Remove all connections of that widget and its children.
+ if (m_con_list.empty())
+ return;
+
+ QWidgetList child_list = qFindChildren<QWidget*>(widget);
+ child_list.prepend(widget);
+
+ const ConnectionSet remove_set = findConnectionsOf(m_con_list, child_list.constBegin(), child_list.constEnd());
+
+ if (!remove_set.isEmpty())
+ m_undo_stack->push(new DeleteConnectionsCommand(this, remove_set.keys()));
+
+ updateBackground();
+}
+
+void ConnectionEdit::objectRemoved(QObject *o)
+{
+ // Remove all connections of that object and its children (in case of action groups).
+ if (m_con_list.empty())
+ return;
+
+ QObjectList child_list = o->children();
+ child_list.prepend(o);
+ const ConnectionSet remove_set = findConnectionsOf(m_con_list, child_list.constBegin(), child_list.constEnd());
+ if (!remove_set.isEmpty())
+ m_undo_stack->push(new DeleteConnectionsCommand(this, remove_set.keys()));
+
+ updateBackground();
+}
+
+void ConnectionEdit::setSelected(Connection *con, bool sel)
+{
+ if (!con || sel == m_sel_con_set.contains(con))
+ return;
+
+ if (sel) {
+ m_sel_con_set.insert(con, con);
+ emit connectionSelected(con);
+ } else {
+ m_sel_con_set.remove(con);
+ }
+
+ con->update();
+}
+
+bool ConnectionEdit::selected(const Connection *con) const
+{
+ return m_sel_con_set.contains(const_cast<Connection*>(con));
+}
+
+void ConnectionEdit::selectNone()
+{
+ foreach (Connection *con, m_sel_con_set)
+ con->update();
+
+ m_sel_con_set.clear();
+}
+
+void ConnectionEdit::selectAll()
+{
+ if (m_sel_con_set.size() == m_con_list.size())
+ return;
+ foreach (Connection *con, m_con_list)
+ setSelected(con, true);
+}
+
+Connection *ConnectionEdit::connectionAt(const QPoint &pos) const
+{
+ foreach (Connection *con, m_con_list) {
+ if (con->contains(pos))
+ return con;
+ }
+ return 0;
+}
+
+CETypes::EndPoint ConnectionEdit::endPointAt(const QPoint &pos) const
+{
+ foreach (Connection *con, m_con_list) {
+ if (!selected(con))
+ continue;
+ const QRect sr = con->endPointRect(EndPoint::Source);
+ const QRect tr = con->endPointRect(EndPoint::Target);
+
+ if (sr.contains(pos))
+ return EndPoint(con, EndPoint::Source);
+ if (tr.contains(pos))
+ return EndPoint(con, EndPoint::Target);
+ }
+ return EndPoint();
+}
+
+void ConnectionEdit::startDrag(const EndPoint &end_point, const QPoint &pos)
+{
+ Q_ASSERT(m_drag_end_point.isNull());
+ m_drag_end_point = end_point;
+ m_old_source_pos = m_drag_end_point.con->endPointPos(EndPoint::Source);
+ m_old_target_pos = m_drag_end_point.con->endPointPos(EndPoint::Target);
+ adjustHotSopt(m_drag_end_point, pos);
+}
+
+void ConnectionEdit::continueDrag(const QPoint &pos)
+{
+ Q_ASSERT(!m_drag_end_point.isNull());
+ adjustHotSopt(m_drag_end_point, pos);
+}
+
+void ConnectionEdit::endDrag(const QPoint &pos)
+{
+ Q_ASSERT(!m_drag_end_point.isNull());
+ adjustHotSopt(m_drag_end_point, pos);
+
+ Connection *con = m_drag_end_point.con;
+ const QPoint new_source_pos = con->endPointPos(EndPoint::Source);
+ const QPoint new_target_pos = con->endPointPos(EndPoint::Target);
+ m_undo_stack->push(new AdjustConnectionCommand(this, con, m_old_source_pos, m_old_target_pos,
+ new_source_pos, new_target_pos));
+
+ m_drag_end_point = EndPoint();
+}
+
+void ConnectionEdit::adjustHotSopt(const EndPoint &end_point, const QPoint &pos)
+{
+ QWidget *w = end_point.con->widget(end_point.type);
+ end_point.con->setEndPoint(end_point.type, w, pointInsideRect(widgetRect(w), pos));
+}
+
+void ConnectionEdit::deleteSelected()
+{
+ if (m_sel_con_set.isEmpty())
+ return;
+ m_undo_stack->push(new DeleteConnectionsCommand(this, m_sel_con_set.keys()));
+}
+
+void ConnectionEdit::addConnection(Connection *con)
+{
+ m_con_list.append(con);
+}
+
+void ConnectionEdit::updateLines()
+{
+ foreach (Connection *con, m_con_list)
+ con->checkWidgets();
+}
+
+void ConnectionEdit::resizeEvent(QResizeEvent *e)
+{
+ updateBackground();
+ QWidget::resizeEvent(e);
+}
+
+void ConnectionEdit::setSource(Connection *con, const QString &obj_name)
+{
+ QObject *object = 0;
+ if (!obj_name.isEmpty()) {
+ object = qFindChild<QObject*>(m_bg_widget, obj_name);
+ if (object == 0 && m_bg_widget->objectName() == obj_name)
+ object = m_bg_widget;
+
+ if (object == con->object(EndPoint::Source))
+ return;
+ }
+ m_undo_stack->push(new SetEndPointCommand(this, con, EndPoint::Source, object));
+}
+
+void ConnectionEdit::setTarget(Connection *con, const QString &obj_name)
+{
+ QObject *object = 0;
+ if (!obj_name.isEmpty()) {
+ object = qFindChild<QObject*>(m_bg_widget, obj_name);
+ if (object == 0 && m_bg_widget->objectName() == obj_name)
+ object = m_bg_widget;
+
+ if (object == con->object(EndPoint::Target))
+ return;
+ }
+ m_undo_stack->push(new SetEndPointCommand(this, con, EndPoint::Target, object));
+}
+
+Connection *ConnectionEdit::takeConnection(Connection *con)
+{
+ if (!m_con_list.contains(con))
+ return 0;
+ m_con_list.removeAll(con);
+ return con;
+}
+
+void ConnectionEdit::clearNewlyAddedConnection()
+{
+ delete m_tmp_con;
+ m_tmp_con = 0;
+}
+
+void ConnectionEdit::createContextMenu(QMenu &menu)
+{
+ // Select
+ QAction *selectAllAction = menu.addAction(tr("Select All"));
+ selectAllAction->setEnabled(connectionList().size());
+ connect(selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll()));
+ QAction *deselectAllAction = menu.addAction(tr("Deselect All"));
+ deselectAllAction->setEnabled(selection().size());
+ connect(deselectAllAction, SIGNAL(triggered()), this, SLOT(selectNone()));
+ menu.addSeparator();
+ // Delete
+ QAction *deleteAction = menu.addAction(tr("Delete"));
+ deleteAction->setShortcut(QKeySequence::Delete);
+ deleteAction->setEnabled(!selection().isEmpty());
+ connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelected()));
+}
+
+void ConnectionEdit::contextMenuEvent(QContextMenuEvent * event)
+{
+ QMenu menu;
+ createContextMenu(menu);
+ menu.exec(event->globalPos());
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/connectionedit_p.h b/tools/designer/src/lib/shared/connectionedit_p.h
new file mode 100644
index 0000000000..c4f735aac3
--- /dev/null
+++ b/tools/designer/src/lib/shared/connectionedit_p.h
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef CONNECTIONEDIT_H
+#define CONNECTIONEDIT_H
+
+#include "shared_global_p.h"
+
+#include <QtCore/QMultiMap>
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+
+#include <QtGui/QWidget>
+#include <QtGui/QPixmap>
+#include <QtGui/QPolygonF>
+
+#include <QtGui/QUndoCommand>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QUndoStack;
+class QMenu;
+
+namespace qdesigner_internal {
+
+class Connection;
+class ConnectionEdit;
+
+class QDESIGNER_SHARED_EXPORT CETypes
+{
+public:
+ typedef QList<Connection*> ConnectionList;
+ typedef QMap<Connection*, Connection*> ConnectionSet;
+ typedef QMap<QWidget*, QWidget*> WidgetSet;
+
+ class EndPoint {
+ public:
+ enum Type { Source, Target };
+ EndPoint(Connection *_con = 0, Type _type = Source) : con(_con), type(_type) {}
+ bool isNull() const { return con == 0; }
+ bool operator == (const EndPoint &other) const { return con == other.con && type == other.type; }
+ bool operator != (const EndPoint &other) const { return !operator == (other); }
+ Connection *con;
+ Type type;
+ };
+ enum LineDir { UpDir = 0, DownDir, RightDir, LeftDir };
+};
+
+class QDESIGNER_SHARED_EXPORT Connection : public CETypes
+{
+public:
+ explicit Connection(ConnectionEdit *edit);
+ explicit Connection(ConnectionEdit *edit, QObject *source, QObject *target);
+ virtual ~Connection() {}
+
+ QObject *object(EndPoint::Type type) const
+ {
+ return (type == EndPoint::Source ? m_source : m_target);
+ }
+
+ QWidget *widget(EndPoint::Type type) const
+ {
+ return qobject_cast<QWidget*>(object(type));
+ }
+
+ QPoint endPointPos(EndPoint::Type type) const;
+ QRect endPointRect(EndPoint::Type) const;
+ void setEndPoint(EndPoint::Type type, QObject *w, const QPoint &pos)
+ { type == EndPoint::Source ? setSource(w, pos) : setTarget(w, pos); }
+
+ bool isVisible() const;
+ virtual void updateVisibility();
+ void setVisible(bool b);
+
+ virtual QRegion region() const;
+ bool contains(const QPoint &pos) const;
+ virtual void paint(QPainter *p) const;
+
+ void update(bool update_widgets = true) const;
+ void checkWidgets();
+
+ QString label(EndPoint::Type type) const
+ { return type == EndPoint::Source ? m_source_label : m_target_label; }
+ void setLabel(EndPoint::Type type, const QString &text);
+ QRect labelRect(EndPoint::Type type) const;
+ QPixmap labelPixmap(EndPoint::Type type) const
+ { return type == EndPoint::Source ? m_source_label_pm : m_target_label_pm; }
+
+ ConnectionEdit *edit() const { return m_edit; }
+
+ virtual void inserted() {}
+ virtual void removed() {}
+
+private:
+ QPoint m_source_pos, m_target_pos;
+ QObject *m_source, *m_target;
+ QList<QPoint> m_knee_list;
+ QPolygonF m_arrow_head;
+ ConnectionEdit *m_edit;
+ QString m_source_label, m_target_label;
+ QPixmap m_source_label_pm, m_target_label_pm;
+ QRect m_source_rect, m_target_rect;
+ bool m_visible;
+
+ void setSource(QObject *source, const QPoint &pos);
+ void setTarget(QObject *target, const QPoint &pos);
+ void updateKneeList();
+ void trimLine();
+ void updatePixmap(EndPoint::Type type);
+ LineDir labelDir(EndPoint::Type type) const;
+ bool ground() const;
+ QRect groundRect() const;
+};
+
+class QDESIGNER_SHARED_EXPORT ConnectionEdit : public QWidget, public CETypes
+{
+ Q_OBJECT
+public:
+ ConnectionEdit(QWidget *parent, QDesignerFormWindowInterface *form);
+ virtual ~ConnectionEdit();
+
+ inline const QPointer<QWidget> &background() const { return m_bg_widget; }
+
+ void setSelected(Connection *con, bool sel);
+ bool selected(const Connection *con) const;
+
+ int connectionCount() const { return m_con_list.size(); }
+ Connection *connection(int i) const { return m_con_list.at(i); }
+ int indexOfConnection(Connection *con) const { return m_con_list.indexOf(con); }
+
+ virtual void setSource(Connection *con, const QString &obj_name);
+ virtual void setTarget(Connection *con, const QString &obj_name);
+
+ QUndoStack *undoStack() const { return m_undo_stack; }
+
+ void clear();
+
+ void showEvent(QShowEvent * /*e*/)
+ {
+ updateBackground();
+ }
+
+signals:
+ void aboutToAddConnection(int idx);
+ void connectionAdded(Connection *con);
+ void aboutToRemoveConnection(Connection *con);
+ void connectionRemoved(int idx);
+ void connectionSelected(Connection *con);
+ void widgetActivated(QWidget *wgt);
+ void connectionChanged(Connection *con);
+
+public slots:
+ void selectNone();
+ void selectAll();
+ virtual void deleteSelected();
+ virtual void setBackground(QWidget *background);
+ virtual void updateBackground();
+ virtual void widgetRemoved(QWidget *w);
+ virtual void objectRemoved(QObject *o);
+
+ void updateLines();
+ void enableUpdateBackground(bool enable);
+
+protected:
+ virtual void paintEvent(QPaintEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void contextMenuEvent(QContextMenuEvent * event);
+
+ virtual Connection *createConnection(QWidget *source, QWidget *target);
+ virtual void modifyConnection(Connection *con);
+
+ virtual QWidget *widgetAt(const QPoint &pos) const;
+ virtual void createContextMenu(QMenu &menu);
+ void addConnection(Connection *con);
+ QRect widgetRect(QWidget *w) const;
+
+ enum State { Editing, Connecting, Dragging };
+ State state() const;
+
+ virtual void endConnection(QWidget *target, const QPoint &pos);
+
+ const ConnectionList &connectionList() const { return m_con_list; }
+ const ConnectionSet &selection() const { return m_sel_con_set; }
+ Connection *takeConnection(Connection *con);
+ Connection *newlyAddedConnection() { return m_tmp_con; }
+ void clearNewlyAddedConnection();
+
+ void findObjectsUnderMouse(const QPoint &pos);
+
+private:
+ void startConnection(QWidget *source, const QPoint &pos);
+ void continueConnection(QWidget *target, const QPoint &pos);
+ void abortConnection();
+
+ void startDrag(const EndPoint &end_point, const QPoint &pos);
+ void continueDrag(const QPoint &pos);
+ void endDrag(const QPoint &pos);
+ void adjustHotSopt(const EndPoint &end_point, const QPoint &pos);
+ Connection *connectionAt(const QPoint &pos) const;
+ EndPoint endPointAt(const QPoint &pos) const;
+ void paintConnection(QPainter *p, Connection *con,
+ WidgetSet *heavy_highlight_set,
+ WidgetSet *light_highlight_set) const;
+ void paintLabel(QPainter *p, EndPoint::Type type, Connection *con);
+
+
+ QPointer<QWidget> m_bg_widget;
+ QUndoStack *m_undo_stack;
+ bool m_enable_update_background;
+
+ Connection *m_tmp_con; // the connection we are currently editing
+ ConnectionList m_con_list;
+ bool m_start_connection_on_drag;
+ EndPoint m_end_point_under_mouse;
+ QPointer<QWidget> m_widget_under_mouse;
+
+ EndPoint m_drag_end_point;
+ QPoint m_old_source_pos, m_old_target_pos;
+ ConnectionSet m_sel_con_set;
+ const QColor m_inactive_color;
+ const QColor m_active_color;
+
+private:
+ friend class Connection;
+ friend class AddConnectionCommand;
+ friend class DeleteConnectionsCommand;
+ friend class SetEndPointCommand;
+};
+
+class QDESIGNER_SHARED_EXPORT CECommand : public QUndoCommand, public CETypes
+{
+public:
+ explicit CECommand(ConnectionEdit *edit)
+ : m_edit(edit) {}
+
+ virtual bool mergeWith(const QUndoCommand *) { return false; }
+
+ ConnectionEdit *edit() const { return m_edit; }
+
+private:
+ ConnectionEdit *m_edit;
+};
+
+class QDESIGNER_SHARED_EXPORT AddConnectionCommand : public CECommand
+{
+public:
+ AddConnectionCommand(ConnectionEdit *edit, Connection *con);
+ virtual void redo();
+ virtual void undo();
+private:
+ Connection *m_con;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteConnectionsCommand : public CECommand
+{
+public:
+ DeleteConnectionsCommand(ConnectionEdit *edit, const ConnectionList &con_list);
+ virtual void redo();
+ virtual void undo();
+private:
+ ConnectionList m_con_list;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // CONNECTIONEDIT_H
diff --git a/tools/designer/src/lib/shared/csshighlighter.cpp b/tools/designer/src/lib/shared/csshighlighter.cpp
new file mode 100644
index 0000000000..d5e045bfd9
--- /dev/null
+++ b/tools/designer/src/lib/shared/csshighlighter.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::StyleSheetEditorDialog
+*/
+
+#include "csshighlighter_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+CssHighlighter::CssHighlighter(QTextDocument *document)
+: QSyntaxHighlighter(document)
+{
+}
+
+void CssHighlighter::highlightBlock(const QString& text)
+{
+ enum Token { ALNUM, LBRACE, RBRACE, COLON, SEMICOLON, COMMA, QUOTE, SLASH, STAR };
+ static const int transitions[10][9] = {
+ { Selector, Property, Selector, Pseudo, Property, Selector, Quote, MaybeComment, Selector }, // Selector
+ { Property, Property, Selector, Value, Property, Property, Quote, MaybeComment, Property }, // Property
+ { Value, Property, Selector, Value, Property, Value, Quote, MaybeComment, Value }, // Value
+ { Pseudo1, Property, Selector, Pseudo2, Selector, Selector, Quote, MaybeComment, Pseudo }, // Pseudo
+ { Pseudo1, Property, Selector, Pseudo, Selector, Selector, Quote, MaybeComment, Pseudo1 }, // Pseudo1
+ { Pseudo2, Property, Selector, Pseudo, Selector, Selector, Quote, MaybeComment, Pseudo2 }, // Pseudo2
+ { Quote, Quote, Quote, Quote, Quote, Quote, -1, Quote, Quote }, // Quote
+ { -1, -1, -1, -1, -1, -1, -1, -1, Comment }, // MaybeComment
+ { Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment, MaybeCommentEnd }, // Comment
+ { Comment, Comment, Comment, Comment, Comment, Comment, Comment, -1, MaybeCommentEnd } // MaybeCommentEnd
+ };
+
+ int lastIndex = 0;
+ bool lastWasSlash = false;
+ int state = previousBlockState(), save_state;
+ if (state == -1) {
+ // As long as the text is empty, leave the state undetermined
+ if (text.isEmpty()) {
+ setCurrentBlockState(-1);
+ return;
+ }
+ // The initial state is based on the precense of a : and the absense of a {.
+ // This is because Qt style sheets support both a full stylesheet as well as
+ // an inline form with just properties.
+ state = save_state = (text.indexOf(QLatin1Char(':')) > -1 &&
+ text.indexOf(QLatin1Char('{')) == -1) ? Property : Selector;
+ } else {
+ save_state = state>>16;
+ state &= 0x00ff;
+ }
+
+ if (state == MaybeCommentEnd) {
+ state = Comment;
+ } else if (state == MaybeComment) {
+ state = save_state;
+ }
+
+ for (int i = 0; i < text.length(); i++) {
+ int token = ALNUM;
+ const QChar c = text.at(i);
+ const char a = c.toAscii();
+
+ if (state == Quote) {
+ if (a == '\\') {
+ lastWasSlash = true;
+ } else {
+ if (a == '\"' && !lastWasSlash) {
+ token = QUOTE;
+ }
+ lastWasSlash = false;
+ }
+ } else {
+ switch (a) {
+ case '{': token = LBRACE; break;
+ case '}': token = RBRACE; break;
+ case ':': token = COLON; break;
+ case ';': token = SEMICOLON; break;
+ case ',': token = COMMA; break;
+ case '\"': token = QUOTE; break;
+ case '/': token = SLASH; break;
+ case '*': token = STAR; break;
+ default: break;
+ }
+ }
+
+ int new_state = transitions[state][token];
+
+ if (new_state != state) {
+ bool include_token = new_state == MaybeCommentEnd || (state == MaybeCommentEnd && new_state!= Comment)
+ || state == Quote;
+ highlight(text, lastIndex, i-lastIndex+include_token, state);
+
+ if (new_state == Comment) {
+ lastIndex = i-1; // include the slash and star
+ } else {
+ lastIndex = i + ((token == ALNUM || new_state == Quote) ? 0 : 1);
+ }
+ }
+
+ if (new_state == -1) {
+ state = save_state;
+ } else if (state <= Pseudo2) {
+ save_state = state;
+ state = new_state;
+ } else {
+ state = new_state;
+ }
+ }
+
+ highlight(text, lastIndex, text.length() - lastIndex, state);
+ setCurrentBlockState(state + (save_state<<16));
+}
+
+void CssHighlighter::highlight(const QString &text, int start, int length, int state)
+{
+ if (start >= text.length() || length <= 0)
+ return;
+
+ QTextCharFormat format;
+
+ switch (state) {
+ case Selector:
+ setFormat(start, length, Qt::darkRed);
+ break;
+ case Property:
+ setFormat(start, length, Qt::blue);
+ break;
+ case Value:
+ setFormat(start, length, Qt::black);
+ break;
+ case Pseudo1:
+ setFormat(start, length, Qt::darkRed);
+ break;
+ case Pseudo2:
+ setFormat(start, length, Qt::darkRed);
+ break;
+ case Quote:
+ setFormat(start, length, Qt::darkMagenta);
+ break;
+ case Comment:
+ case MaybeCommentEnd:
+ format.setForeground(Qt::darkGreen);
+ setFormat(start, length, format);
+ break;
+ default:
+ break;
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/csshighlighter_p.h b/tools/designer/src/lib/shared/csshighlighter_p.h
new file mode 100644
index 0000000000..fa671ea70e
--- /dev/null
+++ b/tools/designer/src/lib/shared/csshighlighter_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef CSSHIGHLIGHTER_H
+#define CSSHIGHLIGHTER_H
+
+#include <QtGui/QSyntaxHighlighter>
+#include "shared_global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT CssHighlighter : public QSyntaxHighlighter
+{
+ Q_OBJECT
+public:
+ explicit CssHighlighter(QTextDocument *document);
+
+protected:
+ void highlightBlock(const QString&);
+ void highlight(const QString&, int, int, int/*State*/);
+
+private:
+ enum State { Selector, Property, Value, Pseudo, Pseudo1, Pseudo2, Quote,
+ MaybeComment, Comment, MaybeCommentEnd };
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // CSSHIGHLIGHTER_H
diff --git a/tools/designer/src/lib/shared/defaultgradients.xml b/tools/designer/src/lib/shared/defaultgradients.xml
new file mode 100644
index 0000000000..70559ad12d
--- /dev/null
+++ b/tools/designer/src/lib/shared/defaultgradients.xml
@@ -0,0 +1,498 @@
+<gradients>
+ <gradient name="BlackWhite" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="1" endY="0" >
+ <stopData position="0" >
+ <colorData g="0" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Czech" >
+ <gradientData centerX="0.5" centerY="0.5" spread="RepeatSpread" coordinateMode="StretchToDeviceMode" type="ConicalGradient" angle="0" >
+ <stopData position="0" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.373978669201521" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.3739913434727503" >
+ <colorData g="30" r="33" a="255" b="255" />
+ </stopData>
+ <stopData position="0.6240176679340937" >
+ <colorData g="30" r="33" a="255" b="255" />
+ </stopData>
+ <stopData position="0.6240430164765525" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Dutch" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="0" endY="1" >
+ <stopData position="0" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.3397947548460661" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.339798898163606" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.6624439732888147" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.6624690150250417" >
+ <colorData g="0" r="0" a="255" b="255" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="0" r="0" a="255" b="255" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Eye" >
+ <gradientData centerX="0.5" centerY="0.5" radius="0.5" spread="PadSpread" focalX="0.5" focalY="0.5" coordinateMode="StretchToDeviceMode" type="RadialGradient" >
+ <stopData position="0" >
+ <colorData g="0" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="0.1939699465240642" >
+ <colorData g="0" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="0.202312192513369" >
+ <colorData g="97" r="122" a="255" b="0" />
+ </stopData>
+ <stopData position="0.4955143315508022" >
+ <colorData g="58" r="76" a="255" b="0" />
+ </stopData>
+ <stopData position="0.5048191443850267" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.79" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="158" r="255" a="255" b="158" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Flare1" >
+ <gradientData centerX="0.5" centerY="0.5" radius="0.5" spread="PadSpread" focalX="0.5" focalY="0.5" coordinateMode="StretchToDeviceMode" type="RadialGradient" >
+ <stopData position="0" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.1" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.2" >
+ <colorData g="176" r="255" a="167" b="176" />
+ </stopData>
+ <stopData position="0.3" >
+ <colorData g="151" r="255" a="92" b="151" />
+ </stopData>
+ <stopData position="0.4" >
+ <colorData g="125" r="255" a="51" b="125" />
+ </stopData>
+ <stopData position="0.5" >
+ <colorData g="76" r="255" a="205" b="76" />
+ </stopData>
+ <stopData position="0.52" >
+ <colorData g="76" r="255" a="205" b="76" />
+ </stopData>
+ <stopData position="0.6" >
+ <colorData g="180" r="255" a="84" b="180" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="255" r="255" a="0" b="255" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Flare2" >
+ <gradientData centerX="0.5" centerY="0.5" radius="0.5" spread="PadSpread" focalX="0.5" focalY="0.5" coordinateMode="StretchToDeviceMode" type="RadialGradient" >
+ <stopData position="0" >
+ <colorData g="0" r="0" a="0" b="0" />
+ </stopData>
+ <stopData position="0.52" >
+ <colorData g="0" r="0" a="0" b="0" />
+ </stopData>
+ <stopData position="0.5649999999999999" >
+ <colorData g="121" r="82" a="33" b="76" />
+ </stopData>
+ <stopData position="0.65" >
+ <colorData g="235" r="159" a="64" b="148" />
+ </stopData>
+ <stopData position="0.7219251336898396" >
+ <colorData g="238" r="255" a="129" b="150" />
+ </stopData>
+ <stopData position="0.77" >
+ <colorData g="128" r="255" a="204" b="128" />
+ </stopData>
+ <stopData position="0.89" >
+ <colorData g="128" r="191" a="64" b="255" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="0" r="0" a="0" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Flare3" >
+ <gradientData centerX="0.5" centerY="0.5" radius="0.5" spread="PadSpread" focalX="0.5" focalY="0.5" coordinateMode="StretchToDeviceMode" type="RadialGradient" >
+ <stopData position="0" >
+ <colorData g="235" r="255" a="206" b="235" />
+ </stopData>
+ <stopData position="0.35" >
+ <colorData g="188" r="255" a="80" b="188" />
+ </stopData>
+ <stopData position="0.4" >
+ <colorData g="162" r="255" a="80" b="162" />
+ </stopData>
+ <stopData position="0.425" >
+ <colorData g="132" r="255" a="156" b="132" />
+ </stopData>
+ <stopData position="0.44" >
+ <colorData g="128" r="252" a="80" b="128" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="255" r="255" a="0" b="255" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="German" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="0" endY="1" >
+ <stopData position="0" >
+ <colorData g="0" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="0.33" >
+ <colorData g="0" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="0.34" >
+ <colorData g="30" r="255" a="255" b="30" />
+ </stopData>
+ <stopData position="0.66" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.67" >
+ <colorData g="255" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="255" r="255" a="255" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Golden" >
+ <gradientData centerX="0.5" centerY="0.5" spread="PadSpread" coordinateMode="StretchToDeviceMode" type="ConicalGradient" angle="0" >
+ <stopData position="0" >
+ <colorData g="40" r="35" a="255" b="3" />
+ </stopData>
+ <stopData position="0.16" >
+ <colorData g="106" r="136" a="255" b="22" />
+ </stopData>
+ <stopData position="0.225" >
+ <colorData g="140" r="166" a="255" b="41" />
+ </stopData>
+ <stopData position="0.285" >
+ <colorData g="181" r="204" a="255" b="74" />
+ </stopData>
+ <stopData position="0.345" >
+ <colorData g="219" r="235" a="255" b="102" />
+ </stopData>
+ <stopData position="0.415" >
+ <colorData g="236" r="245" a="255" b="112" />
+ </stopData>
+ <stopData position="0.52" >
+ <colorData g="190" r="209" a="255" b="76" />
+ </stopData>
+ <stopData position="0.57" >
+ <colorData g="156" r="187" a="255" b="51" />
+ </stopData>
+ <stopData position="0.635" >
+ <colorData g="142" r="168" a="255" b="42" />
+ </stopData>
+ <stopData position="0.695" >
+ <colorData g="174" r="202" a="255" b="68" />
+ </stopData>
+ <stopData position="0.75" >
+ <colorData g="202" r="218" a="255" b="86" />
+ </stopData>
+ <stopData position="0.8149999999999999" >
+ <colorData g="187" r="208" a="255" b="73" />
+ </stopData>
+ <stopData position="0.88" >
+ <colorData g="156" r="187" a="255" b="51" />
+ </stopData>
+ <stopData position="0.9350000000000001" >
+ <colorData g="108" r="137" a="255" b="26" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="40" r="35" a="255" b="3" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Japanese" >
+ <gradientData centerX="0.5" centerY="0.5" radius="0.5" spread="PadSpread" focalX="0.5" focalY="0.5" coordinateMode="StretchToDeviceMode" type="RadialGradient" >
+ <stopData position="0" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.4799044117647059" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.5226851604278074" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Norwegian" >
+ <gradientData spread="RepeatSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="1" endY="0" >
+ <stopData position="0" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.17" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.18" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.2102117403738299" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.2202117403738299" >
+ <colorData g="16" r="0" a="255" b="255" />
+ </stopData>
+ <stopData position="0.2798973635190806" >
+ <colorData g="16" r="0" a="255" b="255" />
+ </stopData>
+ <stopData position="0.2898973635190806" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.32" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.33" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Pastels" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="1" endY="0" >
+ <stopData position="0" >
+ <colorData g="224" r="245" a="255" b="176" />
+ </stopData>
+ <stopData position="0.09" >
+ <colorData g="189" r="246" a="255" b="237" />
+ </stopData>
+ <stopData position="0.14" >
+ <colorData g="207" r="194" a="255" b="246" />
+ </stopData>
+ <stopData position="0.19" >
+ <colorData g="160" r="184" a="255" b="168" />
+ </stopData>
+ <stopData position="0.25" >
+ <colorData g="186" r="171" a="255" b="248" />
+ </stopData>
+ <stopData position="0.32" >
+ <colorData g="248" r="243" a="255" b="224" />
+ </stopData>
+ <stopData position="0.385" >
+ <colorData g="162" r="249" a="255" b="183" />
+ </stopData>
+ <stopData position="0.47" >
+ <colorData g="115" r="100" a="255" b="124" />
+ </stopData>
+ <stopData position="0.58" >
+ <colorData g="205" r="251" a="255" b="202" />
+ </stopData>
+ <stopData position="0.65" >
+ <colorData g="128" r="170" a="255" b="185" />
+ </stopData>
+ <stopData position="0.75" >
+ <colorData g="222" r="252" a="255" b="204" />
+ </stopData>
+ <stopData position="0.805" >
+ <colorData g="122" r="206" a="255" b="218" />
+ </stopData>
+ <stopData position="0.86" >
+ <colorData g="223" r="254" a="255" b="175" />
+ </stopData>
+ <stopData position="0.91" >
+ <colorData g="236" r="254" a="255" b="244" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="191" r="255" a="255" b="221" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Polish" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="0" endY="1" >
+ <stopData position="0" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.495" >
+ <colorData g="255" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="0.505" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Rainbow" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="1" endY="0" >
+ <stopData position="0" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.166" >
+ <colorData g="255" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.333" >
+ <colorData g="255" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="0.5" >
+ <colorData g="255" r="0" a="255" b="255" />
+ </stopData>
+ <stopData position="0.666" >
+ <colorData g="0" r="0" a="255" b="255" />
+ </stopData>
+ <stopData position="0.833" >
+ <colorData g="0" r="255" a="255" b="255" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="0" r="255" a="255" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Sky" >
+ <gradientData spread="PadSpread" startX="0" startY="1" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="0" endY="0" >
+ <stopData position="0" >
+ <colorData g="0" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="0.05" >
+ <colorData g="8" r="14" a="255" b="73" />
+ </stopData>
+ <stopData position="0.36" >
+ <colorData g="17" r="28" a="255" b="145" />
+ </stopData>
+ <stopData position="0.6" >
+ <colorData g="14" r="126" a="255" b="81" />
+ </stopData>
+ <stopData position="0.75" >
+ <colorData g="11" r="234" a="255" b="11" />
+ </stopData>
+ <stopData position="0.79" >
+ <colorData g="70" r="244" a="255" b="5" />
+ </stopData>
+ <stopData position="0.86" >
+ <colorData g="136" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.9350000000000001" >
+ <colorData g="236" r="239" a="255" b="55" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="SunRay" >
+ <gradientData centerX="0" centerY="0" spread="RepeatSpread" coordinateMode="StretchToDeviceMode" type="ConicalGradient" angle="135" >
+ <stopData position="0" >
+ <colorData g="255" r="255" a="69" b="0" />
+ </stopData>
+ <stopData position="0.375" >
+ <colorData g="255" r="255" a="69" b="0" />
+ </stopData>
+ <stopData position="0.4235329090018885" >
+ <colorData g="255" r="251" a="145" b="0" />
+ </stopData>
+ <stopData position="0.45" >
+ <colorData g="255" r="247" a="208" b="0" />
+ </stopData>
+ <stopData position="0.4775811200061043" >
+ <colorData g="244" r="255" a="130" b="71" />
+ </stopData>
+ <stopData position="0.5187165775401069" >
+ <colorData g="218" r="255" a="130" b="71" />
+ </stopData>
+ <stopData position="0.55" >
+ <colorData g="255" r="255" a="255" b="0" />
+ </stopData>
+ <stopData position="0.5775401069518716" >
+ <colorData g="203" r="255" a="130" b="0" />
+ </stopData>
+ <stopData position="0.625" >
+ <colorData g="255" r="255" a="69" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="255" r="255" a="69" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Tropical" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="1" endY="0" >
+ <stopData position="0" >
+ <colorData g="41" r="9" a="255" b="4" />
+ </stopData>
+ <stopData position="0.08500000000000001" >
+ <colorData g="79" r="2" a="255" b="0" />
+ </stopData>
+ <stopData position="0.19" >
+ <colorData g="147" r="50" a="255" b="22" />
+ </stopData>
+ <stopData position="0.275" >
+ <colorData g="191" r="236" a="255" b="49" />
+ </stopData>
+ <stopData position="0.39" >
+ <colorData g="61" r="243" a="255" b="34" />
+ </stopData>
+ <stopData position="0.555" >
+ <colorData g="81" r="135" a="255" b="60" />
+ </stopData>
+ <stopData position="0.667" >
+ <colorData g="75" r="121" a="255" b="255" />
+ </stopData>
+ <stopData position="0.825" >
+ <colorData g="255" r="164" a="255" b="244" />
+ </stopData>
+ <stopData position="0.885" >
+ <colorData g="222" r="104" a="255" b="71" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="128" r="93" a="255" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Wave" >
+ <gradientData centerX="0.5" centerY="0.5" radius="0.077" spread="RepeatSpread" focalX="0.5" focalY="0.5" coordinateMode="StretchToDeviceMode" type="RadialGradient" >
+ <stopData position="0" >
+ <colorData g="169" r="0" a="147" b="255" />
+ </stopData>
+ <stopData position="0.4973262032085561" >
+ <colorData g="0" r="0" a="147" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="169" r="0" a="147" b="255" />
+ </stopData>
+ </gradientData>
+ </gradient>
+ <gradient name="Wood" >
+ <gradientData spread="PadSpread" startX="0" startY="0" coordinateMode="StretchToDeviceMode" type="LinearGradient" endX="1" endY="0" >
+ <stopData position="0" >
+ <colorData g="178" r="255" a="255" b="102" />
+ </stopData>
+ <stopData position="0.55" >
+ <colorData g="148" r="235" a="255" b="61" />
+ </stopData>
+ <stopData position="0.98" >
+ <colorData g="0" r="0" a="255" b="0" />
+ </stopData>
+ <stopData position="1" >
+ <colorData g="0" r="0" a="0" b="0" />
+ </stopData>
+ </gradientData>
+ </gradient>
+</gradients>
diff --git a/tools/designer/src/lib/shared/deviceprofile.cpp b/tools/designer/src/lib/shared/deviceprofile.cpp
new file mode 100644
index 0000000000..c512ff5305
--- /dev/null
+++ b/tools/designer/src/lib/shared/deviceprofile.cpp
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deviceprofile_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <widgetfactory_p.h>
+#include <qdesigner_utils_p.h>
+
+#include <QtGui/QApplication>
+#include <QtGui/QFont>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleFactory>
+#include <QtGui/QApplication>
+
+#include <QtCore/QSharedData>
+#include <QtCore/QTextStream>
+
+#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QXmlStreamReader>
+
+
+static const char *dpiXPropertyC = "_q_customDpiX";
+static const char *dpiYPropertyC = "_q_customDpiY";
+
+// XML serialization
+static const char *xmlVersionC="1.0";
+static const char *rootElementC="deviceprofile";
+static const char *nameElementC = "name";
+static const char *fontFamilyElementC = "fontfamily";
+static const char *fontPointSizeElementC = "fontpointsize";
+static const char *dPIXElementC = "dpix";
+static const char *dPIYElementC = "dpiy";
+static const char *styleElementC = "style";
+
+/* DeviceProfile:
+ * For preview purposes (preview, widget box, new form dialog), the
+ * QDesignerFormBuilder applies the settings to the form main container
+ * (Point being here that the DPI must be set directly for size calculations
+ * to be correct).
+ * For editing purposes, FormWindow applies the settings to the form container
+ * as not to interfere with the font settings of the form main container.
+ * In addition, the widgetfactory maintains the system settings style
+ * and applies it when creating widgets. */
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ---------------- DeviceProfileData
+class DeviceProfileData : public QSharedData {
+public:
+ DeviceProfileData();
+ void fromSystem();
+ void clear();
+
+ QString m_fontFamily;
+ int m_fontPointSize;
+ QString m_style;
+ int m_dpiX;
+ int m_dpiY;
+ QString m_name;
+};
+
+DeviceProfileData::DeviceProfileData() :
+ m_fontPointSize(-1),
+ m_dpiX(-1),
+ m_dpiY(-1)
+{
+}
+
+void DeviceProfileData::clear()
+{
+ m_fontPointSize = -1;
+ m_dpiX = 0;
+ m_dpiY = 0;
+ m_name.clear();
+ m_style.clear();
+}
+
+void DeviceProfileData::fromSystem()
+{
+ const QFont appFont = QApplication::font();
+ m_fontFamily = appFont.family();
+ m_fontPointSize = appFont.pointSize();
+ DeviceProfile::systemResolution(&m_dpiX, &m_dpiY);
+ m_style.clear();
+}
+
+// ---------------- DeviceProfile
+DeviceProfile::DeviceProfile() :
+ m_d(new DeviceProfileData)
+{
+}
+
+DeviceProfile::DeviceProfile(const DeviceProfile &o) :
+ m_d(o.m_d)
+
+{
+}
+
+DeviceProfile& DeviceProfile::operator=(const DeviceProfile &o)
+{
+ m_d.operator=(o.m_d);
+ return *this;
+}
+
+DeviceProfile::~DeviceProfile()
+{
+}
+
+void DeviceProfile::clear()
+{
+ m_d->clear();
+}
+
+bool DeviceProfile::isEmpty() const
+{
+ return m_d->m_name.isEmpty();
+}
+
+QString DeviceProfile::fontFamily() const
+{
+ return m_d->m_fontFamily;
+}
+
+void DeviceProfile::setFontFamily(const QString &f)
+{
+ m_d->m_fontFamily = f;
+}
+
+int DeviceProfile::fontPointSize() const
+{
+ return m_d->m_fontPointSize;
+}
+
+void DeviceProfile::setFontPointSize(int p)
+{
+ m_d->m_fontPointSize = p;
+}
+
+QString DeviceProfile::style() const
+{
+ return m_d->m_style;
+}
+
+void DeviceProfile::setStyle(const QString &s)
+{
+ m_d->m_style = s;
+}
+
+int DeviceProfile::dpiX() const
+{
+ return m_d->m_dpiX;
+}
+
+void DeviceProfile::setDpiX(int d)
+{
+ m_d->m_dpiX = d;
+}
+
+int DeviceProfile::dpiY() const
+{
+ return m_d->m_dpiY;
+}
+
+void DeviceProfile::setDpiY(int d)
+{
+ m_d->m_dpiY = d;
+}
+
+void DeviceProfile::fromSystem()
+{
+ m_d->fromSystem();
+}
+
+QString DeviceProfile::name() const
+{
+ return m_d->m_name;
+}
+
+void DeviceProfile::setName(const QString &n)
+{
+ m_d->m_name = n;
+}
+
+void DeviceProfile::systemResolution(int *dpiX, int *dpiY)
+{
+ const QDesktopWidget *dw = qApp->desktop();
+ *dpiX = dw->logicalDpiX();
+ *dpiY = dw->logicalDpiY();
+}
+
+class FriendlyWidget : public QWidget {
+ friend class DeviceProfile;
+};
+
+void DeviceProfile::widgetResolution(const QWidget *w, int *dpiX, int *dpiY)
+{
+ const FriendlyWidget *fw = static_cast<const FriendlyWidget*>(w);
+ *dpiX = fw->metric(QPaintDevice::PdmDpiX);
+ *dpiY = fw->metric(QPaintDevice::PdmDpiY);
+}
+
+QString DeviceProfile::toString() const
+{
+ const DeviceProfileData &d = *m_d;
+ QString rc;
+ QTextStream(&rc) << "DeviceProfile:name=" << d.m_name << " Font=" << d.m_fontFamily << ' '
+ << d.m_fontPointSize << " Style=" << d.m_style << " DPI=" << d.m_dpiX << ',' << d.m_dpiY;
+ return rc;
+}
+
+// Apply font to widget
+static void applyFont(const QString &family, int size, DeviceProfile::ApplyMode am, QWidget *widget)
+{
+ QFont currentFont = widget->font();
+ if (currentFont.pointSize() == size && currentFont.family() == family)
+ return;
+ switch (am) {
+ case DeviceProfile::ApplyFormParent:
+ // Invisible form parent: Apply all
+ widget->setFont(QFont(family, size));
+ break;
+ case DeviceProfile::ApplyPreview: {
+ // Preview: Apply only subproperties that have not been changed by designer properties
+ bool apply = false;
+ const uint resolve = currentFont.resolve();
+ if (!(resolve & QFont::FamilyResolved)) {
+ currentFont.setFamily(family);
+ apply = true;
+ }
+ if (!(resolve & QFont::SizeResolved)) {
+ currentFont.setPointSize(size);
+ apply = true;
+ }
+ if (apply)
+ widget->setFont(currentFont);
+ }
+ break;
+ }
+}
+
+void DeviceProfile::applyDPI(int dpiX, int dpiY, QWidget *widget)
+{
+ int sysDPIX, sysDPIY; // Set dynamic variables in case values are different from system DPI
+ systemResolution(&sysDPIX, &sysDPIY);
+ if (dpiX != sysDPIX && dpiY != sysDPIY) {
+ widget->setProperty(dpiXPropertyC, QVariant(dpiX));
+ widget->setProperty(dpiYPropertyC, QVariant(dpiY));
+ }
+}
+
+void DeviceProfile::apply(const QDesignerFormEditorInterface *core, QWidget *widget, ApplyMode am) const
+{
+ if (isEmpty())
+ return;
+
+ const DeviceProfileData &d = *m_d;
+
+ if (!d.m_fontFamily.isEmpty())
+ applyFont(d.m_fontFamily, d.m_fontPointSize, am, widget);
+
+ applyDPI(d.m_dpiX, d.m_dpiY, widget);
+
+ if (!d.m_style.isEmpty()) {
+ if (WidgetFactory *wf = qobject_cast<qdesigner_internal::WidgetFactory *>(core->widgetFactory()))
+ wf->applyStyleTopLevel(d.m_style, widget);
+ }
+}
+
+bool DeviceProfile::equals(const DeviceProfile& rhs) const
+{
+ const DeviceProfileData &d = *m_d;
+ const DeviceProfileData &rhs_d = *rhs.m_d;
+ return d.m_fontPointSize == rhs_d.m_fontPointSize &&
+ d.m_dpiX == rhs_d.m_dpiX && d.m_dpiY == rhs_d.m_dpiY && d.m_fontFamily == rhs_d.m_fontFamily &&
+ d.m_style == rhs_d.m_style && d.m_name == rhs_d.m_name;
+}
+
+static inline void writeElement(QXmlStreamWriter &writer, const QString &element, const QString &cdata)
+{
+ writer.writeStartElement(element);
+ writer.writeCharacters(cdata);
+ writer.writeEndElement();
+}
+
+QString DeviceProfile::toXml() const
+{
+ const DeviceProfileData &d = *m_d;
+ QString rc;
+ QXmlStreamWriter writer(&rc);
+ writer.writeStartDocument(QLatin1String(xmlVersionC));
+ writer.writeStartElement(QLatin1String(rootElementC));
+ writeElement(writer, QLatin1String(nameElementC), d.m_name);
+
+ if (!d.m_fontFamily.isEmpty())
+ writeElement(writer, QLatin1String(fontFamilyElementC), d.m_fontFamily);
+ if (d.m_fontPointSize >= 0)
+ writeElement(writer, QLatin1String(fontPointSizeElementC), QString::number(d.m_fontPointSize));
+ if (d.m_dpiX > 0)
+ writeElement(writer, QLatin1String(dPIXElementC), QString::number(d.m_dpiX));
+ if (d.m_dpiY > 0)
+ writeElement(writer, QLatin1String(dPIYElementC), QString::number(d.m_dpiY));
+ if (!d.m_style.isEmpty())
+ writeElement(writer, QLatin1String(styleElementC), d.m_style);
+
+ writer.writeEndElement();
+ writer.writeEndDocument();
+ return rc;
+}
+
+/* Switch stages when encountering a start element (state table) */
+enum ParseStage { ParseBeginning, ParseWithinRoot,
+ ParseName, ParseFontFamily, ParseFontPointSize, ParseDPIX, ParseDPIY, ParseStyle,
+ ParseError };
+
+static ParseStage nextStage(ParseStage currentStage, const QStringRef &startElement)
+{
+ switch (currentStage) {
+ case ParseBeginning:
+ if (startElement == QLatin1String(rootElementC))
+ return ParseWithinRoot;
+ break;
+ case ParseWithinRoot:
+ case ParseName:
+ case ParseFontFamily:
+ case ParseFontPointSize:
+ case ParseDPIX:
+ case ParseDPIY:
+ case ParseStyle:
+ if (startElement == QLatin1String(nameElementC))
+ return ParseName;
+ if (startElement == QLatin1String(fontFamilyElementC))
+ return ParseFontFamily;
+ if (startElement == QLatin1String(fontPointSizeElementC))
+ return ParseFontPointSize;
+ if (startElement == QLatin1String(dPIXElementC))
+ return ParseDPIX;
+ if (startElement == QLatin1String(dPIYElementC))
+ return ParseDPIY;
+ if (startElement == QLatin1String(styleElementC))
+ return ParseStyle;
+ break;
+ case ParseError:
+ break;
+ }
+ return ParseError;
+}
+
+static bool readIntegerElement(QXmlStreamReader &reader, int *v)
+{
+ const QString e = reader.readElementText();
+ bool ok;
+ *v = e.toInt(&ok);
+ //: Reading a number for an embedded device profile
+ if (!ok)
+ reader.raiseError(QApplication::translate("DeviceProfile", "'%1' is not a number.").arg(e));
+ return ok;
+}
+
+bool DeviceProfile::fromXml(const QString &xml, QString *errorMessage)
+{
+ DeviceProfileData &d = *m_d;
+ d.fromSystem();
+
+ QXmlStreamReader reader(xml);
+
+ ParseStage ps = ParseBeginning;
+ QXmlStreamReader::TokenType tt = QXmlStreamReader::NoToken;
+ int iv = 0;
+ do {
+ tt = reader.readNext();
+ if (tt == QXmlStreamReader::StartElement) {
+ ps = nextStage(ps, reader.name());
+ switch (ps) {
+ case ParseBeginning:
+ case ParseWithinRoot:
+ break;
+ case ParseError:
+ reader.raiseError(QApplication::translate("DeviceProfile", "An invalid tag <%1> was encountered.").arg(reader.name().toString()));
+ tt = QXmlStreamReader::Invalid;
+ break;
+ case ParseName:
+ d.m_name = reader.readElementText();
+ break;
+ case ParseFontFamily:
+ d.m_fontFamily = reader.readElementText();
+ break;
+ case ParseFontPointSize:
+ if (readIntegerElement(reader, &iv)) {
+ d.m_fontPointSize = iv;
+ } else {
+ tt = QXmlStreamReader::Invalid;
+ }
+ break;
+ case ParseDPIX:
+ if (readIntegerElement(reader, &iv)) {
+ d.m_dpiX = iv;
+ } else {
+ tt = QXmlStreamReader::Invalid;
+ }
+ break;
+ case ParseDPIY:
+ if (readIntegerElement(reader, &iv)) {
+ d.m_dpiY = iv;
+ } else {
+ tt = QXmlStreamReader::Invalid;
+ }
+ break;
+ case ParseStyle:
+ d.m_style = reader.readElementText();
+ break;
+ }
+ }
+ } while (tt != QXmlStreamReader::Invalid && tt != QXmlStreamReader::EndDocument);
+
+ if (reader.hasError()) {
+ *errorMessage = reader.errorString();
+ return false;
+ }
+
+ return true;
+}
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/lib/shared/deviceprofile_p.h b/tools/designer/src/lib/shared/deviceprofile_p.h
new file mode 100644
index 0000000000..a1a36e36d8
--- /dev/null
+++ b/tools/designer/src/lib/shared/deviceprofile_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef DEVICEPROFILE_H
+#define DEVICEPROFILE_H
+
+#include "shared_global_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QWidget;
+class QStyle;
+
+namespace qdesigner_internal {
+
+class DeviceProfileData;
+
+/* DeviceProfile for embedded design. They influence
+ * default properties (for example, fonts), dpi and
+ * style of the form. This class represents a device
+ * profile. */
+
+class QDESIGNER_SHARED_EXPORT DeviceProfile {
+public:
+ DeviceProfile();
+
+ DeviceProfile(const DeviceProfile&);
+ DeviceProfile& operator=(const DeviceProfile&);
+ ~DeviceProfile();
+
+ void clear();
+
+ // Device name
+ QString name() const;
+ void setName(const QString &);
+
+ // System settings active
+ bool isEmpty() const;
+
+ // Default font family of the embedded system
+ QString fontFamily() const;
+ void setFontFamily(const QString &);
+
+ // Default font size of the embedded system
+ int fontPointSize() const;
+ void setFontPointSize(int p);
+
+ // Display resolution of the embedded system
+ int dpiX() const;
+ void setDpiX(int d);
+ int dpiY() const;
+ void setDpiY(int d);
+
+ // Style
+ QString style() const;
+ void setStyle(const QString &);
+
+ // Initialize from desktop system
+ void fromSystem();
+
+ static void systemResolution(int *dpiX, int *dpiY);
+ static void widgetResolution(const QWidget *w, int *dpiX, int *dpiY);
+
+ bool equals(const DeviceProfile& rhs) const;
+
+ // Apply to form/preview (using font inheritance)
+ enum ApplyMode {
+ /* Pre-Apply to parent widget of form being edited: Apply font
+ * and make use of property inheritance to be able to modify the
+ * font property freely. */
+ ApplyFormParent,
+ /* Post-Apply to preview widget: Change only inherited font
+ * sub properties. */
+ ApplyPreview
+ };
+ void apply(const QDesignerFormEditorInterface *core, QWidget *widget, ApplyMode am) const;
+
+ static void applyDPI(int dpiX, int dpiY, QWidget *widget);
+
+ QString toString() const;
+
+ QString toXml() const;
+ bool fromXml(const QString &xml, QString *errorMessage);
+
+private:
+ QSharedDataPointer<DeviceProfileData> m_d;
+};
+
+inline bool operator==(const DeviceProfile &s1, const DeviceProfile &s2)
+ { return s1.equals(s2); }
+inline bool operator!=(const DeviceProfile &s1, const DeviceProfile &s2)
+ { return !s1.equals(s2); }
+
+}
+
+
+QT_END_NAMESPACE
+
+#endif // DEVICEPROFILE_H
diff --git a/tools/designer/src/lib/shared/dialoggui.cpp b/tools/designer/src/lib/shared/dialoggui.cpp
new file mode 100644
index 0000000000..ef9dbae7da
--- /dev/null
+++ b/tools/designer/src/lib/shared/dialoggui.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "dialoggui_p.h"
+
+#include <QtGui/QFileIconProvider>
+#include <QtGui/QIcon>
+#include <QtGui/QImage>
+#include <QtGui/QImageReader>
+#include <QtGui/QPixmap>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QFile>
+#include <QtCore/QSet>
+
+// QFileDialog on X11 does not provide an image preview. Display icons.
+#ifdef Q_WS_X11
+# define IMAGE_PREVIEW
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// Icon provider that reads out the known image formats
+class IconProvider : public QFileIconProvider {
+ Q_DISABLE_COPY(IconProvider)
+
+public:
+ IconProvider();
+ virtual QIcon icon (const QFileInfo &info) const;
+
+ inline bool loadCheck(const QFileInfo &info) const;
+ QImage loadImage(const QString &fileName) const;
+
+private:
+ QSet<QString> m_imageFormats;
+};
+
+IconProvider::IconProvider()
+{
+ // Determine a list of readable extensions (upper and lower case)
+ typedef QList<QByteArray> ByteArrayList;
+ const ByteArrayList fmts = QImageReader::supportedImageFormats();
+ const ByteArrayList::const_iterator cend = fmts.constEnd();
+ for (ByteArrayList::const_iterator it = fmts.constBegin(); it != cend; ++it) {
+ const QString suffix = QString::fromUtf8(it->constData());
+ m_imageFormats.insert(suffix.toLower());
+ m_imageFormats.insert(suffix.toUpper());
+
+ }
+}
+
+// Check by extension and type if this appears to be a loadable image
+bool IconProvider::loadCheck(const QFileInfo &info) const
+{
+ if (info.isFile() && info.isReadable()) {
+ const QString suffix = info.suffix();
+ if (!suffix.isEmpty())
+ return m_imageFormats.contains(suffix);
+ }
+ return false;
+}
+
+QImage IconProvider::loadImage(const QString &fileName) const
+{
+ QFile file(fileName);
+ if (file.open(QIODevice::ReadOnly)) {
+ QImageReader imgReader(&file);
+ if (imgReader.canRead()) {
+ QImage image;
+ if (imgReader.read(&image))
+ return image;
+ }
+ }
+ return QImage();
+}
+
+QIcon IconProvider::icon (const QFileInfo &info) const
+{
+ // Don't get stuck on large images.
+ const qint64 maxSize = 131072;
+ if (loadCheck(info) && info.size() < maxSize) {
+ const QImage image = loadImage(info.absoluteFilePath());
+ if (!image.isNull())
+ return QIcon(QPixmap::fromImage(image, Qt::ThresholdDither|Qt::AutoColor));
+ }
+ return QFileIconProvider::icon(info);
+}
+
+// ---------------- DialogGui
+DialogGui::DialogGui() :
+ m_iconProvider(0)
+{
+}
+
+DialogGui::~DialogGui()
+{
+ delete m_iconProvider;
+}
+
+QFileIconProvider *DialogGui::ensureIconProvider()
+{
+ if (!m_iconProvider)
+ m_iconProvider = new IconProvider;
+ return m_iconProvider;
+}
+
+QMessageBox::StandardButton
+ DialogGui::message(QWidget *parent, Message /*context*/, QMessageBox::Icon icon,
+ const QString &title, const QString &text, QMessageBox::StandardButtons buttons,
+ QMessageBox::StandardButton defaultButton)
+{
+ QMessageBox::StandardButton rc = QMessageBox::NoButton;
+ switch (icon) {
+ case QMessageBox::Information:
+ rc = QMessageBox::information(parent, title, text, buttons, defaultButton);
+ break;
+ case QMessageBox::Warning:
+ rc = QMessageBox::warning(parent, title, text, buttons, defaultButton);
+ break;
+ case QMessageBox::Critical:
+ rc = QMessageBox::critical(parent, title, text, buttons, defaultButton);
+ break;
+ case QMessageBox::Question:
+ rc = QMessageBox::question(parent, title, text, buttons, defaultButton);
+ break;
+ case QMessageBox::NoIcon:
+ break;
+ }
+ return rc;
+}
+
+QMessageBox::StandardButton
+ DialogGui::message(QWidget *parent, Message /*context*/, QMessageBox::Icon icon,
+ const QString &title, const QString &text, const QString &informativeText,
+ QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
+{
+ QMessageBox msgBox(icon, title, text, buttons, parent);
+ msgBox.setDefaultButton(defaultButton);
+ msgBox.setInformativeText(informativeText);
+ return static_cast<QMessageBox::StandardButton>(msgBox.exec());
+}
+
+QMessageBox::StandardButton
+ DialogGui::message(QWidget *parent, Message /*context*/, QMessageBox::Icon icon,
+ const QString &title, const QString &text, const QString &informativeText, const QString &detailedText,
+ QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
+{
+ QMessageBox msgBox(icon, title, text, buttons, parent);
+ msgBox.setDefaultButton(defaultButton);
+ msgBox.setInformativeText(informativeText);
+ msgBox.setDetailedText(detailedText);
+ return static_cast<QMessageBox::StandardButton>(msgBox.exec());
+}
+
+QString DialogGui::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options)
+{
+ return QFileDialog::getExistingDirectory(parent, caption, dir, options);
+}
+
+QString DialogGui::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
+{
+ return QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options);
+}
+
+QStringList DialogGui::getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
+{
+ return QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options);
+}
+
+QString DialogGui::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
+{
+ return QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options);
+}
+
+void DialogGui::initializeImageFileDialog(QFileDialog &fileDialog, QFileDialog::Options options, QFileDialog::FileMode fm)
+{
+ fileDialog.setConfirmOverwrite( !(options & QFileDialog::DontConfirmOverwrite) );
+ fileDialog.setResolveSymlinks( !(options & QFileDialog::DontResolveSymlinks) );
+ fileDialog.setIconProvider(ensureIconProvider());
+ fileDialog.setFileMode(fm);
+}
+
+QString DialogGui::getOpenImageFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options )
+{
+
+#ifdef IMAGE_PREVIEW
+ QFileDialog fileDialog(parent, caption, dir, filter);
+ initializeImageFileDialog(fileDialog, options, QFileDialog::ExistingFile);
+ if (fileDialog.exec() != QDialog::Accepted)
+ return QString();
+
+ const QStringList selectedFiles = fileDialog.selectedFiles();
+ if (selectedFiles.empty())
+ return QString();
+
+ if (selectedFilter)
+ *selectedFilter = fileDialog.selectedFilter();
+
+ return selectedFiles.front();
+#else
+ return getOpenFileName(parent, caption, dir, filter, selectedFilter, options);
+#endif
+}
+
+QStringList DialogGui::getOpenImageFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options )
+{
+#ifdef IMAGE_PREVIEW
+ QFileDialog fileDialog(parent, caption, dir, filter);
+ initializeImageFileDialog(fileDialog, options, QFileDialog::ExistingFiles);
+ if (fileDialog.exec() != QDialog::Accepted)
+ return QStringList();
+
+ const QStringList selectedFiles = fileDialog.selectedFiles();
+ if (!selectedFiles.empty() && selectedFilter)
+ *selectedFilter = fileDialog.selectedFilter();
+
+ return selectedFiles;
+#else
+ return getOpenFileNames(parent, caption, dir, filter, selectedFilter, options);
+#endif
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/dialoggui_p.h b/tools/designer/src/lib/shared/dialoggui_p.h
new file mode 100644
index 0000000000..753e130d2f
--- /dev/null
+++ b/tools/designer/src/lib/shared/dialoggui_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DIALOGGUI
+#define DIALOGGUI
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "shared_global_p.h"
+#include <abstractdialoggui_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFileIconProvider;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT DialogGui : public QDesignerDialogGuiInterface
+{
+public:
+ DialogGui();
+ virtual ~DialogGui();
+
+ virtual QMessageBox::StandardButton
+ message(QWidget *parent, Message context, QMessageBox::Icon icon,
+ const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
+ QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
+
+ virtual QMessageBox::StandardButton
+ message(QWidget *parent, Message context, QMessageBox::Icon icon,
+ const QString &title, const QString &text, const QString &informativeText,
+ QMessageBox::StandardButtons buttons = QMessageBox::Ok,
+ QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
+
+ virtual QMessageBox::StandardButton
+ message(QWidget *parent, Message context, QMessageBox::Icon icon,
+ const QString &title, const QString &text, const QString &informativeText, const QString &detailedText,
+ QMessageBox::StandardButtons buttons = QMessageBox::Ok,
+ QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
+
+ virtual QString getExistingDirectory(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), QFileDialog::Options options = QFileDialog::ShowDirsOnly);
+ virtual QString getOpenFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
+ virtual QStringList getOpenFileNames(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
+ virtual QString getSaveFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
+
+ virtual QString getOpenImageFileName(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
+ virtual QStringList getOpenImageFileNames(QWidget *parent = 0, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
+
+private:
+ QFileIconProvider *ensureIconProvider();
+ void initializeImageFileDialog(QFileDialog &fd, QFileDialog::Options options, QFileDialog::FileMode);
+
+ QFileIconProvider *m_iconProvider;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DIALOGGUI
diff --git a/tools/designer/src/lib/shared/extensionfactory_p.h b/tools/designer/src/lib/shared/extensionfactory_p.h
new file mode 100644
index 0000000000..10649c4a31
--- /dev/null
+++ b/tools/designer/src/lib/shared/extensionfactory_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SHARED_EXTENSIONFACTORY_H
+#define SHARED_EXTENSIONFACTORY_H
+
+#include <QtDesigner/default_extensionfactory.h>
+#include <QtDesigner/QExtensionManager>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// Extension factory for registering an extension for an object type.
+template <class ExtensionInterface, class Object, class Extension>
+class ExtensionFactory: public QExtensionFactory
+{
+public:
+ explicit ExtensionFactory(const QString &iid, QExtensionManager *parent = 0);
+
+ // Convenience for registering the extension. Do not use for derived classes.
+ static void registerExtension(QExtensionManager *mgr, const QString &iid);
+
+protected:
+ virtual QObject *createExtension(QObject *qObject, const QString &iid, QObject *parent) const;
+
+private:
+ // Can be overwritten to perform checks on the object.
+ // Default does a qobject_cast to the desired class.
+ virtual Object *checkObject(QObject *qObject) const;
+
+ const QString m_iid;
+};
+
+template <class ExtensionInterface, class Object, class Extension>
+ExtensionFactory<ExtensionInterface, Object, Extension>::ExtensionFactory(const QString &iid, QExtensionManager *parent) :
+ QExtensionFactory(parent),
+ m_iid(iid)
+{
+}
+
+template <class ExtensionInterface, class Object, class Extension>
+Object *ExtensionFactory<ExtensionInterface, Object, Extension>::checkObject(QObject *qObject) const
+{
+ return qobject_cast<Object*>(qObject);
+}
+
+template <class ExtensionInterface, class Object, class Extension>
+QObject *ExtensionFactory<ExtensionInterface, Object, Extension>::createExtension(QObject *qObject, const QString &iid, QObject *parent) const
+{
+ if (iid != m_iid)
+ return 0;
+
+ Object *object = checkObject(qObject);
+ if (!object)
+ return 0;
+
+ return new Extension(object, parent);
+}
+
+template <class ExtensionInterface, class Object, class Extension>
+void ExtensionFactory<ExtensionInterface, Object, Extension>::registerExtension(QExtensionManager *mgr, const QString &iid)
+{
+ ExtensionFactory *factory = new ExtensionFactory(iid, mgr);
+ mgr->registerExtensions(factory, iid);
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SHARED_EXTENSIONFACTORY_H
diff --git a/tools/designer/src/lib/shared/filterwidget.cpp b/tools/designer/src/lib/shared/filterwidget.cpp
new file mode 100644
index 0000000000..f0a77c3ec7
--- /dev/null
+++ b/tools/designer/src/lib/shared/filterwidget.cpp
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "filterwidget_p.h"
+#include "iconloader_p.h"
+
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QLineEdit>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QPalette>
+#include <QtGui/QCursor>
+
+#include <QtCore/QDebug>
+
+enum { debugFilter = 0 };
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+HintLineEdit::HintLineEdit(QWidget *parent) :
+ QLineEdit(parent),
+ m_defaultFocusPolicy(focusPolicy()),
+ m_hintColor(QColor(0xbbbbbb)),
+ m_refuseFocus(false),
+ m_showingHintText(false)
+{
+}
+
+bool HintLineEdit::refuseFocus() const
+{
+ return m_refuseFocus;
+}
+
+void HintLineEdit::setRefuseFocus(bool v)
+{
+ if (v == m_refuseFocus)
+ return;
+ m_refuseFocus = v;
+ setFocusPolicy(m_refuseFocus ? Qt::NoFocus : m_defaultFocusPolicy);
+}
+
+void HintLineEdit::mousePressEvent(QMouseEvent *e)
+{
+ if (debugFilter)
+ qDebug() << Q_FUNC_INFO;
+ // Explicitly focus on click.
+ if (m_refuseFocus && !hasFocus())
+ setFocus(Qt::OtherFocusReason);
+ QLineEdit::mousePressEvent(e);
+}
+
+void HintLineEdit::focusInEvent(QFocusEvent *e)
+{
+ if (debugFilter)
+ qDebug() << Q_FUNC_INFO;
+ if (m_refuseFocus) {
+ // Refuse the focus if the mouse it outside. In addition to the mouse
+ // press logic, this prevents a re-focussing which occurs once
+ // we actually had focus
+ const Qt::FocusReason reason = e->reason();
+ if (reason == Qt::ActiveWindowFocusReason || reason == Qt::PopupFocusReason) {
+ const QPoint mousePos = mapFromGlobal(QCursor::pos());
+ const bool refuse = !geometry().contains(mousePos);
+ if (debugFilter)
+ qDebug() << Q_FUNC_INFO << refuse ;
+ if (refuse) {
+ e->ignore();
+ return;
+ }
+ }
+ }
+
+ hideHintText();
+ QLineEdit::focusInEvent(e);
+}
+
+void HintLineEdit::focusOutEvent(QFocusEvent *e)
+{
+ if (debugFilter)
+ qDebug() << Q_FUNC_INFO;
+ // Focus out: Switch to displaying the hint text unless there is user input
+ showHintText();
+ QLineEdit::focusOutEvent(e);
+}
+
+QString HintLineEdit::hintText() const
+{
+ return m_hintText;
+}
+
+void HintLineEdit::setHintText(const QString &ht)
+{
+ if (ht == m_hintText)
+ return;
+ hideHintText();
+ m_hintText = ht;
+ if (!hasFocus() && !ht.isEmpty())
+ showHintText();
+}
+
+void HintLineEdit::showHintText(bool force)
+{
+ if (m_showingHintText || m_hintText.isEmpty())
+ return;
+ if (force || text().isEmpty()) {
+ m_showingHintText = true;
+ setText(m_hintText);
+ setTextColor(m_hintColor, &m_textColor);
+ }
+}
+void HintLineEdit::hideHintText()
+{
+ if (m_showingHintText && !m_hintText.isEmpty()) {
+ m_showingHintText = false;
+ setText(QString());
+ setTextColor(m_textColor);
+ }
+}
+
+bool HintLineEdit::isShowingHintText() const
+{
+ return m_showingHintText;
+}
+
+QString HintLineEdit::typedText() const
+{
+ return m_showingHintText ? QString() : text();
+}
+
+void HintLineEdit::setTextColor(const QColor &newColor, QColor *oldColor)
+{
+ QPalette pal = palette();
+ if (oldColor)
+ *oldColor = pal.color(QPalette::Text);
+ pal.setColor(QPalette::Text, newColor);
+ setPalette(pal);}
+
+// ------------------- FilterWidget
+FilterWidget::FilterWidget(QWidget *parent, LayoutMode lm) :
+ QWidget(parent),
+ m_button(new QPushButton),
+ m_editor(new HintLineEdit)
+{
+ m_editor->setHintText(tr("<Filter>"));
+ QHBoxLayout *l = new QHBoxLayout(this);
+ l->setMargin(0);
+ l->setSpacing(0);
+
+ if (lm == LayoutAlignRight)
+ l->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+ l->addWidget(m_editor);
+
+ m_button->setIcon(createIconSet(QLatin1String("resetproperty.png")));
+ m_button->setIconSize(QSize(8, 8));
+ m_button->setFlat(true);
+ l->addWidget(m_button);
+
+ connect(m_button, SIGNAL(clicked()), this, SLOT(reset()));
+ connect(m_editor, SIGNAL(textChanged(QString)), this, SLOT(checkButton(QString)));
+ connect(m_editor, SIGNAL(textEdited(QString)), this, SIGNAL(filterChanged(QString)));
+}
+
+QString FilterWidget::text() const
+{
+ return m_editor->typedText();
+}
+
+void FilterWidget::checkButton(const QString &)
+{
+ m_button->setEnabled(!text().isEmpty());
+}
+
+void FilterWidget::reset()
+{
+ if (debugFilter)
+ qDebug() << Q_FUNC_INFO;
+ if (!text().isEmpty()) {
+ // Editor has lost focus once this is pressed
+ m_editor->showHintText(true);
+ emit filterChanged(QString());
+ }
+}
+
+bool FilterWidget::refuseFocus() const
+{
+ return m_editor->refuseFocus();
+}
+
+void FilterWidget::setRefuseFocus(bool v)
+{
+ m_editor->setRefuseFocus(v);
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/filterwidget_p.h b/tools/designer/src/lib/shared/filterwidget_p.h
new file mode 100644
index 0000000000..3d1f64e3cc
--- /dev/null
+++ b/tools/designer/src/lib/shared/filterwidget_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef FILTERWIDGET_H
+#define FILTERWIDGET_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QWidget>
+#include <QtGui/QLineEdit>
+#include <QtGui/QColor>
+
+QT_BEGIN_NAMESPACE
+
+class QPushButton;
+
+namespace qdesigner_internal {
+
+/* A line edit that displays a grayed hintText (like "Type Here to Filter")
+ * when not focussed and empty. When connecting to the changed signals and
+ * querying text, one has to be aware that the text is set to that hint
+ * text if isShowingHintText() returns true (that is, does not contain
+ * valid user input). This widget should never have initial focus
+ * (ie, be the first widget of a dialog, else, the hint cannot be displayed.
+ * For situations, where it is the only focusable control (widget box),
+ * there is a special "refuseFocus()" mode, in which it clears the focus
+ * policy and focusses explicitly on click (note that setting Qt::ClickFocus
+ * is not sufficient for that as an ActivationFocus will occur). */
+
+class QDESIGNER_SHARED_EXPORT HintLineEdit : public QLineEdit {
+ Q_OBJECT
+public:
+ explicit HintLineEdit(QWidget *parent = 0);
+
+ QString hintText() const;
+
+ bool isShowingHintText() const;
+
+ // Convenience for accessing the text that returns "" in case of isShowingHintText().
+ QString typedText() const;
+
+ bool refuseFocus() const;
+ void setRefuseFocus(bool v);
+
+public slots:
+ void setHintText(const QString &ht);
+ void showHintText(bool force = false);
+ void hideHintText();
+
+protected:
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void focusInEvent(QFocusEvent *e);
+ virtual void focusOutEvent(QFocusEvent *e);
+
+private:
+ void setTextColor(const QColor &newColor, QColor *oldColor = 0);
+
+ const Qt::FocusPolicy m_defaultFocusPolicy;
+ const QColor m_hintColor;
+ QColor m_textColor;
+ bool m_refuseFocus;
+ QString m_hintText;
+ bool m_showingHintText;
+};
+
+// FilterWidget: For filtering item views, with reset button Uses HintLineEdit.
+
+class QDESIGNER_SHARED_EXPORT FilterWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ enum LayoutMode {
+ // For use in toolbars: Expand to the right
+ LayoutAlignRight,
+ // No special alignment
+ LayoutAlignNone
+ };
+
+ explicit FilterWidget(QWidget *parent = 0, LayoutMode lm = LayoutAlignRight);
+
+ QString text() const;
+
+ bool refuseFocus() const; // see HintLineEdit
+ void setRefuseFocus(bool v);
+
+signals:
+ void filterChanged(const QString &);
+
+public slots:
+ void reset();
+
+private slots:
+ void checkButton(const QString &text);
+
+private:
+ QPushButton *m_button;
+ HintLineEdit *m_editor;
+};
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/formlayoutmenu.cpp b/tools/designer/src/lib/shared/formlayoutmenu.cpp
new file mode 100644
index 0000000000..c2966a1bfb
--- /dev/null
+++ b/tools/designer/src/lib/shared/formlayoutmenu.cpp
@@ -0,0 +1,534 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formlayoutmenu_p.h"
+#include "layoutinfo_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_utils_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "ui_formlayoutrowdialog.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+
+#include <QtGui/QAction>
+#include <QtGui/QWidget>
+#include <QtGui/QFormLayout>
+#include <QtGui/QUndoStack>
+#include <QtGui/QDialog>
+#include <QtGui/QPushButton>
+#include <QtGui/QRegExpValidator>
+
+#include <QtCore/QPair>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QRegExp>
+#include <QtCore/QMultiHash>
+#include <QtCore/QDebug>
+
+static const char *buddyPropertyC = "buddy";
+static const char *fieldWidgetBaseClasses[] = {
+ "QLineEdit", "QComboBox", "QSpinBox", "QDoubleSpinBox", "QCheckBox",
+ "QDateEdit", "QTimeEdit", "QDateTimeEdit", "QDial", "QWidget"
+};
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// Struct that describes a row of controls (descriptive label and control) to
+// be added to a form layout.
+struct FormLayoutRow {
+ FormLayoutRow() : buddy(false) {}
+
+ QString labelName;
+ QString labelText;
+ QString fieldClassName;
+ QString fieldName;
+ bool buddy;
+};
+
+// A Dialog to edit a FormLayoutRow. Lets the user input a label text, label
+// name, field widget type, field object name and buddy setting. As the
+// user types the label text; the object names to be used for label and field
+// are updated. It also checks the buddy setting depending on whether the
+// label text contains a buddy marker.
+class FormLayoutRowDialog : public QDialog {
+ Q_DISABLE_COPY(FormLayoutRowDialog)
+ Q_OBJECT
+public:
+ explicit FormLayoutRowDialog(QDesignerFormEditorInterface *core,
+ QWidget *parent);
+
+ FormLayoutRow formLayoutRow() const;
+
+ bool buddy() const;
+ void setBuddy(bool);
+
+ // Accessors for form layout row numbers using 0..[n-1] convention
+ int row() const;
+ void setRow(int);
+ void setRowRange(int, int);
+
+ QString fieldClass() const;
+ QString labelText() const;
+
+ static QStringList fieldWidgetClasses(QDesignerFormEditorInterface *core);
+
+private slots:
+ void labelTextEdited(const QString &text);
+ void labelNameEdited(const QString &text);
+ void fieldNameEdited(const QString &text);
+ void buddyClicked();
+ void fieldClassChanged(int);
+
+private:
+ bool isValid() const;
+ void updateObjectNames(bool updateLabel, bool updateField);
+ void updateOkButton();
+
+ // Check for buddy marker in string
+ const QRegExp m_buddyMarkerRegexp;
+
+ Ui::FormLayoutRowDialog m_ui;
+ bool m_labelNameEdited;
+ bool m_fieldNameEdited;
+ bool m_buddyClicked;
+};
+
+FormLayoutRowDialog::FormLayoutRowDialog(QDesignerFormEditorInterface *core,
+ QWidget *parent) :
+ QDialog(parent),
+ m_buddyMarkerRegexp(QLatin1String("\\&[^&]")),
+ m_labelNameEdited(false),
+ m_fieldNameEdited(false),
+ m_buddyClicked(false)
+{
+ Q_ASSERT(m_buddyMarkerRegexp.isValid());
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setModal(true);
+ m_ui.setupUi(this);
+ connect(m_ui.labelTextLineEdit, SIGNAL(textEdited(QString)), this, SLOT(labelTextEdited(QString)));
+
+ QRegExpValidator *nameValidator = new QRegExpValidator(QRegExp(QLatin1String("^[a-zA-Z0-9_]+$")), this);
+ Q_ASSERT(nameValidator->regExp().isValid());
+
+ m_ui.labelNameLineEdit->setValidator(nameValidator);
+ connect(m_ui.labelNameLineEdit, SIGNAL(textEdited(QString)),
+ this, SLOT(labelNameEdited(QString)));
+
+ m_ui.fieldNameLineEdit->setValidator(nameValidator);
+ connect(m_ui.fieldNameLineEdit, SIGNAL(textEdited(QString)),
+ this, SLOT(fieldNameEdited(QString)));
+
+ connect(m_ui.buddyCheckBox, SIGNAL(clicked()), this, SLOT(buddyClicked()));
+
+ m_ui.fieldClassComboBox->addItems(fieldWidgetClasses(core));
+ m_ui.fieldClassComboBox->setCurrentIndex(0);
+ connect(m_ui.fieldClassComboBox, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(fieldClassChanged(int)));
+
+ updateOkButton();
+}
+
+FormLayoutRow FormLayoutRowDialog::formLayoutRow() const
+{
+ FormLayoutRow rc;
+ rc.labelText = labelText();
+ rc.labelName = m_ui.labelNameLineEdit->text();
+ rc.fieldClassName = fieldClass();
+ rc.fieldName = m_ui.fieldNameLineEdit->text();
+ rc.buddy = buddy();
+ return rc;
+}
+
+bool FormLayoutRowDialog::buddy() const
+{
+ return m_ui.buddyCheckBox->checkState() == Qt::Checked;
+}
+
+void FormLayoutRowDialog::setBuddy(bool b)
+{
+ m_ui.buddyCheckBox->setCheckState(b ? Qt::Checked : Qt::Unchecked);
+}
+
+// Convert rows to 1..n convention for users
+int FormLayoutRowDialog::row() const
+{
+ return m_ui.rowSpinBox->value() - 1;
+}
+
+void FormLayoutRowDialog::setRow(int row)
+{
+ m_ui.rowSpinBox->setValue(row + 1);
+}
+
+void FormLayoutRowDialog::setRowRange(int from, int to)
+{
+ m_ui.rowSpinBox->setMinimum(from + 1);
+ m_ui.rowSpinBox->setMaximum(to + 1);
+ m_ui.rowSpinBox->setEnabled(to - from > 0);
+}
+
+QString FormLayoutRowDialog::fieldClass() const
+{
+ return m_ui.fieldClassComboBox->itemText(m_ui.fieldClassComboBox->currentIndex());
+}
+
+QString FormLayoutRowDialog::labelText() const
+{
+ return m_ui.labelTextLineEdit->text();
+}
+
+bool FormLayoutRowDialog::isValid() const
+{
+ // Check for non-empty names and presence of buddy marker if checked
+ const QString name = labelText();
+ if (name.isEmpty() || m_ui.labelNameLineEdit->text().isEmpty() || m_ui.fieldNameLineEdit->text().isEmpty())
+ return false;
+ if (buddy() && !name.contains(m_buddyMarkerRegexp))
+ return false;
+ return true;
+}
+
+void FormLayoutRowDialog::updateOkButton()
+{
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid());
+}
+
+void FormLayoutRowDialog::labelTextEdited(const QString &text)
+{
+ updateObjectNames(true, true);
+ // Set buddy if '&' is present unless the user changed it
+ if (!m_buddyClicked)
+ setBuddy(text.contains(m_buddyMarkerRegexp));
+
+ updateOkButton();
+}
+
+// Get a suitable object name postfix from a class name:
+// "namespace::QLineEdit"->"LineEdit"
+static inline QString postFixFromClassName(QString className)
+{
+ const int index = className.lastIndexOf(QLatin1String("::"));
+ if (index != -1)
+ className.remove(0, index + 2);
+ if (className.size() > 2)
+ if (className.at(0) == QLatin1Char('Q') || className.at(0) == QLatin1Char('K'))
+ if (className.at(1).isUpper())
+ className.remove(0, 1);
+ return className;
+}
+
+// Helper routines to filter out characters for converting texts into
+// class name prefixes. Only accepts ASCII characters/digits and underscores.
+
+enum PrefixCharacterKind { PC_Digit, PC_UpperCaseLetter, PC_LowerCaseLetter,
+ PC_Other, PC_Invalid };
+
+static inline PrefixCharacterKind prefixCharacterKind(const QChar &c)
+{
+ switch (c.category()) {
+ case QChar::Number_DecimalDigit:
+ return PC_Digit;
+ case QChar::Letter_Lowercase: {
+ const char a = c.toAscii();
+ if (a >= 'a' && a <= 'z')
+ return PC_LowerCaseLetter;
+ }
+ break;
+ case QChar::Letter_Uppercase: {
+ const char a = c.toAscii();
+ if (a >= 'A' && a <= 'Z')
+ return PC_UpperCaseLetter;
+ }
+ break;
+ case QChar::Punctuation_Connector:
+ if (c.toAscii() == '_')
+ return PC_Other;
+ break;
+ default:
+ break;
+ }
+ return PC_Invalid;
+}
+
+// Convert the text the user types into a usable class name prefix by filtering
+// characters, lower-casing the first character and camel-casing subsequent
+// words. ("zip code:") --> ("zipCode").
+
+static QString prefixFromLabel(const QString &prefix)
+{
+ QString rc;
+ const int length = prefix.size();
+ bool lastWasAcceptable = false;
+ for (int i = 0 ; i < length; i++) {
+ const QChar c = prefix.at(i);
+ const PrefixCharacterKind kind = prefixCharacterKind(c);
+ const bool acceptable = kind != PC_Invalid;
+ if (acceptable) {
+ if (rc.isEmpty()) {
+ // Lower-case first character
+ rc += kind == PC_UpperCaseLetter ? c.toLower() : c;
+ } else {
+ // Camel-case words
+ rc += !lastWasAcceptable && kind == PC_LowerCaseLetter ? c.toUpper() : c;
+ }
+ }
+ lastWasAcceptable = acceptable;
+ }
+ return rc;
+}
+
+void FormLayoutRowDialog::updateObjectNames(bool updateLabel, bool updateField)
+{
+ // Generate label + field object names from the label text, that is,
+ // "&Zip code:" -> "zipcodeLabel", "zipcodeLineEdit" unless the user
+ // edited it.
+ const bool doUpdateLabel = !m_labelNameEdited && updateLabel;
+ const bool doUpdateField = !m_fieldNameEdited && updateField;
+ if (!doUpdateLabel && !doUpdateField)
+ return;
+
+ const QString prefix = prefixFromLabel(labelText());
+ // Set names
+ if (doUpdateLabel)
+ m_ui.labelNameLineEdit->setText(prefix + QLatin1String("Label"));
+ if (doUpdateField)
+ m_ui.fieldNameLineEdit->setText(prefix + postFixFromClassName(fieldClass()));
+}
+
+void FormLayoutRowDialog::fieldClassChanged(int)
+{
+ updateObjectNames(false, true);
+}
+
+void FormLayoutRowDialog::labelNameEdited(const QString & /*text*/)
+{
+ m_labelNameEdited = true; // stop auto-updating after user change
+ updateOkButton();
+}
+
+void FormLayoutRowDialog::fieldNameEdited(const QString & /*text*/)
+{
+ m_fieldNameEdited = true; // stop auto-updating after user change
+ updateOkButton();
+}
+
+void FormLayoutRowDialog::buddyClicked()
+{
+ m_buddyClicked = true; // stop auto-updating after user change
+ updateOkButton();
+}
+
+/* Create a list of classes suitable for field widgets. Take the fixed base
+ * classes provided and look in the widget database for custom widgets derived
+ * from them ("QLineEdit", "CustomLineEdit", "QComboBox"...). */
+QStringList FormLayoutRowDialog::fieldWidgetClasses(QDesignerFormEditorInterface *core)
+{
+ // Base class -> custom widgets map
+ typedef QMultiHash<QString, QString> ClassMap;
+
+ static QStringList rc;
+ if (rc.empty()) {
+ const int fwCount = sizeof(fieldWidgetBaseClasses)/sizeof(const char*);
+ // Turn known base classes into list
+ QStringList baseClasses;
+ for (int i = 0; i < fwCount; i++)
+ baseClasses.push_back(QLatin1String(fieldWidgetBaseClasses[i]));
+ // Scan for custom widgets that inherit them and store them in a
+ // multimap of base class->custom widgets unless we have a language
+ // extension installed which might do funny things with custom widgets.
+ ClassMap customClassMap;
+ if (qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core) == 0) {
+ const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
+ const int wdbCount = wdb->count();
+ for (int w = 0; w < wdbCount; ++w) {
+ // Check for non-container custom types that extend the
+ // respective base class.
+ const QDesignerWidgetDataBaseItemInterface *dbItem = wdb->item(w);
+ if (!dbItem->isPromoted() && !dbItem->isContainer() && dbItem->isCustom()) {
+ const int index = baseClasses.indexOf(dbItem->extends());
+ if (index != -1)
+ customClassMap.insert(baseClasses.at(index), dbItem->name());
+ }
+ }
+ }
+ // Compile final list, taking each base class and append custom widgets
+ // based on it.
+ for (int i = 0; i < fwCount; i++) {
+ rc.push_back(baseClasses.at(i));
+ rc += customClassMap.values(baseClasses.at(i));
+ }
+ }
+ return rc;
+}
+
+// ------------------ Utilities
+
+static QFormLayout *managedFormLayout(const QDesignerFormEditorInterface *core, const QWidget *w)
+{
+ QLayout *l = 0;
+ if (LayoutInfo::managedLayoutType(core, w, &l) == LayoutInfo::Form)
+ return qobject_cast<QFormLayout *>(l);
+ return 0;
+}
+
+// Create the widgets of a control row and apply text properties contained
+// in the struct, called by addFormLayoutRow()
+static QPair<QWidget *,QWidget *>
+ createWidgets(const FormLayoutRow &row, QWidget *parent,
+ QDesignerFormWindowInterface *formWindow)
+{
+ QDesignerFormEditorInterface *core = formWindow->core();
+ QDesignerWidgetFactoryInterface *wf = core->widgetFactory();
+
+ QPair<QWidget *,QWidget *> rc = QPair<QWidget *,QWidget *>(wf->createWidget(QLatin1String("QLabel"), parent),
+ wf->createWidget(row.fieldClassName, parent));
+ // Set up properties of the label
+ const QString objectNameProperty = QLatin1String("objectName");
+ QDesignerPropertySheetExtension *labelSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.first);
+ int nameIndex = labelSheet->indexOf(objectNameProperty);
+ labelSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.labelName)));
+ labelSheet->setChanged(nameIndex, true);
+ formWindow->ensureUniqueObjectName(rc.first);
+ const int textIndex = labelSheet->indexOf(QLatin1String("text"));
+ labelSheet->setProperty(textIndex, qVariantFromValue(PropertySheetStringValue(row.labelText)));
+ labelSheet->setChanged(textIndex, true);
+ // Set up properties of the control
+ QDesignerPropertySheetExtension *controlSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), rc.second);
+ nameIndex = controlSheet->indexOf(objectNameProperty);
+ controlSheet->setProperty(nameIndex, qVariantFromValue(PropertySheetStringValue(row.fieldName)));
+ controlSheet->setChanged(nameIndex, true);
+ formWindow->ensureUniqueObjectName(rc.second);
+ return rc;
+}
+
+// Create a command sequence on the undo stack of the form window that creates
+// the widgets of the row and inserts them into the form layout.
+static void addFormLayoutRow(const FormLayoutRow &formLayoutRow, int row, QWidget *w,
+ QDesignerFormWindowInterface *formWindow)
+{
+ QFormLayout *formLayout = managedFormLayout(formWindow->core(), w);
+ Q_ASSERT(formLayout);
+ QUndoStack *undoStack = formWindow->commandHistory();
+ const QString macroName = QCoreApplication::translate("Command", "Add '%1' to '%2'").arg(formLayoutRow.labelText, formLayout->objectName());
+ undoStack->beginMacro(macroName);
+
+ // Create a list of widget insertion commands and pass them a cell position
+ const QPair<QWidget *,QWidget *> widgetPair = createWidgets(formLayoutRow, w, formWindow);
+
+ InsertWidgetCommand *labelCmd = new InsertWidgetCommand(formWindow);
+ labelCmd->init(widgetPair.first, false, row, 0);
+ undoStack->push(labelCmd);
+ InsertWidgetCommand *controlCmd = new InsertWidgetCommand(formWindow);
+ controlCmd->init(widgetPair.second, false, row, 1);
+ undoStack->push(controlCmd);
+ if (formLayoutRow.buddy) {
+ SetPropertyCommand *buddyCommand = new SetPropertyCommand(formWindow);
+ buddyCommand->init(widgetPair.first, QLatin1String(buddyPropertyC), widgetPair.second->objectName());
+ undoStack->push(buddyCommand);
+ }
+ undoStack->endMacro();
+}
+
+// ---------------- FormLayoutMenu
+FormLayoutMenu::FormLayoutMenu(QObject *parent) :
+ QObject(parent),
+ m_separator1(new QAction(this)),
+ m_populateFormAction(new QAction(tr("Add form layout row..."), this)),
+ m_separator2(new QAction(this))
+{
+ m_separator1->setSeparator(true);
+ connect(m_populateFormAction, SIGNAL(triggered()), this, SLOT(slotAddRow()));
+ m_separator2->setSeparator(true);
+}
+
+void FormLayoutMenu::populate(QWidget *w, QDesignerFormWindowInterface *fw, ActionList &actions)
+{
+ switch (LayoutInfo::managedLayoutType(fw->core(), w)) {
+ case LayoutInfo::Form:
+ if (!actions.empty() && !actions.back()->isSeparator())
+ actions.push_back(m_separator1);
+ actions.push_back(m_populateFormAction);
+ actions.push_back(m_separator2);
+ m_widget = w;
+ break;
+ default:
+ m_widget = 0;
+ break;
+ }
+}
+
+void FormLayoutMenu::slotAddRow()
+{
+ QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_widget);
+ Q_ASSERT(m_widget && fw);
+ const int rowCount = managedFormLayout(fw->core(), m_widget)->rowCount();
+
+ FormLayoutRowDialog dialog(fw->core(), fw);
+ dialog.setRowRange(0, rowCount);
+ dialog.setRow(rowCount);
+
+ if (dialog.exec() != QDialog::Accepted)
+ return;
+ addFormLayoutRow(dialog.formLayoutRow(), dialog.row(), m_widget, fw);
+}
+
+QAction *FormLayoutMenu::preferredEditAction(QWidget *w, QDesignerFormWindowInterface *fw)
+{
+ if (LayoutInfo::managedLayoutType(fw->core(), w) == LayoutInfo::Form) {
+ m_widget = w;
+ return m_populateFormAction;
+ }
+ return 0;
+}
+}
+
+QT_END_NAMESPACE
+
+#include "formlayoutmenu.moc"
+
diff --git a/tools/designer/src/lib/shared/formlayoutmenu_p.h b/tools/designer/src/lib/shared/formlayoutmenu_p.h
new file mode 100644
index 0000000000..a57546805b
--- /dev/null
+++ b/tools/designer/src/lib/shared/formlayoutmenu_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMLAYOUTMENU
+#define FORMLAYOUTMENU
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "shared_global_p.h"
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+class QAction;
+class QWidget;
+
+namespace qdesigner_internal {
+
+// Task menu to be used for form layouts. Offers an options "Add row" which
+// pops up a dialog in which the user can specify label name, text and buddy.
+class QDESIGNER_SHARED_EXPORT FormLayoutMenu : public QObject
+{
+ Q_DISABLE_COPY(FormLayoutMenu)
+ Q_OBJECT
+public:
+ typedef QList<QAction *> ActionList;
+
+ explicit FormLayoutMenu(QObject *parent);
+
+ // Populate a list of actions with the form layout actions.
+ void populate(QWidget *w, QDesignerFormWindowInterface *fw, ActionList &actions);
+ // For implementing QDesignerTaskMenuExtension::preferredEditAction():
+ // Return appropriate action for double clicking.
+ QAction *preferredEditAction(QWidget *w, QDesignerFormWindowInterface *fw);
+
+private slots:
+ void slotAddRow();
+
+private:
+ QAction *m_separator1;
+ QAction *m_populateFormAction;
+ QAction *m_separator2;
+ QPointer<QWidget> m_widget;
+};
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMLAYOUTMENU
diff --git a/tools/designer/src/lib/shared/formlayoutrowdialog.ui b/tools/designer/src/lib/shared/formlayoutrowdialog.ui
new file mode 100644
index 0000000000..c0e0cfe2ba
--- /dev/null
+++ b/tools/designer/src/lib/shared/formlayoutrowdialog.ui
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FormLayoutRowDialog</class>
+ <widget class="QDialog" name="FormLayoutRowDialog">
+ <property name="windowTitle">
+ <string>Add Form Layout Row</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::ExpandingFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="labelTextLabel">
+ <property name="text">
+ <string>&amp;Label text:</string>
+ </property>
+ <property name="buddy">
+ <cstring>labelTextLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="labelTextLineEdit">
+ <property name="minimumSize">
+ <size>
+ <width>180</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="labelNameLineEdit"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="fieldClassLabel">
+ <property name="text">
+ <string>Field &amp;type:</string>
+ </property>
+ <property name="buddy">
+ <cstring>fieldClassComboBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="fieldClassComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="fieldNameLabel">
+ <property name="text">
+ <string>&amp;Field name:</string>
+ </property>
+ <property name="buddy">
+ <cstring>fieldNameLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="buddyLabel">
+ <property name="text">
+ <string>&amp;Buddy:</string>
+ </property>
+ <property name="buddy">
+ <cstring>buddyCheckBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QCheckBox" name="buddyCheckBox">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="rowLabel">
+ <property name="text">
+ <string>&amp;Row:</string>
+ </property>
+ <property name="buddy">
+ <cstring>rowSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QSpinBox" name="rowSpinBox"/>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="fieldNameLineEdit"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelNameLabel">
+ <property name="text">
+ <string>Label &amp;name:</string>
+ </property>
+ <property name="buddy">
+ <cstring>labelNameLineEdit</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>FormLayoutRowDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>FormLayoutRowDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/formwindowbase.cpp b/tools/designer/src/lib/shared/formwindowbase.cpp
new file mode 100644
index 0000000000..3e7e17bb58
--- /dev/null
+++ b/tools/designer/src/lib/shared/formwindowbase.cpp
@@ -0,0 +1,487 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::FormWindowBase
+*/
+
+#include "formwindowbase_p.h"
+#include "connectionedit_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_propertysheet_p.h"
+#include "qdesigner_propertyeditor_p.h"
+#include "qdesigner_menu_p.h"
+#include "qdesigner_menubar_p.h"
+#include "shared_settings_p.h"
+#include "grid_p.h"
+#include "deviceprofile_p.h"
+#include "qdesigner_utils_p.h"
+
+#include <abstractformbuilder.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerTaskMenuExtension>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/QList>
+#include <QtCore/QTimer>
+#include <QtGui/QMenu>
+#include <QtGui/QListWidget>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QTableWidget>
+#include <QtGui/QComboBox>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QToolBar>
+#include <QtGui/QStatusBar>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class FormWindowBasePrivate {
+public:
+ explicit FormWindowBasePrivate(QDesignerFormEditorInterface *core);
+
+ static Grid m_defaultGrid;
+
+ QDesignerFormWindowInterface::Feature m_feature;
+ Grid m_grid;
+ bool m_hasFormGrid;
+ DesignerPixmapCache *m_pixmapCache;
+ DesignerIconCache *m_iconCache;
+ QtResourceSet *m_resourceSet;
+ QMap<QDesignerPropertySheet *, QMap<int, bool> > m_reloadableResources; // bool is dummy, QMap used as QSet
+ QMap<QDesignerPropertySheet *, QObject *> m_reloadablePropertySheets;
+ const DeviceProfile m_deviceProfile;
+ FormWindowBase::LineTerminatorMode m_lineTerminatorMode;
+ FormWindowBase::SaveResourcesBehaviour m_saveResourcesBehaviour;
+};
+
+FormWindowBasePrivate::FormWindowBasePrivate(QDesignerFormEditorInterface *core) :
+ m_feature(QDesignerFormWindowInterface::DefaultFeature),
+ m_grid(m_defaultGrid),
+ m_hasFormGrid(false),
+ m_pixmapCache(0),
+ m_iconCache(0),
+ m_resourceSet(0),
+ m_deviceProfile(QDesignerSharedSettings(core).currentDeviceProfile()),
+ m_lineTerminatorMode(FormWindowBase::NativeLineTerminator),
+ m_saveResourcesBehaviour(FormWindowBase::SaveAll)
+{
+}
+
+Grid FormWindowBasePrivate::m_defaultGrid;
+
+FormWindowBase::FormWindowBase(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags) :
+ QDesignerFormWindowInterface(parent, flags),
+ m_d(new FormWindowBasePrivate(core))
+{
+ syncGridFeature();
+ m_d->m_pixmapCache = new DesignerPixmapCache(this);
+ m_d->m_iconCache = new DesignerIconCache(m_d->m_pixmapCache, this);
+}
+
+FormWindowBase::~FormWindowBase()
+{
+ delete m_d;
+}
+
+DesignerPixmapCache *FormWindowBase::pixmapCache() const
+{
+ return m_d->m_pixmapCache;
+}
+
+DesignerIconCache *FormWindowBase::iconCache() const
+{
+ return m_d->m_iconCache;
+}
+
+QtResourceSet *FormWindowBase::resourceSet() const
+{
+ return m_d->m_resourceSet;
+}
+
+void FormWindowBase::setResourceSet(QtResourceSet *resourceSet)
+{
+ m_d->m_resourceSet = resourceSet;
+}
+
+void FormWindowBase::addReloadableProperty(QDesignerPropertySheet *sheet, int index)
+{
+ m_d->m_reloadableResources[sheet][index] = true;
+}
+
+void FormWindowBase::removeReloadableProperty(QDesignerPropertySheet *sheet, int index)
+{
+ m_d->m_reloadableResources[sheet].remove(index);
+ if (m_d->m_reloadableResources[sheet].count() == 0)
+ m_d->m_reloadableResources.remove(sheet);
+}
+
+void FormWindowBase::addReloadablePropertySheet(QDesignerPropertySheet *sheet, QObject *object)
+{
+ if (qobject_cast<QTreeWidget *>(object) ||
+ qobject_cast<QTableWidget *>(object) ||
+ qobject_cast<QListWidget *>(object) ||
+ qobject_cast<QComboBox *>(object))
+ m_d->m_reloadablePropertySheets[sheet] = object;
+}
+
+void FormWindowBase::removeReloadablePropertySheet(QDesignerPropertySheet *sheet)
+{
+ m_d->m_reloadablePropertySheets.remove(sheet);
+}
+
+void FormWindowBase::reloadProperties()
+{
+ pixmapCache()->clear();
+ iconCache()->clear();
+ QMapIterator<QDesignerPropertySheet *, QMap<int, bool> > itSheet(m_d->m_reloadableResources);
+ while (itSheet.hasNext()) {
+ QDesignerPropertySheet *sheet = itSheet.next().key();
+ QMapIterator<int, bool> itIndex(itSheet.value());
+ while (itIndex.hasNext()) {
+ const int index = itIndex.next().key();
+ sheet->setProperty(index, sheet->property(index));
+ }
+ if (QTabWidget *tabWidget = qobject_cast<QTabWidget *>(sheet->object())) {
+ const int count = tabWidget->count();
+ const int current = tabWidget->currentIndex();
+ const QString currentTabIcon = QLatin1String("currentTabIcon");
+ for (int i = 0; i < count; i++) {
+ tabWidget->setCurrentIndex(i);
+ const int index = sheet->indexOf(currentTabIcon);
+ sheet->setProperty(index, sheet->property(index));
+ }
+ tabWidget->setCurrentIndex(current);
+ } else if (QToolBox *toolBox = qobject_cast<QToolBox *>(sheet->object())) {
+ const int count = toolBox->count();
+ const int current = toolBox->currentIndex();
+ const QString currentItemIcon = QLatin1String("currentItemIcon");
+ for (int i = 0; i < count; i++) {
+ toolBox->setCurrentIndex(i);
+ const int index = sheet->indexOf(currentItemIcon);
+ sheet->setProperty(index, sheet->property(index));
+ }
+ toolBox->setCurrentIndex(current);
+ }
+ }
+ QMapIterator<QDesignerPropertySheet *, QObject *> itSh(m_d->m_reloadablePropertySheets);
+ while (itSh.hasNext()) {
+ QObject *object = itSh.next().value();
+ reloadIconResources(iconCache(), object);
+ }
+}
+
+void FormWindowBase::resourceSetActivated(QtResourceSet *resource, bool resourceSetChanged)
+{
+ if (resource == resourceSet() && resourceSetChanged) {
+ reloadProperties();
+ emit pixmapCache()->reloaded();
+ emit iconCache()->reloaded();
+ if (QDesignerPropertyEditor *propertyEditor = qobject_cast<QDesignerPropertyEditor *>(core()->propertyEditor()))
+ propertyEditor->reloadResourceProperties();
+ }
+}
+
+QVariantMap FormWindowBase::formData()
+{
+ QVariantMap rc;
+ if (m_d->m_hasFormGrid)
+ m_d->m_grid.addToVariantMap(rc, true);
+ return rc;
+}
+
+void FormWindowBase::setFormData(const QVariantMap &vm)
+{
+ Grid formGrid;
+ m_d->m_hasFormGrid = formGrid.fromVariantMap(vm);
+ if (m_d->m_hasFormGrid)
+ m_d->m_grid = formGrid;
+}
+
+QPoint FormWindowBase::grid() const
+{
+ return QPoint(m_d->m_grid.deltaX(), m_d->m_grid.deltaY());
+}
+
+void FormWindowBase::setGrid(const QPoint &grid)
+{
+ m_d->m_grid.setDeltaX(grid.x());
+ m_d->m_grid.setDeltaY(grid.y());
+}
+
+bool FormWindowBase::hasFeature(Feature f) const
+{
+ return f & m_d->m_feature;
+}
+
+static void recursiveUpdate(QWidget *w)
+{
+ w->update();
+
+ const QObjectList &l = w->children();
+ const QObjectList::const_iterator cend = l.constEnd();
+ for (QObjectList::const_iterator it = l.constBegin(); it != cend; ++it) {
+ if (QWidget *w = qobject_cast<QWidget*>(*it))
+ recursiveUpdate(w);
+ }
+}
+
+void FormWindowBase::setFeatures(Feature f)
+{
+ m_d->m_feature = f;
+ const bool enableGrid = f & GridFeature;
+ m_d->m_grid.setVisible(enableGrid);
+ m_d->m_grid.setSnapX(enableGrid);
+ m_d->m_grid.setSnapY(enableGrid);
+ emit featureChanged(f);
+ recursiveUpdate(this);
+}
+
+FormWindowBase::Feature FormWindowBase::features() const
+{
+ return m_d->m_feature;
+}
+
+bool FormWindowBase::gridVisible() const
+{
+ return m_d->m_grid.visible() && currentTool() == 0;
+}
+
+FormWindowBase::SaveResourcesBehaviour FormWindowBase::saveResourcesBehaviour() const
+{
+ return m_d->m_saveResourcesBehaviour;
+}
+
+void FormWindowBase::setSaveResourcesBehaviour(SaveResourcesBehaviour behaviour)
+{
+ m_d->m_saveResourcesBehaviour = behaviour;
+}
+
+void FormWindowBase::syncGridFeature()
+{
+ if (m_d->m_grid.snapX() || m_d->m_grid.snapY())
+ m_d->m_feature |= GridFeature;
+ else
+ m_d->m_feature &= ~GridFeature;
+}
+
+void FormWindowBase::setDesignerGrid(const Grid& grid)
+{
+ m_d->m_grid = grid;
+ syncGridFeature();
+ recursiveUpdate(this);
+}
+
+const Grid &FormWindowBase::designerGrid() const
+{
+ return m_d->m_grid;
+}
+
+bool FormWindowBase::hasFormGrid() const
+{
+ return m_d->m_hasFormGrid;
+}
+
+void FormWindowBase::setHasFormGrid(bool b)
+{
+ m_d->m_hasFormGrid = b;
+}
+
+void FormWindowBase::setDefaultDesignerGrid(const Grid& grid)
+{
+ FormWindowBasePrivate::m_defaultGrid = grid;
+}
+
+const Grid &FormWindowBase::defaultDesignerGrid()
+{
+ return FormWindowBasePrivate::m_defaultGrid;
+}
+
+QMenu *FormWindowBase::initializePopupMenu(QWidget * /*managedWidget*/)
+{
+ return 0;
+}
+
+// Widget under mouse for finding the Widget to highlight
+// when doing DnD. Restricts to pages by geometry if a container with
+// a container extension (or one of its helper widgets) is hit; otherwise
+// returns the widget as such (be it managed/unmanaged)
+
+QWidget *FormWindowBase::widgetUnderMouse(const QPoint &formPos, WidgetUnderMouseMode /* wum */)
+{
+ // widget_under_mouse might be some temporary thing like the dropLine. We need
+ // the actual widget that's part of the edited GUI.
+ QWidget *rc = widgetAt(formPos);
+ if (!rc || qobject_cast<ConnectionEdit*>(rc))
+ return 0;
+
+ if (rc == mainContainer()) {
+ // Refuse main container areas if the main container has a container extension,
+ // for example when hitting QToolBox/QTabWidget empty areas.
+ if (qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), rc))
+ return 0;
+ return rc;
+ }
+
+ // If we hit on container extension type container, make sure
+ // we use the top-most current page
+ if (QWidget *container = findContainer(rc, false))
+ if (QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), container)) {
+ // For container that do not have a "stacked" nature (QToolBox, QMdiArea),
+ // make sure the position is within the current page
+ const int ci = c->currentIndex();
+ if (ci < 0)
+ return 0;
+ QWidget *page = c->widget(ci);
+ QRect pageGeometry = page->geometry();
+ pageGeometry.moveTo(page->mapTo(this, pageGeometry.topLeft()));
+ if (!pageGeometry.contains(formPos))
+ return 0;
+ return page;
+ }
+
+ return rc;
+}
+
+void FormWindowBase::deleteWidgetList(const QWidgetList &widget_list)
+{
+ // We need a macro here even for single widgets because the some components (for example,
+ // the signal slot editor are connected to widgetRemoved() and add their
+ // own commands (for example, to delete w's connections)
+ const QString description = widget_list.size() == 1 ?
+ tr("Delete '%1'").arg(widget_list.front()->objectName()) : tr("Delete");
+
+ commandHistory()->beginMacro(description);
+ foreach (QWidget *w, widget_list) {
+ emit widgetRemoved(w);
+ DeleteWidgetCommand *cmd = new DeleteWidgetCommand(this);
+ cmd->init(w);
+ commandHistory()->push(cmd);
+ }
+ commandHistory()->endMacro();
+}
+
+QMenu *FormWindowBase::createExtensionTaskMenu(QDesignerFormWindowInterface *fw, QObject *o, bool trailingSeparator)
+{
+ typedef QList<QAction *> ActionList;
+ ActionList actions;
+ // 1) Standard public extension
+ QExtensionManager *em = fw->core()->extensionManager();
+ if (const QDesignerTaskMenuExtension *extTaskMenu = qt_extension<QDesignerTaskMenuExtension*>(em, o))
+ actions += extTaskMenu->taskActions();
+ if (const QDesignerTaskMenuExtension *intTaskMenu = qobject_cast<QDesignerTaskMenuExtension *>(em->extension(o, QLatin1String("QDesignerInternalTaskMenuExtension")))) {
+ if (!actions.empty()) {
+ QAction *a = new QAction(fw);
+ a->setSeparator(true);
+ actions.push_back(a);
+ }
+ actions += intTaskMenu->taskActions();
+ }
+ if (actions.empty())
+ return 0;
+ if (trailingSeparator && !actions.back()->isSeparator()) {
+ QAction *a = new QAction(fw);
+ a->setSeparator(true);
+ actions.push_back(a);
+ }
+ QMenu *rc = new QMenu;
+ const ActionList::const_iterator cend = actions.constEnd();
+ for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
+ rc->addAction(*it);
+ return rc;
+}
+
+void FormWindowBase::emitObjectRemoved(QObject *o)
+{
+ emit objectRemoved(o);
+}
+
+DeviceProfile FormWindowBase::deviceProfile() const
+{
+ return m_d->m_deviceProfile;
+}
+
+QString FormWindowBase::styleName() const
+{
+ return m_d->m_deviceProfile.isEmpty() ? QString() : m_d->m_deviceProfile.style();
+}
+
+void FormWindowBase::emitWidgetRemoved(QWidget *w)
+{
+ emit widgetRemoved(w);
+}
+
+QString FormWindowBase::deviceProfileName() const
+{
+ return m_d->m_deviceProfile.isEmpty() ? QString() : m_d->m_deviceProfile.name();
+}
+
+void FormWindowBase::setLineTerminatorMode(FormWindowBase::LineTerminatorMode mode)
+{
+ m_d->m_lineTerminatorMode = mode;
+}
+
+FormWindowBase::LineTerminatorMode FormWindowBase::lineTerminatorMode() const
+{
+ return m_d->m_lineTerminatorMode;
+}
+
+void FormWindowBase::triggerDefaultAction(QWidget *widget)
+{
+ if (QAction *action = qdesigner_internal::preferredEditAction(core(), widget))
+ QTimer::singleShot(0, action, SIGNAL(triggered()));
+}
+
+void FormWindowBase::setupDefaultAction(QDesignerFormWindowInterface *fw)
+{
+ QObject::connect(fw, SIGNAL(activated(QWidget*)), fw, SLOT(triggerDefaultAction(QWidget*)));
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/formwindowbase_p.h b/tools/designer/src/lib/shared/formwindowbase_p.h
new file mode 100644
index 0000000000..68e977efe5
--- /dev/null
+++ b/tools/designer/src/lib/shared/formwindowbase_p.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef FORMWINDOWBASE_H
+#define FORMWINDOWBASE_H
+
+#include "shared_global_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtCore/QVariantMap>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerDnDItemInterface;
+class QMenu;
+class QtResourceSet;
+class QDesignerPropertySheet;
+
+namespace qdesigner_internal {
+
+class QEditorFormBuilder;
+class DeviceProfile;
+class Grid;
+
+class DesignerPixmapCache;
+class DesignerIconCache;
+class FormWindowBasePrivate;
+
+class QDESIGNER_SHARED_EXPORT FormWindowBase: public QDesignerFormWindowInterface
+{
+ Q_OBJECT
+public:
+ enum HighlightMode { Restore, Highlight };
+ enum SaveResourcesBehaviour { SaveAll, SaveOnlyUsedQrcFiles, DontSaveQrcFiles };
+
+ explicit FormWindowBase(QDesignerFormEditorInterface *core, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~FormWindowBase();
+
+ QVariantMap formData();
+ void setFormData(const QVariantMap &vm);
+
+ // Return the widget containing the form. This is used to
+ // apply embedded design settings to that are inherited (for example font).
+ // These are meant to be applied to the form only and not to the other editors
+ // in the widget stack.
+ virtual QWidget *formContainer() const = 0;
+
+ // Deprecated
+ virtual QPoint grid() const;
+
+ // Deprecated
+ virtual void setGrid(const QPoint &grid);
+
+ virtual bool hasFeature(Feature f) const;
+ virtual Feature features() const;
+ virtual void setFeatures(Feature f);
+
+ const Grid &designerGrid() const;
+ void setDesignerGrid(const Grid& grid);
+
+ bool hasFormGrid() const;
+ void setHasFormGrid(bool b);
+
+ bool gridVisible() const;
+
+ SaveResourcesBehaviour saveResourcesBehaviour() const;
+ void setSaveResourcesBehaviour(SaveResourcesBehaviour behaviour);
+
+ static const Grid &defaultDesignerGrid();
+ static void setDefaultDesignerGrid(const Grid& grid);
+
+ // Overwrite to initialize and return a full popup menu for a managed widget
+ virtual QMenu *initializePopupMenu(QWidget *managedWidget);
+ // Helper to create a basic popup menu from task menu extensions (internal/public)
+ static QMenu *createExtensionTaskMenu(QDesignerFormWindowInterface *fw, QObject *o, bool trailingSeparator = true);
+
+ virtual bool dropWidgets(const QList<QDesignerDnDItemInterface*> &item_list, QWidget *target,
+ const QPoint &global_mouse_pos) = 0;
+
+ // Helper to find the widget at the mouse position with some flags.
+ enum WidgetUnderMouseMode { FindSingleSelectionDropTarget, FindMultiSelectionDropTarget };
+ QWidget *widgetUnderMouse(const QPoint &formPos, WidgetUnderMouseMode m);
+
+ virtual QWidget *widgetAt(const QPoint &pos) = 0;
+ virtual QWidget *findContainer(QWidget *w, bool excludeLayout) const = 0;
+
+ void deleteWidgetList(const QWidgetList &widget_list);
+
+ virtual void highlightWidget(QWidget *w, const QPoint &pos, HighlightMode mode = Highlight) = 0;
+
+ enum PasteMode { PasteAll, PasteActionsOnly };
+ virtual void paste(PasteMode pasteMode) = 0;
+
+ // Factory method to create a form builder
+ virtual QEditorFormBuilder *createFormBuilder() = 0;
+
+ virtual bool blockSelectionChanged(bool blocked) = 0;
+ virtual void emitSelectionChanged() = 0;
+
+ DesignerPixmapCache *pixmapCache() const;
+ DesignerIconCache *iconCache() const;
+ QtResourceSet *resourceSet() const;
+ void setResourceSet(QtResourceSet *resourceSet);
+ void addReloadableProperty(QDesignerPropertySheet *sheet, int index);
+ void removeReloadableProperty(QDesignerPropertySheet *sheet, int index);
+ void addReloadablePropertySheet(QDesignerPropertySheet *sheet, QObject *object);
+ void removeReloadablePropertySheet(QDesignerPropertySheet *sheet);
+ void reloadProperties();
+
+ void emitWidgetRemoved(QWidget *w);
+ void emitObjectRemoved(QObject *o);
+
+ DeviceProfile deviceProfile() const;
+ QString styleName() const;
+ QString deviceProfileName() const;
+
+ enum LineTerminatorMode {
+ LFLineTerminator,
+ CRLFLineTerminator,
+ NativeLineTerminator =
+#if defined (Q_OS_WIN)
+ CRLFLineTerminator
+#else
+ LFLineTerminator
+#endif
+ };
+
+ void setLineTerminatorMode(LineTerminatorMode mode);
+ LineTerminatorMode lineTerminatorMode() const;
+
+ // Connect the 'activated' (doubleclicked) signal of the form window to a
+ // slot triggering the default action (of the task menu)
+ static void setupDefaultAction(QDesignerFormWindowInterface *fw);
+
+public slots:
+ void resourceSetActivated(QtResourceSet *resourceSet, bool resourceSetChanged);
+
+private slots:
+ void triggerDefaultAction(QWidget *w);
+
+private:
+ void syncGridFeature();
+
+ FormWindowBasePrivate *m_d;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // FORMWINDOWBASE_H
diff --git a/tools/designer/src/lib/shared/grid.cpp b/tools/designer/src/lib/shared/grid.cpp
new file mode 100644
index 0000000000..99dbcee1e8
--- /dev/null
+++ b/tools/designer/src/lib/shared/grid.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "grid_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtGui/QPainter>
+#include <QtGui/QWidget>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+static const bool defaultSnap = true;
+static const bool defaultVisible = true;
+static const int DEFAULT_GRID = 10;
+static const char* KEY_VISIBLE = "gridVisible";
+static const char* KEY_SNAPX = "gridSnapX";
+static const char* KEY_SNAPY = "gridSnapY";
+static const char* KEY_DELTAX = "gridDeltaX";
+static const char* KEY_DELTAY = "gridDeltaY";
+
+// Insert a value into the serialization map unless default
+template <class T>
+ static inline void valueToVariantMap(T value, T defaultValue, const QString &key, QVariantMap &v, bool forceKey) {
+ if (forceKey || value != defaultValue)
+ v.insert(key, QVariant(value));
+ }
+
+// Obtain a value form QVariantMap
+template <class T>
+ static inline bool valueFromVariantMap(const QVariantMap &v, const QString &key, T &value) {
+ const QVariantMap::const_iterator it = v.constFind(key);
+ const bool found = it != v.constEnd();
+ if (found)
+ value = qVariantValue<T>(it.value());
+ return found;
+ }
+
+namespace qdesigner_internal
+{
+
+Grid::Grid() :
+ m_visible(defaultVisible),
+ m_snapX(defaultSnap),
+ m_snapY(defaultSnap),
+ m_deltaX(DEFAULT_GRID),
+ m_deltaY(DEFAULT_GRID)
+{
+}
+
+bool Grid::fromVariantMap(const QVariantMap& vm)
+{
+ *this = Grid();
+ valueFromVariantMap(vm, QLatin1String(KEY_VISIBLE), m_visible);
+ valueFromVariantMap(vm, QLatin1String(KEY_SNAPX), m_snapX);
+ valueFromVariantMap(vm, QLatin1String(KEY_SNAPY), m_snapY);
+ valueFromVariantMap(vm, QLatin1String(KEY_DELTAX), m_deltaX);
+ return valueFromVariantMap(vm, QLatin1String(KEY_DELTAY), m_deltaY);
+}
+
+QVariantMap Grid::toVariantMap(bool forceKeys) const
+{
+ QVariantMap rc;
+ addToVariantMap(rc, forceKeys);
+ return rc;
+}
+
+void Grid::addToVariantMap(QVariantMap& vm, bool forceKeys) const
+{
+ valueToVariantMap(m_visible, defaultVisible, QLatin1String(KEY_VISIBLE), vm, forceKeys);
+ valueToVariantMap(m_snapX, defaultSnap, QLatin1String(KEY_SNAPX), vm, forceKeys);
+ valueToVariantMap(m_snapY, defaultSnap, QLatin1String(KEY_SNAPY), vm, forceKeys);
+ valueToVariantMap(m_deltaX, DEFAULT_GRID, QLatin1String(KEY_DELTAX), vm, forceKeys);
+ valueToVariantMap(m_deltaY, DEFAULT_GRID, QLatin1String(KEY_DELTAY), vm, forceKeys);
+}
+
+void Grid::paint(QWidget *widget, QPaintEvent *e) const
+{
+ QPainter p(widget);
+ paint(p, widget, e);
+}
+
+void Grid::paint(QPainter &p, const QWidget *widget, QPaintEvent *e) const
+{
+ p.setPen(widget->palette().dark().color());
+
+ if (m_visible) {
+ const int xstart = (e->rect().x() / m_deltaX) * m_deltaX;
+ const int ystart = (e->rect().y() / m_deltaY) * m_deltaY;
+
+ const int xend = e->rect().right();
+ const int yend = e->rect().bottom();
+
+ typedef QVector<QPointF> Points;
+ static Points points;
+ points.clear();
+
+ for (int x = xstart; x <= xend; x += m_deltaX) {
+ points.reserve((yend - ystart) / m_deltaY + 1);
+ for (int y = ystart; y <= yend; y += m_deltaY)
+ points.push_back(QPointF(x, y));
+ p.drawPoints( &(*points.begin()), points.count());
+ points.clear();
+ }
+ }
+}
+
+int Grid::snapValue(int value, int grid) const
+{
+ const int rest = value % grid;
+ const int absRest = (rest < 0) ? -rest : rest;
+ int offset = 0;
+ if (2 * absRest > grid)
+ offset = 1;
+ if (rest < 0)
+ offset *= -1;
+ return (value / grid + offset) * grid;
+}
+
+QPoint Grid::snapPoint(const QPoint &p) const
+{
+ const int sx = m_snapX ? snapValue(p.x(), m_deltaX) : p.x();
+ const int sy = m_snapY ? snapValue(p.y(), m_deltaY) : p.y();
+ return QPoint(sx, sy);
+}
+
+int Grid::widgetHandleAdjustX(int x) const
+{
+ return m_snapX ? (x / m_deltaX) * m_deltaX + 1 : x;
+}
+
+int Grid::widgetHandleAdjustY(int y) const
+{
+ return m_snapY ? (y / m_deltaY) * m_deltaY + 1 : y;
+}
+
+bool Grid::equals(const Grid &rhs) const
+{
+ return m_visible == rhs.m_visible &&
+ m_snapX == rhs.m_snapX &&
+ m_snapY == rhs.m_snapY &&
+ m_deltaX == rhs.m_deltaX &&
+ m_deltaY == rhs.m_deltaY;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/grid_p.h b/tools/designer/src/lib/shared/grid_p.h
new file mode 100644
index 0000000000..b07217f424
--- /dev/null
+++ b/tools/designer/src/lib/shared/grid_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_GRID_H
+#define QDESIGNER_GRID_H
+
+#include "shared_global_p.h"
+
+#include <QtCore/QVariantMap>
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+class QPaintEvent;
+class QPainter;
+
+namespace qdesigner_internal {
+
+// Designer grid which is able to serialize to QVariantMap
+class QDESIGNER_SHARED_EXPORT Grid
+{
+public:
+ Grid();
+
+ bool fromVariantMap(const QVariantMap& vm);
+
+ void addToVariantMap(QVariantMap& vm, bool forceKeys = false) const;
+ QVariantMap toVariantMap(bool forceKeys = false) const;
+
+ inline bool visible() const { return m_visible; }
+ void setVisible(bool visible) { m_visible = visible; }
+
+ inline bool snapX() const { return m_snapX; }
+ void setSnapX(bool snap) { m_snapX = snap; }
+
+ inline bool snapY() const { return m_snapY; }
+ void setSnapY(bool snap) { m_snapY = snap; }
+
+ inline int deltaX() const { return m_deltaX; }
+ void setDeltaX(int dx) { m_deltaX = dx; }
+
+ inline int deltaY() const { return m_deltaY; }
+ void setDeltaY(int dy) { m_deltaY = dy; }
+
+ void paint(QWidget *widget, QPaintEvent *e) const;
+ void paint(QPainter &p, const QWidget *widget, QPaintEvent *e) const;
+
+ QPoint snapPoint(const QPoint &p) const;
+
+ int widgetHandleAdjustX(int x) const;
+ int widgetHandleAdjustY(int y) const;
+
+ inline bool operator==(const Grid &rhs) const { return equals(rhs); }
+ inline bool operator!=(const Grid &rhs) const { return !equals(rhs); }
+
+private:
+ bool equals(const Grid &rhs) const;
+ int snapValue(int value, int grid) const;
+ bool m_visible;
+ bool m_snapX;
+ bool m_snapY;
+ int m_deltaX;
+ int m_deltaY;
+};
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_GRID_H
diff --git a/tools/designer/src/lib/shared/gridpanel.cpp b/tools/designer/src/lib/shared/gridpanel.cpp
new file mode 100644
index 0000000000..f7658bae85
--- /dev/null
+++ b/tools/designer/src/lib/shared/gridpanel.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gridpanel_p.h"
+#include "ui_gridpanel.h"
+#include "grid_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+GridPanel::GridPanel(QWidget *parentWidget) :
+ QWidget(parentWidget)
+{
+ m_ui = new Ui::GridPanel;
+ m_ui->setupUi(this);
+
+ connect(m_ui->m_resetButton, SIGNAL(clicked()), this, SLOT(reset()));
+}
+
+GridPanel::~GridPanel()
+{
+ delete m_ui;
+}
+
+void GridPanel::setGrid(const Grid &g)
+{
+ m_ui->m_deltaXSpinBox->setValue(g.deltaX());
+ m_ui->m_deltaYSpinBox->setValue(g.deltaY());
+ m_ui->m_visibleCheckBox->setCheckState(g.visible() ? Qt::Checked : Qt::Unchecked);
+ m_ui->m_snapXCheckBox->setCheckState(g.snapX() ? Qt::Checked : Qt::Unchecked);
+ m_ui->m_snapYCheckBox->setCheckState(g.snapY() ? Qt::Checked : Qt::Unchecked);
+}
+
+void GridPanel::setTitle(const QString &title)
+{
+ m_ui->m_gridGroupBox->setTitle(title);
+}
+
+Grid GridPanel::grid() const
+{
+ Grid rc;
+ rc.setDeltaX(m_ui->m_deltaXSpinBox->value());
+ rc.setDeltaY(m_ui->m_deltaYSpinBox->value());
+ rc.setSnapX(m_ui->m_snapXCheckBox->checkState() == Qt::Checked);
+ rc.setSnapY(m_ui->m_snapYCheckBox->checkState() == Qt::Checked);
+ rc.setVisible(m_ui->m_visibleCheckBox->checkState() == Qt::Checked);
+ return rc;
+}
+
+void GridPanel::reset()
+{
+ setGrid(Grid());
+}
+
+void GridPanel::setCheckable (bool c)
+{
+ m_ui->m_gridGroupBox->setCheckable(c);
+}
+
+bool GridPanel::isCheckable () const
+{
+ return m_ui->m_gridGroupBox->isCheckable ();
+}
+
+bool GridPanel::isChecked () const
+{
+ return m_ui->m_gridGroupBox->isChecked ();
+}
+
+void GridPanel::setChecked(bool c)
+{
+ m_ui->m_gridGroupBox->setChecked(c);
+}
+
+void GridPanel::setResetButtonVisible(bool v)
+{
+ m_ui->m_resetButton->setVisible(v);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/gridpanel.ui b/tools/designer/src/lib/shared/gridpanel.ui
new file mode 100644
index 0000000000..adfdd3684a
--- /dev/null
+++ b/tools/designer/src/lib/shared/gridpanel.ui
@@ -0,0 +1,144 @@
+<ui version="4.0" >
+ <class>qdesigner_internal::GridPanel</class>
+ <widget class="QWidget" name="qdesigner_internal::GridPanel" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>393</width>
+ <height>110</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="m_gridGroupBox" >
+ <property name="title" >
+ <string>Grid</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QCheckBox" name="m_visibleCheckBox" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Visible</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Grid &amp;X</string>
+ </property>
+ <property name="buddy" >
+ <cstring>m_deltaXSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QSpinBox" name="m_deltaXSpinBox" >
+ <property name="minimum" >
+ <number>2</number>
+ </property>
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3" >
+ <widget class="QCheckBox" name="m_snapXCheckBox" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Snap</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QPushButton" name="m_resetButton" >
+ <property name="text" >
+ <string>Reset</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Grid &amp;Y</string>
+ </property>
+ <property name="buddy" >
+ <cstring>m_deltaYSpinBox</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QSpinBox" name="m_deltaYSpinBox" >
+ <property name="minimum" >
+ <number>2</number>
+ </property>
+ <property name="maximum" >
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <widget class="QCheckBox" name="m_snapYCheckBox" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Snap</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/lib/shared/gridpanel_p.h b/tools/designer/src/lib/shared/gridpanel_p.h
new file mode 100644
index 0000000000..c51b08c07f
--- /dev/null
+++ b/tools/designer/src/lib/shared/gridpanel_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Qt tools. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef GRIDPANEL_H
+#define GRIDPANEL_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class Grid;
+
+namespace Ui {
+ class GridPanel;
+}
+
+class QDESIGNER_SHARED_EXPORT GridPanel : public QWidget
+{
+ Q_OBJECT
+public:
+ GridPanel(QWidget *parent = 0);
+ ~GridPanel();
+
+ void setTitle(const QString &title);
+
+ void setGrid(const Grid &g);
+ Grid grid() const;
+
+ void setCheckable (bool c);
+ bool isCheckable () const;
+
+ bool isChecked () const;
+ void setChecked(bool c);
+
+ void setResetButtonVisible(bool v);
+
+private slots:
+ void reset();
+
+private:
+ Ui::GridPanel *m_ui;
+};
+
+} // qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // GRIDPANEL_H
diff --git a/tools/designer/src/lib/shared/htmlhighlighter.cpp b/tools/designer/src/lib/shared/htmlhighlighter.cpp
new file mode 100644
index 0000000000..ba07673a37
--- /dev/null
+++ b/tools/designer/src/lib/shared/htmlhighlighter.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QTextStream>
+
+#include "htmlhighlighter_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+HtmlHighlighter::HtmlHighlighter(QTextEdit *textEdit)
+ : QSyntaxHighlighter(textEdit)
+{
+ QTextCharFormat entityFormat;
+ entityFormat.setForeground(Qt::red);
+ setFormatFor(Entity, entityFormat);
+
+ QTextCharFormat tagFormat;
+ tagFormat.setForeground(Qt::darkMagenta);
+ tagFormat.setFontWeight(QFont::Bold);
+ setFormatFor(Tag, tagFormat);
+
+ QTextCharFormat commentFormat;
+ commentFormat.setForeground(Qt::gray);
+ commentFormat.setFontItalic(true);
+ setFormatFor(Comment, commentFormat);
+
+ QTextCharFormat attributeFormat;
+ attributeFormat.setForeground(Qt::black);
+ attributeFormat.setFontWeight(QFont::Bold);
+ setFormatFor(Attribute, attributeFormat);
+
+ QTextCharFormat valueFormat;
+ valueFormat.setForeground(Qt::blue);
+ setFormatFor(Value, valueFormat);
+}
+
+void HtmlHighlighter::setFormatFor(Construct construct,
+ const QTextCharFormat &format)
+{
+ m_formats[construct] = format;
+ rehighlight();
+}
+
+void HtmlHighlighter::highlightBlock(const QString &text)
+{
+ static const QLatin1Char tab = QLatin1Char('\t');
+ static const QLatin1Char space = QLatin1Char(' ');
+ static const QLatin1Char amp = QLatin1Char('&');
+ static const QLatin1Char startTag = QLatin1Char('<');
+ static const QLatin1Char endTag = QLatin1Char('>');
+ static const QLatin1Char quot = QLatin1Char('"');
+ static const QLatin1Char apos = QLatin1Char('\'');
+ static const QLatin1Char semicolon = QLatin1Char(';');
+ static const QLatin1Char equals = QLatin1Char('=');
+ static const QLatin1String startComment = QLatin1String("<!--");
+ static const QLatin1String endComment = QLatin1String("-->");
+ static const QLatin1String endElement = QLatin1String("/>");
+
+ int state = previousBlockState();
+ int len = text.length();
+ int start = 0;
+ int pos = 0;
+
+ while (pos < len) {
+ switch (state) {
+ case NormalState:
+ default:
+ while (pos < len) {
+ QChar ch = text.at(pos);
+ if (ch == startTag) {
+ if (text.mid(pos, 4) == startComment) {
+ state = InComment;
+ } else {
+ state = InTag;
+ start = pos;
+ while (pos < len && text.at(pos) != space
+ && text.at(pos) != endTag
+ && text.at(pos) != tab
+ && text.mid(pos, 2) != endElement)
+ ++pos;
+ if (text.mid(pos, 2) == endElement)
+ ++pos;
+ setFormat(start, pos - start,
+ m_formats[Tag]);
+ break;
+ }
+ break;
+ } else if (ch == amp) {
+ start = pos;
+ while (pos < len && text.at(pos++) != semicolon)
+ ;
+ setFormat(start, pos - start,
+ m_formats[Entity]);
+ } else {
+ // No tag, comment or entity started, continue...
+ ++pos;
+ }
+ }
+ break;
+ case InComment:
+ start = pos;
+ while (pos < len) {
+ if (text.mid(pos, 3) == endComment) {
+ pos += 3;
+ state = NormalState;
+ break;
+ } else {
+ ++pos;
+ }
+ }
+ setFormat(start, pos - start, m_formats[Comment]);
+ break;
+ case InTag:
+ QChar quote = QChar::Null;
+ while (pos < len) {
+ QChar ch = text.at(pos);
+ if (quote.isNull()) {
+ start = pos;
+ if (ch == apos || ch == quot) {
+ quote = ch;
+ } else if (ch == endTag) {
+ ++pos;
+ setFormat(start, pos - start, m_formats[Tag]);
+ state = NormalState;
+ break;
+ } else if (text.mid(pos, 2) == endElement) {
+ pos += 2;
+ setFormat(start, pos - start, m_formats[Tag]);
+ state = NormalState;
+ break;
+ } else if (ch != space && text.at(pos) != tab) {
+ // Tag not ending, not a quote and no whitespace, so
+ // we must be dealing with an attribute.
+ ++pos;
+ while (pos < len && text.at(pos) != space
+ && text.at(pos) != tab
+ && text.at(pos) != equals)
+ ++pos;
+ setFormat(start, pos - start, m_formats[Attribute]);
+ start = pos;
+ }
+ } else if (ch == quote) {
+ quote = QChar::Null;
+
+ // Anything quoted is a value
+ setFormat(start, pos - start, m_formats[Value]);
+ }
+ ++pos;
+ }
+ break;
+ }
+ }
+ setCurrentBlockState(state);
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/htmlhighlighter_p.h b/tools/designer/src/lib/shared/htmlhighlighter_p.h
new file mode 100644
index 0000000000..e841ec7071
--- /dev/null
+++ b/tools/designer/src/lib/shared/htmlhighlighter_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef HTMLHIGHLIGHTER_H
+#define HTMLHIGHLIGHTER_H
+
+#include <QtGui/QSyntaxHighlighter>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+/* HTML syntax highlighter based on Qt Quarterly example */
+class HtmlHighlighter : public QSyntaxHighlighter
+{
+ Q_OBJECT
+
+public:
+ enum Construct {
+ Entity,
+ Tag,
+ Comment,
+ Attribute,
+ Value,
+ LastConstruct = Value
+ };
+
+ HtmlHighlighter(QTextEdit *textEdit);
+
+ void setFormatFor(Construct construct, const QTextCharFormat &format);
+
+ QTextCharFormat formatFor(Construct construct) const
+ { return m_formats[construct]; }
+
+protected:
+ enum State {
+ NormalState = -1,
+ InComment,
+ InTag
+ };
+
+ void highlightBlock(const QString &text);
+
+private:
+ QTextCharFormat m_formats[LastConstruct + 1];
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // HTMLHIGHLIGHTER_H
diff --git a/tools/designer/src/lib/shared/iconloader.cpp b/tools/designer/src/lib/shared/iconloader.cpp
new file mode 100644
index 0000000000..b2df262a4f
--- /dev/null
+++ b/tools/designer/src/lib/shared/iconloader.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "iconloader_p.h"
+
+#include <QtCore/QFile>
+#include <QtGui/QIcon>
+#include <QtGui/QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QDESIGNER_SHARED_EXPORT QIcon createIconSet(const QString &name)
+{
+ QStringList candidates = QStringList()
+ << (QString::fromUtf8(":/trolltech/formeditor/images/") + name)
+#ifdef Q_WS_MAC
+ << (QString::fromUtf8(":/trolltech/formeditor/images/mac/") + name)
+#else
+ << (QString::fromUtf8(":/trolltech/formeditor/images/win/") + name)
+#endif
+ << (QString::fromUtf8(":/trolltech/formeditor/images/designer_") + name);
+
+ foreach (QString f, candidates) {
+ if (QFile::exists(f))
+ return QIcon(f);
+ }
+
+ return QIcon();
+}
+
+QDESIGNER_SHARED_EXPORT QIcon emptyIcon()
+{
+ static const QIcon empty_icon(QLatin1String(":/trolltech/formeditor/images/emptyicon.png"));
+ return empty_icon;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/lib/shared/iconloader_p.h b/tools/designer/src/lib/shared/iconloader_p.h
new file mode 100644
index 0000000000..572aab9d26
--- /dev/null
+++ b/tools/designer/src/lib/shared/iconloader_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ICONLOADER_H
+#define ICONLOADER_H
+
+#include "shared_global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QIcon;
+
+namespace qdesigner_internal {
+
+QDESIGNER_SHARED_EXPORT QIcon createIconSet(const QString &name);
+QDESIGNER_SHARED_EXPORT QIcon emptyIcon();
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ICONLOADER_H
diff --git a/tools/designer/src/lib/shared/iconselector.cpp b/tools/designer/src/lib/shared/iconselector.cpp
new file mode 100644
index 0000000000..02a3dee725
--- /dev/null
+++ b/tools/designer/src/lib/shared/iconselector.cpp
@@ -0,0 +1,546 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "iconselector_p.h"
+#include "qdesigner_utils_p.h"
+#include "qtresourcemodel_p.h"
+#include "qtresourceview_p.h"
+#include "iconloader_p.h"
+#include "qdesigner_integration_p.h"
+#include "formwindowbase_p.h"
+
+#include <abstractdialoggui_p.h>
+#include <qdesigner_integration_p.h>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerResourceBrowserInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QToolButton>
+#include <QtCore/QSignalMapper>
+#include <QtGui/QComboBox>
+#include <QtGui/QAction>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialog>
+#include <QtGui/QMenu>
+#include <QtGui/QApplication>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QImageReader>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QVBoxLayout>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// -------------------- LanguageResourceDialogPrivate
+class LanguageResourceDialogPrivate {
+ LanguageResourceDialog *q_ptr;
+ Q_DECLARE_PUBLIC(LanguageResourceDialog)
+
+public:
+ LanguageResourceDialogPrivate(QDesignerResourceBrowserInterface *rb);
+ void init(LanguageResourceDialog *p);
+
+ void setCurrentPath(const QString &filePath);
+ QString currentPath() const;
+
+ void slotAccepted();
+ void slotPathChanged(const QString &);
+
+private:
+ void setOkButtonEnabled(bool v) { m_dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(v); }
+ static bool checkPath(const QString &p);
+
+ QDesignerResourceBrowserInterface *m_browser;
+ QDialogButtonBox *m_dialogButtonBox;
+};
+
+LanguageResourceDialogPrivate::LanguageResourceDialogPrivate(QDesignerResourceBrowserInterface *rb) :
+ q_ptr(0),
+ m_browser(rb),
+ m_dialogButtonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel))
+{
+ setOkButtonEnabled(false);
+}
+
+void LanguageResourceDialogPrivate::init(LanguageResourceDialog *p)
+{
+ q_ptr = p;
+ QLayout *layout = new QVBoxLayout(p);
+ layout->addWidget(m_browser);
+ layout->addWidget(m_dialogButtonBox);
+ QObject::connect(m_dialogButtonBox, SIGNAL(accepted()), p, SLOT(slotAccepted()));
+ QObject::connect(m_dialogButtonBox, SIGNAL(rejected()), p, SLOT(reject()));
+ QObject::connect(m_browser, SIGNAL(currentPathChanged(QString)), p, SLOT(slotPathChanged(QString)));
+ QObject::connect(m_browser, SIGNAL(pathActivated(QString)), p, SLOT(slotAccepted()));
+ p->setModal(true);
+ p->setWindowTitle(LanguageResourceDialog::tr("Choose Resource"));
+ p->setWindowFlags(p->windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setOkButtonEnabled(false);
+}
+
+void LanguageResourceDialogPrivate::setCurrentPath(const QString &filePath)
+{
+ m_browser->setCurrentPath(filePath);
+ setOkButtonEnabled(checkPath(filePath));
+}
+
+QString LanguageResourceDialogPrivate::currentPath() const
+{
+ return m_browser->currentPath();
+}
+
+bool LanguageResourceDialogPrivate::checkPath(const QString &p)
+{
+ return p.isEmpty() ? false : IconSelector::checkPixmap(p, IconSelector::CheckFast);
+}
+
+void LanguageResourceDialogPrivate::slotAccepted()
+{
+ if (checkPath(currentPath()))
+ q_ptr->accept();
+}
+
+void LanguageResourceDialogPrivate::slotPathChanged(const QString &p)
+{
+ setOkButtonEnabled(checkPath(p));
+}
+
+// ------------ LanguageResourceDialog
+LanguageResourceDialog::LanguageResourceDialog(QDesignerResourceBrowserInterface *rb, QWidget *parent) :
+ QDialog(parent),
+ d_ptr(new LanguageResourceDialogPrivate(rb))
+{
+ d_ptr->init( this);
+}
+
+LanguageResourceDialog::~LanguageResourceDialog()
+{
+ delete d_ptr;
+}
+
+void LanguageResourceDialog::setCurrentPath(const QString &filePath)
+{
+ d_ptr->setCurrentPath(filePath);
+}
+
+QString LanguageResourceDialog::currentPath() const
+{
+ return d_ptr->currentPath();
+}
+
+LanguageResourceDialog* LanguageResourceDialog::create(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
+ if (QDesignerResourceBrowserInterface *rb = lang->createResourceBrowser(0))
+ return new LanguageResourceDialog(rb, parent);
+ if (QDesignerIntegration *di = qobject_cast<QDesignerIntegration*>(core->integration()))
+ if (QDesignerResourceBrowserInterface *rb = di->createResourceBrowser(0))
+ return new LanguageResourceDialog(rb, parent);
+ return 0;
+}
+
+// ------------ IconSelectorPrivate
+class IconSelectorPrivate
+{
+ IconSelector *q_ptr;
+ Q_DECLARE_PUBLIC(IconSelector)
+public:
+ IconSelectorPrivate();
+
+ void slotStateActivated();
+ void slotSetActivated();
+ void slotSetResourceActivated();
+ void slotSetFileActivated();
+ void slotResetActivated();
+ void slotResetAllActivated();
+ void slotUpdate();
+
+ QList<QPair<QPair<QIcon::Mode, QIcon::State>, QString> > m_stateToName; // could be static map
+
+ QMap<QPair<QIcon::Mode, QIcon::State>, int> m_stateToIndex;
+ QMap<int, QPair<QIcon::Mode, QIcon::State> > m_indexToState;
+
+ QIcon m_emptyIcon;
+ QComboBox *m_stateComboBox;
+ QToolButton *m_iconButton;
+ QAction *m_resetAction;
+ QAction *m_resetAllAction;
+ PropertySheetIconValue m_icon;
+ DesignerIconCache *m_iconCache;
+ DesignerPixmapCache *m_pixmapCache;
+ QtResourceModel *m_resourceModel;
+ QDesignerFormEditorInterface *m_core;
+};
+
+IconSelectorPrivate::IconSelectorPrivate() :
+ q_ptr(0),
+ m_stateComboBox(0),
+ m_iconButton(0),
+ m_resetAction(0),
+ m_resetAllAction(0),
+ m_iconCache(0),
+ m_pixmapCache(0),
+ m_resourceModel(0),
+ m_core(0)
+{
+}
+void IconSelectorPrivate::slotUpdate()
+{
+ QIcon icon;
+ if (m_iconCache)
+ icon = m_iconCache->icon(m_icon);
+
+ QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> paths = m_icon.paths();
+ QMapIterator<QPair<QIcon::Mode, QIcon::State>, int> itIndex(m_stateToIndex);
+ while (itIndex.hasNext()) {
+ const QPair<QIcon::Mode, QIcon::State> state = itIndex.next().key();
+ const PropertySheetPixmapValue pixmap = paths.value(state);
+ const int index = itIndex.value();
+
+ QIcon pixmapIcon = QIcon(icon.pixmap(16, 16, state.first, state.second));
+ if (pixmapIcon.isNull())
+ pixmapIcon = m_emptyIcon;
+ m_stateComboBox->setItemIcon(index, pixmapIcon);
+ QFont font = q_ptr->font();
+ if (!pixmap.path().isEmpty())
+ font.setBold(true);
+ m_stateComboBox->setItemData(index, font, Qt::FontRole);
+ }
+
+ QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
+ PropertySheetPixmapValue currentPixmap = paths.value(state);
+ m_resetAction->setEnabled(!currentPixmap.path().isEmpty());
+ m_resetAllAction->setEnabled(!paths.isEmpty());
+ m_stateComboBox->update();
+}
+
+void IconSelectorPrivate::slotStateActivated()
+{
+ slotUpdate();
+}
+
+void IconSelectorPrivate::slotSetActivated()
+{
+ QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
+ const PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
+ // Default to resource
+ const PropertySheetPixmapValue::PixmapSource ps = pixmap.path().isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : pixmap.pixmapSource(m_core);
+ switch (ps) {
+ case PropertySheetPixmapValue::LanguageResourcePixmap:
+ case PropertySheetPixmapValue::ResourcePixmap:
+ slotSetResourceActivated();
+ break;
+ case PropertySheetPixmapValue::FilePixmap:
+ slotSetFileActivated();
+ break;
+ }
+}
+
+// Choose a pixmap from resource; use language-dependent resource browser if present
+QString IconSelector::choosePixmapResource(QDesignerFormEditorInterface *core, QtResourceModel *resourceModel, const QString &oldPath, QWidget *parent)
+{
+ Q_UNUSED(resourceModel)
+ QString rc;
+
+ if (LanguageResourceDialog* ldlg = LanguageResourceDialog::create(core, parent)) {
+ ldlg->setCurrentPath(oldPath);
+ if (ldlg->exec() == QDialog::Accepted)
+ rc = ldlg->currentPath();
+ delete ldlg;
+ } else {
+ QtResourceViewDialog dlg(core, parent);
+
+ QDesignerIntegration *designerIntegration = qobject_cast<QDesignerIntegration *>(core->integration());
+ if (designerIntegration)
+ dlg.setResourceEditingEnabled(designerIntegration->isResourceEditingEnabled());
+
+ dlg.selectResource(oldPath);
+ if (dlg.exec() == QDialog::Accepted)
+ rc = dlg.selectedResource();
+ }
+ return rc;
+}
+
+void IconSelectorPrivate::slotSetResourceActivated()
+{
+ const QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
+
+ PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
+ const QString oldPath = pixmap.path();
+ const QString newPath = IconSelector::choosePixmapResource(m_core, m_resourceModel, oldPath, q_ptr);
+ if (newPath.isEmpty() || newPath == oldPath)
+ return;
+ const PropertySheetPixmapValue newPixmap = PropertySheetPixmapValue(newPath);
+ if (newPixmap != pixmap) {
+ m_icon.setPixmap(state.first, state.second, newPixmap);
+ slotUpdate();
+ emit q_ptr->iconChanged(m_icon);
+ }
+}
+
+// Helpers for choosing image files: Check for valid image.
+bool IconSelector::checkPixmap(const QString &fileName, CheckMode cm, QString *errorMessage)
+{
+ const QFileInfo fi(fileName);
+ if (!fi.exists() || !fi.isFile() || !fi.isReadable()) {
+ if (errorMessage)
+ *errorMessage = tr("The pixmap file '%1' cannot be read.").arg(fileName);
+ return false;
+ }
+ QImageReader reader(fileName);
+ if (!reader.canRead()) {
+ if (errorMessage)
+ *errorMessage = tr("The file '%1' does not appear to be a valid pixmap file: %2").arg(fileName).arg(reader.errorString());
+ return false;
+ }
+ if (cm == CheckFast)
+ return true;
+
+ const QImage image = reader.read();
+ if (image.isNull()) {
+ if (errorMessage)
+ *errorMessage = tr("The file '%1' could not be read: %2").arg(fileName).arg(reader.errorString());
+ return false;
+ }
+ return true;
+}
+
+// Helpers for choosing image files: Return an image filter for QFileDialog, courtesy of StyledButton
+static QString imageFilter()
+{
+ QString filter = QApplication::translate("IconSelector", "All Pixmaps (");
+ const QList<QByteArray> supportedImageFormats = QImageReader::supportedImageFormats();
+ const QString jpeg = QLatin1String("JPEG");
+ const int count = supportedImageFormats.count();
+ for (int i = 0; i< count; ++i) {
+ if (i)
+ filter += QLatin1Char(' ');
+ filter += QLatin1String("*.");
+ const QString outputFormat = QString::fromUtf8(supportedImageFormats.at(i));
+ if (outputFormat != jpeg)
+ filter += outputFormat.toLower();
+ else
+ filter += QLatin1String("jpg *.jpeg");
+ }
+ filter += QLatin1Char(')');
+ return filter;
+}
+
+// Helpers for choosing image files: Choose a file
+QString IconSelector::choosePixmapFile(const QString &directory, QDesignerDialogGuiInterface *dlgGui,QWidget *parent)
+{
+ QString errorMessage;
+ QString newPath;
+ do {
+ const QString title = tr("Choose a Pixmap");
+ static const QString filter = imageFilter();
+ newPath = dlgGui->getOpenImageFileName(parent, title, directory, filter);
+ if (newPath.isEmpty())
+ break;
+ if (checkPixmap(newPath, CheckFully, &errorMessage))
+ break;
+ dlgGui->message(parent, QDesignerDialogGuiInterface::ResourceEditorMessage, QMessageBox::Warning, tr("Pixmap Read Error"), errorMessage);
+ } while(true);
+ return newPath;
+}
+
+void IconSelectorPrivate::slotSetFileActivated()
+{
+ QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
+
+ PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
+ const QString newPath = IconSelector::choosePixmapFile(pixmap.path(), m_core->dialogGui(), q_ptr);
+ if (!newPath.isEmpty()) {
+ const PropertySheetPixmapValue newPixmap = PropertySheetPixmapValue(newPath);
+ if (!(newPixmap == pixmap)) {
+ m_icon.setPixmap(state.first, state.second, newPixmap);
+ slotUpdate();
+ emit q_ptr->iconChanged(m_icon);
+ }
+ }
+}
+
+void IconSelectorPrivate::slotResetActivated()
+{
+ QPair<QIcon::Mode, QIcon::State> state = m_indexToState.value(m_stateComboBox->currentIndex());
+
+ PropertySheetPixmapValue pixmap = m_icon.pixmap(state.first, state.second);
+ const PropertySheetPixmapValue newPixmap;
+ if (!(newPixmap == pixmap)) {
+ m_icon.setPixmap(state.first, state.second, newPixmap);
+ slotUpdate();
+ emit q_ptr->iconChanged(m_icon);
+ }
+}
+
+void IconSelectorPrivate::slotResetAllActivated()
+{
+ const PropertySheetIconValue newIcon;
+ if (!(m_icon == newIcon)) {
+ m_icon = newIcon;
+ slotUpdate();
+ emit q_ptr->iconChanged(m_icon);
+ }
+}
+
+// ------------- IconSelector
+IconSelector::IconSelector(QWidget *parent) :
+ QWidget(parent)
+{
+ d_ptr = new IconSelectorPrivate();
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_stateComboBox = new QComboBox(this);
+
+ QHBoxLayout *l = new QHBoxLayout(this);
+ d_ptr->m_iconButton = new QToolButton(this);
+ d_ptr->m_iconButton->setText(tr("..."));
+ d_ptr->m_iconButton->setPopupMode(QToolButton::MenuButtonPopup);
+ l->addWidget(d_ptr->m_stateComboBox);
+ l->addWidget(d_ptr->m_iconButton);
+ l->setMargin(0);
+
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Normal, QIcon::Off), tr("Normal Off") );
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Normal, QIcon::On), tr("Normal On") );
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Disabled, QIcon::Off), tr("Disabled Off") );
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Disabled, QIcon::On), tr("Disabled On") );
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Active, QIcon::Off), tr("Active Off") );
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Active, QIcon::On), tr("Active On") );
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::Off), tr("Selected Off") );
+ d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::On), tr("Selected On") );
+
+ QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ d_ptr->m_emptyIcon = QIcon(QPixmap::fromImage(img));
+
+ QMenu *setMenu = new QMenu(this);
+
+ QAction *setResourceAction = new QAction(tr("Choose Resource..."), this);
+ QAction *setFileAction = new QAction(tr("Choose File..."), this);
+ d_ptr->m_resetAction = new QAction(tr("Reset"), this);
+ d_ptr->m_resetAllAction = new QAction(tr("Reset All"), this);
+ d_ptr->m_resetAction->setEnabled(false);
+ d_ptr->m_resetAllAction->setEnabled(false);
+ //d_ptr->m_resetAction->setIcon(createIconSet(QString::fromUtf8("resetproperty.png")));
+
+ setMenu->addAction(setResourceAction);
+ setMenu->addAction(setFileAction);
+ setMenu->addSeparator();
+ setMenu->addAction(d_ptr->m_resetAction);
+ setMenu->addAction(d_ptr->m_resetAllAction);
+
+ int index = 0;
+ QStringList items;
+ QListIterator<QPair<QPair<QIcon::Mode, QIcon::State>, QString> > itName(d_ptr->m_stateToName);
+ while (itName.hasNext()) {
+ QPair<QPair<QIcon::Mode, QIcon::State>, QString> item = itName.next();
+ const QPair<QIcon::Mode, QIcon::State> state = item.first;
+ const QString name = item.second;
+
+ items.append(name);
+ d_ptr->m_stateToIndex[state] = index;
+ d_ptr->m_indexToState[index] = state;
+ index++;
+ }
+ d_ptr->m_stateComboBox->addItems(items);
+
+ d_ptr->m_iconButton->setMenu(setMenu);
+
+ connect(d_ptr->m_stateComboBox, SIGNAL(activated(int)), this, SLOT(slotStateActivated()));
+ connect(d_ptr->m_iconButton, SIGNAL(clicked()), this, SLOT(slotSetActivated()));
+ connect(setResourceAction, SIGNAL(triggered()), this, SLOT(slotSetResourceActivated()));
+ connect(setFileAction, SIGNAL(triggered()), this, SLOT(slotSetFileActivated()));
+ connect(d_ptr->m_resetAction, SIGNAL(triggered()), this, SLOT(slotResetActivated()));
+ connect(d_ptr->m_resetAllAction, SIGNAL(triggered()), this, SLOT(slotResetAllActivated()));
+
+ d_ptr->slotUpdate();
+}
+
+IconSelector::~IconSelector()
+{
+ delete d_ptr;
+}
+
+void IconSelector::setIcon(const PropertySheetIconValue &icon)
+{
+ if (d_ptr->m_icon == icon)
+ return;
+
+ d_ptr->m_icon = icon;
+ d_ptr->slotUpdate();
+}
+
+PropertySheetIconValue IconSelector::icon() const
+{
+ return d_ptr->m_icon;
+}
+
+void IconSelector::setFormEditor(QDesignerFormEditorInterface *core)
+{
+ d_ptr->m_core = core;
+ d_ptr->m_resourceModel = core->resourceModel();
+ d_ptr->slotUpdate();
+}
+
+void IconSelector::setIconCache(DesignerIconCache *iconCache)
+{
+ d_ptr->m_iconCache = iconCache;
+ connect(iconCache, SIGNAL(reloaded()), this, SLOT(slotUpdate()));
+ d_ptr->slotUpdate();
+}
+
+void IconSelector::setPixmapCache(DesignerPixmapCache *pixmapCache)
+{
+ d_ptr->m_pixmapCache = pixmapCache;
+ connect(pixmapCache, SIGNAL(reloaded()), this, SLOT(slotUpdate()));
+ d_ptr->slotUpdate();
+}
+
+} // qdesigner_internal
+
+QT_END_NAMESPACE
+
+#include "moc_iconselector_p.cpp"
+
diff --git a/tools/designer/src/lib/shared/iconselector_p.h b/tools/designer/src/lib/shared/iconselector_p.h
new file mode 100644
index 0000000000..6b70cd285c
--- /dev/null
+++ b/tools/designer/src/lib/shared/iconselector_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef ICONSELECTOR_H
+#define ICONSELECTOR_H
+
+#include "shared_global_p.h"
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QtResourceModel;
+class QDesignerFormEditorInterface;
+class QDesignerDialogGuiInterface;
+class QDesignerResourceBrowserInterface;
+
+namespace qdesigner_internal {
+
+class DesignerIconCache;
+class DesignerPixmapCache;
+class PropertySheetIconValue;
+
+// Resource Dialog that embeds the language-dependent resource widget as returned by the language extension
+class QDESIGNER_SHARED_EXPORT LanguageResourceDialog : public QDialog
+{
+ Q_OBJECT
+
+ LanguageResourceDialog(QDesignerResourceBrowserInterface *rb, QWidget *parent = 0);
+
+public:
+ virtual ~LanguageResourceDialog();
+ // Factory: Returns 0 if the language extension does not provide a resource browser.
+ static LanguageResourceDialog* create(QDesignerFormEditorInterface *core, QWidget *parent);
+
+ void setCurrentPath(const QString &filePath);
+ QString currentPath() const;
+
+private:
+ class LanguageResourceDialogPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(LanguageResourceDialog)
+ Q_DISABLE_COPY(LanguageResourceDialog)
+ Q_PRIVATE_SLOT(d_func(), void slotAccepted())
+ Q_PRIVATE_SLOT(d_func(), void slotPathChanged(QString))
+
+};
+
+class QDESIGNER_SHARED_EXPORT IconSelector: public QWidget
+{
+ Q_OBJECT
+public:
+ IconSelector(QWidget *parent = 0);
+ virtual ~IconSelector();
+
+ void setFormEditor(QDesignerFormEditorInterface *core); // required for dialog gui.
+ void setIconCache(DesignerIconCache *iconCache);
+ void setPixmapCache(DesignerPixmapCache *pixmapCache);
+
+ void setIcon(const PropertySheetIconValue &icon);
+ PropertySheetIconValue icon() const;
+
+ // Check whether a pixmap may be read
+ enum CheckMode { CheckFast, CheckFully };
+ static bool checkPixmap(const QString &fileName, CheckMode cm = CheckFully, QString *errorMessage = 0);
+ // Choose a pixmap from file
+ static QString choosePixmapFile(const QString &directory, QDesignerDialogGuiInterface *dlgGui, QWidget *parent);
+ // Choose a pixmap from resource; use language-dependent resource browser if present
+ static QString choosePixmapResource(QDesignerFormEditorInterface *core, QtResourceModel *resourceModel, const QString &oldPath, QWidget *parent);
+
+signals:
+ void iconChanged(const PropertySheetIconValue &icon);
+private:
+ class IconSelectorPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(IconSelector)
+ Q_DISABLE_COPY(IconSelector)
+
+ Q_PRIVATE_SLOT(d_func(), void slotStateActivated())
+ Q_PRIVATE_SLOT(d_func(), void slotSetActivated())
+ Q_PRIVATE_SLOT(d_func(), void slotSetResourceActivated())
+ Q_PRIVATE_SLOT(d_func(), void slotSetFileActivated())
+ Q_PRIVATE_SLOT(d_func(), void slotResetActivated())
+ Q_PRIVATE_SLOT(d_func(), void slotResetAllActivated())
+ Q_PRIVATE_SLOT(d_func(), void slotUpdate())
+};
+
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ICONSELECTOR_H
+
diff --git a/tools/designer/src/lib/shared/invisible_widget.cpp b/tools/designer/src/lib/shared/invisible_widget.cpp
new file mode 100644
index 0000000000..f88022c3f7
--- /dev/null
+++ b/tools/designer/src/lib/shared/invisible_widget.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "invisible_widget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+InvisibleWidget::InvisibleWidget(QWidget *parent)
+ : QWidget()
+{
+ setAttribute(Qt::WA_NoChildEventsForParent);
+ setParent(parent);
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/invisible_widget_p.h b/tools/designer/src/lib/shared/invisible_widget_p.h
new file mode 100644
index 0000000000..11c8f81c0c
--- /dev/null
+++ b/tools/designer/src/lib/shared/invisible_widget_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef INVISIBLE_WIDGET_H
+#define INVISIBLE_WIDGET_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT InvisibleWidget: public QWidget
+{
+ Q_OBJECT
+public:
+ InvisibleWidget(QWidget *parent = 0);
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // INVISIBLE_WIDGET_H
diff --git a/tools/designer/src/lib/shared/layout.cpp b/tools/designer/src/lib/shared/layout.cpp
new file mode 100644
index 0000000000..b1fe02ab71
--- /dev/null
+++ b/tools/designer/src/lib/shared/layout.cpp
@@ -0,0 +1,1326 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "layout_p.h"
+#include "qdesigner_utils_p.h"
+#include "qlayout_widget_p.h"
+#include "spacer_widget_p.h"
+#include "layoutdecoration.h"
+#include "widgetfactory_p.h"
+#include "qdesigner_widgetitem_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/QVector>
+
+#include <QtGui/qevent.h>
+#include <QtGui/QGridLayout>
+#include <QtGui/QPainter>
+#include <QtGui/QBitmap>
+#include <QtGui/QSplitter>
+#include <QtGui/QMainWindow>
+#include <QtGui/QApplication>
+#include <QtGui/QScrollArea>
+#include <QtGui/QFormLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QWizardPage>
+#include <QtGui/QWizard>
+#include <QtCore/QDebug>
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+enum { FormLayoutColumns = 2 };
+
+namespace qdesigner_internal {
+
+/* The wizard has a policy of setting a size policy of its external children
+ * according to the page being expanding or not (in the latter case, the
+ * page will be pushed to the top). When setting/breaking layouts, this needs
+ * to be updated, which happens via a fake style change event. */
+
+void updateWizardLayout(QWidget *layoutBase);
+
+class FriendlyWizardPage : public QWizardPage {
+ friend void updateWizardLayout(QWidget *);
+};
+
+void updateWizardLayout(QWidget *layoutBase)
+{
+ if (QWizardPage *wizardPage = qobject_cast<QWizardPage*>(layoutBase))
+ if (QWizard *wizard = static_cast<FriendlyWizardPage*>(wizardPage)->wizard()) {
+ QEvent event(QEvent::StyleChange);
+ QApplication::sendEvent(wizard, &event);
+ }
+}
+
+/*!
+ \class Layout layout.h
+ \brief Baseclass for layouting widgets in the Designer (Helper for Layout commands)
+ \internal
+
+ Classes derived from this abstract base class are used for layouting
+ operations in the Designer (creating/breaking layouts).
+
+ Instances live in the Layout/BreakLayout commands.
+*/
+
+/*! \a p specifies the parent of the layoutBase \a lb. The parent
+ might be changed in setup(). If the layoutBase is a
+ container, the parent and the layoutBase are the same. Also they
+ always have to be a widget known to the designer (e.g. in the case
+ of the tabwidget parent and layoutBase are the tabwidget and not the
+ page which actually gets laid out. For actual usage the correct
+ widget is found later by Layout.)
+ */
+
+Layout::Layout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb, LayoutInfo::Type layoutType) :
+ m_widgets(wl),
+ m_parentWidget(p),
+ m_layoutBase(lb),
+ m_formWindow(fw),
+ m_layoutType(layoutType),
+ m_reparentLayoutWidget(true),
+ m_isBreak(false)
+{
+ if (m_layoutBase)
+ m_oldGeometry = m_layoutBase->geometry();
+}
+
+Layout::~Layout()
+{
+}
+
+/*! The widget list we got in the constructor might contain too much
+ widgets (like widgets with different parents, already laid out
+ widgets, etc.). Here we set up the list and so the only the "best"
+ widgets get laid out.
+*/
+
+void Layout::setup()
+{
+ m_startPoint = QPoint(32767, 32767);
+
+ // Go through all widgets of the list we got. As we can only
+ // layout widgets which have the same parent, we first do some
+ // sorting which means create a list for each parent containing
+ // its child here. After that we keep working on the list of
+ // children which has the most entries.
+ // Widgets which are already laid out are thrown away here too
+
+ QMultiMap<QWidget*, QWidget*> lists;
+ foreach (QWidget *w, m_widgets) {
+ QWidget *p = w->parentWidget();
+
+ if (p && LayoutInfo::layoutType(m_formWindow->core(), p) != LayoutInfo::NoLayout
+ && m_formWindow->core()->metaDataBase()->item(p->layout()) != 0)
+ continue;
+
+ lists.insert(p, w);
+ }
+
+ QWidgetList lastList;
+ QWidgetList parents = lists.keys();
+ foreach (QWidget *p, parents) {
+ QWidgetList children = lists.values(p);
+
+ if (children.count() > lastList.count())
+ lastList = children;
+ }
+
+
+ // If we found no list (because no widget did fit at all) or the
+ // best list has only one entry and we do not layout a container,
+ // we leave here.
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_formWindow->core()->widgetDataBase();
+ if (lastList.count() < 2 &&
+ (!m_layoutBase ||
+ (!widgetDataBase->isContainer(m_layoutBase, false) &&
+ m_layoutBase != m_formWindow->mainContainer()))
+ ) {
+ m_widgets.clear();
+ m_startPoint = QPoint(0, 0);
+ return;
+ }
+
+ // Now we have a new and clean widget list, which makes sense
+ // to layout
+ m_widgets = lastList;
+ // Also use the only correct parent later, so store it
+
+ Q_ASSERT(m_widgets.isEmpty() == false);
+
+ m_parentWidget = m_formWindow->core()->widgetFactory()->widgetOfContainer(m_widgets.first()->parentWidget());
+ // Now calculate the position where the layout-meta-widget should
+ // be placed and connect to widgetDestroyed() signals of the
+ // widgets to get informed if one gets deleted to be able to
+ // handle that and do not crash in this case
+ foreach (QWidget *w, m_widgets) {
+ connect(w, SIGNAL(destroyed()), this, SLOT(widgetDestroyed()));
+ m_startPoint = QPoint(qMin(m_startPoint.x(), w->x()), qMin(m_startPoint.y(), w->y()));
+ const QRect rc(w->geometry());
+
+ m_geometries.insert(w, rc);
+ // Change the Z-order, as saving/loading uses the Z-order for
+ // writing/creating widgets and this has to be the same as in
+ // the layout. Else saving + loading will give different results
+ w->raise();
+ }
+
+ sort();
+}
+
+void Layout::widgetDestroyed()
+{
+ if (QWidget *w = qobject_cast<QWidget *>(sender())) {
+ m_widgets.removeAt(m_widgets.indexOf(w));
+ m_geometries.remove(w);
+ }
+}
+
+bool Layout::prepareLayout(bool &needMove, bool &needReparent)
+{
+ foreach (QWidget *widget, m_widgets) {
+ widget->raise();
+ }
+
+ needMove = !m_layoutBase;
+ needReparent = needMove || (m_reparentLayoutWidget && qobject_cast<QLayoutWidget*>(m_layoutBase)) || qobject_cast<QSplitter*>(m_layoutBase);
+
+ QDesignerWidgetFactoryInterface *widgetFactory = m_formWindow->core()->widgetFactory();
+ QDesignerMetaDataBaseInterface *metaDataBase = m_formWindow->core()->metaDataBase();
+
+ if (m_layoutBase == 0) {
+ const bool useSplitter = m_layoutType == LayoutInfo::HSplitter || m_layoutType == LayoutInfo::VSplitter;
+ const QString baseWidgetClassName = useSplitter ? QLatin1String("QSplitter") : QLatin1String("QLayoutWidget");
+ m_layoutBase = widgetFactory->createWidget(baseWidgetClassName, widgetFactory->containerOfWidget(m_parentWidget));
+ if (useSplitter) {
+ m_layoutBase->setObjectName(QLatin1String("splitter"));
+ m_formWindow->ensureUniqueObjectName(m_layoutBase);
+ }
+ } else {
+ LayoutInfo::deleteLayout(m_formWindow->core(), m_layoutBase);
+ }
+
+ metaDataBase->add(m_layoutBase);
+
+ Q_ASSERT(m_layoutBase->layout() == 0 || metaDataBase->item(m_layoutBase->layout()) == 0);
+
+ return true;
+}
+
+static bool isMainContainer(QDesignerFormWindowInterface *fw, const QWidget *w)
+{
+ return w && (w == fw || w == fw->mainContainer());
+}
+
+static bool isPageOfContainerWidget(QDesignerFormWindowInterface *fw, QWidget *widget)
+{
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(
+ fw->core()->extensionManager(), widget->parentWidget());
+
+ if (c != 0) {
+ for (int i = 0; i<c->count(); ++i) {
+ if (widget == c->widget(i))
+ return true;
+ }
+ }
+
+ return false;
+}
+void Layout::finishLayout(bool needMove, QLayout *layout)
+{
+ if (m_parentWidget == m_layoutBase) {
+ QWidget *widget = m_layoutBase;
+ m_oldGeometry = widget->geometry();
+
+ bool done = false;
+ while (!isMainContainer(m_formWindow, widget) && !done) {
+ if (!m_formWindow->isManaged(widget)) {
+ widget = widget->parentWidget();
+ continue;
+ } else if (LayoutInfo::isWidgetLaidout(m_formWindow->core(), widget)) {
+ widget = widget->parentWidget();
+ continue;
+ } else if (isPageOfContainerWidget(m_formWindow, widget)) {
+ widget = widget->parentWidget();
+ continue;
+ } else if (widget->parentWidget()) {
+ QScrollArea *area = qobject_cast<QScrollArea*>(widget->parentWidget()->parentWidget());
+ if (area && area->widget() == widget) {
+ widget = area;
+ continue;
+ }
+ }
+
+ done = true;
+ }
+ updateWizardLayout(m_layoutBase);
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ // We don't want to resize the form window
+ if (!Utils::isCentralWidget(m_formWindow, widget))
+ widget->adjustSize();
+
+ return;
+ }
+
+ if (needMove)
+ m_layoutBase->move(m_startPoint);
+
+ const QRect g(m_layoutBase->pos(), m_layoutBase->size());
+
+ if (LayoutInfo::layoutType(m_formWindow->core(), m_layoutBase->parentWidget()) == LayoutInfo::NoLayout && !m_isBreak)
+ m_layoutBase->adjustSize();
+ else if (m_isBreak)
+ m_layoutBase->setGeometry(m_oldGeometry);
+
+ m_oldGeometry = g;
+ if (layout)
+ layout->invalidate();
+ m_layoutBase->show();
+
+ if (qobject_cast<QLayoutWidget*>(m_layoutBase) || qobject_cast<QSplitter*>(m_layoutBase)) {
+ m_formWindow->clearSelection(false);
+ m_formWindow->manageWidget(m_layoutBase);
+ m_formWindow->selectWidget(m_layoutBase);
+ }
+}
+
+void Layout::undoLayout()
+{
+ if (!m_widgets.count())
+ return;
+
+ m_formWindow->selectWidget(m_layoutBase, false);
+
+ QDesignerWidgetFactoryInterface *widgetFactory = m_formWindow->core()->widgetFactory();
+ QHashIterator<QWidget *, QRect> it(m_geometries);
+ while (it.hasNext()) {
+ it.next();
+
+ if (!it.key())
+ continue;
+
+ QWidget* w = it.key();
+ const QRect rc = it.value();
+
+ const bool showIt = w->isVisibleTo(m_formWindow);
+ QWidget *container = widgetFactory->containerOfWidget(m_parentWidget);
+
+ // ### remove widget here
+ QWidget *parentWidget = w->parentWidget();
+ QDesignerFormEditorInterface *core = m_formWindow->core();
+ QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core->extensionManager(), parentWidget);
+
+ if (deco)
+ deco->removeWidget(w);
+
+ w->setParent(container);
+ w->setGeometry(rc);
+
+ if (showIt)
+ w->show();
+ }
+
+ LayoutInfo::deleteLayout(m_formWindow->core(), m_layoutBase);
+
+ if (m_parentWidget != m_layoutBase && !qobject_cast<QMainWindow*>(m_layoutBase)) {
+ m_formWindow->unmanageWidget(m_layoutBase);
+ m_layoutBase->hide();
+ } else {
+ QMainWindow *mw = qobject_cast<QMainWindow*>(m_formWindow->mainContainer());
+ if (m_layoutBase != m_formWindow->mainContainer() &&
+ (!mw || mw->centralWidget() != m_layoutBase))
+ m_layoutBase->setGeometry(m_oldGeometry);
+ }
+}
+
+void Layout::breakLayout()
+{
+ typedef QMap<QWidget *, QRect> WidgetRectMap;
+ WidgetRectMap rects;
+ /* Store the geometry of the widgets. The idea is to give the user space
+ * to rearrange them, so, we do a adjustSize() on them, unless they want
+ * to grow (expanding widgets like QTextEdit), in which the geometry is
+ * preserved. Note that historically, geometries were re-applied
+ * only after breaking splitters. */
+ foreach (QWidget *w, m_widgets) {
+ const QRect geom = w->geometry();
+ const QSize sizeHint = w->sizeHint();
+ const bool restoreGeometry = sizeHint.isEmpty() || sizeHint.width() > geom.width() || sizeHint.height() > geom.height();
+ rects.insert(w, restoreGeometry ? w->geometry() : QRect(geom.topLeft(), QSize()));
+ }
+ const QPoint m_layoutBasePos = m_layoutBase->pos();
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_formWindow->core()->widgetDataBase();
+
+ LayoutInfo::deleteLayout(m_formWindow->core(), m_layoutBase);
+
+ const bool needReparent = (m_reparentLayoutWidget && qobject_cast<QLayoutWidget*>(m_layoutBase)) ||
+ qobject_cast<QSplitter*>(m_layoutBase) ||
+ (!widgetDataBase->isContainer(m_layoutBase, false) &&
+ m_layoutBase != m_formWindow->mainContainer());
+ const bool add = m_geometries.isEmpty();
+
+ QMapIterator<QWidget*, QRect> it(rects);
+ while (it.hasNext()) {
+ it.next();
+
+ QWidget *w = it.key();
+ if (needReparent) {
+ w->setParent(m_layoutBase->parentWidget(), 0);
+ w->move(m_layoutBasePos + it.value().topLeft());
+ w->show();
+ }
+
+ const QRect oldGeometry = it.value();
+ if (oldGeometry.isEmpty()) {
+ w->adjustSize();
+ } else {
+ w->resize(oldGeometry.size());
+ }
+
+ if (add)
+ m_geometries.insert(w, QRect(w->pos(), w->size()));
+ }
+
+ if (needReparent) {
+ m_layoutBase->hide();
+ m_parentWidget = m_layoutBase->parentWidget();
+ m_formWindow->unmanageWidget(m_layoutBase);
+ } else {
+ m_parentWidget = m_layoutBase;
+ }
+ updateWizardLayout(m_layoutBase);
+
+ if (!m_widgets.isEmpty() && m_widgets.first() && m_widgets.first()->isVisibleTo(m_formWindow))
+ m_formWindow->selectWidget(m_widgets.first());
+ else
+ m_formWindow->selectWidget(m_formWindow);
+}
+
+static QString suggestLayoutName(const char *className)
+{
+ // Legacy
+ if (!qstrcmp(className, "QHBoxLayout"))
+ return QLatin1String("horizontalLayout");
+ if (!qstrcmp(className, "QVBoxLayout"))
+ return QLatin1String("verticalLayout");
+ if (!qstrcmp(className, "QGridLayout"))
+ return QLatin1String("gridLayout");
+
+ return qtify(QString::fromUtf8(className));
+}
+QLayout *Layout::createLayout(int type)
+{
+ Q_ASSERT(m_layoutType != LayoutInfo::HSplitter && m_layoutType != LayoutInfo::VSplitter);
+ QLayout *layout = m_formWindow->core()->widgetFactory()->createLayout(m_layoutBase, 0, type);
+ // set a name
+ layout->setObjectName(suggestLayoutName(layout->metaObject()->className()));
+ m_formWindow->ensureUniqueObjectName(layout);
+ // QLayoutWidget
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(m_formWindow->core()->extensionManager(), layout);
+ if (sheet && qobject_cast<QLayoutWidget*>(m_layoutBase)) {
+ sheet->setProperty(sheet->indexOf(QLatin1String("leftMargin")), 0);
+ sheet->setProperty(sheet->indexOf(QLatin1String("topMargin")), 0);
+ sheet->setProperty(sheet->indexOf(QLatin1String("rightMargin")), 0);
+ sheet->setProperty(sheet->indexOf(QLatin1String("bottomMargin")), 0);
+ }
+ return layout;
+}
+
+void Layout::reparentToLayoutBase(QWidget *w)
+{
+ if (w->parent() != m_layoutBase) {
+ w->setParent(m_layoutBase, 0);
+ w->move(QPoint(0,0));
+ }
+}
+
+namespace { // within qdesigner_internal
+
+// ----- PositionSortPredicate: Predicate to be usable as LessThan function to sort widgets by position
+class PositionSortPredicate {
+public:
+ PositionSortPredicate(Qt::Orientation orientation) : m_orientation(orientation) {}
+ bool operator()(const QWidget* w1, const QWidget* w2) {
+ return m_orientation == Qt::Horizontal ? w1->x() < w2->x() : w1->y() < w2->y();
+ }
+ private:
+ const Qt::Orientation m_orientation;
+};
+
+// -------- BoxLayout
+class BoxLayout : public Layout
+{
+public:
+ BoxLayout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb,
+ Qt::Orientation orientation);
+
+ virtual void doLayout();
+ virtual void sort();
+
+private:
+ const Qt::Orientation m_orientation;
+};
+
+BoxLayout::BoxLayout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb,
+ Qt::Orientation orientation) :
+ Layout(wl, p, fw, lb, orientation == Qt::Horizontal ? LayoutInfo::HBox : LayoutInfo::VBox),
+ m_orientation(orientation)
+{
+}
+
+void BoxLayout::sort()
+{
+ QWidgetList wl = widgets();
+ qStableSort(wl.begin(), wl.end(), PositionSortPredicate(m_orientation));
+ setWidgets(wl);
+}
+
+void BoxLayout::doLayout()
+{
+ bool needMove, needReparent;
+ if (!prepareLayout(needMove, needReparent))
+ return;
+
+ QBoxLayout *layout = static_cast<QBoxLayout *>(createLayout(m_orientation == Qt::Horizontal ? LayoutInfo::HBox : LayoutInfo::VBox));
+
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+
+ const QWidgetList::const_iterator cend = widgets().constEnd();
+ for (QWidgetList::const_iterator it = widgets().constBegin(); it != cend; ++it) {
+ QWidget *w = *it;
+ if (needReparent)
+ reparentToLayoutBase(w);
+
+ if (const Spacer *spacer = qobject_cast<const Spacer*>(w))
+ layout->addWidget(w, 0, spacer->alignment());
+ else
+ layout->addWidget(w);
+ w->show();
+ }
+ finishLayout(needMove, layout);
+}
+
+// -------- SplitterLayout
+class SplitterLayout : public Layout
+{
+public:
+ SplitterLayout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb,
+ Qt::Orientation orientation);
+
+ virtual void doLayout();
+ virtual void sort();
+
+private:
+ const Qt::Orientation m_orientation;
+};
+
+SplitterLayout::SplitterLayout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb,
+ Qt::Orientation orientation) :
+ Layout(wl, p, fw, lb, orientation == Qt::Horizontal ? LayoutInfo::HSplitter : LayoutInfo::VSplitter),
+ m_orientation(orientation)
+{
+}
+
+void SplitterLayout::sort()
+{
+ QWidgetList wl = widgets();
+ qStableSort(wl.begin(), wl.end(), PositionSortPredicate(m_orientation));
+ setWidgets(wl);
+}
+
+void SplitterLayout::doLayout()
+{
+ bool needMove, needReparent;
+ if (!prepareLayout(needMove, needReparent))
+ return;
+
+ QSplitter *splitter = qobject_cast<QSplitter*>(layoutBaseWidget());
+ Q_ASSERT(splitter != 0);
+
+
+ const QWidgetList::const_iterator cend = widgets().constEnd();
+ for (QWidgetList::const_iterator it = widgets().constBegin(); it != cend; ++it) {
+ QWidget *w = *it;
+ if (needReparent)
+ reparentToLayoutBase(w);
+ splitter->addWidget(w);
+ w->show();
+ }
+
+ splitter->setOrientation(m_orientation);
+ finishLayout(needMove);
+}
+
+// ---------- Grid: Helper for laying out grids
+
+class Grid
+{
+public:
+ enum Mode {
+ GridLayout, // Arbitrary size/supports span
+ FormLayout // 2-column/no span
+ };
+
+ Grid(Mode mode);
+ void resize(int nrows, int ncols);
+
+ ~Grid();
+
+ QWidget* cell(int row, int col) const { return m_cells[ row * m_ncols + col]; }
+
+ void setCells(const QRect &c, QWidget* w);
+
+ bool empty() const { return m_nrows * m_ncols; }
+ int numRows() const { return m_nrows; }
+ int numCols() const { return m_ncols; }
+
+ void simplify();
+ bool locateWidget(QWidget* w, int& row, int& col, int& rowspan, int& colspan) const;
+
+ QDebug debug(QDebug str) const;
+
+private:
+ void setCell(int row, int col, QWidget* w) { m_cells[ row * m_ncols + col] = w; }
+ void swapCells(int r1, int c1, int r2, int c2);
+ void shrink();
+ void reallocFormLayout();
+ int countRow(int r, int c) const;
+ int countCol(int r, int c) const;
+ void setRow(int r, int c, QWidget* w, int count);
+ void setCol(int r, int c, QWidget* w, int count);
+ bool isWidgetStartCol(int c) const;
+ bool isWidgetEndCol(int c) const;
+ bool isWidgetStartRow(int r) const;
+ bool isWidgetEndRow(int r) const;
+ bool isWidgetTopLeft(int r, int c) const;
+ void extendLeft();
+ void extendRight();
+ void extendUp();
+ void extendDown();
+ bool shrinkFormLayoutSpans();
+
+ const Mode m_mode;
+ int m_nrows;
+ int m_ncols;
+
+ QWidget** m_cells; // widget matrix w11, w12, w21...
+};
+
+Grid::Grid(Mode mode) :
+ m_mode(mode),
+ m_nrows(0),
+ m_ncols(0),
+ m_cells(0)
+{
+}
+
+Grid::~Grid()
+{
+ delete [] m_cells;
+}
+
+void Grid::resize(int nrows, int ncols)
+{
+ delete [] m_cells;
+ m_cells = 0;
+ m_nrows = nrows;
+ m_ncols = ncols;
+ if (const int allocSize = m_nrows * m_ncols) {
+ m_cells = new QWidget*[allocSize];
+ qFill(m_cells, m_cells + allocSize, static_cast<QWidget *>(0));
+ }
+}
+
+QDebug Grid::debug(QDebug str) const
+{
+ str << m_nrows << 'x' << m_ncols << '\n';
+ QSet<QWidget *> widgets;
+ const int cellCount = m_nrows * m_ncols;
+ int row, col, rowspan, colspan;
+ for (int c = 0; c < cellCount; c++)
+ if (QWidget *w = m_cells[c])
+ if (!widgets.contains(w)) {
+ widgets.insert(w);
+ locateWidget(w, row, col, rowspan, colspan);
+ str << w << " at " << row << col << rowspan << 'x' << colspan << '\n';
+ }
+ for (int r = 0; r < m_nrows; r++)
+ for (int c = 0; c < m_ncols; c++)
+ str << "At " << r << c << cell(r, c) << '\n';
+
+ return str;
+}
+
+static inline QDebug operator<<(QDebug str, const Grid &g) { return g.debug(str); }
+
+void Grid::setCells(const QRect &c, QWidget* w)
+{
+ const int bottom = c.top() + c.height();
+ const int width = c.width();
+
+ for (int r = c.top(); r < bottom; r++) {
+ QWidget **pos = m_cells + r * m_ncols + c.left();
+ qFill(pos, pos + width, w);
+ }
+}
+
+
+void Grid::swapCells(int r1, int c1, int r2, int c2)
+{
+ QWidget *w1 = cell(r1, c1);
+ setCell(r1, c1, cell(r2, c2));
+ setCell(r2, c2, w1);
+}
+
+int Grid::countRow(int r, int c) const
+{
+ QWidget* w = cell(r, c);
+ int i = c + 1;
+ while (i < m_ncols && cell(r, i) == w)
+ i++;
+ return i - c;
+}
+
+int Grid::countCol(int r, int c) const
+{
+ QWidget* w = cell(r, c);
+ int i = r + 1;
+ while (i < m_nrows && cell(i, c) == w)
+ i++;
+ return i - r;
+}
+
+void Grid::setCol(int r, int c, QWidget* w, int count)
+{
+ for (int i = 0; i < count; i++)
+ setCell(r + i, c, w);
+}
+
+void Grid::setRow(int r, int c, QWidget* w, int count)
+{
+ for (int i = 0; i < count; i++)
+ setCell(r, c + i, w);
+}
+
+bool Grid::isWidgetStartCol(int c) const
+{
+ for (int r = 0; r < m_nrows; r++) {
+ if (cell(r, c) && ((c==0) || (cell(r, c) != cell(r, c-1)))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Grid::isWidgetEndCol(int c) const
+{
+ for (int r = 0; r < m_nrows; r++) {
+ if (cell(r, c) && ((c == m_ncols-1) || (cell(r, c) != cell(r, c+1))))
+ return true;
+ }
+ return false;
+}
+
+bool Grid::isWidgetStartRow(int r) const
+{
+ for ( int c = 0; c < m_ncols; c++) {
+ if (cell(r, c) && ((r==0) || (cell(r, c) != cell(r-1, c))))
+ return true;
+ }
+ return false;
+}
+
+bool Grid::isWidgetEndRow(int r) const
+{
+ for (int c = 0; c < m_ncols; c++) {
+ if (cell(r, c) && ((r == m_nrows-1) || (cell(r, c) != cell(r+1, c))))
+ return true;
+ }
+ return false;
+}
+
+
+bool Grid::isWidgetTopLeft(int r, int c) const
+{
+ QWidget* w = cell(r, c);
+ if (!w)
+ return false;
+ return (!r || cell(r-1, c) != w) && (!c || cell(r, c-1) != w);
+}
+
+void Grid::extendLeft()
+{
+ for (int c = 1; c < m_ncols; c++) {
+ for (int r = 0; r < m_nrows; r++) {
+ QWidget* w = cell(r, c);
+ if (!w)
+ continue;
+
+ const int cc = countCol(r, c);
+ int stretch = 0;
+ for (int i = c-1; i >= 0; i--) {
+ if (cell(r, i))
+ break;
+ if (countCol(r, i) < cc)
+ break;
+ if (isWidgetEndCol(i))
+ break;
+ if (isWidgetStartCol(i)) {
+ stretch = c - i;
+ break;
+ }
+ }
+ if (stretch) {
+ for (int i = 0; i < stretch; i++)
+ setCol(r, c-i-1, w, cc);
+ }
+ }
+ }
+}
+
+
+void Grid::extendRight()
+{
+ for (int c = m_ncols - 2; c >= 0; c--) {
+ for (int r = 0; r < m_nrows; r++) {
+ QWidget* w = cell(r, c);
+ if (!w)
+ continue;
+ const int cc = countCol(r, c);
+ int stretch = 0;
+ for (int i = c+1; i < m_ncols; i++) {
+ if (cell(r, i))
+ break;
+ if (countCol(r, i) < cc)
+ break;
+ if (isWidgetStartCol(i))
+ break;
+ if (isWidgetEndCol(i)) {
+ stretch = i - c;
+ break;
+ }
+ }
+ if (stretch) {
+ for (int i = 0; i < stretch; i++)
+ setCol(r, c+i+1, w, cc);
+ }
+ }
+ }
+
+}
+
+void Grid::extendUp()
+{
+ for (int r = 1; r < m_nrows; r++) {
+ for (int c = 0; c < m_ncols; c++) {
+ QWidget* w = cell(r, c);
+ if (!w)
+ continue;
+ const int cr = countRow(r, c);
+ int stretch = 0;
+ for (int i = r-1; i >= 0; i--) {
+ if (cell(i, c))
+ break;
+ if (countRow(i, c) < cr)
+ break;
+ if (isWidgetEndRow(i))
+ break;
+ if (isWidgetStartRow(i)) {
+ stretch = r - i;
+ break;
+ }
+ }
+ if (stretch) {
+ for (int i = 0; i < stretch; i++)
+ setRow(r-i-1, c, w, cr);
+ }
+ }
+ }
+}
+
+void Grid::extendDown()
+{
+ for (int r = m_nrows - 2; r >= 0; r--) {
+ for (int c = 0; c < m_ncols; c++) {
+ QWidget* w = cell(r, c);
+ if (!w)
+ continue;
+ const int cr = countRow(r, c);
+ int stretch = 0;
+ for (int i = r+1; i < m_nrows; i++) {
+ if (cell(i, c))
+ break;
+ if (countRow(i, c) < cr)
+ break;
+ if (isWidgetStartRow(i))
+ break;
+ if (isWidgetEndRow(i)) {
+ stretch = i - r;
+ break;
+ }
+ }
+ if (stretch) {
+ for (int i = 0; i < stretch; i++)
+ setRow(r+i+1, c, w, cr);
+ }
+ }
+ }
+}
+
+void Grid::simplify()
+{
+ switch (m_mode) {
+ case GridLayout:
+ // Grid: Extend all widgets to occupy most space and delete
+ // rows/columns that are not bordering on a widget
+ extendLeft();
+ extendRight();
+ extendUp();
+ extendDown();
+ shrink();
+ break;
+ case FormLayout:
+ // Form: First treat it as a grid to get the same behaviour
+ // regarding spanning and shrinking. Then restrict the span to
+ // the horizontal span possible in the form, simplify again
+ // and spread the widgets over a 2-column layout
+ extendLeft();
+ extendRight();
+ extendUp();
+ extendDown();
+ shrink();
+ if (shrinkFormLayoutSpans())
+ shrink();
+ reallocFormLayout();
+ break;
+ }
+
+}
+
+void Grid::shrink()
+{
+ // tick off the occupied cols/rows (bordering on widget edges)
+ QVector<bool> columns(m_ncols, false);
+ QVector<bool> rows(m_nrows, false);
+
+ for (int c = 0; c < m_ncols; c++)
+ for (int r = 0; r < m_nrows; r++)
+ if (isWidgetTopLeft(r, c))
+ rows[r] = columns[c] = true;
+
+ // remove empty cols/rows
+ const int simplifiedNCols = columns.count(true);
+ const int simplifiedNRows = rows.count(true);
+ if (simplifiedNCols == m_ncols && simplifiedNRows == m_nrows)
+ return;
+ // reallocate and copy omitting the empty cells
+ QWidget **simplifiedCells = new QWidget*[simplifiedNCols * simplifiedNRows];
+ qFill(simplifiedCells, simplifiedCells + simplifiedNCols * simplifiedNRows, static_cast<QWidget *>(0));
+ QWidget **simplifiedPtr = simplifiedCells;
+
+ for (int r = 0; r < m_nrows; r++)
+ if (rows[r])
+ for (int c = 0; c < m_ncols; c++)
+ if (columns[c]) {
+ if (QWidget *w = cell(r, c))
+ *simplifiedPtr = w;
+ simplifiedPtr++;
+ }
+ Q_ASSERT(simplifiedPtr == simplifiedCells + simplifiedNCols * simplifiedNRows);
+ delete [] m_cells;
+ m_cells = simplifiedCells;
+ m_nrows = simplifiedNRows;
+ m_ncols = simplifiedNCols;
+}
+
+bool Grid::shrinkFormLayoutSpans()
+{
+ bool shrunk = false;
+ typedef QSet<QWidget*> WidgetSet;
+ // Determine unique set of widgets
+ WidgetSet widgets;
+ QWidget **end = m_cells + m_ncols * m_nrows;
+ for (QWidget **wptr = m_cells; wptr < end; wptr++)
+ if (QWidget *w = *wptr)
+ widgets.insert(w);
+ // Restrict the widget span: max horizontal span at column 0: 2, anything else: 1
+ const int maxRowSpan = 1;
+ const WidgetSet::const_iterator cend = widgets.constEnd();
+ for (WidgetSet::const_iterator it = widgets.constBegin(); it != cend ; ++it) {
+ QWidget *w = *it;
+ int row, col, rowspan, colspan;
+ locateWidget(w, row, col, rowspan, colspan);
+ const int maxColSpan = col == 0 ? 2 : 1;
+ const int newColSpan = qMin(colspan, maxColSpan);
+ const int newRowSpan = qMin(rowspan, maxRowSpan);
+ if (newColSpan != colspan || newRowSpan != rowspan) {
+ setCells(QRect(col, row, colspan, rowspan), 0);
+ setCells(QRect(col, row, newColSpan, newRowSpan), w);
+ shrunk = true;
+ }
+ }
+ return shrunk;
+}
+
+void Grid::reallocFormLayout()
+{
+ // Columns matching? -> happy!
+ if (m_ncols == FormLayoutColumns)
+ return;
+
+ // If there are offset columns (starting past the field column),
+ // move them to the left and squeeze them. This also prevents the
+ // following reallocation from creating empty form rows.
+ int pastRightWidgetCount = 0;
+ if (m_ncols > FormLayoutColumns) {
+ for (int r = 0; r < m_nrows; r++) {
+ // Try to find a column where the form columns are empty and
+ // there are widgets further to the right.
+ if (cell(r, 0) == 0 && cell(r, 1) == 0) {
+ int sourceCol = FormLayoutColumns;
+ QWidget *firstWidget = 0;
+ for ( ; sourceCol < m_ncols; sourceCol++)
+ if (QWidget *w = cell(r, sourceCol)) {
+ firstWidget = w;
+ break;
+ }
+ if (firstWidget) {
+ // Move/squeeze. Copy to beginning of column if it is a label, else field
+ int targetCol = qobject_cast<QLabel*>(firstWidget) ? 0 : 1;
+ for ( ; sourceCol < m_ncols; sourceCol++)
+ if (QWidget *w = cell(r, sourceCol))
+ setCell(r, targetCol++, w);
+ // Pad with zero
+ for ( ; targetCol < m_ncols; targetCol++)
+ setCell(r, targetCol, 0);
+ }
+ }
+ // Any protruding widgets left on that row?
+ for (int c = FormLayoutColumns; c < m_ncols; c++)
+ if (cell(r, c))
+ pastRightWidgetCount++;
+ }
+ }
+ // Reallocate with 2 columns. Just insert the protruding ones as fields.
+ const int formNRows = m_nrows + pastRightWidgetCount;
+ QWidget **formCells = new QWidget*[FormLayoutColumns * formNRows];
+ qFill(formCells, formCells + FormLayoutColumns * formNRows, static_cast<QWidget *>(0));
+ QWidget **formPtr = formCells;
+ const int matchingColumns = qMin(m_ncols, static_cast<int>(FormLayoutColumns));
+ for (int r = 0; r < m_nrows; r++) {
+ int c = 0;
+ for ( ; c < matchingColumns; c++) // Just copy over matching columns
+ *formPtr++ = cell(r, c);
+ formPtr += FormLayoutColumns - matchingColumns; // In case old format was 1 column
+ // protruding widgets: Insert as single-field rows
+ for ( ; c < m_ncols; c++)
+ if (QWidget *w = cell(r, c)) {
+ formPtr++;
+ *formPtr++ = w;
+ }
+ }
+ Q_ASSERT(formPtr == formCells + FormLayoutColumns * formNRows);
+ delete [] m_cells;
+ m_cells = formCells;
+ m_nrows = formNRows;
+ m_ncols = FormLayoutColumns;
+}
+
+bool Grid::locateWidget(QWidget *w, int &row, int &col, int &rowspan, int &colspan) const
+{
+ const int end = m_nrows * m_ncols;
+ const int startIndex = qFind(m_cells, m_cells + end, w) - m_cells;
+ if (startIndex == end)
+ return false;
+
+ row = startIndex / m_ncols;
+ col = startIndex % m_ncols;
+ for (rowspan = 1; row + rowspan < m_nrows && cell(row + rowspan, col) == w; rowspan++) {}
+ for (colspan = 1; col + colspan < m_ncols && cell(row, col + colspan) == w; colspan++) {}
+ return true;
+}
+
+// QGridLayout/QFormLayout Helpers: get item position/add item (overloads to make templates work)
+
+void getGridItemPosition(QGridLayout *gridLayout, int index, int *row, int *column, int *rowspan, int *colspan)
+{
+ gridLayout->getItemPosition(index, row, column, rowspan, colspan);
+}
+
+void addWidgetToGrid(QGridLayout *lt, QWidget * widget, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
+{
+ lt->addWidget(widget, row, column, rowSpan, columnSpan, alignment);
+}
+
+inline void getGridItemPosition(QFormLayout *formLayout, int index, int *row, int *column, int *rowspan, int *colspan)
+{
+ getFormLayoutItemPosition(formLayout, index, row, column, rowspan, colspan);
+}
+
+inline void addWidgetToGrid(QFormLayout *lt, QWidget * widget, int row, int column, int, int columnSpan, Qt::Alignment)
+{
+ formLayoutAddWidget(lt, widget, QRect(column, row, columnSpan, 1), false);
+}
+
+// ----------- Base template for grid like layouts
+template <class GridLikeLayout, int LayoutType, int GridMode>
+class GridLayout : public Layout
+{
+public:
+ GridLayout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb);
+
+ virtual void doLayout();
+ virtual void sort() { setWidgets(buildGrid(widgets())); }
+
+protected:
+ QWidget *widgetAt(GridLikeLayout *layout, int row, int column) const;
+
+protected:
+ QWidgetList buildGrid(const QWidgetList &);
+ Grid m_grid;
+};
+
+template <class GridLikeLayout, int LayoutType, int GridMode>
+GridLayout<GridLikeLayout, LayoutType, GridMode>::GridLayout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb) :
+ Layout(wl, p, fw, lb, LayoutInfo::Grid),
+ m_grid(static_cast<Grid::Mode>(GridMode))
+{
+}
+
+template <class GridLikeLayout, int LayoutType, int GridMode>
+QWidget *GridLayout<GridLikeLayout, LayoutType, GridMode>::widgetAt(GridLikeLayout *layout, int row, int column) const
+{
+ int index = 0;
+ while (QLayoutItem *item = layout->itemAt(index)) {
+ if (item->widget()) {
+ int r, c, rowspan, colspan;
+ getGridItemPosition(layout, index, &r, &c, &rowspan, &colspan);
+ if (row == r && column == c)
+ return item->widget();
+ }
+ ++index;
+ }
+ return 0;
+}
+
+template <class GridLikeLayout, int LayoutType, int GridMode>
+void GridLayout<GridLikeLayout, LayoutType, GridMode>::doLayout()
+{
+ bool needMove, needReparent;
+ if (!prepareLayout(needMove, needReparent))
+ return;
+
+ GridLikeLayout *layout = static_cast<GridLikeLayout *>(createLayout(LayoutType));
+
+ if (m_grid.empty())
+ sort();
+
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+
+ const QWidgetList::const_iterator cend = widgets().constEnd();
+ for (QWidgetList::const_iterator it = widgets().constBegin(); it != cend; ++it) {
+ QWidget *w = *it;
+ int r = 0, c = 0, rs = 0, cs = 0;
+
+ if (m_grid.locateWidget(w, r, c, rs, cs)) {
+ if (needReparent)
+ reparentToLayoutBase(w);
+
+ Qt::Alignment alignment = Qt::Alignment(0);
+ if (const Spacer *spacer = qobject_cast<const Spacer*>(w))
+ alignment = spacer->alignment();
+
+ if (rs * cs == 1) {
+ addWidgetToGrid(layout, w, r, c, 1, 1, alignment);
+ } else {
+ addWidgetToGrid(layout, w, r, c, rs, cs, alignment);
+ }
+
+ w->show();
+ } else {
+ qDebug("ooops, widget '%s' does not fit in layout", w->objectName().toUtf8().constData());
+ }
+ }
+
+ QLayoutSupport::createEmptyCells(layout);
+
+ finishLayout(needMove, layout);
+}
+
+// Remove duplicate entries (Remove next, if equal to current)
+void removeIntVecDuplicates(QVector<int> &v)
+{
+ if (v.size() < 2)
+ return;
+
+ for (QVector<int>::iterator current = v.begin() ; (current != v.end()) && ((current+1) != v.end()) ; )
+ if ( (*current == *(current+1)) )
+ v.erase(current+1);
+ else
+ ++current;
+}
+
+// Ensure a non-zero size for a widget geometry (squeezed spacers)
+inline QRect expandGeometry(const QRect &rect)
+{
+ return rect.isEmpty() ? QRect(rect.topLeft(), rect.size().expandedTo(QSize(1, 1))) : rect;
+}
+
+template <class GridLikeLayout, int LayoutType, int GridMode>
+QWidgetList GridLayout<GridLikeLayout, LayoutType, GridMode>::buildGrid(const QWidgetList &widgetList)
+{
+ if (widgetList.empty())
+ return QWidgetList();
+
+ // Pixel to cell conversion:
+ // By keeping a list of start'n'stop values (x & y) for each widget,
+ // it is possible to create a very small grid of cells to represent
+ // the widget layout.
+ // -----------------------------------------------------------------
+
+ // We need a list of both start and stop values for x- & y-axis
+ const int widgetCount = widgetList.size();
+ QVector<int> x( widgetCount * 2 );
+ QVector<int> y( widgetCount * 2 );
+
+ // Using push_back would look nicer, but operator[] is much faster
+ int index = 0;
+ for (int i = 0; i < widgetCount; ++i) {
+ const QRect widgetPos = expandGeometry(widgetList.at(i)->geometry());
+ x[index] = widgetPos.left();
+ x[index+1] = widgetPos.right();
+ y[index] = widgetPos.top();
+ y[index+1] = widgetPos.bottom();
+ index += 2;
+ }
+
+ qSort(x);
+ qSort(y);
+
+ // Remove duplicate x entries (Remove next, if equal to current)
+ removeIntVecDuplicates(x);
+ removeIntVecDuplicates(y);
+
+ // Note that left == right and top == bottom for size 1 items; reserve
+ // enough space
+ m_grid.resize(y.size(), x.size());
+
+ const QWidgetList::const_iterator cend = widgetList.constEnd();
+ for (QWidgetList::const_iterator it = widgetList.constBegin(); it != cend; ++it) {
+ QWidget *w = *it;
+ // Mark the cells in the grid that contains a widget
+ const QRect widgetPos = expandGeometry(w->geometry());
+ QRect c(0, 0, 0, 0); // rect of columns/rows
+
+ // From left til right (not including)
+ const int leftIdx = x.indexOf(widgetPos.left());
+ Q_ASSERT(leftIdx != -1);
+ c.setLeft(leftIdx);
+ c.setRight(leftIdx);
+ for (int cw=leftIdx; cw<x.size(); cw++)
+ if (x[cw] < widgetPos.right())
+ c.setRight(cw);
+ else
+ break;
+ // From top til bottom (not including)
+ const int topIdx = y.indexOf(widgetPos.top());
+ Q_ASSERT(topIdx != -1);
+ c.setTop(topIdx);
+ c.setBottom(topIdx);
+ for (int ch=topIdx; ch<y.size(); ch++)
+ if (y[ch] < widgetPos.bottom())
+ c.setBottom(ch);
+ else
+ break;
+ m_grid.setCells(c, w); // Mark cellblock
+ }
+
+ m_grid.simplify();
+
+ QWidgetList ordered;
+ for (int i = 0; i < m_grid.numRows(); i++)
+ for (int j = 0; j < m_grid.numCols(); j++) {
+ QWidget *w = m_grid.cell(i, j);
+ if (w && !ordered.contains(w))
+ ordered.append(w);
+ }
+ return ordered;
+}
+} // anonymous
+
+Layout* Layout::createLayout(const QWidgetList &widgets, QWidget *parentWidget,
+ QDesignerFormWindowInterface *fw,
+ QWidget *layoutBase, LayoutInfo::Type layoutType)
+{
+ switch (layoutType) {
+ case LayoutInfo::Grid:
+ return new GridLayout<QGridLayout, LayoutInfo::Grid, Grid::GridLayout>(widgets, parentWidget, fw, layoutBase);
+ case LayoutInfo::HBox:
+ case LayoutInfo::VBox: {
+ const Qt::Orientation orientation = layoutType == LayoutInfo::HBox ? Qt::Horizontal : Qt::Vertical;
+ return new BoxLayout(widgets, parentWidget, fw, layoutBase, orientation);
+ }
+ case LayoutInfo::HSplitter:
+ case LayoutInfo::VSplitter: {
+ const Qt::Orientation orientation = layoutType == LayoutInfo::HSplitter ? Qt::Horizontal : Qt::Vertical;
+ return new SplitterLayout(widgets, parentWidget, fw, layoutBase, orientation);
+ }
+ case LayoutInfo::Form:
+ return new GridLayout<QFormLayout, LayoutInfo::Form, Grid::FormLayout>(widgets, parentWidget, fw, layoutBase);
+ default:
+ break;
+ }
+ Q_ASSERT(0);
+ return 0;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/layout_p.h b/tools/designer/src/lib/shared/layout_p.h
new file mode 100644
index 0000000000..8396876739
--- /dev/null
+++ b/tools/designer/src/lib/shared/layout_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef LAYOUT_H
+#define LAYOUT_H
+
+#include "shared_global_p.h"
+#include "layoutinfo_p.h"
+
+#include <QtCore/QPointer>
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+#include <QtCore/QHash>
+
+#include <QtGui/QLayout>
+#include <QtGui/QGridLayout>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+class QDESIGNER_SHARED_EXPORT Layout : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(Layout)
+protected:
+ Layout(const QWidgetList &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb, LayoutInfo::Type layoutType);
+
+public:
+ static Layout* createLayout(const QWidgetList &widgets, QWidget *parentWidget,
+ QDesignerFormWindowInterface *fw,
+ QWidget *layoutBase, LayoutInfo::Type layoutType);
+
+ virtual ~Layout();
+
+ virtual void sort() = 0;
+ virtual void doLayout() = 0;
+
+ virtual void setup();
+ virtual void undoLayout();
+ virtual void breakLayout();
+
+ const QWidgetList &widgets() const { return m_widgets; }
+ QWidget *parentWidget() const { return m_parentWidget; }
+ QWidget *layoutBaseWidget() const { return m_layoutBase; }
+
+ /* Determines whether instances of QLayoutWidget are unmanaged/hidden
+ * after breaking a layout. Default is true. Can be turned off when
+ * morphing */
+ bool reparentLayoutWidget() const { return m_reparentLayoutWidget; }
+ void setReparentLayoutWidget(bool v) { m_reparentLayoutWidget = v; }
+
+protected:
+ virtual void finishLayout(bool needMove, QLayout *layout = 0);
+ virtual bool prepareLayout(bool &needMove, bool &needReparent);
+
+ void setWidgets(const QWidgetList &widgets) { m_widgets = widgets; }
+ QLayout *createLayout(int type);
+ void reparentToLayoutBase(QWidget *w);
+
+private slots:
+ void widgetDestroyed();
+
+private:
+ QWidgetList m_widgets;
+ QWidget *m_parentWidget;
+ typedef QHash<QWidget *, QRect> WidgetGeometryHash;
+ WidgetGeometryHash m_geometries;
+ QWidget *m_layoutBase;
+ QDesignerFormWindowInterface *m_formWindow;
+ const LayoutInfo::Type m_layoutType;
+ QPoint m_startPoint;
+ QRect m_oldGeometry;
+
+ bool m_reparentLayoutWidget;
+ const bool m_isBreak;
+};
+
+namespace Utils
+{
+
+inline int indexOfWidget(QLayout *layout, QWidget *widget)
+{
+ int index = 0;
+ while (QLayoutItem *item = layout->itemAt(index)) {
+ if (item->widget() == widget)
+ return index;
+
+ ++index;
+ }
+
+ return -1;
+}
+
+} // namespace Utils
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LAYOUT_H
diff --git a/tools/designer/src/lib/shared/layoutinfo.cpp b/tools/designer/src/lib/shared/layoutinfo.cpp
new file mode 100644
index 0000000000..01eb43a831
--- /dev/null
+++ b/tools/designer/src/lib/shared/layoutinfo.cpp
@@ -0,0 +1,312 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "layoutinfo_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/QSplitter>
+#include <QtCore/QDebug>
+#include <QtCore/QHash>
+#include <QtCore/QRect>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+/*!
+ \overload
+*/
+LayoutInfo::Type LayoutInfo::layoutType(const QDesignerFormEditorInterface *core, const QLayout *layout)
+{
+ Q_UNUSED(core)
+ if (!layout)
+ return NoLayout;
+ else if (qobject_cast<const QHBoxLayout*>(layout))
+ return HBox;
+ else if (qobject_cast<const QVBoxLayout*>(layout))
+ return VBox;
+ else if (qobject_cast<const QGridLayout*>(layout))
+ return Grid;
+ else if (qobject_cast<const QFormLayout*>(layout))
+ return Form;
+ return UnknownLayout;
+}
+
+static const QHash<QString, LayoutInfo::Type> &layoutNameTypeMap()
+{
+ static QHash<QString, LayoutInfo::Type> nameTypeMap;
+ if (nameTypeMap.empty()) {
+ nameTypeMap.insert(QLatin1String("QVBoxLayout"), LayoutInfo::VBox);
+ nameTypeMap.insert(QLatin1String("QHBoxLayout"), LayoutInfo::HBox);
+ nameTypeMap.insert(QLatin1String("QGridLayout"), LayoutInfo::Grid);
+ nameTypeMap.insert(QLatin1String("QFormLayout"), LayoutInfo::Form);
+ }
+ return nameTypeMap;
+}
+
+LayoutInfo::Type LayoutInfo::layoutType(const QString &typeName)
+{
+ return layoutNameTypeMap().value(typeName, NoLayout);
+}
+
+QString LayoutInfo::layoutName(Type t)
+{
+ return layoutNameTypeMap().key(t);
+}
+
+/*!
+ \overload
+*/
+LayoutInfo::Type LayoutInfo::layoutType(const QDesignerFormEditorInterface *core, const QWidget *w)
+{
+ if (const QSplitter *splitter = qobject_cast<const QSplitter *>(w))
+ return splitter->orientation() == Qt::Horizontal ? HSplitter : VSplitter;
+ return layoutType(core, w->layout());
+}
+
+LayoutInfo::Type LayoutInfo::managedLayoutType(const QDesignerFormEditorInterface *core,
+ const QWidget *w,
+ QLayout **ptrToLayout)
+{
+ if (ptrToLayout)
+ *ptrToLayout = 0;
+ if (const QSplitter *splitter = qobject_cast<const QSplitter *>(w))
+ return splitter->orientation() == Qt::Horizontal ? HSplitter : VSplitter;
+ QLayout *layout = managedLayout(core, w);
+ if (!layout)
+ return NoLayout;
+ if (ptrToLayout)
+ *ptrToLayout = layout;
+ return layoutType(core, layout);
+}
+
+QWidget *LayoutInfo::layoutParent(const QDesignerFormEditorInterface *core, QLayout *layout)
+{
+ Q_UNUSED(core)
+
+ QObject *o = layout;
+ while (o) {
+ if (QWidget *widget = qobject_cast<QWidget*>(o))
+ return widget;
+
+ o = o->parent();
+ }
+ return 0;
+}
+
+void LayoutInfo::deleteLayout(const QDesignerFormEditorInterface *core, QWidget *widget)
+{
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), widget))
+ widget = container->widget(container->currentIndex());
+
+ Q_ASSERT(widget != 0);
+
+ QLayout *layout = managedLayout(core, widget);
+
+ if (layout == 0 || core->metaDataBase()->item(layout) != 0) {
+ delete layout;
+ widget->updateGeometry();
+ return;
+ }
+
+ qDebug() << "trying to delete an unmanaged layout:" << "widget:" << widget << "layout:" << layout;
+}
+
+LayoutInfo::Type LayoutInfo::laidoutWidgetType(const QDesignerFormEditorInterface *core,
+ QWidget *widget,
+ bool *isManaged,
+ QLayout **ptrToLayout)
+{
+ if (isManaged)
+ *isManaged = false;
+ if (ptrToLayout)
+ *ptrToLayout = 0;
+
+ QWidget *parent = widget->parentWidget();
+ if (!parent)
+ return NoLayout;
+
+ // 1) Splitter
+ if (QSplitter *splitter = qobject_cast<QSplitter*>(parent)) {
+ if (isManaged)
+ *isManaged = core->metaDataBase()->item(splitter);
+ return splitter->orientation() == Qt::Horizontal ? HSplitter : VSplitter;
+ }
+
+ // 2) Layout of parent
+ QLayout *parentLayout = parent->layout();
+ if (!parentLayout)
+ return NoLayout;
+
+ if (parentLayout->indexOf(widget) != -1) {
+ if (isManaged)
+ *isManaged = core->metaDataBase()->item(parentLayout);
+ if (ptrToLayout)
+ *ptrToLayout = parentLayout;
+ return layoutType(core, parentLayout);
+ }
+
+ // 3) Some child layout (see below comment about Q3GroupBox)
+ const QList<QLayout*> childLayouts = qFindChildren<QLayout*>(parentLayout);
+ if (childLayouts.empty())
+ return NoLayout;
+ const QList<QLayout*>::const_iterator lcend = childLayouts.constEnd();
+ for (QList<QLayout*>::const_iterator it = childLayouts.constBegin(); it != lcend; ++it) {
+ QLayout *layout = *it;
+ if (layout->indexOf(widget) != -1) {
+ if (isManaged)
+ *isManaged = core->metaDataBase()->item(layout);
+ if (ptrToLayout)
+ *ptrToLayout = layout;
+ return layoutType(core, layout);
+ }
+ }
+
+ return NoLayout;
+}
+
+QLayout *LayoutInfo::internalLayout(const QWidget *widget)
+{
+ QLayout *widgetLayout = widget->layout();
+ if (widgetLayout && widget->inherits("Q3GroupBox")) {
+ if (widgetLayout->count()) {
+ widgetLayout = widgetLayout->itemAt(0)->layout();
+ } else {
+ widgetLayout = 0;
+ }
+ }
+ return widgetLayout;
+}
+
+
+QLayout *LayoutInfo::managedLayout(const QDesignerFormEditorInterface *core, const QWidget *widget)
+{
+ if (widget == 0)
+ return 0;
+
+ QLayout *layout = widget->layout();
+ if (!layout)
+ return 0;
+
+ return managedLayout(core, layout);
+}
+
+QLayout *LayoutInfo::managedLayout(const QDesignerFormEditorInterface *core, QLayout *layout)
+{
+ QDesignerMetaDataBaseInterface *metaDataBase = core->metaDataBase();
+
+ if (!metaDataBase)
+ return layout;
+ /* This code exists mainly for the Q3GroupBox class, for which
+ * widget->layout() returns an internal VBoxLayout. */
+ const QDesignerMetaDataBaseItemInterface *item = metaDataBase->item(layout);
+ if (item == 0) {
+ layout = qFindChild<QLayout*>(layout);
+ item = metaDataBase->item(layout);
+ }
+ if (!item)
+ return 0;
+ return layout;
+}
+
+// Is it a a dummy grid placeholder created by Designer?
+bool LayoutInfo::isEmptyItem(QLayoutItem *item)
+{
+ if (item == 0) {
+ qDebug() << "** WARNING Zero-item passed on to isEmptyItem(). This indicates a layout inconsistency.";
+ return true;
+ }
+ return item->spacerItem() != 0;
+}
+
+QDESIGNER_SHARED_EXPORT void getFormLayoutItemPosition(const QFormLayout *formLayout, int index, int *rowPtr, int *columnPtr, int *rowspanPtr, int *colspanPtr)
+{
+ int row;
+ QFormLayout::ItemRole role;
+ formLayout->getItemPosition(index, &row, &role);
+ const int columnspan = role == QFormLayout::SpanningRole ? 2 : 1;
+ const int column = (columnspan > 1 || role == QFormLayout::LabelRole) ? 0 : 1;
+ if (rowPtr)
+ *rowPtr = row;
+ if (columnPtr)
+ *columnPtr = column;
+ if (rowspanPtr)
+ *rowspanPtr = 1;
+ if (colspanPtr)
+ *colspanPtr = columnspan;
+}
+
+static inline QFormLayout::ItemRole formLayoutRole(int column, int colspan)
+{
+ if (colspan > 1)
+ return QFormLayout::SpanningRole;
+ return column == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole;
+}
+
+QDESIGNER_SHARED_EXPORT void formLayoutAddWidget(QFormLayout *formLayout, QWidget *w, const QRect &r, bool insert)
+{
+ // Consistent API galore...
+ if (insert) {
+ const bool spanning = r.width() > 1;
+ if (spanning) {
+ formLayout->insertRow(r.y(), w);
+ } else {
+ QWidget *label = 0, *field = 0;
+ if (r.x() == 0) {
+ label = w;
+ } else {
+ field = w;
+ }
+ formLayout->insertRow(r.y(), label, field);
+ }
+ } else {
+ formLayout->setWidget(r.y(), formLayoutRole(r.x(), r.width()), w);
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/layoutinfo_p.h b/tools/designer/src/lib/shared/layoutinfo_p.h
new file mode 100644
index 0000000000..64f3f049ba
--- /dev/null
+++ b/tools/designer/src/lib/shared/layoutinfo_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef LAYOUTINFO_H
+#define LAYOUTINFO_H
+
+#include "shared_global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+class QLayout;
+class QLayoutItem;
+class QDesignerFormEditorInterface;
+class QFormLayout;
+class QRect;
+class QString;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT LayoutInfo
+{
+public:
+ enum Type
+ {
+ NoLayout,
+ HSplitter,
+ VSplitter,
+ HBox,
+ VBox,
+ Grid,
+ Form,
+ UnknownLayout // QDockWindow inside QMainWindow is inside QMainWindowLayout - it doesn't mean there is no layout
+ };
+
+ static void deleteLayout(const QDesignerFormEditorInterface *core, QWidget *widget);
+
+ // Examines the immediate layout of the widget (will fail for Q3Group Box).
+ static Type layoutType(const QDesignerFormEditorInterface *core, const QWidget *w);
+ // Examines the managed layout of the widget
+ static Type managedLayoutType(const QDesignerFormEditorInterface *core, const QWidget *w, QLayout **layout = 0);
+ static Type layoutType(const QDesignerFormEditorInterface *core, const QLayout *layout);
+ static Type layoutType(const QString &typeName);
+ static QString layoutName(Type t);
+
+ static QWidget *layoutParent(const QDesignerFormEditorInterface *core, QLayout *layout);
+
+ static Type laidoutWidgetType(const QDesignerFormEditorInterface *core, QWidget *widget, bool *isManaged = 0, QLayout **layout = 0);
+ static bool inline isWidgetLaidout(const QDesignerFormEditorInterface *core, QWidget *widget) { return laidoutWidgetType(core, widget) != NoLayout; }
+
+ static QLayout *managedLayout(const QDesignerFormEditorInterface *core, const QWidget *widget);
+ static QLayout *managedLayout(const QDesignerFormEditorInterface *core, QLayout *layout);
+ static QLayout *internalLayout(const QWidget *widget);
+
+ // Is it a a dummy grid placeholder created by Designer?
+ static bool isEmptyItem(QLayoutItem *item);
+};
+
+QDESIGNER_SHARED_EXPORT void getFormLayoutItemPosition(const QFormLayout *formLayout, int index, int *rowPtr, int *columnPtr = 0, int *rowspanPtr = 0, int *colspanPtr = 0);
+QDESIGNER_SHARED_EXPORT void formLayoutAddWidget(QFormLayout *formLayout, QWidget *w, const QRect &r, bool insert);
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // LAYOUTINFO_H
diff --git a/tools/designer/src/lib/shared/metadatabase.cpp b/tools/designer/src/lib/shared/metadatabase.cpp
new file mode 100644
index 0000000000..1403440636
--- /dev/null
+++ b/tools/designer/src/lib/shared/metadatabase.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "metadatabase_p.h"
+#include "widgetdatabase_p.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+// Qt
+#include <QtGui/QWidget>
+#include <QtCore/qalgorithms.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ const bool debugMetaDatabase = false;
+}
+
+namespace qdesigner_internal {
+
+MetaDataBaseItem::MetaDataBaseItem(QObject *object)
+ : m_object(object),
+ m_enabled(true)
+{
+}
+
+MetaDataBaseItem::~MetaDataBaseItem()
+{
+}
+
+QString MetaDataBaseItem::name() const
+{
+ Q_ASSERT(m_object);
+ return m_object->objectName();
+}
+
+void MetaDataBaseItem::setName(const QString &name)
+{
+ Q_ASSERT(m_object);
+ m_object->setObjectName(name);
+}
+
+QString MetaDataBaseItem::customClassName() const
+{
+ return m_customClassName;
+}
+void MetaDataBaseItem::setCustomClassName(const QString &customClassName)
+{
+ m_customClassName = customClassName;
+}
+
+
+MetaDataBaseItem::TabOrder MetaDataBaseItem::tabOrder() const
+{
+ return m_tabOrder;
+}
+
+void MetaDataBaseItem::setTabOrder(const TabOrder &tabOrder)
+{
+ m_tabOrder = tabOrder;
+}
+
+bool MetaDataBaseItem::enabled() const
+{
+ return m_enabled;
+}
+
+void MetaDataBaseItem::setEnabled(bool b)
+{
+ m_enabled = b;
+}
+
+QString MetaDataBaseItem::script() const
+{
+ return m_script;
+}
+
+void MetaDataBaseItem::setScript(const QString &script)
+{
+ m_script = script;
+}
+
+QStringList MetaDataBaseItem::fakeSlots() const
+{
+ return m_fakeSlots;
+}
+
+void MetaDataBaseItem::setFakeSlots(const QStringList &fs)
+{
+ m_fakeSlots = fs;
+}
+
+QStringList MetaDataBaseItem::fakeSignals() const
+{
+ return m_fakeSignals;
+}
+
+void MetaDataBaseItem::setFakeSignals(const QStringList &fs)
+{
+ m_fakeSignals = fs;
+}
+
+// -----------------------------------------------------
+MetaDataBase::MetaDataBase(QDesignerFormEditorInterface *core, QObject *parent)
+ : QDesignerMetaDataBaseInterface(parent),
+ m_core(core)
+{
+}
+
+MetaDataBase::~MetaDataBase()
+{
+ qDeleteAll(m_items);
+}
+
+MetaDataBaseItem *MetaDataBase::metaDataBaseItem(QObject *object) const
+{
+ MetaDataBaseItem *i = m_items.value(object);
+ if (i == 0 || !i->enabled())
+ return 0;
+ return i;
+}
+
+void MetaDataBase::add(QObject *object)
+{
+ MetaDataBaseItem *item = m_items.value(object);
+ if (item != 0) {
+ item->setEnabled(true);
+ if (debugMetaDatabase) {
+ qDebug() << "MetaDataBase::add: Existing item for " << object->metaObject()->className() << item->name();
+ }
+ return;
+ }
+
+ item = new MetaDataBaseItem(object);
+ m_items.insert(object, item);
+ if (debugMetaDatabase) {
+ qDebug() << "MetaDataBase::add: New item " << object->metaObject()->className() << item->name();
+ }
+ connect(object, SIGNAL(destroyed(QObject*)),
+ this, SLOT(slotDestroyed(QObject*)));
+
+ emit changed();
+}
+
+void MetaDataBase::remove(QObject *object)
+{
+ Q_ASSERT(object);
+
+ if (MetaDataBaseItem *item = m_items.value(object)) {
+ item->setEnabled(false);
+ emit changed();
+ }
+}
+
+QList<QObject*> MetaDataBase::objects() const
+{
+ QList<QObject*> result;
+
+ ItemMap::const_iterator it = m_items.begin();
+ for (; it != m_items.end(); ++it) {
+ if (it.value()->enabled())
+ result.append(it.key());
+ }
+
+ return result;
+}
+
+QDesignerFormEditorInterface *MetaDataBase::core() const
+{
+ return m_core;
+}
+
+void MetaDataBase::slotDestroyed(QObject *object)
+{
+ if (m_items.contains(object)) {
+ MetaDataBaseItem *item = m_items.value(object);
+ delete item;
+ m_items.remove(object);
+ }
+}
+
+// promotion convenience
+QDESIGNER_SHARED_EXPORT bool promoteWidget(QDesignerFormEditorInterface *core,QWidget *widget,const QString &customClassName)
+{
+
+ MetaDataBase *db = qobject_cast<MetaDataBase *>(core->metaDataBase());
+ if (!db)
+ return false;
+ MetaDataBaseItem *item = db->metaDataBaseItem(widget);
+ if (!item) {
+ db ->add(widget);
+ item = db->metaDataBaseItem(widget);
+ }
+ // Recursive promotion occurs if there is a plugin missing.
+ const QString oldCustomClassName = item->customClassName();
+ if (!oldCustomClassName.isEmpty()) {
+ qDebug() << "WARNING: Recursive promotion of " << oldCustomClassName << " to " << customClassName
+ << ". A plugin is missing.";
+ }
+ item->setCustomClassName(customClassName);
+ if (debugMetaDatabase) {
+ qDebug() << "Promoting " << widget->metaObject()->className() << " to " << customClassName;
+ }
+ return true;
+}
+
+QDESIGNER_SHARED_EXPORT void demoteWidget(QDesignerFormEditorInterface *core,QWidget *widget)
+{
+ MetaDataBase *db = qobject_cast<MetaDataBase *>(core->metaDataBase());
+ if (!db)
+ return;
+ MetaDataBaseItem *item = db->metaDataBaseItem(widget);
+ item->setCustomClassName(QString());
+ if (debugMetaDatabase) {
+ qDebug() << "Demoting " << widget;
+ }
+}
+
+QDESIGNER_SHARED_EXPORT bool isPromoted(QDesignerFormEditorInterface *core, QWidget* widget)
+{
+ const MetaDataBase *db = qobject_cast<const MetaDataBase *>(core->metaDataBase());
+ if (!db)
+ return false;
+ const MetaDataBaseItem *item = db->metaDataBaseItem(widget);
+ if (!item)
+ return false;
+ return !item->customClassName().isEmpty();
+}
+
+QDESIGNER_SHARED_EXPORT QString promotedCustomClassName(QDesignerFormEditorInterface *core, QWidget* widget)
+{
+ const MetaDataBase *db = qobject_cast<const MetaDataBase *>(core->metaDataBase());
+ if (!db)
+ return QString();
+ const MetaDataBaseItem *item = db->metaDataBaseItem(widget);
+ if (!item)
+ return QString();
+ return item->customClassName();
+}
+
+QDESIGNER_SHARED_EXPORT QString promotedExtends(QDesignerFormEditorInterface *core, QWidget* widget)
+{
+ const QString customClassName = promotedCustomClassName(core,widget);
+ if (customClassName.isEmpty())
+ return QString();
+ const int i = core->widgetDataBase()->indexOfClassName(customClassName);
+ if (i == -1)
+ return QString();
+ return core->widgetDataBase()->item(i)->extends();
+}
+
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/metadatabase_p.h b/tools/designer/src/lib/shared/metadatabase_p.h
new file mode 100644
index 0000000000..874b5404ac
--- /dev/null
+++ b/tools/designer/src/lib/shared/metadatabase_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef METADATABASE_H
+#define METADATABASE_H
+
+#include "shared_global_p.h"
+
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
+#include <QtGui/QCursor>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT MetaDataBaseItem: public QDesignerMetaDataBaseItemInterface
+{
+public:
+ explicit MetaDataBaseItem(QObject *object);
+ virtual ~MetaDataBaseItem();
+
+ virtual QString name() const;
+ virtual void setName(const QString &name);
+
+ typedef QList<QWidget*> TabOrder;
+ virtual TabOrder tabOrder() const;
+ virtual void setTabOrder(const TabOrder &tabOrder);
+
+ virtual bool enabled() const;
+ virtual void setEnabled(bool b);
+
+ QString customClassName() const;
+ void setCustomClassName(const QString &customClassName);
+
+ QString script() const;
+ void setScript(const QString &script);
+
+ QStringList fakeSlots() const;
+ void setFakeSlots(const QStringList &);
+
+ QStringList fakeSignals() const;
+ void setFakeSignals(const QStringList &);
+
+private:
+ QObject *m_object;
+ TabOrder m_tabOrder;
+ bool m_enabled;
+ QString m_customClassName;
+ QString m_script;
+ QStringList m_fakeSlots;
+ QStringList m_fakeSignals;
+};
+
+class QDESIGNER_SHARED_EXPORT MetaDataBase: public QDesignerMetaDataBaseInterface
+{
+ Q_OBJECT
+public:
+ explicit MetaDataBase(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ virtual ~MetaDataBase();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual QDesignerMetaDataBaseItemInterface *item(QObject *object) const { return metaDataBaseItem(object); }
+ virtual MetaDataBaseItem *metaDataBaseItem(QObject *object) const;
+ virtual void add(QObject *object);
+ virtual void remove(QObject *object);
+
+ virtual QList<QObject*> objects() const;
+
+private slots:
+ void slotDestroyed(QObject *object);
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ typedef QHash<QObject *, MetaDataBaseItem*> ItemMap;
+ ItemMap m_items;
+};
+
+ // promotion convenience
+ QDESIGNER_SHARED_EXPORT bool promoteWidget(QDesignerFormEditorInterface *core,QWidget *widget,const QString &customClassName);
+ QDESIGNER_SHARED_EXPORT void demoteWidget(QDesignerFormEditorInterface *core,QWidget *widget);
+ QDESIGNER_SHARED_EXPORT bool isPromoted(QDesignerFormEditorInterface *core, QWidget* w);
+ QDESIGNER_SHARED_EXPORT QString promotedCustomClassName(QDesignerFormEditorInterface *core, QWidget* w);
+ QDESIGNER_SHARED_EXPORT QString promotedExtends(QDesignerFormEditorInterface *core, QWidget* w);
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // METADATABASE_H
diff --git a/tools/designer/src/lib/shared/morphmenu.cpp b/tools/designer/src/lib/shared/morphmenu.cpp
new file mode 100644
index 0000000000..0d41af0de0
--- /dev/null
+++ b/tools/designer/src/lib/shared/morphmenu.cpp
@@ -0,0 +1,635 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "morphmenu_p.h"
+#include "formwindowbase_p.h"
+#include "widgetfactory_p.h"
+#include "qdesigner_formwindowcommand_p.h"
+#include "qlayout_widget_p.h"
+#include "layoutinfo_p.h"
+#include "qdesigner_propertycommand_p.h"
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+
+#include <QtGui/QWidget>
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+#include <QtGui/QApplication>
+#include <QtGui/QLayout>
+#include <QtGui/QUndoStack>
+
+#include <QtGui/QFrame>
+#include <QtGui/QGroupBox>
+#include <QtGui/QTabWidget>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QAbstractButton>
+#include <QtGui/QAbstractSpinBox>
+#include <QtGui/QTextEdit>
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QLabel>
+
+#include <QtCore/QStringList>
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+#include <QtCore/QSignalMapper>
+#include <QtCore/QDebug>
+
+Q_DECLARE_METATYPE(QWidgetList)
+
+QT_BEGIN_NAMESPACE
+
+// Helpers for the dynamic properties that store Z/Widget order
+static const char *widgetOrderPropertyC = "_q_widgetOrder";
+static const char *zOrderPropertyC = "_q_zOrder";
+
+/* Morphing in Designer:
+ * It is possible to morph:
+ * - Non-Containers into similar widgets by category
+ * - Simple page containers into similar widgets or page-based containers with
+ * a single page (in theory also into a QLayoutWidget, but this might
+ * not always be appropriate).
+ * - Page-based containers into page-based containers or simple containers if
+ * they have just one page
+ * [Page based containers meaning here having a container extension]
+ * Morphing types are restricted to the basic Qt types. Morphing custom
+ * widgets is considered risky since they might have unmanaged layouts
+ * or the like.
+ *
+ * Requirements:
+ * - The widget must be on a non-laid out parent or in a layout managed
+ * by Designer
+ * - Its child widgets must be non-laid out or in a layout managed
+ * by Designer
+ * Note that child widgets can be
+ * - On the widget itself in the case of simple containers
+ * - On several pages in the case of page-based containers
+ * This is what is called 'childContainers' in the code (the widget itself
+ * or the list of container extension pages).
+ *
+ * The Morphing process encompasses:
+ * - Create a target widget and apply properties as far as applicable
+ * If the target widget has a container extension, add a sufficient
+ * number of pages.
+ * - Transferring the child widgets over to the new childContainers.
+ * In the case of a managed layout on a childContainer, this is simply
+ * set on the target childContainer, which is a new Qt 4.5
+ * functionality.
+ * - Replace the widget itself in the parent layout
+ */
+
+namespace qdesigner_internal {
+
+enum MorphCategory {
+ MorphCategoryNone, MorphSimpleContainer, MorphPageContainer, MorphItemView,
+ MorphButton, MorphSpinBox, MorphTextEdit
+};
+
+// Determine category of a widget
+static MorphCategory category(const QWidget *w)
+{
+ // Simple containers: Exact match
+ const QMetaObject *mo = w->metaObject();
+ if (mo == &QWidget::staticMetaObject || mo == &QFrame::staticMetaObject || mo == &QGroupBox::staticMetaObject || mo == &QLayoutWidget::staticMetaObject)
+ return MorphSimpleContainer;
+ if (mo == &QTabWidget::staticMetaObject || mo == &QStackedWidget::staticMetaObject || mo == &QToolBox::staticMetaObject)
+ return MorphPageContainer;
+ if (qobject_cast<const QAbstractItemView*>(w))
+ return MorphItemView;
+ if (qobject_cast<const QAbstractButton *>(w))
+ return MorphButton;
+ if (qobject_cast<const QAbstractSpinBox *>(w))
+ return MorphSpinBox;
+ if (qobject_cast<const QPlainTextEdit *>(w) || qobject_cast<const QTextEdit*>(w))
+ return MorphTextEdit;
+
+ return MorphCategoryNone;
+}
+
+/* Return the similar classes of a category. This is currently restricted
+ * to the known Qt classes with no precautions to parse the Widget Database
+ * (which is too risky, custom classes might have container extensions
+ * or non-managed layouts, etc.). */
+
+static QStringList classesOfCategory(MorphCategory cat)
+{
+ typedef QMap<MorphCategory, QStringList> CandidateCache;
+ static CandidateCache candidateCache;
+ CandidateCache::iterator it = candidateCache.find(cat);
+ if (it == candidateCache.end()) {
+ it = candidateCache.insert(cat, QStringList());
+ QStringList &l = it.value();
+ switch (cat) {
+ case MorphCategoryNone:
+ break;
+ case MorphSimpleContainer:
+ // Do not generally allow to morph into a layout.
+ // This can be risky in case of container pages,etc.
+ l << QLatin1String("QWidget") << QLatin1String("QFrame") << QLatin1String("QGroupBox");
+ break;
+ case MorphPageContainer:
+ l << QLatin1String("QTabWidget") << QLatin1String("QStackedWidget") << QLatin1String("QToolBox");
+ break;
+ case MorphItemView:
+ l << QLatin1String("QListView") << QLatin1String("QListWidget")
+ << QLatin1String("QTreeView") << QLatin1String("QTreeWidget")
+ << QLatin1String("QTableView") << QLatin1String("QTableWidget")
+ << QLatin1String("QColumnView");
+ break;
+ case MorphButton:
+ l << QLatin1String("QCheckBox") << QLatin1String("QRadioButton")
+ << QLatin1String("QPushButton") << QLatin1String("QToolButton")
+ << QLatin1String("QCommandLinkButton");
+ break;
+ case MorphSpinBox:
+ l << QLatin1String("QDateTimeEdit") << QLatin1String("QDateEdit")
+ << QLatin1String("QTimeEdit")
+ << QLatin1String("QSpinBox") << QLatin1String("QDoubleSpinBox");
+ break;
+ case MorphTextEdit:
+ l << QLatin1String("QTextEdit") << QLatin1String("QPlainTextEdit");
+ break;
+ }
+ }
+ return it.value();
+}
+
+// Return the widgets containing the children to be transferred to. This is the
+// widget itself in most cases, except for QDesignerContainerExtension cases
+static QWidgetList childContainers(const QDesignerFormEditorInterface *core, QWidget *w)
+{
+ if (const QDesignerContainerExtension *ce = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), w)) {
+ QWidgetList children;
+ if (const int count = ce->count()) {
+ for (int i = 0; i < count; i++)
+ children.push_back(ce->widget(i));
+ }
+ return children;
+ }
+ QWidgetList self;
+ self.push_back(w);
+ return self;
+}
+
+// Suggest a suitable objectname for the widget to be morphed into
+// Replace the class name parts: 'xxFrame' -> 'xxGroupBox', 'frame' -> 'groupBox'
+static QString suggestObjectName(const QString &oldClassName, const QString &newClassName, const QString &oldName)
+{
+ QString oldClassPart = oldClassName;
+ QString newClassPart = newClassName;
+ if (oldClassPart.startsWith(QLatin1Char('Q')))
+ oldClassPart.remove(0, 1);
+ if (newClassPart.startsWith(QLatin1Char('Q')))
+ newClassPart.remove(0, 1);
+
+ QString newName = oldName;
+ newName.replace(oldClassPart, newClassPart);
+ oldClassPart[0] = oldClassPart.at(0).toLower();
+ newClassPart[0] = newClassPart.at(0).toLower();
+ newName.replace(oldClassPart, newClassPart);
+ return newName;
+}
+
+// Find the label whose buddy the widget is.
+QLabel *buddyLabelOf(QDesignerFormWindowInterface *fw, QWidget *w)
+{
+ typedef QList<QLabel*> LabelList;
+ const LabelList labelList = qFindChildren<QLabel*>(fw);
+ if (labelList.empty())
+ return 0;
+ const LabelList::const_iterator cend = labelList.constEnd();
+ for (LabelList::const_iterator it = labelList.constBegin(); it != cend; ++it )
+ if ( (*it)->buddy() == w)
+ return *it;
+ return 0;
+}
+
+// Replace widgets in a widget-list type dynamic property of the parent
+// used for Z-order, etc.
+static void replaceWidgetListDynamicProperty(QWidget *parentWidget,
+ QWidget *oldWidget, QWidget *newWidget,
+ const char *name)
+{
+ QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name));
+ const int index = list.indexOf(oldWidget);
+ if (index != -1) {
+ list.replace(index, newWidget);
+ parentWidget->setProperty(name, qVariantFromValue(list));
+ }
+}
+
+/* Morph a widget into another class. Use the static addMorphMacro() to
+ * add a respective command sequence to the undo stack as it emits signals
+ * which cause other commands to be added. */
+class MorphWidgetCommand : public QDesignerFormWindowCommand
+{
+ Q_DISABLE_COPY(MorphWidgetCommand)
+public:
+
+ explicit MorphWidgetCommand(QDesignerFormWindowInterface *formWindow);
+ ~MorphWidgetCommand();
+
+ // Convenience to add a morph command sequence macro
+ static bool addMorphMacro(QDesignerFormWindowInterface *formWindow, QWidget *w, const QString &newClass);
+
+ bool init(QWidget *widget, const QString &newClass);
+
+ QString newWidgetName() const { return m_afterWidget->objectName(); }
+
+ virtual void redo();
+ virtual void undo();
+
+ static QStringList candidateClasses(QDesignerFormWindowInterface *fw, QWidget *w);
+
+private:
+ static bool canMorph(QDesignerFormWindowInterface *fw, QWidget *w, int *childContainerCount = 0, MorphCategory *cat = 0);
+ void morph(QWidget *before, QWidget *after);
+
+ QWidget *m_beforeWidget;
+ QWidget *m_afterWidget;
+};
+
+bool MorphWidgetCommand::addMorphMacro(QDesignerFormWindowInterface *fw, QWidget *w, const QString &newClass)
+{
+ MorphWidgetCommand *morphCmd = new MorphWidgetCommand(fw);
+ if (!morphCmd->init(w, newClass)) {
+ qWarning("*** Unable to create a MorphWidgetCommand");
+ delete morphCmd;
+ return false;
+ }
+ QLabel *buddyLabel = buddyLabelOf(fw, w);
+ // Need a macro since it adds further commands
+ QUndoStack *us = fw->commandHistory();
+ us->beginMacro(morphCmd->text());
+ // Have the signal slot/buddy editors add their commands to delete widget
+ if (FormWindowBase *fwb = qobject_cast<FormWindowBase*>(fw))
+ fwb->emitWidgetRemoved(w);
+
+ const QString newWidgetName = morphCmd->newWidgetName();
+ us->push(morphCmd);
+
+ // restore buddy using the QByteArray name.
+ if (buddyLabel) {
+ SetPropertyCommand *buddyCmd = new SetPropertyCommand(fw);
+ buddyCmd->init(buddyLabel, QLatin1String("buddy"), QVariant(newWidgetName.toUtf8()));
+ us->push(buddyCmd);
+ }
+ us->endMacro();
+ return true;
+}
+
+MorphWidgetCommand::MorphWidgetCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_beforeWidget(0),
+ m_afterWidget(0)
+{
+}
+
+MorphWidgetCommand::~MorphWidgetCommand()
+{
+}
+
+bool MorphWidgetCommand::init(QWidget *widget, const QString &newClassName)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ QDesignerFormEditorInterface *core = fw->core();
+
+ if (!canMorph(fw, widget))
+ return false;
+
+ const QString oldClassName = WidgetFactory::classNameOf(core, widget);
+ const QString oldName = widget->objectName();
+ //: MorphWidgetCommand description
+ setText(QApplication::translate("Command", "Morph %1/'%2' into %3").arg(oldClassName, oldName, newClassName));
+
+ m_beforeWidget = widget;
+ m_afterWidget = core->widgetFactory()->createWidget(newClassName, fw);
+ if (!m_afterWidget)
+ return false;
+
+ // Set object name. Do not unique it (as to maintain it).
+ m_afterWidget->setObjectName(suggestObjectName(oldClassName, newClassName, oldName));
+
+ // If the target has a container extension, we add enough new pages to take
+ // up the children of the before widget
+ if (QDesignerContainerExtension* c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_afterWidget)) {
+ if (const int pageCount = childContainers(core, m_beforeWidget).size()) {
+ const QString qWidget = QLatin1String("QWidget");
+ const QString containerName = m_afterWidget->objectName();
+ for (int i = 0; i < pageCount; i++) {
+ QString name = containerName;
+ name += QLatin1String("Page");
+ name += QString::number(i + 1);
+ QWidget *page = core->widgetFactory()->createWidget(qWidget);
+ page->setObjectName(name);
+ fw->ensureUniqueObjectName(page);
+ c->addWidget(page);
+ core->metaDataBase()->add(page);
+ }
+ }
+ }
+
+ // Copy over applicable properties
+ const QDesignerPropertySheetExtension *beforeSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), widget);
+ QDesignerPropertySheetExtension *afterSheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), m_afterWidget);
+ const QString objectNameProperty = QLatin1String("objectName");
+ const int count = beforeSheet->count();
+ for (int i = 0; i < count; i++)
+ if (beforeSheet->isVisible(i) && beforeSheet->isChanged(i)) {
+ const QString name = beforeSheet->propertyName(i);
+ if (name != objectNameProperty) {
+ const int afterIndex = afterSheet->indexOf(name);
+ if (afterIndex != -1 && afterSheet->isVisible(afterIndex) && afterSheet->propertyGroup(afterIndex) == beforeSheet->propertyGroup(i)) {
+ afterSheet->setProperty(i, beforeSheet->property(i));
+ afterSheet->setChanged(i, true);
+ } else {
+ // Some mismatch. The rest won't match, either
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+void MorphWidgetCommand::redo()
+{
+ morph(m_beforeWidget, m_afterWidget);
+}
+
+void MorphWidgetCommand::undo()
+{
+ morph(m_afterWidget, m_beforeWidget);
+}
+
+void MorphWidgetCommand::morph(QWidget *before, QWidget *after)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+
+ fw->unmanageWidget(before);
+
+ const QRect oldGeom = before->geometry();
+ QWidget *parent = before->parentWidget();
+ Q_ASSERT(parent);
+ /* Morphing consists of main 2 steps
+ * 1) Move over children (laid out, non-laid out)
+ * 2) Register self with new parent (laid out, non-laid out) */
+
+ // 1) Move children. Loop over child containers
+ QWidgetList beforeChildContainers = childContainers(fw->core(), before);
+ QWidgetList afterChildContainers = childContainers(fw->core(), after);
+ Q_ASSERT(beforeChildContainers.size() == afterChildContainers.size());
+ const int childContainerCount = beforeChildContainers.size();
+ for (int i = 0; i < childContainerCount; i++) {
+ QWidget *beforeChildContainer = beforeChildContainers.at(i);
+ QWidget *afterChildContainer = afterChildContainers.at(i);
+ if (QLayout *childLayout = beforeChildContainer->layout()) {
+ // Laid-out: Move the layout (since 4.5)
+ afterChildContainer->setLayout(childLayout);
+ } else {
+ // Non-Laid-out: Reparent, move over
+ const QObjectList c = beforeChildContainer->children();
+ const QObjectList::const_iterator cend = c.constEnd();
+ for (QObjectList::const_iterator it = c.constBegin(); it != cend; ++it) {
+ if ( (*it)->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(*it);
+ if (fw->isManaged(w)) {
+ const QRect geom = w->geometry();
+ w->setParent(afterChildContainer);
+ w->setGeometry(geom);
+ }
+ }
+ }
+ }
+ afterChildContainer->setProperty(widgetOrderPropertyC, beforeChildContainer->property(widgetOrderPropertyC));
+ afterChildContainer->setProperty(zOrderPropertyC, beforeChildContainer->property(zOrderPropertyC));
+ }
+
+ // 2) Replace the actual widget in the parent layout
+ after->setGeometry(oldGeom);
+ if (QLayout *containingLayout = LayoutInfo::managedLayout(fw->core(), parent)) {
+ LayoutHelper *lh = LayoutHelper::createLayoutHelper(LayoutInfo::layoutType(fw->core(), containingLayout));
+ Q_ASSERT(lh);
+ lh->replaceWidget(containingLayout, before, after);
+ delete lh;
+ } else {
+ before->hide();
+ before->setParent(0);
+ after->setParent(parent);
+ after->setGeometry(oldGeom);
+ }
+
+ // Check various properties: Z order, form tab order
+ replaceWidgetListDynamicProperty(parent, before, after, widgetOrderPropertyC);
+ replaceWidgetListDynamicProperty(parent, before, after, zOrderPropertyC);
+
+ QDesignerMetaDataBaseItemInterface *formItem = fw->core()->metaDataBase()->item(fw);
+ QWidgetList tabOrder = formItem->tabOrder();
+ const int tabIndex = tabOrder.indexOf(before);
+ if (tabIndex != -1) {
+ tabOrder.replace(tabIndex, after);
+ formItem->setTabOrder(tabOrder);
+ }
+
+ after->show();
+ fw->manageWidget(after);
+
+ fw->clearSelection(false);
+ fw->selectWidget(after);
+}
+
+/* Check if morphing is possible. It must be a valid category and the parent/
+ * child relationships must be either non-laidout or directly on
+ * Designer-managed layouts. */
+bool MorphWidgetCommand::canMorph(QDesignerFormWindowInterface *fw, QWidget *w, int *ptrToChildContainerCount, MorphCategory *ptrToCat)
+{
+ if (ptrToChildContainerCount)
+ *ptrToChildContainerCount = 0;
+ const MorphCategory cat = category(w);
+ if (ptrToCat)
+ *ptrToCat = cat;
+ if (cat == MorphCategoryNone)
+ return false;
+
+ QDesignerFormEditorInterface *core = fw->core();
+ // Don't know how to fiddle class names in Jambi..
+ if (qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
+ return false;
+ if (!fw->isManaged(w) || w == fw->mainContainer())
+ return false;
+ // Check the parent relationship. We accept only managed parent widgets
+ // with a single, managed layout in which widget is a member.
+ QWidget *parent = w->parentWidget();
+ if (parent == 0)
+ return false;
+ if (QLayout *pl = LayoutInfo::managedLayout(core, parent))
+ if (pl->indexOf(w) < 0 || !core->metaDataBase()->item(pl))
+ return false;
+ // Check Widget database
+ const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
+ const int wdbindex = wdb->indexOfObject(w);
+ if (wdbindex == -1)
+ return false;
+ const bool isContainer = wdb->item(wdbindex)->isContainer();
+ if (!isContainer)
+ return true;
+ // Check children. All child containers must be non-laid-out or have managed layouts
+ const QWidgetList pages = childContainers(core, w);
+ const int pageCount = pages.size();
+ if (ptrToChildContainerCount)
+ *ptrToChildContainerCount = pageCount;
+ if (pageCount) {
+ for (int i = 0; i < pageCount; i++)
+ if (QLayout *cl = pages.at(i)->layout())
+ if (!core->metaDataBase()->item(cl))
+ return false;
+ }
+ return true;
+}
+
+QStringList MorphWidgetCommand::candidateClasses(QDesignerFormWindowInterface *fw, QWidget *w)
+{
+ int childContainerCount;
+ MorphCategory cat;
+ if (!canMorph(fw, w, &childContainerCount, &cat))
+ return QStringList();
+
+ QStringList rc = classesOfCategory(cat);
+ switch (cat) {
+ // Frames, etc can always be morphed into one-page page containers
+ case MorphSimpleContainer:
+ rc += classesOfCategory(MorphPageContainer);
+ break;
+ // Multipage-Containers can be morphed into simple containers if they
+ // have 1 page.
+ case MorphPageContainer:
+ if (childContainerCount == 1)
+ rc += classesOfCategory(MorphSimpleContainer);
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
+
+// MorphMenu
+MorphMenu::MorphMenu(QObject *parent) :
+ QObject(parent),
+ m_subMenuAction(0),
+ m_menu(0),
+ m_mapper(0),
+ m_widget(0),
+ m_formWindow(0)
+{
+}
+
+void MorphMenu::populate(QWidget *w, QDesignerFormWindowInterface *fw, ActionList& al)
+{
+ if (populateMenu(w, fw))
+ al.push_back(m_subMenuAction);
+}
+
+void MorphMenu::populate(QWidget *w, QDesignerFormWindowInterface *fw, QMenu& m)
+{
+ if (populateMenu(w, fw))
+ m.addAction(m_subMenuAction);
+}
+
+void MorphMenu::slotMorph(const QString &newClassName)
+{
+ MorphWidgetCommand::addMorphMacro(m_formWindow, m_widget, newClassName);
+}
+
+bool MorphMenu::populateMenu(QWidget *w, QDesignerFormWindowInterface *fw)
+{
+ m_widget = 0;
+ m_formWindow = 0;
+
+ // Clear menu
+ if (m_subMenuAction) {
+ m_subMenuAction->setVisible(false);
+ m_menu->clear();
+ }
+
+ // Checks: Must not be main container
+ if (w == fw->mainContainer())
+ return false;
+
+ const QStringList c = MorphWidgetCommand::candidateClasses(fw, w);
+ if (c.empty())
+ return false;
+
+ // Pull up
+ m_widget = w;
+ m_formWindow = fw;
+ const QString oldClassName = WidgetFactory::classNameOf(fw->core(), w);
+
+ if (!m_subMenuAction) {
+ m_subMenuAction = new QAction(tr("Morph into"), this);
+ m_menu = new QMenu;
+ m_subMenuAction->setMenu(m_menu);
+ m_mapper = new QSignalMapper(this);
+ connect(m_mapper , SIGNAL(mapped(QString)), this, SLOT(slotMorph(QString)));
+ }
+
+ // Add actions
+ const QStringList::const_iterator cend = c.constEnd();
+ for (QStringList::const_iterator it = c.constBegin(); it != cend; ++it) {
+ if (*it != oldClassName) {
+ QAction *a = m_menu->addAction(*it);
+ m_mapper->setMapping (a, *it);
+ connect(a, SIGNAL(triggered()), m_mapper, SLOT(map()));
+ }
+ }
+ m_subMenuAction->setVisible(true);
+ return true;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/morphmenu_p.h b/tools/designer/src/lib/shared/morphmenu_p.h
new file mode 100644
index 0000000000..92389a0590
--- /dev/null
+++ b/tools/designer/src/lib/shared/morphmenu_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef MORPH_COMMAND_H
+#define MORPH_COMMAND_H
+
+#include "shared_global_p.h"
+#include "qdesigner_formwindowcommand_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QSignalMapper;
+class QMenu;
+
+namespace qdesigner_internal {
+
+/* Conveniene morph menu that acts on a single widget. */
+class QDESIGNER_SHARED_EXPORT MorphMenu : public QObject {
+ Q_DISABLE_COPY(MorphMenu)
+ Q_OBJECT
+public:
+ typedef QList<QAction *> ActionList;
+
+ explicit MorphMenu(QObject *parent = 0);
+
+ void populate(QWidget *w, QDesignerFormWindowInterface *fw, ActionList& al);
+ void populate(QWidget *w, QDesignerFormWindowInterface *fw, QMenu& m);
+
+private slots:
+ void slotMorph(const QString &newClassName);
+
+private:
+ bool populateMenu(QWidget *w, QDesignerFormWindowInterface *fw);
+
+ QAction *m_subMenuAction;
+ QMenu *m_menu;
+ QSignalMapper *m_mapper;
+
+ QWidget *m_widget;
+ QDesignerFormWindowInterface *m_formWindow;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // MORPH_COMMAND_H
diff --git a/tools/designer/src/lib/shared/newactiondialog.cpp b/tools/designer/src/lib/shared/newactiondialog.cpp
new file mode 100644
index 0000000000..53aec4b441
--- /dev/null
+++ b/tools/designer/src/lib/shared/newactiondialog.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "newactiondialog_p.h"
+#include "ui_newactiondialog.h"
+#include "richtexteditor_p.h"
+#include "actioneditor_p.h"
+#include "formwindowbase_p.h"
+#include "qdesigner_utils_p.h"
+#include "iconloader_p.h"
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/abstractformeditor.h>
+
+#include <QtGui/QPushButton>
+#include <QtCore/QRegExp>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+// -------------------- ActionData
+
+ActionData::ActionData() :
+ checkable(false)
+{
+}
+
+// Returns a combination of ChangeMask flags
+unsigned ActionData::compare(const ActionData &rhs) const
+{
+ unsigned rc = 0;
+ if (text != rhs.text)
+ rc |= TextChanged;
+ if (name != rhs.name)
+ rc |= NameChanged;
+ if (toolTip != rhs.toolTip)
+ rc |= ToolTipChanged ;
+ if (icon != rhs.icon)
+ rc |= IconChanged ;
+ if (checkable != rhs.checkable)
+ rc |= CheckableChanged;
+ if (keysequence != rhs.keysequence)
+ rc |= KeysequenceChanged ;
+ return rc;
+}
+
+// -------------------- NewActionDialog
+NewActionDialog::NewActionDialog(ActionEditor *parent) :
+ QDialog(parent, Qt::Sheet),
+ m_ui(new Ui::NewActionDialog),
+ m_actionEditor(parent)
+{
+ m_ui->setupUi(this);
+
+ m_ui->tooltipEditor->setTextPropertyValidationMode(ValidationRichText);
+ connect(m_ui->toolTipToolButton, SIGNAL(clicked()), this, SLOT(slotEditToolTip()));
+
+ m_ui->keysequenceResetToolButton->setIcon(createIconSet(QLatin1String("resetproperty.png")));
+ connect(m_ui->keysequenceResetToolButton, SIGNAL(clicked()), this, SLOT(slotResetKeySequence()));
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ m_ui->editActionText->setFocus();
+ m_auto_update_object_name = true;
+ updateButtons();
+
+ QDesignerFormWindowInterface *form = parent->formWindow();
+ m_ui->iconSelector->setFormEditor(form->core());
+ FormWindowBase *formBase = qobject_cast<FormWindowBase *>(form);
+
+ if (formBase) {
+ m_ui->iconSelector->setPixmapCache(formBase->pixmapCache());
+ m_ui->iconSelector->setIconCache(formBase->iconCache());
+ }
+}
+
+NewActionDialog::~NewActionDialog()
+{
+ delete m_ui;
+}
+
+QString NewActionDialog::actionText() const
+{
+ return m_ui->editActionText->text();
+}
+
+QString NewActionDialog::actionName() const
+{
+ return m_ui->editObjectName->text();
+}
+
+ActionData NewActionDialog::actionData() const
+{
+ ActionData rc;
+ rc.text = actionText();
+ rc.name = actionName();
+ rc.toolTip = m_ui->tooltipEditor->text();
+ rc.icon = m_ui->iconSelector->icon();
+ rc.checkable = m_ui->checkableCheckBox->checkState() == Qt::Checked;
+ rc.keysequence = m_ui->keySequenceEdit->keySequence();
+ return rc;
+}
+
+void NewActionDialog::setActionData(const ActionData &d)
+{
+ m_ui->editActionText->setText(d.text);
+ m_ui->editObjectName->setText(d.name);
+ m_ui->iconSelector->setIcon(d.icon);
+ m_ui->tooltipEditor->setText(d.toolTip);
+ m_ui->keySequenceEdit->setKeySequence(d.keysequence);
+ m_ui->checkableCheckBox->setCheckState(d.checkable ? Qt::Checked : Qt::Unchecked);
+
+ m_auto_update_object_name = false;
+ updateButtons();
+}
+
+void NewActionDialog::on_editActionText_textEdited(const QString &text)
+{
+ if (text.isEmpty())
+ m_auto_update_object_name = true;
+
+ if (m_auto_update_object_name)
+ m_ui->editObjectName->setText(ActionEditor::actionTextToName(text));
+
+ updateButtons();
+}
+
+void NewActionDialog::on_editObjectName_textEdited(const QString&)
+{
+ updateButtons();
+ m_auto_update_object_name = false;
+}
+
+void NewActionDialog::slotEditToolTip()
+{
+ const QString oldToolTip = m_ui->tooltipEditor->text();
+ RichTextEditorDialog richTextDialog(m_actionEditor->core(), this);
+ richTextDialog.setText(oldToolTip);
+ if (richTextDialog.showDialog() == QDialog::Rejected)
+ return;
+ const QString newToolTip = richTextDialog.text();
+ if (newToolTip != oldToolTip)
+ m_ui->tooltipEditor->setText(newToolTip);
+}
+
+void NewActionDialog::slotResetKeySequence()
+{
+ m_ui->keySequenceEdit->setKeySequence(QKeySequence());
+ m_ui->keySequenceEdit->setFocus(Qt::MouseFocusReason);
+}
+
+void NewActionDialog::updateButtons()
+{
+ QPushButton *okButton = m_ui->buttonBox->button(QDialogButtonBox::Ok);
+ okButton->setEnabled(!actionText().isEmpty() && !actionName().isEmpty());
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/newactiondialog.ui b/tools/designer/src/lib/shared/newactiondialog.ui
new file mode 100644
index 0000000000..77eda28245
--- /dev/null
+++ b/tools/designer/src/lib/shared/newactiondialog.ui
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::NewActionDialog</class>
+ <widget class="QDialog" name="qdesigner_internal::NewActionDialog">
+ <property name="windowTitle">
+ <string>New Action...</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="textLabel">
+ <property name="text">
+ <string>&amp;Text:</string>
+ </property>
+ <property name="buddy">
+ <cstring>editActionText</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="editActionText">
+ <property name="minimumSize">
+ <size>
+ <width>255</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="objectNameLabel">
+ <property name="text">
+ <string>Object &amp;name:</string>
+ </property>
+ <property name="buddy">
+ <cstring>editObjectName</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="editObjectName"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="iconLabel">
+ <property name="text">
+ <string>&amp;Icon:</string>
+ </property>
+ <property name="buddy">
+ <cstring>iconSelector</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="qdesigner_internal::IconSelector" name="iconSelector" native="true"/>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="shortcutLabel">
+ <property name="text">
+ <string>Shortcut:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QCheckBox" name="checkableCheckBox">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="checkableLabel">
+ <property name="text">
+ <string>Checkable:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="toolTipLabel">
+ <property name="text">
+ <string>ToolTip:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <layout class="QHBoxLayout" name="toolTipLayout">
+ <item>
+ <widget class="TextPropertyEditor" name="tooltipEditor" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="toolTipToolButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="5" column="1">
+ <layout class="QHBoxLayout" name="keysequenceLayout">
+ <item>
+ <widget class="QtKeySequenceEdit" name="keySequenceEdit" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="keysequenceResetToolButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>qdesigner_internal::IconSelector</class>
+ <extends>QWidget</extends>
+ <header>iconselector_p.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QtKeySequenceEdit</class>
+ <extends>QWidget</extends>
+ <header>qtpropertybrowserutils_p.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>TextPropertyEditor</class>
+ <extends>QWidget</extends>
+ <header>textpropertyeditor_p.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>editActionText</tabstop>
+ <tabstop>editObjectName</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>qdesigner_internal::NewActionDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>165</x>
+ <y>162</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>291</x>
+ <y>94</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>qdesigner_internal::NewActionDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>259</x>
+ <y>162</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>293</x>
+ <y>128</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/newactiondialog_p.h b/tools/designer/src/lib/shared/newactiondialog_p.h
new file mode 100644
index 0000000000..c8bd34c5f3
--- /dev/null
+++ b/tools/designer/src/lib/shared/newactiondialog_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NEWACTIONDIALOG_P_H
+#define NEWACTIONDIALOG_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qdesigner_utils_p.h" // PropertySheetIconValue
+
+#include <QtGui/QDialog>
+#include <QtGui/QKeySequence>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+namespace Ui {
+ class NewActionDialog;
+}
+
+class ActionEditor;
+
+struct ActionData {
+
+ enum ChangeMask {
+ TextChanged = 0x1, NameChanged = 0x2, ToolTipChanged = 0x4,
+ IconChanged = 0x8, CheckableChanged = 0x10, KeysequenceChanged = 0x20
+ };
+
+ ActionData();
+ // Returns a combination of ChangeMask flags
+ unsigned compare(const ActionData &rhs) const;
+
+ QString text;
+ QString name;
+ QString toolTip;
+ PropertySheetIconValue icon;
+ bool checkable;
+ QKeySequence keysequence;
+};
+
+inline bool operator==(const ActionData &a1, const ActionData &a2) { return a1.compare(a2) == 0u; }
+inline bool operator!=(const ActionData &a1, const ActionData &a2) { return a1.compare(a2) != 0u; }
+
+class NewActionDialog: public QDialog
+{
+ Q_OBJECT
+public:
+ explicit NewActionDialog(ActionEditor *parent);
+ virtual ~NewActionDialog();
+
+ ActionData actionData() const;
+ void setActionData(const ActionData &d);
+
+ QString actionText() const;
+ QString actionName() const;
+
+private slots:
+ void on_editActionText_textEdited(const QString &text);
+ void on_editObjectName_textEdited(const QString &text);
+ void slotEditToolTip();
+ void slotResetKeySequence();
+
+private:
+ Ui::NewActionDialog *m_ui;
+ ActionEditor *m_actionEditor;
+ bool m_auto_update_object_name;
+
+ void updateButtons();
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // NEWACTIONDIALOG_P_H
diff --git a/tools/designer/src/lib/shared/newformwidget.cpp b/tools/designer/src/lib/shared/newformwidget.cpp
new file mode 100644
index 0000000000..d79d77acf1
--- /dev/null
+++ b/tools/designer/src/lib/shared/newformwidget.cpp
@@ -0,0 +1,587 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "newformwidget_p.h"
+#include "ui_newformwidget.h"
+#include "qdesigner_formbuilder_p.h"
+#include "sheet_delegate_p.h"
+#include "widgetdatabase_p.h"
+#include "shared_settings_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QByteArray>
+#include <QtCore/QBuffer>
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+
+#include <QtGui/QHeaderView>
+#include <QtGui/QTreeWidgetItem>
+#include <QtGui/QPainter>
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+enum { profileComboIndexOffset = 1 };
+enum { debugNewFormWidget = 0 };
+
+enum NewForm_CustomRole {
+ // File name (templates from resources, paths)
+ TemplateNameRole = Qt::UserRole + 100,
+ // Class name (widgets from Widget data base)
+ ClassNameRole = Qt::UserRole + 101
+};
+
+static const char *newFormObjectNameC = "Form";
+
+// Create a form name for an arbitrary class. If it is Qt, qtify it,
+// else return "Form".
+static QString formName(const QString &className)
+{
+ if (!className.startsWith(QLatin1Char('Q')))
+ return QLatin1String(newFormObjectNameC);
+ QString rc = className;
+ rc.remove(0, 1);
+ return rc;
+}
+
+namespace qdesigner_internal {
+
+struct TemplateSize {
+ const char *name;
+ int width;
+ int height;
+};
+
+static const struct TemplateSize templateSizes[] =
+{
+ { QT_TRANSLATE_NOOP("qdesigner_internal::NewFormWidget", "Default size"), 0, 0 },
+ { QT_TRANSLATE_NOOP("qdesigner_internal::NewFormWidget", "QVGA portrait (240x320)"), 240, 320 },
+ { QT_TRANSLATE_NOOP("qdesigner_internal::NewFormWidget", "QVGA landscape (320x240)"), 320, 240 },
+ { QT_TRANSLATE_NOOP("qdesigner_internal::NewFormWidget", "VGA portrait (480x640)"), 480, 640 },
+ { QT_TRANSLATE_NOOP("qdesigner_internal::NewFormWidget", "VGA landscape (640x480)"), 640, 480 }
+};
+
+/* -------------- NewForm dialog.
+ * Designer takes new form templates from:
+ * 1) Files located in directories specified in resources
+ * 2) Files located in directories specified as user templates
+ * 3) XML from container widgets deemed usable for form templates by the widget
+ * database
+ * 4) XML from custom container widgets deemed usable for form templates by the
+ * widget database
+ *
+ * The widget database provides helper functions to obtain lists of names
+ * and xml for 3,4.
+ *
+ * Fixed-size forms for embedded platforms are obtained as follows:
+ * 1) If the origin is a file:
+ * - Check if the file exists in the subdirectory "/<width>x<height>/" of
+ * the path (currently the case for the dialog box because the button box
+ * needs to be positioned)
+ * - Scale the form using the QWidgetDatabase::scaleFormTemplate routine.
+ * 2) If the origin is XML:
+ * - Scale the form using the QWidgetDatabase::scaleFormTemplate routine.
+ *
+ * The tree widget item roles indicate which type of entry it is
+ * (TemplateNameRole = file name 1,2, ClassNameRole = class name 3,4)
+ */
+
+NewFormWidget::NewFormWidget(QDesignerFormEditorInterface *core, QWidget *parentWidget) :
+ QDesignerNewFormWidgetInterface(parentWidget),
+ m_core(core),
+ m_ui(new Ui::NewFormWidget),
+ m_currentItem(0),
+ m_acceptedItem(0)
+{
+ typedef QList<qdesigner_internal::DeviceProfile> DeviceProfileList;
+
+ m_ui->setupUi(this);
+ m_ui->treeWidget->setItemDelegate(new qdesigner_internal::SheetDelegate(m_ui->treeWidget, this));
+ m_ui->treeWidget->header()->hide();
+ m_ui->treeWidget->header()->setStretchLastSection(true);
+ m_ui->lblPreview->setBackgroundRole(QPalette::Base);
+ QDesignerSharedSettings settings(m_core);
+
+ QString uiExtension = QLatin1String("ui");
+ QString templatePath = QLatin1String(":/trolltech/designer/templates/forms");
+
+ QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core);
+ if (lang) {
+ templatePath = QLatin1String(":/templates/forms");
+ uiExtension = lang->uiExtension();
+ }
+
+ // Resource templates
+ const QString formTemplate = settings.formTemplate();
+ QTreeWidgetItem *selectedItem = 0;
+ loadFrom(templatePath, true, uiExtension, formTemplate, selectedItem);
+ // Additional template paths
+ const QStringList formTemplatePaths = settings.formTemplatePaths();
+ const QStringList::const_iterator ftcend = formTemplatePaths.constEnd();
+ for (QStringList::const_iterator it = formTemplatePaths.constBegin(); it != ftcend; ++it)
+ loadFrom(*it, false, uiExtension, formTemplate, selectedItem);
+
+ // Widgets/custom widgets
+ if (!lang) {
+ //: New Form Dialog Categories
+ loadFrom(tr("Widgets"), qdesigner_internal::WidgetDataBase::formWidgetClasses(core), formTemplate, selectedItem);
+ loadFrom(tr("Custom Widgets"), qdesigner_internal::WidgetDataBase::customFormWidgetClasses(core), formTemplate, selectedItem);
+ }
+
+ // Still no selection - default to first item
+ if (selectedItem == 0 && m_ui->treeWidget->topLevelItemCount() != 0) {
+ QTreeWidgetItem *firstTopLevel = m_ui->treeWidget->topLevelItem(0);
+ if (firstTopLevel->childCount() > 0)
+ selectedItem = firstTopLevel->child(0);
+ }
+
+ // Open parent, select and make visible
+ if (selectedItem) {
+ m_ui->treeWidget->setCurrentItem(selectedItem);
+ m_ui->treeWidget->setItemSelected(selectedItem, true);
+ m_ui->treeWidget->scrollToItem(selectedItem->parent());
+ }
+ // Fill profile combo
+ m_deviceProfiles = settings.deviceProfiles();
+ m_ui->profileComboBox->addItem(tr("None"));
+ connect(m_ui->profileComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotDeviceProfileIndexChanged(int)));
+ if (m_deviceProfiles.empty()) {
+ m_ui->profileComboBox->setEnabled(false);
+ } else {
+ const DeviceProfileList::const_iterator dcend = m_deviceProfiles.constEnd();
+ for (DeviceProfileList::const_iterator it = m_deviceProfiles.constBegin(); it != dcend; ++it)
+ m_ui->profileComboBox->addItem(it->name());
+ const int ci = settings.currentDeviceProfileIndex();
+ if (ci >= 0)
+ m_ui->profileComboBox->setCurrentIndex(ci + profileComboIndexOffset);
+ }
+ // Fill size combo
+ const int sizeCount = sizeof(templateSizes)/ sizeof(TemplateSize);
+ for (int i = 0; i < sizeCount; i++) {
+ const QSize size = QSize(templateSizes[i].width, templateSizes[i].height);
+ m_ui->sizeComboBox->addItem(tr(templateSizes[i].name), size);
+ }
+
+ setTemplateSize(settings.newFormSize());
+
+ if (debugNewFormWidget)
+ qDebug() << Q_FUNC_INFO << "Leaving";
+}
+
+NewFormWidget::~NewFormWidget()
+{
+ QDesignerSharedSettings settings (m_core);
+ settings.setNewFormSize(templateSize());
+ // Do not change previously stored item if dialog was rejected
+ if (m_acceptedItem)
+ settings.setFormTemplate(m_acceptedItem->text(0));
+ delete m_ui;
+}
+
+void NewFormWidget::on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *)
+{
+ if (debugNewFormWidget)
+ qDebug() << Q_FUNC_INFO << current;
+ if (!current)
+ return;
+
+ if (!current->parent()) { // Top level item: Ensure expanded when browsing down
+ return;
+ }
+
+ m_currentItem = current;
+
+ emit currentTemplateChanged(showCurrentItemPixmap());
+}
+
+bool NewFormWidget::showCurrentItemPixmap()
+{
+ bool rc = false;
+ if (m_currentItem) {
+ const QPixmap pixmap = formPreviewPixmap(m_currentItem);
+ if (pixmap.isNull()) {
+ m_ui->lblPreview->setText(tr("Error loading form"));
+ } else {
+ m_ui->lblPreview->setPixmap(pixmap);
+ rc = true;
+ }
+ }
+ return rc;
+}
+
+void NewFormWidget::on_treeWidget_itemActivated(QTreeWidgetItem *item)
+{
+ if (debugNewFormWidget)
+ qDebug() << Q_FUNC_INFO << item;
+
+ if (item->data(0, TemplateNameRole).isValid() || item->data(0, ClassNameRole).isValid())
+ emit templateActivated();
+}
+
+QPixmap NewFormWidget::formPreviewPixmap(const QTreeWidgetItem *item)
+{
+ // Cache pixmaps per item/device profile
+ const ItemPixmapCacheKey cacheKey(item, profileComboIndex());
+ ItemPixmapCache::iterator it = m_itemPixmapCache.find(cacheKey);
+ if (it == m_itemPixmapCache.end()) {
+ // file or string?
+ const QVariant fileName = item->data(0, TemplateNameRole);
+ QPixmap rc;
+ if (fileName.type() == QVariant::String) {
+ rc = formPreviewPixmap(fileName.toString());
+ } else {
+ const QVariant classNameV = item->data(0, ClassNameRole);
+ Q_ASSERT(classNameV.type() == QVariant::String);
+ const QString className = classNameV.toString();
+ QByteArray data = qdesigner_internal::WidgetDataBase::formTemplate(m_core, className, formName(className)).toUtf8();
+ QBuffer buffer(&data);
+ buffer.open(QIODevice::ReadOnly);
+ rc = formPreviewPixmap(buffer);
+ }
+ if (rc.isNull()) // Retry invalid ones
+ return rc;
+ it = m_itemPixmapCache.insert(cacheKey, rc);
+ }
+ return it.value();
+}
+
+QPixmap NewFormWidget::formPreviewPixmap(const QString &fileName) const
+{
+ QFile f(fileName);
+ if (f.open(QFile::ReadOnly)) {
+ QFileInfo fi(fileName);
+ const QPixmap rc = formPreviewPixmap(f, fi.absolutePath());
+ f.close();
+ return rc;
+ }
+ qWarning() << "The file " << fileName << " could not be opened: " << f.errorString();
+ return QPixmap();
+}
+
+QImage NewFormWidget::grabForm(QDesignerFormEditorInterface *core,
+ QIODevice &file,
+ const QString &workingDir,
+ const qdesigner_internal::DeviceProfile &dp)
+{
+ qdesigner_internal::QDesignerFormBuilder formBuilder(core,
+ qdesigner_internal::QDesignerFormBuilder::DisableScripts,
+ dp);
+ if (!workingDir.isEmpty())
+ formBuilder.setWorkingDirectory(workingDir);
+
+ QWidget *widget = formBuilder.load(&file, 0);
+ if (!widget)
+ return QImage();
+
+ const QPixmap pixmap = QPixmap::grabWidget(widget);
+ widget->deleteLater();
+ return pixmap.toImage();
+}
+
+QPixmap NewFormWidget::formPreviewPixmap(QIODevice &file, const QString &workingDir) const
+{
+ const int margin = 7;
+ const int shadow = 7;
+ const int previewSize = 256;
+
+ const QImage wimage = grabForm(m_core, file, workingDir, currentDeviceProfile());
+ if (wimage.isNull())
+ return QPixmap();
+ const QImage image = wimage.scaled(previewSize - margin * 2, previewSize - margin * 2,
+ Qt::KeepAspectRatio,
+ Qt::SmoothTransformation);
+
+ QImage dest(previewSize, previewSize, QImage::Format_ARGB32_Premultiplied);
+ dest.fill(0);
+
+ QPainter p(&dest);
+ p.drawImage(margin, margin, image);
+
+ p.setPen(QPen(palette().brush(QPalette::WindowText), 0));
+
+ p.drawRect(margin-1, margin-1, image.width() + 1, image.height() + 1);
+
+ const QColor dark(Qt::darkGray);
+ const QColor light(Qt::transparent);
+
+ // right shadow
+ {
+ const QRect rect(margin + image.width() + 1, margin + shadow, shadow, image.height() - shadow + 1);
+ QLinearGradient lg(rect.topLeft(), rect.topRight());
+ lg.setColorAt(0, dark);
+ lg.setColorAt(1, light);
+ p.fillRect(rect, lg);
+ }
+
+ // bottom shadow
+ {
+ const QRect rect(margin + shadow, margin + image.height() + 1, image.width() - shadow + 1, shadow);
+ QLinearGradient lg(rect.topLeft(), rect.bottomLeft());
+ lg.setColorAt(0, dark);
+ lg.setColorAt(1, light);
+ p.fillRect(rect, lg);
+ }
+
+ // bottom/right corner shadow
+ {
+ const QRect rect(margin + image.width() + 1, margin + image.height() + 1, shadow, shadow);
+ QRadialGradient g(rect.topLeft(), shadow);
+ g.setColorAt(0, dark);
+ g.setColorAt(1, light);
+ p.fillRect(rect, g);
+ }
+
+ // top/right corner
+ {
+ const QRect rect(margin + image.width() + 1, margin, shadow, shadow);
+ QRadialGradient g(rect.bottomLeft(), shadow);
+ g.setColorAt(0, dark);
+ g.setColorAt(1, light);
+ p.fillRect(rect, g);
+ }
+
+ // bottom/left corner
+ {
+ const QRect rect(margin, margin + image.height() + 1, shadow, shadow);
+ QRadialGradient g(rect.topRight(), shadow);
+ g.setColorAt(0, dark);
+ g.setColorAt(1, light);
+ p.fillRect(rect, g);
+ }
+
+ p.end();
+
+ return QPixmap::fromImage(dest);
+}
+
+void NewFormWidget::loadFrom(const QString &path, bool resourceFile, const QString &uiExtension,
+ const QString &selectedItem, QTreeWidgetItem *&selectedItemFound)
+{
+ const QDir dir(path);
+
+ if (!dir.exists())
+ return;
+
+ // Iterate through the directory and add the templates
+ const QFileInfoList list = dir.entryInfoList(QStringList(QLatin1String("*.") + uiExtension),
+ QDir::Files);
+
+ if (list.isEmpty())
+ return;
+
+ const QChar separator = resourceFile ? QChar(QLatin1Char('/'))
+ : QDir::separator();
+ QTreeWidgetItem *root = new QTreeWidgetItem(m_ui->treeWidget);
+ root->setFlags(root->flags() & ~Qt::ItemIsSelectable);
+ // Try to get something that is easy to read.
+ QString visiblePath = path;
+ int index = visiblePath.lastIndexOf(separator);
+ if (index != -1) {
+ // try to find a second slash, just to be a bit better.
+ const int index2 = visiblePath.lastIndexOf(separator, index - 1);
+ if (index2 != -1)
+ index = index2;
+ visiblePath = visiblePath.mid(index + 1);
+ visiblePath = QDir::toNativeSeparators(visiblePath);
+ }
+
+ const QChar underscore = QLatin1Char('_');
+ const QChar blank = QLatin1Char(' ');
+ root->setText(0, visiblePath.replace(underscore, blank));
+ root->setToolTip(0, path);
+
+ const QFileInfoList::const_iterator lcend = list.constEnd();
+ for (QFileInfoList::const_iterator it = list.constBegin(); it != lcend; ++it) {
+ if (!it->isFile())
+ continue;
+
+ QTreeWidgetItem *item = new QTreeWidgetItem(root);
+ const QString text = it->baseName().replace(underscore, blank);
+ if (selectedItemFound == 0 && text == selectedItem)
+ selectedItemFound = item;
+ item->setText(0, text);
+ item->setData(0, TemplateNameRole, it->absoluteFilePath());
+ }
+}
+
+void NewFormWidget::loadFrom(const QString &title, const QStringList &nameList,
+ const QString &selectedItem, QTreeWidgetItem *&selectedItemFound)
+{
+ if (nameList.empty())
+ return;
+ QTreeWidgetItem *root = new QTreeWidgetItem(m_ui->treeWidget);
+ root->setFlags(root->flags() & ~Qt::ItemIsSelectable);
+ root->setText(0, title);
+ const QStringList::const_iterator cend = nameList.constEnd();
+ for (QStringList::const_iterator it = nameList.constBegin(); it != cend; ++it) {
+ const QString text = *it;
+ QTreeWidgetItem *item = new QTreeWidgetItem(root);
+ item->setText(0, text);
+ if (selectedItemFound == 0 && text == selectedItem)
+ selectedItemFound = item;
+ item->setData(0, ClassNameRole, *it);
+ }
+}
+
+void NewFormWidget::on_treeWidget_itemPressed(QTreeWidgetItem *item)
+{
+ if (item && !item->parent())
+ m_ui->treeWidget->setItemExpanded(item, !m_ui->treeWidget->isItemExpanded(item));
+}
+
+QSize NewFormWidget::templateSize() const
+{
+ return m_ui->sizeComboBox->itemData(m_ui->sizeComboBox->currentIndex()).toSize();
+}
+
+void NewFormWidget::setTemplateSize(const QSize &s)
+{
+ const int index = s.isNull() ? 0 : m_ui->sizeComboBox->findData(s);
+ if (index != -1)
+ m_ui->sizeComboBox->setCurrentIndex(index);
+}
+
+static QString readAll(const QString &fileName, QString *errorMessage)
+{
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ *errorMessage = NewFormWidget::tr("Unable to open the form template file '%1': %2").arg(fileName, file.errorString());
+ return QString();
+ }
+ return QString::fromUtf8(file.readAll());
+}
+
+QString NewFormWidget::itemToTemplate(const QTreeWidgetItem *item, QString *errorMessage) const
+{
+ const QSize size = templateSize();
+ // file name or string contents?
+ const QVariant templateFileName = item->data(0, TemplateNameRole);
+ if (templateFileName.type() == QVariant::String) {
+ const QString fileName = templateFileName.toString();
+ // No fixed size: just open.
+ if (size.isNull())
+ return readAll(fileName, errorMessage);
+ // try to find a file matching the size, like "../640x480/xx.ui"
+ const QFileInfo fiBase(fileName);
+ QString sizeFileName;
+ QTextStream(&sizeFileName) << fiBase.path() << QDir::separator()
+ << size.width() << QLatin1Char('x') << size.height() << QDir::separator()
+ << fiBase.fileName();
+ if (QFileInfo(sizeFileName).isFile())
+ return readAll(sizeFileName, errorMessage);
+ // Nothing found, scale via DOM/temporary file
+ QString contents = readAll(fileName, errorMessage);
+ if (!contents.isEmpty())
+ contents = qdesigner_internal::WidgetDataBase::scaleFormTemplate(contents, size, false);
+ return contents;
+ }
+ // Content.
+ const QString className = item->data(0, ClassNameRole).toString();
+ QString contents = qdesigner_internal::WidgetDataBase::formTemplate(m_core, className, formName(className));
+ if (!size.isNull())
+ contents = qdesigner_internal::WidgetDataBase::scaleFormTemplate(contents, size, false);
+ return contents;
+}
+
+void NewFormWidget::slotDeviceProfileIndexChanged(int idx)
+{
+ // Store index for form windows to take effect and refresh pixmap
+ QDesignerSharedSettings settings(m_core);
+ settings.setCurrentDeviceProfileIndex(idx - profileComboIndexOffset);
+ showCurrentItemPixmap();
+}
+
+int NewFormWidget::profileComboIndex() const
+{
+ return m_ui->profileComboBox->currentIndex();
+}
+
+qdesigner_internal::DeviceProfile NewFormWidget::currentDeviceProfile() const
+{
+ const int ci = profileComboIndex();
+ if (ci > 0)
+ return m_deviceProfiles.at(ci - profileComboIndexOffset);
+ return qdesigner_internal::DeviceProfile();
+}
+
+bool NewFormWidget::hasCurrentTemplate() const
+{
+ return m_currentItem != 0;
+}
+
+QString NewFormWidget::currentTemplateI(QString *ptrToErrorMessage)
+{
+ if (m_currentItem == 0) {
+ *ptrToErrorMessage = tr("Internal error: No template selected.");
+ return QString();
+ }
+ const QString contents = itemToTemplate(m_currentItem, ptrToErrorMessage);
+ if (contents.isEmpty())
+ return contents;
+
+ m_acceptedItem = m_currentItem;
+ return contents;
+}
+
+QString NewFormWidget::currentTemplate(QString *ptrToErrorMessage)
+{
+ if (ptrToErrorMessage)
+ return currentTemplateI(ptrToErrorMessage);
+ // Do not loose the error
+ QString errorMessage;
+ const QString contents = currentTemplateI(&errorMessage);
+ if (!errorMessage.isEmpty())
+ qWarning("%s", errorMessage.toUtf8().constData());
+ return contents;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/newformwidget.ui b/tools/designer/src/lib/shared/newformwidget.ui
new file mode 100644
index 0000000000..c062602366
--- /dev/null
+++ b/tools/designer/src/lib/shared/newformwidget.ui
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::NewFormWidget</class>
+ <widget class="QWidget" name="qdesigner_internal::NewFormWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>480</width>
+ <height>194</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>1</number>
+ </property>
+ <item>
+ <widget class="QTreeWidget" name="treeWidget">
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>128</width>
+ <height>128</height>
+ </size>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="columnCount">
+ <number>1</number>
+ </property>
+ <column>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="lblPreview">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="text">
+ <string>Choose a template for a preview</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="margin">
+ <number>5</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>7</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="embeddedGroup">
+ <property name="title">
+ <string>Embedded Design</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QComboBox" name="profileComboBox"/>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="sizeComboBox"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Device:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Screen Size:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/lib/shared/newformwidget_p.h b/tools/designer/src/lib/shared/newformwidget_p.h
new file mode 100644
index 0000000000..f94f952b12
--- /dev/null
+++ b/tools/designer/src/lib/shared/newformwidget_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NEWFORMWIDGET_H
+#define NEWFORMWIDGET_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "shared_global_p.h"
+#include "deviceprofile_p.h"
+
+#include <abstractnewformwidget_p.h>
+
+#include <QtGui/QWidget>
+#include <QtGui/QPixmap>
+
+#include <QtCore/QStringList>
+#include <QtCore/QPair>
+#include <QtCore/QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+class QTreeWidgetItem;
+
+namespace qdesigner_internal {
+
+namespace Ui {
+ class NewFormWidget;
+}
+
+class QDesignerWorkbench;
+
+class QDESIGNER_SHARED_EXPORT NewFormWidget : public QDesignerNewFormWidgetInterface
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(NewFormWidget)
+
+public:
+ typedef QList<qdesigner_internal::DeviceProfile> DeviceProfileList;
+
+ explicit NewFormWidget(QDesignerFormEditorInterface *core, QWidget *parentWidget);
+ virtual ~NewFormWidget();
+
+ virtual bool hasCurrentTemplate() const;
+ virtual QString currentTemplate(QString *errorMessage = 0);
+
+ // Convenience for implementing file dialogs with preview
+ static QImage grabForm(QDesignerFormEditorInterface *core,
+ QIODevice &file,
+ const QString &workingDir,
+ const qdesigner_internal::DeviceProfile &dp);
+
+private slots:
+ void on_treeWidget_itemActivated(QTreeWidgetItem *item);
+ void on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *);
+ void on_treeWidget_itemPressed(QTreeWidgetItem *item);
+ void slotDeviceProfileIndexChanged(int idx);
+
+private:
+ QPixmap formPreviewPixmap(const QString &fileName) const;
+ QPixmap formPreviewPixmap(QIODevice &file, const QString &workingDir = QString()) const;
+ QPixmap formPreviewPixmap(const QTreeWidgetItem *item);
+
+ void loadFrom(const QString &path, bool resourceFile, const QString &uiExtension,
+ const QString &selectedItem, QTreeWidgetItem *&selectedItemFound);
+ void loadFrom(const QString &title, const QStringList &nameList,
+ const QString &selectedItem, QTreeWidgetItem *&selectedItemFound);
+
+private:
+ QString itemToTemplate(const QTreeWidgetItem *item, QString *errorMessage) const;
+ QString currentTemplateI(QString *ptrToErrorMessage);
+
+ QSize templateSize() const;
+ void setTemplateSize(const QSize &s);
+ int profileComboIndex() const;
+ qdesigner_internal::DeviceProfile currentDeviceProfile() const;
+ bool showCurrentItemPixmap();
+
+ // Pixmap cache (item, profile combo index)
+ typedef QPair<const QTreeWidgetItem *, int> ItemPixmapCacheKey;
+ typedef QMap<ItemPixmapCacheKey, QPixmap> ItemPixmapCache;
+ ItemPixmapCache m_itemPixmapCache;
+
+ QDesignerFormEditorInterface *m_core;
+ Ui::NewFormWidget *m_ui;
+ QTreeWidgetItem *m_currentItem;
+ QTreeWidgetItem *m_acceptedItem;
+ DeviceProfileList m_deviceProfiles;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // NEWFORMWIDGET_H
diff --git a/tools/designer/src/lib/shared/orderdialog.cpp b/tools/designer/src/lib/shared/orderdialog.cpp
new file mode 100644
index 0000000000..3f14ca6701
--- /dev/null
+++ b/tools/designer/src/lib/shared/orderdialog.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::OrderDialog
+*/
+
+#include "orderdialog_p.h"
+#include "iconloader_p.h"
+#include "ui_orderdialog.h"
+
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QModelIndex>
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+// OrderDialog: Used to reorder the pages of QStackedWidget and QToolBox.
+// Provides up and down buttons as well as DnD via QAbstractItemView::InternalMove mode
+namespace qdesigner_internal {
+
+OrderDialog::OrderDialog(QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::OrderDialog),
+ m_format(PageOrderFormat)
+{
+ m_ui->setupUi(this);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ m_ui->upButton->setIcon(createIconSet(QString::fromUtf8("up.png")));
+ m_ui->downButton->setIcon(createIconSet(QString::fromUtf8("down.png")));
+ m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
+ connect(m_ui->buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()), this, SLOT(slotReset()));
+ // Catch the remove operation of a DnD operation in QAbstractItemView::InternalMove mode to enable buttons
+ // Selection mode is 'contiguous' to enable DnD of groups
+ connect(m_ui->pageList->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(slotEnableButtonsAfterDnD()));
+
+ m_ui->upButton->setEnabled(false);
+ m_ui->downButton->setEnabled(false);
+}
+
+OrderDialog::~OrderDialog()
+{
+ delete m_ui;
+}
+
+void OrderDialog::setDescription(const QString &d)
+{
+ m_ui->groupBox->setTitle(d);
+}
+
+void OrderDialog::setPageList(const QWidgetList &pages)
+{
+ // The QWidget* are stored in a map indexed by the old index.
+ // The old index is set as user data on the item instead of the QWidget*
+ // because DnD is enabled which requires the user data to serializable
+ m_orderMap.clear();
+ const int count = pages.count();
+ for (int i=0; i < count; ++i)
+ m_orderMap.insert(i, pages.at(i));
+ buildList();
+}
+
+void OrderDialog::buildList()
+{
+ m_ui->pageList->clear();
+ const OrderMap::const_iterator cend = m_orderMap.constEnd();
+ for (OrderMap::const_iterator it = m_orderMap.constBegin(); it != cend; ++it) {
+ QListWidgetItem *item = new QListWidgetItem();
+ const int index = it.key();
+ switch (m_format) {
+ case PageOrderFormat:
+ item->setText(tr("Index %1 (%2)").arg(index).arg(it.value()->objectName()));
+ break;
+ case TabOrderFormat:
+ item->setText(tr("%1 %2").arg(index+1).arg(it.value()->objectName()));
+ break;
+ }
+ item->setData(Qt::UserRole, QVariant(index));
+ m_ui->pageList->addItem(item);
+ }
+
+ if (m_ui->pageList->count() > 0)
+ m_ui->pageList->setCurrentRow(0);
+}
+
+void OrderDialog::slotReset()
+{
+ buildList();
+}
+
+QWidgetList OrderDialog::pageList() const
+{
+ QWidgetList rc;
+ const int count = m_ui->pageList->count();
+ for (int i=0; i < count; ++i) {
+ const int oldIndex = m_ui->pageList->item(i)->data(Qt::UserRole).toInt();
+ rc.append(m_orderMap.value(oldIndex));
+ }
+ return rc;
+}
+
+void OrderDialog::on_upButton_clicked()
+{
+ const int row = m_ui->pageList->currentRow();
+ if (row <= 0)
+ return;
+
+ m_ui->pageList->insertItem(row - 1, m_ui->pageList->takeItem(row));
+ m_ui->pageList->setCurrentRow(row - 1);
+}
+
+void OrderDialog::on_downButton_clicked()
+{
+ const int row = m_ui->pageList->currentRow();
+ if (row == -1 || row == m_ui->pageList->count() - 1)
+ return;
+
+ m_ui->pageList->insertItem(row + 1, m_ui->pageList->takeItem(row));
+ m_ui->pageList->setCurrentRow(row + 1);
+}
+
+void OrderDialog::slotEnableButtonsAfterDnD()
+{
+ enableButtons(m_ui->pageList->currentRow());
+}
+
+void OrderDialog::on_pageList_currentRowChanged(int r)
+{
+ enableButtons(r);
+}
+
+void OrderDialog::enableButtons(int r)
+{
+ m_ui->upButton->setEnabled(r > 0);
+ m_ui->downButton->setEnabled(r >= 0 && r < m_ui->pageList->count() - 1);
+}
+
+QWidgetList OrderDialog::pagesOfContainer(const QDesignerFormEditorInterface *core, QWidget *container)
+{
+ QWidgetList rc;
+ if (QDesignerContainerExtension* ce = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), container)) {
+ const int count = ce->count();
+ for (int i = 0; i < count ;i ++)
+ rc.push_back(ce->widget(i));
+ }
+ return rc;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/orderdialog.ui b/tools/designer/src/lib/shared/orderdialog.ui
new file mode 100644
index 0000000000..dcecb31dab
--- /dev/null
+++ b/tools/designer/src/lib/shared/orderdialog.ui
@@ -0,0 +1,198 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>qdesigner_internal::OrderDialog</class>
+ <widget class="QDialog" name="qdesigner_internal::OrderDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>467</width>
+ <height>310</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Change Page Order</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Page Order</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>9</number>
+ </property>
+ <property name="topMargin" >
+ <number>9</number>
+ </property>
+ <property name="rightMargin" >
+ <number>9</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>9</number>
+ </property>
+ <item>
+ <widget class="QListWidget" name="pageList" >
+ <property name="minimumSize" >
+ <size>
+ <width>344</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="dragDropMode" >
+ <enum>QAbstractItemView::InternalMove</enum>
+ </property>
+ <property name="selectionMode" >
+ <enum>QAbstractItemView::ContiguousSelection</enum>
+ </property>
+ <property name="movement" >
+ <enum>QListView::Snap</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="upButton" >
+ <property name="toolTip" >
+ <string>Move page up</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="downButton" >
+ <property name="toolTip" >
+ <string>Move page down</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>99</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>qdesigner_internal::OrderDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>50</x>
+ <y>163</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>6</x>
+ <y>151</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>qdesigner_internal::OrderDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>300</x>
+ <y>160</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>348</x>
+ <y>148</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/orderdialog_p.h b/tools/designer/src/lib/shared/orderdialog_p.h
new file mode 100644
index 0000000000..e8897e6270
--- /dev/null
+++ b/tools/designer/src/lib/shared/orderdialog_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ORDERDIALOG_P_H
+#define ORDERDIALOG_P_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QDialog>
+#include <QtCore/QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+namespace Ui {
+ class OrderDialog;
+}
+
+class QDESIGNER_SHARED_EXPORT OrderDialog: public QDialog
+{
+ Q_OBJECT
+public:
+ OrderDialog(QWidget *parent);
+ virtual ~OrderDialog();
+
+ static QWidgetList pagesOfContainer(const QDesignerFormEditorInterface *core, QWidget *container);
+
+ void setPageList(const QWidgetList &pages);
+ QWidgetList pageList() const;
+
+ void setDescription(const QString &d);
+
+ enum Format { // Display format
+ PageOrderFormat, // Container pages, ranging 0..[n-1]
+ TabOrderFormat // List of widgets, ranging 1..1
+ };
+
+ void setFormat(Format f) { m_format = f; }
+ Format format() const { return m_format; }
+
+private slots:
+ void on_upButton_clicked();
+ void on_downButton_clicked();
+ void on_pageList_currentRowChanged(int row);
+ void slotEnableButtonsAfterDnD();
+ void slotReset();
+
+private:
+ void buildList();
+ void enableButtons(int r);
+
+ typedef QMap<int, QWidget*> OrderMap;
+ OrderMap m_orderMap;
+ Ui::OrderDialog* m_ui;
+ Format m_format;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // ORDERDIALOG_P_H
diff --git a/tools/designer/src/lib/shared/plaintexteditor.cpp b/tools/designer/src/lib/shared/plaintexteditor.cpp
new file mode 100644
index 0000000000..ce5cd5bd11
--- /dev/null
+++ b/tools/designer/src/lib/shared/plaintexteditor.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::PlainTextEditorDialog
+*/
+
+#include "plaintexteditor_p.h"
+#include "abstractsettings_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+static const char *PlainTextDialogC = "PlainTextDialog";
+static const char *Geometry = "Geometry";
+
+
+namespace qdesigner_internal {
+
+PlainTextEditorDialog::PlainTextEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QDialog(parent),
+ m_editor(new QPlainTextEdit),
+ m_core(core)
+{
+ setWindowTitle(tr("Edit text"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QVBoxLayout *vlayout = new QVBoxLayout(this);
+ vlayout->addWidget(m_editor);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
+ QPushButton *ok_button = buttonBox->button(QDialogButtonBox::Ok);
+ ok_button->setDefault(true);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ vlayout->addWidget(buttonBox);
+
+ QDesignerSettingsInterface *settings = core->settingsManager();
+ settings->beginGroup(QLatin1String(PlainTextDialogC));
+
+ if (settings->contains(QLatin1String(Geometry)))
+ restoreGeometry(settings->value(QLatin1String(Geometry)).toByteArray());
+
+ settings->endGroup();
+}
+
+PlainTextEditorDialog::~PlainTextEditorDialog()
+{
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(PlainTextDialogC));
+
+ settings->setValue(QLatin1String(Geometry), saveGeometry());
+ settings->endGroup();
+}
+
+int PlainTextEditorDialog::showDialog()
+{
+ m_editor->setFocus();
+ return exec();
+}
+
+void PlainTextEditorDialog::setDefaultFont(const QFont &font)
+{
+ m_editor->setFont(font);
+}
+
+void PlainTextEditorDialog::setText(const QString &text)
+{
+ m_editor->setPlainText(text);
+}
+
+QString PlainTextEditorDialog::text() const
+{
+ return m_editor->toPlainText();
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/plaintexteditor_p.h b/tools/designer/src/lib/shared/plaintexteditor_p.h
new file mode 100644
index 0000000000..d227db8baf
--- /dev/null
+++ b/tools/designer/src/lib/shared/plaintexteditor_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PLAINTEXTEDITOR_H
+#define PLAINTEXTEDITOR_H
+
+#include <QtGui/QDialog>
+#include "shared_global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPlainTextEdit;
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT PlainTextEditorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit PlainTextEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ ~PlainTextEditorDialog();
+
+ int showDialog();
+
+ void setDefaultFont(const QFont &font);
+
+ void setText(const QString &text);
+ QString text() const;
+
+private:
+ QPlainTextEdit *m_editor;
+ QDesignerFormEditorInterface *m_core;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // RITCHTEXTEDITOR_H
diff --git a/tools/designer/src/lib/shared/plugindialog.cpp b/tools/designer/src/lib/shared/plugindialog.cpp
new file mode 100644
index 0000000000..447f1e23cb
--- /dev/null
+++ b/tools/designer/src/lib/shared/plugindialog.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "plugindialog_p.h"
+#include "pluginmanager_p.h"
+#include "qdesigner_integration_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerCustomWidgetCollectionInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtGui/QStyle>
+#include <QtGui/QHeaderView>
+#include <QtGui/QPushButton>
+#include <QtCore/QFileInfo>
+#include <QtCore/QPluginLoader>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+PluginDialog::PluginDialog(QDesignerFormEditorInterface *core, QWidget *parent)
+ : QDialog(parent
+#ifdef Q_WS_MAC
+ , Qt::Tool
+#endif
+ ), m_core(core)
+{
+ ui.setupUi(this);
+
+ ui.message->hide();
+
+ const QStringList headerLabels(tr("Components"));
+
+ ui.treeWidget->setAlternatingRowColors(false);
+ ui.treeWidget->setSelectionMode(QAbstractItemView::NoSelection);
+ ui.treeWidget->setHeaderLabels(headerLabels);
+ ui.treeWidget->header()->hide();
+
+ interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon),
+ QIcon::Normal, QIcon::On);
+ interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
+ QIcon::Normal, QIcon::Off);
+ featureIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
+
+ setWindowTitle(tr("Plugin Information"));
+ populateTreeWidget();
+
+ if (qobject_cast<qdesigner_internal::QDesignerIntegration *>(m_core->integration())) {
+ QPushButton *updateButton = new QPushButton(tr("Refresh"));
+ const QString tooltip = tr("Scan for newly installed custom widget plugins.");
+ updateButton->setToolTip(tooltip);
+ updateButton->setWhatsThis(tooltip);
+ connect(updateButton, SIGNAL(clicked()), this, SLOT(updateCustomWidgetPlugins()));
+ ui.buttonBox->addButton(updateButton, QDialogButtonBox::ActionRole);
+ }
+}
+
+void PluginDialog::populateTreeWidget()
+{
+ ui.treeWidget->clear();
+ QDesignerPluginManager *pluginManager = m_core->pluginManager();
+ const QStringList fileNames = pluginManager->registeredPlugins();
+
+ if (!fileNames.isEmpty()) {
+ QTreeWidgetItem *topLevelItem = setTopLevelItem(QLatin1String("Loaded Plugins"));
+ QFont boldFont = topLevelItem->font(0);
+
+ foreach (QString fileName, fileNames) {
+ QPluginLoader loader(fileName);
+ const QFileInfo fileInfo(fileName);
+
+ QTreeWidgetItem *pluginItem = setPluginItem(topLevelItem, fileInfo.fileName(), boldFont);
+
+ if (QObject *plugin = loader.instance()) {
+ if (const QDesignerCustomWidgetCollectionInterface *c = qobject_cast<QDesignerCustomWidgetCollectionInterface*>(plugin)) {
+ foreach (const QDesignerCustomWidgetInterface *p, c->customWidgets())
+ setItem(pluginItem, p->name(), p->toolTip(), p->whatsThis(), p->icon());
+ } else {
+ if (const QDesignerCustomWidgetInterface *p = qobject_cast<QDesignerCustomWidgetInterface*>(plugin))
+ setItem(pluginItem, p->name(), p->toolTip(), p->whatsThis(), p->icon());
+ }
+ }
+ }
+ }
+
+ const QStringList notLoadedPlugins = pluginManager->failedPlugins();
+ if (!notLoadedPlugins.isEmpty()) {
+ QTreeWidgetItem *topLevelItem = setTopLevelItem(QLatin1String("Failed Plugins"));
+ const QFont boldFont = topLevelItem->font(0);
+ foreach (const QString plugin, notLoadedPlugins) {
+ const QString failureReason = pluginManager->failureReason(plugin);
+ QTreeWidgetItem *pluginItem = setPluginItem(topLevelItem, plugin, boldFont);
+ setItem(pluginItem, failureReason, failureReason, QString(), QIcon());
+ }
+ }
+
+ if (ui.treeWidget->topLevelItemCount() == 0) {
+ ui.label->setText(tr("Qt Designer couldn't find any plugins"));
+ ui.treeWidget->hide();
+ } else {
+ ui.label->setText(tr("Qt Designer found the following plugins"));
+ }
+}
+
+QIcon PluginDialog::pluginIcon(const QIcon &icon)
+{
+ if (icon.isNull())
+ return QIcon(QLatin1String(":/trolltech/formeditor/images/qtlogo.png"));
+
+ return icon;
+}
+
+QTreeWidgetItem* PluginDialog::setTopLevelItem(const QString &itemName)
+{
+ QTreeWidgetItem *topLevelItem = new QTreeWidgetItem(ui.treeWidget);
+ topLevelItem->setText(0, itemName);
+ ui.treeWidget->setItemExpanded(topLevelItem, true);
+ topLevelItem->setIcon(0, style()->standardPixmap(QStyle::SP_DirOpenIcon));
+
+ QFont boldFont = topLevelItem->font(0);
+ boldFont.setBold(true);
+ topLevelItem->setFont(0, boldFont);
+
+ return topLevelItem;
+}
+
+QTreeWidgetItem* PluginDialog::setPluginItem(QTreeWidgetItem *topLevelItem,
+ const QString &itemName, const QFont &font)
+{
+ QTreeWidgetItem *pluginItem = new QTreeWidgetItem(topLevelItem);
+ pluginItem->setFont(0, font);
+ pluginItem->setText(0, itemName);
+ ui.treeWidget->setItemExpanded(pluginItem, true);
+ pluginItem->setIcon(0, style()->standardPixmap(QStyle::SP_DirOpenIcon));
+
+ return pluginItem;
+}
+
+void PluginDialog::setItem(QTreeWidgetItem *pluginItem, const QString &name,
+ const QString &toolTip, const QString &whatsThis, const QIcon &icon)
+{
+ QTreeWidgetItem *item = new QTreeWidgetItem(pluginItem);
+ item->setText(0, name);
+ item->setToolTip(0, toolTip);
+ item->setWhatsThis(0, whatsThis);
+ item->setIcon(0, pluginIcon(icon));
+}
+
+void PluginDialog::updateCustomWidgetPlugins()
+{
+ if (qdesigner_internal::QDesignerIntegration *integration = qobject_cast<qdesigner_internal::QDesignerIntegration *>(m_core->integration())) {
+ const int before = m_core->widgetDataBase()->count();
+ integration->updateCustomWidgetPlugins();
+ const int after = m_core->widgetDataBase()->count();
+ if (after > before) {
+ ui.message->setText(tr("New custom widget plugins have been found."));
+ ui.message->show();
+ } else {
+ ui.message->setText(QString());
+ }
+ populateTreeWidget();
+ }
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/plugindialog.ui b/tools/designer/src/lib/shared/plugindialog.ui
new file mode 100644
index 0000000000..b12a42d41c
--- /dev/null
+++ b/tools/designer/src/lib/shared/plugindialog.ui
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>PluginDialog</class>
+ <widget class="QDialog" name="PluginDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>401</width>
+ <height>331</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Plugin Information</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string notr="true">TextLabel</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTreeWidget" name="treeWidget">
+ <property name="textElideMode">
+ <enum>Qt::ElideNone</enum>
+ </property>
+ <column>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="message">
+ <property name="text">
+ <string notr="true">TextLabel</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>PluginDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>154</x>
+ <y>307</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>401</x>
+ <y>280</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/plugindialog_p.h b/tools/designer/src/lib/shared/plugindialog_p.h
new file mode 100644
index 0000000000..d50a804cd5
--- /dev/null
+++ b/tools/designer/src/lib/shared/plugindialog_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PLUGINDIALOG_H
+#define PLUGINDIALOG_H
+
+#include "ui_plugindialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class PluginDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit PluginDialog(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+
+private slots:
+ void updateCustomWidgetPlugins();
+
+private:
+ void populateTreeWidget();
+ QIcon pluginIcon(const QIcon &icon);
+ QTreeWidgetItem* setTopLevelItem(const QString &itemName);
+ QTreeWidgetItem* setPluginItem(QTreeWidgetItem *topLevelItem,
+ const QString &itemName, const QFont &font);
+ void setItem(QTreeWidgetItem *pluginItem, const QString &name,
+ const QString &toolTip, const QString &whatsThis, const QIcon &icon);
+
+ QDesignerFormEditorInterface *m_core;
+ Ui::PluginDialog ui;
+ QIcon interfaceIcon;
+ QIcon featureIcon;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/pluginmanager.cpp b/tools/designer/src/lib/shared/pluginmanager.cpp
new file mode 100644
index 0000000000..9dc8c7b81e
--- /dev/null
+++ b/tools/designer/src/lib/shared/pluginmanager.cpp
@@ -0,0 +1,670 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pluginmanager_p.h"
+#include "qdesigner_utils_p.h"
+#include "qdesigner_qsettings_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerLanguageExtension>
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QSet>
+#include <QtCore/QPluginLoader>
+#include <QtCore/QLibrary>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/qdebug.h>
+#include <QtCore/QMap>
+#include <QtCore/QSettings>
+#include <QtCore/QCoreApplication>
+
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QXmlStreamAttributes>
+#include <QtCore/QXmlStreamAttribute>
+
+static const char *uiElementC = "ui";
+static const char *languageAttributeC = "language";
+static const char *widgetElementC = "widget";
+static const char *displayNameAttributeC = "displayname";
+static const char *classAttributeC = "class";
+static const char *customwidgetElementC = "customwidget";
+static const char *extendsElementC = "extends";
+static const char *addPageMethodC = "addpagemethod";
+static const char *jambiLanguageC = "jambi";
+
+enum { debugPluginManager = 0 };
+
+/* Custom widgets: Loading custom widgets is a 2-step process: PluginManager
+ * scans for its plugins in the constructor. At this point, it might not be safe
+ * to immediately initialize the custom widgets it finds, because the rest of
+ * Designer is not initialized yet.
+ * Later on, in ensureInitialized(), the plugin instances (including static ones)
+ * are iterated and the custom widget plugins are initialized and added to internal
+ * list of custom widgets and parsed data. Should there be a parse error or a language
+ * mismatch, it kicks out the respective custom widget. The m_initialized flag
+ * is used to indicate the state.
+ * Later, someone might call registerNewPlugins(), which agains clears the flag via
+ * registerPlugin() and triggers the process again.
+ * Also note that Jambi fakes a custom widget collection that changes its contents
+ * every time the project is switched. So, custom widget plugins can actually
+ * disappear, and the custom widget list must be cleared and refilled in
+ * ensureInitialized() after registerNewPlugins. */
+
+QT_BEGIN_NAMESPACE
+
+static QStringList unique(const QStringList &lst)
+{
+ const QSet<QString> s = QSet<QString>::fromList(lst);
+ return s.toList();
+}
+
+QStringList QDesignerPluginManager::defaultPluginPaths()
+{
+ QStringList result;
+
+ const QStringList path_list = QCoreApplication::libraryPaths();
+
+ const QString designer = QLatin1String("designer");
+ foreach (const QString &path, path_list) {
+ QString libPath = path;
+ libPath += QDir::separator();
+ libPath += designer;
+ result.append(libPath);
+ }
+
+ QString homeLibPath = QDir::homePath();
+ homeLibPath += QDir::separator();
+ homeLibPath += QLatin1String(".designer");
+ homeLibPath += QDir::separator();
+ homeLibPath += QLatin1String("plugins");
+
+ result.append(homeLibPath);
+ return result;
+}
+
+// Figure out the language designer is running. ToDo: Introduce some
+// Language name API to QDesignerLanguageExtension?
+
+static inline QString getDesignerLanguage(QDesignerFormEditorInterface *core)
+{
+ if (QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core)) {
+ if (lang->uiExtension() == QLatin1String("jui"))
+ return QLatin1String(jambiLanguageC);
+ return QLatin1String("unknown");
+ }
+ return QLatin1String("c++");
+}
+
+// ---------------- QDesignerCustomWidgetSharedData
+
+class QDesignerCustomWidgetSharedData : public QSharedData {
+public:
+ explicit QDesignerCustomWidgetSharedData(const QString &thePluginPath) : pluginPath(thePluginPath) {}
+ void clearXML();
+
+ QString pluginPath;
+
+ QString xmlClassName;
+ QString xmlDisplayName;
+ QString xmlLanguage;
+ QString xmlAddPageMethod;
+ QString xmlExtends;
+
+};
+
+void QDesignerCustomWidgetSharedData::clearXML()
+{
+ xmlClassName.clear();
+ xmlDisplayName.clear();
+ xmlLanguage.clear();
+ xmlAddPageMethod.clear();
+ xmlExtends.clear();
+}
+
+// ---------------- QDesignerCustomWidgetData
+
+QDesignerCustomWidgetData::QDesignerCustomWidgetData(const QString &pluginPath) :
+ m_d(new QDesignerCustomWidgetSharedData(pluginPath))
+{
+}
+
+QDesignerCustomWidgetData::QDesignerCustomWidgetData(const QDesignerCustomWidgetData &o) :
+ m_d(o.m_d)
+{
+}
+
+QDesignerCustomWidgetData& QDesignerCustomWidgetData::operator=(const QDesignerCustomWidgetData &o)
+{
+ m_d.operator=(o.m_d);
+ return *this;
+}
+
+QDesignerCustomWidgetData::~QDesignerCustomWidgetData()
+{
+}
+
+bool QDesignerCustomWidgetData::isNull() const
+{
+ return m_d->xmlClassName.isEmpty() || m_d->pluginPath.isEmpty();
+}
+
+QString QDesignerCustomWidgetData::xmlClassName() const
+{
+ return m_d->xmlClassName;
+}
+
+QString QDesignerCustomWidgetData::xmlLanguage() const
+{
+ return m_d->xmlLanguage;
+}
+
+QString QDesignerCustomWidgetData::xmlAddPageMethod() const
+{
+ return m_d->xmlAddPageMethod;
+}
+
+QString QDesignerCustomWidgetData::xmlExtends() const
+{
+ return m_d->xmlExtends;
+}
+
+QString QDesignerCustomWidgetData::xmlDisplayName() const
+{
+ return m_d->xmlDisplayName;
+}
+
+QString QDesignerCustomWidgetData::pluginPath() const
+{
+ return m_d->pluginPath;
+}
+
+// Wind a QXmlStreamReader until it finds an element. Returns index or one of FindResult
+enum FindResult { FindError = -2, ElementNotFound = -1 };
+
+static int findElement(const QStringList &desiredElts, QXmlStreamReader &sr)
+{
+ while (true) {
+ switch(sr.readNext()) {
+ case QXmlStreamReader::EndDocument:
+ return ElementNotFound;
+ case QXmlStreamReader::Invalid:
+ return FindError;
+ case QXmlStreamReader::StartElement: {
+ const int index = desiredElts.indexOf(sr.name().toString().toLower());
+ if (index >= 0)
+ return index;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return FindError;
+}
+
+static inline QString msgXmlError(const QString &name, const QString &errorMessage)
+{
+ return QDesignerPluginManager::tr("An XML error was encountered when parsing the XML of the custom widget %1: %2").arg(name, errorMessage);
+}
+
+QDesignerCustomWidgetData::ParseResult
+ QDesignerCustomWidgetData::parseXml(const QString &xml, const QString &name, QString *errorMessage)
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO << name;
+
+ QDesignerCustomWidgetSharedData &data = *m_d;
+ data.clearXML();
+
+ QXmlStreamReader sr(xml);
+
+ bool foundUI = false;
+ bool foundWidget = false;
+ ParseResult rc = ParseOk;
+ // Parse for the (optional) <ui> or the first <widget> element
+ QStringList elements;
+ elements.push_back(QLatin1String(uiElementC));
+ elements.push_back(QLatin1String(widgetElementC));
+ for (int i = 0; i < 2 && !foundWidget; i++) {
+ switch (findElement(elements, sr)) {
+ case FindError:
+ *errorMessage = msgXmlError(name, sr.errorString());
+ return ParseError;
+ case ElementNotFound:
+ *errorMessage = QDesignerPluginManager::tr("The XML of the custom widget %1 does not contain any of the elements <widget> or <ui>.").arg(name);
+ return ParseError;
+ case 0: { // <ui>
+ const QXmlStreamAttributes attributes = sr.attributes();
+ data.xmlLanguage = attributes.value(QLatin1String(languageAttributeC)).toString();
+ data.xmlDisplayName = attributes.value(QLatin1String(displayNameAttributeC)).toString();
+ foundUI = true;
+ }
+ break;
+ case 1: // <widget>: Do some sanity checks
+ data.xmlClassName = sr.attributes().value(QLatin1String(classAttributeC)).toString();
+ if (data.xmlClassName.isEmpty()) {
+ *errorMessage = QDesignerPluginManager::tr("The class attribute for the class %1 is missing.").arg(name);
+ rc = ParseWarning;
+ } else {
+ if (data.xmlClassName != name) {
+ *errorMessage = QDesignerPluginManager::tr("The class attribute for the class %1 does not match the class name %2.").arg(data.xmlClassName, name);
+ rc = ParseWarning;
+ }
+ }
+ foundWidget = true;
+ break;
+ }
+ }
+ // Parse out the <customwidget> element which might be present if <ui> was there
+ if (!foundUI)
+ return rc;
+ elements.clear();
+ elements.push_back(QLatin1String(customwidgetElementC));
+ switch (findElement(elements, sr)) {
+ case FindError:
+ *errorMessage = msgXmlError(name, sr.errorString());
+ return ParseError;
+ case ElementNotFound:
+ return rc;
+ default:
+ break;
+ }
+ // Find <extends>, <addPageMethod>
+ elements.clear();
+ elements.push_back(QLatin1String(extendsElementC));
+ elements.push_back(QLatin1String(addPageMethodC));
+ while (true) {
+ switch (findElement(elements, sr)) {
+ case FindError:
+ *errorMessage = msgXmlError(name, sr.errorString());
+ return ParseError;
+ case ElementNotFound:
+ return rc;
+ case 0: // <extends>
+ data.xmlExtends = sr.readElementText();
+ if (sr.tokenType() != QXmlStreamReader::EndElement) {
+ *errorMessage = msgXmlError(name, sr.errorString());
+ return ParseError;
+ }
+ break;
+ case 1: // <addPageMethod>
+ data.xmlAddPageMethod = sr.readElementText();
+ if (sr.tokenType() != QXmlStreamReader::EndElement) {
+ *errorMessage = msgXmlError(name, sr.errorString());
+ return ParseError;
+ }
+ break;
+ }
+ }
+ return rc;
+}
+
+// ---------------- QDesignerPluginManagerPrivate
+
+class QDesignerPluginManagerPrivate {
+ public:
+ QDesignerPluginManagerPrivate(QDesignerFormEditorInterface *core);
+
+ void clearCustomWidgets();
+ bool addCustomWidget(QDesignerCustomWidgetInterface *c,
+ const QString &pluginPath,
+ const QString &designerLanguage);
+ void addCustomWidgets(const QObject *o,
+ const QString &pluginPath,
+ const QString &designerLanguage);
+
+ QDesignerFormEditorInterface *m_core;
+ QStringList m_pluginPaths;
+ QStringList m_registeredPlugins;
+ // TODO: QPluginLoader also caches invalid plugins -> This seems to be dead code
+ QStringList m_disabledPlugins;
+
+ typedef QMap<QString, QString> FailedPluginMap;
+ FailedPluginMap m_failedPlugins;
+
+ // Synced lists of custom widgets and their data. Note that the list
+ // must be ordered for collections to appear in order.
+ QList<QDesignerCustomWidgetInterface *> m_customWidgets;
+ QList<QDesignerCustomWidgetData> m_customWidgetData;
+
+ QStringList defaultPluginPaths() const;
+
+ bool m_initialized;
+};
+
+QDesignerPluginManagerPrivate::QDesignerPluginManagerPrivate(QDesignerFormEditorInterface *core) :
+ m_core(core),
+ m_initialized(false)
+{
+}
+
+void QDesignerPluginManagerPrivate::clearCustomWidgets()
+{
+ m_customWidgets.clear();
+ m_customWidgetData.clear();
+}
+
+// Add a custom widget to the list if it parses correctly
+// and is of the right language
+bool QDesignerPluginManagerPrivate::addCustomWidget(QDesignerCustomWidgetInterface *c,
+ const QString &pluginPath,
+ const QString &designerLanguage)
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO << c->name();
+
+ if (!c->isInitialized())
+ c->initialize(m_core);
+ // Parse the XML even if the plugin is initialized as Jambi might play tricks here
+ QDesignerCustomWidgetData data(pluginPath);
+ const QString domXml = c->domXml();
+ if (!domXml.isEmpty()) { // Legacy: Empty XML means: Do not show up in widget box.
+ QString errorMessage;
+ const QDesignerCustomWidgetData::ParseResult pr = data.parseXml(domXml, c->name(), &errorMessage);
+ switch (pr) {
+ case QDesignerCustomWidgetData::ParseOk:
+ break;
+ case QDesignerCustomWidgetData::ParseWarning:
+ qdesigner_internal::designerWarning(errorMessage);
+ break;
+ case QDesignerCustomWidgetData::ParseError:
+ qdesigner_internal::designerWarning(errorMessage);
+ return false;
+ }
+ // Does the language match?
+ const QString pluginLanguage = data.xmlLanguage();
+ if (!pluginLanguage.isEmpty() && pluginLanguage.compare(designerLanguage, Qt::CaseInsensitive))
+ return false;
+ }
+ m_customWidgets.push_back(c);
+ m_customWidgetData.push_back(data);
+ return true;
+}
+
+// Check the plugin interface for either a custom widget or a collection and
+// add all contained custom widgets.
+void QDesignerPluginManagerPrivate::addCustomWidgets(const QObject *o,
+ const QString &pluginPath,
+ const QString &designerLanguage)
+{
+ if (QDesignerCustomWidgetInterface *c = qobject_cast<QDesignerCustomWidgetInterface*>(o)) {
+ addCustomWidget(c, pluginPath, designerLanguage);
+ return;
+ }
+ if (const QDesignerCustomWidgetCollectionInterface *coll = qobject_cast<QDesignerCustomWidgetCollectionInterface*>(o)) {
+ foreach(QDesignerCustomWidgetInterface *c, coll->customWidgets())
+ addCustomWidget(c, pluginPath, designerLanguage);
+ }
+}
+
+
+// ---------------- QDesignerPluginManager
+// As of 4.4, the header will be distributed with the Eclipse plugin.
+
+QDesignerPluginManager::QDesignerPluginManager(QDesignerFormEditorInterface *core) :
+ QObject(core),
+ m_d(new QDesignerPluginManagerPrivate(core))
+{
+ m_d->m_pluginPaths = defaultPluginPaths();
+ const QSettings settings(qApp->organizationName(), QDesignerQSettings::settingsApplicationName());
+ m_d->m_disabledPlugins = unique(settings.value(QLatin1String("PluginManager/DisabledPlugins")).toStringList());
+
+ // Register plugins
+ updateRegisteredPlugins();
+
+ if (debugPluginManager)
+ qDebug() << "QDesignerPluginManager::disabled: " << m_d->m_disabledPlugins << " static " << m_d->m_customWidgets.size();
+}
+
+QDesignerPluginManager::~QDesignerPluginManager()
+{
+ syncSettings();
+ delete m_d;
+}
+
+QDesignerFormEditorInterface *QDesignerPluginManager::core() const
+{
+ return m_d->m_core;
+}
+
+QStringList QDesignerPluginManager::findPlugins(const QString &path)
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO << path;
+ const QDir dir(path);
+ if (!dir.exists())
+ return QStringList();
+
+ const QFileInfoList infoList = dir.entryInfoList(QDir::Files);
+ if (infoList.empty())
+ return QStringList();
+
+ // Load symbolic links but make sure all file names are unique as not
+ // to fall for something like 'libplugin.so.1 -> libplugin.so'
+ QStringList result;
+ const QFileInfoList::const_iterator icend = infoList.constEnd();
+ for (QFileInfoList::const_iterator it = infoList.constBegin(); it != icend; ++it) {
+ QString fileName;
+ if (it->isSymLink()) {
+ const QFileInfo linkTarget = QFileInfo(it->symLinkTarget());
+ if (linkTarget.exists() && linkTarget.isFile())
+ fileName = linkTarget.absoluteFilePath();
+ } else {
+ fileName = it->absoluteFilePath();
+ }
+ if (!fileName.isEmpty() && QLibrary::isLibrary(fileName) && !result.contains(fileName))
+ result += fileName;
+ }
+ return result;
+}
+
+void QDesignerPluginManager::setDisabledPlugins(const QStringList &disabled_plugins)
+{
+ m_d->m_disabledPlugins = disabled_plugins;
+ updateRegisteredPlugins();
+}
+
+void QDesignerPluginManager::setPluginPaths(const QStringList &plugin_paths)
+{
+ m_d->m_pluginPaths = plugin_paths;
+ updateRegisteredPlugins();
+}
+
+QStringList QDesignerPluginManager::disabledPlugins() const
+{
+ return m_d->m_disabledPlugins;
+}
+
+QStringList QDesignerPluginManager::failedPlugins() const
+{
+ return m_d->m_failedPlugins.keys();
+}
+
+QString QDesignerPluginManager::failureReason(const QString &pluginName) const
+{
+ return m_d->m_failedPlugins.value(pluginName);
+}
+
+QStringList QDesignerPluginManager::registeredPlugins() const
+{
+ return m_d->m_registeredPlugins;
+}
+
+QStringList QDesignerPluginManager::pluginPaths() const
+{
+ return m_d->m_pluginPaths;
+}
+
+QObject *QDesignerPluginManager::instance(const QString &plugin) const
+{
+ if (m_d->m_disabledPlugins.contains(plugin))
+ return 0;
+
+ QPluginLoader loader(plugin);
+ return loader.instance();
+}
+
+void QDesignerPluginManager::updateRegisteredPlugins()
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO;
+ m_d->m_registeredPlugins.clear();
+ foreach (const QString &path, m_d->m_pluginPaths)
+ registerPath(path);
+}
+
+bool QDesignerPluginManager::registerNewPlugins()
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO;
+
+ const int before = m_d->m_registeredPlugins.size();
+ foreach (const QString &path, m_d->m_pluginPaths)
+ registerPath(path);
+ const bool newPluginsFound = m_d->m_registeredPlugins.size() > before;
+ // We force a re-initialize as Jambi collection might return
+ // different widget lists when switching projects.
+ m_d->m_initialized = false;
+ ensureInitialized();
+
+ return newPluginsFound;
+}
+
+void QDesignerPluginManager::registerPath(const QString &path)
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO << path;
+ QStringList candidates = findPlugins(path);
+
+ foreach (const QString &plugin, candidates)
+ registerPlugin(plugin);
+}
+
+void QDesignerPluginManager::registerPlugin(const QString &plugin)
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO << plugin;
+ if (m_d->m_disabledPlugins.contains(plugin))
+ return;
+ if (m_d->m_registeredPlugins.contains(plugin))
+ return;
+
+ QPluginLoader loader(plugin);
+ if (loader.isLoaded() || loader.load()) {
+ m_d->m_registeredPlugins += plugin;
+ QDesignerPluginManagerPrivate::FailedPluginMap::iterator fit = m_d->m_failedPlugins.find(plugin);
+ if (fit != m_d->m_failedPlugins.end())
+ m_d->m_failedPlugins.erase(fit);
+ return;
+ }
+
+ const QString errorMessage = loader.errorString();
+ m_d->m_failedPlugins.insert(plugin, errorMessage);
+}
+
+
+
+bool QDesignerPluginManager::syncSettings()
+{
+ QSettings settings(qApp->organizationName(), QDesignerQSettings::settingsApplicationName());
+ settings.beginGroup(QLatin1String("PluginManager"));
+ settings.setValue(QLatin1String("DisabledPlugins"), m_d->m_disabledPlugins);
+ settings.endGroup();
+ return settings.status() == QSettings::NoError;
+}
+
+void QDesignerPluginManager::ensureInitialized()
+{
+ if (debugPluginManager)
+ qDebug() << Q_FUNC_INFO << m_d->m_initialized << m_d->m_customWidgets.size();
+
+ if (m_d->m_initialized)
+ return;
+
+ const QString designerLanguage = getDesignerLanguage(m_d->m_core);
+
+ m_d->clearCustomWidgets();
+ // Add the static custom widgets
+ const QObjectList staticPluginObjects = QPluginLoader::staticInstances();
+ if (!staticPluginObjects.empty()) {
+ const QString staticPluginPath = QCoreApplication::applicationFilePath();
+ foreach(QObject *o, staticPluginObjects)
+ m_d->addCustomWidgets(o, staticPluginPath, designerLanguage);
+ }
+ foreach (const QString &plugin, m_d->m_registeredPlugins)
+ if (QObject *o = instance(plugin))
+ m_d->addCustomWidgets(o, plugin, designerLanguage);
+
+ m_d->m_initialized = true;
+}
+
+QDesignerPluginManager::CustomWidgetList QDesignerPluginManager::registeredCustomWidgets() const
+{
+ const_cast<QDesignerPluginManager*>(this)->ensureInitialized();
+ return m_d->m_customWidgets;
+}
+
+QDesignerCustomWidgetData QDesignerPluginManager::customWidgetData(QDesignerCustomWidgetInterface *w) const
+{
+ const int index = m_d->m_customWidgets.indexOf(w);
+ if (index == -1)
+ return QDesignerCustomWidgetData();
+ return m_d->m_customWidgetData.at(index);
+}
+
+QObjectList QDesignerPluginManager::instances() const
+{
+ QStringList plugins = registeredPlugins();
+
+ QObjectList lst;
+ foreach (const QString &plugin, plugins) {
+ if (QObject *o = instance(plugin))
+ lst.append(o);
+ }
+
+ return lst;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/pluginmanager_p.h b/tools/designer/src/lib/shared/pluginmanager_p.h
new file mode 100644
index 0000000000..e374f42c2a
--- /dev/null
+++ b/tools/designer/src/lib/shared/pluginmanager_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PLUGINMANAGER_H
+#define PLUGINMANAGER_H
+
+#include "shared_global_p.h"
+
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QMap>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerCustomWidgetInterface;
+class QDesignerPluginManagerPrivate;
+
+class QDesignerCustomWidgetSharedData;
+
+/* Information contained in the Dom XML of a custom widget. */
+class QDESIGNER_SHARED_EXPORT QDesignerCustomWidgetData {
+public:
+ explicit QDesignerCustomWidgetData(const QString &pluginPath = QString());
+
+ enum ParseResult { ParseOk, ParseWarning, ParseError };
+ ParseResult parseXml(const QString &xml, const QString &name, QString *errorMessage);
+
+ QDesignerCustomWidgetData(const QDesignerCustomWidgetData&);
+ QDesignerCustomWidgetData& operator=(const QDesignerCustomWidgetData&);
+ ~QDesignerCustomWidgetData();
+
+ bool isNull() const;
+
+ QString pluginPath() const;
+
+ // Data as parsed from the widget's domXML().
+ QString xmlClassName() const;
+ // Optional. The language the plugin is supposed to be used with.
+ QString xmlLanguage() const;
+ // Optional. method used to add pages to a container with a container extension
+ QString xmlAddPageMethod() const;
+ // Optional. Base class
+ QString xmlExtends() const;
+ // Optional. The name to be used in the widget box.
+ QString xmlDisplayName() const;
+
+private:
+ QSharedDataPointer<QDesignerCustomWidgetSharedData> m_d;
+};
+
+class QDESIGNER_SHARED_EXPORT QDesignerPluginManager: public QObject
+{
+ Q_OBJECT
+public:
+ typedef QList<QDesignerCustomWidgetInterface*> CustomWidgetList;
+
+ explicit QDesignerPluginManager(QDesignerFormEditorInterface *core);
+ virtual ~QDesignerPluginManager();
+
+ QDesignerFormEditorInterface *core() const;
+
+ QObject *instance(const QString &plugin) const;
+
+ QStringList registeredPlugins() const;
+
+ QStringList findPlugins(const QString &path);
+
+ QStringList pluginPaths() const;
+ void setPluginPaths(const QStringList &plugin_paths);
+
+ QStringList disabledPlugins() const;
+ void setDisabledPlugins(const QStringList &disabled_plugins);
+
+ QStringList failedPlugins() const;
+ QString failureReason(const QString &pluginName) const;
+
+ QObjectList instances() const;
+
+ CustomWidgetList registeredCustomWidgets() const;
+ QDesignerCustomWidgetData customWidgetData(QDesignerCustomWidgetInterface *w) const;
+
+ bool registerNewPlugins();
+
+public slots:
+ bool syncSettings();
+ void ensureInitialized();
+
+private:
+ void updateRegisteredPlugins();
+ void registerPath(const QString &path);
+ void registerPlugin(const QString &plugin);
+
+private:
+ static QStringList defaultPluginPaths();
+
+ QDesignerPluginManagerPrivate *m_d;
+};
+
+QT_END_NAMESPACE
+
+#endif // PLUGINMANAGER_H
diff --git a/tools/designer/src/lib/shared/previewconfigurationwidget.cpp b/tools/designer/src/lib/shared/previewconfigurationwidget.cpp
new file mode 100644
index 0000000000..2cf362f754
--- /dev/null
+++ b/tools/designer/src/lib/shared/previewconfigurationwidget.cpp
@@ -0,0 +1,382 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* It is possible to link the skins as resources into Designer by specifying:
+ * QVFB_ROOT=$$QT_SOURCE_TREE/tools/qvfb
+ * RESOURCES += $$QVFB_ROOT/ClamshellPhone.qrc $$QVFB_ROOT/PDAPhone.qrc ...
+ * in lib/shared/shared.pri. However, this exceeds a limit of Visual Studio 6. */
+
+#include "previewconfigurationwidget_p.h"
+#include "ui_previewconfigurationwidget.h"
+#include "previewmanager_p.h"
+#include "abstractsettings_p.h"
+#include "shared_settings_p.h"
+
+#include <iconloader_p.h>
+#include <stylesheeteditor_p.h>
+
+#include <deviceskin.h>
+
+#include <QtGui/QFileDialog>
+#include <QtGui/QStyleFactory>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtCore/QPair>
+#include <QtCore/QList>
+#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
+#include <QtCore/QSharedData>
+
+// #define DEFAULT_SKINS_FROM_RESOURCE
+#ifdef DEFAULT_SKINS_FROM_RESOURCE
+QT_BEGIN_NAMESPACE
+static const char *skinResourcePathC = ":/skins/";
+QT_END_NAMESPACE
+#else
+# include <QtCore/QLibraryInfo>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static const char *skinExtensionC = "skin";
+
+namespace {
+ // Pair of skin name, path
+ typedef QPair<QString, QString> SkinNamePath;
+ typedef QList<SkinNamePath> Skins;
+ enum { SkinComboNoneIndex = 0 };
+}
+
+// find default skins (resources)
+static const Skins &defaultSkins() {
+ static Skins rc;
+ if (rc.empty()) {
+#ifdef DEFAULT_SKINS_FROM_RESOURCE
+ const QString skinPath = QLatin1String(skinResourcePathC);
+#else
+ QString skinPath = QLibraryInfo::location(QLibraryInfo::PrefixPath);
+ skinPath += QDir::separator();
+ skinPath += QLatin1String("tools");
+ skinPath += QDir::separator();
+ skinPath += QLatin1String("qvfb");
+#endif
+ QString pattern = QLatin1String("*.");
+ pattern += QLatin1String(skinExtensionC);
+ const QDir dir(skinPath, pattern);
+ const QFileInfoList list = dir.entryInfoList();
+ if (list.empty())
+ return rc;
+ const QFileInfoList::const_iterator lcend = list.constEnd();
+ for (QFileInfoList::const_iterator it = list.constBegin(); it != lcend; ++it)
+ rc.push_back(SkinNamePath(it->baseName(), it->filePath()));
+ }
+ return rc;
+}
+
+namespace qdesigner_internal {
+
+// ------------- PreviewConfigurationWidgetPrivate
+class PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate {
+public:
+ PreviewConfigurationWidgetPrivate(QDesignerFormEditorInterface *core, QGroupBox *g);
+
+ void slotEditAppStyleSheet();
+ void slotDeleteSkinEntry();
+ void slotSkinChanged(int index);
+
+ void retrieveSettings();
+ void storeSettings() const;
+
+ QAbstractButton *appStyleSheetChangeButton() const { return m_ui.m_appStyleSheetChangeButton; }
+ QAbstractButton *skinRemoveButton() const { return m_ui.m_skinRemoveButton; }
+ QComboBox *skinCombo() const { return m_ui.m_skinCombo; }
+
+ QDesignerFormEditorInterface *m_core;
+
+private:
+ PreviewConfiguration previewConfiguration() const;
+ void setPreviewConfiguration(const PreviewConfiguration &pc);
+
+ QStringList userSkins() const;
+ void addUserSkins(const QStringList &files);
+ bool canRemoveSkin(int index) const;
+ int browseSkin();
+
+ const QString m_defaultStyle;
+ QGroupBox *m_parent;
+ Ui::PreviewConfigurationWidget m_ui;
+
+ int m_firstUserSkinIndex;
+ int m_browseSkinIndex;
+ int m_lastSkinIndex; // required in case browse fails
+};
+
+PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::PreviewConfigurationWidgetPrivate(
+ QDesignerFormEditorInterface *core, QGroupBox *g) :
+ m_core(core),
+ m_defaultStyle(PreviewConfigurationWidget::tr("Default")),
+ m_parent(g),
+ m_firstUserSkinIndex(0),
+ m_browseSkinIndex(0),
+ m_lastSkinIndex(0)
+{
+ m_ui.setupUi(g);
+ // styles
+ m_ui.m_styleCombo->setEditable(false);
+ QStringList styleItems(m_defaultStyle);
+ styleItems += QStyleFactory::keys();
+ m_ui.m_styleCombo->addItems(styleItems);
+
+ // sheet
+ m_ui.m_appStyleSheetLineEdit->setTextPropertyValidationMode(qdesigner_internal::ValidationStyleSheet);
+ m_ui.m_appStyleSheetClearButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("resetproperty.png")));
+ QObject::connect(m_ui.m_appStyleSheetClearButton, SIGNAL(clicked()), m_ui.m_appStyleSheetLineEdit, SLOT(clear()));
+
+ m_ui.m_skinRemoveButton->setIcon(qdesigner_internal::createIconSet(QString::fromUtf8("editdelete.png")));
+ // skins: find default skins (resources)
+ m_ui.m_skinRemoveButton->setEnabled(false);
+ Skins skins = defaultSkins();
+ skins.push_front(SkinNamePath(PreviewConfigurationWidget::tr("None"), QString()));
+
+ const Skins::const_iterator scend = skins.constEnd();
+ for (Skins::const_iterator it = skins.constBegin(); it != scend; ++it)
+ m_ui.m_skinCombo->addItem (it->first, QVariant(it->second));
+ m_browseSkinIndex = m_firstUserSkinIndex = skins.size();
+ m_ui.m_skinCombo->addItem(PreviewConfigurationWidget::tr("Browse..."), QString());
+
+ m_ui.m_skinCombo->setMaxVisibleItems (qMax(15, 2 * m_browseSkinIndex));
+ m_ui.m_skinCombo->setEditable(false);
+
+ retrieveSettings();
+}
+
+bool PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::canRemoveSkin(int index) const
+{
+ return index >= m_firstUserSkinIndex && index != m_browseSkinIndex;
+}
+
+QStringList PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::userSkins() const
+{
+ QStringList rc;
+ for (int i = m_firstUserSkinIndex; i < m_browseSkinIndex; i++)
+ rc.push_back(m_ui.m_skinCombo->itemData(i).toString());
+ return rc;
+}
+
+void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::addUserSkins(const QStringList &files)
+{
+ if (files.empty())
+ return;
+ const QStringList ::const_iterator fcend = files.constEnd();
+ for (QStringList::const_iterator it = files.constBegin(); it != fcend; ++it) {
+ const QFileInfo fi(*it);
+ if (fi.isDir() && fi.isReadable()) {
+ m_ui.m_skinCombo->insertItem(m_browseSkinIndex++, fi.baseName(), QVariant(*it));
+ } else {
+ qWarning() << "Unable to access the skin directory '" << *it << "'.";
+ }
+ }
+}
+
+PreviewConfiguration PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::previewConfiguration() const
+{
+ PreviewConfiguration rc;
+ QString style = m_ui.m_styleCombo->currentText();
+ if (style == m_defaultStyle)
+ style.clear();
+ const QString applicationStyleSheet = m_ui.m_appStyleSheetLineEdit->text();
+ // Figure out skin. 0 is None by definition..
+ const int skinIndex = m_ui.m_skinCombo->currentIndex();
+ QString deviceSkin;
+ if (skinIndex != SkinComboNoneIndex && skinIndex != m_browseSkinIndex)
+ deviceSkin = m_ui.m_skinCombo->itemData(skinIndex).toString();
+
+ return PreviewConfiguration(style, applicationStyleSheet, deviceSkin);
+}
+
+void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::setPreviewConfiguration(const PreviewConfiguration &pc)
+{
+ int styleIndex = m_ui.m_styleCombo->findText(pc.style());
+ if (styleIndex == -1)
+ styleIndex = m_ui.m_styleCombo->findText(m_defaultStyle);
+ m_ui.m_styleCombo->setCurrentIndex(styleIndex);
+ m_ui.m_appStyleSheetLineEdit->setText(pc.applicationStyleSheet());
+ // find skin by file name. 0 is "none"
+ const QString deviceSkin = pc.deviceSkin();
+ int skinIndex = deviceSkin.isEmpty() ? 0 : m_ui.m_skinCombo->findData(QVariant(deviceSkin));
+ if (skinIndex == -1) {
+ qWarning() << "Unable to find skin '" << deviceSkin << "'.";
+ skinIndex = 0;
+ }
+ m_ui.m_skinCombo->setCurrentIndex(skinIndex);
+}
+
+void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::slotEditAppStyleSheet()
+{
+ StyleSheetEditorDialog dlg(m_core, m_parent, StyleSheetEditorDialog::ModeGlobal);
+ dlg.setText(m_ui.m_appStyleSheetLineEdit->text());
+ if (dlg.exec() == QDialog::Accepted)
+ m_ui.m_appStyleSheetLineEdit->setText(dlg.text());
+}
+
+void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::slotDeleteSkinEntry()
+{
+ const int index = m_ui.m_skinCombo->currentIndex();
+ if (canRemoveSkin(index)) {
+ m_ui.m_skinCombo->setCurrentIndex(SkinComboNoneIndex);
+ m_ui.m_skinCombo->removeItem(index);
+ m_browseSkinIndex--;
+ }
+}
+
+void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::slotSkinChanged(int index)
+{
+ if (index == m_browseSkinIndex) {
+ m_ui.m_skinCombo->setCurrentIndex(browseSkin());
+ } else {
+ m_lastSkinIndex = index;
+ m_ui.m_skinRemoveButton->setEnabled(canRemoveSkin(index));
+ m_ui.m_skinCombo->setToolTip(index != SkinComboNoneIndex ? m_ui.m_skinCombo->itemData(index).toString() : QString());
+ }
+}
+
+void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::retrieveSettings()
+{
+ QDesignerSharedSettings settings(m_core);
+ m_parent->setChecked(settings.isCustomPreviewConfigurationEnabled());
+ setPreviewConfiguration(settings.customPreviewConfiguration());
+ addUserSkins(settings.userDeviceSkins());
+}
+
+void PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::storeSettings() const
+{
+ QDesignerSharedSettings settings(m_core);
+ settings.setCustomPreviewConfigurationEnabled(m_parent->isChecked());
+ settings.setCustomPreviewConfiguration(previewConfiguration());
+ settings.setUserDeviceSkins(userSkins());
+}
+
+int PreviewConfigurationWidget::PreviewConfigurationWidgetPrivate::browseSkin()
+{
+ QFileDialog dlg(m_parent);
+ dlg.setFileMode(QFileDialog::DirectoryOnly);
+ const QString title = tr("Load Custom Device Skin");
+ dlg.setWindowTitle(title);
+ dlg.setFilter(tr("All QVFB Skins (*.%1)").arg(QLatin1String(skinExtensionC)));
+
+ int rc = m_lastSkinIndex;
+ do {
+ if (!dlg.exec())
+ break;
+
+ const QStringList directories = dlg.selectedFiles();
+ if (directories.size() != 1)
+ break;
+
+ // check: 1) name already there
+ const QString directory = directories.front();
+ const QString name = QFileInfo(directory).baseName();
+ const int existingIndex = m_ui.m_skinCombo->findText(name);
+ if (existingIndex != -1 && existingIndex != SkinComboNoneIndex && existingIndex != m_browseSkinIndex) {
+ const QString msgTitle = tr("%1 - Duplicate Skin").arg(title);
+ const QString msg = tr("The skin '%1' already exists.").arg(name);
+ QMessageBox::information(m_parent, msgTitle, msg);
+ break;
+ }
+ // check: 2) can read
+ DeviceSkinParameters parameters;
+ QString readError;
+ if (parameters.read(directory, DeviceSkinParameters::ReadSizeOnly, &readError)) {
+ const QString name = QFileInfo(directory).baseName();
+ m_ui.m_skinCombo->insertItem(m_browseSkinIndex, name, QVariant(directory));
+ rc = m_browseSkinIndex++;
+
+ break;
+ } else {
+ const QString msgTitle = tr("%1 - Error").arg(title);
+ const QString msg = tr("%1 is not a valid skin directory:\n%2").arg(directory).arg(readError);
+ QMessageBox::warning (m_parent, msgTitle, msg);
+ }
+ } while (true);
+ return rc;
+}
+
+// ------------- PreviewConfigurationWidget
+PreviewConfigurationWidget::PreviewConfigurationWidget(QDesignerFormEditorInterface *core,
+ QWidget *parent) :
+ QGroupBox(parent),
+ m_impl(new PreviewConfigurationWidgetPrivate(core, this))
+{
+ connect(m_impl->appStyleSheetChangeButton(), SIGNAL(clicked()), this, SLOT(slotEditAppStyleSheet()));
+ connect(m_impl->skinRemoveButton(), SIGNAL(clicked()), this, SLOT(slotDeleteSkinEntry()));
+ connect(m_impl->skinCombo(), SIGNAL(currentIndexChanged(int)), this, SLOT(slotSkinChanged(int)));
+
+ m_impl->retrieveSettings();
+}
+
+PreviewConfigurationWidget::~PreviewConfigurationWidget()
+{
+ delete m_impl;
+}
+
+void PreviewConfigurationWidget::saveState()
+{
+ m_impl->storeSettings();
+}
+
+void PreviewConfigurationWidget::slotEditAppStyleSheet()
+{
+ m_impl->slotEditAppStyleSheet();
+}
+
+void PreviewConfigurationWidget::slotDeleteSkinEntry()
+{
+ m_impl->slotDeleteSkinEntry();
+}
+
+void PreviewConfigurationWidget::slotSkinChanged(int index)
+{
+ m_impl->slotSkinChanged(index);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/previewconfigurationwidget.ui b/tools/designer/src/lib/shared/previewconfigurationwidget.ui
new file mode 100644
index 0000000000..2f18766ff7
--- /dev/null
+++ b/tools/designer/src/lib/shared/previewconfigurationwidget.ui
@@ -0,0 +1,91 @@
+<ui version="4.0" >
+ <class>PreviewConfigurationWidget</class>
+ <widget class="QGroupBox" name="PreviewConfigurationWidget" >
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <property name="title" >
+ <string>Print/Preview Configuration</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <layout class="QFormLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="m_styleLabel" >
+ <property name="text" >
+ <string>Style</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QComboBox" name="m_styleCombo" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="m_appStyleSheetLabel" >
+ <property name="text" >
+ <string>Style sheet</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="qdesigner_internal::TextPropertyEditor" name="m_appStyleSheetLineEdit" >
+ <property name="minimumSize" >
+ <size>
+ <width>149</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="m_appStyleSheetChangeButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="m_appStyleSheetClearButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="m_skinLabel" >
+ <property name="text" >
+ <string>Device skin</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QComboBox" name="m_skinCombo" />
+ </item>
+ <item>
+ <widget class="QToolButton" name="m_skinRemoveButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>qdesigner_internal::TextPropertyEditor</class>
+ <extends>QLineEdit</extends>
+ <header location="global" >textpropertyeditor_p.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/lib/shared/previewconfigurationwidget_p.h b/tools/designer/src/lib/shared/previewconfigurationwidget_p.h
new file mode 100644
index 0000000000..897ec4e8bf
--- /dev/null
+++ b/tools/designer/src/lib/shared/previewconfigurationwidget_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PREVIEWCONFIGURATIONWIDGET_H
+#define PREVIEWCONFIGURATIONWIDGET_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QGroupBox>
+#include <QtCore/QSharedDataPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerSettingsInterface;
+
+namespace qdesigner_internal {
+
+// ----------- PreviewConfigurationWidget: Widget to edit the preview configuration.
+
+class QDESIGNER_SHARED_EXPORT PreviewConfigurationWidget : public QGroupBox
+{
+ Q_OBJECT
+public:
+ explicit PreviewConfigurationWidget(QDesignerFormEditorInterface *core,
+ QWidget *parent = 0);
+ virtual ~PreviewConfigurationWidget();
+ void saveState();
+
+private slots:
+ void slotEditAppStyleSheet();
+ void slotDeleteSkinEntry();
+ void slotSkinChanged(int);
+
+private:
+ class PreviewConfigurationWidgetPrivate;
+ PreviewConfigurationWidgetPrivate *m_impl;
+
+ PreviewConfigurationWidget(const PreviewConfigurationWidget &other);
+ PreviewConfigurationWidget &operator =(const PreviewConfigurationWidget &other);
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PREVIEWCONFIGURATIONWIDGET_H
diff --git a/tools/designer/src/lib/shared/previewmanager.cpp b/tools/designer/src/lib/shared/previewmanager.cpp
new file mode 100644
index 0000000000..8ed1772ad7
--- /dev/null
+++ b/tools/designer/src/lib/shared/previewmanager.cpp
@@ -0,0 +1,815 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractsettings_p.h"
+#include "previewmanager_p.h"
+#include "qdesigner_formbuilder_p.h"
+#include "shared_settings_p.h"
+#include "shared_settings_p.h"
+#include "zoomwidget_p.h"
+#include "formwindowbase_p.h"
+#include "widgetfactory_p.h"
+
+#include <deviceskin.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+#include <QtGui/QWidget>
+#include <QtGui/qevent.h>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QMainWindow>
+#include <QtGui/QDockWidget>
+#include <QtGui/QApplication>
+#include <QtGui/QPixmap>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QDialog>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QCursor>
+
+#include <QtCore/QMap>
+#include <QtCore/QDebug>
+#include <QtCore/QSharedData>
+
+QT_BEGIN_NAMESPACE
+
+static inline int compare(const qdesigner_internal::PreviewConfiguration &pc1, const qdesigner_internal::PreviewConfiguration &pc2)
+{
+ int rc = pc1.style().compare(pc2.style());
+ if (rc)
+ return rc;
+ rc = pc1.applicationStyleSheet().compare(pc2.applicationStyleSheet());
+ if (rc)
+ return rc;
+ return pc1.deviceSkin().compare(pc2.deviceSkin());
+}
+
+namespace {
+ // ------ PreviewData (data associated with a preview window)
+ struct PreviewData {
+ PreviewData(const QPointer<QWidget> &widget, const QDesignerFormWindowInterface *formWindow, const qdesigner_internal::PreviewConfiguration &pc);
+ QPointer<QWidget> m_widget;
+ const QDesignerFormWindowInterface *m_formWindow;
+ qdesigner_internal::PreviewConfiguration m_configuration;
+ };
+
+ PreviewData::PreviewData(const QPointer<QWidget>& widget,
+ const QDesignerFormWindowInterface *formWindow,
+ const qdesigner_internal::PreviewConfiguration &pc) :
+ m_widget(widget),
+ m_formWindow(formWindow),
+ m_configuration(pc)
+ {
+ }
+}
+
+namespace qdesigner_internal {
+
+/* In designer, we have the situation that laid-out maincontainers have
+ * a geometry set (which might differ from their sizeHint()). The QGraphicsItem
+ * should return that in its size hint, else such cases won't work */
+
+class DesignerZoomProxyWidget : public ZoomProxyWidget {
+ Q_DISABLE_COPY(DesignerZoomProxyWidget)
+public:
+ DesignerZoomProxyWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
+protected:
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+};
+
+DesignerZoomProxyWidget::DesignerZoomProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) :
+ ZoomProxyWidget(parent, wFlags)
+{
+}
+
+QSizeF DesignerZoomProxyWidget::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
+{
+ if (const QWidget *w = widget())
+ return QSizeF(w->size());
+ return ZoomProxyWidget::sizeHint(which, constraint);
+}
+
+// DesignerZoomWidget which returns DesignerZoomProxyWidget in its factory function
+class DesignerZoomWidget : public ZoomWidget {
+ Q_DISABLE_COPY(DesignerZoomWidget)
+public:
+ DesignerZoomWidget(QWidget *parent = 0);
+private:
+ virtual QGraphicsProxyWidget *createProxyWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0) const;
+};
+
+DesignerZoomWidget::DesignerZoomWidget(QWidget *parent) :
+ ZoomWidget(parent)
+{
+}
+
+QGraphicsProxyWidget *DesignerZoomWidget::createProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) const
+{
+ return new DesignerZoomProxyWidget(parent, wFlags);
+}
+
+// --------- Widget Preview skin: Forward the key events to the window
+class PreviewDeviceSkin : public DeviceSkin
+{
+ Q_OBJECT
+public:
+ explicit PreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent);
+ virtual void setPreview(QWidget *w);
+ QSize screenSize() const { return m_screenSize; }
+
+private slots:
+ void slotSkinKeyPressEvent(int code, const QString& text, bool autorep);
+ void slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep);
+ void slotPopupMenu();
+
+protected:
+ virtual void populateContextMenu(QMenu *m);
+
+private:
+ const QSize m_screenSize;
+};
+
+PreviewDeviceSkin::PreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent) :
+ DeviceSkin(parameters, parent),
+ m_screenSize(parameters.screenSize())
+{
+ connect(this, SIGNAL(skinKeyPressEvent(int,QString,bool)),
+ this, SLOT(slotSkinKeyPressEvent(int,QString,bool)));
+ connect(this, SIGNAL(skinKeyReleaseEvent(int,QString,bool)),
+ this, SLOT(slotSkinKeyReleaseEvent(int,QString,bool)));
+ connect(this, SIGNAL(popupMenu()), this, SLOT(slotPopupMenu()));
+}
+
+void PreviewDeviceSkin::setPreview(QWidget *formWidget)
+{
+ formWidget->setFixedSize(m_screenSize);
+ formWidget->setParent(this, Qt::SubWindow);
+ formWidget->setAutoFillBackground(true);
+ setView(formWidget);
+}
+
+void PreviewDeviceSkin::slotSkinKeyPressEvent(int code, const QString& text, bool autorep)
+{
+ if (QWidget *focusWidget = QApplication::focusWidget()) {
+ QKeyEvent e(QEvent::KeyPress,code,0,text,autorep);
+ QApplication::sendEvent(focusWidget, &e);
+ }
+
+}
+
+void PreviewDeviceSkin::slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep)
+{
+ if (QWidget *focusWidget = QApplication::focusWidget()) {
+ QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep);
+ QApplication::sendEvent(focusWidget, &e);
+ }
+}
+
+void PreviewDeviceSkin::slotPopupMenu()
+{
+ QMenu menu(this);
+ populateContextMenu(&menu);
+ menu.exec(QCursor::pos());
+}
+
+void PreviewDeviceSkin::populateContextMenu(QMenu *menu)
+{
+ connect(menu->addAction(tr("&Close")), SIGNAL(triggered()), parentWidget(), SLOT(close()));
+}
+
+// ------------ PreviewConfigurationPrivate
+class PreviewConfigurationData : public QSharedData {
+public:
+ PreviewConfigurationData() {}
+ explicit PreviewConfigurationData(const QString &style, const QString &applicationStyleSheet, const QString &deviceSkin);
+
+ QString m_style;
+ // Style sheet to prepend (to simulate the effect od QApplication::setSyleSheet()).
+ QString m_applicationStyleSheet;
+ QString m_deviceSkin;
+};
+
+PreviewConfigurationData::PreviewConfigurationData(const QString &style, const QString &applicationStyleSheet, const QString &deviceSkin) :
+ m_style(style),
+ m_applicationStyleSheet(applicationStyleSheet),
+ m_deviceSkin(deviceSkin)
+{
+}
+
+/* ZoomablePreviewDeviceSkin: A Zoomable Widget Preview skin. Embeds preview
+ * into a ZoomWidget and this in turn into the DeviceSkin view and keeps
+ * Device skin zoom + ZoomWidget zoom in sync. */
+
+class ZoomablePreviewDeviceSkin : public PreviewDeviceSkin
+{
+ Q_OBJECT
+public:
+ explicit ZoomablePreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent);
+ virtual void setPreview(QWidget *w);
+
+ int zoomPercent() const; // Device Skins have a double 'zoom' property
+
+public slots:
+ void setZoomPercent(int);
+
+signals:
+ void zoomPercentChanged(int);
+
+protected:
+ virtual void populateContextMenu(QMenu *m);
+
+private:
+ ZoomMenu *m_zoomMenu;
+ ZoomWidget *m_zoomWidget;
+};
+
+ZoomablePreviewDeviceSkin::ZoomablePreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent) :
+ PreviewDeviceSkin(parameters, parent),
+ m_zoomMenu(new ZoomMenu(this)),
+ m_zoomWidget(new DesignerZoomWidget)
+{
+ connect(m_zoomMenu, SIGNAL(zoomChanged(int)), this, SLOT(setZoomPercent(int)));
+ connect(m_zoomMenu, SIGNAL(zoomChanged(int)), this, SIGNAL(zoomPercentChanged(int)));
+ m_zoomWidget->setZoomContextMenuEnabled(false);
+ m_zoomWidget->setWidgetZoomContextMenuEnabled(false);
+ m_zoomWidget->resize(screenSize());
+ m_zoomWidget->setParent(this, Qt::SubWindow);
+ m_zoomWidget->setAutoFillBackground(true);
+ setView(m_zoomWidget);
+}
+
+void ZoomablePreviewDeviceSkin::setPreview(QWidget *formWidget)
+{
+ formWidget->setFixedSize(screenSize());
+ m_zoomWidget->setWidget(formWidget);
+}
+
+int ZoomablePreviewDeviceSkin::zoomPercent() const
+{
+ return m_zoomWidget->zoom();
+}
+
+void ZoomablePreviewDeviceSkin::setZoomPercent(int z)
+{
+ if (z == zoomPercent())
+ return;
+
+ // If not triggered by the menu itself: Update it
+ if (m_zoomMenu->zoom() != z)
+ m_zoomMenu->setZoom(z);
+
+ const QCursor oldCursor = cursor();
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ // DeviceSkin has double, not qreal.
+ const double hundred = 100.0;
+ setZoom(static_cast<double>(z) / hundred);
+ m_zoomWidget->setZoom(z);
+ QApplication::restoreOverrideCursor();
+}
+
+void ZoomablePreviewDeviceSkin::populateContextMenu(QMenu *menu)
+{
+ m_zoomMenu->addActions(menu);
+ menu->addSeparator();
+ PreviewDeviceSkin::populateContextMenu(menu);
+ menu->addSeparator();
+}
+
+// ------------- PreviewConfiguration
+
+static const char *styleKey = "Style";
+static const char *appStyleSheetKey = "AppStyleSheet";
+static const char *skinKey = "Skin";
+
+PreviewConfiguration::PreviewConfiguration() :
+ m_d(new PreviewConfigurationData)
+{
+}
+
+PreviewConfiguration::PreviewConfiguration(const QString &sty, const QString &applicationSheet, const QString &skin) :
+ m_d(new PreviewConfigurationData(sty, applicationSheet, skin))
+{
+}
+
+PreviewConfiguration::PreviewConfiguration(const PreviewConfiguration &o) :
+ m_d(o.m_d)
+{
+}
+
+PreviewConfiguration &PreviewConfiguration::operator=(const PreviewConfiguration &o)
+{
+ m_d.operator=(o.m_d);
+ return *this;
+}
+
+PreviewConfiguration::~PreviewConfiguration()
+{
+}
+
+void PreviewConfiguration::clear()
+{
+ PreviewConfigurationData &d = *m_d;
+ d.m_style.clear();
+ d.m_applicationStyleSheet.clear();
+ d.m_deviceSkin.clear();
+}
+
+QString PreviewConfiguration::style() const
+{
+ return m_d->m_style;
+}
+
+void PreviewConfiguration::setStyle(const QString &s)
+{
+ m_d->m_style = s;
+}
+
+// Style sheet to prepend (to simulate the effect od QApplication::setSyleSheet()).
+QString PreviewConfiguration::applicationStyleSheet() const
+{
+ return m_d->m_applicationStyleSheet;
+}
+
+void PreviewConfiguration::setApplicationStyleSheet(const QString &as)
+{
+ m_d->m_applicationStyleSheet = as;
+}
+
+QString PreviewConfiguration::deviceSkin() const
+{
+ return m_d->m_deviceSkin;
+}
+
+void PreviewConfiguration::setDeviceSkin(const QString &s)
+{
+ m_d->m_deviceSkin = s;
+}
+
+void PreviewConfiguration::toSettings(const QString &prefix, QDesignerSettingsInterface *settings) const
+{
+ const PreviewConfigurationData &d = *m_d;
+ settings->beginGroup(prefix);
+ settings->setValue(QLatin1String(styleKey), d.m_style);
+ settings->setValue(QLatin1String(appStyleSheetKey), d.m_applicationStyleSheet);
+ settings->setValue(QLatin1String(skinKey), d.m_deviceSkin);
+ settings->endGroup();
+}
+
+void PreviewConfiguration::fromSettings(const QString &prefix, const QDesignerSettingsInterface *settings)
+{
+ clear();
+ QString key = prefix;
+ key += QLatin1Char('/');
+ const int prefixSize = key.size();
+
+ PreviewConfigurationData &d = *m_d;
+
+ const QVariant emptyString = QVariant(QString());
+
+ key += QLatin1String(styleKey);
+ d.m_style = settings->value(key, emptyString).toString();
+
+ key.replace(prefixSize, key.size() - prefixSize, QLatin1String(appStyleSheetKey));
+ d.m_applicationStyleSheet = settings->value(key, emptyString).toString();
+
+ key.replace(prefixSize, key.size() - prefixSize, QLatin1String(skinKey));
+ d.m_deviceSkin = settings->value(key, emptyString).toString();
+}
+
+
+QDESIGNER_SHARED_EXPORT bool operator<(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2)
+{
+ return compare(pc1, pc2) < 0;
+}
+
+QDESIGNER_SHARED_EXPORT bool operator==(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2)
+{
+ return compare(pc1, pc2) == 0;
+}
+
+QDESIGNER_SHARED_EXPORT bool operator!=(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2)
+{
+ return compare(pc1, pc2) != 0;
+}
+
+// ------------- PreviewManagerPrivate
+class PreviewManagerPrivate {
+public:
+ PreviewManagerPrivate(PreviewManager::PreviewMode mode);
+
+ const PreviewManager::PreviewMode m_mode;
+
+ QPointer<QWidget> m_activePreview;
+
+ typedef QList<PreviewData> PreviewDataList;
+
+ PreviewDataList m_previews;
+
+ typedef QMap<QString, DeviceSkinParameters> DeviceSkinConfigCache;
+ DeviceSkinConfigCache m_deviceSkinConfigCache;
+
+ QDesignerFormEditorInterface *m_core;
+ bool m_updateBlocked;
+};
+
+PreviewManagerPrivate::PreviewManagerPrivate(PreviewManager::PreviewMode mode) :
+ m_mode(mode),
+ m_core(0),
+ m_updateBlocked(false)
+{
+}
+
+// ------------- PreviewManager
+
+PreviewManager::PreviewManager(PreviewMode mode, QObject *parent) :
+ QObject(parent),
+ d(new PreviewManagerPrivate(mode))
+{
+}
+
+PreviewManager:: ~PreviewManager()
+{
+ delete d;
+}
+
+
+Qt::WindowFlags PreviewManager::previewWindowFlags(const QWidget *widget) const
+{
+#ifdef Q_WS_WIN
+ Qt::WindowFlags windowFlags = (widget->windowType() == Qt::Window) ? Qt::Window | Qt::WindowMaximizeButtonHint : Qt::WindowFlags(Qt::Dialog);
+#else
+ Q_UNUSED(widget)
+ // Only Dialogs have close buttons on Mac.
+ // On Linux, we don't want an additional task bar item and we don't want a minimize button;
+ // we want the preview to be on top.
+ Qt::WindowFlags windowFlags = Qt::Dialog;
+#endif
+ return windowFlags;
+}
+
+QWidget *PreviewManager::createDeviceSkinContainer(const QDesignerFormWindowInterface *fw) const
+{
+ return new QDialog(fw->window());
+}
+
+// Some widgets might require fake containers
+
+static QWidget *fakeContainer(QWidget *w)
+{
+ // Prevent a dock widget from trying to dock to Designer's main window
+ // (which can be found in the parent hierarchy in MDI mode) by
+ // providing a fake mainwindow
+ if (QDockWidget *dock = qobject_cast<QDockWidget *>(w)) {
+ // Reparent: Clear modality, propagate title and resize outer container
+ const QSize size = w->size();
+ w->setWindowModality(Qt::NonModal);
+ dock->setFeatures(dock->features() & ~(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetClosable));
+ dock->setAllowedAreas(Qt::LeftDockWidgetArea);
+ QMainWindow *mw = new QMainWindow;
+ int leftMargin, topMargin, rightMargin, bottomMargin;
+ mw->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
+ mw->addDockWidget(Qt::LeftDockWidgetArea, dock);
+ mw->resize(size + QSize(leftMargin + rightMargin, topMargin + bottomMargin));
+ return mw;
+ }
+ return w;
+}
+
+static PreviewConfiguration configurationFromSettings(QDesignerFormEditorInterface *core, const QString &style)
+{
+ qdesigner_internal::PreviewConfiguration pc;
+ const QDesignerSharedSettings settings(core);
+ if (settings.isCustomPreviewConfigurationEnabled())
+ pc = settings.customPreviewConfiguration();
+ if (!style.isEmpty())
+ pc.setStyle(style);
+ return pc;
+}
+
+QWidget *PreviewManager::showPreview(const QDesignerFormWindowInterface *fw, const QString &style, int deviceProfileIndex, QString *errorMessage)
+{
+ return showPreview(fw, configurationFromSettings(fw->core(), style), deviceProfileIndex, errorMessage);
+}
+
+QWidget *PreviewManager::showPreview(const QDesignerFormWindowInterface *fw, const QString &style, QString *errorMessage)
+{
+ return showPreview(fw, style, -1, errorMessage);
+}
+
+QWidget *PreviewManager::createPreview(const QDesignerFormWindowInterface *fw,
+ const PreviewConfiguration &pc,
+ int deviceProfileIndex,
+ QString *errorMessage,
+ int initialZoom)
+{
+ if (!d->m_core)
+ d->m_core = fw->core();
+
+ const bool zoomable = initialZoom > 0;
+ // Figure out which profile to apply
+ DeviceProfile deviceProfile;
+ if (deviceProfileIndex >= 0) {
+ deviceProfile = QDesignerSharedSettings(fw->core()).deviceProfileAt(deviceProfileIndex);
+ } else {
+ if (const FormWindowBase *fwb = qobject_cast<const FormWindowBase *>(fw))
+ deviceProfile = fwb->deviceProfile();
+ }
+ // Create
+ QWidget *formWidget = QDesignerFormBuilder::createPreview(fw, pc.style(), pc.applicationStyleSheet(), deviceProfile, errorMessage);
+ if (!formWidget)
+ return 0;
+
+ const QString title = tr("%1 - [Preview]").arg(formWidget->windowTitle());
+ formWidget = fakeContainer(formWidget);
+
+ // Clear any modality settings, child widget modalities must not be higher than parent's
+ formWidget->setWindowModality(Qt::NonModal);
+ // No skin
+ const QString deviceSkin = pc.deviceSkin();
+ if (deviceSkin.isEmpty()) {
+ if (zoomable) { // Embed into ZoomWidget
+ ZoomWidget *zw = new DesignerZoomWidget;
+ connect(zw->zoomMenu(), SIGNAL(zoomChanged(int)), this, SLOT(slotZoomChanged(int)));
+ zw->setWindowTitle(title);
+ zw->setWidget(formWidget);
+ // Keep any widgets' context menus working, do not use global menu
+ zw->setWidgetZoomContextMenuEnabled(true);
+ zw->setParent(fw->window(), previewWindowFlags(formWidget));
+ // Make preview close when Widget closes (Dialog/accept, etc)
+ formWidget->setAttribute(Qt::WA_DeleteOnClose, true);
+ connect(formWidget, SIGNAL(destroyed()), zw, SLOT(close()));
+ zw->setZoom(initialZoom);
+ zw->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true));
+ return zw;
+ }
+ formWidget->setParent(fw->window(), previewWindowFlags(formWidget));
+ formWidget->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true));
+ return formWidget;
+ }
+ // Embed into skin. find config in cache
+ PreviewManagerPrivate::DeviceSkinConfigCache::iterator it = d->m_deviceSkinConfigCache.find(deviceSkin);
+ if (it == d->m_deviceSkinConfigCache.end()) {
+ DeviceSkinParameters parameters;
+ if (!parameters.read(deviceSkin, DeviceSkinParameters::ReadAll, errorMessage)) {
+ formWidget->deleteLater();
+ return 0;
+ }
+ it = d->m_deviceSkinConfigCache.insert(deviceSkin, parameters);
+ }
+
+ QWidget *skinContainer = createDeviceSkinContainer(fw);
+ PreviewDeviceSkin *skin = 0;
+ if (zoomable) {
+ ZoomablePreviewDeviceSkin *zds = new ZoomablePreviewDeviceSkin(it.value(), skinContainer);
+ zds->setZoomPercent(initialZoom);
+ connect(zds, SIGNAL(zoomPercentChanged(int)), this, SLOT(slotZoomChanged(int)));
+ skin = zds;
+ } else {
+ skin = new PreviewDeviceSkin(it.value(), skinContainer);
+ }
+ skin->setPreview(formWidget);
+ // Make preview close when Widget closes (Dialog/accept, etc)
+ formWidget->setAttribute(Qt::WA_DeleteOnClose, true);
+ connect(formWidget, SIGNAL(destroyed()), skinContainer, SLOT(close()));
+ skinContainer->setWindowTitle(title);
+ skinContainer->setProperty(WidgetFactory::disableStyleCustomPaintingPropertyC, QVariant(true));
+ return skinContainer;
+}
+
+QWidget *PreviewManager::showPreview(const QDesignerFormWindowInterface *fw,
+ const PreviewConfiguration &pc,
+ int deviceProfileIndex,
+ QString *errorMessage)
+{
+ enum { Spacing = 10 };
+ if (QWidget *existingPreviewWidget = raise(fw, pc))
+ return existingPreviewWidget;
+
+ const QDesignerSharedSettings settings(fw->core());
+ const int initialZoom = settings.zoomEnabled() ? settings.zoom() : -1;
+
+ QWidget *widget = createPreview(fw, pc, deviceProfileIndex, errorMessage, initialZoom);
+ if (!widget)
+ return 0;
+ // Install filter for Escape key
+ widget->setAttribute(Qt::WA_DeleteOnClose, true);
+ widget->installEventFilter(this);
+
+ switch (d->m_mode) {
+ case ApplicationModalPreview:
+ // Cannot do this on the Mac as the dialog would have no close button
+ widget->setWindowModality(Qt::ApplicationModal);
+ break;
+ case SingleFormNonModalPreview:
+ case MultipleFormNonModalPreview:
+ widget->setWindowModality(Qt::NonModal);
+ connect(fw, SIGNAL(changed()), widget, SLOT(close()));
+ connect(fw, SIGNAL(destroyed()), widget, SLOT(close()));
+ if (d->m_mode == SingleFormNonModalPreview)
+ connect(fw->core()->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)), widget, SLOT(close()));
+ break;
+ }
+ // Semi-smart algorithm to position previews:
+ // If its the first one, position relative to form.
+ // 2nd, attempt to tile right (for comparing styles) or cascade
+ const QSize size = widget->size();
+ const bool firstPreview = d->m_previews.empty();
+ if (firstPreview) {
+ widget->move(fw->mapToGlobal(QPoint(Spacing, Spacing)));
+ } else {
+ if (QWidget *lastPreview = d->m_previews.back().m_widget) {
+ QDesktopWidget *desktop = qApp->desktop();
+ const QRect lastPreviewGeometry = lastPreview->frameGeometry();
+ const QRect availGeometry = desktop->availableGeometry(desktop->screenNumber(lastPreview));
+ const QPoint newPos = lastPreviewGeometry.topRight() + QPoint(Spacing, 0);
+ if (newPos.x() + size.width() < availGeometry.right())
+ widget->move(newPos);
+ else
+ widget->move(lastPreviewGeometry.topLeft() + QPoint(Spacing, Spacing));
+ }
+
+ }
+ d->m_previews.push_back(PreviewData(widget, fw, pc));
+ widget->show();
+ if (firstPreview)
+ emit firstPreviewOpened();
+ return widget;
+}
+
+QWidget *PreviewManager::raise(const QDesignerFormWindowInterface *fw, const PreviewConfiguration &pc)
+{
+ typedef PreviewManagerPrivate::PreviewDataList PreviewDataList;
+ if (d->m_previews.empty())
+ return false;
+
+ // find matching window
+ const PreviewDataList::const_iterator cend = d->m_previews.constEnd();
+ for (PreviewDataList::const_iterator it = d->m_previews.constBegin(); it != cend ;++it) {
+ QWidget * w = it->m_widget;
+ if (w && it->m_formWindow == fw && it->m_configuration == pc) {
+ w->raise();
+ w->activateWindow();
+ return w;
+ }
+ }
+ return 0;
+}
+
+void PreviewManager::closeAllPreviews()
+{
+ typedef PreviewManagerPrivate::PreviewDataList PreviewDataList;
+ if (!d->m_previews.empty()) {
+ d->m_updateBlocked = true;
+ d->m_activePreview = 0;
+ const PreviewDataList::iterator cend = d->m_previews.end();
+ for (PreviewDataList::iterator it = d->m_previews.begin(); it != cend ;++it) {
+ if (it->m_widget)
+ it->m_widget->close();
+ }
+ d->m_previews.clear();
+ d->m_updateBlocked = false;
+ emit lastPreviewClosed();
+ }
+}
+
+void PreviewManager::updatePreviewClosed(QWidget *w)
+{
+ typedef PreviewManagerPrivate::PreviewDataList PreviewDataList;
+ if (d->m_updateBlocked)
+ return;
+ // Purge out all 0 or widgets to be deleted
+ for (PreviewDataList::iterator it = d->m_previews.begin(); it != d->m_previews.end() ; ) {
+ QWidget *iw = it->m_widget; // Might be 0 when catching QEvent::Destroyed
+ if (iw == 0 || iw == w) {
+ it = d->m_previews.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ if (d->m_previews.empty())
+ emit lastPreviewClosed();
+}
+
+bool PreviewManager::eventFilter(QObject *watched, QEvent *event)
+{
+ // Courtesy of designer
+ do {
+ if (!watched->isWidgetType())
+ break;
+ QWidget *previewWindow = qobject_cast<QWidget *>(watched);
+ if (!previewWindow || !previewWindow->isWindow())
+ break;
+
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ case QEvent::ShortcutOverride: {
+ const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
+ const int key = keyEvent->key();
+ if ((key == Qt::Key_Escape
+#ifdef Q_WS_MAC
+ || (keyEvent->modifiers() == Qt::ControlModifier && key == Qt::Key_Period)
+#endif
+ )) {
+ previewWindow->close();
+ return true;
+ }
+ }
+ break;
+ case QEvent::WindowActivate:
+ d->m_activePreview = previewWindow;
+ break;
+ case QEvent::Destroy: // We don't get QEvent::Close if someone accepts a QDialog.
+ updatePreviewClosed(previewWindow);
+ break;
+ case QEvent::Close:
+ updatePreviewClosed(previewWindow);
+ previewWindow->removeEventFilter (this);
+ break;
+ default:
+ break;
+ }
+ } while(false);
+ return QObject::eventFilter(watched, event);
+}
+
+int PreviewManager::previewCount() const
+{
+ return d->m_previews.size();
+}
+
+QPixmap PreviewManager::createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &style, int deviceProfileIndex, QString *errorMessage)
+{
+ return createPreviewPixmap(fw, configurationFromSettings(fw->core(), style), deviceProfileIndex, errorMessage);
+}
+
+QPixmap PreviewManager::createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &style, QString *errorMessage)
+{
+ return createPreviewPixmap(fw, style, -1, errorMessage);
+}
+
+QPixmap PreviewManager::createPreviewPixmap(const QDesignerFormWindowInterface *fw,
+ const PreviewConfiguration &pc,
+ int deviceProfileIndex,
+ QString *errorMessage)
+{
+ QWidget *widget = createPreview(fw, pc, deviceProfileIndex, errorMessage);
+ if (!widget)
+ return QPixmap();
+ const QPixmap rc = QPixmap::grabWidget(widget);
+ widget->deleteLater();
+ return rc;
+}
+
+void PreviewManager::slotZoomChanged(int z)
+{
+ if (d->m_core) { // Save the last zoom chosen by the user.
+ QDesignerSharedSettings settings(d->m_core);
+ settings.setZoom(z);
+ }
+}
+}
+
+QT_END_NAMESPACE
+
+#include "previewmanager.moc"
diff --git a/tools/designer/src/lib/shared/previewmanager_p.h b/tools/designer/src/lib/shared/previewmanager_p.h
new file mode 100644
index 0000000000..1060f3c9c4
--- /dev/null
+++ b/tools/designer/src/lib/shared/previewmanager_p.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PREVIEWMANAGER_H
+#define PREVIEWMANAGER_H
+
+#include "shared_global_p.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QSharedDataPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QWidget;
+class QPixmap;
+class QAction;
+class QActionGroup;
+class QMenu;
+class QWidget;
+class QDesignerSettingsInterface;
+
+namespace qdesigner_internal {
+
+// ----------- PreviewConfiguration
+
+class PreviewConfigurationData;
+
+class QDESIGNER_SHARED_EXPORT PreviewConfiguration {
+public:
+ PreviewConfiguration();
+ explicit PreviewConfiguration(const QString &style,
+ const QString &applicationStyleSheet = QString(),
+ const QString &deviceSkin = QString());
+
+ PreviewConfiguration(const PreviewConfiguration&);
+ PreviewConfiguration& operator=(const PreviewConfiguration&);
+ ~PreviewConfiguration();
+
+ QString style() const;
+ void setStyle(const QString &);
+
+ // Style sheet to prepend (to simulate the effect od QApplication::setSyleSheet()).
+ QString applicationStyleSheet() const;
+ void setApplicationStyleSheet(const QString &);
+
+ QString deviceSkin() const;
+ void setDeviceSkin(const QString &);
+
+ void clear();
+ void toSettings(const QString &prefix, QDesignerSettingsInterface *settings) const;
+ void fromSettings(const QString &prefix, const QDesignerSettingsInterface *settings);
+
+private:
+ QSharedDataPointer<PreviewConfigurationData> m_d;
+};
+
+QDESIGNER_SHARED_EXPORT bool operator<(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2);
+QDESIGNER_SHARED_EXPORT bool operator==(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2);
+QDESIGNER_SHARED_EXPORT bool operator!=(const PreviewConfiguration &pc1, const PreviewConfiguration &pc2);
+
+// ----------- Preview window manager.
+// Maintains a list of preview widgets with their associated form windows and configuration.
+
+class PreviewManagerPrivate;
+
+class QDESIGNER_SHARED_EXPORT PreviewManager : public QObject
+{
+ Q_OBJECT
+public:
+
+ enum PreviewMode {
+ // Modal preview. Do not use on Macs as dialogs would have no close button
+ ApplicationModalPreview,
+ // Non modal previewing of one form in different configurations (closes if form window changes)
+ SingleFormNonModalPreview,
+ // Non modal previewing of several forms in different configurations
+ MultipleFormNonModalPreview };
+
+ explicit PreviewManager(PreviewMode mode, QObject *parent);
+ virtual ~PreviewManager();
+
+ // Show preview. Raise existing preview window if there is one with a matching
+ // configuration, else create a new preview.
+ QWidget *showPreview(const QDesignerFormWindowInterface *, const PreviewConfiguration &pc, int deviceProfileIndex /*=-1*/, QString *errorMessage);
+ // Convenience that creates a preview using a configuration taken from the settings.
+ QWidget *showPreview(const QDesignerFormWindowInterface *, const QString &style, int deviceProfileIndex /*=-1*/, QString *errorMessage);
+ QWidget *showPreview(const QDesignerFormWindowInterface *, const QString &style, QString *errorMessage);
+
+ int previewCount() const;
+
+ // Create a pixmap for printing.
+ QPixmap createPreviewPixmap(const QDesignerFormWindowInterface *fw, const PreviewConfiguration &pc, int deviceProfileIndex /*=-1*/, QString *errorMessage);
+ // Convenience that creates a pixmap using a configuration taken from the settings.
+ QPixmap createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &style, int deviceProfileIndex /*=-1*/, QString *errorMessage);
+ QPixmap createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &style, QString *errorMessage);
+
+ virtual bool eventFilter(QObject *watched, QEvent *event);
+
+public slots:
+ void closeAllPreviews();
+
+signals:
+ void firstPreviewOpened();
+ void lastPreviewClosed();
+
+private slots:
+ void slotZoomChanged(int);
+
+private:
+
+ virtual Qt::WindowFlags previewWindowFlags(const QWidget *widget) const;
+ virtual QWidget *createDeviceSkinContainer(const QDesignerFormWindowInterface *) const;
+
+ QWidget *raise(const QDesignerFormWindowInterface *, const PreviewConfiguration &pc);
+ QWidget *createPreview(const QDesignerFormWindowInterface *,
+ const PreviewConfiguration &pc,
+ int deviceProfileIndex /* = -1 */,
+ QString *errorMessage,
+ /*Disabled by default, <0 */
+ int initialZoom = -1);
+
+ void updatePreviewClosed(QWidget *w);
+
+ PreviewManagerPrivate *d;
+
+ PreviewManager(const PreviewManager &other);
+ PreviewManager &operator =(const PreviewManager &other);
+};
+}
+
+QT_END_NAMESPACE
+
+#endif // PREVIEWMANAGER_H
diff --git a/tools/designer/src/lib/shared/promotionmodel.cpp b/tools/designer/src/lib/shared/promotionmodel.cpp
new file mode 100644
index 0000000000..77d0bbbcb1
--- /dev/null
+++ b/tools/designer/src/lib/shared/promotionmodel.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::PromotionModel
+*/
+
+#include "promotionmodel_p.h"
+#include "widgetdatabase_p.h"
+
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QDesignerPromotionInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QStandardItem>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ typedef QList<QStandardItem *> StandardItemList;
+
+ // Model columns.
+ enum { ClassNameColumn, IncludeFileColumn, IncludeTypeColumn, ReferencedColumn, NumColumns };
+
+ // Create a model row.
+ StandardItemList modelRow() {
+ StandardItemList rc;
+ for (int i = 0; i < NumColumns; i++) {
+ rc.push_back(new QStandardItem());
+ }
+ return rc;
+ }
+
+ // Create a model row for a base class (read-only, cannot be selected).
+ StandardItemList baseModelRow(const QDesignerWidgetDataBaseItemInterface *dbItem) {
+ StandardItemList rc = modelRow();
+
+ rc[ClassNameColumn]->setText(dbItem->name());
+ for (int i = 0; i < NumColumns; i++) {
+ rc[i]->setFlags(Qt::ItemIsEnabled);
+ }
+ return rc;
+ }
+
+ // Create an editable model row for a promoted class.
+ StandardItemList promotedModelRow(const QDesignerWidgetDataBaseInterface *widgetDataBase,
+ QDesignerWidgetDataBaseItemInterface *dbItem,
+ bool referenced = false) {
+
+ const int index = widgetDataBase->indexOf(dbItem);
+
+ // Associate user data: database index and enabled flag
+ QVariantList userDataList;
+ userDataList.push_back(QVariant(index));
+ userDataList.push_back(QVariant(referenced));
+ const QVariant userData(userDataList);
+
+ StandardItemList rc = modelRow();
+ // name
+ rc[ClassNameColumn]->setText(dbItem->name());
+ rc[ClassNameColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable);
+ rc[ClassNameColumn]->setData(userData);
+ // header
+ const qdesigner_internal::IncludeSpecification spec = qdesigner_internal::includeSpecification(dbItem->includeFile());
+ rc[IncludeFileColumn]->setText(spec.first);
+ rc[IncludeFileColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable);
+ rc[IncludeFileColumn]->setData(userData);
+ // global include
+ rc[IncludeTypeColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable|Qt::ItemIsUserCheckable);
+ rc[IncludeTypeColumn]->setData(userData);
+ rc[IncludeTypeColumn]->setCheckState(spec.second == qdesigner_internal::IncludeGlobal ? Qt::Checked : Qt::Unchecked);
+ // referenced
+ rc[ReferencedColumn]->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled);
+ rc[ClassNameColumn]->setData(userData);
+ if (!referenced) {
+ //: Usage of promoted widgets
+ static const QString notUsed = QCoreApplication::translate("PromotionModel", "Not used");
+ rc[ReferencedColumn]->setText(notUsed);
+ }
+ return rc;
+ }
+}
+
+namespace qdesigner_internal {
+
+ PromotionModel::PromotionModel(QDesignerFormEditorInterface *core) :
+ m_core(core)
+ {
+ connect(this, SIGNAL(itemChanged(QStandardItem *)), this, SLOT(slotItemChanged(QStandardItem *)));
+ }
+
+ void PromotionModel::initializeHeaders() {
+ setColumnCount(NumColumns);
+ QStringList horizontalLabels(tr("Name"));
+ horizontalLabels += tr("Header file");
+ horizontalLabels += tr("Global include");
+ horizontalLabels += tr("Usage");
+ setHorizontalHeaderLabels (horizontalLabels);
+ }
+
+ void PromotionModel::updateFromWidgetDatabase() {
+ typedef QDesignerPromotionInterface::PromotedClasses PromotedClasses;
+
+ clear();
+ initializeHeaders();
+
+ // retrieve list of pairs from DB and convert into a tree structure.
+ // Set the item index as user data on the item.
+ const PromotedClasses promotedClasses = m_core->promotion()->promotedClasses();
+
+ if (promotedClasses.empty())
+ return;
+
+ const QSet<QString> usedPromotedClasses = m_core->promotion()->referencedPromotedClassNames();
+
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase();
+ QDesignerWidgetDataBaseItemInterface *baseClass = 0;
+ QStandardItem *baseItem = 0;
+
+ const PromotedClasses::const_iterator bcend = promotedClasses.constEnd();
+ for (PromotedClasses::const_iterator it = promotedClasses.constBegin(); it != bcend; ++it) {
+ // Start a new base class?
+ if (baseClass != it->baseItem) {
+ baseClass = it->baseItem;
+ const StandardItemList baseRow = baseModelRow(it->baseItem);
+ baseItem = baseRow.front();
+ appendRow(baseRow);
+ }
+ Q_ASSERT(baseItem);
+ // Append derived
+ baseItem->appendRow(promotedModelRow(widgetDataBase, it->promotedItem, usedPromotedClasses.contains(it->promotedItem->name())));
+ }
+ }
+
+ void PromotionModel::slotItemChanged(QStandardItem * changedItem) {
+ // Retrieve DB item
+ bool referenced;
+ QDesignerWidgetDataBaseItemInterface *dbItem = databaseItem(changedItem, &referenced);
+ Q_ASSERT(dbItem);
+ // Change header or type
+ switch (changedItem->column()) {
+ case ClassNameColumn:
+ emit classNameChanged(dbItem, changedItem->text());
+ break;
+ case IncludeTypeColumn:
+ case IncludeFileColumn: {
+ // Get both file and type items via parent.
+ const QStandardItem *baseClassItem = changedItem->parent();
+ const QStandardItem *fileItem = baseClassItem->child(changedItem->row(), IncludeFileColumn);
+ const QStandardItem *typeItem = baseClassItem->child(changedItem->row(), IncludeTypeColumn);
+ emit includeFileChanged(dbItem, buildIncludeFile(fileItem->text(), typeItem->checkState() == Qt::Checked ? IncludeGlobal : IncludeLocal));
+ }
+ break;
+ }
+ }
+
+ QDesignerWidgetDataBaseItemInterface *PromotionModel::databaseItemAt(const QModelIndex &index, bool *referenced) const {
+ if (const QStandardItem *item = itemFromIndex (index))
+ return databaseItem(item, referenced);
+
+ *referenced = false;
+ return 0;
+ }
+
+ QDesignerWidgetDataBaseItemInterface *PromotionModel::databaseItem(const QStandardItem * item, bool *referenced) const {
+ // Decode user data associated with item.
+ const QVariant data = item->data();
+ if (data.type() != QVariant::List) {
+ *referenced = false;
+ return 0;
+ }
+
+ const QVariantList dataList = data.toList();
+ const int index = dataList[0].toInt();
+ *referenced = dataList[1].toBool();
+ return m_core->widgetDataBase()->item(index);
+ }
+
+ QModelIndex PromotionModel::indexOfClass(const QString &className) const {
+ const StandardItemList matches = findItems (className, Qt::MatchFixedString|Qt::MatchCaseSensitive|Qt::MatchRecursive);
+ return matches.empty() ? QModelIndex() : indexFromItem (matches.front());
+ }
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/promotionmodel_p.h b/tools/designer/src/lib/shared/promotionmodel_p.h
new file mode 100644
index 0000000000..d5843fc616
--- /dev/null
+++ b/tools/designer/src/lib/shared/promotionmodel_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PROMOTIONMODEL_H
+#define PROMOTIONMODEL_H
+
+#include <QtGui/QStandardItemModel>
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerWidgetDataBaseItemInterface;
+
+namespace qdesigner_internal {
+
+ // Item model representing the promoted widgets.
+ class PromotionModel : public QStandardItemModel {
+ Q_OBJECT
+
+ public:
+ explicit PromotionModel(QDesignerFormEditorInterface *core);
+
+ void updateFromWidgetDatabase();
+
+ // Return item at model index or 0.
+ QDesignerWidgetDataBaseItemInterface *databaseItemAt(const QModelIndex &, bool *referenced) const;
+
+ QModelIndex indexOfClass(const QString &className) const;
+
+ signals:
+ void includeFileChanged(QDesignerWidgetDataBaseItemInterface *, const QString &includeFile);
+ void classNameChanged(QDesignerWidgetDataBaseItemInterface *, const QString &newName);
+
+ private slots:
+ void slotItemChanged(QStandardItem * item);
+
+ private:
+ void initializeHeaders();
+ // Retrieve data base item of item or return 0.
+ QDesignerWidgetDataBaseItemInterface *databaseItem(const QStandardItem * item, bool *referenced) const;
+
+ QDesignerFormEditorInterface *m_core;
+ };
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PROMOTIONMODEL_H
diff --git a/tools/designer/src/lib/shared/promotiontaskmenu.cpp b/tools/designer/src/lib/shared/promotiontaskmenu.cpp
new file mode 100644
index 0000000000..e458aabada
--- /dev/null
+++ b/tools/designer/src/lib/shared/promotiontaskmenu.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "promotiontaskmenu_p.h"
+#include "qdesigner_promotiondialog_p.h"
+#include "widgetfactory_p.h"
+#include "metadatabase_p.h"
+#include "widgetdatabase_p.h"
+#include "qdesigner_command_p.h"
+#include "signalslotdialog_p.h"
+#include "qdesigner_objectinspector_p.h"
+#include "abstractintrospection_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QAction>
+#include <QtGui/QWidget>
+#include <QtGui/QMenu>
+#include <QtCore/QSignalMapper>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+static QAction *separatorAction(QObject *parent)
+{
+ QAction *rc = new QAction(parent);
+ rc->setSeparator(true);
+ return rc;
+}
+
+static inline QDesignerLanguageExtension *languageExtension(QDesignerFormEditorInterface *core)
+{
+ return qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core);
+}
+
+namespace qdesigner_internal {
+
+PromotionTaskMenu::PromotionTaskMenu(QWidget *widget,Mode mode, QObject *parent) :
+ QObject(parent),
+ m_mode(mode),
+ m_widget(widget),
+ m_promotionMapper(0),
+ m_globalEditAction(new QAction(tr("Promoted widgets..."), this)),
+ m_EditPromoteToAction(new QAction(tr("Promote to ..."), this)),
+ m_EditSignalsSlotsAction(new QAction(tr("Change signals/slots..."), this)),
+ m_promoteLabel(tr("Promote to")),
+ m_demoteLabel(tr("Demote to %1"))
+{
+ connect(m_globalEditAction, SIGNAL(triggered()), this, SLOT(slotEditPromotedWidgets()));
+ connect(m_EditPromoteToAction, SIGNAL(triggered()), this, SLOT(slotEditPromoteTo()));
+ connect(m_EditSignalsSlotsAction, SIGNAL(triggered()), this, SLOT(slotEditSignalsSlots()));
+}
+
+PromotionTaskMenu::Mode PromotionTaskMenu::mode() const
+{
+ return m_mode;
+}
+
+void PromotionTaskMenu::setMode(Mode m)
+{
+ m_mode = m;
+}
+
+void PromotionTaskMenu::setWidget(QWidget *widget)
+{
+ m_widget = widget;
+}
+
+void PromotionTaskMenu::setPromoteLabel(const QString &promoteLabel)
+{
+ m_promoteLabel = promoteLabel;
+}
+
+void PromotionTaskMenu::setEditPromoteToLabel(const QString &promoteEditLabel)
+{
+ m_EditPromoteToAction->setText(promoteEditLabel);
+}
+
+void PromotionTaskMenu::setDemoteLabel(const QString &demoteLabel)
+{
+ m_demoteLabel = demoteLabel;
+}
+
+PromotionTaskMenu::PromotionState PromotionTaskMenu::createPromotionActions(QDesignerFormWindowInterface *formWindow)
+{
+ // clear out old
+ if (!m_promotionActions.empty()) {
+ qDeleteAll(m_promotionActions);
+ m_promotionActions.clear();
+ }
+ // No promotion of main container
+ if (formWindow->mainContainer() == m_widget)
+ return NotApplicable;
+
+ // Check for a homogenous selection
+ const PromotionSelectionList promotionSelection = promotionSelectionList(formWindow);
+
+ if (promotionSelection.empty())
+ return NoHomogenousSelection;
+
+ QDesignerFormEditorInterface *core = formWindow->core();
+ // if it is promoted: demote only.
+ if (isPromoted(formWindow->core(), m_widget)) {
+ const QString label = m_demoteLabel.arg( promotedExtends(core , m_widget));
+ QAction *demoteAction = new QAction(label, this);
+ connect(demoteAction, SIGNAL(triggered()), this, SLOT(slotDemoteFromCustomWidget()));
+ m_promotionActions.push_back(demoteAction);
+ return CanDemote;
+ }
+ // figure out candidates
+ const QString baseClassName = WidgetFactory::classNameOf(core, m_widget);
+ const WidgetDataBaseItemList candidates = promotionCandidates(core->widgetDataBase(), baseClassName );
+ if (candidates.empty()) {
+ // Is this thing promotable at all?
+ return QDesignerPromotionDialog::baseClassNames(core->promotion()).contains(baseClassName) ? CanPromote : NotApplicable;
+ }
+ // Set up a signal mapper to associate class names
+ if (!m_promotionMapper) {
+ m_promotionMapper = new QSignalMapper(this);
+ connect(m_promotionMapper, SIGNAL(mapped(QString)), this, SLOT(slotPromoteToCustomWidget(QString)));
+ }
+
+ QMenu *candidatesMenu = new QMenu();
+ // Create a sub menu
+ const WidgetDataBaseItemList::const_iterator cend = candidates.constEnd();
+ // Set up actions and map class names
+ for (WidgetDataBaseItemList::const_iterator it = candidates.constBegin(); it != cend; ++it) {
+ const QString customClassName = (*it)->name();
+ QAction *action = new QAction((*it)->name(), this);
+ connect(action, SIGNAL(triggered()), m_promotionMapper, SLOT(map()));
+ m_promotionMapper->setMapping(action, customClassName);
+ candidatesMenu->addAction(action);
+ }
+ // Sub menu action
+ QAction *subMenuAction = new QAction(m_promoteLabel, this);
+ subMenuAction->setMenu(candidatesMenu);
+ m_promotionActions.push_back(subMenuAction);
+ return CanPromote;
+}
+
+void PromotionTaskMenu::addActions(unsigned separatorFlags, ActionList &actionList)
+{
+ addActions(formWindow(), separatorFlags, actionList);
+}
+
+void PromotionTaskMenu::addActions(QDesignerFormWindowInterface *fw, unsigned flags,
+ ActionList &actionList)
+{
+ Q_ASSERT(m_widget);
+ const int previousSize = actionList.size();
+ const PromotionState promotionState = createPromotionActions(fw);
+
+ // Promotion candidates/demote
+ actionList += m_promotionActions;
+
+ // Edit action depending on context
+ switch (promotionState) {
+ case CanPromote:
+ actionList += m_EditPromoteToAction;
+ break;
+ case CanDemote:
+ if (!(flags & SuppressGlobalEdit))
+ actionList += m_globalEditAction;
+ if (!languageExtension(fw->core())) {
+ actionList += separatorAction(this);
+ actionList += m_EditSignalsSlotsAction;
+ }
+ break;
+ default:
+ if (!(flags & SuppressGlobalEdit))
+ actionList += m_globalEditAction;
+ break;
+ }
+ // Add separators if required
+ if (actionList.size() > previousSize) {
+ if (flags & LeadingSeparator)
+ actionList.insert(previousSize, separatorAction(this));
+ if (flags & TrailingSeparator)
+ actionList += separatorAction(this);
+ }
+}
+
+void PromotionTaskMenu::addActions(QDesignerFormWindowInterface *fw, unsigned flags, QMenu *menu)
+{
+ ActionList actionList;
+ addActions(fw, flags, actionList);
+ menu->addActions(actionList);
+}
+
+void PromotionTaskMenu::addActions(unsigned flags, QMenu *menu)
+{
+ addActions(formWindow(), flags, menu);
+}
+
+void PromotionTaskMenu::promoteTo(QDesignerFormWindowInterface *fw, const QString &customClassName)
+{
+ Q_ASSERT(m_widget);
+ PromoteToCustomWidgetCommand *cmd = new PromoteToCustomWidgetCommand(fw);
+ cmd->init(promotionSelectionList(fw), customClassName);
+ fw->commandHistory()->push(cmd);
+}
+
+
+void PromotionTaskMenu::slotPromoteToCustomWidget(const QString &customClassName)
+{
+ promoteTo(formWindow(), customClassName);
+}
+
+void PromotionTaskMenu::slotDemoteFromCustomWidget()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ const PromotionSelectionList promotedWidgets = promotionSelectionList(fw);
+ Q_ASSERT(!promotedWidgets.empty() && isPromoted(fw->core(), promotedWidgets.front()));
+
+ // ### use the undo stack
+ DemoteFromCustomWidgetCommand *cmd = new DemoteFromCustomWidgetCommand(fw);
+ cmd->init(promotedWidgets);
+ fw->commandHistory()->push(cmd);
+}
+
+void PromotionTaskMenu::slotEditPromoteTo()
+{
+ Q_ASSERT(m_widget);
+ // Check whether invoked over a promotable widget
+ QDesignerFormWindowInterface *fw = formWindow();
+ QDesignerFormEditorInterface *core = fw->core();
+ const QString base_class_name = WidgetFactory::classNameOf(core, m_widget);
+ Q_ASSERT(QDesignerPromotionDialog::baseClassNames(core->promotion()).contains(base_class_name));
+ // Show over promotable widget
+ QString promoteToClassName;
+ QDialog *promotionEditor = 0;
+ if (QDesignerLanguageExtension *lang = languageExtension(core))
+ promotionEditor = lang->createPromotionDialog(core, base_class_name, &promoteToClassName, fw);
+ if (!promotionEditor)
+ promotionEditor = new QDesignerPromotionDialog(core, fw, base_class_name, &promoteToClassName);
+ if (promotionEditor->exec() == QDialog::Accepted && !promoteToClassName.isEmpty()) {
+ promoteTo(fw, promoteToClassName);
+ }
+ delete promotionEditor;
+}
+
+void PromotionTaskMenu::slotEditPromotedWidgets()
+{
+ // Global context, show over non-promotable widget
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+ editPromotedWidgets(fw->core(), fw);
+}
+
+PromotionTaskMenu::PromotionSelectionList PromotionTaskMenu::promotionSelectionList(QDesignerFormWindowInterface *formWindow) const
+{
+ // In multi selection mode, check for a homogenous selection (same class, same promotion state)
+ // and return the list if this is the case. Also make sure m_widget
+ // is the last widget in the list so that it is re-selected as the last
+ // widget by the promotion commands.
+
+ PromotionSelectionList rc;
+
+ if (m_mode != ModeSingleWidget) {
+ QDesignerFormEditorInterface *core = formWindow->core();
+ const QDesignerIntrospectionInterface *intro = core->introspection();
+ const QString className = intro->metaObject(m_widget)->className();
+ const bool promoted = isPromoted(formWindow->core(), m_widget);
+ // Just in case someone plugged an old-style Object Inspector
+ if (QDesignerObjectInspector *designerObjectInspector = qobject_cast<QDesignerObjectInspector *>(core->objectInspector())) {
+ Selection s;
+ designerObjectInspector->getSelection(s);
+ // Find objects of similar state
+ const QWidgetList &source = m_mode == ModeManagedMultiSelection ? s.managed : s.unmanaged;
+ const QWidgetList::const_iterator cend = source.constEnd();
+ for (QWidgetList::const_iterator it = source.constBegin(); it != cend; ++it) {
+ QWidget *w = *it;
+ if (w != m_widget) {
+ // Selection state mismatch
+ if (intro->metaObject(w)->className() != className || isPromoted(core, w) != promoted)
+ return PromotionSelectionList();
+ rc.push_back(w);
+ }
+ }
+ }
+ }
+
+ rc.push_back(m_widget);
+ return rc;
+}
+
+QDesignerFormWindowInterface *PromotionTaskMenu::formWindow() const
+{
+ // Use the QObject overload of QDesignerFormWindowInterface::findFormWindow since that works
+ // for QDesignerMenus also.
+ QObject *o = m_widget;
+ QDesignerFormWindowInterface *result = QDesignerFormWindowInterface::findFormWindow(o);
+ Q_ASSERT(result != 0);
+ return result;
+}
+
+void PromotionTaskMenu::editPromotedWidgets(QDesignerFormEditorInterface *core, QWidget* parent) {
+ QDesignerLanguageExtension *lang = languageExtension(core);
+ // Show over non-promotable widget
+ QDialog *promotionEditor = 0;
+ if (lang)
+ lang->createPromotionDialog(core, parent);
+ if (!promotionEditor)
+ promotionEditor = new QDesignerPromotionDialog(core, parent);
+ promotionEditor->exec();
+ delete promotionEditor;
+}
+
+void PromotionTaskMenu::slotEditSignalsSlots()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+ SignalSlotDialog::editPromotedClass(fw->core(), m_widget, fw);
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/promotiontaskmenu_p.h b/tools/designer/src/lib/shared/promotiontaskmenu_p.h
new file mode 100644
index 0000000000..223ce48c30
--- /dev/null
+++ b/tools/designer/src/lib/shared/promotiontaskmenu_p.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PROMOTIONTASKMENU_H
+#define PROMOTIONTASKMENU_H
+
+#include "shared_global_p.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+
+class QAction;
+class QMenu;
+class QWidget;
+class QSignalMapper;
+
+namespace qdesigner_internal {
+
+// A helper class for creating promotion context menus and handling promotion actions.
+
+class QDESIGNER_SHARED_EXPORT PromotionTaskMenu: public QObject
+{
+ Q_OBJECT
+public:
+ enum Mode {
+ ModeSingleWidget,
+ ModeManagedMultiSelection,
+ ModeUnmanagedMultiSelection
+ };
+
+ explicit PromotionTaskMenu(QWidget *widget,Mode mode = ModeManagedMultiSelection, QObject *parent = 0);
+
+ Mode mode() const;
+ void setMode(Mode m);
+
+ void setWidget(QWidget *widget);
+
+ // Set menu labels
+ void setPromoteLabel(const QString &promoteLabel);
+ void setEditPromoteToLabel(const QString &promoteEditLabel);
+ // Defaults to "Demote to %1".arg(class).
+ void setDemoteLabel(const QString &demoteLabel);
+
+ typedef QList<QAction*> ActionList;
+
+ enum AddFlags { LeadingSeparator = 1, TrailingSeparator = 2, SuppressGlobalEdit = 4};
+
+ // Adds a list of promotion actions according to the current promotion state of the widget.
+ void addActions(QDesignerFormWindowInterface *fw, unsigned flags, ActionList &actionList);
+ // Convenience that finds the form window.
+ void addActions(unsigned flags, ActionList &actionList);
+
+ void addActions(QDesignerFormWindowInterface *fw, unsigned flags, QMenu *menu);
+ void addActions(unsigned flags, QMenu *menu);
+
+ // Pop up the editor in a global context.
+ static void editPromotedWidgets(QDesignerFormEditorInterface *core, QWidget* parent);
+
+private slots:
+ void slotPromoteToCustomWidget(const QString &customClassName);
+ void slotDemoteFromCustomWidget();
+ void slotEditPromotedWidgets();
+ void slotEditPromoteTo();
+ void slotEditSignalsSlots();
+
+private:
+ void promoteTo(QDesignerFormWindowInterface *fw, const QString &customClassName);
+
+ enum PromotionState { NotApplicable, NoHomogenousSelection, CanPromote, CanDemote };
+ PromotionState createPromotionActions(QDesignerFormWindowInterface *formWindow);
+ QDesignerFormWindowInterface *formWindow() const;
+
+ typedef QList<QPointer<QWidget> > PromotionSelectionList;
+ PromotionSelectionList promotionSelectionList(QDesignerFormWindowInterface *formWindow) const;
+
+ Mode m_mode;
+
+ QPointer<QWidget> m_widget;
+
+ QSignalMapper *m_promotionMapper;
+ // Per-Widget actions
+ QList<QAction *> m_promotionActions;
+
+ QAction *m_globalEditAction;
+ QAction *m_EditPromoteToAction;
+ QAction *m_EditSignalsSlotsAction;
+
+ QString m_promoteLabel;
+ QString m_demoteLabel;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PROMOTIONTASKMENU_H
diff --git a/tools/designer/src/lib/shared/propertylineedit.cpp b/tools/designer/src/lib/shared/propertylineedit.cpp
new file mode 100644
index 0000000000..a3b1efa940
--- /dev/null
+++ b/tools/designer/src/lib/shared/propertylineedit.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "propertylineedit_p.h"
+
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMenu>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ PropertyLineEdit::PropertyLineEdit(QWidget *parent) :
+ QLineEdit(parent), m_wantNewLine(false)
+ {
+ }
+
+ bool PropertyLineEdit::event(QEvent *e)
+ {
+ // handle 'Select all' here as it is not done in the QLineEdit
+ if (e->type() == QEvent::ShortcutOverride && !isReadOnly()) {
+ QKeyEvent* ke = static_cast<QKeyEvent*> (e);
+ if (ke->modifiers() & Qt::ControlModifier) {
+ if(ke->key() == Qt::Key_A) {
+ ke->accept();
+ return true;
+ }
+ }
+ }
+ return QLineEdit::event(e);
+ }
+
+ void PropertyLineEdit::insertNewLine() {
+ insertText(QLatin1String("\\n"));
+ }
+
+ void PropertyLineEdit::insertText(const QString &text) {
+ // position cursor after new text and grab focus
+ const int oldCursorPosition = cursorPosition ();
+ insert(text);
+ setCursorPosition (oldCursorPosition + text.length());
+ setFocus(Qt::OtherFocusReason);
+ }
+
+ void PropertyLineEdit::contextMenuEvent(QContextMenuEvent *event) {
+ QMenu *menu = createStandardContextMenu ();
+
+ if (m_wantNewLine) {
+ menu->addSeparator();
+ QAction* nlAction = menu->addAction(tr("Insert line break"));
+ connect(nlAction, SIGNAL(triggered()), this, SLOT(insertNewLine()));
+ }
+
+ menu->exec(event->globalPos());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/propertylineedit_p.h b/tools/designer/src/lib/shared/propertylineedit_p.h
new file mode 100644
index 0000000000..42f0b3c930
--- /dev/null
+++ b/tools/designer/src/lib/shared/propertylineedit_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PROPERTYLINEEDIT_H
+#define PROPERTYLINEEDIT_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QLineEdit>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ // A line edit with a special context menu allowing for adding (escaped) new lines
+ class PropertyLineEdit : public QLineEdit {
+ Q_OBJECT
+ public:
+ explicit PropertyLineEdit(QWidget *parent);
+ void setWantNewLine(bool nl) { m_wantNewLine = nl; }
+ bool wantNewLine() const { return m_wantNewLine; }
+
+ bool event(QEvent *e);
+ protected:
+ void contextMenuEvent (QContextMenuEvent *event );
+ private slots:
+ void insertNewLine();
+ private:
+ void insertText(const QString &);
+ bool m_wantNewLine;
+ };
+}
+
+QT_END_NAMESPACE
+
+#endif // PROPERTYLINEEDIT_H
diff --git a/tools/designer/src/lib/shared/qdesigner_command.cpp b/tools/designer/src/lib/shared/qdesigner_command.cpp
new file mode 100644
index 0000000000..81d5917e80
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_command.cpp
@@ -0,0 +1,2968 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_command_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "qdesigner_utils_p.h"
+#include "layout_p.h"
+#include "qlayout_widget_p.h"
+#include "qdesigner_widget_p.h"
+#include "qdesigner_menu_p.h"
+#include "shared_enums_p.h"
+#include "metadatabase_p.h"
+#include "formwindowbase_p.h"
+#include <abstractformbuilder.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerActionEditorInterface>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerLayoutDecorationExtension>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtDesigner/QDesignerIntegrationInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtCore/qdebug.h>
+#include <QtCore/QTextStream>
+#include <QtCore/QQueue>
+
+#include <QtGui/QMenuBar>
+#include <QtGui/QStatusBar>
+#include <QtGui/QToolBar>
+#include <QtGui/QToolBox>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QTabWidget>
+#include <QtGui/QTableWidget>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QListWidget>
+#include <QtGui/QComboBox>
+#include <QtGui/QSplitter>
+#include <QtGui/QDockWidget>
+#include <QtGui/QMainWindow>
+#include <QtGui/QWizardPage>
+#include <QtGui/QApplication>
+#include <QtGui/QFormLayout>
+
+Q_DECLARE_METATYPE(QWidgetList)
+
+QT_BEGIN_NAMESPACE
+
+static inline void setPropertySheetWindowTitle(const QDesignerFormEditorInterface *core, QObject *o, const QString &t)
+{
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), o)) {
+ const int idx = sheet->indexOf(QLatin1String("windowTitle"));
+ if (idx != -1) {
+ sheet->setProperty(idx, t);
+ sheet->setChanged(idx, true);
+ }
+ }
+}
+
+namespace qdesigner_internal {
+
+// Helpers for the dynamic properties that store Z/Widget order
+static const char *widgetOrderPropertyC = "_q_widgetOrder";
+static const char *zOrderPropertyC = "_q_zOrder";
+
+static void addToWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name, int index = -1)
+{
+ QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name));
+ list.removeAll(widget);
+ if (index >= 0 && index < list.size()) {
+ list.insert(index, widget);
+ } else {
+ list.append(widget);
+ }
+ parentWidget->setProperty(name, qVariantFromValue(list));
+}
+
+static int removeFromWidgetListDynamicProperty(QWidget *parentWidget, QWidget *widget, const char *name)
+{
+ QWidgetList list = qVariantValue<QWidgetList>(parentWidget->property(name));
+ const int firstIndex = list.indexOf(widget);
+ if (firstIndex != -1) {
+ list.removeAll(widget);
+ parentWidget->setProperty(name, qVariantFromValue(list));
+ }
+ return firstIndex;
+}
+
+// ---- InsertWidgetCommand ----
+InsertWidgetCommand::InsertWidgetCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_insertMode(QDesignerLayoutDecorationExtension::InsertWidgetMode),
+ m_layoutHelper(0),
+ m_widgetWasManaged(false)
+{
+}
+
+InsertWidgetCommand::~InsertWidgetCommand()
+{
+ delete m_layoutHelper;
+}
+
+void InsertWidgetCommand::init(QWidget *widget, bool already_in_form, int layoutRow, int layoutColumn)
+{
+ m_widget = widget;
+
+ setText(QApplication::translate("Command", "Insert '%1'").arg(widget->objectName()));
+
+ QWidget *parentWidget = m_widget->parentWidget();
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core->extensionManager(), parentWidget);
+
+ m_insertMode = deco ? deco->currentInsertMode() : QDesignerLayoutDecorationExtension::InsertWidgetMode;
+ if (layoutRow >= 0 && layoutColumn >= 0) {
+ m_cell.first = layoutRow;
+ m_cell.second = layoutColumn;
+ } else {
+ m_cell = deco ? deco->currentCell() : qMakePair(0, 0);
+ }
+ m_widgetWasManaged = already_in_form;
+}
+
+static void recursiveUpdate(QWidget *w)
+{
+ w->update();
+
+ const QObjectList &l = w->children();
+ const QObjectList::const_iterator cend = l.end();
+ for ( QObjectList::const_iterator it = l.begin(); it != cend; ++it) {
+ if (QWidget *w = qobject_cast<QWidget*>(*it))
+ recursiveUpdate(w);
+ }
+}
+
+void InsertWidgetCommand::redo()
+{
+ QWidget *parentWidget = m_widget->parentWidget();
+ Q_ASSERT(parentWidget);
+
+ addToWidgetListDynamicProperty(parentWidget, m_widget, widgetOrderPropertyC);
+ addToWidgetListDynamicProperty(parentWidget, m_widget, zOrderPropertyC);
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core->extensionManager(), parentWidget);
+
+ if (deco != 0) {
+ const LayoutInfo::Type type = LayoutInfo::layoutType(core, LayoutInfo::managedLayout(core, parentWidget));
+ m_layoutHelper = LayoutHelper::createLayoutHelper(type);
+ m_layoutHelper->pushState(core, parentWidget);
+ if (type == LayoutInfo::Grid) {
+ switch (m_insertMode) {
+ case QDesignerLayoutDecorationExtension::InsertRowMode: {
+ deco->insertRow(m_cell.first);
+ } break;
+
+ case QDesignerLayoutDecorationExtension::InsertColumnMode: {
+ deco->insertColumn(m_cell.second);
+ } break;
+
+ default: break;
+ } // end switch
+ }
+ deco->insertWidget(m_widget, m_cell);
+ }
+
+ if (!m_widgetWasManaged)
+ formWindow()->manageWidget(m_widget);
+ m_widget->show();
+ formWindow()->emitSelectionChanged();
+
+ if (parentWidget && parentWidget->layout()) {
+ recursiveUpdate(parentWidget);
+ parentWidget->layout()->invalidate();
+ }
+
+ refreshBuddyLabels();
+}
+
+void InsertWidgetCommand::undo()
+{
+ QWidget *parentWidget = m_widget->parentWidget();
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core->extensionManager(), parentWidget);
+
+ if (deco) {
+ deco->removeWidget(m_widget);
+ m_layoutHelper->popState(core, parentWidget);
+ }
+
+ if (!m_widgetWasManaged) {
+ formWindow()->unmanageWidget(m_widget);
+ m_widget->hide();
+ }
+
+ removeFromWidgetListDynamicProperty(parentWidget, m_widget, widgetOrderPropertyC);
+ removeFromWidgetListDynamicProperty(parentWidget, m_widget, zOrderPropertyC);
+
+ formWindow()->emitSelectionChanged();
+
+ refreshBuddyLabels();
+}
+
+void InsertWidgetCommand::refreshBuddyLabels()
+{
+ typedef QList<QLabel*> LabelList;
+
+ const LabelList label_list = qFindChildren<QLabel*>(formWindow());
+ if (label_list.empty())
+ return;
+
+ const QString buddyProperty = QLatin1String("buddy");
+ const QByteArray objectNameU8 = m_widget->objectName().toUtf8();
+ // Re-set the buddy (The sheet locates the object by name and sets it)
+ const LabelList::const_iterator cend = label_list.constEnd();
+ for (LabelList::const_iterator it = label_list.constBegin(); it != cend; ++it ) {
+ if (QDesignerPropertySheetExtension* sheet = propertySheet(*it)) {
+ const int idx = sheet->indexOf(buddyProperty);
+ if (idx != -1) {
+ const QVariant value = sheet->property(idx);
+ if (value.toByteArray() == objectNameU8)
+ sheet->setProperty(idx, value);
+ }
+ }
+ }
+}
+
+// ---- ChangeZOrderCommand ----
+ChangeZOrderCommand::ChangeZOrderCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QString(), formWindow)
+{
+}
+
+void ChangeZOrderCommand::init(QWidget *widget)
+{
+ Q_ASSERT(widget);
+
+ m_widget = widget;
+
+ setText(QApplication::translate("Command", "Change Z-order of '%1'").arg(widget->objectName()));
+
+ m_oldParentZOrder = qVariantValue<QWidgetList>(widget->parentWidget()->property("_q_zOrder"));
+ const int index = m_oldParentZOrder.indexOf(m_widget);
+ if (index != -1 && index + 1 < m_oldParentZOrder.count())
+ m_oldPreceding = m_oldParentZOrder.at(index + 1);
+}
+
+void ChangeZOrderCommand::redo()
+{
+ m_widget->parentWidget()->setProperty("_q_zOrder", qVariantFromValue(reorderWidget(m_oldParentZOrder, m_widget)));
+
+ reorder(m_widget);
+}
+
+void ChangeZOrderCommand::undo()
+{
+ m_widget->parentWidget()->setProperty("_q_zOrder", qVariantFromValue(m_oldParentZOrder));
+
+ if (m_oldPreceding)
+ m_widget->stackUnder(m_oldPreceding);
+ else
+ m_widget->raise();
+}
+
+// ---- RaiseWidgetCommand ----
+RaiseWidgetCommand::RaiseWidgetCommand(QDesignerFormWindowInterface *formWindow)
+ : ChangeZOrderCommand(formWindow)
+{
+}
+
+void RaiseWidgetCommand::init(QWidget *widget)
+{
+ ChangeZOrderCommand::init(widget);
+ setText(QApplication::translate("Command", "Raise '%1'").arg(widget->objectName()));
+}
+
+QWidgetList RaiseWidgetCommand::reorderWidget(const QWidgetList &list, QWidget *widget) const
+{
+ QWidgetList l = list;
+ l.removeAll(widget);
+ l.append(widget);
+ return l;
+}
+
+void RaiseWidgetCommand::reorder(QWidget *widget) const
+{
+ widget->raise();
+}
+
+// ---- LowerWidgetCommand ----
+LowerWidgetCommand::LowerWidgetCommand(QDesignerFormWindowInterface *formWindow)
+ : ChangeZOrderCommand(formWindow)
+{
+}
+
+QWidgetList LowerWidgetCommand::reorderWidget(const QWidgetList &list, QWidget *widget) const
+{
+ QWidgetList l = list;
+ l.removeAll(widget);
+ l.prepend(widget);
+ return l;
+}
+
+void LowerWidgetCommand::init(QWidget *widget)
+{
+ ChangeZOrderCommand::init(widget);
+ setText(QApplication::translate("Command", "Lower '%1'").arg(widget->objectName()));
+}
+
+void LowerWidgetCommand::reorder(QWidget *widget) const
+{
+ widget->lower();
+}
+
+// ---- ManageWidgetCommandHelper
+ManageWidgetCommandHelper::ManageWidgetCommandHelper() :
+ m_widget(0)
+{
+}
+
+void ManageWidgetCommandHelper::init(const QDesignerFormWindowInterface *fw, QWidget *widget)
+{
+ m_widget = widget;
+ m_managedChildren.clear();
+
+ const QWidgetList children = qFindChildren<QWidget *>(m_widget);
+ if (children.empty())
+ return;
+
+ m_managedChildren.reserve(children.size());
+ const QWidgetList::const_iterator lcend = children.constEnd();
+ for (QWidgetList::const_iterator it = children.constBegin(); it != lcend; ++it)
+ if (fw->isManaged(*it))
+ m_managedChildren.push_back(*it);
+}
+
+void ManageWidgetCommandHelper::init(QWidget *widget, const WidgetVector &managedChildren)
+{
+ m_widget = widget;
+ m_managedChildren = managedChildren;
+}
+
+void ManageWidgetCommandHelper::manage(QDesignerFormWindowInterface *fw)
+{
+ // Manage the managed children after parent
+ fw->manageWidget(m_widget);
+ if (!m_managedChildren.empty()) {
+ const WidgetVector::const_iterator lcend = m_managedChildren.constEnd();
+ for (WidgetVector::const_iterator it = m_managedChildren.constBegin(); it != lcend; ++it)
+ fw->manageWidget(*it);
+ }
+}
+
+void ManageWidgetCommandHelper::unmanage(QDesignerFormWindowInterface *fw)
+{
+ // Unmanage the managed children first
+ if (!m_managedChildren.empty()) {
+ const WidgetVector::const_iterator lcend = m_managedChildren.constEnd();
+ for (WidgetVector::const_iterator it = m_managedChildren.constBegin(); it != lcend; ++it)
+ fw->unmanageWidget(*it);
+ }
+ fw->unmanageWidget(m_widget);
+}
+
+// ---- DeleteWidgetCommand ----
+DeleteWidgetCommand::DeleteWidgetCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_layoutType(LayoutInfo::NoLayout),
+ m_layoutHelper(0),
+ m_flags(0),
+ m_splitterIndex(-1),
+ m_layoutSimplified(false),
+ m_formItem(0),
+ m_tabOrderIndex(-1),
+ m_widgetOrderIndex(-1),
+ m_zOrderIndex(-1)
+{
+}
+
+DeleteWidgetCommand::~DeleteWidgetCommand()
+{
+ delete m_layoutHelper;
+}
+
+void DeleteWidgetCommand::init(QWidget *widget, unsigned flags)
+{
+ m_widget = widget;
+ m_parentWidget = widget->parentWidget();
+ m_geometry = widget->geometry();
+ m_flags = flags;
+ m_layoutType = LayoutInfo::NoLayout;
+ m_splitterIndex = -1;
+ bool isManaged; // Check for a managed layout
+ QLayout *layout;
+ m_layoutType = LayoutInfo::laidoutWidgetType(formWindow()->core(), m_widget, &isManaged, &layout);
+ if (!isManaged)
+ m_layoutType = LayoutInfo::NoLayout;
+ switch (m_layoutType) {
+ case LayoutInfo::HSplitter:
+ case LayoutInfo::VSplitter: {
+ QSplitter *splitter = qobject_cast<QSplitter *>(m_parentWidget);
+ Q_ASSERT(splitter);
+ m_splitterIndex = splitter->indexOf(widget);
+ }
+ break;
+ case LayoutInfo::NoLayout:
+ break;
+ default:
+ m_layoutHelper = LayoutHelper::createLayoutHelper(m_layoutType);
+ m_layoutPosition = m_layoutHelper->itemInfo(layout, m_widget);
+ break;
+ }
+
+ m_formItem = formWindow()->core()->metaDataBase()->item(formWindow());
+ m_tabOrderIndex = m_formItem->tabOrder().indexOf(widget);
+
+ // Build the list of managed children
+ m_manageHelper.init(formWindow(), m_widget);
+
+ setText(QApplication::translate("Command", "Delete '%1'").arg(widget->objectName()));
+}
+
+void DeleteWidgetCommand::redo()
+{
+ formWindow()->clearSelection();
+ QDesignerFormEditorInterface *core = formWindow()->core();
+
+ if (QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_parentWidget)) {
+ const int count = c->count();
+ for (int i=0; i<count; ++i) {
+ if (c->widget(i) == m_widget) {
+ c->remove(i);
+ return;
+ }
+ }
+ }
+
+ m_widgetOrderIndex = removeFromWidgetListDynamicProperty(m_parentWidget, m_widget, widgetOrderPropertyC);
+ m_zOrderIndex = removeFromWidgetListDynamicProperty(m_parentWidget, m_widget, zOrderPropertyC);
+
+ if (QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core->extensionManager(), m_parentWidget))
+ deco->removeWidget(m_widget);
+
+ if (m_layoutHelper)
+ switch (m_layoutType) {
+ case LayoutInfo::NoLayout:
+ case LayoutInfo::HSplitter:
+ case LayoutInfo::VSplitter:
+ break;
+ default:
+ // Attempt to simplify grids if a row/column becomes empty
+ m_layoutSimplified = (m_flags & DoNotSimplifyLayout) ? false : m_layoutHelper->canSimplify(core, m_parentWidget, m_layoutPosition);
+ if (m_layoutSimplified) {
+ m_layoutHelper->pushState(core, m_parentWidget);
+ m_layoutHelper->simplify(core, m_parentWidget, m_layoutPosition);
+ }
+ break;
+ }
+
+ if (!(m_flags & DoNotUnmanage))
+ m_manageHelper.unmanage(formWindow());
+
+ m_widget->setParent(formWindow());
+ m_widget->hide();
+
+ if (m_tabOrderIndex != -1) {
+ QList<QWidget*> tab_order = m_formItem->tabOrder();
+ tab_order.removeAt(m_tabOrderIndex);
+ m_formItem->setTabOrder(tab_order);
+ }
+}
+
+void DeleteWidgetCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ formWindow()->clearSelection();
+
+ m_widget->setParent(m_parentWidget);
+
+ if (QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_parentWidget)) {
+ c->addWidget(m_widget);
+ return;
+ }
+
+ addToWidgetListDynamicProperty(m_parentWidget, m_widget, widgetOrderPropertyC, m_widgetOrderIndex);
+ addToWidgetListDynamicProperty(m_parentWidget, m_widget, zOrderPropertyC, m_zOrderIndex);
+
+ m_widget->setGeometry(m_geometry);
+
+ if (!(m_flags & DoNotUnmanage))
+ m_manageHelper.manage(formWindow());
+ // ### set up alignment
+ switch (m_layoutType) {
+ case LayoutInfo::NoLayout:
+ break;
+ case LayoutInfo::HSplitter:
+ case LayoutInfo::VSplitter: {
+ QSplitter *splitter = qobject_cast<QSplitter *>(m_widget->parent());
+ Q_ASSERT(splitter);
+ splitter->insertWidget(m_splitterIndex, m_widget);
+ } break;
+ default: {
+ Q_ASSERT(m_layoutHelper);
+ if (m_layoutSimplified)
+ m_layoutHelper->popState(core, m_parentWidget);
+ QLayout *layout = LayoutInfo::managedLayout(core, m_parentWidget);
+ Q_ASSERT(m_layoutType == LayoutInfo::layoutType(core, layout));
+ m_layoutHelper->insertWidget(layout, m_layoutPosition, m_widget);
+ }
+ break;
+ }
+
+ m_widget->show();
+
+ if (m_tabOrderIndex != -1) {
+ QList<QWidget*> tab_order = m_formItem->tabOrder();
+ tab_order.insert(m_tabOrderIndex, m_widget);
+ m_formItem->setTabOrder(tab_order);
+ }
+}
+
+// ---- ReparentWidgetCommand ----
+ReparentWidgetCommand::ReparentWidgetCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QString(), formWindow)
+{
+}
+
+void ReparentWidgetCommand::init(QWidget *widget, QWidget *parentWidget)
+{
+ Q_ASSERT(widget);
+
+ m_widget = widget;
+ m_oldParentWidget = widget->parentWidget();
+ m_newParentWidget = parentWidget;
+
+ m_oldPos = m_widget->pos();
+ m_newPos = m_newParentWidget->mapFromGlobal(m_oldParentWidget->mapToGlobal(m_oldPos));
+
+ setText(QApplication::translate("Command", "Reparent '%1'").arg(widget->objectName()));
+
+ m_oldParentList = qVariantValue<QWidgetList>(m_oldParentWidget->property("_q_widgetOrder"));
+ m_oldParentZOrder = qVariantValue<QWidgetList>(m_oldParentWidget->property("_q_zOrder"));
+}
+
+void ReparentWidgetCommand::redo()
+{
+ m_widget->setParent(m_newParentWidget);
+ m_widget->move(m_newPos);
+
+ QWidgetList oldList = m_oldParentList;
+ oldList.removeAll(m_widget);
+ m_oldParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(oldList));
+
+ QWidgetList newList = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_widgetOrder"));
+ newList.append(m_widget);
+ m_newParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(newList));
+
+ QWidgetList oldZOrder = m_oldParentZOrder;
+ oldZOrder.removeAll(m_widget);
+ m_oldParentWidget->setProperty("_q_zOrder", qVariantFromValue(oldZOrder));
+
+ QWidgetList newZOrder = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_zOrder"));
+ newZOrder.append(m_widget);
+ m_newParentWidget->setProperty("_q_zOrder", qVariantFromValue(newZOrder));
+
+ m_widget->show();
+ core()->objectInspector()->setFormWindow(formWindow());
+}
+
+void ReparentWidgetCommand::undo()
+{
+ m_widget->setParent(m_oldParentWidget);
+ m_widget->move(m_oldPos);
+
+ m_oldParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(m_oldParentList));
+
+ QWidgetList newList = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_widgetOrder"));
+ newList.removeAll(m_widget);
+ m_newParentWidget->setProperty("_q_widgetOrder", qVariantFromValue(newList));
+
+ m_oldParentWidget->setProperty("_q_zOrder", qVariantFromValue(m_oldParentZOrder));
+
+ QWidgetList newZOrder = qVariantValue<QWidgetList>(m_newParentWidget->property("_q_zOrder"));
+ m_newParentWidget->setProperty("_q_zOrder", qVariantFromValue(newZOrder));
+
+ m_widget->show();
+ core()->objectInspector()->setFormWindow(formWindow());
+}
+
+PromoteToCustomWidgetCommand::PromoteToCustomWidgetCommand
+ (QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Promote to custom widget"), formWindow)
+{
+}
+
+void PromoteToCustomWidgetCommand::init(const WidgetList &widgets,const QString &customClassName)
+{
+ m_widgets = widgets;
+ m_customClassName = customClassName;
+}
+
+void PromoteToCustomWidgetCommand::redo()
+{
+ foreach (QWidget *w, m_widgets) {
+ if (w)
+ promoteWidget(core(), w, m_customClassName);
+ }
+ updateSelection();
+}
+
+void PromoteToCustomWidgetCommand::updateSelection()
+{
+ // Update class names in ObjectInspector, PropertyEditor
+ QDesignerFormWindowInterface *fw = formWindow();
+ QDesignerFormEditorInterface *core = fw->core();
+ core->objectInspector()->setFormWindow(fw);
+ if (QObject *o = core->propertyEditor()->object())
+ core->propertyEditor()->setObject(o);
+}
+
+void PromoteToCustomWidgetCommand::undo()
+{
+ foreach (QWidget *w, m_widgets) {
+ if (w)
+ demoteWidget(core(), w);
+ }
+ updateSelection();
+}
+
+// ---- DemoteFromCustomWidgetCommand ----
+
+DemoteFromCustomWidgetCommand::DemoteFromCustomWidgetCommand
+ (QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Demote from custom widget"), formWindow),
+ m_promote_cmd(formWindow)
+{
+}
+
+void DemoteFromCustomWidgetCommand::init(const WidgetList &promoted)
+{
+ m_promote_cmd.init(promoted, promotedCustomClassName(core(), promoted.front()));
+}
+
+void DemoteFromCustomWidgetCommand::redo()
+{
+ m_promote_cmd.undo();
+}
+
+void DemoteFromCustomWidgetCommand::undo()
+{
+ m_promote_cmd.redo();
+}
+
+// ---------- CursorSelectionState
+CursorSelectionState::CursorSelectionState()
+{
+}
+
+void CursorSelectionState::save(const QDesignerFormWindowInterface *formWindow)
+{
+ const QDesignerFormWindowCursorInterface *cursor = formWindow->cursor();
+ m_selection.clear();
+ m_current = cursor->current();
+ if (cursor->hasSelection()) {
+ const int count = cursor->selectedWidgetCount();
+ for(int i = 0; i < count; i++)
+ m_selection.push_back(cursor->selectedWidget(i));
+ }
+}
+
+void CursorSelectionState::restore(QDesignerFormWindowInterface *formWindow) const
+{
+ if (m_selection.empty()) {
+ formWindow->clearSelection(true);
+ } else {
+ // Select current as last
+ formWindow->clearSelection(false);
+ const WidgetPointerList::const_iterator cend = m_selection.constEnd();
+ for (WidgetPointerList::const_iterator it = m_selection.constBegin(); it != cend; ++it)
+ if (QWidget *w = *it)
+ if (w != m_current)
+ formWindow->selectWidget(*it, true);
+ if (m_current)
+ formWindow->selectWidget(m_current, true);
+ }
+}
+
+// ---- LayoutCommand ----
+
+LayoutCommand::LayoutCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_setup(false)
+{
+}
+
+LayoutCommand::~LayoutCommand()
+{
+ delete m_layout;
+}
+
+void LayoutCommand::init(QWidget *parentWidget, const QWidgetList &widgets,
+ LayoutInfo::Type layoutType, QWidget *layoutBase,
+ bool reparentLayoutWidget)
+{
+ m_parentWidget = parentWidget;
+ m_widgets = widgets;
+ formWindow()->simplifySelection(&m_widgets);
+ m_layout = Layout::createLayout(widgets, parentWidget, formWindow(), layoutBase, layoutType);
+ m_layout->setReparentLayoutWidget(reparentLayoutWidget);
+
+ switch (layoutType) {
+ case LayoutInfo::Grid:
+ setText(QApplication::translate("Command", "Lay out using grid"));
+ break;
+ case LayoutInfo::VBox:
+ setText(QApplication::translate("Command", "Lay out vertically"));
+ break;
+ case LayoutInfo::HBox:
+ setText(QApplication::translate("Command", "Lay out horizontally"));
+ break;
+ default:
+ break;
+ }
+ // Delayed setup to avoid confusion in case we are chained
+ // with a BreakLayout in a morph layout macro
+ m_setup = false;
+}
+
+void LayoutCommand::redo()
+{
+ if (!m_setup) {
+ m_layout->setup();
+ m_cursorSelectionState.save(formWindow());
+ m_setup = true;
+ }
+ m_layout->doLayout();
+ core()->objectInspector()->setFormWindow(formWindow());
+}
+
+void LayoutCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+
+ QWidget *lb = m_layout->layoutBaseWidget();
+ QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core->extensionManager(), lb);
+ m_layout->undoLayout();
+ delete deco; // release the extension
+
+ // ### generalize (put in function)
+ if (!m_layoutBase && lb != 0 && !(qobject_cast<QLayoutWidget*>(lb) || qobject_cast<QSplitter*>(lb))) {
+ core->metaDataBase()->add(lb);
+ lb->show();
+ }
+ m_cursorSelectionState.restore(formWindow());
+ core->objectInspector()->setFormWindow(formWindow());
+}
+
+// ---- BreakLayoutCommand ----
+BreakLayoutCommand::BreakLayoutCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Break layout"), formWindow),
+ m_layoutHelper(0),
+ m_properties(0),
+ m_propertyMask(0)
+{
+}
+
+BreakLayoutCommand::~BreakLayoutCommand()
+{
+ delete m_layoutHelper;
+ delete m_layout;
+ delete m_properties;
+}
+
+const LayoutProperties *BreakLayoutCommand::layoutProperties() const
+{
+ return m_properties;
+}
+
+int BreakLayoutCommand::propertyMask() const
+{
+ return m_propertyMask;
+}
+
+void BreakLayoutCommand::init(const QWidgetList &widgets, QWidget *layoutBase, bool reparentLayoutWidget)
+{
+ enum Type { SplitterLayout, LayoutHasMarginSpacing, LayoutHasState };
+
+ const QDesignerFormEditorInterface *core = formWindow()->core();
+ m_widgets = widgets;
+ m_layoutBase = core->widgetFactory()->containerOfWidget(layoutBase);
+ QLayout *layoutToBeBroken;
+ const LayoutInfo::Type layoutType = LayoutInfo::managedLayoutType(core, m_layoutBase, &layoutToBeBroken);
+ m_layout = Layout::createLayout(widgets, m_layoutBase, formWindow(), layoutBase, layoutType);
+ m_layout->setReparentLayoutWidget(reparentLayoutWidget);
+
+ Type type = LayoutHasState;
+ switch (layoutType) {
+ case LayoutInfo::NoLayout:
+ case LayoutInfo::HSplitter:
+ case LayoutInfo::VSplitter:
+ type = SplitterLayout;
+ break;
+ case LayoutInfo::HBox:
+ case LayoutInfo::VBox: // Margin/spacing need to be saved
+ type = LayoutHasMarginSpacing;
+ break;
+ default: // Margin/spacing need to be saved + has a state (empty rows/columns of a grid)
+ type = LayoutHasState;
+ break;
+ }
+ Q_ASSERT(m_layout != 0);
+ m_layout->sort();
+
+
+ if (type >= LayoutHasMarginSpacing) {
+ m_properties = new LayoutProperties;
+ m_propertyMask = m_properties->fromPropertySheet(core, layoutToBeBroken, LayoutProperties::AllProperties);
+ }
+ if (type >= LayoutHasState)
+ m_layoutHelper = LayoutHelper::createLayoutHelper(layoutType);
+ m_cursorSelectionState.save(formWindow());
+}
+
+void BreakLayoutCommand::redo()
+{
+ if (!m_layout)
+ return;
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QWidget *lb = m_layout->layoutBaseWidget();
+ QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core->extensionManager(), lb);
+ formWindow()->clearSelection(false);
+ if (m_layoutHelper)
+ m_layoutHelper->pushState(core, m_layoutBase);
+ m_layout->breakLayout();
+ delete deco; // release the extension
+
+ foreach (QWidget *widget, m_widgets) {
+ widget->resize(widget->size().expandedTo(QSize(16, 16)));
+ }
+ // Update unless we are in an intermediate state of morphing layout
+ // in which a QLayoutWidget will have no layout at all.
+ if (m_layout->reparentLayoutWidget())
+ core->objectInspector()->setFormWindow(formWindow());
+}
+
+void BreakLayoutCommand::undo()
+{
+ if (!m_layout)
+ return;
+
+ formWindow()->clearSelection(false);
+ m_layout->doLayout();
+ if (m_layoutHelper)
+ m_layoutHelper->popState(formWindow()->core(), m_layoutBase);
+
+ QLayout *layoutToRestored = LayoutInfo::managedLayout(formWindow()->core(), m_layoutBase);
+ if (m_properties && m_layoutBase && layoutToRestored)
+ m_properties->toPropertySheet(formWindow()->core(), layoutToRestored, m_propertyMask);
+ m_cursorSelectionState.restore(formWindow());
+ core()->objectInspector()->setFormWindow(formWindow());
+}
+// ---- SimplifyLayoutCommand
+SimplifyLayoutCommand::SimplifyLayoutCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Simplify Grid Layout"), formWindow),
+ m_area(0, 0, 32767, 32767),
+ m_layoutBase(0),
+ m_layoutHelper(0),
+ m_layoutSimplified(false)
+{
+}
+
+SimplifyLayoutCommand::~SimplifyLayoutCommand()
+{
+ delete m_layoutHelper;
+}
+
+bool SimplifyLayoutCommand::canSimplify(QDesignerFormEditorInterface *core, const QWidget *w, int *layoutType)
+{
+ if (!w)
+ return false;
+ QLayout *layout;
+ const LayoutInfo::Type type = LayoutInfo::managedLayoutType(core, w, &layout);
+ if (layoutType)
+ *layoutType = type;
+ if (!layout)
+ return false;
+ switch (type) { // Known negatives
+ case LayoutInfo::NoLayout:
+ case LayoutInfo::UnknownLayout:
+ case LayoutInfo::HSplitter:
+ case LayoutInfo::VSplitter:
+ case LayoutInfo::HBox:
+ case LayoutInfo::VBox:
+ return false;
+ default:
+ break;
+ }
+ switch (type) {
+ case LayoutInfo::Grid:
+ return QLayoutSupport::canSimplifyQuickCheck(qobject_cast<QGridLayout*>(layout));
+ case LayoutInfo::Form:
+ return QLayoutSupport::canSimplifyQuickCheck(qobject_cast<const QFormLayout*>(layout));
+ default:
+ break;
+ }
+ return false;
+}
+
+bool SimplifyLayoutCommand::init(QWidget *layoutBase)
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ m_layoutSimplified = false;
+ int type;
+ if (canSimplify(core, layoutBase, &type)) {
+ m_layoutBase = layoutBase;
+ m_layoutHelper = LayoutHelper::createLayoutHelper(type);
+ m_layoutSimplified = m_layoutHelper->canSimplify(core, layoutBase, m_area);
+ }
+ return m_layoutSimplified;
+}
+
+void SimplifyLayoutCommand::redo()
+{
+ const QDesignerFormEditorInterface *core = formWindow()->core();
+ if (m_layoutSimplified) {
+ m_layoutHelper->pushState(core, m_layoutBase);
+ m_layoutHelper->simplify(core, m_layoutBase, m_area);
+ }
+}
+void SimplifyLayoutCommand::undo()
+{
+ if (m_layoutSimplified)
+ m_layoutHelper->popState(formWindow()->core(), m_layoutBase);
+}
+
+// ---- ToolBoxCommand ----
+ToolBoxCommand::ToolBoxCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_index(-1)
+{
+}
+
+ToolBoxCommand::~ToolBoxCommand()
+{
+}
+
+void ToolBoxCommand::init(QToolBox *toolBox)
+{
+ m_toolBox = toolBox;
+ m_index = m_toolBox->currentIndex();
+ m_widget = m_toolBox->widget(m_index);
+ m_itemText = m_toolBox->itemText(m_index);
+ m_itemIcon = m_toolBox->itemIcon(m_index);
+}
+
+void ToolBoxCommand::removePage()
+{
+ m_toolBox->removeItem(m_index);
+
+ m_widget->hide();
+ m_widget->setParent(formWindow());
+ formWindow()->clearSelection();
+ formWindow()->selectWidget(m_toolBox, true);
+
+}
+
+void ToolBoxCommand::addPage()
+{
+ m_widget->setParent(m_toolBox);
+ m_toolBox->insertItem(m_index, m_widget, m_itemIcon, m_itemText);
+ m_toolBox->setCurrentIndex(m_index);
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(formWindow()->core()->extensionManager(), m_toolBox);
+ if (sheet) {
+ qdesigner_internal::PropertySheetStringValue itemText(m_itemText);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentItemText")), qVariantFromValue(itemText));
+ }
+
+ m_widget->show();
+ formWindow()->clearSelection();
+ formWindow()->selectWidget(m_toolBox, true);
+}
+
+// ---- MoveToolBoxPageCommand ----
+MoveToolBoxPageCommand::MoveToolBoxPageCommand(QDesignerFormWindowInterface *formWindow) :
+ ToolBoxCommand(formWindow),
+ m_newIndex(-1),
+ m_oldIndex(-1)
+{
+}
+
+MoveToolBoxPageCommand::~MoveToolBoxPageCommand()
+{
+}
+
+void MoveToolBoxPageCommand::init(QToolBox *toolBox, QWidget *page, int newIndex)
+{
+ ToolBoxCommand::init(toolBox);
+ setText(QApplication::translate("Command", "Move Page"));
+
+ m_widget = page;
+ m_oldIndex = m_toolBox->indexOf(m_widget);
+ m_itemText = m_toolBox->itemText(m_oldIndex);
+ m_itemIcon = m_toolBox->itemIcon(m_oldIndex);
+ m_newIndex = newIndex;
+}
+
+void MoveToolBoxPageCommand::redo()
+{
+ m_toolBox->removeItem(m_oldIndex);
+ m_toolBox->insertItem(m_newIndex, m_widget, m_itemIcon, m_itemText);
+}
+
+void MoveToolBoxPageCommand::undo()
+{
+ m_toolBox->removeItem(m_newIndex);
+ m_toolBox->insertItem(m_oldIndex, m_widget, m_itemIcon, m_itemText);
+}
+
+// ---- DeleteToolBoxPageCommand ----
+DeleteToolBoxPageCommand::DeleteToolBoxPageCommand(QDesignerFormWindowInterface *formWindow)
+ : ToolBoxCommand(formWindow)
+{
+}
+
+DeleteToolBoxPageCommand::~DeleteToolBoxPageCommand()
+{
+}
+
+void DeleteToolBoxPageCommand::init(QToolBox *toolBox)
+{
+ ToolBoxCommand::init(toolBox);
+ setText(QApplication::translate("Command", "Delete Page"));
+}
+
+void DeleteToolBoxPageCommand::redo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+void DeleteToolBoxPageCommand::undo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+// ---- AddToolBoxPageCommand ----
+AddToolBoxPageCommand::AddToolBoxPageCommand(QDesignerFormWindowInterface *formWindow)
+ : ToolBoxCommand(formWindow)
+{
+}
+
+AddToolBoxPageCommand::~AddToolBoxPageCommand()
+{
+}
+
+void AddToolBoxPageCommand::init(QToolBox *toolBox)
+{
+ init(toolBox, InsertBefore);
+}
+
+void AddToolBoxPageCommand::init(QToolBox *toolBox, InsertionMode mode)
+{
+ m_toolBox = toolBox;
+
+ m_index = m_toolBox->currentIndex();
+ if (mode == InsertAfter)
+ m_index++;
+ m_widget = new QDesignerWidget(formWindow(), m_toolBox);
+ m_itemText = QApplication::translate("Command", "Page");
+ m_itemIcon = QIcon();
+ m_widget->setObjectName(QApplication::translate("Command", "page"));
+ formWindow()->ensureUniqueObjectName(m_widget);
+
+ setText(QApplication::translate("Command", "Insert Page"));
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ core->metaDataBase()->add(m_widget);
+}
+
+void AddToolBoxPageCommand::redo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+void AddToolBoxPageCommand::undo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+// ---- TabWidgetCommand ----
+TabWidgetCommand::TabWidgetCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_index(-1)
+{
+}
+
+TabWidgetCommand::~TabWidgetCommand()
+{
+}
+
+void TabWidgetCommand::init(QTabWidget *tabWidget)
+{
+ m_tabWidget = tabWidget;
+ m_index = m_tabWidget->currentIndex();
+ m_widget = m_tabWidget->widget(m_index);
+ m_itemText = m_tabWidget->tabText(m_index);
+ m_itemIcon = m_tabWidget->tabIcon(m_index);
+}
+
+void TabWidgetCommand::removePage()
+{
+ m_tabWidget->removeTab(m_index);
+
+ m_widget->hide();
+ m_widget->setParent(formWindow());
+ m_tabWidget->setCurrentIndex(qMin(m_index, m_tabWidget->count()));
+
+ formWindow()->clearSelection();
+ formWindow()->selectWidget(m_tabWidget, true);
+}
+
+void TabWidgetCommand::addPage()
+{
+ m_widget->setParent(0);
+ m_tabWidget->insertTab(m_index, m_widget, m_itemIcon, m_itemText);
+ m_widget->show();
+ m_tabWidget->setCurrentIndex(m_index);
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(formWindow()->core()->extensionManager(), m_tabWidget);
+ if (sheet) {
+ qdesigner_internal::PropertySheetStringValue itemText(m_itemText);
+ sheet->setProperty(sheet->indexOf(QLatin1String("currentTabText")), qVariantFromValue(itemText));
+ }
+
+ formWindow()->clearSelection();
+ formWindow()->selectWidget(m_tabWidget, true);
+}
+
+// ---- DeleteTabPageCommand ----
+DeleteTabPageCommand::DeleteTabPageCommand(QDesignerFormWindowInterface *formWindow)
+ : TabWidgetCommand(formWindow)
+{
+}
+
+DeleteTabPageCommand::~DeleteTabPageCommand()
+{
+}
+
+void DeleteTabPageCommand::init(QTabWidget *tabWidget)
+{
+ TabWidgetCommand::init(tabWidget);
+ setText(QApplication::translate("Command", "Delete Page"));
+}
+
+void DeleteTabPageCommand::redo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+void DeleteTabPageCommand::undo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+// ---- AddTabPageCommand ----
+AddTabPageCommand::AddTabPageCommand(QDesignerFormWindowInterface *formWindow)
+ : TabWidgetCommand(formWindow)
+{
+}
+
+AddTabPageCommand::~AddTabPageCommand()
+{
+}
+
+void AddTabPageCommand::init(QTabWidget *tabWidget)
+{
+ init(tabWidget, InsertBefore);
+}
+
+void AddTabPageCommand::init(QTabWidget *tabWidget, InsertionMode mode)
+{
+ m_tabWidget = tabWidget;
+
+ m_index = m_tabWidget->currentIndex();
+ if (mode == InsertAfter)
+ m_index++;
+ m_widget = new QDesignerWidget(formWindow(), m_tabWidget);
+ m_itemText = QApplication::translate("Command", "Page");
+ m_itemIcon = QIcon();
+ m_widget->setObjectName(QApplication::translate("Command", "tab"));
+ formWindow()->ensureUniqueObjectName(m_widget);
+
+ setText(QApplication::translate("Command", "Insert Page"));
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ core->metaDataBase()->add(m_widget);
+}
+
+void AddTabPageCommand::redo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+void AddTabPageCommand::undo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+// ---- MoveTabPageCommand ----
+MoveTabPageCommand::MoveTabPageCommand(QDesignerFormWindowInterface *formWindow) :
+ TabWidgetCommand(formWindow),
+ m_newIndex(-1),
+ m_oldIndex(-1)
+{
+}
+
+MoveTabPageCommand::~MoveTabPageCommand()
+{
+}
+
+void MoveTabPageCommand::init(QTabWidget *tabWidget, QWidget *page,
+ const QIcon &icon, const QString &label,
+ int index, int newIndex)
+{
+ TabWidgetCommand::init(tabWidget);
+ setText(QApplication::translate("Command", "Move Page"));
+
+ m_page = page;
+ m_newIndex = newIndex;
+ m_oldIndex = index;
+ m_label = label;
+ m_icon = icon;
+}
+
+void MoveTabPageCommand::redo()
+{
+ m_tabWidget->removeTab(m_oldIndex);
+ m_tabWidget->insertTab(m_newIndex, m_page, m_icon, m_label);
+ m_tabWidget->setCurrentIndex(m_newIndex);
+}
+
+void MoveTabPageCommand::undo()
+{
+ m_tabWidget->removeTab(m_newIndex);
+ m_tabWidget->insertTab(m_oldIndex, m_page, m_icon, m_label);
+ m_tabWidget->setCurrentIndex(m_oldIndex);
+}
+
+// ---- StackedWidgetCommand ----
+StackedWidgetCommand::StackedWidgetCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_index(-1)
+{
+}
+
+StackedWidgetCommand::~StackedWidgetCommand()
+{
+}
+
+void StackedWidgetCommand::init(QStackedWidget *stackedWidget)
+{
+ m_stackedWidget = stackedWidget;
+ m_index = m_stackedWidget->currentIndex();
+ m_widget = m_stackedWidget->widget(m_index);
+}
+
+void StackedWidgetCommand::removePage()
+{
+ m_stackedWidget->removeWidget(m_stackedWidget->widget(m_index));
+
+ m_widget->hide();
+ m_widget->setParent(formWindow());
+
+ formWindow()->clearSelection();
+ formWindow()->selectWidget(m_stackedWidget, true);
+}
+
+void StackedWidgetCommand::addPage()
+{
+ m_stackedWidget->insertWidget(m_index, m_widget);
+
+ m_widget->show();
+ m_stackedWidget->setCurrentIndex(m_index);
+
+ formWindow()->clearSelection();
+ formWindow()->selectWidget(m_stackedWidget, true);
+}
+
+// ---- MoveStackedWidgetCommand ----
+MoveStackedWidgetCommand::MoveStackedWidgetCommand(QDesignerFormWindowInterface *formWindow) :
+ StackedWidgetCommand(formWindow),
+ m_newIndex(-1),
+ m_oldIndex(-1)
+{
+}
+
+MoveStackedWidgetCommand::~MoveStackedWidgetCommand()
+{
+}
+
+void MoveStackedWidgetCommand::init(QStackedWidget *stackedWidget, QWidget *page, int newIndex)
+{
+ StackedWidgetCommand::init(stackedWidget);
+ setText(QApplication::translate("Command", "Move Page"));
+
+ m_widget = page;
+ m_newIndex = newIndex;
+ m_oldIndex = m_stackedWidget->indexOf(m_widget);
+}
+
+void MoveStackedWidgetCommand::redo()
+{
+ m_stackedWidget->removeWidget(m_widget);
+ m_stackedWidget->insertWidget(m_newIndex, m_widget);
+}
+
+void MoveStackedWidgetCommand::undo()
+{
+ m_stackedWidget->removeWidget(m_widget);
+ m_stackedWidget->insertWidget(m_oldIndex, m_widget);
+}
+
+// ---- DeleteStackedWidgetPageCommand ----
+DeleteStackedWidgetPageCommand::DeleteStackedWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
+ : StackedWidgetCommand(formWindow)
+{
+}
+
+DeleteStackedWidgetPageCommand::~DeleteStackedWidgetPageCommand()
+{
+}
+
+void DeleteStackedWidgetPageCommand::init(QStackedWidget *stackedWidget)
+{
+ StackedWidgetCommand::init(stackedWidget);
+ setText(QApplication::translate("Command", "Delete Page"));
+}
+
+void DeleteStackedWidgetPageCommand::redo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+void DeleteStackedWidgetPageCommand::undo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+// ---- AddStackedWidgetPageCommand ----
+AddStackedWidgetPageCommand::AddStackedWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
+ : StackedWidgetCommand(formWindow)
+{
+}
+
+AddStackedWidgetPageCommand::~AddStackedWidgetPageCommand()
+{
+}
+
+void AddStackedWidgetPageCommand::init(QStackedWidget *stackedWidget)
+{
+ init(stackedWidget, InsertBefore);
+}
+
+void AddStackedWidgetPageCommand::init(QStackedWidget *stackedWidget, InsertionMode mode)
+{
+ m_stackedWidget = stackedWidget;
+
+ m_index = m_stackedWidget->currentIndex();
+ if (mode == InsertAfter)
+ m_index++;
+ m_widget = new QDesignerWidget(formWindow(), m_stackedWidget);
+ m_widget->setObjectName(QApplication::translate("Command", "page"));
+ formWindow()->ensureUniqueObjectName(m_widget);
+
+ setText(QApplication::translate("Command", "Insert Page"));
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ core->metaDataBase()->add(m_widget);
+}
+
+void AddStackedWidgetPageCommand::redo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+void AddStackedWidgetPageCommand::undo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+// ---- TabOrderCommand ----
+TabOrderCommand::TabOrderCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Change Tab order"), formWindow),
+ m_widgetItem(0)
+{
+}
+
+void TabOrderCommand::init(const QList<QWidget*> &newTabOrder)
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ Q_ASSERT(core);
+
+ m_widgetItem = core->metaDataBase()->item(formWindow());
+ Q_ASSERT(m_widgetItem);
+ m_oldTabOrder = m_widgetItem->tabOrder();
+ m_newTabOrder = newTabOrder;
+}
+
+void TabOrderCommand::redo()
+{
+ m_widgetItem->setTabOrder(m_newTabOrder);
+}
+
+void TabOrderCommand::undo()
+{
+ m_widgetItem->setTabOrder(m_oldTabOrder);
+}
+
+// ---- CreateMenuBarCommand ----
+CreateMenuBarCommand::CreateMenuBarCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Create Menu Bar"), formWindow)
+{
+}
+
+void CreateMenuBarCommand::init(QMainWindow *mainWindow)
+{
+ m_mainWindow = mainWindow;
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ m_menuBar = qobject_cast<QMenuBar*>(core->widgetFactory()->createWidget(QLatin1String("QMenuBar"), m_mainWindow));
+ core->widgetFactory()->initialize(m_menuBar);
+}
+
+void CreateMenuBarCommand::redo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerContainerExtension *c;
+ c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ c->addWidget(m_menuBar);
+
+ m_menuBar->setObjectName(QLatin1String("menuBar"));
+ formWindow()->ensureUniqueObjectName(m_menuBar);
+ core->metaDataBase()->add(m_menuBar);
+ formWindow()->emitSelectionChanged();
+ m_menuBar->setFocus();
+}
+
+void CreateMenuBarCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerContainerExtension *c;
+ c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ for (int i = 0; i < c->count(); ++i) {
+ if (c->widget(i) == m_menuBar) {
+ c->remove(i);
+ break;
+ }
+ }
+
+ core->metaDataBase()->remove(m_menuBar);
+ formWindow()->emitSelectionChanged();
+}
+
+// ---- DeleteMenuBarCommand ----
+DeleteMenuBarCommand::DeleteMenuBarCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Delete Menu Bar"), formWindow)
+{
+}
+
+void DeleteMenuBarCommand::init(QMenuBar *menuBar)
+{
+ m_menuBar = menuBar;
+ m_mainWindow = qobject_cast<QMainWindow*>(menuBar->parentWidget());
+}
+
+void DeleteMenuBarCommand::redo()
+{
+ if (m_mainWindow) {
+ QDesignerContainerExtension *c;
+ c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), m_mainWindow);
+ Q_ASSERT(c != 0);
+ for (int i=0; i<c->count(); ++i) {
+ if (c->widget(i) == m_menuBar) {
+ c->remove(i);
+ break;
+ }
+ }
+ }
+
+ core()->metaDataBase()->remove(m_menuBar);
+ m_menuBar->hide();
+ m_menuBar->setParent(formWindow());
+ formWindow()->emitSelectionChanged();
+}
+
+void DeleteMenuBarCommand::undo()
+{
+ if (m_mainWindow) {
+ m_menuBar->setParent(m_mainWindow);
+ QDesignerContainerExtension *c;
+ c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), m_mainWindow);
+
+ c->addWidget(m_menuBar);
+
+ core()->metaDataBase()->add(m_menuBar);
+ m_menuBar->show();
+ formWindow()->emitSelectionChanged();
+ }
+}
+
+// ---- CreateStatusBarCommand ----
+CreateStatusBarCommand::CreateStatusBarCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Create Status Bar"), formWindow)
+{
+}
+
+void CreateStatusBarCommand::init(QMainWindow *mainWindow)
+{
+ m_mainWindow = mainWindow;
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ m_statusBar = qobject_cast<QStatusBar*>(core->widgetFactory()->createWidget(QLatin1String("QStatusBar"), m_mainWindow));
+ core->widgetFactory()->initialize(m_statusBar);
+}
+
+void CreateStatusBarCommand::redo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerContainerExtension *c;
+ c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ c->addWidget(m_statusBar);
+
+ m_statusBar->setObjectName(QLatin1String("statusBar"));
+ formWindow()->ensureUniqueObjectName(m_statusBar);
+ core->metaDataBase()->add(m_statusBar);
+ formWindow()->emitSelectionChanged();
+}
+
+void CreateStatusBarCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ for (int i = 0; i < c->count(); ++i) {
+ if (c->widget(i) == m_statusBar) {
+ c->remove(i);
+ break;
+ }
+ }
+
+ core->metaDataBase()->remove(m_statusBar);
+ formWindow()->emitSelectionChanged();
+}
+
+// ---- DeleteStatusBarCommand ----
+DeleteStatusBarCommand::DeleteStatusBarCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Delete Status Bar"), formWindow)
+{
+}
+
+void DeleteStatusBarCommand::init(QStatusBar *statusBar)
+{
+ m_statusBar = statusBar;
+ m_mainWindow = qobject_cast<QMainWindow*>(statusBar->parentWidget());
+}
+
+void DeleteStatusBarCommand::redo()
+{
+ if (m_mainWindow) {
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), m_mainWindow);
+ Q_ASSERT(c != 0);
+ for (int i=0; i<c->count(); ++i) {
+ if (c->widget(i) == m_statusBar) {
+ c->remove(i);
+ break;
+ }
+ }
+ }
+
+ core()->metaDataBase()->remove(m_statusBar);
+ m_statusBar->hide();
+ m_statusBar->setParent(formWindow());
+ formWindow()->emitSelectionChanged();
+}
+
+void DeleteStatusBarCommand::undo()
+{
+ if (m_mainWindow) {
+ m_statusBar->setParent(m_mainWindow);
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), m_mainWindow);
+
+ c->addWidget(m_statusBar);
+
+ core()->metaDataBase()->add(m_statusBar);
+ m_statusBar->show();
+ formWindow()->emitSelectionChanged();
+ }
+}
+
+// ---- AddToolBarCommand ----
+AddToolBarCommand::AddToolBarCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Add Tool Bar"), formWindow)
+{
+}
+
+void AddToolBarCommand::init(QMainWindow *mainWindow)
+{
+ m_mainWindow = mainWindow;
+ QDesignerWidgetFactoryInterface * wf = formWindow()->core()->widgetFactory();
+ // Pass on 0 parent first to avoid reparenting flicker.
+ m_toolBar = qobject_cast<QToolBar*>(wf->createWidget(QLatin1String("QToolBar"), 0));
+ wf->initialize(m_toolBar);
+ m_toolBar->hide();
+}
+
+void AddToolBarCommand::redo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ core->metaDataBase()->add(m_toolBar);
+
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ c->addWidget(m_toolBar);
+
+ m_toolBar->setObjectName(QLatin1String("toolBar"));
+ formWindow()->ensureUniqueObjectName(m_toolBar);
+ setPropertySheetWindowTitle(core, m_toolBar, m_toolBar->objectName());
+ formWindow()->emitSelectionChanged();
+}
+
+void AddToolBarCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ core->metaDataBase()->remove(m_toolBar);
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ for (int i = 0; i < c->count(); ++i) {
+ if (c->widget(i) == m_toolBar) {
+ c->remove(i);
+ break;
+ }
+ }
+ formWindow()->emitSelectionChanged();
+}
+
+// ---- DockWidgetCommand:: ----
+DockWidgetCommand::DockWidgetCommand(const QString &description, QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(description, formWindow)
+{
+}
+
+DockWidgetCommand::~DockWidgetCommand()
+{
+}
+
+void DockWidgetCommand::init(QDockWidget *dockWidget)
+{
+ m_dockWidget = dockWidget;
+}
+
+// ---- AddDockWidgetCommand ----
+AddDockWidgetCommand::AddDockWidgetCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Add Dock Window"), formWindow)
+{
+}
+
+void AddDockWidgetCommand::init(QMainWindow *mainWindow, QDockWidget *dockWidget)
+{
+ m_mainWindow = mainWindow;
+ m_dockWidget = dockWidget;
+}
+
+void AddDockWidgetCommand::init(QMainWindow *mainWindow)
+{
+ m_mainWindow = mainWindow;
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ m_dockWidget = qobject_cast<QDockWidget*>(core->widgetFactory()->createWidget(QLatin1String("QDockWidget"), m_mainWindow));
+}
+
+void AddDockWidgetCommand::redo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ c->addWidget(m_dockWidget);
+
+ m_dockWidget->setObjectName(QLatin1String("dockWidget"));
+ formWindow()->ensureUniqueObjectName(m_dockWidget);
+ formWindow()->manageWidget(m_dockWidget);
+ formWindow()->emitSelectionChanged();
+}
+
+void AddDockWidgetCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), m_mainWindow);
+ for (int i = 0; i < c->count(); ++i) {
+ if (c->widget(i) == m_dockWidget) {
+ c->remove(i);
+ break;
+ }
+ }
+
+ formWindow()->unmanageWidget(m_dockWidget);
+ formWindow()->emitSelectionChanged();
+}
+
+// ---- AdjustWidgetSizeCommand ----
+AdjustWidgetSizeCommand::AdjustWidgetSizeCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QString(), formWindow)
+{
+}
+
+void AdjustWidgetSizeCommand::init(QWidget *widget)
+{
+ m_widget = widget;
+ setText(QApplication::translate("Command", "Adjust Size of '%1'").arg(widget->objectName()));
+}
+
+QWidget *AdjustWidgetSizeCommand::widgetForAdjust() const
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ // Return the outer, embedding widget if it is the main container
+ if (Utils::isCentralWidget(fw, m_widget))
+ return fw->core()->integration()->containerWindow(m_widget);
+ return m_widget;
+}
+
+void AdjustWidgetSizeCommand::redo()
+{
+ QWidget *aw = widgetForAdjust();
+ m_geometry = aw->geometry();
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ aw->adjustSize();
+ const bool isMainContainer = aw != m_widget;
+ if (!isMainContainer) {
+ /* When doing adjustsize on a selected non-laid out child that has been enlarged
+ * and pushed partially over the top/left edge[s], it is possible that it "disappears"
+ * when shrinking. In that case, move it back so that it remains visible. */
+ if (aw->parentWidget()->layout() == 0) {
+ const QRect contentsRect = aw->parentWidget()->contentsRect();
+ const QRect newGeometry = aw->geometry();
+ QPoint newPos = m_geometry.topLeft();
+ if (newGeometry.bottom() <= contentsRect.y())
+ newPos.setY(contentsRect.y());
+ if (newGeometry.right() <= contentsRect.x())
+ newPos.setX(contentsRect.x());
+ if (newPos != m_geometry.topLeft())
+ aw->move(newPos);
+ }
+ }
+ updatePropertyEditor();
+}
+
+void AdjustWidgetSizeCommand::undo()
+{
+ QWidget *aw = widgetForAdjust();
+ aw->resize(m_geometry.size());
+ if (m_geometry.topLeft() != aw->geometry().topLeft())
+ aw->move(m_geometry.topLeft());
+ updatePropertyEditor();
+}
+
+void AdjustWidgetSizeCommand::updatePropertyEditor() const
+{
+ if (QDesignerPropertyEditorInterface *propertyEditor = formWindow()->core()->propertyEditor()) {
+ if (propertyEditor->object() == m_widget)
+ propertyEditor->setPropertyValue(QLatin1String("geometry"), m_widget->geometry(), true);
+ }
+}
+// ------------ ChangeFormLayoutItemRoleCommand
+
+ChangeFormLayoutItemRoleCommand::ChangeFormLayoutItemRoleCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Change Form Layout Item Geometry"), formWindow),
+ m_operation(SpanningToLabel)
+{
+}
+
+void ChangeFormLayoutItemRoleCommand::init(QWidget *widget, Operation op)
+{
+ m_widget = widget;
+ m_operation = op;
+}
+
+void ChangeFormLayoutItemRoleCommand::redo()
+{
+ doOperation(m_operation);
+}
+
+void ChangeFormLayoutItemRoleCommand::undo()
+{
+ doOperation(reverseOperation(m_operation));
+}
+
+ChangeFormLayoutItemRoleCommand::Operation ChangeFormLayoutItemRoleCommand::reverseOperation(Operation op)
+{
+ switch (op) {
+ case SpanningToLabel:
+ return LabelToSpanning;
+ case SpanningToField:
+ return FieldToSpanning;
+ case LabelToSpanning:
+ return SpanningToLabel;
+ case FieldToSpanning:
+ return SpanningToField;
+ }
+ return SpanningToField;
+}
+
+void ChangeFormLayoutItemRoleCommand::doOperation(Operation op)
+{
+ QFormLayout *fl = ChangeFormLayoutItemRoleCommand::managedFormLayoutOf(formWindow()->core(), m_widget);
+ const int index = fl->indexOf(m_widget);
+ Q_ASSERT(index != -1);
+ int row;
+ QFormLayout::ItemRole role;
+ fl->getItemPosition (index, &row, &role);
+ Q_ASSERT(index != -1);
+ QLayoutItem *item = fl->takeAt(index);
+ const QRect area = QRect(0, row, 2, 1);
+ switch (op) {
+ case SpanningToLabel:
+ fl->setItem(row, QFormLayout::LabelRole, item);
+ QLayoutSupport::createEmptyCells(fl);
+ break;
+ case SpanningToField:
+ fl->setItem(row, QFormLayout::FieldRole, item);
+ QLayoutSupport::createEmptyCells(fl);
+ break;
+ case LabelToSpanning:
+ case FieldToSpanning:
+ QLayoutSupport::removeEmptyCells(fl, area);
+ fl->setItem(row, QFormLayout::SpanningRole, item);
+ break;
+ }
+}
+
+unsigned ChangeFormLayoutItemRoleCommand::possibleOperations(QDesignerFormEditorInterface *core, QWidget *w)
+{
+ QFormLayout *fl = managedFormLayoutOf(core, w);
+ if (!fl)
+ return 0;
+ const int index = fl->indexOf(w);
+ if (index == -1)
+ return 0;
+ int row, col, colspan;
+ getFormLayoutItemPosition(fl, index, &row, &col, 0, &colspan);
+ // Spanning item?
+ if (colspan > 1)
+ return SpanningToLabel|SpanningToField;
+ // Is the neighbouring column free, that is, can the current item be expanded?
+ const QFormLayout::ItemRole neighbouringRole = col == 0 ? QFormLayout::FieldRole : QFormLayout::LabelRole;
+ const bool empty = LayoutInfo::isEmptyItem(fl->itemAt(row, neighbouringRole));
+ if (empty)
+ return col == 0 ? LabelToSpanning : FieldToSpanning;
+ return 0;
+}
+
+QFormLayout *ChangeFormLayoutItemRoleCommand::managedFormLayoutOf(QDesignerFormEditorInterface *core, QWidget *w)
+{
+ if (QLayout *layout = LayoutInfo::managedLayout(core, w->parentWidget()))
+ if (QFormLayout *fl = qobject_cast<QFormLayout *>(layout))
+ return fl;
+ return 0;
+}
+
+// ---- ChangeLayoutItemGeometry ----
+ChangeLayoutItemGeometry::ChangeLayoutItemGeometry(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Change Layout Item Geometry"), formWindow)
+{
+}
+
+void ChangeLayoutItemGeometry::init(QWidget *widget, int row, int column, int rowspan, int colspan)
+{
+ m_widget = widget;
+ Q_ASSERT(m_widget->parentWidget() != 0);
+
+ QLayout *layout = LayoutInfo::managedLayout(formWindow()->core(), m_widget->parentWidget());
+ Q_ASSERT(layout != 0);
+
+ QGridLayout *grid = qobject_cast<QGridLayout*>(layout);
+ Q_ASSERT(grid != 0);
+
+ const int itemIndex = grid->indexOf(m_widget);
+ Q_ASSERT(itemIndex != -1);
+
+ int current_row, current_column, current_rowspan, current_colspan;
+ grid->getItemPosition(itemIndex, &current_row, &current_column, &current_rowspan, &current_colspan);
+
+ m_oldInfo.setRect(current_column, current_row, current_colspan, current_rowspan);
+ m_newInfo.setRect(column, row, colspan, rowspan);
+}
+
+void ChangeLayoutItemGeometry::changeItemPosition(const QRect &g)
+{
+ QLayout *layout = LayoutInfo::managedLayout(formWindow()->core(), m_widget->parentWidget());
+ Q_ASSERT(layout != 0);
+
+ QGridLayout *grid = qobject_cast<QGridLayout*>(layout);
+ Q_ASSERT(grid != 0);
+
+ const int itemIndex = grid->indexOf(m_widget);
+ Q_ASSERT(itemIndex != -1);
+
+ QLayoutItem *item = grid->takeAt(itemIndex);
+ delete item;
+
+ if (!QLayoutSupport::removeEmptyCells(grid, g))
+ qWarning() << "ChangeLayoutItemGeometry::changeItemPosition: Nonempty cell at " << g << '.';
+
+ grid->addWidget(m_widget, g.top(), g.left(), g.height(), g.width());
+
+ grid->invalidate();
+ grid->activate();
+
+ QLayoutSupport::createEmptyCells(grid);
+
+ formWindow()->clearSelection(false);
+ formWindow()->selectWidget(m_widget, true);
+}
+
+void ChangeLayoutItemGeometry::redo()
+{
+ changeItemPosition(m_newInfo);
+}
+
+void ChangeLayoutItemGeometry::undo()
+{
+ changeItemPosition(m_oldInfo);
+}
+
+// ---- ContainerWidgetCommand ----
+ContainerWidgetCommand::ContainerWidgetCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_index(-1)
+{
+}
+
+ContainerWidgetCommand::~ContainerWidgetCommand()
+{
+}
+
+QDesignerContainerExtension *ContainerWidgetCommand::containerExtension() const
+{
+ QExtensionManager *mgr = core()->extensionManager();
+ return qt_extension<QDesignerContainerExtension*>(mgr, m_containerWidget);
+}
+
+void ContainerWidgetCommand::init(QWidget *containerWidget)
+{
+ m_containerWidget = containerWidget;
+
+ if (QDesignerContainerExtension *c = containerExtension()) {
+ m_index = c->currentIndex();
+ m_widget = c->widget(m_index);
+ }
+}
+
+void ContainerWidgetCommand::removePage()
+{
+ if (QDesignerContainerExtension *c = containerExtension()) {
+ if (const int count = c->count()) {
+ // Undo add after last?
+ const int deleteIndex = m_index >= 0 ? m_index : count - 1;
+ c->remove(deleteIndex);
+ m_widget->hide();
+ m_widget->setParent(formWindow());
+ }
+ }
+}
+
+void ContainerWidgetCommand::addPage()
+{
+ if (QDesignerContainerExtension *c = containerExtension()) {
+ int newCurrentIndex;
+ if (m_index >= 0) {
+ c->insertWidget(m_index, m_widget);
+ newCurrentIndex = m_index;
+ } else {
+ c->addWidget(m_widget);
+ newCurrentIndex = c->count() -1 ;
+ }
+ m_widget->show();
+ c->setCurrentIndex(newCurrentIndex);
+ }
+}
+
+// ---- DeleteContainerWidgetPageCommand ----
+DeleteContainerWidgetPageCommand::DeleteContainerWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
+ : ContainerWidgetCommand(formWindow)
+{
+}
+
+DeleteContainerWidgetPageCommand::~DeleteContainerWidgetPageCommand()
+{
+}
+
+void DeleteContainerWidgetPageCommand::init(QWidget *containerWidget, ContainerType ct)
+{
+ ContainerWidgetCommand::init(containerWidget);
+ switch (ct) {
+ case WizardContainer:
+ case PageContainer:
+ setText(QApplication::translate("Command", "Delete Page"));
+ break;
+ case MdiContainer:
+ setText(QApplication::translate("Command", "Delete Subwindow"));
+ break;
+ }
+}
+
+void DeleteContainerWidgetPageCommand::redo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+void DeleteContainerWidgetPageCommand::undo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+// ---- AddContainerWidgetPageCommand ----
+AddContainerWidgetPageCommand::AddContainerWidgetPageCommand(QDesignerFormWindowInterface *formWindow)
+ : ContainerWidgetCommand(formWindow)
+{
+}
+
+AddContainerWidgetPageCommand::~AddContainerWidgetPageCommand()
+{
+}
+
+void AddContainerWidgetPageCommand::init(QWidget *containerWidget, ContainerType ct, InsertionMode mode)
+{
+ m_containerWidget = containerWidget;
+
+ if (QDesignerContainerExtension *c = containerExtension()) {
+ m_index = c->currentIndex();
+ if (m_index >= 0 && mode == InsertAfter)
+ m_index++;
+ m_widget = 0;
+ const QDesignerFormEditorInterface *core = formWindow()->core();
+ switch (ct) {
+ case PageContainer:
+ setText(QApplication::translate("Command", "Insert Page"));
+ m_widget = new QDesignerWidget(formWindow(), m_containerWidget);
+ m_widget->setObjectName(QApplication::translate("Command", "page"));
+ break;
+ case MdiContainer:
+ setText(QApplication::translate("Command", "Insert Subwindow"));
+ m_widget = new QDesignerWidget(formWindow(), m_containerWidget);
+ m_widget->setObjectName(QApplication::translate("Command", "subwindow"));
+ setPropertySheetWindowTitle(core, m_widget, QApplication::translate("Command", "Subwindow"));
+ break;
+ case WizardContainer: // Apply style, don't manage
+ m_widget = core->widgetFactory()->createWidget(QLatin1String("QWizardPage"), 0);
+ break;
+ }
+ formWindow()->ensureUniqueObjectName(m_widget);
+ core->metaDataBase()->add(m_widget);
+ }
+}
+
+void AddContainerWidgetPageCommand::redo()
+{
+ addPage();
+ cheapUpdate();
+}
+
+void AddContainerWidgetPageCommand::undo()
+{
+ removePage();
+ cheapUpdate();
+}
+
+ChangeCurrentPageCommand::ChangeCurrentPageCommand(QDesignerFormWindowInterface *formWindow)
+ :
+ QDesignerFormWindowCommand(QString(), formWindow), m_oldIndex(0), m_newIndex(0)
+{
+}
+
+ChangeCurrentPageCommand::~ChangeCurrentPageCommand()
+{
+}
+
+QDesignerContainerExtension *ChangeCurrentPageCommand::containerExtension() const
+{
+ QExtensionManager *mgr = core()->extensionManager();
+ return qt_extension<QDesignerContainerExtension*>(mgr, m_containerWidget);
+}
+
+void ChangeCurrentPageCommand::init(QWidget *containerWidget, int newIndex)
+{
+ m_containerWidget = containerWidget;
+
+ if (QDesignerContainerExtension *c = containerExtension()) {
+ m_newIndex = newIndex;
+ m_oldIndex = c->currentIndex();
+ m_widget = c->widget(m_oldIndex);
+ }
+}
+
+void ChangeCurrentPageCommand::redo()
+{
+ containerExtension()->setCurrentIndex(m_newIndex);
+}
+
+void ChangeCurrentPageCommand::undo()
+{
+ containerExtension()->setCurrentIndex(m_oldIndex);
+}
+
+static int itemRoles[] = {
+ Qt::DecorationPropertyRole,
+ Qt::DisplayPropertyRole,
+ Qt::ToolTipPropertyRole,
+ Qt::StatusTipPropertyRole,
+ Qt::WhatsThisPropertyRole,
+ Qt::FontRole,
+ Qt::TextAlignmentRole,
+ Qt::BackgroundRole,
+ Qt::ForegroundRole,
+ Qt::CheckStateRole,
+ -1
+};
+
+template<class T>
+static void copyRoleFromItem(ItemData *id, int role, const T *item)
+{
+ QVariant v = item->data(role);
+ if (v.isValid())
+ id->m_properties.insert(role, v);
+}
+
+template<class T>
+static void copyRolesFromItem(ItemData *id, const T *item, bool editor)
+{
+ static const int defaultFlags = T().flags();
+
+ for (int i = 0; itemRoles[i] != -1; i++)
+ copyRoleFromItem<T>(id, itemRoles[i], item);
+
+ if (editor)
+ copyRoleFromItem<T>(id, ItemFlagsShadowRole, item);
+ else if (item->flags() != defaultFlags)
+ id->m_properties.insert(ItemFlagsShadowRole, qVariantFromValue((int)item->flags()));
+}
+
+template<class T>
+static void copyRolesToItem(const ItemData *id, T *item, DesignerIconCache *iconCache, bool editor)
+{
+ QHash<int, QVariant>::const_iterator it = id->m_properties.constBegin(),
+ end = id->m_properties.constEnd();
+ for (; it != end; ++it)
+ if (it.value().isValid()) {
+ if (!editor && it.key() == ItemFlagsShadowRole) {
+ item->setFlags((Qt::ItemFlags)it.value().toInt());
+ } else {
+ item->setData(it.key(), it.value());
+ switch (it.key()) {
+ case Qt::DecorationPropertyRole:
+ if (iconCache)
+ item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(it.value())));
+ break;
+ case Qt::DisplayPropertyRole:
+ item->setText(qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::ToolTipPropertyRole:
+ item->setToolTip(qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::StatusTipPropertyRole:
+ item->setStatusTip(qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::WhatsThisPropertyRole:
+ item->setWhatsThis(qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ }
+ }
+ }
+
+ if (editor)
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+}
+
+ItemData::ItemData(const QListWidgetItem *item, bool editor)
+{
+ copyRolesFromItem<QListWidgetItem>(this, item, editor);
+}
+
+QListWidgetItem *ItemData::createListItem(DesignerIconCache *iconCache, bool editor) const
+{
+ QListWidgetItem *item = new QListWidgetItem();
+ copyRolesToItem(this, item, iconCache, editor);
+ return item;
+}
+
+ItemData::ItemData(const QTableWidgetItem *item, bool editor)
+{
+ copyRolesFromItem(this, item, editor);
+}
+
+QTableWidgetItem *ItemData::createTableItem(DesignerIconCache *iconCache, bool editor) const
+{
+ QTableWidgetItem *item = new QTableWidgetItem;
+ copyRolesToItem(this, item, iconCache, editor);
+ return item;
+}
+
+static void copyRoleFromItem(ItemData *id, int role, const QTreeWidgetItem *item, int column)
+{
+ QVariant v = item->data(column, role);
+ if (v.isValid())
+ id->m_properties.insert(role, v);
+}
+
+ItemData::ItemData(const QTreeWidgetItem *item, int column)
+{
+ copyRoleFromItem(this, Qt::EditRole, item, column);
+ PropertySheetStringValue str(item->text(column));
+ m_properties.insert(Qt::DisplayPropertyRole, qVariantFromValue(str));
+
+ for (int i = 0; itemRoles[i] != -1; i++)
+ copyRoleFromItem(this, itemRoles[i], item, column);
+}
+
+void ItemData::fillTreeItemColumn(QTreeWidgetItem *item, int column, DesignerIconCache *iconCache) const
+{
+ QHash<int, QVariant>::const_iterator it = m_properties.constBegin(), end = m_properties.constEnd();
+ for (; it != end; ++it)
+ if (it.value().isValid()) {
+ item->setData(column, it.key(), it.value());
+ switch (it.key()) {
+ case Qt::DecorationPropertyRole:
+ if (iconCache)
+ item->setIcon(column, iconCache->icon(qVariantValue<PropertySheetIconValue>(it.value())));
+ break;
+ case Qt::DisplayPropertyRole:
+ item->setText(column, qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::ToolTipPropertyRole:
+ item->setToolTip(column, qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::StatusTipPropertyRole:
+ item->setStatusTip(column, qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ case Qt::WhatsThisPropertyRole:
+ item->setWhatsThis(column, qVariantValue<PropertySheetStringValue>(it.value()).value());
+ break;
+ }
+ }
+}
+
+ListContents::ListContents(const QTreeWidgetItem *item)
+{
+ for (int i = 0; i < item->columnCount(); i++)
+ m_items.append(ItemData(item, i));
+}
+
+QTreeWidgetItem *ListContents::createTreeItem(DesignerIconCache *iconCache) const
+{
+ QTreeWidgetItem *item = new QTreeWidgetItem;
+ int i = 0;
+ foreach (const ItemData &id, m_items)
+ id.fillTreeItemColumn(item, i++, iconCache);
+ return item;
+}
+
+void ListContents::createFromListWidget(const QListWidget *listWidget, bool editor)
+{
+ m_items.clear();
+
+ for (int i = 0; i < listWidget->count(); i++)
+ m_items.append(ItemData(listWidget->item(i), editor));
+}
+
+void ListContents::applyToListWidget(QListWidget *listWidget, DesignerIconCache *iconCache, bool editor) const
+{
+ listWidget->clear();
+
+ int i = 0;
+ foreach (const ItemData &entry, m_items) {
+ if (!entry.isValid())
+ new QListWidgetItem(TableWidgetContents::defaultHeaderText(i), listWidget);
+ else
+ listWidget->addItem(entry.createListItem(iconCache, editor));
+ i++;
+ }
+}
+
+void ListContents::createFromComboBox(const QComboBox *comboBox)
+{
+ m_items.clear();
+
+ const int count = comboBox->count();
+ for (int i = 0; i < count; i++) {
+ // We might encounter items added in a custom combo
+ // constructor. Ignore those.
+ const QVariant textValue = comboBox->itemData(i, Qt::DisplayPropertyRole);
+ if (!textValue.isNull()) {
+ ItemData entry;
+ entry.m_properties.insert(Qt::DisplayPropertyRole, textValue);
+ const QVariant iconValue = comboBox->itemData(i, Qt::DecorationPropertyRole);
+ if (!iconValue.isNull())
+ entry.m_properties.insert(Qt::DecorationPropertyRole, iconValue);
+ m_items.append(entry);
+ }
+ }
+}
+
+void ListContents::applyToComboBox(QComboBox *comboBox, DesignerIconCache *iconCache) const
+{
+ comboBox->clear();
+
+ foreach (const ItemData &hash, m_items) {
+ QIcon icon;
+ if (iconCache)
+ icon = iconCache->icon(qVariantValue<PropertySheetIconValue>(
+ hash.m_properties[Qt::DecorationPropertyRole]));
+ QVariant var = hash.m_properties[Qt::DisplayPropertyRole];
+ PropertySheetStringValue str = qVariantValue<PropertySheetStringValue>(var);
+ comboBox->addItem(icon, str.value());
+ comboBox->setItemData(comboBox->count() - 1,
+ var,
+ Qt::DisplayPropertyRole);
+ comboBox->setItemData(comboBox->count() - 1,
+ hash.m_properties[Qt::DecorationPropertyRole],
+ Qt::DecorationPropertyRole);
+ }
+}
+
+// --------- TableWidgetContents
+
+TableWidgetContents::TableWidgetContents() :
+ m_columnCount(0),
+ m_rowCount(0)
+{
+}
+
+void TableWidgetContents::clear()
+{
+ m_horizontalHeader.m_items.clear();
+ m_verticalHeader.m_items.clear();
+ m_items.clear();
+ m_columnCount = 0;
+ m_rowCount = 0;
+}
+
+QString TableWidgetContents::defaultHeaderText(int i)
+{
+ return QString::number(i + 1);
+}
+
+bool TableWidgetContents::nonEmpty(const QTableWidgetItem *item, int headerColumn)
+{
+ static int defaultFlags = QTableWidgetItem().flags();
+
+ if (item->flags() != defaultFlags)
+ return true;
+
+ QString text = qVariantValue<PropertySheetStringValue>(item->data(Qt::DisplayPropertyRole)).value();
+ if (!text.isEmpty()) {
+ if (headerColumn < 0 || text != defaultHeaderText(headerColumn))
+ return true;
+ } else {
+ // FIXME: This doesn't seem to make sense
+ return true;
+ }
+
+ for (int i = 0; itemRoles[i] != -1; i++)
+ if (itemRoles[i] != Qt::DisplayPropertyRole && item->data(itemRoles[i]).isValid())
+ return true;
+
+ return false;
+}
+
+void TableWidgetContents::insertHeaderItem(const QTableWidgetItem *item, int i, ListContents *header, bool editor)
+{
+ if (nonEmpty(item, i))
+ header->m_items.append(ItemData(item, editor));
+ else
+ header->m_items.append(ItemData());
+}
+
+void TableWidgetContents::fromTableWidget(const QTableWidget *tableWidget, bool editor)
+{
+ clear();
+ m_columnCount = tableWidget->columnCount();
+ m_rowCount = tableWidget->rowCount();
+ // horiz header: Legacy behaviour: auto-generate number for empty items
+ for (int col = 0; col < m_columnCount; col++)
+ if (const QTableWidgetItem *item = tableWidget->horizontalHeaderItem(col))
+ insertHeaderItem(item, col, &m_horizontalHeader, editor);
+ // vertical header: Legacy behaviour: auto-generate number for empty items
+ for (int row = 0; row < m_rowCount; row++)
+ if (const QTableWidgetItem *item = tableWidget->verticalHeaderItem(row))
+ insertHeaderItem(item, row, &m_verticalHeader, editor);
+ // cell data
+ for (int col = 0; col < m_columnCount; col++)
+ for (int row = 0; row < m_rowCount; row++)
+ if (const QTableWidgetItem *item = tableWidget->item(row, col))
+ if (nonEmpty(item, -1))
+ m_items.insert(CellRowColumnAddress(row, col), ItemData(item, editor));
+}
+
+void TableWidgetContents::applyToTableWidget(QTableWidget *tableWidget, DesignerIconCache *iconCache, bool editor) const
+{
+ tableWidget->clear();
+
+ tableWidget->setColumnCount(m_columnCount);
+ tableWidget->setRowCount(m_rowCount);
+
+ // horiz header
+ int col = 0;
+ foreach (const ItemData &id, m_horizontalHeader.m_items) {
+ if (id.isValid())
+ tableWidget->setHorizontalHeaderItem(col, id.createTableItem(iconCache, editor));
+ col++;
+ }
+ // vertical header
+ int row = 0;
+ foreach (const ItemData &id, m_verticalHeader.m_items) {
+ if (id.isValid())
+ tableWidget->setVerticalHeaderItem(row, id.createTableItem(iconCache, editor));
+ row++;
+ }
+ // items
+ const TableItemMap::const_iterator icend = m_items.constEnd();
+ for (TableItemMap::const_iterator it = m_items.constBegin(); it != icend; ++ it)
+ tableWidget->setItem(it.key().first, it.key().second, it.value().createTableItem(iconCache, editor));
+}
+
+bool TableWidgetContents::operator==(const TableWidgetContents &rhs) const
+{
+ if (m_columnCount != rhs.m_columnCount || m_rowCount != rhs.m_rowCount)
+ return false;
+
+ return m_horizontalHeader.m_items == rhs.m_horizontalHeader.m_items &&
+ m_verticalHeader.m_items == rhs.m_verticalHeader.m_items &&
+ m_items == rhs.m_items;
+}
+
+// ---- ChangeTableContentsCommand ----
+ChangeTableContentsCommand::ChangeTableContentsCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Change Table Contents"),
+ formWindow), m_iconCache(0)
+{
+ FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow);
+ if (fwb)
+ m_iconCache = fwb->iconCache();
+}
+
+void ChangeTableContentsCommand::init(QTableWidget *tableWidget,
+ const TableWidgetContents &oldCont, const TableWidgetContents &newCont)
+{
+ m_tableWidget = tableWidget;
+ m_oldContents = oldCont;
+ m_newContents = newCont;
+}
+
+void ChangeTableContentsCommand::redo()
+{
+ m_newContents.applyToTableWidget(m_tableWidget, m_iconCache, false);
+ QMetaObject::invokeMethod(m_tableWidget, "updateGeometries");
+}
+
+void ChangeTableContentsCommand::undo()
+{
+ m_oldContents.applyToTableWidget(m_tableWidget, m_iconCache, false);
+ QMetaObject::invokeMethod(m_tableWidget, "updateGeometries");
+}
+
+// --------- TreeWidgetContents
+TreeWidgetContents::ItemContents::ItemContents(const QTreeWidgetItem *item, bool editor) :
+ ListContents(item)
+{
+ static const int defaultFlags = QTreeWidgetItem().flags();
+
+ if (editor) {
+ QVariant v = item->data(0, ItemFlagsShadowRole);
+ m_itemFlags = v.isValid() ? v.toInt() : -1;
+ } else {
+ m_itemFlags = (item->flags() != defaultFlags) ? (int)item->flags() : -1;
+ }
+
+ for (int i = 0; i < item->childCount(); i++)
+ m_children.append(ItemContents(item->child(i), editor));
+}
+
+QTreeWidgetItem *TreeWidgetContents::ItemContents::createTreeItem(DesignerIconCache *iconCache, bool editor) const
+{
+ QTreeWidgetItem *item = ListContents::createTreeItem(iconCache);
+
+ if (editor)
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+
+ if (m_itemFlags != -1) {
+ if (editor)
+ item->setData(0, ItemFlagsShadowRole, qVariantFromValue(m_itemFlags));
+ else
+ item->setFlags((Qt::ItemFlags)m_itemFlags);
+ }
+
+ foreach (const ItemContents &ic, m_children)
+ item->addChild(ic.createTreeItem(iconCache, editor));
+
+ return item;
+}
+
+bool TreeWidgetContents::ItemContents::operator==(const TreeWidgetContents::ItemContents &rhs) const
+{
+ return
+ m_itemFlags == rhs.m_itemFlags &&
+ m_items == rhs.m_items &&
+ m_children == rhs.m_children;
+}
+
+void TreeWidgetContents::clear()
+{
+ m_headerItem.m_items.clear();
+ m_rootItems.clear();
+}
+
+void TreeWidgetContents::fromTreeWidget(const QTreeWidget *treeWidget, bool editor)
+{
+ clear();
+ m_headerItem = ListContents(treeWidget->headerItem());
+ for (int col = 0; col < treeWidget->topLevelItemCount(); col++)
+ m_rootItems.append(ItemContents(treeWidget->topLevelItem(col), editor));
+}
+
+void TreeWidgetContents::applyToTreeWidget(QTreeWidget *treeWidget, DesignerIconCache *iconCache, bool editor) const
+{
+ treeWidget->clear();
+
+ treeWidget->setColumnCount(m_headerItem.m_items.count());
+ treeWidget->setHeaderItem(m_headerItem.createTreeItem(iconCache));
+ foreach (const ItemContents &ic, m_rootItems)
+ treeWidget->addTopLevelItem(ic.createTreeItem(iconCache, editor));
+ treeWidget->expandAll();
+}
+
+bool TreeWidgetContents::operator==(const TreeWidgetContents &rhs) const
+{
+ return
+ m_headerItem == rhs.m_headerItem &&
+ m_rootItems == rhs.m_rootItems;
+}
+
+// ---- ChangeTreeContentsCommand ----
+ChangeTreeContentsCommand::ChangeTreeContentsCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Change Tree Contents"), formWindow),
+ m_iconCache(0)
+{
+ FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow);
+ if (fwb)
+ m_iconCache = fwb->iconCache();
+}
+
+void ChangeTreeContentsCommand::init(QTreeWidget *treeWidget,
+ const TreeWidgetContents &oldState, const TreeWidgetContents &newState)
+{
+ m_treeWidget = treeWidget;
+ m_oldState = oldState;
+ m_newState = newState;
+}
+
+void ChangeTreeContentsCommand::redo()
+{
+ m_newState.applyToTreeWidget(m_treeWidget, m_iconCache, false);
+}
+
+void ChangeTreeContentsCommand::undo()
+{
+ m_oldState.applyToTreeWidget(m_treeWidget, m_iconCache, false);
+}
+
+// ---- ChangeListContentsCommand ----
+ChangeListContentsCommand::ChangeListContentsCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QString(), formWindow), m_iconCache(0)
+{
+ FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow);
+ if (fwb)
+ m_iconCache = fwb->iconCache();
+}
+
+void ChangeListContentsCommand::init(QListWidget *listWidget,
+ const ListContents &oldItems, const ListContents &items)
+{
+ m_listWidget = listWidget;
+ m_comboBox = 0;
+
+ m_newItemsState = items;
+ m_oldItemsState = oldItems;
+}
+
+void ChangeListContentsCommand::init(QComboBox *comboBox,
+ const ListContents &oldItems, const ListContents &items)
+{
+ m_listWidget = 0;
+ m_comboBox = comboBox;
+
+ m_newItemsState = items;
+ m_oldItemsState = oldItems;
+}
+
+void ChangeListContentsCommand::redo()
+{
+ if (m_listWidget)
+ m_newItemsState.applyToListWidget(m_listWidget, m_iconCache, false);
+ else if (m_comboBox)
+ m_newItemsState.applyToComboBox(m_comboBox, m_iconCache);
+}
+
+void ChangeListContentsCommand::undo()
+{
+ if (m_listWidget)
+ m_oldItemsState.applyToListWidget(m_listWidget, m_iconCache, false);
+ else if (m_comboBox)
+ m_oldItemsState.applyToComboBox(m_comboBox, m_iconCache);
+}
+
+// ---- AddActionCommand ----
+
+AddActionCommand::AddActionCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Add action"), formWindow)
+{
+ m_action = 0;
+}
+
+void AddActionCommand::init(QAction *action)
+{
+ Q_ASSERT(m_action == 0);
+ m_action = action;
+}
+
+void AddActionCommand::redo()
+{
+ core()->actionEditor()->setFormWindow(formWindow());
+ core()->actionEditor()->manageAction(m_action);
+}
+
+void AddActionCommand::undo()
+{
+ core()->actionEditor()->setFormWindow(formWindow());
+ core()->actionEditor()->unmanageAction(m_action);
+}
+
+// ---- RemoveActionCommand ----
+
+RemoveActionCommand::RemoveActionCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Remove action"), formWindow),
+ m_action(0)
+{
+}
+
+static RemoveActionCommand::ActionData findActionIn(QAction *action)
+{
+ RemoveActionCommand::ActionData result;
+ // We only want menus and toolbars, no toolbuttons.
+ foreach (QWidget *widget, action->associatedWidgets())
+ if (qobject_cast<const QMenu *>(widget) || qobject_cast<const QToolBar *>(widget)) {
+ const QList<QAction*> actionList = widget->actions();
+ const int size = actionList.size();
+ for (int i = 0; i < size; ++i) {
+ if (actionList.at(i) == action) {
+ QAction *before = 0;
+ if (i + 1 < size)
+ before = actionList.at(i + 1);
+ result.append(RemoveActionCommand::ActionDataItem(before, widget));
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+void RemoveActionCommand::init(QAction *action)
+{
+ Q_ASSERT(m_action == 0);
+ m_action = action;
+
+ m_actionData = findActionIn(action);
+}
+
+void RemoveActionCommand::redo()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ foreach (const ActionDataItem &item, m_actionData) {
+ item.widget->removeAction(m_action);
+ }
+ // Notify components (for example, signal slot editor)
+ if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(fw))
+ fwb->emitObjectRemoved(m_action);
+
+ core()->actionEditor()->setFormWindow(fw);
+ core()->actionEditor()->unmanageAction(m_action);
+ if (!m_actionData.empty())
+ core()->objectInspector()->setFormWindow(fw);
+}
+
+void RemoveActionCommand::undo()
+{
+ core()->actionEditor()->setFormWindow(formWindow());
+ core()->actionEditor()->manageAction(m_action);
+ foreach (const ActionDataItem &item, m_actionData) {
+ item.widget->insertAction(item.before, m_action);
+ }
+ if (!m_actionData.empty())
+ core()->objectInspector()->setFormWindow(formWindow());
+}
+
+// ---- ActionInsertionCommand ----
+
+ActionInsertionCommand::ActionInsertionCommand(const QString &text, QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(text, formWindow),
+ m_parentWidget(0),
+ m_action(0),
+ m_beforeAction(0),
+ m_update(false)
+{
+}
+
+void ActionInsertionCommand::init(QWidget *parentWidget, QAction *action, QAction *beforeAction, bool update)
+{
+ Q_ASSERT(m_parentWidget == 0);
+ Q_ASSERT(m_action == 0);
+
+ m_parentWidget = parentWidget;
+ m_action = action;
+ m_beforeAction = beforeAction;
+ m_update = update;
+}
+
+void ActionInsertionCommand::insertAction()
+{
+ Q_ASSERT(m_action != 0);
+ Q_ASSERT(m_parentWidget != 0);
+
+ if (m_beforeAction)
+ m_parentWidget->insertAction(m_beforeAction, m_action);
+ else
+ m_parentWidget->addAction(m_action);
+
+ if (m_update) {
+ cheapUpdate();
+ if (QMenu *menu = m_action->menu())
+ selectUnmanagedObject(menu);
+ else
+ selectUnmanagedObject(m_action);
+ PropertyHelper::triggerActionChanged(m_action); // Update Used column in action editor.
+ }
+}
+void ActionInsertionCommand::removeAction()
+{
+ Q_ASSERT(m_action != 0);
+ Q_ASSERT(m_parentWidget != 0);
+
+ if (QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(m_parentWidget))
+ menu->hideSubMenu();
+
+ m_parentWidget->removeAction(m_action);
+
+ if (m_update) {
+ cheapUpdate();
+ selectUnmanagedObject(m_parentWidget);
+ PropertyHelper::triggerActionChanged(m_action); // Update Used column in action editor.
+ }
+}
+
+InsertActionIntoCommand::InsertActionIntoCommand(QDesignerFormWindowInterface *formWindow) :
+ ActionInsertionCommand(QApplication::translate("Command", "Add action"), formWindow)
+{
+}
+// ---- RemoveActionFromCommand ----
+
+RemoveActionFromCommand::RemoveActionFromCommand(QDesignerFormWindowInterface *formWindow) :
+ ActionInsertionCommand(QApplication::translate("Command", "Remove action"), formWindow)
+{
+}
+
+// ---- AddMenuActionCommand ----
+
+MenuActionCommand::MenuActionCommand(const QString &text, QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(text, formWindow),
+ m_action(0),
+ m_actionBefore(0),
+ m_menuParent(0),
+ m_associatedWidget(0),
+ m_objectToSelect(0)
+{
+}
+
+void MenuActionCommand::init(QAction *action, QAction *actionBefore,
+ QWidget *associatedWidget, QWidget *objectToSelect)
+{
+ QMenu *menu = action->menu();
+ Q_ASSERT(menu);
+ m_menuParent = menu->parentWidget();
+ m_action = action;
+ m_actionBefore = actionBefore;
+ m_associatedWidget = associatedWidget;
+ m_objectToSelect = objectToSelect;
+}
+
+void MenuActionCommand::insertMenu()
+{
+ core()->metaDataBase()->add(m_action);
+ QMenu *menu = m_action->menu();
+ if (m_menuParent && menu->parentWidget() != m_menuParent)
+ menu->setParent(m_menuParent);
+ core()->metaDataBase()->add(menu);
+ m_associatedWidget->insertAction(m_actionBefore, m_action);
+ cheapUpdate();
+ selectUnmanagedObject(menu);
+}
+
+void MenuActionCommand::removeMenu()
+{
+ m_action->menu()->setParent(0);
+ QMenu *menu = m_action->menu();
+ core()->metaDataBase()->remove(menu);
+ menu->setParent(0);
+ core()->metaDataBase()->remove(m_action);
+ m_associatedWidget->removeAction(m_action);
+ cheapUpdate();
+ selectUnmanagedObject(m_objectToSelect);
+}
+
+AddMenuActionCommand::AddMenuActionCommand(QDesignerFormWindowInterface *formWindow) :
+ MenuActionCommand(QApplication::translate("Command", "Add menu"), formWindow)
+{
+}
+
+// ---- RemoveMenuActionCommand ----
+RemoveMenuActionCommand::RemoveMenuActionCommand(QDesignerFormWindowInterface *formWindow) :
+ MenuActionCommand(QApplication::translate("Command", "Remove menu"), formWindow)
+{
+}
+
+// ---- CreateSubmenuCommand ----
+CreateSubmenuCommand::CreateSubmenuCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QApplication::translate("Command", "Create submenu"), formWindow),
+ m_action(0),
+ m_menu(0),
+ m_objectToSelect(0)
+{
+}
+
+void CreateSubmenuCommand::init(QDesignerMenu *menu, QAction *action, QObject *objectToSelect)
+{
+ m_menu = menu;
+ m_action = action;
+ m_objectToSelect = objectToSelect;
+}
+
+void CreateSubmenuCommand::redo()
+{
+ m_menu->createRealMenuAction(m_action);
+ cheapUpdate();
+ if (m_objectToSelect)
+ selectUnmanagedObject(m_objectToSelect);
+}
+
+void CreateSubmenuCommand::undo()
+{
+ m_menu->removeRealMenu(m_action);
+ cheapUpdate();
+ selectUnmanagedObject(m_menu);
+}
+
+// ---- DeleteToolBarCommand ----
+DeleteToolBarCommand::DeleteToolBarCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QApplication::translate("Command", "Delete Tool Bar"), formWindow)
+{
+}
+
+void DeleteToolBarCommand::init(QToolBar *toolBar)
+{
+ m_toolBar = toolBar;
+ m_mainWindow = qobject_cast<QMainWindow*>(toolBar->parentWidget());
+}
+
+void DeleteToolBarCommand::redo()
+{
+ if (m_mainWindow) {
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), m_mainWindow);
+ Q_ASSERT(c != 0);
+ for (int i=0; i<c->count(); ++i) {
+ if (c->widget(i) == m_toolBar) {
+ c->remove(i);
+ break;
+ }
+ }
+ }
+
+ core()->metaDataBase()->remove(m_toolBar);
+ m_toolBar->hide();
+ m_toolBar->setParent(formWindow());
+ formWindow()->emitSelectionChanged();
+}
+
+void DeleteToolBarCommand::undo()
+{
+ if (m_mainWindow) {
+ m_toolBar->setParent(m_mainWindow);
+ QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), m_mainWindow);
+
+ c->addWidget(m_toolBar);
+
+ core()->metaDataBase()->add(m_toolBar);
+ m_toolBar->show();
+ formWindow()->emitSelectionChanged();
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_command2.cpp b/tools/designer/src/lib/shared/qdesigner_command2.cpp
new file mode 100644
index 0000000000..db534c075d
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_command2.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_command2_p.h"
+#include "formwindowbase_p.h"
+#include "layoutinfo_p.h"
+#include "qdesigner_command_p.h"
+#include "widgetfactory_p.h"
+#include "qlayout_widget_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+
+#include <QtGui/QApplication>
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+MorphLayoutCommand::MorphLayoutCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow),
+ m_breakLayoutCommand(new BreakLayoutCommand(formWindow)),
+ m_layoutCommand(new LayoutCommand(formWindow)),
+ m_newType(LayoutInfo::VBox),
+ m_layoutBase(0)
+{
+}
+
+MorphLayoutCommand::~MorphLayoutCommand()
+{
+ delete m_layoutCommand;
+ delete m_breakLayoutCommand;
+}
+
+bool MorphLayoutCommand::init(QWidget *w, int newType)
+{
+ int oldType;
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!canMorph(fw, w, &oldType) || oldType == newType)
+ return false;
+ m_layoutBase = w;
+ m_newType = newType;
+ // Find all managed widgets
+ m_widgets.clear();
+ const QLayout *layout = LayoutInfo::managedLayout(fw->core(), w);
+ const int count = layout->count();
+ for (int i = 0; i < count ; i++) {
+ if (QWidget *w = layout->itemAt(i)->widget())
+ if (fw->isManaged(w))
+ m_widgets.push_back(w);
+ }
+ const bool reparentLayoutWidget = false; // leave QLayoutWidget intact
+ m_breakLayoutCommand->init(m_widgets, m_layoutBase, reparentLayoutWidget);
+ m_layoutCommand->init(m_layoutBase, m_widgets, static_cast<LayoutInfo::Type>(m_newType), m_layoutBase, reparentLayoutWidget);
+ setText(formatDescription(core(), m_layoutBase, oldType, newType));
+ return true;
+}
+
+bool MorphLayoutCommand::canMorph(const QDesignerFormWindowInterface *formWindow, QWidget *w, int *ptrToCurrentType)
+{
+ if (ptrToCurrentType)
+ *ptrToCurrentType = LayoutInfo::NoLayout;
+ // We want a managed widget or a container page
+ // with a level-0 managed layout
+ QDesignerFormEditorInterface *core = formWindow->core();
+ QLayout *layout = LayoutInfo::managedLayout(core, w);
+ if (!layout)
+ return false;
+ const LayoutInfo::Type type = LayoutInfo::layoutType(core, layout);
+ if (ptrToCurrentType)
+ *ptrToCurrentType = type;
+ switch (type) {
+ case LayoutInfo::HBox:
+ case LayoutInfo::VBox:
+ case LayoutInfo::Grid:
+ case LayoutInfo::Form:
+ return true;
+ break;
+ case LayoutInfo::NoLayout:
+ case LayoutInfo::HSplitter: // Nothing doing
+ case LayoutInfo::VSplitter:
+ case LayoutInfo::UnknownLayout:
+ break;
+ }
+ return false;
+}
+
+void MorphLayoutCommand::redo()
+{
+ m_breakLayoutCommand->redo();
+ m_layoutCommand->redo();
+ /* Transfer applicable properties which is a cross-section of the modified
+ * properties except object name. */
+ if (const LayoutProperties *properties = m_breakLayoutCommand->layoutProperties()) {
+ const int oldMask = m_breakLayoutCommand->propertyMask();
+ QLayout *newLayout = LayoutInfo::managedLayout(core(), m_layoutBase);
+ const int newMask = LayoutProperties::visibleProperties(newLayout);
+ const int applicableMask = (oldMask & newMask) & ~LayoutProperties::ObjectNameProperty;
+ if (applicableMask)
+ properties->toPropertySheet(core(), newLayout, applicableMask);
+ }
+}
+
+void MorphLayoutCommand::undo()
+{
+ m_layoutCommand->undo();
+ m_breakLayoutCommand->undo();
+}
+
+QString MorphLayoutCommand::formatDescription(QDesignerFormEditorInterface * /* core*/, const QWidget *w, int oldType, int newType)
+{
+ const QString oldName = LayoutInfo::layoutName(static_cast<LayoutInfo::Type>(oldType));
+ const QString newName = LayoutInfo::layoutName(static_cast<LayoutInfo::Type>(newType));
+ const QString widgetName = qobject_cast<const QLayoutWidget*>(w) ? w->layout()->objectName() : w->objectName();
+ return QApplication::translate("Command", "Change layout of '%1' from %2 to %3").arg(widgetName, oldName, newName);
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_command2_p.h b/tools/designer/src/lib/shared/qdesigner_command2_p.h
new file mode 100644
index 0000000000..e61222b17f
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_command2_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_COMMAND2_H
+#define QDESIGNER_COMMAND2_H
+
+#include "shared_global_p.h"
+#include "qdesigner_formwindowcommand_p.h"
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class LayoutCommand;
+class BreakLayoutCommand;
+
+/* This command changes the type of a managed layout on a widget (including
+ * red layouts of type 'QLayoutWidget') into another type, maintaining the
+ * applicable properties. It does this by chaining BreakLayoutCommand and
+ * LayoutCommand, parametrizing them not to actually delete/reparent
+ * QLayoutWidget's. */
+
+class QDESIGNER_SHARED_EXPORT MorphLayoutCommand : public QDesignerFormWindowCommand {
+ Q_DISABLE_COPY(MorphLayoutCommand)
+public:
+ explicit MorphLayoutCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~MorphLayoutCommand();
+
+ bool init(QWidget *w, int newType);
+
+ static bool canMorph(const QDesignerFormWindowInterface *formWindow, QWidget *w, int *ptrToCurrentType = 0);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ static QString formatDescription(QDesignerFormEditorInterface *core, const QWidget *w, int oldType, int newType);
+
+ BreakLayoutCommand *m_breakLayoutCommand;
+ LayoutCommand *m_layoutCommand;
+ int m_newType;
+ QWidgetList m_widgets;
+ QWidget *m_layoutBase;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_COMMAND2_H
diff --git a/tools/designer/src/lib/shared/qdesigner_command_p.h b/tools/designer/src/lib/shared/qdesigner_command_p.h
new file mode 100644
index 0000000000..3a4ce2d258
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_command_p.h
@@ -0,0 +1,1136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_COMMAND_H
+#define QDESIGNER_COMMAND_H
+
+#include "shared_global_p.h"
+#include "shared_enums_p.h"
+#include "layoutinfo_p.h"
+#include "qdesigner_utils_p.h"
+#include "qdesigner_formwindowcommand_p.h"
+#include "qdesigner_formeditorcommand_p.h"
+
+#include <QtDesigner/layoutdecoration.h>
+
+#include <QtGui/QIcon>
+#include <QtCore/QObject>
+#include <QtCore/QPair>
+#include <QtCore/QMap>
+#include <QtCore/QHash>
+#include <QtCore/QPoint>
+#include <QtCore/QRect>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerContainerExtension;
+class QDesignerMetaDataBaseItemInterface;
+class QDesignerMenu;
+
+class QMenuBar;
+class QStatusBar;
+class QToolBar;
+class QToolBox;
+class QTabWidget;
+class QTableWidget;
+class QTableWidgetItem;
+class QTreeWidget;
+class QTreeWidgetItem;
+class QListWidget;
+class QListWidgetItem;
+class QComboBox;
+class QStackedWidget;
+class QDockWidget;
+class QMainWindow;
+class QFormLayout;
+
+namespace qdesigner_internal {
+
+class Layout;
+class LayoutHelper;
+class PropertySheetIconValue;
+class DesignerIconCache;
+struct LayoutProperties;
+
+class QDESIGNER_SHARED_EXPORT InsertWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit InsertWidgetCommand(QDesignerFormWindowInterface *formWindow);
+ ~InsertWidgetCommand();
+
+ void init(QWidget *widget, bool already_in_form = false, int layoutRow = -1, int layoutColumn = -1);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ void refreshBuddyLabels();
+
+ QPointer<QWidget> m_widget;
+ QDesignerLayoutDecorationExtension::InsertMode m_insertMode;
+ QPair<int, int> m_cell;
+ LayoutHelper* m_layoutHelper;
+ bool m_widgetWasManaged;
+};
+
+class QDESIGNER_SHARED_EXPORT ChangeZOrderCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ChangeZOrderCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QWidget *widget);
+
+ virtual void redo();
+ virtual void undo();
+protected:
+ virtual QWidgetList reorderWidget(const QWidgetList &list, QWidget *widget) const = 0;
+ virtual void reorder(QWidget *widget) const = 0;
+
+private:
+ QPointer<QWidget> m_widget;
+ QPointer<QWidget> m_oldPreceding;
+ QList<QWidget *> m_oldParentZOrder;
+};
+
+class QDESIGNER_SHARED_EXPORT RaiseWidgetCommand: public ChangeZOrderCommand
+{
+
+public:
+ explicit RaiseWidgetCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QWidget *widget);
+
+protected:
+ virtual QWidgetList reorderWidget(const QWidgetList &list, QWidget *widget) const;
+ virtual void reorder(QWidget *widget) const;
+};
+
+class QDESIGNER_SHARED_EXPORT LowerWidgetCommand: public ChangeZOrderCommand
+{
+
+public:
+ explicit LowerWidgetCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QWidget *widget);
+
+protected:
+ virtual QWidgetList reorderWidget(const QWidgetList &list, QWidget *widget) const;
+ virtual void reorder(QWidget *widget) const;
+};
+
+class QDESIGNER_SHARED_EXPORT AdjustWidgetSizeCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit AdjustWidgetSizeCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QWidget *widget);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ QWidget *widgetForAdjust() const;
+ bool adjustNonLaidOutMainContainer(QWidget *integrationContainer);
+ void updatePropertyEditor() const;
+
+ QPointer<QWidget> m_widget;
+ QRect m_geometry;
+};
+
+// Helper to correctly unmanage a widget and its children for delete operations
+class QDESIGNER_SHARED_EXPORT ManageWidgetCommandHelper {
+public:
+ typedef QVector<QWidget*> WidgetVector;
+
+ ManageWidgetCommandHelper();
+ void init(const QDesignerFormWindowInterface *fw, QWidget *widget);
+ void init(QWidget *widget, const WidgetVector &managedChildren);
+
+ void manage(QDesignerFormWindowInterface *fw);
+ void unmanage(QDesignerFormWindowInterface *fw);
+
+ const WidgetVector &managedChildren() const { return m_managedChildren; }
+private:
+ QWidget *m_widget;
+ WidgetVector m_managedChildren;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit DeleteWidgetCommand(QDesignerFormWindowInterface *formWindow);
+ ~DeleteWidgetCommand();
+
+ enum DeleteFlags { DoNotUnmanage = 0x1, DoNotSimplifyLayout = 0x2 };
+
+ void init(QWidget *widget, unsigned flags = 0);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ QPointer<QWidget> m_widget;
+ QPointer<QWidget> m_parentWidget;
+ QRect m_geometry;
+ LayoutInfo::Type m_layoutType;
+ LayoutHelper* m_layoutHelper;
+ unsigned m_flags;
+ QRect m_layoutPosition;
+ int m_splitterIndex;
+ bool m_layoutSimplified;
+ QDesignerMetaDataBaseItemInterface *m_formItem;
+ int m_tabOrderIndex;
+ int m_widgetOrderIndex;
+ int m_zOrderIndex;
+ ManageWidgetCommandHelper m_manageHelper;
+};
+
+class QDESIGNER_SHARED_EXPORT ReparentWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ReparentWidgetCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QWidget *widget, QWidget *parentWidget);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ QPointer<QWidget> m_widget;
+ QPoint m_oldPos;
+ QPoint m_newPos;
+ QPointer<QWidget> m_oldParentWidget;
+ QPointer<QWidget> m_newParentWidget;
+ QList<QWidget *> m_oldParentList;
+ QList<QWidget *> m_oldParentZOrder;
+};
+
+class QDESIGNER_SHARED_EXPORT ChangeFormLayoutItemRoleCommand : public QDesignerFormWindowCommand
+{
+public:
+ enum Operation { SpanningToLabel = 0x1, SpanningToField = 0x2, LabelToSpanning = 0x4, FieldToSpanning =0x8 };
+
+ explicit ChangeFormLayoutItemRoleCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QWidget *widget, Operation op);
+
+ virtual void redo();
+ virtual void undo();
+
+ // Return a mask of possible operations of that item
+ static unsigned possibleOperations(QDesignerFormEditorInterface *core, QWidget *w);
+
+private:
+ static QFormLayout *managedFormLayoutOf(QDesignerFormEditorInterface *core, QWidget *w);
+ static Operation reverseOperation(Operation op);
+ void doOperation(Operation op);
+
+ QPointer<QWidget> m_widget;
+ Operation m_operation;
+};
+
+class QDESIGNER_SHARED_EXPORT ChangeLayoutItemGeometry: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ChangeLayoutItemGeometry(QDesignerFormWindowInterface *formWindow);
+
+ void init(QWidget *widget, int row, int column, int rowspan, int colspan);
+
+ virtual void redo();
+ virtual void undo();
+
+protected:
+ void changeItemPosition(const QRect &g);
+
+private:
+ QPointer<QWidget> m_widget;
+ QRect m_oldInfo;
+ QRect m_newInfo;
+};
+
+class QDESIGNER_SHARED_EXPORT TabOrderCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit TabOrderCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(const QList<QWidget*> &newTabOrder);
+
+ inline QList<QWidget*> oldTabOrder() const
+ { return m_oldTabOrder; }
+
+ inline QList<QWidget*> newTabOrder() const
+ { return m_newTabOrder; }
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ QDesignerMetaDataBaseItemInterface *m_widgetItem;
+ QList<QWidget*> m_oldTabOrder;
+ QList<QWidget*> m_newTabOrder;
+};
+
+class QDESIGNER_SHARED_EXPORT PromoteToCustomWidgetCommand : public QDesignerFormWindowCommand
+{
+public:
+ typedef QList<QPointer<QWidget> > WidgetList;
+
+ explicit PromoteToCustomWidgetCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(const WidgetList &widgets, const QString &customClassName);
+ virtual void redo();
+ virtual void undo();
+
+private:
+ void updateSelection();
+ WidgetList m_widgets;
+ QString m_customClassName;
+};
+
+class QDESIGNER_SHARED_EXPORT DemoteFromCustomWidgetCommand : public QDesignerFormWindowCommand
+{
+public:
+ typedef PromoteToCustomWidgetCommand::WidgetList WidgetList;
+
+ explicit DemoteFromCustomWidgetCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(const WidgetList &promoted);
+ virtual void redo();
+ virtual void undo();
+private:
+ PromoteToCustomWidgetCommand m_promote_cmd;
+};
+
+// Mixin class for storing the selection state
+class QDESIGNER_SHARED_EXPORT CursorSelectionState {
+ Q_DISABLE_COPY(CursorSelectionState)
+public:
+ CursorSelectionState();
+
+ void save(const QDesignerFormWindowInterface *formWindow);
+ void restore(QDesignerFormWindowInterface *formWindow) const;
+
+private:
+ typedef QList<QPointer<QWidget> > WidgetPointerList;
+ WidgetPointerList m_selection;
+ QPointer<QWidget> m_current;
+};
+
+class QDESIGNER_SHARED_EXPORT LayoutCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit LayoutCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~LayoutCommand();
+
+ inline QWidgetList widgets() const { return m_widgets; }
+
+ void init(QWidget *parentWidget, const QWidgetList &widgets, LayoutInfo::Type layoutType,
+ QWidget *layoutBase = 0,
+ // Reparent/Hide instances of QLayoutWidget.
+ bool reparentLayoutWidget = true);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ QPointer<QWidget> m_parentWidget;
+ QWidgetList m_widgets;
+ QPointer<QWidget> m_layoutBase;
+ QPointer<Layout> m_layout;
+ CursorSelectionState m_cursorSelectionState;
+ bool m_setup;
+};
+
+class QDESIGNER_SHARED_EXPORT BreakLayoutCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit BreakLayoutCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~BreakLayoutCommand();
+
+ inline QWidgetList widgets() const { return m_widgets; }
+
+ void init(const QWidgetList &widgets, QWidget *layoutBase,
+ // Reparent/Hide instances of QLayoutWidget.
+ bool reparentLayoutWidget = true);
+
+ virtual void redo();
+ virtual void undo();
+
+ // Access the properties of the layout, 0 in case of splitters.
+ const LayoutProperties *layoutProperties() const;
+ int propertyMask() const;
+
+private:
+ QWidgetList m_widgets;
+ QPointer<QWidget> m_layoutBase;
+ QPointer<Layout> m_layout;
+ LayoutHelper* m_layoutHelper;
+ LayoutProperties *m_properties;
+ int m_propertyMask;
+ CursorSelectionState m_cursorSelectionState;
+};
+
+class QDESIGNER_SHARED_EXPORT SimplifyLayoutCommand: public QDesignerFormWindowCommand
+{
+public:
+ explicit SimplifyLayoutCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~SimplifyLayoutCommand();
+
+ bool init(QWidget *layoutBase);
+
+ // Quick check
+ static bool canSimplify(QDesignerFormEditorInterface *core, const QWidget *w, int *layoutType = 0);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ const QRect m_area;
+ QWidget *m_layoutBase;
+ LayoutHelper* m_layoutHelper;
+ bool m_layoutSimplified;
+};
+
+class QDESIGNER_SHARED_EXPORT ToolBoxCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ToolBoxCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~ToolBoxCommand();
+
+ void init(QToolBox *toolBox);
+
+ virtual void removePage();
+ virtual void addPage();
+
+protected:
+ QPointer<QToolBox> m_toolBox;
+ QPointer<QWidget> m_widget;
+ int m_index;
+ QString m_itemText;
+ QIcon m_itemIcon;
+};
+
+class QDESIGNER_SHARED_EXPORT MoveToolBoxPageCommand: public ToolBoxCommand
+{
+
+public:
+ explicit MoveToolBoxPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~MoveToolBoxPageCommand();
+
+ void init(QToolBox *toolBox, QWidget *page, int newIndex);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ int m_newIndex;
+ int m_oldIndex;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteToolBoxPageCommand: public ToolBoxCommand
+{
+
+public:
+ explicit DeleteToolBoxPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~DeleteToolBoxPageCommand();
+
+ void init(QToolBox *toolBox);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT AddToolBoxPageCommand: public ToolBoxCommand
+{
+
+public:
+ enum InsertionMode {
+ InsertBefore,
+ InsertAfter
+ };
+ explicit AddToolBoxPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~AddToolBoxPageCommand();
+
+ void init(QToolBox *toolBox);
+ void init(QToolBox *toolBox, InsertionMode mode);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT TabWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit TabWidgetCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~TabWidgetCommand();
+
+ void init(QTabWidget *tabWidget);
+
+ virtual void removePage();
+ virtual void addPage();
+
+protected:
+ QPointer<QTabWidget> m_tabWidget;
+ QPointer<QWidget> m_widget;
+ int m_index;
+ QString m_itemText;
+ QIcon m_itemIcon;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteTabPageCommand: public TabWidgetCommand
+{
+
+public:
+ explicit DeleteTabPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~DeleteTabPageCommand();
+
+ void init(QTabWidget *tabWidget);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT AddTabPageCommand: public TabWidgetCommand
+{
+
+public:
+ enum InsertionMode {
+ InsertBefore,
+ InsertAfter
+ };
+ explicit AddTabPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~AddTabPageCommand();
+
+ void init(QTabWidget *tabWidget);
+ void init(QTabWidget *tabWidget, InsertionMode mode);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT MoveTabPageCommand: public TabWidgetCommand
+{
+
+public:
+ explicit MoveTabPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~MoveTabPageCommand();
+
+ void init(QTabWidget *tabWidget, QWidget *page,
+ const QIcon &icon, const QString &label,
+ int index, int newIndex);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ int m_newIndex;
+ int m_oldIndex;
+ QPointer<QWidget> m_page;
+ QString m_label;
+ QIcon m_icon;
+};
+
+class QDESIGNER_SHARED_EXPORT StackedWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit StackedWidgetCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~StackedWidgetCommand();
+
+ void init(QStackedWidget *stackedWidget);
+
+ virtual void removePage();
+ virtual void addPage();
+
+protected:
+ QPointer<QStackedWidget> m_stackedWidget;
+ QPointer<QWidget> m_widget;
+ int m_index;
+};
+
+class QDESIGNER_SHARED_EXPORT MoveStackedWidgetCommand: public StackedWidgetCommand
+{
+
+public:
+ explicit MoveStackedWidgetCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~MoveStackedWidgetCommand();
+
+ void init(QStackedWidget *stackedWidget, QWidget *page, int newIndex);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ int m_newIndex;
+ int m_oldIndex;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteStackedWidgetPageCommand: public StackedWidgetCommand
+{
+
+public:
+ explicit DeleteStackedWidgetPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~DeleteStackedWidgetPageCommand();
+
+ void init(QStackedWidget *stackedWidget);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT AddStackedWidgetPageCommand: public StackedWidgetCommand
+{
+
+public:
+ enum InsertionMode {
+ InsertBefore,
+ InsertAfter
+ };
+ explicit AddStackedWidgetPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~AddStackedWidgetPageCommand();
+
+ void init(QStackedWidget *stackedWidget);
+ void init(QStackedWidget *stackedWidget, InsertionMode mode);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT CreateMenuBarCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit CreateMenuBarCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QMainWindow *mainWindow);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QPointer<QMainWindow> m_mainWindow;
+ QPointer<QMenuBar> m_menuBar;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteMenuBarCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit DeleteMenuBarCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QMenuBar *menuBar);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QPointer<QMainWindow> m_mainWindow;
+ QPointer<QMenuBar> m_menuBar;
+};
+
+class QDESIGNER_SHARED_EXPORT CreateStatusBarCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit CreateStatusBarCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QMainWindow *mainWindow);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QPointer<QMainWindow> m_mainWindow;
+ QPointer<QStatusBar> m_statusBar;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteStatusBarCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit DeleteStatusBarCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QStatusBar *statusBar);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QPointer<QMainWindow> m_mainWindow;
+ QPointer<QStatusBar> m_statusBar;
+};
+
+class QDESIGNER_SHARED_EXPORT AddToolBarCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit AddToolBarCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QMainWindow *mainWindow);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QPointer<QMainWindow> m_mainWindow;
+ QPointer<QToolBar> m_toolBar;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteToolBarCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit DeleteToolBarCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QToolBar *toolBar);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QPointer<QMainWindow> m_mainWindow;
+ QPointer<QToolBar> m_toolBar;
+};
+
+class QDESIGNER_SHARED_EXPORT DockWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit DockWidgetCommand(const QString &description, QDesignerFormWindowInterface *formWindow);
+ virtual ~DockWidgetCommand();
+
+ void init(QDockWidget *dockWidget);
+
+protected:
+ QPointer<QDockWidget> m_dockWidget;
+};
+
+class QDESIGNER_SHARED_EXPORT AddDockWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit AddDockWidgetCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QMainWindow *mainWindow, QDockWidget *dockWidget);
+ void init(QMainWindow *mainWindow);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QPointer<QMainWindow> m_mainWindow;
+ QPointer<QDockWidget> m_dockWidget;
+};
+
+class QDESIGNER_SHARED_EXPORT ContainerWidgetCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ContainerWidgetCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~ContainerWidgetCommand();
+
+ QDesignerContainerExtension *containerExtension() const;
+
+ void init(QWidget *containerWidget);
+
+ virtual void removePage();
+ virtual void addPage();
+
+protected:
+ QPointer<QWidget> m_containerWidget;
+ QPointer<QWidget> m_widget;
+ int m_index;
+};
+
+class QDESIGNER_SHARED_EXPORT DeleteContainerWidgetPageCommand: public ContainerWidgetCommand
+{
+
+public:
+ explicit DeleteContainerWidgetPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~DeleteContainerWidgetPageCommand();
+
+ void init(QWidget *containerWidget, ContainerType ct);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT AddContainerWidgetPageCommand: public ContainerWidgetCommand
+{
+
+public:
+ enum InsertionMode {
+ InsertBefore,
+ InsertAfter
+ };
+ explicit AddContainerWidgetPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~AddContainerWidgetPageCommand();
+
+ void init(QWidget *containerWidget, ContainerType ct, InsertionMode mode);
+
+ virtual void redo();
+ virtual void undo();
+};
+
+class QDESIGNER_SHARED_EXPORT ChangeCurrentPageCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ChangeCurrentPageCommand(QDesignerFormWindowInterface *formWindow);
+ virtual ~ChangeCurrentPageCommand();
+
+ QDesignerContainerExtension *containerExtension() const;
+
+ void init(QWidget *containerWidget, int newIndex);
+
+ virtual void redo();
+ virtual void undo();
+
+protected:
+ QPointer<QWidget> m_containerWidget;
+ QPointer<QWidget> m_widget;
+ int m_oldIndex;
+ int m_newIndex;
+};
+
+struct QDESIGNER_SHARED_EXPORT ItemData {
+ ItemData() {}
+
+ ItemData(const QListWidgetItem *item, bool editor);
+ ItemData(const QTableWidgetItem *item, bool editor);
+ ItemData(const QTreeWidgetItem *item, int column);
+ QListWidgetItem *createListItem(DesignerIconCache *iconCache, bool editor) const;
+ QTableWidgetItem *createTableItem(DesignerIconCache *iconCache, bool editor) const;
+ void fillTreeItemColumn(QTreeWidgetItem *item, int column, DesignerIconCache *iconCache) const;
+
+ bool isValid() const { return !m_properties.isEmpty(); }
+ bool operator==(const ItemData &rhs) const { return m_properties == rhs.m_properties; }
+ bool operator!=(const ItemData &rhs) const { return m_properties != rhs.m_properties; }
+
+ QHash<int, QVariant> m_properties;
+};
+
+struct QDESIGNER_SHARED_EXPORT ListContents {
+ ListContents() {}
+
+ ListContents(const QTreeWidgetItem *item);
+ QTreeWidgetItem *createTreeItem(DesignerIconCache *iconCache) const;
+
+ void createFromListWidget(const QListWidget *listWidget, bool editor);
+ void applyToListWidget(QListWidget *listWidget, DesignerIconCache *iconCache, bool editor) const;
+ void createFromComboBox(const QComboBox *listWidget);
+ void applyToComboBox(QComboBox *listWidget, DesignerIconCache *iconCache) const;
+
+ bool operator==(const ListContents &rhs) const { return m_items == rhs.m_items; }
+ bool operator!=(const ListContents &rhs) const { return m_items != rhs.m_items; }
+
+ QList<ItemData> m_items;
+};
+
+// Data structure representing the contents of a QTableWidget with
+// methods to retrieve and apply for ChangeTableContentsCommand
+struct QDESIGNER_SHARED_EXPORT TableWidgetContents {
+
+ typedef QPair<int, int> CellRowColumnAddress;
+ typedef QMap<CellRowColumnAddress, ItemData> TableItemMap;
+
+ TableWidgetContents();
+ void clear();
+
+ void fromTableWidget(const QTableWidget *tableWidget, bool editor);
+ void applyToTableWidget(QTableWidget *tableWidget, DesignerIconCache *iconCache, bool editor) const;
+
+ bool operator==(const TableWidgetContents &rhs) const;
+ bool operator!=(const TableWidgetContents &rhs) const { return !(*this == rhs); }
+
+ static bool nonEmpty(const QTableWidgetItem *item, int headerColumn);
+ static QString defaultHeaderText(int i);
+ static void insertHeaderItem(const QTableWidgetItem *item, int i, ListContents *header, bool editor);
+
+ int m_columnCount;
+ int m_rowCount;
+ ListContents m_horizontalHeader;
+ ListContents m_verticalHeader;
+ TableItemMap m_items;
+};
+
+class QDESIGNER_SHARED_EXPORT ChangeTableContentsCommand: public QDesignerFormWindowCommand
+{
+public:
+ explicit ChangeTableContentsCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QTableWidget *tableWidget, const TableWidgetContents &oldCont, const TableWidgetContents &newCont);
+ virtual void redo();
+ virtual void undo();
+
+private:
+ QPointer<QTableWidget> m_tableWidget;
+ TableWidgetContents m_oldContents;
+ TableWidgetContents m_newContents;
+ DesignerIconCache *m_iconCache;
+};
+
+// Data structure representing the contents of a QTreeWidget with
+// methods to retrieve and apply for ChangeTreeContentsCommand
+struct QDESIGNER_SHARED_EXPORT TreeWidgetContents {
+
+ struct ItemContents : public ListContents {
+ ItemContents() : m_itemFlags(-1) {}
+ ItemContents(const QTreeWidgetItem *item, bool editor);
+ QTreeWidgetItem *createTreeItem(DesignerIconCache *iconCache, bool editor) const;
+
+ bool operator==(const ItemContents &rhs) const;
+ bool operator!=(const ItemContents &rhs) const { return !(*this == rhs); }
+
+ int m_itemFlags;
+ //bool m_firstColumnSpanned:1;
+ //bool m_hidden:1;
+ //bool m_expanded:1;
+ QList<ItemContents> m_children;
+ };
+
+ void clear();
+
+ void fromTreeWidget(const QTreeWidget *treeWidget, bool editor);
+ void applyToTreeWidget(QTreeWidget *treeWidget, DesignerIconCache *iconCache, bool editor) const;
+
+ bool operator==(const TreeWidgetContents &rhs) const;
+ bool operator!=(const TreeWidgetContents &rhs) const { return !(*this == rhs); }
+
+ ListContents m_headerItem;
+ QList<ItemContents> m_rootItems;
+};
+
+class QDESIGNER_SHARED_EXPORT ChangeTreeContentsCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ChangeTreeContentsCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QTreeWidget *treeWidget, const TreeWidgetContents &oldState, const TreeWidgetContents &newState);
+ virtual void redo();
+ virtual void undo();
+ enum ApplyIconStrategy {
+ SetIconStrategy,
+ ResetIconStrategy
+ };
+private:
+ QPointer<QTreeWidget> m_treeWidget;
+ TreeWidgetContents m_oldState;
+ TreeWidgetContents m_newState;
+ DesignerIconCache *m_iconCache;
+};
+
+class QDESIGNER_SHARED_EXPORT ChangeListContentsCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit ChangeListContentsCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QListWidget *listWidget, const ListContents &oldItems, const ListContents &items);
+ void init(QComboBox *comboBox, const ListContents &oldItems, const ListContents &items);
+ virtual void redo();
+ virtual void undo();
+private:
+ QPointer<QListWidget> m_listWidget;
+ QPointer<QComboBox> m_comboBox;
+ ListContents m_oldItemsState;
+ ListContents m_newItemsState;
+ DesignerIconCache *m_iconCache;
+};
+
+class QDESIGNER_SHARED_EXPORT AddActionCommand : public QDesignerFormWindowCommand
+{
+
+public:
+ explicit AddActionCommand(QDesignerFormWindowInterface *formWindow);
+ void init(QAction *action);
+ virtual void redo();
+ virtual void undo();
+private:
+ QAction *m_action;
+};
+
+// Note: This command must be executed within a macro since it
+// makes the form emit objectRemoved() which might cause other components
+// to add commands (for example, removal of signals and slots
+class QDESIGNER_SHARED_EXPORT RemoveActionCommand : public QDesignerFormWindowCommand
+{
+
+public:
+ explicit RemoveActionCommand(QDesignerFormWindowInterface *formWindow);
+ void init(QAction *action);
+ virtual void redo();
+ virtual void undo();
+
+ struct ActionDataItem {
+ ActionDataItem(QAction *_before = 0, QWidget *_widget = 0)
+ : before(_before), widget(_widget) {}
+ QAction *before;
+ QWidget *widget;
+ };
+ typedef QList<ActionDataItem> ActionData;
+
+private:
+ QAction *m_action;
+
+ ActionData m_actionData;
+};
+
+class QDESIGNER_SHARED_EXPORT ActionInsertionCommand : public QDesignerFormWindowCommand
+{
+
+protected:
+ ActionInsertionCommand(const QString &text, QDesignerFormWindowInterface *formWindow);
+
+public:
+ void init(QWidget *parentWidget, QAction *action, QAction *beforeAction = 0, bool update = true);
+
+protected:
+ void insertAction();
+ void removeAction();
+
+private:
+ QWidget *m_parentWidget;
+ QAction *m_action;
+ QAction *m_beforeAction;
+ bool m_update;
+};
+
+class QDESIGNER_SHARED_EXPORT InsertActionIntoCommand : public ActionInsertionCommand
+{
+
+public:
+ explicit InsertActionIntoCommand(QDesignerFormWindowInterface *formWindow);
+
+ virtual void redo() { insertAction(); }
+ virtual void undo() { removeAction(); }
+};
+
+class QDESIGNER_SHARED_EXPORT RemoveActionFromCommand : public ActionInsertionCommand
+{
+
+public:
+ explicit RemoveActionFromCommand(QDesignerFormWindowInterface *formWindow);
+
+ virtual void redo() { removeAction(); }
+ virtual void undo() { insertAction(); }
+};
+
+class QDESIGNER_SHARED_EXPORT MenuActionCommand : public QDesignerFormWindowCommand
+{
+public:
+ void init(QAction *action, QAction *actionBefore, QWidget *associatedWidget, QWidget *objectToSelect);
+
+protected:
+ MenuActionCommand(const QString &text, QDesignerFormWindowInterface *formWindow);
+ void insertMenu();
+ void removeMenu();
+
+private:
+ QAction *m_action;
+ QAction *m_actionBefore;
+ QWidget *m_menuParent;
+ QWidget *m_associatedWidget;
+ QWidget *m_objectToSelect;
+};
+
+class QDESIGNER_SHARED_EXPORT AddMenuActionCommand : public MenuActionCommand
+{
+
+public:
+ explicit AddMenuActionCommand(QDesignerFormWindowInterface *formWindow);
+
+ virtual void redo() { insertMenu(); }
+ virtual void undo() { removeMenu(); }
+};
+
+class QDESIGNER_SHARED_EXPORT RemoveMenuActionCommand : public MenuActionCommand
+{
+
+public:
+ explicit RemoveMenuActionCommand(QDesignerFormWindowInterface *formWindow);
+
+ virtual void redo() { removeMenu(); }
+ virtual void undo() { insertMenu(); }
+};
+
+class QDESIGNER_SHARED_EXPORT CreateSubmenuCommand : public QDesignerFormWindowCommand
+{
+
+public:
+ explicit CreateSubmenuCommand(QDesignerFormWindowInterface *formWindow);
+ void init(QDesignerMenu *menu, QAction *action, QObject *m_objectToSelect = 0);
+ virtual void redo();
+ virtual void undo();
+private:
+ QAction *m_action;
+ QDesignerMenu *m_menu;
+ QObject *m_objectToSelect;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_COMMAND_H
diff --git a/tools/designer/src/lib/shared/qdesigner_dnditem.cpp b/tools/designer/src/lib/shared/qdesigner_dnditem.cpp
new file mode 100644
index 0000000000..5dfbb65ff8
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_dnditem.cpp
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_dnditem_p.h"
+#include "formwindowbase_p.h"
+#include "ui4_p.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QBitmap>
+#include <QtGui/QPixmap>
+#include <QtGui/QImage>
+#include <QtGui/QLabel>
+#include <QtGui/QDrag>
+#include <QtGui/QCursor>
+#include <QtGui/QDropEvent>
+#include <QtGui/QRgb>
+
+#include <QtCore/QMultiMap>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QDesignerDnDItem::QDesignerDnDItem(DropType type, QWidget *source) :
+ m_source(source),
+ m_type(type),
+ m_dom_ui(0),
+ m_widget(0),
+ m_decoration(0)
+{
+}
+
+void QDesignerDnDItem::init(DomUI *ui, QWidget *widget, QWidget *decoration,
+ const QPoint &global_mouse_pos)
+{
+ Q_ASSERT(widget != 0 || ui != 0);
+ Q_ASSERT(decoration != 0);
+
+ m_dom_ui = ui;
+ m_widget = widget;
+ m_decoration = decoration;
+
+ const QRect geometry = m_decoration->geometry();
+ m_hot_spot = global_mouse_pos - m_decoration->geometry().topLeft();
+}
+
+QDesignerDnDItem::~QDesignerDnDItem()
+{
+ if (m_decoration != 0)
+ m_decoration->deleteLater();
+ delete m_dom_ui;
+}
+
+DomUI *QDesignerDnDItem::domUi() const
+{
+ return m_dom_ui;
+}
+
+QWidget *QDesignerDnDItem::decoration() const
+{
+ return m_decoration;
+}
+
+QPoint QDesignerDnDItem::hotSpot() const
+{
+ return m_hot_spot;
+}
+
+QWidget *QDesignerDnDItem::widget() const
+{
+ return m_widget;
+}
+
+QDesignerDnDItem::DropType QDesignerDnDItem::type() const
+{
+ return m_type;
+}
+
+QWidget *QDesignerDnDItem::source() const
+{
+ return m_source;
+}
+
+void QDesignerDnDItem::setDomUi(DomUI *dom_ui)
+{
+ delete m_dom_ui;
+ m_dom_ui = dom_ui;
+}
+
+// ---------- QDesignerMimeData
+
+// Make pixmap transparent on Windows only. Mac is transparent by default, Unix usually does not work.
+#ifdef Q_WS_WIN
+# define TRANSPARENT_DRAG_PIXMAP
+#endif
+
+QDesignerMimeData::QDesignerMimeData(const QDesignerDnDItems &items, QDrag *drag) :
+ m_items(items)
+{
+ enum { Alpha = 200 };
+ QPoint decorationTopLeft;
+ switch (m_items.size()) {
+ case 0:
+ break;
+ case 1: {
+ QWidget *deco = m_items.first()->decoration();
+ decorationTopLeft = deco->pos();
+ const QPixmap widgetPixmap = QPixmap::grabWidget(deco);
+#ifdef TRANSPARENT_DRAG_PIXMAP
+ QImage image(widgetPixmap.size(), QImage::Format_ARGB32);
+ image.fill(QColor(Qt::transparent).rgba());
+ QPainter painter(&image);
+ painter.drawPixmap(QPoint(0, 0), widgetPixmap);
+ painter.end();
+ setImageTransparency(image, Alpha);
+ drag->setPixmap(QPixmap::fromImage(image));
+#else
+ drag->setPixmap(widgetPixmap);
+#endif
+ }
+ break;
+ default: {
+ // determine size of drag decoration by uniting all geometries
+ const QDesignerDnDItems::const_iterator cend = m_items.constEnd();
+ QDesignerDnDItems::const_iterator it =m_items.constBegin();
+ QRect unitedGeometry = (*it)->decoration()->geometry();
+ for (++it; it != cend; ++it )
+ unitedGeometry = unitedGeometry .united((*it)->decoration()->geometry());
+
+ // paint with offset. At the same time, create a mask bitmap, containing widget rectangles.
+ QImage image(unitedGeometry.size(), QImage::Format_ARGB32);
+ image.fill(QColor(Qt::transparent).rgba());
+ QBitmap mask(unitedGeometry.size());
+ mask.clear();
+ // paint with offset, determine action
+ QPainter painter(&image);
+ QPainter maskPainter(&mask);
+ decorationTopLeft = unitedGeometry.topLeft();
+ for (it = m_items.constBegin() ; it != cend; ++it ) {
+ QWidget *w = (*it)->decoration();
+ const QPixmap wp = QPixmap::grabWidget(w);
+ const QPoint pos = w->pos() - decorationTopLeft;
+ painter.drawPixmap(pos, wp);
+ maskPainter.fillRect(QRect(pos, wp.size()), Qt::color1);
+ }
+ painter.end();
+ maskPainter.end();
+#ifdef TRANSPARENT_DRAG_PIXMAP
+ setImageTransparency(image, Alpha);
+#endif
+ QPixmap pixmap = QPixmap::fromImage(image);
+ pixmap.setMask(mask);
+ drag->setPixmap(pixmap);
+ }
+ break;
+ }
+ // determine hot spot and reconstruct the exact starting position as form window
+ // introduces some offset when detecting DnD
+ m_globalStartPos = m_items.first()->decoration()->pos() + m_items.first()->hotSpot();
+ m_hotSpot = m_globalStartPos - decorationTopLeft;
+ drag->setHotSpot(m_hotSpot);
+
+ drag->setMimeData(this);
+}
+
+QDesignerMimeData::~QDesignerMimeData()
+{
+ const QDesignerDnDItems::const_iterator cend = m_items.constEnd();
+ for (QDesignerDnDItems::const_iterator it = m_items.constBegin(); it != cend; ++it )
+ delete *it;
+}
+
+Qt::DropAction QDesignerMimeData::proposedDropAction() const
+{
+ return m_items.first()->type() == QDesignerDnDItemInterface::CopyDrop ? Qt::CopyAction : Qt::MoveAction;
+}
+
+Qt::DropAction QDesignerMimeData::execDrag(const QDesignerDnDItems &items, QWidget * dragSource)
+{
+ if (items.empty())
+ return Qt::IgnoreAction;
+
+ QDrag *drag = new QDrag(dragSource);
+ QDesignerMimeData *mimeData = new QDesignerMimeData(items, drag);
+
+ // Store pointers to widgets that are to be re-shown if a move operation is canceled
+ QWidgetList reshowWidgets;
+ const QDesignerDnDItems::const_iterator cend = items.constEnd();
+ for (QDesignerDnDItems::const_iterator it = items.constBegin(); it != cend; ++it )
+ if (QWidget *w = (*it)->widget())
+ if ((*it)->type() == QDesignerDnDItemInterface::MoveDrop)
+ reshowWidgets.push_back(w);
+
+ const Qt::DropAction executedAction = drag->exec(Qt::CopyAction|Qt::MoveAction, mimeData->proposedDropAction());
+
+ if (executedAction == Qt::IgnoreAction && !reshowWidgets.empty())
+ foreach (QWidget *w, reshowWidgets)
+ w->show();
+
+ return executedAction;
+}
+
+
+void QDesignerMimeData::moveDecoration(const QPoint &globalPos) const
+{
+ const QPoint relativeDistance = globalPos - m_globalStartPos;
+ const QDesignerDnDItems::const_iterator cend = m_items.constEnd();
+ for (QDesignerDnDItems::const_iterator it =m_items.constBegin(); it != cend; ++it ) {
+ QWidget *w = (*it)->decoration();
+ w->move(w->pos() + relativeDistance);
+ }
+}
+
+void QDesignerMimeData::removeMovedWidgetsFromSourceForm(const QDesignerDnDItems &items)
+{
+ typedef QMultiMap<FormWindowBase *, QWidget *> FormWidgetMap;
+ FormWidgetMap formWidgetMap;
+ // Find moved widgets per form
+ const QDesignerDnDItems::const_iterator cend = items.constEnd();
+ for (QDesignerDnDItems::const_iterator it = items.constBegin(); it != cend; ++it )
+ if ((*it)->type() == QDesignerDnDItemInterface::MoveDrop)
+ if (QWidget *w = (*it)->widget())
+ if (FormWindowBase *fb = qobject_cast<FormWindowBase *>((*it)->source()))
+ formWidgetMap.insert(fb, w);
+ if (formWidgetMap.empty())
+ return;
+
+ foreach (FormWindowBase * fb, formWidgetMap.keys())
+ fb->deleteWidgetList(formWidgetMap.values(fb));
+}
+
+void QDesignerMimeData::acceptEventWithAction(Qt::DropAction desiredAction, QDropEvent *e)
+{
+ if (e->proposedAction() == desiredAction) {
+ e->acceptProposedAction();
+ } else {
+ e->setDropAction(desiredAction);
+ e->accept();
+ }
+}
+
+void QDesignerMimeData::acceptEvent(QDropEvent *e) const
+{
+ acceptEventWithAction(proposedDropAction(), e);
+}
+
+void QDesignerMimeData::setImageTransparency(QImage &image, int alpha)
+{
+ const int height = image.height();
+ for (int l = 0; l < height; l++) {
+ QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(l));
+ QRgb *lineEnd = line + image.width();
+ for ( ; line < lineEnd; line++) {
+ const QRgb rgba = *line;
+ *line = qRgba(qRed(rgba), qGreen(rgba), qBlue(rgba), alpha);
+ }
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_dnditem_p.h b/tools/designer/src/lib/shared/qdesigner_dnditem_p.h
new file mode 100644
index 0000000000..cf36b393fc
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_dnditem_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_DNDITEM_H
+#define QDESIGNER_DNDITEM_H
+
+#include "shared_global_p.h"
+#include <QtDesigner/abstractdnditem.h>
+
+#include <QtCore/QPoint>
+#include <QtCore/QList>
+#include <QtCore/QMimeData>
+
+QT_BEGIN_NAMESPACE
+
+class QDrag;
+class QImage;
+class QDropEvent;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT QDesignerDnDItem: public QDesignerDnDItemInterface
+{
+public:
+ explicit QDesignerDnDItem(DropType type, QWidget *source = 0);
+ virtual ~QDesignerDnDItem();
+
+ virtual DomUI *domUi() const;
+ virtual QWidget *decoration() const;
+ virtual QWidget *widget() const;
+ virtual QPoint hotSpot() const;
+ virtual QWidget *source() const;
+
+ virtual DropType type() const;
+
+protected:
+ void setDomUi(DomUI *dom_ui);
+ void init(DomUI *ui, QWidget *widget, QWidget *decoration, const QPoint &global_mouse_pos);
+
+private:
+ QWidget *m_source;
+ const DropType m_type;
+ const QPoint m_globalStartPos;
+ DomUI *m_dom_ui;
+ QWidget *m_widget;
+ QWidget *m_decoration;
+ QPoint m_hot_spot;
+
+ Q_DISABLE_COPY(QDesignerDnDItem)
+};
+
+// Mime data for use with designer drag and drop operations.
+
+class QDESIGNER_SHARED_EXPORT QDesignerMimeData : public QMimeData {
+ Q_OBJECT
+
+public:
+ typedef QList<QDesignerDnDItemInterface *> QDesignerDnDItems;
+
+ virtual ~QDesignerMimeData();
+
+ const QDesignerDnDItems &items() const { return m_items; }
+
+ // Execute a drag and drop operation.
+ static Qt::DropAction execDrag(const QDesignerDnDItems &items, QWidget * dragSource);
+
+ QPoint hotSpot() const { return m_hotSpot; }
+
+ // Move the decoration. Required for drops over form windows as the position
+ // is derived from the decoration position.
+ void moveDecoration(const QPoint &globalPos) const;
+
+ // For a move operation, create the undo command sequence to remove
+ // the widgets from the source form.
+ static void removeMovedWidgetsFromSourceForm(const QDesignerDnDItems &items);
+
+ // Accept an event with the proper action.
+ void acceptEvent(QDropEvent *e) const;
+
+ // Helper to accept an event with the desired action.
+ static void acceptEventWithAction(Qt::DropAction desiredAction, QDropEvent *e);
+
+private:
+ QDesignerMimeData(const QDesignerDnDItems &items, QDrag *drag);
+ Qt::DropAction proposedDropAction() const;
+
+ static void setImageTransparency(QImage &image, int alpha);
+
+ const QDesignerDnDItems m_items;
+ QPoint m_globalStartPos;
+ QPoint m_hotSpot;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_DNDITEM_H
diff --git a/tools/designer/src/lib/shared/qdesigner_dockwidget.cpp b/tools/designer/src/lib/shared/qdesigner_dockwidget.cpp
new file mode 100644
index 0000000000..b678982d3e
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_dockwidget.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_dockwidget_p.h"
+#include "layoutinfo_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+
+#include <QtGui/QMainWindow>
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+QDesignerDockWidget::QDesignerDockWidget(QWidget *parent)
+ : QDockWidget(parent)
+{
+}
+
+QDesignerDockWidget::~QDesignerDockWidget()
+{
+}
+
+bool QDesignerDockWidget::docked() const
+{
+ return qobject_cast<QMainWindow*>(parentWidget()) != 0;
+}
+
+void QDesignerDockWidget::setDocked(bool b)
+{
+ if (QMainWindow *mainWindow = findMainWindow()) {
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerContainerExtension *c;
+ c = qt_extension<QDesignerContainerExtension*>(core->extensionManager(), mainWindow);
+ if (b && !docked()) {
+ // Dock it
+ // ### undo/redo stack
+ setParent(0);
+ c->addWidget(this);
+ formWindow()->selectWidget(this, formWindow()->cursor()->isWidgetSelected(this));
+ } else if (!b && docked()) {
+ // Undock it
+ for (int i = 0; i < c->count(); ++i) {
+ if (c->widget(i) == this) {
+ c->remove(i);
+ break;
+ }
+ }
+ // #### restore the position
+ setParent(mainWindow->centralWidget());
+ show();
+ formWindow()->selectWidget(this, formWindow()->cursor()->isWidgetSelected(this));
+ }
+ }
+}
+
+Qt::DockWidgetArea QDesignerDockWidget::dockWidgetArea() const
+{
+ if (QMainWindow *mainWindow = qobject_cast<QMainWindow*>(parentWidget()))
+ return mainWindow->dockWidgetArea(const_cast<QDesignerDockWidget*>(this));
+
+ return Qt::LeftDockWidgetArea;
+}
+
+void QDesignerDockWidget::setDockWidgetArea(Qt::DockWidgetArea dockWidgetArea)
+{
+ if (QMainWindow *mainWindow = qobject_cast<QMainWindow*>(parentWidget())) {
+ if ((dockWidgetArea != Qt::NoDockWidgetArea)
+ && isAreaAllowed(dockWidgetArea)) {
+ mainWindow->addDockWidget(dockWidgetArea, this);
+ }
+ }
+}
+
+bool QDesignerDockWidget::inMainWindow() const
+{
+ QMainWindow *mw = findMainWindow();
+ if (mw && !mw->centralWidget()->layout()) {
+ if (mw == parentWidget())
+ return true;
+ if (mw->centralWidget() == parentWidget())
+ return true;
+ }
+ return false;
+}
+
+QDesignerFormWindowInterface *QDesignerDockWidget::formWindow() const
+{
+ return QDesignerFormWindowInterface::findFormWindow(const_cast<QDesignerDockWidget*>(this));
+}
+
+QMainWindow *QDesignerDockWidget::findMainWindow() const
+{
+ if (QDesignerFormWindowInterface *fw = formWindow())
+ return qobject_cast<QMainWindow*>(fw->mainContainer());
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_dockwidget_p.h b/tools/designer/src/lib/shared/qdesigner_dockwidget_p.h
new file mode 100644
index 0000000000..f0559083f1
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_dockwidget_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_DOCKWIDGET_H
+#define QDESIGNER_DOCKWIDGET_H
+
+#include "shared_global_p.h"
+#include <QtGui/QDockWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+class QDESIGNER_SHARED_EXPORT QDesignerDockWidget: public QDockWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::DockWidgetArea dockWidgetArea READ dockWidgetArea WRITE setDockWidgetArea DESIGNABLE docked STORED false)
+ Q_PROPERTY(bool docked READ docked WRITE setDocked DESIGNABLE inMainWindow STORED false)
+public:
+ QDesignerDockWidget(QWidget *parent = 0);
+ virtual ~QDesignerDockWidget();
+
+ bool docked() const;
+ void setDocked(bool b);
+
+ Qt::DockWidgetArea dockWidgetArea() const;
+ void setDockWidgetArea(Qt::DockWidgetArea dockWidgetArea);
+
+ bool inMainWindow() const;
+
+private:
+ QDesignerFormWindowInterface *formWindow() const;
+ QMainWindow *findMainWindow() const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_DOCKWIDGET_H
diff --git a/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp b/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp
new file mode 100644
index 0000000000..6394847dbb
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formbuilder.cpp
@@ -0,0 +1,478 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_formbuilder_p.h"
+#include "dynamicpropertysheet.h"
+#include "qsimpleresource_p.h"
+#include "widgetfactory_p.h"
+#include "qdesigner_introspection_p.h"
+
+#include <ui4_p.h>
+#include <formbuilderextra_p.h>
+// sdk
+#include <QtDesigner/container.h>
+#include <QtDesigner/customwidget.h>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+#include <abstractdialoggui_p.h>
+
+// shared
+#include <qdesigner_propertysheet_p.h>
+#include <qdesigner_utils_p.h>
+#include <formwindowbase_p.h>
+#include <qtresourcemodel_p.h>
+#include <scripterrordialog_p.h>
+
+#include <QtGui/QWidget>
+#include <QtGui/QMenu>
+#include <QtGui/QToolBar>
+#include <QtGui/QMenuBar>
+#include <QtGui/QMainWindow>
+#include <QtGui/QStyleFactory>
+#include <QtGui/QStyle>
+#include <QtGui/QApplication>
+#include <QtGui/QAbstractScrollArea>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPixmap>
+
+#include <QtCore/QBuffer>
+#include <QtCore/qdebug.h>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+static QString summarizeScriptErrors(const QFormScriptRunner::Errors &errors)
+{
+ QString rc = QCoreApplication::translate("QDesignerFormBuilder", "Script errors occurred:");
+ foreach (QFormScriptRunner::Error error, errors) {
+ rc += QLatin1Char('\n');
+ rc += error.errorMessage;
+ }
+ return rc;
+}
+
+namespace qdesigner_internal {
+
+QDesignerFormBuilder::QDesignerFormBuilder(QDesignerFormEditorInterface *core,
+ Mode mode,
+ const DeviceProfile &deviceProfile) :
+ m_core(core),
+ m_mode(mode),
+ m_deviceProfile(deviceProfile),
+ m_pixmapCache(0),
+ m_iconCache(0),
+ m_ignoreCreateResources(false),
+ m_tempResourceSet(0),
+ m_mainWidget(true)
+{
+ Q_ASSERT(m_core);
+ // Disable scripting in the editors.
+ QFormScriptRunner::Options options = formScriptRunner()->options();
+ switch (m_mode) {
+ case DisableScripts:
+ options |= QFormScriptRunner::DisableScripts;
+ break;
+ case EnableScripts:
+ options |= QFormScriptRunner::DisableWarnings;
+ options &= ~QFormScriptRunner::DisableScripts;
+ break;
+ }
+ formScriptRunner()-> setOptions(options);
+}
+
+QString QDesignerFormBuilder::systemStyle() const
+{
+ return m_deviceProfile.isEmpty() ?
+ QString::fromUtf8(QApplication::style()->metaObject()->className()) :
+ m_deviceProfile.style();
+}
+
+QWidget *QDesignerFormBuilder::createWidgetFromContents(const QString &contents, QWidget *parentWidget)
+{
+ QByteArray data = contents.toUtf8();
+ QBuffer buffer(&data);
+ buffer.open(QIODevice::ReadOnly);
+ return load(&buffer, parentWidget);
+}
+
+QWidget *QDesignerFormBuilder::create(DomUI *ui, QWidget *parentWidget)
+{
+ m_mainWidget = true;
+ QtResourceSet *resourceSet = core()->resourceModel()->currentResourceSet();
+
+ // reload resource properties;
+ createResources(ui->elementResources());
+ core()->resourceModel()->setCurrentResourceSet(m_tempResourceSet);
+
+ m_ignoreCreateResources = true;
+ DesignerPixmapCache pixmapCache;
+ DesignerIconCache iconCache(&pixmapCache);
+ m_pixmapCache = &pixmapCache;
+ m_iconCache = &iconCache;
+
+ QWidget *widget = QFormBuilder::create(ui, parentWidget);
+
+ core()->resourceModel()->setCurrentResourceSet(resourceSet);
+ core()->resourceModel()->removeResourceSet(m_tempResourceSet);
+ m_tempResourceSet = 0;
+ m_ignoreCreateResources = false;
+ m_pixmapCache = 0;
+ m_iconCache = 0;
+
+ m_customWidgetsWithScript.clear();
+ return widget;
+}
+
+QWidget *QDesignerFormBuilder::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name)
+{
+ QWidget *widget = 0;
+
+ if (widgetName == QLatin1String("QToolBar")) {
+ widget = new QToolBar(parentWidget);
+ } else if (widgetName == QLatin1String("QMenu")) {
+ widget = new QMenu(parentWidget);
+ } else if (widgetName == QLatin1String("QMenuBar")) {
+ widget = new QMenuBar(parentWidget);
+ } else {
+ widget = core()->widgetFactory()->createWidget(widgetName, parentWidget);
+ }
+
+ if (widget) {
+ widget->setObjectName(name);
+ if (QSimpleResource::hasCustomWidgetScript(m_core, widget))
+ m_customWidgetsWithScript.insert(widget);
+ }
+
+ if (m_mainWidget) { // We need to apply the DPI here to take effect on size hints, etc.
+ m_deviceProfile.apply(m_core, widget, DeviceProfile::ApplyPreview);
+ m_mainWidget = false;
+ }
+ return widget;
+}
+
+bool QDesignerFormBuilder::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ // Use container extension or rely on scripts unless main window.
+ if (QFormBuilder::addItem(ui_widget, widget, parentWidget))
+ return true;
+
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), parentWidget)) {
+ container->addWidget(widget);
+ return true;
+ }
+ return false;
+}
+
+bool QDesignerFormBuilder::addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout)
+{
+ return QFormBuilder::addItem(ui_item, item, layout);
+}
+
+QIcon QDesignerFormBuilder::nameToIcon(const QString &filePath, const QString &qrcPath)
+{
+ Q_UNUSED(filePath)
+ Q_UNUSED(qrcPath)
+ qWarning() << "QDesignerFormBuilder::nameToIcon() is obsoleted";
+ return QIcon();
+}
+
+QPixmap QDesignerFormBuilder::nameToPixmap(const QString &filePath, const QString &qrcPath)
+{
+ Q_UNUSED(filePath)
+ Q_UNUSED(qrcPath)
+ qWarning() << "QDesignerFormBuilder::nameToPixmap() is obsoleted";
+ return QPixmap();
+}
+
+/* If the property is a enum or flag value, retrieve
+ * the existing enum/flag type via property sheet and use it to convert */
+
+static bool readDomEnumerationValue(const DomProperty *p,
+ const QDesignerPropertySheetExtension* sheet,
+ QVariant &v)
+{
+ switch (p->kind()) {
+ case DomProperty::Set: {
+ const int index = sheet->indexOf(p->attributeName());
+ if (index == -1)
+ return false;
+ const QVariant sheetValue = sheet->property(index);
+ if (qVariantCanConvert<PropertySheetFlagValue>(sheetValue)) {
+ const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(sheetValue);
+ bool ok = false;
+ v = f.metaFlags.parseFlags(p->elementSet(), &ok);
+ if (!ok)
+ designerWarning(f.metaFlags.messageParseFailed(p->elementSet()));
+ return true;
+ }
+ }
+ break;
+ case DomProperty::Enum: {
+ const int index = sheet->indexOf(p->attributeName());
+ if (index == -1)
+ return false;
+ const QVariant sheetValue = sheet->property(index);
+ if (qVariantCanConvert<PropertySheetEnumValue>(sheetValue)) {
+ const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(sheetValue);
+ bool ok = false;
+ v = e.metaEnum.parseEnum(p->elementEnum(), &ok);
+ if (!ok)
+ designerWarning(e.metaEnum.messageParseFailed(p->elementEnum()));
+ return true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void QDesignerFormBuilder::applyProperties(QObject *o, const QList<DomProperty*> &properties)
+{
+ typedef QList<DomProperty*> DomPropertyList;
+
+ if (properties.empty())
+ return;
+
+ QFormBuilderExtra *formBuilderExtra = QFormBuilderExtra::instance(this);
+ const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), o);
+ const QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core()->extensionManager(), o);
+ const bool changingMetaObject = WidgetFactory::classNameOf(core(), o) == QLatin1String("QAxWidget");
+ const QDesignerMetaObjectInterface *meta = core()->introspection()->metaObject(o);
+ const bool dynamicPropertiesAllowed = dynamicSheet && dynamicSheet->dynamicPropertiesAllowed();
+
+ QDesignerPropertySheet *designerPropertySheet = qobject_cast<QDesignerPropertySheet *>(
+ core()->extensionManager()->extension(o, Q_TYPEID(QDesignerPropertySheetExtension)));
+
+ if (designerPropertySheet) {
+ if (designerPropertySheet->pixmapCache())
+ designerPropertySheet->setPixmapCache(m_pixmapCache);
+ if (designerPropertySheet->iconCache())
+ designerPropertySheet->setIconCache(m_iconCache);
+ }
+
+ const DomPropertyList::const_iterator cend = properties.constEnd();
+ for (DomPropertyList::const_iterator it = properties.constBegin(); it != cend; ++it) {
+ DomProperty *p = *it;
+ QVariant v;
+ if (!readDomEnumerationValue(p, sheet, v))
+ v = toVariant(o->metaObject(), p);
+
+ if (v.isNull())
+ continue;
+
+ const QString attributeName = p->attributeName();
+ if (formBuilderExtra->applyPropertyInternally(o, attributeName, v))
+ continue;
+
+ // refuse fake properties like current tab name (weak test)
+ if (!dynamicPropertiesAllowed) {
+ if (changingMetaObject) // Changes after setting control of QAxWidget
+ meta = core()->introspection()->metaObject(o);
+ if (meta->indexOfProperty(attributeName) == -1)
+ continue;
+ }
+
+ QObject *obj = o;
+ QAbstractScrollArea *scroll = qobject_cast<QAbstractScrollArea *>(o);
+ if (scroll && attributeName == QLatin1String("cursor") && scroll->viewport())
+ obj = scroll->viewport();
+
+ // a real property
+ obj->setProperty(attributeName.toUtf8(), v);
+ }
+}
+
+DomWidget *QDesignerFormBuilder::createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive)
+{
+ DomWidget *ui_widget = QFormBuilder::createDom(widget, ui_parentWidget, recursive);
+ QSimpleResource::addExtensionDataToDOM(this, m_core, ui_widget, widget);
+ return ui_widget;
+}
+
+QWidget *QDesignerFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidget)
+{
+ QWidget *widget = QFormBuilder::create(ui_widget, parentWidget);
+ // Do not apply state if scripts are to be run in preview mode
+ QSimpleResource::applyExtensionDataFromDOM(this, m_core, ui_widget, widget, m_mode == DisableScripts);
+ return widget;
+}
+
+void QDesignerFormBuilder::createResources(DomResources *resources)
+{
+ if (m_ignoreCreateResources)
+ return;
+ QStringList paths;
+ if (resources != 0) {
+ const QList<DomResource*> dom_include = resources->elementInclude();
+ foreach (DomResource *res, dom_include) {
+ QString path = QDir::cleanPath(workingDirectory().absoluteFilePath(res->attributeLocation()));
+ paths << path;
+ }
+ }
+
+ m_tempResourceSet = core()->resourceModel()->addResourceSet(paths);
+}
+
+QLayout *QDesignerFormBuilder::create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget)
+{
+ return QFormBuilder::create(ui_layout, layout, parentWidget);
+}
+
+void QDesignerFormBuilder::loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ QFormBuilder::loadExtraInfo(ui_widget, widget, parentWidget);
+}
+
+QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw,
+ const QString &styleName,
+ const QString &appStyleSheet,
+ const DeviceProfile &deviceProfile,
+ ScriptErrors *scriptErrors,
+ QString *errorMessage)
+{
+ scriptErrors->clear();
+
+ // load
+ QDesignerFormBuilder builder(fw->core(), EnableScripts, deviceProfile);
+ builder.setWorkingDirectory(fw->absoluteDir());
+
+ const bool warningsEnabled = QSimpleResource::setWarningsEnabled(false);
+ QByteArray bytes = fw->contents().toUtf8();
+ QSimpleResource::setWarningsEnabled(warningsEnabled);
+
+ QBuffer buffer(&bytes);
+ buffer.open(QIODevice::ReadOnly);
+
+ QWidget *widget = builder.load(&buffer, 0);
+ if (!widget) { // Shouldn't happen
+ *errorMessage = QCoreApplication::translate("QDesignerFormBuilder", "The preview failed to build.");
+ return 0;
+ }
+ // Make sure palette is applied
+ const QString styleToUse = styleName.isEmpty() ? builder.deviceProfile().style() : styleName;
+ if (!styleToUse.isEmpty()) {
+ if (WidgetFactory *wf = qobject_cast<qdesigner_internal::WidgetFactory *>(fw->core()->widgetFactory())) {
+ if (styleToUse != wf->styleName())
+ WidgetFactory::applyStyleToTopLevel(wf->getStyle(styleToUse), widget);
+ }
+ }
+ // Check for script errors
+ *scriptErrors = builder.formScriptRunner()->errors();
+ if (!scriptErrors->empty()) {
+ *errorMessage = summarizeScriptErrors(*scriptErrors);
+ delete widget;
+ return 0;
+ }
+ // Fake application style sheet by prepending. (If this doesn't work, fake by nesting
+ // into parent widget).
+ if (!appStyleSheet.isEmpty()) {
+ QString styleSheet = appStyleSheet;
+ styleSheet += QLatin1Char('\n');
+ styleSheet += widget->styleSheet();
+ widget->setStyleSheet(styleSheet);
+ }
+ return widget;
+}
+
+QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName)
+{
+ return createPreview(fw, styleName, QString());
+}
+
+QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw,
+ const QString &styleName,
+ const QString &appStyleSheet,
+ const DeviceProfile &deviceProfile,
+ QString *errorMessage)
+{
+ ScriptErrors scriptErrors;
+ return createPreview(fw, styleName, appStyleSheet, deviceProfile, &scriptErrors, errorMessage);
+}
+
+QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw,
+ const QString &styleName,
+ const QString &appStyleSheet,
+ QString *errorMessage)
+{
+ ScriptErrors scriptErrors;
+ return createPreview(fw, styleName, appStyleSheet, DeviceProfile(), &scriptErrors, errorMessage);
+}
+
+QWidget *QDesignerFormBuilder::createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName, const QString &appStyleSheet)
+{
+ ScriptErrors scriptErrors;
+ QString errorMessage;
+ QWidget *widget = createPreview(fw, styleName, appStyleSheet, DeviceProfile(), &scriptErrors, &errorMessage);
+ if (!widget) {
+ // Display Script errors or message box
+ QWidget *dialogParent = fw->core()->topLevel();
+ if (scriptErrors.empty()) {
+ fw->core()->dialogGui()->message(dialogParent, QDesignerDialogGuiInterface::PreviewFailureMessage,
+ QMessageBox::Warning, QCoreApplication::translate("QDesignerFormBuilder", "Designer"), errorMessage, QMessageBox::Ok);
+ } else {
+ ScriptErrorDialog scriptErrorDialog(scriptErrors, dialogParent);
+ scriptErrorDialog.exec();
+ }
+ return 0;
+ }
+ return widget;
+}
+
+QPixmap QDesignerFormBuilder::createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &styleName, const QString &appStyleSheet)
+{
+ QWidget *widget = createPreview(fw, styleName, appStyleSheet);
+ if (!widget)
+ return QPixmap();
+
+ const QPixmap rc = QPixmap::grabWidget (widget);
+ widget->deleteLater();
+ return rc;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_formbuilder_p.h b/tools/designer/src/lib/shared/qdesigner_formbuilder_p.h
new file mode 100644
index 0000000000..b982e1cb4a
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formbuilder_p.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_FORMBUILDER_H
+#define QDESIGNER_FORMBUILDER_H
+
+#include "shared_global_p.h"
+#include "deviceprofile_p.h"
+
+#include <QtDesigner/private/formscriptrunner_p.h>
+#include <QtDesigner/formbuilder.h>
+
+#include <QtCore/QMap>
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+
+class QPixmap;
+class QtResourceSet;
+
+namespace qdesigner_internal {
+
+class DesignerPixmapCache;
+class DesignerIconCache;
+
+/* Form builder used for previewing forms, widget box and new form dialog.
+ * It applies the system settings to its toplevel window. */
+
+class QDESIGNER_SHARED_EXPORT QDesignerFormBuilder: public QFormBuilder
+{
+public:
+ enum Mode {
+ DisableScripts,
+ EnableScripts
+ };
+
+ QDesignerFormBuilder(QDesignerFormEditorInterface *core,
+ Mode mode,
+ const DeviceProfile &deviceProfile = DeviceProfile());
+
+ QWidget *createWidgetFromContents(const QString &contents, QWidget *parentWidget = 0);
+
+ virtual QWidget *createWidget(DomWidget *ui_widget, QWidget *parentWidget = 0)
+ { return QFormBuilder::create(ui_widget, parentWidget); }
+
+ inline QDesignerFormEditorInterface *core() const
+ { return m_core; }
+
+ QString systemStyle() const;
+
+ typedef QFormScriptRunner::Errors ScriptErrors;
+ // Create a preview widget (for integrations) or return 0. The widget has to be embedded into a main window.
+ // Experimental, depending on script support.
+ static QWidget *createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName /* ="" */,
+ const QString &appStyleSheet /* ="" */,
+ const DeviceProfile &deviceProfile,
+ ScriptErrors *scriptErrors, QString *errorMessage);
+ // Convenience that pops up message boxes in case of failures.
+ static QWidget *createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName = QString());
+ // Create a preview widget (for integrations) or return 0. The widget has to be embedded into a main window.
+ static QWidget *createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName, const QString &appStyleSheet, QString *errorMessage);
+ static QWidget *createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName, const QString &appStyleSheet, const DeviceProfile &deviceProfile, QString *errorMessage);
+ // Convenience that pops up message boxes in case of failures.
+ static QWidget *createPreview(const QDesignerFormWindowInterface *fw, const QString &styleName, const QString &appStyleSheet);
+
+ // Create a preview image
+ static QPixmap createPreviewPixmap(const QDesignerFormWindowInterface *fw, const QString &styleName = QString(), const QString &appStyleSheet = QString());
+
+protected:
+ using QFormBuilder::createDom;
+ using QFormBuilder::create;
+
+ virtual QWidget *create(DomUI *ui, QWidget *parentWidget);
+ virtual DomWidget *createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive = true);
+ virtual QWidget *create(DomWidget *ui_widget, QWidget *parentWidget);
+ virtual QLayout *create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget);
+ virtual void createResources(DomResources *resources);
+
+ virtual QWidget *createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name);
+ virtual bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+ virtual bool addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout);
+
+ virtual QIcon nameToIcon(const QString &filePath, const QString &qrcPath);
+ virtual QPixmap nameToPixmap(const QString &filePath, const QString &qrcPath);
+
+ virtual void applyProperties(QObject *o, const QList<DomProperty*> &properties);
+
+ virtual void loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+
+ QtResourceSet *internalResourceSet() const { return m_tempResourceSet; }
+
+ DeviceProfile deviceProfile() const { return m_deviceProfile; }
+
+private:
+ QDesignerFormEditorInterface *m_core;
+ const Mode m_mode;
+
+ typedef QSet<QWidget *> WidgetSet;
+ WidgetSet m_customWidgetsWithScript;
+
+ const DeviceProfile m_deviceProfile;
+
+ DesignerPixmapCache *m_pixmapCache;
+ DesignerIconCache *m_iconCache;
+ bool m_ignoreCreateResources;
+ QtResourceSet *m_tempResourceSet;
+ bool m_mainWidget;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_FORMBUILDER_H
diff --git a/tools/designer/src/lib/shared/qdesigner_formeditorcommand.cpp b/tools/designer/src/lib/shared/qdesigner_formeditorcommand.cpp
new file mode 100644
index 0000000000..5e5e6610ac
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formeditorcommand.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qdesigner_formeditorcommand_p.h"
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ---- QDesignerFormEditorCommand ----
+QDesignerFormEditorCommand::QDesignerFormEditorCommand(const QString &description, QDesignerFormEditorInterface *core)
+ : QUndoCommand(description),
+ m_core(core)
+{
+}
+
+QDesignerFormEditorInterface *QDesignerFormEditorCommand::core() const
+{
+ return m_core;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_formeditorcommand_p.h b/tools/designer/src/lib/shared/qdesigner_formeditorcommand_p.h
new file mode 100644
index 0000000000..b0fdd7788f
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formeditorcommand_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_FORMEDITORCOMMAND_H
+#define QDESIGNER_FORMEDITORCOMMAND_H
+
+#include "shared_global_p.h"
+#include <QtCore/QPointer>
+#include <QtGui/QUndoCommand>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT QDesignerFormEditorCommand: public QUndoCommand
+{
+
+public:
+ QDesignerFormEditorCommand(const QString &description, QDesignerFormEditorInterface *core);
+
+protected:
+ QDesignerFormEditorInterface *core() const;
+
+private:
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_FORMEDITORCOMMAND_H
diff --git a/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp b/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp
new file mode 100644
index 0000000000..9d6d57e2ed
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formwindowcommand.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qdesigner_formwindowcommand_p.h"
+#include "qdesigner_objectinspector_p.h"
+#include "layout_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtDesigner/QDesignerActionEditorInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QVariant>
+#include <QtGui/QWidget>
+#include <QtGui/QLabel>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ---- QDesignerFormWindowCommand ----
+QDesignerFormWindowCommand::QDesignerFormWindowCommand(const QString &description, QDesignerFormWindowInterface *formWindow)
+ : QUndoCommand(description),
+ m_formWindow(formWindow)
+{
+}
+
+QDesignerFormWindowInterface *QDesignerFormWindowCommand::formWindow() const
+{
+ return m_formWindow;
+}
+
+QDesignerFormEditorInterface *QDesignerFormWindowCommand::core() const
+{
+ if (QDesignerFormWindowInterface *fw = formWindow())
+ return fw->core();
+
+ return 0;
+}
+
+void QDesignerFormWindowCommand::undo()
+{
+ cheapUpdate();
+}
+
+void QDesignerFormWindowCommand::redo()
+{
+ cheapUpdate();
+}
+
+void QDesignerFormWindowCommand::cheapUpdate()
+{
+ if (core()->objectInspector())
+ core()->objectInspector()->setFormWindow(formWindow());
+
+ if (core()->actionEditor())
+ core()->actionEditor()->setFormWindow(formWindow());
+}
+
+QDesignerPropertySheetExtension* QDesignerFormWindowCommand::propertySheet(QObject *object) const
+{
+ return qt_extension<QDesignerPropertySheetExtension*>(formWindow()->core()->extensionManager(), object);
+}
+
+void QDesignerFormWindowCommand::updateBuddies(QDesignerFormWindowInterface *form,
+ const QString &old_name,
+ const QString &new_name)
+{
+ QExtensionManager* extensionManager = form->core()->extensionManager();
+
+ typedef QList<QLabel*> LabelList;
+
+ const LabelList label_list = qFindChildren<QLabel*>(form);
+ if (label_list.empty())
+ return;
+
+ const QString buddyProperty = QLatin1String("buddy");
+ const QByteArray oldNameU8 = old_name.toUtf8();
+ const QByteArray newNameU8 = new_name.toUtf8();
+
+ const LabelList::const_iterator cend = label_list.constEnd();
+ for (LabelList::const_iterator it = label_list.constBegin(); it != cend; ++it ) {
+ if (QDesignerPropertySheetExtension* sheet = qt_extension<QDesignerPropertySheetExtension*>(extensionManager, *it)) {
+ const int idx = sheet->indexOf(buddyProperty);
+ if (idx != -1) {
+ const QByteArray oldBuddy = sheet->property(idx).toByteArray();
+ if (oldBuddy == oldNameU8)
+ sheet->setProperty(idx, newNameU8);
+ }
+ }
+ }
+}
+
+void QDesignerFormWindowCommand::selectUnmanagedObject(QObject *unmanagedObject)
+{
+ // Keep selection in sync
+ if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(core()->objectInspector())) {
+ oi->clearSelection();
+ oi->selectObject(unmanagedObject);
+ }
+ core()->propertyEditor()->setObject(unmanagedObject);
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_formwindowcommand_p.h b/tools/designer/src/lib/shared/qdesigner_formwindowcommand_p.h
new file mode 100644
index 0000000000..f640e66455
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formwindowcommand_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_FORMWINDOWCOMMAND_H
+#define QDESIGNER_FORMWINDOWCOMMAND_H
+
+#include "shared_global_p.h"
+
+#include <QtCore/QPointer>
+#include <QtGui/QUndoCommand>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QDesignerPropertySheetExtension;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand: public QUndoCommand
+{
+
+public:
+ QDesignerFormWindowCommand(const QString &description, QDesignerFormWindowInterface *formWindow);
+
+ virtual void undo();
+ virtual void redo();
+
+ static void updateBuddies(QDesignerFormWindowInterface *form,
+ const QString &old_name, const QString &new_name);
+protected:
+ QDesignerFormWindowInterface *formWindow() const;
+ QDesignerFormEditorInterface *core() const;
+ QDesignerPropertySheetExtension* propertySheet(QObject *object) const;
+
+ void cheapUpdate();
+
+ void selectUnmanagedObject(QObject *unmanagedObject);
+private:
+ QPointer<QDesignerFormWindowInterface> m_formWindow;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_COMMAND_H
diff --git a/tools/designer/src/lib/shared/qdesigner_formwindowmanager.cpp b/tools/designer/src/lib/shared/qdesigner_formwindowmanager.cpp
new file mode 100644
index 0000000000..87213b4c31
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formwindowmanager.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_formwindowmanager_p.h"
+#include "plugindialog_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+/*!
+ \class QDesignerFormWindowManager
+
+ Extends QDesignerFormWindowManagerInterface with methods to control
+ the preview and printing of forms. It provides a facade that simplifies
+ the complexity of the more general PreviewConfiguration & PreviewManager
+ interfaces.
+
+ \since 4.5
+ */
+
+
+QDesignerFormWindowManager::QDesignerFormWindowManager(QObject *parent)
+ : QDesignerFormWindowManagerInterface(parent), m_unused(0)
+{
+}
+
+QDesignerFormWindowManager::~QDesignerFormWindowManager()
+{
+}
+
+/*!
+ Allows you to intervene and control \QD's form "Preview" action. The
+ function returns the original action.
+
+ \since 4.5
+ */
+QAction *QDesignerFormWindowManager::actionDefaultPreview() const
+{
+ return 0;
+}
+
+/*!
+ Allows you to intervene and control \QD's form "Preview in" style action. The
+ function returns the original list of actions.
+
+ The method calls PreviewManager::createStyleActionGroup() internally.
+
+ \since 4.5
+ */
+QActionGroup *QDesignerFormWindowManager::actionGroupPreviewInStyle() const
+{
+ return 0;
+}
+
+/*!
+ \fn QPixmap QDesignerFormWindowManager::createPreviewPixmap(QString *errorMessage)
+
+ Creates a pixmap representing the preview of the currently active form.
+
+ The method calls PreviewManager::createPreviewPixmap() internally.
+
+ \since 4.5
+ */
+
+
+/*!
+ \fn QPixmap QDesignerFormWindowManager::closeAllPreviews()
+
+ Closes all preview windows generated by actionDefaultPreview, actionGroupPreviewInStyle
+ and the corresponding methods in PreviewManager.
+
+ \since 4.5
+ */
+
+/*!
+ \fn PreviewManager *QDesignerFormWindowManager::previewManager()
+
+ Accesses the previewmanager implementation.
+
+ \since 4.5
+ \internal
+ */
+
+/*!
+ \fn QAction *QDesignerFormWindowManager::actionShowFormWindowSettingsDialog() const;
+
+ Allows you to intervene and control \QD's form "Form Settings" action. The
+ function returns the original action.
+
+ \since 4.5
+ \internal
+ */
+
+QAction *QDesignerFormWindowManager::actionShowFormWindowSettingsDialog() const
+{
+ return 0;
+}
+
+/*!
+ \fn void QDesignerFormWindowManager::aboutPlugins()
+
+ Pops up an "About plugins" dialog.
+
+ \since 4.5
+ \internal
+ */
+
+void QDesignerFormWindowManager::aboutPlugins()
+{
+ PluginDialog dlg(core(), core()->topLevel());
+ dlg.exec();
+}
+
+/*!
+ \fn
+ void QDesignerFormWindowManager::formWindowSettingsChanged(QDesignerFormWindowInterface *fw);
+
+ This signal is emitted when the form settings dialog was shown
+ and changes have been made to the form.
+
+ \since 4.5
+ \internal
+ */
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_formwindowmanager_p.h b/tools/designer/src/lib/shared/qdesigner_formwindowmanager_p.h
new file mode 100644
index 0000000000..61aee726fe
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_formwindowmanager_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_FORMWINDOMANAGER_H
+#define QDESIGNER_FORMWINDOMANAGER_H
+
+#include "shared_global_p.h"
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class PreviewManager;
+
+//
+// Convenience methods to manage form previews (ultimately forwarded to PreviewManager).
+//
+class QDESIGNER_SHARED_EXPORT QDesignerFormWindowManager
+ : public QDesignerFormWindowManagerInterface
+{
+ Q_OBJECT
+public:
+ explicit QDesignerFormWindowManager(QObject *parent = 0);
+ virtual ~QDesignerFormWindowManager();
+
+ virtual QAction *actionDefaultPreview() const;
+ virtual QActionGroup *actionGroupPreviewInStyle() const;
+ virtual QAction *actionShowFormWindowSettingsDialog() const;
+
+ virtual QPixmap createPreviewPixmap(QString *errorMessage) = 0;
+
+ virtual PreviewManager *previewManager() const = 0;
+
+Q_SIGNALS:
+ void formWindowSettingsChanged(QDesignerFormWindowInterface *fw);
+
+public Q_SLOTS:
+ virtual void closeAllPreviews() = 0;
+ void aboutPlugins();
+
+private:
+ void *m_unused;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_FORMWINDOMANAGER_H
diff --git a/tools/designer/src/lib/shared/qdesigner_integration.cpp b/tools/designer/src/lib/shared/qdesigner_integration.cpp
new file mode 100644
index 0000000000..02e02464e4
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_integration.cpp
@@ -0,0 +1,496 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_integration_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "qdesigner_propertyeditor_p.h"
+#include "qdesigner_objectinspector_p.h"
+#include "widgetdatabase_p.h"
+#include "pluginmanager_p.h"
+#include "widgetfactory_p.h"
+#include "qdesigner_widgetbox_p.h"
+#include "qtgradientmanager.h"
+#include "qtgradientutils.h"
+#include "qtresourcemodel_p.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerActionEditorInterface>
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerResourceBrowserInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+
+#include <QtCore/QVariant>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// ---------------- DesignerIntegrationPrivate
+class QDesignerIntegrationPrivate {
+public:
+ QDesignerIntegrationPrivate()
+ : m_gradientManager(0),
+ m_fileWatcherBehaviour(QDesignerIntegration::PromptAndReload),
+ m_resourceEditingEnabled(true),
+ m_slotNavigationEnabled(false)
+ {}
+
+ QString m_gradientsPath;
+ QtGradientManager *m_gradientManager;
+ QDesignerIntegration::ResourceFileWatcherBehaviour m_fileWatcherBehaviour;
+ bool m_resourceEditingEnabled;
+ bool m_slotNavigationEnabled;
+};
+
+// -------------- QDesignerIntegration
+// As of 4.4, the header will be distributed with the Eclipse plugin.
+
+QDesignerIntegration::QDesignerIntegration(QDesignerFormEditorInterface *core, QObject *parent) :
+ QDesignerIntegrationInterface(core, parent),
+ m_d(new QDesignerIntegrationPrivate)
+{
+ initialize();
+}
+
+QDesignerIntegration::~QDesignerIntegration()
+{
+ QFile f(m_d->m_gradientsPath);
+ if (f.open(QIODevice::WriteOnly)) {
+ f.write(QtGradientUtils::saveState(m_d->m_gradientManager).toUtf8());
+ f.close();
+ }
+ delete m_d;
+}
+
+void QDesignerIntegration::initialize()
+{
+ //
+ // integrate the `Form Editor component'
+ //
+
+ // Extensions
+ if (QDesignerPropertyEditor *designerPropertyEditor= qobject_cast<QDesignerPropertyEditor *>(core()->propertyEditor())) {
+ connect(designerPropertyEditor, SIGNAL(propertyValueChanged(QString, QVariant, bool)), this, SLOT(updateProperty(QString, QVariant, bool)));
+ connect(designerPropertyEditor, SIGNAL(resetProperty(QString)), this, SLOT(resetProperty(QString)));
+ connect(designerPropertyEditor, SIGNAL(addDynamicProperty(QString,QVariant)),
+ this, SLOT(addDynamicProperty(QString,QVariant)));
+ connect(designerPropertyEditor, SIGNAL(removeDynamicProperty(QString)),
+ this, SLOT(removeDynamicProperty(QString)));
+ } else {
+ connect(core()->propertyEditor(), SIGNAL(propertyChanged(QString,QVariant)),
+ this, SLOT(updatePropertyPrivate(QString,QVariant)));
+ }
+
+ connect(core()->formWindowManager(), SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)),
+ this, SLOT(setupFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core()->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(updateActiveFormWindow(QDesignerFormWindowInterface*)));
+
+ m_d->m_gradientManager = new QtGradientManager(this);
+ core()->setGradientManager(m_d->m_gradientManager);
+
+ QString designerFolder = QDir::homePath();
+ designerFolder += QDir::separator();
+ designerFolder += QLatin1String(".designer");
+ m_d->m_gradientsPath = designerFolder;
+ m_d->m_gradientsPath += QDir::separator();
+ m_d->m_gradientsPath += QLatin1String("gradients.xml");
+
+ QFile f(m_d->m_gradientsPath);
+ if (f.open(QIODevice::ReadOnly)) {
+ QtGradientUtils::restoreState(m_d->m_gradientManager, QString::fromAscii(f.readAll()));
+ f.close();
+ } else {
+ QFile defaultGradients(QLatin1String(":/trolltech/designer/defaultgradients.xml"));
+ if (defaultGradients.open(QIODevice::ReadOnly)) {
+ QtGradientUtils::restoreState(m_d->m_gradientManager, QString::fromAscii(defaultGradients.readAll()));
+ defaultGradients.close();
+ }
+ }
+
+ if (WidgetDataBase *widgetDataBase = qobject_cast<WidgetDataBase*>(core()->widgetDataBase()))
+ widgetDataBase->grabStandardWidgetBoxIcons();
+}
+
+void QDesignerIntegration::updateProperty(const QString &name, const QVariant &value, bool enableSubPropertyHandling)
+{
+ QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
+ if (!formWindow)
+ return;
+
+ Selection selection;
+ getSelection(selection);
+ if (selection.empty())
+ return;
+
+ SetPropertyCommand *cmd = new SetPropertyCommand(formWindow);
+ // find a reference object to compare to and to find the right group
+ if (cmd->init(selection.selection(), name, value, propertyEditorObject(), enableSubPropertyHandling)) {
+ formWindow->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ qDebug() << "Unable to set property " << name << '.';
+ }
+
+ emit propertyChanged(formWindow, name, value);
+}
+
+void QDesignerIntegration::updatePropertyPrivate(const QString &name, const QVariant &value)
+{
+ updateProperty(name, value, true);
+}
+
+void QDesignerIntegration::resetProperty(const QString &name)
+{
+ QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
+ if (!formWindow)
+ return;
+
+ Selection selection;
+ getSelection(selection);
+ if (selection.empty())
+ return;
+
+
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(formWindow);
+ // find a reference object to find the right group
+ if (cmd->init(selection.selection(), name, propertyEditorObject())) {
+ formWindow->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ qDebug() << "** WARNING Unable to reset property " << name << '.';
+ }
+}
+
+void QDesignerIntegration::addDynamicProperty(const QString &name, const QVariant &value)
+{
+ QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
+ if (!formWindow)
+ return;
+
+ Selection selection;
+ getSelection(selection);
+ if (selection.empty())
+ return;
+
+ AddDynamicPropertyCommand *cmd = new AddDynamicPropertyCommand(formWindow);
+ if (cmd->init(selection.selection(), propertyEditorObject(), name, value)) {
+ formWindow->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ qDebug() << "** WARNING Unable to add dynamic property " << name << '.';
+ }
+}
+
+void QDesignerIntegration::removeDynamicProperty(const QString &name)
+{
+ QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
+ if (!formWindow)
+ return;
+
+ Selection selection;
+ getSelection(selection);
+ if (selection.empty())
+ return;
+
+ RemoveDynamicPropertyCommand *cmd = new RemoveDynamicPropertyCommand(formWindow);
+ if (cmd->init(selection.selection(), propertyEditorObject(), name)) {
+ formWindow->commandHistory()->push(cmd);
+ } else {
+ delete cmd;
+ qDebug() << "** WARNING Unable to remove dynamic property " << name << '.';
+ }
+
+}
+
+
+void QDesignerIntegration::updateActiveFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_UNUSED(formWindow);
+ updateSelection();
+}
+
+void QDesignerIntegration::setupFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ connect(formWindow, SIGNAL(selectionChanged()), this, SLOT(updateSelection()));
+ connect(formWindow, SIGNAL(activated(QWidget*)), this, SLOT(activateWidget(QWidget*)));
+}
+
+void QDesignerIntegration::updateGeometry()
+{
+}
+
+void QDesignerIntegration::updateSelection()
+{
+ QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
+ QWidget *selection = 0;
+
+ if (formWindow) {
+ selection = formWindow->cursor()->current();
+ }
+
+ if (QDesignerActionEditorInterface *actionEditor = core()->actionEditor())
+ actionEditor->setFormWindow(formWindow);
+
+ if (QDesignerPropertyEditorInterface *propertyEditor = core()->propertyEditor())
+ propertyEditor->setObject(selection);
+
+ if (QDesignerObjectInspectorInterface *objectInspector = core()->objectInspector())
+ objectInspector->setFormWindow(formWindow);
+
+}
+
+void QDesignerIntegration::activateWidget(QWidget *widget)
+{
+ Q_UNUSED(widget);
+}
+
+QWidget *QDesignerIntegration::containerWindow(QWidget *widget) const
+{
+ // Find the parent window to apply a geometry to.
+ while (widget) {
+ if (widget->isWindow())
+ break;
+ if (!qstrcmp(widget->metaObject()->className(), "QMdiSubWindow"))
+ break;
+
+ widget = widget->parentWidget();
+ }
+
+ return widget;
+}
+
+void QDesignerIntegration::getSelection(Selection &s)
+{
+ // Get multiselection from object inspector
+ if (QDesignerObjectInspector *designerObjectInspector = qobject_cast<QDesignerObjectInspector *>(core()->objectInspector())) {
+ designerObjectInspector->getSelection(s);
+ // Action editor puts actions that are not on the form yet
+ // into the property editor only.
+ if (s.empty())
+ if (QObject *object = core()->propertyEditor()->object())
+ s.objects.push_back(object);
+
+ } else {
+ // Just in case someone plugs in an old-style object inspector: Emulate selection
+ s.clear();
+ QDesignerFormWindowInterface *formWindow = core()->formWindowManager()->activeFormWindow();
+ if (!formWindow)
+ return;
+
+ QObject *object = core()->propertyEditor()->object();
+ if (object->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget*>(object);
+ QDesignerFormWindowCursorInterface *cursor = formWindow->cursor();
+ if (cursor->isWidgetSelected(widget)) {
+ s.managed.push_back(widget);
+ } else {
+ s.unmanaged.push_back(widget);
+ }
+ } else {
+ s.objects.push_back(object);
+ }
+ }
+}
+
+QObject *QDesignerIntegration::propertyEditorObject()
+{
+ QDesignerPropertyEditorInterface *propertyEditor = core()->propertyEditor();
+ if (!propertyEditor)
+ return 0;
+ return propertyEditor->object();
+}
+
+// Load plugins into widget database and factory.
+void QDesignerIntegration::initializePlugins(QDesignerFormEditorInterface *formEditor)
+{
+ // load the plugins
+ WidgetDataBase *widgetDataBase = qobject_cast<WidgetDataBase*>(formEditor->widgetDataBase());
+ if (widgetDataBase) {
+ widgetDataBase->loadPlugins();
+ }
+
+ if (WidgetFactory *widgetFactory = qobject_cast<WidgetFactory*>(formEditor->widgetFactory())) {
+ widgetFactory->loadPlugins();
+ }
+
+ if (widgetDataBase) {
+ widgetDataBase->grabDefaultPropertyValues();
+ }
+}
+
+void QDesignerIntegration::updateCustomWidgetPlugins()
+{
+ QDesignerFormEditorInterface *formEditor = core();
+ if (QDesignerPluginManager *pm = formEditor->pluginManager())
+ pm->registerNewPlugins();
+
+ initializePlugins(formEditor);
+
+ // Do not just reload the last file as the WidgetBox merges the compiled-in resources
+ // and $HOME/.designer/widgetbox.xml. This would also double the scratchpad.
+ if (QDesignerWidgetBox *wb = qobject_cast<QDesignerWidgetBox*>(formEditor->widgetBox())) {
+ const QDesignerWidgetBox::LoadMode oldLoadMode = wb->loadMode();
+ wb->setLoadMode(QDesignerWidgetBox::LoadCustomWidgetsOnly);
+ wb->load();
+ wb->setLoadMode(oldLoadMode);
+ }
+}
+
+void QDesignerIntegration::emitObjectNameChanged(QDesignerFormWindowInterface *formWindow, QObject *object, const QString &newName, const QString &oldName)
+{
+ emit objectNameChanged(formWindow, object, newName, oldName);
+}
+
+void QDesignerIntegration::emitNavigateToSlot(const QString &objectName,
+ const QString &signalSignature,
+ const QStringList &parameterNames)
+{
+ emit navigateToSlot(objectName, signalSignature, parameterNames);
+}
+
+void QDesignerIntegration::emitNavigateToSlot(const QString &slotSignature)
+{
+ emit navigateToSlot(slotSignature);
+}
+
+void QDesignerIntegration::requestHelp(const QDesignerFormEditorInterface *core, const QString &manual, const QString &document)
+{
+ if (QDesignerIntegration *di = qobject_cast<QDesignerIntegration *>(core->integration()))
+ emit di->helpRequested(manual, document);
+}
+
+QDesignerResourceBrowserInterface *QDesignerIntegration::createResourceBrowser(QWidget *)
+{
+ return 0;
+}
+
+void QDesignerIntegration::setResourceFileWatcherBehaviour(ResourceFileWatcherBehaviour behaviour)
+{
+ m_d->m_fileWatcherBehaviour = behaviour;
+ core()->resourceModel()->setWatcherEnabled(behaviour != QDesignerIntegration::NoWatcher);
+}
+
+QDesignerIntegration::ResourceFileWatcherBehaviour QDesignerIntegration::resourceFileWatcherBehaviour() const
+{
+ return m_d->m_fileWatcherBehaviour;
+}
+
+void QDesignerIntegration::setResourceEditingEnabled(bool enable)
+{
+ m_d->m_resourceEditingEnabled = enable;
+}
+
+bool QDesignerIntegration::isResourceEditingEnabled() const
+{
+ return m_d->m_resourceEditingEnabled;
+}
+
+void QDesignerIntegration::setSlotNavigationEnabled(bool enable)
+{
+ m_d->m_slotNavigationEnabled = enable;
+}
+
+bool QDesignerIntegration::isSlotNavigationEnabled() const
+{
+ return m_d->m_slotNavigationEnabled;
+}
+
+static QString fixHelpClassName(const QString &className)
+{
+ // ### generalize using the Widget Data Base
+ if (className == QLatin1String("Line"))
+ return QLatin1String("QFrame");
+ if (className == QLatin1String("Spacer"))
+ return QLatin1String("QSpacerItem");
+ if (className == QLatin1String("QLayoutWidget"))
+ return QLatin1String("QLayout");
+ return className;
+}
+
+// Return class in which the property is defined
+static QString classForProperty(QDesignerFormEditorInterface *core,
+ QObject *object,
+ const QString &property)
+{
+ if (const QDesignerPropertySheetExtension *ps = qt_extension<QDesignerPropertySheetExtension *>(core->extensionManager(), object)) {
+ const int index = ps->indexOf(property);
+ if (index >= 0)
+ return ps->propertyGroup(index);
+ }
+ return QString();
+}
+
+QString QDesignerIntegration::contextHelpId() const
+{
+ QObject *currentObject = core()->propertyEditor()->object();
+ if (!currentObject)
+ return QString();
+ // Return a help index id consisting of "class::property"
+ QString className;
+ QString currentPropertyName = core()->propertyEditor()->currentPropertyName();
+ if (!currentPropertyName.isEmpty())
+ className = classForProperty(core(), currentObject, currentPropertyName);
+ if (className.isEmpty()) {
+ currentPropertyName.clear(); // We hit on some fake property.
+ className = WidgetFactory::classNameOf(core(), currentObject);
+ }
+ QString helpId = fixHelpClassName(className);
+ if (!currentPropertyName.isEmpty()) {
+ helpId += QLatin1String("::");
+ helpId += currentPropertyName;
+ }
+ return helpId;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_integration_p.h b/tools/designer/src/lib/shared/qdesigner_integration_p.h
new file mode 100644
index 0000000000..6938bfbf86
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_integration_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_INTEGRATION_H
+#define QDESIGNER_INTEGRATION_H
+
+#include "shared_global_p.h"
+#include <QtDesigner/QDesignerIntegrationInterface>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QDesignerResourceBrowserInterface;
+
+class QVariant;
+class QWidget;
+
+namespace qdesigner_internal {
+
+struct Selection;
+class QDesignerIntegrationPrivate;
+
+class QDESIGNER_SHARED_EXPORT QDesignerIntegration: public QDesignerIntegrationInterface
+{
+ Q_OBJECT
+public:
+ explicit QDesignerIntegration(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ virtual ~QDesignerIntegration();
+
+ static void requestHelp(const QDesignerFormEditorInterface *core, const QString &manual, const QString &document);
+
+ virtual QWidget *containerWindow(QWidget *widget) const;
+
+ // Load plugins into widget database and factory.
+ static void initializePlugins(QDesignerFormEditorInterface *formEditor);
+ void emitObjectNameChanged(QDesignerFormWindowInterface *formWindow, QObject *object,
+ const QString &newName, const QString &oldName);
+ void emitNavigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList &parameterNames);
+ void emitNavigateToSlot(const QString &slotSignature);
+
+ // Create a resource browser specific to integration. Language integration takes precedence
+ virtual QDesignerResourceBrowserInterface *createResourceBrowser(QWidget *parent = 0);
+
+ enum ResourceFileWatcherBehaviour {
+ NoWatcher,
+ ReloadSilently,
+ PromptAndReload
+ };
+
+ ResourceFileWatcherBehaviour resourceFileWatcherBehaviour() const;
+ bool isResourceEditingEnabled() const;
+ bool isSlotNavigationEnabled() const;
+
+ QString contextHelpId() const;
+
+protected:
+
+ void setResourceFileWatcherBehaviour(ResourceFileWatcherBehaviour behaviour); // PromptAndReload by default
+ void setResourceEditingEnabled(bool enable); // true by default
+ void setSlotNavigationEnabled(bool enable); // false by default
+
+signals:
+ void propertyChanged(QDesignerFormWindowInterface *formWindow, const QString &name, const QVariant &value);
+ void objectNameChanged(QDesignerFormWindowInterface *formWindow, QObject *object, const QString &newName, const QString &oldName);
+ void helpRequested(const QString &manual, const QString &document);
+
+ void navigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList &parameterNames);
+ void navigateToSlot(const QString &slotSignature);
+
+public slots:
+ virtual void updateProperty(const QString &name, const QVariant &value, bool enableSubPropertyHandling);
+ // Additional signals of designer property editor
+ virtual void resetProperty(const QString &name);
+ virtual void addDynamicProperty(const QString &name, const QVariant &value);
+ virtual void removeDynamicProperty(const QString &name);
+
+ virtual void updateActiveFormWindow(QDesignerFormWindowInterface *formWindow);
+ virtual void setupFormWindow(QDesignerFormWindowInterface *formWindow);
+ virtual void updateSelection();
+ virtual void updateGeometry();
+ virtual void activateWidget(QWidget *widget);
+
+ void updateCustomWidgetPlugins();
+
+private slots:
+ void updatePropertyPrivate(const QString &name, const QVariant &value);
+
+private:
+ void initialize();
+ void getSelection(Selection &s);
+ QObject *propertyEditorObject();
+
+ QDesignerIntegrationPrivate *m_d;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_INTEGRATION_H
diff --git a/tools/designer/src/lib/shared/qdesigner_introspection.cpp b/tools/designer/src/lib/shared/qdesigner_introspection.cpp
new file mode 100644
index 0000000000..c512a9726d
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_introspection.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_introspection_p.h"
+
+#include <QtCore/QMetaObject>
+#include <QtCore/QMetaEnum>
+#include <QtCore/QStringList>
+#include <QtCore/QVector>
+
+QT_BEGIN_NAMESPACE
+
+// Qt Implementation
+static QStringList byteArrayListToStringList(const QList<QByteArray> &l)
+{
+ if (l.empty())
+ return QStringList();
+ QStringList rc;
+ const QList<QByteArray>::const_iterator cend = l.constEnd();
+ for (QList<QByteArray>::const_iterator it = l.constBegin(); it != cend; ++it)
+ rc += QString::fromUtf8(*it);
+ return rc;
+}
+
+static inline QString charToQString(const char *c)
+{
+ if (!c)
+ return QString::null;
+ return QString::fromUtf8(c);
+}
+
+namespace {
+ // ------- QDesignerMetaEnum
+ class QDesignerMetaEnum : public QDesignerMetaEnumInterface {
+ public:
+ QDesignerMetaEnum(const QMetaEnum &qEnum);
+ virtual bool isFlag() const { return m_enum.isFlag(); }
+ virtual QString key(int index) const { return charToQString(m_enum.key(index)); }
+ virtual int keyCount() const { return m_enum.keyCount(); }
+ virtual int keyToValue(const QString &key) const { return m_enum.keyToValue(key.toUtf8()); }
+ virtual int keysToValue(const QString &keys) const { return m_enum.keysToValue(keys.toUtf8()); }
+ virtual QString name() const { return m_name; }
+ virtual QString scope() const { return m_scope; }
+ virtual QString separator() const;
+ virtual int value(int index) const { return m_enum.value(index); }
+ virtual QString valueToKey(int value) const { return charToQString(m_enum.valueToKey(value)); }
+ virtual QString valueToKeys(int value) const { return charToQString(m_enum.valueToKeys(value)); }
+
+ private:
+ const QMetaEnum m_enum;
+ const QString m_name;
+ const QString m_scope;
+ };
+
+ QDesignerMetaEnum::QDesignerMetaEnum(const QMetaEnum &qEnum) :
+ m_enum(qEnum),
+ m_name(charToQString(m_enum.name())),
+ m_scope(charToQString(m_enum.scope()))
+ {
+ }
+
+ QString QDesignerMetaEnum::separator() const
+ {
+ static const QString rc = QLatin1String("::");
+ return rc;
+ }
+
+ // ------- QDesignerMetaProperty
+ class QDesignerMetaProperty : public QDesignerMetaPropertyInterface {
+ public:
+ QDesignerMetaProperty(const QMetaProperty &property);
+ virtual ~QDesignerMetaProperty();
+
+ virtual const QDesignerMetaEnumInterface *enumerator() const { return m_enumerator; }
+
+ virtual Kind kind() const { return m_kind; }
+
+ virtual AccessFlags accessFlags() const { return m_access; }
+ virtual Attributes attributes(const QObject *object = 0) const;
+
+ virtual QVariant::Type type() const { return m_property.type(); }
+ virtual QString name() const { return m_name; }
+ virtual QString typeName() const { return m_typeName; }
+ virtual int userType() const { return m_property.userType(); }
+ virtual bool hasSetter() const { return m_property.hasStdCppSet(); }
+
+ virtual QVariant read(const QObject *object) const { return m_property.read(object); }
+ virtual bool reset(QObject *object) const { return m_property.reset(object); }
+ virtual bool write(QObject *object, const QVariant &value) const { return m_property.write(object, value); }
+
+ private:
+ const QMetaProperty m_property;
+ const QString m_name;
+ const QString m_typeName;
+ Kind m_kind;
+ AccessFlags m_access;
+ Attributes m_defaultAttributes;
+ QDesignerMetaEnumInterface *m_enumerator;
+ };
+
+ QDesignerMetaProperty::QDesignerMetaProperty(const QMetaProperty &property) :
+ m_property(property),
+ m_name(charToQString(m_property.name())),
+ m_typeName(charToQString(m_property.typeName())),
+ m_kind(OtherKind),
+ m_enumerator(0)
+ {
+ if (m_property.isFlagType() || m_property.isEnumType()) {
+ const QMetaEnum metaEnum = m_property.enumerator();
+ Q_ASSERT(metaEnum.isValid());
+ m_enumerator = new QDesignerMetaEnum(metaEnum);
+ }
+ // kind
+ if (m_property.isFlagType())
+ m_kind = FlagKind;
+ else
+ if (m_property.isEnumType())
+ m_kind = EnumKind;
+ // flags and attributes
+ if (m_property.isReadable())
+ m_access |= ReadAccess;
+ if (m_property.isWritable())
+ m_access |= WriteAccess;
+ if (m_property.isResettable())
+ m_access |= ResetAccess;
+
+ if (m_property.isDesignable())
+ m_defaultAttributes |= DesignableAttribute;
+ if (m_property.isScriptable())
+ m_defaultAttributes |= ScriptableAttribute;
+ if (m_property.isStored())
+ m_defaultAttributes |= StoredAttribute;
+ if (m_property.isUser())
+ m_defaultAttributes |= UserAttribute;
+ }
+
+ QDesignerMetaProperty::~QDesignerMetaProperty()
+ {
+ delete m_enumerator;
+ }
+
+ QDesignerMetaProperty::Attributes QDesignerMetaProperty::attributes(const QObject *object) const
+ {
+ if (!object)
+ return m_defaultAttributes;
+ Attributes rc;
+ if (m_property.isDesignable(object))
+ rc |= DesignableAttribute;
+ if (m_property.isScriptable(object))
+ rc |= ScriptableAttribute;
+ if (m_property.isStored(object))
+ rc |= StoredAttribute;
+ if (m_property.isUser(object))
+ rc |= UserAttribute;
+ return rc;
+ }
+
+ // -------------- QDesignerMetaMethod
+
+ class QDesignerMetaMethod : public QDesignerMetaMethodInterface {
+ public:
+ QDesignerMetaMethod(const QMetaMethod &method);
+
+ virtual Access access() const { return m_access; }
+ virtual MethodType methodType() const { return m_methodType; }
+ virtual QStringList parameterNames() const { return m_parameterNames; }
+ virtual QStringList parameterTypes() const { return m_parameterTypes; }
+ virtual QString signature() const { return m_signature; }
+ virtual QString normalizedSignature() const { return m_normalizedSignature; }
+ virtual QString tag() const { return m_tag; }
+ virtual QString typeName() const { return m_typeName; }
+
+ private:
+ Access m_access;
+ MethodType m_methodType;
+ const QStringList m_parameterNames;
+ const QStringList m_parameterTypes;
+ const QString m_signature;
+ const QString m_normalizedSignature;
+ const QString m_tag;
+ const QString m_typeName;
+ };
+
+ QDesignerMetaMethod::QDesignerMetaMethod(const QMetaMethod &method) :
+ m_parameterNames(byteArrayListToStringList(method.parameterNames())),
+ m_parameterTypes(byteArrayListToStringList(method.parameterTypes())),
+ m_signature(charToQString(method.signature())),
+ m_normalizedSignature(charToQString(QMetaObject::normalizedSignature(method.signature()))),
+ m_tag(charToQString(method.tag())),
+ m_typeName(charToQString(method.typeName()))
+ {
+ switch (method.access()) {
+ case QMetaMethod::Public:
+ m_access = Public;
+ break;
+ case QMetaMethod::Protected:
+ m_access = Protected;
+ break;
+ case QMetaMethod::Private:
+ m_access = Private;
+ break;
+
+ }
+ switch (method.methodType()) {
+ case QMetaMethod::Constructor:
+ m_methodType = Constructor;
+ break;
+ case QMetaMethod::Method:
+ m_methodType = Method;
+ break;
+ case QMetaMethod::Signal:
+ m_methodType = Signal;
+ break;
+
+ case QMetaMethod::Slot:
+ m_methodType = Slot;
+ break;
+ }
+ }
+
+ // ------------- QDesignerMetaObject
+ class QDesignerMetaObject : public QDesignerMetaObjectInterface {
+ public:
+ QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection *introspection, const QMetaObject *metaObject);
+ virtual ~QDesignerMetaObject();
+
+ virtual QString className() const { return m_className; }
+ virtual const QDesignerMetaEnumInterface *enumerator(int index) const { return m_enumerators[index]; }
+ virtual int enumeratorCount() const { return m_enumerators.size(); }
+ virtual int enumeratorOffset() const { return m_metaObject->enumeratorOffset(); }
+
+ virtual int indexOfEnumerator(const QString &name) const { return m_metaObject->indexOfEnumerator(name.toUtf8()); }
+ virtual int indexOfMethod(const QString &method) const { return m_metaObject->indexOfMethod(method.toUtf8()); }
+ virtual int indexOfProperty(const QString &name) const { return m_metaObject->indexOfProperty(name.toUtf8()); }
+ virtual int indexOfSignal(const QString &signal) const { return m_metaObject->indexOfSignal(signal.toUtf8()); }
+ virtual int indexOfSlot(const QString &slot) const { return m_metaObject->indexOfSlot(slot.toUtf8()); }
+
+ virtual const QDesignerMetaMethodInterface *method(int index) const { return m_methods[index]; }
+ virtual int methodCount() const { return m_methods.size(); }
+ virtual int methodOffset() const { return m_metaObject->methodOffset(); }
+
+ virtual const QDesignerMetaPropertyInterface *property(int index) const { return m_properties[index]; }
+ virtual int propertyCount() const { return m_properties.size(); }
+ virtual int propertyOffset() const { return m_metaObject->propertyOffset(); }
+
+ const QDesignerMetaObjectInterface *superClass() const;
+ virtual const QDesignerMetaPropertyInterface *userProperty() const { return m_userProperty; }
+
+ private:
+ const QString m_className;
+ const qdesigner_internal::QDesignerIntrospection *m_introspection;
+ const QMetaObject *m_metaObject;
+
+ typedef QVector<QDesignerMetaEnumInterface *> Enumerators;
+ Enumerators m_enumerators;
+
+ typedef QVector<QDesignerMetaMethodInterface *> Methods;
+ Methods m_methods;
+
+ typedef QVector<QDesignerMetaPropertyInterface *> Properties;
+ Properties m_properties;
+
+ QDesignerMetaPropertyInterface *m_userProperty;
+ };
+
+ QDesignerMetaObject::QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection *introspection, const QMetaObject *metaObject) :
+ m_className(charToQString(metaObject->className())),
+ m_introspection(introspection),
+ m_metaObject(metaObject),
+ m_userProperty(0)
+ {
+ const int numEnumerators = metaObject->enumeratorCount();
+ m_enumerators.reserve(numEnumerators);
+ for (int i = 0; i < numEnumerators; i++)
+ m_enumerators.push_back(new QDesignerMetaEnum(metaObject->enumerator(i)));
+ const int numMethods = metaObject->methodCount();
+ m_methods.reserve(numMethods);
+ for (int i = 0; i < numMethods; i++)
+ m_methods.push_back(new QDesignerMetaMethod(metaObject->method(i)));
+
+ const int numProperties = metaObject->propertyCount();
+ m_properties.reserve(numProperties);
+ for (int i = 0; i < numProperties; i++)
+ m_properties.push_back(new QDesignerMetaProperty(metaObject->property(i)));
+
+ const QMetaProperty userProperty = metaObject->userProperty();
+ if (userProperty.isValid())
+ m_userProperty = new QDesignerMetaProperty(userProperty);
+ }
+
+ QDesignerMetaObject::~QDesignerMetaObject()
+ {
+ qDeleteAll(m_enumerators);
+ qDeleteAll(m_methods);
+ qDeleteAll(m_properties);
+ delete m_userProperty;
+ }
+
+ const QDesignerMetaObjectInterface *QDesignerMetaObject::superClass() const
+ {
+ const QMetaObject *qSuperClass = m_metaObject->superClass();
+ if (!qSuperClass)
+ return 0;
+ return m_introspection->metaObjectForQMetaObject(qSuperClass);
+ }
+
+}
+
+namespace qdesigner_internal {
+
+ QDesignerIntrospection::QDesignerIntrospection()
+ {
+ }
+
+ QDesignerIntrospection::~QDesignerIntrospection()
+ {
+ qDeleteAll(m_metaObjectMap.values());
+ }
+
+ const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObject(const QObject *object) const
+ {
+ return metaObjectForQMetaObject(object->metaObject());
+ }
+
+ const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObjectForQMetaObject(const QMetaObject *metaObject) const
+ {
+ MetaObjectMap::iterator it = m_metaObjectMap.find(metaObject);
+ if (it == m_metaObjectMap.end())
+ it = m_metaObjectMap.insert(metaObject, new QDesignerMetaObject(this, metaObject));
+ return it.value();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_introspection_p.h b/tools/designer/src/lib/shared/qdesigner_introspection_p.h
new file mode 100644
index 0000000000..89f4c53e6e
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_introspection_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef DESIGNERINTROSPECTION
+#define DESIGNERINTROSPECTION
+
+#include "shared_global_p.h"
+#include <abstractintrospection_p.h>
+#include <QtCore/QMap>
+
+QT_BEGIN_NAMESPACE
+
+struct QMetaObject;
+class QWidget;
+
+namespace qdesigner_internal {
+ // Qt C++ introspection with helpers to find core and meta object for an object
+ class QDESIGNER_SHARED_EXPORT QDesignerIntrospection : public QDesignerIntrospectionInterface {
+ public:
+ QDesignerIntrospection();
+ virtual ~QDesignerIntrospection();
+
+ virtual const QDesignerMetaObjectInterface* metaObject(const QObject *object) const;
+
+ const QDesignerMetaObjectInterface* metaObjectForQMetaObject(const QMetaObject *metaObject) const;
+ private:
+ typedef QMap<const QMetaObject*, QDesignerMetaObjectInterface*> MetaObjectMap;
+ mutable MetaObjectMap m_metaObjectMap;
+
+ };
+}
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERINTROSPECTION
diff --git a/tools/designer/src/lib/shared/qdesigner_membersheet.cpp b/tools/designer/src/lib/shared/qdesigner_membersheet.cpp
new file mode 100644
index 0000000000..e51d2fe86b
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_membersheet.cpp
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_membersheet_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <abstractintrospection_p.h>
+
+#include <QtGui/QWidget>
+
+namespace {
+
+class Qt3Members
+ {
+ public:
+ static Qt3Members *instance();
+ QMap<QString, QStringList> getSignals() const { return m_classNameToSignals; }
+ QMap<QString, QStringList> getSlots() const { return m_classNameToSlots; }
+ private:
+ Qt3Members();
+ static Qt3Members *m_instance;
+ QMap<QString, QStringList> m_classNameToSignals;
+ QMap<QString, QStringList> m_classNameToSlots;
+ };
+
+Qt3Members *Qt3Members::m_instance = 0;
+
+Qt3Members::Qt3Members()
+{
+ m_classNameToSignals[QLatin1String("QTextEdit")].append(QLatin1String("currentFontChanged(QFont)"));
+ m_classNameToSignals[QLatin1String("QTextEdit")].append(QLatin1String("currentColorChanged(QColor)"));
+ m_classNameToSignals[QLatin1String("QTabWidget")].append(QLatin1String("currentChanged(QWidget*)"));
+ m_classNameToSignals[QLatin1String("QTabWidget")].append(QLatin1String("selected(QString)"));
+ m_classNameToSignals[QLatin1String("QTabBar")].append(QLatin1String("selected(int)"));
+ m_classNameToSignals[QLatin1String("QMenuBar")].append(QLatin1String("activated(int)"));
+ m_classNameToSignals[QLatin1String("QMenuBar")].append(QLatin1String("highlighted(int)"));
+ m_classNameToSignals[QLatin1String("QMenu")].append(QLatin1String("activated(int)"));
+ m_classNameToSignals[QLatin1String("QMenu")].append(QLatin1String("highlighted(int)"));
+ m_classNameToSignals[QLatin1String("QLineEdit")].append(QLatin1String("lostFocus()"));
+ m_classNameToSignals[QLatin1String("QDial")].append(QLatin1String("dialPressed()"));
+ m_classNameToSignals[QLatin1String("QDial")].append(QLatin1String("dialMoved(int)"));
+ m_classNameToSignals[QLatin1String("QDial")].append(QLatin1String("dialReleased()"));
+ m_classNameToSignals[QLatin1String("QComboBox")].append(QLatin1String("textChanged(QString)"));
+ m_classNameToSignals[QLatin1String("QActionGroup")].append(QLatin1String("selected(QAction*)"));
+ m_classNameToSignals[QLatin1String("QAction")].append(QLatin1String("activated(int)"));
+ m_classNameToSignals[QLatin1String("QAbstractSocket")].append(QLatin1String("connectionClosed()"));
+ m_classNameToSignals[QLatin1String("QAbstractSocket")].append(QLatin1String("delayedCloseFinished()"));
+
+ m_classNameToSlots[QLatin1String("QWidget")].append(QLatin1String("setShown(bool)"));
+ m_classNameToSlots[QLatin1String("QToolButton")].append(QLatin1String("setTextPosition(QToolButton::TextPosition)"));
+ m_classNameToSlots[QLatin1String("QToolButton")].append(QLatin1String("setUsesBigPixmap(bool)"));
+ m_classNameToSlots[QLatin1String("QToolButton")].append(QLatin1String("setUsesTextLabel(bool)"));
+ m_classNameToSlots[QLatin1String("QTextEdit")].append(QLatin1String("setModified(bool)"));
+ m_classNameToSlots[QLatin1String("QTextEdit")].append(QLatin1String("setColor(QColor)"));
+ m_classNameToSlots[QLatin1String("QTabWidget")].append(QLatin1String("setCurrentPage(int)"));
+ m_classNameToSlots[QLatin1String("QTabWidget")].append(QLatin1String("showPage(QWidget*)"));
+ m_classNameToSlots[QLatin1String("QTabWidget")].append(QLatin1String("removePage(QWidget*)"));
+ m_classNameToSlots[QLatin1String("QTabBar")].append(QLatin1String("setCurrentTab(int)"));
+ m_classNameToSlots[QLatin1String("QStatusBar")].append(QLatin1String("message(QString,int)"));
+ m_classNameToSlots[QLatin1String("QStatusBar")].append(QLatin1String("clear()"));
+ m_classNameToSlots[QLatin1String("QSplashScreen")].append(QLatin1String("message(QString,int)"));
+ m_classNameToSlots[QLatin1String("QSplashScreen")].append(QLatin1String("clear()"));
+ m_classNameToSlots[QLatin1String("QSlider")].append(QLatin1String("addStep()"));
+ m_classNameToSlots[QLatin1String("QSlider")].append(QLatin1String("subtractStep()"));
+ m_classNameToSlots[QLatin1String("QAbstractButton")].append(QLatin1String("setOn(bool)"));
+ m_classNameToSlots[QLatin1String("QAction")].append(QLatin1String("setOn(bool)"));
+ m_classNameToSlots[QLatin1String("QErrorMessage")].append(QLatin1String("message(QString)"));
+ m_classNameToSlots[QLatin1String("QTimer")].append(QLatin1String("changeInterval(int)"));
+ m_classNameToSlots[QLatin1String("QTimer")].append(QLatin1String("start(int,bool)"));
+}
+
+Qt3Members *Qt3Members::instance()
+{
+ if (!m_instance)
+ m_instance = new Qt3Members();
+ return m_instance;
+}
+}
+
+QT_BEGIN_NAMESPACE
+
+static QList<QByteArray> stringListToByteArray(const QStringList &l)
+{
+ if (l.empty())
+ return QList<QByteArray>();
+ QList<QByteArray> rc;
+ const QStringList::const_iterator cend = l.constEnd();
+ for (QStringList::const_iterator it = l.constBegin(); it != cend; ++it)
+ rc += it->toUtf8();
+ return rc;
+}
+
+// Find the form editor in the hierarchy.
+// We know that the parent of the sheet is the extension manager
+// whose parent is the core.
+
+static QDesignerFormEditorInterface *formEditorForObject(QObject *o) {
+ do {
+ if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(o))
+ return core;
+ o = o->parent();
+ } while(o);
+ Q_ASSERT(o);
+ return 0;
+}
+
+// ------------ QDesignerMemberSheetPrivate
+class QDesignerMemberSheetPrivate {
+public:
+ explicit QDesignerMemberSheetPrivate(QObject *object, QObject *sheetParent);
+
+ QDesignerFormEditorInterface *m_core;
+ const QDesignerMetaObjectInterface *m_meta;
+
+ class Info {
+ public:
+ inline Info() : visible(true) {}
+
+ QString group;
+ bool visible;
+ };
+
+ typedef QHash<int, Info> InfoHash;
+
+ Info &ensureInfo(int index);
+
+ InfoHash m_info;
+};
+
+QDesignerMemberSheetPrivate::QDesignerMemberSheetPrivate(QObject *object, QObject *sheetParent) :
+ m_core(formEditorForObject(sheetParent)),
+ m_meta(m_core->introspection()->metaObject(object))
+{
+}
+
+QDesignerMemberSheetPrivate::Info &QDesignerMemberSheetPrivate::ensureInfo(int index)
+{
+ InfoHash::iterator it = m_info.find(index);
+ if (it == m_info.end()) {
+ it = m_info.insert(index, Info());
+ }
+ return it.value();
+}
+
+// --------- QDesignerMemberSheet
+
+QDesignerMemberSheet::QDesignerMemberSheet(QObject *object, QObject *parent) :
+ QObject(parent),
+ d(new QDesignerMemberSheetPrivate(object, parent))
+{
+}
+
+QDesignerMemberSheet::~QDesignerMemberSheet()
+{
+ delete d;
+}
+
+int QDesignerMemberSheet::count() const
+{
+ return d->m_meta->methodCount();
+}
+
+int QDesignerMemberSheet::indexOf(const QString &name) const
+{
+ return d->m_meta->indexOfMethod(name);
+}
+
+QString QDesignerMemberSheet::memberName(int index) const
+{
+ return d->m_meta->method(index)->tag();
+}
+
+QString QDesignerMemberSheet::declaredInClass(int index) const
+{
+ const QString member = d->m_meta->method(index)->signature();
+
+ // Find class whose superclass does not contain the method.
+ const QDesignerMetaObjectInterface *meta_obj = d->m_meta;
+
+ for (;;) {
+ const QDesignerMetaObjectInterface *tmp = meta_obj->superClass();
+ if (tmp == 0)
+ break;
+ if (tmp->indexOfMethod(member) == -1)
+ break;
+ meta_obj = tmp;
+ }
+ return meta_obj->className();
+}
+
+QString QDesignerMemberSheet::memberGroup(int index) const
+{
+ return d->m_info.value(index).group;
+}
+
+void QDesignerMemberSheet::setMemberGroup(int index, const QString &group)
+{
+ d->ensureInfo(index).group = group;
+}
+
+QString QDesignerMemberSheet::signature(int index) const
+{
+ return d->m_meta->method(index)->normalizedSignature();
+}
+
+bool QDesignerMemberSheet::isVisible(int index) const
+{
+ typedef QDesignerMemberSheetPrivate::InfoHash InfoHash;
+ const InfoHash::const_iterator it = d->m_info.constFind(index);
+ if (it != d->m_info.constEnd())
+ return it.value().visible;
+
+ return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Signal
+ || d->m_meta->method(index)->access() == QDesignerMetaMethodInterface::Public;
+}
+
+void QDesignerMemberSheet::setVisible(int index, bool visible)
+{
+ d->ensureInfo(index).visible = visible;
+}
+
+bool QDesignerMemberSheet::isSignal(int index) const
+{
+ return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Signal;
+}
+
+bool QDesignerMemberSheet::isSlot(int index) const
+{
+ return d->m_meta->method(index)->methodType() == QDesignerMetaMethodInterface::Slot;
+}
+
+bool QDesignerMemberSheet::inheritedFromWidget(int index) const
+{
+ const QString name = d->m_meta->method(index)->signature();
+ return declaredInClass(index) == QLatin1String("QWidget") || declaredInClass(index) == QLatin1String("QObject");
+}
+
+
+QList<QByteArray> QDesignerMemberSheet::parameterTypes(int index) const
+{
+ return stringListToByteArray(d->m_meta->method(index)->parameterTypes());
+}
+
+QList<QByteArray> QDesignerMemberSheet::parameterNames(int index) const
+{
+ return stringListToByteArray(d->m_meta->method(index)->parameterNames());
+}
+
+bool QDesignerMemberSheet::signalMatchesSlot(const QString &signal, const QString &slot)
+{
+ bool result = true;
+
+ do {
+ int signal_idx = signal.indexOf(QLatin1Char('('));
+ int slot_idx = slot.indexOf(QLatin1Char('('));
+ if (signal_idx == -1 || slot_idx == -1)
+ break;
+
+ ++signal_idx; ++slot_idx;
+
+ if (slot.at(slot_idx) == QLatin1Char(')'))
+ break;
+
+ while (signal_idx < signal.size() && slot_idx < slot.size()) {
+ const QChar signal_c = signal.at(signal_idx);
+ const QChar slot_c = slot.at(slot_idx);
+
+ if (signal_c == QLatin1Char(',') && slot_c == QLatin1Char(')'))
+ break;
+
+ if (signal_c == QLatin1Char(')') && slot_c == QLatin1Char(')'))
+ break;
+
+ if (signal_c != slot_c) {
+ result = false;
+ break;
+ }
+
+ ++signal_idx; ++slot_idx;
+ }
+ } while (false);
+
+ return result;
+}
+
+bool QDesignerMemberSheet::isQt3Signal(int index) const
+{
+ if (!isSignal(index))
+ return false;
+
+ const QString className = declaredInClass(index);
+ const QString signalSignature = signature(index);
+
+ QMap<QString, QStringList> qt3signals = Qt3Members::instance()->getSignals();
+ QMap<QString, QStringList>::const_iterator it = qt3signals.constFind(className);
+ if (it != qt3signals.constEnd() && (*it).contains(signalSignature))
+ return true;
+
+ return false;
+}
+
+bool QDesignerMemberSheet::isQt3Slot(int index) const
+{
+ if (!isSlot(index))
+ return false;
+
+ const QString className = declaredInClass(index);
+ const QString slotSignature = signature(index);
+
+ QMap<QString, QStringList> qt3slots = Qt3Members::instance()->getSlots();
+ QMap<QString, QStringList>::const_iterator it = qt3slots.constFind(className);
+ if (it != qt3slots.constEnd() && (*it).contains(slotSignature))
+ return true;
+ return false;
+}
+
+// ------------ QDesignerMemberSheetFactory
+
+QDesignerMemberSheetFactory::QDesignerMemberSheetFactory(QExtensionManager *parent)
+ : QExtensionFactory(parent)
+{
+}
+
+QObject *QDesignerMemberSheetFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid == Q_TYPEID(QDesignerMemberSheetExtension)) {
+ return new QDesignerMemberSheet(object, parent);
+ }
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_membersheet_p.h b/tools/designer/src/lib/shared/qdesigner_membersheet_p.h
new file mode 100644
index 0000000000..695b808590
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_membersheet_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_MEMBERSHEET_H
+#define QDESIGNER_MEMBERSHEET_H
+
+#include "shared_global_p.h"
+
+#include <QtDesigner/membersheet.h>
+#include <QtDesigner/default_extensionfactory.h>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerMemberSheetPrivate;
+
+class QDESIGNER_SHARED_EXPORT QDesignerMemberSheet: public QObject, public QDesignerMemberSheetExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerMemberSheetExtension)
+
+public:
+ explicit QDesignerMemberSheet(QObject *object, QObject *parent = 0);
+ virtual ~QDesignerMemberSheet();
+
+ virtual int indexOf(const QString &name) const;
+
+ virtual int count() const;
+ virtual QString memberName(int index) const;
+
+ virtual QString memberGroup(int index) const;
+ virtual void setMemberGroup(int index, const QString &group);
+
+ virtual bool isVisible(int index) const;
+ virtual void setVisible(int index, bool b);
+
+ virtual bool isSignal(int index) const;
+ virtual bool isSlot(int index) const;
+
+ virtual bool isQt3Signal(int index) const;
+ virtual bool isQt3Slot(int index) const;
+
+ virtual bool inheritedFromWidget(int index) const;
+
+ static bool signalMatchesSlot(const QString &signal, const QString &slot);
+
+ virtual QString declaredInClass(int index) const;
+
+ virtual QString signature(int index) const;
+ virtual QList<QByteArray> parameterTypes(int index) const;
+ virtual QList<QByteArray> parameterNames(int index) const;
+
+private:
+ QDesignerMemberSheetPrivate *d;
+};
+
+class QDESIGNER_SHARED_EXPORT QDesignerMemberSheetFactory: public QExtensionFactory
+{
+ Q_OBJECT
+ Q_INTERFACES(QAbstractExtensionFactory)
+
+public:
+ QDesignerMemberSheetFactory(QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_MEMBERSHEET_H
diff --git a/tools/designer/src/lib/shared/qdesigner_menu.cpp b/tools/designer/src/lib/shared/qdesigner_menu.cpp
new file mode 100644
index 0000000000..7aea52dd05
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_menu.cpp
@@ -0,0 +1,1355 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_menu_p.h"
+#include "qdesigner_menubar_p.h"
+#include "qdesigner_toolbar_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "actionrepository_p.h"
+#include "actionprovider_p.h"
+#include "actioneditor_p.h"
+#include "qdesigner_utils_p.h"
+#include "qdesigner_objectinspector_p.h"
+
+#include <QtCore/QTimer>
+#include <QtCore/qdebug.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QDesignerMetaDataBaseInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPainter>
+#include <QtGui/QRubberBand>
+#include <QtGui/QToolTip>
+#include <QtGui/QToolBar>
+#include <QtGui/qevent.h>
+
+Q_DECLARE_METATYPE(QAction*)
+
+QT_BEGIN_NAMESPACE
+
+using namespace qdesigner_internal;
+
+QDesignerMenu::QDesignerMenu(QWidget *parent) :
+ QMenu(parent),
+ m_currentIndex(0),
+ m_addItem(new SpecialMenuAction(this)),
+ m_addSeparator(new SpecialMenuAction(this)),
+ m_showSubMenuTimer(new QTimer(this)),
+ m_deactivateWindowTimer(new QTimer(this)),
+ m_adjustSizeTimer(new QTimer(this)),
+ m_editor(new QLineEdit(this)),
+ m_dragging(false),
+ m_lastSubMenuIndex(-1)
+{
+ setContextMenuPolicy(Qt::DefaultContextMenu);
+ setAcceptDrops(true); // ### fake
+ setSeparatorsCollapsible(false);
+
+ connect(m_adjustSizeTimer, SIGNAL(timeout()), this, SLOT(slotAdjustSizeNow()));
+ m_addItem->setText(tr("Type Here"));
+ addAction(m_addItem);
+
+ m_addSeparator->setText(tr("Add Separator"));
+ addAction(m_addSeparator);
+
+ connect(m_showSubMenuTimer, SIGNAL(timeout()), this, SLOT(slotShowSubMenuNow()));
+
+ connect(m_deactivateWindowTimer, SIGNAL(timeout()), this, SLOT(slotDeactivateNow()));
+
+ m_editor->setObjectName(QLatin1String("__qt__passive_editor"));
+ m_editor->hide();
+
+ m_editor->installEventFilter(this);
+ installEventFilter(this);
+}
+
+QDesignerMenu::~QDesignerMenu()
+{
+}
+
+void QDesignerMenu::slotAdjustSizeNow()
+{
+ // Not using a single-shot, since we want to compress the timers if many items are being
+ // adjusted
+ m_adjustSizeTimer->stop();
+ adjustSize();
+}
+
+bool QDesignerMenu::handleEvent(QWidget *widget, QEvent *event)
+{
+ if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) {
+ update();
+
+ if (widget == m_editor)
+ return false;
+ }
+
+ switch (event->type()) {
+ default: break;
+
+ case QEvent::MouseButtonPress:
+ return handleMousePressEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::MouseButtonRelease:
+ return handleMouseReleaseEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::MouseButtonDblClick:
+ return handleMouseDoubleClickEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::MouseMove:
+ return handleMouseMoveEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::ContextMenu:
+ return handleContextMenuEvent(widget, static_cast<QContextMenuEvent*>(event));
+ case QEvent::KeyPress:
+ return handleKeyPressEvent(widget, static_cast<QKeyEvent*>(event));
+ }
+
+ return true;
+}
+
+void QDesignerMenu::startDrag(const QPoint &pos, Qt::KeyboardModifiers modifiers)
+{
+ const int index = findAction(pos);
+ if (index >= realActionCount())
+ return;
+
+ QAction *action = safeActionAt(index);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ const Qt::DropAction dropAction = (modifiers & Qt::ControlModifier) ? Qt::CopyAction : Qt::MoveAction;
+ if (dropAction == Qt::MoveAction) {
+ RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw);
+ cmd->init(this, action, actions().at(index + 1));
+ fw->commandHistory()->push(cmd);
+ }
+
+ QDrag *drag = new QDrag(this);
+ drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap(action));
+ drag->setMimeData(new ActionRepositoryMimeData(action, dropAction));
+
+ const int old_index = m_currentIndex;
+ m_currentIndex = -1;
+
+ if (drag->start(dropAction) == Qt::IgnoreAction) {
+ if (dropAction == Qt::MoveAction) {
+ QAction *previous = safeActionAt(index);
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(this, action, previous);
+ fw->commandHistory()->push(cmd);
+ }
+
+ m_currentIndex = old_index;
+ }
+}
+
+bool QDesignerMenu::handleKeyPressEvent(QWidget * /*widget*/, QKeyEvent *e)
+{
+ m_showSubMenuTimer->stop();
+
+ if (m_editor->isHidden() && hasFocus()) { // In navigation mode
+ switch (e->key()) {
+
+ case Qt::Key_Delete:
+ if (m_currentIndex == -1 || m_currentIndex >= realActionCount())
+ break;
+ hideSubMenu();
+ deleteAction();
+ break;
+
+ case Qt::Key_Left:
+ e->accept();
+ moveLeft();
+ return true;
+
+ case Qt::Key_Right:
+ e->accept();
+ moveRight();
+ return true; // no update
+
+ case Qt::Key_Up:
+ e->accept();
+ moveUp(e->modifiers() & Qt::ControlModifier);
+ return true;
+
+ case Qt::Key_Down:
+ e->accept();
+ moveDown(e->modifiers() & Qt::ControlModifier);
+ return true;
+
+ case Qt::Key_PageUp:
+ m_currentIndex = 0;
+ break;
+
+ case Qt::Key_PageDown:
+ m_currentIndex = actions().count() - 1;
+ break;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ case Qt::Key_F2:
+ e->accept();
+ enterEditMode();
+ return true; // no update
+
+ case Qt::Key_Escape:
+ e->ignore();
+ setFocus();
+ hide();
+ closeMenuChain();
+ return true;
+
+ case Qt::Key_Alt:
+ case Qt::Key_Shift:
+ case Qt::Key_Control:
+ e->ignore();
+ setFocus(); // FIXME: this is because some other widget get the focus when CTRL is pressed
+ return true; // no update
+
+ default: {
+ QAction *action = currentAction();
+ if (!action || action->isSeparator() || action == m_addSeparator) {
+ e->ignore();
+ return true;
+ } else if (!e->text().isEmpty() && e->text().at(0).toLatin1() >= 32) {
+ showLineEdit();
+ QApplication::sendEvent(m_editor, e);
+ e->accept();
+ } else {
+ e->ignore();
+ }
+ }
+ return true;
+ }
+ } else if (m_editor->hasFocus()) { // In edit mode
+ switch (e->key()) {
+ default:
+ e->ignore();
+ return false;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ if (!m_editor->text().isEmpty()) {
+ leaveEditMode(ForceAccept);
+ m_editor->hide();
+ setFocus();
+ moveDown(false);
+ break;
+ }
+ // fall through
+
+ case Qt::Key_Escape:
+ m_editor->hide();
+ setFocus();
+ break;
+ }
+ }
+
+ e->accept();
+ update();
+
+ return true;
+}
+
+static void sendMouseEventTo(QWidget *target, const QPoint &targetPoint, const QMouseEvent *event)
+{
+ QMouseEvent e(event->type(), targetPoint, event->globalPos(), event->button(), event->buttons(), event->modifiers());
+ QApplication::sendEvent(target, &e);
+}
+
+bool QDesignerMenu::handleMouseDoubleClickEvent(QWidget *, QMouseEvent *event)
+{
+ event->accept();
+ m_startPosition = QPoint();
+
+ if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
+ return true;
+
+ if (!rect().contains(event->pos())) {
+ // special case for menubar
+ QWidget *target = QApplication::widgetAt(event->globalPos());
+ QMenuBar *mb = qobject_cast<QMenuBar*>(target);
+ QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(target);
+ if (mb != 0 || menu != 0) {
+ const QPoint pt = target->mapFromGlobal(event->globalPos());
+ QAction *action = mb == 0 ? menu->actionAt(pt) : mb->actionAt(pt);
+ if (action)
+ sendMouseEventTo(target, pt, event);
+ }
+ return true;
+ }
+
+ m_currentIndex = findAction(event->pos());
+ QAction *action = safeActionAt(m_currentIndex);
+
+ QRect pm_rect;
+ if (action->menu() || hasSubMenuPixmap(action)) {
+ pm_rect = subMenuPixmapRect(action);
+ pm_rect.setLeft(pm_rect.left() - 20); // give the user a little more
+ // space to click
+ }
+
+ if (!pm_rect.contains(event->pos()) && m_currentIndex != -1)
+ enterEditMode();
+
+ return true;
+}
+
+bool QDesignerMenu::handleMousePressEvent(QWidget * /*widget*/, QMouseEvent *event)
+{
+ if (!rect().contains(event->pos())) {
+ QWidget *clickedWidget = QApplication::widgetAt(event->globalPos());
+ if (QMenuBar *mb = qobject_cast<QMenuBar*>(clickedWidget)) {
+ const QPoint pt = mb->mapFromGlobal(event->globalPos());
+ if (QAction *action = mb->actionAt(pt)) {
+ QMenu * menu = action->menu();
+ if (menu == findRootMenu()) {
+ // propagate the mouse press event (but don't close the popup)
+ sendMouseEventTo(mb, pt, event);
+ return true;
+ }
+ }
+ }
+
+ if (QDesignerMenu *m = qobject_cast<QDesignerMenu *>(clickedWidget)) {
+ m->hideSubMenu();
+ sendMouseEventTo(m, m->mapFromGlobal(event->globalPos()), event);
+ } else {
+ QDesignerMenu *root = findRootMenu();
+ root->hide();
+ root->hideSubMenu();
+ }
+ if (clickedWidget) {
+ if (QWidget *focusProxy = clickedWidget->focusProxy())
+ clickedWidget = focusProxy;
+ if (clickedWidget->focusPolicy() != Qt::NoFocus)
+ clickedWidget->setFocus(Qt::OtherFocusReason);
+ }
+ return true;
+ }
+
+ m_showSubMenuTimer->stop();
+ m_startPosition = QPoint();
+ event->accept();
+
+ if (event->button() != Qt::LeftButton)
+ return true;
+
+ m_startPosition = mapFromGlobal(event->globalPos());
+
+ const int index = findAction(m_startPosition);
+
+ QAction *action = safeActionAt(index);
+ QRect pm_rect = subMenuPixmapRect(action);
+ pm_rect.setLeft(pm_rect.left() - 20); // give the user a little more space to click
+
+ const int old_index = m_currentIndex;
+ m_currentIndex = index;
+ if ((hasSubMenuPixmap(action) || action->menu() != 0)
+ && pm_rect.contains(m_startPosition)) {
+ if (m_currentIndex == m_lastSubMenuIndex) {
+ hideSubMenu();
+ } else
+ slotShowSubMenuNow();
+ } else {
+ if (index == old_index) {
+ if (m_currentIndex == m_lastSubMenuIndex)
+ hideSubMenu();
+ } else {
+ hideSubMenu();
+ }
+ }
+
+ update();
+ if (index != old_index)
+ selectCurrentAction();
+
+ return true;
+}
+
+bool QDesignerMenu::handleMouseReleaseEvent(QWidget *, QMouseEvent *event)
+{
+ event->accept();
+ m_startPosition = QPoint();
+
+ return true;
+}
+
+bool QDesignerMenu::handleMouseMoveEvent(QWidget *, QMouseEvent *event)
+{
+ if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
+ return true;
+
+ if (!rect().contains(event->pos())) {
+
+ if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::widgetAt(event->globalPos()))) {
+ const QPoint pt = mb->mapFromGlobal(event->globalPos());
+ QAction *action = mb->actionAt(pt);
+ if (action && action->menu() == findRootMenu()) {
+ // propagate the mouse press event (but don't close the popup)
+ sendMouseEventTo(mb, pt, event);
+ return true;
+ }
+ // hide the popup Qt will replay the event
+ slotDeactivateNow();
+ }
+ return true;
+ }
+
+ if (m_startPosition.isNull())
+ return true;
+
+ event->accept();
+
+ const QPoint pos = mapFromGlobal(event->globalPos());
+
+ if ((pos - m_startPosition).manhattanLength() < qApp->startDragDistance())
+ return true;
+
+ startDrag(m_startPosition, event->modifiers());
+ m_startPosition = QPoint();
+
+ return true;
+}
+
+bool QDesignerMenu::handleContextMenuEvent(QWidget *, QContextMenuEvent *event)
+{
+ event->accept();
+
+ const int index = findAction(mapFromGlobal(event->globalPos()));
+ QAction *action = safeActionAt(index);
+ if (qobject_cast<SpecialMenuAction*>(action))
+ return true;
+
+ QMenu menu;
+ QVariant itemData;
+ qVariantSetValue(itemData, action);
+
+ QAction *addSeparatorAction = menu.addAction(tr("Insert separator"));
+ addSeparatorAction->setData(itemData);
+
+ QAction *removeAction = 0;
+ if (action->isSeparator())
+ removeAction = menu.addAction(tr("Remove separator"));
+ else
+ removeAction = menu.addAction(tr("Remove action '%1'").arg(action->objectName()));
+ removeAction->setData(itemData);
+
+ connect(addSeparatorAction, SIGNAL(triggered(bool)), this, SLOT(slotAddSeparator()));
+ connect(removeAction, SIGNAL(triggered(bool)), this, SLOT(slotRemoveSelectedAction()));
+ menu.exec(event->globalPos());
+
+ return true;
+}
+
+void QDesignerMenu::slotAddSeparator()
+{
+ QAction *action = qobject_cast<QAction *>(sender());
+ if (!action)
+ return;
+
+ QAction *a = qvariant_cast<QAction*>(action->data());
+ Q_ASSERT(a != 0);
+
+ const int pos = actions().indexOf(a);
+ QAction *action_before = 0;
+ if (pos != -1)
+ action_before = safeActionAt(pos);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ fw->beginCommand(tr("Add separator"));
+ QAction *sep = createAction(QString(), true);
+
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(this, sep, action_before);
+ fw->commandHistory()->push(cmd);
+
+ if (parentMenu()) {
+ QAction *parent_action = parentMenu()->currentAction();
+ if (parent_action->menu() == 0) {
+ CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw);
+ cmd->init(parentMenu(), parentMenu()->currentAction());
+ fw->commandHistory()->push(cmd);
+ }
+ }
+
+ fw->endCommand();
+}
+
+void QDesignerMenu::slotRemoveSelectedAction()
+{
+ if (QAction *action = qobject_cast<QAction *>(sender()))
+ if (QAction *a = qvariant_cast<QAction*>(action->data()))
+ deleteAction(a);
+}
+
+void QDesignerMenu::deleteAction(QAction *a)
+{
+ const int pos = actions().indexOf(a);
+ QAction *action_before = 0;
+ if (pos != -1)
+ action_before = safeActionAt(pos + 1);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw);
+ cmd->init(this, a, action_before);
+ fw->commandHistory()->push(cmd);
+}
+
+QRect QDesignerMenu::subMenuPixmapRect(QAction *action) const
+{
+ static const QPixmap pm(QLatin1String(":/trolltech/formeditor/images/submenu.png"));
+ const QRect g = actionGeometry(action);
+ const int x = g.right() - pm.width() - 2;
+ const int y = g.top() + (g.height() - pm.height())/2 + 1;
+ return QRect(x, y, pm.width(), pm.height());
+}
+
+bool QDesignerMenu::hasSubMenuPixmap(QAction *action) const
+{
+ return action != 0
+ && qobject_cast<SpecialMenuAction*>(action) == 0
+ && !action->isSeparator()
+ && !action->menu()
+ && canCreateSubMenu(action);
+}
+
+void QDesignerMenu::showEvent ( QShowEvent * event )
+{
+ selectCurrentAction();
+ QMenu::showEvent (event);
+}
+
+void QDesignerMenu::paintEvent(QPaintEvent *event)
+{
+ QMenu::paintEvent(event);
+
+ QPainter p(this);
+
+ QAction *current = currentAction();
+
+ foreach (QAction *a, actions()) {
+ const QRect g = actionGeometry(a);
+
+ if (qobject_cast<SpecialMenuAction*>(a)) {
+ QLinearGradient lg(g.left(), g.top(), g.left(), g.bottom());
+ lg.setColorAt(0.0, Qt::transparent);
+ lg.setColorAt(0.7, QColor(0, 0, 0, 32));
+ lg.setColorAt(1.0, Qt::transparent);
+
+ p.fillRect(g, lg);
+ } else if (hasSubMenuPixmap(a)) {
+ static const QPixmap pm(QLatin1String(":/trolltech/formeditor/images/submenu.png"));
+ p.drawPixmap(subMenuPixmapRect(a).topLeft(), pm);
+ }
+ }
+
+ if (!hasFocus() || !current || m_dragging)
+ return;
+
+ if (QDesignerMenu *menu = parentMenu()) {
+ if (menu->dragging())
+ return;
+ }
+
+ if (QDesignerMenuBar *menubar = qobject_cast<QDesignerMenuBar*>(parentWidget())) {
+ if (menubar->dragging())
+ return;
+ }
+
+ const QRect g = actionGeometry(current);
+ drawSelection(&p, g.adjusted(1, 1, -3, -3));
+}
+
+bool QDesignerMenu::dragging() const
+{
+ return m_dragging;
+}
+
+QDesignerMenu *QDesignerMenu::findRootMenu() const
+{
+ if (parentMenu())
+ return parentMenu()->findRootMenu();
+
+ return const_cast<QDesignerMenu*>(this);
+}
+
+QDesignerMenu *QDesignerMenu::findActivatedMenu() const
+{
+ QList<QDesignerMenu*> candidates;
+ candidates.append(const_cast<QDesignerMenu*>(this));
+ candidates += qFindChildren<QDesignerMenu*>(this);
+
+ foreach (QDesignerMenu *m, candidates) {
+ if (m == qApp->activeWindow())
+ return m;
+ }
+
+ return 0;
+}
+
+bool QDesignerMenu::eventFilter(QObject *object, QEvent *event)
+{
+ if (object != this && object != m_editor) {
+ return false;
+ }
+
+ if (!m_editor->isHidden() && object == m_editor && event->type() == QEvent::FocusOut) {
+ leaveEditMode(Default);
+ m_editor->hide();
+ update();
+ return false;
+ }
+
+ bool dispatch = true;
+
+ switch (event->type()) {
+ default: break;
+
+ case QEvent::WindowDeactivate:
+ deactivateMenu();
+ break;
+ case QEvent::ContextMenu:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+
+ while (QApplication::activePopupWidget() && !qobject_cast<QDesignerMenu*>(QApplication::activePopupWidget())) {
+ QApplication::activePopupWidget()->close();
+ }
+
+ // fall through
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::MouseMove:
+ dispatch = (object != m_editor);
+ // no break
+
+ case QEvent::Enter:
+ case QEvent::Leave:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ if (dispatch)
+ if (QWidget *widget = qobject_cast<QWidget*>(object))
+ if (widget == this || isAncestorOf(widget))
+ return handleEvent(widget, event);
+ break;
+ }
+
+ return false;
+};
+
+int QDesignerMenu::findAction(const QPoint &pos) const
+{
+ const int index = actionIndexAt(this, pos, Qt::Vertical);
+ if (index == -1)
+ return realActionCount();
+
+ return index;
+}
+
+void QDesignerMenu::adjustIndicator(const QPoint &pos)
+{
+ if (QDesignerActionProviderExtension *a = actionProvider()) {
+ a->adjustIndicator(pos);
+ }
+}
+
+QDesignerMenu::ActionDragCheck QDesignerMenu::checkAction(QAction *action) const
+{
+ if (!action || (action->menu() && action->menu()->parentWidget() != const_cast<QDesignerMenu*>(this)))
+ return NoActionDrag; // menu action!! nothing to do
+
+ if (!Utils::isObjectAncestorOf(formWindow()->mainContainer(), action))
+ return NoActionDrag; // the action belongs to another form window
+
+ if (actions().contains(action))
+ return ActionDragOnSubMenu; // we already have the action in the menu
+
+ return AcceptActionDrag;
+}
+
+void QDesignerMenu::dragEnterEvent(QDragEnterEvent *event)
+{
+ const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
+ if (!d || d->actionList().empty()) {
+ event->ignore();
+ return;
+ }
+
+ QAction *action = d->actionList().first();
+
+ switch (checkAction(action)) {
+ case NoActionDrag:
+ event->ignore();
+ break;
+ case ActionDragOnSubMenu:
+ d->accept(event);
+ m_dragging = true;
+ break;
+ case AcceptActionDrag:
+ d->accept(event);
+ m_dragging = true;
+ adjustIndicator(event->pos());
+ break;
+ }
+}
+
+void QDesignerMenu::dragMoveEvent(QDragMoveEvent *event)
+{
+ if (actionGeometry(m_addSeparator).contains(event->pos())) {
+ event->ignore();
+ adjustIndicator(QPoint(-1, -1));
+ return;
+ }
+
+ const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
+ if (!d || d->actionList().empty()) {
+ event->ignore();
+ return;
+ }
+
+ QAction *action = d->actionList().first();
+ const ActionDragCheck dc = checkAction(action);
+ switch (dc) {
+ case NoActionDrag:
+ event->ignore();
+ break;
+ case ActionDragOnSubMenu:
+ case AcceptActionDrag: { // Do not pop up submenu of action being dragged
+ const int newIndex = findAction(event->pos());
+ if (safeActionAt(newIndex) != action) {
+ m_currentIndex = newIndex;
+ if (m_lastSubMenuIndex != m_currentIndex)
+ m_showSubMenuTimer->start(300);
+ }
+ if (dc == AcceptActionDrag) {
+ adjustIndicator(event->pos());
+ d->accept(event);
+ } else {
+ event->ignore();
+ }
+ }
+ break;
+ }
+}
+
+void QDesignerMenu::dragLeaveEvent(QDragLeaveEvent *)
+{
+ m_dragging = false;
+ adjustIndicator(QPoint(-1, -1));
+ m_showSubMenuTimer->stop();
+}
+
+void QDesignerMenu::dropEvent(QDropEvent *event)
+{
+ m_showSubMenuTimer->stop();
+ hideSubMenu();
+ m_dragging = false;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
+ if (!d || d->actionList().empty()) {
+ event->ignore();
+ return;
+ }
+ QAction *action = d->actionList().first();
+ if (action && checkAction(action) == AcceptActionDrag) {
+ event->acceptProposedAction();
+ int index = findAction(event->pos());
+ index = qMin(index, actions().count() - 1);
+
+ fw->beginCommand(tr("Insert action"));
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(this, action, safeActionAt(index));
+ fw->commandHistory()->push(cmd);
+
+ m_currentIndex = index;
+
+ if (parentMenu()) {
+ QAction *parent_action = parentMenu()->currentAction();
+ if (parent_action->menu() == 0) {
+ CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw);
+ cmd->init(parentMenu(), parentMenu()->currentAction(), action);
+ fw->commandHistory()->push(cmd);
+ }
+ }
+ update();
+ fw->endCommand();
+ } else {
+ event->ignore();
+ }
+ adjustIndicator(QPoint(-1, -1));
+}
+
+void QDesignerMenu::actionEvent(QActionEvent *event)
+{
+ QMenu::actionEvent(event);
+ m_adjustSizeTimer->start(0);
+}
+
+QDesignerFormWindowInterface *QDesignerMenu::formWindow() const
+{
+ if (parentMenu())
+ return parentMenu()->formWindow();
+
+ return QDesignerFormWindowInterface::findFormWindow(parentWidget());
+}
+
+QDesignerActionProviderExtension *QDesignerMenu::actionProvider()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QDesignerFormEditorInterface *core = fw->core();
+ return qt_extension<QDesignerActionProviderExtension*>(core->extensionManager(), this);
+ }
+
+ return 0;
+}
+
+void QDesignerMenu::closeMenuChain()
+{
+ m_showSubMenuTimer->stop();
+
+ QWidget *w = this;
+ while (w && qobject_cast<QMenu*>(w))
+ w = w->parentWidget();
+
+ if (w) {
+ foreach (QMenu *subMenu, qFindChildren<QMenu*>(w)) {
+ subMenu->hide();
+ }
+ }
+
+ m_lastSubMenuIndex = -1;
+}
+
+void QDesignerMenu::moveLeft()
+{
+ if (parentMenu()) {
+ hide();
+ } else {
+ closeMenuChain();
+ if (QDesignerMenuBar *mb = parentMenuBar()) {
+ if (QApplication::layoutDirection() == Qt::LeftToRight)
+ mb->moveLeft();
+ else
+ mb->moveRight();
+ }
+ }
+ update();
+}
+
+void QDesignerMenu::moveRight()
+{
+ QAction *action = currentAction();
+
+ if (qobject_cast<SpecialMenuAction*>(action) || action->isSeparator()) {
+ closeMenuChain();
+ if (QDesignerMenuBar *mb = parentMenuBar()) {
+ if (QApplication::layoutDirection() == Qt::LeftToRight)
+ mb->moveRight();
+ else
+ mb->moveLeft();
+ }
+ } else {
+ m_lastSubMenuIndex = -1; // force a refresh
+ slotShowSubMenuNow();
+ }
+}
+
+void QDesignerMenu::moveUp(bool ctrl)
+{
+ if (m_currentIndex == 0) {
+ hide();
+ return;
+ }
+
+ if (ctrl)
+ (void) swap(m_currentIndex, m_currentIndex - 1);
+
+ m_currentIndex = qMax(0, --m_currentIndex);
+ // Always re-select, swapping destroys order
+ update();
+ selectCurrentAction();
+}
+
+void QDesignerMenu::moveDown(bool ctrl)
+{
+ if (m_currentIndex == actions().count() - 1) {
+ return;
+ }
+
+ if (ctrl)
+ (void) swap(m_currentIndex + 1, m_currentIndex);
+
+ m_currentIndex = qMin(actions().count() - 1, ++m_currentIndex);
+ update();
+ if (!ctrl)
+ selectCurrentAction();
+}
+
+QAction *QDesignerMenu::currentAction() const
+{
+ if (m_currentIndex < 0 || m_currentIndex >= actions().count())
+ return 0;
+
+ return safeActionAt(m_currentIndex);
+}
+
+int QDesignerMenu::realActionCount() const
+{
+ return actions().count() - 2; // 2 fake actions
+}
+
+void QDesignerMenu::selectCurrentAction()
+{
+ QAction *action = currentAction();
+ if (!action || action == m_addSeparator || action == m_addItem)
+ return;
+
+ QDesignerObjectInspector *oi = 0;
+ if (QDesignerFormWindowInterface *fw = formWindow())
+ oi = qobject_cast<QDesignerObjectInspector *>(fw->core()->objectInspector());
+
+ if (!oi)
+ return;
+
+ oi->clearSelection();
+ if (QMenu *menu = action->menu())
+ oi->selectObject(menu);
+ else
+ oi->selectObject(action);
+}
+
+void QDesignerMenu::createRealMenuAction(QAction *action)
+{
+ if (action->menu())
+ return; // nothing to do
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ QDesignerFormEditorInterface *core = formWindow()->core();
+
+ QDesignerMenu *menu = findOrCreateSubMenu(action);
+ m_subMenus.remove(action);
+
+ action->setMenu(menu);
+ menu->setTitle(action->text());
+
+ Q_ASSERT(fw);
+
+ core->widgetFactory()->initialize(menu);
+
+ const QString niceObjectName = ActionEditor::actionTextToName(menu->title(), QLatin1String("menu"));
+ menu->setObjectName(niceObjectName);
+
+ core->metaDataBase()->add(menu);
+ fw->ensureUniqueObjectName(menu);
+
+ QAction *menuAction = menu->menuAction();
+ core->metaDataBase()->add(menuAction);
+}
+
+void QDesignerMenu::removeRealMenu(QAction *action)
+{
+ QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(action->menu());
+ if (menu == 0)
+ return;
+ action->setMenu(0);
+ m_subMenus.insert(action, menu);
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ core->metaDataBase()->remove(menu);
+}
+
+QDesignerMenu *QDesignerMenu::findOrCreateSubMenu(QAction *action)
+{
+ if (action->menu())
+ return qobject_cast<QDesignerMenu*>(action->menu());
+
+ QDesignerMenu *menu = m_subMenus.value(action);
+ if (!menu) {
+ menu = new QDesignerMenu(this);
+ m_subMenus.insert(action, menu);
+ }
+
+ return menu;
+}
+
+bool QDesignerMenu::canCreateSubMenu(QAction *action) const // ### improve it's a bit too slow
+{
+ foreach (const QWidget *aw, action->associatedWidgets())
+ if (aw != this) {
+ if (const QMenu *m = qobject_cast<const QMenu *>(aw)) {
+ if (m->actions().contains(action))
+ return false; // sorry
+ } else {
+ if (const QToolBar *tb = qobject_cast<const QToolBar *>(aw))
+ if (tb->actions().contains(action))
+ return false; // sorry
+ }
+ }
+ return true;
+}
+
+void QDesignerMenu::slotShowSubMenuNow()
+{
+ m_showSubMenuTimer->stop();
+
+ if (m_lastSubMenuIndex == m_currentIndex)
+ return;
+
+ if (m_lastSubMenuIndex != -1)
+ hideSubMenu();
+
+ if (m_currentIndex >= realActionCount())
+ return;
+
+ QAction *action = currentAction();
+
+ if (action->isSeparator() || !canCreateSubMenu(action))
+ return;
+
+ if (QMenu *menu = findOrCreateSubMenu(action)) {
+ if (!menu->isVisible()) {
+ if ((menu->windowFlags() & Qt::Popup) != Qt::Popup)
+ menu->setWindowFlags(Qt::Popup);
+ const QRect g = actionGeometry(action);
+ menu->move(mapToGlobal(g.topRight()));
+ menu->show();
+ menu->setFocus();
+ } else {
+ menu->raise();
+ }
+ menu->setFocus();
+
+ m_lastSubMenuIndex = m_currentIndex;
+ }
+}
+
+void QDesignerMenu::showSubMenu(QAction *action)
+{
+ m_showSubMenuTimer->stop();
+
+ if (m_editor->isVisible() || !action || qobject_cast<SpecialMenuAction*>(action)
+ || action->isSeparator() || !isVisible())
+ return;
+
+ m_showSubMenuTimer->start(300);
+}
+
+QDesignerMenu *QDesignerMenu::parentMenu() const
+{
+ return qobject_cast<QDesignerMenu*>(parentWidget());
+}
+
+QDesignerMenuBar *QDesignerMenu::parentMenuBar() const
+{
+ if (QDesignerMenuBar *mb = qobject_cast<QDesignerMenuBar*>(parentWidget())) {
+ return mb;
+ } else if (QDesignerMenu *m = parentMenu()) {
+ return m->parentMenuBar();
+ }
+
+ return 0;
+}
+
+void QDesignerMenu::setVisible(bool visible)
+{
+ if (visible)
+ m_currentIndex = 0;
+ else
+ m_lastSubMenuIndex = -1;
+
+ QMenu::setVisible(visible);
+
+}
+
+void QDesignerMenu::adjustSpecialActions()
+{
+ removeAction(m_addItem);
+ removeAction(m_addSeparator);
+ addAction(m_addItem);
+ addAction(m_addSeparator);
+}
+
+bool QDesignerMenu::interactive(bool i)
+{
+ const bool old = m_interactive;
+ m_interactive = i;
+ return old;
+}
+
+void QDesignerMenu::enterEditMode()
+{
+ if (m_currentIndex >= 0 && m_currentIndex <= realActionCount()) {
+ showLineEdit();
+ } else {
+ hideSubMenu();
+ QDesignerFormWindowInterface *fw = formWindow();
+ fw->beginCommand(tr("Add separator"));
+ QAction *sep = createAction(QString(), true);
+
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(this, sep, safeActionAt(realActionCount()));
+ fw->commandHistory()->push(cmd);
+
+ if (parentMenu()) {
+ QAction *parent_action = parentMenu()->currentAction();
+ if (parent_action->menu() == 0) {
+ CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw);
+ cmd->init(parentMenu(), parentMenu()->currentAction());
+ fw->commandHistory()->push(cmd);
+ }
+ }
+
+ fw->endCommand();
+
+ m_currentIndex = actions().indexOf(m_addItem);
+ update();
+ }
+}
+
+void QDesignerMenu::leaveEditMode(LeaveEditMode mode)
+{
+ if (mode == Default)
+ return;
+
+ QAction *action = 0;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (m_currentIndex < realActionCount()) {
+ action = safeActionAt(m_currentIndex);
+ fw->beginCommand(QApplication::translate("Command", "Set action text"));
+ } else {
+ Q_ASSERT(fw != 0);
+ fw->beginCommand(QApplication::translate("Command", "Insert action"));
+ action = createAction(ActionEditor::actionTextToName(m_editor->text()));
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(this, action, currentAction());
+ fw->commandHistory()->push(cmd);
+ }
+
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(action, QLatin1String("text"), m_editor->text());
+ fw->commandHistory()->push(cmd);
+
+ if (parentMenu()) {
+ QAction *parent_action = parentMenu()->currentAction();
+ if (parent_action->menu() == 0) {
+ CreateSubmenuCommand *cmd = new CreateSubmenuCommand(fw);
+ cmd->init(parentMenu(), parentMenu()->currentAction(), action);
+ fw->commandHistory()->push(cmd);
+ }
+ }
+
+ update();
+ fw->endCommand();
+}
+
+QAction *QDesignerMenu::safeMenuAction(QDesignerMenu *menu) const
+{
+ QAction *action = menu->menuAction();
+
+ if (!action)
+ action = m_subMenus.key(menu);
+
+ return action;
+}
+
+void QDesignerMenu::showLineEdit()
+{
+ m_showSubMenuTimer->stop();
+
+ QAction *action = 0;
+
+ if (m_currentIndex < realActionCount())
+ action = safeActionAt(m_currentIndex);
+ else
+ action = m_addItem;
+
+ if (action->isSeparator())
+ return;
+
+ hideSubMenu();
+
+ // open edit field for item name
+ setFocus();
+
+ const QString text = action != m_addItem ? action->text() : QString();
+ m_editor->setText(text);
+ m_editor->selectAll();
+ m_editor->setGeometry(actionGeometry(action).adjusted(1, 1, -2, -2));
+ m_editor->show();
+ m_editor->setFocus();
+}
+
+QAction *QDesignerMenu::createAction(const QString &objectName, bool separator)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ Q_ASSERT(fw);
+ return ToolBarEventFilter::createAction(fw, objectName, separator);
+}
+
+// ### share with QDesignerMenu::swap
+bool QDesignerMenu::swap(int a, int b)
+{
+ const int left = qMin(a, b);
+ int right = qMax(a, b);
+
+ QAction *action_a = safeActionAt(left);
+ QAction *action_b = safeActionAt(right);
+
+ if (action_a == action_b
+ || !action_a
+ || !action_b
+ || qobject_cast<SpecialMenuAction*>(action_a)
+ || qobject_cast<SpecialMenuAction*>(action_b))
+ return false; // nothing to do
+
+ right = qMin(right, realActionCount());
+ if (right < 0)
+ return false; // nothing to do
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ fw->beginCommand(QApplication::translate("Command", "Move action"));
+
+ QAction *action_b_before = safeActionAt(right + 1);
+
+ RemoveActionFromCommand *cmd1 = new RemoveActionFromCommand(fw);
+ cmd1->init(this, action_b, action_b_before, false);
+ fw->commandHistory()->push(cmd1);
+
+ QAction *action_a_before = safeActionAt(left + 1);
+
+ InsertActionIntoCommand *cmd2 = new InsertActionIntoCommand(fw);
+ cmd2->init(this, action_b, action_a_before, false);
+ fw->commandHistory()->push(cmd2);
+
+ RemoveActionFromCommand *cmd3 = new RemoveActionFromCommand(fw);
+ cmd3->init(this, action_a, action_b, false);
+ fw->commandHistory()->push(cmd3);
+
+ InsertActionIntoCommand *cmd4 = new InsertActionIntoCommand(fw);
+ cmd4->init(this, action_a, action_b_before, true);
+ fw->commandHistory()->push(cmd4);
+
+ fw->endCommand();
+
+ return true;
+}
+
+QAction *QDesignerMenu::safeActionAt(int index) const
+{
+ if (index < 0 || index >= actions().count())
+ return 0;
+
+ return actions().at(index);
+}
+
+void QDesignerMenu::hideSubMenu()
+{
+ m_lastSubMenuIndex = -1;
+ foreach (QMenu *subMenu, qFindChildren<QMenu*>(this)) {
+ subMenu->hide();
+ }
+}
+
+void QDesignerMenu::deleteAction()
+{
+ QAction *action = currentAction();
+ const int pos = actions().indexOf(action);
+ QAction *action_before = 0;
+ if (pos != -1)
+ action_before = safeActionAt(pos + 1);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw);
+ cmd->init(this, action, action_before);
+ fw->commandHistory()->push(cmd);
+
+ update();
+}
+
+void QDesignerMenu::deactivateMenu()
+{
+ m_deactivateWindowTimer->start(10);
+}
+
+void QDesignerMenu::slotDeactivateNow()
+{
+ m_deactivateWindowTimer->stop();
+
+ if (m_dragging)
+ return;
+
+ QDesignerMenu *root = findRootMenu();
+
+ if (! root->findActivatedMenu()) {
+ root->hide();
+ root->hideSubMenu();
+ }
+}
+
+void QDesignerMenu::drawSelection(QPainter *p, const QRect &r)
+{
+ p->save();
+
+ QColor c = Qt::blue;
+ p->setPen(QPen(c, 1));
+ c.setAlpha(32);
+ p->setBrush(c);
+ p->drawRect(r);
+
+ p->restore();
+}
+
+void QDesignerMenu::keyPressEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+void QDesignerMenu::keyReleaseEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_menu_p.h b/tools/designer/src/lib/shared/qdesigner_menu_p.h
new file mode 100644
index 0000000000..ac3ec03c9b
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_menu_p.h
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_MENU_H
+#define QDESIGNER_MENU_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QTimer;
+class QLineEdit;
+
+class QDesignerFormWindowInterface;
+class QDesignerActionProviderExtension;
+class QDesignerMenu;
+class QDesignerMenuBar;
+class QPainter;
+class QMimeData;
+
+namespace qdesigner_internal {
+ class CreateSubmenuCommand;
+ class ActionInsertionCommand;
+}
+
+class QDESIGNER_SHARED_EXPORT QDesignerMenu: public QMenu
+{
+ Q_OBJECT
+public:
+ QDesignerMenu(QWidget *parent = 0);
+ virtual ~QDesignerMenu();
+
+ bool eventFilter(QObject *object, QEvent *event);
+
+ QDesignerFormWindowInterface *formWindow() const;
+ QDesignerActionProviderExtension *actionProvider();
+
+ QDesignerMenu *parentMenu() const;
+ QDesignerMenuBar *parentMenuBar() const;
+
+ virtual void setVisible(bool visible);
+
+ void adjustSpecialActions();
+
+ bool interactive(bool i);
+ void createRealMenuAction(QAction *action);
+ void removeRealMenu(QAction *action);
+
+ static void drawSelection(QPainter *p, const QRect &r);
+
+ bool dragging() const;
+
+ void closeMenuChain();
+
+ void moveLeft();
+ void moveRight();
+ void moveUp(bool ctrl);
+ void moveDown(bool ctrl);
+
+ // Helper for MenuTaskMenu extension
+ void deleteAction(QAction *a);
+
+private slots:
+ void slotAddSeparator();
+ void slotRemoveSelectedAction();
+ void slotShowSubMenuNow();
+ void slotDeactivateNow();
+ void slotAdjustSizeNow();
+
+protected:
+ virtual void actionEvent(QActionEvent *event);
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dragMoveEvent(QDragMoveEvent *event);
+ virtual void dragLeaveEvent(QDragLeaveEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+ virtual void paintEvent(QPaintEvent *event);
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+ virtual void showEvent(QShowEvent *event);
+
+ bool handleEvent(QWidget *widget, QEvent *event);
+ bool handleMouseDoubleClickEvent(QWidget *widget, QMouseEvent *event);
+ bool handleMousePressEvent(QWidget *widget, QMouseEvent *event);
+ bool handleMouseReleaseEvent(QWidget *widget, QMouseEvent *event);
+ bool handleMouseMoveEvent(QWidget *widget, QMouseEvent *event);
+ bool handleContextMenuEvent(QWidget *widget, QContextMenuEvent *event);
+ bool handleKeyPressEvent(QWidget *widget, QKeyEvent *event);
+
+ void startDrag(const QPoint &pos, Qt::KeyboardModifiers modifiers);
+
+ void adjustIndicator(const QPoint &pos);
+ int findAction(const QPoint &pos) const;
+
+ QAction *currentAction() const;
+ int realActionCount() const;
+ enum ActionDragCheck { NoActionDrag, ActionDragOnSubMenu, AcceptActionDrag };
+ ActionDragCheck checkAction(QAction *action) const;
+
+ void showSubMenu(QAction *action);
+
+ enum LeaveEditMode {
+ Default = 0,
+ ForceAccept
+ };
+
+ void enterEditMode();
+ void leaveEditMode(LeaveEditMode mode);
+ void showLineEdit();
+
+ QAction *createAction(const QString &text, bool separator = false);
+ QDesignerMenu *findOrCreateSubMenu(QAction *action);
+
+ QAction *safeActionAt(int index) const;
+ QAction *safeMenuAction(QDesignerMenu *menu) const;
+ bool swap(int a, int b);
+
+ void hideSubMenu();
+ void deleteAction();
+ void deactivateMenu();
+
+ bool canCreateSubMenu(QAction *action) const;
+ QDesignerMenu *findRootMenu() const;
+ QDesignerMenu *findActivatedMenu() const;
+
+ QRect subMenuPixmapRect(QAction *action) const;
+ bool hasSubMenuPixmap(QAction *action) const;
+
+ void selectCurrentAction();
+
+private:
+ QPoint m_startPosition;
+ int m_currentIndex;
+ QAction *m_addItem;
+ QAction *m_addSeparator;
+ QHash<QAction*, QDesignerMenu*> m_subMenus;
+ QTimer *m_showSubMenuTimer;
+ QTimer *m_deactivateWindowTimer;
+ QTimer *m_adjustSizeTimer;
+ bool m_interactive;
+ QLineEdit *m_editor;
+ bool m_dragging;
+ int m_lastSubMenuIndex;
+
+ friend class qdesigner_internal::CreateSubmenuCommand;
+ friend class qdesigner_internal::ActionInsertionCommand;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_MENU_H
diff --git a/tools/designer/src/lib/shared/qdesigner_menubar.cpp b/tools/designer/src/lib/shared/qdesigner_menubar.cpp
new file mode 100644
index 0000000000..97f1734c80
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_menubar.cpp
@@ -0,0 +1,955 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_menubar_p.h"
+#include "qdesigner_menu_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "actionrepository_p.h"
+#include "actionprovider_p.h"
+#include "actioneditor_p.h"
+#include "qdesigner_utils_p.h"
+#include "promotiontaskmenu_p.h"
+#include "qdesigner_objectinspector_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QMimeData>
+
+#include <QtCore/qdebug.h>
+
+#include <QtGui/QApplication>
+#include <QtGui/QDrag>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPainter>
+#include <QtGui/qevent.h>
+
+Q_DECLARE_METATYPE(QAction*)
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QAction *> ActionList;
+
+using namespace qdesigner_internal;
+
+namespace qdesigner_internal
+{
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+SpecialMenuAction::SpecialMenuAction(QObject *parent)
+ : QAction(parent)
+{
+}
+
+SpecialMenuAction::~SpecialMenuAction()
+{
+}
+
+
+} // namespace qdesigner_internal
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+QDesignerMenuBar::QDesignerMenuBar(QWidget *parent) :
+ QMenuBar(parent),
+ m_addMenu(new SpecialMenuAction(this)),
+ m_currentIndex(0),
+ m_interactive(true),
+ m_editor(new QLineEdit(this)),
+ m_dragging(false),
+ m_lastMenuActionIndex( -1),
+ m_promotionTaskMenu(new PromotionTaskMenu(this, PromotionTaskMenu::ModeSingleWidget, this))
+{
+ setContextMenuPolicy(Qt::DefaultContextMenu);
+
+ setAcceptDrops(true); // ### fake
+
+ m_addMenu->setText(tr("Type Here"));
+ addAction(m_addMenu);
+
+ QFont italic;
+ italic.setItalic(true);
+ m_addMenu->setFont(italic);
+
+ m_editor->setObjectName(QLatin1String("__qt__passive_editor"));
+ m_editor->hide();
+ m_editor->installEventFilter(this);
+ installEventFilter(this);
+}
+
+QDesignerMenuBar::~QDesignerMenuBar()
+{
+}
+
+void QDesignerMenuBar::paintEvent(QPaintEvent *event)
+{
+ QMenuBar::paintEvent(event);
+
+ QPainter p(this);
+
+ foreach (QAction *a, actions()) {
+ if (qobject_cast<SpecialMenuAction*>(a)) {
+ const QRect g = actionGeometry(a);
+ QLinearGradient lg(g.left(), g.top(), g.left(), g.bottom());
+ lg.setColorAt(0.0, Qt::transparent);
+ lg.setColorAt(0.7, QColor(0, 0, 0, 32));
+ lg.setColorAt(1.0, Qt::transparent);
+
+ p.fillRect(g, lg);
+ }
+ }
+
+ QAction *action = currentAction();
+
+ if (m_dragging || !action)
+ return;
+
+ if (hasFocus()) {
+ const QRect g = actionGeometry(action);
+ QDesignerMenu::drawSelection(&p, g.adjusted(1, 1, -1, -1));
+ } else if (action->menu() && action->menu()->isVisible()) {
+ const QRect g = actionGeometry(action);
+ p.drawRect(g.adjusted(1, 1, -1, -1));
+ }
+}
+
+bool QDesignerMenuBar::handleEvent(QWidget *widget, QEvent *event)
+{
+ if (!formWindow())
+ return false;
+
+ if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)
+ update();
+
+ switch (event->type()) {
+ default: break;
+
+ case QEvent::MouseButtonDblClick:
+ return handleMouseDoubleClickEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::MouseButtonPress:
+ return handleMousePressEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::MouseButtonRelease:
+ return handleMouseReleaseEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::MouseMove:
+ return handleMouseMoveEvent(widget, static_cast<QMouseEvent*>(event));
+ case QEvent::ContextMenu:
+ return handleContextMenuEvent(widget, static_cast<QContextMenuEvent*>(event));
+ case QEvent::KeyPress:
+ return handleKeyPressEvent(widget, static_cast<QKeyEvent*>(event));
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ return widget != m_editor;
+ }
+
+ return true;
+}
+
+bool QDesignerMenuBar::handleMouseDoubleClickEvent(QWidget *, QMouseEvent *event)
+{
+ if (!rect().contains(event->pos()))
+ return true;
+
+ if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
+ return true;
+
+ event->accept();
+
+ m_startPosition = QPoint();
+
+ m_currentIndex = actionIndexAt(this, event->pos(), Qt::Horizontal);
+ if (m_currentIndex != -1) {
+ showLineEdit();
+ }
+
+ return true;
+}
+
+bool QDesignerMenuBar::handleKeyPressEvent(QWidget *, QKeyEvent *e)
+{
+ if (m_editor->isHidden()) { // In navigation mode
+ switch (e->key()) {
+
+ case Qt::Key_Delete:
+ if (m_currentIndex == -1 || m_currentIndex >= realActionCount())
+ break;
+ hideMenu();
+ deleteMenu();
+ break;
+
+ case Qt::Key_Left:
+ e->accept();
+ if (QApplication::layoutDirection() == Qt::LeftToRight)
+ moveLeft(e->modifiers() & Qt::ControlModifier);
+ else
+ moveRight(e->modifiers() & Qt::ControlModifier);
+ return true;
+
+ case Qt::Key_Right:
+ e->accept();
+ if (QApplication::layoutDirection() == Qt::LeftToRight)
+ moveRight(e->modifiers() & Qt::ControlModifier);
+ else
+ moveLeft(e->modifiers() & Qt::ControlModifier);
+ return true; // no update
+
+ case Qt::Key_Up:
+ e->accept();
+ moveUp();
+ return true;
+
+ case Qt::Key_Down:
+ e->accept();
+ moveDown();
+ return true;
+
+ case Qt::Key_PageUp:
+ m_currentIndex = 0;
+ break;
+
+ case Qt::Key_PageDown:
+ m_currentIndex = actions().count() - 1;
+ break;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ e->accept();
+ enterEditMode();
+ return true; // no update
+
+ case Qt::Key_Alt:
+ case Qt::Key_Shift:
+ case Qt::Key_Control:
+ case Qt::Key_Escape:
+ e->ignore();
+ setFocus(); // FIXME: this is because some other widget get the focus when CTRL is pressed
+ return true; // no update
+
+ default:
+ if (!e->text().isEmpty() && e->text().at(0).toLatin1() >= 32) {
+ showLineEdit();
+ QApplication::sendEvent(m_editor, e);
+ e->accept();
+ } else {
+ e->ignore();
+ }
+ return true;
+ }
+ } else { // In edit mode
+ switch (e->key()) {
+ default:
+ return false;
+
+ case Qt::Key_Control:
+ e->ignore();
+ return true;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ if (!m_editor->text().isEmpty()) {
+ leaveEditMode(ForceAccept);
+ if (m_lastFocusWidget)
+ m_lastFocusWidget->setFocus();
+
+ m_editor->hide();
+ showMenu();
+ break;
+ }
+ // fall through
+
+ case Qt::Key_Escape:
+ update();
+ setFocus();
+ break;
+ }
+ }
+
+ e->accept();
+ update();
+
+ return true;
+}
+
+void QDesignerMenuBar::startDrag(const QPoint &pos)
+{
+ const int index = findAction(pos);
+ if (m_currentIndex == -1 || index >= realActionCount())
+ return;
+
+ QAction *action = safeActionAt(index);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw);
+ cmd->init(this, action, actions().at(index + 1));
+ fw->commandHistory()->push(cmd);
+
+ adjustSize();
+
+ hideMenu(index);
+
+ QDrag *drag = new QDrag(this);
+ drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap(action));
+ drag->setMimeData(new ActionRepositoryMimeData(action, Qt::MoveAction));
+
+ const int old_index = m_currentIndex;
+ m_currentIndex = -1;
+
+ if (drag->start(Qt::MoveAction) == Qt::IgnoreAction) {
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(this, action, safeActionAt(index));
+ fw->commandHistory()->push(cmd);
+
+ m_currentIndex = old_index;
+ adjustSize();
+ }
+}
+
+bool QDesignerMenuBar::handleMousePressEvent(QWidget *, QMouseEvent *event)
+{
+ m_startPosition = QPoint();
+ event->accept();
+
+ if (event->button() != Qt::LeftButton)
+ return true;
+
+ m_startPosition = event->pos();
+ const int newIndex = actionIndexAt(this, m_startPosition, Qt::Horizontal);
+ const bool changed = newIndex != m_currentIndex;
+ m_currentIndex = newIndex;
+ updateCurrentAction(changed);
+
+ return true;
+}
+
+bool QDesignerMenuBar::handleMouseReleaseEvent(QWidget *, QMouseEvent *event)
+{
+ m_startPosition = QPoint();
+
+ if (event->button() != Qt::LeftButton)
+ return true;
+
+ event->accept();
+ m_currentIndex = actionIndexAt(this, event->pos(), Qt::Horizontal);
+ if (!m_editor->isVisible() && m_currentIndex != -1 && m_currentIndex < realActionCount())
+ showMenu();
+
+ return true;
+}
+
+bool QDesignerMenuBar::handleMouseMoveEvent(QWidget *, QMouseEvent *event)
+{
+ if ((event->buttons() & Qt::LeftButton) != Qt::LeftButton)
+ return true;
+
+ if (m_startPosition.isNull())
+ return true;
+
+ const QPoint pos = mapFromGlobal(event->globalPos());
+
+ if ((pos - m_startPosition).manhattanLength() < qApp->startDragDistance())
+ return true;
+
+ const int index = actionIndexAt(this, m_startPosition, Qt::Horizontal);
+ if (index < actions().count()) {
+ hideMenu(index);
+ update();
+ }
+
+ startDrag(m_startPosition);
+ m_startPosition = QPoint();
+
+ return true;
+}
+
+ActionList QDesignerMenuBar::contextMenuActions()
+{
+ ActionList rc;
+ if (QAction *action = safeActionAt(m_currentIndex)) {
+ if (!qobject_cast<SpecialMenuAction*>(action)) {
+ QVariant itemData;
+ qVariantSetValue(itemData, action);
+
+ QAction *remove_action = new QAction(tr("Remove Menu '%1'").arg(action->menu()->objectName()), 0);
+ remove_action->setData(itemData);
+ connect(remove_action, SIGNAL(triggered()), this, SLOT(deleteMenu()));
+ rc.push_back(remove_action);
+ QAction *sep = new QAction(0);
+ sep->setSeparator(true);
+ rc.push_back(sep);
+ }
+ }
+
+ m_promotionTaskMenu->addActions(formWindow(), PromotionTaskMenu::TrailingSeparator, rc);
+
+ QAction *remove_menubar = new QAction(tr("Remove Menu Bar"), 0);
+ connect(remove_menubar, SIGNAL(triggered()), this, SLOT(slotRemoveMenuBar()));
+ rc.push_back(remove_menubar);
+ return rc;
+}
+
+bool QDesignerMenuBar::handleContextMenuEvent(QWidget *, QContextMenuEvent *event)
+{
+ event->accept();
+
+ m_currentIndex = actionIndexAt(this, mapFromGlobal(event->globalPos()), Qt::Horizontal);
+
+ update();
+
+ QMenu menu;
+ const ActionList al = contextMenuActions();
+ const ActionList::const_iterator acend = al.constEnd();
+ for (ActionList::const_iterator it = al.constBegin(); it != acend; ++it)
+ menu.addAction(*it);
+ menu.exec(event->globalPos());
+ return true;
+}
+
+void QDesignerMenuBar::slotRemoveMenuBar()
+{
+ Q_ASSERT(formWindow() != 0);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+
+ DeleteMenuBarCommand *cmd = new DeleteMenuBarCommand(fw);
+ cmd->init(this);
+ fw->commandHistory()->push(cmd);
+}
+
+void QDesignerMenuBar::focusOutEvent(QFocusEvent *event)
+{
+ QMenuBar::focusOutEvent(event);
+}
+
+void QDesignerMenuBar::enterEditMode()
+{
+ if (m_currentIndex >= 0 && m_currentIndex <= realActionCount()) {
+ showLineEdit();
+ }
+}
+
+void QDesignerMenuBar::leaveEditMode(LeaveEditMode mode)
+{
+ m_editor->releaseKeyboard();
+
+ if (mode == Default)
+ return;
+
+ if (m_editor->text().isEmpty())
+ return;
+
+ QAction *action = 0;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ Q_ASSERT(fw);
+
+ if (m_currentIndex >= 0 && m_currentIndex < realActionCount()) {
+ action = safeActionAt(m_currentIndex);
+ fw->beginCommand(QApplication::translate("Command", "Change Title"));
+ } else {
+ fw->beginCommand(QApplication::translate("Command", "Insert Menu"));
+ const QString niceObjectName = ActionEditor::actionTextToName(m_editor->text(), QLatin1String("menu"));
+ QMenu *menu = qobject_cast<QMenu*>(fw->core()->widgetFactory()->createWidget(QLatin1String("QMenu"), this));
+ fw->core()->widgetFactory()->initialize(menu);
+ menu->setObjectName(niceObjectName);
+ menu->setTitle(tr("Menu"));
+ fw->ensureUniqueObjectName(menu);
+ action = menu->menuAction();
+ AddMenuActionCommand *cmd = new AddMenuActionCommand(fw);
+ cmd->init(action, m_addMenu, this, this);
+ fw->commandHistory()->push(cmd);
+ }
+
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(action, QLatin1String("text"), m_editor->text());
+ fw->commandHistory()->push(cmd);
+ fw->endCommand();
+}
+
+void QDesignerMenuBar::showLineEdit()
+{
+ QAction *action = 0;
+
+ if (m_currentIndex >= 0 && m_currentIndex < realActionCount())
+ action = safeActionAt(m_currentIndex);
+ else
+ action = m_addMenu;
+
+ if (action->isSeparator())
+ return;
+
+ // hideMenu();
+
+ m_lastFocusWidget = qApp->focusWidget();
+
+ // open edit field for item name
+ const QString text = action != m_addMenu ? action->text() : QString();
+
+ m_editor->setText(text);
+ m_editor->selectAll();
+ m_editor->setGeometry(actionGeometry(action));
+ m_editor->show();
+ qApp->setActiveWindow(m_editor);
+ m_editor->setFocus();
+ m_editor->grabKeyboard();
+}
+
+bool QDesignerMenuBar::eventFilter(QObject *object, QEvent *event)
+{
+ if (object != this && object != m_editor)
+ return false;
+
+ if (!m_editor->isHidden() && object == m_editor && event->type() == QEvent::FocusOut) {
+ leaveEditMode(Default);
+ m_editor->hide();
+ update();
+ return true;
+ }
+
+ bool dispatch = true;
+
+ switch (event->type()) {
+ default: break;
+
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::ContextMenu:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ dispatch = (object != m_editor);
+ // no break
+
+ case QEvent::Enter:
+ case QEvent::Leave:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ {
+ QWidget *widget = qobject_cast<QWidget*>(object);
+
+ if (dispatch && widget && (widget == this || isAncestorOf(widget)))
+ return handleEvent(widget, event);
+ } break;
+
+ case QEvent::Shortcut:
+ event->accept();
+ return true;
+ }
+
+ return false;
+};
+
+int QDesignerMenuBar::findAction(const QPoint &pos) const
+{
+ const int index = actionIndexAt(this, pos, Qt::Horizontal);
+ if (index == -1)
+ return realActionCount();
+
+ return index;
+}
+
+void QDesignerMenuBar::adjustIndicator(const QPoint &pos)
+{
+ const int index = findAction(pos);
+ QAction *action = safeActionAt(index);
+ Q_ASSERT(action != 0);
+
+ if (pos != QPoint(-1, -1)) {
+ QDesignerMenu *m = qobject_cast<QDesignerMenu*>(action->menu());
+ if (!m || m->parentMenu()) {
+ m_currentIndex = index;
+ showMenu(index);
+ }
+ }
+
+ if (QDesignerActionProviderExtension *a = actionProvider()) {
+ a->adjustIndicator(pos);
+ }
+}
+
+QDesignerMenuBar::ActionDragCheck QDesignerMenuBar::checkAction(QAction *action) const
+{
+ // action belongs to another form
+ if (!action || !Utils::isObjectAncestorOf(formWindow()->mainContainer(), action))
+ return NoActionDrag;
+
+ if (!action->menu())
+ return ActionDragOnSubMenu; // simple action only on sub menus
+
+ QDesignerMenu *m = qobject_cast<QDesignerMenu*>(action->menu());
+ if (m && m->parentMenu())
+ return ActionDragOnSubMenu; // it looks like a submenu
+
+ if (actions().contains(action))
+ return ActionDragOnSubMenu; // we already have the action in the menubar
+
+ return AcceptActionDrag;
+}
+
+void QDesignerMenuBar::dragEnterEvent(QDragEnterEvent *event)
+{
+ const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
+ if (!d || d->actionList().empty()) {
+ event->ignore();
+ return;
+ }
+
+ QAction *action = d->actionList().first();
+ switch (checkAction(action)) {
+ case NoActionDrag:
+ event->ignore();
+ break;
+ case ActionDragOnSubMenu:
+ m_dragging = true;
+ d->accept(event);
+ break;
+ case AcceptActionDrag:
+ m_dragging = true;
+ d->accept(event);
+ adjustIndicator(event->pos());
+ break;
+ }
+}
+
+void QDesignerMenuBar::dragMoveEvent(QDragMoveEvent *event)
+{
+ const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
+ if (!d || d->actionList().empty()) {
+ event->ignore();
+ return;
+ }
+ QAction *action = d->actionList().first();
+
+ switch (checkAction(action)) {
+ case NoActionDrag:
+ event->ignore();
+ break;
+ case ActionDragOnSubMenu:
+ event->ignore();
+ showMenu(findAction(event->pos()));
+ break;
+ case AcceptActionDrag:
+ d->accept(event);
+ adjustIndicator(event->pos());
+ break;
+ }
+}
+
+void QDesignerMenuBar::dragLeaveEvent(QDragLeaveEvent *)
+{
+ m_dragging = false;
+
+ adjustIndicator(QPoint(-1, -1));
+}
+
+void QDesignerMenuBar::dropEvent(QDropEvent *event)
+{
+ m_dragging = false;
+
+ if (const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData())) {
+
+ QAction *action = d->actionList().first();
+ if (checkAction(action) == AcceptActionDrag) {
+ event->acceptProposedAction();
+ int index = findAction(event->pos());
+ index = qMin(index, actions().count() - 1);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(this, action, safeActionAt(index));
+ fw->commandHistory()->push(cmd);
+
+ m_currentIndex = index;
+ update();
+ adjustIndicator(QPoint(-1, -1));
+ return;
+ }
+ }
+ event->ignore();
+}
+
+void QDesignerMenuBar::actionEvent(QActionEvent *event)
+{
+ QMenuBar::actionEvent(event);
+}
+
+QDesignerFormWindowInterface *QDesignerMenuBar::formWindow() const
+{
+ return QDesignerFormWindowInterface::findFormWindow(const_cast<QDesignerMenuBar*>(this));
+}
+
+QDesignerActionProviderExtension *QDesignerMenuBar::actionProvider()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QDesignerFormEditorInterface *core = fw->core();
+ return qt_extension<QDesignerActionProviderExtension*>(core->extensionManager(), this);
+ }
+
+ return 0;
+}
+
+QAction *QDesignerMenuBar::currentAction() const
+{
+ if (m_currentIndex < 0 || m_currentIndex >= actions().count())
+ return 0;
+
+ return safeActionAt(m_currentIndex);
+}
+
+int QDesignerMenuBar::realActionCount() const
+{
+ return actions().count() - 1; // 1 fake actions
+}
+
+void QDesignerMenuBar::moveLeft(bool ctrl)
+{
+ if (ctrl)
+ (void) swap(m_currentIndex, m_currentIndex - 1);
+
+ m_currentIndex = qMax(0, --m_currentIndex);
+ // Always re-select, swapping destroys order
+ updateCurrentAction(true);
+}
+
+bool QDesignerMenuBar::dragging() const
+{
+ return m_dragging;
+}
+
+void QDesignerMenuBar::moveRight(bool ctrl)
+{
+ if (ctrl)
+ (void) swap(m_currentIndex + 1, m_currentIndex);
+
+ m_currentIndex = qMin(actions().count() - 1, ++m_currentIndex);
+ updateCurrentAction(!ctrl);
+}
+
+void QDesignerMenuBar::moveUp()
+{
+ update();
+}
+
+void QDesignerMenuBar::moveDown()
+{
+ showMenu();
+}
+
+void QDesignerMenuBar::adjustSpecialActions()
+{
+ removeAction(m_addMenu);
+ addAction(m_addMenu);
+}
+
+bool QDesignerMenuBar::interactive(bool i)
+{
+ const bool old = m_interactive;
+ m_interactive = i;
+ return old;
+}
+
+void QDesignerMenuBar::hideMenu(int index)
+{
+ if (index < 0 && m_currentIndex >= 0)
+ index = m_currentIndex;
+
+ if (index < 0 || index >= realActionCount())
+ return;
+
+ QAction *action = safeActionAt(index);
+
+ if (action && action->menu()) {
+ action->menu()->hide();
+
+ if (QDesignerMenu *menu = qobject_cast<QDesignerMenu*>(action->menu())) {
+ menu->closeMenuChain();
+ }
+ }
+}
+
+void QDesignerMenuBar::deleteMenu()
+{
+ deleteMenuAction(currentAction());
+}
+
+void QDesignerMenuBar::deleteMenuAction(QAction *action)
+{
+ if (action && !qobject_cast<SpecialMenuAction*>(action)) {
+ const int pos = actions().indexOf(action);
+ QAction *action_before = 0;
+ if (pos != -1)
+ action_before = safeActionAt(pos + 1);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ RemoveMenuActionCommand *cmd = new RemoveMenuActionCommand(fw);
+ cmd->init(action, action_before, this, this);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QDesignerMenuBar::showMenu(int index)
+{
+ if (index < 0 && m_currentIndex >= 0)
+ index = m_currentIndex;
+
+ if (index < 0 || index >= realActionCount())
+ return;
+
+ m_currentIndex = index;
+ QAction *action = currentAction();
+
+ if (action && action->menu()) {
+ if (m_lastMenuActionIndex != -1 && m_lastMenuActionIndex != index) {
+ hideMenu(m_lastMenuActionIndex);
+ }
+
+ m_lastMenuActionIndex = index;
+ QMenu *menu = action->menu();
+ const QRect g = actionGeometry(action);
+
+ if (!menu->isVisible()) {
+ if ((menu->windowFlags() & Qt::Popup) != Qt::Popup)
+ menu->setWindowFlags(Qt::Popup);
+ menu->adjustSize();
+ menu->move(mapToGlobal(g.bottomLeft()));
+ menu->setFocus(Qt::MouseFocusReason);
+ menu->raise();
+ menu->show();
+ } else {
+ menu->raise();
+ }
+ }
+}
+
+QAction *QDesignerMenuBar::safeActionAt(int index) const
+{
+ if (index < 0 || index >= actions().count())
+ return 0;
+
+ return actions().at(index);
+}
+
+bool QDesignerMenuBar::swap(int a, int b)
+{
+ const int left = qMin(a, b);
+ int right = qMax(a, b);
+
+ QAction *action_a = safeActionAt(left);
+ QAction *action_b = safeActionAt(right);
+
+ if (action_a == action_b
+ || !action_a
+ || !action_b
+ || qobject_cast<SpecialMenuAction*>(action_a)
+ || qobject_cast<SpecialMenuAction*>(action_b))
+ return false; // nothing to do
+
+ right = qMin(right, realActionCount());
+ if (right < 0)
+ return false; // nothing to do
+
+ formWindow()->beginCommand(QApplication::translate("Command", "Move action"));
+
+ QAction *action_b_before = safeActionAt(right + 1);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ RemoveActionFromCommand *cmd1 = new RemoveActionFromCommand(fw);
+ cmd1->init(this, action_b, action_b_before, false);
+ fw->commandHistory()->push(cmd1);
+
+ QAction *action_a_before = safeActionAt(left + 1);
+
+ InsertActionIntoCommand *cmd2 = new InsertActionIntoCommand(fw);
+ cmd2->init(this, action_b, action_a_before, false);
+ fw->commandHistory()->push(cmd2);
+
+ RemoveActionFromCommand *cmd3 = new RemoveActionFromCommand(fw);
+ cmd3->init(this, action_a, action_b, false);
+ fw->commandHistory()->push(cmd3);
+
+ InsertActionIntoCommand *cmd4 = new InsertActionIntoCommand(fw);
+ cmd4->init(this, action_a, action_b_before, true);
+ fw->commandHistory()->push(cmd4);
+
+ fw->endCommand();
+
+ return true;
+}
+
+void QDesignerMenuBar::keyPressEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+void QDesignerMenuBar::keyReleaseEvent(QKeyEvent *event)
+{
+ event->ignore();
+}
+
+void QDesignerMenuBar::updateCurrentAction(bool selectAction)
+{
+ update();
+
+ if (!selectAction)
+ return;
+
+ QAction *action = currentAction();
+ if (!action || action == m_addMenu)
+ return;
+
+ QMenu *menu = action->menu();
+ if (!menu)
+ return;
+
+ QDesignerObjectInspector *oi = 0;
+ if (QDesignerFormWindowInterface *fw = formWindow())
+ oi = qobject_cast<QDesignerObjectInspector *>(fw->core()->objectInspector());
+
+ if (!oi)
+ return;
+
+ oi->clearSelection();
+ oi->selectObject(menu);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_menubar_p.h b/tools/designer/src/lib/shared/qdesigner_menubar_p.h
new file mode 100644
index 0000000000..7c8be4ca1d
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_menubar_p.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_MENUBAR_H
+#define QDESIGNER_MENUBAR_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QAction>
+#include <QtGui/QMenuBar>
+
+#include <QtCore/QPointer>
+#include <QtCore/QMimeData>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerActionProviderExtension;
+
+class QLineEdit;
+class QMimeData;
+
+namespace qdesigner_internal {
+class PromotionTaskMenu;
+
+class SpecialMenuAction: public QAction
+{
+ Q_OBJECT
+public:
+ SpecialMenuAction(QObject *parent = 0);
+ virtual ~SpecialMenuAction();
+};
+
+} // namespace qdesigner_internal
+
+class QDESIGNER_SHARED_EXPORT QDesignerMenuBar: public QMenuBar
+{
+ Q_OBJECT
+public:
+ QDesignerMenuBar(QWidget *parent = 0);
+ virtual ~QDesignerMenuBar();
+
+ bool eventFilter(QObject *object, QEvent *event);
+
+ QDesignerFormWindowInterface *formWindow() const;
+ QDesignerActionProviderExtension *actionProvider();
+
+ void adjustSpecialActions();
+ bool interactive(bool i);
+ bool dragging() const;
+
+ void moveLeft(bool ctrl = false);
+ void moveRight(bool ctrl = false);
+ void moveUp();
+ void moveDown();
+
+ // Helpers for MenuTaskMenu/MenuBarTaskMenu extensions
+ QList<QAction *> contextMenuActions();
+ void deleteMenuAction(QAction *action);
+
+private slots:
+ void deleteMenu();
+ void slotRemoveMenuBar();
+
+protected:
+ virtual void actionEvent(QActionEvent *event);
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dragMoveEvent(QDragMoveEvent *event);
+ virtual void dragLeaveEvent(QDragLeaveEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+ virtual void paintEvent(QPaintEvent *event);
+ virtual void focusOutEvent(QFocusEvent *event);
+ virtual void keyPressEvent(QKeyEvent *event);
+ virtual void keyReleaseEvent(QKeyEvent *event);
+
+ bool handleEvent(QWidget *widget, QEvent *event);
+ bool handleMouseDoubleClickEvent(QWidget *widget, QMouseEvent *event);
+ bool handleMousePressEvent(QWidget *widget, QMouseEvent *event);
+ bool handleMouseReleaseEvent(QWidget *widget, QMouseEvent *event);
+ bool handleMouseMoveEvent(QWidget *widget, QMouseEvent *event);
+ bool handleContextMenuEvent(QWidget *widget, QContextMenuEvent *event);
+ bool handleKeyPressEvent(QWidget *widget, QKeyEvent *event);
+
+ void startDrag(const QPoint &pos);
+
+ enum ActionDragCheck { NoActionDrag, ActionDragOnSubMenu, AcceptActionDrag };
+ ActionDragCheck checkAction(QAction *action) const;
+
+ void adjustIndicator(const QPoint &pos);
+ int findAction(const QPoint &pos) const;
+
+ QAction *currentAction() const;
+ int realActionCount() const;
+
+ enum LeaveEditMode {
+ Default = 0,
+ ForceAccept
+ };
+
+ void enterEditMode();
+ void leaveEditMode(LeaveEditMode mode);
+ void showLineEdit();
+
+ void showMenu(int index = -1);
+ void hideMenu(int index = -1);
+
+ QAction *safeActionAt(int index) const;
+
+ bool swap(int a, int b);
+
+private:
+ void updateCurrentAction(bool selectAction);
+
+ QAction *m_addMenu;
+ QPointer<QMenu> m_activeMenu;
+ QPoint m_startPosition;
+ int m_currentIndex;
+ bool m_interactive;
+ QLineEdit *m_editor;
+ bool m_dragging;
+ int m_lastMenuActionIndex;
+ QPointer<QWidget> m_lastFocusWidget;
+ qdesigner_internal::PromotionTaskMenu* m_promotionTaskMenu;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_MENUBAR_H
diff --git a/tools/designer/src/lib/shared/qdesigner_objectinspector.cpp b/tools/designer/src/lib/shared/qdesigner_objectinspector.cpp
new file mode 100644
index 0000000000..9cef55bd69
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_objectinspector.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_objectinspector_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QDesignerObjectInspector::QDesignerObjectInspector(QWidget *parent, Qt::WindowFlags flags) :
+ QDesignerObjectInspectorInterface(parent, flags)
+{
+}
+
+void QDesignerObjectInspector::mainContainerChanged()
+{
+}
+
+void Selection::clear()
+{
+ managed.clear();
+ unmanaged.clear();
+ objects.clear();
+}
+
+bool Selection::empty() const
+{
+ return managed.empty() && unmanaged.empty() && objects.empty();
+}
+
+QObjectList Selection::selection() const
+{
+ QObjectList rc(objects);
+ foreach (QObject* o, managed)
+ rc.push_back(o);
+ foreach (QObject* o, unmanaged)
+ rc.push_back(o);
+ return rc;
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_objectinspector_p.h b/tools/designer/src/lib/shared/qdesigner_objectinspector_p.h
new file mode 100644
index 0000000000..5a4a1635bf
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_objectinspector_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef DESIGNEROBJECTINSPECTOR_H
+#define DESIGNEROBJECTINSPECTOR_H
+
+#include "shared_global_p.h"
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerDnDItemInterface;
+
+namespace qdesigner_internal {
+
+struct QDESIGNER_SHARED_EXPORT Selection {
+ bool empty() const;
+ void clear();
+
+ // Merge all lists
+ QObjectList selection() const;
+
+ // Selection in cursor (managed widgets)
+ QWidgetList managed;
+ // Unmanaged widgets
+ QWidgetList unmanaged;
+ // Remaining selected objects (non-widgets)
+ QObjectList objects;
+};
+
+// Extends the QDesignerObjectInspectorInterface by functionality
+// to access the selection
+
+class QDESIGNER_SHARED_EXPORT QDesignerObjectInspector: public QDesignerObjectInspectorInterface
+{
+ Q_OBJECT
+public:
+ QDesignerObjectInspector(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+
+ // Select a qobject unmanaged by form window
+ virtual bool selectObject(QObject *o) = 0;
+ virtual void getSelection(Selection &s) const = 0;
+ virtual void clearSelection() = 0;
+
+public slots:
+ virtual void mainContainerChanged();
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DESIGNEROBJECTINSPECTOR_H
diff --git a/tools/designer/src/lib/shared/qdesigner_promotion.cpp b/tools/designer/src/lib/shared/qdesigner_promotion.cpp
new file mode 100644
index 0000000000..526b521ea5
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_promotion.cpp
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_promotion_p.h"
+#include "widgetdatabase_p.h"
+#include "metadatabase_p.h"
+#include "widgetdatabase_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtCore/QMap>
+#include <QtCore/QCoreApplication>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ // Return a set of on-promotable classes
+ const QSet<QString> &nonPromotableClasses() {
+ static QSet<QString> rc;
+ if (rc.empty()) {
+ rc.insert(QLatin1String("Line"));
+ rc.insert(QLatin1String("QAction"));
+ rc.insert(QLatin1String("Spacer"));
+ rc.insert(QLatin1String("QMainWindow"));
+ rc.insert(QLatin1String("QDialog"));
+ rc.insert(QLatin1String("QWorkspace"));
+ rc.insert(QLatin1String("QMdiArea"));
+ rc.insert(QLatin1String("QMdiSubWindow"));
+ }
+ return rc;
+ }
+
+ // Return widget database index of a promoted class or -1 with error message
+ int promotedWidgetDataBaseIndex(const QDesignerWidgetDataBaseInterface *widgetDataBase,
+ const QString &className,
+ QString *errorMessage) {
+ const int index = widgetDataBase->indexOfClassName(className);
+ if (index == -1 || !widgetDataBase->item(index)->isPromoted()) {
+ *errorMessage = QCoreApplication::tr("%1 is not a promoted class.").arg(className);
+ return -1;
+ }
+ return index;
+ }
+
+ // Return widget database item of a promoted class or 0 with error message
+ QDesignerWidgetDataBaseItemInterface *promotedWidgetDataBaseItem(const QDesignerWidgetDataBaseInterface *widgetDataBase,
+ const QString &className,
+ QString *errorMessage) {
+
+ const int index = promotedWidgetDataBaseIndex(widgetDataBase, className, errorMessage);
+ if (index == -1)
+ return 0;
+ return widgetDataBase->item(index);
+ }
+
+ // extract class name from xml "<widget class="QWidget" ...>". Quite a hack.
+ QString classNameFromXml(QString xml) {
+ static const QString tag = QLatin1String("class=\"");
+ const int pos = xml.indexOf(tag);
+ if (pos == -1)
+ return QString();
+ xml.remove(0, pos + tag.size());
+ const int closingPos = xml.indexOf(QLatin1Char('"'));
+ if (closingPos == -1)
+ return QString();
+ xml.remove(closingPos, xml.size() - closingPos);
+ return xml;
+ }
+
+ // return a list of class names in the scratch pad
+ QStringList getScratchPadClasses(const QDesignerWidgetBoxInterface *wb) {
+ QStringList rc;
+ const int catCount = wb->categoryCount();
+ for (int c = 0; c < catCount; c++) {
+ const QDesignerWidgetBoxInterface::Category category = wb->category(c);
+ if (category.type() == QDesignerWidgetBoxInterface::Category::Scratchpad) {
+ const int widgetCount = category.widgetCount();
+ for (int w = 0; w < widgetCount; w++) {
+ const QString className = classNameFromXml( category.widget(w).domXml());
+ if (!className.isEmpty())
+ rc += className;
+ }
+ }
+ }
+ return rc;
+ }
+}
+
+namespace qdesigner_internal {
+
+ QDesignerPromotion::QDesignerPromotion(QDesignerFormEditorInterface *core) :
+ m_core(core) {
+ }
+
+ bool QDesignerPromotion::addPromotedClass(const QString &baseClass,
+ const QString &className,
+ const QString &includeFile,
+ QString *errorMessage)
+ {
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase();
+ const int baseClassIndex = widgetDataBase->indexOfClassName(baseClass);
+
+ if (baseClassIndex == -1) {
+ *errorMessage = QCoreApplication::tr("The base class %1 is invalid.").arg(baseClass);
+ return false;
+ }
+
+ const int existingClassIndex = widgetDataBase->indexOfClassName(className);
+
+ if (existingClassIndex != -1) {
+ *errorMessage = QCoreApplication::tr("The class %1 already exists.").arg(className);
+ return false;
+ }
+ // Clone derived item.
+ QDesignerWidgetDataBaseItemInterface *promotedItem = WidgetDataBaseItem::clone(widgetDataBase->item(baseClassIndex));
+ // Also inherit the container flag in case of QWidget-derived classes
+ // as it is most likely intended for stacked pages.
+ // set new props
+ promotedItem->setName(className);
+ promotedItem->setGroup(QCoreApplication::tr("Promoted Widgets"));
+ promotedItem->setCustom(true);
+ promotedItem->setPromoted(true);
+ promotedItem->setExtends(baseClass);
+ promotedItem->setIncludeFile(includeFile);
+ widgetDataBase->append(promotedItem);
+ return true;
+ }
+
+ QList<QDesignerWidgetDataBaseItemInterface *> QDesignerPromotion::promotionBaseClasses() const
+ {
+ typedef QMap<QString, QDesignerWidgetDataBaseItemInterface *> SortedDatabaseItemMap;
+ SortedDatabaseItemMap sortedDatabaseItemMap;
+
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase();
+
+ const int cnt = widgetDataBase->count();
+ for (int i = 0; i < cnt; i++) {
+ QDesignerWidgetDataBaseItemInterface *dbItem = widgetDataBase->item(i);
+ if (canBePromoted(dbItem)) {
+ sortedDatabaseItemMap.insert(dbItem->name(), dbItem);
+ }
+ }
+
+ return sortedDatabaseItemMap.values();
+ }
+
+
+ bool QDesignerPromotion::canBePromoted(const QDesignerWidgetDataBaseItemInterface *dbItem) const
+ {
+ if (dbItem->isPromoted() || !dbItem->extends().isEmpty())
+ return false;
+
+ const QString name = dbItem->name();
+
+ if (nonPromotableClasses().contains(name))
+ return false;
+
+ if (name.startsWith(QLatin1String("QDesigner")) ||
+ name.startsWith(QLatin1String("QLayout")))
+ return false;
+
+ return true;
+ }
+
+ QDesignerPromotion::PromotedClasses QDesignerPromotion::promotedClasses() const
+ {
+ typedef QMap<QString, QDesignerWidgetDataBaseItemInterface *> ClassNameItemMap;
+ // A map containing base classes and their promoted classes.
+ typedef QMap<QString, ClassNameItemMap> BaseClassPromotedMap;
+
+ BaseClassPromotedMap baseClassPromotedMap;
+
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase();
+ // Look for promoted classes and insert into map according to base class.
+ const int cnt = widgetDataBase->count();
+ for (int i = 0; i < cnt; i++) {
+ QDesignerWidgetDataBaseItemInterface *dbItem = widgetDataBase->item(i);
+ if (dbItem->isPromoted()) {
+ const QString baseClassName = dbItem->extends();
+ BaseClassPromotedMap::iterator it = baseClassPromotedMap.find(baseClassName);
+ if (it == baseClassPromotedMap.end()) {
+ it = baseClassPromotedMap.insert(baseClassName, ClassNameItemMap());
+ }
+ it.value().insert(dbItem->name(), dbItem);
+ }
+ }
+ // convert map into list.
+ PromotedClasses rc;
+
+ if (baseClassPromotedMap.empty())
+ return rc;
+
+ const BaseClassPromotedMap::const_iterator bcend = baseClassPromotedMap.constEnd();
+ for (BaseClassPromotedMap::const_iterator bit = baseClassPromotedMap.constBegin(); bit != bcend; ++bit) {
+ const int baseIndex = widgetDataBase->indexOfClassName(bit.key());
+ Q_ASSERT(baseIndex >= 0);
+ QDesignerWidgetDataBaseItemInterface *baseItem = widgetDataBase->item(baseIndex);
+ // promoted
+ const ClassNameItemMap::const_iterator pcend = bit.value().constEnd();
+ for (ClassNameItemMap::const_iterator pit = bit.value().constBegin(); pit != pcend; ++pit) {
+ PromotedClass item;
+ item.baseItem = baseItem;
+ item.promotedItem = pit.value();
+ rc.push_back(item);
+ }
+ }
+
+ return rc;
+ }
+
+ QSet<QString> QDesignerPromotion::referencedPromotedClassNames() const {
+ QSet<QString> rc;
+ const MetaDataBase *metaDataBase = qobject_cast<const MetaDataBase*>(m_core->metaDataBase());
+ if (!metaDataBase)
+ return rc;
+
+ const QList<QObject*> objs = metaDataBase->objects();
+ const QList<QObject*>::const_iterator cend = objs.constEnd();
+ for ( QList<QObject*>::const_iterator it = objs.constBegin(); it != cend; ++it) {
+ const QString customClass = metaDataBase->metaDataBaseItem(*it)->customClassName();
+ if (!customClass.isEmpty())
+ rc.insert(customClass);
+
+ }
+ // check the scratchpad of the widget box
+ if (QDesignerWidgetBoxInterface *widgetBox = m_core->widgetBox()) {
+ const QStringList scratchPadClasses = getScratchPadClasses(widgetBox);
+ if (!scratchPadClasses.empty()) {
+ // Check whether these are actually promoted
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase();
+ QStringList::const_iterator cend = scratchPadClasses.constEnd();
+ for (QStringList::const_iterator it = scratchPadClasses.constBegin(); it != cend; ++it ) {
+ const int index = widgetDataBase->indexOfClassName(*it);
+ if (index != -1 && widgetDataBase->item(index)->isPromoted())
+ rc += *it;
+ }
+ }
+ }
+ return rc;
+ }
+
+ bool QDesignerPromotion::removePromotedClass(const QString &className, QString *errorMessage) {
+ // check if it exists and is promoted
+ WidgetDataBase *widgetDataBase = qobject_cast<WidgetDataBase *>(m_core->widgetDataBase());
+ if (!widgetDataBase) {
+ *errorMessage = QCoreApplication::tr("The class %1 cannot be removed").arg(className);
+ return false;
+ }
+
+ const int index = promotedWidgetDataBaseIndex(widgetDataBase, className, errorMessage);
+ if (index == -1)
+ return false;
+
+ if (referencedPromotedClassNames().contains(className)) {
+ *errorMessage = QCoreApplication::tr("The class %1 cannot be removed because it is still referenced.").arg(className);
+ return false;
+ }
+ widgetDataBase->remove(index);
+ return true;
+ }
+
+ bool QDesignerPromotion::changePromotedClassName(const QString &oldclassName, const QString &newClassName, QString *errorMessage) {
+ const MetaDataBase *metaDataBase = qobject_cast<const MetaDataBase*>(m_core->metaDataBase());
+ if (!metaDataBase) {
+ *errorMessage = QCoreApplication::tr("The class %1 cannot be renamed").arg(oldclassName);
+ return false;
+ }
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase();
+
+ // check the new name
+ if (newClassName.isEmpty()) {
+ *errorMessage = QCoreApplication::tr("The class %1 cannot be renamed to an empty name.").arg(oldclassName);
+ return false;
+ }
+ const int existingIndex = widgetDataBase->indexOfClassName(newClassName);
+ if (existingIndex != -1) {
+ *errorMessage = QCoreApplication::tr("There is already a class named %1.").arg(newClassName);
+ return false;
+ }
+ // Check old class
+ QDesignerWidgetDataBaseItemInterface *dbItem = promotedWidgetDataBaseItem(widgetDataBase, oldclassName, errorMessage);
+ if (!dbItem)
+ return false;
+
+ // Change the name in the data base and change all referencing objects in the meta database
+ dbItem->setName(newClassName);
+ bool foundReferences = false;
+ foreach (QObject* object, metaDataBase->objects()) {
+ MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(object);
+ Q_ASSERT(item);
+ if (item->customClassName() == oldclassName) {
+ item->setCustomClassName(newClassName);
+ foundReferences = true;
+ }
+ }
+ // set state
+ if (foundReferences)
+ refreshObjectInspector();
+
+ return true;
+ }
+
+ bool QDesignerPromotion::setPromotedClassIncludeFile(const QString &className, const QString &includeFile, QString *errorMessage) {
+ // check file
+ if (includeFile.isEmpty()) {
+ *errorMessage = QCoreApplication::tr("Cannot set an empty include file.");
+ return false;
+ }
+ // check item
+ QDesignerWidgetDataBaseInterface *widgetDataBase = m_core->widgetDataBase();
+ QDesignerWidgetDataBaseItemInterface *dbItem = promotedWidgetDataBaseItem(widgetDataBase, className, errorMessage);
+ if (!dbItem)
+ return false;
+
+ dbItem->setIncludeFile(includeFile);
+ return true;
+ }
+
+ void QDesignerPromotion::refreshObjectInspector() {
+ if (QDesignerFormWindowManagerInterface *fwm = m_core->formWindowManager()) {
+ if (QDesignerFormWindowInterface *fw = fwm->activeFormWindow())
+ if ( QDesignerObjectInspectorInterface *oi = m_core->objectInspector()) {
+ oi->setFormWindow(fw);
+ }
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_promotion_p.h b/tools/designer/src/lib/shared/qdesigner_promotion_p.h
new file mode 100644
index 0000000000..6806b4c4b2
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_promotion_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNERPROMOTION_H
+#define QDESIGNERPROMOTION_H
+
+#include "shared_global_p.h"
+
+#include <QtDesigner/QDesignerPromotionInterface>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+ class QDESIGNER_SHARED_EXPORT QDesignerPromotion : public QDesignerPromotionInterface
+ {
+ public:
+ explicit QDesignerPromotion(QDesignerFormEditorInterface *core);
+
+ virtual PromotedClasses promotedClasses() const;
+
+ virtual QSet<QString> referencedPromotedClassNames() const;
+
+ virtual bool addPromotedClass(const QString &baseClass,
+ const QString &className,
+ const QString &includeFile,
+ QString *errorMessage);
+
+ virtual bool removePromotedClass(const QString &className, QString *errorMessage);
+
+ virtual bool changePromotedClassName(const QString &oldclassName, const QString &newClassName, QString *errorMessage);
+
+ virtual bool setPromotedClassIncludeFile(const QString &className, const QString &includeFile, QString *errorMessage);
+
+ virtual QList<QDesignerWidgetDataBaseItemInterface *> promotionBaseClasses() const;
+
+ private:
+ bool canBePromoted(const QDesignerWidgetDataBaseItemInterface *) const;
+ void refreshObjectInspector();
+
+ QDesignerFormEditorInterface *m_core;
+ };
+}
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNERPROMOTION_H
diff --git a/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp
new file mode 100644
index 0000000000..8453c1683b
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_promotiondialog.cpp
@@ -0,0 +1,452 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::QDesignerPromotionDialog
+*/
+
+#include "qdesigner_promotiondialog_p.h"
+#include "promotionmodel_p.h"
+#include "iconloader_p.h"
+#include "widgetdatabase_p.h"
+#include "signalslotdialog_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerPromotionInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseItemInterface>
+#include <abstractdialoggui_p.h>
+
+#include <QtCore/QTimer>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QTreeView>
+#include <QtGui/QHeaderView>
+#include <QtGui/QPushButton>
+#include <QtGui/QItemSelectionModel>
+#include <QtGui/QItemSelection>
+#include <QtGui/QComboBox>
+#include <QtGui/QLineEdit>
+#include <QtGui/QCheckBox>
+#include <QtGui/QRegExpValidator>
+#include <QtGui/QLabel>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ // PromotionParameters
+ struct PromotionParameters {
+ QString m_baseClass;
+ QString m_className;
+ QString m_includeFile;
+ };
+
+ // NewPromotedClassPanel
+ NewPromotedClassPanel::NewPromotedClassPanel(const QStringList &baseClasses,
+ int selectedBaseClass,
+ QWidget *parent) :
+ QGroupBox(parent),
+ m_baseClassCombo(new QComboBox),
+ m_classNameEdit(new QLineEdit),
+ m_includeFileEdit(new QLineEdit),
+ m_globalIncludeCheckBox(new QCheckBox),
+ m_addButton(new QPushButton(tr("Add")))
+ {
+ setTitle(tr("New Promoted Class"));
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
+ QHBoxLayout *hboxLayout = new QHBoxLayout(this);
+
+ m_classNameEdit->setValidator(new QRegExpValidator(QRegExp(QLatin1String("[_a-zA-Z:][:_a-zA-Z0-9]*")), m_classNameEdit));
+ connect(m_classNameEdit, SIGNAL(textChanged(QString)), this, SLOT(slotNameChanged(QString)));
+ connect(m_includeFileEdit, SIGNAL(textChanged(QString)), this, SLOT(slotIncludeFileChanged(QString)));
+
+ m_baseClassCombo->setEditable(false);
+ m_baseClassCombo->addItems(baseClasses);
+ if (selectedBaseClass != -1)
+ m_baseClassCombo->setCurrentIndex(selectedBaseClass);
+
+ // Grid
+ QFormLayout *formLayout = new QFormLayout();
+ formLayout->addRow(tr("Base class name:"), m_baseClassCombo);
+ formLayout->addRow(tr("Promoted class name:"), m_classNameEdit);
+ formLayout->addRow(tr("Header file:"), m_includeFileEdit);
+ formLayout->addRow(tr("Global include"), m_globalIncludeCheckBox);
+ hboxLayout->addLayout(formLayout);
+ hboxLayout->addItem(new QSpacerItem(15, 0, QSizePolicy::Fixed, QSizePolicy::Ignored));
+ // Button box
+ QVBoxLayout *buttonLayout = new QVBoxLayout();
+
+ m_addButton->setAutoDefault(false);
+ connect(m_addButton, SIGNAL(clicked()), this, SLOT(slotAdd()));
+ m_addButton->setEnabled(false);
+ buttonLayout->addWidget(m_addButton);
+
+ QPushButton *resetButton = new QPushButton(tr("Reset"));
+ resetButton->setAutoDefault(false);
+ connect(resetButton, SIGNAL(clicked()), this, SLOT(slotReset()));
+
+ buttonLayout->addWidget(resetButton);
+ buttonLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding));
+ hboxLayout->addLayout(buttonLayout);
+
+ enableButtons();
+ }
+
+ void NewPromotedClassPanel::slotAdd() {
+ bool ok = false;
+ emit newPromotedClass(promotionParameters(), &ok);
+ if (ok)
+ slotReset();
+ }
+
+ void NewPromotedClassPanel::slotReset() {
+ const QString empty;
+ m_classNameEdit->setText(empty);
+ m_includeFileEdit->setText(empty);
+ m_globalIncludeCheckBox->setCheckState(Qt::Unchecked);
+ }
+
+ void NewPromotedClassPanel::grabFocus() {
+ m_classNameEdit->setFocus(Qt::OtherFocusReason);
+ }
+
+ void NewPromotedClassPanel::slotNameChanged(const QString &className) {
+ // Suggest a name
+ if (!className.isEmpty()) {
+ QString suggestedHeader = className.toLower().replace(QLatin1String("::"), QString(QLatin1Char('_')));
+ suggestedHeader += QLatin1String(".h");
+
+ const bool blocked = m_includeFileEdit->blockSignals(true);
+ m_includeFileEdit->setText(suggestedHeader);
+ m_includeFileEdit->blockSignals(blocked);
+ }
+ enableButtons();
+ }
+
+ void NewPromotedClassPanel::slotIncludeFileChanged(const QString &){
+ enableButtons();
+ }
+
+ void NewPromotedClassPanel::enableButtons() {
+ const bool enabled = !m_classNameEdit->text().isEmpty() && !m_includeFileEdit->text().isEmpty();
+ m_addButton->setEnabled(enabled);
+ m_addButton->setDefault(enabled);
+ }
+
+ PromotionParameters NewPromotedClassPanel::promotionParameters() const {
+ PromotionParameters rc;
+ rc.m_baseClass = m_baseClassCombo->currentText();
+ rc.m_className = m_classNameEdit->text();
+ rc.m_includeFile = buildIncludeFile(m_includeFileEdit->text(),
+ m_globalIncludeCheckBox->checkState() == Qt::Checked ? IncludeGlobal : IncludeLocal);
+ return rc;
+ }
+
+ void NewPromotedClassPanel::chooseBaseClass(const QString &baseClass) {
+ const int index = m_baseClassCombo->findText (baseClass);
+ if (index != -1)
+ m_baseClassCombo->setCurrentIndex (index);
+ }
+
+ // --------------- QDesignerPromotionDialog
+ QDesignerPromotionDialog::QDesignerPromotionDialog(QDesignerFormEditorInterface *core,
+ QWidget *parent,
+ const QString &promotableWidgetClassName,
+ QString *promoteTo) :
+ QDialog(parent),
+ m_mode(promotableWidgetClassName.isEmpty() || promoteTo == 0 ? ModeEdit : ModeEditChooseClass),
+ m_promotableWidgetClassName(promotableWidgetClassName),
+ m_core(core),
+ m_promoteTo(promoteTo),
+ m_promotion(core->promotion()),
+ m_model(new PromotionModel(core)),
+ m_treeView(new QTreeView),
+ m_buttonBox(0),
+ m_removeButton(new QPushButton(createIconSet(QString::fromUtf8("minus.png")), QString()))
+ {
+ m_buttonBox = createButtonBox();
+ setModal(true);
+ setWindowTitle(tr("Promoted Widgets"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QVBoxLayout *vboxLayout = new QVBoxLayout(this);
+
+ // tree view group
+ QGroupBox *treeViewGroup = new QGroupBox();
+ treeViewGroup->setTitle(tr("Promoted Classes"));
+ QVBoxLayout *treeViewVBoxLayout = new QVBoxLayout(treeViewGroup);
+ // tree view
+ m_treeView->setModel (m_model);
+ m_treeView->setMinimumWidth(450);
+ m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(m_treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+ this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+
+ connect(m_treeView, SIGNAL(customContextMenuRequested(QPoint)),
+ this, SLOT(slotTreeViewContextMenu(QPoint)));
+
+ QHeaderView *headerView = m_treeView->header();
+ headerView->setResizeMode(QHeaderView::ResizeToContents);
+ treeViewVBoxLayout->addWidget(m_treeView);
+ // remove button
+ QHBoxLayout *hboxLayout = new QHBoxLayout();
+ hboxLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
+
+ m_removeButton->setAutoDefault(false);
+ connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemove()));
+ m_removeButton->setEnabled(false);
+ hboxLayout->addWidget(m_removeButton);
+ treeViewVBoxLayout->addLayout(hboxLayout);
+ vboxLayout->addWidget(treeViewGroup);
+ // Create new panel: Try to be smart and preselect a base class. Default to QFrame
+ const QStringList &baseClassNameList = baseClassNames(m_promotion);
+ int preselectedBaseClass = -1;
+ if (m_mode == ModeEditChooseClass) {
+ preselectedBaseClass = baseClassNameList.indexOf(m_promotableWidgetClassName);
+ }
+ if (preselectedBaseClass == -1)
+ preselectedBaseClass = baseClassNameList.indexOf(QLatin1String("QFrame"));
+
+ NewPromotedClassPanel *newPromotedClassPanel = new NewPromotedClassPanel(baseClassNameList, preselectedBaseClass);
+ connect(newPromotedClassPanel, SIGNAL(newPromotedClass(PromotionParameters, bool *)), this, SLOT(slotNewPromotedClass(PromotionParameters, bool *)));
+ connect(this, SIGNAL(selectedBaseClassChanged(QString)),
+ newPromotedClassPanel, SLOT(chooseBaseClass(QString)));
+ vboxLayout->addWidget(newPromotedClassPanel);
+ // button box
+ vboxLayout->addWidget(m_buttonBox);
+ // connect model
+ connect(m_model, SIGNAL(includeFileChanged(QDesignerWidgetDataBaseItemInterface*, QString)),
+ this, SLOT(slotIncludeFileChanged(QDesignerWidgetDataBaseItemInterface*, QString)));
+
+ connect(m_model, SIGNAL(classNameChanged(QDesignerWidgetDataBaseItemInterface*, QString)),
+ this, SLOT(slotClassNameChanged(QDesignerWidgetDataBaseItemInterface*, QString)));
+
+ // focus
+ if (m_mode == ModeEditChooseClass)
+ newPromotedClassPanel->grabFocus();
+
+ slotUpdateFromWidgetDatabase();
+ }
+
+ QDialogButtonBox *QDesignerPromotionDialog::createButtonBox() {
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Close);
+
+ connect(buttonBox , SIGNAL(accepted()), this, SLOT(slotAcceptPromoteTo()));
+ buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Promote"));
+ buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+
+ connect(buttonBox , SIGNAL(rejected()), this, SLOT(reject()));
+ return buttonBox;
+ }
+
+ void QDesignerPromotionDialog::slotUpdateFromWidgetDatabase() {
+ m_model->updateFromWidgetDatabase();
+ m_treeView->expandAll();
+ m_removeButton->setEnabled(false);
+ }
+
+ void QDesignerPromotionDialog::delayedUpdateFromWidgetDatabase() {
+ QTimer::singleShot(0, this, SLOT(slotUpdateFromWidgetDatabase()));
+ }
+
+ const QStringList &QDesignerPromotionDialog::baseClassNames(const QDesignerPromotionInterface *promotion) {
+ typedef QList<QDesignerWidgetDataBaseItemInterface *> WidgetDataBaseItemList;
+ static QStringList rc;
+ if (rc.empty()) {
+ // Convert the item list into a string list.
+ const WidgetDataBaseItemList dbItems = promotion->promotionBaseClasses();
+ const WidgetDataBaseItemList::const_iterator cend = dbItems.constEnd();
+ for (WidgetDataBaseItemList::const_iterator it = dbItems.constBegin() ; it != cend; ++it) {
+ rc.push_back( (*it)->name());
+ }
+ }
+ return rc;
+ }
+
+ void QDesignerPromotionDialog::slotAcceptPromoteTo() {
+ Q_ASSERT(m_mode == ModeEditChooseClass);
+ unsigned flags;
+ // Ok pressed: Promote to selected class
+ if (QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags)) {
+ if (flags & CanPromote) {
+ *m_promoteTo = dbItem ->name();
+ accept();
+ }
+ }
+ }
+
+ void QDesignerPromotionDialog::slotRemove() {
+ unsigned flags;
+ QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags);
+ if (!dbItem || (flags & Referenced))
+ return;
+
+ QString errorMessage;
+ if (m_promotion->removePromotedClass(dbItem->name(), &errorMessage)) {
+ slotUpdateFromWidgetDatabase();
+ } else {
+ displayError(errorMessage);
+ }
+ }
+
+ void QDesignerPromotionDialog::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &) {
+ // Enable deleting non-referenced items
+ unsigned flags;
+ const QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(selected, flags);
+ m_removeButton->setEnabled(dbItem && !(flags & Referenced));
+ // In choose mode, can we promote to the class?
+ if (m_mode == ModeEditChooseClass) {
+ const bool enablePromoted = flags & CanPromote;
+ m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enablePromoted);
+ m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(enablePromoted);
+ }
+ // different base?
+ if (dbItem) {
+ const QString baseClass = dbItem->extends();
+ if (baseClass != m_lastSelectedBaseClass) {
+ m_lastSelectedBaseClass = baseClass;
+ emit selectedBaseClassChanged(m_lastSelectedBaseClass);
+ }
+ }
+ }
+
+ QDesignerWidgetDataBaseItemInterface *QDesignerPromotionDialog::databaseItemAt(const QItemSelection &selected, unsigned &flags) const {
+ flags = 0;
+ const QModelIndexList indexes = selected.indexes();
+ if (indexes.empty())
+ return 0;
+
+ bool referenced;
+ QDesignerWidgetDataBaseItemInterface *dbItem = m_model->databaseItemAt(indexes.front(), &referenced);
+
+ if (dbItem) {
+ if (referenced)
+ flags |= Referenced;
+ // In choose mode, can we promote to the class?
+ if (m_mode == ModeEditChooseClass && dbItem && dbItem->isPromoted() && dbItem->extends() == m_promotableWidgetClassName)
+ flags |= CanPromote;
+
+ }
+ return dbItem;
+ }
+
+ void QDesignerPromotionDialog::slotNewPromotedClass(const PromotionParameters &p, bool *ok) {
+ QString errorMessage;
+ *ok = m_promotion->addPromotedClass(p.m_baseClass, p.m_className, p.m_includeFile, &errorMessage);
+ if (*ok) {
+ // update and select
+ slotUpdateFromWidgetDatabase();
+ const QModelIndex newClassIndex = m_model->indexOfClass(p.m_className);
+ if (newClassIndex.isValid()) {
+ m_treeView->selectionModel()->select(newClassIndex, QItemSelectionModel::SelectCurrent|QItemSelectionModel::Rows);
+ }
+ } else {
+ displayError(errorMessage);
+ }
+ }
+
+ void QDesignerPromotionDialog::slotIncludeFileChanged(QDesignerWidgetDataBaseItemInterface *dbItem, const QString &includeFile) {
+ if (includeFile.isEmpty()) {
+ delayedUpdateFromWidgetDatabase();
+ return;
+ }
+
+ if (dbItem->includeFile() == includeFile)
+ return;
+
+ QString errorMessage;
+ if (!m_promotion->setPromotedClassIncludeFile(dbItem->name(), includeFile, &errorMessage)) {
+ displayError(errorMessage);
+ delayedUpdateFromWidgetDatabase();
+ }
+ }
+
+ void QDesignerPromotionDialog::slotClassNameChanged(QDesignerWidgetDataBaseItemInterface *dbItem, const QString &newName) {
+ if (newName.isEmpty()) {
+ delayedUpdateFromWidgetDatabase();
+ return;
+ }
+ const QString oldName = dbItem->name();
+ if (newName == oldName)
+ return;
+
+ QString errorMessage;
+ if (!m_promotion->changePromotedClassName(oldName , newName, &errorMessage)) {
+ displayError(errorMessage);
+ delayedUpdateFromWidgetDatabase();
+ }
+ }
+
+ void QDesignerPromotionDialog::slotTreeViewContextMenu(const QPoint &pos) {
+ unsigned flags;
+ const QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags);
+ if (!dbItem)
+ return;
+
+ QMenu menu;
+ QAction *signalSlotAction = menu.addAction(tr("Change signals/slots..."));
+ connect(signalSlotAction, SIGNAL(triggered()), this, SLOT(slotEditSignalsSlots()));
+
+ menu.exec(m_treeView->viewport()->mapToGlobal(pos));
+ }
+
+ void QDesignerPromotionDialog::slotEditSignalsSlots() {
+ unsigned flags;
+ const QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags);
+ if (!dbItem)
+ return;
+
+ SignalSlotDialog::editPromotedClass(m_core, dbItem->name(), this);
+ }
+
+ void QDesignerPromotionDialog::displayError(const QString &message) {
+ m_core->dialogGui()->message(this, QDesignerDialogGuiInterface::PromotionErrorMessage, QMessageBox::Warning,
+ tr("%1 - Error").arg(windowTitle()), message, QMessageBox::Close);
+ }
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h b/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h
new file mode 100644
index 0000000000..d371df8c61
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_promotiondialog_p.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PROMOTIONEDITORDIALOG_H
+#define PROMOTIONEDITORDIALOG_H
+
+#include <QtGui/QDialog>
+#include <QtGui/QGroupBox>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QDesignerPromotionInterface;
+class QDesignerWidgetDataBaseItemInterface;
+
+class QTreeView;
+class QPushButton;
+class QItemSelection;
+class QDialogButtonBox;
+class QComboBox;
+class QLineEdit;
+class QCheckBox;
+
+namespace qdesigner_internal {
+ struct PromotionParameters;
+ class PromotionModel;
+
+
+ // Panel for adding a new promoted class. Separate class for code cleanliness.
+ class NewPromotedClassPanel : public QGroupBox {
+ Q_OBJECT
+ public:
+ NewPromotedClassPanel(const QStringList &baseClasses,
+ int selectedBaseClass = -1,
+ QWidget *parent = 0);
+
+ signals:
+ void newPromotedClass(const PromotionParameters &, bool *ok);
+
+ public slots:
+ void grabFocus();
+ void chooseBaseClass(const QString &);
+ private slots:
+ void slotNameChanged(const QString &);
+ void slotIncludeFileChanged(const QString &);
+ void slotAdd();
+ void slotReset();
+
+ private:
+ PromotionParameters promotionParameters() const;
+ void enableButtons();
+
+ QComboBox *m_baseClassCombo;
+ QLineEdit *m_classNameEdit;
+ QLineEdit *m_includeFileEdit;
+ QCheckBox *m_globalIncludeCheckBox;
+ QPushButton *m_addButton;
+ };
+
+ // Dialog for editing promoted classes.
+ class QDesignerPromotionDialog : public QDialog {
+ Q_OBJECT
+
+ public:
+ enum Mode { ModeEdit, ModeEditChooseClass };
+
+ QDesignerPromotionDialog(QDesignerFormEditorInterface *core,
+ QWidget *parent = 0,
+ const QString &promotableWidgetClassName = QString(),
+ QString *promoteTo = 0);
+ // Return an alphabetically ordered list of base class names for adding new classes.
+ static const QStringList &baseClassNames(const QDesignerPromotionInterface *promotion);
+
+ signals:
+ void selectedBaseClassChanged(const QString &);
+ private slots:
+ void slotRemove();
+ void slotAcceptPromoteTo();
+ void slotSelectionChanged(const QItemSelection &, const QItemSelection &);
+ void slotNewPromotedClass(const PromotionParameters &, bool *ok);
+
+ void slotIncludeFileChanged(QDesignerWidgetDataBaseItemInterface *, const QString &includeFile);
+ void slotClassNameChanged(QDesignerWidgetDataBaseItemInterface *, const QString &newName);
+ void slotUpdateFromWidgetDatabase();
+ void slotTreeViewContextMenu(const QPoint &);
+ void slotEditSignalsSlots();
+
+ private:
+ QDialogButtonBox *createButtonBox();
+ void delayedUpdateFromWidgetDatabase();
+ // Return item at model index and a combination of flags or 0.
+ enum { Referenced = 1, CanPromote = 2 };
+ QDesignerWidgetDataBaseItemInterface *databaseItemAt(const QItemSelection &, unsigned &flags) const;
+ void displayError(const QString &message);
+
+ const Mode m_mode;
+ const QString m_promotableWidgetClassName;
+ QDesignerFormEditorInterface *m_core;
+ QString *m_promoteTo;
+ QDesignerPromotionInterface *m_promotion;
+ PromotionModel *m_model;
+ QTreeView *m_treeView;
+ QDialogButtonBox *m_buttonBox;
+ QPushButton *m_removeButton;
+ QString m_lastSelectedBaseClass;
+ };
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // PROMOTIONEDITORDIALOG_H
diff --git a/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp b/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp
new file mode 100644
index 0000000000..ff3b50bce6
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_propertycommand.cpp
@@ -0,0 +1,1479 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_propertycommand_p.h"
+#include "qdesigner_utils_p.h"
+#include "dynamicpropertysheet.h"
+#include "qdesigner_propertyeditor_p.h"
+#include "qdesigner_integration_p.h"
+#include "spacer_widget_p.h"
+#include "qdesigner_propertysheet_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerDynamicPropertySheetExtension>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QDesignerObjectInspectorInterface>
+#include <QtDesigner/QDesignerIntegrationInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QSize>
+#include <QtCore/QTextStream>
+#include <QtGui/QWidget>
+#include <QtGui/QApplication>
+#include <QtGui/QAction>
+#include <QtGui/QDialog>
+#include <QtGui/QPushButton>
+#include <QtGui/QLayout>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+enum { debugPropertyCommands = 0 };
+
+// Debug resolve mask of font
+QString fontMask(unsigned m)
+{
+ QString rc;
+ if (m & QFont::FamilyResolved)
+ rc += QLatin1String("Family");
+ if (m & QFont::SizeResolved)
+ rc += QLatin1String("Size ");
+ if (m & QFont::WeightResolved)
+ rc += QLatin1String("Bold ");
+ if (m & QFont::StyleResolved)
+ rc += QLatin1String("Style ");
+ if (m & QFont::UnderlineResolved)
+ rc += QLatin1String("Underline ");
+ if (m & QFont::StrikeOutResolved)
+ rc += QLatin1String("StrikeOut ");
+ if (m & QFont::KerningResolved)
+ rc += QLatin1String("Kerning ");
+ if (m & QFont::StyleStrategyResolved)
+ rc += QLatin1String("StyleStrategy");
+ return rc;
+}
+
+// Debug font
+QString fontString(const QFont &f)
+{
+ QString rc; {
+ const QChar comma = QLatin1Char(',');
+ QTextStream str(&rc);
+ str << QLatin1String("QFont(\"") << f.family() << comma <<
+ f.pointSize();
+ if (f.bold())
+ str << comma << QLatin1String("bold");
+ if (f.italic())
+ str << comma << QLatin1String("italic");
+ if (f.underline())
+ str << comma << QLatin1String("underline");
+ if (f.strikeOut())
+ str << comma << QLatin1String("strikeOut");
+ if (f.kerning())
+ str << comma << QLatin1String("kerning");
+ str << comma << f.styleStrategy() << QLatin1String(" resolve: ")
+ << fontMask(f.resolve()) << QLatin1Char(')');
+ }
+ return rc;
+}
+QSize checkSize(const QSize &size)
+{
+ return size.boundedTo(QSize(0xFFFFFF, 0xFFFFFF));
+}
+
+QSize diffSize(QDesignerFormWindowInterface *fw)
+{
+ const QWidget *container = fw->core()->integration()->containerWindow(fw);
+ if (!container)
+ return QSize();
+
+ const QSize diff = container->size() - fw->size(); // decoration offset of container window
+ return diff;
+}
+
+void checkSizes(QDesignerFormWindowInterface *fw, const QSize &size, QSize *formSize, QSize *containerSize)
+{
+ const QWidget *container = fw->core()->integration()->containerWindow(fw);
+ if (!container)
+ return;
+
+ const QSize diff = diffSize(fw); // decoration offset of container window
+
+ QSize newFormSize = checkSize(size).expandedTo(fw->mainContainer()->minimumSizeHint()); // don't try to resize to smaller size than minimumSizeHint
+ QSize newContainerSize = newFormSize + diff;
+
+ newContainerSize = newContainerSize.expandedTo(container->minimumSizeHint());
+ newContainerSize = newContainerSize.expandedTo(container->minimumSize());
+
+ newFormSize = newContainerSize - diff;
+
+ newContainerSize = checkSize(newContainerSize);
+
+ if (formSize)
+ *formSize = newFormSize;
+ if (containerSize)
+ *containerSize = newContainerSize;
+}
+
+/* SubProperties: When applying a changed property to a multiselection, it sometimes makes
+ * sense to apply only parts (subproperties) of the property.
+ * For example, if someone changes the x-value of a geometry in the property editor
+ * and applies it to a multi-selection, y should not be applied as this would cause all
+ * the widgets to overlap.
+ * The following routines can be used to find out the changed subproperties of a property,
+ * which are represented as a mask, and to apply them while leaving the others intact. */
+
+enum RectSubPropertyMask { SubPropertyX=1, SubPropertyY = 2, SubPropertyWidth = 4, SubPropertyHeight = 8 };
+enum SizePolicySubPropertyMask { SubPropertyHSizePolicy = 1, SubPropertyHStretch = 2, SubPropertyVSizePolicy = 4, SubPropertyVStretch = 8 };
+enum AlignmentSubPropertyMask { SubPropertyHorizontalAlignment = 1, SubPropertyVerticalAlignment = 2 };
+enum StringSubPropertyMask { SubPropertyStringValue = 1, SubPropertyStringComment = 2, SubPropertyStringTranslatable = 4, SubPropertyStringDisambiguation = 8 };
+enum KeySequenceSubPropertyMask { SubPropertyKeySequenceValue = 1, SubPropertyKeySequenceComment = 2, SubPropertyKeySequenceTranslatable = 4, SubPropertyKeySequenceDisambiguation = 8 };
+
+enum CommonSubPropertyMask { SubPropertyAll = 0xFFFFFFFF };
+
+// Set the mask flag in mask if the properties do not match.
+#define COMPARE_SUBPROPERTY(object1, object2, getter, mask, maskFlag) if (object1.getter() != object2.getter()) mask |= maskFlag;
+
+// find changed subproperties of a rectangle
+unsigned compareSubProperties(const QRect & r1, const QRect & r2)
+{
+ unsigned rc = 0;
+ COMPARE_SUBPROPERTY(r1, r2, x, rc, SubPropertyX)
+ COMPARE_SUBPROPERTY(r1, r2, y, rc, SubPropertyY)
+ COMPARE_SUBPROPERTY(r1, r2, width, rc, SubPropertyWidth)
+ COMPARE_SUBPROPERTY(r1, r2, height, rc, SubPropertyHeight)
+ return rc;
+}
+
+// find changed subproperties of a QSize
+unsigned compareSubProperties(const QSize & r1, const QSize & r2)
+{
+ unsigned rc = 0;
+ COMPARE_SUBPROPERTY(r1, r2, width, rc, SubPropertyWidth)
+ COMPARE_SUBPROPERTY(r1, r2, height, rc, SubPropertyHeight)
+ return rc;
+}
+// find changed subproperties of a QSizePolicy
+unsigned compareSubProperties(const QSizePolicy & sp1, const QSizePolicy & sp2)
+{
+ unsigned rc = 0;
+ COMPARE_SUBPROPERTY(sp1, sp2, horizontalPolicy, rc, SubPropertyHSizePolicy)
+ COMPARE_SUBPROPERTY(sp1, sp2, horizontalStretch, rc, SubPropertyHStretch)
+ COMPARE_SUBPROPERTY(sp1, sp2, verticalPolicy, rc, SubPropertyVSizePolicy)
+ COMPARE_SUBPROPERTY(sp1, sp2, verticalStretch, rc, SubPropertyVStretch)
+ return rc;
+}
+// find changed subproperties of qdesigner_internal::PropertySheetStringValue
+unsigned compareSubProperties(const qdesigner_internal::PropertySheetStringValue & str1, const qdesigner_internal::PropertySheetStringValue & str2)
+{
+ unsigned rc = 0;
+ COMPARE_SUBPROPERTY(str1, str2, value, rc, SubPropertyStringValue)
+ COMPARE_SUBPROPERTY(str1, str2, comment, rc, SubPropertyStringComment)
+ COMPARE_SUBPROPERTY(str1, str2, translatable, rc, SubPropertyStringTranslatable)
+ COMPARE_SUBPROPERTY(str1, str2, disambiguation, rc, SubPropertyStringDisambiguation)
+ return rc;
+}
+// find changed subproperties of qdesigner_internal::PropertySheetKeySequenceValue
+unsigned compareSubProperties(const qdesigner_internal::PropertySheetKeySequenceValue & str1, const qdesigner_internal::PropertySheetKeySequenceValue & str2)
+{
+ unsigned rc = 0;
+ COMPARE_SUBPROPERTY(str1, str2, value, rc, SubPropertyKeySequenceValue)
+ COMPARE_SUBPROPERTY(str1, str2, comment, rc, SubPropertyKeySequenceComment)
+ COMPARE_SUBPROPERTY(str1, str2, translatable, rc, SubPropertyKeySequenceTranslatable)
+ COMPARE_SUBPROPERTY(str1, str2, disambiguation, rc, SubPropertyKeySequenceDisambiguation)
+ return rc;
+}
+
+// Compare font-subproperties taking the [undocumented]
+// resolve flag into account
+template <class Property>
+void compareFontSubProperty(const QFont & f1,
+ const QFont & f2,
+ Property (QFont::*getter) () const,
+ unsigned maskBit,
+ unsigned &mask)
+{
+ const bool f1Changed = f1.resolve() & maskBit;
+ const bool f2Changed = f2.resolve() & maskBit;
+ // Role has been set/reset in editor
+ if (f1Changed != f2Changed) {
+ mask |= maskBit;
+ } else {
+ // Was modified in both palettes: Compare values.
+ if (f1Changed && f2Changed && (f1.*getter)() != (f2.*getter)())
+ mask |= maskBit;
+ }
+}
+// find changed subproperties of a QFont
+unsigned compareSubProperties(const QFont & f1, const QFont & f2)
+{
+ unsigned rc = 0;
+ compareFontSubProperty(f1, f2, &QFont::family, QFont::FamilyResolved, rc);
+ compareFontSubProperty(f1, f2, &QFont::pointSize, QFont::SizeResolved, rc);
+ compareFontSubProperty(f1, f2, &QFont::bold, QFont::WeightResolved, rc);
+ compareFontSubProperty(f1, f2, &QFont::italic, QFont::StyleResolved, rc);
+ compareFontSubProperty(f1, f2, &QFont::underline, QFont::UnderlineResolved, rc);
+ compareFontSubProperty(f1, f2, &QFont::strikeOut, QFont::StrikeOutResolved, rc);
+ compareFontSubProperty(f1, f2, &QFont::kerning, QFont::KerningResolved, rc);
+ compareFontSubProperty(f1, f2, &QFont::styleStrategy, QFont::StyleStrategyResolved, rc);
+ if (debugPropertyCommands)
+ qDebug() << "compareSubProperties " << fontString(f1) << fontString(f2) << "\n\treturns " << fontMask(rc);
+ return rc;
+}
+
+// Compare colors of a role
+bool roleColorChanged(const QPalette & p1, const QPalette & p2, QPalette::ColorRole role)
+{
+ for (int group = QPalette::Active; group < QPalette::NColorGroups; group++) {
+ const QPalette::ColorGroup pgroup = static_cast<QPalette::ColorGroup>(group);
+ if (p1.color(pgroup, role) != p2.color(pgroup, role))
+ return true;
+ }
+ return false;
+}
+// find changed subproperties of a QPalette taking the [undocumented] resolve flags into account
+unsigned compareSubProperties(const QPalette & p1, const QPalette & p2)
+{
+ unsigned rc = 0;
+ unsigned maskBit = 1u;
+ // generate a mask for each role
+ const unsigned p1Changed = p1.resolve();
+ const unsigned p2Changed = p2.resolve();
+ for (int role = QPalette::WindowText; role < QPalette::NColorRoles; role++, maskBit <<= 1u) {
+ const bool p1RoleChanged = p1Changed & maskBit;
+ const bool p2RoleChanged = p2Changed & maskBit;
+ // Role has been set/reset in editor
+ if (p1RoleChanged != p2RoleChanged) {
+ rc |= maskBit;
+ } else {
+ // Was modified in both palettes: Compare values.
+ if (p1RoleChanged && p2RoleChanged && roleColorChanged(p1, p2, static_cast<QPalette::ColorRole>(role)))
+ rc |= maskBit;
+ }
+ }
+ return rc;
+}
+
+// find changed subproperties of a QAlignment which is a flag combination of vertical and horizontal
+
+unsigned compareSubProperties(Qt::Alignment a1, Qt::Alignment a2)
+{
+ unsigned rc = 0;
+ if ((a1 & Qt::AlignHorizontal_Mask) != (a2 & Qt::AlignHorizontal_Mask))
+ rc |= SubPropertyHorizontalAlignment;
+ if ((a1 & Qt::AlignVertical_Mask) != (a2 & Qt::AlignVertical_Mask))
+ rc |= SubPropertyVerticalAlignment;
+ return rc;
+}
+
+Qt::Alignment variantToAlignment(const QVariant & q)
+{
+ return Qt::Alignment(qdesigner_internal::Utils::valueOf(q));
+}
+// find changed subproperties of a variant
+unsigned compareSubProperties(const QVariant & q1, const QVariant & q2, qdesigner_internal::SpecialProperty specialProperty)
+{
+ switch (q1.type()) {
+ case QVariant::Rect:
+ return compareSubProperties(q1.toRect(), q2.toRect());
+ case QVariant::Size:
+ return compareSubProperties(q1.toSize(), q2.toSize());
+ case QVariant::SizePolicy:
+ return compareSubProperties(qvariant_cast<QSizePolicy>(q1), qvariant_cast<QSizePolicy>(q2));
+ case QVariant::Font:
+ return compareSubProperties(qvariant_cast<QFont>(q1), qvariant_cast<QFont>(q2));
+ case QVariant::Palette:
+ return compareSubProperties(qvariant_cast<QPalette>(q1), qvariant_cast<QPalette>(q2));
+ default:
+ if (q1.userType() == qMetaTypeId<qdesigner_internal::PropertySheetIconValue>())
+ return qvariant_cast<qdesigner_internal::PropertySheetIconValue>(q1).compare(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(q2));
+ else if (q1.userType() == qMetaTypeId<qdesigner_internal::PropertySheetStringValue>())
+ return compareSubProperties(qvariant_cast<qdesigner_internal::PropertySheetStringValue>(q1), qvariant_cast<qdesigner_internal::PropertySheetStringValue>(q2));
+ else if (q1.userType() == qMetaTypeId<qdesigner_internal::PropertySheetKeySequenceValue>())
+ return compareSubProperties(qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(q1), qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(q2));
+ // Enumerations, flags
+ switch (specialProperty) {
+ case qdesigner_internal::SP_Alignment:
+ return compareSubProperties(variantToAlignment(q1), variantToAlignment(q2));
+ default:
+ break;
+ }
+ break;
+ }
+ return SubPropertyAll;
+}
+
+// Apply the sub property if mask flag is set in mask
+#define SET_SUBPROPERTY(rc, newValue, getter, setter, mask, maskFlag) if (mask & maskFlag) rc.setter(newValue.getter());
+
+// apply changed subproperties to a rectangle
+QRect applyRectSubProperty(const QRect &oldValue, const QRect &newValue, unsigned mask)
+{
+ QRect rc = oldValue;
+ SET_SUBPROPERTY(rc, newValue, x, moveLeft, mask, SubPropertyX)
+ SET_SUBPROPERTY(rc, newValue, y, moveTop, mask, SubPropertyY)
+ SET_SUBPROPERTY(rc, newValue, width, setWidth, mask, SubPropertyWidth)
+ SET_SUBPROPERTY(rc, newValue, height, setHeight, mask, SubPropertyHeight)
+ return rc;
+}
+
+
+// apply changed subproperties to a rectangle QSize
+QSize applySizeSubProperty(const QSize &oldValue, const QSize &newValue, unsigned mask)
+{
+ QSize rc = oldValue;
+ SET_SUBPROPERTY(rc, newValue, width, setWidth, mask, SubPropertyWidth)
+ SET_SUBPROPERTY(rc, newValue, height, setHeight, mask, SubPropertyHeight)
+ return rc;
+}
+
+
+// apply changed subproperties to a SizePolicy
+QSizePolicy applySizePolicySubProperty(const QSizePolicy &oldValue, const QSizePolicy &newValue, unsigned mask)
+{
+ QSizePolicy rc = oldValue;
+ SET_SUBPROPERTY(rc, newValue, horizontalPolicy, setHorizontalPolicy, mask, SubPropertyHSizePolicy)
+ SET_SUBPROPERTY(rc, newValue, horizontalStretch, setHorizontalStretch, mask, SubPropertyHStretch)
+ SET_SUBPROPERTY(rc, newValue, verticalPolicy, setVerticalPolicy, mask, SubPropertyVSizePolicy)
+ SET_SUBPROPERTY(rc, newValue, verticalStretch, setVerticalStretch, mask, SubPropertyVStretch)
+ return rc;
+}
+
+// apply changed subproperties to a qdesigner_internal::PropertySheetStringValue
+qdesigner_internal::PropertySheetStringValue applyStringSubProperty(const qdesigner_internal::PropertySheetStringValue &oldValue,
+ const qdesigner_internal::PropertySheetStringValue &newValue, unsigned mask)
+{
+ qdesigner_internal::PropertySheetStringValue rc = oldValue;
+ SET_SUBPROPERTY(rc, newValue, value, setValue, mask, SubPropertyStringValue)
+ SET_SUBPROPERTY(rc, newValue, comment, setComment, mask, SubPropertyStringComment)
+ SET_SUBPROPERTY(rc, newValue, translatable, setTranslatable, mask, SubPropertyStringTranslatable)
+ SET_SUBPROPERTY(rc, newValue, disambiguation, setDisambiguation, mask, SubPropertyStringDisambiguation)
+ return rc;
+}
+
+// apply changed subproperties to a qdesigner_internal::PropertySheetKeySequenceValue
+qdesigner_internal::PropertySheetKeySequenceValue applyKeySequenceSubProperty(const qdesigner_internal::PropertySheetKeySequenceValue &oldValue,
+ const qdesigner_internal::PropertySheetKeySequenceValue &newValue, unsigned mask)
+{
+ qdesigner_internal::PropertySheetKeySequenceValue rc = oldValue;
+ SET_SUBPROPERTY(rc, newValue, value, setValue, mask, SubPropertyKeySequenceValue)
+ SET_SUBPROPERTY(rc, newValue, comment, setComment, mask, SubPropertyKeySequenceComment)
+ SET_SUBPROPERTY(rc, newValue, translatable, setTranslatable, mask, SubPropertyKeySequenceTranslatable)
+ SET_SUBPROPERTY(rc, newValue, disambiguation, setDisambiguation, mask, SubPropertyKeySequenceDisambiguation)
+ return rc;
+}
+
+// Apply the font-subproperties keeping the [undocumented]
+// resolve flag in sync (note that PropertySetterType might be something like const T&).
+template <class PropertyReturnType, class PropertySetterType>
+inline void setFontSubProperty(unsigned mask,
+ const QFont &newValue,
+ unsigned maskBit,
+ PropertyReturnType (QFont::*getter) () const,
+ void (QFont::*setter) (PropertySetterType),
+ QFont &value)
+{
+ if (mask & maskBit) {
+ (value.*setter)((newValue.*getter)());
+ // Set the resolve bit from NewValue in return value
+ uint r = value.resolve();
+ const bool origFlag = newValue.resolve() & maskBit;
+ if (origFlag)
+ r |= maskBit;
+ else
+ r &= ~maskBit;
+ value.resolve(r);
+ if (debugPropertyCommands)
+ qDebug() << "setFontSubProperty " << fontMask(maskBit) << " resolve=" << origFlag;
+ }
+}
+// apply changed subproperties to a QFont
+QFont applyFontSubProperty(const QFont &oldValue, const QFont &newValue, unsigned mask)
+{
+ QFont rc = oldValue;
+ setFontSubProperty(mask, newValue, QFont::FamilyResolved, &QFont::family, &QFont::setFamily, rc);
+ setFontSubProperty(mask, newValue, QFont::SizeResolved, &QFont::pointSize, &QFont::setPointSize, rc);
+ setFontSubProperty(mask, newValue, QFont::WeightResolved, &QFont::bold, &QFont::setBold, rc);
+ setFontSubProperty(mask, newValue, QFont::StyleResolved, &QFont::italic, &QFont::setItalic, rc);
+ setFontSubProperty(mask, newValue, QFont::UnderlineResolved, &QFont::underline, &QFont::setUnderline, rc);
+ setFontSubProperty(mask, newValue, QFont::StrikeOutResolved, &QFont::strikeOut, &QFont::setStrikeOut, rc);
+ setFontSubProperty(mask, newValue, QFont::KerningResolved, &QFont::kerning, &QFont::setKerning, rc);
+ setFontSubProperty(mask, newValue, QFont::StyleStrategyResolved, &QFont::styleStrategy, &QFont::setStyleStrategy, rc);
+ if (debugPropertyCommands)
+ qDebug() << "applyFontSubProperty old " << fontMask(oldValue.resolve()) << " new " << fontMask(newValue.resolve()) << " return: " << fontMask(rc.resolve());
+ return rc;
+}
+
+// apply changed subproperties to a QPalette
+QPalette applyPaletteSubProperty(const QPalette &oldValue, const QPalette &newValue, unsigned mask)
+{
+ QPalette rc = oldValue;
+ // apply a mask for each role
+ unsigned maskBit = 1u;
+ for (int role = QPalette::WindowText; role < QPalette::NColorRoles; role++, maskBit <<= 1u) {
+ if (mask & maskBit) {
+ for (int group = QPalette::Active; group < QPalette::NColorGroups; group++) {
+ const QPalette::ColorGroup pgroup = static_cast<QPalette::ColorGroup>(group);
+ const QPalette::ColorRole prole = static_cast<QPalette::ColorRole>(role);
+ rc.setColor(pgroup, prole, newValue.color(pgroup, prole));
+ }
+ // Set the resolve bit from NewValue in return value
+ uint r = rc.resolve();
+ const bool origFlag = newValue.resolve() & maskBit;
+ if (origFlag)
+ r |= maskBit;
+ else
+ r &= ~maskBit;
+ rc.resolve(r);
+ }
+ }
+ return rc;
+}
+
+// apply changed subproperties to a QAlignment which is a flag combination of vertical and horizontal
+Qt::Alignment applyAlignmentSubProperty(Qt::Alignment oldValue, Qt::Alignment newValue, unsigned mask)
+{
+ // easy: both changed.
+ if (mask == (SubPropertyHorizontalAlignment|SubPropertyVerticalAlignment))
+ return newValue;
+ // Change subprop
+ const Qt::Alignment changeMask = (mask & SubPropertyHorizontalAlignment) ? Qt::AlignHorizontal_Mask : Qt::AlignVertical_Mask;
+ const Qt::Alignment takeOverMask = (mask & SubPropertyHorizontalAlignment) ? Qt::AlignVertical_Mask : Qt::AlignHorizontal_Mask;
+ return (oldValue & takeOverMask) | (newValue & changeMask);
+}
+
+}
+
+namespace qdesigner_internal {
+
+// apply changed subproperties to a variant
+PropertyHelper::Value applySubProperty(const QVariant &oldValue, const QVariant &newValue, qdesigner_internal::SpecialProperty specialProperty, unsigned mask, bool changed)
+{
+ if (mask == SubPropertyAll)
+ return PropertyHelper::Value(newValue, changed);
+
+ switch (oldValue.type()) {
+ case QVariant::Rect:
+ return PropertyHelper::Value(applyRectSubProperty(oldValue.toRect(), newValue.toRect(), mask), changed);
+ case QVariant::Size:
+ return PropertyHelper::Value(applySizeSubProperty(oldValue.toSize(), newValue.toSize(), mask), changed);
+ case QVariant::SizePolicy:
+ return PropertyHelper::Value(qVariantFromValue(applySizePolicySubProperty(qvariant_cast<QSizePolicy>(oldValue), qvariant_cast<QSizePolicy>(newValue), mask)), changed);
+ case QVariant::Font: {
+ // Changed flag in case of font and palette depends on resolve mask only, not on the passed "changed" value.
+
+ // The first case: the user changed bold subproperty and then pressed reset button for this subproperty (not for
+ // the whole font property). We instantiate SetPropertyCommand passing changed=true. But in this case no
+ // subproperty is changed and the whole property should be marked an unchanged.
+
+ // The second case: there are 2 pushbuttons, for 1st the user set bold and italic subproperties,
+ // for the 2nd he set bold only. He does multiselection so that the current widget is the 2nd one.
+ // He press reset next to bold subproperty. In result the 2nd widget should have the whole
+ // font property marked as unchanged and the 1st widget should have the font property
+ // marked as changed and only italic subproperty should be marked as changed (the bold should be reset).
+
+ // The third case: there are 2 pushbuttons, for 1st the user set bold and italic subproperties,
+ // for the 2nd he set bold only. He does multiselection so that the current widget is the 2nd one.
+ // He press reset button for the whole font property. In result whole font properties for both
+ // widgets should be marked as unchanged.
+ QFont font = applyFontSubProperty(qvariant_cast<QFont>(oldValue), qvariant_cast<QFont>(newValue), mask);
+ return PropertyHelper::Value(qVariantFromValue(font), font.resolve());
+ }
+ case QVariant::Palette: {
+ QPalette palette = applyPaletteSubProperty(qvariant_cast<QPalette>(oldValue), qvariant_cast<QPalette>(newValue), mask);
+ return PropertyHelper::Value(qVariantFromValue(palette), palette.resolve());
+ }
+ default:
+ if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetIconValue>()) {
+ PropertySheetIconValue icon = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(oldValue);
+ icon.assign(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(newValue), mask);
+ return PropertyHelper::Value(qVariantFromValue(icon), icon.mask());
+ } else if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetStringValue>()) {
+ qdesigner_internal::PropertySheetStringValue str = applyStringSubProperty(
+ qvariant_cast<qdesigner_internal::PropertySheetStringValue>(oldValue),
+ qvariant_cast<qdesigner_internal::PropertySheetStringValue>(newValue), mask);
+ return PropertyHelper::Value(qVariantFromValue(str), changed);
+ } else if (oldValue.userType() == qMetaTypeId<qdesigner_internal::PropertySheetKeySequenceValue>()) {
+ qdesigner_internal::PropertySheetKeySequenceValue key = applyKeySequenceSubProperty(
+ qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(oldValue),
+ qvariant_cast<qdesigner_internal::PropertySheetKeySequenceValue>(newValue), mask);
+ return PropertyHelper::Value(qVariantFromValue(key), changed);
+ }
+ // Enumerations, flags
+ switch (specialProperty) {
+ case qdesigner_internal::SP_Alignment: {
+ qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(oldValue);
+ f.value = applyAlignmentSubProperty(variantToAlignment(oldValue), variantToAlignment(newValue), mask);
+ QVariant v;
+ qVariantSetValue(v, f);
+ return PropertyHelper::Value(v, changed);
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ return PropertyHelper::Value(newValue, changed);
+
+}
+// figure out special property
+enum SpecialProperty getSpecialProperty(const QString& propertyName)
+{
+ if (propertyName == QLatin1String("objectName"))
+ return SP_ObjectName;
+ if (propertyName == QLatin1String("layoutName"))
+ return SP_LayoutName;
+ if (propertyName == QLatin1String("spacerName"))
+ return SP_SpacerName;
+ if (propertyName == QLatin1String("icon"))
+ return SP_Icon;
+ if (propertyName == QLatin1String("currentTabName"))
+ return SP_CurrentTabName;
+ if (propertyName == QLatin1String("currentItemName"))
+ return SP_CurrentItemName;
+ if (propertyName == QLatin1String("currentPageName"))
+ return SP_CurrentPageName;
+ if (propertyName == QLatin1String("geometry"))
+ return SP_Geometry;
+ if (propertyName == QLatin1String("windowTitle"))
+ return SP_WindowTitle;
+ if (propertyName == QLatin1String("minimumSize"))
+ return SP_MinimumSize;
+ if (propertyName == QLatin1String("maximumSize"))
+ return SP_MaximumSize;
+ if (propertyName == QLatin1String("alignment"))
+ return SP_Alignment;
+ if (propertyName == QLatin1String("autoDefault"))
+ return SP_AutoDefault;
+ if (propertyName == QLatin1String("shortcut"))
+ return SP_Shortcut;
+ if (propertyName == QLatin1String("orientation"))
+ return SP_Orientation;
+ return SP_None;
+}
+
+
+PropertyHelper::PropertyHelper(QObject* object,
+ SpecialProperty specialProperty,
+ QDesignerPropertySheetExtension *sheet,
+ int index) :
+ m_specialProperty(specialProperty),
+ m_object(object),
+ m_objectType(OT_Object),
+ m_propertySheet(sheet), m_index(index),
+ m_oldValue(m_propertySheet->property(m_index), m_propertySheet->isChanged(m_index))
+{
+ if (object->isWidgetType()) {
+ m_parentWidget = (qobject_cast<QWidget*>(object))->parentWidget();
+ m_objectType = OT_Widget;
+ } else {
+ if (const QAction *action = qobject_cast<const QAction *>(m_object))
+ m_objectType = action->associatedWidgets().empty() ? OT_FreeAction : OT_AssociatedAction;
+ }
+
+ if(debugPropertyCommands)
+ qDebug() << "PropertyHelper on " << m_object->objectName() << " index= " << m_index << " type = " << m_objectType;
+}
+
+QDesignerIntegration *PropertyHelper::integration(QDesignerFormWindowInterface *fw) const
+{
+ return qobject_cast<QDesignerIntegration *>(fw->core()->integration());
+}
+
+// Set widget value, apply corrections and checks in case of main window.
+void PropertyHelper::checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWidget* w,
+ SpecialProperty specialProperty, QVariant &value)
+{
+
+ bool isMainContainer = false;
+ if (QDesignerFormWindowCursorInterface *cursor = fw->cursor()) {
+ if (cursor->isWidgetSelected(w)) {
+ if (cursor->isWidgetSelected(fw->mainContainer())) {
+ isMainContainer = true;
+ }
+ }
+ }
+ if (!isMainContainer)
+ return;
+
+ QWidget *container = fw->core()->integration()->containerWindow(fw);
+ if (!container)
+ return;
+
+
+ switch (specialProperty) {
+ case SP_MinimumSize: {
+ const QSize size = checkSize(value.toSize());
+ qVariantSetValue(value, size);
+ }
+
+ break;
+ case SP_MaximumSize: {
+ QSize fs, cs;
+ checkSizes(fw, value.toSize(), &fs, &cs);
+ container->setMaximumSize(cs);
+ fw->mainContainer()->setMaximumSize(fs);
+ qVariantSetValue(value, fs);
+
+ }
+ break;
+ case SP_Geometry: {
+ QRect r = value.toRect();
+ QSize fs, cs;
+ checkSizes(fw, r.size(), &fs, &cs);
+ container->resize(cs);
+ r.setSize(fs);
+ qVariantSetValue(value, r);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+unsigned PropertyHelper::updateMask() const
+{
+ unsigned rc = 0;
+ switch (m_specialProperty) {
+ case SP_ObjectName:
+ case SP_LayoutName:
+ case SP_SpacerName:
+ case SP_CurrentTabName:
+ case SP_CurrentItemName:
+ case SP_CurrentPageName:
+ if (m_objectType != OT_FreeAction)
+ rc |= UpdateObjectInspector;
+ break;
+ case SP_Icon:
+ if (m_objectType == OT_AssociatedAction)
+ rc |= UpdateObjectInspector;
+ break;
+ case SP_Orientation: // for updating splitter icon
+ rc |= UpdateObjectInspector;
+ break;
+ default:
+ break;
+
+ }
+ return rc;
+}
+
+
+bool PropertyHelper::canMerge(const PropertyHelper &other) const
+{
+ return m_object == other.m_object && m_index == other.m_index;
+}
+
+void PropertyHelper::triggerActionChanged(QAction *a)
+{
+ a->setData(QVariant(true)); // this triggers signal "changed" in QAction
+ a->setData(QVariant(false));
+}
+
+// Update the object to reflect the changes
+void PropertyHelper::updateObject(QDesignerFormWindowInterface *fw, const QVariant &oldValue, const QVariant &newValue)
+{
+ if(debugPropertyCommands){
+ qDebug() << "PropertyHelper::updateObject(" << m_object->objectName() << ") " << oldValue << " -> " << newValue;
+ }
+ switch (m_objectType) {
+ case OT_Widget: {
+ switch (m_specialProperty) {
+ case SP_ObjectName: {
+ const QString oldName = qVariantValue<PropertySheetStringValue>(oldValue).value();
+ const QString newName = qVariantValue<PropertySheetStringValue>(newValue).value();
+ QDesignerFormWindowCommand::updateBuddies(fw, oldName, newName);
+ }
+ break;
+ default:
+ break;
+ }
+ } break;
+ case OT_AssociatedAction:
+ case OT_FreeAction:
+ // SP_Shortcut is a fake property, so, QAction::changed does not trigger.
+ if (m_specialProperty == SP_ObjectName || m_specialProperty == SP_Shortcut)
+ triggerActionChanged(qobject_cast<QAction *>(m_object));
+ break;
+ default:
+ break;
+ }
+
+ switch (m_specialProperty) {
+ case SP_ObjectName:
+ case SP_LayoutName:
+ case SP_SpacerName:
+ if (QDesignerIntegration *integr = integration(fw)) {
+ const QString oldName = qVariantValue<PropertySheetStringValue>(oldValue).value();
+ const QString newName = qVariantValue<PropertySheetStringValue>(newValue).value();
+ integr->emitObjectNameChanged(fw, m_object, newName, oldName);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void PropertyHelper::ensureUniqueObjectName(QDesignerFormWindowInterface *fw, QObject *object) const
+{
+ switch (m_specialProperty) {
+ case SP_SpacerName:
+ if (object->isWidgetType()) {
+ if (Spacer *sp = qobject_cast<Spacer *>(object)) {
+ fw->ensureUniqueObjectName(sp);
+ return;
+ }
+ }
+ fw->ensureUniqueObjectName(object);
+ break;
+ case SP_LayoutName: // Layout name is invoked on the parent widget.
+ if (object->isWidgetType()) {
+ const QWidget * w = qobject_cast<const QWidget *>(object);
+ if (QLayout *wlayout = w->layout()) {
+ fw->ensureUniqueObjectName(wlayout);
+ return;
+ }
+ }
+ fw->ensureUniqueObjectName(object);
+ break;
+ case SP_ObjectName:
+ fw->ensureUniqueObjectName(object);
+ break;
+ default:
+ break;
+ }
+}
+
+PropertyHelper::Value PropertyHelper::setValue(QDesignerFormWindowInterface *fw, const QVariant &value, bool changed, unsigned subPropertyMask)
+{
+ // Set new whole value
+ if (subPropertyMask == SubPropertyAll)
+ return applyValue(fw, m_oldValue.first, Value(value, changed));
+
+ // apply subproperties
+ const PropertyHelper::Value maskedNewValue = applySubProperty(m_oldValue.first, value, m_specialProperty, subPropertyMask, changed);
+ return applyValue(fw, m_oldValue.first, maskedNewValue);
+}
+
+// Apply the value and update. Returns corrected value
+PropertyHelper::Value PropertyHelper::applyValue(QDesignerFormWindowInterface *fw, const QVariant &oldValue, Value newValue)
+{
+ if(debugPropertyCommands){
+ qDebug() << "PropertyHelper::applyValue(" << m_object << ") " << oldValue << " -> " << newValue.first << " changed=" << newValue.second;
+ }
+
+ if (m_objectType == OT_Widget) {
+ checkApplyWidgetValue(fw, qobject_cast<QWidget *>(m_object), m_specialProperty, newValue.first);
+ }
+
+ m_propertySheet->setProperty(m_index, newValue.first);
+ m_propertySheet->setChanged(m_index, newValue.second);
+
+ switch (m_specialProperty) {
+ case SP_LayoutName:
+ case SP_ObjectName:
+ case SP_SpacerName:
+ ensureUniqueObjectName(fw, m_object);
+ newValue.first = m_propertySheet->property(m_index);
+ break;
+ default:
+ break;
+ }
+
+ updateObject(fw, oldValue, newValue.first);
+ return newValue;
+}
+
+PropertyHelper::Value PropertyHelper::restoreOldValue(QDesignerFormWindowInterface *fw)
+{
+ return applyValue(fw, m_propertySheet->property(m_index), m_oldValue);
+}
+
+// find the default value in widget DB in case PropertySheet::reset fails
+QVariant PropertyHelper::findDefaultValue(QDesignerFormWindowInterface *fw) const
+{
+ if (m_specialProperty == SP_AutoDefault && qobject_cast<const QPushButton*>(m_object)) {
+ // AutoDefault defaults to true on dialogs
+ const bool isDialog = qobject_cast<const QDialog *>(fw->mainContainer());
+ return QVariant(isDialog);
+ }
+
+ const int item_idx = fw->core()->widgetDataBase()->indexOfObject(m_object);
+ if (item_idx == -1)
+ return m_oldValue.first; // We simply don't know the value in this case
+
+ const QDesignerWidgetDataBaseItemInterface *item = fw->core()->widgetDataBase()->item(item_idx);
+ const QList<QVariant> default_prop_values = item->defaultPropertyValues();
+ if (m_index < default_prop_values.size())
+ return default_prop_values.at(m_index);
+
+ if (m_oldValue.first.type() == QVariant::Color)
+ return QColor();
+
+ return m_oldValue.first; // Again, we just don't know
+}
+
+PropertyHelper::Value PropertyHelper::restoreDefaultValue(QDesignerFormWindowInterface *fw)
+{
+
+ Value defaultValue = qMakePair(QVariant(), false);
+ const QVariant currentValue = m_propertySheet->property(m_index);
+ // try to reset sheet, else try to find default
+ if (m_propertySheet->reset(m_index)) {
+ defaultValue.first = m_propertySheet->property(m_index);
+ } else {
+ defaultValue.first = findDefaultValue(fw);
+ m_propertySheet->setProperty(m_index, defaultValue.first);
+ }
+
+ m_propertySheet->setChanged(m_index, defaultValue.second);
+
+ if (m_objectType == OT_Widget) {
+ checkApplyWidgetValue(fw, qobject_cast<QWidget *>(m_object), m_specialProperty, defaultValue.first);
+ }
+
+ switch (m_specialProperty) {
+ case SP_LayoutName:
+ case SP_ObjectName:
+ case SP_SpacerName:
+ ensureUniqueObjectName(fw, m_object);
+ defaultValue.first = m_propertySheet->property(m_index);
+ break;
+ default:
+ break;
+ }
+
+ updateObject(fw, currentValue, defaultValue.first);
+ return defaultValue;
+}
+
+// ---- PropertyListCommand::PropertyDescription(
+
+
+PropertyListCommand::PropertyDescription::PropertyDescription(const QString &propertyName,
+ QDesignerPropertySheetExtension *propertySheet,
+ int index) :
+ m_propertyName(propertyName),
+ m_propertyGroup(propertySheet->propertyGroup(index)),
+ m_propertyType(propertySheet->property(index).type()),
+ m_specialProperty(getSpecialProperty(propertyName))
+{
+}
+
+PropertyListCommand::PropertyDescription::PropertyDescription() :
+ m_propertyType(QVariant::Invalid),
+ m_specialProperty(SP_None)
+{
+}
+
+void PropertyListCommand::PropertyDescription::debug() const
+{
+ qDebug() << m_propertyName << m_propertyGroup << m_propertyType << m_specialProperty;
+}
+
+bool PropertyListCommand::PropertyDescription::equals(const PropertyDescription &p) const
+{
+ return m_propertyType == p.m_propertyType && m_specialProperty == p.m_specialProperty &&
+ m_propertyName == p.m_propertyName && m_propertyGroup == p.m_propertyGroup;
+}
+
+
+// ---- PropertyListCommand
+PropertyListCommand::PropertyListCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QString(), formWindow)
+{
+}
+
+const QString PropertyListCommand::propertyName() const
+{
+ return m_propertyDescription.m_propertyName;
+}
+
+SpecialProperty PropertyListCommand::specialProperty() const
+{
+ return m_propertyDescription.m_specialProperty;
+}
+
+// add an object
+bool PropertyListCommand::add(QObject *object, const QString &propertyName)
+{
+ QDesignerPropertySheetExtension* sheet = propertySheet(object);
+ Q_ASSERT(sheet);
+
+ const int index = sheet->indexOf(propertyName);
+ if (index == -1)
+ return false;
+
+ if (QDesignerPropertySheet *exSheet = qobject_cast<QDesignerPropertySheet*>(core()->extensionManager()->extension(object, Q_TYPEID(QDesignerPropertySheetExtension))))
+ if (!exSheet->isEnabled(index))
+ return false;
+
+ const PropertyDescription description(propertyName, sheet, index);
+
+ if (m_propertyHelperList.empty()) {
+ // first entry
+ m_propertyDescription = description;
+ } else {
+ // checks: mismatch or only one object in case of name
+ const bool match = m_propertyDescription.equals(description);
+ if (!match || m_propertyDescription.m_specialProperty == SP_ObjectName)
+ return false;
+ }
+ m_propertyHelperList.push_back(PropertyHelper(object, m_propertyDescription.m_specialProperty, sheet, index));
+ return true;
+}
+
+
+// Init from a list and make sure referenceObject is added first to obtain the right property group
+bool PropertyListCommand::initList(const ObjectList &list, const QString &apropertyName, QObject *referenceObject)
+{
+ propertyHelperList().clear();
+
+ // Ensure the referenceObject (property editor) is first, so the right property group is chosen.
+ if (referenceObject) {
+ if (!add(referenceObject, apropertyName))
+ return false;
+ }
+ foreach (QObject *o, list) {
+ if (o != referenceObject)
+ add(o, apropertyName);
+ }
+
+ return !propertyHelperList().empty();
+}
+
+
+QObject* PropertyListCommand::object(int index) const
+{
+ Q_ASSERT(index < m_propertyHelperList.size());
+ return m_propertyHelperList[index].object();
+}
+
+QVariant PropertyListCommand::oldValue(int index) const
+{
+ Q_ASSERT(index < m_propertyHelperList.size());
+ return m_propertyHelperList[index].oldValue();
+}
+
+void PropertyListCommand::setOldValue(const QVariant &oldValue, int index)
+{
+ Q_ASSERT(index < m_propertyHelperList.size());
+ m_propertyHelperList[index].setOldValue(oldValue);
+}
+// ----- SetValueFunction: Set a new value when applied to a PropertyHelper.
+class SetValueFunction {
+public:
+ SetValueFunction(QDesignerFormWindowInterface *formWindow, const PropertyHelper::Value &newValue, unsigned subPropertyMask);
+
+ PropertyHelper::Value operator()(PropertyHelper&);
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+ const PropertyHelper::Value m_newValue;
+ const unsigned m_subPropertyMask;
+};
+
+
+SetValueFunction::SetValueFunction(QDesignerFormWindowInterface *formWindow, const PropertyHelper::Value &newValue, unsigned subPropertyMask) :
+ m_formWindow(formWindow),
+ m_newValue(newValue),
+ m_subPropertyMask(subPropertyMask)
+{
+}
+
+PropertyHelper::Value SetValueFunction::operator()(PropertyHelper &ph) {
+ return ph.setValue(m_formWindow, m_newValue.first, m_newValue.second, m_subPropertyMask);
+}
+
+// ----- UndoSetValueFunction: Restore old value when applied to a PropertyHelper.
+class UndoSetValueFunction {
+public:
+ UndoSetValueFunction(QDesignerFormWindowInterface *formWindow) : m_formWindow(formWindow) {}
+ PropertyHelper::Value operator()(PropertyHelper& ph) { return ph.restoreOldValue(m_formWindow); }
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+};
+
+// ----- RestoreDefaultFunction: Restore default value when applied to a PropertyHelper.
+class RestoreDefaultFunction {
+public:
+ RestoreDefaultFunction(QDesignerFormWindowInterface *formWindow) : m_formWindow(formWindow) {}
+ PropertyHelper::Value operator()(PropertyHelper& ph) { return ph.restoreDefaultValue(m_formWindow); }
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+};
+
+// ----- changePropertyList: Iterates over a sequence of PropertyHelpers and
+// applies a function to them.
+// The function returns the corrected value which is then set in the property editor.
+// Returns a combination of update flags.
+template <class PropertyListIterator, class Function>
+ unsigned changePropertyList(QDesignerFormEditorInterface *core,
+ const QString &propertyName,
+ PropertyListIterator begin,
+ PropertyListIterator end,
+ Function function)
+{
+ unsigned updateMask = 0;
+ QDesignerPropertyEditorInterface *propertyEditor = core->propertyEditor();
+ bool updatedPropertyEditor = false;
+
+ for (PropertyListIterator it = begin; it != end; ++it) {
+ if (QObject* object = it->object()) { // Might have been deleted in the meantime
+ const PropertyHelper::Value newValue = function(*it);
+ updateMask |= it->updateMask();
+ // Update property editor if it is the current object
+ if (!updatedPropertyEditor && propertyEditor && object == propertyEditor->object()) {
+ propertyEditor->setPropertyValue(propertyName, newValue.first, newValue.second);
+ updatedPropertyEditor = true;
+ }
+ }
+ }
+ if (!updatedPropertyEditor) updateMask |= PropertyHelper::UpdatePropertyEditor;
+ return updateMask;
+}
+
+
+// set a new value, return update mask
+unsigned PropertyListCommand::setValue(QVariant value, bool changed, unsigned subPropertyMask)
+{
+ if(debugPropertyCommands)
+ qDebug() << "PropertyListCommand::setValue(" << value << changed << subPropertyMask << ')';
+ return changePropertyList(formWindow()->core(),
+ m_propertyDescription.m_propertyName, m_propertyHelperList.begin(), m_propertyHelperList.end(),
+ SetValueFunction(formWindow(), PropertyHelper::Value(value, changed), subPropertyMask));
+}
+
+// restore old value, return update mask
+unsigned PropertyListCommand::restoreOldValue()
+{
+ if(debugPropertyCommands)
+ qDebug() << "PropertyListCommand::restoreOldValue()";
+
+ return changePropertyList(formWindow()->core(),
+ m_propertyDescription.m_propertyName, m_propertyHelperList.begin(), m_propertyHelperList.end(),
+ UndoSetValueFunction(formWindow()));
+}
+// set default value, return update mask
+unsigned PropertyListCommand::restoreDefaultValue()
+{
+ if(debugPropertyCommands)
+ qDebug() << "PropertyListCommand::restoreDefaultValue()";
+
+ return changePropertyList(formWindow()->core(),
+ m_propertyDescription.m_propertyName, m_propertyHelperList.begin(), m_propertyHelperList.end(),
+ RestoreDefaultFunction(formWindow()));
+}
+
+// update
+void PropertyListCommand::update(unsigned updateMask)
+{
+ if(debugPropertyCommands)
+ qDebug() << "PropertyListCommand::update(" << updateMask << ')';
+
+ if (updateMask & PropertyHelper::UpdateObjectInspector) {
+ if (QDesignerObjectInspectorInterface *oi = formWindow()->core()->objectInspector())
+ oi->setFormWindow(formWindow());
+ }
+
+ if (updateMask & PropertyHelper::UpdatePropertyEditor) {
+ // this is needed when f.ex. undo, changes parent's palette, but
+ // the child is the active widget,
+ // TODO: current object?
+ if (QDesignerPropertyEditorInterface *propertyEditor = formWindow()->core()->propertyEditor()) {
+ propertyEditor->setObject(propertyEditor->object());
+ }
+ }
+}
+
+void PropertyListCommand::undo()
+{
+ update(restoreOldValue());
+ QDesignerPropertyEditor *designerPropertyEditor = qobject_cast<QDesignerPropertyEditor *>(core()->propertyEditor());
+ if (designerPropertyEditor)
+ designerPropertyEditor->updatePropertySheet();
+}
+
+// check if lists are aequivalent for command merging (same widgets and props)
+bool PropertyListCommand::canMergeLists(const PropertyHelperList& other) const
+{
+ if (m_propertyHelperList.size() != other.size())
+ return false;
+ for (int i = 0; i < m_propertyHelperList.size(); i++) {
+ if (!m_propertyHelperList[i].canMerge(other[i]))
+ return false;
+ }
+ return true;
+}
+
+// ---- SetPropertyCommand ----
+SetPropertyCommand::SetPropertyCommand(QDesignerFormWindowInterface *formWindow)
+ : PropertyListCommand(formWindow),
+ m_subPropertyMask(SubPropertyAll)
+{
+}
+
+bool SetPropertyCommand::init(QObject *object, const QString &apropertyName, const QVariant &newValue)
+{
+ Q_ASSERT(object);
+
+ m_newValue = newValue;
+
+ propertyHelperList().clear();
+ if (!add(object, apropertyName))
+ return false;
+
+ setDescription();
+ return true;
+}
+
+bool SetPropertyCommand::init(const ObjectList &list, const QString &apropertyName, const QVariant &newValue,
+ QObject *referenceObject, bool enableSubPropertyHandling)
+{
+ if (!initList(list, apropertyName, referenceObject))
+ return false;
+
+ m_newValue = newValue;
+
+ if(debugPropertyCommands)
+ qDebug() << "SetPropertyCommand::init()" << propertyHelperList().size() << '/' << list.size() << " reference " << referenceObject;
+
+ setDescription();
+
+ if (enableSubPropertyHandling)
+ m_subPropertyMask = subPropertyMask(newValue, referenceObject);
+ return true;
+}
+
+unsigned SetPropertyCommand::subPropertyMask(const QVariant &newValue, QObject *referenceObject)
+{
+ // figure out the mask of changed sub properties when comparing newValue to the current value of the reference object.
+ if (!referenceObject)
+ return SubPropertyAll;
+
+ QDesignerPropertySheetExtension* sheet = propertySheet(referenceObject);
+ Q_ASSERT(sheet);
+
+ const int index = sheet->indexOf(propertyName());
+ if (index == -1 || !sheet->isVisible(index))
+ return SubPropertyAll;
+
+ return compareSubProperties(sheet->property(index), newValue, specialProperty());
+}
+
+void SetPropertyCommand::setDescription()
+{
+ if (propertyHelperList().size() == 1) {
+ setText(QApplication::translate("Command", "Changed '%1' of '%2'").arg(propertyName()).arg(propertyHelperList()[0].object()->objectName()));
+ } else {
+ int count = propertyHelperList().size();
+ setText(QApplication::translate("Command", "Changed '%1' of %n objects", "", QCoreApplication::UnicodeUTF8, count).arg(propertyName()));
+ }
+}
+
+void SetPropertyCommand::redo()
+{
+ update(setValue(m_newValue, true, m_subPropertyMask));
+ QDesignerPropertyEditor *designerPropertyEditor = qobject_cast<QDesignerPropertyEditor *>(core()->propertyEditor());
+ if (designerPropertyEditor)
+ designerPropertyEditor->updatePropertySheet();
+}
+
+
+int SetPropertyCommand::id() const
+{
+ return 1976;
+}
+
+bool SetPropertyCommand::mergeWith(const QUndoCommand *other)
+{
+ if (id() != other->id() || !formWindow()->isDirty())
+ return false;
+
+ // Merging: When for example when the user types ahead in an inplace-editor,
+ // it makes sense to merge all the generated commands containing the one-character changes.
+ // In the case of subproperties, if the user changes the font size from 10 to 30 via 20
+ // and then changes to bold, it makes sense to merge the font size commands only.
+ // This is why the m_subPropertyMask is checked.
+
+ const SetPropertyCommand *cmd = static_cast<const SetPropertyCommand*>(other);
+ if (!propertyDescription().equals(cmd->propertyDescription()) ||
+ m_subPropertyMask != cmd->m_subPropertyMask ||
+ !canMergeLists(cmd->propertyHelperList()))
+ return false;
+
+ m_newValue = cmd->newValue();
+ m_subPropertyMask |= cmd->m_subPropertyMask;
+ if(debugPropertyCommands)
+ qDebug() << "SetPropertyCommand::mergeWith() succeeded " << propertyName();
+
+ return true;
+}
+
+// ---- ResetPropertyCommand ----
+ResetPropertyCommand::ResetPropertyCommand(QDesignerFormWindowInterface *formWindow)
+ : PropertyListCommand(formWindow)
+{
+}
+
+bool ResetPropertyCommand::init(QObject *object, const QString &apropertyName)
+{
+ Q_ASSERT(object);
+
+ propertyHelperList().clear();
+ if (!add(object, apropertyName))
+ return false;
+
+ setDescription();
+ return true;
+}
+
+bool ResetPropertyCommand::init(const ObjectList &list, const QString &apropertyName, QObject *referenceObject)
+{
+ if (!initList(list, apropertyName, referenceObject))
+ return false;
+
+ if(debugPropertyCommands)
+ qDebug() << "ResetPropertyCommand::init()" << propertyHelperList().size() << '/' << list.size();
+
+ setDescription();
+ return true;
+}
+
+void ResetPropertyCommand::setDescription()
+{
+ if (propertyHelperList().size() == 1) {
+ setText(QApplication::translate("Command", "Reset '%1' of '%2'").arg(propertyName()).arg(propertyHelperList()[0].object()->objectName()));
+ } else {
+ int count = propertyHelperList().size();
+ setText(QApplication::translate("Command", "Reset '%1' of %n objects", "", QCoreApplication::UnicodeUTF8, count).arg(propertyName()));
+ }
+}
+
+void ResetPropertyCommand::redo()
+{
+ update(restoreDefaultValue());
+ QDesignerPropertyEditor *designerPropertyEditor = qobject_cast<QDesignerPropertyEditor *>(core()->propertyEditor());
+ if (designerPropertyEditor)
+ designerPropertyEditor->updatePropertySheet();
+}
+
+AddDynamicPropertyCommand::AddDynamicPropertyCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QString(), formWindow)
+{
+
+}
+
+bool AddDynamicPropertyCommand::init(const QList<QObject *> &selection, QObject *current,
+ const QString &propertyName, const QVariant &value)
+{
+ Q_ASSERT(current);
+ m_propertyName = propertyName;
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), current);
+ Q_ASSERT(dynamicSheet);
+
+ m_selection.clear();
+
+ if (!value.isValid())
+ return false;
+
+ if (!dynamicSheet->canAddDynamicProperty(m_propertyName))
+ return false;
+
+ m_selection.append(current);
+
+ m_value = value;
+
+ QListIterator<QObject *> it(selection);
+ while (it.hasNext()) {
+ QObject *obj = it.next();
+ if (m_selection.contains(obj))
+ continue;
+ dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), obj);
+ Q_ASSERT(dynamicSheet);
+ if (dynamicSheet->canAddDynamicProperty(m_propertyName))
+ m_selection.append(obj);
+ }
+
+ setDescription();
+ return true;
+}
+
+void AddDynamicPropertyCommand::redo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QListIterator<QObject *> it(m_selection);
+ while (it.hasNext()) {
+ QObject *obj = it.next();
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), obj);
+ dynamicSheet->addDynamicProperty(m_propertyName, m_value);
+ if (QDesignerPropertyEditorInterface *propertyEditor = formWindow()->core()->propertyEditor()) {
+ if (propertyEditor->object() == obj)
+ propertyEditor->setObject(obj);
+ }
+ }
+}
+
+void AddDynamicPropertyCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QListIterator<QObject *> it(m_selection);
+ while (it.hasNext()) {
+ QObject *obj = it.next();
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), obj);
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), obj);
+ dynamicSheet->removeDynamicProperty(sheet->indexOf(m_propertyName));
+ if (QDesignerPropertyEditorInterface *propertyEditor = formWindow()->core()->propertyEditor()) {
+ if (propertyEditor->object() == obj)
+ propertyEditor->setObject(obj);
+ }
+ }
+}
+
+void AddDynamicPropertyCommand::setDescription()
+{
+ if (m_selection.size() == 1) {
+ setText(QApplication::translate("Command", "Add dynamic property '%1' to '%2'").arg(m_propertyName).arg(m_selection.first()->objectName()));
+ } else {
+ int count = m_selection.size();
+ setText(QApplication::translate("Command", "Add dynamic property '%1' to %n objects", "", QCoreApplication::UnicodeUTF8, count).arg(m_propertyName));
+ }
+}
+
+
+RemoveDynamicPropertyCommand::RemoveDynamicPropertyCommand(QDesignerFormWindowInterface *formWindow)
+ : QDesignerFormWindowCommand(QString(), formWindow)
+{
+
+}
+
+bool RemoveDynamicPropertyCommand::init(const QList<QObject *> &selection, QObject *current,
+ const QString &propertyName)
+{
+ Q_ASSERT(current);
+ m_propertyName = propertyName;
+
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QDesignerPropertySheetExtension *propertySheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), current);
+ Q_ASSERT(propertySheet);
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), current);
+ Q_ASSERT(dynamicSheet);
+
+ m_objectToValueAndChanged.clear();
+
+ const int index = propertySheet->indexOf(m_propertyName);
+ if (!dynamicSheet->isDynamicProperty(index))
+ return false;
+
+ m_objectToValueAndChanged[current] = qMakePair(propertySheet->property(index), propertySheet->isChanged(index));
+
+ QListIterator<QObject *> it(selection);
+ while (it.hasNext()) {
+ QObject *obj = it.next();
+ if (m_objectToValueAndChanged.contains(obj))
+ continue;
+
+ propertySheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), obj);
+ dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), obj);
+ const int idx = propertySheet->indexOf(m_propertyName);
+ if (dynamicSheet->isDynamicProperty(idx))
+ m_objectToValueAndChanged[obj] = qMakePair(propertySheet->property(idx), propertySheet->isChanged(idx));
+ }
+
+ setDescription();
+ return true;
+}
+
+void RemoveDynamicPropertyCommand::redo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QMap<QObject *, QPair<QVariant, bool> >::ConstIterator it = m_objectToValueAndChanged.constBegin();
+ while (it != m_objectToValueAndChanged.constEnd()) {
+ QObject *obj = it.key();
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), obj);
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), obj);
+ dynamicSheet->removeDynamicProperty(sheet->indexOf(m_propertyName));
+ if (QDesignerPropertyEditorInterface *propertyEditor = formWindow()->core()->propertyEditor()) {
+ if (propertyEditor->object() == obj)
+ propertyEditor->setObject(obj);
+ }
+ ++it;
+ }
+}
+
+void RemoveDynamicPropertyCommand::undo()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ QMap<QObject *, QPair<QVariant, bool> >::ConstIterator it = m_objectToValueAndChanged.constBegin();
+ while (it != m_objectToValueAndChanged.constEnd()) {
+ QObject *obj = it.key();
+ QDesignerPropertySheetExtension *propertySheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), obj);
+ QDesignerDynamicPropertySheetExtension *dynamicSheet = qt_extension<QDesignerDynamicPropertySheetExtension*>(core->extensionManager(), obj);
+ const int index = dynamicSheet->addDynamicProperty(m_propertyName, it.value().first);
+ propertySheet->setChanged(index, it.value().second);
+ if (QDesignerPropertyEditorInterface *propertyEditor = formWindow()->core()->propertyEditor()) {
+ if (propertyEditor->object() == obj)
+ propertyEditor->setObject(obj);
+ }
+ ++it;
+ }
+}
+
+void RemoveDynamicPropertyCommand::setDescription()
+{
+ if (m_objectToValueAndChanged.size() == 1) {
+ setText(QApplication::translate("Command", "Remove dynamic property '%1' from '%2'").arg(m_propertyName).arg(m_objectToValueAndChanged.constBegin().key()->objectName()));
+ } else {
+ int count = m_objectToValueAndChanged.size();
+ setText(QApplication::translate("Command", "Remove dynamic property '%1' from %n objects", "", QCoreApplication::UnicodeUTF8, count).arg(m_propertyName));
+ }
+}
+
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_propertycommand_p.h b/tools/designer/src/lib/shared/qdesigner_propertycommand_p.h
new file mode 100644
index 0000000000..6b9722f588
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_propertycommand_p.h
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_PROPERTYCOMMAND_H
+#define QDESIGNER_PROPERTYCOMMAND_H
+
+#include "qdesigner_formwindowcommand_p.h"
+
+#include <QtCore/QVariant>
+#include <QtCore/QList>
+#include <QtCore/QPair>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerPropertySheetExtension;
+
+namespace qdesigner_internal {
+
+class QDesignerIntegration;
+
+enum SpecialProperty {
+ SP_None, SP_ObjectName, SP_LayoutName, SP_SpacerName,SP_WindowTitle,
+ SP_MinimumSize, SP_MaximumSize, SP_Geometry, SP_Icon, SP_CurrentTabName, SP_CurrentItemName, SP_CurrentPageName,
+ SP_AutoDefault, SP_Alignment, SP_Shortcut, SP_Orientation
+};
+
+//Determine special property
+enum SpecialProperty getSpecialProperty(const QString& propertyName);
+
+
+// A helper class for applying properties to objects.
+// Can be used for Set commands (setValue(), restoreOldValue()) or
+// Reset Commands restoreDefaultValue(), restoreOldValue()).
+class PropertyHelper {
+public:
+ // A pair of Value and changed flag
+ typedef QPair<QVariant, bool> Value;
+
+ enum ObjectType {OT_Object, OT_FreeAction, OT_AssociatedAction, OT_Widget};
+
+ PropertyHelper(QObject* object,
+ SpecialProperty specialProperty,
+ QDesignerPropertySheetExtension *sheet,
+ int index);
+
+ QObject *object() const { return m_object; }
+ SpecialProperty specialProperty() const { return m_specialProperty; }
+ // set a new value
+ Value setValue(QDesignerFormWindowInterface *fw, const QVariant &value, bool changed, unsigned subPropertyMask);
+
+ // restore old value
+ Value restoreOldValue(QDesignerFormWindowInterface *fw);
+ // set default value
+ Value restoreDefaultValue(QDesignerFormWindowInterface *fw);
+
+ inline QVariant oldValue() const
+ { return m_oldValue.first; }
+
+ inline void setOldValue(const QVariant &oldValue)
+ { m_oldValue.first = oldValue; }
+
+ // required updates for this property (bit mask)
+ enum UpdateMask { UpdatePropertyEditor=1, UpdateObjectInspector=2 };
+ unsigned updateMask() const;
+
+ // can be merged into one command (that is, object and name match)
+ bool canMerge(const PropertyHelper &other) const;
+ QDesignerIntegration *integration(QDesignerFormWindowInterface *fw) const;
+
+ static void triggerActionChanged(QAction *a);
+
+private:
+ // Apply the value and update. Returns corrected value
+ Value applyValue(QDesignerFormWindowInterface *fw, const QVariant &oldValue, Value newValue);
+
+ static void checkApplyWidgetValue(QDesignerFormWindowInterface *fw, QWidget* w,
+ SpecialProperty specialProperty, QVariant &v);
+
+ void updateObject(QDesignerFormWindowInterface *fw, const QVariant &oldValue, const QVariant &newValue);
+ QVariant findDefaultValue(QDesignerFormWindowInterface *fw) const;
+ void ensureUniqueObjectName(QDesignerFormWindowInterface *fw, QObject *object) const;
+ SpecialProperty m_specialProperty;
+
+ QPointer<QObject> m_object;
+ ObjectType m_objectType;
+ QPointer<QWidget> m_parentWidget;
+
+ QDesignerPropertySheetExtension *m_propertySheet;
+ int m_index;
+
+ Value m_oldValue;
+};
+
+// Base class for commands that can be applied to several widgets
+
+class QDESIGNER_SHARED_EXPORT PropertyListCommand : public QDesignerFormWindowCommand {
+public:
+ typedef QList<QObject *> ObjectList;
+
+ explicit PropertyListCommand(QDesignerFormWindowInterface *formWindow);
+
+ QObject* object(int index = 0) const;
+
+ QVariant oldValue(int index = 0) const;
+
+ void setOldValue(const QVariant &oldValue, int index = 0);
+
+ // Calls restoreDefaultValue() and update()
+ virtual void undo();
+
+protected:
+ typedef QList<PropertyHelper> PropertyHelperList;
+
+
+ // add an object
+ bool add(QObject *object, const QString &propertyName);
+
+ // Init from a list and make sure referenceObject is added first to obtain the right property group
+ bool initList(const ObjectList &list, const QString &apropertyName, QObject *referenceObject = 0);
+
+ // set a new value, return update mask
+ unsigned setValue(QVariant value, bool changed, unsigned subPropertyMask);
+
+ // restore old value, return update mask
+ unsigned restoreOldValue();
+ // set default value, return update mask
+ unsigned restoreDefaultValue();
+
+ // update designer
+ void update(unsigned updateMask);
+
+ // check if lists are aequivalent for command merging (same widgets and props)
+ bool canMergeLists(const PropertyHelperList& other) const;
+
+ PropertyHelperList& propertyHelperList() { return m_propertyHelperList; }
+ const PropertyHelperList& propertyHelperList() const { return m_propertyHelperList; }
+
+ const QString propertyName() const;
+ SpecialProperty specialProperty() const;
+
+ // Helper struct describing a property used for checking whether
+ // properties of different widgets are equivalent
+ struct PropertyDescription {
+ public:
+ PropertyDescription();
+ PropertyDescription(const QString &propertyName, QDesignerPropertySheetExtension *propertySheet, int index);
+ bool equals(const PropertyDescription &p) const;
+ void debug() const;
+
+ QString m_propertyName;
+ QString m_propertyGroup;
+ QVariant::Type m_propertyType;
+ SpecialProperty m_specialProperty;
+ };
+ const PropertyDescription &propertyDescription() const { return m_propertyDescription; }
+
+private:
+ PropertyDescription m_propertyDescription;
+ PropertyHelperList m_propertyHelperList;
+};
+
+class QDESIGNER_SHARED_EXPORT SetPropertyCommand: public PropertyListCommand
+{
+
+public:
+ typedef QList<QObject *> ObjectList;
+
+ explicit SetPropertyCommand(QDesignerFormWindowInterface *formWindow);
+
+ bool init(QObject *object, const QString &propertyName, const QVariant &newValue);
+ bool init(const ObjectList &list, const QString &propertyName, const QVariant &newValue,
+ QObject *referenceObject = 0, bool enableSubPropertyHandling = true);
+
+
+ inline QVariant newValue() const
+ { return m_newValue; }
+
+ inline void setNewValue(const QVariant &newValue)
+ { m_newValue = newValue; }
+
+ int id() const;
+ bool mergeWith(const QUndoCommand *other);
+
+ virtual void redo();
+private:
+ unsigned subPropertyMask(const QVariant &newValue, QObject *referenceObject);
+ void setDescription();
+ QVariant m_newValue;
+ unsigned m_subPropertyMask;
+};
+
+class QDESIGNER_SHARED_EXPORT ResetPropertyCommand: public PropertyListCommand
+{
+
+public:
+ typedef QList<QObject *> ObjectList;
+
+ explicit ResetPropertyCommand(QDesignerFormWindowInterface *formWindow);
+
+ bool init(QObject *object, const QString &propertyName);
+ bool init(const ObjectList &list, const QString &propertyName, QObject *referenceObject = 0);
+
+ virtual void redo();
+
+protected:
+ virtual bool mergeWith(const QUndoCommand *) { return false; }
+
+private:
+ void setDescription();
+ QString m_propertyName;
+};
+
+
+class QDESIGNER_SHARED_EXPORT AddDynamicPropertyCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit AddDynamicPropertyCommand(QDesignerFormWindowInterface *formWindow);
+
+ bool init(const QList<QObject *> &selection, QObject *current, const QString &propertyName, const QVariant &value);
+
+ virtual void redo();
+ virtual void undo();
+private:
+ void setDescription();
+ QString m_propertyName;
+ QList<QObject *> m_selection;
+ QVariant m_value;
+};
+
+class QDESIGNER_SHARED_EXPORT RemoveDynamicPropertyCommand: public QDesignerFormWindowCommand
+{
+
+public:
+ explicit RemoveDynamicPropertyCommand(QDesignerFormWindowInterface *formWindow);
+
+ bool init(const QList<QObject *> &selection, QObject *current, const QString &propertyName);
+
+ virtual void redo();
+ virtual void undo();
+private:
+ void setDescription();
+ QString m_propertyName;
+ QMap<QObject *, QPair<QVariant, bool> > m_objectToValueAndChanged;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_PROPERTYCOMMAND_H
diff --git a/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp b/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp
new file mode 100644
index 0000000000..7c7d9d7620
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_propertyeditor_p.h"
+#ifdef Q_OS_WIN
+# include <widgetfactory_p.h>
+#endif
+#include <QAction>
+#include <QLineEdit>
+#include <QAbstractButton>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+QDesignerPropertyEditor::QDesignerPropertyEditor(QWidget *parent, Qt::WindowFlags flags) :
+ QDesignerPropertyEditorInterface(parent, flags)
+{
+ // Make old signal work for compatibility
+ connect(this, SIGNAL(propertyChanged(QString,QVariant)), this, SLOT(slotPropertyChanged(QString,QVariant)));
+}
+
+QDesignerPropertyEditor::StringPropertyParameters QDesignerPropertyEditor::textPropertyValidationMode(
+ QDesignerFormEditorInterface *core, const QObject *object,
+ const QString &propertyName, bool isMainContainer)
+{
+ // object name - no comment
+ if (propertyName == QLatin1String("objectName")) {
+ const TextPropertyValidationMode vm = isMainContainer ? ValidationObjectNameScope : ValidationObjectName;
+ return StringPropertyParameters(vm, false);
+ }
+
+ // Accessibility. Both are texts the narrator reads
+ if (propertyName == QLatin1String("accessibleDescription") || propertyName == QLatin1String("accessibleName"))
+ return StringPropertyParameters(ValidationRichText, true);
+
+ // Names
+ if (propertyName == QLatin1String("buddy")
+ || propertyName == QLatin1String("currentItemName")
+ || propertyName == QLatin1String("currentPageName")
+ || propertyName == QLatin1String("currentTabName")
+ || propertyName == QLatin1String("layoutName")
+ || propertyName == QLatin1String("spacerName"))
+ return StringPropertyParameters(ValidationObjectName, false);
+
+ if (propertyName.endsWith(QLatin1String("Name")))
+ return StringPropertyParameters(ValidationSingleLine, true);
+
+ // Multi line?
+ if (propertyName == QLatin1String("styleSheet"))
+ return StringPropertyParameters(ValidationStyleSheet, false);
+
+ if (propertyName == QLatin1String("description") || propertyName == QLatin1String("iconText")) // QCommandLinkButton
+ return StringPropertyParameters(ValidationMultiLine, true);
+
+ if (propertyName == QLatin1String("toolTip") || propertyName.endsWith(QLatin1String("ToolTip")) ||
+ propertyName == QLatin1String("whatsThis") ||
+ propertyName == QLatin1String("windowIconText") || propertyName == QLatin1String("html"))
+ return StringPropertyParameters(ValidationRichText, true);
+
+ // text: Check according to widget type.
+ if (propertyName == QLatin1String("text")) {
+ if (qobject_cast<const QAction *>(object) || qobject_cast<const QLineEdit *>(object))
+ return StringPropertyParameters(ValidationSingleLine, true);
+ if (qobject_cast<const QAbstractButton *>(object))
+ return StringPropertyParameters(ValidationMultiLine, true);
+ return StringPropertyParameters(ValidationRichText, true);
+ }
+ if (propertyName == QLatin1String("pageId")) // A QWizard page id
+ return StringPropertyParameters(ValidationSingleLine, false);
+
+ if (propertyName == QLatin1String("plainText")) // QPlainTextEdit
+ return StringPropertyParameters(ValidationMultiLine, true);
+
+#ifdef Q_OS_WIN // No translation for the active X "control" property
+ if (propertyName == QLatin1String("control") && WidgetFactory::classNameOf(core, object) == QLatin1String("QAxWidget"))
+ return StringPropertyParameters(ValidationSingleLine, false);
+#else
+ Q_UNUSED(core);
+#endif
+
+ // default to single
+ return StringPropertyParameters(ValidationSingleLine, true);
+}
+
+void QDesignerPropertyEditor::slotPropertyChanged(const QString &name, const QVariant &value)
+{
+ emit propertyValueChanged(name, value, true);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h b/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h
new file mode 100644
index 0000000000..a979fde521
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef DESIGNERPROPERTYEDITOR_H
+#define DESIGNERPROPERTYEDITOR_H
+
+#include "shared_global_p.h"
+#include "shared_enums_p.h"
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+// Extends the QDesignerPropertyEditorInterface by property comment handling and
+// a signal for resetproperty.
+
+class QDESIGNER_SHARED_EXPORT QDesignerPropertyEditor: public QDesignerPropertyEditorInterface
+{
+ Q_OBJECT
+public:
+ QDesignerPropertyEditor(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+
+ // A pair <ValidationMode, bool isTranslatable>.
+ typedef QPair<TextPropertyValidationMode, bool> StringPropertyParameters;
+
+ // Return a pair of validation mode and flag indicating whether property is translatable
+ // for textual properties.
+ static StringPropertyParameters textPropertyValidationMode(QDesignerFormEditorInterface *core,
+ const QObject *object, const QString &propertyName, bool isMainContainer);
+
+
+Q_SIGNALS:
+ void propertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling);
+ void resetProperty(const QString &name);
+ void addDynamicProperty(const QString &name, const QVariant &value);
+ void removeDynamicProperty(const QString &name);
+ void editorOpened();
+ void editorClosed();
+
+public Q_SLOTS:
+ /* Quick update that assumes the actual count of properties has not changed
+ * (as opposed to setObject()). N/A when for example executing a
+ * layout command and margin properties appear. */
+ virtual void updatePropertySheet() = 0;
+ virtual void reloadResourceProperties() = 0;
+
+private Q_SLOTS:
+ void slotPropertyChanged(const QString &name, const QVariant &value);
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // DESIGNERPROPERTYEDITOR_H
diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
new file mode 100644
index 0000000000..7abbde746a
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
@@ -0,0 +1,1601 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_propertysheet_p.h"
+#include "qdesigner_utils_p.h"
+#include "formwindowbase_p.h"
+#include "layoutinfo_p.h"
+#include "qlayout_widget_p.h"
+#include "qdesigner_introspection_p.h"
+
+#include <formbuilderextra_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtCore/QDebug>
+
+#include <QtGui/QLayout>
+#include <QtGui/QDockWidget>
+#include <QtGui/QDialog>
+#include <QtGui/QLabel>
+#include <QtGui/QGroupBox>
+#include <QtGui/QStyle>
+#include <QtGui/QApplication>
+#include <QtGui/QToolBar>
+#include <QtGui/QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+#define USE_LAYOUT_SIZE_CONSTRAINT
+
+static const QDesignerMetaObjectInterface *propertyIntroducedBy(const QDesignerMetaObjectInterface *meta, int index)
+{
+ if (index >= meta->propertyOffset())
+ return meta;
+
+ if (meta->superClass())
+ return propertyIntroducedBy(meta->superClass(), index);
+
+ return 0;
+}
+
+// Layout fake properties (prefixed by 'layout' to distinguish them from other 'margins'
+// that might be around. These are forwarded to the layout sheet (after name transformation).
+//
+// 'layoutObjectName' is new for 4.4. It is the name of the actual layout.
+// Up to 4.3, QLayoutWidget's name was displayed in the objectinspector.
+// This changes with 4.4; the layout name is displayed. This means that for
+// old forms, QLayoutWidget will show up as ''; however, the uic code will
+// still use 'verticalLayout' (in case someone accesses it). New Layouts get autogenerated names,
+// legacy forms will keep their empty names (unless someone types in a new name).
+static const char *layoutObjectNameC = "layoutName";
+static const char *layoutLeftMarginC = "layoutLeftMargin";
+static const char *layoutTopMarginC = "layoutTopMargin";
+static const char *layoutRightMarginC = "layoutRightMargin";
+static const char *layoutBottomMarginC = "layoutBottomMargin";
+static const char *layoutSpacingC = "layoutSpacing";
+static const char *layoutHorizontalSpacingC = "layoutHorizontalSpacing";
+static const char *layoutVerticalSpacingC = "layoutVerticalSpacing";
+static const char *layoutSizeConstraintC = "layoutSizeConstraint";
+// form layout
+static const char *layoutFieldGrowthPolicyC = "layoutFieldGrowthPolicy";
+static const char *layoutRowWrapPolicyC = "layoutRowWrapPolicy";
+static const char *layoutLabelAlignmentC = "layoutLabelAlignment";
+static const char *layoutFormAlignmentC = "layoutFormAlignment";
+// stretches
+static const char *layoutboxStretchPropertyC = "layoutStretch";
+static const char *layoutGridRowStretchPropertyC = "layoutRowStretch";
+static const char *layoutGridColumnStretchPropertyC = "layoutColumnStretch";
+static const char *layoutGridRowMinimumHeightC = "layoutRowMinimumHeight";
+static const char *layoutGridColumnMinimumWidthC = "layoutColumnMinimumWidth";
+
+// Find the form editor in the hierarchy.
+// We know that the parent of the sheet is the extension manager
+// whose parent is the core.
+
+static QDesignerFormEditorInterface *formEditorForObject(QObject *o) {
+ do {
+ if (QDesignerFormEditorInterface* core = qobject_cast<QDesignerFormEditorInterface*>(o))
+ return core;
+ o = o->parent();
+ } while(o);
+ Q_ASSERT(o);
+ return 0;
+}
+
+static bool hasLayoutAttributes(QDesignerFormEditorInterface *core, QObject *object)
+{
+ if (!object->isWidgetType())
+ return false;
+
+ QWidget *w = qobject_cast<QWidget *>(object);
+ if (const QDesignerWidgetDataBaseInterface *db = core->widgetDataBase()) {
+ if (db->isContainer(w))
+ return true;
+ }
+ return false;
+}
+
+// Cache DesignerMetaEnum by scope/name of a QMetaEnum
+static const qdesigner_internal::DesignerMetaEnum &designerMetaEnumFor(const QDesignerMetaEnumInterface *me)
+{
+ typedef QPair<QString, QString> ScopeNameKey;
+ typedef QMap<ScopeNameKey, qdesigner_internal::DesignerMetaEnum> DesignerMetaEnumCache;
+ static DesignerMetaEnumCache cache;
+
+ const QString name = me->name();
+ const QString scope = me->scope();
+
+ const ScopeNameKey key = ScopeNameKey(scope, name);
+ DesignerMetaEnumCache::iterator it = cache.find(key);
+ if (it == cache.end()) {
+ qdesigner_internal::DesignerMetaEnum dme = qdesigner_internal::DesignerMetaEnum(name, scope, me->separator());
+ const int keyCount = me->keyCount();
+ for (int i=0; i < keyCount; ++i)
+ dme.addKey(me->value(i), me->key(i));
+ it = cache.insert(key, dme);
+ }
+ return it.value();
+}
+
+// Cache DesignerMetaFlags by scope/name of a QMetaEnum
+static const qdesigner_internal::DesignerMetaFlags &designerMetaFlagsFor(const QDesignerMetaEnumInterface *me)
+{
+ typedef QPair<QString, QString> ScopeNameKey;
+ typedef QMap<ScopeNameKey, qdesigner_internal::DesignerMetaFlags> DesignerMetaFlagsCache;
+ static DesignerMetaFlagsCache cache;
+
+ const QString name = me->name();
+ const QString scope = me->scope();
+
+ const ScopeNameKey key = ScopeNameKey(scope, name);
+ DesignerMetaFlagsCache::iterator it = cache.find(key);
+ if (it == cache.end()) {
+ qdesigner_internal::DesignerMetaFlags dme = qdesigner_internal::DesignerMetaFlags(name, scope, me->separator());
+ const int keyCount = me->keyCount();
+ for (int i=0; i < keyCount; ++i)
+ dme.addKey(me->value(i), me->key(i));
+ it = cache.insert(key, dme);
+ }
+ return it.value();
+}
+
+// ------------ QDesignerMemberSheetPrivate
+class QDesignerPropertySheetPrivate {
+public:
+ typedef QDesignerPropertySheet::PropertyType PropertyType;
+ typedef QDesignerPropertySheet::ObjectType ObjectType;
+
+ explicit QDesignerPropertySheetPrivate(QDesignerPropertySheet *sheetPublic, QObject *object, QObject *sheetParent);
+
+ bool invalidIndex(const char *functionName, int index) const;
+ inline int count() const { return m_meta->propertyCount() + m_addProperties.count(); }
+
+ PropertyType propertyType(int index) const;
+ QString transformLayoutPropertyName(int index) const;
+ QLayout* layout(QDesignerPropertySheetExtension **layoutPropertySheet = 0) const;
+ static ObjectType objectType(const QObject *o);
+
+ bool isReloadableProperty(int index) const;
+ bool isResourceProperty(int index) const;
+ void addResourceProperty(int index, QVariant::Type type);
+ QVariant resourceProperty(int index) const;
+ void setResourceProperty(int index, const QVariant &value);
+ QVariant emptyResourceProperty(int index) const; // of type PropertySheetPixmapValue / PropertySheetIconValue
+ QVariant defaultResourceProperty(int index) const; // of type QPixmap / QIcon (maybe it can be generalized for all types, not resource only)
+
+ bool isStringProperty(int index) const;
+ void addStringProperty(int index);
+ qdesigner_internal::PropertySheetStringValue stringProperty(int index) const;
+ void setStringProperty(int index, const qdesigner_internal::PropertySheetStringValue &value);
+
+ bool isKeySequenceProperty(int index) const;
+ void addKeySequenceProperty(int index);
+ qdesigner_internal::PropertySheetKeySequenceValue keySequenceProperty(int index) const;
+ void setKeySequenceProperty(int index, const qdesigner_internal::PropertySheetKeySequenceValue &value);
+
+ enum PropertyKind { NormalProperty, FakeProperty, DynamicProperty, DefaultDynamicProperty };
+ class Info {
+ public:
+ Info();
+
+ QString group;
+ QVariant defaultValue;
+ bool changed;
+ bool visible;
+ bool attribute;
+ bool reset;
+ PropertyType propertyType;
+ PropertyKind kind;
+ };
+
+ Info &ensureInfo(int index);
+
+ QDesignerPropertySheet *q;
+ QDesignerFormEditorInterface *m_core;
+ const QDesignerMetaObjectInterface *m_meta;
+ const ObjectType m_objectType;
+
+ typedef QHash<int, Info> InfoHash;
+ InfoHash m_info;
+ QHash<int, QVariant> m_fakeProperties;
+ QHash<int, QVariant> m_addProperties;
+ QHash<QString, int> m_addIndex;
+ QHash<int, QVariant> m_resourceProperties; // only PropertySheetPixmapValue snd PropertySheetIconValue here
+ QHash<int, qdesigner_internal::PropertySheetStringValue> m_stringProperties; // only PropertySheetStringValue
+ QHash<int, qdesigner_internal::PropertySheetKeySequenceValue> m_keySequenceProperties; // only PropertySheetKeySequenceValue
+
+ const bool m_canHaveLayoutAttributes;
+
+ // Variables used for caching the layout, access via layout().
+ QPointer<QObject> m_object;
+ mutable QPointer<QLayout> m_lastLayout;
+ mutable QDesignerPropertySheetExtension *m_lastLayoutPropertySheet;
+ mutable bool m_LastLayoutByDesigner;
+
+ qdesigner_internal::DesignerPixmapCache *m_pixmapCache;
+ qdesigner_internal::DesignerIconCache *m_iconCache;
+ QPointer<qdesigner_internal::FormWindowBase> m_fwb;
+
+ // Enable Qt's internal properties starting with prefix "_q_"
+ static bool m_internalDynamicPropertiesEnabled;
+};
+
+bool QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled = false;
+
+/*
+ The property is reloadable if its contents depends on resource.
+*/
+bool QDesignerPropertySheetPrivate::isReloadableProperty(int index) const
+{
+ return isResourceProperty(index)
+ || propertyType(index) == QDesignerPropertySheet::PropertyStyleSheet
+ || q->property(index).type() == QVariant::Url;
+}
+
+/*
+ Resource properties are those which:
+ 1) are reloadable
+ 2) their state is associated with a file which can be taken from resources
+ 3) we don't store them in Qt meta object system (because designer keeps different data structure for them)
+*/
+
+bool QDesignerPropertySheetPrivate::isResourceProperty(int index) const
+{
+ return m_resourceProperties.contains(index);
+}
+
+void QDesignerPropertySheetPrivate::addResourceProperty(int index, QVariant::Type type)
+{
+ if (type == QVariant::Pixmap)
+ m_resourceProperties.insert(index, qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue()));
+ else if (type == QVariant::Icon)
+ m_resourceProperties.insert(index, qVariantFromValue(qdesigner_internal::PropertySheetIconValue()));
+}
+
+QVariant QDesignerPropertySheetPrivate::emptyResourceProperty(int index) const
+{
+ QVariant v = m_resourceProperties.value(index);
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v))
+ return qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue());
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v))
+ return qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
+ return v;
+}
+
+QVariant QDesignerPropertySheetPrivate::defaultResourceProperty(int index) const
+{
+ return m_info.value(index).defaultValue;
+}
+
+QVariant QDesignerPropertySheetPrivate::resourceProperty(int index) const
+{
+ return m_resourceProperties.value(index);
+}
+
+void QDesignerPropertySheetPrivate::setResourceProperty(int index, const QVariant &value)
+{
+ Q_ASSERT(isResourceProperty(index));
+
+ QVariant &v = m_resourceProperties[index];
+ if ((qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(v))
+ || (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value) && qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(v)))
+ v = value;
+}
+
+bool QDesignerPropertySheetPrivate::isStringProperty(int index) const
+{
+ return m_stringProperties.contains(index);
+}
+
+void QDesignerPropertySheetPrivate::addStringProperty(int index)
+{
+ m_stringProperties.insert(index, qdesigner_internal::PropertySheetStringValue());
+}
+
+qdesigner_internal::PropertySheetStringValue QDesignerPropertySheetPrivate::stringProperty(int index) const
+{
+ return m_stringProperties.value(index);
+}
+
+void QDesignerPropertySheetPrivate::setStringProperty(int index, const qdesigner_internal::PropertySheetStringValue &value)
+{
+ Q_ASSERT(isStringProperty(index));
+
+ m_stringProperties[index] = value;
+}
+
+bool QDesignerPropertySheetPrivate::isKeySequenceProperty(int index) const
+{
+ return m_keySequenceProperties.contains(index);
+}
+
+void QDesignerPropertySheetPrivate::addKeySequenceProperty(int index)
+{
+ m_keySequenceProperties.insert(index, qdesigner_internal::PropertySheetKeySequenceValue());
+}
+
+qdesigner_internal::PropertySheetKeySequenceValue QDesignerPropertySheetPrivate::keySequenceProperty(int index) const
+{
+ return m_keySequenceProperties.value(index);
+}
+
+void QDesignerPropertySheetPrivate::setKeySequenceProperty(int index, const qdesigner_internal::PropertySheetKeySequenceValue &value)
+{
+ Q_ASSERT(isKeySequenceProperty(index));
+
+ m_keySequenceProperties[index] = value;
+}
+
+QDesignerPropertySheetPrivate::Info::Info() :
+ changed(false),
+ visible(true),
+ attribute(false),
+ reset(true),
+ propertyType(QDesignerPropertySheet::PropertyNone),
+ kind(NormalProperty)
+{
+}
+
+QDesignerPropertySheetPrivate::QDesignerPropertySheetPrivate(QDesignerPropertySheet *sheetPublic, QObject *object, QObject *sheetParent) :
+ q(sheetPublic),
+ m_core(formEditorForObject(sheetParent)),
+ m_meta(m_core->introspection()->metaObject(object)),
+ m_objectType(QDesignerPropertySheet::objectTypeFromObject(object)),
+ m_canHaveLayoutAttributes(hasLayoutAttributes(m_core, object)),
+ m_object(object),
+ m_lastLayout(0),
+ m_lastLayoutPropertySheet(0),
+ m_LastLayoutByDesigner(false),
+ m_pixmapCache(0),
+ m_iconCache(0)
+{
+}
+
+qdesigner_internal::FormWindowBase *QDesignerPropertySheet::formWindowBase() const
+{
+ return d->m_fwb;
+}
+
+bool QDesignerPropertySheetPrivate::invalidIndex(const char *functionName, int index) const
+{
+ if (index < 0 || index >= count()) {
+ qWarning() << "** WARNING " << functionName << " invoked for " << m_object->objectName() << " was passed an invalid index " << index << '.';
+ return true;
+ }
+ return false;
+}
+
+QLayout* QDesignerPropertySheetPrivate::layout(QDesignerPropertySheetExtension **layoutPropertySheet) const
+{
+ // Return the layout and its property sheet
+ // only if it is managed by designer and not one created on a custom widget.
+ // (attempt to cache the value as this requires some hoops).
+ if (layoutPropertySheet)
+ *layoutPropertySheet = 0;
+
+ if (!m_object->isWidgetType() || !m_canHaveLayoutAttributes)
+ return 0;
+
+ QWidget *widget = qobject_cast<QWidget*>(m_object);
+ QLayout *widgetLayout = qdesigner_internal::LayoutInfo::internalLayout(widget);
+ if (!widgetLayout) {
+ m_lastLayout = 0;
+ m_lastLayoutPropertySheet = 0;
+ return 0;
+ }
+ // Smart logic to avoid retrieving the meta DB from the widget every time.
+ if (widgetLayout != m_lastLayout) {
+ m_lastLayout = widgetLayout;
+ m_LastLayoutByDesigner = false;
+ m_lastLayoutPropertySheet = 0;
+ // Is this a layout managed by designer or some layout on a custom widget?
+ if (qdesigner_internal::LayoutInfo::managedLayout(m_core ,widgetLayout)) {
+ m_LastLayoutByDesigner = true;
+ m_lastLayoutPropertySheet = qt_extension<QDesignerPropertySheetExtension*>(m_core->extensionManager(), m_lastLayout);
+ }
+ }
+ if (!m_LastLayoutByDesigner)
+ return 0;
+
+ if (layoutPropertySheet)
+ *layoutPropertySheet = m_lastLayoutPropertySheet;
+
+ return m_lastLayout;
+}
+
+QDesignerPropertySheetPrivate::Info &QDesignerPropertySheetPrivate::ensureInfo(int index)
+{
+ InfoHash::iterator it = m_info.find(index);
+ if (it == m_info.end())
+ it = m_info.insert(index, Info());
+ return it.value();
+}
+
+QDesignerPropertySheet::PropertyType QDesignerPropertySheetPrivate::propertyType(int index) const
+{
+ const InfoHash::const_iterator it = m_info.constFind(index);
+ if (it == m_info.constEnd())
+ return QDesignerPropertySheet::PropertyNone;
+ return it.value().propertyType;
+}
+
+QString QDesignerPropertySheetPrivate::transformLayoutPropertyName(int index) const
+{
+ typedef QMap<QDesignerPropertySheet::PropertyType, QString> TypeNameMap;
+ static TypeNameMap typeNameMap;
+ if (typeNameMap.empty()) {
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutObjectName, QLatin1String("objectName"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutLeftMargin, QLatin1String("leftMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutTopMargin, QLatin1String("topMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutRightMargin, QLatin1String("rightMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutBottomMargin, QLatin1String("bottomMargin"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutSpacing, QLatin1String("spacing"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutHorizontalSpacing, QLatin1String("horizontalSpacing"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutVerticalSpacing, QLatin1String("verticalSpacing"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutSizeConstraint, QLatin1String("sizeConstraint"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutFieldGrowthPolicy, QLatin1String("fieldGrowthPolicy"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutRowWrapPolicy, QLatin1String("rowWrapPolicy"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutLabelAlignment, QLatin1String("labelAlignment"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutFormAlignment, QLatin1String("formAlignment"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutBoxStretch, QLatin1String("stretch"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridRowStretch, QLatin1String("rowStretch"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridColumnStretch, QLatin1String("columnStretch"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridRowMinimumHeight, QLatin1String("rowMinimumHeight"));
+ typeNameMap.insert(QDesignerPropertySheet::PropertyLayoutGridColumnMinimumWidth, QLatin1String("columnMinimumWidth"));
+ }
+ const TypeNameMap::const_iterator it = typeNameMap.constFind(propertyType(index));
+ if (it != typeNameMap.constEnd())
+ return it.value();
+ return QString();
+}
+
+// ----------- QDesignerPropertySheet
+
+QDesignerPropertySheet::ObjectType QDesignerPropertySheet::objectTypeFromObject(const QObject *o)
+{
+ if (qobject_cast<const QLayout *>(o))
+ return ObjectLayout;
+
+ if (!o->isWidgetType())
+ return ObjectNone;
+
+ if (qobject_cast<const QLayoutWidget *>(o))
+ return ObjectLayoutWidget;
+
+ if (qobject_cast<const QLabel*>(o))
+ return ObjectLabel;
+
+ if (o->inherits("Q3GroupBox"))
+ return ObjectQ3GroupBox;
+
+ return ObjectNone;
+}
+
+QDesignerPropertySheet::PropertyType QDesignerPropertySheet::propertyTypeFromName(const QString &name)
+{
+ typedef QHash<QString, PropertyType> PropertyTypeHash;
+ static PropertyTypeHash propertyTypeHash;
+ if (propertyTypeHash.empty()) {
+ propertyTypeHash.insert(QLatin1String(layoutObjectNameC), PropertyLayoutObjectName);
+ propertyTypeHash.insert(QLatin1String(layoutLeftMarginC), PropertyLayoutLeftMargin);
+ propertyTypeHash.insert(QLatin1String(layoutTopMarginC), PropertyLayoutTopMargin);
+ propertyTypeHash.insert(QLatin1String(layoutRightMarginC), PropertyLayoutRightMargin);
+ propertyTypeHash.insert(QLatin1String(layoutBottomMarginC), PropertyLayoutBottomMargin);
+ propertyTypeHash.insert(QLatin1String(layoutSpacingC), PropertyLayoutSpacing);
+ propertyTypeHash.insert(QLatin1String(layoutHorizontalSpacingC), PropertyLayoutHorizontalSpacing);
+ propertyTypeHash.insert(QLatin1String(layoutVerticalSpacingC), PropertyLayoutVerticalSpacing);
+ propertyTypeHash.insert(QLatin1String(layoutSizeConstraintC), PropertyLayoutSizeConstraint);
+ propertyTypeHash.insert(QLatin1String(layoutFieldGrowthPolicyC), PropertyLayoutFieldGrowthPolicy);
+ propertyTypeHash.insert(QLatin1String(layoutRowWrapPolicyC), PropertyLayoutRowWrapPolicy);
+ propertyTypeHash.insert(QLatin1String(layoutLabelAlignmentC), PropertyLayoutLabelAlignment);
+ propertyTypeHash.insert(QLatin1String(layoutFormAlignmentC), PropertyLayoutFormAlignment);
+ propertyTypeHash.insert(QLatin1String(layoutboxStretchPropertyC), PropertyLayoutBoxStretch);
+ propertyTypeHash.insert(QLatin1String(layoutGridRowStretchPropertyC), PropertyLayoutGridRowStretch);
+ propertyTypeHash.insert(QLatin1String(layoutGridColumnStretchPropertyC), PropertyLayoutGridColumnStretch);
+ propertyTypeHash.insert(QLatin1String(layoutGridRowMinimumHeightC), PropertyLayoutGridRowMinimumHeight);
+ propertyTypeHash.insert(QLatin1String(layoutGridColumnMinimumWidthC), PropertyLayoutGridColumnMinimumWidth);
+ propertyTypeHash.insert(QLatin1String("buddy"), PropertyBuddy);
+ propertyTypeHash.insert(QLatin1String("geometry"), PropertyGeometry);
+ propertyTypeHash.insert(QLatin1String("checkable"), PropertyCheckable);
+ propertyTypeHash.insert(QLatin1String("accessibleName"), PropertyAccessibility);
+ propertyTypeHash.insert(QLatin1String("accessibleDescription"), PropertyAccessibility);
+ propertyTypeHash.insert(QLatin1String("windowTitle"), PropertyWindowTitle);
+ propertyTypeHash.insert(QLatin1String("windowIcon"), PropertyWindowIcon);
+ propertyTypeHash.insert(QLatin1String("windowFilePath"), PropertyWindowFilePath);
+ propertyTypeHash.insert(QLatin1String("windowOpacity"), PropertyWindowOpacity);
+ propertyTypeHash.insert(QLatin1String("windowIconText"), PropertyWindowIconText);
+ propertyTypeHash.insert(QLatin1String("windowModality"), PropertyWindowModality);
+ propertyTypeHash.insert(QLatin1String("windowModified"), PropertyWindowModified);
+ propertyTypeHash.insert(QLatin1String("styleSheet"), PropertyStyleSheet);
+ }
+ return propertyTypeHash.value(name, PropertyNone);
+}
+
+QDesignerPropertySheet::QDesignerPropertySheet(QObject *object, QObject *parent) :
+ QObject(parent),
+ d(new QDesignerPropertySheetPrivate(this, object, parent))
+{
+ typedef QDesignerPropertySheetPrivate::Info Info;
+ const QDesignerMetaObjectInterface *baseMeta = d->m_meta;
+
+ while (baseMeta &&baseMeta->className().startsWith(QLatin1String("QDesigner"))) {
+ baseMeta = baseMeta->superClass();
+ }
+ Q_ASSERT(baseMeta != 0);
+
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(d->m_object);
+ d->m_fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow);
+ if (d->m_fwb) {
+ d->m_pixmapCache = d->m_fwb->pixmapCache();
+ d->m_iconCache = d->m_fwb->iconCache();
+ d->m_fwb->addReloadablePropertySheet(this, object);
+ }
+
+ for (int index=0; index<count(); ++index) {
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ const QString name = p->name();
+ if (p->type() == QVariant::KeySequence) {
+ createFakeProperty(name);
+ } else {
+ setVisible(index, false); // use the default for `real' properties
+ }
+
+ QString pgroup = baseMeta->className();
+
+ if (const QDesignerMetaObjectInterface *pmeta = propertyIntroducedBy(baseMeta, index)) {
+ pgroup = pmeta->className();
+ }
+
+ Info &info = d->ensureInfo(index);
+ info.group = pgroup;
+ info.propertyType = propertyTypeFromName(name);
+
+ if (p->type() == QVariant::Cursor || p->type() == QVariant::Icon || p->type() == QVariant::Pixmap) {
+ info.defaultValue = p->read(d->m_object);
+ if (p->type() == QVariant::Icon || p->type() == QVariant::Pixmap)
+ d->addResourceProperty(index, p->type());
+ } else if (p->type() == QVariant::String) {
+ d->addStringProperty(index);
+ } else if (p->type() == QVariant::KeySequence) {
+ d->addKeySequenceProperty(index);
+ }
+ }
+
+ if (object->isWidgetType()) {
+ createFakeProperty(QLatin1String("focusPolicy"));
+ createFakeProperty(QLatin1String("cursor"));
+ createFakeProperty(QLatin1String("toolTip"));
+ createFakeProperty(QLatin1String("whatsThis"));
+ createFakeProperty(QLatin1String("acceptDrops"));
+ createFakeProperty(QLatin1String("dragEnabled"));
+ // windowModality is visible only for the main container, in which case the form windows enables it on loading
+ setVisible(createFakeProperty(QLatin1String("windowModality")), false);
+ if (qobject_cast<const QToolBar *>(d->m_object)) // prevent toolbars from being dragged off
+ createFakeProperty(QLatin1String("floatable"), QVariant(true));
+
+ if (d->m_canHaveLayoutAttributes) {
+ static const QString layoutGroup = QLatin1String("Layout");
+ const char* fakeLayoutProperties[] = {
+ layoutObjectNameC, layoutLeftMarginC, layoutTopMarginC, layoutRightMarginC, layoutBottomMarginC, layoutSpacingC, layoutHorizontalSpacingC, layoutVerticalSpacingC,
+ layoutFieldGrowthPolicyC, layoutRowWrapPolicyC, layoutLabelAlignmentC, layoutFormAlignmentC,
+ layoutboxStretchPropertyC, layoutGridRowStretchPropertyC, layoutGridColumnStretchPropertyC,
+ layoutGridRowMinimumHeightC, layoutGridColumnMinimumWidthC
+#ifdef USE_LAYOUT_SIZE_CONSTRAINT
+ , layoutSizeConstraintC
+#endif
+ };
+ const int fakeLayoutPropertyCount = sizeof(fakeLayoutProperties)/sizeof(const char*);
+ const int size = count();
+ for (int i = 0; i < fakeLayoutPropertyCount; i++) {
+ createFakeProperty(QLatin1String(fakeLayoutProperties[i]), 0);
+ setAttribute(size + i, true);
+ setPropertyGroup(size + i, layoutGroup);
+ }
+ }
+
+ if (d->m_objectType == ObjectLabel)
+ createFakeProperty(QLatin1String("buddy"), QVariant(QByteArray()));
+ /* We need to create a fake property since the property does not work
+ * for non-toplevel windows or on other systems than Mac and only if
+ * it is above a certain Mac OS version. */
+ if (qobject_cast<const QMainWindow *>(d->m_object))
+ createFakeProperty(QLatin1String("unifiedTitleAndToolBarOnMac"), false);
+ }
+
+ if (qobject_cast<const QDialog*>(object)) {
+ createFakeProperty(QLatin1String("modal"));
+ }
+ if (qobject_cast<const QDockWidget*>(object)) {
+ createFakeProperty(QLatin1String("floating"));
+ }
+
+ typedef QList<QByteArray> ByteArrayList;
+ const ByteArrayList names = object->dynamicPropertyNames();
+ if (!names.empty()) {
+ const ByteArrayList::const_iterator cend = names.constEnd();
+ for (ByteArrayList::const_iterator it = names.constBegin(); it != cend; ++it) {
+ const char* cName = it->constData();
+ const QString name = QString::fromLatin1(cName);
+ const int idx = addDynamicProperty(name, object->property(cName));
+ if (idx != -1)
+ d->ensureInfo(idx).kind = QDesignerPropertySheetPrivate::DefaultDynamicProperty;
+ }
+ }
+}
+
+QDesignerPropertySheet::~QDesignerPropertySheet()
+{
+ if (d->m_fwb)
+ d->m_fwb->removeReloadablePropertySheet(this);
+ delete d;
+}
+
+QObject *QDesignerPropertySheet::object() const
+{
+ return d->m_object;
+}
+
+bool QDesignerPropertySheet::dynamicPropertiesAllowed() const
+{
+ return true;
+}
+
+bool QDesignerPropertySheet::canAddDynamicProperty(const QString &propName) const
+{
+ const int index = d->m_meta->indexOfProperty(propName);
+ if (index != -1)
+ return false; // property already exists and is not a dynamic one
+ if (d->m_addIndex.contains(propName)) {
+ const int idx = d->m_addIndex.value(propName);
+ if (isVisible(idx))
+ return false; // dynamic property already exists
+ else
+ return true;
+ }
+ if (!QDesignerPropertySheet::internalDynamicPropertiesEnabled() && propName.startsWith(QLatin1String("_q_")))
+ return false;
+ return true;
+}
+
+int QDesignerPropertySheet::addDynamicProperty(const QString &propName, const QVariant &value)
+{
+ typedef QDesignerPropertySheetPrivate::Info Info;
+ if (!value.isValid())
+ return -1; // property has invalid type
+ if (!canAddDynamicProperty(propName))
+ return -1;
+
+ QVariant v = value;
+ if (value.type() == QVariant::Icon)
+ v = qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
+ else if (value.type() == QVariant::Pixmap)
+ v = qVariantFromValue(qdesigner_internal::PropertySheetPixmapValue());
+ else if (value.type() == QVariant::String)
+ v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
+ else if (value.type() == QVariant::KeySequence)
+ v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue());
+
+
+ if (d->m_addIndex.contains(propName)) {
+ const int idx = d->m_addIndex.value(propName);
+ // have to be invisible, this was checked in canAddDynamicProperty() method
+ setVisible(idx, true);
+ d->m_addProperties.insert(idx, v);
+ setChanged(idx, false);
+ const int index = d->m_meta->indexOfProperty(propName);
+ Info &info = d->ensureInfo(index);
+ info.defaultValue = value;
+ info.kind = QDesignerPropertySheetPrivate::DynamicProperty;
+ if (value.type() == QVariant::Icon || value.type() == QVariant::Pixmap)
+ d->addResourceProperty(idx, value.type());
+ else if (value.type() == QVariant::String)
+ d->addStringProperty(idx);
+ else if (value.type() == QVariant::KeySequence)
+ d->addKeySequenceProperty(idx);
+ return idx;
+ }
+
+ const int index = count();
+ d->m_addIndex.insert(propName, index);
+ d->m_addProperties.insert(index, v);
+ Info &info = d->ensureInfo(index);
+ info.visible = true;
+ info.changed = false;
+ info.defaultValue = value;
+ info.kind = QDesignerPropertySheetPrivate::DynamicProperty;
+ setPropertyGroup(index, tr("Dynamic Properties"));
+ if (value.type() == QVariant::Icon || value.type() == QVariant::Pixmap)
+ d->addResourceProperty(index, value.type());
+ else if (value.type() == QVariant::String)
+ d->addStringProperty(index);
+ else if (value.type() == QVariant::KeySequence)
+ d->addKeySequenceProperty(index);
+ return index;
+}
+
+bool QDesignerPropertySheet::removeDynamicProperty(int index)
+{
+ if (!d->m_addIndex.contains(propertyName(index)))
+ return false;
+
+ setVisible(index, false);
+ return true;
+}
+
+bool QDesignerPropertySheet::isDynamic(int index) const
+{
+ if (!d->m_addProperties.contains(index))
+ return false;
+
+ switch (propertyType(index)) {
+ case PropertyBuddy:
+ if (d->m_objectType == ObjectLabel)
+ return false;
+ break;
+ case PropertyLayoutLeftMargin:
+ case PropertyLayoutTopMargin:
+ case PropertyLayoutRightMargin:
+ case PropertyLayoutBottomMargin:
+ case PropertyLayoutSpacing:
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ case PropertyLayoutObjectName:
+ case PropertyLayoutSizeConstraint:
+ case PropertyLayoutFieldGrowthPolicy:
+ case PropertyLayoutRowWrapPolicy:
+ case PropertyLayoutLabelAlignment:
+ case PropertyLayoutFormAlignment:
+ case PropertyLayoutBoxStretch:
+ case PropertyLayoutGridRowStretch:
+ case PropertyLayoutGridColumnStretch:
+ case PropertyLayoutGridRowMinimumHeight:
+ case PropertyLayoutGridColumnMinimumWidth:
+ if (d->m_object->isWidgetType() && d->m_canHaveLayoutAttributes)
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool QDesignerPropertySheet::isDynamicProperty(int index) const
+{
+ // Do not complain here, as an invalid index might be encountered
+ // if someone implements a property sheet only, omitting the dynamic sheet.
+ if (index < 0 || index >= count())
+ return false;
+ return d->m_info.value(index).kind == QDesignerPropertySheetPrivate::DynamicProperty;
+}
+
+bool QDesignerPropertySheet::isDefaultDynamicProperty(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ return d->m_info.value(index).kind == QDesignerPropertySheetPrivate::DefaultDynamicProperty;
+}
+
+bool QDesignerPropertySheet::isResourceProperty(int index) const
+{
+ return d->isResourceProperty(index);
+}
+
+QVariant QDesignerPropertySheet::defaultResourceProperty(int index) const
+{
+ return d->defaultResourceProperty(index);
+}
+
+qdesigner_internal::DesignerPixmapCache *QDesignerPropertySheet::pixmapCache() const
+{
+ return d->m_pixmapCache;
+}
+
+void QDesignerPropertySheet::setPixmapCache(qdesigner_internal::DesignerPixmapCache *cache)
+{
+ d->m_pixmapCache = cache;
+}
+
+qdesigner_internal::DesignerIconCache *QDesignerPropertySheet::iconCache() const
+{
+ return d->m_iconCache;
+}
+
+void QDesignerPropertySheet::setIconCache(qdesigner_internal::DesignerIconCache *cache)
+{
+ d->m_iconCache = cache;
+}
+
+int QDesignerPropertySheet::createFakeProperty(const QString &propertyName, const QVariant &value)
+{
+ typedef QDesignerPropertySheetPrivate::Info Info;
+ // fake properties
+ const int index = d->m_meta->indexOfProperty(propertyName);
+ if (index != -1) {
+ if (!(d->m_meta->property(index)->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute))
+ return -1;
+ Info &info = d->ensureInfo(index);
+ info.visible = false;
+ info.kind = QDesignerPropertySheetPrivate::FakeProperty;
+ QVariant v = value.isValid() ? value : metaProperty(index);
+ if (v.type() == QVariant::String)
+ v = qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
+ if (v.type() == QVariant::KeySequence)
+ v = qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue());
+ d->m_fakeProperties.insert(index, v);
+ return index;
+ }
+ if (!value.isValid())
+ return -1;
+
+ const int newIndex = count();
+ d->m_addIndex.insert(propertyName, newIndex);
+ d->m_addProperties.insert(newIndex, value);
+ Info &info = d->ensureInfo(newIndex);
+ info.propertyType = propertyTypeFromName(propertyName);
+ info.kind = QDesignerPropertySheetPrivate::FakeProperty;
+ return newIndex;
+}
+
+bool QDesignerPropertySheet::isAdditionalProperty(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ return d->m_addProperties.contains(index);
+}
+
+bool QDesignerPropertySheet::isFakeProperty(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ // additional properties must be fake
+ return (d->m_fakeProperties.contains(index) || isAdditionalProperty(index));
+}
+
+int QDesignerPropertySheet::count() const
+{
+ return d->count();
+}
+
+int QDesignerPropertySheet::indexOf(const QString &name) const
+{
+ int index = d->m_meta->indexOfProperty(name);
+
+ if (index == -1)
+ index = d->m_addIndex.value(name, -1);
+
+ return index;
+}
+
+QDesignerPropertySheet::PropertyType QDesignerPropertySheet::propertyType(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return PropertyNone;
+ return d->propertyType(index);
+}
+
+QDesignerPropertySheet::ObjectType QDesignerPropertySheet::objectType() const
+{
+ return d->m_objectType;
+}
+
+QString QDesignerPropertySheet::propertyName(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return QString();
+ if (isAdditionalProperty(index))
+ return d->m_addIndex.key(index);
+
+ return d->m_meta->property(index)->name();
+}
+
+QString QDesignerPropertySheet::propertyGroup(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return QString();
+ const QString g = d->m_info.value(index).group;
+
+ if (!g.isEmpty())
+ return g;
+
+ if (propertyType(index) == PropertyAccessibility)
+ return QString::fromUtf8("Accessibility");
+
+ if (isAdditionalProperty(index))
+ return d->m_meta->className();
+
+ return g;
+}
+
+void QDesignerPropertySheet::setPropertyGroup(int index, const QString &group)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ d->ensureInfo(index).group = group;
+}
+
+QVariant QDesignerPropertySheet::property(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return QVariant();
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ return layoutPropertySheet->property(newIndex);
+ return QVariant();
+ }
+ }
+ }
+ return d->m_addProperties.value(index);
+ }
+
+ if (isFakeProperty(index)) {
+ return d->m_fakeProperties.value(index);
+ }
+
+ if (d->isResourceProperty(index))
+ return d->resourceProperty(index);
+
+ if (d->isStringProperty(index)) {
+ QString strValue = metaProperty(index).toString();
+ qdesigner_internal::PropertySheetStringValue value = d->stringProperty(index);
+ if (strValue != value.value()) {
+ value.setValue(strValue);
+ d->setStringProperty(index, value); // cache it
+ }
+ return qVariantFromValue(value);
+ }
+
+ if (d->isKeySequenceProperty(index)) {
+ QKeySequence keyValue = qVariantValue<QKeySequence>(metaProperty(index));
+ qdesigner_internal::PropertySheetKeySequenceValue value = d->keySequenceProperty(index);
+ if (keyValue != value.value()) {
+ value.setValue(keyValue);
+ d->setKeySequenceProperty(index, value); // cache it
+ }
+ return qVariantFromValue(value);
+ }
+
+ return metaProperty(index);
+}
+
+QVariant QDesignerPropertySheet::metaProperty(int index) const
+{
+ Q_ASSERT(!isFakeProperty(index));
+
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ QVariant v = p->read(d->m_object);
+ switch (p->kind()) {
+ case QDesignerMetaPropertyInterface::FlagKind: {
+ qdesigner_internal::PropertySheetFlagValue psflags = qdesigner_internal::PropertySheetFlagValue(v.toInt(), designerMetaFlagsFor(p->enumerator()));
+ qVariantSetValue(v, psflags);
+ }
+ break;
+ case QDesignerMetaPropertyInterface::EnumKind: {
+ qdesigner_internal::PropertySheetEnumValue pse = qdesigner_internal::PropertySheetEnumValue(v.toInt(), designerMetaEnumFor(p->enumerator()));
+ qVariantSetValue(v, pse);
+ }
+ break;
+ case QDesignerMetaPropertyInterface::OtherKind:
+ break;
+ }
+ return v;
+}
+
+QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant &value) const
+{
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value))
+ return qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(value).value;
+
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value))
+ return qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(value).value;
+
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetStringValue>(value))
+ return qVariantValue<qdesigner_internal::PropertySheetStringValue>(value).value();
+
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetKeySequenceValue>(value))
+ return qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value).value();
+
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetPixmapValue>(value)) {
+ const QString path = qVariantValue<qdesigner_internal::PropertySheetPixmapValue>(value).path();
+ if (path.isEmpty())
+ return defaultResourceProperty(index);
+ if (d->m_pixmapCache) {
+ return d->m_pixmapCache->pixmap(qvariant_cast<qdesigner_internal::PropertySheetPixmapValue>(value));
+ }
+ }
+
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetIconValue>(value)) {
+ const int pathCount = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value).paths().count();
+ if (pathCount == 0)
+ return defaultResourceProperty(index);
+ if (d->m_iconCache)
+ return d->m_iconCache->icon(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value));
+ }
+
+ return value;
+}
+
+void QDesignerPropertySheet::setFakeProperty(int index, const QVariant &value)
+{
+ Q_ASSERT(isFakeProperty(index));
+
+ QVariant &v = d->m_fakeProperties[index];
+
+ // set resource properties also (if we are going to have fake resource properties)
+ if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(value) || qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(value)) {
+ v = value;
+ } else if (qVariantCanConvert<qdesigner_internal::PropertySheetFlagValue>(v)) {
+ qdesigner_internal::PropertySheetFlagValue f = qvariant_cast<qdesigner_internal::PropertySheetFlagValue>(v);
+ f.value = value.toInt();
+ qVariantSetValue(v, f);
+ Q_ASSERT(value.type() == QVariant::Int);
+ } else if (qVariantCanConvert<qdesigner_internal::PropertySheetEnumValue>(v)) {
+ qdesigner_internal::PropertySheetEnumValue e = qvariant_cast<qdesigner_internal::PropertySheetEnumValue>(v);
+ e.value = value.toInt();
+ qVariantSetValue(v, e);
+ Q_ASSERT(value.type() == QVariant::Int);
+ } else {
+ v = value;
+ }
+}
+
+void QDesignerPropertySheet::clearFakeProperties()
+{
+ d->m_fakeProperties.clear();
+}
+
+// Buddy needs to be byte array, else uic won't work
+static QVariant toByteArray(const QVariant &value) {
+ if (value.type() == QVariant::ByteArray)
+ return value;
+ const QByteArray ba = value.toString().toUtf8();
+ return QVariant(ba);
+}
+
+void QDesignerPropertySheet::setProperty(int index, const QVariant &value)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ if (isAdditionalProperty(index)) {
+ if (d->m_objectType == ObjectLabel && propertyType(index) == PropertyBuddy) {
+ QFormBuilderExtra::applyBuddy(value.toString(), QFormBuilderExtra::BuddyApplyVisibleOnly, qobject_cast<QLabel *>(d->m_object));
+ d->m_addProperties[index] = toByteArray(value);
+ return;
+ }
+
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ layoutPropertySheet->setProperty(newIndex, value);
+ }
+ }
+ }
+
+ if (isDynamicProperty(index)) {
+ if (d->isResourceProperty(index))
+ d->setResourceProperty(index, value);
+ if (d->isStringProperty(index))
+ d->setStringProperty(index, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value));
+ if (d->isKeySequenceProperty(index))
+ d->setKeySequenceProperty(index, qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value));
+ d->m_object->setProperty(propertyName(index).toUtf8(), resolvePropertyValue(index, value));
+ if (d->m_object->isWidgetType()) {
+ QWidget *w = qobject_cast<QWidget *>(d->m_object);
+ w->setStyleSheet(w->styleSheet());
+ }
+ }
+ d->m_addProperties[index] = value;
+ } else if (isFakeProperty(index)) {
+ setFakeProperty(index, value);
+ } else {
+ if (d->isResourceProperty(index))
+ d->setResourceProperty(index, value);
+ if (d->isStringProperty(index))
+ d->setStringProperty(index, qVariantValue<qdesigner_internal::PropertySheetStringValue>(value));
+ if (d->isKeySequenceProperty(index))
+ d->setKeySequenceProperty(index, qVariantValue<qdesigner_internal::PropertySheetKeySequenceValue>(value));
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ p->write(d->m_object, resolvePropertyValue(index, value));
+ if (qobject_cast<QGroupBox *>(d->m_object) && propertyType(index) == PropertyCheckable) {
+ const int idx = indexOf(QLatin1String("focusPolicy"));
+ if (!isChanged(idx)) {
+ qdesigner_internal::PropertySheetEnumValue e = qVariantValue<qdesigner_internal::PropertySheetEnumValue>(property(idx));
+ if (value.toBool()) {
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(idx);
+ p->write(d->m_object, Qt::NoFocus);
+ e.value = Qt::StrongFocus;
+ QVariant v;
+ qVariantSetValue(v, e);
+ setFakeProperty(idx, v);
+ } else {
+ e.value = Qt::NoFocus;
+ QVariant v;
+ qVariantSetValue(v, e);
+ setFakeProperty(idx, v);
+ }
+ }
+ }
+ }
+}
+
+bool QDesignerPropertySheet::hasReset(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index))
+ return d->m_info.value(index).reset;
+ return true;
+}
+
+bool QDesignerPropertySheet::reset(int index)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (d->isStringProperty(index))
+ setProperty(index, qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
+ if (d->isKeySequenceProperty(index))
+ setProperty(index, qVariantFromValue(qdesigner_internal::PropertySheetKeySequenceValue()));
+ if (d->isResourceProperty(index)) {
+ setProperty(index, d->emptyResourceProperty(index));
+ return true;
+ } else if (isDynamic(index)) {
+ const QString propName = propertyName(index);
+ const QVariant oldValue = d->m_addProperties.value(index);
+ const QVariant newValue = d->m_info.value(index).defaultValue;
+ if (oldValue == newValue)
+ return true;
+ d->m_object->setProperty(propName.toUtf8(), newValue);
+ d->m_addProperties[index] = newValue;
+ return true;
+ } else if (!d->m_info.value(index).defaultValue.isNull()) {
+ setProperty(index, d->m_info.value(index).defaultValue);
+ return true;
+ }
+ if (isAdditionalProperty(index)) {
+ const PropertyType pType = propertyType(index);
+ if (d->m_objectType == ObjectLabel && pType == PropertyBuddy) {
+ setProperty(index, QVariant(QByteArray()));
+ return true;
+ }
+ if (isFakeLayoutProperty(index)) {
+ // special properties
+ switch (pType) {
+ case PropertyLayoutObjectName:
+ setProperty(index, QString());
+ return true;
+ case PropertyLayoutSizeConstraint:
+ setProperty(index, QVariant(QLayout::SetDefaultConstraint));
+ return true;
+ case PropertyLayoutBoxStretch:
+ case PropertyLayoutGridRowStretch:
+ case PropertyLayoutGridColumnStretch:
+ case PropertyLayoutGridRowMinimumHeight:
+ case PropertyLayoutGridColumnMinimumWidth:
+ case PropertyLayoutFieldGrowthPolicy:
+ case PropertyLayoutRowWrapPolicy:
+ case PropertyLayoutLabelAlignment:
+ case PropertyLayoutFormAlignment: {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet)
+ return layoutPropertySheet->reset(layoutPropertySheet->indexOf(d->transformLayoutPropertyName(index)));
+ }
+ break;
+ default:
+ break;
+ }
+ // special margins
+ int value = -1;
+ switch (d->m_objectType) {
+ case ObjectQ3GroupBox: {
+ const QWidget *w = qobject_cast<const QWidget *>(d->m_object);
+ switch (pType) {
+ case PropertyLayoutLeftMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
+ break;
+ case PropertyLayoutTopMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutTopMargin);
+ break;
+ case PropertyLayoutRightMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutRightMargin);
+ break;
+ case PropertyLayoutBottomMargin:
+ value = w->style()->pixelMetric(QStyle::PM_LayoutBottomMargin);
+ break;
+ case PropertyLayoutSpacing:
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ value = -1;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case ObjectLayoutWidget:
+ if (pType == PropertyLayoutLeftMargin ||
+ pType == PropertyLayoutTopMargin ||
+ pType == PropertyLayoutRightMargin ||
+ pType == PropertyLayoutBottomMargin)
+ value = 0;
+ break;
+ default:
+ break;
+ }
+ setProperty(index, value);
+ return true;
+ }
+ return false;
+ } else if (isFakeProperty(index)) {
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ const bool result = p->reset(d->m_object);
+ d->m_fakeProperties[index] = p->read(d->m_object);
+ return result;
+ } else if (propertyType(index) == PropertyGeometry && d->m_object->isWidgetType()) {
+ if (QWidget *w = qobject_cast<QWidget*>(d->m_object)) {
+ QWidget *widget = w;
+ if (qdesigner_internal::Utils::isCentralWidget(d->m_fwb, widget) && d->m_fwb->parentWidget())
+ widget = d->m_fwb->parentWidget();
+
+ if (widget != w && widget->parentWidget()) {
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ widget->parentWidget()->adjustSize();
+ }
+ QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ widget->adjustSize();
+ return true;
+ }
+ }
+ // ### TODO: reset for fake properties.
+
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ return p->reset(d->m_object);
+}
+
+bool QDesignerPropertySheet::isChanged(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ return layoutPropertySheet->isChanged(newIndex);
+ return false;
+ }
+ }
+ }
+ }
+ return d->m_info.value(index).changed;
+}
+
+void QDesignerPropertySheet::setChanged(int index, bool changed)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index)) {
+ QDesignerPropertySheetExtension *layoutPropertySheet;
+ if (d->layout(&layoutPropertySheet) && layoutPropertySheet) {
+ const QString newPropName = d->transformLayoutPropertyName(index);
+ if (!newPropName.isEmpty()) {
+ const int newIndex = layoutPropertySheet->indexOf(newPropName);
+ if (newIndex != -1)
+ layoutPropertySheet->setChanged(newIndex, changed);
+ }
+ }
+ }
+ }
+ if (d->isReloadableProperty(index)) {
+ if (d->m_fwb) {
+ if (changed)
+ d->m_fwb->addReloadableProperty(this, index);
+ else
+ d->m_fwb->removeReloadableProperty(this, index);
+ }
+ }
+ d->ensureInfo(index).changed = changed;
+}
+
+bool QDesignerPropertySheet::isFakeLayoutProperty(int index) const
+{
+ if (!isAdditionalProperty(index))
+ return false;
+
+ switch (propertyType(index)) {
+ case PropertyLayoutObjectName:
+ case PropertyLayoutSizeConstraint:
+ return true;
+ case PropertyLayoutLeftMargin:
+ case PropertyLayoutTopMargin:
+ case PropertyLayoutRightMargin:
+ case PropertyLayoutBottomMargin:
+ case PropertyLayoutSpacing:
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ case PropertyLayoutFieldGrowthPolicy:
+ case PropertyLayoutRowWrapPolicy:
+ case PropertyLayoutLabelAlignment:
+ case PropertyLayoutFormAlignment:
+ case PropertyLayoutBoxStretch:
+ case PropertyLayoutGridRowStretch:
+ case PropertyLayoutGridColumnStretch:
+ case PropertyLayoutGridRowMinimumHeight:
+ case PropertyLayoutGridColumnMinimumWidth:
+ return d->m_canHaveLayoutAttributes;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool QDesignerPropertySheet::isVisible(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+
+ const PropertyType type = propertyType(index);
+ if (isAdditionalProperty(index)) {
+ if (isFakeLayoutProperty(index) && d->m_object->isWidgetType()) {
+ const QLayout *currentLayout = d->layout();
+ if (!currentLayout)
+ return false;
+ const int visibleMask = qdesigner_internal::LayoutProperties::visibleProperties(currentLayout);
+ switch (type) {
+ case PropertyLayoutSpacing:
+ return visibleMask & qdesigner_internal::LayoutProperties::SpacingProperty;
+ case PropertyLayoutHorizontalSpacing:
+ case PropertyLayoutVerticalSpacing:
+ return visibleMask & qdesigner_internal::LayoutProperties::HorizSpacingProperty;
+ case PropertyLayoutFieldGrowthPolicy:
+ return visibleMask & qdesigner_internal::LayoutProperties::FieldGrowthPolicyProperty;
+ case PropertyLayoutRowWrapPolicy:
+ return visibleMask & qdesigner_internal::LayoutProperties::RowWrapPolicyProperty;
+ case PropertyLayoutLabelAlignment:
+ return visibleMask & qdesigner_internal::LayoutProperties::LabelAlignmentProperty;
+ case PropertyLayoutFormAlignment:
+ return visibleMask & qdesigner_internal::LayoutProperties::FormAlignmentProperty;
+ case PropertyLayoutBoxStretch:
+ return visibleMask & qdesigner_internal::LayoutProperties::BoxStretchProperty;
+ case PropertyLayoutGridRowStretch:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridRowStretchProperty;
+ case PropertyLayoutGridColumnStretch:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridColumnStretchProperty;
+ case PropertyLayoutGridRowMinimumHeight:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridRowMinimumHeightProperty;
+ case PropertyLayoutGridColumnMinimumWidth:
+ return visibleMask & qdesigner_internal::LayoutProperties::GridColumnMinimumWidthProperty;
+ default:
+ break;
+ }
+ return true;
+ }
+ return d->m_info.value(index).visible;
+ }
+
+ if (isFakeProperty(index)) {
+ if (type == PropertyWindowModality) // Hidden for child widgets
+ return d->m_info.value(index).visible;
+ return true;
+ }
+
+ const bool visible = d->m_info.value(index).visible;
+ switch (type) {
+ case PropertyWindowTitle:
+ case PropertyWindowIcon:
+ case PropertyWindowFilePath:
+ case PropertyWindowOpacity:
+ case PropertyWindowIconText:
+ case PropertyWindowModified:
+ return visible;
+ default:
+ if (visible)
+ return true;
+ break;
+ }
+
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ if (!(p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess))
+ return false;
+
+ // Enabled handling
+ return (p->attributes(d->m_object) & QDesignerMetaPropertyInterface::DesignableAttribute) ||
+ (p->attributes() & QDesignerMetaPropertyInterface::DesignableAttribute);
+}
+
+void QDesignerPropertySheet::setVisible(int index, bool visible)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ d->ensureInfo(index).visible = visible;
+}
+
+bool QDesignerPropertySheet::isEnabled(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index))
+ return true;
+
+ if (isFakeProperty(index))
+ return true;
+
+ // Grey out geometry of laid-out widgets (including splitter)
+ if (propertyType(index) == PropertyGeometry && d->m_object->isWidgetType()) {
+ bool isManaged;
+ const qdesigner_internal::LayoutInfo::Type lt = qdesigner_internal::LayoutInfo::laidoutWidgetType(d->m_core, qobject_cast<QWidget *>(d->m_object), &isManaged);
+ return !isManaged || lt == qdesigner_internal::LayoutInfo::NoLayout;
+ }
+
+ if (d->m_info.value(index).visible == true) // Sun CC 5.5 oddity, wants true
+ return true;
+
+ const QDesignerMetaPropertyInterface *p = d->m_meta->property(index);
+ return (p->accessFlags() & QDesignerMetaPropertyInterface::WriteAccess) &&
+ (p->attributes(d->m_object) & QDesignerMetaPropertyInterface::DesignableAttribute);
+}
+
+bool QDesignerPropertySheet::isAttribute(int index) const
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return false;
+ if (isAdditionalProperty(index))
+ return d->m_info.value(index).attribute;
+
+ if (isFakeProperty(index))
+ return false;
+
+ return d->m_info.value(index).attribute;
+}
+
+void QDesignerPropertySheet::setAttribute(int index, bool attribute)
+{
+ if (d->invalidIndex(Q_FUNC_INFO, index))
+ return;
+ d->ensureInfo(index).attribute = attribute;
+}
+
+QDesignerFormEditorInterface *QDesignerPropertySheet::core() const
+{
+ return d->m_core;
+}
+
+bool QDesignerPropertySheet::internalDynamicPropertiesEnabled()
+{
+ return QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled;
+}
+
+void QDesignerPropertySheet::setInternalDynamicPropertiesEnabled(bool v)
+{
+ QDesignerPropertySheetPrivate::m_internalDynamicPropertiesEnabled = v;
+}
+
+// ---------- QDesignerAbstractPropertySheetFactory
+
+struct QDesignerAbstractPropertySheetFactory::PropertySheetFactoryPrivate {
+ PropertySheetFactoryPrivate();
+ const QString m_propertySheetId;
+ const QString m_dynamicPropertySheetId;
+
+ typedef QMap<QObject*, QObject*> ExtensionMap;
+ ExtensionMap m_extensions;
+ typedef QHash<QObject*, bool> ExtendedSet;
+ ExtendedSet m_extended;
+};
+
+QDesignerAbstractPropertySheetFactory::PropertySheetFactoryPrivate::PropertySheetFactoryPrivate() :
+ m_propertySheetId(Q_TYPEID(QDesignerPropertySheetExtension)),
+ m_dynamicPropertySheetId(Q_TYPEID(QDesignerDynamicPropertySheetExtension))
+{
+}
+
+// ---------- QDesignerAbstractPropertySheetFactory
+
+
+QDesignerAbstractPropertySheetFactory::QDesignerAbstractPropertySheetFactory(QExtensionManager *parent) :
+ QExtensionFactory(parent),
+ m_impl(new PropertySheetFactoryPrivate)
+{
+}
+
+QDesignerAbstractPropertySheetFactory::~QDesignerAbstractPropertySheetFactory()
+{
+ delete m_impl;
+}
+
+QObject *QDesignerAbstractPropertySheetFactory::extension(QObject *object, const QString &iid) const
+{
+ typedef PropertySheetFactoryPrivate::ExtensionMap ExtensionMap;
+ if (!object)
+ return 0;
+
+ if (iid != m_impl->m_propertySheetId && iid != m_impl->m_dynamicPropertySheetId)
+ return 0;
+
+ ExtensionMap::iterator it = m_impl->m_extensions.find(object);
+ if (it == m_impl->m_extensions.end()) {
+ if (QObject *ext = createPropertySheet(object, const_cast<QDesignerAbstractPropertySheetFactory*>(this))) {
+ connect(ext, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ it = m_impl->m_extensions.insert(object, ext);
+ }
+ }
+
+ if (!m_impl->m_extended.contains(object)) {
+ connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ m_impl->m_extended.insert(object, true);
+ }
+
+ if (it == m_impl->m_extensions.end())
+ return 0;
+
+ return it.value();
+}
+
+void QDesignerAbstractPropertySheetFactory::objectDestroyed(QObject *object)
+{
+ QMutableMapIterator<QObject*, QObject*> it(m_impl->m_extensions);
+ while (it.hasNext()) {
+ it.next();
+
+ QObject *o = it.key();
+ if (o == object || object == it.value()) {
+ it.remove();
+ }
+ }
+
+ m_impl->m_extended.remove(object);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet_p.h b/tools/designer/src/lib/shared/qdesigner_propertysheet_p.h
new file mode 100644
index 0000000000..8a25baf1ee
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_propertysheet_p.h
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_PROPERTYSHEET_H
+#define QDESIGNER_PROPERTYSHEET_H
+
+#include "shared_global_p.h"
+#include "dynamicpropertysheet.h"
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/default_extensionfactory.h>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QVariant>
+#include <QtCore/QPair>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QLayout;
+class QDesignerFormEditorInterface;
+class QDesignerPropertySheetPrivate;
+
+namespace qdesigner_internal
+{
+ class DesignerPixmapCache;
+ class DesignerIconCache;
+ class FormWindowBase;
+}
+
+class QDESIGNER_SHARED_EXPORT QDesignerPropertySheet: public QObject, public QDesignerPropertySheetExtension, public QDesignerDynamicPropertySheetExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension QDesignerDynamicPropertySheetExtension)
+public:
+ explicit QDesignerPropertySheet(QObject *object, QObject *parent = 0);
+ virtual ~QDesignerPropertySheet();
+
+ virtual int indexOf(const QString &name) const;
+
+ virtual int count() const;
+ virtual QString propertyName(int index) const;
+
+ virtual QString propertyGroup(int index) const;
+ virtual void setPropertyGroup(int index, const QString &group);
+
+ virtual bool hasReset(int index) const;
+ virtual bool reset(int index);
+
+ virtual bool isAttribute(int index) const;
+ virtual void setAttribute(int index, bool b);
+
+ virtual bool isVisible(int index) const;
+ virtual void setVisible(int index, bool b);
+
+ virtual QVariant property(int index) const;
+ virtual void setProperty(int index, const QVariant &value);
+
+ virtual bool isChanged(int index) const;
+
+ virtual void setChanged(int index, bool changed);
+
+ virtual bool dynamicPropertiesAllowed() const;
+ virtual int addDynamicProperty(const QString &propertyName, const QVariant &value);
+ virtual bool removeDynamicProperty(int index);
+ virtual bool isDynamicProperty(int index) const;
+ virtual bool canAddDynamicProperty(const QString &propertyName) const;
+
+ bool isDefaultDynamicProperty(int index) const;
+
+ bool isResourceProperty(int index) const;
+ QVariant defaultResourceProperty(int index) const;
+
+ qdesigner_internal::DesignerPixmapCache *pixmapCache() const;
+ void setPixmapCache(qdesigner_internal::DesignerPixmapCache *cache);
+ qdesigner_internal::DesignerIconCache *iconCache() const;
+ void setIconCache(qdesigner_internal::DesignerIconCache *cache);
+ int createFakeProperty(const QString &propertyName, const QVariant &value = QVariant());
+
+ virtual bool isEnabled(int index) const;
+ QObject *object() const;
+
+ static bool internalDynamicPropertiesEnabled();
+ static void setInternalDynamicPropertiesEnabled(bool v);
+
+protected:
+ bool isAdditionalProperty(int index) const;
+ bool isFakeProperty(int index) const;
+ QVariant resolvePropertyValue(int index, const QVariant &value) const;
+ QVariant metaProperty(int index) const;
+ void setFakeProperty(int index, const QVariant &value);
+ void clearFakeProperties();
+
+ bool isFakeLayoutProperty(int index) const;
+ bool isDynamic(int index) const;
+ qdesigner_internal::FormWindowBase *formWindowBase() const;
+ QDesignerFormEditorInterface *core() const;
+
+public:
+ enum PropertyType { PropertyNone,
+ PropertyLayoutObjectName,
+ PropertyLayoutLeftMargin,
+ PropertyLayoutTopMargin,
+ PropertyLayoutRightMargin,
+ PropertyLayoutBottomMargin,
+ PropertyLayoutSpacing,
+ PropertyLayoutHorizontalSpacing,
+ PropertyLayoutVerticalSpacing,
+ PropertyLayoutSizeConstraint,
+ PropertyLayoutFieldGrowthPolicy,
+ PropertyLayoutRowWrapPolicy,
+ PropertyLayoutLabelAlignment,
+ PropertyLayoutFormAlignment,
+ PropertyLayoutBoxStretch,
+ PropertyLayoutGridRowStretch,
+ PropertyLayoutGridColumnStretch,
+ PropertyLayoutGridRowMinimumHeight,
+ PropertyLayoutGridColumnMinimumWidth,
+ PropertyBuddy,
+ PropertyAccessibility,
+ PropertyGeometry,
+ PropertyCheckable,
+ PropertyWindowTitle,
+ PropertyWindowIcon,
+ PropertyWindowFilePath,
+ PropertyWindowOpacity,
+ PropertyWindowIconText,
+ PropertyWindowModality,
+ PropertyWindowModified,
+ PropertyStyleSheet
+ };
+
+ enum ObjectType { ObjectNone, ObjectLabel, ObjectLayout, ObjectLayoutWidget, ObjectQ3GroupBox };
+
+ static ObjectType objectTypeFromObject(const QObject *o);
+ static PropertyType propertyTypeFromName(const QString &name);
+
+protected:
+ PropertyType propertyType(int index) const;
+ ObjectType objectType() const;
+
+private:
+ QDesignerPropertySheetPrivate *d;
+};
+
+/* Abstract base class for factories that register a property sheet that implements
+ * both QDesignerPropertySheetExtension and QDesignerDynamicPropertySheetExtension
+ * by multiple inheritance. The factory maintains ownership of
+ * the extension and returns it for both id's. */
+
+class QDESIGNER_SHARED_EXPORT QDesignerAbstractPropertySheetFactory: public QExtensionFactory
+{
+ Q_OBJECT
+ Q_INTERFACES(QAbstractExtensionFactory)
+public:
+ explicit QDesignerAbstractPropertySheetFactory(QExtensionManager *parent = 0);
+ virtual ~QDesignerAbstractPropertySheetFactory();
+
+ QObject *extension(QObject *object, const QString &iid) const;
+
+private slots:
+ void objectDestroyed(QObject *object);
+
+private:
+ virtual QObject *createPropertySheet(QObject *qObject, QObject *parent) const = 0;
+
+ struct PropertySheetFactoryPrivate;
+ PropertySheetFactoryPrivate *m_impl;
+};
+
+/* Convenience factory template for property sheets that implement
+ * QDesignerPropertySheetExtension and QDesignerDynamicPropertySheetExtension
+ * by multiple inheritance. */
+
+template <class Object, class PropertySheet>
+class QDesignerPropertySheetFactory : public QDesignerAbstractPropertySheetFactory {
+public:
+ explicit QDesignerPropertySheetFactory(QExtensionManager *parent = 0);
+
+ static void registerExtension(QExtensionManager *mgr);
+
+private:
+ // Does a qobject_cast on the object.
+ virtual QObject *createPropertySheet(QObject *qObject, QObject *parent) const;
+};
+
+template <class Object, class PropertySheet>
+QDesignerPropertySheetFactory<Object, PropertySheet>::QDesignerPropertySheetFactory(QExtensionManager *parent) :
+ QDesignerAbstractPropertySheetFactory(parent)
+{
+}
+
+template <class Object, class PropertySheet>
+QObject *QDesignerPropertySheetFactory<Object, PropertySheet>::createPropertySheet(QObject *qObject, QObject *parent) const
+{
+ Object *object = qobject_cast<Object *>(qObject);
+ if (!object)
+ return 0;
+ return new PropertySheet(object, parent);
+}
+
+template <class Object, class PropertySheet>
+void QDesignerPropertySheetFactory<Object, PropertySheet>::registerExtension(QExtensionManager *mgr)
+{
+ QDesignerPropertySheetFactory *factory = new QDesignerPropertySheetFactory(mgr);
+ mgr->registerExtensions(factory, Q_TYPEID(QDesignerPropertySheetExtension));
+ mgr->registerExtensions(factory, Q_TYPEID(QDesignerDynamicPropertySheetExtension));
+}
+
+
+// Standard property sheet
+typedef QDesignerPropertySheetFactory<QObject, QDesignerPropertySheet> QDesignerDefaultPropertySheetFactory;
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_PROPERTYSHEET_H
diff --git a/tools/designer/src/lib/shared/qdesigner_qsettings.cpp b/tools/designer/src/lib/shared/qdesigner_qsettings.cpp
new file mode 100644
index 0000000000..efea643f41
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_qsettings.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_qsettings_p.h"
+
+#include <QtCore/QSettings>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QTextStream>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+
+/*!
+ \class QDesignerSettingsSimple
+
+ \brief Implements QDesignerSettingsInterface by calls to QSettings
+ */
+
+QDesignerQSettings::QDesignerQSettings() :
+ m_settings(qApp->organizationName(), settingsApplicationName())
+{
+}
+
+QString QDesignerQSettings::settingsApplicationName()
+{
+ return qApp->applicationName();
+}
+
+void QDesignerQSettings::beginGroup(const QString &prefix)
+{
+ m_settings.beginGroup(prefix);
+}
+
+void QDesignerQSettings::endGroup()
+{
+ m_settings.endGroup();
+}
+
+bool QDesignerQSettings::contains(const QString &key) const
+{
+ return m_settings.contains(key);
+}
+
+void QDesignerQSettings::setValue(const QString &key, const QVariant &value)
+{
+ m_settings.setValue(key, value);
+}
+
+QVariant QDesignerQSettings::value(const QString &key, const QVariant &defaultValue) const
+{
+ return m_settings.value(key, defaultValue);
+}
+
+void QDesignerQSettings::remove(const QString &key)
+{
+ m_settings.remove(key);
+}
diff --git a/tools/designer/src/lib/shared/qdesigner_qsettings_p.h b/tools/designer/src/lib/shared/qdesigner_qsettings_p.h
new file mode 100644
index 0000000000..2ca749b589
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_qsettings_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_QSETTINGS_H
+#define QDESIGNER_QSETTINGS_H
+
+#include "abstractsettings_p.h"
+#include "shared_global_p.h"
+
+#include <QtCore/QSettings>
+
+QT_BEGIN_NAMESPACE
+
+// Implements QDesignerSettingsInterface by calls to QSettings
+class QDESIGNER_SHARED_EXPORT QDesignerQSettings : public QDesignerSettingsInterface
+{
+public:
+ QDesignerQSettings();
+
+ virtual void beginGroup(const QString &prefix);
+ virtual void endGroup();
+
+ virtual bool contains(const QString &key) const;
+ virtual void setValue(const QString &key, const QVariant &value);
+ virtual QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
+ virtual void remove(const QString &key);
+
+ // The application name to be used for settings. Allows for including
+ // the Qt version to prevent settings of different Qt versions from
+ // interfering.
+ static QString settingsApplicationName();
+
+private:
+ QSettings m_settings;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_QSETTINGS_H
diff --git a/tools/designer/src/lib/shared/qdesigner_stackedbox.cpp b/tools/designer/src/lib/shared/qdesigner_stackedbox.cpp
new file mode 100644
index 0000000000..c36ab9a617
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_stackedbox.cpp
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_stackedbox_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "orderdialog_p.h"
+#include "promotiontaskmenu_p.h"
+#include "widgetfactory_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QToolButton>
+#include <QtGui/QAction>
+#include <QtGui/qevent.h>
+#include <QtGui/QMenu>
+#include <QtGui/QStackedWidget>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+static QToolButton *createToolButton(QWidget *parent, Qt::ArrowType at, const QString &name) {
+ QToolButton *rc = new QToolButton();
+ rc->setAttribute(Qt::WA_NoChildEventsForParent, true);
+ rc->setParent(parent);
+ rc->setObjectName(name);
+ rc->setArrowType(at);
+ rc->setAutoRaise(true);
+ rc->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ rc->setFixedSize(QSize(15, 15));
+ return rc;
+}
+
+// --------------- QStackedWidgetPreviewEventFilter
+QStackedWidgetPreviewEventFilter::QStackedWidgetPreviewEventFilter(QStackedWidget *parent) :
+ QObject(parent),
+ m_buttonToolTipEnabled(false), // Not on preview
+ m_stackedWidget(parent),
+ m_prev(createToolButton(m_stackedWidget, Qt::LeftArrow, QLatin1String("__qt__passive_prev"))),
+ m_next(createToolButton(m_stackedWidget, Qt::RightArrow, QLatin1String("__qt__passive_next")))
+{
+ connect(m_prev, SIGNAL(clicked()), this, SLOT(prevPage()));
+ connect(m_next, SIGNAL(clicked()), this, SLOT(nextPage()));
+
+ updateButtons();
+ m_stackedWidget->installEventFilter(this);
+ m_prev->installEventFilter(this);
+ m_next->installEventFilter(this);
+}
+
+void QStackedWidgetPreviewEventFilter::install(QStackedWidget *stackedWidget)
+{
+ new QStackedWidgetPreviewEventFilter(stackedWidget);
+}
+
+void QStackedWidgetPreviewEventFilter::updateButtons()
+{
+ m_prev->move(m_stackedWidget->width() - 31, 1);
+ m_prev->show();
+ m_prev->raise();
+
+ m_next->move(m_stackedWidget->width() - 16, 1);
+ m_next->show();
+ m_next->raise();
+}
+
+void QStackedWidgetPreviewEventFilter::prevPage()
+{
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
+ fw->clearSelection();
+ fw->selectWidget(stackedWidget(), true);
+ }
+ const int count = m_stackedWidget->count();
+ if (count > 1) {
+ int newIndex = m_stackedWidget->currentIndex() - 1;
+ if (newIndex < 0)
+ newIndex = count - 1;
+ gotoPage(newIndex);
+ }
+}
+
+void QStackedWidgetPreviewEventFilter::nextPage()
+{
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
+ fw->clearSelection();
+ fw->selectWidget(stackedWidget(), true);
+ }
+ const int count = m_stackedWidget->count();
+ if (count > 1)
+ gotoPage((m_stackedWidget->currentIndex() + 1) % count);
+}
+
+bool QStackedWidgetPreviewEventFilter::eventFilter(QObject *watched, QEvent *event)
+{
+ if (watched->isWidgetType()) {
+ if (watched == m_stackedWidget) {
+ switch (event->type()) {
+ case QEvent::LayoutRequest:
+ updateButtons();
+ break;
+ case QEvent::ChildAdded:
+ case QEvent::ChildRemoved:
+ case QEvent::Resize:
+ case QEvent::Show:
+ updateButtons();
+ break;
+ default:
+ break;
+ }
+ }
+ if (m_buttonToolTipEnabled && (watched == m_next || watched == m_prev)) {
+ switch (event->type()) {
+ case QEvent::ToolTip:
+ updateButtonToolTip(watched); // Tooltip includes page number, so, refresh on demand
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+void QStackedWidgetPreviewEventFilter::gotoPage(int page)
+{
+ m_stackedWidget->setCurrentIndex(page);
+ updateButtons();
+}
+
+static inline QString stackedClassName(QStackedWidget *w)
+{
+ if (const QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(w))
+ return qdesigner_internal::WidgetFactory::classNameOf(fw->core(), w);
+ return QLatin1String("Stacked widget");
+}
+
+void QStackedWidgetPreviewEventFilter::updateButtonToolTip(QObject *o)
+{
+ QString className = QLatin1String("Stacked widget");
+ if (const QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_stackedWidget))
+ className = qdesigner_internal::WidgetFactory::classNameOf(fw->core(), m_stackedWidget);
+ if (o == m_prev) {
+ const QString msg = tr("Go to previous page of %1 '%2' (%3/%4).").arg(stackedClassName(m_stackedWidget)).arg(m_stackedWidget->objectName()).arg(m_stackedWidget->currentIndex() + 1).arg(m_stackedWidget->count());
+ m_prev->setToolTip(msg);
+ } else {
+ if (o == m_next) {
+ const QString msg = tr("Go to next page of %1 '%2' (%3/%4).").arg(stackedClassName(m_stackedWidget)).arg(m_stackedWidget->objectName()).arg(m_stackedWidget->currentIndex() + 1).arg(m_stackedWidget->count());
+ m_next->setToolTip(msg);
+ }
+ }
+}
+
+// --------------- QStackedWidgetEventFilter
+QStackedWidgetEventFilter::QStackedWidgetEventFilter(QStackedWidget *parent) :
+ QStackedWidgetPreviewEventFilter(parent),
+ m_actionPreviousPage(new QAction(tr("Previous Page"), this)),
+ m_actionNextPage(new QAction(tr("Next Page"), this)),
+ m_actionDeletePage(new QAction(tr("Delete"), this)),
+ m_actionInsertPage(new QAction(tr("Before Current Page"), this)),
+ m_actionInsertPageAfter(new QAction(tr("After Current Page"), this)),
+ m_actionChangePageOrder(new QAction(tr("Change Page Order..."), this)),
+ m_pagePromotionTaskMenu(new qdesigner_internal::PromotionTaskMenu(0, qdesigner_internal::PromotionTaskMenu::ModeSingleWidget, this))
+{
+ setButtonToolTipEnabled(true);
+ connect(m_actionPreviousPage, SIGNAL(triggered()), this, SLOT(prevPage()));
+ connect(m_actionNextPage, SIGNAL(triggered()), this, SLOT(nextPage()));
+ connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
+ connect(m_actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
+ connect(m_actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
+ connect(m_actionChangePageOrder, SIGNAL(triggered()), this, SLOT(changeOrder()));
+}
+
+void QStackedWidgetEventFilter::install(QStackedWidget *stackedWidget)
+{
+ new QStackedWidgetEventFilter(stackedWidget);
+}
+
+QStackedWidgetEventFilter *QStackedWidgetEventFilter::eventFilterOf(const QStackedWidget *stackedWidget)
+{
+ // Look for 1st order children only..otherwise, we might get filters of nested widgets
+ const QObjectList children = stackedWidget->children();
+ const QObjectList::const_iterator cend = children.constEnd();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
+ QObject *o = *it;
+ if (!o->isWidgetType())
+ if (QStackedWidgetEventFilter *ef = qobject_cast<QStackedWidgetEventFilter *>(o))
+ return ef;
+ }
+ return 0;
+}
+
+QMenu *QStackedWidgetEventFilter::addStackedWidgetContextMenuActions(const QStackedWidget *stackedWidget, QMenu *popup)
+{
+ QStackedWidgetEventFilter *filter = eventFilterOf(stackedWidget);
+ if (!filter)
+ return 0;
+ return filter->addContextMenuActions(popup);
+}
+
+void QStackedWidgetEventFilter::removeCurrentPage()
+{
+ if (stackedWidget()->currentIndex() == -1)
+ return;
+
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
+ qdesigner_internal::DeleteStackedWidgetPageCommand *cmd = new qdesigner_internal::DeleteStackedWidgetPageCommand(fw);
+ cmd->init(stackedWidget());
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QStackedWidgetEventFilter::changeOrder()
+{
+ QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget());
+
+ if (!fw)
+ return;
+
+ const QWidgetList oldPages = qdesigner_internal::OrderDialog::pagesOfContainer(fw->core(), stackedWidget());
+ const int pageCount = oldPages.size();
+ if (pageCount < 2)
+ return;
+
+ qdesigner_internal::OrderDialog dlg(fw);
+ dlg.setPageList(oldPages);
+ if (dlg.exec() == QDialog::Rejected)
+ return;
+
+ const QWidgetList newPages = dlg.pageList();
+ if (newPages == oldPages)
+ return;
+
+ fw->beginCommand(tr("Change Page Order"));
+ for(int i=0; i < pageCount; ++i) {
+ if (newPages.at(i) == stackedWidget()->widget(i))
+ continue;
+ qdesigner_internal::MoveStackedWidgetCommand *cmd = new qdesigner_internal::MoveStackedWidgetCommand(fw);
+ cmd->init(stackedWidget(), newPages.at(i), i);
+ fw->commandHistory()->push(cmd);
+ }
+ fw->endCommand();
+}
+
+void QStackedWidgetEventFilter::addPage()
+{
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
+ qdesigner_internal::AddStackedWidgetPageCommand *cmd = new qdesigner_internal::AddStackedWidgetPageCommand(fw);
+ cmd->init(stackedWidget(), qdesigner_internal::AddStackedWidgetPageCommand::InsertBefore);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QStackedWidgetEventFilter::addPageAfter()
+{
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
+ qdesigner_internal::AddStackedWidgetPageCommand *cmd = new qdesigner_internal::AddStackedWidgetPageCommand(fw);
+ cmd->init(stackedWidget(), qdesigner_internal::AddStackedWidgetPageCommand::InsertAfter);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QStackedWidgetEventFilter::gotoPage(int page) {
+ // Are we on a form or in a preview?
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(stackedWidget())) {
+ qdesigner_internal::SetPropertyCommand *cmd = new qdesigner_internal::SetPropertyCommand(fw);
+ cmd->init(stackedWidget(), QLatin1String("currentIndex"), page);
+ fw->commandHistory()->push(cmd);
+ fw->emitSelectionChanged(); // Magically prevent an endless loop triggered by auto-repeat.
+ updateButtons();
+ } else {
+ QStackedWidgetPreviewEventFilter::gotoPage(page);
+ }
+}
+
+QMenu *QStackedWidgetEventFilter::addContextMenuActions(QMenu *popup)
+{
+ QMenu *pageMenu = 0;
+ const int count = stackedWidget()->count();
+ const bool hasSeveralPages = count > 1;
+ m_actionDeletePage->setEnabled(hasSeveralPages);
+ if (count) {
+ const QString pageSubMenuLabel = tr("Page %1 of %2").arg(stackedWidget()->currentIndex() + 1).arg(count);
+ pageMenu = popup->addMenu(pageSubMenuLabel);
+ pageMenu->addAction(m_actionDeletePage);
+ // Set up promotion menu for current widget.
+ if (QWidget *page = stackedWidget()->currentWidget ()) {
+ m_pagePromotionTaskMenu->setWidget(page);
+ m_pagePromotionTaskMenu->addActions(QDesignerFormWindowInterface::findFormWindow(stackedWidget()),
+ qdesigner_internal::PromotionTaskMenu::SuppressGlobalEdit,
+ pageMenu);
+ }
+ }
+ QMenu *insertPageMenu = popup->addMenu(tr("Insert Page"));
+ insertPageMenu->addAction(m_actionInsertPageAfter);
+ insertPageMenu->addAction(m_actionInsertPage);
+ popup->addAction(m_actionNextPage);
+ m_actionNextPage->setEnabled(hasSeveralPages);
+ popup->addAction(m_actionPreviousPage);
+ m_actionPreviousPage->setEnabled(hasSeveralPages);
+ popup->addAction(m_actionChangePageOrder);
+ m_actionChangePageOrder->setEnabled(hasSeveralPages);
+ popup->addSeparator();
+ return pageMenu;
+}
+
+// -------- QStackedWidgetPropertySheet
+
+static const char *pagePropertyName = "currentPageName";
+
+QStackedWidgetPropertySheet::QStackedWidgetPropertySheet(QStackedWidget *object, QObject *parent) :
+ QDesignerPropertySheet(object, parent),
+ m_stackedWidget(object)
+{
+ createFakeProperty(QLatin1String(pagePropertyName), QString());
+}
+
+bool QStackedWidgetPropertySheet::isEnabled(int index) const
+{
+ if (propertyName(index) != QLatin1String(pagePropertyName))
+ return QDesignerPropertySheet::isEnabled(index);
+ return m_stackedWidget->currentWidget() != 0;
+}
+
+void QStackedWidgetPropertySheet::setProperty(int index, const QVariant &value)
+{
+ if (propertyName(index) == QLatin1String(pagePropertyName)) {
+ if (QWidget *w = m_stackedWidget->currentWidget())
+ w->setObjectName(value.toString());
+ } else {
+ QDesignerPropertySheet::setProperty(index, value);
+ }
+}
+
+QVariant QStackedWidgetPropertySheet::property(int index) const
+{
+ if (propertyName(index) == QLatin1String(pagePropertyName)) {
+ if (const QWidget *w = m_stackedWidget->currentWidget())
+ return w->objectName();
+ return QString();
+ }
+ return QDesignerPropertySheet::property(index);
+}
+
+bool QStackedWidgetPropertySheet::reset(int index)
+{
+ if (propertyName(index) == QLatin1String(pagePropertyName)) {
+ setProperty(index, QString());
+ return true;
+ }
+ return QDesignerPropertySheet::reset(index);
+}
+
+bool QStackedWidgetPropertySheet::checkProperty(const QString &propertyName)
+{
+ return propertyName != QLatin1String(pagePropertyName);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_stackedbox_p.h b/tools/designer/src/lib/shared/qdesigner_stackedbox_p.h
new file mode 100644
index 0000000000..a48dd94b8e
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_stackedbox_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_STACKEDBOX_H
+#define QDESIGNER_STACKEDBOX_H
+
+#include "shared_global_p.h"
+#include "qdesigner_propertysheet_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QStackedWidget;
+class QWidget;
+class QAction;
+class QMenu;
+class QToolButton;
+
+namespace qdesigner_internal {
+ class PromotionTaskMenu;
+}
+
+// Event filter to be installed on a QStackedWidget in preview mode.
+// Create two buttons to switch pages.
+
+class QDESIGNER_SHARED_EXPORT QStackedWidgetPreviewEventFilter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QStackedWidgetPreviewEventFilter(QStackedWidget *parent);
+
+ // Install helper on QStackedWidget
+ static void install(QStackedWidget *stackedWidget);
+ bool eventFilter(QObject *watched, QEvent *event);
+
+ void setButtonToolTipEnabled(bool v) { m_buttonToolTipEnabled = v; }
+ bool buttonToolTipEnabled() const { return m_buttonToolTipEnabled; }
+
+public slots:
+ void updateButtons();
+ void prevPage();
+ void nextPage();
+
+protected:
+ QStackedWidget *stackedWidget() const { return m_stackedWidget; }
+ virtual void gotoPage(int page);
+
+private:
+ void updateButtonToolTip(QObject *o);
+
+ bool m_buttonToolTipEnabled;
+ QStackedWidget *m_stackedWidget;
+ QToolButton *m_prev;
+ QToolButton *m_next;
+};
+
+// Event filter to be installed on a QStackedWidget in editing mode.
+// In addition to the browse buttons, handles context menu and everything
+
+class QDESIGNER_SHARED_EXPORT QStackedWidgetEventFilter : public QStackedWidgetPreviewEventFilter
+{
+ Q_OBJECT
+public:
+ explicit QStackedWidgetEventFilter(QStackedWidget *parent);
+
+ // Install helper on QStackedWidget
+ static void install(QStackedWidget *stackedWidget);
+ static QStackedWidgetEventFilter *eventFilterOf(const QStackedWidget *stackedWidget);
+ // Convenience to add a menu on a tackedWidget
+ static QMenu *addStackedWidgetContextMenuActions(const QStackedWidget *stackedWidget, QMenu *popup);
+
+ // Add context menu and return page submenu or 0.
+ QMenu *addContextMenuActions(QMenu *popup);
+
+private slots:
+ void removeCurrentPage();
+ void addPage();
+ void addPageAfter();
+ void changeOrder();
+
+protected:
+ virtual void gotoPage(int page);
+
+private:
+ QAction *m_actionPreviousPage;
+ QAction *m_actionNextPage;
+ QAction *m_actionDeletePage;
+ QAction *m_actionInsertPage;
+ QAction *m_actionInsertPageAfter;
+ QAction *m_actionChangePageOrder;
+ qdesigner_internal::PromotionTaskMenu* m_pagePromotionTaskMenu;
+};
+
+// PropertySheet to handle the "currentPageName" property
+class QDESIGNER_SHARED_EXPORT QStackedWidgetPropertySheet : public QDesignerPropertySheet {
+public:
+ explicit QStackedWidgetPropertySheet(QStackedWidget *object, QObject *parent = 0);
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual QVariant property(int index) const;
+ virtual bool reset(int index);
+ virtual bool isEnabled(int index) const;
+
+ // Check whether the property is to be saved. Returns false for the page
+ // properties (as the property sheet has no concept of 'stored')
+ static bool checkProperty(const QString &propertyName);
+
+private:
+ QStackedWidget *m_stackedWidget;
+};
+
+typedef QDesignerPropertySheetFactory<QStackedWidget, QStackedWidgetPropertySheet> QStackedWidgetPropertySheetFactory;
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_STACKEDBOX_H
diff --git a/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp b/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp
new file mode 100644
index 0000000000..903b066d6d
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_tabwidget.cpp
@@ -0,0 +1,567 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_tabwidget_p.h"
+#include "qdesigner_command_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "promotiontaskmenu_p.h"
+#include "formwindowbase_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtGui/QApplication>
+#include <QtGui/QTabBar>
+#include <QtGui/QAction>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QMenu>
+#include <QtGui/QLabel>
+#include <QtGui/QTabWidget>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+// Store tab widget as drag source
+class MyMimeData : public QMimeData
+{
+ Q_OBJECT
+public:
+ MyMimeData(const QTabWidget *tab) : m_tab(tab) {}
+ static bool fromMyTab(const QMimeData *mimeData, const QTabWidget *tab) {
+ if (!mimeData)
+ return false;
+ const MyMimeData *m = qobject_cast<const MyMimeData *>(mimeData);
+ return m && m->m_tab == tab;
+ }
+private:
+ const QTabWidget *m_tab;
+};
+
+} // namespace qdesigner_internal
+
+// ------------- QTabWidgetEventFilter
+
+QTabWidgetEventFilter::QTabWidgetEventFilter(QTabWidget *parent) :
+ QObject(parent),
+ m_tabWidget(parent),
+ m_dropIndicator(0),
+ m_dragPage(0),
+ m_mousePressed(false),
+ m_actionDeletePage(new QAction(tr("Delete"), this)),
+ m_actionInsertPage(new QAction(tr("Before Current Page"), this)),
+ m_actionInsertPageAfter(new QAction(tr("After Current Page"), this)),
+ m_pagePromotionTaskMenu(new qdesigner_internal::PromotionTaskMenu(0, qdesigner_internal::PromotionTaskMenu::ModeSingleWidget, this))
+{
+ tabBar()->setAcceptDrops(true);
+ tabBar()->installEventFilter(this);
+
+ connect(m_actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
+ connect(m_actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
+ connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
+}
+
+QTabWidgetEventFilter::~QTabWidgetEventFilter()
+{
+}
+
+void QTabWidgetEventFilter::install(QTabWidget *tabWidget)
+{
+ new QTabWidgetEventFilter(tabWidget);
+}
+
+QTabWidgetEventFilter *QTabWidgetEventFilter::eventFilterOf(const QTabWidget *tabWidget)
+{
+ // Look for 1st order children only..otherwise, we might get filters of nested tab widgets
+ const QObjectList children = tabWidget->children();
+ const QObjectList::const_iterator cend = children.constEnd();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
+ QObject *o = *it;
+ if (!o->isWidgetType())
+ if (QTabWidgetEventFilter *ef = qobject_cast<QTabWidgetEventFilter*>(o))
+ return ef;
+ }
+ return 0;
+}
+
+QMenu *QTabWidgetEventFilter::addTabWidgetContextMenuActions(const QTabWidget *tabWidget, QMenu *popup)
+{
+ QTabWidgetEventFilter *filter = eventFilterOf(tabWidget);
+ if (!filter)
+ return 0;
+ return filter->addContextMenuActions(popup);
+}
+
+QTabBar *QTabWidgetEventFilter::tabBar() const
+{
+ // QTabWidget::tabBar() accessor is protected, grmbl...
+ if (!m_cachedTabBar) {
+ const QList<QTabBar *> tabBars = qFindChildren<QTabBar *>(m_tabWidget);
+ Q_ASSERT(tabBars.size() == 1);
+ m_cachedTabBar = tabBars.front();
+ }
+ return m_cachedTabBar;
+
+}
+
+static bool canMove(const QPoint &pressPoint, const QMouseEvent *e)
+{
+ const QPoint pt = pressPoint - e->pos();
+ return pt.manhattanLength() > QApplication::startDragDistance();
+}
+
+bool QTabWidgetEventFilter::eventFilter(QObject *o, QEvent *e)
+{
+ const QEvent::Type type = e->type();
+ // Do not try to locate tab bar and form window, etc. for uninteresting events and
+ // avoid asserts about missing tab bars when being destroyed
+ switch (type) {
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ case QEvent::DragLeave:
+ case QEvent::DragEnter:
+ case QEvent::DragMove:
+ case QEvent::Drop:
+ break;
+ default:
+ return false;
+ }
+
+ if (o != tabBar())
+ return false;
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return false;
+
+ switch (type) {
+ case QEvent::MouseButtonDblClick:
+ break;
+ case QEvent::MouseButtonPress: {
+ QMouseEvent *mev = static_cast<QMouseEvent*>(e);
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ fw->clearSelection();
+ fw->selectWidget(m_tabWidget, true);
+ }
+ if (mev->button() & Qt::LeftButton) {
+ m_mousePressed = true;
+ m_pressPoint = mev->pos();
+
+ QTabBar *tabbar = tabBar();
+ const int count = tabbar->count();
+ for (int i = 0; i < count; ++i) {
+ if (tabbar->tabRect(i).contains(m_pressPoint)) {
+ if (i != tabbar->currentIndex()) {
+ qdesigner_internal::SetPropertyCommand *cmd = new qdesigner_internal::SetPropertyCommand(fw);
+ cmd->init(m_tabWidget, QLatin1String("currentIndex"), i);
+ fw->commandHistory()->push(cmd);
+ }
+ break;
+ }
+ }
+ }
+ } break;
+
+ case QEvent::MouseButtonRelease:
+ m_mousePressed = false;
+ break;
+
+ case QEvent::MouseMove: {
+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
+ if (m_mousePressed && canMove(m_pressPoint, mouseEvent)) {
+ const int index = m_tabWidget->currentIndex();
+ if (index == -1)
+ break;
+
+ m_mousePressed = false;
+ QDrag *drg = new QDrag(m_tabWidget);
+ drg->setMimeData(new qdesigner_internal::MyMimeData(m_tabWidget));
+
+ m_dragIndex = index;
+ m_dragPage = m_tabWidget->currentWidget();
+ m_dragLabel = m_tabWidget->tabText(index);
+ m_dragIcon = m_tabWidget->tabIcon(index);
+ if (m_dragIcon.isNull()) {
+ QLabel *label = new QLabel(m_dragLabel);
+ label->adjustSize();
+ drg->setPixmap(QPixmap::grabWidget(label));
+ label->deleteLater();
+ } else {
+ drg->setPixmap(m_dragIcon.pixmap(22, 22));
+ }
+
+ m_tabWidget->removeTab(m_dragIndex);
+
+ const Qt::DropActions dropAction = drg->start(Qt::MoveAction);
+
+ if (dropAction == Qt::IgnoreAction) {
+ // abort
+ m_tabWidget->insertTab(m_dragIndex, m_dragPage, m_dragIcon, m_dragLabel);
+ m_tabWidget->setCurrentIndex(m_dragIndex);
+ }
+
+ if (m_dropIndicator)
+ m_dropIndicator->hide();
+ }
+ } break;
+
+ case QEvent::DragLeave: {
+ if (m_dropIndicator)
+ m_dropIndicator->hide();
+ } break;
+
+ case QEvent::DragEnter:
+ case QEvent::DragMove: {
+ QDragMoveEvent *de = static_cast<QDragMoveEvent*>(e);
+ if (!qdesigner_internal::MyMimeData::fromMyTab(de->mimeData(), m_tabWidget))
+ return false;
+
+ if (de->proposedAction() == Qt::MoveAction)
+ de->acceptProposedAction();
+ else {
+ de->setDropAction(Qt::MoveAction);
+ de->accept();
+ }
+
+ QRect rect;
+ const int index = pageFromPosition(de->pos(), rect);
+
+ if (!m_dropIndicator) {
+ m_dropIndicator = new QWidget(m_tabWidget);
+ QPalette p = m_dropIndicator->palette();
+ p.setColor(m_tabWidget->backgroundRole(), Qt::red);
+ m_dropIndicator->setPalette(p);
+ }
+
+ QPoint pos;
+ if (index == m_tabWidget->count())
+ pos = tabBar()->mapToParent(QPoint(rect.x() + rect.width(), rect.y()));
+ else
+ pos = tabBar()->mapToParent(QPoint(rect.x(), rect.y()));
+
+ m_dropIndicator->setGeometry(pos.x(), pos.y() , 3, rect.height());
+ m_dropIndicator->show();
+ } break;
+
+ case QEvent::Drop: {
+ QDropEvent *de = static_cast<QDropEvent*>(e);
+ if (!qdesigner_internal::MyMimeData::fromMyTab(de->mimeData(), m_tabWidget))
+ return false;
+ de->acceptProposedAction();
+ de->accept();
+
+ QRect rect;
+ const int newIndex = pageFromPosition(de->pos(), rect);
+
+ qdesigner_internal::MoveTabPageCommand *cmd = new qdesigner_internal::MoveTabPageCommand(fw);
+ m_tabWidget->insertTab(m_dragIndex, m_dragPage, m_dragIcon, m_dragLabel);
+ cmd->init(m_tabWidget, m_dragPage, m_dragIcon, m_dragLabel, m_dragIndex, newIndex);
+ fw->commandHistory()->push(cmd);
+ } break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void QTabWidgetEventFilter::removeCurrentPage()
+{
+ if (!m_tabWidget->currentWidget())
+ return;
+
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ qdesigner_internal::DeleteTabPageCommand *cmd = new qdesigner_internal::DeleteTabPageCommand(fw);
+ cmd->init(m_tabWidget);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QTabWidgetEventFilter::addPage()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ qdesigner_internal::AddTabPageCommand *cmd = new qdesigner_internal::AddTabPageCommand(fw);
+ cmd->init(m_tabWidget, qdesigner_internal::AddTabPageCommand::InsertBefore);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QTabWidgetEventFilter::addPageAfter()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ qdesigner_internal::AddTabPageCommand *cmd = new qdesigner_internal::AddTabPageCommand(fw);
+ cmd->init(m_tabWidget, qdesigner_internal::AddTabPageCommand::InsertAfter);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+QDesignerFormWindowInterface *QTabWidgetEventFilter::formWindow() const
+{
+ return QDesignerFormWindowInterface::findFormWindow(const_cast<QTabWidget*>(m_tabWidget));
+}
+
+// Get page from mouse position. Default to new page if in right half of last page?
+int QTabWidgetEventFilter::pageFromPosition(const QPoint &pos, QRect &rect) const
+{
+ int index = 0;
+ const QTabBar *tabbar = tabBar();
+ const int count = m_tabWidget->count();
+ for (; index < count; index++) {
+ const QRect rc = tabbar->tabRect(index);
+ if (rc.contains(pos)) {
+ rect = rc;
+ break;
+ }
+ }
+
+ if (index == count -1) {
+ QRect rect2 = rect;
+ rect2.setLeft(rect2.left() + rect2.width() / 2);
+ if (rect2.contains(pos))
+ index++;
+ }
+ return index;
+}
+
+QMenu *QTabWidgetEventFilter::addContextMenuActions(QMenu *popup)
+{
+ QMenu *pageMenu = 0;
+ const int count = m_tabWidget->count();
+ m_actionDeletePage->setEnabled(count > 1);
+ if (count) {
+ const int currentIndex = m_tabWidget->currentIndex();
+ const QString pageSubMenuLabel = tr("Page %1 of %2").arg(currentIndex + 1).arg(count);
+ pageMenu = popup->addMenu(pageSubMenuLabel);
+ pageMenu->addAction(m_actionDeletePage);
+ // Set up promotion menu for current widget.
+ if (QWidget *page = m_tabWidget->currentWidget ()) {
+ m_pagePromotionTaskMenu->setWidget(page);
+ m_pagePromotionTaskMenu->addActions(QDesignerFormWindowInterface::findFormWindow(m_tabWidget),
+ qdesigner_internal::PromotionTaskMenu::SuppressGlobalEdit,
+ pageMenu);
+ }
+ }
+
+ QMenu *insertPageMenu = popup->addMenu(tr("Insert Page"));
+ insertPageMenu->addAction(m_actionInsertPageAfter);
+ insertPageMenu->addAction(m_actionInsertPage);
+ popup->addSeparator();
+ return pageMenu;
+}
+
+// ----------- QTabWidgetPropertySheet
+
+static const char *currentTabTextKey = "currentTabText";
+static const char *currentTabNameKey = "currentTabName";
+static const char *currentTabIconKey = "currentTabIcon";
+static const char *currentTabToolTipKey = "currentTabToolTip";
+static const char *currentTabWhatsThisKey = "currentTabWhatsThis";
+
+QTabWidgetPropertySheet::QTabWidgetPropertySheet(QTabWidget *object, QObject *parent) :
+ QDesignerPropertySheet(object, parent),
+ m_tabWidget(object)
+{
+ createFakeProperty(QLatin1String(currentTabTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
+ createFakeProperty(QLatin1String(currentTabNameKey), QString());
+ createFakeProperty(QLatin1String(currentTabIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue()));
+ if (formWindowBase())
+ formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentTabIconKey)));
+ createFakeProperty(QLatin1String(currentTabToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
+ createFakeProperty(QLatin1String(currentTabWhatsThisKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
+}
+
+QTabWidgetPropertySheet::TabWidgetProperty QTabWidgetPropertySheet::tabWidgetPropertyFromName(const QString &name)
+{
+ typedef QHash<QString, TabWidgetProperty> TabWidgetPropertyHash;
+ static TabWidgetPropertyHash tabWidgetPropertyHash;
+ if (tabWidgetPropertyHash.empty()) {
+ tabWidgetPropertyHash.insert(QLatin1String(currentTabTextKey), PropertyCurrentTabText);
+ tabWidgetPropertyHash.insert(QLatin1String(currentTabNameKey), PropertyCurrentTabName);
+ tabWidgetPropertyHash.insert(QLatin1String(currentTabIconKey), PropertyCurrentTabIcon);
+ tabWidgetPropertyHash.insert(QLatin1String(currentTabToolTipKey), PropertyCurrentTabToolTip);
+ tabWidgetPropertyHash.insert(QLatin1String(currentTabWhatsThisKey), PropertyCurrentTabWhatsThis);
+ }
+ return tabWidgetPropertyHash.value(name, PropertyTabWidgetNone);
+}
+
+void QTabWidgetPropertySheet::setProperty(int index, const QVariant &value)
+{
+ const TabWidgetProperty tabWidgetProperty = tabWidgetPropertyFromName(propertyName(index));
+ if (tabWidgetProperty == PropertyTabWidgetNone) {
+ QDesignerPropertySheet::setProperty(index, value);
+ return;
+ }
+
+ // index-dependent
+ const int currentIndex = m_tabWidget->currentIndex();
+ QWidget *currentWidget = m_tabWidget->currentWidget();
+ if (!currentWidget)
+ return;
+
+ switch (tabWidgetProperty) {
+ case PropertyCurrentTabText:
+ m_tabWidget->setTabText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
+ break;
+ case PropertyCurrentTabName:
+ currentWidget->setObjectName(value.toString());
+ break;
+ case PropertyCurrentTabIcon:
+ m_tabWidget->setTabIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value);
+ break;
+ case PropertyCurrentTabToolTip:
+ m_tabWidget->setTabToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
+ break;
+ case PropertyCurrentTabWhatsThis:
+ m_tabWidget->setTabWhatsThis(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].whatsthis = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
+ break;
+ case PropertyTabWidgetNone:
+ break;
+ }
+}
+
+bool QTabWidgetPropertySheet::isEnabled(int index) const
+{
+ if (tabWidgetPropertyFromName(propertyName(index)) == PropertyTabWidgetNone)
+ return QDesignerPropertySheet::isEnabled(index);
+ return m_tabWidget->currentIndex() != -1;
+}
+
+QVariant QTabWidgetPropertySheet::property(int index) const
+{
+ const TabWidgetProperty tabWidgetProperty = tabWidgetPropertyFromName(propertyName(index));
+ if (tabWidgetProperty == PropertyTabWidgetNone)
+ return QDesignerPropertySheet::property(index);
+
+ // index-dependent
+ QWidget *currentWidget = m_tabWidget->currentWidget();
+ if (!currentWidget) {
+ if (tabWidgetProperty == PropertyCurrentTabIcon)
+ return qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
+ if (tabWidgetProperty == PropertyCurrentTabText)
+ return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
+ if (tabWidgetProperty == PropertyCurrentTabToolTip)
+ return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
+ if (tabWidgetProperty == PropertyCurrentTabWhatsThis)
+ return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
+ return QVariant(QString());
+ }
+
+ // index-dependent
+ switch (tabWidgetProperty) {
+ case PropertyCurrentTabText:
+ return qVariantFromValue(m_pageToData.value(currentWidget).text);
+ case PropertyCurrentTabName:
+ return currentWidget->objectName();
+ case PropertyCurrentTabIcon:
+ return qVariantFromValue(m_pageToData.value(currentWidget).icon);
+ case PropertyCurrentTabToolTip:
+ return qVariantFromValue(m_pageToData.value(currentWidget).tooltip);
+ case PropertyCurrentTabWhatsThis:
+ return qVariantFromValue(m_pageToData.value(currentWidget).whatsthis);
+ case PropertyTabWidgetNone:
+ break;
+ }
+ return QVariant();
+}
+
+bool QTabWidgetPropertySheet::reset(int index)
+{
+ const TabWidgetProperty tabWidgetProperty = tabWidgetPropertyFromName(propertyName(index));
+ if (tabWidgetProperty == PropertyTabWidgetNone)
+ return QDesignerPropertySheet::reset(index);
+
+ // index-dependent
+ QWidget *currentWidget = m_tabWidget->currentWidget();
+ if (!currentWidget)
+ return false;
+
+ // index-dependent
+ switch (tabWidgetProperty) {
+ case PropertyCurrentTabName:
+ setProperty(index, QString());
+ break;
+ case PropertyCurrentTabToolTip:
+ m_pageToData[currentWidget].tooltip = qdesigner_internal::PropertySheetStringValue();
+ setProperty(index, QString());
+ break;
+ case PropertyCurrentTabWhatsThis:
+ m_pageToData[currentWidget].whatsthis = qdesigner_internal::PropertySheetStringValue();
+ setProperty(index, QString());
+ break;
+ case PropertyCurrentTabText:
+ m_pageToData[currentWidget].text = qdesigner_internal::PropertySheetStringValue();
+ setProperty(index, QString());
+ break;
+ case PropertyCurrentTabIcon:
+ m_pageToData[currentWidget].icon = qdesigner_internal::PropertySheetIconValue();
+ setProperty(index, QIcon());
+ break;
+ case PropertyTabWidgetNone:
+ break;
+ }
+ return true;
+}
+
+bool QTabWidgetPropertySheet::checkProperty(const QString &propertyName)
+{
+ switch (tabWidgetPropertyFromName(propertyName)) {
+ case PropertyCurrentTabText:
+ case PropertyCurrentTabName:
+ case PropertyCurrentTabToolTip:
+ case PropertyCurrentTabWhatsThis:
+ case PropertyCurrentTabIcon:
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "qdesigner_tabwidget.moc" // required for MyMimeData
diff --git a/tools/designer/src/lib/shared/qdesigner_tabwidget_p.h b/tools/designer/src/lib/shared/qdesigner_tabwidget_p.h
new file mode 100644
index 0000000000..b5af372445
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_tabwidget_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_TABWIDGET_H
+#define QDESIGNER_TABWIDGET_H
+
+#include "shared_global_p.h"
+#include "qdesigner_propertysheet_p.h"
+#include "qdesigner_utils_p.h"
+
+#include <QtCore/QPointer>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QTabWidget;
+class QTabBar;
+class QMenu;
+class QAction;
+
+namespace qdesigner_internal {
+ class PromotionTaskMenu;
+}
+
+class QDESIGNER_SHARED_EXPORT QTabWidgetEventFilter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QTabWidgetEventFilter(QTabWidget *parent);
+ ~QTabWidgetEventFilter();
+
+ // Install helper on QTabWidget
+ static void install(QTabWidget *tabWidget);
+ static QTabWidgetEventFilter *eventFilterOf(const QTabWidget *tabWidget);
+ // Convenience to add a menu on a tackedWidget
+ static QMenu *addTabWidgetContextMenuActions(const QTabWidget *tabWidget, QMenu *popup);
+
+ // Add context menu and return page submenu or 0.
+ QMenu *addContextMenuActions(QMenu *popup);
+
+ virtual bool eventFilter(QObject *o, QEvent *e);
+
+ QDesignerFormWindowInterface *formWindow() const;
+
+private slots:
+ void removeCurrentPage();
+ void addPage();
+ void addPageAfter();
+
+private:
+ int pageFromPosition(const QPoint &pos, QRect &rect) const;
+ QTabBar *tabBar() const;
+
+ QTabWidget *m_tabWidget;
+ mutable QPointer<QTabBar> m_cachedTabBar;
+ QPoint m_pressPoint;
+ QWidget *m_dropIndicator;
+ int m_dragIndex;
+ QWidget *m_dragPage;
+ QString m_dragLabel;
+ QIcon m_dragIcon;
+ bool m_mousePressed;
+ QAction *m_actionDeletePage;
+ QAction *m_actionInsertPage;
+ QAction *m_actionInsertPageAfter;
+ qdesigner_internal::PromotionTaskMenu* m_pagePromotionTaskMenu;
+};
+
+// PropertySheet to handle the page properties
+class QDESIGNER_SHARED_EXPORT QTabWidgetPropertySheet : public QDesignerPropertySheet {
+public:
+ explicit QTabWidgetPropertySheet(QTabWidget *object, QObject *parent = 0);
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual QVariant property(int index) const;
+ virtual bool reset(int index);
+ virtual bool isEnabled(int index) const;
+
+ // Check whether the property is to be saved. Returns false for the page
+ // properties (as the property sheet has no concept of 'stored')
+ static bool checkProperty(const QString &propertyName);
+
+private:
+ enum TabWidgetProperty { PropertyCurrentTabText, PropertyCurrentTabName, PropertyCurrentTabIcon,
+ PropertyCurrentTabToolTip, PropertyCurrentTabWhatsThis, PropertyTabWidgetNone };
+
+ static TabWidgetProperty tabWidgetPropertyFromName(const QString &name);
+ QTabWidget *m_tabWidget;
+ struct PageData
+ {
+ qdesigner_internal::PropertySheetStringValue text;
+ qdesigner_internal::PropertySheetStringValue tooltip;
+ qdesigner_internal::PropertySheetStringValue whatsthis;
+ qdesigner_internal::PropertySheetIconValue icon;
+ };
+ QMap<QWidget *, PageData> m_pageToData;
+};
+
+typedef QDesignerPropertySheetFactory<QTabWidget, QTabWidgetPropertySheet> QTabWidgetPropertySheetFactory;
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TABWIDGET_H
diff --git a/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp b/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp
new file mode 100644
index 0000000000..cce0528322
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_taskmenu.cpp
@@ -0,0 +1,781 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::QDesignerTaskMenu
+*/
+
+#include "qdesigner_taskmenu_p.h"
+#include "qdesigner_command_p.h"
+#include "richtexteditor_p.h"
+#include "plaintexteditor_p.h"
+#include "stylesheeteditor_p.h"
+#include "qlayout_widget_p.h"
+#include "layout_p.h"
+#include "spacer_widget_p.h"
+#include "textpropertyeditor_p.h"
+#include "promotiontaskmenu_p.h"
+#include "metadatabase_p.h"
+#include "scriptdialog_p.h"
+#include "scriptcommand_p.h"
+#include "signalslotdialog_p.h"
+#include "qdesigner_membersheet_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "qdesigner_utils_p.h"
+#include "qdesigner_objectinspector_p.h"
+#include "morphmenu_p.h"
+#include "qdesigner_integration_p.h"
+#include "formlayoutmenu_p.h"
+#include "ui_selectsignaldialog.h"
+#include "widgetfactory_p.h"
+#include "abstractintrospection_p.h"
+#include "widgetdatabase_p.h"
+
+#include <shared_enums_p.h>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QWidget>
+#include <QtGui/QMenuBar>
+#include <QtGui/QMainWindow>
+#include <QtGui/QStatusBar>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QUndoStack>
+#include <QtCore/QDebug>
+#include <QtCore/QSignalMapper>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+static QMenuBar *findMenuBar(const QWidget *widget)
+{
+ const QList<QObject*> children = widget->children();
+ foreach (QObject *obj, widget->children()) {
+ if (QMenuBar *mb = qobject_cast<QMenuBar*>(obj)) {
+ return mb;
+ }
+ }
+
+ return 0;
+}
+
+static QStatusBar *findStatusBar(const QWidget *widget)
+{
+ const QList<QObject*> children = widget->children();
+ foreach (QObject *obj, widget->children()) {
+ if (QStatusBar *sb = qobject_cast<QStatusBar*>(obj)) {
+ return sb;
+ }
+ }
+
+ return 0;
+}
+
+static inline QAction *createSeparatorHelper(QObject *parent) {
+ QAction *rc = new QAction(parent);
+ rc->setSeparator(true);
+ return rc;
+}
+
+static inline qdesigner_internal::QDesignerIntegration *integration(const QDesignerFormEditorInterface *core) {
+ return qobject_cast<qdesigner_internal::QDesignerIntegration *>(core->integration());
+}
+
+static QString objName(const QDesignerFormEditorInterface *core, QObject *object) {
+ QDesignerPropertySheetExtension *sheet
+ = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), object);
+ Q_ASSERT(sheet != 0);
+
+ const QString objectNameProperty = QLatin1String("objectName");
+ const int index = sheet->indexOf(objectNameProperty);
+ const qdesigner_internal::PropertySheetStringValue objectNameValue
+ = qVariantValue<qdesigner_internal::PropertySheetStringValue>(sheet->property(index));
+ return objectNameValue.value();
+}
+
+enum { ApplyMinimumWidth = 0x1, ApplyMinimumHeight = 0x2, ApplyMaximumWidth = 0x4, ApplyMaximumHeight = 0x8 };
+
+namespace {
+// --------------- ObjectNameDialog
+class ObjectNameDialog : public QDialog
+{
+ public:
+ ObjectNameDialog(QWidget *parent, const QString &oldName);
+ QString newObjectName() const;
+
+ private:
+ qdesigner_internal::TextPropertyEditor *m_editor;
+};
+
+ObjectNameDialog::ObjectNameDialog(QWidget *parent, const QString &oldName)
+ : QDialog(parent),
+ m_editor( new qdesigner_internal::TextPropertyEditor(this, qdesigner_internal::TextPropertyEditor::EmbeddingNone,
+ qdesigner_internal::ValidationObjectName))
+{
+ setWindowTitle(QCoreApplication::translate("ObjectNameDialog", "Change Object Name"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QVBoxLayout *vboxLayout = new QVBoxLayout(this);
+ vboxLayout->addWidget(new QLabel(QCoreApplication::translate("ObjectNameDialog", "Object Name")));
+
+ m_editor->setText(oldName);
+ m_editor->selectAll();
+ m_editor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ vboxLayout->addWidget(m_editor);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
+ Qt::Horizontal, this);
+ QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
+ okButton->setDefault(true);
+ vboxLayout->addWidget(buttonBox);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+}
+
+QString ObjectNameDialog::newObjectName() const
+{
+ return m_editor->text();
+}
+
+}
+
+namespace qdesigner_internal {
+// -------------- QDesignerTaskMenuPrivate
+class QDesignerTaskMenuPrivate {
+public:
+ QDesignerTaskMenuPrivate(QWidget *widget, QObject *parent);
+
+ QDesignerTaskMenu *m_q;
+ QPointer<QWidget> m_widget;
+ QAction *m_separator;
+ QAction *m_separator2;
+ QAction *m_separator3;
+ QAction *m_separator4;
+ QAction *m_separator5;
+ QAction *m_separator6;
+ QAction *m_separator7;
+ QAction *m_changeObjectNameAction;
+ QAction *m_changeToolTip;
+ QAction *m_changeWhatsThis;
+ QAction *m_changeStyleSheet;
+ MorphMenu *m_morphMenu;
+ FormLayoutMenu *m_formLayoutMenu;
+
+ QAction *m_addMenuBar;
+ QAction *m_addToolBar;
+ QAction *m_addStatusBar;
+ QAction *m_removeStatusBar;
+ QAction *m_changeScript;
+ QAction *m_containerFakeMethods;
+ QAction *m_navigateToSlot;
+ PromotionTaskMenu* m_promotionTaskMenu;
+ QActionGroup *m_sizeActionGroup;
+ QAction *m_sizeActionsSubMenu;
+};
+
+QDesignerTaskMenuPrivate::QDesignerTaskMenuPrivate(QWidget *widget, QObject *parent) :
+ m_q(0),
+ m_widget(widget),
+ m_separator(createSeparatorHelper(parent)),
+ m_separator2(createSeparatorHelper(parent)),
+ m_separator3(createSeparatorHelper(parent)),
+ m_separator4(createSeparatorHelper(parent)),
+ m_separator5(createSeparatorHelper(parent)),
+ m_separator6(createSeparatorHelper(parent)),
+ m_separator7(createSeparatorHelper(parent)),
+ m_changeObjectNameAction(new QAction(QDesignerTaskMenu::tr("Change objectName..."), parent)),
+ m_changeToolTip(new QAction(QDesignerTaskMenu::tr("Change toolTip..."), parent)),
+ m_changeWhatsThis(new QAction(QDesignerTaskMenu::tr("Change whatsThis..."), parent)),
+ m_changeStyleSheet(new QAction(QDesignerTaskMenu::tr("Change styleSheet..."), parent)),
+ m_morphMenu(new MorphMenu(parent)),
+ m_formLayoutMenu(new FormLayoutMenu(parent)),
+ m_addMenuBar(new QAction(QDesignerTaskMenu::tr("Create Menu Bar"), parent)),
+ m_addToolBar(new QAction(QDesignerTaskMenu::tr("Add Tool Bar"), parent)),
+ m_addStatusBar(new QAction(QDesignerTaskMenu::tr("Create Status Bar"), parent)),
+ m_removeStatusBar(new QAction(QDesignerTaskMenu::tr("Remove Status Bar"), parent)),
+ m_changeScript(new QAction(QDesignerTaskMenu::tr("Change script..."), parent)),
+ m_containerFakeMethods(new QAction(QDesignerTaskMenu::tr("Change signals/slots..."), parent)),
+ m_navigateToSlot(new QAction(QDesignerTaskMenu::tr("Go to slot..."), parent)),
+ m_promotionTaskMenu(new PromotionTaskMenu(widget, PromotionTaskMenu::ModeManagedMultiSelection, parent)),
+ m_sizeActionGroup(new QActionGroup(parent)),
+ m_sizeActionsSubMenu(new QAction(QDesignerTaskMenu::tr("Size Constraints"), parent))
+{
+ QMenu *sizeMenu = new QMenu;
+ m_sizeActionsSubMenu->setMenu(sizeMenu);
+ QAction *sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Width"));
+ sizeAction->setData(ApplyMinimumWidth);
+ sizeMenu->addAction(sizeAction);
+
+ sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Height"));
+ sizeAction->setData(ApplyMinimumHeight);
+ sizeMenu->addAction(sizeAction);
+
+ sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Minimum Size"));
+ sizeAction->setData(ApplyMinimumWidth|ApplyMinimumHeight);
+ sizeMenu->addAction(sizeAction);
+
+ sizeMenu->addSeparator();
+
+ sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Width"));
+ sizeAction->setData(ApplyMaximumWidth);
+ sizeMenu->addAction(sizeAction);
+
+ sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Height"));
+ sizeAction->setData(ApplyMaximumHeight);
+ sizeMenu->addAction(sizeAction);
+
+ sizeAction = m_sizeActionGroup->addAction(QDesignerTaskMenu::tr("Set Maximum Size"));
+ sizeAction->setData(ApplyMaximumWidth|ApplyMaximumHeight);
+ sizeMenu->addAction(sizeAction);
+}
+
+// --------- QDesignerTaskMenu
+QDesignerTaskMenu::QDesignerTaskMenu(QWidget *widget, QObject *parent) :
+ QObject(parent),
+ d(new QDesignerTaskMenuPrivate(widget, parent))
+{
+ d->m_q = this;
+ Q_ASSERT(qobject_cast<QDesignerFormWindowInterface*>(widget) == 0);
+
+ connect(d->m_changeObjectNameAction, SIGNAL(triggered()), this, SLOT(changeObjectName()));
+ connect(d->m_changeToolTip, SIGNAL(triggered()), this, SLOT(changeToolTip()));
+ connect(d->m_changeWhatsThis, SIGNAL(triggered()), this, SLOT(changeWhatsThis()));
+ connect(d->m_changeStyleSheet, SIGNAL(triggered()), this, SLOT(changeStyleSheet()));
+ connect(d->m_addMenuBar, SIGNAL(triggered()), this, SLOT(createMenuBar()));
+ connect(d->m_addToolBar, SIGNAL(triggered()), this, SLOT(addToolBar()));
+ connect(d->m_addStatusBar, SIGNAL(triggered()), this, SLOT(createStatusBar()));
+ connect(d->m_removeStatusBar, SIGNAL(triggered()), this, SLOT(removeStatusBar()));
+ connect(d->m_changeScript, SIGNAL(triggered()), this, SLOT(changeScript()));
+ connect(d->m_containerFakeMethods, SIGNAL(triggered()), this, SLOT(containerFakeMethods()));
+ connect(d->m_navigateToSlot, SIGNAL(triggered()), this, SLOT(slotNavigateToSlot()));
+ connect(d->m_sizeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(applySize(QAction*)));
+}
+
+QDesignerTaskMenu::~QDesignerTaskMenu()
+{
+ delete d;
+}
+
+QAction *QDesignerTaskMenu::createSeparator()
+{
+ return createSeparatorHelper(this);
+}
+
+QWidget *QDesignerTaskMenu::widget() const
+{
+ return d->m_widget;
+}
+
+QDesignerFormWindowInterface *QDesignerTaskMenu::formWindow() const
+{
+ QDesignerFormWindowInterface *result = QDesignerFormWindowInterface::findFormWindow(widget());
+ Q_ASSERT(result != 0);
+ return result;
+}
+
+void QDesignerTaskMenu::createMenuBar()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
+ if (!mw) {
+ // ### warning message
+ return;
+ }
+
+ CreateMenuBarCommand *cmd = new CreateMenuBarCommand(fw);
+ cmd->init(mw);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QDesignerTaskMenu::addToolBar()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
+ if (!mw) {
+ // ### warning message
+ return;
+ }
+
+ AddToolBarCommand *cmd = new AddToolBarCommand(fw);
+ cmd->init(mw);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QDesignerTaskMenu::createStatusBar()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
+ if (!mw) {
+ // ### warning message
+ return;
+ }
+
+ CreateStatusBarCommand *cmd = new CreateStatusBarCommand(fw);
+ cmd->init(mw);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QDesignerTaskMenu::removeStatusBar()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer());
+ if (!mw) {
+ // ### warning message
+ return;
+ }
+
+ DeleteStatusBarCommand *cmd = new DeleteStatusBarCommand(fw);
+ cmd->init(findStatusBar(mw));
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+QList<QAction*> QDesignerTaskMenu::taskActions() const
+{
+ QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(widget());
+ Q_ASSERT(formWindow);
+
+ const bool isMainContainer = formWindow->mainContainer() == widget();
+
+ QList<QAction*> actions;
+
+ if (const QMainWindow *mw = qobject_cast<const QMainWindow*>(formWindow->mainContainer())) {
+ if (isMainContainer || mw->centralWidget() == widget()) {
+ if (!findMenuBar(mw)) {
+ actions.append(d->m_addMenuBar);
+ }
+
+ actions.append(d->m_addToolBar);
+ // ### create the status bar
+ if (!findStatusBar(mw))
+ actions.append(d->m_addStatusBar);
+ else
+ actions.append(d->m_removeStatusBar);
+ actions.append(d->m_separator);
+ }
+ }
+ actions.append(d->m_changeObjectNameAction);
+ d->m_morphMenu->populate(d->m_widget, formWindow, actions);
+ d->m_formLayoutMenu->populate(d->m_widget, formWindow, actions);
+ actions.append(d->m_separator2);
+ actions.append(d->m_changeToolTip);
+ actions.append(d->m_changeWhatsThis);
+ actions.append(d->m_changeStyleSheet);
+ actions.append(d->m_separator6);
+ actions.append(d->m_sizeActionsSubMenu);
+ d->m_promotionTaskMenu->setMode(formWindow->isManaged(d->m_widget) ?
+ PromotionTaskMenu::ModeManagedMultiSelection : PromotionTaskMenu::ModeUnmanagedMultiSelection);
+ d->m_promotionTaskMenu->addActions(formWindow, PromotionTaskMenu::LeadingSeparator, actions);
+
+#ifdef WANT_SCRIPT_OPTION
+ if (!isMainContainer) {
+ actions.append(d->m_separator4);
+ actions.append(d->m_changeScript);
+ }
+#endif
+ if (isMainContainer && !qt_extension<QDesignerLanguageExtension*>(formWindow->core()->extensionManager(), formWindow->core())) {
+ actions.append(d->m_separator5);
+ actions.append(d->m_containerFakeMethods);
+ }
+
+ if (isSlotNavigationEnabled(formWindow->core())) {
+ actions.append(d->m_separator7);
+ actions.append(d->m_navigateToSlot);
+ }
+
+ return actions;
+}
+
+void QDesignerTaskMenu::changeObjectName()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ Q_ASSERT(fw != 0);
+
+ const QString oldObjectName = objName(fw->core(), widget());
+
+ ObjectNameDialog dialog(fw, oldObjectName);
+ if (dialog.exec() == QDialog::Accepted) {
+ const QString newObjectName = dialog.newObjectName();
+ if (!newObjectName.isEmpty() && newObjectName != oldObjectName ) {
+ const QString objectNameProperty = QLatin1String("objectName");
+ PropertySheetStringValue objectNameValue;
+ objectNameValue.setValue(newObjectName);
+ setProperty(fw, CurrentWidgetMode, objectNameProperty, qVariantFromValue(objectNameValue));
+ }
+ }
+}
+
+void QDesignerTaskMenu::changeTextProperty(const QString &propertyName, const QString &windowTitle, PropertyMode pm, Qt::TextFormat desiredFormat)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+ Q_ASSERT(d->m_widget->parentWidget() != 0);
+
+ const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(fw->core()->extensionManager(), d->m_widget);
+ const int index = sheet->indexOf(propertyName);
+ if (index == -1) {
+ qDebug() << "** WARNING Invalid property" << propertyName << " passed to changeTextProperty!";
+ return;
+ }
+ PropertySheetStringValue textValue = qVariantValue<PropertySheetStringValue>(sheet->property(index));
+ const QString oldText = textValue.value();
+ // Pop up respective dialog
+ bool accepted = false;
+ QString newText;
+ switch (desiredFormat) {
+ case Qt::PlainText: {
+ PlainTextEditorDialog dlg(fw->core(), fw);
+ if (!windowTitle.isEmpty())
+ dlg.setWindowTitle(windowTitle);
+ dlg.setDefaultFont(d->m_widget->font());
+ dlg.setText(oldText);
+ accepted = dlg.showDialog() == QDialog::Accepted;
+ newText = dlg.text();
+ }
+ break;
+ default: {
+ RichTextEditorDialog dlg(fw->core(), fw);
+ if (!windowTitle.isEmpty())
+ dlg.setWindowTitle(windowTitle);
+ dlg.setDefaultFont(d->m_widget->font());
+ dlg.setText(oldText);
+ accepted = dlg.showDialog() == QDialog::Accepted;
+ newText = dlg.text(desiredFormat);
+ }
+ break;
+ }
+ // change property
+ if (!accepted || oldText == newText)
+ return;
+
+
+ textValue.setValue(newText);
+ setProperty(fw, pm, propertyName, qVariantFromValue(textValue));
+}
+
+void QDesignerTaskMenu::changeToolTip()
+{
+ changeTextProperty(QLatin1String("toolTip"), tr("Edit ToolTip"), MultiSelectionMode, Qt::AutoText);
+}
+
+void QDesignerTaskMenu::changeWhatsThis()
+{
+ changeTextProperty(QLatin1String("whatsThis"), tr("Edit WhatsThis"), MultiSelectionMode, Qt::AutoText);
+}
+
+void QDesignerTaskMenu::changeStyleSheet()
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ StyleSheetPropertyEditorDialog dlg(fw, fw, d->m_widget);
+ dlg.exec();
+ }
+}
+
+void QDesignerTaskMenu::changeScript()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+
+ MetaDataBase *metaDataBase = qobject_cast<MetaDataBase*>(fw->core()->metaDataBase());
+ if (!metaDataBase)
+ return;
+
+ const MetaDataBaseItem* item = metaDataBase->metaDataBaseItem(d->m_widget);
+ if (!item)
+ return;
+
+ const QString oldScript = item->script();
+ QString newScript = oldScript;
+
+ ScriptDialog scriptDialog(fw->core()->dialogGui(), fw);
+ if (!scriptDialog.editScript(newScript))
+ return;
+
+ // compile list of selected objects
+ ScriptCommand *scriptCommand = new ScriptCommand(fw);
+ if (!scriptCommand->init(applicableObjects(fw, MultiSelectionMode), newScript)) {
+ delete scriptCommand;
+ return;
+ }
+
+ fw->commandHistory()->push(scriptCommand);
+}
+
+void QDesignerTaskMenu::containerFakeMethods()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+ SignalSlotDialog::editMetaDataBase(fw, d->m_widget, fw);
+}
+
+static QString declaredInClass(const QDesignerMetaObjectInterface *metaObject, const QString &member)
+{
+ // Find class whose superclass does not contain the method.
+ const QDesignerMetaObjectInterface *meta = metaObject;
+
+ for (;;) {
+ const QDesignerMetaObjectInterface *tmpMeta = meta->superClass();
+ if (tmpMeta == 0)
+ break;
+ if (tmpMeta->indexOfMethod(member) == -1)
+ break;
+ meta = tmpMeta;
+ }
+ return meta->className();
+}
+
+bool QDesignerTaskMenu::isSlotNavigationEnabled(const QDesignerFormEditorInterface *core)
+{
+ if (QDesignerIntegration *integr = integration(core))
+ return integr->isSlotNavigationEnabled();
+ return false;
+}
+
+void QDesignerTaskMenu::slotNavigateToSlot()
+{
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ Q_ASSERT(core);
+ navigateToSlot(core, widget());
+}
+
+void QDesignerTaskMenu::navigateToSlot(QDesignerFormEditorInterface *core,
+ QObject *object,
+ const QString &defaultSignal)
+{
+ const QString objectName = objName(core, object);
+ QMap<QString, QMap<QString, QStringList> > classToSignalList;
+
+ QDesignerIntegration *integr = integration(core);
+
+ // "real" signals
+ if (const QDesignerMetaObjectInterface *metaObject = core->introspection()->metaObject(object)) {
+ const int methodCount = metaObject->methodCount();
+ for (int i = 0; i < methodCount; ++i) {
+ const QDesignerMetaMethodInterface *metaMethod = metaObject->method(i);
+ if (metaMethod->methodType() == QDesignerMetaMethodInterface::Signal) {
+ const QString signature = metaMethod->signature();
+ const QStringList parameterNames = metaMethod->parameterNames();
+ classToSignalList[declaredInClass(metaObject, signature)][signature] = parameterNames;
+ }
+ }
+ }
+
+ // fake signals
+ if (qdesigner_internal::MetaDataBase *metaDataBase
+ = qobject_cast<qdesigner_internal::MetaDataBase *>(core->metaDataBase())) {
+ qdesigner_internal::MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(object);
+ Q_ASSERT(item);
+ const QStringList fakeSignals = item->fakeSignals();
+ foreach (const QString &fakeSignal, fakeSignals)
+ classToSignalList[item->customClassName()][fakeSignal] = QStringList();
+ }
+
+ if (object->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget *>(object);
+ if (WidgetDataBase *db = qobject_cast<WidgetDataBase *>(core->widgetDataBase())) {
+ const QString promotedClassName = promotedCustomClassName(core, widget);
+ const int index = core->widgetDataBase()->indexOfClassName(promotedClassName);
+ if (index >= 0) {
+ WidgetDataBaseItem* item = static_cast<WidgetDataBaseItem*>(db->item(index));
+ const QStringList fakeSignals = item->fakeSignals();
+ foreach (const QString &fakeSignal, fakeSignals)
+ classToSignalList[promotedClassName][fakeSignal] = QStringList();
+ }
+ }
+ }
+
+ Ui::SelectSignalDialog dialogUi;
+ QDialog selectSignalDialog(0, Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
+ dialogUi.setupUi(&selectSignalDialog);
+
+ QMap<QString, QMap<QString, QStringList> >::const_iterator iter(classToSignalList.constBegin());
+ for (; iter != classToSignalList.constEnd(); ++iter) {
+ const QString className = iter.key();
+ QMap<QString, QStringList> signalNames = iter.value();
+
+ QMap<QString, QStringList>::const_iterator itSignal(signalNames.constBegin());
+ for (; itSignal != signalNames.constEnd(); ++itSignal) {
+ const QString signalName = itSignal.key();
+ QTreeWidgetItem *row = new QTreeWidgetItem(QStringList() << signalName << className);
+ row->setData(0, Qt::UserRole, itSignal.value());
+ dialogUi.signalList->addTopLevelItem(row);
+ }
+ }
+ if (dialogUi.signalList->topLevelItemCount() == 0) {
+ QTreeWidgetItem *row = new QTreeWidgetItem(QStringList() << tr("no signals available"));
+ dialogUi.signalList->addTopLevelItem(row);
+ dialogUi.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+ } else {
+ connect(dialogUi.signalList, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+ &selectSignalDialog, SLOT(accept()));
+ }
+
+ if (defaultSignal.isEmpty()) {
+ dialogUi.signalList->setCurrentItem(dialogUi.signalList->topLevelItem(0));
+ } else {
+ const QList<QTreeWidgetItem *> items = dialogUi.signalList->findItems (defaultSignal, Qt::MatchExactly, 0);
+ if (!items.empty())
+ dialogUi.signalList->setCurrentItem(items.front());
+ }
+
+ dialogUi.signalList->resizeColumnToContents(0);
+
+ if (selectSignalDialog.exec() == QDialog::Accepted) {
+ QTreeWidgetItem *selectedItem = dialogUi.signalList->selectedItems().first();
+ const QString signalSignature = selectedItem->text(0);
+ const QStringList parameterNames = qVariantValue<QStringList>(selectedItem->data(0, Qt::UserRole));
+
+ // TODO: Check wether signal is connected to slot
+ integr->emitNavigateToSlot(objectName, signalSignature, parameterNames);
+ }
+}
+
+// Add a command that takes over the value of the current geometry as
+// minimum/maximum size according to the flags.
+static void createSizeCommand(QDesignerFormWindowInterface *fw, QWidget *w, int flags)
+{
+ const QSize size = w->size();
+ if (flags & (ApplyMinimumWidth|ApplyMinimumHeight)) {
+ QSize minimumSize = w-> minimumSize();
+ if (flags & ApplyMinimumWidth)
+ minimumSize.setWidth(size.width());
+ if (flags & ApplyMinimumHeight)
+ minimumSize.setHeight(size.height());
+ SetPropertyCommand* cmd = new SetPropertyCommand(fw);
+ cmd->init(w, QLatin1String("minimumSize"), minimumSize);
+ fw->commandHistory()->push(cmd);
+ }
+ if (flags & (ApplyMaximumWidth|ApplyMaximumHeight)) {
+ QSize maximumSize = w-> maximumSize();
+ if (flags & ApplyMaximumWidth)
+ maximumSize.setWidth(size.width());
+ if (flags & ApplyMaximumHeight)
+ maximumSize.setHeight(size.height());
+ SetPropertyCommand* cmd = new SetPropertyCommand(fw);
+ cmd->init(w, QLatin1String("maximumSize"), maximumSize);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QDesignerTaskMenu::applySize(QAction *a)
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ if (!fw)
+ return;
+
+ const QWidgetList selection = applicableWidgets(fw, MultiSelectionMode);
+ if (selection.isEmpty())
+ return;
+
+ const int mask = a->data().toInt();
+ const int size = selection.size();
+ fw->commandHistory()->beginMacro(tr("Set size constraint on %n widget(s)", 0, size));
+ for (int i = 0; i < size; i++)
+ createSizeCommand(fw, selection.at(i), mask);
+ fw->commandHistory()->endMacro();
+}
+
+template <class Container>
+ static void getApplicableObjects(const QDesignerFormWindowInterface *fw, QWidget *current,
+ QDesignerTaskMenu::PropertyMode pm, Container *c)
+{
+ // Current is always first
+ c->push_back(current);
+ if (pm == QDesignerTaskMenu::CurrentWidgetMode)
+ return;
+ QDesignerObjectInspector *designerObjectInspector = qobject_cast<QDesignerObjectInspector *>(fw->core()->objectInspector());
+ if (!designerObjectInspector)
+ return; // Ooops, someone plugged an old-style Object Inspector
+ // Add managed or unmanaged selection according to current type, make current first
+ Selection s;
+ designerObjectInspector->getSelection(s);
+ const QWidgetList &source = fw->isManaged(current) ? s.managed : s.unmanaged;
+ const QWidgetList::const_iterator cend = source.constEnd();
+ for ( QWidgetList::const_iterator it = source.constBegin(); it != cend; ++it)
+ if (*it != current) // was first
+ c->push_back(*it);
+}
+
+QObjectList QDesignerTaskMenu::applicableObjects(const QDesignerFormWindowInterface *fw, PropertyMode pm) const
+{
+ QObjectList rc;
+ getApplicableObjects(fw, d->m_widget, pm, &rc);
+ return rc;
+}
+
+QWidgetList QDesignerTaskMenu::applicableWidgets(const QDesignerFormWindowInterface *fw, PropertyMode pm) const
+{
+ QWidgetList rc;
+ getApplicableObjects(fw, d->m_widget, pm, &rc);
+ return rc;
+}
+
+void QDesignerTaskMenu::setProperty(QDesignerFormWindowInterface *fw, PropertyMode pm, const QString &name, const QVariant &newValue)
+{
+ SetPropertyCommand* setPropertyCommand = new SetPropertyCommand(fw);
+ if (setPropertyCommand->init(applicableObjects(fw, pm), name, newValue, d->m_widget)) {
+ fw->commandHistory()->push(setPropertyCommand);
+ } else {
+ delete setPropertyCommand;
+ qDebug() << "Unable to set property " << name << '.';
+ }
+}
+
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_taskmenu_p.h b/tools/designer/src/lib/shared/qdesigner_taskmenu_p.h
new file mode 100644
index 0000000000..db5807bfc2
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_taskmenu_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_TASKMENU_H
+#define QDESIGNER_TASKMENU_H
+
+#include "shared_global_p.h"
+#include "extensionfactory_p.h"
+#include <QtDesigner/QDesignerTaskMenuExtension>
+
+#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+
+class QWidget;
+class QSignalMapper;
+
+namespace qdesigner_internal {
+class QDesignerTaskMenuPrivate;
+
+class QDESIGNER_SHARED_EXPORT QDesignerTaskMenu: public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ QDesignerTaskMenu(QWidget *widget, QObject *parent);
+ virtual ~QDesignerTaskMenu();
+
+ QWidget *widget() const;
+
+ virtual QList<QAction*> taskActions() const;
+
+ enum PropertyMode { CurrentWidgetMode, MultiSelectionMode };
+
+ static bool isSlotNavigationEnabled(const QDesignerFormEditorInterface *core);
+ static void navigateToSlot(QDesignerFormEditorInterface *core, QObject *o,
+ const QString &defaultSignal = QString());
+
+protected:
+
+ QDesignerFormWindowInterface *formWindow() const;
+ void changeTextProperty(const QString &propertyName, const QString &windowTitle, PropertyMode pm, Qt::TextFormat desiredFormat);
+
+ QAction *createSeparator();
+
+ /* Retrieve the list of objects the task menu is supposed to act on. Note that a task menu can be invoked for
+ * an unmanaged widget [as of 4.5], in which case it must not use the cursor selection,
+ * but the unmanaged selection of the object inspector. */
+ QObjectList applicableObjects(const QDesignerFormWindowInterface *fw, PropertyMode pm) const;
+ QList<QWidget *> applicableWidgets(const QDesignerFormWindowInterface *fw, PropertyMode pm) const;
+
+ void setProperty(QDesignerFormWindowInterface *fw, PropertyMode pm, const QString &name, const QVariant &newValue);
+
+private slots:
+ void changeObjectName();
+ void changeToolTip();
+ void changeWhatsThis();
+ void changeStyleSheet();
+ void createMenuBar();
+ void addToolBar();
+ void createStatusBar();
+ void removeStatusBar();
+ void changeScript();
+ void containerFakeMethods();
+ void slotNavigateToSlot();
+ void applySize(QAction *a);
+
+private:
+ QDesignerTaskMenuPrivate *d;
+};
+
+typedef ExtensionFactory<QDesignerTaskMenuExtension, QWidget, QDesignerTaskMenu> QDesignerTaskMenuFactory;
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TASKMENU_H
diff --git a/tools/designer/src/lib/shared/qdesigner_toolbar.cpp b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp
new file mode 100644
index 0000000000..cb77801d86
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_toolbar.cpp
@@ -0,0 +1,486 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::Sentinel
+*/
+
+#include "qdesigner_toolbar_p.h"
+#include "qdesigner_command_p.h"
+#include "actionrepository_p.h"
+#include "actionprovider_p.h"
+#include "qdesigner_utils_p.h"
+#include "qdesigner_objectinspector_p.h"
+#include "promotiontaskmenu_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <actionprovider_p.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QToolButton>
+#include <QtGui/QToolBar>
+#include <QtGui/QMenu>
+#include <QtGui/qevent.h>
+#include <QtGui/QApplication>
+#include <QtGui/private/qtoolbarlayout_p.h>
+#include <QtCore/QDebug>
+
+Q_DECLARE_METATYPE(QAction*)
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QAction*> ActionList;
+
+namespace qdesigner_internal {
+// ------------------- ToolBarEventFilter
+void ToolBarEventFilter::install(QToolBar *tb)
+{
+ ToolBarEventFilter *tf = new ToolBarEventFilter(tb);
+ tb->installEventFilter(tf);
+ tb->setAcceptDrops(true); // ### fake
+}
+
+ToolBarEventFilter::ToolBarEventFilter(QToolBar *tb) :
+ QObject(tb),
+ m_toolBar(tb),
+ m_promotionTaskMenu(0)
+{
+}
+
+ToolBarEventFilter *ToolBarEventFilter::eventFilterOf(const QToolBar *tb)
+{
+ // Look for 1st order children only..otherwise, we might get filters of nested widgets
+ const QObjectList children = tb->children();
+ const QObjectList::const_iterator cend = children.constEnd();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
+ QObject *o = *it;
+ if (!o->isWidgetType())
+ if (ToolBarEventFilter *ef = qobject_cast<ToolBarEventFilter *>(o))
+ return ef;
+ }
+ return 0;
+}
+
+bool ToolBarEventFilter::eventFilter (QObject *watched, QEvent *event)
+{
+ if (watched != m_toolBar)
+ return QObject::eventFilter (watched, event);
+
+ switch (event->type()) {
+ case QEvent::ChildAdded: {
+ // Children should not interact with the mouse
+ const QChildEvent *ce = static_cast<const QChildEvent *>(event);
+ if (QWidget *w = qobject_cast<QWidget *>(ce->child())) {
+ w->setAttribute(Qt::WA_TransparentForMouseEvents, true);
+ w->setFocusPolicy(Qt::NoFocus);
+ }
+ }
+ break;
+ case QEvent::ContextMenu:
+ return handleContextMenuEvent(static_cast<QContextMenuEvent*>(event));
+ case QEvent::DragEnter:
+ case QEvent::DragMove:
+ return handleDragEnterMoveEvent(static_cast<QDragMoveEvent *>(event));
+ case QEvent::DragLeave:
+ return handleDragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
+ case QEvent::Drop:
+ return handleDropEvent(static_cast<QDropEvent *>(event));
+ case QEvent::MouseButtonPress:
+ return handleMousePressEvent(static_cast<QMouseEvent*>(event));
+ case QEvent::MouseButtonRelease:
+ return handleMouseReleaseEvent(static_cast<QMouseEvent*>(event));
+ case QEvent::MouseMove:
+ return handleMouseMoveEvent(static_cast<QMouseEvent*>(event));
+ default:
+ break;
+ }
+ return QObject::eventFilter (watched, event);
+}
+
+ActionList ToolBarEventFilter::contextMenuActions(const QPoint &globalPos)
+{
+ ActionList rc;
+ const int index = actionIndexAt(m_toolBar, m_toolBar->mapFromGlobal(globalPos), m_toolBar->orientation());
+ const ActionList actions = m_toolBar->actions();
+ QAction *action = index != -1 ?actions.at(index) : 0;
+ QVariant itemData;
+
+ // Insert before
+ if (action && index != 0 && !action->isSeparator()) {
+ QAction *newSeperatorAct = new QAction(tr("Insert Separator before '%1'").arg(action->objectName()), 0);
+ qVariantSetValue(itemData, action);
+ newSeperatorAct->setData(itemData);
+ connect(newSeperatorAct, SIGNAL(triggered()), this, SLOT(slotInsertSeparator()));
+ rc.push_back(newSeperatorAct);
+ }
+
+ // Append separator
+ if (actions.empty() || !actions.back()->isSeparator()) {
+ QAction *newSeperatorAct = new QAction(tr("Append Separator"), 0);
+ qVariantSetValue(itemData, static_cast<QAction*>(0));
+ newSeperatorAct->setData(itemData);
+ connect(newSeperatorAct, SIGNAL(triggered()), this, SLOT(slotInsertSeparator()));
+ rc.push_back(newSeperatorAct);
+ }
+ // Promotion
+ if (!m_promotionTaskMenu)
+ m_promotionTaskMenu = new PromotionTaskMenu(m_toolBar, PromotionTaskMenu::ModeSingleWidget, this);
+ m_promotionTaskMenu->addActions(formWindow(), PromotionTaskMenu::LeadingSeparator|PromotionTaskMenu::TrailingSeparator, rc);
+ // Remove
+ if (action) {
+ QAction *a = new QAction(tr("Remove action '%1'").arg(action->objectName()), 0);
+ qVariantSetValue(itemData, action);
+ a->setData(itemData);
+ connect(a, SIGNAL(triggered()), this, SLOT(slotRemoveSelectedAction()));
+ rc.push_back(a);
+ }
+
+ QAction *remove_toolbar = new QAction(tr("Remove Toolbar '%1'").arg(m_toolBar->objectName()), 0);
+ connect(remove_toolbar, SIGNAL(triggered()), this, SLOT(slotRemoveToolBar()));
+ rc.push_back(remove_toolbar);
+ return rc;
+}
+
+bool ToolBarEventFilter::handleContextMenuEvent(QContextMenuEvent * event )
+{
+ event->accept();
+
+ const QPoint globalPos = event->globalPos();
+ const ActionList al = contextMenuActions(event->globalPos());
+
+ QMenu menu(0);
+ const ActionList::const_iterator acend = al.constEnd();
+ for (ActionList::const_iterator it = al.constBegin(); it != acend; ++it)
+ menu.addAction(*it);
+ menu.exec(globalPos);
+ return true;
+}
+
+void ToolBarEventFilter::slotRemoveSelectedAction()
+{
+ QAction *action = qobject_cast<QAction*>(sender());
+ if (!action)
+ return;
+
+ QAction *a = qvariant_cast<QAction*>(action->data());
+ Q_ASSERT(a != 0);
+
+ QDesignerFormWindowInterface *fw = formWindow();
+ Q_ASSERT(fw);
+
+ const ActionList actions = m_toolBar->actions();
+ const int pos = actions.indexOf(a);
+ QAction *action_before = 0;
+ if (pos != -1 && actions.count() > pos + 1)
+ action_before = actions.at(pos + 1);
+
+ RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw);
+ cmd->init(m_toolBar, a, action_before);
+ fw->commandHistory()->push(cmd);
+}
+
+void ToolBarEventFilter::slotRemoveToolBar()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ Q_ASSERT(fw);
+ DeleteToolBarCommand *cmd = new DeleteToolBarCommand(fw);
+ cmd->init(m_toolBar);
+ fw->commandHistory()->push(cmd);
+}
+
+void ToolBarEventFilter::slotInsertSeparator()
+{
+ QDesignerFormWindowInterface *fw = formWindow();
+ QAction *theSender = qobject_cast<QAction*>(sender());
+ QAction *previous = qvariant_cast<QAction *>(theSender->data());
+ fw->beginCommand(tr("Insert Separator"));
+ QAction *action = createAction(fw, QLatin1String("separator"), true);
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(m_toolBar, action, previous);
+ fw->commandHistory()->push(cmd);
+ fw->endCommand();
+}
+
+QDesignerFormWindowInterface *ToolBarEventFilter::formWindow() const
+{
+ return QDesignerFormWindowInterface::findFormWindow(m_toolBar);
+}
+
+QAction *ToolBarEventFilter::createAction(QDesignerFormWindowInterface *fw, const QString &objectName, bool separator)
+{
+ QAction *action = new QAction(fw);
+ fw->core()->widgetFactory()->initialize(action);
+ if (separator)
+ action->setSeparator(true);
+
+ action->setObjectName(objectName);
+ fw->ensureUniqueObjectName(action);
+
+ qdesigner_internal::AddActionCommand *cmd = new qdesigner_internal::AddActionCommand(fw);
+ cmd->init(action);
+ fw->commandHistory()->push(cmd);
+
+ return action;
+}
+
+void ToolBarEventFilter::adjustDragIndicator(const QPoint &pos)
+{
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QDesignerFormEditorInterface *core = fw->core();
+ if (QDesignerActionProviderExtension *a = qt_extension<QDesignerActionProviderExtension*>(core->extensionManager(), m_toolBar))
+ a->adjustIndicator(pos);
+ }
+}
+
+void ToolBarEventFilter::hideDragIndicator()
+{
+ adjustDragIndicator(QPoint(-1, -1));
+}
+
+bool ToolBarEventFilter::handleMousePressEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton || withinHandleArea(m_toolBar, event->pos()))
+ return false;
+
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ QDesignerFormEditorInterface *core = fw->core();
+ // Keep selection in sync
+ fw->clearSelection(false);
+ if (QDesignerObjectInspector *oi = qobject_cast<QDesignerObjectInspector *>(core->objectInspector())) {
+ oi->clearSelection();
+ oi->selectObject(m_toolBar);
+ }
+ core->propertyEditor()->setObject(m_toolBar);
+ }
+ m_startPosition = m_toolBar->mapFromGlobal(event->globalPos());
+ event->accept();
+ return true;
+}
+
+bool ToolBarEventFilter::handleMouseReleaseEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton || m_startPosition.isNull() || withinHandleArea(m_toolBar, event->pos()))
+ return false;
+
+ // Accept the event, otherwise, form window selection will trigger
+ m_startPosition = QPoint();
+ event->accept();
+ return true;
+}
+
+bool ToolBarEventFilter::handleMouseMoveEvent(QMouseEvent *event)
+{
+ if (m_startPosition.isNull() || withinHandleArea(m_toolBar, event->pos()))
+ return false;
+
+ const QPoint pos = m_toolBar->mapFromGlobal(event->globalPos());
+ if ((pos - m_startPosition).manhattanLength() > qApp->startDragDistance()) {
+ startDrag(m_startPosition, event->modifiers());
+ m_startPosition = QPoint();
+ event->accept();
+ return true;
+ }
+ return false;
+}
+
+bool ToolBarEventFilter::handleDragEnterMoveEvent(QDragMoveEvent *event)
+{
+ const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
+ if (!d)
+ return false;
+
+ if (d->actionList().isEmpty()) {
+ event->ignore();
+ hideDragIndicator();
+ return true;
+ }
+
+ QAction *action = d->actionList().first();
+ if (!action || action->menu() || m_toolBar->actions().contains(action) || !Utils::isObjectAncestorOf(formWindow()->mainContainer(), action)) {
+ event->ignore();
+ hideDragIndicator();
+ return true;
+ }
+
+ d->accept(event);
+ adjustDragIndicator(event->pos());
+ return true;
+}
+
+bool ToolBarEventFilter::handleDragLeaveEvent(QDragLeaveEvent *)
+{
+ hideDragIndicator();
+ return false;
+}
+
+bool ToolBarEventFilter::handleDropEvent(QDropEvent *event)
+{
+ const ActionRepositoryMimeData *d = qobject_cast<const ActionRepositoryMimeData*>(event->mimeData());
+ if (!d)
+ return false;
+
+ if (d->actionList().isEmpty()) {
+ event->ignore();
+ hideDragIndicator();
+ return true;
+ }
+
+ QAction *action = d->actionList().first();
+
+ const ActionList actions = m_toolBar->actions();
+ if (!action || actions.contains(action)) {
+ event->ignore();
+ hideDragIndicator();
+ return true;
+ }
+
+ // Try to find action to 'insert before'. Click on action or in free area, else ignore.
+ QAction *beforeAction = 0;
+ const QPoint pos = event->pos();
+ const int index = actionIndexAt(m_toolBar, pos, m_toolBar->orientation());
+ if (index != -1) {
+ beforeAction = actions.at(index);
+ } else {
+ if (!freeArea(m_toolBar).contains(pos)) {
+ event->ignore();
+ hideDragIndicator();
+ return true;
+ }
+ }
+
+ event->acceptProposedAction();
+ QDesignerFormWindowInterface *fw = formWindow();
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(m_toolBar, action, beforeAction);
+ fw->commandHistory()->push(cmd);
+ hideDragIndicator();
+ return true;
+}
+
+void ToolBarEventFilter::startDrag(const QPoint &pos, Qt::KeyboardModifiers modifiers)
+{
+ const int index = actionIndexAt(m_toolBar, pos, m_toolBar->orientation());
+ if (index == - 1)
+ return;
+
+ const ActionList actions = m_toolBar->actions();
+ QAction *action = actions.at(index);
+ QDesignerFormWindowInterface *fw = formWindow();
+
+ const Qt::DropAction dropAction = (modifiers & Qt::ControlModifier) ? Qt::CopyAction : Qt::MoveAction;
+ if (dropAction == Qt::MoveAction) {
+ RemoveActionFromCommand *cmd = new RemoveActionFromCommand(fw);
+ const int nextIndex = index + 1;
+ QAction *nextAction = nextIndex < actions.size() ? actions.at(nextIndex) : 0;
+ cmd->init(m_toolBar, action, nextAction);
+ fw->commandHistory()->push(cmd);
+ }
+
+ QDrag *drag = new QDrag(m_toolBar);
+ drag->setPixmap(ActionRepositoryMimeData::actionDragPixmap( action));
+ drag->setMimeData(new ActionRepositoryMimeData(action, dropAction));
+
+ if (drag->start(dropAction) == Qt::IgnoreAction) {
+ hideDragIndicator();
+ if (dropAction == Qt::MoveAction) {
+ const ActionList currentActions = m_toolBar->actions();
+ QAction *previous = 0;
+ if (index >= 0 && index < currentActions.size())
+ previous = currentActions.at(index);
+ InsertActionIntoCommand *cmd = new InsertActionIntoCommand(fw);
+ cmd->init(m_toolBar, action, previous);
+ fw->commandHistory()->push(cmd);
+ }
+ }
+}
+
+QAction *ToolBarEventFilter::actionAt(const QToolBar *tb, const QPoint &pos)
+{
+ const int index = actionIndexAt(tb, pos, tb->orientation());
+ if (index == -1)
+ return 0;
+ return tb->actions().at(index);
+}
+
+QRect ToolBarEventFilter::handleArea(const QToolBar *tb)
+{
+ const QToolBarLayout *tbl = qobject_cast<QToolBarLayout *>(tb->layout());
+ Q_ASSERT(tbl);
+ return tbl->handleRect();
+}
+
+bool ToolBarEventFilter::withinHandleArea(const QToolBar *tb, const QPoint &pos)
+{
+ return handleArea(tb).contains(pos);
+}
+
+// Determine the free area behind the last action.
+QRect ToolBarEventFilter::freeArea(const QToolBar *tb)
+{
+ QRect rc = QRect(QPoint(0, 0), tb->size());
+ const ActionList actionList = tb->actions();
+ QRect exclusionRectangle = actionList.empty() ? handleArea(tb) : tb->actionGeometry(actionList.back());
+ switch (tb->orientation()) {
+ case Qt::Horizontal:
+ switch (QApplication::layoutDirection()) {
+ case Qt::LeftToRight:
+ rc.setX(exclusionRectangle.right() + 1);
+ break;
+ case Qt::RightToLeft:
+ rc.setRight(exclusionRectangle.x());
+ break;
+ }
+ break;
+ case Qt::Vertical:
+ rc.setY(exclusionRectangle.bottom() + 1);
+ break;
+ }
+ return rc;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_toolbar_p.h b/tools/designer/src/lib/shared/qdesigner_toolbar_p.h
new file mode 100644
index 0000000000..fd14eb4827
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_toolbar_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_TOOLBAR_H
+#define QDESIGNER_TOOLBAR_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QAction>
+#include <QtGui/QToolButton>
+
+#include <QtCore/QList>
+#include <QtCore/QPoint>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QToolBar;
+class QRect;
+class QAction;
+
+namespace qdesigner_internal {
+
+class PromotionTaskMenu;
+
+// Special event filter for tool bars in designer.
+// Handles drag and drop to and from. Ensures that each
+// child widget is WA_TransparentForMouseEvents to enable drag and drop.
+
+class QDESIGNER_SHARED_EXPORT ToolBarEventFilter : public QObject {
+ Q_OBJECT
+
+public:
+ static void install(QToolBar *tb);
+
+ // Find action by position. Note that QToolBar::actionAt() will
+ // not work as designer sets WA_TransparentForMouseEvents on its tool bar buttons
+ // to be able to drag them. This function will return the dummy
+ // sentinel action when applied to tool bars created by designer if the position matches.
+ static QAction *actionAt(const QToolBar *tb, const QPoint &pos);
+
+ static bool withinHandleArea(const QToolBar *tb, const QPoint &pos);
+ static QRect handleArea(const QToolBar *tb);
+ static QRect freeArea(const QToolBar *tb);
+
+ // Utility to create an action
+ static QAction *createAction(QDesignerFormWindowInterface *fw, const QString &objectName, bool separator);
+
+ virtual bool eventFilter (QObject *watched, QEvent *event);
+
+ // Helper for task menu extension
+ QList<QAction *> contextMenuActions(const QPoint &globalPos = QPoint(-1, -1));
+
+ static ToolBarEventFilter *eventFilterOf(const QToolBar *tb);
+
+private slots:
+ void slotRemoveSelectedAction();
+ void slotRemoveToolBar();
+ void slotInsertSeparator();
+
+private:
+ explicit ToolBarEventFilter(QToolBar *tb);
+
+ bool handleContextMenuEvent(QContextMenuEvent * event);
+ bool handleDragEnterMoveEvent(QDragMoveEvent *event);
+ bool handleDragLeaveEvent(QDragLeaveEvent *);
+ bool handleDropEvent(QDropEvent *event);
+ bool handleMousePressEvent(QMouseEvent *event);
+ bool handleMouseReleaseEvent(QMouseEvent *event);
+ bool handleMouseMoveEvent(QMouseEvent *event);
+
+ QDesignerFormWindowInterface *formWindow() const;
+ void adjustDragIndicator(const QPoint &pos);
+ void hideDragIndicator();
+ void startDrag(const QPoint &pos, Qt::KeyboardModifiers modifiers);
+ bool withinHandleArea(const QPoint &pos) const;
+
+ QToolBar *m_toolBar;
+ PromotionTaskMenu *m_promotionTaskMenu;
+ QPoint m_startPosition;
+};
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TOOLBAR_H
diff --git a/tools/designer/src/lib/shared/qdesigner_toolbox.cpp b/tools/designer/src/lib/shared/qdesigner_toolbox.cpp
new file mode 100644
index 0000000000..46c8ffec8b
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_toolbox.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_toolbox_p.h"
+#include "qdesigner_command_p.h"
+#include "orderdialog_p.h"
+#include "promotiontaskmenu_p.h"
+#include "formwindowbase_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtCore/QEvent>
+#include <QtGui/QAction>
+#include <QtGui/QToolBox>
+#include <QtGui/QMenu>
+#include <QtGui/QLayout>
+#include <QtGui/QApplication>
+#include <QtGui/QContextMenuEvent>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+QToolBoxHelper::QToolBoxHelper(QToolBox *toolbox) :
+ QObject(toolbox),
+ m_toolbox(toolbox),
+ m_actionDeletePage(new QAction(tr("Delete Page"), this)),
+ m_actionInsertPage(new QAction(tr("Before Current Page"), this)),
+ m_actionInsertPageAfter(new QAction(tr("After Current Page"), this)),
+ m_actionChangePageOrder(new QAction(tr("Change Page Order..."), this)),
+ m_pagePromotionTaskMenu(new qdesigner_internal::PromotionTaskMenu(0, qdesigner_internal::PromotionTaskMenu::ModeSingleWidget, this))
+{
+ connect(m_actionDeletePage, SIGNAL(triggered()), this, SLOT(removeCurrentPage()));
+ connect(m_actionInsertPage, SIGNAL(triggered()), this, SLOT(addPage()));
+ connect(m_actionInsertPageAfter, SIGNAL(triggered()), this, SLOT(addPageAfter()));
+ connect(m_actionChangePageOrder, SIGNAL(triggered()), this, SLOT(changeOrder()));
+
+ m_toolbox->installEventFilter(this);
+}
+
+void QToolBoxHelper::install(QToolBox *toolbox)
+{
+ new QToolBoxHelper(toolbox);
+}
+
+bool QToolBoxHelper::eventFilter(QObject *watched, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::ChildPolished:
+ // Install on the buttons
+ if (watched == m_toolbox) {
+ QChildEvent *ce = static_cast<QChildEvent *>(event);
+ if (!qstrcmp(ce->child()->metaObject()->className(), "QToolBoxButton"))
+ ce->child()->installEventFilter(this);
+ }
+ break;
+ case QEvent::ContextMenu:
+ if (watched != m_toolbox) {
+ // An action invoked from the passive interactor (ToolBox button) might
+ // cause its deletion within its event handler, triggering a warning. Re-post
+ // the event to the toolbox.
+ QContextMenuEvent *current = static_cast<QContextMenuEvent *>(event);
+ QContextMenuEvent *copy = new QContextMenuEvent(current->reason(), current->pos(), current-> globalPos(), current->modifiers());
+ QApplication::postEvent(m_toolbox, copy);
+ current->accept();
+ return true;
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if (watched != m_toolbox)
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
+ fw->clearSelection();
+ fw->selectWidget(m_toolbox, true);
+ }
+ break;
+ default:
+ break;
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+QToolBoxHelper *QToolBoxHelper::helperOf(const QToolBox *toolbox)
+{
+ // Look for 1st order children only..otherwise, we might get filters of nested widgets
+ const QObjectList children = toolbox->children();
+ const QObjectList::const_iterator cend = children.constEnd();
+ for (QObjectList::const_iterator it = children.constBegin(); it != cend; ++it) {
+ QObject *o = *it;
+ if (!o->isWidgetType())
+ if (QToolBoxHelper *h = qobject_cast<QToolBoxHelper *>(o))
+ return h;
+ }
+ return 0;
+}
+
+QMenu *QToolBoxHelper::addToolBoxContextMenuActions(const QToolBox *toolbox, QMenu *popup)
+{
+ QToolBoxHelper *helper = helperOf(toolbox);
+ if (!helper)
+ return 0;
+ return helper->addContextMenuActions(popup);
+}
+
+void QToolBoxHelper::removeCurrentPage()
+{
+ if (m_toolbox->currentIndex() == -1 || !m_toolbox->widget(m_toolbox->currentIndex()))
+ return;
+
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
+ qdesigner_internal::DeleteToolBoxPageCommand *cmd = new qdesigner_internal::DeleteToolBoxPageCommand(fw);
+ cmd->init(m_toolbox);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QToolBoxHelper::addPage()
+{
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
+ qdesigner_internal::AddToolBoxPageCommand *cmd = new qdesigner_internal::AddToolBoxPageCommand(fw);
+ cmd->init(m_toolbox, qdesigner_internal::AddToolBoxPageCommand::InsertBefore);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+void QToolBoxHelper::changeOrder()
+{
+ QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox);
+
+ if (!fw)
+ return;
+
+ const QWidgetList oldPages = qdesigner_internal::OrderDialog::pagesOfContainer(fw->core(), m_toolbox);
+ const int pageCount = oldPages.size();
+ if (pageCount < 2)
+ return;
+
+ qdesigner_internal::OrderDialog dlg(fw);
+ dlg.setPageList(oldPages);
+ if (dlg.exec() == QDialog::Rejected)
+ return;
+
+ const QWidgetList newPages = dlg.pageList();
+ if (newPages == oldPages)
+ return;
+
+ fw->beginCommand(tr("Change Page Order"));
+ for(int i=0; i < pageCount; ++i) {
+ if (newPages.at(i) == m_toolbox->widget(i))
+ continue;
+ qdesigner_internal::MoveToolBoxPageCommand *cmd = new qdesigner_internal::MoveToolBoxPageCommand(fw);
+ cmd->init(m_toolbox, newPages.at(i), i);
+ fw->commandHistory()->push(cmd);
+ }
+ fw->endCommand();
+}
+
+void QToolBoxHelper::addPageAfter()
+{
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_toolbox)) {
+ qdesigner_internal::AddToolBoxPageCommand *cmd = new qdesigner_internal::AddToolBoxPageCommand(fw);
+ cmd->init(m_toolbox, qdesigner_internal::AddToolBoxPageCommand::InsertAfter);
+ fw->commandHistory()->push(cmd);
+ }
+}
+
+QPalette::ColorRole QToolBoxHelper::currentItemBackgroundRole() const
+{
+ const QWidget *w = m_toolbox->widget(0);
+ if (!w)
+ return QPalette::Window;
+ return w->backgroundRole();
+}
+
+void QToolBoxHelper::setCurrentItemBackgroundRole(QPalette::ColorRole role)
+{
+ const int count = m_toolbox->count();
+ for (int i = 0; i < count; ++i) {
+ QWidget *w = m_toolbox->widget(i);
+ w->setBackgroundRole(role);
+ w->update();
+ }
+}
+
+QMenu *QToolBoxHelper::addContextMenuActions(QMenu *popup) const
+{
+ QMenu *pageMenu = 0;
+ const int count = m_toolbox->count();
+ m_actionDeletePage->setEnabled(count > 1);
+ if (count) {
+ const QString pageSubMenuLabel = tr("Page %1 of %2").arg(m_toolbox->currentIndex() + 1).arg(count);
+ pageMenu = popup->addMenu(pageSubMenuLabel);
+
+ pageMenu->addAction(m_actionDeletePage);
+ // Set up promotion menu for current widget.
+ if (QWidget *page = m_toolbox->currentWidget ()) {
+ m_pagePromotionTaskMenu->setWidget(page);
+ m_pagePromotionTaskMenu->addActions(QDesignerFormWindowInterface::findFormWindow(m_toolbox),
+ qdesigner_internal::PromotionTaskMenu::SuppressGlobalEdit,
+ pageMenu);
+ }
+ }
+ QMenu *insertPageMenu = popup->addMenu(tr("Insert Page"));
+ insertPageMenu->addAction(m_actionInsertPageAfter);
+ insertPageMenu->addAction(m_actionInsertPage);
+ if (count > 1) {
+ popup->addAction(m_actionChangePageOrder);
+ }
+ popup->addSeparator();
+ return pageMenu;
+}
+
+// -------- QToolBoxWidgetPropertySheet
+
+static const char *currentItemTextKey = "currentItemText";
+static const char *currentItemNameKey = "currentItemName";
+static const char *currentItemIconKey = "currentItemIcon";
+static const char *currentItemToolTipKey = "currentItemToolTip";
+static const char *tabSpacingKey = "tabSpacing";
+
+enum { tabSpacingDefault = -1 };
+
+QToolBoxWidgetPropertySheet::QToolBoxWidgetPropertySheet(QToolBox *object, QObject *parent) :
+ QDesignerPropertySheet(object, parent),
+ m_toolBox(object)
+{
+ createFakeProperty(QLatin1String(currentItemTextKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
+ createFakeProperty(QLatin1String(currentItemNameKey), QString());
+ createFakeProperty(QLatin1String(currentItemIconKey), qVariantFromValue(qdesigner_internal::PropertySheetIconValue()));
+ if (formWindowBase())
+ formWindowBase()->addReloadableProperty(this, indexOf(QLatin1String(currentItemIconKey)));
+ createFakeProperty(QLatin1String(currentItemToolTipKey), qVariantFromValue(qdesigner_internal::PropertySheetStringValue()));
+ createFakeProperty(QLatin1String(tabSpacingKey), QVariant(tabSpacingDefault));
+}
+
+QToolBoxWidgetPropertySheet::ToolBoxProperty QToolBoxWidgetPropertySheet::toolBoxPropertyFromName(const QString &name)
+{
+ typedef QHash<QString, ToolBoxProperty> ToolBoxPropertyHash;
+ static ToolBoxPropertyHash toolBoxPropertyHash;
+ if (toolBoxPropertyHash.empty()) {
+ toolBoxPropertyHash.insert(QLatin1String(currentItemTextKey), PropertyCurrentItemText);
+ toolBoxPropertyHash.insert(QLatin1String(currentItemNameKey), PropertyCurrentItemName);
+ toolBoxPropertyHash.insert(QLatin1String(currentItemIconKey), PropertyCurrentItemIcon);
+ toolBoxPropertyHash.insert(QLatin1String(currentItemToolTipKey), PropertyCurrentItemToolTip);
+ toolBoxPropertyHash.insert(QLatin1String(tabSpacingKey), PropertyTabSpacing);
+ }
+ return toolBoxPropertyHash.value(name, PropertyToolBoxNone);
+}
+
+void QToolBoxWidgetPropertySheet::setProperty(int index, const QVariant &value)
+{
+ const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
+ // independent of index
+ switch (toolBoxProperty) {
+ case PropertyTabSpacing:
+ m_toolBox->layout()->setSpacing(value.toInt());
+ return;
+ case PropertyToolBoxNone:
+ QDesignerPropertySheet::setProperty(index, value);
+ return;
+ default:
+ break;
+ }
+ // index-dependent
+ const int currentIndex = m_toolBox->currentIndex();
+ QWidget *currentWidget = m_toolBox->currentWidget();
+ if (!currentWidget)
+ return;
+
+ switch (toolBoxProperty) {
+ case PropertyCurrentItemText:
+ m_toolBox->setItemText(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].text = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
+ break;
+ case PropertyCurrentItemName:
+ currentWidget->setObjectName(value.toString());
+ break;
+ case PropertyCurrentItemIcon:
+ m_toolBox->setItemIcon(currentIndex, qvariant_cast<QIcon>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].icon = qVariantValue<qdesigner_internal::PropertySheetIconValue>(value);
+ break;
+ case PropertyCurrentItemToolTip:
+ m_toolBox->setItemToolTip(currentIndex, qvariant_cast<QString>(resolvePropertyValue(index, value)));
+ m_pageToData[currentWidget].tooltip = qVariantValue<qdesigner_internal::PropertySheetStringValue>(value);
+ break;
+ case PropertyTabSpacing:
+ case PropertyToolBoxNone:
+ break;
+ }
+}
+
+bool QToolBoxWidgetPropertySheet::isEnabled(int index) const
+{
+ switch (toolBoxPropertyFromName(propertyName(index))) {
+ case PropertyToolBoxNone: // independent of index
+ case PropertyTabSpacing:
+ return QDesignerPropertySheet::isEnabled(index);
+ default:
+ break;
+ }
+ return m_toolBox->currentIndex() != -1;
+}
+
+QVariant QToolBoxWidgetPropertySheet::property(int index) const
+{
+ const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
+ // independent of index
+ switch (toolBoxProperty) {
+ case PropertyTabSpacing:
+ return m_toolBox->layout()->spacing();
+ case PropertyToolBoxNone:
+ return QDesignerPropertySheet::property(index);
+ default:
+ break;
+ }
+ // index-dependent
+ QWidget *currentWidget = m_toolBox->currentWidget();
+ if (!currentWidget) {
+ if (toolBoxProperty == PropertyCurrentItemIcon)
+ return qVariantFromValue(qdesigner_internal::PropertySheetIconValue());
+ if (toolBoxProperty == PropertyCurrentItemText)
+ return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
+ if (toolBoxProperty == PropertyCurrentItemToolTip)
+ return qVariantFromValue(qdesigner_internal::PropertySheetStringValue());
+ return QVariant(QString());
+ }
+
+ // index-dependent
+ switch (toolBoxProperty) {
+ case PropertyCurrentItemText:
+ return qVariantFromValue(m_pageToData.value(currentWidget).text);
+ case PropertyCurrentItemName:
+ return currentWidget->objectName();
+ case PropertyCurrentItemIcon:
+ return qVariantFromValue(m_pageToData.value(currentWidget).icon);
+ case PropertyCurrentItemToolTip:
+ return qVariantFromValue(m_pageToData.value(currentWidget).tooltip);
+ case PropertyTabSpacing:
+ case PropertyToolBoxNone:
+ break;
+ }
+ return QVariant();
+}
+
+bool QToolBoxWidgetPropertySheet::reset(int index)
+{
+ const ToolBoxProperty toolBoxProperty = toolBoxPropertyFromName(propertyName(index));
+ // independent of index
+ switch (toolBoxProperty) {
+ case PropertyTabSpacing:
+ setProperty(index, QVariant(tabSpacingDefault));
+ return true;
+ case PropertyToolBoxNone:
+ return QDesignerPropertySheet::reset(index);
+ default:
+ break;
+ }
+ // index-dependent
+ QWidget *currentWidget = m_toolBox->currentWidget();
+ if (!currentWidget)
+ return false;
+
+ // index-dependent
+ switch (toolBoxProperty) {
+ case PropertyCurrentItemName:
+ setProperty(index, QString());
+ break;
+ case PropertyCurrentItemToolTip:
+ m_pageToData[currentWidget].tooltip = qdesigner_internal::PropertySheetStringValue();
+ setProperty(index, QString());
+ break;
+ case PropertyCurrentItemText:
+ m_pageToData[currentWidget].text = qdesigner_internal::PropertySheetStringValue();
+ setProperty(index, QString());
+ break;
+ case PropertyCurrentItemIcon:
+ m_pageToData[currentWidget].icon = qdesigner_internal::PropertySheetIconValue();
+ setProperty(index, QIcon());
+ break;
+ case PropertyTabSpacing:
+ case PropertyToolBoxNone:
+ break;
+ }
+ return true;
+}
+
+bool QToolBoxWidgetPropertySheet::checkProperty(const QString &propertyName)
+{
+ switch (toolBoxPropertyFromName(propertyName)) {
+ case PropertyCurrentItemText:
+ case PropertyCurrentItemName:
+ case PropertyCurrentItemToolTip:
+ case PropertyCurrentItemIcon:
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_toolbox_p.h b/tools/designer/src/lib/shared/qdesigner_toolbox_p.h
new file mode 100644
index 0000000000..fdd738ad55
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_toolbox_p.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_TOOLBOX_H
+#define QDESIGNER_TOOLBOX_H
+
+#include "shared_global_p.h"
+#include "qdesigner_propertysheet_p.h"
+#include "qdesigner_utils_p.h"
+#include <QtGui/QPalette>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+ class PromotionTaskMenu;
+}
+
+class QToolBox;
+
+class QAction;
+class QMenu;
+
+class QDESIGNER_SHARED_EXPORT QToolBoxHelper : public QObject
+{
+ Q_OBJECT
+
+ explicit QToolBoxHelper(QToolBox *toolbox);
+public:
+ // Install helper on QToolBox
+ static void install(QToolBox *toolbox);
+ static QToolBoxHelper *helperOf(const QToolBox *toolbox);
+ // Convenience to add a menu on a toolbox
+ static QMenu *addToolBoxContextMenuActions(const QToolBox *toolbox, QMenu *popup);
+
+ QPalette::ColorRole currentItemBackgroundRole() const;
+ void setCurrentItemBackgroundRole(QPalette::ColorRole role);
+
+ bool eventFilter(QObject *watched, QEvent *event);
+ // Add context menu and return page submenu or 0.
+
+ QMenu *addContextMenuActions(QMenu *popup) const;
+
+private slots:
+ void removeCurrentPage();
+ void addPage();
+ void addPageAfter();
+ void changeOrder();
+
+private:
+ QToolBox *m_toolbox;
+ QAction *m_actionDeletePage;
+ QAction *m_actionInsertPage;
+ QAction *m_actionInsertPageAfter;
+ QAction *m_actionChangePageOrder;
+ qdesigner_internal::PromotionTaskMenu* m_pagePromotionTaskMenu;
+};
+
+// PropertySheet to handle the page properties
+class QDESIGNER_SHARED_EXPORT QToolBoxWidgetPropertySheet : public QDesignerPropertySheet {
+public:
+ explicit QToolBoxWidgetPropertySheet(QToolBox *object, QObject *parent = 0);
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual QVariant property(int index) const;
+ virtual bool reset(int index);
+ virtual bool isEnabled(int index) const;
+
+ // Check whether the property is to be saved. Returns false for the page
+ // properties (as the property sheet has no concept of 'stored')
+ static bool checkProperty(const QString &propertyName);
+
+private:
+ enum ToolBoxProperty { PropertyCurrentItemText, PropertyCurrentItemName, PropertyCurrentItemIcon,
+ PropertyCurrentItemToolTip, PropertyTabSpacing, PropertyToolBoxNone };
+
+ static ToolBoxProperty toolBoxPropertyFromName(const QString &name);
+ QToolBox *m_toolBox;
+ struct PageData
+ {
+ qdesigner_internal::PropertySheetStringValue text;
+ qdesigner_internal::PropertySheetStringValue tooltip;
+ qdesigner_internal::PropertySheetIconValue icon;
+ };
+ QMap<QWidget *, PageData> m_pageToData;
+};
+
+typedef QDesignerPropertySheetFactory<QToolBox, QToolBoxWidgetPropertySheet> QToolBoxWidgetPropertySheetFactory;
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_TOOLBOX_H
diff --git a/tools/designer/src/lib/shared/qdesigner_utils.cpp b/tools/designer/src/lib/shared/qdesigner_utils.cpp
new file mode 100644
index 0000000000..d2f092eba6
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_utils.cpp
@@ -0,0 +1,734 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_utils_p.h"
+#include "qdesigner_propertycommand_p.h"
+#include "abstractformbuilder.h"
+#include "formwindowbase_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerResourceBrowserInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QDesignerTaskMenuExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QIcon>
+#include <QtGui/QPixmap>
+#include <QtCore/QDir>
+
+#include <QtGui/QApplication>
+#include <QtCore/QProcess>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QDebug>
+#include <QtCore/QQueue>
+#include <QtGui/QListWidget>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QTableWidget>
+#include <QtGui/QComboBox>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal
+{
+ QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message)
+ {
+ qWarning("Designer: %s", qPrintable(message));
+ }
+
+ void reloadTreeItem(DesignerIconCache *iconCache, QTreeWidgetItem *item)
+ {
+ if (!item)
+ return;
+
+ for (int c = 0; c < item->columnCount(); c++) {
+ const QVariant v = item->data(c, Qt::DecorationPropertyRole);
+ if (qVariantCanConvert<PropertySheetIconValue>(v))
+ item->setIcon(c, iconCache->icon(qVariantValue<PropertySheetIconValue>(v)));
+ }
+ }
+
+ void reloadListItem(DesignerIconCache *iconCache, QListWidgetItem *item)
+ {
+ if (!item)
+ return;
+
+ const QVariant v = item->data(Qt::DecorationPropertyRole);
+ if (qVariantCanConvert<PropertySheetIconValue>(v))
+ item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(v)));
+ }
+
+ void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item)
+ {
+ if (!item)
+ return;
+
+ const QVariant v = item->data(Qt::DecorationPropertyRole);
+ if (qVariantCanConvert<PropertySheetIconValue>(v))
+ item->setIcon(iconCache->icon(qVariantValue<PropertySheetIconValue>(v)));
+ }
+
+ void reloadIconResources(DesignerIconCache *iconCache, QObject *object)
+ {
+ if (QListWidget *listWidget = qobject_cast<QListWidget *>(object)) {
+ for (int i = 0; i < listWidget->count(); i++)
+ reloadListItem(iconCache, listWidget->item(i));
+ } else if (QComboBox *comboBox = qobject_cast<QComboBox *>(object)) {
+ for (int i = 0; i < comboBox->count(); i++) {
+ const QVariant v = comboBox->itemData(i, Qt::DecorationPropertyRole);
+ if (qVariantCanConvert<PropertySheetIconValue>(v)) {
+ QIcon icon = iconCache->icon(qVariantValue<PropertySheetIconValue>(v));
+ comboBox->setItemIcon(i, icon);
+ comboBox->setItemData(i, icon);
+ }
+ }
+ } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(object)) {
+ reloadTreeItem(iconCache, treeWidget->headerItem());
+ QQueue<QTreeWidgetItem *> itemsQueue;
+ for (int i = 0; i < treeWidget->topLevelItemCount(); i++)
+ itemsQueue.enqueue(treeWidget->topLevelItem(i));
+ while (!itemsQueue.isEmpty()) {
+ QTreeWidgetItem *item = itemsQueue.dequeue();
+ for (int i = 0; i < item->childCount(); i++)
+ itemsQueue.enqueue(item->child(i));
+ reloadTreeItem(iconCache, item);
+ }
+ } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget *>(object)) {
+ const int columnCount = tableWidget->columnCount();
+ const int rowCount = tableWidget->rowCount();
+ for (int c = 0; c < columnCount; c++)
+ reloadTableItem(iconCache, tableWidget->horizontalHeaderItem(c));
+ for (int r = 0; r < rowCount; r++)
+ reloadTableItem(iconCache, tableWidget->verticalHeaderItem(r));
+ for (int c = 0; c < columnCount; c++)
+ for (int r = 0; r < rowCount; r++)
+ reloadTableItem(iconCache, tableWidget->item(r, c));
+ }
+ }
+
+ // ------------- DesignerMetaEnum
+ DesignerMetaEnum::DesignerMetaEnum(const QString &name, const QString &scope, const QString &separator) :
+ MetaEnum<int>(name, scope, separator)
+ {
+ }
+
+
+ QString DesignerMetaEnum::toString(int value, SerializationMode sm, bool *ok) const
+ {
+ // find value
+ bool valueOk;
+ const QString item = valueToKey(value, &valueOk);
+ if (ok)
+ *ok = valueOk;
+
+ if (!valueOk || sm == NameOnly)
+ return item;
+
+ QString qualifiedItem;
+ appendQualifiedName(item, qualifiedItem);
+ return qualifiedItem;
+ }
+
+ QString DesignerMetaEnum::messageToStringFailed(int value) const
+ {
+ return QCoreApplication::translate("DesignerMetaEnum", "%1 is not a valid enumeration value of '%2'.").arg(value).arg(name());
+ }
+
+ QString DesignerMetaEnum::messageParseFailed(const QString &s) const
+ {
+ return QCoreApplication::translate("DesignerMetaEnum", "'%1' could not be converted to an enumeration value of type '%2'.").arg(s).arg(name());
+ }
+ // -------------- DesignerMetaFlags
+ DesignerMetaFlags::DesignerMetaFlags(const QString &name, const QString &scope, const QString &separator) :
+ MetaEnum<uint>(name, scope, separator)
+ {
+ }
+
+ QStringList DesignerMetaFlags::flags(int ivalue) const
+ {
+ typedef MetaEnum<uint>::KeyToValueMap::const_iterator KeyToValueMapIterator;
+ QStringList rc;
+ const uint v = static_cast<uint>(ivalue);
+ const KeyToValueMapIterator cend = keyToValueMap().constEnd();
+ for (KeyToValueMapIterator it = keyToValueMap().constBegin();it != cend; ++it ) {
+ const uint itemValue = it.value();
+ // Check for equality first as flag values can be 0 or -1, too. Takes preference over a bitwise flag
+ if (v == itemValue) {
+ rc.clear();
+ rc.push_back(it.key());
+ return rc;
+ }
+ // Do not add 0-flags (None-flags)
+ if (itemValue)
+ if ((v & itemValue) == itemValue)
+ rc.push_back(it.key());
+ }
+ return rc;
+ }
+
+
+ QString DesignerMetaFlags::toString(int value, SerializationMode sm) const
+ {
+ const QStringList flagIds = flags(value);
+ if (flagIds.empty())
+ return QString();
+
+ const QChar delimiter = QLatin1Char('|');
+ QString rc;
+ const QStringList::const_iterator cend = flagIds.constEnd();
+ for (QStringList::const_iterator it = flagIds.constBegin(); it != cend; ++it) {
+ if (!rc.isEmpty())
+ rc += delimiter ;
+ if (sm == FullyQualified)
+ appendQualifiedName(*it, rc);
+ else
+ rc += *it;
+ }
+ return rc;
+ }
+
+
+ int DesignerMetaFlags::parseFlags(const QString &s, bool *ok) const
+ {
+ if (s.isEmpty()) {
+ if (ok)
+ *ok = true;
+ return 0;
+ }
+ uint flags = 0;
+ bool valueOk = true;
+ QStringList keys = s.split(QString(QLatin1Char('|')));
+ const QStringList::iterator cend = keys.end();
+ for (QStringList::iterator it = keys.begin(); it != cend; ++it) {
+ const uint flagValue = keyToValue(*it, &valueOk);
+ if (!valueOk) {
+ flags = 0;
+ break;
+ }
+ flags |= flagValue;
+ }
+ if (ok)
+ *ok = valueOk;
+ return static_cast<int>(flags);
+ }
+
+ QString DesignerMetaFlags::messageParseFailed(const QString &s) const
+ {
+ return QCoreApplication::translate("DesignerMetaFlags", "'%1' could not be converted to a flag value of type '%2'.").arg(s).arg(name());
+ }
+
+ // ---------- PropertySheetEnumValue
+
+ PropertySheetEnumValue::PropertySheetEnumValue(int v, const DesignerMetaEnum &me) :
+ value(v),
+ metaEnum(me)
+ {
+ }
+ PropertySheetEnumValue::PropertySheetEnumValue() :
+ value(0)
+ {
+ }
+
+ // ---------------- PropertySheetFlagValue
+ PropertySheetFlagValue::PropertySheetFlagValue(int v, const DesignerMetaFlags &mf) :
+ value(v),
+ metaFlags(mf)
+ {
+ }
+
+ PropertySheetFlagValue::PropertySheetFlagValue() :
+ value(0)
+ {
+ }
+
+ // ---------------- PropertySheetPixmapValue
+ PropertySheetPixmapValue::PropertySheetPixmapValue(const QString &path) : m_path(path)
+ {
+ }
+
+ PropertySheetPixmapValue::PropertySheetPixmapValue()
+ {
+ }
+
+ PropertySheetPixmapValue::PixmapSource PropertySheetPixmapValue::getPixmapSource(QDesignerFormEditorInterface *core, const QString & path)
+ {
+ if (const QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
+ return lang->isLanguageResource(path) ? LanguageResourcePixmap : FilePixmap;
+ return path.startsWith(QLatin1Char(':')) ? ResourcePixmap : FilePixmap;
+ }
+
+ int PropertySheetPixmapValue::compare(const PropertySheetPixmapValue &other) const
+ {
+ return m_path.compare(other.m_path);
+ }
+
+ QString PropertySheetPixmapValue::path() const
+ {
+ return m_path;
+ }
+
+ void PropertySheetPixmapValue::setPath(const QString &path)
+ {
+ if (m_path == path)
+ return;
+ m_path = path;
+ }
+
+ // ---------- PropertySheetIconValue
+ PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap)
+ {
+ setPixmap(QIcon::Normal, QIcon::Off, pixmap);
+ }
+
+ PropertySheetIconValue::PropertySheetIconValue()
+ {
+ }
+
+ bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const
+ {
+ return m_paths == rhs.m_paths;
+ }
+
+ bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const
+ {
+ QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_paths);
+ QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_paths);
+ while (itThis.hasNext() && itOther.hasNext()) {
+ const ModeStateKey thisPair = itThis.next().key();
+ const ModeStateKey otherPair = itOther.next().key();
+ if (thisPair < otherPair)
+ return true;
+ else if (otherPair < thisPair)
+ return false;
+ const int crc = itThis.value().compare(itOther.value());
+ if (crc < 0)
+ return true;
+ if (crc > 0)
+ return false;
+ }
+ if (itOther.hasNext())
+ return true;
+ return false;
+ }
+
+ PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const
+ {
+ const ModeStateKey pair = qMakePair(mode, state);
+ return m_paths.value(pair);
+ }
+
+ void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap)
+ {
+ const ModeStateKey pair = qMakePair(mode, state);
+ if (pixmap.path().isEmpty())
+ m_paths.remove(pair);
+ else
+ m_paths.insert(pair, pixmap);
+ }
+
+ QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const
+ {
+ QMap<PropertySheetPixmapValue, QPixmap>::const_iterator it = m_cache.constFind(value);
+ if (it != m_cache.constEnd())
+ return it.value();
+
+ QPixmap pix = QPixmap(value.path());
+ m_cache.insert(value, pix);
+ return pix;
+ }
+
+ void DesignerPixmapCache::clear()
+ {
+ m_cache.clear();
+ }
+
+ DesignerPixmapCache::DesignerPixmapCache(QObject *parent)
+ : QObject(parent)
+ {
+ }
+
+ QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const
+ {
+ QMap<PropertySheetIconValue, QIcon>::const_iterator it = m_cache.constFind(value);
+ if (it != m_cache.constEnd())
+ return it.value();
+
+ QIcon icon;
+ QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> paths = value.paths();
+ QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPath(paths);
+ while (itPath.hasNext()) {
+ QPair<QIcon::Mode, QIcon::State> pair = itPath.next().key();
+ icon.addPixmap(m_pixmapCache->pixmap(itPath.value()), pair.first, pair.second);
+ }
+ m_cache.insert(value, icon);
+ return icon;
+ }
+
+ void DesignerIconCache::clear()
+ {
+ m_cache.clear();
+ }
+
+ DesignerIconCache::DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent)
+ : QObject(parent),
+ m_pixmapCache(pixmapCache)
+ {
+
+ }
+
+ PropertySheetStringValue::PropertySheetStringValue(const QString &value,
+ bool translatable, const QString &disambiguation, const QString &comment)
+ : m_value(value), m_translatable(translatable), m_disambiguation(disambiguation), m_comment(comment)
+ { }
+
+ QString PropertySheetStringValue::value() const
+ {
+ return m_value;
+ }
+
+ void PropertySheetStringValue::setValue(const QString &value)
+ {
+ m_value = value;
+ }
+
+ bool PropertySheetStringValue::translatable() const
+ {
+ return m_translatable;
+ }
+
+ void PropertySheetStringValue::setTranslatable(bool translatable)
+ {
+ m_translatable = translatable;
+ }
+
+ QString PropertySheetStringValue::disambiguation() const
+ {
+ return m_disambiguation;
+ }
+
+ void PropertySheetStringValue::setDisambiguation(const QString &disambiguation)
+ {
+ m_disambiguation = disambiguation;
+ }
+
+ QString PropertySheetStringValue::comment() const
+ {
+ return m_comment;
+ }
+
+ void PropertySheetStringValue::setComment(const QString &comment)
+ {
+ m_comment = comment;
+ }
+
+ bool PropertySheetStringValue::equals(const PropertySheetStringValue &rhs) const
+ {
+ return (m_value == rhs.m_value) && (m_translatable == rhs.m_translatable)
+ && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment);
+ }
+
+ PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence &value,
+ bool translatable, const QString &disambiguation, const QString &comment)
+ : m_value(value),
+ m_standardKey(QKeySequence::UnknownKey),
+ m_translatable(translatable),
+ m_disambiguation(disambiguation),
+ m_comment(comment)
+ { }
+
+ PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence::StandardKey &standardKey,
+ bool translatable, const QString &disambiguation, const QString &comment)
+ : m_value(QKeySequence(standardKey)),
+ m_standardKey(standardKey),
+ m_translatable(translatable),
+ m_disambiguation(disambiguation),
+ m_comment(comment)
+ { }
+
+ QKeySequence PropertySheetKeySequenceValue::value() const
+ {
+ return m_value;
+ }
+
+ void PropertySheetKeySequenceValue::setValue(const QKeySequence &value)
+ {
+ m_value = value;
+ m_standardKey = QKeySequence::UnknownKey;
+ }
+
+ QKeySequence::StandardKey PropertySheetKeySequenceValue::standardKey() const
+ {
+ return m_standardKey;
+ }
+
+ void PropertySheetKeySequenceValue::setStandardKey(const QKeySequence::StandardKey &standardKey)
+ {
+ m_value = QKeySequence(standardKey);
+ m_standardKey = standardKey;
+ }
+
+ bool PropertySheetKeySequenceValue::isStandardKey() const
+ {
+ return m_standardKey != QKeySequence::UnknownKey;
+ }
+
+ QString PropertySheetKeySequenceValue::comment() const
+ {
+ return m_comment;
+ }
+
+ void PropertySheetKeySequenceValue::setComment(const QString &comment)
+ {
+ m_comment = comment;
+ }
+
+ QString PropertySheetKeySequenceValue::disambiguation() const
+ {
+ return m_disambiguation;
+ }
+
+ void PropertySheetKeySequenceValue::setDisambiguation(const QString &disambiguation)
+ {
+ m_disambiguation = disambiguation;
+ }
+
+ bool PropertySheetKeySequenceValue::translatable() const
+ {
+ return m_translatable;
+ }
+
+ void PropertySheetKeySequenceValue::setTranslatable(bool translatable)
+ {
+ m_translatable = translatable;
+ }
+
+ bool PropertySheetKeySequenceValue::equals(const PropertySheetKeySequenceValue &rhs) const
+ {
+ return (m_value == rhs.m_value) && (m_standardKey == rhs.m_standardKey)
+ && (m_translatable == rhs.m_translatable) && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment);
+ }
+
+ class StateMap
+ {
+ public:
+ StateMap()
+ {
+ m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::Off), 0x01);
+ m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::On), 0x02);
+ m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::Off), 0x04);
+ m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::On), 0x08);
+ m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::Off), 0x10);
+ m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::On), 0x20);
+ m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::Off), 0x40);
+ m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::On), 0x80);
+
+ m_flagToState.insert(0x01, qMakePair(QIcon::Normal, QIcon::Off));
+ m_flagToState.insert(0x02, qMakePair(QIcon::Normal, QIcon::On));
+ m_flagToState.insert(0x04, qMakePair(QIcon::Disabled, QIcon::Off));
+ m_flagToState.insert(0x08, qMakePair(QIcon::Disabled, QIcon::On));
+ m_flagToState.insert(0x10, qMakePair(QIcon::Active, QIcon::Off));
+ m_flagToState.insert(0x20, qMakePair(QIcon::Active, QIcon::On));
+ m_flagToState.insert(0x40, qMakePair(QIcon::Selected, QIcon::Off));
+ m_flagToState.insert(0x80, qMakePair(QIcon::Selected, QIcon::On));
+ }
+ uint flag(const QPair<QIcon::Mode, QIcon::State> &pair) const
+ {
+ return m_stateToFlag.value(pair);
+ }
+ QPair<QIcon::Mode, QIcon::State> state(uint flag) const
+ {
+ return m_flagToState.value(flag);
+ }
+ private:
+ QMap<QPair<QIcon::Mode, QIcon::State>, uint > m_stateToFlag;
+ QMap<uint, QPair<QIcon::Mode, QIcon::State> > m_flagToState;
+ };
+
+ Q_GLOBAL_STATIC(StateMap, stateMap)
+
+ uint PropertySheetIconValue::mask() const
+ {
+ uint flags = 0;
+ QMapIterator<ModeStateKey, PropertySheetPixmapValue> itPath(m_paths);
+ while (itPath.hasNext())
+ flags |= stateMap()->flag(itPath.next().key());
+ return flags;
+ }
+
+ uint PropertySheetIconValue::compare(const PropertySheetIconValue &other) const
+ {
+ uint diffMask = mask() | other.mask();
+ for (int i = 0; i < 8; i++) {
+ uint flag = 1 << i;
+ if (diffMask & flag) { // if state is set in both icons, compare the values
+ const ModeStateKey state = stateMap()->state(flag);
+ if (pixmap(state.first, state.second) == other.pixmap(state.first, state.second))
+ diffMask &= ~flag;
+ }
+ }
+ return diffMask;
+ }
+
+ void PropertySheetIconValue::assign(const PropertySheetIconValue &other, uint mask)
+ {
+ for (int i = 0; i < 8; i++) {
+ uint flag = 1 << i;
+ if (mask & flag) {
+ const ModeStateKey state = stateMap()->state(flag);
+ setPixmap(state.first, state.second, other.pixmap(state.first, state.second));
+ }
+ }
+ }
+
+ PropertySheetIconValue::ModeStateToPixmapMap PropertySheetIconValue::paths() const
+ {
+ return m_paths;
+ }
+
+ QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw)
+ {
+ if (text.isEmpty()) {
+ ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
+ cmd->init(object, propertyName);
+ return cmd;
+ }
+ SetPropertyCommand *cmd = new SetPropertyCommand(fw);
+ cmd->init(object, propertyName, text);
+ return cmd;
+ }
+
+ QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget)
+ {
+ QAction *action = 0;
+ if (const QDesignerTaskMenuExtension *taskMenu = qt_extension<QDesignerTaskMenuExtension*>(core->extensionManager(), managedWidget)) {
+ action = taskMenu->preferredEditAction();
+ if (!action) {
+ const QList<QAction *> actions = taskMenu->taskActions();
+ if (!actions.isEmpty())
+ action = actions.first();
+ }
+ }
+ if (!action) {
+ if (const QDesignerTaskMenuExtension *taskMenu = qobject_cast<QDesignerTaskMenuExtension *>(
+ core->extensionManager()->extension(managedWidget, QLatin1String("QDesignerInternalTaskMenuExtension")))) {
+ action = taskMenu->preferredEditAction();
+ if (!action) {
+ const QList<QAction *> actions = taskMenu->taskActions();
+ if (!actions.isEmpty())
+ action = actions.first();
+ }
+ }
+ }
+ return action;
+ }
+
+ QDESIGNER_SHARED_EXPORT bool runUIC(const QString &fileName, UIC_Mode mode, QByteArray& ba, QString &errorMessage)
+ {
+ QStringList argv;
+ QString binary = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+ binary += QDir::separator();
+ switch (mode) {
+ case UIC_GenerateCode:
+ binary += QLatin1String("uic");
+ break;
+ case UIC_ConvertV3:
+ binary += QLatin1String("uic3");
+ argv += QLatin1String("-convert");
+ break;
+ }
+ argv += fileName;
+ QProcess uic;
+ uic.start(binary, argv);
+ if (!uic.waitForStarted()) {
+ errorMessage = QApplication::translate("Designer", "Unable to launch %1.").arg(binary);
+ return false;
+ }
+ if (!uic.waitForFinished()) {
+ errorMessage = QApplication::translate("Designer", "%1 timed out.").arg(binary);
+ return false;
+ }
+ if (uic.exitCode()) {
+ errorMessage = QString::fromAscii(uic.readAllStandardError());
+ return false;
+ }
+ ba = uic.readAllStandardOutput();
+ return true;
+ }
+
+ QDESIGNER_SHARED_EXPORT QString qtify(const QString &name)
+ {
+ QString qname = name;
+
+ Q_ASSERT(qname.isEmpty() == false);
+
+
+ if (qname.count() > 1 && qname.at(1).isUpper()) {
+ const QChar first = qname.at(0);
+ if (first == QLatin1Char('Q') || first == QLatin1Char('K'))
+ qname.remove(0, 1);
+ }
+
+ const int len = qname.count();
+ for (int i = 0; i < len && qname.at(i).isUpper(); i++)
+ qname[i] = qname.at(i).toLower();
+
+ return qname;
+ }
+
+ // --------------- UpdateBlocker
+ UpdateBlocker::UpdateBlocker(QWidget *w) :
+ m_widget(w),
+ m_enabled(w->updatesEnabled() && w->isVisible())
+ {
+ if (m_enabled)
+ m_widget->setUpdatesEnabled(false);
+ }
+
+ UpdateBlocker::~UpdateBlocker()
+ {
+ if (m_enabled)
+ m_widget->setUpdatesEnabled(true);
+ }
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_utils_p.h b/tools/designer/src/lib/shared/qdesigner_utils_p.h
new file mode 100644
index 0000000000..85b3090af9
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_utils_p.h
@@ -0,0 +1,482 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_UTILS_H
+#define QDESIGNER_UTILS_H
+
+#include "shared_global_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtCore/QVariant>
+#include <QtCore/QMap>
+#include <QtGui/QMainWindow>
+#include <QtGui/QIcon>
+#include <QtGui/QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+class QDesignerFormWindowCommand;
+class DesignerIconCache;
+class FormWindowBase;
+
+
+QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message);
+
+QDESIGNER_SHARED_EXPORT void reloadIconResources(DesignerIconCache *iconCache, QObject *object);
+
+/* Flag/Enumeration helpers for the property sheet: Enumeration or flag values are returned by the property sheet
+ * as a pair of meta type and integer value.
+ * The meta type carries all the information required for the property editor and serialization
+ * by the form builders (names, etc).
+ * Note that the property editor uses unqualified names ("Cancel") while the form builder serialization (uic)
+ * requires the whole string
+ * ("QDialogButtonBox::Cancel" or "com.trolltech.qt.gui.QDialogButtonBox.StandardButton.Cancel").*/
+
+/* --------- MetaEnum: Base class representing a QMetaEnum with lookup functions
+ * in both ways. Template of int type since unsigned is more suitable for flags.
+ * The keyToValue() is ignorant of scopes, it can handle fully qualified or unqualified names. */
+
+template <class IntType>
+class MetaEnum
+{
+public:
+ typedef QMap<QString, IntType> KeyToValueMap;
+
+ MetaEnum(const QString &name, const QString &scope, const QString &separator);
+ MetaEnum() {}
+ void addKey(IntType value, const QString &name);
+
+ QString valueToKey(IntType value, bool *ok = 0) const;
+ // Ignorant of scopes.
+ IntType keyToValue(QString key, bool *ok = 0) const;
+
+ const QString &name() const { return m_name; }
+ const QString &scope() const { return m_scope; }
+ const QString &separator() const { return m_separator; }
+
+ const QStringList &keys() const { return m_keys; }
+ const KeyToValueMap &keyToValueMap() const { return m_keyToValueMap; }
+
+protected:
+ void appendQualifiedName(const QString &key, QString &target) const;
+
+private:
+ QString m_name;
+ QString m_scope;
+ QString m_separator;
+ KeyToValueMap m_keyToValueMap;
+ QStringList m_keys;
+};
+
+template <class IntType>
+MetaEnum<IntType>::MetaEnum(const QString &name, const QString &scope, const QString &separator) :
+ m_name(name),
+ m_scope(scope),
+ m_separator(separator)
+{
+}
+
+template <class IntType>
+void MetaEnum<IntType>::addKey(IntType value, const QString &name)
+{
+ m_keyToValueMap.insert(name, value);
+ m_keys.append(name);
+}
+
+template <class IntType>
+QString MetaEnum<IntType>::valueToKey(IntType value, bool *ok) const
+{
+ const QString rc = m_keyToValueMap.key(value);
+ if (ok)
+ *ok = !rc.isEmpty();
+ return rc;
+}
+
+template <class IntType>
+IntType MetaEnum<IntType>::keyToValue(QString key, bool *ok) const
+{
+ if (!m_scope.isEmpty() && key.startsWith(m_scope))
+ key.remove(0, m_scope.size() + m_separator.size());
+ const Q_TYPENAME KeyToValueMap::const_iterator it = m_keyToValueMap.find(key);
+ const bool found = it != m_keyToValueMap.constEnd();
+ if (ok)
+ *ok = found;
+ return found ? it.value() : IntType(0);
+}
+
+template <class IntType>
+void MetaEnum<IntType>::appendQualifiedName(const QString &key, QString &target) const
+{
+ if (!m_scope.isEmpty()) {
+ target += m_scope;
+ target += m_separator;
+ }
+ target += key;
+}
+
+// -------------- DesignerMetaEnum: Meta type for enumerations
+
+class QDESIGNER_SHARED_EXPORT DesignerMetaEnum : public MetaEnum<int>
+{
+public:
+ DesignerMetaEnum(const QString &name, const QString &scope, const QString &separator);
+ DesignerMetaEnum() {}
+
+ enum SerializationMode { FullyQualified, NameOnly };
+ QString toString(int value, SerializationMode sm, bool *ok = 0) const;
+
+ QString messageToStringFailed(int value) const;
+ QString messageParseFailed(const QString &s) const;
+
+ // parse a string (ignorant of scopes)
+ int parseEnum(const QString &s, bool *ok = 0) const { return keyToValue(s, ok); }
+};
+
+// -------------- DesignerMetaFlags: Meta type for flags.
+// Note that while the handling of flags is done using unsigned integers, the actual values returned
+// by the property system are integers.
+
+class QDESIGNER_SHARED_EXPORT DesignerMetaFlags : public MetaEnum<uint>
+{
+public:
+ DesignerMetaFlags(const QString &name, const QString &scope, const QString &separator);
+ DesignerMetaFlags() {}
+
+ enum SerializationMode { FullyQualified, NameOnly };
+ QString toString(int value, SerializationMode sm) const;
+ QStringList flags(int value) const;
+
+ QString messageParseFailed(const QString &s) const;
+ // parse a string (ignorant of scopes)
+ int parseFlags(const QString &s, bool *ok = 0) const;
+};
+
+// -------------- EnumValue: Returned by the property sheet for enumerations
+
+struct QDESIGNER_SHARED_EXPORT PropertySheetEnumValue
+{
+ PropertySheetEnumValue(int v, const DesignerMetaEnum &me);
+ PropertySheetEnumValue();
+
+ int value;
+ DesignerMetaEnum metaEnum;
+};
+
+// -------------- FlagValue: Returned by the property sheet for flags
+
+struct QDESIGNER_SHARED_EXPORT PropertySheetFlagValue
+{
+ PropertySheetFlagValue(int v, const DesignerMetaFlags &mf);
+ PropertySheetFlagValue();
+
+ int value;
+ DesignerMetaFlags metaFlags;
+};
+
+// -------------- PixmapValue: Returned by the property sheet for pixmaps
+class QDESIGNER_SHARED_EXPORT PropertySheetPixmapValue
+{
+public:
+ PropertySheetPixmapValue(const QString &path);
+ PropertySheetPixmapValue();
+
+ bool operator==(const PropertySheetPixmapValue &other) const { return compare(other) == 0; }
+ bool operator!=(const PropertySheetPixmapValue &other) const { return compare(other) != 0; }
+ bool operator<(const PropertySheetPixmapValue &other) const { return compare(other) < 0; }
+
+ // Check where a pixmap comes from
+ enum PixmapSource { LanguageResourcePixmap , ResourcePixmap, FilePixmap };
+ static PixmapSource getPixmapSource(QDesignerFormEditorInterface *core, const QString & path);
+
+ PixmapSource pixmapSource(QDesignerFormEditorInterface *core) const { return getPixmapSource(core, m_path); }
+
+ QString path() const;
+ void setPath(const QString &path); // passing the empty path resets the pixmap
+
+ int compare(const PropertySheetPixmapValue &other) const;
+
+private:
+ QString m_path;
+};
+
+// -------------- IconValue: Returned by the property sheet for icons
+
+class QDESIGNER_SHARED_EXPORT PropertySheetIconValue
+{
+ public:
+ PropertySheetIconValue(const PropertySheetPixmapValue &pixmap);
+ PropertySheetIconValue();
+
+ bool operator==(const PropertySheetIconValue &other) const { return equals(other); }
+ bool operator!=(const PropertySheetIconValue &other) const { return !equals(other); }
+ bool operator<(const PropertySheetIconValue &other) const;
+
+ PropertySheetPixmapValue pixmap(QIcon::Mode mode, QIcon::State state) const;
+ void setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &path); // passing the empty path resets the pixmap
+
+ uint mask() const;
+ uint compare(const PropertySheetIconValue &other) const;
+ void assign(const PropertySheetIconValue &other, uint mask);
+
+ typedef QPair<QIcon::Mode, QIcon::State> ModeStateKey;
+ typedef QMap<ModeStateKey, PropertySheetPixmapValue> ModeStateToPixmapMap;
+
+ ModeStateToPixmapMap paths() const;
+
+private:
+ bool equals(const PropertySheetIconValue &rhs) const;
+
+ ModeStateToPixmapMap m_paths;
+};
+
+class QDESIGNER_SHARED_EXPORT DesignerPixmapCache : public QObject
+{
+ Q_OBJECT
+public:
+ DesignerPixmapCache(QObject *parent = 0);
+ QPixmap pixmap(const PropertySheetPixmapValue &value) const;
+ void clear();
+signals:
+ void reloaded();
+private:
+ mutable QMap<PropertySheetPixmapValue, QPixmap> m_cache;
+ friend class FormWindowBase;
+};
+
+class QDESIGNER_SHARED_EXPORT DesignerIconCache : public QObject
+{
+ Q_OBJECT
+public:
+ DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent = 0);
+ QIcon icon(const PropertySheetIconValue &value) const;
+ void clear();
+signals:
+ void reloaded();
+private:
+ mutable QMap<PropertySheetIconValue, QIcon> m_cache;
+ DesignerPixmapCache *m_pixmapCache;
+ friend class FormWindowBase;
+};
+
+// -------------- StringValue: Returned by the property sheet for strings
+class QDESIGNER_SHARED_EXPORT PropertySheetStringValue
+{
+public:
+ PropertySheetStringValue(const QString &value = QString(),
+ bool translatable = true,
+ const QString &disambiguation = QString(),
+ const QString &comment = QString());
+
+ bool operator==(const PropertySheetStringValue &other) const { return equals(other); }
+ bool operator!=(const PropertySheetStringValue &other) const { return !equals(other); }
+
+ QString value() const;
+ void setValue(const QString &value);
+ bool translatable() const;
+ void setTranslatable(bool translatable);
+ QString disambiguation() const;
+ void setDisambiguation(const QString &disambiguation);
+ QString comment() const;
+ void setComment(const QString &comment);
+
+private:
+ bool equals(const PropertySheetStringValue &rhs) const;
+
+ QString m_value;
+ bool m_translatable;
+ QString m_disambiguation;
+ QString m_comment;
+};
+
+
+
+// -------------- StringValue: Returned by the property sheet for strings
+class QDESIGNER_SHARED_EXPORT PropertySheetKeySequenceValue
+{
+public:
+ PropertySheetKeySequenceValue(const QKeySequence &value = QKeySequence(),
+ bool translatable = true,
+ const QString &disambiguation = QString(),
+ const QString &comment = QString());
+ PropertySheetKeySequenceValue(const QKeySequence::StandardKey &standardKey,
+ bool translatable = true,
+ const QString &disambiguation = QString(),
+ const QString &comment = QString());
+
+ bool operator==(const PropertySheetKeySequenceValue &other) const { return equals(other); }
+ bool operator!=(const PropertySheetKeySequenceValue &other) const { return !equals(other); }
+
+ QKeySequence value() const;
+ void setValue(const QKeySequence &value);
+ QKeySequence::StandardKey standardKey() const;
+ void setStandardKey(const QKeySequence::StandardKey &standardKey);
+ bool isStandardKey() const;
+
+ bool translatable() const;
+ void setTranslatable(bool translatable);
+ QString disambiguation() const;
+ void setDisambiguation(const QString &disambiguation);
+ QString comment() const;
+ void setComment(const QString &comment);
+
+private:
+ bool equals(const PropertySheetKeySequenceValue &rhs) const;
+
+ QKeySequence m_value;
+ QKeySequence::StandardKey m_standardKey;
+ bool m_translatable;
+ QString m_disambiguation;
+ QString m_comment;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+
+// NOTE: Do not move this code, needed for GCC 3.3
+Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetEnumValue)
+Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetFlagValue)
+Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetPixmapValue)
+Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetIconValue)
+Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetStringValue)
+Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetKeySequenceValue)
+
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+
+// Create a command to change a text property (that is, create a reset property command if the text is empty)
+QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw);
+
+// Returns preferred task menu action for managed widget
+QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget);
+
+// Convenience to run UIC
+enum UIC_Mode { UIC_GenerateCode, UIC_ConvertV3 };
+QDESIGNER_SHARED_EXPORT bool runUIC(const QString &fileName, UIC_Mode mode, QByteArray& ba, QString &errorMessage);
+
+// Find a suitable variable name for a class.
+QDESIGNER_SHARED_EXPORT QString qtify(const QString &name);
+
+/* UpdateBlocker: Blocks the updates of the widget passed on while in scope.
+ * Does nothing if the incoming widget already has updatesEnabled==false
+ * which is important to avoid side-effects when putting it into QStackedLayout. */
+
+class QDESIGNER_SHARED_EXPORT UpdateBlocker {
+ Q_DISABLE_COPY(UpdateBlocker)
+
+public:
+ UpdateBlocker(QWidget *w);
+ ~UpdateBlocker();
+
+private:
+ QWidget *m_widget;
+ const bool m_enabled;
+};
+
+namespace Utils {
+
+inline int valueOf(const QVariant &value, bool *ok = 0)
+{
+ if (qVariantCanConvert<PropertySheetEnumValue>(value)) {
+ if (ok)
+ *ok = true;
+ return qVariantValue<PropertySheetEnumValue>(value).value;
+ }
+ else if (qVariantCanConvert<PropertySheetFlagValue>(value)) {
+ if (ok)
+ *ok = true;
+ return qVariantValue<PropertySheetFlagValue>(value).value;
+ }
+ return value.toInt(ok);
+}
+
+inline bool isObjectAncestorOf(QObject *ancestor, QObject *child)
+{
+ QObject *obj = child;
+ while (obj != 0) {
+ if (obj == ancestor)
+ return true;
+ obj = obj->parent();
+ }
+ return false;
+}
+
+inline bool isCentralWidget(QDesignerFormWindowInterface *fw, QWidget *widget)
+{
+ if (! fw || ! widget)
+ return false;
+
+ if (widget == fw->mainContainer())
+ return true;
+
+ // ### generalize for other containers
+ if (QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer())) {
+ return mw->centralWidget() == widget;
+ }
+
+ return false;
+}
+
+} // namespace Utils
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_UTILS_H
diff --git a/tools/designer/src/lib/shared/qdesigner_widget.cpp b/tools/designer/src/lib/shared/qdesigner_widget.cpp
new file mode 100644
index 0000000000..6d2be17ac0
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_widget.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_widget_p.h"
+#include "formwindowbase_p.h"
+#include "grid_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtGui/QPainter>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+/* QDesignerDialog / QDesignerWidget are used to paint a grid on QDialog and QWidget main containers
+ * and container extension pages.
+ * The paint routines work as follows:
+ * We need to clean the background here (to make the parent grid disappear in case we are a container page
+ * and to make palette background settings take effect),
+ * which would normally break style sheets with background settings.
+ * So, we manually make the style paint after cleaning. On top comes the grid
+ * In addition, this code works around
+ * the QStyleSheetStyle setting Qt::WA_StyledBackground to false for subclasses of QWidget.
+ */
+
+QDesignerDialog::QDesignerDialog(QDesignerFormWindowInterface *fw, QWidget *parent) :
+ QDialog(parent),
+ m_formWindow(qobject_cast<qdesigner_internal::FormWindowBase*>(fw))
+{
+}
+
+void QDesignerDialog::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ QStyleOption opt;
+ opt.initFrom(this);
+ p.fillRect(e->rect(), palette().brush(backgroundRole()));
+ style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+ if (m_formWindow && m_formWindow->gridVisible())
+ m_formWindow->designerGrid().paint(p, this, e);
+}
+
+QDesignerWidget::QDesignerWidget(QDesignerFormWindowInterface* formWindow, QWidget *parent) :
+ QWidget(parent),
+ m_formWindow(qobject_cast<qdesigner_internal::FormWindowBase*>(formWindow))
+{
+}
+
+QDesignerWidget::~QDesignerWidget()
+{
+}
+
+QDesignerFormWindowInterface* QDesignerWidget::formWindow() const
+{
+ return m_formWindow;
+}
+
+void QDesignerWidget::paintEvent(QPaintEvent *e)
+{
+ QPainter p(this);
+ QStyleOption opt;
+ opt.initFrom(this);
+ p.fillRect(e->rect(), palette().brush(backgroundRole()));
+ style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+ if (m_formWindow && m_formWindow->gridVisible())
+ m_formWindow->designerGrid().paint(p, this, e);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_widget_p.h b/tools/designer/src/lib/shared/qdesigner_widget_p.h
new file mode 100644
index 0000000000..77d3934981
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_widget_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_WIDGET_H
+#define QDESIGNER_WIDGET_H
+
+#include "shared_global_p.h"
+#include <QtGui/QDialog>
+#include <QtGui/QLabel>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+ class FormWindowBase;
+}
+
+class QDESIGNER_SHARED_EXPORT QDesignerWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit QDesignerWidget(QDesignerFormWindowInterface* formWindow, QWidget *parent = 0);
+ virtual ~QDesignerWidget();
+
+ QDesignerFormWindowInterface* formWindow() const;
+
+ void updatePixmap();
+
+ virtual QSize minimumSizeHint() const
+ { return QWidget::minimumSizeHint().expandedTo(QSize(16, 16)); }
+
+protected:
+ virtual void paintEvent(QPaintEvent *e);
+
+private:
+ qdesigner_internal::FormWindowBase* m_formWindow;
+};
+
+class QDESIGNER_SHARED_EXPORT QDesignerDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit QDesignerDialog(QDesignerFormWindowInterface *fw, QWidget *parent);
+
+ virtual QSize minimumSizeHint() const
+ { return QWidget::minimumSizeHint().expandedTo(QSize(16, 16)); }
+
+protected:
+ void paintEvent(QPaintEvent *e);
+
+private:
+ qdesigner_internal::FormWindowBase* m_formWindow;
+};
+
+class QDESIGNER_SHARED_EXPORT Line : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+public:
+ explicit Line(QWidget *parent) : QFrame(parent)
+ { setAttribute(Qt::WA_MouseNoMask); setFrameStyle(HLine | Sunken); }
+
+ inline void setOrientation(Qt::Orientation orient)
+ { setFrameShape(orient == Qt::Horizontal ? HLine : VLine); }
+
+ inline Qt::Orientation orientation() const
+ { return frameShape() == HLine ? Qt::Horizontal : Qt::Vertical; }
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_WIDGET_H
diff --git a/tools/designer/src/lib/shared/qdesigner_widgetbox.cpp b/tools/designer/src/lib/shared/qdesigner_widgetbox.cpp
new file mode 100644
index 0000000000..5ba8ad7afd
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_widgetbox.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::QDesignerWidgetBox
+*/
+
+#include "qdesigner_widgetbox_p.h"
+#include "qdesigner_utils_p.h"
+
+#include <ui4_p.h>
+
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+#include <QtCore/QXmlStreamReader>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+QDesignerWidgetBox::QDesignerWidgetBox(QWidget *parent, Qt::WindowFlags flags)
+ : QDesignerWidgetBoxInterface(parent, flags),
+ m_loadMode(LoadMerge)
+{
+
+}
+
+QDesignerWidgetBox::LoadMode QDesignerWidgetBox::loadMode() const
+{
+ return m_loadMode;
+}
+
+void QDesignerWidgetBox::setLoadMode(LoadMode lm)
+{
+ m_loadMode = lm;
+}
+
+// Convenience to find a widget by class name
+bool QDesignerWidgetBox::findWidget(const QDesignerWidgetBoxInterface *wbox,
+ const QString &className,
+ const QString &category,
+ Widget *widgetData)
+{
+ // Note that entry names do not necessarily match the class name
+ // (at least, not for the standard widgets), so,
+ // look in the XML for the class name of the first widget to appear
+ const QString widgetTag = QLatin1String("<widget");
+ QString pattern = QLatin1String("^<widget\\s+class\\s*=\\s*\"");
+ pattern += className;
+ pattern += QLatin1String("\".*$");
+ const QRegExp regexp(pattern);
+ Q_ASSERT(regexp.isValid());
+ const int catCount = wbox->categoryCount();
+ for (int c = 0; c < catCount; c++) {
+ const Category cat = wbox->category(c);
+ if (category.isEmpty() || cat.name() == category) {
+ const int widgetCount = cat.widgetCount();
+ for (int w = 0; w < widgetCount; w++) {
+ const Widget widget = cat.widget(w);
+ QString xml = widget.domXml(); // Erase the <ui> tag that can be present starting from 4.4
+ const int widgetTagIndex = xml.indexOf(widgetTag);
+ if (widgetTagIndex != -1) {
+ xml.remove(0, widgetTagIndex);
+ if (regexp.exactMatch(xml)) {
+ *widgetData = widget;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// Convenience to create a Dom Widget from widget box xml code.
+DomUI *QDesignerWidgetBox::xmlToUi(const QString &name, const QString &xml, bool insertFakeTopLevel,
+ QString *errorMessage)
+{
+ QXmlStreamReader reader(xml);
+ DomUI *ui = 0;
+
+ // The xml description must either contain a root element "ui" with a child element "widget"
+ // or "widget" as the root element (4.3 legacy)
+ const QString widgetTag = QLatin1String("widget");
+
+ while (!reader.atEnd()) {
+ if (reader.readNext() == QXmlStreamReader::StartElement) {
+ const QStringRef name = reader.name();
+ if (ui) {
+ reader.raiseError(tr("Unexpected element <%1>").arg(name.toString()));
+ continue;
+ }
+
+ if (name.compare(QLatin1String("widget"), Qt::CaseInsensitive) == 0) { // 4.3 legacy, wrap into DomUI
+ ui = new DomUI;
+ DomWidget *widget = new DomWidget;
+ widget->read(reader);
+ ui->setElementWidget(widget);
+ } else if (name.compare(QLatin1String("ui"), Qt::CaseInsensitive) == 0) { // 4.4
+ ui = new DomUI;
+ ui->read(reader);
+ } else {
+ reader.raiseError(tr("Unexpected element <%1>").arg(name.toString()));
+ }
+ }
+ }
+
+ if (reader.hasError()) {
+ delete ui;
+ *errorMessage = tr("A parse error occurred at line %1, column %2 of the XML code "
+ "specified for the widget %3: %4\n%5")
+ .arg(reader.lineNumber()).arg(reader.columnNumber()).arg(name)
+ .arg(reader.errorString()).arg(xml);
+ return 0;
+ }
+
+ if (!ui || !ui->elementWidget()) {
+ delete ui;
+ *errorMessage = tr("The XML code specified for the widget %1 does not contain "
+ "any widget elements.\n%2").arg(name).arg(xml);
+ return 0;
+ }
+
+ if (insertFakeTopLevel) {
+ DomWidget *fakeTopLevel = new DomWidget;
+ fakeTopLevel->setAttributeClass(QLatin1String("QWidget"));
+ QList<DomWidget *> children;
+ children.push_back(ui->takeElementWidget());
+ fakeTopLevel->setElementWidget(children);
+ ui->setElementWidget(fakeTopLevel);
+ }
+
+ return ui;
+}
+
+// Convenience to create a Dom Widget from widget box xml code.
+DomUI *QDesignerWidgetBox::xmlToUi(const QString &name, const QString &xml, bool insertFakeTopLevel)
+{
+ QString errorMessage;
+ DomUI *rc = xmlToUi(name, xml, insertFakeTopLevel, &errorMessage);
+ if (!rc)
+ qdesigner_internal::designerWarning(errorMessage);
+ return rc;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_widgetbox_p.h b/tools/designer/src/lib/shared/qdesigner_widgetbox_p.h
new file mode 100644
index 0000000000..bec008184b
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_widgetbox_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_WIDGETBOX_H
+#define QDESIGNER_WIDGETBOX_H
+
+#include "shared_global_p.h"
+#include <QtDesigner/QDesignerWidgetBoxInterface>
+
+QT_BEGIN_NAMESPACE
+
+class DomUI;
+
+namespace qdesigner_internal {
+
+// A widget box with a load mode that allows for updating custom widgets.
+
+class QDESIGNER_SHARED_EXPORT QDesignerWidgetBox : public QDesignerWidgetBoxInterface
+{
+ Q_OBJECT
+public:
+ enum LoadMode { LoadMerge, LoadReplace, LoadCustomWidgetsOnly };
+
+ QDesignerWidgetBox(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+
+ LoadMode loadMode() const;
+ void setLoadMode(LoadMode lm);
+
+ virtual bool loadContents(const QString &contents) = 0;
+
+ // Convenience to access the widget box icon of a widget. Empty category
+ // matches all
+ virtual QIcon iconForWidget(const QString &className,
+ const QString &category = QString()) const = 0;
+
+ // Convenience to find a widget by class name. Empty category matches all
+ static bool findWidget(const QDesignerWidgetBoxInterface *wbox,
+ const QString &className,
+ const QString &category /* = QString() */,
+ Widget *widgetData);
+ // Convenience functions to create a DomWidget from widget box xml.
+ static DomUI *xmlToUi(const QString &name, const QString &xml, bool insertFakeTopLevel, QString *errorMessage);
+ static DomUI *xmlToUi(const QString &name, const QString &xml, bool insertFakeTopLevel);
+
+private:
+ LoadMode m_loadMode;
+};
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_WIDGETBOX_H
diff --git a/tools/designer/src/lib/shared/qdesigner_widgetitem.cpp b/tools/designer/src/lib/shared/qdesigner_widgetitem.cpp
new file mode 100644
index 0000000000..029ee891c1
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_widgetitem.cpp
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_widgetitem_p.h"
+#include "qdesigner_widget_p.h"
+#include "widgetfactory_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QGridLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/QApplication>
+
+#include <QtCore/QTextStream>
+#include <QtCore/QDebug>
+#include <private/qlayout_p.h>
+
+QT_BEGIN_NAMESPACE
+
+enum { DebugWidgetItem = 0 };
+enum { MinimumLength = 10 };
+
+// Widget item creation function to be registered as factory method with
+// QLayoutPrivate
+static QWidgetItem *createDesignerWidgetItem(const QLayout *layout, QWidget *widget)
+{
+ Qt::Orientations orientations;
+ if (qdesigner_internal::QDesignerWidgetItem::check(layout, widget, &orientations)) {
+ if (DebugWidgetItem)
+ qDebug() << "QDesignerWidgetItem: Creating on " << layout << widget << orientations;
+ return new qdesigner_internal::QDesignerWidgetItem(layout, widget, orientations);
+ }
+ if (DebugWidgetItem)
+ qDebug() << "QDesignerWidgetItem: Noncontainer: " << layout << widget;
+
+ return 0;
+}
+
+static QString sizePolicyToString(const QSizePolicy &p)
+{
+ QString rc; {
+ QTextStream str(&rc);
+ str << "Control=" << p.controlType() << " expdirs=" << p.expandingDirections()
+ << " hasHeightForWidth=" << p.hasHeightForWidth()
+ << " H: Policy=" << p.horizontalPolicy()
+ << " stretch=" << p.horizontalStretch()
+ << " V: Policy=" << p.verticalPolicy()
+ << " stretch=" << p.verticalStretch();
+ }
+ return rc;
+}
+
+// Find the layout the item is contained in, recursing over
+// child layouts
+static const QLayout *findLayoutOfItem(const QLayout *haystack, const QLayoutItem *needle)
+{
+ const int count = haystack->count();
+ for (int i = 0; i < count; i++) {
+ QLayoutItem *item = haystack->itemAt(i);
+ if (item == needle)
+ return haystack;
+ if (QLayout *childLayout = item->layout())
+ if (const QLayout *containing = findLayoutOfItem(childLayout, needle))
+ return containing;
+ }
+ return 0;
+}
+
+
+namespace qdesigner_internal {
+
+// ------------------ QDesignerWidgetItem
+QDesignerWidgetItem::QDesignerWidgetItem(const QLayout *containingLayout, QWidget *w, Qt::Orientations o) :
+ QWidgetItemV2(w),
+ m_orientations(o),
+ m_nonLaidOutMinSize(w->minimumSizeHint()),
+ m_nonLaidOutSizeHint(w->sizeHint()),
+ m_cachedContainingLayout(containingLayout)
+{
+ // Initialize the minimum size to prevent nonlaid-out frames/widgets
+ // from being slammed to zero
+ const QSize minimumSize = w->minimumSize();
+ if (!minimumSize.isEmpty())
+ m_nonLaidOutMinSize = minimumSize;
+ expand(&m_nonLaidOutMinSize);
+ expand(&m_nonLaidOutSizeHint);
+ w->installEventFilter(this);
+ connect(containingLayout, SIGNAL(destroyed()), this, SLOT(layoutChanged()));
+ if (DebugWidgetItem )
+ qDebug() << "QDesignerWidgetItem" << w << sizePolicyToString(w->sizePolicy()) << m_nonLaidOutMinSize << m_nonLaidOutSizeHint;
+}
+
+void QDesignerWidgetItem::expand(QSize *s) const
+{
+ // Expand the size if its too small
+ if (m_orientations & Qt::Horizontal && s->width() <= 0)
+ s->setWidth(MinimumLength);
+ if (m_orientations & Qt::Vertical && s->height() <= 0)
+ s->setHeight(MinimumLength);
+}
+
+QSize QDesignerWidgetItem::minimumSize() const
+{
+ // Just track the size in case we are laid-out or stretched.
+ const QSize baseMinSize = QWidgetItemV2::minimumSize();
+ QWidget * w = constWidget();
+ if (w->layout() || subjectToStretch(containingLayout(), w)) {
+ m_nonLaidOutMinSize = baseMinSize;
+ return baseMinSize;
+ }
+ // Nonlaid out: Maintain last laid-out size
+ const QSize rc = baseMinSize.expandedTo(m_nonLaidOutMinSize);
+ if (DebugWidgetItem > 1)
+ qDebug() << "minimumSize" << constWidget() << baseMinSize << rc;
+ return rc;
+}
+
+QSize QDesignerWidgetItem::sizeHint() const
+{
+ // Just track the size in case we are laid-out or stretched.
+ const QSize baseSizeHint = QWidgetItemV2::sizeHint();
+ QWidget * w = constWidget();
+ if (w->layout() || subjectToStretch(containingLayout(), w)) {
+ m_nonLaidOutSizeHint = baseSizeHint;
+ return baseSizeHint;
+ }
+ // Nonlaid out: Maintain last laid-out size
+ const QSize rc = baseSizeHint.expandedTo(m_nonLaidOutSizeHint);
+ if (DebugWidgetItem > 1)
+ qDebug() << "sizeHint" << constWidget() << baseSizeHint << rc;
+ return rc;
+}
+
+bool QDesignerWidgetItem::subjectToStretch(const QLayout *layout, QWidget *w)
+{
+ if (!layout)
+ return false;
+ // Are we under some stretch factor?
+ if (const QBoxLayout *bl = qobject_cast<const QBoxLayout *>(layout)) {
+ const int index = bl->indexOf(w);
+ Q_ASSERT(index != -1);
+ return bl->stretch(index) != 0;
+ }
+ if (const QGridLayout *cgl = qobject_cast<const QGridLayout *>(layout)) {
+ QGridLayout *gl = const_cast<QGridLayout *>(cgl);
+ const int index = cgl->indexOf(w);
+ Q_ASSERT(index != -1);
+ int row, column, rowSpan, columnSpan;
+ gl->getItemPosition (index, &row, &column, &rowSpan, &columnSpan);
+ const int rend = row + rowSpan;
+ const int cend = column + columnSpan;
+ for (int r = row; r < rend; r++)
+ if (cgl->rowStretch(r) != 0)
+ return true;
+ for (int c = column; c < cend; c++)
+ if (cgl->columnStretch(c) != 0)
+ return true;
+ }
+ return false;
+}
+
+/* Return the orientations mask for a layout, specifying
+ * in which directions squeezing should be prevented. */
+static Qt::Orientations layoutOrientation(const QLayout *layout)
+{
+ if (const QBoxLayout *bl = qobject_cast<const QBoxLayout *>(layout)) {
+ const QBoxLayout::Direction direction = bl->direction();
+ return direction == QBoxLayout::LeftToRight || direction == QBoxLayout::RightToLeft ? Qt::Horizontal : Qt::Vertical;
+ }
+ if (qobject_cast<const QFormLayout*>(layout))
+ return Qt::Vertical;
+ return Qt::Horizontal|Qt::Vertical;
+}
+
+// Check for a non-container extension container
+bool QDesignerWidgetItem::isContainer(const QDesignerFormEditorInterface *core, QWidget *w)
+{
+ if (!WidgetFactory::isFormEditorObject(w))
+ return false;
+ const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
+ const int widx = wdb->indexOfObject(w);
+ if (widx == -1 || !wdb->item(widx)->isContainer())
+ return false;
+ if (qt_extension<QDesignerContainerExtension*>(core->extensionManager(), w))
+ return false;
+ return true;
+}
+
+bool QDesignerWidgetItem::check(const QLayout *layout, QWidget *w, Qt::Orientations *ptrToOrientations)
+{
+ // Check for form-editor non-containerextension-containers (QFrame, etc)
+ // within laid-out form editor widgets. No check for managed() here as we
+ // want container pages and widgets in the process of being morphed as
+ // well. Avoid nested layouts (as the effective stretch cannot be easily
+ // computed and may mess things up). Won't work for Q3 Group boxes.
+ if (ptrToOrientations)
+ *ptrToOrientations = 0;
+
+ const QObject *layoutParent = layout->parent();
+ if (!layoutParent || !layoutParent->isWidgetType() || !WidgetFactory::isFormEditorObject(layoutParent))
+ return false;
+
+ QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(w);
+ if (!fw || !isContainer(fw->core(), w))
+ return false;
+
+ // If it is a box, restrict to its orientation
+ if (ptrToOrientations)
+ *ptrToOrientations = layoutOrientation(layout);
+
+ return true;
+}
+
+QSize QDesignerWidgetItem::nonLaidOutMinSize() const
+{
+ return m_nonLaidOutMinSize;
+}
+
+void QDesignerWidgetItem::setNonLaidOutMinSize(const QSize &s)
+{
+ if (DebugWidgetItem > 1)
+ qDebug() << "setNonLaidOutMinSize" << constWidget() << s;
+ m_nonLaidOutMinSize = s;
+}
+
+QSize QDesignerWidgetItem::nonLaidOutSizeHint() const
+{
+ return m_nonLaidOutSizeHint;
+}
+
+void QDesignerWidgetItem::setNonLaidOutSizeHint(const QSize &s)
+{
+ if (DebugWidgetItem > 1)
+ qDebug() << "setNonLaidOutSizeHint" << constWidget() << s;
+ m_nonLaidOutSizeHint = s;
+}
+
+void QDesignerWidgetItem::install()
+{
+ QLayoutPrivate::widgetItemFactoryMethod = createDesignerWidgetItem;
+}
+
+void QDesignerWidgetItem::deinstall()
+{
+ QLayoutPrivate::widgetItemFactoryMethod = 0;
+}
+
+const QLayout *QDesignerWidgetItem::containingLayout() const
+{
+ if (!m_cachedContainingLayout) {
+ if (QWidget *parentWidget = constWidget()->parentWidget())
+ if (QLayout *parentLayout = parentWidget->layout()) {
+ m_cachedContainingLayout = findLayoutOfItem(parentLayout, this);
+ if (m_cachedContainingLayout)
+ connect(m_cachedContainingLayout, SIGNAL(destroyed()), this, SLOT(layoutChanged()));
+ }
+ if (DebugWidgetItem)
+ qDebug() << Q_FUNC_INFO << " found " << m_cachedContainingLayout << " after reparenting " << constWidget();
+ }
+ return m_cachedContainingLayout;
+}
+
+void QDesignerWidgetItem::layoutChanged()
+{
+ if (DebugWidgetItem)
+ qDebug() << Q_FUNC_INFO;
+ m_cachedContainingLayout = 0;
+}
+
+bool QDesignerWidgetItem::eventFilter(QObject * /* watched */, QEvent *event)
+{
+ if (event->type() == QEvent::ParentChange)
+ layoutChanged();
+ return false;
+}
+
+// ------------------ QDesignerWidgetItemInstaller
+
+int QDesignerWidgetItemInstaller::m_instanceCount = 0;
+
+QDesignerWidgetItemInstaller::QDesignerWidgetItemInstaller()
+{
+ if (m_instanceCount++ == 0) {
+ if (DebugWidgetItem)
+ qDebug() << "QDesignerWidgetItemInstaller: installing";
+ QDesignerWidgetItem::install();
+ }
+}
+
+QDesignerWidgetItemInstaller::~QDesignerWidgetItemInstaller()
+{
+ if (--m_instanceCount == 0) {
+ if (DebugWidgetItem)
+ qDebug() << "QDesignerWidgetItemInstaller: deinstalling";
+ QDesignerWidgetItem::deinstall();
+ }
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qdesigner_widgetitem_p.h b/tools/designer/src/lib/shared/qdesigner_widgetitem_p.h
new file mode 100644
index 0000000000..1d8ff3e23d
--- /dev/null
+++ b/tools/designer/src/lib/shared/qdesigner_widgetitem_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef DESIGNERWIDGETITEM_H
+#define DESIGNERWIDGETITEM_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QLayoutItem>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+// QDesignerWidgetItem: A Layout Item that is used for non-containerextension-
+// containers (QFrame, etc) on Designer forms. It prevents its widget
+// from being slammed to size 0 if the widget has no layout:
+// Pre 4.5, this item ensured only that QWidgets and QFrames were not squeezed
+// to size 0 since they have an invalid size hint when non-laid out.
+// Since 4.5, the item is used for every non-containerextension-container.
+// In case the container has itself a layout, it merely tracks the minimum
+// size. If the container has no layout and is not subject to some stretch
+// factor, it will return the last valid size. The effect is that after
+// breaking a layout on a container within a layout, it just maintains its
+// last size and is not slammed to 0,0. In addition, it can be resized.
+// The class keeps track of the containing layout by tracking widget reparent
+// and destroyed slots as Designer will for example re-create grid layouts to
+// shrink them.
+
+class QDESIGNER_SHARED_EXPORT QDesignerWidgetItem : public QObject, public QWidgetItemV2 {
+ Q_DISABLE_COPY(QDesignerWidgetItem)
+ Q_OBJECT
+public:
+ explicit QDesignerWidgetItem(const QLayout *containingLayout, QWidget *w, Qt::Orientations o = Qt::Horizontal|Qt::Vertical);
+
+ const QLayout *containingLayout() const;
+
+ inline QWidget *constWidget() const { return const_cast<QDesignerWidgetItem*>(this)->widget(); }
+
+ virtual QSize minimumSize() const;
+ virtual QSize sizeHint() const;
+
+ // Resize: Takes effect if the contained widget does not have a layout
+ QSize nonLaidOutMinSize() const;
+ void setNonLaidOutMinSize(const QSize &s);
+
+ QSize nonLaidOutSizeHint() const;
+ void setNonLaidOutSizeHint(const QSize &s);
+
+ // Check whether a QDesignerWidgetItem should be installed
+ static bool check(const QLayout *layout, QWidget *w, Qt::Orientations *ptrToOrientations = 0);
+
+ // Register itself using QLayoutPrivate's widget item factory method hook
+ static void install();
+ static void deinstall();
+
+ // Check for a non-container extension container
+ static bool isContainer(const QDesignerFormEditorInterface *core, QWidget *w);
+
+ static bool subjectToStretch(const QLayout *layout, QWidget *w);
+
+ virtual bool eventFilter(QObject * watched, QEvent * event);
+
+private slots:
+ void layoutChanged();
+
+private:
+ void expand(QSize *s) const;
+ bool subjectToStretch() const;
+
+ const Qt::Orientations m_orientations;
+ mutable QSize m_nonLaidOutMinSize;
+ mutable QSize m_nonLaidOutSizeHint;
+ mutable const QLayout *m_cachedContainingLayout;
+};
+
+// Helper class that ensures QDesignerWidgetItem is installed while an
+// instance is in scope.
+
+class QDESIGNER_SHARED_EXPORT QDesignerWidgetItemInstaller {
+ Q_DISABLE_COPY(QDesignerWidgetItemInstaller)
+
+public:
+ QDesignerWidgetItemInstaller();
+ ~QDesignerWidgetItemInstaller();
+
+private:
+ static int m_instanceCount;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/qlayout_widget.cpp b/tools/designer/src/lib/shared/qlayout_widget.cpp
new file mode 100644
index 0000000000..c0986ce855
--- /dev/null
+++ b/tools/designer/src/lib/shared/qlayout_widget.cpp
@@ -0,0 +1,2103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "qlayout_widget_p.h"
+#include "qdesigner_utils_p.h"
+#include "layout_p.h"
+#include "layoutinfo_p.h"
+#include "invisible_widget_p.h"
+#include "qdesigner_widgetitem_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+
+#include <QtGui/QPainter>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QGridLayout>
+#include <QtGui/QFormLayout>
+#include <QtGui/qevent.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/QtAlgorithms>
+#include <QtCore/QMap>
+#include <QtCore/QStack>
+#include <QtCore/QPair>
+#include <QtCore/QSet>
+
+enum { ShiftValue = 1 };
+enum { debugLayout = 0 };
+enum { FormLayoutColumns = 2 };
+enum { indicatorSize = 2 };
+// Grid/form Helpers: get info (overloads to make templates work)
+
+namespace { // Do not use static, will break HP-UX due to templates
+
+QT_USE_NAMESPACE
+
+// overloads to make templates over QGridLayout/QFormLayout work
+inline int gridRowCount(const QGridLayout *gridLayout)
+{
+ return gridLayout->rowCount();
+}
+
+inline int gridColumnCount(const QGridLayout *gridLayout)
+{
+ return gridLayout->columnCount();
+}
+
+// QGridLayout/QFormLayout Helpers: get item position (overloads to make templates work)
+inline void getGridItemPosition(QGridLayout *gridLayout, int index,
+ int *row, int *column, int *rowspan, int *colspan)
+{
+ gridLayout->getItemPosition(index, row, column, rowspan, colspan);
+}
+
+QRect gridItemInfo(QGridLayout *grid, int index)
+{
+ int row, column, rowSpan, columnSpan;
+ // getItemPosition is not const, grmbl..
+ grid->getItemPosition(index, &row, &column, &rowSpan, &columnSpan);
+ return QRect(column, row, columnSpan, rowSpan);
+}
+
+inline int gridRowCount(const QFormLayout *formLayout) { return formLayout->rowCount(); }
+inline int gridColumnCount(const QFormLayout *) { return FormLayoutColumns; }
+
+inline void getGridItemPosition(QFormLayout *formLayout, int index, int *row, int *column, int *rowspan, int *colspan)
+{
+ qdesigner_internal::getFormLayoutItemPosition(formLayout, index, row, column, rowspan, colspan);
+}
+
+QRect gridItemInfo(const QFormLayout *form, int index)
+{
+ int row;
+ int column;
+ int colspan;
+ qdesigner_internal::getFormLayoutItemPosition(form, index, &row, &column, 0, &colspan);
+ return QRect(column, row, colspan, 1);
+}
+} // namespace anonymous
+
+QT_BEGIN_NAMESPACE
+
+static const char *objectNameC = "objectName";
+static const char *sizeConstraintC = "sizeConstraint";
+
+/* A padding spacer element that is used to represent an empty form layout cell. It should grow with its cell.
+ * Should not be used on a grid as it causes resizing inconsistencies */
+namespace qdesigner_internal {
+ class PaddingSpacerItem : public QSpacerItem {
+ public:
+ PaddingSpacerItem() : QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding) {}
+ virtual Qt::Orientations expandingDirections () const { return Qt::Vertical | Qt::Horizontal; }
+ };
+}
+
+static inline QSpacerItem *createGridSpacer()
+{
+ return new QSpacerItem(0, 0);
+}
+
+static inline QSpacerItem *createFormSpacer()
+{
+ return new qdesigner_internal::PaddingSpacerItem;
+}
+
+// QGridLayout/QFormLayout Helpers: Debug items of GridLikeLayout
+template <class GridLikeLayout>
+static QDebug debugGridLikeLayout(QDebug str, const GridLikeLayout &gl)
+{
+ const int count = gl.count();
+ str << "Grid: " << gl.objectName() << gridRowCount(&gl) << " rows x " << gridColumnCount(&gl)
+ << " cols " << count << " items\n";
+ for (int i = 0; i < count; i++) {
+ QLayoutItem *item = gl.itemAt(i);
+ str << "Item " << i << item << item->widget() << gridItemInfo(const_cast<GridLikeLayout *>(&gl), i) << " empty=" << qdesigner_internal::LayoutInfo::isEmptyItem(item) << "\n";
+ }
+ return str;
+}
+
+static inline QDebug operator<<(QDebug str, const QGridLayout &gl) { return debugGridLikeLayout(str, gl); }
+static inline QDebug operator<<(QDebug str, const QFormLayout &fl) { return debugGridLikeLayout(str, fl); }
+
+static inline bool isEmptyFormLayoutRow(const QFormLayout *fl, int row)
+{
+ // Spanning can never be empty
+ if (fl->itemAt(row, QFormLayout::SpanningRole))
+ return false;
+ return qdesigner_internal::LayoutInfo::isEmptyItem(fl->itemAt(row, QFormLayout::LabelRole)) && qdesigner_internal::LayoutInfo::isEmptyItem(fl->itemAt(row, QFormLayout::FieldRole));
+}
+
+static inline bool canSimplifyFormLayout(const QFormLayout *formLayout, const QRect &restrictionArea)
+{
+ if (restrictionArea.x() >= FormLayoutColumns)
+ return false;
+ // Try to find empty rows
+ const int bottomCheckRow = qMin(formLayout->rowCount(), restrictionArea.top() + restrictionArea.height());
+ for (int r = restrictionArea.y(); r < bottomCheckRow; r++)
+ if (isEmptyFormLayoutRow(formLayout, r))
+ return true;
+ return false;
+}
+
+// recreate a managed layout (which does not automagically remove
+// empty rows/columns like grid or form layout) in case it needs to shrink
+
+static QLayout *recreateManagedLayout(const QDesignerFormEditorInterface *core, QWidget *w, QLayout *lt)
+{
+ const qdesigner_internal::LayoutInfo::Type t = qdesigner_internal::LayoutInfo::layoutType(core, lt);
+ qdesigner_internal::LayoutProperties properties;
+ const int mask = properties.fromPropertySheet(core, lt, qdesigner_internal::LayoutProperties::AllProperties);
+ qdesigner_internal::LayoutInfo::deleteLayout(core, w);
+ QLayout *rc = core->widgetFactory()->createLayout(w, 0, t);
+ properties.toPropertySheet(core, rc, mask, true);
+ return rc;
+}
+
+// QGridLayout/QFormLayout Helpers: find an item on a form/grid. Return index
+template <class GridLikeLayout>
+int findGridItemAt(GridLikeLayout *gridLayout, int at_row, int at_column)
+{
+ Q_ASSERT(gridLayout);
+ const int count = gridLayout->count();
+ for (int index = 0; index < count; index++) {
+ int row, column, rowspan, colspan;
+ getGridItemPosition(gridLayout, index, &row, &column, &rowspan, &colspan);
+ if (at_row >= row && at_row < (row + rowspan)
+ && at_column >= column && at_column < (column + colspan)) {
+ return index;
+ }
+ }
+ return -1;
+}
+// QGridLayout/QFormLayout Helpers: remove dummy spacers on form/grid
+template <class GridLikeLayout>
+static bool removeEmptyCellsOnGrid(GridLikeLayout *grid, const QRect &area)
+{
+ // check if there are any items in the way. Should be only spacers
+ // Unique out items that span rows/columns.
+ QVector<int> indexesToBeRemoved;
+ indexesToBeRemoved.reserve(grid->count());
+ const int rightColumn = area.x() + area.width();
+ const int bottomRow = area.y() + area.height();
+ for (int c = area.x(); c < rightColumn; c++)
+ for (int r = area.y(); r < bottomRow; r++) {
+ const int index = findGridItemAt(grid, r ,c);
+ if (index != -1)
+ if (QLayoutItem *item = grid->itemAt(index)) {
+ if (qdesigner_internal::LayoutInfo::isEmptyItem(item)) {
+ if (indexesToBeRemoved.indexOf(index) == -1)
+ indexesToBeRemoved.push_back(index);
+ } else {
+ return false;
+ }
+ }
+ }
+ // remove, starting from last
+ if (!indexesToBeRemoved.empty()) {
+ qStableSort(indexesToBeRemoved.begin(), indexesToBeRemoved.end());
+ for (int i = indexesToBeRemoved.size() - 1; i >= 0; i--)
+ delete grid->takeAt(indexesToBeRemoved[i]);
+ }
+ return true;
+}
+
+namespace qdesigner_internal {
+// --------- LayoutProperties
+
+LayoutProperties::LayoutProperties()
+{
+ clear();
+}
+
+void LayoutProperties::clear()
+{
+ qFill(m_margins, m_margins + MarginCount, 0);
+ qFill(m_marginsChanged, m_marginsChanged + MarginCount, false);
+ qFill(m_spacings, m_spacings + SpacingsCount, 0);
+ qFill(m_spacingsChanged, m_spacingsChanged + SpacingsCount, false);
+
+ m_objectName = QVariant();
+ m_objectNameChanged = false;
+ m_sizeConstraint = QVariant(QLayout::SetDefaultConstraint);
+ m_sizeConstraintChanged = false;
+
+ m_fieldGrowthPolicyChanged = m_rowWrapPolicyChanged = m_labelAlignmentChanged = m_formAlignmentChanged = false;
+ m_fieldGrowthPolicy = m_rowWrapPolicy = m_formAlignment = QVariant();
+
+ m_boxStretchChanged = m_gridRowStretchChanged = m_gridColumnStretchChanged = m_gridRowMinimumHeightChanged = false;
+ m_boxStretch = m_gridRowStretch = m_gridColumnStretch = m_gridRowMinimumHeight = QVariant();
+}
+
+int LayoutProperties::visibleProperties(const QLayout *layout)
+{
+ // Grid like layout have 2 spacings.
+ const bool isFormLayout = qobject_cast<const QFormLayout*>(layout);
+ const bool isGridLike = qobject_cast<const QGridLayout*>(layout) || isFormLayout;
+ int rc = ObjectNameProperty|LeftMarginProperty|TopMarginProperty|RightMarginProperty|BottomMarginProperty|
+ SizeConstraintProperty;
+
+ rc |= isGridLike ? (HorizSpacingProperty|VertSpacingProperty) : SpacingProperty;
+ if (isFormLayout) {
+ rc |= FieldGrowthPolicyProperty|RowWrapPolicyProperty|LabelAlignmentProperty|FormAlignmentProperty;
+ } else {
+ if (isGridLike) {
+ rc |= GridRowStretchProperty|GridColumnStretchProperty|GridRowMinimumHeightProperty|GridColumnMinimumWidthProperty;
+ } else {
+ rc |= BoxStretchProperty;
+ }
+ }
+ return rc;
+}
+
+static const char *marginPropertyNamesC[] = {"leftMargin", "topMargin", "rightMargin", "bottomMargin"};
+static const char *spacingPropertyNamesC[] = {"spacing", "horizontalSpacing", "verticalSpacing" };
+static const char *fieldGrowthPolicyPropertyC = "fieldGrowthPolicy";
+static const char *rowWrapPolicyPropertyC = "rowWrapPolicy";
+static const char *labelAlignmentPropertyC = "labelAlignment";
+static const char *formAlignmentPropertyC = "formAlignment";
+static const char *boxStretchPropertyC = "stretch";
+static const char *gridRowStretchPropertyC = "rowStretch";
+static const char *gridColumnStretchPropertyC = "columnStretch";
+static const char *gridRowMinimumHeightPropertyC = "rowMinimumHeight";
+static const char *gridColumnMinimumWidthPropertyC = "columnMinimumWidth";
+
+static bool intValueFromSheet(const QDesignerPropertySheetExtension *sheet, const QString &name, int *value, bool *changed)
+{
+ const int sheetIndex = sheet->indexOf(name);
+ if (sheetIndex == -1)
+ return false;
+ *value = sheet->property(sheetIndex).toInt();
+ *changed = sheet->isChanged(sheetIndex);
+ return true;
+}
+
+static void variantPropertyFromSheet(int mask, int flag, const QDesignerPropertySheetExtension *sheet, const QString &name,
+ QVariant *value, bool *changed, int *returnMask)
+{
+ if (mask & flag) {
+ const int sIndex = sheet->indexOf(name);
+ if (sIndex != -1) {
+ *value = sheet->property(sIndex);
+ *changed = sheet->isChanged(sIndex);
+ *returnMask |= flag;
+ }
+ }
+}
+
+int LayoutProperties::fromPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask)
+{
+ int rc = 0;
+ const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), l);
+ Q_ASSERT(sheet);
+ // name
+ if (mask & ObjectNameProperty) {
+ const int nameIndex = sheet->indexOf(QLatin1String(objectNameC));
+ Q_ASSERT(nameIndex != -1);
+ m_objectName = sheet->property(nameIndex);
+ m_objectNameChanged = sheet->isChanged(nameIndex);
+ rc |= ObjectNameProperty;
+ }
+ // -- Margins
+ const int marginFlags[MarginCount] = { LeftMarginProperty, TopMarginProperty, RightMarginProperty, BottomMarginProperty};
+ for (int i = 0; i < MarginCount; i++)
+ if (mask & marginFlags[i])
+ if (intValueFromSheet(sheet, QLatin1String(marginPropertyNamesC[i]), m_margins + i, m_marginsChanged + i))
+ rc |= marginFlags[i];
+
+ const int spacingFlags[] = { SpacingProperty, HorizSpacingProperty, VertSpacingProperty};
+ for (int i = 0; i < SpacingsCount; i++)
+ if (mask & spacingFlags[i])
+ if (intValueFromSheet(sheet, QLatin1String(spacingPropertyNamesC[i]), m_spacings + i, m_spacingsChanged + i))
+ rc |= spacingFlags[i];
+ // sizeConstraint, flags
+ variantPropertyFromSheet(mask, SizeConstraintProperty, sheet, QLatin1String(sizeConstraintC), &m_sizeConstraint, &m_sizeConstraintChanged, &rc);
+ variantPropertyFromSheet(mask, FieldGrowthPolicyProperty, sheet, QLatin1String(fieldGrowthPolicyPropertyC), &m_fieldGrowthPolicy, &m_fieldGrowthPolicyChanged, &rc);
+ variantPropertyFromSheet(mask, RowWrapPolicyProperty, sheet, QLatin1String(rowWrapPolicyPropertyC), &m_rowWrapPolicy, &m_rowWrapPolicyChanged, &rc);
+ variantPropertyFromSheet(mask, LabelAlignmentProperty, sheet, QLatin1String(labelAlignmentPropertyC), &m_labelAlignment, &m_labelAlignmentChanged, &rc);
+ variantPropertyFromSheet(mask, FormAlignmentProperty, sheet, QLatin1String(formAlignmentPropertyC), &m_formAlignment, &m_formAlignmentChanged, &rc);
+ variantPropertyFromSheet(mask, BoxStretchProperty, sheet, QLatin1String(boxStretchPropertyC), &m_boxStretch, & m_boxStretchChanged, &rc);
+ variantPropertyFromSheet(mask, GridRowStretchProperty, sheet, QLatin1String(gridRowStretchPropertyC), &m_gridRowStretch, &m_gridRowStretchChanged, &rc);
+ variantPropertyFromSheet(mask, GridColumnStretchProperty, sheet, QLatin1String(gridColumnStretchPropertyC), &m_gridColumnStretch, &m_gridColumnStretchChanged, &rc);
+ variantPropertyFromSheet(mask, GridRowMinimumHeightProperty, sheet, QLatin1String(gridRowMinimumHeightPropertyC), &m_gridRowMinimumHeight, &m_gridRowMinimumHeightChanged, &rc);
+ variantPropertyFromSheet(mask, GridColumnMinimumWidthProperty, sheet, QLatin1String(gridColumnMinimumWidthPropertyC), &m_gridColumnMinimumWidth, &m_gridColumnMinimumWidthChanged, &rc);
+ return rc;
+}
+
+static bool intValueToSheet(QDesignerPropertySheetExtension *sheet, const QString &name, int value, bool changed, bool applyChanged)
+
+{
+
+ const int sheetIndex = sheet->indexOf(name);
+ if (sheetIndex == -1) {
+ qWarning() << " LayoutProperties: Attempt to set property " << name << " that does not exist for the layout.";
+ return false;
+ }
+ sheet->setProperty(sheetIndex, QVariant(value));
+ if (applyChanged)
+ sheet->setChanged(sheetIndex, changed);
+ return true;
+}
+
+static void variantPropertyToSheet(int mask, int flag, bool applyChanged, QDesignerPropertySheetExtension *sheet, const QString &name,
+ const QVariant &value, bool changed, int *returnMask)
+{
+ if (mask & flag) {
+ const int sIndex = sheet->indexOf(name);
+ if (sIndex != -1) {
+ sheet->setProperty(sIndex, value);
+ if (applyChanged)
+ sheet->setChanged(sIndex, changed);
+ *returnMask |= flag;
+ }
+ }
+}
+
+int LayoutProperties::toPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask, bool applyChanged) const
+{
+ int rc = 0;
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core->extensionManager(), l);
+ Q_ASSERT(sheet);
+ // name
+ if (mask & ObjectNameProperty) {
+ const int nameIndex = sheet->indexOf(QLatin1String(objectNameC));
+ Q_ASSERT(nameIndex != -1);
+ sheet->setProperty(nameIndex, m_objectName);
+ if (applyChanged)
+ sheet->setChanged(nameIndex, m_objectNameChanged);
+ rc |= ObjectNameProperty;
+ }
+ // margins
+ const int marginFlags[MarginCount] = { LeftMarginProperty, TopMarginProperty, RightMarginProperty, BottomMarginProperty};
+ for (int i = 0; i < MarginCount; i++)
+ if (mask & marginFlags[i])
+ if (intValueToSheet(sheet, QLatin1String(marginPropertyNamesC[i]), m_margins[i], m_marginsChanged[i], applyChanged))
+ rc |= marginFlags[i];
+
+ const int spacingFlags[] = { SpacingProperty, HorizSpacingProperty, VertSpacingProperty};
+ for (int i = 0; i < SpacingsCount; i++)
+ if (mask & spacingFlags[i])
+ if (intValueToSheet(sheet, QLatin1String(spacingPropertyNamesC[i]), m_spacings[i], m_spacingsChanged[i], applyChanged))
+ rc |= spacingFlags[i];
+ // sizeConstraint
+ variantPropertyToSheet(mask, SizeConstraintProperty, applyChanged, sheet, QLatin1String(sizeConstraintC), m_sizeConstraint, m_sizeConstraintChanged, &rc);
+ variantPropertyToSheet(mask, FieldGrowthPolicyProperty, applyChanged, sheet, QLatin1String(fieldGrowthPolicyPropertyC), m_fieldGrowthPolicy, &m_fieldGrowthPolicyChanged, &rc);
+ variantPropertyToSheet(mask, RowWrapPolicyProperty, applyChanged, sheet, QLatin1String(rowWrapPolicyPropertyC), m_rowWrapPolicy, m_rowWrapPolicyChanged, &rc);
+ variantPropertyToSheet(mask, LabelAlignmentProperty, applyChanged, sheet, QLatin1String(labelAlignmentPropertyC), m_labelAlignment, m_labelAlignmentChanged, &rc);
+ variantPropertyToSheet(mask, FormAlignmentProperty, applyChanged, sheet, QLatin1String(formAlignmentPropertyC), m_formAlignment, m_formAlignmentChanged, &rc);
+ variantPropertyToSheet(mask, BoxStretchProperty, applyChanged, sheet, QLatin1String(boxStretchPropertyC), m_boxStretch, m_boxStretchChanged, &rc);
+ variantPropertyToSheet(mask, GridRowStretchProperty, applyChanged, sheet, QLatin1String(gridRowStretchPropertyC), m_gridRowStretch, m_gridRowStretchChanged, &rc);
+ variantPropertyToSheet(mask, GridColumnStretchProperty, applyChanged, sheet, QLatin1String(gridColumnStretchPropertyC), m_gridColumnStretch, m_gridColumnStretchChanged, &rc);
+ variantPropertyToSheet(mask, GridRowMinimumHeightProperty, applyChanged, sheet, QLatin1String(gridRowMinimumHeightPropertyC), m_gridRowMinimumHeight, m_gridRowMinimumHeightChanged, &rc);
+ variantPropertyToSheet(mask, GridColumnMinimumWidthProperty, applyChanged, sheet, QLatin1String(gridColumnMinimumWidthPropertyC), m_gridColumnMinimumWidth, m_gridColumnMinimumWidthChanged, &rc);
+ return rc;
+}
+
+// ---------------- LayoutHelper
+LayoutHelper::LayoutHelper()
+{
+}
+
+LayoutHelper::~LayoutHelper()
+{
+}
+
+int LayoutHelper::indexOf(const QLayout *lt, const QWidget *widget)
+{
+ if (!lt)
+ return -1;
+
+ const int itemCount = lt->count();
+ for (int i = 0; i < itemCount; i++)
+ if (lt->itemAt(i)->widget() == widget)
+ return i;
+ return -1;
+}
+
+QRect LayoutHelper::itemInfo(QLayout *lt, const QWidget *widget) const
+{
+ const int index = indexOf(lt, widget);
+ if (index == -1) {
+ qWarning() << "LayoutHelper::itemInfo: " << widget << " not in layout " << lt;
+ return QRect(0, 0, 1, 1);
+ }
+ return itemInfo(lt, index);
+}
+
+ // ---------------- BoxLayoutHelper
+ class BoxLayoutHelper : public LayoutHelper {
+ public:
+ BoxLayoutHelper(const Qt::Orientation orientation) : m_orientation(orientation) {}
+
+ virtual QRect itemInfo(QLayout *lt, int index) const;
+ virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w);
+ virtual void removeWidget(QLayout *lt, QWidget *widget);
+ virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after);
+
+ virtual void pushState(const QDesignerFormEditorInterface *, const QWidget *);
+ virtual void popState(const QDesignerFormEditorInterface *, QWidget *);
+
+ virtual bool canSimplify(const QDesignerFormEditorInterface *, const QWidget *, const QRect &) const { return false; }
+ virtual void simplify(const QDesignerFormEditorInterface *, QWidget *, const QRect &) {}
+
+ // Helper for restoring layout states
+ typedef QVector <QLayoutItem *> LayoutItemVector;
+ static LayoutItemVector disassembleLayout(QLayout *lt);
+ static QLayoutItem *findItemOfWidget(const LayoutItemVector &lv, QWidget *w);
+
+ private:
+ typedef QVector<QWidget *> BoxLayoutState;
+
+ static BoxLayoutState state(const QBoxLayout*lt);
+
+ QStack<BoxLayoutState> m_states;
+ const Qt::Orientation m_orientation;
+ };
+
+ QRect BoxLayoutHelper::itemInfo(QLayout * /*lt*/, int index) const
+ {
+ return m_orientation == Qt::Horizontal ? QRect(index, 0, 1, 1) : QRect(0, index, 1, 1);
+ }
+
+ void BoxLayoutHelper::insertWidget(QLayout *lt, const QRect &info, QWidget *w)
+ {
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(lt);
+ Q_ASSERT(boxLayout);
+ boxLayout->insertWidget(m_orientation == Qt::Horizontal ? info.x() : info.y(), w);
+ }
+
+ void BoxLayoutHelper::removeWidget(QLayout *lt, QWidget *widget)
+ {
+ QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(lt);
+ Q_ASSERT(boxLayout);
+ boxLayout->removeWidget(widget);
+ }
+
+ void BoxLayoutHelper::replaceWidget(QLayout *lt, QWidget *before, QWidget *after)
+ {
+ bool ok = false;
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ if (QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(lt)) {
+ const int index = boxLayout->indexOf(before);
+ if (index != -1) {
+ const bool visible = before->isVisible();
+ delete boxLayout->takeAt(index);
+ if (visible)
+ before->hide();
+ before->setParent(0);
+ boxLayout->insertWidget(index, after);
+ ok = true;
+ }
+ }
+ if (!ok)
+ qWarning() << "BoxLayoutHelper::replaceWidget : Unable to replace " << before << " by " << after << " in " << lt;
+ }
+
+ BoxLayoutHelper::BoxLayoutState BoxLayoutHelper::state(const QBoxLayout*lt)
+ {
+ BoxLayoutState rc;
+ if (const int count = lt->count()) {
+ rc.reserve(count);
+ for (int i = 0; i < count; i++)
+ if (QWidget *w = lt->itemAt(i)->widget())
+ rc.push_back(w);
+ }
+ return rc;
+ }
+
+ void BoxLayoutHelper::pushState(const QDesignerFormEditorInterface *core, const QWidget *w)
+ {
+ const QBoxLayout *boxLayout = qobject_cast<const QBoxLayout *>(LayoutInfo::managedLayout(core, w));
+ Q_ASSERT(boxLayout);
+ m_states.push(state(boxLayout));
+ }
+
+ QLayoutItem *BoxLayoutHelper::findItemOfWidget(const LayoutItemVector &lv, QWidget *w)
+ {
+ const LayoutItemVector::const_iterator cend = lv.constEnd();
+ for (LayoutItemVector::const_iterator it = lv.constBegin(); it != cend; ++it)
+ if ( (*it)->widget() == w)
+ return *it;
+
+ return 0;
+ }
+
+ BoxLayoutHelper::LayoutItemVector BoxLayoutHelper::disassembleLayout(QLayout *lt)
+ {
+ // Take items
+ const int count = lt->count();
+ if (count == 0)
+ return LayoutItemVector();
+ LayoutItemVector rc;
+ rc.reserve(count);
+ for (int i = count - 1; i >= 0; i--)
+ rc.push_back(lt->takeAt(i));
+ return rc;
+ }
+
+ void BoxLayoutHelper::popState(const QDesignerFormEditorInterface *core, QWidget *w)
+ {
+ QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(LayoutInfo::managedLayout(core, w));
+ Q_ASSERT(boxLayout);
+ const BoxLayoutState savedState = m_states.pop();
+ const BoxLayoutState currentState = state(boxLayout);
+ // Check for equality/empty. Note that this will currently
+ // always trigger as box layouts do not have a state apart from
+ // the order and there is no layout order editor yet.
+ if (savedState == state(boxLayout))
+ return;
+
+ const int count = savedState.size();
+ Q_ASSERT(count == currentState.size());
+ // Take items and reassemble in saved order
+ const LayoutItemVector items = disassembleLayout(boxLayout);
+ for (int i = 0; i < count; i++) {
+ QLayoutItem *item = findItemOfWidget(items, savedState[i]);
+ Q_ASSERT(item);
+ boxLayout->addItem(item);
+ }
+ }
+
+ // Grid Layout state. Datatypically store the state of a GridLayout as a map of
+ // widgets to QRect(columns, rows) and size. Used to store the state for undo operations
+ // that do not change the widgets within the layout; also provides some manipulation
+ // functions and ability to apply the state to a layout provided its widgets haven't changed.
+ struct GridLayoutState {
+ GridLayoutState();
+
+ void fromLayout(QGridLayout *l);
+ void applyToLayout(const QDesignerFormEditorInterface *core, QWidget *w) const;
+
+ void insertRow(int row);
+ void insertColumn(int column);
+
+ bool simplify(const QRect &r, bool testOnly);
+ void removeFreeRow(int row);
+ void removeFreeColumn(int column);
+
+
+ // State of a cell in one dimension
+ enum DimensionCellState {
+ Free,
+ Spanned, // Item spans it
+ Occupied // Item bordering on it
+ };
+ // Horiontal, Vertical pair of state
+ typedef QPair<DimensionCellState, DimensionCellState> CellState;
+ typedef QVector<CellState> CellStates;
+
+ // Figure out states of a cell and return as a flat vector of
+ // [column1, column2,...] (address as row * columnCount + col)
+ static CellStates cellStates(const QList<QRect> &rects, int numRows, int numColumns);
+
+ typedef QMap<QWidget *, QRect> WidgetItemMap;
+ WidgetItemMap widgetItemMap;
+ int rowCount;
+ int colCount;
+ };
+
+ static inline bool needsSpacerItem(const GridLayoutState::CellState &cs) {
+ return cs.first == GridLayoutState::Free && cs.second == GridLayoutState::Free;
+ }
+
+ static inline QDebug operator<<(QDebug str, const GridLayoutState &gs)
+ {
+ str << "GridLayoutState: " << gs.rowCount << " rows x " << gs.colCount
+ << " cols " << gs.widgetItemMap.size() << " items\n";
+
+ const GridLayoutState::WidgetItemMap::const_iterator wcend = gs.widgetItemMap.constEnd();
+ for (GridLayoutState::WidgetItemMap::const_iterator it = gs.widgetItemMap.constBegin(); it != wcend; ++it)
+ str << "Item " << it.key() << it.value() << '\n';
+ return str;
+ }
+
+ GridLayoutState::GridLayoutState() :
+ rowCount(0),
+ colCount(0)
+ {
+ }
+
+ GridLayoutState::CellStates GridLayoutState::cellStates(const QList<QRect> &rects, int numRows, int numColumns)
+ {
+ CellStates rc = CellStates(numRows * numColumns, CellState(Free, Free));
+ const QList<QRect>::const_iterator rcend = rects.constEnd();
+ for (QList<QRect>::const_iterator it = rects.constBegin(); it != rcend; ++it) {
+ const int leftColumn = it->x();
+ const int topRow = it->y();
+ const int rightColumn = leftColumn + it->width() - 1;
+ const int bottomRow = topRow + it->height() - 1;
+ for (int r = topRow; r <= bottomRow; r++)
+ for (int c = leftColumn; c <= rightColumn; c++) {
+ const int flatIndex = r * numColumns + c;
+ // Bordering horizontally?
+ DimensionCellState &horizState = rc[flatIndex].first;
+ if (c == leftColumn || c == rightColumn) {
+ horizState = Occupied;
+ } else {
+ if (horizState < Spanned)
+ horizState = Spanned;
+ }
+ // Bordering vertically?
+ DimensionCellState &vertState = rc[flatIndex].second;
+ if (r == topRow || r == bottomRow) {
+ vertState = Occupied;
+ } else {
+ if (vertState < Spanned)
+ vertState = Spanned;
+ }
+ }
+ }
+ if (debugLayout) {
+ qDebug() << "GridLayoutState::cellStates: " << numRows << " x " << numColumns;
+ for (int r = 0; r < numRows; r++)
+ for (int c = 0; c < numColumns; c++)
+ qDebug() << " Row: " << r << " column: " << c << rc[r * numColumns + c];
+ }
+ return rc;
+ }
+
+ void GridLayoutState::fromLayout(QGridLayout *l)
+ {
+ rowCount = l->rowCount();
+ colCount = l->columnCount();
+ const int count = l->count();
+ for (int i = 0; i < count; i++) {
+ QLayoutItem *item = l->itemAt(i);
+ if (!LayoutInfo::isEmptyItem(item))
+ widgetItemMap.insert(item->widget(), gridItemInfo(l, i));
+ }
+ }
+
+ void GridLayoutState::applyToLayout(const QDesignerFormEditorInterface *core, QWidget *w) const
+ {
+ typedef QMap<QLayoutItem *, QRect> LayoutItemRectMap;
+ QGridLayout *grid = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, w));
+ Q_ASSERT(grid);
+ if (debugLayout)
+ qDebug() << ">GridLayoutState::applyToLayout" << *this << *grid;
+ const bool shrink = grid->rowCount() > rowCount || grid->columnCount() > colCount;
+ // Build a map of existing items to rectangles via widget map, delete spacers
+ LayoutItemRectMap itemMap;
+ while (grid->count()) {
+ QLayoutItem *item = grid->takeAt(0);
+ if (!LayoutInfo::isEmptyItem(item)) {
+ QWidget *itemWidget = item->widget();
+ const WidgetItemMap::const_iterator it = widgetItemMap.constFind(itemWidget);
+ if (it == widgetItemMap.constEnd())
+ qFatal("GridLayoutState::applyToLayout: Attempt to apply to a layout that has a widget '%s'/'%s' added after saving the state.",
+ itemWidget->metaObject()->className(), itemWidget->objectName().toUtf8().constData());
+ itemMap.insert(item, it.value());
+ } else {
+ delete item;
+ }
+ }
+ Q_ASSERT(itemMap.size() == widgetItemMap.size());
+ // recreate if shrink
+ if (shrink)
+ grid = static_cast<QGridLayout*>(recreateManagedLayout(core, w, grid));
+
+ // Add widgets items
+ const LayoutItemRectMap::const_iterator icend = itemMap.constEnd();
+ for (LayoutItemRectMap::const_iterator it = itemMap.constBegin(); it != icend; ++it) {
+ const QRect info = it.value();
+ grid->addItem(it.key(), info.y(), info.x(), info.height(), info.width());
+ }
+ // create spacers
+ const CellStates cs = cellStates(itemMap.values(), rowCount, colCount);
+ for (int r = 0; r < rowCount; r++)
+ for (int c = 0; c < colCount; c++)
+ if (needsSpacerItem(cs[r * colCount + c]))
+ grid->addItem(createGridSpacer(), r, c);
+ grid->activate();
+ if (debugLayout)
+ qDebug() << "<GridLayoutState::applyToLayout" << *grid;
+ }
+
+ void GridLayoutState::insertRow(int row)
+ {
+ rowCount++;
+ const WidgetItemMap::iterator iend = widgetItemMap.end();
+ for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
+ const int topRow = it.value().y();
+ if (topRow >= row) {
+ it.value().translate(0, 1);
+ } else { //Over it: Does it span it -> widen?
+ const int rowSpan = it.value().height();
+ if (rowSpan > 1 && topRow + rowSpan > row)
+ it.value().setHeight(rowSpan + 1);
+ }
+ }
+ }
+
+ void GridLayoutState::insertColumn(int column)
+ {
+ colCount++;
+ const WidgetItemMap::iterator iend = widgetItemMap.end();
+ for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
+ const int leftColumn = it.value().x();
+ if (leftColumn >= column) {
+ it.value().translate(1, 0);
+ } else { // Left of it: Does it span it -> widen?
+ const int colSpan = it.value().width();
+ if (colSpan > 1 && leftColumn + colSpan > column)
+ it.value().setWidth(colSpan + 1);
+ }
+ }
+ }
+
+ // Simplify: Remove empty columns/rows and such ones that are only spanned (shrink
+ // spanning items).
+ // 'AB.C.' 'ABC'
+ // 'DDDD.' ==> 'DDD'
+ // 'EF.G.' 'EFG'
+ bool GridLayoutState::simplify(const QRect &r, bool testOnly)
+ {
+ // figure out free rows/columns.
+ QVector<bool> occupiedRows(rowCount, false);
+ QVector<bool> occupiedColumns(colCount, false);
+ // Mark everything outside restriction rectangle as occupied
+ const int restrictionLeftColumn = r.x();
+ const int restrictionRightColumn = restrictionLeftColumn + r.width();
+ const int restrictionTopRow = r.y();
+ const int restrictionBottomRow = restrictionTopRow + r.height();
+ if (restrictionLeftColumn > 0 || restrictionRightColumn < colCount ||
+ restrictionTopRow > 0 || restrictionBottomRow < rowCount) {
+ for (int r = 0; r < rowCount; r++)
+ if (r < restrictionTopRow || r >= restrictionBottomRow)
+ occupiedRows[r] = true;
+ for (int c = 0; c < colCount; c++)
+ if (c < restrictionLeftColumn || c >= restrictionRightColumn)
+ occupiedColumns[c] = true;
+ }
+ // figure out free fields and tick off occupied rows and columns
+ const CellStates cs = cellStates(widgetItemMap.values(), rowCount, colCount);
+ for (int r = 0; r < rowCount; r++)
+ for (int c = 0; c < colCount; c++) {
+ const CellState &state = cs[r * colCount + c];
+ if (state.first == Occupied)
+ occupiedColumns[c] = true;
+ if (state.second == Occupied)
+ occupiedRows[r] = true;
+ }
+ // Any free rows/columns?
+ if (occupiedRows.indexOf(false) == -1 && occupiedColumns.indexOf(false) == -1)
+ return false;
+ if (testOnly)
+ return true;
+ // remove rows
+ for (int r = rowCount - 1; r >= 0; r--)
+ if (!occupiedRows[r])
+ removeFreeRow(r);
+ // remove columns
+ for (int c = colCount - 1; c >= 0; c--)
+ if (!occupiedColumns[c])
+ removeFreeColumn(c);
+ return true;
+ }
+
+ void GridLayoutState::removeFreeRow(int removeRow)
+ {
+ const WidgetItemMap::iterator iend = widgetItemMap.end();
+ for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
+ const int r = it.value().y();
+ Q_ASSERT(r != removeRow); // Free rows only
+ if (r < removeRow) { // Does the item span it? - shrink it
+ const int rowSpan = it.value().height();
+ if (rowSpan > 1) {
+ const int bottomRow = r + rowSpan;
+ if (bottomRow > removeRow)
+ it.value().setHeight(rowSpan - 1);
+ }
+ } else
+ if (r > removeRow) // Item below it? - move.
+ it.value().translate(0, -1);
+ }
+ rowCount--;
+ }
+
+ void GridLayoutState::removeFreeColumn(int removeColumn)
+ {
+ const WidgetItemMap::iterator iend = widgetItemMap.end();
+ for (WidgetItemMap::iterator it = widgetItemMap.begin(); it != iend; ++it) {
+ const int c = it.value().x();
+ Q_ASSERT(c != removeColumn); // Free columns only
+ if (c < removeColumn) { // Does the item span it? - shrink it
+ const int colSpan = it.value().width();
+ if (colSpan > 1) {
+ const int rightColumn = c + colSpan;
+ if (rightColumn > removeColumn)
+ it.value().setWidth(colSpan - 1);
+ }
+ } else
+ if (c > removeColumn) // Item to the right of it? - move.
+ it.value().translate(-1, 0);
+ }
+ colCount--;
+ }
+
+ // ---------------- GridLayoutHelper
+ class GridLayoutHelper : public LayoutHelper {
+ public:
+ GridLayoutHelper() {}
+
+ virtual QRect itemInfo(QLayout *lt, int index) const;
+ virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w);
+ virtual void removeWidget(QLayout *lt, QWidget *widget);
+ virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after);
+
+ virtual void pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout);
+ virtual void popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout);
+
+ virtual bool canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const;
+ virtual void simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea);
+
+ static void insertRow(QGridLayout *grid, int row);
+
+ private:
+ QStack<GridLayoutState> m_states;
+ };
+
+ void GridLayoutHelper::insertRow(QGridLayout *grid, int row)
+ {
+ GridLayoutState state;
+ state.fromLayout(grid);
+ state.insertRow(row);
+ QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(grid);
+ state.applyToLayout(fw->core(), grid->parentWidget());
+ }
+
+ QRect GridLayoutHelper::itemInfo(QLayout * lt, int index) const
+ {
+ QGridLayout *grid = qobject_cast<QGridLayout *>(lt);
+ Q_ASSERT(grid);
+ return gridItemInfo(grid, index);
+ }
+
+ void GridLayoutHelper::insertWidget(QLayout *lt, const QRect &info, QWidget *w)
+ {
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ QGridLayout *gridLayout = qobject_cast<QGridLayout *>(lt);
+ Q_ASSERT(gridLayout);
+ // check if there are any items. Should be only spacers, else something is wrong
+ const int row = info.y();
+ int column = info.x();
+ int colSpan = info.width();
+ int rowSpan = info.height();
+ // If not empty: A multiselection was dropped on an empty item, insert row
+ // and spread items along new row
+ if (!removeEmptyCellsOnGrid(gridLayout, info)) {
+ int freeColumn = -1;
+ colSpan = rowSpan = 1;
+ // First look to the right for a free column
+ const int columnCount = gridLayout->columnCount();
+ for (int c = column; c < columnCount; c++) {
+ const int idx = findGridItemAt(gridLayout, row, c);
+ if (idx != -1 && LayoutInfo::isEmptyItem(gridLayout->itemAt(idx))) {
+ freeColumn = c;
+ break;
+ }
+ }
+ if (freeColumn != -1) {
+ removeEmptyCellsOnGrid(gridLayout, QRect(freeColumn, row, 1, 1));
+ column = freeColumn;
+ } else {
+ GridLayoutHelper::insertRow(gridLayout, row);
+ column = 0;
+ }
+ }
+ gridLayout->addWidget(w, row , column, rowSpan, colSpan);
+ }
+
+ void GridLayoutHelper::removeWidget(QLayout *lt, QWidget *widget)
+ {
+ QGridLayout *gridLayout = qobject_cast<QGridLayout *>(lt);
+ Q_ASSERT(gridLayout);
+ const int index = gridLayout->indexOf(widget);
+ if (index == -1) {
+ qWarning() << "GridLayoutHelper::removeWidget : Attempt to remove " << widget << " which is not in the layout.";
+ return;
+ }
+ // delete old item and pad with by spacer items
+ int row, column, rowspan, colspan;
+ gridLayout->getItemPosition(index, &row, &column, &rowspan, &colspan);
+ delete gridLayout->takeAt(index);
+ const int rightColumn = column + colspan;
+ const int bottomRow = row + rowspan;
+ for (int c = column; c < rightColumn; c++)
+ for (int r = row; r < bottomRow; r++)
+ gridLayout->addItem(createGridSpacer(), r, c);
+ }
+
+ void GridLayoutHelper::replaceWidget(QLayout *lt, QWidget *before, QWidget *after)
+ {
+ bool ok = false;
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ if (QGridLayout *gridLayout = qobject_cast<QGridLayout *>(lt)) {
+ const int index = gridLayout->indexOf(before);
+ if (index != -1) {
+ int row, column, rowSpan, columnSpan;
+ gridLayout->getItemPosition (index, &row, &column, &rowSpan, &columnSpan);
+ const bool visible = before->isVisible();
+ delete gridLayout->takeAt(index);
+ if (visible)
+ before->hide();
+ before->setParent(0);
+ gridLayout->addWidget(after, row, column, rowSpan, columnSpan);
+ ok = true;
+ }
+ }
+ if (!ok)
+ qWarning() << "GridLayoutHelper::replaceWidget : Unable to replace " << before << " by " << after << " in " << lt;
+ }
+
+ void GridLayoutHelper::pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout)
+ {
+ QGridLayout *gridLayout = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
+ Q_ASSERT(gridLayout);
+ GridLayoutState gs;
+ gs.fromLayout(gridLayout);
+ m_states.push(gs);
+ }
+
+ void GridLayoutHelper::popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout)
+ {
+ Q_ASSERT(!m_states.empty());
+ const GridLayoutState state = m_states.pop();
+ state.applyToLayout(core, widgetWithManagedLayout);
+ }
+
+ bool GridLayoutHelper::canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const
+ {
+ QGridLayout *gridLayout = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
+ Q_ASSERT(gridLayout);
+ GridLayoutState gs;
+ gs.fromLayout(gridLayout);
+ return gs.simplify(restrictionArea, true);
+ }
+
+ void GridLayoutHelper::simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea)
+ {
+ QGridLayout *gridLayout = qobject_cast<QGridLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
+ Q_ASSERT(gridLayout);
+ if (debugLayout)
+ qDebug() << ">GridLayoutHelper::simplify" << *gridLayout;
+ GridLayoutState gs;
+ gs.fromLayout(gridLayout);
+ if (gs.simplify(restrictionArea, false))
+ gs.applyToLayout(core, widgetWithManagedLayout);
+ if (debugLayout)
+ qDebug() << "<GridLayoutHelper::simplify" << *gridLayout;
+ }
+
+ // ---------------- FormLayoutHelper
+ class FormLayoutHelper : public LayoutHelper {
+ public:
+ typedef QPair<QWidget *, QWidget *> WidgetPair;
+ typedef QVector<WidgetPair> FormLayoutState;
+
+ FormLayoutHelper() {}
+
+ virtual QRect itemInfo(QLayout *lt, int index) const;
+ virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w);
+ virtual void removeWidget(QLayout *lt, QWidget *widget);
+ virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after);
+
+ virtual void pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout);
+ virtual void popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout);
+
+ virtual bool canSimplify(const QDesignerFormEditorInterface *core, const QWidget *, const QRect &) const;
+ virtual void simplify(const QDesignerFormEditorInterface *, QWidget *, const QRect &);
+
+ private:
+ static FormLayoutState state(const QFormLayout *lt);
+
+ QStack<FormLayoutState> m_states;
+ };
+
+ QRect FormLayoutHelper::itemInfo(QLayout * lt, int index) const
+ {
+ QFormLayout *form = qobject_cast<QFormLayout *>(lt);
+ Q_ASSERT(form);
+ int row, column, colspan;
+ getFormLayoutItemPosition(form, index, &row, &column, 0, &colspan);
+ return QRect(column, row, colspan, 1);
+ }
+
+ void FormLayoutHelper::insertWidget(QLayout *lt, const QRect &info, QWidget *w)
+ {
+ if (debugLayout)
+ qDebug() << "FormLayoutHelper::insertWidget:" << w << info;
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ QFormLayout *formLayout = qobject_cast<QFormLayout *>(lt);
+ Q_ASSERT(formLayout);
+ // check if there are any nonspacer items? (Drop on 3rd column or drop of a multiselection
+ // on an empty item. As the Form layout does not have insert semantics; we need to manually insert a row
+ const bool insert = !removeEmptyCellsOnGrid(formLayout, info);
+ formLayoutAddWidget(formLayout, w, info, insert);
+ QLayoutSupport::createEmptyCells(formLayout);
+ }
+
+ void FormLayoutHelper::removeWidget(QLayout *lt, QWidget *widget)
+ {
+ QFormLayout *formLayout = qobject_cast<QFormLayout *>(lt);
+ Q_ASSERT(formLayout);
+ const int index = formLayout->indexOf(widget);
+ if (index == -1) {
+ qWarning() << "FormLayoutHelper::removeWidget : Attempt to remove " << widget << " which is not in the layout.";
+ return;
+ }
+ // delete old item and pad with by spacer items
+ int row, column, colspan;
+ getFormLayoutItemPosition(formLayout, index, &row, &column, 0, &colspan);
+ if (debugLayout)
+ qDebug() << "FormLayoutHelper::removeWidget: #" << index << widget << " at " << row << column << colspan;
+ delete formLayout->takeAt(index);
+ if (colspan > 1 || column == 0)
+ formLayout->setItem(row, QFormLayout::LabelRole, createFormSpacer());
+ if (colspan > 1 || column == 1)
+ formLayout->setItem(row, QFormLayout::FieldRole, createFormSpacer());
+ }
+
+ void FormLayoutHelper::replaceWidget(QLayout *lt, QWidget *before, QWidget *after)
+ {
+ bool ok = false;
+ QDesignerWidgetItemInstaller wii; // Make sure we use QDesignerWidgetItem.
+ if (QFormLayout *formLayout = qobject_cast<QFormLayout *>(lt)) {
+ const int index = formLayout->indexOf(before);
+ if (index != -1) {
+ int row;
+ QFormLayout::ItemRole role;
+ formLayout->getItemPosition (index, &row, &role);
+ const bool visible = before->isVisible();
+ delete formLayout->takeAt(index);
+ if (visible)
+ before->hide();
+ before->setParent(0);
+ formLayout->setWidget(row, role, after);
+ ok = true;
+ }
+ }
+ if (!ok)
+ qWarning() << "FormLayoutHelper::replaceWidget : Unable to replace " << before << " by " << after << " in " << lt;
+ }
+
+ FormLayoutHelper::FormLayoutState FormLayoutHelper::state(const QFormLayout *lt)
+ {
+ const int rowCount = lt->rowCount();
+ if (rowCount == 0)
+ return FormLayoutState();
+ FormLayoutState rc(rowCount, WidgetPair(0, 0));
+ const int count = lt->count();
+ int row, column, colspan;
+ for (int i = 0; i < count; i++) {
+ QLayoutItem *item = lt->itemAt(i);
+ if (!LayoutInfo::isEmptyItem(item)) {
+ QWidget *w = item->widget();
+ Q_ASSERT(w);
+ getFormLayoutItemPosition(lt, i, &row, &column, 0, &colspan);
+ if (colspan > 1 || column == 0)
+ rc[row].first = w;
+ if (colspan > 1 || column == 1)
+ rc[row].second = w;
+ }
+ }
+ if (debugLayout) {
+ qDebug() << "FormLayoutHelper::state: " << rowCount;
+ for (int r = 0; r < rowCount; r++)
+ qDebug() << " Row: " << r << rc[r].first << rc[r].second;
+ }
+ return rc;
+ }
+
+ void FormLayoutHelper::pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout)
+ {
+ QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
+ Q_ASSERT(formLayout);
+ m_states.push(state(formLayout));
+ }
+
+ void FormLayoutHelper::popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout)
+ {
+ QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
+ Q_ASSERT(!m_states.empty() && formLayout);
+
+ const FormLayoutState storedState = m_states.pop();
+ const FormLayoutState currentState = state(formLayout);
+ if (currentState == storedState)
+ return;
+ const int rowCount = storedState.size();
+ // clear out, shrink if required, but maintain items via map, pad spacers
+ const BoxLayoutHelper::LayoutItemVector items = BoxLayoutHelper::disassembleLayout(formLayout);
+ if (rowCount < formLayout->rowCount())
+ formLayout = static_cast<QFormLayout*>(recreateManagedLayout(core, widgetWithManagedLayout, formLayout ));
+ for (int r = 0; r < rowCount; r++) {
+ QWidget *widgets[FormLayoutColumns] = { storedState[r].first, storedState[r].second };
+ const bool spanning = widgets[0] != 0 && widgets[0] == widgets[1];
+ if (spanning) {
+ formLayout->setWidget(r, QFormLayout::SpanningRole, widgets[0]);
+ } else {
+ for (int c = 0; c < FormLayoutColumns; c++) {
+ const QFormLayout::ItemRole role = c == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole;
+ if (widgets[c]) {
+ Q_ASSERT(BoxLayoutHelper::findItemOfWidget(items, widgets[c]));
+ formLayout->setWidget(r, role, widgets[c]);
+ } else {
+ formLayout->setItem(r, role, createFormSpacer());
+ }
+ }
+ }
+ }
+ }
+
+ bool FormLayoutHelper::canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const
+ {
+ const QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
+ Q_ASSERT(formLayout);
+ return canSimplifyFormLayout(formLayout, restrictionArea);
+ }
+
+ void FormLayoutHelper::simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea)
+ {
+ typedef QPair<QLayoutItem*, QLayoutItem*> LayoutItemPair;
+ typedef QVector<LayoutItemPair> LayoutItemPairs;
+
+ QFormLayout *formLayout = qobject_cast<QFormLayout *>(LayoutInfo::managedLayout(core, widgetWithManagedLayout));
+ Q_ASSERT(formLayout);
+ if (debugLayout)
+ qDebug() << "FormLayoutHelper::simplify";
+ // Transform into vector of item pairs
+ const int rowCount = formLayout->rowCount();
+ LayoutItemPairs pairs(rowCount, LayoutItemPair(0, 0));
+ for (int i = formLayout->count() - 1; i >= 0; i--) {
+ int row, col,colspan;
+ getFormLayoutItemPosition(formLayout, i, &row, &col, 0, &colspan);
+ if (colspan > 1) {
+ pairs[row].first = pairs[row].second = formLayout->takeAt(i);
+ } else {
+ if (col == 0)
+ pairs[row].first = formLayout->takeAt(i);
+ else
+ pairs[row].second = formLayout->takeAt(i);
+ }
+ }
+ // Weed out empty ones
+ const int bottomCheckRow = qMin(rowCount, restrictionArea.y() + restrictionArea.height());
+ for (int r = bottomCheckRow - 1; r >= restrictionArea.y(); r--)
+ if (LayoutInfo::isEmptyItem(pairs[r].first) && LayoutInfo::isEmptyItem(pairs[r].second)) {
+ delete pairs[r].first;
+ delete pairs[r].second;
+ pairs.remove(r);
+ }
+ const int simpleRowCount = pairs.size();
+ if (simpleRowCount < rowCount)
+ formLayout = static_cast<QFormLayout *>(recreateManagedLayout(core, widgetWithManagedLayout, formLayout));
+ // repopulate
+ for (int r = 0; r < simpleRowCount; r++) {
+ const bool spanning = pairs[r].first == pairs[r].second;
+ if (spanning) {
+ formLayout->setItem(r, QFormLayout::SpanningRole, pairs[r].first);
+ } else {
+ formLayout->setItem(r, QFormLayout::LabelRole, pairs[r].first);
+ formLayout->setItem(r, QFormLayout::FieldRole, pairs[r].second);
+ }
+ }
+ }
+
+LayoutHelper *LayoutHelper::createLayoutHelper(int type)
+{
+ LayoutHelper *rc = 0;
+ switch (type) {
+ case LayoutInfo::HBox:
+ rc = new BoxLayoutHelper(Qt::Horizontal);
+ break;
+ case LayoutInfo::VBox:
+ rc = new BoxLayoutHelper(Qt::Vertical);
+ break;
+ case LayoutInfo::Grid:
+ rc = new GridLayoutHelper;
+ break;
+ case LayoutInfo::Form:
+ return new FormLayoutHelper;
+ default:
+ break;
+ }
+ Q_ASSERT(rc);
+ return rc;
+}
+
+// ---- QLayoutSupport (LayoutDecorationExtension)
+QLayoutSupport::QLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, LayoutHelper *helper, QObject *parent) :
+ QObject(parent),
+ m_formWindow(formWindow),
+ m_helper(helper),
+ m_widget(widget),
+ m_currentIndex(-1),
+ m_currentInsertMode(QDesignerLayoutDecorationExtension::InsertWidgetMode)
+{
+}
+
+QLayout * QLayoutSupport::layout() const
+{
+ return LayoutInfo::managedLayout(m_formWindow->core(), m_widget);
+}
+
+void QLayoutSupport::hideIndicator(Indicator i)
+{
+ if (m_indicators[i])
+ m_indicators[i]->hide();
+}
+
+void QLayoutSupport::showIndicator(Indicator i, const QRect &geometry, const QPalette &p)
+{
+ if (!m_indicators[i])
+ m_indicators[i] = new qdesigner_internal::InvisibleWidget(m_widget);
+ QWidget *indicator = m_indicators[i];
+ indicator->setAutoFillBackground(true);
+ indicator->setPalette(p);
+ indicator->setGeometry(geometry);
+ indicator->show();
+ indicator->raise();
+}
+
+QLayoutSupport::~QLayoutSupport()
+{
+ delete m_helper;
+ for (int i = 0; i < NumIndicators; i++)
+ if (m_indicators[i])
+ m_indicators[i]->deleteLater();
+}
+
+QGridLayout * QLayoutSupport::gridLayout() const
+{
+ return qobject_cast<QGridLayout*>(LayoutInfo::managedLayout(m_formWindow->core(), m_widget));
+}
+
+QRect QLayoutSupport::itemInfo(int index) const
+{
+ return m_helper->itemInfo(LayoutInfo::managedLayout(m_formWindow->core(), m_widget), index);
+}
+
+void QLayoutSupport::setInsertMode(InsertMode im)
+{
+ m_currentInsertMode = im;
+}
+
+void QLayoutSupport::setCurrentCell(const QPair<int, int> &cell)
+{
+ m_currentCell = cell;
+}
+
+void QLayoutSupport::adjustIndicator(const QPoint &pos, int index)
+{
+ if (index == -1) { // first item goes anywhere
+ hideIndicator(LeftIndicator);
+ hideIndicator(TopIndicator);
+ hideIndicator(RightIndicator);
+ hideIndicator(BottomIndicator);
+ return;
+ }
+ m_currentIndex = index;
+ m_currentInsertMode = QDesignerLayoutDecorationExtension::InsertWidgetMode;
+
+ QLayoutItem *item = layout()->itemAt(index);
+ const QRect g = extendedGeometry(index);
+ // ### cleanup
+ if (LayoutInfo::isEmptyItem(item)) {
+ // Empty grid/form cell. Draw a rectangle
+ QPalette redPalette;
+ redPalette.setColor(QPalette::Window, Qt::red);
+
+ showIndicator(LeftIndicator, QRect(g.x(), g.y(), indicatorSize, g.height()), redPalette);
+ showIndicator(TopIndicator, QRect(g.x(), g.y(), g.width(), indicatorSize), redPalette);
+ showIndicator(RightIndicator, QRect(g.right(), g.y(), indicatorSize, g.height()), redPalette);
+ showIndicator(BottomIndicator, QRect(g.x(), g.bottom(), g.width(), indicatorSize), redPalette);
+ setCurrentCellFromIndicatorOnEmptyCell(m_currentIndex);
+ } else {
+ // Append/Insert. Draw a bar left/right or above/below
+ QPalette bluePalette;
+ bluePalette.setColor(QPalette::Window, Qt::blue);
+ hideIndicator(LeftIndicator);
+ hideIndicator(TopIndicator);
+
+ const int fromRight = g.right() - pos.x();
+ const int fromBottom = g.bottom() - pos.y();
+
+ const int fromLeft = pos.x() - g.x();
+ const int fromTop = pos.y() - g.y();
+
+ const int fromLeftRight = qMin(fromRight, fromLeft );
+ const int fromBottomTop = qMin(fromBottom, fromTop);
+
+ const Qt::Orientation indicatorOrientation = fromLeftRight < fromBottomTop ? Qt::Vertical : Qt::Horizontal;
+
+ if (supportsIndicatorOrientation(indicatorOrientation)) {
+ const QRect r(layout()->geometry().topLeft(), layout()->parentWidget()->size());
+ switch (indicatorOrientation) {
+ case Qt::Vertical: {
+ hideIndicator(BottomIndicator);
+ const bool closeToLeft = fromLeftRight == fromLeft;
+ showIndicator(RightIndicator, QRect(closeToLeft ? g.x() : g.right() + 1 - indicatorSize, 0, indicatorSize, r.height()), bluePalette);
+
+ const int incr = closeToLeft ? 0 : +1;
+ setCurrentCellFromIndicator(indicatorOrientation, m_currentIndex, incr);
+ }
+ break;
+ case Qt::Horizontal: {
+ hideIndicator(RightIndicator);
+ const bool closeToTop = fromBottomTop == fromTop;
+ showIndicator(BottomIndicator, QRect(r.x(), closeToTop ? g.y() : g.bottom() + 1 - indicatorSize, r.width(), indicatorSize), bluePalette);
+
+ const int incr = closeToTop ? 0 : +1;
+ setCurrentCellFromIndicator(indicatorOrientation, m_currentIndex, incr);
+ }
+ break;
+ }
+ } else {
+ hideIndicator(RightIndicator);
+ hideIndicator(BottomIndicator);
+ } // can handle indicatorOrientation
+ }
+}
+
+int QLayoutSupport::indexOf(QLayoutItem *i) const
+{
+ const QLayout *lt = layout();
+ if (!lt)
+ return -1;
+
+ int index = 0;
+
+ while (QLayoutItem *item = lt->itemAt(index)) {
+ if (item == i)
+ return index;
+
+ ++index;
+ }
+
+ return -1;
+}
+
+int QLayoutSupport::indexOf(QWidget *widget) const
+{
+ const QLayout *lt = layout();
+ if (!lt)
+ return -1;
+
+ int index = 0;
+ while (QLayoutItem *item = lt->itemAt(index)) {
+ if (item->widget() == widget)
+ return index;
+
+ ++index;
+ }
+
+ return -1;
+}
+
+QList<QWidget*> QLayoutSupport::widgets(QLayout *layout) const
+{
+ if (!layout)
+ return QList<QWidget*>();
+
+ QList<QWidget*> lst;
+ int index = 0;
+ while (QLayoutItem *item = layout->itemAt(index)) {
+ ++index;
+
+ QWidget *widget = item->widget();
+ if (widget && formWindow()->isManaged(widget))
+ lst.append(widget);
+ }
+
+ return lst;
+}
+
+int QLayoutSupport::findItemAt(QGridLayout *gridLayout, int at_row, int at_column)
+{
+ return findGridItemAt(gridLayout, at_row, at_column);
+}
+
+// Quick check whether simplify should be enabled for grids. May return false positives.
+// Note: Calculating the occupied area does not work as spanning items may also be simplified.
+
+bool QLayoutSupport::canSimplifyQuickCheck(const QGridLayout *gl)
+{
+ if (!gl)
+ return false;
+ const int colCount = gl->columnCount();
+ const int rowCount = gl->rowCount();
+ if (colCount < 2 || rowCount < 2)
+ return false;
+ // try to find a spacer.
+ const int count = gl->count();
+ for (int index = 0; index < count; index++)
+ if (LayoutInfo::isEmptyItem(gl->itemAt(index)))
+ return true;
+ return false;
+}
+
+bool QLayoutSupport::canSimplifyQuickCheck(const QFormLayout *fl)
+{
+ return canSimplifyFormLayout(fl, QRect(QPoint(0, 0), QSize(32767, 32767)));
+}
+
+// remove dummy spacers
+bool QLayoutSupport::removeEmptyCells(QGridLayout *grid, const QRect &area)
+{
+ return removeEmptyCellsOnGrid(grid, area);
+}
+
+void QLayoutSupport::createEmptyCells(QGridLayout *gridLayout)
+{
+ Q_ASSERT(gridLayout);
+ GridLayoutState gs;
+ gs.fromLayout(gridLayout);
+
+ const GridLayoutState::CellStates cs = GridLayoutState::cellStates(gs.widgetItemMap.values(), gs.rowCount, gs.colCount);
+ for (int c = 0; c < gs.colCount; c++)
+ for (int r = 0; r < gs.rowCount; r++)
+ if (needsSpacerItem(cs[r * gs.colCount + c])) {
+ const int existingItemIndex = findItemAt(gridLayout, r, c);
+ if (existingItemIndex == -1)
+ gridLayout->addItem(createGridSpacer(), r, c);
+ }
+}
+
+bool QLayoutSupport::removeEmptyCells(QFormLayout *formLayout, const QRect &area)
+{
+ return removeEmptyCellsOnGrid(formLayout, area);
+}
+
+void QLayoutSupport::createEmptyCells(QFormLayout *formLayout)
+{
+ // No spanning items here..
+ if (const int rowCount = formLayout->rowCount())
+ for (int c = 0; c < FormLayoutColumns; c++)
+ for (int r = 0; r < rowCount; r++)
+ if (findGridItemAt(formLayout, r, c) == -1)
+ formLayout->setItem(r, c == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole, createFormSpacer());
+}
+
+int QLayoutSupport::findItemAt(const QPoint &pos) const
+{
+ if (!layout())
+ return -1;
+
+ const QLayout *lt = layout();
+ const int count = lt->count();
+
+ if (count == 0)
+ return -1;
+
+ int best = -1;
+ int bestIndex = -1;
+
+ for (int index = 0; index < count; index++) {
+ QLayoutItem *item = lt->itemAt(index);
+ bool visible = true;
+ // When dragging widgets within layout, the source widget is invisible and must not be hit
+ if (const QWidget *w = item->widget())
+ visible = w->isVisible();
+ if (visible) {
+ const QRect g = item->geometry();
+
+ const int dist = (g.center() - pos).manhattanLength();
+ if (best == -1 || dist < best) {
+ best = dist;
+ bestIndex = index;
+ }
+ }
+ }
+ return bestIndex;
+}
+
+// ------------ QBoxLayoutSupport (LayoutDecorationExtension)
+namespace {
+class QBoxLayoutSupport: public QLayoutSupport
+{
+public:
+ QBoxLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, Qt::Orientation orientation, QObject *parent = 0);
+
+ virtual void insertWidget(QWidget *widget, const QPair<int, int> &cell);
+ virtual void removeWidget(QWidget *widget);
+ virtual void simplify() {}
+ virtual void insertRow(int /*row*/) {}
+ virtual void insertColumn(int /*column*/) {}
+
+ virtual int findItemAt(int /*at_row*/, int /*at_column*/) const { return -1; }
+
+private:
+ virtual void setCurrentCellFromIndicatorOnEmptyCell(int index);
+ virtual void setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment);
+ virtual bool supportsIndicatorOrientation(Qt::Orientation indicatorOrientation) const;
+ virtual QRect extendedGeometry(int index) const;
+
+ const Qt::Orientation m_orientation;
+};
+
+void QBoxLayoutSupport::removeWidget(QWidget *widget)
+{
+ QLayout *lt = layout();
+ const int index = lt->indexOf(widget);
+ // Adjust the current cell in case a widget was dragged within the same layout to a position
+ // of higher index, which happens as follows:
+ // Drag start: The widget is hidden
+ // Drop: Current cell is stored, widget is removed and re-added, causing an index offset that needs to be compensated
+ QPair<int, int> currCell = currentCell();
+ switch (m_orientation) {
+ case Qt::Horizontal:
+ if (currCell.second > 0 && index < currCell.second ) {
+ currCell.second--;
+ setCurrentCell(currCell);
+ }
+ break;
+ case Qt::Vertical:
+ if (currCell.first > 0 && index < currCell.first) {
+ currCell.first--;
+ setCurrentCell(currCell);
+ }
+ break;
+ }
+ helper()->removeWidget(lt, widget);
+}
+
+QBoxLayoutSupport::QBoxLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, Qt::Orientation orientation, QObject *parent) :
+ QLayoutSupport(formWindow, widget, new BoxLayoutHelper(orientation), parent),
+ m_orientation(orientation)
+{
+}
+
+void QBoxLayoutSupport::setCurrentCellFromIndicatorOnEmptyCell(int index)
+{
+ qDebug() << "QBoxLayoutSupport::setCurrentCellFromIndicatorOnEmptyCell(): Warning: found a fake spacer inside a vbox layout at " << index;
+ setCurrentCell(qMakePair(0, 0));
+}
+
+void QBoxLayoutSupport::insertWidget(QWidget *widget, const QPair<int, int> &cell)
+{
+ switch (m_orientation) {
+ case Qt::Horizontal:
+ helper()->insertWidget(layout(), QRect(cell.second, 0, 1, 1), widget);
+ break;
+ case Qt::Vertical:
+ helper()->insertWidget(layout(), QRect(0, cell.first, 1, 1), widget);
+ break;
+ }
+}
+
+void QBoxLayoutSupport::setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment)
+{
+ if (m_orientation == Qt::Horizontal && indicatorOrientation == Qt::Vertical) {
+ setCurrentCell(qMakePair(0, index + increment));
+ } else if (m_orientation == Qt::Vertical && indicatorOrientation == Qt::Horizontal) {
+ setCurrentCell(qMakePair(index + increment, 0));
+ }
+}
+
+bool QBoxLayoutSupport::supportsIndicatorOrientation(Qt::Orientation indicatorOrientation) const
+{
+ return m_orientation != indicatorOrientation;
+}
+
+QRect QBoxLayoutSupport::extendedGeometry(int index) const
+{
+ QLayoutItem *item = layout()->itemAt(index);
+ // start off with item geometry
+ QRect g = item->geometry();
+
+ const QRect info = itemInfo(index);
+
+ // On left border: extend to widget border
+ if (info.x() == 0) {
+ QPoint topLeft = g.topLeft();
+ topLeft.rx() = layout()->geometry().left();
+ g.setTopLeft(topLeft);
+ }
+
+ // On top border: extend to widget border
+ if (info.y() == 0) {
+ QPoint topLeft = g.topLeft();
+ topLeft.ry() = layout()->geometry().top();
+ g.setTopLeft(topLeft);
+ }
+
+ // is this the last item?
+ const QBoxLayout *box = static_cast<const QBoxLayout*>(layout());
+ if (index < box->count() -1)
+ return g; // Nope.
+
+ // extend to widget border
+ QPoint bottomRight = g.bottomRight();
+ switch (m_orientation) {
+ case Qt::Vertical:
+ bottomRight.ry() = layout()->geometry().bottom();
+ break;
+ case Qt::Horizontal:
+ bottomRight.rx() = layout()->geometry().right();
+ break;
+ }
+ g.setBottomRight(bottomRight);
+ return g;
+}
+
+// -------------- Base class for QGridLayout-like support classes (LayoutDecorationExtension)
+template <class GridLikeLayout>
+class GridLikeLayoutSupportBase: public QLayoutSupport
+{
+public:
+
+ GridLikeLayoutSupportBase(QDesignerFormWindowInterface *formWindow, QWidget *widget, LayoutHelper *helper, QObject *parent = 0) :
+ QLayoutSupport(formWindow, widget, helper, parent) {}
+
+ void insertWidget(QWidget *widget, const QPair<int, int> &cell);
+ virtual void removeWidget(QWidget *widget) { helper()->removeWidget(layout(), widget); }
+ virtual int findItemAt(int row, int column) const;
+
+protected:
+ GridLikeLayout *gridLikeLayout() const {
+ return qobject_cast<GridLikeLayout*>(LayoutInfo::managedLayout(formWindow()->core(), widget()));
+ }
+
+private:
+
+ virtual void setCurrentCellFromIndicatorOnEmptyCell(int index);
+ virtual void setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment);
+ virtual bool supportsIndicatorOrientation(Qt::Orientation) const { return true; }
+
+ virtual QRect extendedGeometry(int index) const;
+
+ // Overwrite to check the insertion position (if there are limits)
+ virtual void checkCellForInsertion(int * /*row*/, int * /*col*/) const {}
+};
+
+template <class GridLikeLayout>
+void GridLikeLayoutSupportBase<GridLikeLayout>::setCurrentCellFromIndicatorOnEmptyCell(int index)
+{
+ GridLikeLayout *grid = gridLikeLayout();
+ Q_ASSERT(grid);
+
+ setInsertMode(InsertWidgetMode);
+ int row, column, rowspan, colspan;
+
+ getGridItemPosition(grid, index, &row, &column, &rowspan, &colspan);
+ setCurrentCell(qMakePair(row, column));
+}
+
+template <class GridLikeLayout>
+void GridLikeLayoutSupportBase<GridLikeLayout>::setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment) {
+ const QRect info = itemInfo(index);
+ switch (indicatorOrientation) {
+ case Qt::Vertical: {
+ setInsertMode(InsertColumnMode);
+ int row = info.top();
+ int column = increment ? info.right() + 1 : info.left();
+ checkCellForInsertion(&row, &column);
+ setCurrentCell(qMakePair(row , column));
+ }
+ break;
+ case Qt::Horizontal: {
+ setInsertMode(InsertRowMode);
+ int row = increment ? info.bottom() + 1 : info.top();
+ int column = info.left();
+ checkCellForInsertion(&row, &column);
+ setCurrentCell(qMakePair(row, column));
+ }
+ break;
+ }
+}
+
+template <class GridLikeLayout>
+void GridLikeLayoutSupportBase<GridLikeLayout>::insertWidget(QWidget *widget, const QPair<int, int> &cell)
+{
+ helper()->insertWidget(layout(), QRect(cell.second, cell.first, 1, 1), widget);
+}
+
+template <class GridLikeLayout>
+int GridLikeLayoutSupportBase<GridLikeLayout>::findItemAt(int at_row, int at_column) const
+{
+ GridLikeLayout *grid = gridLikeLayout();
+ Q_ASSERT(grid);
+ return findGridItemAt(grid, at_row, at_column);
+}
+
+template <class GridLikeLayout>
+QRect GridLikeLayoutSupportBase<GridLikeLayout>::extendedGeometry(int index) const
+{
+ QLayoutItem *item = layout()->itemAt(index);
+ // start off with item geometry
+ QRect g = item->geometry();
+
+ const QRect info = itemInfo(index);
+
+ // On left border: extend to widget border
+ if (info.x() == 0) {
+ QPoint topLeft = g.topLeft();
+ topLeft.rx() = layout()->geometry().left();
+ g.setTopLeft(topLeft);
+ }
+
+ // On top border: extend to widget border
+ if (info.y() == 0) {
+ QPoint topLeft = g.topLeft();
+ topLeft.ry() = layout()->geometry().top();
+ g.setTopLeft(topLeft);
+ }
+ const GridLikeLayout *grid = gridLikeLayout();
+ Q_ASSERT(grid);
+
+ // extend to widget border
+ QPoint bottomRight = g.bottomRight();
+ if (gridRowCount(grid) == info.y())
+ bottomRight.ry() = layout()->geometry().bottom();
+ if (gridColumnCount(grid) == info.x())
+ bottomRight.rx() = layout()->geometry().right();
+ g.setBottomRight(bottomRight);
+ return g;
+}
+
+// -------------- QGridLayoutSupport (LayoutDecorationExtension)
+class QGridLayoutSupport: public GridLikeLayoutSupportBase<QGridLayout>
+{
+public:
+
+ QGridLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent = 0);
+
+ virtual void simplify();
+ virtual void insertRow(int row);
+ virtual void insertColumn(int column);
+
+private:
+};
+
+QGridLayoutSupport::QGridLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent) :
+ GridLikeLayoutSupportBase<QGridLayout>(formWindow, widget, new GridLayoutHelper, parent)
+{
+}
+
+void QGridLayoutSupport::insertRow(int row)
+{
+ QGridLayout *grid = gridLayout();
+ Q_ASSERT(grid);
+ GridLayoutHelper::insertRow(grid, row);
+}
+
+void QGridLayoutSupport::insertColumn(int column)
+{
+ QGridLayout *grid = gridLayout();
+ Q_ASSERT(grid);
+ GridLayoutState state;
+ state.fromLayout(grid);
+ state.insertColumn(column);
+ state.applyToLayout(formWindow()->core(), widget());
+}
+
+void QGridLayoutSupport::simplify()
+{
+ QGridLayout *grid = gridLayout();
+ Q_ASSERT(grid);
+ GridLayoutState state;
+ state.fromLayout(grid);
+
+ const QRect fullArea = QRect(0, 0, state.colCount, state.rowCount);
+ if (state.simplify(fullArea, false))
+ state.applyToLayout(formWindow()->core(), widget());
+}
+
+// -------------- QFormLayoutSupport (LayoutDecorationExtension)
+class QFormLayoutSupport: public GridLikeLayoutSupportBase<QFormLayout>
+{
+public:
+ QFormLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent = 0);
+
+ virtual void simplify() {}
+ virtual void insertRow(int /*row*/) {}
+ virtual void insertColumn(int /*column*/) {}
+
+private:
+ virtual void checkCellForInsertion(int * row, int *col) const;
+};
+
+QFormLayoutSupport::QFormLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent) :
+ GridLikeLayoutSupportBase<QFormLayout>(formWindow, widget, new FormLayoutHelper, parent)
+{
+}
+
+void QFormLayoutSupport::checkCellForInsertion(int *row, int *col) const
+{
+ if (*col >= FormLayoutColumns) { // Clamp to 2 columns
+ *col = 1;
+ (*row)++;
+ }
+}
+} // anonymous namespace
+
+QLayoutSupport *QLayoutSupport::createLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent)
+{
+ const QLayout *layout = LayoutInfo::managedLayout(formWindow->core(), widget);
+ Q_ASSERT(layout);
+ QLayoutSupport *rc = 0;
+ switch (LayoutInfo::layoutType(formWindow->core(), layout)) {
+ case LayoutInfo::HBox:
+ rc = new QBoxLayoutSupport(formWindow, widget, Qt::Horizontal, parent);
+ break;
+ case LayoutInfo::VBox:
+ rc = new QBoxLayoutSupport(formWindow, widget, Qt::Vertical, parent);
+ break;
+ case LayoutInfo::Grid:
+ rc = new QGridLayoutSupport(formWindow, widget, parent);
+ break;
+ case LayoutInfo::Form:
+ rc = new QFormLayoutSupport(formWindow, widget, parent);
+ break;
+ default:
+ break;
+ }
+ Q_ASSERT(rc);
+ return rc;
+}
+} // namespace qdesigner_internal
+
+// -------------- QLayoutWidget
+QLayoutWidget::QLayoutWidget(QDesignerFormWindowInterface *formWindow, QWidget *parent)
+ : QWidget(parent), m_formWindow(formWindow),
+ m_leftMargin(0), m_topMargin(0), m_rightMargin(0), m_bottomMargin(0)
+{
+}
+
+void QLayoutWidget::paintEvent(QPaintEvent*)
+{
+ if (m_formWindow->currentTool() != 0)
+ return;
+
+ // only draw red borders if we're editting widgets
+
+ QPainter p(this);
+
+ QMap<int, QMap<int, bool> > excludedRowsForColumn;
+ QMap<int, QMap<int, bool> > excludedColumnsForRow;
+
+ QLayout *lt = layout();
+ QGridLayout *grid = qobject_cast<QGridLayout *>(lt);
+ if (lt) {
+ if (const int count = lt->count()) {
+ p.setPen(QPen(QColor(255, 0, 0, 35), 1));
+ for (int i = 0; i < count; i++) {
+ QLayoutItem *item = lt->itemAt(i);
+ if (grid) {
+ int row, column, rowSpan, columnSpan;
+ grid->getItemPosition(i, &row, &column, &rowSpan, &columnSpan);
+ QMap<int, bool> rows;
+ QMap<int, bool> columns;
+ for (int i = rowSpan; i > 1; i--)
+ rows[row + i - 2] = true;
+ for (int i = columnSpan; i > 1; i--)
+ columns[column + i - 2] = true;
+
+ while (rowSpan > 0) {
+ excludedColumnsForRow[row + rowSpan - 1].unite(columns);
+ rowSpan--;
+ }
+ while (columnSpan > 0) {
+ excludedRowsForColumn[column + columnSpan - 1].unite(rows);
+ columnSpan--;
+ }
+ }
+ if (item->spacerItem()) {
+ const QRect geometry = item->geometry();
+ if (!geometry.isNull())
+ p.drawRect(geometry.adjusted(1, 1, -2, -2));
+ }
+ }
+ }
+ }
+ if (grid) {
+ p.setPen(QPen(QColor(0, 0x80, 0, 0x80), 1));
+ const int rowCount = grid->rowCount();
+ const int columnCount = grid->columnCount();
+ for (int i = 0; i < rowCount; i++) {
+ for (int j = 0; j < columnCount; j++) {
+ const QRect cellRect = grid->cellRect(i, j);
+ if (j < columnCount - 1 && excludedColumnsForRow.value(i).value(j, false) == false) {
+ const double y0 = (i == 0)
+ ? 0 : (grid->cellRect(i - 1, j).bottom() + cellRect.top()) / 2.0;
+ const double y1 = (i == rowCount - 1)
+ ? height() - 1 : (cellRect.bottom() + grid->cellRect(i + 1, j).top()) / 2.0;
+ const double x = (cellRect.right() + grid->cellRect(i, j + 1).left()) / 2.0;
+ p.drawLine(QPointF(x, y0), QPointF(x, y1));
+ }
+ if (i < rowCount - 1 && excludedRowsForColumn.value(j).value(i, false) == false) {
+ const double x0 = (j == 0)
+ ? 0 : (grid->cellRect(i, j - 1).right() + cellRect.left()) / 2.0;
+ const double x1 = (j == columnCount - 1)
+ ? width() - 1 : (cellRect.right() + grid->cellRect(i, j + 1).left()) / 2.0;
+ const double y = (cellRect.bottom() + grid->cellRect(i + 1, j).top()) / 2.0;
+ p.drawLine(QPointF(x0, y), QPointF(x1, y));
+ }
+ }
+ }
+ }
+ p.setPen(QPen(QColor(255, 0, 0, 128), 1));
+ p.drawRect(0, 0, width() - 1, height() - 1);
+}
+
+bool QLayoutWidget::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::LayoutRequest: {
+ (void) QWidget::event(e);
+ // Magic: We are layouted, but the parent is not..
+ if (layout() && qdesigner_internal::LayoutInfo::layoutType(formWindow()->core(), parentWidget()) == qdesigner_internal::LayoutInfo::NoLayout) {
+ resize(layout()->totalMinimumSize().expandedTo(size()));
+ }
+
+ update();
+
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ return QWidget::event(e);
+}
+
+int QLayoutWidget::layoutLeftMargin() const
+{
+ if (m_leftMargin < 0 && layout()) {
+ int margin;
+ layout()->getContentsMargins(&margin, 0, 0, 0);
+ return margin;
+ }
+ return m_leftMargin;
+}
+
+void QLayoutWidget::setLayoutLeftMargin(int layoutMargin)
+{
+ m_leftMargin = layoutMargin;
+ if (layout()) {
+ int newMargin = m_leftMargin;
+ if (newMargin >= 0 && newMargin < ShiftValue)
+ newMargin = ShiftValue;
+ int left, top, right, bottom;
+ layout()->getContentsMargins(&left, &top, &right, &bottom);
+ layout()->setContentsMargins(newMargin, top, right, bottom);
+ }
+}
+
+int QLayoutWidget::layoutTopMargin() const
+{
+ if (m_topMargin < 0 && layout()) {
+ int margin;
+ layout()->getContentsMargins(0, &margin, 0, 0);
+ return margin;
+ }
+ return m_topMargin;
+}
+
+void QLayoutWidget::setLayoutTopMargin(int layoutMargin)
+{
+ m_topMargin = layoutMargin;
+ if (layout()) {
+ int newMargin = m_topMargin;
+ if (newMargin >= 0 && newMargin < ShiftValue)
+ newMargin = ShiftValue;
+ int left, top, right, bottom;
+ layout()->getContentsMargins(&left, &top, &right, &bottom);
+ layout()->setContentsMargins(left, newMargin, right, bottom);
+ }
+}
+
+int QLayoutWidget::layoutRightMargin() const
+{
+ if (m_rightMargin < 0 && layout()) {
+ int margin;
+ layout()->getContentsMargins(0, 0, &margin, 0);
+ return margin;
+ }
+ return m_rightMargin;
+}
+
+void QLayoutWidget::setLayoutRightMargin(int layoutMargin)
+{
+ m_rightMargin = layoutMargin;
+ if (layout()) {
+ int newMargin = m_rightMargin;
+ if (newMargin >= 0 && newMargin < ShiftValue)
+ newMargin = ShiftValue;
+ int left, top, right, bottom;
+ layout()->getContentsMargins(&left, &top, &right, &bottom);
+ layout()->setContentsMargins(left, top, newMargin, bottom);
+ }
+}
+
+int QLayoutWidget::layoutBottomMargin() const
+{
+ if (m_bottomMargin < 0 && layout()) {
+ int margin;
+ layout()->getContentsMargins(0, 0, 0, &margin);
+ return margin;
+ }
+ return m_bottomMargin;
+}
+
+void QLayoutWidget::setLayoutBottomMargin(int layoutMargin)
+{
+ m_bottomMargin = layoutMargin;
+ if (layout()) {
+ int newMargin = m_bottomMargin;
+ if (newMargin >= 0 && newMargin < ShiftValue)
+ newMargin = ShiftValue;
+ int left, top, right, bottom;
+ layout()->getContentsMargins(&left, &top, &right, &bottom);
+ layout()->setContentsMargins(left, top, right, newMargin);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qlayout_widget_p.h b/tools/designer/src/lib/shared/qlayout_widget_p.h
new file mode 100644
index 0000000000..785608869e
--- /dev/null
+++ b/tools/designer/src/lib/shared/qlayout_widget_p.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QLAYOUT_WIDGET_H
+#define QLAYOUT_WIDGET_H
+
+#include "shared_global_p.h"
+
+#include <QtDesigner/QDesignerLayoutDecorationExtension>
+
+#include <QtCore/QPointer>
+#include <QtCore/QVariant>
+#include <QtGui/QWidget>
+#include <QtGui/QLayout>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+class QGridLayout;
+class QFormLayout;
+
+namespace qdesigner_internal {
+// ---- LayoutProperties: Helper struct that stores all layout-relevant properties
+// with functions to retrieve and apply to property sheets. Can be used to store the state
+// for undo commands and while rebuilding layouts.
+struct QDESIGNER_SHARED_EXPORT LayoutProperties
+{
+ LayoutProperties();
+ void clear();
+
+ enum Margins { LeftMargin, TopMargin, RightMargin, BottomMargin, MarginCount };
+ enum Spacings { Spacing, HorizSpacing, VertSpacing, SpacingsCount };
+
+ enum PropertyMask {
+ ObjectNameProperty = 0x1,
+ LeftMarginProperty = 0x2, TopMarginProperty = 0x4, RightMarginProperty = 0x8, BottomMarginProperty = 0x10,
+ SpacingProperty = 0x20, HorizSpacingProperty = 0x40, VertSpacingProperty = 0x80,
+ SizeConstraintProperty = 0x100,
+ FieldGrowthPolicyProperty = 0x200, RowWrapPolicyProperty = 0x400, LabelAlignmentProperty = 0x0800, FormAlignmentProperty = 0x1000,
+ BoxStretchProperty = 0x2000, GridRowStretchProperty = 0x4000, GridColumnStretchProperty = 0x8000,
+ GridRowMinimumHeightProperty = 0x10000, GridColumnMinimumWidthProperty = 0x20000,
+ AllProperties = 0xFFFF};
+
+ // return a PropertyMask of visible properties
+ static int visibleProperties(const QLayout *layout);
+
+ // Retrieve from /apply to sheet: A property mask is returned indicating the properties found in the sheet
+ int fromPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask = AllProperties);
+ int toPropertySheet(const QDesignerFormEditorInterface *core, QLayout *l, int mask = AllProperties, bool applyChanged = true) const;
+
+ int m_margins[MarginCount];
+ bool m_marginsChanged[MarginCount];
+
+ int m_spacings[SpacingsCount];
+ bool m_spacingsChanged[SpacingsCount];
+
+ QVariant m_objectName; // receives a PropertySheetStringValue
+ bool m_objectNameChanged;
+ QVariant m_sizeConstraint;
+ bool m_sizeConstraintChanged;
+
+ bool m_fieldGrowthPolicyChanged;
+ QVariant m_fieldGrowthPolicy;
+ bool m_rowWrapPolicyChanged;
+ QVariant m_rowWrapPolicy;
+ bool m_labelAlignmentChanged;
+ QVariant m_labelAlignment;
+ bool m_formAlignmentChanged;
+ QVariant m_formAlignment;
+
+ bool m_boxStretchChanged;
+ QVariant m_boxStretch;
+
+ bool m_gridRowStretchChanged;
+ QVariant m_gridRowStretch;
+
+ bool m_gridColumnStretchChanged;
+ QVariant m_gridColumnStretch;
+
+ bool m_gridRowMinimumHeightChanged;
+ QVariant m_gridRowMinimumHeight;
+
+ bool m_gridColumnMinimumWidthChanged;
+ QVariant m_gridColumnMinimumWidth;
+};
+
+// -- LayoutHelper: For use with the 'insert widget'/'delete widget' command,
+// able to store and restore states.
+// This could become part of 'QDesignerLayoutDecorationExtensionV2',
+// but to keep any existing old extensions working, it is provided as
+// separate class with a factory function.
+class LayoutHelper {
+protected:
+ LayoutHelper();
+
+public:
+ virtual ~LayoutHelper();
+
+ static LayoutHelper *createLayoutHelper(int type);
+
+ static int indexOf(const QLayout *lt, const QWidget *widget);
+
+ // Return area of an item (x == columns)
+ QRect itemInfo(QLayout *lt, const QWidget *widget) const;
+
+ virtual QRect itemInfo(QLayout *lt, int index) const = 0;
+ virtual void insertWidget(QLayout *lt, const QRect &info, QWidget *w) = 0;
+ virtual void removeWidget(QLayout *lt, QWidget *widget) = 0;
+ // Since 4.5: The 'morphing' feature requires an API for replacing widgets on layouts.
+ virtual void replaceWidget(QLayout *lt, QWidget *before, QWidget *after) = 0;
+
+ // Simplify a grid, remove empty columns, rows within the rectangle
+ // The DeleteWidget command restricts the area to be simplified.
+ virtual bool canSimplify(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout, const QRect &restrictionArea) const = 0;
+ virtual void simplify(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout, const QRect &restrictionArea) = 0;
+
+ // Push and pop a state. Can be used for implementing undo for
+ // simplify/row, column insertion commands, provided that
+ // the widgets remain the same.
+ virtual void pushState(const QDesignerFormEditorInterface *core, const QWidget *widgetWithManagedLayout) = 0;
+ virtual void popState(const QDesignerFormEditorInterface *core, QWidget *widgetWithManagedLayout) = 0;
+};
+
+// Base class for layout decoration extensions.
+class QDESIGNER_SHARED_EXPORT QLayoutSupport: public QObject, public QDesignerLayoutDecorationExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerLayoutDecorationExtension)
+
+protected:
+ QLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, LayoutHelper *helper, QObject *parent = 0);
+
+public:
+ virtual ~QLayoutSupport();
+
+ inline QDesignerFormWindowInterface *formWindow() const { return m_formWindow; }
+
+ // DecorationExtension V2
+ LayoutHelper* helper() const { return m_helper; }
+
+ // DecorationExtension
+ virtual int currentIndex() const { return m_currentIndex; }
+
+ virtual InsertMode currentInsertMode() const { return m_currentInsertMode; }
+
+ virtual QPair<int, int> currentCell() const { return m_currentCell; }
+
+ virtual int findItemAt(const QPoint &pos) const;
+ virtual int indexOf(QWidget *widget) const;
+ virtual int indexOf(QLayoutItem *item) const;
+
+ virtual void adjustIndicator(const QPoint &pos, int index);
+
+ virtual QList<QWidget*> widgets(QLayout *layout) const;
+
+ // Pad empty cells with dummy spacers. Called by layouting commands.
+ static void createEmptyCells(QGridLayout *gridLayout);
+ // remove dummy spacers in the area. Returns false if there are non-empty items in the way
+ static bool removeEmptyCells(QGridLayout *gridLayout, const QRect &area);
+ static void createEmptyCells(QFormLayout *formLayout); // ditto.
+ static bool removeEmptyCells(QFormLayout *formLayout, const QRect &area);
+
+ // grid helpers: find item index
+ static int findItemAt(QGridLayout *, int row, int column);
+ // grid helpers: Quick check whether simplify should be enabled for grids. May return false positives.
+ static bool canSimplifyQuickCheck(const QGridLayout *);
+ static bool canSimplifyQuickCheck(const QFormLayout *fl);
+ // Factory function, create layout support according to layout type of widget
+ static QLayoutSupport *createLayoutSupport(QDesignerFormWindowInterface *formWindow, QWidget *widget, QObject *parent = 0);
+
+protected:
+ // figure out insertion position and mode from indicator on empty cell if supported
+ virtual void setCurrentCellFromIndicatorOnEmptyCell(int index) = 0;
+ // figure out insertion position and mode from indicator
+ virtual void setCurrentCellFromIndicator(Qt::Orientation indicatorOrientation, int index, int increment) = 0;
+
+ // Overwrite to return the extended geometry of an item, that is,
+ // if it is a border item, include the widget border for the indicator to work correctly
+ virtual QRect extendedGeometry(int index) const = 0;
+ virtual bool supportsIndicatorOrientation(Qt::Orientation indicatorOrientation) const = 0;
+
+ QRect itemInfo(int index) const;
+ QLayout *layout() const;
+ QGridLayout *gridLayout() const;
+ QWidget *widget() const { return m_widget; }
+
+ void setInsertMode(InsertMode im);
+ void setCurrentCell(const QPair<int, int> &cell);
+
+private:
+ enum Indicator { LeftIndicator, TopIndicator, RightIndicator, BottomIndicator, NumIndicators };
+
+ void hideIndicator(Indicator i);
+ void showIndicator(Indicator i, const QRect &geometry, const QPalette &);
+
+ QDesignerFormWindowInterface *m_formWindow;
+ LayoutHelper* m_helper;
+
+ QPointer<QWidget> m_widget;
+ QPointer<QWidget> m_indicators[NumIndicators];
+ int m_currentIndex;
+ InsertMode m_currentInsertMode;
+ QPair<int, int> m_currentCell;
+};
+} // namespace qdesigner_internal
+
+// Red layout widget.
+class QDESIGNER_SHARED_EXPORT QLayoutWidget: public QWidget
+{
+ Q_OBJECT
+public:
+ explicit QLayoutWidget(QDesignerFormWindowInterface *formWindow, QWidget *parent = 0);
+
+ int layoutLeftMargin() const;
+ void setLayoutLeftMargin(int layoutMargin);
+
+ int layoutTopMargin() const;
+ void setLayoutTopMargin(int layoutMargin);
+
+ int layoutRightMargin() const;
+ void setLayoutRightMargin(int layoutMargin);
+
+ int layoutBottomMargin() const;
+ void setLayoutBottomMargin(int layoutMargin);
+
+ inline QDesignerFormWindowInterface *formWindow() const { return m_formWindow; }
+
+protected:
+ virtual bool event(QEvent *e);
+ virtual void paintEvent(QPaintEvent *e);
+
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+ int m_leftMargin;
+ int m_topMargin;
+ int m_rightMargin;
+ int m_bottomMargin;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_WIDGET_H
diff --git a/tools/designer/src/lib/shared/qscripthighlighter.cpp b/tools/designer/src/lib/shared/qscripthighlighter.cpp
new file mode 100644
index 0000000000..3f1d638f8c
--- /dev/null
+++ b/tools/designer/src/lib/shared/qscripthighlighter.cpp
@@ -0,0 +1,468 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscripthighlighter_p.h"
+
+#include <QtCore/QSet>
+
+QT_BEGIN_NAMESPACE
+
+static const QSet<QString> &qscriptKeywords() {
+ static QSet<QString> keywords;
+ if (keywords.empty()) {
+ keywords.insert(QLatin1String("Infinity"));
+ keywords.insert(QLatin1String("NaN"));
+ keywords.insert(QLatin1String("abstract"));
+ keywords.insert(QLatin1String("boolean"));
+ keywords.insert(QLatin1String("break"));
+ keywords.insert(QLatin1String("byte"));
+ keywords.insert(QLatin1String("case"));
+ keywords.insert(QLatin1String("catch"));
+ keywords.insert(QLatin1String("char"));
+ keywords.insert(QLatin1String("class"));
+ keywords.insert(QLatin1String("const"));
+ keywords.insert(QLatin1String("constructor"));
+ keywords.insert(QLatin1String("continue"));
+ keywords.insert(QLatin1String("debugger"));
+ keywords.insert(QLatin1String("default"));
+ keywords.insert(QLatin1String("delete"));
+ keywords.insert(QLatin1String("do"));
+ keywords.insert(QLatin1String("double"));
+ keywords.insert(QLatin1String("else"));
+ keywords.insert(QLatin1String("enum"));
+ keywords.insert(QLatin1String("export"));
+ keywords.insert(QLatin1String("extends"));
+ keywords.insert(QLatin1String("false"));
+ keywords.insert(QLatin1String("final"));
+ keywords.insert(QLatin1String("finally"));
+ keywords.insert(QLatin1String("float"));
+ keywords.insert(QLatin1String("for"));
+ keywords.insert(QLatin1String("function"));
+ keywords.insert(QLatin1String("goto"));
+ keywords.insert(QLatin1String("if"));
+ keywords.insert(QLatin1String("implements"));
+ keywords.insert(QLatin1String("import"));
+ keywords.insert(QLatin1String("in"));
+ keywords.insert(QLatin1String("instanceof"));
+ keywords.insert(QLatin1String("int"));
+ keywords.insert(QLatin1String("interface"));
+ keywords.insert(QLatin1String("long"));
+ keywords.insert(QLatin1String("native"));
+ keywords.insert(QLatin1String("new"));
+ keywords.insert(QLatin1String("package"));
+ keywords.insert(QLatin1String("private"));
+ keywords.insert(QLatin1String("protected"));
+ keywords.insert(QLatin1String("public"));
+ keywords.insert(QLatin1String("return"));
+ keywords.insert(QLatin1String("short"));
+ keywords.insert(QLatin1String("static"));
+ keywords.insert(QLatin1String("super"));
+ keywords.insert(QLatin1String("switch"));
+ keywords.insert(QLatin1String("synchronized"));
+ keywords.insert(QLatin1String("this"));
+ keywords.insert(QLatin1String("throw"));
+ keywords.insert(QLatin1String("throws"));
+ keywords.insert(QLatin1String("transient"));
+ keywords.insert(QLatin1String("true"));
+ keywords.insert(QLatin1String("try"));
+ keywords.insert(QLatin1String("typeof"));
+ keywords.insert(QLatin1String("undefined"));
+ keywords.insert(QLatin1String("var"));
+ keywords.insert(QLatin1String("void"));
+ keywords.insert(QLatin1String("volatile"));
+ keywords.insert(QLatin1String("while"));
+ keywords.insert(QLatin1String("with")); // end
+ }
+ return keywords;
+}
+
+static QSet<QChar> alphaChars() {
+ QSet<QChar> rc;
+ const QString alpha = QLatin1String("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ foreach (QChar chr, alpha)
+ rc.insert(chr);
+ return rc;
+}
+
+namespace qdesigner_internal {
+
+QScriptHighlighter::QScriptHighlighter(QTextDocument *parent)
+ : QSyntaxHighlighter(parent)
+{
+ m_numberFormat.setForeground(Qt::blue);
+ m_stringFormat.setForeground(Qt::darkGreen);
+ m_typeFormat.setForeground(Qt::darkMagenta);
+ m_keywordFormat.setForeground(Qt::darkYellow);
+ m_labelFormat.setForeground(Qt::darkRed);
+ m_commentFormat.setForeground(Qt::red);
+ //m_commentFormat.setFontFamily("times");
+ m_commentFormat.setFontItalic(true);
+ m_preProcessorFormat.setForeground(Qt::darkBlue);
+}
+
+void QScriptHighlighter::highlightBlock(const QString &text)
+{
+ // states
+ enum {
+ StateStandard,
+ StateCommentStart1,
+ StateCCommentStart2,
+ StateCppCommentStart2,
+ StateCComment,
+ StateCppComment,
+ StateCCommentEnd1,
+ StateCCommentEnd2,
+ StateStringStart,
+ StateString,
+ StateStringEnd,
+ StateString2Start,
+ StateString2,
+ StateString2End,
+ StateNumber,
+ StatePreProcessor,
+ NumStates
+ };
+ // tokens
+ enum {
+ InputAlpha,
+ InputNumber,
+ InputAsterix,
+ InputSlash,
+ InputParen,
+ InputSpace,
+ InputHash,
+ InputQuotation,
+ InputApostrophe,
+ InputSep,
+ NumInputs
+ };
+
+ static const uchar table[NumStates][NumInputs] = {
+ { StateStandard, StateNumber, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateStandard
+ { StateStandard, StateNumber, StateCCommentStart2, StateCppCommentStart2, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateCommentStart1
+ { StateCComment, StateCComment, StateCCommentEnd1, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment }, // StateCCommentStart2
+ { StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment }, // CppCommentStart2
+ { StateCComment, StateCComment, StateCCommentEnd1, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment }, // StateCComment
+ { StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment, StateCppComment }, // StateCppComment
+ { StateCComment, StateCComment, StateCCommentEnd1, StateCCommentEnd2, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment, StateCComment }, // StateCCommentEnd1
+ { StateStandard, StateNumber, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateCCommentEnd2
+ { StateString, StateString, StateString, StateString, StateString, StateString, StateString, StateStringEnd, StateString, StateString }, // StateStringStart
+ { StateString, StateString, StateString, StateString, StateString, StateString, StateString, StateStringEnd, StateString, StateString }, // StateString
+ { StateStandard, StateStandard, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateStringEnd
+ { StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2End, StateString2 }, // StateString2Start
+ { StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2, StateString2End, StateString2 }, // StateString2
+ { StateStandard, StateStandard, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateString2End
+ { StateNumber, StateNumber, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard }, // StateNumber
+ { StatePreProcessor, StateStandard, StateStandard, StateCommentStart1, StateStandard, StateStandard, StatePreProcessor, StateStringStart, StateString2Start, StateStandard } // StatePreProcessor
+ };
+
+ QString buffer;
+ buffer.reserve(text.length());
+ QTextCharFormat emptyFormat;
+
+ int state = StateStandard;
+ const int previousState = previousBlockState();
+ if (previousState != -1)
+ state = previousState;
+
+ if (text.isEmpty()) {
+ setCurrentBlockState(previousState);
+ return;
+ }
+
+ int input = -1;
+ int i = 0;
+ bool lastWasBackSlash = false;
+ bool makeLastStandard = false;
+
+ static const QSet<QChar> alphabeth = alphaChars();
+ static const QString mathChars = QString::fromLatin1("xXeE");
+ static const QString numbers = QString::fromLatin1("0123456789");
+ bool questionMark = false;
+ QChar lastChar;
+ QString firstWord;
+ forever {
+ const QChar c = text.at(i);
+
+ if (lastWasBackSlash) {
+ input = InputSep;
+ } else {
+ switch (c.toLatin1()) {
+ case '*':
+ input = InputAsterix;
+ break;
+ case '/':
+ input = InputSlash;
+ break;
+ case '(': case '[': case '{':
+ input = InputParen;
+ if (state == StateStandard
+ || state == StateNumber
+ || state == StatePreProcessor
+ || state == StateCCommentEnd2
+ || state == StateCCommentEnd1
+ || state == StateString2End
+ || state == StateStringEnd
+ )
+ //blockData->parentheses << Parenthesis(Parenthesis::Open, c, i);
+ break;
+ case ')': case ']': case '}':
+ input = InputParen;
+ if (state == StateStandard
+ || state == StateNumber
+ || state == StatePreProcessor
+ || state == StateCCommentEnd2
+ || state == StateCCommentEnd1
+ || state == StateString2End
+ || state == StateStringEnd
+ ) {
+ //blockData->parentheses << Parenthesis(Parenthesis::Closed, c, i);
+ }
+ break;
+ case '#':
+ input = InputHash;
+ break;
+ case '"':
+ input = InputQuotation;
+ break;
+ case '\'':
+ input = InputApostrophe;
+ break;
+ case ' ':
+ input = InputSpace;
+ break;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': case '0':
+ if (alphabeth.contains(lastChar)
+ && (!mathChars.contains(lastChar) || !numbers.contains(text.at(i - 1)))) {
+ input = InputAlpha;
+ } else {
+ if (input == InputAlpha && numbers.contains(lastChar))
+ input = InputAlpha;
+ else
+ input = InputNumber;
+ }
+ break;
+ case ':': {
+ input = InputAlpha;
+ QChar nextChar = QLatin1Char(' ');
+ if (i < text.length() - 1)
+ nextChar = text.at(i + 1);
+ if (state == StateStandard && !questionMark &&
+ lastChar != QLatin1Char(':') && nextChar != QLatin1Char(':')) {
+ for (int j = 0; j < i; ++j) {
+ if (format(j) == emptyFormat)
+ setFormat(j, 1, m_labelFormat);
+ }
+ }
+ break;
+ }
+ default: {
+ if (!questionMark && c == QLatin1Char('?'))
+ questionMark = true;
+ if (c.isLetter() || c == QLatin1Char('_'))
+ input = InputAlpha;
+ else
+ input = InputSep;
+ } break;
+ }
+ }
+
+ lastWasBackSlash = !lastWasBackSlash && c == QLatin1Char('\\');
+
+ if (input == InputAlpha)
+ buffer += c;
+
+ state = table[state][input];
+
+ switch (state) {
+ case StateStandard: {
+ setFormat(i, 1, emptyFormat);
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ if (!buffer.isEmpty() && input != InputAlpha ) {
+ highlightKeyword(i, buffer);
+ buffer.clear();
+ }
+ } break;
+ case StateCommentStart1:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = true;
+ buffer.resize(0);
+ break;
+ case StateCCommentStart2:
+ setFormat(i - 1, 2, m_commentFormat);
+ makeLastStandard = false;
+ buffer.resize(0);
+ break;
+ case StateCppCommentStart2:
+ setFormat(i - 1, 2, m_commentFormat);
+ makeLastStandard = false;
+ buffer.resize(0);
+ break;
+ case StateCComment:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, m_commentFormat);
+ buffer.resize(0);
+ break;
+ case StateCppComment:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, m_commentFormat);
+ buffer.resize(0);
+ break;
+ case StateCCommentEnd1:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, m_commentFormat);
+ buffer.resize(0);
+ break;
+ case StateCCommentEnd2:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, m_commentFormat);
+ buffer.resize(0);
+ break;
+ case StateStringStart:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, emptyFormat);
+ buffer.resize(0);
+ break;
+ case StateString:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, m_stringFormat);
+ buffer.resize(0);
+ break;
+ case StateStringEnd:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, emptyFormat);
+ buffer.resize(0);
+ break;
+ case StateString2Start:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, emptyFormat);
+ buffer.resize(0);
+ break;
+ case StateString2:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, m_stringFormat);
+ buffer.resize(0);
+ break;
+ case StateString2End:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, emptyFormat);
+ buffer.resize(0);
+ break;
+ case StateNumber:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat( i, 1, m_numberFormat);
+ buffer.resize(0);
+ break;
+ case StatePreProcessor:
+ if (makeLastStandard)
+ setFormat(i - 1, 1, emptyFormat);
+ makeLastStandard = false;
+ setFormat(i, 1, m_preProcessorFormat);
+ buffer.resize(0);
+ break;
+ }
+
+ lastChar = c;
+ i++;
+ if (i >= text.length())
+ break;
+ }
+
+ highlightKeyword(text.length(), buffer);
+
+ if (state == StateCComment
+ || state == StateCCommentEnd1
+ || state == StateCCommentStart2
+ ) {
+ state = StateCComment;
+ } else if (state == StateString) {
+ state = StateString;
+ } else if (state == StateString2) {
+ state = StateString2;
+ } else {
+ state = StateStandard;
+ }
+
+ setCurrentBlockState(state);
+}
+
+void QScriptHighlighter::highlightKeyword(int currentPos, const QString &buffer)
+{
+ if (buffer.isEmpty())
+ return;
+
+ if (buffer.at(0) == QLatin1Char('Q')) {
+ setFormat(currentPos - buffer.length(), buffer.length(), m_typeFormat);
+ } else {
+ if (qscriptKeywords().contains(buffer)) {
+ setFormat(currentPos - buffer.length(), buffer.length(), m_keywordFormat);
+ }
+ }
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qscripthighlighter_p.h b/tools/designer/src/lib/shared/qscripthighlighter_p.h
new file mode 100644
index 0000000000..9530ba2c7a
--- /dev/null
+++ b/tools/designer/src/lib/shared/qscripthighlighter_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QSCRIPTSYNTAXHIGHLIGHTER_H
+#define QSCRIPTSYNTAXHIGHLIGHTER_H
+
+#include <QtGui/QSyntaxHighlighter>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+class QScriptHighlighter : public QSyntaxHighlighter
+{
+public:
+ explicit QScriptHighlighter(QTextDocument *parent);
+ virtual void highlightBlock(const QString &text);
+
+private:
+ void highlightKeyword(int currentPos, const QString &buffer);
+
+ QTextCharFormat m_numberFormat;
+ QTextCharFormat m_stringFormat;
+ QTextCharFormat m_typeFormat;
+ QTextCharFormat m_keywordFormat;
+ QTextCharFormat m_labelFormat;
+ QTextCharFormat m_commentFormat;
+ QTextCharFormat m_preProcessorFormat;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/qsimpleresource.cpp b/tools/designer/src/lib/shared/qsimpleresource.cpp
new file mode 100644
index 0000000000..8d2900275a
--- /dev/null
+++ b/tools/designer/src/lib/shared/qsimpleresource.cpp
@@ -0,0 +1,283 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimpleresource_p.h"
+#include "widgetfactory_p.h"
+
+#include <formscriptrunner_p.h>
+#include <properties_p.h>
+#include <ui4_p.h>
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <script_p.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+#include <QtDesigner/extrainfo.h>
+
+#include <QtGui/QIcon>
+#include <QtGui/QWidget>
+#include <QtGui/QAction>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ typedef QList<DomWidgetData*> DomWidgetDataList;
+ typedef QList<DomProperty*> DomPropertyList;
+ typedef QList<QDesignerCustomWidgetInterface *> CustomWidgetInterfaces;
+}
+
+namespace qdesigner_internal {
+
+bool QSimpleResource::m_warningsEnabled = true;
+
+QSimpleResource::QSimpleResource(QDesignerFormEditorInterface *core) :
+ QAbstractFormBuilder(),
+ m_core(core)
+{
+ QString workingDirectory = QDir::homePath();
+ workingDirectory += QDir::separator();
+ workingDirectory += QLatin1String(".designer");
+ setWorkingDirectory(QDir(workingDirectory));
+ // Disable scripting in the editors.
+ formScriptRunner()-> setOptions(QFormScriptRunner::DisableScripts);
+}
+
+QSimpleResource::~QSimpleResource()
+{
+
+}
+
+QBrush QSimpleResource::setupBrush(DomBrush *brush)
+{
+ return QAbstractFormBuilder::setupBrush(brush);
+}
+
+DomBrush *QSimpleResource::saveBrush(const QBrush &brush)
+{
+ return QAbstractFormBuilder::saveBrush(brush);
+}
+
+QIcon QSimpleResource::nameToIcon(const QString &filePath, const QString &qrcPath)
+{
+ Q_UNUSED(filePath)
+ Q_UNUSED(qrcPath)
+ qWarning() << "QSimpleResource::nameToIcon() is obsoleted";
+ return QIcon();
+}
+
+QString QSimpleResource::iconToFilePath(const QIcon &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QSimpleResource::iconToFilePath() is obsoleted";
+ return QString();
+}
+
+QString QSimpleResource::iconToQrcPath(const QIcon &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QSimpleResource::iconToQrcPath() is obsoleted";
+ return QString();
+}
+
+QPixmap QSimpleResource::nameToPixmap(const QString &filePath, const QString &qrcPath)
+{
+ Q_UNUSED(filePath)
+ Q_UNUSED(qrcPath)
+ qWarning() << "QSimpleResource::nameToPixmap() is obsoleted";
+ return QPixmap();
+}
+
+QString QSimpleResource::pixmapToFilePath(const QPixmap &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QSimpleResource::pixmapToFilePath() is obsoleted";
+ return QString();
+}
+
+QString QSimpleResource::pixmapToQrcPath(const QPixmap &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QSimpleResource::pixmapToQrcPath() is obsoleted";
+ return QString();
+}
+
+DomScript *QSimpleResource::createScript(const QString &script, ScriptSource source)
+{
+ if (script.isEmpty())
+ return 0;
+ DomScript *domScript = new DomScript();
+ switch (source) {
+ case ScriptExtension:
+ domScript->setAttributeSource(QLatin1String("extension"));
+ break;
+ case ScriptDesigner:
+ domScript->setAttributeSource(QLatin1String("designer"));
+ break;
+ case ScriptCustomWidgetPlugin:
+ domScript->setAttributeSource(QLatin1String("customwidgetplugin"));
+ break;
+ }
+ domScript->setAttributeLanguage(QLatin1String("Qt Script"));
+ domScript->setText(script);
+ return domScript;
+}
+
+// Add a script to a list of DomScripts unless empty
+void QSimpleResource::addScript(const QString &script, ScriptSource source, DomScripts &domScripts)
+{
+ if (DomScript *domScript = createScript(script, source)) {
+ domScripts += domScript;
+ }
+}
+
+void QSimpleResource::addExtensionDataToDOM(QAbstractFormBuilder *afb,
+ QDesignerFormEditorInterface *core,
+ DomWidget *ui_widget, QWidget *widget)
+{
+ QExtensionManager *emgr = core->extensionManager();
+ if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) {
+ extra->saveWidgetExtraInfo(ui_widget);
+ }
+ if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) {
+ // Add internal state
+ const QVariantMap data = scriptExt->data();
+ if (!data.empty()) {
+ // Convert the map to a DomState.
+ // We pass on the widget for property introspection. Thus, non-designable properties
+ // that have to be converted using QMetaObject (enums and the like) will work.
+ DomPropertyList properties;
+ const QVariantMap::const_iterator vcend = data.constEnd();
+ for (QVariantMap::const_iterator it = data.constBegin(); it != vcend; ++it) {
+ if (DomProperty *prop = variantToDomProperty(afb, widget->metaObject(), it.key(), it.value()))
+ properties += prop;
+ }
+ if (!properties.empty()) {
+ DomWidgetData *domData = new DomWidgetData;
+ domData->setElementProperty(properties);
+ DomWidgetDataList domDataList;
+ domDataList += domData;
+ ui_widget->setElementWidgetData(domDataList);
+ }
+
+ }
+ // Add script
+ const QString script = scriptExt->script();
+ if (!script.isEmpty()) {
+ DomScripts domScripts = ui_widget->elementScript();
+ addScript(script, ScriptExtension, domScripts);
+ ui_widget->setElementScript(domScripts);
+ }
+ }
+}
+
+void QSimpleResource::applyExtensionDataFromDOM(QAbstractFormBuilder *afb,
+ QDesignerFormEditorInterface *core,
+ DomWidget *ui_widget, QWidget *widget, bool applyState)
+{
+ QExtensionManager *emgr = core->extensionManager();
+ if (QDesignerExtraInfoExtension *extra = qt_extension<QDesignerExtraInfoExtension*>(emgr, widget)) {
+ extra->loadWidgetExtraInfo(ui_widget);
+ }
+ if (applyState) {
+ if (QDesignerScriptExtension *scriptExt = qt_extension<QDesignerScriptExtension*>(emgr, widget)) {
+ // Apply the state.
+ // We pass on the widget for property introspection. Thus, non-designable properties
+ // that have to be converted using QMetaObject (enums and the like) will work.
+ QVariantMap data;
+ DomWidgetDataList domDataList = ui_widget->elementWidgetData();
+ if (!domDataList.empty()) {
+ foreach (const DomWidgetData *domData, domDataList) {
+ const DomPropertyList properties = domData->elementProperty();
+ foreach(const DomProperty *prop, properties) {
+ const QVariant vprop = domPropertyToVariant(afb, widget->metaObject(), prop);
+ if (vprop.type() != QVariant::Invalid)
+ data.insert(prop->attributeName(), vprop);
+ }
+ }
+ }
+ scriptExt->setData(data);
+ }
+ }
+}
+
+QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *core, QObject *object)
+{
+ return customWidgetScript(core, qdesigner_internal::WidgetFactory::classNameOf(core, object));
+}
+
+bool QSimpleResource::hasCustomWidgetScript(QDesignerFormEditorInterface *, QObject *)
+{
+ return false;
+}
+
+QString QSimpleResource::customWidgetScript(QDesignerFormEditorInterface *, const QString &)
+{
+ return QString();
+}
+
+bool QSimpleResource::setWarningsEnabled(bool warningsEnabled)
+{
+ const bool rc = m_warningsEnabled;
+ m_warningsEnabled = warningsEnabled;
+ return rc;
+}
+
+bool QSimpleResource::warningsEnabled()
+{
+ return m_warningsEnabled;
+}
+
+// ------------ FormBuilderClipboard
+
+FormBuilderClipboard::FormBuilderClipboard(QWidget *w)
+{
+ m_widgets += w;
+}
+
+bool FormBuilderClipboard::empty() const
+{
+ return m_widgets.empty() && m_actions.empty();
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/qsimpleresource_p.h b/tools/designer/src/lib/shared/qsimpleresource_p.h
new file mode 100644
index 0000000000..8d45c3c674
--- /dev/null
+++ b/tools/designer/src/lib/shared/qsimpleresource_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QSIMPLERESOURCE_H
+#define QSIMPLERESOURCE_H
+
+#include "shared_global_p.h"
+#include "abstractformbuilder.h"
+
+QT_BEGIN_NAMESPACE
+
+class DomScript;
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT QSimpleResource : public QAbstractFormBuilder
+{
+public:
+ explicit QSimpleResource(QDesignerFormEditorInterface *core);
+ virtual ~QSimpleResource();
+
+ QBrush setupBrush(DomBrush *brush);
+ DomBrush *saveBrush(const QBrush &brush);
+
+ inline QDesignerFormEditorInterface *core() const
+ { return m_core; }
+
+ // Query extensions for additional data
+ static void addExtensionDataToDOM(QAbstractFormBuilder *afb,
+ QDesignerFormEditorInterface *core,
+ DomWidget *ui_widget, QWidget *widget);
+ static void applyExtensionDataFromDOM(QAbstractFormBuilder *afb,
+ QDesignerFormEditorInterface *core,
+ DomWidget *ui_widget, QWidget *widget,
+ bool applyState);
+ // Enable warnings while saving. Turn off for backups.
+ static bool setWarningsEnabled(bool warningsEnabled);
+ static bool warningsEnabled();
+ // Return the script returned by the CustomWidget codeTemplate API
+ static QString customWidgetScript(QDesignerFormEditorInterface *core, QObject *object);
+ static QString customWidgetScript(QDesignerFormEditorInterface *core, const QString &className);
+ static bool hasCustomWidgetScript(QDesignerFormEditorInterface *core, QObject *object);
+
+protected:
+ virtual QIcon nameToIcon(const QString &filePath, const QString &qrcPath);
+ virtual QString iconToFilePath(const QIcon &pm) const;
+ virtual QString iconToQrcPath(const QIcon &pm) const;
+ virtual QPixmap nameToPixmap(const QString &filePath, const QString &qrcPath);
+ virtual QString pixmapToFilePath(const QPixmap &pm) const;
+ virtual QString pixmapToQrcPath(const QPixmap &pm) const;
+
+ enum ScriptSource { ScriptDesigner, ScriptExtension, ScriptCustomWidgetPlugin };
+ static DomScript*createScript(const QString &script, ScriptSource source);
+ typedef QList<DomScript*> DomScripts;
+ static void addScript(const QString &script, ScriptSource source, DomScripts &domScripts);
+
+private:
+ static bool m_warningsEnabled;
+ QDesignerFormEditorInterface *m_core;
+};
+
+// Contents of clipboard for formbuilder copy and paste operations
+// (Actions and widgets)
+struct QDESIGNER_SHARED_EXPORT FormBuilderClipboard {
+ typedef QList<QAction*> ActionList;
+
+ FormBuilderClipboard() {}
+ FormBuilderClipboard(QWidget *w);
+
+ bool empty() const;
+
+ QWidgetList m_widgets;
+ ActionList m_actions;
+};
+
+// Base class for a form builder used in the editor that
+// provides copy and paste.(move into base interface)
+class QDESIGNER_SHARED_EXPORT QEditorFormBuilder : public QSimpleResource
+{
+public:
+ explicit QEditorFormBuilder(QDesignerFormEditorInterface *core) : QSimpleResource(core) {}
+
+ virtual bool copy(QIODevice *dev, const FormBuilderClipboard &selection) = 0;
+ virtual DomUI *copy(const FormBuilderClipboard &selection) = 0;
+
+ // A widget parent needs to be specified, otherwise, the widget factory cannot locate the form window via parent
+ // and thus is not able to construct special widgets (QLayoutWidget).
+ virtual FormBuilderClipboard paste(DomUI *ui, QWidget *widgetParent, QObject *actionParent = 0) = 0;
+ virtual FormBuilderClipboard paste(QIODevice *dev, QWidget *widgetParent, QObject *actionParent = 0) = 0;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/qtresourceeditordialog.cpp b/tools/designer/src/lib/shared/qtresourceeditordialog.cpp
new file mode 100644
index 0000000000..adddf7229b
--- /dev/null
+++ b/tools/designer/src/lib/shared/qtresourceeditordialog.cpp
@@ -0,0 +1,2226 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractsettings_p.h"
+#include "abstractformeditor.h"
+#include "qtresourceeditordialog_p.h"
+#include "ui_qtresourceeditordialog.h"
+#include "qtresourcemodel_p.h"
+#include "iconloader_p.h"
+
+#include <abstractdialoggui_p.h>
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QCoreApplication>
+#include <QtXml/QDomDocument>
+#include <QtGui/QMenu>
+#include <QtGui/QHeaderView>
+#include <QtGui/QInputDialog>
+#include <QtGui/QMessageBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QStandardItemModel>
+
+QT_BEGIN_NAMESPACE
+
+static const char *rccRootTag = "RCC";
+static const char *rccTag = "qresource";
+static const char *rccFileTag = "file";
+static const char *rccAliasAttribute = "alias";
+static const char *rccPrefixAttribute = "prefix";
+static const char *rccLangAttribute = "lang";
+static const char *SplitterPosition = "SplitterPosition";
+static const char *Geometry = "Geometry";
+static const char *QrcDialogC = "QrcDialog";
+
+static QString msgOverwrite(const QString &fname)
+{
+ return QApplication::translate("QtResourceEditorDialog", "%1 already exists.\nDo you want to replace it?", 0, QApplication::UnicodeUTF8).arg(fname);
+}
+
+static QString msgTagMismatch(const QString &got, const QString &expected)
+{
+ return QApplication::translate("QtResourceEditorDialog", "The file does not appear to be a resource file; element '%1' was found where '%2' was expected.").arg(got).arg(expected);
+}
+
+namespace {
+
+// below 3 data classes should be derived from QSharedData and made implicit shared class
+struct QtResourceFileData {
+ QString path;
+ QString alias;
+ bool operator==(const QtResourceFileData &other) const {
+ if (path == other.path && alias == other.alias)
+ return true;
+ return false;
+ }
+};
+
+struct QtResourcePrefixData {
+ QString prefix;
+ QString language;
+ QList<QtResourceFileData> resourceFileList;
+ bool operator==(const QtResourcePrefixData &other) const {
+ if (prefix == other.prefix && language == other.language && resourceFileList == other.resourceFileList)
+ return true;
+ return false;
+ }
+};
+
+struct QtQrcFileData {
+ QString qrcPath;
+ QList<QtResourcePrefixData> resourceList;
+ bool operator==(const QtQrcFileData &other) const {
+ if (qrcPath == other.qrcPath && resourceList == other.resourceList)
+ return true;
+ return false;
+ }
+};
+
+bool loadResourceFileData(const QDomElement &fileElem, QtResourceFileData *fileData, QString *errorMessage)
+{
+ if (!fileData)
+ return false;
+
+ if (fileElem.tagName() != QLatin1String(rccFileTag)) {
+ *errorMessage = msgTagMismatch(fileElem.tagName(), QLatin1String(rccFileTag));
+ return false;
+ }
+
+ QtResourceFileData &data = *fileData;
+
+ data.path = fileElem.text();
+ data.alias = fileElem.attribute(QLatin1String(rccAliasAttribute));
+
+ return true;
+}
+
+static bool loadResourcePrefixData(const QDomElement &prefixElem, QtResourcePrefixData *prefixData, QString *errorMessage)
+{
+ if (!prefixData)
+ return false;
+
+ if (prefixElem.tagName() != QLatin1String(rccTag)) {
+ *errorMessage = msgTagMismatch(prefixElem.tagName(), QLatin1String(rccTag));
+ return false;
+ }
+
+ QtResourcePrefixData &data = *prefixData;
+
+ data.prefix = prefixElem.attribute(QLatin1String(rccPrefixAttribute));
+ data.language = prefixElem.attribute(QLatin1String(rccLangAttribute));
+ QDomElement fileElem = prefixElem.firstChildElement();
+ while (!fileElem.isNull()) {
+ QtResourceFileData fileData;
+ if (!loadResourceFileData(fileElem, &fileData, errorMessage))
+ return false;
+ data.resourceFileList.append(fileData);
+ fileElem = fileElem.nextSiblingElement();
+ }
+ return true;
+}
+
+static bool loadQrcFileData(const QDomDocument &doc, const QString &path, QtQrcFileData *qrcFileData, QString *errorMessage)
+{
+ if (!qrcFileData)
+ return false;
+
+ QtQrcFileData &data = *qrcFileData;
+
+ QDomElement docElem = doc.documentElement();
+ if (docElem.tagName() != QLatin1String(rccRootTag)) {
+ *errorMessage = msgTagMismatch(docElem.tagName(), QLatin1String(rccRootTag));
+ return false;
+ }
+
+ QDomElement prefixElem = docElem.firstChildElement();
+ while (!prefixElem.isNull()) {
+ QtResourcePrefixData prefixData;
+ if (!loadResourcePrefixData(prefixElem, &prefixData, errorMessage))
+ return false;
+ data.resourceList.append(prefixData);
+ prefixElem = prefixElem.nextSiblingElement();
+ }
+
+ data.qrcPath = path;
+
+ return true;
+}
+
+QDomElement saveResourceFileData(QDomDocument &doc, const QtResourceFileData &fileData)
+{
+ QDomElement fileElem = doc.createElement(QLatin1String(rccFileTag));
+ if (!fileData.alias.isEmpty())
+ fileElem.setAttribute(QLatin1String(rccAliasAttribute), fileData.alias);
+
+ QDomText textElem = doc.createTextNode(fileData.path);
+ fileElem.appendChild(textElem);
+
+ return fileElem;
+}
+
+QDomElement saveResourcePrefixData(QDomDocument &doc, const QtResourcePrefixData &prefixData)
+{
+ QDomElement prefixElem = doc.createElement(QLatin1String(rccTag));
+ if (!prefixData.prefix.isEmpty())
+ prefixElem.setAttribute(QLatin1String(rccPrefixAttribute), prefixData.prefix);
+ if (!prefixData.language.isEmpty())
+ prefixElem.setAttribute(QLatin1String(rccLangAttribute), prefixData.language);
+
+ QListIterator<QtResourceFileData> itFile(prefixData.resourceFileList);
+ while (itFile.hasNext()) {
+ QDomElement fileElem = saveResourceFileData(doc, itFile.next());
+ prefixElem.appendChild(fileElem);
+ }
+
+ return prefixElem;
+}
+
+QDomDocument saveQrcFileData(const QtQrcFileData &qrcFileData)
+{
+ QDomDocument doc;
+ QDomElement docElem = doc.createElement(QLatin1String(rccRootTag));
+ QListIterator<QtResourcePrefixData> itPrefix(qrcFileData.resourceList);
+ while (itPrefix.hasNext()) {
+ QDomElement prefixElem = saveResourcePrefixData(doc, itPrefix.next());
+
+ docElem.appendChild(prefixElem);
+ }
+ doc.appendChild(docElem);
+
+ return doc;
+}
+// --------------- QtResourceFile
+class QtResourceFile {
+public:
+ friend class QtQrcManager;
+
+ QString path() const { return m_path; }
+ QString alias() const { return m_alias; }
+ QString fullPath() const { return m_fullPath; }
+private:
+ QtResourceFile() {}
+
+ QString m_path;
+ QString m_alias;
+ QString m_fullPath;
+};
+
+class QtResourcePrefix {
+public:
+ friend class QtQrcManager;
+
+ QString prefix() const { return m_prefix; }
+ QString language() const { return m_language; }
+ QList<QtResourceFile *> resourceFiles() const { return m_resourceFiles; }
+private:
+ QtResourcePrefix() {}
+
+ QString m_prefix;
+ QString m_language;
+ QList<QtResourceFile *> m_resourceFiles;
+
+};
+// ------------------- QtQrcFile
+class QtQrcFile {
+public:
+ friend class QtQrcManager;
+
+ QString path() const { return m_path; }
+ QString fileName() const { return m_fileName; }
+ QList<QtResourcePrefix *> resourcePrefixList() const { return m_resourcePrefixes; }
+ QtQrcFileData initialState() const { return m_initialState; }
+
+private:
+ QtQrcFile() { }
+
+ void setPath(const QString &path) {
+ m_path = path;
+ QFileInfo fi(path);
+ m_fileName = fi.fileName();
+ }
+
+ QString m_path;
+ QString m_fileName;
+ QList<QtResourcePrefix *> m_resourcePrefixes;
+ QtQrcFileData m_initialState;
+};
+
+// ------------------ QtQrcManager
+class QtQrcManager : public QObject
+{
+ Q_OBJECT
+public:
+ QtQrcManager(QObject *parent = 0);
+ ~QtQrcManager();
+
+ QList<QtQrcFile *> qrcFiles() const;
+
+ // helpers
+ QtQrcFile *qrcFileOf(const QString &path) const;
+ QtQrcFile *qrcFileOf(QtResourcePrefix *resourcePrefix) const;
+ QtQrcFile *qrcFileOf(QtResourceFile *resourceFile) const;
+ QtResourcePrefix *resourcePrefixOf(QtResourceFile *resourceFile) const;
+
+ QtQrcFile *importQrcFile(const QtQrcFileData &qrcFileData, QtQrcFile *beforeQrcFile = 0);
+ void exportQrcFile(QtQrcFile *qrcFile, QtQrcFileData *qrcFileData) const;
+
+ QList<QtResourceFile *> resourceFilesOf(const QString &resourceFullPath) const;
+ QIcon icon(const QString &resourceFullPath) const;
+ bool exists(const QString &resourceFullPath) const;
+ bool exists(QtQrcFile *qrcFile) const;
+
+ QtQrcFile *prevQrcFile(QtQrcFile *qrcFile) const;
+ QtQrcFile *nextQrcFile(QtQrcFile *qrcFile) const;
+ QtResourcePrefix *prevResourcePrefix(QtResourcePrefix *resourcePrefix) const;
+ QtResourcePrefix *nextResourcePrefix(QtResourcePrefix *resourcePrefix) const;
+ QtResourceFile *prevResourceFile(QtResourceFile *resourceFile) const;
+ QtResourceFile *nextResourceFile(QtResourceFile *resourceFile) const;
+
+ void clear();
+
+public slots:
+
+ QtQrcFile *insertQrcFile(const QString &path, QtQrcFile *beforeQrcFile = 0, bool newFile = false);
+ void moveQrcFile(QtQrcFile *qrcFile, QtQrcFile *beforeQrcFile);
+ void setInitialState(QtQrcFile *qrcFile, const QtQrcFileData &initialState);
+ void removeQrcFile(QtQrcFile *qrcFile);
+
+ QtResourcePrefix *insertResourcePrefix(QtQrcFile *qrcFile, const QString &prefix,
+ const QString &language, QtResourcePrefix *beforeResourcePrefix = 0);
+ void moveResourcePrefix(QtResourcePrefix *resourcePrefix, QtResourcePrefix *beforeResourcePrefix); // the same qrc file???
+ void changeResourcePrefix(QtResourcePrefix *resourcePrefix, const QString &newPrefix);
+ void changeResourceLanguage(QtResourcePrefix *resourcePrefix, const QString &newLanguage);
+ void removeResourcePrefix(QtResourcePrefix *resourcePrefix);
+
+ QtResourceFile *insertResourceFile(QtResourcePrefix *resourcePrefix, const QString &path,
+ const QString &alias, QtResourceFile *beforeResourceFile = 0);
+ void moveResourceFile(QtResourceFile *resourceFile, QtResourceFile *beforeResourceFile); // the same prefix???
+ void changeResourceAlias(QtResourceFile *resourceFile, const QString &newAlias);
+ void removeResourceFile(QtResourceFile *resourceFile);
+
+signals:
+ void qrcFileInserted(QtQrcFile *qrcFile);
+ void qrcFileMoved(QtQrcFile *qrcFile, QtQrcFile *oldBeforeQrcFile);
+ void qrcFileRemoved(QtQrcFile *qrcFile);
+
+ void resourcePrefixInserted(QtResourcePrefix *resourcePrefix);
+ void resourcePrefixMoved(QtResourcePrefix *resourcePrefix, QtResourcePrefix *oldBeforeResourcePrefix);
+ void resourcePrefixChanged(QtResourcePrefix *resourcePrefix, const QString &oldPrefix);
+ void resourceLanguageChanged(QtResourcePrefix *resourcePrefix, const QString &oldLanguage);
+ void resourcePrefixRemoved(QtResourcePrefix *resourcePrefix);
+
+ void resourceFileInserted(QtResourceFile *resourceFile);
+ void resourceFileMoved(QtResourceFile *resourceFile, QtResourceFile *oldBeforeResourceFile);
+ void resourceAliasChanged(QtResourceFile *resourceFile, const QString &oldAlias);
+ void resourceFileRemoved(QtResourceFile *resourceFile);
+private:
+
+ QList<QtQrcFile *> m_qrcFiles;
+ QMap<QString, QtQrcFile *> m_pathToQrc;
+ QMap<QtQrcFile *, bool> m_qrcFileToExists;
+ QMap<QtResourcePrefix *, QtQrcFile *> m_prefixToQrc;
+ QMap<QtResourceFile *, QtResourcePrefix *> m_fileToPrefix;
+ QMap<QString, QList<QtResourceFile *> > m_fullPathToResourceFiles;
+ QMap<QString, QIcon> m_fullPathToIcon;
+ QMap<QString, bool> m_fullPathToExists;
+};
+
+QtQrcManager::QtQrcManager(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+QtQrcManager::~QtQrcManager()
+{
+ clear();
+}
+
+QList<QtQrcFile *> QtQrcManager::qrcFiles() const
+{
+ return m_qrcFiles;
+}
+
+QtQrcFile *QtQrcManager::qrcFileOf(const QString &path) const
+{
+ return m_pathToQrc.value(path);
+}
+
+QtQrcFile *QtQrcManager::qrcFileOf(QtResourcePrefix *resourcePrefix) const
+{
+ return m_prefixToQrc.value(resourcePrefix);
+}
+
+QtQrcFile *QtQrcManager::qrcFileOf(QtResourceFile *resourceFile) const
+{
+ return qrcFileOf(resourcePrefixOf(resourceFile));
+}
+
+QtResourcePrefix *QtQrcManager::resourcePrefixOf(QtResourceFile *resourceFile) const
+{
+ return m_fileToPrefix.value(resourceFile);
+}
+
+QtQrcFile *QtQrcManager::importQrcFile(const QtQrcFileData &qrcFileData, QtQrcFile *beforeQrcFile)
+{
+ QtQrcFile *qrcFile = insertQrcFile(qrcFileData.qrcPath, beforeQrcFile);
+ if (!qrcFile)
+ return 0;
+ QListIterator<QtResourcePrefixData> itPrefix(qrcFileData.resourceList);
+ while (itPrefix.hasNext()) {
+ const QtResourcePrefixData &prefixData = itPrefix.next();
+ QtResourcePrefix *resourcePrefix = insertResourcePrefix(qrcFile, prefixData.prefix, prefixData.language, 0);
+ QListIterator<QtResourceFileData> itFile(prefixData.resourceFileList);
+ while (itFile.hasNext()) {
+ const QtResourceFileData &fileData = itFile.next();
+ insertResourceFile(resourcePrefix, fileData.path, fileData.alias, 0);
+ }
+ }
+ setInitialState(qrcFile, qrcFileData);
+ return qrcFile;
+}
+
+void QtQrcManager::exportQrcFile(QtQrcFile *qrcFile, QtQrcFileData *qrcFileData) const
+{
+ if (!qrcFileData)
+ return;
+
+ if (!qrcFile)
+ return;
+
+ QtQrcFileData &data = *qrcFileData;
+
+ QList<QtResourcePrefixData> resourceList;
+
+ QList<QtResourcePrefix *> resourcePrefixes = qrcFile->resourcePrefixList();
+ QListIterator<QtResourcePrefix *> itPrefix(resourcePrefixes);
+ while (itPrefix.hasNext()) {
+ QList<QtResourceFileData> resourceFileList;
+
+ QtResourcePrefix *prefix = itPrefix.next();
+
+ QList<QtResourceFile *> resourceFiles = prefix->resourceFiles();
+ QListIterator<QtResourceFile *> itFile(resourceFiles);
+ while (itFile.hasNext()) {
+ QtResourceFile *file = itFile.next();
+ QtResourceFileData fileData;
+ fileData.path = file->path();
+ fileData.alias = file->alias();
+ resourceFileList << fileData;
+ }
+ QtResourcePrefixData prefixData;
+ prefixData.prefix = prefix->prefix();
+ prefixData.language = prefix->language();
+ prefixData.resourceFileList = resourceFileList;
+
+ resourceList << prefixData;
+ }
+ data = QtQrcFileData();
+ data.qrcPath = qrcFile->path();
+ data.resourceList = resourceList;
+}
+
+QList<QtResourceFile *> QtQrcManager::resourceFilesOf(const QString &resourcePath) const
+{
+ return m_fullPathToResourceFiles.value(resourcePath);
+}
+
+QIcon QtQrcManager::icon(const QString &resourceFullPath) const
+{
+ return m_fullPathToIcon.value(resourceFullPath);
+}
+
+bool QtQrcManager::exists(const QString &resourceFullPath) const
+{
+ return m_fullPathToExists.value(resourceFullPath, false);
+}
+
+bool QtQrcManager::exists(QtQrcFile *qrcFile) const
+{
+ return m_qrcFileToExists.value(qrcFile, false);
+}
+
+QtQrcFile *QtQrcManager::prevQrcFile(QtQrcFile *qrcFile) const
+{
+ if (!qrcFile)
+ return 0;
+ const int idx = m_qrcFiles.indexOf(qrcFile);
+ if (idx <= 0)
+ return 0;
+ return m_qrcFiles.at(idx - 1);
+}
+
+QtQrcFile *QtQrcManager::nextQrcFile(QtQrcFile *qrcFile) const
+{
+ if (!qrcFile)
+ return 0;
+ const int idx = m_qrcFiles.indexOf(qrcFile);
+ if (idx < 0 || idx == m_qrcFiles.size() - 1)
+ return 0;
+ return m_qrcFiles.at(idx + 1);
+}
+
+QtResourcePrefix *QtQrcManager::prevResourcePrefix(QtResourcePrefix *resourcePrefix) const
+{
+ if (!resourcePrefix)
+ return 0;
+ QList<QtResourcePrefix *> prefixes = qrcFileOf(resourcePrefix)->resourcePrefixList();
+ const int idx = prefixes.indexOf(resourcePrefix);
+ if (idx <= 0)
+ return 0;
+ return prefixes.at(idx - 1);
+}
+
+QtResourcePrefix *QtQrcManager::nextResourcePrefix(QtResourcePrefix *resourcePrefix) const
+{
+ if (!resourcePrefix)
+ return 0;
+ QList<QtResourcePrefix *> prefixes = qrcFileOf(resourcePrefix)->resourcePrefixList();
+ const int idx = prefixes.indexOf(resourcePrefix);
+ if (idx < 0 || idx == prefixes.size() - 1)
+ return 0;
+ return prefixes.at(idx + 1);
+}
+
+QtResourceFile *QtQrcManager::prevResourceFile(QtResourceFile *resourceFile) const
+{
+ if (!resourceFile)
+ return 0;
+ QList<QtResourceFile *> files = resourcePrefixOf(resourceFile)->resourceFiles();
+ const int idx = files.indexOf(resourceFile);
+ if (idx <= 0)
+ return 0;
+ return files.at(idx - 1);
+}
+
+QtResourceFile *QtQrcManager::nextResourceFile(QtResourceFile *resourceFile) const
+{
+ if (!resourceFile)
+ return 0;
+ QList<QtResourceFile *> files = resourcePrefixOf(resourceFile)->resourceFiles();
+ const int idx = files.indexOf(resourceFile);
+ if (idx < 0 || idx == files.size() - 1)
+ return 0;
+ return files.at(idx + 1);
+}
+
+void QtQrcManager::clear()
+{
+ QList<QtQrcFile *> oldQrcFiles = qrcFiles();
+ QListIterator<QtQrcFile *> it(oldQrcFiles);
+ while (it.hasNext())
+ removeQrcFile(it.next());
+}
+
+QtQrcFile *QtQrcManager::insertQrcFile(const QString &path, QtQrcFile *beforeQrcFile, bool newFile)
+{
+ if (m_pathToQrc.contains(path))
+ return 0;
+
+ int idx = m_qrcFiles.indexOf(beforeQrcFile);
+ if (idx < 0)
+ idx = m_qrcFiles.size();
+
+ QtQrcFile *qrcFile = new QtQrcFile();
+ qrcFile->setPath(path);
+
+ m_qrcFiles.insert(idx, qrcFile);
+ m_pathToQrc[path] = qrcFile;
+
+ const QFileInfo fi(path);
+ m_qrcFileToExists[qrcFile] = fi.exists() || newFile;
+
+ emit qrcFileInserted(qrcFile);
+ return qrcFile;
+}
+
+void QtQrcManager::moveQrcFile(QtQrcFile *qrcFile, QtQrcFile *beforeQrcFile)
+{
+ if (qrcFile == beforeQrcFile)
+ return;
+
+ const int idx = m_qrcFiles.indexOf(qrcFile);
+ if (idx < 0)
+ return;
+
+ int beforeIdx = m_qrcFiles.indexOf(beforeQrcFile);
+ if (beforeIdx < 0)
+ beforeIdx = m_qrcFiles.size();
+
+ if (idx == beforeIdx - 1) // the same position, nothing changes
+ return;
+
+ QtQrcFile *oldBefore = 0;
+ if (idx < m_qrcFiles.size() - 1)
+ oldBefore = m_qrcFiles.at(idx + 1);
+
+ m_qrcFiles.removeAt(idx);
+ if (idx < beforeIdx)
+ beforeIdx -= 1;
+
+ m_qrcFiles.insert(beforeIdx, qrcFile);
+
+ emit qrcFileMoved(qrcFile, oldBefore);
+}
+
+void QtQrcManager::setInitialState(QtQrcFile *qrcFile, const QtQrcFileData &initialState)
+{
+ qrcFile->m_initialState = initialState;
+}
+
+void QtQrcManager::removeQrcFile(QtQrcFile *qrcFile)
+{
+ const int idx = m_qrcFiles.indexOf(qrcFile);
+ if (idx < 0)
+ return;
+
+ QList<QtResourcePrefix *> resourcePrefixes = qrcFile->resourcePrefixList();
+ QListIterator<QtResourcePrefix *> it(resourcePrefixes);
+ while (it.hasNext())
+ removeResourcePrefix(it.next());
+
+ emit qrcFileRemoved(qrcFile);
+
+ m_qrcFiles.removeAt(idx);
+ m_pathToQrc.remove(qrcFile->path());
+ m_qrcFileToExists.remove(qrcFile);
+ delete qrcFile;
+}
+
+QtResourcePrefix *QtQrcManager::insertResourcePrefix(QtQrcFile *qrcFile, const QString &prefix,
+ const QString &language, QtResourcePrefix *beforeResourcePrefix)
+{
+ if (!qrcFile)
+ return 0;
+
+ int idx = qrcFile->m_resourcePrefixes.indexOf(beforeResourcePrefix);
+ if (idx < 0)
+ idx = qrcFile->m_resourcePrefixes.size();
+
+ QtResourcePrefix *resourcePrefix = new QtResourcePrefix();
+ resourcePrefix->m_prefix = prefix;
+ resourcePrefix->m_language = language;
+
+ qrcFile->m_resourcePrefixes.insert(idx, resourcePrefix);
+ m_prefixToQrc[resourcePrefix] = qrcFile;
+
+ emit resourcePrefixInserted(resourcePrefix);
+ return resourcePrefix;
+}
+
+void QtQrcManager::moveResourcePrefix(QtResourcePrefix *resourcePrefix, QtResourcePrefix *beforeResourcePrefix)
+{
+ if (resourcePrefix == beforeResourcePrefix)
+ return;
+
+ QtQrcFile *qrcFile = qrcFileOf(resourcePrefix);
+ if (!qrcFile)
+ return;
+
+ if (beforeResourcePrefix && qrcFileOf(beforeResourcePrefix) != qrcFile)
+ return;
+
+ const int idx = qrcFile->m_resourcePrefixes.indexOf(resourcePrefix);
+
+ int beforeIdx = qrcFile->m_resourcePrefixes.indexOf(beforeResourcePrefix);
+ if (beforeIdx < 0)
+ beforeIdx = qrcFile->m_resourcePrefixes.size();
+
+ if (idx == beforeIdx - 1) // the same position, nothing changes
+ return;
+
+ QtResourcePrefix *oldBefore = 0;
+ if (idx < qrcFile->m_resourcePrefixes.size() - 1)
+ oldBefore = qrcFile->m_resourcePrefixes.at(idx + 1);
+
+ qrcFile->m_resourcePrefixes.removeAt(idx);
+ if (idx < beforeIdx)
+ beforeIdx -= 1;
+
+ qrcFile->m_resourcePrefixes.insert(beforeIdx, resourcePrefix);
+
+ emit resourcePrefixMoved(resourcePrefix, oldBefore);
+}
+
+void QtQrcManager::changeResourcePrefix(QtResourcePrefix *resourcePrefix, const QString &newPrefix)
+{
+ if (!resourcePrefix)
+ return;
+
+ const QString oldPrefix = resourcePrefix->m_prefix;
+ if (oldPrefix == newPrefix)
+ return;
+
+ resourcePrefix->m_prefix = newPrefix;
+
+ emit resourcePrefixChanged(resourcePrefix, oldPrefix);
+}
+
+void QtQrcManager::changeResourceLanguage(QtResourcePrefix *resourcePrefix, const QString &newLanguage)
+{
+ if (!resourcePrefix)
+ return;
+
+ const QString oldLanguage = resourcePrefix->m_language;
+ if (oldLanguage == newLanguage)
+ return;
+
+ resourcePrefix->m_language = newLanguage;
+
+ emit resourceLanguageChanged(resourcePrefix, oldLanguage);
+}
+
+void QtQrcManager::removeResourcePrefix(QtResourcePrefix *resourcePrefix)
+{
+ QtQrcFile *qrcFile = qrcFileOf(resourcePrefix);
+ if (!qrcFile)
+ return;
+
+ const int idx = qrcFile->m_resourcePrefixes.indexOf(resourcePrefix);
+
+ QList<QtResourceFile *> resourceFiles = resourcePrefix->resourceFiles();
+ QListIterator<QtResourceFile *> it(resourceFiles);
+ while (it.hasNext())
+ removeResourceFile(it.next());
+
+ emit resourcePrefixRemoved(resourcePrefix);
+
+ qrcFile->m_resourcePrefixes.removeAt(idx);
+ m_prefixToQrc.remove(resourcePrefix);
+ delete resourcePrefix;
+}
+
+QtResourceFile *QtQrcManager::insertResourceFile(QtResourcePrefix *resourcePrefix, const QString &path,
+ const QString &alias, QtResourceFile *beforeResourceFile)
+{
+ if (!resourcePrefix)
+ return 0;
+
+ int idx = resourcePrefix->m_resourceFiles.indexOf(beforeResourceFile);
+ if (idx < 0)
+ idx = resourcePrefix->m_resourceFiles.size();
+
+ QtResourceFile *resourceFile = new QtResourceFile();
+ resourceFile->m_path = path;
+ resourceFile->m_alias = alias;
+ const QFileInfo fi(qrcFileOf(resourcePrefix)->path());
+ const QDir dir(fi.absolutePath());
+ const QString fullPath = dir.absoluteFilePath(path);
+ resourceFile->m_fullPath = fullPath;
+
+ resourcePrefix->m_resourceFiles.insert(idx, resourceFile);
+ m_fileToPrefix[resourceFile] = resourcePrefix;
+ m_fullPathToResourceFiles[fullPath].append(resourceFile);
+ if (!m_fullPathToIcon.contains(fullPath)) {
+ m_fullPathToIcon[fullPath] = QIcon(fullPath);
+ const QFileInfo fullInfo(fullPath);
+ m_fullPathToExists[fullPath] = fullInfo.exists();
+ }
+
+ emit resourceFileInserted(resourceFile);
+ return resourceFile;
+}
+
+void QtQrcManager::moveResourceFile(QtResourceFile *resourceFile, QtResourceFile *beforeResourceFile)
+{
+ if (resourceFile == beforeResourceFile)
+ return;
+
+ QtResourcePrefix *resourcePrefix = resourcePrefixOf(resourceFile);
+ if (!resourcePrefix)
+ return;
+
+ if (beforeResourceFile && resourcePrefixOf(beforeResourceFile) != resourcePrefix)
+ return;
+
+ const int idx = resourcePrefix->m_resourceFiles.indexOf(resourceFile);
+
+ int beforeIdx = resourcePrefix->m_resourceFiles.indexOf(beforeResourceFile);
+ if (beforeIdx < 0)
+ beforeIdx = resourcePrefix->m_resourceFiles.size();
+
+ if (idx == beforeIdx - 1) // the same position, nothing changes
+ return;
+
+ QtResourceFile *oldBefore = 0;
+ if (idx < resourcePrefix->m_resourceFiles.size() - 1)
+ oldBefore = resourcePrefix->m_resourceFiles.at(idx + 1);
+
+ resourcePrefix->m_resourceFiles.removeAt(idx);
+ if (idx < beforeIdx)
+ beforeIdx -= 1;
+
+ resourcePrefix->m_resourceFiles.insert(beforeIdx, resourceFile);
+
+ emit resourceFileMoved(resourceFile, oldBefore);
+}
+
+void QtQrcManager::changeResourceAlias(QtResourceFile *resourceFile, const QString &newAlias)
+{
+ if (!resourceFile)
+ return;
+
+ const QString oldAlias = resourceFile->m_alias;
+ if (oldAlias == newAlias)
+ return;
+
+ resourceFile->m_alias = newAlias;
+
+ emit resourceAliasChanged(resourceFile, oldAlias);
+}
+
+void QtQrcManager::removeResourceFile(QtResourceFile *resourceFile)
+{
+ QtResourcePrefix *resourcePrefix = resourcePrefixOf(resourceFile);
+ if (!resourcePrefix)
+ return;
+
+ const int idx = resourcePrefix->m_resourceFiles.indexOf(resourceFile);
+
+ emit resourceFileRemoved(resourceFile);
+
+ resourcePrefix->m_resourceFiles.removeAt(idx);
+ m_fileToPrefix.remove(resourceFile);
+ const QString fullPath = resourceFile->fullPath();
+ m_fullPathToResourceFiles[fullPath].removeAll(resourceFile); // optimize me
+ if (m_fullPathToResourceFiles[fullPath].isEmpty()) {
+ m_fullPathToResourceFiles.remove(fullPath);
+ m_fullPathToIcon.remove(fullPath);
+ m_fullPathToExists.remove(fullPath);
+ }
+ delete resourceFile;
+}
+
+
+
+}
+
+// ----------------- QtResourceEditorDialogPrivate
+class QtResourceEditorDialogPrivate
+{
+ QtResourceEditorDialog *q_ptr;
+ Q_DECLARE_PUBLIC(QtResourceEditorDialog)
+public:
+ QtResourceEditorDialogPrivate();
+
+ void slotQrcFileInserted(QtQrcFile *qrcFile);
+ void slotQrcFileMoved(QtQrcFile *qrcFile);
+ void slotQrcFileRemoved(QtQrcFile *qrcFile);
+
+ QStandardItem *insertResourcePrefix(QtResourcePrefix *resourcePrefix);
+
+ void slotResourcePrefixInserted(QtResourcePrefix *resourcePrefix) { insertResourcePrefix(resourcePrefix); }
+ void slotResourcePrefixMoved(QtResourcePrefix *resourcePrefix);
+ void slotResourcePrefixChanged(QtResourcePrefix *resourcePrefix);
+ void slotResourceLanguageChanged(QtResourcePrefix *resourcePrefix);
+ void slotResourcePrefixRemoved(QtResourcePrefix *resourcePrefix);
+ void slotResourceFileInserted(QtResourceFile *resourceFile);
+ void slotResourceFileMoved(QtResourceFile *resourceFile);
+ void slotResourceAliasChanged(QtResourceFile *resourceFile);
+ void slotResourceFileRemoved(QtResourceFile *resourceFile);
+
+ void slotCurrentQrcFileChanged(QListWidgetItem *item);
+ void slotCurrentTreeViewItemChanged(const QModelIndex &index);
+ void slotListWidgetContextMenuRequested(const QPoint &pos);
+ void slotTreeViewContextMenuRequested(const QPoint &pos);
+ void slotTreeViewItemChanged(QStandardItem *item);
+
+ void slotNewQrcFile();
+ void slotImportQrcFile();
+ void slotRemoveQrcFile();
+ void slotMoveUpQrcFile();
+ void slotMoveDownQrcFile();
+
+ void slotNewPrefix();
+ void slotAddFiles();
+ void slotChangePrefix();
+ void slotChangeLanguage();
+ void slotChangeAlias();
+ void slotClonePrefix();
+ void slotRemove();
+ void slotMoveUp();
+ void slotMoveDown();
+
+ bool loadQrcFile(const QString &path, QtQrcFileData *qrcFileData, QString *errorMessage);
+ bool loadQrcFile(const QString &path, QtQrcFileData *qrcFileData);
+ bool saveQrcFile(const QtQrcFileData &qrcFileData);
+
+ QString qrcFileText(QtQrcFile *qrcFile) const;
+
+ QMessageBox::StandardButton warning(const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
+ QMessageBox::StandardButton defaultButton = QMessageBox::NoButton) const;
+
+ QString browseForNewLocation(const QString &resourceFile, const QDir &rootDir) const;
+ QString copyResourceFile(const QString &resourceFile, const QString &destPath) const;
+ QtResourceFile *getCurrentResourceFile() const;
+ QtResourcePrefix *getCurrentResourcePrefix() const;
+ void selectTreeRow(QStandardItem *item);
+ QString getSaveFileNameWithExtension(QWidget *parent,
+ const QString &title, QString dir, const QString &filter, const QString &extension) const;
+ QString qrcStartDirectory() const;
+
+ Ui::QtResourceEditorDialog m_ui;
+ QDesignerFormEditorInterface *m_core;
+ QtResourceModel *m_resourceModel;
+ QDesignerDialogGuiInterface *m_dlgGui;
+ QtQrcManager *m_qrcManager;
+ QList<QtQrcFileData> m_initialState;
+
+ QMap<QtQrcFile *, QListWidgetItem *> m_qrcFileToItem;
+ QMap<QListWidgetItem *, QtQrcFile *> m_itemToQrcFile;
+ QMap<QtResourcePrefix *, QStandardItem *> m_resourcePrefixToPrefixItem;
+ QMap<QtResourcePrefix *, QStandardItem *> m_resourcePrefixToLanguageItem;
+ QMap<QStandardItem *, QtResourcePrefix *> m_prefixItemToResourcePrefix;
+ QMap<QStandardItem *, QtResourcePrefix *> m_languageItemToResourcePrefix;
+ QMap<QtResourceFile *, QStandardItem *> m_resourceFileToPathItem;
+ QMap<QtResourceFile *, QStandardItem *> m_resourceFileToAliasItem;
+ QMap<QStandardItem *, QtResourceFile *> m_pathItemToResourceFile;
+ QMap<QStandardItem *, QtResourceFile *> m_aliasItemToResourceFile;
+
+ bool m_ignoreCurrentChanged;
+ bool m_firstQrcFileDialog;
+ QtQrcFile *m_currentQrcFile;
+
+ QAction *m_newQrcFileAction;
+ QAction *m_importQrcFileAction;
+ QAction *m_removeQrcFileAction;
+ QAction *m_moveUpQrcFileAction;
+ QAction *m_moveDownQrcFileAction;
+
+ QAction *m_newPrefixAction;
+ QAction *m_addResourceFileAction;
+ QAction *m_changePrefixAction;
+ QAction *m_changeLanguageAction;
+ QAction *m_changeAliasAction;
+ QAction *m_clonePrefixAction;
+ QAction *m_moveUpAction;
+ QAction *m_moveDownAction;
+ QAction *m_removeAction;
+
+ QStandardItemModel *m_treeModel;
+ QItemSelectionModel *m_treeSelection;
+};
+
+QtResourceEditorDialogPrivate::QtResourceEditorDialogPrivate() :
+ q_ptr(0),
+ m_core(0),
+ m_resourceModel(0),
+ m_dlgGui(0),
+ m_qrcManager(0),
+ m_ignoreCurrentChanged(false),
+ m_firstQrcFileDialog(true),
+ m_currentQrcFile(0),
+ m_newQrcFileAction(0),
+ m_importQrcFileAction(0),
+ m_removeQrcFileAction(0),
+ m_moveUpQrcFileAction(0),
+ m_moveDownQrcFileAction(0),
+ m_newPrefixAction(0),
+ m_addResourceFileAction(0),
+ m_changePrefixAction(0),
+ m_changeLanguageAction(0),
+ m_changeAliasAction(0),
+ m_clonePrefixAction(0),
+ m_moveUpAction(0),
+ m_moveDownAction(0),
+ m_removeAction(0),
+ m_treeModel(0),
+ m_treeSelection(0)
+{
+}
+
+QMessageBox::StandardButton QtResourceEditorDialogPrivate::warning(const QString &title, const QString &text, QMessageBox::StandardButtons buttons,
+ QMessageBox::StandardButton defaultButton) const
+{
+ return m_dlgGui->message(q_ptr, QDesignerDialogGuiInterface::ResourceEditorMessage, QMessageBox::Warning, title, text, buttons, defaultButton);
+}
+
+QString QtResourceEditorDialogPrivate::qrcFileText(QtQrcFile *qrcFile) const
+{
+ const QString path = qrcFile->path();
+ const QString fileName = qrcFile->fileName();
+ const QFileInfo fi(path);
+ if (fi.exists() && !fi.isWritable())
+ return QApplication::translate("QtResourceEditorDialog", "%1 [read-only]").arg(fileName);
+ if (!m_qrcManager->exists(qrcFile))
+ return QApplication::translate("QtResourceEditorDialog", "%1 [missing]").arg(fileName);
+ return fileName;
+}
+
+void QtResourceEditorDialogPrivate::slotQrcFileInserted(QtQrcFile *qrcFile)
+{
+ QListWidgetItem *currentItem = m_ui.qrcFileList->currentItem();
+ int idx = m_ui.qrcFileList->count();
+ QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(qrcFile);
+ QListWidgetItem *nextItem = m_qrcFileToItem.value(nextQrcFile);
+ if (nextItem) {
+ const int row = m_ui.qrcFileList->row(nextItem);
+ if (row >= 0)
+ idx = row;
+ }
+ const QString path = qrcFile->path();
+ QListWidgetItem *item = new QListWidgetItem(qrcFileText(qrcFile));
+ item->setToolTip(path);
+ m_ignoreCurrentChanged = true;
+ m_ui.qrcFileList->insertItem(idx, item);
+ m_ui.qrcFileList->setCurrentItem(currentItem);
+ m_ignoreCurrentChanged = false;
+ m_qrcFileToItem[qrcFile] = item;
+ m_itemToQrcFile[item] = qrcFile;
+ if (!m_qrcManager->exists(qrcFile))
+ item->setForeground(QBrush(Qt::red));
+}
+
+void QtResourceEditorDialogPrivate::slotQrcFileMoved(QtQrcFile *qrcFile)
+{
+ QListWidgetItem *currentItem = m_ui.qrcFileList->currentItem();
+ QListWidgetItem *item = m_qrcFileToItem.value(qrcFile);
+ m_ignoreCurrentChanged = true;
+ m_ui.qrcFileList->takeItem(m_ui.qrcFileList->row(item));
+
+ int idx = m_ui.qrcFileList->count();
+ QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(qrcFile);
+ QListWidgetItem *nextItem = m_qrcFileToItem.value(nextQrcFile);
+ if (nextItem) {
+ int row = m_ui.qrcFileList->row(nextItem);
+ if (row >= 0)
+ idx = row;
+ }
+ m_ui.qrcFileList->insertItem(idx, item);
+ if (currentItem == item)
+ m_ui.qrcFileList->setCurrentItem(item);
+ m_ignoreCurrentChanged = false;
+}
+
+void QtResourceEditorDialogPrivate::slotQrcFileRemoved(QtQrcFile *qrcFile)
+{
+ QListWidgetItem *item = m_qrcFileToItem.value(qrcFile);
+ if (item == m_ui.qrcFileList->currentItem())
+ m_ui.qrcFileList->setCurrentItem(0); // this should trigger list view signal currentItemChanged(0), and slot should set m_currentQrcFile to 0
+ m_ignoreCurrentChanged = true;
+ delete item;
+ m_ignoreCurrentChanged = false;
+ m_itemToQrcFile.remove(item);
+ m_qrcFileToItem.remove(qrcFile);
+}
+
+QStandardItem *QtResourceEditorDialogPrivate::insertResourcePrefix(QtResourcePrefix *resourcePrefix)
+{
+ if (m_qrcManager->qrcFileOf(resourcePrefix) != m_currentQrcFile)
+ return 0;
+
+ QtResourcePrefix *prevResourcePrefix = m_qrcManager->prevResourcePrefix(resourcePrefix);
+ QStandardItem *prevItem = m_resourcePrefixToPrefixItem.value(prevResourcePrefix);
+
+ int row = 0;
+ if (prevItem)
+ row = m_treeModel->indexFromItem(prevItem).row() + 1;
+
+ QStandardItem *prefixItem = new QStandardItem();
+ QStandardItem *languageItem = new QStandardItem();
+ QList<QStandardItem *> items;
+ items << prefixItem;
+ items << languageItem;
+ m_treeModel->insertRow(row, items);
+ const QModelIndex newIndex = m_treeModel->indexFromItem(prefixItem);
+ m_ui.resourceTreeView->setExpanded(newIndex, true);
+ prefixItem->setFlags(prefixItem->flags() | Qt::ItemIsEditable);
+ languageItem->setFlags(languageItem->flags() | Qt::ItemIsEditable);
+ m_resourcePrefixToPrefixItem[resourcePrefix] = prefixItem;
+ m_resourcePrefixToLanguageItem[resourcePrefix] = languageItem;
+ m_prefixItemToResourcePrefix[prefixItem] = resourcePrefix;
+ m_languageItemToResourcePrefix[languageItem] = resourcePrefix;
+ slotResourcePrefixChanged(resourcePrefix);
+ slotResourceLanguageChanged(resourcePrefix);
+ return prefixItem;
+}
+
+void QtResourceEditorDialogPrivate::slotResourcePrefixMoved(QtResourcePrefix *resourcePrefix)
+{
+ QStandardItem *prefixItem = m_resourcePrefixToPrefixItem.value(resourcePrefix);
+ if (!prefixItem)
+ return;
+
+ QStandardItem *languageItem = m_resourcePrefixToLanguageItem.value(resourcePrefix);
+ if (!languageItem)
+ return;
+
+ const QModelIndex index = m_treeModel->indexFromItem(prefixItem);
+ const bool expanded = m_ui.resourceTreeView->isExpanded(index);
+ m_ignoreCurrentChanged = true;
+ const QList<QStandardItem *> items = m_treeModel->takeRow(index.row());
+
+ int row = m_treeModel->rowCount();
+ QtResourcePrefix *nextResourcePrefix = m_qrcManager->nextResourcePrefix(resourcePrefix);
+ QStandardItem *nextItem = m_resourcePrefixToPrefixItem.value(nextResourcePrefix);
+ if (nextItem)
+ row = m_treeModel->indexFromItem(nextItem).row();
+ m_treeModel->insertRow(row, items);
+ m_ignoreCurrentChanged = false;
+ m_ui.resourceTreeView->setExpanded(m_treeModel->indexFromItem(items.at(0)), expanded);
+}
+
+void QtResourceEditorDialogPrivate::slotResourcePrefixChanged(QtResourcePrefix *resourcePrefix)
+{
+ QStandardItem *item = m_resourcePrefixToPrefixItem.value(resourcePrefix);
+ if (!item)
+ return;
+
+ m_ignoreCurrentChanged = true;
+ QString prefix = resourcePrefix->prefix();
+ if (prefix.isEmpty())
+ prefix = QApplication::translate("QtResourceEditorDialog", "<no prefix>", 0, QApplication::UnicodeUTF8);
+ item->setText(prefix);
+ item->setToolTip(prefix);
+ m_ignoreCurrentChanged = false;
+}
+
+void QtResourceEditorDialogPrivate::slotResourceLanguageChanged(QtResourcePrefix *resourcePrefix)
+{
+ QStandardItem *item = m_resourcePrefixToLanguageItem.value(resourcePrefix);
+ if (!item)
+ return;
+
+ m_ignoreCurrentChanged = true;
+ const QString language = resourcePrefix->language();
+ item->setText(language);
+ item->setToolTip(language);
+
+ m_ignoreCurrentChanged = false;
+}
+
+void QtResourceEditorDialogPrivate::slotResourcePrefixRemoved(QtResourcePrefix *resourcePrefix)
+{
+ QStandardItem *prefixItem = m_resourcePrefixToPrefixItem.value(resourcePrefix);
+ if (!prefixItem)
+ return;
+
+ QStandardItem *languageItem = m_resourcePrefixToLanguageItem.value(resourcePrefix);
+ if (!languageItem)
+ return;
+
+ m_ignoreCurrentChanged = true;
+ m_treeModel->takeRow(m_treeModel->indexFromItem(prefixItem).row());
+ delete prefixItem;
+ delete languageItem;
+ m_ignoreCurrentChanged = false;
+ m_prefixItemToResourcePrefix.remove(prefixItem);
+ m_languageItemToResourcePrefix.remove(languageItem);
+ m_resourcePrefixToPrefixItem.remove(resourcePrefix);
+ m_resourcePrefixToLanguageItem.remove(resourcePrefix);
+}
+
+void QtResourceEditorDialogPrivate::slotResourceFileInserted(QtResourceFile *resourceFile)
+{
+ QtResourcePrefix *resourcePrefix = m_qrcManager->resourcePrefixOf(resourceFile);
+ if (m_qrcManager->qrcFileOf(resourcePrefix) != m_currentQrcFile)
+ return;
+
+ QtResourceFile *prevResourceFile = m_qrcManager->prevResourceFile(resourceFile);
+ QStandardItem *prevItem = m_resourceFileToPathItem.value(prevResourceFile);
+
+ QStandardItem *pathItem = new QStandardItem(resourceFile->path());
+ QStandardItem *aliasItem = new QStandardItem();
+ QStandardItem *parentItem = m_resourcePrefixToPrefixItem.value(resourcePrefix);
+ QList<QStandardItem *> items;
+ items << pathItem;
+ items << aliasItem;
+
+ int row = 0;
+ if (prevItem)
+ row = m_treeModel->indexFromItem(prevItem).row() + 1;
+
+ parentItem->insertRow(row, items);
+
+ pathItem->setFlags(pathItem->flags() & ~Qt::ItemIsEditable);
+ aliasItem->setFlags(aliasItem->flags() | Qt::ItemIsEditable);
+ m_resourceFileToPathItem[resourceFile] = pathItem;
+ m_resourceFileToAliasItem[resourceFile] = aliasItem;
+ m_pathItemToResourceFile[pathItem] = resourceFile;
+ m_aliasItemToResourceFile[aliasItem] = resourceFile;
+ pathItem->setToolTip(resourceFile->path());
+ pathItem->setIcon(m_qrcManager->icon(resourceFile->fullPath()));
+ if (!m_qrcManager->exists(resourceFile->fullPath())) {
+ pathItem->setText(QApplication::translate("QtResourceEditorDialog", "%1 [missing]").arg(resourceFile->path()));
+ QBrush redBrush(Qt::red);
+ pathItem->setForeground(redBrush);
+ aliasItem->setForeground(redBrush);
+ }
+ slotResourceAliasChanged(resourceFile);
+}
+
+void QtResourceEditorDialogPrivate::slotResourceFileMoved(QtResourceFile *resourceFile)
+{
+ QStandardItem *pathItem = m_resourceFileToPathItem.value(resourceFile);
+ if (!pathItem)
+ return;
+
+ QStandardItem *aliasItem = m_resourceFileToAliasItem.value(resourceFile);
+ if (!aliasItem)
+ return;
+
+ QStandardItem *parentItem = pathItem->parent();
+ m_ignoreCurrentChanged = true;
+ const QList<QStandardItem *> items = parentItem->takeRow(m_treeModel->indexFromItem(pathItem).row());
+
+ int row = parentItem->rowCount();
+ QtResourceFile *nextResourceFile = m_qrcManager->nextResourceFile(resourceFile);
+ QStandardItem *nextItem = m_resourceFileToPathItem.value(nextResourceFile);
+ if (nextItem)
+ row = m_treeModel->indexFromItem(nextItem).row();
+ parentItem->insertRow(row, items);
+ m_ignoreCurrentChanged = false;
+}
+
+void QtResourceEditorDialogPrivate::slotResourceAliasChanged(QtResourceFile *resourceFile)
+{
+ QStandardItem *item = m_resourceFileToAliasItem.value(resourceFile);
+ if (!item)
+ return;
+
+ m_ignoreCurrentChanged = true;
+ const QString alias = resourceFile->alias();
+ item->setText(alias);
+ item->setToolTip(alias);
+
+ m_ignoreCurrentChanged = false;
+}
+
+void QtResourceEditorDialogPrivate::slotResourceFileRemoved(QtResourceFile *resourceFile)
+{
+ QStandardItem *pathItem = m_resourceFileToPathItem.value(resourceFile);
+ if (!pathItem)
+ return;
+
+ QStandardItem *aliasItem = m_resourceFileToAliasItem.value(resourceFile);
+ if (!aliasItem)
+ return;
+
+ QStandardItem *parentItem = pathItem->parent();
+
+ m_ignoreCurrentChanged = true;
+ parentItem->takeRow(m_treeModel->indexFromItem(pathItem).row());
+ delete pathItem;
+ delete aliasItem;
+ m_ignoreCurrentChanged = false;
+ m_pathItemToResourceFile.remove(pathItem);
+ m_aliasItemToResourceFile.remove(aliasItem);
+ m_resourceFileToPathItem.remove(resourceFile);
+ m_resourceFileToAliasItem.remove(resourceFile);
+}
+
+
+void QtResourceEditorDialogPrivate::slotCurrentQrcFileChanged(QListWidgetItem *item)
+{
+ if (m_ignoreCurrentChanged)
+ return;
+
+ QtQrcFile *newCurrentQrcFile = m_itemToQrcFile.value(item);
+
+ if (newCurrentQrcFile == m_currentQrcFile)
+ return;
+
+ if (m_currentQrcFile) {
+ QMap<QtResourcePrefix *, QStandardItem *> currentPrefixList = m_resourcePrefixToPrefixItem;
+ QMapIterator<QtResourcePrefix *, QStandardItem *> itPrefix(currentPrefixList);
+ while (itPrefix.hasNext()) {
+ QtResourcePrefix *resourcePrefix = itPrefix.next().key();
+ QList<QtResourceFile *> currentResourceFiles = resourcePrefix->resourceFiles();
+ QListIterator<QtResourceFile *> itFile(currentResourceFiles);
+ while (itFile.hasNext())
+ slotResourceFileRemoved(itFile.next());
+ slotResourcePrefixRemoved(resourcePrefix);
+ }
+ }
+
+ m_currentQrcFile = newCurrentQrcFile;
+ slotCurrentTreeViewItemChanged(QModelIndex());
+ QStandardItem *firstPrefix = 0; // select first prefix
+ if (m_currentQrcFile) {
+ QList<QtResourcePrefix *> newPrefixList = m_currentQrcFile->resourcePrefixList();
+ QListIterator<QtResourcePrefix *> itPrefix(newPrefixList);
+ while (itPrefix.hasNext()) {
+ QtResourcePrefix *resourcePrefix = itPrefix.next();
+ if (QStandardItem *newPrefixItem = insertResourcePrefix(resourcePrefix))
+ if (!firstPrefix)
+ firstPrefix = newPrefixItem;
+ QList<QtResourceFile *> newResourceFiles = resourcePrefix->resourceFiles();
+ QListIterator<QtResourceFile *> itFile(newResourceFiles);
+ while (itFile.hasNext())
+ slotResourceFileInserted(itFile.next());
+ }
+ }
+ m_ui.resourceTreeView->setCurrentIndex(firstPrefix ? m_treeModel->indexFromItem(firstPrefix) : QModelIndex());
+
+ m_removeQrcFileAction->setEnabled(m_currentQrcFile);
+ m_moveUpQrcFileAction->setEnabled(m_currentQrcFile && m_qrcManager->prevQrcFile(m_currentQrcFile));
+ m_moveDownQrcFileAction->setEnabled(m_currentQrcFile && m_qrcManager->nextQrcFile(m_currentQrcFile));
+}
+
+void QtResourceEditorDialogPrivate::slotCurrentTreeViewItemChanged(const QModelIndex &index)
+{
+ QStandardItem *item = m_treeModel->itemFromIndex(index);
+ QtResourceFile *resourceFile = m_pathItemToResourceFile.value(item);
+ if (!resourceFile)
+ resourceFile = m_aliasItemToResourceFile.value(item);
+ QtResourcePrefix *resourcePrefix = m_prefixItemToResourcePrefix.value(item);
+ if (!resourcePrefix)
+ resourcePrefix = m_languageItemToResourcePrefix.value(item);
+
+ bool moveUpEnabled = false;
+ bool moveDownEnabled = false;
+ bool currentItem = resourceFile || resourcePrefix;
+
+ if (resourceFile) {
+ if (m_qrcManager->prevResourceFile(resourceFile))
+ moveUpEnabled = true;
+ if (m_qrcManager->nextResourceFile(resourceFile))
+ moveDownEnabled = true;
+ } else if (resourcePrefix) {
+ if (m_qrcManager->prevResourcePrefix(resourcePrefix))
+ moveUpEnabled = true;
+ if (m_qrcManager->nextResourcePrefix(resourcePrefix))
+ moveDownEnabled = true;
+ }
+
+ m_newPrefixAction->setEnabled(m_currentQrcFile);
+ m_addResourceFileAction->setEnabled(currentItem);
+ m_changePrefixAction->setEnabled(currentItem);
+ m_changeLanguageAction->setEnabled(currentItem);
+ m_changeAliasAction->setEnabled(resourceFile);
+ m_removeAction->setEnabled(currentItem);
+ m_moveUpAction->setEnabled(moveUpEnabled);
+ m_moveDownAction->setEnabled(moveDownEnabled);
+ m_clonePrefixAction->setEnabled(currentItem);
+}
+
+void QtResourceEditorDialogPrivate::slotListWidgetContextMenuRequested(const QPoint &pos)
+{
+ QMenu menu(q_ptr);
+ menu.addAction(m_newQrcFileAction);
+ menu.addAction(m_importQrcFileAction);
+ menu.addAction(m_removeQrcFileAction);
+ menu.addSeparator();
+ menu.addAction(m_moveUpQrcFileAction);
+ menu.addAction(m_moveDownQrcFileAction);
+ menu.exec(m_ui.qrcFileList->mapToGlobal(pos));
+}
+
+void QtResourceEditorDialogPrivate::slotTreeViewContextMenuRequested(const QPoint &pos)
+{
+ QMenu menu(q_ptr);
+ menu.addAction(m_newPrefixAction);
+ menu.addAction(m_addResourceFileAction);
+ menu.addAction(m_removeAction);
+ menu.addSeparator();
+ menu.addAction(m_changePrefixAction);
+ menu.addAction(m_changeLanguageAction);
+ menu.addAction(m_changeAliasAction);
+ menu.addSeparator();
+ menu.addAction(m_clonePrefixAction);
+ menu.addSeparator();
+ menu.addAction(m_moveUpAction);
+ menu.addAction(m_moveDownAction);
+ menu.exec(m_ui.resourceTreeView->mapToGlobal(pos));
+}
+
+void QtResourceEditorDialogPrivate::slotTreeViewItemChanged(QStandardItem *item)
+{
+ if (m_ignoreCurrentChanged)
+ return;
+
+ const QString newValue = item->text();
+ QtResourceFile *resourceFile = m_aliasItemToResourceFile.value(item);
+ if (resourceFile) {
+ m_qrcManager->changeResourceAlias(resourceFile, newValue);
+ return;
+ }
+
+ QtResourcePrefix *resourcePrefix = m_prefixItemToResourcePrefix.value(item);
+ if (resourcePrefix) {
+ m_qrcManager->changeResourcePrefix(resourcePrefix, newValue);
+ return;
+ }
+
+ resourcePrefix = m_languageItemToResourcePrefix.value(item);
+ if (resourcePrefix) {
+ m_qrcManager->changeResourceLanguage(resourcePrefix, newValue);
+ return;
+ }
+}
+
+QString QtResourceEditorDialogPrivate::getSaveFileNameWithExtension(QWidget *parent,
+ const QString &title, QString dir, const QString &filter, const QString &extension) const
+{
+ const QChar dot = QLatin1Char('.');
+
+ QString saveFile;
+ while (true) {
+ saveFile = m_dlgGui->getSaveFileName(parent, title, dir, filter, 0, QFileDialog::DontConfirmOverwrite);
+ if (saveFile.isEmpty())
+ return saveFile;
+
+ const QFileInfo fInfo(saveFile);
+ if (fInfo.suffix().isEmpty() && !fInfo.fileName().endsWith(dot)) {
+ saveFile += dot;
+ saveFile += extension;
+ }
+
+ const QFileInfo fi(saveFile);
+ if (!fi.exists())
+ break;
+
+ if (warning(title, msgOverwrite(fi.fileName()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
+ break;
+
+ dir = saveFile;
+ }
+ return saveFile;
+}
+
+QString QtResourceEditorDialogPrivate::qrcStartDirectory() const
+{
+ if (!m_currentQrcFile)
+ return QString();
+ const QDir dir = QFileInfo(m_currentQrcFile->path()).dir();
+ return dir.exists() ? dir.absolutePath() : QString();
+}
+
+void QtResourceEditorDialogPrivate::slotNewQrcFile()
+{
+ const QString qrcPath = getSaveFileNameWithExtension(q_ptr,
+ QApplication::translate("QtResourceEditorDialog", "New Resource File", 0, QApplication::UnicodeUTF8),
+ m_firstQrcFileDialog ? qrcStartDirectory() : QString(),
+ QApplication::translate("QtResourceEditorDialog", "Resource files (*.qrc)", 0, QApplication::UnicodeUTF8),
+ QLatin1String("qrc"));
+ if (qrcPath.isEmpty())
+ return;
+
+ m_firstQrcFileDialog = false;
+ if (QtQrcFile *sameQrcFile = m_qrcManager->qrcFileOf(qrcPath)) {
+ // QMessageBox ???
+ QListWidgetItem *item = m_qrcFileToItem.value(sameQrcFile);
+ m_ui.qrcFileList->setCurrentItem(item);
+ item->setSelected(true);
+ return;
+ }
+
+ QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(m_currentQrcFile);
+
+ QtQrcFile *qrcFile = m_qrcManager->insertQrcFile(qrcPath, nextQrcFile, true);
+ m_ui.qrcFileList->setCurrentItem(m_qrcFileToItem.value(qrcFile));
+}
+
+void QtResourceEditorDialogPrivate::slotImportQrcFile()
+{
+ const QString qrcPath = m_dlgGui->getOpenFileName(q_ptr,
+ QApplication::translate("QtResourceEditorDialog", "Import Resource File", 0, QApplication::UnicodeUTF8),
+ m_firstQrcFileDialog ? qrcStartDirectory() : QString(),
+ QApplication::translate("QtResourceEditorDialog", "Resource files (*.qrc)", 0, QApplication::UnicodeUTF8));
+ if (qrcPath.isEmpty())
+ return;
+ m_firstQrcFileDialog = false;
+ if (QtQrcFile *sameQrcFile = m_qrcManager->qrcFileOf(qrcPath)) {
+ // QMessageBox ???
+ QListWidgetItem *item = m_qrcFileToItem.value(sameQrcFile);
+ m_ui.qrcFileList->setCurrentItem(item);
+ item->setSelected(true);
+ return;
+ }
+
+ QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(m_currentQrcFile);
+
+ QtQrcFileData qrcFileData;
+ loadQrcFile(qrcPath, &qrcFileData);
+ QtQrcFile *qrcFile = m_qrcManager->importQrcFile(qrcFileData, nextQrcFile);
+ m_ui.qrcFileList->setCurrentItem(m_qrcFileToItem.value(qrcFile));
+}
+
+void QtResourceEditorDialogPrivate::slotRemoveQrcFile()
+{
+ if (!m_currentQrcFile)
+ return;
+
+ QtQrcFile *currentQrcFile = m_qrcManager->nextQrcFile(m_currentQrcFile);
+ if (!currentQrcFile)
+ currentQrcFile = m_qrcManager->prevQrcFile(m_currentQrcFile);
+
+ m_qrcManager->removeQrcFile(m_currentQrcFile);
+ QListWidgetItem *item = m_qrcFileToItem.value(currentQrcFile);
+ if (item) {
+ m_ui.qrcFileList->setCurrentItem(item);
+ item->setSelected(true);
+ }
+}
+
+void QtResourceEditorDialogPrivate::slotMoveUpQrcFile()
+{
+ if (!m_currentQrcFile)
+ return;
+
+ QtQrcFile *prevQrcFile = m_qrcManager->prevQrcFile(m_currentQrcFile);
+ if (!prevQrcFile)
+ return;
+
+ m_qrcManager->moveQrcFile(m_currentQrcFile, prevQrcFile);
+}
+
+void QtResourceEditorDialogPrivate::slotMoveDownQrcFile()
+{
+ if (!m_currentQrcFile)
+ return;
+
+ QtQrcFile *nextQrcFile = m_qrcManager->nextQrcFile(m_currentQrcFile);
+ if (!nextQrcFile)
+ return;
+ nextQrcFile = m_qrcManager->nextQrcFile(nextQrcFile);
+
+ m_qrcManager->moveQrcFile(m_currentQrcFile, nextQrcFile);
+}
+
+QtResourceFile *QtResourceEditorDialogPrivate::getCurrentResourceFile() const
+{
+ QStandardItem *currentItem = m_treeModel->itemFromIndex(m_treeSelection->currentIndex());
+
+
+ QtResourceFile *currentResourceFile = 0;
+ if (currentItem) {
+ currentResourceFile = m_pathItemToResourceFile.value(currentItem);
+ if (!currentResourceFile)
+ currentResourceFile = m_aliasItemToResourceFile.value(currentItem);
+ }
+ return currentResourceFile;
+}
+
+QtResourcePrefix *QtResourceEditorDialogPrivate::getCurrentResourcePrefix() const
+{
+ QStandardItem *currentItem = m_treeModel->itemFromIndex(m_treeSelection->currentIndex());
+
+ QtResourcePrefix *currentResourcePrefix = 0;
+ if (currentItem) {
+ currentResourcePrefix = m_prefixItemToResourcePrefix.value(currentItem);
+ if (!currentResourcePrefix) {
+ currentResourcePrefix = m_languageItemToResourcePrefix.value(currentItem);
+ if (!currentResourcePrefix) {
+ QtResourceFile *currentResourceFile = getCurrentResourceFile();
+ if (currentResourceFile)
+ currentResourcePrefix = m_qrcManager->resourcePrefixOf(currentResourceFile);
+ }
+ }
+ }
+ return currentResourcePrefix;
+}
+
+void QtResourceEditorDialogPrivate::selectTreeRow(QStandardItem *item)
+{
+ const QModelIndex index = m_treeModel->indexFromItem(item);
+ m_treeSelection->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
+ m_treeSelection->setCurrentIndex(index, QItemSelectionModel::Select);
+}
+
+void QtResourceEditorDialogPrivate::slotNewPrefix()
+{
+ if (!m_currentQrcFile)
+ return;
+
+ QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix();
+ QtResourcePrefix *nextResourcePrefix = m_qrcManager->nextResourcePrefix(currentResourcePrefix);
+ QtResourcePrefix *newResourcePrefix = m_qrcManager->insertResourcePrefix(m_currentQrcFile,
+ QApplication::translate("QtResourceEditorDialog", "newPrefix", 0, QApplication::UnicodeUTF8),
+ QString(), nextResourcePrefix);
+ if (!newResourcePrefix)
+ return;
+
+ QStandardItem *newItem = m_resourcePrefixToPrefixItem.value(newResourcePrefix);
+ if (!newItem)
+ return;
+
+ const QModelIndex index = m_treeModel->indexFromItem(newItem);
+ selectTreeRow(newItem);
+ m_ui.resourceTreeView->edit(index);
+}
+
+static inline QString outOfPathWarning(const QString &fname)
+{
+ return QApplication::translate("QtResourceEditorDialog",
+ "<p><b>Warning:</b> The file</p>"
+ "<p>%1</p>"
+ "<p>is outside of the current resource file's parent directory.</p>").arg(fname);
+}
+
+static inline QString outOfPathWarningInfo()
+{
+ return QApplication::translate("QtResourceEditorDialog",
+ "<p>To resolve the issue, press:</p>"
+ "<table>"
+ "<tr><th align=\"left\">Copy</th><td>to copy the file to the resource file's parent directory.</td></tr>"
+ "<tr><th align=\"left\">Copy As...</th><td>to copy the file into a subdirectory of the resource file's parent directory.</td></tr>"
+ "<tr><th align=\"left\">Keep</th><td>to use its current location.</td></tr></table>");
+}
+
+void QtResourceEditorDialogPrivate::slotAddFiles()
+{
+ if (!m_currentQrcFile)
+ return;
+
+ QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix();
+ QtResourceFile *currentResourceFile = getCurrentResourceFile();
+ if (!currentResourcePrefix)
+ return;
+
+ QString initialPath = m_currentQrcFile->path();
+ if (currentResourceFile) {
+ QFileInfo fi(currentResourceFile->fullPath());
+ initialPath = fi.absolutePath();
+ }
+
+ const QStringList resourcePaths = m_dlgGui->getOpenImageFileNames(q_ptr,
+ QApplication::translate("QtResourceEditorDialog", "Add Files", 0, QApplication::UnicodeUTF8),
+ initialPath);
+ if (resourcePaths.isEmpty())
+ return;
+
+ QtResourceFile *nextResourceFile = m_qrcManager->nextResourceFile(currentResourceFile);
+ if (!currentResourceFile) {
+ QList<QtResourceFile *> resourceFiles = currentResourcePrefix->resourceFiles();
+ if (resourceFiles.count() > 0)
+ nextResourceFile = resourceFiles.first();
+ }
+
+ const QFileInfo fi(m_currentQrcFile->path());
+ const QString destDir = fi.absolutePath();
+ const QDir dir(fi.absolutePath());
+ QStringListIterator itResourcePath(resourcePaths);
+ while (itResourcePath.hasNext()) {
+ QString resourcePath = itResourcePath.next();
+ QString relativePath = dir.relativeFilePath(resourcePath);
+ if (relativePath.startsWith(QLatin1String(".."))) {
+ QMessageBox msgBox(QMessageBox::Warning,
+ QApplication::translate("QtResourceEditorDialog", "Incorrect Path", 0, QApplication::UnicodeUTF8),
+ outOfPathWarning(relativePath), QMessageBox::Cancel);
+ msgBox.setInformativeText(outOfPathWarningInfo());
+ QPushButton *copyButton = msgBox.addButton(QApplication::translate("QtResourceEditorDialog",
+ "Copy", 0, QApplication::UnicodeUTF8), QMessageBox::ActionRole);
+ QPushButton *copyAsButton = msgBox.addButton(QApplication::translate("QtResourceEditorDialog",
+ "Copy As...", 0, QApplication::UnicodeUTF8), QMessageBox::ActionRole);
+ QPushButton *keepButton = msgBox.addButton(QApplication::translate("QtResourceEditorDialog",
+ "Keep", 0, QApplication::UnicodeUTF8), QMessageBox::ActionRole);
+ QPushButton *skipButton = msgBox.addButton(QApplication::translate("QtResourceEditorDialog",
+ "Skip", 0, QApplication::UnicodeUTF8), QMessageBox::ActionRole);
+ msgBox.setEscapeButton(QMessageBox::Cancel);
+ msgBox.setDefaultButton(copyButton);
+ msgBox.exec();
+ QString destPath;
+ if (msgBox.clickedButton() == keepButton) {
+ // nothing
+ } else if (msgBox.clickedButton() == copyButton) {
+ QFileInfo resInfo(resourcePath);
+ QDir dd(destDir);
+ destPath = dd.absoluteFilePath(resInfo.fileName());
+ if (dd.exists(resInfo.fileName())) {
+ if (warning(QApplication::translate("QtResourceEditorDialog", "Copy", 0, QApplication::UnicodeUTF8),
+ msgOverwrite(resInfo.fileName()),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Yes)
+ continue;
+ }
+ resourcePath = copyResourceFile(resourcePath, destPath); // returns empty string in case copy failed or was canceled
+ } else if (msgBox.clickedButton() == copyAsButton) {
+ destPath = browseForNewLocation(resourcePath, dir); // returns empty string in case browsing was canceled
+ if (destPath.isEmpty())
+ continue;
+ resourcePath = copyResourceFile(resourcePath, destPath); // returns empty string in case copy failed or was canceled
+ } else if (msgBox.clickedButton() == skipButton) { // skipped
+ continue;
+ } else { // canceled
+ return;
+ }
+ if (resourcePath.isEmpty())
+ continue;
+ }
+ relativePath = dir.relativeFilePath(resourcePath);
+ QtResourceFile *newResourceFile = m_qrcManager->insertResourceFile(currentResourcePrefix, relativePath, QString(), nextResourceFile);
+
+ QStandardItem *newItem = m_resourceFileToPathItem.value(newResourceFile);
+ if (newItem)
+ selectTreeRow(newItem);
+ }
+}
+
+void QtResourceEditorDialogPrivate::slotChangePrefix()
+{
+ QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix();
+ if (!currentResourcePrefix)
+ return;
+
+ QStandardItem *item = m_resourcePrefixToPrefixItem.value(currentResourcePrefix);
+ QModelIndex index = m_treeModel->indexFromItem(item);
+ selectTreeRow(item);
+ m_ui.resourceTreeView->scrollTo(index);
+ m_ui.resourceTreeView->edit(index);
+}
+
+void QtResourceEditorDialogPrivate::slotChangeLanguage()
+{
+ QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix();
+ if (!currentResourcePrefix)
+ return;
+
+ QStandardItem *item = m_resourcePrefixToLanguageItem.value(currentResourcePrefix);
+ QModelIndex index = m_treeModel->indexFromItem(item);
+ selectTreeRow(item);
+ m_ui.resourceTreeView->scrollTo(index);
+ m_ui.resourceTreeView->edit(index);
+}
+
+void QtResourceEditorDialogPrivate::slotChangeAlias()
+{
+ QtResourceFile *currentResourceFile = getCurrentResourceFile();
+ if (!currentResourceFile)
+ return;
+
+ QStandardItem *item = m_resourceFileToAliasItem.value(currentResourceFile);
+ QModelIndex index = m_treeModel->indexFromItem(item);
+ selectTreeRow(item);
+ m_ui.resourceTreeView->scrollTo(index);
+ m_ui.resourceTreeView->edit(index);
+}
+
+void QtResourceEditorDialogPrivate::slotClonePrefix()
+{
+ QtResourcePrefix *currentResourcePrefix = getCurrentResourcePrefix();
+ if (!currentResourcePrefix)
+ return;
+
+ bool ok;
+ QString suffix = QInputDialog::getText(q_ptr, QApplication::translate("QtResourceEditorDialog", "Clone Prefix", 0, QApplication::UnicodeUTF8),
+ QApplication::translate("QtResourceEditorDialog", "Enter the suffix which you want to add to the names of the cloned files.\n"
+ "This could for example be a language extension like \"_de\".", 0, QApplication::UnicodeUTF8),
+ QLineEdit::Normal, QString(), &ok);
+ if (!ok)
+ return;
+
+ QtResourcePrefix *newResourcePrefix = m_qrcManager->insertResourcePrefix(m_currentQrcFile, currentResourcePrefix->prefix(),
+ currentResourcePrefix->language(), m_qrcManager->nextResourcePrefix(currentResourcePrefix));
+ if (newResourcePrefix) {
+ QList<QtResourceFile *> files = currentResourcePrefix->resourceFiles();
+ QListIterator<QtResourceFile *> itFile(files);
+ while (itFile.hasNext()) {
+ QtResourceFile *resourceFile = itFile.next();
+ QString path = resourceFile->path();
+ QFileInfo fi(path);
+ QDir dir(fi.dir());
+ QString oldSuffix = fi.completeSuffix();
+ if (!oldSuffix.isEmpty())
+ oldSuffix = QLatin1Char('.') + oldSuffix;
+ const QString newBaseName = fi.baseName() + suffix + oldSuffix;
+ const QString newPath = QDir::cleanPath(dir.filePath(newBaseName));
+ m_qrcManager->insertResourceFile(newResourcePrefix, newPath,
+ resourceFile->alias());
+ }
+ }
+}
+
+void QtResourceEditorDialogPrivate::slotRemove()
+{
+ QStandardItem *item = m_treeModel->itemFromIndex(m_treeSelection->currentIndex());
+ if (!item)
+ return;
+
+ QtResourceFile *resourceFile = m_pathItemToResourceFile.value(item);
+ if (!resourceFile)
+ resourceFile = m_aliasItemToResourceFile.value(item);
+ QtResourcePrefix *resourcePrefix = m_prefixItemToResourcePrefix.value(item);
+ if (!resourcePrefix)
+ resourcePrefix = m_languageItemToResourcePrefix.value(item);
+
+ QStandardItem *newCurrentItem = 0;
+
+ if (resourceFile) {
+ QtResourceFile *nextFile = m_qrcManager->nextResourceFile(resourceFile);
+ if (!nextFile)
+ nextFile = m_qrcManager->prevResourceFile(resourceFile);
+ newCurrentItem = m_resourceFileToPathItem.value(nextFile);
+ if (!newCurrentItem)
+ newCurrentItem = m_resourcePrefixToPrefixItem.value(m_qrcManager->resourcePrefixOf(resourceFile));
+ }
+ if (!newCurrentItem) {
+ QtResourcePrefix *nextPrefix = m_qrcManager->nextResourcePrefix(resourcePrefix);
+ if (!nextPrefix)
+ nextPrefix = m_qrcManager->prevResourcePrefix(resourcePrefix);
+ newCurrentItem = m_resourcePrefixToPrefixItem.value(nextPrefix);
+ }
+
+ selectTreeRow(newCurrentItem);
+
+ if (resourcePrefix)
+ m_qrcManager->removeResourcePrefix(resourcePrefix);
+ else if (resourceFile)
+ m_qrcManager->removeResourceFile(resourceFile);
+}
+
+void QtResourceEditorDialogPrivate::slotMoveUp()
+{
+ if (QtResourceFile *resourceFile = getCurrentResourceFile()) {
+ QtResourceFile *prevFile = m_qrcManager->prevResourceFile(resourceFile);
+
+ if (!prevFile)
+ return;
+
+ m_qrcManager->moveResourceFile(resourceFile, prevFile);
+ selectTreeRow(m_resourceFileToPathItem.value(resourceFile));
+ } else if (QtResourcePrefix *resourcePrefix = getCurrentResourcePrefix()) {
+ QtResourcePrefix *prevPrefix = m_qrcManager->prevResourcePrefix(resourcePrefix);
+
+ if (!prevPrefix)
+ return;
+
+ m_qrcManager->moveResourcePrefix(resourcePrefix, prevPrefix);
+ selectTreeRow(m_resourcePrefixToPrefixItem.value(resourcePrefix));
+ }
+}
+
+void QtResourceEditorDialogPrivate::slotMoveDown()
+{
+ if (QtResourceFile *resourceFile = getCurrentResourceFile()) {
+ QtResourceFile *nextFile = m_qrcManager->nextResourceFile(resourceFile);
+
+ if (!nextFile)
+ return;
+
+ m_qrcManager->moveResourceFile(resourceFile, m_qrcManager->nextResourceFile(nextFile));
+ selectTreeRow(m_resourceFileToPathItem.value(resourceFile));
+ } else if (QtResourcePrefix *resourcePrefix = getCurrentResourcePrefix()) {
+ QtResourcePrefix *nextPrefix = m_qrcManager->nextResourcePrefix(resourcePrefix);
+
+ if (!nextPrefix)
+ return;
+
+ m_qrcManager->moveResourcePrefix(resourcePrefix, m_qrcManager->nextResourcePrefix(nextPrefix));
+ selectTreeRow(m_resourcePrefixToPrefixItem.value(resourcePrefix));
+ }
+}
+
+QString QtResourceEditorDialogPrivate::browseForNewLocation(const QString &resourceFile, const QDir &rootDir) const
+{
+ QFileInfo fi(resourceFile);
+ const QString initialPath = rootDir.absoluteFilePath(fi.fileName());
+ while (1) {
+ QString newPath = m_dlgGui->getSaveFileName(q_ptr,
+ QApplication::translate("QtResourceEditorDialog", "Copy As", 0, QApplication::UnicodeUTF8),
+ initialPath);
+ QString relativePath = rootDir.relativeFilePath(newPath);
+ if (relativePath.startsWith(QLatin1String(".."))) {
+ if (warning(QApplication::translate("QtResourceEditorDialog", "Copy As", 0, QApplication::UnicodeUTF8),
+ QApplication::translate("QtResourceEditorDialog", "<p>The selected file:</p>"
+ "<p>%1</p><p>is outside of the current resource file's directory:</p><p>%2</p>"
+ "<p>Please select another path within this directory.<p>", 0,
+ QApplication::UnicodeUTF8).arg(relativePath).arg(rootDir.absolutePath()),
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok) != QMessageBox::Ok)
+ return QString();
+ } else {
+ return newPath;
+ }
+ }
+
+ return QString();
+}
+
+QString QtResourceEditorDialogPrivate::copyResourceFile(const QString &resourceFile, const QString &destPath) const
+{
+ QFileInfo fi(destPath);
+ if (fi.exists()) {
+ while (fi.exists() && !QFile::remove(destPath)) {
+ if (warning(QApplication::translate("QtResourceEditorDialog", "Copy", 0, QApplication::UnicodeUTF8),
+ QApplication::translate("QtResourceEditorDialog", "Could not overwrite %1.", 0, QApplication::UnicodeUTF8).arg(fi.fileName()),
+ QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Retry)
+ return QString();
+ }
+ }
+ while (!QFile::copy(resourceFile, destPath)) {
+ if (warning(QApplication::translate("QtResourceEditorDialog", "Copy", 0, QApplication::UnicodeUTF8),
+ QApplication::translate("QtResourceEditorDialog", "Could not copy\n%1\nto\n%2",
+ 0, QApplication::UnicodeUTF8).arg(resourceFile).arg(destPath),
+ QMessageBox::Retry | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Retry)
+ return QString();
+ }
+ return destPath;
+}
+bool QtResourceEditorDialogPrivate::loadQrcFile(const QString &path, QtQrcFileData *qrcFileData)
+{
+ QString errorMessage;
+ const bool rc = loadQrcFile(path, qrcFileData, &errorMessage);
+// if (!rc)
+// warning(QApplication::translate("QtResourceEditorDialog", "Resource File Load Error"), errorMessage);
+ return rc;
+}
+bool QtResourceEditorDialogPrivate::loadQrcFile(const QString &path, QtQrcFileData *qrcFileData, QString *errorMessage)
+{
+ if (!qrcFileData)
+ return false;
+
+ qrcFileData->qrcPath = path;
+
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly)) {
+ // there is sufficient hint while loading a form and after opening the editor (qrc marked marked with red and with [missing] text)
+ //*errorMessage = QApplication::translate("QtResourceEditorDialog", "Unable to open %1 for reading: %2").arg(path).arg(file.errorString());
+ return false;
+ }
+
+ QByteArray dataArray = file.readAll();
+ file.close();
+
+ QDomDocument doc;
+ int errLine, errCol;
+ if (!doc.setContent(dataArray, errorMessage, &errLine, &errCol)) {
+ *errorMessage = QCoreApplication::translate("QtResourceEditorDialog", "A parse error occurred at line %1, column %2 of %3:\n%4").arg(errLine).arg(errCol).arg(path).arg(*errorMessage);
+ return false;
+ }
+
+ return loadQrcFileData(doc, path, qrcFileData, errorMessage);
+}
+
+bool QtResourceEditorDialogPrivate::saveQrcFile(const QtQrcFileData &qrcFileData)
+{
+ QFile file(qrcFileData.qrcPath);
+ while (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox msgBox(QMessageBox::Warning,
+ QApplication::translate("QtResourceEditorDialog", "Save Resource File", 0, QApplication::UnicodeUTF8),
+ QApplication::translate("QtResourceEditorDialog", "Could not write %1: %2", 0, QApplication::UnicodeUTF8).arg(qrcFileData.qrcPath).arg(file.errorString()),
+ QMessageBox::Cancel|QMessageBox::Ignore|QMessageBox::Retry);
+ msgBox.setEscapeButton(QMessageBox::Cancel);
+ msgBox.setDefaultButton(QMessageBox::Ignore);
+ switch (msgBox.exec()) {
+ case QMessageBox::Retry:
+ break; // nothing
+ case QMessageBox::Ignore:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ QDomDocument doc = saveQrcFileData(qrcFileData);
+
+ QByteArray dataArray = doc.toByteArray(2);
+ file.write(dataArray);
+
+ file.close();
+ return true;
+}
+
+QtResourceEditorDialog::QtResourceEditorDialog(QDesignerFormEditorInterface *core, QDesignerDialogGuiInterface *dlgGui, QWidget *parent)
+ : QDialog(parent)
+{
+ d_ptr = new QtResourceEditorDialogPrivate();
+ d_ptr->q_ptr = this;
+ d_ptr->m_ui.setupUi(this);
+ d_ptr->m_qrcManager = new QtQrcManager(this);
+ d_ptr->m_dlgGui = dlgGui;
+ d_ptr->m_core = core;
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setWindowTitle(tr("Edit Resources"));
+
+ connect(d_ptr->m_qrcManager, SIGNAL(qrcFileInserted(QtQrcFile *)),
+ this, SLOT(slotQrcFileInserted(QtQrcFile *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(qrcFileMoved(QtQrcFile *, QtQrcFile *)),
+ this, SLOT(slotQrcFileMoved(QtQrcFile *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(qrcFileRemoved(QtQrcFile *)),
+ this, SLOT(slotQrcFileRemoved(QtQrcFile *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourcePrefixInserted(QtResourcePrefix *)),
+ this, SLOT(slotResourcePrefixInserted(QtResourcePrefix *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourcePrefixMoved(QtResourcePrefix *, QtResourcePrefix *)),
+ this, SLOT(slotResourcePrefixMoved(QtResourcePrefix *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourcePrefixChanged(QtResourcePrefix *, const QString &)),
+ this, SLOT(slotResourcePrefixChanged(QtResourcePrefix *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourceLanguageChanged(QtResourcePrefix *, const QString &)),
+ this, SLOT(slotResourceLanguageChanged(QtResourcePrefix *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourcePrefixRemoved(QtResourcePrefix *)),
+ this, SLOT(slotResourcePrefixRemoved(QtResourcePrefix *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourceFileInserted(QtResourceFile *)),
+ this, SLOT(slotResourceFileInserted(QtResourceFile *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourceFileMoved(QtResourceFile *, QtResourceFile *)),
+ this, SLOT(slotResourceFileMoved(QtResourceFile *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourceAliasChanged(QtResourceFile *, const QString &)),
+ this, SLOT(slotResourceAliasChanged(QtResourceFile *)));
+ connect(d_ptr->m_qrcManager, SIGNAL(resourceFileRemoved(QtResourceFile *)),
+ this, SLOT(slotResourceFileRemoved(QtResourceFile *)));
+
+ QIcon upIcon = qdesigner_internal::createIconSet(QString::fromUtf8("up.png"));
+ QIcon downIcon = qdesigner_internal::createIconSet(QString::fromUtf8("down.png"));
+ QIcon minusIcon = qdesigner_internal::createIconSet(QString::fromUtf8("minus-16.png"));
+ QIcon newIcon = qdesigner_internal::createIconSet(QString::fromUtf8("filenew-16.png"));
+ QIcon openIcon = qdesigner_internal::createIconSet(QString::fromUtf8("fileopen-16.png"));
+ QIcon removeIcon = qdesigner_internal::createIconSet(QString::fromUtf8("editdelete-16.png"));
+ QIcon addPrefixIcon = qdesigner_internal::createIconSet(QString::fromUtf8("prefix-add.png"));
+
+ d_ptr->m_newQrcFileAction = new QAction(newIcon, tr("New..."), this);
+ d_ptr->m_newQrcFileAction->setToolTip(tr("New Resource File"));
+ d_ptr->m_importQrcFileAction = new QAction(openIcon, tr("Open..."), this);
+ d_ptr->m_importQrcFileAction->setToolTip(tr("Open Resource File"));
+ d_ptr->m_removeQrcFileAction = new QAction(removeIcon, tr("Remove"), this);
+ d_ptr->m_moveUpQrcFileAction = new QAction(upIcon, tr("Move Up"), this);
+ d_ptr->m_moveDownQrcFileAction = new QAction(downIcon, tr("Move Down"), this);
+
+ d_ptr->m_newPrefixAction = new QAction(addPrefixIcon, tr("Add Prefix"), this);
+ d_ptr->m_newPrefixAction->setToolTip(tr("Add Prefix"));
+ d_ptr->m_addResourceFileAction = new QAction(openIcon, tr("Add Files..."), this);
+ d_ptr->m_changePrefixAction = new QAction(tr("Change Prefix"), this);
+ d_ptr->m_changeLanguageAction = new QAction(tr("Change Language"), this);
+ d_ptr->m_changeAliasAction = new QAction(tr("Change Alias"), this);
+ d_ptr->m_clonePrefixAction = new QAction(tr("Clone Prefix..."), this);
+ d_ptr->m_removeAction = new QAction(minusIcon, tr("Remove"), this);
+ d_ptr->m_moveUpAction = new QAction(upIcon, tr("Move Up"), this);
+ d_ptr->m_moveDownAction = new QAction(downIcon, tr("Move Down"), this);
+
+ d_ptr->m_ui.newQrcButton->setDefaultAction(d_ptr->m_newQrcFileAction);
+ d_ptr->m_ui.importQrcButton->setDefaultAction(d_ptr->m_importQrcFileAction);
+ d_ptr->m_ui.removeQrcButton->setDefaultAction(d_ptr->m_removeQrcFileAction);
+
+ d_ptr->m_ui.newResourceButton->setDefaultAction(d_ptr->m_newPrefixAction);
+ d_ptr->m_ui.addResourceButton->setDefaultAction(d_ptr->m_addResourceFileAction);
+ d_ptr->m_ui.removeResourceButton->setDefaultAction(d_ptr->m_removeAction);
+
+ connect(d_ptr->m_newQrcFileAction, SIGNAL(triggered()), this, SLOT(slotNewQrcFile()));
+ connect(d_ptr->m_importQrcFileAction, SIGNAL(triggered()), this, SLOT(slotImportQrcFile()));
+ connect(d_ptr->m_removeQrcFileAction, SIGNAL(triggered()), this, SLOT(slotRemoveQrcFile()));
+ connect(d_ptr->m_moveUpQrcFileAction, SIGNAL(triggered()), this, SLOT(slotMoveUpQrcFile()));
+ connect(d_ptr->m_moveDownQrcFileAction, SIGNAL(triggered()), this, SLOT(slotMoveDownQrcFile()));
+
+ connect(d_ptr->m_newPrefixAction, SIGNAL(triggered()), this, SLOT(slotNewPrefix()));
+ connect(d_ptr->m_addResourceFileAction, SIGNAL(triggered()), this, SLOT(slotAddFiles()));
+ connect(d_ptr->m_changePrefixAction, SIGNAL(triggered()), this, SLOT(slotChangePrefix()));
+ connect(d_ptr->m_changeLanguageAction, SIGNAL(triggered()), this, SLOT(slotChangeLanguage()));
+ connect(d_ptr->m_changeAliasAction, SIGNAL(triggered()), this, SLOT(slotChangeAlias()));
+ connect(d_ptr->m_clonePrefixAction, SIGNAL(triggered()), this, SLOT(slotClonePrefix()));
+ connect(d_ptr->m_removeAction, SIGNAL(triggered()), this, SLOT(slotRemove()));
+ connect(d_ptr->m_moveUpAction, SIGNAL(triggered()), this, SLOT(slotMoveUp()));
+ connect(d_ptr->m_moveDownAction, SIGNAL(triggered()), this, SLOT(slotMoveDown()));
+
+ d_ptr->m_ui.qrcFileList->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(d_ptr->m_ui.qrcFileList, SIGNAL(customContextMenuRequested(const QPoint &)),
+ this, SLOT(slotListWidgetContextMenuRequested(const QPoint &)));
+ connect(d_ptr->m_ui.qrcFileList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+ this, SLOT(slotCurrentQrcFileChanged(QListWidgetItem *)));
+
+ d_ptr->m_treeModel = new QStandardItemModel(this);
+ d_ptr->m_treeModel->setColumnCount(2);
+ d_ptr->m_treeModel->setHorizontalHeaderItem(0, new QStandardItem(tr("Prefix / Path")));
+ d_ptr->m_treeModel->setHorizontalHeaderItem(1, new QStandardItem(tr("Language / Alias")));
+ d_ptr->m_ui.resourceTreeView->setModel(d_ptr->m_treeModel);
+ d_ptr->m_ui.resourceTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
+ d_ptr->m_treeSelection = d_ptr->m_ui.resourceTreeView->selectionModel();
+ connect(d_ptr->m_ui.resourceTreeView->header(), SIGNAL(sectionDoubleClicked(int)), d_ptr->m_ui.resourceTreeView, SLOT(resizeColumnToContents(int)));
+ d_ptr->m_ui.resourceTreeView->setTextElideMode(Qt::ElideLeft);
+
+ connect(d_ptr->m_ui.resourceTreeView, SIGNAL(customContextMenuRequested(const QPoint &)),
+ this, SLOT(slotTreeViewContextMenuRequested(const QPoint &)));
+ connect(d_ptr->m_treeModel, SIGNAL(itemChanged(QStandardItem *)),
+ this, SLOT(slotTreeViewItemChanged(QStandardItem *)));
+ connect(d_ptr->m_treeSelection, SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
+ this, SLOT(slotCurrentTreeViewItemChanged(const QModelIndex &)));
+
+ d_ptr->m_ui.resourceTreeView->setColumnWidth(0, 200);
+
+ d_ptr->slotCurrentTreeViewItemChanged(QModelIndex());
+ d_ptr->m_removeQrcFileAction->setEnabled(false);
+ d_ptr->m_moveUpQrcFileAction->setEnabled(false);
+ d_ptr->m_moveDownQrcFileAction->setEnabled(false);
+
+ QDesignerSettingsInterface *settings = core->settingsManager();
+ settings->beginGroup(QLatin1String(QrcDialogC));
+
+ d_ptr->m_ui.splitter->restoreState(settings->value(QLatin1String(SplitterPosition)).toByteArray());
+ if (settings->contains(QLatin1String(Geometry)))
+ setGeometry(settings->value(QLatin1String(Geometry)).toRect());
+
+ settings->endGroup();
+}
+
+QtResourceEditorDialog::~QtResourceEditorDialog()
+{
+ QDesignerSettingsInterface *settings = d_ptr->m_core->settingsManager();
+ settings->beginGroup(QLatin1String(QrcDialogC));
+
+ settings->setValue(QLatin1String(SplitterPosition), d_ptr->m_ui.splitter->saveState());
+ settings->setValue(QLatin1String(Geometry), geometry());
+ settings->endGroup();
+
+ delete d_ptr;
+}
+
+QtResourceModel *QtResourceEditorDialog::model() const
+{
+ return d_ptr->m_resourceModel;
+}
+
+void QtResourceEditorDialog::setResourceModel(QtResourceModel *model)
+{
+ d_ptr->m_resourceModel = model;
+
+ QtResourceSet *resourceSet = d_ptr->m_resourceModel->currentResourceSet();
+ if (!resourceSet) {
+ // disable everything but cancel button
+ return;
+ }
+
+ d_ptr->m_initialState.clear();
+
+ // enable qrcBox
+
+ QStringList paths = resourceSet->activeQrcPaths();
+ QStringListIterator it(paths);
+ while (it.hasNext()) {
+ const QString path = it.next();
+ QtQrcFileData qrcFileData;
+ d_ptr->loadQrcFile(path, &qrcFileData);
+ d_ptr->m_initialState << qrcFileData;
+ d_ptr->m_qrcManager->importQrcFile(qrcFileData);
+ }
+ if (d_ptr->m_ui.qrcFileList->count() > 0) {
+ d_ptr->m_ui.qrcFileList->item(0)->setSelected(true);
+ }
+}
+
+QString QtResourceEditorDialog::selectedResource() const
+{
+ //QtResourcePrefix *currentResourcePrefix = d_ptr->m_qrcManager->resourcePrefixOf(currentResourceFile);
+ QtResourcePrefix *currentResourcePrefix = d_ptr->getCurrentResourcePrefix();
+ if (!currentResourcePrefix)
+ return QString();
+
+ const QChar slash(QLatin1Char('/'));
+ QString resource = currentResourcePrefix->prefix();
+ if (!resource.startsWith(slash))
+ resource.prepend(slash);
+ if (!resource.endsWith(slash))
+ resource.append(slash);
+ resource.prepend(QLatin1Char(':'));
+
+ QtResourceFile *currentResourceFile = d_ptr->getCurrentResourceFile();
+ if (!currentResourceFile)
+ return resource;
+
+ QString resourceEnding = currentResourceFile->path();
+ if (!currentResourceFile->alias().isEmpty())
+ resourceEnding = currentResourceFile->alias();
+
+ const QString dotSlash(QLatin1String("./"));
+ const QString dotDotSlash(QLatin1String("../"));
+ while (1) {
+ if (resourceEnding.startsWith(slash))
+ resourceEnding = resourceEnding.mid(1);
+ else if (resourceEnding.startsWith(dotSlash))
+ resourceEnding = resourceEnding.mid(dotSlash.count());
+ else if (resourceEnding.startsWith(dotDotSlash))
+ resourceEnding = resourceEnding.mid(dotDotSlash.count());
+ else
+ break;
+ }
+
+ resource.append(resourceEnding);
+
+ return resource;
+}
+
+void QtResourceEditorDialog::displayResourceFailures(const QString &logOutput, QDesignerDialogGuiInterface *dlgGui, QWidget *parent)
+{
+ const QString msg = tr("<html><p><b>Warning:</b> There have been problems while reloading the resources:</p><pre>%1</pre></html>").arg(logOutput);
+ dlgGui->message(parent, QDesignerDialogGuiInterface::ResourceEditorMessage, QMessageBox::Warning,
+ tr("Resource Warning"), msg);
+}
+
+void QtResourceEditorDialog::accept()
+{
+ QStringList newQrcPaths;
+ QList<QtQrcFileData> currentState;
+
+ QList<QtQrcFile *> qrcFiles = d_ptr->m_qrcManager->qrcFiles();
+ QListIterator<QtQrcFile *> itQrc(qrcFiles);
+ while (itQrc.hasNext()) {
+ QtQrcFile *qrcFile = itQrc.next();
+ QtQrcFileData qrcFileData;
+ d_ptr->m_qrcManager->exportQrcFile(qrcFile, &qrcFileData);
+ currentState << qrcFileData;
+ if (qrcFileData == qrcFile->initialState()) {
+ // nothing
+ } else {
+ d_ptr->m_resourceModel->setWatcherEnabled(qrcFileData.qrcPath, false);
+ bool ok = d_ptr->saveQrcFile(qrcFileData);
+ d_ptr->m_resourceModel->setWatcherEnabled(qrcFileData.qrcPath, true);
+ if (!ok)
+ return;
+
+ d_ptr->m_resourceModel->setModified(qrcFileData.qrcPath);
+ }
+ newQrcPaths << qrcFileData.qrcPath;
+ }
+
+ if (currentState == d_ptr->m_initialState) {
+ // nothing
+ } else {
+ int errorCount;
+ QString errorMessages;
+ d_ptr->m_resourceModel->currentResourceSet()->activateQrcPaths(newQrcPaths, &errorCount, &errorMessages);
+ if (errorCount)
+ displayResourceFailures(errorMessages, d_ptr->m_dlgGui, this);
+ }
+ QDialog::accept();
+}
+
+QString QtResourceEditorDialog::editResources(QDesignerFormEditorInterface *core,
+ QtResourceModel *model,
+ QDesignerDialogGuiInterface *dlgGui,
+ QWidget *parent)
+{
+ QtResourceEditorDialog dialog(core, dlgGui, parent);
+ dialog.setResourceModel(model);
+ if (dialog.exec() == QDialog::Accepted)
+ return dialog.selectedResource();
+ return QString();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtresourceeditordialog_p.cpp"
+#include "qtresourceeditordialog.moc"
diff --git a/tools/designer/src/lib/shared/qtresourceeditordialog.ui b/tools/designer/src/lib/shared/qtresourceeditordialog.ui
new file mode 100644
index 0000000000..fa760d9a1c
--- /dev/null
+++ b/tools/designer/src/lib/shared/qtresourceeditordialog.ui
@@ -0,0 +1,177 @@
+<ui version="4.0" >
+ <class>QtResourceEditorDialog</class>
+ <widget class="QDialog" name="QtResourceEditorDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>469</width>
+ <height>317</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <widget class="QSplitter" name="splitter" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="childrenCollapsible" >
+ <bool>false</bool>
+ </property>
+ <widget class="QWidget" name="qrcLayoutWidget" >
+ <layout class="QGridLayout" name="qrcLayout" >
+ <item row="0" column="0" colspan="4" >
+ <widget class="QListWidget" name="qrcFileList" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QToolButton" name="newQrcButton" >
+ <property name="toolTip" >
+ <string>New File</string>
+ </property>
+ <property name="text" >
+ <string>N</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QToolButton" name="removeQrcButton" >
+ <property name="toolTip" >
+ <string>Remove File</string>
+ </property>
+ <property name="text" >
+ <string>R</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType" >
+ <enum>QSizePolicy::Ignored</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QToolButton" name="importQrcButton" >
+ <property name="text" >
+ <string>I</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="resourceLayoutWidget" >
+ <layout class="QGridLayout" name="resourceLayout" >
+ <item row="0" column="0" colspan="4" >
+ <widget class="QTreeView" name="resourceTreeView" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QToolButton" name="newResourceButton" >
+ <property name="toolTip" >
+ <string>New Resource</string>
+ </property>
+ <property name="text" >
+ <string>N</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QToolButton" name="addResourceButton" >
+ <property name="text" >
+ <string>A</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QToolButton" name="removeResourceButton" >
+ <property name="toolTip" >
+ <string>Remove Resource or File</string>
+ </property>
+ <property name="text" >
+ <string>R</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3" >
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>QtResourceEditorDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>QtResourceEditorDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/qtresourceeditordialog_p.h b/tools/designer/src/lib/shared/qtresourceeditordialog_p.h
new file mode 100644
index 0000000000..f2531d9f13
--- /dev/null
+++ b/tools/designer/src/lib/shared/qtresourceeditordialog_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QTRESOURCEEDITOR_H
+#define QTRESOURCEEDITOR_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QtResourceModel;
+class QDesignerDialogGuiInterface;
+class QDesignerFormEditorInterface;
+
+class QtResourceEditorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QtResourceModel *model() const;
+ void setResourceModel(QtResourceModel *model);
+
+ QString selectedResource() const;
+
+ static QString editResources(QDesignerFormEditorInterface *core, QtResourceModel *model,
+ QDesignerDialogGuiInterface *dlgGui, QWidget *parent = 0);
+
+ // Helper to display a message box with rcc logs in case of errors.
+ static void displayResourceFailures(const QString &logOutput, QDesignerDialogGuiInterface *dlgGui, QWidget *parent = 0);
+
+public slots:
+ virtual void accept();
+
+private:
+ QtResourceEditorDialog(QDesignerFormEditorInterface *core, QDesignerDialogGuiInterface *dlgGui, QWidget *parent = 0);
+ ~QtResourceEditorDialog();
+
+ class QtResourceEditorDialogPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtResourceEditorDialog)
+ Q_DISABLE_COPY(QtResourceEditorDialog)
+
+ Q_PRIVATE_SLOT(d_func(), void slotQrcFileInserted(QtQrcFile *))
+ Q_PRIVATE_SLOT(d_func(), void slotQrcFileMoved(QtQrcFile *))
+ Q_PRIVATE_SLOT(d_func(), void slotQrcFileRemoved(QtQrcFile *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourcePrefixInserted(QtResourcePrefix *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourcePrefixMoved(QtResourcePrefix *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourcePrefixChanged(QtResourcePrefix *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourceLanguageChanged(QtResourcePrefix *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourcePrefixRemoved(QtResourcePrefix *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourceFileInserted(QtResourceFile *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourceFileMoved(QtResourceFile *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourceAliasChanged(QtResourceFile *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourceFileRemoved(QtResourceFile *))
+
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentQrcFileChanged(QListWidgetItem *))
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentTreeViewItemChanged(const QModelIndex &))
+ Q_PRIVATE_SLOT(d_func(), void slotListWidgetContextMenuRequested(const QPoint &))
+ Q_PRIVATE_SLOT(d_func(), void slotTreeViewContextMenuRequested(const QPoint &))
+ Q_PRIVATE_SLOT(d_func(), void slotTreeViewItemChanged(QStandardItem *))
+
+ Q_PRIVATE_SLOT(d_func(), void slotNewQrcFile())
+ Q_PRIVATE_SLOT(d_func(), void slotImportQrcFile())
+ Q_PRIVATE_SLOT(d_func(), void slotRemoveQrcFile())
+ Q_PRIVATE_SLOT(d_func(), void slotMoveUpQrcFile())
+ Q_PRIVATE_SLOT(d_func(), void slotMoveDownQrcFile())
+
+ Q_PRIVATE_SLOT(d_func(), void slotNewPrefix())
+ Q_PRIVATE_SLOT(d_func(), void slotAddFiles())
+ Q_PRIVATE_SLOT(d_func(), void slotChangePrefix())
+ Q_PRIVATE_SLOT(d_func(), void slotChangeLanguage())
+ Q_PRIVATE_SLOT(d_func(), void slotChangeAlias())
+ Q_PRIVATE_SLOT(d_func(), void slotClonePrefix())
+ Q_PRIVATE_SLOT(d_func(), void slotRemove())
+ Q_PRIVATE_SLOT(d_func(), void slotMoveUp())
+ Q_PRIVATE_SLOT(d_func(), void slotMoveDown())
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/tools/designer/src/lib/shared/qtresourcemodel.cpp b/tools/designer/src/lib/shared/qtresourcemodel.cpp
new file mode 100644
index 0000000000..e6152beb18
--- /dev/null
+++ b/tools/designer/src/lib/shared/qtresourcemodel.cpp
@@ -0,0 +1,648 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtresourcemodel_p.h"
+#include <rcc.h>
+
+#include <QtCore/QStringList>
+#include <QtCore/QMap>
+#include <QtCore/QResource>
+#include <QtCore/QFileInfo>
+#include <QtCore/QIODevice>
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QBuffer>
+#include <QtCore/QFileSystemWatcher>
+
+QT_BEGIN_NAMESPACE
+
+enum { debugResourceModel = 0 };
+
+// ------------------- QtResourceSetPrivate
+class QtResourceSetPrivate
+{
+ QtResourceSet *q_ptr;
+ Q_DECLARE_PUBLIC(QtResourceSet)
+public:
+ QtResourceSetPrivate(QtResourceModel *model = 0);
+
+ QtResourceModel *m_resourceModel;
+};
+
+QtResourceSetPrivate::QtResourceSetPrivate(QtResourceModel *model) :
+ q_ptr(0),
+ m_resourceModel(model)
+{
+}
+
+// -------------------- QtResourceModelPrivate
+class QtResourceModelPrivate
+{
+ QtResourceModel *q_ptr;
+ Q_DECLARE_PUBLIC(QtResourceModel)
+ Q_DISABLE_COPY(QtResourceModelPrivate)
+public:
+ QtResourceModelPrivate();
+ void activate(QtResourceSet *resourceSet, const QStringList &newPaths, int *errorCount = 0, QString *errorMessages = 0);
+ void removeOldPaths(QtResourceSet *resourceSet, const QStringList &newPaths);
+
+ QMap<QString, bool> m_pathToModified;
+ QMap<QtResourceSet *, QStringList> m_resourceSetToPaths;
+ QMap<QtResourceSet *, bool> m_resourceSetToReload; // while path is recreated it needs to be reregistered
+ // (it is - in the new current resource set, but when the path was used in
+ // other resource set
+ // then later when that resource set is activated it needs to be reregistered)
+ QMap<QtResourceSet *, bool> m_newlyCreated; // all created but not activated yet
+ // (if was active at some point and it's not now it will not be on that map)
+ QMap<QString, QList<QtResourceSet *> > m_pathToResourceSet;
+ QtResourceSet *m_currentResourceSet;
+
+ typedef QMap<QString, const QByteArray *> PathDataMap;
+ PathDataMap m_pathToData;
+
+ QMap<QString, QStringList> m_pathToContents; // qrc path to its contents.
+ QMap<QString, QString> m_fileToQrc; // this map contains the content of active resource set only.
+ // Activating different resource set changes the contents.
+
+ QFileSystemWatcher *m_fileWatcher;
+ bool m_fileWatcherEnabled;
+ QMap<QString, bool> m_fileWatchedMap;
+private:
+ void registerResourceSet(QtResourceSet *resourceSet);
+ void unregisterResourceSet(QtResourceSet *resourceSet);
+ void setWatcherEnabled(const QString &path, bool enable);
+ void addWatcher(const QString &path);
+ void removeWatcher(const QString &path);
+
+ void slotFileChanged(const QString &);
+
+ const QByteArray *createResource(const QString &path, QStringList *contents, int *errorCount, QIODevice &errorDevice) const;
+ void deleteResource(const QByteArray *data) const;
+};
+
+QtResourceModelPrivate::QtResourceModelPrivate() :
+ q_ptr(0),
+ m_currentResourceSet(0),
+ m_fileWatcher(0),
+ m_fileWatcherEnabled(true)
+{
+}
+
+// --------------------- QtResourceSet
+QtResourceSet::QtResourceSet() :
+ d_ptr(new QtResourceSetPrivate)
+{
+ d_ptr->q_ptr = this;
+}
+
+QtResourceSet::QtResourceSet(QtResourceModel *model) :
+ d_ptr(new QtResourceSetPrivate(model))
+{
+ d_ptr->q_ptr = this;
+}
+
+QtResourceSet::~QtResourceSet()
+{
+ delete d_ptr;
+}
+
+QStringList QtResourceSet::activeQrcPaths() const
+{
+ QtResourceSet *that = const_cast<QtResourceSet *>(this);
+ return d_ptr->m_resourceModel->d_ptr->m_resourceSetToPaths.value(that);
+}
+
+void QtResourceSet::activateQrcPaths(const QStringList &paths, int *errorCount, QString *errorMessages)
+{
+ d_ptr->m_resourceModel->d_ptr->activate(this, paths, errorCount, errorMessages);
+}
+
+bool QtResourceSet::isModified(const QString &path) const
+{
+ return d_ptr->m_resourceModel->isModified(path);
+}
+
+void QtResourceSet::setModified(const QString &path)
+{
+ d_ptr->m_resourceModel->setModified(path);
+}
+
+// ------------------- QtResourceModelPrivate
+const QByteArray *QtResourceModelPrivate::createResource(const QString &path, QStringList *contents, int *errorCount, QIODevice &errorDevice) const
+{
+ typedef RCCResourceLibrary::ResourceDataFileMap ResourceDataFileMap;
+ const QByteArray *rc = 0;
+ *errorCount = -1;
+ contents->clear();
+ do {
+ // run RCC
+ RCCResourceLibrary library;
+ library.setVerbose(true);
+ library.setInputFiles(QStringList(path));
+ library.setFormat(RCCResourceLibrary::Binary);
+
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ if (!library.readFiles(/* ignore errors*/ true, errorDevice))
+ break;
+ // return code cannot be fully trusted, might still be empty
+ const ResourceDataFileMap resMap = library.resourceDataFileMap();
+ if (resMap.empty())
+ break;
+
+ if (!library.output(buffer, errorDevice))
+ break;
+
+ *errorCount = library.failedResources().size();
+ *contents = resMap.keys();
+
+ buffer.close();
+ rc = new QByteArray(buffer.data());
+ } while (false);
+
+ if (debugResourceModel)
+ qDebug() << "createResource" << path << "returns data=" << rc << " hasWarnings=" << *errorCount;
+ return rc;
+}
+
+void QtResourceModelPrivate::deleteResource(const QByteArray *data) const
+{
+ if (data) {
+ if (debugResourceModel)
+ qDebug() << "deleteResource";
+ delete data;
+ }
+}
+
+void QtResourceModelPrivate::registerResourceSet(QtResourceSet *resourceSet)
+{
+ if (!resourceSet)
+ return;
+
+ // unregister old paths (all because the order of registration is important), later it can be optimized a bit
+ QStringList toRegister = resourceSet->activeQrcPaths();
+ QStringListIterator itRegister(toRegister);
+ while (itRegister.hasNext()) {
+ const QString path = itRegister.next();
+ if (debugResourceModel)
+ qDebug() << "registerResourceSet " << path;
+ const PathDataMap::const_iterator itRcc = m_pathToData.constFind(path);
+ if (itRcc != m_pathToData.constEnd()) { // otherwise data was not created yet
+ if (!QResource::registerResource(reinterpret_cast<const uchar *>(itRcc.value()->constData()))) {
+ qDebug() << "** WARNING: Failed to register " << path << " (QResource failure).";
+ } else {
+ QStringList contents = m_pathToContents.value(path);
+ QStringListIterator itContents(contents);
+ while (itContents.hasNext()) {
+ const QString filePath = itContents.next();
+ if (!m_fileToQrc.contains(filePath)) // the first loaded resource has higher priority in qt resource system
+ m_fileToQrc.insert(filePath, path);
+ }
+ }
+ }
+ }
+}
+
+void QtResourceModelPrivate::unregisterResourceSet(QtResourceSet *resourceSet)
+{
+ if (!resourceSet)
+ return;
+
+ // unregister old paths (all because the order of registration is importans), later it can be optimized a bit
+ QStringList toUnregister = resourceSet->activeQrcPaths();
+ QStringListIterator itUnregister(toUnregister);
+ while (itUnregister.hasNext()) {
+ const QString path = itUnregister.next();
+ if (debugResourceModel)
+ qDebug() << "unregisterResourceSet " << path;
+ const PathDataMap::const_iterator itRcc = m_pathToData.constFind(path);
+ if (itRcc != m_pathToData.constEnd()) { // otherwise data was not created yet
+ if (!QResource::unregisterResource(reinterpret_cast<const uchar *>(itRcc.value()->constData())))
+ qDebug() << "** WARNING: Failed to unregister " << path << " (QResource failure).";
+ }
+ }
+ m_fileToQrc.clear();
+}
+
+void QtResourceModelPrivate::activate(QtResourceSet *resourceSet, const QStringList &newPaths, int *errorCountPtr, QString *errorMessages)
+{
+ if (debugResourceModel)
+ qDebug() << "activate " << resourceSet;
+ if (errorCountPtr)
+ *errorCountPtr = 0;
+ if (errorMessages)
+ errorMessages->clear();
+
+ QBuffer errorStream;
+ errorStream.open(QIODevice::WriteOnly);
+
+ int errorCount = 0;
+ int generatedCount = 0;
+ bool newResourceSetChanged = false;
+
+ if (resourceSet && resourceSet->activeQrcPaths() != newPaths && !m_newlyCreated.contains(resourceSet))
+ newResourceSetChanged = true;
+
+ PathDataMap newPathToData = m_pathToData;
+
+ QStringListIterator itPath(newPaths);
+ while (itPath.hasNext()) {
+ const QString path = itPath.next();
+ if (resourceSet && !m_pathToResourceSet[path].contains(resourceSet))
+ m_pathToResourceSet[path].append(resourceSet);
+ const QMap<QString, bool>::iterator itMod = m_pathToModified.find(path);
+ if (itMod == m_pathToModified.end() || itMod.value()) { // new path or path is already created, but needs to be recreated
+ QStringList contents;
+ int qrcErrorCount;
+ generatedCount++;
+ if (const QByteArray *data = createResource(path, &contents, &qrcErrorCount, errorStream)) {
+ newPathToData.insert(path, data);
+ if (qrcErrorCount) // Count single failed files as sort of 1/2 error
+ errorCount++;
+ addWatcher(path);
+ } else {
+ newPathToData.remove(path);
+ errorCount++;
+ }
+ m_pathToModified.insert(path, false);
+ m_pathToContents.insert(path, contents);
+ newResourceSetChanged = true;
+ const QMap<QString, QList<QtResourceSet *> >::iterator itReload = m_pathToResourceSet.find(path);
+ if (itReload != m_pathToResourceSet.end()) {
+ QList<QtResourceSet *> resources = itReload.value();
+ QListIterator<QtResourceSet *> itRes(resources);
+ while (itRes.hasNext()) {
+ QtResourceSet *res = itRes.next();
+ if (res != resourceSet) {
+ m_resourceSetToReload[res] = true;
+ }
+ }
+ }
+ } else { // path is already created, don't need to recreate
+ }
+ }
+
+ QList<const QByteArray *> oldData = m_pathToData.values();
+ QList<const QByteArray *> newData = newPathToData.values();
+
+ QList<const QByteArray *> toDelete;
+ QListIterator<const QByteArray *> itOld(oldData);
+ if (itOld.hasNext()) {
+ const QByteArray *array = itOld.next();
+ if (!newData.contains(array))
+ toDelete.append(array);
+ }
+
+ // Nothing can fail below here?
+ if (generatedCount) {
+ if (errorCountPtr)
+ *errorCountPtr = errorCount;
+ errorStream.close();
+ const QString stderrOutput = QString::fromUtf8(errorStream.data());
+ if (debugResourceModel)
+ qDebug() << "Output: (" << errorCount << ")\n" << stderrOutput;
+ if (errorMessages)
+ *errorMessages = stderrOutput;
+ }
+ // register
+ const QMap<QtResourceSet *, bool>::iterator itReload = m_resourceSetToReload.find(resourceSet);
+ if (itReload != m_resourceSetToReload.end()) {
+ if (itReload.value()) {
+ newResourceSetChanged = true;
+ m_resourceSetToReload.insert(resourceSet, false);
+ }
+ }
+
+ QStringList oldActivePaths;
+ if (m_currentResourceSet)
+ oldActivePaths = m_currentResourceSet->activeQrcPaths();
+
+ const bool needReregister = (oldActivePaths != newPaths) || newResourceSetChanged;
+
+ QMap<QtResourceSet *, bool>::iterator itNew = m_newlyCreated.find(resourceSet);
+ if (itNew != m_newlyCreated.end()) {
+ m_newlyCreated.remove(resourceSet);
+ if (needReregister)
+ newResourceSetChanged = true;
+ }
+
+ if (!newResourceSetChanged && !needReregister && (m_currentResourceSet == resourceSet)) {
+ foreach (const QByteArray *data, toDelete)
+ deleteResource(data);
+
+ return; // nothing changed
+ }
+
+ if (needReregister)
+ unregisterResourceSet(m_currentResourceSet);
+
+ foreach (const QByteArray *data, toDelete)
+ deleteResource(data);
+
+ m_pathToData = newPathToData;
+ m_currentResourceSet = resourceSet;
+
+ if (resourceSet)
+ removeOldPaths(resourceSet, newPaths);
+
+ if (needReregister)
+ registerResourceSet(m_currentResourceSet);
+
+ emit q_ptr->resourceSetActivated(m_currentResourceSet, newResourceSetChanged);
+
+ // deactivates the paths from old current resource set
+ // add new paths to the new current resource set
+ // reloads all paths which are marked as modified from the current resource set;
+ // activates the paths from current resource set
+ // emits resourceSetActivated() (don't emit only in case when old resource set is the same as new one
+ // AND no path was reloaded AND the list of paths is exactly the same)
+}
+
+void QtResourceModelPrivate::removeOldPaths(QtResourceSet *resourceSet, const QStringList &newPaths)
+{
+ QStringList oldPaths = m_resourceSetToPaths.value(resourceSet);
+ if (oldPaths != newPaths) {
+ // remove old
+ QStringListIterator itOldPaths(oldPaths);
+ while (itOldPaths.hasNext()) {
+ QString oldPath = itOldPaths.next();
+ if (!newPaths.contains(oldPath)) {
+ const QMap<QString, QList<QtResourceSet *> >::iterator itRemove = m_pathToResourceSet.find(oldPath);
+ if (itRemove != m_pathToResourceSet.end()) {
+ const int idx = itRemove.value().indexOf(resourceSet);
+ if (idx >= 0)
+ itRemove.value().removeAt(idx);
+ if (itRemove.value().count() == 0) {
+ PathDataMap::iterator it = m_pathToData.find(oldPath);
+ if (it != m_pathToData.end())
+ deleteResource(it.value());
+ m_pathToResourceSet.erase(itRemove);
+ m_pathToModified.remove(oldPath);
+ m_pathToContents.remove(oldPath);
+ m_pathToData.remove(oldPath);
+ removeWatcher(oldPath);
+ }
+ }
+ }
+ }
+ m_resourceSetToPaths[resourceSet] = newPaths;
+ }
+}
+
+void QtResourceModelPrivate::setWatcherEnabled(const QString &path, bool enable)
+{
+ m_fileWatcher->removePath(path);
+
+ if (!enable)
+ return;
+
+ QFileInfo fi(path);
+ if (fi.exists())
+ m_fileWatcher->addPath(path);
+}
+
+void QtResourceModelPrivate::addWatcher(const QString &path)
+{
+ QMap<QString, bool>::ConstIterator it = m_fileWatchedMap.constFind(path);
+ if (it != m_fileWatchedMap.constEnd() && it.value() == false)
+ return;
+
+ m_fileWatchedMap.insert(path, true);
+ if (!m_fileWatcherEnabled)
+ return;
+ setWatcherEnabled(path, true);
+}
+
+void QtResourceModelPrivate::removeWatcher(const QString &path)
+{
+ if (!m_fileWatchedMap.contains(path))
+ return;
+
+ m_fileWatchedMap.remove(path);
+ if (!m_fileWatcherEnabled)
+ return;
+ setWatcherEnabled(path, false);
+}
+
+void QtResourceModelPrivate::slotFileChanged(const QString &path)
+{
+ setWatcherEnabled(path, false);
+ emit q_ptr->qrcFileModifiedExternally(path);
+ setWatcherEnabled(path, true); //readd
+}
+
+// ----------------------- QtResourceModel
+QtResourceModel::QtResourceModel(QObject *parent) :
+ QObject(parent),
+ d_ptr(new QtResourceModelPrivate)
+{
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_fileWatcher = new QFileSystemWatcher(this);
+ connect(d_ptr->m_fileWatcher, SIGNAL(fileChanged(const QString &)),
+ this, SLOT(slotFileChanged(const QString &)));
+}
+
+QtResourceModel::~QtResourceModel()
+{
+ blockSignals(true);
+ QList<QtResourceSet *> resourceList = resourceSets();
+ QListIterator<QtResourceSet *> it(resourceList);
+ while (it.hasNext())
+ removeResourceSet(it.next());
+ blockSignals(false);
+ delete d_ptr;
+}
+
+QStringList QtResourceModel::loadedQrcFiles() const
+{
+ return d_ptr->m_pathToModified.keys();
+}
+
+bool QtResourceModel::isModified(const QString &path) const
+{
+ QMap<QString, bool>::const_iterator it = d_ptr->m_pathToModified.find(path);
+ if (it != d_ptr->m_pathToModified.constEnd())
+ return it.value();
+ return true;
+}
+
+void QtResourceModel::setModified(const QString &path)
+{
+ QMap<QString, bool>::const_iterator itMod = d_ptr->m_pathToModified.find(path);
+ if (itMod == d_ptr->m_pathToModified.constEnd())
+ return;
+
+ d_ptr->m_pathToModified[path] = true;
+ QMap<QString, QList<QtResourceSet *> >::const_iterator it = d_ptr->m_pathToResourceSet.constFind(path);
+ if (it == d_ptr->m_pathToResourceSet.constEnd())
+ return;
+
+ QList<QtResourceSet *> resourceList = it.value();
+ QListIterator<QtResourceSet *> itReload(resourceList);
+ while (itReload.hasNext())
+ d_ptr->m_resourceSetToReload.insert(itReload.next(), true);
+}
+
+QList<QtResourceSet *> QtResourceModel::resourceSets() const
+{
+ return d_ptr->m_resourceSetToPaths.keys();
+}
+
+QtResourceSet *QtResourceModel::currentResourceSet() const
+{
+ return d_ptr->m_currentResourceSet;
+}
+
+void QtResourceModel::setCurrentResourceSet(QtResourceSet *resourceSet, int *errorCount, QString *errorMessages)
+{
+ d_ptr->activate(resourceSet, d_ptr->m_resourceSetToPaths.value(resourceSet), errorCount, errorMessages);
+}
+
+QtResourceSet *QtResourceModel::addResourceSet(const QStringList &paths)
+{
+ QtResourceSet *newResource = new QtResourceSet(this);
+ d_ptr->m_resourceSetToPaths.insert(newResource, paths);
+ d_ptr->m_resourceSetToReload.insert(newResource, false);
+ d_ptr->m_newlyCreated.insert(newResource, true);
+ QStringListIterator it(paths);
+ while (it.hasNext()) {
+ const QString path = it.next();
+ d_ptr->m_pathToResourceSet[path].append(newResource);
+ }
+ return newResource;
+}
+
+// TODO
+void QtResourceModel::removeResourceSet(QtResourceSet *resourceSet)
+{
+ if (!resourceSet)
+ return;
+ if (currentResourceSet() == resourceSet)
+ setCurrentResourceSet(0);
+
+ // remove rcc files for those paths which are not used in any other resource set
+ d_ptr->removeOldPaths(resourceSet, QStringList());
+
+ d_ptr->m_resourceSetToPaths.remove(resourceSet);
+ d_ptr->m_resourceSetToReload.remove(resourceSet);
+ d_ptr->m_newlyCreated.remove(resourceSet);
+ delete resourceSet;
+}
+
+void QtResourceModel::reload(const QString &path, int *errorCount, QString *errorMessages)
+{
+ setModified(path);
+
+ d_ptr->activate(d_ptr->m_currentResourceSet, d_ptr->m_resourceSetToPaths.value(d_ptr->m_currentResourceSet), errorCount, errorMessages);
+}
+
+void QtResourceModel::reload(int *errorCount, QString *errorMessages)
+{
+ QMap<QString, bool>::iterator it = d_ptr->m_pathToModified.begin();
+ QMap<QString, bool>::iterator itEnd = d_ptr->m_pathToModified.end(); // will it be valid when I iterate the map and change it???
+ while (it != itEnd) {
+ it = d_ptr->m_pathToModified.insert(it.key(), true);
+ ++it;
+ }
+
+ QMap<QtResourceSet *, bool>::iterator itReload = d_ptr->m_resourceSetToReload.begin();
+ QMap<QtResourceSet *, bool>::iterator itReloadEnd = d_ptr->m_resourceSetToReload.end();
+ while (itReload != itReloadEnd) {
+ itReload = d_ptr->m_resourceSetToReload.insert(itReload.key(), true); // empty resourceSets could be omitted here
+ ++itReload;
+ }
+
+ d_ptr->activate(d_ptr->m_currentResourceSet, d_ptr->m_resourceSetToPaths.value(d_ptr->m_currentResourceSet), errorCount, errorMessages);
+}
+
+QMap<QString, QString> QtResourceModel::contents() const
+{
+ return d_ptr->m_fileToQrc;
+}
+
+QString QtResourceModel::qrcPath(const QString &file) const
+{
+ return d_ptr->m_fileToQrc.value(file);
+}
+
+void QtResourceModel::setWatcherEnabled(bool enable)
+{
+ if (d_ptr->m_fileWatcherEnabled == enable)
+ return;
+
+ d_ptr->m_fileWatcherEnabled = enable;
+
+ QMapIterator<QString, bool> it(d_ptr->m_fileWatchedMap);
+ if (it.hasNext())
+ d_ptr->setWatcherEnabled(it.next().key(), d_ptr->m_fileWatcherEnabled);
+}
+
+bool QtResourceModel::isWatcherEnabled() const
+{
+ return d_ptr->m_fileWatcherEnabled;
+}
+
+void QtResourceModel::setWatcherEnabled(const QString &path, bool enable)
+{
+ QMap<QString, bool>::Iterator it = d_ptr->m_fileWatchedMap.find(path);
+ if (it == d_ptr->m_fileWatchedMap.end())
+ return;
+
+ if (it.value() == enable)
+ return;
+
+ it.value() = enable;
+
+ if (!d_ptr->m_fileWatcherEnabled)
+ return;
+
+ d_ptr->setWatcherEnabled(it.key(), enable);
+}
+
+bool QtResourceModel::isWatcherEnabled(const QString &path)
+{
+ return d_ptr->m_fileWatchedMap.value(path, false);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtresourcemodel_p.cpp"
diff --git a/tools/designer/src/lib/shared/qtresourcemodel_p.h b/tools/designer/src/lib/shared/qtresourcemodel_p.h
new file mode 100644
index 0000000000..726db299a4
--- /dev/null
+++ b/tools/designer/src/lib/shared/qtresourcemodel_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QTRESOURCEMODEL_H
+#define QTRESOURCEMODEL_H
+
+#include "shared_global_p.h"
+#include <QtCore/QMap>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QtResourceModel;
+
+class QDESIGNER_SHARED_EXPORT QtResourceSet // one instance per one form
+{
+public:
+ QStringList activeQrcPaths() const;
+
+ // activateQrcPaths(): if this QtResourceSet is active it emits resourceSetActivated();
+ // otherwise only in case if active QtResource set contains one of
+ // paths which was marked as modified by this resource set, the signal
+ // is emitted (with reload = true);
+ // If new path appears on the list it is automatically added to
+ // loaded list of QtResourceModel. In addition it is marked as modified in case
+ // QtResourceModel didn't contain the path.
+ // If some path is removed from that list (and is not used in any other
+ // resource set) it is automatically unloaded. The removed file can also be
+ // marked as modified (later when another resource set which contains
+ // removed path is activated will be reloaded)
+ void activateQrcPaths(const QStringList &paths, int *errorCount = 0, QString *errorMessages = 0);
+
+ bool isModified(const QString &path) const; // for all paths in resource model (redundant here, maybe it should be removed from here)
+ void setModified(const QString &path); // for all paths in resource model (redundant here, maybe it should be removed from here)
+private:
+ QtResourceSet();
+ QtResourceSet(QtResourceModel *model);
+ ~QtResourceSet();
+ friend class QtResourceModel;
+
+ class QtResourceSetPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtResourceSet)
+ Q_DISABLE_COPY(QtResourceSet)
+};
+
+class QDESIGNER_SHARED_EXPORT QtResourceModel : public QObject // one instance per whole designer
+{
+ Q_OBJECT
+public:
+ QtResourceModel(QObject *parent = 0);
+ ~QtResourceModel();
+
+ QStringList loadedQrcFiles() const;
+ bool isModified(const QString &path) const; // only for paths which are on loadedQrcFiles() list
+ void setModified(const QString &path); // only for paths which are on loadedQrcPaths() list
+
+ QList<QtResourceSet *> resourceSets() const;
+
+ QtResourceSet *currentResourceSet() const;
+ void setCurrentResourceSet(QtResourceSet *resourceSet, int *errorCount = 0, QString *errorMessages = 0);
+
+ QtResourceSet *addResourceSet(const QStringList &paths);
+ void removeResourceSet(QtResourceSet *resourceSet);
+
+ void reload(const QString &path, int *errorCount = 0, QString *errorMessages = 0);
+ void reload(int *errorCount = 0, QString *errorMessages = 0);
+
+ // Contents of the current resource set (content file to qrc path)
+ QMap<QString, QString> contents() const;
+ // Find the qrc file belonging to the contained file (from current resource set)
+ QString qrcPath(const QString &file) const;
+
+ void setWatcherEnabled(bool enable);
+ bool isWatcherEnabled() const;
+
+ void setWatcherEnabled(const QString &path, bool enable);
+ bool isWatcherEnabled(const QString &path);
+
+signals:
+ void resourceSetActivated(QtResourceSet *resourceSet, bool resourceSetChanged); // resourceSetChanged since last time it was activated!
+ void qrcFileModifiedExternally(const QString &path);
+
+private:
+ friend class QtResourceSet;
+
+ class QtResourceModelPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtResourceModel)
+ Q_DISABLE_COPY(QtResourceModel)
+
+ Q_PRIVATE_SLOT(d_func(), void slotFileChanged(const QString &))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/qtresourceview.cpp b/tools/designer/src/lib/shared/qtresourceview.cpp
new file mode 100644
index 0000000000..d95649119f
--- /dev/null
+++ b/tools/designer/src/lib/shared/qtresourceview.cpp
@@ -0,0 +1,766 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractsettings_p.h"
+#include "qtresourceview_p.h"
+#include "qtresourcemodel_p.h"
+#include "qtresourceeditordialog_p.h"
+#include "iconloader_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtGui/QToolBar>
+#include <QtGui/QAction>
+#include <QtGui/QSplitter>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QListWidget>
+#include <QtGui/QHeaderView>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPainter>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QQueue>
+#include <QtGui/QPainter>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QMessageBox>
+#include <QtGui/QApplication>
+#include <QtGui/QClipboard>
+#include <QtGui/QMenu>
+#include <QtGui/QDrag>
+#include <QtCore/QMimeData>
+#include <QtXml/QDomDocument>
+
+QT_BEGIN_NAMESPACE
+
+static const char *elementResourceData = "resource";
+static const char *typeAttribute = "type";
+static const char *typeImage = "image";
+static const char *typeStyleSheet = "stylesheet";
+static const char *typeOther = "other";
+static const char *fileAttribute = "file";
+static const char *SplitterPosition = "SplitterPosition";
+static const char *Geometry = "Geometry";
+static const char *ResourceViewDialogC = "ResourceDialog";
+
+// ---------------- ResourceListWidget: A list widget that has drag enabled
+class ResourceListWidget : public QListWidget {
+public:
+ ResourceListWidget(QWidget *parent = 0);
+
+protected:
+ virtual void startDrag(Qt::DropActions supportedActions);
+};
+
+ResourceListWidget::ResourceListWidget(QWidget *parent) :
+ QListWidget(parent)
+{
+ setDragEnabled(true);
+}
+
+void ResourceListWidget::startDrag(Qt::DropActions supportedActions)
+{
+ if (supportedActions == Qt::MoveAction)
+ return;
+
+ QListWidgetItem *item = currentItem();
+ if (!item)
+ return;
+
+ const QString filePath = item->data(Qt::UserRole).toString();
+ const QIcon icon = item->icon();
+
+ QMimeData *mimeData = new QMimeData;
+ const QtResourceView::ResourceType type = icon.isNull() ? QtResourceView::ResourceOther : QtResourceView::ResourceImage;
+ mimeData->setText(QtResourceView::encodeMimeData(type , filePath));
+
+ QDrag *drag = new QDrag(this);
+ if (!icon.isNull()) {
+ const QSize size = icon.actualSize(iconSize());
+ drag->setPixmap(icon.pixmap(size));
+ drag->setHotSpot(QPoint(size.width() / 2, size.height() / 2));
+ }
+
+ drag->setMimeData(mimeData);
+ drag->exec(Qt::CopyAction);
+}
+
+/* TODO
+
+ 1) load the icons in separate thread...Hmm..if Qt is configured with threads....
+*/
+
+// ---------------------------- QtResourceViewPrivate
+class QtResourceViewPrivate
+{
+ QtResourceView *q_ptr;
+ Q_DECLARE_PUBLIC(QtResourceView)
+public:
+ QtResourceViewPrivate(QDesignerFormEditorInterface *core);
+
+ void slotResourceSetActivated(QtResourceSet *resourceSet);
+ void slotCurrentPathChanged(QTreeWidgetItem *);
+ void slotCurrentResourceChanged(QListWidgetItem *);
+ void slotResourceActivated(QListWidgetItem *);
+ void slotEditResources();
+ void slotReloadResources();
+ void slotCopyResourcePath();
+ void slotListWidgetContextMenuRequested(const QPoint &pos);
+ void createPaths();
+ QTreeWidgetItem *createPath(const QString &path, QTreeWidgetItem *parent);
+ void createResources(const QString &path);
+ void storeExpansionState();
+ void applyExpansionState();
+ void restoreSettings();
+ void saveSettings();
+ void updateActions();
+
+ QPixmap makeThumbnail(const QPixmap &pix) const;
+
+ QDesignerFormEditorInterface *m_core;
+ QtResourceModel *m_resourceModel;
+ QToolBar *m_toolBar;
+ QTreeWidget *m_treeWidget;
+ QListWidget *m_listWidget;
+ QSplitter *m_splitter;
+ QMap<QString, QStringList> m_pathToContents; // full path to contents file names
+ QMap<QString, QTreeWidgetItem *> m_pathToItem;
+ QMap<QTreeWidgetItem *, QString> m_itemToPath;
+ QMap<QString, QListWidgetItem *> m_resourceToItem;
+ QMap<QListWidgetItem *, QString> m_itemToResource;
+ QAction *m_editResourcesAction;
+ QAction *m_reloadResourcesAction;
+ QAction *m_copyResourcePathAction;
+
+ QMap<QString, bool> m_expansionState;
+
+ bool m_ignoreGuiSignals;
+ QString m_settingsKey;
+ bool m_resourceEditingEnabled;
+};
+
+QtResourceViewPrivate::QtResourceViewPrivate(QDesignerFormEditorInterface *core) :
+ q_ptr(0),
+ m_core(core),
+ m_resourceModel(0),
+ m_toolBar(new QToolBar),
+ m_treeWidget(new QTreeWidget),
+ m_listWidget(new ResourceListWidget),
+ m_splitter(0),
+ m_editResourcesAction(0),
+ m_reloadResourcesAction(0),
+ m_copyResourcePathAction(0),
+ m_ignoreGuiSignals(false),
+ m_resourceEditingEnabled(true)
+{
+}
+
+void QtResourceViewPrivate::restoreSettings()
+{
+ if (m_settingsKey.isEmpty())
+ return;
+
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(m_settingsKey);
+
+ m_splitter->restoreState(settings->value(QLatin1String(SplitterPosition)).toByteArray());
+ settings->endGroup();
+}
+
+void QtResourceViewPrivate::saveSettings()
+{
+ if (m_settingsKey.isEmpty())
+ return;
+
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(m_settingsKey);
+
+ settings->setValue(QLatin1String(SplitterPosition), m_splitter->saveState());
+ settings->endGroup();
+}
+
+void QtResourceViewPrivate::slotEditResources()
+{
+ const QString selectedResource
+ = QtResourceEditorDialog::editResources(m_core, m_resourceModel,
+ m_core->dialogGui(), q_ptr);
+ if (!selectedResource.isEmpty())
+ q_ptr->selectResource(selectedResource);
+}
+
+void QtResourceViewPrivate::slotReloadResources()
+{
+ if (m_resourceModel) {
+ int errorCount;
+ QString errorMessages;
+ m_resourceModel->reload(&errorCount, &errorMessages);
+ if (errorCount)
+ QtResourceEditorDialog::displayResourceFailures(errorMessages, m_core->dialogGui(), q_ptr);
+ }
+}
+
+void QtResourceViewPrivate::slotCopyResourcePath()
+{
+ const QString path = q_ptr->selectedResource();
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setText(path);
+}
+
+void QtResourceViewPrivate::slotListWidgetContextMenuRequested(const QPoint &pos)
+{
+ QMenu menu(q_ptr);
+ menu.addAction(m_copyResourcePathAction);
+ menu.exec(m_listWidget->mapToGlobal(pos));
+}
+
+void QtResourceViewPrivate::storeExpansionState()
+{
+ QMapIterator<QString, QTreeWidgetItem *> it(m_pathToItem);
+ while (it.hasNext()) {
+ it.next();
+ m_expansionState[it.key()] = it.value()->isExpanded();
+ }
+}
+
+void QtResourceViewPrivate::applyExpansionState()
+{
+ QMapIterator<QString, QTreeWidgetItem *> it(m_pathToItem);
+ while (it.hasNext()) {
+ it.next();
+ it.value()->setExpanded(m_expansionState.value(it.key(), true));
+ }
+}
+
+QPixmap QtResourceViewPrivate::makeThumbnail(const QPixmap &pix) const
+{
+ int w = qMax(48, pix.width());
+ int h = qMax(48, pix.height());
+ QRect imgRect(0, 0, w, h);
+ QImage img(w, h, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ if (!pix.isNull()) {
+ QRect r(0, 0, pix.width(), pix.height());
+ r.moveCenter(imgRect.center());
+ QPainter p(&img);
+ p.drawPixmap(r.topLeft(), pix);
+ }
+ return QPixmap::fromImage(img);
+}
+
+void QtResourceViewPrivate::updateActions()
+{
+ bool resourceActive = false;
+ if (m_resourceModel)
+ resourceActive = m_resourceModel->currentResourceSet();
+
+ m_editResourcesAction->setVisible(m_resourceEditingEnabled);
+ m_editResourcesAction->setEnabled(resourceActive);
+ m_reloadResourcesAction->setEnabled(resourceActive);
+}
+
+void QtResourceViewPrivate::slotResourceSetActivated(QtResourceSet *resourceSet)
+{
+ Q_UNUSED(resourceSet)
+
+ updateActions();
+
+ storeExpansionState();
+ const QString currentPath = m_itemToPath.value(m_treeWidget->currentItem());
+ const QString currentResource = m_itemToResource.value(m_listWidget->currentItem());
+ m_treeWidget->clear();
+ m_pathToContents.clear();
+ m_pathToItem.clear();
+ m_itemToPath.clear();
+ m_listWidget->clear();
+ m_resourceToItem.clear();
+ m_itemToResource.clear();
+
+ createPaths();
+ applyExpansionState();
+
+ if (!currentResource.isEmpty())
+ q_ptr->selectResource(currentResource);
+ else if (!currentPath.isEmpty())
+ q_ptr->selectResource(currentPath);
+}
+
+void QtResourceViewPrivate::slotCurrentPathChanged(QTreeWidgetItem *item)
+{
+ if (m_ignoreGuiSignals)
+ return;
+
+ m_listWidget->clear();
+ m_resourceToItem.clear();
+ m_itemToResource.clear();
+
+ if (!item)
+ return;
+
+ const QString currentPath = m_itemToPath.value(item);
+ createResources(currentPath);
+}
+
+void QtResourceViewPrivate::slotCurrentResourceChanged(QListWidgetItem *item)
+{
+ m_copyResourcePathAction->setEnabled(item);
+ if (m_ignoreGuiSignals)
+ return;
+
+ emit q_ptr->resourceSelected(m_itemToResource.value(item));
+}
+
+void QtResourceViewPrivate::slotResourceActivated(QListWidgetItem *item)
+{
+ if (m_ignoreGuiSignals)
+ return;
+
+ emit q_ptr->resourceActivated(m_itemToResource.value(item));
+}
+
+void QtResourceViewPrivate::createPaths()
+{
+ if (!m_resourceModel)
+ return;
+
+ const QString root(QLatin1Char(':'));
+
+ QMap<QString, QString> pathToParentPath; // full path to full parent path
+ QMap<QString, QStringList> pathToSubPaths; // full path to full sub paths
+
+ QMap<QString, QString> contents = m_resourceModel->contents();
+ QMapIterator<QString, QString> itContents(contents);
+ while (itContents.hasNext()) {
+ const QString filePath = itContents.next().key();
+ const QFileInfo fi(filePath);
+ QString dirPath = fi.absolutePath();
+ m_pathToContents[dirPath].append(fi.fileName());
+ while (!pathToParentPath.contains(dirPath) && dirPath != root) {
+ const QFileInfo fd(dirPath);
+ const QString parentDirPath = fd.absolutePath();
+ pathToParentPath[dirPath] = parentDirPath;
+ pathToSubPaths[parentDirPath].append(dirPath);
+ dirPath = parentDirPath;
+ }
+ }
+
+ QQueue<QPair<QString, QTreeWidgetItem *> > pathToParentItemQueue;
+ pathToParentItemQueue.enqueue(qMakePair(root, static_cast<QTreeWidgetItem *>(0)));
+ while (!pathToParentItemQueue.isEmpty()) {
+ QPair<QString, QTreeWidgetItem *> pathToParentItem = pathToParentItemQueue.dequeue();
+ const QString path = pathToParentItem.first;
+ QTreeWidgetItem *item = createPath(path, pathToParentItem.second);
+ QStringList subPaths = pathToSubPaths.value(path);
+ QStringListIterator itSubPaths(subPaths);
+ while (itSubPaths.hasNext())
+ pathToParentItemQueue.enqueue(qMakePair(itSubPaths.next(), item));
+ }
+}
+
+QTreeWidgetItem *QtResourceViewPrivate::createPath(const QString &path, QTreeWidgetItem *parent)
+{
+ QTreeWidgetItem *item = 0;
+ if (parent)
+ item = new QTreeWidgetItem(parent);
+ else
+ item = new QTreeWidgetItem(m_treeWidget);
+ m_pathToItem[path] = item;
+ m_itemToPath[item] = path;
+ QString substPath;
+ if (parent) {
+ QFileInfo di(path);
+ substPath = di.fileName();
+ } else {
+ substPath = QLatin1String("<resource root>");
+ }
+ item->setText(0, substPath);
+ item->setToolTip(0, path);
+ return item;
+}
+
+void QtResourceViewPrivate::createResources(const QString &path)
+{
+ QDir dir(path);
+ QStringList files = m_pathToContents.value(path);
+ QStringListIterator it(files);
+ while (it.hasNext()) {
+ QString file = it.next();
+ QString filePath = dir.absoluteFilePath(file);
+ QFileInfo fi(filePath);
+ if (fi.isFile()) {
+ QListWidgetItem *item = new QListWidgetItem(fi.fileName(), m_listWidget);
+ const QPixmap pix = QPixmap(filePath);
+ if (pix.isNull()) {
+ item->setToolTip(filePath);
+ } else {
+ item->setIcon(QIcon(makeThumbnail(pix)));
+ const QSize size = pix.size();
+ item->setToolTip(QtResourceView::tr("Size: %1 x %2\n%3").arg(size.width()).arg(size.height()).arg(filePath));
+ }
+ item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
+ item->setData(Qt::UserRole, filePath);
+ m_itemToResource[item] = filePath;
+ m_resourceToItem[filePath] = item;
+ }
+ }
+}
+
+// -------------- QtResourceView
+
+QtResourceView::QtResourceView(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QWidget(parent),
+ d_ptr(new QtResourceViewPrivate(core))
+{
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_editResourcesAction = new QAction(qdesigner_internal::createIconSet(QLatin1String("edit.png")), tr("Edit Resources..."), this);
+ d_ptr->m_toolBar->addAction(d_ptr->m_editResourcesAction);
+ connect(d_ptr->m_editResourcesAction, SIGNAL(triggered()), this, SLOT(slotEditResources()));
+ d_ptr->m_editResourcesAction->setEnabled(false);
+
+ d_ptr->m_reloadResourcesAction = new QAction(qdesigner_internal::createIconSet(QLatin1String("reload.png")), tr("Reload"), this);
+ d_ptr->m_toolBar->addAction(d_ptr->m_reloadResourcesAction);
+ connect(d_ptr->m_reloadResourcesAction, SIGNAL(triggered()), this, SLOT(slotReloadResources()));
+ d_ptr->m_reloadResourcesAction->setEnabled(false);
+
+ d_ptr->m_copyResourcePathAction = new QAction(qdesigner_internal::createIconSet(QLatin1String("editcopy.png")), tr("Copy Path"), this);
+ connect(d_ptr->m_copyResourcePathAction, SIGNAL(triggered()), this, SLOT(slotCopyResourcePath()));
+ d_ptr->m_copyResourcePathAction->setEnabled(false);
+
+ d_ptr->m_splitter = new QSplitter;
+ d_ptr->m_splitter->setChildrenCollapsible(false);
+ d_ptr->m_splitter->addWidget(d_ptr->m_treeWidget);
+ d_ptr->m_splitter->addWidget(d_ptr->m_listWidget);
+
+ QLayout *layout = new QVBoxLayout(this);
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ layout->addWidget(d_ptr->m_toolBar);
+ layout->addWidget(d_ptr->m_splitter);
+
+ d_ptr->m_treeWidget->setColumnCount(1);
+ d_ptr->m_treeWidget->header()->hide();
+ d_ptr->m_treeWidget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
+
+ d_ptr->m_listWidget->setViewMode(QListView::IconMode);
+ d_ptr->m_listWidget->setResizeMode(QListView::Adjust);
+ d_ptr->m_listWidget->setIconSize(QSize(48, 48));
+ d_ptr->m_listWidget->setGridSize(QSize(64, 64));
+
+ connect(d_ptr->m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
+ this, SLOT(slotCurrentPathChanged(QTreeWidgetItem *)));
+ connect(d_ptr->m_listWidget, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+ this, SLOT(slotCurrentResourceChanged(QListWidgetItem *)));
+ connect(d_ptr->m_listWidget, SIGNAL(itemActivated(QListWidgetItem *)),
+ this, SLOT(slotResourceActivated(QListWidgetItem *)));
+ d_ptr->m_listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(d_ptr->m_listWidget, SIGNAL(customContextMenuRequested(QPoint)),
+ this, SLOT(slotListWidgetContextMenuRequested(QPoint)));
+}
+
+QtResourceView::~QtResourceView()
+{
+ if (!d_ptr->m_settingsKey.isEmpty())
+ d_ptr->saveSettings();
+
+ delete d_ptr;
+}
+
+bool QtResourceView::event(QEvent *event)
+{
+ if (event->type() == QEvent::Show) {
+ d_ptr->m_listWidget->scrollToItem(d_ptr->m_listWidget->currentItem());
+ d_ptr->m_treeWidget->scrollToItem(d_ptr->m_treeWidget->currentItem());
+ }
+ return QWidget::event(event);
+}
+
+QtResourceModel *QtResourceView::model() const
+{
+ return d_ptr->m_resourceModel;
+}
+
+QString QtResourceView::selectedResource() const
+{
+ QListWidgetItem *item = d_ptr->m_listWidget->currentItem();
+ return d_ptr->m_itemToResource.value(item);
+}
+
+void QtResourceView::selectResource(const QString &resource)
+{
+ QFileInfo fi(resource);
+ QDir dir = fi.absoluteDir();
+ if (fi.isDir())
+ dir = QDir(resource);
+ QString dirPath = dir.absolutePath();
+ QMap<QString, QTreeWidgetItem *>::const_iterator it;
+ while ((it = d_ptr->m_pathToItem.find(dirPath)) == d_ptr->m_pathToItem.constEnd()) {
+ if (!dir.cdUp())
+ break;
+ dirPath = dir.absolutePath();
+ }
+ if (it != d_ptr->m_pathToItem.constEnd()) {
+ QTreeWidgetItem *treeItem = it.value();
+ d_ptr->m_treeWidget->setCurrentItem(treeItem);
+ d_ptr->m_treeWidget->scrollToItem(treeItem);
+ // expand all up to current one is done by qt
+ // list widget is already propagated (currrent changed was sent by qt)
+ QListWidgetItem *item = d_ptr->m_resourceToItem.value(resource);
+ if (item) {
+ d_ptr->m_listWidget->setCurrentItem(item);
+ d_ptr->m_listWidget->scrollToItem(item);
+ }
+ }
+}
+
+QString QtResourceView::settingsKey() const
+{
+ return d_ptr->m_settingsKey;
+}
+
+void QtResourceView::setSettingsKey(const QString &key)
+{
+ if (d_ptr->m_settingsKey == key)
+ return;
+
+ d_ptr->m_settingsKey = key;
+
+ if (key.isEmpty())
+ return;
+
+ d_ptr->restoreSettings();
+}
+
+void QtResourceView::setResourceModel(QtResourceModel *model)
+{
+ if (d_ptr->m_resourceModel) {
+ disconnect(d_ptr->m_resourceModel, SIGNAL(resourceSetActivated(QtResourceSet *, bool)),
+ this, SLOT(slotResourceSetActivated(QtResourceSet *)));
+ }
+
+ // clear here
+ d_ptr->m_treeWidget->clear();
+ d_ptr->m_listWidget->clear();
+
+ d_ptr->m_resourceModel = model;
+
+ if (!d_ptr->m_resourceModel)
+ return;
+
+ connect(d_ptr->m_resourceModel, SIGNAL(resourceSetActivated(QtResourceSet *, bool)),
+ this, SLOT(slotResourceSetActivated(QtResourceSet *)));
+
+ // fill new here
+ d_ptr->slotResourceSetActivated(d_ptr->m_resourceModel->currentResourceSet());
+}
+
+bool QtResourceView::isResourceEditingEnabled() const
+{
+ return d_ptr->m_resourceEditingEnabled;
+}
+
+void QtResourceView::setResourceEditingEnabled(bool enable)
+{
+ d_ptr->m_resourceEditingEnabled = enable;
+ d_ptr->updateActions();
+}
+
+void QtResourceView::setDragEnabled(bool dragEnabled)
+{
+ d_ptr->m_listWidget->setDragEnabled(dragEnabled);
+}
+
+bool QtResourceView::dragEnabled() const
+{
+ return d_ptr->m_listWidget->dragEnabled();
+}
+
+QString QtResourceView::encodeMimeData(ResourceType resourceType, const QString &path)
+{
+ QDomDocument doc;
+ QDomElement elem = doc.createElement(QLatin1String(elementResourceData));
+ switch (resourceType) {
+ case ResourceImage:
+ elem.setAttribute(QLatin1String(typeAttribute), QLatin1String(typeImage));
+ break;
+ case ResourceStyleSheet:
+ elem.setAttribute(QLatin1String(typeAttribute), QLatin1String(typeStyleSheet));
+ break;
+ case ResourceOther:
+ elem.setAttribute(QLatin1String(typeAttribute), QLatin1String(typeOther));
+ break;
+ }
+ elem.setAttribute(QLatin1String(fileAttribute), path);
+ doc.appendChild(elem);
+ return doc.toString();
+}
+
+bool QtResourceView::decodeMimeData(const QMimeData *md, ResourceType *t, QString *file)
+{
+ return md->hasText() ? decodeMimeData(md->text(), t, file) : false;
+}
+
+bool QtResourceView::decodeMimeData(const QString &text, ResourceType *t, QString *file)
+{
+
+ const QString docElementName = QLatin1String(elementResourceData);
+ static const QString docElementString = QLatin1Char('<') + docElementName;
+
+ if (text.isEmpty() || text.indexOf(docElementString) == -1)
+ return false;
+
+ QDomDocument doc;
+ if (!doc.setContent(text))
+ return false;
+
+ const QDomElement domElement = doc.documentElement();
+ if (domElement.tagName() != docElementName)
+ return false;
+
+ if (t) {
+ const QString typeAttr = QLatin1String(typeAttribute);
+ if (domElement.hasAttribute (typeAttr)) {
+ const QString typeValue = domElement.attribute(typeAttr, QLatin1String(typeOther));
+ if (typeValue == QLatin1String(typeImage)) {
+ *t = ResourceImage;
+ } else {
+ *t = typeValue == QLatin1String(typeStyleSheet) ? ResourceStyleSheet : ResourceOther;
+ }
+ }
+ }
+ if (file) {
+ const QString fileAttr = QLatin1String(fileAttribute);
+ if (domElement.hasAttribute(fileAttr)) {
+ *file = domElement.attribute(fileAttr, QString());
+ } else {
+ file->clear();
+ }
+ }
+ return true;
+}
+
+// ---------------------------- QtResourceViewDialogPrivate
+
+class QtResourceViewDialogPrivate
+{
+ QtResourceViewDialog *q_ptr;
+ Q_DECLARE_PUBLIC(QtResourceViewDialog)
+public:
+ QtResourceViewDialogPrivate(QDesignerFormEditorInterface *core);
+
+ void slotResourceSelected(const QString &resource) { setOkButtonEnabled(!resource.isEmpty()); }
+ void setOkButtonEnabled(bool v) { m_box->button(QDialogButtonBox::Ok)->setEnabled(v); }
+
+ QDesignerFormEditorInterface *m_core;
+ QtResourceView *m_view;
+ QDialogButtonBox *m_box;
+};
+
+QtResourceViewDialogPrivate::QtResourceViewDialogPrivate(QDesignerFormEditorInterface *core) :
+ q_ptr(0),
+ m_core(core),
+ m_view(new QtResourceView(core)),
+ m_box(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel))
+{
+ m_view->setSettingsKey(QLatin1String(ResourceViewDialogC));
+}
+
+// ------------ QtResourceViewDialog
+QtResourceViewDialog::QtResourceViewDialog(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QDialog(parent),
+ d_ptr(new QtResourceViewDialogPrivate(core))
+{
+ setWindowTitle(tr("Select Resource"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ d_ptr->q_ptr = this;
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(d_ptr->m_view);
+ layout->addWidget(d_ptr->m_box);
+ connect(d_ptr->m_box, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(d_ptr->m_box, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(d_ptr->m_view, SIGNAL(resourceActivated(QString)), this, SLOT(accept()));
+ connect(d_ptr->m_view, SIGNAL(resourceSelected(QString)), this, SLOT(slotResourceSelected(QString)));
+ d_ptr->setOkButtonEnabled(false);
+ d_ptr->m_view->setResourceModel(core->resourceModel());
+
+ QDesignerSettingsInterface *settings = core->settingsManager();
+ settings->beginGroup(QLatin1String(ResourceViewDialogC));
+
+ if (settings->contains(QLatin1String(Geometry)))
+ setGeometry(settings->value(QLatin1String(Geometry)).toRect());
+
+ settings->endGroup();
+}
+
+QtResourceViewDialog::~QtResourceViewDialog()
+{
+ QDesignerSettingsInterface *settings = d_ptr->m_core->settingsManager();
+ settings->beginGroup(QLatin1String(ResourceViewDialogC));
+
+ settings->setValue(QLatin1String(Geometry), geometry());
+
+ settings->endGroup();
+
+ delete d_ptr;
+}
+
+QString QtResourceViewDialog::selectedResource() const
+{
+ return d_ptr->m_view->selectedResource();
+}
+
+void QtResourceViewDialog::selectResource(const QString &path)
+{
+ d_ptr->m_view->selectResource(path);
+}
+
+bool QtResourceViewDialog::isResourceEditingEnabled() const
+{
+ return d_ptr->m_view->isResourceEditingEnabled();
+}
+
+void QtResourceViewDialog::setResourceEditingEnabled(bool enable)
+{
+ d_ptr->m_view->setResourceEditingEnabled(enable);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtresourceview_p.cpp"
diff --git a/tools/designer/src/lib/shared/qtresourceview_p.h b/tools/designer/src/lib/shared/qtresourceview_p.h
new file mode 100644
index 0000000000..33162c5d46
--- /dev/null
+++ b/tools/designer/src/lib/shared/qtresourceview_p.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QTRESOURCEVIEW_H
+#define QTRESOURCEVIEW_H
+
+#include "shared_global_p.h"
+#include <QtGui/QWidget>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QtResourceModel;
+class QtResourceSet;
+class QDesignerFormEditorInterface;
+class QMimeData;
+
+class QDESIGNER_SHARED_EXPORT QtResourceView : public QWidget
+{
+ Q_OBJECT
+public:
+ QtResourceView(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ ~QtResourceView();
+
+ void setDragEnabled(bool dragEnabled);
+ bool dragEnabled() const;
+
+ QtResourceModel *model() const;
+ void setResourceModel(QtResourceModel *model);
+
+ QString selectedResource() const;
+ void selectResource(const QString &resource);
+
+ QString settingsKey() const;
+ void setSettingsKey(const QString &key);
+
+ bool isResourceEditingEnabled() const;
+ void setResourceEditingEnabled(bool enable);
+
+ // Helpers for handling the drag originating in QtResourceView (Xml/text)
+ enum ResourceType { ResourceImage, ResourceStyleSheet, ResourceOther };
+ static QString encodeMimeData(ResourceType resourceType, const QString &path);
+
+ static bool decodeMimeData(const QMimeData *md, ResourceType *t = 0, QString *file = 0);
+ static bool decodeMimeData(const QString &text, ResourceType *t = 0, QString *file = 0);
+
+signals:
+ void resourceSelected(const QString &resource);
+ void resourceActivated(const QString &resource);
+
+protected:
+ bool event(QEvent *event);
+
+private:
+
+ class QtResourceViewPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtResourceView)
+ Q_DISABLE_COPY(QtResourceView)
+ Q_PRIVATE_SLOT(d_func(), void slotResourceSetActivated(QtResourceSet *))
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentPathChanged(QTreeWidgetItem *))
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentResourceChanged(QListWidgetItem *))
+ Q_PRIVATE_SLOT(d_func(), void slotResourceActivated(QListWidgetItem *))
+ Q_PRIVATE_SLOT(d_func(), void slotEditResources())
+ Q_PRIVATE_SLOT(d_func(), void slotReloadResources())
+ Q_PRIVATE_SLOT(d_func(), void slotCopyResourcePath())
+ Q_PRIVATE_SLOT(d_func(), void slotListWidgetContextMenuRequested(const QPoint &pos))
+};
+
+class QDESIGNER_SHARED_EXPORT QtResourceViewDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QtResourceViewDialog(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ virtual ~QtResourceViewDialog();
+
+ QString selectedResource() const;
+ void selectResource(const QString &path);
+
+ bool isResourceEditingEnabled() const;
+ void setResourceEditingEnabled(bool enable);
+
+private:
+ class QtResourceViewDialogPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtResourceViewDialog)
+ Q_DISABLE_COPY(QtResourceViewDialog)
+ Q_PRIVATE_SLOT(d_func(), void slotResourceSelected(const QString &))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/richtexteditor.cpp b/tools/designer/src/lib/shared/richtexteditor.cpp
new file mode 100644
index 0000000000..8aa036b254
--- /dev/null
+++ b/tools/designer/src/lib/shared/richtexteditor.cpp
@@ -0,0 +1,762 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::RichTextEditorDialog
+*/
+
+#include "richtexteditor_p.h"
+#include "htmlhighlighter_p.h"
+#include "iconselector_p.h"
+#include "ui_addlinkdialog.h"
+#include "abstractsettings_p.h"
+
+#include "iconloader_p.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QPointer>
+
+#include <QtGui/QAction>
+#include <QtGui/QColorDialog>
+#include <QtGui/QComboBox>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QTextCursor>
+#include <QtGui/QPainter>
+#include <QtGui/QIcon>
+#include <QtGui/QMenu>
+#include <QtGui/QMoveEvent>
+#include <QtGui/QTabWidget>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+#include <QtGui/QToolBar>
+#include <QtGui/QToolButton>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialogButtonBox>
+
+QT_BEGIN_NAMESPACE
+
+static const char *RichTextDialogC = "RichTextDialog";
+static const char *Geometry = "Geometry";
+
+namespace qdesigner_internal {
+
+class RichTextEditor : public QTextEdit
+{
+ Q_OBJECT
+public:
+ RichTextEditor(QWidget *parent = 0);
+ void setDefaultFont(const QFont &font);
+
+ QToolBar *createToolBar(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+
+public slots:
+ void setFontBold(bool b);
+ void setFontPointSize(double);
+ void setText(const QString &text);
+ QString text(Qt::TextFormat format) const;
+
+signals:
+ void stateChanged();
+};
+
+class AddLinkDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ AddLinkDialog(RichTextEditor *editor, QWidget *parent = 0);
+ ~AddLinkDialog();
+
+ int showDialog();
+
+public slots:
+ void accept();
+
+private:
+ RichTextEditor *m_editor;
+ Ui::AddLinkDialog *m_ui;
+};
+
+AddLinkDialog::AddLinkDialog(RichTextEditor *editor, QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::AddLinkDialog)
+{
+ m_ui->setupUi(this);
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ m_editor = editor;
+}
+
+AddLinkDialog::~AddLinkDialog()
+{
+ delete m_ui;
+}
+
+int AddLinkDialog::showDialog()
+{
+ // Set initial focus
+ const QTextCursor cursor = m_editor->textCursor();
+ if (cursor.hasSelection()) {
+ m_ui->titleInput->setText(cursor.selectedText());
+ m_ui->urlInput->setFocus();
+ } else {
+ m_ui->titleInput->setFocus();
+ }
+
+ return exec();
+}
+
+void AddLinkDialog::accept()
+{
+ const QString title = m_ui->titleInput->text();
+ const QString url = m_ui->urlInput->text();
+
+ if (!title.isEmpty()) {
+ QString html = QLatin1String("<a href=\"");
+ html += url;
+ html += QLatin1String("\">");
+ html += title;
+ html += QLatin1String("</a>");
+
+ m_editor->insertHtml(html);
+ }
+
+ m_ui->titleInput->clear();
+ m_ui->urlInput->clear();
+
+ QDialog::accept();
+}
+
+class HtmlTextEdit : public QTextEdit
+{
+ Q_OBJECT
+
+public:
+ HtmlTextEdit(QWidget *parent = 0)
+ : QTextEdit(parent)
+ {}
+
+ void contextMenuEvent(QContextMenuEvent *event);
+
+private slots:
+ void actionTriggered(QAction *action);
+};
+
+void HtmlTextEdit::contextMenuEvent(QContextMenuEvent *event)
+{
+ QMenu *menu = createStandardContextMenu();
+ QMenu *htmlMenu = new QMenu(tr("Insert HTML entity"), menu);
+
+ typedef struct {
+ const char *text;
+ const char *entity;
+ } Entry;
+
+ const Entry entries[] = {
+ { "&&amp; (&&)", "&amp;" },
+ { "&&nbsp;", "&nbsp;" },
+ { "&&lt; (<)", "&lt;" },
+ { "&&gt; (>)", "&gt;" },
+ { "&&copy; (Copyright)", "&copy;" },
+ { "&&reg; (Trade Mark)", "&reg;" },
+ };
+
+ for (int i = 0; i < 6; ++i) {
+ QAction *entityAction = new QAction(QLatin1String(entries[i].text),
+ htmlMenu);
+ entityAction->setData(QLatin1String(entries[i].entity));
+ htmlMenu->addAction(entityAction);
+ }
+
+ menu->addMenu(htmlMenu);
+ connect(htmlMenu, SIGNAL(triggered(QAction*)),
+ SLOT(actionTriggered(QAction*)));
+ menu->exec(event->globalPos());
+ delete menu;
+}
+
+void HtmlTextEdit::actionTriggered(QAction *action)
+{
+ insertPlainText(action->data().toString());
+}
+
+class ColorAction : public QAction
+{
+ Q_OBJECT
+
+public:
+ ColorAction(QObject *parent);
+
+ const QColor& color() const { return m_color; }
+ void setColor(const QColor &color);
+
+signals:
+ void colorChanged(const QColor &color);
+
+private slots:
+ void chooseColor();
+
+private:
+ QColor m_color;
+};
+
+ColorAction::ColorAction(QObject *parent):
+ QAction(parent)
+{
+ setText(tr("Text Color"));
+ setColor(Qt::black);
+ connect(this, SIGNAL(triggered()), this, SLOT(chooseColor()));
+}
+
+void ColorAction::setColor(const QColor &color)
+{
+ if (color == m_color)
+ return;
+ m_color = color;
+ QPixmap pix(24, 24);
+ QPainter painter(&pix);
+ painter.setRenderHint(QPainter::Antialiasing, false);
+ painter.fillRect(pix.rect(), m_color);
+ painter.setPen(m_color.darker());
+ painter.drawRect(pix.rect().adjusted(0, 0, -1, -1));
+ setIcon(pix);
+}
+
+void ColorAction::chooseColor()
+{
+ const QColor col = QColorDialog::getColor(m_color, 0);
+ if (col.isValid() && col != m_color) {
+ setColor(col);
+ emit colorChanged(m_color);
+ }
+}
+
+class RichTextEditorToolBar : public QToolBar
+{
+ Q_OBJECT
+public:
+ RichTextEditorToolBar(QDesignerFormEditorInterface *core,
+ RichTextEditor *editor,
+ QWidget *parent = 0);
+
+public slots:
+ void updateActions();
+
+private slots:
+ void alignmentActionTriggered(QAction *action);
+ void sizeInputActivated(const QString &size);
+ void colorChanged(const QColor &color);
+ void setVAlignSuper(bool super);
+ void setVAlignSub(bool sub);
+ void insertLink();
+ void insertImage();
+
+private:
+ QAction *m_bold_action;
+ QAction *m_italic_action;
+ QAction *m_underline_action;
+ QAction *m_valign_sup_action;
+ QAction *m_valign_sub_action;
+ QAction *m_align_left_action;
+ QAction *m_align_center_action;
+ QAction *m_align_right_action;
+ QAction *m_align_justify_action;
+ QAction *m_link_action;
+ QAction *m_image_action;
+ ColorAction *m_color_action;
+ QComboBox *m_font_size_input;
+
+ QDesignerFormEditorInterface *m_core;
+ QPointer<RichTextEditor> m_editor;
+};
+
+static QAction *createCheckableAction(const QIcon &icon, const QString &text,
+ QObject *receiver, const char *slot,
+ QObject *parent = 0)
+{
+ QAction *result = new QAction(parent);
+ result->setIcon(icon);
+ result->setText(text);
+ result->setCheckable(true);
+ result->setChecked(false);
+ if (slot)
+ QObject::connect(result, SIGNAL(triggered(bool)), receiver, slot);
+ return result;
+}
+
+RichTextEditorToolBar::RichTextEditorToolBar(QDesignerFormEditorInterface *core,
+ RichTextEditor *editor,
+ QWidget *parent) :
+ QToolBar(parent),
+ m_link_action(new QAction(this)),
+ m_image_action(new QAction(this)),
+ m_color_action(new ColorAction(this)),
+ m_font_size_input(new QComboBox),
+ m_core(core),
+ m_editor(editor)
+{
+ // Font size combo box
+ m_font_size_input->setEditable(false);
+ const QList<int> font_sizes = QFontDatabase::standardSizes();
+ foreach (int font_size, font_sizes)
+ m_font_size_input->addItem(QString::number(font_size));
+
+ connect(m_font_size_input, SIGNAL(activated(QString)),
+ this, SLOT(sizeInputActivated(QString)));
+ addWidget(m_font_size_input);
+
+ addSeparator();
+
+ // Bold, italic and underline buttons
+
+ m_bold_action = createCheckableAction(
+ createIconSet(QLatin1String("textbold.png")),
+ tr("Bold"), editor, SLOT(setFontBold(bool)), this);
+ m_bold_action->setShortcut(tr("CTRL+B"));
+ addAction(m_bold_action);
+
+ m_italic_action = createCheckableAction(
+ createIconSet(QLatin1String("textitalic.png")),
+ tr("Italic"), editor, SLOT(setFontItalic(bool)), this);
+ m_italic_action->setShortcut(tr("CTRL+I"));
+ addAction(m_italic_action);
+
+ m_underline_action = createCheckableAction(
+ createIconSet(QLatin1String("textunder.png")),
+ tr("Underline"), editor, SLOT(setFontUnderline(bool)), this);
+ m_underline_action->setShortcut(tr("CTRL+U"));
+ addAction(m_underline_action);
+
+ addSeparator();
+
+ // Left, center, right and justified alignment buttons
+
+ QActionGroup *alignment_group = new QActionGroup(this);
+ connect(alignment_group, SIGNAL(triggered(QAction*)),
+ SLOT(alignmentActionTriggered(QAction*)));
+
+ m_align_left_action = createCheckableAction(
+ createIconSet(QLatin1String("textleft.png")),
+ tr("Left Align"), editor, 0, alignment_group);
+ addAction(m_align_left_action);
+
+ m_align_center_action = createCheckableAction(
+ createIconSet(QLatin1String("textcenter.png")),
+ tr("Center"), editor, 0, alignment_group);
+ addAction(m_align_center_action);
+
+ m_align_right_action = createCheckableAction(
+ createIconSet(QLatin1String("textright.png")),
+ tr("Right Align"), editor, 0, alignment_group);
+ addAction(m_align_right_action);
+
+ m_align_justify_action = createCheckableAction(
+ createIconSet(QLatin1String("textjustify.png")),
+ tr("Justify"), editor, 0, alignment_group);
+ addAction(m_align_justify_action);
+
+ addSeparator();
+
+ // Superscript and subscript buttons
+
+ m_valign_sup_action = createCheckableAction(
+ createIconSet(QLatin1String("textsuperscript.png")),
+ tr("Superscript"),
+ this, SLOT(setVAlignSuper(bool)), this);
+ addAction(m_valign_sup_action);
+
+ m_valign_sub_action = createCheckableAction(
+ createIconSet(QLatin1String("textsubscript.png")),
+ tr("Subscript"),
+ this, SLOT(setVAlignSub(bool)), this);
+ addAction(m_valign_sub_action);
+
+ addSeparator();
+
+ // Insert hyperlink and image buttons
+
+ m_link_action->setIcon(createIconSet(QLatin1String("textanchor.png")));
+ m_link_action->setText(tr("Insert &Link"));
+ connect(m_link_action, SIGNAL(triggered()), SLOT(insertLink()));
+ addAction(m_link_action);
+
+ m_image_action->setIcon(createIconSet(QLatin1String("insertimage.png")));
+ m_image_action->setText(tr("Insert &Image"));
+ connect(m_image_action, SIGNAL(triggered()), SLOT(insertImage()));
+ addAction(m_image_action);
+
+ addSeparator();
+
+ // Text color button
+ connect(m_color_action, SIGNAL(colorChanged(QColor)),
+ this, SLOT(colorChanged(QColor)));
+ addAction(m_color_action);
+
+ connect(editor, SIGNAL(textChanged()), this, SLOT(updateActions()));
+ connect(editor, SIGNAL(stateChanged()), this, SLOT(updateActions()));
+
+ updateActions();
+}
+
+void RichTextEditorToolBar::alignmentActionTriggered(QAction *action)
+{
+ Qt::Alignment new_alignment;
+
+ if (action == m_align_left_action) {
+ new_alignment = Qt::AlignLeft;
+ } else if (action == m_align_center_action) {
+ new_alignment = Qt::AlignCenter;
+ } else if (action == m_align_right_action) {
+ new_alignment = Qt::AlignRight;
+ } else {
+ new_alignment = Qt::AlignJustify;
+ }
+
+ m_editor->setAlignment(new_alignment);
+}
+
+void RichTextEditorToolBar::colorChanged(const QColor &color)
+{
+ m_editor->setTextColor(color);
+ m_editor->setFocus();
+}
+
+void RichTextEditorToolBar::sizeInputActivated(const QString &size)
+{
+ bool ok;
+ int i = size.toInt(&ok);
+ if (!ok)
+ return;
+
+ m_editor->setFontPointSize(i);
+ m_editor->setFocus();
+}
+
+void RichTextEditorToolBar::setVAlignSuper(bool super)
+{
+ const QTextCharFormat::VerticalAlignment align = super ?
+ QTextCharFormat::AlignSuperScript : QTextCharFormat::AlignNormal;
+
+ QTextCharFormat charFormat = m_editor->currentCharFormat();
+ charFormat.setVerticalAlignment(align);
+ m_editor->setCurrentCharFormat(charFormat);
+
+ m_valign_sub_action->setChecked(false);
+}
+
+void RichTextEditorToolBar::setVAlignSub(bool sub)
+{
+ const QTextCharFormat::VerticalAlignment align = sub ?
+ QTextCharFormat::AlignSubScript : QTextCharFormat::AlignNormal;
+
+ QTextCharFormat charFormat = m_editor->currentCharFormat();
+ charFormat.setVerticalAlignment(align);
+ m_editor->setCurrentCharFormat(charFormat);
+
+ m_valign_sup_action->setChecked(false);
+}
+
+void RichTextEditorToolBar::insertLink()
+{
+ AddLinkDialog linkDialog(m_editor, this);
+ linkDialog.showDialog();
+ m_editor->setFocus();
+}
+
+void RichTextEditorToolBar::insertImage()
+{
+ const QString path = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), QString(), this);
+ if (!path.isEmpty())
+ m_editor->insertHtml(QLatin1String("<img src=\"") + path + QLatin1String("\"/>"));
+}
+
+void RichTextEditorToolBar::updateActions()
+{
+ if (m_editor == 0) {
+ setEnabled(false);
+ return;
+ }
+
+ const Qt::Alignment alignment = m_editor->alignment();
+ const QTextCursor cursor = m_editor->textCursor();
+ const QTextCharFormat charFormat = cursor.charFormat();
+ const QFont font = charFormat.font();
+ const QTextCharFormat::VerticalAlignment valign =
+ charFormat.verticalAlignment();
+ const bool superScript = valign == QTextCharFormat::AlignSuperScript;
+ const bool subScript = valign == QTextCharFormat::AlignSubScript;
+
+ if (alignment & Qt::AlignLeft) {
+ m_align_left_action->setChecked(true);
+ } else if (alignment & Qt::AlignRight) {
+ m_align_right_action->setChecked(true);
+ } else if (alignment & Qt::AlignHCenter) {
+ m_align_center_action->setChecked(true);
+ } else {
+ m_align_justify_action->setChecked(true);
+ }
+
+ m_bold_action->setChecked(font.bold());
+ m_italic_action->setChecked(font.italic());
+ m_underline_action->setChecked(font.underline());
+ m_valign_sup_action->setChecked(superScript);
+ m_valign_sub_action->setChecked(subScript);
+
+ const int size = font.pointSize();
+ const int idx = m_font_size_input->findText(QString::number(size));
+ if (idx != -1)
+ m_font_size_input->setCurrentIndex(idx);
+
+ m_color_action->setColor(m_editor->textColor());
+}
+
+RichTextEditor::RichTextEditor(QWidget *parent)
+ : QTextEdit(parent)
+{
+ connect(this, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
+ this, SIGNAL(stateChanged()));
+ connect(this, SIGNAL(cursorPositionChanged()),
+ this, SIGNAL(stateChanged()));
+}
+
+QToolBar *RichTextEditor::createToolBar(QDesignerFormEditorInterface *core, QWidget *parent)
+{
+ return new RichTextEditorToolBar(core, this, parent);
+}
+
+void RichTextEditor::setFontBold(bool b)
+{
+ if (b)
+ setFontWeight(QFont::Bold);
+ else
+ setFontWeight(QFont::Normal);
+}
+
+void RichTextEditor::setFontPointSize(double d)
+{
+ QTextEdit::setFontPointSize(qreal(d));
+}
+
+void RichTextEditor::setText(const QString &text)
+{
+ if (Qt::mightBeRichText(text))
+ setHtml(text);
+ else
+ setPlainText(text);
+}
+
+void RichTextEditor::setDefaultFont(const QFont &font)
+{
+ document()->setDefaultFont(font);
+ if (font.pointSize() > 0)
+ setFontPointSize(font.pointSize());
+ else
+ setFontPointSize(QFontInfo(font).pointSize());
+ emit textChanged();
+}
+
+QString RichTextEditor::text(Qt::TextFormat format) const
+{
+ switch (format) {
+ case Qt::LogText:
+ case Qt::PlainText:
+ return toPlainText();
+ case Qt::RichText:
+ return toHtml();
+ case Qt::AutoText:
+ break;
+ }
+ const QString html = toHtml();
+ const QString plain = toPlainText();
+ QTextEdit tester;
+ tester.setPlainText(plain);
+ return tester.toHtml() == html ? plain : html;
+}
+
+RichTextEditorDialog::RichTextEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent) :
+ QDialog(parent),
+ m_editor(new RichTextEditor()),
+ m_text_edit(new HtmlTextEdit),
+ m_tab_widget(new QTabWidget),
+ m_state(Clean),
+ m_core(core)
+{
+ setWindowTitle(tr("Edit text"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ m_text_edit->setAcceptRichText(false);
+ new HtmlHighlighter(m_text_edit);
+
+ connect(m_editor, SIGNAL(textChanged()), this, SLOT(richTextChanged()));
+ connect(m_text_edit, SIGNAL(textChanged()), this, SLOT(sourceChanged()));
+
+ // The toolbar needs to be created after the RichTextEditor
+ QToolBar *tool_bar = m_editor->createToolBar(core);
+ tool_bar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+
+ QWidget *rich_edit = new QWidget;
+ QVBoxLayout *rich_edit_layout = new QVBoxLayout(rich_edit);
+ rich_edit_layout->addWidget(tool_bar);
+ rich_edit_layout->addWidget(m_editor);
+
+ QWidget *plain_edit = new QWidget;
+ QVBoxLayout *plain_edit_layout = new QVBoxLayout(plain_edit);
+ plain_edit_layout->addWidget(m_text_edit);
+
+ m_tab_widget->setTabPosition(QTabWidget::South);
+ m_tab_widget->addTab(rich_edit, tr("Rich Text"));
+ m_tab_widget->addTab(plain_edit, tr("Source"));
+ connect(m_tab_widget, SIGNAL(currentChanged(int)),
+ SLOT(tabIndexChanged(int)));
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
+ QPushButton *ok_button = buttonBox->button(QDialogButtonBox::Ok);
+ ok_button->setText(tr("&OK"));
+ ok_button->setDefault(true);
+ buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("&Cancel"));
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(m_tab_widget);
+ layout->addWidget(buttonBox);
+
+ m_editor->setFocus();
+
+ QDesignerSettingsInterface *settings = core->settingsManager();
+ settings->beginGroup(QLatin1String(RichTextDialogC));
+
+ if (settings->contains(QLatin1String(Geometry)))
+ restoreGeometry(settings->value(QLatin1String(Geometry)).toByteArray());
+
+ settings->endGroup();
+}
+
+RichTextEditorDialog::~RichTextEditorDialog()
+{
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(RichTextDialogC));
+
+ settings->setValue(QLatin1String(Geometry), saveGeometry());
+ settings->endGroup();
+}
+
+int RichTextEditorDialog::showDialog()
+{
+ m_tab_widget->setCurrentIndex(0);
+ m_editor->selectAll();
+ m_editor->setFocus();
+
+ return exec();
+}
+
+void RichTextEditorDialog::setDefaultFont(const QFont &font)
+{
+ m_editor->setDefaultFont(font);
+}
+
+void RichTextEditorDialog::setText(const QString &text)
+{
+ m_editor->setText(text);
+ m_text_edit->setPlainText(text);
+ m_state = Clean;
+}
+
+QString RichTextEditorDialog::text(Qt::TextFormat format) const
+{
+ // In autotext mode, if the user has changed the source, use that
+ if (format == Qt::AutoText && (m_state == Clean || m_state == SourceChanged))
+ return m_text_edit->toPlainText();
+ // If the plain text HTML editor is selected, first copy its contents over
+ // to the rich text editor so that it is converted to Qt-HTML or actual
+ // plain text.
+ if (m_tab_widget->currentIndex() == SourceIndex && m_state == SourceChanged)
+ m_editor->setHtml(m_text_edit->toPlainText());
+ return m_editor->text(format);
+}
+
+void RichTextEditorDialog::tabIndexChanged(int newIndex)
+{
+ // Anything changed, is there a need for a conversion?
+ if (newIndex == SourceIndex && m_state != RichTextChanged)
+ return;
+ if (newIndex == RichTextIndex && m_state != SourceChanged)
+ return;
+ const State oldState = m_state;
+ // Remember the cursor position, since it is invalidated by setPlainText
+ QTextEdit *new_edit = (newIndex == SourceIndex) ? m_text_edit : m_editor;
+ const int position = new_edit->textCursor().position();
+
+ if (newIndex == SourceIndex)
+ m_text_edit->setPlainText(m_editor->text(Qt::RichText));
+ else
+ m_editor->setHtml(m_text_edit->toPlainText());
+
+ QTextCursor cursor = new_edit->textCursor();
+ cursor.movePosition(QTextCursor::End);
+ if (cursor.position() > position) {
+ cursor.setPosition(position);
+ }
+ new_edit->setTextCursor(cursor);
+ m_state = oldState; // Changed is triggered by setting the text
+}
+
+void RichTextEditorDialog::richTextChanged()
+{
+ m_state = RichTextChanged;
+}
+
+void RichTextEditorDialog::sourceChanged()
+{
+ m_state = SourceChanged;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#include "richtexteditor.moc"
diff --git a/tools/designer/src/lib/shared/richtexteditor_p.h b/tools/designer/src/lib/shared/richtexteditor_p.h
new file mode 100644
index 0000000000..5341fbb46b
--- /dev/null
+++ b/tools/designer/src/lib/shared/richtexteditor_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef RICHTEXTEDITOR_H
+#define RICHTEXTEDITOR_H
+
+#include <QtGui/QTextEdit>
+#include <QtGui/QDialog>
+#include "shared_global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTabWidget;
+class QToolBar;
+
+class QDesignerFormEditorInterface;
+
+namespace qdesigner_internal {
+
+class RichTextEditor;
+
+class QDESIGNER_SHARED_EXPORT RichTextEditorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ RichTextEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent = 0);
+ ~RichTextEditorDialog();
+
+ int showDialog();
+ void setDefaultFont(const QFont &font);
+ void setText(const QString &text);
+ QString text(Qt::TextFormat format = Qt::AutoText) const;
+
+private slots:
+ void tabIndexChanged(int newIndex);
+ void richTextChanged();
+ void sourceChanged();
+
+private:
+ enum TabIndex { RichTextIndex, SourceIndex };
+ enum State { Clean, RichTextChanged, SourceChanged };
+ RichTextEditor *m_editor;
+ QTextEdit *m_text_edit;
+ QTabWidget *m_tab_widget;
+ State m_state;
+ QDesignerFormEditorInterface *m_core;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // RITCHTEXTEDITOR_H
diff --git a/tools/designer/src/lib/shared/scriptcommand.cpp b/tools/designer/src/lib/shared/scriptcommand.cpp
new file mode 100644
index 0000000000..5261562bdd
--- /dev/null
+++ b/tools/designer/src/lib/shared/scriptcommand.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scriptcommand_p.h"
+#include "metadatabase_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ScriptCommand::ScriptCommand(QDesignerFormWindowInterface *formWindow) :
+ QDesignerFormWindowCommand(QCoreApplication::translate("Command", "Change script"), formWindow)
+{
+}
+
+bool ScriptCommand::init(const ObjectList &list, const QString &script)
+{
+ MetaDataBase *metaDataBase = qobject_cast<MetaDataBase*>(formWindow()->core()->metaDataBase());
+ if (!metaDataBase)
+ return false;
+
+ // Save old values
+ m_oldValues.clear();
+ foreach (QObject *obj, list) {
+ const MetaDataBaseItem* item = metaDataBase->metaDataBaseItem(obj);
+ if (!item)
+ return false;
+ m_oldValues.push_back(ObjectScriptPair(obj, item->script()));
+ }
+ m_script = script;
+ return true;
+}
+
+void ScriptCommand::redo()
+{
+ MetaDataBase *metaDataBase = qobject_cast<MetaDataBase*>(formWindow()->core()->metaDataBase());
+ Q_ASSERT(metaDataBase);
+
+ ObjectScriptList::const_iterator cend = m_oldValues.constEnd();
+ for (ObjectScriptList::const_iterator it = m_oldValues.constBegin();it != cend; ++it ) {
+ if (it->first)
+ metaDataBase->metaDataBaseItem(it->first)->setScript(m_script);
+ }
+}
+
+void ScriptCommand::undo()
+{
+ MetaDataBase *metaDataBase = qobject_cast<MetaDataBase*>(formWindow()->core()->metaDataBase());
+ Q_ASSERT(metaDataBase);
+
+ ObjectScriptList::const_iterator cend = m_oldValues.constEnd();
+ for (ObjectScriptList::const_iterator it = m_oldValues.constBegin();it != cend; ++it ) {
+ if (it->first)
+ metaDataBase->metaDataBaseItem(it->first)->setScript(it->second);
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/scriptcommand_p.h b/tools/designer/src/lib/shared/scriptcommand_p.h
new file mode 100644
index 0000000000..45cc588ea0
--- /dev/null
+++ b/tools/designer/src/lib/shared/scriptcommand_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_SCRIPTCOMMAND_H
+#define QDESIGNER_SCRIPTCOMMAND_H
+
+#include "qdesigner_formwindowcommand_p.h"
+
+#include <QtCore/QPair>
+#include <QtCore/QList>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT ScriptCommand: public QDesignerFormWindowCommand
+{
+ ScriptCommand(const ScriptCommand &);
+ ScriptCommand& operator=(const ScriptCommand &);
+
+public:
+ explicit ScriptCommand(QDesignerFormWindowInterface *formWindow);
+
+ typedef QList<QObject *> ObjectList;
+ bool init(const ObjectList &list, const QString &script);
+
+ virtual void redo();
+ virtual void undo();
+
+private:
+ typedef QPair<QPointer<QObject>, QString> ObjectScriptPair;
+ typedef QList<ObjectScriptPair> ObjectScriptList;
+ ObjectScriptList m_oldValues;
+ QString m_script;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // QDESIGNER_SCRIPTCOMMAND_H
diff --git a/tools/designer/src/lib/shared/scriptdialog.cpp b/tools/designer/src/lib/shared/scriptdialog.cpp
new file mode 100644
index 0000000000..616f0c9659
--- /dev/null
+++ b/tools/designer/src/lib/shared/scriptdialog.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ScriptDialog
+*/
+
+#include "scriptdialog_p.h"
+#include "qscripthighlighter_p.h"
+
+#include <abstractdialoggui_p.h>
+
+#include <QtGui/QTextEdit>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QMessageBox>
+#include <QtScript/QScriptEngine>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ // ScriptDialog
+ ScriptDialog::ScriptDialog(QDesignerDialogGuiInterface *m_dialogGui, QWidget *parent) :
+ QDialog(parent),
+ m_dialogGui(m_dialogGui),
+ m_textEdit(new QTextEdit)
+ {
+ setWindowTitle(tr("Edit script"));
+ setModal(true);
+
+ QVBoxLayout *vboxLayout = new QVBoxLayout(this);
+
+ const QString textHelp = tr("\
+<html>Enter a Qt Script snippet to be executed while loading the form.<br>\
+The widget and its children are accessible via the \
+variables <i>widget</i> and <i>childWidgets</i>, respectively.");
+ m_textEdit->setToolTip(textHelp);
+ m_textEdit->setWhatsThis(textHelp);
+ m_textEdit->setMinimumSize(QSize(600, 400));
+ vboxLayout->addWidget(m_textEdit);
+ new QScriptHighlighter(m_textEdit->document());
+ // button box
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ connect(buttonBox , SIGNAL(rejected()), this, SLOT(reject()));
+ connect(buttonBox , SIGNAL(accepted()), this, SLOT(slotAccept()));
+ vboxLayout->addWidget(buttonBox);
+ }
+
+ bool ScriptDialog::editScript(QString &script)
+ {
+ m_textEdit->setText(script);
+ if (exec() != Accepted)
+ return false;
+
+ script = trimmedScript();
+ return true;
+ }
+
+ void ScriptDialog::slotAccept()
+ {
+ if (checkScript())
+ accept();
+ }
+
+ QString ScriptDialog::trimmedScript() const
+ {
+ // Ensure a single newline
+ QString rc = m_textEdit->toPlainText().trimmed();
+ if (!rc.isEmpty())
+ rc += QLatin1Char('\n');
+ return rc;
+ }
+
+ bool ScriptDialog::checkScript()
+ {
+ const QString script = trimmedScript();
+ if (script.isEmpty())
+ return true;
+ QScriptEngine scriptEngine;
+ if (scriptEngine.canEvaluate(script))
+ return true;
+ m_dialogGui->message(this, QDesignerDialogGuiInterface::ScriptDialogMessage, QMessageBox::Warning,
+ windowTitle(), tr("Syntax error"), QMessageBox::Ok);
+ return false;
+ }
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/scriptdialog_p.h b/tools/designer/src/lib/shared/scriptdialog_p.h
new file mode 100644
index 0000000000..418cc1e604
--- /dev/null
+++ b/tools/designer/src/lib/shared/scriptdialog_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SCRIPTDIALOG_H
+#define SCRIPTDIALOG_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerDialogGuiInterface;
+
+class QTextEdit;
+
+namespace qdesigner_internal {
+
+ // Dialog for showing script errors
+ class QDESIGNER_SHARED_EXPORT ScriptDialog : public QDialog {
+ Q_OBJECT
+
+ public:
+ explicit ScriptDialog(QDesignerDialogGuiInterface *dialogGui, QWidget *parent);
+ bool editScript(QString &script);
+
+ private slots:
+ void slotAccept();
+
+ private:
+ QString trimmedScript() const;
+ bool checkScript();
+
+ QDesignerDialogGuiInterface *m_dialogGui;
+ QTextEdit *m_textEdit;
+ };
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SCRIPTDIALOG_H
diff --git a/tools/designer/src/lib/shared/scripterrordialog.cpp b/tools/designer/src/lib/shared/scripterrordialog.cpp
new file mode 100644
index 0000000000..c4a7e0792e
--- /dev/null
+++ b/tools/designer/src/lib/shared/scripterrordialog.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::ScriptErrorDialog
+*/
+
+#include "scripterrordialog_p.h"
+
+#include <QtGui/QTextEdit>
+#include <QtGui/QTextCursor>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPen>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+static void formatError(const QFormScriptRunner::Error &error,
+ QTextCursor &cursor)
+{
+ const QTextCharFormat oldFormat = cursor.charFormat();
+ // Message
+ cursor.insertText(QCoreApplication::translate("ScriptErrorDialog", "An error occurred while running the scripts for \"%1\":\n").arg(error.objectName));
+
+ QTextCharFormat format(oldFormat);
+
+ // verbatim listing
+ format.setFontFamily(QLatin1String("Courier"));
+ cursor.insertText(error.script, format);
+
+ const QString newLine(QLatin1Char('\n'));
+
+ cursor.insertText(newLine);
+
+ // red error
+ format = oldFormat;
+ format.setTextOutline(QPen(Qt::red));
+ cursor.insertText(error.errorMessage, format);
+ cursor.insertText(newLine);
+ cursor.setCharFormat (oldFormat);
+}
+
+namespace qdesigner_internal {
+
+ // ScriptErrorDialog
+ ScriptErrorDialog::ScriptErrorDialog(const Errors& errors, QWidget *parent) :
+ QDialog(parent),
+ m_textEdit(new QTextEdit)
+ {
+ setWindowTitle(tr("Script errors"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setModal(true);
+
+ QVBoxLayout *vboxLayout = new QVBoxLayout(this);
+
+ m_textEdit->setReadOnly(true);
+ m_textEdit->setMinimumSize(QSize(600, 400));
+ vboxLayout->addWidget(m_textEdit);
+ // button box
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
+ connect(buttonBox , SIGNAL(rejected()), this, SLOT(reject()));
+ vboxLayout->addWidget(buttonBox);
+
+ // Generate text
+ QTextCursor cursor = m_textEdit->textCursor();
+ cursor.movePosition (QTextCursor::End);
+ foreach (const QFormScriptRunner::Error error, errors)
+ formatError(error, cursor);
+ }
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/scripterrordialog_p.h b/tools/designer/src/lib/shared/scripterrordialog_p.h
new file mode 100644
index 0000000000..2a8b89a55f
--- /dev/null
+++ b/tools/designer/src/lib/shared/scripterrordialog_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SCRIPTERRORDIALOG_H
+#define SCRIPTERRORDIALOG_H
+
+#include "shared_global_p.h"
+#include "formscriptrunner_p.h"
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+
+namespace qdesigner_internal {
+
+ // Dialog for showing script errors
+ class QDESIGNER_SHARED_EXPORT ScriptErrorDialog : public QDialog {
+ Q_OBJECT
+
+ public:
+ typedef QFormScriptRunner::Errors Errors;
+ ScriptErrorDialog(const Errors& errors, QWidget *parent);
+
+ private:
+ QTextEdit *m_textEdit;
+
+ };
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SCRIPTERRORDIALOG_H
diff --git a/tools/designer/src/lib/shared/selectsignaldialog.ui b/tools/designer/src/lib/shared/selectsignaldialog.ui
new file mode 100644
index 0000000000..99387dd2a5
--- /dev/null
+++ b/tools/designer/src/lib/shared/selectsignaldialog.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SelectSignalDialog</class>
+ <widget class="QDialog" name="SelectSignalDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>514</width>
+ <height>183</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Go to slot</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Select signal</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QTreeWidget" name="signalList">
+ <property name="sortingEnabled">
+ <bool>false</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ <column>
+ <property name="text">
+ <string>signal</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>class</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>SelectSignalDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>257</x>
+ <y>335</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>SelectSignalDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>325</x>
+ <y>335</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/shared.pri b/tools/designer/src/lib/shared/shared.pri
new file mode 100644
index 0000000000..8ed051a5a2
--- /dev/null
+++ b/tools/designer/src/lib/shared/shared.pri
@@ -0,0 +1,189 @@
+
+INCLUDEPATH += $$PWD
+QT += script
+
+include($$QT_SOURCE_TREE/tools/shared/qtpropertybrowser/qtpropertybrowser.pri)
+include($$QT_SOURCE_TREE/tools/shared/deviceskin/deviceskin.pri)
+include($$QT_SOURCE_TREE/src/tools/rcc/rcc.pri)
+include($$QT_SOURCE_TREE/tools/shared/findwidget/findwidget.pri)
+include($$QT_SOURCE_TREE/tools/shared/qtgradienteditor/qtgradienteditor.pri)
+
+# Input
+FORMS += $$PWD/addlinkdialog.ui \
+ $$PWD/orderdialog.ui \
+ $$PWD/newactiondialog.ui \
+ $$PWD/gridpanel.ui \
+ $$PWD/signalslotdialog.ui \
+ $$PWD/previewconfigurationwidget.ui \
+ $$PWD/qtresourceeditordialog.ui \
+ $$PWD/newformwidget.ui \
+ $$PWD/selectsignaldialog.ui \
+ $$PWD/formlayoutrowdialog.ui \
+ $$PWD/plugindialog.ui
+
+HEADERS += \
+ $$PWD/shared_global_p.h \
+ $$PWD/spacer_widget_p.h \
+ $$PWD/layoutinfo_p.h \
+ $$PWD/layout_p.h \
+ $$PWD/connectionedit_p.h \
+ $$PWD/pluginmanager_p.h \
+ $$PWD/metadatabase_p.h \
+ $$PWD/qdesigner_formeditorcommand_p.h \
+ $$PWD/qdesigner_formwindowcommand_p.h \
+ $$PWD/qdesigner_command_p.h \
+ $$PWD/morphmenu_p.h \
+ $$PWD/qdesigner_command2_p.h \
+ $$PWD/qdesigner_formbuilder_p.h \
+ $$PWD/qdesigner_taskmenu_p.h \
+ $$PWD/formlayoutmenu_p.h \
+ $$PWD/qdesigner_widget_p.h \
+ $$PWD/qdesigner_propertysheet_p.h \
+ $$PWD/qdesigner_membersheet_p.h \
+ $$PWD/qdesigner_propertyeditor_p.h \
+ $$PWD/qdesigner_objectinspector_p.h \
+ $$PWD/qdesigner_integration_p.h \
+ $$PWD/invisible_widget_p.h \
+ $$PWD/qlayout_widget_p.h \
+ $$PWD/sheet_delegate_p.h \
+ $$PWD/qdesigner_stackedbox_p.h \
+ $$PWD/qdesigner_tabwidget_p.h \
+ $$PWD/qdesigner_dockwidget_p.h \
+ $$PWD/qdesigner_toolbox_p.h \
+ $$PWD/qdesigner_dnditem_p.h \
+ $$PWD/qsimpleresource_p.h \
+ $$PWD/widgetfactory_p.h \
+ $$PWD/widgetdatabase_p.h \
+ $$PWD/qdesigner_promotion_p.h \
+ $$PWD/qdesigner_introspection_p.h \
+ $$PWD/promotionmodel_p.h \
+ $$PWD/qdesigner_promotiondialog_p.h \
+ $$PWD/iconloader_p.h \
+ $$PWD/richtexteditor_p.h \
+ $$PWD/plaintexteditor_p.h \
+ $$PWD/actioneditor_p.h \
+ $$PWD/actionrepository_p.h \
+ $$PWD/qdesigner_toolbar_p.h \
+ $$PWD/qdesigner_menubar_p.h \
+ $$PWD/qdesigner_menu_p.h \
+ $$PWD/actionprovider_p.h \
+ $$PWD/orderdialog_p.h \
+ $$PWD/newactiondialog_p.h \
+ $$PWD/stylesheeteditor_p.h \
+ $$PWD/csshighlighter_p.h \
+ $$PWD/shared_enums_p.h \
+ $$PWD/textpropertyeditor_p.h \
+ $$PWD/propertylineedit_p.h \
+ $$PWD/promotiontaskmenu_p.h \
+ $$PWD/scripterrordialog_p.h \
+ $$PWD/scriptcommand_p.h \
+ $$PWD/scriptdialog_p.h \
+ $$PWD/qscripthighlighter_p.h \
+ $$PWD/gridpanel_p.h \
+ $$PWD/grid_p.h \
+ $$PWD/formwindowbase_p.h \
+ $$PWD/qdesigner_utils_p.h \
+ $$PWD/qdesigner_widgetbox_p.h \
+ $$PWD/signalslotdialog_p.h \
+ $$PWD/extensionfactory_p.h \
+ $$PWD/dialoggui_p.h \
+ $$PWD/deviceprofile_p.h \
+ $$PWD/zoomwidget_p.h \
+ $$PWD/previewmanager_p.h \
+ $$PWD/previewconfigurationwidget_p.h \
+ $$PWD/codedialog_p.h \
+ $$PWD/qtresourceeditordialog_p.h \
+ $$PWD/qtresourcemodel_p.h \
+ $$PWD/qtresourceview_p.h \
+ $$PWD/iconselector_p.h \
+ $$PWD/htmlhighlighter_p.h \
+ $$PWD/qdesigner_widgetitem_p.h \
+ $$PWD/qdesigner_qsettings_p.h \
+ $$PWD/qdesigner_formwindowmanager_p.h \
+ $$PWD/shared_settings_p.h \
+ $$PWD/newformwidget_p.h \
+ $$PWD/filterwidget_p.h \
+ $$PWD/plugindialog_p.h
+
+SOURCES += \
+ $$PWD/spacer_widget.cpp \
+ $$PWD/layoutinfo.cpp \
+ $$PWD/layout.cpp \
+ $$PWD/connectionedit.cpp \
+ $$PWD/pluginmanager.cpp \
+ $$PWD/qdesigner_formwindowcommand.cpp \
+ $$PWD/qdesigner_formeditorcommand.cpp \
+ $$PWD/qdesigner_command.cpp \
+ $$PWD/morphmenu.cpp \
+ $$PWD/qdesigner_command2.cpp \
+ $$PWD/qdesigner_propertycommand.cpp \
+ $$PWD/qdesigner_formbuilder.cpp \
+ $$PWD/qdesigner_taskmenu.cpp \
+ $$PWD/formlayoutmenu.cpp \
+ $$PWD/qdesigner_widget.cpp \
+ $$PWD/qdesigner_dockwidget.cpp \
+ $$PWD/qdesigner_propertysheet.cpp \
+ $$PWD/qdesigner_membersheet.cpp \
+ $$PWD/qdesigner_propertyeditor.cpp \
+ $$PWD/qdesigner_objectinspector.cpp \
+ $$PWD/qdesigner_integration.cpp \
+ $$PWD/qdesigner_dnditem.cpp \
+ $$PWD/qsimpleresource.cpp \
+ $$PWD/invisible_widget.cpp \
+ $$PWD/qlayout_widget.cpp \
+ $$PWD/sheet_delegate.cpp \
+ $$PWD/metadatabase.cpp \
+ $$PWD/qdesigner_stackedbox.cpp \
+ $$PWD/qdesigner_tabwidget.cpp \
+ $$PWD/qdesigner_toolbox.cpp \
+ $$PWD/widgetfactory.cpp \
+ $$PWD/widgetdatabase.cpp \
+ $$PWD/qdesigner_promotion.cpp \
+ $$PWD/qdesigner_introspection.cpp \
+ $$PWD/promotionmodel.cpp \
+ $$PWD/qdesigner_promotiondialog.cpp \
+ $$PWD/richtexteditor.cpp \
+ $$PWD/plaintexteditor.cpp \
+ $$PWD/actioneditor.cpp \
+ $$PWD/actionrepository.cpp \
+ $$PWD/qdesigner_toolbar.cpp \
+ $$PWD/qdesigner_menubar.cpp \
+ $$PWD/qdesigner_menu.cpp \
+ $$PWD/orderdialog.cpp \
+ $$PWD/newactiondialog.cpp \
+ $$PWD/stylesheeteditor.cpp \
+ $$PWD/csshighlighter.cpp \
+ $$PWD/textpropertyeditor.cpp \
+ $$PWD/propertylineedit.cpp \
+ $$PWD/promotiontaskmenu.cpp \
+ $$PWD/scripterrordialog.cpp \
+ $$PWD/scriptcommand.cpp \
+ $$PWD/scriptdialog.cpp \
+ $$PWD/qscripthighlighter.cpp\
+ $$PWD/gridpanel.cpp \
+ $$PWD/grid.cpp \
+ $$PWD/formwindowbase.cpp \
+ $$PWD/qdesigner_utils.cpp \
+ $$PWD/qdesigner_widgetbox.cpp \
+ $$PWD/iconloader.cpp \
+ $$PWD/signalslotdialog.cpp \
+ $$PWD/dialoggui.cpp \
+ $$PWD/deviceprofile.cpp \
+ $$PWD/zoomwidget.cpp \
+ $$PWD/previewmanager.cpp \
+ $$PWD/previewconfigurationwidget.cpp \
+ $$PWD/codedialog.cpp \
+ $$PWD/qtresourceeditordialog.cpp \
+ $$PWD/qtresourcemodel.cpp \
+ $$PWD/qtresourceview.cpp \
+ $$PWD/iconselector.cpp \
+ $$PWD/htmlhighlighter.cpp \
+ $$PWD/qdesigner_widgetitem.cpp \
+ $$PWD/qdesigner_qsettings.cpp \
+ $$PWD/qdesigner_formwindowmanager.cpp \
+ $$PWD/shared_settings.cpp \
+ $$PWD/newformwidget.cpp \
+ $$PWD/filterwidget.cpp \
+ $$PWD/plugindialog.cpp
+
+RESOURCES += $$PWD/shared.qrc
diff --git a/tools/designer/src/lib/shared/shared.qrc b/tools/designer/src/lib/shared/shared.qrc
new file mode 100644
index 0000000000..81be8076d2
--- /dev/null
+++ b/tools/designer/src/lib/shared/shared.qrc
@@ -0,0 +1,20 @@
+<RCC>
+ <qresource prefix="/trolltech/designer">
+ <file>defaultgradients.xml</file>
+ <!-- Templates -->
+ <file>templates/forms/Dialog_with_Buttons_Bottom.ui</file>
+ <file>templates/forms/240x320/Dialog_with_Buttons_Bottom.ui</file>
+ <file>templates/forms/320x240/Dialog_with_Buttons_Bottom.ui</file>
+ <file>templates/forms/480x640/Dialog_with_Buttons_Bottom.ui</file>
+ <file>templates/forms/640x480/Dialog_with_Buttons_Bottom.ui</file>
+ <file>templates/forms/Dialog_with_Buttons_Right.ui</file>
+ <file>templates/forms/240x320/Dialog_with_Buttons_Right.ui</file>
+ <file>templates/forms/320x240/Dialog_with_Buttons_Right.ui</file>
+ <file>templates/forms/480x640/Dialog_with_Buttons_Right.ui</file>
+ <file>templates/forms/640x480/Dialog_with_Buttons_Right.ui</file>
+ <file>templates/forms/Dialog_without_Buttons.ui</file>
+ <file>templates/forms/Widget.ui</file>
+ <file>templates/forms/Main_Window.ui</file>
+ </qresource>
+</RCC>
+
diff --git a/tools/designer/src/lib/shared/shared_enums_p.h b/tools/designer/src/lib/shared/shared_enums_p.h
new file mode 100644
index 0000000000..838b9d08fc
--- /dev/null
+++ b/tools/designer/src/lib/shared/shared_enums_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SHAREDENUMS_H
+#define SHAREDENUMS_H
+
+#include "shared_global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ // Validation mode of text property line edits
+ enum TextPropertyValidationMode {
+ // Allow for multiline editing using literal "\n".
+ ValidationMultiLine,
+ // Allow for HTML rich text including multiline editing using literal "\n".
+ ValidationRichText,
+ // Validate a stylesheet
+ ValidationStyleSheet,
+ // Single line mode, suppresses newlines
+ ValidationSingleLine,
+ // Allow only for identifier characters
+ ValidationObjectName,
+ // Allow only for identifier characters and colons
+ ValidationObjectNameScope,
+ // URL
+ ValidationURL
+ };
+
+ // Container types
+ enum ContainerType {
+ // A container with pages, at least one of which one must always be present (for example, QTabWidget)
+ PageContainer,
+ // Mdi type container. All pages may be deleted, no concept of page order
+ MdiContainer,
+ // Wizard container
+ WizardContainer
+ };
+
+ enum AuxiliaryItemDataRoles {
+ // item->flags while being edited
+ ItemFlagsShadowRole = 0x13370551
+ };
+
+}
+
+QT_END_NAMESPACE
+
+#endif // SHAREDENUMS_H
diff --git a/tools/designer/src/lib/shared/shared_global_p.h b/tools/designer/src/lib/shared/shared_global_p.h
new file mode 100644
index 0000000000..277472ca45
--- /dev/null
+++ b/tools/designer/src/lib/shared/shared_global_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SHARED_GLOBAL_H
+#define SHARED_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef QT_DESIGNER_STATIC
+#define QDESIGNER_SHARED_EXTERN
+#define QDESIGNER_SHARED_IMPORT
+#else
+#define QDESIGNER_SHARED_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_SHARED_IMPORT Q_DECL_IMPORT
+#endif
+
+#ifndef QT_NO_SHARED_EXPORT
+# ifdef QDESIGNER_SHARED_LIBRARY
+# define QDESIGNER_SHARED_EXPORT QDESIGNER_SHARED_EXTERN
+# else
+# define QDESIGNER_SHARED_EXPORT QDESIGNER_SHARED_IMPORT
+# endif
+#else
+# define QDESIGNER_SHARED_EXPORT
+#endif
+
+#endif // SHARED_GLOBAL_H
diff --git a/tools/designer/src/lib/shared/shared_settings.cpp b/tools/designer/src/lib/shared/shared_settings.cpp
new file mode 100644
index 0000000000..c97dd3b054
--- /dev/null
+++ b/tools/designer/src/lib/shared/shared_settings.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shared_settings_p.h"
+#include "grid_p.h"
+#include "previewmanager_p.h"
+#include "qdesigner_utils_p.h"
+#include <QtDesigner/abstractformeditor.h>
+#include <QtDesigner/private/abstractsettings_p.h>
+#include <QtCore/QStringList>
+#include <QtCore/QDir>
+#include <QtCore/QVariantMap>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QSize>
+
+QT_BEGIN_NAMESPACE
+
+static const char *designerPath = "/.designer";
+static const char *defaultGridKey = "defaultGrid";
+static const char *previewKey = "Preview";
+static const char *enabledKey = "Enabled";
+static const char *userDeviceSkinsKey= "UserDeviceSkins";
+static const char *zoomKey = "zoom";
+static const char *zoomEnabledKey = "zoomEnabled";
+static const char *deviceProfileIndexKey = "DeviceProfileIndex";
+static const char *deviceProfilesKey = "DeviceProfiles";
+static const char *formTemplatePathsKey = "FormTemplatePaths";
+static const char *formTemplateKey = "FormTemplate";
+static const char *newFormSizeKey = "NewFormSize";
+
+using namespace qdesigner_internal;
+
+static bool checkTemplatePath(const QString &path, bool create)
+{
+ QDir current(QDir::current());
+ if (current.exists(path))
+ return true;
+
+ if (!create)
+ return false;
+
+ if (current.mkpath(path))
+ return true;
+
+ qdesigner_internal::designerWarning(QCoreApplication::translate("QDesignerSharedSettings", "The template path %1 could not be created.").arg(path));
+ return false;
+}
+
+namespace qdesigner_internal {
+
+QDesignerSharedSettings::QDesignerSharedSettings(QDesignerFormEditorInterface *core)
+ : m_settings(core->settingsManager())
+{
+}
+
+Grid QDesignerSharedSettings::defaultGrid() const
+{
+ Grid grid;
+ const QVariantMap defaultGridMap
+ = m_settings->value(QLatin1String(defaultGridKey), QVariantMap()).toMap();
+ if (!defaultGridMap.empty())
+ grid.fromVariantMap(defaultGridMap);
+ return grid;
+}
+
+void QDesignerSharedSettings::setDefaultGrid(const Grid &grid)
+{
+ m_settings->setValue(QLatin1String(defaultGridKey), grid.toVariantMap());
+}
+
+const QStringList &QDesignerSharedSettings::defaultFormTemplatePaths()
+{
+ static QStringList rc;
+ if (rc.empty()) {
+ // Ensure default form template paths
+ const QString templatePath = QLatin1String("/templates");
+ // home
+ QString path = QDir::homePath();
+ path += QLatin1String(designerPath);
+ path += templatePath;
+ if (checkTemplatePath(path, true))
+ rc += path;
+
+ // designer/bin: Might be owned by root in some installations, do not force it.
+ path = qApp->applicationDirPath();
+ path += templatePath;
+ if (checkTemplatePath(path, false))
+ rc += path;
+ }
+ return rc;
+}
+
+QStringList QDesignerSharedSettings::formTemplatePaths() const
+{
+ return m_settings->value(QLatin1String(formTemplatePathsKey),
+ defaultFormTemplatePaths()).toStringList();
+}
+
+void QDesignerSharedSettings::setFormTemplatePaths(const QStringList &paths)
+{
+ m_settings->setValue(QLatin1String(formTemplatePathsKey), paths);
+}
+
+QString QDesignerSharedSettings::formTemplate() const
+{
+ return m_settings->value(QLatin1String(formTemplateKey)).toString();
+}
+
+void QDesignerSharedSettings::setFormTemplate(const QString &t)
+{
+ m_settings->setValue(QLatin1String(formTemplateKey), t);
+}
+
+void QDesignerSharedSettings::setAdditionalFormTemplatePaths(const QStringList &additionalPaths)
+{
+ // merge template paths
+ QStringList templatePaths = defaultFormTemplatePaths();
+ templatePaths += additionalPaths;
+ setFormTemplatePaths(templatePaths);
+}
+
+QStringList QDesignerSharedSettings::additionalFormTemplatePaths() const
+{
+ // get template paths excluding internal ones
+ QStringList rc = formTemplatePaths();
+ foreach (QString internalTemplatePath, defaultFormTemplatePaths()) {
+ const int index = rc.indexOf(internalTemplatePath);
+ if (index != -1)
+ rc.removeAt(index);
+ }
+ return rc;
+}
+
+QSize QDesignerSharedSettings::newFormSize() const
+{
+ return m_settings->value(QLatin1String(newFormSizeKey), QSize(0, 0)).toSize();
+}
+
+void QDesignerSharedSettings::setNewFormSize(const QSize &s)
+{
+ if (s.isNull()) {
+ m_settings->remove(QLatin1String(newFormSizeKey));
+ } else {
+ m_settings->setValue(QLatin1String(newFormSizeKey), s);
+ }
+}
+
+
+PreviewConfiguration QDesignerSharedSettings::customPreviewConfiguration() const
+{
+ PreviewConfiguration configuration;
+ configuration.fromSettings(QLatin1String(previewKey), m_settings);
+ return configuration;
+}
+
+void QDesignerSharedSettings::setCustomPreviewConfiguration(const PreviewConfiguration &configuration)
+{
+ configuration.toSettings(QLatin1String(previewKey), m_settings);
+}
+
+bool QDesignerSharedSettings::isCustomPreviewConfigurationEnabled() const
+{
+ m_settings->beginGroup(QLatin1String(previewKey));
+ bool isEnabled = m_settings->value(QLatin1String(enabledKey), false).toBool();
+ m_settings->endGroup();
+ return isEnabled;
+}
+
+void QDesignerSharedSettings::setCustomPreviewConfigurationEnabled(bool enabled)
+{
+ m_settings->beginGroup(QLatin1String(previewKey));
+ m_settings->setValue(QLatin1String(enabledKey), enabled);
+ m_settings->endGroup();
+}
+
+QStringList QDesignerSharedSettings::userDeviceSkins() const
+{
+ m_settings->beginGroup(QLatin1String(previewKey));
+ QStringList userDeviceSkins
+ = m_settings->value(QLatin1String(userDeviceSkinsKey), QStringList()).toStringList();
+ m_settings->endGroup();
+ return userDeviceSkins;
+}
+
+void QDesignerSharedSettings::setUserDeviceSkins(const QStringList &userDeviceSkins)
+{
+ m_settings->beginGroup(QLatin1String(previewKey));
+ m_settings->setValue(QLatin1String(userDeviceSkinsKey), userDeviceSkins);
+ m_settings->endGroup();
+}
+
+int QDesignerSharedSettings::zoom() const
+{
+ return m_settings->value(QLatin1String(zoomKey), 100).toInt();
+}
+
+void QDesignerSharedSettings::setZoom(int z)
+{
+ m_settings->setValue(QLatin1String(zoomKey), QVariant(z));
+}
+
+bool QDesignerSharedSettings::zoomEnabled() const
+{
+ return m_settings->value(QLatin1String(zoomEnabledKey), false).toBool();
+}
+
+void QDesignerSharedSettings::setZoomEnabled(bool v)
+{
+ m_settings->setValue(QLatin1String(zoomEnabledKey), v);
+}
+
+DeviceProfile QDesignerSharedSettings::currentDeviceProfile() const
+{
+ return deviceProfileAt(currentDeviceProfileIndex());
+}
+
+void QDesignerSharedSettings::setCurrentDeviceProfileIndex(int i)
+{
+ m_settings->setValue(QLatin1String(deviceProfileIndexKey), i);
+}
+
+int QDesignerSharedSettings::currentDeviceProfileIndex() const
+{
+ return m_settings->value(QLatin1String(deviceProfileIndexKey), -1).toInt();
+}
+
+static inline QString msgWarnDeviceProfileXml(const QString &msg)
+{
+ return QCoreApplication::translate("QDesignerSharedSettings", "An error has been encountered while parsing device profile XML: %1").arg(msg);
+}
+
+DeviceProfile QDesignerSharedSettings::deviceProfileAt(int idx) const
+{
+ DeviceProfile rc;
+ if (idx < 0)
+ return rc;
+ const QStringList xmls = deviceProfileXml();
+ if (idx >= xmls.size())
+ return rc;
+ QString errorMessage;
+ if (!rc.fromXml(xmls.at(idx), &errorMessage)) {
+ rc.clear();
+ designerWarning(msgWarnDeviceProfileXml(errorMessage));
+ }
+ return rc;
+}
+
+QStringList QDesignerSharedSettings::deviceProfileXml() const
+{
+ return m_settings->value(QLatin1String(deviceProfilesKey), QStringList()).toStringList();
+}
+
+QDesignerSharedSettings::DeviceProfileList QDesignerSharedSettings::deviceProfiles() const
+{
+ DeviceProfileList rc;
+ const QStringList xmls = deviceProfileXml();
+ if (xmls.empty())
+ return rc;
+ // De-serialize
+ QString errorMessage;
+ DeviceProfile dp;
+ const QStringList::const_iterator scend = xmls.constEnd();
+ for (QStringList::const_iterator it = xmls.constBegin(); it != scend; ++it) {
+ if (dp.fromXml(*it, &errorMessage)) {
+ rc.push_back(dp);
+ } else {
+ designerWarning(msgWarnDeviceProfileXml(errorMessage));
+ }
+ }
+ return rc;
+}
+
+void QDesignerSharedSettings::setDeviceProfiles(const DeviceProfileList &dp)
+{
+ QStringList l;
+ const DeviceProfileList::const_iterator dcend = dp.constEnd();
+ for (DeviceProfileList::const_iterator it = dp.constBegin(); it != dcend; ++it)
+ l.push_back(it->toXml());
+ m_settings->setValue(QLatin1String(deviceProfilesKey), l);
+}
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/shared_settings_p.h b/tools/designer/src/lib/shared/shared_settings_p.h
new file mode 100644
index 0000000000..c021b00170
--- /dev/null
+++ b/tools/designer/src/lib/shared/shared_settings_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef SHARED_SETTINGS_H
+#define SHARED_SETTINGS_H
+
+#include "shared_global_p.h"
+#include "deviceprofile_p.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerSettingsInterface;
+
+class QStringList;
+class QSize;
+
+namespace qdesigner_internal {
+class Grid;
+class PreviewConfiguration;
+}
+
+/*!
+ Auxiliary methods to store/retrieve settings
+ */
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT QDesignerSharedSettings {
+public:
+ typedef QList<DeviceProfile> DeviceProfileList;
+
+ explicit QDesignerSharedSettings(QDesignerFormEditorInterface *core);
+
+ Grid defaultGrid() const;
+ void setDefaultGrid(const Grid &grid);
+
+ QStringList formTemplatePaths() const;
+ void setFormTemplatePaths(const QStringList &paths);
+
+ void setAdditionalFormTemplatePaths(const QStringList &additionalPaths);
+ QStringList additionalFormTemplatePaths() const;
+
+ QString formTemplate() const;
+ void setFormTemplate(const QString &t);
+
+ QSize newFormSize() const;
+ void setNewFormSize(const QSize &s);
+
+ // Check with isCustomPreviewConfigurationEnabled if custom or default
+ // configuration should be used.
+ PreviewConfiguration customPreviewConfiguration() const;
+ void setCustomPreviewConfiguration(const PreviewConfiguration &configuration);
+
+ bool isCustomPreviewConfigurationEnabled() const;
+ void setCustomPreviewConfigurationEnabled(bool enabled);
+
+ QStringList userDeviceSkins() const;
+ void setUserDeviceSkins(const QStringList &userDeviceSkins);
+
+ bool zoomEnabled() const;
+ void setZoomEnabled(bool v);
+
+ // Zoom in percent
+ int zoom() const;
+ void setZoom(int z);
+
+ // Embedded Design
+ DeviceProfile currentDeviceProfile() const;
+ void setCurrentDeviceProfileIndex(int i);
+ int currentDeviceProfileIndex() const;
+
+ DeviceProfile deviceProfileAt(int idx) const;
+ DeviceProfileList deviceProfiles() const;
+ void setDeviceProfiles(const DeviceProfileList &dp);
+
+ static const QStringList &defaultFormTemplatePaths();
+
+protected:
+ QDesignerSettingsInterface *settings() const { return m_settings; }
+
+private:
+ QStringList deviceProfileXml() const;
+ QDesignerSettingsInterface *m_settings;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SHARED_SETTINGS_H
diff --git a/tools/designer/src/lib/shared/sheet_delegate.cpp b/tools/designer/src/lib/shared/sheet_delegate.cpp
new file mode 100644
index 0000000000..c0722bbedd
--- /dev/null
+++ b/tools/designer/src/lib/shared/sheet_delegate.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "sheet_delegate_p.h"
+
+#include <QtCore/QAbstractItemModel>
+#include <QtGui/QTreeView>
+#include <QtGui/QStyle>
+#include <QtGui/QPainter>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+SheetDelegate::SheetDelegate(QTreeView *view, QWidget *parent)
+ : QItemDelegate(parent),
+ m_view(view)
+{
+}
+
+void SheetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ const QAbstractItemModel *model = index.model();
+ Q_ASSERT(model);
+
+ if (!model->parent(index).isValid()) {
+ // this is a top-level item.
+ QStyleOptionButton buttonOption;
+
+ buttonOption.state = option.state;
+#ifdef Q_WS_MAC
+ buttonOption.state |= QStyle::State_Raised;
+#endif
+ buttonOption.state &= ~QStyle::State_HasFocus;
+
+ buttonOption.rect = option.rect;
+ buttonOption.palette = option.palette;
+ buttonOption.features = QStyleOptionButton::None;
+ m_view->style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, m_view);
+
+ QStyleOption branchOption;
+ static const int i = 9; // ### hardcoded in qcommonstyle.cpp
+ QRect r = option.rect;
+ branchOption.rect = QRect(r.left() + i/2, r.top() + (r.height() - i)/2, i, i);
+ branchOption.palette = option.palette;
+ branchOption.state = QStyle::State_Children;
+
+ if (m_view->isExpanded(index))
+ branchOption.state |= QStyle::State_Open;
+
+ m_view->style()->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, painter, m_view);
+
+ // draw text
+ QRect textrect = QRect(r.left() + i*2, r.top(), r.width() - ((5*i)/2), r.height());
+ QString text = elidedText(option.fontMetrics, textrect.width(), Qt::ElideMiddle,
+ model->data(index, Qt::DisplayRole).toString());
+ m_view->style()->drawItemText(painter, textrect, Qt::AlignCenter,
+ option.palette, m_view->isEnabled(), text);
+
+ } else {
+ QItemDelegate::paint(painter, option, index);
+ }
+}
+
+QSize SheetDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const
+{
+ QStyleOptionViewItem option = opt;
+ QSize sz = QItemDelegate::sizeHint(opt, index) + QSize(2, 2);
+ return sz;
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/sheet_delegate_p.h b/tools/designer/src/lib/shared/sheet_delegate_p.h
new file mode 100644
index 0000000000..a3d70df1db
--- /dev/null
+++ b/tools/designer/src/lib/shared/sheet_delegate_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef SHEET_DELEGATE_H
+#define SHEET_DELEGATE_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QItemDelegate>
+#include <QtGui/QTreeView>
+
+QT_BEGIN_NAMESPACE
+
+class QTreeView;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT SheetDelegate: public QItemDelegate
+{
+ Q_OBJECT
+public:
+ SheetDelegate(QTreeView *view, QWidget *parent);
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+ virtual QSize sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const;
+
+private:
+ QTreeView *m_view;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // SHEET_DELEGATE_H
diff --git a/tools/designer/src/lib/shared/signalslotdialog.cpp b/tools/designer/src/lib/shared/signalslotdialog.cpp
new file mode 100644
index 0000000000..a23d2284f8
--- /dev/null
+++ b/tools/designer/src/lib/shared/signalslotdialog.cpp
@@ -0,0 +1,526 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "signalslotdialog_p.h"
+#include "ui_signalslotdialog.h"
+#include "metadatabase_p.h"
+#include "widgetdatabase_p.h"
+
+#include "qdesigner_formwindowcommand_p.h"
+#include "iconloader_p.h"
+
+#include <QtDesigner/QDesignerMemberSheetExtension>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+#include <abstractdialoggui_p.h>
+
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QRegExpValidator>
+#include <QtGui/QItemDelegate>
+#include <QtGui/QLineEdit>
+#include <QtGui/QApplication>
+#include <QtGui/QMessageBox>
+
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+// Regexp to match a function signature, arguments potentially
+// with namespace colons.
+static const char *signatureRegExp = "^[\\w+_]+\\(([\\w+:]\\*?,?)*\\)$";
+static const char *methodNameRegExp = "^[\\w+_]+$";
+
+static QStandardItem *createEditableItem(const QString &text)
+{
+ QStandardItem *rc = new QStandardItem(text);
+ rc->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable|Qt::ItemIsSelectable);
+ return rc;
+}
+
+static QStandardItem *createDisabledItem(const QString &text)
+{
+ QStandardItem *rc = new QStandardItem(text);
+ Qt::ItemFlags flags = rc->flags();
+ rc->setFlags(flags & ~(Qt::ItemIsEnabled|Qt::ItemIsEditable|Qt::ItemIsSelectable));
+ return rc;
+}
+
+static void fakeMethodsFromMetaDataBase(QDesignerFormEditorInterface *core, QObject *o, QStringList &slotList, QStringList &signalList)
+{
+ slotList.clear();
+ signalList.clear();
+ if (qdesigner_internal::MetaDataBase *metaDataBase = qobject_cast<qdesigner_internal::MetaDataBase *>(core->metaDataBase()))
+ if (const qdesigner_internal::MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(o)) {
+ slotList = item->fakeSlots();
+ signalList = item->fakeSignals();
+ }
+}
+
+static void fakeMethodsToMetaDataBase(QDesignerFormEditorInterface *core, QObject *o, const QStringList &slotList, const QStringList &signalList)
+{
+ if (qdesigner_internal::MetaDataBase *metaDataBase = qobject_cast<qdesigner_internal::MetaDataBase *>(core->metaDataBase())) {
+ qdesigner_internal::MetaDataBaseItem *item = metaDataBase->metaDataBaseItem(o);
+ Q_ASSERT(item);
+ item->setFakeSlots(slotList);
+ item->setFakeSignals(signalList);
+ }
+}
+
+static void existingMethodsFromMemberSheet(QDesignerFormEditorInterface *core,
+ QObject *o,
+ QStringList &slotList, QStringList &signalList)
+{
+ slotList.clear();
+ signalList.clear();
+
+ QDesignerMemberSheetExtension *msheet = qt_extension<QDesignerMemberSheetExtension*>(core->extensionManager(), o);
+ if (!msheet)
+ return;
+
+ for (int i = 0, count = msheet->count(); i < count; ++i)
+ if (msheet->isVisible(i)) {
+ if (msheet->isSlot(i))
+ slotList += msheet->signature(i);
+ else
+ if (msheet->isSignal(i))
+ signalList += msheet->signature(i);
+ }
+}
+
+namespace {
+ // Internal helper class: A Delegate that validates using RegExps and additionally checks
+ // on closing (adds missing parentheses).
+ class SignatureDelegate : public QItemDelegate {
+ public:
+ SignatureDelegate(QObject * parent = 0);
+ virtual QWidget * createEditor (QWidget * parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
+ virtual void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
+
+ private:
+ const QRegExp m_signatureRegexp;
+ const QRegExp m_methodNameRegexp;
+ };
+
+ SignatureDelegate::SignatureDelegate(QObject * parent) :
+ QItemDelegate(parent),
+ m_signatureRegexp(QLatin1String(signatureRegExp)),
+ m_methodNameRegexp(QLatin1String(methodNameRegExp))
+ {
+ Q_ASSERT(m_signatureRegexp.isValid());
+ Q_ASSERT(m_methodNameRegexp.isValid());
+ }
+
+ QWidget * SignatureDelegate::createEditor ( QWidget * parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
+ {
+ QWidget *rc = QItemDelegate::createEditor(parent, option, index);
+ QLineEdit *le = qobject_cast<QLineEdit *>(rc);
+ Q_ASSERT(le);
+ le->setValidator(new QRegExpValidator(m_signatureRegexp, le));
+ return rc;
+ }
+
+ void SignatureDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
+ {
+ QLineEdit *le = qobject_cast<QLineEdit *>(editor);
+ Q_ASSERT(le);
+ // Did the user just type a name? .. Add parentheses
+ QString signature = le->text();
+ if (!m_signatureRegexp.exactMatch(signature )) {
+ if (m_methodNameRegexp.exactMatch(signature )) {
+ signature += QLatin1String("()");
+ le->setText(signature);
+ } else {
+ return;
+ }
+ }
+ QItemDelegate::setModelData(editor, model, index);
+ }
+
+ // ------ FakeMethodMetaDBCommand: Undo Command to change fake methods in the meta DB.
+ class FakeMethodMetaDBCommand : public qdesigner_internal::QDesignerFormWindowCommand {
+
+ public:
+ explicit FakeMethodMetaDBCommand(QDesignerFormWindowInterface *formWindow);
+
+ void init(QObject *o,
+ const QStringList &oldFakeSlots, const QStringList &oldFakeSignals,
+ const QStringList &newFakeSlots, const QStringList &newFakeSignals);
+
+ virtual void undo() { fakeMethodsToMetaDataBase(core(), m_object, m_oldFakeSlots, m_oldFakeSignals); }
+ virtual void redo() { fakeMethodsToMetaDataBase(core(), m_object, m_newFakeSlots, m_newFakeSignals); }
+
+ private:
+ QObject *m_object;
+ QStringList m_oldFakeSlots;
+ QStringList m_oldFakeSignals;
+ QStringList m_newFakeSlots;
+ QStringList m_newFakeSignals;
+ };
+
+ FakeMethodMetaDBCommand::FakeMethodMetaDBCommand(QDesignerFormWindowInterface *formWindow) :
+ qdesigner_internal::QDesignerFormWindowCommand(QApplication::translate("Command", "Change signals/slots"), formWindow),
+ m_object(0)
+ {
+ }
+
+ void FakeMethodMetaDBCommand::init(QObject *o,
+ const QStringList &oldFakeSlots, const QStringList &oldFakeSignals,
+ const QStringList &newFakeSlots, const QStringList &newFakeSignals)
+ {
+ m_object = o;
+ m_oldFakeSlots = oldFakeSlots;
+ m_oldFakeSignals = oldFakeSignals;
+ m_newFakeSlots = newFakeSlots;
+ m_newFakeSignals = newFakeSignals;
+ }
+}
+
+namespace qdesigner_internal {
+
+// ------ SignalSlotDialogData
+void SignalSlotDialogData::clear()
+{
+ m_existingMethods.clear();
+ m_fakeMethods.clear();
+}
+
+// ------ SignatureModel
+SignatureModel::SignatureModel(QObject *parent) :
+ QStandardItemModel(parent)
+{
+}
+
+bool SignatureModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (role != Qt::EditRole)
+ return QStandardItemModel::setData(index, value, role);
+ // check via signal (unless it is the same), in which case we can't be bothered.
+ const QStandardItem *item = itemFromIndex(index);
+ Q_ASSERT(item);
+ const QString signature = value.toString();
+ if (item->text() == signature)
+ return true;
+
+ bool ok = true;
+ emit checkSignature(signature, &ok);
+ if (!ok)
+ return false;
+
+ return QStandardItemModel::setData(index, value, role);
+}
+
+// ------ SignaturePanel
+SignaturePanel::SignaturePanel(QObject *parent, QListView *listView, QToolButton *addButton, QToolButton *removeButton, const QString &newPrefix) :
+ QObject(parent),
+ m_newPrefix(newPrefix),
+ m_model(new SignatureModel(this)),
+ m_listView(listView),
+ m_removeButton(removeButton)
+{
+ m_removeButton->setEnabled(false);
+
+ connect(addButton, SIGNAL(clicked()), this, SLOT(slotAdd()));
+ connect(m_removeButton, SIGNAL(clicked()), this, SLOT(slotRemove()));
+
+ m_listView->setModel(m_model);
+ SignatureDelegate *delegate = new SignatureDelegate(this);
+ m_listView->setItemDelegate(delegate);
+ connect(m_model, SIGNAL(checkSignature(QString,bool*)), this, SIGNAL(checkSignature(QString,bool*)));
+
+ connect(m_listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
+ this, SLOT(slotSelectionChanged(QItemSelection, QItemSelection)));
+}
+
+void SignaturePanel::slotAdd()
+{
+ m_listView->selectionModel()->clearSelection();
+ // find unique name
+ for (int i = 1; ; i++) {
+ QString newSlot = m_newPrefix;
+ newSlot += QString::number(i); // Always add number, Avoid setting 'slot' for first entry
+ newSlot += QLatin1Char('(');
+ // check for function name independent of parameters
+ if (m_model->findItems(newSlot, Qt::MatchStartsWith, 0).empty()) {
+ newSlot += QLatin1Char(')');
+ QStandardItem * item = createEditableItem(newSlot);
+ m_model->appendRow(item);
+ const QModelIndex index = m_model->indexFromItem (item);
+ m_listView->setCurrentIndex (index);
+ m_listView->edit(index);
+ return;
+ }
+ }
+}
+
+int SignaturePanel::count(const QString &signature) const
+{
+ return m_model->findItems(signature).size();
+}
+
+void SignaturePanel::slotRemove()
+{
+ const QModelIndexList selectedIndexes = m_listView->selectionModel()->selectedIndexes ();
+ if (selectedIndexes.empty())
+ return;
+
+ closeEditor();
+ // scroll to previous
+ if (const int row = selectedIndexes.front().row())
+ m_listView->setCurrentIndex (selectedIndexes.front().sibling(row - 1, 0));
+
+ for (int i = selectedIndexes.size() - 1; i >= 0; i--)
+ qDeleteAll(m_model->takeRow(selectedIndexes[i].row()));
+}
+
+void SignaturePanel::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &)
+{
+ m_removeButton->setEnabled(!selected.indexes().empty());
+}
+
+void SignaturePanel::setData(const SignalSlotDialogData &d)
+{
+ m_model->clear();
+
+ QStandardItem *lastExisting = 0;
+ foreach(const QString &s, d.m_existingMethods) {
+ lastExisting = createDisabledItem(s);
+ m_model->appendRow(lastExisting);
+ }
+ foreach(const QString &s, d.m_fakeMethods)
+ m_model->appendRow(createEditableItem(s));
+ if (lastExisting)
+ m_listView->scrollTo(m_model->indexFromItem(lastExisting));
+}
+
+QStringList SignaturePanel::fakeMethods() const
+{
+ QStringList rc;
+ if (const int rowCount = m_model->rowCount())
+ for (int i = 0; i < rowCount; i++) {
+ const QStandardItem *item = m_model->item(i);
+ if (item->flags() & Qt::ItemIsEditable)
+ rc += item->text();
+ }
+ return rc;
+}
+
+void SignaturePanel::closeEditor()
+{
+ const QModelIndex idx = m_listView->currentIndex();
+ if (idx.isValid())
+ m_listView->closePersistentEditor(idx);
+}
+
+// ------ SignalSlotDialog
+
+SignalSlotDialog::SignalSlotDialog(QDesignerDialogGuiInterface *dialogGui, QWidget *parent, FocusMode mode) :
+ QDialog(parent),
+ m_focusMode(mode),
+ m_ui(new Ui::SignalSlotDialogClass),
+ m_dialogGui(dialogGui)
+{
+ setModal(true);
+ m_ui->setupUi(this);
+
+ const QIcon plusIcon = qdesigner_internal::createIconSet(QString::fromUtf8("plus.png"));
+ const QIcon minusIcon = qdesigner_internal::createIconSet(QString::fromUtf8("minus.png"));
+ m_ui->addSlotButton->setIcon(plusIcon);
+ m_ui->removeSlotButton->setIcon(minusIcon);
+ m_ui->addSignalButton->setIcon(plusIcon);
+ m_ui->removeSignalButton->setIcon(minusIcon);
+
+ m_slotPanel = new SignaturePanel(this, m_ui->slotListView, m_ui->addSlotButton, m_ui->removeSlotButton, QLatin1String("slot"));
+ m_signalPanel = new SignaturePanel(this, m_ui->signalListView, m_ui->addSignalButton, m_ui->removeSignalButton, QLatin1String("signal"));
+ connect(m_slotPanel, SIGNAL(checkSignature(QString,bool*)), this, SLOT(slotCheckSignature(QString,bool*)));
+ connect(m_signalPanel, SIGNAL(checkSignature(QString,bool*)), this, SLOT(slotCheckSignature(QString,bool*)));
+
+ connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ switch(m_focusMode) {
+ case FocusSlots:
+ m_ui->slotListView->setFocus(Qt::OtherFocusReason);
+ break;
+ case FocusSignals:
+ m_ui->signalListView->setFocus(Qt::OtherFocusReason);
+ break;
+ }
+}
+
+SignalSlotDialog::~SignalSlotDialog()
+{
+ delete m_ui;
+}
+
+void SignalSlotDialog::slotCheckSignature(const QString &signature, bool *ok)
+{
+ QString errorMessage;
+ do {
+ if (m_slotPanel->count(signature)) {
+ errorMessage = tr("There is already a slot with the signature '%1'.").arg(signature);
+ *ok = false;
+ break;
+ }
+ if (m_signalPanel->count(signature)) {
+ errorMessage = tr("There is already a signal with the signature '%1'.").arg(signature);
+ *ok = false;
+ break;
+ }
+ } while (false);
+ if (!*ok)
+ m_dialogGui->message(this, QDesignerDialogGuiInterface::SignalSlotDialogMessage,
+ QMessageBox::Warning, tr("%1 - Duplicate Signature").arg(windowTitle()), errorMessage, QMessageBox::Close);
+}
+
+QDialog::DialogCode SignalSlotDialog::showDialog(SignalSlotDialogData &slotData, SignalSlotDialogData &signalData)
+{
+ m_slotPanel->setData(slotData);
+ m_signalPanel->setData(signalData);
+
+ const DialogCode rc = static_cast<DialogCode>(exec());
+ if (rc == Rejected)
+ return rc;
+
+ slotData.m_fakeMethods = m_slotPanel->fakeMethods();
+ signalData.m_fakeMethods = m_signalPanel->fakeMethods();
+ return rc;
+}
+
+bool SignalSlotDialog::editMetaDataBase(QDesignerFormWindowInterface *fw, QObject *object, QWidget *parent, FocusMode mode)
+{
+ QDesignerFormEditorInterface *core = fw->core();
+ SignalSlotDialog dlg(core->dialogGui(), parent, mode);
+ dlg.setWindowTitle(tr("Signals/Slots of %1").arg(object->objectName()));
+
+ SignalSlotDialogData slotData;
+ SignalSlotDialogData signalData;
+
+ existingMethodsFromMemberSheet(core, object, slotData.m_existingMethods, signalData.m_existingMethods);
+ fakeMethodsFromMetaDataBase(core, object, slotData.m_fakeMethods, signalData.m_fakeMethods);
+
+ const QStringList oldSlots = slotData.m_fakeMethods;
+ const QStringList oldSignals = signalData.m_fakeMethods;
+
+ if (dlg.showDialog(slotData, signalData) == QDialog::Rejected)
+ return false;
+
+ if (oldSlots == slotData.m_fakeMethods && oldSignals == signalData.m_fakeMethods)
+ return false;
+
+ FakeMethodMetaDBCommand *cmd = new FakeMethodMetaDBCommand(fw);
+ cmd->init(object, oldSlots, oldSignals, slotData.m_fakeMethods, signalData.m_fakeMethods);
+ fw->commandHistory()->push(cmd);
+ return true;
+}
+
+bool SignalSlotDialog::editPromotedClass(QDesignerFormEditorInterface *core, const QString &promotedClassName, QWidget *parent, FocusMode mode)
+{
+ const int index = core->widgetDataBase()->indexOfClassName(promotedClassName);
+ if (index == -1)
+ return false;
+
+ const QString baseClassName = core->widgetDataBase()->item(index)->extends();
+ if (baseClassName.isEmpty())
+ return false;
+
+ QWidget *widget = core->widgetFactory()->createWidget(baseClassName, 0);
+ if (!widget)
+ return false;
+ const bool rc = editPromotedClass(core, promotedClassName, widget, parent, mode);
+ widget->deleteLater();
+ return rc;
+}
+
+bool SignalSlotDialog::editPromotedClass(QDesignerFormEditorInterface *core, QObject *baseObject, QWidget *parent, FocusMode mode)
+{
+ if (!baseObject->isWidgetType())
+ return false;
+
+ const QString promotedClassName = promotedCustomClassName(core, qobject_cast<QWidget*>(baseObject));
+ if (promotedClassName.isEmpty())
+ return false;
+ return editPromotedClass(core, promotedClassName, baseObject, parent, mode);
+}
+
+
+bool SignalSlotDialog::editPromotedClass(QDesignerFormEditorInterface *core, const QString &promotedClassName, QObject *object, QWidget *parent, FocusMode mode)
+{
+ WidgetDataBase *db = qobject_cast<WidgetDataBase *>(core->widgetDataBase());
+ if (!db)
+ return false;
+
+ const int index = core->widgetDataBase()->indexOfClassName(promotedClassName);
+ if (index == -1)
+ return false;
+
+ WidgetDataBaseItem* item = static_cast<WidgetDataBaseItem*>(db->item(index));
+
+ SignalSlotDialogData slotData;
+ SignalSlotDialogData signalData;
+
+ existingMethodsFromMemberSheet(core, object, slotData.m_existingMethods, signalData.m_existingMethods);
+ slotData.m_fakeMethods = item->fakeSlots();
+ signalData.m_fakeMethods = item->fakeSignals();
+
+ const QStringList oldSlots = slotData.m_fakeMethods;
+ const QStringList oldSignals = signalData.m_fakeMethods;
+
+ SignalSlotDialog dlg(core->dialogGui(), parent, mode);
+ dlg.setWindowTitle(tr("Signals/Slots of %1").arg(promotedClassName));
+
+ if (dlg.showDialog(slotData, signalData) == QDialog::Rejected)
+ return false;
+
+ if (oldSlots == slotData.m_fakeMethods && oldSignals == signalData.m_fakeMethods)
+ return false;
+
+ item->setFakeSlots(slotData.m_fakeMethods);
+ item->setFakeSignals(signalData.m_fakeMethods);
+
+ return true;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/signalslotdialog.ui b/tools/designer/src/lib/shared/signalslotdialog.ui
new file mode 100644
index 0000000000..1a8a8d9219
--- /dev/null
+++ b/tools/designer/src/lib/shared/signalslotdialog.ui
@@ -0,0 +1,129 @@
+<ui version="4.0" >
+ <class>SignalSlotDialogClass</class>
+ <widget class="QDialog" name="SignalSlotDialogClass" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>617</width>
+ <height>535</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Signals and slots</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="slotGroupBox" >
+ <property name="title" >
+ <string>Slots</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QListView" name="slotListView" />
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QToolButton" name="addSlotButton" >
+ <property name="toolTip" >
+ <string>Add</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="removeSlotButton" >
+ <property name="toolTip" >
+ <string>Delete</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="signalGroupBox" >
+ <property name="title" >
+ <string>Signals</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QListView" name="signalListView" />
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QToolButton" name="addSignalButton" >
+ <property name="toolTip" >
+ <string>Add</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="removeSignalButton" >
+ <property name="toolTip" >
+ <string>Delete</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="spacerName" stdset="0" >
+ <string/>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/lib/shared/signalslotdialog_p.h b/tools/designer/src/lib/shared/signalslotdialog_p.h
new file mode 100644
index 0000000000..434b73f867
--- /dev/null
+++ b/tools/designer/src/lib/shared/signalslotdialog_p.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef _SIGNALSLOTDIALOG_H
+#define _SIGNALSLOTDIALOG_H
+
+#include "shared_global_p.h"
+#include <QtCore/QStringList>
+#include <QtGui/QDialog>
+#include <QtGui/QStandardItemModel>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+class QDesignerFormWindowInterface;
+class QDesignerDialogGuiInterface;
+class QDesignerMemberSheet;
+class QListView;
+class QToolButton;
+class QItemSelection;
+
+namespace Ui {
+ class SignalSlotDialogClass;
+}
+
+namespace qdesigner_internal {
+
+// Dialog data
+struct SignalSlotDialogData {
+ void clear();
+ QStringList m_existingMethods;
+ QStringList m_fakeMethods;
+};
+
+// Internal helper class: A model for signatures that allows for verifying duplicates
+// (checking signals versus slots and vice versa).
+class SignatureModel : public QStandardItemModel {
+ Q_OBJECT
+
+public:
+ SignatureModel(QObject *parent = 0);
+ virtual bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+signals:
+ void checkSignature(const QString &signature, bool *ok);
+};
+
+// Internal helper class: Panel for editing method signatures. List view with validator,
+// add and remove button
+class SignaturePanel : public QObject {
+ Q_OBJECT
+
+public:
+ SignaturePanel(QObject *parent, QListView *listView, QToolButton *addButton, QToolButton *removeButton, const QString &newPrefix);
+
+ QStringList fakeMethods() const;
+ void setData(const SignalSlotDialogData &d);
+ int count(const QString &signature) const;
+
+signals:
+ void checkSignature(const QString &signature, bool *ok);
+
+private slots:
+ void slotAdd();
+ void slotRemove();
+ void slotSelectionChanged(const QItemSelection &, const QItemSelection &);
+
+private:
+ void closeEditor();
+
+ const QString m_newPrefix;
+ SignatureModel *m_model;
+ QListView *m_listView;
+ QToolButton *m_removeButton;
+};
+
+// Dialog for editing signals and slots.
+// Provides static convenience function
+// to modify fake signals and slots. They are
+// handled in 2 ways:
+// 1) For the MainContainer: Fake signals and slots are stored
+// in the meta database (per-instance)
+// 2) For promoted widgets: Fake signals and slots are stored
+// in the widget database (per-class)
+// Arguably, we could require the MainContainer to be promoted for that, too,
+// but that would require entering a header.
+
+class QDESIGNER_SHARED_EXPORT SignalSlotDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ enum FocusMode { FocusSlots, FocusSignals };
+
+ explicit SignalSlotDialog(QDesignerDialogGuiInterface *dialogGui, QWidget *parent = 0, FocusMode m = FocusSlots);
+ virtual ~SignalSlotDialog();
+
+ DialogCode showDialog(SignalSlotDialogData &slotData, SignalSlotDialogData &signalData);
+
+ // Edit fake methods stored in MetaDataBase (per instance, used for main containers)
+ static bool editMetaDataBase(QDesignerFormWindowInterface *fw, QObject *object, QWidget *parent = 0, FocusMode m = FocusSlots);
+
+ // Edit fake methods of a promoted class stored in WidgetDataBase (synthesizes a widget to obtain existing members).
+ static bool editPromotedClass(QDesignerFormEditorInterface *core, const QString &promotedClassName, QWidget *parent = 0, FocusMode m = FocusSlots);
+ // Edit fake methods of a promoted class stored in WidgetDataBase on a base class instance.
+ static bool editPromotedClass(QDesignerFormEditorInterface *core, QObject *baseObject, QWidget *parent = 0, FocusMode m = FocusSlots);
+
+private slots:
+ void slotCheckSignature(const QString &signature, bool *ok);
+
+private:
+ // Edit fake methods of a promoted class stored in WidgetDataBase using an instance of the base class.
+ static bool editPromotedClass(QDesignerFormEditorInterface *core, const QString &promotedClassName, QObject *baseObject, QWidget *parent, FocusMode m);
+
+ const FocusMode m_focusMode;
+ Ui::SignalSlotDialogClass *m_ui;
+ QDesignerDialogGuiInterface *m_dialogGui;
+ SignaturePanel *m_slotPanel;
+ SignaturePanel *m_signalPanel;
+};
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/shared/spacer_widget.cpp b/tools/designer/src/lib/shared/spacer_widget.cpp
new file mode 100644
index 0000000000..8256bf70e4
--- /dev/null
+++ b/tools/designer/src/lib/shared/spacer_widget.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "spacer_widget_p.h"
+#include "layoutinfo_p.h"
+
+#include <QtDesigner/abstractformwindow.h>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QLayout>
+#include <QtGui/QPainter>
+#include <QtGui/qevent.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+// The Spacer widget is Designer representation of QLayoutItem.
+// It uses QLayoutItem's sizeHint property as QWidget
+// sizeHint and the QLayoutItem's sizeType property as QWidget size policy.
+// If it is not within a layout, it adds a margin (m_SizeOffset) around it
+// to avoid being shrunk to an invisible state when the sizeHint is reset to 0,0
+// and enables sizeHandle-resizing. In a layout, however, this m_SizeOffset
+// should not be applied for pixel-exact design.
+
+Spacer::Spacer(QWidget *parent) :
+ QWidget(parent),
+ m_SizeOffset(3, 3), // A small offset to ensure the spacer is still visible when reset to size 0,0
+ m_orientation(Qt::Vertical),
+ m_interactive(true),
+ m_layoutState(UnknownLayoutState),
+ m_sizeHint(0, 0)
+{
+ setAttribute(Qt::WA_MouseNoMask);
+ m_formWindow = QDesignerFormWindowInterface::findFormWindow(this);
+ setSizeType(QSizePolicy::Expanding);
+}
+
+bool Spacer::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::ToolTip:
+ updateToolTip(); // Tooltip includes size, so, refresh on demand
+ break;
+ case QEvent::ParentChange: // Cache information about 'being in layout' which is expensive to calculate.
+ m_layoutState = UnknownLayoutState;
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(e);
+}
+
+bool Spacer::isInLayout() const
+{
+ if (m_layoutState == UnknownLayoutState) {
+ m_layoutState = OutsideLayout;
+ if (m_formWindow)
+ if (const QWidget *parent = parentWidget())
+ if (qdesigner_internal::LayoutInfo::managedLayoutType(m_formWindow->core(), parent) != qdesigner_internal::LayoutInfo::NoLayout)
+ m_layoutState = InLayout;
+ }
+ return m_layoutState == InLayout;
+}
+
+void Spacer::paintEvent(QPaintEvent *)
+{
+ // Only draw spacers when we're editting widgets
+ if (m_formWindow != 0 && m_formWindow->currentTool() != 0)
+ return;
+
+ QPainter p(this);
+ p.setPen(Qt::blue);
+ const int w = width();
+ const int h = height();
+ if (w * h == 0)
+ return;
+
+ if (w <= m_SizeOffset.width() || h <= m_SizeOffset.height()) {
+ const int lw = w - 1;
+ const int lh = h - 1;
+ switch (m_orientation) {
+ case Qt::Horizontal:
+ p.drawLine(0, 0, 0, lh);
+ p.drawLine(lw, 0, lw, lh);
+ break;
+ case Qt::Vertical:
+ p.drawLine(0, 0, lw, 0);
+ p.drawLine(0, lh, lw, lh);
+ break;
+ }
+ return;
+ }
+ if (m_orientation == Qt::Horizontal) {
+ const int dist = 3;
+ const int amplitude = qMin(3, h / 3);
+ const int base = h / 2;
+ int i = 0;
+ p.setPen(Qt::white);
+ for (i = 0; i < w / 3 +2; ++i)
+ p.drawLine(i * dist, base - amplitude, i * dist + dist / 2, base + amplitude);
+ p.setPen(Qt::blue);
+ for (i = 0; i < w / 3 +2; ++i)
+ p.drawLine(i * dist + dist / 2, base + amplitude, i * dist + dist, base - amplitude);
+ const int y = h/2;
+ p.drawLine(0, y-10, 0, y+10);
+ p.drawLine(w - 1, y-10, w - 1, y+10);
+ } else {
+ const int dist = 3;
+ const int amplitude = qMin(3, w / 3);
+ const int base = w / 2;
+ int i = 0;
+ p.setPen(Qt::white);
+ for (i = 0; i < h / 3 +2; ++i)
+ p.drawLine(base - amplitude, i * dist, base + amplitude,i * dist + dist / 2);
+ p.setPen(Qt::blue);
+ for (i = 0; i < h / 3 +2; ++i)
+ p.drawLine(base + amplitude, i * dist + dist / 2, base - amplitude, i * dist + dist);
+ const int x = w/2;
+ p.drawLine(x-10, 0, x+10, 0);
+ p.drawLine(x-10, h - 1, x+10, h - 1);
+ }
+}
+
+void Spacer::resizeEvent(QResizeEvent* e)
+{
+ QWidget::resizeEvent(e);
+ // When resized by widget handle dragging after a reset (QSize(0, 0)):
+ // Mark the property as changed (geometry and sizeHint are in sync except for 'changed').
+ if (m_formWindow) {
+ const QSize oldSize = e->oldSize();
+ if (oldSize.isNull() || oldSize.width() <= m_SizeOffset.width() || oldSize.height() <= m_SizeOffset.height())
+ if (QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(m_formWindow->core()->extensionManager(), this))
+ sheet->setChanged(sheet->indexOf(QLatin1String("sizeHint")), true);
+ }
+
+ updateMask();
+
+ if (!m_interactive)
+ return;
+
+ if (!isInLayout()) { // Allow size-handle resize only if not in layout
+ const QSize currentSize = size();
+ if (currentSize.width() >= m_SizeOffset.width() && currentSize.height() >= m_SizeOffset.height())
+ m_sizeHint = currentSize - m_SizeOffset;
+ }
+}
+
+void Spacer::updateMask()
+{
+ QRegion r(rect());
+ const int w = width();
+ const int h = height();
+ if (w > 1 && h > 1) {
+ if (m_orientation == Qt::Horizontal) {
+ const int amplitude = qMin(3, h / 3);
+ const int base = h / 2;
+ r = r.subtract(QRect(1, 0, w - 2, base - amplitude));
+ r = r.subtract(QRect(1, base + amplitude, w - 2, h - base - amplitude));
+ } else {
+ const int amplitude = qMin(3, w / 3);
+ const int base = w / 2;
+ r = r.subtract(QRect(0, 1, base - amplitude, h - 2));
+ r = r.subtract(QRect(base + amplitude, 1, w - base - amplitude, h - 2));
+ }
+ }
+ setMask(r);
+}
+
+void Spacer::setSizeType(QSizePolicy::Policy t)
+{
+ const QSizePolicy sizeP = m_orientation == Qt::Vertical ? QSizePolicy(QSizePolicy::Minimum, t) : QSizePolicy(t, QSizePolicy::Minimum);
+ setSizePolicy(sizeP);
+}
+
+
+QSizePolicy::Policy Spacer::sizeType() const
+{
+ return m_orientation == Qt::Vertical ? sizePolicy().verticalPolicy() : sizePolicy().horizontalPolicy();
+}
+
+Qt::Alignment Spacer::alignment() const
+{
+ // For grid layouts
+ return m_orientation == Qt::Vertical ? Qt::AlignHCenter : Qt::AlignVCenter;
+}
+
+QSize Spacer::sizeHint() const
+{
+ return isInLayout() ? m_sizeHint : m_sizeHint + m_SizeOffset;
+}
+
+QSize Spacer::sizeHintProperty() const
+{
+ return m_sizeHint;
+}
+
+void Spacer::setSizeHintProperty(const QSize &s)
+{
+ m_sizeHint = s;
+
+ if (!isInLayout()) // Visible resize only if not in layout
+ resize(s + m_SizeOffset);
+
+ updateGeometry();
+}
+
+Qt::Orientation Spacer::orientation() const
+{
+ return m_orientation;
+}
+
+void Spacer::setOrientation(Qt::Orientation o)
+{
+ if (m_orientation == o)
+ return;
+
+ const QSizePolicy::Policy st = sizeType(); // flip size type
+ m_orientation = o;
+ setSizeType(st);
+
+ if (m_interactive) {
+ m_sizeHint = QSize(m_sizeHint.height(), m_sizeHint.width());
+ if (!isInLayout())
+ resize(m_sizeHint + m_SizeOffset);
+ }
+
+ updateMask();
+ update();
+ updateGeometry();
+}
+
+void Spacer::updateToolTip()
+{
+ const QString format = m_orientation == Qt::Horizontal ? tr("Horizontal Spacer '%1', %2 x %3") : tr("Vertical Spacer '%1', %2 x %3");
+ QString msg = format.arg(objectName()).arg(m_sizeHint.width()).arg(m_sizeHint.height());
+ setToolTip(msg);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/spacer_widget_p.h b/tools/designer/src/lib/shared/spacer_widget_p.h
new file mode 100644
index 0000000000..2b9081317c
--- /dev/null
+++ b/tools/designer/src/lib/shared/spacer_widget_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef SPACER_WIDGET_H
+#define SPACER_WIDGET_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QWidget>
+#include <QtGui/QSizePolicy>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+
+class QDESIGNER_SHARED_EXPORT Spacer: public QWidget
+{
+ Q_OBJECT
+
+ Q_ENUMS(SizeType)
+ // Special hack: Make name appear as "spacer name"
+ Q_PROPERTY(QString spacerName READ objectName WRITE setObjectName)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_PROPERTY(QSizePolicy::Policy sizeType READ sizeType WRITE setSizeType)
+ Q_PROPERTY(QSize sizeHint READ sizeHintProperty WRITE setSizeHintProperty DESIGNABLE true STORED true)
+
+public:
+ Spacer(QWidget *parent = 0);
+
+ QSize sizeHint() const;
+
+ QSize sizeHintProperty() const;
+ void setSizeHintProperty(const QSize &s);
+
+ QSizePolicy::Policy sizeType() const;
+ void setSizeType(QSizePolicy::Policy t);
+
+ Qt::Alignment alignment() const;
+ Qt::Orientation orientation() const;
+
+ void setOrientation(Qt::Orientation o);
+ void setInteractiveMode(bool b) { m_interactive = b; };
+
+ virtual bool event(QEvent *e);
+
+protected:
+ void paintEvent(QPaintEvent *e);
+ void resizeEvent(QResizeEvent* e);
+ void updateMask();
+
+private:
+ bool isInLayout() const;
+ void updateToolTip();
+
+ const QSize m_SizeOffset;
+ QDesignerFormWindowInterface *m_formWindow;
+ Qt::Orientation m_orientation;
+ bool m_interactive;
+ // Cache information about 'being in layout' which is expensive to calculate.
+ enum LayoutState { InLayout, OutsideLayout, UnknownLayoutState };
+ mutable LayoutState m_layoutState;
+ QSize m_sizeHint;
+};
+
+QT_END_NAMESPACE
+
+#endif // SPACER_WIDGET_H
diff --git a/tools/designer/src/lib/shared/stylesheeteditor.cpp b/tools/designer/src/lib/shared/stylesheeteditor.cpp
new file mode 100644
index 0000000000..2056fcfd99
--- /dev/null
+++ b/tools/designer/src/lib/shared/stylesheeteditor.cpp
@@ -0,0 +1,415 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::StyleSheetEditorDialog
+*/
+
+#include "stylesheeteditor_p.h"
+#include "csshighlighter_p.h"
+#include "iconselector_p.h"
+#include "qtgradientmanager.h"
+#include "qtgradientviewdialog.h"
+#include "qtgradientutils.h"
+#include "qdesigner_integration_p.h"
+#include "qdesigner_utils_p.h"
+#include "abstractsettings_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QSignalMapper>
+#include <QtGui/QAction>
+#include <QtGui/QColorDialog>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QFontDialog>
+#include <QtGui/QMenu>
+#include <QtGui/QPushButton>
+#include <QtGui/QTextDocument>
+#include <QtGui/QToolBar>
+#include <QtGui/QVBoxLayout>
+#include "private/qcssparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static const char *styleSheetProperty = "styleSheet";
+static const char *StyleSheetDialogC = "StyleSheetDialog";
+static const char *Geometry = "Geometry";
+
+namespace qdesigner_internal {
+
+StyleSheetEditor::StyleSheetEditor(QWidget *parent)
+ : QTextEdit(parent)
+{
+ setTabStopWidth(fontMetrics().width(QLatin1Char(' '))*4);
+ new CssHighlighter(document());
+}
+
+// --- StyleSheetEditorDialog
+StyleSheetEditorDialog::StyleSheetEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent, Mode mode):
+ QDialog(parent),
+ m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Help)),
+ m_editor(new StyleSheetEditor),
+ m_validityLabel(new QLabel(tr("Valid Style Sheet"))),
+ m_core(core),
+ m_addResourceAction(new QAction(tr("Add Resource..."), this)),
+ m_addGradientAction(new QAction(tr("Add Gradient..."), this)),
+ m_addColorAction(new QAction(tr("Add Color..."), this)),
+ m_addFontAction(new QAction(tr("Add Font..."), this))
+{
+ setWindowTitle(tr("Edit Style Sheet"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(m_buttonBox, SIGNAL(helpRequested()), this, SLOT(slotRequestHelp()));
+ m_buttonBox->button(QDialogButtonBox::Help)->setShortcut(QKeySequence::HelpContents);
+
+ connect(m_editor, SIGNAL(textChanged()), this, SLOT(validateStyleSheet()));
+
+ QToolBar *toolBar = new QToolBar;
+
+ QGridLayout *layout = new QGridLayout;
+ layout->addWidget(toolBar, 0, 0, 1, 2);
+ layout->addWidget(m_editor, 1, 0, 1, 2);
+ layout->addWidget(m_validityLabel, 2, 0, 1, 1);
+ layout->addWidget(m_buttonBox, 2, 1, 1, 1);
+ setLayout(layout);
+
+ m_editor->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_editor, SIGNAL(customContextMenuRequested(const QPoint &)),
+ this, SLOT(slotContextMenuRequested(const QPoint &)));
+
+ QSignalMapper *resourceActionMapper = new QSignalMapper(this);
+ QSignalMapper *gradientActionMapper = new QSignalMapper(this);
+ QSignalMapper *colorActionMapper = new QSignalMapper(this);
+
+ resourceActionMapper->setMapping(m_addResourceAction, QString());
+ gradientActionMapper->setMapping(m_addGradientAction, QString());
+ colorActionMapper->setMapping(m_addColorAction, QString());
+
+ connect(m_addResourceAction, SIGNAL(triggered()), resourceActionMapper, SLOT(map()));
+ connect(m_addGradientAction, SIGNAL(triggered()), gradientActionMapper, SLOT(map()));
+ connect(m_addColorAction, SIGNAL(triggered()), colorActionMapper, SLOT(map()));
+ connect(m_addFontAction, SIGNAL(triggered()), this, SLOT(slotAddFont()));
+
+ m_addResourceAction->setEnabled(mode == ModePerForm);
+
+ const char * const resourceProperties[] = {
+ "background-image",
+ "border-image",
+ "image",
+ 0
+ };
+
+ const char * const colorProperties[] = {
+ "color",
+ "background-color",
+ "alternate-background-color",
+ "border-color",
+ "border-top-color",
+ "border-right-color",
+ "border-bottom-color",
+ "border-left-color",
+ "gridline-color",
+ "selection-color",
+ "selection-background-color",
+ 0
+ };
+
+ QMenu *resourceActionMenu = new QMenu(this);
+ QMenu *gradientActionMenu = new QMenu(this);
+ QMenu *colorActionMenu = new QMenu(this);
+
+ for (int resourceProperty = 0; resourceProperties[resourceProperty]; ++resourceProperty) {
+ QAction *action = resourceActionMenu->addAction(QLatin1String(resourceProperties[resourceProperty]));
+ connect(action, SIGNAL(triggered()), resourceActionMapper, SLOT(map()));
+ resourceActionMapper->setMapping(action, QLatin1String(resourceProperties[resourceProperty]));
+ }
+
+ for (int colorProperty = 0; colorProperties[colorProperty]; ++colorProperty) {
+ QAction *gradientAction = gradientActionMenu->addAction(QLatin1String(colorProperties[colorProperty]));
+ QAction *colorAction = colorActionMenu->addAction(QLatin1String(colorProperties[colorProperty]));
+ connect(gradientAction, SIGNAL(triggered()), gradientActionMapper, SLOT(map()));
+ connect(colorAction, SIGNAL(triggered()), colorActionMapper, SLOT(map()));
+ gradientActionMapper->setMapping(gradientAction, QLatin1String(colorProperties[colorProperty]));
+ colorActionMapper->setMapping(colorAction, QLatin1String(colorProperties[colorProperty]));
+ }
+
+ connect(resourceActionMapper, SIGNAL(mapped(QString)), this, SLOT(slotAddResource(QString)));
+ connect(gradientActionMapper, SIGNAL(mapped(QString)), this, SLOT(slotAddGradient(QString)));
+ connect(colorActionMapper, SIGNAL(mapped(QString)), this, SLOT(slotAddColor(QString)));
+
+ m_addResourceAction->setMenu(resourceActionMenu);
+ m_addGradientAction->setMenu(gradientActionMenu);
+ m_addColorAction->setMenu(colorActionMenu);
+
+ toolBar->addAction(m_addResourceAction);
+ toolBar->addAction(m_addGradientAction);
+ toolBar->addAction(m_addColorAction);
+ toolBar->addAction(m_addFontAction);
+
+ m_editor->setFocus();
+
+ QDesignerSettingsInterface *settings = core->settingsManager();
+ settings->beginGroup(QLatin1String(StyleSheetDialogC));
+
+ if (settings->contains(QLatin1String(Geometry)))
+ restoreGeometry(settings->value(QLatin1String(Geometry)).toByteArray());
+
+ settings->endGroup();
+}
+
+StyleSheetEditorDialog::~StyleSheetEditorDialog()
+{
+ QDesignerSettingsInterface *settings = m_core->settingsManager();
+ settings->beginGroup(QLatin1String(StyleSheetDialogC));
+
+ settings->setValue(QLatin1String(Geometry), saveGeometry());
+ settings->endGroup();
+}
+
+void StyleSheetEditorDialog::setOkButtonEnabled(bool v)
+{
+ m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(v);
+ if (QPushButton *applyButton = m_buttonBox->button(QDialogButtonBox::Apply))
+ applyButton->setEnabled(v);
+}
+
+void StyleSheetEditorDialog::slotContextMenuRequested(const QPoint &pos)
+{
+ QMenu *menu = m_editor->createStandardContextMenu();
+ menu->addSeparator();
+ menu->addAction(m_addResourceAction);
+ menu->addAction(m_addGradientAction);
+ menu->exec(mapToGlobal(pos));
+ delete menu;
+}
+
+void StyleSheetEditorDialog::slotAddResource(const QString &property)
+{
+ const QString path = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), QString(), this);
+ if (!path.isEmpty())
+ insertCssProperty(property, QString(QLatin1String("url(%1)")).arg(path));
+}
+
+void StyleSheetEditorDialog::slotAddGradient(const QString &property)
+{
+ bool ok;
+ const QGradient grad = QtGradientViewDialog::getGradient(&ok, m_core->gradientManager(), this);
+ if (ok)
+ insertCssProperty(property, QtGradientUtils::styleSheetCode(grad));
+}
+
+void StyleSheetEditorDialog::slotAddColor(const QString &property)
+{
+ bool ok;
+ QRgb rgba = QColorDialog::getRgba(0xffffffff, &ok, this);
+ if (!ok)
+ return;
+
+ QColor color;
+ color.setRgba(rgba);
+ QString colorStr;
+
+ if (color.alpha() == 255) {
+ colorStr = QString(QLatin1String("rgb(%1, %2, %3)")).arg(
+ color.red()).arg(color.green()).arg(color.blue());
+ } else {
+ colorStr = QString(QLatin1String("rgba(%1, %2, %3, %4)")).arg(
+ color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha());
+ }
+
+ insertCssProperty(property, colorStr);
+}
+
+void StyleSheetEditorDialog::slotAddFont()
+{
+ bool ok;
+ QFont font = QFontDialog::getFont(&ok, this);
+ if (ok) {
+ QString fontStr;
+ if (font.weight() != QFont::Normal) {
+ fontStr += QString::number(font.weight());
+ fontStr += QLatin1Char(' ');
+ }
+
+ switch (font.style()) {
+ case QFont::StyleItalic:
+ fontStr += QLatin1String("italic ");
+ break;
+ case QFont::StyleOblique:
+ fontStr += QLatin1String("oblique ");
+ break;
+ default:
+ break;
+ }
+ fontStr += QString::number(font.pointSize());
+ fontStr += QLatin1String("pt \"");
+ fontStr += font.family();
+ fontStr += QLatin1Char('"');
+
+ insertCssProperty(QLatin1String("font"), fontStr);
+ QString decoration;
+ if (font.underline())
+ decoration += QLatin1String("underline");
+ if (font.strikeOut()) {
+ if (!decoration.isEmpty())
+ decoration += QLatin1Char(' ');
+ decoration += QLatin1String("line-through");
+ }
+ insertCssProperty(QLatin1String("text-decoration"), decoration);
+ }
+}
+
+void StyleSheetEditorDialog::insertCssProperty(const QString &name, const QString &value)
+{
+ if (!value.isEmpty()) {
+ QTextCursor cursor = m_editor->textCursor();
+ if (!name.isEmpty()) {
+ cursor.beginEditBlock();
+ cursor.removeSelectedText();
+ cursor.movePosition(QTextCursor::EndOfLine);
+
+ // Simple check to see if we're in a selector scope
+ const QTextDocument *doc = m_editor->document();
+ const QTextCursor closing = doc->find(QLatin1String("}"), cursor, QTextDocument::FindBackward);
+ const QTextCursor opening = doc->find(QLatin1String("{"), cursor, QTextDocument::FindBackward);
+ const bool inSelector = !opening.isNull() && (closing.isNull() ||
+ closing.position() < opening.position());
+ QString insertion;
+ if (m_editor->textCursor().block().length() != 1)
+ insertion += QLatin1Char('\n');
+ if (inSelector)
+ insertion += QLatin1Char('\t');
+ insertion += name;
+ insertion += QLatin1String(": ");
+ insertion += value;
+ insertion += QLatin1Char(';');
+ cursor.insertText(insertion);
+ cursor.endEditBlock();
+ } else {
+ cursor.insertText(value);
+ }
+ }
+}
+
+void StyleSheetEditorDialog::slotRequestHelp()
+{
+ QDesignerIntegration::requestHelp(m_core, QLatin1String("qt"),
+ QLatin1String("stylesheet-reference.html"));
+}
+
+QDialogButtonBox * StyleSheetEditorDialog::buttonBox() const
+{
+ return m_buttonBox;
+}
+
+QString StyleSheetEditorDialog::text() const
+{
+ return m_editor->toPlainText();
+}
+
+void StyleSheetEditorDialog::setText(const QString &t)
+{
+ m_editor->setText(t);
+}
+
+bool StyleSheetEditorDialog::isStyleSheetValid(const QString &styleSheet)
+{
+ QCss::Parser parser(styleSheet);
+ QCss::StyleSheet sheet;
+ if (parser.parse(&sheet))
+ return true;
+ QString fullSheet = QLatin1String("* { ");
+ fullSheet += styleSheet;
+ fullSheet += QLatin1Char('}');
+ QCss::Parser parser2(fullSheet);
+ return parser2.parse(&sheet);
+}
+
+void StyleSheetEditorDialog::validateStyleSheet()
+{
+ const bool valid = isStyleSheetValid(m_editor->toPlainText());
+ setOkButtonEnabled(valid);
+ if (valid) {
+ m_validityLabel->setText(tr("Valid Style Sheet"));
+ m_validityLabel->setStyleSheet(QLatin1String("color: green"));
+ } else {
+ m_validityLabel->setText(tr("Invalid Style Sheet"));
+ m_validityLabel->setStyleSheet(QLatin1String("color: red"));
+ }
+}
+
+// --- StyleSheetPropertyEditorDialog
+StyleSheetPropertyEditorDialog::StyleSheetPropertyEditorDialog(QWidget *parent,
+ QDesignerFormWindowInterface *fw,
+ QWidget *widget):
+ StyleSheetEditorDialog(fw->core(), parent),
+ m_fw(fw),
+ m_widget(widget)
+{
+ Q_ASSERT(m_fw != 0);
+
+ QPushButton *apply = buttonBox()->addButton(QDialogButtonBox::Apply);
+ QObject::connect(apply, SIGNAL(clicked()), this, SLOT(applyStyleSheet()));
+ QObject::connect(buttonBox(), SIGNAL(accepted()), this, SLOT(applyStyleSheet()));
+
+ QDesignerPropertySheetExtension *sheet =
+ qt_extension<QDesignerPropertySheetExtension*>(m_fw->core()->extensionManager(), m_widget);
+ Q_ASSERT(sheet != 0);
+ const int index = sheet->indexOf(QLatin1String(styleSheetProperty));
+ const PropertySheetStringValue value = qVariantValue<PropertySheetStringValue>(sheet->property(index));
+ setText(value.value());
+}
+
+void StyleSheetPropertyEditorDialog::applyStyleSheet()
+{
+ const PropertySheetStringValue value(text(), false);
+ m_fw->cursor()->setWidgetProperty(m_widget, QLatin1String(styleSheetProperty), qVariantFromValue(value));
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/stylesheeteditor_p.h b/tools/designer/src/lib/shared/stylesheeteditor_p.h
new file mode 100644
index 0000000000..c9fd682b74
--- /dev/null
+++ b/tools/designer/src/lib/shared/stylesheeteditor_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef STYLESHEETEDITOR_H
+#define STYLESHEETEDITOR_H
+
+#include <QtGui/QTextEdit>
+#include <QtGui/QDialog>
+#include <QtGui/QLabel>
+#include "shared_global_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerFormEditorInterface;
+
+class QDialogButtonBox;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT StyleSheetEditor : public QTextEdit
+{
+ Q_OBJECT
+public:
+ StyleSheetEditor(QWidget *parent = 0);
+};
+
+// Edit a style sheet.
+class QDESIGNER_SHARED_EXPORT StyleSheetEditorDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ enum Mode {
+ ModeGlobal, // resources are disabled (we don't have current resource set loaded), used e.g. in configuration dialog context
+ ModePerForm // resources are available
+ };
+
+ StyleSheetEditorDialog(QDesignerFormEditorInterface *core, QWidget *parent, Mode mode = ModePerForm);
+ ~StyleSheetEditorDialog();
+ QString text() const;
+ void setText(const QString &t);
+
+ static bool isStyleSheetValid(const QString &styleSheet);
+
+
+private slots:
+ void validateStyleSheet();
+ void slotContextMenuRequested(const QPoint &pos);
+ void slotAddResource(const QString &property);
+ void slotAddGradient(const QString &property);
+ void slotAddColor(const QString &property);
+ void slotAddFont();
+ void slotRequestHelp();
+
+protected:
+ QDialogButtonBox *buttonBox() const;
+ void setOkButtonEnabled(bool v);
+
+private:
+ void insertCssProperty(const QString &name, const QString &value);
+
+ QDialogButtonBox *m_buttonBox;
+ StyleSheetEditor *m_editor;
+ QLabel *m_validityLabel;
+ QDesignerFormEditorInterface *m_core;
+ QAction *m_addResourceAction;
+ QAction *m_addGradientAction;
+ QAction *m_addColorAction;
+ QAction *m_addFontAction;
+};
+
+// Edit the style sheet property of the designer selection.
+// Provides an "Apply" button.
+
+class QDESIGNER_SHARED_EXPORT StyleSheetPropertyEditorDialog : public StyleSheetEditorDialog
+{
+ Q_OBJECT
+public:
+ StyleSheetPropertyEditorDialog(QWidget *parent, QDesignerFormWindowInterface *fw, QWidget *widget);
+
+ static bool isStyleSheetValid(const QString &styleSheet);
+
+private slots:
+ void applyStyleSheet();
+
+private:
+ QDesignerFormWindowInterface *m_fw;
+ QWidget *m_widget;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // STYLESHEETEDITOR_H
diff --git a/tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui b/tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 0000000000..7ff64b0cb6
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Bottom.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>240</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>270</y>
+ <width>221</width>
+ <height>41</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui b/tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui
new file mode 100644
index 0000000000..203af78ff9
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/240x320/Dialog_with_Buttons_Right.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>240</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>150</x>
+ <y>10</y>
+ <width>81</width>
+ <height>301</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui b/tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 0000000000..0ac856e4ef
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Bottom.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>320</width>
+ <height>240</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>200</y>
+ <width>301</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui b/tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui
new file mode 100644
index 0000000000..52f0f66a47
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/320x240/Dialog_with_Buttons_Right.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>320</width>
+ <height>240</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>230</x>
+ <y>10</y>
+ <width>81</width>
+ <height>221</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui b/tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 0000000000..0d219c937c
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Bottom.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>480</width>
+ <height>640</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>600</y>
+ <width>461</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui b/tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui
new file mode 100644
index 0000000000..c82a78e87c
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/480x640/Dialog_with_Buttons_Right.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>480</width>
+ <height>640</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>390</x>
+ <y>10</y>
+ <width>81</width>
+ <height>621</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui b/tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 0000000000..adc5d48476
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Bottom.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>640</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>440</y>
+ <width>621</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui b/tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui
new file mode 100644
index 0000000000..defb42a40a
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/640x480/Dialog_with_Buttons_Right.ui
@@ -0,0 +1,67 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>640</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>550</x>
+ <y>10</y>
+ <width>81</width>
+ <height>461</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui b/tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui
new file mode 100644
index 0000000000..18d31ab915
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Bottom.ui
@@ -0,0 +1,71 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>30</x>
+ <y>240</y>
+ <width>341</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui b/tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui
new file mode 100644
index 0000000000..703d594f4f
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/Dialog_with_Buttons_Right.ui
@@ -0,0 +1,71 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="geometry" >
+ <rect>
+ <x>290</x>
+ <y>20</y>
+ <width>81</width>
+ <height>241</height>
+ </rect>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui b/tools/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui
new file mode 100644
index 0000000000..1be629818c
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/Dialog_without_Buttons.ui
@@ -0,0 +1,18 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/Main_Window.ui b/tools/designer/src/lib/shared/templates/forms/Main_Window.ui
new file mode 100644
index 0000000000..9ae3b5024b
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/Main_Window.ui
@@ -0,0 +1,24 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>MainWindow</string>
+ </property>
+ <widget class="QMenuBar" name="menubar" />
+ <widget class="QWidget" name="centralwidget" />
+ <widget class="QStatusBar" name="statusbar" />
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/lib/shared/templates/forms/Widget.ui b/tools/designer/src/lib/shared/templates/forms/Widget.ui
new file mode 100644
index 0000000000..4b7d6a45fb
--- /dev/null
+++ b/tools/designer/src/lib/shared/templates/forms/Widget.ui
@@ -0,0 +1,21 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>Form</class>
+ <widget class="QWidget" name="Form" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <connections/>
+</ui>
diff --git a/tools/designer/src/lib/shared/textpropertyeditor.cpp b/tools/designer/src/lib/shared/textpropertyeditor.cpp
new file mode 100644
index 0000000000..cf12842edd
--- /dev/null
+++ b/tools/designer/src/lib/shared/textpropertyeditor.cpp
@@ -0,0 +1,429 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "textpropertyeditor_p.h"
+#include "propertylineedit_p.h"
+#include "stylesheeteditor_p.h"
+
+#include <QtGui/QLineEdit>
+#include <QtGui/QRegExpValidator>
+#include <QtGui/QResizeEvent>
+#include <QtGui/QCompleter>
+#include <QtGui/QAbstractItemView>
+#include <QtCore/QRegExp>
+#include <QtCore/QUrl>
+#include <QtCore/QFile>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ const QChar NewLineChar(QLatin1Char('\n'));
+ const QLatin1String EscapedNewLine("\\n");
+
+ // A validator that replaces offending strings
+ class ReplacementValidator : public QValidator {
+ public:
+ ReplacementValidator (QObject * parent,
+ const QString &offending,
+ const QString &replacement);
+ virtual void fixup ( QString & input ) const;
+ virtual State validate ( QString & input, int &pos) const;
+ private:
+ const QString m_offending;
+ const QString m_replacement;
+ };
+
+ ReplacementValidator::ReplacementValidator (QObject * parent,
+ const QString &offending,
+ const QString &replacement) :
+ QValidator(parent ),
+ m_offending(offending),
+ m_replacement(replacement)
+ {
+ }
+
+ void ReplacementValidator::fixup ( QString & input ) const {
+ input.replace(m_offending, m_replacement);
+ }
+
+ QValidator::State ReplacementValidator::validate ( QString & input, int &/* pos */) const {
+ fixup (input);
+ return Acceptable;
+ }
+
+ // A validator for style sheets. Does newline handling and validates sheets.
+ class StyleSheetValidator : public ReplacementValidator {
+ public:
+ StyleSheetValidator (QObject * parent);
+ virtual State validate(QString & input, int &pos) const;
+ };
+
+ StyleSheetValidator::StyleSheetValidator (QObject * parent) :
+ ReplacementValidator(parent, NewLineChar, EscapedNewLine)
+ {
+ }
+
+ QValidator::State StyleSheetValidator::validate ( QString & input, int &pos) const
+ {
+ // base class
+ const State state = ReplacementValidator:: validate(input, pos);
+ if (state != Acceptable)
+ return state;
+ // now check style sheet, create string with newlines
+ const QString styleSheet = qdesigner_internal::TextPropertyEditor::editorStringToString(input, qdesigner_internal::ValidationStyleSheet);
+ const bool valid = qdesigner_internal::StyleSheetEditorDialog::isStyleSheetValid(styleSheet);
+ return valid ? Acceptable : Intermediate;
+ }
+
+ // A validator for URLs based on QUrl. Enforces complete protocol
+ // specification with a completer (adds a trailing slash)
+ class UrlValidator : public QValidator {
+ public:
+ UrlValidator(QCompleter *completer, QObject *parent);
+
+ virtual State validate(QString &input, int &pos) const;
+ virtual void fixup(QString &input) const;
+ private:
+ QUrl guessUrlFromString(const QString &string) const;
+ QCompleter *m_completer;
+ };
+
+ UrlValidator::UrlValidator(QCompleter *completer, QObject *parent) :
+ QValidator(parent),
+ m_completer(completer)
+ {
+ }
+
+ QValidator::State UrlValidator::validate(QString &input, int &pos) const
+ {
+ Q_UNUSED(pos);
+
+ if (input.isEmpty())
+ return Acceptable;
+
+ const QUrl url(input, QUrl::StrictMode);
+
+ if (!url.isValid() || url.isEmpty())
+ return Intermediate;
+
+ if (url.scheme().isEmpty())
+ return Intermediate;
+
+ if (url.host().isEmpty() && url.path().isEmpty())
+ return Intermediate;
+
+ return Acceptable;
+ }
+
+ void UrlValidator::fixup(QString &input) const
+ {
+ // Don't try to fixup if the user is busy selecting a completion proposal
+ if (const QAbstractItemView *iv = m_completer->popup()) {
+ if (iv->isVisible())
+ return;
+ }
+
+ input = guessUrlFromString(input).toString();
+ }
+
+ QUrl UrlValidator::guessUrlFromString(const QString &string) const
+ {
+ const QString urlStr = string.trimmed();
+ const QRegExp qualifiedUrl(QLatin1String("^[a-zA-Z]+\\:.*"));
+
+ // Check if it looks like a qualified URL. Try parsing it and see.
+ const bool hasSchema = qualifiedUrl.exactMatch(urlStr);
+ if (hasSchema) {
+ const QUrl url(urlStr, QUrl::TolerantMode);
+ if (url.isValid())
+ return url;
+ }
+
+ // Might be a Qt resource
+ if (string.startsWith(QLatin1String(":/")))
+ return QUrl(QLatin1String("qrc") + string);
+
+ // Might be a file.
+ if (QFile::exists(urlStr))
+ return QUrl::fromLocalFile(urlStr);
+
+ // Might be a short url - try to detect the schema.
+ if (!hasSchema) {
+ const int dotIndex = urlStr.indexOf(QLatin1Char('.'));
+ if (dotIndex != -1) {
+ const QString prefix = urlStr.left(dotIndex).toLower();
+ QString urlString;
+ if (prefix == QLatin1String("ftp"))
+ urlString += prefix;
+ else
+ urlString += QLatin1String("http");
+ urlString += QLatin1String("://");
+ urlString += urlStr;
+ const QUrl url(urlString, QUrl::TolerantMode);
+ if (url.isValid())
+ return url;
+ }
+ }
+
+ // Fall back to QUrl's own tolerant parser.
+ return QUrl(string, QUrl::TolerantMode);
+ }
+}
+
+namespace qdesigner_internal {
+ // TextPropertyEditor
+ TextPropertyEditor::TextPropertyEditor(QWidget *parent,
+ EmbeddingMode embeddingMode,
+ TextPropertyValidationMode validationMode) :
+ QWidget(parent),
+ m_validationMode(ValidationSingleLine),
+ m_updateMode(UpdateAsYouType),
+ m_lineEdit(new PropertyLineEdit(this)),
+ m_textEdited(false)
+ {
+ switch (embeddingMode) {
+ case EmbeddingNone:
+ break;
+ case EmbeddingTreeView:
+ m_lineEdit->setFrame(false);
+ break;
+ case EmbeddingInPlace:
+ m_lineEdit->setFrame(false);
+ Q_ASSERT(parent);
+ m_lineEdit->setBackgroundRole(parent->backgroundRole());
+ break;
+ }
+
+ setFocusProxy(m_lineEdit);
+
+ connect(m_lineEdit,SIGNAL(editingFinished()), this, SIGNAL(editingFinished()));
+ connect(m_lineEdit,SIGNAL(returnPressed()), this, SLOT(slotEditingFinished()));
+ connect(m_lineEdit,SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString)));
+ connect(m_lineEdit,SIGNAL(textEdited(QString)), this, SLOT(slotTextEdited()));
+
+ setTextPropertyValidationMode(validationMode);
+ }
+
+ void TextPropertyEditor::setTextPropertyValidationMode(TextPropertyValidationMode vm) {
+ m_validationMode = vm;
+ m_lineEdit->setWantNewLine(multiLine(m_validationMode));
+ switch (m_validationMode) {
+ case ValidationStyleSheet:
+ m_lineEdit->setValidator(new StyleSheetValidator(m_lineEdit));
+ m_lineEdit->setCompleter(0);
+ break;
+ case ValidationMultiLine:
+ case ValidationRichText:
+ // Set a validator that replaces newline characters by literal "\\n".
+ // While it is not possible to actually type a newline characters,
+ // it can be pasted into the line edit.
+ m_lineEdit->setValidator(new ReplacementValidator(m_lineEdit, NewLineChar, EscapedNewLine));
+ m_lineEdit->setCompleter(0);
+ break;
+ case ValidationSingleLine:
+ // Set a validator that replaces newline characters by a blank.
+ m_lineEdit->setValidator(new ReplacementValidator(m_lineEdit, NewLineChar, QString(QLatin1Char(' '))));
+ m_lineEdit->setCompleter(0);
+ break;
+ case ValidationObjectName:
+ setRegExpValidator(QLatin1String("[_a-zA-Z][_a-zA-Z0-9]{,1023}"));
+ m_lineEdit->setCompleter(0);
+ break;
+ case ValidationObjectNameScope:
+ setRegExpValidator(QLatin1String("[_a-zA-Z:][_a-zA-Z0-9:]{,1023}"));
+ m_lineEdit->setCompleter(0);
+ break;
+ case ValidationURL: {
+ static QStringList urlCompletions;
+ if (urlCompletions.empty()) {
+ urlCompletions.push_back(QLatin1String("about:blank"));
+ urlCompletions.push_back(QLatin1String("http://"));
+ urlCompletions.push_back(QLatin1String("http://www."));
+ urlCompletions.push_back(QLatin1String("http://qtsoftware.com/"));
+ urlCompletions.push_back(QLatin1String("file://"));
+ urlCompletions.push_back(QLatin1String("ftp://"));
+ urlCompletions.push_back(QLatin1String("data:"));
+ urlCompletions.push_back(QLatin1String("data:text/html,"));
+ urlCompletions.push_back(QLatin1String("qrc:/"));
+ }
+ QCompleter *completer = new QCompleter(urlCompletions, m_lineEdit);
+ m_lineEdit->setCompleter(completer);
+ m_lineEdit->setValidator(new UrlValidator(completer, m_lineEdit));
+ }
+ break;
+ }
+
+ setFocusProxy(m_lineEdit);
+ markIntermediateState();
+ }
+
+ void TextPropertyEditor::setRegExpValidator(const QString &pattern)
+ {
+ const QRegExp regExp(pattern);
+ Q_ASSERT(regExp.isValid());
+ m_lineEdit->setValidator(new QRegExpValidator(regExp,m_lineEdit));
+ }
+
+ QString TextPropertyEditor::text() const
+ {
+ return m_cachedText;
+ }
+
+ void TextPropertyEditor::markIntermediateState()
+ {
+ if (m_lineEdit->hasAcceptableInput()) {
+ m_lineEdit->setPalette(QPalette());
+ } else {
+ QPalette palette = m_lineEdit->palette();
+ palette.setColor(QPalette::Active, QPalette::Text, Qt::red);
+ m_lineEdit->setPalette(palette);
+ }
+
+ }
+
+ void TextPropertyEditor::setText(const QString &text)
+ {
+ m_cachedText = text;
+ m_lineEdit->setText(stringToEditorString(text, m_validationMode));
+ markIntermediateState();
+ m_textEdited = false;
+ }
+
+ void TextPropertyEditor::slotTextEdited()
+ {
+ m_textEdited = true;
+ }
+
+ void TextPropertyEditor::slotTextChanged(const QString &text) {
+ m_cachedText = editorStringToString(text, m_validationMode);
+ markIntermediateState();
+ if (m_updateMode == UpdateAsYouType)
+ emit textChanged(m_cachedText);
+ }
+
+ void TextPropertyEditor::slotEditingFinished()
+ {
+ if (m_updateMode == UpdateOnFinished && m_textEdited) {
+ emit textChanged(m_cachedText);
+ m_textEdited = false;
+ }
+ }
+
+ void TextPropertyEditor::selectAll() {
+ m_lineEdit->selectAll();
+ }
+
+ void TextPropertyEditor::clear() {
+ m_lineEdit->clear();
+ }
+
+ void TextPropertyEditor::setAlignment(Qt::Alignment alignment) {
+ m_lineEdit->setAlignment(alignment);
+ }
+
+ void TextPropertyEditor::installEventFilter(QObject *filterObject)
+ {
+ if (m_lineEdit)
+ m_lineEdit->installEventFilter(filterObject);
+ }
+
+ void TextPropertyEditor::resizeEvent ( QResizeEvent * event ) {
+ m_lineEdit->resize( event->size());
+ }
+
+ QSize TextPropertyEditor::sizeHint () const {
+ return m_lineEdit->sizeHint ();
+ }
+
+ QSize TextPropertyEditor::minimumSizeHint () const {
+ return m_lineEdit->minimumSizeHint ();
+ }
+
+ // Returns whether newline characters are valid in validationMode.
+ bool TextPropertyEditor::multiLine(TextPropertyValidationMode validationMode) {
+ return validationMode == ValidationMultiLine || validationMode == ValidationStyleSheet || validationMode == ValidationRichText;
+ }
+
+ // Replace newline characters literal "\n" for inline editing in mode ValidationMultiLine
+ QString TextPropertyEditor::stringToEditorString(const QString &s, TextPropertyValidationMode validationMode) {
+ if (s.isEmpty() || !multiLine(validationMode))
+ return s;
+
+ QString rc(s);
+ // protect backslashes
+ rc.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
+ // escape newlines
+ rc.replace(NewLineChar, QString(EscapedNewLine));
+ return rc;
+
+ }
+
+ // Replace literal "\n" by actual new lines for inline editing in mode ValidationMultiLine
+ // Note: As the properties are updated while the user types, it is important
+ // that trailing slashes ('bla\') are not deleted nor ignored, else this will
+ // cause jumping of the cursor
+ QString TextPropertyEditor::editorStringToString(const QString &s, TextPropertyValidationMode validationMode) {
+ if (s.isEmpty() || !multiLine(validationMode))
+ return s;
+
+ QString rc(s);
+ for (int pos = 0; (pos = rc.indexOf(QLatin1Char('\\'),pos)) >= 0 ; ) {
+ // found an escaped character. If not a newline or at end of string, leave as is, else insert '\n'
+ const int nextpos = pos + 1;
+ if (nextpos >= rc.length()) // trailing '\\'
+ break;
+ // Escaped NewLine
+ if (rc.at(nextpos) == QChar(QLatin1Char('n')))
+ rc[nextpos] = NewLineChar;
+ // Remove escape, go past escaped
+ rc.remove(pos,1);
+ pos++;
+ }
+ return rc;
+ }
+
+ bool TextPropertyEditor::hasAcceptableInput() const {
+ return m_lineEdit->hasAcceptableInput();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/textpropertyeditor_p.h b/tools/designer/src/lib/shared/textpropertyeditor_p.h
new file mode 100644
index 0000000000..d92113516e
--- /dev/null
+++ b/tools/designer/src/lib/shared/textpropertyeditor_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef TEXTPROPERTYEDITOR_H
+#define TEXTPROPERTYEDITOR_H
+
+#include "shared_global_p.h"
+#include "shared_enums_p.h"
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+namespace qdesigner_internal {
+
+ class PropertyLineEdit;
+
+ // Inline-Editor for text properties. Does escaping of newline characters
+ // to '\n' and back and provides validation modes. The interface
+ // corresponds to that of QLineEdit.
+ class QDESIGNER_SHARED_EXPORT TextPropertyEditor : public QWidget
+ {
+ TextPropertyEditor(const TextPropertyEditor &);
+ TextPropertyEditor& operator=(const TextPropertyEditor &);
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText USER true)
+ public:
+ enum EmbeddingMode {
+ // Stand-alone widget
+ EmbeddingNone,
+ // Disable frame
+ EmbeddingTreeView,
+ // For editing in forms
+ EmbeddingInPlace
+ };
+
+ enum UpdateMode {
+ // Emit textChanged() as the user types
+ UpdateAsYouType,
+ // Emit textChanged() only when the user finishes (for QUrl, etc.)
+ UpdateOnFinished
+ };
+
+ TextPropertyEditor(QWidget *parent = 0, EmbeddingMode embeddingMode = EmbeddingNone, TextPropertyValidationMode validationMode = ValidationMultiLine);
+
+ TextPropertyValidationMode textPropertyValidationMode() const { return m_validationMode; }
+ void setTextPropertyValidationMode(TextPropertyValidationMode vm);
+
+ UpdateMode updateMode() const { return m_updateMode; }
+ void setUpdateMode(UpdateMode um) { m_updateMode = um; }
+
+ QString text() const;
+
+ virtual QSize sizeHint () const;
+ virtual QSize minimumSizeHint () const;
+
+ void setAlignment(Qt::Alignment alignment);
+
+ bool hasAcceptableInput() const;
+
+ // installs an event filter object on the private QLineEdit
+ void installEventFilter(QObject *filterObject);
+
+ // Replace newline characters by literal "\n" for inline editing
+ // in mode ValidationMultiLine
+ static QString stringToEditorString(const QString &s, TextPropertyValidationMode validationMode = ValidationMultiLine);
+
+ // Replace literal "\n" by actual new lines in mode ValidationMultiLine
+ static QString editorStringToString(const QString &s, TextPropertyValidationMode validationMode = ValidationMultiLine);
+
+ // Returns whether newline characters are valid in validationMode.
+ static bool multiLine(TextPropertyValidationMode validationMode);
+
+ signals:
+ void textChanged(const QString &text);
+ void editingFinished();
+
+ public slots:
+ void setText(const QString &text);
+ void selectAll();
+ void clear();
+
+ protected:
+ void resizeEvent(QResizeEvent * event );
+
+ private slots:
+ void slotTextChanged(const QString &text);
+ void slotTextEdited();
+ void slotEditingFinished();
+
+ private:
+ void setRegExpValidator(const QString &pattern);
+ void markIntermediateState();
+
+ TextPropertyValidationMode m_validationMode;
+ UpdateMode m_updateMode;
+ PropertyLineEdit* m_lineEdit;
+
+ // Cached text containing real newline characters.
+ QString m_cachedText;
+ bool m_textEdited;
+ };
+}
+
+QT_END_NAMESPACE
+
+#endif // TEXTPROPERTYEDITOR_H
diff --git a/tools/designer/src/lib/shared/widgetdatabase.cpp b/tools/designer/src/lib/shared/widgetdatabase.cpp
new file mode 100644
index 0000000000..e452eabcfc
--- /dev/null
+++ b/tools/designer/src/lib/shared/widgetdatabase.cpp
@@ -0,0 +1,865 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "widgetdatabase_p.h"
+#include "widgetfactory_p.h"
+#include "spacer_widget_p.h"
+#include "abstractlanguage.h"
+#include "pluginmanager_p.h"
+#include "qdesigner_widgetbox_p.h"
+#include "qdesigner_utils_p.h"
+#include <ui4_p.h>
+
+#include <QtDesigner/customwidget.h>
+#include <QtDesigner/propertysheet.h>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtXml/QXmlStreamWriter>
+#include <QtCore/QtAlgorithms>
+#include <QtCore/qdebug.h>
+#include <QtCore/QMetaProperty>
+#include <QtCore/QTextStream>
+#include <QtCore/QRegExp>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { debugWidgetDataBase = 0 };
+}
+
+namespace qdesigner_internal {
+
+// ----------------------------------------------------------
+WidgetDataBaseItem::WidgetDataBaseItem(const QString &name, const QString &group)
+ : m_name(name),
+ m_group(group),
+ m_compat(0),
+ m_container(0),
+ m_form(0),
+ m_custom(0),
+ m_promoted(0)
+{
+}
+
+QString WidgetDataBaseItem::name() const
+{
+ return m_name;
+}
+
+void WidgetDataBaseItem::setName(const QString &name)
+{
+ m_name = name;
+}
+
+QString WidgetDataBaseItem::group() const
+{
+ return m_group;
+}
+
+void WidgetDataBaseItem::setGroup(const QString &group)
+{
+ m_group = group;
+}
+
+QString WidgetDataBaseItem::toolTip() const
+{
+ return m_toolTip;
+}
+
+void WidgetDataBaseItem::setToolTip(const QString &toolTip)
+{
+ m_toolTip = toolTip;
+}
+
+QString WidgetDataBaseItem::whatsThis() const
+{
+ return m_whatsThis;
+}
+
+void WidgetDataBaseItem::setWhatsThis(const QString &whatsThis)
+{
+ m_whatsThis = whatsThis;
+}
+
+QString WidgetDataBaseItem::includeFile() const
+{
+ return m_includeFile;
+}
+
+void WidgetDataBaseItem::setIncludeFile(const QString &includeFile)
+{
+ m_includeFile = includeFile;
+}
+
+QIcon WidgetDataBaseItem::icon() const
+{
+ return m_icon;
+}
+
+void WidgetDataBaseItem::setIcon(const QIcon &icon)
+{
+ m_icon = icon;
+}
+
+bool WidgetDataBaseItem::isCompat() const
+{
+ return m_compat;
+}
+
+void WidgetDataBaseItem::setCompat(bool b)
+{
+ m_compat = b;
+}
+
+bool WidgetDataBaseItem::isContainer() const
+{
+ return m_container;
+}
+
+void WidgetDataBaseItem::setContainer(bool b)
+{
+ m_container = b;
+}
+
+bool WidgetDataBaseItem::isCustom() const
+{
+ return m_custom;
+}
+
+void WidgetDataBaseItem::setCustom(bool b)
+{
+ m_custom = b;
+}
+
+QString WidgetDataBaseItem::pluginPath() const
+{
+ return m_pluginPath;
+}
+
+void WidgetDataBaseItem::setPluginPath(const QString &path)
+{
+ m_pluginPath = path;
+}
+
+bool WidgetDataBaseItem::isPromoted() const
+{
+ return m_promoted;
+}
+
+void WidgetDataBaseItem::setPromoted(bool b)
+{
+ m_promoted = b;
+}
+
+QString WidgetDataBaseItem::extends() const
+{
+ return m_extends;
+}
+
+void WidgetDataBaseItem::setExtends(const QString &s)
+{
+ m_extends = s;
+}
+
+void WidgetDataBaseItem::setDefaultPropertyValues(const QList<QVariant> &list)
+{
+ m_defaultPropertyValues = list;
+}
+
+QList<QVariant> WidgetDataBaseItem::defaultPropertyValues() const
+{
+ return m_defaultPropertyValues;
+}
+
+QStringList WidgetDataBaseItem::fakeSlots() const
+{
+ return m_fakeSlots;
+}
+
+void WidgetDataBaseItem::setFakeSlots(const QStringList &fs)
+{
+ m_fakeSlots = fs;
+}
+
+QStringList WidgetDataBaseItem::fakeSignals() const
+{
+ return m_fakeSignals;
+}
+
+void WidgetDataBaseItem::setFakeSignals(const QStringList &fs)
+{
+ m_fakeSignals = fs;
+}
+
+QString WidgetDataBaseItem::addPageMethod() const
+{
+ return m_addPageMethod;
+}
+
+void WidgetDataBaseItem::setAddPageMethod(const QString &m)
+{
+ m_addPageMethod = m;
+}
+
+WidgetDataBaseItem *WidgetDataBaseItem::clone(const QDesignerWidgetDataBaseItemInterface *item)
+{
+ WidgetDataBaseItem *rc = new WidgetDataBaseItem(item->name(), item->group());
+
+ rc->setToolTip(item->toolTip());
+ rc->setWhatsThis(item->whatsThis());
+ rc->setIncludeFile(item->includeFile());
+ rc->setIcon(item->icon());
+ rc->setCompat(item->isCompat());
+ rc->setContainer(item->isContainer());
+ rc->setCustom(item->isCustom() );
+ rc->setPluginPath(item->pluginPath());
+ rc->setPromoted(item->isPromoted());
+ rc->setExtends(item->extends());
+ rc->setDefaultPropertyValues(item->defaultPropertyValues());
+ // container page method, fake slots and signals ignored here.y
+ return rc;
+}
+
+// ----------------------------------------------------------
+WidgetDataBase::WidgetDataBase(QDesignerFormEditorInterface *core, QObject *parent)
+ : QDesignerWidgetDataBaseInterface(parent),
+ m_core(core)
+{
+#define DECLARE_LAYOUT(L, C)
+#define DECLARE_COMPAT_WIDGET(W, C) DECLARE_WIDGET(W, C)
+#define DECLARE_WIDGET(W, C) append(new WidgetDataBaseItem(QString::fromUtf8(#W)));
+
+#include "widgets.table"
+
+#undef DECLARE_COMPAT_WIDGET
+#undef DECLARE_LAYOUT
+#undef DECLARE_WIDGET
+#undef DECLARE_WIDGET_1
+
+ append(new WidgetDataBaseItem(QString::fromUtf8("Line")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("Spacer")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QSplitter")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QLayoutWidget")));
+ // QDesignerWidget is used as central widget and as container for tab widgets, etc.
+ WidgetDataBaseItem *designerWidgetItem = new WidgetDataBaseItem(QString::fromUtf8("QDesignerWidget"));
+ designerWidgetItem->setContainer(true);
+ append(designerWidgetItem);
+ append(new WidgetDataBaseItem(QString::fromUtf8("QDesignerDialog")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QDesignerMenu")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QDesignerMenuBar")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QDesignerDockWidget")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QDesignerQ3WidgetStack")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QAction")));
+ append(new WidgetDataBaseItem(QString::fromUtf8("QButtonGroup")));
+
+ // ### remove me
+ // ### check the casts
+
+#if 0 // ### enable me after 4.1
+ item(indexOfClassName(QLatin1String("QToolBar")))->setContainer(true);
+#endif
+
+ item(indexOfClassName(QLatin1String("QTabWidget")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QGroupBox")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QScrollArea")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QStackedWidget")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QToolBox")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QFrame")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QLayoutWidget")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QDesignerWidget")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QDesignerDialog")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QSplitter")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QMainWindow")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QDockWidget")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QDesignerDockWidget")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QDesignerQ3WidgetStack")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QMdiArea")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QWorkspace")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QWizard")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QWizardPage")))->setContainer(true);
+
+ item(indexOfClassName(QLatin1String("QWidget")))->setContainer(true);
+ item(indexOfClassName(QLatin1String("QDialog")))->setContainer(true);
+}
+
+WidgetDataBase::~WidgetDataBase()
+{
+}
+
+QDesignerFormEditorInterface *WidgetDataBase::core() const
+{
+ return m_core;
+}
+
+int WidgetDataBase::indexOfObject(QObject *object, bool /*resolveName*/) const
+{
+ QExtensionManager *mgr = m_core->extensionManager();
+ QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension*> (mgr, m_core);
+
+ QString id;
+
+ if (lang)
+ id = lang->classNameOf(object);
+
+ if (id.isEmpty())
+ id = WidgetFactory::classNameOf(m_core,object);
+
+ return QDesignerWidgetDataBaseInterface::indexOfClassName(id);
+}
+
+static WidgetDataBaseItem *createCustomWidgetItem(const QDesignerCustomWidgetInterface *c,
+ const QDesignerCustomWidgetData &data)
+{
+ WidgetDataBaseItem *item = new WidgetDataBaseItem(c->name(), c->group());
+ item->setContainer(c->isContainer());
+ item->setCustom(true);
+ item->setIcon(c->icon());
+ item->setIncludeFile(c->includeFile());
+ item->setToolTip(c->toolTip());
+ item->setWhatsThis(c->whatsThis());
+ item->setPluginPath(data.pluginPath());
+ item->setAddPageMethod(data.xmlAddPageMethod());
+ item->setExtends(data.xmlExtends());
+ return item;
+}
+
+void WidgetDataBase::loadPlugins()
+{
+ typedef QMap<QString, int> NameIndexMap;
+ typedef QList<QDesignerWidgetDataBaseItemInterface*> ItemList;
+ typedef QMap<QString, QDesignerWidgetDataBaseItemInterface*> NameItemMap;
+ typedef QSet<QString> NameSet;
+ // 1) create a map of existing custom classes
+ NameIndexMap existingCustomClasses;
+ NameSet nonCustomClasses;
+ const int count = m_items.size();
+ for (int i = 0; i < count; i++) {
+ const QDesignerWidgetDataBaseItemInterface* item = m_items[i];
+ if (item->isCustom() && !item->isPromoted())
+ existingCustomClasses.insert(item->name(), i);
+ else
+ nonCustomClasses.insert(item->name());
+ }
+ // 2) create a list plugins
+ ItemList pluginList;
+ const QDesignerPluginManager *pm = m_core->pluginManager();
+ foreach(QDesignerCustomWidgetInterface* c, pm->registeredCustomWidgets())
+ pluginList += createCustomWidgetItem(c, pm->customWidgetData(c));
+
+ // 3) replace custom classes or add new ones, remove them from existingCustomClasses,
+ // leaving behind deleted items
+ unsigned replacedPlugins = 0;
+ unsigned addedPlugins = 0;
+ unsigned removedPlugins = 0;
+ if (!pluginList.empty()) {
+ ItemList::const_iterator cend = pluginList.constEnd();
+ for (ItemList::const_iterator it = pluginList.constBegin();it != cend; ++it ) {
+ QDesignerWidgetDataBaseItemInterface* pluginItem = *it;
+ const QString pluginName = pluginItem->name();
+ NameIndexMap::iterator existingIt = existingCustomClasses.find(pluginName);
+ if (existingIt == existingCustomClasses.end()) {
+ // Add new class.
+ if (nonCustomClasses.contains(pluginName)) {
+ designerWarning(tr("A custom widget plugin whose class name (%1) matches that of an existing class has been found.").arg(pluginName));
+ } else {
+ append(pluginItem);
+ addedPlugins++;
+ }
+ } else {
+ // replace existing info
+ const int existingIndex = existingIt.value();
+ delete m_items[existingIndex];
+ m_items[existingIndex] = pluginItem;
+ existingCustomClasses.erase(existingIt);
+ replacedPlugins++;
+
+ }
+ }
+ }
+ // 4) remove classes that have not been matched. The stored indexes become invalid while deleting.
+ if (!existingCustomClasses.empty()) {
+ NameIndexMap::const_iterator cend = existingCustomClasses.constEnd();
+ for (NameIndexMap::const_iterator it = existingCustomClasses.constBegin();it != cend; ++it ) {
+ const int index = indexOfClassName(it.key());
+ if (index != -1) {
+ remove(index);
+ removedPlugins++;
+ }
+ }
+ }
+ if (debugWidgetDataBase)
+ qDebug() << "WidgetDataBase::loadPlugins(): " << addedPlugins << " added, " << replacedPlugins << " replaced, " << removedPlugins << "deleted.";
+}
+
+void WidgetDataBase::remove(int index)
+{
+ Q_ASSERT(index < m_items.size());
+ delete m_items.takeAt(index);
+}
+
+QList<QVariant> WidgetDataBase::defaultPropertyValues(const QString &name)
+{
+ WidgetFactory *factory = qobject_cast<WidgetFactory *>(m_core->widgetFactory());
+ Q_ASSERT(factory);
+ // Create non-widgets, widgets in order
+ QObject* object = factory->createObject(name, 0);
+ if (!object)
+ object = factory->createWidget(name, 0);
+ if (!object) {
+ qDebug() << "** WARNING Factory failed to create " << name;
+ return QList<QVariant>();
+ }
+ // Get properties from sheet.
+ QList<QVariant> result;
+ if (const QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(m_core->extensionManager(), object)) {
+ const int propertyCount = sheet->count();
+ for (int i = 0; i < propertyCount; ++i) {
+ result.append(sheet->property(i));
+ }
+ }
+ delete object;
+ return result;
+}
+
+void WidgetDataBase::grabDefaultPropertyValues()
+{
+ const int itemCount = count();
+ for (int i = 0; i < itemCount; ++i) {
+ QDesignerWidgetDataBaseItemInterface *dbItem = item(i);
+ const QList<QVariant> default_prop_values = defaultPropertyValues(dbItem->name());
+ dbItem->setDefaultPropertyValues(default_prop_values);
+ }
+}
+
+void WidgetDataBase::grabStandardWidgetBoxIcons()
+{
+ // At this point, grab the default icons for the non-custom widgets from
+ // the widget box. They will show up in the object inspector.
+ if (const QDesignerWidgetBox *wb = qobject_cast<const QDesignerWidgetBox *>(m_core->widgetBox())) {
+ const QString qWidgetClass = QLatin1String("QWidget");
+ const int itemCount = count();
+ for (int i = 0; i < itemCount; ++i) {
+ QDesignerWidgetDataBaseItemInterface *dbItem = item(i);
+ if (!dbItem->isCustom() && dbItem->icon().isNull()) {
+ // Careful not to catch the layout icons when looking for
+ // QWidget
+ const QString name = dbItem->name();
+ if (name == qWidgetClass) {
+ dbItem->setIcon(wb->iconForWidget(name, QLatin1String("Containers")));
+ } else {
+ dbItem->setIcon(wb->iconForWidget(name));
+ }
+ }
+ }
+ }
+}
+
+// --------------------- Functions relevant generation of new forms based on widgets (apart from the standard templates)
+
+enum { NewFormWidth = 400, NewFormHeight = 300 };
+
+// Check if class is suitable to generate a form from
+static inline bool isExistingTemplate(const QString &className)
+{
+ return className == QLatin1String("QWidget") || className == QLatin1String("QDialog") || className == QLatin1String("QMainWindow");
+}
+
+// Check if class is suitable to generate a form from
+static inline bool suitableForNewForm(const QString &className)
+{
+ if (className.isEmpty()) // Missing custom widget information
+ return false;
+ if (className == QLatin1String("QWorkspace"))
+ return false;
+ if (className == QLatin1String("QSplitter"))
+ return false;
+ if (className.startsWith(QLatin1String("QDesigner")) || className.startsWith(QLatin1String("Q3")) || className.startsWith(QLatin1String("QLayout")))
+ return false;
+ return true;
+}
+
+// Return a list of widget classes from which new forms can be generated.
+// Suitable for 'New form' wizards in integrations.
+QStringList WidgetDataBase::formWidgetClasses(const QDesignerFormEditorInterface *core)
+{
+ static QStringList rc;
+ if (rc.empty()) {
+ const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
+ const int widgetCount = wdb->count();
+ for (int i = 0; i < widgetCount; i++) {
+ const QDesignerWidgetDataBaseItemInterface *item = wdb->item(i);
+ if (item->isContainer() && !item->isCustom() && !item->isPromoted()) {
+ const QString name = item->name(); // Standard Widgets: no existing templates
+ if (!isExistingTemplate(name) && suitableForNewForm(name))
+ rc += name;
+ }
+ }
+ }
+ return rc;
+}
+
+// Return a list of custom widget classes from which new forms can be generated.
+// Suitable for 'New form' wizards in integrations.
+QStringList WidgetDataBase::customFormWidgetClasses(const QDesignerFormEditorInterface *core)
+{
+ QStringList rc;
+ const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
+ const int widgetCount = wdb->count();
+ for (int i = 0; i < widgetCount; i++) { // Custom widgets: check name and base class.
+ const QDesignerWidgetDataBaseItemInterface *item = wdb->item(i);
+ if (item->isContainer() && item->isCustom() && !item->isPromoted()) {
+ if (suitableForNewForm(item->name()) && suitableForNewForm(item->extends()))
+ rc += item->name();
+ }
+ }
+ return rc;
+}
+
+// Get XML for a new form from the widget box. Change objectName/geometry
+// properties to be suitable for new forms
+static QString xmlFromWidgetBox(const QDesignerFormEditorInterface *core, const QString &className, const QString &objectName)
+{
+ typedef QList<DomProperty*> PropertyList;
+
+ QDesignerWidgetBoxInterface::Widget widget;
+ const bool found = QDesignerWidgetBox::findWidget(core->widgetBox(), className, QString(), &widget);
+ if (!found)
+ return QString();
+ DomUI *domUI = QDesignerWidgetBox::xmlToUi(className, widget.domXml(), false);
+ domUI->setAttributeVersion(QLatin1String("4.0"));
+ if (!domUI)
+ return QString();
+ DomWidget *domWidget = domUI->elementWidget();
+ if (!domWidget)
+ return QString();
+ // Properties: Remove the "objectName" property in favour of the name attribute and check geometry.
+ domWidget->setAttributeName(objectName);
+ const QString geometryProperty = QLatin1String("geometry");
+ const QString objectNameProperty = QLatin1String("objectName");
+ PropertyList properties = domWidget->elementProperty();
+ for (PropertyList::iterator it = properties.begin(); it != properties.end(); ) {
+ DomProperty *property = *it;
+ if (property->attributeName() == objectNameProperty) { // remove "objectName"
+ it = properties.erase(it);
+ delete property;
+ } else {
+ if (property->attributeName() == geometryProperty) { // Make sure form is at least 400, 300
+ if (DomRect *geom = property->elementRect()) {
+ if (geom->elementWidth() < NewFormWidth)
+ geom->setElementWidth(NewFormWidth);
+ if (geom->elementHeight() < NewFormHeight)
+ geom->setElementHeight(NewFormHeight);
+ }
+ }
+ ++it;
+ }
+ }
+ // Add a window title property
+ DomString *windowTitleString = new DomString;
+ windowTitleString->setText(objectName);
+ DomProperty *windowTitleProperty = new DomProperty;
+ windowTitleProperty->setAttributeName(QLatin1String("windowTitle"));
+ windowTitleProperty->setElementString(windowTitleString);
+ properties.push_back(windowTitleProperty);
+ // ------
+ domWidget->setElementProperty(properties);
+ // Embed in in DomUI and get string. Omit the version number.
+ domUI->setElementClass(objectName);
+
+ QString rc;
+ { // Serialize domUI
+ QXmlStreamWriter writer(&rc);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ domUI->write(writer);
+ writer.writeEndDocument();
+ }
+ delete domUI;
+ return rc;
+}
+
+// Generate default standard ui new form xml based on the class passed on as similarClassName.
+static QString generateNewFormXML(const QString &className, const QString &similarClassName, const QString &name)
+{
+ QString rc; {
+ QTextStream str(&rc);
+ str << QLatin1String("<ui version=\"4.0\" >\n<class>") << name << QLatin1String("</class>\n")
+ << QLatin1String("<widget class=\"") << className << QLatin1String("\" name=\"") << name << QLatin1String("\" >\n")
+ << QLatin1String("<property name=\"geometry\" >\n<rect><x>0</x><y>0</y><width>")
+ << NewFormWidth << QLatin1String("</width><height>") << NewFormHeight << QLatin1String("</height></rect>\n</property>\n");
+ str << QLatin1String("<property name=\"windowTitle\" >\n<string>") << name << QLatin1String("</string>\n</property>\n");
+
+ if (similarClassName == QLatin1String("QMainWindow")) {
+ str << QLatin1String("<widget class=\"QWidget\" name=\"centralwidget\" />\n");
+ } else {
+ if (similarClassName == QLatin1String("QWizard"))
+ str << QLatin1String("<widget class=\"QWizardPage\" name=\"wizardPage1\" /><widget class=\"QWizardPage\" name=\"wizardPage2\" />\n");
+ }
+ str << QLatin1String("</widget>\n</ui>\n");
+ }
+ return rc;
+}
+
+// Generate a form template using a class name obtained from formWidgetClasses(), customFormWidgetClasses().
+QString WidgetDataBase::formTemplate(const QDesignerFormEditorInterface *core, const QString &className, const QString &objectName)
+{
+ // How to find suitable XML for a class:
+ // 1) Look in widget box (as all the required centralwidgets, tab widget pages, etc. should be there).
+ const QString widgetBoxXml = xmlFromWidgetBox(core, className, objectName);
+ if (!widgetBoxXml.isEmpty())
+ return widgetBoxXml;
+ // 2) If that fails, only custom main windows, custom dialogs and unsupported Qt Widgets should
+ // be left over. Generate something that is similar to the default templates. Find a similar class.
+ const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
+ QString similarClass = QLatin1String("QWidget");
+ const int index = wdb->indexOfClassName(className);
+ if (index != -1) {
+ const QDesignerWidgetDataBaseItemInterface *item = wdb->item(index);
+ similarClass = item->isCustom() ? item->extends() : item->name();
+ }
+ // Generate standard ui based on the class passed on as baseClassName.
+ const QString rc = generateNewFormXML(className, similarClass, objectName);
+ return rc;
+}
+
+// Set a fixed size on a XML template
+QString WidgetDataBase::scaleFormTemplate(const QString &xml, const QSize &size, bool fixed)
+{
+ typedef QList<DomProperty*> PropertyList;
+ DomUI *domUI = QDesignerWidgetBox::xmlToUi(QLatin1String("Form"), xml, false);
+ if (!domUI)
+ return QString();
+ DomWidget *domWidget = domUI->elementWidget();
+ if (!domWidget)
+ return QString();
+ // Properties: Find/Ensure the geometry, minimum and maximum sizes properties
+ const QString geometryPropertyName = QLatin1String("geometry");
+ const QString minimumSizePropertyName = QLatin1String("minimumSize");
+ const QString maximumSizePropertyName = QLatin1String("maximumSize");
+ DomProperty *geomProperty = 0;
+ DomProperty *minimumSizeProperty = 0;
+ DomProperty *maximumSizeProperty = 0;
+
+ PropertyList properties = domWidget->elementProperty();
+ const PropertyList::const_iterator cend = properties.constEnd();
+ for (PropertyList::const_iterator it = properties.constBegin(); it != cend; ++it) {
+ const QString name = (*it)->attributeName();
+ if (name == geometryPropertyName) {
+ geomProperty = *it;
+ } else {
+ if (name == minimumSizePropertyName) {
+ minimumSizeProperty = *it;
+ } else {
+ if (name == maximumSizePropertyName)
+ maximumSizeProperty = *it;
+ }
+ }
+ }
+ if (!geomProperty) {
+ geomProperty = new DomProperty;
+ geomProperty->setAttributeName(geometryPropertyName);
+ geomProperty->setElementRect(new DomRect);
+ properties.push_front(geomProperty);
+ }
+ if (fixed) {
+ if (!minimumSizeProperty) {
+ minimumSizeProperty = new DomProperty;
+ minimumSizeProperty->setAttributeName(minimumSizePropertyName);
+ minimumSizeProperty->setElementSize(new DomSize);
+ properties.push_back(minimumSizeProperty);
+ }
+ if (!maximumSizeProperty) {
+ maximumSizeProperty = new DomProperty;
+ maximumSizeProperty->setAttributeName(maximumSizePropertyName);
+ maximumSizeProperty->setElementSize(new DomSize);
+ properties.push_back(maximumSizeProperty);
+ }
+ }
+ // Set values of geometry, minimum and maximum sizes properties
+ const int width = size.width();
+ const int height = size.height();
+ if (DomRect *geom = geomProperty->elementRect()) {
+ geom->setElementWidth(width);
+ geom->setElementHeight(height);
+ }
+ if (fixed) {
+ if (DomSize *s = minimumSizeProperty->elementSize()) {
+ s->setElementWidth(width);
+ s->setElementHeight(height);
+ }
+ if (DomSize *s = maximumSizeProperty->elementSize()) {
+ s->setElementWidth(width);
+ s->setElementHeight(height);
+ }
+ }
+ // write back
+ domWidget->setElementProperty(properties);
+
+ QString rc;
+ { // serialize domUI
+ QXmlStreamWriter writer(&rc);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ domUI->write(writer);
+ writer.writeEndDocument();
+ }
+
+ delete domUI;
+ return rc;
+}
+
+// ---- free functions
+QDESIGNER_SHARED_EXPORT IncludeSpecification includeSpecification(QString includeFile)
+{
+ const bool global = !includeFile.isEmpty() &&
+ includeFile[0] == QLatin1Char('<') &&
+ includeFile[includeFile.size() - 1] == QLatin1Char('>');
+ if (global) {
+ includeFile.remove(includeFile.size() - 1, 1);
+ includeFile.remove(0, 1);
+ }
+ return IncludeSpecification(includeFile, global ? IncludeGlobal : IncludeLocal);
+}
+
+QDESIGNER_SHARED_EXPORT QString buildIncludeFile(QString includeFile, IncludeType includeType) {
+ if (includeType == IncludeGlobal && !includeFile.isEmpty()) {
+ includeFile.append(QLatin1Char('>'));
+ includeFile.insert(0, QLatin1Char('<'));
+ }
+ return includeFile;
+}
+
+
+/* Appends a derived class to the database inheriting the data of the base class. Used
+ for custom and promoted widgets.
+
+ Depending on whether an entry exists, the existing or a newly created entry is
+ returned. A return value of 0 indicates that the base class could not be found. */
+
+QDESIGNER_SHARED_EXPORT QDesignerWidgetDataBaseItemInterface *
+ appendDerived(QDesignerWidgetDataBaseInterface *db,
+ const QString &className, const QString &group,
+ const QString &baseClassName,
+ const QString &includeFile,
+ bool promoted, bool custom)
+{
+ if (debugWidgetDataBase)
+ qDebug() << "appendDerived " << className << " derived from " << baseClassName;
+ // Check.
+ if (className.isEmpty() || baseClassName.isEmpty()) {
+ qWarning("** WARNING %s called with an empty class names: '%s' extends '%s'.",
+ Q_FUNC_INFO, className.toUtf8().constData(), baseClassName.toUtf8().constData());
+ return 0;
+ }
+ // Check whether item already exists.
+ QDesignerWidgetDataBaseItemInterface *derivedItem = 0;
+ const int existingIndex = db->indexOfClassName(className);
+ if ( existingIndex != -1)
+ derivedItem = db->item(existingIndex);
+ if (derivedItem) {
+ // Check the existing item for base class mismatch. This will likely
+ // happen when loading a file written by an instance with missing plugins.
+ // In that case, just warn and ignore the file properties.
+ //
+ // An empty base class indicates that it is not known (for example, for custom plugins).
+ // In this case, the widget DB is later updated once the widget is created
+ // by DOM (by querying the metaobject). Suppress the warning.
+ const QString existingBaseClass = derivedItem->extends();
+ if (existingBaseClass.isEmpty() || baseClassName == existingBaseClass)
+ return derivedItem;
+
+ // Warn about mismatches
+ designerWarning(QCoreApplication::translate("WidgetDataBase",
+ "The file contains a custom widget '%1' whose base class (%2)"
+ " differs from the current entry in the widget database (%3)."
+ " The widget database is left unchanged.").
+ arg(className, baseClassName, existingBaseClass));
+ return derivedItem;
+ }
+ // Create this item, inheriting its base properties
+ const int baseIndex = db->indexOfClassName(baseClassName);
+ if (baseIndex == -1) {
+ if (debugWidgetDataBase)
+ qDebug() << "appendDerived failed due to missing base class";
+ return 0;
+ }
+ const QDesignerWidgetDataBaseItemInterface *baseItem = db->item(baseIndex);
+ derivedItem = WidgetDataBaseItem::clone(baseItem);
+ // Sort of hack: If base class is QWidget, we most likely
+ // do not want to inherit the container attribute.
+ static const QString qWidgetName = QLatin1String("QWidget");
+ if (baseItem->name() == qWidgetName)
+ derivedItem->setContainer(false);
+ // set new props
+ derivedItem->setName(className);
+ derivedItem->setGroup(group);
+ derivedItem->setCustom(custom);
+ derivedItem->setPromoted(promoted);
+ derivedItem->setExtends(baseClassName);
+ derivedItem->setIncludeFile(includeFile);
+ db->append(derivedItem);
+ return derivedItem;
+}
+
+/* Return a list of database items to which a class can be promoted to. */
+
+QDESIGNER_SHARED_EXPORT WidgetDataBaseItemList
+ promotionCandidates(const QDesignerWidgetDataBaseInterface *db,
+ const QString &baseClassName)
+{
+ WidgetDataBaseItemList rc;
+ // find existing promoted widgets deriving from base.
+ const int count = db->count();
+ for (int i = 0; i < count; ++i) {
+ QDesignerWidgetDataBaseItemInterface *item = db->item(i);
+ if (item->isPromoted() && item->extends() == baseClassName) {
+ rc.push_back(item);
+ }
+ }
+ return rc;
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/widgetdatabase_p.h b/tools/designer/src/lib/shared/widgetdatabase_p.h
new file mode 100644
index 0000000000..4414bbe5c2
--- /dev/null
+++ b/tools/designer/src/lib/shared/widgetdatabase_p.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef WIDGETDATABASE_H
+#define WIDGETDATABASE_H
+
+#include "shared_global_p.h"
+
+#include <QtDesigner/QDesignerWidgetDataBaseInterface>
+
+#include <QtGui/QIcon>
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <QtCore/QPair>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QDesignerCustomWidgetInterface;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT WidgetDataBaseItem: public QDesignerWidgetDataBaseItemInterface
+{
+public:
+ WidgetDataBaseItem(const QString &name = QString(),
+ const QString &group = QString());
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString group() const;
+ void setGroup(const QString &group);
+
+ QString toolTip() const;
+ void setToolTip(const QString &toolTip);
+
+ QString whatsThis() const;
+ void setWhatsThis(const QString &whatsThis);
+
+ QString includeFile() const;
+ void setIncludeFile(const QString &includeFile);
+
+
+ QIcon icon() const;
+ void setIcon(const QIcon &icon);
+
+ bool isCompat() const;
+ void setCompat(bool compat);
+
+ bool isContainer() const;
+ void setContainer(bool b);
+
+ bool isCustom() const;
+ void setCustom(bool b);
+
+ QString pluginPath() const;
+ void setPluginPath(const QString &path);
+
+ bool isPromoted() const;
+ void setPromoted(bool b);
+
+ QString extends() const;
+ void setExtends(const QString &s);
+
+ void setDefaultPropertyValues(const QList<QVariant> &list);
+ QList<QVariant> defaultPropertyValues() const;
+
+ static WidgetDataBaseItem *clone(const QDesignerWidgetDataBaseItemInterface *item);
+
+ QStringList fakeSlots() const;
+ void setFakeSlots(const QStringList &);
+
+ QStringList fakeSignals() const;
+ void setFakeSignals(const QStringList &);
+
+ QString addPageMethod() const;
+ void setAddPageMethod(const QString &m);
+
+private:
+ QString m_name;
+ QString m_group;
+ QString m_toolTip;
+ QString m_whatsThis;
+ QString m_includeFile;
+ QString m_pluginPath;
+ QString m_extends;
+ QString m_addPageMethod;
+ QIcon m_icon;
+ uint m_compat: 1;
+ uint m_container: 1;
+ uint m_form: 1;
+ uint m_custom: 1;
+ uint m_promoted: 1;
+ QList<QVariant> m_defaultPropertyValues;
+ QStringList m_fakeSlots;
+ QStringList m_fakeSignals;
+};
+
+enum IncludeType { IncludeLocal, IncludeGlobal };
+
+typedef QPair<QString, IncludeType> IncludeSpecification;
+
+QDESIGNER_SHARED_EXPORT IncludeSpecification includeSpecification(QString includeFile);
+QDESIGNER_SHARED_EXPORT QString buildIncludeFile(QString includeFile, IncludeType includeType);
+
+class QDESIGNER_SHARED_EXPORT WidgetDataBase: public QDesignerWidgetDataBaseInterface
+{
+ Q_OBJECT
+public:
+ WidgetDataBase(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ virtual ~WidgetDataBase();
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual int indexOfObject(QObject *o, bool resolveName = true) const;
+
+ void remove(int index);
+
+
+ void grabDefaultPropertyValues();
+ void grabStandardWidgetBoxIcons();
+
+ // Helpers for 'New Form' wizards in integrations. Obtain a list of suitable classes and generate XML for them.
+ static QStringList formWidgetClasses(const QDesignerFormEditorInterface *core);
+ static QStringList customFormWidgetClasses(const QDesignerFormEditorInterface *core);
+ static QString formTemplate(const QDesignerFormEditorInterface *core, const QString &className, const QString &objectName);
+
+ // Helpers for 'New Form' wizards: Set a fixed size on a XML form template
+ static QString scaleFormTemplate(const QString &xml, const QSize &size, bool fixed);
+
+public slots:
+ void loadPlugins();
+
+private:
+ QList<QVariant> defaultPropertyValues(const QString &name);
+
+ QDesignerFormEditorInterface *m_core;
+};
+
+QDESIGNER_SHARED_EXPORT QDesignerWidgetDataBaseItemInterface
+ *appendDerived(QDesignerWidgetDataBaseInterface *db,
+ const QString &className,
+ const QString &group,
+ const QString &baseClassName,
+ const QString &includeFile,
+ bool promoted,
+ bool custom);
+
+typedef QList<QDesignerWidgetDataBaseItemInterface*> WidgetDataBaseItemList;
+
+QDESIGNER_SHARED_EXPORT WidgetDataBaseItemList
+ promotionCandidates(const QDesignerWidgetDataBaseInterface *db,
+ const QString &baseClassName);
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETDATABASE_H
diff --git a/tools/designer/src/lib/shared/widgetfactory.cpp b/tools/designer/src/lib/shared/widgetfactory.cpp
new file mode 100644
index 0000000000..3822fecb7f
--- /dev/null
+++ b/tools/designer/src/lib/shared/widgetfactory.cpp
@@ -0,0 +1,897 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::WidgetFactory
+*/
+
+#include "widgetfactory_p.h"
+#include "widgetdatabase_p.h"
+#include "metadatabase_p.h"
+#include "qlayout_widget_p.h"
+#include "qdesigner_widget_p.h"
+#include "qdesigner_tabwidget_p.h"
+#include "qdesigner_toolbox_p.h"
+#include "qdesigner_stackedbox_p.h"
+#include "qdesigner_toolbar_p.h"
+#include "qdesigner_menubar_p.h"
+#include "qdesigner_menu_p.h"
+#include "qdesigner_dockwidget_p.h"
+#include "qdesigner_utils_p.h"
+#include "formwindowbase_p.h"
+
+// shared
+#include "layoutinfo_p.h"
+#include "spacer_widget_p.h"
+#include "layout_p.h"
+#include "abstractintrospection_p.h"
+
+// sdk
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerPropertySheetExtension>
+#include <QtDesigner/QDesignerLanguageExtension>
+#include <QtDesigner/QDesignerFormWindowManagerInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+
+#include <QtGui/QtGui>
+#include <QtGui/QScrollBar>
+#include <QtGui/QFontComboBox>
+#include <QtGui/QAbstractSpinBox>
+#include <QtGui/QLineEdit>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleFactory>
+#include <QtGui/QWizard>
+#include <QtCore/qdebug.h>
+#include <QtCore/QMetaObject>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+static inline bool isAxWidget(const QObject *o)
+{
+ // Is it one of QDesignerAxWidget/QDesignerAxPluginWidget?
+ static const char *axWidgetName = "QDesignerAx";
+ static const unsigned axWidgetNameLen = qstrlen(axWidgetName);
+ return qstrncmp(o->metaObject()->className(), axWidgetName, axWidgetNameLen) == 0;
+}
+#endif
+
+/* Dynamic boolean property indicating object was created by the factory
+ * for the form editor. */
+
+static const char *formEditorDynamicProperty = "_q_formEditorObject";
+
+namespace qdesigner_internal {
+
+// A friendly SpinBox that grants access to its QLineEdit
+class FriendlySpinBox : public QAbstractSpinBox {
+public:
+ friend class WidgetFactory;
+};
+
+// An event filter for form-combo boxes that prevents the embedded line edit
+// from getting edit focus (and drawing blue artifacts/lines). It catches the
+// ChildPolished event when the "editable" property flips to true and the
+// QLineEdit is created and turns off the LineEdit's focus policy.
+
+class ComboEventFilter : public QObject {
+public:
+ explicit ComboEventFilter(QComboBox *parent) : QObject(parent) {}
+ virtual bool eventFilter(QObject *watched, QEvent *event);
+};
+
+bool ComboEventFilter::eventFilter(QObject *watched, QEvent *event)
+{
+ if (event->type() == QEvent::ChildPolished) {
+ QComboBox *cb = static_cast<QComboBox*>(watched);
+ if (QLineEdit *le = cb->lineEdit())
+ le->setFocusPolicy(Qt::NoFocus);
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+/* Watch out for QWizards changing their pages and make sure that not some
+ * selected widget becomes invisible on a hidden page (causing the selection
+ * handles to shine through). Select the wizard in that case in analogy to
+ * the QTabWidget event filters, etc. */
+
+class WizardPageChangeWatcher : public QObject {
+ Q_OBJECT
+public:
+ explicit WizardPageChangeWatcher(QWizard *parent);
+
+public slots:
+ void pageChanged();
+};
+
+WizardPageChangeWatcher::WizardPageChangeWatcher(QWizard *parent) :
+ QObject(parent)
+{
+ connect(parent, SIGNAL(currentIdChanged(int)), this, SLOT(pageChanged()));
+}
+
+void WizardPageChangeWatcher::pageChanged()
+{
+ /* Use a bit more conservative approach than that for the QTabWidget,
+ * change the selection only if a selected child becomes invisible by
+ * changing the page. */
+ QWizard *wizard = static_cast<QWizard *>(parent());
+ QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(wizard);
+ if (!fw)
+ return;
+ QDesignerFormWindowCursorInterface *cursor = fw->cursor();
+ const int selCount = cursor->selectedWidgetCount();
+ for (int i = 0; i < selCount; i++) {
+ if (!cursor->selectedWidget(i)->isVisible()) {
+ fw->clearSelection(false);
+ fw->selectWidget(wizard, true);
+ break;
+ }
+ }
+}
+
+// ---------------- WidgetFactory::Strings
+WidgetFactory::Strings::Strings() :
+ m_alignment(QLatin1String("alignment")),
+ m_bottomMargin(QLatin1String("bottomMargin")),
+ m_geometry(QLatin1String("geometry")),
+ m_leftMargin(QLatin1String("leftMargin")),
+ m_line(QLatin1String("Line")),
+ m_objectName(QLatin1String("objectName")),
+ m_spacerName(QLatin1String("spacerName")),
+ m_orientation(QLatin1String("orientation")),
+ m_q3WidgetStack(QLatin1String("Q3WidgetStack")),
+ m_qAction(QLatin1String("QAction")),
+ m_qButtonGroup(QLatin1String("QButtonGroup")),
+ m_qAxWidget(QLatin1String("QAxWidget")),
+ m_qDialog(QLatin1String("QDialog")),
+ m_qDockWidget(QLatin1String("QDockWidget")),
+ m_qLayoutWidget(QLatin1String("QLayoutWidget")),
+ m_qMenu(QLatin1String("QMenu")),
+ m_qMenuBar(QLatin1String("QMenuBar")),
+ m_qWidget(QLatin1String("QWidget")),
+ m_rightMargin(QLatin1String("rightMargin")),
+ m_sizeHint(QLatin1String("sizeHint")),
+ m_spacer(QLatin1String("Spacer")),
+ m_text(QLatin1String("text")),
+ m_title(QLatin1String("title")),
+ m_topMargin(QLatin1String("topMargin")),
+ m_windowIcon(QLatin1String("windowIcon")),
+ m_windowTitle(QLatin1String("windowTitle"))
+{
+}
+// ---------------- WidgetFactory
+QPointer<QWidget> *WidgetFactory::m_lastPassiveInteractor = new QPointer<QWidget>();
+bool WidgetFactory::m_lastWasAPassiveInteractor = false;
+const char *WidgetFactory::disableStyleCustomPaintingPropertyC = "_q_custom_style_disabled";
+
+WidgetFactory::WidgetFactory(QDesignerFormEditorInterface *core, QObject *parent)
+ : QDesignerWidgetFactoryInterface(parent),
+ m_core(core),
+ m_formWindow(0),
+ m_currentStyle(0)
+{
+}
+
+WidgetFactory::~WidgetFactory()
+{
+}
+
+QDesignerFormWindowInterface *WidgetFactory::currentFormWindow(QDesignerFormWindowInterface *fw)
+{
+ QDesignerFormWindowInterface *was = m_formWindow;
+ m_formWindow = fw;
+ return was;
+}
+
+void WidgetFactory::loadPlugins()
+{
+ m_customFactory.clear();
+
+ QDesignerPluginManager *pluginManager = m_core->pluginManager();
+
+ QList<QDesignerCustomWidgetInterface*> lst = pluginManager->registeredCustomWidgets();
+ foreach (QDesignerCustomWidgetInterface *c, lst) {
+ m_customFactory.insert(c->name(), c);
+ }
+}
+
+// Convencience to create non-widget objects. Returns 0 if unknown
+QObject* WidgetFactory::createObject(const QString &className, QObject* parent) const
+{
+ if (className.isEmpty()) {
+ qWarning("** WARNING %s called with an empty class name", Q_FUNC_INFO);
+ return 0;
+ }
+ if (className == m_strings.m_qAction)
+ return new QAction(parent);
+ if (className == m_strings.m_qButtonGroup)
+ return new QButtonGroup(parent);
+ return 0;
+}
+
+QWidget* WidgetFactory::createCustomWidget(const QString &className, QWidget *parentWidget, bool *creationError) const
+{
+ *creationError = false;
+ CustomWidgetFactoryMap::const_iterator it = m_customFactory.constFind(className);
+ if (it == m_customFactory.constEnd())
+ return 0;
+
+ QDesignerCustomWidgetInterface *factory = it.value();
+ QWidget *rc = factory->createWidget(parentWidget);
+ // shouldn't happen
+ if (!rc) {
+ *creationError = true;
+ designerWarning(tr("The custom widget factory registered for widgets of class %1 returned 0.").arg(className));
+ return 0;
+ }
+ // Figure out the base class unless it is known
+ static QSet<QString> knownCustomClasses;
+ if (!knownCustomClasses.contains(className)) {
+ QDesignerWidgetDataBaseInterface *wdb = m_core->widgetDataBase();
+ const int widgetInfoIndex = wdb->indexOfObject(rc, false);
+ if (widgetInfoIndex != -1) {
+ if (wdb->item(widgetInfoIndex)->extends().isEmpty()) {
+ const QDesignerMetaObjectInterface *mo = core()->introspection()->metaObject(rc)->superClass();
+ // If we hit on a 'Q3DesignerXXWidget' that claims to be a 'Q3XXWidget', step
+ // over.
+ if (mo && mo->className() == className)
+ mo = mo->superClass();
+ while (mo != 0) {
+ if (core()->widgetDataBase()->indexOfClassName(mo->className()) != -1) {
+ wdb->item(widgetInfoIndex)->setExtends(mo->className());
+ break;
+ }
+ mo = mo->superClass();
+ }
+ }
+ knownCustomClasses.insert(className);
+ }
+ }
+ // Since a language plugin may lie about its names, like Qt Jambi
+ // does, return immediately here...
+ QDesignerLanguageExtension *lang =
+ qt_extension<QDesignerLanguageExtension *>(m_core->extensionManager(), m_core);
+ if (lang)
+ return rc;
+
+#ifdef Q_OS_WIN
+ if (isAxWidget(rc))
+ return rc;
+#endif
+ // Check for mismatched class names which is hard to track.
+ // Perform literal comparison first for QAxWidget, for which a meta object hack is in effect.
+ const char *createdClassNameC = rc->metaObject()->className();
+ const QByteArray classNameB = className.toUtf8();
+ const char *classNameC = classNameB.constData();
+
+ if (qstrcmp(createdClassNameC, classNameC) && !rc->inherits(classNameC))
+ designerWarning(tr("A class name mismatch occurred when creating a widget using the custom widget factory registered for widgets of class %1."
+ " It returned a widget of class %2.").arg(className).arg(QString::fromUtf8(createdClassNameC)));
+ return rc;
+}
+
+
+QWidget *WidgetFactory::createWidget(const QString &widgetName, QWidget *parentWidget) const
+{
+ if (widgetName.isEmpty()) {
+ qWarning("** WARNING %s called with an empty class name", Q_FUNC_INFO);
+ return 0;
+ }
+ // Preview or for form window?
+ QDesignerFormWindowInterface *fw = m_formWindow;
+ if (! fw)
+ fw = QDesignerFormWindowInterface::findFormWindow(parentWidget);
+
+ QWidget *w = 0;
+ do {
+ // 1) custom. If there is an explicit failure(factory wants to indicate something is wrong),
+ // return 0, do not try to find fallback, which might be worse in the case of Q3 widget.
+ bool customWidgetCreationError;
+ w = createCustomWidget(widgetName, parentWidget, &customWidgetCreationError);
+ if (w) {
+ break;
+ } else {
+ if (customWidgetCreationError)
+ return 0;
+ }
+
+ // 2) Special widgets
+ if (widgetName == m_strings.m_line) {
+ w = new Line(parentWidget);
+ } else if (widgetName == m_strings.m_qDockWidget) {
+ w = new QDesignerDockWidget(parentWidget);
+ } else if (widgetName == m_strings.m_qMenuBar) {
+ w = new QDesignerMenuBar(parentWidget);
+ } else if (widgetName == m_strings.m_qMenu) {
+ w = new QDesignerMenu(parentWidget);
+ } else if (widgetName == m_strings.m_spacer) {
+ w = new Spacer(parentWidget);
+ } else if (widgetName == m_strings.m_qDockWidget) {
+ w = new QDesignerDockWidget(parentWidget);
+ } else if (widgetName == m_strings.m_qLayoutWidget) {
+ w = fw ? new QLayoutWidget(fw, parentWidget) : new QWidget(parentWidget);
+ } else if (widgetName == m_strings.m_qDialog) {
+ if (fw) {
+ w = new QDesignerDialog(fw, parentWidget);
+ } else {
+ w = new QDialog(parentWidget);
+ }
+ } else if (widgetName == m_strings.m_qWidget) {
+ /* We want a 'QDesignerWidget' that draws a grid only for widget
+ * forms and container extension pages (not for preview and not
+ * for normal QWidget children on forms (legacy) */
+ if (fw && parentWidget) {
+ if (qt_extension<QDesignerContainerExtension*>(m_core->extensionManager(), parentWidget)) {
+ w = new QDesignerWidget(fw, parentWidget);
+ } else {
+ if (const FormWindowBase *fwb = qobject_cast<FormWindowBase *>(fw))
+ if (parentWidget == fwb->formContainer())
+ w = new QDesignerWidget(fw, parentWidget);
+ }
+ }
+ if (!w)
+ w = new QWidget(parentWidget);
+ }
+ if (w)
+ break;
+
+ // 3) table
+ const QByteArray widgetNameBA = widgetName.toUtf8();
+ const char *widgetNameC = widgetNameBA.constData();
+
+ if (w) { // symmetry for macro
+ }
+
+#define DECLARE_LAYOUT(L, C)
+#define DECLARE_COMPAT_WIDGET(W, C) /*DECLARE_WIDGET(W, C)*/
+#define DECLARE_WIDGET(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(parentWidget); }
+#define DECLARE_WIDGET_1(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(0, parentWidget); }
+
+#include "widgets.table"
+
+#undef DECLARE_COMPAT_WIDGET
+#undef DECLARE_LAYOUT
+#undef DECLARE_WIDGET
+#undef DECLARE_WIDGET_1
+
+ if (w)
+ break;
+ // 4) fallBack
+ const QString fallBackBaseClass = m_strings.m_qWidget;
+ QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase();
+ QDesignerWidgetDataBaseItemInterface *item = db->item(db->indexOfClassName(widgetName));
+ if (item == 0) {
+ // Emergency: Create, derived from QWidget
+ QString includeFile = widgetName.toLower();
+ includeFile += QLatin1String(".h");
+ item = appendDerived(db,widgetName, tr("%1 Widget").arg(widgetName),fallBackBaseClass,
+ includeFile, true, true);
+ Q_ASSERT(item);
+ }
+ QString baseClass = item->extends();
+ if (baseClass.isEmpty()) {
+ // Currently happens in the case of Q3-Support widgets
+ baseClass =fallBackBaseClass;
+ }
+ w = createWidget(baseClass, parentWidget);
+ promoteWidget(core(),w,widgetName);
+ } while (false);
+
+ Q_ASSERT(w != 0);
+ if (m_currentStyle)
+ w->setStyle(m_currentStyle);
+ initializeCommon(w);
+ if (fw) { // form editor initialization
+ initialize(w);
+ } else { // preview-only initialization
+ initializePreview(w);
+ }
+ return w;
+}
+
+QString WidgetFactory::classNameOf(QDesignerFormEditorInterface *c, const QObject* o)
+{
+ if (o == 0)
+ return QString();
+
+ const char *className = o->metaObject()->className();
+ if (!o->isWidgetType())
+ return QLatin1String(className);
+ const QWidget *w = static_cast<const QWidget*>(o);
+ // check promoted before designer special
+ const QString customClassName = promotedCustomClassName(c, const_cast<QWidget*>(w));
+ if (!customClassName.isEmpty())
+ return customClassName;
+ if (qobject_cast<const QDesignerMenuBar*>(w))
+ return QLatin1String("QMenuBar");
+ else if (qobject_cast<const QDesignerMenu*>(w))
+ return QLatin1String("QMenu");
+ else if (qobject_cast<const QDesignerDockWidget*>(w))
+ return QLatin1String("QDockWidget");
+ else if (qobject_cast<const QDesignerDialog*>(w))
+ return QLatin1String("QDialog");
+ else if (qobject_cast<const QDesignerWidget*>(w))
+ return QLatin1String("QWidget");
+#ifdef Q_OS_WIN
+ else if (isAxWidget(w))
+ return QLatin1String("QAxWidget");
+#endif
+ else if (qstrcmp(className, "QDesignerQ3WidgetStack") == 0)
+ return QLatin1String("Q3WidgetStack");
+
+ return QLatin1String(className);
+}
+
+QLayout *WidgetFactory::createUnmanagedLayout(QWidget *parentWidget, int type)
+{
+ switch (type) {
+ case LayoutInfo::HBox:
+ return new QHBoxLayout(parentWidget);
+ case LayoutInfo::VBox:
+ return new QVBoxLayout(parentWidget);
+ case LayoutInfo::Grid:
+ return new QGridLayout(parentWidget);
+ case LayoutInfo::Form:
+ return new QFormLayout(parentWidget);
+ default:
+ Q_ASSERT(0);
+ break;
+ }
+ return 0;
+}
+
+
+/*! Creates a layout on the widget \a widget of the type \a type
+ which can be \c HBox, \c VBox or \c Grid.
+*/
+
+QLayout *WidgetFactory::createLayout(QWidget *widget, QLayout *parentLayout, int type) const // ### (sizepolicy)
+{
+ QDesignerMetaDataBaseInterface *metaDataBase = core()->metaDataBase();
+
+ if (parentLayout == 0) {
+ QWidget *page = containerOfWidget(widget);
+ if (page) {
+ widget = page;
+ } else {
+ const QString msg = tr("The current page of the container '%1' (%2) could not be determined while creating a layout."
+"This indicates an inconsistency in the ui-file, probably a layout being constructed on a container widget.").arg(widget->objectName()).arg(classNameOf(core(), widget));
+ designerWarning(msg);
+ }
+ }
+
+ Q_ASSERT(metaDataBase->item(widget) != 0); // ensure the widget is managed
+
+ if (parentLayout == 0 && metaDataBase->item(widget->layout()) == 0) {
+ parentLayout = widget->layout();
+ }
+
+ QWidget *parentWidget = parentLayout != 0 ? 0 : widget;
+
+ QLayout *layout = createUnmanagedLayout(parentWidget, type);
+ metaDataBase->add(layout); // add the layout in the MetaDataBase
+
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), layout);
+
+ sheet->setChanged(sheet->indexOf(m_strings.m_objectName), true);
+ if (widget->inherits("Q3GroupBox")) {
+ layout->setContentsMargins(widget->style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
+ widget->style()->pixelMetric(QStyle::PM_LayoutTopMargin),
+ widget->style()->pixelMetric(QStyle::PM_LayoutRightMargin),
+ widget->style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
+ QGridLayout *grid = qobject_cast<QGridLayout *>(layout);
+ if (grid) {
+ grid->setHorizontalSpacing(-1);
+ grid->setVerticalSpacing(-1);
+ } else {
+ layout->setSpacing(-1);
+ }
+ layout->setAlignment(Qt::AlignTop);
+ // Just to ensure; before 4.3 orientation property was always set (now only for QSplitter class).
+ // Calling Q3GroupBox::setOrientation() invoked in turn setSpacing(0). Below fixes that
+ widget->layout()->setSpacing(-1);
+ } else if (widget->inherits("QLayoutWidget")) {
+ sheet->setProperty(sheet->indexOf(m_strings.m_leftMargin), 0);
+ sheet->setProperty(sheet->indexOf(m_strings.m_topMargin), 0);
+ sheet->setProperty(sheet->indexOf(m_strings.m_rightMargin), 0);
+ sheet->setProperty(sheet->indexOf(m_strings.m_bottomMargin), 0);
+ }
+
+ if (sheet) {
+ const int index = sheet->indexOf(m_strings.m_alignment);
+ if (index != -1)
+ sheet->setChanged(index, true);
+ }
+
+ if (metaDataBase->item(widget->layout()) == 0) {
+ Q_ASSERT(layout->parent() == 0);
+ QBoxLayout *box = qobject_cast<QBoxLayout*>(widget->layout());
+ if (!box) { // we support only unmanaged box layouts
+ const QString msg = tr("Attempt to add a layout to a widget '%1' (%2) which already has an unmanaged layout of type %3.\n"
+ "This indicates an inconsistency in the ui-file.").
+ arg(widget->objectName()).arg(classNameOf(core(), widget)).arg(classNameOf(core(), widget->layout()));
+ designerWarning(msg);
+ return 0;
+ }
+ box->addLayout(layout);
+ }
+
+ return layout;
+}
+
+/*! Returns the widget into which children should be inserted when \a
+ w is a container known to designer.
+
+ Usually, it is \a w itself, but there are exceptions (for example, a
+ tabwidget is known to designer as a container, but the child
+ widgets should be inserted into the current page of the
+ tabwidget. In this case, the current page of
+ the tabwidget would be returned.)
+ */
+QWidget* WidgetFactory::containerOfWidget(QWidget *w) const
+{
+ if (QDesignerContainerExtension *container = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), w))
+ return container->widget(container->currentIndex());
+
+ return w;
+}
+
+/*! Returns the actual designer widget of the container \a w. This is
+ normally \a w itself, but it might be a parent or grand parent of \a w
+ (for example, when working with a tabwidget and \a w is the container which
+ contains and layouts children, but the actual widget known to
+ designer is the tabwidget which is the parent of \a w. In this case,
+ the tabwidget would be returned.)
+*/
+
+QWidget* WidgetFactory::widgetOfContainer(QWidget *w) const
+{
+ // ### cleanup
+ if (!w)
+ return 0;
+ if (w->parentWidget() && w->parentWidget()->parentWidget() &&
+ w->parentWidget()->parentWidget()->parentWidget() &&
+ qobject_cast<QToolBox*>(w->parentWidget()->parentWidget()->parentWidget()))
+ return w->parentWidget()->parentWidget()->parentWidget();
+
+ while (w != 0) {
+ if (core()->widgetDataBase()->isContainer(w) ||
+ (w && qobject_cast<QDesignerFormWindowInterface*>(w->parentWidget())))
+ return w;
+
+ w = w->parentWidget();
+ }
+
+ return w;
+}
+
+QDesignerFormEditorInterface *WidgetFactory::core() const
+{
+ return m_core;
+}
+
+// Necessary initializations for form editor/preview objects
+void WidgetFactory::initializeCommon(QWidget *widget) const
+{
+ // Apply style
+ if (m_currentStyle)
+ widget->setStyle(m_currentStyle);
+ // Prevent the wizard from emulating the Windows Vista Theme.
+ // This theme (in both Aero and Basic mode) is tricky to
+ // emulate properly in designer due to 1) the manipulation of the non-client area of
+ // the top-level window, and 2) the upper-right location of the Back button.
+ // The wizard falls back to QWizard::ModernStyle whenever the Vista theme
+ // would normally apply.
+ if (QWizard *wizard = qobject_cast<QWizard *>(widget)) {
+ wizard->setProperty("_q_wizard_vista_off", QVariant(true));
+ return;
+ }
+}
+
+// Necessary initializations for preview objects
+void WidgetFactory::initializePreview(QWidget *widget) const
+{
+
+ if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget)) {
+ QStackedWidgetPreviewEventFilter::install(stackedWidget); // Add browse button only.
+ return;
+ }
+}
+
+// Necessary initializations for form editor objects
+void WidgetFactory::initialize(QObject *object) const
+{
+ // Indicate that this is a form object (for QDesignerFormWindowInterface::findFormWindow)
+ object->setProperty(formEditorDynamicProperty, QVariant(true));
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension*>(m_core->extensionManager(), object);
+ if (!sheet)
+ return;
+
+ sheet->setChanged(sheet->indexOf(m_strings.m_objectName), true);
+
+ if (!object->isWidgetType()) {
+ if (qobject_cast<QAction*>(object))
+ sheet->setChanged(sheet->indexOf(m_strings.m_text), true);
+ return;
+ }
+
+ QWidget *widget = static_cast<QWidget*>(object);
+ const bool isMenu = qobject_cast<QMenu*>(widget);
+ const bool isMenuBar = !isMenu && qobject_cast<QMenuBar*>(widget);
+
+ widget->setAttribute(Qt::WA_TransparentForMouseEvents, false);
+ widget->setFocusPolicy((isMenu || isMenuBar) ? Qt::StrongFocus : Qt::NoFocus);
+
+ if (!isMenu)
+ sheet->setChanged(sheet->indexOf(m_strings.m_geometry), true);
+
+ if (qobject_cast<Spacer*>(widget)) {
+ sheet->setChanged(sheet->indexOf(m_strings.m_spacerName), true);
+ return;
+ }
+
+ const int o = sheet->indexOf(m_strings.m_orientation);
+ if (o != -1 && widget->inherits("QSplitter"))
+ sheet->setChanged(o, true);
+
+ if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
+ ToolBarEventFilter::install(toolBar);
+ sheet->setVisible(sheet->indexOf(m_strings.m_windowTitle), true);
+ toolBar->setFloatable(false); // prevent toolbars from being dragged off
+ return;
+ }
+
+ if (qobject_cast<QDockWidget*>(widget)) {
+ sheet->setVisible(sheet->indexOf(m_strings.m_windowTitle), true);
+ sheet->setVisible(sheet->indexOf(m_strings.m_windowIcon), true);
+ return;
+ }
+
+ if (isMenu) {
+ sheet->setChanged(sheet->indexOf(m_strings.m_title), true);
+ return;
+ }
+ // helpers
+ if (QToolBox *toolBox = qobject_cast<QToolBox*>(widget)) {
+ QToolBoxHelper::install(toolBox);
+ return;
+ }
+ if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget)) {
+ QStackedWidgetEventFilter::install(stackedWidget);
+ return;
+ }
+ if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(widget)) {
+ QTabWidgetEventFilter::install(tabWidget);
+ return;
+ }
+ // Prevent embedded line edits from getting focus
+ if (QAbstractSpinBox *asb = qobject_cast<QAbstractSpinBox *>(widget)) {
+ if (QLineEdit *lineEdit = static_cast<FriendlySpinBox*>(asb)->lineEdit())
+ lineEdit->setFocusPolicy(Qt::NoFocus);
+ return;
+ }
+ if (QComboBox *cb = qobject_cast<QComboBox *>(widget)) {
+ if (QFontComboBox *fcb = qobject_cast<QFontComboBox *>(widget)) {
+ fcb->lineEdit()->setFocusPolicy(Qt::NoFocus); // Always present
+ return;
+ }
+ cb->installEventFilter(new ComboEventFilter(cb));
+ return;
+ }
+ if (QWizard *wz = qobject_cast<QWizard *>(widget)) {
+ WizardPageChangeWatcher *pw = new WizardPageChangeWatcher(wz);
+ Q_UNUSED(pw);
+ }
+}
+
+static inline QString classNameOfStyle(const QStyle *s)
+{
+ return QLatin1String(s->metaObject()->className());
+}
+
+QString WidgetFactory::styleName() const
+{
+ return classNameOfStyle(style());
+}
+
+static inline bool isApplicationStyle(const QString &styleName)
+{
+ return styleName.isEmpty() || styleName == classNameOfStyle(qApp->style());
+}
+
+void WidgetFactory::setStyleName(const QString &styleName)
+{
+ m_currentStyle = isApplicationStyle(styleName) ? static_cast<QStyle*>(0) : getStyle(styleName);
+}
+
+QStyle *WidgetFactory::style() const
+{
+ return m_currentStyle ? m_currentStyle : qApp->style();
+}
+
+QStyle *WidgetFactory::getStyle(const QString &styleName)
+{
+ if (isApplicationStyle(styleName))
+ return qApp->style();
+
+ StyleCache::iterator it = m_styleCache.find(styleName);
+ if (it == m_styleCache.end()) {
+ QStyle *style = QStyleFactory::create(styleName);
+ if (!style) {
+ const QString msg = tr("Cannot create style '%1'.").arg(styleName);
+ designerWarning(msg);
+ return 0;
+ }
+ it = m_styleCache.insert(styleName, style);
+ }
+ return it.value();
+}
+
+void WidgetFactory::applyStyleTopLevel(const QString &styleName, QWidget *w)
+{
+ if (QStyle *style = getStyle(styleName))
+ applyStyleToTopLevel(style, w);
+}
+
+void WidgetFactory::applyStyleToTopLevel(QStyle *style, QWidget *widget)
+{
+ const QPalette standardPalette = style->standardPalette();
+ if (widget->style() == style && widget->palette() == standardPalette)
+ return;
+
+ widget->setStyle(style);
+ widget->setPalette(standardPalette);
+ const QWidgetList lst = qFindChildren<QWidget*>(widget);
+ const QWidgetList::const_iterator cend = lst.constEnd();
+ for (QWidgetList::const_iterator it = lst.constBegin(); it != cend; ++it)
+ (*it)->setStyle(style);
+}
+
+// Check for 'interactor' click on a tab bar,
+// which can appear within a QTabWidget or as a standalone widget.
+
+static bool isTabBarInteractor(const QTabBar *tabBar)
+{
+ // Tabbar embedded in Q(Designer)TabWidget, ie, normal tab widget case
+ if (qobject_cast<const QTabWidget*>(tabBar->parentWidget()))
+ return true;
+
+ // Standalone tab bar on the form. Return true for tab rect areas
+ // only to allow the user to select the tab bar by clicking outside the actual tabs.
+ const int count = tabBar->count();
+ if (count == 0)
+ return false;
+
+ // click into current tab: No Interaction
+ const int currentIndex = tabBar->currentIndex();
+ const QPoint pos = tabBar->mapFromGlobal(QCursor::pos());
+ if (tabBar->tabRect(currentIndex).contains(pos))
+ return false;
+
+ // click outside: No Interaction
+ const QRect geometry = QRect(QPoint(0, 0), tabBar->size());
+ if (!geometry.contains(pos))
+ return false;
+ // click into another tab: Let's interact, switch tabs.
+ for (int i = 0; i < count; i++)
+ if (tabBar->tabRect(i).contains(pos))
+ return true;
+ return false;
+}
+
+bool WidgetFactory::isPassiveInteractor(QWidget *widget)
+{
+ static const QString qtPassive = QLatin1String("__qt__passive_");
+ if (m_lastPassiveInteractor != 0 && (QWidget*)(*m_lastPassiveInteractor) == widget)
+ return m_lastWasAPassiveInteractor;
+
+ if (QApplication::activePopupWidget() || widget == 0) // if a popup is open, we have to make sure that this one is closed, else X might do funny things
+ return true;
+
+ m_lastWasAPassiveInteractor = false;
+ (*m_lastPassiveInteractor) = widget;
+
+ if (const QTabBar *tabBar = qobject_cast<const QTabBar*>(widget)) {
+ if (isTabBarInteractor(tabBar))
+ m_lastWasAPassiveInteractor = true;
+ return m_lastWasAPassiveInteractor;
+ } else if (qobject_cast<QSizeGrip*>(widget))
+ return (m_lastWasAPassiveInteractor = true);
+ else if (qobject_cast<QMdiSubWindow*>(widget))
+ return (m_lastWasAPassiveInteractor = true);
+ else if (qobject_cast<QAbstractButton*>(widget) && (qobject_cast<QTabBar*>(widget->parent()) || qobject_cast<QToolBox*>(widget->parent())))
+ return (m_lastWasAPassiveInteractor = true);
+ else if (qobject_cast<QMenuBar*>(widget))
+ return (m_lastWasAPassiveInteractor = true);
+ else if (qobject_cast<QToolBar*>(widget))
+ return (m_lastWasAPassiveInteractor = true);
+ else if (qobject_cast<QScrollBar*>(widget)) {
+ // A scroll bar is an interactor on a QAbstractScrollArea only.
+ if (const QWidget *parent = widget->parentWidget()) {
+ const QString objectName = parent->objectName();
+ static const QString scrollAreaVContainer = QLatin1String("qt_scrollarea_vcontainer");
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+ void formWindowAdded(QDesignerFormWindowInterface *formWindow);
+ static const QString scrollAreaHContainer = QLatin1String("qt_scrollarea_hcontainer");
+ if (objectName == scrollAreaVContainer || objectName == scrollAreaHContainer) {
+ m_lastWasAPassiveInteractor = true;
+ return m_lastWasAPassiveInteractor;
+ }
+ }
+ } else if (qstrcmp(widget->metaObject()->className(), "QDockWidgetTitle") == 0)
+ return (m_lastWasAPassiveInteractor = true);
+ else if (qstrcmp(widget->metaObject()->className(), "QWorkspaceTitleBar") == 0)
+ return (m_lastWasAPassiveInteractor = true);
+ else if (widget->objectName().startsWith(qtPassive))
+ return (m_lastWasAPassiveInteractor = true);
+ return m_lastWasAPassiveInteractor;
+}
+
+void WidgetFactory::formWindowAdded(QDesignerFormWindowInterface *formWindow)
+{
+ setFormWindowStyle(formWindow);
+}
+
+void WidgetFactory::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+{
+ setFormWindowStyle(formWindow);
+}
+
+void WidgetFactory::setFormWindowStyle(QDesignerFormWindowInterface *formWindow)
+{
+ if (FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow))
+ setStyleName(fwb->styleName());
+}
+
+bool WidgetFactory::isFormEditorObject(const QObject *object)
+{
+ return object->property(formEditorDynamicProperty).isValid();
+}
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#include "widgetfactory.moc"
diff --git a/tools/designer/src/lib/shared/widgetfactory_p.h b/tools/designer/src/lib/shared/widgetfactory_p.h
new file mode 100644
index 0000000000..1a053ed7a7
--- /dev/null
+++ b/tools/designer/src/lib/shared/widgetfactory_p.h
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef WIDGETFACTORY_H
+#define WIDGETFACTORY_H
+
+#include "shared_global_p.h"
+#include "pluginmanager_p.h"
+
+#include <QtDesigner/QDesignerWidgetFactoryInterface>
+
+#include <QtCore/QMap>
+#include <QtCore/QHash>
+#include <QtCore/QVariant>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QWidget;
+class QLayout;
+class QDesignerFormEditorInterface;
+class QDesignerCustomWidgetInterface;
+class QDesignerFormWindowInterface;
+class QStyle;
+
+namespace qdesigner_internal {
+
+class QDESIGNER_SHARED_EXPORT WidgetFactory: public QDesignerWidgetFactoryInterface
+{
+ Q_OBJECT
+public:
+ explicit WidgetFactory(QDesignerFormEditorInterface *core, QObject *parent = 0);
+ ~WidgetFactory();
+
+ virtual QWidget* containerOfWidget(QWidget *widget) const;
+ virtual QWidget* widgetOfContainer(QWidget *widget) const;
+
+ QObject* createObject(const QString &className, QObject* parent) const;
+
+ virtual QWidget *createWidget(const QString &className, QWidget *parentWidget) const;
+ virtual QLayout *createLayout(QWidget *widget, QLayout *layout, int type) const;
+
+ virtual bool isPassiveInteractor(QWidget *widget);
+ virtual void initialize(QObject *object) const;
+ void initializeCommon(QWidget *object) const;
+ void initializePreview(QWidget *object) const;
+
+
+ virtual QDesignerFormEditorInterface *core() const;
+
+ static QString classNameOf(QDesignerFormEditorInterface *core, const QObject* o);
+
+ QDesignerFormWindowInterface *currentFormWindow(QDesignerFormWindowInterface *fw);
+
+ static QLayout *createUnmanagedLayout(QWidget *parentWidget, int type);
+
+ // The widget factory maintains a cache of styles which it owns.
+ QString styleName() const;
+ void setStyleName(const QString &styleName);
+
+ /* Return a cached style matching the name or QApplication's style if
+ * it is the default. */
+ QStyle *getStyle(const QString &styleName);
+ // Return the current style used by the factory. This either a cached one
+ // or QApplication's style */
+ QStyle *style() const;
+
+ // Apply one of the cached styles or QApplication's style to a toplevel widget.
+ void applyStyleTopLevel(const QString &styleName, QWidget *w);
+ static void applyStyleToTopLevel(QStyle *style, QWidget *widget);
+
+ // Return whether object was created by the factory for the form editor.
+ static bool isFormEditorObject(const QObject *o);
+
+ // Boolean dynamic property to set on widgets to prevent custom
+ // styles from interfering
+ static const char *disableStyleCustomPaintingPropertyC;
+
+public slots:
+ void loadPlugins();
+
+private slots:
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+ void formWindowAdded(QDesignerFormWindowInterface *formWindow);
+
+private:
+ struct Strings { // Reduce string allocations by storing predefined strings
+ Strings();
+ const QString m_alignment;
+ const QString m_bottomMargin;
+ const QString m_geometry;
+ const QString m_leftMargin;
+ const QString m_line;
+ const QString m_objectName;
+ const QString m_spacerName;
+ const QString m_orientation;
+ const QString m_q3WidgetStack;
+ const QString m_qAction;
+ const QString m_qButtonGroup;
+ const QString m_qAxWidget;
+ const QString m_qDialog;
+ const QString m_qDockWidget;
+ const QString m_qLayoutWidget;
+ const QString m_qMenu;
+ const QString m_qMenuBar;
+ const QString m_qWidget;
+ const QString m_rightMargin;
+ const QString m_sizeHint;
+ const QString m_spacer;
+ const QString m_text;
+ const QString m_title;
+ const QString m_topMargin;
+ const QString m_windowIcon;
+ const QString m_windowTitle;
+ };
+
+ QWidget* createCustomWidget(const QString &className, QWidget *parentWidget, bool *creationError) const;
+ QDesignerFormWindowInterface *findFormWindow(QWidget *parentWidget) const;
+ void setFormWindowStyle(QDesignerFormWindowInterface *formWindow);
+
+ const Strings m_strings;
+ QDesignerFormEditorInterface *m_core;
+ typedef QMap<QString, QDesignerCustomWidgetInterface*> CustomWidgetFactoryMap;
+ CustomWidgetFactoryMap m_customFactory;
+ QDesignerFormWindowInterface *m_formWindow;
+
+ // Points to the cached style or 0 if the default (qApp) is active
+ QStyle *m_currentStyle;
+ typedef QHash<QString, QStyle *> StyleCache;
+ StyleCache m_styleCache;
+
+ static QPointer<QWidget> *m_lastPassiveInteractor;
+ static bool m_lastWasAPassiveInteractor;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif // WIDGETFACTORY_H
diff --git a/tools/designer/src/lib/shared/zoomwidget.cpp b/tools/designer/src/lib/shared/zoomwidget.cpp
new file mode 100644
index 0000000000..f4ab48e6e3
--- /dev/null
+++ b/tools/designer/src/lib/shared/zoomwidget.cpp
@@ -0,0 +1,578 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "zoomwidget_p.h"
+
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QGraphicsProxyWidget>
+#include <QtGui/QMenu>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QScrollBar>
+
+#include <QtCore/QTextStream>
+#include <QtCore/qmath.h>
+#include <QtCore/QDebug>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QAction*> ActionList;
+typedef QList<QGraphicsItem *> GraphicsItemList;
+
+enum { debugZoomWidget = 0 };
+
+static const int menuZoomList[] = { 100, 25, 50, 75, 125, 150 , 175, 200 };
+
+static inline QSize qCeiling(const QSizeF &s)
+{
+ return QSize(qCeil(s.width()), qCeil(s.height()));
+}
+
+namespace qdesigner_internal {
+
+// ---------- ZoomMenu
+
+ZoomMenu::ZoomMenu(QObject *parent) :
+ QObject(parent),
+ m_menuActions(new QActionGroup(this))
+{
+ connect(m_menuActions, SIGNAL(triggered(QAction*)), this, SLOT(slotZoomMenu(QAction*)));
+ const int nz = sizeof(menuZoomList)/sizeof(int);
+ for (int i = 0; i < nz; i++) {
+ const int zoom = menuZoomList[i];
+ //: Zoom factor
+ QAction *a = m_menuActions->addAction(tr("%1 %").arg(zoom));
+ a->setCheckable(true);
+ a->setData(QVariant(zoom));
+ if (zoom == 100)
+ a->setChecked(true);
+ m_menuActions->addAction(a);
+ }
+}
+
+int ZoomMenu::zoomOf(const QAction *a)
+{
+ return a->data().toInt();
+}
+
+void ZoomMenu::addActions(QMenu *m)
+{
+ const ActionList za = m_menuActions->actions();
+ const ActionList::const_iterator cend = za.constEnd();
+ for (ActionList::const_iterator it = za.constBegin(); it != cend; ++it) {
+ m->addAction(*it);
+ if (zoomOf(*it) == 100)
+ m->addSeparator();
+ }
+}
+
+int ZoomMenu::zoom() const
+{
+ return m_menuActions->checkedAction()->data().toInt();
+}
+
+void ZoomMenu::setZoom(int percent)
+{
+ const ActionList za = m_menuActions->actions();
+ const ActionList::const_iterator cend = za.constEnd();
+ for (ActionList::const_iterator it = za.constBegin(); it != cend; ++it)
+ if (zoomOf(*it) == percent) {
+ (*it)->setChecked(true);
+ return;
+ }
+}
+
+void ZoomMenu::slotZoomMenu(QAction *a)
+{
+ emit zoomChanged(zoomOf(a));
+}
+
+QList<int> ZoomMenu::zoomValues()
+{
+ QList<int> rc;
+ const int nz = sizeof(menuZoomList)/sizeof(int);
+ for (int i = 0; i < nz; i++)
+ rc.push_back(menuZoomList[i]);
+ return rc;
+}
+
+// --------- ZoomView
+ZoomView::ZoomView(QWidget *parent) :
+ QGraphicsView(parent),
+ m_scene(new QGraphicsScene(this)),
+ m_zoom(100),
+ m_zoomFactor(1.0),
+ m_zoomContextMenuEnabled(false),
+ m_autoScrollSuppressed(true),
+ m_zoomMenu(0)
+{
+ setFrameShape(QFrame::NoFrame);
+ setScene(m_scene);
+ if (debugZoomWidget)
+ qDebug() << "scene" << m_scene->sceneRect();
+
+}
+
+int ZoomView::zoom() const
+{
+ return m_zoom;
+}
+
+void ZoomView::scrollToOrigin()
+{
+ const QPoint origin(0 ,0);
+ const QPoint current = scrollPosition();
+ if (current != origin) {
+ if (debugZoomWidget)
+ qDebug() << "ZoomView::scrollToOrigin from " << current;
+ setScrollPosition(origin);
+ }
+}
+
+void ZoomView::setZoom(int percent)
+{
+ if (debugZoomWidget)
+ qDebug() << "ZoomView::setZoom" << percent;
+
+ if (m_zoom == percent)
+ return;
+
+ m_zoom = percent;
+ const qreal hundred = 100.0;
+ m_zoomFactor = static_cast<qreal>(m_zoom) / hundred;
+
+ applyZoom();
+ if (m_zoomMenu) // Do not force them into existence
+ m_zoomMenu->setZoom(m_zoom);
+
+ resetTransform();
+ scale(m_zoomFactor, m_zoomFactor);
+ if (m_autoScrollSuppressed)
+ scrollToOrigin();
+}
+
+void ZoomView::applyZoom()
+{
+}
+
+qreal ZoomView::zoomFactor() const
+{
+ return m_zoomFactor;
+}
+
+bool ZoomView::isZoomContextMenuEnabled() const
+{
+ return m_zoomContextMenuEnabled;
+}
+
+void ZoomView::setZoomContextMenuEnabled(bool e)
+{
+ m_zoomContextMenuEnabled = e;
+}
+
+bool ZoomView::isAutoScrollSuppressed() const
+{
+ return m_autoScrollSuppressed;
+}
+
+void ZoomView::setAutoScrollSuppressed(bool s)
+{
+ m_autoScrollSuppressed = s;
+}
+
+ZoomMenu *ZoomView::zoomMenu()
+{
+ if (!m_zoomMenu) {
+ m_zoomMenu = new ZoomMenu(this);
+ m_zoomMenu->setZoom(m_zoom);
+ connect(m_zoomMenu, SIGNAL(zoomChanged(int)), this, SLOT(setZoom(int)));
+ }
+ return m_zoomMenu;
+}
+
+void ZoomView::contextMenuEvent(QContextMenuEvent *event)
+{
+ if (debugZoomWidget > 1)
+ qDebug() << "ZoomView::contextMenuEvent" << event->pos() << event->globalPos() << zoom() << '%';
+
+ if (m_zoomContextMenuEnabled) {
+ showContextMenu(event->globalPos());
+ } else {
+ QGraphicsView::contextMenuEvent(event);
+ }
+}
+
+void ZoomView::showContextMenu(const QPoint &globalPos)
+{
+ QMenu menu;
+ zoomMenu()->addActions(&menu);
+ if (debugZoomWidget) {
+ menu.addSeparator();
+ QAction *da = menu.addAction(QLatin1String("Dump"));
+ connect(da, SIGNAL(triggered()), this, SLOT(dump()));
+ }
+ menu.exec(globalPos);
+}
+
+QPoint ZoomView::scrollPosition() const
+{
+ return QPoint(horizontalScrollBar()->value(), verticalScrollBar()->value());
+}
+
+void ZoomView::setScrollPosition(const QPoint& pos)
+{
+ horizontalScrollBar()->setValue(pos.x());
+ verticalScrollBar()->setValue(pos.y());
+}
+
+// -------------- ZoomProxyWidget
+ZoomProxyWidget::ZoomProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) :
+ QGraphicsProxyWidget(parent, wFlags)
+{
+}
+
+QVariant ZoomProxyWidget::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ switch (change) {
+ case ItemPositionChange: {
+ const QPointF newPos = value.toPointF();
+ const QPointF desiredPos = QPointF(0, 0);
+ if (newPos != desiredPos && debugZoomWidget)
+ qDebug() << "ZoomProxyWidget::itemChange: refusing " << newPos;
+ return desiredPos;
+ }
+ default:
+ break;
+ }
+ return QGraphicsProxyWidget::itemChange(change, value);
+}
+
+/* ZoomedEventFilterRedirector: Event filter for the zoomed widget.
+ * It redirects the events to another handler of ZoomWidget as its
+ * base class QScrollArea also implements eventFilter() for its viewport. */
+
+static const char *zoomedEventFilterRedirectorNameC = "__qt_ZoomedEventFilterRedirector";
+
+class ZoomedEventFilterRedirector : public QObject {
+ Q_DISABLE_COPY(ZoomedEventFilterRedirector)
+
+public:
+ explicit ZoomedEventFilterRedirector(ZoomWidget *zw, QObject *parent);
+ virtual bool eventFilter(QObject *watched, QEvent *event);
+
+private:
+ ZoomWidget *m_zw;
+};
+
+ZoomedEventFilterRedirector::ZoomedEventFilterRedirector(ZoomWidget *zw, QObject *parent) :
+ QObject(parent),
+ m_zw(zw)
+{
+ setObjectName(QLatin1String(zoomedEventFilterRedirectorNameC));
+}
+
+bool ZoomedEventFilterRedirector::eventFilter(QObject *watched, QEvent *event)
+{
+ return m_zw->zoomedEventFilter(watched, event);
+}
+
+
+// --------- ZoomWidget
+
+ZoomWidget::ZoomWidget(QWidget *parent) :
+ ZoomView(parent),
+ m_proxy(0),
+ m_viewResizeBlocked(false),
+ m_widgetResizeBlocked(false),
+ m_widgetZoomContextMenuEnabled(false)
+{
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+}
+
+void ZoomWidget::setWidget(QWidget *w, Qt::WindowFlags wFlags)
+{
+ if (debugZoomWidget)
+ qDebug() << "ZoomWidget::setWidget" << w << bin << wFlags;
+
+ if (m_proxy) {
+ scene().removeItem(m_proxy);
+ if (QWidget *w = m_proxy->widget()) {
+ // remove the event filter
+ if (QObject *evf = qFindChild<QObject*>(w, QLatin1String(zoomedEventFilterRedirectorNameC)))
+ w->removeEventFilter(evf);
+ }
+ m_proxy->deleteLater();
+ }
+ // Set window flags on the outer proxy for them to take effect
+ m_proxy = createProxyWidget(0, Qt::Window);
+ m_proxy->setWidget(w);
+
+ m_proxy->setWindowFlags(wFlags);
+ scene().addItem(m_proxy);
+ w->installEventFilter(new ZoomedEventFilterRedirector(this, w));
+ resizeToWidgetSize(); // Do manually for new widget
+ m_proxy->show();
+}
+
+bool ZoomWidget::isWidgetZoomContextMenuEnabled() const
+{
+ return m_widgetZoomContextMenuEnabled;
+}
+void ZoomWidget::setWidgetZoomContextMenuEnabled(bool e)
+{
+ m_widgetZoomContextMenuEnabled = e;
+}
+
+QSize ZoomWidget::viewPortMargin() const
+{
+ return QSize(0, 0);
+}
+
+QSizeF ZoomWidget::widgetDecorationSizeF() const
+{
+ qreal left, top, right, bottom;
+ m_proxy->getWindowFrameMargins (&left, &top, &right, &bottom);
+ const QSizeF rc = QSizeF(left + right, top + bottom);
+ return rc;
+}
+
+QSize ZoomWidget::widgetSize() const
+{
+ if (m_proxy)
+ return m_proxy->widget()->size();
+ return QSize(0, 0);
+}
+
+/* Convert widget size to QGraphicsView size.
+ * Watch out for limits (0, QWIDGETSIZE_MAX); just pass them on */
+
+QSize ZoomWidget::widgetSizeToViewSize(const QSize &s, bool *ptrToValid) const
+{
+ const QSize vpMargin = viewPortMargin();
+ const QSizeF deco = widgetDecorationSizeF();
+ const int width = s.width();
+
+ QSize rc = s;
+ bool valid = false;
+ if (width != 0 && width != QWIDGETSIZE_MAX) {
+ valid = true;
+ rc.setWidth(vpMargin.width() + qCeil(deco.width() + zoomFactor() * static_cast<qreal>(width)));
+ }
+
+ const int height = s.height();
+ if (height != 0 && height != QWIDGETSIZE_MAX) {
+ valid = true;
+ rc.setHeight(vpMargin.height() + qCeil(deco.height() + zoomFactor() * static_cast<qreal>(height)));
+ }
+
+ if (ptrToValid)
+ *ptrToValid = valid;
+
+ return rc;
+}
+
+// On changing zoom: Make QGraphicsView big enough to hold the widget
+void ZoomWidget::resizeToWidgetSize()
+{
+ if (!m_proxy)
+ return;
+
+ m_viewResizeBlocked = true;
+ // Convert size, apply transformed min/max size if applicable
+ const QSize wsize = widgetSize();
+ const QSize viewSize = widgetSizeToViewSize(wsize);
+
+ bool hasMinimumSize = false;
+ const QSize minimumSize = m_proxy->widget()->minimumSize();
+ const QSize viewMinimumSize = widgetSizeToViewSize(minimumSize, &hasMinimumSize);
+
+ bool hasMaximumSize = false;
+ const QSize maximumSize = m_proxy->widget()->maximumSize();
+ const QSize viewMaximumSize = widgetSizeToViewSize(maximumSize, &hasMaximumSize);
+
+ if (debugZoomWidget) {
+ qDebug()
+ << "ZoomWidget::resizeToWidgetSize()\n"
+ << "Widget: " << wsize << "(scaled)" << (wsize * zoomFactor()) << " Min/Max" << minimumSize << maximumSize << '\n'
+ << " View: " << viewSize << hasMinimumSize << viewMinimumSize << hasMaximumSize << viewMaximumSize;
+ }
+ // Apply
+ if (hasMinimumSize)
+ setMinimumSize(viewMinimumSize);
+ if (hasMaximumSize)
+ setMaximumSize(viewMaximumSize);
+ // now resize
+ doResize(viewSize);
+ if (debugZoomWidget)
+ qDebug() << "ZoomWidget::resizeToWidgetSize(): resulting view size" << size();
+ m_viewResizeBlocked = false;
+}
+
+void ZoomWidget::applyZoom()
+{
+ resizeToWidgetSize();
+}
+
+/* virtual */ void ZoomWidget::doResize(const QSize &s)
+{
+ if (debugZoomWidget > 1)
+ qDebug() << ">ZoomWidget::doResize() " << s;
+ resize(s);
+}
+
+void ZoomWidget::resizeEvent(QResizeEvent *event)
+{
+ /* QGraphicsView Resized from outside: Adapt widget. For some reason,
+ * the size passed in the event is not to be trusted. This might be due
+ * to some QScrollArea event fiddling. Have QScrollArea resize first
+ * and the use the size ZoomView::resizeEvent(event); */
+ if (m_proxy && !m_viewResizeBlocked) {
+ if (debugZoomWidget > 1)
+ qDebug() << ">ZoomWidget (" << size() << ")::resizeEvent from " << event->oldSize() << " to " << event->size();
+ const QSizeF newViewPortSize = size() - viewPortMargin();
+ const QSizeF widgetSizeF = newViewPortSize / zoomFactor() - widgetDecorationSizeF();
+ m_widgetResizeBlocked = true;
+ m_proxy->widget()->resize(widgetSizeF.toSize());
+ scrollToOrigin();
+ m_widgetResizeBlocked = false;
+ }
+}
+
+QSize ZoomWidget::minimumSizeHint() const
+{
+ if (!m_proxy)
+ return QGraphicsView::minimumSizeHint();
+
+ const QSizeF wmsh = m_proxy->widget()->minimumSizeHint();
+ const QSize rc = viewPortMargin() + (wmsh * zoomFactor()).toSize();
+ if (debugZoomWidget > 1)
+ qDebug() << "minimumSizeHint()" << rc;
+ return rc;
+}
+
+QSize ZoomWidget::sizeHint() const
+{
+ if (!m_proxy)
+ return QGraphicsView::sizeHint();
+
+ const QSizeF wsh = m_proxy->widget()->sizeHint();
+ const QSize rc = viewPortMargin() + (wsh * zoomFactor()).toSize();
+ if (debugZoomWidget > 1)
+ qDebug() << "sizeHint()" << rc;
+ return rc;
+}
+
+bool ZoomWidget::zoomedEventFilter(QObject * /*watched*/, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ if (debugZoomWidget) { // Debug helper: Press 'D' on the zoomed widget
+ const QKeyEvent *kevent = static_cast<QKeyEvent*>(event);
+ if (kevent->key() == Qt::Key_D)
+ dump();
+ }
+ break;
+ case QEvent::Resize:
+ if (debugZoomWidget > 1) {
+ const QResizeEvent *re = static_cast<const QResizeEvent *>(event);
+ qDebug() << "ZoomWidget::zoomedEventFilter" << re->oldSize() << re->size() << " at " << m_proxy->widget()->geometry();
+ }
+ if (!m_widgetResizeBlocked)
+ resizeToWidgetSize();
+
+ break;
+ case QEvent::ContextMenu:
+ if (m_widgetZoomContextMenuEnabled) {
+ // Calculate global position from scaled
+ QContextMenuEvent *ce = static_cast<QContextMenuEvent*>(event);
+ const QPointF origin = mapToGlobal(QPoint(0, 0)) - scrollPosition();
+ const QPointF pos = QPointF(origin + (QPointF(ce->pos()) * zoomFactor()));
+ showContextMenu(pos.toPoint());
+ ce->accept();
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+void ZoomWidget::setItemAcceptDrops(bool)
+{
+ if (m_proxy)
+ m_proxy->setAcceptDrops(true);
+}
+
+bool ZoomWidget::itemAcceptDrops() const
+{
+ return m_proxy ? m_proxy->acceptDrops() : false;
+}
+
+ // Factory function for QGraphicsProxyWidgets which can be overwritten. Default creates a ZoomProxyWidget
+QGraphicsProxyWidget *ZoomWidget::createProxyWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags) const
+{
+ return new ZoomProxyWidget(parent, wFlags);
+}
+
+void ZoomWidget::dump() const
+{
+
+ qDebug() << "ZoomWidget " << geometry() << " Viewport " << viewport()->geometry()
+ << "Scroll: " << scrollPosition() << "Matrix: " << matrix() << " SceneRect: " << sceneRect();
+ if (m_proxy) {
+ qDebug() << "Proxy Pos: " << m_proxy->pos() << "Proxy " << m_proxy->size()
+ << "\nProxy size hint"
+ << m_proxy->effectiveSizeHint(Qt::MinimumSize)
+ << m_proxy->effectiveSizeHint(Qt::PreferredSize)
+ << m_proxy->effectiveSizeHint(Qt::MaximumSize)
+ << "\nMatrix: " << m_proxy->matrix()
+ << "\nWidget: " << m_proxy->widget()->geometry()
+ << "scaled" << (zoomFactor() * m_proxy->widget()->size());
+ }
+}
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/shared/zoomwidget_p.h b/tools/designer/src/lib/shared/zoomwidget_p.h
new file mode 100644
index 0000000000..fe850f725f
--- /dev/null
+++ b/tools/designer/src/lib/shared/zoomwidget_p.h
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef ZOOMWIDGET_H
+#define ZOOMWIDGET_H
+
+#include "shared_global_p.h"
+
+#include <QtGui/QGraphicsView>
+#include <QtGui/QGraphicsProxyWidget>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsScene;
+class QMenu;
+class QAction;
+class QActionGroup;
+
+namespace qdesigner_internal {
+
+// A checkable zoom menu action group. Operates in percent.
+
+class QDESIGNER_SHARED_EXPORT ZoomMenu : public QObject {
+ Q_OBJECT
+ Q_DISABLE_COPY(ZoomMenu)
+
+public:
+ ZoomMenu(QObject *parent = 0);
+ void addActions(QMenu *m);
+
+ int zoom() const;
+
+ // Return a list of available zoom values.
+ static QList<int> zoomValues();
+
+public slots:
+ void setZoom(int percent);
+
+signals:
+ void zoomChanged(int);
+
+private slots:
+ void slotZoomMenu(QAction *);
+
+private:
+ static int zoomOf(const QAction *a);
+
+ QActionGroup *m_menuActions;
+};
+
+/* Zoom view: A QGraphicsView with a zoom menu */
+
+class QDESIGNER_SHARED_EXPORT ZoomView : public QGraphicsView
+{
+ Q_PROPERTY(int zoom READ zoom WRITE setZoom DESIGNABLE true SCRIPTABLE true)
+ Q_PROPERTY(bool zoomContextMenuEnabled READ isZoomContextMenuEnabled WRITE setZoomContextMenuEnabled DESIGNABLE true SCRIPTABLE true)
+ Q_PROPERTY(bool autoScrollSuppressed READ isAutoScrollSuppressed WRITE setAutoScrollSuppressed DESIGNABLE true SCRIPTABLE true)
+
+ Q_OBJECT
+ Q_DISABLE_COPY(ZoomView)
+public:
+ ZoomView(QWidget *parent = 0);
+
+ /* Zoom in percent (for easily implementing menus) and qreal zoomFactor
+ * in sync */
+ int zoom() const; // in percent
+ qreal zoomFactor() const;
+
+ // Zoom Menu on QGraphicsView.
+ bool isZoomContextMenuEnabled() const;
+ void setZoomContextMenuEnabled(bool e);
+
+ // Suppress scrolling when changing zoom. Default: on
+ bool isAutoScrollSuppressed() const;
+ void setAutoScrollSuppressed(bool s);
+
+ QGraphicsScene &scene() { return *m_scene; }
+ const QGraphicsScene &scene() const { return *m_scene; }
+
+ // Helpers for menu
+ ZoomMenu *zoomMenu();
+
+ QPoint scrollPosition() const;
+ void setScrollPosition(const QPoint& pos);
+ void scrollToOrigin();
+
+public slots:
+ void setZoom(int percent);
+ void showContextMenu(const QPoint &globalPos);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event);
+
+ // Overwrite for implementing additional behaviour when doing setZoom();
+ virtual void applyZoom();
+
+private:
+ QGraphicsScene *m_scene;
+ int m_zoom;
+ qreal m_zoomFactor;
+
+ bool m_zoomContextMenuEnabled;
+ bool m_autoScrollSuppressed;
+ bool m_resizeBlocked;
+ ZoomMenu *m_zoomMenu;
+};
+
+/* The proxy widget used in ZoomWidget. It refuses to move away from 0,0,
+ * This behaviour is required for Windows only. */
+
+class QDESIGNER_SHARED_EXPORT ZoomProxyWidget : public QGraphicsProxyWidget {
+ Q_DISABLE_COPY(ZoomProxyWidget)
+public:
+ explicit ZoomProxyWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
+
+protected:
+ virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+};
+
+/* Zoom widget: A QGraphicsView-based container for a widget that allows for
+ * zooming it. Communicates changes in size in the following ways:
+ * 1) Embedded widget wants to resize: Listen for its resize in event filter
+ * and resize
+ * 2) Zoom is changed: resize to fully display the embedded widget
+ * 3) Outer widget changes (by manually resizing the window:
+ * Pass the scaled change on to the embedded widget.
+ * Provides helper functions for a zoom context menu on the widget. */
+
+class QDESIGNER_SHARED_EXPORT ZoomWidget : public ZoomView
+{
+ Q_PROPERTY(bool widgetZoomContextMenuEnabled READ isWidgetZoomContextMenuEnabled WRITE setWidgetZoomContextMenuEnabled DESIGNABLE true SCRIPTABLE true)
+ Q_PROPERTY(bool itemAcceptDrops READ itemAcceptDrops WRITE setItemAcceptDrops DESIGNABLE true SCRIPTABLE true)
+ Q_OBJECT
+ Q_DISABLE_COPY(ZoomWidget)
+
+public:
+ ZoomWidget(QWidget *parent = 0);
+ void setWidget(QWidget *w, Qt::WindowFlags wFlags = 0);
+
+ const QGraphicsProxyWidget *proxy() const { return m_proxy; }
+ QGraphicsProxyWidget *proxy() { return m_proxy; }
+
+ /* Enable the zoom Menu on the Widget (as opposed ZoomView's menu which
+ * is on the canvas). */
+ bool isWidgetZoomContextMenuEnabled() const;
+ void setWidgetZoomContextMenuEnabled(bool e);
+
+ void setItemAcceptDrops(bool);
+ bool itemAcceptDrops() const;
+
+ virtual QSize minimumSizeHint() const;
+ virtual QSize sizeHint() const;
+
+ bool zoomedEventFilter(QObject *watched, QEvent *event);
+
+public slots:
+ // debug state
+ void dump() const;
+
+protected:
+ void resizeEvent(QResizeEvent * event);
+
+ // Overwritten from ZoomView
+ virtual void applyZoom();
+ // Overwrite to actually perform a resize. This is required if we are in a layout. Default does resize().
+ virtual void doResize(const QSize &s);
+
+private:
+ // Factory function for QGraphicsProxyWidgets which can be overwritten. Default creates a ZoomProxyWidget
+ virtual QGraphicsProxyWidget *createProxyWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0) const;
+ QSize widgetSizeToViewSize(const QSize &s, bool *ptrToValid = 0) const;
+
+ void resizeToWidgetSize();
+ QSize viewPortMargin() const;
+ QSize widgetSize() const;
+ QSizeF widgetDecorationSizeF() const;
+
+ QGraphicsProxyWidget *m_proxy;
+ bool m_viewResizeBlocked;
+ bool m_widgetResizeBlocked;
+ bool m_widgetZoomContextMenuEnabled;
+};
+
+} // namespace qdesigner_internal
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/lib/uilib/abstractformbuilder.cpp b/tools/designer/src/lib/uilib/abstractformbuilder.cpp
new file mode 100644
index 0000000000..4dae28e237
--- /dev/null
+++ b/tools/designer/src/lib/uilib/abstractformbuilder.cpp
@@ -0,0 +1,2920 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**sw
+****************************************************************************/
+
+#include "abstractformbuilder.h"
+#include "formbuilderextra_p.h"
+#include "resourcebuilder_p.h"
+#include "textbuilder_p.h"
+#include "ui4_p.h"
+#include "properties_p.h"
+
+#include <QtCore/QVariant>
+#include <QtCore/QMetaProperty>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QQueue>
+#include <QtCore/QHash>
+#include <QtCore/qdebug.h>
+#include <QtCore/QCoreApplication>
+
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QComboBox>
+#include <QtGui/QFontComboBox>
+#include <QtGui/QGridLayout>
+#ifndef QT_NO_FORMLAYOUT
+# include <QtGui/QFormLayout>
+#endif
+#include <QtGui/QIcon>
+#include <QtGui/QListWidget>
+#include <QtGui/QMainWindow>
+#include <QtGui/QPixmap>
+#include <QtGui/QStatusBar>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QTableWidget>
+#include <QtGui/QWidget>
+#include <QtGui/QSplitter>
+#include <QtGui/QScrollArea>
+#include <QtGui/QAbstractButton>
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QHeaderView>
+#ifndef QFORMINTERNAL_NAMESPACE
+# include <private/qlayout_p.h> // Compiling within Designer
+#endif
+
+#include <QtXml/QXmlStreamReader>
+
+#include <QtGui/QDialog>
+
+// containers
+#include <QtGui/QToolBox>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolBar>
+#include <QtGui/QMenuBar>
+#include <QtGui/QDockWidget>
+#include <QtGui/QMdiArea>
+#include <QtGui/QWorkspace>
+#include <QtGui/QWizard>
+#include <QtGui/QWizardPage>
+
+#include <QtCore/qdebug.h>
+
+#include <limits.h>
+
+Q_DECLARE_METATYPE(QWidgetList)
+
+static const char *buttonGroupPropertyC = "buttonGroup";
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QFORMINTERNAL_NAMESPACE
+using namespace QFormInternal;
+#endif
+
+class QFriendlyLayout: public QLayout
+{
+public:
+ inline QFriendlyLayout() { Q_ASSERT(0); }
+
+#ifdef QFORMINTERNAL_NAMESPACE
+ friend class QFormInternal::QAbstractFormBuilder;
+#else
+ friend class QAbstractFormBuilder;
+#endif
+};
+
+/*!
+ \class QAbstractFormBuilder
+
+ \brief The QAbstractFormBuilder class provides a default
+ implementation for classes that create user interfaces at
+ run-time.
+
+ \inmodule QtDesigner
+
+ QAbstractFormBuilder provides a standard interface and a default
+ implementation for constructing forms from user interface
+ files. It is not intended to be instantiated directly. Use the
+ QFormBuilder class to create user interfaces from \c{.ui} files at
+ run-time. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_uilib_abstractformbuilder.cpp 0
+
+ To override certain aspects of the form builder's behavior,
+ subclass QAbstractFormBuilder and reimplement the relevant virtual
+ functions:
+
+ \list
+ \o load() handles reading of \c{.ui} format files from arbitrary
+ QIODevices, and construction of widgets from the XML data
+ that they contain.
+ \o save() handles saving of widget details in \c{.ui} format to
+ arbitrary QIODevices.
+ \o workingDirectory() and setWorkingDirectory() control the
+ directory in which forms are held. The form builder looks for
+ other resources on paths relative to this directory.
+ \endlist
+
+ The QFormBuilder class is typically used by custom components and
+ applications that embed \QD. Standalone applications that need to
+ dynamically generate user interfaces at run-time use the
+ QUiLoader, found in the QtUiTools module.
+
+ \sa {QtUiTools Module}
+*/
+
+/*!
+ Constructs a new form builder.*/
+QAbstractFormBuilder::QAbstractFormBuilder() :
+ m_defaultMargin(INT_MIN),
+ m_defaultSpacing(INT_MIN)
+{
+ setResourceBuilder(new QResourceBuilder());
+ setTextBuilder(new QTextBuilder());
+}
+
+/*!
+ Destroys the form builder.*/
+QAbstractFormBuilder::~QAbstractFormBuilder()
+{
+ QFormBuilderExtra::removeInstance(this);
+}
+
+
+/*!
+ \fn QWidget *QAbstractFormBuilder::load(QIODevice *device, QWidget *parent)
+
+ Loads an XML representation of a widget from the given \a device,
+ and constructs a new widget with the specified \a parent.
+
+ \sa save()
+*/
+QWidget *QAbstractFormBuilder::load(QIODevice *dev, QWidget *parentWidget)
+{
+ QXmlStreamReader reader;
+ reader.setDevice(dev);
+ DomUI ui;
+ bool initialized = false;
+
+ const QString uiElement = QLatin1String("ui");
+ while (!reader.atEnd()) {
+ if (reader.readNext() == QXmlStreamReader::StartElement) {
+ if (reader.name().compare(uiElement, Qt::CaseInsensitive) == 0) {
+ ui.read(reader);
+ initialized = true;
+ } else {
+ reader.raiseError(QCoreApplication::translate("QAbstractFormBuilder", "Unexpected element <%1>").arg(reader.name().toString()));
+ }
+ }
+ }
+ if (reader.hasError()) {
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "An error has occurred while reading the ui file at line %1, column %2: %3")
+ .arg(reader.lineNumber()).arg(reader.columnNumber())
+ .arg(reader.errorString()));
+ return 0;
+ }
+ if (!initialized) {
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Invalid ui file: The root element <ui> is missing."));
+ return 0;
+ }
+
+ QWidget *widget = create(&ui, parentWidget);
+ return widget;
+}
+
+/*!
+ \internal
+*/
+QWidget *QAbstractFormBuilder::create(DomUI *ui, QWidget *parentWidget)
+{
+ typedef QFormBuilderExtra::ButtonGroupHash ButtonGroupHash;
+
+ QFormBuilderExtra *formBuilderPrivate = QFormBuilderExtra::instance(this);
+ formBuilderPrivate->clear();
+ if (const DomLayoutDefault *def = ui->elementLayoutDefault()) {
+ m_defaultMargin = def->hasAttributeMargin() ? def->attributeMargin() : INT_MIN;
+ m_defaultSpacing = def->hasAttributeSpacing() ? def->attributeSpacing() : INT_MIN;
+ }
+
+ DomWidget *ui_widget = ui->elementWidget();
+ if (!ui_widget)
+ return 0;
+
+ initialize(ui);
+
+ if (const DomButtonGroups *domButtonGroups = ui->elementButtonGroups())
+ formBuilderPrivate->registerButtonGroups(domButtonGroups);
+
+ if (QWidget *widget = create(ui_widget, parentWidget)) {
+ // Reparent button groups that were actually created to main container for them to be found in the signal/slot part
+ const ButtonGroupHash &buttonGroups = formBuilderPrivate->buttonGroups();
+ if (!buttonGroups.empty()) {
+ const ButtonGroupHash::const_iterator cend = buttonGroups.constEnd();
+ for (ButtonGroupHash::const_iterator it = buttonGroups.constBegin(); it != cend; ++it)
+ if (it.value().second)
+ it.value().second->setParent(widget);
+ }
+ createConnections(ui->elementConnections(), widget);
+ createResources(ui->elementResources()); // maybe this should go first, before create()...
+ applyTabStops(widget, ui->elementTabStops());
+ formBuilderPrivate->applyInternalProperties();
+ reset();
+ formBuilderPrivate->clear();
+ return widget;
+ }
+ formBuilderPrivate->clear();
+ return 0;
+}
+
+/*!
+ \internal
+ Retrieve relevant information from the custom widgets section.
+ Called by create(DomUI *, QWidget *); call manually if you
+ just use create(DomWidget *, QWidget *) on some child widget of DomUI.
+ */
+
+void QAbstractFormBuilder::initialize(const DomUI *ui)
+{
+ typedef QList<DomCustomWidget*> DomCustomWidgetList;
+
+ DomCustomWidgets *domCustomWidgets = ui->elementCustomWidgets();
+ createCustomWidgets(domCustomWidgets);
+
+ if (domCustomWidgets) {
+ const DomCustomWidgetList customWidgets = domCustomWidgets->elementCustomWidget();
+ if (!customWidgets.empty()) {
+ QFormBuilderExtra *formBuilderPrivate = QFormBuilderExtra::instance(this);
+ const DomCustomWidgetList::const_iterator cend = customWidgets.constEnd();
+ for (DomCustomWidgetList::const_iterator it = customWidgets.constBegin(); it != cend; ++it) {
+ const DomCustomWidget *cw = *it;
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ if (const DomScript *domScript = cw->elementScript()) {
+ const QString script = domScript->text();
+ if (!script.isEmpty())
+ formBuilderPrivate->storeCustomWidgetScript(cw->elementClass(), script);
+ }
+#endif
+ const QString addPageMethod = cw->elementAddPageMethod();
+ if (!addPageMethod.isEmpty())
+ formBuilderPrivate->storeCustomWidgetAddPageMethod(cw->elementClass(), addPageMethod);
+
+ const QString extends = cw->elementExtends();
+ if (!extends.isEmpty())
+ formBuilderPrivate->storeCustomWidgetBaseClass(cw->elementClass(), extends);
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+QWidget *QAbstractFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidget)
+{
+ QWidget *w = createWidget(ui_widget->attributeClass(), parentWidget, ui_widget->attributeName());
+ if (!w)
+ return 0;
+
+ applyProperties(w, ui_widget->elementProperty());
+
+ foreach (DomAction *ui_action, ui_widget->elementAction()) {
+ QAction *child_action = create(ui_action, w);
+ Q_UNUSED( child_action );
+ }
+
+ foreach (DomActionGroup *ui_action_group, ui_widget->elementActionGroup()) {
+ QActionGroup *child_action_group = create(ui_action_group, w);
+ Q_UNUSED( child_action_group );
+ }
+
+ QWidgetList children;
+ foreach (DomWidget *ui_child, ui_widget->elementWidget()) {
+ if (QWidget *child = create(ui_child, w)) {
+ children += child;
+ } else {
+ const QString className = ui_child->elementClass().empty() ? QString() : ui_child->elementClass().front();
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "The creation of a widget of the class '%1' failed.").arg(className));
+ }
+ }
+
+ foreach (DomLayout *ui_lay, ui_widget->elementLayout()) {
+ QLayout *child_lay = create(ui_lay, 0, w);
+ Q_UNUSED( child_lay );
+ }
+
+ const QList<DomActionRef *> addActions = ui_widget->elementAddAction();
+ if (!addActions.empty()) {
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ foreach (DomActionRef *ui_action_ref, addActions) {
+ const QString name = ui_action_ref->attributeName();
+ if (name == strings.separator) {
+ QAction *sep = new QAction(w);
+ sep->setSeparator(true);
+ w->addAction(sep);
+ addMenuAction(sep);
+ } else if (QAction *a = m_actions.value(name)) {
+ w->addAction(a);
+ } else if (QActionGroup *g = m_actionGroups.value(name)) {
+ w->addActions(g->actions());
+ } else if (QMenu *menu = qFindChild<QMenu*>(w, name)) {
+ w->addAction(menu->menuAction());
+ addMenuAction(menu->menuAction());
+ }
+ }
+ }
+
+ loadExtraInfo(ui_widget, w, parentWidget);
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ QString scriptErrorMessage;
+ QFormBuilderExtra *extra = QFormBuilderExtra::instance(this);
+ extra->formScriptRunner().run(ui_widget,
+ extra->customWidgetScript(ui_widget->attributeClass()),
+ w, children, &scriptErrorMessage);
+#endif
+ addItem(ui_widget, w, parentWidget);
+
+ if (qobject_cast<QDialog *>(w) && parentWidget)
+ w->setAttribute(Qt::WA_Moved, false); // So that QDialog::setVisible(true) will center it
+
+ const QStringList zOrderNames = ui_widget->elementZOrder();
+ if (!zOrderNames.isEmpty()) {
+ QList<QWidget *> zOrder = qVariantValue<QWidgetList>(w->property("_q_zOrder"));
+ foreach (QString widgetName, zOrderNames) {
+ if (QWidget *child = qFindChild<QWidget*>(w, widgetName)) {
+ if (child->parentWidget() == w) {
+ zOrder.removeAll(child);
+ zOrder.append(child);
+ child->raise();
+ }
+ }
+ }
+ w->setProperty("_q_zOrder", qVariantFromValue(zOrder));
+ }
+
+ return w;
+}
+
+/*!
+ \internal
+*/
+QAction *QAbstractFormBuilder::create(DomAction *ui_action, QObject *parent)
+{
+ QAction *a = createAction(parent, ui_action->attributeName());
+ if (!a)
+ return 0;
+
+ applyProperties(a, ui_action->elementProperty());
+ return a;
+}
+
+/*!
+ \internal
+*/
+QActionGroup *QAbstractFormBuilder::create(DomActionGroup *ui_action_group, QObject *parent)
+{
+ QActionGroup *a = createActionGroup(parent, ui_action_group->attributeName());
+ if (!a)
+ return 0;
+
+ applyProperties(a, ui_action_group->elementProperty());
+
+ foreach (DomAction *ui_action, ui_action_group->elementAction()) {
+ QAction *child_action = create(ui_action, a);
+ Q_UNUSED( child_action );
+ }
+
+ foreach (DomActionGroup *g, ui_action_group->elementActionGroup()) {
+ QActionGroup *child_action_group = create(g, parent);
+ Q_UNUSED( child_action_group );
+ }
+
+ return a;
+}
+
+// figure out the toolbar area of a DOM attrib list.
+// By legacy, it is stored as an integer. As of 4.3.0, it is the enumeration value.
+Qt::ToolBarArea QAbstractFormBuilder::toolbarAreaFromDOMAttributes(const DomPropertyHash &attributes) {
+ const DomProperty *attr = attributes.value(QFormBuilderStrings::instance().toolBarAreaAttribute);
+ if (!attr)
+ return Qt::TopToolBarArea;
+ switch(attr->kind()) {
+ case DomProperty::Number:
+ return static_cast<Qt::ToolBarArea>(attr->elementNumber());
+ case DomProperty::Enum:
+ return enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::ToolBarArea>("toolBarArea", attr->elementEnum().toLatin1());
+ default:
+ break;
+ }
+ return Qt::TopToolBarArea;
+}
+
+/*!
+ \internal
+*/
+bool QAbstractFormBuilder::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
+
+ if (parentWidget == 0)
+ return true;
+ // Check special cases. First: Custom container
+ const QString className = QLatin1String(parentWidget->metaObject()->className());
+ const QString addPageMethod = QFormBuilderExtra::instance(this)->customWidgetAddPageMethod(className);
+ if (!addPageMethod.isEmpty()) {
+ // If this fails ( non-existent or non-slot), use ContainerExtension in Designer, else it can't be helped
+ return QMetaObject::invokeMethod(parentWidget, addPageMethod.toUtf8().constData(), Qt::DirectConnection, Q_ARG(QWidget*, widget));
+ }
+
+ if (QMainWindow *mw = qobject_cast<QMainWindow*>(parentWidget)) {
+
+#ifndef QT_NO_MENUBAR
+ // the menubar
+ if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(widget)) {
+ mw->setMenuBar(menuBar);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_TOOLBAR
+ // apply the toolbar's attributes
+ else if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
+ mw->addToolBar(toolbarAreaFromDOMAttributes(attributes), toolBar);
+ // check break
+ if (const DomProperty *attr = attributes.value(strings.toolBarBreakAttribute))
+ if (attr->elementBool() == strings.trueValue)
+ mw->insertToolBarBreak (toolBar);
+
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_STATUSBAR
+ // statusBar
+ else if (QStatusBar *statusBar = qobject_cast<QStatusBar*>(widget)) {
+ mw->setStatusBar(statusBar);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+ // apply the dockwidget's attributes
+ else if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(widget)) {
+ if (const DomProperty *attr = attributes.value(strings.dockWidgetAreaAttribute)) {
+ Qt::DockWidgetArea area = static_cast<Qt::DockWidgetArea>(attr->elementNumber());
+ if (!dockWidget->isAreaAllowed(area)) {
+ if (dockWidget->isAreaAllowed(Qt::LeftDockWidgetArea))
+ area = Qt::LeftDockWidgetArea;
+ else if (dockWidget->isAreaAllowed(Qt::RightDockWidgetArea))
+ area = Qt::RightDockWidgetArea;
+ else if (dockWidget->isAreaAllowed(Qt::TopDockWidgetArea))
+ area = Qt::TopDockWidgetArea;
+ else if (dockWidget->isAreaAllowed(Qt::BottomDockWidgetArea))
+ area = Qt::BottomDockWidgetArea;
+ }
+ mw->addDockWidget(area, dockWidget);
+ } else {
+ mw->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
+ }
+ return true;
+ }
+#endif
+
+ else if (! mw->centralWidget()) {
+ mw->setCentralWidget(widget);
+ return true;
+ }
+ }
+
+#ifndef QT_NO_TABWIDGET
+ else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(parentWidget)) {
+ widget->setParent(0);
+
+ const int tabIndex = tabWidget->count();
+ if (const DomProperty *titleP = attributes.value(strings.titleAttribute, 0))
+ tabWidget->addTab(widget, toString(titleP->elementString()));
+ else
+ tabWidget->addTab(widget, strings.defaultTitle);
+
+ if (DomProperty *picon = attributes.value(strings.iconAttribute)) {
+ QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon);
+ QVariant nativeValue = resourceBuilder()->toNativeValue(v);
+ tabWidget->setTabIcon(tabIndex, qvariant_cast<QIcon>(nativeValue));
+ }
+
+#ifndef QT_NO_TOOLTIP
+ if (const DomProperty *ptoolTip = attributes.value(strings.toolTipAttribute)) {
+ tabWidget->setTabToolTip(tabIndex, toString(ptoolTip->elementString()));
+ }
+#endif
+
+#ifndef QT_NO_WHATSTHIS
+ if (const DomProperty *pwhatsThis = attributes.value(strings.whatsThisAttribute)) {
+ tabWidget->setTabWhatsThis(tabIndex, toString(pwhatsThis->elementString()));
+ }
+#endif
+
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_TOOLBOX
+ else if (QToolBox *toolBox = qobject_cast<QToolBox*>(parentWidget)) {
+ const int tabIndex = toolBox->count();
+ if (const DomProperty *labelP = attributes.value(strings.labelAttribute, 0))
+ toolBox->addItem(widget, toString(labelP->elementString()));
+ else
+ toolBox->addItem(widget, strings.defaultTitle);
+
+ if (DomProperty *picon = attributes.value(strings.iconAttribute)) {
+ QVariant v = resourceBuilder()->loadResource(workingDirectory(), picon);
+ QVariant nativeValue = resourceBuilder()->toNativeValue(v);
+ toolBox->setItemIcon(tabIndex, qvariant_cast<QIcon>(nativeValue));
+ }
+
+#ifndef QT_NO_TOOLTIP
+ if (const DomProperty *ptoolTip = attributes.value(strings.toolTipAttribute)) {
+ toolBox->setItemToolTip(tabIndex, toString(ptoolTip->elementString()));
+ }
+#endif
+
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_STACKEDWIDGET
+ else if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(parentWidget)) {
+ stackedWidget->addWidget(widget);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_SPLITTER
+ else if (QSplitter *splitter = qobject_cast<QSplitter*>(parentWidget)) {
+ splitter->addWidget(widget);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_MDIAREA
+ else if (QMdiArea *mdiArea = qobject_cast<QMdiArea*>(parentWidget)) {
+ mdiArea->addSubWindow(widget);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_WORKSPACE
+ else if (QWorkspace *ws = qobject_cast<QWorkspace*>(parentWidget)) {
+ ws->addWindow(widget);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+ else if (QDockWidget *dockWidget = qobject_cast<QDockWidget*>(parentWidget)) {
+ dockWidget->setWidget(widget);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_SCROLLAREA
+ else if (QScrollArea *scrollArea = qobject_cast<QScrollArea*>(parentWidget)) {
+ scrollArea->setWidget(widget);
+ return true;
+ }
+#endif
+
+#ifndef QT_NO_WIZARD
+ else if (QWizard *wizard = qobject_cast<QWizard *>(parentWidget)) {
+ QWizardPage *page = qobject_cast<QWizardPage*>(widget);
+ if (!page) {
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Attempt to add child that is not of class QWizardPage to QWizard."));
+ return false;
+ }
+ wizard->addPage(page);
+ return true;
+ }
+#endif
+ return false;
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::layoutInfo(DomLayout *ui_layout, QObject *parent, int *margin, int *spacing)
+{
+ Q_UNUSED(parent)
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ const DomPropertyHash properties = propertyMap(ui_layout->elementProperty());
+
+ int mar = INT_MIN;
+ int spac = INT_MIN;
+ if (const DomProperty *p = properties.value(strings.marginProperty, 0))
+ mar = p->elementNumber();
+
+ if (const DomProperty *p = properties.value(strings.spacingProperty, 0))
+ spac = p->elementNumber();
+
+#ifdef Q_OS_MAC
+ // here we recognize ui file < 4.3 (no we don't store margin property)
+ if (mar != INT_MIN) {
+ const int defaultMargin = parent->inherits("QLayoutWidget") ? 0 : 9;
+ if (mar == defaultMargin)
+ mar = INT_MIN;
+ if (spac == 6)
+ spac = INT_MIN;
+
+ if (mar == INT_MIN || spac == INT_MIN) {
+ QList<DomProperty *> properties = ui_layout->elementProperty();
+ QMutableListIterator<DomProperty *> it(properties);
+ while (it.hasNext()) {
+ DomProperty *prop = it.next();
+ if ((mar == INT_MIN && prop->attributeName() == strings.marginProperty) ||
+ (spac == INT_MIN && prop->attributeName() == strings.spacingProperty)) {
+ it.remove();
+ delete prop;
+ }
+ }
+ ui_layout->setElementProperty(properties);
+ }
+ }
+#endif
+ if (margin)
+ *margin = mar;
+ if (spacing)
+ *spacing = spac;
+}
+
+/*!
+ \internal
+*/
+QLayout *QAbstractFormBuilder::create(DomLayout *ui_layout, QLayout *parentLayout, QWidget *parentWidget)
+{
+ QObject *p = parentLayout;
+
+ if (p == 0)
+ p = parentWidget;
+
+ Q_ASSERT(p != 0);
+
+ bool tracking = false;
+
+ if (p == parentWidget && parentWidget->layout()) {
+ tracking = true;
+ p = parentWidget->layout();
+ }
+
+ QLayout *layout = createLayout(ui_layout->attributeClass(), p, ui_layout->hasAttributeName() ? ui_layout->attributeName() : QString());
+
+ if (layout == 0)
+ return 0;
+
+ if (tracking && layout->parent() == 0) {
+ QBoxLayout *box = qobject_cast<QBoxLayout*>(parentWidget->layout());
+ if (!box) { // only QBoxLayout is supported
+ const QString widgetClass = QString::fromUtf8(parentWidget->metaObject()->className());
+ const QString layoutClass = QString::fromUtf8(parentWidget->layout()->metaObject()->className());
+ const QString msg = QCoreApplication::translate("QAbstractFormBuilder", "Attempt to add a layout to a widget '%1' (%2) which already has a layout of non-box type %3.\n"
+ "This indicates an inconsistency in the ui-file.").
+ arg(parentWidget->objectName(), widgetClass, layoutClass);
+ uiLibWarning(msg);
+ return 0;
+ }
+ box->addLayout(layout);
+ }
+
+ int margin = INT_MIN, spacing = INT_MIN;
+ layoutInfo(ui_layout, p, &margin, &spacing);
+
+ if (margin != INT_MIN) {
+ layout->setMargin(margin);
+ } else {
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ int left, top, right, bottom;
+ left = top = right = bottom = -1;
+ layout->getContentsMargins(&left, &top, &right, &bottom);
+
+ const DomPropertyHash properties = propertyMap(ui_layout->elementProperty());
+
+ if (const DomProperty *p = properties.value(strings.leftMarginProperty, 0))
+ left = p->elementNumber();
+
+ if (const DomProperty *p = properties.value(strings.topMarginProperty, 0))
+ top = p->elementNumber();
+
+ if (const DomProperty *p = properties.value(strings.rightMarginProperty, 0))
+ right = p->elementNumber();
+
+ if (const DomProperty *p = properties.value(strings.bottomMarginProperty, 0))
+ bottom = p->elementNumber();
+
+ layout->setContentsMargins(left, top, right, bottom);
+ }
+
+ if (spacing != INT_MIN) {
+ layout->setSpacing(spacing);
+ } else {
+ QGridLayout *grid = qobject_cast<QGridLayout *>(layout);
+ if (grid) {
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ const DomPropertyHash properties = propertyMap(ui_layout->elementProperty());
+
+ if (const DomProperty *p = properties.value(strings.horizontalSpacingProperty, 0))
+ grid->setHorizontalSpacing(p->elementNumber());
+ if (const DomProperty *p = properties.value(strings.verticalSpacingProperty, 0))
+ grid->setVerticalSpacing(p->elementNumber());
+ }
+ }
+
+ applyProperties(layout, ui_layout->elementProperty());
+
+ foreach (DomLayoutItem *ui_item, ui_layout->elementItem()) {
+ if (QLayoutItem *item = create(ui_item, layout, parentWidget)) {
+ addItem(ui_item, item, layout);
+ }
+ }
+ // Check the box stretch attributes
+ if (QBoxLayout *box = qobject_cast<QBoxLayout*>(layout)) {
+ const QString boxStretch = ui_layout->attributeStretch();
+ if (!boxStretch.isEmpty())
+ QFormBuilderExtra::setBoxLayoutStretch(boxStretch, box);
+ }
+ // Check the grid stretch/minimum size attributes
+ if (QGridLayout *grid = qobject_cast<QGridLayout*>(layout)) {
+ // Stretch
+ const QString gridRowStretch = ui_layout->attributeRowStretch();
+ if (!gridRowStretch.isEmpty())
+ QFormBuilderExtra::setGridLayoutRowStretch(gridRowStretch, grid);
+ const QString gridColumnStretch = ui_layout->attributeColumnStretch();
+ if (!gridColumnStretch.isEmpty())
+ QFormBuilderExtra::setGridLayoutColumnStretch(gridColumnStretch, grid);
+ // Minimum size
+ const QString gridColumnMinimumWidth = ui_layout->attributeColumnMinimumWidth();
+ if (!gridColumnMinimumWidth.isEmpty())
+ QFormBuilderExtra::setGridLayoutColumnMinimumWidth(gridColumnMinimumWidth, grid);
+ const QString gridRowMinimumHeight = ui_layout->attributeRowMinimumHeight();
+ if (!gridRowMinimumHeight.isEmpty())
+ QFormBuilderExtra::setGridLayoutRowMinimumHeight(gridRowMinimumHeight, grid);
+ }
+ return layout;
+}
+
+#ifndef QT_NO_FORMLAYOUT
+static inline QFormLayout::ItemRole formLayoutRole(int column, int colspan)
+{
+ if (colspan > 1)
+ return QFormLayout::SpanningRole;
+ return column == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole;
+}
+#endif
+
+/*!
+ \internal
+*/
+bool QAbstractFormBuilder::addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout)
+{
+ // Calling addChildWidget(), etc. is required to maintain consistency of the layouts,
+ // see documentation of addItem(), which should ideally not be used.
+ if (item->widget()) {
+ static_cast<QFriendlyLayout*>(layout)->addChildWidget(item->widget());
+ } else if (item->layout()) {
+ static_cast<QFriendlyLayout*>(layout)->addChildLayout(item->layout());
+ } else if (item->spacerItem()) {
+ // nothing to do
+ } else {
+ return false;
+ }
+
+ if (QGridLayout *grid = qobject_cast<QGridLayout*>(layout)) {
+ const int rowSpan = ui_item->hasAttributeRowSpan() ? ui_item->attributeRowSpan() : 1;
+ const int colSpan = ui_item->hasAttributeColSpan() ? ui_item->attributeColSpan() : 1;
+ grid->addItem(item, ui_item->attributeRow(), ui_item->attributeColumn(),
+ rowSpan, colSpan, item->alignment());
+ return true;
+ }
+#ifndef QT_NO_FORMLAYOUT
+ if (QFormLayout *form = qobject_cast<QFormLayout *>(layout)) {
+ const int row = ui_item->attributeRow();
+ const int colSpan = ui_item->hasAttributeColSpan() ? ui_item->attributeColSpan() : 1;
+ form->setItem(row, formLayoutRole(ui_item->attributeColumn(), colSpan), item);
+ return true;
+ }
+
+#endif
+ layout->addItem(item);
+ return true;
+}
+
+/*!
+ \internal
+*/
+QLayoutItem *QAbstractFormBuilder::create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget)
+{
+ switch (ui_layoutItem->kind()) {
+ case DomLayoutItem::Widget: {
+ if (QWidget *w = create(ui_layoutItem->elementWidget(), parentWidget))
+#ifdef QFORMINTERNAL_NAMESPACE // uilib
+ return new QWidgetItemV2(w);
+#else // Within Designer: Use factory method that returns special items that refuse to shrink to 0,0
+ return QLayoutPrivate::createWidgetItem(layout, w);
+#endif
+ qWarning() << QCoreApplication::translate("QAbstractFormBuilder", "Empty widget item in %1 '%2'.").arg(QString::fromUtf8(layout->metaObject()->className()), layout->objectName());
+ return 0;
+ }
+ case DomLayoutItem::Spacer: {
+ QSize size(0, 0);
+ QSizePolicy::Policy sizeType = QSizePolicy::Expanding;
+ bool isVspacer = false;
+
+ const DomSpacer *ui_spacer = ui_layoutItem->elementSpacer();
+
+ const QMetaEnum sizePolicy_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");
+ const QMetaEnum orientation_enum = metaEnum<QAbstractFormBuilderGadget>("orientation");
+
+ const QList<DomProperty *> spacerProperties = ui_spacer->elementProperty();
+ if (!spacerProperties.empty()) {
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ foreach (DomProperty *p, spacerProperties) {
+ const QVariant v = toVariant(&QAbstractFormBuilderGadget::staticMetaObject, p); // ### remove me
+ if (v.isNull())
+ continue;
+ if (p->attributeName() == strings.sizeHintProperty && p->kind() == DomProperty::Size) {
+ size = v.toSize(); // ### remove me
+ } else if (p->attributeName() == strings.sizeTypeProperty && p->kind() == DomProperty::Enum) {
+ sizeType = static_cast<QSizePolicy::Policy>(v.toInt());
+ } else if (p->attributeName() == strings.orientationProperty && p->kind() == DomProperty::Enum) {
+ const Qt::Orientation o = static_cast<Qt::Orientation>(v.toInt());
+ isVspacer = (o == Qt::Vertical);
+ }
+ }
+ }
+
+ QSpacerItem *spacer = 0;
+ if (isVspacer)
+ spacer = new QSpacerItem(size.width(), size.height(), QSizePolicy::Minimum, sizeType);
+ else
+ spacer = new QSpacerItem(size.width(), size.height(), sizeType, QSizePolicy::Minimum);
+ return spacer; }
+
+ case DomLayoutItem::Layout:
+ return create(ui_layoutItem->elementLayout(), layout, parentWidget);
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::applyProperties(QObject *o, const QList<DomProperty*> &properties)
+{
+ typedef QList<DomProperty*> DomPropertyList;
+
+ if (properties.empty())
+ return;
+
+ QFormBuilderExtra *fb = QFormBuilderExtra::instance(this);
+
+ const DomPropertyList::const_iterator cend = properties.constEnd();
+ for (DomPropertyList::const_iterator it = properties.constBegin(); it != cend; ++it) {
+ const QVariant v = toVariant(o->metaObject(), *it);
+ if (!v.isNull()) {
+ const QString attributeName = (*it)->attributeName();
+ if (!fb->applyPropertyInternally(o, attributeName, v))
+ o->setProperty(attributeName.toUtf8(), v);
+ }
+ }
+}
+
+
+/*!
+ \internal
+ Check whether a property is applied internally by QAbstractFormBuilder. Call this
+ from overwritten applyProperties().
+*/
+
+bool QAbstractFormBuilder::applyPropertyInternally(QObject *o, const QString &propertyName, const QVariant &value)
+{
+ return QFormBuilderExtra::instance(this)->applyPropertyInternally(o,propertyName, value);
+}
+
+/*!
+ \internal
+*/
+
+QVariant QAbstractFormBuilder::toVariant(const QMetaObject *meta, DomProperty *p)
+{
+ return domPropertyToVariant(this, meta, p);
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::setupColorGroup(QPalette &palette, QPalette::ColorGroup colorGroup,
+ DomColorGroup *group)
+{
+ // old format
+ const QList<DomColor*> colors = group->elementColor();
+ for (int role = 0; role < colors.size(); ++role) {
+ const DomColor *color = colors.at(role);
+ const QColor c(color->elementRed(), color->elementGreen(), color->elementBlue());
+ palette.setColor(colorGroup, QPalette::ColorRole(role), c);
+ }
+
+ // new format
+ const QMetaEnum colorRole_enum = metaEnum<QAbstractFormBuilderGadget>("colorRole");
+
+ const QList<DomColorRole*> colorRoles = group->elementColorRole();
+ for (int role = 0; role < colorRoles.size(); ++role) {
+ const DomColorRole *colorRole = colorRoles.at(role);
+
+ if (colorRole->hasAttributeRole()) {
+ const int r = colorRole_enum.keyToValue(colorRole->attributeRole().toLatin1());
+ if (r != -1) {
+ const QBrush br = setupBrush(colorRole->elementBrush());
+ palette.setBrush(colorGroup, static_cast<QPalette::ColorRole>(r), br);
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+DomColorGroup *QAbstractFormBuilder::saveColorGroup(const QPalette &palette)
+{
+
+ const QMetaEnum colorRole_enum = metaEnum<QAbstractFormBuilderGadget>("colorRole");
+
+ DomColorGroup *group = new DomColorGroup();
+ QList<DomColorRole*> colorRoles;
+
+ const uint mask = palette.resolve();
+ for (int role = QPalette::WindowText; role < QPalette::NColorRoles; ++role) {
+ if (mask & (1 << role)) {
+ QBrush br = palette.brush(QPalette::ColorRole(role));
+
+ DomColorRole *colorRole = new DomColorRole();
+ colorRole->setElementBrush(saveBrush(br));
+ colorRole->setAttributeRole(QLatin1String(colorRole_enum.valueToKey(role)));
+ colorRoles.append(colorRole);
+ }
+ }
+
+ group->setElementColorRole(colorRoles);
+ return group;
+}
+
+/*!
+ \internal
+*/
+QBrush QAbstractFormBuilder::setupBrush(DomBrush *brush)
+{
+ QBrush br;
+ if (!brush->hasAttributeBrushStyle())
+ return br;
+
+ const Qt::BrushStyle style = enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::BrushStyle>("brushStyle", brush->attributeBrushStyle().toLatin1());
+
+ if (style == Qt::LinearGradientPattern ||
+ style == Qt::RadialGradientPattern ||
+ style == Qt::ConicalGradientPattern) {
+ const QMetaEnum gradientType_enum = metaEnum<QAbstractFormBuilderGadget>("gradientType");
+ const QMetaEnum gradientSpread_enum = metaEnum<QAbstractFormBuilderGadget>("gradientSpread");
+ const QMetaEnum gradientCoordinate_enum = metaEnum<QAbstractFormBuilderGadget>("gradientCoordinate");
+
+ const DomGradient *gradient = brush->elementGradient();
+ const QGradient::Type type = enumKeyToValue<QGradient::Type>(gradientType_enum, gradient->attributeType().toLatin1());
+
+
+ QGradient *gr = 0;
+
+ if (type == QGradient::LinearGradient) {
+ gr = new QLinearGradient(QPointF(gradient->attributeStartX(), gradient->attributeStartY()),
+ QPointF(gradient->attributeEndX(), gradient->attributeEndY()));
+ } else if (type == QGradient::RadialGradient) {
+ gr = new QRadialGradient(QPointF(gradient->attributeCentralX(), gradient->attributeCentralY()),
+ gradient->attributeRadius(),
+ QPointF(gradient->attributeFocalX(), gradient->attributeFocalY()));
+ } else if (type == QGradient::ConicalGradient) {
+ gr = new QConicalGradient(QPointF(gradient->attributeCentralX(), gradient->attributeCentralY()),
+ gradient->attributeAngle());
+ }
+ if (!gr)
+ return br;
+
+ const QGradient::Spread spread = enumKeyToValue<QGradient::Spread>(gradientSpread_enum, gradient->attributeSpread().toLatin1());
+ gr->setSpread(spread);
+
+ const QGradient::CoordinateMode coord = enumKeyToValue<QGradient::CoordinateMode>(gradientCoordinate_enum, gradient->attributeCoordinateMode().toLatin1());
+ gr->setCoordinateMode(coord);
+
+ const QList<DomGradientStop *> stops = gradient->elementGradientStop();
+ QListIterator<DomGradientStop *> it(stops);
+ while (it.hasNext()) {
+ const DomGradientStop *stop = it.next();
+ const DomColor *color = stop->elementColor();
+ gr->setColorAt(stop->attributePosition(), QColor::fromRgb(color->elementRed(),
+ color->elementGreen(), color->elementBlue(), color->attributeAlpha()));
+ }
+ br = QBrush(*gr);
+ delete gr;
+ } else if (style == Qt::TexturePattern) {
+ const DomProperty *texture = brush->elementTexture();
+ if (texture && texture->kind() == DomProperty::Pixmap) {
+ br.setTexture(domPropertyToPixmap(texture));
+ }
+ } else {
+ const DomColor *color = brush->elementColor();
+ br.setColor(QColor::fromRgb(color->elementRed(),
+ color->elementGreen(), color->elementBlue(), color->attributeAlpha()));
+ br.setStyle((Qt::BrushStyle)style);
+ }
+ return br;
+}
+
+/*!
+ \internal
+*/
+DomBrush *QAbstractFormBuilder::saveBrush(const QBrush &br)
+{
+ const QMetaEnum brushStyle_enum = metaEnum<QAbstractFormBuilderGadget>("brushStyle");
+
+ DomBrush *brush = new DomBrush();
+ const Qt::BrushStyle style = br.style();
+ brush->setAttributeBrushStyle(QLatin1String(brushStyle_enum.valueToKey(style)));
+ if (style == Qt::LinearGradientPattern ||
+ style == Qt::RadialGradientPattern ||
+ style == Qt::ConicalGradientPattern) {
+ const QMetaEnum gradientType_enum = metaEnum<QAbstractFormBuilderGadget>("gradientType");
+ const QMetaEnum gradientSpread_enum = metaEnum<QAbstractFormBuilderGadget>("gradientSpread");
+ const QMetaEnum gradientCoordinate_enum = metaEnum<QAbstractFormBuilderGadget>("gradientCoordinate");
+
+ DomGradient *gradient = new DomGradient();
+ const QGradient *gr = br.gradient();
+ const QGradient::Type type = gr->type();
+ gradient->setAttributeType(QLatin1String(gradientType_enum.valueToKey(type)));
+ gradient->setAttributeSpread(QLatin1String(gradientSpread_enum.valueToKey(gr->spread())));
+ gradient->setAttributeCoordinateMode(QLatin1String(gradientCoordinate_enum.valueToKey(gr->coordinateMode())));
+ QList<DomGradientStop *> stops;
+ QGradientStops st = gr->stops();
+ QVectorIterator<QPair<qreal, QColor> > it(st);
+ while (it.hasNext()) {
+ const QPair<qreal, QColor> pair = it.next();
+ DomGradientStop *stop = new DomGradientStop();
+ stop->setAttributePosition(pair.first);
+ DomColor *color = new DomColor();
+ color->setElementRed(pair.second.red());
+ color->setElementGreen(pair.second.green());
+ color->setElementBlue(pair.second.blue());
+ color->setAttributeAlpha(pair.second.alpha());
+ stop->setElementColor(color);
+ stops.append(stop);
+ }
+ gradient->setElementGradientStop(stops);
+ if (type == QGradient::LinearGradient) {
+ QLinearGradient *lgr = (QLinearGradient *)(gr);
+ gradient->setAttributeStartX(lgr->start().x());
+ gradient->setAttributeStartY(lgr->start().y());
+ gradient->setAttributeEndX(lgr->finalStop().x());
+ gradient->setAttributeEndY(lgr->finalStop().y());
+ } else if (type == QGradient::RadialGradient) {
+ QRadialGradient *rgr = (QRadialGradient *)(gr);
+ gradient->setAttributeCentralX(rgr->center().x());
+ gradient->setAttributeCentralY(rgr->center().y());
+ gradient->setAttributeFocalX(rgr->focalPoint().x());
+ gradient->setAttributeFocalY(rgr->focalPoint().y());
+ gradient->setAttributeRadius(rgr->radius());
+ } else if (type == QGradient::ConicalGradient) {
+ QConicalGradient *cgr = (QConicalGradient *)(gr);
+ gradient->setAttributeCentralX(cgr->center().x());
+ gradient->setAttributeCentralY(cgr->center().y());
+ gradient->setAttributeAngle(cgr->angle());
+ }
+
+ brush->setElementGradient(gradient);
+ } else if (style == Qt::TexturePattern) {
+ const QPixmap pixmap = br.texture();
+ if (!pixmap.isNull()) {
+ DomProperty *p = new DomProperty;
+ setPixmapProperty(*p, pixmapPaths(pixmap));
+ brush->setElementTexture(p);
+ }
+ } else {
+ QColor c = br.color();
+ DomColor *color = new DomColor();
+ color->setElementRed(c.red());
+ color->setElementGreen(c.green());
+ color->setElementBlue(c.blue());
+ color->setAttributeAlpha(c.alpha());
+ brush->setElementColor(color);
+ }
+ return brush;
+}
+
+/*!
+ \internal
+*/
+QWidget *QAbstractFormBuilder::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name)
+{
+ Q_UNUSED(widgetName);
+ Q_UNUSED(parentWidget);
+ Q_UNUSED(name);
+ return 0;
+}
+
+/*!
+ \internal
+*/
+QLayout *QAbstractFormBuilder::createLayout(const QString &layoutName, QObject *parent, const QString &name)
+{
+ Q_UNUSED(layoutName);
+ Q_UNUSED(parent);
+ Q_UNUSED(name);
+ return 0;
+}
+
+/*!
+ \internal
+*/
+QAction *QAbstractFormBuilder::createAction(QObject *parent, const QString &name)
+{
+ QAction *action = new QAction(parent);
+ action->setObjectName(name);
+ m_actions.insert(name, action);
+
+ return action;
+}
+
+/*!
+ \internal
+*/
+QActionGroup *QAbstractFormBuilder::createActionGroup(QObject *parent, const QString &name)
+{
+ QActionGroup *g = new QActionGroup(parent);
+ g->setObjectName(name);
+ m_actionGroups.insert(name, g);
+
+ return g;
+}
+
+/*!
+ \fn void QAbstractFormBuilder::save(QIODevice *device, QWidget *widget)
+
+ Saves an XML representation of the given \a widget to the
+ specified \a device in the standard \c{.ui} file format.
+
+ \sa load()*/
+void QAbstractFormBuilder::save(QIODevice *dev, QWidget *widget)
+{
+ DomWidget *ui_widget = createDom(widget, 0);
+ Q_ASSERT( ui_widget != 0 );
+
+ DomUI *ui = new DomUI();
+ ui->setAttributeVersion(QLatin1String("4.0"));
+ ui->setElementWidget(ui_widget);
+
+ saveDom(ui, widget);
+
+ QXmlStreamWriter writer(dev);
+ writer.setAutoFormatting(true);
+ writer.setAutoFormattingIndent(1);
+ writer.writeStartDocument();
+ ui->write(writer);
+ writer.writeEndDocument();
+
+ m_laidout.clear();
+
+ delete ui;
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::saveDom(DomUI *ui, QWidget *widget)
+{
+ ui->setElementClass(widget->objectName());
+
+ if (DomConnections *ui_connections = saveConnections()) {
+ ui->setElementConnections(ui_connections);
+ }
+
+ if (DomCustomWidgets *ui_customWidgets = saveCustomWidgets()) {
+ ui->setElementCustomWidgets(ui_customWidgets);
+ }
+
+ if (DomTabStops *ui_tabStops = saveTabStops()) {
+ ui->setElementTabStops(ui_tabStops);
+ }
+
+ if (DomResources *ui_resources = saveResources()) {
+ ui->setElementResources(ui_resources);
+ }
+ if (DomButtonGroups *ui_buttonGroups = saveButtonGroups(widget))
+ ui->setElementButtonGroups(ui_buttonGroups);
+}
+
+/*!
+ \internal
+*/
+DomConnections *QAbstractFormBuilder::saveConnections()
+{
+ return new DomConnections;
+}
+
+/*!
+ \internal
+*/
+
+DomWidget *QAbstractFormBuilder::createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive)
+{
+ DomWidget *ui_widget = new DomWidget();
+ ui_widget->setAttributeClass(QLatin1String(widget->metaObject()->className()));
+ ui_widget->setElementProperty(computeProperties(widget));
+
+ if (recursive) {
+ if (QLayout *layout = widget->layout()) {
+ if (DomLayout *ui_layout = createDom(layout, 0, ui_parentWidget)) {
+ QList<DomLayout*> ui_layouts;
+ ui_layouts.append(ui_layout);
+
+ ui_widget->setElementLayout(ui_layouts);
+ }
+ }
+ }
+
+ // widgets, actions and action groups
+ QList<DomWidget*> ui_widgets;
+ QList<DomAction*> ui_actions;
+ QList<DomActionGroup*> ui_action_groups;
+
+ QList<QObject*> children;
+
+ // splitters need to store their children in the order specified by child indexes,
+ // not the order of the child list.
+#ifndef QT_NO_SPLITTER
+ if (const QSplitter *splitter = qobject_cast<const QSplitter*>(widget)) {
+ const int count = splitter->count();
+ for (int i = 0; i < count; ++i)
+ children.append(splitter->widget(i));
+ } else
+#endif
+ {
+ QList<QObject *> childObjects = widget->children();
+
+ const QList<QWidget *> list = qVariantValue<QWidgetList>(widget->property("_q_widgetOrder"));
+ foreach (QWidget *w, list) {
+ if (childObjects.contains(w)) {
+ children.append(w);
+ childObjects.removeAll(w);
+ }
+ }
+ children += childObjects;
+
+ const QList<QWidget *> zOrder = qVariantValue<QWidgetList>(widget->property("_q_zOrder"));
+ if (list != zOrder) {
+ QStringList zOrderList;
+ QListIterator<QWidget* > itZOrder(zOrder);
+ while (itZOrder.hasNext())
+ zOrderList.append(itZOrder.next()->objectName());
+ ui_widget->setElementZOrder(zOrderList);
+ }
+ }
+
+ foreach (QObject *obj, children) {
+ if (QWidget *childWidget = qobject_cast<QWidget*>(obj)) {
+ if (m_laidout.contains(childWidget) || recursive == false)
+ continue;
+
+ if (QMenu *menu = qobject_cast<QMenu *>(childWidget)) {
+ QList<QAction *> actions = menu->parentWidget()->actions();
+ QListIterator<QAction *> it(actions);
+ bool found = false;
+ while (it.hasNext()) {
+ if (it.next()->menu() == menu)
+ found = true;
+ }
+ if (!found)
+ continue;
+ }
+
+ if (DomWidget *ui_child = createDom(childWidget, ui_widget)) {
+ ui_widgets.append(ui_child);
+ }
+ } else if (QAction *childAction = qobject_cast<QAction*>(obj)) {
+ if (childAction->actionGroup() != 0) {
+ // it will be added later.
+ continue;
+ }
+
+ if (DomAction *ui_action = createDom(childAction)) {
+ ui_actions.append(ui_action);
+ }
+ } else if (QActionGroup *childActionGroup = qobject_cast<QActionGroup*>(obj)) {
+ if (DomActionGroup *ui_action_group = createDom(childActionGroup)) {
+ ui_action_groups.append(ui_action_group);
+ }
+ }
+ }
+
+ // add-action
+ QList<DomActionRef*> ui_action_refs;
+ foreach (QAction *action, widget->actions()) {
+ if (DomActionRef *ui_action_ref = createActionRefDom(action)) {
+ ui_action_refs.append(ui_action_ref);
+ }
+ }
+
+ if (recursive)
+ ui_widget->setElementWidget(ui_widgets);
+
+ ui_widget->setElementAction(ui_actions);
+ ui_widget->setElementActionGroup(ui_action_groups);
+ ui_widget->setElementAddAction(ui_action_refs);
+
+ saveExtraInfo(widget, ui_widget, ui_parentWidget);
+
+ return ui_widget;
+}
+
+/*!
+ \internal
+*/
+DomActionRef *QAbstractFormBuilder::createActionRefDom(QAction *action)
+{
+ QString name = action->objectName();
+
+ if (action->menu() != 0)
+ name = action->menu()->objectName();
+
+ DomActionRef *ui_action_ref = new DomActionRef();
+ if (action->isSeparator())
+ ui_action_ref->setAttributeName(QFormBuilderStrings::instance().separator);
+ else
+ ui_action_ref->setAttributeName(name);
+
+ return ui_action_ref;
+}
+
+/*!
+ \internal
+*/
+DomLayout *QAbstractFormBuilder::createDom(QLayout *layout, DomLayout *ui_layout, DomWidget *ui_parentWidget)
+{
+ Q_UNUSED(ui_layout)
+ DomLayout *lay = new DomLayout();
+ lay->setAttributeClass(QLatin1String(layout->metaObject()->className()));
+ const QString objectName = layout->objectName();
+ if (!objectName.isEmpty())
+ lay->setAttributeName(objectName);
+ lay->setElementProperty(computeProperties(layout));
+
+ QList<DomLayoutItem*> ui_items;
+
+ QMap<QObject *, QLayoutItem *> objectToItem;
+ QList<QLayoutItem *> spacerItems;
+ QList<QLayoutItem *> newList;
+
+ for (int idx=0; layout->itemAt(idx); ++idx) {
+ QLayoutItem *item = layout->itemAt(idx);
+ if (item->widget())
+ objectToItem[item->widget()] = item;
+ else if (item->layout())
+ objectToItem[item->layout()] = item;
+ else if (item->spacerItem())
+ spacerItems.append(item);
+ newList.append(item);
+ }
+
+ if (qobject_cast<QGridLayout *>(layout)) {
+ newList.clear();
+ QList<QObject *> childrenList = layout->parentWidget()->children();
+ foreach (QObject *o, childrenList) {
+ if (objectToItem.contains(o))
+ newList.append(objectToItem[o]);
+ }
+ newList += spacerItems;
+ }
+
+ foreach (QLayoutItem *item, newList) {
+ DomLayoutItem *ui_item = createDom(item, lay, ui_parentWidget);
+ if (ui_item)
+ ui_items.append(ui_item);
+ }
+
+ lay->setElementItem(ui_items);
+
+ return lay;
+}
+
+/*!
+ \internal
+*/
+DomLayoutItem *QAbstractFormBuilder::createDom(QLayoutItem *item, DomLayout *ui_layout, DomWidget *ui_parentWidget)
+{
+ DomLayoutItem *ui_item = new DomLayoutItem();
+
+ if (item->widget()) {
+ ui_item->setElementWidget(createDom(item->widget(), ui_parentWidget));
+ m_laidout.insert(item->widget(), true);
+ } else if (item->layout()) {
+ ui_item->setElementLayout(createDom(item->layout(), ui_layout, ui_parentWidget));
+ } else if (item->spacerItem()) {
+ ui_item->setElementSpacer(createDom(item->spacerItem(), ui_layout, ui_parentWidget));
+ }
+
+ return ui_item;
+}
+
+/*!
+ \internal
+*/
+DomSpacer *QAbstractFormBuilder::createDom(QSpacerItem *spacer, DomLayout *ui_layout, DomWidget *ui_parentWidget)
+{
+ Q_UNUSED(ui_layout);
+ Q_UNUSED(ui_parentWidget);
+
+ DomSpacer *ui_spacer = new DomSpacer();
+ QList<DomProperty*> properties;
+
+ DomProperty *prop = 0;
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ // sizeHint property
+ prop = new DomProperty();
+ prop->setAttributeName(strings.sizeHintProperty);
+ prop->setElementSize(new DomSize());
+ prop->elementSize()->setElementWidth(spacer->sizeHint().width());
+ prop->elementSize()->setElementHeight(spacer->sizeHint().height());
+ properties.append(prop);
+
+ // orientation property
+ prop = new DomProperty(); // ### we don't implemented the case where expandingDirections() is both Vertical and Horizontal
+ prop->setAttributeName(strings.orientationProperty);
+ prop->setElementEnum((spacer->expandingDirections() & Qt::Horizontal) ? strings.qtHorizontal : strings.qtVertical);
+ properties.append(prop);
+
+ ui_spacer->setElementProperty(properties);
+ return ui_spacer;
+}
+
+/*!
+ \internal
+*/
+DomProperty *QAbstractFormBuilder::createProperty(QObject *obj, const QString &pname, const QVariant &v)
+{
+ if (!checkProperty(obj, pname)) {
+ return 0;
+ }
+ return variantToDomProperty(this, obj->metaObject(), pname, v);
+}
+
+/*!
+ \internal
+*/
+QList<DomProperty*> QAbstractFormBuilder::computeProperties(QObject *obj)
+{
+ QList<DomProperty*> lst;
+
+ const QMetaObject *meta = obj->metaObject();
+
+ QHash<QByteArray, bool> properties;
+ const int propertyCount = meta->propertyCount();
+ for(int i=0; i < propertyCount; ++i)
+ properties.insert(meta->property(i).name(), true);
+
+ const QList<QByteArray> propertyNames = properties.keys();
+
+ const int propertyNamesCount = propertyNames.size();
+ for(int i=0; i<propertyNamesCount ; ++i) {
+ const QString pname = QString::fromUtf8(propertyNames.at(i));
+ const QMetaProperty prop = meta->property(meta->indexOfProperty(pname.toUtf8()));
+
+ if (!prop.isWritable() || !checkProperty(obj, QLatin1String(prop.name())))
+ continue;
+
+ const QVariant v = prop.read(obj);
+
+ DomProperty *dom_prop = 0;
+ if (v.type() == QVariant::Int) {
+ dom_prop = new DomProperty();
+
+ if (prop.isFlagType())
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Flags property are not supported yet."));
+
+ if (prop.isEnumType()) {
+ QString scope = QString::fromUtf8(prop.enumerator().scope());
+ if (scope.size())
+ scope += QString::fromUtf8("::");
+ const QString e = QString::fromUtf8(prop.enumerator().valueToKey(v.toInt()));
+ if (e.size())
+ dom_prop->setElementEnum(scope + e);
+ } else
+ dom_prop->setElementNumber(v.toInt());
+ dom_prop->setAttributeName(pname);
+ } else {
+ dom_prop = createProperty(obj, pname, v);
+ }
+
+ if (!dom_prop || dom_prop->kind() == DomProperty::Unknown)
+ delete dom_prop;
+ else
+ lst.append(dom_prop);
+ }
+
+ return lst;
+}
+
+
+/*!
+ \internal
+ \typedef QAbstractFormBuilder::DomPropertyHash
+ \typedef QAbstractFormBuilder::IconPaths
+*/
+
+
+/*!
+ \internal
+*/
+QAbstractFormBuilder::DomPropertyHash QAbstractFormBuilder::propertyMap(const QList<DomProperty*> &properties)
+{
+ DomPropertyHash map;
+
+ foreach (DomProperty *p, properties)
+ map.insert(p->attributeName(), p);
+
+ return map;
+}
+
+/*!
+ \internal
+*/
+bool QAbstractFormBuilder::checkProperty(QObject *obj, const QString &prop) const
+{
+ Q_UNUSED(obj);
+ Q_UNUSED(prop);
+
+ return true;
+}
+
+/*!
+ \internal
+*/
+QString QAbstractFormBuilder::toString(const DomString *str)
+{
+ return str ? str->text() : QString();
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::applyTabStops(QWidget *widget, DomTabStops *tabStops)
+{
+ if (!tabStops)
+ return;
+
+ QWidget *lastWidget = 0;
+
+ const QStringList l = tabStops->elementTabStop();
+ for (int i=0; i<l.size(); ++i) {
+ const QString name = l.at(i);
+
+ QWidget *child = qFindChild<QWidget*>(widget, name);
+ if (!child) {
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "While applying tab stops: The widget '%1' could not be found.").arg(name));
+ continue;
+ }
+
+ if (i == 0) {
+ lastWidget = qFindChild<QWidget*>(widget, name);
+ continue;
+ } else if (!child || !lastWidget) {
+ continue;
+ }
+
+ QWidget::setTabOrder(lastWidget, child);
+
+ lastWidget = qFindChild<QWidget*>(widget, name);
+ }
+}
+
+/*!
+ \internal
+*/
+DomCustomWidgets *QAbstractFormBuilder::saveCustomWidgets()
+{
+ return 0;
+}
+
+/*!
+ \internal
+*/
+DomTabStops *QAbstractFormBuilder::saveTabStops()
+{
+ return 0;
+}
+
+/*!
+ \internal
+*/
+DomResources *QAbstractFormBuilder::saveResources()
+{
+ return 0;
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+
+DomButtonGroups *QAbstractFormBuilder::saveButtonGroups(const QWidget *mainContainer)
+{
+ // Save fst order buttongroup children of maincontainer
+ typedef QList<QButtonGroup*> ButtonGroupList;
+ const QObjectList mchildren = mainContainer->children();
+ if (mchildren.empty())
+ return 0;
+ QList<DomButtonGroup*> domGroups;
+ const QObjectList::const_iterator cend = mchildren.constEnd();
+ for (QObjectList::const_iterator it = mchildren.constBegin(); it != cend; ++it)
+ if (QButtonGroup *bg = qobject_cast<QButtonGroup *>(*it))
+ if (DomButtonGroup* dg = createDom(bg))
+ domGroups.push_back(dg);
+
+ if (domGroups.empty())
+ return 0;
+ DomButtonGroups *rc = new DomButtonGroups;
+ rc->setElementButtonGroup(domGroups);
+ return rc;
+}
+
+// VC6 would not find templated members, so we use statics and this utter hack.
+class FriendlyFB : public QAbstractFormBuilder {
+public:
+ using QAbstractFormBuilder::saveResource;
+ using QAbstractFormBuilder::saveText;
+ using QAbstractFormBuilder::resourceBuilder;
+ using QAbstractFormBuilder::textBuilder;
+ using QAbstractFormBuilder::toVariant;
+};
+
+template<class T>
+static void storeItemProps(QAbstractFormBuilder *abstractFormBuilder, const T *item,
+ QList<DomProperty*> *properties)
+{
+ static const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ FriendlyFB * const formBuilder = static_cast<FriendlyFB *>(abstractFormBuilder);
+
+ DomProperty *p;
+ QVariant v;
+
+ foreach (const QFormBuilderStrings::TextRoleNName &it, strings.itemTextRoles)
+ if ((p = formBuilder->saveText(it.second, item->data(it.first.second))))
+ properties->append(p);
+
+ foreach (const QFormBuilderStrings::RoleNName &it, strings.itemRoles)
+ if ((v = item->data(it.first)).isValid() &&
+ (p = variantToDomProperty(abstractFormBuilder,
+ static_cast<const QMetaObject *>(&QAbstractFormBuilderGadget::staticMetaObject),
+ it.second, v)))
+ properties->append(p);
+
+ if ((p = formBuilder->saveResource(item->data(Qt::DecorationPropertyRole))))
+ properties->append(p);
+}
+
+template<class T>
+static void storeItemFlags(const T *item, QList<DomProperty*> *properties)
+{
+ static const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ static const Qt::ItemFlags defaultFlags = T().flags();
+ static const QMetaEnum itemFlags_enum = metaEnum<QAbstractFormBuilderGadget>("itemFlags");
+
+ if (item->flags() != defaultFlags) {
+ DomProperty *p = new DomProperty;
+ p->setAttributeName(strings.flagsAttribute);
+ p->setElementSet(QString::fromAscii(itemFlags_enum.valueToKeys(item->flags())));
+ properties->append(p);
+ }
+}
+
+template<class T>
+static void storeItemPropsNFlags(QAbstractFormBuilder *abstractFormBuilder, const T *item,
+ QList<DomProperty*> *properties)
+{
+ storeItemProps<T>(abstractFormBuilder, item, properties);
+ storeItemFlags<T>(item, properties);
+}
+
+template<class T>
+static void loadItemProps(QAbstractFormBuilder *abstractFormBuilder, T *item,
+ const QHash<QString, DomProperty*> &properties)
+{
+ static const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ FriendlyFB * const formBuilder = static_cast<FriendlyFB *>(abstractFormBuilder);
+
+ DomProperty *p;
+ QVariant v;
+
+ foreach (const QFormBuilderStrings::TextRoleNName &it, strings.itemTextRoles)
+ if ((p = properties.value(it.second))) {
+ v = formBuilder->textBuilder()->loadText(p);
+ QVariant nativeValue = formBuilder->textBuilder()->toNativeValue(v);
+ item->setData(it.first.first, qVariantValue<QString>(nativeValue));
+ item->setData(it.first.second, v);
+ }
+
+ foreach (const QFormBuilderStrings::RoleNName &it, strings.itemRoles)
+ if ((p = properties.value(it.second)) &&
+ (v = formBuilder->toVariant(&QAbstractFormBuilderGadget::staticMetaObject, p)).isValid())
+ item->setData(it.first, v);
+
+ if ((p = properties.value(strings.iconAttribute))) {
+ v = formBuilder->resourceBuilder()->loadResource(formBuilder->workingDirectory(), p);
+ QVariant nativeValue = formBuilder->resourceBuilder()->toNativeValue(v);
+ item->setIcon(qVariantValue<QIcon>(nativeValue));
+ item->setData(Qt::DecorationPropertyRole, v);
+ }
+}
+
+template<class T>
+static void loadItemPropsNFlags(QAbstractFormBuilder *abstractFormBuilder, T *item,
+ const QHash<QString, DomProperty*> &properties)
+{
+ static const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ static const QMetaEnum itemFlags_enum = metaEnum<QAbstractFormBuilderGadget>("itemFlags");
+
+ loadItemProps<T>(abstractFormBuilder, item, properties);
+
+ DomProperty *p;
+ if ((p = properties.value(strings.flagsAttribute)) && p->kind() == DomProperty::Set)
+ item->setFlags(enumKeysToValue<Qt::ItemFlags>(itemFlags_enum, p->elementSet().toAscii()));
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::saveTreeWidgetExtraInfo(QTreeWidget *treeWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget)
+{
+ Q_UNUSED(ui_parentWidget);
+
+ QList<DomColumn*> columns;
+ DomProperty *p;
+ QVariant v;
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ // save the header
+ for (int c = 0; c<treeWidget->columnCount(); ++c) {
+ DomColumn *column = new DomColumn;
+
+ QList<DomProperty*> properties;
+
+ foreach (const QFormBuilderStrings::TextRoleNName &it, strings.itemTextRoles) {
+ p = saveText(it.second, treeWidget->headerItem()->data(c, it.first.second));
+ // Prevent uic 4.4.X from crashing if it cannot find a column text
+ if (!p && it.first.first == Qt::EditRole && it.second == QLatin1String("text")) {
+ DomString *defaultHeader = new DomString;
+ defaultHeader->setText(QString::number(c + 1));
+ defaultHeader->setAttributeNotr(QLatin1String("true"));
+ p = new DomProperty;
+ p->setAttributeName(it.second);
+ p->setElementString(defaultHeader);
+ }
+ if (p)
+ properties.append(p);
+ }
+
+ foreach (const QFormBuilderStrings::RoleNName &it, strings.itemRoles)
+ if ((v = treeWidget->headerItem()->data(c, it.first)).isValid() &&
+ (p = variantToDomProperty(this, &QAbstractFormBuilderGadget::staticMetaObject, it.second, v)))
+ properties.append(p);
+
+ if ((p = saveResource(treeWidget->headerItem()->data(c, Qt::DecorationPropertyRole))))
+ properties.append(p);
+
+ column->setElementProperty(properties);
+ columns.append(column);
+ }
+
+ ui_widget->setElementColumn(columns);
+
+ QList<DomItem *> items = ui_widget->elementItem();
+
+ QQueue<QPair<QTreeWidgetItem *, DomItem *> > pendingQueue;
+ for (int i = 0; i < treeWidget->topLevelItemCount(); i++)
+ pendingQueue.enqueue(qMakePair(treeWidget->topLevelItem(i), (DomItem *)0));
+
+ while (!pendingQueue.isEmpty()) {
+ const QPair<QTreeWidgetItem *, DomItem *> pair = pendingQueue.dequeue();
+ QTreeWidgetItem *item = pair.first;
+ DomItem *parentDomItem = pair.second;
+
+ DomItem *currentDomItem = new DomItem;
+
+ QList<DomProperty*> properties;
+ for (int c = 0; c < treeWidget->columnCount(); c++) {
+ foreach (const QFormBuilderStrings::TextRoleNName &it, strings.itemTextRoles)
+ if ((p = saveText(it.second, item->data(c, it.first.second))))
+ properties.append(p);
+
+ foreach (const QFormBuilderStrings::RoleNName &it, strings.itemRoles)
+ if ((v = item->data(c, it.first)).isValid() &&
+ (p = variantToDomProperty(this, &QAbstractFormBuilderGadget::staticMetaObject, it.second, v)))
+ properties.append(p);
+
+ if ((p = saveResource(item->data(c, Qt::DecorationPropertyRole))))
+ properties.append(p);
+ }
+ storeItemFlags(item, &properties);
+ currentDomItem->setElementProperty(properties);
+
+ if (parentDomItem) {
+ QList<DomItem *> childrenItems = parentDomItem->elementItem();
+ childrenItems.append(currentDomItem);
+ parentDomItem->setElementItem(childrenItems);
+ } else
+ items.append(currentDomItem);
+
+ for (int i = 0; i < item->childCount(); i++)
+ pendingQueue.enqueue(qMakePair(item->child(i), currentDomItem));
+ }
+
+ ui_widget->setElementItem(items);
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::saveTableWidgetExtraInfo(QTableWidget *tableWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget)
+{
+ Q_UNUSED(ui_parentWidget);
+
+ // save the horizontal header
+ QList<DomColumn*> columns;
+ for (int c = 0; c < tableWidget->columnCount(); c++) {
+ QList<DomProperty*> properties;
+ QTableWidgetItem *item = tableWidget->horizontalHeaderItem(c);
+ if (item)
+ storeItemProps(this, item, &properties);
+
+ DomColumn *column = new DomColumn;
+ column->setElementProperty(properties);
+ columns.append(column);
+ }
+ ui_widget->setElementColumn(columns);
+
+ // save the vertical header
+ QList<DomRow*> rows;
+ for (int r = 0; r < tableWidget->rowCount(); r++) {
+ QList<DomProperty*> properties;
+ QTableWidgetItem *item = tableWidget->verticalHeaderItem(r);
+ if (item)
+ storeItemProps(this, item, &properties);
+
+ DomRow *row = new DomRow;
+ row->setElementProperty(properties);
+ rows.append(row);
+ }
+ ui_widget->setElementRow(rows);
+
+ QList<DomItem *> items = ui_widget->elementItem();
+ for (int r = 0; r < tableWidget->rowCount(); r++)
+ for (int c = 0; c < tableWidget->columnCount(); c++) {
+ QTableWidgetItem *item = tableWidget->item(r, c);
+ if (item) {
+ QList<DomProperty*> properties;
+ storeItemPropsNFlags(this, item, &properties);
+
+ DomItem *domItem = new DomItem;
+ domItem->setAttributeRow(r);
+ domItem->setAttributeColumn(c);
+ domItem->setElementProperty(properties);
+ items.append(domItem);
+ }
+ }
+
+ ui_widget->setElementItem(items);
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::saveListWidgetExtraInfo(QListWidget *listWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget)
+{
+ Q_UNUSED(ui_parentWidget);
+
+ QList<DomItem*> ui_items = ui_widget->elementItem();
+ for (int i=0; i<listWidget->count(); ++i) {
+ QList<DomProperty*> properties;
+ storeItemPropsNFlags(this, listWidget->item(i), &properties);
+
+ DomItem *ui_item = new DomItem();
+ ui_item->setElementProperty(properties);
+ ui_items.append(ui_item);
+ }
+
+ ui_widget->setElementItem(ui_items);
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::saveComboBoxExtraInfo(QComboBox *comboBox, DomWidget *ui_widget, DomWidget *ui_parentWidget)
+{
+ Q_UNUSED(ui_parentWidget);
+ QList<DomItem*> ui_items = ui_widget->elementItem();
+
+ const int count = comboBox->count();
+ for (int i=0; i < count; ++i) {
+ // We might encounter items for which both builders return 0 in Designer
+ // (indicating a custom combo adding items in the constructor). Ignore those.
+ DomProperty *textProperty = saveText(QFormBuilderStrings::instance().textAttribute,
+ comboBox->itemData(i, Qt::DisplayPropertyRole));
+ DomProperty *iconProperty = saveResource(comboBox->itemData(i, Qt::DecorationPropertyRole));
+ if (textProperty || iconProperty) {
+ QList<DomProperty*> properties;
+ if (textProperty)
+ properties.push_back(textProperty);
+ if (iconProperty)
+ properties.push_back(iconProperty);
+
+ DomItem *ui_item = new DomItem();
+ ui_item->setElementProperty(properties);
+ ui_items.push_back(ui_item);
+ }
+ }
+
+ ui_widget->setElementItem(ui_items);
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+
+void QAbstractFormBuilder::saveButtonExtraInfo(const QAbstractButton *widget, DomWidget *ui_widget, DomWidget *)
+{
+ typedef QList<DomProperty*> DomPropertyList;
+ if (const QButtonGroup *buttonGroup = widget->group()) {
+ DomPropertyList attributes = ui_widget->elementAttribute();
+ DomString *domString = new DomString();
+ domString->setText(buttonGroup->objectName());
+ DomProperty *domProperty = new DomProperty();
+ domProperty->setAttributeName(QLatin1String(buttonGroupPropertyC));
+ domProperty->setElementString(domString);
+ attributes += domProperty;
+ ui_widget->setElementAttribute(attributes);
+ }
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+void QAbstractFormBuilder::saveItemViewExtraInfo(const QAbstractItemView *itemView,
+ DomWidget *ui_widget, DomWidget *)
+{
+ //
+ // Special handling for qtableview/qtreeview fake header attributes
+ //
+ static QStringList realPropertyNames =
+ (QStringList() << QLatin1String("visible")
+ << QLatin1String("cascadingSectionResizes")
+ << QLatin1String("defaultSectionSize")
+ << QLatin1String("highlightSections")
+ << QLatin1String("minimumSectionSize")
+ << QLatin1String("showSortIndicator")
+ << QLatin1String("stretchLastSection"));
+
+ if (const QTreeView *treeView = qobject_cast<const QTreeView*>(itemView)) {
+ QList<DomProperty*> viewProperties = ui_widget->elementAttribute();
+ QList<DomProperty*> headerProperties = computeProperties(treeView->header());
+ foreach (const QString &realPropertyName, realPropertyNames) {
+ const QString upperPropertyName = realPropertyName.at(0).toUpper()
+ + realPropertyName.mid(1);
+ const QString fakePropertyName = QLatin1String("header") + upperPropertyName;
+ foreach (DomProperty *property, headerProperties) {
+ if (property->attributeName() == realPropertyName) {
+ property->setAttributeName(fakePropertyName);
+ viewProperties << property;
+ }
+ }
+ }
+ ui_widget->setElementAttribute(viewProperties);
+ } else if (const QTableView *tableView = qobject_cast<const QTableView*>(itemView)) {
+ static QStringList headerPrefixes =
+ (QStringList() << QLatin1String("horizontalHeader")
+ << QLatin1String("verticalHeader"));
+
+ QList<DomProperty*> viewProperties = ui_widget->elementAttribute();
+ foreach (const QString &headerPrefix, headerPrefixes) {
+ QList<DomProperty*> headerProperties;
+ if (headerPrefix == QLatin1String("horizontalHeader"))
+ headerProperties = computeProperties(tableView->horizontalHeader());
+ else
+ headerProperties = computeProperties(tableView->verticalHeader());
+ foreach (const QString &realPropertyName, realPropertyNames) {
+ const QString upperPropertyName = realPropertyName.at(0).toUpper()
+ + realPropertyName.mid(1);
+ const QString fakePropertyName = headerPrefix + upperPropertyName;
+ foreach (DomProperty *property, headerProperties) {
+ if (property->attributeName() == realPropertyName) {
+ property->setAttributeName(fakePropertyName);
+ viewProperties << property;
+ }
+ }
+ }
+ }
+ ui_widget->setElementAttribute(viewProperties);
+ }
+}
+
+/*!
+ \internal
+ \since 4.4
+*/
+
+void QAbstractFormBuilder::setResourceBuilder(QResourceBuilder *builder)
+{
+ QFormBuilderExtra::instance(this)->setResourceBuilder(builder);
+}
+
+/*!
+ \internal
+ \since 4.4
+*/
+
+QResourceBuilder *QAbstractFormBuilder::resourceBuilder() const
+{
+ return QFormBuilderExtra::instance(this)->resourceBuilder();
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+
+void QAbstractFormBuilder::setTextBuilder(QTextBuilder *builder)
+{
+ QFormBuilderExtra::instance(this)->setTextBuilder(builder);
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+
+QTextBuilder *QAbstractFormBuilder::textBuilder() const
+{
+ return QFormBuilderExtra::instance(this)->textBuilder();
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::saveExtraInfo(QWidget *widget, DomWidget *ui_widget,
+ DomWidget *ui_parentWidget)
+{
+ if (QListWidget *listWidget = qobject_cast<QListWidget*>(widget)) {
+ saveListWidgetExtraInfo(listWidget, ui_widget, ui_parentWidget);
+ } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget*>(widget)) {
+ saveTreeWidgetExtraInfo(treeWidget, ui_widget, ui_parentWidget);
+ } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget*>(widget)) {
+ saveTableWidgetExtraInfo(tableWidget, ui_widget, ui_parentWidget);
+ } else if (QComboBox *comboBox = qobject_cast<QComboBox*>(widget)) {
+ if (!qobject_cast<QFontComboBox*>(widget))
+ saveComboBoxExtraInfo(comboBox, ui_widget, ui_parentWidget);
+ } else if(QAbstractButton *ab = qobject_cast<QAbstractButton *>(widget)) {
+ saveButtonExtraInfo(ab, ui_widget, ui_parentWidget);
+ }
+ if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(widget)) {
+ saveItemViewExtraInfo(itemView, ui_widget, ui_parentWidget);
+ }
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::loadListWidgetExtraInfo(DomWidget *ui_widget, QListWidget *listWidget, QWidget *parentWidget)
+{
+ Q_UNUSED(parentWidget);
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ const QMetaEnum itemFlags_enum = metaEnum<QAbstractFormBuilderGadget>("itemFlags");
+
+ foreach (DomItem *ui_item, ui_widget->elementItem()) {
+ const DomPropertyHash properties = propertyMap(ui_item->elementProperty());
+ QListWidgetItem *item = new QListWidgetItem(listWidget);
+ loadItemPropsNFlags<QListWidgetItem>(this, item, properties);
+ }
+
+ DomProperty *currentRow = propertyMap(ui_widget->elementProperty()).value(strings.currentRowProperty);
+ if (currentRow)
+ listWidget->setCurrentRow(currentRow->elementNumber());
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWidget *treeWidget, QWidget *parentWidget)
+{
+ Q_UNUSED(parentWidget);
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ const QMetaEnum itemFlags_enum = metaEnum<QAbstractFormBuilderGadget>("itemFlags");
+ const QList<DomColumn*> columns = ui_widget->elementColumn();
+ if (columns.count() > 0)
+ treeWidget->setColumnCount(columns.count());
+
+ for (int i = 0; i<columns.count(); ++i) {
+ const DomColumn *c = columns.at(i);
+ const DomPropertyHash properties = propertyMap(c->elementProperty());
+
+ DomProperty *p;
+ QVariant v;
+
+ foreach (const QFormBuilderStrings::RoleNName &it, strings.itemRoles)
+ if ((p = properties.value(it.second)) &&
+ (v = toVariant(&QAbstractFormBuilderGadget::staticMetaObject, p)).isValid())
+ treeWidget->headerItem()->setData(i, it.first, v);
+
+ foreach (const QFormBuilderStrings::TextRoleNName &it, strings.itemTextRoles)
+ if ((p = properties.value(it.second))) {
+ v = textBuilder()->loadText(p);
+ QVariant nativeValue = textBuilder()->toNativeValue(v);
+ treeWidget->headerItem()->setData(i, it.first.first, qVariantValue<QString>(nativeValue));
+ treeWidget->headerItem()->setData(i, it.first.second, v);
+ }
+
+ if ((p = properties.value(strings.iconAttribute))) {
+ v = resourceBuilder()->loadResource(workingDirectory(), p);
+ QVariant nativeValue = resourceBuilder()->toNativeValue(v);
+ treeWidget->headerItem()->setIcon(i, qVariantValue<QIcon>(nativeValue));
+ treeWidget->headerItem()->setData(i, Qt::DecorationPropertyRole, v);
+ }
+ }
+
+ QQueue<QPair<DomItem *, QTreeWidgetItem *> > pendingQueue;
+ foreach (DomItem *ui_item, ui_widget->elementItem())
+ pendingQueue.enqueue(qMakePair(ui_item, (QTreeWidgetItem *)0));
+
+ while (!pendingQueue.isEmpty()) {
+ const QPair<DomItem *, QTreeWidgetItem *> pair = pendingQueue.dequeue();
+ const DomItem *domItem = pair.first;
+ QTreeWidgetItem *parentItem = pair.second;
+
+ QTreeWidgetItem *currentItem = 0;
+
+ if (parentItem)
+ currentItem = new QTreeWidgetItem(parentItem);
+ else
+ currentItem = new QTreeWidgetItem(treeWidget);
+
+ const QList<DomProperty *> properties = domItem->elementProperty();
+ int col = -1;
+ foreach (DomProperty *property, properties) {
+ if (property->attributeName() == strings.flagsAttribute && !property->elementSet().isEmpty()) {
+ currentItem->setFlags(enumKeysToValue<Qt::ItemFlags>(itemFlags_enum, property->elementSet().toAscii()));
+ } else if (property->attributeName() == strings.textAttribute && property->elementString()) {
+ col++;
+ QVariant textV = textBuilder()->loadText(property);
+ QVariant nativeValue = textBuilder()->toNativeValue(textV);
+ currentItem->setText(col, qVariantValue<QString>(nativeValue));
+ currentItem->setData(col, Qt::DisplayPropertyRole, textV);
+ } else if (col >= 0) {
+ if (property->attributeName() == strings.iconAttribute) {
+ QVariant v = resourceBuilder()->loadResource(workingDirectory(), property);
+ if (v.isValid()) {
+ QVariant nativeValue = resourceBuilder()->toNativeValue(v);
+ currentItem->setIcon(col, qVariantValue<QIcon>(nativeValue));
+ currentItem->setData(col, Qt::DecorationPropertyRole, v);
+ }
+ } else {
+ QVariant v;
+ int role = strings.treeItemRoleHash.value(property->attributeName(), (Qt::ItemDataRole)-1);
+ if (role >= 0) {
+ if ((v = toVariant(&QAbstractFormBuilderGadget::staticMetaObject, property)).isValid())
+ currentItem->setData(col, role, v);
+ } else {
+ QPair<Qt::ItemDataRole, Qt::ItemDataRole> rolePair =
+ strings.treeItemTextRoleHash.value(property->attributeName(),
+ qMakePair((Qt::ItemDataRole)-1, (Qt::ItemDataRole)-1));
+ if (rolePair.first >= 0) {
+ QVariant textV = textBuilder()->loadText(property);
+ QVariant nativeValue = textBuilder()->toNativeValue(textV);
+ currentItem->setData(col, rolePair.first, qVariantValue<QString>(nativeValue));
+ currentItem->setData(col, rolePair.second, textV);
+ }
+ }
+ }
+ }
+ }
+
+ foreach (DomItem *childItem, domItem->elementItem())
+ pendingQueue.enqueue(qMakePair(childItem, currentItem));
+
+ }
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::loadTableWidgetExtraInfo(DomWidget *ui_widget, QTableWidget *tableWidget, QWidget *parentWidget)
+{
+ Q_UNUSED(parentWidget);
+
+ const QList<DomColumn*> columns = ui_widget->elementColumn();
+ if (columns.count() > 0)
+ tableWidget->setColumnCount(columns.count());
+ for (int i = 0; i< columns.count(); i++) {
+ DomColumn *c = columns.at(i);
+ const DomPropertyHash properties = propertyMap(c->elementProperty());
+
+ if (!properties.isEmpty()) {
+ QTableWidgetItem *item = new QTableWidgetItem;
+ loadItemProps(this, item, properties);
+ tableWidget->setHorizontalHeaderItem(i, item);
+ }
+ }
+
+ const QList<DomRow*> rows = ui_widget->elementRow();
+ if (rows.count() > 0)
+ tableWidget->setRowCount(rows.count());
+ for (int i = 0; i< rows.count(); i++) {
+ const DomRow *r = rows.at(i);
+ const DomPropertyHash properties = propertyMap(r->elementProperty());
+
+ if (!properties.isEmpty()) {
+ QTableWidgetItem *item = new QTableWidgetItem;
+ loadItemProps(this, item, properties);
+ tableWidget->setVerticalHeaderItem(i, item);
+ }
+ }
+
+ foreach (DomItem *ui_item, ui_widget->elementItem()) {
+ if (ui_item->hasAttributeRow() && ui_item->hasAttributeColumn()) {
+ const DomPropertyHash properties = propertyMap(ui_item->elementProperty());
+ QTableWidgetItem *item = new QTableWidgetItem;
+ loadItemPropsNFlags(this, item, properties);
+ tableWidget->setItem(ui_item->attributeRow(), ui_item->attributeColumn(), item);
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::loadComboBoxExtraInfo(DomWidget *ui_widget, QComboBox *comboBox, QWidget *parentWidget)
+{
+ Q_UNUSED(parentWidget);
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ foreach (DomItem *ui_item, ui_widget->elementItem()) {
+ const DomPropertyHash properties = propertyMap(ui_item->elementProperty());
+ QString text;
+ QIcon icon;
+ QVariant textData;
+ QVariant iconData;
+
+ DomProperty *p = 0;
+
+ p = properties.value(strings.textAttribute);
+ if (p && p->elementString()) {
+ textData = textBuilder()->loadText(p);
+ text = qVariantValue<QString>(textBuilder()->toNativeValue(textData));
+ }
+
+ p = properties.value(strings.iconAttribute);
+ if (p) {
+ iconData = resourceBuilder()->loadResource(workingDirectory(), p);
+ icon = qVariantValue<QIcon>(resourceBuilder()->toNativeValue(iconData));
+ }
+
+ comboBox->addItem(icon, text);
+ comboBox->setItemData((comboBox->count()-1), iconData, Qt::DecorationPropertyRole);
+ comboBox->setItemData((comboBox->count()-1), textData, Qt::DisplayPropertyRole);
+ }
+
+ DomProperty *currentIndex = propertyMap(ui_widget->elementProperty()).value(strings.currentIndexProperty);
+ if (currentIndex)
+ comboBox->setCurrentIndex(currentIndex->elementNumber());
+}
+
+// Get the button group name out of a widget's attribute list
+static QString buttonGroupName(const DomWidget *ui_widget)
+{
+ typedef QList<DomProperty*> DomPropertyList;
+ const DomPropertyList attributes = ui_widget->elementAttribute();
+ if (attributes.empty())
+ return QString();
+ const QString buttonGroupProperty = QLatin1String(buttonGroupPropertyC);
+ const DomPropertyList::const_iterator cend = attributes.constEnd();
+ for (DomPropertyList::const_iterator it = attributes.constBegin(); it != cend; ++it)
+ if ( (*it)->attributeName() == buttonGroupProperty)
+ return (*it)->elementString()->text();
+ return QString();
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+
+void QAbstractFormBuilder::loadButtonExtraInfo(const DomWidget *ui_widget, QAbstractButton *button, QWidget *)
+{
+ typedef QFormBuilderExtra::ButtonGroupEntry ButtonGroupEntry;
+ typedef QFormBuilderExtra::ButtonGroupHash ButtonGroupHash;
+
+ const QString groupName = buttonGroupName(ui_widget);
+ if (groupName.isEmpty())
+ return;
+ // Find entry
+ QFormBuilderExtra *extra = QFormBuilderExtra::instance(this);
+ ButtonGroupHash &buttonGroups = extra->buttonGroups();
+ ButtonGroupHash::iterator it = buttonGroups.find(groupName);
+ if (it == buttonGroups.end()) {
+#ifdef QFORMINTERNAL_NAMESPACE // Suppress the warning when copying in Designer
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "Invalid QButtonGroup reference '%1' referenced by '%2'.").arg(groupName, button->objectName()));
+#endif
+ return;
+ }
+ // Create button group on demand?
+ QButtonGroup *&group = it.value().second;
+ if (group == 0) {
+ group = new QButtonGroup;
+ group->setObjectName(groupName);
+ applyProperties(group, it.value().first->elementProperty());
+ }
+ group->addButton(button);
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+void QAbstractFormBuilder::loadItemViewExtraInfo(DomWidget *ui_widget, QAbstractItemView *itemView,
+ QWidget *)
+{
+ //
+ // Special handling for qtableview/qtreeview fake header attributes
+ //
+ static QStringList realPropertyNames =
+ (QStringList() << QLatin1String("visible")
+ << QLatin1String("cascadingSectionResizes")
+ << QLatin1String("defaultSectionSize")
+ << QLatin1String("highlightSections")
+ << QLatin1String("minimumSectionSize")
+ << QLatin1String("showSortIndicator")
+ << QLatin1String("stretchLastSection"));
+
+ if (QTreeView *treeView = qobject_cast<QTreeView*>(itemView)) {
+ QList<DomProperty*> allAttributes = ui_widget->elementAttribute();
+ QList<DomProperty*> headerProperties;
+ foreach (const QString &realPropertyName, realPropertyNames) {
+ const QString upperPropertyName = realPropertyName.at(0).toUpper()
+ + realPropertyName.mid(1);
+ const QString fakePropertyName = QLatin1String("header") + upperPropertyName;
+ foreach (DomProperty *attr, allAttributes) {
+ if (attr->attributeName() == fakePropertyName) {
+ attr->setAttributeName(realPropertyName);
+ headerProperties << attr;
+ }
+ }
+ }
+ applyProperties(treeView->header(), headerProperties);
+ } else if (QTableView *tableView = qobject_cast<QTableView*>(itemView)) {
+ static QStringList headerPrefixes =
+ (QStringList() << QLatin1String("horizontalHeader")
+ << QLatin1String("verticalHeader"));
+
+ QList<DomProperty*> allAttributes = ui_widget->elementAttribute();
+ foreach (const QString &headerPrefix, headerPrefixes) {
+ QList<DomProperty*> headerProperties;
+ foreach (const QString &realPropertyName, realPropertyNames) {
+ const QString upperPropertyName = realPropertyName.at(0).toUpper()
+ + realPropertyName.mid(1);
+ const QString fakePropertyName = headerPrefix + upperPropertyName;
+ foreach (DomProperty *attr, allAttributes) {
+ if (attr->attributeName() == fakePropertyName) {
+ attr->setAttributeName(realPropertyName);
+ headerProperties << attr;
+ }
+ }
+ }
+ if (headerPrefix == QLatin1String("horizontalHeader"))
+ applyProperties(tableView->horizontalHeader(), headerProperties);
+ else
+ applyProperties(tableView->verticalHeader(), headerProperties);
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ if (0) {
+#ifndef QT_NO_LISTWIDGET
+ } else if (QListWidget *listWidget = qobject_cast<QListWidget*>(widget)) {
+ loadListWidgetExtraInfo(ui_widget, listWidget, parentWidget);
+#endif
+#ifndef QT_NO_TREEWIDGET
+ } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget*>(widget)) {
+ loadTreeWidgetExtraInfo(ui_widget, treeWidget, parentWidget);
+#endif
+#ifndef QT_NO_TABLEWIDGET
+ } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget*>(widget)) {
+ loadTableWidgetExtraInfo(ui_widget, tableWidget, parentWidget);
+#endif
+#ifndef QT_NO_COMBOBOX
+ } else if (QComboBox *comboBox = qobject_cast<QComboBox*>(widget)) {
+ if (!qobject_cast<QFontComboBox *>(widget))
+ loadComboBoxExtraInfo(ui_widget, comboBox, parentWidget);
+#endif
+#ifndef QT_NO_TABWIDGET
+ } else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(widget)) {
+ const DomProperty *currentIndex = propertyMap(ui_widget->elementProperty()).value(strings.currentIndexProperty);
+ if (currentIndex)
+ tabWidget->setCurrentIndex(currentIndex->elementNumber());
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+ } else if (QStackedWidget *stackedWidget = qobject_cast<QStackedWidget*>(widget)) {
+ const DomProperty *currentIndex = propertyMap(ui_widget->elementProperty()).value(strings.currentIndexProperty);
+ if (currentIndex)
+ stackedWidget->setCurrentIndex(currentIndex->elementNumber());
+#endif
+#ifndef QT_NO_TOOLBOX
+ } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(widget)) {
+ const DomProperty *currentIndex = propertyMap(ui_widget->elementProperty()).value(strings.currentIndexProperty);
+ if (currentIndex)
+ toolBox->setCurrentIndex(currentIndex->elementNumber());
+ const DomProperty *tabSpacing = propertyMap(ui_widget->elementProperty()).value(strings.tabSpacingProperty);
+ if (tabSpacing)
+ toolBox->layout()->setSpacing(tabSpacing->elementNumber());
+#endif
+ } else if (QAbstractButton *ab = qobject_cast<QAbstractButton *>(widget)) {
+ loadButtonExtraInfo(ui_widget, ab, parentWidget);
+ }
+ if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(widget)) {
+ loadItemViewExtraInfo(ui_widget, itemView, parentWidget);
+ }
+}
+
+/*!
+ \internal
+*/
+QIcon QAbstractFormBuilder::nameToIcon(const QString &filePath, const QString &qrcPath)
+{
+ Q_UNUSED(filePath)
+ Q_UNUSED(qrcPath)
+ qWarning() << "QAbstractFormBuilder::nameToIcon() is obsoleted";
+ return QIcon();
+}
+
+/*!
+ \internal
+*/
+QString QAbstractFormBuilder::iconToFilePath(const QIcon &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QAbstractFormBuilder::iconToFilePath() is obsoleted";
+ return QString();
+}
+
+/*!
+ \internal
+*/
+QString QAbstractFormBuilder::iconToQrcPath(const QIcon &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QAbstractFormBuilder::iconToQrcPath() is obsoleted";
+ return QString();
+}
+
+/*!
+ \internal
+*/
+QPixmap QAbstractFormBuilder::nameToPixmap(const QString &filePath, const QString &qrcPath)
+{
+ Q_UNUSED(filePath)
+ Q_UNUSED(qrcPath)
+ qWarning() << "QAbstractFormBuilder::nameToPixmap() is obsoleted";
+ return QPixmap();
+}
+
+/*!
+ \internal
+*/
+QString QAbstractFormBuilder::pixmapToFilePath(const QPixmap &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QAbstractFormBuilder::pixmapToFilePath() is obsoleted";
+ return QString();
+}
+
+/*!
+ \internal
+*/
+QString QAbstractFormBuilder::pixmapToQrcPath(const QPixmap &pm) const
+{
+ Q_UNUSED(pm)
+ qWarning() << "QAbstractFormBuilder::pixmapToQrcPath() is obsoleted";
+ return QString();
+}
+
+/*!
+ Returns the current working directory of the form builder.
+
+ \sa setWorkingDirectory() */
+QDir QAbstractFormBuilder::workingDirectory() const
+{
+ return m_workingDirectory;
+}
+
+/*!
+ Sets the current working directory of the form builder to the
+ specified \a directory.
+
+ \sa workingDirectory()*/
+void QAbstractFormBuilder::setWorkingDirectory(const QDir &directory)
+{
+ m_workingDirectory = directory;
+}
+
+/*!
+ \internal
+*/
+DomAction *QAbstractFormBuilder::createDom(QAction *action)
+{
+ if (action->parentWidget() == action->menu() || action->isSeparator())
+ return 0;
+
+ DomAction *ui_action = new DomAction;
+ ui_action->setAttributeName(action->objectName());
+
+ const QList<DomProperty*> properties = computeProperties(action);
+ ui_action->setElementProperty(properties);
+
+ return ui_action;
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+
+DomButtonGroup *QAbstractFormBuilder::createDom(QButtonGroup *buttonGroup)
+{
+ if (buttonGroup->buttons().count() == 0) // Empty group left over on form?
+ return 0;
+ DomButtonGroup *domButtonGroup = new DomButtonGroup;
+ domButtonGroup->setAttributeName(buttonGroup->objectName());
+
+ QList<DomProperty*> properties = computeProperties(buttonGroup);
+ domButtonGroup->setElementProperty(properties);
+ return domButtonGroup;
+}
+
+/*!
+ \internal
+*/
+DomActionGroup *QAbstractFormBuilder::createDom(QActionGroup *actionGroup)
+{
+ DomActionGroup *ui_action_group = new DomActionGroup;
+ ui_action_group->setAttributeName(actionGroup->objectName());
+
+ QList<DomProperty*> properties = computeProperties(actionGroup);
+ ui_action_group->setElementProperty(properties);
+
+ QList<DomAction*> ui_actions;
+
+ foreach (QAction *action, actionGroup->actions()) {
+ if (DomAction *ui_action = createDom(action)) {
+ ui_actions.append(ui_action);
+ }
+ }
+
+ ui_action_group->setElementAction(ui_actions);
+
+ return ui_action_group;
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::addMenuAction(QAction *action)
+{
+ Q_UNUSED(action);
+}
+
+/*!
+ \internal
+*/
+void QAbstractFormBuilder::reset()
+{
+ m_laidout.clear();
+ m_actions.clear();
+ m_actionGroups.clear();
+ m_defaultMargin = INT_MIN;
+ m_defaultSpacing = INT_MIN;
+}
+
+/*!
+ \internal
+ Access meta enumeration for Qt::ToolBarArea
+*/
+
+QMetaEnum QAbstractFormBuilder::toolBarAreaMetaEnum()
+{
+ return metaEnum<QAbstractFormBuilderGadget>("toolBarArea");
+}
+
+namespace {
+ // set forward slashes in image path.
+ inline void fixImagePath(QString &p) {
+ p.replace(QLatin1Char('\\'), QLatin1Char('/'));
+ }
+}
+
+/*!
+ \internal
+ Return paths of an icon.
+*/
+
+QAbstractFormBuilder::IconPaths QAbstractFormBuilder::iconPaths(const QIcon &icon) const
+{
+ Q_UNUSED(icon);
+ qWarning() << "QAbstractFormBuilder::iconPaths() is obsoleted";
+ return IconPaths();
+}
+
+/*!
+ \internal
+ Return paths of a pixmap.
+*/
+
+QAbstractFormBuilder::IconPaths QAbstractFormBuilder::pixmapPaths(const QPixmap &pixmap) const
+{
+ Q_UNUSED(pixmap);
+ qWarning() << "QAbstractFormBuilder::pixmapPaths() is obsoleted";
+ return IconPaths();
+}
+
+/*!
+ \internal
+ Set up a DOM property with icon.
+*/
+
+void QAbstractFormBuilder::setIconProperty(DomProperty &p, const IconPaths &ip) const
+{
+ DomResourceIcon *dpi = new DomResourceIcon;
+
+ /* TODO
+ if (!ip.second.isEmpty())
+ pix->setAttributeResource(ip.second);
+*/
+ dpi->setText(ip.first);
+
+ p.setAttributeName(QFormBuilderStrings::instance().iconAttribute);
+ p.setElementIconSet(dpi);
+}
+
+/*!
+ \internal
+ Set up a DOM property with pixmap.
+*/
+
+void QAbstractFormBuilder::setPixmapProperty(DomProperty &p, const IconPaths &ip) const
+{
+ DomResourcePixmap *pix = new DomResourcePixmap;
+ if (!ip.second.isEmpty())
+ pix->setAttributeResource(ip.second);
+
+ pix->setText(ip.first);
+
+ p.setAttributeName(QFormBuilderStrings::instance().pixmapAttribute);
+ p.setElementPixmap(pix);
+}
+
+/*!
+ \internal
+ Convenience. Return DOM property for icon; 0 if icon.isNull().
+*/
+
+DomProperty* QAbstractFormBuilder::iconToDomProperty(const QIcon &icon) const
+{
+ Q_UNUSED(icon);
+ qWarning() << "QAbstractFormBuilder::iconToDomProperty() is obsoleted";
+ return 0;
+}
+
+/*!
+ \internal
+ \since 4.4
+*/
+
+DomProperty *QAbstractFormBuilder::saveResource(const QVariant &v) const
+{
+ if (v.isNull())
+ return 0;
+
+ DomProperty *p = resourceBuilder()->saveResource(workingDirectory(), v);
+ if (p)
+ p->setAttributeName(QFormBuilderStrings::instance().iconAttribute);
+ return p;
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+
+DomProperty *QAbstractFormBuilder::saveText(const QString &attributeName, const QVariant &v) const
+{
+ if (v.isNull())
+ return 0;
+
+ DomProperty *p = textBuilder()->saveText(v);
+ if (p)
+ p->setAttributeName(attributeName);
+ return p;
+}
+
+/*!
+ \internal
+ Return the appropriate DOM pixmap for an image dom property.
+ From 4.4 - unused
+*/
+
+const DomResourcePixmap *QAbstractFormBuilder::domPixmap(const DomProperty* p) {
+ switch (p->kind()) {
+ case DomProperty::IconSet:
+ qDebug() << "** WARNING QAbstractFormBuilder::domPixmap() called for icon set!";
+ break;
+ case DomProperty::Pixmap:
+ return p->elementPixmap();
+ default:
+ break;
+ }
+ return 0;
+}
+
+/*!
+ \internal
+ Create icon from DOM.
+ From 4.4 - unused
+*/
+
+QIcon QAbstractFormBuilder::domPropertyToIcon(const DomResourcePixmap *icon)
+{
+ Q_UNUSED(icon);
+ qWarning() << "QAbstractFormBuilder::domPropertyToIcon() is obsoleted";
+ return QIcon();
+}
+
+/*!
+ \internal
+ Create icon from DOM. Assert if !domPixmap
+ From 4.4 - unused
+*/
+
+QIcon QAbstractFormBuilder::domPropertyToIcon(const DomProperty* p)
+{
+ Q_UNUSED(p);
+ qWarning() << "QAbstractFormBuilder::domPropertyToIcon() is obsoleted";
+ return QIcon();
+}
+
+
+/*!
+ \internal
+ Create pixmap from DOM.
+ From 4.4 - unused
+*/
+
+QPixmap QAbstractFormBuilder::domPropertyToPixmap(const DomResourcePixmap* pixmap)
+{
+ Q_UNUSED(pixmap);
+ qWarning() << "QAbstractFormBuilder::domPropertyToPixmap() is obsoleted";
+ return QPixmap();
+}
+
+
+/*!
+ \internal
+ Create pixmap from DOM. Assert if !domPixmap
+ From 4.4 - unused
+*/
+
+QPixmap QAbstractFormBuilder::domPropertyToPixmap(const DomProperty* p)
+{
+ Q_UNUSED(p);
+ qWarning() << "QAbstractFormBuilder::domPropertyToPixmap() is obsoleted";
+ return QPixmap();
+}
+
+/*!
+ \fn void QAbstractFormBuilder::createConnections ( DomConnections *, QWidget * )
+ \internal
+*/
+
+/*!
+ \fn void QAbstractFormBuilder::createCustomWidgets ( DomCustomWidgets * )
+ \internal
+*/
+
+/*!
+ \fn void QAbstractFormBuilder::createResources ( DomResources * )
+ \internal
+*/
+
+/*!
+ \fn QFormScriptRunner *QAbstractFormBuilder::formScriptRunner() const
+ \internal
+ \since 4.3
+*/
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+QFormScriptRunner *QAbstractFormBuilder::formScriptRunner() const
+{
+ return &(QFormBuilderExtra::instance(this)->formScriptRunner());
+}
+#endif
+
+/*!
+ Sets whether the execution of scripts is enabled to \a enabled.
+ \since 4.3
+ \internal
+*/
+
+void QAbstractFormBuilder::setScriptingEnabled(bool enabled)
+{
+#ifdef QT_FORMBUILDER_NO_SCRIPT
+ if (enabled)
+ uiLibWarning(QCoreApplication::translate("QAbstractFormBuilder", "This version of the uitools library is linked without script support."));
+#else
+ QFormScriptRunner::Options options = formScriptRunner()->options();
+ if (enabled)
+ options &= ~QFormScriptRunner::DisableScripts;
+ else
+ options |= QFormScriptRunner::DisableScripts;
+ formScriptRunner()->setOptions(options);
+#endif
+}
+
+/*!
+ Returns whether the execution of scripts is enabled.
+ \sa setScriptingEnabled()
+ \since 4.3
+ \internal
+*/
+
+bool QAbstractFormBuilder::isScriptingEnabled() const
+{
+#ifdef QT_FORMBUILDER_NO_SCRIPT
+ return false;
+#else
+ return !(formScriptRunner()->options() & QFormScriptRunner::DisableScripts);
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/uilib/abstractformbuilder.h b/tools/designer/src/lib/uilib/abstractformbuilder.h
new file mode 100644
index 0000000000..94429f87d9
--- /dev/null
+++ b/tools/designer/src/lib/uilib/abstractformbuilder.h
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMBUILDER_H
+#define ABSTRACTFORMBUILDER_H
+
+#include <QtDesigner/uilib_global.h>
+
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QDir>
+
+#include <QtGui/QSizePolicy>
+#include <QtGui/QPalette>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+#if 0
+// pragma for syncqt, don't remove.
+
+#pragma qt_class(QAbstractFormBuilder)
+#endif
+
+class QAction;
+class QButtonGroup;
+class QActionGroup;
+class QComboBox;
+class QIODevice;
+class QIcon;
+class QLayout;
+class QLayoutItem;
+class QListWidget;
+class QObject;
+class QSpacerItem;
+class QTreeWidget;
+class QTableWidget;
+class QVariant;
+class QWidget;
+class QAbstractButton;
+class QAbstractItemView;
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class DomAction;
+class DomActionGroup;
+class DomButtonGroup;
+class DomButtonGroups;
+class DomActionRef;
+class DomBrush;
+class DomColorGroup;
+class DomConnections;
+class DomCustomWidgets;
+class DomLayout;
+class DomLayoutItem;
+class DomProperty;
+class DomResources;
+class DomSpacer;
+class DomString;
+class DomTabStops;
+class DomUI;
+class DomWidget;
+class DomResourcePixmap;
+
+class QResourceBuilder;
+class QTextBuilder;
+
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+class QFormScriptRunner;
+#endif
+
+class QDESIGNER_UILIB_EXPORT QAbstractFormBuilder
+{
+public:
+ QAbstractFormBuilder();
+ virtual ~QAbstractFormBuilder();
+
+ QDir workingDirectory() const;
+ void setWorkingDirectory(const QDir &directory);
+
+ virtual QWidget *load(QIODevice *dev, QWidget *parentWidget=0);
+ virtual void save(QIODevice *dev, QWidget *widget);
+
+ void setScriptingEnabled(bool enabled);
+ bool isScriptingEnabled() const;
+
+protected:
+//
+// load
+//
+ virtual void loadExtraInfo(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+
+ virtual QWidget *create(DomUI *ui, QWidget *parentWidget);
+ virtual QWidget *create(DomWidget *ui_widget, QWidget *parentWidget);
+ virtual QLayout *create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget);
+ virtual QLayoutItem *create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget);
+
+ virtual QAction *create(DomAction *ui_action, QObject *parent);
+ virtual QActionGroup *create(DomActionGroup *ui_action_group, QObject *parent);
+ virtual void addMenuAction(QAction *action);
+
+ virtual void applyProperties(QObject *o, const QList<DomProperty*> &properties);
+ bool applyPropertyInternally(QObject *o, const QString &propertyName, const QVariant &value);
+
+ virtual void applyTabStops(QWidget *widget, DomTabStops *tabStops);
+
+ virtual QWidget *createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name);
+ virtual QLayout *createLayout(const QString &layoutName, QObject *parent, const QString &name);
+ virtual QAction *createAction(QObject *parent, const QString &name);
+ virtual QActionGroup *createActionGroup(QObject *parent, const QString &name);
+
+ virtual void createCustomWidgets(DomCustomWidgets *) {}
+ virtual void createConnections(DomConnections *, QWidget *) {}
+ virtual void createResources(DomResources*) {}
+
+ virtual bool addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout);
+ virtual bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+
+//
+// save
+//
+ virtual void saveExtraInfo(QWidget *widget, DomWidget *ui_widget, DomWidget *ui_parentWidget);
+
+ virtual void saveDom(DomUI *ui, QWidget *widget);
+
+ virtual DomActionRef *createActionRefDom(QAction *action);
+
+ virtual DomWidget *createDom(QWidget *widget, DomWidget *ui_parentWidget, bool recursive = true);
+ virtual DomLayout *createDom(QLayout *layout, DomLayout *ui_layout, DomWidget *ui_parentWidget);
+ virtual DomLayoutItem *createDom(QLayoutItem *item, DomLayout *ui_parentLayout, DomWidget *ui_parentWidget);
+ virtual DomSpacer *createDom(QSpacerItem *spacer, DomLayout *ui_parentLayout, DomWidget *ui_parentWidget);
+
+ virtual DomAction *createDom(QAction *action);
+ virtual DomActionGroup *createDom(QActionGroup *actionGroup);
+ DomButtonGroup *createDom(QButtonGroup *buttonGroup);
+
+ virtual DomConnections *saveConnections();
+ virtual DomCustomWidgets *saveCustomWidgets();
+ virtual DomTabStops *saveTabStops();
+ virtual DomResources *saveResources();
+ DomButtonGroups *saveButtonGroups(const QWidget *mainContainer);
+ virtual QList<DomProperty*> computeProperties(QObject *obj);
+ virtual bool checkProperty(QObject *obj, const QString &prop) const;
+ virtual DomProperty *createProperty(QObject *object, const QString &propertyName, const QVariant &value);
+
+ virtual void layoutInfo(DomLayout *layout, QObject *parent, int *margin, int *spacing);
+
+ virtual QIcon nameToIcon(const QString &filePath, const QString &qrcPath);
+ virtual QString iconToFilePath(const QIcon &pm) const;
+ virtual QString iconToQrcPath(const QIcon &pm) const;
+ virtual QPixmap nameToPixmap(const QString &filePath, const QString &qrcPath);
+ virtual QString pixmapToFilePath(const QPixmap &pm) const;
+ virtual QString pixmapToQrcPath(const QPixmap &pm) const;
+
+ void loadListWidgetExtraInfo(DomWidget *ui_widget, QListWidget *listWidget, QWidget *parentWidget);
+ void loadTreeWidgetExtraInfo(DomWidget *ui_widget, QTreeWidget *treeWidget, QWidget *parentWidget);
+ void loadTableWidgetExtraInfo(DomWidget *ui_widget, QTableWidget *tableWidget, QWidget *parentWidget);
+ void loadComboBoxExtraInfo(DomWidget *ui_widget, QComboBox *comboBox, QWidget *parentWidget);
+ void loadButtonExtraInfo(const DomWidget *ui_widget, QAbstractButton *button, QWidget *parentWidget);
+ void loadItemViewExtraInfo(DomWidget *ui_widget, QAbstractItemView *itemView, QWidget *parentWidget);
+
+ void saveListWidgetExtraInfo(QListWidget *widget, DomWidget *ui_widget, DomWidget *ui_parentWidget);
+ void saveTreeWidgetExtraInfo(QTreeWidget *treeWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget);
+ void saveTableWidgetExtraInfo(QTableWidget *tablWidget, DomWidget *ui_widget, DomWidget *ui_parentWidget);
+ void saveComboBoxExtraInfo(QComboBox *widget, DomWidget *ui_widget, DomWidget *ui_parentWidget);
+ void saveButtonExtraInfo(const QAbstractButton *widget, DomWidget *ui_widget, DomWidget *ui_parentWidget);
+ void saveItemViewExtraInfo(const QAbstractItemView *itemView, DomWidget *ui_widget, DomWidget *ui_parentWidget);
+
+ void setResourceBuilder(QResourceBuilder *builder);
+ QResourceBuilder *resourceBuilder() const;
+ DomProperty *saveResource(const QVariant &v) const;
+
+ void setTextBuilder(QTextBuilder *builder);
+ QTextBuilder *textBuilder() const;
+ DomProperty *saveText(const QString &attributeName, const QVariant &v) const;
+//
+// utils
+//
+
+ QVariant toVariant(const QMetaObject *meta, DomProperty *property);
+ static QString toString(const DomString *str);
+
+ typedef QHash<QString, DomProperty*> DomPropertyHash;
+ static DomPropertyHash propertyMap(const QList<DomProperty*> &properties);
+
+ void setupColorGroup(QPalette &palette, QPalette::ColorGroup colorGroup, DomColorGroup *group);
+ DomColorGroup *saveColorGroup(const QPalette &palette);
+ QBrush setupBrush(DomBrush *brush);
+ DomBrush *saveBrush(const QBrush &brush);
+
+ void reset();
+ void initialize(const DomUI *ui);
+
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ QFormScriptRunner *formScriptRunner() const;
+#endif
+//
+// utils
+//
+
+ static QMetaEnum toolBarAreaMetaEnum();
+
+//
+// Icon/pixmap stuff
+//
+ // A Pair of icon path/qrc path.
+ typedef QPair<QString, QString> IconPaths;
+
+ IconPaths iconPaths(const QIcon &) const;
+ IconPaths pixmapPaths(const QPixmap &) const;
+ void setIconProperty(DomProperty &, const IconPaths &) const;
+ void setPixmapProperty(DomProperty &, const IconPaths &) const;
+ DomProperty* iconToDomProperty(const QIcon &) const;
+
+ static const DomResourcePixmap *domPixmap(const DomProperty* p);
+ QIcon domPropertyToIcon(const DomResourcePixmap *);
+ QIcon domPropertyToIcon(const DomProperty* p);
+ QPixmap domPropertyToPixmap(const DomResourcePixmap* p);
+ QPixmap domPropertyToPixmap(const DomProperty* p);
+
+ QHash<QObject*, bool> m_laidout;
+ QHash<QString, QAction*> m_actions;
+ QHash<QString, QActionGroup*> m_actionGroups;
+ int m_defaultMargin;
+ int m_defaultSpacing;
+ QDir m_workingDirectory;
+
+private:
+//
+// utils
+//
+ static Qt::ToolBarArea toolbarAreaFromDOMAttributes(const DomPropertyHash &attributeMap);
+
+ QAbstractFormBuilder(const QAbstractFormBuilder &other);
+ void operator = (const QAbstractFormBuilder &other);
+
+ friend QDESIGNER_UILIB_EXPORT DomProperty *variantToDomProperty(QAbstractFormBuilder *abstractFormBuilder, const QMetaObject *meta, const QString &propertyName, const QVariant &value);
+ friend QDESIGNER_UILIB_EXPORT QVariant domPropertyToVariant(QAbstractFormBuilder *abstractFormBuilder,const QMetaObject *meta, const DomProperty *property);
+};
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // ABSTRACTFORMBUILDER_H
diff --git a/tools/designer/src/lib/uilib/container.h b/tools/designer/src/lib/uilib/container.h
new file mode 100644
index 0000000000..e107ad70b6
--- /dev/null
+++ b/tools/designer/src/lib/uilib/container.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CONTAINER_H
+#define CONTAINER_H
+
+#include <QtDesigner/extension.h>
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+
+class QDesignerContainerExtension
+{
+public:
+ virtual ~QDesignerContainerExtension() {}
+
+ virtual int count() const = 0;
+ virtual QWidget *widget(int index) const = 0;
+
+ virtual int currentIndex() const = 0;
+ virtual void setCurrentIndex(int index) = 0;
+
+ virtual void addWidget(QWidget *widget) = 0;
+ virtual void insertWidget(int index, QWidget *widget) = 0;
+ virtual void remove(int index) = 0;
+};
+Q_DECLARE_EXTENSION_INTERFACE(QDesignerContainerExtension, "com.trolltech.Qt.Designer.Container")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // CONTAINER_H
diff --git a/tools/designer/src/lib/uilib/customwidget.h b/tools/designer/src/lib/uilib/customwidget.h
new file mode 100644
index 0000000000..0da4c053ff
--- /dev/null
+++ b/tools/designer/src/lib/uilib/customwidget.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUSTOMWIDGET_H
+#define CUSTOMWIDGET_H
+
+#include <QtDesigner/extension.h>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtGui/QIcon>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+class QDesignerFormEditorInterface;
+
+class QDesignerCustomWidgetInterface
+{
+public:
+ virtual ~QDesignerCustomWidgetInterface() {}
+
+ virtual QString name() const = 0;
+ virtual QString group() const = 0;
+ virtual QString toolTip() const = 0;
+ virtual QString whatsThis() const = 0;
+ virtual QString includeFile() const = 0;
+ virtual QIcon icon() const = 0;
+
+ virtual bool isContainer() const = 0;
+
+ virtual QWidget *createWidget(QWidget *parent) = 0;
+
+ virtual bool isInitialized() const { return false; }
+ virtual void initialize(QDesignerFormEditorInterface *core) { Q_UNUSED(core); }
+
+ virtual QString domXml() const
+ {
+ return QString::fromUtf8("<widget class=\"%1\" name=\"%2\"/>")
+ .arg(name()).arg(name().toLower());
+ }
+
+ virtual QString codeTemplate() const { return QString(); }
+};
+Q_DECLARE_INTERFACE(QDesignerCustomWidgetInterface, "com.trolltech.Qt.Designer.CustomWidget")
+
+
+class QDesignerCustomWidgetCollectionInterface
+{
+public:
+ virtual ~QDesignerCustomWidgetCollectionInterface() {}
+
+ virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const = 0;
+};
+Q_DECLARE_INTERFACE(QDesignerCustomWidgetCollectionInterface,
+ "com.trolltech.Qt.Designer.CustomWidgetCollection")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // CUSTOMWIDGET_H
diff --git a/tools/designer/src/lib/uilib/formbuilder.cpp b/tools/designer/src/lib/uilib/formbuilder.cpp
new file mode 100644
index 0000000000..414eb1453d
--- /dev/null
+++ b/tools/designer/src/lib/uilib/formbuilder.cpp
@@ -0,0 +1,562 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "customwidget.h"
+#include "formbuilder.h"
+#include "formbuilderextra_p.h"
+#include "ui4_p.h"
+
+#include <QtGui/QtGui>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal {
+#endif
+
+/*!
+ \class QFormBuilder
+
+ \brief The QFormBuilder class is used to dynamically construct
+ user interfaces from .ui files at run-time.
+
+ \inmodule QtDesigner
+
+ The QFormBuilder class provides a mechanism for dynamically
+ creating user interfaces at run-time, based on \c{.ui} files
+ created with \QD. For example:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_uilib_formbuilder.cpp 0
+
+ By including the user interface in the example's resources (\c
+ myForm.qrc), we ensure that it will be present when the example is
+ run:
+
+ \snippet doc/src/snippets/code/tools_designer_src_lib_uilib_formbuilder.cpp 1
+
+ QFormBuilder extends the QAbstractFormBuilder base class with a
+ number of functions that are used to support custom widget
+ plugins:
+
+ \list
+ \o pluginPaths() returns the list of paths that the form builder
+ searches when loading custom widget plugins.
+ \o addPluginPath() allows additional paths to be registered with
+ the form builder.
+ \o setPluginPath() is used to replace the existing list of paths
+ with a list obtained from some other source.
+ \o clearPluginPaths() removes all paths registered with the form
+ builder.
+ \o customWidgets() returns a list of interfaces to plugins that
+ can be used to create new instances of registered custom widgets.
+ \endlist
+
+ The QFormBuilder class is typically used by custom components and
+ applications that embed \QD. Standalone applications that need to
+ dynamically generate user interfaces at run-time use the
+ QUiLoader class, found in the QtUiTools module.
+
+ \sa QAbstractFormBuilder, {QtUiTools Module}
+*/
+
+/*!
+ \fn QFormBuilder::QFormBuilder()
+
+ Constructs a new form builder.
+*/
+
+QFormBuilder::QFormBuilder() : QAbstractFormBuilder()
+{
+}
+
+/*!
+ Destroys the form builder.
+*/
+QFormBuilder::~QFormBuilder()
+{
+}
+
+/*!
+ \internal
+*/
+QWidget *QFormBuilder::create(DomWidget *ui_widget, QWidget *parentWidget)
+{
+ QFormBuilderExtra::instance(this)->setProcessingLayoutWidget(false);
+ if (ui_widget->attributeClass() == QFormBuilderStrings::instance().qWidgetClass && !ui_widget->hasAttributeNative()
+ && parentWidget
+#ifndef QT_NO_MAINWINDOW
+ && !qobject_cast<QMainWindow *>(parentWidget)
+#endif
+#ifndef QT_NO_TOOLBOX
+ && !qobject_cast<QToolBox *>(parentWidget)
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+ && !qobject_cast<QStackedWidget *>(parentWidget)
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+ && !qobject_cast<QTabWidget *>(parentWidget)
+#endif
+#ifndef QT_NO_SCROLLAREA
+ && !qobject_cast<QScrollArea *>(parentWidget)
+#endif
+#ifndef QT_NO_MDIAREA
+ && !qobject_cast<QMdiArea *>(parentWidget)
+#endif
+#ifndef QT_NO_DOCKWIDGET
+ && !qobject_cast<QDockWidget *>(parentWidget)
+#endif
+ )
+ QFormBuilderExtra::instance(this)->setProcessingLayoutWidget(true);
+ return QAbstractFormBuilder::create(ui_widget, parentWidget);
+}
+
+
+/*!
+ \internal
+*/
+QWidget *QFormBuilder::createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name)
+{
+ if (widgetName.isEmpty()) {
+ //: Empty class name passed to widget factory method
+ qWarning() << QCoreApplication::translate("QFormBuilder", "An empty class name was passed on to %1 (object name: '%2').").arg(QString::fromUtf8(Q_FUNC_INFO), name);
+ return 0;
+ }
+
+ QWidget *w = 0;
+
+#ifndef QT_NO_TABWIDGET
+ if (qobject_cast<QTabWidget*>(parentWidget))
+ parentWidget = 0;
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+ if (qobject_cast<QStackedWidget*>(parentWidget))
+ parentWidget = 0;
+#endif
+#ifndef QT_NO_TOOLBOX
+ if (qobject_cast<QToolBox*>(parentWidget))
+ parentWidget = 0;
+#endif
+
+ // ### special-casing for Line (QFrame) -- fix for 4.2
+ do {
+ if (widgetName == QFormBuilderStrings::instance().lineClass) {
+ w = new QFrame(parentWidget);
+ static_cast<QFrame*>(w)->setFrameStyle(QFrame::HLine | QFrame::Sunken);
+ break;
+ }
+ const QByteArray widgetNameBA = widgetName.toUtf8();
+ const char *widgetNameC = widgetNameBA.constData();
+ if (w) { // symmetry for macro
+ }
+
+#define DECLARE_LAYOUT(L, C)
+#define DECLARE_COMPAT_WIDGET(W, C)
+#define DECLARE_WIDGET(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(parentWidget); }
+#define DECLARE_WIDGET_1(W, C) else if (!qstrcmp(widgetNameC, #W)) { Q_ASSERT(w == 0); w = new W(0, parentWidget); }
+
+#include "widgets.table"
+
+#undef DECLARE_COMPAT_WIDGET
+#undef DECLARE_LAYOUT
+#undef DECLARE_WIDGET
+#undef DECLARE_WIDGET_1
+
+ if (w)
+ break;
+
+ // try with a registered custom widget
+ QDesignerCustomWidgetInterface *factory = m_customWidgets.value(widgetName);
+ if (factory != 0)
+ w = factory->createWidget(parentWidget);
+ } while(false);
+
+ QFormBuilderExtra *fb = QFormBuilderExtra::instance(this);
+ if (w == 0) { // Attempt to instantiate base class of promoted/custom widgets
+ const QString baseClassName = fb->customWidgetBaseClass(widgetName);
+ if (!baseClassName.isEmpty()) {
+ qWarning() << QCoreApplication::translate("QFormBuilder", "QFormBuilder was unable to create a custom widget of the class '%1'; defaulting to base class '%2'.").arg(widgetName, baseClassName);
+ return createWidget(baseClassName, parentWidget, name);
+ }
+ }
+
+ if (w == 0) { // nothing to do
+ qWarning() << QCoreApplication::translate("QFormBuilder", "QFormBuilder was unable to create a widget of the class '%1'.").arg(widgetName);
+ return 0;
+ }
+
+ w->setObjectName(name);
+
+ if (qobject_cast<QDialog *>(w))
+ w->setParent(parentWidget);
+
+ if (!fb->rootWidget())
+ fb->setRootWidget(w);
+
+ return w;
+}
+
+/*!
+ \internal
+*/
+QLayout *QFormBuilder::createLayout(const QString &layoutName, QObject *parent, const QString &name)
+{
+ QLayout *l = 0;
+
+ QWidget *parentWidget = qobject_cast<QWidget*>(parent);
+ QLayout *parentLayout = qobject_cast<QLayout*>(parent);
+
+ Q_ASSERT(parentWidget || parentLayout);
+
+#define DECLARE_WIDGET(W, C)
+#define DECLARE_COMPAT_WIDGET(W, C)
+
+#define DECLARE_LAYOUT(L, C) \
+ if (layoutName == QLatin1String(#L)) { \
+ Q_ASSERT(l == 0); \
+ l = parentLayout \
+ ? new L() \
+ : new L(parentWidget); \
+ }
+
+#include "widgets.table"
+
+#undef DECLARE_LAYOUT
+#undef DECLARE_COMPAT_WIDGET
+#undef DECLARE_WIDGET
+
+ if (l) {
+ l->setObjectName(name);
+ if (parentLayout) {
+ QWidget *w = qobject_cast<QWidget *>(parentLayout->parent());
+ if (w && w->inherits("Q3GroupBox")) {
+ l->setContentsMargins(w->style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
+ w->style()->pixelMetric(QStyle::PM_LayoutTopMargin),
+ w->style()->pixelMetric(QStyle::PM_LayoutRightMargin),
+ w->style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
+ QGridLayout *grid = qobject_cast<QGridLayout *>(l);
+ if (grid) {
+ grid->setHorizontalSpacing(-1);
+ grid->setVerticalSpacing(-1);
+ } else {
+ l->setSpacing(-1);
+ }
+ l->setAlignment(Qt::AlignTop);
+ }
+ }
+ } else {
+ qWarning() << QCoreApplication::translate("QFormBuilder", "The layout type `%1' is not supported.").arg(layoutName);
+ }
+
+ return l;
+}
+
+/*!
+ \internal
+*/
+bool QFormBuilder::addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout)
+{
+ return QAbstractFormBuilder::addItem(ui_item, item, layout);
+}
+
+/*!
+ \internal
+*/
+bool QFormBuilder::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ return QAbstractFormBuilder::addItem(ui_widget, widget, parentWidget);
+}
+
+/*!
+ \internal
+*/
+QWidget *QFormBuilder::widgetByName(QWidget *topLevel, const QString &name)
+{
+ Q_ASSERT(topLevel);
+ if (topLevel->objectName() == name)
+ return topLevel;
+
+ return qFindChild<QWidget*>(topLevel, name);
+}
+
+static QObject *objectByName(QWidget *topLevel, const QString &name)
+{
+ Q_ASSERT(topLevel);
+ if (topLevel->objectName() == name)
+ return topLevel;
+
+ return qFindChild<QObject*>(topLevel, name);
+}
+
+/*!
+ \internal
+*/
+void QFormBuilder::createConnections(DomConnections *ui_connections, QWidget *widget)
+{
+ typedef QList<DomConnection*> DomConnectionList;
+ Q_ASSERT(widget != 0);
+
+ if (ui_connections == 0)
+ return;
+
+ const DomConnectionList connections = ui_connections->elementConnection();
+ if (!connections.empty()) {
+ const DomConnectionList::const_iterator cend = connections.constEnd();
+ for (DomConnectionList::const_iterator it = connections.constBegin(); it != cend; ++it) {
+
+ QObject *sender = objectByName(widget, (*it)->elementSender());
+ QObject *receiver = objectByName(widget, (*it)->elementReceiver());
+ if (!sender || !receiver)
+ continue;
+
+ QByteArray sig = (*it)->elementSignal().toUtf8();
+ sig.prepend("2");
+ QByteArray sl = (*it)->elementSlot().toUtf8();
+ sl.prepend("1");
+ QObject::connect(sender, sig, receiver, sl);
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+QWidget *QFormBuilder::create(DomUI *ui, QWidget *parentWidget)
+{
+ return QAbstractFormBuilder::create(ui, parentWidget);
+}
+
+/*!
+ \internal
+*/
+QLayout *QFormBuilder::create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget)
+{
+ // Is this a temporary layout widget used to represent QLayout hierarchies in Designer?
+ // Set its margins to 0.
+ bool layoutWidget = QFormBuilderExtra::instance(this)->processingLayoutWidget();
+ QLayout *l = QAbstractFormBuilder::create(ui_layout, layout, parentWidget);
+ if (layoutWidget) {
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ int left, top, right, bottom;
+ left = top = right = bottom = 0;
+ const DomPropertyHash properties = propertyMap(ui_layout->elementProperty());
+
+ if (DomProperty *prop = properties.value(strings.leftMarginProperty))
+ left = prop->elementNumber();
+
+ if (DomProperty *prop = properties.value(strings.topMarginProperty))
+ top = prop->elementNumber();
+
+ if (DomProperty *prop = properties.value(strings.rightMarginProperty))
+ right = prop->elementNumber();
+
+ if (DomProperty *prop = properties.value(strings.bottomMarginProperty))
+ bottom = prop->elementNumber();
+
+ l->setContentsMargins(left, top, right, bottom);
+ QFormBuilderExtra::instance(this)->setProcessingLayoutWidget(false);
+ }
+ return l;
+}
+
+/*!
+ \internal
+*/
+QLayoutItem *QFormBuilder::create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget)
+{
+ return QAbstractFormBuilder::create(ui_layoutItem, layout, parentWidget);
+}
+
+/*!
+ \internal
+*/
+QAction *QFormBuilder::create(DomAction *ui_action, QObject *parent)
+{
+ return QAbstractFormBuilder::create(ui_action, parent);
+}
+
+/*!
+ \internal
+*/
+QActionGroup *QFormBuilder::create(DomActionGroup *ui_action_group, QObject *parent)
+{
+ return QAbstractFormBuilder::create(ui_action_group, parent);
+}
+
+/*!
+ Returns the list of paths the form builder searches for plugins.
+
+ \sa addPluginPath()
+*/
+QStringList QFormBuilder::pluginPaths() const
+{
+ return m_pluginPaths;
+}
+
+/*!
+ Clears the list of paths that the form builder uses to search for
+ custom widget plugins.
+
+ \sa pluginPaths()
+*/
+void QFormBuilder::clearPluginPaths()
+{
+ m_pluginPaths.clear();
+ updateCustomWidgets();
+}
+
+/*!
+ Adds a new plugin path specified by \a pluginPath to the list of
+ paths that will be searched by the form builder when loading a
+ custom widget plugin.
+
+ \sa setPluginPath(), clearPluginPaths()
+*/
+void QFormBuilder::addPluginPath(const QString &pluginPath)
+{
+ m_pluginPaths.append(pluginPath);
+ updateCustomWidgets();
+}
+
+/*!
+ Sets the list of plugin paths to the list specified by \a pluginPaths.
+
+ \sa addPluginPath()
+*/
+void QFormBuilder::setPluginPath(const QStringList &pluginPaths)
+{
+ m_pluginPaths = pluginPaths;
+ updateCustomWidgets();
+}
+
+static void insertPlugins(QObject *o, QMap<QString, QDesignerCustomWidgetInterface*> *customWidgets)
+{
+ // step 1) try with a normal plugin
+ if (QDesignerCustomWidgetInterface *iface = qobject_cast<QDesignerCustomWidgetInterface *>(o)) {
+ customWidgets->insert(iface->name(), iface);
+ return;
+ }
+ // step 2) try with a collection of plugins
+ if (QDesignerCustomWidgetCollectionInterface *c = qobject_cast<QDesignerCustomWidgetCollectionInterface *>(o)) {
+ foreach (QDesignerCustomWidgetInterface *iface, c->customWidgets())
+ customWidgets->insert(iface->name(), iface);
+ }
+}
+
+/*!
+ \internal
+*/
+void QFormBuilder::updateCustomWidgets()
+{
+ m_customWidgets.clear();
+
+ foreach (QString path, m_pluginPaths) {
+ const QDir dir(path);
+ const QStringList candidates = dir.entryList(QDir::Files);
+
+ foreach (const QString &plugin, candidates) {
+ if (!QLibrary::isLibrary(plugin))
+ continue;
+
+ QString loaderPath = path;
+ loaderPath += QLatin1Char('/');
+ loaderPath += plugin;
+
+ QPluginLoader loader(loaderPath);
+ if (loader.load())
+ insertPlugins(loader.instance(), &m_customWidgets);
+ }
+ }
+ // Check statically linked plugins
+ const QObjectList staticPlugins = QPluginLoader::staticInstances();
+ if (!staticPlugins.empty())
+ foreach (QObject *o, staticPlugins)
+ insertPlugins(o, &m_customWidgets);
+}
+
+/*!
+ \fn QList<QDesignerCustomWidgetInterface*> QFormBuilder::customWidgets() const
+
+ Returns a list of the available plugins.
+*/
+QList<QDesignerCustomWidgetInterface*> QFormBuilder::customWidgets() const
+{
+ return m_customWidgets.values();
+}
+
+/*!
+ \internal
+*/
+void QFormBuilder::applyProperties(QObject *o, const QList<DomProperty*> &properties)
+{
+ typedef QList<DomProperty*> DomPropertyList;
+
+ if (properties.empty())
+ return;
+
+ QFormBuilderExtra *fb = QFormBuilderExtra::instance(this);
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+
+ const DomPropertyList::const_iterator cend = properties.constEnd();
+ for (DomPropertyList::const_iterator it = properties.constBegin(); it != cend; ++it) {
+ const QVariant v = toVariant(o->metaObject(), *it);
+ if (v.isNull())
+ continue;
+
+ const QString attributeName = (*it)->attributeName();
+ if (o == fb->rootWidget() && attributeName == strings.geometryProperty) {
+ // apply only the size for the rootWidget
+ fb->rootWidget()->resize(qvariant_cast<QRect>(v).size());
+ } else if (fb->applyPropertyInternally(o, attributeName, v)) {
+ } else if (!qstrcmp("QFrame", o->metaObject()->className ()) && attributeName == strings.orientationProperty) {
+ // ### special-casing for Line (QFrame) -- try to fix me
+ o->setProperty("frameShape", v); // v is of QFrame::Shape enum
+ } else {
+ o->setProperty(attributeName.toUtf8(), v);
+ }
+ }
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+} // namespace QFormInternal
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/uilib/formbuilder.h b/tools/designer/src/lib/uilib/formbuilder.h
new file mode 100644
index 0000000000..a9fe90052d
--- /dev/null
+++ b/tools/designer/src/lib/uilib/formbuilder.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMBUILDER_H
+#define FORMBUILDER_H
+
+#include <QtDesigner/uilib_global.h>
+#include <QtDesigner/QAbstractFormBuilder>
+
+#include <QtCore/QStringList>
+#include <QtCore/QMap>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+#if 0
+// pragma for syncqt, don't remove.
+
+#pragma qt_class(QFormBuilder)
+#endif
+
+class QDesignerCustomWidgetInterface;
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class QDESIGNER_UILIB_EXPORT QFormBuilder: public QAbstractFormBuilder
+{
+public:
+ QFormBuilder();
+ virtual ~QFormBuilder();
+
+ QStringList pluginPaths() const;
+
+ void clearPluginPaths();
+ void addPluginPath(const QString &pluginPath);
+ void setPluginPath(const QStringList &pluginPaths);
+
+ QList<QDesignerCustomWidgetInterface*> customWidgets() const;
+
+protected:
+ virtual QWidget *create(DomUI *ui, QWidget *parentWidget);
+ virtual QWidget *create(DomWidget *ui_widget, QWidget *parentWidget);
+ virtual QLayout *create(DomLayout *ui_layout, QLayout *layout, QWidget *parentWidget);
+ virtual QLayoutItem *create(DomLayoutItem *ui_layoutItem, QLayout *layout, QWidget *parentWidget);
+ virtual QAction *create(DomAction *ui_action, QObject *parent);
+ virtual QActionGroup *create(DomActionGroup *ui_action_group, QObject *parent);
+
+ virtual QWidget *createWidget(const QString &widgetName, QWidget *parentWidget, const QString &name);
+ virtual QLayout *createLayout(const QString &layoutName, QObject *parent, const QString &name);
+
+ virtual void createConnections(DomConnections *connections, QWidget *widget);
+
+ virtual bool addItem(DomLayoutItem *ui_item, QLayoutItem *item, QLayout *layout);
+ virtual bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+
+ virtual void updateCustomWidgets();
+ virtual void applyProperties(QObject *o, const QList<DomProperty*> &properties);
+
+ static QWidget *widgetByName(QWidget *topLevel, const QString &name);
+
+private:
+ QStringList m_pluginPaths;
+ QMap<QString, QDesignerCustomWidgetInterface*> m_customWidgets;
+};
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // FORMBUILDER_H
diff --git a/tools/designer/src/lib/uilib/formbuilderextra.cpp b/tools/designer/src/lib/uilib/formbuilderextra.cpp
new file mode 100644
index 0000000000..cb829673b8
--- /dev/null
+++ b/tools/designer/src/lib/uilib/formbuilderextra.cpp
@@ -0,0 +1,531 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formbuilderextra_p.h"
+#include "abstractformbuilder.h"
+#include "resourcebuilder_p.h"
+#include "textbuilder_p.h"
+#include "ui4_p.h"
+
+#include <QtGui/QLabel>
+#include <QtGui/QBoxLayout>
+#include <QtGui/QGridLayout>
+
+#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+#include <QtCore/QTextStream>
+#include <QtCore/QStringList>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal {
+#endif
+
+void uiLibWarning(const QString &message) {
+ qWarning("Designer: %s", qPrintable(message));
+}
+
+QFormBuilderExtra::QFormBuilderExtra() :
+ m_layoutWidget(false),
+ m_resourceBuilder(0),
+ m_textBuilder(0)
+{
+}
+
+QFormBuilderExtra::~QFormBuilderExtra()
+{
+ clearResourceBuilder();
+ clearTextBuilder();
+}
+
+void QFormBuilderExtra::clear()
+{
+ m_buddies.clear();
+ m_rootWidget = 0;
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ m_FormScriptRunner.clearErrors();
+ m_customWidgetScriptHash.clear();
+#endif
+ m_buttonGroups.clear();
+}
+
+
+bool QFormBuilderExtra::applyPropertyInternally(QObject *o, const QString &propertyName, const QVariant &value)
+{
+ // Store buddies and apply them later on as the widgets might not exist yet.
+ QLabel *label = qobject_cast<QLabel*>(o);
+ if (!label || propertyName != QFormBuilderStrings::instance().buddyProperty)
+ return false;
+
+ m_buddies.insert(label, value.toString());
+ return true;
+}
+
+void QFormBuilderExtra::applyInternalProperties() const
+{
+ if (m_buddies.empty())
+ return;
+
+ const BuddyHash::const_iterator cend = m_buddies.constEnd();
+ for (BuddyHash::const_iterator it = m_buddies.constBegin(); it != cend; ++it )
+ applyBuddy(it.value(), BuddyApplyAll, it.key());
+}
+
+bool QFormBuilderExtra::applyBuddy(const QString &buddyName, BuddyMode applyMode, QLabel *label)
+{
+ if (buddyName.isEmpty()) {
+ label->setBuddy(0);
+ return false;
+ }
+
+ const QWidgetList widgets = qFindChildren<QWidget*>(label->topLevelWidget(), buddyName);
+ if (widgets.empty()) {
+ label->setBuddy(0);
+ return false;
+ }
+
+ const QWidgetList::const_iterator cend = widgets.constEnd();
+ for ( QWidgetList::const_iterator it = widgets.constBegin(); it != cend; ++it) {
+ if (applyMode == BuddyApplyAll || !(*it)->isHidden()) {
+ label->setBuddy(*it);
+ return true;
+ }
+ }
+
+ label->setBuddy(0);
+ return false;
+}
+
+const QPointer<QWidget> &QFormBuilderExtra::rootWidget() const
+{
+ return m_rootWidget;
+}
+
+void QFormBuilderExtra::setRootWidget(const QPointer<QWidget> &w)
+{
+ m_rootWidget = w;
+}
+
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+QFormScriptRunner &QFormBuilderExtra::formScriptRunner()
+{
+ return m_FormScriptRunner;
+}
+
+void QFormBuilderExtra::storeCustomWidgetScript(const QString &className, const QString &script)
+{
+ m_customWidgetScriptHash.insert(className, script);
+}
+
+QString QFormBuilderExtra::customWidgetScript(const QString &className) const
+{
+ const CustomWidgetScriptHash::const_iterator it = m_customWidgetScriptHash.constFind(className);
+ if ( it == m_customWidgetScriptHash.constEnd())
+ return QString();
+ return it.value();
+}
+
+#endif
+
+void QFormBuilderExtra::storeCustomWidgetBaseClass(const QString &className, const QString &baseClassName)
+{
+ m_customWidgetBaseClassHash.insert(className, baseClassName);
+}
+
+QString QFormBuilderExtra::customWidgetBaseClass(const QString &className) const
+{
+ const QHash<QString, QString>::const_iterator it = m_customWidgetBaseClassHash.constFind(className);
+ if (it == m_customWidgetBaseClassHash.constEnd())
+ return QString();
+ return it.value();
+}
+
+void QFormBuilderExtra::storeCustomWidgetAddPageMethod(const QString &className, const QString &ct)
+{
+ m_customWidgetAddPageMethodHash.insert(className, ct);
+}
+
+QString QFormBuilderExtra::customWidgetAddPageMethod(const QString &className) const
+{
+ const QHash<QString, QString>::const_iterator it = m_customWidgetAddPageMethodHash.constFind(className);
+ if (it == m_customWidgetAddPageMethodHash.constEnd())
+ return QString();
+ return it.value();
+}
+
+namespace {
+ typedef QHash<const QAbstractFormBuilder *, QFormBuilderExtra *> FormBuilderPrivateHash;
+}
+
+Q_GLOBAL_STATIC(FormBuilderPrivateHash, g_FormBuilderPrivateHash)
+
+QFormBuilderExtra *QFormBuilderExtra::instance(const QAbstractFormBuilder *afb)
+{
+ FormBuilderPrivateHash &fbHash = *g_FormBuilderPrivateHash();
+
+ FormBuilderPrivateHash::iterator it = fbHash.find(afb);
+ if (it == fbHash.end())
+ it = fbHash.insert(afb, new QFormBuilderExtra);
+ return it.value();
+}
+
+void QFormBuilderExtra::removeInstance(const QAbstractFormBuilder *afb)
+{
+ FormBuilderPrivateHash &fbHash = *g_FormBuilderPrivateHash();
+
+ FormBuilderPrivateHash::iterator it = fbHash.find(afb);
+ if (it != fbHash.end()) {
+ delete it.value();
+ fbHash.erase(it);
+ }
+}
+
+void QFormBuilderExtra::setProcessingLayoutWidget(bool processing)
+{
+ m_layoutWidget = processing;
+}
+
+ bool QFormBuilderExtra::processingLayoutWidget() const
+{
+ return m_layoutWidget;
+}
+void QFormBuilderExtra::setResourceBuilder(QResourceBuilder *builder)
+{
+ if (m_resourceBuilder == builder)
+ return;
+ clearResourceBuilder();
+ m_resourceBuilder = builder;
+}
+
+QResourceBuilder *QFormBuilderExtra::resourceBuilder() const
+{
+ return m_resourceBuilder;
+}
+
+void QFormBuilderExtra::clearResourceBuilder()
+{
+ if (m_resourceBuilder) {
+ delete m_resourceBuilder;
+ m_resourceBuilder = 0;
+ }
+}
+
+void QFormBuilderExtra::setTextBuilder(QTextBuilder *builder)
+{
+ if (m_textBuilder == builder)
+ return;
+ clearTextBuilder();
+ m_textBuilder = builder;
+}
+
+QTextBuilder *QFormBuilderExtra::textBuilder() const
+{
+ return m_textBuilder;
+}
+
+void QFormBuilderExtra::clearTextBuilder()
+{
+ if (m_textBuilder) {
+ delete m_textBuilder;
+ m_textBuilder = 0;
+ }
+}
+
+void QFormBuilderExtra::registerButtonGroups(const DomButtonGroups *domGroups)
+{
+ typedef QList<DomButtonGroup*> DomButtonGroupList;
+ const DomButtonGroupList domGroupList = domGroups->elementButtonGroup();
+ const DomButtonGroupList::const_iterator cend = domGroupList.constEnd();
+ for (DomButtonGroupList::const_iterator it = domGroupList.constBegin(); it != cend; ++it) {
+ DomButtonGroup *domGroup = *it;
+ m_buttonGroups.insert(domGroup->attributeName(), ButtonGroupEntry(domGroup, 0));
+ }
+}
+
+// Utilities for parsing per-cell integer properties that have setters and
+// getters of the form 'setX(int idx, int value)' and 'x(int index)'
+// (converting them to comma-separated string lists and back).
+// Used for layout stretch and grid per-row/column properties.
+
+// Format a list of cell-properties of one dimension as a ','-separated list
+template <class Layout>
+inline QString perCellPropertyToString(const Layout *l, int count, int (Layout::*getter)(int) const)
+{
+ if (count == 0)
+ return QString();
+ QString rc;
+ {
+ QTextStream str(&rc);
+ for (int i = 0; i < count; i++) {
+ if (i)
+ str << QLatin1Char(',');
+ str << (l->*getter)(i);
+ }
+ }
+ return rc;
+}
+
+// Clear the property, set all cells to 0
+
+template <class Layout>
+inline void clearPerCellValue(Layout *l, int count, void (Layout::*setter)(int,int), int value = 0)
+{
+ for (int i = 0; i < count; i++)
+ (l->*setter)(i, value);
+}
+
+// Parse and set the property from a comma-separated list
+
+template <class Layout>
+inline bool parsePerCellProperty(Layout *l, int count, void (Layout::*setter)(int,int), const QString &s, int defaultValue = 0)
+{
+ if (s.isEmpty()) {
+ clearPerCellValue(l, count, setter, defaultValue);
+ return true;
+ }
+ const QStringList list = s.split(QLatin1Char(','));
+ if (list.empty()) {
+ clearPerCellValue(l, count, setter, defaultValue);
+ return true;
+ }
+ // Apply all values contained in list
+ const int ac = qMin(count, list.size());
+ bool ok;
+ int i = 0;
+ for ( ; i < ac; i++) {
+ const int value = list.at(i).toInt(&ok);
+ if (!ok || value < 0)
+ return false;
+ (l->*setter)(i, value);
+ }
+ // Clear rest
+ for ( ; i < count; i++)
+ (l->*setter)(i, defaultValue);
+ return true;
+}
+
+// Read and write stretch
+static QString msgInvalidStretch(const QString &objectName, const QString &stretch)
+{
+ //: Parsing layout stretch values
+ return QCoreApplication::translate("FormBuilder", "Invalid stretch value for '%1': '%2'").arg(objectName, stretch);
+}
+
+QString QFormBuilderExtra::boxLayoutStretch(const QBoxLayout *box)
+{
+ return perCellPropertyToString(box, box->count(), &QBoxLayout::stretch);
+}
+
+bool QFormBuilderExtra::setBoxLayoutStretch(const QString &s, QBoxLayout *box)
+{
+ const bool rc = parsePerCellProperty(box, box->count(), &QBoxLayout::setStretch, s);
+ if (!rc)
+ uiLibWarning(msgInvalidStretch(box->objectName(), s));
+ return rc;
+}
+
+void QFormBuilderExtra::clearBoxLayoutStretch(QBoxLayout *box)
+{
+ clearPerCellValue(box, box->count(), &QBoxLayout::setStretch);
+}
+
+QString QFormBuilderExtra::gridLayoutRowStretch(const QGridLayout *grid)
+{
+ return perCellPropertyToString(grid, grid->rowCount(), &QGridLayout::rowStretch);
+}
+
+bool QFormBuilderExtra::setGridLayoutRowStretch(const QString &s, QGridLayout *grid)
+{
+ const bool rc = parsePerCellProperty(grid, grid->rowCount(), &QGridLayout::setRowStretch, s);
+ if (!rc)
+ uiLibWarning(msgInvalidStretch(grid->objectName(), s));
+ return rc;
+}
+
+void QFormBuilderExtra::clearGridLayoutRowStretch(QGridLayout *grid)
+{
+ clearPerCellValue(grid, grid->rowCount(), &QGridLayout::setRowStretch);
+}
+
+QString QFormBuilderExtra::gridLayoutColumnStretch(const QGridLayout *grid)
+{
+ return perCellPropertyToString(grid, grid->columnCount(), &QGridLayout::columnStretch);
+}
+
+bool QFormBuilderExtra::setGridLayoutColumnStretch(const QString &s, QGridLayout *grid)
+{
+ const bool rc = parsePerCellProperty(grid, grid->columnCount(), &QGridLayout::setColumnStretch, s);
+ if (!rc)
+ uiLibWarning(msgInvalidStretch(grid->objectName(), s));
+ return rc;
+}
+
+void QFormBuilderExtra::clearGridLayoutColumnStretch(QGridLayout *grid)
+{
+ clearPerCellValue(grid, grid->columnCount(), &QGridLayout::setColumnStretch);
+}
+
+// Read and write grid layout row/column size limits
+
+static QString msgInvalidMinimumSize(const QString &objectName, const QString &ms)
+{
+ //: Parsing grid layout minimum size values
+ return QCoreApplication::translate("FormBuilder", "Invalid minimum size for '%1': '%2'").arg(objectName, ms);
+}
+
+QString QFormBuilderExtra::gridLayoutRowMinimumHeight(const QGridLayout *grid)
+{
+ return perCellPropertyToString(grid, grid->rowCount(), &QGridLayout::rowMinimumHeight);
+}
+
+bool QFormBuilderExtra::setGridLayoutRowMinimumHeight(const QString &s, QGridLayout *grid)
+{
+ const bool rc = parsePerCellProperty(grid, grid->rowCount(), &QGridLayout::setRowMinimumHeight, s);
+ if (!rc)
+ uiLibWarning(msgInvalidMinimumSize(grid->objectName(), s));
+ return rc;
+}
+
+void QFormBuilderExtra::clearGridLayoutRowMinimumHeight(QGridLayout *grid)
+{
+ clearPerCellValue(grid, grid->rowCount(), &QGridLayout::setRowMinimumHeight);
+}
+
+QString QFormBuilderExtra::gridLayoutColumnMinimumWidth(const QGridLayout *grid)
+{
+ return perCellPropertyToString(grid, grid->columnCount(), &QGridLayout::columnMinimumWidth);
+}
+
+bool QFormBuilderExtra::setGridLayoutColumnMinimumWidth(const QString &s, QGridLayout *grid)
+{
+ const bool rc = parsePerCellProperty(grid, grid->columnCount(), &QGridLayout::setColumnMinimumWidth, s);
+ if (!rc)
+ uiLibWarning(msgInvalidMinimumSize(grid->objectName(), s));
+ return rc;
+}
+
+void QFormBuilderExtra::clearGridLayoutColumnMinimumWidth(QGridLayout *grid)
+{
+ clearPerCellValue(grid, grid->columnCount(), &QGridLayout::setColumnMinimumWidth);
+}
+
+// ------------ QFormBuilderStrings
+
+QFormBuilderStrings::QFormBuilderStrings() :
+ buddyProperty(QLatin1String("buddy")),
+ cursorProperty(QLatin1String("cursor")),
+ objectNameProperty(QLatin1String("objectName")),
+ trueValue(QLatin1String("true")),
+ falseValue(QLatin1String("false")),
+ horizontalPostFix(QLatin1String("Horizontal")),
+ separator(QLatin1String("separator")),
+ defaultTitle(QLatin1String("Page")),
+ titleAttribute(QLatin1String("title")),
+ labelAttribute(QLatin1String("label")),
+ toolTipAttribute(QLatin1String("toolTip")),
+ whatsThisAttribute(QLatin1String("whatsThis")),
+ flagsAttribute(QLatin1String("flags")),
+ iconAttribute(QLatin1String("icon")),
+ pixmapAttribute(QLatin1String("pixmap")),
+ textAttribute(QLatin1String("text")),
+ currentIndexProperty(QLatin1String("currentIndex")),
+ toolBarAreaAttribute(QLatin1String("toolBarArea")),
+ toolBarBreakAttribute(QLatin1String("toolBarBreak")),
+ dockWidgetAreaAttribute(QLatin1String("dockWidgetArea")),
+ marginProperty(QLatin1String("margin")),
+ spacingProperty(QLatin1String("spacing")),
+ leftMarginProperty(QLatin1String("leftMargin")),
+ topMarginProperty(QLatin1String("topMargin")),
+ rightMarginProperty(QLatin1String("rightMargin")),
+ bottomMarginProperty(QLatin1String("bottomMargin")),
+ horizontalSpacingProperty(QLatin1String("horizontalSpacing")),
+ verticalSpacingProperty(QLatin1String("verticalSpacing")),
+ sizeHintProperty(QLatin1String("sizeHint")),
+ sizeTypeProperty(QLatin1String("sizeType")),
+ orientationProperty(QLatin1String("orientation")),
+ styleSheetProperty(QLatin1String("styleSheet")),
+ qtHorizontal(QLatin1String("Qt::Horizontal")),
+ qtVertical(QLatin1String("Qt::Vertical")),
+ currentRowProperty(QLatin1String("currentRow")),
+ tabSpacingProperty(QLatin1String("tabSpacing")),
+ qWidgetClass(QLatin1String("QWidget")),
+ lineClass(QLatin1String("Line")),
+ geometryProperty(QLatin1String("geometry")),
+ scriptWidgetVariable(QLatin1String("widget")),
+ scriptChildWidgetsVariable(QLatin1String("childWidgets"))
+{
+ itemRoles.append(qMakePair(Qt::FontRole, QString::fromLatin1("font")));
+ itemRoles.append(qMakePair(Qt::TextAlignmentRole, QString::fromLatin1("textAlignment")));
+ itemRoles.append(qMakePair(Qt::BackgroundRole, QString::fromLatin1("background")));
+ itemRoles.append(qMakePair(Qt::ForegroundRole, QString::fromLatin1("foreground")));
+ itemRoles.append(qMakePair(Qt::CheckStateRole, QString::fromLatin1("checkState")));
+
+ foreach (const RoleNName &it, itemRoles)
+ treeItemRoleHash.insert(it.second, it.first);
+
+ itemTextRoles.append(qMakePair(qMakePair(Qt::EditRole, Qt::DisplayPropertyRole),
+ textAttribute)); // This must be first for the loop below
+ itemTextRoles.append(qMakePair(qMakePair(Qt::ToolTipRole, Qt::ToolTipPropertyRole),
+ toolTipAttribute));
+ itemTextRoles.append(qMakePair(qMakePair(Qt::StatusTipRole, Qt::StatusTipPropertyRole),
+ QString::fromLatin1("statusTip")));
+ itemTextRoles.append(qMakePair(qMakePair(Qt::WhatsThisRole, Qt::WhatsThisPropertyRole),
+ whatsThisAttribute));
+
+ // Note: this skips the first item!
+ QList<TextRoleNName>::const_iterator it = itemTextRoles.constBegin(), end = itemTextRoles.constEnd();
+ while (++it != end)
+ treeItemTextRoleHash.insert(it->second, it->first);
+}
+
+const QFormBuilderStrings &QFormBuilderStrings::instance()
+{
+ static const QFormBuilderStrings rc;
+ return rc;
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+} // namespace QFormInternal
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/uilib/formbuilderextra_p.h b/tools/designer/src/lib/uilib/formbuilderextra_p.h
new file mode 100644
index 0000000000..f35723955e
--- /dev/null
+++ b/tools/designer/src/lib/uilib/formbuilderextra_p.h
@@ -0,0 +1,255 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFORMBUILDERPRIVATE_H
+#define ABSTRACTFORMBUILDERPRIVATE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "uilib_global.h"
+
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+# include "formscriptrunner_p.h"
+#endif
+
+#include <QtCore/QHash>
+#include <QtCore/QPointer>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QVariant;
+class QWidget;
+class QObject;
+class QLabel;
+class QButtonGroup;
+
+class QBoxLayout;
+class QGridLayout;
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class DomButtonGroups;
+class DomButtonGroup;
+
+class QAbstractFormBuilder;
+class QResourceBuilder;
+class QTextBuilder;
+
+class QDESIGNER_UILIB_EXPORT QFormBuilderExtra
+{
+ QFormBuilderExtra();
+ ~QFormBuilderExtra();
+public:
+ void clear();
+
+ bool applyPropertyInternally(QObject *o, const QString &propertyName, const QVariant &value);
+
+ enum BuddyMode { BuddyApplyAll, BuddyApplyVisibleOnly };
+
+ void applyInternalProperties() const;
+ static bool applyBuddy(const QString &buddyName, BuddyMode applyMode, QLabel *label);
+
+ const QPointer<QWidget> &rootWidget() const;
+ void setRootWidget(const QPointer<QWidget> &w);
+
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ QFormScriptRunner &formScriptRunner();
+ void storeCustomWidgetScript(const QString &className, const QString &script);
+ QString customWidgetScript(const QString &className) const;
+#endif
+
+ void setProcessingLayoutWidget(bool processing);
+ bool processingLayoutWidget() const;
+
+ void setResourceBuilder(QResourceBuilder *builder);
+ QResourceBuilder *resourceBuilder() const;
+
+ void setTextBuilder(QTextBuilder *builder);
+ QTextBuilder *textBuilder() const;
+
+ static QFormBuilderExtra *instance(const QAbstractFormBuilder *afb);
+ static void removeInstance(const QAbstractFormBuilder *afb);
+
+ void storeCustomWidgetAddPageMethod(const QString &className, const QString &ct);
+ QString customWidgetAddPageMethod(const QString &className) const;
+
+ void storeCustomWidgetBaseClass(const QString &className, const QString &baseClassName);
+ QString customWidgetBaseClass(const QString &className) const;
+
+ // --- Hash used in creating button groups on demand. Store a map of name and pair of dom group and real group
+ void registerButtonGroups(const DomButtonGroups *groups);
+
+ typedef QPair<DomButtonGroup *, QButtonGroup*> ButtonGroupEntry;
+ typedef QHash<QString, ButtonGroupEntry> ButtonGroupHash;
+ const ButtonGroupHash &buttonGroups() const { return m_buttonGroups; }
+ ButtonGroupHash &buttonGroups() { return m_buttonGroups; }
+
+ // return stretch as a comma-separated list
+ static QString boxLayoutStretch(const QBoxLayout*);
+ // apply stretch
+ static bool setBoxLayoutStretch(const QString &, QBoxLayout*);
+ static void clearBoxLayoutStretch(QBoxLayout*);
+
+ static QString gridLayoutRowStretch(const QGridLayout *);
+ static bool setGridLayoutRowStretch(const QString &, QGridLayout *);
+ static void clearGridLayoutRowStretch(QGridLayout *);
+
+ static QString gridLayoutColumnStretch(const QGridLayout *);
+ static bool setGridLayoutColumnStretch(const QString &, QGridLayout *);
+ static void clearGridLayoutColumnStretch(QGridLayout *);
+
+ // return the row/column sizes as comma-separated lists
+ static QString gridLayoutRowMinimumHeight(const QGridLayout *);
+ static bool setGridLayoutRowMinimumHeight(const QString &, QGridLayout *);
+ static void clearGridLayoutRowMinimumHeight(QGridLayout *);
+
+ static QString gridLayoutColumnMinimumWidth(const QGridLayout *);
+ static bool setGridLayoutColumnMinimumWidth(const QString &, QGridLayout *);
+ static void clearGridLayoutColumnMinimumWidth(QGridLayout *);
+
+private:
+ void clearResourceBuilder();
+ void clearTextBuilder();
+
+ typedef QHash<QLabel*, QString> BuddyHash;
+ BuddyHash m_buddies;
+
+#ifndef QT_FORMBUILDER_NO_SCRIPT
+ QFormScriptRunner m_FormScriptRunner;
+
+ typedef QHash<QString, QString> CustomWidgetScriptHash;
+ CustomWidgetScriptHash m_customWidgetScriptHash;
+#endif
+
+ QHash<QString, QString> m_customWidgetAddPageMethodHash;
+ QHash<QString, QString> m_customWidgetBaseClassHash;
+
+ ButtonGroupHash m_buttonGroups;
+
+ bool m_layoutWidget;
+ QResourceBuilder *m_resourceBuilder;
+ QTextBuilder *m_textBuilder;
+
+ QPointer<QWidget> m_rootWidget;
+};
+
+void uiLibWarning(const QString &message);
+
+// Struct with static accessor that provides most strings used in the form builder.
+struct QDESIGNER_UILIB_EXPORT QFormBuilderStrings {
+ QFormBuilderStrings();
+
+ static const QFormBuilderStrings &instance();
+
+ const QString buddyProperty;
+ const QString cursorProperty;
+ const QString objectNameProperty;
+ const QString trueValue;
+ const QString falseValue;
+ const QString horizontalPostFix;
+ const QString separator;
+ const QString defaultTitle;
+ const QString titleAttribute;
+ const QString labelAttribute;
+ const QString toolTipAttribute;
+ const QString whatsThisAttribute;
+ const QString flagsAttribute;
+ const QString iconAttribute;
+ const QString pixmapAttribute;
+ const QString textAttribute;
+ const QString currentIndexProperty;
+ const QString toolBarAreaAttribute;
+ const QString toolBarBreakAttribute;
+ const QString dockWidgetAreaAttribute;
+ const QString marginProperty;
+ const QString spacingProperty;
+ const QString leftMarginProperty;
+ const QString topMarginProperty;
+ const QString rightMarginProperty;
+ const QString bottomMarginProperty;
+ const QString horizontalSpacingProperty;
+ const QString verticalSpacingProperty;
+ const QString sizeHintProperty;
+ const QString sizeTypeProperty;
+ const QString orientationProperty;
+ const QString styleSheetProperty;
+ const QString qtHorizontal;
+ const QString qtVertical;
+ const QString currentRowProperty;
+ const QString tabSpacingProperty;
+ const QString qWidgetClass;
+ const QString lineClass;
+ const QString geometryProperty;
+ const QString scriptWidgetVariable;
+ const QString scriptChildWidgetsVariable;
+
+ typedef QPair<Qt::ItemDataRole, QString> RoleNName;
+ QList<RoleNName> itemRoles;
+ QHash<QString, Qt::ItemDataRole> treeItemRoleHash;
+
+ // first.first is primary role, first.second is shadow role.
+ // Shadow is used for either the translation source or the designer
+ // representation of the string value.
+ typedef QPair<QPair<Qt::ItemDataRole, Qt::ItemDataRole>, QString> TextRoleNName;
+ QList<TextRoleNName> itemTextRoles;
+ QHash<QString, QPair<Qt::ItemDataRole, Qt::ItemDataRole> > treeItemTextRoleHash;
+};
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // ABSTRACTFORMBUILDERPRIVATE_H
diff --git a/tools/designer/src/lib/uilib/formscriptrunner.cpp b/tools/designer/src/lib/uilib/formscriptrunner.cpp
new file mode 100644
index 0000000000..d07673aeae
--- /dev/null
+++ b/tools/designer/src/lib/uilib/formscriptrunner.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formscriptrunner_p.h"
+#include "formbuilderextra_p.h"
+#include "ui4_p.h"
+
+#include <QtScript/QScriptEngine>
+#include <QtGui/QWidget>
+#include <QtCore/QDebug>
+#include <QtCore/QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { debugFormScriptRunner = 0 };
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal {
+#endif
+
+class QFormScriptRunner::QFormScriptRunnerPrivate {
+public:
+ QFormScriptRunnerPrivate() : m_options(DisableScripts) {}
+ void clearErrors() { m_errors.clear(); }
+
+ bool run(const QString &script, QWidget *widget, const WidgetList &children, QString *errorMessage);
+
+ static void initializeEngine(QWidget *w, const WidgetList &children, QScriptEngine &scriptEngine);
+ static QString engineError(QScriptEngine &scriptEngine);
+
+ Options options() const { return m_options; }
+ void setOptions(Options options) { m_options = options; }
+
+ Errors errors() const { return m_errors; }
+private:
+ QScriptEngine m_scriptEngine;
+ Options m_options;
+ Errors m_errors;
+};
+
+bool QFormScriptRunner::QFormScriptRunnerPrivate::run(const QString &script, QWidget *widget, const WidgetList &children, QString *errorMessage) {
+ bool rc = false;
+ initializeEngine(widget, children, m_scriptEngine);
+
+ do {
+ m_scriptEngine.evaluate(script);
+ if (m_scriptEngine.hasUncaughtException ()) {
+ *errorMessage = QCoreApplication::tr("Exception at line %1: %2").arg(m_scriptEngine.uncaughtExceptionLineNumber()).arg(engineError(m_scriptEngine));
+ break;
+ }
+ rc = true;
+ } while (false);
+ m_scriptEngine.popContext();
+
+ if (!rc) {
+ Error error;
+ error.objectName = widget->objectName();
+ error.script = script;
+ error.errorMessage = *errorMessage;
+ m_errors.push_back(error);
+ }
+ return rc;
+}
+
+void QFormScriptRunner::QFormScriptRunnerPrivate::initializeEngine(QWidget *w, const WidgetList &children, QScriptEngine &scriptEngine) {
+ // Populate the script variables. This pushes a context which must be popped.
+ QScriptContext *ctx = scriptEngine.pushContext();
+ QScriptValue widgetObject = scriptEngine.newQObject(w);
+ QScriptValue childrenArray = scriptEngine.newArray (children.size());
+
+ for(int i = 0; i < children.size(); i++) {
+ childrenArray.setProperty(i, scriptEngine.newQObject(children[i]));
+ }
+
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ ctx ->activationObject().setProperty(strings.scriptWidgetVariable, widgetObject);
+ ctx ->activationObject().setProperty(strings.scriptChildWidgetsVariable, childrenArray);
+}
+
+QString QFormScriptRunner::QFormScriptRunnerPrivate::engineError(QScriptEngine &scriptEngine) {
+ QScriptValue error = scriptEngine.evaluate(QLatin1String("Error"));
+ if (error.isValid())
+ return error.toString();
+ return QCoreApplication::tr("Unknown error");
+}
+// -- QFormScriptRunner
+
+QFormScriptRunner::QFormScriptRunner() : m_impl(new QFormScriptRunnerPrivate)
+{
+}
+
+QFormScriptRunner::~QFormScriptRunner()
+{
+ delete m_impl;
+}
+
+bool QFormScriptRunner::run(const DomWidget *domWidget,
+ const QString &customWidgetScript,
+ QWidget *widget, const WidgetList &children,
+ QString *errorMessage)
+{
+ typedef QList<DomScript*> DomScripts;
+
+ const Options scriptOptions = m_impl->options();
+ if (scriptOptions & DisableScripts)
+ return true;
+ // get list
+ const DomScripts domScripts = domWidget->elementScript();
+ // Concatenate snippets, starting with custom widget script
+ QString script = customWidgetScript;
+ if (script.isEmpty() && domScripts.empty())
+ return true;
+
+ foreach (const DomScript *scriptSnippet, domScripts) {
+ // Ensure new line
+ if (!script.isEmpty() && !script.endsWith(QLatin1Char('\n')))
+ script += QLatin1Char('\n');
+ script += scriptSnippet->text();
+ }
+
+ if (script.isEmpty())
+ return true;
+
+ const bool rc = m_impl->run(script, widget, children, errorMessage);
+
+ if (debugFormScriptRunner) {
+ qDebug() << "For " << widget << " with " << children.size() << " children, ran: " << script;
+ if (!rc)
+ qDebug() << *errorMessage;
+ }
+
+ if (!rc) {
+ if (!(scriptOptions & DisableWarnings)) {
+ const QString message = QCoreApplication::tr("An error occurred while running the script for %1: %2\nScript: %3").
+ arg(widget->objectName()).arg(*errorMessage).arg(script);
+ qWarning() << message;
+ }
+ }
+ return rc;
+}
+
+QFormScriptRunner::Options QFormScriptRunner::options() const
+{
+ return m_impl->options();
+}
+
+void QFormScriptRunner::setOptions(Options options)
+{
+ m_impl->setOptions(options);
+}
+
+
+QFormScriptRunner::Errors QFormScriptRunner::errors() const
+{
+ return m_impl->errors();
+}
+
+void QFormScriptRunner::clearErrors()
+{
+ m_impl->clearErrors();
+}
+
+
+#ifdef QFORMINTERNAL_NAMESPACE
+} // namespace QFormInternal
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/uilib/formscriptrunner_p.h b/tools/designer/src/lib/uilib/formscriptrunner_p.h
new file mode 100644
index 0000000000..f53120ccc4
--- /dev/null
+++ b/tools/designer/src/lib/uilib/formscriptrunner_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMSCRIPTRUNNER_H
+#define FORMSCRIPTRUNNER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDesigner/uilib_global.h>
+#include <QtCore/QList>
+#include <QtCore/QFlags>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class DomWidget;
+
+class QDESIGNER_UILIB_EXPORT QFormScriptRunner
+{
+public:
+ QFormScriptRunner();
+ ~QFormScriptRunner();
+
+ typedef QList<QWidget*> WidgetList;
+
+ bool run(const DomWidget *domWidget,
+ const QString &customWidgetScript,
+ QWidget *widget, const WidgetList &children,
+ QString *errorMessage);
+
+ struct Error {
+ QString objectName;
+ QString script;
+ QString errorMessage;
+ };
+ typedef QList<Error> Errors;
+ Errors errors() const;
+ void clearErrors();
+
+ enum Option {
+ NoOptions = 0x0,
+ DisableWarnings = 0x1,
+ DisableScripts = 02
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
+ Options options() const;
+ void setOptions(Options options);
+
+private:
+ class QFormScriptRunnerPrivate;
+ QFormScriptRunnerPrivate *m_impl;
+
+ QFormScriptRunner(const QFormScriptRunner &);
+ void operator = (const QFormScriptRunner &);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFormScriptRunner::Options)
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // FORMSCRIPTRUNNER_H
diff --git a/tools/designer/src/lib/uilib/properties.cpp b/tools/designer/src/lib/uilib/properties.cpp
new file mode 100644
index 0000000000..2cf9bf9875
--- /dev/null
+++ b/tools/designer/src/lib/uilib/properties.cpp
@@ -0,0 +1,676 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "properties_p.h"
+#include "ui4_p.h"
+#include "abstractformbuilder.h"
+#include "formbuilderextra_p.h"
+#include "resourcebuilder_p.h"
+
+#include <QtCore/QDateTime>
+#include <QtCore/QUrl>
+#include <QtCore/qdebug.h>
+
+#include <QtGui/QIcon>
+#include <QtGui/QPixmap>
+#include <QtGui/QFont>
+#include <QtGui/QFrame>
+#include <QtGui/QAbstractScrollArea>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+static inline void fixEnum(QString &s)
+{
+ int qualifierIndex = s.lastIndexOf(QLatin1Char(':'));
+ if (qualifierIndex == -1)
+ qualifierIndex = s.lastIndexOf(QLatin1Char('.'));
+ if (qualifierIndex != -1)
+ s.remove(0, qualifierIndex + 1);
+}
+// Convert complex DOM types with the help of QAbstractFormBuilder
+QVariant domPropertyToVariant(QAbstractFormBuilder *afb,const QMetaObject *meta,const DomProperty *p)
+{
+ // Complex types that need functions from QAbstractFormBuilder
+ switch(p->kind()) {
+ case DomProperty::String: {
+ const int index = meta->indexOfProperty(p->attributeName().toUtf8());
+ if (index != -1 && meta->property(index).type() == QVariant::KeySequence)
+ return qVariantFromValue(QKeySequence(p->elementString()->text()));
+ }
+ break;
+
+ case DomProperty::Palette: {
+ const DomPalette *dom = p->elementPalette();
+ QPalette palette;
+
+ if (dom->elementActive())
+ afb->setupColorGroup(palette, QPalette::Active, dom->elementActive());
+
+ if (dom->elementInactive())
+ afb->setupColorGroup(palette, QPalette::Inactive, dom->elementInactive());
+
+ if (dom->elementDisabled())
+ afb->setupColorGroup(palette, QPalette::Disabled, dom->elementDisabled());
+
+ palette.setCurrentColorGroup(QPalette::Active);
+ return qVariantFromValue(palette);
+ }
+
+ case DomProperty::Set: {
+ const QByteArray pname = p->attributeName().toUtf8();
+ const int index = meta->indexOfProperty(pname);
+ if (index == -1) {
+ uiLibWarning(QCoreApplication::translate("QFormBuilder", "The set-type property %1 could not be read.").arg(p->attributeName()));
+ return QVariant();
+ }
+
+ const QMetaEnum e = meta->property(index).enumerator();
+ Q_ASSERT(e.isFlag() == true);
+ return QVariant(e.keysToValue(p->elementSet().toUtf8()));
+ }
+
+ case DomProperty::Enum: {
+ const QByteArray pname = p->attributeName().toUtf8();
+ const int index = meta->indexOfProperty(pname);
+ QString enumValue = p->elementEnum();
+ // Triggers in case of objects in Designer like Spacer/Line for which properties
+ // are serialized using language introspection. On preview, however, these objects are
+ // emulated by hacks in the formbuilder (size policy/orientation)
+ fixEnum(enumValue);
+ if (index == -1) {
+ // ### special-casing for Line (QFrame) -- fix for 4.2. Jambi hack for enumerations
+ if (!qstrcmp(meta->className(), "QFrame")
+ && (pname == QByteArray("orientation"))) {
+ return QVariant(enumValue == QFormBuilderStrings::instance().horizontalPostFix ? QFrame::HLine : QFrame::VLine);
+ } else {
+ uiLibWarning(QCoreApplication::translate("QFormBuilder", "The enumeration-type property %1 could not be read.").arg(p->attributeName()));
+ return QVariant();
+ }
+ }
+
+ const QMetaEnum e = meta->property(index).enumerator();
+ return QVariant(e.keyToValue(enumValue.toUtf8()));
+ }
+ case DomProperty::Brush:
+ return qVariantFromValue(afb->setupBrush(p->elementBrush()));
+ default:
+ if (afb->resourceBuilder()->isResourceProperty(p)) {
+ return afb->resourceBuilder()->loadResource(afb->workingDirectory(), p);
+ }
+
+ break;
+ }
+
+ // simple type
+ return domPropertyToVariant(p);
+}
+
+// Convert simple DOM types
+QVariant domPropertyToVariant(const DomProperty *p)
+{
+ // requires non-const virtual nameToIcon, etc.
+ switch(p->kind()) {
+ case DomProperty::Bool:
+ return QVariant(p->elementBool() == QFormBuilderStrings::instance().trueValue);
+
+ case DomProperty::Cstring:
+ return QVariant(p->elementCstring().toUtf8());
+
+ case DomProperty::Point: {
+ const DomPoint *point = p->elementPoint();
+ return QVariant(QPoint(point->elementX(), point->elementY()));
+ }
+
+ case DomProperty::PointF: {
+ const DomPointF *pointf = p->elementPointF();
+ return QVariant(QPointF(pointf->elementX(), pointf->elementY()));
+ }
+
+ case DomProperty::Size: {
+ const DomSize *size = p->elementSize();
+ return QVariant(QSize(size->elementWidth(), size->elementHeight()));
+ }
+
+ case DomProperty::SizeF: {
+ const DomSizeF *sizef = p->elementSizeF();
+ return QVariant(QSizeF(sizef->elementWidth(), sizef->elementHeight()));
+ }
+
+ case DomProperty::Rect: {
+ const DomRect *rc = p->elementRect();
+ const QRect g(rc->elementX(), rc->elementY(), rc->elementWidth(), rc->elementHeight());
+ return QVariant(g);
+ }
+
+ case DomProperty::RectF: {
+ const DomRectF *rcf = p->elementRectF();
+ const QRectF g(rcf->elementX(), rcf->elementY(), rcf->elementWidth(), rcf->elementHeight());
+ return QVariant(g);
+ }
+
+ case DomProperty::String:
+ return QVariant(p->elementString()->text());
+
+ case DomProperty::Number:
+ return QVariant(p->elementNumber());
+
+ case DomProperty::UInt:
+ return QVariant(p->elementUInt());
+
+ case DomProperty::LongLong:
+ return QVariant(p->elementLongLong());
+
+ case DomProperty::ULongLong:
+ return QVariant(p->elementULongLong());
+
+ case DomProperty::Double:
+ return QVariant(p->elementDouble());
+
+ case DomProperty::Char: {
+ const DomChar *character = p->elementChar();
+ const QChar c(character->elementUnicode());
+ return qVariantFromValue(c);
+ }
+
+ case DomProperty::Color: {
+ const DomColor *color = p->elementColor();
+ QColor c(color->elementRed(), color->elementGreen(), color->elementBlue());
+ if (color->hasAttributeAlpha())
+ c.setAlpha(color->attributeAlpha());
+ return qVariantFromValue(c);
+ }
+
+ case DomProperty::Font: {
+ const DomFont *font = p->elementFont();
+
+ QFont f;
+ if (font->hasElementFamily() && !font->elementFamily().isEmpty())
+ f.setFamily(font->elementFamily());
+ if (font->hasElementPointSize() && font->elementPointSize() > 0)
+ f.setPointSize(font->elementPointSize());
+ if (font->hasElementWeight() && font->elementWeight() > 0)
+ f.setWeight(font->elementWeight());
+ if (font->hasElementItalic())
+ f.setItalic(font->elementItalic());
+ if (font->hasElementBold())
+ f.setBold(font->elementBold());
+ if (font->hasElementUnderline())
+ f.setUnderline(font->elementUnderline());
+ if (font->hasElementStrikeOut())
+ f.setStrikeOut(font->elementStrikeOut());
+ if (font->hasElementKerning())
+ f.setKerning(font->elementKerning());
+ if (font->hasElementAntialiasing())
+ f.setStyleStrategy(font->elementAntialiasing() ? QFont::PreferDefault : QFont::NoAntialias);
+ if (font->hasElementStyleStrategy()) {
+ f.setStyleStrategy(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QFont::StyleStrategy>("styleStrategy", font->elementStyleStrategy().toLatin1()));
+ }
+ return qVariantFromValue(f);
+ }
+
+ case DomProperty::Date: {
+ const DomDate *date = p->elementDate();
+ return QVariant(QDate(date->elementYear(), date->elementMonth(), date->elementDay()));
+ }
+
+ case DomProperty::Time: {
+ const DomTime *t = p->elementTime();
+ return QVariant(QTime(t->elementHour(), t->elementMinute(), t->elementSecond()));
+ }
+
+ case DomProperty::DateTime: {
+ const DomDateTime *dateTime = p->elementDateTime();
+ const QDate d(dateTime->elementYear(), dateTime->elementMonth(), dateTime->elementDay());
+ const QTime tm(dateTime->elementHour(), dateTime->elementMinute(), dateTime->elementSecond());
+ return QVariant(QDateTime(d, tm));
+ }
+
+ case DomProperty::Url: {
+ const DomUrl *url = p->elementUrl();
+ return QVariant(QUrl(url->elementString()->text()));
+ }
+
+#ifndef QT_NO_CURSOR
+ case DomProperty::Cursor:
+ return qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(p->elementCursor())));
+
+ case DomProperty::CursorShape:
+ return qVariantFromValue(QCursor(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, Qt::CursorShape>("cursorShape", p->elementCursorShape().toLatin1())));
+#endif
+
+ case DomProperty::Locale: {
+ const DomLocale *locale = p->elementLocale();
+ return qVariantFromValue(QLocale(enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Language>("language", locale->attributeLanguage().toLatin1()),
+ enumKeyOfObjectToValue<QAbstractFormBuilderGadget, QLocale::Country>("country", locale->attributeCountry().toLatin1())));
+ }
+ case DomProperty::SizePolicy: {
+ const DomSizePolicy *sizep = p->elementSizePolicy();
+
+ QSizePolicy sizePolicy;
+ sizePolicy.setHorizontalStretch(sizep->elementHorStretch());
+ sizePolicy.setVerticalStretch(sizep->elementVerStretch());
+
+ const QMetaEnum sizeType_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");
+
+ if (sizep->hasElementHSizeType()) {
+ sizePolicy.setHorizontalPolicy((QSizePolicy::Policy) sizep->elementHSizeType());
+ } else if (sizep->hasAttributeHSizeType()) {
+ const QSizePolicy::Policy sp = enumKeyToValue<QSizePolicy::Policy>(sizeType_enum, sizep->attributeHSizeType().toLatin1());
+ sizePolicy.setHorizontalPolicy(sp);
+ }
+
+ if (sizep->hasElementVSizeType()) {
+ sizePolicy.setVerticalPolicy((QSizePolicy::Policy) sizep->elementVSizeType());
+ } else if (sizep->hasAttributeVSizeType()) {
+ const QSizePolicy::Policy sp = enumKeyToValue<QSizePolicy::Policy>(sizeType_enum, sizep->attributeVSizeType().toLatin1());
+ sizePolicy.setVerticalPolicy(sp);
+ }
+
+ return qVariantFromValue(sizePolicy);
+ }
+
+ case DomProperty::StringList:
+ return QVariant(p->elementStringList()->elementString());
+
+ default:
+ uiLibWarning(QCoreApplication::translate("QFormBuilder", "Reading properties of the type %1 is not supported yet.").arg(p->kind()));
+ break;
+ }
+
+ return QVariant();
+}
+
+// Apply a simple variant type to a DOM property
+static bool applySimpleProperty(const QVariant &v, bool translateString, DomProperty *dom_prop)
+{
+ switch (v.type()) {
+ case QVariant::String: {
+ DomString *str = new DomString();
+ str->setText(v.toString());
+ if (!translateString)
+ str->setAttributeNotr(QLatin1String("true"));
+ dom_prop->setElementString(str);
+ }
+ return true;
+
+ case QVariant::ByteArray:
+ dom_prop->setElementCstring(QString::fromUtf8(v.toByteArray()));
+ return true;
+
+ case QVariant::Int:
+ dom_prop->setElementNumber(v.toInt());
+ return true;
+
+ case QVariant::UInt:
+ dom_prop->setElementUInt(v.toUInt());
+ return true;
+
+ case QVariant::LongLong:
+ dom_prop->setElementLongLong(v.toLongLong());
+ return true;
+
+ case QVariant::ULongLong:
+ dom_prop->setElementULongLong(v.toULongLong());
+ return true;
+
+ case QVariant::Double:
+ dom_prop->setElementDouble(v.toDouble());
+ return true;
+
+ case QVariant::Bool:
+ dom_prop->setElementBool(v.toBool() ? QFormBuilderStrings::instance().trueValue : QFormBuilderStrings::instance().falseValue);
+ return true;
+
+ case QVariant::Char: {
+ DomChar *ch = new DomChar();
+ const QChar character = v.toChar();
+ ch->setElementUnicode(character.unicode());
+ dom_prop->setElementChar(ch);
+ }
+ return true;
+
+ case QVariant::Point: {
+ DomPoint *pt = new DomPoint();
+ const QPoint point = v.toPoint();
+ pt->setElementX(point.x());
+ pt->setElementY(point.y());
+ dom_prop->setElementPoint(pt);
+ }
+ return true;
+
+ case QVariant::PointF: {
+ DomPointF *ptf = new DomPointF();
+ const QPointF pointf = v.toPointF();
+ ptf->setElementX(pointf.x());
+ ptf->setElementY(pointf.y());
+ dom_prop->setElementPointF(ptf);
+ }
+ return true;
+
+ case QVariant::Color: {
+ DomColor *clr = new DomColor();
+ const QColor color = qvariant_cast<QColor>(v);
+ clr->setElementRed(color.red());
+ clr->setElementGreen(color.green());
+ clr->setElementBlue(color.blue());
+ const int alphaChannel = color.alpha();
+ if (alphaChannel != 255)
+ clr->setAttributeAlpha(alphaChannel);
+ dom_prop->setElementColor(clr);
+ }
+ return true;
+
+ case QVariant::Size: {
+ DomSize *sz = new DomSize();
+ const QSize size = v.toSize();
+ sz->setElementWidth(size.width());
+ sz->setElementHeight(size.height());
+ dom_prop->setElementSize(sz);
+ }
+ return true;
+
+ case QVariant::SizeF: {
+ DomSizeF *szf = new DomSizeF();
+ const QSizeF sizef = v.toSizeF();
+ szf->setElementWidth(sizef.width());
+ szf->setElementHeight(sizef.height());
+ dom_prop->setElementSizeF(szf);
+ }
+ return true;
+
+ case QVariant::Rect: {
+ DomRect *rc = new DomRect();
+ const QRect rect = v.toRect();
+ rc->setElementX(rect.x());
+ rc->setElementY(rect.y());
+ rc->setElementWidth(rect.width());
+ rc->setElementHeight(rect.height());
+ dom_prop->setElementRect(rc);
+ }
+ return true;
+
+ case QVariant::RectF: {
+ DomRectF *rcf = new DomRectF();
+ const QRectF rectf = v.toRectF();
+ rcf->setElementX(rectf.x());
+ rcf->setElementY(rectf.y());
+ rcf->setElementWidth(rectf.width());
+ rcf->setElementHeight(rectf.height());
+ dom_prop->setElementRectF(rcf);
+ }
+ return true;
+
+ case QVariant::Font: {
+ DomFont *fnt = new DomFont();
+ const QFont font = qvariant_cast<QFont>(v);
+ const uint mask = font.resolve();
+ if (mask & QFont::WeightResolved) {
+ fnt->setElementBold(font.bold());
+ fnt->setElementWeight(font.weight());
+ }
+ if (mask & QFont::FamilyResolved)
+ fnt->setElementFamily(font.family());
+ if (mask & QFont::StyleResolved)
+ fnt->setElementItalic(font.italic());
+ if (mask & QFont::SizeResolved)
+ fnt->setElementPointSize(font.pointSize());
+ if (mask & QFont::StrikeOutResolved)
+ fnt->setElementStrikeOut(font.strikeOut());
+ if (mask & QFont::UnderlineResolved)
+ fnt->setElementUnderline(font.underline());
+ if (mask & QFont::KerningResolved)
+ fnt->setElementKerning(font.kerning());
+ if (mask & QFont::StyleStrategyResolved) {
+ const QMetaEnum styleStrategy_enum = metaEnum<QAbstractFormBuilderGadget>("styleStrategy");
+ fnt->setElementStyleStrategy(QLatin1String(styleStrategy_enum.valueToKey(font.styleStrategy())));
+ }
+ dom_prop->setElementFont(fnt);
+ }
+ return true;
+
+#ifndef QT_NO_CURSOR
+ case QVariant::Cursor: {
+ const QMetaEnum cursorShape_enum = metaEnum<QAbstractFormBuilderGadget>("cursorShape");
+ dom_prop->setElementCursorShape(QLatin1String(cursorShape_enum.valueToKey(qvariant_cast<QCursor>(v).shape())));
+ }
+ return true;
+#endif
+
+ case QVariant::KeySequence: {
+ DomString *s = new DomString();
+ s->setText(qvariant_cast<QKeySequence>(v).toString(QKeySequence::PortableText));
+ dom_prop->setElementString(s);
+ }
+ return true;
+
+ case QVariant::Locale: {
+ DomLocale *dom = new DomLocale();
+ const QLocale locale = qvariant_cast<QLocale>(v);
+
+ const QMetaEnum language_enum = metaEnum<QAbstractFormBuilderGadget>("language");
+ const QMetaEnum country_enum = metaEnum<QAbstractFormBuilderGadget>("country");
+
+ dom->setAttributeLanguage(QLatin1String(language_enum.valueToKey(locale.language())));
+ dom->setAttributeCountry(QLatin1String(country_enum.valueToKey(locale.country())));
+
+ dom_prop->setElementLocale(dom);
+ }
+ return true;
+
+ case QVariant::SizePolicy: {
+ DomSizePolicy *dom = new DomSizePolicy();
+ const QSizePolicy sizePolicy = qvariant_cast<QSizePolicy>(v);
+
+ dom->setElementHorStretch(sizePolicy.horizontalStretch());
+ dom->setElementVerStretch(sizePolicy.verticalStretch());
+
+ const QMetaEnum sizeType_enum = metaEnum<QAbstractFormBuilderGadget>("sizeType");
+
+ dom->setAttributeHSizeType(QLatin1String(sizeType_enum.valueToKey(sizePolicy.horizontalPolicy())));
+ dom->setAttributeVSizeType(QLatin1String(sizeType_enum.valueToKey(sizePolicy.verticalPolicy())));
+
+ dom_prop->setElementSizePolicy(dom);
+ }
+ return true;
+
+ case QVariant::Date: {
+ DomDate *dom = new DomDate();
+ const QDate date = qvariant_cast<QDate>(v);
+
+ dom->setElementYear(date.year());
+ dom->setElementMonth(date.month());
+ dom->setElementDay(date.day());
+
+ dom_prop->setElementDate(dom);
+ }
+ return true;
+
+ case QVariant::Time: {
+ DomTime *dom = new DomTime();
+ const QTime time = qvariant_cast<QTime>(v);
+
+ dom->setElementHour(time.hour());
+ dom->setElementMinute(time.minute());
+ dom->setElementSecond(time.second());
+
+ dom_prop->setElementTime(dom);
+ }
+ return true;
+
+ case QVariant::DateTime: {
+ DomDateTime *dom = new DomDateTime();
+ const QDateTime dateTime = qvariant_cast<QDateTime>(v);
+
+ dom->setElementHour(dateTime.time().hour());
+ dom->setElementMinute(dateTime.time().minute());
+ dom->setElementSecond(dateTime.time().second());
+ dom->setElementYear(dateTime.date().year());
+ dom->setElementMonth(dateTime.date().month());
+ dom->setElementDay(dateTime.date().day());
+
+ dom_prop->setElementDateTime(dom);
+ }
+ return true;
+
+ case QVariant::Url: {
+ DomUrl *dom = new DomUrl();
+ const QUrl url = v.toUrl();
+
+ DomString *str = new DomString();
+ str->setText(url.toString());
+ dom->setElementString(str);
+
+ dom_prop->setElementUrl(dom);
+ }
+ return true;
+
+ case QVariant::StringList: {
+ DomStringList *sl = new DomStringList;
+ sl->setElementString(qvariant_cast<QStringList>(v));
+ dom_prop->setElementStringList(sl);
+ }
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+static QString msgCannotWriteProperty(const QString &pname, const QVariant &v)
+{
+ return QCoreApplication::translate("QFormBuilder", "The property %1 could not be written. The type %2 is not supported yet.").
+ arg(pname).arg(QLatin1String(v.typeName()));
+
+}
+
+static bool isOfType(const QMetaObject *what, const QMetaObject *type)
+{
+ do {
+ if (what == type)
+ return true;
+ } while ((what = what->superClass()));
+ return false;
+}
+
+static bool isTranslatable(const QString &pname, const QVariant &v, const QMetaObject *meta)
+{
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+ if (pname == strings.objectNameProperty)
+ return false;
+ if (pname == strings.styleSheetProperty && v.type() == QVariant::String && isOfType(meta, &QWidget::staticMetaObject))
+ return false;
+ return true;
+}
+
+// Convert complex variant types to DOM properties with the help of QAbstractFormBuilder
+// Does not perform a check using QAbstractFormBuilder::checkProperty().
+DomProperty *variantToDomProperty(QAbstractFormBuilder *afb, const QMetaObject *meta,
+ const QString &pname, const QVariant &v)
+{
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+
+ DomProperty *dom_prop = new DomProperty();
+ dom_prop->setAttributeName(pname);
+
+ const int pindex = meta->indexOfProperty(pname.toLatin1());
+ if (pindex != -1) {
+ QMetaProperty meta_property = meta->property(pindex);
+ if ((v.type() == QVariant::Int || v.type() == QVariant::UInt) && meta_property.isEnumType()) {
+ const QMetaEnum e = meta_property.enumerator();
+ if (e.isFlag())
+ dom_prop->setElementSet(QString::fromAscii(e.valueToKeys(v.toInt())));
+ else
+ dom_prop->setElementEnum(QString::fromAscii(e.valueToKey(v.toInt())));
+ return dom_prop;
+ }
+ if (!meta_property.hasStdCppSet() || (isOfType(meta, &QAbstractScrollArea::staticMetaObject) && pname == strings.cursorProperty))
+ dom_prop->setAttributeStdset(0);
+ }
+
+ // Try simple properties
+ if (applySimpleProperty(v, isTranslatable(pname, v, meta), dom_prop))
+ return dom_prop;
+
+ // Complex properties
+ switch (v.type()) {
+ case QVariant::Palette: {
+ DomPalette *dom = new DomPalette();
+ QPalette palette = qvariant_cast<QPalette>(v);
+
+ palette.setCurrentColorGroup(QPalette::Active);
+ dom->setElementActive(afb->saveColorGroup(palette));
+
+ palette.setCurrentColorGroup(QPalette::Inactive);
+ dom->setElementInactive(afb->saveColorGroup(palette));
+
+ palette.setCurrentColorGroup(QPalette::Disabled);
+ dom->setElementDisabled(afb->saveColorGroup(palette));
+
+ dom_prop->setElementPalette(dom);
+ } break;
+ case QVariant::Brush:
+ dom_prop->setElementBrush(afb->saveBrush(qvariant_cast<QBrush>(v)));
+ break;
+ default:
+ delete dom_prop;
+ if (afb->resourceBuilder()->isResourceType(v)) {
+ dom_prop = afb->resourceBuilder()->saveResource(afb->workingDirectory(), v);
+ if (dom_prop)
+ dom_prop->setAttributeName(pname);
+ break;
+ }
+ uiLibWarning(msgCannotWriteProperty(pname, v));
+ return 0;
+ }
+ return dom_prop;
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/uilib/properties_p.h b/tools/designer/src/lib/uilib/properties_p.h
new file mode 100644
index 0000000000..bc02ad542c
--- /dev/null
+++ b/tools/designer/src/lib/uilib/properties_p.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef UILIBPROPERTIES_H
+#define UILIBPROPERTIES_H
+
+#include <QtDesigner/uilib_global.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QMetaProperty>
+#include <QtCore/QLocale>
+#include <QtCore/QCoreApplication>
+
+#include <QtGui/QWidget>
+
+#include "formbuilderextra_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class QAbstractFormBuilder;
+class DomProperty;
+
+QDESIGNER_UILIB_EXPORT DomProperty *variantToDomProperty(QAbstractFormBuilder *abstractFormBuilder, const QMetaObject *meta, const QString &propertyName, const QVariant &value);
+
+
+QDESIGNER_UILIB_EXPORT QVariant domPropertyToVariant(const DomProperty *property);
+QDESIGNER_UILIB_EXPORT QVariant domPropertyToVariant(QAbstractFormBuilder *abstractFormBuilder, const QMetaObject *meta, const DomProperty *property);
+
+// This class exists to provide meta information
+// for enumerations only.
+class QAbstractFormBuilderGadget: public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::ItemFlags itemFlags READ fakeItemFlags)
+ Q_PROPERTY(Qt::CheckState checkState READ fakeCheckState)
+ Q_PROPERTY(Qt::Alignment textAlignment READ fakeAlignment)
+ Q_PROPERTY(Qt::Orientation orientation READ fakeOrientation)
+ Q_PROPERTY(QSizePolicy::Policy sizeType READ fakeSizeType)
+ Q_PROPERTY(QPalette::ColorRole colorRole READ fakeColorRole)
+ Q_PROPERTY(QPalette::ColorGroup colorGroup READ fakeColorGroup)
+ Q_PROPERTY(QFont::StyleStrategy styleStrategy READ fakeStyleStrategy)
+ Q_PROPERTY(Qt::CursorShape cursorShape READ fakeCursorShape)
+ Q_PROPERTY(Qt::BrushStyle brushStyle READ fakeBrushStyle)
+ Q_PROPERTY(Qt::ToolBarArea toolBarArea READ fakeToolBarArea)
+ Q_PROPERTY(QGradient::Type gradientType READ fakeGradientType)
+ Q_PROPERTY(QGradient::Spread gradientSpread READ fakeGradientSpread)
+ Q_PROPERTY(QGradient::CoordinateMode gradientCoordinate READ fakeGradientCoordinate)
+ Q_PROPERTY(QLocale::Language language READ fakeLanguage)
+ Q_PROPERTY(QLocale::Country country READ fakeCountry)
+public:
+ QAbstractFormBuilderGadget() { Q_ASSERT(0); }
+
+ Qt::Orientation fakeOrientation() const { Q_ASSERT(0); return Qt::Horizontal; }
+ QSizePolicy::Policy fakeSizeType() const { Q_ASSERT(0); return QSizePolicy::Expanding; }
+ QPalette::ColorGroup fakeColorGroup() const { Q_ASSERT(0); return static_cast<QPalette::ColorGroup>(0); }
+ QPalette::ColorRole fakeColorRole() const { Q_ASSERT(0); return static_cast<QPalette::ColorRole>(0); }
+ QFont::StyleStrategy fakeStyleStrategy() const { Q_ASSERT(0); return QFont::PreferDefault; }
+ Qt::CursorShape fakeCursorShape() const { Q_ASSERT(0); return Qt::ArrowCursor; }
+ Qt::BrushStyle fakeBrushStyle() const { Q_ASSERT(0); return Qt::NoBrush; }
+ Qt::ToolBarArea fakeToolBarArea() const { Q_ASSERT(0); return Qt::NoToolBarArea; }
+ QGradient::Type fakeGradientType() const { Q_ASSERT(0); return QGradient::NoGradient; }
+ QGradient::Spread fakeGradientSpread() const { Q_ASSERT(0); return QGradient::PadSpread; }
+ QGradient::CoordinateMode fakeGradientCoordinate() const { Q_ASSERT(0); return QGradient::LogicalMode; }
+ QLocale::Language fakeLanguage() const { Q_ASSERT(0); return QLocale::C; }
+ QLocale::Country fakeCountry() const { Q_ASSERT(0); return QLocale::AnyCountry; }
+ Qt::ItemFlags fakeItemFlags() const { Q_ASSERT(0); return Qt::NoItemFlags; }
+ Qt::CheckState fakeCheckState() const { Q_ASSERT(0); return Qt::Unchecked; }
+ Qt::Alignment fakeAlignment() const { Q_ASSERT(0); return Qt::AlignLeft; }
+};
+
+// Convert key to value for a given QMetaEnum
+template <class EnumType>
+inline EnumType enumKeyToValue(const QMetaEnum &metaEnum,const char *key, const EnumType* = 0)
+{
+ int val = metaEnum.keyToValue(key);
+ if (val == -1) {
+
+ uiLibWarning(QCoreApplication::translate("QFormBuilder", "The enumeration-value '%1' is invalid. The default value '%2' will be used instead.")
+ .arg(QString::fromUtf8(key)).arg(QString::fromUtf8(metaEnum.key(0))));
+ val = metaEnum.value(0);
+ }
+ return static_cast<EnumType>(val);
+}
+
+// Convert keys to value for a given QMetaEnum
+template <class EnumType>
+inline EnumType enumKeysToValue(const QMetaEnum &metaEnum,const char *keys, const EnumType* = 0)
+{
+ int val = metaEnum.keysToValue(keys);
+ if (val == -1) {
+
+ uiLibWarning(QCoreApplication::translate("QFormBuilder", "The flag-value '%1' is invalid. Zero will be used instead.")
+ .arg(QString::fromUtf8(keys)));
+ val = 0;
+ }
+ return static_cast<EnumType>(QFlag(val));
+}
+
+// Access meta enumeration object of a qobject
+template <class QObjectType>
+inline QMetaEnum metaEnum(const char *name, const QObjectType* = 0)
+{
+ const int e_index = QObjectType::staticMetaObject.indexOfProperty(name);
+ Q_ASSERT(e_index != -1);
+ return QObjectType::staticMetaObject.property(e_index).enumerator();
+}
+
+// Convert key to value for enumeration by name
+template <class QObjectType, class EnumType>
+inline EnumType enumKeyOfObjectToValue(const char *enumName, const char *key, const QObjectType* = 0, const EnumType* = 0)
+{
+ const QMetaEnum me = metaEnum<QObjectType>(enumName);
+ return enumKeyToValue<EnumType>(me, key);
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // UILIBPROPERTIES_H
diff --git a/tools/designer/src/lib/uilib/qdesignerexportwidget.h b/tools/designer/src/lib/uilib/qdesignerexportwidget.h
new file mode 100644
index 0000000000..c50f34c259
--- /dev/null
+++ b/tools/designer/src/lib/uilib/qdesignerexportwidget.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDESIGNEREXPORTWIDGET_H
+#define QDESIGNEREXPORTWIDGET_H
+
+#include <QtCore/QtGlobal>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#if 0
+// pragma for syncqt, don't remove.
+#pragma qt_class(QDesignerExportWidget)
+#endif
+
+#if defined(QDESIGNER_EXPORT_WIDGETS)
+# define QDESIGNER_WIDGET_EXPORT Q_DECL_EXPORT
+#else
+# define QDESIGNER_WIDGET_EXPORT Q_DECL_IMPORT
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QDESIGNEREXPORTWIDGET_H
diff --git a/tools/designer/src/lib/uilib/resourcebuilder.cpp b/tools/designer/src/lib/uilib/resourcebuilder.cpp
new file mode 100644
index 0000000000..3679f92048
--- /dev/null
+++ b/tools/designer/src/lib/uilib/resourcebuilder.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "resourcebuilder_p.h"
+#include "ui4_p.h"
+#include <QtCore/QVariant>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtGui/QPixmap>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal {
+#endif
+
+QResourceBuilder::QResourceBuilder()
+{
+
+}
+
+QResourceBuilder::~QResourceBuilder()
+{
+
+}
+
+int QResourceBuilder::iconStateFlags(const DomResourceIcon *dpi)
+{
+ int rc = 0;
+ if (dpi->hasElementNormalOff())
+ rc |= NormalOff;
+ if (dpi->hasElementNormalOn())
+ rc |= NormalOn;
+ if (dpi->hasElementDisabledOff())
+ rc |= DisabledOff;
+ if (dpi->hasElementDisabledOn())
+ rc |= DisabledOn;
+ if (dpi->hasElementActiveOff())
+ rc |= ActiveOff;
+ if (dpi->hasElementActiveOn())
+ rc |= ActiveOn;
+ if (dpi->hasElementSelectedOff())
+ rc |= SelectedOff;
+ if (dpi->hasElementSelectedOn())
+ rc |= SelectedOn;
+ return rc;
+}
+
+QVariant QResourceBuilder::loadResource(const QDir &workingDirectory, const DomProperty *property) const
+{
+ switch (property->kind()) {
+ case DomProperty::Pixmap: {
+ const DomResourcePixmap *dpx = property->elementPixmap();
+ QPixmap pixmap(QFileInfo(workingDirectory, dpx->text()).absoluteFilePath());
+ return qVariantFromValue(pixmap);
+ }
+ case DomProperty::IconSet: {
+ const DomResourceIcon *dpi = property->elementIconSet();
+ if (const int flags = iconStateFlags(dpi)) { // new, post 4.4 format
+ QIcon icon;
+ if (flags & NormalOff)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementNormalOff()->text()).absoluteFilePath(), QIcon::Normal, QIcon::Off);
+ if (flags & NormalOn)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementNormalOn()->text()).absoluteFilePath(), QIcon::Normal, QIcon::On);
+ if (flags & DisabledOff)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementDisabledOff()->text()).absoluteFilePath(), QIcon::Disabled, QIcon::Off);
+ if (flags & DisabledOn)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementDisabledOn()->text()).absoluteFilePath(), QIcon::Disabled, QIcon::On);
+ if (flags & ActiveOff)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementActiveOff()->text()).absoluteFilePath(), QIcon::Active, QIcon::Off);
+ if (flags & ActiveOn)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementActiveOn()->text()).absoluteFilePath(), QIcon::Active, QIcon::On);
+ if (flags & SelectedOff)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementSelectedOff()->text()).absoluteFilePath(), QIcon::Selected, QIcon::Off);
+ if (flags & SelectedOn)
+ icon.addPixmap(QFileInfo(workingDirectory, dpi->elementSelectedOn()->text()).absoluteFilePath(), QIcon::Selected, QIcon::On);
+ return qVariantFromValue(icon);
+ } else { // 4.3 legacy
+ const QIcon icon(QFileInfo(workingDirectory, dpi->text()).absoluteFilePath());
+ return qVariantFromValue(icon);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+QVariant QResourceBuilder::toNativeValue(const QVariant &value) const
+{
+ return value;
+}
+
+DomProperty *QResourceBuilder::saveResource(const QDir &workingDirectory, const QVariant &value) const
+{
+ Q_UNUSED(workingDirectory)
+ Q_UNUSED(value)
+ return 0;
+}
+
+bool QResourceBuilder::isResourceProperty(const DomProperty *p) const
+{
+ switch (p->kind()) {
+ case DomProperty::Pixmap:
+ case DomProperty::IconSet:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool QResourceBuilder::isResourceType(const QVariant &value) const
+{
+ switch (value.type()) {
+ case QVariant::Pixmap:
+ case QVariant::Icon:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+} // namespace QFormInternal
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/uilib/resourcebuilder_p.h b/tools/designer/src/lib/uilib/resourcebuilder_p.h
new file mode 100644
index 0000000000..5274b2d05a
--- /dev/null
+++ b/tools/designer/src/lib/uilib/resourcebuilder_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RESOURCEBUILDER_H
+#define RESOURCEBUILDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDesigner/uilib_global.h>
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QDir;
+class QVariant;
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class DomProperty;
+class DomResourceIcon;
+
+class QDESIGNER_UILIB_EXPORT QResourceBuilder
+{
+public:
+ enum IconStateFlags {
+ NormalOff = 0x1, NormalOn = 0x2, DisabledOff = 0x4, DisabledOn = 0x8,
+ ActiveOff = 0x10, ActiveOn = 0x20, SelectedOff = 0x40, SelectedOn = 0x80
+ };
+
+ QResourceBuilder();
+ virtual ~QResourceBuilder();
+
+ virtual QVariant loadResource(const QDir &workingDirectory, const DomProperty *property) const;
+
+ virtual QVariant toNativeValue(const QVariant &value) const;
+
+ virtual DomProperty *saveResource(const QDir &workingDirectory, const QVariant &value) const;
+
+ virtual bool isResourceProperty(const DomProperty *p) const;
+
+ virtual bool isResourceType(const QVariant &value) const;
+
+ static int iconStateFlags(const DomResourceIcon *resIcon);
+};
+
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // RESOURCEBUILDER_H
diff --git a/tools/designer/src/lib/uilib/textbuilder.cpp b/tools/designer/src/lib/uilib/textbuilder.cpp
new file mode 100644
index 0000000000..4219d14b37
--- /dev/null
+++ b/tools/designer/src/lib/uilib/textbuilder.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "textbuilder_p.h"
+#include "ui4_p.h"
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal {
+#endif
+
+QTextBuilder::QTextBuilder()
+{
+
+}
+
+QTextBuilder::~QTextBuilder()
+{
+
+}
+
+QVariant QTextBuilder::loadText(const DomProperty *property) const
+{
+ if (property->kind() == DomProperty::String)
+ return property->elementString()->text();
+ return QVariant();
+}
+
+QVariant QTextBuilder::toNativeValue(const QVariant &value) const
+{
+ return value;
+}
+
+DomProperty *QTextBuilder::saveText(const QVariant &value) const
+{
+ Q_UNUSED(value)
+ return 0;
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+} // namespace QFormInternal
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/lib/uilib/textbuilder_p.h b/tools/designer/src/lib/uilib/textbuilder_p.h
new file mode 100644
index 0000000000..fb0b9819b0
--- /dev/null
+++ b/tools/designer/src/lib/uilib/textbuilder_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTBUILDER_H
+#define TEXTBUILDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtDesigner/uilib_global.h>
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QDir;
+class QVariant;
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class DomProperty;
+class DomString;
+
+class QDESIGNER_UILIB_EXPORT QTextBuilder
+{
+public:
+ QTextBuilder();
+ virtual ~QTextBuilder();
+
+ virtual QVariant loadText(const DomProperty *property) const;
+
+ virtual QVariant toNativeValue(const QVariant &value) const;
+
+ virtual DomProperty *saveText(const QVariant &value) const;
+};
+
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // TEXTBUILDER_H
diff --git a/tools/designer/src/lib/uilib/ui4.cpp b/tools/designer/src/lib/uilib/ui4.cpp
new file mode 100644
index 0000000000..2047739f36
--- /dev/null
+++ b/tools/designer/src/lib/uilib/ui4.cpp
@@ -0,0 +1,10887 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "ui4_p.h"
+
+#ifdef QUILOADER_QDOM_READ
+#include <QtXml/QDomElement>
+#endif
+
+QT_BEGIN_NAMESPACE
+#ifdef QFORMINTERNAL_NAMESPACE
+using namespace QFormInternal;
+#endif
+
+/*******************************************************************************
+** Implementations
+*/
+
+void DomUI::clear(bool clear_all)
+{
+ delete m_widget;
+ delete m_layoutDefault;
+ delete m_layoutFunction;
+ delete m_customWidgets;
+ delete m_tabStops;
+ delete m_images;
+ delete m_includes;
+ delete m_resources;
+ delete m_connections;
+ delete m_designerdata;
+ delete m_slots;
+ delete m_buttonGroups;
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_version = false;
+ m_has_attr_language = false;
+ m_has_attr_displayname = false;
+ m_has_attr_stdsetdef = false;
+ m_attr_stdsetdef = 0;
+ m_has_attr_stdSetDef = false;
+ m_attr_stdSetDef = 0;
+ }
+
+ m_children = 0;
+ m_widget = 0;
+ m_layoutDefault = 0;
+ m_layoutFunction = 0;
+ m_customWidgets = 0;
+ m_tabStops = 0;
+ m_images = 0;
+ m_includes = 0;
+ m_resources = 0;
+ m_connections = 0;
+ m_designerdata = 0;
+ m_slots = 0;
+ m_buttonGroups = 0;
+}
+
+DomUI::DomUI()
+{
+ m_children = 0;
+ m_has_attr_version = false;
+ m_has_attr_language = false;
+ m_has_attr_displayname = false;
+ m_has_attr_stdsetdef = false;
+ m_attr_stdsetdef = 0;
+ m_has_attr_stdSetDef = false;
+ m_attr_stdSetDef = 0;
+ m_widget = 0;
+ m_layoutDefault = 0;
+ m_layoutFunction = 0;
+ m_customWidgets = 0;
+ m_tabStops = 0;
+ m_images = 0;
+ m_includes = 0;
+ m_resources = 0;
+ m_connections = 0;
+ m_designerdata = 0;
+ m_slots = 0;
+ m_buttonGroups = 0;
+}
+
+DomUI::~DomUI()
+{
+ delete m_widget;
+ delete m_layoutDefault;
+ delete m_layoutFunction;
+ delete m_customWidgets;
+ delete m_tabStops;
+ delete m_images;
+ delete m_includes;
+ delete m_resources;
+ delete m_connections;
+ delete m_designerdata;
+ delete m_slots;
+ delete m_buttonGroups;
+}
+
+void DomUI::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("version")) {
+ setAttributeVersion(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("language")) {
+ setAttributeLanguage(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("displayname")) {
+ setAttributeDisplayname(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("stdsetdef")) {
+ setAttributeStdsetdef(attribute.value().toString().toInt());
+ continue;
+ }
+ if (name == QLatin1String("stdSetDef")) {
+ setAttributeStdSetDef(attribute.value().toString().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("author")) {
+ setElementAuthor(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("comment")) {
+ setElementComment(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("exportmacro")) {
+ setElementExportMacro(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("class")) {
+ setElementClass(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("widget")) {
+ DomWidget *v = new DomWidget();
+ v->read(reader);
+ setElementWidget(v);
+ continue;
+ }
+ if (tag == QLatin1String("layoutdefault")) {
+ DomLayoutDefault *v = new DomLayoutDefault();
+ v->read(reader);
+ setElementLayoutDefault(v);
+ continue;
+ }
+ if (tag == QLatin1String("layoutfunction")) {
+ DomLayoutFunction *v = new DomLayoutFunction();
+ v->read(reader);
+ setElementLayoutFunction(v);
+ continue;
+ }
+ if (tag == QLatin1String("pixmapfunction")) {
+ setElementPixmapFunction(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("customwidgets")) {
+ DomCustomWidgets *v = new DomCustomWidgets();
+ v->read(reader);
+ setElementCustomWidgets(v);
+ continue;
+ }
+ if (tag == QLatin1String("tabstops")) {
+ DomTabStops *v = new DomTabStops();
+ v->read(reader);
+ setElementTabStops(v);
+ continue;
+ }
+ if (tag == QLatin1String("images")) {
+ DomImages *v = new DomImages();
+ v->read(reader);
+ setElementImages(v);
+ continue;
+ }
+ if (tag == QLatin1String("includes")) {
+ DomIncludes *v = new DomIncludes();
+ v->read(reader);
+ setElementIncludes(v);
+ continue;
+ }
+ if (tag == QLatin1String("resources")) {
+ DomResources *v = new DomResources();
+ v->read(reader);
+ setElementResources(v);
+ continue;
+ }
+ if (tag == QLatin1String("connections")) {
+ DomConnections *v = new DomConnections();
+ v->read(reader);
+ setElementConnections(v);
+ continue;
+ }
+ if (tag == QLatin1String("designerdata")) {
+ DomDesignerData *v = new DomDesignerData();
+ v->read(reader);
+ setElementDesignerdata(v);
+ continue;
+ }
+ if (tag == QLatin1String("slots")) {
+ DomSlots *v = new DomSlots();
+ v->read(reader);
+ setElementSlots(v);
+ continue;
+ }
+ if (tag == QLatin1String("buttongroups")) {
+ DomButtonGroups *v = new DomButtonGroups();
+ v->read(reader);
+ setElementButtonGroups(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomUI::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("version")))
+ setAttributeVersion(node.attribute(QLatin1String("version")));
+ if (node.hasAttribute(QLatin1String("language")))
+ setAttributeLanguage(node.attribute(QLatin1String("language")));
+ if (node.hasAttribute(QLatin1String("displayname")))
+ setAttributeDisplayname(node.attribute(QLatin1String("displayname")));
+ if (node.hasAttribute(QLatin1String("stdsetdef")))
+ setAttributeStdsetdef(node.attribute(QLatin1String("stdsetdef")).toInt());
+ if (node.hasAttribute(QLatin1String("stdSetDef")))
+ setAttributeStdSetDef(node.attribute(QLatin1String("stdSetDef")).toInt());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("author")) {
+ setElementAuthor(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("comment")) {
+ setElementComment(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("exportmacro")) {
+ setElementExportMacro(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("class")) {
+ setElementClass(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("widget")) {
+ DomWidget *v = new DomWidget();
+ v->read(e);
+ setElementWidget(v);
+ continue;
+ }
+ if (tag == QLatin1String("layoutdefault")) {
+ DomLayoutDefault *v = new DomLayoutDefault();
+ v->read(e);
+ setElementLayoutDefault(v);
+ continue;
+ }
+ if (tag == QLatin1String("layoutfunction")) {
+ DomLayoutFunction *v = new DomLayoutFunction();
+ v->read(e);
+ setElementLayoutFunction(v);
+ continue;
+ }
+ if (tag == QLatin1String("pixmapfunction")) {
+ setElementPixmapFunction(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("customwidgets")) {
+ DomCustomWidgets *v = new DomCustomWidgets();
+ v->read(e);
+ setElementCustomWidgets(v);
+ continue;
+ }
+ if (tag == QLatin1String("tabstops")) {
+ DomTabStops *v = new DomTabStops();
+ v->read(e);
+ setElementTabStops(v);
+ continue;
+ }
+ if (tag == QLatin1String("images")) {
+ DomImages *v = new DomImages();
+ v->read(e);
+ setElementImages(v);
+ continue;
+ }
+ if (tag == QLatin1String("includes")) {
+ DomIncludes *v = new DomIncludes();
+ v->read(e);
+ setElementIncludes(v);
+ continue;
+ }
+ if (tag == QLatin1String("resources")) {
+ DomResources *v = new DomResources();
+ v->read(e);
+ setElementResources(v);
+ continue;
+ }
+ if (tag == QLatin1String("connections")) {
+ DomConnections *v = new DomConnections();
+ v->read(e);
+ setElementConnections(v);
+ continue;
+ }
+ if (tag == QLatin1String("designerdata")) {
+ DomDesignerData *v = new DomDesignerData();
+ v->read(e);
+ setElementDesignerdata(v);
+ continue;
+ }
+ if (tag == QLatin1String("slots")) {
+ DomSlots *v = new DomSlots();
+ v->read(e);
+ setElementSlots(v);
+ continue;
+ }
+ if (tag == QLatin1String("buttongroups")) {
+ DomButtonGroups *v = new DomButtonGroups();
+ v->read(e);
+ setElementButtonGroups(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomUI::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("ui") : tagName.toLower());
+
+ if (hasAttributeVersion())
+ writer.writeAttribute(QLatin1String("version"), attributeVersion());
+
+ if (hasAttributeLanguage())
+ writer.writeAttribute(QLatin1String("language"), attributeLanguage());
+
+ if (hasAttributeDisplayname())
+ writer.writeAttribute(QLatin1String("displayname"), attributeDisplayname());
+
+ if (hasAttributeStdsetdef())
+ writer.writeAttribute(QLatin1String("stdsetdef"), QString::number(attributeStdsetdef()));
+
+ if (hasAttributeStdSetDef())
+ writer.writeAttribute(QLatin1String("stdsetdef"), QString::number(attributeStdSetDef()));
+
+ if (m_children & Author) {
+ writer.writeTextElement(QLatin1String("author"), m_author);
+ }
+
+ if (m_children & Comment) {
+ writer.writeTextElement(QLatin1String("comment"), m_comment);
+ }
+
+ if (m_children & ExportMacro) {
+ writer.writeTextElement(QLatin1String("exportmacro"), m_exportMacro);
+ }
+
+ if (m_children & Class) {
+ writer.writeTextElement(QLatin1String("class"), m_class);
+ }
+
+ if (m_children & Widget) {
+ m_widget->write(writer, QLatin1String("widget"));
+ }
+
+ if (m_children & LayoutDefault) {
+ m_layoutDefault->write(writer, QLatin1String("layoutdefault"));
+ }
+
+ if (m_children & LayoutFunction) {
+ m_layoutFunction->write(writer, QLatin1String("layoutfunction"));
+ }
+
+ if (m_children & PixmapFunction) {
+ writer.writeTextElement(QLatin1String("pixmapfunction"), m_pixmapFunction);
+ }
+
+ if (m_children & CustomWidgets) {
+ m_customWidgets->write(writer, QLatin1String("customwidgets"));
+ }
+
+ if (m_children & TabStops) {
+ m_tabStops->write(writer, QLatin1String("tabstops"));
+ }
+
+ if (m_children & Images) {
+ m_images->write(writer, QLatin1String("images"));
+ }
+
+ if (m_children & Includes) {
+ m_includes->write(writer, QLatin1String("includes"));
+ }
+
+ if (m_children & Resources) {
+ m_resources->write(writer, QLatin1String("resources"));
+ }
+
+ if (m_children & Connections) {
+ m_connections->write(writer, QLatin1String("connections"));
+ }
+
+ if (m_children & Designerdata) {
+ m_designerdata->write(writer, QLatin1String("designerdata"));
+ }
+
+ if (m_children & Slots) {
+ m_slots->write(writer, QLatin1String("slots"));
+ }
+
+ if (m_children & ButtonGroups) {
+ m_buttonGroups->write(writer, QLatin1String("buttongroups"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomUI::setElementAuthor(const QString& a)
+{
+ m_children |= Author;
+ m_author = a;
+}
+
+void DomUI::setElementComment(const QString& a)
+{
+ m_children |= Comment;
+ m_comment = a;
+}
+
+void DomUI::setElementExportMacro(const QString& a)
+{
+ m_children |= ExportMacro;
+ m_exportMacro = a;
+}
+
+void DomUI::setElementClass(const QString& a)
+{
+ m_children |= Class;
+ m_class = a;
+}
+
+DomWidget* DomUI::takeElementWidget()
+{
+ DomWidget* a = m_widget;
+ m_widget = 0;
+ m_children ^= Widget;
+ return a;
+}
+
+void DomUI::setElementWidget(DomWidget* a)
+{
+ delete m_widget;
+ m_children |= Widget;
+ m_widget = a;
+}
+
+DomLayoutDefault* DomUI::takeElementLayoutDefault()
+{
+ DomLayoutDefault* a = m_layoutDefault;
+ m_layoutDefault = 0;
+ m_children ^= LayoutDefault;
+ return a;
+}
+
+void DomUI::setElementLayoutDefault(DomLayoutDefault* a)
+{
+ delete m_layoutDefault;
+ m_children |= LayoutDefault;
+ m_layoutDefault = a;
+}
+
+DomLayoutFunction* DomUI::takeElementLayoutFunction()
+{
+ DomLayoutFunction* a = m_layoutFunction;
+ m_layoutFunction = 0;
+ m_children ^= LayoutFunction;
+ return a;
+}
+
+void DomUI::setElementLayoutFunction(DomLayoutFunction* a)
+{
+ delete m_layoutFunction;
+ m_children |= LayoutFunction;
+ m_layoutFunction = a;
+}
+
+void DomUI::setElementPixmapFunction(const QString& a)
+{
+ m_children |= PixmapFunction;
+ m_pixmapFunction = a;
+}
+
+DomCustomWidgets* DomUI::takeElementCustomWidgets()
+{
+ DomCustomWidgets* a = m_customWidgets;
+ m_customWidgets = 0;
+ m_children ^= CustomWidgets;
+ return a;
+}
+
+void DomUI::setElementCustomWidgets(DomCustomWidgets* a)
+{
+ delete m_customWidgets;
+ m_children |= CustomWidgets;
+ m_customWidgets = a;
+}
+
+DomTabStops* DomUI::takeElementTabStops()
+{
+ DomTabStops* a = m_tabStops;
+ m_tabStops = 0;
+ m_children ^= TabStops;
+ return a;
+}
+
+void DomUI::setElementTabStops(DomTabStops* a)
+{
+ delete m_tabStops;
+ m_children |= TabStops;
+ m_tabStops = a;
+}
+
+DomImages* DomUI::takeElementImages()
+{
+ DomImages* a = m_images;
+ m_images = 0;
+ m_children ^= Images;
+ return a;
+}
+
+void DomUI::setElementImages(DomImages* a)
+{
+ delete m_images;
+ m_children |= Images;
+ m_images = a;
+}
+
+DomIncludes* DomUI::takeElementIncludes()
+{
+ DomIncludes* a = m_includes;
+ m_includes = 0;
+ m_children ^= Includes;
+ return a;
+}
+
+void DomUI::setElementIncludes(DomIncludes* a)
+{
+ delete m_includes;
+ m_children |= Includes;
+ m_includes = a;
+}
+
+DomResources* DomUI::takeElementResources()
+{
+ DomResources* a = m_resources;
+ m_resources = 0;
+ m_children ^= Resources;
+ return a;
+}
+
+void DomUI::setElementResources(DomResources* a)
+{
+ delete m_resources;
+ m_children |= Resources;
+ m_resources = a;
+}
+
+DomConnections* DomUI::takeElementConnections()
+{
+ DomConnections* a = m_connections;
+ m_connections = 0;
+ m_children ^= Connections;
+ return a;
+}
+
+void DomUI::setElementConnections(DomConnections* a)
+{
+ delete m_connections;
+ m_children |= Connections;
+ m_connections = a;
+}
+
+DomDesignerData* DomUI::takeElementDesignerdata()
+{
+ DomDesignerData* a = m_designerdata;
+ m_designerdata = 0;
+ m_children ^= Designerdata;
+ return a;
+}
+
+void DomUI::setElementDesignerdata(DomDesignerData* a)
+{
+ delete m_designerdata;
+ m_children |= Designerdata;
+ m_designerdata = a;
+}
+
+DomSlots* DomUI::takeElementSlots()
+{
+ DomSlots* a = m_slots;
+ m_slots = 0;
+ m_children ^= Slots;
+ return a;
+}
+
+void DomUI::setElementSlots(DomSlots* a)
+{
+ delete m_slots;
+ m_children |= Slots;
+ m_slots = a;
+}
+
+DomButtonGroups* DomUI::takeElementButtonGroups()
+{
+ DomButtonGroups* a = m_buttonGroups;
+ m_buttonGroups = 0;
+ m_children ^= ButtonGroups;
+ return a;
+}
+
+void DomUI::setElementButtonGroups(DomButtonGroups* a)
+{
+ delete m_buttonGroups;
+ m_children |= ButtonGroups;
+ m_buttonGroups = a;
+}
+
+void DomUI::clearElementAuthor()
+{
+ m_children &= ~Author;
+}
+
+void DomUI::clearElementComment()
+{
+ m_children &= ~Comment;
+}
+
+void DomUI::clearElementExportMacro()
+{
+ m_children &= ~ExportMacro;
+}
+
+void DomUI::clearElementClass()
+{
+ m_children &= ~Class;
+}
+
+void DomUI::clearElementWidget()
+{
+ delete m_widget;
+ m_widget = 0;
+ m_children &= ~Widget;
+}
+
+void DomUI::clearElementLayoutDefault()
+{
+ delete m_layoutDefault;
+ m_layoutDefault = 0;
+ m_children &= ~LayoutDefault;
+}
+
+void DomUI::clearElementLayoutFunction()
+{
+ delete m_layoutFunction;
+ m_layoutFunction = 0;
+ m_children &= ~LayoutFunction;
+}
+
+void DomUI::clearElementPixmapFunction()
+{
+ m_children &= ~PixmapFunction;
+}
+
+void DomUI::clearElementCustomWidgets()
+{
+ delete m_customWidgets;
+ m_customWidgets = 0;
+ m_children &= ~CustomWidgets;
+}
+
+void DomUI::clearElementTabStops()
+{
+ delete m_tabStops;
+ m_tabStops = 0;
+ m_children &= ~TabStops;
+}
+
+void DomUI::clearElementImages()
+{
+ delete m_images;
+ m_images = 0;
+ m_children &= ~Images;
+}
+
+void DomUI::clearElementIncludes()
+{
+ delete m_includes;
+ m_includes = 0;
+ m_children &= ~Includes;
+}
+
+void DomUI::clearElementResources()
+{
+ delete m_resources;
+ m_resources = 0;
+ m_children &= ~Resources;
+}
+
+void DomUI::clearElementConnections()
+{
+ delete m_connections;
+ m_connections = 0;
+ m_children &= ~Connections;
+}
+
+void DomUI::clearElementDesignerdata()
+{
+ delete m_designerdata;
+ m_designerdata = 0;
+ m_children &= ~Designerdata;
+}
+
+void DomUI::clearElementSlots()
+{
+ delete m_slots;
+ m_slots = 0;
+ m_children &= ~Slots;
+}
+
+void DomUI::clearElementButtonGroups()
+{
+ delete m_buttonGroups;
+ m_buttonGroups = 0;
+ m_children &= ~ButtonGroups;
+}
+
+void DomIncludes::clear(bool clear_all)
+{
+ qDeleteAll(m_include);
+ m_include.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomIncludes::DomIncludes()
+{
+ m_children = 0;
+}
+
+DomIncludes::~DomIncludes()
+{
+ qDeleteAll(m_include);
+ m_include.clear();
+}
+
+void DomIncludes::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("include")) {
+ DomInclude *v = new DomInclude();
+ v->read(reader);
+ m_include.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomIncludes::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("include")) {
+ DomInclude *v = new DomInclude();
+ v->read(e);
+ m_include.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomIncludes::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("includes") : tagName.toLower());
+
+ for (int i = 0; i < m_include.size(); ++i) {
+ DomInclude* v = m_include[i];
+ v->write(writer, QLatin1String("include"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomIncludes::setElementInclude(const QList<DomInclude*>& a)
+{
+ m_children |= Include;
+ m_include = a;
+}
+
+void DomInclude::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text = QLatin1String("");
+ m_has_attr_location = false;
+ m_has_attr_impldecl = false;
+ }
+
+ m_children = 0;
+}
+
+DomInclude::DomInclude()
+{
+ m_children = 0;
+ m_has_attr_location = false;
+ m_has_attr_impldecl = false;
+ m_text = QLatin1String("");
+}
+
+DomInclude::~DomInclude()
+{
+}
+
+void DomInclude::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("location")) {
+ setAttributeLocation(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("impldecl")) {
+ setAttributeImpldecl(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomInclude::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("location")))
+ setAttributeLocation(node.attribute(QLatin1String("location")));
+ if (node.hasAttribute(QLatin1String("impldecl")))
+ setAttributeImpldecl(node.attribute(QLatin1String("impldecl")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text = QLatin1String("");
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomInclude::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("include") : tagName.toLower());
+
+ if (hasAttributeLocation())
+ writer.writeAttribute(QLatin1String("location"), attributeLocation());
+
+ if (hasAttributeImpldecl())
+ writer.writeAttribute(QLatin1String("impldecl"), attributeImpldecl());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomResources::clear(bool clear_all)
+{
+ qDeleteAll(m_include);
+ m_include.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ }
+
+ m_children = 0;
+}
+
+DomResources::DomResources()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+}
+
+DomResources::~DomResources()
+{
+ qDeleteAll(m_include);
+ m_include.clear();
+}
+
+void DomResources::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("include")) {
+ DomResource *v = new DomResource();
+ v->read(reader);
+ m_include.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomResources::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("include")) {
+ DomResource *v = new DomResource();
+ v->read(e);
+ m_include.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomResources::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resources") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ for (int i = 0; i < m_include.size(); ++i) {
+ DomResource* v = m_include[i];
+ v->write(writer, QLatin1String("include"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomResources::setElementInclude(const QList<DomResource*>& a)
+{
+ m_children |= Include;
+ m_include = a;
+}
+
+void DomResource::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_location = false;
+ }
+
+ m_children = 0;
+}
+
+DomResource::DomResource()
+{
+ m_children = 0;
+ m_has_attr_location = false;
+}
+
+DomResource::~DomResource()
+{
+}
+
+void DomResource::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("location")) {
+ setAttributeLocation(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomResource::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("location")))
+ setAttributeLocation(node.attribute(QLatin1String("location")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomResource::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resource") : tagName.toLower());
+
+ if (hasAttributeLocation())
+ writer.writeAttribute(QLatin1String("location"), attributeLocation());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomActionGroup::clear(bool clear_all)
+{
+ qDeleteAll(m_action);
+ m_action.clear();
+ qDeleteAll(m_actionGroup);
+ m_actionGroup.clear();
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ }
+
+ m_children = 0;
+}
+
+DomActionGroup::DomActionGroup()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+}
+
+DomActionGroup::~DomActionGroup()
+{
+ qDeleteAll(m_action);
+ m_action.clear();
+ qDeleteAll(m_actionGroup);
+ m_actionGroup.clear();
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+}
+
+void DomActionGroup::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("action")) {
+ DomAction *v = new DomAction();
+ v->read(reader);
+ m_action.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("actiongroup")) {
+ DomActionGroup *v = new DomActionGroup();
+ v->read(reader);
+ m_actionGroup.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_attribute.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomActionGroup::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("action")) {
+ DomAction *v = new DomAction();
+ v->read(e);
+ m_action.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("actiongroup")) {
+ DomActionGroup *v = new DomActionGroup();
+ v->read(e);
+ m_actionGroup.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_attribute.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomActionGroup::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("actiongroup") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ for (int i = 0; i < m_action.size(); ++i) {
+ DomAction* v = m_action[i];
+ v->write(writer, QLatin1String("action"));
+ }
+ for (int i = 0; i < m_actionGroup.size(); ++i) {
+ DomActionGroup* v = m_actionGroup[i];
+ v->write(writer, QLatin1String("actiongroup"));
+ }
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ for (int i = 0; i < m_attribute.size(); ++i) {
+ DomProperty* v = m_attribute[i];
+ v->write(writer, QLatin1String("attribute"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomActionGroup::setElementAction(const QList<DomAction*>& a)
+{
+ m_children |= Action;
+ m_action = a;
+}
+
+void DomActionGroup::setElementActionGroup(const QList<DomActionGroup*>& a)
+{
+ m_children |= ActionGroup;
+ m_actionGroup = a;
+}
+
+void DomActionGroup::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomActionGroup::setElementAttribute(const QList<DomProperty*>& a)
+{
+ m_children |= Attribute;
+ m_attribute = a;
+}
+
+void DomAction::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ m_has_attr_menu = false;
+ }
+
+ m_children = 0;
+}
+
+DomAction::DomAction()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+ m_has_attr_menu = false;
+}
+
+DomAction::~DomAction()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+}
+
+void DomAction::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("menu")) {
+ setAttributeMenu(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_attribute.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomAction::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+ if (node.hasAttribute(QLatin1String("menu")))
+ setAttributeMenu(node.attribute(QLatin1String("menu")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_attribute.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomAction::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("action") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ if (hasAttributeMenu())
+ writer.writeAttribute(QLatin1String("menu"), attributeMenu());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ for (int i = 0; i < m_attribute.size(); ++i) {
+ DomProperty* v = m_attribute[i];
+ v->write(writer, QLatin1String("attribute"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomAction::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomAction::setElementAttribute(const QList<DomProperty*>& a)
+{
+ m_children |= Attribute;
+ m_attribute = a;
+}
+
+void DomActionRef::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ }
+
+ m_children = 0;
+}
+
+DomActionRef::DomActionRef()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+}
+
+DomActionRef::~DomActionRef()
+{
+}
+
+void DomActionRef::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomActionRef::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomActionRef::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("actionref") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomButtonGroup::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ }
+
+ m_children = 0;
+}
+
+DomButtonGroup::DomButtonGroup()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+}
+
+DomButtonGroup::~DomButtonGroup()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+}
+
+void DomButtonGroup::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_attribute.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomButtonGroup::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_attribute.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomButtonGroup::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("buttongroup") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ for (int i = 0; i < m_attribute.size(); ++i) {
+ DomProperty* v = m_attribute[i];
+ v->write(writer, QLatin1String("attribute"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomButtonGroup::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomButtonGroup::setElementAttribute(const QList<DomProperty*>& a)
+{
+ m_children |= Attribute;
+ m_attribute = a;
+}
+
+void DomButtonGroups::clear(bool clear_all)
+{
+ qDeleteAll(m_buttonGroup);
+ m_buttonGroup.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomButtonGroups::DomButtonGroups()
+{
+ m_children = 0;
+}
+
+DomButtonGroups::~DomButtonGroups()
+{
+ qDeleteAll(m_buttonGroup);
+ m_buttonGroup.clear();
+}
+
+void DomButtonGroups::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("buttongroup")) {
+ DomButtonGroup *v = new DomButtonGroup();
+ v->read(reader);
+ m_buttonGroup.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomButtonGroups::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("buttongroup")) {
+ DomButtonGroup *v = new DomButtonGroup();
+ v->read(e);
+ m_buttonGroup.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomButtonGroups::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("buttongroups") : tagName.toLower());
+
+ for (int i = 0; i < m_buttonGroup.size(); ++i) {
+ DomButtonGroup* v = m_buttonGroup[i];
+ v->write(writer, QLatin1String("buttongroup"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomButtonGroups::setElementButtonGroup(const QList<DomButtonGroup*>& a)
+{
+ m_children |= ButtonGroup;
+ m_buttonGroup = a;
+}
+
+void DomImages::clear(bool clear_all)
+{
+ qDeleteAll(m_image);
+ m_image.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomImages::DomImages()
+{
+ m_children = 0;
+}
+
+DomImages::~DomImages()
+{
+ qDeleteAll(m_image);
+ m_image.clear();
+}
+
+void DomImages::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("image")) {
+ DomImage *v = new DomImage();
+ v->read(reader);
+ m_image.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomImages::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("image")) {
+ DomImage *v = new DomImage();
+ v->read(e);
+ m_image.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomImages::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("images") : tagName.toLower());
+
+ for (int i = 0; i < m_image.size(); ++i) {
+ DomImage* v = m_image[i];
+ v->write(writer, QLatin1String("image"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomImages::setElementImage(const QList<DomImage*>& a)
+{
+ m_children |= Image;
+ m_image = a;
+}
+
+void DomImage::clear(bool clear_all)
+{
+ delete m_data;
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ }
+
+ m_children = 0;
+ m_data = 0;
+}
+
+DomImage::DomImage()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+ m_data = 0;
+}
+
+DomImage::~DomImage()
+{
+ delete m_data;
+}
+
+void DomImage::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("data")) {
+ DomImageData *v = new DomImageData();
+ v->read(reader);
+ setElementData(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomImage::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("data")) {
+ DomImageData *v = new DomImageData();
+ v->read(e);
+ setElementData(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomImage::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("image") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ if (m_children & Data) {
+ m_data->write(writer, QLatin1String("data"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomImageData* DomImage::takeElementData()
+{
+ DomImageData* a = m_data;
+ m_data = 0;
+ m_children ^= Data;
+ return a;
+}
+
+void DomImage::setElementData(DomImageData* a)
+{
+ delete m_data;
+ m_children |= Data;
+ m_data = a;
+}
+
+void DomImage::clearElementData()
+{
+ delete m_data;
+ m_data = 0;
+ m_children &= ~Data;
+}
+
+void DomImageData::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text = QLatin1String("");
+ m_has_attr_format = false;
+ m_has_attr_length = false;
+ m_attr_length = 0;
+ }
+
+ m_children = 0;
+}
+
+DomImageData::DomImageData()
+{
+ m_children = 0;
+ m_has_attr_format = false;
+ m_has_attr_length = false;
+ m_attr_length = 0;
+ m_text = QLatin1String("");
+}
+
+DomImageData::~DomImageData()
+{
+}
+
+void DomImageData::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("format")) {
+ setAttributeFormat(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("length")) {
+ setAttributeLength(attribute.value().toString().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomImageData::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("format")))
+ setAttributeFormat(node.attribute(QLatin1String("format")));
+ if (node.hasAttribute(QLatin1String("length")))
+ setAttributeLength(node.attribute(QLatin1String("length")).toInt());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text = QLatin1String("");
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomImageData::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("imagedata") : tagName.toLower());
+
+ if (hasAttributeFormat())
+ writer.writeAttribute(QLatin1String("format"), attributeFormat());
+
+ if (hasAttributeLength())
+ writer.writeAttribute(QLatin1String("length"), QString::number(attributeLength()));
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomCustomWidgets::clear(bool clear_all)
+{
+ qDeleteAll(m_customWidget);
+ m_customWidget.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomCustomWidgets::DomCustomWidgets()
+{
+ m_children = 0;
+}
+
+DomCustomWidgets::~DomCustomWidgets()
+{
+ qDeleteAll(m_customWidget);
+ m_customWidget.clear();
+}
+
+void DomCustomWidgets::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("customwidget")) {
+ DomCustomWidget *v = new DomCustomWidget();
+ v->read(reader);
+ m_customWidget.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomCustomWidgets::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("customwidget")) {
+ DomCustomWidget *v = new DomCustomWidget();
+ v->read(e);
+ m_customWidget.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomCustomWidgets::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("customwidgets") : tagName.toLower());
+
+ for (int i = 0; i < m_customWidget.size(); ++i) {
+ DomCustomWidget* v = m_customWidget[i];
+ v->write(writer, QLatin1String("customwidget"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomCustomWidgets::setElementCustomWidget(const QList<DomCustomWidget*>& a)
+{
+ m_children |= CustomWidget;
+ m_customWidget = a;
+}
+
+void DomHeader::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text = QLatin1String("");
+ m_has_attr_location = false;
+ }
+
+ m_children = 0;
+}
+
+DomHeader::DomHeader()
+{
+ m_children = 0;
+ m_has_attr_location = false;
+ m_text = QLatin1String("");
+}
+
+DomHeader::~DomHeader()
+{
+}
+
+void DomHeader::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("location")) {
+ setAttributeLocation(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomHeader::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("location")))
+ setAttributeLocation(node.attribute(QLatin1String("location")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text = QLatin1String("");
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomHeader::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("header") : tagName.toLower());
+
+ if (hasAttributeLocation())
+ writer.writeAttribute(QLatin1String("location"), attributeLocation());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomCustomWidget::clear(bool clear_all)
+{
+ delete m_header;
+ delete m_sizeHint;
+ delete m_sizePolicy;
+ delete m_script;
+ delete m_properties;
+ delete m_slots;
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_header = 0;
+ m_sizeHint = 0;
+ m_container = 0;
+ m_sizePolicy = 0;
+ m_script = 0;
+ m_properties = 0;
+ m_slots = 0;
+}
+
+DomCustomWidget::DomCustomWidget()
+{
+ m_children = 0;
+ m_header = 0;
+ m_sizeHint = 0;
+ m_container = 0;
+ m_sizePolicy = 0;
+ m_script = 0;
+ m_properties = 0;
+ m_slots = 0;
+}
+
+DomCustomWidget::~DomCustomWidget()
+{
+ delete m_header;
+ delete m_sizeHint;
+ delete m_sizePolicy;
+ delete m_script;
+ delete m_properties;
+ delete m_slots;
+}
+
+void DomCustomWidget::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("class")) {
+ setElementClass(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("extends")) {
+ setElementExtends(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("header")) {
+ DomHeader *v = new DomHeader();
+ v->read(reader);
+ setElementHeader(v);
+ continue;
+ }
+ if (tag == QLatin1String("sizehint")) {
+ DomSize *v = new DomSize();
+ v->read(reader);
+ setElementSizeHint(v);
+ continue;
+ }
+ if (tag == QLatin1String("addpagemethod")) {
+ setElementAddPageMethod(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("container")) {
+ setElementContainer(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("sizepolicy")) {
+ DomSizePolicyData *v = new DomSizePolicyData();
+ v->read(reader);
+ setElementSizePolicy(v);
+ continue;
+ }
+ if (tag == QLatin1String("pixmap")) {
+ setElementPixmap(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("script")) {
+ DomScript *v = new DomScript();
+ v->read(reader);
+ setElementScript(v);
+ continue;
+ }
+ if (tag == QLatin1String("properties")) {
+ DomProperties *v = new DomProperties();
+ v->read(reader);
+ setElementProperties(v);
+ continue;
+ }
+ if (tag == QLatin1String("slots")) {
+ DomSlots *v = new DomSlots();
+ v->read(reader);
+ setElementSlots(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomCustomWidget::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("class")) {
+ setElementClass(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("extends")) {
+ setElementExtends(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("header")) {
+ DomHeader *v = new DomHeader();
+ v->read(e);
+ setElementHeader(v);
+ continue;
+ }
+ if (tag == QLatin1String("sizehint")) {
+ DomSize *v = new DomSize();
+ v->read(e);
+ setElementSizeHint(v);
+ continue;
+ }
+ if (tag == QLatin1String("addpagemethod")) {
+ setElementAddPageMethod(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("container")) {
+ setElementContainer(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("sizepolicy")) {
+ DomSizePolicyData *v = new DomSizePolicyData();
+ v->read(e);
+ setElementSizePolicy(v);
+ continue;
+ }
+ if (tag == QLatin1String("pixmap")) {
+ setElementPixmap(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("script")) {
+ DomScript *v = new DomScript();
+ v->read(e);
+ setElementScript(v);
+ continue;
+ }
+ if (tag == QLatin1String("properties")) {
+ DomProperties *v = new DomProperties();
+ v->read(e);
+ setElementProperties(v);
+ continue;
+ }
+ if (tag == QLatin1String("slots")) {
+ DomSlots *v = new DomSlots();
+ v->read(e);
+ setElementSlots(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomCustomWidget::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("customwidget") : tagName.toLower());
+
+ if (m_children & Class) {
+ writer.writeTextElement(QLatin1String("class"), m_class);
+ }
+
+ if (m_children & Extends) {
+ writer.writeTextElement(QLatin1String("extends"), m_extends);
+ }
+
+ if (m_children & Header) {
+ m_header->write(writer, QLatin1String("header"));
+ }
+
+ if (m_children & SizeHint) {
+ m_sizeHint->write(writer, QLatin1String("sizehint"));
+ }
+
+ if (m_children & AddPageMethod) {
+ writer.writeTextElement(QLatin1String("addpagemethod"), m_addPageMethod);
+ }
+
+ if (m_children & Container) {
+ writer.writeTextElement(QLatin1String("container"), QString::number(m_container));
+ }
+
+ if (m_children & SizePolicy) {
+ m_sizePolicy->write(writer, QLatin1String("sizepolicy"));
+ }
+
+ if (m_children & Pixmap) {
+ writer.writeTextElement(QLatin1String("pixmap"), m_pixmap);
+ }
+
+ if (m_children & Script) {
+ m_script->write(writer, QLatin1String("script"));
+ }
+
+ if (m_children & Properties) {
+ m_properties->write(writer, QLatin1String("properties"));
+ }
+
+ if (m_children & Slots) {
+ m_slots->write(writer, QLatin1String("slots"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomCustomWidget::setElementClass(const QString& a)
+{
+ m_children |= Class;
+ m_class = a;
+}
+
+void DomCustomWidget::setElementExtends(const QString& a)
+{
+ m_children |= Extends;
+ m_extends = a;
+}
+
+DomHeader* DomCustomWidget::takeElementHeader()
+{
+ DomHeader* a = m_header;
+ m_header = 0;
+ m_children ^= Header;
+ return a;
+}
+
+void DomCustomWidget::setElementHeader(DomHeader* a)
+{
+ delete m_header;
+ m_children |= Header;
+ m_header = a;
+}
+
+DomSize* DomCustomWidget::takeElementSizeHint()
+{
+ DomSize* a = m_sizeHint;
+ m_sizeHint = 0;
+ m_children ^= SizeHint;
+ return a;
+}
+
+void DomCustomWidget::setElementSizeHint(DomSize* a)
+{
+ delete m_sizeHint;
+ m_children |= SizeHint;
+ m_sizeHint = a;
+}
+
+void DomCustomWidget::setElementAddPageMethod(const QString& a)
+{
+ m_children |= AddPageMethod;
+ m_addPageMethod = a;
+}
+
+void DomCustomWidget::setElementContainer(int a)
+{
+ m_children |= Container;
+ m_container = a;
+}
+
+DomSizePolicyData* DomCustomWidget::takeElementSizePolicy()
+{
+ DomSizePolicyData* a = m_sizePolicy;
+ m_sizePolicy = 0;
+ m_children ^= SizePolicy;
+ return a;
+}
+
+void DomCustomWidget::setElementSizePolicy(DomSizePolicyData* a)
+{
+ delete m_sizePolicy;
+ m_children |= SizePolicy;
+ m_sizePolicy = a;
+}
+
+void DomCustomWidget::setElementPixmap(const QString& a)
+{
+ m_children |= Pixmap;
+ m_pixmap = a;
+}
+
+DomScript* DomCustomWidget::takeElementScript()
+{
+ DomScript* a = m_script;
+ m_script = 0;
+ m_children ^= Script;
+ return a;
+}
+
+void DomCustomWidget::setElementScript(DomScript* a)
+{
+ delete m_script;
+ m_children |= Script;
+ m_script = a;
+}
+
+DomProperties* DomCustomWidget::takeElementProperties()
+{
+ DomProperties* a = m_properties;
+ m_properties = 0;
+ m_children ^= Properties;
+ return a;
+}
+
+void DomCustomWidget::setElementProperties(DomProperties* a)
+{
+ delete m_properties;
+ m_children |= Properties;
+ m_properties = a;
+}
+
+DomSlots* DomCustomWidget::takeElementSlots()
+{
+ DomSlots* a = m_slots;
+ m_slots = 0;
+ m_children ^= Slots;
+ return a;
+}
+
+void DomCustomWidget::setElementSlots(DomSlots* a)
+{
+ delete m_slots;
+ m_children |= Slots;
+ m_slots = a;
+}
+
+void DomCustomWidget::clearElementClass()
+{
+ m_children &= ~Class;
+}
+
+void DomCustomWidget::clearElementExtends()
+{
+ m_children &= ~Extends;
+}
+
+void DomCustomWidget::clearElementHeader()
+{
+ delete m_header;
+ m_header = 0;
+ m_children &= ~Header;
+}
+
+void DomCustomWidget::clearElementSizeHint()
+{
+ delete m_sizeHint;
+ m_sizeHint = 0;
+ m_children &= ~SizeHint;
+}
+
+void DomCustomWidget::clearElementAddPageMethod()
+{
+ m_children &= ~AddPageMethod;
+}
+
+void DomCustomWidget::clearElementContainer()
+{
+ m_children &= ~Container;
+}
+
+void DomCustomWidget::clearElementSizePolicy()
+{
+ delete m_sizePolicy;
+ m_sizePolicy = 0;
+ m_children &= ~SizePolicy;
+}
+
+void DomCustomWidget::clearElementPixmap()
+{
+ m_children &= ~Pixmap;
+}
+
+void DomCustomWidget::clearElementScript()
+{
+ delete m_script;
+ m_script = 0;
+ m_children &= ~Script;
+}
+
+void DomCustomWidget::clearElementProperties()
+{
+ delete m_properties;
+ m_properties = 0;
+ m_children &= ~Properties;
+}
+
+void DomCustomWidget::clearElementSlots()
+{
+ delete m_slots;
+ m_slots = 0;
+ m_children &= ~Slots;
+}
+
+void DomProperties::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomProperties::DomProperties()
+{
+ m_children = 0;
+}
+
+DomProperties::~DomProperties()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+}
+
+void DomProperties::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomPropertyData *v = new DomPropertyData();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomProperties::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomPropertyData *v = new DomPropertyData();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomProperties::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("properties") : tagName.toLower());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomPropertyData* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomProperties::setElementProperty(const QList<DomPropertyData*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomPropertyData::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_type = false;
+ }
+
+ m_children = 0;
+}
+
+DomPropertyData::DomPropertyData()
+{
+ m_children = 0;
+ m_has_attr_type = false;
+}
+
+DomPropertyData::~DomPropertyData()
+{
+}
+
+void DomPropertyData::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("type")) {
+ setAttributeType(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomPropertyData::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("type")))
+ setAttributeType(node.attribute(QLatin1String("type")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomPropertyData::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("propertydata") : tagName.toLower());
+
+ if (hasAttributeType())
+ writer.writeAttribute(QLatin1String("type"), attributeType());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSizePolicyData::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_horData = 0;
+ m_verData = 0;
+}
+
+DomSizePolicyData::DomSizePolicyData()
+{
+ m_children = 0;
+ m_horData = 0;
+ m_verData = 0;
+}
+
+DomSizePolicyData::~DomSizePolicyData()
+{
+}
+
+void DomSizePolicyData::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("hordata")) {
+ setElementHorData(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("verdata")) {
+ setElementVerData(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomSizePolicyData::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("hordata")) {
+ setElementHorData(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("verdata")) {
+ setElementVerData(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomSizePolicyData::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("sizepolicydata") : tagName.toLower());
+
+ if (m_children & HorData) {
+ writer.writeTextElement(QLatin1String("hordata"), QString::number(m_horData));
+ }
+
+ if (m_children & VerData) {
+ writer.writeTextElement(QLatin1String("verdata"), QString::number(m_verData));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSizePolicyData::setElementHorData(int a)
+{
+ m_children |= HorData;
+ m_horData = a;
+}
+
+void DomSizePolicyData::setElementVerData(int a)
+{
+ m_children |= VerData;
+ m_verData = a;
+}
+
+void DomSizePolicyData::clearElementHorData()
+{
+ m_children &= ~HorData;
+}
+
+void DomSizePolicyData::clearElementVerData()
+{
+ m_children &= ~VerData;
+}
+
+void DomLayoutDefault::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_spacing = false;
+ m_attr_spacing = 0;
+ m_has_attr_margin = false;
+ m_attr_margin = 0;
+ }
+
+ m_children = 0;
+}
+
+DomLayoutDefault::DomLayoutDefault()
+{
+ m_children = 0;
+ m_has_attr_spacing = false;
+ m_attr_spacing = 0;
+ m_has_attr_margin = false;
+ m_attr_margin = 0;
+}
+
+DomLayoutDefault::~DomLayoutDefault()
+{
+}
+
+void DomLayoutDefault::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("spacing")) {
+ setAttributeSpacing(attribute.value().toString().toInt());
+ continue;
+ }
+ if (name == QLatin1String("margin")) {
+ setAttributeMargin(attribute.value().toString().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomLayoutDefault::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("spacing")))
+ setAttributeSpacing(node.attribute(QLatin1String("spacing")).toInt());
+ if (node.hasAttribute(QLatin1String("margin")))
+ setAttributeMargin(node.attribute(QLatin1String("margin")).toInt());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomLayoutDefault::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layoutdefault") : tagName.toLower());
+
+ if (hasAttributeSpacing())
+ writer.writeAttribute(QLatin1String("spacing"), QString::number(attributeSpacing()));
+
+ if (hasAttributeMargin())
+ writer.writeAttribute(QLatin1String("margin"), QString::number(attributeMargin()));
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomLayoutFunction::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_spacing = false;
+ m_has_attr_margin = false;
+ }
+
+ m_children = 0;
+}
+
+DomLayoutFunction::DomLayoutFunction()
+{
+ m_children = 0;
+ m_has_attr_spacing = false;
+ m_has_attr_margin = false;
+}
+
+DomLayoutFunction::~DomLayoutFunction()
+{
+}
+
+void DomLayoutFunction::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("spacing")) {
+ setAttributeSpacing(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("margin")) {
+ setAttributeMargin(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomLayoutFunction::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("spacing")))
+ setAttributeSpacing(node.attribute(QLatin1String("spacing")));
+ if (node.hasAttribute(QLatin1String("margin")))
+ setAttributeMargin(node.attribute(QLatin1String("margin")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomLayoutFunction::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layoutfunction") : tagName.toLower());
+
+ if (hasAttributeSpacing())
+ writer.writeAttribute(QLatin1String("spacing"), attributeSpacing());
+
+ if (hasAttributeMargin())
+ writer.writeAttribute(QLatin1String("margin"), attributeMargin());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomTabStops::clear(bool clear_all)
+{
+ m_tabStop.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomTabStops::DomTabStops()
+{
+ m_children = 0;
+}
+
+DomTabStops::~DomTabStops()
+{
+ m_tabStop.clear();
+}
+
+void DomTabStops::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("tabstop")) {
+ m_tabStop.append(reader.readElementText());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomTabStops::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("tabstop")) {
+ m_tabStop.append(e.text());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomTabStops::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("tabstops") : tagName.toLower());
+
+ for (int i = 0; i < m_tabStop.size(); ++i) {
+ QString v = m_tabStop[i];
+ writer.writeTextElement(QLatin1String("tabstop"), v);
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomTabStops::setElementTabStop(const QStringList& a)
+{
+ m_children |= TabStop;
+ m_tabStop = a;
+}
+
+void DomLayout::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+ qDeleteAll(m_item);
+ m_item.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_class = false;
+ m_has_attr_name = false;
+ m_has_attr_stretch = false;
+ m_has_attr_rowStretch = false;
+ m_has_attr_columnStretch = false;
+ m_has_attr_rowMinimumHeight = false;
+ m_has_attr_columnMinimumWidth = false;
+ }
+
+ m_children = 0;
+}
+
+DomLayout::DomLayout()
+{
+ m_children = 0;
+ m_has_attr_class = false;
+ m_has_attr_name = false;
+ m_has_attr_stretch = false;
+ m_has_attr_rowStretch = false;
+ m_has_attr_columnStretch = false;
+ m_has_attr_rowMinimumHeight = false;
+ m_has_attr_columnMinimumWidth = false;
+}
+
+DomLayout::~DomLayout()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+ qDeleteAll(m_item);
+ m_item.clear();
+}
+
+void DomLayout::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("class")) {
+ setAttributeClass(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("stretch")) {
+ setAttributeStretch(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("rowstretch")) {
+ setAttributeRowStretch(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("columnstretch")) {
+ setAttributeColumnStretch(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("rowminimumheight")) {
+ setAttributeRowMinimumHeight(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("columnminimumwidth")) {
+ setAttributeColumnMinimumWidth(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_attribute.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("item")) {
+ DomLayoutItem *v = new DomLayoutItem();
+ v->read(reader);
+ m_item.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomLayout::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("class")))
+ setAttributeClass(node.attribute(QLatin1String("class")));
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+ if (node.hasAttribute(QLatin1String("stretch")))
+ setAttributeStretch(node.attribute(QLatin1String("stretch")));
+ if (node.hasAttribute(QLatin1String("rowstretch")))
+ setAttributeRowStretch(node.attribute(QLatin1String("rowstretch")));
+ if (node.hasAttribute(QLatin1String("columnstretch")))
+ setAttributeColumnStretch(node.attribute(QLatin1String("columnstretch")));
+ if (node.hasAttribute(QLatin1String("rowminimumheight")))
+ setAttributeRowMinimumHeight(node.attribute(QLatin1String("rowminimumheight")));
+ if (node.hasAttribute(QLatin1String("columnminimumwidth")))
+ setAttributeColumnMinimumWidth(node.attribute(QLatin1String("columnminimumwidth")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_attribute.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("item")) {
+ DomLayoutItem *v = new DomLayoutItem();
+ v->read(e);
+ m_item.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomLayout::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layout") : tagName.toLower());
+
+ if (hasAttributeClass())
+ writer.writeAttribute(QLatin1String("class"), attributeClass());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ if (hasAttributeStretch())
+ writer.writeAttribute(QLatin1String("stretch"), attributeStretch());
+
+ if (hasAttributeRowStretch())
+ writer.writeAttribute(QLatin1String("rowstretch"), attributeRowStretch());
+
+ if (hasAttributeColumnStretch())
+ writer.writeAttribute(QLatin1String("columnstretch"), attributeColumnStretch());
+
+ if (hasAttributeRowMinimumHeight())
+ writer.writeAttribute(QLatin1String("rowminimumheight"), attributeRowMinimumHeight());
+
+ if (hasAttributeColumnMinimumWidth())
+ writer.writeAttribute(QLatin1String("columnminimumwidth"), attributeColumnMinimumWidth());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ for (int i = 0; i < m_attribute.size(); ++i) {
+ DomProperty* v = m_attribute[i];
+ v->write(writer, QLatin1String("attribute"));
+ }
+ for (int i = 0; i < m_item.size(); ++i) {
+ DomLayoutItem* v = m_item[i];
+ v->write(writer, QLatin1String("item"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomLayout::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomLayout::setElementAttribute(const QList<DomProperty*>& a)
+{
+ m_children |= Attribute;
+ m_attribute = a;
+}
+
+void DomLayout::setElementItem(const QList<DomLayoutItem*>& a)
+{
+ m_children |= Item;
+ m_item = a;
+}
+
+void DomLayoutItem::clear(bool clear_all)
+{
+ delete m_widget;
+ delete m_layout;
+ delete m_spacer;
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_row = false;
+ m_attr_row = 0;
+ m_has_attr_column = false;
+ m_attr_column = 0;
+ m_has_attr_rowSpan = false;
+ m_attr_rowSpan = 0;
+ m_has_attr_colSpan = false;
+ m_attr_colSpan = 0;
+ }
+
+ m_kind = Unknown;
+
+ m_widget = 0;
+ m_layout = 0;
+ m_spacer = 0;
+}
+
+DomLayoutItem::DomLayoutItem()
+{
+ m_kind = Unknown;
+
+ m_has_attr_row = false;
+ m_attr_row = 0;
+ m_has_attr_column = false;
+ m_attr_column = 0;
+ m_has_attr_rowSpan = false;
+ m_attr_rowSpan = 0;
+ m_has_attr_colSpan = false;
+ m_attr_colSpan = 0;
+ m_widget = 0;
+ m_layout = 0;
+ m_spacer = 0;
+}
+
+DomLayoutItem::~DomLayoutItem()
+{
+ delete m_widget;
+ delete m_layout;
+ delete m_spacer;
+}
+
+void DomLayoutItem::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("row")) {
+ setAttributeRow(attribute.value().toString().toInt());
+ continue;
+ }
+ if (name == QLatin1String("column")) {
+ setAttributeColumn(attribute.value().toString().toInt());
+ continue;
+ }
+ if (name == QLatin1String("rowspan")) {
+ setAttributeRowSpan(attribute.value().toString().toInt());
+ continue;
+ }
+ if (name == QLatin1String("colspan")) {
+ setAttributeColSpan(attribute.value().toString().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("widget")) {
+ DomWidget *v = new DomWidget();
+ v->read(reader);
+ setElementWidget(v);
+ continue;
+ }
+ if (tag == QLatin1String("layout")) {
+ DomLayout *v = new DomLayout();
+ v->read(reader);
+ setElementLayout(v);
+ continue;
+ }
+ if (tag == QLatin1String("spacer")) {
+ DomSpacer *v = new DomSpacer();
+ v->read(reader);
+ setElementSpacer(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomLayoutItem::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("row")))
+ setAttributeRow(node.attribute(QLatin1String("row")).toInt());
+ if (node.hasAttribute(QLatin1String("column")))
+ setAttributeColumn(node.attribute(QLatin1String("column")).toInt());
+ if (node.hasAttribute(QLatin1String("rowspan")))
+ setAttributeRowSpan(node.attribute(QLatin1String("rowspan")).toInt());
+ if (node.hasAttribute(QLatin1String("colspan")))
+ setAttributeColSpan(node.attribute(QLatin1String("colspan")).toInt());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("widget")) {
+ DomWidget *v = new DomWidget();
+ v->read(e);
+ setElementWidget(v);
+ continue;
+ }
+ if (tag == QLatin1String("layout")) {
+ DomLayout *v = new DomLayout();
+ v->read(e);
+ setElementLayout(v);
+ continue;
+ }
+ if (tag == QLatin1String("spacer")) {
+ DomSpacer *v = new DomSpacer();
+ v->read(e);
+ setElementSpacer(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layoutitem") : tagName.toLower());
+
+ if (hasAttributeRow())
+ writer.writeAttribute(QLatin1String("row"), QString::number(attributeRow()));
+
+ if (hasAttributeColumn())
+ writer.writeAttribute(QLatin1String("column"), QString::number(attributeColumn()));
+
+ if (hasAttributeRowSpan())
+ writer.writeAttribute(QLatin1String("rowspan"), QString::number(attributeRowSpan()));
+
+ if (hasAttributeColSpan())
+ writer.writeAttribute(QLatin1String("colspan"), QString::number(attributeColSpan()));
+
+ switch (kind()) {
+ case Widget: {
+ DomWidget* v = elementWidget();
+ if (v != 0) {
+ v->write(writer, QLatin1String("widget"));
+ }
+ break;
+ }
+ case Layout: {
+ DomLayout* v = elementLayout();
+ if (v != 0) {
+ v->write(writer, QLatin1String("layout"));
+ }
+ break;
+ }
+ case Spacer: {
+ DomSpacer* v = elementSpacer();
+ if (v != 0) {
+ v->write(writer, QLatin1String("spacer"));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomWidget* DomLayoutItem::takeElementWidget()
+{
+ DomWidget* a = m_widget;
+ m_widget = 0;
+ return a;
+}
+
+void DomLayoutItem::setElementWidget(DomWidget* a)
+{
+ clear(false);
+ m_kind = Widget;
+ m_widget = a;
+}
+
+DomLayout* DomLayoutItem::takeElementLayout()
+{
+ DomLayout* a = m_layout;
+ m_layout = 0;
+ return a;
+}
+
+void DomLayoutItem::setElementLayout(DomLayout* a)
+{
+ clear(false);
+ m_kind = Layout;
+ m_layout = a;
+}
+
+DomSpacer* DomLayoutItem::takeElementSpacer()
+{
+ DomSpacer* a = m_spacer;
+ m_spacer = 0;
+ return a;
+}
+
+void DomLayoutItem::setElementSpacer(DomSpacer* a)
+{
+ clear(false);
+ m_kind = Spacer;
+ m_spacer = a;
+}
+
+void DomRow::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomRow::DomRow()
+{
+ m_children = 0;
+}
+
+DomRow::~DomRow()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+}
+
+void DomRow::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomRow::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomRow::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("row") : tagName.toLower());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomRow::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomColumn::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomColumn::DomColumn()
+{
+ m_children = 0;
+}
+
+DomColumn::~DomColumn()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+}
+
+void DomColumn::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomColumn::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomColumn::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("column") : tagName.toLower());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomColumn::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomItem::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_item);
+ m_item.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_row = false;
+ m_attr_row = 0;
+ m_has_attr_column = false;
+ m_attr_column = 0;
+ }
+
+ m_children = 0;
+}
+
+DomItem::DomItem()
+{
+ m_children = 0;
+ m_has_attr_row = false;
+ m_attr_row = 0;
+ m_has_attr_column = false;
+ m_attr_column = 0;
+}
+
+DomItem::~DomItem()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_item);
+ m_item.clear();
+}
+
+void DomItem::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("row")) {
+ setAttributeRow(attribute.value().toString().toInt());
+ continue;
+ }
+ if (name == QLatin1String("column")) {
+ setAttributeColumn(attribute.value().toString().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("item")) {
+ DomItem *v = new DomItem();
+ v->read(reader);
+ m_item.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomItem::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("row")))
+ setAttributeRow(node.attribute(QLatin1String("row")).toInt());
+ if (node.hasAttribute(QLatin1String("column")))
+ setAttributeColumn(node.attribute(QLatin1String("column")).toInt());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("item")) {
+ DomItem *v = new DomItem();
+ v->read(e);
+ m_item.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomItem::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("item") : tagName.toLower());
+
+ if (hasAttributeRow())
+ writer.writeAttribute(QLatin1String("row"), QString::number(attributeRow()));
+
+ if (hasAttributeColumn())
+ writer.writeAttribute(QLatin1String("column"), QString::number(attributeColumn()));
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ for (int i = 0; i < m_item.size(); ++i) {
+ DomItem* v = m_item[i];
+ v->write(writer, QLatin1String("item"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomItem::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomItem::setElementItem(const QList<DomItem*>& a)
+{
+ m_children |= Item;
+ m_item = a;
+}
+
+void DomWidget::clear(bool clear_all)
+{
+ m_class.clear();
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_script);
+ m_script.clear();
+ qDeleteAll(m_widgetData);
+ m_widgetData.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+ qDeleteAll(m_row);
+ m_row.clear();
+ qDeleteAll(m_column);
+ m_column.clear();
+ qDeleteAll(m_item);
+ m_item.clear();
+ qDeleteAll(m_layout);
+ m_layout.clear();
+ qDeleteAll(m_widget);
+ m_widget.clear();
+ qDeleteAll(m_action);
+ m_action.clear();
+ qDeleteAll(m_actionGroup);
+ m_actionGroup.clear();
+ qDeleteAll(m_addAction);
+ m_addAction.clear();
+ m_zOrder.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_class = false;
+ m_has_attr_name = false;
+ m_has_attr_native = false;
+ m_attr_native = false;
+ }
+
+ m_children = 0;
+}
+
+DomWidget::DomWidget()
+{
+ m_children = 0;
+ m_has_attr_class = false;
+ m_has_attr_name = false;
+ m_has_attr_native = false;
+ m_attr_native = false;
+}
+
+DomWidget::~DomWidget()
+{
+ m_class.clear();
+ qDeleteAll(m_property);
+ m_property.clear();
+ qDeleteAll(m_script);
+ m_script.clear();
+ qDeleteAll(m_widgetData);
+ m_widgetData.clear();
+ qDeleteAll(m_attribute);
+ m_attribute.clear();
+ qDeleteAll(m_row);
+ m_row.clear();
+ qDeleteAll(m_column);
+ m_column.clear();
+ qDeleteAll(m_item);
+ m_item.clear();
+ qDeleteAll(m_layout);
+ m_layout.clear();
+ qDeleteAll(m_widget);
+ m_widget.clear();
+ qDeleteAll(m_action);
+ m_action.clear();
+ qDeleteAll(m_actionGroup);
+ m_actionGroup.clear();
+ qDeleteAll(m_addAction);
+ m_addAction.clear();
+ m_zOrder.clear();
+}
+
+void DomWidget::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("class")) {
+ setAttributeClass(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("native")) {
+ setAttributeNative((attribute.value().toString() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("class")) {
+ m_class.append(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("script")) {
+ DomScript *v = new DomScript();
+ v->read(reader);
+ m_script.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("widgetdata")) {
+ DomWidgetData *v = new DomWidgetData();
+ v->read(reader);
+ m_widgetData.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_attribute.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("row")) {
+ DomRow *v = new DomRow();
+ v->read(reader);
+ m_row.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("column")) {
+ DomColumn *v = new DomColumn();
+ v->read(reader);
+ m_column.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("item")) {
+ DomItem *v = new DomItem();
+ v->read(reader);
+ m_item.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("layout")) {
+ DomLayout *v = new DomLayout();
+ v->read(reader);
+ m_layout.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("widget")) {
+ DomWidget *v = new DomWidget();
+ v->read(reader);
+ m_widget.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("action")) {
+ DomAction *v = new DomAction();
+ v->read(reader);
+ m_action.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("actiongroup")) {
+ DomActionGroup *v = new DomActionGroup();
+ v->read(reader);
+ m_actionGroup.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("addaction")) {
+ DomActionRef *v = new DomActionRef();
+ v->read(reader);
+ m_addAction.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("zorder")) {
+ m_zOrder.append(reader.readElementText());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomWidget::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("class")))
+ setAttributeClass(node.attribute(QLatin1String("class")));
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+ if (node.hasAttribute(QLatin1String("native")))
+ setAttributeNative((node.attribute(QLatin1String("native")) == QLatin1String("true") ? true : false));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("class")) {
+ m_class.append(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("script")) {
+ DomScript *v = new DomScript();
+ v->read(e);
+ m_script.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("widgetdata")) {
+ DomWidgetData *v = new DomWidgetData();
+ v->read(e);
+ m_widgetData.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("attribute")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_attribute.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("row")) {
+ DomRow *v = new DomRow();
+ v->read(e);
+ m_row.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("column")) {
+ DomColumn *v = new DomColumn();
+ v->read(e);
+ m_column.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("item")) {
+ DomItem *v = new DomItem();
+ v->read(e);
+ m_item.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("layout")) {
+ DomLayout *v = new DomLayout();
+ v->read(e);
+ m_layout.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("widget")) {
+ DomWidget *v = new DomWidget();
+ v->read(e);
+ m_widget.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("action")) {
+ DomAction *v = new DomAction();
+ v->read(e);
+ m_action.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("actiongroup")) {
+ DomActionGroup *v = new DomActionGroup();
+ v->read(e);
+ m_actionGroup.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("addaction")) {
+ DomActionRef *v = new DomActionRef();
+ v->read(e);
+ m_addAction.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("zorder")) {
+ m_zOrder.append(e.text());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomWidget::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("widget") : tagName.toLower());
+
+ if (hasAttributeClass())
+ writer.writeAttribute(QLatin1String("class"), attributeClass());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ if (hasAttributeNative())
+ writer.writeAttribute(QLatin1String("native"), (attributeNative() ? QLatin1String("true") : QLatin1String("false")));
+
+ for (int i = 0; i < m_class.size(); ++i) {
+ QString v = m_class[i];
+ writer.writeTextElement(QLatin1String("class"), v);
+ }
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ for (int i = 0; i < m_script.size(); ++i) {
+ DomScript* v = m_script[i];
+ v->write(writer, QLatin1String("script"));
+ }
+ for (int i = 0; i < m_widgetData.size(); ++i) {
+ DomWidgetData* v = m_widgetData[i];
+ v->write(writer, QLatin1String("widgetdata"));
+ }
+ for (int i = 0; i < m_attribute.size(); ++i) {
+ DomProperty* v = m_attribute[i];
+ v->write(writer, QLatin1String("attribute"));
+ }
+ for (int i = 0; i < m_row.size(); ++i) {
+ DomRow* v = m_row[i];
+ v->write(writer, QLatin1String("row"));
+ }
+ for (int i = 0; i < m_column.size(); ++i) {
+ DomColumn* v = m_column[i];
+ v->write(writer, QLatin1String("column"));
+ }
+ for (int i = 0; i < m_item.size(); ++i) {
+ DomItem* v = m_item[i];
+ v->write(writer, QLatin1String("item"));
+ }
+ for (int i = 0; i < m_layout.size(); ++i) {
+ DomLayout* v = m_layout[i];
+ v->write(writer, QLatin1String("layout"));
+ }
+ for (int i = 0; i < m_widget.size(); ++i) {
+ DomWidget* v = m_widget[i];
+ v->write(writer, QLatin1String("widget"));
+ }
+ for (int i = 0; i < m_action.size(); ++i) {
+ DomAction* v = m_action[i];
+ v->write(writer, QLatin1String("action"));
+ }
+ for (int i = 0; i < m_actionGroup.size(); ++i) {
+ DomActionGroup* v = m_actionGroup[i];
+ v->write(writer, QLatin1String("actiongroup"));
+ }
+ for (int i = 0; i < m_addAction.size(); ++i) {
+ DomActionRef* v = m_addAction[i];
+ v->write(writer, QLatin1String("addaction"));
+ }
+ for (int i = 0; i < m_zOrder.size(); ++i) {
+ QString v = m_zOrder[i];
+ writer.writeTextElement(QLatin1String("zorder"), v);
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomWidget::setElementClass(const QStringList& a)
+{
+ m_children |= Class;
+ m_class = a;
+}
+
+void DomWidget::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomWidget::setElementScript(const QList<DomScript*>& a)
+{
+ m_children |= Script;
+ m_script = a;
+}
+
+void DomWidget::setElementWidgetData(const QList<DomWidgetData*>& a)
+{
+ m_children |= WidgetData;
+ m_widgetData = a;
+}
+
+void DomWidget::setElementAttribute(const QList<DomProperty*>& a)
+{
+ m_children |= Attribute;
+ m_attribute = a;
+}
+
+void DomWidget::setElementRow(const QList<DomRow*>& a)
+{
+ m_children |= Row;
+ m_row = a;
+}
+
+void DomWidget::setElementColumn(const QList<DomColumn*>& a)
+{
+ m_children |= Column;
+ m_column = a;
+}
+
+void DomWidget::setElementItem(const QList<DomItem*>& a)
+{
+ m_children |= Item;
+ m_item = a;
+}
+
+void DomWidget::setElementLayout(const QList<DomLayout*>& a)
+{
+ m_children |= Layout;
+ m_layout = a;
+}
+
+void DomWidget::setElementWidget(const QList<DomWidget*>& a)
+{
+ m_children |= Widget;
+ m_widget = a;
+}
+
+void DomWidget::setElementAction(const QList<DomAction*>& a)
+{
+ m_children |= Action;
+ m_action = a;
+}
+
+void DomWidget::setElementActionGroup(const QList<DomActionGroup*>& a)
+{
+ m_children |= ActionGroup;
+ m_actionGroup = a;
+}
+
+void DomWidget::setElementAddAction(const QList<DomActionRef*>& a)
+{
+ m_children |= AddAction;
+ m_addAction = a;
+}
+
+void DomWidget::setElementZOrder(const QStringList& a)
+{
+ m_children |= ZOrder;
+ m_zOrder = a;
+}
+
+void DomSpacer::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ }
+
+ m_children = 0;
+}
+
+DomSpacer::DomSpacer()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+}
+
+DomSpacer::~DomSpacer()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+}
+
+void DomSpacer::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomSpacer::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomSpacer::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("spacer") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSpacer::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomColor::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_alpha = false;
+ m_attr_alpha = 0;
+ }
+
+ m_children = 0;
+ m_red = 0;
+ m_green = 0;
+ m_blue = 0;
+}
+
+DomColor::DomColor()
+{
+ m_children = 0;
+ m_has_attr_alpha = false;
+ m_attr_alpha = 0;
+ m_red = 0;
+ m_green = 0;
+ m_blue = 0;
+}
+
+DomColor::~DomColor()
+{
+}
+
+void DomColor::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("alpha")) {
+ setAttributeAlpha(attribute.value().toString().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("red")) {
+ setElementRed(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("green")) {
+ setElementGreen(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("blue")) {
+ setElementBlue(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomColor::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("alpha")))
+ setAttributeAlpha(node.attribute(QLatin1String("alpha")).toInt());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("red")) {
+ setElementRed(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("green")) {
+ setElementGreen(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("blue")) {
+ setElementBlue(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomColor::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("color") : tagName.toLower());
+
+ if (hasAttributeAlpha())
+ writer.writeAttribute(QLatin1String("alpha"), QString::number(attributeAlpha()));
+
+ if (m_children & Red) {
+ writer.writeTextElement(QLatin1String("red"), QString::number(m_red));
+ }
+
+ if (m_children & Green) {
+ writer.writeTextElement(QLatin1String("green"), QString::number(m_green));
+ }
+
+ if (m_children & Blue) {
+ writer.writeTextElement(QLatin1String("blue"), QString::number(m_blue));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomColor::setElementRed(int a)
+{
+ m_children |= Red;
+ m_red = a;
+}
+
+void DomColor::setElementGreen(int a)
+{
+ m_children |= Green;
+ m_green = a;
+}
+
+void DomColor::setElementBlue(int a)
+{
+ m_children |= Blue;
+ m_blue = a;
+}
+
+void DomColor::clearElementRed()
+{
+ m_children &= ~Red;
+}
+
+void DomColor::clearElementGreen()
+{
+ m_children &= ~Green;
+}
+
+void DomColor::clearElementBlue()
+{
+ m_children &= ~Blue;
+}
+
+void DomGradientStop::clear(bool clear_all)
+{
+ delete m_color;
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_position = false;
+ m_attr_position = 0.0;
+ }
+
+ m_children = 0;
+ m_color = 0;
+}
+
+DomGradientStop::DomGradientStop()
+{
+ m_children = 0;
+ m_has_attr_position = false;
+ m_attr_position = 0.0;
+ m_color = 0;
+}
+
+DomGradientStop::~DomGradientStop()
+{
+ delete m_color;
+}
+
+void DomGradientStop::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("position")) {
+ setAttributePosition(attribute.value().toString().toDouble());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(reader);
+ setElementColor(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomGradientStop::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("position")))
+ setAttributePosition(node.attribute(QLatin1String("position")).toDouble());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(e);
+ setElementColor(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomGradientStop::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("gradientstop") : tagName.toLower());
+
+ if (hasAttributePosition())
+ writer.writeAttribute(QLatin1String("position"), QString::number(attributePosition(), 'f', 15));
+
+ if (m_children & Color) {
+ m_color->write(writer, QLatin1String("color"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomColor* DomGradientStop::takeElementColor()
+{
+ DomColor* a = m_color;
+ m_color = 0;
+ m_children ^= Color;
+ return a;
+}
+
+void DomGradientStop::setElementColor(DomColor* a)
+{
+ delete m_color;
+ m_children |= Color;
+ m_color = a;
+}
+
+void DomGradientStop::clearElementColor()
+{
+ delete m_color;
+ m_color = 0;
+ m_children &= ~Color;
+}
+
+void DomGradient::clear(bool clear_all)
+{
+ qDeleteAll(m_gradientStop);
+ m_gradientStop.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_startX = false;
+ m_attr_startX = 0.0;
+ m_has_attr_startY = false;
+ m_attr_startY = 0.0;
+ m_has_attr_endX = false;
+ m_attr_endX = 0.0;
+ m_has_attr_endY = false;
+ m_attr_endY = 0.0;
+ m_has_attr_centralX = false;
+ m_attr_centralX = 0.0;
+ m_has_attr_centralY = false;
+ m_attr_centralY = 0.0;
+ m_has_attr_focalX = false;
+ m_attr_focalX = 0.0;
+ m_has_attr_focalY = false;
+ m_attr_focalY = 0.0;
+ m_has_attr_radius = false;
+ m_attr_radius = 0.0;
+ m_has_attr_angle = false;
+ m_attr_angle = 0.0;
+ m_has_attr_type = false;
+ m_has_attr_spread = false;
+ m_has_attr_coordinateMode = false;
+ }
+
+ m_children = 0;
+}
+
+DomGradient::DomGradient()
+{
+ m_children = 0;
+ m_has_attr_startX = false;
+ m_attr_startX = 0.0;
+ m_has_attr_startY = false;
+ m_attr_startY = 0.0;
+ m_has_attr_endX = false;
+ m_attr_endX = 0.0;
+ m_has_attr_endY = false;
+ m_attr_endY = 0.0;
+ m_has_attr_centralX = false;
+ m_attr_centralX = 0.0;
+ m_has_attr_centralY = false;
+ m_attr_centralY = 0.0;
+ m_has_attr_focalX = false;
+ m_attr_focalX = 0.0;
+ m_has_attr_focalY = false;
+ m_attr_focalY = 0.0;
+ m_has_attr_radius = false;
+ m_attr_radius = 0.0;
+ m_has_attr_angle = false;
+ m_attr_angle = 0.0;
+ m_has_attr_type = false;
+ m_has_attr_spread = false;
+ m_has_attr_coordinateMode = false;
+}
+
+DomGradient::~DomGradient()
+{
+ qDeleteAll(m_gradientStop);
+ m_gradientStop.clear();
+}
+
+void DomGradient::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("startx")) {
+ setAttributeStartX(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("starty")) {
+ setAttributeStartY(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("endx")) {
+ setAttributeEndX(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("endy")) {
+ setAttributeEndY(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("centralx")) {
+ setAttributeCentralX(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("centraly")) {
+ setAttributeCentralY(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("focalx")) {
+ setAttributeFocalX(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("focaly")) {
+ setAttributeFocalY(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("radius")) {
+ setAttributeRadius(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("angle")) {
+ setAttributeAngle(attribute.value().toString().toDouble());
+ continue;
+ }
+ if (name == QLatin1String("type")) {
+ setAttributeType(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("spread")) {
+ setAttributeSpread(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("coordinatemode")) {
+ setAttributeCoordinateMode(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("gradientstop")) {
+ DomGradientStop *v = new DomGradientStop();
+ v->read(reader);
+ m_gradientStop.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomGradient::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("startx")))
+ setAttributeStartX(node.attribute(QLatin1String("startx")).toDouble());
+ if (node.hasAttribute(QLatin1String("starty")))
+ setAttributeStartY(node.attribute(QLatin1String("starty")).toDouble());
+ if (node.hasAttribute(QLatin1String("endx")))
+ setAttributeEndX(node.attribute(QLatin1String("endx")).toDouble());
+ if (node.hasAttribute(QLatin1String("endy")))
+ setAttributeEndY(node.attribute(QLatin1String("endy")).toDouble());
+ if (node.hasAttribute(QLatin1String("centralx")))
+ setAttributeCentralX(node.attribute(QLatin1String("centralx")).toDouble());
+ if (node.hasAttribute(QLatin1String("centraly")))
+ setAttributeCentralY(node.attribute(QLatin1String("centraly")).toDouble());
+ if (node.hasAttribute(QLatin1String("focalx")))
+ setAttributeFocalX(node.attribute(QLatin1String("focalx")).toDouble());
+ if (node.hasAttribute(QLatin1String("focaly")))
+ setAttributeFocalY(node.attribute(QLatin1String("focaly")).toDouble());
+ if (node.hasAttribute(QLatin1String("radius")))
+ setAttributeRadius(node.attribute(QLatin1String("radius")).toDouble());
+ if (node.hasAttribute(QLatin1String("angle")))
+ setAttributeAngle(node.attribute(QLatin1String("angle")).toDouble());
+ if (node.hasAttribute(QLatin1String("type")))
+ setAttributeType(node.attribute(QLatin1String("type")));
+ if (node.hasAttribute(QLatin1String("spread")))
+ setAttributeSpread(node.attribute(QLatin1String("spread")));
+ if (node.hasAttribute(QLatin1String("coordinatemode")))
+ setAttributeCoordinateMode(node.attribute(QLatin1String("coordinatemode")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("gradientstop")) {
+ DomGradientStop *v = new DomGradientStop();
+ v->read(e);
+ m_gradientStop.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomGradient::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("gradient") : tagName.toLower());
+
+ if (hasAttributeStartX())
+ writer.writeAttribute(QLatin1String("startx"), QString::number(attributeStartX(), 'f', 15));
+
+ if (hasAttributeStartY())
+ writer.writeAttribute(QLatin1String("starty"), QString::number(attributeStartY(), 'f', 15));
+
+ if (hasAttributeEndX())
+ writer.writeAttribute(QLatin1String("endx"), QString::number(attributeEndX(), 'f', 15));
+
+ if (hasAttributeEndY())
+ writer.writeAttribute(QLatin1String("endy"), QString::number(attributeEndY(), 'f', 15));
+
+ if (hasAttributeCentralX())
+ writer.writeAttribute(QLatin1String("centralx"), QString::number(attributeCentralX(), 'f', 15));
+
+ if (hasAttributeCentralY())
+ writer.writeAttribute(QLatin1String("centraly"), QString::number(attributeCentralY(), 'f', 15));
+
+ if (hasAttributeFocalX())
+ writer.writeAttribute(QLatin1String("focalx"), QString::number(attributeFocalX(), 'f', 15));
+
+ if (hasAttributeFocalY())
+ writer.writeAttribute(QLatin1String("focaly"), QString::number(attributeFocalY(), 'f', 15));
+
+ if (hasAttributeRadius())
+ writer.writeAttribute(QLatin1String("radius"), QString::number(attributeRadius(), 'f', 15));
+
+ if (hasAttributeAngle())
+ writer.writeAttribute(QLatin1String("angle"), QString::number(attributeAngle(), 'f', 15));
+
+ if (hasAttributeType())
+ writer.writeAttribute(QLatin1String("type"), attributeType());
+
+ if (hasAttributeSpread())
+ writer.writeAttribute(QLatin1String("spread"), attributeSpread());
+
+ if (hasAttributeCoordinateMode())
+ writer.writeAttribute(QLatin1String("coordinatemode"), attributeCoordinateMode());
+
+ for (int i = 0; i < m_gradientStop.size(); ++i) {
+ DomGradientStop* v = m_gradientStop[i];
+ v->write(writer, QLatin1String("gradientstop"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomGradient::setElementGradientStop(const QList<DomGradientStop*>& a)
+{
+ m_children |= GradientStop;
+ m_gradientStop = a;
+}
+
+void DomBrush::clear(bool clear_all)
+{
+ delete m_color;
+ delete m_texture;
+ delete m_gradient;
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_brushStyle = false;
+ }
+
+ m_kind = Unknown;
+
+ m_color = 0;
+ m_texture = 0;
+ m_gradient = 0;
+}
+
+DomBrush::DomBrush()
+{
+ m_kind = Unknown;
+
+ m_has_attr_brushStyle = false;
+ m_color = 0;
+ m_texture = 0;
+ m_gradient = 0;
+}
+
+DomBrush::~DomBrush()
+{
+ delete m_color;
+ delete m_texture;
+ delete m_gradient;
+}
+
+void DomBrush::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("brushstyle")) {
+ setAttributeBrushStyle(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(reader);
+ setElementColor(v);
+ continue;
+ }
+ if (tag == QLatin1String("texture")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ setElementTexture(v);
+ continue;
+ }
+ if (tag == QLatin1String("gradient")) {
+ DomGradient *v = new DomGradient();
+ v->read(reader);
+ setElementGradient(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomBrush::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("brushstyle")))
+ setAttributeBrushStyle(node.attribute(QLatin1String("brushstyle")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(e);
+ setElementColor(v);
+ continue;
+ }
+ if (tag == QLatin1String("texture")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ setElementTexture(v);
+ continue;
+ }
+ if (tag == QLatin1String("gradient")) {
+ DomGradient *v = new DomGradient();
+ v->read(e);
+ setElementGradient(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomBrush::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("brush") : tagName.toLower());
+
+ if (hasAttributeBrushStyle())
+ writer.writeAttribute(QLatin1String("brushstyle"), attributeBrushStyle());
+
+ switch (kind()) {
+ case Color: {
+ DomColor* v = elementColor();
+ if (v != 0) {
+ v->write(writer, QLatin1String("color"));
+ }
+ break;
+ }
+ case Texture: {
+ DomProperty* v = elementTexture();
+ if (v != 0) {
+ v->write(writer, QLatin1String("texture"));
+ }
+ break;
+ }
+ case Gradient: {
+ DomGradient* v = elementGradient();
+ if (v != 0) {
+ v->write(writer, QLatin1String("gradient"));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomColor* DomBrush::takeElementColor()
+{
+ DomColor* a = m_color;
+ m_color = 0;
+ return a;
+}
+
+void DomBrush::setElementColor(DomColor* a)
+{
+ clear(false);
+ m_kind = Color;
+ m_color = a;
+}
+
+DomProperty* DomBrush::takeElementTexture()
+{
+ DomProperty* a = m_texture;
+ m_texture = 0;
+ return a;
+}
+
+void DomBrush::setElementTexture(DomProperty* a)
+{
+ clear(false);
+ m_kind = Texture;
+ m_texture = a;
+}
+
+DomGradient* DomBrush::takeElementGradient()
+{
+ DomGradient* a = m_gradient;
+ m_gradient = 0;
+ return a;
+}
+
+void DomBrush::setElementGradient(DomGradient* a)
+{
+ clear(false);
+ m_kind = Gradient;
+ m_gradient = a;
+}
+
+void DomColorRole::clear(bool clear_all)
+{
+ delete m_brush;
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_role = false;
+ }
+
+ m_children = 0;
+ m_brush = 0;
+}
+
+DomColorRole::DomColorRole()
+{
+ m_children = 0;
+ m_has_attr_role = false;
+ m_brush = 0;
+}
+
+DomColorRole::~DomColorRole()
+{
+ delete m_brush;
+}
+
+void DomColorRole::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("role")) {
+ setAttributeRole(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("brush")) {
+ DomBrush *v = new DomBrush();
+ v->read(reader);
+ setElementBrush(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomColorRole::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("role")))
+ setAttributeRole(node.attribute(QLatin1String("role")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("brush")) {
+ DomBrush *v = new DomBrush();
+ v->read(e);
+ setElementBrush(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomColorRole::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("colorrole") : tagName.toLower());
+
+ if (hasAttributeRole())
+ writer.writeAttribute(QLatin1String("role"), attributeRole());
+
+ if (m_children & Brush) {
+ m_brush->write(writer, QLatin1String("brush"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomBrush* DomColorRole::takeElementBrush()
+{
+ DomBrush* a = m_brush;
+ m_brush = 0;
+ m_children ^= Brush;
+ return a;
+}
+
+void DomColorRole::setElementBrush(DomBrush* a)
+{
+ delete m_brush;
+ m_children |= Brush;
+ m_brush = a;
+}
+
+void DomColorRole::clearElementBrush()
+{
+ delete m_brush;
+ m_brush = 0;
+ m_children &= ~Brush;
+}
+
+void DomColorGroup::clear(bool clear_all)
+{
+ qDeleteAll(m_colorRole);
+ m_colorRole.clear();
+ qDeleteAll(m_color);
+ m_color.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomColorGroup::DomColorGroup()
+{
+ m_children = 0;
+}
+
+DomColorGroup::~DomColorGroup()
+{
+ qDeleteAll(m_colorRole);
+ m_colorRole.clear();
+ qDeleteAll(m_color);
+ m_color.clear();
+}
+
+void DomColorGroup::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("colorrole")) {
+ DomColorRole *v = new DomColorRole();
+ v->read(reader);
+ m_colorRole.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(reader);
+ m_color.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomColorGroup::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("colorrole")) {
+ DomColorRole *v = new DomColorRole();
+ v->read(e);
+ m_colorRole.append(v);
+ continue;
+ }
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(e);
+ m_color.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomColorGroup::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("colorgroup") : tagName.toLower());
+
+ for (int i = 0; i < m_colorRole.size(); ++i) {
+ DomColorRole* v = m_colorRole[i];
+ v->write(writer, QLatin1String("colorrole"));
+ }
+ for (int i = 0; i < m_color.size(); ++i) {
+ DomColor* v = m_color[i];
+ v->write(writer, QLatin1String("color"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomColorGroup::setElementColorRole(const QList<DomColorRole*>& a)
+{
+ m_children |= ColorRole;
+ m_colorRole = a;
+}
+
+void DomColorGroup::setElementColor(const QList<DomColor*>& a)
+{
+ m_children |= Color;
+ m_color = a;
+}
+
+void DomPalette::clear(bool clear_all)
+{
+ delete m_active;
+ delete m_inactive;
+ delete m_disabled;
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_active = 0;
+ m_inactive = 0;
+ m_disabled = 0;
+}
+
+DomPalette::DomPalette()
+{
+ m_children = 0;
+ m_active = 0;
+ m_inactive = 0;
+ m_disabled = 0;
+}
+
+DomPalette::~DomPalette()
+{
+ delete m_active;
+ delete m_inactive;
+ delete m_disabled;
+}
+
+void DomPalette::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("active")) {
+ DomColorGroup *v = new DomColorGroup();
+ v->read(reader);
+ setElementActive(v);
+ continue;
+ }
+ if (tag == QLatin1String("inactive")) {
+ DomColorGroup *v = new DomColorGroup();
+ v->read(reader);
+ setElementInactive(v);
+ continue;
+ }
+ if (tag == QLatin1String("disabled")) {
+ DomColorGroup *v = new DomColorGroup();
+ v->read(reader);
+ setElementDisabled(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomPalette::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("active")) {
+ DomColorGroup *v = new DomColorGroup();
+ v->read(e);
+ setElementActive(v);
+ continue;
+ }
+ if (tag == QLatin1String("inactive")) {
+ DomColorGroup *v = new DomColorGroup();
+ v->read(e);
+ setElementInactive(v);
+ continue;
+ }
+ if (tag == QLatin1String("disabled")) {
+ DomColorGroup *v = new DomColorGroup();
+ v->read(e);
+ setElementDisabled(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomPalette::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("palette") : tagName.toLower());
+
+ if (m_children & Active) {
+ m_active->write(writer, QLatin1String("active"));
+ }
+
+ if (m_children & Inactive) {
+ m_inactive->write(writer, QLatin1String("inactive"));
+ }
+
+ if (m_children & Disabled) {
+ m_disabled->write(writer, QLatin1String("disabled"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomColorGroup* DomPalette::takeElementActive()
+{
+ DomColorGroup* a = m_active;
+ m_active = 0;
+ m_children ^= Active;
+ return a;
+}
+
+void DomPalette::setElementActive(DomColorGroup* a)
+{
+ delete m_active;
+ m_children |= Active;
+ m_active = a;
+}
+
+DomColorGroup* DomPalette::takeElementInactive()
+{
+ DomColorGroup* a = m_inactive;
+ m_inactive = 0;
+ m_children ^= Inactive;
+ return a;
+}
+
+void DomPalette::setElementInactive(DomColorGroup* a)
+{
+ delete m_inactive;
+ m_children |= Inactive;
+ m_inactive = a;
+}
+
+DomColorGroup* DomPalette::takeElementDisabled()
+{
+ DomColorGroup* a = m_disabled;
+ m_disabled = 0;
+ m_children ^= Disabled;
+ return a;
+}
+
+void DomPalette::setElementDisabled(DomColorGroup* a)
+{
+ delete m_disabled;
+ m_children |= Disabled;
+ m_disabled = a;
+}
+
+void DomPalette::clearElementActive()
+{
+ delete m_active;
+ m_active = 0;
+ m_children &= ~Active;
+}
+
+void DomPalette::clearElementInactive()
+{
+ delete m_inactive;
+ m_inactive = 0;
+ m_children &= ~Inactive;
+}
+
+void DomPalette::clearElementDisabled()
+{
+ delete m_disabled;
+ m_disabled = 0;
+ m_children &= ~Disabled;
+}
+
+void DomFont::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_pointSize = 0;
+ m_weight = 0;
+ m_italic = false;
+ m_bold = false;
+ m_underline = false;
+ m_strikeOut = false;
+ m_antialiasing = false;
+ m_kerning = false;
+}
+
+DomFont::DomFont()
+{
+ m_children = 0;
+ m_pointSize = 0;
+ m_weight = 0;
+ m_italic = false;
+ m_bold = false;
+ m_underline = false;
+ m_strikeOut = false;
+ m_antialiasing = false;
+ m_kerning = false;
+}
+
+DomFont::~DomFont()
+{
+}
+
+void DomFont::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("family")) {
+ setElementFamily(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("pointsize")) {
+ setElementPointSize(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("weight")) {
+ setElementWeight(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("italic")) {
+ setElementItalic((reader.readElementText() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("bold")) {
+ setElementBold((reader.readElementText() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("underline")) {
+ setElementUnderline((reader.readElementText() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("strikeout")) {
+ setElementStrikeOut((reader.readElementText() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("antialiasing")) {
+ setElementAntialiasing((reader.readElementText() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("stylestrategy")) {
+ setElementStyleStrategy(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("kerning")) {
+ setElementKerning((reader.readElementText() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomFont::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("family")) {
+ setElementFamily(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("pointsize")) {
+ setElementPointSize(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("weight")) {
+ setElementWeight(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("italic")) {
+ setElementItalic((e.text() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("bold")) {
+ setElementBold((e.text() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("underline")) {
+ setElementUnderline((e.text() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("strikeout")) {
+ setElementStrikeOut((e.text() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("antialiasing")) {
+ setElementAntialiasing((e.text() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ if (tag == QLatin1String("stylestrategy")) {
+ setElementStyleStrategy(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("kerning")) {
+ setElementKerning((e.text() == QLatin1String("true") ? true : false));
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomFont::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("font") : tagName.toLower());
+
+ if (m_children & Family) {
+ writer.writeTextElement(QLatin1String("family"), m_family);
+ }
+
+ if (m_children & PointSize) {
+ writer.writeTextElement(QLatin1String("pointsize"), QString::number(m_pointSize));
+ }
+
+ if (m_children & Weight) {
+ writer.writeTextElement(QLatin1String("weight"), QString::number(m_weight));
+ }
+
+ if (m_children & Italic) {
+ writer.writeTextElement(QLatin1String("italic"), (m_italic ? QLatin1String("true") : QLatin1String("false")));
+ }
+
+ if (m_children & Bold) {
+ writer.writeTextElement(QLatin1String("bold"), (m_bold ? QLatin1String("true") : QLatin1String("false")));
+ }
+
+ if (m_children & Underline) {
+ writer.writeTextElement(QLatin1String("underline"), (m_underline ? QLatin1String("true") : QLatin1String("false")));
+ }
+
+ if (m_children & StrikeOut) {
+ writer.writeTextElement(QLatin1String("strikeout"), (m_strikeOut ? QLatin1String("true") : QLatin1String("false")));
+ }
+
+ if (m_children & Antialiasing) {
+ writer.writeTextElement(QLatin1String("antialiasing"), (m_antialiasing ? QLatin1String("true") : QLatin1String("false")));
+ }
+
+ if (m_children & StyleStrategy) {
+ writer.writeTextElement(QLatin1String("stylestrategy"), m_styleStrategy);
+ }
+
+ if (m_children & Kerning) {
+ writer.writeTextElement(QLatin1String("kerning"), (m_kerning ? QLatin1String("true") : QLatin1String("false")));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomFont::setElementFamily(const QString& a)
+{
+ m_children |= Family;
+ m_family = a;
+}
+
+void DomFont::setElementPointSize(int a)
+{
+ m_children |= PointSize;
+ m_pointSize = a;
+}
+
+void DomFont::setElementWeight(int a)
+{
+ m_children |= Weight;
+ m_weight = a;
+}
+
+void DomFont::setElementItalic(bool a)
+{
+ m_children |= Italic;
+ m_italic = a;
+}
+
+void DomFont::setElementBold(bool a)
+{
+ m_children |= Bold;
+ m_bold = a;
+}
+
+void DomFont::setElementUnderline(bool a)
+{
+ m_children |= Underline;
+ m_underline = a;
+}
+
+void DomFont::setElementStrikeOut(bool a)
+{
+ m_children |= StrikeOut;
+ m_strikeOut = a;
+}
+
+void DomFont::setElementAntialiasing(bool a)
+{
+ m_children |= Antialiasing;
+ m_antialiasing = a;
+}
+
+void DomFont::setElementStyleStrategy(const QString& a)
+{
+ m_children |= StyleStrategy;
+ m_styleStrategy = a;
+}
+
+void DomFont::setElementKerning(bool a)
+{
+ m_children |= Kerning;
+ m_kerning = a;
+}
+
+void DomFont::clearElementFamily()
+{
+ m_children &= ~Family;
+}
+
+void DomFont::clearElementPointSize()
+{
+ m_children &= ~PointSize;
+}
+
+void DomFont::clearElementWeight()
+{
+ m_children &= ~Weight;
+}
+
+void DomFont::clearElementItalic()
+{
+ m_children &= ~Italic;
+}
+
+void DomFont::clearElementBold()
+{
+ m_children &= ~Bold;
+}
+
+void DomFont::clearElementUnderline()
+{
+ m_children &= ~Underline;
+}
+
+void DomFont::clearElementStrikeOut()
+{
+ m_children &= ~StrikeOut;
+}
+
+void DomFont::clearElementAntialiasing()
+{
+ m_children &= ~Antialiasing;
+}
+
+void DomFont::clearElementStyleStrategy()
+{
+ m_children &= ~StyleStrategy;
+}
+
+void DomFont::clearElementKerning()
+{
+ m_children &= ~Kerning;
+}
+
+void DomPoint::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+}
+
+DomPoint::DomPoint()
+{
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+}
+
+DomPoint::~DomPoint()
+{
+}
+
+void DomPoint::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomPoint::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(e.text().toInt());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomPoint::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("point") : tagName.toLower());
+
+ if (m_children & X) {
+ writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
+ }
+
+ if (m_children & Y) {
+ writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomPoint::setElementX(int a)
+{
+ m_children |= X;
+ m_x = a;
+}
+
+void DomPoint::setElementY(int a)
+{
+ m_children |= Y;
+ m_y = a;
+}
+
+void DomPoint::clearElementX()
+{
+ m_children &= ~X;
+}
+
+void DomPoint::clearElementY()
+{
+ m_children &= ~Y;
+}
+
+void DomRect::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomRect::DomRect()
+{
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomRect::~DomRect()
+{
+}
+
+void DomRect::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("width")) {
+ setElementWidth(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomRect::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(e.text().toInt());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("width")) {
+ setElementWidth(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomRect::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("rect") : tagName.toLower());
+
+ if (m_children & X) {
+ writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
+ }
+
+ if (m_children & Y) {
+ writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
+ }
+
+ if (m_children & Width) {
+ writer.writeTextElement(QLatin1String("width"), QString::number(m_width));
+ }
+
+ if (m_children & Height) {
+ writer.writeTextElement(QLatin1String("height"), QString::number(m_height));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomRect::setElementX(int a)
+{
+ m_children |= X;
+ m_x = a;
+}
+
+void DomRect::setElementY(int a)
+{
+ m_children |= Y;
+ m_y = a;
+}
+
+void DomRect::setElementWidth(int a)
+{
+ m_children |= Width;
+ m_width = a;
+}
+
+void DomRect::setElementHeight(int a)
+{
+ m_children |= Height;
+ m_height = a;
+}
+
+void DomRect::clearElementX()
+{
+ m_children &= ~X;
+}
+
+void DomRect::clearElementY()
+{
+ m_children &= ~Y;
+}
+
+void DomRect::clearElementWidth()
+{
+ m_children &= ~Width;
+}
+
+void DomRect::clearElementHeight()
+{
+ m_children &= ~Height;
+}
+
+void DomLocale::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_language = false;
+ m_has_attr_country = false;
+ }
+
+ m_children = 0;
+}
+
+DomLocale::DomLocale()
+{
+ m_children = 0;
+ m_has_attr_language = false;
+ m_has_attr_country = false;
+}
+
+DomLocale::~DomLocale()
+{
+}
+
+void DomLocale::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("language")) {
+ setAttributeLanguage(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("country")) {
+ setAttributeCountry(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomLocale::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("language")))
+ setAttributeLanguage(node.attribute(QLatin1String("language")));
+ if (node.hasAttribute(QLatin1String("country")))
+ setAttributeCountry(node.attribute(QLatin1String("country")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomLocale::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("locale") : tagName.toLower());
+
+ if (hasAttributeLanguage())
+ writer.writeAttribute(QLatin1String("language"), attributeLanguage());
+
+ if (hasAttributeCountry())
+ writer.writeAttribute(QLatin1String("country"), attributeCountry());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSizePolicy::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_hSizeType = false;
+ m_has_attr_vSizeType = false;
+ }
+
+ m_children = 0;
+ m_hSizeType = 0;
+ m_vSizeType = 0;
+ m_horStretch = 0;
+ m_verStretch = 0;
+}
+
+DomSizePolicy::DomSizePolicy()
+{
+ m_children = 0;
+ m_has_attr_hSizeType = false;
+ m_has_attr_vSizeType = false;
+ m_hSizeType = 0;
+ m_vSizeType = 0;
+ m_horStretch = 0;
+ m_verStretch = 0;
+}
+
+DomSizePolicy::~DomSizePolicy()
+{
+}
+
+void DomSizePolicy::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("hsizetype")) {
+ setAttributeHSizeType(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("vsizetype")) {
+ setAttributeVSizeType(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("hsizetype")) {
+ setElementHSizeType(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("vsizetype")) {
+ setElementVSizeType(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("horstretch")) {
+ setElementHorStretch(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("verstretch")) {
+ setElementVerStretch(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomSizePolicy::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("hsizetype")))
+ setAttributeHSizeType(node.attribute(QLatin1String("hsizetype")));
+ if (node.hasAttribute(QLatin1String("vsizetype")))
+ setAttributeVSizeType(node.attribute(QLatin1String("vsizetype")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("hsizetype")) {
+ setElementHSizeType(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("vsizetype")) {
+ setElementVSizeType(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("horstretch")) {
+ setElementHorStretch(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("verstretch")) {
+ setElementVerStretch(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomSizePolicy::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("sizepolicy") : tagName.toLower());
+
+ if (hasAttributeHSizeType())
+ writer.writeAttribute(QLatin1String("hsizetype"), attributeHSizeType());
+
+ if (hasAttributeVSizeType())
+ writer.writeAttribute(QLatin1String("vsizetype"), attributeVSizeType());
+
+ if (m_children & HSizeType) {
+ writer.writeTextElement(QLatin1String("hsizetype"), QString::number(m_hSizeType));
+ }
+
+ if (m_children & VSizeType) {
+ writer.writeTextElement(QLatin1String("vsizetype"), QString::number(m_vSizeType));
+ }
+
+ if (m_children & HorStretch) {
+ writer.writeTextElement(QLatin1String("horstretch"), QString::number(m_horStretch));
+ }
+
+ if (m_children & VerStretch) {
+ writer.writeTextElement(QLatin1String("verstretch"), QString::number(m_verStretch));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSizePolicy::setElementHSizeType(int a)
+{
+ m_children |= HSizeType;
+ m_hSizeType = a;
+}
+
+void DomSizePolicy::setElementVSizeType(int a)
+{
+ m_children |= VSizeType;
+ m_vSizeType = a;
+}
+
+void DomSizePolicy::setElementHorStretch(int a)
+{
+ m_children |= HorStretch;
+ m_horStretch = a;
+}
+
+void DomSizePolicy::setElementVerStretch(int a)
+{
+ m_children |= VerStretch;
+ m_verStretch = a;
+}
+
+void DomSizePolicy::clearElementHSizeType()
+{
+ m_children &= ~HSizeType;
+}
+
+void DomSizePolicy::clearElementVSizeType()
+{
+ m_children &= ~VSizeType;
+}
+
+void DomSizePolicy::clearElementHorStretch()
+{
+ m_children &= ~HorStretch;
+}
+
+void DomSizePolicy::clearElementVerStretch()
+{
+ m_children &= ~VerStretch;
+}
+
+void DomSize::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomSize::DomSize()
+{
+ m_children = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomSize::~DomSize()
+{
+}
+
+void DomSize::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("width")) {
+ setElementWidth(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomSize::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("width")) {
+ setElementWidth(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomSize::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("size") : tagName.toLower());
+
+ if (m_children & Width) {
+ writer.writeTextElement(QLatin1String("width"), QString::number(m_width));
+ }
+
+ if (m_children & Height) {
+ writer.writeTextElement(QLatin1String("height"), QString::number(m_height));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSize::setElementWidth(int a)
+{
+ m_children |= Width;
+ m_width = a;
+}
+
+void DomSize::setElementHeight(int a)
+{
+ m_children |= Height;
+ m_height = a;
+}
+
+void DomSize::clearElementWidth()
+{
+ m_children &= ~Width;
+}
+
+void DomSize::clearElementHeight()
+{
+ m_children &= ~Height;
+}
+
+void DomDate::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_year = 0;
+ m_month = 0;
+ m_day = 0;
+}
+
+DomDate::DomDate()
+{
+ m_children = 0;
+ m_year = 0;
+ m_month = 0;
+ m_day = 0;
+}
+
+DomDate::~DomDate()
+{
+}
+
+void DomDate::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("year")) {
+ setElementYear(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("month")) {
+ setElementMonth(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("day")) {
+ setElementDay(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomDate::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("year")) {
+ setElementYear(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("month")) {
+ setElementMonth(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("day")) {
+ setElementDay(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomDate::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("date") : tagName.toLower());
+
+ if (m_children & Year) {
+ writer.writeTextElement(QLatin1String("year"), QString::number(m_year));
+ }
+
+ if (m_children & Month) {
+ writer.writeTextElement(QLatin1String("month"), QString::number(m_month));
+ }
+
+ if (m_children & Day) {
+ writer.writeTextElement(QLatin1String("day"), QString::number(m_day));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomDate::setElementYear(int a)
+{
+ m_children |= Year;
+ m_year = a;
+}
+
+void DomDate::setElementMonth(int a)
+{
+ m_children |= Month;
+ m_month = a;
+}
+
+void DomDate::setElementDay(int a)
+{
+ m_children |= Day;
+ m_day = a;
+}
+
+void DomDate::clearElementYear()
+{
+ m_children &= ~Year;
+}
+
+void DomDate::clearElementMonth()
+{
+ m_children &= ~Month;
+}
+
+void DomDate::clearElementDay()
+{
+ m_children &= ~Day;
+}
+
+void DomTime::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_hour = 0;
+ m_minute = 0;
+ m_second = 0;
+}
+
+DomTime::DomTime()
+{
+ m_children = 0;
+ m_hour = 0;
+ m_minute = 0;
+ m_second = 0;
+}
+
+DomTime::~DomTime()
+{
+}
+
+void DomTime::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("hour")) {
+ setElementHour(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("minute")) {
+ setElementMinute(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("second")) {
+ setElementSecond(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomTime::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("hour")) {
+ setElementHour(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("minute")) {
+ setElementMinute(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("second")) {
+ setElementSecond(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomTime::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("time") : tagName.toLower());
+
+ if (m_children & Hour) {
+ writer.writeTextElement(QLatin1String("hour"), QString::number(m_hour));
+ }
+
+ if (m_children & Minute) {
+ writer.writeTextElement(QLatin1String("minute"), QString::number(m_minute));
+ }
+
+ if (m_children & Second) {
+ writer.writeTextElement(QLatin1String("second"), QString::number(m_second));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomTime::setElementHour(int a)
+{
+ m_children |= Hour;
+ m_hour = a;
+}
+
+void DomTime::setElementMinute(int a)
+{
+ m_children |= Minute;
+ m_minute = a;
+}
+
+void DomTime::setElementSecond(int a)
+{
+ m_children |= Second;
+ m_second = a;
+}
+
+void DomTime::clearElementHour()
+{
+ m_children &= ~Hour;
+}
+
+void DomTime::clearElementMinute()
+{
+ m_children &= ~Minute;
+}
+
+void DomTime::clearElementSecond()
+{
+ m_children &= ~Second;
+}
+
+void DomDateTime::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_hour = 0;
+ m_minute = 0;
+ m_second = 0;
+ m_year = 0;
+ m_month = 0;
+ m_day = 0;
+}
+
+DomDateTime::DomDateTime()
+{
+ m_children = 0;
+ m_hour = 0;
+ m_minute = 0;
+ m_second = 0;
+ m_year = 0;
+ m_month = 0;
+ m_day = 0;
+}
+
+DomDateTime::~DomDateTime()
+{
+}
+
+void DomDateTime::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("hour")) {
+ setElementHour(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("minute")) {
+ setElementMinute(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("second")) {
+ setElementSecond(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("year")) {
+ setElementYear(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("month")) {
+ setElementMonth(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("day")) {
+ setElementDay(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomDateTime::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("hour")) {
+ setElementHour(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("minute")) {
+ setElementMinute(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("second")) {
+ setElementSecond(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("year")) {
+ setElementYear(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("month")) {
+ setElementMonth(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("day")) {
+ setElementDay(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomDateTime::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("datetime") : tagName.toLower());
+
+ if (m_children & Hour) {
+ writer.writeTextElement(QLatin1String("hour"), QString::number(m_hour));
+ }
+
+ if (m_children & Minute) {
+ writer.writeTextElement(QLatin1String("minute"), QString::number(m_minute));
+ }
+
+ if (m_children & Second) {
+ writer.writeTextElement(QLatin1String("second"), QString::number(m_second));
+ }
+
+ if (m_children & Year) {
+ writer.writeTextElement(QLatin1String("year"), QString::number(m_year));
+ }
+
+ if (m_children & Month) {
+ writer.writeTextElement(QLatin1String("month"), QString::number(m_month));
+ }
+
+ if (m_children & Day) {
+ writer.writeTextElement(QLatin1String("day"), QString::number(m_day));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomDateTime::setElementHour(int a)
+{
+ m_children |= Hour;
+ m_hour = a;
+}
+
+void DomDateTime::setElementMinute(int a)
+{
+ m_children |= Minute;
+ m_minute = a;
+}
+
+void DomDateTime::setElementSecond(int a)
+{
+ m_children |= Second;
+ m_second = a;
+}
+
+void DomDateTime::setElementYear(int a)
+{
+ m_children |= Year;
+ m_year = a;
+}
+
+void DomDateTime::setElementMonth(int a)
+{
+ m_children |= Month;
+ m_month = a;
+}
+
+void DomDateTime::setElementDay(int a)
+{
+ m_children |= Day;
+ m_day = a;
+}
+
+void DomDateTime::clearElementHour()
+{
+ m_children &= ~Hour;
+}
+
+void DomDateTime::clearElementMinute()
+{
+ m_children &= ~Minute;
+}
+
+void DomDateTime::clearElementSecond()
+{
+ m_children &= ~Second;
+}
+
+void DomDateTime::clearElementYear()
+{
+ m_children &= ~Year;
+}
+
+void DomDateTime::clearElementMonth()
+{
+ m_children &= ~Month;
+}
+
+void DomDateTime::clearElementDay()
+{
+ m_children &= ~Day;
+}
+
+void DomStringList::clear(bool clear_all)
+{
+ m_string.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomStringList::DomStringList()
+{
+ m_children = 0;
+}
+
+DomStringList::~DomStringList()
+{
+ m_string.clear();
+}
+
+void DomStringList::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("string")) {
+ m_string.append(reader.readElementText());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomStringList::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("string")) {
+ m_string.append(e.text());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomStringList::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("stringlist") : tagName.toLower());
+
+ for (int i = 0; i < m_string.size(); ++i) {
+ QString v = m_string[i];
+ writer.writeTextElement(QLatin1String("string"), v);
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomStringList::setElementString(const QStringList& a)
+{
+ m_children |= String;
+ m_string = a;
+}
+
+void DomResourcePixmap::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text = QLatin1String("");
+ m_has_attr_resource = false;
+ m_has_attr_alias = false;
+ }
+
+ m_children = 0;
+}
+
+DomResourcePixmap::DomResourcePixmap()
+{
+ m_children = 0;
+ m_has_attr_resource = false;
+ m_has_attr_alias = false;
+ m_text = QLatin1String("");
+}
+
+DomResourcePixmap::~DomResourcePixmap()
+{
+}
+
+void DomResourcePixmap::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("resource")) {
+ setAttributeResource(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("alias")) {
+ setAttributeAlias(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomResourcePixmap::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("resource")))
+ setAttributeResource(node.attribute(QLatin1String("resource")));
+ if (node.hasAttribute(QLatin1String("alias")))
+ setAttributeAlias(node.attribute(QLatin1String("alias")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text = QLatin1String("");
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomResourcePixmap::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourcepixmap") : tagName.toLower());
+
+ if (hasAttributeResource())
+ writer.writeAttribute(QLatin1String("resource"), attributeResource());
+
+ if (hasAttributeAlias())
+ writer.writeAttribute(QLatin1String("alias"), attributeAlias());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomResourceIcon::clear(bool clear_all)
+{
+ delete m_normalOff;
+ delete m_normalOn;
+ delete m_disabledOff;
+ delete m_disabledOn;
+ delete m_activeOff;
+ delete m_activeOn;
+ delete m_selectedOff;
+ delete m_selectedOn;
+
+ if (clear_all) {
+ m_text = QLatin1String("");
+ m_has_attr_resource = false;
+ }
+
+ m_children = 0;
+ m_normalOff = 0;
+ m_normalOn = 0;
+ m_disabledOff = 0;
+ m_disabledOn = 0;
+ m_activeOff = 0;
+ m_activeOn = 0;
+ m_selectedOff = 0;
+ m_selectedOn = 0;
+}
+
+DomResourceIcon::DomResourceIcon()
+{
+ m_children = 0;
+ m_has_attr_resource = false;
+ m_text = QLatin1String("");
+ m_normalOff = 0;
+ m_normalOn = 0;
+ m_disabledOff = 0;
+ m_disabledOn = 0;
+ m_activeOff = 0;
+ m_activeOn = 0;
+ m_selectedOff = 0;
+ m_selectedOn = 0;
+}
+
+DomResourceIcon::~DomResourceIcon()
+{
+ delete m_normalOff;
+ delete m_normalOn;
+ delete m_disabledOff;
+ delete m_disabledOn;
+ delete m_activeOff;
+ delete m_activeOn;
+ delete m_selectedOff;
+ delete m_selectedOn;
+}
+
+void DomResourceIcon::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("resource")) {
+ setAttributeResource(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("normaloff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementNormalOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("normalon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementNormalOn(v);
+ continue;
+ }
+ if (tag == QLatin1String("disabledoff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementDisabledOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("disabledon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementDisabledOn(v);
+ continue;
+ }
+ if (tag == QLatin1String("activeoff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementActiveOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("activeon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementActiveOn(v);
+ continue;
+ }
+ if (tag == QLatin1String("selectedoff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementSelectedOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("selectedon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementSelectedOn(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomResourceIcon::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("resource")))
+ setAttributeResource(node.attribute(QLatin1String("resource")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("normaloff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementNormalOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("normalon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementNormalOn(v);
+ continue;
+ }
+ if (tag == QLatin1String("disabledoff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementDisabledOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("disabledon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementDisabledOn(v);
+ continue;
+ }
+ if (tag == QLatin1String("activeoff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementActiveOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("activeon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementActiveOn(v);
+ continue;
+ }
+ if (tag == QLatin1String("selectedoff")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementSelectedOff(v);
+ continue;
+ }
+ if (tag == QLatin1String("selectedon")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementSelectedOn(v);
+ continue;
+ }
+ }
+ m_text = QLatin1String("");
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourceicon") : tagName.toLower());
+
+ if (hasAttributeResource())
+ writer.writeAttribute(QLatin1String("resource"), attributeResource());
+
+ if (m_children & NormalOff) {
+ m_normalOff->write(writer, QLatin1String("normaloff"));
+ }
+
+ if (m_children & NormalOn) {
+ m_normalOn->write(writer, QLatin1String("normalon"));
+ }
+
+ if (m_children & DisabledOff) {
+ m_disabledOff->write(writer, QLatin1String("disabledoff"));
+ }
+
+ if (m_children & DisabledOn) {
+ m_disabledOn->write(writer, QLatin1String("disabledon"));
+ }
+
+ if (m_children & ActiveOff) {
+ m_activeOff->write(writer, QLatin1String("activeoff"));
+ }
+
+ if (m_children & ActiveOn) {
+ m_activeOn->write(writer, QLatin1String("activeon"));
+ }
+
+ if (m_children & SelectedOff) {
+ m_selectedOff->write(writer, QLatin1String("selectedoff"));
+ }
+
+ if (m_children & SelectedOn) {
+ m_selectedOn->write(writer, QLatin1String("selectedon"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementNormalOff()
+{
+ DomResourcePixmap* a = m_normalOff;
+ m_normalOff = 0;
+ m_children ^= NormalOff;
+ return a;
+}
+
+void DomResourceIcon::setElementNormalOff(DomResourcePixmap* a)
+{
+ delete m_normalOff;
+ m_children |= NormalOff;
+ m_normalOff = a;
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementNormalOn()
+{
+ DomResourcePixmap* a = m_normalOn;
+ m_normalOn = 0;
+ m_children ^= NormalOn;
+ return a;
+}
+
+void DomResourceIcon::setElementNormalOn(DomResourcePixmap* a)
+{
+ delete m_normalOn;
+ m_children |= NormalOn;
+ m_normalOn = a;
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementDisabledOff()
+{
+ DomResourcePixmap* a = m_disabledOff;
+ m_disabledOff = 0;
+ m_children ^= DisabledOff;
+ return a;
+}
+
+void DomResourceIcon::setElementDisabledOff(DomResourcePixmap* a)
+{
+ delete m_disabledOff;
+ m_children |= DisabledOff;
+ m_disabledOff = a;
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementDisabledOn()
+{
+ DomResourcePixmap* a = m_disabledOn;
+ m_disabledOn = 0;
+ m_children ^= DisabledOn;
+ return a;
+}
+
+void DomResourceIcon::setElementDisabledOn(DomResourcePixmap* a)
+{
+ delete m_disabledOn;
+ m_children |= DisabledOn;
+ m_disabledOn = a;
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementActiveOff()
+{
+ DomResourcePixmap* a = m_activeOff;
+ m_activeOff = 0;
+ m_children ^= ActiveOff;
+ return a;
+}
+
+void DomResourceIcon::setElementActiveOff(DomResourcePixmap* a)
+{
+ delete m_activeOff;
+ m_children |= ActiveOff;
+ m_activeOff = a;
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementActiveOn()
+{
+ DomResourcePixmap* a = m_activeOn;
+ m_activeOn = 0;
+ m_children ^= ActiveOn;
+ return a;
+}
+
+void DomResourceIcon::setElementActiveOn(DomResourcePixmap* a)
+{
+ delete m_activeOn;
+ m_children |= ActiveOn;
+ m_activeOn = a;
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementSelectedOff()
+{
+ DomResourcePixmap* a = m_selectedOff;
+ m_selectedOff = 0;
+ m_children ^= SelectedOff;
+ return a;
+}
+
+void DomResourceIcon::setElementSelectedOff(DomResourcePixmap* a)
+{
+ delete m_selectedOff;
+ m_children |= SelectedOff;
+ m_selectedOff = a;
+}
+
+DomResourcePixmap* DomResourceIcon::takeElementSelectedOn()
+{
+ DomResourcePixmap* a = m_selectedOn;
+ m_selectedOn = 0;
+ m_children ^= SelectedOn;
+ return a;
+}
+
+void DomResourceIcon::setElementSelectedOn(DomResourcePixmap* a)
+{
+ delete m_selectedOn;
+ m_children |= SelectedOn;
+ m_selectedOn = a;
+}
+
+void DomResourceIcon::clearElementNormalOff()
+{
+ delete m_normalOff;
+ m_normalOff = 0;
+ m_children &= ~NormalOff;
+}
+
+void DomResourceIcon::clearElementNormalOn()
+{
+ delete m_normalOn;
+ m_normalOn = 0;
+ m_children &= ~NormalOn;
+}
+
+void DomResourceIcon::clearElementDisabledOff()
+{
+ delete m_disabledOff;
+ m_disabledOff = 0;
+ m_children &= ~DisabledOff;
+}
+
+void DomResourceIcon::clearElementDisabledOn()
+{
+ delete m_disabledOn;
+ m_disabledOn = 0;
+ m_children &= ~DisabledOn;
+}
+
+void DomResourceIcon::clearElementActiveOff()
+{
+ delete m_activeOff;
+ m_activeOff = 0;
+ m_children &= ~ActiveOff;
+}
+
+void DomResourceIcon::clearElementActiveOn()
+{
+ delete m_activeOn;
+ m_activeOn = 0;
+ m_children &= ~ActiveOn;
+}
+
+void DomResourceIcon::clearElementSelectedOff()
+{
+ delete m_selectedOff;
+ m_selectedOff = 0;
+ m_children &= ~SelectedOff;
+}
+
+void DomResourceIcon::clearElementSelectedOn()
+{
+ delete m_selectedOn;
+ m_selectedOn = 0;
+ m_children &= ~SelectedOn;
+}
+
+void DomString::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text = QLatin1String("");
+ m_has_attr_notr = false;
+ m_has_attr_comment = false;
+ m_has_attr_extraComment = false;
+ }
+
+ m_children = 0;
+}
+
+DomString::DomString()
+{
+ m_children = 0;
+ m_has_attr_notr = false;
+ m_has_attr_comment = false;
+ m_has_attr_extraComment = false;
+ m_text = QLatin1String("");
+}
+
+DomString::~DomString()
+{
+}
+
+void DomString::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("notr")) {
+ setAttributeNotr(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("comment")) {
+ setAttributeComment(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("extracomment")) {
+ setAttributeExtraComment(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomString::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("notr")))
+ setAttributeNotr(node.attribute(QLatin1String("notr")));
+ if (node.hasAttribute(QLatin1String("comment")))
+ setAttributeComment(node.attribute(QLatin1String("comment")));
+ if (node.hasAttribute(QLatin1String("extracomment")))
+ setAttributeExtraComment(node.attribute(QLatin1String("extracomment")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text = QLatin1String("");
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomString::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("string") : tagName.toLower());
+
+ if (hasAttributeNotr())
+ writer.writeAttribute(QLatin1String("notr"), attributeNotr());
+
+ if (hasAttributeComment())
+ writer.writeAttribute(QLatin1String("comment"), attributeComment());
+
+ if (hasAttributeExtraComment())
+ writer.writeAttribute(QLatin1String("extracomment"), attributeExtraComment());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomPointF::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+}
+
+DomPointF::DomPointF()
+{
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+}
+
+DomPointF::~DomPointF()
+{
+}
+
+void DomPointF::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(reader.readElementText().toDouble());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(reader.readElementText().toDouble());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomPointF::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(e.text().toDouble());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(e.text().toDouble());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomPointF::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("pointf") : tagName.toLower());
+
+ if (m_children & X) {
+ writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x, 'f', 15));
+ }
+
+ if (m_children & Y) {
+ writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y, 'f', 15));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomPointF::setElementX(double a)
+{
+ m_children |= X;
+ m_x = a;
+}
+
+void DomPointF::setElementY(double a)
+{
+ m_children |= Y;
+ m_y = a;
+}
+
+void DomPointF::clearElementX()
+{
+ m_children &= ~X;
+}
+
+void DomPointF::clearElementY()
+{
+ m_children &= ~Y;
+}
+
+void DomRectF::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomRectF::DomRectF()
+{
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomRectF::~DomRectF()
+{
+}
+
+void DomRectF::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(reader.readElementText().toDouble());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(reader.readElementText().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("width")) {
+ setElementWidth(reader.readElementText().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(reader.readElementText().toDouble());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomRectF::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(e.text().toDouble());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(e.text().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("width")) {
+ setElementWidth(e.text().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(e.text().toDouble());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomRectF::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("rectf") : tagName.toLower());
+
+ if (m_children & X) {
+ writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x, 'f', 15));
+ }
+
+ if (m_children & Y) {
+ writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y, 'f', 15));
+ }
+
+ if (m_children & Width) {
+ writer.writeTextElement(QLatin1String("width"), QString::number(m_width, 'f', 15));
+ }
+
+ if (m_children & Height) {
+ writer.writeTextElement(QLatin1String("height"), QString::number(m_height, 'f', 15));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomRectF::setElementX(double a)
+{
+ m_children |= X;
+ m_x = a;
+}
+
+void DomRectF::setElementY(double a)
+{
+ m_children |= Y;
+ m_y = a;
+}
+
+void DomRectF::setElementWidth(double a)
+{
+ m_children |= Width;
+ m_width = a;
+}
+
+void DomRectF::setElementHeight(double a)
+{
+ m_children |= Height;
+ m_height = a;
+}
+
+void DomRectF::clearElementX()
+{
+ m_children &= ~X;
+}
+
+void DomRectF::clearElementY()
+{
+ m_children &= ~Y;
+}
+
+void DomRectF::clearElementWidth()
+{
+ m_children &= ~Width;
+}
+
+void DomRectF::clearElementHeight()
+{
+ m_children &= ~Height;
+}
+
+void DomSizeF::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomSizeF::DomSizeF()
+{
+ m_children = 0;
+ m_width = 0;
+ m_height = 0;
+}
+
+DomSizeF::~DomSizeF()
+{
+}
+
+void DomSizeF::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("width")) {
+ setElementWidth(reader.readElementText().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(reader.readElementText().toDouble());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomSizeF::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("width")) {
+ setElementWidth(e.text().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("height")) {
+ setElementHeight(e.text().toDouble());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomSizeF::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("sizef") : tagName.toLower());
+
+ if (m_children & Width) {
+ writer.writeTextElement(QLatin1String("width"), QString::number(m_width, 'f', 15));
+ }
+
+ if (m_children & Height) {
+ writer.writeTextElement(QLatin1String("height"), QString::number(m_height, 'f', 15));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSizeF::setElementWidth(double a)
+{
+ m_children |= Width;
+ m_width = a;
+}
+
+void DomSizeF::setElementHeight(double a)
+{
+ m_children |= Height;
+ m_height = a;
+}
+
+void DomSizeF::clearElementWidth()
+{
+ m_children &= ~Width;
+}
+
+void DomSizeF::clearElementHeight()
+{
+ m_children &= ~Height;
+}
+
+void DomChar::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_unicode = 0;
+}
+
+DomChar::DomChar()
+{
+ m_children = 0;
+ m_unicode = 0;
+}
+
+DomChar::~DomChar()
+{
+}
+
+void DomChar::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("unicode")) {
+ setElementUnicode(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomChar::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("unicode")) {
+ setElementUnicode(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomChar::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("char") : tagName.toLower());
+
+ if (m_children & Unicode) {
+ writer.writeTextElement(QLatin1String("unicode"), QString::number(m_unicode));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomChar::setElementUnicode(int a)
+{
+ m_children |= Unicode;
+ m_unicode = a;
+}
+
+void DomChar::clearElementUnicode()
+{
+ m_children &= ~Unicode;
+}
+
+void DomUrl::clear(bool clear_all)
+{
+ delete m_string;
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_string = 0;
+}
+
+DomUrl::DomUrl()
+{
+ m_children = 0;
+ m_string = 0;
+}
+
+DomUrl::~DomUrl()
+{
+ delete m_string;
+}
+
+void DomUrl::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("string")) {
+ DomString *v = new DomString();
+ v->read(reader);
+ setElementString(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomUrl::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("string")) {
+ DomString *v = new DomString();
+ v->read(e);
+ setElementString(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomUrl::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("url") : tagName.toLower());
+
+ if (m_children & String) {
+ m_string->write(writer, QLatin1String("string"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+DomString* DomUrl::takeElementString()
+{
+ DomString* a = m_string;
+ m_string = 0;
+ m_children ^= String;
+ return a;
+}
+
+void DomUrl::setElementString(DomString* a)
+{
+ delete m_string;
+ m_children |= String;
+ m_string = a;
+}
+
+void DomUrl::clearElementString()
+{
+ delete m_string;
+ m_string = 0;
+ m_children &= ~String;
+}
+
+void DomProperty::clear(bool clear_all)
+{
+ delete m_color;
+ delete m_font;
+ delete m_iconSet;
+ delete m_pixmap;
+ delete m_palette;
+ delete m_point;
+ delete m_rect;
+ delete m_locale;
+ delete m_sizePolicy;
+ delete m_size;
+ delete m_string;
+ delete m_stringList;
+ delete m_date;
+ delete m_time;
+ delete m_dateTime;
+ delete m_pointF;
+ delete m_rectF;
+ delete m_sizeF;
+ delete m_char;
+ delete m_url;
+ delete m_brush;
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ m_has_attr_stdset = false;
+ m_attr_stdset = 0;
+ }
+
+ m_kind = Unknown;
+
+ m_color = 0;
+ m_cursor = 0;
+ m_font = 0;
+ m_iconSet = 0;
+ m_pixmap = 0;
+ m_palette = 0;
+ m_point = 0;
+ m_rect = 0;
+ m_locale = 0;
+ m_sizePolicy = 0;
+ m_size = 0;
+ m_string = 0;
+ m_stringList = 0;
+ m_number = 0;
+ m_float = 0.0;
+ m_double = 0;
+ m_date = 0;
+ m_time = 0;
+ m_dateTime = 0;
+ m_pointF = 0;
+ m_rectF = 0;
+ m_sizeF = 0;
+ m_longLong = 0;
+ m_char = 0;
+ m_url = 0;
+ m_UInt = 0;
+ m_uLongLong = 0;
+ m_brush = 0;
+}
+
+DomProperty::DomProperty()
+{
+ m_kind = Unknown;
+
+ m_has_attr_name = false;
+ m_has_attr_stdset = false;
+ m_attr_stdset = 0;
+ m_color = 0;
+ m_cursor = 0;
+ m_font = 0;
+ m_iconSet = 0;
+ m_pixmap = 0;
+ m_palette = 0;
+ m_point = 0;
+ m_rect = 0;
+ m_locale = 0;
+ m_sizePolicy = 0;
+ m_size = 0;
+ m_string = 0;
+ m_stringList = 0;
+ m_number = 0;
+ m_float = 0.0;
+ m_double = 0;
+ m_date = 0;
+ m_time = 0;
+ m_dateTime = 0;
+ m_pointF = 0;
+ m_rectF = 0;
+ m_sizeF = 0;
+ m_longLong = 0;
+ m_char = 0;
+ m_url = 0;
+ m_UInt = 0;
+ m_uLongLong = 0;
+ m_brush = 0;
+}
+
+DomProperty::~DomProperty()
+{
+ delete m_color;
+ delete m_font;
+ delete m_iconSet;
+ delete m_pixmap;
+ delete m_palette;
+ delete m_point;
+ delete m_rect;
+ delete m_locale;
+ delete m_sizePolicy;
+ delete m_size;
+ delete m_string;
+ delete m_stringList;
+ delete m_date;
+ delete m_time;
+ delete m_dateTime;
+ delete m_pointF;
+ delete m_rectF;
+ delete m_sizeF;
+ delete m_char;
+ delete m_url;
+ delete m_brush;
+}
+
+void DomProperty::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("stdset")) {
+ setAttributeStdset(attribute.value().toString().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("bool")) {
+ setElementBool(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(reader);
+ setElementColor(v);
+ continue;
+ }
+ if (tag == QLatin1String("cstring")) {
+ setElementCstring(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("cursor")) {
+ setElementCursor(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("cursorshape")) {
+ setElementCursorShape(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("enum")) {
+ setElementEnum(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("font")) {
+ DomFont *v = new DomFont();
+ v->read(reader);
+ setElementFont(v);
+ continue;
+ }
+ if (tag == QLatin1String("iconset")) {
+ DomResourceIcon *v = new DomResourceIcon();
+ v->read(reader);
+ setElementIconSet(v);
+ continue;
+ }
+ if (tag == QLatin1String("pixmap")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(reader);
+ setElementPixmap(v);
+ continue;
+ }
+ if (tag == QLatin1String("palette")) {
+ DomPalette *v = new DomPalette();
+ v->read(reader);
+ setElementPalette(v);
+ continue;
+ }
+ if (tag == QLatin1String("point")) {
+ DomPoint *v = new DomPoint();
+ v->read(reader);
+ setElementPoint(v);
+ continue;
+ }
+ if (tag == QLatin1String("rect")) {
+ DomRect *v = new DomRect();
+ v->read(reader);
+ setElementRect(v);
+ continue;
+ }
+ if (tag == QLatin1String("set")) {
+ setElementSet(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("locale")) {
+ DomLocale *v = new DomLocale();
+ v->read(reader);
+ setElementLocale(v);
+ continue;
+ }
+ if (tag == QLatin1String("sizepolicy")) {
+ DomSizePolicy *v = new DomSizePolicy();
+ v->read(reader);
+ setElementSizePolicy(v);
+ continue;
+ }
+ if (tag == QLatin1String("size")) {
+ DomSize *v = new DomSize();
+ v->read(reader);
+ setElementSize(v);
+ continue;
+ }
+ if (tag == QLatin1String("string")) {
+ DomString *v = new DomString();
+ v->read(reader);
+ setElementString(v);
+ continue;
+ }
+ if (tag == QLatin1String("stringlist")) {
+ DomStringList *v = new DomStringList();
+ v->read(reader);
+ setElementStringList(v);
+ continue;
+ }
+ if (tag == QLatin1String("number")) {
+ setElementNumber(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("float")) {
+ setElementFloat(reader.readElementText().toFloat());
+ continue;
+ }
+ if (tag == QLatin1String("double")) {
+ setElementDouble(reader.readElementText().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("date")) {
+ DomDate *v = new DomDate();
+ v->read(reader);
+ setElementDate(v);
+ continue;
+ }
+ if (tag == QLatin1String("time")) {
+ DomTime *v = new DomTime();
+ v->read(reader);
+ setElementTime(v);
+ continue;
+ }
+ if (tag == QLatin1String("datetime")) {
+ DomDateTime *v = new DomDateTime();
+ v->read(reader);
+ setElementDateTime(v);
+ continue;
+ }
+ if (tag == QLatin1String("pointf")) {
+ DomPointF *v = new DomPointF();
+ v->read(reader);
+ setElementPointF(v);
+ continue;
+ }
+ if (tag == QLatin1String("rectf")) {
+ DomRectF *v = new DomRectF();
+ v->read(reader);
+ setElementRectF(v);
+ continue;
+ }
+ if (tag == QLatin1String("sizef")) {
+ DomSizeF *v = new DomSizeF();
+ v->read(reader);
+ setElementSizeF(v);
+ continue;
+ }
+ if (tag == QLatin1String("longlong")) {
+ setElementLongLong(reader.readElementText().toLongLong());
+ continue;
+ }
+ if (tag == QLatin1String("char")) {
+ DomChar *v = new DomChar();
+ v->read(reader);
+ setElementChar(v);
+ continue;
+ }
+ if (tag == QLatin1String("url")) {
+ DomUrl *v = new DomUrl();
+ v->read(reader);
+ setElementUrl(v);
+ continue;
+ }
+ if (tag == QLatin1String("uint")) {
+ setElementUInt(reader.readElementText().toUInt());
+ continue;
+ }
+ if (tag == QLatin1String("ulonglong")) {
+ setElementULongLong(reader.readElementText().toULongLong());
+ continue;
+ }
+ if (tag == QLatin1String("brush")) {
+ DomBrush *v = new DomBrush();
+ v->read(reader);
+ setElementBrush(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomProperty::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+ if (node.hasAttribute(QLatin1String("stdset")))
+ setAttributeStdset(node.attribute(QLatin1String("stdset")).toInt());
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("bool")) {
+ setElementBool(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("color")) {
+ DomColor *v = new DomColor();
+ v->read(e);
+ setElementColor(v);
+ continue;
+ }
+ if (tag == QLatin1String("cstring")) {
+ setElementCstring(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("cursor")) {
+ setElementCursor(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("cursorshape")) {
+ setElementCursorShape(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("enum")) {
+ setElementEnum(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("font")) {
+ DomFont *v = new DomFont();
+ v->read(e);
+ setElementFont(v);
+ continue;
+ }
+ if (tag == QLatin1String("iconset")) {
+ DomResourceIcon *v = new DomResourceIcon();
+ v->read(e);
+ setElementIconSet(v);
+ continue;
+ }
+ if (tag == QLatin1String("pixmap")) {
+ DomResourcePixmap *v = new DomResourcePixmap();
+ v->read(e);
+ setElementPixmap(v);
+ continue;
+ }
+ if (tag == QLatin1String("palette")) {
+ DomPalette *v = new DomPalette();
+ v->read(e);
+ setElementPalette(v);
+ continue;
+ }
+ if (tag == QLatin1String("point")) {
+ DomPoint *v = new DomPoint();
+ v->read(e);
+ setElementPoint(v);
+ continue;
+ }
+ if (tag == QLatin1String("rect")) {
+ DomRect *v = new DomRect();
+ v->read(e);
+ setElementRect(v);
+ continue;
+ }
+ if (tag == QLatin1String("set")) {
+ setElementSet(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("locale")) {
+ DomLocale *v = new DomLocale();
+ v->read(e);
+ setElementLocale(v);
+ continue;
+ }
+ if (tag == QLatin1String("sizepolicy")) {
+ DomSizePolicy *v = new DomSizePolicy();
+ v->read(e);
+ setElementSizePolicy(v);
+ continue;
+ }
+ if (tag == QLatin1String("size")) {
+ DomSize *v = new DomSize();
+ v->read(e);
+ setElementSize(v);
+ continue;
+ }
+ if (tag == QLatin1String("string")) {
+ DomString *v = new DomString();
+ v->read(e);
+ setElementString(v);
+ continue;
+ }
+ if (tag == QLatin1String("stringlist")) {
+ DomStringList *v = new DomStringList();
+ v->read(e);
+ setElementStringList(v);
+ continue;
+ }
+ if (tag == QLatin1String("number")) {
+ setElementNumber(e.text().toInt());
+ continue;
+ }
+ if (tag == QLatin1String("float")) {
+ setElementFloat(e.text().toFloat());
+ continue;
+ }
+ if (tag == QLatin1String("double")) {
+ setElementDouble(e.text().toDouble());
+ continue;
+ }
+ if (tag == QLatin1String("date")) {
+ DomDate *v = new DomDate();
+ v->read(e);
+ setElementDate(v);
+ continue;
+ }
+ if (tag == QLatin1String("time")) {
+ DomTime *v = new DomTime();
+ v->read(e);
+ setElementTime(v);
+ continue;
+ }
+ if (tag == QLatin1String("datetime")) {
+ DomDateTime *v = new DomDateTime();
+ v->read(e);
+ setElementDateTime(v);
+ continue;
+ }
+ if (tag == QLatin1String("pointf")) {
+ DomPointF *v = new DomPointF();
+ v->read(e);
+ setElementPointF(v);
+ continue;
+ }
+ if (tag == QLatin1String("rectf")) {
+ DomRectF *v = new DomRectF();
+ v->read(e);
+ setElementRectF(v);
+ continue;
+ }
+ if (tag == QLatin1String("sizef")) {
+ DomSizeF *v = new DomSizeF();
+ v->read(e);
+ setElementSizeF(v);
+ continue;
+ }
+ if (tag == QLatin1String("longlong")) {
+ setElementLongLong(e.text().toLongLong());
+ continue;
+ }
+ if (tag == QLatin1String("char")) {
+ DomChar *v = new DomChar();
+ v->read(e);
+ setElementChar(v);
+ continue;
+ }
+ if (tag == QLatin1String("url")) {
+ DomUrl *v = new DomUrl();
+ v->read(e);
+ setElementUrl(v);
+ continue;
+ }
+ if (tag == QLatin1String("uint")) {
+ setElementUInt(e.text().toUInt());
+ continue;
+ }
+ if (tag == QLatin1String("ulonglong")) {
+ setElementULongLong(e.text().toULongLong());
+ continue;
+ }
+ if (tag == QLatin1String("brush")) {
+ DomBrush *v = new DomBrush();
+ v->read(e);
+ setElementBrush(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomProperty::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("property") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ if (hasAttributeStdset())
+ writer.writeAttribute(QLatin1String("stdset"), QString::number(attributeStdset()));
+
+ switch (kind()) {
+ case Bool: {
+ writer.writeTextElement(QLatin1String("bool"), elementBool());
+ break;
+ }
+ case Color: {
+ DomColor* v = elementColor();
+ if (v != 0) {
+ v->write(writer, QLatin1String("color"));
+ }
+ break;
+ }
+ case Cstring: {
+ writer.writeTextElement(QLatin1String("cstring"), elementCstring());
+ break;
+ }
+ case Cursor: {
+ writer.writeTextElement(QLatin1String("cursor"), QString::number(elementCursor()));
+ break;
+ }
+ case CursorShape: {
+ writer.writeTextElement(QLatin1String("cursorShape"), elementCursorShape());
+ break;
+ }
+ case Enum: {
+ writer.writeTextElement(QLatin1String("enum"), elementEnum());
+ break;
+ }
+ case Font: {
+ DomFont* v = elementFont();
+ if (v != 0) {
+ v->write(writer, QLatin1String("font"));
+ }
+ break;
+ }
+ case IconSet: {
+ DomResourceIcon* v = elementIconSet();
+ if (v != 0) {
+ v->write(writer, QLatin1String("iconset"));
+ }
+ break;
+ }
+ case Pixmap: {
+ DomResourcePixmap* v = elementPixmap();
+ if (v != 0) {
+ v->write(writer, QLatin1String("pixmap"));
+ }
+ break;
+ }
+ case Palette: {
+ DomPalette* v = elementPalette();
+ if (v != 0) {
+ v->write(writer, QLatin1String("palette"));
+ }
+ break;
+ }
+ case Point: {
+ DomPoint* v = elementPoint();
+ if (v != 0) {
+ v->write(writer, QLatin1String("point"));
+ }
+ break;
+ }
+ case Rect: {
+ DomRect* v = elementRect();
+ if (v != 0) {
+ v->write(writer, QLatin1String("rect"));
+ }
+ break;
+ }
+ case Set: {
+ writer.writeTextElement(QLatin1String("set"), elementSet());
+ break;
+ }
+ case Locale: {
+ DomLocale* v = elementLocale();
+ if (v != 0) {
+ v->write(writer, QLatin1String("locale"));
+ }
+ break;
+ }
+ case SizePolicy: {
+ DomSizePolicy* v = elementSizePolicy();
+ if (v != 0) {
+ v->write(writer, QLatin1String("sizepolicy"));
+ }
+ break;
+ }
+ case Size: {
+ DomSize* v = elementSize();
+ if (v != 0) {
+ v->write(writer, QLatin1String("size"));
+ }
+ break;
+ }
+ case String: {
+ DomString* v = elementString();
+ if (v != 0) {
+ v->write(writer, QLatin1String("string"));
+ }
+ break;
+ }
+ case StringList: {
+ DomStringList* v = elementStringList();
+ if (v != 0) {
+ v->write(writer, QLatin1String("stringlist"));
+ }
+ break;
+ }
+ case Number: {
+ writer.writeTextElement(QLatin1String("number"), QString::number(elementNumber()));
+ break;
+ }
+ case Float: {
+ writer.writeTextElement(QLatin1String("float"), QString::number(elementFloat(), 'f', 8));
+ break;
+ }
+ case Double: {
+ writer.writeTextElement(QLatin1String("double"), QString::number(elementDouble(), 'f', 15));
+ break;
+ }
+ case Date: {
+ DomDate* v = elementDate();
+ if (v != 0) {
+ v->write(writer, QLatin1String("date"));
+ }
+ break;
+ }
+ case Time: {
+ DomTime* v = elementTime();
+ if (v != 0) {
+ v->write(writer, QLatin1String("time"));
+ }
+ break;
+ }
+ case DateTime: {
+ DomDateTime* v = elementDateTime();
+ if (v != 0) {
+ v->write(writer, QLatin1String("datetime"));
+ }
+ break;
+ }
+ case PointF: {
+ DomPointF* v = elementPointF();
+ if (v != 0) {
+ v->write(writer, QLatin1String("pointf"));
+ }
+ break;
+ }
+ case RectF: {
+ DomRectF* v = elementRectF();
+ if (v != 0) {
+ v->write(writer, QLatin1String("rectf"));
+ }
+ break;
+ }
+ case SizeF: {
+ DomSizeF* v = elementSizeF();
+ if (v != 0) {
+ v->write(writer, QLatin1String("sizef"));
+ }
+ break;
+ }
+ case LongLong: {
+ writer.writeTextElement(QLatin1String("longLong"), QString::number(elementLongLong()));
+ break;
+ }
+ case Char: {
+ DomChar* v = elementChar();
+ if (v != 0) {
+ v->write(writer, QLatin1String("char"));
+ }
+ break;
+ }
+ case Url: {
+ DomUrl* v = elementUrl();
+ if (v != 0) {
+ v->write(writer, QLatin1String("url"));
+ }
+ break;
+ }
+ case UInt: {
+ writer.writeTextElement(QLatin1String("UInt"), QString::number(elementUInt()));
+ break;
+ }
+ case ULongLong: {
+ writer.writeTextElement(QLatin1String("uLongLong"), QString::number(elementULongLong()));
+ break;
+ }
+ case Brush: {
+ DomBrush* v = elementBrush();
+ if (v != 0) {
+ v->write(writer, QLatin1String("brush"));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomProperty::setElementBool(const QString& a)
+{
+ clear(false);
+ m_kind = Bool;
+ m_bool = a;
+}
+
+DomColor* DomProperty::takeElementColor()
+{
+ DomColor* a = m_color;
+ m_color = 0;
+ return a;
+}
+
+void DomProperty::setElementColor(DomColor* a)
+{
+ clear(false);
+ m_kind = Color;
+ m_color = a;
+}
+
+void DomProperty::setElementCstring(const QString& a)
+{
+ clear(false);
+ m_kind = Cstring;
+ m_cstring = a;
+}
+
+void DomProperty::setElementCursor(int a)
+{
+ clear(false);
+ m_kind = Cursor;
+ m_cursor = a;
+}
+
+void DomProperty::setElementCursorShape(const QString& a)
+{
+ clear(false);
+ m_kind = CursorShape;
+ m_cursorShape = a;
+}
+
+void DomProperty::setElementEnum(const QString& a)
+{
+ clear(false);
+ m_kind = Enum;
+ m_enum = a;
+}
+
+DomFont* DomProperty::takeElementFont()
+{
+ DomFont* a = m_font;
+ m_font = 0;
+ return a;
+}
+
+void DomProperty::setElementFont(DomFont* a)
+{
+ clear(false);
+ m_kind = Font;
+ m_font = a;
+}
+
+DomResourceIcon* DomProperty::takeElementIconSet()
+{
+ DomResourceIcon* a = m_iconSet;
+ m_iconSet = 0;
+ return a;
+}
+
+void DomProperty::setElementIconSet(DomResourceIcon* a)
+{
+ clear(false);
+ m_kind = IconSet;
+ m_iconSet = a;
+}
+
+DomResourcePixmap* DomProperty::takeElementPixmap()
+{
+ DomResourcePixmap* a = m_pixmap;
+ m_pixmap = 0;
+ return a;
+}
+
+void DomProperty::setElementPixmap(DomResourcePixmap* a)
+{
+ clear(false);
+ m_kind = Pixmap;
+ m_pixmap = a;
+}
+
+DomPalette* DomProperty::takeElementPalette()
+{
+ DomPalette* a = m_palette;
+ m_palette = 0;
+ return a;
+}
+
+void DomProperty::setElementPalette(DomPalette* a)
+{
+ clear(false);
+ m_kind = Palette;
+ m_palette = a;
+}
+
+DomPoint* DomProperty::takeElementPoint()
+{
+ DomPoint* a = m_point;
+ m_point = 0;
+ return a;
+}
+
+void DomProperty::setElementPoint(DomPoint* a)
+{
+ clear(false);
+ m_kind = Point;
+ m_point = a;
+}
+
+DomRect* DomProperty::takeElementRect()
+{
+ DomRect* a = m_rect;
+ m_rect = 0;
+ return a;
+}
+
+void DomProperty::setElementRect(DomRect* a)
+{
+ clear(false);
+ m_kind = Rect;
+ m_rect = a;
+}
+
+void DomProperty::setElementSet(const QString& a)
+{
+ clear(false);
+ m_kind = Set;
+ m_set = a;
+}
+
+DomLocale* DomProperty::takeElementLocale()
+{
+ DomLocale* a = m_locale;
+ m_locale = 0;
+ return a;
+}
+
+void DomProperty::setElementLocale(DomLocale* a)
+{
+ clear(false);
+ m_kind = Locale;
+ m_locale = a;
+}
+
+DomSizePolicy* DomProperty::takeElementSizePolicy()
+{
+ DomSizePolicy* a = m_sizePolicy;
+ m_sizePolicy = 0;
+ return a;
+}
+
+void DomProperty::setElementSizePolicy(DomSizePolicy* a)
+{
+ clear(false);
+ m_kind = SizePolicy;
+ m_sizePolicy = a;
+}
+
+DomSize* DomProperty::takeElementSize()
+{
+ DomSize* a = m_size;
+ m_size = 0;
+ return a;
+}
+
+void DomProperty::setElementSize(DomSize* a)
+{
+ clear(false);
+ m_kind = Size;
+ m_size = a;
+}
+
+DomString* DomProperty::takeElementString()
+{
+ DomString* a = m_string;
+ m_string = 0;
+ return a;
+}
+
+void DomProperty::setElementString(DomString* a)
+{
+ clear(false);
+ m_kind = String;
+ m_string = a;
+}
+
+DomStringList* DomProperty::takeElementStringList()
+{
+ DomStringList* a = m_stringList;
+ m_stringList = 0;
+ return a;
+}
+
+void DomProperty::setElementStringList(DomStringList* a)
+{
+ clear(false);
+ m_kind = StringList;
+ m_stringList = a;
+}
+
+void DomProperty::setElementNumber(int a)
+{
+ clear(false);
+ m_kind = Number;
+ m_number = a;
+}
+
+void DomProperty::setElementFloat(float a)
+{
+ clear(false);
+ m_kind = Float;
+ m_float = a;
+}
+
+void DomProperty::setElementDouble(double a)
+{
+ clear(false);
+ m_kind = Double;
+ m_double = a;
+}
+
+DomDate* DomProperty::takeElementDate()
+{
+ DomDate* a = m_date;
+ m_date = 0;
+ return a;
+}
+
+void DomProperty::setElementDate(DomDate* a)
+{
+ clear(false);
+ m_kind = Date;
+ m_date = a;
+}
+
+DomTime* DomProperty::takeElementTime()
+{
+ DomTime* a = m_time;
+ m_time = 0;
+ return a;
+}
+
+void DomProperty::setElementTime(DomTime* a)
+{
+ clear(false);
+ m_kind = Time;
+ m_time = a;
+}
+
+DomDateTime* DomProperty::takeElementDateTime()
+{
+ DomDateTime* a = m_dateTime;
+ m_dateTime = 0;
+ return a;
+}
+
+void DomProperty::setElementDateTime(DomDateTime* a)
+{
+ clear(false);
+ m_kind = DateTime;
+ m_dateTime = a;
+}
+
+DomPointF* DomProperty::takeElementPointF()
+{
+ DomPointF* a = m_pointF;
+ m_pointF = 0;
+ return a;
+}
+
+void DomProperty::setElementPointF(DomPointF* a)
+{
+ clear(false);
+ m_kind = PointF;
+ m_pointF = a;
+}
+
+DomRectF* DomProperty::takeElementRectF()
+{
+ DomRectF* a = m_rectF;
+ m_rectF = 0;
+ return a;
+}
+
+void DomProperty::setElementRectF(DomRectF* a)
+{
+ clear(false);
+ m_kind = RectF;
+ m_rectF = a;
+}
+
+DomSizeF* DomProperty::takeElementSizeF()
+{
+ DomSizeF* a = m_sizeF;
+ m_sizeF = 0;
+ return a;
+}
+
+void DomProperty::setElementSizeF(DomSizeF* a)
+{
+ clear(false);
+ m_kind = SizeF;
+ m_sizeF = a;
+}
+
+void DomProperty::setElementLongLong(qlonglong a)
+{
+ clear(false);
+ m_kind = LongLong;
+ m_longLong = a;
+}
+
+DomChar* DomProperty::takeElementChar()
+{
+ DomChar* a = m_char;
+ m_char = 0;
+ return a;
+}
+
+void DomProperty::setElementChar(DomChar* a)
+{
+ clear(false);
+ m_kind = Char;
+ m_char = a;
+}
+
+DomUrl* DomProperty::takeElementUrl()
+{
+ DomUrl* a = m_url;
+ m_url = 0;
+ return a;
+}
+
+void DomProperty::setElementUrl(DomUrl* a)
+{
+ clear(false);
+ m_kind = Url;
+ m_url = a;
+}
+
+void DomProperty::setElementUInt(uint a)
+{
+ clear(false);
+ m_kind = UInt;
+ m_UInt = a;
+}
+
+void DomProperty::setElementULongLong(qulonglong a)
+{
+ clear(false);
+ m_kind = ULongLong;
+ m_uLongLong = a;
+}
+
+DomBrush* DomProperty::takeElementBrush()
+{
+ DomBrush* a = m_brush;
+ m_brush = 0;
+ return a;
+}
+
+void DomProperty::setElementBrush(DomBrush* a)
+{
+ clear(false);
+ m_kind = Brush;
+ m_brush = a;
+}
+
+void DomConnections::clear(bool clear_all)
+{
+ qDeleteAll(m_connection);
+ m_connection.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomConnections::DomConnections()
+{
+ m_children = 0;
+}
+
+DomConnections::~DomConnections()
+{
+ qDeleteAll(m_connection);
+ m_connection.clear();
+}
+
+void DomConnections::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("connection")) {
+ DomConnection *v = new DomConnection();
+ v->read(reader);
+ m_connection.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomConnections::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("connection")) {
+ DomConnection *v = new DomConnection();
+ v->read(e);
+ m_connection.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomConnections::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connections") : tagName.toLower());
+
+ for (int i = 0; i < m_connection.size(); ++i) {
+ DomConnection* v = m_connection[i];
+ v->write(writer, QLatin1String("connection"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomConnections::setElementConnection(const QList<DomConnection*>& a)
+{
+ m_children |= Connection;
+ m_connection = a;
+}
+
+void DomConnection::clear(bool clear_all)
+{
+ delete m_hints;
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+ m_hints = 0;
+}
+
+DomConnection::DomConnection()
+{
+ m_children = 0;
+ m_hints = 0;
+}
+
+DomConnection::~DomConnection()
+{
+ delete m_hints;
+}
+
+void DomConnection::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("sender")) {
+ setElementSender(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("signal")) {
+ setElementSignal(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("receiver")) {
+ setElementReceiver(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("slot")) {
+ setElementSlot(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("hints")) {
+ DomConnectionHints *v = new DomConnectionHints();
+ v->read(reader);
+ setElementHints(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomConnection::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("sender")) {
+ setElementSender(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("signal")) {
+ setElementSignal(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("receiver")) {
+ setElementReceiver(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("slot")) {
+ setElementSlot(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("hints")) {
+ DomConnectionHints *v = new DomConnectionHints();
+ v->read(e);
+ setElementHints(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomConnection::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connection") : tagName.toLower());
+
+ if (m_children & Sender) {
+ writer.writeTextElement(QLatin1String("sender"), m_sender);
+ }
+
+ if (m_children & Signal) {
+ writer.writeTextElement(QLatin1String("signal"), m_signal);
+ }
+
+ if (m_children & Receiver) {
+ writer.writeTextElement(QLatin1String("receiver"), m_receiver);
+ }
+
+ if (m_children & Slot) {
+ writer.writeTextElement(QLatin1String("slot"), m_slot);
+ }
+
+ if (m_children & Hints) {
+ m_hints->write(writer, QLatin1String("hints"));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomConnection::setElementSender(const QString& a)
+{
+ m_children |= Sender;
+ m_sender = a;
+}
+
+void DomConnection::setElementSignal(const QString& a)
+{
+ m_children |= Signal;
+ m_signal = a;
+}
+
+void DomConnection::setElementReceiver(const QString& a)
+{
+ m_children |= Receiver;
+ m_receiver = a;
+}
+
+void DomConnection::setElementSlot(const QString& a)
+{
+ m_children |= Slot;
+ m_slot = a;
+}
+
+DomConnectionHints* DomConnection::takeElementHints()
+{
+ DomConnectionHints* a = m_hints;
+ m_hints = 0;
+ m_children ^= Hints;
+ return a;
+}
+
+void DomConnection::setElementHints(DomConnectionHints* a)
+{
+ delete m_hints;
+ m_children |= Hints;
+ m_hints = a;
+}
+
+void DomConnection::clearElementSender()
+{
+ m_children &= ~Sender;
+}
+
+void DomConnection::clearElementSignal()
+{
+ m_children &= ~Signal;
+}
+
+void DomConnection::clearElementReceiver()
+{
+ m_children &= ~Receiver;
+}
+
+void DomConnection::clearElementSlot()
+{
+ m_children &= ~Slot;
+}
+
+void DomConnection::clearElementHints()
+{
+ delete m_hints;
+ m_hints = 0;
+ m_children &= ~Hints;
+}
+
+void DomConnectionHints::clear(bool clear_all)
+{
+ qDeleteAll(m_hint);
+ m_hint.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomConnectionHints::DomConnectionHints()
+{
+ m_children = 0;
+}
+
+DomConnectionHints::~DomConnectionHints()
+{
+ qDeleteAll(m_hint);
+ m_hint.clear();
+}
+
+void DomConnectionHints::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("hint")) {
+ DomConnectionHint *v = new DomConnectionHint();
+ v->read(reader);
+ m_hint.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomConnectionHints::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("hint")) {
+ DomConnectionHint *v = new DomConnectionHint();
+ v->read(e);
+ m_hint.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomConnectionHints::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connectionhints") : tagName.toLower());
+
+ for (int i = 0; i < m_hint.size(); ++i) {
+ DomConnectionHint* v = m_hint[i];
+ v->write(writer, QLatin1String("hint"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomConnectionHints::setElementHint(const QList<DomConnectionHint*>& a)
+{
+ m_children |= Hint;
+ m_hint = a;
+}
+
+void DomConnectionHint::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_type = false;
+ }
+
+ m_children = 0;
+ m_x = 0;
+ m_y = 0;
+}
+
+DomConnectionHint::DomConnectionHint()
+{
+ m_children = 0;
+ m_has_attr_type = false;
+ m_x = 0;
+ m_y = 0;
+}
+
+DomConnectionHint::~DomConnectionHint()
+{
+}
+
+void DomConnectionHint::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("type")) {
+ setAttributeType(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(reader.readElementText().toInt());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(reader.readElementText().toInt());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomConnectionHint::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("type")))
+ setAttributeType(node.attribute(QLatin1String("type")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QString(QLatin1Char('x'))) {
+ setElementX(e.text().toInt());
+ continue;
+ }
+ if (tag == QString(QLatin1Char('y'))) {
+ setElementY(e.text().toInt());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomConnectionHint::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connectionhint") : tagName.toLower());
+
+ if (hasAttributeType())
+ writer.writeAttribute(QLatin1String("type"), attributeType());
+
+ if (m_children & X) {
+ writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
+ }
+
+ if (m_children & Y) {
+ writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
+ }
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomConnectionHint::setElementX(int a)
+{
+ m_children |= X;
+ m_x = a;
+}
+
+void DomConnectionHint::setElementY(int a)
+{
+ m_children |= Y;
+ m_y = a;
+}
+
+void DomConnectionHint::clearElementX()
+{
+ m_children &= ~X;
+}
+
+void DomConnectionHint::clearElementY()
+{
+ m_children &= ~Y;
+}
+
+void DomScript::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_source = false;
+ m_has_attr_language = false;
+ }
+
+ m_children = 0;
+}
+
+DomScript::DomScript()
+{
+ m_children = 0;
+ m_has_attr_source = false;
+ m_has_attr_language = false;
+}
+
+DomScript::~DomScript()
+{
+}
+
+void DomScript::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("source")) {
+ setAttributeSource(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("language")) {
+ setAttributeLanguage(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomScript::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("source")))
+ setAttributeSource(node.attribute(QLatin1String("source")));
+ if (node.hasAttribute(QLatin1String("language")))
+ setAttributeLanguage(node.attribute(QLatin1String("language")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomScript::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("script") : tagName.toLower());
+
+ if (hasAttributeSource())
+ writer.writeAttribute(QLatin1String("source"), attributeSource());
+
+ if (hasAttributeLanguage())
+ writer.writeAttribute(QLatin1String("language"), attributeLanguage());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomWidgetData::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomWidgetData::DomWidgetData()
+{
+ m_children = 0;
+}
+
+DomWidgetData::~DomWidgetData()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+}
+
+void DomWidgetData::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomWidgetData::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomWidgetData::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("widgetdata") : tagName.toLower());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomWidgetData::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomDesignerData::clear(bool clear_all)
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomDesignerData::DomDesignerData()
+{
+ m_children = 0;
+}
+
+DomDesignerData::~DomDesignerData()
+{
+ qDeleteAll(m_property);
+ m_property.clear();
+}
+
+void DomDesignerData::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(reader);
+ m_property.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomDesignerData::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("property")) {
+ DomProperty *v = new DomProperty();
+ v->read(e);
+ m_property.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomDesignerData::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("designerdata") : tagName.toLower());
+
+ for (int i = 0; i < m_property.size(); ++i) {
+ DomProperty* v = m_property[i];
+ v->write(writer, QLatin1String("property"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomDesignerData::setElementProperty(const QList<DomProperty*>& a)
+{
+ m_children |= Property;
+ m_property = a;
+}
+
+void DomSlots::clear(bool clear_all)
+{
+ m_signal.clear();
+ m_slot.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomSlots::DomSlots()
+{
+ m_children = 0;
+}
+
+DomSlots::~DomSlots()
+{
+ m_signal.clear();
+ m_slot.clear();
+}
+
+void DomSlots::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("signal")) {
+ m_signal.append(reader.readElementText());
+ continue;
+ }
+ if (tag == QLatin1String("slot")) {
+ m_slot.append(reader.readElementText());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomSlots::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("signal")) {
+ m_signal.append(e.text());
+ continue;
+ }
+ if (tag == QLatin1String("slot")) {
+ m_slot.append(e.text());
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomSlots::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("slots") : tagName.toLower());
+
+ for (int i = 0; i < m_signal.size(); ++i) {
+ QString v = m_signal[i];
+ writer.writeTextElement(QLatin1String("signal"), v);
+ }
+ for (int i = 0; i < m_slot.size(); ++i) {
+ QString v = m_slot[i];
+ writer.writeTextElement(QLatin1String("slot"), v);
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomSlots::setElementSignal(const QStringList& a)
+{
+ m_children |= Signal;
+ m_signal = a;
+}
+
+void DomSlots::setElementSlot(const QStringList& a)
+{
+ m_children |= Slot;
+ m_slot = a;
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/designer/src/lib/uilib/ui4_p.h b/tools/designer/src/lib/uilib/ui4_p.h
new file mode 100644
index 0000000000..df02a39230
--- /dev/null
+++ b/tools/designer/src/lib/uilib/ui4_p.h
@@ -0,0 +1,3696 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// THIS FILE IS AUTOMATICALLY GENERATED
+
+#ifndef UI4_H
+#define UI4_H
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QXmlStreamWriter>
+#include <QtCore/qglobal.h>
+
+#if defined(QT_UIC3)
+ #define QUILOADER_QDOM_READ
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QUILOADER_QDOM_READ
+ class QDomElement;
+#endif
+
+
+#define QDESIGNER_UILIB_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_UILIB_IMPORT Q_DECL_IMPORT
+
+#if defined(QT_DESIGNER_STATIC) || defined(QT_UIC) || defined(QT_UIC3)
+# define QDESIGNER_UILIB_EXPORT
+#elif defined(QDESIGNER_UILIB_LIBRARY)
+# define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_EXTERN
+#else
+# define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_IMPORT
+#endif
+
+#ifndef QDESIGNER_UILIB_EXPORT
+# define QDESIGNER_UILIB_EXPORT
+#endif
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+
+/*******************************************************************************
+** Forward declarations
+*/
+
+class DomUI;
+class DomIncludes;
+class DomInclude;
+class DomResources;
+class DomResource;
+class DomActionGroup;
+class DomAction;
+class DomActionRef;
+class DomButtonGroup;
+class DomButtonGroups;
+class DomImages;
+class DomImage;
+class DomImageData;
+class DomCustomWidgets;
+class DomHeader;
+class DomCustomWidget;
+class DomProperties;
+class DomPropertyData;
+class DomSizePolicyData;
+class DomLayoutDefault;
+class DomLayoutFunction;
+class DomTabStops;
+class DomLayout;
+class DomLayoutItem;
+class DomRow;
+class DomColumn;
+class DomItem;
+class DomWidget;
+class DomSpacer;
+class DomColor;
+class DomGradientStop;
+class DomGradient;
+class DomBrush;
+class DomColorRole;
+class DomColorGroup;
+class DomPalette;
+class DomFont;
+class DomPoint;
+class DomRect;
+class DomLocale;
+class DomSizePolicy;
+class DomSize;
+class DomDate;
+class DomTime;
+class DomDateTime;
+class DomStringList;
+class DomResourcePixmap;
+class DomResourceIcon;
+class DomString;
+class DomPointF;
+class DomRectF;
+class DomSizeF;
+class DomChar;
+class DomUrl;
+class DomProperty;
+class DomConnections;
+class DomConnection;
+class DomConnectionHints;
+class DomConnectionHint;
+class DomScript;
+class DomWidgetData;
+class DomDesignerData;
+class DomSlots;
+
+/*******************************************************************************
+** Declarations
+*/
+
+class QDESIGNER_UILIB_EXPORT DomUI {
+public:
+ DomUI();
+ ~DomUI();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeVersion() const { return m_has_attr_version; }
+ inline QString attributeVersion() const { return m_attr_version; }
+ inline void setAttributeVersion(const QString& a) { m_attr_version = a; m_has_attr_version = true; }
+ inline void clearAttributeVersion() { m_has_attr_version = false; }
+
+ inline bool hasAttributeLanguage() const { return m_has_attr_language; }
+ inline QString attributeLanguage() const { return m_attr_language; }
+ inline void setAttributeLanguage(const QString& a) { m_attr_language = a; m_has_attr_language = true; }
+ inline void clearAttributeLanguage() { m_has_attr_language = false; }
+
+ inline bool hasAttributeDisplayname() const { return m_has_attr_displayname; }
+ inline QString attributeDisplayname() const { return m_attr_displayname; }
+ inline void setAttributeDisplayname(const QString& a) { m_attr_displayname = a; m_has_attr_displayname = true; }
+ inline void clearAttributeDisplayname() { m_has_attr_displayname = false; }
+
+ inline bool hasAttributeStdsetdef() const { return m_has_attr_stdsetdef; }
+ inline int attributeStdsetdef() const { return m_attr_stdsetdef; }
+ inline void setAttributeStdsetdef(int a) { m_attr_stdsetdef = a; m_has_attr_stdsetdef = true; }
+ inline void clearAttributeStdsetdef() { m_has_attr_stdsetdef = false; }
+
+ inline bool hasAttributeStdSetDef() const { return m_has_attr_stdSetDef; }
+ inline int attributeStdSetDef() const { return m_attr_stdSetDef; }
+ inline void setAttributeStdSetDef(int a) { m_attr_stdSetDef = a; m_has_attr_stdSetDef = true; }
+ inline void clearAttributeStdSetDef() { m_has_attr_stdSetDef = false; }
+
+ // child element accessors
+ inline QString elementAuthor() const { return m_author; }
+ void setElementAuthor(const QString& a);
+ inline bool hasElementAuthor() const { return m_children & Author; }
+ void clearElementAuthor();
+
+ inline QString elementComment() const { return m_comment; }
+ void setElementComment(const QString& a);
+ inline bool hasElementComment() const { return m_children & Comment; }
+ void clearElementComment();
+
+ inline QString elementExportMacro() const { return m_exportMacro; }
+ void setElementExportMacro(const QString& a);
+ inline bool hasElementExportMacro() const { return m_children & ExportMacro; }
+ void clearElementExportMacro();
+
+ inline QString elementClass() const { return m_class; }
+ void setElementClass(const QString& a);
+ inline bool hasElementClass() const { return m_children & Class; }
+ void clearElementClass();
+
+ inline DomWidget* elementWidget() const { return m_widget; }
+ DomWidget* takeElementWidget();
+ void setElementWidget(DomWidget* a);
+ inline bool hasElementWidget() const { return m_children & Widget; }
+ void clearElementWidget();
+
+ inline DomLayoutDefault* elementLayoutDefault() const { return m_layoutDefault; }
+ DomLayoutDefault* takeElementLayoutDefault();
+ void setElementLayoutDefault(DomLayoutDefault* a);
+ inline bool hasElementLayoutDefault() const { return m_children & LayoutDefault; }
+ void clearElementLayoutDefault();
+
+ inline DomLayoutFunction* elementLayoutFunction() const { return m_layoutFunction; }
+ DomLayoutFunction* takeElementLayoutFunction();
+ void setElementLayoutFunction(DomLayoutFunction* a);
+ inline bool hasElementLayoutFunction() const { return m_children & LayoutFunction; }
+ void clearElementLayoutFunction();
+
+ inline QString elementPixmapFunction() const { return m_pixmapFunction; }
+ void setElementPixmapFunction(const QString& a);
+ inline bool hasElementPixmapFunction() const { return m_children & PixmapFunction; }
+ void clearElementPixmapFunction();
+
+ inline DomCustomWidgets* elementCustomWidgets() const { return m_customWidgets; }
+ DomCustomWidgets* takeElementCustomWidgets();
+ void setElementCustomWidgets(DomCustomWidgets* a);
+ inline bool hasElementCustomWidgets() const { return m_children & CustomWidgets; }
+ void clearElementCustomWidgets();
+
+ inline DomTabStops* elementTabStops() const { return m_tabStops; }
+ DomTabStops* takeElementTabStops();
+ void setElementTabStops(DomTabStops* a);
+ inline bool hasElementTabStops() const { return m_children & TabStops; }
+ void clearElementTabStops();
+
+ inline DomImages* elementImages() const { return m_images; }
+ DomImages* takeElementImages();
+ void setElementImages(DomImages* a);
+ inline bool hasElementImages() const { return m_children & Images; }
+ void clearElementImages();
+
+ inline DomIncludes* elementIncludes() const { return m_includes; }
+ DomIncludes* takeElementIncludes();
+ void setElementIncludes(DomIncludes* a);
+ inline bool hasElementIncludes() const { return m_children & Includes; }
+ void clearElementIncludes();
+
+ inline DomResources* elementResources() const { return m_resources; }
+ DomResources* takeElementResources();
+ void setElementResources(DomResources* a);
+ inline bool hasElementResources() const { return m_children & Resources; }
+ void clearElementResources();
+
+ inline DomConnections* elementConnections() const { return m_connections; }
+ DomConnections* takeElementConnections();
+ void setElementConnections(DomConnections* a);
+ inline bool hasElementConnections() const { return m_children & Connections; }
+ void clearElementConnections();
+
+ inline DomDesignerData* elementDesignerdata() const { return m_designerdata; }
+ DomDesignerData* takeElementDesignerdata();
+ void setElementDesignerdata(DomDesignerData* a);
+ inline bool hasElementDesignerdata() const { return m_children & Designerdata; }
+ void clearElementDesignerdata();
+
+ inline DomSlots* elementSlots() const { return m_slots; }
+ DomSlots* takeElementSlots();
+ void setElementSlots(DomSlots* a);
+ inline bool hasElementSlots() const { return m_children & Slots; }
+ void clearElementSlots();
+
+ inline DomButtonGroups* elementButtonGroups() const { return m_buttonGroups; }
+ DomButtonGroups* takeElementButtonGroups();
+ void setElementButtonGroups(DomButtonGroups* a);
+ inline bool hasElementButtonGroups() const { return m_children & ButtonGroups; }
+ void clearElementButtonGroups();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_version;
+ bool m_has_attr_version;
+
+ QString m_attr_language;
+ bool m_has_attr_language;
+
+ QString m_attr_displayname;
+ bool m_has_attr_displayname;
+
+ int m_attr_stdsetdef;
+ bool m_has_attr_stdsetdef;
+
+ int m_attr_stdSetDef;
+ bool m_has_attr_stdSetDef;
+
+ // child element data
+ uint m_children;
+ QString m_author;
+ QString m_comment;
+ QString m_exportMacro;
+ QString m_class;
+ DomWidget* m_widget;
+ DomLayoutDefault* m_layoutDefault;
+ DomLayoutFunction* m_layoutFunction;
+ QString m_pixmapFunction;
+ DomCustomWidgets* m_customWidgets;
+ DomTabStops* m_tabStops;
+ DomImages* m_images;
+ DomIncludes* m_includes;
+ DomResources* m_resources;
+ DomConnections* m_connections;
+ DomDesignerData* m_designerdata;
+ DomSlots* m_slots;
+ DomButtonGroups* m_buttonGroups;
+ enum Child {
+ Author = 1,
+ Comment = 2,
+ ExportMacro = 4,
+ Class = 8,
+ Widget = 16,
+ LayoutDefault = 32,
+ LayoutFunction = 64,
+ PixmapFunction = 128,
+ CustomWidgets = 256,
+ TabStops = 512,
+ Images = 1024,
+ Includes = 2048,
+ Resources = 4096,
+ Connections = 8192,
+ Designerdata = 16384,
+ Slots = 32768,
+ ButtonGroups = 65536
+ };
+
+ DomUI(const DomUI &other);
+ void operator = (const DomUI&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomIncludes {
+public:
+ DomIncludes();
+ ~DomIncludes();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomInclude*> elementInclude() const { return m_include; }
+ void setElementInclude(const QList<DomInclude*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomInclude*> m_include;
+ enum Child {
+ Include = 1
+ };
+
+ DomIncludes(const DomIncludes &other);
+ void operator = (const DomIncludes&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomInclude {
+public:
+ DomInclude();
+ ~DomInclude();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeLocation() const { return m_has_attr_location; }
+ inline QString attributeLocation() const { return m_attr_location; }
+ inline void setAttributeLocation(const QString& a) { m_attr_location = a; m_has_attr_location = true; }
+ inline void clearAttributeLocation() { m_has_attr_location = false; }
+
+ inline bool hasAttributeImpldecl() const { return m_has_attr_impldecl; }
+ inline QString attributeImpldecl() const { return m_attr_impldecl; }
+ inline void setAttributeImpldecl(const QString& a) { m_attr_impldecl = a; m_has_attr_impldecl = true; }
+ inline void clearAttributeImpldecl() { m_has_attr_impldecl = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_location;
+ bool m_has_attr_location;
+
+ QString m_attr_impldecl;
+ bool m_has_attr_impldecl;
+
+ // child element data
+ uint m_children;
+
+ DomInclude(const DomInclude &other);
+ void operator = (const DomInclude&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomResources {
+public:
+ DomResources();
+ ~DomResources();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ // child element accessors
+ inline QList<DomResource*> elementInclude() const { return m_include; }
+ void setElementInclude(const QList<DomResource*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ // child element data
+ uint m_children;
+ QList<DomResource*> m_include;
+ enum Child {
+ Include = 1
+ };
+
+ DomResources(const DomResources &other);
+ void operator = (const DomResources&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomResource {
+public:
+ DomResource();
+ ~DomResource();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeLocation() const { return m_has_attr_location; }
+ inline QString attributeLocation() const { return m_attr_location; }
+ inline void setAttributeLocation(const QString& a) { m_attr_location = a; m_has_attr_location = true; }
+ inline void clearAttributeLocation() { m_has_attr_location = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_location;
+ bool m_has_attr_location;
+
+ // child element data
+ uint m_children;
+
+ DomResource(const DomResource &other);
+ void operator = (const DomResource&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomActionGroup {
+public:
+ DomActionGroup();
+ ~DomActionGroup();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ // child element accessors
+ inline QList<DomAction*> elementAction() const { return m_action; }
+ void setElementAction(const QList<DomAction*>& a);
+
+ inline QList<DomActionGroup*> elementActionGroup() const { return m_actionGroup; }
+ void setElementActionGroup(const QList<DomActionGroup*>& a);
+
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+ inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
+ void setElementAttribute(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ // child element data
+ uint m_children;
+ QList<DomAction*> m_action;
+ QList<DomActionGroup*> m_actionGroup;
+ QList<DomProperty*> m_property;
+ QList<DomProperty*> m_attribute;
+ enum Child {
+ Action = 1,
+ ActionGroup = 2,
+ Property = 4,
+ Attribute = 8
+ };
+
+ DomActionGroup(const DomActionGroup &other);
+ void operator = (const DomActionGroup&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomAction {
+public:
+ DomAction();
+ ~DomAction();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ inline bool hasAttributeMenu() const { return m_has_attr_menu; }
+ inline QString attributeMenu() const { return m_attr_menu; }
+ inline void setAttributeMenu(const QString& a) { m_attr_menu = a; m_has_attr_menu = true; }
+ inline void clearAttributeMenu() { m_has_attr_menu = false; }
+
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+ inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
+ void setElementAttribute(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ QString m_attr_menu;
+ bool m_has_attr_menu;
+
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ QList<DomProperty*> m_attribute;
+ enum Child {
+ Property = 1,
+ Attribute = 2
+ };
+
+ DomAction(const DomAction &other);
+ void operator = (const DomAction&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomActionRef {
+public:
+ DomActionRef();
+ ~DomActionRef();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ // child element data
+ uint m_children;
+
+ DomActionRef(const DomActionRef &other);
+ void operator = (const DomActionRef&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomButtonGroup {
+public:
+ DomButtonGroup();
+ ~DomButtonGroup();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+ inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
+ void setElementAttribute(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ QList<DomProperty*> m_attribute;
+ enum Child {
+ Property = 1,
+ Attribute = 2
+ };
+
+ DomButtonGroup(const DomButtonGroup &other);
+ void operator = (const DomButtonGroup&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomButtonGroups {
+public:
+ DomButtonGroups();
+ ~DomButtonGroups();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomButtonGroup*> elementButtonGroup() const { return m_buttonGroup; }
+ void setElementButtonGroup(const QList<DomButtonGroup*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomButtonGroup*> m_buttonGroup;
+ enum Child {
+ ButtonGroup = 1
+ };
+
+ DomButtonGroups(const DomButtonGroups &other);
+ void operator = (const DomButtonGroups&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomImages {
+public:
+ DomImages();
+ ~DomImages();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomImage*> elementImage() const { return m_image; }
+ void setElementImage(const QList<DomImage*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomImage*> m_image;
+ enum Child {
+ Image = 1
+ };
+
+ DomImages(const DomImages &other);
+ void operator = (const DomImages&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomImage {
+public:
+ DomImage();
+ ~DomImage();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ // child element accessors
+ inline DomImageData* elementData() const { return m_data; }
+ DomImageData* takeElementData();
+ void setElementData(DomImageData* a);
+ inline bool hasElementData() const { return m_children & Data; }
+ void clearElementData();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ // child element data
+ uint m_children;
+ DomImageData* m_data;
+ enum Child {
+ Data = 1
+ };
+
+ DomImage(const DomImage &other);
+ void operator = (const DomImage&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomImageData {
+public:
+ DomImageData();
+ ~DomImageData();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeFormat() const { return m_has_attr_format; }
+ inline QString attributeFormat() const { return m_attr_format; }
+ inline void setAttributeFormat(const QString& a) { m_attr_format = a; m_has_attr_format = true; }
+ inline void clearAttributeFormat() { m_has_attr_format = false; }
+
+ inline bool hasAttributeLength() const { return m_has_attr_length; }
+ inline int attributeLength() const { return m_attr_length; }
+ inline void setAttributeLength(int a) { m_attr_length = a; m_has_attr_length = true; }
+ inline void clearAttributeLength() { m_has_attr_length = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_format;
+ bool m_has_attr_format;
+
+ int m_attr_length;
+ bool m_has_attr_length;
+
+ // child element data
+ uint m_children;
+
+ DomImageData(const DomImageData &other);
+ void operator = (const DomImageData&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomCustomWidgets {
+public:
+ DomCustomWidgets();
+ ~DomCustomWidgets();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomCustomWidget*> elementCustomWidget() const { return m_customWidget; }
+ void setElementCustomWidget(const QList<DomCustomWidget*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomCustomWidget*> m_customWidget;
+ enum Child {
+ CustomWidget = 1
+ };
+
+ DomCustomWidgets(const DomCustomWidgets &other);
+ void operator = (const DomCustomWidgets&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomHeader {
+public:
+ DomHeader();
+ ~DomHeader();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeLocation() const { return m_has_attr_location; }
+ inline QString attributeLocation() const { return m_attr_location; }
+ inline void setAttributeLocation(const QString& a) { m_attr_location = a; m_has_attr_location = true; }
+ inline void clearAttributeLocation() { m_has_attr_location = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_location;
+ bool m_has_attr_location;
+
+ // child element data
+ uint m_children;
+
+ DomHeader(const DomHeader &other);
+ void operator = (const DomHeader&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomCustomWidget {
+public:
+ DomCustomWidget();
+ ~DomCustomWidget();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QString elementClass() const { return m_class; }
+ void setElementClass(const QString& a);
+ inline bool hasElementClass() const { return m_children & Class; }
+ void clearElementClass();
+
+ inline QString elementExtends() const { return m_extends; }
+ void setElementExtends(const QString& a);
+ inline bool hasElementExtends() const { return m_children & Extends; }
+ void clearElementExtends();
+
+ inline DomHeader* elementHeader() const { return m_header; }
+ DomHeader* takeElementHeader();
+ void setElementHeader(DomHeader* a);
+ inline bool hasElementHeader() const { return m_children & Header; }
+ void clearElementHeader();
+
+ inline DomSize* elementSizeHint() const { return m_sizeHint; }
+ DomSize* takeElementSizeHint();
+ void setElementSizeHint(DomSize* a);
+ inline bool hasElementSizeHint() const { return m_children & SizeHint; }
+ void clearElementSizeHint();
+
+ inline QString elementAddPageMethod() const { return m_addPageMethod; }
+ void setElementAddPageMethod(const QString& a);
+ inline bool hasElementAddPageMethod() const { return m_children & AddPageMethod; }
+ void clearElementAddPageMethod();
+
+ inline int elementContainer() const { return m_container; }
+ void setElementContainer(int a);
+ inline bool hasElementContainer() const { return m_children & Container; }
+ void clearElementContainer();
+
+ inline DomSizePolicyData* elementSizePolicy() const { return m_sizePolicy; }
+ DomSizePolicyData* takeElementSizePolicy();
+ void setElementSizePolicy(DomSizePolicyData* a);
+ inline bool hasElementSizePolicy() const { return m_children & SizePolicy; }
+ void clearElementSizePolicy();
+
+ inline QString elementPixmap() const { return m_pixmap; }
+ void setElementPixmap(const QString& a);
+ inline bool hasElementPixmap() const { return m_children & Pixmap; }
+ void clearElementPixmap();
+
+ inline DomScript* elementScript() const { return m_script; }
+ DomScript* takeElementScript();
+ void setElementScript(DomScript* a);
+ inline bool hasElementScript() const { return m_children & Script; }
+ void clearElementScript();
+
+ inline DomProperties* elementProperties() const { return m_properties; }
+ DomProperties* takeElementProperties();
+ void setElementProperties(DomProperties* a);
+ inline bool hasElementProperties() const { return m_children & Properties; }
+ void clearElementProperties();
+
+ inline DomSlots* elementSlots() const { return m_slots; }
+ DomSlots* takeElementSlots();
+ void setElementSlots(DomSlots* a);
+ inline bool hasElementSlots() const { return m_children & Slots; }
+ void clearElementSlots();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QString m_class;
+ QString m_extends;
+ DomHeader* m_header;
+ DomSize* m_sizeHint;
+ QString m_addPageMethod;
+ int m_container;
+ DomSizePolicyData* m_sizePolicy;
+ QString m_pixmap;
+ DomScript* m_script;
+ DomProperties* m_properties;
+ DomSlots* m_slots;
+ enum Child {
+ Class = 1,
+ Extends = 2,
+ Header = 4,
+ SizeHint = 8,
+ AddPageMethod = 16,
+ Container = 32,
+ SizePolicy = 64,
+ Pixmap = 128,
+ Script = 256,
+ Properties = 512,
+ Slots = 1024
+ };
+
+ DomCustomWidget(const DomCustomWidget &other);
+ void operator = (const DomCustomWidget&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomProperties {
+public:
+ DomProperties();
+ ~DomProperties();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomPropertyData*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomPropertyData*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomPropertyData*> m_property;
+ enum Child {
+ Property = 1
+ };
+
+ DomProperties(const DomProperties &other);
+ void operator = (const DomProperties&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomPropertyData {
+public:
+ DomPropertyData();
+ ~DomPropertyData();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeType() const { return m_has_attr_type; }
+ inline QString attributeType() const { return m_attr_type; }
+ inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
+ inline void clearAttributeType() { m_has_attr_type = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_type;
+ bool m_has_attr_type;
+
+ // child element data
+ uint m_children;
+
+ DomPropertyData(const DomPropertyData &other);
+ void operator = (const DomPropertyData&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomSizePolicyData {
+public:
+ DomSizePolicyData();
+ ~DomSizePolicyData();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementHorData() const { return m_horData; }
+ void setElementHorData(int a);
+ inline bool hasElementHorData() const { return m_children & HorData; }
+ void clearElementHorData();
+
+ inline int elementVerData() const { return m_verData; }
+ void setElementVerData(int a);
+ inline bool hasElementVerData() const { return m_children & VerData; }
+ void clearElementVerData();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_horData;
+ int m_verData;
+ enum Child {
+ HorData = 1,
+ VerData = 2
+ };
+
+ DomSizePolicyData(const DomSizePolicyData &other);
+ void operator = (const DomSizePolicyData&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomLayoutDefault {
+public:
+ DomLayoutDefault();
+ ~DomLayoutDefault();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeSpacing() const { return m_has_attr_spacing; }
+ inline int attributeSpacing() const { return m_attr_spacing; }
+ inline void setAttributeSpacing(int a) { m_attr_spacing = a; m_has_attr_spacing = true; }
+ inline void clearAttributeSpacing() { m_has_attr_spacing = false; }
+
+ inline bool hasAttributeMargin() const { return m_has_attr_margin; }
+ inline int attributeMargin() const { return m_attr_margin; }
+ inline void setAttributeMargin(int a) { m_attr_margin = a; m_has_attr_margin = true; }
+ inline void clearAttributeMargin() { m_has_attr_margin = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ int m_attr_spacing;
+ bool m_has_attr_spacing;
+
+ int m_attr_margin;
+ bool m_has_attr_margin;
+
+ // child element data
+ uint m_children;
+
+ DomLayoutDefault(const DomLayoutDefault &other);
+ void operator = (const DomLayoutDefault&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomLayoutFunction {
+public:
+ DomLayoutFunction();
+ ~DomLayoutFunction();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeSpacing() const { return m_has_attr_spacing; }
+ inline QString attributeSpacing() const { return m_attr_spacing; }
+ inline void setAttributeSpacing(const QString& a) { m_attr_spacing = a; m_has_attr_spacing = true; }
+ inline void clearAttributeSpacing() { m_has_attr_spacing = false; }
+
+ inline bool hasAttributeMargin() const { return m_has_attr_margin; }
+ inline QString attributeMargin() const { return m_attr_margin; }
+ inline void setAttributeMargin(const QString& a) { m_attr_margin = a; m_has_attr_margin = true; }
+ inline void clearAttributeMargin() { m_has_attr_margin = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_spacing;
+ bool m_has_attr_spacing;
+
+ QString m_attr_margin;
+ bool m_has_attr_margin;
+
+ // child element data
+ uint m_children;
+
+ DomLayoutFunction(const DomLayoutFunction &other);
+ void operator = (const DomLayoutFunction&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomTabStops {
+public:
+ DomTabStops();
+ ~DomTabStops();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QStringList elementTabStop() const { return m_tabStop; }
+ void setElementTabStop(const QStringList& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QStringList m_tabStop;
+ enum Child {
+ TabStop = 1
+ };
+
+ DomTabStops(const DomTabStops &other);
+ void operator = (const DomTabStops&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomLayout {
+public:
+ DomLayout();
+ ~DomLayout();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeClass() const { return m_has_attr_class; }
+ inline QString attributeClass() const { return m_attr_class; }
+ inline void setAttributeClass(const QString& a) { m_attr_class = a; m_has_attr_class = true; }
+ inline void clearAttributeClass() { m_has_attr_class = false; }
+
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ inline bool hasAttributeStretch() const { return m_has_attr_stretch; }
+ inline QString attributeStretch() const { return m_attr_stretch; }
+ inline void setAttributeStretch(const QString& a) { m_attr_stretch = a; m_has_attr_stretch = true; }
+ inline void clearAttributeStretch() { m_has_attr_stretch = false; }
+
+ inline bool hasAttributeRowStretch() const { return m_has_attr_rowStretch; }
+ inline QString attributeRowStretch() const { return m_attr_rowStretch; }
+ inline void setAttributeRowStretch(const QString& a) { m_attr_rowStretch = a; m_has_attr_rowStretch = true; }
+ inline void clearAttributeRowStretch() { m_has_attr_rowStretch = false; }
+
+ inline bool hasAttributeColumnStretch() const { return m_has_attr_columnStretch; }
+ inline QString attributeColumnStretch() const { return m_attr_columnStretch; }
+ inline void setAttributeColumnStretch(const QString& a) { m_attr_columnStretch = a; m_has_attr_columnStretch = true; }
+ inline void clearAttributeColumnStretch() { m_has_attr_columnStretch = false; }
+
+ inline bool hasAttributeRowMinimumHeight() const { return m_has_attr_rowMinimumHeight; }
+ inline QString attributeRowMinimumHeight() const { return m_attr_rowMinimumHeight; }
+ inline void setAttributeRowMinimumHeight(const QString& a) { m_attr_rowMinimumHeight = a; m_has_attr_rowMinimumHeight = true; }
+ inline void clearAttributeRowMinimumHeight() { m_has_attr_rowMinimumHeight = false; }
+
+ inline bool hasAttributeColumnMinimumWidth() const { return m_has_attr_columnMinimumWidth; }
+ inline QString attributeColumnMinimumWidth() const { return m_attr_columnMinimumWidth; }
+ inline void setAttributeColumnMinimumWidth(const QString& a) { m_attr_columnMinimumWidth = a; m_has_attr_columnMinimumWidth = true; }
+ inline void clearAttributeColumnMinimumWidth() { m_has_attr_columnMinimumWidth = false; }
+
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+ inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
+ void setElementAttribute(const QList<DomProperty*>& a);
+
+ inline QList<DomLayoutItem*> elementItem() const { return m_item; }
+ void setElementItem(const QList<DomLayoutItem*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_class;
+ bool m_has_attr_class;
+
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ QString m_attr_stretch;
+ bool m_has_attr_stretch;
+
+ QString m_attr_rowStretch;
+ bool m_has_attr_rowStretch;
+
+ QString m_attr_columnStretch;
+ bool m_has_attr_columnStretch;
+
+ QString m_attr_rowMinimumHeight;
+ bool m_has_attr_rowMinimumHeight;
+
+ QString m_attr_columnMinimumWidth;
+ bool m_has_attr_columnMinimumWidth;
+
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ QList<DomProperty*> m_attribute;
+ QList<DomLayoutItem*> m_item;
+ enum Child {
+ Property = 1,
+ Attribute = 2,
+ Item = 4
+ };
+
+ DomLayout(const DomLayout &other);
+ void operator = (const DomLayout&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomLayoutItem {
+public:
+ DomLayoutItem();
+ ~DomLayoutItem();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeRow() const { return m_has_attr_row; }
+ inline int attributeRow() const { return m_attr_row; }
+ inline void setAttributeRow(int a) { m_attr_row = a; m_has_attr_row = true; }
+ inline void clearAttributeRow() { m_has_attr_row = false; }
+
+ inline bool hasAttributeColumn() const { return m_has_attr_column; }
+ inline int attributeColumn() const { return m_attr_column; }
+ inline void setAttributeColumn(int a) { m_attr_column = a; m_has_attr_column = true; }
+ inline void clearAttributeColumn() { m_has_attr_column = false; }
+
+ inline bool hasAttributeRowSpan() const { return m_has_attr_rowSpan; }
+ inline int attributeRowSpan() const { return m_attr_rowSpan; }
+ inline void setAttributeRowSpan(int a) { m_attr_rowSpan = a; m_has_attr_rowSpan = true; }
+ inline void clearAttributeRowSpan() { m_has_attr_rowSpan = false; }
+
+ inline bool hasAttributeColSpan() const { return m_has_attr_colSpan; }
+ inline int attributeColSpan() const { return m_attr_colSpan; }
+ inline void setAttributeColSpan(int a) { m_attr_colSpan = a; m_has_attr_colSpan = true; }
+ inline void clearAttributeColSpan() { m_has_attr_colSpan = false; }
+
+ // child element accessors
+ enum Kind { Unknown = 0, Widget, Layout, Spacer };
+ inline Kind kind() const { return m_kind; }
+
+ inline DomWidget* elementWidget() const { return m_widget; }
+ DomWidget* takeElementWidget();
+ void setElementWidget(DomWidget* a);
+
+ inline DomLayout* elementLayout() const { return m_layout; }
+ DomLayout* takeElementLayout();
+ void setElementLayout(DomLayout* a);
+
+ inline DomSpacer* elementSpacer() const { return m_spacer; }
+ DomSpacer* takeElementSpacer();
+ void setElementSpacer(DomSpacer* a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ int m_attr_row;
+ bool m_has_attr_row;
+
+ int m_attr_column;
+ bool m_has_attr_column;
+
+ int m_attr_rowSpan;
+ bool m_has_attr_rowSpan;
+
+ int m_attr_colSpan;
+ bool m_has_attr_colSpan;
+
+ // child element data
+ Kind m_kind;
+ DomWidget* m_widget;
+ DomLayout* m_layout;
+ DomSpacer* m_spacer;
+
+ DomLayoutItem(const DomLayoutItem &other);
+ void operator = (const DomLayoutItem&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomRow {
+public:
+ DomRow();
+ ~DomRow();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ enum Child {
+ Property = 1
+ };
+
+ DomRow(const DomRow &other);
+ void operator = (const DomRow&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomColumn {
+public:
+ DomColumn();
+ ~DomColumn();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ enum Child {
+ Property = 1
+ };
+
+ DomColumn(const DomColumn &other);
+ void operator = (const DomColumn&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomItem {
+public:
+ DomItem();
+ ~DomItem();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeRow() const { return m_has_attr_row; }
+ inline int attributeRow() const { return m_attr_row; }
+ inline void setAttributeRow(int a) { m_attr_row = a; m_has_attr_row = true; }
+ inline void clearAttributeRow() { m_has_attr_row = false; }
+
+ inline bool hasAttributeColumn() const { return m_has_attr_column; }
+ inline int attributeColumn() const { return m_attr_column; }
+ inline void setAttributeColumn(int a) { m_attr_column = a; m_has_attr_column = true; }
+ inline void clearAttributeColumn() { m_has_attr_column = false; }
+
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+ inline QList<DomItem*> elementItem() const { return m_item; }
+ void setElementItem(const QList<DomItem*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ int m_attr_row;
+ bool m_has_attr_row;
+
+ int m_attr_column;
+ bool m_has_attr_column;
+
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ QList<DomItem*> m_item;
+ enum Child {
+ Property = 1,
+ Item = 2
+ };
+
+ DomItem(const DomItem &other);
+ void operator = (const DomItem&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomWidget {
+public:
+ DomWidget();
+ ~DomWidget();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeClass() const { return m_has_attr_class; }
+ inline QString attributeClass() const { return m_attr_class; }
+ inline void setAttributeClass(const QString& a) { m_attr_class = a; m_has_attr_class = true; }
+ inline void clearAttributeClass() { m_has_attr_class = false; }
+
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ inline bool hasAttributeNative() const { return m_has_attr_native; }
+ inline bool attributeNative() const { return m_attr_native; }
+ inline void setAttributeNative(bool a) { m_attr_native = a; m_has_attr_native = true; }
+ inline void clearAttributeNative() { m_has_attr_native = false; }
+
+ // child element accessors
+ inline QStringList elementClass() const { return m_class; }
+ void setElementClass(const QStringList& a);
+
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+ inline QList<DomScript*> elementScript() const { return m_script; }
+ void setElementScript(const QList<DomScript*>& a);
+
+ inline QList<DomWidgetData*> elementWidgetData() const { return m_widgetData; }
+ void setElementWidgetData(const QList<DomWidgetData*>& a);
+
+ inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
+ void setElementAttribute(const QList<DomProperty*>& a);
+
+ inline QList<DomRow*> elementRow() const { return m_row; }
+ void setElementRow(const QList<DomRow*>& a);
+
+ inline QList<DomColumn*> elementColumn() const { return m_column; }
+ void setElementColumn(const QList<DomColumn*>& a);
+
+ inline QList<DomItem*> elementItem() const { return m_item; }
+ void setElementItem(const QList<DomItem*>& a);
+
+ inline QList<DomLayout*> elementLayout() const { return m_layout; }
+ void setElementLayout(const QList<DomLayout*>& a);
+
+ inline QList<DomWidget*> elementWidget() const { return m_widget; }
+ void setElementWidget(const QList<DomWidget*>& a);
+
+ inline QList<DomAction*> elementAction() const { return m_action; }
+ void setElementAction(const QList<DomAction*>& a);
+
+ inline QList<DomActionGroup*> elementActionGroup() const { return m_actionGroup; }
+ void setElementActionGroup(const QList<DomActionGroup*>& a);
+
+ inline QList<DomActionRef*> elementAddAction() const { return m_addAction; }
+ void setElementAddAction(const QList<DomActionRef*>& a);
+
+ inline QStringList elementZOrder() const { return m_zOrder; }
+ void setElementZOrder(const QStringList& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_class;
+ bool m_has_attr_class;
+
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ bool m_attr_native;
+ bool m_has_attr_native;
+
+ // child element data
+ uint m_children;
+ QStringList m_class;
+ QList<DomProperty*> m_property;
+ QList<DomScript*> m_script;
+ QList<DomWidgetData*> m_widgetData;
+ QList<DomProperty*> m_attribute;
+ QList<DomRow*> m_row;
+ QList<DomColumn*> m_column;
+ QList<DomItem*> m_item;
+ QList<DomLayout*> m_layout;
+ QList<DomWidget*> m_widget;
+ QList<DomAction*> m_action;
+ QList<DomActionGroup*> m_actionGroup;
+ QList<DomActionRef*> m_addAction;
+ QStringList m_zOrder;
+ enum Child {
+ Class = 1,
+ Property = 2,
+ Script = 4,
+ WidgetData = 8,
+ Attribute = 16,
+ Row = 32,
+ Column = 64,
+ Item = 128,
+ Layout = 256,
+ Widget = 512,
+ Action = 1024,
+ ActionGroup = 2048,
+ AddAction = 4096,
+ ZOrder = 8192
+ };
+
+ DomWidget(const DomWidget &other);
+ void operator = (const DomWidget&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomSpacer {
+public:
+ DomSpacer();
+ ~DomSpacer();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ enum Child {
+ Property = 1
+ };
+
+ DomSpacer(const DomSpacer &other);
+ void operator = (const DomSpacer&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomColor {
+public:
+ DomColor();
+ ~DomColor();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeAlpha() const { return m_has_attr_alpha; }
+ inline int attributeAlpha() const { return m_attr_alpha; }
+ inline void setAttributeAlpha(int a) { m_attr_alpha = a; m_has_attr_alpha = true; }
+ inline void clearAttributeAlpha() { m_has_attr_alpha = false; }
+
+ // child element accessors
+ inline int elementRed() const { return m_red; }
+ void setElementRed(int a);
+ inline bool hasElementRed() const { return m_children & Red; }
+ void clearElementRed();
+
+ inline int elementGreen() const { return m_green; }
+ void setElementGreen(int a);
+ inline bool hasElementGreen() const { return m_children & Green; }
+ void clearElementGreen();
+
+ inline int elementBlue() const { return m_blue; }
+ void setElementBlue(int a);
+ inline bool hasElementBlue() const { return m_children & Blue; }
+ void clearElementBlue();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ int m_attr_alpha;
+ bool m_has_attr_alpha;
+
+ // child element data
+ uint m_children;
+ int m_red;
+ int m_green;
+ int m_blue;
+ enum Child {
+ Red = 1,
+ Green = 2,
+ Blue = 4
+ };
+
+ DomColor(const DomColor &other);
+ void operator = (const DomColor&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomGradientStop {
+public:
+ DomGradientStop();
+ ~DomGradientStop();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributePosition() const { return m_has_attr_position; }
+ inline double attributePosition() const { return m_attr_position; }
+ inline void setAttributePosition(double a) { m_attr_position = a; m_has_attr_position = true; }
+ inline void clearAttributePosition() { m_has_attr_position = false; }
+
+ // child element accessors
+ inline DomColor* elementColor() const { return m_color; }
+ DomColor* takeElementColor();
+ void setElementColor(DomColor* a);
+ inline bool hasElementColor() const { return m_children & Color; }
+ void clearElementColor();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ double m_attr_position;
+ bool m_has_attr_position;
+
+ // child element data
+ uint m_children;
+ DomColor* m_color;
+ enum Child {
+ Color = 1
+ };
+
+ DomGradientStop(const DomGradientStop &other);
+ void operator = (const DomGradientStop&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomGradient {
+public:
+ DomGradient();
+ ~DomGradient();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeStartX() const { return m_has_attr_startX; }
+ inline double attributeStartX() const { return m_attr_startX; }
+ inline void setAttributeStartX(double a) { m_attr_startX = a; m_has_attr_startX = true; }
+ inline void clearAttributeStartX() { m_has_attr_startX = false; }
+
+ inline bool hasAttributeStartY() const { return m_has_attr_startY; }
+ inline double attributeStartY() const { return m_attr_startY; }
+ inline void setAttributeStartY(double a) { m_attr_startY = a; m_has_attr_startY = true; }
+ inline void clearAttributeStartY() { m_has_attr_startY = false; }
+
+ inline bool hasAttributeEndX() const { return m_has_attr_endX; }
+ inline double attributeEndX() const { return m_attr_endX; }
+ inline void setAttributeEndX(double a) { m_attr_endX = a; m_has_attr_endX = true; }
+ inline void clearAttributeEndX() { m_has_attr_endX = false; }
+
+ inline bool hasAttributeEndY() const { return m_has_attr_endY; }
+ inline double attributeEndY() const { return m_attr_endY; }
+ inline void setAttributeEndY(double a) { m_attr_endY = a; m_has_attr_endY = true; }
+ inline void clearAttributeEndY() { m_has_attr_endY = false; }
+
+ inline bool hasAttributeCentralX() const { return m_has_attr_centralX; }
+ inline double attributeCentralX() const { return m_attr_centralX; }
+ inline void setAttributeCentralX(double a) { m_attr_centralX = a; m_has_attr_centralX = true; }
+ inline void clearAttributeCentralX() { m_has_attr_centralX = false; }
+
+ inline bool hasAttributeCentralY() const { return m_has_attr_centralY; }
+ inline double attributeCentralY() const { return m_attr_centralY; }
+ inline void setAttributeCentralY(double a) { m_attr_centralY = a; m_has_attr_centralY = true; }
+ inline void clearAttributeCentralY() { m_has_attr_centralY = false; }
+
+ inline bool hasAttributeFocalX() const { return m_has_attr_focalX; }
+ inline double attributeFocalX() const { return m_attr_focalX; }
+ inline void setAttributeFocalX(double a) { m_attr_focalX = a; m_has_attr_focalX = true; }
+ inline void clearAttributeFocalX() { m_has_attr_focalX = false; }
+
+ inline bool hasAttributeFocalY() const { return m_has_attr_focalY; }
+ inline double attributeFocalY() const { return m_attr_focalY; }
+ inline void setAttributeFocalY(double a) { m_attr_focalY = a; m_has_attr_focalY = true; }
+ inline void clearAttributeFocalY() { m_has_attr_focalY = false; }
+
+ inline bool hasAttributeRadius() const { return m_has_attr_radius; }
+ inline double attributeRadius() const { return m_attr_radius; }
+ inline void setAttributeRadius(double a) { m_attr_radius = a; m_has_attr_radius = true; }
+ inline void clearAttributeRadius() { m_has_attr_radius = false; }
+
+ inline bool hasAttributeAngle() const { return m_has_attr_angle; }
+ inline double attributeAngle() const { return m_attr_angle; }
+ inline void setAttributeAngle(double a) { m_attr_angle = a; m_has_attr_angle = true; }
+ inline void clearAttributeAngle() { m_has_attr_angle = false; }
+
+ inline bool hasAttributeType() const { return m_has_attr_type; }
+ inline QString attributeType() const { return m_attr_type; }
+ inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
+ inline void clearAttributeType() { m_has_attr_type = false; }
+
+ inline bool hasAttributeSpread() const { return m_has_attr_spread; }
+ inline QString attributeSpread() const { return m_attr_spread; }
+ inline void setAttributeSpread(const QString& a) { m_attr_spread = a; m_has_attr_spread = true; }
+ inline void clearAttributeSpread() { m_has_attr_spread = false; }
+
+ inline bool hasAttributeCoordinateMode() const { return m_has_attr_coordinateMode; }
+ inline QString attributeCoordinateMode() const { return m_attr_coordinateMode; }
+ inline void setAttributeCoordinateMode(const QString& a) { m_attr_coordinateMode = a; m_has_attr_coordinateMode = true; }
+ inline void clearAttributeCoordinateMode() { m_has_attr_coordinateMode = false; }
+
+ // child element accessors
+ inline QList<DomGradientStop*> elementGradientStop() const { return m_gradientStop; }
+ void setElementGradientStop(const QList<DomGradientStop*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ double m_attr_startX;
+ bool m_has_attr_startX;
+
+ double m_attr_startY;
+ bool m_has_attr_startY;
+
+ double m_attr_endX;
+ bool m_has_attr_endX;
+
+ double m_attr_endY;
+ bool m_has_attr_endY;
+
+ double m_attr_centralX;
+ bool m_has_attr_centralX;
+
+ double m_attr_centralY;
+ bool m_has_attr_centralY;
+
+ double m_attr_focalX;
+ bool m_has_attr_focalX;
+
+ double m_attr_focalY;
+ bool m_has_attr_focalY;
+
+ double m_attr_radius;
+ bool m_has_attr_radius;
+
+ double m_attr_angle;
+ bool m_has_attr_angle;
+
+ QString m_attr_type;
+ bool m_has_attr_type;
+
+ QString m_attr_spread;
+ bool m_has_attr_spread;
+
+ QString m_attr_coordinateMode;
+ bool m_has_attr_coordinateMode;
+
+ // child element data
+ uint m_children;
+ QList<DomGradientStop*> m_gradientStop;
+ enum Child {
+ GradientStop = 1
+ };
+
+ DomGradient(const DomGradient &other);
+ void operator = (const DomGradient&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomBrush {
+public:
+ DomBrush();
+ ~DomBrush();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeBrushStyle() const { return m_has_attr_brushStyle; }
+ inline QString attributeBrushStyle() const { return m_attr_brushStyle; }
+ inline void setAttributeBrushStyle(const QString& a) { m_attr_brushStyle = a; m_has_attr_brushStyle = true; }
+ inline void clearAttributeBrushStyle() { m_has_attr_brushStyle = false; }
+
+ // child element accessors
+ enum Kind { Unknown = 0, Color, Texture, Gradient };
+ inline Kind kind() const { return m_kind; }
+
+ inline DomColor* elementColor() const { return m_color; }
+ DomColor* takeElementColor();
+ void setElementColor(DomColor* a);
+
+ inline DomProperty* elementTexture() const { return m_texture; }
+ DomProperty* takeElementTexture();
+ void setElementTexture(DomProperty* a);
+
+ inline DomGradient* elementGradient() const { return m_gradient; }
+ DomGradient* takeElementGradient();
+ void setElementGradient(DomGradient* a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_brushStyle;
+ bool m_has_attr_brushStyle;
+
+ // child element data
+ Kind m_kind;
+ DomColor* m_color;
+ DomProperty* m_texture;
+ DomGradient* m_gradient;
+
+ DomBrush(const DomBrush &other);
+ void operator = (const DomBrush&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomColorRole {
+public:
+ DomColorRole();
+ ~DomColorRole();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeRole() const { return m_has_attr_role; }
+ inline QString attributeRole() const { return m_attr_role; }
+ inline void setAttributeRole(const QString& a) { m_attr_role = a; m_has_attr_role = true; }
+ inline void clearAttributeRole() { m_has_attr_role = false; }
+
+ // child element accessors
+ inline DomBrush* elementBrush() const { return m_brush; }
+ DomBrush* takeElementBrush();
+ void setElementBrush(DomBrush* a);
+ inline bool hasElementBrush() const { return m_children & Brush; }
+ void clearElementBrush();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_role;
+ bool m_has_attr_role;
+
+ // child element data
+ uint m_children;
+ DomBrush* m_brush;
+ enum Child {
+ Brush = 1
+ };
+
+ DomColorRole(const DomColorRole &other);
+ void operator = (const DomColorRole&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomColorGroup {
+public:
+ DomColorGroup();
+ ~DomColorGroup();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomColorRole*> elementColorRole() const { return m_colorRole; }
+ void setElementColorRole(const QList<DomColorRole*>& a);
+
+ inline QList<DomColor*> elementColor() const { return m_color; }
+ void setElementColor(const QList<DomColor*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomColorRole*> m_colorRole;
+ QList<DomColor*> m_color;
+ enum Child {
+ ColorRole = 1,
+ Color = 2
+ };
+
+ DomColorGroup(const DomColorGroup &other);
+ void operator = (const DomColorGroup&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomPalette {
+public:
+ DomPalette();
+ ~DomPalette();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline DomColorGroup* elementActive() const { return m_active; }
+ DomColorGroup* takeElementActive();
+ void setElementActive(DomColorGroup* a);
+ inline bool hasElementActive() const { return m_children & Active; }
+ void clearElementActive();
+
+ inline DomColorGroup* elementInactive() const { return m_inactive; }
+ DomColorGroup* takeElementInactive();
+ void setElementInactive(DomColorGroup* a);
+ inline bool hasElementInactive() const { return m_children & Inactive; }
+ void clearElementInactive();
+
+ inline DomColorGroup* elementDisabled() const { return m_disabled; }
+ DomColorGroup* takeElementDisabled();
+ void setElementDisabled(DomColorGroup* a);
+ inline bool hasElementDisabled() const { return m_children & Disabled; }
+ void clearElementDisabled();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ DomColorGroup* m_active;
+ DomColorGroup* m_inactive;
+ DomColorGroup* m_disabled;
+ enum Child {
+ Active = 1,
+ Inactive = 2,
+ Disabled = 4
+ };
+
+ DomPalette(const DomPalette &other);
+ void operator = (const DomPalette&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomFont {
+public:
+ DomFont();
+ ~DomFont();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QString elementFamily() const { return m_family; }
+ void setElementFamily(const QString& a);
+ inline bool hasElementFamily() const { return m_children & Family; }
+ void clearElementFamily();
+
+ inline int elementPointSize() const { return m_pointSize; }
+ void setElementPointSize(int a);
+ inline bool hasElementPointSize() const { return m_children & PointSize; }
+ void clearElementPointSize();
+
+ inline int elementWeight() const { return m_weight; }
+ void setElementWeight(int a);
+ inline bool hasElementWeight() const { return m_children & Weight; }
+ void clearElementWeight();
+
+ inline bool elementItalic() const { return m_italic; }
+ void setElementItalic(bool a);
+ inline bool hasElementItalic() const { return m_children & Italic; }
+ void clearElementItalic();
+
+ inline bool elementBold() const { return m_bold; }
+ void setElementBold(bool a);
+ inline bool hasElementBold() const { return m_children & Bold; }
+ void clearElementBold();
+
+ inline bool elementUnderline() const { return m_underline; }
+ void setElementUnderline(bool a);
+ inline bool hasElementUnderline() const { return m_children & Underline; }
+ void clearElementUnderline();
+
+ inline bool elementStrikeOut() const { return m_strikeOut; }
+ void setElementStrikeOut(bool a);
+ inline bool hasElementStrikeOut() const { return m_children & StrikeOut; }
+ void clearElementStrikeOut();
+
+ inline bool elementAntialiasing() const { return m_antialiasing; }
+ void setElementAntialiasing(bool a);
+ inline bool hasElementAntialiasing() const { return m_children & Antialiasing; }
+ void clearElementAntialiasing();
+
+ inline QString elementStyleStrategy() const { return m_styleStrategy; }
+ void setElementStyleStrategy(const QString& a);
+ inline bool hasElementStyleStrategy() const { return m_children & StyleStrategy; }
+ void clearElementStyleStrategy();
+
+ inline bool elementKerning() const { return m_kerning; }
+ void setElementKerning(bool a);
+ inline bool hasElementKerning() const { return m_children & Kerning; }
+ void clearElementKerning();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QString m_family;
+ int m_pointSize;
+ int m_weight;
+ bool m_italic;
+ bool m_bold;
+ bool m_underline;
+ bool m_strikeOut;
+ bool m_antialiasing;
+ QString m_styleStrategy;
+ bool m_kerning;
+ enum Child {
+ Family = 1,
+ PointSize = 2,
+ Weight = 4,
+ Italic = 8,
+ Bold = 16,
+ Underline = 32,
+ StrikeOut = 64,
+ Antialiasing = 128,
+ StyleStrategy = 256,
+ Kerning = 512
+ };
+
+ DomFont(const DomFont &other);
+ void operator = (const DomFont&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomPoint {
+public:
+ DomPoint();
+ ~DomPoint();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementX() const { return m_x; }
+ void setElementX(int a);
+ inline bool hasElementX() const { return m_children & X; }
+ void clearElementX();
+
+ inline int elementY() const { return m_y; }
+ void setElementY(int a);
+ inline bool hasElementY() const { return m_children & Y; }
+ void clearElementY();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_x;
+ int m_y;
+ enum Child {
+ X = 1,
+ Y = 2
+ };
+
+ DomPoint(const DomPoint &other);
+ void operator = (const DomPoint&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomRect {
+public:
+ DomRect();
+ ~DomRect();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementX() const { return m_x; }
+ void setElementX(int a);
+ inline bool hasElementX() const { return m_children & X; }
+ void clearElementX();
+
+ inline int elementY() const { return m_y; }
+ void setElementY(int a);
+ inline bool hasElementY() const { return m_children & Y; }
+ void clearElementY();
+
+ inline int elementWidth() const { return m_width; }
+ void setElementWidth(int a);
+ inline bool hasElementWidth() const { return m_children & Width; }
+ void clearElementWidth();
+
+ inline int elementHeight() const { return m_height; }
+ void setElementHeight(int a);
+ inline bool hasElementHeight() const { return m_children & Height; }
+ void clearElementHeight();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_x;
+ int m_y;
+ int m_width;
+ int m_height;
+ enum Child {
+ X = 1,
+ Y = 2,
+ Width = 4,
+ Height = 8
+ };
+
+ DomRect(const DomRect &other);
+ void operator = (const DomRect&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomLocale {
+public:
+ DomLocale();
+ ~DomLocale();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeLanguage() const { return m_has_attr_language; }
+ inline QString attributeLanguage() const { return m_attr_language; }
+ inline void setAttributeLanguage(const QString& a) { m_attr_language = a; m_has_attr_language = true; }
+ inline void clearAttributeLanguage() { m_has_attr_language = false; }
+
+ inline bool hasAttributeCountry() const { return m_has_attr_country; }
+ inline QString attributeCountry() const { return m_attr_country; }
+ inline void setAttributeCountry(const QString& a) { m_attr_country = a; m_has_attr_country = true; }
+ inline void clearAttributeCountry() { m_has_attr_country = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_language;
+ bool m_has_attr_language;
+
+ QString m_attr_country;
+ bool m_has_attr_country;
+
+ // child element data
+ uint m_children;
+
+ DomLocale(const DomLocale &other);
+ void operator = (const DomLocale&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomSizePolicy {
+public:
+ DomSizePolicy();
+ ~DomSizePolicy();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeHSizeType() const { return m_has_attr_hSizeType; }
+ inline QString attributeHSizeType() const { return m_attr_hSizeType; }
+ inline void setAttributeHSizeType(const QString& a) { m_attr_hSizeType = a; m_has_attr_hSizeType = true; }
+ inline void clearAttributeHSizeType() { m_has_attr_hSizeType = false; }
+
+ inline bool hasAttributeVSizeType() const { return m_has_attr_vSizeType; }
+ inline QString attributeVSizeType() const { return m_attr_vSizeType; }
+ inline void setAttributeVSizeType(const QString& a) { m_attr_vSizeType = a; m_has_attr_vSizeType = true; }
+ inline void clearAttributeVSizeType() { m_has_attr_vSizeType = false; }
+
+ // child element accessors
+ inline int elementHSizeType() const { return m_hSizeType; }
+ void setElementHSizeType(int a);
+ inline bool hasElementHSizeType() const { return m_children & HSizeType; }
+ void clearElementHSizeType();
+
+ inline int elementVSizeType() const { return m_vSizeType; }
+ void setElementVSizeType(int a);
+ inline bool hasElementVSizeType() const { return m_children & VSizeType; }
+ void clearElementVSizeType();
+
+ inline int elementHorStretch() const { return m_horStretch; }
+ void setElementHorStretch(int a);
+ inline bool hasElementHorStretch() const { return m_children & HorStretch; }
+ void clearElementHorStretch();
+
+ inline int elementVerStretch() const { return m_verStretch; }
+ void setElementVerStretch(int a);
+ inline bool hasElementVerStretch() const { return m_children & VerStretch; }
+ void clearElementVerStretch();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_hSizeType;
+ bool m_has_attr_hSizeType;
+
+ QString m_attr_vSizeType;
+ bool m_has_attr_vSizeType;
+
+ // child element data
+ uint m_children;
+ int m_hSizeType;
+ int m_vSizeType;
+ int m_horStretch;
+ int m_verStretch;
+ enum Child {
+ HSizeType = 1,
+ VSizeType = 2,
+ HorStretch = 4,
+ VerStretch = 8
+ };
+
+ DomSizePolicy(const DomSizePolicy &other);
+ void operator = (const DomSizePolicy&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomSize {
+public:
+ DomSize();
+ ~DomSize();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementWidth() const { return m_width; }
+ void setElementWidth(int a);
+ inline bool hasElementWidth() const { return m_children & Width; }
+ void clearElementWidth();
+
+ inline int elementHeight() const { return m_height; }
+ void setElementHeight(int a);
+ inline bool hasElementHeight() const { return m_children & Height; }
+ void clearElementHeight();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_width;
+ int m_height;
+ enum Child {
+ Width = 1,
+ Height = 2
+ };
+
+ DomSize(const DomSize &other);
+ void operator = (const DomSize&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomDate {
+public:
+ DomDate();
+ ~DomDate();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementYear() const { return m_year; }
+ void setElementYear(int a);
+ inline bool hasElementYear() const { return m_children & Year; }
+ void clearElementYear();
+
+ inline int elementMonth() const { return m_month; }
+ void setElementMonth(int a);
+ inline bool hasElementMonth() const { return m_children & Month; }
+ void clearElementMonth();
+
+ inline int elementDay() const { return m_day; }
+ void setElementDay(int a);
+ inline bool hasElementDay() const { return m_children & Day; }
+ void clearElementDay();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_year;
+ int m_month;
+ int m_day;
+ enum Child {
+ Year = 1,
+ Month = 2,
+ Day = 4
+ };
+
+ DomDate(const DomDate &other);
+ void operator = (const DomDate&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomTime {
+public:
+ DomTime();
+ ~DomTime();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementHour() const { return m_hour; }
+ void setElementHour(int a);
+ inline bool hasElementHour() const { return m_children & Hour; }
+ void clearElementHour();
+
+ inline int elementMinute() const { return m_minute; }
+ void setElementMinute(int a);
+ inline bool hasElementMinute() const { return m_children & Minute; }
+ void clearElementMinute();
+
+ inline int elementSecond() const { return m_second; }
+ void setElementSecond(int a);
+ inline bool hasElementSecond() const { return m_children & Second; }
+ void clearElementSecond();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_hour;
+ int m_minute;
+ int m_second;
+ enum Child {
+ Hour = 1,
+ Minute = 2,
+ Second = 4
+ };
+
+ DomTime(const DomTime &other);
+ void operator = (const DomTime&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomDateTime {
+public:
+ DomDateTime();
+ ~DomDateTime();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementHour() const { return m_hour; }
+ void setElementHour(int a);
+ inline bool hasElementHour() const { return m_children & Hour; }
+ void clearElementHour();
+
+ inline int elementMinute() const { return m_minute; }
+ void setElementMinute(int a);
+ inline bool hasElementMinute() const { return m_children & Minute; }
+ void clearElementMinute();
+
+ inline int elementSecond() const { return m_second; }
+ void setElementSecond(int a);
+ inline bool hasElementSecond() const { return m_children & Second; }
+ void clearElementSecond();
+
+ inline int elementYear() const { return m_year; }
+ void setElementYear(int a);
+ inline bool hasElementYear() const { return m_children & Year; }
+ void clearElementYear();
+
+ inline int elementMonth() const { return m_month; }
+ void setElementMonth(int a);
+ inline bool hasElementMonth() const { return m_children & Month; }
+ void clearElementMonth();
+
+ inline int elementDay() const { return m_day; }
+ void setElementDay(int a);
+ inline bool hasElementDay() const { return m_children & Day; }
+ void clearElementDay();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_hour;
+ int m_minute;
+ int m_second;
+ int m_year;
+ int m_month;
+ int m_day;
+ enum Child {
+ Hour = 1,
+ Minute = 2,
+ Second = 4,
+ Year = 8,
+ Month = 16,
+ Day = 32
+ };
+
+ DomDateTime(const DomDateTime &other);
+ void operator = (const DomDateTime&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomStringList {
+public:
+ DomStringList();
+ ~DomStringList();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QStringList elementString() const { return m_string; }
+ void setElementString(const QStringList& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QStringList m_string;
+ enum Child {
+ String = 1
+ };
+
+ DomStringList(const DomStringList &other);
+ void operator = (const DomStringList&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomResourcePixmap {
+public:
+ DomResourcePixmap();
+ ~DomResourcePixmap();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeResource() const { return m_has_attr_resource; }
+ inline QString attributeResource() const { return m_attr_resource; }
+ inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; }
+ inline void clearAttributeResource() { m_has_attr_resource = false; }
+
+ inline bool hasAttributeAlias() const { return m_has_attr_alias; }
+ inline QString attributeAlias() const { return m_attr_alias; }
+ inline void setAttributeAlias(const QString& a) { m_attr_alias = a; m_has_attr_alias = true; }
+ inline void clearAttributeAlias() { m_has_attr_alias = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_resource;
+ bool m_has_attr_resource;
+
+ QString m_attr_alias;
+ bool m_has_attr_alias;
+
+ // child element data
+ uint m_children;
+
+ DomResourcePixmap(const DomResourcePixmap &other);
+ void operator = (const DomResourcePixmap&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomResourceIcon {
+public:
+ DomResourceIcon();
+ ~DomResourceIcon();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeResource() const { return m_has_attr_resource; }
+ inline QString attributeResource() const { return m_attr_resource; }
+ inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; }
+ inline void clearAttributeResource() { m_has_attr_resource = false; }
+
+ // child element accessors
+ inline DomResourcePixmap* elementNormalOff() const { return m_normalOff; }
+ DomResourcePixmap* takeElementNormalOff();
+ void setElementNormalOff(DomResourcePixmap* a);
+ inline bool hasElementNormalOff() const { return m_children & NormalOff; }
+ void clearElementNormalOff();
+
+ inline DomResourcePixmap* elementNormalOn() const { return m_normalOn; }
+ DomResourcePixmap* takeElementNormalOn();
+ void setElementNormalOn(DomResourcePixmap* a);
+ inline bool hasElementNormalOn() const { return m_children & NormalOn; }
+ void clearElementNormalOn();
+
+ inline DomResourcePixmap* elementDisabledOff() const { return m_disabledOff; }
+ DomResourcePixmap* takeElementDisabledOff();
+ void setElementDisabledOff(DomResourcePixmap* a);
+ inline bool hasElementDisabledOff() const { return m_children & DisabledOff; }
+ void clearElementDisabledOff();
+
+ inline DomResourcePixmap* elementDisabledOn() const { return m_disabledOn; }
+ DomResourcePixmap* takeElementDisabledOn();
+ void setElementDisabledOn(DomResourcePixmap* a);
+ inline bool hasElementDisabledOn() const { return m_children & DisabledOn; }
+ void clearElementDisabledOn();
+
+ inline DomResourcePixmap* elementActiveOff() const { return m_activeOff; }
+ DomResourcePixmap* takeElementActiveOff();
+ void setElementActiveOff(DomResourcePixmap* a);
+ inline bool hasElementActiveOff() const { return m_children & ActiveOff; }
+ void clearElementActiveOff();
+
+ inline DomResourcePixmap* elementActiveOn() const { return m_activeOn; }
+ DomResourcePixmap* takeElementActiveOn();
+ void setElementActiveOn(DomResourcePixmap* a);
+ inline bool hasElementActiveOn() const { return m_children & ActiveOn; }
+ void clearElementActiveOn();
+
+ inline DomResourcePixmap* elementSelectedOff() const { return m_selectedOff; }
+ DomResourcePixmap* takeElementSelectedOff();
+ void setElementSelectedOff(DomResourcePixmap* a);
+ inline bool hasElementSelectedOff() const { return m_children & SelectedOff; }
+ void clearElementSelectedOff();
+
+ inline DomResourcePixmap* elementSelectedOn() const { return m_selectedOn; }
+ DomResourcePixmap* takeElementSelectedOn();
+ void setElementSelectedOn(DomResourcePixmap* a);
+ inline bool hasElementSelectedOn() const { return m_children & SelectedOn; }
+ void clearElementSelectedOn();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_resource;
+ bool m_has_attr_resource;
+
+ // child element data
+ uint m_children;
+ DomResourcePixmap* m_normalOff;
+ DomResourcePixmap* m_normalOn;
+ DomResourcePixmap* m_disabledOff;
+ DomResourcePixmap* m_disabledOn;
+ DomResourcePixmap* m_activeOff;
+ DomResourcePixmap* m_activeOn;
+ DomResourcePixmap* m_selectedOff;
+ DomResourcePixmap* m_selectedOn;
+ enum Child {
+ NormalOff = 1,
+ NormalOn = 2,
+ DisabledOff = 4,
+ DisabledOn = 8,
+ ActiveOff = 16,
+ ActiveOn = 32,
+ SelectedOff = 64,
+ SelectedOn = 128
+ };
+
+ DomResourceIcon(const DomResourceIcon &other);
+ void operator = (const DomResourceIcon&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomString {
+public:
+ DomString();
+ ~DomString();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeNotr() const { return m_has_attr_notr; }
+ inline QString attributeNotr() const { return m_attr_notr; }
+ inline void setAttributeNotr(const QString& a) { m_attr_notr = a; m_has_attr_notr = true; }
+ inline void clearAttributeNotr() { m_has_attr_notr = false; }
+
+ inline bool hasAttributeComment() const { return m_has_attr_comment; }
+ inline QString attributeComment() const { return m_attr_comment; }
+ inline void setAttributeComment(const QString& a) { m_attr_comment = a; m_has_attr_comment = true; }
+ inline void clearAttributeComment() { m_has_attr_comment = false; }
+
+ inline bool hasAttributeExtraComment() const { return m_has_attr_extraComment; }
+ inline QString attributeExtraComment() const { return m_attr_extraComment; }
+ inline void setAttributeExtraComment(const QString& a) { m_attr_extraComment = a; m_has_attr_extraComment = true; }
+ inline void clearAttributeExtraComment() { m_has_attr_extraComment = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_notr;
+ bool m_has_attr_notr;
+
+ QString m_attr_comment;
+ bool m_has_attr_comment;
+
+ QString m_attr_extraComment;
+ bool m_has_attr_extraComment;
+
+ // child element data
+ uint m_children;
+
+ DomString(const DomString &other);
+ void operator = (const DomString&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomPointF {
+public:
+ DomPointF();
+ ~DomPointF();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline double elementX() const { return m_x; }
+ void setElementX(double a);
+ inline bool hasElementX() const { return m_children & X; }
+ void clearElementX();
+
+ inline double elementY() const { return m_y; }
+ void setElementY(double a);
+ inline bool hasElementY() const { return m_children & Y; }
+ void clearElementY();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ double m_x;
+ double m_y;
+ enum Child {
+ X = 1,
+ Y = 2
+ };
+
+ DomPointF(const DomPointF &other);
+ void operator = (const DomPointF&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomRectF {
+public:
+ DomRectF();
+ ~DomRectF();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline double elementX() const { return m_x; }
+ void setElementX(double a);
+ inline bool hasElementX() const { return m_children & X; }
+ void clearElementX();
+
+ inline double elementY() const { return m_y; }
+ void setElementY(double a);
+ inline bool hasElementY() const { return m_children & Y; }
+ void clearElementY();
+
+ inline double elementWidth() const { return m_width; }
+ void setElementWidth(double a);
+ inline bool hasElementWidth() const { return m_children & Width; }
+ void clearElementWidth();
+
+ inline double elementHeight() const { return m_height; }
+ void setElementHeight(double a);
+ inline bool hasElementHeight() const { return m_children & Height; }
+ void clearElementHeight();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ double m_x;
+ double m_y;
+ double m_width;
+ double m_height;
+ enum Child {
+ X = 1,
+ Y = 2,
+ Width = 4,
+ Height = 8
+ };
+
+ DomRectF(const DomRectF &other);
+ void operator = (const DomRectF&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomSizeF {
+public:
+ DomSizeF();
+ ~DomSizeF();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline double elementWidth() const { return m_width; }
+ void setElementWidth(double a);
+ inline bool hasElementWidth() const { return m_children & Width; }
+ void clearElementWidth();
+
+ inline double elementHeight() const { return m_height; }
+ void setElementHeight(double a);
+ inline bool hasElementHeight() const { return m_children & Height; }
+ void clearElementHeight();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ double m_width;
+ double m_height;
+ enum Child {
+ Width = 1,
+ Height = 2
+ };
+
+ DomSizeF(const DomSizeF &other);
+ void operator = (const DomSizeF&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomChar {
+public:
+ DomChar();
+ ~DomChar();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline int elementUnicode() const { return m_unicode; }
+ void setElementUnicode(int a);
+ inline bool hasElementUnicode() const { return m_children & Unicode; }
+ void clearElementUnicode();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ int m_unicode;
+ enum Child {
+ Unicode = 1
+ };
+
+ DomChar(const DomChar &other);
+ void operator = (const DomChar&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomUrl {
+public:
+ DomUrl();
+ ~DomUrl();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline DomString* elementString() const { return m_string; }
+ DomString* takeElementString();
+ void setElementString(DomString* a);
+ inline bool hasElementString() const { return m_children & String; }
+ void clearElementString();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ DomString* m_string;
+ enum Child {
+ String = 1
+ };
+
+ DomUrl(const DomUrl &other);
+ void operator = (const DomUrl&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomProperty {
+public:
+ DomProperty();
+ ~DomProperty();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ inline bool hasAttributeStdset() const { return m_has_attr_stdset; }
+ inline int attributeStdset() const { return m_attr_stdset; }
+ inline void setAttributeStdset(int a) { m_attr_stdset = a; m_has_attr_stdset = true; }
+ inline void clearAttributeStdset() { m_has_attr_stdset = false; }
+
+ // child element accessors
+ enum Kind { Unknown = 0, Bool, Color, Cstring, Cursor, CursorShape, Enum, Font, IconSet, Pixmap, Palette, Point, Rect, Set, Locale, SizePolicy, Size, String, StringList, Number, Float, Double, Date, Time, DateTime, PointF, RectF, SizeF, LongLong, Char, Url, UInt, ULongLong, Brush };
+ inline Kind kind() const { return m_kind; }
+
+ inline QString elementBool() const { return m_bool; }
+ void setElementBool(const QString& a);
+
+ inline DomColor* elementColor() const { return m_color; }
+ DomColor* takeElementColor();
+ void setElementColor(DomColor* a);
+
+ inline QString elementCstring() const { return m_cstring; }
+ void setElementCstring(const QString& a);
+
+ inline int elementCursor() const { return m_cursor; }
+ void setElementCursor(int a);
+
+ inline QString elementCursorShape() const { return m_cursorShape; }
+ void setElementCursorShape(const QString& a);
+
+ inline QString elementEnum() const { return m_enum; }
+ void setElementEnum(const QString& a);
+
+ inline DomFont* elementFont() const { return m_font; }
+ DomFont* takeElementFont();
+ void setElementFont(DomFont* a);
+
+ inline DomResourceIcon* elementIconSet() const { return m_iconSet; }
+ DomResourceIcon* takeElementIconSet();
+ void setElementIconSet(DomResourceIcon* a);
+
+ inline DomResourcePixmap* elementPixmap() const { return m_pixmap; }
+ DomResourcePixmap* takeElementPixmap();
+ void setElementPixmap(DomResourcePixmap* a);
+
+ inline DomPalette* elementPalette() const { return m_palette; }
+ DomPalette* takeElementPalette();
+ void setElementPalette(DomPalette* a);
+
+ inline DomPoint* elementPoint() const { return m_point; }
+ DomPoint* takeElementPoint();
+ void setElementPoint(DomPoint* a);
+
+ inline DomRect* elementRect() const { return m_rect; }
+ DomRect* takeElementRect();
+ void setElementRect(DomRect* a);
+
+ inline QString elementSet() const { return m_set; }
+ void setElementSet(const QString& a);
+
+ inline DomLocale* elementLocale() const { return m_locale; }
+ DomLocale* takeElementLocale();
+ void setElementLocale(DomLocale* a);
+
+ inline DomSizePolicy* elementSizePolicy() const { return m_sizePolicy; }
+ DomSizePolicy* takeElementSizePolicy();
+ void setElementSizePolicy(DomSizePolicy* a);
+
+ inline DomSize* elementSize() const { return m_size; }
+ DomSize* takeElementSize();
+ void setElementSize(DomSize* a);
+
+ inline DomString* elementString() const { return m_string; }
+ DomString* takeElementString();
+ void setElementString(DomString* a);
+
+ inline DomStringList* elementStringList() const { return m_stringList; }
+ DomStringList* takeElementStringList();
+ void setElementStringList(DomStringList* a);
+
+ inline int elementNumber() const { return m_number; }
+ void setElementNumber(int a);
+
+ inline float elementFloat() const { return m_float; }
+ void setElementFloat(float a);
+
+ inline double elementDouble() const { return m_double; }
+ void setElementDouble(double a);
+
+ inline DomDate* elementDate() const { return m_date; }
+ DomDate* takeElementDate();
+ void setElementDate(DomDate* a);
+
+ inline DomTime* elementTime() const { return m_time; }
+ DomTime* takeElementTime();
+ void setElementTime(DomTime* a);
+
+ inline DomDateTime* elementDateTime() const { return m_dateTime; }
+ DomDateTime* takeElementDateTime();
+ void setElementDateTime(DomDateTime* a);
+
+ inline DomPointF* elementPointF() const { return m_pointF; }
+ DomPointF* takeElementPointF();
+ void setElementPointF(DomPointF* a);
+
+ inline DomRectF* elementRectF() const { return m_rectF; }
+ DomRectF* takeElementRectF();
+ void setElementRectF(DomRectF* a);
+
+ inline DomSizeF* elementSizeF() const { return m_sizeF; }
+ DomSizeF* takeElementSizeF();
+ void setElementSizeF(DomSizeF* a);
+
+ inline qlonglong elementLongLong() const { return m_longLong; }
+ void setElementLongLong(qlonglong a);
+
+ inline DomChar* elementChar() const { return m_char; }
+ DomChar* takeElementChar();
+ void setElementChar(DomChar* a);
+
+ inline DomUrl* elementUrl() const { return m_url; }
+ DomUrl* takeElementUrl();
+ void setElementUrl(DomUrl* a);
+
+ inline uint elementUInt() const { return m_UInt; }
+ void setElementUInt(uint a);
+
+ inline qulonglong elementULongLong() const { return m_uLongLong; }
+ void setElementULongLong(qulonglong a);
+
+ inline DomBrush* elementBrush() const { return m_brush; }
+ DomBrush* takeElementBrush();
+ void setElementBrush(DomBrush* a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ int m_attr_stdset;
+ bool m_has_attr_stdset;
+
+ // child element data
+ Kind m_kind;
+ QString m_bool;
+ DomColor* m_color;
+ QString m_cstring;
+ int m_cursor;
+ QString m_cursorShape;
+ QString m_enum;
+ DomFont* m_font;
+ DomResourceIcon* m_iconSet;
+ DomResourcePixmap* m_pixmap;
+ DomPalette* m_palette;
+ DomPoint* m_point;
+ DomRect* m_rect;
+ QString m_set;
+ DomLocale* m_locale;
+ DomSizePolicy* m_sizePolicy;
+ DomSize* m_size;
+ DomString* m_string;
+ DomStringList* m_stringList;
+ int m_number;
+ float m_float;
+ double m_double;
+ DomDate* m_date;
+ DomTime* m_time;
+ DomDateTime* m_dateTime;
+ DomPointF* m_pointF;
+ DomRectF* m_rectF;
+ DomSizeF* m_sizeF;
+ qlonglong m_longLong;
+ DomChar* m_char;
+ DomUrl* m_url;
+ uint m_UInt;
+ qulonglong m_uLongLong;
+ DomBrush* m_brush;
+
+ DomProperty(const DomProperty &other);
+ void operator = (const DomProperty&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomConnections {
+public:
+ DomConnections();
+ ~DomConnections();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomConnection*> elementConnection() const { return m_connection; }
+ void setElementConnection(const QList<DomConnection*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomConnection*> m_connection;
+ enum Child {
+ Connection = 1
+ };
+
+ DomConnections(const DomConnections &other);
+ void operator = (const DomConnections&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomConnection {
+public:
+ DomConnection();
+ ~DomConnection();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QString elementSender() const { return m_sender; }
+ void setElementSender(const QString& a);
+ inline bool hasElementSender() const { return m_children & Sender; }
+ void clearElementSender();
+
+ inline QString elementSignal() const { return m_signal; }
+ void setElementSignal(const QString& a);
+ inline bool hasElementSignal() const { return m_children & Signal; }
+ void clearElementSignal();
+
+ inline QString elementReceiver() const { return m_receiver; }
+ void setElementReceiver(const QString& a);
+ inline bool hasElementReceiver() const { return m_children & Receiver; }
+ void clearElementReceiver();
+
+ inline QString elementSlot() const { return m_slot; }
+ void setElementSlot(const QString& a);
+ inline bool hasElementSlot() const { return m_children & Slot; }
+ void clearElementSlot();
+
+ inline DomConnectionHints* elementHints() const { return m_hints; }
+ DomConnectionHints* takeElementHints();
+ void setElementHints(DomConnectionHints* a);
+ inline bool hasElementHints() const { return m_children & Hints; }
+ void clearElementHints();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QString m_sender;
+ QString m_signal;
+ QString m_receiver;
+ QString m_slot;
+ DomConnectionHints* m_hints;
+ enum Child {
+ Sender = 1,
+ Signal = 2,
+ Receiver = 4,
+ Slot = 8,
+ Hints = 16
+ };
+
+ DomConnection(const DomConnection &other);
+ void operator = (const DomConnection&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomConnectionHints {
+public:
+ DomConnectionHints();
+ ~DomConnectionHints();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomConnectionHint*> elementHint() const { return m_hint; }
+ void setElementHint(const QList<DomConnectionHint*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomConnectionHint*> m_hint;
+ enum Child {
+ Hint = 1
+ };
+
+ DomConnectionHints(const DomConnectionHints &other);
+ void operator = (const DomConnectionHints&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomConnectionHint {
+public:
+ DomConnectionHint();
+ ~DomConnectionHint();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeType() const { return m_has_attr_type; }
+ inline QString attributeType() const { return m_attr_type; }
+ inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
+ inline void clearAttributeType() { m_has_attr_type = false; }
+
+ // child element accessors
+ inline int elementX() const { return m_x; }
+ void setElementX(int a);
+ inline bool hasElementX() const { return m_children & X; }
+ void clearElementX();
+
+ inline int elementY() const { return m_y; }
+ void setElementY(int a);
+ inline bool hasElementY() const { return m_children & Y; }
+ void clearElementY();
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_type;
+ bool m_has_attr_type;
+
+ // child element data
+ uint m_children;
+ int m_x;
+ int m_y;
+ enum Child {
+ X = 1,
+ Y = 2
+ };
+
+ DomConnectionHint(const DomConnectionHint &other);
+ void operator = (const DomConnectionHint&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomScript {
+public:
+ DomScript();
+ ~DomScript();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeSource() const { return m_has_attr_source; }
+ inline QString attributeSource() const { return m_attr_source; }
+ inline void setAttributeSource(const QString& a) { m_attr_source = a; m_has_attr_source = true; }
+ inline void clearAttributeSource() { m_has_attr_source = false; }
+
+ inline bool hasAttributeLanguage() const { return m_has_attr_language; }
+ inline QString attributeLanguage() const { return m_attr_language; }
+ inline void setAttributeLanguage(const QString& a) { m_attr_language = a; m_has_attr_language = true; }
+ inline void clearAttributeLanguage() { m_has_attr_language = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_source;
+ bool m_has_attr_source;
+
+ QString m_attr_language;
+ bool m_has_attr_language;
+
+ // child element data
+ uint m_children;
+
+ DomScript(const DomScript &other);
+ void operator = (const DomScript&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomWidgetData {
+public:
+ DomWidgetData();
+ ~DomWidgetData();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ enum Child {
+ Property = 1
+ };
+
+ DomWidgetData(const DomWidgetData &other);
+ void operator = (const DomWidgetData&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomDesignerData {
+public:
+ DomDesignerData();
+ ~DomDesignerData();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomProperty*> elementProperty() const { return m_property; }
+ void setElementProperty(const QList<DomProperty*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomProperty*> m_property;
+ enum Child {
+ Property = 1
+ };
+
+ DomDesignerData(const DomDesignerData &other);
+ void operator = (const DomDesignerData&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomSlots {
+public:
+ DomSlots();
+ ~DomSlots();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QStringList elementSignal() const { return m_signal; }
+ void setElementSignal(const QStringList& a);
+
+ inline QStringList elementSlot() const { return m_slot; }
+ void setElementSlot(const QStringList& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QStringList m_signal;
+ QStringList m_slot;
+ enum Child {
+ Signal = 1,
+ Slot = 2
+ };
+
+ DomSlots(const DomSlots &other);
+ void operator = (const DomSlots&other);
+};
+
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+#endif // UI4_H
diff --git a/tools/designer/src/lib/uilib/uilib.pri b/tools/designer/src/lib/uilib/uilib.pri
new file mode 100644
index 0000000000..cbf415b08c
--- /dev/null
+++ b/tools/designer/src/lib/uilib/uilib.pri
@@ -0,0 +1,31 @@
+
+INCLUDEPATH += $$PWD
+
+DEFINES += QT_DESIGNER
+
+# Input
+HEADERS += \
+ $$PWD/ui4_p.h \
+ $$PWD/abstractformbuilder.h \
+ $$PWD/formbuilder.h \
+ $$PWD/container.h \
+ $$PWD/customwidget.h \
+ $$PWD/properties_p.h \
+ $$PWD/formbuilderextra_p.h \
+ $$PWD/resourcebuilder_p.h \
+ $$PWD/textbuilder_p.h
+
+SOURCES += \
+ $$PWD/abstractformbuilder.cpp \
+ $$PWD/formbuilder.cpp \
+ $$PWD/ui4.cpp \
+ $$PWD/properties.cpp \
+ $$PWD/formbuilderextra.cpp \
+ $$PWD/resourcebuilder.cpp \
+ $$PWD/textbuilder.cpp
+
+!contains(DEFINES, QT_FORMBUILDER_NO_SCRIPT) {
+ QT += script
+ HEADERS += $$PWD/formscriptrunner_p.h
+ SOURCES += $$PWD/formscriptrunner.cpp
+}
diff --git a/tools/designer/src/lib/uilib/uilib_global.h b/tools/designer/src/lib/uilib/uilib_global.h
new file mode 100644
index 0000000000..796fa799d2
--- /dev/null
+++ b/tools/designer/src/lib/uilib/uilib_global.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef UILIB_GLOBAL_H
+#define UILIB_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#define QDESIGNER_UILIB_EXTERN Q_DECL_EXPORT
+#define QDESIGNER_UILIB_IMPORT Q_DECL_IMPORT
+
+#ifdef QT_DESIGNER_STATIC
+# define QDESIGNER_UILIB_EXPORT
+#elif defined(QDESIGNER_UILIB_LIBRARY)
+# define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_EXTERN
+#else
+# define QDESIGNER_UILIB_EXPORT QDESIGNER_UILIB_IMPORT
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // UILIB_GLOBAL_H
diff --git a/tools/designer/src/lib/uilib/widgets.table b/tools/designer/src/lib/uilib/widgets.table
new file mode 100644
index 0000000000..9b8727849b
--- /dev/null
+++ b/tools/designer/src/lib/uilib/widgets.table
@@ -0,0 +1,148 @@
+
+#ifndef DECLARE_WIDGET_1
+# define DECLARE_WIDGET_1(a,b) DECLARE_WIDGET(a,b)
+#endif
+
+// widgets
+#ifndef QT_NO_CHECKBOX
+DECLARE_WIDGET(QCheckBox, "text")
+#endif
+#ifndef QT_NO_COMBOBOX
+DECLARE_WIDGET(QComboBox, "")
+#endif
+#ifndef QT_NO_DATETIMEEDIT
+DECLARE_WIDGET(QDateTimeEdit, "")
+#endif
+#ifndef QT_NO_DATEEDIT
+DECLARE_WIDGET(QDateEdit, "")
+#endif
+#ifndef QT_NO_TIMEEDIT
+DECLARE_WIDGET(QTimeEdit, "")
+#endif
+#ifndef QT_NO_DIAL
+DECLARE_WIDGET(QDial, "")
+#endif
+DECLARE_WIDGET(QDialog, "")
+#ifndef QT_NO_DOCKWIDGET
+DECLARE_WIDGET(QDockWidget, "")
+#endif
+DECLARE_WIDGET(QFrame, "")
+#ifndef QT_NO_GROUPBOX
+DECLARE_WIDGET(QGroupBox, "")
+#endif
+#ifndef QT_NO_SCROLLAREA
+DECLARE_WIDGET(QScrollArea, "")
+#endif
+#ifndef QT_NO_LCDNUMBER
+DECLARE_WIDGET(QLCDNumber, "")
+#endif
+DECLARE_WIDGET(QLabel, "")
+#ifndef QT_NO_LINEEDIT
+DECLARE_WIDGET(QLineEdit, "")
+#endif
+#ifndef QT_NO_LISTVIEW
+DECLARE_WIDGET(QListView, "")
+#endif
+#ifndef QT_NO_LISTWIDGET
+DECLARE_WIDGET(QListWidget, "")
+#endif
+#ifndef QT_NO_MAINWINDOW
+DECLARE_WIDGET(QMainWindow, "")
+#endif
+#ifndef QT_NO_MDIAREA
+DECLARE_WIDGET(QMdiArea, "")
+#endif
+#ifndef QT_NO_MENU
+DECLARE_WIDGET(QMenu, "")
+#endif
+#ifndef QT_NO_MENUBAR
+DECLARE_WIDGET(QMenuBar, "")
+#endif
+#ifndef QT_NO_PROGRESSBAR
+DECLARE_WIDGET(QProgressBar, "")
+#endif
+DECLARE_WIDGET(QPushButton, "text")
+DECLARE_WIDGET(QRadioButton, "text")
+DECLARE_WIDGET(QCommandLinkButton, "text")
+#ifndef QT_NO_SCROLLBAR
+DECLARE_WIDGET(QScrollBar, "")
+#endif
+#ifndef QT_NO_SLIDER
+DECLARE_WIDGET(QSlider, "")
+#endif
+#ifndef QT_NO_SPINBOX
+DECLARE_WIDGET(QSpinBox, "")
+DECLARE_WIDGET(QDoubleSpinBox, "")
+#endif
+#ifndef QT_NO_TABWIDGET
+DECLARE_WIDGET(QTabWidget, "")
+#endif
+#ifndef QT_NO_TABLEVIEW
+DECLARE_WIDGET(QTableView, "")
+#endif
+#ifndef QT_NO_TABLEWIDGET
+DECLARE_WIDGET(QTableWidget, "")
+#endif
+#ifndef QT_NO_TEXTBROWSER
+DECLARE_WIDGET(QTextBrowser, "")
+#endif
+#ifndef QT_NO_TEXTEDIT
+DECLARE_WIDGET(QTextEdit, "")
+DECLARE_WIDGET(QPlainTextEdit, "")
+#endif
+#ifndef QT_NO_TOOLBAR
+DECLARE_WIDGET(QToolBar, "")
+#endif
+#ifndef QT_NO_TOOLBOX
+DECLARE_WIDGET(QToolBox, "")
+#endif
+#ifndef QT_NO_TOOLBUTTON
+DECLARE_WIDGET(QToolButton, "text")
+#endif
+#ifndef QT_NO_TREEVIEW
+DECLARE_WIDGET(QTreeView, "")
+#endif
+#ifndef QT_NO_TREEWIDGET
+DECLARE_WIDGET(QTreeWidget, "")
+#endif
+DECLARE_WIDGET(QWidget, "")
+#ifndef QT_NO_WORKSPACE
+DECLARE_WIDGET(QWorkspace, "")
+#endif
+#ifndef QT_NO_SPLITTER
+DECLARE_WIDGET(QSplitter, "")
+#endif
+#ifndef QT_NO_STACKEDWIDGET
+DECLARE_WIDGET(QStackedWidget, "")
+#endif
+#ifndef QT_NO_STATUSBAR
+DECLARE_WIDGET(QStatusBar, "")
+#endif
+DECLARE_WIDGET(QDialogButtonBox, "")
+#ifndef QT_NO_FONTCOMBOBOX
+DECLARE_WIDGET(QFontComboBox, "")
+#endif
+#ifndef QT_NO_CALENDARWIDGET
+DECLARE_WIDGET(QCalendarWidget, "")
+#endif
+#ifndef QT_NO_COLUMNVIEW
+DECLARE_WIDGET(QColumnView, "")
+#endif
+
+#ifndef QT_NO_WIZARD
+DECLARE_WIDGET(QWizard, "")
+DECLARE_WIDGET(QWizardPage, "")
+#endif
+
+#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+DECLARE_WIDGET_1(QGraphicsView, "")
+#endif
+
+// layouts
+DECLARE_LAYOUT(QGridLayout, "")
+DECLARE_LAYOUT(QHBoxLayout, "")
+DECLARE_LAYOUT(QStackedLayout, "")
+DECLARE_LAYOUT(QVBoxLayout, "")
+#ifndef QT_NO_FORMLAYOUT
+DECLARE_LAYOUT(QFormLayout, "")
+#endif
diff --git a/tools/designer/src/plugins/activeqt/activeqt.pro b/tools/designer/src/plugins/activeqt/activeqt.pro
new file mode 100644
index 0000000000..f58df8a388
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/activeqt.pro
@@ -0,0 +1,32 @@
+TARGET = $$qtLibraryTarget(qaxwidget)
+TEMPLATE = lib
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer
+
+CONFIG += qt warn_on qaxcontainer plugin designer debug_and_release
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+INCLUDEPATH += $$QT_SOURCE_TREE/src/activeqt/shared/ \
+ $$QT_BUILD_TREE/src/activeqt/container \
+ ../../lib/uilib
+
+# Input
+SOURCES += qaxwidgetextrainfo.cpp \
+qaxwidgetplugin.cpp \
+qdesigneraxwidget.cpp \
+qaxwidgetpropertysheet.cpp \
+qaxwidgettaskmenu.cpp \
+ $$QT_SOURCE_TREE/src/activeqt/shared/qaxtypes.cpp
+
+HEADERS += qaxwidgetextrainfo.h \
+qaxwidgetplugin.h \
+qdesigneraxwidget.h \
+qaxwidgetpropertysheet.h \
+qaxwidgettaskmenu.h \
+ $$QT_SOURCE_TREE/src/activeqt/shared/qaxtypes.h
+
+# install
+target.path = $$[QT_INSTALL_PLUGINS]/designer
+INSTALLS += target
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp b/tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp
new file mode 100644
index 0000000000..369cd7fbb4
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaxwidgetextrainfo.h"
+#include "qdesigneraxwidget.h"
+#include "qaxwidgetpropertysheet.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QAxWidgetExtraInfo::QAxWidgetExtraInfo(QDesignerAxWidget *widget, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_widget(widget), m_core(core)
+{
+}
+
+QWidget *QAxWidgetExtraInfo::widget() const
+{
+ return m_widget;
+}
+
+QDesignerFormEditorInterface *QAxWidgetExtraInfo::core() const
+{
+ return m_core;
+}
+
+bool QAxWidgetExtraInfo::saveUiExtraInfo(DomUI *)
+{
+ return false;
+}
+
+bool QAxWidgetExtraInfo::loadUiExtraInfo(DomUI *)
+{
+ return false;
+}
+
+bool QAxWidgetExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ /* Turn off standard setters and make sure "control" is in front,
+ * otherwise, previews will not work as the properties are not applied via
+ * the caching property sheet, them. */
+ typedef QList<DomProperty *> DomPropertyList;
+ DomPropertyList props = ui_widget->elementProperty();
+ const int size = props.size();
+ const QString controlProperty = QLatin1String(QAxWidgetPropertySheet::controlPropertyName);
+ for (int i = 0; i < size; i++) {
+ props.at(i)->setAttributeStdset(false);
+ if (i > 0 && props.at(i)->attributeName() == controlProperty) {
+ qSwap(props[0], props[i]);
+ ui_widget->setElementProperty(props);
+ }
+
+ }
+ return true;
+}
+
+bool QAxWidgetExtraInfo::loadWidgetExtraInfo(DomWidget *)
+{
+ return false;
+}
+
+QAxWidgetExtraInfoFactory::QAxWidgetExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{
+}
+
+QObject *QAxWidgetExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (QDesignerAxWidget *w = qobject_cast<QDesignerAxWidget*>(object))
+ return new QAxWidgetExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.h b/tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.h
new file mode 100644
index 0000000000..343bb76376
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgetextrainfo.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACTIVEQT_EXTRAINFO_H
+#define ACTIVEQT_EXTRAINFO_H
+
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionFactory>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerAxWidget;
+
+class QAxWidgetExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ QAxWidgetExtraInfo(QDesignerAxWidget *widget, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+private:
+ QPointer<QDesignerAxWidget> m_widget;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class QAxWidgetExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ QAxWidgetExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // ACTIVEQT_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgetplugin.cpp b/tools/designer/src/plugins/activeqt/qaxwidgetplugin.cpp
new file mode 100644
index 0000000000..f80df141c3
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgetplugin.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaxwidgetplugin.h"
+#include "qaxwidgetextrainfo.h"
+#include "qdesigneraxwidget.h"
+#include "qaxwidgetpropertysheet.h"
+#include "qaxwidgettaskmenu.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerFormWindowInterface>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <ActiveQt/QAxWidget>
+
+QT_BEGIN_NAMESPACE
+
+QAxWidgetPlugin::QAxWidgetPlugin(QObject *parent) :
+ QObject(parent),
+ m_core(0)
+{
+}
+
+QString QAxWidgetPlugin::name() const
+{
+ return QLatin1String("QAxWidget");
+}
+
+QString QAxWidgetPlugin::group() const
+{
+ return QLatin1String("Containers");
+}
+
+QString QAxWidgetPlugin::toolTip() const
+{
+ return tr("ActiveX control");
+}
+
+QString QAxWidgetPlugin::whatsThis() const
+{
+ return tr("ActiveX control widget");
+}
+
+QString QAxWidgetPlugin::includeFile() const
+{
+ return QLatin1String("qaxwidget.h");
+}
+
+QIcon QAxWidgetPlugin::icon() const
+{
+ return QIcon(QDesignerAxWidget::widgetIcon());
+}
+
+bool QAxWidgetPlugin::isContainer() const
+{
+ return false;
+}
+
+QWidget *QAxWidgetPlugin::createWidget(QWidget *parent)
+{
+ // Construction from Widget box or on a form?
+ const bool isFormEditor = parent != 0 && QDesignerFormWindowInterface::findFormWindow(parent) != 0;
+ QDesignerAxWidget *rc = new QDesignerAxPluginWidget(parent);
+ if (!isFormEditor)
+ rc->setDrawFlags(QDesignerAxWidget::DrawFrame|QDesignerAxWidget::DrawControl);
+ return rc;
+}
+
+bool QAxWidgetPlugin::isInitialized() const
+{
+ return m_core != 0;
+}
+
+void QAxWidgetPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ if (m_core != 0)
+ return;
+
+ m_core = core;
+
+ QExtensionManager *mgr = core->extensionManager();
+ ActiveXPropertySheetFactory::registerExtension(mgr);
+ ActiveXTaskMenuFactory::registerExtension(mgr, Q_TYPEID(QDesignerTaskMenuExtension));
+ QAxWidgetExtraInfoFactory *extraInfoFactory = new QAxWidgetExtraInfoFactory(core, mgr);
+ mgr->registerExtensions(extraInfoFactory, Q_TYPEID(QDesignerExtraInfoExtension));
+}
+
+QString QAxWidgetPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"QAxWidget\" name=\"axWidget\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>80</width>\
+ <height>70</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+Q_EXPORT_PLUGIN(QAxWidgetPlugin)
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgetplugin.h b/tools/designer/src/plugins/activeqt/qaxwidgetplugin.h
new file mode 100644
index 0000000000..662c490ef9
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgetplugin.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACTIVEXPLUGIN_H
+#define ACTIVEXPLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormEditorInterface;
+
+class QAxWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ explicit inline QAxWidgetPlugin(QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp b/tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp
new file mode 100644
index 0000000000..f94da88696
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaxwidgetpropertysheet.h"
+#include "qdesigneraxwidget.h"
+
+#include <QtDesigner/QDesignerMemberSheetExtension>
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QDesignerPropertyEditorInterface>
+
+#include <QtDesigner/QExtensionManager>
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
+static const char *geometryPropertyC = "geometry";
+
+QT_BEGIN_NAMESPACE
+
+const char *QAxWidgetPropertySheet::controlPropertyName = "control";
+
+QAxWidgetPropertySheet::QAxWidgetPropertySheet(QDesignerAxWidget *object, QObject *parent) :
+ QDesignerPropertySheet(object, parent),
+ m_controlProperty(controlPropertyName),
+ m_propertyGroup(QLatin1String("QAxWidget"))
+{
+ if (!axWidget()->loaded()) { // For some obscure reason....
+ const int controlIndex = QDesignerPropertySheet::indexOf(m_controlProperty);
+ setPropertyGroup(controlIndex, m_propertyGroup);
+ }
+}
+
+bool QAxWidgetPropertySheet::isEnabled(int index) const
+{
+ if (propertyName(index) == m_controlProperty)
+ return false;
+ return QDesignerPropertySheet::isEnabled(index);
+}
+
+bool QAxWidgetPropertySheet::dynamicPropertiesAllowed() const
+{
+ return false;
+}
+
+QDesignerAxWidget *QAxWidgetPropertySheet::axWidget() const
+{
+ return static_cast<QDesignerAxWidget*>(object());
+}
+
+// Reload as the meta object changes.
+bool QAxWidgetPropertySheet::reset(int index)
+{
+ const QString name = propertyName(index);
+ QMap<QString, QVariant>::iterator it = m_currentProperties.changedProperties.find(name);
+ if (it != m_currentProperties.changedProperties.end())
+ m_currentProperties.changedProperties.erase(it);
+ if (name != m_controlProperty)
+ return QDesignerPropertySheet::reset(index);
+ axWidget()->resetControl();
+ QTimer::singleShot(0, this, SLOT(updatePropertySheet()));
+ return true;
+}
+
+void QAxWidgetPropertySheet::setProperty(int index, const QVariant &value)
+{
+
+ // take care of all changed properties
+ const QString name = propertyName(index);
+ m_currentProperties.changedProperties[name] = value;
+ if (name != m_controlProperty) {
+ QDesignerPropertySheet::setProperty(index, value);
+ return;
+ }
+ // Loading forms: Reload
+ if (name == m_controlProperty) {
+ const QString clsid = value.toString();
+ if (clsid.isEmpty() || !axWidget()->loadControl(clsid))
+ reset(index);
+ else
+ QTimer::singleShot(100, this, SLOT(updatePropertySheet()));
+ }
+}
+
+int QAxWidgetPropertySheet::indexOf(const QString &name) const
+{
+ const int index = QDesignerPropertySheet::indexOf(name);
+ if (index != -1)
+ return index;
+ // Loading before recreation of sheet in timer slot: Add a fake property to store the value
+ const QVariant dummValue(0);
+ QAxWidgetPropertySheet *that = const_cast<QAxWidgetPropertySheet *>(this);
+ const int newIndex = that->createFakeProperty(name, dummValue);
+ that->setPropertyGroup(newIndex, m_propertyGroup);
+ return newIndex;
+}
+
+void QAxWidgetPropertySheet::updatePropertySheet()
+{
+ // refresh the property sheet (we are deleting m_currentProperties)
+ struct SavedProperties tmp = m_currentProperties;
+ QDesignerAxWidget *axw = axWidget();
+ QDesignerFormWindowInterface *formWin = QDesignerFormWindowInterface::findFormWindow(axw);
+ Q_ASSERT(formWin != 0);
+ tmp.widget = axw;
+ tmp.clsid = axw->control();
+ // Delete the sheets as they cache the meta object and other information
+ delete this;
+ delete qt_extension<QDesignerMemberSheetExtension *>(formWin->core()->extensionManager(), axw);
+ reloadPropertySheet(tmp, formWin);
+}
+
+void QAxWidgetPropertySheet::reloadPropertySheet(const struct SavedProperties &properties, QDesignerFormWindowInterface *formWin)
+{
+ QDesignerFormEditorInterface *core = formWin->core();
+ //Recreation of the property sheet
+ QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension *>(core->extensionManager(), properties.widget);
+
+ bool foundGeometry = false;
+ const QString geometryProperty = QLatin1String(geometryPropertyC);
+ const SavedProperties::NamePropertyMap::const_iterator cend = properties.changedProperties.constEnd();
+ for (SavedProperties::NamePropertyMap::const_iterator i = properties.changedProperties.constBegin(); i != cend; ++i) {
+ const QString name = i.key();
+ const int index = sheet->indexOf(name);
+ if (index == -1)
+ continue;
+ // filter out geometry as this will resize the control
+ // to is default size even if it is attached to an layout
+ // but set the changed flag to work around preview bug...
+ if (name == geometryProperty) {
+ sheet->setChanged(index, true);
+ foundGeometry = true;
+ continue;
+ }
+ if (name == QLatin1String(controlPropertyName)) {
+ sheet->setChanged(index, !i.value().toString().isEmpty());
+ continue;
+ }
+ sheet->setChanged(index, true);
+ sheet->setProperty(index, i.value());
+ }
+
+ if (!foundGeometry) // Make sure geometry is always changed in Designer
+ sheet->setChanged(sheet->indexOf(geometryProperty), true);
+
+ if (core->propertyEditor()->object() == properties.widget) {
+ formWin->clearSelection(true);
+ formWin->selectWidget(properties.widget);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h b/tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h
new file mode 100644
index 0000000000..64caf3cfa0
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgetpropertysheet.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTIVEXPROPERTYSHEET_H
+#define QACTIVEXPROPERTYSHEET_H
+
+#include <QtDesigner/private/qdesigner_propertysheet_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerAxWidget;
+class QDesignerFormWindowInterface;
+
+/* The propertysheet has a method to delete itself and repopulate
+ * if the "control" property changes. Pre 4.5, the control property
+ * might not be the first one, so, the properties are stored and
+ * re-applied. If the "control" is the first one, it should be
+ * sufficient to reapply the changed flags, however, care must be taken when
+ * resetting the control.
+ * Resetting a control: The current behaviour is that the modified Active X properties are added again
+ * as Fake-Properties, which is a nice side-effect as not cause a loss. */
+
+class QAxWidgetPropertySheet: public QDesignerPropertySheet
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerPropertySheetExtension)
+public:
+ explicit QAxWidgetPropertySheet(QDesignerAxWidget *object, QObject *parent = 0);
+
+ virtual bool isEnabled(int index) const;
+ virtual void setProperty(int index, const QVariant &value);
+ virtual bool reset(int index);
+ int indexOf(const QString &name) const;
+ bool dynamicPropertiesAllowed() const;
+
+ static const char *controlPropertyName;
+
+public slots:
+ void updatePropertySheet();
+
+private:
+ QDesignerAxWidget *axWidget() const;
+
+ const QString m_controlProperty;
+ const QString m_propertyGroup;
+ int m_controlIndex;
+ struct SavedProperties {
+ typedef QMap<QString, QVariant> NamePropertyMap;
+ NamePropertyMap changedProperties;
+ QWidget *widget;
+ QString clsid;
+ } m_currentProperties;
+
+ static void reloadPropertySheet(const struct SavedProperties &properties, QDesignerFormWindowInterface *formWin);
+};
+
+typedef QDesignerPropertySheetFactory<QDesignerAxWidget, QAxWidgetPropertySheet> ActiveXPropertySheetFactory;
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp b/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp
new file mode 100644
index 0000000000..96b209fe6d
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaxwidgettaskmenu.h"
+#include "qdesigneraxwidget.h"
+#include "qaxwidgetpropertysheet.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtGui/QUndoCommand>
+#include <QtGui/QMessageBox>
+#include <QtGui/QUndoStack>
+#include <QtCore/QUuid>
+#include <ActiveQt/qaxselect.h>
+
+#include <olectl.h>
+#include <qaxtypes.h>
+
+QT_BEGIN_NAMESPACE
+
+/* SetControlCommand: An undo commands that sets a control bypassing
+ Designer's property system which cannot handle the changing
+ of the 'control' property's index and other cached information
+ when modifying it. */
+
+class SetControlCommand : public QUndoCommand
+{
+public:
+ SetControlCommand(QDesignerAxWidget *ax, QDesignerFormWindowInterface *core, const QString &newClsid = QString());
+
+ virtual void redo() { apply(m_newClsid); }
+ virtual void undo() { apply(m_oldClsid); }
+
+private:
+ bool apply(const QString &clsid);
+
+ QDesignerAxWidget *m_axWidget;
+ QDesignerFormWindowInterface *m_formWindow;
+ QString m_oldClsid;
+ QString m_newClsid;
+};
+
+SetControlCommand::SetControlCommand(QDesignerAxWidget *ax, QDesignerFormWindowInterface *fw, const QString &newClsid) :
+ m_axWidget(ax),
+ m_formWindow(fw),
+ m_oldClsid(ax->control()),
+ m_newClsid(newClsid)
+{
+ if (m_newClsid.isEmpty())
+ setText(QDesignerAxWidget::tr("Reset control"));
+ else
+ setText(QDesignerAxWidget::tr("Set control"));
+}
+
+bool SetControlCommand::apply(const QString &clsid)
+{
+ if (m_oldClsid == m_newClsid)
+ return true;
+
+ QObject *ext = m_formWindow->core()->extensionManager()->extension(m_axWidget, Q_TYPEID(QDesignerPropertySheetExtension));
+ QAxWidgetPropertySheet *sheet = qobject_cast<QAxWidgetPropertySheet*>(ext);
+ if (!sheet)
+ return false;
+
+ const bool hasClsid = !clsid.isEmpty();
+ const int index = sheet->indexOf(QLatin1String(QAxWidgetPropertySheet::controlPropertyName));
+ if (hasClsid)
+ sheet->setProperty(index, clsid);
+ else
+ sheet->reset(index);
+ return true;
+}
+
+// -------------------- QAxWidgetTaskMenu
+QAxWidgetTaskMenu::QAxWidgetTaskMenu(QDesignerAxWidget *object, QObject *parent) :
+ QObject(parent),
+ m_axwidget(object),
+ m_setAction(new QAction(tr("Set Control"), this)),
+ m_resetAction(new QAction(tr("Reset Control"), this))
+{
+ connect(m_setAction, SIGNAL(triggered()), this, SLOT(setActiveXControl()));
+ connect(m_resetAction, SIGNAL(triggered()), this, SLOT(resetActiveXControl()));
+ m_taskActions.push_back(m_setAction);
+ m_taskActions.push_back(m_resetAction);
+}
+
+QAxWidgetTaskMenu::~QAxWidgetTaskMenu()
+{
+}
+
+QList<QAction*> QAxWidgetTaskMenu::taskActions() const
+{
+ const bool loaded = m_axwidget->loaded();
+ m_setAction->setEnabled(!loaded);
+ m_resetAction->setEnabled(loaded);
+ return m_taskActions;
+}
+
+void QAxWidgetTaskMenu::resetActiveXControl()
+{
+ QDesignerFormWindowInterface *formWin = QDesignerFormWindowInterface::findFormWindow(m_axwidget);
+ Q_ASSERT(formWin != 0);
+ formWin->commandHistory()->push(new SetControlCommand(m_axwidget, formWin));
+}
+
+void QAxWidgetTaskMenu::setActiveXControl()
+{
+ QAxSelect *dialog = new QAxSelect(m_axwidget->topLevelWidget());
+ if (dialog->exec()) {
+ QUuid clsid = dialog->clsid();
+ QString key;
+
+ IClassFactory2 *cf2 = 0;
+ CoGetClassObject(clsid, CLSCTX_SERVER, 0, IID_IClassFactory2, (void**)&cf2);
+
+ if (cf2) {
+ BSTR bKey;
+ HRESULT hres = cf2->RequestLicKey(0, &bKey);
+ if (hres == CLASS_E_NOTLICENSED) {
+ QMessageBox::warning(m_axwidget->topLevelWidget(), tr("Licensed Control"),
+ tr("The control requires a design-time license"));
+ clsid = QUuid();
+ } else {
+ key = QString::fromUtf16((ushort *)bKey);
+ }
+
+ cf2->Release();
+ }
+
+ if (!clsid.isNull()) {
+ QDesignerFormWindowInterface *formWin = QDesignerFormWindowInterface::findFormWindow(m_axwidget);
+
+ Q_ASSERT(formWin != 0);
+ QString value = clsid.toString();
+ if (!key.isEmpty()) {
+ value += QLatin1Char(':');
+ value += key;
+ }
+ formWin->commandHistory()->push(new SetControlCommand(m_axwidget, formWin, value));
+ }
+ }
+ delete dialog;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.h b/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.h
new file mode 100644
index 0000000000..9520673cd7
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qaxwidgettaskmenu.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTIVEXTASKMENU_H
+#define QACTIVEXTASKMENU_H
+
+#include <QtDesigner/QDesignerTaskMenuExtension>
+#include <QtDesigner/private/extensionfactory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerAxWidget;
+
+class QAxWidgetTaskMenu: public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit QAxWidgetTaskMenu(QDesignerAxWidget *object, QObject *parent = 0);
+ virtual ~QAxWidgetTaskMenu();
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void setActiveXControl();
+ void resetActiveXControl();
+
+private:
+ QDesignerAxWidget *m_axwidget;
+ QAction *m_setAction;
+ QAction *m_resetAction;
+ QList<QAction*> m_taskActions;
+};
+
+typedef qdesigner_internal::ExtensionFactory<QDesignerTaskMenuExtension, QDesignerAxWidget, QAxWidgetTaskMenu> ActiveXTaskMenuFactory;
+
+QT_END_NAMESPACE
+
+#endif // QACTIVEXTASKMENU
diff --git a/tools/designer/src/plugins/activeqt/qdesigneraxwidget.cpp b/tools/designer/src/plugins/activeqt/qdesigneraxwidget.cpp
new file mode 100644
index 0000000000..48245f1ecc
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qdesigneraxwidget.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigneraxwidget.h"
+
+#include <QtCore/QMetaProperty>
+#include <QtCore/QDebug>
+#include <QtGui/QIcon>
+#include <QtGui/QPainter>
+#include <QtGui/QResizeEvent>
+
+#include <ActiveQt/QAxWidget>
+
+#include <olectl.h>
+#include <qaxtypes.h>
+
+enum { debugAxWidget = 0 };
+
+QT_BEGIN_NAMESPACE
+
+/* XPM */
+const char *widgetIconXPM[]={
+"22 22 6 1",
+"a c #000000",
+"# c #808080",
+"+ c #aaa5a0",
+"b c #dddddd",
+"* c #d4d0c8",
+". c none",
+".........#aa#...#aa#..",
+".........abba...abba..",
+".........abba...abba..",
+".........#aa#...#aa#..",
+"..........aa.....aa...",
+"..........aa.....aa...",
+"..........aa.....aa...",
+".......aaaaaaaaaaaaaaa",
+".......a*************a",
+".......a************#a",
+".......a***********+#a",
+".......a***********+#a",
+".......a***********+#a",
+"#aa#...a***********+#a",
+"abbaaaaa***********+#a",
+"abbaaaaa***********+#a",
+"#aa#...a***********+#a",
+".......a***********+#a",
+".......a***********+#a",
+".......a**++++++++++#a",
+".......a*############a",
+".......aaaaaaaaaaaaaaa"};
+
+QDesignerAxWidget::QDesignerAxWidget(QWidget *parent) :
+ QWidget(parent),
+ m_defaultSize(80, 70),
+ m_drawFlags(DrawIndicator|DrawFrame|DrawControl),
+ m_axobject(0),
+ m_axImage(widgetIcon())
+{
+}
+
+QDesignerAxWidget::~QDesignerAxWidget()
+{
+ delete m_axobject;
+}
+
+QPixmap QDesignerAxWidget::widgetIcon()
+{
+ return QPixmap(widgetIconXPM);
+}
+
+QString QDesignerAxWidget::control() const
+{
+ if (m_axobject)
+ return m_axobject->control();
+ return QString();
+}
+
+void QDesignerAxWidget::setControl(const QString &clsid)
+{
+ if (clsid == control())
+ return;
+ if (clsid.isEmpty()) {
+ resetControl();
+ } else {
+ loadControl(clsid);
+ }
+}
+void QDesignerAxWidget::resetControl()
+{
+ if (!m_axobject)
+ return;
+ delete m_axobject;
+ m_axobject = 0;
+ update();
+}
+
+bool QDesignerAxWidget::loadControl(const QString &clsid)
+{
+ if (clsid.isEmpty())
+ return false;
+ if (m_axobject)
+ resetControl();
+ m_axobject = new QAxWidget();
+
+ if (!m_axobject->setControl(clsid)) {
+ delete m_axobject;
+ m_axobject = 0;
+ return false;
+ }
+ update();
+ return true;
+}
+
+QSize QDesignerAxWidget::sizeHint() const
+{
+ if (m_axobject)
+ return m_axobject->sizeHint();
+ return m_defaultSize;
+}
+
+QSize QDesignerAxWidget::minimumSizeHint() const
+{
+ if (m_axobject)
+ return m_axobject->minimumSizeHint();
+ return QWidget::minimumSizeHint();
+}
+
+void QDesignerAxWidget::paintEvent(QPaintEvent * /*event */)
+{
+ QPainter p(this);
+ const QRect r = contentsRect();
+ const int contentsWidth = r.width();
+ const int contentsHeight= r.height();
+ if (m_axobject) { // QAxWidget has no concept of sizeHint()
+ if (m_drawFlags & DrawControl) {
+ m_axobject->resize(size());
+ m_axobject->render(&p);
+ }
+ if (m_drawFlags & DrawIndicator) {
+ static const QString loaded = tr("Control loaded");
+ QColor patternColor(Qt::green);
+ if (m_drawFlags & DrawControl)
+ patternColor.setAlpha(80);
+ p.setBrush(QBrush(patternColor, Qt::BDiagPattern));
+ p.setPen(Qt::black);
+ if (r.height() > 5)
+ p.drawText(5,contentsHeight - 5, loaded);
+ }
+ }
+ if (m_drawFlags & DrawFrame) {
+ p.drawRect(r.adjusted(0, 0, -1, -1));
+ }
+ if (m_drawFlags & DrawIndicator) {
+ if (contentsWidth > m_axImage.width() && contentsHeight > m_axImage.height())
+ p.drawPixmap((contentsWidth - m_axImage.width()) / 2,
+ (contentsHeight-m_axImage.height()) / 2, m_axImage);
+ }
+}
+
+// --------- QDesignerAxPluginWidget
+QDesignerAxPluginWidget::QDesignerAxPluginWidget(QWidget *parent) :
+ QDesignerAxWidget(parent)
+{
+}
+
+QDesignerAxPluginWidget::~QDesignerAxPluginWidget()
+{
+}
+
+const QMetaObject *QDesignerAxPluginWidget::metaObject() const
+{
+ if (const QAxWidget *aw = axobject())
+ return aw->metaObject();
+
+ return QDesignerAxWidget::metaObject();
+}
+
+static QString msgComException(const QObject *o, const QMetaObject::Call call, int index)
+{
+ return QDesignerAxWidget::tr("A COM exception occurred when executing a meta call of type %1, index %2 of \"%3\".").
+ arg(call).arg(index).arg(o->objectName());
+}
+
+int QDesignerAxPluginWidget::qt_metacall(QMetaObject::Call call, int signal, void **argv)
+{
+ QAxWidget *aw = axobject();
+ if (!aw)
+ return QDesignerAxWidget::qt_metacall(call,signal,argv);
+
+
+ const QMetaObject *mo = metaObject();
+ // Have base class handle inherited stuff (geometry, enabled...)
+ const bool inherited = call == QMetaObject::InvokeMetaMethod ?
+ (signal < mo->methodOffset()) : (signal < mo->propertyOffset());
+ if (inherited)
+ return QDesignerAxWidget::qt_metacall(call, signal, argv);
+
+ int rc = -1;
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ if (debugAxWidget)
+ if (call != QMetaObject::InvokeMetaMethod)
+ qDebug() << objectName() << call << signal << mo->property(signal).name();
+ switch (call) {
+ case QMetaObject::QueryPropertyStored: // Pretend all changed properties are stored for them to be saved
+ if (m_propValues.contains(signal))
+ if (argv[0])
+ *reinterpret_cast< bool*>(argv[0]) = true;
+ break;
+ case QMetaObject::ResetProperty:
+ rc = aw->qt_metacall(call, signal, argv);
+ update();
+ m_propValues.remove(signal);
+ break;
+ case QMetaObject::WriteProperty:
+ rc = aw->qt_metacall(call, signal, argv);
+ update();
+ m_propValues.insert(signal, true);
+ break;
+ default:
+ rc = aw->qt_metacall(call, signal, argv);
+ break;
+ }
+#ifndef QT_NO_EXCEPTIONS
+ } catch(...) {
+ qWarning(msgComException(this, call, signal).toUtf8());
+ }
+#endif
+ return rc;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/activeqt/qdesigneraxwidget.h b/tools/designer/src/plugins/activeqt/qdesigneraxwidget.h
new file mode 100644
index 0000000000..290ce8fa40
--- /dev/null
+++ b/tools/designer/src/plugins/activeqt/qdesigneraxwidget.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTIVEXPLUGINOBJECT_H
+#define QACTIVEXPLUGINOBJECT_H
+
+#include <QtCore/QPointer>
+#include <QtCore/QMap>
+#include <QtGui/QWidget>
+#include <QtGui/QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+class QAxWidget;
+
+/* QDesignerAxWidget aggregates QAxWidget to keep it out of the event loop while applying
+ * properties directly.
+ * Thus, it is possible to set property values in designer that are out of range
+ * for the control, which might cause it to throw exceptions.
+ *
+ * QDesignerAxWidget is the base class following the internal naming
+ * conventions that makes the control property visible to the introspection interface.
+ *
+ * The trick to aggregate a QAxWidget is to overwrite the metaObject() function
+ * generated by moc to return the QMetaObject of QAxWidget. This is what QDesignerAxPluginWidget does. */
+
+class QDesignerAxWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QString control READ control WRITE setControl RESET resetControl DESIGNABLE true)
+ Q_DISABLE_COPY(QDesignerAxWidget)
+
+protected:
+ explicit QDesignerAxWidget(QWidget *parent);
+
+public:
+ virtual ~QDesignerAxWidget();
+
+ bool loadControl(const QString &clsid);
+
+ void resetControl();
+ void setControl(const QString &clsid);
+ QString control() const;
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ bool loaded() { return (m_axobject != 0); }
+
+ static QPixmap widgetIcon();
+
+ enum { DrawIndicator = 0x1, DrawFrame = 0x2, DrawControl = 0x4 };
+
+ unsigned drawFlags() const { return m_drawFlags; }
+ void setDrawFlags(unsigned f) { m_drawFlags = f; }
+
+protected:
+ void paintEvent(QPaintEvent *event);
+ QAxWidget *axobject() const { return m_axobject; }
+
+private:
+ const QSize m_defaultSize;
+ unsigned m_drawFlags;
+ QAxWidget *m_axobject;
+ QPixmap m_axImage;
+};
+
+class QDesignerAxPluginWidget : public QDesignerAxWidget
+{
+ // No Q_OBJECT here! - meta functionality is overriden
+public:
+ explicit QDesignerAxPluginWidget(QWidget *parent);
+ virtual ~QDesignerAxPluginWidget();
+
+ virtual const QMetaObject *metaObject() const;
+ virtual int qt_metacall(QMetaObject::Call, int, void **);
+
+private:
+ QMap<int, bool> m_propValues;
+};
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template <> inline QDesignerAxWidget *qobject_cast_helper<QDesignerAxWidget*>(QObject *o, QDesignerAxWidget*)
+#else
+template <> inline QDesignerAxWidget *qobject_cast<QDesignerAxWidget*>(QObject *o)
+#endif
+{
+ if (!o)
+ return 0;
+
+ // Unloaded state
+ if (strcmp(o->metaObject()->className(), "QDesignerAxWidget") == 0)
+ return static_cast<QDesignerAxPluginWidget*>(o);
+
+ // Loaded state with fake meta object
+ if (strcmp(o->metaObject()->className(), "QAxWidget") == 0)
+ return static_cast<QDesignerAxPluginWidget*>(o);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#endif // ACTIVEQT_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/phononwidgets/images/seekslider.png b/tools/designer/src/plugins/phononwidgets/images/seekslider.png
new file mode 100644
index 0000000000..a1f4cb0d50
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/images/seekslider.png
Binary files differ
diff --git a/tools/designer/src/plugins/phononwidgets/images/videoplayer.png b/tools/designer/src/plugins/phononwidgets/images/videoplayer.png
new file mode 100644
index 0000000000..55d86a6d33
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/images/videoplayer.png
Binary files differ
diff --git a/tools/designer/src/plugins/phononwidgets/images/videowidget.png b/tools/designer/src/plugins/phononwidgets/images/videowidget.png
new file mode 100644
index 0000000000..3e8706e456
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/images/videowidget.png
Binary files differ
diff --git a/tools/designer/src/plugins/phononwidgets/images/volumeslider.png b/tools/designer/src/plugins/phononwidgets/images/volumeslider.png
new file mode 100644
index 0000000000..ea81dd2a11
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/images/volumeslider.png
Binary files differ
diff --git a/tools/designer/src/plugins/phononwidgets/phononcollection.cpp b/tools/designer/src/plugins/phononwidgets/phononcollection.cpp
new file mode 100644
index 0000000000..3d32fd445a
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/phononcollection.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoplayerplugin.h"
+#include "seeksliderplugin.h"
+#include "volumesliderplugin.h"
+
+#include <QtDesigner/QDesignerCustomWidgetCollectionInterface>
+#include <QtCore/qplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+class PhononCollection: public QObject, public QDesignerCustomWidgetCollectionInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
+public:
+ explicit PhononCollection(QObject *parent = 0);
+
+ virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const;
+
+private:
+ QList<QDesignerCustomWidgetInterface*> m_plugins;
+};
+
+PhononCollection::PhononCollection(QObject *parent) :
+ QObject(parent)
+{
+ const QString group = QLatin1String("Phonon");
+ m_plugins.push_back(new VideoPlayerPlugin(group, this));
+ m_plugins.push_back(new SeekSliderPlugin(group, this));
+ m_plugins.push_back(new VolumeSliderPlugin(group, this));
+}
+
+QList<QDesignerCustomWidgetInterface*> PhononCollection::customWidgets() const
+{
+ return m_plugins;
+}
+
+Q_EXPORT_PLUGIN(PhononCollection)
+
+QT_END_NAMESPACE
+
+#include "phononcollection.moc"
diff --git a/tools/designer/src/plugins/phononwidgets/phononwidgets.pro b/tools/designer/src/plugins/phononwidgets/phononwidgets.pro
new file mode 100644
index 0000000000..4e0f0cc1af
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/phononwidgets.pro
@@ -0,0 +1,24 @@
+TEMPLATE = lib
+TARGET = phononwidgets
+CONFIG += qt warn_on plugin
+QT += phonon
+
+include(../plugins.pri)
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+# Input
+SOURCES += videoplayerplugin.cpp \
+ videoplayertaskmenu.cpp \
+ seeksliderplugin.cpp \
+ volumesliderplugin.cpp \
+ phononcollection.cpp
+
+HEADERS += videoplayerplugin.h \
+ videoplayertaskmenu.h \
+ seeksliderplugin.h \
+ volumesliderplugin.h
+
+RESOURCES += phononwidgets.qrc
diff --git a/tools/designer/src/plugins/phononwidgets/phononwidgets.qrc b/tools/designer/src/plugins/phononwidgets/phononwidgets.qrc
new file mode 100644
index 0000000000..aa51330fd7
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/phononwidgets.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/trolltech/phononwidgets">
+ <file>images/videoplayer.png</file>
+ <file>images/videowidget.png</file>
+ <file>images/seekslider.png</file>
+ <file>images/volumeslider.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/designer/src/plugins/phononwidgets/seeksliderplugin.cpp b/tools/designer/src/plugins/phononwidgets/seeksliderplugin.cpp
new file mode 100644
index 0000000000..9bb1317a67
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/seeksliderplugin.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "seeksliderplugin.h"
+
+#include <phonon/seekslider.h>
+
+static const char *toolTipC = "Phonon Seek Slider";
+
+QT_BEGIN_NAMESPACE
+
+SeekSliderPlugin::SeekSliderPlugin(const QString &group, QObject *parent) :
+ QObject(parent),
+ m_group(group),
+ m_initialized(false)
+{
+}
+
+QString SeekSliderPlugin::name() const
+{
+ return QLatin1String("Phonon::SeekSlider");
+}
+
+QString SeekSliderPlugin::group() const
+{
+ return m_group;
+}
+
+QString SeekSliderPlugin::toolTip() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString SeekSliderPlugin::whatsThis() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString SeekSliderPlugin::includeFile() const
+{
+ return QLatin1String("<phonon/seekslider.h>");
+}
+
+QIcon SeekSliderPlugin::icon() const
+{
+ return QIcon(QLatin1String(":/trolltech/phononwidgets/images/seekslider.png"));
+}
+
+bool SeekSliderPlugin::isContainer() const
+{
+ return false;
+}
+
+QWidget *SeekSliderPlugin::createWidget(QWidget *parent)
+{
+ return new Phonon::SeekSlider(parent);
+}
+
+bool SeekSliderPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void SeekSliderPlugin::initialize(QDesignerFormEditorInterface *)
+{
+ if (m_initialized)
+ return;
+ m_initialized = true;
+}
+
+QString SeekSliderPlugin::domXml() const
+{
+ return QLatin1String("\
+ <ui language=\"c++\">\
+ <widget class=\"Phonon::SeekSlider\" name=\"seekSlider\"/>\
+ </ui>");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/phononwidgets/seeksliderplugin.h b/tools/designer/src/plugins/phononwidgets/seeksliderplugin.h
new file mode 100644
index 0000000000..6facefe02e
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/seeksliderplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SEEKSLIDER_PLUGIN_H
+#define SEEKSLIDER_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class SeekSliderPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ explicit SeekSliderPlugin(const QString &group, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ const QString m_group;
+ bool m_initialized;
+};
+
+QT_END_NAMESPACE
+
+#endif // SEEKSLIDER_PLUGIN_H
diff --git a/tools/designer/src/plugins/phononwidgets/videoplayerplugin.cpp b/tools/designer/src/plugins/phononwidgets/videoplayerplugin.cpp
new file mode 100644
index 0000000000..a111b1aee3
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/videoplayerplugin.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoplayerplugin.h"
+#include "videoplayertaskmenu.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+#include <QtDesigner/QDesignerFormEditorInterface>
+
+#include <QtCore/qplugin.h>
+#include <phonon/videoplayer.h>
+
+static const char *toolTipC = "Phonon Video Player";
+
+QT_BEGIN_NAMESPACE
+
+VideoPlayerPlugin::VideoPlayerPlugin(const QString &group, QObject *parent) :
+ QObject(parent),
+ m_group(group),
+ m_initialized(false)
+{
+}
+
+QString VideoPlayerPlugin::name() const
+{
+ return QLatin1String("Phonon::VideoPlayer");
+}
+
+QString VideoPlayerPlugin::group() const
+{
+ return m_group;
+}
+
+QString VideoPlayerPlugin::toolTip() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString VideoPlayerPlugin::whatsThis() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString VideoPlayerPlugin::includeFile() const
+{
+ return QLatin1String("<phonon/videoplayer.h>");
+}
+
+QIcon VideoPlayerPlugin::icon() const
+{
+ return QIcon(QLatin1String(":/trolltech/phononwidgets/images/videoplayer.png"));
+}
+
+bool VideoPlayerPlugin::isContainer() const
+{
+ return false;
+}
+
+QWidget *VideoPlayerPlugin::createWidget(QWidget *parent)
+{
+ return new Phonon::VideoPlayer(Phonon::NoCategory, parent);
+}
+
+bool VideoPlayerPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void VideoPlayerPlugin::initialize(QDesignerFormEditorInterface * core)
+{
+ if (m_initialized)
+ return;
+
+ QExtensionManager *mgr = core->extensionManager();
+ VideoPlayerTaskMenuFactory::registerExtension(mgr, Q_TYPEID(QDesignerTaskMenuExtension));
+ m_initialized = true;
+}
+
+QString VideoPlayerPlugin::domXml() const
+{
+ return QLatin1String("\
+ <ui language=\"c++\">\
+ <widget class=\"Phonon::VideoPlayer\" name=\"videoPlayer\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>300</width>\
+ <height>200</height>\
+ </rect>\
+ </property>\
+ </widget>\
+ </ui>");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/phononwidgets/videoplayerplugin.h b/tools/designer/src/plugins/phononwidgets/videoplayerplugin.h
new file mode 100644
index 0000000000..1f88dc6186
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/videoplayerplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOPLAYER_PLUGIN_H
+#define VIDEOPLAYER_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class VideoPlayerPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ explicit VideoPlayerPlugin(const QString &group, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ const QString m_group;
+ bool m_initialized;
+};
+
+QT_END_NAMESPACE
+
+#endif // VIDEOPLAYER_PLUGIN_H
diff --git a/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp b/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp
new file mode 100644
index 0000000000..9c1f2f7415
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "videoplayertaskmenu.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerFormWindowCursorInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <phonon/videoplayer.h>
+#include <phonon/mediaobject.h>
+
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QAction>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+
+QT_BEGIN_NAMESPACE
+
+// ----------------- MimeTypeDialog: Display mime types in scrollable text
+
+class MimeTypeDialog : public QDialog {
+ Q_DISABLE_COPY(MimeTypeDialog)
+public:
+ explicit MimeTypeDialog(QWidget *parent = 0);
+
+ void setMimeTypes(const QStringList &);
+
+private:
+ QPlainTextEdit *m_plainTextEdit;
+};
+
+MimeTypeDialog::MimeTypeDialog(QWidget *parent) :
+ QDialog(parent),
+ m_plainTextEdit(new QPlainTextEdit)
+{
+ setModal(true);
+ setWindowTitle(VideoPlayerTaskMenu::tr("Available Mime Types"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ m_plainTextEdit->setReadOnly(true);
+ layout->addWidget(m_plainTextEdit);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ layout->addWidget(buttonBox);
+
+ setLayout(layout);
+}
+
+void MimeTypeDialog::setMimeTypes(const QStringList &l)
+{
+ m_plainTextEdit->setPlainText(l.join(QString(1, QLatin1Char('\n'))));
+}
+
+// ----------------- VideoPlayerTaskMenu
+VideoPlayerTaskMenu::VideoPlayerTaskMenu(Phonon::VideoPlayer *object, QObject *parent) :
+ QObject(parent),
+ m_widget(object),
+ m_displayMimeTypesAction(new QAction(tr("Display supported mime types..."), this)),
+ m_loadAction(new QAction(tr("Load..."), this)),
+ m_playAction(new QAction(tr("Play"), this)),
+ m_pauseAction(new QAction(tr("Pause"), this)),
+ m_stopAction(new QAction(tr("Stop"), this))
+{
+ m_taskActions << m_displayMimeTypesAction << m_loadAction << m_playAction << m_pauseAction << m_stopAction;
+
+ connect(m_widget->mediaObject(), SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(mediaObjectStateChanged(Phonon::State,Phonon::State)));
+ connect(m_displayMimeTypesAction, SIGNAL(triggered()), this, SLOT(slotMimeTypes()));
+ connect(m_loadAction, SIGNAL(triggered()), this, SLOT(slotLoad()));
+ connect(m_playAction, SIGNAL(triggered()), object, SLOT(play()));
+ connect(m_pauseAction, SIGNAL(triggered()), object, SLOT(pause()));
+ connect(m_stopAction, SIGNAL(triggered()), object, SLOT(stop()));
+}
+
+QList<QAction*> VideoPlayerTaskMenu::taskActions() const
+{
+ const bool isPlaying = m_widget->isPlaying();
+ const bool isPaused = m_widget->isPlaying();
+ m_loadAction->setEnabled(!isPlaying && !isPaused);
+ m_playAction->setEnabled(!isPlaying);
+ m_pauseAction->setEnabled(isPlaying);
+ m_stopAction->setEnabled(isPlaying || isPaused);
+ return m_taskActions;
+}
+
+void VideoPlayerTaskMenu::slotMimeTypes()
+{
+ MimeTypeDialog mimeTypeDialog(m_widget->window());
+ mimeTypeDialog.setMimeTypes(Phonon::BackendCapabilities::availableMimeTypes());
+ mimeTypeDialog.exec();
+}
+
+void VideoPlayerTaskMenu::slotLoad()
+{
+ const QString fileName = QFileDialog::getOpenFileName(m_widget->window(), tr("Choose Video Player Media Source"));
+ if (fileName.isEmpty())
+ return;
+ m_widget->load(Phonon::MediaSource(fileName));
+
+}
+
+void VideoPlayerTaskMenu::mediaObjectStateChanged(Phonon::State newstate, Phonon::State /* oldstate */)
+{
+ if (newstate == Phonon::ErrorState) {
+ const QString msg = tr("An error has occurred in '%1': %2").arg(m_widget->objectName(), m_widget->mediaObject()->errorString());
+ QMessageBox::warning(m_widget->window(), tr("Video Player Error"), msg);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h b/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h
new file mode 100644
index 0000000000..d58d62d5eb
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIDEOPLAYERTASKMENU_H
+#define VIDEOPLAYERTASKMENU_H
+
+
+#include <QtCore/QObject>
+#include <QtDesigner/QDesignerTaskMenuExtension>
+#include <QtDesigner/private/extensionfactory_p.h>
+
+#include <phonon>
+
+QT_BEGIN_NAMESPACE
+
+class VideoPlayerTaskMenu: public QObject, public QDesignerTaskMenuExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerTaskMenuExtension)
+public:
+ explicit VideoPlayerTaskMenu(Phonon::VideoPlayer *object, QObject *parent = 0);
+ virtual QList<QAction*> taskActions() const;
+
+private slots:
+ void slotLoad();
+ void slotMimeTypes();
+ void mediaObjectStateChanged(Phonon::State newstate, Phonon::State oldstate);
+
+private:
+ Phonon::VideoPlayer *m_widget;
+ QAction *m_displayMimeTypesAction;
+ QAction *m_loadAction;
+ QAction *m_playAction;
+ QAction *m_pauseAction;
+ QAction *m_stopAction;
+
+ QList<QAction*> m_taskActions;
+};
+
+typedef qdesigner_internal::ExtensionFactory<QDesignerTaskMenuExtension, Phonon::VideoPlayer, VideoPlayerTaskMenu> VideoPlayerTaskMenuFactory;
+
+QT_END_NAMESPACE
+
+#endif // VIDEOPLAYERTASKMENU_H
diff --git a/tools/designer/src/plugins/phononwidgets/volumesliderplugin.cpp b/tools/designer/src/plugins/phononwidgets/volumesliderplugin.cpp
new file mode 100644
index 0000000000..61625cc7c2
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/volumesliderplugin.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "volumesliderplugin.h"
+
+#include <phonon/volumeslider.h>
+
+static const char *toolTipC = "Phonon Volume Slider";
+
+QT_BEGIN_NAMESPACE
+
+VolumeSliderPlugin::VolumeSliderPlugin(const QString &group, QObject *parent) :
+ QObject(parent),
+ m_group(group),
+ m_initialized(false)
+{
+}
+
+QString VolumeSliderPlugin::name() const
+{
+ return QLatin1String("Phonon::VolumeSlider");
+}
+
+QString VolumeSliderPlugin::group() const
+{
+ return m_group;
+}
+
+QString VolumeSliderPlugin::toolTip() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString VolumeSliderPlugin::whatsThis() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString VolumeSliderPlugin::includeFile() const
+{
+ return QLatin1String("<phonon/volumeslider.h>");
+}
+
+QIcon VolumeSliderPlugin::icon() const
+{
+ return QIcon(QLatin1String(":/trolltech/phononwidgets/images/volumeslider.png"));
+}
+
+bool VolumeSliderPlugin::isContainer() const
+{
+ return false;
+}
+
+QWidget *VolumeSliderPlugin::createWidget(QWidget *parent)
+{
+ return new Phonon::VolumeSlider(parent);
+}
+
+bool VolumeSliderPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void VolumeSliderPlugin::initialize(QDesignerFormEditorInterface *)
+{
+ if (m_initialized)
+ return;
+ m_initialized = true;
+}
+
+QString VolumeSliderPlugin::domXml() const
+{
+ return QLatin1String("\
+ <ui language=\"c++\">\
+ <widget class=\"Phonon::VolumeSlider\" name=\"volumeSlider\"/>\
+ </ui>");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/phononwidgets/volumesliderplugin.h b/tools/designer/src/plugins/phononwidgets/volumesliderplugin.h
new file mode 100644
index 0000000000..02c5fe1abf
--- /dev/null
+++ b/tools/designer/src/plugins/phononwidgets/volumesliderplugin.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VOLUMESLIDER_PLUGIN_H
+#define VOLUMESLIDER_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class VolumeSliderPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ explicit VolumeSliderPlugin(const QString &group, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ const QString m_group;
+ bool m_initialized;
+};
+
+QT_END_NAMESPACE
+
+#endif // VOLUMESLIDER_PLUGIN_H
diff --git a/tools/designer/src/plugins/plugins.pri b/tools/designer/src/plugins/plugins.pri
new file mode 100644
index 0000000000..e5edfe2f2e
--- /dev/null
+++ b/tools/designer/src/plugins/plugins.pri
@@ -0,0 +1,8 @@
+CONFIG += designer
+win32|mac: CONFIG+= debug_and_release
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer
+contains(TEMPLATE, ".*lib"):TARGET = $$qtLibraryTarget($$TARGET)
+
+# install
+target.path = $$[QT_INSTALL_PLUGINS]/designer
+INSTALLS += target
diff --git a/tools/designer/src/plugins/plugins.pro b/tools/designer/src/plugins/plugins.pro
new file mode 100644
index 0000000000..baf5261139
--- /dev/null
+++ b/tools/designer/src/plugins/plugins.pro
@@ -0,0 +1,9 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+REQUIRES = !CONFIG(static,shared|static)
+contains(QT_CONFIG, qt3support): SUBDIRS += widgets
+win32:!contains(QT_EDITION, OpenSource):SUBDIRS += activeqt
+# contains(QT_CONFIG, opengl): SUBDIRS += tools/view3d
+contains(QT_CONFIG, webkit): SUBDIRS += qwebview
+contains(QT_CONFIG, phonon): SUBDIRS += phononwidgets
diff --git a/tools/designer/src/plugins/qwebview/images/qwebview.png b/tools/designer/src/plugins/qwebview/images/qwebview.png
new file mode 100644
index 0000000000..01a0920c93
--- /dev/null
+++ b/tools/designer/src/plugins/qwebview/images/qwebview.png
Binary files differ
diff --git a/tools/designer/src/plugins/qwebview/qwebview.pro b/tools/designer/src/plugins/qwebview/qwebview.pro
new file mode 100644
index 0000000000..b1f6371d15
--- /dev/null
+++ b/tools/designer/src/plugins/qwebview/qwebview.pro
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+TARGET = qwebview
+CONFIG += qt warn_on plugin
+QT += webkit
+
+include(../plugins.pri)
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+# Input
+SOURCES += qwebview_plugin.cpp
+HEADERS += qwebview_plugin.h
+RESOURCES += qwebview_plugin.qrc
diff --git a/tools/designer/src/plugins/qwebview/qwebview_plugin.cpp b/tools/designer/src/plugins/qwebview/qwebview_plugin.cpp
new file mode 100644
index 0000000000..9b0932a99e
--- /dev/null
+++ b/tools/designer/src/plugins/qwebview/qwebview_plugin.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwebview_plugin.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtWebKit/QWebView>
+
+static const char *toolTipC = "QtWebKit Web widget";
+
+QT_BEGIN_NAMESPACE
+
+QWebViewPlugin::QWebViewPlugin(QObject *parent) :
+ QObject(parent),
+ m_initialized(false)
+{
+}
+
+QString QWebViewPlugin::name() const
+{
+ return QLatin1String("QWebView");
+}
+
+QString QWebViewPlugin::group() const
+{
+ return QLatin1String("Display Widgets");
+}
+
+QString QWebViewPlugin::toolTip() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString QWebViewPlugin::whatsThis() const
+{
+ return QString(QLatin1String(toolTipC));
+}
+
+QString QWebViewPlugin::includeFile() const
+{
+ return QLatin1String("QtWebKit/QWebView");
+}
+
+QIcon QWebViewPlugin::icon() const
+{
+ return QIcon(QLatin1String(":/trolltech/qwebview/images/qwebview.png"));
+}
+
+bool QWebViewPlugin::isContainer() const
+{
+ return false;
+}
+
+QWidget *QWebViewPlugin::createWidget(QWidget *parent)
+{
+ return new QWebView(parent);
+}
+
+bool QWebViewPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void QWebViewPlugin::initialize(QDesignerFormEditorInterface * /*core*/)
+{
+ if (m_initialized)
+ return;
+
+ m_initialized = true;
+}
+
+QString QWebViewPlugin::domXml() const
+{
+ return QLatin1String("\
+ <ui language=\"c++\">\
+ <widget class=\"QWebView\" name=\"webView\">\
+ <property name=\"url\">\
+ <url>\
+ <string>about:blank</string>\
+ </url>\
+ </property>\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>300</width>\
+ <height>200</height>\
+ </rect>\
+ </property>\
+ </widget>\
+ </ui>");
+}
+
+Q_EXPORT_PLUGIN2(customwidgetplugin, QWebViewPlugin)
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/qwebview/qwebview_plugin.h b/tools/designer/src/plugins/qwebview/qwebview_plugin.h
new file mode 100644
index 0000000000..345daa76c6
--- /dev/null
+++ b/tools/designer/src/plugins/qwebview/qwebview_plugin.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBPAGE_PLUGIN_H
+#define QWEBPAGE_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class QWebViewPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ QWebViewPlugin(QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBPAGE_PLUGIN_H
diff --git a/tools/designer/src/plugins/qwebview/qwebview_plugin.qrc b/tools/designer/src/plugins/qwebview/qwebview_plugin.qrc
new file mode 100644
index 0000000000..a3e2b90169
--- /dev/null
+++ b/tools/designer/src/plugins/qwebview/qwebview_plugin.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/trolltech/qwebview">
+ <file>images/qwebview.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/designer/src/plugins/tools/view3d/view3d.cpp b/tools/designer/src/plugins/tools/view3d/view3d.cpp
new file mode 100644
index 0000000000..97d90975f1
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d.cpp
@@ -0,0 +1,492 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtGui>
+#include <QtOpenGL>
+
+#include "abstractformeditor.h"
+#include "abstractmetadatabase.h"
+#include "abstractformwindow.h"
+#include "view3d.h"
+
+#define SELECTION_BUFSIZE 512
+
+/*******************************************************************************
+** QView3DWidget
+*/
+
+class QView3DWidget : public QGLWidget
+{
+ Q_OBJECT
+public:
+ QView3DWidget(QWidget *parent);
+ virtual void initializeGL();
+ virtual void resizeGL(int w, int h);
+ virtual void paintGL();
+ void clear();
+
+ void addTexture(QWidget *w, const QPixmap &pm);
+
+ void beginAddingWidgets(QWidget *form);
+ void addWidget(int depth, QWidget *w);
+ void endAddingWidgets();
+
+ QWidget *widgetAt(const QPoint &pos);
+
+signals:
+ void updateForm();
+
+protected:
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void wheelEvent(QWheelEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+
+ void contextMenuEvent(QContextMenuEvent *);
+
+private:
+ QWidget *m_form;
+ QPoint m_old_pos;
+ bool m_layer_coloring;
+ bool m_use_mipmaps;
+ GLuint m_form_list_id;
+
+ typedef QMap<QWidget*, GLuint> TextureMap;
+ TextureMap m_texture_map;
+
+ typedef QMap<GLuint, QWidget*> WidgetNameMap;
+ GLuint m_next_widget_name;
+ WidgetNameMap m_widget_name_map;
+};
+
+QView3DWidget::QView3DWidget(QWidget *parent)
+ : QGLWidget(parent)
+ , m_layer_coloring(true)
+ , m_form_list_id(0)
+ , m_next_widget_name(0)
+{
+ setFocusPolicy(Qt::StrongFocus);
+}
+
+static int nearestSize(int v)
+{
+ int n = 0, last = 0;
+ for (int s = 0; s < 32; ++s) {
+ if (((v>>s) & 1) == 1) {
+ ++n;
+ last = s;
+ }
+ }
+ if (n > 1)
+ return 1 << (last+1);
+ return 1 << last;
+}
+
+// static int pm_cnt = 0;
+
+void QView3DWidget::addTexture(QWidget *w, const QPixmap &pm)
+{
+ int tx_w = nearestSize(pm.width());
+ int tx_h = nearestSize(pm.height());
+
+ QPixmap tmp(tx_w, tx_h);
+ tmp.fill(QColor(0,0,0));
+ QPainter p(&tmp);
+ p.drawPixmap(0, tx_h - pm.height(), pm);
+ p.end();
+ QImage tex = tmp.toImage();
+
+// QString file_name = QString("pixmapDump%1.png").arg(pm_cnt++);
+// qDebug() << "grabWidget():" << file_name << tex.save(file_name, "PNG");
+
+ tex = QGLWidget::convertToGLFormat(tex);
+
+ GLuint tx_id;
+ glGenTextures(1, &tx_id);
+ glBindTexture(GL_TEXTURE_2D, tx_id);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ if (m_use_mipmaps) {
+ //glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
+ //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.f);
+ } else {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex.width(), tex.height(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, tex.bits());
+ m_texture_map[w] = tx_id;
+}
+
+void QView3DWidget::addWidget(int depth, QWidget *widget)
+{
+ TextureMap::const_iterator it = m_texture_map.find(widget);
+ Q_ASSERT(it != m_texture_map.end());
+
+ makeCurrent();
+
+ int w = m_form->size().width();
+ int h = m_form->size().height();
+ int max = qMax(w, h);
+ QRect r = widget->rect();
+ QPoint pos = widget->mapToGlobal(QPoint(0, 0));
+ r.moveTopLeft(m_form->mapFromGlobal(pos));
+
+ float s = r.width()/float(nearestSize(r.width()));
+ float t = r.height()/float(nearestSize(r.height()));
+
+ if (m_layer_coloring)
+ glColor4f(1.0 - depth/10.0, 1.0 - depth/10.0, 1.0, 1.0 - depth/20.0);
+ else
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ glBindTexture(GL_TEXTURE_2D, *it);
+ glBegin(GL_QUADS);
+ glLoadName(m_next_widget_name);
+ glTexCoord2f(0.0, 0.0); glVertex3f(r.left() - w/2, r.bottom() - h/2, depth*max/8);
+ glTexCoord2f(s, 0.0); glVertex3f(r.right() - w/2, r.bottom()- h/2, depth*max/8);
+ glTexCoord2f(s, t); glVertex3f(r.right() - w/2, r.top() - h/2, depth*max/8);
+ glTexCoord2f(0.0, t); glVertex3f(r.left() - w/2, r.top() - h/2, depth*max/8);
+ glEnd();
+
+ m_widget_name_map[m_next_widget_name++] = widget;
+}
+
+void QView3DWidget::clear()
+{
+ makeCurrent();
+ glDeleteLists(m_form_list_id, 1);
+ foreach (GLuint id, m_texture_map)
+ glDeleteTextures(1, &id);
+ m_texture_map.clear();
+ m_widget_name_map.clear();
+ m_next_widget_name = 0;
+}
+
+void QView3DWidget::beginAddingWidgets(QWidget *form)
+{
+ makeCurrent();
+ m_form = form;
+ m_form_list_id = glGenLists(1);
+ glNewList(m_form_list_id, GL_COMPILE);
+ glInitNames();
+ glPushName(-1);
+ m_next_widget_name = 0;
+}
+
+void QView3DWidget::endAddingWidgets()
+{
+ makeCurrent();
+ glEndList();
+}
+
+void QView3DWidget::initializeGL()
+{
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ qglClearColor(palette().color(QPalette::Window).dark());
+ glColor3f (1.0, 1.0, 1.0);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+
+ glShadeModel(GL_FLAT);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ QString extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
+ m_use_mipmaps = false;// extensions.contains("GL_SGIS_generate_mipmap");
+}
+
+void QView3DWidget::resizeGL(int width, int height)
+{
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-width/2, width/2, height/2, -height/2, -999999, 999999);
+}
+
+void QView3DWidget::paintGL()
+{
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glCallList(m_form_list_id);
+
+ glPushAttrib(GL_ENABLE_BIT);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glTranslatef(-width()/2, -height()/2, 0.0);
+
+ QFontMetrics fm(font());
+ glColor4f(0.4, 0.4, 0.4, 0.7);
+ glRecti(0, height() - fm.lineSpacing()*2.5, width(), height());
+
+ glColor3f(1.0, 1.0, 1.0);
+ renderText(10, height() - fm.lineSpacing()*1.5,
+ "Press and hold left/right mouse button = tilt the view.");
+ renderText(10, height() - fm.lineSpacing()*0.5,
+ "Mouse wheel = zoom. 't' = toggle layer coloring. 'r' = reset transform.");
+ glPopMatrix();
+ glPopAttrib();
+}
+
+QWidget *QView3DWidget::widgetAt(const QPoint &pos)
+{
+ makeCurrent();
+ GLuint selectBuf[SELECTION_BUFSIZE];
+ glSelectBuffer(SELECTION_BUFSIZE, selectBuf);
+ glRenderMode (GL_SELECT);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glCallList(m_form_list_id);
+ return 0;
+}
+
+void QView3DWidget::keyReleaseEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_T) {
+ m_layer_coloring = !m_layer_coloring;
+ emit updateForm();
+ } else if (e->key() == Qt::Key_R) {
+ makeCurrent();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ }
+
+ updateGL();
+}
+
+void QView3DWidget::mousePressEvent(QMouseEvent *e)
+{
+ m_old_pos = e->pos();
+}
+
+void QView3DWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ m_old_pos = e->pos();
+}
+
+void QView3DWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ if (e->buttons() & (Qt::LeftButton | Qt::RightButton)) {
+ GLfloat rx = (GLfloat) (e->x() - m_old_pos.x()) / width();
+ GLfloat ry = (GLfloat) (e->y() - m_old_pos.y()) / height();
+
+ makeCurrent();
+ glMatrixMode(GL_MODELVIEW);
+ if (e->buttons() & Qt::LeftButton) {
+ // Left button down - rotate around X and Y axes
+ glRotatef(-180*ry, 1, 0, 0);
+ glRotatef(180*rx, 0, 1, 0);
+ } else if (e->buttons() & Qt::RightButton) {
+ // Right button down - rotate around X and Z axes
+ glRotatef(-180*ry, 1, 0, 0);
+ glRotatef(-180*rx, 0, 0, 1);
+ }
+ updateGL();
+ m_old_pos = e->pos();
+ } else {
+
+ }
+}
+
+void QView3DWidget::wheelEvent(QWheelEvent *e)
+{
+ makeCurrent();
+ glMatrixMode(GL_MODELVIEW);
+ if (e->delta() < 0)
+ glScalef(0.9, 0.9, 0.9);
+ else
+ glScalef(1.1, 1.1, 1.1);
+ updateGL();
+}
+
+void QView3DWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ e->accept();
+}
+
+/*******************************************************************************
+** Misc tools
+*/
+
+class WalkWidgetTreeFunction
+{
+public:
+ virtual void operator () (int depth, QWidget *widget) const = 0;
+};
+
+static bool skipWidget(QDesignerFormEditorInterface *core, QWidget *widget)
+{
+ QDesignerMetaDataBaseItemInterface *item = core->metaDataBase()->item(widget);
+ if (item == 0)
+ return true;
+ QString name = widget->metaObject()->className();
+ if (name == "QLayoutWidget")
+ return true;
+
+ return false;
+}
+
+static void walkWidgetTree(QDesignerFormEditorInterface *core, int depth, QWidget *widget, const WalkWidgetTreeFunction &func)
+{
+ if (widget == 0)
+ return;
+ if (!widget->isVisible())
+ return;
+
+ if (!skipWidget(core, widget))
+ func(depth++, widget);
+
+ QObjectList child_obj_list = widget->children();
+ foreach (QObject *child_obj, child_obj_list) {
+ QWidget *child = qobject_cast<QWidget*>(child_obj);
+ if (child != 0)
+ walkWidgetTree(core, depth, child, func);
+ }
+}
+
+static void grabWidget_helper(QWidget *widget, QPixmap &res, QPixmap &buf,
+ const QRect &r, const QPoint &offset, QDesignerFormEditorInterface *core)
+{
+ buf.fill(widget, r.topLeft());
+ QPainter::setRedirected(widget, &buf, r.topLeft());
+ QPaintEvent e(r & widget->rect());
+ QApplication::sendEvent(widget, &e);
+ QPainter::restoreRedirected(widget);
+ {
+ QPainter pt(&res);
+ pt.drawPixmap(offset.x(), offset.y(), buf, 0, 0, r.width(), r.height());
+ }
+
+ const QObjectList children = widget->children();
+ for (int i = 0; i < children.size(); ++i) {
+ QWidget *child = qobject_cast<QWidget*>(children.at(i));
+ if (child == 0 || child->isWindow())
+ continue;
+ if (child->isHidden() || !child->geometry().intersects(r))
+ continue;
+ if (core->metaDataBase()->item(child) != 0)
+ continue;
+ QRect cr = r & child->geometry();
+ cr.translate(-child->pos());
+ grabWidget_helper(child, res, buf, cr, offset + child->pos(), core);
+ }
+}
+
+static QPixmap grabWidget(QWidget * widget, QDesignerFormEditorInterface *core)
+{
+ if (!widget)
+ return QPixmap();
+
+ QRect r = widget->rect();
+ QSize s = widget->size();
+
+ QPixmap res(s), buf(s);
+
+ grabWidget_helper(widget, res, buf, r, QPoint(), core);
+
+ return res;
+}
+
+/*******************************************************************************
+** QView3D
+*/
+
+class AddTexture : public WalkWidgetTreeFunction
+{
+public:
+ inline AddTexture(QDesignerFormEditorInterface *core, QView3DWidget *w)
+ : m_core(core), m_3d_widget(w) {}
+ inline virtual void operator ()(int, QWidget *w) const
+ { m_3d_widget->addTexture(w, ::grabWidget(w, m_core)); }
+ QDesignerFormEditorInterface *m_core;
+ QView3DWidget *m_3d_widget;
+};
+
+class AddWidget : public WalkWidgetTreeFunction
+{
+public:
+ inline AddWidget(QView3DWidget *w) : m_3d_widget(w) {}
+ inline virtual void operator ()(int depth, QWidget *w) const
+ { m_3d_widget->addWidget(depth, w); }
+ QView3DWidget *m_3d_widget;
+};
+
+QView3D::QView3D(QDesignerFormWindowInterface *form_window, QWidget *parent)
+ : QWidget(parent)
+{
+ m_form_window = form_window;
+ m_3d_widget = new QView3DWidget(this);
+ connect(m_3d_widget, SIGNAL(updateForm()), this, SLOT(updateForm()));
+
+ QGridLayout *layout = new QGridLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_3d_widget, 0, 0, 1, 1);
+
+ updateForm();
+}
+
+void QView3D::updateForm()
+{
+ QWidget *w = m_form_window->mainContainer();
+ if (w == 0)
+ return;
+
+ m_3d_widget->clear();
+
+ walkWidgetTree(m_form_window->core(), 0, w, AddTexture(m_form_window->core(), m_3d_widget));
+ m_3d_widget->beginAddingWidgets(w);
+ walkWidgetTree(m_form_window->core(), 0, w, AddWidget(m_3d_widget));
+ m_3d_widget->endAddingWidgets();
+}
+
+#include "view3d.moc"
diff --git a/tools/designer/src/plugins/tools/view3d/view3d.h b/tools/designer/src/plugins/tools/view3d/view3d.h
new file mode 100644
index 0000000000..bc6b58332e
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIEW3D_H
+#define VIEW3D_H
+
+#include "view3d_global.h"
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QScrollBar;
+class QGLWidget;
+class QDesignerFormWindowInterface;
+
+class QView3DWidget;
+
+class QView3D : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QView3D(QDesignerFormWindowInterface *form_window, QWidget *parent);
+
+public slots:
+ void updateForm();
+
+private:
+ QView3DWidget *m_3d_widget;
+ QDesignerFormWindowInterface *m_form_window;
+
+ void addWidget(int depth, QWidget *w);
+ void addTexture(QWidget *w);
+};
+
+#endif // VIEW3D_H
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/tools/view3d/view3d.pro b/tools/designer/src/plugins/tools/view3d/view3d.pro
new file mode 100644
index 0000000000..c28c706930
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d.pro
@@ -0,0 +1,17 @@
+
+TEMPLATE = lib
+QT += opengl
+CONFIG += qt warn_on plugin
+DESTDIR =
+TARGET = view3d
+
+include(../../plugins.pri)
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+# Input
+SOURCES += view3d.cpp view3d_tool.cpp view3d_plugin.cpp
+HEADERS += view3d.h view3d_tool.h view3d_plugin.h view3d_global.h
+
diff --git a/tools/designer/src/plugins/tools/view3d/view3d_global.h b/tools/designer/src/plugins/tools/view3d/view3d_global.h
new file mode 100644
index 0000000000..90c8ce2528
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d_global.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIEW3D_GLOBAL_H
+#define VIEW3D_GLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+#ifdef VIEW3D_LIBRARY
+# define VIEW3D_EXPORT
+#else
+# define VIEW3D_EXPORT
+#endif
+#else
+#define VIEW3D_EXPORT
+#endif
+
+#endif // VIEW3D_GLOBAL_H
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/tools/view3d/view3d_plugin.cpp b/tools/designer/src/plugins/tools/view3d/view3d_plugin.cpp
new file mode 100644
index 0000000000..a599e7e4b3
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d_plugin.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qplugin.h>
+#include <QtGui/QAction>
+#include "view3d_plugin.h"
+#include "view3d_tool.h"
+
+QView3DPlugin::QView3DPlugin()
+{
+ m_core = 0;
+ m_action = 0;
+}
+
+bool QView3DPlugin::isInitialized() const
+{
+ return m_core != 0;
+}
+
+void QView3DPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_ASSERT(!isInitialized());
+
+ m_action = new QAction(tr("3D View"), this);
+ m_core = core;
+ setParent(core);
+
+ connect(core->formWindowManager(), SIGNAL(formWindowAdded(QDesignerFormWindowInterface*)),
+ this, SLOT(addFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(formWindowRemoved(QDesignerFormWindowInterface*)),
+ this, SLOT(removeFormWindow(QDesignerFormWindowInterface*)));
+
+ connect(core->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
+ this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
+}
+
+QAction *QView3DPlugin::action() const
+{
+ return m_action;
+}
+
+QDesignerFormEditorInterface *QView3DPlugin::core() const
+{
+ return m_core;
+}
+
+void QView3DPlugin::activeFormWindowChanged(QDesignerFormWindowInterface *formWindow)
+{
+ m_action->setEnabled(formWindow != 0);
+}
+
+void QView3DPlugin::addFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tool_list.contains(formWindow) == false);
+
+ QView3DTool *tool = new QView3DTool(formWindow, this);
+ m_tool_list[formWindow] = tool;
+ connect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+ formWindow->registerTool(tool);
+}
+
+void QView3DPlugin::removeFormWindow(QDesignerFormWindowInterface *formWindow)
+{
+ Q_ASSERT(formWindow != 0);
+ Q_ASSERT(m_tool_list.contains(formWindow));
+
+ QView3DTool *tool = m_tool_list.value(formWindow);
+ m_tool_list.remove(formWindow);
+ disconnect(m_action, SIGNAL(triggered()), tool->action(), SLOT(trigger()));
+
+ delete tool;
+}
+
+Q_EXPORT_PLUGIN2(view3d, QView3DPlugin)
diff --git a/tools/designer/src/plugins/tools/view3d/view3d_plugin.h b/tools/designer/src/plugins/tools/view3d/view3d_plugin.h
new file mode 100644
index 0000000000..a9db8a6147
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d_plugin.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3VIEW3D_PLUGIN_H
+#define Q3VIEW3D_PLUGIN_H
+
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtDesigner/QDesignerFormEditorPluginInterface>
+#include "view3d_global.h"
+
+QT_BEGIN_NAMESPACE
+
+class QView3DTool;
+class QAction;
+
+class VIEW3D_EXPORT QView3DPlugin : public QObject, public QDesignerFormEditorPluginInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerFormEditorPluginInterface)
+
+public:
+ QView3DPlugin();
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QAction *action() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+public slots:
+ void activeFormWindowChanged(QDesignerFormWindowInterface *formWindow);
+
+private slots:
+ void addFormWindow(QDesignerFormWindowInterface *formWindow);
+ void removeFormWindow(QDesignerFormWindowInterface *formWindow);
+
+private:
+ QPointer<QDesignerFormEditorInterface> m_core;
+ QHash<QDesignerFormWindowInterface*, QView3DTool*> m_tool_list;
+ QAction *m_action;
+};
+
+#endif // QVIEW3D_PLUGIN_H
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/tools/view3d/view3d_tool.cpp b/tools/designer/src/plugins/tools/view3d/view3d_tool.cpp
new file mode 100644
index 0000000000..05015c3519
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d_tool.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QAction>
+#include "view3d_tool.h"
+
+QView3DTool::QView3DTool(QDesignerFormWindowInterface *formWindow, QObject *parent)
+ : QDesignerFormWindowToolInterface(parent)
+{
+ m_action = new QAction(tr("3DView"), this);
+ m_formWindow = formWindow;
+}
+
+QDesignerFormEditorInterface *QView3DTool::core() const
+{
+ return m_formWindow->core();
+}
+
+QDesignerFormWindowInterface *QView3DTool::formWindow() const
+{
+ return m_formWindow;
+}
+
+QWidget *QView3DTool::editor() const
+{
+ if (m_editor == 0)
+ m_editor = new QView3D(formWindow(), 0);
+
+ return m_editor;
+}
+
+QAction *QView3DTool::action() const
+{
+ return m_action;
+}
+
+void QView3DTool::activated()
+{
+ if (m_editor != 0)
+ m_editor->updateForm();
+}
+
+void QView3DTool::deactivated()
+{
+}
+
+bool QView3DTool::handleEvent(QWidget*, QWidget*, QEvent*)
+{
+ return false;
+}
diff --git a/tools/designer/src/plugins/tools/view3d/view3d_tool.h b/tools/designer/src/plugins/tools/view3d/view3d_tool.h
new file mode 100644
index 0000000000..d099019eab
--- /dev/null
+++ b/tools/designer/src/plugins/tools/view3d/view3d_tool.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIEW3D_TOOL_H
+#define VIEW3D_TOOL_H
+
+#include "view3d_global.h"
+#include "view3d.h"
+#include <QtDesigner/QDesignerFormWindowToolInterface>
+
+QT_BEGIN_NAMESPACE
+
+class VIEW3D_EXPORT QView3DTool : public QDesignerFormWindowToolInterface
+{
+ Q_OBJECT
+
+public:
+ explicit QView3DTool(QDesignerFormWindowInterface *formWindow, QObject *parent = 0);
+ virtual QDesignerFormEditorInterface *core() const;
+ virtual QDesignerFormWindowInterface *formWindow() const;
+ virtual QWidget *editor() const;
+
+ virtual QAction *action() const;
+
+ virtual void activated();
+ virtual void deactivated();
+
+ virtual bool handleEvent(QWidget *widget, QWidget *managedWidget, QEvent *event);
+
+private:
+ QDesignerFormWindowInterface *m_formWindow;
+ mutable QPointer<QView3D> m_editor;
+ QAction *m_action;
+};
+
+#endif // VIEW3D_TOOL_H
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp
new file mode 100644
index 0000000000..3f0b0b51fb
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3iconview_extrainfo.h"
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+#include <Qt3Support/Q3IconView>
+
+QT_BEGIN_NAMESPACE
+
+inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties) // ### remove me
+{
+ QHash<QString, DomProperty *> map;
+
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ map.insert(p->attributeName(), p);
+ }
+
+ return map;
+}
+
+Q3IconViewExtraInfo::Q3IconViewExtraInfo(Q3IconView *widget, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_widget(widget), m_core(core)
+{}
+
+QWidget *Q3IconViewExtraInfo::widget() const
+{ return m_widget; }
+
+QDesignerFormEditorInterface *Q3IconViewExtraInfo::core() const
+{ return m_core; }
+
+bool Q3IconViewExtraInfo::saveUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3IconViewExtraInfo::loadUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+
+bool Q3IconViewExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ // ### finish me
+ Q3IconView *iconView = qobject_cast<Q3IconView*>(widget());
+ Q_ASSERT(iconView != 0);
+
+ QList<DomItem*> ui_items;
+
+ Q3IconViewItem *__item = iconView->firstItem();
+ while (__item != 0) {
+ DomItem *ui_item = new DomItem();
+
+ QList<DomProperty*> properties;
+
+ // text property
+ DomProperty *ptext = new DomProperty();
+ DomString *str = new DomString();
+ str->setText(__item->text());
+ ptext->setAttributeName(QLatin1String("text"));
+ ptext->setElementString(str);
+ properties.append(ptext);
+
+ ui_item->setElementProperty(properties);
+ ui_items.append(ui_item);
+
+ if (__item->pixmap() != 0 && core()->iconCache()) {
+ QPixmap pix = *__item->pixmap();
+ QString filePath = core()->iconCache()->pixmapToFilePath(pix);
+ QString qrcPath = core()->iconCache()->pixmapToQrcPath(pix);
+ DomResourcePixmap *ui_pix = new DomResourcePixmap();
+ if (!qrcPath.isEmpty())
+ ui_pix->setAttributeResource(qrcPath);
+ ui_pix->setText(filePath);
+
+ DomProperty *ppix = new DomProperty();
+ ppix->setAttributeName(QLatin1String("pixmap"));
+ ppix->setElementPixmap(ui_pix);
+ properties.append(ppix);
+ }
+
+ __item = __item->nextItem();
+ }
+
+ ui_widget->setElementItem(ui_items);
+
+ return true;
+}
+
+bool Q3IconViewExtraInfo::loadWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q3IconView *iconView = qobject_cast<Q3IconView*>(widget());
+ Q_ASSERT(iconView != 0);
+ Q_UNUSED(iconView);
+
+ if (ui_widget->elementItem().size()) {
+ initializeQ3IconViewItems(ui_widget->elementItem());
+ }
+
+ return true;
+}
+
+void Q3IconViewExtraInfo::initializeQ3IconViewItems(const QList<DomItem *> &items)
+{
+ Q3IconView *iconView = qobject_cast<Q3IconView*>(widget());
+ Q_ASSERT(iconView != 0);
+
+ for (int i=0; i<items.size(); ++i) {
+ DomItem *item = items.at(i);
+
+ Q3IconViewItem *__item = new Q3IconViewItem(iconView);
+
+ QList<DomProperty*> properties = item->elementProperty();
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ if (p->attributeName() == QLatin1String("text"))
+ __item->setText(p->elementString()->text());
+
+ if (p->attributeName() == QLatin1String("pixmap")) {
+ DomResourcePixmap *pix = p->elementPixmap();
+ QPixmap pixmap(core()->iconCache()->resolveQrcPath(pix->text(), pix->attributeResource(), workingDirectory()));
+ __item->setPixmap(pixmap);
+ }
+ }
+ }
+}
+
+
+Q3IconViewExtraInfoFactory::Q3IconViewExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{}
+
+QObject *Q3IconViewExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (Q3IconView *w = qobject_cast<Q3IconView*>(object))
+ return new Q3IconViewExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h
new file mode 100644
index 0000000000..bd07bf616e
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_extrainfo.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3ICONVIEW_EXTRAINFO_H
+#define Q3ICONVIEW_EXTRAINFO_H
+
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionFactory>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class Q3IconView;
+class Q3IconViewItem;
+class DomItem;
+
+class Q3IconViewExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ Q3IconViewExtraInfo(Q3IconView *widget, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+ void initializeQ3IconViewItems(const QList<DomItem *> &items);
+
+private:
+ QPointer<Q3IconView> m_widget;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class Q3IconViewExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ Q3IconViewExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3ICONVIEW_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp
new file mode 100644
index 0000000000..6d85326d32
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3iconview_plugin.h"
+#include "q3iconview_extrainfo.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <Qt3Support/Q3IconView>
+
+QT_BEGIN_NAMESPACE
+
+Q3IconViewPlugin::Q3IconViewPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3IconViewPlugin::name() const
+{ return QLatin1String("Q3IconView"); }
+
+QString Q3IconViewPlugin::group() const
+{ return QLatin1String("Qt 3 Support"); }
+
+QString Q3IconViewPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3IconViewPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3IconViewPlugin::includeFile() const
+{ return QLatin1String("q3iconview.h"); }
+
+QIcon Q3IconViewPlugin::icon() const
+{ return m_icon; }
+
+bool Q3IconViewPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3IconViewPlugin::createWidget(QWidget *parent)
+{ return new Q3IconView(parent); }
+
+bool Q3IconViewPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3IconViewPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ QExtensionManager *mgr = core->extensionManager();
+ Q_ASSERT(mgr != 0);
+
+ mgr->registerExtensions(new Q3IconViewExtraInfoFactory(core, mgr), Q_TYPEID(QDesignerExtraInfoExtension));
+
+ m_initialized = true;
+}
+
+QString Q3IconViewPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3IconViewPlugin::domXml() const
+{ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3IconView\" name=\"iconView\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h
new file mode 100644
index 0000000000..982bbf3489
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3iconview/q3iconview_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3ICONVIEW_PLUGIN_H
+#define Q3ICONVIEW_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3IconViewPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3IconViewPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3ICONVIEW_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp
new file mode 100644
index 0000000000..36a6fc18ad
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3listbox_extrainfo.h"
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+#include <Qt3Support/Q3ListBox>
+
+QT_BEGIN_NAMESPACE
+
+inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties) // ### remove me
+{
+ QHash<QString, DomProperty *> map;
+
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ map.insert(p->attributeName(), p);
+ }
+
+ return map;
+}
+
+Q3ListBoxExtraInfo::Q3ListBoxExtraInfo(Q3ListBox *widget, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_widget(widget), m_core(core)
+{}
+
+QWidget *Q3ListBoxExtraInfo::widget() const
+{ return m_widget; }
+
+QDesignerFormEditorInterface *Q3ListBoxExtraInfo::core() const
+{ return m_core; }
+
+bool Q3ListBoxExtraInfo::saveUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3ListBoxExtraInfo::loadUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+
+bool Q3ListBoxExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q3ListBox *listBox = qobject_cast<Q3ListBox*>(widget());
+ Q_ASSERT(listBox != 0);
+
+ QList<DomItem *> items;
+ const int childCount = listBox->count();
+ for (int i = 0; i < childCount; ++i) {
+ DomItem *item = new DomItem();
+
+ QList<DomProperty*> properties;
+
+ DomString *str = new DomString();
+ str->setText(listBox->text(i));
+
+ DomProperty *ptext = new DomProperty();
+ ptext->setAttributeName(QLatin1String("text"));
+ ptext->setElementString(str);
+
+ properties.append(ptext);
+ item->setElementProperty(properties);
+ items.append(item);
+ }
+ ui_widget->setElementItem(items);
+
+ return true;
+}
+
+bool Q3ListBoxExtraInfo::loadWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q3ListBox *listBox = qobject_cast<Q3ListBox*>(widget());
+ Q_ASSERT(listBox != 0);
+
+ QList<DomItem *> items = ui_widget->elementItem();
+ for (int i = 0; i < items.size(); ++i) {
+ DomItem *item = items.at(i);
+
+ QHash<QString, DomProperty*> properties = propertyMap(item->elementProperty());
+ DomProperty *text = properties.value(QLatin1String("text"));
+ DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
+
+ QString txt = text->elementString()->text();
+
+ if (pixmap != 0) {
+ DomResourcePixmap *pix = pixmap->elementPixmap();
+ QPixmap pixmap(core()->iconCache()->resolveQrcPath(pix->text(), pix->attributeResource(), workingDirectory()));
+ listBox->insertItem(pixmap, txt);
+ } else {
+ listBox->insertItem(txt);
+ }
+ }
+
+ return true;
+}
+
+Q3ListBoxExtraInfoFactory::Q3ListBoxExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{}
+
+QObject *Q3ListBoxExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (Q3ListBox *w = qobject_cast<Q3ListBox*>(object))
+ return new Q3ListBoxExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h
new file mode 100644
index 0000000000..ddfa83f7d2
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_extrainfo.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3LISTBOX_EXTRAINFO_H
+#define Q3LISTBOX_EXTRAINFO_H
+
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionFactory>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class Q3ListBox;
+class Q3ListBoxItem;
+class DomItem;
+
+class Q3ListBoxExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ Q3ListBoxExtraInfo(Q3ListBox *widget, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+private:
+ QPointer<Q3ListBox> m_widget;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class Q3ListBoxExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ Q3ListBoxExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3LISTBOX_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp
new file mode 100644
index 0000000000..ab383f52be
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3listbox_plugin.h"
+#include "q3listbox_extrainfo.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <Qt3Support/Q3ListBox>
+
+QT_BEGIN_NAMESPACE
+
+Q3ListBoxPlugin::Q3ListBoxPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3ListBoxPlugin::name() const
+{ return QLatin1String("Q3ListBox"); }
+
+QString Q3ListBoxPlugin::group() const
+{ return QLatin1String("Qt 3 Support"); }
+
+QString Q3ListBoxPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3ListBoxPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3ListBoxPlugin::includeFile() const
+{ return QLatin1String("q3listbox.h"); }
+
+QIcon Q3ListBoxPlugin::icon() const
+{ return m_icon; }
+
+bool Q3ListBoxPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3ListBoxPlugin::createWidget(QWidget *parent)
+{ return new Q3ListBox(parent); }
+
+bool Q3ListBoxPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3ListBoxPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ QExtensionManager *mgr = core->extensionManager();
+ Q_ASSERT(mgr != 0);
+
+ mgr->registerExtensions(new Q3ListBoxExtraInfoFactory(core, mgr), Q_TYPEID(QDesignerExtraInfoExtension));
+
+ m_initialized = true;
+}
+
+QString Q3ListBoxPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3ListBoxPlugin::domXml() const
+{ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3ListBox\" name=\"listBox\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h
new file mode 100644
index 0000000000..e48f8985e2
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listbox/q3listbox_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3LISTBOX_PLUGIN_H
+#define Q3LISTBOX_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3ListBoxPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3ListBoxPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3LISTBOX_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp b/tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp
new file mode 100644
index 0000000000..8ba507ddf3
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.cpp
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3listview_extrainfo.h"
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+#include <Qt3Support/Q3ListView>
+#include <Qt3Support/Q3Header>
+
+QT_BEGIN_NAMESPACE
+
+inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties) // ### remove me
+{
+ QHash<QString, DomProperty *> map;
+
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ map.insert(p->attributeName(), p);
+ }
+
+ return map;
+}
+
+Q3ListViewExtraInfo::Q3ListViewExtraInfo(Q3ListView *widget, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_widget(widget), m_core(core)
+{}
+
+QWidget *Q3ListViewExtraInfo::widget() const
+{ return m_widget; }
+
+QDesignerFormEditorInterface *Q3ListViewExtraInfo::core() const
+{ return m_core; }
+
+bool Q3ListViewExtraInfo::saveUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3ListViewExtraInfo::loadUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+
+bool Q3ListViewExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ // ### finish me
+ Q3ListView *listView = qobject_cast<Q3ListView*>(widget());
+ Q_ASSERT(listView != 0);
+
+ QList<DomColumn*> columns;
+ Q3Header *header = listView->header();
+ for (int i=0; i<header->count(); ++i) {
+ DomColumn *c = new DomColumn();
+
+ QList<DomProperty*> properties;
+
+ DomString *str = new DomString();
+ str->setText(header->label(i));
+
+ DomProperty *ptext = new DomProperty();
+ ptext->setAttributeName(QLatin1String("text"));
+ ptext->setElementString(str);
+
+ DomProperty *pclickable = new DomProperty();
+ pclickable->setAttributeName(QLatin1String("clickable"));
+ pclickable->setElementBool(header->isClickEnabled(i) ? QLatin1String("true") : QLatin1String("false"));
+
+ DomProperty *presizable = new DomProperty();
+ presizable->setAttributeName(QLatin1String("resizable"));
+ presizable->setElementBool(header->isResizeEnabled(i) ? QLatin1String("true") : QLatin1String("false"));
+
+ properties.append(ptext);
+ properties.append(pclickable);
+ properties.append(presizable);
+
+ c->setElementProperty(properties);
+ columns.append(c);
+ }
+
+ ui_widget->setElementColumn(columns);
+
+ QList<DomItem *> items;
+ Q3ListViewItem *child = listView->firstChild();
+ while (child) {
+ items.append(saveQ3ListViewItem(child));
+ child = child->nextSibling();
+ }
+ ui_widget->setElementItem(items);
+
+
+ return true;
+}
+
+bool Q3ListViewExtraInfo::loadWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q3ListView *listView = qobject_cast<Q3ListView*>(widget());
+ Q_ASSERT(listView != 0);
+
+ Q3Header *header = listView->header();
+
+ QList<DomColumn*> columns = ui_widget->elementColumn();
+ for (int i=0; i<columns.size(); ++i) {
+ DomColumn *column = columns.at(i);
+
+ QHash<QString, DomProperty*> properties = propertyMap(column->elementProperty());
+ DomProperty *text = properties.value(QLatin1String("text"));
+ DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
+ DomProperty *clickable = properties.value(QLatin1String("clickable"));
+ DomProperty *resizable = properties.value(QLatin1String("resizable"));
+
+ QString txt = text->elementString()->text();
+
+ if (pixmap != 0) {
+ DomResourcePixmap *pix = pixmap->elementPixmap();
+ QIcon icon(core()->iconCache()->resolveQrcPath(pix->text(), pix->attributeResource(), workingDirectory()));
+ listView->addColumn(icon, txt);
+ } else {
+ listView->addColumn(txt);
+ }
+
+ if (clickable != 0) {
+ header->setClickEnabled(clickable->elementBool() == QLatin1String("true"), header->count() - 1);
+ }
+
+ if (resizable != 0) {
+ header->setResizeEnabled(resizable->elementBool() == QLatin1String("true"), header->count() - 1);
+ }
+ }
+
+ if (ui_widget->elementItem().size()) {
+ initializeQ3ListViewItems(ui_widget->elementItem());
+ }
+
+ return true;
+}
+
+DomItem *Q3ListViewExtraInfo::saveQ3ListViewItem(Q3ListViewItem *item) const
+{
+ DomItem *pitem = new DomItem();
+ QList<DomProperty *> properties;
+ const int columnCount = static_cast<Q3ListView*>(widget())->columns();
+ for (int i = 0; i < columnCount; ++i) {
+ DomString *str = new DomString();
+ str->setText(item->text(i));
+
+ DomProperty *ptext = new DomProperty();
+ ptext->setAttributeName(QLatin1String("text"));
+ ptext->setElementString(str);
+
+ properties.append(ptext);
+ }
+ pitem->setElementProperty(properties);
+ QList<DomItem *> items;
+ Q3ListViewItem *child = item->firstChild();
+ while (child) {
+ items.append(saveQ3ListViewItem(child));
+ child = child->nextSibling();
+ }
+ pitem->setElementItem(items);
+ return pitem;
+}
+
+void Q3ListViewExtraInfo::initializeQ3ListViewItems(const QList<DomItem *> &items, Q3ListViewItem *parentItem)
+{
+ for (int i=0; i<items.size(); ++i) {
+ DomItem *item = items.at(i);
+
+ Q3ListViewItem *__item = 0;
+ if (parentItem != 0)
+ __item = new Q3ListViewItem(parentItem);
+ else
+ __item = new Q3ListViewItem(static_cast<Q3ListView*>(widget()));
+
+ int textCount = 0, pixCount = 0;
+ QList<DomProperty*> properties = item->elementProperty();
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ if (p->attributeName() == QLatin1String("text"))
+ __item->setText(textCount++, p->elementString()->text());
+
+ if (p->attributeName() == QLatin1String("pixmap")) {
+ DomResourcePixmap *pix = p->elementPixmap();
+ QPixmap pixmap(core()->iconCache()->resolveQrcPath(pix->text(), pix->attributeResource(), workingDirectory()));
+ __item->setPixmap(pixCount++, pixmap);
+ }
+ }
+
+ if (item->elementItem().size()) {
+ __item->setOpen(true);
+ initializeQ3ListViewItems(item->elementItem(), __item);
+ }
+ }
+}
+
+
+Q3ListViewExtraInfoFactory::Q3ListViewExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{}
+
+QObject *Q3ListViewExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (Q3ListView *w = qobject_cast<Q3ListView*>(object))
+ return new Q3ListViewExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h b/tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h
new file mode 100644
index 0000000000..15fb0dc734
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listview/q3listview_extrainfo.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3LISTVIEW_EXTRAINFO_H
+#define Q3LISTVIEW_EXTRAINFO_H
+
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionFactory>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class Q3ListView;
+class Q3ListViewItem;
+class DomItem;
+
+class Q3ListViewExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ Q3ListViewExtraInfo(Q3ListView *widget, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+ DomItem *saveQ3ListViewItem(Q3ListViewItem *item) const;
+ void initializeQ3ListViewItems(const QList<DomItem *> &items, Q3ListViewItem *parentItem = 0);
+
+private:
+ QPointer<Q3ListView> m_widget;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class Q3ListViewExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ Q3ListViewExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3LISTVIEW_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp b/tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp
new file mode 100644
index 0000000000..16e417957d
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3listview_plugin.h"
+#include "q3listview_extrainfo.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <Qt3Support/Q3ListView>
+
+QT_BEGIN_NAMESPACE
+
+Q3ListViewPlugin::Q3ListViewPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3ListViewPlugin::name() const
+{ return QLatin1String("Q3ListView"); }
+
+QString Q3ListViewPlugin::group() const
+{ return QLatin1String("Qt 3 Support"); }
+
+QString Q3ListViewPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3ListViewPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3ListViewPlugin::includeFile() const
+{ return QLatin1String("q3listview.h"); }
+
+QIcon Q3ListViewPlugin::icon() const
+{ return m_icon; }
+
+bool Q3ListViewPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3ListViewPlugin::createWidget(QWidget *parent)
+{ return new Q3ListView(parent); }
+
+bool Q3ListViewPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3ListViewPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ QExtensionManager *mgr = core->extensionManager();
+ Q_ASSERT(mgr != 0);
+
+ mgr->registerExtensions(new Q3ListViewExtraInfoFactory(core, mgr), Q_TYPEID(QDesignerExtraInfoExtension));
+
+ m_initialized = true;
+}
+
+QString Q3ListViewPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3ListViewPlugin::domXml() const
+{ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3ListView\" name=\"listView\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.h b/tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.h
new file mode 100644
index 0000000000..85e35c6367
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3listview/q3listview_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3LISTVIEW_PLUGIN_H
+#define Q3LISTVIEW_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3ListViewPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3ListViewPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3LISTVIEW_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp
new file mode 100644
index 0000000000..f0bebd5d8d
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3mainwindow_container.h"
+
+#include <Qt3Support/Q3MainWindow>
+
+#include <QtCore/qdebug.h>
+#include <QtGui/QToolBar>
+#include <QtGui/QMenuBar>
+#include <QtGui/QStatusBar>
+
+#include <Qt3Support/Q3ToolBar>
+
+QT_BEGIN_NAMESPACE
+
+Q3MainWindowContainer::Q3MainWindowContainer(Q3MainWindow *widget, QObject *parent)
+ : QObject(parent),
+ m_mainWindow(widget)
+{}
+
+int Q3MainWindowContainer::count() const
+{
+ return m_widgets.count();
+}
+
+QWidget *Q3MainWindowContainer::widget(int index) const
+{
+ if (index == -1)
+ return 0;
+
+ return m_widgets.at(index);
+}
+
+int Q3MainWindowContainer::currentIndex() const
+{
+ return m_mainWindow->centralWidget() ? 0 : -1;
+}
+
+void Q3MainWindowContainer::setCurrentIndex(int index)
+{
+ Q_UNUSED(index);
+}
+
+void Q3MainWindowContainer::addWidget(QWidget *widget)
+{
+ if (qobject_cast<QToolBar*>(widget)) {
+ m_widgets.append(widget);
+ } else if (qobject_cast<Q3ToolBar*>(widget)) {
+ m_widgets.append(widget);
+ } else if (qobject_cast<QMenuBar*>(widget)) {
+ (void) m_mainWindow->menuBar();
+ m_widgets.append(widget);
+ } else if (qobject_cast<QStatusBar*>(widget)) {
+ (void) m_mainWindow->statusBar();
+ m_widgets.append(widget);
+ } else {
+ Q_ASSERT(m_mainWindow->centralWidget() == 0);
+ widget->setParent(m_mainWindow);
+ m_mainWindow->setCentralWidget(widget);
+ m_widgets.prepend(widget);
+ }
+}
+
+void Q3MainWindowContainer::insertWidget(int index, QWidget *widget)
+{
+ m_widgets.insert(index, widget);
+}
+
+void Q3MainWindowContainer::remove(int index)
+{
+ m_widgets.removeAt(index);
+}
+
+Q3MainWindowContainerFactory::Q3MainWindowContainerFactory(QExtensionManager *parent)
+ : QExtensionFactory(parent)
+{
+}
+
+QObject *Q3MainWindowContainerFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerContainerExtension))
+ return 0;
+
+ if (Q3MainWindow *w = qobject_cast<Q3MainWindow*>(object))
+ return new Q3MainWindowContainer(w, parent);
+
+ return 0;
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h
new file mode 100644
index 0000000000..ad44265740
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_container.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3MAINWINDOW_CONTAINER_H
+#define Q3MAINWINDOW_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionFactory>
+
+QT_BEGIN_NAMESPACE
+
+class Q3MainWindow;
+
+class Q3MainWindowContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit Q3MainWindowContainer(Q3MainWindow *widget, QObject *parent = 0);
+
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int index);
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ Q3MainWindow *m_mainWindow;
+ QList<QWidget*> m_widgets;
+};
+
+class Q3MainWindowContainerFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ explicit Q3MainWindowContainerFactory(QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3MAINWINDOW_CONTAINER_H
diff --git a/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp
new file mode 100644
index 0000000000..dd21833cce
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3mainwindow_plugin.h"
+#include "q3mainwindow_container.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <Qt3Support/Q3MainWindow>
+
+QT_BEGIN_NAMESPACE
+
+Q3MainWindowPlugin::Q3MainWindowPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3MainWindowPlugin::name() const
+{ return QLatin1String("Q3MainWindow"); }
+
+QString Q3MainWindowPlugin::group() const
+{ return QLatin1String("[invisible]"); }
+
+QString Q3MainWindowPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3MainWindowPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3MainWindowPlugin::includeFile() const
+{ return QLatin1String("q3mainwindow.h"); }
+
+QIcon Q3MainWindowPlugin::icon() const
+{ return m_icon; }
+
+bool Q3MainWindowPlugin::isContainer() const
+{ return true; }
+
+QWidget *Q3MainWindowPlugin::createWidget(QWidget *parent)
+{ return new Q3MainWindow(parent); }
+
+bool Q3MainWindowPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3MainWindowPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ m_initialized = true;
+ QExtensionManager *mgr = core->extensionManager();
+ mgr->registerExtensions(new Q3MainWindowContainerFactory(mgr), Q_TYPEID(QDesignerContainerExtension));
+}
+
+QString Q3MainWindowPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3MainWindowPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3MainWindow\" name=\"mainWindow\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ <widget class=\"QWidget\" name=\"centralWidget\" />\
+ </widget>\
+</ui>");
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h
new file mode 100644
index 0000000000..524506f567
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3MAINWINDOW_PLUGIN_H
+#define Q3MAINWINDOW_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3MainWindowPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3MainWindowPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3MAINWINDOW_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp b/tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp
new file mode 100644
index 0000000000..83534663ac
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3table_extrainfo.h"
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+#include <Qt3Support/Q3Table>
+
+QT_BEGIN_NAMESPACE
+
+inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties) // ### remove me
+{
+ QHash<QString, DomProperty *> map;
+
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ map.insert(p->attributeName(), p);
+ }
+
+ return map;
+}
+
+Q3TableExtraInfo::Q3TableExtraInfo(Q3Table *widget, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_widget(widget), m_core(core)
+{}
+
+QWidget *Q3TableExtraInfo::widget() const
+{ return m_widget; }
+
+QDesignerFormEditorInterface *Q3TableExtraInfo::core() const
+{ return m_core; }
+
+bool Q3TableExtraInfo::saveUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3TableExtraInfo::loadUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+
+bool Q3TableExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q_UNUSED(ui_widget);
+
+ Q3Table *table = qobject_cast<Q3Table*>(widget());
+ Q_ASSERT(table != 0);
+
+ Q3Header *hHeader = table->horizontalHeader();
+
+ QList<DomColumn*> columns;
+ for (int i=0; i<hHeader->count(); ++i) {
+ DomColumn *column = new DomColumn();
+ QList<DomProperty *> properties;
+
+ DomProperty *property = new DomProperty();
+ DomString *string = new DomString();
+ string->setText(hHeader->label(i));
+ property->setElementString(string);
+ property->setAttributeName("text");
+ properties.append(property);
+
+ column->setElementProperty(properties);
+ columns.append(column);
+ }
+ ui_widget->setElementColumn(columns);
+
+ Q3Header *vHeader = table->verticalHeader();
+
+ QList<DomRow*> rows;
+ for (int i=0; i<vHeader->count(); ++i) {
+ DomRow *row = new DomRow();
+ QList<DomProperty *> properties;
+
+ DomProperty *property = new DomProperty();
+ DomString *string = new DomString();
+ string->setText(vHeader->label(i));
+ property->setElementString(string);
+ property->setAttributeName("text");
+ properties.append(property);
+
+ row->setElementProperty(properties);
+ rows.append(row);
+ }
+ ui_widget->setElementRow(rows);
+
+ return true;
+}
+
+bool Q3TableExtraInfo::loadWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q_UNUSED(ui_widget);
+
+ Q3Table *table = qobject_cast<Q3Table*>(widget());
+ Q_ASSERT(table != 0);
+
+ Q3Header *hHeader = table->horizontalHeader();
+
+ QList<DomColumn*> columns = ui_widget->elementColumn();
+ for (int i=0; i<columns.size(); ++i) {
+ DomColumn *column = columns.at(i);
+
+ QHash<QString, DomProperty*> properties = propertyMap(column->elementProperty());
+ DomProperty *text = properties.value(QLatin1String("text"));
+ DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
+
+ QString txt = text->elementString()->text();
+
+ if (pixmap != 0) {
+ DomResourcePixmap *pix = pixmap->elementPixmap();
+ QIcon icon(core()->iconCache()->resolveQrcPath(pix->text(), pix->attributeResource(), workingDirectory()));
+ hHeader->setLabel(i, icon, txt);
+ } else {
+ hHeader->setLabel(i, txt);
+ }
+ }
+
+ Q3Header *vHeader = table->verticalHeader();
+
+ QList<DomRow*> rows = ui_widget->elementRow();
+ for (int i=0; i<rows.size(); ++i) {
+ DomRow *row = rows.at(i);
+
+ QHash<QString, DomProperty*> properties = propertyMap(row->elementProperty());
+ DomProperty *text = properties.value(QLatin1String("text"));
+ DomProperty *pixmap = properties.value(QLatin1String("pixmap"));
+
+ QString txt = text->elementString()->text();
+
+ if (pixmap != 0) {
+ DomResourcePixmap *pix = pixmap->elementPixmap();
+ QIcon icon(core()->iconCache()->resolveQrcPath(pix->text(), pix->attributeResource(), workingDirectory()));
+ vHeader->setLabel(i, icon, txt);
+ } else {
+ vHeader->setLabel(i, txt);
+ }
+ }
+
+ return true;
+}
+
+Q3TableExtraInfoFactory::Q3TableExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{}
+
+QObject *Q3TableExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (Q3Table *w = qobject_cast<Q3Table*>(object))
+ return new Q3TableExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.h b/tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.h
new file mode 100644
index 0000000000..6dc7a30051
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3table/q3table_extrainfo.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3TABLE_EXTRAINFO_H
+#define Q3TABLE_EXTRAINFO_H
+
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionFactory>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class Q3Table;
+class Q3TableItem;
+class DomItem;
+
+class Q3TableExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ Q3TableExtraInfo(Q3Table *widget, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+private:
+ QPointer<Q3Table> m_widget;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class Q3TableExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ Q3TableExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3TABLE_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/widgets/q3table/q3table_plugin.cpp b/tools/designer/src/plugins/widgets/q3table/q3table_plugin.cpp
new file mode 100644
index 0000000000..142a15b216
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3table/q3table_plugin.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3table_plugin.h"
+#include "q3table_extrainfo.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <Qt3Support/Q3Table>
+
+QT_BEGIN_NAMESPACE
+
+Q3TablePlugin::Q3TablePlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3TablePlugin::name() const
+{ return QLatin1String("Q3Table"); }
+
+QString Q3TablePlugin::group() const
+{ return QLatin1String("Qt 3 Support"); }
+
+QString Q3TablePlugin::toolTip() const
+{ return QString(); }
+
+QString Q3TablePlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3TablePlugin::includeFile() const
+{ return QLatin1String("q3table.h"); }
+
+QIcon Q3TablePlugin::icon() const
+{ return m_icon; }
+
+bool Q3TablePlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3TablePlugin::createWidget(QWidget *parent)
+{ return new Q3Table(parent); }
+
+bool Q3TablePlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3TablePlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ QExtensionManager *mgr = core->extensionManager();
+ Q_ASSERT(mgr != 0);
+
+ mgr->registerExtensions(new Q3TableExtraInfoFactory(core, mgr), Q_TYPEID(QDesignerExtraInfoExtension));
+
+ m_initialized = true;
+}
+
+QString Q3TablePlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3TablePlugin::domXml() const
+{ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3Table\" name=\"table\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3table/q3table_plugin.h b/tools/designer/src/plugins/widgets/q3table/q3table_plugin.h
new file mode 100644
index 0000000000..0a23e97aa9
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3table/q3table_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3TABLE_PLUGIN_H
+#define Q3TABLE_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3TablePlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3TablePlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3TABLE_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp
new file mode 100644
index 0000000000..f60c395281
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3textedit_extrainfo.h"
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+#include <Qt3Support/Q3TextEdit>
+
+QT_BEGIN_NAMESPACE
+
+inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties) // ### remove me
+{
+ QHash<QString, DomProperty *> map;
+
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ map.insert(p->attributeName(), p);
+ }
+
+ return map;
+}
+
+Q3TextEditExtraInfo::Q3TextEditExtraInfo(Q3TextEdit *widget, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_widget(widget), m_core(core)
+{}
+
+QWidget *Q3TextEditExtraInfo::widget() const
+{ return m_widget; }
+
+QDesignerFormEditorInterface *Q3TextEditExtraInfo::core() const
+{ return m_core; }
+
+bool Q3TextEditExtraInfo::saveUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3TextEditExtraInfo::loadUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+
+bool Q3TextEditExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q_UNUSED(ui_widget);
+
+ Q3TextEdit *textEdit = qobject_cast<Q3TextEdit*>(widget());
+ Q_ASSERT(textEdit != 0);
+ Q_UNUSED(textEdit);
+ return true;
+}
+
+bool Q3TextEditExtraInfo::loadWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q_UNUSED(ui_widget);
+
+ Q3TextEdit *textEdit = qobject_cast<Q3TextEdit*>(widget());
+ Q_ASSERT(textEdit != 0);
+ Q_UNUSED(textEdit);
+ return true;
+}
+
+Q3TextEditExtraInfoFactory::Q3TextEditExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{}
+
+QObject *Q3TextEditExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (Q3TextEdit *w = qobject_cast<Q3TextEdit*>(object))
+ return new Q3TextEditExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h
new file mode 100644
index 0000000000..3ccc211802
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_extrainfo.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3TEXTEDIT_EXTRAINFO_H
+#define Q3TEXTEDIT_EXTRAINFO_H
+
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionFactory>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class Q3TextEdit;
+class Q3TextEditItem;
+class DomItem;
+
+class Q3TextEditExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ Q3TextEditExtraInfo(Q3TextEdit *widget, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+private:
+ QPointer<Q3TextEdit> m_widget;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class Q3TextEditExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ Q3TextEditExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3TEXTEDIT_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp
new file mode 100644
index 0000000000..804c4cd4c2
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3textedit_plugin.h"
+#include "q3textedit_extrainfo.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <Qt3Support/Q3TextEdit>
+
+QT_BEGIN_NAMESPACE
+
+Q3TextEditPlugin::Q3TextEditPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3TextEditPlugin::name() const
+{ return QLatin1String("Q3TextEdit"); }
+
+QString Q3TextEditPlugin::group() const
+{ return QLatin1String("Qt 3 Support"); }
+
+QString Q3TextEditPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3TextEditPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3TextEditPlugin::includeFile() const
+{ return QLatin1String("q3textedit.h"); }
+
+QIcon Q3TextEditPlugin::icon() const
+{ return m_icon; }
+
+
+bool Q3TextEditPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3TextEditPlugin::createWidget(QWidget *parent)
+{ return new Q3TextEdit(parent); }
+
+bool Q3TextEditPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3TextEditPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ QExtensionManager *mgr = core->extensionManager();
+ Q_ASSERT(mgr != 0);
+
+ mgr->registerExtensions(new Q3TextEditExtraInfoFactory(core, mgr), Q_TYPEID(QDesignerExtraInfoExtension));
+
+ m_initialized = true;
+}
+
+QString Q3TextEditPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3TextEditPlugin::domXml() const
+{ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3TextEdit\" name=\"textEdit\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h
new file mode 100644
index 0000000000..7ab94c7d71
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3textedit/q3textedit_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3TEXTEDIT_PLUGIN_H
+#define Q3TEXTEDIT_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3TextEditPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3TextEditPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3TEXTEDIT_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp
new file mode 100644
index 0000000000..0ad538c7ac
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3toolbar_extrainfo.h"
+
+#include <QtDesigner/QDesignerIconCacheInterface>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+#include <Qt3Support/Q3ToolBar>
+
+QT_BEGIN_NAMESPACE
+
+inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties) // ### remove me
+{
+ QHash<QString, DomProperty *> map;
+
+ for (int i=0; i<properties.size(); ++i) {
+ DomProperty *p = properties.at(i);
+ map.insert(p->attributeName(), p);
+ }
+
+ return map;
+}
+
+Q3ToolBarExtraInfo::Q3ToolBarExtraInfo(Q3ToolBar *widget, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_widget(widget), m_core(core)
+{}
+
+QWidget *Q3ToolBarExtraInfo::widget() const
+{ return m_widget; }
+
+QDesignerFormEditorInterface *Q3ToolBarExtraInfo::core() const
+{ return m_core; }
+
+bool Q3ToolBarExtraInfo::saveUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3ToolBarExtraInfo::loadUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+
+bool Q3ToolBarExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q_UNUSED(ui_widget);
+ return true;
+}
+
+bool Q3ToolBarExtraInfo::loadWidgetExtraInfo(DomWidget *ui_widget)
+{
+ Q_UNUSED(ui_widget);
+ return true;
+}
+
+Q3ToolBarExtraInfoFactory::Q3ToolBarExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{}
+
+QObject *Q3ToolBarExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (Q3ToolBar *w = qobject_cast<Q3ToolBar*>(object))
+ return new Q3ToolBarExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h
new file mode 100644
index 0000000000..c2e3c54aeb
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3TOOLBAR_EXTRAINFO_H
+#define Q3TOOLBAR_EXTRAINFO_H
+
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionFactory>
+
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+class Q3ToolBar;
+class DomItem;
+
+class Q3ToolBarExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ Q3ToolBarExtraInfo(Q3ToolBar *widget, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+private:
+ QPointer<Q3ToolBar> m_widget;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class Q3ToolBarExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ Q3ToolBarExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3TOOLBAR_EXTRAINFO_H
diff --git a/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp
new file mode 100644
index 0000000000..1f5debe91b
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3toolbar_plugin.h"
+#include "q3toolbar_extrainfo.h"
+
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <QtCore/QDebug>
+
+#include <Qt3Support/Q3MainWindow>
+#include <Qt3Support/Q3ToolBar>
+#include <QtGui/QMainWindow>
+#include <QtGui/QToolBar>
+
+QT_BEGIN_NAMESPACE
+
+Q3ToolBarPlugin::Q3ToolBarPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3ToolBarPlugin::name() const
+{ return QLatin1String("Q3ToolBar"); }
+
+QString Q3ToolBarPlugin::group() const
+{ return QLatin1String("Qt 3 Support"); }
+
+QString Q3ToolBarPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3ToolBarPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3ToolBarPlugin::includeFile() const
+{ return QLatin1String("q3listview.h"); }
+
+QIcon Q3ToolBarPlugin::icon() const
+{ return m_icon; }
+
+bool Q3ToolBarPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3ToolBarPlugin::createWidget(QWidget *parent)
+{
+ if (!parent)
+ return new Q3ToolBar;
+ // If there is a parent, it must be a Q3MainWindow
+ if (Q3MainWindow *mw3 = qobject_cast<Q3MainWindow*>(parent))
+ return new Q3ToolBar(mw3);
+ // Somebody hacked up a form?
+ if (QMainWindow *mw4 = qobject_cast<QMainWindow*>(parent)) {
+ qDebug() << "*** WARNING QMainWindow was passed as a parent widget of Q3ToolBar. Creating a QToolBar...";
+ return new QToolBar(mw4);
+ }
+ // Can't be helped
+ const QString msg = QString::fromUtf8("*** WARNING Parent widget of Q3ToolBar must be a Q3MainWindow (%1)!").arg(QLatin1String(parent->metaObject()->className()));
+ qDebug() << msg;
+ return 0;
+}
+
+bool Q3ToolBarPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3ToolBarPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ QExtensionManager *mgr = core->extensionManager();
+ Q_ASSERT(mgr != 0);
+
+ mgr->registerExtensions(new Q3ToolBarExtraInfoFactory(core, mgr), Q_TYPEID(QDesignerExtraInfoExtension));
+
+ m_initialized = true;
+}
+
+QString Q3ToolBarPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3ToolBarPlugin::domXml() const
+{ return QString(); }
+
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h
new file mode 100644
index 0000000000..7cb85bb814
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3toolbar/q3toolbar_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3TOOLBAR_PLUGIN_H
+#define Q3TOOLBAR_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3ToolBarPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3ToolBarPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3TOOLBAR_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp b/tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp
new file mode 100644
index 0000000000..faf3da6956
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.cpp
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3widget_plugins.h"
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QIcon>
+#include <QtGui/QLayout>
+#include <Qt3Support/Q3ButtonGroup>
+#include <Qt3Support/Q3ComboBox>
+#include <Qt3Support/Q3DateEdit>
+#include <Qt3Support/Q3DateTimeEdit>
+#include <Qt3Support/Q3Frame>
+#include <Qt3Support/Q3GroupBox>
+#include <Qt3Support/Q3ProgressBar>
+#include <Qt3Support/Q3TextBrowser>
+#include <Qt3Support/Q3TimeEdit>
+
+static const char *groupNameC = "Qt 3 Support";
+
+QT_BEGIN_NAMESPACE
+
+Q3ButtonGroupPlugin::Q3ButtonGroupPlugin(const QIcon &icon, QObject *parent) :
+ QObject(parent),
+ m_initialized(false),
+ m_icon(icon)
+{
+}
+
+Q3ButtonGroupPlugin::~Q3ButtonGroupPlugin()
+{
+}
+
+QString Q3ButtonGroupPlugin::name() const
+{
+ return QLatin1String("Q3ButtonGroup");
+}
+
+QString Q3ButtonGroupPlugin::group() const
+{
+ return QLatin1String(groupNameC);
+}
+
+QString Q3ButtonGroupPlugin::toolTip() const
+{
+ return QString();
+}
+
+QString Q3ButtonGroupPlugin::whatsThis() const
+{
+ return QString();
+}
+
+QString Q3ButtonGroupPlugin::includeFile() const
+{
+ return QLatin1String("Qt3Support/Q3ButtonGroup");
+}
+
+QIcon Q3ButtonGroupPlugin::icon() const
+{
+ return m_icon;
+}
+
+bool Q3ButtonGroupPlugin::isContainer() const
+{
+ return true;
+}
+
+QWidget *Q3ButtonGroupPlugin::createWidget(QWidget *parent)
+{
+ Q3ButtonGroup *g = new Q3ButtonGroup(parent);
+ g->setColumnLayout(0, Qt::Vertical);
+ g->setInsideMargin(0);
+ g->layout()->setSpacing(-1);
+ return g;
+}
+
+bool Q3ButtonGroupPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void Q3ButtonGroupPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3ButtonGroupPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3ButtonGroup\" name=\"buttonGroup\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+Q3ComboBoxPlugin::Q3ComboBoxPlugin(const QIcon &icon, QObject *parent) :
+ QObject(parent),
+ m_initialized(false),
+ m_icon(icon)
+{
+}
+
+Q3ComboBoxPlugin::~Q3ComboBoxPlugin()
+{
+}
+
+QString Q3ComboBoxPlugin::name() const
+{
+ return QLatin1String("Q3ComboBox");
+}
+
+QString Q3ComboBoxPlugin::group() const
+{
+ return QLatin1String(groupNameC);
+}
+
+QString Q3ComboBoxPlugin::toolTip() const
+{
+ return QString();
+}
+
+QString Q3ComboBoxPlugin::whatsThis() const
+{
+ return QString();
+}
+
+QString Q3ComboBoxPlugin::includeFile() const
+{
+ return QLatin1String("Qt3Support/Q3ComboBox");
+}
+
+QIcon Q3ComboBoxPlugin::icon() const
+{
+ return m_icon;
+}
+
+bool Q3ComboBoxPlugin::isContainer() const
+{
+ return false;
+}
+
+QWidget *Q3ComboBoxPlugin::createWidget(QWidget *parent)
+{
+ return new Q3ComboBox(parent);
+}
+
+bool Q3ComboBoxPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+QString Q3ComboBoxPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+<widget class=\"Q3ComboBox\" name=\"comboBox\"/>\
+</ui>");
+}
+
+void Q3ComboBoxPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+Q3DateEditPlugin::Q3DateEditPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3DateEditPlugin::name() const
+{ return QLatin1String("Q3DateEdit"); }
+
+QString Q3DateEditPlugin::group() const
+{ return QLatin1String(groupNameC); }
+
+QString Q3DateEditPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3DateEditPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3DateEditPlugin::includeFile() const
+{ return QLatin1String("Qt3Support/Q3DateEdit"); }
+
+QIcon Q3DateEditPlugin::icon() const
+{ return m_icon; }
+
+bool Q3DateEditPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3DateEditPlugin::createWidget(QWidget *parent)
+{ return new Q3DateEdit(parent); }
+
+bool Q3DateEditPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3DateEditPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3DateEditPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3DateEdit\" name=\"dateEdit\"/>\
+</ui>");
+}
+
+Q3DateTimeEditPlugin::Q3DateTimeEditPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3DateTimeEditPlugin::name() const
+{ return QLatin1String("Q3DateTimeEdit"); }
+
+QString Q3DateTimeEditPlugin::group() const
+{ return QLatin1String(groupNameC); }
+
+QString Q3DateTimeEditPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3DateTimeEditPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3DateTimeEditPlugin::includeFile() const
+{ return QLatin1String("Qt3Support/Q3DateTimeEdit"); }
+
+QIcon Q3DateTimeEditPlugin::icon() const
+{ return m_icon; }
+
+bool Q3DateTimeEditPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3DateTimeEditPlugin::createWidget(QWidget *parent)
+{ return new Q3DateTimeEdit(parent); }
+
+bool Q3DateTimeEditPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3DateTimeEditPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3DateTimeEditPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3DateTimeEdit\" name=\"dateTimeEdit\"/>\
+</ui>");
+}
+
+Q3FramePlugin::Q3FramePlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent),
+ m_initialized(false),
+ m_icon(icon)
+{
+}
+
+Q3FramePlugin::~Q3FramePlugin()
+{
+}
+
+QString Q3FramePlugin::name() const
+{
+ return QLatin1String("Q3Frame");
+}
+
+QString Q3FramePlugin::group() const
+{
+ return QLatin1String(groupNameC);
+}
+
+QString Q3FramePlugin::toolTip() const
+{
+ return QString();
+}
+
+QString Q3FramePlugin::whatsThis() const
+{
+ return QString();
+}
+
+QString Q3FramePlugin::includeFile() const
+{
+ return QLatin1String("Qt3Support/Q3Frame");
+}
+
+QIcon Q3FramePlugin::icon() const
+{
+ return m_icon;
+}
+
+bool Q3FramePlugin::isContainer() const
+{
+ return true;
+}
+
+QWidget *Q3FramePlugin::createWidget(QWidget *parent)
+{
+ return new Q3Frame(parent);
+}
+
+bool Q3FramePlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void Q3FramePlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3FramePlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3Frame\" name=\"frame\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+Q3GroupBoxPlugin::Q3GroupBoxPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent),
+ m_initialized(false),
+ m_icon(icon)
+{
+}
+
+Q3GroupBoxPlugin::~Q3GroupBoxPlugin()
+{
+}
+
+QString Q3GroupBoxPlugin::name() const
+{
+ return QLatin1String("Q3GroupBox");
+}
+
+QString Q3GroupBoxPlugin::group() const
+{
+ return QLatin1String(groupNameC);
+}
+
+QString Q3GroupBoxPlugin::toolTip() const
+{
+ return QString();
+}
+
+QString Q3GroupBoxPlugin::whatsThis() const
+{
+ return QString();
+}
+
+QString Q3GroupBoxPlugin::includeFile() const
+{
+ return QLatin1String("Qt3Support/Q3GroupBox");
+}
+
+QIcon Q3GroupBoxPlugin::icon() const
+{
+ return m_icon;
+}
+
+bool Q3GroupBoxPlugin::isContainer() const
+{
+ return true;
+}
+
+QWidget *Q3GroupBoxPlugin::createWidget(QWidget *parent)
+{
+ Q3GroupBox *g = new Q3GroupBox(parent);
+ g->setColumnLayout(0, Qt::Vertical);
+ g->setInsideMargin(0);
+ g->layout()->setSpacing(-1);
+ return g;
+}
+
+bool Q3GroupBoxPlugin::isInitialized() const
+{
+ return m_initialized;
+}
+
+void Q3GroupBoxPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3GroupBoxPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3GroupBox\" name=\"groupBox\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ </widget>\
+</ui>");
+}
+
+Q3ProgressBarPlugin::Q3ProgressBarPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3ProgressBarPlugin::name() const
+{ return QLatin1String("Q3ProgressBar"); }
+
+QString Q3ProgressBarPlugin::group() const
+{ return QLatin1String(groupNameC); }
+
+QString Q3ProgressBarPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3ProgressBarPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3ProgressBarPlugin::includeFile() const
+{ return QLatin1String("Qt3Support/Q3ProgressBar"); }
+
+QIcon Q3ProgressBarPlugin::icon() const
+{ return m_icon; }
+
+bool Q3ProgressBarPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3ProgressBarPlugin::createWidget(QWidget *parent)
+{ return new Q3ProgressBar(parent); }
+
+bool Q3ProgressBarPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3ProgressBarPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3ProgressBarPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3ProgressBar\" name=\"progressBar\"/>\
+</ui>");
+}
+
+Q3TextBrowserPlugin::Q3TextBrowserPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3TextBrowserPlugin::name() const
+{ return QLatin1String("Q3TextBrowser"); }
+
+QString Q3TextBrowserPlugin::group() const
+{ return QLatin1String(groupNameC); }
+
+QString Q3TextBrowserPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3TextBrowserPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3TextBrowserPlugin::includeFile() const
+{ return QLatin1String("Qt3Support/Q3TextBrowser"); }
+
+QIcon Q3TextBrowserPlugin::icon() const
+{ return m_icon; }
+
+bool Q3TextBrowserPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3TextBrowserPlugin::createWidget(QWidget *parent)
+{ return new Q3TextBrowser(parent); }
+
+bool Q3TextBrowserPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3TextBrowserPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3TextBrowserPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3TextBrowser\" name=\"textBrowser\"/>\
+</ui>");
+}
+
+Q3TimeEditPlugin::Q3TimeEditPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3TimeEditPlugin::name() const
+{ return QLatin1String("Q3TimeEdit"); }
+
+QString Q3TimeEditPlugin::group() const
+{ return QLatin1String(groupNameC); }
+
+QString Q3TimeEditPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3TimeEditPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3TimeEditPlugin::includeFile() const
+{ return QLatin1String("Qt3Support/Q3TimeEdit"); }
+
+QIcon Q3TimeEditPlugin::icon() const
+{ return m_icon; }
+
+bool Q3TimeEditPlugin::isContainer() const
+{ return false; }
+
+QWidget *Q3TimeEditPlugin::createWidget(QWidget *parent)
+{ return new Q3TimeEdit(parent); }
+
+bool Q3TimeEditPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3TimeEditPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+ m_initialized = true;
+}
+
+QString Q3TimeEditPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3TimeEdit\" name=\"timeEdit\"/>\
+</ui>");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h b/tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h
new file mode 100644
index 0000000000..76a14c50a3
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgets/q3widget_plugins.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3WIDGET_PLUGINS_H
+#define Q3WIDGET_PLUGINS_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3ButtonGroupPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3ButtonGroupPlugin(const QIcon &icon, QObject *parent = 0);
+ virtual ~Q3ButtonGroupPlugin();
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+
+ virtual bool isContainer() const;
+
+ virtual QWidget *createWidget(QWidget *parent);
+
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3ComboBoxPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3ComboBoxPlugin(const QIcon &icon, QObject *parent = 0);
+ virtual ~Q3ComboBoxPlugin();
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+
+ virtual bool isContainer() const;
+
+ virtual QWidget *createWidget(QWidget *parent);
+
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3DateEditPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3DateEditPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3DateTimeEditPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3DateTimeEditPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3FramePlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3FramePlugin(const QIcon &icon, QObject *parent = 0);
+ virtual ~Q3FramePlugin();
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+
+ virtual bool isContainer() const;
+
+ virtual QWidget *createWidget(QWidget *parent);
+
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3GroupBoxPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3GroupBoxPlugin(const QIcon &icon, QObject *parent = 0);
+ virtual ~Q3GroupBoxPlugin();
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+
+ virtual bool isContainer() const;
+
+ virtual QWidget *createWidget(QWidget *parent);
+
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3ProgressBarPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3ProgressBarPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3TextBrowserPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3TextBrowserPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+class Q3TimeEditPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3TimeEditPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3WIDGET_PLUGINS_H
diff --git a/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp
new file mode 100644
index 0000000000..9482d4bcce
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3widgetstack_container.h"
+#include "qdesigner_q3widgetstack_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+Q3WidgetStackContainer::Q3WidgetStackContainer(QDesignerQ3WidgetStack *widget, QObject *parent)
+ : QObject(parent),
+ m_widget(widget)
+{}
+
+int Q3WidgetStackContainer::count() const
+{ return m_pages.count(); }
+
+QWidget *Q3WidgetStackContainer::widget(int index) const
+{
+ if (index == -1)
+ return 0;
+
+ return m_pages.at(index);
+}
+
+int Q3WidgetStackContainer::currentIndex() const
+{ return m_pages.indexOf(m_widget->visibleWidget()); }
+
+void Q3WidgetStackContainer::setCurrentIndex(int index)
+{ m_widget->raiseWidget(m_pages.at(index)); }
+
+void Q3WidgetStackContainer::addWidget(QWidget *widget)
+{
+ m_pages.append(widget);
+ m_widget->addWidget(widget);
+}
+
+void Q3WidgetStackContainer::insertWidget(int index, QWidget *widget)
+{
+ m_pages.insert(index, widget);
+ m_widget->addWidget(widget);
+ m_widget->setCurrentIndex(index);
+}
+
+void Q3WidgetStackContainer::remove(int index)
+{
+ int current = currentIndex();
+ m_widget->removeWidget(m_pages.at(index));
+ m_pages.removeAt(index);
+ if (index == current) {
+ if (count() > 0)
+ m_widget->setCurrentIndex((index == count()) ? index-1 : index);
+ } else if (index < current) {
+ if (current > 0)
+ m_widget->setCurrentIndex(current-1);
+ }
+}
+
+Q3WidgetStackContainerFactory::Q3WidgetStackContainerFactory(QExtensionManager *parent)
+ : QExtensionFactory(parent)
+{
+}
+
+QObject *Q3WidgetStackContainerFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerContainerExtension))
+ return 0;
+
+ if (QDesignerQ3WidgetStack *w = qobject_cast<QDesignerQ3WidgetStack*>(object))
+ return new Q3WidgetStackContainer(w, parent);
+
+ return 0;
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h
new file mode 100644
index 0000000000..3d6045de26
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_container.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3WIDGETSTACK_CONTAINER_H
+#define Q3WIDGETSTACK_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionFactory>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerQ3WidgetStack;
+
+class Q3WidgetStackContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit Q3WidgetStackContainer(QDesignerQ3WidgetStack *widget, QObject *parent = 0);
+
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int index);
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ QDesignerQ3WidgetStack *m_widget;
+ QList<QWidget*> m_pages;
+};
+
+class Q3WidgetStackContainerFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ explicit Q3WidgetStackContainerFactory(QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3WIDGETSTACK_CONTAINER_H
diff --git a/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp
new file mode 100644
index 0000000000..61907a6077
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3widgetstack_plugin.h"
+#include "q3widgetstack_container.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include "qdesigner_q3widgetstack_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q3WidgetStackPlugin::Q3WidgetStackPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3WidgetStackPlugin::name() const
+{ return QLatin1String("Q3WidgetStack"); }
+
+QString Q3WidgetStackPlugin::group() const
+{ return QLatin1String("Qt 3 Support"); }
+
+QString Q3WidgetStackPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3WidgetStackPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3WidgetStackPlugin::includeFile() const
+{ return QLatin1String("q3widgetstack.h"); }
+
+QIcon Q3WidgetStackPlugin::icon() const
+{ return m_icon; }
+
+bool Q3WidgetStackPlugin::isContainer() const
+{ return true; }
+
+QWidget *Q3WidgetStackPlugin::createWidget(QWidget *parent)
+{ return new QDesignerQ3WidgetStack(parent); }
+
+bool Q3WidgetStackPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3WidgetStackPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ m_initialized = true;
+ QExtensionManager *mgr = core->extensionManager();
+ mgr->registerExtensions(new Q3WidgetStackContainerFactory(mgr), Q_TYPEID(QDesignerContainerExtension));
+}
+
+QString Q3WidgetStackPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3WidgetStackPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3WidgetStack\" name=\"widgetStack\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ <widget class=\"QWidget\" name=\"page\"/>\
+ <widget class=\"QWidget\" name=\"page_2\"/>\
+ </widget>\
+</ui>");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h
new file mode 100644
index 0000000000..bbe85ff5fe
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3WIDGETSTACK_PLUGIN_H
+#define Q3WIDGETSTACK_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3WidgetStackPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3WidgetStackPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3WIDGETSTACK_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp b/tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp
new file mode 100644
index 0000000000..adb3d56bcd
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesigner_q3widgetstack_p.h"
+#include "../../../lib/shared/qdesigner_propertycommand_p.h"
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/QEvent>
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ QToolButton *createToolButton(QWidget *parent, Qt::ArrowType at, const QString &name) {
+ QToolButton *rc = new QToolButton();
+ rc->setAttribute(Qt::WA_NoChildEventsForParent, true);
+ rc->setParent(parent);
+ rc->setObjectName(name);
+ rc->setArrowType(at);
+ rc->setAutoRaise(true);
+ rc->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ rc->setFixedSize(QSize(15, 15));
+ return rc;
+ }
+}
+
+QDesignerQ3WidgetStack::QDesignerQ3WidgetStack(QWidget *parent) :
+ Q3WidgetStack(parent),
+ m_prev(createToolButton(this, Qt::LeftArrow, QLatin1String("__qt__passive_prev"))),
+ m_next(createToolButton(this, Qt::RightArrow, QLatin1String("__qt__passive_next")))
+{
+ connect(m_prev, SIGNAL(clicked()), this, SLOT(prevPage()));
+ connect(m_next, SIGNAL(clicked()), this, SLOT(nextPage()));
+ updateButtons();
+
+ connect(this, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentChanged(int)));
+}
+
+QDesignerFormWindowInterface *QDesignerQ3WidgetStack::formWindow()
+{
+ return QDesignerFormWindowInterface::findFormWindow(this);
+}
+
+QDesignerContainerExtension *QDesignerQ3WidgetStack::container()
+{
+ if (formWindow()) {
+ QDesignerFormEditorInterface *core = formWindow()->core();
+ return qt_extension<QDesignerContainerExtension*>(core->extensionManager(), this);
+ }
+ return 0;
+}
+
+int QDesignerQ3WidgetStack::count()
+{
+ return container() ? container()->count() : 0;
+}
+
+int QDesignerQ3WidgetStack::currentIndex()
+{
+ return container() ? container()->currentIndex() : -1;
+}
+
+void QDesignerQ3WidgetStack::setCurrentIndex(int index)
+{
+ if (container() && (index >= 0) && (index < count())) {
+ container()->setCurrentIndex(index);
+ emit currentChanged(index);
+ }
+}
+
+QWidget *QDesignerQ3WidgetStack::widget(int index)
+{
+ return container() ? container()->widget(index) : 0;
+}
+
+void QDesignerQ3WidgetStack::updateButtons()
+{
+ if (m_prev) {
+ m_prev->move(width() - 31, 1);
+ m_prev->show();
+ m_prev->raise();
+ }
+
+ if (m_next) {
+ m_next->move(width() - 16, 1);
+ m_next->show();
+ m_next->raise();
+ }
+}
+
+void QDesignerQ3WidgetStack::gotoPage(int page) {
+ // Are we on a form or in a preview?
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ qdesigner_internal::SetPropertyCommand *cmd = new qdesigner_internal::SetPropertyCommand(fw);
+ cmd->init(this, QLatin1String("currentIndex"), page);
+ fw->commandHistory()->push(cmd);
+ fw->emitSelectionChanged(); // Magically prevent an endless loop triggered by auto-repeat.
+ } else {
+ setCurrentIndex(page);
+ }
+ updateButtons();
+}
+
+
+void QDesignerQ3WidgetStack::prevPage()
+{
+ if (count() > 1) {
+ int newIndex = currentIndex() - 1;
+ if (newIndex < 0)
+ newIndex = count() - 1;
+ gotoPage(newIndex);
+ }
+}
+
+void QDesignerQ3WidgetStack::nextPage()
+{
+ if (count() > 1)
+ gotoPage((currentIndex() + 1) % count());
+}
+
+QString QDesignerQ3WidgetStack::currentPageName()
+{
+ if (currentIndex() == -1)
+ return QString();
+
+ return widget(currentIndex())->objectName();
+}
+
+void QDesignerQ3WidgetStack::setCurrentPageName(const QString &pageName)
+{
+ if (currentIndex() == -1)
+ return;
+
+ if (QWidget *w = widget(currentIndex()))
+ w->setObjectName(pageName);
+}
+
+bool QDesignerQ3WidgetStack::event(QEvent *e)
+{
+ if (e->type() == QEvent::LayoutRequest) {
+ updateButtons();
+ }
+
+ return Q3WidgetStack::event(e);
+}
+
+void QDesignerQ3WidgetStack::childEvent(QChildEvent *e)
+{
+ Q3WidgetStack::childEvent(e);
+ updateButtons();
+}
+
+void QDesignerQ3WidgetStack::resizeEvent(QResizeEvent *e)
+{
+ Q3WidgetStack::resizeEvent(e);
+ updateButtons();
+}
+
+void QDesignerQ3WidgetStack::showEvent(QShowEvent *e)
+{
+ Q3WidgetStack::showEvent(e);
+ updateButtons();
+}
+
+void QDesignerQ3WidgetStack::slotCurrentChanged(int index)
+{
+ if (widget(index)) {
+ if (QDesignerFormWindowInterface *fw = formWindow()) {
+ fw->clearSelection();
+ fw->selectWidget(this, true);
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h b/tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h
new file mode 100644
index 0000000000..5c35514d43
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QDESIGNER_Q3WIDGETSTACK_P_H
+#define QDESIGNER_Q3WIDGETSTACK_P_H
+
+#include <Qt3Support/Q3WidgetStack>
+
+QT_BEGIN_NAMESPACE
+
+class QDesignerFormWindowInterface;
+class QDesignerContainerExtension;
+class QToolButton;
+class QChildEvent;
+class QResizeEvent;
+class QShowEvent;
+class QEvent;
+
+class QDesignerQ3WidgetStack : public Q3WidgetStack
+{
+ Q_OBJECT
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex STORED false DESIGNABLE true)
+ Q_PROPERTY(QString currentPageName READ currentPageName WRITE setCurrentPageName STORED false DESIGNABLE true)
+public:
+ QDesignerQ3WidgetStack(QWidget *parent = 0);
+ int currentIndex();
+ QString currentPageName();
+
+public slots:
+ void updateButtons();
+ void setCurrentIndex(int index);
+ void setCurrentPageName(const QString &pageName);
+
+private slots:
+ void prevPage();
+ void nextPage();
+ void slotCurrentChanged(int index);
+
+signals:
+ void currentChanged(int index);
+
+protected:
+ virtual void childEvent(QChildEvent *e);
+ virtual void resizeEvent(QResizeEvent *e);
+ virtual void showEvent(QShowEvent *e);
+ virtual bool event(QEvent *e);
+
+private:
+ void gotoPage(int page);
+ QDesignerFormWindowInterface *formWindow();
+ QDesignerContainerExtension *container();
+ int count();
+ QWidget *widget(int index);
+ QToolButton *m_prev, *m_next;
+};
+
+QT_END_NAMESPACE
+
+#endif // !QDESIGNER_Q3WIDGETSTACK_P_H
diff --git a/tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp
new file mode 100644
index 0000000000..57252b99bc
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3wizard_container.h"
+#include <Qt3Support/Q3Wizard>
+
+#include <QtDesigner/QDesignerFormWindowInterface>
+#include <QtDesigner/private/ui4_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+static const char *currentPageText = "currentPageText";
+
+Q3WizardHelper::Q3WizardHelper(Q3Wizard *wizard)
+ : QObject(wizard),
+ m_wizard(wizard)
+{
+ connect(m_wizard, SIGNAL(selected(const QString &)), this, SLOT(slotCurrentChanged()));
+}
+
+void Q3WizardHelper::slotCurrentChanged()
+{
+ if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(m_wizard)) {
+ fw->clearSelection();
+ fw->selectWidget(m_wizard, true);
+ }
+}
+
+Q3WizardExtraInfo::Q3WizardExtraInfo(Q3Wizard *wizard, QDesignerFormEditorInterface *core, QObject *parent)
+ : QObject(parent), m_wizard(wizard), m_core(core)
+{}
+
+QWidget *Q3WizardExtraInfo::widget() const
+{ return m_wizard; }
+
+Q3Wizard *Q3WizardExtraInfo::wizard() const
+{ return m_wizard; }
+
+QDesignerFormEditorInterface *Q3WizardExtraInfo::core() const
+{ return m_core; }
+
+bool Q3WizardExtraInfo::saveUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3WizardExtraInfo::loadUiExtraInfo(DomUI *ui)
+{ Q_UNUSED(ui); return false; }
+
+bool Q3WizardExtraInfo::saveWidgetExtraInfo(DomWidget *ui_widget)
+{
+ int i = 0;
+ foreach (DomWidget *ui_child, ui_widget->elementWidget()) {
+ DomProperty *p = new DomProperty();
+ p->setAttributeName(QLatin1String("title"));
+ DomString *str = new DomString();
+ str->setText(wizard()->title(wizard()->page(i)));
+ p->setElementString(str);
+
+ QList<DomProperty *> attributes = ui_child->elementAttribute();
+ attributes.append(p);
+ ui_child->setElementAttribute(attributes);
+
+ i++;
+ }
+ return true;
+}
+
+bool Q3WizardExtraInfo::loadWidgetExtraInfo(DomWidget *ui_widget)
+{
+ int i = 0;
+ foreach (const DomWidget *ui_child, ui_widget->elementWidget()) {
+ foreach (const DomProperty *ui_prop, ui_child->elementAttribute()) {
+ if (ui_prop->attributeName() == QLatin1String("title")) {
+ const DomString *ui_string = ui_prop->elementString();
+ if (ui_string)
+ wizard()->setTitle(wizard()->page(i), ui_string->text());
+ }
+ }
+ i++;
+ }
+ return true;
+}
+
+Q3WizardExtraInfoFactory::Q3WizardExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent)
+ : QExtensionFactory(parent), m_core(core)
+{}
+
+QObject *Q3WizardExtraInfoFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerExtraInfoExtension))
+ return 0;
+
+ if (Q3Wizard *w = qobject_cast<Q3Wizard *>(object))
+ return new Q3WizardExtraInfo(w, m_core, parent);
+
+ return 0;
+}
+
+Q3WizardContainer::Q3WizardContainer(Q3Wizard *wizard, QObject *parent)
+ : QObject(parent),
+ m_wizard(wizard)
+{}
+
+int Q3WizardContainer::count() const
+{
+ return m_wizard->pageCount();
+}
+
+QWidget *Q3WizardContainer::widget(int index) const
+{
+ Q_ASSERT(index != -1);
+ return m_wizard->page(index);
+}
+
+int Q3WizardContainer::currentIndex() const
+{
+ if (m_wizard->currentPage() == 0 && m_wizard->pageCount())
+ m_wizard->showPage(widget(0));
+
+ return m_wizard->indexOf(m_wizard->currentPage());
+}
+
+void Q3WizardContainer::setCurrentIndex(int index)
+{
+ const bool blocked = m_wizard->signalsBlocked();
+ m_wizard->blockSignals(true);
+ m_wizard->showPage(widget(index));
+ m_wizard->blockSignals(blocked);
+}
+
+void Q3WizardContainer::addWidget(QWidget *widget)
+{
+ m_wizard->addPage(widget, tr("Page"));
+}
+
+void Q3WizardContainer::insertWidget(int index, QWidget *widget)
+{
+ m_wizard->insertPage(widget, tr("Page"), index);
+}
+
+void Q3WizardContainer::remove(int index)
+{
+ m_wizard->removePage(widget(index));
+}
+
+Q3WizardContainerFactory::Q3WizardContainerFactory(QExtensionManager *parent)
+ : QExtensionFactory(parent)
+{
+}
+
+QObject *Q3WizardContainerFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
+{
+ if (iid != Q_TYPEID(QDesignerContainerExtension))
+ return 0;
+
+ if (Q3Wizard *w = qobject_cast<Q3Wizard*>(object))
+ return new Q3WizardContainer(w, parent);
+
+ return 0;
+}
+
+Q3WizardPropertySheet::Q3WizardPropertySheet(Q3Wizard *object, QObject *parent)
+ : QDesignerPropertySheet(object, parent), m_wizard(object)
+{
+ createFakeProperty(QLatin1String(currentPageText), QString());
+}
+
+void Q3WizardPropertySheet::setProperty(int index, const QVariant &value)
+{
+ const QString prop = propertyName(index);
+ if (prop == QLatin1String(currentPageText)) {
+ m_wizard->setTitle(m_wizard->currentPage(), value.toString());
+ return;
+ }
+ QDesignerPropertySheet::setProperty(index, value);
+}
+
+QVariant Q3WizardPropertySheet::property(int index) const
+{
+ const QString prop = propertyName(index);
+ if (prop == QLatin1String(currentPageText))
+ return m_wizard->title(m_wizard->currentPage());
+ return QDesignerPropertySheet::property(index);
+}
+
+bool Q3WizardPropertySheet::reset(int index)
+{
+ const QString prop = propertyName(index);
+ if (prop == QLatin1String(currentPageText)) {
+ m_wizard->setTitle(m_wizard->currentPage(), QString());
+ return true;
+ }
+ return QDesignerPropertySheet::reset(index);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.h b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.h
new file mode 100644
index 0000000000..1e28176355
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_container.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3WIZARD_CONTAINER_H
+#define Q3WIZARD_CONTAINER_H
+
+#include <QtDesigner/QDesignerContainerExtension>
+#include <QtDesigner/QExtensionFactory>
+#include <QtDesigner/QDesignerExtraInfoExtension>
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/private/qdesigner_propertysheet_p.h>
+
+#include <QtCore/QPointer>
+#include <Qt3Support/Q3Wizard>
+
+QT_BEGIN_NAMESPACE
+
+class Q3Wizard;
+
+class Q3WizardHelper : public QObject
+{
+ Q_OBJECT
+public:
+ Q3WizardHelper(Q3Wizard *wizard);
+private slots:
+ void slotCurrentChanged();
+private:
+ Q3Wizard *m_wizard;
+};
+
+class Q3WizardExtraInfo: public QObject, public QDesignerExtraInfoExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerExtraInfoExtension)
+public:
+ Q3WizardExtraInfo(Q3Wizard *wizard, QDesignerFormEditorInterface *core, QObject *parent);
+
+ virtual QWidget *widget() const;
+ virtual Q3Wizard *wizard() const;
+ virtual QDesignerFormEditorInterface *core() const;
+
+ virtual bool saveUiExtraInfo(DomUI *ui);
+ virtual bool loadUiExtraInfo(DomUI *ui);
+
+ virtual bool saveWidgetExtraInfo(DomWidget *ui_widget);
+ virtual bool loadWidgetExtraInfo(DomWidget *ui_widget);
+
+private:
+ QPointer<Q3Wizard> m_wizard;
+ QPointer<QDesignerFormEditorInterface> m_core;
+};
+
+class Q3WizardExtraInfoFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ Q3WizardExtraInfoFactory(QDesignerFormEditorInterface *core, QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+
+private:
+ QDesignerFormEditorInterface *m_core;
+};
+
+class Q3WizardContainer: public QObject, public QDesignerContainerExtension
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerContainerExtension)
+public:
+ explicit Q3WizardContainer(Q3Wizard *wizard, QObject *parent = 0);
+
+ virtual int count() const;
+ virtual QWidget *widget(int index) const;
+ virtual int currentIndex() const;
+ virtual void setCurrentIndex(int index);
+ virtual void addWidget(QWidget *widget);
+ virtual void insertWidget(int index, QWidget *widget);
+ virtual void remove(int index);
+
+private:
+ Q3Wizard *m_wizard;
+};
+
+class Q3WizardContainerFactory: public QExtensionFactory
+{
+ Q_OBJECT
+public:
+ explicit Q3WizardContainerFactory(QExtensionManager *parent = 0);
+
+protected:
+ virtual QObject *createExtension(QObject *object, const QString &iid, QObject *parent) const;
+};
+
+class Q3WizardPropertySheet : public QDesignerPropertySheet {
+public:
+ explicit Q3WizardPropertySheet(Q3Wizard *object, QObject *parent = 0);
+
+ virtual void setProperty(int index, const QVariant &value);
+ virtual QVariant property(int index) const;
+ virtual bool reset(int index);
+
+private:
+ Q3Wizard *m_wizard;
+};
+
+typedef QDesignerPropertySheetFactory<Q3Wizard, Q3WizardPropertySheet> Q3WizardPropertySheetFactory;
+
+QT_END_NAMESPACE
+
+#endif // Q3WIZARD_CONTAINER_H
diff --git a/tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp
new file mode 100644
index 0000000000..bdd6ddc722
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3wizard_plugin.h"
+#include "q3wizard_container.h"
+
+#include <QtDesigner/QDesignerFormEditorInterface>
+#include <QtDesigner/QExtensionManager>
+
+#include <QtCore/qplugin.h>
+#include <QtGui/QPushButton>
+#include <Qt3Support/Q3Wizard>
+
+QT_BEGIN_NAMESPACE
+
+Q3WizardPlugin::Q3WizardPlugin(const QIcon &icon, QObject *parent)
+ : QObject(parent), m_initialized(false), m_icon(icon)
+{}
+
+QString Q3WizardPlugin::name() const
+{ return QLatin1String("Q3Wizard"); }
+
+QString Q3WizardPlugin::group() const
+{ return QLatin1String("[invisible]"); }
+
+QString Q3WizardPlugin::toolTip() const
+{ return QString(); }
+
+QString Q3WizardPlugin::whatsThis() const
+{ return QString(); }
+
+QString Q3WizardPlugin::includeFile() const
+{ return QLatin1String("q3wizard.h"); }
+
+QIcon Q3WizardPlugin::icon() const
+{ return m_icon; }
+
+bool Q3WizardPlugin::isContainer() const
+{ return true; }
+
+QWidget *Q3WizardPlugin::createWidget(QWidget *parent)
+{
+ Q3Wizard *wizard = new Q3Wizard(parent);
+ new Q3WizardHelper(wizard);
+ wizard->backButton()->setObjectName(QLatin1String("__qt__passive_") + wizard->backButton()->objectName());
+ wizard->nextButton()->setObjectName(QLatin1String("__qt__passive_") + wizard->nextButton()->objectName());
+ return wizard;
+}
+
+bool Q3WizardPlugin::isInitialized() const
+{ return m_initialized; }
+
+void Q3WizardPlugin::initialize(QDesignerFormEditorInterface *core)
+{
+ Q_UNUSED(core);
+
+ if (m_initialized)
+ return;
+
+ m_initialized = true;
+ QExtensionManager *mgr = core->extensionManager();
+ Q3WizardPropertySheetFactory::registerExtension(mgr);
+ mgr->registerExtensions(new Q3WizardContainerFactory(mgr), Q_TYPEID(QDesignerContainerExtension));
+ mgr->registerExtensions(new Q3WizardExtraInfoFactory(core, mgr), Q_TYPEID(QDesignerExtraInfoExtension));
+}
+
+QString Q3WizardPlugin::codeTemplate() const
+{ return QString(); }
+
+QString Q3WizardPlugin::domXml() const
+{
+ return QLatin1String("\
+<ui language=\"c++\">\
+ <widget class=\"Q3Wizard\" name=\"wizard\">\
+ <property name=\"geometry\">\
+ <rect>\
+ <x>0</x>\
+ <y>0</y>\
+ <width>100</width>\
+ <height>80</height>\
+ </rect>\
+ </property>\
+ <widget class=\"QWidget\" />\
+ <widget class=\"QWidget\" />\
+ </widget>\
+</ui>");
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h
new file mode 100644
index 0000000000..f21dfd3221
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/q3wizard/q3wizard_plugin.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q3WIZARD_PLUGIN_H
+#define Q3WIZARD_PLUGIN_H
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q3WizardPlugin: public QObject, public QDesignerCustomWidgetInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+public:
+ Q3WizardPlugin(const QIcon &icon, QObject *parent = 0);
+
+ virtual QString name() const;
+ virtual QString group() const;
+ virtual QString toolTip() const;
+ virtual QString whatsThis() const;
+ virtual QString includeFile() const;
+ virtual QIcon icon() const;
+ virtual bool isContainer() const;
+ virtual QWidget *createWidget(QWidget *parent);
+ virtual bool isInitialized() const;
+ virtual void initialize(QDesignerFormEditorInterface *core);
+ virtual QString codeTemplate() const;
+ virtual QString domXml() const;
+
+private:
+ bool m_initialized;
+ QIcon m_icon;
+};
+
+QT_END_NAMESPACE
+
+#endif // Q3WIZARD_PLUGIN_H
diff --git a/tools/designer/src/plugins/widgets/qt3supportwidgets.cpp b/tools/designer/src/plugins/widgets/qt3supportwidgets.cpp
new file mode 100644
index 0000000000..eafcf7a28b
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/qt3supportwidgets.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "q3toolbar/q3toolbar_plugin.h"
+#include "q3iconview/q3iconview_plugin.h"
+#include "q3wizard/q3wizard_plugin.h"
+#include "q3mainwindow/q3mainwindow_plugin.h"
+#include "q3widgetstack/q3widgetstack_plugin.h"
+#include "q3listview/q3listview_plugin.h"
+#include "q3table/q3table_plugin.h"
+#include "q3listbox/q3listbox_plugin.h"
+#include "q3listview/q3listview_plugin.h"
+#include "q3textedit/q3textedit_plugin.h"
+#include "q3widgets/q3widget_plugins.h"
+
+#include <QtDesigner/QDesignerCustomWidgetCollectionInterface>
+#include <QtCore/qplugin.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/QIcon>
+
+QT_BEGIN_NAMESPACE
+
+class Qt3SupportWidgets: public QObject, public QDesignerCustomWidgetCollectionInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
+public:
+ Qt3SupportWidgets(QObject *parent = 0);
+
+ virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const;
+
+private:
+ QList<QDesignerCustomWidgetInterface*> m_plugins;
+};
+
+Qt3SupportWidgets::Qt3SupportWidgets(QObject *parent)
+ : QObject(parent)
+{
+ const QIcon qt3Icon(QLatin1String(":/trolltech/formeditor/images/qt3logo.png"));
+ m_plugins.append(new Q3ToolBarPlugin(qt3Icon, this));
+ m_plugins.append(new Q3IconViewPlugin(qt3Icon, this));
+ m_plugins.append(new Q3GroupBoxPlugin(qt3Icon, this));
+ m_plugins.append(new Q3FramePlugin(qt3Icon, this));
+ m_plugins.append(new Q3WizardPlugin(qt3Icon, this));
+ m_plugins.append(new Q3MainWindowPlugin(qt3Icon, this));
+ m_plugins.append(new Q3WidgetStackPlugin(qt3Icon, this));
+ m_plugins.append(new Q3ButtonGroupPlugin(qt3Icon, this));
+ m_plugins.append(new Q3TablePlugin(qt3Icon, this));
+ m_plugins.append(new Q3ListBoxPlugin(qt3Icon, this));
+ m_plugins.append(new Q3ListViewPlugin(qt3Icon, this));
+ m_plugins.append(new Q3ComboBoxPlugin(qt3Icon, this));
+ m_plugins.append(new Q3TextEditPlugin(qt3Icon, this));
+ m_plugins.append(new Q3DateEditPlugin(qt3Icon, this));
+ m_plugins.append(new Q3TimeEditPlugin(qt3Icon, this));
+ m_plugins.append(new Q3DateTimeEditPlugin(qt3Icon, this));
+ m_plugins.append(new Q3ProgressBarPlugin(qt3Icon, this));
+ m_plugins.append(new Q3TextBrowserPlugin(qt3Icon, this));
+}
+
+QList<QDesignerCustomWidgetInterface*> Qt3SupportWidgets::customWidgets() const
+{
+ return m_plugins;
+}
+
+Q_EXPORT_PLUGIN(Qt3SupportWidgets)
+
+QT_END_NAMESPACE
+
+#include "qt3supportwidgets.moc"
diff --git a/tools/designer/src/plugins/widgets/widgets.pro b/tools/designer/src/plugins/widgets/widgets.pro
new file mode 100644
index 0000000000..4d8f9bae84
--- /dev/null
+++ b/tools/designer/src/plugins/widgets/widgets.pro
@@ -0,0 +1,82 @@
+QT += qt3support
+TEMPLATE = lib
+CONFIG += plugin
+DESTDIR =
+TARGET = qt3supportwidgets
+
+CONFIG += qt warn_on qt_no_compat_warning
+
+include(../plugins.pri)
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+DEPENDPATH += q3iconview \
+ q3listview \
+ q3mainwindow \
+ q3toolbar \
+ q3widgetstack \
+ q3wizard \
+ q3listbox \
+ q3table \
+ q3textedit \
+ q3widgets
+
+INCLUDEPATH += . \
+ q3iconview \
+ q3listview \
+ q3mainwindow \
+ q3toolbar \
+ q3widgetstack \
+ q3wizard \
+ q3listbox \
+ q3table \
+ q3textedit \
+ q3widgets
+
+
+SOURCES += qt3supportwidgets.cpp
+
+# Input
+HEADERS += q3iconview/q3iconview_extrainfo.h \
+ q3iconview/q3iconview_plugin.h \
+ q3listview/q3listview_extrainfo.h \
+ q3listview/q3listview_plugin.h \
+ q3mainwindow/q3mainwindow_container.h \
+ q3mainwindow/q3mainwindow_plugin.h \
+ q3toolbar/q3toolbar_extrainfo.h \
+ q3toolbar/q3toolbar_plugin.h \
+ q3widgetstack/q3widgetstack_container.h \
+ q3widgetstack/q3widgetstack_plugin.h \
+ q3widgetstack/qdesigner_q3widgetstack_p.h \
+ q3wizard/q3wizard_container.h \
+ q3wizard/q3wizard_plugin.h \
+ q3listbox/q3listbox_extrainfo.h \
+ q3listbox/q3listbox_plugin.h \
+ q3table/q3table_extrainfo.h \
+ q3table/q3table_plugin.h \
+ q3textedit/q3textedit_extrainfo.h \
+ q3textedit/q3textedit_plugin.h \
+ q3widgets/q3widget_plugins.h \
+
+SOURCES += q3iconview/q3iconview_extrainfo.cpp \
+ q3iconview/q3iconview_plugin.cpp \
+ q3listview/q3listview_extrainfo.cpp \
+ q3listview/q3listview_plugin.cpp \
+ q3mainwindow/q3mainwindow_container.cpp \
+ q3mainwindow/q3mainwindow_plugin.cpp \
+ q3toolbar/q3toolbar_extrainfo.cpp \
+ q3toolbar/q3toolbar_plugin.cpp \
+ q3widgetstack/q3widgetstack_container.cpp \
+ q3widgetstack/q3widgetstack_plugin.cpp \
+ q3widgetstack/qdesigner_q3widgetstack.cpp \
+ q3wizard/q3wizard_container.cpp \
+ q3wizard/q3wizard_plugin.cpp \
+ q3listbox/q3listbox_extrainfo.cpp \
+ q3listbox/q3listbox_plugin.cpp \
+ q3table/q3table_extrainfo.cpp \
+ q3table/q3table_plugin.cpp \
+ q3textedit/q3textedit_extrainfo.cpp \
+ q3textedit/q3textedit_plugin.cpp \
+ q3widgets/q3widget_plugins.cpp
diff --git a/tools/designer/src/sharedcomponents.pri b/tools/designer/src/sharedcomponents.pri
new file mode 100644
index 0000000000..98c59667d8
--- /dev/null
+++ b/tools/designer/src/sharedcomponents.pri
@@ -0,0 +1,30 @@
+contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE
+
+for(QTSHAREDLIB, $$list($$unique(LIBS))) {
+ QT_SHARED_LIB_NAME =
+ isEqual(QTSHAREDLIB, -lformeditor):QT_SHARED_LIB_NAME = formeditor
+ else:isEqual(QTSHAREDLIB, -lobjectinspector):QT_SHARED_LIB_NAME = objectinspector
+ else:isEqual(QTSHAREDLIB, -lpropertyeditor):QT_SHARED_LIB_NAME = propertyeditor
+ else:isEqual(QTSHAREDLIB, -lwidgetbox):QT_SHARED_LIB_NAME = widgetbox
+ else:isEqual(QTSHAREDLIB, -lsignalsloteditor):QT_SHARED_LIB_NAME = signalsloteditor
+ else:isEqual(QTSHAREDLIB, -ltabordereditor):QT_SHARED_LIB_NAME = tabordereditor
+ else:isEqual(QTSHAREDLIB, -lresourceeditor):QT_SHARED_LIB_NAME = resourceeditor
+ else:isEqual(QTSHAREDLIB, -lbuddyeditor):QT_SHARED_LIB_NAME = buddyeditor
+ else:isEqual(QTSHAREDLIB, -ltaskmenu):QT_SHARED_LIB_NAME = taskmenu
+ else:isEqual(QTSHAREDLIB, -lQtDesigner):QT_SHARED_LIB_NAME = QtDesigner
+ else:isEqual(QTSHAREDLIB, -lQtDesignerComponents):QT_SHARED_LIB_NAME = QtDesignerComponents
+ else:isEqual(QTSHAREDLIB, -lQtOpenGL):QT_SHARED_LIB_NAME = QtOpenGL
+
+ !isEmpty(QT_SHARED_LIB_NAME) {
+ LIBS -= -l$${QT_SHARED_LIB_NAME}
+ qtAddLibrary($$QT_SHARED_LIB_NAME)
+ }
+}
+
+unix {
+ CONFIG += create_pc
+ QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS]
+ QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET
+ QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS]
+ QMAKE_PKGCONFIG_DESTDIR = pkgconfig
+}
diff --git a/tools/designer/src/src.pro b/tools/designer/src/src.pro
new file mode 100644
index 0000000000..e7ce55f8ba
--- /dev/null
+++ b/tools/designer/src/src.pro
@@ -0,0 +1,13 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+SUBDIRS = \
+ uitools \
+ lib \
+ components \
+ designer
+
+CONFIG(shared,shared|static):SUBDIRS += plugins
+
+wince*: SUBDIRS -= designer plugins
+contains(DEFINES, QT_NO_CURSOR): SUBDIRS -= lib components \ No newline at end of file
diff --git a/tools/designer/src/uitools/quiloader.cpp b/tools/designer/src/uitools/quiloader.cpp
new file mode 100644
index 0000000000..d3d1d54489
--- /dev/null
+++ b/tools/designer/src/uitools/quiloader.cpp
@@ -0,0 +1,927 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "quiloader.h"
+#include "quiloader_p.h"
+#include "customwidget.h"
+
+#include <formbuilder.h>
+#include <formbuilderextra_p.h>
+#include <textbuilder_p.h>
+#include <ui4_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QApplication>
+#include <QtCore/QDir>
+#include <QtCore/QLibraryInfo>
+#include <QtGui/QLayout>
+#include <QtGui/QWidget>
+#include <QtCore/QMap>
+#include <QtGui/QTabWidget>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QListWidget>
+#include <QtGui/QTableWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QComboBox>
+#include <QtGui/QFontComboBox>
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap<QString, bool> widget_map;
+Q_GLOBAL_STATIC(widget_map, g_widgets)
+
+class QUiLoader;
+class QUiLoaderPrivate;
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+class TranslatingTextBuilder : public QTextBuilder
+{
+public:
+ TranslatingTextBuilder(bool trEnabled, const QByteArray &className) :
+ m_trEnabled(trEnabled), m_className(className) {}
+
+ virtual QVariant loadText(const DomProperty *icon) const;
+
+ virtual QVariant toNativeValue(const QVariant &value) const;
+
+private:
+ bool m_trEnabled;
+ QByteArray m_className;
+};
+
+QVariant TranslatingTextBuilder::loadText(const DomProperty *text) const
+{
+ const DomString *str = text->elementString();
+ if (!str)
+ return QVariant();
+ if (str->hasAttributeNotr()) {
+ const QString notr = str->attributeNotr();
+ if (notr == QLatin1String("true") || notr == QLatin1String("yes"))
+ return qVariantFromValue(str->text());
+ }
+ QUiTranslatableStringValue strVal;
+ strVal.setValue(str->text().toUtf8());
+ if (str->hasAttributeComment())
+ strVal.setComment(str->attributeComment().toUtf8());
+ return qVariantFromValue(strVal);
+}
+
+QVariant TranslatingTextBuilder::toNativeValue(const QVariant &value) const
+{
+ if (qVariantCanConvert<QUiTranslatableStringValue>(value)) {
+ QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(value);
+ if (!m_trEnabled)
+ return QString::fromUtf8(tsv.value().data());
+ return qVariantFromValue(
+ QApplication::translate(m_className, tsv.value(), tsv.comment(),
+ QCoreApplication::UnicodeUTF8));
+ }
+ if (qVariantCanConvert<QString>(value))
+ return qVariantFromValue(qVariantValue<QString>(value));
+ return value;
+}
+
+// This is "exported" to linguist
+const QUiItemRolePair qUiItemRoles[] = {
+ { Qt::DisplayRole, Qt::DisplayPropertyRole },
+#ifndef QT_NO_TOOLTIP
+ { Qt::ToolTipRole, Qt::ToolTipPropertyRole },
+#endif
+#ifndef QT_NO_STATUSTIP
+ { Qt::StatusTipRole, Qt::StatusTipPropertyRole },
+#endif
+#ifndef QT_NO_WHATSTHIS
+ { Qt::WhatsThisRole, Qt::WhatsThisPropertyRole },
+#endif
+ { -1 , -1 }
+};
+
+static void recursiveReTranslate(QTreeWidgetItem *item, const QByteArray &class_name)
+{
+ const QUiItemRolePair *irs = qUiItemRoles;
+
+ int cnt = item->columnCount();
+ for (int i = 0; i < cnt; ++i) {
+ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
+ QVariant v = item->data(i, irs[j].shadowRole);
+ if (v.isValid()) {
+ QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v);
+ const QString text = QApplication::translate(class_name,
+ tsv.value(), tsv.comment(),
+ QCoreApplication::UnicodeUTF8);
+ item->setData(i, irs[j].realRole, text);
+ }
+ }
+ }
+
+ cnt = item->childCount();
+ for (int i = 0; i < cnt; ++i)
+ recursiveReTranslate(item->child(i), class_name);
+}
+
+template<typename T>
+static void reTranslateWidgetItem(T *item, const QByteArray &class_name)
+{
+ const QUiItemRolePair *irs = qUiItemRoles;
+
+ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
+ QVariant v = item->data(irs[j].shadowRole);
+ if (v.isValid()) {
+ QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v);
+ const QString text = QApplication::translate(class_name,
+ tsv.value(), tsv.comment(),
+ QCoreApplication::UnicodeUTF8);
+ item->setData(irs[j].realRole, text);
+ }
+ }
+}
+
+static void reTranslateTableItem(QTableWidgetItem *item, const QByteArray &class_name)
+{
+ if (item)
+ reTranslateWidgetItem(item, class_name);
+}
+
+#define RETRANSLATE_SUBWIDGET_PROP(mainWidget, setter, propName) \
+ do { \
+ QVariant v = mainWidget->widget(i)->property(propName); \
+ if (v.isValid()) { \
+ QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v); \
+ const QString text = QApplication::translate(m_className, \
+ tsv.value(), tsv.comment(), \
+ QCoreApplication::UnicodeUTF8); \
+ mainWidget->setter(i, text); \
+ } \
+ } while (0)
+
+class TranslationWatcher: public QObject
+{
+ Q_OBJECT
+
+public:
+ TranslationWatcher(QObject *parent, const QByteArray &className):
+ QObject(parent),
+ m_className(className)
+ {
+ }
+
+ virtual bool eventFilter(QObject *o, QEvent *event)
+ {
+ if (event->type() == QEvent::LanguageChange) {
+ foreach (const QByteArray &prop, o->dynamicPropertyNames()) {
+ if (prop.startsWith(PROP_GENERIC_PREFIX)) {
+ const QByteArray propName = prop.mid(sizeof(PROP_GENERIC_PREFIX) - 1);
+ const QUiTranslatableStringValue tsv =
+ qVariantValue<QUiTranslatableStringValue>(o->property(prop));
+ const QString text = QApplication::translate(m_className,
+ tsv.value(), tsv.comment(),
+ QCoreApplication::UnicodeUTF8);
+ o->setProperty(propName, text);
+ }
+ }
+ if (0) {
+#ifndef QT_NO_TABWIDGET
+ } else if (QTabWidget *tabw = qobject_cast<QTabWidget*>(o)) {
+ const int cnt = tabw->count();
+ for (int i = 0; i < cnt; ++i) {
+ RETRANSLATE_SUBWIDGET_PROP(tabw, setTabText, PROP_TABPAGETEXT);
+# ifndef QT_NO_TOOLTIP
+ RETRANSLATE_SUBWIDGET_PROP(tabw, setTabToolTip, PROP_TABPAGETOOLTIP);
+# endif
+# ifndef QT_NO_WHATSTHIS
+ RETRANSLATE_SUBWIDGET_PROP(tabw, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
+# endif
+ }
+#endif
+#ifndef QT_NO_LISTWIDGET
+ } else if (QListWidget *listw = qobject_cast<QListWidget*>(o)) {
+ const int cnt = listw->count();
+ for (int i = 0; i < cnt; ++i)
+ reTranslateWidgetItem(listw->item(i), m_className);
+#endif
+#ifndef QT_NO_TREEWIDGET
+ } else if (QTreeWidget *treew = qobject_cast<QTreeWidget*>(o)) {
+ if (QTreeWidgetItem *item = treew->headerItem())
+ recursiveReTranslate(item, m_className);
+ const int cnt = treew->topLevelItemCount();
+ for (int i = 0; i < cnt; ++i) {
+ QTreeWidgetItem *item = treew->topLevelItem(i);
+ recursiveReTranslate(item, m_className);
+ }
+#endif
+#ifndef QT_NO_TABLEWIDGET
+ } else if (QTableWidget *tablew = qobject_cast<QTableWidget*>(o)) {
+ const int row_cnt = tablew->rowCount();
+ const int col_cnt = tablew->columnCount();
+ for (int j = 0; j < col_cnt; ++j)
+ reTranslateTableItem(tablew->verticalHeaderItem(j), m_className);
+ for (int i = 0; i < row_cnt; ++i) {
+ reTranslateTableItem(tablew->horizontalHeaderItem(i), m_className);
+ for (int j = 0; j < col_cnt; ++j)
+ reTranslateTableItem(tablew->item(i, j), m_className);
+ }
+#endif
+#ifndef QT_NO_COMBOBOX
+ } else if (QComboBox *combow = qobject_cast<QComboBox*>(o)) {
+ if (!qobject_cast<QFontComboBox*>(o)) {
+ const int cnt = combow->count();
+ for (int i = 0; i < cnt; ++i) {
+ const QVariant v = combow->itemData(i, Qt::DisplayPropertyRole);
+ if (v.isValid()) {
+ QUiTranslatableStringValue tsv = qVariantValue<QUiTranslatableStringValue>(v);
+ const QString text = QApplication::translate(m_className,
+ tsv.value(), tsv.comment(),
+ QCoreApplication::UnicodeUTF8);
+ combow->setItemText(i, text);
+ }
+ }
+ }
+#endif
+#ifndef QT_NO_TOOLBOX
+ } else if (QToolBox *toolw = qobject_cast<QToolBox*>(o)) {
+ const int cnt = toolw->count();
+ for (int i = 0; i < cnt; ++i) {
+ RETRANSLATE_SUBWIDGET_PROP(toolw, setItemText, PROP_TOOLITEMTEXT);
+# ifndef QT_NO_TOOLTIP
+ RETRANSLATE_SUBWIDGET_PROP(toolw, setItemToolTip, PROP_TOOLITEMTOOLTIP);
+# endif
+ }
+#endif
+ }
+ }
+ return false;
+ }
+
+private:
+ QByteArray m_className;
+};
+
+class FormBuilderPrivate: public QFormBuilder
+{
+ friend class QT_PREPEND_NAMESPACE(QUiLoader);
+ friend class QT_PREPEND_NAMESPACE(QUiLoaderPrivate);
+ typedef QFormBuilder ParentClass;
+
+public:
+ QUiLoader *loader;
+
+ bool dynamicTr;
+ bool trEnabled;
+
+ FormBuilderPrivate(): loader(0), dynamicTr(false), trEnabled(true), m_trwatch(0) {}
+
+ QWidget *defaultCreateWidget(const QString &className, QWidget *parent, const QString &name)
+ {
+ return ParentClass::createWidget(className, parent, name);
+ }
+
+ QLayout *defaultCreateLayout(const QString &className, QObject *parent, const QString &name)
+ {
+ return ParentClass::createLayout(className, parent, name);
+ }
+
+ QAction *defaultCreateAction(QObject *parent, const QString &name)
+ {
+ return ParentClass::createAction(parent, name);
+ }
+
+ QActionGroup *defaultCreateActionGroup(QObject *parent, const QString &name)
+ {
+ return ParentClass::createActionGroup(parent, name);
+ }
+
+ virtual QWidget *createWidget(const QString &className, QWidget *parent, const QString &name)
+ {
+ if (QWidget *widget = loader->createWidget(className, parent, name)) {
+ widget->setObjectName(name);
+ return widget;
+ }
+
+ return 0;
+ }
+
+ virtual QLayout *createLayout(const QString &className, QObject *parent, const QString &name)
+ {
+ if (QLayout *layout = loader->createLayout(className, parent, name)) {
+ layout->setObjectName(name);
+ return layout;
+ }
+
+ return 0;
+ }
+
+ virtual QActionGroup *createActionGroup(QObject *parent, const QString &name)
+ {
+ if (QActionGroup *actionGroup = loader->createActionGroup(parent, name)) {
+ actionGroup->setObjectName(name);
+ return actionGroup;
+ }
+
+ return 0;
+ }
+
+ virtual QAction *createAction(QObject *parent, const QString &name)
+ {
+ if (QAction *action = loader->createAction(parent, name)) {
+ action->setObjectName(name);
+ return action;
+ }
+
+ return 0;
+ }
+
+ virtual void applyProperties(QObject *o, const QList<DomProperty*> &properties);
+ virtual QWidget *create(DomUI *ui, QWidget *parentWidget);
+ virtual QWidget *create(DomWidget *ui_widget, QWidget *parentWidget);
+ virtual bool addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget);
+
+private:
+ QByteArray m_class;
+ TranslationWatcher *m_trwatch;
+};
+
+static QString convertTranslatable(const DomProperty *p, const QByteArray &className,
+ QUiTranslatableStringValue *strVal)
+{
+ if (p->kind() != DomProperty::String)
+ return QString();
+ const DomString *dom_str = p->elementString();
+ if (!dom_str)
+ return QString();
+ if (dom_str->hasAttributeNotr()) {
+ const QString notr = dom_str->attributeNotr();
+ if (notr == QLatin1String("yes") || notr == QLatin1String("true"))
+ return QString();
+ }
+ strVal->setValue(dom_str->text().toUtf8());
+ strVal->setComment(dom_str->attributeComment().toUtf8());
+ if (strVal->value().isEmpty() && strVal->comment().isEmpty())
+ return QString();
+ return QApplication::translate(className,
+ strVal->value(), strVal->comment(),
+ QCoreApplication::UnicodeUTF8);
+}
+
+void FormBuilderPrivate::applyProperties(QObject *o, const QList<DomProperty*> &properties)
+{
+ typedef QList<DomProperty*> DomPropertyList;
+
+ QFormBuilder::applyProperties(o, properties);
+
+ if (!m_trwatch)
+ m_trwatch = new TranslationWatcher(o, m_class);
+
+ if (properties.empty())
+ return;
+
+ // Unlike string item roles, string properties are not loaded via the textBuilder
+ // (as they are "shadowed" by the property sheets in designer). So do the initial
+ // translation here.
+ bool anyTrs = false;
+ foreach (const DomProperty *p, properties) {
+ QUiTranslatableStringValue strVal;
+ const QString text = convertTranslatable(p, m_class, &strVal);
+ if (text.isEmpty())
+ continue;
+ const QByteArray name = p->attributeName().toUtf8();
+ if (dynamicTr) {
+ o->setProperty(PROP_GENERIC_PREFIX + name, qVariantFromValue(strVal));
+ anyTrs = trEnabled;
+ }
+ o->setProperty(name, text);
+ }
+ if (anyTrs)
+ o->installEventFilter(m_trwatch);
+}
+
+QWidget *FormBuilderPrivate::create(DomUI *ui, QWidget *parentWidget)
+{
+ m_class = ui->elementClass().toUtf8();
+ m_trwatch = 0;
+ setTextBuilder(new TranslatingTextBuilder(trEnabled, m_class));
+ return QFormBuilder::create(ui, parentWidget);
+}
+
+QWidget *FormBuilderPrivate::create(DomWidget *ui_widget, QWidget *parentWidget)
+{
+ QWidget *w = QFormBuilder::create(ui_widget, parentWidget);
+ if (w == 0)
+ return 0;
+
+ if (0) {
+#ifndef QT_NO_TABWIDGET
+ } else if (qobject_cast<QTabWidget*>(w)) {
+#endif
+#ifndef QT_NO_LISTWIDGET
+ } else if (qobject_cast<QListWidget*>(w)) {
+#endif
+#ifndef QT_NO_TREEWIDGET
+ } else if (qobject_cast<QTreeWidget*>(w)) {
+#endif
+#ifndef QT_NO_TABLEWIDGET
+ } else if (qobject_cast<QTableWidget*>(w)) {
+#endif
+#ifndef QT_NO_COMBOBOX
+ } else if (qobject_cast<QComboBox*>(w)) {
+ if (qobject_cast<QFontComboBox*>(w))
+ return w;
+#endif
+#ifndef QT_NO_TOOLBOX
+ } else if (qobject_cast<QToolBox*>(w)) {
+#endif
+ } else {
+ return w;
+ }
+ if (dynamicTr && trEnabled)
+ w->installEventFilter(m_trwatch);
+ return w;
+}
+
+#define TRANSLATE_SUBWIDGET_PROP(mainWidget, attribute, setter, propName) \
+ do { \
+ if (const DomProperty *p##attribute = attributes.value(strings.attribute)) { \
+ QUiTranslatableStringValue strVal; \
+ const QString text = convertTranslatable(p##attribute, m_class, &strVal); \
+ if (!text.isEmpty()) { \
+ if (dynamicTr) \
+ mainWidget->widget(i)->setProperty(propName, qVariantFromValue(strVal)); \
+ mainWidget->setter(i, text); \
+ } \
+ } \
+ } while (0)
+
+bool FormBuilderPrivate::addItem(DomWidget *ui_widget, QWidget *widget, QWidget *parentWidget)
+{
+ if (parentWidget == 0)
+ return true;
+
+ if (!ParentClass::addItem(ui_widget, widget, parentWidget))
+ return false;
+
+ // Check special cases. First: Custom container
+ const QString className = QLatin1String(parentWidget->metaObject()->className());
+ if (!QFormBuilderExtra::instance(this)->customWidgetAddPageMethod(className).isEmpty())
+ return true;
+
+ const QFormBuilderStrings &strings = QFormBuilderStrings::instance();
+
+ if (0) {
+#ifndef QT_NO_TABWIDGET
+ } else if (QTabWidget *tabWidget = qobject_cast<QTabWidget*>(parentWidget)) {
+ const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
+ const int i = tabWidget->count() - 1;
+ TRANSLATE_SUBWIDGET_PROP(tabWidget, titleAttribute, setTabText, PROP_TABPAGETEXT);
+# ifndef QT_NO_TOOLTIP
+ TRANSLATE_SUBWIDGET_PROP(tabWidget, toolTipAttribute, setTabToolTip, PROP_TABPAGETOOLTIP);
+# endif
+# ifndef QT_NO_WHATSTHIS
+ TRANSLATE_SUBWIDGET_PROP(tabWidget, whatsThisAttribute, setTabWhatsThis, PROP_TABPAGEWHATSTHIS);
+# endif
+#endif
+#ifndef QT_NO_TOOLBOX
+ } else if (QToolBox *toolBox = qobject_cast<QToolBox*>(parentWidget)) {
+ const DomPropertyHash attributes = propertyMap(ui_widget->elementAttribute());
+ const int i = toolBox->count() - 1;
+ TRANSLATE_SUBWIDGET_PROP(toolBox, labelAttribute, setItemText, PROP_TOOLITEMTEXT);
+# ifndef QT_NO_TOOLTIP
+ TRANSLATE_SUBWIDGET_PROP(toolBox, toolTipAttribute, setItemToolTip, PROP_TOOLITEMTOOLTIP);
+# endif
+#endif
+ }
+
+ return true;
+}
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+class QUiLoaderPrivate
+{
+public:
+#ifdef QFORMINTERNAL_NAMESPACE
+ QFormInternal::FormBuilderPrivate builder;
+#else
+ FormBuilderPrivate builder;
+#endif
+
+ void setupWidgetMap() const;
+};
+
+void QUiLoaderPrivate::setupWidgetMap() const
+{
+ if (!g_widgets()->isEmpty())
+ return;
+
+#define DECLARE_WIDGET(a, b) g_widgets()->insert(QLatin1String(#a), true);
+#define DECLARE_LAYOUT(a, b)
+
+#include "widgets.table"
+
+#undef DECLARE_WIDGET
+#undef DECLARE_WIDGET_1
+#undef DECLARE_LAYOUT
+}
+
+/*!
+ \class QUiLoader
+ \inmodule QtUiTools
+
+ \brief The QUiLoader class allows standalone applications dynamically
+ create user interfaces at run-time using the information stored in
+ .ui files or specified plugin paths.
+
+ In addition, you can customize of creating an user interface by
+ deriving your own loader class.
+
+ If you have a custom component or an application that embeds Qt
+ Designer, you can also use the QFormBuilder class provided by the
+ QtDesigner module to create user interfaces from .ui files.
+
+ The QUiLoader class provides a collection of functions that allows
+ you to create widgets based on the information stored in \c .ui
+ files (created with Qt Designer) or available in the specified
+ plugin paths. The specified plugin paths can be retrieved using
+ the pluginPaths() function. You can retrieve the contents of an \c
+ .ui file using the load() function. For example:
+
+ \snippet doc/src/snippets/quiloader/mywidget.cpp 0
+
+ By including the user interface in the form's resources (\c myform.qrc),
+ we ensure that it will be present at run-time:
+
+ \quotefile doc/src/snippets/quiloader/mywidget.qrc
+
+ The availableWidgets() function returns a QStringList with the
+ class names of the widgets available in the specified plugin
+ paths. You can create any of these widgets using the
+ createWidget() function. For example:
+
+ \snippet doc/src/snippets/quiloader/main.cpp 0
+
+ You can make a custom widget available to the loader using the
+ addPluginPath() function, and you can remove all the available widgets
+ by calling the clearPluginPaths() function.
+
+ The createAction(), createActionGroup(), createLayout() and
+ createWidget() functions are used internally by the QUiLoader class
+ whenever it has to create an action, action group, layout or
+ widget respectively. For that reason, you can subclass the QUiLoader
+ class and reimplement these functions to intervene the process of
+ constructing an user interface. For example, you might want to
+ create a list of the actions created when loading a form or
+ creating a custom widget.
+
+ For a complete example using the QUiLoader class, see the \l
+ {designer/calculatorbuilder}{Calculator Builder} example.
+
+ \sa QtUiTools, QFormBuilder
+*/
+
+/*!
+ Creates a form loader with the given \a parent.
+*/
+QUiLoader::QUiLoader(QObject *parent)
+ : QObject(parent), d_ptr(new QUiLoaderPrivate)
+{
+ Q_D(QUiLoader);
+
+ d->builder.loader = this;
+
+ QStringList paths;
+ foreach (const QString &path, QApplication::libraryPaths()) {
+ QString libPath = path;
+ libPath += QDir::separator();
+ libPath += QLatin1String("designer");
+ paths.append(libPath);
+ }
+
+ d->builder.setPluginPath(paths);
+}
+
+/*!
+ Destroys the loader.
+*/
+QUiLoader::~QUiLoader()
+{
+ delete d_ptr;
+}
+
+/*!
+ Loads a form from the given \a device and creates a new widget with the given
+ \a parentWidget to hold its contents.
+
+ \sa createWidget()
+*/
+QWidget *QUiLoader::load(QIODevice *device, QWidget *parentWidget)
+{
+ Q_D(QUiLoader);
+ // QXmlStreamReader will report errors on open failure.
+ if (!device->isOpen())
+ device->open(QIODevice::ReadOnly|QIODevice::Text);
+ return d->builder.load(device, parentWidget);
+}
+
+/*!
+ Returns a list naming the paths the loader searches when locating
+ custom widget plugins.
+
+ \sa addPluginPath(), clearPluginPaths()
+*/
+QStringList QUiLoader::pluginPaths() const
+{
+ Q_D(const QUiLoader);
+ return d->builder.pluginPaths();
+}
+
+/*!
+ Clears the list of paths the loader searches when locating
+ plugins.
+
+ \sa addPluginPath(), pluginPaths()
+*/
+void QUiLoader::clearPluginPaths()
+{
+ Q_D(QUiLoader);
+ d->builder.clearPluginPaths();
+}
+
+/*!
+ Adds the given \a path to the list of paths the loader searches
+ when locating plugins.
+
+ \sa pluginPaths(), clearPluginPaths()
+*/
+void QUiLoader::addPluginPath(const QString &path)
+{
+ Q_D(QUiLoader);
+ d->builder.addPluginPath(path);
+}
+
+/*!
+ Creates a new widget with the given \a parent and \a name
+ using the class specified by \a className. You can use this
+ function to create any of the widgets returned by the
+ availableWidgets() function.
+
+ The function is also used internally by the QUiLoader class whenever
+ it has to create a widget. For that reason, you can subclass the
+ QUiLoader class and reimplement this function to intervene in the
+ process of constructing a user interface or widget.
+
+ \sa availableWidgets(), load()
+*/
+QWidget *QUiLoader::createWidget(const QString &className, QWidget *parent, const QString &name)
+{
+ Q_D(QUiLoader);
+ return d->builder.defaultCreateWidget(className, parent, name);
+}
+
+/*!
+ Creates a new layout with the given \a parent and \a name
+ using the class specified by \a className.
+
+ The function is used internally by the QUiLoader class whenever it
+ has to create a layout. For that reason, you can subclass the
+ QUiLoader class and reimplement this function to intervene the
+ process of constructing an user interface or widget.
+
+ \sa createWidget(), load()
+*/
+QLayout *QUiLoader::createLayout(const QString &className, QObject *parent, const QString &name)
+{
+ Q_D(QUiLoader);
+ return d->builder.defaultCreateLayout(className, parent, name);
+}
+
+/*!
+ Creates a new action group with the given \a parent and \a name.
+
+ The function is used internally by the QUiLoader class whenever it
+ has to create an action group. For that reason, you can subclass
+ the QUiLoader class and reimplement this function to intervene the
+ process of constructing an user interface or widget.
+
+ \sa createAction(), createWidget(), load()
+ */
+QActionGroup *QUiLoader::createActionGroup(QObject *parent, const QString &name)
+{
+ Q_D(QUiLoader);
+ return d->builder.defaultCreateActionGroup(parent, name);
+}
+
+/*!
+ Creates a new action with the given \a parent and \a name.
+
+ The function is used internally by the QUiLoader class whenever it
+ has to create an action. For that reason, you can subclass the
+ QUiLoader class and reimplement this function to intervene the
+ process of constructing an user interface or widget.
+
+ \sa createActionGroup(), createWidget(), load()
+*/
+QAction *QUiLoader::createAction(QObject *parent, const QString &name)
+{
+ Q_D(QUiLoader);
+ return d->builder.defaultCreateAction(parent, name);
+}
+
+/*!
+ Returns a list naming the available widgets that can be built
+ using the createWidget() function, i.e all the widgets specified
+ within the given plugin paths.
+
+ \sa pluginPaths(), createWidget()
+
+*/
+QStringList QUiLoader::availableWidgets() const
+{
+ Q_D(const QUiLoader);
+
+ d->setupWidgetMap();
+ widget_map available = *g_widgets();
+
+ foreach (QDesignerCustomWidgetInterface *plugin, d->builder.customWidgets()) {
+ available.insert(plugin->name(), true);
+ }
+
+ return available.keys();
+}
+
+
+/*!
+ Returns a list naming the available layouts that can be built
+ using the createLayout() function
+
+ \sa createLayout()
+ \since 4.5
+*/
+
+QStringList QUiLoader::availableLayouts() const
+{
+ QStringList rc;
+#define DECLARE_WIDGET(a, b)
+#define DECLARE_LAYOUT(a, b) rc.push_back(QLatin1String(#a));
+
+#include "widgets.table"
+
+#undef DECLARE_WIDGET
+#undef DECLARE_LAYOUT
+ return rc;
+}
+
+/*!
+ Sets the working directory of the loader to \a dir. The loader
+ looks for other resources, such as icons and resource files,
+ in paths relative to this directory.
+
+ \sa workingDirectory()
+*/
+
+void QUiLoader::setWorkingDirectory(const QDir &dir)
+{
+ Q_D(QUiLoader);
+ d->builder.setWorkingDirectory(dir);
+}
+
+/*!
+ Returns the working directory of the loader.
+
+ \sa setWorkingDirectory()
+*/
+
+QDir QUiLoader::workingDirectory() const
+{
+ Q_D(const QUiLoader);
+ return d->builder.workingDirectory();
+}
+
+/*!
+ Sets whether the execution of scripts is enabled to \a enabled.
+ \since 4.3
+ \internal
+*/
+
+void QUiLoader::setScriptingEnabled(bool enabled)
+{
+ Q_D(QUiLoader);
+ d->builder.setScriptingEnabled(enabled);
+}
+
+/*!
+ Returns whether the execution of scripts is enabled.
+ \sa setScriptingEnabled()
+ \since 4.3
+ \internal
+*/
+
+bool QUiLoader::isScriptingEnabled() const
+{
+ Q_D(const QUiLoader);
+ return d->builder.isScriptingEnabled();
+}
+
+/*!
+ Sets whether user interfaces loaded by this loader automatically
+ retranslate themselves upon receiving a language change event or not,
+ depending on \a enabled.
+
+ \since 4.5
+*/
+
+void QUiLoader::setLanguageChangeEnabled(bool enabled)
+{
+ Q_D(QUiLoader);
+ d->builder.dynamicTr = enabled;
+}
+
+/*!
+ Returns whether dynamic retranslation on language change is enabled.
+ \sa setLanguageChangeEnabled()
+ \since 4.5
+*/
+
+bool QUiLoader::isLanguageChangeEnabled() const
+{
+ Q_D(const QUiLoader);
+ return d->builder.dynamicTr;
+}
+
+/*!
+ \internal
+
+ Sets whether user interfaces loaded by this loader are translated
+ at all. Note that this is orthogonal to languageChangeEnabled.
+
+ \since 4.5
+*/
+
+void QUiLoader::setTranslationEnabled(bool enabled)
+{
+ Q_D(QUiLoader);
+ d->builder.trEnabled = enabled;
+}
+
+/*!
+ \internal
+
+ Returns whether translation is enabled.
+ \sa setTranslationEnabled()
+
+ \since 4.5
+*/
+
+bool QUiLoader::isTranslationEnabled() const
+{
+ Q_D(const QUiLoader);
+ return d->builder.trEnabled;
+}
+
+QT_END_NAMESPACE
+
+#include "quiloader.moc"
diff --git a/tools/designer/src/uitools/quiloader.h b/tools/designer/src/uitools/quiloader.h
new file mode 100644
index 0000000000..6543ba8b65
--- /dev/null
+++ b/tools/designer/src/uitools/quiloader.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUILOADER_H
+#define QUILOADER_H
+
+#include <QtCore/QObject>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+class QLayout;
+class QAction;
+class QActionGroup;
+class QString;
+class QIODevice;
+class QDir;
+
+class QUiLoaderPrivate;
+class QUiLoader : public QObject
+{
+ Q_OBJECT
+public:
+ QUiLoader(QObject *parent = 0);
+ virtual ~QUiLoader();
+
+ QStringList pluginPaths() const;
+ void clearPluginPaths();
+ void addPluginPath(const QString &path);
+
+ QWidget *load(QIODevice *device, QWidget *parentWidget = 0);
+ QStringList availableWidgets() const;
+ QStringList availableLayouts() const;
+
+ virtual QWidget *createWidget(const QString &className, QWidget *parent = 0, const QString &name = QString());
+ virtual QLayout *createLayout(const QString &className, QObject *parent = 0, const QString &name = QString());
+ virtual QActionGroup *createActionGroup(QObject *parent = 0, const QString &name = QString());
+ virtual QAction *createAction(QObject *parent = 0, const QString &name = QString());
+
+ void setWorkingDirectory(const QDir &dir);
+ QDir workingDirectory() const;
+
+ void setScriptingEnabled(bool enabled);
+ bool isScriptingEnabled() const;
+
+ void setLanguageChangeEnabled(bool enabled);
+ bool isLanguageChangeEnabled() const;
+
+ void setTranslationEnabled(bool enabled);
+ bool isTranslationEnabled() const;
+
+private:
+ QUiLoaderPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QUiLoader)
+ Q_DISABLE_COPY(QUiLoader)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QUILOADER_H
diff --git a/tools/designer/src/uitools/quiloader_p.h b/tools/designer/src/uitools/quiloader_p.h
new file mode 100644
index 0000000000..6441106a26
--- /dev/null
+++ b/tools/designer/src/uitools/quiloader_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Designer of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUILOADER_P_H
+#define QUILOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QByteArray>
+#include <QtCore/QMetaType>
+
+// This file is here for use by the form preview in Linguist. If you change anything
+// here or in the code which uses it, remember to adapt Linguist accordingly.
+
+#define PROP_GENERIC_PREFIX "_q_notr_"
+#define PROP_TOOLITEMTEXT "_q_toolItemText_notr"
+#define PROP_TOOLITEMTOOLTIP "_q_toolItemToolTip_notr"
+#define PROP_TABPAGETEXT "_q_tabPageText_notr"
+#define PROP_TABPAGETOOLTIP "_q_tabPageToolTip_notr"
+#define PROP_TABPAGEWHATSTHIS "_q_tabPageWhatsThis_notr"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QUiTranslatableStringValue
+{
+public:
+ QByteArray value() const { return m_value; }
+ void setValue(const QByteArray &value) { m_value = value; }
+ QByteArray comment() const { return m_comment; }
+ void setComment(const QByteArray &comment) { m_comment = comment; }
+
+private:
+ QByteArray m_value;
+ QByteArray m_comment;
+};
+
+struct QUiItemRolePair {
+ int realRole;
+ int shadowRole;
+};
+
+#ifdef QFORMINTERNAL_NAMESPACE
+namespace QFormInternal
+{
+#endif
+
+extern const QUiItemRolePair qUiItemRoles[];
+
+#ifdef QFORMINTERNAL_NAMESPACE
+}
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+Q_DECLARE_METATYPE(QUiTranslatableStringValue)
+
+
+#endif // QUILOADER_P_H
diff --git a/tools/designer/src/uitools/uitools.pro b/tools/designer/src/uitools/uitools.pro
new file mode 100644
index 0000000000..a20abf0b2d
--- /dev/null
+++ b/tools/designer/src/uitools/uitools.pro
@@ -0,0 +1,41 @@
+TEMPLATE = lib
+TARGET = $$qtLibraryTarget(QtUiTools)
+QT += xml
+CONFIG += qt staticlib
+DESTDIR = ../../../../lib
+DLLDESTDIR = ../../../../bin
+
+win32|mac:!macx-xcode:CONFIG += debug_and_release build_all
+
+DEFINES += QFORMINTERNAL_NAMESPACE QT_DESIGNER_STATIC QT_FORMBUILDER_NO_SCRIPT
+isEmpty(QT_MAJOR_VERSION) {
+ VERSION=4.3.0
+} else {
+ VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}
+}
+include(../../../../src/qt_targets.pri)
+QMAKE_TARGET_PRODUCT = UiLoader
+QMAKE_TARGET_DESCRIPTION = QUiLoader
+
+include(../lib/uilib/uilib.pri)
+
+HEADERS += quiloader.h
+SOURCES += quiloader.cpp
+
+include($$QT_BUILD_TREE/include/QtUiTools/headers.pri)
+quitools_headers.files = $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES
+quitools_headers.path = $$[QT_INSTALL_HEADERS]/QtUiTools
+INSTALLS += quitools_headers
+
+target.path=$$[QT_INSTALL_LIBS]
+INSTALLS += target
+
+unix {
+ CONFIG += create_pc
+ QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS]
+ QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET
+ QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS]
+ QMAKE_PKGCONFIG_DESTDIR = pkgconfig
+ QMAKE_PKGCONFIG_REQUIRES += QtXml
+}
+
diff --git a/tools/designer/translations/translations.pro b/tools/designer/translations/translations.pro
new file mode 100644
index 0000000000..7294956b11
--- /dev/null
+++ b/tools/designer/translations/translations.pro
@@ -0,0 +1,140 @@
+include(../src/components/buddyeditor/buddyeditor.pri)
+include(../src/components/component.pri)
+include(../src/components/formeditor/formeditor.pri)
+include(../src/components/objectinspector/objectinspector.pri)
+include(../src/components/propertyeditor/propertyeditor.pri)
+include(../src/components/signalsloteditor/signalsloteditor.pri)
+include(../src/components/tabordereditor/tabordereditor.pri)
+include(../src/components/taskmenu/taskmenu.pri)
+include(../src/components/widgetbox/widgetbox.pri)
+include(../src/lib/extension/extension.pri)
+include(../src/lib/sdk/sdk.pri)
+include(../src/lib/shared/shared.pri)
+include(../src/lib/uilib/uilib.pri)
+include(../../shared/qttoolbardialog/qttoolbardialog.pri)
+include(../../shared/qtpropertybrowser/qtpropertybrowser.pri)
+include(../../shared/qtgradienteditor/qtgradienteditor.pri)
+
+# Include ActiveQt plugin
+SOURCES += ../src/plugins/activeqt/qaxwidgetextrainfo.cpp \
+ ../src/plugins/activeqt/qaxwidgetplugin.cpp \
+ ../src/plugins/activeqt/qaxwidgetpropertysheet.cpp \
+ ../src/plugins/activeqt/qaxwidgettaskmenu.cpp \
+ ../src/plugins/activeqt/qdesigneraxwidget.cpp
+
+HEADERS += ../src/plugins/activeqt/qaxwidgetextrainfo.h \
+ ../src/plugins/activeqt/qaxwidgetplugin.h \
+ ../src/plugins/activeqt/qaxwidgetpropertysheet.h \
+ ../src/plugins/activeqt/qaxwidgettaskmenu.h \
+ ../src/plugins/activeqt/qdesigneraxwidget.h \
+ ../../../src/activeqt/shared/qaxtypes.h
+
+
+# Include Qt3Support plugin
+
+SOURCES += ../src/plugins/widgets/qt3supportwidgets.cpp
+HEADERS += ../src/plugins/widgets/q3iconview/q3iconview_extrainfo.h \
+ ../src/plugins/widgets/q3iconview/q3iconview_plugin.h \
+ ../src/plugins/widgets/q3listview/q3listview_extrainfo.h \
+ ../src/plugins/widgets/q3listview/q3listview_plugin.h \
+ ../src/plugins/widgets/q3mainwindow/q3mainwindow_container.h \
+ ../src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.h \
+ ../src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.h \
+ ../src/plugins/widgets/q3toolbar/q3toolbar_plugin.h \
+ ../src/plugins/widgets/q3widgetstack/q3widgetstack_container.h \
+ ../src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.h \
+ ../src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack_p.h \
+ ../src/plugins/widgets/q3wizard/q3wizard_container.h \
+ ../src/plugins/widgets/q3wizard/q3wizard_plugin.h \
+ ../src/plugins/widgets/q3listbox/q3listbox_extrainfo.h \
+ ../src/plugins/widgets/q3listbox/q3listbox_plugin.h \
+ ../src/plugins/widgets/q3table/q3table_extrainfo.h \
+ ../src/plugins/widgets/q3table/q3table_plugin.h \
+ ../src/plugins/widgets/q3textedit/q3textedit_extrainfo.h \
+ ../src/plugins/widgets/q3textedit/q3textedit_plugin.h \
+ ../src/plugins/widgets/q3widgets/q3widget_plugins.h
+
+SOURCES += ../src/plugins/widgets/q3iconview/q3iconview_extrainfo.cpp \
+ ../src/plugins/widgets/q3iconview/q3iconview_plugin.cpp \
+ ../src/plugins/widgets/q3listview/q3listview_extrainfo.cpp \
+ ../src/plugins/widgets/q3listview/q3listview_plugin.cpp \
+ ../src/plugins/widgets/q3mainwindow/q3mainwindow_container.cpp \
+ ../src/plugins/widgets/q3mainwindow/q3mainwindow_plugin.cpp \
+ ../src/plugins/widgets/q3toolbar/q3toolbar_extrainfo.cpp \
+ ../src/plugins/widgets/q3toolbar/q3toolbar_plugin.cpp \
+ ../src/plugins/widgets/q3widgetstack/q3widgetstack_container.cpp \
+ ../src/plugins/widgets/q3widgetstack/q3widgetstack_plugin.cpp \
+ ../src/plugins/widgets/q3widgetstack/qdesigner_q3widgetstack.cpp \
+ ../src/plugins/widgets/q3wizard/q3wizard_container.cpp \
+ ../src/plugins/widgets/q3wizard/q3wizard_plugin.cpp \
+ ../src/plugins/widgets/q3listbox/q3listbox_extrainfo.cpp \
+ ../src/plugins/widgets/q3listbox/q3listbox_plugin.cpp \
+ ../src/plugins/widgets/q3table/q3table_extrainfo.cpp \
+ ../src/plugins/widgets/q3table/q3table_plugin.cpp \
+ ../src/plugins/widgets/q3textedit/q3textedit_extrainfo.cpp \
+ ../src/plugins/widgets/q3textedit/q3textedit_plugin.cpp \
+ ../src/plugins/widgets/q3widgets/q3widget_plugins.cpp
+
+# Include those manually as they do not contain any directory specification
+APP_DIR=../src/designer
+SOURCES += $$APP_DIR/appfontdialog.cpp \
+ $$APP_DIR/assistantclient.cpp \
+ $$APP_DIR/main.cpp \
+ $$APP_DIR/mainwindow.cpp \
+ $$APP_DIR/newform.cpp \
+ $$APP_DIR/plugindialog.cpp \
+ $$APP_DIR/preferencesdialog.cpp \
+ $$APP_DIR/qdesigner_actions.cpp \
+ $$APP_DIR/qdesigner_appearanceoptions.cpp \
+ $$APP_DIR/qdesigner.cpp \
+ $$APP_DIR/qdesigner_formwindow.cpp \
+ $$APP_DIR/qdesigner_server.cpp \
+ $$APP_DIR/qdesigner_settings.cpp \
+ $$APP_DIR/qdesigner_toolwindow.cpp \
+ $$APP_DIR/qdesigner_workbench.cpp \
+ $$APP_DIR/saveformastemplate.cpp \
+ $$APP_DIR/versiondialog.cpp
+
+HEADERS+= $$APP_DIR/appfontdialog.h \
+ $$APP_DIR/assistantclient.h \
+ $$APP_DIR/designer_enums.h \
+ $$APP_DIR/mainwindow.h \
+ $$APP_DIR/newform.h \
+ $$APP_DIR/plugindialog.h \
+ $$APP_DIR/preferencesdialog.h \
+ $$APP_DIR/qdesigner_actions.h \
+ $$APP_DIR/qdesigner_appearanceoptions.h \
+ $$APP_DIR/qdesigner_formwindow.h \
+ $$APP_DIR/qdesigner.h \
+ $$APP_DIR/qdesigner_pch.h \
+ $$APP_DIR/qdesigner_server.h \
+ $$APP_DIR/qdesigner_settings.h \
+ $$APP_DIR/qdesigner_toolwindow.h \
+ $$APP_DIR/qdesigner_workbench.h \
+ $$APP_DIR/saveformastemplate.h \
+ $$APP_DIR/versiondialog.h
+
+FORMS += $$APP_DIR/plugindialog.ui \
+ $$APP_DIR/preferencesdialog.ui \
+ $$APP_DIR/qdesigner_appearanceoptions.ui \
+ $$APP_DIR/saveformastemplate.ui
+
+# Shared solutions
+SOURCES += ../../shared/fontpanel/fontpanel.cpp \
+ ../../shared/deviceskin/deviceskin.cpp \
+ ../../shared/findwidget/abstractfindwidget.cpp \
+ ../../shared/findwidget/itemviewfindwidget.cpp \
+ ../../shared/findwidget/texteditfindwidget.cpp \
+
+HEADERS += ../../shared/findwidget/abstractfindwidget.h \
+ ../../shared/findwidget/itemviewfindwidget.h \
+ ../../shared/findwidget/texteditfindwidget.h
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/designer_de.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/designer_ja.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/designer_pl.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/designer_tr_TR.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/designer_zh_CN.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/designer_zh_TW.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/designer_untranslated.ts
+
diff --git a/tools/doxygen/config/footer.html b/tools/doxygen/config/footer.html
new file mode 100644
index 0000000000..7efa978225
--- /dev/null
+++ b/tools/doxygen/config/footer.html
@@ -0,0 +1,8 @@
+<p /><address><hr /><div align="center">
+<table width="100%" cellspacing="0" border="0"><tr class="address">
+<td width="30%">Copyright &copy; 2009 Nokia Corporation</td>
+<td width="40%" align="center"><a href="trademarks.html">Trademarks</a></td>
+<td width="30%" align="right"><div align="right">Qt $projectnumber</div></td>
+</tr></table></div></address>
+</body>
+</html>
diff --git a/tools/doxygen/config/header.html b/tools/doxygen/config/header.html
new file mode 100644
index 0000000000..a445b2aa81
--- /dev/null
+++ b/tools/doxygen/config/header.html
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>$title</title>
+ <link href="phonon.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<table border="0" cellpadding="0" cellspacing="0" width="100%">
+<tr>
+<td align="left" valign="top" width="32">
+<a href="http://qtsoftware.com/products/qt"><img src="images/qt-logo.png" align="left" width="32" height="32" border="0" /></a>
+</td>
+<td width="1">&nbsp;&nbsp;</td>
+<td class="postheader" valign="center">
+<a href="index.html">
+<font color="#004faf">Home</font></a>&nbsp;&middot;
+ <a href="classes.html">
+<font color="#004faf">All&nbsp;Classes</font></a>&nbsp;&middot;
+ <a href="mainclasses.html">
+<font color="#004faf">Main&nbsp;Classes</font></a>&nbsp;&middot;
+ <a href="groups.html">
+<font color="#004faf">Grouped&nbsp;Classes</font></a>&nbsp;&middot;
+ <a href="modules.html">
+<font color="#004faf">Modules</font></a>&nbsp;&middot;
+ <a href="functions.html">
+<font color="#004faf">Functions</font></a>
+</td>
+<td align="right" valign="top" width="230"><a href="http://qtsoftware.com"><img src="images/trolltech-logo.png" align="right" width="203" height="32" border="0" /></a></td></tr></table>
diff --git a/tools/doxygen/config/phonon.css b/tools/doxygen/config/phonon.css
new file mode 100644
index 0000000000..fe05e2f609
--- /dev/null
+++ b/tools/doxygen/config/phonon.css
@@ -0,0 +1,114 @@
+h3.fn,span.fn
+{
+ margin-left: 1cm;
+ text-indent: -1cm;
+}
+
+a:link
+{
+ color: #004faf;
+ text-decoration: none
+}
+
+a:visited
+{
+ color: #672967;
+ text-decoration: none
+}
+
+td.postheader
+{
+ font-family: sans-serif
+}
+
+tr.address
+{
+ font-family: sans-serif
+}
+
+body
+{
+ background: #ffffff;
+ color: black
+}
+
+table tr.odd {
+ background: #f0f0f0;
+ color: black;
+}
+
+table tr.even {
+ background: #e4e4e4;
+ color: black;
+}
+
+table.annotated th {
+ padding: 3px;
+ text-align: left
+}
+
+table.annotated td {
+ padding: 3px;
+}
+
+table tr pre
+{
+ padding-top: none;
+ padding-bottom: none;
+ padding-left: none;
+ padding-right: none;
+ border: none;
+ background: none
+}
+
+tr.qt-style
+{
+ background: #a2c511;
+ color: black
+}
+
+body pre
+{
+ padding: 0.2em;
+ border: #e7e7e7 1px solid;
+ background: #f1f1f1;
+ color: black
+}
+
+p code
+{
+ padding: 0.2em;
+ border: #e7e7e7 1px solid;
+ background: #f1f1f1;
+ color: black
+}
+
+h1 {
+ text-align: center
+}
+
+span.preprocessor, span.preprocessor a
+{
+ color: darkblue;
+}
+
+span.comment
+{
+ color: darkred;
+ font-style: italic
+}
+
+span.string,span.char
+{
+ color: darkgreen;
+}
+
+.subtitle
+{
+ font-size: 0.8em
+}
+
+.small-subtitle
+{
+ font-size: 0.65em
+}
diff --git a/tools/doxygen/config/phonon.doxyfile b/tools/doxygen/config/phonon.doxyfile
new file mode 100644
index 0000000000..a190cfa8d1
--- /dev/null
+++ b/tools/doxygen/config/phonon.doxyfile
@@ -0,0 +1,220 @@
+# Doxygen config file for Phonon documentation, adapted from the KDE apidocs
+# config file.
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = Qt
+PROJECT_NUMBER = %VERSION%
+OUTPUT_DIRECTORY = doc
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 4
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+BUILTIN_STL_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = YES
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE = doxygen.log
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = src/3rdparty/kdelibs/phonon
+FILE_PATTERNS = *.cpp \
+ *.h \
+ *.dox
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html-phonon
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = tools/doxygen/config/header.html
+HTML_FOOTER = tools/doxygen/config/footer.html
+HTML_STYLESHEET = tools/doxygen/config/phonon.css
+HTML_ALIGN_MEMBERS = NO
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = NO
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES = doc/indexes/qt.tags
+GENERATE_TAGFILE = doc/indexes/phonon.tags
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+
+
+### KDE Settings
+ALIASES = \
+ "intern=\par<b>Internal use only.</b>" \
+ "reimp=\par<b>Reimplemented from superclass.</b>" \
+ "obsolete=@deprecated" \
+ "feature=\xrefitem features \"Feature(s)\" \"Features\"" \
+ "maintainer=\xrefitem maintainers \"Maintainer(s)\" \"Maintainers\"" \
+ "unmaintained=\xrefitem unmaintained \"Unmaintained\" \"Unmaintained\"" \
+ "requirement=\xrefitem requirements \"Requirement(s)\" \"Requirements\"" \
+ "faq=\xrefitem FAQ \"F.A.Q.\" \"F.A.Q.\"" \
+ "authors=\xrefitem authors \"Author(s)\" \"Authors\"" \
+ "maintainers=\xrefitem maintainers \"Maintainer(s)\" \"Maintainers\"" \
+ "port4=\xrefitem port4 \"KDE 4 Porting Guide\" \"KDE 4 Porting Guide\"" \
+ "glossary=\xrefitem glossary \"KDE 4 Glossary\" \"KDE 4 Glossary\"" \
+ "acronym=\b "\
+ "licenses=\xrefitem licenses \"License(s)\" \"Licenses\"" \
+ "short=@brief "\
+ "FIXME=\xrefitem fixme \"Fixme\" \"Fixme\"" \
+ "bc=\xrefitem bc \"Binary Compatible\" \"Binary Compatible\"" \
+ "artistic=<a href=\"http://www.opensource.org/licenses/artistic-license.php\">Artistic</a>" \
+ "bsd=<a href=\"http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5\">BSD</a>" \
+ "x11=<a href=\"http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3\">X11</a>" \
+ "gpl=<a href=\"http://www.fsf.org/licensing/licenses/gpl.html#SEC1\">GPL</a>" \
+ "lgpl=<a href=\"http://www.fsf.org/licensing/licenses/lgpl.html#SEC1\">LGPL</a>" \
+ "qpl=<a href=\"http://qtsoftware.com/products/qt/licenses\">QPL</a>"
+
diff --git a/tools/installer/README b/tools/installer/README
new file mode 100644
index 0000000000..63abf6d0a7
--- /dev/null
+++ b/tools/installer/README
@@ -0,0 +1,12 @@
+iwmake is the tool used to generate the Qt installer binaries.
+
+To be able to use it yourself create a config.default in the
+config/ directory. You can refer to config.default.sample to see
+which values need to be set within this file.
+
+Afterwards call "iwmake.bat mingw-opensource.conf" to create an
+installer package yourself.
+
+Note that the binary creation takes a lot of time and is very
+CPU-intensive as it recompiles the Qt source package among other
+steps.
diff --git a/tools/installer/batch/build.bat b/tools/installer/batch/build.bat
new file mode 100755
index 0000000000..ee90f92ef8
--- /dev/null
+++ b/tools/installer/batch/build.bat
@@ -0,0 +1,160 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+call :%1 %2
+goto END
+
+:begin
+for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_COMPILER=%%~m& set IWMAKE_TMP=%%~n
+
+if "%IWMAKE_TMP%"=="" set IWMAKE_TMP=build_%IWMAKE_COMPILER%
+set IWMAKE_BUILD=%IWMAKE_ROOT%\%IWMAKE_TMP%
+if not exist %IWMAKE_BUILD% mkdir %IWMAKE_BUILD%
+
+if not "%PATH%"=="" set IWMAKE_OLD_PATH=%PATH%
+if not "%QMAKESPEC%"=="" set IWMAKE_OLD_QMAKESPEC=%QMAKESPEC%
+if not "%QTDIR%"=="" set IWMAKE_OLD_QTDIR=%QTDIR%
+if not "%INCLUDE%"=="" set IWMAKE_OLD_INCLUDE=%INCLUDE%
+if not "%LIB%"=="" set IWMAKE_OLD_LIB=%LIB%
+
+set PATH=%IWMAKE_BUILD%\bin;%PATH%
+set QTDIR=%IWMAKE_BUILD%
+
+if "%IWMAKE_COMPILER%"=="vs2003" goto VS2003Env
+if "%IWMAKE_COMPILER%"=="vs2002" goto VS2002Env
+if "%IWMAKE_COMPILER%"=="vs2005" goto VS2005Env
+if "%IWMAKE_COMPILER%"=="vc60" goto VC60Env
+if "%IWMAKE_COMPILER%"=="mingw" goto MinGWEnv
+goto :eof
+
+:VS2003Env
+set QMAKESPEC=win32-msvc.net
+if not exist "%VS71COMNTOOLS%vsvars32.bat" echo VS2003 not found >> %IWMAKE_LOGFILE% & exit /b 1
+call "%VS71COMNTOOLS%vsvars32.bat" >> %IWMAKE_LOGFILE%
+set IWMAKE_MAKE=nmake
+goto :eof
+
+:VS2002Env
+set QMAKESPEC=win32-msvc.net
+if not exist "%VSCOMNTOOLS%vsvars32.bat" echo VS2002 not found >> %IWMAKE_LOGFILE% & exit /b 1
+call "%VSCOMNTOOLS%vsvars32.bat" >> %IWMAKE_LOGFILE%
+set IWMAKE_MAKE=nmake
+goto :eof
+
+:VS2005Env
+set QMAKESPEC=win32-msvc2005
+if not exist "%VS80COMNTOOLS%vsvars32.bat" echo VS2005 not found >> %IWMAKE_LOGFILE% & exit /b 1
+call "%VS80COMNTOOLS%vsvars32.bat" >> %IWMAKE_LOGFILE%
+set IWMAKE_MAKE=nmake
+goto :eof
+
+:VC60Env
+set QMAKESPEC=win32-msvc
+if not exist "%ProgramFiles%\Microsoft Visual Studio\VC98\Bin\vcvars32.bat" echo VC60 not found >> %IWMAKE_LOGFILE% & exit /b 1
+call "%ProgramFiles%\Microsoft Visual Studio\VC98\Bin\vcvars32.bat" >> %IWMAKE_LOGFILE%
+set IWMAKE_MAKE=nmake
+goto :eof
+
+:MinGWEnv
+set QMAKESPEC=win32-g++
+if not exist %IWMAKE_MINGWPATH%\bin\gcc.exe echo MinGW not found in %IWMAKE_MINGWPATH% >> %IWMAKE_LOGFILE% & exit /b 1
+set PATH=%IWMAKE_MINGWPATH%\bin;%PATH%
+set IWMAKE_MAKE=mingw32-make
+goto :eof
+
+:finish
+ if not "%IWMAKE_OLD_PATH%"=="" set PATH=%IWMAKE_OLD_PATH%& set IWMAKE_OLD_PATH=
+ if not "%IWMAKE_OLD_QMAKESPEC%"=="" set QMAKESPEC=%IWMAKE_OLD_QMAKESPEC%& set IWMAKE_OLD_QMAKESPEC=
+ if not "%IWMAKE_OLD_QTDIR%"=="" set QTDIR=%IWMAKE_OLD_QTDIR%& set IWMAKE_OLD_QTDIR=
+ if not "%IWMAKE_OLD_INCLUDE%"=="" set INCLUDE=%IWMAKE_OLD_INCLUDE%& set IWMAKE_OLD_INCLUDE=
+ if not "%IWMAKE_OLD_LIB%"=="" set LIB=%IWMAKE_OLD_LIB%& set IWMAKE_OLD_LIB=
+goto :eof
+
+:configure
+ pushd %IWMAKE_BUILD%
+ configure %~1 >> %IWMAKE_LOGFILE% 2>&1
+ popd
+goto :eof
+
+:bin
+ pushd %IWMAKE_BUILD%
+ %IWMAKE_MAKE% %~1 >>%IWMAKE_LOGFILE% 2>&1
+ popd
+goto :eof
+
+:binInDir
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n
+ pushd %IWMAKE_BUILD%\%IWMAKE_TMP%
+ %IWMAKE_MAKE% %IWMAKE_TMP2% >> %IWMAKE_LOGFILE% 2>&1
+ popd
+goto :eof
+
+:DBPlugins
+ call "%IWMAKE_SCRIPTDIR%\batch\copy.bat" extsync sql
+ set IWMAKE_SQL_OLD_LIB=%LIB%
+ pushd %IWMAKE_BUILD%\src\plugins\sqldrivers\mysql
+ set LIB=%IWMAKE_ROOT%\sql\mysql\lib\debug;%IWMAKE_SQL_OLD_LIB%
+ qmake "INCLUDEPATH+=%IWMAKE_ROOT%\sql\mysql\include" "LIBS+=libmysql.lib ws2_32.lib advapi32.lib user32.lib" >> %IWMAKE_LOGFILE% 2>&1
+ %IWMAKE_MAKE% debug >> %IWMAKE_LOGFILE% 2>&1
+ set LIB=%IWMAKE_ROOT%\sql\mysql\lib\opt;%IWMAKE_SQL_OLD_LIB%
+ qmake "INCLUDEPATH+=%IWMAKE_ROOT%\sql\mysql\include" "LIBS+=libmysql.lib ws2_32.lib advapi32.lib" >> %IWMAKE_LOGFILE% 2>&1
+ %IWMAKE_MAKE% release >> %IWMAKE_LOGFILE% 2>&1
+ popd
+
+ set LIB=%IWMAKE_ROOT%\sql\%IWMAKE_COMPILER%;%IWMAKE_SQL_OLD_LIB%
+ pushd %IWMAKE_BUILD%\src\plugins\sqldrivers\psql
+ qmake "INCLUDEPATH+=%IWMAKE_ROOT%\sql\include\psql" "LIBS+=libpqd.lib ws2_32.lib advapi32.lib shfolder.lib shell32.lib" >> %IWMAKE_LOGFILE% 2>&1
+ %IWMAKE_MAKE% debug >> %IWMAKE_LOGFILE% 2>&1
+ qmake "INCLUDEPATH+=%IWMAKE_ROOT%\sql\include\psql" "LIBS+=libpq.lib ws2_32.lib advapi32.lib shfolder.lib shell32.lib" >> %IWMAKE_LOGFILE% 2>&1
+ %IWMAKE_MAKE% release >> %IWMAKE_LOGFILE% 2>&1
+ popd
+ set LIB=%IWMAKE_SQL_OLD_LIB%
+ set IWMAKE_SQL_OLD_LIB=
+goto :eof
+
+:root
+ set IWMAKE_BUILD=%~1
+ if not exist %IWMAKE_BUILD% mkdir %IWMAKE_BUILD%
+goto :eof
+
+:END
diff --git a/tools/installer/batch/copy.bat b/tools/installer/batch/copy.bat
new file mode 100755
index 0000000000..0fcb5a6820
--- /dev/null
+++ b/tools/installer/batch/copy.bat
@@ -0,0 +1,124 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+call :%1 %2
+goto END
+
+:dest
+ set IWMAKE_OUTDIR=%IWMAKE_ROOT%\%~1
+ if not exist %IWMAKE_OUTDIR% mkdir %IWMAKE_OUTDIR%
+goto :eof
+
+:src
+ set IWMAKE_SRCDIR=%IWMAKE_ROOT%\%~1
+ if not exist %IWMAKE_SRCDIR% mkdir %IWMAKE_SRCDIR%
+goto :eof
+
+:destAbs
+ set IWMAKE_OUTDIR=%1
+ if not exist %IWMAKE_OUTDIR% mkdir %IWMAKE_OUTDIR%
+goto :eof
+
+:srcAbs
+ set IWMAKE_SRCDIR=%1
+ if not exist %IWMAKE_SRCDIR% mkdir %IWMAKE_SRCDIR%
+goto :eof
+
+:extsync
+ if exist %IWMAKE_ROOT%\%~1 rd /S /Q %IWMAKE_ROOT%\%~1 >> %IWMAKE_LOGFILE%
+ xcopy /H /Y /Q /I /R /E %IWMAKE_EXTERNAL%\%~1 %IWMAKE_ROOT%\%~1 >> %IWMAKE_LOGFILE%
+goto :eof
+
+:all
+ xcopy /H /Y /Q /I /R /S %IWMAKE_SRCDIR%\%~1 %IWMAKE_OUTDIR%\ >> %IWMAKE_LOGFILE%
+goto :eof
+
+:filesEx
+ for /F "tokens=1,2*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n& set IWMAKE_TMP3=%%~o
+ echo %IWMAKE_TMP3% > %IWMAKE_ROOT%\iwmake_exclude
+ xcopy /H /Y /Q /I /R /S /EXCLUDE:%IWMAKE_ROOT%\iwmake_exclude %IWMAKE_SRCDIR%\%IWMAKE_TMP% %IWMAKE_OUTDIR%\%IWMAKE_TMP2% >> %IWMAKE_LOGFILE%
+goto :eof
+
+:file
+ set IWMAKE_TMP=%~1
+ set IWMAKE_TMP2=%~nx1
+ echo set IWMAKE_TMP3=%%IWMAKE_TMP:%IWMAKE_TMP2%=%%>"%IWMAKE_ROOT%\iwmake_tmp.bat"
+ call %IWMAKE_ROOT%\iwmake_tmp.bat
+ if not exist "%IWMAKE_OUTDIR%\%IWMAKE_TMP3%" mkdir "%IWMAKE_OUTDIR%\%IWMAKE_TMP3%"
+ xcopy /H /Y /Q /I /R %IWMAKE_SRCDIR%\%IWMAKE_TMP% %IWMAKE_OUTDIR%\%IWMAKE_TMP3% >> %IWMAKE_LOGFILE%
+goto :eof
+
+:fileAndRename
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n& set IWMAKE_TMP4=%%~nxn
+ echo set IWMAKE_TMP3=%%IWMAKE_TMP2:%IWMAKE_TMP4%=%%>"%IWMAKE_ROOT%\iwmake_tmp.bat"
+ call %IWMAKE_ROOT%\iwmake_tmp.bat
+ if not exist "%IWMAKE_OUTDIR%\%IWMAKE_TMP3%" mkdir "%IWMAKE_OUTDIR%\%IWMAKE_TMP3%"
+ echo > %IWMAKE_OUTDIR%\%IWMAKE_TMP2%
+ xcopy /H /Y /Q /R %IWMAKE_SRCDIR%\%IWMAKE_TMP% %IWMAKE_OUTDIR%\%IWMAKE_TMP2% >> %IWMAKE_LOGFILE%
+ set IWMAKE_TMP4=
+goto :eof
+
+:files
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n
+ if not exist "%IWMAKE_OUTDIR%\%IWMAKE_TMP2%" mkdir "%IWMAKE_OUTDIR%\%IWMAKE_TMP2%"
+ xcopy /H /Y /Q /I /R /S %IWMAKE_SRCDIR%\%IWMAKE_TMP% %IWMAKE_OUTDIR%\%IWMAKE_TMP2% >> %IWMAKE_LOGFILE%
+goto :eof
+
+:runtime
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n
+ if "%IWMAKE_TMP2%" == "" set IWMAKE_TMP2=bin
+ xcopy /H /Y /Q /I /R %SystemRoot%\system32\msvcr%IWMAKE_TMP%.dll %IWMAKE_OUTDIR%\%IWMAKE_TMP2%\ >> %IWMAKE_LOGFILE%
+ xcopy /H /Y /Q /I /R %SystemRoot%\system32\msvcp%IWMAKE_TMP%.dll %IWMAKE_OUTDIR%\%IWMAKE_TMP2%\ >> %IWMAKE_LOGFILE%
+goto :eof
+
+:syncqt
+ pushd %IWMAKE_OUTDIR%
+ if exist "include" rd /S /Q include
+ if not "%QTDIR%"=="" set IWMAKE_OLD_QTDIR=%QTDIR%
+ set QTDIR=%IWMAKE_OUTDIR%
+ "%IWMAKE_PERLPATH%\perl" %QTDIR%\bin\syncqt -copy >> %IWMAKE_LOGFILE% 2>&1
+ if not "%IWMAKE_OLD_QTDIR%"=="" set QTDIR=%IWMAKE_OLD_QTDIR%
+ popd
+goto :eof
+
+:END
diff --git a/tools/installer/batch/delete.bat b/tools/installer/batch/delete.bat
new file mode 100755
index 0000000000..1174cde32f
--- /dev/null
+++ b/tools/installer/batch/delete.bat
@@ -0,0 +1,76 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+call :%1 %2
+goto END
+
+:destDir
+ if exist "%IWMAKE_OUTDIR%\%~1" rd /S /Q %IWMAKE_OUTDIR%\%~1
+goto :eof
+
+:dir
+ if exist "%IWMAKE_ROOT%\%~1" rd /S /Q %IWMAKE_ROOT%\%~1
+goto :eof
+
+:dirAbs
+ if exist "%~1" rd /S /Q %~1
+goto :eof
+
+:file
+ del /Q /F %IWMAKE_OUTDIR%\%~1 >> %IWMAKE_LOGFILE% 2>&1
+ exit /b 0
+goto :eof
+
+:files
+ del /S /Q /F %IWMAKE_OUTDIR%\%~1 >> %IWMAKE_LOGFILE% 2>&1
+ exit /b 0
+goto :eof
+
+:line
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n
+ if exist "%IWMAKE_ROOT%\tmp_line.txt" del /Q /F "%IWMAKE_ROOT%\tmp_line.txt" >> %IWMAKE_LOGFILE%
+ type "%IWMAKE_ROOT%\%IWMAKE_TMP%" | find /V "%IWMAKE_TMP2%" >> "%IWMAKE_ROOT%\tmp_line.txt"
+ xcopy /Y /Q /R %IWMAKE_ROOT%\tmp_line.txt %IWMAKE_ROOT%\%IWMAKE_TMP% >> %IWMAKE_LOGFILE%
+goto :eof
+
+:END
diff --git a/tools/installer/batch/env.bat b/tools/installer/batch/env.bat
new file mode 100755
index 0000000000..cbea4f5b9d
--- /dev/null
+++ b/tools/installer/batch/env.bat
@@ -0,0 +1,144 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+call :%1 %2
+goto END
+
+:setglobals
+set IWMAKE_PARSESECTION=1
+set IWMAKE_MINGWPATH=c:\MinGW\bin
+set IWMAKE_STARTDIR=%CD%
+set IWMAKE_NSISCONF=%IWMAKE_SCRIPTDIR%\nsis\config.nsh
+set IWMAKE_ROOT=c:\package
+set IWMAKE_OUTDIR=%IWMAKE_ROOT%
+set IWMAKE_SRCDIR=%IWMAKE_ROOT%
+set IWMAKE_EXTRACTDEST=%IWMAKE_ROOT%
+set IWMAKE_NSISPATH=%PROGRAMFILES%\NSIS
+call %IWMAKE_SCRIPTDIR%\batch\log.bat fileAbs "%IWMAKE_STARTDIR%\log.txt"
+goto :eof
+
+:signPath
+ set IWMAKE_SIGNPATH=%~1
+goto :eof
+
+:wgetPath
+ set IWMAKE_WGET=%~1
+goto :eof
+
+:wgetDir
+ set IWMAKE_WGET=%IWMAKE_ROOT%\%~1
+goto :eof
+
+:NSISPath
+ set IWMAKE_NSISPATH=%~1
+goto :eof
+
+:PerlPath
+ set IWMAKE_PERLPATH=%~1
+goto :eof
+
+:MinGWPath
+ set IWMAKE_MINGWPATH=%~1
+goto :eof
+
+:unzipApp
+ set IWMAKE_UNZIPAPP=%~1
+goto :eof
+
+:releaseLocation
+ set IWMAKE_WGETUSER=
+ set IWMAKE_WGETPASS=
+ for /F "tokens=1,2*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& if not "%%~n"=="" set IWMAKE_TMP2=%%~n& if not "%%~o"=="" set IWMAKE_TMP3=%%~o
+ if not "%IWMAKE_TMP2%"=="" set IWMAKE_WGETUSER=--http-user=%IWMAKE_TMP2%
+ if not "%IWMAKE_TMP3%"=="" set IWMAKE_WGETPASS=--http-passwd=%IWMAKE_TMP3%
+ set IWMAKE_RELEASELOCATION=%IWMAKE_TMP%
+goto :eof
+
+:removeglobals
+if not "%IWMAKE_OLD_PATH%"=="" call %IWMAKE_SCRIPTDIR%\batch\build.bat finish
+set IWMAKE_RELEASELOCATION=
+set IWMAKE_NSISPATH=
+set IWMAKE_SECTION=
+set IWMAKE_WGET=
+set IWMAKE_WGETUSER=
+set IWMAKE_WGETPASS=
+set IWMAKE_UNZIPAPP=
+set IWMAKE_MINGWPATH=
+set IWMAKE_MAKE=
+set IWMAKE_PERLPATH=
+set IWMAKE_STARTDIR=
+set IWMAKE_SCRIPTDIR=
+set IWMAKE_NSISCONF=
+set IWMAKE_RESULT=
+set IWMAKE_TMP=
+set IWMAKE_TMP2=
+set IWMAKE_TMP3=
+set IWMAKE_STATUS=
+set IWMAKE_LOGFILE=
+set IWMAKE_BUILD=
+set IWMAKE_ROOT=
+set IWMAKE_OUTDIR=
+set IWMAKE_EXTERNAL=
+set IWMAKE_OLD_PATH=
+set IWMAKE_OLD_QMAKESPEC=
+set IWMAKE_OLD_QTDIR=
+set IWMAKE_OLD_INCLUDE=
+set IWMAKE_OLD_LIB=
+set IWMAKE_COMPILER=
+set IWMAKE_SRCDIR=
+set IWMAKE_EXTRACTSRC=
+set IWMAKE_EXTRACTDEST=
+set IWMAKE_PARSESECTION=
+set IWMAKE_OUTPUT_FILE=
+set IWMAKE_SIGNPATH=
+goto :eof
+
+:root
+set IWMAKE_ROOT=%~1
+goto :eof
+
+:extroot
+set IWMAKE_EXTERNAL=%~1
+goto :eof
+
+:END
diff --git a/tools/installer/batch/extract.bat b/tools/installer/batch/extract.bat
new file mode 100755
index 0000000000..59554bc518
--- /dev/null
+++ b/tools/installer/batch/extract.bat
@@ -0,0 +1,86 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+call :%1 %2
+goto END
+
+:dest
+ set IWMAKE_EXTRACTDEST=%IWMAKE_ROOT%\%~1
+goto :eof
+
+:extUnpack
+ set IWMAKE_EXTRACTSRC=%~n1
+ pushd %IWMAKE_ROOT%
+ if exist "%IWMAKE_EXTRACTSRC%.zip" del /Q /F "%IWMAKE_EXTRACTSRC%.zip"
+ %IWMAKE_WGET%\wget %IWMAKE_WGETUSER% %IWMAKE_WGETPASS% %IWMAKE_RELEASELOCATION%/%IWMAKE_EXTRACTSRC%.zip >> %IWMAKE_LOGFILE% 2>&1
+ popd
+ call :unpack "%~1"
+goto :eof
+
+:unpack
+ set IWMAKE_EXTRACTSRC=%~n1
+ pushd %IWMAKE_ROOT%
+ if exist "%IWMAKE_EXTRACTDEST%" rd /S /Q %IWMAKE_EXTRACTDEST% >> %IWMAKE_LOGFILE% 2>&1
+ if exist "%IWMAKE_EXTRACTSRC%" rd /S /Q %IWMAKE_EXTRACTSRC% >> %IWMAKE_LOGFILE% 2>&1
+ %IWMAKE_UNZIPAPP% %IWMAKE_EXTRACTSRC%.zip >> %IWMAKE_LOGFILE%
+ popd
+ move %IWMAKE_ROOT%\%IWMAKE_EXTRACTSRC% %IWMAKE_EXTRACTDEST% >> %IWMAKE_LOGFILE%
+goto :eof
+
+:extPatch
+ pushd %IWMAKE_ROOT%
+ if exist "%~1" del /Q /F "%~1"
+ %IWMAKE_WGET%\wget %IWMAKE_WGETUSER% %IWMAKE_WGETPASS% %IWMAKE_RELEASELOCATION%/%~1 >> %IWMAKE_LOGFILE% 2>&1
+ popd
+ call :patch "%~1"
+goto :eof
+
+:patch
+ pushd %IWMAKE_ROOT%
+ %IWMAKE_UNZIPAPP% %~1 >> %IWMAKE_LOGFILE%
+ popd
+ xcopy /R /I /S /Q /Y %IWMAKE_ROOT%\%IWMAKE_EXTRACTSRC%\*.* %IWMAKE_EXTRACTDEST%\ >> %IWMAKE_LOGFILE%
+ rd /S /Q %IWMAKE_ROOT%\%IWMAKE_EXTRACTSRC% >> %IWMAKE_LOGFILE%
+goto :eof
+
+:END
diff --git a/tools/installer/batch/installer.bat b/tools/installer/batch/installer.bat
new file mode 100755
index 0000000000..c5c51de440
--- /dev/null
+++ b/tools/installer/batch/installer.bat
@@ -0,0 +1,250 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+call :%1 %2
+goto END
+
+:begin
+ call :reset
+ echo !define PRODUCT_NAME "%~1" >> %IWMAKE_NSISCONF%
+ echo !define INSTALL_ROOT "%IWMAKE_ROOT%" >> %IWMAKE_NSISCONF%
+goto :eof
+
+:output
+ set IWMAKE_OUTPUT_FILE=%~1
+ echo !define OUTPUT_FILE "%~1" >> %IWMAKE_NSISCONF%
+goto :eof
+
+:module
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %~1
+ echo !define MODULE_%IWMAKE_RESULT% >> %IWMAKE_NSISCONF%
+goto :eof
+
+:enable
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %~1
+ echo !define USE_%IWMAKE_RESULT:"=% >> %IWMAKE_NSISCONF%
+goto :eof
+
+:disable
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %~1
+ echo !undef USE_%IWMAKE_RESULT:"=% >> %IWMAKE_NSISCONF%
+goto :eof
+
+:startmenu
+ echo !define DEFAULT_STARTMENU_STRING "%~1" >> %IWMAKE_NSISCONF%
+goto :eof
+
+:reset
+ if exist "%IWMAKE_NSISCONF%" del /Q /F "%IWMAKE_NSISCONF%"
+goto :eof
+
+:instdir
+ for /F "tokens=1,2*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n& set IWMAKE_TMP3="%%~o"
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP%
+ echo !define INSTDIR_%IWMAKE_TMP2% %IWMAKE_RESULT:"=% >> "%IWMAKE_NSISCONF%"
+ echo !define INSTDIR_%IWMAKE_TMP2%_TEXT %IWMAKE_TMP3% >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:version
+ echo !define PRODUCT_VERSION "%~1" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:readme
+ echo !define README_FILE "%~1" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:licenseFile
+ echo !define LICENSE_FILE "%~1" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:runfunction
+ echo !define RUN_FUNCTION "%~1" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:readmefunction
+ echo !define README_FUNCTION "%~1" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:welcomenote
+ echo !define WELCOME_NOTE "%~1" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:updateplugins
+ call "%IWMAKE_SCRIPTDIR%\batch\copy.bat" extsync INetLoad
+ xcopy /Q /Y /R "%IWMAKE_ROOT%\INetLoad\INetLoad.dll" "%IWMAKE_NSISPATH%\Plugins\" >> %IWMAKE_LOGFILE%
+:: xcopy /Q /Y /R "%IWMAKE_SCRIPTDIR%\nsis\qtnsisext\qtnsisext.dll" "%IWMAKE_NSISPATH%\Plugins\" >> %IWMAKE_LOGFILE%
+goto :eof
+
+:defineDir
+ for /F "tokens=1,2*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n& set IWMAKE_TMP3=%%~o
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP%
+ set IWMAKE_TMP=%IWMAKE_RESULT%
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP2%
+ set IWMAKE_TMP2=%IWMAKE_RESULT%
+ echo !define MODULE_%IWMAKE_TMP%_%IWMAKE_TMP2% "%IWMAKE_ROOT%\%IWMAKE_TMP3%" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:define
+ for /F "tokens=1,2*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n& set IWMAKE_TMP3="%%~o"
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP%
+ set IWMAKE_TMP=%IWMAKE_RESULT%
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP2%
+ set IWMAKE_TMP2=%IWMAKE_RESULT%
+ if %IWMAKE_TMP3%=="" set IWMAKE_TMP3=
+ echo !define MODULE_%IWMAKE_TMP%_%IWMAKE_TMP2% %IWMAKE_TMP3% >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:src
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP%
+ set IWMAKE_TMP=%IWMAKE_RESULT%
+ set IWMAKE_TMP3="%IWMAKE_ROOT%\%IWMAKE_TMP2%"
+ echo !define MODULE_%IWMAKE_TMP%_ROOT %IWMAKE_TMP3% >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:buildDir
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP%
+ set IWMAKE_TMP=%IWMAKE_RESULT%
+ set IWMAKE_TMP3="%IWMAKE_ROOT%\%IWMAKE_TMP2%"
+ echo !define MODULE_%IWMAKE_TMP%_BUILDDIR %IWMAKE_TMP3% >> "%IWMAKE_NSISCONF%"
+ for /F "eol=- tokens=1,2,3" %%m in ('%SystemRoot%\system32\find "QT_PACKAGEDATE_STR" %IWMAKE_ROOT%\%IWMAKE_TMP2%\src\corelib\global\qglobal.h') do echo !define MODULE_LICENSECHECK_PACKAGEDATE %%o >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:compile
+ call :required
+ pushd %IWMAKE_SCRIPTDIR%\nsis
+ "%IWMAKE_NSISPATH%\makensis.exe" installer.nsi >> %IWMAKE_LOGFILE%
+ popd
+goto :eof
+
+:required
+ call :setrequired PRODUCT_NAME
+ call :setrequired INSTALL_ROOT
+ call :setrequired PRODUCT_VERSION
+ call :setrequired OUTPUT_FILE
+ call :setrequired INSTDIR_0
+ call :setrequired DEFAULT_STARTMENU_STRING
+goto :eof
+
+:setrequired
+ echo !ifndef %1 >> "%IWMAKE_NSISCONF%"
+ echo !error "%1 must be in the .conf file..." >> "%IWMAKE_NSISCONF%"
+ echo !endif >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:makeFileList
+ for /F "tokens=1*" %%m in ("%~1") do set IWMAKE_TMP=%%~m& set IWMAKE_TMP2=%%~n
+ call "%IWMAKE_SCRIPTDIR%\batch\toupper.bat" %IWMAKE_TMP%
+ set IWMAKE_TMP=%IWMAKE_RESULT%
+ set IWMAKE_TMP3="%IWMAKE_ROOT%\%IWMAKE_TMP2%"
+
+
+ echo !macro MODULE_%IWMAKE_TMP%_INSTALLFILES >> "%IWMAKE_NSISCONF%"
+
+ pushd %IWMAKE_TMP3%
+
+ echo set IWMAKE_TMP2=%%IWMAKE_TMP2:%CD%\=%% > "%IWMAKE_ROOT%\iwmake_tmp.bat"
+
+ dir /AD /B /S | %SystemRoot%\system32\sort /R > "%IWMAKE_ROOT%\iwmake_tmp.txt"
+ for /F "tokens=1" %%m in (%IWMAKE_ROOT%\iwmake_tmp.txt) do call :addInstallDirectory "%%m"
+
+
+ dir /A-D /B /S > "%IWMAKE_ROOT%\iwmake_tmp.txt"
+ for /F "tokens=1" %%m in (%IWMAKE_ROOT%\iwmake_tmp.txt) do call :addInstallFile "%%m"
+
+ popd
+ echo !macroend >> "%IWMAKE_NSISCONF%"
+
+
+ echo !macro MODULE_%IWMAKE_TMP%_REMOVE removepath >> "%IWMAKE_NSISCONF%"
+ echo strcmp ${removepath} "" MODULE_%IWMAKE_TMP%_REMOVE_SAFETYLABEL >> "%IWMAKE_NSISCONF%"
+ pushd %IWMAKE_TMP3%
+
+ echo set IWMAKE_TMP2=%%IWMAKE_TMP2:%CD%\=%% > "%IWMAKE_ROOT%\iwmake_tmp.bat"
+
+ dir /A-D /B /S > "%IWMAKE_ROOT%\iwmake_tmp.txt"
+ for /F "tokens=1" %%m in (%IWMAKE_ROOT%\iwmake_tmp.txt) do call :addRemoveFiles "%%m"
+
+ dir /AD /B /S | %SystemRoot%\system32\sort /R > "%IWMAKE_ROOT%\iwmake_tmp.txt"
+ for /F "tokens=1" %%m in (%IWMAKE_ROOT%\iwmake_tmp.txt) do call :addRemoveDirectory "%%m"
+
+ popd
+ echo MODULE_%IWMAKE_TMP%_REMOVE_SAFETYLABEL: >> "%IWMAKE_NSISCONF%"
+ echo !macroend >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:addInstallFile
+ set IWMAKE_TMP2=%~1
+ call "%IWMAKE_ROOT%\iwmake_tmp.bat"
+ echo File "/oname=%IWMAKE_TMP2%" "%~1" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:addInstallDirectory
+ set IWMAKE_TMP2=%~1
+ call "%IWMAKE_ROOT%\iwmake_tmp.bat"
+ echo CreateDirectory "$OUTDIR\%IWMAKE_TMP2%" >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:addRemoveDirectory
+ set IWMAKE_TMP2=%~1
+ call "%IWMAKE_ROOT%\iwmake_tmp.bat"
+ echo RMDir ${removepath}\%IWMAKE_TMP2% >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:addRemoveFiles
+ set IWMAKE_TMP2=%~1
+ call "%IWMAKE_ROOT%\iwmake_tmp.bat"
+ echo Delete ${removepath}\%IWMAKE_TMP2% >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:sign
+ echo Signing Installer ...
+ %IWMAKE_SIGNPATH%\signtool.exe sign /v /t http://timestamp.verisign.com/scripts/timestamp.dll /f "%IWMAKE_SIGNPATH%\keys.pfx" "%IWMAKE_OUTPUT_FILE%" >> %IWMAKE_LOGFILE%
+goto :eof
+
+:openpackage
+ echo !define OPENSOURCE_BUILD >> "%IWMAKE_NSISCONF%"
+goto :eof
+
+:END
diff --git a/tools/installer/batch/log.bat b/tools/installer/batch/log.bat
new file mode 100755
index 0000000000..094df8f799
--- /dev/null
+++ b/tools/installer/batch/log.bat
@@ -0,0 +1,61 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+call :%1 %2
+goto END
+
+:file
+set IWMAKE_LOGFILE=%IWMAKE_ROOT%\%~1
+call :reset
+goto :eof
+
+:fileAbs
+set IWMAKE_LOGFILE=%1
+call :reset
+goto :eof
+
+:reset
+date /T > %IWMAKE_LOGFILE%
+goto :eof
+
+:END
diff --git a/tools/installer/batch/toupper.bat b/tools/installer/batch/toupper.bat
new file mode 100755
index 0000000000..5e19f0f110
--- /dev/null
+++ b/tools/installer/batch/toupper.bat
@@ -0,0 +1,72 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+set IWMAKE_RESULT=%1
+if [%IWMAKE_RESULT%]==[] goto :eof
+set IWMAKE_RESULT=%IWMAKE_RESULT:a=A%
+set IWMAKE_RESULT=%IWMAKE_RESULT:b=B%
+set IWMAKE_RESULT=%IWMAKE_RESULT:c=C%
+set IWMAKE_RESULT=%IWMAKE_RESULT:d=D%
+set IWMAKE_RESULT=%IWMAKE_RESULT:e=E%
+set IWMAKE_RESULT=%IWMAKE_RESULT:f=F%
+set IWMAKE_RESULT=%IWMAKE_RESULT:g=G%
+set IWMAKE_RESULT=%IWMAKE_RESULT:h=H%
+set IWMAKE_RESULT=%IWMAKE_RESULT:i=I%
+set IWMAKE_RESULT=%IWMAKE_RESULT:j=J%
+set IWMAKE_RESULT=%IWMAKE_RESULT:k=K%
+set IWMAKE_RESULT=%IWMAKE_RESULT:l=L%
+set IWMAKE_RESULT=%IWMAKE_RESULT:m=M%
+set IWMAKE_RESULT=%IWMAKE_RESULT:n=N%
+set IWMAKE_RESULT=%IWMAKE_RESULT:o=O%
+set IWMAKE_RESULT=%IWMAKE_RESULT:p=P%
+set IWMAKE_RESULT=%IWMAKE_RESULT:q=Q%
+set IWMAKE_RESULT=%IWMAKE_RESULT:r=R%
+set IWMAKE_RESULT=%IWMAKE_RESULT:s=S%
+set IWMAKE_RESULT=%IWMAKE_RESULT:t=T%
+set IWMAKE_RESULT=%IWMAKE_RESULT:u=U%
+set IWMAKE_RESULT=%IWMAKE_RESULT:v=V%
+set IWMAKE_RESULT=%IWMAKE_RESULT:w=W%
+set IWMAKE_RESULT=%IWMAKE_RESULT:x=X%
+set IWMAKE_RESULT=%IWMAKE_RESULT:y=Y%
+set IWMAKE_RESULT=%IWMAKE_RESULT:z=Z%
+
diff --git a/tools/installer/config/config.default.sample b/tools/installer/config/config.default.sample
new file mode 100644
index 0000000000..c6e79e408c
--- /dev/null
+++ b/tools/installer/config/config.default.sample
@@ -0,0 +1,67 @@
+#############################################################################
+##
+## Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+## Contact: Qt Software Information (qt-info@nokia.com)
+##
+## This file is part of the tools applications of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the either Technology Preview License Agreement or the
+## Beta Release License Agreement.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 2.1 requirements
+## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## In addition, as a special exception, Nokia gives you certain
+## additional rights. These rights are described in the Nokia Qt LGPL
+## Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+## package.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3.0 as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU General Public License version 3.0 requirements will be
+## met: http://www.gnu.org/copyleft/gpl.html.
+##
+## If you are unsure which license is appropriate for your use, please
+## contact the sales department at qt-sales@nokia.com.
+## $QT_END_LICENSE$
+##
+## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+##
+#############################################################################
+
+# root directory
+# Describes the directory where temporary folder, build directory and
+# package will be located at.
+env root "c:\qt_packages"
+
+# where to find all external files
+# To resolve the external dependencies specify a server, where to get
+# required tools like wget, sign, etc.
+env extroot "\\someshare\tools\"
+
+# Location of the installed MinGW to build binaries
+env mingwPath "c:\mingw"
+
+# Location to NSIS package creator
+env NSISPath "%ProgramFiles%\NSIS"
+
+# Location to the install path of PERL
+env perlPath "c:\Perl\bin"
+
+# source package directory
+# Describe the directory where compressed source package is located at.
+# The installer script uses this one for building and creating a package.
+env releaseLocation "http://your.source.server/somepath"
diff --git a/tools/installer/config/mingw-opensource.conf b/tools/installer/config/mingw-opensource.conf
new file mode 100644
index 0000000000..b01c2a1bad
--- /dev/null
+++ b/tools/installer/config/mingw-opensource.conf
@@ -0,0 +1,139 @@
+#############################################################################
+##
+## Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+## Contact: Qt Software Information (qt-info@nokia.com)
+##
+## This file is part of the tools applications of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## No Commercial Usage
+## This file contains pre-release code and may not be distributed.
+## You may use this file in accordance with the terms and conditions
+## contained in the either Technology Preview License Agreement or the
+## Beta Release License Agreement.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 2.1 requirements
+## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## In addition, as a special exception, Nokia gives you certain
+## additional rights. These rights are described in the Nokia Qt LGPL
+## Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+## package.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3.0 as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU General Public License version 3.0 requirements will be
+## met: http://www.gnu.org/copyleft/gpl.html.
+##
+## If you are unsure which license is appropriate for your use, please
+## contact the sales department at qt-sales@nokia.com.
+## $QT_END_LICENSE$
+##
+## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+##
+#############################################################################
+#extracts the package to buildDir
+
+#extract dest "build_mingw_opensource"
+#Section EXTRACT
+#extract extUnpack "qt-win-opensource-src-%VERSION%.zip"
+#SectionEnd
+
+#build the binaries
+#build begin mingw "build_mingw_opensource"
+
+#Section CONFIGURE
+#build configure "-confirm-license -release -plugin-sql-sqlite -qt-libpng -qt-libjpeg"
+#SectionEnd
+
+#Section BUILD
+#build bin
+#SectionEnd
+
+#build finish
+
+# organize release files
+#Section ORGANIZE
+#delete dir "release_mingw_opensource"
+
+#copy dest "release_mingw_opensource"
+#copy src "build_mingw_opensource"
+
+# extract everything once more
+#extract dest "release_mingw_opensource"
+#extract unpack "qt-win-opensource-src-4.4.3.zip"
+
+# qconfig.h
+#copy file "src\corelib\global\qconfig.h"
+#copy file "include\QtCore\qconfig.h"
+#copy file "include\Qt\qconfig.h"
+
+# qconfig.pri
+#copy file "mkspecs\qconfig.pri"
+
+# .qmake.cache
+#copy file ".qmake.cache"
+
+# default mkspec
+#copy files "mkspecs\default\*" "mkspecs\default\"
+
+# copy all binary files
+#copy all "*.a"
+#copy all "*.exe"
+#copy all "*.dll"
+
+# .prl files
+#copy files "lib\*.prl" "lib\"
+
+# remove unused stuff
+#delete files "lib\*.dll"
+
+# copy InetLoad license info
+#copy files "..\INetLoad\Readme.txt" "src\3rdparty\InetLoad\"
+
+#SectionEnd
+
+Section NSIS
+# general installer options
+installer begin "Qt OpenSource"
+installer version "4.4.3"
+installer output "c:\iwmake\qt-win-opensource-4.4.3-mingw.exe"
+installer startmenu "Qt by Nokia v4.4.3 (OpenSource)"
+installer enable component_page
+installer enable directory_page
+installer enable startmenu_page
+installer instdir mingw 0 "Qt Installation Directory"
+installer licenseFile "%IWMAKE_ROOT%\release_mingw_opensource\LICENSE.GPL"
+#installer licenseFile "%IWMAKE_ROOT%\release_mingw_opensource\LICENSE.PREVIEW.OPENSOURCE"
+
+installer runfunction "Run Examples and Demos"
+installer readmefunction "Show Documentation"
+
+installer module registeruiext
+installer module opensource
+
+# mingw options
+installer module mingw
+installer src mingw "release_mingw_opensource"
+installer makeFileList mingw "release_mingw_opensource"
+installer buildDir mingw "build_mingw_opensource"
+installer enable nodirlengthcheck
+
+# public generatable package
+installer openpackage
+
+SectionEnd
+
+# compile the package
+Section NSIS_COMPILE
+installer compile
+SectionEnd
diff --git a/tools/installer/iwmake.bat b/tools/installer/iwmake.bat
new file mode 100755
index 0000000000..ee1158d037
--- /dev/null
+++ b/tools/installer/iwmake.bat
@@ -0,0 +1,127 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+:: Contact: Qt Software Information (qt-info@nokia.com)
+::
+:: This file is part of the tools applications of the Qt Toolkit.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: No Commercial Usage
+:: This file contains pre-release code and may not be distributed.
+:: You may use this file in accordance with the terms and conditions
+:: contained in the either Technology Preview License Agreement or the
+:: Beta Release License Agreement.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 2.1 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 2.1 requirements
+:: will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+::
+:: In addition, as a special exception, Nokia gives you certain
+:: additional rights. These rights are described in the Nokia Qt LGPL
+:: Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+:: package.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 3.0 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU General Public License version 3.0 requirements will be
+:: met: http://www.gnu.org/copyleft/gpl.html.
+::
+:: If you are unsure which license is appropriate for your use, please
+:: contact the sales department at qt-sales@nokia.com.
+:: $QT_END_LICENSE$
+::
+:: This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+:: WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+::
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+rem @echo off
+call :init
+if "%IWMAKE_STATUS%"=="failed" goto FAILED
+if not exist "%IWMAKE_SCRIPTDIR%\config\%1.conf" goto FAILED
+if not "%~2"=="" set IWMAKE_SECTION=%~2
+for /F "eol=# tokens=1,2*" %%i in (%IWMAKE_SCRIPTDIR%\config\config.default) do set IWMAKE_TMP=%%k& call :func_delegate %%i %%j
+if "%IWMAKE_STATUS%"=="failed" goto FAILED
+if exist "%IWMAKE_SCRIPTDIR%\config\config.%COMPUTERNAME%" for /F "eol=# tokens=1,2*" %%i in (%IWMAKE_SCRIPTDIR%\config\config.%COMPUTERNAME%) do set IWMAKE_TMP=%%k& call :func_delegate %%i %%j
+if "%IWMAKE_STATUS%"=="failed" goto FAILED
+call :checkrequirements
+if "%IWMAKE_STATUS%"=="failed" goto FAILED
+for /F "eol=# tokens=1,2*" %%i in (%IWMAKE_SCRIPTDIR%\config\%1.conf) do set IWMAKE_TMP=%%k& call :func_delegate %%i %%j
+if "%IWMAKE_STATUS%"=="failed" goto FAILED
+goto DONE
+
+:func_delegate
+if "%IWMAKE_STATUS%"=="failed" goto :eof
+set IWMAKE_TMP="%IWMAKE_TMP:"=%"
+
+if /i "%1"=="sectionend" echo Leaving Section& set IWMAKE_PARSESECTION=1& goto :eof
+if /i not "%1"=="section" goto callScript
+echo Entering Section %~2
+for %%m in (%IWMAKE_SECTION%) do call :checkSection %%m %~2
+goto :eof
+
+:callScript
+if "%IWMAKE_PARSESECTION%"=="0" goto :eof
+
+call "%IWMAKE_SCRIPTDIR%\batch\%1.bat" %2 %IWMAKE_TMP%
+if not "%errorlevel%"=="0" echo %1 %2 failed! >> %IWMAKE_LOGFILE%& set IWMAKE_STATUS=failed
+goto :eof
+
+:checkSection
+ if /i "%1"=="%2" echo Skipping Section& set IWMAKE_PARSESECTION=0
+goto :eof
+
+:checkrequirements
+ if not exist %IWMAKE_ROOT% mkdir %IWMAKE_ROOT%
+ if not "%IWMAKE_SIGNPATH%"=="" goto CheckSIGNOK
+ call "%IWMAKE_SCRIPTDIR%\batch\copy.bat" extsync sign
+ call "%IWMAKE_SCRIPTDIR%\batch\env.bat" signPath "%IWMAKE_ROOT%\sign"
+:CheckSIGNOK
+ if not "%IWMAKE_WGET%"=="" goto CheckWGETOK
+ call "%IWMAKE_SCRIPTDIR%\batch\copy.bat" extsync wget
+ call "%IWMAKE_SCRIPTDIR%\batch\env.bat" wgetDir wget
+:CheckWGETOK
+ if exist "%IWMAKE_PERLPATH%\perl.exe" goto CheckPerlOK
+ set IWMAKE_STATUS=failed
+ echo Perl not found in %IWMAKE_PERLPATH%! (check your config file)
+:CheckPerlOK
+ if not "%IWMAKE_UNZIPAPP%"=="" goto CheckUNZIPOK
+ call "%IWMAKE_SCRIPTDIR%\batch\copy.bat" extsync unzip
+ call "%IWMAKE_SCRIPTDIR%\batch\env.bat" unzipApp "%IWMAKE_ROOT%\unzip\unzip.exe"
+:CheckUNZIPOK
+ if exist "%IWMAKE_NSISPATH%\makensis.exe" goto CheckNSISOK
+ set IWMAKE_STATUS=failed
+ echo NSIS not found! (check your config file)
+:CheckNSISOK
+ call "%IWMAKE_SCRIPTDIR%\batch\installer.bat" updateplugins
+goto :eof
+
+:init
+ set IWMAKE_SCRIPTDIR=%~dp0
+ set IWMAKE_SCRIPTDIR=%IWMAKE_SCRIPTDIR:~0,-1%
+ call "%IWMAKE_SCRIPTDIR%\batch\env.bat" setglobals
+goto :eof
+
+:cleanup
+ pushd "%IWMAKE_STARTDIR%"
+ call "%IWMAKE_SCRIPTDIR%\batch\env.bat" removeglobals
+ popd
+goto :eof
+
+:FAILED
+ call :cleanup
+ echo Failed!
+goto END
+
+:DONE
+ call :cleanup
+ echo Done!
+goto END
+
+:END
diff --git a/tools/installer/nsis/confirmpage.ini b/tools/installer/nsis/confirmpage.ini
new file mode 100644
index 0000000000..8790e83ea9
--- /dev/null
+++ b/tools/installer/nsis/confirmpage.ini
@@ -0,0 +1,62 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Ini file generated by the HM NIS Edit IO designer.
+[Settings]
+NumFields=2
+
+[Field 1]
+Type=Label
+Text=The following components will be uninstalled:
+Left=1
+Right=298
+Top=1
+Bottom=12
+
+[Field 2]
+Type=Label
+Left=16
+Right=298
+Top=16
+Bottom=136
+
diff --git a/tools/installer/nsis/gwdownload.ini b/tools/installer/nsis/gwdownload.ini
new file mode 100644
index 0000000000..05c5952b1d
--- /dev/null
+++ b/tools/installer/nsis/gwdownload.ini
@@ -0,0 +1,121 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Ini file generated by the HM NIS Edit IO designer.
+[Settings]
+NumFields=9
+
+[Field 1]
+Type=Groupbox
+Text=Find MinGW
+Left=0
+Right=299
+Top=49
+Bottom=91
+
+[Field 2]
+Type=Label
+Text=Please specify a directory where to find MinGW (for instance: C:\\MinGW). If you do not have MinGW installed, you can let the installer download and install it for you.
+Left=2
+Right=298
+Top=1
+Bottom=27
+
+[Field 3]
+Type=DirRequest
+Left=8
+Right=290
+Top=68
+Bottom=81
+
+[Field 4]
+Type=Groupbox
+Text=Download and install MinGW
+Left=0
+Right=299
+Top=94
+Bottom=137
+
+[Field 5]
+Type=Label
+Text=Previously installed MinGW:
+Left=8
+Right=286
+Top=60
+Bottom=68
+
+[Field 6]
+Type=DirRequest
+Left=8
+Right=290
+Top=116
+Bottom=129
+Flags=DISABLED
+
+[Field 7]
+Type=Label
+Text=Installation directory:
+Left=8
+Right=124
+Top=107
+Bottom=115
+Flags=DISABLED
+
+[Field 8]
+Type=Checkbox
+Text=Download and install minimal MinGW installation.
+Left=8
+Right=172
+Top=28
+Bottom=40
+Flags=NOTIFY
+
+[Field 9]
+Type=Link
+Text=(http://www.mingw.org)
+Left=174
+Right=260
+Top=30
+Bottom=38
+State=http://www.mingw.org
+
diff --git a/tools/installer/nsis/gwmirror.ini b/tools/installer/nsis/gwmirror.ini
new file mode 100644
index 0000000000..9525164992
--- /dev/null
+++ b/tools/installer/nsis/gwmirror.ini
@@ -0,0 +1,70 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Ini file generated by the HM NIS Edit IO designer.
+[Settings]
+NumFields=3
+
+[Field 1]
+Type=Label
+Text=Select a mirror where to download MinGW:
+Left=0
+Right=211
+Top=0
+Bottom=8
+
+[Field 2]
+Type=Checkbox
+Text=Download MinGW source code. (You don't need this to compile Qt)
+Left=4
+Right=296
+Top=124
+Bottom=134
+
+[Field 3]
+Type=Listbox
+Left=0
+Right=299
+Top=9
+Bottom=118
+
diff --git a/tools/installer/nsis/images/install.ico b/tools/installer/nsis/images/install.ico
new file mode 100644
index 0000000000..080d82d11f
--- /dev/null
+++ b/tools/installer/nsis/images/install.ico
Binary files differ
diff --git a/tools/installer/nsis/images/qt-header.bmp b/tools/installer/nsis/images/qt-header.bmp
new file mode 100644
index 0000000000..1333cb416e
--- /dev/null
+++ b/tools/installer/nsis/images/qt-header.bmp
Binary files differ
diff --git a/tools/installer/nsis/images/qt-wizard.bmp b/tools/installer/nsis/images/qt-wizard.bmp
new file mode 100644
index 0000000000..4aefd2da4f
--- /dev/null
+++ b/tools/installer/nsis/images/qt-wizard.bmp
Binary files differ
diff --git a/tools/installer/nsis/includes/global.nsh b/tools/installer/nsis/includes/global.nsh
new file mode 100644
index 0000000000..c12401801c
--- /dev/null
+++ b/tools/installer/nsis/includes/global.nsh
@@ -0,0 +1,146 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!include "StrFunc.nsh"
+!include "includes\list.nsh"
+
+${StrCase}
+${StrTrimNewLines}
+${StrStr}
+${StrRep}
+${UnStrRep}
+
+var STARTMENU_STRING
+var PRODUCT_UNIQUE_KEY
+var RUNNING_AS_ADMIN
+
+!ifndef MODULE_MINGW
+ !ifdef MODULE_MSVC_VC60
+ !define INSTALL_COMPILER "vc60"
+ !else
+ !ifdef MODULE_MSVC_VS2002
+ !define INSTALL_COMPILER "vs2002"
+ !else
+ !ifdef MODULE_MSVC_VS2005
+ !define INSTALL_COMPILER "vs2005"
+ !else
+ !define INSTALL_COMPILER "vs2003"
+ !endif
+ !endif
+ !endif
+!else
+ !define INSTALL_COMPILER "mingw"
+!endif
+
+; ADDIN\INTEGRATION
+var VS_VERSION
+var VS_VERSION_SHORT
+var ADDIN_INSTDIR
+var VSIP_INSTDIR
+var HELP_INSTDIR
+var ECLIPSE_INSTDIR
+var QTJAMBIECLIPSE_INSTDIR
+
+; LICENSECHECK
+var LICENSE_KEY
+var LICENSEE
+var LICENSE_PRODUCT
+var LICENSE_FILE
+
+; MSVC
+!ifdef MODULE_MSVC
+ !define MSVC_ValidateDirectory
+ var MSVC_INSTDIR
+!endif
+
+; MINGW
+!ifdef MODULE_MINGW
+ !define MINGW_ValidateDirectory
+ var MINGW_INSTDIR
+!endif
+
+; QSA
+var QSA_INSTDIR
+
+; QTDIR PAGE
+var QTDIR_SELECTED
+var COMPILER_SELECTED
+
+; used by addin7x and vsip
+!ifndef MODULE_VSIP_ROOT
+ !define MODULE_VSIP_ROOT "${INSTALL_ROOT}\vsip"
+!endif
+
+; add to confirm path
+var UninstallerConfirmProduct
+
+Function un.ConfirmOnDelete
+ exch $0
+ push $1
+
+ push "$0"
+ push "$UninstallerConfirmProduct"
+ call un.ItemInList
+ pop $1
+ IntCmp $1 1 ConfirmOnDeleteDone
+
+ strcmp "$UninstallerConfirmProduct" "" 0 +3
+ strcpy $UninstallerConfirmProduct "$0"
+ goto +2
+ strcpy $UninstallerConfirmProduct "$UninstallerConfirmProduct$\r$\n$0"
+
+ ConfirmOnDeleteDone:
+ pop $1
+ pop $0
+FunctionEnd
+
+!macro ConfirmOnRemove REG_KEY PRODUCT_NAME
+ push $0
+ ClearErrors
+ ReadRegDWORD $0 SHCTX "$PRODUCT_UNIQUE_KEY" "${REG_KEY}"
+ intcmp $0 1 0 +3
+ push "${PRODUCT_NAME}"
+ call un.ConfirmOnDelete
+ ClearErrors
+ pop $0
+!macroend \ No newline at end of file
diff --git a/tools/installer/nsis/includes/instdir.nsh b/tools/installer/nsis/includes/instdir.nsh
new file mode 100644
index 0000000000..859b004e06
--- /dev/null
+++ b/tools/installer/nsis/includes/instdir.nsh
@@ -0,0 +1,257 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifndef INSTDIR_1
+ !macro INSTDIR_INITIALIZE
+ !define MUI_DIRECTORYPAGE_VARIABLE $${INSTDIR_0}_INSTDIR
+ !ifdef ${INSTDIR_0}_ValidateDirectory
+ !define MUI_PAGE_CUSTOMFUNCTION_LEAVE "${INSTDIR_0}_ValidateDirectoryFunc"
+ !endif
+ !insertmacro MUI_PAGE_DIRECTORY
+ !macroend
+ !macro INSTDIR_FUNCTIONS
+ !macroend
+ !macro INSTDIR_STARTUP
+ !macroend
+!else
+!macro INSTDIR_INITIALIZE
+ !define INSTDIR_INI_FILE "instdir.ini"
+ !define INSTDIR_0_DIRFIELD "Field 10"
+ !define INSTDIR_0_TEXTFIELD "Field 13"
+ !define INSTDIR_1_DIRFIELD "Field 7"
+ !define INSTDIR_1_TEXTFIELD "Field 11"
+ !define INSTDIR_2_DIRFIELD "Field 5"
+ !define INSTDIR_2_TEXTFIELD "Field 8"
+ !define INSTDIR_3_DIRFIELD "Field 3"
+ !define INSTDIR_3_TEXTFIELD "Field 6"
+ !define INSTDIR_4_DIRFIELD "Field 2"
+ !define INSTDIR_4_TEXTFIELD "Field 4"
+ !define INSTDIR_5_DIRFIELD "Field 9"
+ !define INSTDIR_5_TEXTFIELD "Field 12"
+ !define INSTDIR_DIRHEIGHT 18
+
+ Page custom InitInstDirs UpdateInstDirs
+
+ LangString InstDirLicenseTitle ${LANG_ENGLISH} "Installation Directories"
+ LangString InstDirLicenseTitleDescription ${LANG_ENGLISH} "Select the directories where you want the software installed."
+!macroend
+
+!macro INSTDIR_FUNCTIONS
+ Function InitInstDirs
+ push $0
+ push $1
+ push $2
+ push $3
+
+ !insertmacro MUI_HEADER_TEXT "$(InstDirLicenseTitle)" "$(InstDirLicenseTitleDescription)"
+ strcpy $0 "129"
+
+!ifdef INSTDIR_0
+ SectionGetFlags ${${INSTDIR_0}_SEC01} $1
+!ifdef ${INSTDIR_0}_SEC02
+ SectionGetFlags ${${INSTDIR_0}_SEC02} $3
+ IntOp $1 $1 | $3
+!endif
+ IntOp $2 $1 & 1 ;just care about the first flag
+ StrCpy $1 "READONLY"
+ StrCmp "$2" "1" +2
+ StrCpy $1 "DISABLED"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_0_TEXTFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_0_DIRFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_0_TEXTFIELD}" "Text" "${INSTDIR_0_TEXT}"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_0_DIRFIELD}" "State" $${INSTDIR_0}_INSTDIR
+!else
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_0_DIRFIELD}" "Type" "Unknown"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_0_TEXTFIELD}" "Type" "Unknown"
+ intop $0 $0 - ${INSTDIR_DIRHEIGHT}
+!endif
+!ifdef INSTDIR_1
+ SectionGetFlags ${${INSTDIR_1}_SEC01} $1
+!ifdef ${INSTDIR_1}_SEC02
+ SectionGetFlags ${${INSTDIR_1}_SEC02} $3
+ IntOp $1 $1 | $3
+!endif
+ IntOp $2 $1 & 1 ;just care about the first flag
+ StrCpy $1 "READONLY"
+ StrCmp "$2" "1" +2
+ StrCpy $1 "DISABLED"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_1_TEXTFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_1_DIRFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_1_TEXTFIELD}" "Text" "${INSTDIR_1_TEXT}"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_1_DIRFIELD}" "State" $${INSTDIR_1}_INSTDIR
+!else
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_1_DIRFIELD}" "Type" "Unknown"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_1_TEXTFIELD}" "Type" "Unknown"
+ intop $0 $0 - ${INSTDIR_DIRHEIGHT}
+!endif
+!ifdef INSTDIR_2
+ SectionGetFlags ${${INSTDIR_2}_SEC01} $1
+!ifdef ${INSTDIR_2}_SEC02
+ SectionGetFlags ${${INSTDIR_2}_SEC02} $3
+ IntOp $1 $1 | $3
+!endif
+ IntOp $2 $1 & 1 ;just care about the first flag
+ StrCpy $1 "READONLY"
+ StrCmp "$2" "1" +2
+ StrCpy $1 "DISABLED"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_2_TEXTFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_2_DIRFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_2_TEXTFIELD}" "Text" "${INSTDIR_2_TEXT}"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_2_DIRFIELD}" "State" $${INSTDIR_2}_INSTDIR
+!else
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_2_DIRFIELD}" "Type" "Unknown"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_2_TEXTFIELD}" "Type" "Unknown"
+ intop $0 $0 - ${INSTDIR_DIRHEIGHT}
+!endif
+!ifdef INSTDIR_3
+ SectionGetFlags ${${INSTDIR_3}_SEC01} $1
+!ifdef ${INSTDIR_3}_SEC02
+ SectionGetFlags ${${INSTDIR_3}_SEC02} $3
+ IntOp $1 $1 | $3
+!endif
+ IntOp $2 $1 & 1 ;just care about the first flag
+ StrCpy $1 "READONLY"
+ StrCmp "$2" "1" +2
+ StrCpy $1 "DISABLED"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_3_TEXTFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_3_DIRFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_3_TEXTFIELD}" "Text" "${INSTDIR_3_TEXT}"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_3_DIRFIELD}" "State" $${INSTDIR_3}_INSTDIR
+!else
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_3_DIRFIELD}" "Type" "Unknown"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_3_TEXTFIELD}" "Type" "Unknown"
+ intop $0 $0 - ${INSTDIR_DIRHEIGHT}
+!endif
+!ifdef INSTDIR_4
+ SectionGetFlags ${${INSTDIR_4}_SEC01} $1
+!ifdef ${INSTDIR_4}_SEC02
+ SectionGetFlags ${${INSTDIR_4}_SEC02} $3
+ IntOp $1 $1 | $3
+!endif
+ IntOp $2 $1 & 1 ;just care about the first flag
+ StrCpy $1 "READONLY"
+ StrCmp "$2" "1" +2
+ StrCpy $1 "DISABLED"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_4_TEXTFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_4_DIRFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_4_TEXTFIELD}" "Text" "${INSTDIR_4_TEXT}"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_4_DIRFIELD}" "State" $${INSTDIR_4}_INSTDIR
+!else
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_4_DIRFIELD}" "Type" "Unknown"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_4_TEXTFIELD}" "Type" "Unknown"
+ intop $0 $0 - ${INSTDIR_DIRHEIGHT}
+!endif
+!ifdef INSTDIR_5
+ SectionGetFlags ${${INSTDIR_5}_SEC01} $1
+!ifdef ${INSTDIR_5}_SEC02
+ SectionGetFlags ${${INSTDIR_5}_SEC02} $3
+ IntOp $1 $1 | $3
+!endif
+ IntOp $2 $1 & 1 ;just care about the first flag
+ StrCpy $1 "READONLY"
+ StrCmp "$2" "1" +2
+ StrCpy $1 "DISABLED"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_5_TEXTFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_5_DIRFIELD}" "Flags" "$1"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_5_TEXTFIELD}" "Text" "${INSTDIR_5_TEXT}"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_5_DIRFIELD}" "State" $${INSTDIR_5}_INSTDIR
+!else
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_5_DIRFIELD}" "Type" "Unknown"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "${INSTDIR_5_TEXTFIELD}" "Type" "Unknown"
+ intop $0 $0 - ${INSTDIR_DIRHEIGHT}
+!endif
+
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${INSTDIR_INI_FILE}" "Field 1" "Bottom" "$0"
+ !insertmacro MUI_INSTALLOPTIONS_DISPLAY "${INSTDIR_INI_FILE}"
+
+ pop $3
+ pop $2
+ pop $1
+ pop $0
+ FunctionEnd
+
+ Function UpdateInstDirs
+!ifdef INSTDIR_0
+ !insertmacro MUI_INSTALLOPTIONS_READ $${INSTDIR_0}_INSTDIR "${INSTDIR_INI_FILE}" "${INSTDIR_0_DIRFIELD}" "State"
+ !ifdef ${INSTDIR_0}_ValidateDirectory
+ call ${INSTDIR_0}_ValidateDirectoryFunc
+ !endif
+!endif
+!ifdef INSTDIR_1
+ !insertmacro MUI_INSTALLOPTIONS_READ $${INSTDIR_1}_INSTDIR "${INSTDIR_INI_FILE}" "${INSTDIR_1_DIRFIELD}" "State"
+ !ifdef ${INSTDIR_1}_ValidateDirectory
+ call ${INSTDIR_1}_ValidateDirectoryFunc
+ !endif
+!endif
+!ifdef INSTDIR_2
+ !insertmacro MUI_INSTALLOPTIONS_READ $${INSTDIR_2}_INSTDIR "${INSTDIR_INI_FILE}" "${INSTDIR_2_DIRFIELD}" "State"
+ !ifdef ${INSTDIR_2}_ValidateDirectory
+ call ${INSTDIR_2}_ValidateDirectoryFunc
+ !endif
+!endif
+!ifdef INSTDIR_3
+ !insertmacro MUI_INSTALLOPTIONS_READ $${INSTDIR_3}_INSTDIR "${INSTDIR_INI_FILE}" "${INSTDIR_3_DIRFIELD}" "State"
+ !ifdef ${INSTDIR_3}_ValidateDirectory
+ call ${INSTDIR_3}_ValidateDirectoryFunc
+ !endif
+!endif
+!ifdef INSTDIR_4
+ !insertmacro MUI_INSTALLOPTIONS_READ $${INSTDIR_4}_INSTDIR "${INSTDIR_INI_FILE}" "${INSTDIR_4_DIRFIELD}" "State"
+ !ifdef ${INSTDIR_4}_ValidateDirectory
+ call ${INSTDIR_4}_ValidateDirectoryFunc
+ !endif
+!endif
+!ifdef INSTDIR_5
+ !insertmacro MUI_INSTALLOPTIONS_READ $${INSTDIR_5}_INSTDIR "${INSTDIR_INI_FILE}" "${INSTDIR_5_DIRFIELD}" "State"
+ !ifdef ${INSTDIR_5}_ValidateDirectory
+ call ${INSTDIR_5}_ValidateDirectoryFunc
+ !endif
+!endif
+ FunctionEnd
+!macroend
+
+!macro INSTDIR_STARTUP
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "${INSTDIR_INI_FILE}"
+!macroend
+
+!endif ;ifndef INSTDIR_1 \ No newline at end of file
diff --git a/tools/installer/nsis/includes/list.nsh b/tools/installer/nsis/includes/list.nsh
new file mode 100644
index 0000000000..c553f67e67
--- /dev/null
+++ b/tools/installer/nsis/includes/list.nsh
@@ -0,0 +1,139 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifndef LIST_INCLUDE
+!define LIST_INCLUDE
+
+; usage:
+; push item
+; push list
+; call ItemInList
+; returns 1 or 0
+!macro ItemInList UN
+Function ${UN}ItemInList
+ exch $0 ;list
+ exch
+ exch $1 ;item
+ push $2 ;counter
+ push $3 ;substr
+ push $4 ;char
+
+ strcpy $3 ""
+ strcpy $2 "0"
+
+ loop:
+ strcpy $4 $0 1 $2
+ strcmp "$4" "" atend
+ intop $2 $2 + 1
+
+ strcmp "$4" "|" 0 +4
+ strcmp "$3" "$1" found
+ strcpy $3 "" ;reset substr
+ goto +2
+ strcpy $3 "$3$4" ;append char to substr
+ goto loop
+
+ found:
+ strcpy $0 "1"
+ goto done
+
+ atend:
+ strcmp "$3" "$1" found
+ strcpy $0 "0"
+
+ done:
+ pop $4
+ pop $3
+ pop $2
+ pop $1
+ exch $0
+FunctionEnd
+!macroend
+
+!insertmacro ItemInList ""
+!insertmacro ItemInList "un."
+
+Function GetItemInList
+ exch $0 ;list
+ exch
+ exch $1 ;index
+ push $2 ;counter
+ push $3 ;substr
+ push $4 ;char
+ push $5 ;current index
+
+ strcpy $3 ""
+ strcpy $2 "0"
+ strcpy $5 "1"
+
+ loop:
+ strcpy $4 $0 1 $2
+ strcmp "$4" "" atend
+ intop $2 $2 + 1
+
+ strcmp "$4" "|" 0 +5
+ strcmp "$5" "$1" found
+ strcpy $3 "" ;reset substr
+ intop $5 $5 + 1
+ goto +2
+ strcpy $3 "$3$4" ;append char to substr
+ goto loop
+
+ found:
+ strcpy $0 "$3"
+ goto done
+
+ atend:
+ strcmp "$5" "$1" found
+ strcpy $0 ""
+
+ done:
+ pop $5
+ pop $4
+ pop $3
+ pop $2
+ pop $1
+ exch $0
+FunctionEnd
+
+!endif ;LIST_INCLUDE \ No newline at end of file
diff --git a/tools/installer/nsis/includes/qtcommon.nsh b/tools/installer/nsis/includes/qtcommon.nsh
new file mode 100644
index 0000000000..72a52118db
--- /dev/null
+++ b/tools/installer/nsis/includes/qtcommon.nsh
@@ -0,0 +1,574 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifndef QTCOMMON_INCLUDE
+!define QTCOMMON_INCLUDE
+
+!macro MakeQtDirectory UN
+Function ${UN}MakeQtDirectory
+ exch $0
+
+ push $0
+ push " " #replace
+ push "-" #with
+ call ${UN}ReplaceString
+ pop $0
+
+ push $0
+ push "(" #replace
+ push "" #with
+ call ${UN}ReplaceString
+ pop $0
+
+ push $0
+ push ")" #replace
+ push "" #with
+ call ${UN}ReplaceString
+ pop $0
+
+ exch $0
+FunctionEnd
+!macroend
+!insertmacro MakeQtDirectory ""
+!insertmacro MakeQtDirectory "un."
+
+Function DeleteFloatingLicenseProgram
+ exch $1
+ push $0
+
+ StrCmp $LICENSE_KEY "" end
+
+ ClearErrors
+ !ifndef OPENSOURCE_BUILD
+ qtnsisext::IsFloatingLicense $LICENSE_KEY
+ !endif
+ IfErrors end
+ pop $0
+
+ StrCmp $0 "1" end
+ IfFileExists "$1\bin\qtusagereporter.exe" 0 end
+ Delete "$1\bin\qtusagereporter.exe"
+
+ end:
+ pop $0
+ pop $1
+FunctionEnd
+
+Function AddStartmenuApplication
+ exch $0
+ IfFileExists "$0\assistant.exe" 0 +2
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\Assistant.lnk" "$0\assistant.exe"
+ IfFileExists "$0\designer.exe" 0 +2
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\Designer.lnk" "$0\designer.exe"
+ IfFileExists "$0\linguist.exe" 0 +2
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\Linguist.lnk" "$0\linguist.exe"
+ IfFileExists "$0\qtdemo.exe" 0 +2
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\Examples and Demos.lnk" "$0\qtdemo.exe"
+ IfFileExists "$0\..\README" 0 ReadMeShortCutFinished
+ IfFileExists "$WINDIR\notepad.exe" +3
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\Qt Readme.lnk" "$SYSDIR\notepad.exe" "$0\..\README"
+ goto ReadMeShortCutFinished
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\Qt Readme.lnk" "$WINDIR\notepad.exe" "$0\..\README"
+ ReadMeShortCutFinished:
+ pop $0
+FunctionEnd
+
+Function un.RemoveStartmenuApplication
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\Assistant.lnk"
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\Designer.lnk"
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\Linguist.lnk"
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\Examples and Demos.lnk"
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\Qt Readme.lnk"
+FunctionEnd
+
+#patch the licence information
+Function PatchLicenseInformation
+ exch $0
+ push $1
+ push $2
+
+ DetailPrint "Patching license information..."
+
+ IfFileExists "$0\src\corelib\global\qconfig.h" 0 +3
+ strcpy $2 "$0\src\corelib\global\qconfig.h"
+ goto PatchLicensee
+
+ IfFileExists "$0\include\Qt\qconfig.h" 0 PatchConfigPriFile
+ strcpy $2 "$0\include\Qt\qconfig.h"
+
+ PatchLicensee:
+ push $2
+ push '#define QT_PRODUCT_LICENSEE "'
+ push '#define QT_PRODUCT_LICENSEE "$LICENSEE"$\r$\n'
+ call PatchLine
+
+ push $2
+ push '#define QT_PRODUCT_LICENSE "'
+ push '#define QT_PRODUCT_LICENSE "$LICENSE_PRODUCT"$\r$\n'
+ call PatchLine
+
+ push $2
+ ${StrCase} $1 "$LICENSE_PRODUCT" "U"
+ push '# define QT_EDITION QT_EDITION_'
+ push '# define QT_EDITION QT_EDITION_$1$\r$\n'
+ call PatchLine
+
+ PatchConfigPriFile:
+ IfFileExists "$0\mkspecs\qconfig.pri" 0 PatchLicenseProductDone
+ push "$0\mkspecs\qconfig.pri"
+ push "QT_EDITION = "
+ push "QT_EDITION = $LICENSE_PRODUCT$\r$\n"
+ call PatchLine
+
+ PatchLicenseProductDone:
+ pop $2
+ pop $1
+ pop $0
+FunctionEnd
+
+Function PatchCommonBinaryFiles
+ exch $2
+ push $0
+ push $1
+
+ IfFileExists "$2\bin\qmake.exe" 0 +5
+ DetailPrint "Patching paths in qmake..."
+ push $2
+ push "$2\bin\qmake.exe"
+ call PatchBinaryPaths
+
+ DetailPrint "Patching paths in core..."
+ FindFirst $0 $1 "$2\bin\QtCore*.dll"
+ StrCmp $1 "" ErrorPatching
+ push $2
+ push "$2\bin\$1"
+ call PatchBinaryPaths
+
+ FindNext $0 $1
+ StrCmp $1 "" ErrorPatching
+ push $2
+ push "$2\bin\$1"
+ call PatchBinaryPaths
+
+ ErrorPatching:
+
+ pop $1
+ pop $0
+ pop $2
+FunctionEnd
+
+Function PatchBinaryPaths
+ exch $0
+ exch
+ exch $2
+ push $1
+
+!ifndef OPENSOURCE_BUILD
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_prfxpath=" "qt_prfxpath=$2"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_docspath=" "qt_docspath=$2\doc"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_hdrspath=" "qt_hdrspath=$2\include"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_libspath=" "qt_libspath=$2\lib"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_binspath=" "qt_binspath=$2\bin"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_plugpath=" "qt_plugpath=$2\plugins"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_datapath=" "qt_datapath=$2"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_trnspath=" "qt_trnspath=$2\translations"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_xmplpath=" "qt_xmplpath=$2\examples"
+!ifdef MODULE_LICENSECHECK
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_lcnsuser=" "qt_lcnsuser=$LICENSEE"
+ qtnsisext::PatchBinary /NOUNLOAD $0 "qt_lcnsprod=" "qt_lcnsprod=$LICENSE_PRODUCT"
+!endif
+ qtnsisext::PatchBinary $0 "qt_demopath=" "qt_demopath=$2\demos"
+!endif
+
+ pop $1
+ pop $2
+ pop $0
+FunctionEnd
+
+#patching the prl files
+Function PatchPrlFiles
+ exch $2
+ exch
+ exch $3 ;buildDir
+ push $0
+ push $1
+
+ FindFirst $0 $1 "$2\lib\*.prl"
+ loop:
+ StrCmp $1 "" done
+ DetailPrint "Patching $1..."
+
+ push "$2\lib\$1"
+ push $3
+ push $2
+ call PatchPath
+
+ FindNext $0 $1
+ Goto loop
+ done:
+ pop $1
+ pop $0
+ pop $3
+ pop $2
+FunctionEnd
+
+#
+# patch line in text files
+# push "qtcore4.prl" #Filename
+# push "#define ..." #START WITH
+# push "c:\qt" #REPLACE WITH
+# call PatchLine
+#
+Function PatchLine
+ exch $2 ;replacement line
+ exch 2
+ exch $1 ;Filename
+ exch
+ exch $0 ;start with
+ push $3 ; tmp filename
+ push $4 ; handle (tmp)
+ push $5 ; handle (org)
+ push $6 ; string
+
+ ClearErrors
+ GetTempFileName $3
+ IfErrors done
+ FileOpen $4 $3 w
+ IfErrors done
+ FileOpen $5 $1 r
+ IfErrors done
+
+nextline:
+ FileRead $5 $6
+ IfErrors renameFile
+ push $6
+ push $0
+ push $2
+ call ReplaceLine
+ pop $6
+ FileWrite $4 $6
+ goto nextline
+
+renameFile:
+ FileClose $4
+ FileClose $5
+ SetDetailsPrint none
+ Delete $1
+ Rename $3 $1
+ SetDetailsPrint both
+
+ done:
+ pop $6
+ pop $5
+ pop $4
+ pop $3
+ pop $0
+ pop $1
+ pop $2
+FunctionEnd
+
+#
+# replaces a string that starts with something, with another string
+# push string
+# push "#define ..." #START WITH
+# push "c:\qt" #REPLACE WITH
+# call ReplaceLine
+# pop $0 #new string
+#
+Function ReplaceLine
+ exch $2 ;new line
+ exch 2
+ exch $1 ;string
+ exch
+ exch $0 ;start with
+
+ push $3 ; tmp string
+ push $4 ; counter
+ push $5 ; strlen
+
+ StrCpy $4 "-1"
+ StrLen $5 $1
+
+ loop:
+ IntOp $4 $4 + 1 ;increase counter
+ StrCpy $3 $1 $4 ;get substring
+ IntCmp $4 $5 copystring ; check for end
+ StrCmp $3 $0 done ;start with found
+ goto loop
+
+ copystring:
+ StrCpy $2 $1
+ goto done
+
+ done:
+ pop $5
+ pop $4
+ pop $3
+ pop $0
+ pop $1
+ exch $2
+FunctionEnd
+
+#
+# patch paths in text files
+# push "qtcore4.prl" #Filename
+# push "c:\compile" #OLD_QTDIR
+# push "c:\qt" #QTDIR
+# call PatchPath
+#
+Function PatchPath
+ exch $2 ;NEW
+ exch 2
+ exch $1 ;Filename
+ exch
+ exch $0 ;OLD
+ push $3 ;readline
+ push $4 ;file 1
+ push $5 ;file 2
+ push $6 ;tmpfilename
+
+ push $7 ;forward slash NEW
+ push $8 ;forward slash OLD
+
+ push $2
+ push "\"
+ push "/"
+ call ReplaceString
+ pop $7
+
+ push $0
+ push "\"
+ push "/"
+ call ReplaceString
+ pop $8
+
+ ClearErrors
+ GetTempFileName $6
+ IfErrors done
+ FileOpen $5 $6 w
+ IfErrors done
+ FileOpen $4 $1 r
+ IfErrors done
+
+nextline:
+ FileRead $4 $3
+ IfErrors renameFile
+ push $3
+ push $0
+ push $2
+ call ReplaceString ;replace backward slash path
+ push $8
+ push $7
+ call ReplaceString ;replace forward slash path
+ pop $3
+ FileWrite $5 $3
+ goto nextline
+
+renameFile:
+ FileClose $5
+ FileClose $4
+ SetDetailsPrint none
+ Delete $1
+ Rename $6 $1
+ SetDetailsPrint both
+
+done:
+ pop $8
+ pop $7
+ pop $6
+ pop $5
+ pop $4
+ pop $3
+ pop $0
+ pop $1
+ pop $2
+FunctionEnd
+
+#
+# replaces a string with another string
+# push string
+# push "c:\qt" #replace
+# push "c:\compile" #with
+# call ReplaceString
+# pop $0 #new string
+#
+!macro ReplaceString UN
+Function ${UN}ReplaceString
+ exch $2 ;NEW
+ exch 2
+ exch $1 ;string
+ exch
+ exch $0 ;OLD
+
+ push $3 ; tmp string
+ push $4 ; counter
+ push $5 ; result
+
+ push $6 ; old strlen
+
+ StrCpy $4 "-1"
+ StrCpy $5 ""
+
+ StrLen $6 $0
+
+ loop:
+ IntOp $4 $4 + 1 ;increase counter
+ StrCpy $3 $1 $6 $4 ;get substring
+ StrCmp $3 "" done ; check for end
+ StrCmp $3 $0 replace ;replace if old
+ StrCpy $3 $1 "1" $4
+ StrCpy $5 $5$3 ;append character to result
+ goto loop
+
+ replace:
+ StrCpy $5 $5$2 ;insert new qtdir
+ IntOp $4 $4 + $6 ;increase offset
+ IntOp $4 $4 - 1 ;decrease offset one more
+ goto loop
+
+ done:
+ StrCpy $2 $5
+ pop $6
+ pop $5
+ pop $4
+ pop $3
+ pop $0
+ pop $1
+ exch $2
+FunctionEnd
+!macroend
+!insertmacro ReplaceString ""
+!insertmacro ReplaceString "un."
+
+Function CommonCheckDirectory
+ exch $4
+ exch
+ exch $5
+ push $0
+ push $1
+ push $2
+ push $3
+
+ ; check if qt is already installed
+ IfFileExists "$4\bin\qmake.exe" 0 +2
+ IfFileExists "$4\uninst.exe" qtExistsError
+
+ ; check if directory is empty
+ FindFirst $0 $1 "$4\*"
+ CommonCheckDirectory_FileSearchLoop:
+ StrCmp $1 "" CommonCheckDirectory_DirDoesNotExist
+ StrCmp $1 "." CommonCheckDirectory_ContinueSearchLoop
+ StrCmp $1 ".." CommonCheckDirectory_ContinueSearchLoop
+ goto CommonCheckDirectory_FoundFile
+ CommonCheckDirectory_ContinueSearchLoop:
+ FindNext $0 $1
+ goto CommonCheckDirectory_FileSearchLoop
+
+CommonCheckDirectory_FoundFile:
+ FindClose $0
+ MessageBox MB_YESNO|MB_ICONEXCLAMATION "This directory already has contents. Are you sure you want to use this directory?" IDYES CommonCheckDirectory_DirDoesNotExist
+ Goto errorInDirectory
+CommonCheckDirectory_DirDoesNotExist:
+ FindClose $0
+
+ GetInstDirError $0
+ IntCmp 0 $0 0 instDirError
+
+ StrLen $0 $4
+
+!ifdef USE_NODIRLENGTHCHECK
+ StrCpy $1 "400"
+!else
+ StrLen $1 $5
+!endif
+
+ IntCmp $1 $0 0 directoryToLong
+
+ ;check for spaces
+ StrCpy $2 "-1"
+ StrCpy $3 ""
+
+ loop:
+ IntOp $2 $2 + 1 ;increase counter
+ StrCpy $3 $4 "1" $2 ;get char
+ StrCmp $3 "" directoryOk ; check for end
+ StrCmp $3 " " spaceInDirectory ;check for space
+ goto loop
+
+qtExistsError:
+ MessageBox MB_OK|MB_ICONEXCLAMATION "Qt is already installed in this directory. Please uninstall the previous version and try again."
+ Goto errorInDirectory
+
+instDirError:
+ MessageBox MB_OK|MB_ICONEXCLAMATION "This is not a valid installation directory."
+ Goto errorInDirectory
+
+spaceInDirectory:
+ MessageBox MB_OK|MB_ICONEXCLAMATION "The installation path can't contain spaces."
+ Goto errorInDirectory
+
+directoryToLong:
+ MessageBox MB_OK|MB_ICONEXCLAMATION "The installation directory is to long."
+ Goto errorInDirectory
+
+errorInDirectory:
+ pop $3
+ pop $2
+ pop $1
+ pop $0
+ pop $5
+ pop $4
+ Abort
+ goto done
+
+directoryOk:
+ pop $3
+ pop $2
+ pop $1
+ pop $0
+ pop $5
+ pop $4
+done:
+FunctionEnd
+
+!endif ;QTCOMMON_INCLUDE \ No newline at end of file
diff --git a/tools/installer/nsis/includes/qtenv.nsh b/tools/installer/nsis/includes/qtenv.nsh
new file mode 100644
index 0000000000..9232093797
--- /dev/null
+++ b/tools/installer/nsis/includes/qtenv.nsh
@@ -0,0 +1,306 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifndef QTENV_INCLUDE
+!define QTENV_INCLUDE
+#
+# creates a qtvars.bat file in $QTDIR\bin
+# push "vs2003" #compiler
+# push "c:\qt" #QTDIR
+# call MakeQtVarsFile
+#
+Function MakeQtVarsFile
+ exch $1 ; QTDIR
+ exch
+ exch $3 ; vs version
+ push $0 ; file handle
+ push $2
+ push $4
+
+ push $3
+ call GetMkSpec
+ pop $2
+
+ ClearErrors
+ FileOpen $0 "$1\bin\qtvars.bat" w
+ IfErrors done
+ FileWrite $0 "@echo off$\r$\n"
+ FileWrite $0 "rem$\r$\n"
+ FileWrite $0 "rem This file is generated$\r$\n"
+ FileWrite $0 "rem$\r$\n"
+ FileWrite $0 "$\r$\n"
+ FileWrite $0 "echo Setting up a Qt environment...$\r$\n"
+ FileWrite $0 "echo -- QTDIR set to $1$\r$\n"
+ FileWrite $0 "echo -- Added $1\bin to PATH$\r$\n"
+ FileWrite $0 "echo -- QMAKESPEC set to $2$\r$\n"
+ FileWrite $0 "$\r$\n"
+ FileWrite $0 "set QTDIR=$1$\r$\n"
+ FileWrite $0 "set PATH=$1\bin;%PATH%$\r$\n"
+ FileWrite $0 "set QMAKESPEC=$2$\r$\n"
+
+ call IsExpressVersion
+ pop $4
+ strcmp $4 "" noExpressVersion
+ FileWrite $0 "$\r$\n"
+ FileWrite $0 'regedit /e S$$D$$K$$ "HKEY_LOCAL_MACHINE\Software\Microsoft\MicrosoftSDK"$\r$\n'
+ Filewrite $0 'if not exist S$$D$$K$$ goto ENDSDK\r$\n'
+ FileWrite $0 'find "Install Dir" < S$$D$$K$$ > D$$I$$R$$$\r$\n'
+ FileWrite $0 'del S$$D$$K$$$\r$\n'
+ FileWrite $0 'for /f "tokens=2 delims==" %%i in (D$$I$$R$$) do call %%i\setenv$\r$\n'
+ FileWrite $0 'del D$$I$$R$$$\r$\n'
+ Filewrite $0 ':ENDSDK\r$\n'
+ noExpressVersion:
+
+ push $3
+ call GetVSVarsFile
+ pop $2
+ strcmp $2 "" novsvars
+ FileWrite $0 "$\r$\n"
+ FileWrite $0 'if not "%1"=="vsvars" goto END$\r$\n'
+ FileWrite $0 'call "$2"$\r$\n'
+ FileWrite $0 ":END$\r$\n"
+
+ FileWrite $0 "$\r$\n"
+ FileWrite $0 'if not "%1"=="vsstart" goto ENDSTARTVS$\r$\n'
+ FileWrite $0 'call "$2"$\r$\n'
+
+ strcmp $3 "vc60" vc60startup
+ FileWrite $0 "devenv /useenv$\r$\n"
+ Goto donevsstartup
+ vc60startup:
+ FileWrite $0 "msdev /useenv$\r$\n"
+ donevsstartup:
+
+ FileWrite $0 ":ENDSTARTVS$\r$\n"
+
+ novsvars:
+ FileWrite $0 "$\r$\n"
+ FileClose $0
+ done:
+ pop $4
+ pop $2
+ pop $0
+ pop $3
+ pop $1
+FunctionEnd
+
+Function GetMkSpec
+ exch $0
+ StrCmp $0 "mingw" MINGW
+ StrCmp $0 "vs2005" VS2005
+ StrCmp $0 "vs2003" VS2003
+ StrCmp $0 "vs2002" VS2002
+ StrCmp $0 "vc60" VS60
+ StrCmp $0 "icc" ICC
+
+ MINGW:
+ pop $0
+ push "win32-g++"
+ goto done
+
+ VS2005:
+ pop $0
+ push "win32-msvc2005"
+ goto done
+
+ VS2003:
+ pop $0
+ push "win32-msvc.net"
+ goto done
+
+ VS2002:
+ pop $0
+ push "win32-msvc.net"
+ goto done
+
+ VS60:
+ pop $0
+ push "win32-msvc"
+ goto done
+
+ ICC:
+ pop $0
+ push "win32-icc"
+ goto done
+
+ done:
+FunctionEnd
+
+!define AD_COMPILER_NAME_VS2005 "Visual Studio .NET 2005"
+!define AD_COMPILER_NAME_VS2005_EXPRESS "Visual C++ 2005 Express Edition"
+!define AD_COMPILER_NAME_VS2003 "Visual Studio .NET 2003"
+!define AD_COMPILER_NAME_VS2002 "Visual Studio .NET 2002"
+!define AD_COMPILER_NAME_VC60 "Visual Studio 6.0"
+!define AD_COMPILER_NAME_ICC "Intel C++ Compiler"
+!define AD_COMPILER_NAME_MINGW "MinGW (Must be in PATH!)"
+
+Function GetShortCompilerName
+ exch $0
+
+ strcmp "$0" "${AD_COMPILER_NAME_VS2005}" 0 +3
+ strcpy $0 "vs2005"
+ goto done
+
+ strcmp "$0" "${AD_COMPILER_NAME_VS2005_EXPRESS}" 0 +3
+ strcpy $0 "vs2005"
+ goto done
+
+ strcmp "$0" "${AD_COMPILER_NAME_VS2003}" 0 +3
+ strcpy $0 "vs2003"
+ goto done
+
+ strcmp "$0" "${AD_COMPILER_NAME_VS2002}" 0 +3
+ strcpy $0 "vs2002"
+ goto done
+
+ strcmp "$0" "${AD_COMPILER_NAME_VC60}" 0 +3
+ strcpy $0 "vc60"
+ goto done
+
+ strcmp "$0" "${AD_COMPILER_NAME_ICC}" 0 +3
+ strcpy $0 "icc"
+ goto done
+
+ strcmp "$0" "${AD_COMPILER_NAME_MINGW}" 0 +3
+ strcpy $0 "mingw"
+ goto done
+
+ strcpy $0 "" ;this is bad!
+
+ done:
+ exch $0
+FunctionEnd
+
+Function IsExpressVersion
+ push $0
+ ReadRegStr $0 HKLM "Software\Microsoft\VCExpress\8.0" "InstallDir"
+ ClearErrors
+ exch $0
+FunctionEnd
+
+Function AutoDetectCompilers
+ push $0
+ push $1
+
+ strcpy $1 ""
+
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\8.0" "InstallDir"
+ strcmp $0 "" +2
+ strcpy $1 "$1${AD_COMPILER_NAME_VS2005}|"
+
+ ReadRegStr $0 HKLM "Software\Microsoft\VCExpress\8.0" "InstallDir"
+ strcmp $0 "" +2
+ strcpy $1 "$1${AD_COMPILER_NAME_VS2005_EXPRESS}|"
+
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\7.1" "InstallDir"
+ strcmp $0 "" +2
+ strcpy $1 "$1${AD_COMPILER_NAME_VS2003}|"
+
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\7.0" "InstallDir"
+ strcmp $0 "" +2
+ strcpy $1 "$1${AD_COMPILER_NAME_VS2002}|"
+
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\6.0\Setup" "VsCommonDir"
+ strcmp $0 "" +2
+ strcpy $1 "$1${AD_COMPILER_NAME_VC60}|"
+
+ ReadRegStr $0 HKLM "Software\Intel\Compilers\C++\80" "Major Version"
+ strcmp $0 "" +2
+ strcpy $1 "$1${AD_COMPILER_NAME_ICC}|"
+
+ strcpy $1 "$1${AD_COMPILER_NAME_MINGW}"
+
+ exch
+ pop $0
+ exch $1
+FunctionEnd
+
+Function GetVSVarsFile
+ exch $1
+ push $0
+
+ StrCmp $1 "vs2005" VS2005
+ StrCmp $1 "vs2003" VS2003
+ StrCmp $1 "vs2002" VS2002
+ StrCmp $1 "vc60" VS60
+
+ push "" ;empty string if not found
+ goto done
+
+ VS2005:
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\8.0\Setup\VS" "ProductDir"
+ StrCmp $0 "" +1 foundVSDir ; found msvc.net 2005
+
+ ReadRegStr $0 HKLM "Software\Microsoft\VCExpress\8.0\Setup\VS" "ProductDir"
+ StrCmp $0 "" +1 foundVSDir ; found msvc.net 2005 epress
+
+ VS2003:
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\7.1\Setup\VS" "ProductDir"
+ StrCmp $0 "" +1 foundVSDir ; found msvc.net 2003
+
+ VS2002:
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\7.0\Setup\VS" "ProductDir"
+ StrCmp $0 "" +1 foundVSDir ; found msvc.net 2002
+
+ VS60:
+ ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++" "ProductDir"
+ StrCmp $0 "" +1 foundVCDir ; found msvc 6.0
+
+ push "" ;empty string if not found
+ goto done
+
+ foundVSDir:
+ push "$0\Common7\Tools\vsvars32.bat"
+ goto done
+
+ foundVCDir:
+ push "$0\bin\vcvars32.bat"
+
+ done:
+ exch
+ pop $0
+ exch
+ pop $1
+FunctionEnd
+
+!endif ;QTENV_INCLUDE
diff --git a/tools/installer/nsis/includes/system.nsh b/tools/installer/nsis/includes/system.nsh
new file mode 100644
index 0000000000..f7cbec4ac9
--- /dev/null
+++ b/tools/installer/nsis/includes/system.nsh
@@ -0,0 +1,272 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifndef SYSTEM_INCLUDE
+!define SYSTEM_INCLUDE
+
+!define QTVSIP2003_GUID "{789202F4-94F5-4f0a-AA00-73295FEBFD68}"
+!define QTVSIP2005_GUID "{789202F4-94F5-4f0a-AA00-73295FEBFD69}"
+
+!define QMSNET2002_GUID "{C174ACCD-D856-4B60-9887-0FF9E841E0EC}"
+!define QMSNET2003_GUID "{C174ACCE-D857-4B61-9888-0FF9E841E0ED}"
+!define QMSNET2005_GUID "{14E98DB4-A232-49a4-8EC1-8CE4F6985C73}"
+
+!macro GetVSInstallationDir UN
+; Usage:
+;
+; push "7.0"
+; call GetVSInstallationDir
+; pop $0
+;
+; If the requested VS version can be found, its
+; installation directory is returned.
+Function ${UN}GetVSInstallationDir
+ Exch $0
+ Push $1
+ ReadRegStr $1 HKLM "Software\Microsoft\VisualStudio\$0" "InstallDir"
+ StrCpy $0 $1
+ StrCmp $0 "" 0 +2
+ SetErrors
+ Pop $1
+ Exch $0
+FunctionEnd
+!macroend
+
+!insertmacro GetVSInstallationDir ""
+!insertmacro GetVSInstallationDir "un."
+
+
+!macro IsDotNETInstalled UN
+; Usage:
+;
+; push "8.0"
+; call IsDotNETInstalled
+; pop $0
+;
+; $0 contains the path where the .NET framework is installed.
+; If not installation can be found $0 is empty.
+Function ${UN}IsDotNETInstalled
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+
+ StrCpy $5 $0
+
+ ReadRegStr $4 HKEY_LOCAL_MACHINE "Software\Microsoft\.NETFramework" "InstallRoot"
+ Push $4
+ Exch $EXEDIR
+ Exch $EXEDIR
+ Pop $4
+
+ IfFileExists $4 0 noDotNET
+ StrCpy $0 0
+
+ EnumStart:
+ EnumRegKey $2 HKEY_LOCAL_MACHINE "Software\Microsoft\.NETFramework\Policy" $0
+ IntOp $0 $0 + 1
+ StrCmp $2 "" noDotNET
+ StrCpy $1 0
+
+ EnumPolicy:
+ EnumRegValue $3 HKEY_LOCAL_MACHINE "Software\Microsoft\.NETFramework\Policy\$2" $1
+ IntOp $1 $1 + 1
+ StrCmp $3 "" EnumStart
+
+ StrCmp $5 "8.0" 0 +2
+ StrCmp $2 "v2.0" 0 EnumPolicy
+
+ IfFileExists "$4\$2.$3" foundDotNET EnumPolicy
+
+ noDotNET:
+ StrCpy $0 0
+ Goto done
+
+ foundDotNET:
+ StrCpy $0 "$4\$2.$3"
+
+ done:
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+FunctionEnd
+!macroend
+
+!insertmacro IsDotNETInstalled ""
+!insertmacro IsDotNETInstalled "un."
+
+!macro IsQMsNetInstalled UN
+; Usage:
+;
+; push "8.0"
+; call IsQMsNetInstalled
+; pop $0
+Function ${UN}IsQMsNetInstalled
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+
+ StrCmp $0 "7.0" 0 +2
+ StrCpy $2 "${QMSNET2002_GUID}"
+ StrCmp $0 "7.1" 0 +2
+ StrCpy $2 "${QMSNET2003_GUID}"
+ StrCmp $0 "8.0" 0 +2
+ StrCpy $2 "${QMSNET2005_GUID}"
+
+ StrCpy $3 0
+
+ ReadRegStr $1 HKLM "SOFTWARE\Microsoft\VisualStudio\$0\NewProjectTemplates\TemplateDirs\$2\/2" "TemplatesDir"
+ StrCmp $1 "" +3
+ StrCpy $3 1
+ goto done
+
+ ReadRegStr $1 HKCU "SOFTWARE\Microsoft\VisualStudio\$0\NewProjectTemplates\TemplateDirs\$2\/2" "TemplatesDir"
+ StrCmp $1 "" +2
+ StrCpy $3 1
+
+done:
+ StrCpy $0 $3
+
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+FunctionEnd
+!macroend
+
+!insertmacro IsQMsNetInstalled ""
+!insertmacro IsQMsNetInstalled "un."
+
+!macro IsQMsDevInstalled UN
+; Usage:
+;
+; call IsQMsDevInstalled
+; pop $0
+Function ${UN}IsQMsDevInstalled
+ Push $0
+ Push $1
+ Push $2
+
+ StrCpy $0 0
+
+ ReadRegStr $1 HKLM "SOFTWARE\Microsoft\DevStudio\6.0\AddIns\q4msdev.Q4MsDev.1" "Filename"
+ StrCmp $1 "" +3
+ StrCpy $0 1
+ goto done
+
+ ReadRegStr $1 HKCU "SOFTWARE\Microsoft\DevStudio\6.0\AddIns\q4msdev.Q4MsDev.1" "Filename"
+ StrCmp $1 "" +2
+ StrCpy $0 1
+
+done:
+ Pop $2
+ Pop $1
+ Exch $0
+FunctionEnd
+!macroend
+
+!insertmacro IsQMsDevInstalled ""
+!insertmacro IsQMsDevInstalled "un."
+
+!macro IsIntegrationInstalled UN
+; Usage:
+;
+; push "8.0"
+; call IsIntegrationInstalled
+; pop $0
+Function ${UN}IsIntegrationInstalled
+ Exch $0
+ Push $1
+ Push $2
+
+ StrCmp $0 "7.1" 0 +2
+ StrCpy $2 "${QTVSIP2003_GUID}"
+ StrCmp $0 "8.0" 0 +2
+ StrCpy $2 "${QTVSIP2005_GUID}"
+
+ ReadRegStr $1 HKLM "SOFTWARE\Microsoft\VisualStudio\$0\Packages\$2" "ProductName"
+
+ StrCpy $0 0
+ StrCmp $1 "" done
+ StrCpy $0 1
+
+done:
+ Pop $2
+ Pop $1
+ Exch $0
+FunctionEnd
+!macroend
+
+!insertmacro IsIntegrationInstalled ""
+!insertmacro IsIntegrationInstalled "un."
+
+!macro AdministratorRights UN
+Function ${UN}HasAdminRights
+ push $0
+ ClearErrors
+ UserInfo::GetAccountType
+ IfErrors Yes ;It's probably Win95
+ pop $0
+ StrCmp $0 "Admin" Yes
+ StrCmp $0 "Power" Yes
+
+ StrCpy $0 "false"
+ goto Done
+
+ Yes:
+ StrCpy $0 "true"
+
+ Done:
+ exch $0
+FunctionEnd
+!macroend
+!insertmacro AdministratorRights ""
+!insertmacro AdministratorRights "un."
+
+!endif ;SYSTEM_INCLUDE \ No newline at end of file
diff --git a/tools/installer/nsis/installer.nsi b/tools/installer/nsis/installer.nsi
new file mode 100644
index 0000000000..c077850cc7
--- /dev/null
+++ b/tools/installer/nsis/installer.nsi
@@ -0,0 +1,527 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Script generated by the HM NIS Edit Script Wizard.
+
+!include "config.nsh"
+!include "includes\global.nsh"
+
+!define PRODUCT_PUBLISHER "Nokia Corporation and/or its subsidiary(-ies)"
+!define PRODUCT_WEB_SITE "http://qtsoftware.com"
+
+!define INSTALL_ICON "images\install.ico"
+!define WELCOME_PAGE_ICON "images\qt-wizard.bmp"
+!define PAGE_HEADER_ICON "images\qt-header.bmp"
+
+!include "MUI.nsh"
+
+; modules
+!include "modules\mingw.nsh"
+!include "modules\opensource.nsh"
+!include "includes\instdir.nsh"
+!include "modules\environment.nsh"
+!include "modules\registeruiext.nsh"
+!ifndef OPENSOURCE_BUILD
+!include "modules\msvc.nsh"
+!include "modules\addin7x.nsh"
+!include "modules\qsa.nsh"
+!include "modules\addin60.nsh"
+!include "modules\debugext.nsh"
+!include "modules\license.nsh"
+!include "modules\vsip.nsh"
+!include "modules\help.nsh"
+!include "modules\evaluation.nsh"
+!include "modules\eclipse.nsh"
+!include "modules\qtjambieclipse.nsh"
+!endif
+
+; MUI Settings
+!define MUI_ABORTWARNING
+!define MUI_ICON "${INSTALL_ICON}"
+!define MUI_UNICON "${INSTALL_ICON}"
+
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "${PAGE_HEADER_ICON}"
+!define MUI_HEADERIMAGE_UNBITMAP "${PAGE_HEADER_ICON}"
+
+!define MUI_WELCOMEFINISHPAGE_BITMAP "${WELCOME_PAGE_ICON}"
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${WELCOME_PAGE_ICON}"
+
+!ifdef WELCOME_NOTE
+ !define MUI_WELCOMEPAGE_TEXT "${WELCOME_NOTE}"
+!endif
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro OPENSOURCE_INITIALIZE
+!ifndef OPENSOURCE_BUILD
+!insertmacro EVALUATION_INITIALIZE
+!insertmacro LICENSECHECK_INITIALIZE
+!insertmacro MSVC_INITIALIZE
+!insertmacro ADDIN7X_INITIALIZE
+!insertmacro ADDIN60_INITIALIZE
+!insertmacro DEBUGEXT_INITIALIZE
+!insertmacro HELP_INITIALIZE
+!insertmacro VSIP_INITIALIZE
+!endif
+
+!ifdef USE_COMPONENT_PAGE
+ !insertmacro MUI_PAGE_COMPONENTS
+!endif
+
+!ifdef USE_DIRECTORY_PAGE
+ !insertmacro INSTDIR_INITIALIZE
+!endif
+
+!ifdef USE_STARTMENU_PAGE
+ !define MUI_STARTMENUPAGE_NODISABLE
+ !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${DEFAULT_STARTMENU_STRING}"
+ !insertmacro MUI_PAGE_STARTMENU 1 $STARTMENU_STRING
+!endif
+
+!insertmacro MINGW_INITIALIZE
+!insertmacro ENVIRONMENT_INITIALIZE
+!insertmacro REGISTERUIEXT_INITIALIZE
+!ifndef OPENSOURCE_BUILD
+!insertmacro QSA_INITIALIZE
+!insertmacro ECLIPSE_INITIALIZE
+!insertmacro QTJAMBIECLIPSE_INITIALIZE
+!endif
+
+!define MUI_FINISHPAGE_NOAUTOCLOSE
+
+!insertmacro MUI_PAGE_INSTFILES
+!ifdef README_FILE
+ !define MUI_FINISHPAGE_SHOWREADME ${README_FILE}
+!else
+ !ifdef README_FUNCTION
+ !define MUI_FINISHPAGE_SHOWREADME
+ !define MUI_FINISHPAGE_SHOWREADME_TEXT "${README_FUNCTION}"
+ !define MUI_FINISHPAGE_SHOWREADME_FUNCTION "CommonReadmeFunction"
+ !endif
+!endif
+!ifdef RUN_FUNCTION
+ !define MUI_FINISHPAGE_RUN
+ !define MUI_FINISHPAGE_RUN_TEXT "${RUN_FUNCTION}"
+ !define MUI_FINISHPAGE_RUN_FUNCTION "CommonRunFunction"
+!endif
+!insertmacro MUI_PAGE_FINISH
+
+!insertmacro MUI_UNPAGE_WELCOME
+!define UNINSTALLER_CONFIRM_PAGE "confirmpage.ini"
+UninstPage custom un.UninstallerConfirmPage
+!insertmacro MUI_UNPAGE_INSTFILES
+
+!insertmacro MUI_UNPAGE_FINISH
+
+!insertmacro MUI_LANGUAGE "English"
+
+Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
+OutFile ${OUTPUT_FILE}
+
+Section -PreCommonSection
+!ifdef INSTDIR_0 ;the default one, must exist
+ strcpy $INSTDIR $${INSTDIR_0}_INSTDIR
+ ${StrRep} $PRODUCT_UNIQUE_KEY "${PRODUCT_NAME} ${PRODUCT_VERSION} - $INSTDIR" "\" "_"
+ strcpy $PRODUCT_UNIQUE_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\$PRODUCT_UNIQUE_KEY"
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_0}_INSTDIR" "$${INSTDIR_0}_INSTDIR"
+!endif
+!ifdef INSTDIR_1
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_1}_INSTDIR" "$${INSTDIR_1}_INSTDIR"
+!endif
+!ifdef INSTDIR_2
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_2}_INSTDIR" "$${INSTDIR_2}_INSTDIR"
+!endif
+!ifdef INSTDIR_3
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_3}_INSTDIR" "$${INSTDIR_3}_INSTDIR"
+!endif
+!ifdef INSTDIR_4
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_4}_INSTDIR" "$${INSTDIR_4}_INSTDIR"
+!endif
+!ifdef INSTDIR_5
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_5}_INSTDIR" "$${INSTDIR_5}_INSTDIR"
+!endif
+
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "StartMenu" "$STARTMENU_STRING"
+ CreateDirectory "$SMPROGRAMS\$STARTMENU_STRING"
+SectionEnd
+
+!insertmacro OPENSOURCE_SECTIONS
+!insertmacro MINGW_SECTIONS
+!insertmacro ENVIRONMENT_SECTIONS
+!insertmacro REGISTERUIEXT_SECTIONS
+!ifndef OPENSOURCE_BUILD
+!insertmacro MSVC_SECTIONS
+!insertmacro ADDIN7X_SECTIONS
+!insertmacro ADDIN60_SECTIONS
+!insertmacro VSIP_SECTIONS
+!insertmacro HELP_SECTIONS
+!insertmacro DEBUGEXT_SECTIONS
+!insertmacro LICENSECHECK_SECTIONS
+!insertmacro QSA_SECTIONS
+!insertmacro EVALUATION_SECTIONS
+!insertmacro ECLIPSE_SECTIONS
+!insertmacro QTJAMBIECLIPSE_SECTIONS
+!endif
+
+!insertmacro INSTDIR_FUNCTIONS
+
+Section -CommonSection
+ WriteUninstaller "$INSTDIR\uninst.exe"
+
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "DisplayName" "$(^Name)"
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "UninstallString" "$INSTDIR\uninst.exe"
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "DisplayVersion" "${PRODUCT_VERSION}"
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "Publisher" "${PRODUCT_PUBLISHER}"
+
+ WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\QtSoftware.com.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\Uninstall ${PRODUCT_NAME} ${PRODUCT_VERSION}.lnk" "$INSTDIR\uninst.exe"
+ SetOutPath "$INSTDIR"
+SectionEnd
+
+Function CheckLocalLicenseProduct
+!ifdef MODULE_LICENSECHECK
+ !insertmacro QSA_CHECKLICENSEPRODUCT
+!endif
+FunctionEnd
+
+Function .onInit
+ StrCpy $STARTMENU_STRING "${DEFAULT_STARTMENU_STRING}"
+
+!ifdef USE_UNINSTALL_PREVIOUS
+ push "${PRODUCT_NAME}"
+ call GetExistsPreviousInstallationOfProduct
+ exch $0
+ StrCmp $0 true 0 +3
+ MessageBox MB_OK|MB_ICONSTOP "A previous installation of ${PRODUCT_NAME} was detected.$\nPlease uninstall it before running this installer."
+ Abort
+ pop $0
+!endif
+
+ call SetAdminVar
+ StrCmp "$RUNNING_AS_ADMIN" "false" 0 common_running_as_admin
+!ifdef USE_ADMIN_CHECK
+ MessageBox MB_OK|MB_ICONSTOP "You need to have administrator rights to install this software!"
+ Abort
+!endif
+ SetShellVarContext current
+ goto common_admin_check_done
+ common_running_as_admin:
+ SetShellVarContext all
+ common_admin_check_done:
+
+ !insertmacro INSTDIR_STARTUP
+
+ !insertmacro OPENSOURCE_STARTUP
+ !insertmacro ENVIRONMENT_STARTUP
+ !insertmacro REGISTERUIEXT_STARTUP
+ !insertmacro MINGW_STARTUP
+!ifndef OPENSOURCE_BUILD
+ !insertmacro LICENSECHECK_STARTUP
+ !insertmacro MSVC_STARTUP
+ !insertmacro EVALUATION_STARTUP
+ !insertmacro ADDIN7X_STARTUP
+ !insertmacro ADDIN60_STARTUP
+ !insertmacro DEBUGEXT_STARTUP
+ !insertmacro VSIP_STARTUP
+ !insertmacro HELP_STARTUP
+ !insertmacro QSA_STARTUP
+ !insertmacro ECLIPSE_STARTUP
+ !insertmacro QTJAMBIECLIPSE_STARTUP
+!endif
+FunctionEnd
+
+Function .onInstSuccess
+ !insertmacro ENVIRONMENT_FINISH
+ !insertmacro REGISTERUIEXT_FINISH
+ !insertmacro OPENSOURCE_FINISH
+ !insertmacro MINGW_FINISH
+!ifndef OPENSOURCE_BUILD
+ !insertmacro LICENSECHECK_FINISH
+ !insertmacro MSVC_FINISH
+ !insertmacro EVALUATION_FINISH
+ !insertmacro ADDIN7X_FINISH
+ !insertmacro ADDIN60_FINISH
+ !insertmacro DEBUGEXT_FINISH
+ !insertmacro VSIP_FINISH
+ !insertmacro HELP_FINISH
+ !insertmacro QSA_FINISH
+ !insertmacro ECLIPSE_FINISH
+ !insertmacro QTJAMBIECLIPSE_FINISH
+!endif
+FunctionEnd
+
+Function un.onUninstSuccess
+ !insertmacro ENVIRONMENT_UNFINISH
+ !insertmacro REGISTERUIEXT_UNFINISH
+ !insertmacro OPENSOURCE_UNFINISH
+ !insertmacro MINGW_UNFINISH
+!ifndef OPENSOURCE_BUILD
+ !insertmacro LICENSECHECK_UNFINISH
+ !insertmacro MSVC_UNFINISH
+ !insertmacro EVALUATION_UNFINISH
+ !insertmacro ADDIN7X_UNFINISH
+ !insertmacro ADDIN60_UNFINISH
+ !insertmacro DEBUGEXT_UNFINISH
+ !insertmacro VSIP_UNFINISH
+ !insertmacro HELP_UNFINISH
+ !insertmacro QSA_UNFINISH
+ !insertmacro ECLIPSE_UNFINISH
+ !insertmacro QTJAMBIECLIPSE_UNFINISH
+!endif
+FunctionEnd
+
+Function un.onInit
+ call un.SetAdminVar
+ StrCmp "$RUNNING_AS_ADMIN" "false" 0 common_running_as_admin
+!ifdef USE_ADMIN_CHECK
+ MessageBox MB_OK|MB_ICONSTOP "You do not have the required access rights to uninstall this package."
+ Abort
+!endif
+ SetShellVarContext current
+ goto common_admin_check_done
+ common_running_as_admin:
+ SetShellVarContext all
+ common_admin_check_done:
+
+ ${UnStrRep} $PRODUCT_UNIQUE_KEY "${PRODUCT_NAME} ${PRODUCT_VERSION} - $INSTDIR" "\" "_"
+ strcpy $PRODUCT_UNIQUE_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\$PRODUCT_UNIQUE_KEY"
+
+ push $0
+ ClearErrors
+ ReadRegStr $0 SHCTX "$PRODUCT_UNIQUE_KEY" "DisplayName"
+ IfErrors 0 +3
+ MessageBox MB_OK|MB_ICONSTOP "The uninstaller was unable to find the product to uninstall."
+ Abort
+ pop $0
+
+ ReadRegStr $STARTMENU_STRING SHCTX "$PRODUCT_UNIQUE_KEY" "StartMenu"
+ StrCmp "$STARTMENU_STRING" "" 0 +2
+ StrCpy $STARTMENU_STRING "${DEFAULT_STARTMENU_STRING}"
+
+!ifdef INSTDIR_0 ;the default one, must exist
+ ReadRegStr $${INSTDIR_0}_INSTDIR SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_0}_INSTDIR"
+!endif
+!ifdef INSTDIR_1
+ ReadRegStr $${INSTDIR_1}_INSTDIR SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_1}_INSTDIR"
+!endif
+!ifdef INSTDIR_2
+ ReadRegStr $${INSTDIR_2}_INSTDIR SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_2}_INSTDIR"
+!endif
+!ifdef INSTDIR_3
+ ReadRegStr $${INSTDIR_3}_INSTDIR SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_3}_INSTDIR"
+!endif
+!ifdef INSTDIR_4
+ ReadRegStr $${INSTDIR_4}_INSTDIR SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_4}_INSTDIR"
+!endif
+!ifdef INSTDIR_5
+ ReadRegStr $${INSTDIR_5}_INSTDIR SHCTX "$PRODUCT_UNIQUE_KEY" "${INSTDIR_5}_INSTDIR"
+!endif
+
+ !insertmacro ENVIRONMENT_UNSTARTUP
+ !insertmacro REGISTERUIEXT_UNSTARTUP
+ !insertmacro OPENSOURCE_UNSTARTUP
+ !insertmacro MINGW_UNSTARTUP
+!ifndef OPENSOURCE_BUILD
+ !insertmacro LICENSECHECK_UNSTARTUP
+ !insertmacro MSVC_UNSTARTUP
+ !insertmacro EVALUATION_UNSTARTUP
+ !insertmacro ADDIN7X_UNSTARTUP
+ !insertmacro ADDIN60_UNSTARTUP
+ !insertmacro DEBUGEXT_UNSTARTUP
+ !insertmacro VSIP_UNSTARTUP
+ !insertmacro HELP_UNSTARTUP
+ !insertmacro QSA_UNSTARTUP
+ !insertmacro ECLIPSE_UNSTARTUP
+ !insertmacro QTJAMBIECLIPSE_UNSTARTUP
+!endif
+
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "${UNINSTALLER_CONFIRM_PAGE}"
+FunctionEnd
+
+!insertmacro OPENSOURCE_UNINSTALL
+!insertmacro ENVIRONMENT_UNINSTALL
+!insertmacro REGISTERUIEXT_UNINSTALL
+!insertmacro MINGW_UNINSTALL
+!ifndef OPENSOURCE_BUILD
+!insertmacro HELP_UNINSTALL
+!insertmacro DEBUGEXT_UNINSTALL
+!insertmacro MSVC_UNINSTALL
+!insertmacro EVALUATION_UNINSTALL
+!insertmacro QSA_UNINSTALL
+!insertmacro ECLIPSE_UNINSTALL
+!insertmacro QTJAMBIECLIPSE_UNINSTALL
+!endif
+
+Section Uninstall
+ !ifndef OPENSOURCE_BUILD
+ !insertmacro LICENSECHECK_UNINSTALL
+ !insertmacro ADDIN7X_UNINSTALL
+ !insertmacro ADDIN60_UNINSTALL
+ !insertmacro VSIP_UNINSTALL
+ !endif
+
+ ; COMMON
+ Delete "$INSTDIR\${PRODUCT_NAME}.url"
+ Delete "$INSTDIR\uninst.exe"
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\Uninstall ${PRODUCT_NAME} ${PRODUCT_VERSION}.lnk"
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\QtSoftware.com.lnk"
+
+ RMDir "$SMPROGRAMS\$STARTMENU_STRING"
+ RMDir "$INSTDIR"
+
+ DeleteRegKey SHCTX "$PRODUCT_UNIQUE_KEY"
+SectionEnd
+
+Function CommonRunFunction
+ !ifndef OPENSOURCE_BUILD
+ !insertmacro MSVC_RUN_FUNCTION
+ !insertmacro QSA_RUN_FUNCTION
+ !endif
+ !insertmacro MINGW_RUN_FUNCTION
+ DoneRunFunction:
+FunctionEnd
+
+Function CommonReadmeFunction
+ !ifndef OPENSOURCE_BUILD
+ !insertmacro MSVC_README_FUNCTION
+ !endif
+ !insertmacro MINGW_README_FUNCTION
+ DoneReadmeFunction:
+FunctionEnd
+
+Function un.UninstallerConfirmPage
+ !insertmacro MUI_HEADER_TEXT "Confirm" "Confirm Uninstallation Directories"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${UNINSTALLER_CONFIRM_PAGE}" "Field 2" "Text" "$UninstallerConfirmProduct"
+ !insertmacro MUI_INSTALLOPTIONS_DISPLAY "${UNINSTALLER_CONFIRM_PAGE}"
+FunctionEnd
+
+;pops product name from stack and as result pushes TRUE or FALSE on stack
+Function GetExistsPreviousInstallationOfProduct
+ exch $0
+ push $1
+ push $2
+ push $3
+
+ StrCpy $1 0
+ loop:
+ EnumRegKey $2 HKLM Software\Microsoft\Windows\CurrentVersion\Uninstall $1
+ StrCmp $2 "" no_reg_key_found
+ ${StrStr} $3 $2 $0
+ StrCmp $3 $2 reg_key_found
+ IntOp $1 $1 + 1
+ goto loop
+
+ reg_key_found:
+ push true
+ goto done
+
+ no_reg_key_found:
+ push false
+
+ done:
+ exch
+ pop $3
+ exch
+ pop $2
+ exch
+ pop $1
+ exch
+ pop $0
+FunctionEnd
+
+;pops product name from stack
+Function WarnIfInstalledProductDetected
+ exch $0
+ push $0
+ call GetExistsPreviousInstallationOfProduct
+ exch $1
+ StrCmp $1 true +1 +3
+ MessageBox MB_YESNO|MB_ICONQUESTION "An existing installation of $0 was detected.$\nIt is recommended to deinstall $0 before continuing.$\nDo you want to continue this installation nevertheless?" IDYES +2 IDNO +1
+ Abort
+ pop $1
+ pop $0
+FunctionEnd
+
+;sets $RUNNING_AS_ADMIN to "true" if Admin or Power user
+!macro SetAdminVar UN
+Function ${UN}SetAdminVar
+ push $0
+ ClearErrors
+ UserInfo::GetAccountType
+ IfErrors Admin ;It's probably Win95
+ pop $0
+ StrCmp $0 "Admin" Admin
+ StrCmp $0 "Power" Admin
+
+ StrCpy $RUNNING_AS_ADMIN "false"
+ goto Done
+
+ Admin:
+ StrCpy $RUNNING_AS_ADMIN "true"
+
+ Done:
+ pop $0
+FunctionEnd
+!macroend
+!insertmacro SetAdminVar ""
+!insertmacro SetAdminVar "un."
+
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro OPENSOURCE_DESCRIPTION
+ !insertmacro ENVIRONMENT_DESCRIPTION
+ !insertmacro REGISTERUIEXT_DESCRIPTION
+ !insertmacro MINGW_DESCRIPTION
+ !ifndef OPENSOURCE_BUILD
+ !insertmacro MSVC_DESCRIPTION
+ !insertmacro EVALUATION_DESCRIPTION
+ !insertmacro ADDIN7X_DESCRIPTION
+ !insertmacro ADDIN60_DESCRIPTION
+ !insertmacro DEBUGEXT_DESCRIPTION
+ !insertmacro HELP_DESCRIPTION
+ !insertmacro VSIP_DESCRIPTION
+ !insertmacro QSA_DESCRIPTION
+ !insertmacro ECLIPSE_DESCRIPTION
+ !insertmacro QTJAMBIECLIPSE_DESCRIPTION
+ !endif
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
diff --git a/tools/installer/nsis/modules/environment.nsh b/tools/installer/nsis/modules/environment.nsh
new file mode 100644
index 0000000000..0f6013bc70
--- /dev/null
+++ b/tools/installer/nsis/modules/environment.nsh
@@ -0,0 +1,219 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifdef MODULE_ENVIRONMENT
+!macro ENVIRONMENT_INITIALIZE
+ !include "includes\writeEnvStr.nsh"
+ !include "includes\writePathStr.nsh"
+
+ !ifndef MODULE_ENVIRONMENT_QTDIR
+ !ifdef MODULE_MINGW
+ !define MODULE_ENVIRONMENT_QTDIR $MINGW_INSTDIR
+ !endif
+
+ !ifdef MODULE_MSVC
+ !define MODULE_ENVIRONMENT_QTDIR $MSVC_INSTDIR
+ !endif
+ !endif
+
+ !define MODULE_ENVIRONMENT_PAGE "envpage.ini"
+ var MODULE_ENVIRONMENT_SET
+ var MODULE_ENVIRONMENT_OLD
+ LangString ModuleEnvironmentTitle ${LANG_ENGLISH} "Configure Environment"
+ LangString ModuleEnvironmentDescription ${LANG_ENGLISH} "Configure Qt environment variables"
+
+ Page custom ModuleEnvironmentPageEnter ModuleEnvironmentPageExit
+!macroend
+!macro ENVIRONMENT_SECTIONS
+ Section -ModuleEnvironmentRegister
+ push "${MODULE_ENVIRONMENT_QTDIR}"
+ call RegisterQtEnvVariables
+ SectionEnd
+
+ Function ModuleEnvironmentPageEnter
+ push $0
+ Call IsNT
+ pop $0
+ strcmp "$0" "1" +2
+ abort
+ pop $0
+
+ !insertmacro MUI_HEADER_TEXT "$(ModuleEnvironmentTitle)" "$(ModuleEnvironmentDescription)"
+
+ strcmp $MODULE_ENVIRONMENT_SET "1" 0 envCheckNo
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${MODULE_ENVIRONMENT_PAGE}" "Field 2" "State" "1"
+ goto showEnvPage
+ envCheckNo:
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${MODULE_ENVIRONMENT_PAGE}" "Field 2" "State" "0"
+
+ showEnvPage:
+ !insertmacro MUI_INSTALLOPTIONS_DISPLAY "${MODULE_ENVIRONMENT_PAGE}"
+ FunctionEnd
+
+ Function ModuleEnvironmentPageExit
+ !insertmacro MUI_INSTALLOPTIONS_READ $MODULE_ENVIRONMENT_SET "${MODULE_ENVIRONMENT_PAGE}" "Field 2" "State"
+ FunctionEnd
+
+ Function RegisterQtEnvVariables
+ exch $2 ; the installation path = QTDIR
+ push $0 ; I think WriteEnvStr mixes up $0 and $1
+ push $1
+
+ WriteRegDWORD SHCTX "$PRODUCT_UNIQUE_KEY" "QtEnvSet" $MODULE_ENVIRONMENT_SET
+
+ strcmp $MODULE_ENVIRONMENT_SET "1" 0 noenv
+
+ StrCmp $MODULE_ENVIRONMENT_OLD "0" +4
+ DetailPrint "Removing $MODULE_ENVIRONMENT_OLD\bin from PATH"
+ push "$MODULE_ENVIRONMENT_OLD\bin"
+ Call RemoveFromPath ; remove old qtdir
+
+ DetailPrint "Setting QTDIR to $2"
+ push "QTDIR"
+ push $2
+ Call WriteEnvStr ; set the QTDIR
+
+ DetailPrint "Adding $2\bin to PATH"
+ push "$2\bin"
+ Call AddToPath ; set the PATH
+
+
+ push "QMAKESPEC"
+ push ${INSTALL_COMPILER}
+ Call GetMkSpec
+ pop $0
+ DetailPrint "Setting QMAKESPEC to $0"
+ push $0
+ Call WriteEnvStr ; set the QMAKESPEC
+
+ noenv:
+ pop $1
+ pop $0
+ pop $2
+ FunctionEnd
+
+ Function un.RegisterQtEnvVariables
+ exch $0 ; QTDIR
+ push $1
+
+ ClearErrors
+ ReadRegDWORD $MODULE_ENVIRONMENT_SET SHCTX "$PRODUCT_UNIQUE_KEY" "QtEnvSet"
+ intcmp $MODULE_ENVIRONMENT_SET 0 noenv
+
+ DetailPrint "Removing $0\bin from the PATH"
+ push "$0\bin"
+ Call un.RemoveFromPath ; removes qt from the path
+
+ ;Check if QTDIR is equal to installdir
+ ExpandEnvStrings $1 "%QTDIR%"
+
+ StrCmp "$0" "$1" removeenv
+ StrCmp "$0\" "$1" removeenv
+ StrCmp "$0" "$1\" removeenv
+ Goto noenv
+
+ removeenv:
+ DetailPrint "Removing QTDIR"
+ push "QTDIR"
+ Call un.DeleteEnvStr ; removes QTDIR
+
+ DetailPrint "Removing QMAKESPEC"
+ push "QMAKESPEC"
+ Call un.DeleteEnvStr ; removes QMAKESPEC
+
+ noenv:
+ pop $1
+ pop $0
+ FunctionEnd
+!macroend
+!macro ENVIRONMENT_DESCRIPTION
+!macroend
+!macro ENVIRONMENT_STARTUP
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "${MODULE_ENVIRONMENT_PAGE}"
+ push $0
+ ExpandEnvStrings $0 "%QTDIR%"
+
+ StrCmp $0 "%QTDIR%" +4
+ strcpy $MODULE_ENVIRONMENT_SET "0" ;QTDIR exists
+ strcpy $MODULE_ENVIRONMENT_OLD $0
+ Goto +3
+ strcpy $MODULE_ENVIRONMENT_SET "1" ;no QTDIR
+ strcpy $MODULE_ENVIRONMENT_OLD "0"
+
+ Call IsNT
+ pop $0
+ strcmp "$0" "1" +2
+ strcpy $MODULE_ENVIRONMENT_SET "0"
+ pop $0
+!macroend
+!macro ENVIRONMENT_FINISH
+!macroend
+!macro ENVIRONMENT_UNSTARTUP
+!macroend
+!macro ENVIRONMENT_UNINSTALL
+ Section -un.ModuleEnvironmentRegister
+ push "${MODULE_ENVIRONMENT_QTDIR}"
+ call un.RegisterQtEnvVariables
+ SectionEnd
+!macroend
+!macro ENVIRONMENT_UNFINISH
+!macroend
+!else ;MODULE_ENVIRONMENT
+!macro ENVIRONMENT_INITIALIZE
+!macroend
+!macro ENVIRONMENT_SECTIONS
+!macroend
+!macro ENVIRONMENT_DESCRIPTION
+!macroend
+!macro ENVIRONMENT_STARTUP
+!macroend
+!macro ENVIRONMENT_FINISH
+!macroend
+!macro ENVIRONMENT_UNSTARTUP
+!macroend
+!macro ENVIRONMENT_UNINSTALL
+!macroend
+!macro ENVIRONMENT_UNFINISH
+!macroend
+!endif ;MODULE_ENVIRONMENT
+
diff --git a/tools/installer/nsis/modules/mingw.nsh b/tools/installer/nsis/modules/mingw.nsh
new file mode 100644
index 0000000000..84851781e7
--- /dev/null
+++ b/tools/installer/nsis/modules/mingw.nsh
@@ -0,0 +1,676 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifdef MODULE_MINGW
+!macro MINGW_INITIALIZE
+!include "includes\qtcommon.nsh"
+!ifndef MODULE_MINGW_NAME
+ !define MODULE_MINGW_NAME "Qt"
+!endif
+!ifndef MODULE_MINGW_VERSION
+ !define MODULE_MINGW_VERSION "${PRODUCT_VERSION}"
+!endif
+!ifndef MODULE_MINGW_BUILDDIR
+ !error "MODULE_MINGW_BUILDDIR not defined!"
+!endif
+!ifndef MODULE_MINGW_ROOT
+ !error "MODULE_MINGW_ROOT not defined!"
+!endif
+!ifndef MODULE_MINGW_URL
+ !define MODULE_MINGW_URL "ftp://ftp.trolltech.com/misc"
+!endif
+!ifndef MODULE_MINGW_COMPILERVERSION
+ !define MODULE_MINGW_COMPILERVERSION "3.4.2"
+!endif
+!ifndef MODULE_MINGW_LICENSE
+ !define MODULE_MINGW_LICENSE "C:\MinGW\COPYING"
+!endif
+
+!define MODULE_MINGW_DOWNLOADPAGE "gwdownload.ini"
+!define MODULE_MINGW_MIRRORPAGE "gwmirror.ini"
+!define MODULE_MINGW_RUNTIME_LIB "mingw*.dll"
+!define MODULE_MINGW_DOWNLOADFILE "MinGW-${MODULE_MINGW_COMPILERVERSION}"
+
+var MODULE_MINGW_DOWNLOAD
+var MODULE_MINGW_SOURCEDOWNLOAD
+var MODULE_MINGW_MIRRORS
+var MODULE_MINGW_INSTOK
+var MODULE_MINGW_COMPILERINSTDIR
+
+LangString ModuleMinGWTitle ${LANG_ENGLISH} "MinGW Installation"
+LangString ModuleMinGWDescription ${LANG_ENGLISH} "You need MinGW to be able to compile Qt applications."
+LangString ModuleMinGWMirrorTitle ${LANG_ENGLISH} "MinGW Download Mirror"
+LangString ModuleMinGWMirrorDescription ${LANG_ENGLISH} "Select a download mirror."
+
+Page custom ModuleMinGWDownloadPageEnter ModuleMinGWDownloadPageExit
+!define MUI_PAGE_CUSTOMFUNCTION_PRE ModuleMinGWLicensePageEnter
+!define MUI_PAGE_HEADER_TEXT "MinGW License Agreement"
+!define MUI_PAGE_HEADER_SUBTEXT "Please review the license terms before installing MinGW."
+!define MUI_LICENSEPAGE_TEXT_TOP "MinGW License Information"
+!insertmacro MUI_PAGE_LICENSE "${MODULE_MINGW_LICENSE}"
+Page custom ModuleMinGWMirrorPageEnter ModuleMinGWMirrorPageExit
+
+!include "includes\qtenv.nsh"
+!macroend
+
+!macro MINGW_SECTIONS
+Section "${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION}" MINGW_SEC01
+ strcmp "$MINGW_INSTDIR" "" 0 +5
+ StrCpy $MINGW_INSTDIR "$INSTDIR\${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION}"
+ push $MINGW_INSTDIR
+ call MakeQtDirectory
+ pop $MINGW_INSTDIR
+
+ WriteRegDWORD SHCTX "$PRODUCT_UNIQUE_KEY" "MINGWInstalled" 1
+
+ SetOutPath "$MINGW_INSTDIR"
+ SetOverwrite ifnewer
+ !insertmacro MODULE_MINGW_INSTALLFILES
+
+ push "$MINGW_INSTDIR"
+ call DeleteFloatingLicenseProgram
+
+ push "$MINGW_INSTDIR\bin"
+ call AddStartmenuApplication
+
+ push ${MODULE_MINGW_BUILDDIR}
+ push "$MINGW_INSTDIR"
+ call PatchPrlFiles
+
+ IfFileExists "$MINGW_INSTDIR\.qmake.cache" 0 +5
+ push "$MINGW_INSTDIR\.qmake.cache"
+ push ${MODULE_MINGW_BUILDDIR}
+ push $MINGW_INSTDIR
+ call PatchPath
+
+ IfFileExists "$MINGW_INSTDIR\mkspecs\default\qmake.conf" 0 +5
+ push "$MINGW_INSTDIR\mkspecs\default\qmake.conf"
+ push ${MODULE_MINGW_BUILDDIR}
+ push $MINGW_INSTDIR
+ call PatchPath
+
+ push $MINGW_INSTDIR
+ call PatchCommonBinaryFiles
+
+ push $MINGW_INSTDIR
+ call PatchLicenseInformation
+
+ WriteRegStr SHCTX "SOFTWARE\Trolltech\Common\${MODULE_MINGW_VERSION}\$LICENSE_PRODUCT" "Key" "$LICENSE_KEY"
+
+ push $MINGW_INSTDIR
+ call ModuleMinGWMakeEnvFile
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION} Command Prompt.lnk" "%COMSPEC%" '/k "$MINGW_INSTDIR\bin\qtvars.bat"'
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_STRING\${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION} (Build Debug Libraries).lnk" "%COMSPEC%" '/k "$MINGW_INSTDIR\bin\qtvars.bat compile_debug"'
+
+ push $0
+ strcmp $MODULE_MINGW_DOWNLOAD "no" DoneMinGWInstall
+ DetailPrint "Installing MinGW into $MODULE_MINGW_COMPILERINSTDIR"
+ WriteRegStr SHCTX "$PRODUCT_UNIQUE_KEY" "MinGWInstDir" "$MODULE_MINGW_COMPILERINSTDIR"
+ nsExec::ExecToLog '"$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}.exe" /S /D=$MODULE_MINGW_COMPILERINSTDIR'
+ pop $0
+ strcmp $MODULE_MINGW_SOURCEDOWNLOAD "no" DoneMinGWInstall
+ DetailPrint "Installing MinGW sources into $MODULE_MINGW_COMPILERINSTDIR\src"
+ WriteRegDWORD SHCTX "$PRODUCT_UNIQUE_KEY" "MinGWSources" 1
+ nsExec::ExecToLog '"$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}-src.exe" /S /D=$MODULE_MINGW_COMPILERINSTDIR\src'
+ pop $0
+ DoneMinGWInstall:
+ pop $0
+
+ DetailPrint "Copying MinGW runtime..."
+ SetDetailsPrint none
+ CopyFiles /SILENT "$MODULE_MINGW_COMPILERINSTDIR\bin\${MODULE_MINGW_RUNTIME_LIB}" "$MINGW_INSTDIR\bin"
+ SetDetailsPrint both
+SectionEnd
+
+Function EnableButtons
+ Push $0
+ GetDlgItem $0 $HWNDPARENT 3
+ EnableWindow $0 1
+ GetDlgItem $0 $HWNDPARENT 1
+ EnableWindow $0 1
+ GetDlgItem $0 $HWNDPARENT 2
+ EnableWindow $0 1
+ Pop $0
+FunctionEnd
+
+Function DisableButtons
+ Push $0
+ GetDlgItem $0 $HWNDPARENT 3
+ EnableWindow $0 0
+ GetDlgItem $0 $HWNDPARENT 1
+ EnableWindow $0 0
+ GetDlgItem $0 $HWNDPARENT 2
+ EnableWindow $0 0
+ Pop $0
+FunctionEnd
+
+Function ModuleMinGWDownloadPageEnter
+ strcmp $MODULE_MINGW_INSTOK "yes" 0 +2
+ Abort
+
+ !insertmacro MUI_HEADER_TEXT "$(ModuleMinGWTitle)" "$(ModuleMinGWTitleDescription)"
+ Call UpdateCtrlStates
+ !insertmacro MUI_INSTALLOPTIONS_DISPLAY "${MODULE_MINGW_DOWNLOADPAGE}"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${MODULE_MINGW_DOWNLOADPAGE}" "Field 8" "State" "0"
+FunctionEnd
+
+Function ModuleMinGWMirrorPageEnter
+ strcmp $MODULE_MINGW_DOWNLOAD "yes" +2
+ Abort
+
+ !insertmacro MUI_HEADER_TEXT "$(ModuleMinGWMirrorTitle)" "$(ModuleMinGWMirrorDescription)"
+ !insertmacro MUI_INSTALLOPTIONS_DISPLAY "${MODULE_MINGW_MIRRORPAGE}"
+FunctionEnd
+
+Function ModuleMinGWLicensePageEnter
+ strcmp $MODULE_MINGW_DOWNLOAD "yes" +2
+ Abort
+FunctionEnd
+
+Function UpdateCtrlStates
+ push $0
+ push $1
+ push $2
+
+ !insertmacro MUI_INSTALLOPTIONS_READ $0 "${MODULE_MINGW_DOWNLOADPAGE}" "Field 8" "State"
+ intop $0 $0 !
+ FindWindow $2 "#32770" "" $HWNDPARENT
+ GetDlgItem $1 $2 1205
+ EnableWindow $1 $0
+ GetDlgItem $1 $2 1202
+ EnableWindow $1 $0
+ GetDlgItem $1 $2 1203
+ EnableWindow $1 $0
+
+ intop $0 $0 !
+ GetDlgItem $1 $2 1206
+ EnableWindow $1 $0
+ GetDlgItem $1 $2 1207
+ EnableWindow $1 $0
+ GetDlgItem $1 $2 1208
+ EnableWindow $1 $0
+
+ GetDlgItem $1 $HWNDPARENT 1
+ IntCmp $0 0 +3
+ SendMessage $1 ${WM_SETTEXT} 0 "STR:Next >"
+ Goto +2
+ SendMessage $1 ${WM_SETTEXT} 0 "STR:Install"
+
+ pop $2
+ pop $1
+ pop $0
+FunctionEnd
+
+Function ModuleMinGWDownloadPageExit
+ push $0
+ push $1
+
+ !insertmacro MUI_INSTALLOPTIONS_READ $0 "${MODULE_MINGW_DOWNLOADPAGE}" "Settings" "State"
+ strcmp "$0" "8" 0 NoNotify
+ Call UpdateCtrlStates
+ abort
+ NoNotify:
+
+ !insertmacro MUI_INSTALLOPTIONS_READ $0 "${MODULE_MINGW_DOWNLOADPAGE}" "Field 8" "State"
+ strcmp "$0" "0" noDownload doDownload
+
+doDownload:
+ !insertmacro MUI_INSTALLOPTIONS_READ $0 "${MODULE_MINGW_DOWNLOADPAGE}" "Field 6" "State"
+ strcmp $0 "" 0 +3
+ MessageBox MB_ICONEXCLAMATION|MB_OK "You need to specify an installation directory!"
+ goto tryAgain
+
+ strcpy $MODULE_MINGW_COMPILERINSTDIR $0
+ strcpy $MODULE_MINGW_DOWNLOAD "yes"
+ CreateDirectory "$MINGW_INSTDIR\downloads"
+
+ Call DisableButtons
+ InetLoad::load /BANNER "Mirror Download" "Downloading mirrors from server..." "${MODULE_MINGW_URL}/${MODULE_MINGW_DOWNLOADFILE}.mirrors" "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}.mirrors" /END
+ Pop $1 ;Get the return value
+ Call EnableButtons
+
+ StrCmp $1 "OK" +3
+ MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL "Was not able to download mirror list ($1)." IDRETRY tryAgain 0
+ Quit
+
+ call ModuleMinGWReadMirrors
+ !insertmacro MUI_INSTALLOPTIONS_WRITE ${MODULE_MINGW_MIRRORPAGE} "Field 3" "ListItems" "$MODULE_MINGW_MIRRORS"
+ goto done
+
+noDownload:
+ strcpy $MODULE_MINGW_DOWNLOAD "no"
+ strcpy $MODULE_MINGW_SOURCEDOWNLOAD "no"
+ call ModuleMinGWChecking
+ strcmp $MODULE_MINGW_INSTOK "yes" done
+ MessageBox MB_ICONEXCLAMATION|MB_YESNO "There is a problem with your MinGW installation:$\r$\n$MODULE_MINGW_INSTOK$\r$\nDo you still want to continue? (Your installation may not work)" IDNO tryAgain
+ goto done
+
+tryAgain:
+ pop $1
+ pop $0
+ Abort
+
+done:
+ pop $1
+ pop $0
+FunctionEnd
+
+Function ModuleMinGWMirrorPageExit
+ push $0
+ push $2
+ push $1
+
+ !insertmacro MUI_INSTALLOPTIONS_READ $0 "${MODULE_MINGW_MIRRORPAGE}" "Field 3" "State"
+ strcmp "$0" "" 0 +3
+ MessageBox MB_ICONEXCLAMATION|MB_OK "You must select a mirror to download from!"
+ goto tryAgain
+
+ push $0
+ call ModuleMinGWGetMirror
+ pop $0
+
+ Call DisableButtons
+ InetLoad::load /BANNER "MinGW Download" "Downloading MinGW from server..." "$0/${MODULE_MINGW_DOWNLOADFILE}.exe" "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}.exe" /END
+ Pop $2 ;get the return value
+ Call EnableButtons
+
+ StrCmp $2 "OK" +3
+ MessageBox MB_ICONEXCLAMATION|MB_OK "Was not able to download MinGW ($2). Please try another mirror."
+ Goto tryAgain
+
+ !insertmacro MUI_INSTALLOPTIONS_READ $1 "${MODULE_MINGW_MIRRORPAGE}" "Field 2" "State"
+ strcmp "$1" "0" done
+
+ Call DisableButtons
+ InetLoad::load /BANNER "MinGW Sources Download" "Downloading MinGW Sources from server..." "$0/${MODULE_MINGW_DOWNLOADFILE}-src.exe" "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}-src.exe" /END
+ Pop $2
+ Call EnableButtons
+
+ strcpy $MODULE_MINGW_SOURCEDOWNLOAD "yes"
+
+ StrCmp $2 "OK" +3
+ MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL "Was not able to download MinGW sources ($2). Please try another mirror?" IDRETRY tryAgain 0
+ Quit
+
+ goto done
+
+tryAgain:
+ pop $1
+ pop $2
+ pop $0
+ Abort
+
+done:
+ pop $1
+ pop $2
+ pop $0
+FunctionEnd
+
+Function ModuleMinGWReadMirrors
+ push $0 ;file handle
+ push $1 ;line
+
+ ClearErrors
+ FileOpen $0 "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}.mirrors" r
+ IfErrors done
+
+ strcpy $MODULE_MINGW_MIRRORS ""
+
+nextline:
+ FileRead $0 $1
+ IfErrors done
+ push $1
+ call ModuleMinGWRemoveNewLine
+ pop $1
+ strcpy $MODULE_MINGW_MIRRORS "$MODULE_MINGW_MIRRORS|$1"
+ FileRead $0 $1 ;Jump over next line
+ IfErrors done
+ goto nextline
+
+done:
+ FileClose $0
+ strlen $1 $MODULE_MINGW_MIRRORS
+ intcmp $1 0 failed failed cleanup
+
+failed:
+ MessageBox MB_ICONSTOP|MB_OK "Unable to parse mirror list, exiting!"
+ Quit
+
+cleanup:
+ pop $1
+ pop $0
+FunctionEnd
+
+#this just removes the last two chars
+Function ModuleMinGWRemoveNewLine
+exch $0
+push $1
+push $2
+
+strlen $1 $0
+intop $1 $1 - 1
+strcpy $2 $0 1 $1 ;get last char
+
+strcmp "$2" "$\n" 0 +2
+intop $1 $1 - 1
+
+strcpy $2 $0 1 $1 ;get last char
+strcmp "$2" "$\r" 0 +2
+intop $1 $1 - 1
+
+intop $1 $1 + 1
+strcpy $0 $0 $1
+
+pop $2
+pop $1
+exch $0
+FunctionEnd
+
+#push serverid
+#call GetMirror
+#pop server
+Function ModuleMinGWGetMirror
+ exch $1 ;id
+ push $0 ;file handle
+ push $2 ;line
+ push $3 ;tmp
+
+ strcpy $3 ""
+
+ ClearErrors
+ FileOpen $0 "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}.mirrors" r
+ IfErrors done
+
+nextline:
+ FileRead $0 $2
+ IfErrors done
+ push $2
+ call ModuleMinGWRemoveNewLine
+ pop $2
+ strcmp $1 $2 0 nextline
+ FileRead $0 $3
+ IfErrors done
+ push $3
+ call ModuleMinGWRemoveNewLine
+ pop $3
+
+done:
+ strcpy $1 $3
+ FileClose $0
+ strlen $2 $1
+ intcmp $2 0 failed failed cleanup
+
+failed:
+ MessageBox MB_ICONSTOP|MB_OK "Unable to parse mirror list, exiting!"
+ Quit
+
+cleanup:
+ pop $3
+ pop $2
+ pop $0
+ exch $1
+FunctionEnd
+
+Function ModuleMinGWChecking
+ push $0
+
+ ### update with plugin
+ strcpy $MODULE_MINGW_INSTOK "yes"
+ strcpy $MODULE_MINGW_COMPILERINSTDIR "C:\MinGW" ;fallback dir
+
+ !insertmacro MUI_INSTALLOPTIONS_READ $0 "${MODULE_MINGW_DOWNLOADPAGE}" "Field 3" "State"
+ strcmp "$0" "" +2
+ strcpy $MODULE_MINGW_COMPILERINSTDIR $0
+
+ IfFileExists "$MODULE_MINGW_COMPILERINSTDIR\bin\g++.exe" +3 0
+ strcpy $MODULE_MINGW_INSTOK "g++ not found in $MODULE_MINGW_COMPILERINSTDIR\bin\"
+ goto DoneChecking
+
+!ifndef OPENSOURCE_BUILD
+ ; check w32api.h
+ push $MODULE_MINGW_COMPILERINSTDIR
+ qtnsisext::HasValidWin32Library
+ pop $0
+ strcmp "$0" "1" +3 0
+ strcpy $MODULE_MINGW_INSTOK "The installer could not find a valid $MODULE_MINGW_COMPILERINSTDIR\include\w32api.h$\r$\n(The supported version is 3.2)"
+ goto DoneChecking
+
+ ; check version
+ push $MODULE_MINGW_COMPILERINSTDIR
+ qtnsisext::GetMinGWVersion
+ pop $0
+ strcmp "$0" "${MODULE_MINGW_COMPILERVERSION}" +3 0
+ strcpy $MODULE_MINGW_INSTOK "g++ version found does not match ${MODULE_MINGW_COMPILERVERSION} (Found version $0)."
+ goto DoneChecking
+!endif
+
+DoneChecking:
+ pop $0
+FunctionEnd
+
+#
+# creates a qtvars.bat file in $QTDIR\bin
+# push "c:\qt" #QTDIR
+# call MakeQtVarsFile
+#
+Function ModuleMinGWMakeEnvFile
+ push $0 ; file handle
+
+ ClearErrors
+ FileOpen $0 "$MINGW_INSTDIR\bin\qtvars.bat" w
+ IfErrors WriteMakeFile
+ FileWrite $0 "@echo off$\r$\n"
+ FileWrite $0 "rem$\r$\n"
+ FileWrite $0 "rem This file is generated$\r$\n"
+ FileWrite $0 "rem$\r$\n"
+ FileWrite $0 "$\r$\n"
+ FileWrite $0 "echo Setting up a MinGW/Qt only environment...$\r$\n"
+ FileWrite $0 "echo -- QTDIR set to $MINGW_INSTDIR$\r$\n"
+ FileWrite $0 "echo -- PATH set to $MINGW_INSTDIR\bin$\r$\n"
+ FileWrite $0 "echo -- Adding $MODULE_MINGW_COMPILERINSTDIR\bin to PATH$\r$\n"
+ FileWrite $0 "echo -- Adding %SystemRoot%\System32 to PATH$\r$\n"
+ FileWrite $0 "echo -- QMAKESPEC set to win32-g++$\r$\n"
+ FileWrite $0 "$\r$\n"
+ FileWrite $0 "set QTDIR=$MINGW_INSTDIR$\r$\n"
+ FileWrite $0 "set PATH=$MINGW_INSTDIR\bin$\r$\n"
+ FileWrite $0 "set PATH=%PATH%;$MODULE_MINGW_COMPILERINSTDIR\bin$\r$\n"
+ FileWrite $0 "set PATH=%PATH%;%SystemRoot%\System32$\r$\n"
+ FileWrite $0 "set QMAKESPEC=win32-g++$\r$\n"
+ FileWrite $0 "$\r$\n"
+
+ FileWrite $0 'if not "%1"=="compile_debug" goto END$\r$\n'
+ FileWrite $0 "cd %QTDIR%$\r$\n"
+ FileWrite $0 "echo This will configure and compile qt in debug.$\r$\n"
+ FileWrite $0 "echo The release libraries will not be recompiled.$\r$\n"
+ FileWrite $0 "pause$\r$\n"
+ FileWrite $0 "configure -plugin-sql-sqlite -plugin-sql-odbc -qt-libpng -qt-libjpeg$\r$\n"
+ FileWrite $0 "cd %QTDIR%\src$\r$\n"
+ FileWrite $0 "qmake$\r$\n"
+ FileWrite $0 "mingw32-make debug$\r$\n"
+ FileWrite $0 ":END$\r$\n"
+ FileClose $0
+
+WriteMakeFile:
+ ClearErrors
+ FileOpen $0 "$MINGW_INSTDIR\bin\make.bat" w
+ IfErrors done
+ FileWrite $0 "@echo off$\r$\n"
+ FileWrite $0 "mingw32-make %*$\r$\n"
+ FileClose $0
+
+done:
+; pop $1
+ pop $0
+FunctionEnd
+
+Function MINGW_ValidateDirectoryFunc
+ push "${MODULE_MINGW_BUILDDIR}"
+ push $MINGW_INSTDIR
+ call CommonCheckDirectory
+FunctionEnd
+!macroend
+
+!macro MINGW_DESCRIPTION
+ !insertmacro MUI_DESCRIPTION_TEXT ${MINGW_SEC01} "This installs ${MODULE_MINGW_NAME} version ${MODULE_MINGW_VERSION} on your system."
+!macroend
+
+!macro MINGW_STARTUP
+ !ifndef MODULE_MINGW_NODEFAULT
+ SectionSetFlags ${MINGW_SEC01} 17
+ !endif
+ strcpy $MINGW_INSTDIR "C:\Qt\${MODULE_MINGW_VERSION}"
+ push $MINGW_INSTDIR
+ call MakeQtDirectory
+ pop $MINGW_INSTDIR
+
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "${MODULE_MINGW_DOWNLOADPAGE}"
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "${MODULE_MINGW_MIRRORPAGE}"
+
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${MODULE_MINGW_DOWNLOADPAGE}" "Field 3" "State" "C:\MinGW"
+ !insertmacro MUI_INSTALLOPTIONS_WRITE "${MODULE_MINGW_DOWNLOADPAGE}" "Field 6" "State" "C:\MinGW"
+
+ strcpy $MODULE_MINGW_DOWNLOAD "no"
+ strcpy $MODULE_MINGW_SOURCEDOWNLOAD "no"
+!macroend
+
+!macro MINGW_FINISH
+!macroend
+
+!macro MINGW_RUN_FUNCTION
+ ReadRegDWORD $0 SHCTX "$PRODUCT_UNIQUE_KEY" "MINGWInstalled"
+ intcmp $0 1 0 DoneRunFunctionMINGW
+
+ IfFileExists "$MINGW_INSTDIR\bin\qtdemo.exe" 0 +2
+ Exec '$MINGW_INSTDIR\bin\qtdemo.exe'
+ goto DoneRunFunction ;don't run more applications
+
+ DoneRunFunctionMINGW:
+!macroend
+
+!macro MINGW_README_FUNCTION
+ ReadRegDWORD $0 SHCTX "$PRODUCT_UNIQUE_KEY" "MINGWInstalled"
+ intcmp $0 1 0 DoneReadmeFunctionMINGW
+
+ IfFileExists "$MINGW_INSTDIR\bin\assistant.exe" 0 +2
+ Exec '$MINGW_INSTDIR\bin\assistant.exe'
+ goto DoneReadmeFunction ;don't run more applications
+
+ DoneReadmeFunctionMINGW:
+!macroend
+
+!macro MINGW_UNSTARTUP
+ strcmp "$MINGW_INSTDIR" "" 0 +5
+ StrCpy $MINGW_INSTDIR "$INSTDIR\${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION}"
+ push $MINGW_INSTDIR
+ call un.MakeQtDirectory
+ pop $MINGW_INSTDIR
+
+ !insertmacro ConfirmOnRemove "MINGWInstalled" "- ${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION} in $MINGW_INSTDIR"
+!macroend
+
+!macro MINGW_UNINSTALL
+Section un.ModuleMinGW
+ push $0
+ push $1
+
+ ReadRegDWORD $0 SHCTX "$PRODUCT_UNIQUE_KEY" "MINGWInstalled"
+ intcmp $0 1 0 DoneUnInstallMINGW
+
+ Delete "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}.mirrors"
+
+ ReadRegDWORD $0 SHCTX "$PRODUCT_UNIQUE_KEY" "MinGWSources"
+ strcmp $0 "" MinGWSourcesUninstallDone ;not installed
+ Delete "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}-src.exe"
+ nsExec::ExecToLog '"$0\src\uninst.exe"'
+ pop $1
+ MinGWSourcesUninstallDone:
+
+ ReadRegStr $0 SHCTX "$PRODUCT_UNIQUE_KEY" "MinGWInstDir"
+ strcmp $0 "" MinGWUninstallDone ;not installed
+ Delete "$MINGW_INSTDIR\downloads\${MODULE_MINGW_DOWNLOADFILE}.exe"
+ nsExec::ExecToLog '"$0\uninst.exe"'
+ pop $1
+ MinGWUninstallDone:
+
+ DetailPrint "Removing start menu shortcuts"
+ call un.RemoveStartmenuApplication
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION} Command Prompt.lnk"
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\${MODULE_MINGW_NAME} ${MODULE_MINGW_VERSION} (Build Debug Libraries).lnk"
+
+ Delete "$MINGW_INSTDIR\bin\${MODULE_MINGW_RUNTIME_LIB}"
+ Delete "$MINGW_INSTDIR\bin\make.bat"
+ Delete "$MINGW_INSTDIR\bin\qtvars.bat"
+
+ !insertmacro MODULE_MINGW_REMOVE "$MINGW_INSTDIR"
+ RMDir $MINGW_INSTDIR ;removes it if empty
+
+ DoneUnInstallMINGW:
+ pop $1
+ pop $0
+SectionEnd
+!macroend
+!macro MINGW_UNFINISH
+!macroend
+!else ;MODULE_MINGW
+!macro MINGW_INITIALIZE
+!macroend
+!macro MINGW_SECTIONS
+!macroend
+!macro MINGW_DESCRIPTION
+!macroend
+!macro MINGW_STARTUP
+!macroend
+!macro MINGW_FINISH
+!macroend
+!macro MINGW_RUN_FUNCTION
+!macroend
+!macro MINGW_README_FUNCTION
+!macroend
+!macro MINGW_UNSTARTUP
+!macroend
+!macro MINGW_UNINSTALL
+!macroend
+!macro MINGW_UNFINISH
+!macroend
+!endif ;MODULE_MINGW
+
diff --git a/tools/installer/nsis/modules/opensource.nsh b/tools/installer/nsis/modules/opensource.nsh
new file mode 100644
index 0000000000..3657ba8796
--- /dev/null
+++ b/tools/installer/nsis/modules/opensource.nsh
@@ -0,0 +1,98 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+!ifdef MODULE_OPENSOURCE
+!macro OPENSOURCE_INITIALIZE
+ !define MODULE_OPENSOURCE_PAGE "opensource.ini"
+ page custom ModuleOpenSourceShowPage
+!macroend
+!macro OPENSOURCE_SECTIONS
+ Section -ModuleOpenSourceSection
+ !ifdef MODULE_OPENSOURCE_ROOT
+ SetOutPath "$INSTDIR"
+ File "${MODULE_OPENSOURCE_ROOT}\OPENSOURCE-NOTICE.TXT"
+ !endif
+ SectionEnd
+
+ Function ModuleOpenSourceShowPage
+ !insertmacro MUI_HEADER_TEXT "Open Source Edition" " "
+ !insertmacro MUI_INSTALLOPTIONS_DISPLAY "${MODULE_OPENSOURCE_PAGE}"
+ strcpy "$LICENSEE" "Open Source"
+ strcpy "$LICENSE_PRODUCT" "OpenSource"
+ FunctionEnd
+!macroend
+!macro OPENSOURCE_DESCRIPTION
+!macroend
+!macro OPENSOURCE_STARTUP
+ !insertmacro MUI_INSTALLOPTIONS_EXTRACT "${MODULE_OPENSOURCE_PAGE}"
+!macroend
+!macro OPENSOURCE_FINISH
+!macroend
+!macro OPENSOURCE_UNSTARTUP
+!macroend
+!macro OPENSOURCE_UNINSTALL
+ Section -un.ModuleOpenSourceSection
+ Delete "$SMPROGRAMS\$STARTMENU_STRING\OpenSource Notice.lnk"
+ SectionEnd
+!macroend
+!macro OPENSOURCE_UNFINISH
+!macroend
+!else ;MODULE_OPENSOURCE
+!macro OPENSOURCE_INITIALIZE
+!macroend
+!macro OPENSOURCE_SECTIONS
+!macroend
+!macro OPENSOURCE_DESCRIPTION
+!macroend
+!macro OPENSOURCE_STARTUP
+!macroend
+!macro OPENSOURCE_FINISH
+!macroend
+!macro OPENSOURCE_UNSTARTUP
+!macroend
+!macro OPENSOURCE_UNINSTALL
+!macroend
+!macro OPENSOURCE_UNFINISH
+!macroend
+!endif ;MODULE_OPENSOURCE
+
diff --git a/tools/installer/nsis/modules/registeruiext.nsh b/tools/installer/nsis/modules/registeruiext.nsh
new file mode 100644
index 0000000000..a335097bee
--- /dev/null
+++ b/tools/installer/nsis/modules/registeruiext.nsh
@@ -0,0 +1,210 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; UI Extension Module
+
+!ifdef MODULE_REGISTERUIEXT
+
+;------------------------------------------------------------------------------------------------
+!macro REGISTERUIEXT_INITIALIZE
+ !include "includes\system.nsh"
+
+ !ifndef MODULE_REGISTERUIEXT_QTDIR
+ !ifdef MODULE_MINGW
+ !define MODULE_REGISTERUIEXT_QTDIR $MINGW_INSTDIR
+ !endif
+
+ !ifdef MODULE_MSVC
+ !define MODULE_REGISTERUIEXT_QTDIR $MSVC_INSTDIR
+ !endif
+ !endif
+
+ !define MODULE_REGISTERUIEXT_INTERNAL_DESC "Trolltech.DesignerForm"
+ !define MODULE_REGISTERUIEXT_DESC_DESIGNER "Open with Qt Designer"
+ !define MODULE_REGISTERUIEXT_DESC_DEVENV "Open with Visual Studio .NET"
+ !define MODULE_REGISTERUIEXT_FILE_DESC "Qt Designer File"
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!macro REGISTERUIEXT_SECTIONS
+
+Function GetSelectedVSIP
+ Push $0
+ Push $1
+
+ StrCpy $0 ""
+!ifdef MODULE_VSIP
+!ifdef VSIP_SEC01
+ SectionGetFlags ${VSIP_SEC01} $1
+ IntOp $1 $1 & 1
+ IntCmp $1 0 +2
+ StrCpy $0 "7.1"
+!endif
+!ifdef VSIP_SEC02
+ SectionGetFlags ${VSIP_SEC02} $1
+ IntOp $1 $1 & 1
+ IntCmp $1 0 +2
+ StrCpy $0 "8.0"
+!endif
+!endif
+
+ Pop $1
+ Exch $0
+FunctionEnd
+
+SectionGroup "File Associations"
+Section "UI Files (*.ui)" REGISTERUIEXT_SEC01
+ call ModuleRegisterUI
+SectionEnd
+SectionGroupEnd
+
+Function ModuleRegisterUI
+ push $0
+ push $1
+
+ WriteRegDWORD SHCTX "$PRODUCT_UNIQUE_KEY" "UIExtRegistered" 1
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}" "" "${MODULE_REGISTERUIEXT_FILE_DESC}"
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}\shell" "" "open"
+
+ Call GetSelectedVSIP
+ Pop $1
+
+ StrCmp "$1" "" 0 RegisterVSIP
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}\shell\open" "" "${MODULE_REGISTERUIEXT_DESC_DESIGNER}"
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}\shell\open\command" "" "${MODULE_REGISTERUIEXT_QTDIR}\bin\designer.exe $\"%1$\""
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}\DefaultIcon" "" "${MODULE_REGISTERUIEXT_QTDIR}\bin\designer.exe,0"
+ goto RegisterFinished
+
+ RegisterVSIP:
+ Push $1
+ Call GetVSInstallationDir
+ Pop $0
+
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}\shell\open" "" "${MODULE_REGISTERUIEXT_DESC_DEVENV}"
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}\shell\${MODULE_REGISTERUIEXT_DESC_DEVENV}\command" "" "$0\devenv.exe $\"%1$\""
+ WriteRegStr HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}\DefaultIcon" "" "$VSIP_INSTDIR\ui.ico"
+ RegisterFinished:
+ WriteRegStr HKCR ".ui" "" "${MODULE_REGISTERUIEXT_INTERNAL_DESC}"
+
+ pop $1
+ pop $0
+FunctionEnd
+
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!macro REGISTERUIEXT_DESCRIPTION
+ !insertmacro MUI_DESCRIPTION_TEXT ${REGISTERUIEXT_SEC01} "This will associate the file extention .ui with the Qt GUI editor."
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!macro REGISTERUIEXT_STARTUP
+ StrCmp $RUNNING_AS_ADMIN "true" +2
+ SectionSetFlags ${REGISTERUIEXT_SEC01} 16
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!macro REGISTERUIEXT_FINISH
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!macro REGISTERUIEXT_UNSTARTUP
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!macro REGISTERUIEXT_UNINSTALL
+Function un.ModuleRegisterUI
+ push $1
+ ReadRegStr $1 HKCR ".ui" ""
+ strcmp $1 "${MODULE_REGISTERUIEXT_INTERNAL_DESC}" 0 continue
+ ; do not delete this key since a subkey openwithlist
+ ; or open withprogid may exist
+ WriteRegStr HKCR ".ui" "" ""
+ continue:
+ ; just delete it since nobody else is supposed to use it
+ DeleteRegKey HKCR "${MODULE_REGISTERUIEXT_INTERNAL_DESC}"
+
+ pop $1
+FunctionEnd
+
+Section -un.ModuleRegisterUIExtSection
+ push $0
+ ReadRegDWORD $0 SHCTX "$PRODUCT_UNIQUE_KEY" "UIExtRegistered"
+ intcmp $0 1 0 DoneUnRegister
+ call un.ModuleRegisterUI
+ DoneUnRegister:
+ pop $0
+SectionEnd
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!macro REGISTERUIEXT_UNFINISH
+!macroend
+
+;------------------------------------------------------------------------------------------------
+
+!else
+!macro REGISTERUIEXT_INITIALIZE
+!macroend
+!macro REGISTERUIEXT_SECTIONS
+!macroend
+!macro REGISTERUIEXT_DESCRIPTION
+!macroend
+!macro REGISTERUIEXT_STARTUP
+!macroend
+!macro REGISTERUIEXT_FINISH
+!macroend
+!macro REGISTERUIEXT_UNSTARTUP
+!macroend
+!macro REGISTERUIEXT_UNINSTALL
+!macroend
+!macro REGISTERUIEXT_UNFINISH
+!macroend
+!endif
diff --git a/tools/installer/nsis/opensource.ini b/tools/installer/nsis/opensource.ini
new file mode 100644
index 0000000000..334dc5d146
--- /dev/null
+++ b/tools/installer/nsis/opensource.ini
@@ -0,0 +1,81 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;; Contact: Qt Software Information (qt-info@nokia.com)
+;;
+;; This file is part of the tools applications of the Qt Toolkit.
+;;
+;; $QT_BEGIN_LICENSE:LGPL$
+;; No Commercial Usage
+;; This file contains pre-release code and may not be distributed.
+;; You may use this file in accordance with the terms and conditions
+;; contained in the either Technology Preview License Agreement or the
+;; Beta Release License Agreement.
+;;
+;; GNU Lesser General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU Lesser
+;; General Public License version 2.1 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.LGPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU Lesser General Public License version 2.1 requirements
+;; will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+;;
+;; In addition, as a special exception, Nokia gives you certain
+;; additional rights. These rights are described in the Nokia Qt LGPL
+;; Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+;; package.
+;;
+;; GNU General Public License Usage
+;; Alternatively, this file may be used under the terms of the GNU
+;; General Public License version 3.0 as published by the Free Software
+;; Foundation and appearing in the file LICENSE.GPL included in the
+;; packaging of this file. Please review the following information to
+;; ensure the GNU General Public License version 3.0 requirements will be
+;; met: http://www.gnu.org/copyleft/gpl.html.
+;;
+;; If you are unsure which license is appropriate for your use, please
+;; contact the sales department at qt-sales@nokia.com.
+;; $QT_END_LICENSE$
+;;
+;; This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+;; WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Ini file generated by the HM NIS Edit IO designer.
+[Settings]
+NumFields=4
+
+[Field 1]
+Type=Label
+Text=You are now installing the Open Source Edition of Qt. It is licensed under GNU LGPL version 2.1 and the GPL version 3.
+Left=0
+Right=300
+Top=0
+Bottom=78
+
+[Field 2]
+Type=Link
+Text=http://qtsoftware.com/developer/downloads/qt
+State=http://qtsoftware.com/developer/downloads/qt
+Left=0
+Right=278
+Top=80
+Bottom=88
+
+[Field 3]
+Type=Link
+Text=http://qtsoftware.com/company/model
+State=http://qtsoftware.com/company/model
+Left=0
+Right=267
+Top=112
+Bottom=120
+
+[Field 4]
+Type=Label
+Text=To read more about Nokia/Qt Software's licensing, please go to:
+Left=0
+Right=278
+Top=97
+Bottom=105
+
diff --git a/tools/linguist/LICENSE.GPL b/tools/linguist/LICENSE.GPL
new file mode 100644
index 0000000000..b6e1c33e04
--- /dev/null
+++ b/tools/linguist/LICENSE.GPL
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/tools/linguist/lconvert/lconvert.pro b/tools/linguist/lconvert/lconvert.pro
new file mode 100644
index 0000000000..66a194ec15
--- /dev/null
+++ b/tools/linguist/lconvert/lconvert.pro
@@ -0,0 +1,22 @@
+
+TEMPLATE = app
+TARGET = lconvert
+DESTDIR = ../../../bin
+
+QT -= gui
+
+CONFIG += qt warn_on console
+CONFIG -= app_bundle
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+include(../shared/formats.pri)
+
+DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
+SOURCES += main.cpp
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/tools/linguist/lconvert/main.cpp b/tools/linguist/lconvert/main.cpp
new file mode 100644
index 0000000000..2842bc7c56
--- /dev/null
+++ b/tools/linguist/lconvert/main.cpp
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+static int usage(const QStringList &args)
+{
+ Q_UNUSED(args);
+
+ QString loaders;
+ QString savers;
+ QString line = QString(QLatin1String(" %1 - %2\n"));
+ foreach (Translator::FileFormat format, Translator::registeredFileFormats()) {
+ loaders += line.arg(format.extension, -5).arg(format.description);
+ if (format.fileType != Translator::FileFormat::SourceCode)
+ savers += line.arg(format.extension, -5).arg(format.description);
+ }
+
+ qWarning("%s", qPrintable(QString(QLatin1String("\nUsage:\n"
+ " lconvert [options] <infile> [<infile>...]\n\n"
+ "lconvert is part of Qt's Linguist tool chain. It can be used as a\n"
+ "stand-alone tool to convert translation data files from one of the\n"
+ "following input formats\n\n%1\n"
+ "to one of the following output formats\n\n%2\n"
+ "If multiple input files are specified the translations are merged with\n"
+ "translations from later files taking precedence.\n\n"
+ "Options:\n"
+ " -h\n"
+ " --help Display this information and exit.\n\n"
+ " -i <infile>\n"
+ " --input-file <infile>\n"
+ " Specify input file. Use if <infile> might start with a dash.\n"
+ " This option can be used several times to merge inputs.\n"
+ " May be '-' (standard input) for use in a pipe.\n\n"
+ " -o <outfile>\n"
+ " --output-file <outfile>\n"
+ " Specify output file. Default is '-' (standard output).\n\n"
+ " -if <informat>\n"
+ " --input-format <format>\n"
+ " Specify input format for subsequent <infile>s.\n"
+ " The format is auto-detected from the file name and defaults to 'ts'.\n\n"
+ " -of <outformat>\n"
+ " --output-format <outformat>\n"
+ " Specify output format. See -if.\n\n"
+ " --drop-tags <regexp>\n"
+ " Drop named extra tags when writing 'ts' or 'xlf' files.\n"
+ " May be specified repeatedly.\n\n"
+ " --drop-translations\n"
+ " Drop existing translations and reset the status to 'unfinished'.\n"
+ " Note: this implies --no-obsolete.\n\n"
+ " --source-language <language>[_<region>]\n"
+ " Specify/override the language of the source strings. Defaults to\n"
+ " POSIX if not specified and the file does not name it yet.\n"
+ " --target-language <language>[_<region>]\n"
+ " Specify/override the language of the translation.\n"
+ " The target language is guessed from the file name if this option\n"
+ " is not specified and the file contents name no language yet.\n\n"
+ " --no-obsolete\n"
+ " Drop obsolete messages.\n\n"
+ " --no-finished\n"
+ " Drop finished messages.\n\n"
+ " --verbose\n"
+ " be a bit more verbose\n\n"
+ "Long options can be specified with only one leading dash, too.\n\n"
+ "Return value:\n"
+ " 0 on success\n"
+ " 1 on command line parse failures\n"
+ " 2 on read failures\n"
+ " 3 on write failures\n")).arg(loaders).arg(savers)));
+ return 1;
+}
+
+struct File
+{
+ QString name;
+ QString format;
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ QStringList args = app.arguments();
+
+ QList<File> inFiles;
+ QString inFormat(QLatin1String("auto"));
+ QString outFileName;
+ QString outFormat(QLatin1String("auto"));
+ QString targetLanguage;
+ QString sourceLanguage;
+ bool dropTranslations = false;
+ bool noObsolete = false;
+ bool noFinished = false;
+ bool verbose = false;
+
+ ConversionData cd;
+ Translator tr;
+
+ for (int i = 1; i < args.size(); ++i) {
+ if (args[i].startsWith(QLatin1String("--")))
+ args[i].remove(0, 1);
+ if (args[i] == QLatin1String("-o")
+ || args[i] == QLatin1String("-output-file")) {
+ if (++i >= args.size())
+ return usage(args);
+ outFileName = args[i];
+ } else if (args[i] == QLatin1String("-of")
+ || args[i] == QLatin1String("-output-format")) {
+ if (++i >= args.size())
+ return usage(args);
+ outFormat = args[i];
+ } else if (args[i] == QLatin1String("-i")
+ || args[i] == QLatin1String("-input-file")) {
+ if (++i >= args.size())
+ return usage(args);
+ File file;
+ file.name = args[i];
+ file.format = inFormat;
+ inFiles.append(file);
+ } else if (args[i] == QLatin1String("-if")
+ || args[i] == QLatin1String("-input-format")) {
+ if (++i >= args.size())
+ return usage(args);
+ inFormat = args[i];
+ } else if (args[i] == QLatin1String("-drop-tag")) {
+ if (++i >= args.size())
+ return usage(args);
+ cd.m_dropTags.append(args[i]);
+ } else if (args[i] == QLatin1String("-drop-translations")) {
+ dropTranslations = true;
+ } else if (args[i] == QLatin1String("-target-language")) {
+ if (++i >= args.size())
+ return usage(args);
+ targetLanguage = args[i];
+ } else if (args[i] == QLatin1String("-source-language")) {
+ if (++i >= args.size())
+ return usage(args);
+ sourceLanguage = args[i];
+ } else if (args[i].startsWith(QLatin1String("-h"))) {
+ usage(args);
+ return 0;
+ } else if (args[i] == QLatin1String("-no-obsolete")) {
+ noObsolete = true;
+ } else if (args[i] == QLatin1String("-no-finished")) {
+ noFinished = true;
+ } else if (args[i] == QLatin1String("-verbose")) {
+ verbose = true;
+ } else if (args[i].startsWith(QLatin1Char('-'))) {
+ return usage(args);
+ } else {
+ File file;
+ file.name = args[i];
+ file.format = inFormat;
+ inFiles.append(file);
+ }
+ }
+
+ if (inFiles.isEmpty())
+ return usage(args);
+
+ tr.setLanguageCode(Translator::guessLanguageCodeFromFileName(inFiles[0].name));
+ if (!targetLanguage.isEmpty())
+ tr.setLanguageCode(targetLanguage);
+ if (!sourceLanguage.isEmpty())
+ tr.setSourceLanguageCode(sourceLanguage);
+
+ if (!tr.load(inFiles[0].name, cd, inFiles[0].format)) {
+ qWarning() << qPrintable(cd.error());
+ return 2;
+ }
+
+ for (int i = 1; i < inFiles.size(); ++i) {
+ Translator tr2;
+ if (!tr2.load(inFiles[i].name, cd, inFiles[i].format)) {
+ qWarning() << qPrintable(cd.error());
+ return 2;
+ }
+ for (int j = 0; j < tr2.messageCount(); ++j)
+ tr.replaceSorted(tr2.message(j));
+ }
+
+ if (noObsolete)
+ tr.stripObsoleteMessages();
+ if (noFinished)
+ tr.stripFinishedMessages();
+ if (dropTranslations)
+ tr.dropTranslations();
+
+ if (!tr.save(outFileName, cd, outFormat)) {
+ qWarning("%s", qPrintable(cd.error()));
+ return 3;
+ }
+ return 0;
+}
diff --git a/tools/linguist/linguist.pro b/tools/linguist/linguist.pro
new file mode 100644
index 0000000000..e1c8a63529
--- /dev/null
+++ b/tools/linguist/linguist.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ linguist \
+ lrelease \
+ lupdate \
+ lconvert
+CONFIG += ordered
+
diff --git a/tools/linguist/linguist/Info_mac.plist b/tools/linguist/linguist/Info_mac.plist
new file mode 100644
index 0000000000..b11f493bdd
--- /dev/null
+++ b/tools/linguist/linguist/Info_mac.plist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.1">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>linguist.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.trolltech.Linguist</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleExecutable</key>
+ <string>Linguist</string>
+</dict>
+</plist>
diff --git a/tools/linguist/linguist/batchtranslation.ui b/tools/linguist/linguist/batchtranslation.ui
new file mode 100644
index 0000000000..4824dfb852
--- /dev/null
+++ b/tools/linguist/linguist/batchtranslation.ui
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>BatchTranslationDialog</class>
+ <widget class="QDialog" name="batchTranslationDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>437</width>
+ <height>492</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Qt Linguist - Batch Translation</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="ckMarkFinished">
+ <property name="toolTip">
+ <string/>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Set translated entries to finished</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="ckTranslateTranslated">
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Retranslate entries with existing translation</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="ckTranslateFinished">
+ <property name="toolTip">
+ <string>Note that the modified entries will be reset to unfinished if 'Set translated entries to finished' above is unchecked.</string>
+ </property>
+ <property name="text">
+ <string>Translate also finished entries</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Phrase book preference</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QListView" name="phrasebookList">
+ <property name="uniformItemSizes">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="moveUpButton">
+ <property name="text">
+ <string>Move up</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="moveDownButton">
+ <property name="text">
+ <string>Move down</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>The batch translator will search through the selected phrase books in the order given above.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="runButton">
+ <property name="text">
+ <string>&amp;Run</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>batchTranslationDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>388</x>
+ <y>461</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>188</x>
+ <y>465</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/linguist/linguist/batchtranslationdialog.cpp b/tools/linguist/linguist/batchtranslationdialog.cpp
new file mode 100644
index 0000000000..101ad975ab
--- /dev/null
+++ b/tools/linguist/linguist/batchtranslationdialog.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "batchtranslationdialog.h"
+#include "phrase.h"
+#include "messagemodel.h"
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QProgressDialog>
+
+QT_BEGIN_NAMESPACE
+
+CheckableListModel::CheckableListModel(QObject *parent)
+ : QStandardItemModel(parent)
+{
+}
+
+Qt::ItemFlags CheckableListModel::flags(const QModelIndex &index) const
+{
+ Q_UNUSED(index);
+ return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+}
+
+BatchTranslationDialog::BatchTranslationDialog(MultiDataModel *dataModel, QWidget *w)
+ : QDialog(w), m_model(this), m_dataModel(dataModel)
+{
+ m_ui.setupUi(this);
+ connect(m_ui.runButton, SIGNAL(clicked()), this, SLOT(startTranslation()));
+ connect(m_ui.moveUpButton, SIGNAL(clicked()), this, SLOT(movePhraseBookUp()));
+ connect(m_ui.moveDownButton, SIGNAL(clicked()), this, SLOT(movePhraseBookDown()));
+
+ m_ui.phrasebookList->setModel(&m_model);
+ m_ui.phrasebookList->setSelectionBehavior(QAbstractItemView::SelectItems);
+ m_ui.phrasebookList->setSelectionMode(QAbstractItemView::SingleSelection);
+}
+
+
+void BatchTranslationDialog::setPhraseBooks(const QList<PhraseBook *> &phrasebooks, int modelIndex)
+{
+ QString fn = QFileInfo(m_dataModel->srcFileName(modelIndex)).baseName();
+ setWindowTitle(tr("Batch Translation of '%1' - Qt Linguist").arg(fn));
+ m_model.clear();
+ m_model.insertColumn(0);
+ m_phrasebooks = phrasebooks;
+ m_modelIndex = modelIndex;
+ int count = phrasebooks.count();
+ m_model.insertRows(0, count);
+ for (int i = 0; i < count; ++i) {
+ QModelIndex idx(m_model.index(i, 0));
+ m_model.setData(idx, phrasebooks[i]->friendlyPhraseBookName());
+ int sortOrder;
+ if (phrasebooks[i]->language() != QLocale::C
+ && m_dataModel->language(m_modelIndex) != QLocale::C) {
+ if (phrasebooks[i]->language() != m_dataModel->language(m_modelIndex))
+ sortOrder = 3;
+ else
+ sortOrder = (phrasebooks[i]->country()
+ == m_dataModel->model(m_modelIndex)->country()) ? 0 : 1;
+ } else {
+ sortOrder = 2;
+ }
+ m_model.setData(idx, sortOrder == 3 ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
+ m_model.setData(idx, sortOrder, Qt::UserRole + 1);
+ m_model.setData(idx, i, Qt::UserRole);
+ }
+ m_model.setSortRole(Qt::UserRole + 1);
+ m_model.sort(0);
+}
+
+void BatchTranslationDialog::startTranslation()
+{
+ int translatedcount = 0;
+ QCursor oldCursor = cursor();
+ setCursor(Qt::BusyCursor);
+ int messageCount = m_dataModel->messageCount();
+
+ QProgressDialog *dlgProgress;
+ dlgProgress = new QProgressDialog(tr("Searching, please wait..."), tr("&Cancel"), 0, messageCount, this);
+ dlgProgress->show();
+
+ int msgidx = 0;
+ const bool translateTranslated = m_ui.ckTranslateTranslated->isChecked();
+ const bool translateFinished = m_ui.ckTranslateFinished->isChecked();
+ for (MultiDataModelIterator it(m_dataModel, m_modelIndex); it.isValid(); ++it) {
+ if (MessageItem *m = it.current()) {
+ if (!m->isObsolete()
+ && (translateTranslated || m->translation().isEmpty())
+ && (translateFinished || !m->isFinished())) {
+
+ // Go through them in the order the user specified in the phrasebookList
+ for (int b = 0; b < m_model.rowCount(); ++b) {
+ QModelIndex idx(m_model.index(b, 0));
+ QVariant checkState = m_model.data(idx, Qt::CheckStateRole);
+ if (checkState == Qt::Checked) {
+ PhraseBook *pb = m_phrasebooks[m_model.data(idx, Qt::UserRole).toInt()];
+ foreach (const Phrase *ph, pb->phrases()) {
+ if (ph->source() == m->text()) {
+ m_dataModel->setTranslation(it, ph->target());
+ m_dataModel->setFinished(it, m_ui.ckMarkFinished->isChecked());
+ ++translatedcount;
+ goto done; // break 2;
+ }
+ }
+ }
+ }
+ }
+ }
+ done:
+ ++msgidx;
+ if (!(msgidx & 15))
+ dlgProgress->setValue(msgidx);
+ qApp->processEvents();
+ if (dlgProgress->wasCanceled())
+ break;
+ }
+ dlgProgress->hide();
+
+ setCursor(oldCursor);
+ emit finished();
+ QMessageBox::information(this, tr("Linguist batch translator"),
+ tr("Batch translated %n entries", "", translatedcount), QMessageBox::Ok);
+}
+
+void BatchTranslationDialog::movePhraseBookUp()
+{
+ QModelIndexList indexes = m_ui.phrasebookList->selectionModel()->selectedIndexes();
+ if (indexes.count() <= 0) return;
+
+ QModelIndex sel = indexes[0];
+ int row = sel.row();
+ if (row > 0) {
+ QModelIndex other = m_model.index(row - 1, 0);
+ QMap<int, QVariant> seldata = m_model.itemData(sel);
+ m_model.setItemData(sel, m_model.itemData(other));
+ m_model.setItemData(other, seldata);
+ m_ui.phrasebookList->selectionModel()->setCurrentIndex(other, QItemSelectionModel::ClearAndSelect);
+ }
+}
+
+void BatchTranslationDialog::movePhraseBookDown()
+{
+ QModelIndexList indexes = m_ui.phrasebookList->selectionModel()->selectedIndexes();
+ if (indexes.count() <= 0) return;
+
+ QModelIndex sel = indexes[0];
+ int row = sel.row();
+ if (row < m_model.rowCount() - 1) {
+ QModelIndex other = m_model.index(row + 1, 0);
+ QMap<int, QVariant> seldata = m_model.itemData(sel);
+ m_model.setItemData(sel, m_model.itemData(other));
+ m_model.setItemData(other, seldata);
+ m_ui.phrasebookList->selectionModel()->setCurrentIndex(other, QItemSelectionModel::ClearAndSelect);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/batchtranslationdialog.h b/tools/linguist/linguist/batchtranslationdialog.h
new file mode 100644
index 0000000000..1ceeb6eb83
--- /dev/null
+++ b/tools/linguist/linguist/batchtranslationdialog.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BATCHTRANSLATIONDIALOG_H
+#define BATCHTRANSLATIONDIALOG_H
+
+#include "ui_batchtranslation.h"
+#include "phrase.h"
+
+#include <QtGui/QDialog>
+#include <QtGui/QStandardItemModel>
+
+QT_BEGIN_NAMESPACE
+
+class MultiDataModel;
+
+class CheckableListModel : public QStandardItemModel
+{
+public:
+ CheckableListModel(QObject *parent = 0);
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+};
+
+class BatchTranslationDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ BatchTranslationDialog(MultiDataModel *model, QWidget *w = 0);
+ void setPhraseBooks(const QList<PhraseBook *> &phrasebooks, int modelIndex);
+
+signals:
+ void finished();
+
+private slots:
+ void startTranslation();
+ void movePhraseBookUp();
+ void movePhraseBookDown();
+
+private:
+ Ui::BatchTranslationDialog m_ui;
+ CheckableListModel m_model;
+ MultiDataModel *m_dataModel;
+ QList<PhraseBook *> m_phrasebooks;
+ int m_modelIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif // BATCHTRANSLATIONDIALOG_H
diff --git a/tools/linguist/linguist/errorsview.cpp b/tools/linguist/linguist/errorsview.cpp
new file mode 100644
index 0000000000..9ffebaaa4b
--- /dev/null
+++ b/tools/linguist/linguist/errorsview.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "errorsview.h"
+
+#include "messagemodel.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+
+#include <QtGui/QListView>
+#include <QtGui/QStandardItem>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QTextEdit>
+#include <QtGui/QVBoxLayout>
+
+QT_BEGIN_NAMESPACE
+
+ErrorsView::ErrorsView(MultiDataModel *dataModel, QWidget *parent) :
+ QListView(parent),
+ m_dataModel(dataModel)
+{
+ m_list = new QStandardItemModel(this);
+ setModel(m_list);
+}
+
+void ErrorsView::clear()
+{
+ m_list->clear();
+}
+
+void ErrorsView::addError(int model, const ErrorType type, const QString &arg)
+{
+ QString error;
+ switch (type) {
+ case SuperfluousAccelerator:
+ addError(model, tr("Accelerator possibly superfluous in translation."));
+ break;
+ case MissingAccelerator:
+ addError(model, tr("Accelerator possibly missing in translation."));
+ break;
+ case PunctuationDiffer:
+ addError(model, tr("Translation does not end with the same punctuation as the source text."));
+ break;
+ case IgnoredPhrasebook:
+ addError(model, tr("A phrase book suggestion for '%1' was ignored.").arg(arg));
+ break;
+ case PlaceMarkersDiffer:
+ addError(model, tr("Translation does not refer to the same place markers as in the source text."));
+ break;
+ case NumerusMarkerMissing:
+ addError(model, tr("Translation does not contain the necessary %n place marker."));
+ break;
+ default:
+ addError(model, tr("Unknown error"));
+ break;
+ }
+}
+
+QString ErrorsView::firstError()
+{
+ return (m_list->rowCount() == 0) ? QString() : m_list->item(0)->text();
+}
+
+void ErrorsView::addError(int model, const QString &error)
+{
+ // NOTE: Three statics instead of one just for GCC 3.3.5
+ static QLatin1String imageLocation(":/images/s_check_danger.png");
+ static QPixmap image(imageLocation);
+ static QIcon pxDanger(image);
+ QString lang;
+ if (m_dataModel->modelCount() > 1)
+ lang = m_dataModel->model(model)->localizedLanguage() + QLatin1String(": ");
+ QStandardItem *item = new QStandardItem(pxDanger, lang + error);
+ item->setEditable(false);
+ m_list->appendRow(QList<QStandardItem*>() << item);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/errorsview.h b/tools/linguist/linguist/errorsview.h
new file mode 100644
index 0000000000..bc6097b93b
--- /dev/null
+++ b/tools/linguist/linguist/errorsview.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ERRORSVIEW_H
+#define ERRORSVIEW_H
+
+#include <QListView>
+
+QT_BEGIN_NAMESPACE
+
+class QStandardItemModel;
+
+class MultiDataModel;
+
+class ErrorsView : public QListView
+{
+ Q_OBJECT
+public:
+ enum ErrorType {
+ SuperfluousAccelerator,
+ MissingAccelerator,
+ PunctuationDiffer,
+ IgnoredPhrasebook,
+ PlaceMarkersDiffer,
+ NumerusMarkerMissing
+ };
+
+ ErrorsView(MultiDataModel *dataModel, QWidget *parent = 0);
+ void clear();
+ void addError(int model, const ErrorType type, const QString &arg = QString());
+ QString firstError();
+private:
+ void addError(int model, const QString &error);
+ QStandardItemModel *m_list;
+ MultiDataModel *m_dataModel;
+};
+
+QT_END_NAMESPACE
+
+#endif // ERRORSVIEW_H
diff --git a/tools/linguist/linguist/finddialog.cpp b/tools/linguist/linguist/finddialog.cpp
new file mode 100644
index 0000000000..ae243ea8b6
--- /dev/null
+++ b/tools/linguist/linguist/finddialog.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* TRANSLATOR FindDialog
+
+ Choose Edit|Find from the menu bar or press Ctrl+F to pop up the
+ Find dialog
+*/
+
+#include "finddialog.h"
+
+QT_BEGIN_NAMESPACE
+
+FindDialog::FindDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ setupUi(this);
+
+ findNxt->setEnabled(false);
+
+ connect(findNxt, SIGNAL(clicked()), this, SLOT(emitFindNext()));
+ connect(led, SIGNAL(textChanged(const QString &)), this, SLOT(verifyText(const QString &)));
+
+ led->setFocus();
+}
+
+void FindDialog::verifyText(const QString &text)
+{
+ findNxt->setEnabled(!text.isEmpty());
+}
+
+void FindDialog::emitFindNext()
+{
+ DataModel::FindLocation where;
+ if (sourceText != 0)
+ where =
+ DataModel::FindLocation(
+ (sourceText->isChecked() ? DataModel::SourceText : 0) |
+ (translations->isChecked() ? DataModel::Translations : 0) |
+ (comments->isChecked() ? DataModel::Comments : 0));
+ else
+ where = DataModel::Translations;
+ emit findNext(led->text(), where, matchCase->isChecked(), ignoreAccelerators->isChecked());
+ led->selectAll();
+}
+
+void FindDialog::find()
+{
+ led->setFocus();
+
+ show();
+ activateWindow();
+ raise();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/finddialog.h b/tools/linguist/linguist/finddialog.h
new file mode 100644
index 0000000000..a9fc146dab
--- /dev/null
+++ b/tools/linguist/linguist/finddialog.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FINDDIALOG_H
+#define FINDDIALOG_H
+
+#include "ui_finddialog.h"
+#include "messagemodel.h"
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class FindDialog : public QDialog, public Ui::FindDialog
+{
+ Q_OBJECT
+public:
+ FindDialog(QWidget *parent = 0);
+
+signals:
+ void findNext(const QString& text, DataModel::FindLocation where, bool matchCase, bool ignoreAccelerators);
+
+private slots:
+ void emitFindNext();
+ void verifyText(const QString &);
+ void find();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/linguist/finddialog.ui b/tools/linguist/linguist/finddialog.ui
new file mode 100644
index 0000000000..fd1c4a1a9c
--- /dev/null
+++ b/tools/linguist/linguist/finddialog.ui
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>FindDialog</class>
+ <widget class="QDialog" name="FindDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>414</width>
+ <height>175</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Find</string>
+ </property>
+ <property name="whatsThis">
+ <string>This window allows you to search for some text in the translation source file.</string>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <item>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="findWhat">
+ <property name="text">
+ <string>&amp;Find what:</string>
+ </property>
+ <property name="buddy">
+ <cstring>led</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="led">
+ <property name="whatsThis">
+ <string>Type in the text to search for.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="sourceText">
+ <property name="whatsThis">
+ <string>Source texts are searched when checked.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Source texts</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="translations">
+ <property name="whatsThis">
+ <string>Translations are searched when checked.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Translations</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QCheckBox" name="matchCase">
+ <property name="whatsThis">
+ <string>Texts such as 'TeX' and 'tex' are considered as different when checked.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Match case</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="comments">
+ <property name="whatsThis">
+ <string>Comments and contexts are searched when checked.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Comments</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QCheckBox" name="ignoreAccelerators">
+ <property name="text">
+ <string>Ignore &amp;accelerators</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="findNxt">
+ <property name="whatsThis">
+ <string>Click here to find the next occurrence of the text you typed in.</string>
+ </property>
+ <property name="text">
+ <string>Find Next</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancel">
+ <property name="whatsThis">
+ <string>Click here to close this window.</string>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <tabstops>
+ <tabstop>led</tabstop>
+ <tabstop>findNxt</tabstop>
+ <tabstop>cancel</tabstop>
+ <tabstop>comments</tabstop>
+ <tabstop>sourceText</tabstop>
+ <tabstop>translations</tabstop>
+ <tabstop>matchCase</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>cancel</sender>
+ <signal>clicked()</signal>
+ <receiver>FindDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>372</x>
+ <y>58</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>373</x>
+ <y>109</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/linguist/linguist/formpreviewview.cpp b/tools/linguist/linguist/formpreviewview.cpp
new file mode 100644
index 0000000000..990414b0cd
--- /dev/null
+++ b/tools/linguist/linguist/formpreviewview.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "formpreviewview.h"
+#include "messagemodel.h"
+
+#include <quiloader.h>
+#include <abstractformbuilder.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QTime>
+
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QFontComboBox>
+#include <QtGui/QFrame>
+#include <QtGui/QGridLayout>
+#include <QtGui/QListWidget>
+#include <QtGui/QMdiArea>
+#include <QtGui/QMdiSubWindow>
+#include <QtGui/QMenu>
+#include <QtGui/QTableWidget>
+#include <QtGui/QTabWidget>
+#include <QtGui/QToolBox>
+#include <QtGui/QTreeWidget>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_CC_SUN) || defined(Q_CC_HPACC) || defined(Q_CC_XLC)
+int qHash(const QUiTranslatableStringValue &tsv)
+#else
+static int qHash(const QUiTranslatableStringValue &tsv)
+#endif
+{
+ return qHash(tsv.value()) ^ qHash(tsv.comment());
+}
+
+static bool operator==(const QUiTranslatableStringValue &tsv1, const QUiTranslatableStringValue &tsv2)
+{
+ return tsv1.value() == tsv2.value() && tsv1.comment() == tsv2.comment();
+}
+
+#define INSERT_TARGET(_tsv, _type, _target, _prop) \
+ do { \
+ target.type = _type; \
+ target.target._target; \
+ target.prop._prop; \
+ (*targets)[qVariantValue<QUiTranslatableStringValue>(_tsv)].append(target); \
+ } while (0)
+
+static void registerTreeItem(QTreeWidgetItem *item, TargetsHash *targets)
+{
+ const QUiItemRolePair *irs = QFormInternal::qUiItemRoles;
+
+ int cnt = item->columnCount();
+ for (int i = 0; i < cnt; ++i) {
+ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) {
+ QVariant v = item->data(i, irs[j].shadowRole);
+ if (v.isValid()) {
+ TranslatableEntry target;
+ target.prop.treeIndex.column = i;
+ INSERT_TARGET(v, TranslatableTreeWidgetItem, treeWidgetItem = item, treeIndex.index = j);
+ }
+ }
+ }
+
+ cnt = item->childCount();
+ for (int j = 0; j < cnt; ++j)
+ registerTreeItem(item->child(j), targets);
+}
+
+#define REGISTER_ITEM_CORE(item, propType, targetName) \
+ const QUiItemRolePair *irs = QFormInternal::qUiItemRoles; \
+ for (unsigned j = 0; irs[j].shadowRole >= 0; j++) { \
+ QVariant v = item->data(irs[j].shadowRole); \
+ if (v.isValid()) \
+ INSERT_TARGET(v, propType, targetName = item, index = j); \
+ }
+
+static void registerListItem(QListWidgetItem *item, TargetsHash *targets)
+{
+ TranslatableEntry target;
+ REGISTER_ITEM_CORE(item, TranslatableListWidgetItem, listWidgetItem);
+}
+
+static void registerTableItem(QTableWidgetItem *item, TargetsHash *targets)
+{
+ if (!item)
+ return;
+
+ TranslatableEntry target;
+ REGISTER_ITEM_CORE(item, TranslatableTableWidgetItem, tableWidgetItem);
+}
+
+#define REGISTER_SUBWIDGET_PROP(mainWidget, propType, propName) \
+ do { \
+ QVariant v = mainWidget->widget(i)->property(propName); \
+ if (v.isValid()) \
+ INSERT_TARGET(v, propType, object = mainWidget, index = i); \
+ } while (0)
+
+static void buildTargets(QObject *o, TargetsHash *targets)
+{
+ TranslatableEntry target;
+
+ foreach (const QByteArray &prop, o->dynamicPropertyNames()) {
+ if (prop.startsWith(PROP_GENERIC_PREFIX)) {
+ const QByteArray propName = prop.mid(sizeof(PROP_GENERIC_PREFIX) - 1);
+ INSERT_TARGET(o->property(prop),
+ TranslatableProperty, object = o, name = qstrdup(propName.data()));
+ }
+ }
+ if (0) {
+#ifndef QT_NO_TABWIDGET
+ } else if (QTabWidget *tabw = qobject_cast<QTabWidget*>(o)) {
+ const int cnt = tabw->count();
+ for (int i = 0; i < cnt; ++i) {
+ REGISTER_SUBWIDGET_PROP(tabw, TranslatableTabPageText, PROP_TABPAGETEXT);
+# ifndef QT_NO_TOOLTIP
+ REGISTER_SUBWIDGET_PROP(tabw, TranslatableTabPageToolTip, PROP_TABPAGETOOLTIP);
+# endif
+# ifndef QT_NO_WHATSTHIS
+ REGISTER_SUBWIDGET_PROP(tabw, TranslatableTabPageWhatsThis, PROP_TABPAGEWHATSTHIS);
+# endif
+ }
+#endif
+#ifndef QT_NO_TOOLBOX
+ } else if (QToolBox *toolw = qobject_cast<QToolBox*>(o)) {
+ const int cnt = toolw->count();
+ for (int i = 0; i < cnt; ++i) {
+ REGISTER_SUBWIDGET_PROP(toolw, TranslatableToolItemText, PROP_TOOLITEMTEXT);
+# ifndef QT_NO_TOOLTIP
+ REGISTER_SUBWIDGET_PROP(toolw, TranslatableToolItemToolTip, PROP_TOOLITEMTOOLTIP);
+# endif
+ }
+#endif
+#ifndef QT_NO_COMBOBOX
+ } else if (QComboBox *combow = qobject_cast<QComboBox*>(o)) {
+ if (!qobject_cast<QFontComboBox*>(o)) {
+ const int cnt = combow->count();
+ for (int i = 0; i < cnt; ++i) {
+ const QVariant v = combow->itemData(i, Qt::DisplayPropertyRole);
+ if (v.isValid())
+ INSERT_TARGET(v, TranslatableComboBoxItem, comboBox = combow, index = i);
+ }
+ }
+#endif
+#ifndef QT_NO_LISTWIDGET
+ } else if (QListWidget *listw = qobject_cast<QListWidget*>(o)) {
+ const int cnt = listw->count();
+ for (int i = 0; i < cnt; ++i)
+ registerListItem(listw->item(i), targets);
+#endif
+#ifndef QT_NO_TABLEWIDGET
+ } else if (QTableWidget *tablew = qobject_cast<QTableWidget*>(o)) {
+ const int row_cnt = tablew->rowCount();
+ const int col_cnt = tablew->columnCount();
+ for (int j = 0; j < col_cnt; ++j)
+ registerTableItem(tablew->verticalHeaderItem(j), targets);
+ for (int i = 0; i < row_cnt; ++i) {
+ registerTableItem(tablew->horizontalHeaderItem(i), targets);
+ for (int j = 0; j < col_cnt; ++j)
+ registerTableItem(tablew->item(i, j), targets);
+ }
+#endif
+#ifndef QT_NO_TREEWIDGET
+ } else if (QTreeWidget *treew = qobject_cast<QTreeWidget*>(o)) {
+ if (QTreeWidgetItem *item = treew->headerItem())
+ registerTreeItem(item, targets);
+ const int cnt = treew->topLevelItemCount();
+ for (int i = 0; i < cnt; ++i)
+ registerTreeItem(treew->topLevelItem(i), targets);
+#endif
+ }
+ foreach (QObject *co, o->children())
+ buildTargets(co, targets);
+}
+
+static void destroyTargets(TargetsHash *targets)
+{
+ for (TargetsHash::Iterator it = targets->begin(), end = targets->end(); it != end; ++it)
+ foreach (const TranslatableEntry &target, *it)
+ if (target.type == TranslatableProperty)
+ delete target.prop.name;
+ targets->clear();
+}
+
+static void retranslateTarget(const TranslatableEntry &target, const QString &text)
+{
+ switch (target.type) {
+ case TranslatableProperty:
+ target.target.object->setProperty(target.prop.name, text);
+ break;
+#ifndef QT_NO_TABWIDGET
+ case TranslatableTabPageText:
+ target.target.tabWidget->setTabText(target.prop.index, text);
+ break;
+# ifndef QT_NO_TOOLTIP
+ case TranslatableTabPageToolTip:
+ target.target.tabWidget->setTabToolTip(target.prop.index, text);
+ break;
+# endif
+# ifndef QT_NO_WHATSTHIS
+ case TranslatableTabPageWhatsThis:
+ target.target.tabWidget->setTabWhatsThis(target.prop.index, text);
+ break;
+# endif
+#endif // QT_NO_TABWIDGET
+#ifndef QT_NO_TOOLBOX
+ case TranslatableToolItemText:
+ target.target.toolBox->setItemText(target.prop.index, text);
+ break;
+# ifndef QT_NO_TOOLTIP
+ case TranslatableToolItemToolTip:
+ target.target.toolBox->setItemToolTip(target.prop.index, text);
+ break;
+# endif
+#endif // QT_NO_TOOLBOX
+#ifndef QT_NO_COMBOBOX
+ case TranslatableComboBoxItem:
+ target.target.comboBox->setItemText(target.prop.index, text);
+ break;
+#endif
+#ifndef QT_NO_LISTWIDGET
+ case TranslatableListWidgetItem:
+ target.target.listWidgetItem->setData(target.prop.index, text);
+ break;
+#endif
+#ifndef QT_NO_TABLEWIDGET
+ case TranslatableTableWidgetItem:
+ target.target.tableWidgetItem->setData(target.prop.index, text);
+ break;
+#endif
+#ifndef QT_NO_TREEWIDGET
+ case TranslatableTreeWidgetItem:
+ target.target.treeWidgetItem->setData(target.prop.treeIndex.column, target.prop.treeIndex.index, text);
+ break;
+#endif
+ }
+}
+
+static void retranslateTargets(
+ const QList<TranslatableEntry> &targets, const QUiTranslatableStringValue &tsv,
+ const DataModel *dataModel, const QString &className)
+{
+ QString sourceText = QString::fromUtf8(tsv.value());
+ QString text;
+ if (MessageItem *msg = dataModel->findMessage(
+ className, sourceText, QString::fromUtf8(tsv.comment())))
+ text = msg->translation();
+ if (text.isEmpty() && !tsv.value().isEmpty())
+ text = QLatin1Char('#') + sourceText;
+
+ foreach (const TranslatableEntry &target, targets)
+ retranslateTarget(target, text);
+}
+
+static void highlightTreeWidgetItem(QTreeWidgetItem *item, int col, bool on)
+{
+ QVariant br = item->data(col, Qt::BackgroundRole + 500);
+ QVariant fr = item->data(col, Qt::ForegroundRole + 500);
+ if (on) {
+ if (!br.isValid() && !fr.isValid()) {
+ item->setData(col, Qt::BackgroundRole + 500, item->data(col, Qt::BackgroundRole));
+ item->setData(col, Qt::ForegroundRole + 500, item->data(col, Qt::ForegroundRole));
+ QPalette pal = qApp->palette();
+ item->setData(col, Qt::BackgroundRole, pal.color(QPalette::Dark));
+ item->setData(col, Qt::ForegroundRole, pal.color(QPalette::Light));
+ }
+ } else {
+ if (br.isValid() || fr.isValid()) {
+ item->setData(col, Qt::BackgroundRole, br);
+ item->setData(col, Qt::ForegroundRole, fr);
+ item->setData(col, Qt::BackgroundRole + 500, QVariant());
+ item->setData(col, Qt::ForegroundRole + 500, QVariant());
+ }
+ }
+}
+
+template <class T>
+static void highlightWidgetItem(T *item, bool on)
+{
+ QVariant br = item->data(Qt::BackgroundRole + 500);
+ QVariant fr = item->data(Qt::ForegroundRole + 500);
+ if (on) {
+ if (!br.isValid() && !fr.isValid()) {
+ item->setData(Qt::BackgroundRole + 500, item->data(Qt::BackgroundRole));
+ item->setData(Qt::ForegroundRole + 500, item->data(Qt::ForegroundRole));
+ QPalette pal = qApp->palette();
+ item->setData(Qt::BackgroundRole, pal.color(QPalette::Dark));
+ item->setData(Qt::ForegroundRole, pal.color(QPalette::Light));
+ }
+ } else {
+ if (br.isValid() || fr.isValid()) {
+ item->setData(Qt::BackgroundRole, br);
+ item->setData(Qt::ForegroundRole, fr);
+ item->setData(Qt::BackgroundRole + 500, QVariant());
+ item->setData(Qt::ForegroundRole + 500, QVariant());
+ }
+ }
+}
+
+#define AUTOFILL_BACKUP_PROP "_q_linguist_autoFillBackup"
+#define PALETTE_BACKUP_PROP "_q_linguist_paletteBackup"
+#define FONT_BACKUP_PROP "_q_linguist_fontBackup"
+
+static void highlightWidget(QWidget *w, bool on);
+
+static void highlightAction(QAction *a, bool on)
+{
+ QVariant bak = a->property(FONT_BACKUP_PROP);
+ if (on) {
+ if (!bak.isValid()) {
+ QFont fnt = qApp->font();
+ a->setProperty(FONT_BACKUP_PROP, qVariantFromValue(a->font().resolve(fnt)));
+ fnt.setBold(true);
+ fnt.setItalic(true);
+ a->setFont(fnt);
+ }
+ } else {
+ if (bak.isValid()) {
+ a->setFont(qVariantValue<QFont>(bak));
+ a->setProperty(FONT_BACKUP_PROP, QVariant());
+ }
+ }
+ foreach (QWidget *w, a->associatedWidgets())
+ highlightWidget(w, on);
+}
+
+static void highlightWidget(QWidget *w, bool on)
+{
+ QVariant bak = w->property(PALETTE_BACKUP_PROP);
+ if (on) {
+ if (!bak.isValid()) {
+ QPalette pal = qApp->palette();
+ foreach (QObject *co, w->children())
+ if (QWidget *cw = qobject_cast<QWidget *>(co))
+ cw->setPalette(cw->palette().resolve(pal));
+ w->setProperty(PALETTE_BACKUP_PROP, qVariantFromValue(w->palette().resolve(pal)));
+ w->setProperty(AUTOFILL_BACKUP_PROP, qVariantFromValue(w->autoFillBackground()));
+ QColor col1 = pal.color(QPalette::Dark);
+ QColor col2 = pal.color(QPalette::Light);
+ pal.setColor(QPalette::Base, col1);
+ pal.setColor(QPalette::Window, col1);
+ pal.setColor(QPalette::Button, col1);
+ pal.setColor(QPalette::Text, col2);
+ pal.setColor(QPalette::WindowText, col2);
+ pal.setColor(QPalette::ButtonText, col2);
+ pal.setColor(QPalette::BrightText, col2);
+ w->setPalette(pal);
+ w->setAutoFillBackground(true);
+ }
+ } else {
+ if (bak.isValid()) {
+ w->setPalette(qVariantValue<QPalette>(bak));
+ w->setAutoFillBackground(qVariantValue<bool>(w->property(AUTOFILL_BACKUP_PROP)));
+ w->setProperty(PALETTE_BACKUP_PROP, QVariant());
+ w->setProperty(AUTOFILL_BACKUP_PROP, QVariant());
+ }
+ }
+ if (QMenu *m = qobject_cast<QMenu *>(w))
+ if (m->menuAction())
+ highlightAction(m->menuAction(), on);
+}
+
+static void highlightTarget(const TranslatableEntry &target, bool on)
+{
+ switch (target.type) {
+ case TranslatableProperty:
+ if (QAction *a = qobject_cast<QAction *>(target.target.object)) {
+ highlightAction(a, on);
+ break;
+ }
+ // fallthrough
+#ifndef QT_NO_TABWIDGET
+ case TranslatableTabPageText:
+# ifndef QT_NO_TOOLTIP
+ case TranslatableTabPageToolTip:
+# endif
+# ifndef QT_NO_WHATSTHIS
+ case TranslatableTabPageWhatsThis:
+# endif
+#endif // QT_NO_TABWIDGET
+#ifndef QT_NO_TOOLBOX
+ case TranslatableToolItemText:
+# ifndef QT_NO_TOOLTIP
+ case TranslatableToolItemToolTip:
+# endif
+#endif // QT_NO_TOOLBOX
+#ifndef QT_NO_COMBOBOX
+ case TranslatableComboBoxItem:
+#endif
+ if (QWidget *w = qobject_cast<QWidget *>(target.target.object))
+ highlightWidget(w, on);
+ break;
+#ifndef QT_NO_LISTWIDGET
+ case TranslatableListWidgetItem:
+ highlightWidgetItem(target.target.listWidgetItem, on);
+ break;
+#endif
+#ifndef QT_NO_TABLEWIDGET
+ case TranslatableTableWidgetItem:
+ highlightWidgetItem(target.target.tableWidgetItem, on);
+ break;
+#endif
+#ifndef QT_NO_TREEWIDGET
+ case TranslatableTreeWidgetItem:
+ highlightTreeWidgetItem(target.target.treeWidgetItem, target.prop.treeIndex.column, on);
+ break;
+#endif
+ }
+}
+
+static void highlightTargets(const QList<TranslatableEntry> &targets, bool on)
+{
+ foreach (const TranslatableEntry &target, targets)
+ highlightTarget(target, on);
+}
+
+FormPreviewView::FormPreviewView(QWidget *parent, MultiDataModel *dataModel)
+ : QMainWindow(parent), m_form(0), m_dataModel(dataModel)
+{
+ m_mdiSubWindow = new QMdiSubWindow;
+ m_mdiSubWindow->setWindowFlags(m_mdiSubWindow->windowFlags() & ~Qt::WindowSystemMenuHint);
+ m_mdiArea = new QMdiArea(this);
+ m_mdiArea->addSubWindow(m_mdiSubWindow);
+ setCentralWidget(m_mdiArea);
+}
+
+void FormPreviewView::setSourceContext(int model, MessageItem *messageItem)
+{
+ if (model < 0 || !messageItem) {
+ m_lastModel = -1;
+ return;
+ }
+
+ QDir dir = QFileInfo(m_dataModel->srcFileName(model)).dir();
+ QString fileName = dir.absoluteFilePath(messageItem->fileName());
+ if (m_lastFormName != fileName) {
+ delete m_form;
+ m_form = 0;
+ m_lastFormName.clear();
+ m_highlights.clear();
+ destroyTargets(&m_targets);
+
+ static QUiLoader *uiLoader;
+ if (!uiLoader) {
+ uiLoader = new QUiLoader(this);
+ uiLoader->setLanguageChangeEnabled(true);
+ uiLoader->setTranslationEnabled(false);
+ }
+
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qDebug() << "CANNOT OPEN FORM" << fileName;
+ m_mdiSubWindow->hide();
+ return;
+ }
+ m_form = uiLoader->load(&file, m_mdiSubWindow);
+ if (!m_form) {
+ qDebug() << "CANNOT LOAD FORM" << fileName;
+ m_mdiSubWindow->hide();
+ return;
+ }
+ file.close();
+ buildTargets(m_form, &m_targets);
+
+ setToolTip(fileName);
+
+ m_form->setWindowFlags(Qt::Widget);
+ m_form->setWindowModality(Qt::NonModal);
+ m_form->setFocusPolicy(Qt::NoFocus);
+ m_form->show(); // needed, otherwide the Qt::NoFocus is not propagated.
+ m_mdiSubWindow->setWidget(m_form);
+ m_mdiSubWindow->show();
+ m_mdiArea->cascadeSubWindows();
+ m_lastFormName = fileName;
+ m_lastClassName = messageItem->context();
+ m_lastModel = -1;
+ } else {
+ highlightTargets(m_highlights, false);
+ }
+ QUiTranslatableStringValue tsv;
+ tsv.setValue(messageItem->text().toUtf8());
+ tsv.setComment(messageItem->comment().toUtf8());
+ m_highlights = m_targets.value(tsv);
+ if (m_lastModel != model) {
+ for (TargetsHash::Iterator it = m_targets.begin(), end = m_targets.end(); it != end; ++it)
+ retranslateTargets(*it, it.key(), m_dataModel->model(model), m_lastClassName);
+ m_lastModel = model;
+ } else {
+ retranslateTargets(m_highlights, tsv, m_dataModel->model(model), m_lastClassName);
+ }
+ highlightTargets(m_highlights, true);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/formpreviewview.h b/tools/linguist/linguist/formpreviewview.h
new file mode 100644
index 0000000000..5923f24579
--- /dev/null
+++ b/tools/linguist/linguist/formpreviewview.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FORMPREVIEWVIEW_H
+#define FORMPREVIEWVIEW_H
+
+#include <quiloader_p.h>
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+
+#include <QtGui/QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+class MultiDataModel;
+class FormFrame;
+class MessageItem;
+
+class QComboBox;
+class QListWidgetItem;
+class QGridLayout;
+class QMdiArea;
+class QMdiSubWindow;
+class QToolBox;
+class QTableWidgetItem;
+class QTreeWidgetItem;
+
+enum TranslatableEntryType {
+ TranslatableProperty,
+ TranslatableToolItemText,
+ TranslatableToolItemToolTip,
+ TranslatableTabPageText,
+ TranslatableTabPageToolTip,
+ TranslatableTabPageWhatsThis,
+ TranslatableListWidgetItem,
+ TranslatableTableWidgetItem,
+ TranslatableTreeWidgetItem,
+ TranslatableComboBoxItem
+};
+
+struct TranslatableEntry {
+ TranslatableEntryType type;
+ union {
+ QObject *object;
+ QComboBox *comboBox;
+ QTabWidget *tabWidget;
+ QToolBox *toolBox;
+ QListWidgetItem *listWidgetItem;
+ QTableWidgetItem *tableWidgetItem;
+ QTreeWidgetItem *treeWidgetItem;
+ } target;
+ union {
+ char *name;
+ int index;
+ struct {
+ short index; // Known to be below 1000
+ short column;
+ } treeIndex;
+ } prop;
+};
+
+typedef QHash<QUiTranslatableStringValue, QList<TranslatableEntry> > TargetsHash;
+
+class FormPreviewView : public QMainWindow
+{
+ Q_OBJECT
+public:
+ FormPreviewView(QWidget *parent, MultiDataModel *dataModel);
+
+ void setSourceContext(int model, MessageItem *messageItem);
+
+private:
+ bool m_isActive;
+ QString m_currentFileName;
+ QMdiArea *m_mdiArea;
+ QMdiSubWindow *m_mdiSubWindow;
+ QWidget *m_form;
+ TargetsHash m_targets;
+ QList<TranslatableEntry> m_highlights;
+ MultiDataModel *m_dataModel;
+
+ QString m_lastFormName;
+ QString m_lastClassName;
+ int m_lastModel;
+};
+
+QT_END_NAMESPACE
+
+#endif // FORMPREVIEWVIEW_H
diff --git a/tools/linguist/linguist/images/appicon.png b/tools/linguist/linguist/images/appicon.png
new file mode 100644
index 0000000000..d388cbd0ba
--- /dev/null
+++ b/tools/linguist/linguist/images/appicon.png
Binary files differ
diff --git a/tools/linguist/linguist/images/down.png b/tools/linguist/linguist/images/down.png
new file mode 100644
index 0000000000..29d1d4439a
--- /dev/null
+++ b/tools/linguist/linguist/images/down.png
Binary files differ
diff --git a/tools/linguist/linguist/images/editdelete.png b/tools/linguist/linguist/images/editdelete.png
new file mode 100644
index 0000000000..df2a147d24
--- /dev/null
+++ b/tools/linguist/linguist/images/editdelete.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-128-32.png b/tools/linguist/linguist/images/icons/linguist-128-32.png
new file mode 100644
index 0000000000..d108208fa8
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-128-32.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-128-8.png b/tools/linguist/linguist/images/icons/linguist-128-8.png
new file mode 100644
index 0000000000..6678dd2ae7
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-128-8.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-16-32.png b/tools/linguist/linguist/images/icons/linguist-16-32.png
new file mode 100644
index 0000000000..8dfc97406c
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-16-32.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-16-8.png b/tools/linguist/linguist/images/icons/linguist-16-8.png
new file mode 100644
index 0000000000..4f4e839555
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-16-8.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-32-32.png b/tools/linguist/linguist/images/icons/linguist-32-32.png
new file mode 100644
index 0000000000..d388cbd0ba
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-32-32.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-32-8.png b/tools/linguist/linguist/images/icons/linguist-32-8.png
new file mode 100644
index 0000000000..3db4bc5c02
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-32-8.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-48-32.png b/tools/linguist/linguist/images/icons/linguist-48-32.png
new file mode 100644
index 0000000000..ceb7387593
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-48-32.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-48-8.png b/tools/linguist/linguist/images/icons/linguist-48-8.png
new file mode 100644
index 0000000000..9a13c201d8
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-48-8.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-64-32.png b/tools/linguist/linguist/images/icons/linguist-64-32.png
new file mode 100644
index 0000000000..0cce805e36
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-64-32.png
Binary files differ
diff --git a/tools/linguist/linguist/images/icons/linguist-64-8.png b/tools/linguist/linguist/images/icons/linguist-64-8.png
new file mode 100644
index 0000000000..05c833dc97
--- /dev/null
+++ b/tools/linguist/linguist/images/icons/linguist-64-8.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/accelerator.png b/tools/linguist/linguist/images/mac/accelerator.png
new file mode 100644
index 0000000000..9a684c1041
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/accelerator.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/book.png b/tools/linguist/linguist/images/mac/book.png
new file mode 100644
index 0000000000..7a3204c870
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/book.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/doneandnext.png b/tools/linguist/linguist/images/mac/doneandnext.png
new file mode 100644
index 0000000000..512fea8847
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/doneandnext.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/editcopy.png b/tools/linguist/linguist/images/mac/editcopy.png
new file mode 100644
index 0000000000..f551364464
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/editcopy.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/editcut.png b/tools/linguist/linguist/images/mac/editcut.png
new file mode 100644
index 0000000000..a784fd5709
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/editcut.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/editpaste.png b/tools/linguist/linguist/images/mac/editpaste.png
new file mode 100644
index 0000000000..64c0b2d6ab
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/editpaste.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/filenew.png b/tools/linguist/linguist/images/mac/filenew.png
new file mode 100644
index 0000000000..d3882c7b3f
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/filenew.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/fileopen.png b/tools/linguist/linguist/images/mac/fileopen.png
new file mode 100644
index 0000000000..fc06c5ec63
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/fileopen.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/fileprint.png b/tools/linguist/linguist/images/mac/fileprint.png
new file mode 100644
index 0000000000..808c97ea3c
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/fileprint.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/filesave.png b/tools/linguist/linguist/images/mac/filesave.png
new file mode 100644
index 0000000000..b41ecf5319
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/filesave.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/next.png b/tools/linguist/linguist/images/mac/next.png
new file mode 100644
index 0000000000..ba0792c367
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/next.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/nextunfinished.png b/tools/linguist/linguist/images/mac/nextunfinished.png
new file mode 100644
index 0000000000..bffbf0bb15
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/nextunfinished.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/phrase.png b/tools/linguist/linguist/images/mac/phrase.png
new file mode 100644
index 0000000000..6512341094
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/phrase.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/prev.png b/tools/linguist/linguist/images/mac/prev.png
new file mode 100644
index 0000000000..612fb34dce
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/prev.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/prevunfinished.png b/tools/linguist/linguist/images/mac/prevunfinished.png
new file mode 100644
index 0000000000..4d937b2a2c
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/prevunfinished.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/print.png b/tools/linguist/linguist/images/mac/print.png
new file mode 100644
index 0000000000..10ca56c82a
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/print.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/punctuation.png b/tools/linguist/linguist/images/mac/punctuation.png
new file mode 100644
index 0000000000..4719fc68ff
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/punctuation.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/redo.png b/tools/linguist/linguist/images/mac/redo.png
new file mode 100644
index 0000000000..8875bf246c
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/redo.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/searchfind.png b/tools/linguist/linguist/images/mac/searchfind.png
new file mode 100644
index 0000000000..3561745f01
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/searchfind.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/undo.png b/tools/linguist/linguist/images/mac/undo.png
new file mode 100644
index 0000000000..a3bd5e0bf2
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/undo.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/validateplacemarkers.png b/tools/linguist/linguist/images/mac/validateplacemarkers.png
new file mode 100644
index 0000000000..18ccc4cbc8
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/validateplacemarkers.png
Binary files differ
diff --git a/tools/linguist/linguist/images/mac/whatsthis.png b/tools/linguist/linguist/images/mac/whatsthis.png
new file mode 100644
index 0000000000..5b7078fffd
--- /dev/null
+++ b/tools/linguist/linguist/images/mac/whatsthis.png
Binary files differ
diff --git a/tools/linguist/linguist/images/s_check_danger.png b/tools/linguist/linguist/images/s_check_danger.png
new file mode 100644
index 0000000000..e10157768c
--- /dev/null
+++ b/tools/linguist/linguist/images/s_check_danger.png
Binary files differ
diff --git a/tools/linguist/linguist/images/s_check_empty.png b/tools/linguist/linguist/images/s_check_empty.png
new file mode 100644
index 0000000000..759a41b6c1
--- /dev/null
+++ b/tools/linguist/linguist/images/s_check_empty.png
Binary files differ
diff --git a/tools/linguist/linguist/images/s_check_obsolete.png b/tools/linguist/linguist/images/s_check_obsolete.png
new file mode 100644
index 0000000000..b852b639fe
--- /dev/null
+++ b/tools/linguist/linguist/images/s_check_obsolete.png
Binary files differ
diff --git a/tools/linguist/linguist/images/s_check_off.png b/tools/linguist/linguist/images/s_check_off.png
new file mode 100644
index 0000000000..640b689729
--- /dev/null
+++ b/tools/linguist/linguist/images/s_check_off.png
Binary files differ
diff --git a/tools/linguist/linguist/images/s_check_on.png b/tools/linguist/linguist/images/s_check_on.png
new file mode 100644
index 0000000000..afcaf634dd
--- /dev/null
+++ b/tools/linguist/linguist/images/s_check_on.png
Binary files differ
diff --git a/tools/linguist/linguist/images/s_check_warning.png b/tools/linguist/linguist/images/s_check_warning.png
new file mode 100644
index 0000000000..f689c33031
--- /dev/null
+++ b/tools/linguist/linguist/images/s_check_warning.png
Binary files differ
diff --git a/tools/linguist/linguist/images/splash.png b/tools/linguist/linguist/images/splash.png
new file mode 100644
index 0000000000..0e99a1cf0c
--- /dev/null
+++ b/tools/linguist/linguist/images/splash.png
Binary files differ
diff --git a/tools/linguist/linguist/images/transbox.png b/tools/linguist/linguist/images/transbox.png
new file mode 100644
index 0000000000..2d7219bd64
--- /dev/null
+++ b/tools/linguist/linguist/images/transbox.png
Binary files differ
diff --git a/tools/linguist/linguist/images/up.png b/tools/linguist/linguist/images/up.png
new file mode 100644
index 0000000000..e437312217
--- /dev/null
+++ b/tools/linguist/linguist/images/up.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/accelerator.png b/tools/linguist/linguist/images/win/accelerator.png
new file mode 100644
index 0000000000..c423c12cf9
--- /dev/null
+++ b/tools/linguist/linguist/images/win/accelerator.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/book.png b/tools/linguist/linguist/images/win/book.png
new file mode 100644
index 0000000000..09ec4d33f7
--- /dev/null
+++ b/tools/linguist/linguist/images/win/book.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/doneandnext.png b/tools/linguist/linguist/images/win/doneandnext.png
new file mode 100644
index 0000000000..9d1d58d6a0
--- /dev/null
+++ b/tools/linguist/linguist/images/win/doneandnext.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/editcopy.png b/tools/linguist/linguist/images/win/editcopy.png
new file mode 100644
index 0000000000..1121b47d8b
--- /dev/null
+++ b/tools/linguist/linguist/images/win/editcopy.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/editcut.png b/tools/linguist/linguist/images/win/editcut.png
new file mode 100644
index 0000000000..4b6c82c7a7
--- /dev/null
+++ b/tools/linguist/linguist/images/win/editcut.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/editpaste.png b/tools/linguist/linguist/images/win/editpaste.png
new file mode 100644
index 0000000000..ffab15aaf8
--- /dev/null
+++ b/tools/linguist/linguist/images/win/editpaste.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/filenew.png b/tools/linguist/linguist/images/win/filenew.png
new file mode 100644
index 0000000000..af5d122141
--- /dev/null
+++ b/tools/linguist/linguist/images/win/filenew.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/fileopen.png b/tools/linguist/linguist/images/win/fileopen.png
new file mode 100644
index 0000000000..fc6f17e977
--- /dev/null
+++ b/tools/linguist/linguist/images/win/fileopen.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/filesave.png b/tools/linguist/linguist/images/win/filesave.png
new file mode 100644
index 0000000000..8feec99bee
--- /dev/null
+++ b/tools/linguist/linguist/images/win/filesave.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/next.png b/tools/linguist/linguist/images/win/next.png
new file mode 100644
index 0000000000..8df4127a00
--- /dev/null
+++ b/tools/linguist/linguist/images/win/next.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/nextunfinished.png b/tools/linguist/linguist/images/win/nextunfinished.png
new file mode 100644
index 0000000000..636b9213b5
--- /dev/null
+++ b/tools/linguist/linguist/images/win/nextunfinished.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/phrase.png b/tools/linguist/linguist/images/win/phrase.png
new file mode 100644
index 0000000000..8ff952c518
--- /dev/null
+++ b/tools/linguist/linguist/images/win/phrase.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/prev.png b/tools/linguist/linguist/images/win/prev.png
new file mode 100644
index 0000000000..0780bc23dd
--- /dev/null
+++ b/tools/linguist/linguist/images/win/prev.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/prevunfinished.png b/tools/linguist/linguist/images/win/prevunfinished.png
new file mode 100644
index 0000000000..139d11b03e
--- /dev/null
+++ b/tools/linguist/linguist/images/win/prevunfinished.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/print.png b/tools/linguist/linguist/images/win/print.png
new file mode 100644
index 0000000000..ba7c02dc18
--- /dev/null
+++ b/tools/linguist/linguist/images/win/print.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/punctuation.png b/tools/linguist/linguist/images/win/punctuation.png
new file mode 100644
index 0000000000..e2372a2efd
--- /dev/null
+++ b/tools/linguist/linguist/images/win/punctuation.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/redo.png b/tools/linguist/linguist/images/win/redo.png
new file mode 100644
index 0000000000..686ad141c6
--- /dev/null
+++ b/tools/linguist/linguist/images/win/redo.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/searchfind.png b/tools/linguist/linguist/images/win/searchfind.png
new file mode 100644
index 0000000000..6ea35e930d
--- /dev/null
+++ b/tools/linguist/linguist/images/win/searchfind.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/undo.png b/tools/linguist/linguist/images/win/undo.png
new file mode 100644
index 0000000000..c3b8c51368
--- /dev/null
+++ b/tools/linguist/linguist/images/win/undo.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/validateplacemarkers.png b/tools/linguist/linguist/images/win/validateplacemarkers.png
new file mode 100644
index 0000000000..cc127fde9f
--- /dev/null
+++ b/tools/linguist/linguist/images/win/validateplacemarkers.png
Binary files differ
diff --git a/tools/linguist/linguist/images/win/whatsthis.png b/tools/linguist/linguist/images/win/whatsthis.png
new file mode 100644
index 0000000000..623cad6876
--- /dev/null
+++ b/tools/linguist/linguist/images/win/whatsthis.png
Binary files differ
diff --git a/tools/linguist/linguist/linguist.icns b/tools/linguist/linguist/linguist.icns
new file mode 100644
index 0000000000..5918e001c5
--- /dev/null
+++ b/tools/linguist/linguist/linguist.icns
Binary files differ
diff --git a/tools/linguist/linguist/linguist.ico b/tools/linguist/linguist/linguist.ico
new file mode 100644
index 0000000000..5bbdc485ba
--- /dev/null
+++ b/tools/linguist/linguist/linguist.ico
Binary files differ
diff --git a/tools/linguist/linguist/linguist.pro b/tools/linguist/linguist/linguist.pro
new file mode 100644
index 0000000000..417ef67f5c
--- /dev/null
+++ b/tools/linguist/linguist/linguist.pro
@@ -0,0 +1,107 @@
+TEMPLATE = app
+LANGUAGE = C++
+DESTDIR = ../../../bin
+
+QT += xml \
+ network
+
+CONFIG += qt \
+ warn_on \
+ uitools
+
+DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+include(../shared/formats.pri)
+
+DEFINES += QFORMINTERNAL_NAMESPACE
+INCLUDEPATH += ../../designer/src/uitools
+INCLUDEPATH += ../../designer/src/lib/uilib
+
+SOURCES += \
+ batchtranslationdialog.cpp \
+ errorsview.cpp \
+ finddialog.cpp \
+ formpreviewview.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ messageeditor.cpp \
+ messageeditorwidgets.cpp \
+ messagehighlighter.cpp \
+ messagemodel.cpp \
+ phrasebookbox.cpp \
+ phrase.cpp \
+ phrasemodel.cpp \
+ phraseview.cpp \
+ printout.cpp \
+ recentfiles.cpp \
+ sourcecodeview.cpp \
+ statistics.cpp \
+ translatedialog.cpp \
+ translationsettingsdialog.cpp \
+ ../shared/simtexth.cpp
+
+HEADERS += \
+ batchtranslationdialog.h \
+ errorsview.h \
+ finddialog.h \
+ formpreviewview.h \
+ mainwindow.h \
+ messageeditor.h \
+ messageeditorwidgets.h \
+ messagehighlighter.h \
+ messagemodel.h \
+ phrasebookbox.h \
+ phrase.h \
+ phrasemodel.h \
+ phraseview.h \
+ printout.h \
+ recentfiles.h \
+ sourcecodeview.h \
+ statistics.h \
+ translatedialog.h \
+ translationsettingsdialog.h \
+ ../shared/simtexth.h
+
+contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE
+DEFINES += QT_KEYWORDS
+TARGET = linguist
+win32:RC_FILE = linguist.rc
+mac {
+ static:CONFIG -= global_init_link_order
+ ICON = linguist.icns
+ TARGET = Linguist
+ QMAKE_INFO_PLIST=Info_mac.plist
+}
+PROJECTNAME = Qt \
+ Linguist
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+linguisttranslations.files = *.qm
+linguisttranslations.path = $$[QT_INSTALL_TRANSLATIONS]
+INSTALLS += linguisttranslations
+phrasebooks.path = $$[QT_INSTALL_DATA]/phrasebooks
+
+# ## will this work on windows?
+phrasebooks.files = $$QT_SOURCE_TREE/tools/linguist/phrasebooks/*
+INSTALLS += phrasebooks
+FORMS += statistics.ui \
+ phrasebookbox.ui \
+ batchtranslation.ui \
+ translatedialog.ui \
+ mainwindow.ui \
+ translationsettings.ui \
+ finddialog.ui
+RESOURCES += linguist.qrc
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/linguist_ja.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/linguist_pl.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/linguist_untranslated.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/linguist_tr_TR.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/linguist_zh_CN.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/linguist_zh_TW.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/linguist_de.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/linguist_fr.ts
diff --git a/tools/linguist/linguist/linguist.qrc b/tools/linguist/linguist/linguist.qrc
new file mode 100644
index 0000000000..42cf6e3ab4
--- /dev/null
+++ b/tools/linguist/linguist/linguist.qrc
@@ -0,0 +1,56 @@
+<RCC>
+ <qresource prefix="/" >
+ <file>images/appicon.png</file>
+ <file>images/mac/accelerator.png</file>
+ <file>images/mac/book.png</file>
+ <file>images/mac/doneandnext.png</file>
+ <file>images/mac/editcopy.png</file>
+ <file>images/mac/editcut.png</file>
+ <file>images/mac/editpaste.png</file>
+ <file>images/mac/fileopen.png</file>
+ <file>images/mac/filesave.png</file>
+ <file>images/mac/next.png</file>
+ <file>images/mac/nextunfinished.png</file>
+ <file>images/mac/phrase.png</file>
+ <file>images/mac/prev.png</file>
+ <file>images/mac/prevunfinished.png</file>
+ <file>images/mac/print.png</file>
+ <file>images/mac/punctuation.png</file>
+ <file>images/mac/redo.png</file>
+ <file>images/mac/searchfind.png</file>
+ <file>images/mac/undo.png</file>
+ <file>images/mac/validateplacemarkers.png</file>
+ <file>images/mac/whatsthis.png</file>
+ <file>images/s_check_danger.png</file>
+ <file>images/s_check_empty.png</file>
+ <file>images/s_check_obsolete.png</file>
+ <file>images/s_check_off.png</file>
+ <file>images/s_check_on.png</file>
+ <file>images/s_check_warning.png</file>
+ <file>images/splash.png</file>
+ <file>images/transbox.png</file>
+ <file>images/up.png</file>
+ <file>images/down.png</file>
+ <file>images/editdelete.png</file>
+ <file>images/win/accelerator.png</file>
+ <file>images/win/book.png</file>
+ <file>images/win/doneandnext.png</file>
+ <file>images/win/editcopy.png</file>
+ <file>images/win/editcut.png</file>
+ <file>images/win/editpaste.png</file>
+ <file>images/win/fileopen.png</file>
+ <file>images/win/filesave.png</file>
+ <file>images/win/next.png</file>
+ <file>images/win/nextunfinished.png</file>
+ <file>images/win/phrase.png</file>
+ <file>images/win/prev.png</file>
+ <file>images/win/prevunfinished.png</file>
+ <file>images/win/print.png</file>
+ <file>images/win/punctuation.png</file>
+ <file>images/win/redo.png</file>
+ <file>images/win/searchfind.png</file>
+ <file>images/win/undo.png</file>
+ <file>images/win/validateplacemarkers.png</file>
+ <file>images/win/whatsthis.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/linguist/linguist/linguist.rc b/tools/linguist/linguist/linguist.rc
new file mode 100644
index 0000000000..865e021c47
--- /dev/null
+++ b/tools/linguist/linguist/linguist.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "linguist.ico"
diff --git a/tools/linguist/linguist/main.cpp b/tools/linguist/linguist/main.cpp
new file mode 100644
index 0000000000..018fbc5f7d
--- /dev/null
+++ b/tools/linguist/linguist/main.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QLibraryInfo>
+#include <QtCore/QLocale>
+#include <QtCore/QSettings>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTranslator>
+
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QPixmap>
+#include <QtGui/QSplashScreen>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ Q_INIT_RESOURCE(linguist);
+
+ QApplication app(argc, argv);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+
+ QStringList files;
+ QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+ QStringList args = app.arguments();
+
+ for (int i = 1; i < args.count(); ++i) {
+ QString argument = args.at(i);
+ if (argument == QLatin1String("-resourcedir")) {
+ if (i + 1 < args.count()) {
+ resourceDir = QFile::decodeName(args.at(++i).toLocal8Bit());
+ } else {
+ // issue a warning
+ }
+ } else if (!files.contains(argument)) {
+ files.append(argument);
+ }
+ }
+
+ QTranslator translator;
+ translator.load(QLatin1String("linguist_") + QLocale::system().name(), resourceDir);
+ app.installTranslator(&translator);
+
+ QTranslator qtTranslator;
+ qtTranslator.load(QLatin1String("qt_") + QLocale::system().name(), resourceDir);
+ app.installTranslator(&qtTranslator);
+
+ app.setOrganizationName(QLatin1String("Trolltech"));
+ app.setApplicationName(QLatin1String("Linguist"));
+ QString keybase(QString::number( (QT_VERSION >> 16) & 0xff ) +
+ QLatin1Char('.') + QString::number( (QT_VERSION >> 8) & 0xff ) + QLatin1Char('/') );
+
+ QSettings config;
+
+ QWidget tmp;
+ tmp.restoreGeometry(config.value(keybase + QLatin1String("Geometry/WindowGeometry")).toByteArray());
+
+ QSplashScreen *splash = 0;
+ int screenId = QApplication::desktop()->screenNumber(tmp.geometry().center());
+ splash = new QSplashScreen(QApplication::desktop()->screen(screenId),
+ QPixmap(QLatin1String(":/images/splash.png")));
+ if (QApplication::desktop()->isVirtualDesktop()) {
+ QRect srect(0, 0, splash->width(), splash->height());
+ splash->move(QApplication::desktop()->availableGeometry(screenId).center() - srect.center());
+ }
+ splash->setAttribute(Qt::WA_DeleteOnClose);
+ splash->show();
+
+ MainWindow mw;
+ mw.show();
+ splash->finish(&mw);
+ QApplication::restoreOverrideCursor();
+
+ mw.openFiles(files, true);
+
+ return app.exec();
+}
diff --git a/tools/linguist/linguist/mainwindow.cpp b/tools/linguist/linguist/mainwindow.cpp
new file mode 100644
index 0000000000..e0a8a56712
--- /dev/null
+++ b/tools/linguist/linguist/mainwindow.cpp
@@ -0,0 +1,2673 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* TRANSLATOR MainWindow
+
+ This is the application's main window.
+*/
+
+#include "mainwindow.h"
+
+#include "batchtranslationdialog.h"
+#include "errorsview.h"
+#include "finddialog.h"
+#include "formpreviewview.h"
+#include "messageeditor.h"
+#include "messagemodel.h"
+#include "phrasebookbox.h"
+#include "phrasemodel.h"
+#include "phraseview.h"
+#include "printout.h"
+#include "sourcecodeview.h"
+#include "statistics.h"
+#include "translatedialog.h"
+#include "translationsettingsdialog.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QBitmap>
+#include <QCloseEvent>
+#include <QDebug>
+#include <QDesktopWidget>
+#include <QDockWidget>
+#include <QFile>
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QHeaderView>
+#include <QInputDialog>
+#include <QItemDelegate>
+#include <QLabel>
+#include <QLayout>
+#include <QLibraryInfo>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPrintDialog>
+#include <QProcess>
+#include <QRegExp>
+#include <QSettings>
+#include <QSortFilterProxyModel>
+#include <QStackedWidget>
+#include <QStatusBar>
+#include <QTextStream>
+#include <QToolBar>
+#include <QUrl>
+#include <QWhatsThis>
+
+QT_BEGIN_NAMESPACE
+
+static const int MessageMS = 2500;
+
+const QString &settingsPrefix()
+{
+ static QString prefix = QString(QLatin1String("%1.%2/"))
+ .arg((QT_VERSION >> 16) & 0xff)
+ .arg((QT_VERSION >> 8) & 0xff);
+ return prefix;
+}
+
+enum Ending {
+ End_None,
+ End_FullStop,
+ End_Interrobang,
+ End_Colon,
+ End_Ellipsis
+};
+
+static bool hasFormPreview(const QString &fileName)
+{
+ return fileName.endsWith(QLatin1String(".ui"))
+ || fileName.endsWith(QLatin1String(".jui"));
+}
+
+static Ending ending(QString str, QLocale::Language lang)
+{
+ str = str.simplified();
+ int ch = 0;
+ if (!str.isEmpty())
+ ch = str.right(1)[0].unicode();
+
+ switch (ch) {
+ case 0x002e: // full stop
+ if (str.endsWith(QString(QLatin1String("..."))))
+ return End_Ellipsis;
+ else
+ return End_FullStop;
+ case 0x0589: // armenian full stop
+ case 0x06d4: // arabic full stop
+ case 0x3002: // ideographic full stop
+ return End_FullStop;
+ case 0x0021: // exclamation mark
+ case 0x003f: // question mark
+ case 0x00a1: // inverted exclamation mark
+ case 0x00bf: // inverted question mark
+ case 0x01c3: // latin letter retroflex click
+ case 0x037e: // greek question mark
+ case 0x061f: // arabic question mark
+ case 0x203c: // double exclamation mark
+ case 0x203d: // interrobang
+ case 0x2048: // question exclamation mark
+ case 0x2049: // exclamation question mark
+ case 0x2762: // heavy exclamation mark ornament
+ return End_Interrobang;
+ case 0x003b: // greek 'compatibility' questionmark
+ return lang == QLocale::Greek ? End_Interrobang : End_None;
+ case 0x003a: // colon
+ return End_Colon;
+ case 0x2026: // horizontal ellipsis
+ return End_Ellipsis;
+ default:
+ return End_None;
+ }
+}
+
+
+class ContextItemDelegate : public QItemDelegate
+{
+public:
+ ContextItemDelegate(QObject *parent, MultiDataModel *model) : QItemDelegate(parent), m_dataModel(model) {}
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+ {
+ const QAbstractItemModel *model = index.model();
+ Q_ASSERT(model);
+
+ if (!model->parent(index).isValid()) {
+ if (index.column() - 1 == m_dataModel->modelCount()) {
+ QStyleOptionViewItem opt = option;
+ opt.font.setBold(true);
+ QItemDelegate::paint(painter, opt, index);
+ return;
+ }
+ }
+ QItemDelegate::paint(painter, option, index);
+ }
+
+private:
+ MultiDataModel *m_dataModel;
+};
+
+static const QVariant &pxObsolete()
+{
+ static const QVariant v =
+ qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png")));
+ return v;
+}
+
+
+class SortedMessagesModel : public QSortFilterProxyModel
+{
+public:
+ SortedMessagesModel(QObject *parent, MultiDataModel *model) : QSortFilterProxyModel(parent), m_dataModel(model) {}
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const
+ {
+ if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
+ switch (section - m_dataModel->modelCount()) {
+ case 0: return QString();
+ case 1: return MainWindow::tr("Source text");
+ case 2: return MainWindow::tr("Index");
+ }
+
+ if (role == Qt::DecorationRole && orientation == Qt::Horizontal && section - 1 < m_dataModel->modelCount())
+ return pxObsolete();
+
+ return QVariant();
+ }
+
+private:
+ MultiDataModel *m_dataModel;
+};
+
+class SortedContextsModel : public QSortFilterProxyModel
+{
+public:
+ SortedContextsModel(QObject *parent, MultiDataModel *model) : QSortFilterProxyModel(parent), m_dataModel(model) {}
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const
+ {
+ if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
+ switch (section - m_dataModel->modelCount()) {
+ case 0: return QString();
+ case 1: return MainWindow::tr("Context");
+ case 2: return MainWindow::tr("Items");
+ case 3: return MainWindow::tr("Index");
+ }
+
+ if (role == Qt::DecorationRole && orientation == Qt::Horizontal && section - 1 < m_dataModel->modelCount())
+ return pxObsolete();
+
+ return QVariant();
+ }
+
+private:
+ MultiDataModel *m_dataModel;
+};
+
+class FocusWatcher : public QObject
+{
+public:
+ FocusWatcher(MessageEditor *msgedit, QObject *parent) : QObject(parent), m_messageEditor(msgedit) {}
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+
+private:
+ MessageEditor *m_messageEditor;
+};
+
+bool FocusWatcher::eventFilter(QObject *, QEvent *event)
+{
+ if (event->type() == QEvent::FocusIn)
+ m_messageEditor->setEditorFocus(-1);
+ return false;
+}
+
+MainWindow::MainWindow()
+ : QMainWindow(0, Qt::Window),
+ m_assistantProcess(0),
+ m_findMatchCase(Qt::CaseInsensitive),
+ m_findIgnoreAccelerators(true),
+ m_findWhere(DataModel::NoLocation),
+ m_foundWhere(DataModel::NoLocation),
+ m_translationSettingsDialog(0),
+ m_settingCurrentMessage(false),
+ m_fileActiveModel(-1),
+ m_editActiveModel(-1),
+ m_statistics(0)
+{
+ m_ui.setupUi(this);
+
+#ifndef Q_WS_MAC
+ setWindowIcon(QPixmap(QLatin1String(":/images/appicon.png") ));
+#endif
+
+ m_dataModel = new MultiDataModel(this);
+ m_messageModel = new MessageModel(this, m_dataModel);
+
+ // Set up the context dock widget
+ m_contextDock = new QDockWidget(this);
+ m_contextDock->setObjectName(QLatin1String("ContextDockWidget"));
+ m_contextDock->setAllowedAreas(Qt::AllDockWidgetAreas);
+ m_contextDock->setFeatures(QDockWidget::AllDockWidgetFeatures);
+ m_contextDock->setWindowTitle(tr("Context"));
+ m_contextDock->setAcceptDrops(true);
+ m_contextDock->installEventFilter(this);
+
+ m_sortedContextsModel = new SortedContextsModel(this, m_dataModel);
+ m_sortedContextsModel->setSortRole(MessageModel::SortRole);
+ m_sortedContextsModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+ m_sortedContextsModel->setSourceModel(m_messageModel);
+
+ m_contextView = new QTreeView(this);
+ m_contextView->setRootIsDecorated(false);
+ m_contextView->setItemsExpandable(false);
+ m_contextView->setUniformRowHeights(true);
+ m_contextView->setAlternatingRowColors(true);
+ m_contextView->setAllColumnsShowFocus(true);
+ m_contextView->setItemDelegate(new ContextItemDelegate(this, m_dataModel));
+ m_contextView->setSortingEnabled(true);
+ m_contextView->setWhatsThis(tr("This panel lists the source contexts."));
+ m_contextView->setModel(m_sortedContextsModel);
+ m_contextView->header()->setMovable(false);
+ m_contextView->setColumnHidden(0, true);
+ m_contextView->header()->setResizeMode(1, QHeaderView::Stretch);
+ m_contextView->header()->setResizeMode(2, QHeaderView::ResizeToContents);
+ m_contextView->header()->setStretchLastSection(false);
+
+ m_contextDock->setWidget(m_contextView);
+
+ // Set up the messages dock widget
+ m_messagesDock = new QDockWidget(this);
+ m_messagesDock->setObjectName(QLatin1String("StringsDockWidget"));
+ m_messagesDock->setAllowedAreas(Qt::AllDockWidgetAreas);
+ m_messagesDock->setFeatures(QDockWidget::AllDockWidgetFeatures);
+ m_messagesDock->setWindowTitle(tr("Strings"));
+ m_messagesDock->setAcceptDrops(true);
+ m_messagesDock->installEventFilter(this);
+
+ m_sortedMessagesModel = new SortedMessagesModel(this, m_dataModel);
+ m_sortedMessagesModel->setSortRole(MessageModel::SortRole);
+ m_sortedMessagesModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+ m_sortedMessagesModel->setSortLocaleAware(true);
+ m_sortedMessagesModel->setSourceModel(m_messageModel);
+
+ m_messageView = new QTreeView(m_messagesDock);
+ m_messageView->setSortingEnabled(true);
+ m_messageView->setRootIsDecorated(false);
+ m_messageView->setUniformRowHeights(true);
+ m_messageView->setAllColumnsShowFocus(true);
+ m_messageView->setItemsExpandable(false);
+ m_messageView->setModel(m_sortedMessagesModel);
+ m_messageView->header()->setMovable(false);
+ m_messageView->setColumnHidden(0, true);
+ m_messageView->setColumnHidden(2, true);
+ // last visible column auto-stretches
+
+ m_messagesDock->setWidget(m_messageView);
+
+ // Set up main message view
+ m_messageEditor = new MessageEditor(m_dataModel, this);
+ m_messageEditor->setAcceptDrops(true);
+ m_messageEditor->installEventFilter(this);
+ // We can't call setCentralWidget(m_messageEditor), since it is already called in m_ui.setupUi()
+ QBoxLayout *lout = new QBoxLayout(QBoxLayout::TopToBottom, m_ui.centralwidget);
+ lout->addWidget(m_messageEditor);
+ lout->setMargin(0);
+ m_ui.centralwidget->setLayout(lout);
+
+ // Set up the phrases & guesses dock widget
+ m_phrasesDock = new QDockWidget(this);
+ m_phrasesDock->setObjectName(QLatin1String("PhrasesDockwidget"));
+ m_phrasesDock->setAllowedAreas(Qt::AllDockWidgetAreas);
+ m_phrasesDock->setFeatures(QDockWidget::AllDockWidgetFeatures);
+ m_phrasesDock->setWindowTitle(tr("Phrases and guesses"));
+
+ m_phraseView = new PhraseView(m_dataModel, &m_phraseDict, this);
+ m_phrasesDock->setWidget(m_phraseView);
+
+ // Set up source code and form preview dock widget
+ m_sourceAndFormDock = new QDockWidget(this);
+ m_sourceAndFormDock->setObjectName(QLatin1String("SourceAndFormDock"));
+ m_sourceAndFormDock->setAllowedAreas(Qt::AllDockWidgetAreas);
+ m_sourceAndFormDock->setFeatures(QDockWidget::AllDockWidgetFeatures);
+ m_sourceAndFormDock->setWindowTitle(tr("Sources and Forms"));
+ m_sourceAndFormView = new QStackedWidget(this);
+ m_sourceAndFormDock->setWidget(m_sourceAndFormView);
+ //connect(m_sourceAndDock, SIGNAL(visibilityChanged(bool)),
+ // m_sourceCodeView, SLOT(setActivated(bool)));
+ m_formPreviewView = new FormPreviewView(0, m_dataModel);
+ m_sourceCodeView = new SourceCodeView(0);
+ m_sourceAndFormView->addWidget(m_sourceCodeView);
+ m_sourceAndFormView->addWidget(m_formPreviewView);
+
+ // Set up errors dock widget
+ m_errorsDock = new QDockWidget(this);
+ m_errorsDock->setObjectName(QLatin1String("ErrorsDockWidget"));
+ m_errorsDock->setAllowedAreas(Qt::AllDockWidgetAreas);
+ m_errorsDock->setFeatures(QDockWidget::AllDockWidgetFeatures);
+ m_errorsDock->setWindowTitle(tr("Warnings"));
+ m_errorsView = new ErrorsView(m_dataModel, this);
+ m_errorsDock->setWidget(m_errorsView);
+
+ // Arrange dock widgets
+ setDockNestingEnabled(true);
+ setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
+ setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
+ setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+ addDockWidget(Qt::LeftDockWidgetArea, m_contextDock);
+ addDockWidget(Qt::TopDockWidgetArea, m_messagesDock);
+ addDockWidget(Qt::BottomDockWidgetArea, m_phrasesDock);
+ addDockWidget(Qt::TopDockWidgetArea, m_sourceAndFormDock);
+ addDockWidget(Qt::BottomDockWidgetArea, m_errorsDock);
+ //tabifyDockWidget(m_errorsDock, m_sourceAndFormDock);
+ //tabifyDockWidget(m_sourceCodeDock, m_phrasesDock);
+
+ // Allow phrases doc to intercept guesses shortcuts
+ m_messageEditor->installEventFilter(m_phraseView);
+
+ // Set up shortcuts for the dock widgets
+ QShortcut *contextShortcut = new QShortcut(QKeySequence(Qt::Key_F6), this);
+ connect(contextShortcut, SIGNAL(activated()), this, SLOT(showContextDock()));
+ QShortcut *messagesShortcut = new QShortcut(QKeySequence(Qt::Key_F7), this);
+ connect(messagesShortcut, SIGNAL(activated()), this, SLOT(showMessagesDock()));
+ QShortcut *errorsShortcut = new QShortcut(QKeySequence(Qt::Key_F8), this);
+ connect(errorsShortcut, SIGNAL(activated()), this, SLOT(showErrorDock()));
+ QShortcut *sourceCodeShortcut = new QShortcut(QKeySequence(Qt::Key_F9), this);
+ connect(sourceCodeShortcut, SIGNAL(activated()), this, SLOT(showSourceCodeDock()));
+ QShortcut *phrasesShortcut = new QShortcut(QKeySequence(Qt::Key_F10), this);
+ connect(phrasesShortcut, SIGNAL(activated()), this, SLOT(showPhrasesDock()));
+
+ connect(m_phraseView, SIGNAL(phraseSelected(int,QString)),
+ m_messageEditor, SLOT(setTranslation(int,QString)));
+ connect(m_contextView->selectionModel(),
+ SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
+ this, SLOT(selectedContextChanged(QModelIndex,QModelIndex)));
+ connect(m_messageView->selectionModel(),
+ SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
+ this, SLOT(selectedMessageChanged(QModelIndex,QModelIndex)));
+ connect(m_contextView->selectionModel(),
+ SIGNAL(currentColumnChanged(QModelIndex,QModelIndex)),
+ SLOT(updateLatestModel(QModelIndex)));
+ connect(m_messageView->selectionModel(),
+ SIGNAL(currentColumnChanged(QModelIndex,QModelIndex)),
+ SLOT(updateLatestModel(QModelIndex)));
+
+ connect(m_messageEditor, SIGNAL(activeModelChanged(int)), SLOT(updateActiveModel(int)));
+
+ m_translateDialog = new TranslateDialog(this);
+ m_batchTranslateDialog = new BatchTranslationDialog(m_dataModel, this);
+ m_findDialog = new FindDialog(this);
+
+ setupMenuBar();
+ setupToolBars();
+
+ m_progressLabel = new QLabel();
+ statusBar()->addPermanentWidget(m_progressLabel);
+ m_modifiedLabel = new QLabel(tr(" MOD ", "status bar: file(s) modified"));
+ statusBar()->addPermanentWidget(m_modifiedLabel);
+
+ modelCountChanged();
+ resetSorting();
+
+ connect(m_dataModel, SIGNAL(modifiedChanged(bool)),
+ this, SLOT(setWindowModified(bool)));
+ connect(m_dataModel, SIGNAL(modifiedChanged(bool)),
+ m_modifiedLabel, SLOT(setVisible(bool)));
+ connect(m_dataModel, SIGNAL(multiContextDataChanged(MultiDataIndex)),
+ SLOT(updateProgress()));
+ connect(m_dataModel, SIGNAL(messageDataChanged(MultiDataIndex)),
+ SLOT(maybeUpdateStatistics(MultiDataIndex)));
+ connect(m_dataModel, SIGNAL(translationChanged(MultiDataIndex)),
+ SLOT(translationChanged(MultiDataIndex)));
+ connect(m_dataModel, SIGNAL(languageChanged(int)),
+ SLOT(updatePhraseDict(int)));
+
+ setWindowModified(m_dataModel->isModified());
+ m_modifiedLabel->setVisible(m_dataModel->isModified());
+
+ connect(m_messageView, SIGNAL(clicked(QModelIndex)),
+ this, SLOT(toggleFinished(QModelIndex)));
+ connect(m_messageView, SIGNAL(activated(QModelIndex)),
+ m_messageEditor, SLOT(setEditorFocus()));
+ connect(m_contextView, SIGNAL(activated(QModelIndex)),
+ m_messageView, SLOT(setFocus()));
+ connect(m_messageEditor, SIGNAL(translationChanged(QStringList)),
+ this, SLOT(updateTranslation(QStringList)));
+ connect(m_messageEditor, SIGNAL(translatorCommentChanged(QString)),
+ this, SLOT(updateTranslatorComment(QString)));
+ connect(m_findDialog, SIGNAL(findNext(QString,DataModel::FindLocation,bool,bool)),
+ this, SLOT(findNext(QString,DataModel::FindLocation,bool,bool)));
+ connect(m_translateDialog, SIGNAL(requestMatchUpdate(bool &)), SLOT(updateTranslateHit(bool &)));
+ connect(m_translateDialog, SIGNAL(activated(int)), SLOT(translate(int)));
+
+ QSize as(qApp->desktop()->size());
+ as -= QSize(30, 30);
+ resize(QSize(1000, 800).boundedTo(as));
+ show();
+ readConfig();
+ m_statistics = 0;
+
+ m_focusWatcher = new FocusWatcher(m_messageEditor, this);
+ m_contextView->installEventFilter(m_focusWatcher);
+ m_messageView->installEventFilter(m_focusWatcher);
+ m_messageEditor->installEventFilter(m_focusWatcher);
+ m_sourceAndFormView->installEventFilter(m_focusWatcher);
+ m_phraseView->installEventFilter(m_focusWatcher);
+ m_errorsView->installEventFilter(m_focusWatcher);
+}
+
+MainWindow::~MainWindow()
+{
+ writeConfig();
+ if (m_assistantProcess && m_assistantProcess->state() == QProcess::Running) {
+ m_assistantProcess->terminate();
+ m_assistantProcess->waitForFinished(3000);
+ }
+ qDeleteAll(m_phraseBooks);
+ delete m_dataModel;
+ delete m_statistics;
+}
+
+void MainWindow::modelCountChanged()
+{
+ int mc = m_dataModel->modelCount();
+
+ for (int i = 0; i < mc; ++i) {
+ m_contextView->header()->setResizeMode(i + 1, QHeaderView::Fixed);
+ m_contextView->header()->resizeSection(i + 1, 24);
+
+ m_messageView->header()->setResizeMode(i + 1, QHeaderView::Fixed);
+ m_messageView->header()->resizeSection(i + 1, 24);
+ }
+
+ if (!mc) {
+ selectedMessageChanged(QModelIndex(), QModelIndex());
+ updateLatestModel(-1);
+ } else {
+ if (!m_contextView->currentIndex().isValid()) {
+ // Ensure that something is selected
+ m_contextView->setCurrentIndex(m_sortedContextsModel->index(0, 0));
+ } else {
+ // Plug holes that turn up in the selection due to inserting columns
+ m_contextView->selectionModel()->select(m_contextView->currentIndex(),
+ QItemSelectionModel::SelectCurrent|QItemSelectionModel::Rows);
+ m_messageView->selectionModel()->select(m_messageView->currentIndex(),
+ QItemSelectionModel::SelectCurrent|QItemSelectionModel::Rows);
+ }
+ // Field insertions/removals are automatic, but not the re-fill
+ m_messageEditor->showMessage(m_currentIndex);
+ if (mc == 1)
+ updateLatestModel(0);
+ else if (m_currentIndex.model() >= mc)
+ updateLatestModel(mc - 1);
+ }
+
+ m_contextView->setUpdatesEnabled(true);
+ m_messageView->setUpdatesEnabled(true);
+
+ updateProgress();
+ updateCaption();
+
+ m_ui.actionFind->setEnabled(m_dataModel->contextCount() > 0);
+ m_ui.actionFindNext->setEnabled(false);
+
+ m_formPreviewView->setSourceContext(-1, 0);
+}
+
+struct OpenedFile {
+ OpenedFile(DataModel *_dataModel, bool _readWrite, bool _langGuessed)
+ { dataModel = _dataModel; readWrite = _readWrite; langGuessed = _langGuessed; }
+ DataModel *dataModel;
+ bool readWrite;
+ bool langGuessed;
+};
+
+bool MainWindow::openFiles(const QStringList &names, bool globalReadWrite)
+{
+ if (names.isEmpty())
+ return false;
+
+ bool waitCursor = false;
+ statusBar()->showMessage(tr("Loading..."));
+ qApp->processEvents();
+
+ QList<OpenedFile> opened;
+ bool closeOld = false;
+ foreach (QString name, names) {
+ if (!waitCursor) {
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ waitCursor = true;
+ }
+
+ bool readWrite = globalReadWrite;
+ if (name.startsWith(QLatin1Char('='))) {
+ name.remove(0, 1);
+ readWrite = false;
+ }
+ QFileInfo fi(name);
+ if (fi.exists()) // Make the loader error out instead of reading stdin
+ name = fi.canonicalFilePath();
+ if (m_dataModel->isFileLoaded(name) >= 0)
+ continue;
+
+ bool langGuessed;
+ DataModel *dm = new DataModel(m_dataModel);
+ if (!dm->load(name, &langGuessed, this)) {
+ delete dm;
+ continue;
+ }
+ if (opened.isEmpty()) {
+ if (!m_dataModel->isWellMergeable(dm)) {
+ QApplication::restoreOverrideCursor();
+ waitCursor = false;
+ switch (QMessageBox::information(this, tr("Loading File - Qt Linguist"),
+ tr("The file '%1' does not seem to be related to the currently open file(s) '%2'.\n\n"
+ "Close the open file(s) first?")
+ .arg(DataModel::prettifyPlainFileName(name), m_dataModel->condensedSrcFileNames(true)),
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No,
+ QMessageBox::Cancel | QMessageBox::Escape))
+ {
+ case QMessageBox::Cancel:
+ delete dm;
+ return false;
+ case QMessageBox::Yes:
+ closeOld = true;
+ break;
+ case QMessageBox::No:
+ break;
+ }
+ }
+ } else {
+ if (!opened.first().dataModel->isWellMergeable(dm)) {
+ QApplication::restoreOverrideCursor();
+ waitCursor = false;
+ switch (QMessageBox::information(this, tr("Loading File - Qt Linguist"),
+ tr("The file '%1' does not seem to be related to the file '%2'"
+ " which is being loaded as well.\n\n"
+ "Skip loading the first named file?")
+ .arg(DataModel::prettifyPlainFileName(name), opened.first().dataModel->srcFileName(true)),
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No,
+ QMessageBox::Cancel | QMessageBox::Escape))
+ {
+ case QMessageBox::Cancel:
+ delete dm;
+ foreach (const OpenedFile &op, opened)
+ delete op.dataModel;
+ return false;
+ case QMessageBox::Yes:
+ delete dm;
+ continue;
+ case QMessageBox::No:
+ break;
+ }
+ }
+ }
+ opened.append(OpenedFile(dm, readWrite, langGuessed));
+ }
+
+ if (closeOld) {
+ if (waitCursor) {
+ QApplication::restoreOverrideCursor();
+ waitCursor = false;
+ }
+ if (!closeAll()) {
+ foreach (const OpenedFile &op, opened)
+ delete op.dataModel;
+ return false;
+ }
+ }
+
+ foreach (const OpenedFile &op, opened) {
+ if (op.langGuessed) {
+ if (waitCursor) {
+ QApplication::restoreOverrideCursor();
+ waitCursor = false;
+ }
+ if (!m_translationSettingsDialog)
+ m_translationSettingsDialog = new TranslationSettingsDialog(this);
+ m_translationSettingsDialog->setDataModel(op.dataModel);
+ m_translationSettingsDialog->exec();
+ }
+ }
+
+ if (!waitCursor)
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_contextView->setUpdatesEnabled(false);
+ m_messageView->setUpdatesEnabled(false);
+ int totalCount = 0;
+ foreach (const OpenedFile &op, opened) {
+ m_phraseDict.append(QHash<QString, QList<Phrase *> >());
+ m_dataModel->append(op.dataModel, op.readWrite);
+ if (op.readWrite)
+ updatePhraseDictInternal(m_phraseDict.size() - 1);
+ totalCount += op.dataModel->messageCount();
+ }
+ statusBar()->showMessage(tr("%n translation unit(s) loaded.", 0, totalCount), MessageMS);
+ modelCountChanged();
+ recentFiles().addFiles(m_dataModel->srcFileNames());
+
+ revalidate();
+ QApplication::restoreOverrideCursor();
+ return true;
+}
+
+RecentFiles &MainWindow::recentFiles()
+{
+ static RecentFiles recentFiles(10);
+ return recentFiles;
+}
+
+const QString &MainWindow::resourcePrefix()
+{
+#ifdef Q_WS_MAC
+ static const QString prefix(QLatin1String(":/images/mac"));
+#else
+ static const QString prefix(QLatin1String(":/images/win"));
+#endif
+ return prefix;
+}
+
+void MainWindow::open()
+{
+ openFiles(pickTranslationFiles());
+}
+
+void MainWindow::openAux()
+{
+ openFiles(pickTranslationFiles(), false);
+}
+
+void MainWindow::closeFile()
+{
+ int model = m_currentIndex.model();
+ if (model >= 0 && maybeSave(model)) {
+ m_phraseDict.removeAt(model);
+ m_contextView->setUpdatesEnabled(false);
+ m_messageView->setUpdatesEnabled(false);
+ m_dataModel->close(model);
+ modelCountChanged();
+ }
+}
+
+bool MainWindow::closeAll()
+{
+ if (maybeSaveAll()) {
+ m_phraseDict.clear();
+ m_contextView->setUpdatesEnabled(false);
+ m_messageView->setUpdatesEnabled(false);
+ m_dataModel->closeAll();
+ modelCountChanged();
+ recentFiles().closeGroup();
+ return true;
+ }
+ return false;
+}
+
+static QString fileFilters(bool allFirst)
+{
+ static const QString pattern(QLatin1String("%1 (*.%2);;"));
+ QStringList allExtensions;
+ QString filter;
+ foreach (const Translator::FileFormat &format, Translator::registeredFileFormats()) {
+ if (format.fileType == Translator::FileFormat::TranslationSource && format.priority >= 0) {
+ filter.append(pattern.arg(format.description).arg(format.extension));
+ allExtensions.append(QLatin1String("*.") + format.extension);
+ }
+ }
+ QString allFilter = QObject::tr("Translation files (%1);;").arg(allExtensions.join(QLatin1String(" ")));
+ if (allFirst)
+ filter.prepend(allFilter);
+ else
+ filter.append(allFilter);
+ filter.append(QObject::tr("All files (*)"));
+ return filter;
+}
+
+QStringList MainWindow::pickTranslationFiles()
+{
+ QString dir;
+ if (!recentFiles().isEmpty())
+ dir = QFileInfo(recentFiles().lastOpenedFile()).path();
+
+ QString varFilt;
+ if (m_dataModel->modelCount()) {
+ QFileInfo mainFile(m_dataModel->srcFileName(0));
+ QString mainFileBase = mainFile.baseName();
+ int pos = mainFileBase.indexOf(QLatin1Char('_'));
+ if (pos > 0)
+ varFilt = tr("Related files (%1);;")
+ .arg(mainFileBase.left(pos) + QLatin1String("_*.") + mainFile.completeSuffix());
+ }
+
+ return QFileDialog::getOpenFileNames(this, tr("Open Translation Files"), dir,
+ varFilt +
+ fileFilters(true));
+}
+
+void MainWindow::saveInternal(int model)
+{
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ if (m_dataModel->save(model, this)) {
+ updateCaption();
+ statusBar()->showMessage(tr("File saved."), MessageMS);
+ }
+ QApplication::restoreOverrideCursor();
+}
+
+void MainWindow::saveAll()
+{
+ for (int i = 0; i < m_dataModel->modelCount(); ++i)
+ if (m_dataModel->isModelWritable(i))
+ saveInternal(i);
+ recentFiles().closeGroup();
+}
+
+void MainWindow::save()
+{
+ if (m_currentIndex.model() < 0)
+ return;
+
+ saveInternal(m_currentIndex.model());
+}
+
+void MainWindow::saveAs()
+{
+ if (m_currentIndex.model() < 0)
+ return;
+
+ QString newFilename = QFileDialog::getSaveFileName(this, QString(), m_dataModel->srcFileName(m_currentIndex.model()),
+ fileFilters(false));
+ if (!newFilename.isEmpty()) {
+ if (m_dataModel->saveAs(m_currentIndex.model(), newFilename, this)) {
+ updateCaption();
+ statusBar()->showMessage(tr("File saved."), MessageMS);
+ recentFiles().addFiles(m_dataModel->srcFileNames());
+ }
+ }
+}
+
+void MainWindow::releaseAs()
+{
+ if (m_currentIndex.model() < 0)
+ return;
+
+ QFileInfo oldFile(m_dataModel->srcFileName(m_currentIndex.model()));
+ QString newFilename = oldFile.path() + QLatin1String("/")
+ + oldFile.completeBaseName() + QLatin1String(".qm");
+
+ newFilename = QFileDialog::getSaveFileName(this, tr("Release"), newFilename,
+ tr("Qt message files for released applications (*.qm)\nAll files (*)"));
+ if (!newFilename.isEmpty()) {
+ if (m_dataModel->release(m_currentIndex.model(), newFilename, false, false, SaveEverything, this))
+ statusBar()->showMessage(tr("File created."), MessageMS);
+ }
+}
+
+void MainWindow::releaseInternal(int model)
+{
+ QFileInfo oldFile(m_dataModel->srcFileName(model));
+ QString newFilename = oldFile.path() + QLatin1Char('/')
+ + oldFile.completeBaseName() + QLatin1String(".qm");
+
+ if (!newFilename.isEmpty()) {
+ if (m_dataModel->release(model, newFilename, false, false, SaveEverything, this))
+ statusBar()->showMessage(tr("File created."), MessageMS);
+ }
+}
+
+// No-question
+void MainWindow::release()
+{
+ if (m_currentIndex.model() < 0)
+ return;
+
+ releaseInternal(m_currentIndex.model());
+}
+
+void MainWindow::releaseAll()
+{
+ for (int i = 0; i < m_dataModel->modelCount(); ++i)
+ if (m_dataModel->isModelWritable(i))
+ releaseInternal(i);
+}
+
+void MainWindow::print()
+{
+ int pageNum = 0;
+ QPrintDialog dlg(&m_printer, this);
+ if (dlg.exec()) {
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ m_printer.setDocName(m_dataModel->condensedSrcFileNames(true));
+ statusBar()->showMessage(tr("Printing..."));
+ PrintOut pout(&m_printer);
+
+ for (int i = 0; i < m_dataModel->contextCount(); ++i) {
+ MultiContextItem *mc = m_dataModel->multiContextItem(i);
+ pout.vskip();
+ pout.setRule(PrintOut::ThickRule);
+ pout.setGuide(mc->context());
+ pout.addBox(100, tr("Context: %1").arg(mc->context()),
+ PrintOut::Strong);
+ pout.flushLine();
+ pout.addBox(4);
+ pout.addBox(92, mc->comment(), PrintOut::Emphasis);
+ pout.flushLine();
+ pout.setRule(PrintOut::ThickRule);
+
+ for (int j = 0; j < mc->messageCount(); ++j) {
+ pout.setRule(PrintOut::ThinRule);
+ bool printedSrc = false;
+ QString comment;
+ for (int k = 0; k < m_dataModel->modelCount(); ++k) {
+ if (const MessageItem *m = mc->messageItem(k, j)) {
+ if (!printedSrc) {
+ pout.addBox(40, m->text());
+ pout.addBox(4);
+ comment = m->comment();
+ printedSrc = true;
+ } else {
+ pout.addBox(44); // Maybe put the name of the translation here
+ }
+ if (m->message().isPlural() && m_dataModel->language(k) != QLocale::C) {
+ QStringList transls = m->translations();
+ pout.addBox(40, transls.join(QLatin1String("\n")));
+ } else {
+ pout.addBox(40, m->translation());
+ }
+ pout.addBox(4);
+ QString type;
+ switch (m->message().type()) {
+ case TranslatorMessage::Finished:
+ type = tr("finished");
+ break;
+ case TranslatorMessage::Unfinished:
+ type = m->danger() ? tr("unresolved") : QLatin1String("unfinished");
+ break;
+ case TranslatorMessage::Obsolete:
+ type = tr("obsolete");
+ break;
+ }
+ pout.addBox(12, type, PrintOut::Normal, Qt::AlignRight);
+ pout.flushLine();
+ }
+ }
+ if (!comment.isEmpty()) {
+ pout.addBox(4);
+ pout.addBox(92, comment, PrintOut::Emphasis);
+ pout.flushLine(true);
+ }
+
+ if (pout.pageNum() != pageNum) {
+ pageNum = pout.pageNum();
+ statusBar()->showMessage(tr("Printing... (page %1)")
+ .arg(pageNum));
+ }
+ }
+ }
+ pout.flushLine(true);
+ QApplication::restoreOverrideCursor();
+ statusBar()->showMessage(tr("Printing completed"), MessageMS);
+ } else {
+ statusBar()->showMessage(tr("Printing aborted"), MessageMS);
+ }
+}
+
+bool MainWindow::searchItem(const QString &searchWhat)
+{
+ if ((m_findWhere & m_foundWhere) == 0)
+ return false;
+
+ QString text = searchWhat;
+
+ if (m_findIgnoreAccelerators)
+ // FIXME: This removes too much. The proper solution might be too slow, though.
+ text.remove(QLatin1Char('&'));
+
+ int foundOffset = text.indexOf(m_findText, 0, m_findMatchCase);
+ return foundOffset >= 0;
+}
+
+void MainWindow::findAgain()
+{
+ if (m_dataModel->contextCount() == 0)
+ return;
+
+ const QModelIndex &startIndex = m_messageView->currentIndex();
+ QModelIndex index = nextMessage(startIndex);
+
+ while (index.isValid()) {
+ QModelIndex realIndex = m_sortedMessagesModel->mapToSource(index);
+ MultiDataIndex dataIndex = m_messageModel->dataIndex(realIndex, -1);
+ bool hadMessage = false;
+ for (int i = 0; i < m_dataModel->modelCount(); ++i) {
+ if (MessageItem *m = m_dataModel->messageItem(dataIndex, i)) {
+ // Note: we do not look into plurals on grounds of them not
+ // containing anything much different from the singular.
+ if (hadMessage) {
+ m_foundWhere = DataModel::Translations;
+ if (!searchItem(m->translation()))
+ m_foundWhere = DataModel::NoLocation;
+ } else {
+ switch (m_foundWhere) {
+ case 0:
+ m_foundWhere = DataModel::SourceText;
+ // fall-through to search source text
+ case DataModel::SourceText:
+ if (searchItem(m->text()))
+ break;
+ if (searchItem(m->pluralText()))
+ break;
+ m_foundWhere = DataModel::Translations;
+ // fall-through to search translation
+ case DataModel::Translations:
+ if (searchItem(m->translation()))
+ break;
+ m_foundWhere = DataModel::Comments;
+ // fall-through to search comment
+ case DataModel::Comments:
+ if (searchItem(m->comment()))
+ break;
+ if (searchItem(m->extraComment()))
+ break;
+ m_foundWhere = DataModel::NoLocation;
+ // did not find the search string in this message
+ }
+ }
+ if (m_foundWhere != DataModel::NoLocation) {
+ setCurrentMessage(realIndex, i);
+
+ // determine whether the search wrapped
+ const QModelIndex &c1 = m_sortedContextsModel->mapFromSource(
+ m_sortedMessagesModel->mapToSource(startIndex)).parent();
+ const QModelIndex &c2 = m_sortedContextsModel->mapFromSource(realIndex).parent();
+ const QModelIndex &m = m_sortedMessagesModel->mapFromSource(realIndex);
+
+ if (c2.row() < c1.row() || (c1.row() == c2.row() && m.row() <= startIndex.row()))
+ statusBar()->showMessage(tr("Search wrapped."), MessageMS);
+
+ m_findDialog->hide();
+ return;
+ }
+ hadMessage = true;
+ }
+ }
+
+ // since we don't search startIndex at the beginning, only now we have searched everything
+ if (index == startIndex)
+ break;
+
+ index = nextMessage(index);
+ }
+
+ qApp->beep();
+ QMessageBox::warning(m_findDialog, tr("Qt Linguist"),
+ tr("Cannot find the string '%1'.").arg(m_findText));
+ m_foundWhere = DataModel::NoLocation;
+}
+
+void MainWindow::showBatchTranslateDialog()
+{
+ m_messageModel->blockSignals(true);
+ m_batchTranslateDialog->setPhraseBooks(m_phraseBooks, m_currentIndex.model());
+ if (m_batchTranslateDialog->exec() != QDialog::Accepted)
+ m_messageModel->blockSignals(false);
+ // else signal finished() calls refreshItemViews()
+}
+
+void MainWindow::showTranslateDialog()
+{
+ m_latestCaseSensitivity = -1;
+ QModelIndex idx = m_messageView->currentIndex();
+ QModelIndex idx2 = m_sortedMessagesModel->index(idx.row(), m_currentIndex.model() + 1, idx.parent());
+ m_messageView->setCurrentIndex(idx2);
+ QString fn = QFileInfo(m_dataModel->srcFileName(m_currentIndex.model())).baseName();
+ m_translateDialog->setWindowTitle(tr("Search And Translate in '%1' - Qt Linguist").arg(fn));
+ m_translateDialog->exec();
+}
+
+void MainWindow::updateTranslateHit(bool &hit)
+{
+ MessageItem *m;
+ hit = (m = m_dataModel->messageItem(m_currentIndex))
+ && !m->isObsolete()
+ && m->compare(m_translateDialog->findText(), false, m_translateDialog->caseSensitivity());
+}
+
+void MainWindow::translate(int mode)
+{
+ QString findText = m_translateDialog->findText();
+ QString replaceText = m_translateDialog->replaceText();
+ bool markFinished = m_translateDialog->markFinished();
+ Qt::CaseSensitivity caseSensitivity = m_translateDialog->caseSensitivity();
+
+ int translatedCount = 0;
+
+ if (mode == TranslateDialog::TranslateAll) {
+ for (MultiDataModelIterator it(m_dataModel, m_currentIndex.model()); it.isValid(); ++it) {
+ MessageItem *m = it.current();
+ if (m && !m->isObsolete() && m->compare(findText, false, caseSensitivity)) {
+ if (!translatedCount)
+ m_messageModel->blockSignals(true);
+ m_dataModel->setTranslation(it, replaceText);
+ m_dataModel->setFinished(it, markFinished);
+ ++translatedCount;
+ }
+ }
+ if (translatedCount) {
+ refreshItemViews();
+ QMessageBox::warning(m_translateDialog, tr("Translate - Qt Linguist"),
+ tr("Translated %n entry(s)", 0, translatedCount));
+ }
+ } else {
+ if (mode == TranslateDialog::Translate) {
+ m_dataModel->setTranslation(m_currentIndex, replaceText);
+ m_dataModel->setFinished(m_currentIndex, markFinished);
+ }
+
+ if (findText != m_latestFindText || caseSensitivity != m_latestCaseSensitivity) {
+ m_latestFindText = findText;
+ m_latestCaseSensitivity = caseSensitivity;
+ m_remainingCount = m_dataModel->messageCount();
+ m_hitCount = 0;
+ }
+
+ QModelIndex index = m_messageView->currentIndex();
+ int prevRemained = m_remainingCount;
+ forever {
+ if (--m_remainingCount <= 0) {
+ if (!m_hitCount)
+ break;
+ m_remainingCount = m_dataModel->messageCount() - 1;
+ if (QMessageBox::question(m_translateDialog, tr("Translate - Qt Linguist"),
+ tr("No more occurrences of '%1'. Start over?").arg(findText),
+ QMessageBox::Yes|QMessageBox::No) != QMessageBox::Yes)
+ return;
+ m_remainingCount -= prevRemained;
+ }
+
+ index = nextMessage(index);
+
+ QModelIndex realIndex = m_sortedMessagesModel->mapToSource(index);
+ MultiDataIndex dataIndex = m_messageModel->dataIndex(realIndex, m_currentIndex.model());
+ if (MessageItem *m = m_dataModel->messageItem(dataIndex)) {
+ if (!m->isObsolete() && m->compare(findText, false, caseSensitivity)) {
+ setCurrentMessage(realIndex, m_currentIndex.model());
+ ++translatedCount;
+ ++m_hitCount;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!translatedCount) {
+ qApp->beep();
+ QMessageBox::warning(m_translateDialog, tr("Translate - Qt Linguist"),
+ tr("Cannot find the string '%1'.").arg(findText));
+ }
+}
+
+void MainWindow::newPhraseBook()
+{
+ QString name = QFileDialog::getSaveFileName(this, tr("Create New Phrase Book"),
+ m_phraseBookDir, tr("Qt phrase books (*.qph)\nAll files (*)"));
+ if (!name.isEmpty()) {
+ PhraseBook pb;
+ if (!m_translationSettingsDialog)
+ m_translationSettingsDialog = new TranslationSettingsDialog(this);
+ m_translationSettingsDialog->setPhraseBook(&pb);
+ if (!m_translationSettingsDialog->exec())
+ return;
+ m_phraseBookDir = QFileInfo(name).absolutePath();
+ if (savePhraseBook(&name, pb)) {
+ if (openPhraseBook(name))
+ statusBar()->showMessage(tr("Phrase book created."), MessageMS);
+ }
+ }
+}
+
+bool MainWindow::isPhraseBookOpen(const QString &name)
+{
+ foreach(const PhraseBook *pb, m_phraseBooks) {
+ if (pb->fileName() == name)
+ return true;
+ }
+
+ return false;
+}
+
+void MainWindow::openPhraseBook()
+{
+ QString name = QFileDialog::getOpenFileName(this, tr("Open Phrase Book"),
+ m_phraseBookDir, tr("Qt phrase books (*.qph);;All files (*)"));
+
+ if (!name.isEmpty()) {
+ m_phraseBookDir = QFileInfo(name).absolutePath();
+ if (!isPhraseBookOpen(name)) {
+ if (PhraseBook *phraseBook = openPhraseBook(name)) {
+ int n = phraseBook->phrases().count();
+ statusBar()->showMessage(tr("%n phrase(s) loaded.", 0, n), MessageMS);
+ }
+ }
+ }
+}
+
+void MainWindow::closePhraseBook(QAction *action)
+{
+ PhraseBook *pb = m_phraseBookMenu[PhraseCloseMenu].value(action);
+ if (!maybeSavePhraseBook(pb))
+ return;
+
+ m_phraseBookMenu[PhraseCloseMenu].remove(action);
+ m_ui.menuClosePhraseBook->removeAction(action);
+
+ QAction *act = m_phraseBookMenu[PhraseEditMenu].key(pb);
+ m_phraseBookMenu[PhraseEditMenu].remove(act);
+ m_ui.menuEditPhraseBook->removeAction(act);
+
+ act = m_phraseBookMenu[PhrasePrintMenu].key(pb);
+ m_ui.menuPrintPhraseBook->removeAction(act);
+
+ m_phraseBooks.removeOne(pb);
+ disconnect(pb, SIGNAL(listChanged()), this, SLOT(updatePhraseDicts()));
+ updatePhraseDicts();
+ delete pb;
+ updatePhraseBookActions();
+}
+
+void MainWindow::editPhraseBook(QAction *action)
+{
+ PhraseBook *pb = m_phraseBookMenu[PhraseEditMenu].value(action);
+ PhraseBookBox box(pb, this);
+ box.exec();
+
+ updatePhraseDicts();
+}
+
+void MainWindow::printPhraseBook(QAction *action)
+{
+ PhraseBook *phraseBook = m_phraseBookMenu[PhrasePrintMenu].value(action);
+
+ int pageNum = 0;
+
+ QPrintDialog dlg(&m_printer, this);
+ if (dlg.exec()) {
+ m_printer.setDocName(phraseBook->fileName());
+ statusBar()->showMessage(tr("Printing..."));
+ PrintOut pout(&m_printer);
+ pout.setRule(PrintOut::ThinRule);
+ foreach (const Phrase *p, phraseBook->phrases()) {
+ pout.setGuide(p->source());
+ pout.addBox(29, p->source());
+ pout.addBox(4);
+ pout.addBox(29, p->target());
+ pout.addBox(4);
+ pout.addBox(34, p->definition(), PrintOut::Emphasis);
+
+ if (pout.pageNum() != pageNum) {
+ pageNum = pout.pageNum();
+ statusBar()->showMessage(tr("Printing... (page %1)")
+ .arg(pageNum));
+ }
+ pout.setRule(PrintOut::NoRule);
+ pout.flushLine(true);
+ }
+ pout.flushLine(true);
+ statusBar()->showMessage(tr("Printing completed"), MessageMS);
+ } else {
+ statusBar()->showMessage(tr("Printing aborted"), MessageMS);
+ }
+}
+
+void MainWindow::addToPhraseBook()
+{
+ MessageItem *currentMessage = m_dataModel->messageItem(m_currentIndex);
+ Phrase *phrase = new Phrase(currentMessage->text(), currentMessage->translation(), QString());
+ QStringList phraseBookList;
+ QHash<QString, PhraseBook *> phraseBookHash;
+ foreach (PhraseBook *pb, m_phraseBooks) {
+ if (pb->language() != QLocale::C && m_dataModel->language(m_currentIndex.model()) != QLocale::C) {
+ if (pb->language() != m_dataModel->language(m_currentIndex.model()))
+ continue;
+ if (pb->country() == m_dataModel->model(m_currentIndex.model())->country())
+ phraseBookList.prepend(pb->friendlyPhraseBookName());
+ else
+ phraseBookList.append(pb->friendlyPhraseBookName());
+ } else {
+ phraseBookList.append(pb->friendlyPhraseBookName());
+ }
+ phraseBookHash.insert(pb->friendlyPhraseBookName(), pb);
+ }
+ if (phraseBookList.isEmpty()) {
+ QMessageBox::warning(this, tr("Add to phrase book"),
+ tr("No appropriate phrasebook found."));
+ } else if (phraseBookList.size() == 1) {
+ if (QMessageBox::information(this, tr("Add to phrase book"),
+ tr("Adding entry to phrasebook %1").arg(phraseBookList.at(0)),
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok)
+ == QMessageBox::Ok)
+ phraseBookHash.value(phraseBookList.at(0))->append(phrase);
+ } else {
+ bool okPressed = false;
+ QString selection = QInputDialog::getItem(this, tr("Add to phrase book"),
+ tr("Select phrase book to add to"),
+ phraseBookList, 0, false, &okPressed);
+ if (okPressed)
+ phraseBookHash.value(selection)->append(phrase);
+ }
+}
+
+void MainWindow::resetSorting()
+{
+ m_contextView->sortByColumn(-1, Qt::AscendingOrder);
+ m_messageView->sortByColumn(-1, Qt::AscendingOrder);
+}
+
+void MainWindow::manual()
+{
+ if (!m_assistantProcess)
+ m_assistantProcess = new QProcess();
+
+ if (m_assistantProcess->state() != QProcess::Running) {
+ QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator();
+#if !defined(Q_OS_MAC)
+ app += QLatin1String("assistant");
+#else
+ app += QLatin1String("Assistant.app/Contents/MacOS/Assistant");
+#endif
+
+ m_assistantProcess->start(app, QStringList() << QLatin1String("-enableRemoteControl"));
+ if (!m_assistantProcess->waitForStarted()) {
+ QMessageBox::critical(this, tr("Qt Linguist"),
+ tr("Unable to launch Qt Assistant (%1)").arg(app));
+ return;
+ }
+ }
+
+ QTextStream str(m_assistantProcess);
+ str << QLatin1String("SetSource qthelp://com.trolltech.linguist.")
+ << (QT_VERSION >> 16) << ((QT_VERSION >> 8) & 0xFF)
+ << (QT_VERSION & 0xFF)
+ << QLatin1String("/qdoc/linguist-manual.html")
+ << QLatin1Char('\0') << endl;
+}
+
+void MainWindow::about()
+{
+ QMessageBox box(this);
+ box.setTextFormat(Qt::RichText);
+ QString version = tr("Version %1");
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ QString open = tr(" Open Source Edition");
+ version.append(open);
+#endif
+ version = version.arg(QLatin1String(QT_VERSION_STR));
+
+ QString edition =
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ tr("This version of Qt Linguist is part of the Qt Open Source Edition, for use "
+ "in the development of Open Source applications. "
+ "Qt is a comprehensive C++ framework for cross-platform application "
+ "development.<br/><br/>"
+ "You need a commercial Qt license for development of proprietary (closed "
+ "source) applications. Please see <tt>http://qtsoftware.com/company/model"
+ ".html</tt> for an overview of Qt licensing.");
+#elif defined(QT_PRODUCT_LICENSE)
+ tr("This program is licensed to you under the terms of the "
+ "Qt %1 License Agreement. For details, see the license file "
+ "that came with this software distribution.").arg(QLatin1String(QT_PRODUCT_LICENSE));
+#else
+ tr("This program is licensed to you under the terms of the "
+ "Qt Commercial License Agreement. For details, see the file LICENSE "
+ "that came with this software distribution.");
+#endif
+
+ box.setText(tr("<center><img src=\":/images/splash.png\"/></img><p>%1</p></center>"
+ "<p>Qt Linguist is a tool for adding translations to Qt "
+ "applications.</p>"
+ "<p>%2</p>"
+ "<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)."
+ "</p><p>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
+ " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
+ " PARTICULAR PURPOSE.</p>").arg(version).arg(edition));
+
+ box.setWindowTitle(QApplication::translate("AboutDialog", "Qt Linguist"));
+ box.setIcon(QMessageBox::NoIcon);
+ box.exec();
+}
+
+void MainWindow::aboutQt()
+{
+ QMessageBox::aboutQt(this, tr("Qt Linguist"));
+}
+
+void MainWindow::setupPhrase()
+{
+ bool enabled = !m_phraseBooks.isEmpty();
+ m_ui.menuClosePhraseBook->setEnabled(enabled);
+ m_ui.menuEditPhraseBook->setEnabled(enabled);
+ m_ui.menuPrintPhraseBook->setEnabled(enabled);
+}
+
+void MainWindow::closeEvent(QCloseEvent *e)
+{
+ if (maybeSaveAll() && closePhraseBooks())
+ e->accept();
+ else
+ e->ignore();
+}
+
+bool MainWindow::maybeSaveAll()
+{
+ if (!m_dataModel->isModified())
+ return true;
+
+ switch (QMessageBox::information(this, tr("Qt Linguist"),
+ tr("Do you want to save the modified files?"),
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No,
+ QMessageBox::Cancel | QMessageBox::Escape))
+ {
+ case QMessageBox::Cancel:
+ return false;
+ case QMessageBox::Yes:
+ saveAll();
+ return !m_dataModel->isModified();
+ case QMessageBox::No:
+ break;
+ }
+ return true;
+}
+
+bool MainWindow::maybeSave(int model)
+{
+ if (!m_dataModel->isModified(model))
+ return true;
+
+ switch (QMessageBox::information(this, tr("Qt Linguist"),
+ tr("Do you want to save '%1'?").arg(m_dataModel->srcFileName(model, true)),
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No,
+ QMessageBox::Cancel | QMessageBox::Escape))
+ {
+ case QMessageBox::Cancel:
+ return false;
+ case QMessageBox::Yes:
+ saveInternal(model);
+ return !m_dataModel->isModified(model);
+ case QMessageBox::No:
+ break;
+ }
+ return true;
+}
+
+void MainWindow::updateCaption()
+{
+ QString cap;
+ bool enable = false;
+ bool enableRw = false;
+ for (int i = 0; i < m_dataModel->modelCount(); ++i) {
+ enable = true;
+ if (m_dataModel->isModelWritable(i)) {
+ enableRw = true;
+ break;
+ }
+ }
+ m_ui.actionSaveAll->setEnabled(enableRw);
+ m_ui.actionReleaseAll->setEnabled(enableRw);
+ m_ui.actionCloseAll->setEnabled(enable);
+ m_ui.actionPrint->setEnabled(enable);
+ m_ui.actionAccelerators->setEnabled(enable);
+ m_ui.actionEndingPunctuation->setEnabled(enable);
+ m_ui.actionPhraseMatches->setEnabled(enable);
+ m_ui.actionPlaceMarkerMatches->setEnabled(enable);
+ m_ui.actionResetSorting->setEnabled(enable);
+
+ updateActiveModel(m_messageEditor->activeModel());
+ // Ensure that the action labels get updated
+ m_fileActiveModel = m_editActiveModel = -2;
+
+ if (!enable)
+ cap = tr("Qt Linguist[*]");
+ else
+ cap = tr("%1[*] - Qt Linguist").arg(m_dataModel->condensedSrcFileNames(true));
+ setWindowTitle(cap);
+}
+
+void MainWindow::selectedContextChanged(const QModelIndex &sortedIndex, const QModelIndex &oldIndex)
+{
+ if (sortedIndex.isValid()) {
+ if (m_settingCurrentMessage)
+ return; // Avoid playing ping-pong with the current message
+
+ QModelIndex sourceIndex = m_sortedContextsModel->mapToSource(sortedIndex);
+ if (m_messageModel->parent(currentMessageIndex()).row() == sourceIndex.row())
+ return;
+
+ QModelIndex contextIndex = setMessageViewRoot(sourceIndex);
+ const QModelIndex &firstChild =
+ m_sortedMessagesModel->index(0, sourceIndex.column(), contextIndex);
+ m_messageView->setCurrentIndex(firstChild);
+ } else if (oldIndex.isValid()) {
+ m_contextView->setCurrentIndex(oldIndex);
+ }
+}
+
+/*
+ * Updates the message displayed in the message editor and related actions.
+ */
+void MainWindow::selectedMessageChanged(const QModelIndex &sortedIndex, const QModelIndex &oldIndex)
+{
+ // Keep a valid selection whenever possible
+ if (!sortedIndex.isValid() && oldIndex.isValid()) {
+ m_messageView->setCurrentIndex(oldIndex);
+ return;
+ }
+
+ QModelIndex index = m_sortedMessagesModel->mapToSource(sortedIndex);
+ if (index.isValid()) {
+ int model = (index.column() && (index.column() - 1 < m_dataModel->modelCount())) ?
+ index.column() - 1 : m_currentIndex.model();
+ m_currentIndex = m_messageModel->dataIndex(index, model);
+ m_messageEditor->showMessage(m_currentIndex);
+ MessageItem *m = 0;
+ if (model >= 0 && (m = m_dataModel->messageItem(m_currentIndex))) {
+ if (m_dataModel->isModelWritable(model) && !m->isObsolete())
+ m_phraseView->setSourceText(m_currentIndex.model(), m->text());
+ else
+ m_phraseView->setSourceText(-1, QString());
+ } else {
+ if (model < 0) {
+ model = m_dataModel->multiContextItem(m_currentIndex.context())
+ ->firstNonobsoleteMessageIndex(m_currentIndex.message());
+ if (model >= 0)
+ m = m_dataModel->messageItem(m_currentIndex, model);
+ }
+ m_phraseView->setSourceText(-1, QString());
+ }
+ if (m) {
+ if (hasFormPreview(m->fileName())) {
+ m_sourceAndFormView->setCurrentWidget(m_formPreviewView);
+ m_formPreviewView->setSourceContext(model, m);
+ } else {
+ m_sourceAndFormView->setCurrentWidget(m_sourceCodeView);
+ QDir dir = QFileInfo(m_dataModel->srcFileName(model)).dir();
+ QString fileName = dir.absoluteFilePath(m->fileName());
+ m_sourceCodeView->setSourceContext(fileName, m->lineNumber());
+ }
+ m_errorsView->setEnabled(true);
+ } else {
+ m_sourceAndFormView->setCurrentWidget(m_sourceCodeView);
+ m_sourceCodeView->setSourceContext(QString(), 0);
+ m_errorsView->setEnabled(false);
+ }
+ updateDanger(m_currentIndex, true);
+ } else {
+ m_currentIndex = MultiDataIndex();
+ m_messageEditor->showNothing();
+ m_phraseView->setSourceText(-1, QString());
+ m_sourceAndFormView->setCurrentWidget(m_sourceCodeView);
+ m_sourceCodeView->setSourceContext(QString(), 0);
+ }
+
+ updatePhraseBookActions();
+ m_ui.actionSelectAll->setEnabled(index.isValid());
+}
+
+void MainWindow::translationChanged(const MultiDataIndex &index)
+{
+ // We get that as a result of batch translation or search & translate,
+ // so the current model is known to match.
+ if (index != m_currentIndex)
+ return;
+
+ m_messageEditor->showMessage(index);
+ updateDanger(index, true);
+
+ MessageItem *m = m_dataModel->messageItem(index);
+ if (hasFormPreview(m->fileName()))
+ m_formPreviewView->setSourceContext(index.model(), m);
+}
+
+// This and the following function operate directly on the messageitem,
+// so the model does not emit modification notifications.
+void MainWindow::updateTranslation(const QStringList &translations)
+{
+ MessageItem *m = m_dataModel->messageItem(m_currentIndex);
+ if (!m)
+ return;
+ if (translations == m->translations())
+ return;
+
+ m->setTranslations(translations);
+ if (hasFormPreview(m->fileName()))
+ m_formPreviewView->setSourceContext(m_currentIndex.model(), m);
+ updateDanger(m_currentIndex, true);
+
+ if (m->isFinished())
+ m_dataModel->setFinished(m_currentIndex, false);
+ else
+ m_dataModel->setModified(m_currentIndex.model(), true);
+}
+
+void MainWindow::updateTranslatorComment(const QString &comment)
+{
+ MessageItem *m = m_dataModel->messageItem(m_currentIndex);
+ if (!m)
+ return;
+ if (comment == m->translatorComment())
+ return;
+
+ m->setTranslatorComment(comment);
+
+ m_dataModel->setModified(m_currentIndex.model(), true);
+}
+
+void MainWindow::refreshItemViews()
+{
+ m_messageModel->blockSignals(false);
+ m_contextView->update();
+ m_messageView->update();
+ setWindowModified(m_dataModel->isModified());
+ m_modifiedLabel->setVisible(m_dataModel->isModified());
+ updateStatistics();
+}
+
+void MainWindow::doneAndNext()
+{
+ int model = m_messageEditor->activeModel();
+ if (model >= 0 && m_dataModel->isModelWritable(model))
+ m_dataModel->setFinished(m_currentIndex, true);
+
+ if (!m_messageEditor->focusNextUnfinished())
+ nextUnfinished();
+}
+
+void MainWindow::toggleFinished(const QModelIndex &index)
+{
+ if (!index.isValid() || index.column() - 1 >= m_dataModel->modelCount()
+ || !m_dataModel->isModelWritable(index.column() - 1) || index.parent() == QModelIndex())
+ return;
+
+ QModelIndex item = m_sortedMessagesModel->mapToSource(index);
+ MultiDataIndex dataIndex = m_messageModel->dataIndex(item);
+ MessageItem *m = m_dataModel->messageItem(dataIndex);
+
+ if (!m || m->message().type() == TranslatorMessage::Obsolete)
+ return;
+
+ m_dataModel->setFinished(dataIndex, !m->isFinished());
+}
+
+/*
+ * Receives a context index in the sorted messages model and returns the next
+ * logical context index in the same model, based on the sort order of the
+ * contexts in the sorted contexts model.
+ */
+QModelIndex MainWindow::nextContext(const QModelIndex &index) const
+{
+ QModelIndex sortedContextIndex = m_sortedContextsModel->mapFromSource(
+ m_sortedMessagesModel->mapToSource(index));
+
+ int nextRow = sortedContextIndex.row() + 1;
+ if (nextRow >= m_sortedContextsModel->rowCount())
+ nextRow = 0;
+ sortedContextIndex = m_sortedContextsModel->index(nextRow, index.column());
+
+ return m_sortedMessagesModel->mapFromSource(
+ m_sortedContextsModel->mapToSource(sortedContextIndex));
+}
+
+/*
+ * See nextContext.
+ */
+QModelIndex MainWindow::prevContext(const QModelIndex &index) const
+{
+ QModelIndex sortedContextIndex = m_sortedContextsModel->mapFromSource(
+ m_sortedMessagesModel->mapToSource(index));
+
+ int prevRow = sortedContextIndex.row() - 1;
+ if (prevRow < 0) prevRow = m_sortedContextsModel->rowCount() - 1;
+ sortedContextIndex = m_sortedContextsModel->index(prevRow, index.column());
+
+ return m_sortedMessagesModel->mapFromSource(
+ m_sortedContextsModel->mapToSource(sortedContextIndex));
+}
+
+QModelIndex MainWindow::nextMessage(const QModelIndex &currentIndex, bool checkUnfinished) const
+{
+ QModelIndex idx = currentIndex.isValid() ? currentIndex : m_sortedMessagesModel->index(0, 0);
+ do {
+ int row = 0;
+ QModelIndex par = idx.parent();
+ if (par.isValid()) {
+ row = idx.row() + 1;
+ } else { // In case we are located on a top-level node
+ par = idx;
+ }
+
+ if (row >= m_sortedMessagesModel->rowCount(par)) {
+ par = nextContext(par);
+ row = 0;
+ }
+ idx = m_sortedMessagesModel->index(row, idx.column(), par);
+
+ if (!checkUnfinished)
+ return idx;
+
+ QModelIndex item = m_sortedMessagesModel->mapToSource(idx);
+ MultiDataIndex index = m_messageModel->dataIndex(item, -1);
+ if (m_dataModel->multiMessageItem(index)->isUnfinished())
+ return idx;
+ } while (idx != currentIndex);
+ return QModelIndex();
+}
+
+QModelIndex MainWindow::prevMessage(const QModelIndex &currentIndex, bool checkUnfinished) const
+{
+ QModelIndex idx = currentIndex.isValid() ? currentIndex : m_sortedMessagesModel->index(0, 0);
+ do {
+ int row = idx.row() - 1;
+ QModelIndex par = idx.parent();
+ if (!par.isValid()) { // In case we are located on a top-level node
+ par = idx;
+ row = -1;
+ }
+
+ if (row < 0) {
+ par = prevContext(par);
+ row = m_sortedMessagesModel->rowCount(par) - 1;
+ }
+ idx = m_sortedMessagesModel->index(row, idx.column(), par);
+
+ if (!checkUnfinished)
+ return idx;
+
+ QModelIndex item = m_sortedMessagesModel->mapToSource(idx);
+ MultiDataIndex index = m_messageModel->dataIndex(item, -1);
+ if (m_dataModel->multiMessageItem(index)->isUnfinished())
+ return idx;
+ } while (idx != currentIndex);
+ return QModelIndex();
+}
+
+void MainWindow::nextUnfinished()
+{
+ if (m_ui.actionNextUnfinished->isEnabled()) {
+ if (!next(true)) {
+ // If no Unfinished message is left, the user has finished the job. We
+ // congratulate on a job well done with this ringing bell.
+ statusBar()->showMessage(tr("No untranslated translation units left."), MessageMS);
+ qApp->beep();
+ }
+ }
+}
+
+void MainWindow::prevUnfinished()
+{
+ if (m_ui.actionNextUnfinished->isEnabled()) {
+ if (!prev(true)) {
+ // If no Unfinished message is left, the user has finished the job. We
+ // congratulate on a job well done with this ringing bell.
+ statusBar()->showMessage(tr("No untranslated translation units left."), MessageMS);
+ qApp->beep();
+ }
+ }
+}
+
+void MainWindow::prev()
+{
+ prev(false);
+}
+
+void MainWindow::next()
+{
+ next(false);
+}
+
+bool MainWindow::prev(bool checkUnfinished)
+{
+ QModelIndex index = prevMessage(m_messageView->currentIndex(), checkUnfinished);
+ if (index.isValid())
+ setCurrentMessage(m_sortedMessagesModel->mapToSource(index));
+ if (checkUnfinished)
+ m_messageEditor->setUnfinishedEditorFocus();
+ else
+ m_messageEditor->setEditorFocus();
+ return index.isValid();
+}
+
+bool MainWindow::next(bool checkUnfinished)
+{
+ QModelIndex index = nextMessage(m_messageView->currentIndex(), checkUnfinished);
+ if (index.isValid())
+ setCurrentMessage(m_sortedMessagesModel->mapToSource(index));
+ if (checkUnfinished)
+ m_messageEditor->setUnfinishedEditorFocus();
+ else
+ m_messageEditor->setEditorFocus();
+ return index.isValid();
+}
+
+void MainWindow::findNext(const QString &text, DataModel::FindLocation where, bool matchCase, bool ignoreAccelerators)
+{
+ if (text.isEmpty())
+ return;
+ m_findText = text;
+ m_findWhere = where;
+ m_findMatchCase = matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ m_findIgnoreAccelerators = ignoreAccelerators;
+ m_ui.actionFindNext->setEnabled(true);
+ findAgain();
+}
+
+void MainWindow::revalidate()
+{
+ for (MultiDataModelIterator it(m_dataModel, -1); it.isValid(); ++it)
+ updateDanger(it, false);
+
+ if (m_currentIndex.isValid())
+ updateDanger(m_currentIndex, true);
+}
+
+QString MainWindow::friendlyString(const QString& str)
+{
+ QString f = str.toLower();
+ f.replace(QRegExp(QString(QLatin1String("[.,:;!?()-]"))), QString(QLatin1String(" ")));
+ f.remove(QLatin1Char('&'));
+ return f.simplified();
+}
+
+void MainWindow::setupMenuBar()
+{
+ m_ui.actionAccelerators->setIcon(QIcon(resourcePrefix() + QLatin1String("/accelerator.png")));
+ m_ui.actionOpenPhraseBook->setIcon(QIcon(resourcePrefix() + QLatin1String("/book.png")));
+ m_ui.actionDoneAndNext->setIcon(QIcon(resourcePrefix() + QLatin1String("/doneandnext.png")));
+ m_ui.actionCopy->setIcon(QIcon(resourcePrefix() + QLatin1String("/editcopy.png")));
+ m_ui.actionCut->setIcon(QIcon(resourcePrefix() + QLatin1String("/editcut.png")));
+ m_ui.actionPaste->setIcon(QIcon(resourcePrefix() + QLatin1String("/editpaste.png")));
+ m_ui.actionOpen->setIcon(QIcon(resourcePrefix() + QLatin1String("/fileopen.png")));
+ m_ui.actionOpenAux->setIcon(QIcon(resourcePrefix() + QLatin1String("/fileopen.png")));
+ m_ui.actionSaveAll->setIcon(QIcon(resourcePrefix() + QLatin1String("/filesave.png")));
+ m_ui.actionSave->setIcon(QIcon(resourcePrefix() + QLatin1String("/filesave.png")));
+ m_ui.actionNext->setIcon(QIcon(resourcePrefix() + QLatin1String("/next.png")));
+ m_ui.actionNextUnfinished->setIcon(QIcon(resourcePrefix() + QLatin1String("/nextunfinished.png")));
+ m_ui.actionPhraseMatches->setIcon(QIcon(resourcePrefix() + QLatin1String("/phrase.png")));
+ m_ui.actionEndingPunctuation->setIcon(QIcon(resourcePrefix() + QLatin1String("/punctuation.png")));
+ m_ui.actionPrev->setIcon(QIcon(resourcePrefix() + QLatin1String("/prev.png")));
+ m_ui.actionPrevUnfinished->setIcon(QIcon(resourcePrefix() + QLatin1String("/prevunfinished.png")));
+ m_ui.actionPrint->setIcon(QIcon(resourcePrefix() + QLatin1String("/print.png")));
+ m_ui.actionRedo->setIcon(QIcon(resourcePrefix() + QLatin1String("/redo.png")));
+ m_ui.actionFind->setIcon(QIcon(resourcePrefix() + QLatin1String("/searchfind.png")));
+ m_ui.actionUndo->setIcon(QIcon(resourcePrefix() + QLatin1String("/undo.png")));
+ m_ui.actionPlaceMarkerMatches->setIcon(QIcon(resourcePrefix() + QLatin1String("/validateplacemarkers.png")));
+ m_ui.actionWhatsThis->setIcon(QIcon(resourcePrefix() + QLatin1String("/whatsthis.png")));
+
+ // File menu
+ connect(m_ui.menuFile, SIGNAL(aboutToShow()), SLOT(fileAboutToShow()));
+ connect(m_ui.actionOpen, SIGNAL(triggered()), this, SLOT(open()));
+ connect(m_ui.actionOpenAux, SIGNAL(triggered()), this, SLOT(openAux()));
+ connect(m_ui.actionSaveAll, SIGNAL(triggered()), this, SLOT(saveAll()));
+ connect(m_ui.actionSave, SIGNAL(triggered()), this, SLOT(save()));
+ connect(m_ui.actionSaveAs, SIGNAL(triggered()), this, SLOT(saveAs()));
+ connect(m_ui.actionReleaseAll, SIGNAL(triggered()), this, SLOT(releaseAll()));
+ connect(m_ui.actionRelease, SIGNAL(triggered()), this, SLOT(release()));
+ connect(m_ui.actionReleaseAs, SIGNAL(triggered()), this, SLOT(releaseAs()));
+ connect(m_ui.actionPrint, SIGNAL(triggered()), this, SLOT(print()));
+ connect(m_ui.actionClose, SIGNAL(triggered()), this, SLOT(closeFile()));
+ connect(m_ui.actionCloseAll, SIGNAL(triggered()), this, SLOT(closeAll()));
+ connect(m_ui.actionExit, SIGNAL(triggered()), this, SLOT(close()));
+
+ // Edit menu
+ connect(m_ui.menuEdit, SIGNAL(aboutToShow()), SLOT(editAboutToShow()));
+
+ connect(m_ui.actionUndo, SIGNAL(triggered()), m_messageEditor, SLOT(undo()));
+ connect(m_messageEditor, SIGNAL(undoAvailable(bool)), m_ui.actionUndo, SLOT(setEnabled(bool)));
+
+ connect(m_ui.actionRedo, SIGNAL(triggered()), m_messageEditor, SLOT(redo()));
+ connect(m_messageEditor, SIGNAL(redoAvailable(bool)), m_ui.actionRedo, SLOT(setEnabled(bool)));
+
+ connect(m_ui.actionCopy, SIGNAL(triggered()), m_messageEditor, SLOT(copy()));
+ connect(m_messageEditor, SIGNAL(copyAvailable(bool)), m_ui.actionCopy, SLOT(setEnabled(bool)));
+
+ connect(m_messageEditor, SIGNAL(cutAvailable(bool)), m_ui.actionCut, SLOT(setEnabled(bool)));
+ connect(m_ui.actionCut, SIGNAL(triggered()), m_messageEditor, SLOT(cut()));
+
+ connect(m_messageEditor, SIGNAL(pasteAvailable(bool)), m_ui.actionPaste, SLOT(setEnabled(bool)));
+ connect(m_ui.actionPaste, SIGNAL(triggered()), m_messageEditor, SLOT(paste()));
+
+ connect(m_ui.actionSelectAll, SIGNAL(triggered()), m_messageEditor, SLOT(selectAll()));
+ connect(m_ui.actionFind, SIGNAL(triggered()), m_findDialog, SLOT(find()));
+ connect(m_ui.actionFindNext, SIGNAL(triggered()), this, SLOT(findAgain()));
+ connect(m_ui.actionSearchAndTranslate, SIGNAL(triggered()), this, SLOT(showTranslateDialog()));
+ connect(m_ui.actionBatchTranslation, SIGNAL(triggered()), this, SLOT(showBatchTranslateDialog()));
+ connect(m_ui.actionTranslationFileSettings, SIGNAL(triggered()), this, SLOT(showTranslationSettings()));
+
+ connect(m_batchTranslateDialog, SIGNAL(finished()), SLOT(refreshItemViews()));
+
+ // Translation menu
+ // when updating the accelerators, remember the status bar
+ connect(m_ui.actionPrevUnfinished, SIGNAL(triggered()), this, SLOT(prevUnfinished()));
+ connect(m_ui.actionNextUnfinished, SIGNAL(triggered()), this, SLOT(nextUnfinished()));
+ connect(m_ui.actionNext, SIGNAL(triggered()), this, SLOT(next()));
+ connect(m_ui.actionPrev, SIGNAL(triggered()), this, SLOT(prev()));
+ connect(m_ui.actionDoneAndNext, SIGNAL(triggered()), this, SLOT(doneAndNext()));
+ connect(m_ui.actionBeginFromSource, SIGNAL(triggered()), m_messageEditor, SLOT(beginFromSource()));
+ connect(m_messageEditor, SIGNAL(beginFromSourceAvailable(bool)), m_ui.actionBeginFromSource, SLOT(setEnabled(bool)));
+
+ // Phrasebook menu
+ connect(m_ui.actionNewPhraseBook, SIGNAL(triggered()), this, SLOT(newPhraseBook()));
+ connect(m_ui.actionOpenPhraseBook, SIGNAL(triggered()), this, SLOT(openPhraseBook()));
+ connect(m_ui.menuClosePhraseBook, SIGNAL(triggered(QAction*)),
+ this, SLOT(closePhraseBook(QAction*)));
+ connect(m_ui.menuEditPhraseBook, SIGNAL(triggered(QAction*)),
+ this, SLOT(editPhraseBook(QAction*)));
+ connect(m_ui.menuPrintPhraseBook, SIGNAL(triggered(QAction*)),
+ this, SLOT(printPhraseBook(QAction*)));
+ connect(m_ui.actionAddToPhraseBook, SIGNAL(triggered()), this, SLOT(addToPhraseBook()));
+
+ // Validation menu
+ connect(m_ui.actionAccelerators, SIGNAL(triggered()), this, SLOT(revalidate()));
+ connect(m_ui.actionEndingPunctuation, SIGNAL(triggered()), this, SLOT(revalidate()));
+ connect(m_ui.actionPhraseMatches, SIGNAL(triggered()), this, SLOT(revalidate()));
+ connect(m_ui.actionPlaceMarkerMatches, SIGNAL(triggered()), this, SLOT(revalidate()));
+
+ // View menu
+ connect(m_ui.actionResetSorting, SIGNAL(triggered()), this, SLOT(resetSorting()));
+ connect(m_ui.actionDisplayGuesses, SIGNAL(triggered()), m_phraseView, SLOT(toggleGuessing()));
+ connect(m_ui.actionStatistics, SIGNAL(triggered()), this, SLOT(toggleStatistics()));
+ connect(m_ui.menuView, SIGNAL(aboutToShow()), this, SLOT(updateViewMenu()));
+ m_ui.menuViewViews->addAction(m_contextDock->toggleViewAction());
+ m_ui.menuViewViews->addAction(m_messagesDock->toggleViewAction());
+ m_ui.menuViewViews->addAction(m_phrasesDock->toggleViewAction());
+ m_ui.menuViewViews->addAction(m_sourceAndFormDock->toggleViewAction());
+ m_ui.menuViewViews->addAction(m_errorsDock->toggleViewAction());
+
+#if defined(Q_WS_MAC)
+ // Window menu
+ QMenu *windowMenu = new QMenu(tr("&Window"), this);
+ menuBar()->insertMenu(m_ui.menuHelp->menuAction(), windowMenu);
+ windowMenu->addAction(tr("Minimize"), this,
+ SLOT(showMinimized()), QKeySequence(tr("Ctrl+M")));
+#endif
+
+ // Help
+ connect(m_ui.actionManual, SIGNAL(triggered()), this, SLOT(manual()));
+ connect(m_ui.actionAbout, SIGNAL(triggered()), this, SLOT(about()));
+ connect(m_ui.actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
+ connect(m_ui.actionWhatsThis, SIGNAL(triggered()), this, SLOT(onWhatsThis()));
+
+ connect(m_ui.menuRecentlyOpenedFiles, SIGNAL(triggered(QAction*)), this,
+ SLOT(recentFileActivated(QAction*)));
+
+ m_ui.actionManual->setWhatsThis(tr("Display the manual for %1.").arg(tr("Qt Linguist")));
+ m_ui.actionAbout->setWhatsThis(tr("Display information about %1.").arg(tr("Qt Linguist")));
+ m_ui.actionDoneAndNext->setShortcuts(QList<QKeySequence>()
+ << QKeySequence(QLatin1String("Ctrl+Return"))
+ << QKeySequence(QLatin1String("Ctrl+Enter")));
+
+ // Disable the Close/Edit/Print phrasebook menuitems if they are not loaded
+ connect(m_ui.menuPhrases, SIGNAL(aboutToShow()), this, SLOT(setupPhrase()));
+
+ connect(m_ui.menuRecentlyOpenedFiles, SIGNAL(aboutToShow()), SLOT(setupRecentFilesMenu()));
+}
+
+void MainWindow::updateActiveModel(int model)
+{
+ if (model >= 0)
+ updateLatestModel(model);
+}
+
+// Arriving here implies that the messageEditor does not have focus
+void MainWindow::updateLatestModel(const QModelIndex &index)
+{
+ if (index.column() && (index.column() - 1 < m_dataModel->modelCount()))
+ updateLatestModel(index.column() - 1);
+}
+
+void MainWindow::updateLatestModel(int model)
+{
+ m_currentIndex = MultiDataIndex(model, m_currentIndex.context(), m_currentIndex.message());
+ bool enable = false;
+ bool enableRw = false;
+ if (model >= 0) {
+ enable = true;
+ if (m_dataModel->isModelWritable(model))
+ enableRw = true;
+
+ if (m_currentIndex.isValid()) {
+ if (MessageItem *item = m_dataModel->messageItem(m_currentIndex)) {
+ if (hasFormPreview(item->fileName()))
+ m_formPreviewView->setSourceContext(model, item);
+ if (enableRw && !item->isObsolete())
+ m_phraseView->setSourceText(model, item->text());
+ else
+ m_phraseView->setSourceText(-1, QString());
+ } else {
+ m_phraseView->setSourceText(-1, QString());
+ }
+ }
+ }
+ m_ui.actionSave->setEnabled(enableRw);
+ m_ui.actionSaveAs->setEnabled(enableRw);
+ m_ui.actionRelease->setEnabled(enableRw);
+ m_ui.actionReleaseAs->setEnabled(enableRw);
+ m_ui.actionClose->setEnabled(enable);
+ m_ui.actionTranslationFileSettings->setEnabled(enableRw);
+ m_ui.actionSearchAndTranslate->setEnabled(enableRw);
+ // cut & paste - edit only
+ updatePhraseBookActions();
+ updateStatistics();
+}
+
+// Note for *AboutToShow: Due to the delayed nature, only actions without shortcuts
+// and representations outside the menu may be setEnabled()/setVisible() here.
+
+void MainWindow::fileAboutToShow()
+{
+ if (m_fileActiveModel != m_currentIndex.model()) {
+ // We rename the actions so the shortcuts need not be reassigned.
+ bool en;
+ if (m_dataModel->modelCount() > 1) {
+ if (m_currentIndex.model() >= 0) {
+ QString fn = QFileInfo(m_dataModel->srcFileName(m_currentIndex.model())).baseName();
+ m_ui.actionSave->setText(tr("&Save '%1'").arg(fn));
+ m_ui.actionSaveAs->setText(tr("Save '%1' &As...").arg(fn));
+ m_ui.actionRelease->setText(tr("Release '%1'").arg(fn));
+ m_ui.actionReleaseAs->setText(tr("Release '%1' As...").arg(fn));
+ m_ui.actionClose->setText(tr("&Close '%1'").arg(fn));
+ } else {
+ m_ui.actionSave->setText(tr("&Save"));
+ m_ui.actionSaveAs->setText(tr("Save &As..."));
+ m_ui.actionRelease->setText(tr("Release"));
+ m_ui.actionReleaseAs->setText(tr("Release As..."));
+ m_ui.actionClose->setText(tr("&Close"));
+ }
+
+ m_ui.actionSaveAll->setText(tr("Save All"));
+ m_ui.actionReleaseAll->setText(tr("&Release All"));
+ m_ui.actionCloseAll->setText(tr("Close All"));
+ en = true;
+ } else {
+ m_ui.actionSaveAs->setText(tr("Save &As..."));
+ m_ui.actionReleaseAs->setText(tr("Release As..."));
+
+ m_ui.actionSaveAll->setText(tr("&Save"));
+ m_ui.actionReleaseAll->setText(tr("&Release"));
+ m_ui.actionCloseAll->setText(tr("&Close"));
+ en = false;
+ }
+ m_ui.actionSave->setVisible(en);
+ m_ui.actionRelease->setVisible(en);
+ m_ui.actionClose->setVisible(en);
+ m_fileActiveModel = m_currentIndex.model();
+ }
+}
+
+void MainWindow::editAboutToShow()
+{
+ if (m_editActiveModel != m_currentIndex.model()) {
+ if (m_currentIndex.model() >= 0 && m_dataModel->modelCount() > 1) {
+ QString fn = QFileInfo(m_dataModel->srcFileName(m_currentIndex.model())).baseName();
+ m_ui.actionTranslationFileSettings->setText(tr("Translation File &Settings for '%1'...").arg(fn));
+ m_ui.actionBatchTranslation->setText(tr("&Batch Translation of '%1'...").arg(fn));
+ m_ui.actionSearchAndTranslate->setText(tr("Search And &Translate in '%1'...").arg(fn));
+ } else {
+ m_ui.actionTranslationFileSettings->setText(tr("Translation File &Settings..."));
+ m_ui.actionBatchTranslation->setText(tr("&Batch Translation..."));
+ m_ui.actionSearchAndTranslate->setText(tr("Search And &Translate..."));
+ }
+ m_editActiveModel = m_currentIndex.model();
+ }
+}
+
+void MainWindow::updateViewMenu()
+{
+ bool check = m_statistics ? m_statistics->isVisible() : false;
+ m_ui.actionStatistics->setChecked(check);
+}
+
+void MainWindow::showContextDock()
+{
+ m_contextDock->show();
+ m_contextDock->raise();
+}
+
+void MainWindow::showMessagesDock()
+{
+ m_messagesDock->show();
+ m_messagesDock->raise();
+}
+
+void MainWindow::showPhrasesDock()
+{
+ m_phrasesDock->show();
+ m_phrasesDock->raise();
+}
+
+void MainWindow::showSourceCodeDock()
+{
+ m_sourceAndFormDock->show();
+ m_sourceAndFormDock->raise();
+}
+
+void MainWindow::showErrorDock()
+{
+ m_errorsDock->show();
+ m_errorsDock->raise();
+}
+
+void MainWindow::onWhatsThis()
+{
+ QWhatsThis::enterWhatsThisMode();
+}
+
+void MainWindow::setupToolBars()
+{
+ QToolBar *filet = new QToolBar(this);
+ filet->setObjectName(QLatin1String("FileToolbar"));
+ filet->setWindowTitle(tr("File"));
+ this->addToolBar(filet);
+ m_ui.menuToolbars->addAction(filet->toggleViewAction());
+
+ QToolBar *editt = new QToolBar(this);
+ editt->setVisible(false);
+ editt->setObjectName(QLatin1String("EditToolbar"));
+ editt->setWindowTitle(tr("Edit"));
+ this->addToolBar(editt);
+ m_ui.menuToolbars->addAction(editt->toggleViewAction());
+
+ QToolBar *translationst = new QToolBar(this);
+ translationst->setObjectName(QLatin1String("TranslationToolbar"));
+ translationst->setWindowTitle(tr("Translation"));
+ this->addToolBar(translationst);
+ m_ui.menuToolbars->addAction(translationst->toggleViewAction());
+
+ QToolBar *validationt = new QToolBar(this);
+ validationt->setObjectName(QLatin1String("ValidationToolbar"));
+ validationt->setWindowTitle(tr("Validation"));
+ this->addToolBar(validationt);
+ m_ui.menuToolbars->addAction(validationt->toggleViewAction());
+
+ QToolBar *helpt = new QToolBar(this);
+ helpt->setVisible(false);
+ helpt->setObjectName(QLatin1String("HelpToolbar"));
+ helpt->setWindowTitle(tr("Help"));
+ this->addToolBar(helpt);
+ m_ui.menuToolbars->addAction(helpt->toggleViewAction());
+
+
+ filet->addAction(m_ui.actionOpen);
+ filet->addAction(m_ui.actionSaveAll);
+ filet->addAction(m_ui.actionPrint);
+ filet->addSeparator();
+ filet->addAction(m_ui.actionOpenPhraseBook);
+
+ editt->addAction(m_ui.actionUndo);
+ editt->addAction(m_ui.actionRedo);
+ editt->addSeparator();
+ editt->addAction(m_ui.actionCut);
+ editt->addAction(m_ui.actionCopy);
+ editt->addAction(m_ui.actionPaste);
+ editt->addSeparator();
+ editt->addAction(m_ui.actionFind);
+
+ translationst->addAction(m_ui.actionPrev);
+ translationst->addAction(m_ui.actionNext);
+ translationst->addAction(m_ui.actionPrevUnfinished);
+ translationst->addAction(m_ui.actionNextUnfinished);
+ translationst->addAction(m_ui.actionDoneAndNext);
+
+ validationt->addAction(m_ui.actionAccelerators);
+ validationt->addAction(m_ui.actionEndingPunctuation);
+ validationt->addAction(m_ui.actionPhraseMatches);
+ validationt->addAction(m_ui.actionPlaceMarkerMatches);
+
+ helpt->addAction(m_ui.actionWhatsThis);
+}
+
+QModelIndex MainWindow::setMessageViewRoot(const QModelIndex &index)
+{
+ const QModelIndex &sortedContextIndex = m_sortedMessagesModel->mapFromSource(index);
+ const QModelIndex &trueContextIndex = m_sortedMessagesModel->index(sortedContextIndex.row(), 0);
+ if (m_messageView->rootIndex() != trueContextIndex)
+ m_messageView->setRootIndex(trueContextIndex);
+ return trueContextIndex;
+}
+
+/*
+ * Updates the selected entries in the context and message views.
+ */
+void MainWindow::setCurrentMessage(const QModelIndex &index)
+{
+ const QModelIndex &contextIndex = m_messageModel->parent(index);
+ if (!contextIndex.isValid())
+ return;
+
+ const QModelIndex &trueIndex = m_messageModel->index(contextIndex.row(), index.column(), QModelIndex());
+ m_settingCurrentMessage = true;
+ m_contextView->setCurrentIndex(m_sortedContextsModel->mapFromSource(trueIndex));
+ m_settingCurrentMessage = false;
+
+ setMessageViewRoot(contextIndex);
+ m_messageView->setCurrentIndex(m_sortedMessagesModel->mapFromSource(index));
+}
+
+void MainWindow::setCurrentMessage(const QModelIndex &index, int model)
+{
+ const QModelIndex &theIndex = m_messageModel->index(index.row(), model + 1, index.parent());
+ setCurrentMessage(theIndex);
+ m_messageEditor->setEditorFocus(model);
+}
+
+QModelIndex MainWindow::currentContextIndex() const
+{
+ return m_sortedContextsModel->mapToSource(m_contextView->currentIndex());
+}
+
+QModelIndex MainWindow::currentMessageIndex() const
+{
+ return m_sortedMessagesModel->mapToSource(m_messageView->currentIndex());
+}
+
+PhraseBook *MainWindow::openPhraseBook(const QString& name)
+{
+ PhraseBook *pb = new PhraseBook();
+ bool langGuessed;
+ if (!pb->load(name, &langGuessed)) {
+ QMessageBox::warning(this, tr("Qt Linguist"),
+ tr("Cannot read from phrase book '%1'.").arg(name));
+ delete pb;
+ return 0;
+ }
+ if (langGuessed) {
+ if (!m_translationSettingsDialog)
+ m_translationSettingsDialog = new TranslationSettingsDialog(this);
+ m_translationSettingsDialog->setPhraseBook(pb);
+ m_translationSettingsDialog->exec();
+ }
+
+ m_phraseBooks.append(pb);
+
+ QAction *a = m_ui.menuClosePhraseBook->addAction(pb->friendlyPhraseBookName());
+ m_phraseBookMenu[PhraseCloseMenu].insert(a, pb);
+ a->setWhatsThis(tr("Close this phrase book."));
+
+ a = m_ui.menuEditPhraseBook->addAction(pb->friendlyPhraseBookName());
+ m_phraseBookMenu[PhraseEditMenu].insert(a, pb);
+ a->setWhatsThis(tr("Enables you to add, modify, or delete"
+ " entries in this phrase book."));
+
+ a = m_ui.menuPrintPhraseBook->addAction(pb->friendlyPhraseBookName());
+ m_phraseBookMenu[PhrasePrintMenu].insert(a, pb);
+ a->setWhatsThis(tr("Print the entries in this phrase book."));
+
+ connect(pb, SIGNAL(listChanged()), this, SLOT(updatePhraseDicts()));
+ updatePhraseDicts();
+ updatePhraseBookActions();
+
+ return pb;
+}
+
+bool MainWindow::savePhraseBook(QString *name, PhraseBook &pb)
+{
+ if (!name->contains(QLatin1Char('.')))
+ *name += QLatin1String(".qph");
+
+ if (!pb.save(*name)) {
+ QMessageBox::warning(this, tr("Qt Linguist"),
+ tr("Cannot create phrase book '%1'.").arg(*name));
+ return false;
+ }
+ return true;
+}
+
+bool MainWindow::maybeSavePhraseBook(PhraseBook *pb)
+{
+ if (pb->isModified())
+ switch (QMessageBox::information(this, tr("Qt Linguist"),
+ tr("Do you want to save phrase book '%1'?").arg(pb->friendlyPhraseBookName()),
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::No,
+ QMessageBox::Cancel | QMessageBox::Escape))
+ {
+ case QMessageBox::Cancel:
+ return false;
+ case QMessageBox::Yes:
+ if (!pb->save(pb->fileName()))
+ return false;
+ break;
+ case QMessageBox::No:
+ break;
+ }
+ return true;
+}
+
+bool MainWindow::closePhraseBooks()
+{
+ foreach(PhraseBook *phraseBook, m_phraseBooks)
+ if (!maybeSavePhraseBook(phraseBook))
+ return false;
+ return true;
+}
+
+void MainWindow::updateProgress()
+{
+ int numEditable = m_dataModel->getNumEditable();
+ int numFinished = m_dataModel->getNumFinished();
+ if (!m_dataModel->modelCount())
+ m_progressLabel->setText(QString(QLatin1String(" ")));
+ else
+ m_progressLabel->setText(QString(QLatin1String(" %1/%2 "))
+ .arg(numFinished).arg(numEditable));
+ bool enable = numFinished != numEditable;
+ m_ui.actionPrevUnfinished->setEnabled(enable);
+ m_ui.actionNextUnfinished->setEnabled(enable);
+ m_ui.actionDoneAndNext->setEnabled(enable);
+
+ m_ui.actionPrev->setEnabled(m_dataModel->contextCount() > 0);
+ m_ui.actionNext->setEnabled(m_dataModel->contextCount() > 0);
+}
+
+void MainWindow::updatePhraseBookActions()
+{
+ bool phraseBookLoaded = (m_currentIndex.model() >= 0) && !m_phraseBooks.isEmpty();
+ m_ui.actionBatchTranslation->setEnabled(m_dataModel->contextCount() > 0 && phraseBookLoaded
+ && m_dataModel->isModelWritable(m_currentIndex.model()));
+ m_ui.actionAddToPhraseBook->setEnabled(currentMessageIndex().isValid() && phraseBookLoaded);
+}
+
+void MainWindow::updatePhraseDictInternal(int model)
+{
+ QHash<QString, QList<Phrase *> > &pd = m_phraseDict[model];
+
+ pd.clear();
+ foreach (PhraseBook *pb, m_phraseBooks) {
+ bool before;
+ if (pb->language() != QLocale::C && m_dataModel->language(model) != QLocale::C) {
+ if (pb->language() != m_dataModel->language(model))
+ continue;
+ before = (pb->country() == m_dataModel->model(model)->country());
+ } else {
+ before = false;
+ }
+ foreach (Phrase *p, pb->phrases()) {
+ QString f = friendlyString(p->source());
+ if (f.length() > 0) {
+ f = f.split(QLatin1Char(' ')).first();
+ if (!pd.contains(f)) {
+ pd.insert(f, QList<Phrase *>());
+ }
+ if (before)
+ pd[f].prepend(p);
+ else
+ pd[f].append(p);
+ }
+ }
+ }
+}
+
+void MainWindow::updatePhraseDict(int model)
+{
+ updatePhraseDictInternal(model);
+ m_phraseView->update();
+}
+
+void MainWindow::updatePhraseDicts()
+{
+ for (int i = 0; i < m_phraseDict.size(); ++i)
+ if (!m_dataModel->isModelWritable(i))
+ m_phraseDict[i].clear();
+ else
+ updatePhraseDictInternal(i);
+ revalidate();
+ m_phraseView->update();
+}
+
+void MainWindow::updateDanger(const MultiDataIndex &index, bool verbose)
+{
+ MultiDataIndex curIdx = index;
+ m_errorsView->clear();
+
+ QString source;
+ for (int mi = 0; mi < m_dataModel->modelCount(); ++mi) {
+ if (!m_dataModel->isModelWritable(mi))
+ continue;
+ curIdx.setModel(mi);
+ MessageItem *m = m_dataModel->messageItem(curIdx);
+ if (!m || m->isObsolete())
+ continue;
+
+ bool danger = false;
+ if (m->message().isTranslated()) {
+ if (source.isEmpty()) {
+ source = m->pluralText();
+ if (source.isEmpty())
+ source = m->text();
+ }
+ QStringList translations = m->translations();
+
+ if (m_ui.actionAccelerators->isChecked()) {
+ bool sk = !QKeySequence::mnemonic(source).isEmpty();
+ bool tk = true;
+ for (int i = 0; i < translations.count() && tk; ++i) {
+ tk &= !QKeySequence::mnemonic(translations[i]).isEmpty();
+ }
+
+ if (!sk && tk) {
+ if (verbose)
+ m_errorsView->addError(mi, ErrorsView::SuperfluousAccelerator);
+ danger = true;
+ } else if (sk && !tk) {
+ if (verbose)
+ m_errorsView->addError(mi, ErrorsView::MissingAccelerator);
+ danger = true;
+ }
+ }
+ if (m_ui.actionEndingPunctuation->isChecked()) {
+ bool endingok = true;
+ for (int i = 0; i < translations.count() && endingok; ++i) {
+ endingok &= (ending(source, m_dataModel->sourceLanguage(mi)) ==
+ ending(translations[i], m_dataModel->language(mi)));
+ }
+
+ if (!endingok) {
+ if (verbose)
+ m_errorsView->addError(mi, ErrorsView::PunctuationDiffer);
+ danger = true;
+ }
+ }
+ if (m_ui.actionPhraseMatches->isChecked()) {
+ QString fsource = friendlyString(source);
+ QString ftranslation = friendlyString(translations.first());
+ QStringList lookupWords = fsource.split(QLatin1Char(' '));
+
+ bool phraseFound;
+ foreach (const QString &s, lookupWords) {
+ if (m_phraseDict[mi].contains(s)) {
+ phraseFound = true;
+ foreach (const Phrase *p, m_phraseDict[mi].value(s)) {
+ if (fsource == friendlyString(p->source())) {
+ if (ftranslation.indexOf(friendlyString(p->target())) >= 0) {
+ phraseFound = true;
+ break;
+ } else {
+ phraseFound = false;
+ }
+ }
+ }
+ if (!phraseFound) {
+ if (verbose)
+ m_errorsView->addError(mi, ErrorsView::IgnoredPhrasebook, s);
+ danger = true;
+ }
+ }
+ }
+ }
+
+ if (m_ui.actionPlaceMarkerMatches->isChecked()) {
+ // Stores the occurence count of the place markers in the map placeMarkerIndexes.
+ // i.e. the occurence count of %1 is stored at placeMarkerIndexes[1],
+ // count of %2 is stored at placeMarkerIndexes[2] etc.
+ // In the first pass, it counts all place markers in the sourcetext.
+ // In the second pass it (de)counts all place markers in the translation.
+ // When finished, all elements should have returned to a count of 0,
+ // if not there is a mismatch
+ // between place markers in the source text and the translation text.
+ QHash<int, int> placeMarkerIndexes;
+ QString translation;
+ int numTranslations = translations.count();
+ for (int pass = 0; pass < numTranslations + 1; ++pass) {
+ const QChar *uc_begin = source.unicode();
+ const QChar *uc_end = uc_begin + source.length();
+ if (pass >= 1) {
+ translation = translations[pass - 1];
+ uc_begin = translation.unicode();
+ uc_end = uc_begin + translation.length();
+ }
+ const QChar *c = uc_begin;
+ while (c < uc_end) {
+ if (c->unicode() == '%') {
+ const QChar *escape_start = ++c;
+ while (c->isDigit())
+ ++c;
+ const QChar *escape_end = c;
+ bool ok = true;
+ int markerIndex = QString::fromRawData(
+ escape_start, escape_end - escape_start).toInt(&ok);
+ if (ok)
+ placeMarkerIndexes[markerIndex] += (pass == 0 ? numTranslations : -1);
+ }
+ ++c;
+ }
+ }
+
+ foreach (int i, placeMarkerIndexes) {
+ if (i != 0) {
+ if (verbose)
+ m_errorsView->addError(mi, ErrorsView::PlaceMarkersDiffer);
+ danger = true;
+ break;
+ }
+ }
+
+ // Piggy-backed on the general place markers, we check the plural count marker.
+ if (m->message().isPlural()) {
+ for (int i = 0; i < numTranslations; ++i)
+ if (m_dataModel->model(mi)->countRefNeeds().at(i)
+ && !translations[i].contains(QLatin1String("%n"))) {
+ if (verbose)
+ m_errorsView->addError(mi, ErrorsView::NumerusMarkerMissing);
+ danger = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (danger != m->danger())
+ m_dataModel->setDanger(curIdx, danger);
+ }
+
+ if (verbose)
+ statusBar()->showMessage(m_errorsView->firstError());
+}
+
+void MainWindow::readConfig()
+{
+ QString keybase = settingsPrefix();
+ QSettings config;
+
+ QRect r(pos(), size());
+ restoreGeometry(config.value(keybase + QLatin1String("Geometry/WindowGeometry")).toByteArray());
+ restoreState(config.value(keybase + QLatin1String("MainWindowState")).toByteArray());
+
+ m_ui.actionAccelerators->setChecked(
+ config.value(keybase + QLatin1String("Validators/Accelerator"), true).toBool());
+ m_ui.actionEndingPunctuation->setChecked(
+ config.value(keybase + QLatin1String("Validators/EndingPunctuation"), true).toBool());
+ m_ui.actionPhraseMatches->setChecked(
+ config.value(keybase + QLatin1String("Validators/PhraseMatch"), true).toBool());
+ m_ui.actionPlaceMarkerMatches->setChecked(
+ config.value(keybase + QLatin1String("Validators/PlaceMarkers"), true).toBool());
+
+ recentFiles().readConfig();
+
+ int size = config.beginReadArray(keybase + QLatin1String("OpenedPhraseBooks"));
+ for (int i = 0; i < size; ++i) {
+ config.setArrayIndex(i);
+ openPhraseBook(config.value(QLatin1String("FileName")).toString());
+ }
+ config.endArray();
+}
+
+void MainWindow::writeConfig()
+{
+ QString keybase = settingsPrefix();
+ QSettings config;
+ config.setValue(keybase + QLatin1String("Geometry/WindowGeometry"),
+ saveGeometry());
+ config.setValue(keybase + QLatin1String("Validators/Accelerator"),
+ m_ui.actionAccelerators->isChecked());
+ config.setValue(keybase + QLatin1String("Validators/EndingPunctuation"),
+ m_ui.actionEndingPunctuation->isChecked());
+ config.setValue(keybase + QLatin1String("Validators/PhraseMatch"),
+ m_ui.actionPhraseMatches->isChecked());
+ config.setValue(keybase + QLatin1String("Validators/PlaceMarkers"),
+ m_ui.actionPlaceMarkerMatches->isChecked());
+ config.setValue(keybase + QLatin1String("MainWindowState"),
+ saveState());
+ recentFiles().writeConfig();
+
+ config.beginWriteArray(keybase + QLatin1String("OpenedPhraseBooks"),
+ m_phraseBooks.size());
+ for (int i = 0; i < m_phraseBooks.size(); ++i) {
+ config.setArrayIndex(i);
+ config.setValue(QLatin1String("FileName"), m_phraseBooks.at(i)->fileName());
+ }
+ config.endArray();
+}
+
+void MainWindow::setupRecentFilesMenu()
+{
+ m_ui.menuRecentlyOpenedFiles->clear();
+ foreach (const QStringList &strList, recentFiles().filesLists())
+ if (strList.size() == 1) {
+ const QString &str = strList.first();
+ m_ui.menuRecentlyOpenedFiles->addAction(
+ DataModel::prettifyFileName(str))->setData(str);
+ } else {
+ QMenu *menu = m_ui.menuRecentlyOpenedFiles->addMenu(
+ MultiDataModel::condenseFileNames(
+ MultiDataModel::prettifyFileNames(strList)));
+ menu->addAction(tr("All"))->setData(strList);
+ foreach (const QString &str, strList)
+ menu->addAction(DataModel::prettifyFileName(str))->setData(str);
+ }
+}
+
+void MainWindow::recentFileActivated(QAction *action)
+{
+ openFiles(action->data().toStringList());
+}
+
+void MainWindow::toggleStatistics()
+{
+ if (m_ui.actionStatistics->isChecked()) {
+ if (!m_statistics) {
+ m_statistics = new Statistics(this);
+ connect(m_dataModel, SIGNAL(statsChanged(int,int,int,int,int,int)),
+ m_statistics, SLOT(updateStats(int,int,int,int,int,int)));
+ }
+ m_statistics->show();
+ updateStatistics();
+ }
+ else if (m_statistics) {
+ m_statistics->close();
+ }
+}
+
+void MainWindow::maybeUpdateStatistics(const MultiDataIndex &index)
+{
+ if (index.model() == m_currentIndex.model())
+ updateStatistics();
+}
+
+void MainWindow::updateStatistics()
+{
+ // don't call this if stats dialog is not open
+ // because this can be slow...
+ if (!m_statistics || !m_statistics->isVisible() || m_currentIndex.model() < 0)
+ return;
+
+ m_dataModel->model(m_currentIndex.model())->updateStatistics();
+}
+
+void MainWindow::showTranslationSettings(int model)
+{
+ if (!m_translationSettingsDialog)
+ m_translationSettingsDialog = new TranslationSettingsDialog(this);
+ m_translationSettingsDialog->setDataModel(m_dataModel->model(model));
+ m_translationSettingsDialog->exec();
+}
+
+void MainWindow::showTranslationSettings()
+{
+ showTranslationSettings(m_currentIndex.model());
+}
+
+bool MainWindow::eventFilter(QObject *object, QEvent *event)
+{
+ if (event->type() == QEvent::DragEnter) {
+ QDragEnterEvent *e = static_cast<QDragEnterEvent*>(event);
+ if (e->mimeData()->hasFormat(QLatin1String("text/uri-list"))) {
+ e->acceptProposedAction();
+ return true;
+ }
+ } else if (event->type() == QEvent::Drop) {
+ QDropEvent *e = static_cast<QDropEvent*>(event);
+ if (!e->mimeData()->hasFormat(QLatin1String("text/uri-list")))
+ return false;
+ QStringList urls;
+ foreach (QUrl url, e->mimeData()->urls())
+ if (!url.toLocalFile().isEmpty())
+ urls << url.toLocalFile();
+ if (!urls.isEmpty())
+ openFiles(urls);
+ e->acceptProposedAction();
+ return true;
+ } else if (event->type() == QEvent::KeyPress) {
+ if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) {
+ if (object == m_messageEditor)
+ m_messageView->setFocus();
+ else if (object == m_messagesDock)
+ m_contextView->setFocus();
+ }
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/mainwindow.h b/tools/linguist/linguist/mainwindow.h
new file mode 100644
index 0000000000..9f6b4d9e2a
--- /dev/null
+++ b/tools/linguist/linguist/mainwindow.h
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "phrase.h"
+#include "ui_mainwindow.h"
+#include "recentfiles.h"
+#include "messagemodel.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QLocale>
+
+#include <QtGui/QMainWindow>
+#include <QtGui/QPrinter>
+
+QT_BEGIN_NAMESPACE
+
+class QPixmap;
+class QAction;
+class QDialog;
+class QLabel;
+class QMenu;
+class QProcess;
+class QIcon;
+class QSortFilterProxyModel;
+class QStackedWidget;
+class QTableView;
+class QTreeView;
+
+class BatchTranslationDialog;
+class ErrorsView;
+class FindDialog;
+class FocusWatcher;
+class FormPreviewView;
+class MessageEditor;
+class PhraseView;
+class SourceCodeView;
+class Statistics;
+class TranslateDialog;
+class TranslationSettingsDialog;
+
+const QString &settingsPrefix();
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ enum {PhraseCloseMenu, PhraseEditMenu, PhrasePrintMenu};
+
+ MainWindow();
+ ~MainWindow();
+
+ bool openFiles(const QStringList &names, bool readWrite = true);
+ static RecentFiles &recentFiles();
+ static const QString &resourcePrefix();
+ static QString friendlyString(const QString &str);
+
+protected:
+ void readConfig();
+ void writeConfig();
+ void closeEvent(QCloseEvent *);
+ bool eventFilter(QObject *object, QEvent *event);
+
+private slots:
+ void doneAndNext();
+ void prev();
+ void next();
+ void recentFileActivated(QAction *action);
+ void setupRecentFilesMenu();
+ void open();
+ void openAux();
+ void saveAll();
+ void save();
+ void saveAs();
+ void releaseAll();
+ void release();
+ void releaseAs();
+ void print();
+ void closeFile();
+ bool closeAll();
+ void findAgain();
+ void showTranslateDialog();
+ void showBatchTranslateDialog();
+ void showTranslationSettings();
+ void updateTranslateHit(bool &hit);
+ void translate(int mode);
+ void newPhraseBook();
+ void openPhraseBook();
+ void closePhraseBook(QAction *action);
+ void editPhraseBook(QAction *action);
+ void printPhraseBook(QAction *action);
+ void addToPhraseBook();
+ void manual();
+ void resetSorting();
+ void about();
+ void aboutQt();
+
+ void updateViewMenu();
+ void fileAboutToShow();
+ void editAboutToShow();
+
+ void showContextDock();
+ void showMessagesDock();
+ void showPhrasesDock();
+ void showSourceCodeDock();
+ void showErrorDock();
+
+ void setupPhrase();
+ bool maybeSaveAll();
+ bool maybeSave(int model);
+ void updateProgress();
+ void maybeUpdateStatistics(const MultiDataIndex &);
+ void translationChanged(const MultiDataIndex &);
+ void updateCaption();
+ void updateLatestModel(const QModelIndex &index);
+ void selectedContextChanged(const QModelIndex &sortedIndex, const QModelIndex &oldIndex);
+ void selectedMessageChanged(const QModelIndex &sortedIndex, const QModelIndex &oldIndex);
+
+ // To synchronize from the message editor to the model ...
+ void updateTranslation(const QStringList &translations);
+ void updateTranslatorComment(const QString &comment);
+
+ void updateActiveModel(int);
+ void refreshItemViews();
+ void toggleFinished(const QModelIndex &index);
+ void prevUnfinished();
+ void nextUnfinished();
+ void findNext(const QString &text, DataModel::FindLocation where, bool matchCase, bool ignoreAccelerators);
+ void revalidate();
+ void toggleStatistics();
+ void onWhatsThis();
+ void updatePhraseDicts();
+ void updatePhraseDict(int model);
+
+private:
+ QModelIndex nextContext(const QModelIndex &index) const;
+ QModelIndex prevContext(const QModelIndex &index) const;
+ QModelIndex nextMessage(const QModelIndex &currentIndex, bool checkUnfinished = false) const;
+ QModelIndex prevMessage(const QModelIndex &currentIndex, bool checkUnfinished = false) const;
+ bool next(bool checkUnfinished);
+ bool prev(bool checkUnfinished);
+
+ void updateStatistics();
+ void modelCountChanged();
+ void setupMenuBar();
+ void setupToolBars();
+ void setCurrentMessage(const QModelIndex &index);
+ void setCurrentMessage(const QModelIndex &index, int model);
+ QModelIndex setMessageViewRoot(const QModelIndex &index);
+ QModelIndex currentContextIndex() const;
+ QModelIndex currentMessageIndex() const;
+ PhraseBook *openPhraseBook(const QString &name);
+ bool isPhraseBookOpen(const QString &name);
+ bool savePhraseBook(QString *name, PhraseBook &pb);
+ bool maybeSavePhraseBook(PhraseBook *phraseBook);
+ bool closePhraseBooks();
+ QStringList pickTranslationFiles();
+ void showTranslationSettings(int model);
+ void updateLatestModel(int model);
+ void updatePhraseBookActions();
+ void updatePhraseDictInternal(int model);
+ void releaseInternal(int model);
+ void saveInternal(int model);
+
+ // FIXME: move to DataModel
+ void updateDanger(const MultiDataIndex &index, bool verbose);
+
+ bool searchItem(const QString &searchWhat);
+
+ QProcess *m_assistantProcess;
+ QTreeView *m_contextView;
+ QTreeView *m_messageView;
+ MultiDataModel *m_dataModel;
+ MessageModel *m_messageModel;
+ QSortFilterProxyModel *m_sortedContextsModel;
+ QSortFilterProxyModel *m_sortedMessagesModel;
+ MessageEditor *m_messageEditor;
+ PhraseView *m_phraseView;
+ QStackedWidget *m_sourceAndFormView;
+ SourceCodeView *m_sourceCodeView;
+ FormPreviewView *m_formPreviewView;
+ ErrorsView *m_errorsView;
+ QLabel *m_progressLabel;
+ QLabel *m_modifiedLabel;
+ FocusWatcher *m_focusWatcher;
+ QString m_phraseBookDir;
+ // model : keyword -> list of appropriate phrases in the phrasebooks
+ QList<QHash<QString, QList<Phrase *> > > m_phraseDict;
+ QList<PhraseBook *> m_phraseBooks;
+ QMap<QAction *, PhraseBook *> m_phraseBookMenu[3];
+ QPrinter m_printer;
+
+ FindDialog *m_findDialog;
+ QString m_findText;
+ Qt::CaseSensitivity m_findMatchCase;
+ bool m_findIgnoreAccelerators;
+ DataModel::FindLocation m_findWhere;
+ DataModel::FindLocation m_foundWhere;
+
+ TranslateDialog *m_translateDialog;
+ QString m_latestFindText;
+ int m_latestCaseSensitivity;
+ int m_remainingCount;
+ int m_hitCount;
+
+ BatchTranslationDialog *m_batchTranslateDialog;
+ TranslationSettingsDialog *m_translationSettingsDialog;
+
+ bool m_settingCurrentMessage;
+ int m_fileActiveModel;
+ int m_editActiveModel;
+ MultiDataIndex m_currentIndex;
+
+ QDockWidget *m_contextDock;
+ QDockWidget *m_messagesDock;
+ QDockWidget *m_phrasesDock;
+ QDockWidget *m_sourceAndFormDock;
+ QDockWidget *m_errorsDock;
+
+ Ui::MainWindow m_ui; // menus and actions
+ Statistics *m_statistics;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/linguist/mainwindow.ui b/tools/linguist/linguist/mainwindow.ui
new file mode 100644
index 0000000000..6cc74ac23c
--- /dev/null
+++ b/tools/linguist/linguist/mainwindow.ui
@@ -0,0 +1,883 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>673</width>
+ <height>461</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget"/>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>673</width>
+ <height>30</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuPhrases">
+ <property name="title">
+ <string>&amp;Phrases</string>
+ </property>
+ <widget class="QMenu" name="menuClosePhraseBook">
+ <property name="title">
+ <string>&amp;Close Phrase Book</string>
+ </property>
+ </widget>
+ <widget class="QMenu" name="menuEditPhraseBook">
+ <property name="title">
+ <string>&amp;Edit Phrase Book</string>
+ </property>
+ </widget>
+ <widget class="QMenu" name="menuPrintPhraseBook">
+ <property name="title">
+ <string>&amp;Print Phrase Book</string>
+ </property>
+ </widget>
+ <addaction name="actionNewPhraseBook"/>
+ <addaction name="actionOpenPhraseBook"/>
+ <addaction name="menuClosePhraseBook"/>
+ <addaction name="separator"/>
+ <addaction name="menuEditPhraseBook"/>
+ <addaction name="menuPrintPhraseBook"/>
+ <addaction name="actionAddToPhraseBook"/>
+ </widget>
+ <widget class="QMenu" name="menuValidation">
+ <property name="title">
+ <string>V&amp;alidation</string>
+ </property>
+ <addaction name="actionAccelerators"/>
+ <addaction name="actionEndingPunctuation"/>
+ <addaction name="actionPhraseMatches"/>
+ <addaction name="actionPlaceMarkerMatches"/>
+ </widget>
+ <widget class="QMenu" name="menuView">
+ <property name="title">
+ <string>&amp;View</string>
+ </property>
+ <widget class="QMenu" name="menuViewViews">
+ <property name="title">
+ <string>Vie&amp;ws</string>
+ </property>
+ </widget>
+ <widget class="QMenu" name="menuToolbars">
+ <property name="title">
+ <string>&amp;Toolbars</string>
+ </property>
+ </widget>
+ <addaction name="actionResetSorting"/>
+ <addaction name="actionDisplayGuesses"/>
+ <addaction name="actionStatistics"/>
+ <addaction name="separator"/>
+ <addaction name="menuToolbars"/>
+ <addaction name="menuViewViews"/>
+ </widget>
+ <widget class="QMenu" name="menuHelp">
+ <property name="title">
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="actionManual"/>
+ <addaction name="actionAbout"/>
+ <addaction name="actionAboutQt"/>
+ <addaction name="actionWhatsThis"/>
+ </widget>
+ <widget class="QMenu" name="menuTranslation">
+ <property name="title">
+ <string>&amp;Translation</string>
+ </property>
+ <addaction name="actionPrevUnfinished"/>
+ <addaction name="actionNextUnfinished"/>
+ <addaction name="actionPrev"/>
+ <addaction name="actionNext"/>
+ <addaction name="actionDoneAndNext"/>
+ <addaction name="actionBeginFromSource"/>
+ </widget>
+ <widget class="QMenu" name="menuFile">
+ <property name="title">
+ <string>&amp;File</string>
+ </property>
+ <widget class="QMenu" name="menuRecentlyOpenedFiles">
+ <property name="title">
+ <string>Recently Opened &amp;Files</string>
+ </property>
+ </widget>
+ <addaction name="actionOpen"/>
+ <addaction name="actionOpenAux"/>
+ <addaction name="menuRecentlyOpenedFiles"/>
+ <addaction name="separator"/>
+ <addaction name="actionSaveAll"/>
+ <addaction name="actionSave"/>
+ <addaction name="actionSaveAs"/>
+ <addaction name="actionReleaseAll"/>
+ <addaction name="actionRelease"/>
+ <addaction name="actionReleaseAs"/>
+ <addaction name="separator"/>
+ <addaction name="actionPrint"/>
+ <addaction name="separator"/>
+ <addaction name="actionCloseAll"/>
+ <addaction name="actionClose"/>
+ <addaction name="separator"/>
+ <addaction name="actionExit"/>
+ </widget>
+ <widget class="QMenu" name="menuEdit">
+ <property name="title">
+ <string>&amp;Edit</string>
+ </property>
+ <addaction name="actionUndo"/>
+ <addaction name="actionRedo"/>
+ <addaction name="separator"/>
+ <addaction name="actionCut"/>
+ <addaction name="actionCopy"/>
+ <addaction name="actionPaste"/>
+ <addaction name="actionSelectAll"/>
+ <addaction name="separator"/>
+ <addaction name="actionFind"/>
+ <addaction name="actionFindNext"/>
+ <addaction name="actionSearchAndTranslate"/>
+ <addaction name="actionBatchTranslation"/>
+ <addaction name="actionTranslationFileSettings"/>
+ </widget>
+ <addaction name="menuFile"/>
+ <addaction name="menuEdit"/>
+ <addaction name="menuTranslation"/>
+ <addaction name="menuValidation"/>
+ <addaction name="menuPhrases"/>
+ <addaction name="menuView"/>
+ <addaction name="menuHelp"/>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ <action name="actionOpen">
+ <property name="text">
+ <string>&amp;Open...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Open a Qt translation source file (TS file) for editing</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="actionExit">
+ <property name="text">
+ <string>E&amp;xit</string>
+ </property>
+ <property name="statusTip">
+ <string/>
+ </property>
+ <property name="whatsThis">
+ <string>Close this window and exit.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Q</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::QuitRole</enum>
+ </property>
+ </action>
+ <action name="actionSave">
+ <property name="text">
+ <string>Save</string>
+ </property>
+ <property name="whatsThis">
+ <string>Save changes made to this Qt translation source file</string>
+ </property>
+ </action>
+ <action name="actionSaveAs">
+ <property name="text">
+ <string>Save &amp;As...</string>
+ </property>
+ <property name="iconText">
+ <string>Save As...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Save changes made to this Qt translation source file into a new file.</string>
+ </property>
+ </action>
+ <action name="actionRelease">
+ <property name="text">
+ <string>Release</string>
+ </property>
+ <property name="whatsThis">
+ <string>Create a Qt message file suitable for released applications from the current message file.</string>
+ </property>
+ </action>
+ <action name="actionPrint">
+ <property name="text">
+ <string>&amp;Print...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Print a list of all the translation units in the current translation source file.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+P</string>
+ </property>
+ </action>
+ <action name="actionUndo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Undo</string>
+ </property>
+ <property name="whatsThis">
+ <string>Undo the last editing operation performed on the current translation.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Z</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionRedo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Redo</string>
+ </property>
+ <property name="whatsThis">
+ <string>Redo an undone editing operation performed on the translation.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Y</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionCut">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Cu&amp;t</string>
+ </property>
+ <property name="whatsThis">
+ <string>Copy the selected translation text to the clipboard and deletes it.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+X</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionCopy">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Copy</string>
+ </property>
+ <property name="whatsThis">
+ <string>Copy the selected translation text to the clipboard.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+C</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionPaste">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Paste</string>
+ </property>
+ <property name="whatsThis">
+ <string>Paste the clipboard text into the translation.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+V</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionSelectAll">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Select &amp;All</string>
+ </property>
+ <property name="whatsThis">
+ <string>Select the whole translation text.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+A</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionFind">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Find...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Search for some text in the translation source file.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+F</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionFindNext">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Find &amp;Next</string>
+ </property>
+ <property name="whatsThis">
+ <string>Continue the search where it was left.</string>
+ </property>
+ <property name="shortcut">
+ <string>F3</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionPrevUnfinished">
+ <property name="text">
+ <string>&amp;Prev Unfinished</string>
+ </property>
+ <property name="toolTip">
+ <string>Previous unfinished item.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Move to the previous unfinished item.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+K</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionNextUnfinished">
+ <property name="text">
+ <string>&amp;Next Unfinished</string>
+ </property>
+ <property name="toolTip">
+ <string>Next unfinished item.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Move to the next unfinished item.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+J</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionPrev">
+ <property name="text">
+ <string>P&amp;rev</string>
+ </property>
+ <property name="toolTip">
+ <string>Move to previous item.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Move to the previous item.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+K</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionNext">
+ <property name="text">
+ <string>Ne&amp;xt</string>
+ </property>
+ <property name="toolTip">
+ <string>Next item.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Move to the next item.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Shift+J</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionDoneAndNext">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Done and Next</string>
+ </property>
+ <property name="toolTip">
+ <string>Mark item as done and move to the next unfinished item.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Mark this item as done and move to the next unfinished item.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionBeginFromSource">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Copy from source text</string>
+ </property>
+ <property name="iconText">
+ <string>Copy from source text</string>
+ </property>
+ <property name="toolTip">
+ <string>Copies the source text into the translation field.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Copies the source text into the translation field.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+B</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionAccelerators">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Accelerators</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle the validity check of accelerators.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Toggle the validity check of accelerators, i.e. whether the number of ampersands in the source and translation text is the same. If the check fails, a message is shown in the warnings window.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionEndingPunctuation">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Ending Punctuation</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle the validity check of ending punctuation.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Toggle the validity check of ending punctuation. If the check fails, a message is shown in the warnings window.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionPhraseMatches">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Phrase matches</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle checking that phrase suggestions are used.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Toggle checking that phrase suggestions are used. If the check fails, a message is shown in the warnings window.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionPlaceMarkerMatches">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Place &amp;Marker Matches</string>
+ </property>
+ <property name="toolTip">
+ <string>Toggle the validity check of place markers.</string>
+ </property>
+ <property name="whatsThis">
+ <string>Toggle the validity check of place markers, i.e. whether %1, %2, ... are used consistently in the source text and translation text. If the check fails, a message is shown in the warnings window.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionNewPhraseBook">
+ <property name="text">
+ <string>&amp;New Phrase Book...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Create a new phrase book.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+N</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionOpenPhraseBook">
+ <property name="text">
+ <string>&amp;Open Phrase Book...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Open a phrase book to assist translation.</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+H</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionResetSorting">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Reset Sorting</string>
+ </property>
+ <property name="whatsThis">
+ <string>Sort the items back in the same order as in the message file.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionDisplayGuesses">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Display guesses</string>
+ </property>
+ <property name="whatsThis">
+ <string>Set whether or not to display translation guesses.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionStatistics">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Statistics</string>
+ </property>
+ <property name="whatsThis">
+ <string>Display translation statistics.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionManual">
+ <property name="text">
+ <string>&amp;Manual</string>
+ </property>
+ <property name="whatsThis">
+ <string/>
+ </property>
+ <property name="shortcut">
+ <string>F1</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionAbout">
+ <property name="text">
+ <string>About Qt Linguist</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::AboutRole</enum>
+ </property>
+ </action>
+ <action name="actionAboutQt">
+ <property name="text">
+ <string>About Qt</string>
+ </property>
+ <property name="whatsThis">
+ <string>Display information about the Qt toolkit by Trolltech.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::AboutQtRole</enum>
+ </property>
+ </action>
+ <action name="actionWhatsThis">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;What's This?</string>
+ </property>
+ <property name="iconText">
+ <string>What's This?</string>
+ </property>
+ <property name="toolTip">
+ <string>What's This?</string>
+ </property>
+ <property name="whatsThis">
+ <string>Enter What's This? mode.</string>
+ </property>
+ <property name="shortcut">
+ <string>Shift+F1</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionSearchAndTranslate">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Search And Translate...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Replace the translation on all entries that matches the search source text.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionBatchTranslation">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Batch Translation...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Batch translate all entries using the information in the phrase books.</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionReleaseAs">
+ <property name="text">
+ <string>Release As...</string>
+ </property>
+ <property name="iconText">
+ <string>Release As...</string>
+ </property>
+ <property name="whatsThis">
+ <string>Create a Qt message file suitable for released applications from the current message file. The filename will automatically be determined from the name of the .ts file.</string>
+ </property>
+ </action>
+ <action name="actionFile">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>File</string>
+ </property>
+ </action>
+ <action name="actionEdit">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </action>
+ <action name="actionTranslation">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Translation</string>
+ </property>
+ </action>
+ <action name="actionValidation">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Validation</string>
+ </property>
+ </action>
+ <action name="actionHelp">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Help</string>
+ </property>
+ </action>
+ <action name="actionPreviewForm">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Open/Refresh Form &amp;Preview</string>
+ </property>
+ <property name="iconText">
+ <string>Form Preview Tool</string>
+ </property>
+ <property name="toolTip">
+ <string>Form Preview Tool</string>
+ </property>
+ <property name="shortcut">
+ <string>F5</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionTranslationFileSettings">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Translation File &amp;Settings...</string>
+ </property>
+ <property name="menuRole">
+ <enum>QAction::NoRole</enum>
+ </property>
+ </action>
+ <action name="actionAddToPhraseBook">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Add to Phrase Book</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+T</string>
+ </property>
+ </action>
+ <action name="actionOpenAux">
+ <property name="text">
+ <string>Open Read-O&amp;nly...</string>
+ </property>
+ </action>
+ <action name="actionSaveAll">
+ <property name="text">
+ <string>&amp;Save All</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+S</string>
+ </property>
+ </action>
+ <action name="actionReleaseAll">
+ <property name="text">
+ <string>&amp;Release All</string>
+ </property>
+ </action>
+ <action name="actionClose">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </action>
+ <action name="actionCloseAll">
+ <property name="text">
+ <string>&amp;Close All</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+W</string>
+ </property>
+ </action>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/linguist/linguist/messageeditor.cpp b/tools/linguist/linguist/messageeditor.cpp
new file mode 100644
index 0000000000..f8c679ca75
--- /dev/null
+++ b/tools/linguist/linguist/messageeditor.cpp
@@ -0,0 +1,865 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* TRANSLATOR MsgEdit
+
+ This is the right panel of the main window.
+*/
+
+#include "messageeditor.h"
+#include "messageeditorwidgets.h"
+#include "simtexth.h"
+#include "phrasemodel.h"
+
+#include <QApplication>
+#include <QBoxLayout>
+#include <QClipboard>
+#include <QDebug>
+#include <QDockWidget>
+#include <QHeaderView>
+#include <QKeyEvent>
+#include <QMainWindow>
+#include <QPainter>
+#include <QTreeView>
+#include <QVBoxLayout>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef NEVER_TRUE
+// Allow translators to provide localized names for QLocale::languageToString
+// At least the own language should be translated ... This is a "hack" until
+// functionality is provided within Qt (see task 196275).
+static const char * language_strings[] =
+{
+ QT_TRANSLATE_NOOP("MessageEditor", "German"),
+ QT_TRANSLATE_NOOP("MessageEditor", "Japanese"),
+ QT_TRANSLATE_NOOP("MessageEditor", "French"),
+ QT_TRANSLATE_NOOP("MessageEditor", "Polish"),
+ QT_TRANSLATE_NOOP("MessageEditor", "Chinese")
+};
+#endif
+
+/*
+ MessageEditor class impl.
+
+ Handles layout of dock windows and the editor page.
+*/
+MessageEditor::MessageEditor(MultiDataModel *dataModel, QMainWindow *parent)
+ : QScrollArea(parent->centralWidget()),
+ m_dataModel(dataModel),
+ m_currentModel(-1),
+ m_currentNumerus(-1),
+ m_undoAvail(false),
+ m_redoAvail(false),
+ m_cutAvail(false),
+ m_copyAvail(false),
+ m_sourceSelected(false),
+ m_pluralSourceSelected(false),
+ m_currentSelected(false)
+{
+ setObjectName(QLatin1String("scroll area"));
+
+ // Use white explicitly as the background color for the editor page.
+ QPalette p;
+ p.setColor(QPalette::Active, QPalette::Base, Qt::white);
+ p.setColor(QPalette::Inactive, QPalette::Base, Qt::white);
+ p.setColor(QPalette::Disabled, QPalette::Base, Qt::white);
+ p.setColor(QPalette::Active, QPalette::Window, Qt::white);
+ p.setColor(QPalette::Inactive, QPalette::Window, Qt::white);
+ p.setColor(QPalette::Disabled, QPalette::Window, Qt::white);
+ setPalette(p);
+
+ setupEditorPage();
+
+ // Signals
+ connect(qApp->clipboard(), SIGNAL(dataChanged()),
+ SLOT(clipboardChanged()));
+ connect(m_dataModel, SIGNAL(modelAppended()),
+ SLOT(messageModelAppended()));
+ connect(m_dataModel, SIGNAL(modelDeleted(int)),
+ SLOT(messageModelDeleted(int)));
+ connect(m_dataModel, SIGNAL(allModelsDeleted()),
+ SLOT(allModelsDeleted()));
+ connect(m_dataModel, SIGNAL(languageChanged(int)),
+ SLOT(setTargetLanguage(int)));
+
+ clipboardChanged();
+
+ setWhatsThis(tr("This whole panel allows you to view and edit "
+ "the translation of some source text."));
+ showNothing();
+}
+
+void MessageEditor::setupEditorPage()
+{
+ QFrame *editorPage = new QFrame;
+ editorPage->setObjectName(QLatin1String("editorPage"));
+
+ // Due to CSS being rather broken on the Mac style at the moment, only
+ // use the border-image on non-Mac systems.
+ editorPage->setStyleSheet(QLatin1String(
+#ifndef Q_WS_MAC
+ "QFrame#editorPage { border-image: url(:/images/transbox.png) 12 16 16 12 repeat;"
+ " border-width: 12px 16px 16px 12px; }"
+#endif
+ "QFrame#editorPage { background-color: white; }"
+ "QLabel { font-weight: bold; }"
+ ));
+#ifdef Q_WS_MAC
+ editorPage->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+#endif
+ editorPage->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+
+ m_source = new FormWidget(tr("Source text"), false);
+ m_source->setHideWhenEmpty(true);
+ m_source->setWhatsThis(tr("This area shows the source text."));
+ connect(m_source, SIGNAL(selectionChanged()), SLOT(selectionChanged()));
+
+ m_pluralSource = new FormWidget(tr("Source text (Plural)"), false);
+ m_pluralSource->setHideWhenEmpty(true);
+ m_pluralSource->setWhatsThis(tr("This area shows the plural form of the source text."));
+ connect(m_pluralSource, SIGNAL(selectionChanged()), SLOT(selectionChanged()));
+
+ m_commentText = new FormWidget(tr("Developer comments"), false);
+ m_commentText->setHideWhenEmpty(true);
+ m_commentText->setObjectName(QLatin1String("comment/context view"));
+ m_commentText->setWhatsThis(tr("This area shows a comment that"
+ " may guide you, and the context in which the text"
+ " occurs.") );
+
+ QBoxLayout *subLayout = new QVBoxLayout;
+
+ subLayout->setMargin(5);
+ subLayout->addWidget(m_source);
+ subLayout->addWidget(m_pluralSource);
+ subLayout->addWidget(m_commentText);
+
+ m_layout = new QVBoxLayout;
+ m_layout->setSpacing(2);
+ m_layout->setMargin(2);
+ m_layout->addLayout(subLayout);
+ m_layout->addStretch(1);
+ editorPage->setLayout(m_layout);
+
+ setWidget(editorPage);
+ setWidgetResizable(true);
+}
+
+QPalette MessageEditor::paletteForModel(int model) const
+{
+ QBrush brush = m_dataModel->brushForModel(model);
+ QPalette pal;
+
+ if (m_dataModel->isModelWritable(model)) {
+ pal.setBrush(QPalette::Window, brush);
+ } else {
+ QPixmap pm(brush.texture().size());
+ pm.fill();
+ QPainter p(&pm);
+ p.fillRect(brush.texture().rect(), brush);
+ pal.setBrush(QPalette::Window, pm);
+ }
+ return pal;
+}
+
+void MessageEditor::messageModelAppended()
+{
+ int model = m_editors.size();
+ m_editors.append(MessageEditorData());
+ MessageEditorData &ed = m_editors.last();
+ ed.pluralEditMode = false;
+ ed.fontSize = font().pointSize();
+ ed.container = new QWidget;
+ if (model > 0) {
+ ed.container->setPalette(paletteForModel(model));
+ ed.container->setAutoFillBackground(true);
+ if (model == 1) {
+ m_editors[0].container->setPalette(paletteForModel(0));
+ m_editors[0].container->setAutoFillBackground(true);
+ }
+ }
+ bool writable = m_dataModel->isModelWritable(model);
+ ed.transCommentText = new FormWidget(QString(), true);
+ ed.transCommentText->setEditingEnabled(writable);
+ ed.transCommentText->setHideWhenEmpty(!writable);
+ ed.transCommentText->setWhatsThis(tr("Here you can enter comments for your own use."
+ " They have no effect on the translated applications.") );
+ ed.transCommentText->getEditor()->installEventFilter(this);
+ connect(ed.transCommentText, SIGNAL(selectionChanged()), SLOT(selectionChanged()));
+ connect(ed.transCommentText, SIGNAL(textChanged()), SLOT(emitTranslatorCommentChanged()));
+ connect(ed.transCommentText, SIGNAL(textChanged()), SLOT(resetHoverSelection()));
+ connect(ed.transCommentText, SIGNAL(cursorPositionChanged()), SLOT(resetHoverSelection()));
+ QBoxLayout *box = new QVBoxLayout(ed.container);
+ box->setMargin(5);
+ box->addWidget(ed.transCommentText);
+ box->addSpacing(ed.transCommentText->getEditor()->fontMetrics().height() / 2);
+ m_layout->addWidget(ed.container);
+ setTargetLanguage(model);
+}
+
+void MessageEditor::allModelsDeleted()
+{
+ foreach (const MessageEditorData &med, m_editors)
+ med.container->deleteLater();
+ m_editors.clear();
+ m_currentModel = -1;
+ // Do not emit activeModelChanged() - the main window will refresh anyway
+ m_currentNumerus = -1;
+ showNothing();
+}
+
+void MessageEditor::messageModelDeleted(int model)
+{
+ m_editors[model].container->deleteLater();
+ m_editors.removeAt(model);
+ if (model <= m_currentModel) {
+ if (model < m_currentModel || m_currentModel == m_editors.size())
+ --m_currentModel;
+ // Do not emit activeModelChanged() - the main window will refresh anyway
+ if (m_currentModel >= 0) {
+ if (m_currentNumerus >= m_editors[m_currentModel].transTexts.size())
+ m_currentNumerus = m_editors[m_currentModel].transTexts.size() - 1;
+ activeEditor()->getEditor()->setFocus();
+ } else {
+ m_currentNumerus = -1;
+ }
+ }
+ if (m_editors.size() == 1) {
+ m_editors[0].container->setAutoFillBackground(false);
+ } else {
+ for (int i = model; i < m_editors.size(); ++i)
+ m_editors[i].container->setPalette(paletteForModel(i));
+ }
+}
+
+void MessageEditor::addPluralForm(int model, const QString &label, bool writable)
+{
+ FormWidget *transEditor = new FormWidget(label, true);
+ QFont font;
+ font.setPointSize(static_cast<int>(m_editors[model].fontSize));
+ transEditor->getEditor()->setFont(font);
+ transEditor->setEditingEnabled(writable);
+ transEditor->setHideWhenEmpty(!writable);
+ if (!m_editors[model].transTexts.isEmpty())
+ transEditor->setVisible(false);
+ static_cast<QBoxLayout *>(m_editors[model].container->layout())->insertWidget(
+ m_editors[model].transTexts.count(), transEditor);
+
+ transEditor->getEditor()->installEventFilter(this);
+ connect(transEditor, SIGNAL(selectionChanged()), SLOT(selectionChanged()));
+ connect(transEditor, SIGNAL(textChanged()), SLOT(emitTranslationChanged()));
+ connect(transEditor, SIGNAL(textChanged()), SLOT(resetHoverSelection()));
+ connect(transEditor, SIGNAL(cursorPositionChanged()), SLOT(resetHoverSelection()));
+
+ m_editors[model].transTexts << transEditor;
+}
+
+/*! internal
+ Returns all translations for an item.
+ The number of translations is dependent on if we have a plural form or not.
+ If we don't have a plural form, then this should only contain one item.
+ Otherwise it will contain the number of numerus forms for the particular language.
+*/
+QStringList MessageEditor::translations(int model) const
+{
+ QStringList translations;
+ for (int i = 0; i < m_editors[model].transTexts.count() &&
+ m_editors[model].transTexts.at(i)->isVisible(); ++i)
+ translations << m_editors[model].transTexts[i]->getTranslation();
+ return translations;
+}
+
+static bool clearFormSelection(FormWidget *fw, FormWidget *te)
+{
+ if (fw != te) {
+ QTextEdit *t = fw->getEditor();
+ bool oldBlockState = t->blockSignals(true);
+ QTextCursor c = t->textCursor();
+ c.clearSelection();
+ t->setTextCursor(c);
+ t->blockSignals(oldBlockState);
+ return true;
+ }
+ return false;
+}
+
+// Clear the selection for all textedits except the sender
+void MessageEditor::selectionChanged()
+{
+ if (!resetSelection(qobject_cast<FormWidget *>(sender())))
+ updateCanCutCopy();
+}
+
+bool MessageEditor::resetHoverSelection(FormWidget *fw)
+{
+ if (m_sourceSelected) {
+ if (clearFormSelection(m_source, fw)) {
+ updateCanCutCopy();
+ return true;
+ }
+ } else if (m_pluralSourceSelected) {
+ if (clearFormSelection(m_pluralSource, fw)) {
+ updateCanCutCopy();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MessageEditor::resetSelection(FormWidget *fw)
+{
+ if (resetHoverSelection(fw))
+ return true;
+ if (m_currentSelected) {
+ MessageEditorData &ed = m_editors[m_currentModel];
+ FormWidget *cfw = (m_currentNumerus < 0) ? ed.transCommentText
+ : ed.transTexts[m_currentNumerus];
+ if (clearFormSelection(cfw, fw)) {
+ updateCanCutCopy();
+ return true;
+ }
+ }
+ return false;
+}
+
+void MessageEditor::activeModelAndNumerus(int *model, int *numerus) const
+{
+ for (int j = 0; j < m_editors.count(); ++j) {
+ for (int i = 0; i < m_editors[j].transTexts.count(); ++i)
+ if (m_editors[j].transTexts[i]->getEditor()->hasFocus()) {
+ *model = j;
+ *numerus = i;
+ return;
+ }
+ if (m_editors[j].transCommentText->getEditor()->hasFocus()) {
+ *model = j;
+ *numerus = -1;
+ return;
+ }
+ }
+ *model = -1;
+ *numerus = -1;
+}
+
+FormWidget *MessageEditor::activeTranslation() const
+{
+ if (m_currentNumerus < 0)
+ return 0;
+ return m_editors[m_currentModel].transTexts[m_currentNumerus];
+}
+
+FormWidget *MessageEditor::activeOr1stTranslation() const
+{
+ if (m_currentNumerus < 0) {
+ for (int i = 0; i < m_editors.size(); ++i)
+ if (m_editors[i].container->isVisible()
+ && !m_editors[i].transTexts[0]->getEditor()->isReadOnly())
+ return m_editors[i].transTexts[0];
+ return 0;
+ }
+ return m_editors[m_currentModel].transTexts[m_currentNumerus];
+}
+
+FormWidget *MessageEditor::activeTransComment() const
+{
+ if (m_currentModel < 0 || m_currentNumerus >= 0)
+ return 0;
+ return m_editors[m_currentModel].transCommentText;
+}
+
+FormWidget *MessageEditor::activeEditor() const
+{
+ if (FormWidget *fw = activeTransComment())
+ return fw;
+ return activeTranslation();
+}
+
+FormWidget *MessageEditor::activeOr1stEditor() const
+{
+ if (FormWidget *fw = activeTransComment())
+ return fw;
+ return activeOr1stTranslation();
+}
+
+void MessageEditor::setTargetLanguage(int model)
+{
+ const QStringList &numerusForms = m_dataModel->model(model)->numerusForms();
+ const QString &langLocalized = m_dataModel->model(model)->localizedLanguage();
+ bool added = false;
+ for (int i = 0; i < numerusForms.count(); ++i) {
+ const QString &label = tr("%1 translation (%2)").arg(langLocalized, numerusForms[i]);
+ if (!i)
+ m_editors[model].firstForm = label;
+ if (i >= m_editors[model].transTexts.count()) {
+ addPluralForm(model, label, m_dataModel->isModelWritable(model));
+ QWidget *prev;
+ if (i > 0)
+ prev = m_editors[model].transTexts[i - 1]->getEditor();
+ else if (model)
+ prev = m_editors[model - 1].transCommentText->getEditor();
+ else
+ prev = this;
+ setTabOrder(prev, m_editors[model].transTexts[i]->getEditor());
+ added = true;
+ } else {
+ m_editors[model].transTexts[i]->setLabel(label);
+ }
+ m_editors[model].transTexts[i]->setVisible(!i || m_editors[model].pluralEditMode);
+ m_editors[model].transTexts[i]->setWhatsThis(
+ tr("This is where you can enter or modify"
+ " the translation of the above source text.") );
+ }
+ for (int j = m_editors[model].transTexts.count() - numerusForms.count(); j > 0; --j)
+ delete m_editors[model].transTexts.takeLast();
+ m_editors[model].invariantForm = tr("%1 translation").arg(langLocalized);
+ m_editors[model].transCommentText->setLabel(tr("%1 translator comments").arg(langLocalized));
+ if (added)
+ setTabOrder(m_editors[model].transTexts.last()->getEditor(), m_editors[model].transCommentText->getEditor());
+}
+
+MessageEditorData *MessageEditor::modelForWidget(const QObject *o)
+{
+ for (int j = 0; j < m_editors.count(); ++j) {
+ for (int i = 0; i < m_editors[j].transTexts.count(); ++i)
+ if (m_editors[j].transTexts[i]->getEditor() == o)
+ return &m_editors[j];
+ if (m_editors[j].transCommentText->getEditor() == o)
+ return &m_editors[j];
+ }
+ return 0;
+}
+
+static bool applyFont(MessageEditorData *med)
+{
+ QFont font;
+ font.setPointSize(static_cast<int>(med->fontSize));
+ for (int i = 0; i < med->transTexts.count(); ++i)
+ med->transTexts[i]->getEditor()->setFont(font);
+ med->transCommentText->getEditor()->setFont(font);
+ return true;
+}
+
+static bool incFont(MessageEditorData *med)
+{
+ if (!med || med->fontSize >= 32)
+ return true;
+ med->fontSize *= 1.2;
+ return applyFont(med);
+}
+
+static bool decFont(MessageEditorData *med)
+{
+ if (!med || med->fontSize <= 8)
+ return true;
+ med->fontSize /= 1.2;
+ return applyFont(med);
+}
+
+bool MessageEditor::eventFilter(QObject *o, QEvent *e)
+{
+ // handle copying from the source
+ if (e->type() == QEvent::ShortcutOverride) {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
+
+ if (ke->modifiers() & Qt::ControlModifier) {
+ if (ke->key() == Qt::Key_C) {
+ if (m_source->getEditor()->textCursor().hasSelection()) {
+ m_source->getEditor()->copy();
+ return true;
+ }
+ if (m_pluralSource->getEditor()->textCursor().hasSelection()) {
+ m_pluralSource->getEditor()->copy();
+ return true;
+ }
+ }
+ }
+ } else if (e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
+ if (ke->modifiers() & Qt::ControlModifier) {
+ if (ke->key() == Qt::Key_Plus || ke->key() == Qt::Key_Equal)
+ return incFont(modelForWidget(o));
+ if (ke->key() == Qt::Key_Minus)
+ return decFont(modelForWidget(o));
+ } else {
+ // Ctrl-Tab is still passed through to the textedit and causes a tab to be inserted.
+ if (ke->key() == Qt::Key_Tab) {
+ focusNextChild();
+ return true;
+ }
+ }
+ } else if (e->type() == QEvent::Wheel) {
+ QWheelEvent *we = static_cast<QWheelEvent *>(e);
+ if (we->modifiers() & Qt::ControlModifier) {
+ if (we->delta() > 0)
+ return incFont(modelForWidget(o));
+ return decFont(modelForWidget(o));
+ }
+ } else if (e->type() == QEvent::FocusIn) {
+ int model, numerus;
+ activeModelAndNumerus(&model, &numerus);
+ if (model != m_currentModel || numerus != m_currentNumerus) {
+ resetSelection();
+ m_currentModel = model;
+ m_currentNumerus = numerus;
+ emit activeModelChanged(activeModel());
+ updateBeginFromSource();
+ updateUndoRedo();
+ updateCanPaste();
+ }
+ }
+
+ return QScrollArea::eventFilter(o, e);
+}
+
+void MessageEditor::showNothing()
+{
+ m_source->clearTranslation();
+ m_pluralSource->clearTranslation();
+ m_commentText->clearTranslation();
+ for (int j = 0; j < m_editors.count(); ++j) {
+ setEditingEnabled(j, false);
+ foreach (FormWidget *widget, m_editors[j].transTexts)
+ widget->clearTranslation();
+ m_editors[j].transCommentText->clearTranslation();
+ }
+ emit pasteAvailable(false);
+ updateBeginFromSource();
+ updateUndoRedo();
+}
+
+void MessageEditor::showMessage(const MultiDataIndex &index)
+{
+ m_currentIndex = index;
+
+ bool hadMsg = false;
+ for (int j = 0; j < m_editors.size(); ++j) {
+
+ MessageEditorData &ed = m_editors[j];
+
+ MessageItem *item = m_dataModel->messageItem(index, j);
+ if (!item) {
+ ed.container->hide();
+ continue;
+ }
+ ed.container->show();
+
+ if (!hadMsg) {
+
+ // Source text form
+ m_source->setTranslation(item->text());
+ m_pluralSource->setTranslation(item->pluralText());
+ // Use location from first non-obsolete message
+ if (!item->fileName().isEmpty()) {
+ QString toolTip = tr("'%1'\nLine: %2").arg(item->fileName(), QString::number(item->lineNumber()));
+ m_source->setToolTip(toolTip);
+ } else {
+ m_source->setToolTip(QLatin1String(""));
+ }
+
+ // Comment field
+ QString commentText = item->comment().simplified();
+
+ if (!item->extraComment().isEmpty()) {
+ if (!commentText.isEmpty())
+ commentText += QLatin1String("\n");
+ commentText += item->extraComment().simplified();
+ }
+
+ m_commentText->setTranslation(commentText);
+
+ hadMsg = true;
+ }
+
+ setEditingEnabled(j, m_dataModel->isModelWritable(j)
+ && item->message().type() != TranslatorMessage::Obsolete);
+
+ // Translation label
+ ed.pluralEditMode = item->translations().count() > 1;
+ ed.transTexts.first()->setLabel(ed.pluralEditMode ? ed.firstForm : ed.invariantForm);
+
+ // Translation forms
+ if (item->text().isEmpty() && !item->context().isEmpty()) {
+ for (int i = 0; i < ed.transTexts.size(); ++i)
+ ed.transTexts.at(i)->setVisible(false);
+ } else {
+ QStringList normalizedTranslations =
+ m_dataModel->model(j)->normalizedTranslations(*item);
+ for (int i = 0; i < ed.transTexts.size(); ++i) {
+ bool shouldShow = (i < normalizedTranslations.count());
+ if (shouldShow)
+ setTranslation(j, normalizedTranslations.at(i), i);
+ else
+ setTranslation(j, QString(), i);
+ ed.transTexts.at(i)->setVisible(i == 0 || shouldShow);
+ }
+ }
+
+ ed.transCommentText->setTranslation(item->translatorComment().trimmed(), false);
+ }
+
+ updateUndoRedo();
+}
+
+void MessageEditor::setTranslation(int model, const QString &translation, int numerus)
+{
+ MessageEditorData &ed = m_editors[model];
+ if (numerus >= ed.transTexts.count())
+ numerus = 0;
+ FormWidget *transForm = ed.transTexts[numerus];
+ transForm->setTranslation(translation, false);
+
+ updateBeginFromSource();
+}
+
+void MessageEditor::setTranslation(int latestModel, const QString &translation)
+{
+ int numerus;
+ if (m_currentNumerus < 0) {
+ numerus = 0;
+ } else {
+ latestModel = m_currentModel;
+ numerus = m_currentNumerus;
+ }
+ FormWidget *transForm = m_editors[latestModel].transTexts[numerus];
+ transForm->getEditor()->setFocus();
+ transForm->setTranslation(translation, true);
+
+ updateBeginFromSource();
+}
+
+void MessageEditor::setEditingEnabled(int model, bool enabled)
+{
+ MessageEditorData &ed = m_editors[model];
+ foreach (FormWidget *widget, ed.transTexts)
+ widget->setEditingEnabled(enabled);
+ ed.transCommentText->setEditingEnabled(enabled);
+
+ updateCanPaste();
+}
+
+void MessageEditor::undo()
+{
+ activeEditor()->getEditor()->document()->undo();
+}
+
+void MessageEditor::redo()
+{
+ activeEditor()->getEditor()->document()->redo();
+}
+
+void MessageEditor::updateUndoRedo()
+{
+ bool newUndoAvail = false;
+ bool newRedoAvail = false;
+ if (FormWidget *fw = activeEditor()) {
+ QTextDocument *doc = fw->getEditor()->document();
+ newUndoAvail = doc->isUndoAvailable();
+ newRedoAvail = doc->isRedoAvailable();
+ }
+
+ if (newUndoAvail != m_undoAvail) {
+ m_undoAvail = newUndoAvail;
+ emit undoAvailable(newUndoAvail);
+ }
+
+ if (newRedoAvail != m_redoAvail) {
+ m_redoAvail = newRedoAvail;
+ emit redoAvailable(newRedoAvail);
+ }
+}
+
+void MessageEditor::cut()
+{
+ QTextEdit *editor = activeEditor()->getEditor();
+ if (editor->textCursor().hasSelection())
+ editor->cut();
+}
+
+void MessageEditor::copy()
+{
+ QTextEdit *te;
+ if ((te = m_source->getEditor())->textCursor().hasSelection()
+ || (te = m_pluralSource->getEditor())->textCursor().hasSelection()
+ || (te = activeEditor()->getEditor())->textCursor().hasSelection())
+ te->copy();
+}
+
+void MessageEditor::updateCanCutCopy()
+{
+ bool newCopyState = false;
+ bool newCutState = false;
+
+ m_sourceSelected = m_source->getEditor()->textCursor().hasSelection();
+ m_pluralSourceSelected = m_pluralSource->getEditor()->textCursor().hasSelection();
+ m_currentSelected = false;
+
+ if (m_sourceSelected || m_pluralSourceSelected) {
+ newCopyState = true;
+ } else if (FormWidget *fw = activeEditor()) {
+ QTextEdit *te = fw->getEditor();
+ if (te->textCursor().hasSelection()) {
+ m_currentSelected = true;
+ newCopyState = true;
+ newCutState = !te->isReadOnly();
+ }
+ }
+
+ if (newCopyState != m_copyAvail) {
+ m_copyAvail = newCopyState;
+ emit copyAvailable(m_copyAvail);
+ }
+
+ if (newCutState != m_cutAvail) {
+ m_cutAvail = newCutState;
+ emit cutAvailable(m_cutAvail);
+ }
+}
+
+void MessageEditor::paste()
+{
+ activeEditor()->getEditor()->paste();
+}
+
+void MessageEditor::updateCanPaste()
+{
+ FormWidget *fw;
+ emit pasteAvailable(!m_clipboardEmpty
+ && (fw = activeEditor()) && !fw->getEditor()->isReadOnly());
+}
+
+void MessageEditor::clipboardChanged()
+{
+ // this is expensive, so move it out of the common path in updateCanPaste
+ m_clipboardEmpty = qApp->clipboard()->text().isNull();
+ updateCanPaste();
+}
+
+void MessageEditor::selectAll()
+{
+ // make sure we don't select the selection of a translator textedit,
+ // if we really want the source text editor to be selected.
+ QTextEdit *te;
+ FormWidget *fw;
+ if ((te = m_source->getEditor())->underMouse()
+ || (te = m_pluralSource->getEditor())->underMouse()
+ || ((fw = activeEditor()) && (te = fw->getEditor())->hasFocus()))
+ te->selectAll();
+}
+
+void MessageEditor::emitTranslationChanged()
+{
+ updateBeginFromSource();
+ updateUndoRedo();
+ emit translationChanged(translations(m_currentModel));
+}
+
+void MessageEditor::emitTranslatorCommentChanged()
+{
+ updateUndoRedo();
+ emit translatorCommentChanged(m_editors[m_currentModel].transCommentText->getTranslation());
+}
+
+void MessageEditor::updateBeginFromSource()
+{
+ bool overwrite = false;
+ if (FormWidget *transForm = activeTranslation()) {
+ QTextEdit *activeEditor = transForm->getEditor();
+ overwrite = !activeEditor->isReadOnly()
+ && activeEditor->toPlainText().trimmed().isEmpty();
+ }
+ emit beginFromSourceAvailable(overwrite);
+}
+
+void MessageEditor::beginFromSource()
+{
+ MessageItem *item = m_dataModel->messageItem(m_currentIndex, m_currentModel);
+ setTranslation(m_currentModel,
+ m_currentNumerus > 0 && !item->pluralText().isEmpty() ?
+ item->pluralText() : item->text());
+}
+
+void MessageEditor::setEditorFocus()
+{
+ if (!widget()->hasFocus())
+ if (FormWidget *transForm = activeOr1stEditor())
+ transForm->getEditor()->setFocus();
+}
+
+void MessageEditor::setEditorFocus(int model)
+{
+ if (m_currentModel != model) {
+ if (model < 0) {
+ resetSelection();
+ m_currentNumerus = -1;
+ m_currentModel = -1;
+ emit activeModelChanged(activeModel());
+ updateBeginFromSource();
+ updateUndoRedo();
+ updateCanPaste();
+ } else {
+ m_editors[model].transTexts[0]->getEditor()->setFocus();
+ }
+ }
+}
+
+bool MessageEditor::focusNextUnfinished(int start)
+{
+ for (int j = start; j < m_editors.count(); ++j)
+ if (m_dataModel->isModelWritable(j))
+ if (MessageItem *item = m_dataModel->messageItem(m_currentIndex, j))
+ if (item->type() == TranslatorMessage::Unfinished) {
+ m_editors[j].transTexts[0]->getEditor()->setFocus();
+ return true;
+ }
+ return false;
+}
+
+void MessageEditor::setUnfinishedEditorFocus()
+{
+ focusNextUnfinished(0);
+}
+
+bool MessageEditor::focusNextUnfinished()
+{
+ return focusNextUnfinished(m_currentModel + 1);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/messageeditor.h b/tools/linguist/linguist/messageeditor.h
new file mode 100644
index 0000000000..de563ec4c3
--- /dev/null
+++ b/tools/linguist/linguist/messageeditor.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESSAGEEDITOR_H
+#define MESSAGEEDITOR_H
+
+#include "messagemodel.h"
+
+#include <QtCore/QLocale>
+
+#include <QtGui/QFrame>
+#include <QtGui/QScrollArea>
+
+QT_BEGIN_NAMESPACE
+
+class QBoxLayout;
+class QMainWindow;
+class QTextEdit;
+
+class MessageEditor;
+class FormatTextEdit;
+class FormWidget;
+
+struct MessageEditorData {
+ QWidget *container;
+ FormWidget *transCommentText;
+ QList<FormWidget*> transTexts;
+ QString invariantForm;
+ QString firstForm;
+ float fontSize;
+ bool pluralEditMode;
+};
+
+class MessageEditor : public QScrollArea
+{
+ Q_OBJECT
+
+public:
+ MessageEditor(MultiDataModel *dataModel, QMainWindow *parent = 0);
+
+ void showNothing();
+ void showMessage(const MultiDataIndex &index);
+ void setNumerusForms(int model, const QStringList &numerusForms);
+ bool eventFilter(QObject *, QEvent *);
+ void setTranslation(int model, const QString &translation, int numerus);
+ int activeModel() const { return (m_editors.count() != 1) ? m_currentModel : 0; }
+ void setEditorFocus(int model);
+ void setUnfinishedEditorFocus();
+ bool focusNextUnfinished();
+
+signals:
+ void translationChanged(const QStringList &translations);
+ void translatorCommentChanged(const QString &comment);
+ void activeModelChanged(int model);
+
+ void undoAvailable(bool avail);
+ void redoAvailable(bool avail);
+ void cutAvailable(bool avail);
+ void copyAvailable(bool avail);
+ void pasteAvailable(bool avail);
+ void beginFromSourceAvailable(bool enable);
+
+public slots:
+ void undo();
+ void redo();
+ void cut();
+ void copy();
+ void paste();
+ void selectAll();
+ void beginFromSource();
+ void setEditorFocus();
+ void setTranslation(int latestModel, const QString &translation);
+
+private slots:
+ void selectionChanged();
+ bool resetHoverSelection(FormWidget *fw = 0);
+ void emitTranslationChanged();
+ void emitTranslatorCommentChanged();
+ void updateCanPaste();
+ void clipboardChanged();
+ void messageModelAppended();
+ void messageModelDeleted(int model);
+ void allModelsDeleted();
+ void setTargetLanguage(int model);
+
+private:
+ void setupEditorPage();
+ void setEditingEnabled(int model, bool enabled);
+ bool focusNextUnfinished(int start);
+ bool resetSelection(FormWidget *fw = 0);
+ void activeModelAndNumerus(int *model, int *numerus) const;
+ FormWidget *activeTranslation() const;
+ FormWidget *activeOr1stTranslation() const;
+ FormWidget *activeTransComment() const;
+ FormWidget *activeEditor() const;
+ FormWidget *activeOr1stEditor() const;
+ MessageEditorData *modelForWidget(const QObject *o);
+ int activeTranslationNumerus() const;
+ QStringList translations(int model) const;
+ void updateBeginFromSource();
+ void updateUndoRedo();
+ void updateCanCutCopy();
+ void addPluralForm(int model, const QString &label, bool writable);
+ QPalette paletteForModel(int model) const;
+
+ MultiDataModel *m_dataModel;
+
+ MultiDataIndex m_currentIndex;
+ int m_currentModel;
+ int m_currentNumerus;
+
+ bool m_undoAvail;
+ bool m_redoAvail;
+ bool m_cutAvail;
+ bool m_copyAvail;
+ bool m_sourceSelected;
+ bool m_pluralSourceSelected;
+ bool m_currentSelected;
+
+ bool m_clipboardEmpty;
+
+ QBoxLayout *m_layout;
+ FormWidget *m_source;
+ FormWidget *m_pluralSource;
+ FormWidget *m_commentText;
+ QList<MessageEditorData> m_editors;
+};
+
+QT_END_NAMESPACE
+
+#endif // MESSAGEEDITOR_H
diff --git a/tools/linguist/linguist/messageeditorwidgets.cpp b/tools/linguist/linguist/messageeditorwidgets.cpp
new file mode 100644
index 0000000000..7412571e39
--- /dev/null
+++ b/tools/linguist/linguist/messageeditorwidgets.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "messageeditorwidgets.h"
+#include "messagehighlighter.h"
+
+#include <QAbstractTextDocumentLayout>
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QDebug>
+#include <QLayout>
+#include <QMenu>
+#include <QPainter>
+#include <QScrollArea>
+#include <QTextBlock>
+#include <QTextDocumentFragment>
+#include <QVBoxLayout>
+
+QT_BEGIN_NAMESPACE
+
+ExpandingTextEdit::ExpandingTextEdit(QWidget *parent)
+ : QTextEdit(parent)
+{
+ setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding));
+
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ QAbstractTextDocumentLayout *docLayout = document()->documentLayout();
+ connect(docLayout, SIGNAL(documentSizeChanged(QSizeF)), SLOT(updateHeight(QSizeF)));
+ connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(reallyEnsureCursorVisible()));
+
+ m_minimumHeight = qRound(docLayout->documentSize().height()) + frameWidth() * 2;
+}
+
+void ExpandingTextEdit::updateHeight(const QSizeF &documentSize)
+{
+ m_minimumHeight = qRound(documentSize.height()) + frameWidth() * 2;
+ updateGeometry();
+}
+
+QSize ExpandingTextEdit::sizeHint() const
+{
+ return QSize(100, m_minimumHeight);
+}
+
+QSize ExpandingTextEdit::minimumSizeHint() const
+{
+ return QSize(100, m_minimumHeight);
+}
+
+void ExpandingTextEdit::reallyEnsureCursorVisible()
+{
+ QObject *ancestor = parent();
+ while (ancestor) {
+ QScrollArea *scrollArea = qobject_cast<QScrollArea*>(ancestor);
+ if (scrollArea &&
+ (scrollArea->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff &&
+ scrollArea->horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff)) {
+ const QRect &r = cursorRect();
+ const QPoint &c = mapTo(scrollArea->widget(), r.center());
+ scrollArea->ensureVisible(c.x(), c.y());
+ break;
+ }
+ ancestor = ancestor->parent();
+ }
+}
+
+FormatTextEdit::FormatTextEdit(QWidget *parent)
+ : ExpandingTextEdit(parent)
+{
+ setLineWrapMode(QTextEdit::WidgetWidth);
+ setAcceptRichText(false);
+ QTextOption option = document()->defaultTextOption();
+ option.setFlags(option.flags()
+ | QTextOption::ShowLineAndParagraphSeparators
+ | QTextOption::ShowTabsAndSpaces);
+ document()->setDefaultTextOption(option);
+
+ // Do not set different background if disabled
+ QPalette p = palette();
+ p.setColor(QPalette::Disabled, QPalette::Base, p.color(QPalette::Active, QPalette::Base));
+ setPalette(p);
+
+ setEditable(true);
+
+ m_highlighter = new MessageHighlighter(this);
+}
+
+void FormatTextEdit::setEditable(bool editable)
+{
+ // save default frame style
+ static int framed = frameStyle();
+ static Qt::FocusPolicy defaultFocus = focusPolicy();
+
+ if (editable) {
+ setFrameStyle(framed);
+ setFocusPolicy(defaultFocus);
+ } else {
+ setFrameStyle(QFrame::NoFrame | QFrame::Plain);
+ setFocusPolicy(Qt::NoFocus);
+ }
+
+ setReadOnly(!editable);
+}
+
+void FormatTextEdit::setPlainText(const QString &text, bool userAction)
+{
+ bool oldBlockState = false;
+ if (!userAction) {
+ // Prevent contentsChanged signal
+ oldBlockState = document()->blockSignals(true);
+ document()->setUndoRedoEnabled(false);
+ ExpandingTextEdit::setPlainText(text);
+ // highlighter is out of sync because of blocked signals
+ m_highlighter->rehighlight();
+ document()->setUndoRedoEnabled(true);
+ document()->blockSignals(oldBlockState);
+ } else {
+ ExpandingTextEdit::setPlainText(text);
+ }
+}
+
+FormWidget::FormWidget(const QString &label, bool isEditable, QWidget *parent)
+ : QWidget(parent),
+ m_hideWhenEmpty(false)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+
+ m_label = new QLabel(this);
+ m_label->setText(label);
+ layout->addWidget(m_label);
+
+ m_editor = new FormatTextEdit(this);
+ m_editor->setEditable(isEditable);
+ //m_textEdit->setWhatsThis(tr("This area shows text from an auxillary translation."));
+ layout->addWidget(m_editor);
+
+ setLayout(layout);
+
+ connect(m_editor->document(), SIGNAL(contentsChanged()), SIGNAL(textChanged()));
+ connect(m_editor, SIGNAL(selectionChanged()), SIGNAL(selectionChanged()));
+ connect(m_editor, SIGNAL(cursorPositionChanged()), SIGNAL(cursorPositionChanged()));
+}
+
+void FormWidget::setTranslation(const QString &text, bool userAction)
+{
+ m_editor->setPlainText(text, userAction);
+ if (m_hideWhenEmpty)
+ setHidden(text.isEmpty());
+}
+
+void FormWidget::setEditingEnabled(bool enable)
+{
+ // Use read-only state so that the text can still be copied
+ m_editor->setReadOnly(!enable);
+ m_label->setEnabled(enable);
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/messageeditorwidgets.h b/tools/linguist/linguist/messageeditorwidgets.h
new file mode 100644
index 0000000000..b1609e5648
--- /dev/null
+++ b/tools/linguist/linguist/messageeditorwidgets.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESSAGEEDITORWIDGETS_H
+#define MESSAGEEDITORWIDGETS_H
+
+#include <QImage>
+#include <QLabel>
+#include <QMap>
+#include <QTextEdit>
+#include <QUrl>
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QAction;
+class QContextMenuEvent;
+class QKeyEvent;
+class QMenu;
+class QSizeF;
+class QString;
+class QVariant;
+
+class MessageHighlighter;
+
+/*
+ Automatically adapt height to document contents
+ */
+class ExpandingTextEdit : public QTextEdit
+{
+ Q_OBJECT
+
+public:
+ ExpandingTextEdit(QWidget *parent = 0);
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+private slots:
+ void updateHeight(const QSizeF &documentSize);
+ void reallyEnsureCursorVisible();
+
+private:
+ int m_minimumHeight;
+};
+
+/*
+ Format markup & control characters
+*/
+class FormatTextEdit : public ExpandingTextEdit
+{
+ Q_OBJECT
+public:
+ FormatTextEdit(QWidget *parent = 0);
+ void setEditable(bool editable);
+
+public slots:
+ void setPlainText(const QString & text, bool userAction);
+
+private:
+ MessageHighlighter *m_highlighter;
+};
+
+/*
+ Displays text field & associated label
+*/
+class FormWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ FormWidget(const QString &label, bool isEditable, QWidget *parent = 0);
+ void setLabel(const QString &label) { m_label->setText(label); }
+ void setTranslation(const QString &text, bool userAction = false);
+ void clearTranslation() { setTranslation(QString(), false); }
+ QString getTranslation() { return m_editor->toPlainText(); }
+ void setEditingEnabled(bool enable);
+ void setHideWhenEmpty(bool optional) { m_hideWhenEmpty = optional; }
+ FormatTextEdit *getEditor() { return m_editor; }
+
+signals:
+ void textChanged();
+ void selectionChanged();
+ void cursorPositionChanged();
+
+private:
+ QLabel *m_label;
+ FormatTextEdit *m_editor;
+ bool m_hideWhenEmpty;
+};
+
+QT_END_NAMESPACE
+
+#endif // MESSAGEEDITORWIDGETS_H
diff --git a/tools/linguist/linguist/messagehighlighter.cpp b/tools/linguist/linguist/messagehighlighter.cpp
new file mode 100644
index 0000000000..4965582649
--- /dev/null
+++ b/tools/linguist/linguist/messagehighlighter.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "messagehighlighter.h"
+
+#include <QtCore/QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+MessageHighlighter::MessageHighlighter(QTextEdit *textEdit)
+ : QSyntaxHighlighter(textEdit)
+{
+ QTextCharFormat entityFormat;
+ entityFormat.setForeground(Qt::red);
+ m_formats[Entity] = entityFormat;
+
+ QTextCharFormat tagFormat;
+ tagFormat.setForeground(Qt::darkMagenta);
+ m_formats[Tag] = tagFormat;
+
+ QTextCharFormat commentFormat;
+ commentFormat.setForeground(Qt::gray);
+ commentFormat.setFontItalic(true);
+ m_formats[Comment] = commentFormat;
+
+ QTextCharFormat attributeFormat;
+ attributeFormat.setForeground(Qt::black);
+ attributeFormat.setFontItalic(true);
+ m_formats[Attribute] = attributeFormat;
+
+ QTextCharFormat valueFormat;
+ valueFormat.setForeground(Qt::blue);
+ m_formats[Value] = valueFormat;
+
+ QTextCharFormat acceleratorFormat;
+ acceleratorFormat.setFontUnderline(true);
+ m_formats[Accelerator] = acceleratorFormat;
+
+ QTextCharFormat variableFormat;
+ variableFormat.setForeground(Qt::blue);
+ m_formats[Variable] = variableFormat;
+
+ rehighlight();
+}
+
+void MessageHighlighter::highlightBlock(const QString &text)
+{
+ static const QLatin1Char tab = QLatin1Char('\t');
+ static const QLatin1Char space = QLatin1Char(' ');
+ static const QLatin1Char amp = QLatin1Char('&');
+ static const QLatin1Char endTag = QLatin1Char('>');
+ static const QLatin1Char quot = QLatin1Char('"');
+ static const QLatin1Char apos = QLatin1Char('\'');
+ static const QLatin1Char semicolon = QLatin1Char(';');
+ static const QLatin1Char equals = QLatin1Char('=');
+ static const QLatin1Char percent = QLatin1Char('%');
+ static const QLatin1String startComment = QLatin1String("<!--");
+ static const QLatin1String endComment = QLatin1String("-->");
+ static const QLatin1String endElement = QLatin1String("/>");
+
+ int state = previousBlockState();
+ int len = text.length();
+ int start = 0;
+ int pos = 0;
+
+ while (pos < len) {
+ switch (state) {
+ case NormalState:
+ default:
+ while (pos < len) {
+ QChar ch = text.at(pos);
+ if (ch == QLatin1Char('<')) {
+ if (text.mid(pos, 4) == startComment) {
+ state = InComment;
+ } else {
+ state = InTag;
+ start = pos;
+ while (pos < len && text.at(pos) != space
+ && text.at(pos) != endTag
+ && text.at(pos) != tab
+ && text.mid(pos, 2) != endElement)
+ ++pos;
+ if (text.mid(pos, 2) == endElement)
+ ++pos;
+ setFormat(start, pos - start,
+ m_formats[Tag]);
+ break;
+ }
+ break;
+ } else if (ch == amp && pos + 1 < len) {
+ // Default is Accelerator
+ if (text.at(pos + 1).isLetterOrNumber())
+ setFormat(pos + 1, 1, m_formats[Accelerator]);
+
+ // When a semicolon follows assume an Entity
+ start = pos;
+ ch = text.at(++pos);
+ while (pos + 1 < len && ch != semicolon && ch.isLetterOrNumber())
+ ch = text.at(++pos);
+ if (ch == semicolon)
+ setFormat(start, pos - start + 1, m_formats[Entity]);
+ } else if (ch == percent) {
+ start = pos;
+ // %[1-9]*
+ for (++pos; pos < len && text.at(pos).isDigit(); ++pos) {}
+ // %n
+ if (pos < len && pos == start + 1 && text.at(pos) == QLatin1Char('n'))
+ ++pos;
+ setFormat(start, pos - start, m_formats[Variable]);
+ } else {
+ // No tag, comment or entity started, continue...
+ ++pos;
+ }
+ }
+ break;
+ case InComment:
+ start = pos;
+ while (pos < len) {
+ if (text.mid(pos, 3) == endComment) {
+ pos += 3;
+ state = NormalState;
+ break;
+ } else {
+ ++pos;
+ }
+ }
+ setFormat(start, pos - start, m_formats[Comment]);
+ break;
+ case InTag:
+ QChar quote = QChar::Null;
+ while (pos < len) {
+ QChar ch = text.at(pos);
+ if (quote.isNull()) {
+ start = pos;
+ if (ch == apos || ch == quot) {
+ quote = ch;
+ } else if (ch == endTag) {
+ ++pos;
+ setFormat(start, pos - start, m_formats[Tag]);
+ state = NormalState;
+ break;
+ } else if (text.mid(pos, 2) == endElement) {
+ pos += 2;
+ setFormat(start, pos - start, m_formats[Tag]);
+ state = NormalState;
+ break;
+ } else if (ch != space && text.at(pos) != tab) {
+ // Tag not ending, not a quote and no whitespace, so
+ // we must be dealing with an attribute.
+ ++pos;
+ while (pos < len && text.at(pos) != space
+ && text.at(pos) != tab
+ && text.at(pos) != equals)
+ ++pos;
+ setFormat(start, pos - start, m_formats[Attribute]);
+ start = pos;
+ }
+ } else if (ch == quote) {
+ quote = QChar::Null;
+
+ // Anything quoted is a value
+ setFormat(start, pos - start, m_formats[Value]);
+ }
+ ++pos;
+ }
+ break;
+ }
+ }
+ setCurrentBlockState(state);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/messagehighlighter.h b/tools/linguist/linguist/messagehighlighter.h
new file mode 100644
index 0000000000..0fd061b322
--- /dev/null
+++ b/tools/linguist/linguist/messagehighlighter.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESSAGEHIGHLIGHTER_H
+#define MESSAGEHIGHLIGHTER_H
+
+#include <QtGui/QSyntaxHighlighter>
+
+QT_BEGIN_NAMESPACE
+
+/* Message highlighter based on HtmlSyntaxHighlighter from designer */
+class MessageHighlighter : public QSyntaxHighlighter
+{
+ Q_OBJECT
+
+public:
+ MessageHighlighter(QTextEdit *textEdit);
+
+protected:
+ void highlightBlock(const QString &text);
+
+private:
+ enum Construct {
+ Entity,
+ Tag,
+ Comment,
+ Attribute,
+ Value,
+ Accelerator, // "Open &File"
+ Variable, // "Opening %1"
+ LastConstruct = Variable
+ };
+
+ enum State {
+ NormalState = -1,
+ InComment,
+ InTag
+ };
+
+ QTextCharFormat m_formats[LastConstruct + 1];
+};
+
+QT_END_NAMESPACE
+
+#endif // MESSAGEHIGHLIGHTER_H
diff --git a/tools/linguist/linguist/messagemodel.cpp b/tools/linguist/linguist/messagemodel.cpp
new file mode 100644
index 0000000000..a7053cf911
--- /dev/null
+++ b/tools/linguist/linguist/messagemodel.cpp
@@ -0,0 +1,1403 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "messagemodel.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QTextCodec>
+
+#include <QtGui/QMessageBox>
+#include <QtGui/QPainter>
+#include <QtGui/QPixmap>
+#include <QtGui/QTextDocument>
+
+#include <private/qtranslator_p.h>
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+/******************************************************************************
+ *
+ * MessageItem
+ *
+ *****************************************************************************/
+
+MessageItem::MessageItem(const TranslatorMessage &message)
+ : m_message(message),
+ m_danger(false)
+{
+ if (m_message.translation().isEmpty())
+ m_message.setTranslation(QString());
+}
+
+
+bool MessageItem::compare(const QString &findText, bool matchSubstring,
+ Qt::CaseSensitivity cs) const
+{
+ return matchSubstring
+ ? text().indexOf(findText, 0, cs) >= 0
+ : text().compare(findText, cs) == 0;
+}
+
+/******************************************************************************
+ *
+ * ContextItem
+ *
+ *****************************************************************************/
+
+ContextItem::ContextItem(const QString &context)
+ : m_context(context),
+ m_finishedCount(0),
+ m_finishedDangerCount(0),
+ m_unfinishedDangerCount(0),
+ m_nonobsoleteCount(0)
+{}
+
+void ContextItem::appendToComment(const QString &str)
+{
+ if (!m_comment.isEmpty())
+ m_comment += QLatin1String("\n\n");
+ m_comment += str;
+}
+
+MessageItem *ContextItem::messageItem(int i) const
+{
+ if (i >= 0 && i < msgItemList.count())
+ return const_cast<MessageItem *>(&msgItemList[i]);
+ Q_ASSERT(i >= 0 && i < msgItemList.count());
+ return 0;
+}
+
+MessageItem *ContextItem::findMessage(const QString &sourcetext, const QString &comment) const
+{
+ for (int i = 0; i < messageCount(); ++i) {
+ MessageItem *mi = messageItem(i);
+ if (mi->text() == sourcetext && mi->comment() == comment)
+ return mi;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ *
+ * DataModel
+ *
+ *****************************************************************************/
+
+DataModel::DataModel(QObject *parent)
+ : QObject(parent),
+ m_modified(false),
+ m_numMessages(0),
+ m_srcWords(0),
+ m_srcChars(0),
+ m_srcCharsSpc(0),
+ m_language(QLocale::Language(-1)),
+ m_sourceLanguage(QLocale::Language(-1)),
+ m_country(QLocale::Country(-1)),
+ m_sourceCountry(QLocale::Country(-1))
+{}
+
+QStringList DataModel::normalizedTranslations(const MessageItem &m) const
+{
+ return Translator::normalizedTranslations(m.message(), m_language, m_country);
+}
+
+ContextItem *DataModel::contextItem(int context) const
+{
+ if (context >= 0 && context < m_contextList.count())
+ return const_cast<ContextItem *>(&m_contextList[context]);
+ Q_ASSERT(context >= 0 && context < m_contextList.count());
+ return 0;
+}
+
+MessageItem *DataModel::messageItem(const DataIndex &index) const
+{
+ if (ContextItem *c = contextItem(index.context()))
+ return c->messageItem(index.message());
+ return 0;
+}
+
+ContextItem *DataModel::findContext(const QString &context) const
+{
+ for (int c = 0; c < m_contextList.count(); ++c) {
+ ContextItem *ctx = contextItem(c);
+ if (ctx->context() == context)
+ return ctx;
+ }
+ return 0;
+}
+
+MessageItem *DataModel::findMessage(const QString &context,
+ const QString &sourcetext, const QString &comment) const
+{
+ if (ContextItem *ctx = findContext(context))
+ return ctx->findMessage(sourcetext, comment);
+ return 0;
+}
+
+static int calcMergeScore(const DataModel *one, const DataModel *two)
+{
+ int inBoth = 0;
+ for (int i = 0; i < two->contextCount(); ++i) {
+ ContextItem *oc = two->contextItem(i);
+ if (ContextItem *c = one->findContext(oc->context())) {
+ for (int j = 0; j < oc->messageCount(); ++j) {
+ MessageItem *m = oc->messageItem(j);
+ if (c->findMessage(m->text(), m->comment()) >= 0)
+ ++inBoth;
+ }
+ }
+ }
+ return inBoth * 100 / two->messageCount();
+}
+
+bool DataModel::isWellMergeable(const DataModel *other) const
+{
+ if (!other->messageCount() || !messageCount())
+ return true;
+
+ return calcMergeScore(this, other) + calcMergeScore(other, this) > 90;
+}
+
+bool DataModel::load(const QString &fileName, bool *langGuessed, QWidget *parent)
+{
+ Translator tor;
+ ConversionData cd;
+ bool ok = tor.load(fileName, cd, QLatin1String("auto"));
+ if (!ok) {
+ QMessageBox::warning(parent, QObject::tr("Qt Linguist"), cd.error());
+ return false;
+ }
+
+ QList<TranslatorMessage> dupes = tor.findDuplicates();
+ if (!dupes.isEmpty()) {
+ QString err = tr("<qt>Duplicate messages found in '%1':").arg(Qt::escape(fileName));
+ int numdups = 0;
+ foreach (const TranslatorMessage &msg, dupes) {
+ if (++numdups >= 5) {
+ err += tr("<p>[more duplicates omitted]");
+ break;
+ }
+ err += tr("<p>* Context: %1<br>* Source: %2")
+ .arg(Qt::escape(msg.context()), Qt::escape(msg.sourceText()));
+ if (!msg.comment().isEmpty())
+ err += tr("<br>* Comment: %3").arg(Qt::escape(msg.comment()));
+ }
+ QMessageBox::warning(parent, QObject::tr("Qt Linguist"), err);
+ }
+
+ m_srcFileName = fileName;
+ m_codecName = tor.codecName();
+ m_relativeLocations = (tor.locationsType() == Translator::RelativeLocations);
+ m_extra = tor.extras();
+ m_contextList.clear();
+ m_numMessages = 0;
+
+ QHash<QString, int> contexts;
+
+ m_srcWords = 0;
+ m_srcChars = 0;
+ m_srcCharsSpc = 0;
+
+ foreach (const TranslatorMessage &msg, tor.messages()) {
+ if (!contexts.contains(msg.context())) {
+ contexts.insert(msg.context(), m_contextList.size());
+ m_contextList.append(ContextItem(msg.context()));
+ }
+
+ ContextItem *c = contextItem(contexts.value(msg.context()));
+ if (msg.sourceText() == QLatin1String(ContextComment)) {
+ c->appendToComment(msg.comment());
+ } else {
+ MessageItem tmp(msg);
+ if (msg.type() == TranslatorMessage::Finished)
+ c->incrementFinishedCount();
+ if (msg.type() != TranslatorMessage::Obsolete) {
+ doCharCounting(tmp.text(), m_srcWords, m_srcChars, m_srcCharsSpc);
+ doCharCounting(tmp.pluralText(), m_srcWords, m_srcChars, m_srcCharsSpc);
+ c->incrementNonobsoleteCount();
+ }
+ c->appendMessage(tmp);
+ ++m_numMessages;
+ }
+ }
+
+ // Try to detect the correct language in the following order
+ // 1. Look for the language attribute in the ts
+ // if that fails
+ // 2. Guestimate the language from the filename
+ // (expecting the qt_{en,de}.ts convention)
+ // if that fails
+ // 3. Retrieve the locale from the system.
+ *langGuessed = false;
+ QString lang = tor.languageCode();
+ if (lang.isEmpty()) {
+ lang = QFileInfo(fileName).baseName();
+ int pos = lang.indexOf(QLatin1Char('_'));
+ if (pos != -1 && pos + 3 == lang.length())
+ lang = fileName.mid(pos + 1);
+ else
+ lang.clear();
+ *langGuessed = true;
+ }
+ QLocale::Language l;
+ QLocale::Country c;
+ Translator::languageAndCountry(lang, &l, &c);
+ if (l == QLocale::C) {
+ QLocale sys;
+ l = sys.language();
+ c = sys.country();
+ *langGuessed = true;
+ }
+ if (!setLanguageAndCountry(l, c))
+ QMessageBox::warning(parent, QObject::tr("Qt Linguist"),
+ tr("Linguist does not know the plural rules for '%1'.\n"
+ "Will assume a single universal form.")
+ .arg(m_localizedLanguage));
+ // Try to detect the correct source language in the following order
+ // 1. Look for the language attribute in the ts
+ // if that fails
+ // 2. Assume English
+ lang = tor.sourceLanguageCode();
+ if (lang.isEmpty()) {
+ l = QLocale::C;
+ c = QLocale::AnyCountry;
+ } else {
+ Translator::languageAndCountry(lang, &l, &c);
+ }
+ setSourceLanguageAndCountry(l, c);
+
+ setModified(false);
+
+ return true;
+}
+
+bool DataModel::save(const QString &fileName, QWidget *parent)
+{
+ Translator tor;
+ for (DataModelIterator it(this); it.isValid(); ++it)
+ tor.append(it.current()->message());
+
+ tor.setLanguageCode(Translator::makeLanguageCode(m_language, m_country));
+ tor.setSourceLanguageCode(Translator::makeLanguageCode(m_sourceLanguage, m_sourceCountry));
+ tor.setCodecName(m_codecName);
+ tor.setLocationsType(m_relativeLocations ? Translator::RelativeLocations
+ : Translator::AbsoluteLocations);
+ tor.setExtras(m_extra);
+ ConversionData cd;
+ bool ok = tor.save(fileName, cd, QLatin1String("auto"));
+ if (ok)
+ setModified(false);
+ else
+ QMessageBox::warning(parent, QObject::tr("Qt Linguist"), cd.error());
+ return ok;
+}
+
+bool DataModel::saveAs(const QString &newFileName, QWidget *parent)
+{
+ if (!save(newFileName, parent))
+ return false;
+ m_srcFileName = newFileName;
+ return true;
+}
+
+bool DataModel::release(const QString &fileName, bool verbose, bool ignoreUnfinished,
+ TranslatorSaveMode mode, QWidget *parent)
+{
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox::warning(parent, QObject::tr("Qt Linguist"),
+ tr("Cannot create '%2': %1").arg(file.errorString()).arg(fileName));
+ return false;
+ }
+ Translator tor;
+ QLocale locale(m_language, m_country);
+ tor.setLanguageCode(locale.name());
+ for (DataModelIterator it(this); it.isValid(); ++it)
+ tor.append(it.current()->message());
+ ConversionData cd;
+ cd.m_verbose = verbose;
+ cd.m_ignoreUnfinished = ignoreUnfinished;
+ cd.m_saveMode = mode;
+ bool ok = tor.release(&file, cd);
+ if (!ok)
+ QMessageBox::warning(parent, QObject::tr("Qt Linguist"), cd.error());
+ return ok;
+}
+
+void DataModel::doCharCounting(const QString &text, int &trW, int &trC, int &trCS)
+{
+ trCS += text.length();
+ bool inWord = false;
+ for (int i = 0; i < text.length(); ++i) {
+ if (text[i].isLetterOrNumber() || text[i] == QLatin1Char('_')) {
+ if (!inWord) {
+ ++trW;
+ inWord = true;
+ }
+ } else {
+ inWord = false;
+ }
+ if (!text[i].isSpace())
+ trC++;
+ }
+}
+
+bool DataModel::setLanguageAndCountry(QLocale::Language lang, QLocale::Country country)
+{
+ if (m_language == lang && m_country == country)
+ return true;
+ m_language = lang;
+ m_country = country;
+
+ if (lang == QLocale::C || uint(lang) > uint(QLocale::LastLanguage)) // XXX does this make any sense?
+ lang = QLocale::English;
+ QByteArray rules;
+ bool ok = getNumerusInfo(lang, country, &rules, &m_numerusForms);
+ m_localizedLanguage = QCoreApplication::translate("MessageEditor", QLocale::languageToString(lang).toAscii());
+ m_countRefNeeds.clear();
+ for (int i = 0; i < rules.size(); ++i) {
+ m_countRefNeeds.append(!(rules.at(i) == Q_EQ && (i == (rules.size() - 2) || rules.at(i + 2) == (char)Q_NEWRULE)));
+ while (++i < rules.size() && rules.at(i) != (char)Q_NEWRULE) {}
+ }
+ m_countRefNeeds.append(true);
+ if (!ok) {
+ m_numerusForms.clear();
+ m_numerusForms << tr("Universal Form");
+ }
+ emit languageChanged();
+ setModified(true);
+ return ok;
+}
+
+void DataModel::setSourceLanguageAndCountry(QLocale::Language lang, QLocale::Country country)
+{
+ if (m_sourceLanguage == lang && m_sourceCountry == country)
+ return;
+ m_sourceLanguage = lang;
+ m_sourceCountry = country;
+ setModified(true);
+}
+
+void DataModel::updateStatistics()
+{
+ int trW = 0;
+ int trC = 0;
+ int trCS = 0;
+
+ for (DataModelIterator it(this); it.isValid(); ++it) {
+ const MessageItem *mi = it.current();
+ if (mi->isFinished())
+ foreach (const QString &trnsl, mi->translations())
+ doCharCounting(trnsl, trW, trC, trCS);
+ }
+
+ emit statsChanged(m_srcWords, m_srcChars, m_srcCharsSpc, trW, trC, trCS);
+}
+
+void DataModel::setModified(bool isModified)
+{
+ if (m_modified == isModified)
+ return;
+ m_modified = isModified;
+ emit modifiedChanged();
+}
+
+QString DataModel::prettifyPlainFileName(const QString &fn)
+{
+ static QString workdir = QDir::currentPath() + QLatin1Char('/');
+
+ return QDir::toNativeSeparators(fn.startsWith(workdir) ? fn.mid(workdir.length()) : fn);
+}
+
+QString DataModel::prettifyFileName(const QString &fn)
+{
+ if (fn.startsWith(QLatin1Char('=')))
+ return QLatin1Char('=') + prettifyPlainFileName(fn.mid(1));
+ else
+ return prettifyPlainFileName(fn);
+}
+
+/******************************************************************************
+ *
+ * DataModelIterator
+ *
+ *****************************************************************************/
+
+DataModelIterator::DataModelIterator(DataModel *model, int context, int message)
+ : DataIndex(context, message), m_model(model)
+{
+}
+
+bool DataModelIterator::isValid() const
+{
+ return m_context < m_model->m_contextList.count();
+}
+
+void DataModelIterator::operator++()
+{
+ ++m_message;
+ if (m_message >= m_model->m_contextList.at(m_context).messageCount()) {
+ ++m_context;
+ m_message = 0;
+ }
+}
+
+MessageItem *DataModelIterator::current() const
+{
+ return m_model->messageItem(*this);
+}
+
+
+/******************************************************************************
+ *
+ * MultiMessageItem
+ *
+ *****************************************************************************/
+
+MultiMessageItem::MultiMessageItem(const MessageItem *m)
+ : m_text(m->text()),
+ m_pluralText(m->pluralText()),
+ m_comment(m->comment()),
+ m_nonnullCount(0),
+ m_nonobsoleteCount(0),
+ m_editableCount(0),
+ m_unfinishedCount(0)
+{
+}
+
+/******************************************************************************
+ *
+ * MultiContextItem
+ *
+ *****************************************************************************/
+
+MultiContextItem::MultiContextItem(int oldCount, ContextItem *ctx, bool writable)
+ : m_context(ctx->context()),
+ m_comment(ctx->comment()),
+ m_finishedCount(0),
+ m_editableCount(0),
+ m_nonobsoleteCount(0)
+{
+ QList<MessageItem *> mList;
+ QList<MessageItem *> eList;
+ for (int j = 0; j < ctx->messageCount(); ++j) {
+ MessageItem *m = ctx->messageItem(j);
+ mList.append(m);
+ eList.append(0);
+ m_multiMessageList.append(MultiMessageItem(m));
+ }
+ for (int i = 0; i < oldCount; ++i) {
+ m_messageLists.append(eList);
+ m_writableMessageLists.append(0);
+ m_contextList.append(0);
+ }
+ m_messageLists.append(mList);
+ m_writableMessageLists.append(writable ? &m_messageLists.last() : 0);
+ m_contextList.append(ctx);
+}
+
+void MultiContextItem::appendEmptyModel()
+{
+ QList<MessageItem *> eList;
+ for (int j = 0; j < messageCount(); ++j)
+ eList.append(0);
+ m_messageLists.append(eList);
+ m_writableMessageLists.append(0);
+ m_contextList.append(0);
+}
+
+void MultiContextItem::assignLastModel(ContextItem *ctx, bool writable)
+{
+ if (writable)
+ m_writableMessageLists.last() = &m_messageLists.last();
+ m_contextList.last() = ctx;
+}
+
+// XXX this is not needed, yet
+void MultiContextItem::moveModel(int oldPos, int newPos)
+{
+ m_contextList.insert(newPos, m_contextList[oldPos]);
+ m_messageLists.insert(newPos, m_messageLists[oldPos]);
+ m_writableMessageLists.insert(newPos, m_writableMessageLists[oldPos]);
+ removeModel(oldPos < newPos ? oldPos : oldPos + 1);
+}
+
+void MultiContextItem::removeModel(int pos)
+{
+ m_contextList.removeAt(pos);
+ m_messageLists.removeAt(pos);
+ m_writableMessageLists.removeAt(pos);
+}
+
+void MultiContextItem::putMessageItem(int pos, MessageItem *m)
+{
+ m_messageLists.last()[pos] = m;
+}
+
+void MultiContextItem::appendMessageItem(MessageItem *m)
+{
+ for (int i = 0; i < m_messageLists.count() - 1; ++i)
+ m_messageLists[i].append(0);
+ m_messageLists.last().append(m);
+ m_multiMessageList.append(MultiMessageItem(m));
+}
+
+void MultiContextItem::removeMultiMessageItem(int pos)
+{
+ for (int i = 0; i < m_messageLists.count(); ++i)
+ m_messageLists[i].removeAt(pos);
+ m_multiMessageList.removeAt(pos);
+}
+
+int MultiContextItem::firstNonobsoleteMessageIndex(int msgIdx) const
+{
+ for (int i = 0; i < m_messageLists.size(); ++i)
+ if (m_messageLists[i][msgIdx] && !m_messageLists[i][msgIdx]->isObsolete())
+ return i;
+ return -1;
+}
+
+int MultiContextItem::findMessage(const QString &sourcetext, const QString &comment) const
+{
+ for (int i = 0, cnt = messageCount(); i < cnt; ++i) {
+ MultiMessageItem *m = multiMessageItem(i);
+ if (m->text() == sourcetext && m->comment() == comment)
+ return i;
+ }
+ return -1;
+}
+
+/******************************************************************************
+ *
+ * MultiDataModel
+ *
+ *****************************************************************************/
+
+static const uchar paletteRGBs[7][3] = {
+ { 236, 244, 255 }, // blue
+ { 236, 255, 255 }, // cyan
+ { 236, 255, 232 }, // green
+ { 255, 255, 230 }, // yellow
+ { 255, 242, 222 }, // orange
+ { 255, 236, 236 }, // red
+ { 252, 236, 255 } // purple
+};
+
+MultiDataModel::MultiDataModel(QObject *parent) :
+ QObject(parent),
+ m_numFinished(0),
+ m_numEditable(0),
+ m_numMessages(0),
+ m_modified(false)
+{
+ for (int i = 0; i < 7; ++i)
+ m_colors[i] = QColor(paletteRGBs[i][0], paletteRGBs[i][1], paletteRGBs[i][2]);
+
+ m_bitmap = QBitmap(8, 8);
+ m_bitmap.clear();
+ QPainter p(&m_bitmap);
+ for (int j = 0; j < 8; ++j)
+ for (int k = 0; k < 8; ++k)
+ if ((j + k) & 4)
+ p.drawPoint(j, k);
+}
+
+MultiDataModel::~MultiDataModel()
+{
+ qDeleteAll(m_dataModels);
+}
+
+QBrush MultiDataModel::brushForModel(int model) const
+{
+ QBrush brush(m_colors[model % 7]);
+ if (!isModelWritable(model))
+ brush.setTexture(m_bitmap);
+ return brush;
+}
+
+bool MultiDataModel::isWellMergeable(const DataModel *dm) const
+{
+ if (!dm->messageCount() || !messageCount())
+ return true;
+
+ int inBothNew = 0;
+ for (int i = 0; i < dm->contextCount(); ++i) {
+ ContextItem *c = dm->contextItem(i);
+ if (MultiContextItem *mc = findContext(c->context())) {
+ for (int j = 0; j < c->messageCount(); ++j) {
+ MessageItem *m = c->messageItem(j);
+ if (mc->findMessage(m->text(), m->comment()) >= 0)
+ ++inBothNew;
+ }
+ }
+ }
+ int newRatio = inBothNew * 100 / dm->messageCount();
+
+ int inBothOld = 0;
+ for (int k = 0; k < contextCount(); ++k) {
+ MultiContextItem *mc = multiContextItem(k);
+ if (ContextItem *c = dm->findContext(mc->context())) {
+ for (int j = 0; j < mc->messageCount(); ++j) {
+ MultiMessageItem *m = mc->multiMessageItem(j);
+ if (c->findMessage(m->text(), m->comment()))
+ ++inBothOld;
+ }
+ }
+ }
+ int oldRatio = inBothOld * 100 / messageCount();
+
+ return newRatio + oldRatio > 90;
+}
+
+void MultiDataModel::append(DataModel *dm, bool readWrite)
+{
+ int insCol = modelCount() + 1;
+ m_msgModel->beginInsertColumns(QModelIndex(), insCol, insCol);
+ m_dataModels.append(dm);
+ for (int j = 0; j < contextCount(); ++j) {
+ m_msgModel->beginInsertColumns(m_msgModel->createIndex(j, 0, 0), insCol, insCol);
+ m_multiContextList[j].appendEmptyModel();
+ m_msgModel->endInsertColumns();
+ }
+ m_msgModel->endInsertColumns();
+ for (int i = 0; i < dm->contextCount(); ++i) {
+ ContextItem *c = dm->contextItem(i);
+ int mcx = findContextIndex(c->context());
+ if (mcx >= 0) {
+ MultiContextItem *mc = multiContextItem(mcx);
+ mc->assignLastModel(c, readWrite);
+ for (int j = 0; j < c->messageCount(); ++j) {
+ MessageItem *m = c->messageItem(j);
+ int msgIdx = mc->findMessage(m->text(), m->comment());
+ if (msgIdx >= 0) {
+ mc->putMessageItem(msgIdx, m);
+ } else {
+ int msgCnt = mc->messageCount();
+ m_msgModel->beginInsertRows(m_msgModel->createIndex(mcx, 0, 0), msgCnt, msgCnt);
+ mc->appendMessageItem(m);
+ m_msgModel->endInsertRows();
+ ++m_numMessages;
+ }
+ }
+ } else {
+ MultiContextItem item(modelCount() - 1, c, readWrite);
+ m_msgModel->beginInsertRows(QModelIndex(), contextCount(), contextCount());
+ m_multiContextList.append(item);
+ m_msgModel->endInsertRows();
+ m_numMessages += item.messageCount();
+ }
+ }
+ dm->setWritable(readWrite);
+ updateCountsOnAdd(modelCount() - 1, readWrite);
+ connect(dm, SIGNAL(modifiedChanged()), SLOT(onModifiedChanged()));
+ connect(dm, SIGNAL(languageChanged()), SLOT(onLanguageChanged()));
+ connect(dm, SIGNAL(statsChanged(int,int,int,int,int,int)), SIGNAL(statsChanged(int,int,int,int,int,int)));
+ emit modelAppended();
+}
+
+void MultiDataModel::close(int model)
+{
+ if (m_dataModels.count() == 1) {
+ closeAll();
+ } else {
+ updateCountsOnRemove(model, isModelWritable(model));
+ int delCol = model + 1;
+ m_msgModel->beginRemoveColumns(QModelIndex(), delCol, delCol);
+ for (int i = m_multiContextList.size(); --i >= 0;) {
+ m_msgModel->beginRemoveColumns(m_msgModel->createIndex(i, 0, 0), delCol, delCol);
+ m_multiContextList[i].removeModel(model);
+ m_msgModel->endRemoveColumns();
+ }
+ delete m_dataModels.takeAt(model);
+ m_msgModel->endRemoveColumns();
+ emit modelDeleted(model);
+ for (int i = m_multiContextList.size(); --i >= 0;) {
+ MultiContextItem &mc = m_multiContextList[i];
+ QModelIndex contextIdx = m_msgModel->createIndex(i, 0, 0);
+ for (int j = mc.messageCount(); --j >= 0;)
+ if (mc.multiMessageItem(j)->isEmpty()) {
+ m_msgModel->beginRemoveRows(contextIdx, j, j);
+ mc.removeMultiMessageItem(j);
+ m_msgModel->endRemoveRows();
+ --m_numMessages;
+ }
+ if (!mc.messageCount()) {
+ m_msgModel->beginRemoveRows(QModelIndex(), i, i);
+ m_multiContextList.removeAt(i);
+ m_msgModel->endRemoveRows();
+ }
+ }
+ onModifiedChanged();
+ }
+}
+
+void MultiDataModel::closeAll()
+{
+ m_numFinished = 0;
+ m_numEditable = 0;
+ m_numMessages = 0;
+ int delCol = m_dataModels.count();
+ m_msgModel->beginRemoveColumns(QModelIndex(), 1, delCol);
+ for (int i = m_multiContextList.size(); --i >= 0;) {
+ m_msgModel->beginRemoveColumns(m_msgModel->createIndex(i, 0, 0), 1, delCol);
+ m_msgModel->endRemoveColumns();
+ }
+ qDeleteAll(m_dataModels);
+ m_dataModels.clear();
+ m_multiContextList.clear();
+ m_msgModel->endRemoveColumns();
+ m_msgModel->reset();
+ emit allModelsDeleted();
+ onModifiedChanged();
+}
+
+// XXX this is not needed, yet
+void MultiDataModel::moveModel(int oldPos, int newPos)
+{
+ int delPos = oldPos < newPos ? oldPos : oldPos + 1;
+ m_dataModels.insert(newPos, m_dataModels[oldPos]);
+ m_dataModels.removeAt(delPos);
+ for (int i = 0; i < m_multiContextList.size(); ++i)
+ m_multiContextList[i].moveModel(oldPos, newPos);
+}
+
+QStringList MultiDataModel::prettifyFileNames(const QStringList &names)
+{
+ QStringList out;
+
+ foreach (const QString &name, names)
+ out << DataModel::prettifyFileName(name);
+ return out;
+}
+
+QString MultiDataModel::condenseFileNames(const QStringList &names)
+{
+ if (names.isEmpty())
+ return QString();
+
+ if (names.count() < 2)
+ return names.first();
+
+ QString prefix = names.first();
+ if (prefix.startsWith(QLatin1Char('=')))
+ prefix.remove(0, 1);
+ QString suffix = prefix;
+ for (int i = 1; i < names.count(); ++i) {
+ QString fn = names[i];
+ if (fn.startsWith(QLatin1Char('=')))
+ fn.remove(0, 1);
+ for (int j = 0; j < prefix.length(); ++j)
+ if (fn[j] != prefix[j]) {
+ if (j < prefix.length()) {
+ while (j > 0 && prefix[j - 1].isLetterOrNumber())
+ --j;
+ prefix.truncate(j);
+ }
+ break;
+ }
+ int fnl = fn.length() - 1;
+ int sxl = suffix.length() - 1;
+ for (int k = 0; k <= sxl; ++k)
+ if (fn[fnl - k] != suffix[sxl - k]) {
+ if (k < sxl) {
+ while (k > 0 && suffix[sxl - k + 1].isLetterOrNumber())
+ --k;
+ if (prefix.length() + k > fnl)
+ --k;
+ suffix.remove(0, sxl - k + 1);
+ }
+ break;
+ }
+ }
+ QString ret = prefix + QLatin1Char('{');
+ int pxl = prefix.length();
+ int sxl = suffix.length();
+ for (int j = 0; j < names.count(); ++j) {
+ if (j)
+ ret += QLatin1Char(',');
+ int off = pxl;
+ QString fn = names[j];
+ if (fn.startsWith(QLatin1Char('='))) {
+ ret += QLatin1Char('=');
+ ++off;
+ }
+ ret += fn.mid(off, fn.length() - sxl - off);
+ }
+ ret += QLatin1Char('}') + suffix;
+ return ret;
+}
+
+QStringList MultiDataModel::srcFileNames(bool pretty) const
+{
+ QStringList names;
+ foreach (DataModel *dm, m_dataModels)
+ names << (dm->isWritable() ? QString() : QString::fromLatin1("=")) + dm->srcFileName(pretty);
+ return names;
+}
+
+QString MultiDataModel::condensedSrcFileNames(bool pretty) const
+{
+ return condenseFileNames(srcFileNames(pretty));
+}
+
+bool MultiDataModel::isModified() const
+{
+ foreach (const DataModel *mdl, m_dataModels)
+ if (mdl->isModified())
+ return true;
+ return false;
+}
+
+void MultiDataModel::onModifiedChanged()
+{
+ bool modified = isModified();
+ if (modified != m_modified) {
+ emit modifiedChanged(modified);
+ m_modified = modified;
+ }
+}
+
+void MultiDataModel::onLanguageChanged()
+{
+ int i = 0;
+ while (sender() != m_dataModels[i])
+ ++i;
+ emit languageChanged(i);
+}
+
+int MultiDataModel::isFileLoaded(const QString &name) const
+{
+ for (int i = 0; i < m_dataModels.size(); ++i)
+ if (m_dataModels[i]->srcFileName() == name)
+ return i;
+ return -1;
+}
+
+int MultiDataModel::findContextIndex(const QString &context) const
+{
+ for (int i = 0; i < m_multiContextList.size(); ++i) {
+ const MultiContextItem &mc = m_multiContextList[i];
+ if (mc.context() == context)
+ return i;
+ }
+ return -1;
+}
+
+MultiContextItem *MultiDataModel::findContext(const QString &context) const
+{
+ for (int i = 0; i < m_multiContextList.size(); ++i) {
+ const MultiContextItem &mc = m_multiContextList[i];
+ if (mc.context() == context)
+ return const_cast<MultiContextItem *>(&mc);
+ }
+ return 0;
+}
+
+MessageItem *MultiDataModel::messageItem(const MultiDataIndex &index, int model) const
+{
+ if (index.context() < contextCount() && model >= 0 && model < modelCount()) {
+ MultiContextItem *mc = multiContextItem(index.context());
+ if (index.message() < mc->messageCount())
+ return mc->messageItem(model, index.message());
+ }
+ Q_ASSERT(model >= 0 && model < modelCount());
+ Q_ASSERT(index.context() < contextCount());
+ return 0;
+}
+
+void MultiDataModel::setTranslation(const MultiDataIndex &index, const QString &translation)
+{
+ MessageItem *m = messageItem(index);
+ if (translation == m->translation())
+ return;
+ m->setTranslation(translation);
+ setModified(index.model(), true);
+ emit translationChanged(index);
+}
+
+void MultiDataModel::setFinished(const MultiDataIndex &index, bool finished)
+{
+ MultiContextItem *mc = multiContextItem(index.context());
+ MultiMessageItem *mm = mc->multiMessageItem(index.message());
+ ContextItem *c = contextItem(index);
+ MessageItem *m = messageItem(index);
+ TranslatorMessage::Type type = m->type();
+ if (type == TranslatorMessage::Unfinished && finished) {
+ m->setType(TranslatorMessage::Finished);
+ mm->decrementUnfinishedCount();
+ if (!mm->countUnfinished()) {
+ incrementFinishedCount();
+ mc->incrementFinishedCount();
+ emit multiContextDataChanged(index);
+ }
+ c->incrementFinishedCount();
+ if (m->danger()) {
+ c->incrementFinishedDangerCount();
+ c->decrementUnfinishedDangerCount();
+ if (!c->unfinishedDangerCount()
+ || c->finishedCount() == c->nonobsoleteCount())
+ emit contextDataChanged(index);
+ } else if (c->finishedCount() == c->nonobsoleteCount()) {
+ emit contextDataChanged(index);
+ }
+ emit messageDataChanged(index);
+ setModified(index.model(), true);
+ } else if (type == TranslatorMessage::Finished && !finished) {
+ m->setType(TranslatorMessage::Unfinished);
+ mm->incrementUnfinishedCount();
+ if (mm->countUnfinished() == 1) {
+ decrementFinishedCount();
+ mc->decrementFinishedCount();
+ emit multiContextDataChanged(index);
+ }
+ c->decrementFinishedCount();
+ if (m->danger()) {
+ c->decrementFinishedDangerCount();
+ c->incrementUnfinishedDangerCount();
+ if (c->unfinishedDangerCount() == 1
+ || c->finishedCount() + 1 == c->nonobsoleteCount())
+ emit contextDataChanged(index);
+ } else if (c->finishedCount() + 1 == c->nonobsoleteCount()) {
+ emit contextDataChanged(index);
+ }
+ emit messageDataChanged(index);
+ setModified(index.model(), true);
+ }
+}
+
+void MultiDataModel::setDanger(const MultiDataIndex &index, bool danger)
+{
+ ContextItem *c = contextItem(index);
+ MessageItem *m = messageItem(index);
+ if (!m->danger() && danger) {
+ if (m->isFinished()) {
+ c->incrementFinishedDangerCount();
+ if (c->finishedDangerCount() == 1)
+ emit contextDataChanged(index);
+ } else {
+ c->incrementUnfinishedDangerCount();
+ if (c->unfinishedDangerCount() == 1)
+ emit contextDataChanged(index);
+ }
+ emit messageDataChanged(index);
+ m->setDanger(danger);
+ } else if (m->danger() && !danger) {
+ if (m->isFinished()) {
+ c->decrementFinishedDangerCount();
+ if (!c->finishedDangerCount())
+ emit contextDataChanged(index);
+ } else {
+ c->decrementUnfinishedDangerCount();
+ if (!c->unfinishedDangerCount())
+ emit contextDataChanged(index);
+ }
+ emit messageDataChanged(index);
+ m->setDanger(danger);
+ }
+}
+
+void MultiDataModel::updateCountsOnAdd(int model, bool writable)
+{
+ for (int i = 0; i < m_multiContextList.size(); ++i) {
+ MultiContextItem &mc = m_multiContextList[i];
+ for (int j = 0; j < mc.messageCount(); ++j)
+ if (MessageItem *m = mc.messageItem(model, j)) {
+ MultiMessageItem *mm = mc.multiMessageItem(j);
+ mm->incrementNonnullCount();
+ if (!m->isObsolete()) {
+ if (writable) {
+ if (!mm->countEditable()) {
+ mc.incrementEditableCount();
+ incrementEditableCount();
+ if (m->isFinished()) {
+ mc.incrementFinishedCount();
+ incrementFinishedCount();
+ } else {
+ mm->incrementUnfinishedCount();
+ }
+ } else if (!m->isFinished()) {
+ if (!mm->isUnfinished()) {
+ mc.decrementFinishedCount();
+ decrementFinishedCount();
+ }
+ mm->incrementUnfinishedCount();
+ }
+ mm->incrementEditableCount();
+ }
+ mc.incrementNonobsoleteCount();
+ mm->incrementNonobsoleteCount();
+ }
+ }
+ }
+}
+
+void MultiDataModel::updateCountsOnRemove(int model, bool writable)
+{
+ for (int i = 0; i < m_multiContextList.size(); ++i) {
+ MultiContextItem &mc = m_multiContextList[i];
+ for (int j = 0; j < mc.messageCount(); ++j)
+ if (MessageItem *m = mc.messageItem(model, j)) {
+ MultiMessageItem *mm = mc.multiMessageItem(j);
+ mm->decrementNonnullCount();
+ if (!m->isObsolete()) {
+ mm->decrementNonobsoleteCount();
+ mc.decrementNonobsoleteCount();
+ if (writable) {
+ mm->decrementEditableCount();
+ if (!mm->countEditable()) {
+ mc.decrementEditableCount();
+ decrementEditableCount();
+ if (m->isFinished()) {
+ mc.decrementFinishedCount();
+ decrementFinishedCount();
+ } else {
+ mm->decrementUnfinishedCount();
+ }
+ } else if (!m->isFinished()) {
+ mm->decrementUnfinishedCount();
+ if (!mm->isUnfinished()) {
+ mc.incrementFinishedCount();
+ incrementFinishedCount();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/******************************************************************************
+ *
+ * MultiDataModelIterator
+ *
+ *****************************************************************************/
+
+MultiDataModelIterator::MultiDataModelIterator(MultiDataModel *dataModel, int model, int context, int message)
+ : MultiDataIndex(model, context, message), m_dataModel(dataModel)
+{
+}
+
+void MultiDataModelIterator::operator++()
+{
+ Q_ASSERT(isValid());
+ ++m_message;
+ if (m_message >= m_dataModel->m_multiContextList.at(m_context).messageCount()) {
+ ++m_context;
+ m_message = 0;
+ }
+}
+
+bool MultiDataModelIterator::isValid() const
+{
+ return m_context < m_dataModel->m_multiContextList.count();
+}
+
+MessageItem *MultiDataModelIterator::current() const
+{
+ return m_dataModel->messageItem(*this);
+}
+
+
+/******************************************************************************
+ *
+ * MessageModel
+ *
+ *****************************************************************************/
+
+MessageModel::MessageModel(QObject *parent, MultiDataModel *data)
+ : QAbstractItemModel(parent), m_data(data)
+{
+ data->m_msgModel = this;
+ connect(m_data, SIGNAL(multiContextDataChanged(MultiDataIndex)),
+ SLOT(multiContextItemChanged(MultiDataIndex)));
+ connect(m_data, SIGNAL(contextDataChanged(MultiDataIndex)),
+ SLOT(contextItemChanged(MultiDataIndex)));
+ connect(m_data, SIGNAL(messageDataChanged(MultiDataIndex)),
+ SLOT(messageItemChanged(MultiDataIndex)));
+}
+
+QModelIndex MessageModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return createIndex(row, column, 0);
+ if (!parent.internalId())
+ return createIndex(row, column, parent.row() + 1);
+ return QModelIndex();
+}
+
+QModelIndex MessageModel::parent(const QModelIndex& index) const
+{
+ if (index.internalId())
+ return createIndex(index.internalId() - 1, 0, 0);
+ return QModelIndex();
+}
+
+void MessageModel::multiContextItemChanged(const MultiDataIndex &index)
+{
+ QModelIndex idx = createIndex(index.context(), m_data->modelCount() + 2, 0);
+ emit dataChanged(idx, idx);
+}
+
+void MessageModel::contextItemChanged(const MultiDataIndex &index)
+{
+ QModelIndex idx = createIndex(index.context(), index.model() + 1, 0);
+ emit dataChanged(idx, idx);
+}
+
+void MessageModel::messageItemChanged(const MultiDataIndex &index)
+{
+ QModelIndex idx = createIndex(index.message(), index.model() + 1, index.context() + 1);
+ emit dataChanged(idx, idx);
+}
+
+QModelIndex MessageModel::modelIndex(const MultiDataIndex &index)
+{
+ if (index.message() < 0) // Should be unused case
+ return createIndex(index.context(), index.model() + 1, 0);
+ return createIndex(index.message(), index.model() + 1, index.context() + 1);
+}
+
+int MessageModel::rowCount(const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return m_data->contextCount(); // contexts
+ if (!parent.internalId()) // messages
+ return m_data->multiContextItem(parent.row())->messageCount();
+ return 0;
+}
+
+int MessageModel::columnCount(const QModelIndex &) const
+{
+ return m_data->modelCount() + 3;
+}
+
+QVariant MessageModel::data(const QModelIndex &index, int role) const
+{
+ static QVariant pxOn =
+ qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_on.png")));
+ static QVariant pxOff =
+ qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_off.png")));
+ static QVariant pxObsolete =
+ qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_obsolete.png")));
+ static QVariant pxDanger =
+ qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_danger.png")));
+ static QVariant pxWarning =
+ qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_warning.png")));
+ static QVariant pxEmpty =
+ qVariantFromValue(QPixmap(QLatin1String(":/images/s_check_empty.png")));
+
+ int row = index.row();
+ int column = index.column() - 1;
+ if (column < 0)
+ return QVariant();
+
+ int numLangs = m_data->modelCount();
+
+ if (role == Qt::ToolTipRole && column < numLangs) {
+ return tr("Completion status for %1").arg(m_data->model(column)->localizedLanguage());
+ } else if (index.internalId()) {
+ // this is a message
+ int crow = index.internalId() - 1;
+ MultiContextItem *mci = m_data->multiContextItem(crow);
+ if (row >= mci->messageCount() || !index.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column == numLangs)) {
+ switch (column - numLangs) {
+ case 0: // Source text
+ {
+ MultiMessageItem *msgItem = mci->multiMessageItem(row);
+ if (msgItem->text().isEmpty()) {
+ if (mci->context().isEmpty())
+ return tr("<file header>");
+ else
+ return tr("<context comment>");
+ }
+ return msgItem->text().simplified();
+ }
+ default: // Status or dummy column => no text
+ return QVariant();
+ }
+ }
+ else if (role == Qt::DecorationRole && column < numLangs) {
+ if (MessageItem *msgItem = mci->messageItem(column, row)) {
+ switch (msgItem->message().type()) {
+ case TranslatorMessage::Unfinished:
+ if (msgItem->translation().isEmpty())
+ return pxEmpty;
+ if (msgItem->danger())
+ return pxDanger;
+ return pxOff;
+ case TranslatorMessage::Finished:
+ if (msgItem->danger())
+ return pxWarning;
+ return pxOn;
+ default:
+ return pxObsolete;
+ }
+ }
+ return QVariant();
+ }
+ else if (role == SortRole) {
+ switch (column - numLangs) {
+ case 0: // Source text
+ return mci->multiMessageItem(row)->text().simplified().remove(QLatin1Char('&'));
+ case 1: // Dummy column
+ return QVariant();
+ default:
+ if (MessageItem *msgItem = mci->messageItem(column, row)) {
+ int rslt = !msgItem->translation().isEmpty();
+ if (!msgItem->danger())
+ rslt |= 2;
+ if (msgItem->isObsolete())
+ rslt |= 8;
+ else if (msgItem->isFinished())
+ rslt |= 4;
+ return rslt;
+ }
+ return INT_MAX;
+ }
+ }
+ else if (role == Qt::ForegroundRole && column > 0
+ && mci->multiMessageItem(row)->isObsolete()) {
+ return QBrush(Qt::darkGray);
+ }
+ else if (role == Qt::ForegroundRole && column == numLangs
+ && mci->multiMessageItem(row)->text().isEmpty()) {
+ return QBrush(QColor(0, 0xa0, 0xa0));
+ }
+ else if (role == Qt::BackgroundRole) {
+ if (column < numLangs && numLangs != 1)
+ return m_data->brushForModel(column);
+ }
+ } else {
+ // this is a context
+ if (row >= m_data->contextCount() || !index.isValid())
+ return QVariant();
+
+ MultiContextItem *mci = m_data->multiContextItem(row);
+
+ if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column == numLangs)) {
+ switch (column - numLangs) {
+ case 0: // Context
+ {
+ if (mci->context().isEmpty())
+ return tr("<unnamed context>");
+ return mci->context().simplified();
+ }
+ case 1:
+ {
+ QString s;
+ s.sprintf("%d/%d", mci->getNumFinished(), mci->getNumEditable());
+ return s;
+ }
+ default:
+ return QVariant(); // Status => no text
+ }
+ }
+ else if (role == Qt::DecorationRole && column < numLangs) {
+ if (ContextItem *contextItem = mci->contextItem(column)) {
+ if (contextItem->isObsolete())
+ return pxObsolete;
+ if (contextItem->isFinished())
+ return contextItem->finishedDangerCount() > 0 ? pxWarning : pxOn;
+ return contextItem->unfinishedDangerCount() > 0 ? pxDanger : pxOff;
+ }
+ return QVariant();
+ }
+ else if (role == SortRole) {
+ switch (column - numLangs) {
+ case 0: // Context (same as display role)
+ return mci->context().simplified();
+ case 1: // Items
+ return mci->getNumEditable();
+ default: // Percent
+ if (ContextItem *contextItem = mci->contextItem(column)) {
+ int totalItems = contextItem->nonobsoleteCount();
+ int percent = totalItems ? (100 * contextItem->finishedCount()) / totalItems : 100;
+ int rslt = percent * (((1 << 28) - 1) / 100) + totalItems;
+ if (contextItem->isObsolete()) {
+ rslt |= (1 << 30);
+ } else if (contextItem->isFinished()) {
+ rslt |= (1 << 29);
+ if (!contextItem->finishedDangerCount())
+ rslt |= (1 << 28);
+ } else {
+ if (!contextItem->unfinishedDangerCount())
+ rslt |= (1 << 28);
+ }
+ return rslt;
+ }
+ return INT_MAX;
+ }
+ }
+ else if (role == Qt::ForegroundRole && column >= numLangs
+ && m_data->multiContextItem(row)->isObsolete()) {
+ return QBrush(Qt::darkGray);
+ }
+ else if (role == Qt::ForegroundRole && column == numLangs
+ && m_data->multiContextItem(row)->context().isEmpty()) {
+ return QBrush(QColor(0, 0xa0, 0xa0));
+ }
+ else if (role == Qt::BackgroundRole) {
+ if (column < numLangs && numLangs != 1) {
+ QBrush brush = m_data->brushForModel(column);
+ if (row & 1) {
+ brush.setColor(brush.color().darker(108));
+ }
+ return brush;
+ }
+ }
+ }
+ return QVariant();
+}
+
+MultiDataIndex MessageModel::dataIndex(const QModelIndex &index, int model) const
+{
+ Q_ASSERT(index.isValid());
+ Q_ASSERT(index.internalId());
+ return MultiDataIndex(model, index.internalId() - 1, index.row());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/messagemodel.h b/tools/linguist/linguist/messagemodel.h
new file mode 100644
index 0000000000..3b75f7ad94
--- /dev/null
+++ b/tools/linguist/linguist/messagemodel.h
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESSAGEMODEL_H
+#define MESSAGEMODEL_H
+
+#include "translator.h"
+
+#include <QtCore/QAbstractItemModel>
+#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QLocale>
+#include <QtGui/QColor>
+#include <QtGui/QBitmap>
+#include <QtXml/QXmlDefaultHandler>
+
+
+QT_BEGIN_NAMESPACE
+
+class DataModel;
+class MultiDataModel;
+
+class MessageItem
+{
+public:
+ MessageItem(const TranslatorMessage &message);
+
+ bool danger() const { return m_danger; }
+ void setDanger(bool danger) { m_danger = danger; }
+
+ void setTranslation(const QString &translation)
+ { m_message.setTranslation(translation); }
+
+ QString context() const { return m_message.context(); }
+ QString text() const { return m_message.sourceText(); }
+ QString pluralText() const { return m_message.extra(QLatin1String("po-msgid_plural")); }
+ QString comment() const { return m_message.comment(); }
+ QString fileName() const { return m_message.fileName(); }
+ QString extraComment() const { return m_message.extraComment(); }
+ QString translatorComment() const { return m_message.translatorComment(); }
+ void setTranslatorComment(const QString &cmt) { m_message.setTranslatorComment(cmt); }
+ int lineNumber() const { return m_message.lineNumber(); }
+ QString translation() const { return m_message.translation(); }
+ QStringList translations() const { return m_message.translations(); }
+ void setTranslations(const QStringList &translations)
+ { m_message.setTranslations(translations); }
+
+ TranslatorMessage::Type type() const { return m_message.type(); }
+ void setType(TranslatorMessage::Type type) { m_message.setType(type); }
+
+ bool isFinished() const { return type() == TranslatorMessage::Finished; }
+ bool isObsolete() const { return type() == TranslatorMessage::Obsolete; }
+ const TranslatorMessage &message() const { return m_message; }
+
+ bool compare(const QString &findText, bool matchSubstring,
+ Qt::CaseSensitivity cs) const;
+
+private:
+ TranslatorMessage m_message;
+ bool m_danger;
+};
+
+
+class ContextItem
+{
+public:
+ ContextItem(const QString &context);
+
+ int finishedDangerCount() const { return m_finishedDangerCount; }
+ int unfinishedDangerCount() const { return m_unfinishedDangerCount; }
+
+ int finishedCount() const { return m_finishedCount; }
+ int unfinishedCount() const { return m_nonobsoleteCount - m_finishedCount; }
+ int nonobsoleteCount() const { return m_nonobsoleteCount; }
+
+ QString context() const { return m_context; }
+ QString comment() const { return m_comment; }
+ QString fullContext() const { return m_comment.trimmed(); }
+
+ // For item status in context list
+ bool isObsolete() const { return !nonobsoleteCount(); }
+ bool isFinished() const { return unfinishedCount() == 0; }
+
+ MessageItem *messageItem(int i) const;
+ int messageCount() const { return msgItemList.count(); }
+
+ MessageItem *findMessage(const QString &sourcetext, const QString &comment) const;
+
+private:
+ friend class DataModel;
+ friend class MultiDataModel;
+ void appendMessage(const MessageItem &msg) { msgItemList.append(msg); }
+ void appendToComment(const QString &x);
+ void incrementFinishedCount() { ++m_finishedCount; }
+ void decrementFinishedCount() { --m_finishedCount; }
+ void incrementFinishedDangerCount() { ++m_finishedDangerCount; }
+ void decrementFinishedDangerCount() { --m_finishedDangerCount; }
+ void incrementUnfinishedDangerCount() { ++m_unfinishedDangerCount; }
+ void decrementUnfinishedDangerCount() { --m_unfinishedDangerCount; }
+ void incrementNonobsoleteCount() { ++m_nonobsoleteCount; }
+
+ QString m_comment;
+ QString m_context;
+ int m_finishedCount;
+ int m_finishedDangerCount;
+ int m_unfinishedDangerCount;
+ int m_nonobsoleteCount;
+ QList<MessageItem> msgItemList;
+};
+
+
+class DataIndex
+{
+public:
+ DataIndex() : m_context(-1), m_message(-1) {}
+ DataIndex(int context, int message) : m_context(context), m_message(message) {}
+ int context() const { return m_context; }
+ int message() const { return m_message; }
+ bool isValid() const { return m_context >= 0; }
+protected:
+ int m_context;
+ int m_message;
+};
+
+
+class DataModelIterator : public DataIndex
+{
+public:
+ DataModelIterator(DataModel *model, int contextNo = 0, int messageNo = 0);
+ MessageItem *current() const;
+ bool isValid() const;
+ void operator++();
+private:
+ DataModelIterator() {}
+ DataModel *m_model; // not owned
+};
+
+
+class DataModel : public QObject
+{
+ Q_OBJECT
+public:
+ DataModel(QObject *parent = 0);
+
+ enum FindLocation { NoLocation = 0, SourceText = 0x1, Translations = 0x2, Comments = 0x4 };
+
+ // Specializations
+ int contextCount() const { return m_contextList.count(); }
+ ContextItem *findContext(const QString &context) const;
+ MessageItem *findMessage(const QString &context, const QString &sourcetext,
+ const QString &comment) const;
+
+ ContextItem *contextItem(int index) const;
+ MessageItem *messageItem(const DataIndex &index) const;
+
+ int messageCount() const { return m_numMessages; }
+ bool isEmpty() const { return m_numMessages == 0; }
+ bool isModified() const { return m_modified; }
+ void setModified(bool dirty);
+ bool isWritable() const { return m_writable; }
+ void setWritable(bool writable) { m_writable = writable; }
+
+ bool isWellMergeable(const DataModel *other) const;
+ bool load(const QString &fileName, bool *langGuessed, QWidget *parent);
+ bool save(QWidget *parent) { return save(m_srcFileName, parent); }
+ bool saveAs(const QString &newFileName, QWidget *parent);
+ bool release(const QString &fileName, bool verbose,
+ bool ignoreUnfinished, TranslatorSaveMode mode, QWidget *parent);
+ QString srcFileName(bool pretty = false) const
+ { return pretty ? prettifyPlainFileName(m_srcFileName) : m_srcFileName; }
+
+ static QString prettifyPlainFileName(const QString &fn);
+ static QString prettifyFileName(const QString &fn);
+
+ bool setLanguageAndCountry(QLocale::Language lang, QLocale::Country country);
+ QLocale::Language language() const { return m_language; }
+ QLocale::Country country() const { return m_country; }
+ void setSourceLanguageAndCountry(QLocale::Language lang, QLocale::Country country);
+ QLocale::Language sourceLanguage() const { return m_sourceLanguage; }
+ QLocale::Country sourceCountry() const { return m_sourceCountry; }
+
+ const QString &localizedLanguage() const { return m_localizedLanguage; }
+ const QStringList &numerusForms() const { return m_numerusForms; }
+ const QList<bool> &countRefNeeds() const { return m_countRefNeeds; }
+
+ QStringList normalizedTranslations(const MessageItem &m) const;
+ void doCharCounting(const QString& text, int& trW, int& trC, int& trCS);
+ void updateStatistics();
+
+ int getSrcWords() const { return m_srcWords; }
+ int getSrcChars() const { return m_srcChars; }
+ int getSrcCharsSpc() const { return m_srcCharsSpc; }
+
+signals:
+ void statsChanged(int words, int characters, int cs, int words2, int characters2, int cs2);
+ void progressChanged(int finishedCount, int oldFinishedCount);
+ void languageChanged();
+ void modifiedChanged();
+
+private:
+ friend class DataModelIterator;
+ QList<ContextItem> m_contextList;
+
+ bool save(const QString &fileName, QWidget *parent);
+ void updateLocale();
+
+ bool m_writable;
+ bool m_modified;
+
+ int m_numMessages;
+
+ // For statistics
+ int m_srcWords;
+ int m_srcChars;
+ int m_srcCharsSpc;
+
+ QString m_srcFileName;
+ QLocale::Language m_language;
+ QLocale::Language m_sourceLanguage;
+ QLocale::Country m_country;
+ QLocale::Country m_sourceCountry;
+ QByteArray m_codecName;
+ bool m_relativeLocations;
+ Translator::ExtraData m_extra;
+
+ QString m_localizedLanguage;
+ QStringList m_numerusForms;
+ QList<bool> m_countRefNeeds;
+};
+
+
+struct MultiMessageItem
+{
+public:
+ MultiMessageItem(const MessageItem *m);
+ QString text() const { return m_text; }
+ QString pluralText() const { return m_pluralText; }
+ QString comment() const { return m_comment; }
+ bool isEmpty() const { return !m_nonnullCount; }
+ // The next two include also read-only
+ bool isObsolete() const { return m_nonnullCount && !m_nonobsoleteCount; }
+ int countNonobsolete() const { return m_nonobsoleteCount; }
+ // The next three include only read-write
+ int countEditable() const { return m_editableCount; }
+ bool isUnfinished() const { return m_unfinishedCount != 0; }
+ int countUnfinished() const { return m_unfinishedCount; }
+
+private:
+ friend class MultiDataModel;
+ void incrementNonnullCount() { ++m_nonnullCount; }
+ void decrementNonnullCount() { --m_nonnullCount; }
+ void incrementNonobsoleteCount() { ++m_nonobsoleteCount; }
+ void decrementNonobsoleteCount() { --m_nonobsoleteCount; }
+ void incrementEditableCount() { ++m_editableCount; }
+ void decrementEditableCount() { --m_editableCount; }
+ void incrementUnfinishedCount() { ++m_unfinishedCount; }
+ void decrementUnfinishedCount() { --m_unfinishedCount; }
+
+ QString m_text;
+ QString m_pluralText;
+ QString m_comment;
+ int m_nonnullCount; // all
+ int m_nonobsoleteCount; // all
+ int m_editableCount; // read-write
+ int m_unfinishedCount; // read-write
+};
+
+struct MultiContextItem
+{
+public:
+ MultiContextItem(int oldCount, ContextItem *ctx, bool writable);
+
+ ContextItem *contextItem(int model) const { return m_contextList[model]; }
+
+ MultiMessageItem *multiMessageItem(int msgIdx) const
+ { return const_cast<MultiMessageItem *>(&m_multiMessageList[msgIdx]); }
+ MessageItem *messageItem(int model, int msgIdx) const { return m_messageLists[model][msgIdx]; }
+ int firstNonobsoleteMessageIndex(int msgIdx) const;
+ int findMessage(const QString &sourcetext, const QString &comment) const;
+
+ QString context() const { return m_context; }
+ QString comment() const { return m_comment; }
+ int messageCount() const { return m_messageLists.isEmpty() ? 0 : m_messageLists[0].count(); }
+ // For item count in context list
+ int getNumFinished() const { return m_finishedCount; }
+ int getNumEditable() const { return m_editableCount; }
+ // For background in context list
+ bool isObsolete() const { return messageCount() && !m_nonobsoleteCount; }
+
+private:
+ friend class MultiDataModel;
+ void appendEmptyModel();
+ void assignLastModel(ContextItem *ctx, bool writable);
+ void removeModel(int pos);
+ void moveModel(int oldPos, int newPos); // newPos is *before* removing at oldPos
+ void putMessageItem(int pos, MessageItem *m);
+ void appendMessageItem(MessageItem *m);
+ void removeMultiMessageItem(int pos);
+ void incrementFinishedCount() { ++m_finishedCount; }
+ void decrementFinishedCount() { --m_finishedCount; }
+ void incrementEditableCount() { ++m_editableCount; }
+ void decrementEditableCount() { --m_editableCount; }
+ void incrementNonobsoleteCount() { ++m_nonobsoleteCount; }
+ void decrementNonobsoleteCount() { --m_nonobsoleteCount; }
+
+ QString m_context;
+ QString m_comment;
+ QList<MultiMessageItem> m_multiMessageList;
+ QList<ContextItem *> m_contextList;
+ // The next two could be in the MultiMessageItems, but are here for efficiency
+ QList<QList<MessageItem *> > m_messageLists;
+ QList<QList<MessageItem *> *> m_writableMessageLists;
+ int m_finishedCount; // read-write
+ int m_editableCount; // read-write
+ int m_nonobsoleteCount; // all (note: this counts messages, not multi-messages)
+};
+
+
+class MultiDataIndex
+{
+public:
+ MultiDataIndex() : m_model(-1), m_context(-1), m_message(-1) {}
+ MultiDataIndex(int model, int context, int message)
+ : m_model(model), m_context(context), m_message(message) {}
+ void setModel(int model) { m_model = model; }
+ int model() const { return m_model; }
+ int context() const { return m_context; }
+ int message() const { return m_message; }
+ bool isValid() const { return m_context >= 0; }
+ bool operator==(const MultiDataIndex &other) const
+ { return m_model == other.m_model && m_context == other.m_context && m_message == other.m_message; }
+ bool operator!=(const MultiDataIndex &other) const { return !(*this == other); }
+protected:
+ int m_model;
+ int m_context;
+ int m_message;
+};
+
+
+class MultiDataModelIterator : public MultiDataIndex
+{
+public:
+ MultiDataModelIterator(MultiDataModel *model, int modelNo, int contextNo = 0, int messageNo = 0);
+ MessageItem *current() const;
+ bool isValid() const;
+ void operator++();
+private:
+ MultiDataModelIterator() {}
+ MultiDataModel *m_dataModel; // not owned
+};
+
+
+class MessageModel;
+
+class MultiDataModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ MultiDataModel(QObject *parent = 0);
+ ~MultiDataModel();
+
+ bool isWellMergeable(const DataModel *dm) const;
+ void append(DataModel *dm, bool readWrite);
+ bool save(int model, QWidget *parent) { return m_dataModels[model]->save(parent); }
+ bool saveAs(int model, const QString &newFileName, QWidget *parent)
+ { return m_dataModels[model]->saveAs(newFileName, parent); }
+ bool release(int model, const QString &fileName, bool verbose, bool ignoreUnfinished, TranslatorSaveMode mode, QWidget *parent)
+ { return m_dataModels[model]->release(fileName, verbose, ignoreUnfinished, mode, parent); }
+ void close(int model);
+ void closeAll();
+ int isFileLoaded(const QString &name) const;
+ void moveModel(int oldPos, int newPos); // newPos is *before* removing at oldPos; note that this does not emit update signals
+
+ // Entire multi-model
+ int modelCount() const { return m_dataModels.count(); }
+ int contextCount() const { return m_multiContextList.count(); }
+ int messageCount() const { return m_numMessages; }
+ // Next two needed for progress indicator in main window
+ int getNumFinished() const { return m_numFinished; }
+ int getNumEditable() const { return m_numEditable; }
+ bool isModified() const;
+ QStringList srcFileNames(bool pretty = false) const;
+ QString condensedSrcFileNames(bool pretty = false) const;
+
+ // Per submodel
+ QString srcFileName(int model, bool pretty = false) const { return m_dataModels[model]->srcFileName(pretty); }
+ bool isModelWritable(int model) const { return m_dataModels[model]->isWritable(); }
+ bool isModified(int model) const { return m_dataModels[model]->isModified(); }
+ void setModified(int model, bool dirty) { m_dataModels[model]->setModified(dirty); }
+ QLocale::Language language(int model) const { return m_dataModels[model]->language(); }
+ QLocale::Language sourceLanguage(int model) const { return m_dataModels[model]->sourceLanguage(); }
+
+ // Per message
+ void setTranslation(const MultiDataIndex &index, const QString &translation);
+ void setFinished(const MultiDataIndex &index, bool finished);
+ void setDanger(const MultiDataIndex &index, bool danger);
+
+ // Retrieve items
+ DataModel *model(int i) { return m_dataModels[i]; }
+ MultiContextItem *multiContextItem(int ctxIdx) const
+ { return const_cast<MultiContextItem *>(&m_multiContextList[ctxIdx]); }
+ MultiMessageItem *multiMessageItem(const MultiDataIndex &index) const
+ { return multiContextItem(index.context())->multiMessageItem(index.message()); }
+ MessageItem *messageItem(const MultiDataIndex &index, int model) const;
+ MessageItem *messageItem(const MultiDataIndex &index) const { return messageItem(index, index.model()); }
+
+ static QString condenseFileNames(const QStringList &names);
+ static QStringList prettifyFileNames(const QStringList &names);
+
+ QBrush brushForModel(int model) const;
+
+signals:
+ void modelAppended();
+ void modelDeleted(int model);
+ void allModelsDeleted();
+ void languageChanged(int model);
+ void statsChanged(int words, int characters, int cs, int words2, int characters2, int cs2);
+ void modifiedChanged(bool);
+ void multiContextDataChanged(const MultiDataIndex &index);
+ void contextDataChanged(const MultiDataIndex &index);
+ void messageDataChanged(const MultiDataIndex &index);
+ void translationChanged(const MultiDataIndex &index); // Only the primary one
+
+private slots:
+ void onModifiedChanged();
+ void onLanguageChanged();
+
+private:
+ friend class MultiDataModelIterator;
+ friend class MessageModel;
+
+ int findContextIndex(const QString &context) const;
+ MultiContextItem *findContext(const QString &context) const;
+
+ ContextItem *contextItem(const MultiDataIndex &index) const
+ { return multiContextItem(index.context())->contextItem(index.model()); }
+
+ void updateCountsOnAdd(int model, bool writable);
+ void updateCountsOnRemove(int model, bool writable);
+ void incrementFinishedCount() { ++m_numFinished; }
+ void decrementFinishedCount() { --m_numFinished; }
+ void incrementEditableCount() { ++m_numEditable; }
+ void decrementEditableCount() { --m_numEditable; }
+
+ int m_numFinished;
+ int m_numEditable;
+ int m_numMessages;
+
+ bool m_modified;
+
+ QList<MultiContextItem> m_multiContextList;
+ QList<DataModel *> m_dataModels;
+
+ MessageModel *m_msgModel;
+
+ QColor m_colors[7];
+ QBitmap m_bitmap;
+};
+
+class MessageModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ enum { SortRole = Qt::UserRole };
+
+ MessageModel(QObject *parent, MultiDataModel *data);
+
+ // QAbstractItemModel
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex& index) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ // Convenience
+ MultiDataIndex dataIndex(const QModelIndex &index, int model) const;
+ MultiDataIndex dataIndex(const QModelIndex &index) const
+ { return dataIndex(index, index.column() - 1 < m_data->modelCount() ? index.column() - 1 : -1); }
+ QModelIndex modelIndex(const MultiDataIndex &index);
+
+private slots:
+ void reset() { QAbstractItemModel::reset(); }
+ void multiContextItemChanged(const MultiDataIndex &index);
+ void contextItemChanged(const MultiDataIndex &index);
+ void messageItemChanged(const MultiDataIndex &index);
+
+private:
+ friend class MultiDataModel;
+
+ MultiDataModel *m_data; // not owned
+};
+
+QT_END_NAMESPACE
+
+#endif // MESSAGEMODEL_H
diff --git a/tools/linguist/linguist/phrase.cpp b/tools/linguist/linguist/phrase.cpp
new file mode 100644
index 0000000000..563c72d8a6
--- /dev/null
+++ b/tools/linguist/linguist/phrase.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "phrase.h"
+#include "translator.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QFileInfo>
+#include <QMessageBox>
+#include <QRegExp>
+#include <QTextCodec>
+#include <QTextStream>
+#include <QXmlAttributes>
+#include <QXmlDefaultHandler>
+#include <QXmlParseException>
+
+QT_BEGIN_NAMESPACE
+
+static QString protect(const QString & str)
+{
+ QString p = str;
+ p.replace(QLatin1Char('&'), QLatin1String("&amp;"));
+ p.replace(QLatin1Char('\"'), QLatin1String("&quot;"));
+ p.replace(QLatin1Char('>'), QLatin1String("&gt;"));
+ p.replace(QLatin1Char('<'), QLatin1String("&lt;"));
+ p.replace(QLatin1Char('\''), QLatin1String("&apos;"));
+ return p;
+}
+
+Phrase::Phrase()
+ : shrtc(-1), m_phraseBook(0)
+{
+}
+
+Phrase::Phrase(const QString &source, const QString &target,
+ const QString &definition, int sc)
+ : shrtc(sc), s(source), t(target), d(definition),
+ m_phraseBook(0)
+{
+}
+
+Phrase::Phrase(const QString &source, const QString &target,
+ const QString &definition, PhraseBook *phraseBook)
+ : shrtc(-1), s(source), t(target), d(definition),
+ m_phraseBook(phraseBook)
+{
+}
+
+void Phrase::setSource(const QString &ns)
+{
+ if (s == ns)
+ return;
+ s = ns;
+ if (m_phraseBook)
+ m_phraseBook->phraseChanged(this);
+}
+
+void Phrase::setTarget(const QString &nt)
+{
+ if (t == nt)
+ return;
+ t = nt;
+ if (m_phraseBook)
+ m_phraseBook->phraseChanged(this);
+}
+
+void Phrase::setDefinition(const QString &nd)
+{
+ if (d == nd)
+ return;
+ d = nd;
+ if (m_phraseBook)
+ m_phraseBook->phraseChanged(this);
+}
+
+bool operator==(const Phrase &p, const Phrase &q)
+{
+ return p.source() == q.source() && p.target() == q.target() &&
+ p.definition() == q.definition() && p.phraseBook() == q.phraseBook();
+}
+
+class QphHandler : public QXmlDefaultHandler
+{
+public:
+ QphHandler(PhraseBook *phraseBook)
+ : pb(phraseBook), ferrorCount(0) { }
+
+ virtual bool startElement(const QString &namespaceURI,
+ const QString &localName, const QString &qName,
+ const QXmlAttributes &atts);
+ virtual bool endElement(const QString &namespaceURI,
+ const QString &localName, const QString &qName);
+ virtual bool characters(const QString &ch);
+ virtual bool fatalError(const QXmlParseException &exception);
+
+ QString language() const { return m_language; }
+ QString sourceLanguage() const { return m_sourceLanguage; }
+
+private:
+ PhraseBook *pb;
+ QString source;
+ QString target;
+ QString definition;
+ QString m_language;
+ QString m_sourceLanguage;
+
+ QString accum;
+ int ferrorCount;
+};
+
+bool QphHandler::startElement(const QString & /* namespaceURI */,
+ const QString & /* localName */,
+ const QString &qName,
+ const QXmlAttributes &atts)
+{
+ if (qName == QString(QLatin1String("QPH"))) {
+ m_language = atts.value(QLatin1String("language"));
+ m_sourceLanguage = atts.value(QLatin1String("sourcelanguage"));
+ } else if (qName == QString(QLatin1String("phrase"))) {
+ source.truncate(0);
+ target.truncate(0);
+ definition.truncate(0);
+ }
+ accum.truncate(0);
+ return true;
+}
+
+bool QphHandler::endElement(const QString & /* namespaceURI */,
+ const QString & /* localName */,
+ const QString &qName)
+{
+ if (qName == QString(QLatin1String("source")))
+ source = accum;
+ else if (qName == QString(QLatin1String("target")))
+ target = accum;
+ else if (qName == QString(QLatin1String("definition")))
+ definition = accum;
+ else if (qName == QString(QLatin1String("phrase")))
+ pb->m_phrases.append(new Phrase(source, target, definition, pb));
+ return true;
+}
+
+bool QphHandler::characters(const QString &ch)
+{
+ accum += ch;
+ return true;
+}
+
+bool QphHandler::fatalError(const QXmlParseException &exception)
+{
+ if (ferrorCount++ == 0) {
+ QString msg;
+ msg.sprintf("Parse error at line %d, column %d (%s).",
+ exception.lineNumber(), exception.columnNumber(),
+ exception.message().toLatin1().constData());
+ QMessageBox::information(0,
+ QObject::tr("Qt Linguist"), msg);
+ }
+ return false;
+}
+
+PhraseBook::PhraseBook() :
+ m_changed(false),
+ m_language(QLocale::C),
+ m_sourceLanguage(QLocale::C),
+ m_country(QLocale::AnyCountry),
+ m_sourceCountry(QLocale::AnyCountry)
+{
+}
+
+PhraseBook::~PhraseBook()
+{
+ qDeleteAll(m_phrases);
+}
+
+void PhraseBook::setLanguageAndCountry(QLocale::Language lang, QLocale::Country country)
+{
+ if (m_language == lang && m_country == country)
+ return;
+ m_language = lang;
+ m_country = country;
+ setModified(true);
+}
+
+void PhraseBook::setSourceLanguageAndCountry(QLocale::Language lang, QLocale::Country country)
+{
+ if (m_sourceLanguage == lang && m_sourceCountry == country)
+ return;
+ m_sourceLanguage = lang;
+ m_sourceCountry = country;
+ setModified(true);
+}
+
+bool PhraseBook::load(const QString &fileName, bool *langGuessed)
+{
+ QFile f(fileName);
+ if (!f.open(QIODevice::ReadOnly))
+ return false;
+
+ m_fileName = fileName;
+
+ QXmlInputSource in(&f);
+ QXmlSimpleReader reader;
+ // don't click on these!
+ reader.setFeature(QLatin1String("http://xml.org/sax/features/namespaces"), false);
+ reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), true);
+ reader.setFeature(QLatin1String("http://qtsoftware.com/xml/features/report-whitespace"
+ "-only-CharData"), false);
+ QphHandler *hand = new QphHandler(this);
+ reader.setContentHandler(hand);
+ reader.setErrorHandler(hand);
+
+ bool ok = reader.parse(in);
+ reader.setContentHandler(0);
+ reader.setErrorHandler(0);
+
+ Translator::languageAndCountry(hand->language(), &m_language, &m_country);
+ *langGuessed = false;
+ if (m_language == QLocale::C) {
+ QLocale sys;
+ m_language = sys.language();
+ m_country = sys.country();
+ *langGuessed = true;
+ }
+
+ QString lang = hand->sourceLanguage();
+ if (lang.isEmpty()) {
+ m_sourceLanguage = QLocale::C;
+ m_sourceCountry = QLocale::AnyCountry;
+ } else {
+ Translator::languageAndCountry(lang, &m_sourceLanguage, &m_sourceCountry);
+ }
+
+ delete hand;
+ f.close();
+ if (!ok) {
+ qDeleteAll(m_phrases);
+ m_phrases.clear();
+ } else {
+ emit listChanged();
+ }
+
+ return ok;
+}
+
+bool PhraseBook::save(const QString &fileName)
+{
+ QFile f(fileName);
+ if (!f.open(QIODevice::WriteOnly))
+ return false;
+
+ m_fileName = fileName;
+
+ QTextStream t(&f);
+ t.setCodec( QTextCodec::codecForName("UTF-8") );
+
+ t << "<!DOCTYPE QPH>\n<QPH";
+ if (sourceLanguage() != QLocale::C)
+ t << " sourcelanguage=\""
+ << Translator::makeLanguageCode(sourceLanguage(), sourceCountry()) << '"';
+ if (language() != QLocale::C)
+ t << " language=\"" << Translator::makeLanguageCode(language(), country()) << '"';
+ t << ">\n";
+ foreach (Phrase *p, m_phrases) {
+ t << "<phrase>\n";
+ t << " <source>" << protect( p->source() ) << "</source>\n";
+ t << " <target>" << protect( p->target() ) << "</target>\n";
+ if (!p->definition().isEmpty())
+ t << " <definition>" << protect( p->definition() )
+ << "</definition>\n";
+ t << "</phrase>\n";
+ }
+ t << "</QPH>\n";
+ f.close();
+ setModified(false);
+ return true;
+}
+
+void PhraseBook::append(Phrase *phrase)
+{
+ m_phrases.append(phrase);
+ phrase->setPhraseBook(this);
+ setModified(true);
+ emit listChanged();
+}
+
+void PhraseBook::remove(Phrase *phrase)
+{
+ m_phrases.removeOne(phrase);
+ phrase->setPhraseBook(0);
+ setModified(true);
+ emit listChanged();
+}
+
+void PhraseBook::setModified(bool modified)
+ {
+ if (m_changed != modified) {
+ emit modifiedChanged(modified);
+ m_changed = modified;
+ }
+}
+
+void PhraseBook::phraseChanged(Phrase *p)
+{
+ Q_UNUSED(p);
+
+ setModified(true);
+}
+
+QString PhraseBook::friendlyPhraseBookName() const
+{
+ if (!m_fileName.isEmpty())
+ return QFileInfo(m_fileName).fileName();
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/phrase.h b/tools/linguist/linguist/phrase.h
new file mode 100644
index 0000000000..6747c80722
--- /dev/null
+++ b/tools/linguist/linguist/phrase.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHRASE_H
+#define PHRASE_H
+
+#include <QObject>
+#include <QString>
+#include <QList>
+#include <QtCore/QLocale>
+
+QT_BEGIN_NAMESPACE
+
+class PhraseBook;
+
+class Phrase
+{
+public:
+ Phrase();
+ Phrase(const QString &source, const QString &target,
+ const QString &definition, int sc = -1);
+ Phrase(const QString &source, const QString &target,
+ const QString &definition, PhraseBook *phraseBook);
+
+ QString source() const { return s; }
+ void setSource(const QString &ns);
+ QString target() const {return t;}
+ void setTarget(const QString &nt);
+ QString definition() const {return d;}
+ void setDefinition (const QString &nd);
+ int shortcut() const { return shrtc; }
+ PhraseBook *phraseBook() const { return m_phraseBook; }
+ void setPhraseBook(PhraseBook *book) { m_phraseBook = book; }
+
+private:
+ int shrtc;
+ QString s;
+ QString t;
+ QString d;
+ PhraseBook *m_phraseBook;
+};
+
+bool operator==(const Phrase &p, const Phrase &q);
+inline bool operator!=(const Phrase &p, const Phrase &q) {
+ return !(p == q);
+}
+
+class QphHandler;
+
+class PhraseBook : public QObject
+{
+ Q_OBJECT
+
+public:
+ PhraseBook();
+ ~PhraseBook();
+ bool load(const QString &fileName, bool *langGuessed);
+ bool save(const QString &fileName);
+ QList<Phrase *> phrases() const { return m_phrases; }
+ void append(Phrase *phrase);
+ void remove(Phrase *phrase);
+ QString fileName() const { return m_fileName; }
+ QString friendlyPhraseBookName() const;
+ bool isModified() const { return m_changed; }
+
+ void setLanguageAndCountry(QLocale::Language lang, QLocale::Country country);
+ QLocale::Language language() const { return m_language; }
+ QLocale::Country country() const { return m_country; }
+ void setSourceLanguageAndCountry(QLocale::Language lang, QLocale::Country country);
+ QLocale::Language sourceLanguage() const { return m_sourceLanguage; }
+ QLocale::Country sourceCountry() const { return m_sourceCountry; }
+
+signals:
+ void modifiedChanged(bool changed);
+ void listChanged();
+
+private:
+ // Prevent copying
+ PhraseBook(const PhraseBook &);
+ PhraseBook& operator=(const PhraseBook &);
+
+ void setModified(bool modified);
+ void phraseChanged(Phrase *phrase);
+
+ QList<Phrase *> m_phrases;
+ QString m_fileName;
+ bool m_changed;
+
+ QLocale::Language m_language;
+ QLocale::Language m_sourceLanguage;
+ QLocale::Country m_country;
+ QLocale::Country m_sourceCountry;
+
+ friend class QphHandler;
+ friend class Phrase;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/linguist/phrasebookbox.cpp b/tools/linguist/linguist/phrasebookbox.cpp
new file mode 100644
index 0000000000..50749d7ce1
--- /dev/null
+++ b/tools/linguist/linguist/phrasebookbox.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/* TRANSLATOR PhraseBookBox
+
+ Go to Phrase > Edit Phrase Book... The dialog that pops up is a
+ PhraseBookBox.
+*/
+
+#include "phrasebookbox.h"
+#include "translationsettingsdialog.h"
+
+#include <QtEvents>
+#include <QLineEdit>
+#include <QMessageBox>
+#include <QHeaderView>
+#include <QSortFilterProxyModel>
+
+QT_BEGIN_NAMESPACE
+
+#define NewPhrase tr("(New Entry)")
+
+PhraseBookBox::PhraseBookBox(PhraseBook *phraseBook, QWidget *parent)
+ : QDialog(parent),
+ m_phraseBook(phraseBook),
+ m_translationSettingsDialog(0)
+{
+ setupUi(this);
+ setWindowTitle(tr("%1[*] - Qt Linguist").arg(m_phraseBook->friendlyPhraseBookName()));
+ setWindowModified(m_phraseBook->isModified());
+
+ phrMdl = new PhraseModel(this);
+
+ m_sortedPhraseModel = new QSortFilterProxyModel(this);
+ m_sortedPhraseModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+ m_sortedPhraseModel->setSortLocaleAware(true);
+ m_sortedPhraseModel->setDynamicSortFilter(true);
+ m_sortedPhraseModel->setSourceModel(phrMdl);
+
+ phraseList->setModel(m_sortedPhraseModel);
+ phraseList->header()->setDefaultSectionSize(150);
+ phraseList->header()->setResizeMode(QHeaderView::Interactive);
+
+ connect(sourceLed, SIGNAL(textChanged(QString)),
+ this, SLOT(sourceChanged(QString)));
+ connect(targetLed, SIGNAL(textChanged(QString)),
+ this, SLOT(targetChanged(QString)));
+ connect(definitionLed, SIGNAL(textChanged(QString)),
+ this, SLOT(definitionChanged(QString)));
+ connect(phraseList->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
+ this, SLOT(selectionChanged()));
+ connect(newBut, SIGNAL(clicked()), this, SLOT(newPhrase()));
+ connect(removeBut, SIGNAL(clicked()), this, SLOT(removePhrase()));
+ connect(settingsBut, SIGNAL(clicked()), this, SLOT(settings()));
+ connect(saveBut, SIGNAL(clicked()), this, SLOT(save()));
+ connect(m_phraseBook, SIGNAL(modifiedChanged(bool)), this, SLOT(setWindowModified(bool)));
+
+ sourceLed->installEventFilter(this);
+ targetLed->installEventFilter(this);
+ definitionLed->installEventFilter(this);
+
+ foreach (Phrase *p, phraseBook->phrases())
+ phrMdl->addPhrase(p);
+
+ phraseList->sortByColumn(0, Qt::AscendingOrder);
+
+ enableDisable();
+}
+
+bool PhraseBookBox::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::KeyPress &&
+ (obj == sourceLed || obj == targetLed || obj == definitionLed))
+ {
+ const QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
+ const int key = keyEvent->key();
+
+ switch (key) {
+ case Qt::Key_Down:
+ case Qt::Key_Up:
+ case Qt::Key_PageDown:
+ case Qt::Key_PageUp:
+ return QApplication::sendEvent(phraseList, event);
+ }
+ }
+ return QDialog::eventFilter(obj, event);
+}
+
+void PhraseBookBox::newPhrase()
+{
+ Phrase *p = new Phrase();
+ p->setSource(NewPhrase);
+ m_phraseBook->append(p);
+ selectItem(phrMdl->addPhrase(p));
+}
+
+void PhraseBookBox::removePhrase()
+{
+ QModelIndex index = currentPhraseIndex();
+ Phrase *phrase = phrMdl->phrase(index);
+ m_phraseBook->remove(phrase);
+ phrMdl->removePhrase(index);
+ delete phrase;
+}
+
+void PhraseBookBox::settings()
+{
+ if (!m_translationSettingsDialog)
+ m_translationSettingsDialog = new TranslationSettingsDialog(this);
+ m_translationSettingsDialog->setPhraseBook(m_phraseBook);
+ m_translationSettingsDialog->exec();
+}
+
+void PhraseBookBox::save()
+{
+ const QString &fileName = m_phraseBook->fileName();
+ if (!m_phraseBook->save(fileName))
+ QMessageBox::warning(this,
+ tr("Qt Linguist"),
+ tr("Cannot save phrase book '%1'.").arg(fileName));
+}
+
+void PhraseBookBox::sourceChanged(const QString& source)
+{
+ QModelIndex index = currentPhraseIndex();
+ if (index.isValid())
+ phrMdl->setData(phrMdl->index(index.row(), 0), source);
+}
+
+void PhraseBookBox::targetChanged(const QString& target)
+{
+ QModelIndex index = currentPhraseIndex();
+ if (index.isValid())
+ phrMdl->setData(phrMdl->index(index.row(), 1), target);
+}
+
+void PhraseBookBox::definitionChanged(const QString& definition)
+{
+ QModelIndex index = currentPhraseIndex();
+ if (index.isValid())
+ phrMdl->setData(phrMdl->index(index.row(), 2), definition);
+}
+
+void PhraseBookBox::selectionChanged()
+{
+ enableDisable();
+}
+
+void PhraseBookBox::selectItem(const QModelIndex &index)
+{
+ const QModelIndex &sortedIndex = m_sortedPhraseModel->mapFromSource(index);
+ phraseList->scrollTo(sortedIndex);
+ phraseList->setCurrentIndex(sortedIndex);
+}
+
+void PhraseBookBox::enableDisable()
+{
+ QModelIndex index = currentPhraseIndex();
+
+ sourceLed->blockSignals(true);
+ targetLed->blockSignals(true);
+ definitionLed->blockSignals(true);
+
+ bool indexValid = index.isValid();
+
+ if (indexValid) {
+ Phrase *p = phrMdl->phrase(index);
+ sourceLed->setText(p->source().simplified());
+ targetLed->setText(p->target().simplified());
+ definitionLed->setText(p->definition());
+ }
+ else {
+ sourceLed->setText(QString());
+ targetLed->setText(QString());
+ definitionLed->setText(QString());
+ }
+
+ sourceLed->setEnabled(indexValid);
+ targetLed->setEnabled(indexValid);
+ definitionLed->setEnabled(indexValid);
+ removeBut->setEnabled(indexValid);
+
+ sourceLed->blockSignals(false);
+ targetLed->blockSignals(false);
+ definitionLed->blockSignals(false);
+
+ QWidget *f = QApplication::focusWidget();
+ if (f != sourceLed && f != targetLed && f != definitionLed) {
+ QLineEdit *led = (sourceLed->text() == NewPhrase ? sourceLed : targetLed);
+ led->setFocus();
+ led->selectAll();
+ } else {
+ static_cast<QLineEdit*>(f)->selectAll();
+ }
+}
+
+QModelIndex PhraseBookBox::currentPhraseIndex() const
+{
+ return m_sortedPhraseModel->mapToSource(phraseList->currentIndex());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/phrasebookbox.h b/tools/linguist/linguist/phrasebookbox.h
new file mode 100644
index 0000000000..b34cae51d7
--- /dev/null
+++ b/tools/linguist/linguist/phrasebookbox.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHRASEBOOKBOX_H
+#define PHRASEBOOKBOX_H
+
+#include "ui_phrasebookbox.h"
+#include "phrase.h"
+#include "phrasemodel.h"
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class TranslationSettingsDialog;
+
+class QSortFilterProxyModel;
+
+class PhraseBookBox : public QDialog, public Ui::PhraseBookBox
+{
+ Q_OBJECT
+public:
+ PhraseBookBox(PhraseBook *phraseBook, QWidget *parent = 0);
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *event);
+
+private slots:
+ void newPhrase();
+ void removePhrase();
+ void settings();
+ void save();
+ void sourceChanged(const QString &source);
+ void targetChanged(const QString &target);
+ void definitionChanged(const QString &definition);
+ void selectionChanged();
+
+private:
+ void selectItem(const QModelIndex &index);
+ void enableDisable();
+ QModelIndex currentPhraseIndex() const;
+
+ QString fn;
+ PhraseBook *m_phraseBook;
+ PhraseModel *phrMdl;
+ QSortFilterProxyModel *m_sortedPhraseModel;
+ TranslationSettingsDialog *m_translationSettingsDialog;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/linguist/phrasebookbox.ui b/tools/linguist/linguist/phrasebookbox.ui
new file mode 100644
index 0000000000..32c51f6350
--- /dev/null
+++ b/tools/linguist/linguist/phrasebookbox.ui
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>PhraseBookBox</class>
+ <widget class="QDialog" name="PhraseBookBox">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>596</width>
+ <height>454</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Edit Phrase Book</string>
+ </property>
+ <property name="whatsThis">
+ <string>This window allows you to add, modify, or delete entries in a phrase book.</string>
+ </property>
+ <layout class="QHBoxLayout" name="hboxLayout">
+ <item>
+ <layout class="QVBoxLayout" name="inputsLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="0">
+ <widget class="QLabel" name="target">
+ <property name="text">
+ <string>&amp;Translation:</string>
+ </property>
+ <property name="buddy">
+ <cstring>targetLed</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="targetLed">
+ <property name="whatsThis">
+ <string>This is the phrase in the target language corresponding to the source phrase.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="source">
+ <property name="text">
+ <string>S&amp;ource phrase:</string>
+ </property>
+ <property name="buddy">
+ <cstring>sourceLed</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="definitionLed">
+ <property name="whatsThis">
+ <string>This is a definition for the source phrase.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="sourceLed">
+ <property name="whatsThis">
+ <string>This is the phrase in the source language.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="definition">
+ <property name="text">
+ <string>&amp;Definition:</string>
+ </property>
+ <property name="buddy">
+ <cstring>definitionLed</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTreeView" name="phraseList">
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="uniformRowHeights">
+ <bool>true</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="expandsOnDoubleClick">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="buttonLayout">
+ <item>
+ <widget class="QPushButton" name="newBut">
+ <property name="whatsThis">
+ <string>Click here to add the phrase to the phrase book.</string>
+ </property>
+ <property name="text">
+ <string>&amp;New Entry</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeBut">
+ <property name="whatsThis">
+ <string>Click here to remove the entry from the phrase book.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Remove Entry</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="settingsBut">
+ <property name="text">
+ <string>Settin&amp;gs...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="saveBut">
+ <property name="whatsThis">
+ <string>Click here to save the changes made.</string>
+ </property>
+ <property name="text">
+ <string>&amp;Save</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeBut">
+ <property name="whatsThis">
+ <string>Click here to close this window.</string>
+ </property>
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="spacer1">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <tabstops>
+ <tabstop>sourceLed</tabstop>
+ <tabstop>targetLed</tabstop>
+ <tabstop>definitionLed</tabstop>
+ <tabstop>newBut</tabstop>
+ <tabstop>removeBut</tabstop>
+ <tabstop>saveBut</tabstop>
+ <tabstop>closeBut</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>closeBut</sender>
+ <signal>clicked()</signal>
+ <receiver>PhraseBookBox</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>545</x>
+ <y>166</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>545</x>
+ <y>199</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/linguist/linguist/phrasemodel.cpp b/tools/linguist/linguist/phrasemodel.cpp
new file mode 100644
index 0000000000..536897833e
--- /dev/null
+++ b/tools/linguist/linguist/phrasemodel.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "phrasemodel.h"
+
+QT_BEGIN_NAMESPACE
+
+void PhraseModel::removePhrases()
+{
+ int r = plist.count();
+ if (r > 0) {
+ plist.clear();
+ reset();
+ }
+}
+
+Phrase *PhraseModel::phrase(const QModelIndex &index) const
+{
+ return plist.at(index.row());
+}
+
+void PhraseModel::setPhrase(const QModelIndex &indx, Phrase *ph)
+{
+ int r = indx.row();
+
+ plist[r] = ph;
+
+ // update item in view
+ const QModelIndex &si = index(r, 0);
+ const QModelIndex &ei = index(r, 2);
+ emit dataChanged(si, ei);
+}
+
+QModelIndex PhraseModel::addPhrase(Phrase *p)
+{
+ int r = plist.count();
+
+ plist.append(p);
+
+ // update phrases as we add them
+ beginInsertRows(QModelIndex(), r, r);
+ QModelIndex i = index(r, 0);
+ endInsertRows();
+ return i;
+}
+
+void PhraseModel::removePhrase(const QModelIndex &index)
+{
+ int r = index.row();
+ beginRemoveRows(QModelIndex(), r, r);
+ plist.removeAt(r);
+ endRemoveRows();
+}
+
+QModelIndex PhraseModel::index(Phrase * const phr) const
+{
+ int row;
+ if ((row = plist.indexOf(phr)) == -1)
+ return QModelIndex();
+
+ return index(row, 0);
+}
+
+int PhraseModel::rowCount(const QModelIndex &) const
+{
+ return plist.count();
+}
+
+int PhraseModel::columnCount(const QModelIndex &) const
+{
+ return 3;
+}
+
+QVariant PhraseModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if ((role == Qt::DisplayRole) && (orientation == Qt::Horizontal)) {
+ switch(section) {
+ case 0:
+ return tr("Source phrase");
+ case 1:
+ return tr("Translation");
+ case 2:
+ return tr("Definition");
+ }
+ }
+
+ return QVariant();
+}
+
+Qt::ItemFlags PhraseModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return 0;
+ Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+ // Edit is allowed for source & translation if item is from phrasebook
+ if (plist.at(index.row())->phraseBook()
+ && (index.column() != 2))
+ flags |= Qt::ItemIsEditable;
+ return flags;
+}
+
+bool PhraseModel::setData(const QModelIndex & index, const QVariant & value, int role)
+{
+ int row = index.row();
+ int column = index.column();
+
+ if (!index.isValid() || row >= plist.count() || role != Qt::EditRole)
+ return false;
+
+ Phrase *phrase = plist.at(row);
+
+ switch (column) {
+ case 0:
+ phrase->setSource(value.toString());
+ break;
+ case 1:
+ phrase->setTarget(value.toString());
+ break;
+ case 2:
+ phrase->setDefinition(value.toString());
+ break;
+ default:
+ return false;
+ }
+
+ emit dataChanged(index, index);
+ return true;
+}
+
+QVariant PhraseModel::data(const QModelIndex &index, int role) const
+{
+ int row = index.row();
+ int column = index.column();
+
+ if (row >= plist.count() || !index.isValid())
+ return QVariant();
+
+ Phrase *phrase = plist.at(row);
+
+ if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column != 2)) {
+ switch (column) {
+ case 0: // source phrase
+ return phrase->source().simplified();
+ case 1: // translation
+ return phrase->target().simplified();
+ case 2: // definition
+ return phrase->definition();
+ }
+ }
+ else if (role == Qt::EditRole && column != 2) {
+ switch (column) {
+ case 0: // source phrase
+ return phrase->source();
+ case 1: // translation
+ return phrase->target();
+ }
+ }
+
+ return QVariant();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/phrasemodel.h b/tools/linguist/linguist/phrasemodel.h
new file mode 100644
index 0000000000..4013a0b9c2
--- /dev/null
+++ b/tools/linguist/linguist/phrasemodel.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHRASEMODEL_H
+#define PHRASEMODEL_H
+
+#include "phrase.h"
+
+#include <QList>
+#include <QAbstractItemModel>
+
+QT_BEGIN_NAMESPACE
+
+class PhraseModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ PhraseModel(QObject *parent = 0)
+ : QAbstractTableModel(parent)
+ {}
+
+ void removePhrases();
+ QList<Phrase *> phraseList() const {return plist;}
+
+ QModelIndex addPhrase(Phrase *p);
+ void removePhrase(const QModelIndex &index);
+
+ Phrase *phrase(const QModelIndex &index) const;
+ void setPhrase(const QModelIndex &indx, Phrase *ph);
+ QModelIndex index(Phrase * const phr) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+ { return QAbstractTableModel::index(row, column, parent); }
+
+ // from qabstracttablemodel
+ int rowCount(const QModelIndex &) const;
+ int columnCount(const QModelIndex &) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ bool setData(const QModelIndex &index, const QVariant &value,
+ int role = Qt::EditRole);
+
+ // HACK: This model will be displayed in a _TreeView_
+ // which has a tendency to expand 'children' on double click
+ bool hasChildren(const QModelIndex &parent) const
+ { return !parent.isValid(); }
+
+private:
+ QList<Phrase *> plist;
+};
+
+QT_END_NAMESPACE
+
+#endif // PHRASEMODEL_H
diff --git a/tools/linguist/linguist/phraseview.cpp b/tools/linguist/linguist/phraseview.cpp
new file mode 100644
index 0000000000..78c91511ba
--- /dev/null
+++ b/tools/linguist/linguist/phraseview.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "messagemodel.h"
+#include "phrase.h"
+#include "phraseview.h"
+#include "phrasemodel.h"
+#include "simtexth.h"
+
+#include <QHeaderView>
+#include <QKeyEvent>
+#include <QSettings>
+#include <QTreeView>
+#include <QWidget>
+#include <QDebug>
+
+
+QT_BEGIN_NAMESPACE
+
+// Maximum number of guesses to display
+static const int MaxCandidates = 5;
+
+static QString phraseViewHeaderKey()
+{
+ return settingsPrefix() + QLatin1String("PhraseViewHeader");
+}
+
+PhraseView::PhraseView(MultiDataModel *model, QList<QHash<QString, QList<Phrase *> > > *phraseDict, QWidget *parent)
+ : QTreeView(parent),
+ m_dataModel(model),
+ m_phraseDict(phraseDict),
+ m_modelIndex(-1),
+ m_doGuesses(true)
+{
+ setObjectName(QLatin1String("phrase list view"));
+
+ m_phraseModel = new PhraseModel(this);
+
+ setModel(m_phraseModel);
+ setAlternatingRowColors(true);
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setSelectionMode(QAbstractItemView::SingleSelection);
+ setRootIsDecorated(false);
+ setItemsExpandable(false);
+
+ for (int i = 0; i < 10; i++)
+ (void) new GuessShortcut(i, this, SLOT(guessShortcut(int)));
+
+ header()->setResizeMode(QHeaderView::Interactive);
+ header()->setClickable(true);
+ header()->restoreState(QSettings().value(phraseViewHeaderKey()).toByteArray());
+
+ connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(selectPhrase(QModelIndex)));
+}
+
+PhraseView::~PhraseView()
+{
+ QSettings().setValue(phraseViewHeaderKey(), header()->saveState());
+ deleteGuesses();
+}
+
+void PhraseView::toggleGuessing()
+{
+ m_doGuesses = !m_doGuesses;
+ update();
+}
+
+void PhraseView::update()
+{
+ setSourceText(m_modelIndex, m_sourceText);
+}
+
+
+void PhraseView::contextMenuEvent(QContextMenuEvent *event)
+{
+ QModelIndex index = indexAt(event->pos());
+ if (!index.isValid())
+ return;
+
+ QMenu *contextMenu = new QMenu(this);
+
+ QAction *insertAction = new QAction(tr("Insert"), contextMenu);
+ connect(insertAction, SIGNAL(triggered()), this, SLOT(selectPhrase()));
+
+ QAction *editAction = new QAction(tr("Edit"), contextMenu);
+ connect(editAction, SIGNAL(triggered()), this, SLOT(editPhrase()));
+ editAction->setEnabled(model()->flags(index) & Qt::ItemIsEditable);
+
+ contextMenu->addAction(insertAction);
+ contextMenu->addAction(editAction);
+
+ contextMenu->exec(event->globalPos());
+ event->accept();
+}
+
+void PhraseView::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ QModelIndex index = indexAt(event->pos());
+ if (!index.isValid())
+ return;
+
+ emit phraseSelected(m_modelIndex, m_phraseModel->phrase(index)->target());
+ event->accept();
+}
+
+void PhraseView::guessShortcut(int key)
+{
+ foreach (const Phrase *phrase, m_phraseModel->phraseList())
+ if (phrase->shortcut() == key) {
+ emit phraseSelected(m_modelIndex, phrase->target());
+ return;
+ }
+}
+
+void PhraseView::selectPhrase(const QModelIndex &index)
+{
+ emit phraseSelected(m_modelIndex, m_phraseModel->phrase(index)->target());
+}
+
+void PhraseView::selectPhrase()
+{
+ emit phraseSelected(m_modelIndex, m_phraseModel->phrase(currentIndex())->target());
+}
+
+void PhraseView::editPhrase()
+{
+ edit(currentIndex());
+}
+
+static CandidateList similarTextHeuristicCandidates(MultiDataModel *model, int mi,
+ const char *text, int maxCandidates)
+{
+ QList<int> scores;
+ CandidateList candidates;
+
+ StringSimilarityMatcher stringmatcher(QString::fromLatin1(text));
+
+ for (MultiDataModelIterator it(model, mi); it.isValid(); ++it) {
+ MessageItem *m = it.current();
+ if (!m)
+ continue;
+
+ TranslatorMessage mtm = m->message();
+ if (mtm.type() == TranslatorMessage::Unfinished
+ || mtm.translation().isEmpty())
+ continue;
+
+ QString s = m->text();
+
+ int score = stringmatcher.getSimilarityScore(s);
+
+ if (candidates.count() == maxCandidates && score > scores[maxCandidates - 1])
+ candidates.removeLast();
+ if (candidates.count() < maxCandidates && score >= textSimilarityThreshold ) {
+ Candidate cand(s, mtm.translation());
+
+ int i;
+ for (i = 0; i < candidates.size(); ++i) {
+ if (score >= scores.at(i)) {
+ if (score == scores.at(i)) {
+ if (candidates.at(i) == cand)
+ goto continue_outer_loop;
+ } else {
+ break;
+ }
+ }
+ }
+ scores.insert(i, score);
+ candidates.insert(i, cand);
+ }
+ continue_outer_loop:
+ ;
+ }
+ return candidates;
+}
+
+
+void PhraseView::setSourceText(int model, const QString &sourceText)
+{
+ m_modelIndex = model;
+ m_sourceText = sourceText;
+ m_phraseModel->removePhrases();
+ deleteGuesses();
+
+ if (model < 0)
+ return;
+
+ foreach (Phrase *p, getPhrases(model, sourceText))
+ m_phraseModel->addPhrase(p);
+
+ if (!sourceText.isEmpty() && m_doGuesses) {
+ CandidateList cl = similarTextHeuristicCandidates(m_dataModel, model,
+ sourceText.toLatin1(), MaxCandidates);
+ int n = 0;
+ foreach (const Candidate &candidate, cl) {
+ QString def;
+ if (n < 9)
+ def = tr("Guess (%1)").arg(QString(QKeySequence(Qt::CTRL | (Qt::Key_0 + (n + 1)))));
+ else
+ def = tr("Guess");
+ Phrase *guess = new Phrase(candidate.source, candidate.target, def, n);
+ m_guesses.append(guess);
+ m_phraseModel->addPhrase(guess);
+ ++n;
+ }
+ }
+}
+
+QList<Phrase *> PhraseView::getPhrases(int model, const QString &source)
+{
+ QList<Phrase *> phrases;
+ QString f = MainWindow::friendlyString(source);
+ QStringList lookupWords = f.split(QLatin1Char(' '));
+
+ foreach (const QString &s, lookupWords) {
+ if (m_phraseDict->at(model).contains(s)) {
+ foreach (Phrase *p, m_phraseDict->at(model).value(s)) {
+ if (f.contains(MainWindow::friendlyString(p->source())))
+ phrases.append(p);
+ }
+ }
+ }
+ return phrases;
+}
+
+void PhraseView::deleteGuesses()
+{
+ qDeleteAll(m_guesses);
+ m_guesses.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/phraseview.h b/tools/linguist/linguist/phraseview.h
new file mode 100644
index 0000000000..39a535501a
--- /dev/null
+++ b/tools/linguist/linguist/phraseview.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PHRASEVIEW_H
+#define PHRASEVIEW_H
+
+#include <QList>
+#include <QShortcut>
+#include <QTreeView>
+#include "phrase.h"
+
+QT_BEGIN_NAMESPACE
+
+class MultiDataModel;
+class PhraseModel;
+
+class GuessShortcut : public QShortcut
+{
+ Q_OBJECT
+public:
+ GuessShortcut(int nkey, QWidget *parent, const char *member)
+ : QShortcut(parent), nrkey(nkey)
+ {
+ setKey(Qt::CTRL + (Qt::Key_1 + nrkey));
+ connect(this, SIGNAL(activated()), this, SLOT(keyActivated()));
+ connect(this, SIGNAL(activated(int)), parent, member);
+ }
+
+private slots:
+ void keyActivated() { emit activated(nrkey); }
+
+signals:
+ void activated(int nkey);
+
+private:
+ int nrkey;
+};
+
+class PhraseView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ PhraseView(MultiDataModel *model, QList<QHash<QString, QList<Phrase *> > > *phraseDict, QWidget *parent = 0);
+ ~PhraseView();
+ void setSourceText(int model, const QString &sourceText);
+
+public slots:
+ void toggleGuessing();
+ void update();
+
+signals:
+ void phraseSelected(int latestModel, const QString &phrase);
+
+protected:
+ // QObject
+ virtual void contextMenuEvent(QContextMenuEvent *event);
+ // QAbstractItemView
+ virtual void mouseDoubleClickEvent(QMouseEvent *event);
+
+private slots:
+ void guessShortcut(int nkey);
+ void selectPhrase(const QModelIndex &index);
+ void selectPhrase();
+ void editPhrase();
+
+private:
+ QList<Phrase *> getPhrases(int model, const QString &sourceText);
+ void deleteGuesses();
+
+ MultiDataModel *m_dataModel;
+ QList<QHash<QString, QList<Phrase *> > > *m_phraseDict;
+ QList<Phrase *> m_guesses;
+ PhraseModel *m_phraseModel;
+ QString m_sourceText;
+ int m_modelIndex;
+ bool m_doGuesses;
+};
+
+QT_END_NAMESPACE
+
+#endif // PHRASEVIEW_H
diff --git a/tools/linguist/linguist/printout.cpp b/tools/linguist/linguist/printout.cpp
new file mode 100644
index 0000000000..924180c817
--- /dev/null
+++ b/tools/linguist/linguist/printout.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "printout.h"
+
+#include <QPrinter>
+#include <QFontMetrics>
+
+QT_BEGIN_NAMESPACE
+
+PrintOut::PrintOut(QPrinter *printer)
+ : pr(printer), nextRule(NoRule), page(0)
+{
+ p.begin(pr);
+ QFont f(QLatin1String("Arial"));
+ f8 = f;
+ f8.setPointSize(8);
+ f10 = f;
+ f10.setPointSize(10);
+ p.setFont(f10);
+ fmetrics = new QFontMetrics(p.fontMetrics());
+ hmargin = 5 * printer->width() / printer->widthMM(); // 5 mm
+ vmargin = 5 * printer->height() / printer->heightMM(); // 5 mm
+ hsize = printer->width() - 2 * hmargin;
+ vsize = printer->height() - vmargin;
+ dateTime = QDateTime::currentDateTime();
+ breakPage(true); // init vsize and draw first header
+ cp = Paragraph(QPoint(hmargin, voffset));
+}
+
+PrintOut::~PrintOut()
+{
+ flushLine();
+ delete fmetrics;
+ p.end();
+}
+
+void PrintOut::setRule(Rule rule)
+{
+ if (nextRule < rule)
+ nextRule = rule;
+}
+
+void PrintOut::setGuide(const QString &guide)
+{
+ g = guide;
+}
+
+void PrintOut::vskip()
+{
+ if (!firstParagraph)
+ voffset += 14;
+}
+
+void PrintOut::flushLine(bool /* mayBreak */)
+{
+ if (voffset + cp.rect.height() > vsize)
+ breakPage();
+ else if (!firstParagraph)
+ drawRule(nextRule);
+
+ for (int i = 0; i < cp.boxes.count(); ++i) {
+ Box b = cp.boxes[i];
+ b.rect.translate(0, voffset);
+ QRect r = b.rect;
+ p.setFont(b.font);
+ p.drawText(r, b.text, b.options);
+ }
+ voffset += cp.rect.height();
+
+ nextRule = NoRule;
+ cp = Paragraph(QPoint(hmargin, voffset));
+ firstParagraph = false;
+}
+
+void PrintOut::addBox(int percent, const QString &text, Style style, Qt::Alignment halign)
+{
+ QTextOption options;
+ options.setAlignment(halign | Qt::AlignTop);
+ options.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+ QFont f = f10;
+ if (style == Strong)
+ f.setBold(true);
+ else if (style == Emphasis)
+ f.setItalic(true);
+ int wd = hsize * percent / 100;
+ QRect r(cp.rect.x() + cp.rect.width(), 0, wd, vsize);
+ const int ht = static_cast<int>(p.boundingRect(r, text, options).height());
+
+ Box b(r, text, f, options);
+ cp.boxes.append(b);
+ cp.rect.setSize(QSize(cp.rect.width() + wd, qMax(cp.rect.height(), ht)));
+}
+
+// use init if inital vsize should be calculated (first breakPage call)
+void PrintOut::breakPage(bool init)
+{
+ static const int LeftAlign = Qt::AlignLeft | Qt::AlignTop;
+ static const int RightAlign = Qt::AlignRight | Qt::AlignTop;
+ QRect r1, r2;
+ int h1 = 0;
+ int h2 = 0;
+
+ if (page > 0)
+ pr->newPage();
+
+ if (!init)
+ page++;
+
+ voffset = 0;
+
+ p.setFont(f10);
+ r1 = QRect(hmargin, voffset, 3 * hsize / 4, vsize);
+ r2 = QRect(r1.x() + r1.width(), voffset, hsize - r1.width(), vsize);
+ h1 = p.boundingRect(r1, LeftAlign, pr->docName()).height();
+ if (!init)
+ p.drawText(r1, LeftAlign, pr->docName());
+ h2 = p.boundingRect(r2, RightAlign, QString::number(page)).height();
+ if (!init)
+ p.drawText(r2, RightAlign, QString::number(page));
+ voffset += qMax(h1, h2 );
+
+ r1 = QRect(hmargin, voffset, hsize / 2, LeftAlign);
+ p.setFont(f8);
+ h1 = p.boundingRect(r1, LeftAlign, dateTime.toString()).height();
+ if (!init)
+ p.drawText(r1, LeftAlign, dateTime.toString());
+ p.setFont(f10);
+ voffset += qMax(h1, h2);
+
+ voffset += 4;
+ if (!init)
+ p.drawLine(QPoint(hmargin, voffset), QPoint(hmargin + hsize, voffset));
+ voffset += 14;
+
+ firstParagraph = true;
+
+ if (init) {
+ vsize -= voffset;
+ breakPage(); // now draw it when the vsize is ok
+ }
+
+}
+
+void PrintOut::drawRule(Rule rule)
+{
+ QPen pen;
+
+ switch (rule) {
+ case NoRule:
+ voffset += 5;
+ break;
+ case ThinRule:
+ pen.setColor(QColor(192, 192, 192));
+ pen.setStyle(Qt::DotLine);
+ pen.setWidth(0);
+ p.setPen(pen);
+ voffset += 5;
+ p.drawLine(QPoint(hmargin, voffset),
+ QPoint(hmargin + hsize, voffset));
+ p.setPen(QPen());
+ voffset += 2;
+ break;
+ case ThickRule:
+ voffset += 7;
+ p.drawLine(QPoint(hmargin, voffset),
+ QPoint(hmargin + hsize, voffset));
+ voffset += 4;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/printout.h b/tools/linguist/linguist/printout.h
new file mode 100644
index 0000000000..11ffa63ad8
--- /dev/null
+++ b/tools/linguist/linguist/printout.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PRINTOUT_H
+#define PRINTOUT_H
+
+#include <QFont>
+#include <QPainter>
+#include <QRect>
+#include <QTextOption>
+#include <QList>
+#include <QDateTime>
+
+QT_BEGIN_NAMESPACE
+
+class QPrinter;
+class QFontMetrics;
+
+class PrintOut
+{
+public:
+ enum Rule { NoRule, ThinRule, ThickRule };
+ enum Style { Normal, Strong, Emphasis };
+
+ PrintOut(QPrinter *printer);
+ ~PrintOut();
+
+ void setRule(Rule rule);
+ void setGuide(const QString &guide);
+ void vskip();
+ void flushLine(bool mayBreak = false);
+ void addBox(int percent, const QString &text = QString(),
+ Style style = Normal,
+ Qt::Alignment halign = Qt::AlignLeft);
+
+ int pageNum() const { return page; }
+
+ struct Box
+ {
+ QRect rect;
+ QString text;
+ QFont font;
+ QTextOption options;
+
+ Box( const QRect& r, const QString& t, const QFont& f, const QTextOption &o )
+ : rect( r ), text( t ), font( f ), options( o ) { }
+ };
+
+private:
+ void breakPage(bool init = false);
+ void drawRule( Rule rule );
+
+ struct Paragraph {
+ QRect rect;
+ QList<Box> boxes;
+
+ Paragraph() { }
+ Paragraph( QPoint p ) : rect( p, QSize(0, 0) ) { }
+ };
+
+ QPrinter *pr;
+ QPainter p;
+ QFont f8;
+ QFont f10;
+ QFontMetrics *fmetrics;
+ Rule nextRule;
+ Paragraph cp;
+ int page;
+ bool firstParagraph;
+ QString g;
+ QDateTime dateTime;
+
+ int hmargin;
+ int vmargin;
+ int voffset;
+ int hsize;
+ int vsize;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/linguist/recentfiles.cpp b/tools/linguist/linguist/recentfiles.cpp
new file mode 100644
index 0000000000..6fc72f7651
--- /dev/null
+++ b/tools/linguist/linguist/recentfiles.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "recentfiles.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
+#include <QtCore/QSettings>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+const QString &settingsPrefix();
+
+static QString configKey()
+{
+ return settingsPrefix() + QLatin1String("RecentlyOpenedFiles");
+}
+
+
+RecentFiles::RecentFiles(const int maxEntries)
+ : m_groupOpen(false),
+ m_clone1st(false),
+ m_maxEntries(maxEntries)
+{
+ m_timer.setSingleShot(true);
+ m_timer.setInterval(3 * 60 * 1000);
+ connect(&m_timer, SIGNAL(timeout()), SLOT(closeGroup()));
+}
+
+/*
+ * The logic is as follows:
+ * - The most recent (i.e., topmost) item can be open ("in flux")
+ * - The item is closed by either a timeout (3 min or so) or a
+ * "terminal action" (e.g., closing all files)
+ * - While the item is open, modifications to the set of open files
+ * will modify that item instead of creating new items
+ * - If the open item is modified to be equal to an existing item,
+ * the existing item is deleted, but will be re-created when the
+ * open item is modified even further
+ * Cases (actions in parentheses are no-ops):
+ * - identical to top item => (do nothing)
+ * - closed, new item => insert at top, (clear marker)
+ * - closed, existing item => move to top, mark for cloning
+ * - open, new item, not marked => replace top, (clear marker)
+ * - open, new item, marked => insert at top, clear marker
+ * - open, existing item, not marked => replace top, delete copy, mark for cloning
+ * - open, existing item, marked => insert at top, delete copy, (mark for cloning)
+ * - closing clears marker
+ */
+void RecentFiles::addFiles(const QStringList &names)
+{
+ if (m_strLists.isEmpty() || names != m_strLists.first()) {
+ if (m_groupOpen && !m_clone1st)
+ // Group being open implies at least one item in the list
+ m_strLists.removeFirst();
+ m_groupOpen = true;
+
+ // We do *not* sort the actual entries, as that would destroy the user's
+ // chosen arrangement. However, we do the searching on sorted lists, so
+ // we throw out (probably) obsolete arrangements.
+ QList<QStringList> sortedLists = m_strLists;
+ for (int i = 0; i < sortedLists.size(); ++i)
+ sortedLists[i].sort();
+ QStringList sortedNames = names;
+ sortedNames.sort();
+
+ int index = sortedLists.indexOf(sortedNames);
+ if (index >= 0) {
+ m_strLists.removeAt(index);
+ m_clone1st = true;
+ } else {
+ if (m_strLists.count() >= m_maxEntries)
+ m_strLists.removeLast();
+ m_clone1st = false;
+ }
+ m_strLists.prepend(names);
+ }
+ m_timer.start();
+}
+
+void RecentFiles::closeGroup()
+{
+ m_timer.stop();
+ m_groupOpen = false;
+}
+
+void RecentFiles::readConfig()
+{
+ m_strLists.clear();
+ QVariant val = QSettings().value(configKey());
+ if (val.type() == QVariant::StringList) // Backwards compat to Qt < 4.5
+ foreach (const QString &s, val.toStringList())
+ m_strLists << QStringList(QFileInfo(s).canonicalFilePath());
+ else
+ foreach (const QVariant &v, val.toList())
+ m_strLists << v.toStringList();
+}
+
+void RecentFiles::writeConfig() const
+{
+ QList<QVariant> vals;
+ foreach (const QStringList &sl, m_strLists)
+ vals << sl;
+ QSettings().setValue(configKey(), vals);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/recentfiles.h b/tools/linguist/linguist/recentfiles.h
new file mode 100644
index 0000000000..d0d25eb19b
--- /dev/null
+++ b/tools/linguist/linguist/recentfiles.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RECENTFILES_H
+#define RECENTFILES_H
+
+#include <QString>
+#include <QStringList>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class RecentFiles : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit RecentFiles(const int maxEntries);
+
+ bool isEmpty() { return m_strLists.isEmpty(); }
+ void addFiles(const QStringList &names);
+ QString lastOpenedFile() const {
+ if (m_strLists.isEmpty() || m_strLists.first().isEmpty())
+ return QString::null;
+ return m_strLists.at(0).at(0);
+ }
+ const QList<QStringList>& filesLists() const { return m_strLists; }
+
+ void readConfig();
+ void writeConfig() const;
+
+public slots:
+ void closeGroup();
+
+private:
+ bool m_groupOpen;
+ bool m_clone1st;
+ int m_maxEntries;
+ QList<QStringList> m_strLists;
+ QTimer m_timer;
+};
+
+QT_END_NAMESPACE
+
+#endif // RECENTFILES_H
diff --git a/tools/linguist/linguist/sourcecodeview.cpp b/tools/linguist/linguist/sourcecodeview.cpp
new file mode 100644
index 0000000000..c948d77d05
--- /dev/null
+++ b/tools/linguist/linguist/sourcecodeview.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "sourcecodeview.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextStream>
+
+#include <QtGui/QTextCharFormat>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+
+QT_BEGIN_NAMESPACE
+
+SourceCodeView::SourceCodeView(QWidget *parent)
+ : QPlainTextEdit(parent),
+ m_isActive(true),
+ m_lineNumToLoad(0)
+{
+ setReadOnly(true);
+}
+
+void SourceCodeView::setSourceContext(const QString &fileName, const int lineNum)
+{
+ m_fileToLoad.clear();
+ setToolTip(fileName);
+
+ if (fileName.isNull()) {
+ clear();
+ m_currentFileName.clear();
+ appendHtml(tr("<i>Source code not available</i>"));
+ return;
+ }
+
+ if (m_isActive) {
+ showSourceCode(fileName, lineNum);
+ } else {
+ m_fileToLoad = fileName;
+ m_lineNumToLoad = lineNum;
+ }
+}
+
+void SourceCodeView::setActivated(bool activated)
+{
+ m_isActive = activated;
+ if (activated && !m_fileToLoad.isEmpty()) {
+ showSourceCode(m_fileToLoad, m_lineNumToLoad);
+ m_fileToLoad.clear();
+ }
+}
+
+void SourceCodeView::showSourceCode(const QString &absFileName, const int lineNum)
+{
+ QString fileText = fileHash.value(absFileName);
+
+ if (fileText.isNull()) { // File not in hash
+ m_currentFileName.clear();
+
+ // Assume fileName is relative to directory
+ QFile file(absFileName);
+
+ if (!file.exists()) {
+ clear();
+ appendHtml(tr("<i>File %1 not available</i>").arg(absFileName));
+ return;
+ }
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ clear();
+ appendHtml(tr("<i>File %1 not readable</i>").arg(absFileName));
+ return;
+ }
+ fileText = QString::fromLatin1(file.readAll());
+ fileHash.insert(absFileName, fileText);
+ }
+
+
+ if (m_currentFileName != absFileName) {
+ setPlainText(fileText);
+ m_currentFileName = absFileName;
+ }
+
+ QTextCursor cursor = textCursor();
+ cursor.setPosition(document()->findBlockByNumber(lineNum - 1).position());
+ setTextCursor(cursor);
+ centerCursor();
+ cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor);
+
+ QTextEdit::ExtraSelection selectedLine;
+ selectedLine.cursor = cursor;
+
+ // Define custom color for line selection
+ const QColor fg = palette().color(QPalette::Highlight);
+ const QColor bg = palette().color(QPalette::Base);
+ QColor col;
+ const qreal ratio = 0.25;
+ col.setRedF(fg.redF() * ratio + bg.redF() * (1 - ratio));
+ col.setGreenF(fg.greenF() * ratio + bg.greenF() * (1 - ratio));
+ col.setBlueF(fg.blueF() * ratio + bg.blueF() * (1 - ratio));
+
+ selectedLine.format.setBackground(col);
+ selectedLine.format.setProperty(QTextFormat::FullWidthSelection, true);
+ setExtraSelections(QList<QTextEdit::ExtraSelection>() << selectedLine);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/sourcecodeview.h b/tools/linguist/linguist/sourcecodeview.h
new file mode 100644
index 0000000000..99a28c5331
--- /dev/null
+++ b/tools/linguist/linguist/sourcecodeview.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SOURCECODEVIEW_H
+#define SOURCECODEVIEW_H
+
+#include <QDir>
+#include <QHash>
+#include <QPlainTextEdit>
+
+QT_BEGIN_NAMESPACE
+
+class SourceCodeView : public QPlainTextEdit
+{
+ Q_OBJECT
+public:
+ SourceCodeView(QWidget *parent = 0);
+ void setSourceContext(const QString &fileName, const int lineNum);
+
+public slots:
+ void setActivated(bool activated);
+
+private:
+ void showSourceCode(const QString &fileName, const int lineNum);
+
+ bool m_isActive;
+ QString m_fileToLoad;
+ int m_lineNumToLoad;
+ QString m_currentFileName;
+
+ QHash<QString, QString> fileHash;
+};
+
+QT_END_NAMESPACE
+
+#endif // SOURCECODEVIEW_H
diff --git a/tools/linguist/linguist/statistics.cpp b/tools/linguist/linguist/statistics.cpp
new file mode 100644
index 0000000000..2cd197f077
--- /dev/null
+++ b/tools/linguist/linguist/statistics.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "statistics.h"
+
+QT_BEGIN_NAMESPACE
+
+Statistics::Statistics(QWidget* parent, Qt::WindowFlags fl)
+ : QDialog(parent, fl)
+{
+ setupUi(this);
+}
+
+void Statistics::languageChange()
+{
+ retranslateUi(this);
+}
+
+void Statistics::updateStats(int sW,int sC,int sCS,int trW,int trC,int trCS)
+{
+ untrWords->setText(QString::number(sW));
+ untrChars->setText(QString::number(sC));
+ untrCharsSpc->setText(QString::number(sCS));
+ trWords->setText(QString::number(trW));
+ trChars->setText(QString::number(trC));
+ trCharsSpc->setText(QString::number(trCS));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/statistics.h b/tools/linguist/linguist/statistics.h
new file mode 100644
index 0000000000..175f2e1d5d
--- /dev/null
+++ b/tools/linguist/linguist/statistics.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STATISTICS_H
+#define STATISTICS_H
+
+#include "ui_statistics.h"
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Statistics : public QDialog, public Ui::Statistics
+{
+ Q_OBJECT
+
+public:
+ Statistics(QWidget *parent = 0, Qt::WindowFlags fl = 0);
+ ~Statistics() {}
+
+public slots:
+ virtual void updateStats(int w1, int c1, int cs1, int w2, int c2, int cs2);
+
+protected slots:
+ virtual void languageChange();
+};
+
+QT_END_NAMESPACE
+
+#endif // STATISTICS_H
diff --git a/tools/linguist/linguist/statistics.ui b/tools/linguist/linguist/statistics.ui
new file mode 100644
index 0000000000..b7b2e04474
--- /dev/null
+++ b/tools/linguist/linguist/statistics.ui
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>Statistics</class>
+ <widget class="QDialog" name="linguist_stats">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>336</width>
+ <height>169</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Statistics</string>
+ </property>
+ <layout class="QGridLayout">
+ <item row="1" column="0">
+ <layout class="QHBoxLayout">
+ <item>
+ <spacer name="spacer4_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeBtn">
+ <property name="text">
+ <string>Close</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="spacer4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0">
+ <widget class="QFrame" name="frame4">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout">
+ <item row="0" column="2">
+ <widget class="QLabel" name="textLabel4">
+ <property name="text">
+ <string>Translation</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="textLabel5">
+ <property name="text">
+ <string>Source</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="untrWords">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="trWords">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="textLabel1">
+ <property name="text">
+ <string>Words:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="trChars">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="untrChars">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="textLabel3">
+ <property name="text">
+ <string>Characters:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="textLabel6">
+ <property name="text">
+ <string>Characters (with spaces):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QLabel" name="trCharsSpc">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="untrCharsSpc">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>closeBtn</sender>
+ <signal>clicked()</signal>
+ <receiver>linguist_stats</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>179</x>
+ <y>144</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>239</x>
+ <y>142</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/linguist/linguist/translatedialog.cpp b/tools/linguist/linguist/translatedialog.cpp
new file mode 100644
index 0000000000..537c364c3a
--- /dev/null
+++ b/tools/linguist/linguist/translatedialog.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translatedialog.h"
+
+QT_BEGIN_NAMESPACE
+
+TranslateDialog::TranslateDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ m_ui.setupUi(this);
+ connect(m_ui.findNxt, SIGNAL(clicked()), this, SLOT(emitFindNext()));
+ connect(m_ui.translate, SIGNAL(clicked()), this, SLOT(emitTranslateAndFindNext()));
+ connect(m_ui.translateAll, SIGNAL(clicked()), this, SLOT(emitTranslateAll()));
+ connect(m_ui.ledFindWhat, SIGNAL(textChanged(QString)), SLOT(verifyText()));
+ connect(m_ui.ckMatchCase, SIGNAL(toggled(bool)), SLOT(verifyText()));
+}
+
+void TranslateDialog::showEvent(QShowEvent *)
+{
+ verifyText();
+ m_ui.ledFindWhat->setFocus();
+}
+
+void TranslateDialog::verifyText()
+{
+ QString text = m_ui.ledFindWhat->text();
+ bool canFind = !text.isEmpty();
+ bool hit = false;
+ if (canFind)
+ emit requestMatchUpdate(hit);
+ m_ui.findNxt->setEnabled(canFind);
+ m_ui.translate->setEnabled(canFind && hit);
+ m_ui.translateAll->setEnabled(canFind);
+}
+
+void TranslateDialog::emitFindNext()
+{
+ emit activated(Skip);
+}
+
+void TranslateDialog::emitTranslateAndFindNext()
+{
+ emit activated(Translate);
+}
+
+void TranslateDialog::emitTranslateAll()
+{
+ emit activated(TranslateAll);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/translatedialog.h b/tools/linguist/linguist/translatedialog.h
new file mode 100644
index 0000000000..fbed2dfb43
--- /dev/null
+++ b/tools/linguist/linguist/translatedialog.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRANSLATEDIALOG_H
+#define TRANSLATEDIALOG_H
+
+#include "ui_translatedialog.h"
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class TranslateDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ enum {
+ Skip,
+ Translate,
+ TranslateAll
+ };
+
+ TranslateDialog(QWidget *parent = 0);
+
+ bool markFinished() const { return m_ui.ckMarkFinished->isChecked(); }
+ Qt::CaseSensitivity caseSensitivity() const
+ { return m_ui.ckMatchCase->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive; }
+ QString findText() const { return m_ui.ledFindWhat->text(); }
+ QString replaceText() const { return m_ui.ledTranslateTo->text(); }
+
+signals:
+ void requestMatchUpdate(bool &hit);
+ void activated(int mode);
+
+protected:
+ virtual void showEvent(QShowEvent *event);
+
+private slots:
+ void emitFindNext();
+ void emitTranslateAndFindNext();
+ void emitTranslateAll();
+ void verifyText();
+
+private:
+ Ui::TranslateDialog m_ui;
+};
+
+
+QT_END_NAMESPACE
+#endif //TRANSLATEDIALOG_H
+
diff --git a/tools/linguist/linguist/translatedialog.ui b/tools/linguist/linguist/translatedialog.ui
new file mode 100644
index 0000000000..89f21387ce
--- /dev/null
+++ b/tools/linguist/linguist/translatedialog.ui
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>TranslateDialog</class>
+ <widget class="QDialog" name="translateDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>407</width>
+ <height>174</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis">
+ <string>This window allows you to search for some text in the translation source file.</string>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <item>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="ledTranslateTo">
+ <property name="whatsThis">
+ <string>Type in the text to search for.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="findWhat">
+ <property name="text">
+ <string>Find &amp;source text:</string>
+ </property>
+ <property name="buddy">
+ <cstring>ledFindWhat</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="translateTo">
+ <property name="text">
+ <string>&amp;Translate to:</string>
+ </property>
+ <property name="buddy">
+ <cstring>ledTranslateTo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="ledFindWhat">
+ <property name="whatsThis">
+ <string>Type in the text to search for.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Search options</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QCheckBox" name="ckMatchCase">
+ <property name="whatsThis">
+ <string>Texts such as 'TeX' and 'tex' are considered as different when checked.</string>
+ </property>
+ <property name="text">
+ <string>Match &amp;case</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="ckMarkFinished">
+ <property name="text">
+ <string>Mark new translation as &amp;finished</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="findNxt">
+ <property name="whatsThis">
+ <string>Click here to find the next occurrence of the text you typed in.</string>
+ </property>
+ <property name="text">
+ <string>Find Next</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="translate">
+ <property name="text">
+ <string>Translate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="translateAll">
+ <property name="text">
+ <string>Translate All</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancel">
+ <property name="whatsThis">
+ <string>Click here to close this window.</string>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <tabstops>
+ <tabstop>ledFindWhat</tabstop>
+ <tabstop>ledTranslateTo</tabstop>
+ <tabstop>findNxt</tabstop>
+ <tabstop>translate</tabstop>
+ <tabstop>translateAll</tabstop>
+ <tabstop>cancel</tabstop>
+ <tabstop>ckMatchCase</tabstop>
+ <tabstop>ckMarkFinished</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>cancel</sender>
+ <signal>clicked()</signal>
+ <receiver>translateDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>360</x>
+ <y>132</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>357</x>
+ <y>151</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/linguist/linguist/translationsettings.ui b/tools/linguist/linguist/translationsettings.ui
new file mode 100644
index 0000000000..c868360e69
--- /dev/null
+++ b/tools/linguist/linguist/translationsettings.ui
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>TranslationSettingsDialog</class>
+ <widget class="QDialog" name="translationSettingsDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>416</width>
+ <height>263</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="srcGroupBox">
+ <property name="title">
+ <string>Source language</string>
+ </property>
+ <layout class="QGridLayout" name="_2">
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="srcCbLanguageList"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="srcLblLanguage">
+ <property name="text">
+ <string>Language</string>
+ </property>
+ <property name="buddy">
+ <cstring>tgtCbLanguageList</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="srcCbCountryList"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="srcLblCountry">
+ <property name="text">
+ <string>Country/Region</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="tgtGroupBox">
+ <property name="title">
+ <string>Target language</string>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>9</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="tgtCbLanguageList"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="tgtLblLanguage">
+ <property name="text">
+ <string>Language</string>
+ </property>
+ <property name="buddy">
+ <cstring>tgtCbLanguageList</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="tgtCbCountryList"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="tgtLblCountry">
+ <property name="text">
+ <string>Country/Region</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>100</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>translationSettingsDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>216</x>
+ <y>241</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>222</x>
+ <y>213</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/linguist/linguist/translationsettingsdialog.cpp b/tools/linguist/linguist/translationsettingsdialog.cpp
new file mode 100644
index 0000000000..32f5c58d50
--- /dev/null
+++ b/tools/linguist/linguist/translationsettingsdialog.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "translationsettingsdialog.h"
+#include "messagemodel.h"
+#include "phrase.h"
+
+#include <QtCore/QLocale>
+
+QT_BEGIN_NAMESPACE
+
+TranslationSettingsDialog::TranslationSettingsDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ m_ui.setupUi(this);
+
+ for (int i = QLocale::C + 1; i < QLocale::LastLanguage; ++i) {
+ QString lang = QLocale::languageToString(QLocale::Language(i));
+ m_ui.srcCbLanguageList->addItem(lang, QVariant(i));
+ }
+ m_ui.srcCbLanguageList->model()->sort(0, Qt::AscendingOrder);
+ m_ui.srcCbLanguageList->insertItem(0, QLatin1String("POSIX"), QVariant(QLocale::C));
+
+ for (int i = QLocale::AnyCountry + 1; i < QLocale::LastCountry; ++i) {
+ QString country = QLocale::countryToString(QLocale::Country(i));
+ m_ui.srcCbCountryList->addItem(country, QVariant(i));
+ }
+ m_ui.srcCbCountryList->model()->sort(0, Qt::AscendingOrder);
+ m_ui.srcCbCountryList->insertItem(0, tr("Any Country"), QVariant(QLocale::AnyCountry));
+
+ m_ui.tgtCbLanguageList->setModel(m_ui.srcCbLanguageList->model());
+ m_ui.tgtCbCountryList->setModel(m_ui.srcCbCountryList->model());
+}
+
+void TranslationSettingsDialog::setDataModel(DataModel *dataModel)
+{
+ m_dataModel = dataModel;
+ m_phraseBook = 0;
+ QString fn = QFileInfo(dataModel->srcFileName()).baseName();
+ setWindowTitle(tr("Settings for '%1' - Qt Linguist").arg(fn));
+}
+
+void TranslationSettingsDialog::setPhraseBook(PhraseBook *phraseBook)
+{
+ m_phraseBook = phraseBook;
+ m_dataModel = 0;
+ QString fn = QFileInfo(phraseBook->fileName()).baseName();
+ setWindowTitle(tr("Settings for '%1' - Qt Linguist").arg(fn));
+}
+
+void TranslationSettingsDialog::on_buttonBox_accepted()
+{
+ int itemindex = m_ui.tgtCbLanguageList->currentIndex();
+ QVariant var = m_ui.tgtCbLanguageList->itemData(itemindex);
+ QLocale::Language lang = QLocale::Language(var.toInt());
+
+ itemindex = m_ui.tgtCbCountryList->currentIndex();
+ var = m_ui.tgtCbCountryList->itemData(itemindex);
+ QLocale::Country country = QLocale::Country(var.toInt());
+
+ itemindex = m_ui.srcCbLanguageList->currentIndex();
+ var = m_ui.srcCbLanguageList->itemData(itemindex);
+ QLocale::Language lang2 = QLocale::Language(var.toInt());
+
+ itemindex = m_ui.srcCbCountryList->currentIndex();
+ var = m_ui.srcCbCountryList->itemData(itemindex);
+ QLocale::Country country2 = QLocale::Country(var.toInt());
+
+ if (m_phraseBook) {
+ m_phraseBook->setLanguageAndCountry(lang, country);
+ m_phraseBook->setSourceLanguageAndCountry(lang2, country2);
+ } else {
+ m_dataModel->setLanguageAndCountry(lang, country);
+ m_dataModel->setSourceLanguageAndCountry(lang2, country2);
+ }
+
+ accept();
+}
+
+void TranslationSettingsDialog::showEvent(QShowEvent *)
+{
+ QLocale::Language lang, lang2;
+ QLocale::Country country, country2;
+
+ if (m_phraseBook) {
+ lang = m_phraseBook->language();
+ country = m_phraseBook->country();
+ lang2 = m_phraseBook->sourceLanguage();
+ country2 = m_phraseBook->sourceCountry();
+ } else {
+ lang = m_dataModel->language();
+ country = m_dataModel->country();
+ lang2 = m_dataModel->sourceLanguage();
+ country2 = m_dataModel->sourceCountry();
+ }
+
+ int itemindex = m_ui.tgtCbLanguageList->findData(QVariant(int(lang)));
+ m_ui.tgtCbLanguageList->setCurrentIndex(itemindex == -1 ? 0 : itemindex);
+
+ itemindex = m_ui.tgtCbCountryList->findData(QVariant(int(country)));
+ m_ui.tgtCbCountryList->setCurrentIndex(itemindex == -1 ? 0 : itemindex);
+
+ itemindex = m_ui.srcCbLanguageList->findData(QVariant(int(lang2)));
+ m_ui.srcCbLanguageList->setCurrentIndex(itemindex == -1 ? 0 : itemindex);
+
+ itemindex = m_ui.srcCbCountryList->findData(QVariant(int(country2)));
+ m_ui.srcCbCountryList->setCurrentIndex(itemindex == -1 ? 0 : itemindex);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/linguist/translationsettingsdialog.h b/tools/linguist/linguist/translationsettingsdialog.h
new file mode 100644
index 0000000000..8a633d9e1b
--- /dev/null
+++ b/tools/linguist/linguist/translationsettingsdialog.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRANSLATIONSETTINGSDIALOG_H
+#define TRANSLATIONSETTINGSDIALOG_H
+
+#include "ui_translationsettings.h"
+
+#include <QtCore/QLocale>
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class DataModel;
+class PhraseBook;
+
+class TranslationSettingsDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ TranslationSettingsDialog(QWidget *parent = 0);
+ void setDataModel(DataModel *model);
+ void setPhraseBook(PhraseBook *phraseBook);
+
+private:
+ virtual void showEvent(QShowEvent *e);
+
+private slots:
+ void on_buttonBox_accepted();
+
+private:
+ Ui::TranslationSettingsDialog m_ui;
+ DataModel *m_dataModel;
+ PhraseBook *m_phraseBook;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // TRANSLATIONSETTINGSDIALOG_H
diff --git a/tools/linguist/lrelease/lrelease.1 b/tools/linguist/lrelease/lrelease.1
new file mode 100644
index 0000000000..7e01d68bfd
--- /dev/null
+++ b/tools/linguist/lrelease/lrelease.1
@@ -0,0 +1,97 @@
+.TH lrelease 1 "18 October 2001" "Nokia Corporation and/or its subsidiary(-ies)" \" -*- nroff -*-
+.\"
+.\" Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+\" Contact: Qt Software Information (qt-info@nokia.com)
+.\"
+.\" This file may be distributed and/or modified under the terms of the
+.\" GNU General Public License version 2 as published by the Free Software
+.\" Foundation and appearing in the file LICENSE.GPL included in the
+.\" packaging of this file.
+.\"
+.\" This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+.\" WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" See http://qtsoftware.com/gpl/ for GPL licensing information.
+.\"
+.\" Contact qt-info@nokia.com if any conditions of this licensing are
+.\" not clear to you.
+.\"
+.SH NAME
+lrelease \- generate Qt message files from Qt Linguist translation files
+.SH SYNOPSIS
+.B lrelease
+.RI "[ " options " ] " project-file
+.br
+.B lrelease
+.RI "[ " options " ] " ts-files " [ -qm " qm-file " ]"
+.SH DESCRIPTION
+This page documents the
+.B Qt Linguist Release
+tool for the Qt GUI toolkit.
+.B Lrelease
+reads a qmake/tmake project file (.pro file) and converts the
+translation files (.ts files) specified in it into Qt message files
+(.qm files) used by the application to translate.
+.PP
+The .qm file format is a compact binary format that provides
+extremely fast lookups for translations and that is used by Qt.
+.SH OPTIONS
+.TP
+.I "-help"
+Display the usage and exit.
+.TP
+.I "-compress"
+Compress the .qm files.
+.TP
+.I "-nounfinished"
+Do not include unfinished translations.
+.TP
+.I "-removeidentical"
+If the translated text is the same as
+the source text, do not include the message.
+.TP
+.I "-silent"
+Don't explain what is being done.
+.TP
+.I "-version"
+Display the version of
+.B lrelease
+and exit.
+.SH USAGE
+Here is an example .pro file that can be given to
+.B lrelease:
+.PP
+.in +4
+.nf
+HEADERS = funnydialog.h \\
+ wackywidget.h
+SOURCES = funnydialog.cpp \\
+ main.cpp \\
+ wackywidget.cpp
+FORMS = fancybox.ui
+TRANSLATIONS = gnomovision_dk.ts \\
+ gnomovision_fi.ts \\
+ gnomovision_no.ts \\
+ gnomovision_se.ts
+.fi
+.in -4
+.PP
+When running
+.B lrelease
+on this project file, the Qt message files gnomovision_dk.qm,
+gnomovision_fi.qm, gnomovision_no.qm and gnomovision_se.qm will be
+generated from gnomovision_dk.ts, gnomovision_fi.ts,
+gnomovision_no.ts and gnomovision_se.ts, respectively.
+.PP
+.B Lrelease
+can also be invoked with a list of .ts files to convert:
+.PP
+.in +4
+.nf
+lrelease gnomovision_*.ts
+.fi
+.in -4
+.SH "SEE ALSO"
+.BR lupdate (1)
+and
+.BR http://doc.trolltech.com/i18n.html
diff --git a/tools/linguist/lrelease/lrelease.pro b/tools/linguist/lrelease/lrelease.pro
new file mode 100644
index 0000000000..03ea0d036f
--- /dev/null
+++ b/tools/linguist/lrelease/lrelease.pro
@@ -0,0 +1,24 @@
+TEMPLATE = app
+TARGET = lrelease
+DESTDIR = ../../../bin
+
+QT -= gui
+
+CONFIG += qt warn_on console
+CONFIG -= app_bundle
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
+SOURCES += main.cpp
+
+include(../../../src/qt_professional.pri)
+include(../shared/formats.pri)
+include(../shared/proparser.pri)
+include(../shared/translatortools.pri)
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/tools/linguist/lrelease/main.cpp b/tools/linguist/lrelease/main.cpp
new file mode 100644
index 0000000000..f1fdb3af49
--- /dev/null
+++ b/tools/linguist/lrelease/main.cpp
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+#include "translatortools.h"
+#include "profileevaluator.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QRegExp>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QTextStream>
+#include <QtCore/QTranslator>
+
+static void printOut(const QString & out)
+{
+ QTextStream stream(stdout);
+ stream << out;
+}
+
+static void printUsage()
+{
+ printOut(QCoreApplication::tr(
+ "Usage:\n"
+ " lrelease [options] project-file\n"
+ " lrelease [options] ts-files [-qm qm-file]\n\n"
+ "lrelease is part of Qt's Linguist tool chain. It can be used as a\n"
+ "stand-alone tool to convert XML based translations files in the .ts\n"
+ "format into the 'compiled' .qm format used by QTranslator objects.\n\n"
+ "Options:\n"
+ " -help Display this information and exit\n"
+ " -compress\n"
+ " Compress the .qm files\n"
+ " -nounfinished\n"
+ " Do not include unfinished translations\n"
+ " -removeidentical\n"
+ " If the translated text is the same as\n"
+ " the source text, do not include the message\n"
+ " -silent\n"
+ " Don't explain what is being done\n"
+ " -version\n"
+ " Display the version of lrelease and exit\n"
+ ));
+}
+
+static bool loadTsFile(Translator &tor, const QString &tsFileName, bool /* verbose */)
+{
+ ConversionData cd;
+ bool ok = tor.load(tsFileName, cd, QLatin1String("auto"));
+ if (!ok) {
+ qWarning("lrelease error: %s\n", qPrintable(cd.error()));
+ } else {
+ if (!cd.errors().isEmpty())
+ printOut(cd.error());
+ const QList<TranslatorMessage> dupes = tor.findDuplicates();
+ if (!dupes.isEmpty()) {
+ qWarning("lrelease error: duplicate messages found in '%s':",
+ qPrintable(tsFileName));
+ foreach (const TranslatorMessage &msg, dupes) {
+ qWarning("\n* Context: %s\n* Source: %s",
+ qPrintable(msg.context()),
+ qPrintable(msg.sourceText()));
+ if (!msg.comment().isEmpty())
+ qWarning("\n* Comment: %s", qPrintable(msg.comment()));
+ }
+ ok = false;
+ }
+ }
+ return ok;
+}
+
+static bool releaseTranslator(Translator &tor, const QString &qmFileName,
+ bool verbose, bool ignoreUnfinished,
+ bool removeIdentical, TranslatorSaveMode mode)
+{
+ if (verbose)
+ printOut(QCoreApplication::tr( "Updating '%1'...\n").arg(qmFileName));
+ if (removeIdentical) {
+ if ( verbose )
+ printOut(QCoreApplication::tr( "Removing translations equal to source text in '%1'...\n").arg(qmFileName));
+ tor.stripIdenticalSourceTranslations();
+ }
+
+ QFile file(qmFileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ qWarning("lrelease error: cannot create '%s': %s\n",
+ qPrintable(qmFileName), qPrintable(file.errorString()));
+ return false;
+ }
+
+ ConversionData cd;
+ cd.m_verbose = verbose;
+ cd.m_ignoreUnfinished = ignoreUnfinished;
+ cd.m_saveMode = mode;
+ bool ok = tor.release(&file, cd);
+ file.close();
+
+ if (!ok) {
+ qWarning("lrelease error: cannot save '%s': %s\n",
+ qPrintable(qmFileName), qPrintable(cd.error()));
+ return false;
+ } else if (!cd.errors().isEmpty()) {
+ printOut(cd.error());
+ }
+ return true;
+}
+
+static bool releaseTsFile(const QString& tsFileName, bool verbose,
+ bool ignoreUnfinished, bool removeIdentical, TranslatorSaveMode mode)
+{
+ Translator tor;
+ if (!loadTsFile(tor, tsFileName, verbose))
+ return false;
+
+ QString qmFileName = tsFileName;
+ foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
+ if (qmFileName.endsWith(QLatin1Char('.') + fmt.extension)) {
+ qmFileName.chop(fmt.extension.length() + 1);
+ break;
+ }
+ }
+ qmFileName += QLatin1String(".qm");
+
+ return releaseTranslator(tor, qmFileName, verbose, ignoreUnfinished, removeIdentical, mode);
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ QStringList args = app.arguments();
+ QTranslator translator;
+ if (translator.load(QLatin1String("lrelease_") + QLocale::system().name()))
+ app.installTranslator(&translator);
+
+ bool verbose = true; // the default is true starting with Qt 4.2
+ bool ignoreUnfinished = false;
+ // the default mode is SaveEverything starting with Qt 4.2
+ TranslatorSaveMode mode = SaveEverything;
+ bool removeIdentical = false;
+ Translator tor;
+ QString outputFile;
+ int numFiles = 0;
+
+ for (int i = 1; i < argc; ++i) {
+ if (args[i] == QLatin1String("-compress")) {
+ mode = SaveStripped;
+ continue;
+ } else if (args[i] == QLatin1String("-nocompress")) {
+ mode = SaveEverything;
+ continue;
+ } else if (args[i] == QLatin1String("-removeidentical")) {
+ removeIdentical = true;
+ continue;
+ } else if (args[i] == QLatin1String("-nounfinished")) {
+ ignoreUnfinished = true;
+ continue;
+ } else if (args[i] == QLatin1String("-silent")) {
+ verbose = false;
+ continue;
+ } else if (args[i] == QLatin1String("-verbose")) {
+ verbose = true;
+ continue;
+ } else if (args[i] == QLatin1String("-version")) {
+ printOut(QCoreApplication::tr( "lrelease version %1\n").arg(QLatin1String(QT_VERSION_STR)) );
+ return 0;
+ } else if (args[i] == QLatin1String("-qm")) {
+ if (i == argc - 1) {
+ printUsage();
+ return 1;
+ }
+ i++;
+ outputFile = args[i];
+ } else if (args[i] == QLatin1String("-help")) {
+ printUsage();
+ return 0;
+ } else if (args[i][0] == QLatin1Char('-')) {
+ printUsage();
+ return 1;
+ } else {
+ numFiles++;
+ }
+ }
+
+ if (numFiles == 0) {
+ printUsage();
+ return 1;
+ }
+
+ for (int i = 1; i < argc; ++i) {
+ if (args[i][0] == QLatin1Char('-') || args[i] == outputFile)
+ continue;
+
+ if (args[i].endsWith(QLatin1String(".pro"), Qt::CaseInsensitive)
+ || args[i].endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
+ QHash<QByteArray, QStringList> varMap;
+ bool ok = evaluateProFile(args[i], verbose, &varMap );
+ if (ok) {
+ QStringList translations = varMap.value("TRANSLATIONS");
+ if (translations.isEmpty()) {
+ qWarning("lrelease warning: Met no 'TRANSLATIONS' entry in"
+ " project file '%s'\n",
+ qPrintable(args[i]));
+ } else {
+ foreach (const QString &trans, translations)
+ if (!releaseTsFile(trans, verbose, ignoreUnfinished, removeIdentical, mode))
+ return 1;
+ }
+ } else {
+ qWarning("error: lrelease encountered project file functionality that is currently not supported.\n"
+ "You might want to consider using .ts files as input instead of a project file.\n"
+ "Try the following syntax:\n"
+ " lrelease [options] ts-files [-qm qm-file]\n");
+ }
+ } else {
+ if (outputFile.isEmpty()) {
+ if (!releaseTsFile(args[i], verbose, ignoreUnfinished, removeIdentical, mode))
+ return 1;
+ } else {
+ if (!loadTsFile(tor, args[i], verbose))
+ return 1;
+ }
+ }
+ }
+
+ if (!outputFile.isEmpty())
+ return releaseTranslator(tor, outputFile, verbose, ignoreUnfinished,
+ removeIdentical, mode) ? 0 : 1;
+
+ return 0;
+}
diff --git a/tools/linguist/lupdate/lupdate.1 b/tools/linguist/lupdate/lupdate.1
new file mode 100644
index 0000000000..e953273a9d
--- /dev/null
+++ b/tools/linguist/lupdate/lupdate.1
@@ -0,0 +1,132 @@
+.TH lupdate 1 "18 October 2001" "Nokia Corporation and/or its subsidiary(-ies)" \" -*- nroff -*-
+.\"
+.\" Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+.\" Contact: Qt Software Information (qt-info@nokia.com)
+.\"
+.\" This file may be distributed and/or modified under the terms of the
+.\" GNU General Public License version 2 as published by the Free Software
+.\" Foundation and appearing in the file LICENSE.GPL included in the
+.\" packaging of this file.
+.\"
+.\" This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+.\" WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" See http://qtsoftware.com/gpl/ for GPL licensing information.
+.\"
+.\" Contact qt-info@nokia.com if any conditions of this licensing are
+.\" not clear to you.
+.\"
+.SH NAME
+lupdate \- update Qt Linguist translation files
+.SH SYNOPSIS
+.B lupdate
+.RI "[ " options " ] " project-file
+.br
+.B lupdate
+.RI "[ " options " ] " source-files " -ts " ts-files
+.SH DESCRIPTION
+This page documents the
+.B Qt Linguist Update
+tool for the Qt GUI toolkit.
+.B Lupdate
+reads a qmake/tmake project file (.pro file), finds the translatable
+strings in the specified source, header and interface files, and
+updates the translation files (.ts files) specified in it. The
+translation files are given to the translator who uses
+.B Qt Linguist
+to read the files and insert the translations.
+.PP
+The .ts file format is a simple human-readable XML format that can be
+used with version control systems if required.
+.PP
+.SH OPTIONS
+.TP
+.I "-disable-heuristic {sametext|similartext|number}"
+Disable the named merge heuristic. Can be specified multiple times.
+.TP
+.I "-extensions <ext>[,<ext>...]"
+Process files with the given extensions only.
+The extension list must be separated with commas, not with whitespace.
+Default: 'ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx'.
+.TP
+.I "-help"
+Display the usage and exit.
+.TP
+.I "-locations {absolute|relative|none}"
+Specify/override how source code references are saved in ts files.
+Default is absolute.
+.TP
+.I "-no-obsolete"
+Drop all obsolete strings.
+.TP
+.I "-no-recursive"
+Do not recursively scan the following directories.
+.TP
+.I "-no-sort"
+Do not sort contexts in .ts files.
+.TP
+.I "-pluralonly"
+Only include plural form messages.
+.TP
+.I "-pro <filename>"
+Name of a .pro file. Useful for files with .pro
+file syntax but different file suffix
+.TP
+.I "-recursive"
+Recursively scan the following directories.
+.TP
+.I "-silent"
+Don't explain what is being done.
+.TP
+.I "-source-language <language>[_<region>]"
+Specify/override the language of the source strings. Defaults to
+POSIX if not specified and the file does not name it yet.
+.TP
+.I "-target-language <language>[_<region>]"
+Specify/override the language of the translation.
+The target language is guessed from the file name if this option
+is not specified and the file contents name no language yet.
+.I "-version"
+Display the version of
+.B lupdate
+and exit.
+.SH USAGE
+Here is an example .pro file that can be given to
+.B lupdate:
+.PP
+.in +4
+.nf
+HEADERS = funnydialog.h \\
+ wackywidget.h
+SOURCES = funnydialog.cpp \\
+ main.cpp \\
+ wackywidget.cpp
+FORMS = fancybox.ui
+TRANSLATIONS = gnomovision_dk.ts \\
+ gnomovision_fi.ts \\
+ gnomovision_no.ts \\
+ gnomovision_se.ts
+.fi
+.in -4
+.PP
+When running
+.B lupdate
+on this project file, the translatable strings in all the files
+listed in the HEADERS, SOURCES and FORMS entries will be put in
+the translation files listed in the TRANSLATIONS entry. Previous
+translations will be reused as far as possible, and translated
+strings that have vanished from the source files are marked obsolete.
+.PP
+.B lupdate
+can also be invoked with a list of C++ source files, .ui files
+and .ts files:
+.PP
+.in +4
+.nf
+lupdate *.cpp *.h *.ui -ts gnomovision_dk.ts
+.fi
+.in -4
+.SH "SEE ALSO"
+.BR lrelease (1)
+and
+.BR http://doc.trolltech.com/i18n.html
diff --git a/tools/linguist/lupdate/lupdate.exe.manifest b/tools/linguist/lupdate/lupdate.exe.manifest
new file mode 100644
index 0000000000..e0b2f734a1
--- /dev/null
+++ b/tools/linguist/lupdate/lupdate.exe.manifest
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
+ manifestVersion="1.0">
+ <!-- Make sure Vista UAC does not believe lupdate is an installer -->
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel
+ level="asInvoker"
+ uiAccess="false"/>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+</assembly> \ No newline at end of file
diff --git a/tools/linguist/lupdate/lupdate.pro b/tools/linguist/lupdate/lupdate.pro
new file mode 100644
index 0000000000..b05a4efcab
--- /dev/null
+++ b/tools/linguist/lupdate/lupdate.pro
@@ -0,0 +1,34 @@
+TEMPLATE = app
+TARGET = lupdate
+DESTDIR = ../../../bin
+
+QT -= gui
+
+CONFIG += qt warn_on console
+CONFIG -= app_bundle
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+include(../shared/formats.pri)
+include(../shared/proparser.pri)
+include(../shared/translatortools.pri)
+
+SOURCES += main.cpp
+
+DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
+
+
+win32:RC_FILE = winmanifest.rc
+
+embed_manifest_exe:win32-msvc2005 {
+ # The default configuration embed_manifest_exe overrides the manifest file
+ # already embedded via RC_FILE. Vs2008 already have the necessary manifest entry
+ QMAKE_POST_LINK += $$quote(mt.exe -updateresource:$$DESTDIR/lupdate.exe -manifest \"$${PWD}\\lupdate.exe.manifest\")
+}
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp
new file mode 100644
index 0000000000..e7865d5858
--- /dev/null
+++ b/tools/linguist/lupdate/main.cpp
@@ -0,0 +1,513 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+#include "translatortools.h"
+#include "profileevaluator.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QTextCodec>
+
+static QString m_defaultExtensions;
+
+static void printOut(const QString & out)
+{
+ qWarning("%s", qPrintable(out));
+}
+
+static void recursiveFileInfoList(const QDir &dir,
+ const QStringList &nameFilters, QDir::Filters filter, bool recursive,
+ QFileInfoList *fileinfolist)
+{
+ if (recursive)
+ filter |= QDir::AllDirs;
+ QFileInfoList entries = dir.entryInfoList(nameFilters, filter);
+
+ QFileInfoList::iterator it;
+ for (it = entries.begin(); it != entries.end(); ++it) {
+ QString fname = it->fileName();
+ if (fname != QLatin1String(".") && fname != QLatin1String("..")) {
+ if (it->isDir())
+ recursiveFileInfoList(QDir(it->absoluteFilePath()), nameFilters, filter, recursive, fileinfolist);
+ else
+ fileinfolist->append(*it);
+ }
+ }
+}
+
+static void printUsage()
+{
+ printOut(QObject::tr(
+ "Usage:\n"
+ " lupdate [options] [project-file]\n"
+ " lupdate [options] [source-file|path]... -ts ts-files\n\n"
+ "lupdate is part of Qt's Linguist tool chain. It can be used as a\n"
+ "stand-alone tool to create XML based translations files in the .ts\n"
+ "format from translatable messages in C++ and Java source code.\n\n"
+ "lupdate can also merge such messages into existing .ts files.\n\n"
+ "Options:\n"
+ " -help Display this information and exit.\n"
+ " -no-obsolete\n"
+ " Drop all obsolete strings.\n"
+ " -extensions <ext>[,<ext>]...\n"
+ " Process files with the given extensions only.\n"
+ " The extension list must be separated with commas, not with whitespace.\n"
+ " Default: '%1'.\n"
+ " -pluralonly\n"
+ " Only include plural form messages.\n"
+ " -silent\n"
+ " Do not explain what is being done.\n"
+ " -no-sort\n"
+ " Do not sort contexts in .ts files.\n"
+ " -no-recursive\n"
+ " Do not recursively scan the following directories.\n"
+ " -recursive\n"
+ " Recursively scan the following directories.\n"
+ " -locations {absolute|relative|none}\n"
+ " Specify/override how source code references are saved in ts files.\n"
+ " Default is absolute.\n"
+ " -no-ui-lines\n"
+ " Do not record line numbers in references to .ui files.\n"
+ " -disable-heuristic {sametext|similartext|number}\n"
+ " Disable the named merge heuristic. Can be specified multiple times.\n"
+ " -pro <filename>\n"
+ " Name of a .pro file. Useful for files with .pro\n"
+ " file syntax but different file suffix\n"
+ " -source-language <language>[_<region>]\n"
+ " Specify/override the language of the source strings. Defaults to\n"
+ " POSIX if not specified and the file does not name it yet.\n"
+ " -target-language <language>[_<region>]\n"
+ " Specify/override the language of the translation.\n"
+ " The target language is guessed from the file name if this option\n"
+ " is not specified and the file contents name no language yet.\n"
+ " -version\n"
+ " Display the version of lupdate and exit.\n"
+ ).arg(m_defaultExtensions));
+}
+
+static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFileNames,
+ const QByteArray &codecForTr, const QString &sourceLanguage, const QString &targetLanguage,
+ UpdateOptions options, bool *fail)
+{
+ QDir dir;
+ QString err;
+ foreach (const QString &fileName, tsFileNames) {
+ QString fn = dir.relativeFilePath(fileName);
+ ConversionData cd;
+ Translator tor;
+ cd.m_sortContexts = !(options & NoSort);
+ if (QFile(fileName).exists()) {
+ if (!tor.load(fileName, cd, QLatin1String("auto"))) {
+ printOut(cd.error());
+ *fail = true;
+ continue;
+ }
+ cd.clearErrors();
+ if (!codecForTr.isEmpty() && codecForTr != tor.codecName())
+ qWarning("lupdate warning: Codec for tr() '%s' disagrees with "
+ "existing file's codec '%s'. Expect trouble.",
+ codecForTr.constData(), tor.codecName().constData());
+ if (!targetLanguage.isEmpty() && targetLanguage != tor.languageCode())
+ qWarning("lupdate warning: Specified target language '%s' disagrees with "
+ "existing file's language '%s'. Ignoring.",
+ qPrintable(targetLanguage), qPrintable(tor.languageCode()));
+ if (!sourceLanguage.isEmpty() && sourceLanguage != tor.sourceLanguageCode())
+ qWarning("lupdate warning: Specified source language '%s' disagrees with "
+ "existing file's language '%s'. Ignoring.",
+ qPrintable(sourceLanguage), qPrintable(tor.sourceLanguageCode()));
+ } else {
+ if (!codecForTr.isEmpty())
+ tor.setCodecName(codecForTr);
+ if (!targetLanguage.isEmpty())
+ tor.setLanguageCode(targetLanguage);
+ if (!sourceLanguage.isEmpty())
+ tor.setSourceLanguageCode(sourceLanguage);
+ }
+ tor.makeFileNamesAbsolute(QFileInfo(fileName).absoluteDir());
+ if (options & NoLocations)
+ tor.setLocationsType(Translator::NoLocations);
+ else if (options & RelativeLocations)
+ tor.setLocationsType(Translator::RelativeLocations);
+ else if (options & AbsoluteLocations)
+ tor.setLocationsType(Translator::AbsoluteLocations);
+ if (options & Verbose)
+ printOut(QObject::tr("Updating '%1'...\n").arg(fn));
+
+ if (tor.locationsType() == Translator::NoLocations) // Could be set from file
+ options |= NoLocations;
+ Translator out = merge(tor, fetchedTor, options, err);
+ if (!codecForTr.isEmpty())
+ out.setCodecName(codecForTr);
+
+ if ((options & Verbose) && !err.isEmpty()) {
+ printOut(err);
+ err.clear();
+ }
+ if (options & PluralOnly) {
+ if (options & Verbose)
+ printOut(QObject::tr("Stripping non plural forms in '%1'...\n").arg(fn));
+ out.stripNonPluralForms();
+ }
+ if (options & NoObsolete)
+ out.stripObsoleteMessages();
+ out.stripEmptyContexts();
+
+ if (!out.save(fileName, cd, QLatin1String("auto"))) {
+ printOut(cd.error());
+ *fail = true;
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ m_defaultExtensions = QLatin1String("ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx");
+
+ QStringList args = app.arguments();
+ QString defaultContext; // This was QLatin1String("@default") before.
+ Translator fetchedTor;
+ QByteArray codecForTr;
+ QByteArray codecForSource;
+ QStringList tsFileNames;
+ QStringList proFiles;
+ QStringList sourceFiles;
+ QString targetLanguage;
+ QString sourceLanguage;
+
+ UpdateOptions options =
+ Verbose | // verbose is on by default starting with Qt 4.2
+ HeuristicSameText | HeuristicSimilarText | HeuristicNumber;
+ int numFiles = 0;
+ bool standardSyntax = true;
+ bool metTsFlag = false;
+ bool recursiveScan = true;
+
+ QString extensions = m_defaultExtensions;
+ QStringList extensionsNameFilters;
+
+ for (int i = 1; i < argc; ++i) {
+ if (args.at(i) == QLatin1String("-ts"))
+ standardSyntax = false;
+ }
+
+ for (int i = 1; i < argc; ++i) {
+ QString arg = args.at(i);
+ if (arg == QLatin1String("-help")
+ || arg == QLatin1String("--help")
+ || arg == QLatin1String("-h")) {
+ printUsage();
+ return 0;
+ } else if (arg == QLatin1String("-pluralonly")) {
+ options |= PluralOnly;
+ continue;
+ } else if (arg == QLatin1String("-noobsolete")
+ || arg == QLatin1String("-no-obsolete")) {
+ options |= NoObsolete;
+ continue;
+ } else if (arg == QLatin1String("-silent")) {
+ options &= ~Verbose;
+ continue;
+ } else if (arg == QLatin1String("-target-language")) {
+ ++i;
+ if (i == argc) {
+ qWarning("The option -target-language requires a parameter.");
+ return 1;
+ }
+ targetLanguage = args[i];
+ continue;
+ } else if (arg == QLatin1String("-source-language")) {
+ ++i;
+ if (i == argc) {
+ qWarning("The option -source-language requires a parameter.");
+ return 1;
+ }
+ sourceLanguage = args[i];
+ continue;
+ } else if (arg == QLatin1String("-disable-heuristic")) {
+ ++i;
+ if (i == argc) {
+ qWarning("The option -disable-heuristic requires a parameter.");
+ return 1;
+ }
+ arg = args[i];
+ if (arg == QLatin1String("sametext")) {
+ options &= ~HeuristicSameText;
+ } else if (arg == QLatin1String("similartext")) {
+ options &= ~HeuristicSimilarText;
+ } else if (arg == QLatin1String("number")) {
+ options &= ~HeuristicNumber;
+ } else {
+ qWarning("Invalid heuristic name passed to -disable-heuristic.");
+ return 1;
+ }
+ continue;
+ } else if (arg == QLatin1String("-locations")) {
+ ++i;
+ if (i == argc) {
+ qWarning("The option -locations requires a parameter.");
+ return 1;
+ }
+ if (args[i] == QLatin1String("none")) {
+ options |= NoLocations;
+ } else if (args[i] == QLatin1String("relative")) {
+ options |= RelativeLocations;
+ } else if (args[i] == QLatin1String("absolute")) {
+ options |= AbsoluteLocations;
+ } else {
+ qWarning("Invalid parameter passed to -locations.");
+ return 1;
+ }
+ continue;
+ } else if (arg == QLatin1String("-no-ui-lines")) {
+ options |= NoUiLines;
+ continue;
+ } else if (arg == QLatin1String("-verbose")) {
+ options |= Verbose;
+ continue;
+ } else if (arg == QLatin1String("-no-recursive")) {
+ recursiveScan = false;
+ continue;
+ } else if (arg == QLatin1String("-recursive")) {
+ recursiveScan = true;
+ continue;
+ } else if (arg == QLatin1String("-no-sort")
+ || arg == QLatin1String("-nosort")) {
+ options |= NoSort;
+ continue;
+ } else if (arg == QLatin1String("-version")) {
+ printOut(QObject::tr("lupdate version %1\n").arg(QLatin1String(QT_VERSION_STR)));
+ return 0;
+ } else if (arg == QLatin1String("-ts")) {
+ metTsFlag = true;
+ continue;
+ } else if (arg == QLatin1String("-extensions")) {
+ ++i;
+ if (i == argc) {
+ qWarning("The -extensions option should be followed by an extension list.");
+ return 1;
+ }
+ extensions = args[i];
+ continue;
+ } else if (arg == QLatin1String("-pro")) {
+ ++i;
+ if (i == argc) {
+ qWarning("The -pro option should be followed by a filename of .pro file.");
+ return 1;
+ }
+ proFiles += args[i];
+ numFiles++;
+ continue;
+ } else if (arg.startsWith(QLatin1String("-")) && arg != QLatin1String("-")) {
+ qWarning("Unrecognized option '%s'", qPrintable(arg));
+ return 1;
+ }
+
+ numFiles++;
+
+ QString fullText;
+
+ codecForTr.clear();
+ codecForSource.clear();
+
+ if (metTsFlag) {
+ bool found = false;
+ foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
+ if (arg.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive)) {
+ QFileInfo fi(arg);
+ if (!fi.exists() || fi.isWritable()) {
+ tsFileNames.append(QFileInfo(arg).absoluteFilePath());
+ } else {
+ qWarning("lupdate warning: For some reason, '%s' is not writable.\n",
+ qPrintable(arg));
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ qWarning("lupdate error: File '%s' has no recognized extension\n",
+ qPrintable(arg));
+ return 1;
+ }
+ } else if (arg.endsWith(QLatin1String(".pro"), Qt::CaseInsensitive)
+ || arg.endsWith(QLatin1String(".pri"), Qt::CaseInsensitive)) {
+ proFiles << arg;
+ } else {
+ QFileInfo fi(arg);
+ if (!fi.exists()) {
+ qWarning("lupdate error: File '%s' does not exists\n", qPrintable(arg));
+ return 1;
+ } else if (fi.isDir()) {
+ if (options & Verbose)
+ printOut(QObject::tr("Scanning directory '%1'...").arg(arg));
+ QDir dir = QDir(fi.filePath());
+ if (extensionsNameFilters.isEmpty()) {
+ extensions = extensions.trimmed();
+ // Remove the potential dot in front of each extension
+ if (extensions.startsWith(QLatin1Char('.')))
+ extensions.remove(0,1);
+ extensions.replace(QLatin1String(",."), QLatin1String(","));
+
+ extensions.insert(0, QLatin1String("*."));
+ extensions.replace(QLatin1Char(','), QLatin1String(",*."));
+ extensionsNameFilters = extensions.split(QLatin1Char(','));
+ }
+ QDir::Filters filters = QDir::Files | QDir::NoSymLinks;
+ QFileInfoList fileinfolist;
+ recursiveFileInfoList(dir, extensionsNameFilters, filters,
+ recursiveScan, &fileinfolist);
+ QFileInfoList::iterator ii;
+ QString fn;
+ for (ii = fileinfolist.begin(); ii != fileinfolist.end(); ++ii) {
+ // Make sure the path separator is stored with '/' in the ts file
+ sourceFiles << ii->canonicalFilePath().replace(QLatin1Char('\\'), QLatin1Char('/'));
+ }
+ } else {
+ sourceFiles << fi.canonicalFilePath().replace(QLatin1Char('\\'), QLatin1Char('/'));
+ }
+ }
+ } // for args
+
+
+ bool firstPass = true;
+ bool fail = false;
+ while (firstPass || !proFiles.isEmpty()) {
+ ConversionData cd;
+ cd.m_defaultContext = defaultContext;
+ cd.m_noUiLines = options & NoUiLines;
+
+ QStringList tsFiles = tsFileNames;
+ if (proFiles.count() > 0) {
+ QFileInfo pfi(proFiles.takeFirst());
+ QHash<QByteArray, QStringList> variables;
+
+ ProFileEvaluator visitor;
+ visitor.setVerbose(options & Verbose);
+
+ ProFile pro(pfi.absoluteFilePath());
+ if (!visitor.queryProFile(&pro))
+ return 2;
+ if (!visitor.accept(&pro))
+ return 2;
+
+ if (visitor.templateType() == ProFileEvaluator::TT_Subdirs) {
+ QDir proDir(pfi.absoluteDir());
+ foreach (const QString &subdir, visitor.values(QLatin1String("SUBDIRS"))) {
+ QString subPro = QDir::cleanPath(proDir.absoluteFilePath(subdir));
+ QFileInfo subInfo(subPro);
+ if (subInfo.isDir())
+ proFiles << (subPro + QLatin1Char('/')
+ + subInfo.fileName() + QLatin1String(".pro"));
+ else
+ proFiles << subPro;
+ }
+ continue;
+ }
+
+ evaluateProFile(visitor, &variables);
+
+ sourceFiles = variables.value("SOURCES");
+
+ QStringList tmp = variables.value("CODECFORTR");
+ if (!tmp.isEmpty() && !tmp.first().isEmpty()) {
+ codecForTr = tmp.first().toLatin1();
+ fetchedTor.setCodecName(codecForTr);
+ }
+ tmp = variables.value("CODECFORSRC");
+ if (!tmp.isEmpty() && !tmp.first().isEmpty()) {
+ codecForSource = tmp.first().toLatin1();
+ if (!QTextCodec::codecForName(codecForSource))
+ qWarning("lupdate warning: Codec for source '%s' is invalid. Falling back to codec for tr().",
+ codecForSource.constData());
+ else
+ cd.m_codecForSource = codecForSource;
+ }
+
+ tsFiles += variables.value("TRANSLATIONS");
+ }
+
+ for (QStringList::iterator it = sourceFiles.begin(); it != sourceFiles.end(); ++it) {
+ if (it->endsWith(QLatin1String(".java"), Qt::CaseInsensitive)) {
+ cd.m_sourceFileName = *it;
+ fetchedTor.load(*it, cd, QLatin1String("java"));
+ //fetchtr_java(*it, &fetchedTor, defaultContext, true, codecForSource);
+ }
+ else if (it->endsWith(QLatin1String(".ui"), Qt::CaseInsensitive)) {
+ fetchedTor.load(*it, cd, QLatin1String("ui"));
+ //fetchedTor.load(*it + QLatin1String(".h"), cd, QLatin1String("cpp"));
+ //fetchtr_ui(*it, &fetchedTor, defaultContext, true);
+ //fetchtr_cpp(*it + QLatin1String(".h"), &fetchedTor,
+ // defaultContext, false, codecForSource);
+ }
+ else if (it->endsWith(QLatin1String(".js"), Qt::CaseInsensitive)
+ || it->endsWith(QLatin1String(".qs"), Qt::CaseInsensitive)) {
+ fetchedTor.load(*it, cd, QLatin1String("js"));
+ } else {
+ fetchedTor.load(*it, cd, QLatin1String("cpp"));
+ //fetchtr_cpp(*it, &fetchedTor, defaultContext, true, codecForSource);
+ }
+ }
+ if (!cd.error().isEmpty())
+ printOut(cd.error());
+
+ tsFiles.sort();
+ tsFiles.removeDuplicates();
+
+ if (!tsFiles.isEmpty())
+ updateTsFiles(fetchedTor, tsFiles, codecForTr, sourceLanguage, targetLanguage, options, &fail);
+
+ firstPass = false;
+ }
+
+ if (numFiles == 0) {
+ printUsage();
+ return 1;
+ }
+
+ return fail ? 1 : 0;
+}
diff --git a/tools/linguist/lupdate/winmanifest.rc b/tools/linguist/lupdate/winmanifest.rc
new file mode 100644
index 0000000000..45c4935762
--- /dev/null
+++ b/tools/linguist/lupdate/winmanifest.rc
@@ -0,0 +1,4 @@
+#define RT_MANIFEST 24
+#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
+
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "lupdate.exe.manifest"
diff --git a/tools/linguist/phrasebooks/danish.qph b/tools/linguist/phrasebooks/danish.qph
new file mode 100644
index 0000000000..fb06e6f3cf
--- /dev/null
+++ b/tools/linguist/phrasebooks/danish.qph
@@ -0,0 +1,1018 @@
+<!DOCTYPE QPH><QPH language="da">
+<phrase>
+ <source>About</source>
+ <target>Om</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>hurtigtast</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>brugervenlighed</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>genvejshåndtag</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>aktiv</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>markeringsafslutning</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>aktivt objekt</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>aktivt vindue</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>værktøjselement</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Altid øverst</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>forankringspunkt</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Anvend</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>tekstboks med automatisk udgang</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>automatisk gentagelse</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>automatisk kæde</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>automatisk rulning</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>automatisk rulning</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Tilbage</target>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Gennemse</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Annuller</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>undermenu</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>afkrydsningsfelt</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>afkrydsning</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>underordnet vindue</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>vælge</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>klikke</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Udklipsholder</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Luk</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>lukknap</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>skjule</target>
+ <definition>outline/disposition</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>kolonneoverskrift</target>
+ <definition>control/kontrolelement</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>kombinationsboks</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>kommandoknap</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>objektbeholder</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>kontekstafhængig hjælp</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>kontekstafhængig</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>kontrolelement</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Kopier</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Kopier hertil</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Opret genvej</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Opret genvej her</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Klip</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>standard</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>standardknap</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Slet</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>skrivebord</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>destination</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>dialogboks</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>handicap</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>usammenhængende markering</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>forankre</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>dokument</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>dobbeltklikke</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>trække</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>trække og slippe</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>kombinationsboks med rullepil</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>rulleliste</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>rullemenu</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Rediger</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>Menuen Rediger</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>ellipse</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>integreret objekt</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Afslut</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>udvide</target>
+ <definition>an outline/en disposition</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Stifinder</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>udvidet markering</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>liste</target>
+ <definition>der tillader udvidet markering</definition>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>fil</target>
+</phrase>
+<phrase>
+ <source>File menu</source>
+ <target>Menuen Filer</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Søg</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Find næste</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Søg efter</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>mappe</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>skrifttype</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>skriftstørrelse</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>typografi</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>funktionstast</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>gruppeboks</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>håndtag</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Hjælp</target>
+</phrase>
+<phrase>
+ <source>Help menu</source>
+ <target>Menuen Hjælp</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Skjul</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>hierarkisk markering</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>holde nede</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>aktivt punkt</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>aktiv zone</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>ikon</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>ikke-aktiv</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>ikke-aktivt vindue</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>inputfokus</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>Menuen Indsæt</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Indsæt objekt</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>indsætningspunkt</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>kursiv</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>etiket</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>liggende</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>sammenkæde</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>kæde</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Indsæt kæde her</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>liste</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>listevisningsboks</target>
+ <definition>control/kontrolelement</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>manuel kæde</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Maksimer</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>maksimeringsknap</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>menu</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>menulinje</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>menuknap</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>menupunkt</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>menutitel</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>meddelelsesboks</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Minimer</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>minimeringsknap</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>blandet værdi</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>modal</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>tilstand</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>ikke-modal</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>ændringstast</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>mus</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Flyt</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Flyt hertil</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>multiple document interface</target>
+ <definition>MDI</definition>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>liste</target>
+ <definition>der tillader flere markeringer</definition>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Denne computer</target>
+ <definition>icon/ikon</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Andre computere</target>
+ <definition>icon/ikon</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Ny</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Næste</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>objekt</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>OLE-træk og slip</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>integreret OLE-objekt</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>sammenkædet OLE-objekt</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>interaktiv OLE-træk og slip</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Åbn</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Åbn med</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>alternativknap</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>aktiveret indstilling</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>objektpakke</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Sideopsætning</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>paletvindue</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>rude</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>overordnet vindue</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>adgangskode</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Sæt ind</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Indsæt kæde</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Indsæt genvej</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Indsæt speciel</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>sti</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Pause</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Afspil</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>punkt</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>pege</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>markør</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>pop-up-menu</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>pop-up-vindue</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>stående</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>trykke på</target>
+ <definition>and hold a mouse button/og holde en museknap nede</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>trykke på</target>
+ <definition>a key/en tast</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>primært destinationsobjekt</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>primært vindue</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Udskriv</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>printer</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>statusindikator</target>
+ <definition>control/kontrolelement</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>projekt</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Egenskaber</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>egenskabsfremviser</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>egenskabsside</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>egenskabsark</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>kontrolelement på egenskabsark</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Hurtig visning</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>skrivebeskyttet</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Papirkurv</target>
+ <definition>Icon/ikon</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Annuller Fortryd</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>områdemarkering</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>registreringsdatabase</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Gentag</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Erstat</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Gendan</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>gendannelsesknap</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Fortsæt</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Forsøg igen</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>tekstboks til formateret tekst</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Kør</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Gem</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Gem som</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>rulle</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>rullepil</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>rullepanel</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>rulleboks</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>sekundært vindue</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>markere</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>vælge</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Marker alt</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>det markerede</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>markeringshåndtag</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Overfør til</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>separator</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Indstillinger</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Indstillinger</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Installation</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>genvej</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>genvejsknap</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>genvejsikon</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>genvejstast</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>kontrolelement til genvejstast</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Vis</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Luk computeren</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>liste</target>
+ <definition>der kun tillader en enkelt markering</definition>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Tilpas størrelse</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>størrelseshåndtag</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>skala</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>rotationsboks</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Opdel</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>delelinje</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>deleboks</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>startknap</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>Startmappe</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>statuslinje</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Stop</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>fane</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>proceslinje</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>opgaveafhængig Hjælp</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>skabelon</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>tekstboks</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>titellinje</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>titeltekst</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>til/fra-tast</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>verktøjslinje</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>verktøjstip</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>træstruktur</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>skrive</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>type</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>ikke tilgængelig</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Fortryd</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Fjern installationen</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>Menuen Vis</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>lokal redigering</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>grafikpalet</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Hvad er det?</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>Menuen Vindue</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>vindue</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Windows Stifinder</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>guide</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>projektmappe</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>arbejdsgruppe</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>arbejdsområde</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Ja</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/dutch.qph b/tools/linguist/phrasebooks/dutch.qph
new file mode 100644
index 0000000000..f2db4e05fe
--- /dev/null
+++ b/tools/linguist/phrasebooks/dutch.qph
@@ -0,0 +1,1044 @@
+<!DOCTYPE QPH><QPH language="nl">
+<phrase>
+ <source>About</source>
+ <target>Info</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>toegangstoets</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>toegankelijkheid</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>bewerkingsgreep</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>actief</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>selecie-einde</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>actief object</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>actief venster</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>grafisch hulpmiddel</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Altijd op voorgrond</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>fixeerpunt</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Toepassen</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>automatisch verlaten</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>zich automatisch herhalen</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>automatisch herhalen</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>automatische koppeling</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>automatisch schuiven</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>automatisch schuiven</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Vorige</target>
+ <definition>wanneer het een logisch paar vormt met Volgende</definition>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Bladeren</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Annuleren</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>vervolgmenu</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>selectievakje</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>vinkje</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>subvenster</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>kiezen</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>klikken</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Klembord</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Sluiten</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>knop Sluiten</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>samenvouwen</target>
+ <definition>outline</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>kolomnaam</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>keuzelijst met invoervak</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>opdrachtknop</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>hoofdobject</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>contextafhankelijke Help</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>contextafhankelijk</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>besturingselement</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Kopiëren</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Hierheen kopiëren</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Snelkoppeling maken</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Hier snelkoppeling maken</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Knippen</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>standaard</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>standaardknop</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Verwijderen</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>bureaublad</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>doel</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>dialoogvenster</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>handicap</target>
+ <definition>voorzichtig in context, maar handicap niet verbloemen:VB: persoon met een handicap (beter dan gehandicapte)</definition>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>niet-aaneengesloten selectie</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>in werkbalkdok plaatsen</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>document</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>dubbelklikken</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>slepen</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>slepen en neerzetten</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>vervolgkeuzelijst met invoervak</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>vervolgkeuzelijst</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>menu</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Bewerken</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>menu Bewerken</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>puntjes</target>
+ <definition>(...)</definition>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>ingesloten object</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Afsluiten</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>uitvouwen</target>
+ <definition>an outline</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Verkennen</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>uitgebreide selectie</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>keuzelijst met uitgebreide selectie</target>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>bestand</target>
+</phrase>
+<phrase>
+ <source>File menu</source>
+ <target>menu Bestand</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Zoeken</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Volgende zoeken</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Zoeken naar</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>map</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>lettertype</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>tekengrootte</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>tekenstijl</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>functietoets</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>groepsvak</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>greep</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Help</target>
+</phrase>
+<phrase>
+ <source>Help menu</source>
+ <target>menu Help</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Verbergen</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>hiërarchische selectie</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>ingedrukt houden</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>selectiepunt</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>selectiegebied</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>pictogram</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>niet-actief</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>niet-actief venster</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>invoerfocus</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>menu Invoegen</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Object Invoegen</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>invoegpositie</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>cursief</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>label</target>
+ <definition>gender, Masc.: de</definition>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>liggend</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>koppeling</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>koppelen</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Hier koppeling maken</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>keuzelijst</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>weergaveknoppen</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>handmatige koppeling</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Maximaliseren</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>knop Maximaliseren</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>menu</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>menubalk</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>menuknop</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>opdracht</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>menunaam</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>berichtvak</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Minimaliseren</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>knop Minimaliseren</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>met gemengde waarden</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>modusgebonden</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>modi</target>
+ <definition>plural</definition>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>modus</target>
+ <definition>singular</definition>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>niet-modusgebonden</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>modificatietoets</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>muis</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Verplaatsen</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Hierheen verplaatsen</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>interface voor meerdere documenten</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>keuzelijst met meervoudige selectie</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Deze computer</target>
+ <definition>icon/pictogram</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Netwerkomgeving</target>
+ <definition>icon/pictogram</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Nieuw</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Volgende</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>object</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+ <definition>OLE (objecten koppelen en insluiten): voluit alleen in doc en Help</definition>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>slepen en neerzetten</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>slepen en neerzetten via OLE</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>ingesloten OLE-object</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>gekoppeld OLE-object</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>Aangepast slepen en neerzetten</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>Aangepast slepen en neerzetten via OLE</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Openen</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Openen met</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>keuzerondje</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>opties</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>OLE-pakket</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Pagina-instelling</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>paletvenster</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>deelvenster</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>hoofdvenster</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>wachtwoord</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Plakken</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Koppeling plakken</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Snelkoppeling plakken</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Plakken speciaal</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>pad</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Pauze</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Afspelen</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug en Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>aanwijzen</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>aanwijzer</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>pop-up-menu</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>pop-up-venster</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>staand</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>drukken op</target>
+ <definition>a key/een toets</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>ingedrukt houden</target>
+ <definition>and hold a mouse button/een muisknop</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>een muisknop ingedrukt houden</target>
+ <definition>and hold a mouse button</definition>
+</phrase>
+<phrase>
+ <source>press a mouse botton</source>
+ <target>een muisknop indrukken </target>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>primair hoofdobject</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>primair venster</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Afdrukken</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>printer</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>voortgangsindicator</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>project</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Eigenschappen</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>eigenschappenweergave</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>eigenschappenpagina</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>eigenschappenblad</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>besturingselement op een eigenschappenblad</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Snel weergeven</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>alleen-lezen</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Prullenbak</target>
+ <definition>Icon/pictogram</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Opnieuw</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>gebiedsselectie</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>het Register</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Herhalen</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Vervangen</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Vorig formaat</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>knop Vorig formaat</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Doorgaan</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Nogmaals</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>RTF-vak</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Uitvoeren</target>
+ <definition>Maar: macro starten</definition>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Opslaan</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Opslaan als</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>schuiven door</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>schuifpijl</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>schuifbalk</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>schuifblok</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>secundair venster</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>selecteren</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Alles selecteren</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>selectie</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>selectiegreep</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Kopiëren naar</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>scheidingsteken</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Instellingen</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Instellen</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Setup</target>
+ <definition>als het programma Setup wordt bedoeld</definition>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>snelkoppeling</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>snelkoppelingsknop</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>snelkoppelingspictogram</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>sneltoets</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>sneltoetsvak</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Weergeven</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Afsluiten</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>keuzelijst met enkelvoudige selectie</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Formaat wijzigen</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>formaatgreep</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>schuifregelaar</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>kringveld</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Splitsen</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>splitsbalk</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>splitsblokje</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>knop Start</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>map Opstarten</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>statusbalk</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Stoppen</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>tab</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>taakbalk</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>taakgeoriënteerde Help</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>sjabloon</target>
+ <definition>de</definition>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>tekstvak</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>titelbalk</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>venstertitel</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>wisseltoets</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>werkbalk</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>knopinfo</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>besturingselement voor structuurweergave</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>structuurweergave</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>typen</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>type</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>niet beschikbaar</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Ongedaan maken</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Installatie ongedaan maken</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>menu Beeld</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>direct bewerken</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>keuzelijst met grafische opties</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Wat is dit?</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>menu Venster</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>venster</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Windows Verkenner</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>wizard</target>
+ <definition>geen hoofdletter meer in lopende tekst</definition>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>werkmap</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>werkgroep</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>werkruimte</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Ja</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/finnish.qph b/tools/linguist/phrasebooks/finnish.qph
new file mode 100644
index 0000000000..caef1972fc
--- /dev/null
+++ b/tools/linguist/phrasebooks/finnish.qph
@@ -0,0 +1,1033 @@
+<!DOCTYPE QPH><QPH language="fi">
+<phrase>
+ <source>About</source>
+ <target>Tietoja</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>valintanäppäin</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>helppokäyttötoiminto</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>toimintokahva</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>aktiivinen</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>valinnan aktiivinen päätöskohta</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>aktiivinen objekti</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>aktiivinen ikkuna</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>graafinen lisäke</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Aina päällimmäisenä</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>ankkurikohta</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Käytä</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>automaattinen siirtyminen</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>automaattinen toisto</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>automaattinen linkki</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>automaattinen vieritys</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>automaattinen vieritys</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Takaisin</target>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Selaa</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Peruuta</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>alivalikko</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>valintaruutu</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>valintamerkki</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>ali-ikkuna</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>valita</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>napsautta</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Leikepöytä</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Sulje</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>sulkemispainike</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>tiivistää</target>
+ <definition>outline/jäsennys</definition>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>kutistaa</target>
+ <definition>outline/jäsennys</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>saraketunnus</target>
+ <definition>control/ohjausobjekti</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>sarakeotsikko</target>
+ <definition>control/ohjausobjekti</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>yhdistelmäruutu</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>painike</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>komento painike</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>säilö</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>tilannekohtainen ohje</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>tilannekohtainen</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>ohjausobjekti</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Kopioi</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Kopioi tähän</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Luo pikakuvake</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Luo pikakuvake tähän</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Leikkaa</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>oletus</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>oletuspainike</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Poista</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>työpöytä</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>kohde</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>valintaikkuna</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>invaliditeetti</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>hajavalinta</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>telakoida</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>tiedosto</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>asiakirja</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>kaksoisnapsauttaa</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>vetää</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>vetää ja pudottaa</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>avattava yhdistelmäruutu</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>avattava luetteloruutu</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>avattava valikko</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Muokkaa</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>Muokkaa-valikko</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>kolme pistettä</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>upotettu objekti</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Lopeta</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>laajentaa</target>
+ <definition>an outline/jäsennys</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Selaa</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>laajennettu valinta</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>laajennettu valinta-luetteloruutu</target>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>tiedosto</target>
+</phrase>
+<phrase>
+ <source>File menu</source>
+ <target>Tiedosto-valikko</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Etsi</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Etsi seuraava</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Etsittävä</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>kansio</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>fontti</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>fonttikoko</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>fonttityyli</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>funktionäppäin</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>ryhmän kehys</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>kahva</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Ohje</target>
+</phrase>
+<phrase>
+ <source>Help menu</source>
+ <target>Ohje-valikko</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Piilota</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>hierarkkinen valinta</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>pitää painettuna</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>kohdepiste</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>kohdealue</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>kuvake</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>passiivinen</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>passiivinen ikkuna</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>syöttöalue</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>Lisää-valikko</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Lisää objekti</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>lisäyskohta</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>kursivoitu</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>otsikko</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>nimi</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>vaaka</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>linkki</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>linkittää</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Linkitä tähän</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>luetteloruutu</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>luettelonäyttö</target>
+ <definition>control/ohjausobjekti</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>manuaalinen linkki</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Suurenna</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>suurennuspainike</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>valikko</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>valikkorivi</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>valikkopainike</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>valikon vaihtoehto</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>valikon otsikko</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>sanomaruutu</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Pienennä</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>pienennyspainike</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>monitila</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>modaalinen</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>tila</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>ei-modaalinen</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>yhdistelmänäppäin</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>hiiri</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Siirrä</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Siirrä tähän</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>MDI-liittymä</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>monivalintainen luetteloruutu</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Oma tietokone</target>
+ <definition>icon/kuvake</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Verkkoympäristö</target>
+ <definition>icon/kuvake</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Uusi</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Seuraava</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>objekti</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>vedä ja pudota-OLE-toiminto</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>upotettu OLE-objekti</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>linkitetty OLE-objekti</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>käyttäjän määrittämä vedä ja pudota-OLE-toiminto</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Avaa</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Avaa sovelluksessa</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>valintanappi</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>valitsimen tila</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>pakkaus</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Sivun asetukset</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>valikoimaikkuna</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>ruutu</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>ylemmän tason ikkuna</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>salasana</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Liitä</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Liitä linkki</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Liitä pikakuvake</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Liitä määräten</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>polku</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Tauko</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Soita</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>piste</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>osoittaa</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>osoitin</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>pikavalikko</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>ponnahdusikkuna</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>pysty</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>painaa</target>
+ <definition>and hold a mouse button/ja pitää painettuna hiiripainiketta</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>painaa</target>
+ <definition>a key/näppäintä</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>ensisijainen säilö</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>ensisijainen ikkuna</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Tulosta</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>kirjoitin</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>tilanneilmaisin</target>
+ <definition>control/ohjausobjekti</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>projekti</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Ominaisuudet</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>ominaisuuksien tarkastelu</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>ominaisuusryhmä</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>ominaisuusikkuna</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>ominaisuusikkuna-ohjausobjekti</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Pikanäyttö</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>vain luku</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Roskakori</target>
+ <definition>Icon/kuvake</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Tee uudelleen</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>aluevalinta</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>rekisteri</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Toista</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Korvaa</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Palauta</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>palautuspainike</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Jatka</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Yritä uudelleen</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>monimuotoruutu</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Suorita</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Tallenna</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Tallenna nimellä</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>vierittää</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>vieritysnuoli</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>vierityspalkki</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>vieritysruutu</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>toissijainen ikkuna</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>valita</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Valitse kaikki</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>valinta</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>valintakahva</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Lähetä tiedosto</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>erotin</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Asetukset</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Asennus</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>pika-</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>pikapainike</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>pikakuvake</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>pikanäppäin</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>pikanäppäin-ohjausobjekti</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Näytä</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Sammuta</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>yksivalintainen luetteloruutu</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Muuta kokoa</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>koonmuuttokahva</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>liukusäädin</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>askellusruutu</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Jaa</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>jakopalkki</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>jakoruutu</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>Käynnistä-painike</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>Käynnistys-kansio</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>tilarivi</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Pysäytä</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>välilehti</target>
+ <definition>ohjausobjekti</definition>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>tehtäväpalkki</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>tehtäväohje</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>malli</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>muokkausruutu</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>otsikkorivi</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>otsikkoteksti</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>tilanvaihtonäppäin</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>työkalurivi</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>työkaluvihje</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>puunäyttö</target>
+ <definition>ohjausobjekti</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>tyyppi</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>laji</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>kirjoittaa</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>ei käytettävissä</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Kumoa</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Pura asennus</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>Näytä-valikko</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>visuaalinen muokkaus</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>graafisen valinnan ohjausobjekti</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Lisätietoja</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>Ikkuna-valikko</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>ikkuna</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Resurssienhallinta</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>ohjattu toiminto</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>työkirja</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>työryhmä</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>työtila</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Kyllä</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/french.qph b/tools/linguist/phrasebooks/french.qph
new file mode 100644
index 0000000000..f244013a4d
--- /dev/null
+++ b/tools/linguist/phrasebooks/french.qph
@@ -0,0 +1,1104 @@
+<!DOCTYPE QPH><QPH language="fr">
+<phrase>
+ <source>About</source>
+ <target>A propos</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>touche d&apos;accès rapide</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>accessibilité</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>handle d&apos;action</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>actif</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>active</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>point de fin de sélecion</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>objet actif</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>fenêtre activ</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>barre</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Toujours visible</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>point de début de sélection</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Appliquer</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>sortie automatique</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>répétition automatique</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>Liaison automatique</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>défilement automatique</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>défilement automatique</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Précédent</target>
+</phrase>
+<phrase>
+ <source>barrel button</source>
+ <target>Bouton du stylet</target>
+</phrase>
+<phrase>
+ <source>barrel-tap</source>
+ <target>toucher-maintenir enfoncé</target>
+</phrase>
+<phrase>
+ <source>boxed edit</source>
+ <target>édition contrôlée</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Parcourir</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Annuler</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>menu en cascade</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>case à cocher</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>coche</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>fenêtre enfant</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>choisir</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>cliquer sur</target>
+ <definition>verb, à l&apos;écran</definition>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>clic</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>cliquer le</target>
+ <definition>verb, bouton souris</definition>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Presse-papiers</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Fermer</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Fermeture</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>Fermer</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>réduire</target>
+ <definition>outline</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>en-tête de colonne</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>zone de liste modifiable</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>bouton de commande</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>conteneur</target>
+ <definition>d&apos;objets</definition>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>aide contextuelle</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>contextuelle</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>contextuel</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>contrôle</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Copier</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Copier ici</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Copier un raccourci</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Copier un raccourci ice</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Couper</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>par défaut</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>bouton par défaut</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Supprimer</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>bureau</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>destination</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>boîte de dialogue</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>incapacité</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>sélection d&apos;objets disjoints</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>aligner</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>document</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>cliquer deux fois</target>
+</phrase>
+<phrase>
+ <source>double-tap</source>
+ <target>toucher deux fois</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>faire glisser</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>glisser-déplacer</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>zone de liste déroulante modifiable</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>zone de liste déroulante fixe</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>menu déroulant</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Edition</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>modifier</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>points de suspension</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>objet incorporé</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Quitter</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>développer</target>
+ <definition>an outline</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Explorer</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>sélection étendue</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>zone de liste à sélection étendue</target>
+</phrase>
+<phrase>
+ <source>File</source>
+ <target>Fichier</target>
+ <definition>menu</definition>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>fichier</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Rechercher</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Suivant</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Rechercher</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>dossier</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>police</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>taille de police</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>style de police</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>touche de fonction</target>
+</phrase>
+<phrase>
+ <source>gesture</source>
+ <target>signe</target>
+</phrase>
+<phrase>
+ <source>glyph</source>
+ <target>glyphe</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>zone de groupe</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>handle</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>?</target>
+ <definition>menu</definition>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Aide</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Masquer</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>sélection hiérarchique</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>maintenir</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>point d&apos;impact</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>zone critique</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>icône</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>inactive</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>inactif</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>fenêtre inactive</target>
+</phrase>
+<phrase>
+ <source>ink</source>
+ <target>dessin à main levée</target>
+</phrase>
+<phrase>
+ <source>ink edit</source>
+ <target>éditeur de dissin à main levée</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>zone d&apos;interaction</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>Insertion</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Insérer un objet</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>point d&apos;insertion</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>italique</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>nom de volume</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>étiquette</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>paysage</target>
+</phrase>
+<phrase>
+ <source>lasso-tap</source>
+ <target>toucher lasso</target>
+</phrase>
+<phrase>
+ <source>lens</source>
+ <target>loupe</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>lier</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>liaison</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Lier ici</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>zone de liste</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>presentación de iconos </target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>Liste icônes</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>liaison manuelle</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Agrandissement</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>agrandir</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>menu</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>barre de menus</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>bouton de menus</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>élément de menu</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>titre de menu</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>boîte de message</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Réduction</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>réduire</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>valeurs multiples</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>modal</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>mode</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>non modal</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>touche de modification</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>souris</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Déplacement</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Transférer ici</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>Interface documents multiples</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>zone de liste à sélection multiple</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Poste de travail</target>
+ <definition>icon</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Voisinage réseau</target>
+ <definition>icon</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Nouveau</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Suivant</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>objet</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>glisser-déplacer OLE</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>Objet OLE incorporé</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>Objet OLE lié</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>glisser-déplacer OLE non standard</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Ouvrir</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Ouvrir avec</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>case d&apos;option</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>état des caractéristiques</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>ensemble</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Mise en page</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>palette</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>volet</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>fenêtre parent</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>mot de passe</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Coller</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Coller avec liaison</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Coller le raccourci</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Collage spécial</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>chemin</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Pause</target>
+</phrase>
+<phrase>
+ <source>pen</source>
+ <target>stylet</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Exécuter</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>point</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>amener le pointeur sur</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>pointeur</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>menu autonome</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>fenêtre autonome</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>portrait</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>appuyer</target>
+ <definition>and hold a mouse button/et maintenir enfoncé</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>appuyer</target>
+ <definition>a key/sur une touche</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>contenuer principale</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>fenêtre principale</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Imprimer</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>imprimante</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>indicateur d&apos;état</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>projet</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Propriétés</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>inspecteur de propriétés</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>page de propriétés</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>feuille de propriétés</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>feuille de propriétés</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Aperçu</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>en lecture seule</target>
+</phrase>
+<phrase>
+ <source>recognition</source>
+ <target>reconnaissance</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Corbeille</target>
+ <definition>Icon</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Annuler Annuler</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>sélection par zone</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>base des registres</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Répéter</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Remplacer</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Restauration</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>Restaurer</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Reprendre</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Essayer de nouveau</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>zone de texte RTF</target>
+ <definition>Rich Text Format</definition>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Exécuter</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Enregistrer</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Enregistrer sous</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>faire défiler</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>flèche de défilement</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>barre de défilement</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>curseur de défilement</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>fenêtre secondaire</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>sélectionner</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Tout sélectionner</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>sélection</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>handle de sélection</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Envoyer vers</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>séparateur</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Paramètres</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Installation</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>INSTALL</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>raccourci</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>raccourci</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>raccourci</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>touche de raccourci</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>touche de raccourci</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Afficher</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Arrêter l&apos;ordinateur</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>zone de liste à sélection unique</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Dimension</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>poignée de redimensionnement</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>défileur</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>compteur</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Fractionner</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>barre de fractionnement</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>curseur de fractionnement</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>Démarrer</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>dossier de démarrage</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>barre d&apos;état</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Arrêter</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>onglet</target>
+</phrase>
+<phrase>
+ <source>tap</source>
+ <target>toucher</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>barre des tâches</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>aide spécifique aux tâches</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>modèle</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>zone de texte</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>barre de titre</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>texte de la barre de titre</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>touche bascule</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>barre d&apos;outils</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>info-bulle</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>arborescencel</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>type</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>taper</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>pas disponible</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Annuler</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Désinstaller</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>Affichage</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>activation sur place</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>sélection graphique</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Qu&apos;est-ce que c&apos;est?</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>Fenêtre</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>fenêtre</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Explorateur Windows</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>assistant</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>classeur</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>groupe de travail</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>espace de travail</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Oui</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/german.qph b/tools/linguist/phrasebooks/german.qph
new file mode 100644
index 0000000000..2be8c77bd0
--- /dev/null
+++ b/tools/linguist/phrasebooks/german.qph
@@ -0,0 +1,1075 @@
+<!DOCTYPE QPH><QPH language="de">
+<phrase>
+ <source>About</source>
+ <target>Info</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>Zugriffstaste</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>Eingabehilfe</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>Aktionspunkt</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>Aktiv</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>Aktives Ende</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>Aktives Objekt</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>Aktives Fenster</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>Zubehör</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Immer im Vordergrund</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>Ankerpunkt</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Zuweisen</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>Textfeld mit automatischer Freigabe</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>Automatische Wiederholung</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>Automatische OLE-Verknüpfung</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>Automatischer Bildlauf</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>Automatischer Bildlauf</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Zurück</target>
+</phrase>
+<phrase>
+ <source>barrel button</source>
+ <target>Pen-Knopf</target>
+ <definition>pen</definition>
+</phrase>
+<phrase>
+ <source>barrel-tap</source>
+ <target>Tippen mit Pen-Knopf</target>
+</phrase>
+<phrase>
+ <source>boxed edit</source>
+ <target>Texteditor</target>
+ <definition>control/Steuerelement</definition>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Durchsuchen</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Abbrechen</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>Überlappendes Menü</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>Kontrollkästchen</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>Markierung</target>
+ <definition>Kontrollkästchen</definition>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>Untergeordnetes Fenster</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>Wählen</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>Klicken</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Zwischenablage</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Schließen</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>Schließen</target>
+ <definition>Schaltfläche</definition>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>Ausblenden</target>
+ <definition>outline/Gliederung</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>Spaltenüberschrift</target>
+ <definition>control/Steuerelement</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>Kombinationsfeld</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>Schaltfläche</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>Container</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>Kontextbezogene Hilfe</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>Kontextbezogen</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>Steuerelement</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Kopieren</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Hierher kopieren</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Verknüpfung erstellen</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Hiermit verknüpfen</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Ausschneiden</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>Standard</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>Standardschaltfläche</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Löschen</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>Desktop</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>Ziel</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>Dialogfeld</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>Behinderung</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>Nichtzusammenhängende Auswahl</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>Verankern</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>Dokument</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>Doppelklicken</target>
+</phrase>
+<phrase>
+ <source>double-tap</source>
+ <target>Doppeltippen</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>Ziehen</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>Drag &amp; Drop</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>Dropdown-Kombinationsfeld</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>Dropdown-Listenfeld</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>Dropdown-Menü</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Bearbeiten</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Bearbeiten</target>
+ <definition>menu/Menü</definition>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>Auslassungspunkte</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>Eingebettetes</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Beenden</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>Einblenden</target>
+ <definition>an outline/einer Struktur</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Explorer</target>
+ <definition>Befehl</definition>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>Erweiterte Auswahl</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>Listenfeld für erweiterte Auswahl</target>
+</phrase>
+<phrase>
+ <source>File</source>
+ <target>Datei</target>
+ <definition>menu</definition>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>Datei</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Suchen</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Weitersuchen</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Suchen nach</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>Ordner</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>Schriftart</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>Schriftgrad</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>Schriftschnitt</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>Funktionstaste</target>
+</phrase>
+<phrase>
+ <source>gesture</source>
+ <target>Schriftzug</target>
+</phrase>
+<phrase>
+ <source>glyph</source>
+ <target>Zeichen</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>Gruppenfeld</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>Ziehpunkt</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>?</target>
+ <definition>menu</definition>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Hilfe</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Ausblenden</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>Hierarchische Auswahl</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>Halten</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>Hot Spot</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>Hot Zone</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>Symbol</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>Inaktiv</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>Inaktives Fenster</target>
+</phrase>
+<phrase>
+ <source>ink</source>
+ <target>Ink</target>
+</phrase>
+<phrase>
+ <source>ink edit</source>
+ <target>Inkeditor</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>Eingabefokus</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>Einfügen</target>
+ <definition>Menü</definition>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Objekt einfügen</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>Einfügemarke</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>Kursiv</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>Bezeichnung</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>Querformat</target>
+</phrase>
+<phrase>
+ <source>lasso-tap</source>
+ <target>Lasso-tippen</target>
+</phrase>
+<phrase>
+ <source>lens</source>
+ <target>Lupe</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>Verknüpfung</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>Verknüpfen</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Hiermit verknüpfen</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>Listenfeld</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>Listenansicht</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>Manuelle OLE-Verknüpfung</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Maximieren</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>Maximieren</target>
+ <definition>Schaltfläche</definition>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>Menü</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>Menüleiste</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>Menü</target>
+ <definition>Schaltfläche</definition>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>Menüelement</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>Menütitel</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>Meldungsfeld</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Minimieren</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>Minimieren</target>
+ <definition>Schaltfläche</definition>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>Gemischt</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>Modal</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>Modus</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>Interaktiv</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>Zusatztaste</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>Maus</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Verschieben</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Hierher verschieben</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>MDI</target>
+ <definition>Multiple Document Interface</definition>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>Listenfeld für Mehrfachauswahl</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Arbeitsplatz</target>
+ <definition>icon/Symbol</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Netzwerk</target>
+ <definition>icon/Symbol</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Neu</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Weiter</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>Objekt</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>OLE-Drag &amp; Drop</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>Eingebettetes OLE-Objekt</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>Verknüpftes OLE-Objekt</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>Vom Standard abweichendes OLE-Drag &amp; Drop</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>Aangepast slepen en neerzetten via OLE</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Öffnen</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Öffnen mit</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>Optionsfeld</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>Aktivierte Option</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>Paket</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Seite einrichten</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>Palettenfenster</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>Fensterbereich</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>Übergeordnetes Fenster</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>Kennwort</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Einfügen</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Verknüpfung einfügen</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Verknüpfung einfügen</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Inhalte einfügen</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>Pfad</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Anhalten</target>
+</phrase>
+<phrase>
+ <source>pen</source>
+ <target>Pen</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Wiedergeben</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug &amp; Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>Zeigen</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>Zeiger</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>Kontextmenü</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>Popup-Fenster</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>Hochformat</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>Drücken</target>
+ <definition>and hold a mouse button/und Halten einer Maustaste</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>Drücken</target>
+ <definition>a key/einer Taste</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>Primär-Container</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>Primärfenster</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Drucken</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>Drucker</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>Statusanzeige</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>Projekt</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Eigenschaften</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>Eigenschaftenanzeige</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>Eigenschaftengruppe</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>Eigenschaftenfenster</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>Eigenschaftenfenster-Steuerelement</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Schnellansicht</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>Schreibgeschützt</target>
+</phrase>
+<phrase>
+ <source>recognition</source>
+ <target>Schrifterkennung</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Papierkorb</target>
+ <definition>Icon/Symbol</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Wiederherstellen</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>Bereichsauswahl</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>Registrierung</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Wiederholen</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Ersetzen</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Wiederherstellen</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>Wiederherstellen </target>
+ <definition>Schaltfläche</definition>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Fortsetzen</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Wiederholen</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>RTF-Textfeld</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Ausführen</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Speichern</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Speichern unter</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>Bildlauf durchführen</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>Bildlaufpfeil</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>Bildlaufleiste</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>Bildlauffeld</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>Sekundärfenster</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>Auswählen</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Alle markieren</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>Auswahl</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>Auswahlpunkt</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Senden an</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>Trennelement</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Einstellungen</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Einrichten</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>Verknüpfung</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>Verknüpfte Schaltfläche</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>Verknüpfungssymbol</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>Tastenkombination</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>Steuerelement für Tastenbelegung</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Anzeigen</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Beenden</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>Listenfeld für Einfachauswahl</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Größe ändern</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>Element für Größenänderung</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>Schieber</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>Drehfeld</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Teilen</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>Fensterteiler</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>Teilungsfeld</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>Start</target>
+ <definition>Schaltfläche</definition>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>Autostart</target>
+ <definition>Ordner</definition>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>Statusleiste</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Beenden</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>Register</target>
+</phrase>
+<phrase>
+ <source>tap</source>
+ <target>Tippen</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>Task-Leiste</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>Vorgangsbezogene Hilfe</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>Vorlage</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>Textfeld</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>Titelleiste</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>Titeltext</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>Ein-/Aus-Taste</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>Symbolleiste</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>QuickInfo</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>Strukturansicht</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>Eingeben</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>Typ</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>Nicht verfügbar</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Rückgängig</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Deinstallieren</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>Ansicht</target>
+ <definition>Menü</definition>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>Direkte Bearbeitung</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>Steuerelement zur Grafikanzeige</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Direkthilfe</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>Fenster</target>
+ <definition>Menü</definition>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>Fenster</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Explorer</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>Assistent</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>Arbeitsmappe</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>Arbeitsgruppe</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>Arbeitsbereich</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Ja</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/italian.qph b/tools/linguist/phrasebooks/italian.qph
new file mode 100644
index 0000000000..0a4ea1dcc3
--- /dev/null
+++ b/tools/linguist/phrasebooks/italian.qph
@@ -0,0 +1,1105 @@
+<!DOCTYPE QPH><QPH language="it">
+<phrase>
+ <source>About</source>
+ <target>Informazioni su</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>tasto di scelta</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>accesso facilitato</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>identificatore dell&apos;azione</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>attivo</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>punto finale</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>oggetto attivo</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>finestra attiva</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>barra</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Sempre in primo piano</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>punto di ancoraggio</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Applica</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>ad uscita automatica</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>a ripetizione automatica</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>collegamento automatico</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>scorrimento automatico</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>scorrimento automatico</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Indietro</target>
+</phrase>
+<phrase>
+ <source>barrel button</source>
+ <target>pulsante della penna</target>
+ <definition>pen</definition>
+</phrase>
+<phrase>
+ <source>barrel-tap</source>
+ <target>tocco con il pulsante premuto</target>
+</phrase>
+<phrase>
+ <source>boxed edit</source>
+ <target>casella di testo a griglia</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Sfoglia</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Annulla</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>menu sovrapposto</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>casella di controllo</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>segno di spunta</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>finestra secondaria</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>scegliere</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>fare clic</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Appunti</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Chiudi</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>pulsante di chiusura</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>comprimere</target>
+ <definition>outline, verb</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>intestazione di colonna</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>casella combinata</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>pulsante di comando</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>contenitore</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>guida sensibile al contesto</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>contestuale</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>controllo</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Copia</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Copia</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Crea collegamento</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Crea collegamento</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Taglia</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>predefinito</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>pulsante predefinito</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Elimina</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>desktop</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>destinazione</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>finestra di dialogo</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>disabilità</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>selezione multipla</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>posizionare</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>documento</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>doppio clic</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>fare doppio clic</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>double-tap</source>
+ <target>toccare due volte in rapida successione</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>double-tap</source>
+ <target>doppio tocco</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>trascinare</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>trascinare e rilasciare</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>caratteristica Trascina selezione</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>casella combinata a discesa</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>casella di riepilogo a discesa</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>menu a discesa</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Modifica </target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>menu Modifica</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>puntini di sospensione</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>oggetto incorporato</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Esci</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>espandere</target>
+ <definition>an outline/una struttura</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Gestione risorse</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>selezione estesa</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>casella di riepilogo a selezione estesa</target>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>file</target>
+</phrase>
+<phrase>
+ <source>File menu</source>
+ <target>menu File</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Trova</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Trova successivo</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Trova</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>cartella</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>tipo di carattere</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>dimensione carattere</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>stile carattere</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>tasto funzione</target>
+</phrase>
+<phrase>
+ <source>gesture</source>
+ <target>segno</target>
+</phrase>
+<phrase>
+ <source>glyph</source>
+ <target>icona</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>casella di gruppo</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>quadratino di ridimensionamento </target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Guida</target>
+</phrase>
+<phrase>
+ <source>Help menu</source>
+ <target>menu ?</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Nascondi</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>selezione gerarchica</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>tenere premuto</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>area sensibile del puntatore</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>area sensibile dell&apos;oggetto</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>icona</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>inattivo</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>finestra inattiva</target>
+</phrase>
+<phrase>
+ <source>ink</source>
+ <target>tratto</target>
+</phrase>
+<phrase>
+ <source>ink edit</source>
+ <target>modifica tratto</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>elemento attivo</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>menu Inserisci</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Inserisci oggetto</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>punto di inserimento</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>corsivo</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>etichetta</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>orizzontale</target>
+</phrase>
+<phrase>
+ <source>lasso-tap</source>
+ <target>selezione circolare</target>
+</phrase>
+<phrase>
+ <source>lens</source>
+ <target>lente</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>collegamento</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>collegare</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Collega</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>casella di riepilogo</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>visualizzazione elementi</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>collegamento manuale</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Ingrandisci</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>pulsante di ingrandimento</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>menu</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>barra dei menu</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>pulsante menu</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>voce di menu</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>titolo di menu</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>finestra di messaggio</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Riduci a icona</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>pulsante di riduzione ad icona</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>valori misti</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>a scelta obbligatoria</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>modalità</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>non a scelta obbligatoria</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>tasto di modifica delle funzioni di tastiera</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>tasto di modifica dell&apos;output di tastiera</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>mouse</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Sposta</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Sposta</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>interfaccia a documenti multipli</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>casella di riepilogo a selezione multipla</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Risorse del computer</target>
+ <definition>icon/icono</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Risorse di rete</target>
+ <definition>icon</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Nuovo</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Avanti</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>oggetto</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>caratteristica Trascina selezione</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>oggetto incorporato OLE</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>oggetto collegato OLE</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>caratteristica Trascina selezione OLE non predefinita</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Apri</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Apri con</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>pulsante di opzione</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>opzione impostata</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>opzione attivata</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>package</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Imposta pagina</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>casella degli tavolozza di colori</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>casella degli strumenti</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>riquadro</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>finestra principale</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>password</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Incolla </target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Incolla collegamento</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Incolla collegamento</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Incolla speciale</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>percorso</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Interrompi</target>
+</phrase>
+<phrase>
+ <source>pen</source>
+ <target>penna</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Riproduci</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>punto</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>puntatore</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>menu di scelta rapida</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>finestra popup</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>verticale</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>premere</target>
+ <definition>a key/un tasto</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>premere</target>
+ <definition>and hold a mouse button/e tenere premuto un pulsante del mouse</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>contenitore principale</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>finestra principale</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Stampa</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>stampante</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>indicatore di avanzamento del processo</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>progetto</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Proprietà</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>visualizzatore proprietà</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>scheda proprietà</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>finestra proprietà</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>controllo finestra proprietà</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Anteprima</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>sola lettura</target>
+</phrase>
+<phrase>
+ <source>recognition</source>
+ <target>riconoscimento</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Cestino</target>
+ <definition>Icon</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Ripeti</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>selezione dell&apos;area</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>registro di configurazione</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Ripeti</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Sostituisci</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Ripristina</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>pulsante di ripristino</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Riprendi</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Riprova</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>casello di testo RTF</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Esegui</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Salva</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Salva con nome</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>scorrere</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>freccia di scorrimento</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>barra di scorrimento</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>casella di scorrimento</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>finestra secondaria</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>selezionare</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Seleziona tutto</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>selezione</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>quadratino di selezione</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Invia a</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>separatore</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Impostazioni</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Imposta</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>collegamento</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>pulsante di collegamento</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>icona di collegamento</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>tasto di scelta rapida</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>controllo tasto di scelta rapida</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Mostra</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Chiudi sessione</target>
+ <definition>comando del menu Avvio</definition>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Arresta il sistema</target>
+ <definition>pulsanti e opzioni</definition>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>casella di riepilogo a selezione singola</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Dimensione</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>punto di ridimensionamento</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>dispositivo di scorrimento</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>casella di selezione</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Dividi</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>barra di divisione</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>casella di divisione</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>pulsante Avvio</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>cartella Esecuzione automatica</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>barra di stato</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Ferma</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>controllo a schede</target>
+</phrase>
+<phrase>
+ <source>tap</source>
+ <target>toccare</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>tap</source>
+ <target>tocco</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>barra delle applicazioni</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>guida orientata alle attività</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>modello</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>casella di testo</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>barra del titolo</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>testo della barra del titolo</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>tasto interruttore</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>barra degli strumenti</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>descrizione comando</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>controllo per la visualizzazione ad albero</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>inserire</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>digitare</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>tipo</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>non disponibile</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Annulla</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Rimozione</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>menu Visualizza</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>modifica diretta</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>controllo di selezione grafica</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Guida rapida</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>menu Finestra</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>finestra</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Gestione risorse</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>installazione guidata</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>cartella di lavoro</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>gruppo di lavoro</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>area di lavoro</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Sì</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/japanese.qph b/tools/linguist/phrasebooks/japanese.qph
new file mode 100644
index 0000000000..3ecd9e332c
--- /dev/null
+++ b/tools/linguist/phrasebooks/japanese.qph
@@ -0,0 +1,1021 @@
+<!DOCTYPE QPH><QPH language="ja">
+<phrase>
+ <source>About</source>
+ <target>について</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>アクセスキー</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>ユーザー補助</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>アクションハンドル</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>アクティブ</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>アクティブエンド</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>アクティブオブジェクト</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>アクティブウィンドウ</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>装飾</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>常に手前に表示</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>アンカーポイント</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>適用</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>自動終了</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>オートリンク</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>オートスクロール</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>自動繰り返し</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>自動スクロール</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>戻る</target>
+</phrase>
+<phrase>
+ <source>barrel button</source>
+ <target>丸ボタン</target>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>参照</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>キャンセル</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>カスケードメニュー</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>チェックボックス</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>チェックマーク</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>子ウィンドウ</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>選択</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>クリック</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>クリップボード</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>閉じる</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>閉じるボタン</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>非表示</target>
+ <definition>セルなど</definition>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>折りたたみ</target>
+ <definition>XML</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>列見出し</target>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>コンボボックス</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>コマンドボタン</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>コンテナ</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>文脈依存のヘルプ</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>文脈の</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>コントロール</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>コピー</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>ここにコピー</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>ショートカットを作成</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>ショートカットをここに作成</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>切り取り</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>既定</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>既定のボタン</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>削除</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>デスクトップ</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>コピー先</target>
+ <definition>ファイルなど</definition>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>送信先</target>
+ <definition>FAX、ネットワークなど</definition>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>変換先</target>
+ <definition>文字コード、ファイル形式など</definition>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>出力先</target>
+ <definition>ログ、ファイルなど</definition>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>ダイアログボックス</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>障害</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>離れた複数項目を選択</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>ドック</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>ドキュメント</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>ダブルクリック</target>
+</phrase>
+<phrase>
+ <source>double-tap</source>
+ <target>ダブルタップ</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>ドラッグ</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>ドラッグアンドドロップ</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>ドロップダウンコンボボックス</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>ドロップダウンリストボックス</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>ドロップダウンメニュー</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>編集</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>編集メニュー</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>省略</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>埋め込みオブジェクト</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>終了</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>展開する</target>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>エクスプローラ</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>拡張選択</target>
+ <definition>F8</definition>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>拡張選択リストボックス</target>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>ファイル</target>
+</phrase>
+<phrase>
+ <source>File</source>
+ <target>ファイル</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>検索</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>次を検索</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>検索する文字列</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>フォルダ</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>フォント</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>フォントサイズ</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>フォントスタイル</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>ファンクションキー</target>
+</phrase>
+<phrase>
+ <source>gesture</source>
+ <target>ジェスチャー</target>
+</phrase>
+<phrase>
+ <source>glyph</source>
+ <target>標識</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>グループボックス</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>ハンドル</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>ヘルプ</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>非表示</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>保留</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>ホットスポット</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>ホットゾーン</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>アイコン</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>非アクティブ</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>非アクティブウィンドウ</target>
+</phrase>
+<phrase>
+ <source>ink</source>
+ <target>インク</target>
+</phrase>
+<phrase>
+ <source>ink edit</source>
+ <target>インクエディット</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>入力フォーカス</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>挿入</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>オブジェクトの挿入</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>挿入位置</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>斜体</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>ラベル</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>横</target>
+</phrase>
+<phrase>
+ <source>lens</source>
+ <target>レンズ</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>リンク</target>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>ここにリンク</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>リストボックス</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>一覧の表示</target>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>手動リンク</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>最大化</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>最大化ボタン</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>メニュー</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>メニューバー</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>メニューボタン</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>メニュー項目</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>メニュータイトル</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>メッセージボックス</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>最小化</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>最小化ボタン</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>モーダル</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>モード</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>モードレス</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>修飾キー</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>マウス</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>移動</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>ここに移動</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>マルチドキュメントインターフェイス</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>複数選択リストボックス</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>マイコンピュータ</target>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>ネットワークコンピュータ</target>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>新規</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>次へ</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>オブジェクト</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>OLEドラッグアンドドロップ</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>OLE 埋め込みオブジェクト</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>OLE リンクオブジェクト</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>OLE ノンデフォルトドラッグアンドドロップ</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>開く</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>アプリケーションから開く</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>オプションボタン</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>オプションセット</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>パッケージ</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>ページ設定</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>パレットウィンドウ</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>ペイン</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>親ウィンドウ</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>パスワード</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>貼り付け</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>リンク貼り付け</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>ショートカットの貼り付け</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>形式を選択して貼り付け</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>パス</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>一時停止</target>
+</phrase>
+<phrase>
+ <source>pen</source>
+ <target>ペン</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>再生</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>プラグアンドプレイ</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>ポイント</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>ポインタ</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>ポップアップメニュー</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>ポップアップウィンドウ</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>縦</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>押す</target>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>プライマリコンテナ</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>プライマリウィンドウ</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>印刷</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>プリンタ</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>進行状況インジケータ</target>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>プロジェクト</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>プロパティ</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>プロパティインスペクター</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>プロパティページ</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>プロパティシート</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>プロパティシートコントロール</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>クイックビューア</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>読み取り専用</target>
+</phrase>
+<phrase>
+ <source>recognition</source>
+ <target>認識</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>ごみ箱</target>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>やり直す</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>範囲選択</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>レジストリ</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>繰り返す</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>置換</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>元に戻す</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>リストアボタン</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>再開</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>再試行</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>リッチテキストボックス</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>ファイル名を指定して実行</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>保存</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>名前を付けて保存</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>スクロール</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>スクロール矢印</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>スクロールバー</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>スクロールボックス</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>セカンダリウィンドウ</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>選択</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>すべてを選択</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>選択した部分</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>セレクションハンドル</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>送る</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>セパレータ</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>設定</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>設定</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>ショートカット</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>ショートカットボタン</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>ショートカットアイコン</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>ショートカットキー</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>ショートカットキーコントロール</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>表示</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>シャットダウン</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>単一選択リストボックス</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>サイズ</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>サイズグリップ</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>スライダー</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>スピンボックス</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>分割</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>分割バー</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>分割ボックス</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>スタートボタン</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>スタートアップフォルダ</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>ステータスバー</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>停止</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>タブコントロール</target>
+</phrase>
+<phrase>
+ <source>tap</source>
+ <target>タップ</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>タスクバー</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>タスク志向のヘルプ</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>テンプレート</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>テキストボックス</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>タイトルバー</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>タイトルテキスト</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>トグルキー</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>ツールバー</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>ツールチップ</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>ツリービューコントロール</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>タイプ</target>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>利用不可</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>元に戻す</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>アンインストール</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>表示</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>画面編集</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>ヘルプ</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>ウィンドウ</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>ウィンドウ</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>ウィンドウズエクスプローラ</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>ウィザード</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>ワークブック</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>ワークグループ</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>ワークスペース</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>はい</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/norwegian.qph b/tools/linguist/phrasebooks/norwegian.qph
new file mode 100644
index 0000000000..9fda2ad68c
--- /dev/null
+++ b/tools/linguist/phrasebooks/norwegian.qph
@@ -0,0 +1,1004 @@
+<!DOCTYPE QPH><QPH language="no">
+<phrase>
+ <source>About</source>
+ <target>Om</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>tilgangstast</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>tilgjengelighet</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>handlingshåndtak</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>aktiv</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>markeringsavslutning</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>aktivt objekt</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>aktivt vindu</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>verktøyselement</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Alltid øverst</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>forankringspunkt</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Bruk</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>automatisk avslutning</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>automatisk gjentagelse</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>automatisk kobling</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>automatisk rulling</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>autorulling</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Tilbake</target>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Bla gjennom</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Avbryt</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>undermeny</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>avmerkingsboks</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>merke</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>undervindu</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>velge</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>klikke</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>utklippstavle</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Lukk</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>lukkeknapp</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>skjule</target>
+ <definition>outline/disposisjon</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>kolonneoverskrift</target>
+ <definition>control/kontroll</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>kombinasjonsboks</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>kommandoknapp</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>beholder</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>kontekstavhengig hjelp</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>kontekstavhengig</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>kontroll</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Kopier</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Kopier hit</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Lag snarvei</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Lag snarvei her</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Klipp ut</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>standard</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>standardknapp</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Slett</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>skrivebord</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>mål</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>dialogboks</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>funksjonshemning</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>ikke sammenhengende utvalg</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>forankre</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>dokument</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>dobbeltklikke</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>dra</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>dra och slippe</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>kombinasjonsboks</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>rullegardinliste</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>rullegardinmeny</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Rediger</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>Rediger-menyen</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>ellipse</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>innebygd objekt</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Avslutt</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>utvide</target>
+ <definition>an outline/en disposisjon</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Utforsk</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>utvidet merking</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>liste med utvidet merking</target>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>fil</target>
+</phrase>
+<phrase>
+ <source>File menu</source>
+ <target>Fil-menyen</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Søk etter</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Søk etter neste</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Søk etter</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>mappe</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>skrift</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>skriftstørrelse</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>skriftstil</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>funksjonstast</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>gruppeboks</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>håndtak</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Hjelp</target>
+</phrase>
+<phrase>
+ <source>Help menu</source>
+ <target>Hjelp-menyen</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Skjul</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>hierarkisk merking</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>holde</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>fokus</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>fokuseringssone</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>ikon</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>inaktiv</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>inaktivt vindu</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>indatafokus</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>Sett inn-menyen</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Sett inn objekt</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>innsettingspunkt</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>kursiv</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>etikett</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>liggende</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>koble</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>kobling</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Lag kobling her</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>listeboks</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>listevisning</target>
+ <definition>control/kontroll</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>manuell kobling</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Maksimer</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>maksimeringsknapp</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>meny</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>menylinje</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>menyknapp</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>menyelement</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>menytittel</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>meldingsboks</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Minimer</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>minimeringsknapp</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>blandet verdi</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>modal</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>modus</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>icke-modal</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>modifiseringstast</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>mus</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Flytt</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Flytt hit</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>flerdokumentgrensesnitt</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>flervalgsliste</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Min datamaskin</target>
+ <definition>icon/ikon</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Andre maskiner</target>
+ <definition>icon/ikon</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Ny</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Neste</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>objekt</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>OLE dra og slipp</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>innebyggd OLE-objekt</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>koblet OLE-objekt</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>utvidet OLE dra og slipp</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Åpne</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Åpne i</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>alternativknapp</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>valgt alternativ</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>pakke</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Utskriftsformat</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>palettvindu</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>rute</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>hovedvindu</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>passord</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Lim inn</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Lim inn kobling</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Lim inn snarvei</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Lim inn utvalg</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>bane</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Pause</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Spill</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>punkt</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>peke</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>peker</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>hurtigmeny</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>forklaringsvindu</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>stående</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>klikke</target>
+ <definition>and hold a mouse button/og holde nede en musetast</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>trykke</target>
+ <definition>a key/en tast</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>primærbeholder</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>primærvindu</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Skriv ut</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>skriver</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>fremdriftsindikator</target>
+ <definition>control/kontroll</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>prosjekt</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Egenskaper</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>egenskapsvisning</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>egenskapsside</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>egenskapsark</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>egenskapsarkkontroll</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Hurtigvisning</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>skrivebeskyttet</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Papirkurv</target>
+ <definition>Icon/ikon</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Gjør om</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>områdemerking</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>register</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Gjenta</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Erstatt</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Gjenopprett</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>gjenopprettingsknapp</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Fortsett</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Prøv på nytt</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>boks for rik tekst</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Kjør</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Lagre</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Lagre som</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>rulle</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>rullepil</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>rullefelt</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>rulleboks</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>sekundærvindu</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>merke</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Merk alt</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>merket område</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>markeringshåndtak</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Send til</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>skilletegn</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Innstillinger</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Installasjon</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>snarvei</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>snarveisknapp</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>snarveisikon</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>hurtigtast</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>hurtigtastkontroll</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Vis</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Avslutt</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>enkeltvalgsliste</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Størrelse</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>skaleringshåndtak</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>glidebryter</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>verdisettingsboks</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Del</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>delelinje</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>deleboks</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>startknapp</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>Oppstart-mappen</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>statuslinje</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Stopp</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>kategorikontroll</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>oppgavelinje</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>oppgaveorientert hjelp</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>mal</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>tekstboks</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>tittellinje</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>titteltekst</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>veksletast</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>verktøylinje</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>verktøytips</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>trevisningskontroll</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>skrive</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>type</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>ikke tilgjengelig</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Angre</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Avinstaller</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>Vis-meny</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>visuell redigering</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>grafikkontroll</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Hva er dette?</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>Vindu-menyen</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>vindu</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Windows Utforsker</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>veiviser</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>arbeidsbok</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>arbeidsgruppe</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>arbeidsområde</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Ja</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/polish.qph b/tools/linguist/phrasebooks/polish.qph
new file mode 100644
index 0000000000..1553696d30
--- /dev/null
+++ b/tools/linguist/phrasebooks/polish.qph
@@ -0,0 +1,527 @@
+<!DOCTYPE QPH><QPH language="pl">
+<phrase>
+ <source>About</source>
+ <target>Informacje o</target>
+</phrase>
+<phrase>
+ <source>About Qt</source>
+ <target>Informacje o Qt</target>
+</phrase>
+<phrase>
+ <source>Accelerator</source>
+ <target>Klawisz szybkiego dostępu</target>
+</phrase>
+<phrase>
+ <source>Alloc</source>
+ <target>Przydzielić</target>
+</phrase>
+<phrase>
+ <source>Appearance</source>
+ <target>Wygląd</target>
+</phrase>
+<phrase>
+ <source>at line</source>
+ <target>w linii</target>
+</phrase>
+<phrase>
+ <source>Background</source>
+ <target>Tło</target>
+</phrase>
+<phrase>
+ <source>Batch</source>
+ <target>Wsadowy....</target>
+</phrase>
+<phrase>
+ <source>Build </source>
+ <target>Wersja</target>
+</phrase>
+<phrase>
+ <source>Cannot create</source>
+ <target>Nie można utworzyć</target>
+</phrase>
+<phrase>
+ <source>Cannot find</source>
+ <target>Nie można znaleść</target>
+</phrase>
+<phrase>
+ <source>Cannot read</source>
+ <target>Nie można odczytać</target>
+</phrase>
+<phrase>
+ <source>Cannot save</source>
+ <target>Nie można zapisać</target>
+</phrase>
+<phrase>
+ <source>Case sensitive</source>
+ <target>Uwzględniaj wielkość liter</target>
+</phrase>
+<phrase>
+ <source>Child</source>
+ <target>Potomek Dziecko</target>
+</phrase>
+<phrase>
+ <source>Collapse</source>
+ <target>Zwinąć</target>
+</phrase>
+<phrase>
+ <source>ComboBox</source>
+ <target>Lista kombi</target>
+</phrase>
+<phrase>
+ <source>Conflicting</source>
+ <target>Kolidujący</target>
+</phrase>
+<phrase>
+ <source>Content</source>
+ <target>Treść</target>
+</phrase>
+<phrase>
+ <source>Contents</source>
+ <target>Treść Zawartość Spis treści</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Kopiuj</target>
+</phrase>
+<phrase>
+ <source>Custom</source>
+ <target>Niestandardowy, użytkownika</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Wytnij</target>
+</phrase>
+<phrase>
+ <source>Declare</source>
+ <target>Deklarować</target>
+</phrase>
+<phrase>
+ <source>Declared</source>
+ <target>Zadeklarować</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Usuń</target>
+</phrase>
+<phrase>
+ <source>Disable</source>
+ <target>Wyłącz, zablokuj</target>
+</phrase>
+<phrase>
+ <source>Display</source>
+ <target>Pokaż, wyświetl</target>
+</phrase>
+<phrase>
+ <source>Dock</source>
+ <target>Osadzony Zakotwiczony</target>
+</phrase>
+<phrase>
+ <source>Dock window</source>
+ <target>Okno osadzone Okno zakotwiczone</target>
+</phrase>
+<phrase>
+ <source>Down</source>
+ <target>W dół</target>
+</phrase>
+<phrase>
+ <source>Enable</source>
+ <target>Włącz</target>
+</phrase>
+<phrase>
+ <source>Enabled</source>
+ <target>Włączony</target>
+</phrase>
+<phrase>
+ <source>encoding name</source>
+ <target>nazwa kodowania</target>
+</phrase>
+<phrase>
+ <source>Entity</source>
+ <target>Obiekt</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Zakończ</target>
+</phrase>
+<phrase>
+ <source>Expand</source>
+ <target>Rozszerzyć</target>
+</phrase>
+<phrase>
+ <source>Fade</source>
+ <target>Wyłanianie</target>
+</phrase>
+<phrase>
+ <source>Failed to open</source>
+ <target>Nie można otworzyć</target>
+</phrase>
+<phrase>
+ <source>Feel</source>
+ <target>działanie</target>
+</phrase>
+<phrase>
+ <source>File</source>
+ <target>Plik</target>
+</phrase>
+<phrase>
+ <source>Find in text</source>
+ <target>Znajdź w tekście</target>
+</phrase>
+<phrase>
+ <source>Find next</source>
+ <target>Znajdź następne</target>
+</phrase>
+<phrase>
+ <source>Focal</source>
+ <target>Ogniskowa</target>
+</phrase>
+<phrase>
+ <source>Font family</source>
+ <target>Nazwa czcionki</target>
+</phrase>
+<phrase>
+ <source>Foreground</source>
+ <target>PIerwszy plan</target>
+</phrase>
+<phrase>
+ <source>Form</source>
+ <target>Okno formy</target>
+</phrase>
+<phrase>
+ <source>full text search</source>
+ <target>szukanie w treści tesktu</target>
+</phrase>
+<phrase>
+ <source>fulltext search</source>
+ <target>szukanie w treści tesktu</target>
+</phrase>
+<phrase>
+ <source>Go</source>
+ <target>Przejdź</target>
+ <definition>przy przeglądarkach</definition>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Pomoc</target>
+</phrase>
+<phrase>
+ <source>Home</source>
+ <target>Strona startowa</target>
+ <definition>przy przeglądarkach</definition>
+</phrase>
+<phrase>
+ <source>Illegal</source>
+ <target>Niepoprawny</target>
+</phrase>
+<phrase>
+ <source>Invalid</source>
+ <target>Niepoprawny</target>
+</phrase>
+<phrase>
+ <source>Invoke</source>
+ <target>Wywołaj</target>
+</phrase>
+<phrase>
+ <source>is missing</source>
+ <target>Brakuje ...</target>
+</phrase>
+<phrase>
+ <source>Item</source>
+ <target>Pozycja</target>
+</phrase>
+<phrase>
+ <source>Item</source>
+ <target>Wpis</target>
+</phrase>
+<phrase>
+ <source>Lay out</source>
+ <target>Ułóż</target>
+</phrase>
+<phrase>
+ <source>layout</source>
+ <target>ułożenie</target>
+</phrase>
+<phrase>
+ <source>Link</source>
+ <target>Odnośnik</target>
+ <definition>(w pliku HTML)</definition>
+</phrase>
+<phrase>
+ <source>Link</source>
+ <target>Dowiązanie</target>
+ <definition>(lokalizacja)</definition>
+</phrase>
+<phrase>
+ <source>literal</source>
+ <target>stała znakowa</target>
+</phrase>
+<phrase>
+ <source>Load</source>
+ <target>Wczytaj</target>
+</phrase>
+<phrase>
+ <source>Look and feel</source>
+ <target>Wygląd i działanie</target>
+</phrase>
+<phrase>
+ <source>Marker</source>
+ <target>Znacznik</target>
+</phrase>
+<phrase>
+ <source>Match</source>
+ <target>dopasowanie</target>
+</phrase>
+<phrase>
+ <source>Menu bar</source>
+ <target>Pasek menu</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Minimalizuj</target>
+</phrase>
+<phrase>
+ <source>Mismatch</source>
+ <target>Niezgodność, niedopasowanie</target>
+</phrase>
+<phrase>
+ <source>Namespace</source>
+ <target>Przesteń nazw</target>
+</phrase>
+<phrase>
+ <source>Occure</source>
+ <target>Wystąpić</target>
+</phrase>
+<phrase>
+ <source>Occured</source>
+ <target>Wystąpił, pojawił się</target>
+</phrase>
+<phrase>
+ <source>Off The Spot</source>
+ <target>Na pasku stanu</target>
+ <definition>Zmiany wykonywane sa w dodatkowym miejscu np na pasku stanu i dopiero pozniej wprowadzane do tesktu</definition>
+</phrase>
+<phrase>
+ <source>On The Spot</source>
+ <target>W oknie dokumentu</target>
+ <definition>Metoda wprowadzania znaków - bezposrednio w oknie</definition>
+</phrase>
+<phrase>
+ <source>Open Source Edition</source>
+ <target>Wydanie Open Source</target>
+</phrase>
+<phrase>
+ <source>Over The Spot</source>
+ <target>Nad oknem dokumentu</target>
+ <definition>Zmiany są wprowadzane z wyższej warstwie i renderowane później</definition>
+</phrase>
+<phrase>
+ <source>Pad</source>
+ <target>Dopełnić, Podstawka, Dopełnienie</target>
+</phrase>
+<phrase>
+ <source>Parse</source>
+ <target>Przetwarzać</target>
+</phrase>
+<phrase>
+ <source>Parsing</source>
+ <target>Przetwarzanie</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Wklej</target>
+</phrase>
+<phrase>
+ <source>Pattern</source>
+ <target>Wzorzec</target>
+</phrase>
+<phrase>
+ <source>Phrase</source>
+ <target>Wyrażenie, fraza</target>
+</phrase>
+<phrase>
+ <source>Place</source>
+ <target>Wstaw</target>
+</phrase>
+<phrase>
+ <source>Preference</source>
+ <target>Wyróżnienie</target>
+</phrase>
+<phrase>
+ <source>Preferences</source>
+ <target>Wyróżnienia</target>
+</phrase>
+<phrase>
+ <source>Premature</source>
+ <target>Przedwczesny</target>
+</phrase>
+<phrase>
+ <source>Promote</source>
+ <target>Wypromuj</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Właściwości</target>
+</phrase>
+<phrase>
+ <source>Property</source>
+ <target>Właściwość</target>
+</phrase>
+<phrase>
+ <source>Quotation mark</source>
+ <target>Znak cudzysłowu</target>
+</phrase>
+<phrase>
+ <source>Reference</source>
+ <target>Odwołanie</target>
+</phrase>
+<phrase>
+ <source>Refresh</source>
+ <target>Odśwież</target>
+</phrase>
+<phrase>
+ <source>Render</source>
+ <target>Renderuj</target>
+ <definition>odnosi się jedynie do grafiki</definition>
+</phrase>
+<phrase>
+ <source>Reset</source>
+ <target>Przywróc ustawienia</target>
+</phrase>
+<phrase>
+ <source>Root</source>
+ <target>W dodatkowym oknie</target>
+ <definition>Zmiany wprowadzane sa w zupelnie dodatkowym oknie i pozniej wprowadzane do calego tekstu</definition>
+</phrase>
+<phrase>
+ <source>Saturation</source>
+ <target>Nasycenie</target>
+</phrase>
+<phrase>
+ <source>search word</source>
+ <target>wyrażenie do szukania</target>
+</phrase>
+<phrase>
+ <source>Search wrapped</source>
+ <target>Szukanie od początku</target>
+</phrase>
+<phrase>
+ <source>searchword</source>
+ <target>wyrażenie do szukania</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Zaznacz wszystko</target>
+</phrase>
+<phrase>
+ <source>Sequence</source>
+ <target>Ciąg</target>
+</phrase>
+<phrase>
+ <source>Sidebar</source>
+ <target>Panel</target>
+</phrase>
+<phrase>
+ <source>Sidebar</source>
+ <target>Panel boczny</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Rozmiar</target>
+</phrase>
+<phrase>
+ <source>Slider</source>
+ <target>Suwak</target>
+</phrase>
+<phrase>
+ <source>Specified</source>
+ <target>Określony</target>
+</phrase>
+<phrase>
+ <source>Status</source>
+ <target>Stan</target>
+</phrase>
+<phrase>
+ <source>Status Bar</source>
+ <target>Pasek stanu</target>
+</phrase>
+<phrase>
+ <source>Style sheet</source>
+ <target>Wzorzec stylu</target>
+</phrase>
+<phrase>
+ <source>StyleSheet</source>
+ <target>Wzorzec stylu</target>
+</phrase>
+<phrase>
+ <source>superfluous</source>
+ <target>przypadkowe, niecelowe, zbędny</target>
+</phrase>
+<phrase>
+ <source>Support</source>
+ <target>Obsługa</target>
+</phrase>
+<phrase>
+ <source>supported</source>
+ <target>obsługiwany</target>
+</phrase>
+<phrase>
+ <source>This program is licensed</source>
+ <target>Ten program wydany jest na licencji Qt Commercial. Aby sprawdzić szczegóły licencji, proszę sprawdzić plik LICENSE, który dołączany jest do pakietu Qt.</target>
+</phrase>
+<phrase>
+ <source>This version of</source>
+ <target>Ta wersja Qt Assistant jest częścią wydania Qt Open Source, przeznaczonego dla tworzenia i publikowania aplikacji Open Source. Qt jest zaawansowanym zestawem bibliotek wykorzystywanym do pisania aplikacji cross-platformowych.</target>
+</phrase>
+<phrase>
+ <source>to display</source>
+ <target>pokazywać, wyświetlać</target>
+</phrase>
+<phrase>
+ <source>Tool tips</source>
+ <target>Etykietki narzędzi</target>
+</phrase>
+<phrase>
+ <source>Toolbox</source>
+ <target>Narzędzie</target>
+</phrase>
+<phrase>
+ <source>ToolTips</source>
+ <target>Etykietki narzędzi</target>
+</phrase>
+<phrase>
+ <source>Tune</source>
+ <target>Ustawić</target>
+</phrase>
+<phrase>
+ <source>unsupported</source>
+ <target>nieobsługiwany</target>
+</phrase>
+<phrase>
+ <source>Up</source>
+ <target>W górę</target>
+</phrase>
+<phrase>
+ <source>Update</source>
+ <target>Uaktualnij</target>
+</phrase>
+<phrase>
+ <source>Value</source>
+ <target>Wartość</target>
+</phrase>
+<phrase>
+ <source>Widget</source>
+ <target>Element interfejsu</target>
+</phrase>
+<phrase>
+ <source>You need a commercial</source>
+ <target>Aby móc sprzedawać aplikację utworzone przy pomocy Qt potrzebujesz wersji komercyjnej. Proszę sprawdzić &lt;a href=&quot;http://qtsoftware.com/company/model.html&quot;&gt;qtsoftware.com/company/model.html&lt;/a&gt; dla poznania sposobu licencjonowania Qt.</target>
+</phrase>
+<phrase>
+ <source>Zoom in</source>
+ <target>Zwiększ</target>
+</phrase>
+<phrase>
+ <source>Zoom out</source>
+ <target>Zmniejsz</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/russian.qph b/tools/linguist/phrasebooks/russian.qph
new file mode 100644
index 0000000000..0b06ceae70
--- /dev/null
+++ b/tools/linguist/phrasebooks/russian.qph
@@ -0,0 +1,982 @@
+<!DOCTYPE QPH><QPH language="ru">
+<phrase>
+ <source>About</source>
+ <target>О программе</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>горячая клавиша</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>удобство</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>управление поведением</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>активный</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>окончание выбора</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>активный объект</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>активное окно</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>украшение</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Всегда наверху</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>точка начала выбора</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Применить</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>автоматический выход</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>авто-повтор</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>автоматическое связывание</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>автоматическая прокрутка</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>авто-прокрутка</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Назад</target>
+</phrase>
+<phrase>
+ <source>boxed edit</source>
+ <target>окно редактирования</target>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Обзор</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Отмена</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>ниспадающее меню</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>флажок</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>флажок</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>дочернее окно</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>выбрать</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>щелчок</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Буфер обмена</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Закрыть</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>кнопка закрытия</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>крах</target>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>заголовок колонки</target>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>поле со списком</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>кнопка</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>контейнер</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>контекстная помощь</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>контекстный</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>элемент управления</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Копировать</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Копировать сюда</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Создать ярлык</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Создать ярлык здесь</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Вырезать</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>по умолчанию</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>кнопка по умолчанию</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Удалить</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>рабочий стол</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>цель</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>окно диалога</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>неспособность</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>разделить выбранные элементы</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>док</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>документ</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>двойной щелчок</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>перетащить</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>drag-and-drop</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>раскрыть поле со списком</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>прокрутить список</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>открыть меню</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Правка</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>меню Правка</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>эллипс</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>встроенный объект</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Выход</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>расширять</target>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Исследовать</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>расширенный выбор</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>список с расширенным выбором</target>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>файл</target>
+</phrase>
+<phrase>
+ <source>File menu</source>
+ <target>меню Файл</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Поиск</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Продолжить поиск</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Поиск</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>каталог</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>шрифт</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>размер шрифта</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>стиль шрифта</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>функциональная клавиша</target>
+</phrase>
+<phrase>
+ <source>glyph</source>
+ <target>глиф</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>контейнер элементов</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>управление</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Справка</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Скрыть</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>иерархический выбор</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>удерживать</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>фокус</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>активная зона</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>пиктограмма</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>неактивный</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>неактивное окно</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>фокус ввода</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>Вставить</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Вставить объект</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>место вставки</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>курсив</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>надпись</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>альбом</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>ссылка</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>связать</target>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Создать ссылку здесь</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>список</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>древовидный список</target>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>ручное связывание</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Распахнуть</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>кнопка максимизации</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>меню</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>строка меню</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>кнопка меню</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>элемент меню</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>заголовок меню</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>окно сообщений</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Свернуть</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>кнопка минимизации</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>модальный</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>режим</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>немодальный</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>клавиша-модификатор</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>мышь</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Переместить</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Переместить сюда</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>Multiple Document Interface</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>список с множественным выбором</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Мой компьютер</target>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Сетевое окружение</target>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Новый</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Следующий</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>объект</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>OLE-механизм</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>внедренный OLE-объект</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>связанный OLE-объект</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>предопределенный OLE-механизм</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Открыть</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Открыть с помощью</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>переключатель</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>набор параметров</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>пакет</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>шаг установки</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>окно выбора палитры</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>панель</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>родительское окно</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>пароль</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Вставить</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Вставить ссылку</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Вставить ярлык</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Специальная вставка</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>путь</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Пауза</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Воспроизведение</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>пункт</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>указатель</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>всплывающее меню</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>всплывающее окно</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>портрет</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>нажимать</target>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>корневой контейнер</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>главное окно</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Печать</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>принтер</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>индикатор хода процесса</target>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>проект</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Свойства</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>инспектор свойств</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>страница свойств</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>группа свойств</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>управление группой свойств</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Быстрый просмотр</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>только чтение</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Корзина</target>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Повторить</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>область выделения</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>реестр</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Повторить</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Заменить</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Восстановить</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>Кнопка восстановления</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Продолжить</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Повторить</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>окно RTF-редактора</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Выполнить</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Сохранить</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Сохранить как</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>прокрутить</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>кнопка прокрутки</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>полоса прокрутки</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>окно с полосами прокрутки</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>подчиненное окно</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>выбрать</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Выделить все</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>выбор</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>осуществление выбора</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Отправить</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>разделитель</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Настройки</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Установить</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>ярлык</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>кнопка</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>пиктограмма</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>комбинация клавиш</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>настройка комбинации клавиш</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Показать</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Выключение</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>список с одиночным выбором</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Размер</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>уголок для изменения размера</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>ползунок</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>поле со счетчиком</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Разделить</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>разделительная черта</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>разделительная рамка</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>кнопка Пуск</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>каталог Автозапуска</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>статусная строка</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Стоп</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>вкладка</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>панель задач</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>контекстная справка</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>шаблон</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>текстовое поле</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>заголовок</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>текст заголовка</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>кнопка-выключатель</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>панель инструментов</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>всплывающая подсказка</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>древовидный список</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>тип</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>набирать</target>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>недоступный</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Отменить</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Удалить</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>Вид</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>визуальное редактирование</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>элемент графического интерфейса</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Что это?</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>Окно</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>окно</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Проводник Windows</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>мастер</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>учебник</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>рабочая группа</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>рабочая область</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Да</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/spanish.qph b/tools/linguist/phrasebooks/spanish.qph
new file mode 100644
index 0000000000..dacb6b5d2a
--- /dev/null
+++ b/tools/linguist/phrasebooks/spanish.qph
@@ -0,0 +1,1086 @@
+<!DOCTYPE QPH><QPH language="es">
+<phrase>
+ <source>About</source>
+ <target>Acerca de</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>tecla de acceso</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>accesibilidad</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>controlador de acciones</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>activo</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>fin de la selección activa</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>objeto activo</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>ventana activa</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>opción gráfica</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Siempre visible</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>inicio de la selección activa</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Aplicar</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>salida automática</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>repetición automática</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>vínculo automático</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>desplazamiento automático</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>desplazamiento automático</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Atrás</target>
+</phrase>
+<phrase>
+ <source>barrel button</source>
+ <target>botón del lápiz</target>
+ <definition>pen</definition>
+</phrase>
+<phrase>
+ <source>barrel-tap</source>
+ <target>puntenar con el botón presionado</target>
+</phrase>
+<phrase>
+ <source>boxed edit</source>
+ <target>edición en casilla</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Examinar</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Cancelar</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>menú en cascada</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>casilla de verificación</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>marca de verificación</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>ventana secundaria</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>elegir</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>hacer clic</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Portapapeles</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Cerrar</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>botón &amp;quot;Cerrar&amp;quot;</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>contraer</target>
+ <definition>outline/esquerna</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>encabezado de columna</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>cuadro combinado</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>botón de comando</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>contenedor</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>ayuda interactiva</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>contextual</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>control</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Copiar</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Copiar aquí</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Crear acceso directo</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Crear acceso directo aquí</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Cortar</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>predeterminado</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>botón predeterminado</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Eliminar</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>escritorio</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>destino</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>cuadro de diálogo</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>Discapacidades</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>selección disjunta</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>acoplar</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>documento</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>hacer doble clic</target>
+</phrase>
+<phrase>
+ <source>double-tap</source>
+ <target>puntear dos veces</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>arrastrar</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>arrastrar y colocar</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>cuadro combinado desplegable</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>cuadro de lista desplegable</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>menú desplegable</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Edición</target>
+</phrase>
+<phrase>
+ <source>Edit menu</source>
+ <target>menú Edición</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>puntos suspensivos</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>objeto incrustado</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Salir</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>expandir</target>
+ <definition>an outline/un esquema</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Explorar</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>selección extendida</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>cuadro de lista de selección extendida</target>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>archivo</target>
+</phrase>
+<phrase>
+ <source>File menu</source>
+ <target>menú Archivo</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Buscar</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Buscar siguiente</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Buscar</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>carpeta</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>fuente</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>tamaño de fuente</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>estilo de fuente</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>tecla de función</target>
+</phrase>
+<phrase>
+ <source>gesture</source>
+ <target>signo</target>
+</phrase>
+<phrase>
+ <source>glyph</source>
+ <target>símbolo gráfico</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>cuadro de grupo</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>controlar</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>controlador</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Ayuda</target>
+</phrase>
+<phrase>
+ <source>Help menu</source>
+ <target>menú Ayuda</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Ocultar</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>selección jerárquica</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>mantener presionado</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>punto interactivo</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>zona interactiva</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>icono</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>inactivo</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>ventana inactiva</target>
+</phrase>
+<phrase>
+ <source>ink</source>
+ <target>trazo</target>
+</phrase>
+<phrase>
+ <source>ink edit</source>
+ <target>editor de trazos</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>zona de entrada</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>zona de entrada de datos</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>menú Insertar</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Insertar objeto</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>punto de inserción</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>cursiva</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>etiqueta</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>horizontal</target>
+</phrase>
+<phrase>
+ <source>lasso-tap</source>
+ <target>punteo en la selección</target>
+</phrase>
+<phrase>
+ <source>lens</source>
+ <target>lente</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>vincular</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>vínculo</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Vincular aquí</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>cuadro de lista</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>ver lista</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>presentación de iconos </target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>vínculo manual</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Maximizar</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>botón de maximizar</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>menú</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>barra de menús</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>botón de menú</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>elemento de menú</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>título de menú</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>cuadro de mensaje</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Minimizar</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>botón de minimizar</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>valores mezclados</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>modal</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>modo</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>sin modo</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>tecla modificadora</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>mouse</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Mover</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Mover aquí</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>interfaz de documentos múltiples</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>cuadro de lista de selección múltiple</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Mi PC</target>
+ <definition>icon/icono</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Entorno de red</target>
+ <definition>icon/icono</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Nuevo</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Sigulente</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>objeto</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>Aceptar</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>Arrastrar y colocar de OLE</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>Objeto incrustado de OLE</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>Objeto vinculado de OLE</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>Arrastrar y colocar no predeterminado de OLE</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Abrir</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Abrir con</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>botón de opción</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>opción establecida</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>paquete</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Preparar página</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>ventana de paleta</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>panel</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>ventana principal</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>contraseña</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Pegar</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Pegar vínculo</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Pegar acceso directo</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Pegado especial</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>ruta de acceso</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Pausa</target>
+</phrase>
+<phrase>
+ <source>pen</source>
+ <target>lápiz</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Reproducir</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>señalar</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>punto</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>puntero</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>menú emergente</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>ventana emergente</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>vertical</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>presionar</target>
+ <definition>and hold a mouse button/y mantener presionado un botón del mouse</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>presionar</target>
+ <definition>a key/una tecla</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>contenedor primario</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>ventana principal</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Imprimir</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>impresora</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>indicador de progreso</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>proyecto</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Propiedades</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>monitor de propiedades</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>página de propiedades</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>hoja de propiedades</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>control de la hoja de propiedades</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Vista rápida</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>sólo lectura</target>
+</phrase>
+<phrase>
+ <source>recognition</source>
+ <target>reconocimiento</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Papelera de reciclaje</target>
+ <definition>Icon/icono</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Rehacer</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>selección de área</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>Registro de configuraciones</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Repetir</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Reemplazar</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Restaurar</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>botón &amp;quot;Restaurar&amp;quot;</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Reanudar</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Reintentar</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>cuadro de texto enriquecido</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Ejecutar</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Guardar</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Guardar como</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>desplazar</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>flecha de desplazamiento</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>barra de desplazamiento</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>cuadro de desplazamiento</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>ventana secundaria</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>seleccionar</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Seleccionar todo</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>selección</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>controlador de selección</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Enviar a</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>separador</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Configuración</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Configurar</target>
+ <definition>for a device already installed</definition>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Instalar</target>
+ <definition>for an application</definition>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>acceso directo</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>botón de acceso directo</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>icono de acceso directo</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>tecla de método abreviado</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>control de la tecla de método abreviado</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Mostrar</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Apagar el sistema</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>cuadro de lista de selección simple</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Tamaño</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>ajuste de tamaño</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>control deslizante</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>cuadro selector</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Dividir</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>barra de división</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>cuadro de división</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>botón &amp;quot;Inicio&amp;quot;</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>carpeta Inicio</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>barra de estado</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Detener</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>control de fichas</target>
+</phrase>
+<phrase>
+ <source>tap</source>
+ <target>puntear</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>barra de tareas</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>Ayuda relativa a la tarea</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>plantilla</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>cuadro de texto</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>barra de título</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>texto de título</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>tecla para alternar</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>barra de herramientas</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>sugerencias</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>control de visión en árbol</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>escribir</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>tipo</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>no disponible</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Deshacer</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Desinstalar</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>menú Ver</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>edición visual</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>control de opciones gráficas</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>¿Qué es esto?</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>menú Ventana</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>ventana</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Explorador de Windows</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>asistente</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>libro</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>libro de trabajo</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>grupo de trabajo</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>área de trabajo</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Sí</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/phrasebooks/swedish.qph b/tools/linguist/phrasebooks/swedish.qph
new file mode 100644
index 0000000000..a88735ec73
--- /dev/null
+++ b/tools/linguist/phrasebooks/swedish.qph
@@ -0,0 +1,1010 @@
+<!DOCTYPE QPH><QPH language="sv">
+<phrase>
+ <source>About</source>
+ <target>Om</target>
+</phrase>
+<phrase>
+ <source>access key</source>
+ <target>snabbtangent</target>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>Hjälpmedel</target>
+ <definition>ikonen Accessibility</definition>
+</phrase>
+<phrase>
+ <source>accessibility</source>
+ <target>tillgänglighet</target>
+</phrase>
+<phrase>
+ <source>action handle</source>
+ <target>funktionshandtag</target>
+</phrase>
+<phrase>
+ <source>active</source>
+ <target>aktiv</target>
+</phrase>
+<phrase>
+ <source>active end</source>
+ <target>aktiv slutpunkt</target>
+</phrase>
+<phrase>
+ <source>active object</source>
+ <target>aktivt objekt</target>
+</phrase>
+<phrase>
+ <source>active window</source>
+ <target>aktivt fönster</target>
+</phrase>
+<phrase>
+ <source>adornment</source>
+ <target>fönsterfält</target>
+</phrase>
+<phrase>
+ <source>Always on Top</source>
+ <target>Alltid överst</target>
+</phrase>
+<phrase>
+ <source>anchor point</source>
+ <target>startpunkt</target>
+</phrase>
+<phrase>
+ <source>Apply</source>
+ <target>Verkställ</target>
+</phrase>
+<phrase>
+ <source>auto-exit</source>
+ <target>flytta automatiskt</target>
+</phrase>
+<phrase>
+ <source>auto-repeat</source>
+ <target>upprepa automatiskt</target>
+</phrase>
+<phrase>
+ <source>automatic link</source>
+ <target>automatisk länk</target>
+</phrase>
+<phrase>
+ <source>automatic scrolling</source>
+ <target>automatisk rullning</target>
+</phrase>
+<phrase>
+ <source>autoscroll</source>
+ <target>automatisk rullning</target>
+</phrase>
+<phrase>
+ <source>Back</source>
+ <target>Föregående</target>
+</phrase>
+<phrase>
+ <source>Browse</source>
+ <target>Bläddra</target>
+</phrase>
+<phrase>
+ <source>Cancel</source>
+ <target>Avbryt</target>
+</phrase>
+<phrase>
+ <source>cascading menu</source>
+ <target>undermeny</target>
+</phrase>
+<phrase>
+ <source>check box</source>
+ <target>kryssruta</target>
+</phrase>
+<phrase>
+ <source>check mark</source>
+ <target>markering</target>
+</phrase>
+<phrase>
+ <source>child window</source>
+ <target>underfönster</target>
+</phrase>
+<phrase>
+ <source>choose</source>
+ <target>välj</target>
+</phrase>
+<phrase>
+ <source>click</source>
+ <target>klicka</target>
+</phrase>
+<phrase>
+ <source>Clipboard</source>
+ <target>Urklipp</target>
+</phrase>
+<phrase>
+ <source>Close</source>
+ <target>Stäng</target>
+</phrase>
+<phrase>
+ <source>Close button</source>
+ <target>stängningsknapp</target>
+</phrase>
+<phrase>
+ <source>collapse</source>
+ <target>komprimera</target>
+ <definition>outline</definition>
+</phrase>
+<phrase>
+ <source>column heading</source>
+ <target>kolumnrubrik</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>combo box</source>
+ <target>kombinationsruta</target>
+</phrase>
+<phrase>
+ <source>command button</source>
+ <target>kommandoknapp</target>
+</phrase>
+<phrase>
+ <source>container</source>
+ <target>behållare</target>
+</phrase>
+<phrase>
+ <source>context-sensitive Help</source>
+ <target>sammanhangsberoende hjälp</target>
+</phrase>
+<phrase>
+ <source>contextual</source>
+ <target>sammanhangsberoende</target>
+</phrase>
+<phrase>
+ <source>control</source>
+ <target>kontroll</target>
+</phrase>
+<phrase>
+ <source>Copy</source>
+ <target>Kopiera</target>
+</phrase>
+<phrase>
+ <source>Copy here</source>
+ <target>Kopiera hit</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut</source>
+ <target>Skapa genväg</target>
+</phrase>
+<phrase>
+ <source>Create Shortcut Here</source>
+ <target>Skapa genväg här</target>
+</phrase>
+<phrase>
+ <source>Cut</source>
+ <target>Klipp ut</target>
+</phrase>
+<phrase>
+ <source>default</source>
+ <target>standard</target>
+</phrase>
+<phrase>
+ <source>default button</source>
+ <target>standardknapp</target>
+</phrase>
+<phrase>
+ <source>Delete</source>
+ <target>Ta bort</target>
+</phrase>
+<phrase>
+ <source>desktop</source>
+ <target>skrivbord</target>
+</phrase>
+<phrase>
+ <source>destination</source>
+ <target>mål</target>
+</phrase>
+<phrase>
+ <source>dialog box</source>
+ <target>dialogruta</target>
+</phrase>
+<phrase>
+ <source>disability</source>
+ <target>oförmåga</target>
+</phrase>
+<phrase>
+ <source>disjoint selection</source>
+ <target>osammanhängande markering</target>
+</phrase>
+<phrase>
+ <source>dock</source>
+ <target>docka</target>
+</phrase>
+<phrase>
+ <source>document</source>
+ <target>dokument</target>
+</phrase>
+<phrase>
+ <source>double-click</source>
+ <target>dubbelklicka på</target>
+</phrase>
+<phrase>
+ <source>drag</source>
+ <target>dra</target>
+</phrase>
+<phrase>
+ <source>drag-and-drop</source>
+ <target>dra och släpp</target>
+</phrase>
+<phrase>
+ <source>drop-down combo box</source>
+ <target>nedrullningsbar kombinationsruta</target>
+</phrase>
+<phrase>
+ <source>drop-down list box</source>
+ <target>nedrullningsbar listruta</target>
+</phrase>
+<phrase>
+ <source>drop-down menu</source>
+ <target>nedrullningsbar meny</target>
+</phrase>
+<phrase>
+ <source>Edit</source>
+ <target>Redigera</target>
+</phrase>
+<phrase>
+ <source>ellipsis</source>
+ <target>punkter</target>
+</phrase>
+<phrase>
+ <source>embedded object</source>
+ <target>inbäddat objekt</target>
+</phrase>
+<phrase>
+ <source>Exit</source>
+ <target>Avsluta</target>
+</phrase>
+<phrase>
+ <source>expand</source>
+ <target>expandera</target>
+ <definition>an outline</definition>
+</phrase>
+<phrase>
+ <source>Explore</source>
+ <target>Utforska</target>
+</phrase>
+<phrase>
+ <source>extended selection</source>
+ <target>utökad markering</target>
+</phrase>
+<phrase>
+ <source>extended selection list box</source>
+ <target>listruta för utökad markering</target>
+</phrase>
+<phrase>
+ <source>File</source>
+ <target>Arkiv</target>
+ <definition>menu/meny</definition>
+</phrase>
+<phrase>
+ <source>file</source>
+ <target>fil</target>
+</phrase>
+<phrase>
+ <source>Find</source>
+ <target>Sök</target>
+</phrase>
+<phrase>
+ <source>Find Next</source>
+ <target>Sök nästa</target>
+</phrase>
+<phrase>
+ <source>Find What</source>
+ <target>Sök efter</target>
+</phrase>
+<phrase>
+ <source>folder</source>
+ <target>mapp</target>
+</phrase>
+<phrase>
+ <source>font</source>
+ <target>teckensnitt</target>
+</phrase>
+<phrase>
+ <source>font size</source>
+ <target>teckenstorlek</target>
+</phrase>
+<phrase>
+ <source>font style</source>
+ <target>teckenstil</target>
+</phrase>
+<phrase>
+ <source>function key</source>
+ <target>funktionstangent</target>
+</phrase>
+<phrase>
+ <source>group box</source>
+ <target>gruppruta</target>
+</phrase>
+<phrase>
+ <source>handle</source>
+ <target>handtag</target>
+</phrase>
+<phrase>
+ <source>Help</source>
+ <target>Hjälp</target>
+</phrase>
+<phrase>
+ <source>Hide</source>
+ <target>Dölj</target>
+</phrase>
+<phrase>
+ <source>hierarchical selection</source>
+ <target>hierarkisk markering</target>
+</phrase>
+<phrase>
+ <source>hold</source>
+ <target>hålla ned</target>
+</phrase>
+<phrase>
+ <source>hot spot</source>
+ <target>aktiv punkt</target>
+</phrase>
+<phrase>
+ <source>hot zone</source>
+ <target>aktiveringszon</target>
+</phrase>
+<phrase>
+ <source>icon</source>
+ <target>ikon</target>
+</phrase>
+<phrase>
+ <source>inactive</source>
+ <target>inaktiv</target>
+</phrase>
+<phrase>
+ <source>inactive window</source>
+ <target>inaktivt fönster</target>
+</phrase>
+<phrase>
+ <source>input focus</source>
+ <target>inmatningsfokus</target>
+</phrase>
+<phrase>
+ <source>Insert</source>
+ <target>Infoga-meny</target>
+</phrase>
+<phrase>
+ <source>Insert Object</source>
+ <target>Infoga objekt</target>
+</phrase>
+<phrase>
+ <source>insertion point</source>
+ <target>insättningspunkt</target>
+</phrase>
+<phrase>
+ <source>italic</source>
+ <target>kursiv</target>
+</phrase>
+<phrase>
+ <source>label</source>
+ <target>titel</target>
+</phrase>
+<phrase>
+ <source>landscape</source>
+ <target>liggande</target>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>länk</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>link</source>
+ <target>länka</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>Link Here</source>
+ <target>Länka hit</target>
+</phrase>
+<phrase>
+ <source>list box</source>
+ <target>listruta</target>
+</phrase>
+<phrase>
+ <source>list view</source>
+ <target>listvy</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>manual link</source>
+ <target>manuell länk</target>
+</phrase>
+<phrase>
+ <source>Maximize</source>
+ <target>Maximera</target>
+</phrase>
+<phrase>
+ <source>maximize button</source>
+ <target>maximeringsknapp</target>
+</phrase>
+<phrase>
+ <source>MDI</source>
+ <target>MDI</target>
+</phrase>
+<phrase>
+ <source>menu</source>
+ <target>meny</target>
+</phrase>
+<phrase>
+ <source>menu bar</source>
+ <target>menyrad</target>
+</phrase>
+<phrase>
+ <source>menu button</source>
+ <target>menyknapp</target>
+</phrase>
+<phrase>
+ <source>menu item</source>
+ <target>menyobjekt</target>
+</phrase>
+<phrase>
+ <source>menu title</source>
+ <target>menytitel</target>
+</phrase>
+<phrase>
+ <source>message box</source>
+ <target>meddelanderuta</target>
+</phrase>
+<phrase>
+ <source>Minimize</source>
+ <target>Minimera</target>
+</phrase>
+<phrase>
+ <source>minimize button</source>
+ <target>minimeringsknapp</target>
+</phrase>
+<phrase>
+ <source>mixed-value</source>
+ <target>blandvärde</target>
+</phrase>
+<phrase>
+ <source>modal</source>
+ <target>modal</target>
+</phrase>
+<phrase>
+ <source>mode</source>
+ <target>läge</target>
+</phrase>
+<phrase>
+ <source>modeless</source>
+ <target>icke-modal</target>
+</phrase>
+<phrase>
+ <source>modifier key</source>
+ <target>ändringstangent</target>
+</phrase>
+<phrase>
+ <source>mouse</source>
+ <target>mus</target>
+</phrase>
+<phrase>
+ <source>Move</source>
+ <target>Flytta</target>
+</phrase>
+<phrase>
+ <source>Move Here</source>
+ <target>Flytta hit</target>
+</phrase>
+<phrase>
+ <source>Multiple Document Interface</source>
+ <target>multiple document interface</target>
+</phrase>
+<phrase>
+ <source>multiple selection list box</source>
+ <target>listruta för multipel markering</target>
+</phrase>
+<phrase>
+ <source>My Computer</source>
+ <target>Den här datorn</target>
+ <definition>icon</definition>
+</phrase>
+<phrase>
+ <source>Network Neighborhood</source>
+ <target>Nätverket</target>
+ <definition>icon</definition>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Ny</target>
+</phrase>
+<phrase>
+ <source>New</source>
+ <target>Nytt</target>
+</phrase>
+<phrase>
+ <source>Next</source>
+ <target>Nästa</target>
+</phrase>
+<phrase>
+ <source>object</source>
+ <target>objekt</target>
+</phrase>
+<phrase>
+ <source>OK</source>
+ <target>OK</target>
+</phrase>
+<phrase>
+ <source>OLE</source>
+ <target>OLE</target>
+</phrase>
+<phrase>
+ <source>OLE drag and drop</source>
+ <target>dra och släpp (OLE)</target>
+</phrase>
+<phrase>
+ <source>OLE embedded object</source>
+ <target>inbäddat objekt (OLE)</target>
+</phrase>
+<phrase>
+ <source>OLE linked object</source>
+ <target>länkat objekt (OLE)</target>
+</phrase>
+<phrase>
+ <source>OLE nondefault drag and drop</source>
+ <target>utökat drag och släpp (OLE)</target>
+</phrase>
+<phrase>
+ <source>Open</source>
+ <target>Öppna</target>
+</phrase>
+<phrase>
+ <source>Open With</source>
+ <target>Öppna med</target>
+</phrase>
+<phrase>
+ <source>option button</source>
+ <target>alternativknapp</target>
+</phrase>
+<phrase>
+ <source>option-set</source>
+ <target>valt alternativ</target>
+</phrase>
+<phrase>
+ <source>package</source>
+ <target>paket</target>
+</phrase>
+<phrase>
+ <source>Page Setup</source>
+ <target>Utskriftsformat</target>
+</phrase>
+<phrase>
+ <source>palette window</source>
+ <target>palettfönster</target>
+</phrase>
+<phrase>
+ <source>pane</source>
+ <target>fönsterruta</target>
+</phrase>
+<phrase>
+ <source>parent window</source>
+ <target>moderfönster</target>
+</phrase>
+<phrase>
+ <source>password</source>
+ <target>lösenord</target>
+</phrase>
+<phrase>
+ <source>Paste</source>
+ <target>Klistra in</target>
+</phrase>
+<phrase>
+ <source>Paste Link</source>
+ <target>Klistra in länk</target>
+</phrase>
+<phrase>
+ <source>Paste Shortcut</source>
+ <target>Klistra in genväg</target>
+</phrase>
+<phrase>
+ <source>Paste Special</source>
+ <target>Klistra in special</target>
+</phrase>
+<phrase>
+ <source>path</source>
+ <target>sökväg</target>
+</phrase>
+<phrase>
+ <source>Pause</source>
+ <target>Paus</target>
+</phrase>
+<phrase>
+ <source>Play</source>
+ <target>Spela upp</target>
+</phrase>
+<phrase>
+ <source>Plug and Play</source>
+ <target>Plug and Play</target>
+</phrase>
+<phrase>
+ <source>point</source>
+ <target>peka</target>
+</phrase>
+<phrase>
+ <source>pointer</source>
+ <target>pekare</target>
+</phrase>
+<phrase>
+ <source>pop-up menu</source>
+ <target>pop up-meny</target>
+</phrase>
+<phrase>
+ <source>pop-up window</source>
+ <target>pop up-fönster</target>
+</phrase>
+<phrase>
+ <source>portrait</source>
+ <target>stående</target>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>håll ned</target>
+ <definition>and hold a mouse button</definition>
+</phrase>
+<phrase>
+ <source>press</source>
+ <target>tryck på</target>
+ <definition>a key</definition>
+</phrase>
+<phrase>
+ <source>primary container</source>
+ <target>primär behållare</target>
+</phrase>
+<phrase>
+ <source>primary window</source>
+ <target>primärt fönster</target>
+</phrase>
+<phrase>
+ <source>Print</source>
+ <target>Skriv ut</target>
+</phrase>
+<phrase>
+ <source>printer</source>
+ <target>skrivare</target>
+</phrase>
+<phrase>
+ <source>progress indicator</source>
+ <target>förloppsindikator</target>
+ <definition>control</definition>
+</phrase>
+<phrase>
+ <source>project</source>
+ <target>projekt</target>
+</phrase>
+<phrase>
+ <source>Properties</source>
+ <target>Egenskaper</target>
+</phrase>
+<phrase>
+ <source>property inspector</source>
+ <target>egenskapsgranskare</target>
+</phrase>
+<phrase>
+ <source>property page</source>
+ <target>egenskapssida</target>
+</phrase>
+<phrase>
+ <source>property sheet</source>
+ <target>egenskapsförteckning</target>
+</phrase>
+<phrase>
+ <source>property sheet control</source>
+ <target>kontroll i egenskapsförteckning</target>
+</phrase>
+<phrase>
+ <source>Quick View</source>
+ <target>Snabbgranskning</target>
+</phrase>
+<phrase>
+ <source>read-only</source>
+ <target>skrivskydd</target>
+</phrase>
+<phrase>
+ <source>Recycle Bin</source>
+ <target>Papperskorgen</target>
+ <definition>Icon</definition>
+</phrase>
+<phrase>
+ <source>Redo</source>
+ <target>Gör om</target>
+</phrase>
+<phrase>
+ <source>region selection</source>
+ <target>områdesmarkering</target>
+</phrase>
+<phrase>
+ <source>registry</source>
+ <target>Registret</target>
+</phrase>
+<phrase>
+ <source>Repeat</source>
+ <target>Upprepa</target>
+</phrase>
+<phrase>
+ <source>Replace</source>
+ <target>Ersätt</target>
+</phrase>
+<phrase>
+ <source>Restore</source>
+ <target>Återställ</target>
+</phrase>
+<phrase>
+ <source>Restore button</source>
+ <target>knappen Återställ</target>
+</phrase>
+<phrase>
+ <source>Resume</source>
+ <target>Fortsätt</target>
+</phrase>
+<phrase>
+ <source>Retry</source>
+ <target>Försök igen</target>
+</phrase>
+<phrase>
+ <source>rich-text box</source>
+ <target>rich text-ruta</target>
+</phrase>
+<phrase>
+ <source>Run</source>
+ <target>Kör</target>
+</phrase>
+<phrase>
+ <source>Save</source>
+ <target>Spara</target>
+</phrase>
+<phrase>
+ <source>Save as</source>
+ <target>Spara som</target>
+</phrase>
+<phrase>
+ <source>scroll</source>
+ <target>rulla</target>
+</phrase>
+<phrase>
+ <source>scroll arrow</source>
+ <target>rullningspil</target>
+</phrase>
+<phrase>
+ <source>scroll bar</source>
+ <target>rullningslist</target>
+</phrase>
+<phrase>
+ <source>scroll box</source>
+ <target>rullningsruta</target>
+</phrase>
+<phrase>
+ <source>secondary window</source>
+ <target>sekundärt fönster</target>
+</phrase>
+<phrase>
+ <source>select</source>
+ <target>markera</target>
+</phrase>
+<phrase>
+ <source>Select All</source>
+ <target>Markera allt</target>
+</phrase>
+<phrase>
+ <source>selection</source>
+ <target>markering</target>
+</phrase>
+<phrase>
+ <source>selection handle</source>
+ <target>markeringshandtag</target>
+</phrase>
+<phrase>
+ <source>Send To</source>
+ <target>Skicka till</target>
+</phrase>
+<phrase>
+ <source>separator</source>
+ <target>avgränsare</target>
+</phrase>
+<phrase>
+ <source>Settings</source>
+ <target>Inställningar</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>installationsprogram</target>
+</phrase>
+<phrase>
+ <source>Setup</source>
+ <target>Inställningar</target>
+</phrase>
+<phrase>
+ <source>shortcut</source>
+ <target>genväg</target>
+</phrase>
+<phrase>
+ <source>shortcut button</source>
+ <target>genvägsknapp</target>
+</phrase>
+<phrase>
+ <source>shortcut icon</source>
+ <target>genvägsikon</target>
+</phrase>
+<phrase>
+ <source>shortcut key</source>
+ <target>kortkommando</target>
+</phrase>
+<phrase>
+ <source>shortcut key control</source>
+ <target>kortkommandokontroll</target>
+</phrase>
+<phrase>
+ <source>Show</source>
+ <target>Visa</target>
+</phrase>
+<phrase>
+ <source>Shutdown</source>
+ <target>Avsluta</target>
+</phrase>
+<phrase>
+ <source>single selection list box</source>
+ <target>listruta för enkel markering</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Ändra storlek</target>
+</phrase>
+<phrase>
+ <source>Size</source>
+ <target>Storlek</target>
+</phrase>
+<phrase>
+ <source>size grip</source>
+ <target>storleksgrepp</target>
+</phrase>
+<phrase>
+ <source>slider</source>
+ <target>skjutreglage</target>
+</phrase>
+<phrase>
+ <source>spin box</source>
+ <target>rotationsruta</target>
+</phrase>
+<phrase>
+ <source>Split</source>
+ <target>Dela</target>
+</phrase>
+<phrase>
+ <source>split bar</source>
+ <target>delningslist</target>
+</phrase>
+<phrase>
+ <source>split box</source>
+ <target>delningsruta</target>
+</phrase>
+<phrase>
+ <source>Start button</source>
+ <target>startknappen</target>
+</phrase>
+<phrase>
+ <source>StartUp folder</source>
+ <target>mappen Autostart</target>
+</phrase>
+<phrase>
+ <source>status bar</source>
+ <target>statusfält</target>
+</phrase>
+<phrase>
+ <source>Stop</source>
+ <target>Stanna</target>
+</phrase>
+<phrase>
+ <source>tab control</source>
+ <target>flik</target>
+</phrase>
+<phrase>
+ <source>task bar</source>
+ <target>Aktivitetsfältet</target>
+</phrase>
+<phrase>
+ <source>task-oriented Help</source>
+ <target>aktivitetsberoende hjälp</target>
+</phrase>
+<phrase>
+ <source>template</source>
+ <target>mall</target>
+</phrase>
+<phrase>
+ <source>text box</source>
+ <target>textruta</target>
+</phrase>
+<phrase>
+ <source>title bar</source>
+ <target>namnlist</target>
+</phrase>
+<phrase>
+ <source>title text</source>
+ <target>text i namnlist</target>
+</phrase>
+<phrase>
+ <source>toggle key</source>
+ <target>växlingstangent</target>
+</phrase>
+<phrase>
+ <source>toolbar</source>
+ <target>verktygsfält</target>
+</phrase>
+<phrase>
+ <source>tooltip</source>
+ <target>funktionsbeskrivning</target>
+</phrase>
+<phrase>
+ <source>tree view control</source>
+ <target>trädkontroll</target>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>typ</target>
+ <definition>noun</definition>
+</phrase>
+<phrase>
+ <source>type</source>
+ <target>skriva</target>
+ <definition>verb</definition>
+</phrase>
+<phrase>
+ <source>unavailable</source>
+ <target>ej tillgänglig</target>
+</phrase>
+<phrase>
+ <source>Undo</source>
+ <target>Ångra</target>
+</phrase>
+<phrase>
+ <source>Uninstall</source>
+ <target>Avinstallera</target>
+</phrase>
+<phrase>
+ <source>View</source>
+ <target>Visa-meny</target>
+</phrase>
+<phrase>
+ <source>visual editing</source>
+ <target>direktredigering</target>
+</phrase>
+<phrase>
+ <source>well control</source>
+ <target>grafikkontroll</target>
+</phrase>
+<phrase>
+ <source>What&apos;s This?</source>
+ <target>Förklaring</target>
+</phrase>
+<phrase>
+ <source>Window</source>
+ <target>Fönster-meny</target>
+</phrase>
+<phrase>
+ <source>window</source>
+ <target>fönster</target>
+</phrase>
+<phrase>
+ <source>Windows Explorer</source>
+ <target>Utforskaren</target>
+</phrase>
+<phrase>
+ <source>wizard</source>
+ <target>guide</target>
+</phrase>
+<phrase>
+ <source>workbook</source>
+ <target>arbetsbok</target>
+</phrase>
+<phrase>
+ <source>workgroup</source>
+ <target>arbetsgrupp</target>
+</phrase>
+<phrase>
+ <source>workspace</source>
+ <target>arbetsyta</target>
+</phrase>
+<phrase>
+ <source>Yes</source>
+ <target>Ja</target>
+</phrase>
+</QPH>
diff --git a/tools/linguist/qdoc.conf b/tools/linguist/qdoc.conf
new file mode 100644
index 0000000000..a89fb6402d
--- /dev/null
+++ b/tools/linguist/qdoc.conf
@@ -0,0 +1,15 @@
+SOURCEDIRS = $QTDIR/tools/linguist/doc
+DOCDIRS = $QTDIR/tools/linguist/doc
+EXAMPLEDIRS = $QTDIR/tools/linguist/tutorial
+OUTPUTDIR = $QTDIR/tools/linguist/doc/html
+BASE = file:$QTDIR/tools/linguist/doc/html/
+COMPANY = Trolltech
+PRODUCT = Qt Linguist
+VERSIONSYM = QT_VERSION_STR
+DEFINE = QT_QDOC QT_.*_SUPPORT _WS_.*_
+FALSE = 0 1
+INTERNAL = no
+STYLE = "h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; }
+a:link { color: #af4f00; text-decoration: none }
+a:visited { color: #8f2f00; text-decoration: none }
+body { background: #ffffff; color: black; }"
diff --git a/tools/linguist/shared/abstractproitemvisitor.h b/tools/linguist/shared/abstractproitemvisitor.h
new file mode 100644
index 0000000000..b108e7e8aa
--- /dev/null
+++ b/tools/linguist/shared/abstractproitemvisitor.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTPROITEMVISITOR
+#define ABSTRACTPROITEMVISITOR
+
+#include "proitems.h"
+
+QT_BEGIN_NAMESPACE
+
+struct AbstractProItemVisitor
+{
+ virtual ~AbstractProItemVisitor() {}
+ virtual bool visitBeginProBlock(ProBlock *block) = 0;
+ virtual bool visitEndProBlock(ProBlock *block) = 0;
+
+ virtual bool visitBeginProVariable(ProVariable *variable) = 0;
+ virtual bool visitEndProVariable(ProVariable *variable) = 0;
+
+ virtual bool visitBeginProFile(ProFile *value) = 0;
+ virtual bool visitEndProFile(ProFile *value) = 0;
+
+ virtual bool visitProValue(ProValue *value) = 0;
+ virtual bool visitProFunction(ProFunction *function) = 0;
+ virtual bool visitProOperator(ProOperator *function) = 0;
+ virtual bool visitProCondition(ProCondition *function) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // ABSTRACTPROITEMVISITOR
+
diff --git a/tools/linguist/shared/cpp.cpp b/tools/linguist/shared/cpp.cpp
new file mode 100644
index 0000000000..28616cc4bb
--- /dev/null
+++ b/tools/linguist/shared/cpp.cpp
@@ -0,0 +1,1074 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QStack>
+#include <QtCore/QString>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+#include <ctype.h> // for isXXX()
+
+QT_BEGIN_NAMESPACE
+
+/* qmake ignore Q_OBJECT */
+
+static const char MagicComment[] = "TRANSLATOR ";
+
+static QSet<QString> needs_Q_OBJECT;
+static QSet<QString> lacks_Q_OBJECT;
+
+static const int yyIdentMaxLen = 128;
+static const int yyCommentMaxLen = 65536;
+static const int yyStringMaxLen = 65536;
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+#define STRING(s) static QString str##s(QLatin1String(STRINGIFY(s)))
+
+//#define DIAGNOSE_RETRANSLATABILITY
+/*
+ The first part of this source file is the C++ tokenizer. We skip
+ most of C++; the only tokens that interest us are defined here.
+ Thus, the code fragment
+
+ int main()
+ {
+ printf("Hello, world!\n");
+ return 0;
+ }
+
+ is broken down into the following tokens (Tok_ omitted):
+
+ Ident Ident LeftParen RightParen
+ LeftBrace
+ Ident LeftParen String RightParen Semicolon
+ return Semicolon
+ RightBrace.
+
+ The 0 doesn't produce any token.
+*/
+
+enum {
+ Tok_Eof, Tok_class, Tok_namespace, Tok_return,
+ Tok_tr = 10, Tok_trUtf8, Tok_translate, Tok_translateUtf8,
+ Tok_Q_OBJECT = 20, Tok_Q_DECLARE_TR_FUNCTIONS,
+ Tok_Ident, Tok_Comment, Tok_String, Tok_Arrow, Tok_Colon, Tok_ColonColon,
+ Tok_Equals,
+ Tok_LeftBrace = 30, Tok_RightBrace, Tok_LeftParen, Tok_RightParen, Tok_Comma, Tok_Semicolon,
+ Tok_Integer = 40,
+ Tok_Other
+};
+
+/*
+ The tokenizer maintains the following global variables. The names
+ should be self-explanatory.
+*/
+static QString yyFileName;
+static int yyCh;
+static bool yyCodecIsUtf8;
+static bool yyForceUtf8;
+static QString yyIdent;
+static QString yyComment;
+static QString yyString;
+static qlonglong yyInteger;
+static QStack<int> yySavedBraceDepth;
+static QStack<int> yySavedParenDepth;
+static int yyBraceDepth;
+static int yyParenDepth;
+static int yyLineNo;
+static int yyCurLineNo;
+static int yyBraceLineNo;
+static int yyParenLineNo;
+static bool yyTokColonSeen = false;
+
+// the string to read from and current position in the string
+static QTextCodec *yySourceCodec;
+static bool yySourceIsUnicode;
+static QString yyInStr;
+static int yyInPos;
+
+static uint getChar()
+{
+ if (yyInPos >= yyInStr.size())
+ return EOF;
+ QChar c = yyInStr[yyInPos++];
+ if (c.unicode() == '\n')
+ ++yyCurLineNo;
+ return c.unicode();
+}
+
+static uint getToken()
+{
+ yyIdent.clear();
+ yyComment.clear();
+ yyString.clear();
+
+ while (yyCh != EOF) {
+ yyLineNo = yyCurLineNo;
+
+ if (isalpha(yyCh) || yyCh == '_') {
+ do {
+ yyIdent += yyCh;
+ yyCh = getChar();
+ } while (isalnum(yyCh) || yyCh == '_');
+
+ //qDebug() << "IDENT: " << yyIdent;
+
+ switch (yyIdent.at(0).unicode()) {
+ case 'Q':
+ if (yyIdent == QLatin1String("Q_OBJECT"))
+ return Tok_Q_OBJECT;
+ if (yyIdent == QLatin1String("Q_DECLARE_TR_FUNCTIONS"))
+ return Tok_Q_DECLARE_TR_FUNCTIONS;
+ if (yyIdent == QLatin1String("QT_TR_NOOP"))
+ return Tok_tr;
+ if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP"))
+ return Tok_translate;
+ if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP3"))
+ return Tok_translate;
+ if (yyIdent == QLatin1String("QT_TR_NOOP_UTF8"))
+ return Tok_trUtf8;
+ if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP_UTF8"))
+ return Tok_translateUtf8;
+ if (yyIdent == QLatin1String("QT_TRANSLATE_NOOP3_UTF8"))
+ return Tok_translateUtf8;
+ break;
+ case 'T':
+ // TR() for when all else fails
+ if (yyIdent.compare(QLatin1String("TR"), Qt::CaseInsensitive) == 0) {
+ return Tok_tr;
+ }
+ break;
+ case 'c':
+ if (yyIdent == QLatin1String("class"))
+ return Tok_class;
+ break;
+ case 'f':
+ /*
+ QTranslator::findMessage() has the same parameters as
+ QApplication::translate().
+ */
+ if (yyIdent == QLatin1String("findMessage"))
+ return Tok_translate;
+ break;
+ case 'n':
+ if (yyIdent == QLatin1String("namespace"))
+ return Tok_namespace;
+ break;
+ case 'r':
+ if (yyIdent == QLatin1String("return"))
+ return Tok_return;
+ break;
+ case 's':
+ if (yyIdent == QLatin1String("struct"))
+ return Tok_class;
+ break;
+ case 't':
+ if (yyIdent == QLatin1String("tr")) {
+ return Tok_tr;
+ }
+ if (yyIdent == QLatin1String("trUtf8")) {
+ return Tok_trUtf8;
+ }
+ if (yyIdent == QLatin1String("translate")) {
+ return Tok_translate;
+ }
+ }
+ return Tok_Ident;
+ } else {
+ switch (yyCh) {
+ case '#':
+ /*
+ Early versions of lupdate complained about
+ unbalanced braces in the following code:
+
+ #ifdef ALPHA
+ while (beta) {
+ #else
+ while (gamma) {
+ #endif
+ delta;
+ }
+
+ The code contains, indeed, two opening braces for
+ one closing brace; yet there's no reason to panic.
+
+ The solution is to remember yyBraceDepth as it was
+ when #if, #ifdef or #ifndef was met, and to set
+ yyBraceDepth to that value when meeting #elif or
+ #else.
+ */
+ do {
+ yyCh = getChar();
+ } while (isspace(yyCh) && yyCh != '\n');
+
+ switch (yyCh) {
+ case 'i':
+ yyCh = getChar();
+ if (yyCh == 'f') {
+ // if, ifdef, ifndef
+ yySavedBraceDepth.push(yyBraceDepth);
+ yySavedParenDepth.push(yyParenDepth);
+ }
+ break;
+ case 'e':
+ yyCh = getChar();
+ if (yyCh == 'l') {
+ // elif, else
+ if (!yySavedBraceDepth.isEmpty()) {
+ yyBraceDepth = yySavedBraceDepth.top();
+ yyParenDepth = yySavedParenDepth.top();
+ }
+ } else if (yyCh == 'n') {
+ // endif
+ if (!yySavedBraceDepth.isEmpty()) {
+ yySavedBraceDepth.pop();
+ yySavedParenDepth.pop();
+ }
+ }
+ }
+ while (isalnum(yyCh) || yyCh == '_')
+ yyCh = getChar();
+ break;
+ case '/':
+ yyCh = getChar();
+ if (yyCh == '/') {
+ do {
+ yyCh = getChar();
+ if (yyCh == EOF)
+ break;
+ yyComment.append(yyCh);
+ } while (yyCh != '\n');
+ } else if (yyCh == '*') {
+ bool metAster = false;
+ bool metAsterSlash = false;
+
+ while (!metAsterSlash) {
+ yyCh = getChar();
+ if (yyCh == EOF) {
+ qWarning("%s: Unterminated C++ comment starting at"
+ " line %d\n",
+ qPrintable(yyFileName), yyLineNo);
+ return Tok_Comment;
+ }
+ yyComment.append(yyCh);
+
+ if (yyCh == '*')
+ metAster = true;
+ else if (metAster && yyCh == '/')
+ metAsterSlash = true;
+ else
+ metAster = false;
+ }
+ yyCh = getChar();
+ yyComment.chop(2);
+ }
+ return Tok_Comment;
+ case '"':
+ yyCh = getChar();
+ while (yyCh != EOF && yyCh != '\n' && yyCh != '"') {
+ if (yyCh == '\\') {
+ yyCh = getChar();
+ if (yyString.size() < yyStringMaxLen) {
+ yyString.append(QLatin1Char('\\'));
+ yyString.append(yyCh);
+ }
+ } else {
+ if (yyString.size() < yyStringMaxLen)
+ yyString.append(yyCh);
+ }
+ yyCh = getChar();
+ }
+
+ if (yyCh != '"')
+ qWarning("%s:%d: Unterminated C++ string",
+ qPrintable(yyFileName), yyLineNo);
+
+ if (yyCh == EOF)
+ return Tok_Eof;
+ yyCh = getChar();
+ return Tok_String;
+ case '-':
+ yyCh = getChar();
+ if (yyCh == '>') {
+ yyCh = getChar();
+ return Tok_Arrow;
+ }
+ break;
+ case ':':
+ yyCh = getChar();
+ if (yyCh == ':') {
+ yyCh = getChar();
+ return Tok_ColonColon;
+ }
+ return Tok_Colon;
+ // Incomplete: '<' might be part of '<=' or of template syntax.
+ // The main intent of not completely ignoring it is to break
+ // parsing of things like std::cout << QObject::tr() as
+ // context std::cout::QObject (see Task 161106)
+ case '=':
+ yyCh = getChar();
+ return Tok_Equals;
+ case '>':
+ case '<':
+ yyCh = getChar();
+ return Tok_Other;
+ case '\'':
+ yyCh = getChar();
+ if (yyCh == '\\')
+ yyCh = getChar();
+
+ do {
+ yyCh = getChar();
+ } while (yyCh != EOF && yyCh != '\'');
+ yyCh = getChar();
+ break;
+ case '{':
+ if (yyBraceDepth == 0)
+ yyBraceLineNo = yyCurLineNo;
+ yyBraceDepth++;
+ yyCh = getChar();
+ return Tok_LeftBrace;
+ case '}':
+ if (yyBraceDepth == 0)
+ yyBraceLineNo = yyCurLineNo;
+ yyBraceDepth--;
+ yyCh = getChar();
+ return Tok_RightBrace;
+ case '(':
+ if (yyParenDepth == 0)
+ yyParenLineNo = yyCurLineNo;
+ yyParenDepth++;
+ yyCh = getChar();
+ return Tok_LeftParen;
+ case ')':
+ if (yyParenDepth == 0)
+ yyParenLineNo = yyCurLineNo;
+ yyParenDepth--;
+ yyCh = getChar();
+ return Tok_RightParen;
+ case ',':
+ yyCh = getChar();
+ return Tok_Comma;
+ case ';':
+ yyCh = getChar();
+ return Tok_Semicolon;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ QByteArray ba;
+ ba += yyCh;
+ yyCh = getChar();
+ bool hex = yyCh == 'x';
+ if (hex) {
+ ba += yyCh;
+ yyCh = getChar();
+ }
+ while (hex ? isxdigit(yyCh) : isdigit(yyCh)) {
+ ba += yyCh;
+ yyCh = getChar();
+ }
+ bool ok;
+ yyInteger = ba.toLongLong(&ok);
+ if (ok)
+ return Tok_Integer;
+ break;
+ }
+ default:
+ yyCh = getChar();
+ break;
+ }
+ }
+ }
+ return Tok_Eof;
+}
+
+/*
+ The second part of this source file is the parser. It accomplishes
+ a very easy task: It finds all strings inside a tr() or translate()
+ call, and possibly finds out the context of the call. It supports
+ three cases: (1) the context is specified, as in
+ FunnyDialog::tr("Hello") or translate("FunnyDialog", "Hello");
+ (2) the call appears within an inlined function; (3) the call
+ appears within a function defined outside the class definition.
+*/
+
+static uint yyTok;
+
+static bool match(uint t)
+{
+ bool matches = (yyTok == t);
+ if (matches)
+ yyTok = getToken();
+ return matches;
+}
+
+static bool matchString(QString *s)
+{
+ bool matches = (yyTok == Tok_String);
+ s->clear();
+ while (yyTok == Tok_String) {
+ *s += yyString;
+ yyTok = getToken();
+ }
+ return matches;
+}
+
+static bool matchEncoding(bool *utf8)
+{
+ STRING(QApplication);
+ STRING(QCoreApplication);
+ STRING(UnicodeUTF8);
+ STRING(DefaultCodec);
+ STRING(CodecForTr);
+
+ if (yyTok != Tok_Ident)
+ return false;
+ if (yyIdent == strQApplication || yyIdent == strQCoreApplication) {
+ yyTok = getToken();
+ if (yyTok == Tok_ColonColon)
+ yyTok = getToken();
+ }
+ if (yyIdent == strUnicodeUTF8) {
+ *utf8 = true;
+ yyTok = getToken();
+ return true;
+ }
+ if (yyIdent == strDefaultCodec || yyIdent == strCodecForTr) {
+ *utf8 = false;
+ yyTok = getToken();
+ return true;
+ }
+ return false;
+}
+
+static bool matchInteger(qlonglong *number)
+{
+ bool matches = (yyTok == Tok_Integer);
+ if (matches) {
+ yyTok = getToken();
+ *number = yyInteger;
+ }
+ return matches;
+}
+
+static bool matchStringOrNull(QString *s)
+{
+ bool matches = matchString(s);
+ qlonglong num = 0;
+ if (!matches)
+ matches = matchInteger(&num);
+ return matches && num == 0;
+}
+
+/*
+ * match any expression that can return a number, which can be
+ * 1. Literal number (e.g. '11')
+ * 2. simple identifier (e.g. 'm_count')
+ * 3. simple function call (e.g. 'size()' )
+ * 4. function call on an object (e.g. 'list.size()')
+ * 5. function call on an object (e.g. 'list->size()')
+ *
+ * Other cases:
+ * size(2,4)
+ * list().size()
+ * list(a,b).size(2,4)
+ * etc...
+ */
+static bool matchExpression()
+{
+ if (match(Tok_Integer))
+ return true;
+
+ int parenlevel = 0;
+ while (match(Tok_Ident) || parenlevel > 0) {
+ if (yyTok == Tok_RightParen) {
+ if (parenlevel == 0) break;
+ --parenlevel;
+ yyTok = getToken();
+ } else if (yyTok == Tok_LeftParen) {
+ yyTok = getToken();
+ if (yyTok == Tok_RightParen) {
+ yyTok = getToken();
+ } else {
+ ++parenlevel;
+ }
+ } else if (yyTok == Tok_Ident) {
+ continue;
+ } else if (yyTok == Tok_Arrow) {
+ yyTok = getToken();
+ } else if (parenlevel == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static QStringList resolveNamespaces(
+ const QStringList &namespaces, const QHash<QString, QStringList> &namespaceAliases)
+{
+ static QString strColons(QLatin1String("::"));
+
+ QStringList ns;
+ foreach (const QString &cns, namespaces) {
+ ns << cns;
+ ns = namespaceAliases.value(ns.join(strColons), ns);
+ }
+ return ns;
+}
+
+static QStringList getFullyQualifiedNamespaceName(
+ const QSet<QString> &allNamespaces, const QStringList &namespaces,
+ const QHash<QString, QStringList> &namespaceAliases,
+ const QStringList &segments)
+{
+ static QString strColons(QLatin1String("::"));
+
+ if (segments.first().isEmpty()) {
+ // fully qualified
+ QStringList segs = segments;
+ segs.removeFirst();
+ return resolveNamespaces(segs, namespaceAliases);
+ } else {
+ for (int n = namespaces.count(); --n >= -1; ) {
+ QStringList ns;
+ for (int i = 0; i <= n; ++i) // Note: n == -1 possible
+ ns << namespaces[i];
+ foreach (const QString &cns, segments) {
+ ns << cns;
+ ns = namespaceAliases.value(ns.join(strColons), ns);
+ }
+ if (allNamespaces.contains(ns.join(strColons)))
+ return ns;
+ }
+
+ // Fallback when the namespace was declared in a header, etc.
+ QStringList ns = namespaces;
+ ns += segments;
+ return ns;
+ }
+}
+
+static QString getFullyQualifiedClassName(
+ const QSet<QString> &allClasses, const QStringList &namespaces,
+ const QHash<QString, QStringList> &namespaceAliases,
+ const QString &ident, bool hasPrefix)
+{
+ static QString strColons(QLatin1String("::"));
+
+ QString context = ident;
+ QStringList segments = context.split(strColons);
+ if (segments.first().isEmpty()) {
+ // fully qualified
+ segments.removeFirst();
+ context = resolveNamespaces(segments, namespaceAliases).join(strColons);
+ } else {
+ for (int n = namespaces.count(); --n >= -1; ) {
+ QStringList ns;
+ for (int i = 0; i <= n; ++i) // Note: n == -1 possible
+ ns.append(namespaces[i]);
+ foreach (const QString &cns, segments) {
+ ns.append(cns);
+ ns = namespaceAliases.value(ns.join(strColons), ns);
+ }
+ QString nctx = ns.join(strColons);
+ if (allClasses.contains(nctx)) {
+ context = nctx;
+ goto gotit;
+ }
+ }
+
+ if (!hasPrefix && namespaces.count())
+ context = namespaces.join(strColons) + strColons + context;
+ }
+gotit:
+ //qDebug() << "CLASSES:" << allClasses << "NAMEPACES:" << namespaces
+ // << "IDENT:" << ident << "CONTEXT:" << context;
+ return context;
+}
+
+
+static QString transcode(const QString &str, bool utf8)
+{
+ static const char tab[] = "abfnrtv";
+ static const char backTab[] = "\a\b\f\n\r\t\v";
+ const QString in = (!utf8 || yySourceIsUnicode)
+ ? str : QString::fromUtf8(yySourceCodec->fromUnicode(str).data());
+ QString out;
+
+ out.reserve(in.length());
+ for (int i = 0; i < in.length();) {
+ ushort c = in[i++].unicode();
+ if (c == '\\') {
+ if (i >= in.length())
+ break;
+ c = in[i++].unicode();
+
+ if (c == '\n')
+ continue;
+
+ if (c == 'x') {
+ QByteArray hex;
+ while (i < in.length() && isxdigit((c = in[i].unicode()))) {
+ hex += c;
+ i++;
+ }
+ out += hex.toUInt(0, 16);
+ } else if (c >= '0' && c < '8') {
+ QByteArray oct;
+ int n = 0;
+ oct += c;
+ while (n < 2 && i < in.length() && (c = in[i].unicode()) >= '0' && c < '8') {
+ i++;
+ n++;
+ oct += c;
+ }
+ out += oct.toUInt(0, 8);
+ } else {
+ const char *p = strchr(tab, c);
+ out += QChar(QLatin1Char(!p ? c : backTab[p - tab]));
+ }
+ } else {
+ out += c;
+ }
+ }
+ return out;
+}
+
+static void recordMessage(
+ Translator *tor, int line, const QString &context, const QString &text, const QString &comment,
+ const QString &extracomment, bool utf8, bool plural)
+{
+ TranslatorMessage msg(
+ transcode(context, utf8), transcode(text, utf8), transcode(comment, utf8), QString(),
+ yyFileName, line, QStringList(),
+ TranslatorMessage::Unfinished, plural);
+ msg.setExtraComment(transcode(extracomment.simplified(), utf8));
+ if ((utf8 || yyForceUtf8) && !yyCodecIsUtf8 && msg.needs8Bit())
+ msg.setUtf8(true);
+ tor->extend(msg);
+}
+
+static void parse(Translator *tor, const QString &initialContext, const QString &defaultContext)
+{
+ static QString strColons(QLatin1String("::"));
+
+ QMap<QString, QString> qualifiedContexts;
+ QSet<QString> allClasses;
+ QSet<QString> allNamespaces;
+ QHash<QString, QStringList> namespaceAliases;
+ QStringList namespaces;
+ QString context;
+ QString text;
+ QString comment;
+ QString extracomment;
+ QString functionContext = initialContext;
+ QString prefix;
+#ifdef DIAGNOSE_RETRANSLATABILITY
+ QString functionName;
+#endif
+ int line;
+ bool utf8 = false;
+ bool missing_Q_OBJECT = false;
+
+ yyTok = getToken();
+ while (yyTok != Tok_Eof) {
+ //qDebug() << "TOKEN: " << yyTok;
+ switch (yyTok) {
+ case Tok_class:
+ yyTokColonSeen = false;
+ /*
+ Partial support for inlined functions.
+ */
+ yyTok = getToken();
+ if (yyBraceDepth == namespaces.count() && yyParenDepth == 0) {
+ QStringList fct;
+ do {
+ /*
+ This code should execute only once, but we play
+ safe with impure definitions such as
+ 'class Q_EXPORT QMessageBox', in which case
+ 'QMessageBox' is the class name, not 'Q_EXPORT'.
+ */
+ fct = QStringList(yyIdent);
+ yyTok = getToken();
+ } while (yyTok == Tok_Ident);
+ while (yyTok == Tok_ColonColon) {
+ yyTok = getToken();
+ if (yyTok != Tok_Ident)
+ break; // Oops ...
+ fct += yyIdent;
+ yyTok = getToken();
+ }
+ functionContext = resolveNamespaces(namespaces + fct, namespaceAliases).join(strColons);
+ allClasses.insert(functionContext);
+
+ if (yyTok == Tok_Colon) {
+ missing_Q_OBJECT = true;
+ // Skip any token until '{' since lupdate might do things wrong if it finds
+ // a '::' token here.
+ do {
+ yyTok = getToken();
+ } while (yyTok != Tok_LeftBrace && yyTok != Tok_Eof);
+ } else {
+ //functionContext = defaultContext;
+ }
+ }
+ break;
+ case Tok_namespace:
+ yyTokColonSeen = false;
+ yyTok = getToken();
+ if (yyTok == Tok_Ident) {
+ QString ns = yyIdent;
+ yyTok = getToken();
+ if (yyTok == Tok_LeftBrace) {
+ if (yyBraceDepth == namespaces.count() + 1) {
+ namespaces.append(ns);
+ allNamespaces.insert(namespaces.join(strColons));
+ }
+ } else if (yyTok == Tok_Equals) {
+ // e.g. namespace Is = OuterSpace::InnerSpace;
+ QStringList alias = namespaces;
+ alias.append(ns);
+ QStringList fullName;
+ yyTok = getToken();
+ if (yyTok == Tok_ColonColon)
+ fullName.append(QString());
+ while (yyTok == Tok_ColonColon || yyTok == Tok_Ident) {
+ if (yyTok == Tok_Ident)
+ fullName.append(yyIdent);
+ yyTok = getToken();
+ }
+ namespaceAliases[alias.join(strColons)] =
+ getFullyQualifiedNamespaceName(allNamespaces, namespaces, namespaceAliases, fullName);
+ }
+ }
+ break;
+ case Tok_tr:
+ case Tok_trUtf8:
+ utf8 = (yyTok == Tok_trUtf8);
+ line = yyLineNo;
+ yyTok = getToken();
+ if (match(Tok_LeftParen) && matchString(&text) && !text.isEmpty()) {
+ comment.clear();
+ bool plural = false;
+
+ if (match(Tok_RightParen)) {
+ // no comment
+ } else if (match(Tok_Comma) && matchStringOrNull(&comment)) { //comment
+ if (match(Tok_RightParen)) {
+ // ok,
+ } else if (match(Tok_Comma)) {
+ plural = true;
+ }
+ }
+ if (prefix.isEmpty()) {
+ context = functionContext;
+ } else {
+#ifdef DIAGNOSE_RETRANSLATABILITY
+ int last = prefix.lastIndexOf(strColons);
+ QString className = prefix.mid(last == -1 ? 0 : last + 2);
+ if (!className.isEmpty() && className == functionName) {
+ qWarning("%s::%d: It is not recommended to call tr() from within a constructor '%s::%s' ",
+ qPrintable(yyFileName), yyLineNo,
+ className.constData(), functionName.constData());
+ }
+#endif
+ prefix.chop(2);
+ context = getFullyQualifiedClassName(allClasses, namespaces, namespaceAliases, prefix, true);
+ }
+ prefix.clear();
+ if (qualifiedContexts.contains(context))
+ context = qualifiedContexts[context];
+
+ if (!text.isEmpty())
+ recordMessage(tor, line, context, text, comment, extracomment, utf8, plural);
+
+ if (lacks_Q_OBJECT.contains(context)) {
+ qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro",
+ qPrintable(yyFileName), yyLineNo,
+ qPrintable(context));
+ lacks_Q_OBJECT.remove(context);
+ } else {
+ needs_Q_OBJECT.insert(context);
+ }
+ }
+ extracomment.clear();
+ break;
+ case Tok_translateUtf8:
+ case Tok_translate:
+ utf8 = (yyTok == Tok_translateUtf8);
+ line = yyLineNo;
+ yyTok = getToken();
+ if (match(Tok_LeftParen)
+ && matchString(&context)
+ && match(Tok_Comma)
+ && matchString(&text))
+ {
+ comment.clear();
+ bool plural = false;
+ if (!match(Tok_RightParen)) {
+ // look for comment
+ if (match(Tok_Comma) && matchStringOrNull(&comment)) {
+ if (!match(Tok_RightParen)) {
+ // look for encoding
+ if (match(Tok_Comma)) {
+ if (matchEncoding(&utf8)) {
+ if (!match(Tok_RightParen)) {
+ // look for the plural quantifier,
+ // this can be a number, an identifier or
+ // a function call,
+ // so for simplicity we mark it as plural if
+ // we know we have a comma instead of an
+ // right parentheses.
+ plural = match(Tok_Comma);
+ }
+ } else {
+ // This can be a QTranslator::translate("context",
+ // "source", "comment", n) plural translation
+ if (matchExpression() && match(Tok_RightParen)) {
+ plural = true;
+ } else {
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ if (!text.isEmpty())
+ recordMessage(tor, line, context, text, comment, extracomment, utf8, plural);
+ }
+ extracomment.clear();
+ break;
+ case Tok_Q_DECLARE_TR_FUNCTIONS:
+ case Tok_Q_OBJECT:
+ missing_Q_OBJECT = false;
+ yyTok = getToken();
+ break;
+ case Tok_Ident:
+ prefix += yyIdent;
+ yyTok = getToken();
+ if (yyTok != Tok_ColonColon)
+ prefix.clear();
+ break;
+ case Tok_Comment:
+ if (yyComment.startsWith(QLatin1Char(':'))) {
+ yyComment.remove(0, 1);
+ extracomment.append(yyComment);
+ } else {
+ comment = yyComment.simplified();
+ if (comment.startsWith(QLatin1String(MagicComment))) {
+ comment.remove(0, sizeof(MagicComment) - 1);
+ int k = comment.indexOf(QLatin1Char(' '));
+ if (k == -1) {
+ context = comment;
+ } else {
+ context = comment.left(k);
+ comment.remove(0, k + 1);
+ recordMessage(tor, yyLineNo, context, QString(), comment, extracomment, false, false);
+ }
+
+ /*
+ Provide a backdoor for people using "using
+ namespace". See the manual for details.
+ */
+ k = 0;
+ while ((k = context.indexOf(strColons, k)) != -1) {
+ qualifiedContexts.insert(context.mid(k + 2), context);
+ k++;
+ }
+ }
+ }
+ yyTok = getToken();
+ break;
+ case Tok_Arrow:
+ yyTok = getToken();
+ if (yyTok == Tok_tr || yyTok == Tok_trUtf8)
+ qWarning("%s:%d: Cannot invoke tr() like this",
+ qPrintable(yyFileName), yyLineNo);
+ break;
+ case Tok_ColonColon:
+ if (yyBraceDepth == namespaces.count() && yyParenDepth == 0 && !yyTokColonSeen)
+ functionContext = getFullyQualifiedClassName(allClasses, namespaces, namespaceAliases, prefix, false);
+ prefix += strColons;
+ yyTok = getToken();
+#ifdef DIAGNOSE_RETRANSLATABILITY
+ if (yyTok == Tok_Ident && yyBraceDepth == namespaces.count() && yyParenDepth == 0)
+ functionName = yyIdent;
+#endif
+ break;
+ case Tok_RightBrace:
+ case Tok_Semicolon:
+ prefix.clear();
+ extracomment.clear();
+ yyTokColonSeen = false;
+ if (yyBraceDepth >= 0 && yyBraceDepth + 1 == namespaces.count())
+ namespaces.removeLast();
+ if (yyBraceDepth == namespaces.count()) {
+ if (missing_Q_OBJECT) {
+ if (needs_Q_OBJECT.contains(functionContext)) {
+ qWarning("%s:%d: Class '%s' lacks Q_OBJECT macro",
+ qPrintable(yyFileName), yyLineNo,
+ qPrintable(functionContext));
+ } else {
+ lacks_Q_OBJECT.insert(functionContext);
+ }
+ }
+ functionContext = defaultContext;
+ missing_Q_OBJECT = false;
+ }
+ yyTok = getToken();
+ break;
+ case Tok_Colon:
+ yyTokColonSeen = true;
+ yyTok = getToken();
+ break;
+ case Tok_LeftParen:
+ case Tok_RightParen:
+ case Tok_LeftBrace:
+ yyTokColonSeen = false;
+ yyTok = getToken();
+ break;
+ default:
+ yyTok = getToken();
+ break;
+ }
+ }
+
+ if (yyBraceDepth != 0)
+ qWarning("%s:%d: Unbalanced braces in C++ code (or abuse of the C++"
+ " preprocessor)\n",
+ qPrintable(yyFileName), yyBraceLineNo);
+ else if (yyParenDepth != 0)
+ qWarning("%s:%d: Unbalanced parentheses in C++ code (or abuse of the C++"
+ " preprocessor)\n",
+ qPrintable(yyFileName), yyParenLineNo);
+}
+
+/*
+ Fetches tr() calls in C++ code in UI files (inside "<function>"
+ tag). This mechanism is obsolete.
+*/
+void fetchtrInlinedCpp(const QString &in, Translator &translator, const QString &context)
+{
+ yyInStr = in;
+ yyInPos = 0;
+ yyFileName = QString();
+ yyCodecIsUtf8 = (translator.codecName() == "UTF-8");
+ yyForceUtf8 = true;
+ yySourceIsUnicode = true;
+ yySavedBraceDepth.clear();
+ yySavedParenDepth.clear();
+ yyBraceDepth = 0;
+ yyParenDepth = 0;
+ yyCurLineNo = 1;
+ yyBraceLineNo = 1;
+ yyParenLineNo = 1;
+ yyCh = getChar();
+
+ parse(&translator, context, QString());
+}
+
+
+bool loadCPP(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ QString defaultContext = cd.m_defaultContext;
+
+ yyCodecIsUtf8 = (translator.codecName() == "UTF-8");
+ yyForceUtf8 = false;
+ QTextStream ts(&dev);
+ QByteArray codecName = cd.m_codecForSource.isEmpty()
+ ? translator.codecName() : cd.m_codecForSource;
+ ts.setCodec(QTextCodec::codecForName(codecName));
+ ts.setAutoDetectUnicode(true);
+ yySourceCodec = ts.codec();
+ if (yySourceCodec->name() == "UTF-16")
+ translator.setCodecName("System");
+ yySourceIsUnicode = yySourceCodec->name().startsWith("UTF-");
+ yyInStr = ts.readAll();
+ yyInPos = 0;
+ yyFileName = cd.m_sourceFileName;
+ yySavedBraceDepth.clear();
+ yySavedParenDepth.clear();
+ yyBraceDepth = 0;
+ yyParenDepth = 0;
+ yyCurLineNo = 1;
+ yyBraceLineNo = 1;
+ yyParenLineNo = 1;
+ yyCh = getChar();
+
+ parse(&translator, defaultContext, defaultContext);
+
+ return true;
+}
+
+int initCPP()
+{
+ Translator::FileFormat format;
+ format.extension = QLatin1String("cpp");
+ format.fileType = Translator::FileFormat::SourceCode;
+ format.priority = 0;
+ format.description = QObject::tr("C++ source files");
+ format.loader = &loadCPP;
+ format.saver = 0;
+ Translator::registerFileFormat(format);
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initCPP)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/formats.pri b/tools/linguist/shared/formats.pri
new file mode 100644
index 0000000000..9c8072bbbe
--- /dev/null
+++ b/tools/linguist/shared/formats.pri
@@ -0,0 +1,26 @@
+
+# infrastructure
+QT *= xml
+
+INCLUDEPATH *= $$PWD
+
+SOURCES += \
+ $$PWD/numerus.cpp \
+ $$PWD/translator.cpp \
+ $$PWD/translatormessage.cpp
+
+HEADERS += \
+ $$PWD/translator.h \
+ $$PWD/translatormessage.h
+
+# "real" formats readers and writers
+SOURCES += \
+ $$PWD/qm.cpp \
+ $$PWD/qph.cpp \
+ $$PWD/po.cpp \
+ $$PWD/ts.cpp \
+ $$PWD/ui.cpp \
+ $$PWD/cpp.cpp \
+ $$PWD/java.cpp \
+ $$PWD/qscript.cpp \
+ $$PWD/xliff.cpp
diff --git a/tools/linguist/shared/java.cpp b/tools/linguist/shared/java.cpp
new file mode 100644
index 0000000000..912a8d7fe4
--- /dev/null
+++ b/tools/linguist/shared/java.cpp
@@ -0,0 +1,655 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QRegExp>
+#include <QtCore/QStack>
+#include <QtCore/QStack>
+#include <QtCore/QString>
+#include <QtCore/QTextCodec>
+
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+enum { Tok_Eof, Tok_class, Tok_return, Tok_tr,
+ Tok_translate, Tok_Ident, Tok_Package,
+ Tok_Comment, Tok_String, Tok_Colon, Tok_Dot,
+ Tok_LeftBrace, Tok_RightBrace, Tok_LeftParen,
+ Tok_RightParen, Tok_Comma, Tok_Semicolon,
+ Tok_Integer, Tok_Plus, Tok_PlusPlus, Tok_PlusEq };
+
+class Scope
+{
+ public:
+ QString name;
+ enum Type {Clazz, Function, Other} type;
+ int line;
+
+ Scope(const QString & name, Type type, int line) :
+ name(name),
+ type(type),
+ line(line)
+ {}
+
+ ~Scope()
+ {}
+};
+
+/*
+ The tokenizer maintains the following global variables. The names
+ should be self-explanatory.
+*/
+
+static QString yyFileName;
+static QChar yyCh;
+static QString yyIdent;
+static QString yyComment;
+static QString yyString;
+
+
+static qlonglong yyInteger;
+static int yyParenDepth;
+static int yyLineNo;
+static int yyCurLineNo;
+static int yyParenLineNo;
+static int yyTok;
+
+// the string to read from and current position in the string
+static QString yyInStr;
+static int yyInPos;
+
+// The parser maintains the following global variables.
+static QString yyPackage;
+static QStack<Scope*> yyScope;
+static QString yyDefaultContext;
+
+static QChar getChar()
+{
+ if (yyInPos >= yyInStr.size())
+ return EOF;
+ QChar c = yyInStr[yyInPos++];
+ if (c.unicode() == '\n')
+ ++yyCurLineNo;
+ return c.unicode();
+}
+
+static int getToken()
+{
+ const char tab[] = "bfnrt\"\'\\";
+ const char backTab[] = "\b\f\n\r\t\"\'\\";
+
+ yyIdent.clear();
+ yyComment.clear();
+ yyString.clear();
+
+ while ( yyCh != EOF ) {
+ yyLineNo = yyCurLineNo;
+
+ if ( yyCh.isLetter() || yyCh.toLatin1() == '_' ) {
+ do {
+ yyIdent.append(yyCh);
+ yyCh = getChar();
+ } while ( yyCh.isLetterOrNumber() || yyCh.toLatin1() == '_' );
+
+ if (yyTok != Tok_Dot) {
+ switch ( yyIdent.at(0).toLatin1() ) {
+ case 'r':
+ if ( yyIdent == QLatin1String("return") )
+ return Tok_return;
+ break;
+ case 'c':
+ if ( yyIdent == QLatin1String("class") )
+ return Tok_class;
+ break;
+ }
+ }
+ switch ( yyIdent.at(0).toLatin1() ) {
+ case 'T':
+ // TR() for when all else fails
+ if ( yyIdent == QLatin1String("TR") )
+ return Tok_tr;
+ break;
+ case 'p':
+ if( yyIdent == QLatin1String("package") )
+ return Tok_Package;
+ break;
+ case 't':
+ if ( yyIdent == QLatin1String("tr") )
+ return Tok_tr;
+ if ( yyIdent == QLatin1String("translate") )
+ return Tok_translate;
+ }
+ return Tok_Ident;
+ } else {
+ switch ( yyCh.toLatin1() ) {
+
+ case '/':
+ yyCh = getChar();
+ if ( yyCh == QLatin1Char('/') ) {
+ do {
+ yyCh = getChar();
+ if (yyCh == EOF)
+ break;
+ yyComment.append(yyCh);
+ } while (yyCh != QLatin1Char('\n'));
+ return Tok_Comment;
+
+ } else if ( yyCh == QLatin1Char('*') ) {
+ bool metAster = false;
+ bool metAsterSlash = false;
+
+ while ( !metAsterSlash ) {
+ yyCh = getChar();
+ if ( yyCh == EOF ) {
+ qFatal( "%s: Unterminated Java comment starting at"
+ " line %d\n",
+ qPrintable(yyFileName), yyLineNo );
+
+ return Tok_Comment;
+ }
+
+ yyComment.append( yyCh );
+
+ if ( yyCh == QLatin1Char('*') )
+ metAster = true;
+ else if ( metAster && yyCh == QLatin1Char('/') )
+ metAsterSlash = true;
+ else
+ metAster = false;
+ }
+ yyComment.chop(2);
+ yyCh = getChar();
+
+ return Tok_Comment;
+ }
+ break;
+ case '"':
+ yyCh = getChar();
+
+ while ( yyCh != EOF && yyCh != QLatin1Char('\n') && yyCh != QLatin1Char('"') ) {
+ if ( yyCh == QLatin1Char('\\') ) {
+ yyCh = getChar();
+ if ( yyCh == QLatin1Char('u') ) {
+ yyCh = getChar();
+ uint unicode(0);
+ for (int i = 4; i > 0; --i) {
+ unicode = unicode << 4;
+ if( yyCh.isDigit() ) {
+ unicode += yyCh.digitValue();
+ }
+ else {
+ int sub(yyCh.toLower().toAscii() - 87);
+ if( sub > 15 || sub < 10) {
+ qFatal( "%s:%d: Invalid Unicode",
+ qPrintable(yyFileName), yyLineNo );
+ }
+ unicode += sub;
+ }
+ yyCh = getChar();
+ }
+ yyString.append(QChar(unicode));
+ }
+ else if ( yyCh == QLatin1Char('\n') ) {
+ yyCh = getChar();
+ }
+ else {
+ yyString.append( QLatin1Char(backTab[strchr( tab, yyCh.toAscii() ) - tab]) );
+ yyCh = getChar();
+ }
+ } else {
+ yyString.append(yyCh);
+ yyCh = getChar();
+ }
+ }
+
+ if ( yyCh != QLatin1Char('"') )
+ qFatal( "%s:%d: Unterminated string",
+ qPrintable(yyFileName), yyLineNo );
+
+ yyCh = getChar();
+
+ return Tok_String;
+
+ case ':':
+ yyCh = getChar();
+ return Tok_Colon;
+ case '\'':
+ yyCh = getChar();
+
+ if ( yyCh == QLatin1Char('\\') )
+ yyCh = getChar();
+ do {
+ yyCh = getChar();
+ } while ( yyCh != EOF && yyCh != QLatin1Char('\'') );
+ yyCh = getChar();
+ break;
+ case '{':
+ yyCh = getChar();
+ return Tok_LeftBrace;
+ case '}':
+ yyCh = getChar();
+ return Tok_RightBrace;
+ case '(':
+ if (yyParenDepth == 0)
+ yyParenLineNo = yyCurLineNo;
+ yyParenDepth++;
+ yyCh = getChar();
+ return Tok_LeftParen;
+ case ')':
+ if (yyParenDepth == 0)
+ yyParenLineNo = yyCurLineNo;
+ yyParenDepth--;
+ yyCh = getChar();
+ return Tok_RightParen;
+ case ',':
+ yyCh = getChar();
+ return Tok_Comma;
+ case '.':
+ yyCh = getChar();
+ return Tok_Dot;
+ case ';':
+ yyCh = getChar();
+ return Tok_Semicolon;
+ case '+':
+ yyCh = getChar();
+ if (yyCh == QLatin1Char('+')) {
+ yyCh = getChar();
+ return Tok_PlusPlus;
+ }
+ if( yyCh == QLatin1Char('=') ){
+ yyCh = getChar();
+ return Tok_PlusEq;
+ }
+ return Tok_Plus;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ QByteArray ba;
+ ba += yyCh.toLatin1();
+ yyCh = getChar();
+ bool hex = yyCh == QLatin1Char('x');
+ if ( hex ) {
+ ba += yyCh.toLatin1();
+ yyCh = getChar();
+ }
+ while ( hex ? isxdigit(yyCh.toLatin1()) : yyCh.isDigit() ) {
+ ba += yyCh.toLatin1();
+ yyCh = getChar();
+ }
+ bool ok;
+ yyInteger = ba.toLongLong(&ok);
+ if (ok) return Tok_Integer;
+ break;
+ }
+ default:
+ yyCh = getChar();
+ }
+ }
+ }
+ return Tok_Eof;
+}
+
+static bool match( int t )
+{
+ bool matches = ( yyTok == t );
+ if ( matches )
+ yyTok = getToken();
+ return matches;
+}
+
+static bool matchString( QString &s )
+{
+ if ( yyTok != Tok_String )
+ return false;
+
+ s = yyString;
+ yyTok = getToken();
+ while ( yyTok == Tok_Plus ) {
+ yyTok = getToken();
+ if (yyTok == Tok_String)
+ s += yyString;
+ else {
+ qWarning( "%s:%d: String used in translation can only contain strings"
+ " concatenated with other strings, not expressions or numbers.",
+ qPrintable(yyFileName), yyLineNo );
+ return false;
+ }
+ yyTok = getToken();
+ }
+ return true;
+}
+
+static bool matchInteger( qlonglong *number)
+{
+ bool matches = (yyTok == Tok_Integer);
+ if (matches) {
+ yyTok = getToken();
+ *number = yyInteger;
+ }
+ return matches;
+}
+
+static bool matchStringOrNull(QString &s)
+{
+ bool matches = matchString(s);
+ qlonglong num = 0;
+ if (!matches) matches = matchInteger(&num);
+ return matches && num == 0;
+}
+
+/*
+ * match any expression that can return a number, which can be
+ * 1. Literal number (e.g. '11')
+ * 2. simple identifier (e.g. 'm_count')
+ * 3. simple function call (e.g. 'size()' )
+ * 4. function call on an object (e.g. 'list.size()')
+ * 5. function call on an object (e.g. 'list->size()')
+ *
+ * Other cases:
+ * size(2,4)
+ * list().size()
+ * list(a,b).size(2,4)
+ * etc...
+ */
+static bool matchExpression()
+{
+ if (match(Tok_Integer)) {
+ return true;
+ }
+
+ int parenlevel = 0;
+ while (match(Tok_Ident) || parenlevel > 0) {
+ if (yyTok == Tok_RightParen) {
+ if (parenlevel == 0) break;
+ --parenlevel;
+ yyTok = getToken();
+ } else if (yyTok == Tok_LeftParen) {
+ yyTok = getToken();
+ if (yyTok == Tok_RightParen) {
+ yyTok = getToken();
+ } else {
+ ++parenlevel;
+ }
+ } else if (yyTok == Tok_Ident) {
+ continue;
+ } else if (parenlevel == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static const QString context()
+{
+ QString context(yyPackage);
+ bool innerClass = false;
+ for (int i = 0; i < yyScope.size(); ++i) {
+ if (yyScope.at(i)->type == Scope::Clazz) {
+ if (innerClass)
+ context.append(QLatin1String("$"));
+ else
+ context.append(QLatin1String("."));
+
+ context.append(yyScope.at(i)->name);
+ innerClass = true;
+ }
+ }
+ return context.isEmpty() ? yyDefaultContext : context;
+}
+
+static void recordMessage(
+ Translator *tor, const QString &context, const QString &text, const QString &comment,
+ const QString &extracomment, bool plural)
+{
+ TranslatorMessage msg(
+ context, text, comment, QString(),
+ yyFileName, yyLineNo, QStringList(),
+ TranslatorMessage::Unfinished, plural);
+ msg.setExtraComment(extracomment.simplified());
+ tor->extend(msg);
+}
+
+static void parse( Translator *tor )
+{
+ QString text;
+ QString com;
+ QString extracomment;
+
+ yyCh = getChar();
+
+ yyTok = getToken();
+ while ( yyTok != Tok_Eof ) {
+ switch ( yyTok ) {
+ case Tok_class:
+ yyTok = getToken();
+ if(yyTok == Tok_Ident) {
+ yyScope.push(new Scope(yyIdent, Scope::Clazz, yyLineNo));
+ }
+ else {
+ qFatal( "%s:%d: Class must be followed by a classname",
+ qPrintable(yyFileName), yyLineNo );
+ }
+ while (!match(Tok_LeftBrace)) {
+ yyTok = getToken();
+ }
+ break;
+
+ case Tok_tr:
+ yyTok = getToken();
+ if ( match(Tok_LeftParen) && matchString(text) ) {
+ com.clear();
+ bool plural = false;
+
+ if ( match(Tok_RightParen) ) {
+ // no comment
+ } else if (match(Tok_Comma) && matchStringOrNull(com)) { //comment
+ if ( match(Tok_RightParen)) {
+ // ok,
+ } else if (match(Tok_Comma)) {
+ plural = true;
+ }
+ }
+ if (!text.isEmpty())
+ recordMessage(tor, context(), text, com, extracomment, plural);
+ }
+ break;
+ case Tok_translate:
+ {
+ QString contextOverride;
+ yyTok = getToken();
+ if ( match(Tok_LeftParen) &&
+ matchString(contextOverride) &&
+ match(Tok_Comma) &&
+ matchString(text) ) {
+
+ com.clear();
+ bool plural = false;
+ if (!match(Tok_RightParen)) {
+ // look for comment
+ if ( match(Tok_Comma) && matchStringOrNull(com)) {
+ if (!match(Tok_RightParen)) {
+ if (match(Tok_Comma) && matchExpression() && match(Tok_RightParen)) {
+ plural = true;
+ } else {
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ if (!text.isEmpty())
+ recordMessage(tor, contextOverride, text, com, extracomment, plural);
+ }
+ }
+ break;
+
+ case Tok_Ident:
+ yyTok = getToken();
+ break;
+
+ case Tok_Comment:
+ if (yyComment.startsWith(QLatin1Char(':'))) {
+ yyComment.remove(0, 1);
+ extracomment.append(yyComment);
+ }
+ yyTok = getToken();
+ break;
+
+ case Tok_RightBrace:
+ if ( yyScope.isEmpty() ) {
+ qFatal( "%s:%d: Unbalanced right brace in Java code\n",
+ qPrintable(yyFileName), yyLineNo );
+ }
+ else
+ delete (yyScope.pop());
+ extracomment.clear();
+ yyTok = getToken();
+ break;
+
+ case Tok_LeftBrace:
+ yyScope.push(new Scope(QString(), Scope::Other, yyLineNo));
+ yyTok = getToken();
+ break;
+
+ case Tok_Semicolon:
+ extracomment.clear();
+ yyTok = getToken();
+ break;
+
+ case Tok_Package:
+ yyTok = getToken();
+ while(!match(Tok_Semicolon)) {
+ switch(yyTok) {
+ case Tok_Ident:
+ yyPackage.append(yyIdent);
+ break;
+ case Tok_Dot:
+ yyPackage.append(QLatin1String("."));
+ break;
+ default:
+ qFatal( "%s:%d: Package keyword should be followed by com.package.name;",
+ qPrintable(yyFileName), yyLineNo );
+ break;
+ }
+ yyTok = getToken();
+ }
+ break;
+
+ default:
+ yyTok = getToken();
+ }
+ }
+
+ if ( !yyScope.isEmpty() )
+ qFatal( "%s:%d: Unbalanced braces in Java code\n",
+ qPrintable(yyFileName), yyScope.top()->line );
+ else if ( yyParenDepth != 0 )
+ qFatal( "%s:%d: Unbalanced parentheses in Java code\n",
+ qPrintable(yyFileName), yyParenLineNo );
+}
+
+
+bool loadJava(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ //void LupdateApplication::fetchtr_java( const QString &fileName, Translator *tor,
+ //const QString &defaultContext, bool mustExist, const QByteArray &codecForSource )
+
+ yyDefaultContext = cd.m_defaultContext;
+ yyInPos = -1;
+ yyFileName = cd.m_sourceFileName;
+ yyPackage.clear();
+ yyScope.clear();
+ yyTok = -1;
+ yyParenDepth = 0;
+ yyCurLineNo = 0;
+ yyParenLineNo = 1;
+
+ QTextStream ts(&dev);
+ QByteArray codecName;
+ if (!cd.m_codecForSource.isEmpty())
+ codecName = cd.m_codecForSource;
+ else
+ codecName = translator.codecName(); // Just because it should be latin1 already
+ ts.setCodec(QTextCodec::codecForName(codecName));
+ ts.setAutoDetectUnicode(true);
+ yyInStr = ts.readAll();
+ yyInPos = 0;
+ yyFileName = cd.m_sourceFileName;
+ yyCurLineNo = 1;
+ yyParenLineNo = 1;
+ yyCh = getChar();
+
+ parse(&translator);
+
+ // Java uses UTF-16 internally and Jambi makes UTF-8 for tr() purposes of it.
+ translator.setCodecName("UTF-8");
+ return true;
+}
+
+int initJava()
+{
+ Translator::FileFormat format;
+ format.extension = QLatin1String("java");
+ format.fileType = Translator::FileFormat::SourceCode;
+ format.priority = 0;
+ format.description = QObject::tr("Java source files");
+ format.loader = &loadJava;
+ format.saver = 0;
+ Translator::registerFileFormat(format);
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initJava)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/make-qscript.sh b/tools/linguist/shared/make-qscript.sh
new file mode 100755
index 0000000000..42cab7a05d
--- /dev/null
+++ b/tools/linguist/shared/make-qscript.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+me=$(dirname $0)
+mkdir -p $me/out
+(cd $me/out && ${QLALR-qlalr} --no-debug --troll --no-lines ../qscript.g)
+
+for f in $me/out/*.{h,cpp}; do
+ n=$(basename $f)
+ p4 open $me/../$n
+ cp $f $me/../$n
+done
+
+p4 revert -a $me/../...
+p4 diff -du $me/../...
diff --git a/tools/linguist/shared/numerus.cpp b/tools/linguist/shared/numerus.cpp
new file mode 100644
index 0000000000..f3a29ccaf7
--- /dev/null
+++ b/tools/linguist/shared/numerus.cpp
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QMap>
+
+#include <private/qtranslator_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const uchar englishStyleRules[] =
+ { Q_EQ, 1 };
+static const uchar frenchStyleRules[] =
+ { Q_LEQ, 1 };
+static const uchar latvianRules[] =
+ { Q_MOD_10 | Q_EQ, 1, Q_AND, Q_MOD_100 | Q_NEQ, 11, Q_NEWRULE,
+ Q_NEQ, 0 };
+static const uchar irishStyleRules[] =
+ { Q_EQ, 1, Q_NEWRULE,
+ Q_EQ, 2 };
+static const uchar czechRules[] =
+ { Q_MOD_100 | Q_EQ, 1, Q_NEWRULE,
+ Q_MOD_100 | Q_BETWEEN, 2, 4 };
+static const uchar slovakRules[] =
+ { Q_EQ, 1, Q_NEWRULE,
+ Q_BETWEEN, 2, 4 };
+static const uchar macedonianRules[] =
+ { Q_MOD_10 | Q_EQ, 1, Q_NEWRULE,
+ Q_MOD_10 | Q_EQ, 2 };
+static const uchar lithuanianRules[] =
+ { Q_MOD_10 | Q_EQ, 1, Q_AND, Q_MOD_100 | Q_NEQ, 11, Q_NEWRULE,
+ Q_MOD_10 | Q_EQ, 2, Q_AND, Q_MOD_100 | Q_NOT_BETWEEN, 10, 19 };
+static const uchar russianStyleRules[] =
+ { Q_MOD_10 | Q_EQ, 1, Q_AND, Q_MOD_100 | Q_NEQ, 11, Q_NEWRULE,
+ Q_MOD_10 | Q_BETWEEN, 2, 4, Q_AND, Q_MOD_100 | Q_NOT_BETWEEN, 10, 19 };
+static const uchar polishRules[] =
+ { Q_EQ, 1, Q_NEWRULE,
+ Q_MOD_10 | Q_BETWEEN, 2, 4, Q_AND, Q_MOD_100 | Q_NOT_BETWEEN, 10, 19 };
+static const uchar romanianRules[] =
+ { Q_EQ, 1, Q_NEWRULE,
+ Q_EQ, 0, Q_OR, Q_MOD_100 | Q_BETWEEN, 1, 19 };
+static const uchar slovenianRules[] =
+ { Q_MOD_100 | Q_EQ, 1, Q_NEWRULE,
+ Q_MOD_100 | Q_EQ, 2, Q_NEWRULE,
+ Q_MOD_100 | Q_BETWEEN, 3, 4 };
+static const uchar malteseRules[] =
+ { Q_EQ, 1, Q_NEWRULE,
+ Q_EQ, 0, Q_OR, Q_MOD_100 | Q_BETWEEN, 1, 10, Q_NEWRULE,
+ Q_MOD_100 | Q_BETWEEN, 11, 19 };
+static const uchar welshRules[] =
+ { Q_EQ, 0, Q_NEWRULE,
+ Q_EQ, 1, Q_NEWRULE,
+ Q_BETWEEN, 2, 5, Q_NEWRULE,
+ Q_EQ, 6 };
+static const uchar arabicRules[] =
+ { Q_EQ, 0, Q_NEWRULE,
+ Q_EQ, 1, Q_NEWRULE,
+ Q_EQ, 2, Q_NEWRULE,
+ Q_MOD_100 | Q_BETWEEN, 3, 10, Q_NEWRULE,
+ Q_MOD_100 | Q_NEQ, 0 };
+
+static const char * const japaneseStyleForms[] = { "Universal Form", 0 };
+static const char * const englishStyleForms[] = { "Singular", "Plural", 0 };
+static const char * const frenchStyleForms[] = { "Singular", "Plural", 0 };
+static const char * const latvianForms[] = { "Singular", "Plural", "Nullar", 0 };
+static const char * const irishStyleForms[] = { "Singular", "Dual", "Plural", 0 };
+static const char * const czechForms[] = { "Singular", "Dual", "Plural", 0 };
+static const char * const slovakForms[] = { "Singular", "Dual", "Plural", 0 };
+static const char * const macedonianForms[] = { "Singular", "Dual", "Plural", 0 };
+static const char * const lithuanianForms[] = { "Singular", "Dual", "Plural", 0 };
+static const char * const russianStyleForms[] = { "Singular", "Dual", "Plural", 0 };
+static const char * const polishForms[] = { "Singular", "Paucal", "Plural", 0 };
+static const char * const romanianForms[] =
+ { "Singular", "Plural Form for 2 to 19", "Plural", 0 };
+static const char * const slovenianForms[] = { "Singular", "Dual", "Trial", "Plural", 0 };
+static const char * const malteseForms[] =
+ { "Singular", "Plural Form for 2 to 10", "Plural Form for 11 to 19", "Plural", 0 };
+static const char * const welshForms[] =
+ { "Nullar", "Singular", "Dual", "Sexal", "Plural", 0 };
+static const char * const arabicForms[] =
+ { "Nullar", "Singular", "Dual", "Minority Plural", "Plural", "Plural Form for 100, 200, ...", 0 };
+
+#define EOL QLocale::C
+
+static const QLocale::Language japaneseStyleLanguages[] = {
+ QLocale::Afan,
+ QLocale::Armenian,
+ QLocale::Bhutani,
+ QLocale::Bislama,
+ QLocale::Burmese,
+ QLocale::Chinese,
+ QLocale::FijiLanguage,
+ QLocale::Guarani,
+ QLocale::Hungarian,
+ QLocale::Indonesian,
+ QLocale::Japanese,
+ QLocale::Javanese,
+ QLocale::Korean,
+ QLocale::Malay,
+ QLocale::NauruLanguage,
+ QLocale::Persian,
+ QLocale::Sundanese,
+ QLocale::Thai,
+ QLocale::Tibetan,
+ QLocale::Vietnamese,
+ QLocale::Yoruba,
+ QLocale::Zhuang,
+ EOL
+};
+
+static const QLocale::Language englishStyleLanguages[] = {
+ QLocale::Abkhazian,
+ QLocale::Afar,
+ QLocale::Afrikaans,
+ QLocale::Albanian,
+ QLocale::Amharic,
+ QLocale::Assamese,
+ QLocale::Aymara,
+ QLocale::Azerbaijani,
+ QLocale::Bashkir,
+ QLocale::Basque,
+ QLocale::Bengali,
+ QLocale::Bihari,
+ // Missing: Bokmal,
+ QLocale::Bulgarian,
+ QLocale::Cambodian,
+ QLocale::Catalan,
+ QLocale::Cornish,
+ QLocale::Corsican,
+ QLocale::Danish,
+ QLocale::Dutch,
+ QLocale::English,
+ QLocale::Esperanto,
+ QLocale::Estonian,
+ QLocale::Faroese,
+ QLocale::Finnish,
+ // Missing: Friulian,
+ QLocale::Frisian,
+ QLocale::Galician,
+ QLocale::Georgian,
+ QLocale::German,
+ QLocale::Greek,
+ QLocale::Greenlandic,
+ QLocale::Gujarati,
+ QLocale::Hausa,
+ QLocale::Hebrew,
+ QLocale::Hindi,
+ QLocale::Icelandic,
+ QLocale::Interlingua,
+ QLocale::Interlingue,
+ QLocale::Italian,
+ QLocale::Kannada,
+ QLocale::Kashmiri,
+ QLocale::Kazakh,
+ QLocale::Kinyarwanda,
+ QLocale::Kirghiz,
+ QLocale::Kurdish,
+ QLocale::Kurundi,
+ QLocale::Laothian,
+ QLocale::Latin,
+ // Missing: Letzeburgesch,
+ QLocale::Lingala,
+ QLocale::Malagasy,
+ QLocale::Malayalam,
+ QLocale::Marathi,
+ QLocale::Mongolian,
+ // Missing: Nahuatl,
+ QLocale::Nepali,
+ // Missing: Northern Sotho,
+ QLocale::Norwegian,
+ QLocale::Nynorsk,
+ QLocale::Occitan,
+ QLocale::Oriya,
+ QLocale::Pashto,
+ QLocale::Portuguese,
+ QLocale::Punjabi,
+ QLocale::Quechua,
+ QLocale::RhaetoRomance,
+ QLocale::Sesotho,
+ QLocale::Setswana,
+ QLocale::Shona,
+ QLocale::Sindhi,
+ QLocale::Singhalese,
+ QLocale::Siswati,
+ QLocale::Somali,
+ QLocale::Spanish,
+ QLocale::Swahili,
+ QLocale::Swedish,
+ QLocale::Tagalog,
+ QLocale::Tajik,
+ QLocale::Tamil,
+ QLocale::Tatar,
+ QLocale::Telugu,
+ QLocale::TongaLanguage,
+ QLocale::Tsonga,
+ QLocale::Turkish,
+ QLocale::Turkmen,
+ QLocale::Twi,
+ QLocale::Uigur,
+ QLocale::Uzbek,
+ QLocale::Volapuk,
+ QLocale::Wolof,
+ QLocale::Xhosa,
+ QLocale::Yiddish,
+ QLocale::Zulu,
+ EOL
+};
+static const QLocale::Language frenchStyleLanguages[] = {
+ // keep synchronized with frenchStyleCountries
+ QLocale::Breton,
+ QLocale::French,
+ QLocale::Portuguese,
+ // Missing: Filipino,
+ QLocale::Tigrinya,
+ // Missing: Walloon
+ EOL
+};
+static const QLocale::Language latvianLanguage[] = { QLocale::Latvian, EOL };
+static const QLocale::Language irishStyleLanguages[] = {
+ QLocale::Divehi,
+ QLocale::Gaelic,
+ QLocale::Inuktitut,
+ QLocale::Inupiak,
+ QLocale::Irish,
+ QLocale::Manx,
+ QLocale::Maori,
+ // Missing: Sami,
+ QLocale::Samoan,
+ QLocale::Sanskrit,
+ EOL
+};
+static const QLocale::Language czechLanguage[] = { QLocale::Czech, EOL };
+static const QLocale::Language slovakLanguage[] = { QLocale::Slovak, EOL };
+static const QLocale::Language macedonianLanguage[] = { QLocale::Macedonian, EOL };
+static const QLocale::Language lithuanianLanguage[] = { QLocale::Lithuanian, EOL };
+static const QLocale::Language russianStyleLanguages[] = {
+ QLocale::Bosnian,
+ QLocale::Byelorussian,
+ QLocale::Croatian,
+ QLocale::Russian,
+ QLocale::Serbian,
+ QLocale::SerboCroatian,
+ QLocale::Ukrainian,
+ EOL
+};
+static const QLocale::Language polishLanguage[] = { QLocale::Polish, EOL };
+static const QLocale::Language romanianLanguages[] = {
+ QLocale::Moldavian,
+ QLocale::Romanian,
+ EOL
+};
+static const QLocale::Language slovenianLanguage[] = { QLocale::Slovenian, EOL };
+static const QLocale::Language malteseLanguage[] = { QLocale::Maltese, EOL };
+static const QLocale::Language welshLanguage[] = { QLocale::Welsh, EOL };
+static const QLocale::Language arabicLanguage[] = { QLocale::Arabic, EOL };
+
+static const QLocale::Country frenchStyleCountries[] = {
+ // keep synchronized with frenchStyleLanguages
+ QLocale::AnyCountry,
+ QLocale::AnyCountry,
+ QLocale::Brazil,
+ QLocale::AnyCountry
+};
+struct NumerusTableEntry {
+ const uchar *rules;
+ int rulesSize;
+ const char * const *forms;
+ const QLocale::Language *languages;
+ const QLocale::Country *countries;
+};
+
+static const NumerusTableEntry numerusTable[] = {
+ { 0, 0, japaneseStyleForms, japaneseStyleLanguages, 0 },
+ { englishStyleRules, sizeof(englishStyleRules), englishStyleForms, englishStyleLanguages, 0 },
+ { frenchStyleRules, sizeof(frenchStyleRules), frenchStyleForms, frenchStyleLanguages,
+ frenchStyleCountries },
+ { latvianRules, sizeof(latvianRules), latvianForms, latvianLanguage, 0 },
+ { irishStyleRules, sizeof(irishStyleRules), irishStyleForms, irishStyleLanguages, 0 },
+ { czechRules, sizeof(czechRules), czechForms, czechLanguage, 0 },
+ { slovakRules, sizeof(slovakRules), slovakForms, slovakLanguage, 0 },
+ { macedonianRules, sizeof(macedonianRules), macedonianForms, macedonianLanguage, 0 },
+ { lithuanianRules, sizeof(lithuanianRules), lithuanianForms, lithuanianLanguage, 0 },
+ { russianStyleRules, sizeof(russianStyleRules), russianStyleForms, russianStyleLanguages, 0 },
+ { polishRules, sizeof(polishRules), polishForms, polishLanguage, 0 },
+ { romanianRules, sizeof(romanianRules), romanianForms, romanianLanguages, 0 },
+ { slovenianRules, sizeof(slovenianRules), slovenianForms, slovenianLanguage, 0 },
+ { malteseRules, sizeof(malteseRules), malteseForms, malteseLanguage, 0 },
+ { welshRules, sizeof(welshRules), welshForms, welshLanguage, 0 },
+ { arabicRules, sizeof(arabicRules), arabicForms, arabicLanguage, 0 }
+};
+
+static const int NumerusTableSize = sizeof(numerusTable) / sizeof(numerusTable[0]);
+
+// magic number for the file
+static const int MagicLength = 16;
+static const uchar magic[MagicLength] = {
+ 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
+ 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
+};
+
+bool getNumerusInfo(QLocale::Language language, QLocale::Country country,
+ QByteArray *rules, QStringList *forms)
+{
+ while (true) {
+ for (int i = 0; i < NumerusTableSize; ++i) {
+ const NumerusTableEntry &entry = numerusTable[i];
+ for (int j = 0; entry.languages[j] != EOL; ++j) {
+ if (entry.languages[j] == language
+ && ((!entry.countries && country == QLocale::AnyCountry)
+ || (entry.countries && entry.countries[j] == country))) {
+ if (rules) {
+ *rules = QByteArray::fromRawData(reinterpret_cast<const char *>(entry.rules),
+ entry.rulesSize);
+ }
+ if (forms) {
+ forms->clear();
+ for (int k = 0; entry.forms[k]; ++k)
+ forms->append(QLatin1String(entry.forms[k]));
+ }
+ return true;
+ }
+ }
+ }
+
+ if (country == QLocale::AnyCountry)
+ break;
+ country = QLocale::AnyCountry;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/po.cpp b/tools/linguist/shared/po.cpp
new file mode 100644
index 0000000000..e9375e96f1
--- /dev/null
+++ b/tools/linguist/shared/po.cpp
@@ -0,0 +1,662 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QIODevice>
+#include <QtCore/QHash>
+#include <QtCore/QString>
+#include <QtCore/QTextStream>
+
+#include <ctype.h>
+
+#define MAGIC_OBSOLETE_REFERENCE "Obsolete_PO_entries"
+
+// Uncomment if you wish to hard wrap long lines in .po files. Note that this
+// affects only msg strings, not comments.
+//#define HARD_WRAP_LONG_WORDS
+
+QT_BEGIN_NAMESPACE
+
+static const int MAX_LEN = 79;
+
+static QString poEscapedString(const QString &prefix, const QString &keyword,
+ bool noWrap, const QString &ba)
+{
+ QStringList lines;
+ int off = 0;
+ QString res;
+ while (off < ba.length()) {
+ ushort c = ba[off++].unicode();
+ switch (c) {
+ case '\n':
+ res += QLatin1String("\\n");
+ lines.append(res);
+ res.clear();
+ break;
+ case '\r':
+ res += QLatin1String("\\r");
+ break;
+ case '\t':
+ res += QLatin1String("\\t");
+ break;
+ case '\v':
+ res += QLatin1String("\\v");
+ break;
+ case '\a':
+ res += QLatin1String("\\a");
+ break;
+ case '\b':
+ res += QLatin1String("\\b");
+ break;
+ case '\f':
+ res += QLatin1String("\\f");
+ break;
+ case '"':
+ res += QLatin1String("\\\"");
+ break;
+ case '\\':
+ res += QLatin1String("\\\\");
+ break;
+ default:
+ if (c < 32) {
+ res += QLatin1String("\\x");
+ res += QString::number(c, 16);
+ if (off < ba.length() && isxdigit(ba[off].unicode()))
+ res += QLatin1String("\"\"");
+ } else {
+ res += QChar(c);
+ }
+ break;
+ }
+ }
+ if (!res.isEmpty())
+ lines.append(res);
+ if (!lines.isEmpty()) {
+ if (!noWrap) {
+ if (lines.count() != 1 ||
+ lines.first().length() > MAX_LEN - keyword.length() - prefix.length() - 3)
+ {
+ QStringList olines = lines;
+ lines = QStringList(QString());
+ const int maxlen = MAX_LEN - prefix.length() - 2;
+ foreach (const QString &line, olines) {
+ int off = 0;
+ while (off + maxlen < line.length()) {
+ int idx = line.lastIndexOf(QLatin1Char(' '), off + maxlen - 1) + 1;
+ if (idx == off) {
+#ifdef HARD_WRAP_LONG_WORDS
+ // This doesn't seem too nice, but who knows ...
+ idx = off + maxlen;
+#else
+ idx = line.indexOf(QLatin1Char(' '), off + maxlen) + 1;
+ if (!idx)
+ break;
+#endif
+ }
+ lines.append(line.mid(off, idx - off));
+ off = idx;
+ }
+ lines.append(line.mid(off));
+ }
+ }
+ } else if (lines.count() > 1) {
+ lines.prepend(QString());
+ }
+ }
+ return prefix + keyword + QLatin1String(" \"") +
+ lines.join(QLatin1String("\"\n") + prefix + QLatin1Char('"')) +
+ QLatin1String("\"\n");
+}
+
+static QString poEscapedLines(const QString &prefix, bool addSpace, const QStringList &lines)
+{
+ QString out;
+ foreach (const QString &line, lines) {
+ out += prefix;
+ if (addSpace && !line.isEmpty())
+ out += QLatin1Char(' ' );
+ out += line;
+ out += QLatin1Char('\n');
+ }
+ return out;
+}
+
+static QString poEscapedLines(const QString &prefix, bool addSpace, const QString &in0)
+{
+ QString in = in0;
+ if (in.endsWith(QLatin1Char('\n')))
+ in.chop(1);
+ return poEscapedLines(prefix, addSpace, in.split(QLatin1Char('\n')));
+}
+
+static QString poWrappedEscapedLines(const QString &prefix, bool addSpace, const QString &line)
+{
+ const int maxlen = MAX_LEN - prefix.length();
+ QStringList lines;
+ int off = 0;
+ while (off + maxlen < line.length()) {
+ int idx = line.lastIndexOf(QLatin1Char(' '), off + maxlen - 1);
+ if (idx < off) {
+#if 0 //def HARD_WRAP_LONG_WORDS
+ // This cannot work without messing up semantics, so do not even try.
+#else
+ idx = line.indexOf(QLatin1Char(' '), off + maxlen);
+ if (idx < 0)
+ break;
+#endif
+ }
+ lines.append(line.mid(off, idx - off));
+ off = idx + 1;
+ }
+ lines.append(line.mid(off));
+ return poEscapedLines(prefix, addSpace, lines);
+}
+
+struct PoItem
+{
+public:
+ PoItem()
+ : isPlural(false), isFuzzy(false)
+ {}
+
+
+public:
+ QString id;
+ QString context;
+ QString tscomment;
+ QString oldTscomment;
+ QString lineNumber;
+ QString fileName;
+ QString references;
+ QString translatorComments;
+ QString automaticComments;
+ QString msgId;
+ QString oldMsgId;
+ QStringList msgStr;
+ bool isPlural;
+ bool isFuzzy;
+ QHash<QString, QString> extra;
+};
+
+
+static bool isTranslationLine(const QString &line)
+{
+ return line.startsWith(QLatin1String("#~ msgstr"))
+ || line.startsWith(QLatin1String("msgstr"));
+}
+
+static QString slurpEscapedString(const QStringList &lines, int & l,
+ int offset, const QString &prefix, ConversionData &cd)
+{
+ QString msg;
+ int stoff;
+
+ for (; l < lines.size(); ++l) {
+ const QString &line = lines.at(l);
+ if (line.isEmpty() || !line.startsWith(prefix))
+ break;
+ while (line[offset].isSpace()) // No length check, as string has no trailing spaces.
+ offset++;
+ if (line[offset].unicode() != '"')
+ break;
+ offset++;
+ forever {
+ if (offset == line.length())
+ goto premature_eol;
+ ushort c = line[offset++].unicode();
+ if (c == '"') {
+ if (offset == line.length())
+ break;
+ while (line[offset].isSpace())
+ offset++;
+ if (line[offset++].unicode() != '"') {
+ cd.appendError(QString::fromLatin1(
+ "PO parsing error: extra characters on line %1.")
+ .arg(l + 1));
+ break;
+ }
+ continue;
+ }
+ if (c == '\\') {
+ if (offset == line.length())
+ goto premature_eol;
+ c = line[offset++].unicode();
+ switch (c) {
+ case 'r':
+ msg += QLatin1Char('\r'); // Maybe just throw it away?
+ break;
+ case 'n':
+ msg += QLatin1Char('\n');
+ break;
+ case 't':
+ msg += QLatin1Char('\t');
+ break;
+ case 'v':
+ msg += QLatin1Char('\v');
+ break;
+ case 'a':
+ msg += QLatin1Char('\a');
+ break;
+ case 'b':
+ msg += QLatin1Char('\b');
+ break;
+ case 'f':
+ msg += QLatin1Char('\f');
+ break;
+ case '"':
+ msg += QLatin1Char('"');
+ break;
+ case '\\':
+ msg += QLatin1Char('\\');
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ stoff = offset - 1;
+ while ((c = line[offset].unicode()) >= '0' && c <= '7')
+ if (++offset == line.length())
+ goto premature_eol;
+ msg += QChar(line.mid(stoff, offset - stoff).toUInt(0, 8));
+ break;
+ case 'x':
+ stoff = offset;
+ while (isxdigit(line[offset].unicode()))
+ if (++offset == line.length())
+ goto premature_eol;
+ msg += QChar(line.mid(stoff, offset - stoff).toUInt(0, 16));
+ break;
+ default:
+ cd.appendError(QString::fromLatin1(
+ "PO parsing error: invalid escape '\\%1' (line %2).")
+ .arg(QChar(c)).arg(l + 1));
+ msg += QLatin1Char('\\');
+ msg += QChar(c);
+ break;
+ }
+ } else {
+ msg += QChar(c);
+ }
+ }
+ offset = prefix.size();
+ }
+ --l;
+ return msg;
+
+premature_eol:
+ cd.appendError(QString::fromLatin1(
+ "PO parsing error: premature end of line %1.").arg(l + 1));
+ return QString();
+}
+
+static void slurpComment(QString &msg, const QStringList &lines, int & l)
+{
+ const QChar newline = QLatin1Char('\n');
+ QString prefix = lines.at(l);
+ for (int i = 1; ; i++) {
+ if (prefix.at(i).unicode() != ' ') {
+ prefix.truncate(i);
+ break;
+ }
+ }
+ for (; l < lines.size(); ++l) {
+ const QString &line = lines.at(l);
+ if (line.startsWith(prefix))
+ msg += line.mid(prefix.size());
+ else if (line != QLatin1String("#"))
+ break;
+ msg += newline;
+ }
+ --l;
+}
+
+bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ const QChar quote = QLatin1Char('"');
+ const QChar newline = QLatin1Char('\n');
+ QTextStream in(&dev);
+ bool error = false;
+
+ // format of a .po file entry:
+ // white-space
+ // # translator-comments
+ // #. automatic-comments
+ // #: reference...
+ // #, flag...
+ // #~ msgctxt, msgid*, msgstr - used for obsoleted messages
+ // #| msgctxt, msgid* previous untranslated-string - for fuzzy message
+ // msgctx string-context
+ // msgid untranslated-string
+ // -- For singular:
+ // msgstr translated-string
+ // -- For plural:
+ // msgid_plural untranslated-string-plural
+ // msgstr[0] translated-string
+ // ...
+
+ // we need line based lookahead below.
+ QStringList lines;
+ while (!in.atEnd())
+ lines.append(in.readLine().trimmed());
+ lines.append(QString());
+
+ int l = 0;
+ PoItem item;
+ for (; l != lines.size(); ++l) {
+ QString line = lines.at(l);
+ if (line.isEmpty())
+ continue;
+ if (isTranslationLine(line)) {
+ bool isObsolete = line.startsWith(QLatin1String("#~ msgstr"));
+ const QString prefix = QLatin1String(isObsolete ? "#~ " : "");
+ while (true) {
+ int idx = line.indexOf(QLatin1Char(' '), prefix.length());
+ item.msgStr.append(slurpEscapedString(lines, l, idx, prefix, cd));
+ if (l + 1 >= lines.size() || !isTranslationLine(lines.at(l + 1)))
+ break;
+ ++l;
+ line = lines.at(l);
+ }
+ if (item.msgId.isEmpty()) {
+ QRegExp rx(QLatin1String("\\bX-Language: ([^\n]*)\n"));
+ int idx = rx.indexIn(item.msgStr.first());
+ if (idx >= 0) {
+ translator.setLanguageCode(rx.cap(1));
+ item.msgStr.first().remove(idx, rx.matchedLength());
+ }
+ QRegExp rx2(QLatin1String("\\bX-Source-Language: ([^\n]*)\n"));
+ int idx2 = rx2.indexIn(item.msgStr.first());
+ if (idx2 >= 0) {
+ translator.setSourceLanguageCode(rx2.cap(1));
+ item.msgStr.first().remove(idx2, rx2.matchedLength());
+ }
+ if (item.msgStr.first().indexOf(
+ QRegExp(QLatin1String("\\bX-Virgin-Header:[^\n]*\n"))) >= 0) {
+ item = PoItem();
+ continue;
+ }
+ }
+ // build translator message
+ TranslatorMessage msg;
+ msg.setContext(item.context);
+ if (!item.references.isEmpty()) {
+ foreach (const QString &ref,
+ item.references.split(QRegExp(QLatin1String("\\s")),
+ QString::SkipEmptyParts)) {
+ int pos = ref.lastIndexOf(QLatin1Char(':'));
+ if (pos != -1)
+ msg.addReference(ref.left(pos), ref.mid(pos + 1).toInt());
+ }
+ } else if (isObsolete) {
+ msg.setFileName(QLatin1String(MAGIC_OBSOLETE_REFERENCE));
+ }
+ msg.setId(item.id);
+ msg.setSourceText(item.msgId);
+ msg.setOldSourceText(item.oldMsgId);
+ msg.setComment(item.tscomment);
+ msg.setOldComment(item.oldTscomment);
+ msg.setExtraComment(item.automaticComments);
+ msg.setTranslatorComment(item.translatorComments);
+ msg.setPlural(item.isPlural || item.msgStr.size() > 1);
+ msg.setTranslations(item.msgStr);
+ if (isObsolete)
+ msg.setType(TranslatorMessage::Obsolete);
+ else if (item.isFuzzy)
+ msg.setType(TranslatorMessage::Unfinished);
+ else
+ msg.setType(TranslatorMessage::Finished);
+ msg.setExtras(item.extra);
+
+ //qDebug() << "WRITE: " << context;
+ //qDebug() << "SOURCE: " << msg.sourceText();
+ //qDebug() << flags << msg.m_extra;
+ translator.append(msg);
+ item = PoItem();
+ } else if (line.startsWith(QLatin1Char('#'))) {
+ switch(line.size() < 2 ? 0 : line.at(1).unicode()) {
+ case ':':
+ item.references += line.mid(3);
+ item.references += newline;
+ break;
+ case ',': {
+ QStringList flags =
+ line.mid(2).split(QRegExp(QLatin1String("[, ]")),
+ QString::SkipEmptyParts);
+ if (flags.removeOne(QLatin1String("fuzzy")))
+ item.isFuzzy = true;
+ TranslatorMessage::ExtraData::const_iterator it =
+ item.extra.find(QLatin1String("po-flags"));
+ if (it != item.extra.end())
+ flags.prepend(*it);
+ if (!flags.isEmpty())
+ item.extra[QLatin1String("po-flags")] = flags.join(QLatin1String(", "));
+ break;
+ }
+ case 0:
+ item.translatorComments += newline;
+ break;
+ case ' ':
+ slurpComment(item.translatorComments, lines, l);
+ break;
+ case '.':
+ if (line.startsWith(QLatin1String("#. ts-context "))) {
+ item.context = line.mid(14);
+ } else if (line.startsWith(QLatin1String("#. ts-id "))) {
+ item.id = line.mid(9);
+ } else {
+ item.automaticComments += line.mid(3);
+ item.automaticComments += newline;
+ }
+ break;
+ case '|':
+ if (line.startsWith(QLatin1String("#| msgid "))) {
+ item.oldMsgId = slurpEscapedString(lines, l, 9, QLatin1String("#| "), cd);
+ } else if (line.startsWith(QLatin1String("#| msgid_plural "))) {
+ QString extra = slurpEscapedString(lines, l, 16, QLatin1String("#| "), cd);
+ if (extra != item.oldMsgId)
+ item.extra[QLatin1String("po-old_msgid_plural")] = extra;
+ } else if (line.startsWith(QLatin1String("#| msgctxt "))) {
+ item.oldTscomment = slurpEscapedString(lines, l, 11, QLatin1String("#| "), cd);
+ } else {
+ cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
+ .arg(l + 1).arg(lines[l]));
+ error = true;
+ }
+ break;
+ case '~':
+ if (line.startsWith(QLatin1String("#~ msgid "))) {
+ item.msgId = slurpEscapedString(lines, l, 9, QLatin1String("#~ "), cd);
+ } else if (line.startsWith(QLatin1String("#~ msgid_plural "))) {
+ QString extra = slurpEscapedString(lines, l, 16, QLatin1String("#~ "), cd);
+ if (extra != item.msgId)
+ item.extra[QLatin1String("po-msgid_plural")] = extra;
+ item.isPlural = true;
+ } else if (line.startsWith(QLatin1String("#~ msgctxt "))) {
+ item.tscomment = slurpEscapedString(lines, l, 11, QLatin1String("#~ "), cd);
+ } else {
+ cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
+ .arg(l + 1).arg(lines[l]));
+ error = true;
+ }
+ break;
+ default:
+ cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
+ .arg(l + 1).arg(lines[l]));
+ error = true;
+ break;
+ }
+ } else if (line.startsWith(QLatin1String("msgctxt "))) {
+ item.tscomment = slurpEscapedString(lines, l, 8, QString(), cd);
+ } else if (line.startsWith(QLatin1String("msgid "))) {
+ item.msgId = slurpEscapedString(lines, l, 6, QString(), cd);
+ } else if (line.startsWith(QLatin1String("msgid_plural "))) {
+ QString extra = slurpEscapedString(lines, l, 13, QString(), cd);
+ if (extra != item.msgId)
+ item.extra[QLatin1String("po-msgid_plural")] = extra;
+ item.isPlural = true;
+ } else {
+ cd.appendError(QString(QLatin1String("PO-format error in line %1: '%2'\n"))
+ .arg(l + 1).arg(lines[l]));
+ error = true;
+ }
+ }
+ return !error && cd.errors().isEmpty();
+}
+
+bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ bool ok = true;
+ QTextStream out(&dev);
+ //qDebug() << "OUT CODEC: " << out.codec()->name();
+
+ bool first = true;
+ if (translator.messages().isEmpty() || !translator.messages().first().sourceText().isEmpty()) {
+ out <<
+ "# SOME DESCRIPTIVE TITLE.\n"
+ "# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n"
+ "# This file is distributed under the same license as the PACKAGE package.\n"
+ "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n"
+ "#\n"
+ "#, fuzzy\n"
+ "msgid \"\"\n"
+ "msgstr \"\"\n"
+ "\"X-Virgin-Header: remove this line if you change anything in the header.\\n\"\n";
+ if (!translator.languageCode().isEmpty())
+ out << "\"X-Language: " << translator.languageCode() << "\\n\"\n";
+ if (!translator.sourceLanguageCode().isEmpty())
+ out << "\"X-Source-Language: " << translator.sourceLanguageCode() << "\\n\"\n";
+ first = false;
+ }
+ foreach (const TranslatorMessage &msg, translator.messages()) {
+ if (!first)
+ out << endl;
+
+ if (!msg.translatorComment().isEmpty())
+ out << poEscapedLines(QLatin1String("#"), true, msg.translatorComment());
+
+ if (!msg.extraComment().isEmpty())
+ out << poEscapedLines(QLatin1String("#."), true, msg.extraComment());
+
+ if (!msg.context().isEmpty())
+ out << QLatin1String("#. ts-context ") << msg.context() << '\n';
+ if (!msg.id().isEmpty())
+ out << QLatin1String("#. ts-id ") << msg.id() << '\n';
+
+ if (!msg.fileName().isEmpty() && msg.fileName() != QLatin1String(MAGIC_OBSOLETE_REFERENCE)) {
+ QStringList refs;
+ foreach (const TranslatorMessage::Reference &ref, msg.allReferences())
+ refs.append(QString(QLatin1String("%2:%1"))
+ .arg(ref.lineNumber()).arg(ref.fileName()));
+ out << poWrappedEscapedLines(QLatin1String("#:"), true, refs.join(QLatin1String(" ")));
+ }
+
+ bool noWrap = false;
+ QStringList flags;
+ if (msg.type() == TranslatorMessage::Unfinished)
+ flags.append(QLatin1String("fuzzy"));
+ TranslatorMessage::ExtraData::const_iterator itr =
+ msg.extras().find(QLatin1String("po-flags"));
+ if (itr != msg.extras().end()) {
+ if (itr->split(QLatin1String(", ")).contains(QLatin1String("no-wrap")))
+ noWrap = true;
+ flags.append(*itr);
+ }
+ if (!flags.isEmpty())
+ out << "#, " << flags.join(QLatin1String(", ")) << '\n';
+
+ QString prefix = QLatin1String("#| ");
+ if (!msg.oldComment().isEmpty())
+ out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap, msg.oldComment());
+ if (!msg.oldSourceText().isEmpty())
+ out << poEscapedString(prefix, QLatin1String("msgid"), noWrap, msg.oldSourceText());
+ QString plural = msg.extra(QLatin1String("po-old_msgid_plural"));
+ if (!plural.isEmpty())
+ out << poEscapedString(prefix, QLatin1String("msgid_plural"), noWrap, plural);
+ prefix = QLatin1String((msg.type() == TranslatorMessage::Obsolete) ? "#~ " : "");
+ if (!msg.comment().isEmpty())
+ out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap, msg.comment());
+ out << poEscapedString(prefix, QLatin1String("msgid"), noWrap, msg.sourceText());
+ if (!msg.isPlural()) {
+ QString transl = msg.translation();
+ if (first) {
+ transl.remove(QRegExp(QLatin1String("\\bX-Language:[^\n]*\n")));
+ if (!translator.languageCode().isEmpty())
+ transl += QLatin1String("X-Language: ") + translator.languageCode() + QLatin1Char('\n');
+ }
+ out << poEscapedString(prefix, QLatin1String("msgstr"), noWrap, transl);
+ } else {
+ QString plural = msg.extra(QLatin1String("po-msgid_plural"));
+ if (plural.isEmpty())
+ plural = msg.sourceText();
+ out << poEscapedString(prefix, QLatin1String("msgid_plural"), noWrap, plural);
+ QStringList translations = translator.normalizedTranslations(msg, cd, &ok);
+ for (int i = 0; i != translations.size(); ++i) {
+ out << poEscapedString(prefix, QString::fromLatin1("msgstr[%1]").arg(i), noWrap,
+ translations.at(i));
+ }
+ }
+ first = false;
+ }
+ return ok;
+}
+
+int initPO()
+{
+ Translator::FileFormat format;
+ format.extension = QLatin1String("po");
+ format.description = QObject::tr("GNU Gettext localization files");
+ format.loader = &loadPO;
+ format.saver = &savePO;
+ format.fileType = Translator::FileFormat::TranslationSource;
+ format.priority = 1;
+ Translator::registerFileFormat(format);
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initPO)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp
new file mode 100644
index 0000000000..1e91f92ced
--- /dev/null
+++ b/tools/linguist/shared/profileevaluator.cpp
@@ -0,0 +1,1785 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "profileevaluator.h"
+#include "proparserutils.h"
+#include "proitems.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QList>
+#include <QtCore/QRegExp>
+#include <QtCore/QSet>
+#include <QtCore/QStack>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QTextStream>
+
+#ifdef Q_OS_WIN32
+#define QT_POPEN _popen
+#else
+#define QT_POPEN popen
+#endif
+
+QT_BEGIN_NAMESPACE
+
+///////////////////////////////////////////////////////////////////////
+//
+// ProFileEvaluator::Private
+//
+///////////////////////////////////////////////////////////////////////
+
+class ProFileEvaluator::Private : public AbstractProItemVisitor
+{
+public:
+ Private(ProFileEvaluator *q_);
+
+ bool read(ProFile *pro);
+
+ ProBlock *currentBlock();
+ void updateItem();
+ bool parseLine(const QString &line);
+ void insertVariable(const QString &line, int *i);
+ void insertOperator(const char op);
+ void insertComment(const QString &comment);
+ void enterScope(bool multiLine);
+ void leaveScope();
+ void finalizeBlock();
+
+ // implementation of AbstractProItemVisitor
+ bool visitBeginProBlock(ProBlock *block);
+ bool visitEndProBlock(ProBlock *block);
+ bool visitBeginProVariable(ProVariable *variable);
+ bool visitEndProVariable(ProVariable *variable);
+ bool visitBeginProFile(ProFile *value);
+ bool visitEndProFile(ProFile *value);
+ bool visitProValue(ProValue *value);
+ bool visitProFunction(ProFunction *function);
+ bool visitProOperator(ProOperator *oper);
+ bool visitProCondition(ProCondition *condition);
+
+ QStringList valuesDirect(const QString &variableName) const { return m_valuemap[variableName]; }
+ QStringList values(const QString &variableName) const;
+ QStringList values(const QString &variableName, const ProFile *pro) const;
+ QString propertyValue(const QString &val) const;
+
+ bool isActiveConfig(const QString &config, bool regex = false);
+ QStringList expandPattern(const QString &pattern);
+ void expandPatternHelper(const QString &relName, const QString &absName,
+ QStringList &sources_out);
+ QStringList expandVariableReferences(const QString &value);
+ QStringList evaluateExpandFunction(const QString &function, const QString &arguments);
+ QString format(const char *format) const;
+
+ QString currentFileName() const;
+ QString getcwd() const;
+ ProFile *currentProFile() const;
+
+ bool evaluateConditionalFunction(const QString &function, const QString &arguments, bool *result);
+ bool evaluateFile(const QString &fileName, bool *result);
+ bool evaluateFeatureFile(const QString &fileName, bool *result);
+
+ QStringList qmakeFeaturePaths();
+
+ ProFileEvaluator *q;
+
+ QStack<ProBlock *> m_blockstack;
+ ProBlock *m_block;
+
+ ProItem *m_commentItem;
+ QString m_proitem;
+ QString m_pendingComment;
+ bool m_syntaxError;
+ bool m_contNextLine;
+ bool m_condition;
+ bool m_invertNext;
+ QString m_lastVarName;
+ ProVariable::VariableOperator m_variableOperator;
+ int m_lineNo; // Error reporting
+ QString m_oldPath; // To restore the current path to the path
+ QStack<ProFile*> m_profileStack; // To handle 'include(a.pri), so we can track back to 'a.pro' when finished with 'a.pri'
+
+ QHash<QString, QStringList> m_valuemap; // VariableName must be us-ascii, the content however can be non-us-ascii.
+ QHash<const ProFile*, QHash<QString, QStringList> > m_filevaluemap; // Variables per include file
+ QHash<QString, QString> m_properties;
+ QString m_origfile;
+
+ int m_prevLineNo; // Checking whether we're assigning the same TARGET
+ ProFile *m_prevProFile; // See m_prevLineNo
+
+ bool m_verbose;
+};
+
+ProFileEvaluator::Private::Private(ProFileEvaluator *q_)
+ : q(q_)
+{
+ m_prevLineNo = 0;
+ m_prevProFile = 0;
+ m_verbose = true;
+ m_block = 0;
+ m_commentItem = 0;
+ m_syntaxError = 0;
+ m_lineNo = 0;
+ m_contNextLine = false;
+}
+
+bool ProFileEvaluator::Private::read(ProFile *pro)
+{
+ QFile file(pro->fileName());
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ q->errorMessage(format("%1 not readable.").arg(pro->fileName()));
+ return false;
+ }
+
+ m_syntaxError = false;
+ m_lineNo = 1;
+ m_blockstack.push(pro);
+
+ QTextStream ts(&file);
+ while (!ts.atEnd()) {
+ QString line = ts.readLine();
+ if (!parseLine(line)) {
+ q->errorMessage(format(".pro parse failure."));
+ return false;
+ }
+ ++m_lineNo;
+ }
+ return true;
+}
+
+bool ProFileEvaluator::Private::parseLine(const QString &line0)
+{
+ if (m_blockstack.isEmpty())
+ return false;
+
+ ushort quote = 0;
+ int parens = 0;
+ bool contNextLine = false;
+ QString line = line0.simplified();
+
+ for (int i = 0; !m_syntaxError && i < line.length(); ++i) {
+ ushort c = line.at(i).unicode();
+ if (quote && c == quote)
+ quote = 0;
+ else if (c == '(')
+ ++parens;
+ else if (c == ')')
+ --parens;
+ else if (c == '"' && (i == 0 || line.at(i - 1).unicode() != '\\'))
+ quote = c;
+ else if (!parens && !quote) {
+ if (c == '#') {
+ insertComment(line.mid(i + 1));
+ contNextLine = m_contNextLine;
+ break;
+ }
+ if (c == '\\' && i >= line.count() - 1) {
+ updateItem();
+ contNextLine = true;
+ continue;
+ }
+ if (m_block && (m_block->blockKind() & ProBlock::VariableKind)) {
+ if (c == ' ')
+ updateItem();
+ else
+ m_proitem += c;
+ continue;
+ }
+ if (c == ':') {
+ enterScope(false);
+ continue;
+ }
+ if (c == '{') {
+ enterScope(true);
+ continue;
+ }
+ if (c == '}') {
+ leaveScope();
+ continue;
+ }
+ if (c == '=') {
+ insertVariable(line, &i);
+ continue;
+ }
+ if (c == '|' || c == '!') {
+ insertOperator(c);
+ continue;
+ }
+ }
+
+ m_proitem += c;
+ }
+ m_contNextLine = contNextLine;
+
+ if (!m_syntaxError) {
+ updateItem();
+ if (!m_contNextLine)
+ finalizeBlock();
+ }
+ return !m_syntaxError;
+}
+
+void ProFileEvaluator::Private::finalizeBlock()
+{
+ if (m_blockstack.isEmpty()) {
+ m_syntaxError = true;
+ } else {
+ if (m_blockstack.top()->blockKind() & ProBlock::SingleLine)
+ leaveScope();
+ m_block = 0;
+ m_commentItem = 0;
+ }
+}
+
+void ProFileEvaluator::Private::insertVariable(const QString &line, int *i)
+{
+ ProVariable::VariableOperator opkind;
+
+ switch (m_proitem.at(m_proitem.length() - 1).unicode()) {
+ case '+':
+ m_proitem.chop(1);
+ opkind = ProVariable::AddOperator;
+ break;
+ case '-':
+ m_proitem.chop(1);
+ opkind = ProVariable::RemoveOperator;
+ break;
+ case '*':
+ m_proitem.chop(1);
+ opkind = ProVariable::UniqueAddOperator;
+ break;
+ case '~':
+ m_proitem.chop(1);
+ opkind = ProVariable::ReplaceOperator;
+ break;
+ default:
+ opkind = ProVariable::SetOperator;
+ }
+
+ ProBlock *block = m_blockstack.top();
+ m_proitem = m_proitem.trimmed();
+ ProVariable *variable = new ProVariable(m_proitem, block);
+ variable->setLineNumber(m_lineNo);
+ variable->setVariableOperator(opkind);
+ block->appendItem(variable);
+ m_block = variable;
+
+ if (!m_pendingComment.isEmpty()) {
+ m_block->setComment(m_pendingComment);
+ m_pendingComment.clear();
+ }
+ m_commentItem = variable;
+
+ m_proitem.clear();
+
+ if (opkind == ProVariable::ReplaceOperator) {
+ // skip util end of line or comment
+ while (1) {
+ ++(*i);
+
+ // end of line?
+ if (*i >= line.count())
+ break;
+
+ // comment?
+ if (line.at(*i).unicode() == '#') {
+ --(*i);
+ break;
+ }
+
+ m_proitem += line.at(*i);
+ }
+ m_proitem = m_proitem.trimmed();
+ }
+}
+
+void ProFileEvaluator::Private::insertOperator(const char op)
+{
+ updateItem();
+
+ ProOperator::OperatorKind opkind;
+ switch(op) {
+ case '!':
+ opkind = ProOperator::NotOperator;
+ break;
+ case '|':
+ opkind = ProOperator::OrOperator;
+ break;
+ default:
+ opkind = ProOperator::OrOperator;
+ }
+
+ ProBlock * const block = currentBlock();
+ ProOperator * const proOp = new ProOperator(opkind);
+ proOp->setLineNumber(m_lineNo);
+ block->appendItem(proOp);
+ m_commentItem = proOp;
+}
+
+void ProFileEvaluator::Private::insertComment(const QString &comment)
+{
+ updateItem();
+
+ QString strComment;
+ if (!m_commentItem)
+ strComment = m_pendingComment;
+ else
+ strComment = m_commentItem->comment();
+
+ if (strComment.isEmpty())
+ strComment = comment;
+ else {
+ strComment += QLatin1Char('\n');
+ strComment += comment.trimmed();
+ }
+
+ strComment = strComment.trimmed();
+
+ if (!m_commentItem)
+ m_pendingComment = strComment;
+ else
+ m_commentItem->setComment(strComment);
+}
+
+void ProFileEvaluator::Private::enterScope(bool multiLine)
+{
+ updateItem();
+
+ ProBlock *parent = currentBlock();
+ ProBlock *block = new ProBlock(parent);
+ block->setLineNumber(m_lineNo);
+ parent->setBlockKind(ProBlock::ScopeKind);
+
+ parent->appendItem(block);
+
+ if (multiLine)
+ block->setBlockKind(ProBlock::ScopeContentsKind);
+ else
+ block->setBlockKind(ProBlock::ScopeContentsKind|ProBlock::SingleLine);
+
+ m_blockstack.push(block);
+ m_block = 0;
+}
+
+void ProFileEvaluator::Private::leaveScope()
+{
+ updateItem();
+ m_blockstack.pop();
+ finalizeBlock();
+}
+
+ProBlock *ProFileEvaluator::Private::currentBlock()
+{
+ if (m_block)
+ return m_block;
+
+ ProBlock *parent = m_blockstack.top();
+ m_block = new ProBlock(parent);
+ m_block->setLineNumber(m_lineNo);
+ parent->appendItem(m_block);
+
+ if (!m_pendingComment.isEmpty()) {
+ m_block->setComment(m_pendingComment);
+ m_pendingComment.clear();
+ }
+
+ m_commentItem = m_block;
+
+ return m_block;
+}
+
+void ProFileEvaluator::Private::updateItem()
+{
+ m_proitem = m_proitem.trimmed();
+ if (m_proitem.isEmpty())
+ return;
+
+ ProBlock *block = currentBlock();
+ if (block->blockKind() & ProBlock::VariableKind) {
+ m_commentItem = new ProValue(m_proitem, static_cast<ProVariable*>(block));
+ } else if (m_proitem.endsWith(QLatin1Char(')'))) {
+ m_commentItem = new ProFunction(m_proitem);
+ } else {
+ m_commentItem = new ProCondition(m_proitem);
+ }
+ m_commentItem->setLineNumber(m_lineNo);
+ block->appendItem(m_commentItem);
+
+ m_proitem.clear();
+}
+
+
+bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block)
+{
+ if (block->blockKind() == ProBlock::ScopeKind) {
+ m_invertNext = false;
+ m_condition = false;
+ }
+ return true;
+}
+
+bool ProFileEvaluator::Private::visitEndProBlock(ProBlock *block)
+{
+ Q_UNUSED(block);
+ return true;
+}
+
+bool ProFileEvaluator::Private::visitBeginProVariable(ProVariable *variable)
+{
+ m_lastVarName = variable->variable();
+ m_variableOperator = variable->variableOperator();
+ return true;
+}
+
+bool ProFileEvaluator::Private::visitEndProVariable(ProVariable *variable)
+{
+ Q_UNUSED(variable);
+ m_lastVarName.clear();
+ return true;
+}
+
+bool ProFileEvaluator::Private::visitProOperator(ProOperator *oper)
+{
+ m_invertNext = (oper->operatorKind() == ProOperator::NotOperator);
+ return true;
+}
+
+bool ProFileEvaluator::Private::visitProCondition(ProCondition *cond)
+{
+ if (!m_condition) {
+ if (m_invertNext)
+ m_condition |= !isActiveConfig(cond->text(), true);
+ else
+ m_condition |= isActiveConfig(cond->text(), true);
+ }
+ return true;
+}
+
+bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro)
+{
+ PRE(pro);
+ bool ok = true;
+ m_lineNo = pro->lineNumber();
+ if (m_oldPath.isEmpty()) {
+ // change the working directory for the initial profile we visit, since
+ // that is *the* profile. All the other times we reach this function will be due to
+ // include(file) or load(file)
+ m_oldPath = QDir::currentPath();
+ m_profileStack.push(pro);
+ ok = QDir::setCurrent(pro->directoryName());
+ }
+
+ if (m_origfile.isEmpty())
+ m_origfile = pro->fileName();
+
+ return ok;
+}
+
+bool ProFileEvaluator::Private::visitEndProFile(ProFile * pro)
+{
+ PRE(pro);
+ bool ok = true;
+ m_lineNo = pro->lineNumber();
+ if (m_profileStack.count() == 1 && !m_oldPath.isEmpty()) {
+ m_profileStack.pop();
+ ok = QDir::setCurrent(m_oldPath);
+ }
+ return ok;
+}
+
+bool ProFileEvaluator::Private::visitProValue(ProValue *value)
+{
+ PRE(value);
+ m_lineNo = value->lineNumber();
+ QString val = value->value();
+
+ QString varName = m_lastVarName;
+
+ QStringList v = expandVariableReferences(val);
+
+ // Since qmake combines different values for the TARGET variable, we join
+ // TARGET values that are on the same line. We can't do this later with all
+ // values because this parser isn't scope-aware, so we'd risk joining
+ // scope-specific targets together.
+ if (varName == QLatin1String("TARGET")
+ && m_lineNo == m_prevLineNo
+ && currentProFile() == m_prevProFile) {
+ QStringList targets = m_valuemap.value(QLatin1String("TARGET"));
+ m_valuemap.remove(QLatin1String("TARGET"));
+ QStringList lastTarget(targets.takeLast());
+ lastTarget << v.join(QLatin1String(" "));
+ targets.push_back(lastTarget.join(QLatin1String(" ")));
+ v = targets;
+ }
+ m_prevLineNo = m_lineNo;
+ m_prevProFile = currentProFile();
+
+ // The following two blocks fix bug 180128 by making all "interesting"
+ // file name absolute in each .pro file, not just the top most one
+ if (varName == QLatin1String("SOURCES")
+ || varName == QLatin1String("HEADERS")
+ || varName == QLatin1String("INTERFACES")
+ || varName == QLatin1String("FORMS")
+ || varName == QLatin1String("FORMS3")
+ || varName == QLatin1String("RESOURCES")) {
+ // matches only existent files, expand certain(?) patterns
+ QStringList vv;
+ for (int i = v.count(); --i >= 0; )
+ vv << expandPattern(v[i]);
+ v = vv;
+ }
+
+ if (varName == QLatin1String("TRANSLATIONS")) {
+ // also matches non-existent files, but does not expand pattern
+ QString dir = QFileInfo(currentFileName()).absolutePath();
+ dir += QLatin1Char('/');
+ for (int i = v.count(); --i >= 0; )
+ v[i] = QFileInfo(dir, v[i]).absoluteFilePath();
+ }
+
+ switch (m_variableOperator) {
+ case ProVariable::UniqueAddOperator: // *
+ insertUnique(&m_valuemap, varName, v, true);
+ insertUnique(&m_filevaluemap[currentProFile()], varName, v, true);
+ break;
+ case ProVariable::SetOperator: // =
+ case ProVariable::AddOperator: // +
+ insertUnique(&m_valuemap, varName, v, false);
+ insertUnique(&m_filevaluemap[currentProFile()], varName, v, false);
+ break;
+ case ProVariable::RemoveOperator: // -
+ // fix me: interaction between AddOperator and RemoveOperator
+ insertUnique(&m_valuemap, varName.prepend(QLatin1Char('-')), v, false);
+ insertUnique(&m_filevaluemap[currentProFile()],
+ varName.prepend(QLatin1Char('-')), v, false);
+ break;
+ case ProVariable::ReplaceOperator: // ~
+ {
+ // DEFINES ~= s/a/b/?[gqi]
+
+/* Create a superset by executing replacement + adding items that have changed
+ to original list. We're not sure if this is really the right approach, so for
+ the time being we will just do nothing ...
+
+ QChar sep = val.at(1);
+ QStringList func = val.split(sep);
+ if (func.count() < 3 || func.count() > 4) {
+ q->logMessage(format("'~= operator '(function s///) expects 3 or 4 arguments."));
+ return false;
+ }
+ if (func[0] != QLatin1String("s")) {
+ q->logMessage(format("~= operator can only handle s/// function."));
+ return false;
+ }
+
+ bool global = false, quote = false, case_sense = false;
+ if (func.count() == 4) {
+ global = func[3].indexOf(QLatin1Char('g')) != -1;
+ case_sense = func[3].indexOf(QLatin1Char('i')) == -1;
+ quote = func[3].indexOf(QLatin1Char('q')) != -1;
+ }
+ QString pattern = func[1];
+ QString replace = func[2];
+ if (quote)
+ pattern = QRegExp::escape(pattern);
+
+ QRegExp regexp(pattern, case_sense ? Qt::CaseSensitive : Qt::CaseInsensitive);
+
+ QStringList replaceList = replaceInList(m_valuemap.value(varName), regexp, replace,
+ global);
+ // Add changed entries to list
+ foreach (const QString &entry, replaceList)
+ if (!m_valuemap.value(varName).contains(entry))
+ insertUnique(&m_valuemap, varName, QStringList() << entry, false);
+
+ replaceList = replaceInList(m_filevaluemap[currentProFile()].value(varName), regexp,
+ replace, global);
+ foreach (const QString &entry, replaceList)
+ if (!m_filevaluemap[currentProFile()].value(varName).contains(entry))
+ insertUnique(&m_filevaluemap[currentProFile()], varName,
+ QStringList() << entry, false); */
+ }
+ break;
+
+ }
+ return true;
+}
+
+bool ProFileEvaluator::Private::visitProFunction(ProFunction *func)
+{
+ m_lineNo = func->lineNumber();
+ bool result = true;
+ bool ok = true;
+ QString text = func->text();
+ int lparen = text.indexOf(QLatin1Char('('));
+ int rparen = text.lastIndexOf(QLatin1Char(')'));
+ Q_ASSERT(lparen < rparen);
+
+ QString arguments = text.mid(lparen + 1, rparen - lparen - 1);
+ QString funcName = text.left(lparen);
+ ok &= evaluateConditionalFunction(funcName.trimmed(), arguments, &result);
+ return ok;
+}
+
+
+QStringList ProFileEvaluator::Private::qmakeFeaturePaths()
+{
+ QStringList concat;
+ {
+ const QString base_concat = QDir::separator() + QString(QLatin1String("features"));
+ concat << base_concat + QDir::separator() + QLatin1String("mac");
+ concat << base_concat + QDir::separator() + QLatin1String("macx");
+ concat << base_concat + QDir::separator() + QLatin1String("unix");
+ concat << base_concat + QDir::separator() + QLatin1String("win32");
+ concat << base_concat + QDir::separator() + QLatin1String("mac9");
+ concat << base_concat + QDir::separator() + QLatin1String("qnx6");
+ concat << base_concat;
+ }
+ const QString mkspecs_concat = QDir::separator() + QString(QLatin1String("mkspecs"));
+ QStringList feature_roots;
+ QByteArray mkspec_path = qgetenv("QMAKEFEATURES");
+ if (!mkspec_path.isNull())
+ feature_roots += splitPathList(QString::fromLocal8Bit(mkspec_path));
+ /*
+ if (prop)
+ feature_roots += splitPathList(prop->value("QMAKEFEATURES"));
+ if (!Option::mkfile::cachefile.isEmpty()) {
+ QString path;
+ int last_slash = Option::mkfile::cachefile.lastIndexOf(Option::dir_sep);
+ if (last_slash != -1)
+ path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash));
+ foreach (const QString &concat_it, concat)
+ feature_roots << (path + concat_it);
+ }
+ */
+
+ QByteArray qmakepath = qgetenv("QMAKEPATH");
+ if (!qmakepath.isNull()) {
+ const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath));
+ foreach (const QString &item, lst) {
+ foreach (const QString &concat_it, concat)
+ feature_roots << (item + mkspecs_concat + concat_it);
+ }
+ }
+ //if (!Option::mkfile::qmakespec.isEmpty())
+ // feature_roots << Option::mkfile::qmakespec + QDir::separator() + "features";
+ //if (!Option::mkfile::qmakespec.isEmpty()) {
+ // QFileInfo specfi(Option::mkfile::qmakespec);
+ // QDir specdir(specfi.absoluteFilePath());
+ // while (!specdir.isRoot()) {
+ // if (!specdir.cdUp() || specdir.isRoot())
+ // break;
+ // if (QFile::exists(specdir.path() + QDir::separator() + "features")) {
+ // foreach (const QString &concat_it, concat)
+ // feature_roots << (specdir.path() + concat_it);
+ // break;
+ // }
+ // }
+ //}
+ foreach (const QString &concat_it, concat)
+ feature_roots << (propertyValue(QLatin1String("QT_INSTALL_PREFIX")) +
+ mkspecs_concat + concat_it);
+ foreach (const QString &concat_it, concat)
+ feature_roots << (propertyValue(QLatin1String("QT_INSTALL_DATA")) +
+ mkspecs_concat + concat_it);
+ return feature_roots;
+}
+
+QString ProFileEvaluator::Private::propertyValue(const QString &name) const
+{
+ if (m_properties.contains(name))
+ return m_properties.value(name);
+ if (name == QLatin1String("QT_INSTALL_PREFIX"))
+ return QLibraryInfo::location(QLibraryInfo::PrefixPath);
+ if (name == QLatin1String("QT_INSTALL_DATA"))
+ return QLibraryInfo::location(QLibraryInfo::DataPath);
+ if (name == QLatin1String("QT_INSTALL_DOCS"))
+ return QLibraryInfo::location(QLibraryInfo::DocumentationPath);
+ if (name == QLatin1String("QT_INSTALL_HEADERS"))
+ return QLibraryInfo::location(QLibraryInfo::HeadersPath);
+ if (name == QLatin1String("QT_INSTALL_LIBS"))
+ return QLibraryInfo::location(QLibraryInfo::LibrariesPath);
+ if (name == QLatin1String("QT_INSTALL_BINS"))
+ return QLibraryInfo::location(QLibraryInfo::BinariesPath);
+ if (name == QLatin1String("QT_INSTALL_PLUGINS"))
+ return QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ if (name == QLatin1String("QT_INSTALL_TRANSLATIONS"))
+ return QLibraryInfo::location(QLibraryInfo::TranslationsPath);
+ if (name == QLatin1String("QT_INSTALL_CONFIGURATION"))
+ return QLibraryInfo::location(QLibraryInfo::SettingsPath);
+ if (name == QLatin1String("QT_INSTALL_EXAMPLES"))
+ return QLibraryInfo::location(QLibraryInfo::ExamplesPath);
+ if (name == QLatin1String("QT_INSTALL_DEMOS"))
+ return QLibraryInfo::location(QLibraryInfo::DemosPath);
+ if (name == QLatin1String("QMAKE_MKSPECS"))
+ return qmake_mkspec_paths().join(Option::dirlist_sep);
+ if (name == QLatin1String("QMAKE_VERSION"))
+ return QLatin1String("1.0"); //### FIXME
+ //return qmake_version();
+#ifdef QT_VERSION_STR
+ if (name == QLatin1String("QT_VERSION"))
+ return QLatin1String(QT_VERSION_STR);
+#endif
+ return QLatin1String("UNKNOWN"); //###
+}
+
+ProFile *ProFileEvaluator::Private::currentProFile() const
+{
+ if (m_profileStack.count() > 0)
+ return m_profileStack.top();
+ return 0;
+}
+
+QString ProFileEvaluator::Private::currentFileName() const
+{
+ ProFile *pro = currentProFile();
+ if (pro)
+ return pro->fileName();
+ return QString();
+}
+
+QString ProFileEvaluator::Private::getcwd() const
+{
+ ProFile *cur = m_profileStack.top();
+ return cur->directoryName();
+}
+
+QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str)
+{
+ QStringList ret;
+// if (ok)
+// *ok = true;
+ if (str.isEmpty())
+ return ret;
+
+ const ushort LSQUARE = '[';
+ const ushort RSQUARE = ']';
+ const ushort LCURLY = '{';
+ const ushort RCURLY = '}';
+ const ushort LPAREN = '(';
+ const ushort RPAREN = ')';
+ const ushort DOLLAR = '$';
+ const ushort BACKSLASH = '\\';
+ const ushort UNDERSCORE = '_';
+ const ushort DOT = '.';
+ const ushort SPACE = ' ';
+ const ushort TAB = '\t';
+ const ushort SINGLEQUOTE = '\'';
+ const ushort DOUBLEQUOTE = '"';
+
+ ushort unicode, quote = 0;
+ const QChar *str_data = str.data();
+ const int str_len = str.length();
+
+ ushort term;
+ QString var, args;
+
+ int replaced = 0;
+ QString current;
+ for (int i = 0; i < str_len; ++i) {
+ unicode = str_data[i].unicode();
+ const int start_var = i;
+ if (unicode == DOLLAR && str_len > i+2) {
+ unicode = str_data[++i].unicode();
+ if (unicode == DOLLAR) {
+ term = 0;
+ var.clear();
+ args.clear();
+ enum { VAR, ENVIRON, FUNCTION, PROPERTY } var_type = VAR;
+ unicode = str_data[++i].unicode();
+ if (unicode == LSQUARE) {
+ unicode = str_data[++i].unicode();
+ term = RSQUARE;
+ var_type = PROPERTY;
+ } else if (unicode == LCURLY) {
+ unicode = str_data[++i].unicode();
+ var_type = VAR;
+ term = RCURLY;
+ } else if (unicode == LPAREN) {
+ unicode = str_data[++i].unicode();
+ var_type = ENVIRON;
+ term = RPAREN;
+ }
+ forever {
+ if (!(unicode & (0xFF<<8)) &&
+ unicode != DOT && unicode != UNDERSCORE &&
+ //unicode != SINGLEQUOTE && unicode != DOUBLEQUOTE &&
+ (unicode < 'a' || unicode > 'z') && (unicode < 'A' || unicode > 'Z') &&
+ (unicode < '0' || unicode > '9'))
+ break;
+ var.append(QChar(unicode));
+ if (++i == str_len)
+ break;
+ unicode = str_data[i].unicode();
+ // at this point, i points to either the 'term' or 'next' character (which is in unicode)
+ }
+ if (var_type == VAR && unicode == LPAREN) {
+ var_type = FUNCTION;
+ int depth = 0;
+ forever {
+ if (++i == str_len)
+ break;
+ unicode = str_data[i].unicode();
+ if (unicode == LPAREN) {
+ depth++;
+ } else if (unicode == RPAREN) {
+ if (!depth)
+ break;
+ --depth;
+ }
+ args.append(QChar(unicode));
+ }
+ if (++i < str_len)
+ unicode = str_data[i].unicode();
+ else
+ unicode = 0;
+ // at this point i is pointing to the 'next' character (which is in unicode)
+ // this might actually be a term character since you can do $${func()}
+ }
+ if (term) {
+ if (unicode != term) {
+ q->logMessage(format("Missing %1 terminator [found %2]")
+ .arg(QChar(term))
+ .arg(unicode ? QString(unicode) : QString::fromLatin1(("end-of-line"))));
+// if (ok)
+// *ok = false;
+ return QStringList();
+ }
+ } else {
+ // move the 'cursor' back to the last char of the thing we were looking at
+ --i;
+ }
+ // since i never points to the 'next' character, there is no reason for this to be set
+ unicode = 0;
+
+ QStringList replacement;
+ if (var_type == ENVIRON) {
+ replacement = split_value_list(QString::fromLocal8Bit(qgetenv(var.toLatin1().constData())));
+ } else if (var_type == PROPERTY) {
+ replacement << propertyValue(var);
+ } else if (var_type == FUNCTION) {
+ replacement << evaluateExpandFunction(var, args);
+ } else if (var_type == VAR) {
+ replacement = values(var);
+ }
+ if (!(replaced++) && start_var)
+ current = str.left(start_var);
+ if (!replacement.isEmpty()) {
+ if (quote) {
+ current += replacement.join(QString(Option::field_sep));
+ } else {
+ current += replacement.takeFirst();
+ if (!replacement.isEmpty()) {
+ if (!current.isEmpty())
+ ret.append(current);
+ current = replacement.takeLast();
+ if (!replacement.isEmpty())
+ ret += replacement;
+ }
+ }
+ }
+ } else {
+ if (replaced)
+ current.append(QLatin1Char('$'));
+ }
+ }
+ if (quote && unicode == quote) {
+ unicode = 0;
+ quote = 0;
+ } else if (unicode == BACKSLASH) {
+ bool escape = false;
+ const char *symbols = "[]{}()$\\'\"";
+ for (const char *s = symbols; *s; ++s) {
+ if (str_data[i+1].unicode() == (ushort)*s) {
+ i++;
+ escape = true;
+ if (!(replaced++))
+ current = str.left(start_var);
+ current.append(str.at(i));
+ break;
+ }
+ }
+ if (escape || !replaced)
+ unicode =0;
+ } else if (!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) {
+ quote = unicode;
+ unicode = 0;
+ if (!(replaced++) && i)
+ current = str.left(i);
+ } else if (!quote && (unicode == SPACE || unicode == TAB)) {
+ unicode = 0;
+ if (!current.isEmpty()) {
+ ret.append(current);
+ current.clear();
+ }
+ }
+ if (replaced && unicode)
+ current.append(QChar(unicode));
+ }
+ if (!replaced)
+ ret = QStringList(str);
+ else if (!current.isEmpty())
+ ret.append(current);
+ return ret;
+}
+
+bool ProFileEvaluator::Private::isActiveConfig(const QString &config, bool regex)
+{
+ // magic types for easy flipping
+ if (config == QLatin1String("true"))
+ return true;
+ if (config == QLatin1String("false"))
+ return false;
+
+ // mkspecs
+ if ((Option::target_mode == Option::TARG_MACX_MODE
+ || Option::target_mode == Option::TARG_QNX6_MODE
+ || Option::target_mode == Option::TARG_UNIX_MODE)
+ && config == QLatin1String("unix"))
+ return true;
+ if (Option::target_mode == Option::TARG_MACX_MODE && config == QLatin1String("macx"))
+ return true;
+ if (Option::target_mode == Option::TARG_QNX6_MODE && config == QLatin1String("qnx6"))
+ return true;
+ if (Option::target_mode == Option::TARG_MAC9_MODE && config == QLatin1String("mac9"))
+ return true;
+ if ((Option::target_mode == Option::TARG_MAC9_MODE
+ || Option::target_mode == Option::TARG_MACX_MODE)
+ && config == QLatin1String("mac"))
+ return true;
+ if (Option::target_mode == Option::TARG_WIN_MODE && config == QLatin1String("win32"))
+ return true;
+
+ QRegExp re(config, Qt::CaseSensitive, QRegExp::Wildcard);
+ QString spec = Option::qmakespec;
+ if ((regex && re.exactMatch(spec)) || (!regex && spec == config))
+ return true;
+
+ return false;
+}
+
+QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &func, const QString &arguments)
+{
+ QStringList argumentsList = split_arg_list(arguments);
+ QStringList args;
+ for (int i = 0; i < argumentsList.count(); ++i)
+ args += expandVariableReferences(argumentsList[i]);
+
+ enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST,
+ E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION,
+ E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND,
+ E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE,
+ E_REPLACE };
+
+ static QHash<QString, int> *expands = 0;
+ if (!expands) {
+ expands = new QHash<QString, int>;
+ expands->insert(QLatin1String("member"), E_MEMBER); //v (implemented)
+ expands->insert(QLatin1String("first"), E_FIRST); //v
+ expands->insert(QLatin1String("last"), E_LAST); //v
+ expands->insert(QLatin1String("cat"), E_CAT);
+ expands->insert(QLatin1String("fromfile"), E_FROMFILE);
+ expands->insert(QLatin1String("eval"), E_EVAL);
+ expands->insert(QLatin1String("list"), E_LIST);
+ expands->insert(QLatin1String("sprintf"), E_SPRINTF);
+ expands->insert(QLatin1String("join"), E_JOIN); //v
+ expands->insert(QLatin1String("split"), E_SPLIT); //v
+ expands->insert(QLatin1String("basename"), E_BASENAME); //v
+ expands->insert(QLatin1String("dirname"), E_DIRNAME); //v
+ expands->insert(QLatin1String("section"), E_SECTION);
+ expands->insert(QLatin1String("find"), E_FIND);
+ expands->insert(QLatin1String("system"), E_SYSTEM); //v
+ expands->insert(QLatin1String("unique"), E_UNIQUE);
+ expands->insert(QLatin1String("quote"), E_QUOTE); //v
+ expands->insert(QLatin1String("escape_expand"), E_ESCAPE_EXPAND);
+ expands->insert(QLatin1String("upper"), E_UPPER);
+ expands->insert(QLatin1String("lower"), E_LOWER);
+ expands->insert(QLatin1String("re_escape"), E_RE_ESCAPE);
+ expands->insert(QLatin1String("files"), E_FILES);
+ expands->insert(QLatin1String("prompt"), E_PROMPT);
+ expands->insert(QLatin1String("replace"), E_REPLACE);
+ }
+ ExpandFunc func_t = ExpandFunc(expands->value(func.toLower()));
+
+ QStringList ret;
+
+ switch (func_t) {
+ case E_BASENAME:
+ case E_DIRNAME:
+ case E_SECTION: {
+ bool regexp = false;
+ QString sep, var;
+ int beg = 0;
+ int end = -1;
+ if (func_t == E_SECTION) {
+ if (args.count() != 3 && args.count() != 4) {
+ q->logMessage(format("%1(var) section(var, sep, begin, end) "
+ "requires three or four arguments.").arg(func));
+ } else {
+ var = args[0];
+ sep = args[1];
+ beg = args[2].toInt();
+ if (args.count() == 4)
+ end = args[3].toInt();
+ }
+ } else {
+ if (args.count() != 1) {
+ q->logMessage(format("%1(var) requires one argument.").arg(func));
+ } else {
+ var = args[0];
+ regexp = true;
+ sep = QLatin1String("[\\\\/]");
+ if (func_t == E_DIRNAME)
+ end = -2;
+ else
+ beg = -1;
+ }
+ }
+ if (!var.isNull()) {
+ foreach (const QString str, values(var)) {
+ if (regexp)
+ ret += str.section(QRegExp(sep), beg, end);
+ else
+ ret += str.section(sep, beg, end);
+ }
+ }
+ break;
+ }
+ case E_JOIN: {
+ if (args.count() < 1 || args.count() > 4) {
+ q->logMessage(format("join(var, glue, before, after) requires one to four arguments."));
+ } else {
+ QString glue, before, after;
+ if (args.count() >= 2)
+ glue = args[1];
+ if (args.count() >= 3)
+ before = args[2];
+ if (args.count() == 4)
+ after = args[3];
+ const QStringList &var = values(args.first());
+ if (!var.isEmpty())
+ ret.append(before + var.join(glue) + after);
+ }
+ break;
+ }
+ case E_SPLIT: {
+ if (args.count() != 2) {
+ q->logMessage(format("split(var, sep) requires two arguments"));
+ } else {
+ QString sep = args.at(1);
+ foreach (const QString &var, values(args.first()))
+ foreach (const QString &splt, var.split(sep))
+ ret.append(splt);
+ }
+ break;
+ }
+ case E_MEMBER: {
+ if (args.count() < 1 || args.count() > 3) {
+ q->logMessage(format("member(var, start, end) requires one to three arguments."));
+ } else {
+ bool ok = true;
+ const QStringList var = values(args.first());
+ int start = 0, end = 0;
+ if (args.count() >= 2) {
+ QString start_str = args[1];
+ start = start_str.toInt(&ok);
+ if (!ok) {
+ if (args.count() == 2) {
+ int dotdot = start_str.indexOf(QLatin1String(".."));
+ if (dotdot != -1) {
+ start = start_str.left(dotdot).toInt(&ok);
+ if (ok)
+ end = start_str.mid(dotdot+2).toInt(&ok);
+ }
+ }
+ if (!ok)
+ q->logMessage(format("member() argument 2 (start) '%2' invalid.")
+ .arg(start_str));
+ } else {
+ end = start;
+ if (args.count() == 3)
+ end = args[2].toInt(&ok);
+ if (!ok)
+ q->logMessage(format("member() argument 3 (end) '%2' invalid.\n")
+ .arg(args[2]));
+ }
+ }
+ if (ok) {
+ if (start < 0)
+ start += var.count();
+ if (end < 0)
+ end += var.count();
+ if (start < 0 || start >= var.count() || end < 0 || end >= var.count()) {
+ //nothing
+ } else if (start < end) {
+ for (int i = start; i <= end && var.count() >= i; i++)
+ ret.append(var[i]);
+ } else {
+ for (int i = start; i >= end && var.count() >= i && i >= 0; i--)
+ ret += var[i];
+ }
+ }
+ }
+ break;
+ }
+ case E_FIRST:
+ case E_LAST: {
+ if (args.count() != 1) {
+ q->logMessage(format("%1(var) requires one argument.").arg(func));
+ } else {
+ const QStringList var = values(args.first());
+ if (!var.isEmpty()) {
+ if (func_t == E_FIRST)
+ ret.append(var[0]);
+ else
+ ret.append(var.last());
+ }
+ }
+ break;
+ }
+ case E_SYSTEM: {
+ if (m_condition) {
+ if (args.count() < 1 || args.count() > 2) {
+ q->logMessage(format("system(execute) requires one or two arguments."));
+ } else {
+ char buff[256];
+ FILE *proc = QT_POPEN(args[0].toLatin1(), "r");
+ bool singleLine = true;
+ if (args.count() > 1)
+ singleLine = (args[1].toLower() == QLatin1String("true"));
+ QString output;
+ while (proc && !feof(proc)) {
+ int read_in = int(fread(buff, 1, 255, proc));
+ if (!read_in)
+ break;
+ for (int i = 0; i < read_in; i++) {
+ if ((singleLine && buff[i] == '\n') || buff[i] == '\t')
+ buff[i] = ' ';
+ }
+ buff[read_in] = '\0';
+ output += QLatin1String(buff);
+ }
+ ret += split_value_list(output);
+ }
+ }
+ break; }
+ case E_QUOTE:
+ for (int i = 0; i < args.count(); ++i)
+ ret += QStringList(args.at(i));
+ break;
+ case 0:
+ q->logMessage(format("'%1' is not a function").arg(func));
+ break;
+ default:
+ q->logMessage(format("Function '%1' is not implemented").arg(func));
+ break;
+ }
+
+ return ret;
+}
+
+bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &function,
+ const QString &arguments, bool *result)
+{
+ QStringList argumentsList = split_arg_list(arguments);
+ QString sep;
+ sep.append(Option::field_sep);
+
+ QStringList args;
+ for (int i = 0; i < argumentsList.count(); ++i)
+ args += expandVariableReferences(argumentsList[i]).join(sep);
+
+ enum ConditionFunc { CF_CONFIG = 1, CF_CONTAINS, CF_COUNT, CF_EXISTS, CF_INCLUDE,
+ CF_LOAD, CF_ISEMPTY, CF_SYSTEM, CF_MESSAGE};
+
+ static QHash<QString, int> *functions = 0;
+ if (!functions) {
+ functions = new QHash<QString, int>;
+ functions->insert(QLatin1String("load"), CF_LOAD); //v
+ functions->insert(QLatin1String("include"), CF_INCLUDE); //v
+ functions->insert(QLatin1String("message"), CF_MESSAGE); //v
+ functions->insert(QLatin1String("warning"), CF_MESSAGE); //v
+ functions->insert(QLatin1String("error"), CF_MESSAGE); //v
+ }
+
+ bool cond = false;
+ bool ok = true;
+
+ ConditionFunc func_t = (ConditionFunc)functions->value(function);
+
+ switch (func_t) {
+ case CF_CONFIG: {
+ if (args.count() < 1 || args.count() > 2) {
+ q->logMessage(format("CONFIG(config) requires one or two arguments."));
+ ok = false;
+ break;
+ }
+ if (args.count() == 1) {
+ //cond = isActiveConfig(args.first()); XXX
+ break;
+ }
+ const QStringList mutuals = args[1].split(QLatin1Char('|'));
+ const QStringList &configs = valuesDirect(QLatin1String("CONFIG"));
+ for (int i = configs.size() - 1 && ok; i >= 0; i--) {
+ for (int mut = 0; mut < mutuals.count(); mut++) {
+ if (configs[i] == mutuals[mut].trimmed()) {
+ cond = (configs[i] == args[0]);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case CF_CONTAINS: {
+ if (args.count() < 2 || args.count() > 3) {
+ q->logMessage(format("contains(var, val) requires two or three arguments."));
+ ok = false;
+ break;
+ }
+
+ QRegExp regx(args[1]);
+ const QStringList &l = values(args.first());
+ if (args.count() == 2) {
+ for (int i = 0; i < l.size(); ++i) {
+ const QString val = l[i];
+ if (regx.exactMatch(val) || val == args[1]) {
+ cond = true;
+ break;
+ }
+ }
+ } else {
+ const QStringList mutuals = args[2].split(QLatin1Char('|'));
+ for (int i = l.size() - 1; i >= 0; i--) {
+ const QString val = l[i];
+ for (int mut = 0; mut < mutuals.count(); mut++) {
+ if (val == mutuals[mut].trimmed()) {
+ cond = (regx.exactMatch(val) || val == args[1]);
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case CF_COUNT: {
+ if (args.count() != 2 && args.count() != 3) {
+ q->logMessage(format("count(var, count) requires two or three arguments."));
+ ok = false;
+ break;
+ }
+ if (args.count() == 3) {
+ QString comp = args[2];
+ if (comp == QLatin1String(">") || comp == QLatin1String("greaterThan")) {
+ cond = values(args.first()).count() > args[1].toInt();
+ } else if (comp == QLatin1String(">=")) {
+ cond = values(args.first()).count() >= args[1].toInt();
+ } else if (comp == QLatin1String("<") || comp == QLatin1String("lessThan")) {
+ cond = values(args.first()).count() < args[1].toInt();
+ } else if (comp == QLatin1String("<=")) {
+ cond = values(args.first()).count() <= args[1].toInt();
+ } else if (comp == QLatin1String("equals") || comp == QLatin1String("isEqual") || comp == QLatin1String("=") || comp == QLatin1String("==")) {
+ cond = values(args.first()).count() == args[1].toInt();
+ } else {
+ ok = false;
+ q->logMessage(format("unexpected modifier to count(%2)").arg(comp));
+ }
+ break;
+ }
+ cond = values(args.first()).count() == args[1].toInt();
+ break;
+ }
+ case CF_INCLUDE: {
+ QString parseInto;
+ if (args.count() == 2) {
+ parseInto = args[1];
+ } else if (args.count() != 1) {
+ q->logMessage(format("include(file) requires one or two arguments."));
+ ok = false;
+ break;
+ }
+ QString fileName = args.first();
+ // ### this breaks if we have include(c:/reallystupid.pri) but IMHO that's really bad style.
+ QDir currentProPath(getcwd());
+ fileName = QDir::cleanPath(currentProPath.absoluteFilePath(fileName));
+ ok = evaluateFile(fileName, &ok);
+ break;
+ }
+ case CF_LOAD: {
+ QString parseInto;
+ bool ignore_error = false;
+ if (args.count() == 2) {
+ QString sarg = args[1];
+ ignore_error = (sarg.toLower() == QLatin1String("true") || sarg.toInt());
+ } else if (args.count() != 1) {
+ q->logMessage(format("load(feature) requires one or two arguments."));
+ ok = false;
+ break;
+ }
+ ok = evaluateFeatureFile( args.first(), &cond);
+ break;
+ }
+ case CF_MESSAGE: {
+ if (args.count() != 1) {
+ q->logMessage(format("%1(message) requires one argument.").arg(function));
+ ok = false;
+ break;
+ }
+ QString msg = args.first();
+ if (function == QLatin1String("error")) {
+ QStringList parents;
+ foreach (ProFile *proFile, m_profileStack)
+ parents.append(proFile->fileName());
+ if (!parents.isEmpty())
+ parents.takeLast();
+ if (parents.isEmpty())
+ q->fileMessage(format("Project ERROR: %1").arg(msg));
+ else
+ q->fileMessage(format("Project ERROR: %1. File was included from: '%2'")
+ .arg(msg).arg(parents.join(QLatin1String("', '"))));
+ } else {
+ q->fileMessage(format("Project MESSAGE: %1").arg(msg));
+ }
+ break;
+ }
+ case CF_SYSTEM: {
+ if (args.count() != 1) {
+ q->logMessage(format("system(exec) requires one argument."));
+ ok = false;
+ break;
+ }
+ ok = system(args.first().toLatin1().constData()) == 0;
+ break;
+ }
+ case CF_ISEMPTY: {
+ if (args.count() != 1) {
+ q->logMessage(format("isEmpty(var) requires one argument."));
+ ok = false;
+ break;
+ }
+ QStringList sl = values(args.first());
+ if (sl.count() == 0) {
+ cond = true;
+ } else if (sl.count() > 0) {
+ QString var = sl.first();
+ cond = (var.isEmpty());
+ }
+ break;
+ }
+ case CF_EXISTS: {
+ if (args.count() != 1) {
+ q->logMessage(format("exists(file) requires one argument."));
+ ok = false;
+ break;
+ }
+ QString file = args.first();
+
+ file = QDir::cleanPath(file);
+
+ if (QFile::exists(file)) {
+ cond = true;
+ break;
+ }
+ //regular expression I guess
+ QString dirstr = getcwd();
+ int slsh = file.lastIndexOf(Option::dir_sep);
+ if (slsh != -1) {
+ dirstr = file.left(slsh+1);
+ file = file.right(file.length() - slsh - 1);
+ }
+ cond = QDir(dirstr).entryList(QStringList(file)).count();
+
+ break;
+ }
+ }
+
+ if (result)
+ *result = cond;
+
+ return ok;
+}
+
+QStringList ProFileEvaluator::Private::values(const QString &variableName) const
+{
+ if (variableName == QLatin1String("TARGET")) {
+ QStringList list = m_valuemap.value(variableName);
+ if (!m_origfile.isEmpty())
+ list.append(QFileInfo(m_origfile).baseName());
+ return list;
+ }
+ if (variableName == QLatin1String("PWD")) {
+ return QStringList(getcwd());
+ }
+ return m_valuemap.value(variableName);
+}
+
+QStringList ProFileEvaluator::Private::values(const QString &variableName, const ProFile *pro) const
+{
+ if (variableName == QLatin1String("TARGET")) {
+ QStringList list = m_filevaluemap[pro].value(variableName);
+ if (!m_origfile.isEmpty())
+ list.append(QFileInfo(m_origfile).baseName());
+ return list;
+ }
+ if (variableName == QLatin1String("PWD")) {
+ return QStringList(QFileInfo(pro->fileName()).absoluteFilePath());
+ }
+ return m_filevaluemap[pro].value(variableName);
+}
+
+ProFile *ProFileEvaluator::parsedProFile(const QString &fileName)
+{
+ QFileInfo fi(fileName);
+ if (fi.exists()) {
+ ProFile *pro = new ProFile(fi.absoluteFilePath());
+ if (d->read(pro))
+ return pro;
+ delete pro;
+ }
+ return 0;
+}
+
+void ProFileEvaluator::releaseParsedProFile(ProFile *proFile)
+{
+ delete proFile;
+}
+
+bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *result)
+{
+ bool ok = true;
+ ProFile *pro = q->parsedProFile(fileName);
+ if (pro) {
+ m_profileStack.push(pro);
+ ok = (currentProFile() ? pro->Accept(this) : false);
+ m_profileStack.pop();
+ q->releaseParsedProFile(pro);
+
+ if (result)
+ *result = true;
+ } else {
+ if (result)
+ *result = false;
+ }
+/* if (ok && readFeatures) {
+ QStringList configs = values("CONFIG");
+ QSet<QString> processed;
+ foreach (const QString &fn, configs) {
+ if (!processed.contains(fn)) {
+ processed.insert(fn);
+ evaluateFeatureFile(fn, 0);
+ }
+ }
+ } */
+
+ return ok;
+}
+
+bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, bool *result)
+{
+ QString fn;
+ foreach (const QString &path, qmakeFeaturePaths()) {
+ QString fname = path + QLatin1Char('/') + fileName;
+ if (QFileInfo(fname).exists()) {
+ fn = fname;
+ break;
+ }
+ fname += QLatin1String(".prf");
+ if (QFileInfo(fname).exists()) {
+ fn = fname;
+ break;
+ }
+ }
+ return fn.isEmpty() ? false : evaluateFile(fn, result);
+}
+
+void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName,
+ QStringList &sources_out)
+{
+ const QStringList vpaths = values(QLatin1String("VPATH"))
+ + values(QLatin1String("QMAKE_ABSOLUTE_SOURCE_PATH"))
+ + values(QLatin1String("DEPENDPATH"))
+ + values(QLatin1String("VPATH_SOURCES"));
+
+ QFileInfo fi(absName);
+ bool found = fi.exists();
+ // Search in all vpaths
+ if (!found) {
+ foreach (const QString &vpath, vpaths) {
+ fi.setFile(vpath + QDir::separator() + relName);
+ if (fi.exists()) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ sources_out += fi.absoluteFilePath(); // Not resolving symlinks
+ } else {
+ QString val = relName;
+ QString dir;
+ QString wildcard = val;
+ QString real_dir;
+ if (wildcard.lastIndexOf(QLatin1Char('/')) != -1) {
+ dir = wildcard.left(wildcard.lastIndexOf(QLatin1Char('/')) + 1);
+ real_dir = dir;
+ wildcard = wildcard.right(wildcard.length() - dir.length());
+ }
+
+ if (real_dir.isEmpty() || QFileInfo(real_dir).exists()) {
+ QStringList files = QDir(real_dir).entryList(QStringList(wildcard));
+ if (files.isEmpty()) {
+ q->logMessage(format("Failure to find %1").arg(val));
+ } else {
+ QString a;
+ for (int i = files.count() - 1; i >= 0; --i) {
+ if (files[i] == QLatin1String(".") || files[i] == QLatin1String(".."))
+ continue;
+ a = dir + files[i];
+ sources_out += a;
+ }
+ }
+ } else {
+ q->logMessage(format("Cannot match %1/%2, as %3 does not exist.")
+ .arg(real_dir).arg(wildcard).arg(real_dir));
+ }
+ }
+}
+
+
+/*
+ * Lookup of files are done in this order:
+ * 1. look in pwd
+ * 2. look in vpaths
+ * 3. expand wild card files relative from the profiles folder
+ **/
+
+// FIXME: This code supports something that I'd consider a flaw in .pro file syntax
+// which is not even documented. So arguably this can be ditched completely...
+QStringList ProFileEvaluator::Private::expandPattern(const QString& pattern)
+{
+ if (!currentProFile())
+ return QStringList();
+
+ QStringList sources_out;
+ const QString absName = QDir::cleanPath(QDir::current().absoluteFilePath(pattern));
+
+ expandPatternHelper(pattern, absName, sources_out);
+ return sources_out;
+}
+
+QString ProFileEvaluator::Private::format(const char *fmt) const
+{
+ ProFile *pro = currentProFile();
+ QString fileName = pro ? pro->fileName() : QLatin1String("Not a file");
+ int lineNumber = pro ? m_lineNo : 0;
+ return QString::fromLatin1("%1(%2):").arg(fileName).arg(lineNumber) + QString::fromAscii(fmt);
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// ProFileEvaluator
+//
+///////////////////////////////////////////////////////////////////////
+
+ProFileEvaluator::ProFileEvaluator()
+ : d(new Private(this))
+{
+ Option::init();
+}
+
+ProFileEvaluator::~ProFileEvaluator()
+{
+ delete d;
+}
+
+bool ProFileEvaluator::contains(const QString &variableName) const
+{
+ return d->m_valuemap.contains(variableName);
+}
+
+QStringList ProFileEvaluator::values(const QString &variableName) const
+{
+ return d->values(variableName);
+}
+
+QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const
+{
+ return d->values(variableName, pro);
+}
+
+ProFileEvaluator::TemplateType ProFileEvaluator::templateType()
+{
+ QStringList templ = values(QLatin1String("TEMPLATE"));
+ if (templ.count() >= 1) {
+ QString t = templ.last().toLower();
+ if (t == QLatin1String("app"))
+ return TT_Application;
+ if (t == QLatin1String("lib"))
+ return TT_Library;
+ if (t == QLatin1String("subdirs"))
+ return TT_Subdirs;
+ }
+ return TT_Unknown;
+}
+
+bool ProFileEvaluator::queryProFile(ProFile *pro)
+{
+ return d->read(pro);
+}
+
+bool ProFileEvaluator::accept(ProFile *pro)
+{
+ return pro->Accept(d);
+}
+
+QString ProFileEvaluator::propertyValue(const QString &name) const
+{
+ return d->propertyValue(name);
+}
+
+namespace {
+ template<class K, class T> void insert(QHash<K,T> *out, const QHash<K,T> &in)
+ {
+ typename QHash<K,T>::const_iterator i = in.begin();
+ while (i != in.end()) {
+ out->insert(i.key(), i.value());
+ ++i;
+ }
+ }
+} // anon namespace
+
+void ProFileEvaluator::addVariables(const QHash<QString, QStringList> &variables)
+{
+ insert(&(d->m_valuemap), variables);
+}
+
+void ProFileEvaluator::addProperties(const QHash<QString, QString> &properties)
+{
+ insert(&(d->m_properties), properties);
+}
+
+void ProFileEvaluator::logMessage(const QString &message)
+{
+ if (d->m_verbose)
+ qWarning("%s", qPrintable(message));
+}
+
+void ProFileEvaluator::fileMessage(const QString &message)
+{
+ qWarning("%s", qPrintable(message));
+}
+
+void ProFileEvaluator::errorMessage(const QString &message)
+{
+ qWarning("%s", qPrintable(message));
+}
+
+void ProFileEvaluator::setVerbose(bool on)
+{
+ d->m_verbose = on;
+}
+
+void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap)
+{
+ QStringList sourceFiles;
+ QString codecForTr;
+ QString codecForSource;
+ QStringList tsFileNames;
+
+ // app/lib template
+ sourceFiles += visitor.values(QLatin1String("SOURCES"));
+ sourceFiles += visitor.values(QLatin1String("HEADERS"));
+ tsFileNames = visitor.values(QLatin1String("TRANSLATIONS"));
+
+ QStringList trcodec = visitor.values(QLatin1String("CODEC"))
+ + visitor.values(QLatin1String("DEFAULTCODEC"))
+ + visitor.values(QLatin1String("CODECFORTR"));
+ if (!trcodec.isEmpty())
+ codecForTr = trcodec.last();
+
+ QStringList srccodec = visitor.values(QLatin1String("CODECFORSRC"));
+ if (!srccodec.isEmpty())
+ codecForSource = srccodec.last();
+
+ QStringList forms = visitor.values(QLatin1String("INTERFACES"))
+ + visitor.values(QLatin1String("FORMS"))
+ + visitor.values(QLatin1String("FORMS3"));
+ sourceFiles << forms;
+
+ sourceFiles.sort();
+ sourceFiles.removeDuplicates();
+ tsFileNames.sort();
+ tsFileNames.removeDuplicates();
+
+ varMap->insert("SOURCES", sourceFiles);
+ varMap->insert("CODECFORTR", QStringList() << codecForTr);
+ varMap->insert("CODECFORSRC", QStringList() << codecForSource);
+ varMap->insert("TRANSLATIONS", tsFileNames);
+}
+
+bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap)
+{
+ QFileInfo fi(fileName);
+ if (!fi.exists())
+ return false;
+
+ ProFile pro(fi.absoluteFilePath());
+
+ ProFileEvaluator visitor;
+ visitor.setVerbose(verbose);
+
+ if (!visitor.queryProFile(&pro))
+ return false;
+
+ if (!visitor.accept(&pro))
+ return false;
+
+ evaluateProFile(visitor, varMap);
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/profileevaluator.h b/tools/linguist/shared/profileevaluator.h
new file mode 100644
index 0000000000..beb16ea537
--- /dev/null
+++ b/tools/linguist/shared/profileevaluator.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROFILEEVALUATOR_H
+#define PROFILEEVALUATOR_H
+
+#include "proitems.h"
+#include "abstractproitemvisitor.h"
+
+#include <QtCore/QIODevice>
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
+#include <QtCore/QStack>
+
+QT_BEGIN_NAMESPACE
+
+class ProFile;
+class ProFileEvaluator;
+
+void evaluateProFile(const ProFileEvaluator &visitor, QHash<QByteArray, QStringList> *varMap);
+bool evaluateProFile(const QString &fileName, bool verbose, QHash<QByteArray, QStringList> *varMap);
+
+class ProFileEvaluator
+{
+public:
+ enum TemplateType {
+ TT_Unknown = 0,
+ TT_Application,
+ TT_Library,
+ TT_Subdirs
+ };
+
+ ProFileEvaluator();
+ virtual ~ProFileEvaluator();
+
+ ProFileEvaluator::TemplateType templateType();
+ virtual bool contains(const QString &variableName) const;
+ void setVerbose(bool on);
+
+ bool queryProFile(ProFile *pro);
+ bool accept(ProFile *pro);
+
+ void addVariables(const QHash<QString, QStringList> &variables);
+ void addProperties(const QHash<QString, QString> &properties);
+ QStringList values(const QString &variableName) const;
+ QStringList values(const QString &variableName, const ProFile *pro) const;
+ QString propertyValue(const QString &val) const;
+
+ // for our descendents
+ virtual ProFile *parsedProFile(const QString &fileName);
+ virtual void releaseParsedProFile(ProFile *proFile);
+ virtual void logMessage(const QString &msg);
+ virtual void errorMessage(const QString &msg); // .pro parse errors
+ virtual void fileMessage(const QString &msg); // error() and message() from .pro file
+
+private:
+ class Private;
+ Private *d;
+};
+
+QT_END_NAMESPACE
+
+#endif // PROFILEEVALUATOR_H
diff --git a/tools/linguist/shared/proitems.cpp b/tools/linguist/shared/proitems.cpp
new file mode 100644
index 0000000000..1895852838
--- /dev/null
+++ b/tools/linguist/shared/proitems.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "proitems.h"
+#include "abstractproitemvisitor.h"
+
+#include <QtCore/QFileInfo>
+
+QT_BEGIN_NAMESPACE
+
+// --------------- ProItem ------------
+void ProItem::setComment(const QString &comment)
+{
+ m_comment = comment;
+}
+
+QString ProItem::comment() const
+{
+ return m_comment;
+}
+
+// --------------- ProBlock ----------------
+ProBlock::ProBlock(ProBlock *parent)
+{
+ m_blockKind = 0;
+ m_parent = parent;
+}
+
+ProBlock::~ProBlock()
+{
+ qDeleteAll(m_proitems);
+}
+
+void ProBlock::appendItem(ProItem *proitem)
+{
+ m_proitems << proitem;
+}
+
+void ProBlock::setItems(const QList<ProItem *> &proitems)
+{
+ m_proitems = proitems;
+}
+
+QList<ProItem *> ProBlock::items() const
+{
+ return m_proitems;
+}
+
+void ProBlock::setBlockKind(int blockKind)
+{
+ m_blockKind = blockKind;
+}
+
+int ProBlock::blockKind() const
+{
+ return m_blockKind;
+}
+
+void ProBlock::setParent(ProBlock *parent)
+{
+ m_parent = parent;
+}
+
+ProBlock *ProBlock::parent() const
+{
+ return m_parent;
+}
+
+ProItem::ProItemKind ProBlock::kind() const
+{
+ return ProItem::BlockKind;
+}
+
+bool ProBlock::Accept(AbstractProItemVisitor *visitor)
+{
+ visitor->visitBeginProBlock(this);
+ foreach (ProItem *item, m_proitems) {
+ if (!item->Accept(visitor))
+ return false;
+ }
+ return visitor->visitEndProBlock(this);
+}
+
+// --------------- ProVariable ----------------
+ProVariable::ProVariable(const QString &name, ProBlock *parent)
+ : ProBlock(parent)
+{
+ setBlockKind(ProBlock::VariableKind);
+ m_variable = name;
+ m_variableKind = SetOperator;
+}
+
+void ProVariable::setVariableOperator(VariableOperator variableKind)
+{
+ m_variableKind = variableKind;
+}
+
+ProVariable::VariableOperator ProVariable::variableOperator() const
+{
+ return m_variableKind;
+}
+
+void ProVariable::setVariable(const QString &name)
+{
+ m_variable = name;
+}
+
+QString ProVariable::variable() const
+{
+ return m_variable;
+}
+
+bool ProVariable::Accept(AbstractProItemVisitor *visitor)
+{
+ visitor->visitBeginProVariable(this);
+ foreach (ProItem *item, m_proitems) {
+ if (!item->Accept(visitor))
+ return false;
+ }
+ return visitor->visitEndProVariable(this);
+}
+
+// --------------- ProValue ----------------
+ProValue::ProValue(const QString &value, ProVariable *variable)
+{
+ m_variable = variable;
+ m_value = value;
+}
+
+void ProValue::setValue(const QString &value)
+{
+ m_value = value;
+}
+
+QString ProValue::value() const
+{
+ return m_value;
+}
+
+void ProValue::setVariable(ProVariable *variable)
+{
+ m_variable = variable;
+}
+
+ProVariable *ProValue::variable() const
+{
+ return m_variable;
+}
+
+ProItem::ProItemKind ProValue::kind() const
+{
+ return ProItem::ValueKind;
+}
+
+bool ProValue::Accept(AbstractProItemVisitor *visitor)
+{
+ return visitor->visitProValue(this);
+}
+
+// --------------- ProFunction ----------------
+ProFunction::ProFunction(const QString &text)
+{
+ m_text = text;
+}
+
+void ProFunction::setText(const QString &text)
+{
+ m_text = text;
+}
+
+QString ProFunction::text() const
+{
+ return m_text;
+}
+
+ProItem::ProItemKind ProFunction::kind() const
+{
+ return ProItem::FunctionKind;
+}
+
+bool ProFunction::Accept(AbstractProItemVisitor *visitor)
+{
+ return visitor->visitProFunction(this);
+}
+
+// --------------- ProCondition ----------------
+ProCondition::ProCondition(const QString &text)
+{
+ m_text = text;
+}
+
+void ProCondition::setText(const QString &text)
+{
+ m_text = text;
+}
+
+QString ProCondition::text() const
+{
+ return m_text;
+}
+
+ProItem::ProItemKind ProCondition::kind() const
+{
+ return ProItem::ConditionKind;
+}
+
+bool ProCondition::Accept(AbstractProItemVisitor *visitor)
+{
+ return visitor->visitProCondition(this);
+}
+
+// --------------- ProOperator ----------------
+ProOperator::ProOperator(OperatorKind operatorKind)
+{
+ m_operatorKind = operatorKind;
+}
+
+void ProOperator::setOperatorKind(OperatorKind operatorKind)
+{
+ m_operatorKind = operatorKind;
+}
+
+ProOperator::OperatorKind ProOperator::operatorKind() const
+{
+ return m_operatorKind;
+}
+
+ProItem::ProItemKind ProOperator::kind() const
+{
+ return ProItem::OperatorKind;
+}
+
+bool ProOperator::Accept(AbstractProItemVisitor *visitor)
+{
+ return visitor->visitProOperator(this);
+}
+
+// --------------- ProFile ----------------
+ProFile::ProFile(const QString &fileName)
+ : ProBlock(0)
+{
+ m_modified = false;
+ setBlockKind(ProBlock::ProFileKind);
+ m_fileName = fileName;
+
+ QFileInfo fi(fileName);
+ m_displayFileName = fi.fileName();
+ m_directoryName = fi.absolutePath();
+}
+
+ProFile::~ProFile()
+{
+}
+
+QString ProFile::displayFileName() const
+{
+ return m_displayFileName;
+}
+
+QString ProFile::fileName() const
+{
+ return m_fileName;
+}
+
+QString ProFile::directoryName() const
+{
+ return m_directoryName;
+}
+
+void ProFile::setModified(bool modified)
+{
+ m_modified = modified;
+}
+
+bool ProFile::isModified() const
+{
+ return m_modified;
+}
+
+bool ProFile::Accept(AbstractProItemVisitor *visitor)
+{
+ visitor->visitBeginProFile(this);
+ foreach (ProItem *item, m_proitems) {
+ if (!item->Accept(visitor))
+ return false;
+ }
+ return visitor->visitEndProFile(this);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/proitems.h b/tools/linguist/shared/proitems.h
new file mode 100644
index 0000000000..befaa8857c
--- /dev/null
+++ b/tools/linguist/shared/proitems.h
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROITEMS_H
+#define PROITEMS_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+QT_BEGIN_NAMESPACE
+
+struct AbstractProItemVisitor;
+
+class ProItem
+{
+public:
+ enum ProItemKind {
+ ValueKind,
+ FunctionKind,
+ ConditionKind,
+ OperatorKind,
+ BlockKind
+ };
+
+ ProItem() : m_lineNumber(0) {}
+ virtual ~ProItem() {}
+
+ virtual ProItemKind kind() const = 0;
+
+ void setComment(const QString &comment);
+ QString comment() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor) = 0;
+ int lineNumber() const { return m_lineNumber; }
+ void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; }
+
+private:
+ QString m_comment;
+ int m_lineNumber;
+};
+
+class ProBlock : public ProItem
+{
+public:
+ enum ProBlockKind {
+ NormalKind = 0x00,
+ ScopeKind = 0x01,
+ ScopeContentsKind = 0x02,
+ VariableKind = 0x04,
+ ProFileKind = 0x08,
+ SingleLine = 0x10
+ };
+
+ ProBlock(ProBlock *parent);
+ ~ProBlock();
+
+ void appendItem(ProItem *proitem);
+ void setItems(const QList<ProItem *> &proitems);
+ QList<ProItem *> items() const;
+
+ void setBlockKind(int blockKind);
+ int blockKind() const;
+
+ void setParent(ProBlock *parent);
+ ProBlock *parent() const;
+
+ ProItem::ProItemKind kind() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor);
+protected:
+ QList<ProItem *> m_proitems;
+private:
+ ProBlock *m_parent;
+ int m_blockKind;
+};
+
+class ProVariable : public ProBlock
+{
+public:
+ enum VariableOperator {
+ AddOperator = 0,
+ RemoveOperator = 1,
+ ReplaceOperator = 2,
+ SetOperator = 3,
+ UniqueAddOperator = 4
+ };
+
+ ProVariable(const QString &name, ProBlock *parent);
+
+ void setVariableOperator(VariableOperator variableKind);
+ VariableOperator variableOperator() const;
+
+ void setVariable(const QString &name);
+ QString variable() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor);
+private:
+ VariableOperator m_variableKind;
+ QString m_variable;
+};
+
+class ProValue : public ProItem
+{
+public:
+ ProValue(const QString &value, ProVariable *variable);
+
+ void setValue(const QString &value);
+ QString value() const;
+
+ void setVariable(ProVariable *variable);
+ ProVariable *variable() const;
+
+ ProItem::ProItemKind kind() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor);
+private:
+ QString m_value;
+ ProVariable *m_variable;
+};
+
+class ProFunction : public ProItem
+{
+public:
+ explicit ProFunction(const QString &text);
+
+ void setText(const QString &text);
+ QString text() const;
+
+ ProItem::ProItemKind kind() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor);
+private:
+ QString m_text;
+};
+
+class ProCondition : public ProItem
+{
+public:
+ explicit ProCondition(const QString &text);
+
+ void setText(const QString &text);
+ QString text() const;
+
+ ProItem::ProItemKind kind() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor);
+private:
+ QString m_text;
+};
+
+class ProOperator : public ProItem
+{
+public:
+ enum OperatorKind {
+ OrOperator = 1,
+ NotOperator = 2
+ };
+
+ explicit ProOperator(OperatorKind operatorKind);
+
+ void setOperatorKind(OperatorKind operatorKind);
+ OperatorKind operatorKind() const;
+
+ ProItem::ProItemKind kind() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor);
+private:
+ OperatorKind m_operatorKind;
+};
+
+class ProFile : public QObject, public ProBlock
+{
+ Q_OBJECT
+
+public:
+ explicit ProFile(const QString &fileName);
+ ~ProFile();
+
+ QString displayFileName() const;
+ QString fileName() const;
+ QString directoryName() const;
+
+ void setModified(bool modified);
+ bool isModified() const;
+
+ virtual bool Accept(AbstractProItemVisitor *visitor);
+
+private:
+ QString m_fileName;
+ QString m_displayFileName;
+ QString m_directoryName;
+ bool m_modified;
+};
+
+QT_END_NAMESPACE
+
+#endif // PROITEMS_H
diff --git a/tools/linguist/shared/proparser.pri b/tools/linguist/shared/proparser.pri
new file mode 100644
index 0000000000..372247e46c
--- /dev/null
+++ b/tools/linguist/shared/proparser.pri
@@ -0,0 +1,12 @@
+
+INCLUDEPATH *= $$PWD
+
+HEADERS += \
+ $$PWD/abstractproitemvisitor.h \
+ $$PWD/proitems.h \
+ $$PWD/profileevaluator.h \
+ $$PWD/proparserutils.h
+
+SOURCES += \
+ $$PWD/proitems.cpp \
+ $$PWD/profileevaluator.cpp
diff --git a/tools/linguist/shared/proparserutils.h b/tools/linguist/shared/proparserutils.h
new file mode 100644
index 0000000000..8914a8ed9d
--- /dev/null
+++ b/tools/linguist/shared/proparserutils.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROPARSERUTILS_H
+#define PROPARSERUTILS_H
+
+#include <QtCore/QDir>
+#include <QtCore/QLibraryInfo>
+
+QT_BEGIN_NAMESPACE
+
+// Pre- and postcondition macros
+#define PRE(cond) do {if (!(cond))qt_assert(#cond,__FILE__,__LINE__);} while (0)
+#define POST(cond) do {if (!(cond))qt_assert(#cond,__FILE__,__LINE__);} while (0)
+
+// This struct is from qmake, but we are not using everything.
+struct Option
+{
+ //simply global convenience
+ //static QString libtool_ext;
+ //static QString pkgcfg_ext;
+ //static QString prf_ext;
+ //static QString prl_ext;
+ //static QString ui_ext;
+ //static QStringList h_ext;
+ //static QStringList cpp_ext;
+ //static QString h_moc_ext;
+ //static QString cpp_moc_ext;
+ //static QString obj_ext;
+ //static QString lex_ext;
+ //static QString yacc_ext;
+ //static QString h_moc_mod;
+ //static QString cpp_moc_mod;
+ //static QString lex_mod;
+ //static QString yacc_mod;
+ static QString dir_sep;
+ static QString dirlist_sep;
+ static QString qmakespec;
+ static QChar field_sep;
+
+ enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE };
+ static TARG_MODE target_mode;
+ //static QString pro_ext;
+ //static QString res_ext;
+
+ static void init()
+ {
+#ifdef Q_OS_WIN
+ Option::dirlist_sep = QLatin1Char(';');
+ Option::dir_sep = QLatin1Char('\\');
+#else
+ Option::dirlist_sep = QLatin1Char(':');
+ Option::dir_sep = QLatin1Char(QLatin1Char('/'));
+#endif
+ Option::qmakespec = QString::fromLatin1(qgetenv("QMAKESPEC").data());
+ Option::field_sep = QLatin1Char(' ');
+ }
+};
+#if defined(Q_OS_WIN32)
+Option::TARG_MODE Option::target_mode = Option::TARG_WIN_MODE;
+#elif defined(Q_OS_MAC)
+Option::TARG_MODE Option::target_mode = Option::TARG_MACX_MODE;
+#elif defined(Q_OS_QNX6)
+Option::TARG_MODE Option::target_mode = Option::TARG_QNX6_MODE;
+#else
+Option::TARG_MODE Option::target_mode = Option::TARG_UNIX_MODE;
+#endif
+
+QString Option::qmakespec;
+QString Option::dirlist_sep;
+QString Option::dir_sep;
+QChar Option::field_sep;
+
+static void insertUnique(QHash<QString, QStringList> *map,
+ const QString &key, const QStringList &value, bool unique = true)
+{
+ QStringList &sl = (*map)[key];
+ if (!unique) {
+ sl += value;
+ } else {
+ for (int i = 0; i < value.count(); ++i) {
+ if (!sl.contains(value.at(i)))
+ sl.append(value.at(i));
+ }
+ }
+}
+
+/*
+ See ProFileEvaluator::Private::visitProValue(...)
+
+static QStringList replaceInList(const QStringList &varList, const QRegExp &regexp,
+ const QString &replace, bool global)
+{
+ QStringList resultList = varList;
+
+ for (QStringList::Iterator varit = resultList.begin(); varit != resultList.end();) {
+ if (varit->contains(regexp)) {
+ *varit = varit->replace(regexp, replace);
+ if (varit->isEmpty())
+ varit = resultList.erase(varit);
+ else
+ ++varit;
+ if (!global)
+ break;
+ } else {
+ ++varit;
+ }
+ }
+ return resultList;
+}
+*/
+
+inline QStringList splitPathList(const QString paths)
+{
+ return paths.split(Option::dirlist_sep);
+}
+
+static QStringList split_arg_list(QString params)
+{
+ int quote = 0;
+ QStringList args;
+
+ const ushort LPAREN = '(';
+ const ushort RPAREN = ')';
+ const ushort SINGLEQUOTE = '\'';
+ const ushort DOUBLEQUOTE = '"';
+ const ushort COMMA = ',';
+ const ushort SPACE = ' ';
+ //const ushort TAB = '\t';
+
+ ushort unicode;
+ const QChar *params_data = params.data();
+ const int params_len = params.length();
+ int last = 0;
+ while (last < params_len && ((params_data+last)->unicode() == SPACE
+ /*|| (params_data+last)->unicode() == TAB*/))
+ ++last;
+ for (int x = last, parens = 0; x <= params_len; x++) {
+ unicode = (params_data+x)->unicode();
+ if (x == params_len) {
+ while (x && (params_data+(x-1))->unicode() == SPACE)
+ --x;
+ QString mid(params_data+last, x-last);
+ if (quote) {
+ if (mid[0] == quote && mid[(int)mid.length()-1] == quote)
+ mid = mid.mid(1, mid.length()-2);
+ quote = 0;
+ }
+ args << mid;
+ break;
+ }
+ if (unicode == LPAREN) {
+ --parens;
+ } else if (unicode == RPAREN) {
+ ++parens;
+ } else if (quote && unicode == quote) {
+ quote = 0;
+ } else if (!quote && (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE)) {
+ quote = unicode;
+ }
+ if (!parens && !quote && unicode == COMMA) {
+ QString mid = params.mid(last, x - last).trimmed();
+ args << mid;
+ last = x+1;
+ while (last < params_len && ((params_data+last)->unicode() == SPACE
+ /*|| (params_data+last)->unicode() == TAB*/))
+ ++last;
+ }
+ }
+ return args;
+}
+
+static QStringList split_value_list(const QString &vals, bool do_semicolon=false)
+{
+ QString build;
+ QStringList ret;
+ QStack<char> quote;
+
+ const ushort LPAREN = '(';
+ const ushort RPAREN = ')';
+ const ushort SINGLEQUOTE = '\'';
+ const ushort DOUBLEQUOTE = '"';
+ const ushort BACKSLASH = '\\';
+ const ushort SEMICOLON = ';';
+
+ ushort unicode;
+ const QChar *vals_data = vals.data();
+ const int vals_len = vals.length();
+ for (int x = 0, parens = 0; x < vals_len; x++) {
+ unicode = vals_data[x].unicode();
+ if (x != (int)vals_len-1 && unicode == BACKSLASH &&
+ (vals_data[x+1].unicode() == SINGLEQUOTE || vals_data[x+1].unicode() == DOUBLEQUOTE)) {
+ build += vals_data[x++]; //get that 'escape'
+ } else if (!quote.isEmpty() && unicode == quote.top()) {
+ quote.pop();
+ } else if (unicode == SINGLEQUOTE || unicode == DOUBLEQUOTE) {
+ quote.push(unicode);
+ } else if (unicode == RPAREN) {
+ --parens;
+ } else if (unicode == LPAREN) {
+ ++parens;
+ }
+
+ if (!parens && quote.isEmpty() && ((do_semicolon && unicode == SEMICOLON) ||
+ vals_data[x] == Option::field_sep)) {
+ ret << build;
+ build.clear();
+ } else {
+ build += vals_data[x];
+ }
+ }
+ if (!build.isEmpty())
+ ret << build;
+ return ret;
+}
+
+static QStringList qmake_mkspec_paths()
+{
+ QStringList ret;
+ const QString concat = QDir::separator() + QString(QLatin1String("mkspecs"));
+ QByteArray qmakepath = qgetenv("QMAKEPATH");
+ if (!qmakepath.isEmpty()) {
+ const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath));
+ for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it)
+ ret << ((*it) + concat);
+ }
+ ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat;
+
+ return ret;
+}
+
+QT_END_NAMESPACE
+
+#endif // PROPARSERUTILS_H
diff --git a/tools/linguist/shared/qm.cpp b/tools/linguist/shared/qm.cpp
new file mode 100644
index 0000000000..c197e2b1f2
--- /dev/null
+++ b/tools/linguist/shared/qm.cpp
@@ -0,0 +1,717 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QTextCodec>
+
+QT_BEGIN_NAMESPACE
+
+// magic number for the file
+static const int MagicLength = 16;
+static const uchar magic[MagicLength] = {
+ 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
+ 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
+};
+
+
+namespace {
+
+enum Tag {
+ Tag_End = 1,
+ Tag_SourceText16 = 2,
+ Tag_Translation = 3,
+ Tag_Context16 = 4,
+ Tag_Obsolete1 = 5,
+ Tag_SourceText = 6,
+ Tag_Context = 7,
+ Tag_Comment = 8,
+ Tag_Obsolete2 = 9
+};
+
+enum Prefix {
+ NoPrefix,
+ Hash,
+ HashContext,
+ HashContextSourceText,
+ HashContextSourceTextComment
+};
+
+} // namespace anon
+
+static uint elfHash(const QByteArray &ba)
+{
+ const uchar *k = (const uchar *)ba.data();
+ uint h = 0;
+ uint g;
+
+ if (k) {
+ while (*k) {
+ h = (h << 4) + *k++;
+ if ((g = (h & 0xf0000000)) != 0)
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ }
+ if (!h)
+ h = 1;
+ return h;
+}
+
+class Releaser
+{
+public:
+ struct Offset {
+ Offset()
+ : h(0), o(0)
+ {}
+ Offset(uint hash, uint offset)
+ : h(hash), o(offset)
+ {}
+
+ bool operator<(const Offset &other) const {
+ return (h != other.h) ? h < other.h : o < other.o;
+ }
+ bool operator==(const Offset &other) const {
+ return h == other.h && o == other.o;
+ }
+ uint h;
+ uint o;
+ };
+
+ enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88 };
+
+ Releaser() : m_codec(0) {}
+
+ void setCodecName(const QByteArray &codecName)
+ {
+ m_codec = QTextCodec::codecForName(codecName);
+ }
+
+ TranslatorMessage findMessage(const QString &context,
+ const QString &sourceText, const QString &comment,
+ const QString &fileName = QString(), int lineNumber = -1) const;
+
+ bool save(QIODevice *iod);
+
+ void insert(const TranslatorMessage &);
+ void remove(const TranslatorMessage &);
+
+ bool contains(const QString &context, const QString &sourceText,
+ const QString & comment) const;
+
+ bool contains(const QString &context, const QString &comment,
+ const QString &fileName, int lineNumber) const;
+
+ void squeeze(TranslatorSaveMode mode);
+
+ QList<TranslatorMessage> messages() const;
+
+ bool isEmpty() const;
+
+ void setNumerusRules(const QByteArray &rules);
+
+private:
+ Q_DISABLE_COPY(Releaser)
+
+ // This should reproduce the byte array fetched from the source file, which
+ // on turn should be the same as passed to the actual tr(...) calls
+ QByteArray originalBytes(const QString &str, bool isUtf8) const;
+
+ Prefix commonPrefix(const TranslatorMessage &m1, const TranslatorMessage &m2) const;
+
+ uint msgHash(const TranslatorMessage &msg) const;
+
+ void writeMessage(const TranslatorMessage & msg, QDataStream & stream,
+ TranslatorSaveMode strip, Prefix prefix) const;
+
+ // for squeezed but non-file data, this is what needs to be deleted
+ QByteArray m_messageArray;
+ QByteArray m_offsetArray;
+ QByteArray m_contextArray;
+ QMap<TranslatorMessage, void *> m_messages;
+ QByteArray m_numerusRules;
+
+ // Used to reproduce the original bytes
+ QTextCodec *m_codec;
+};
+
+QByteArray Releaser::originalBytes(const QString &str, bool isUtf8) const
+{
+ if (str.isEmpty()) {
+ // Do not use QByteArray() here as the result of the serialization
+ // will be different.
+ return QByteArray("");
+ }
+ if (isUtf8)
+ return str.toUtf8();
+ return m_codec ? m_codec->fromUnicode(str) : str.toLatin1();
+}
+
+uint Releaser::msgHash(const TranslatorMessage &msg) const
+{
+ return elfHash(originalBytes(msg.sourceText() + msg.comment(), msg.isUtf8()));
+}
+
+Prefix Releaser::commonPrefix(const TranslatorMessage &m1, const TranslatorMessage &m2) const
+{
+ if (msgHash(m1) != msgHash(m2))
+ return NoPrefix;
+ if (m1.context() != m2.context())
+ return Hash;
+ if (m1.sourceText() != m2.sourceText())
+ return HashContext;
+ if (m1.comment() != m2.comment())
+ return HashContextSourceText;
+ return HashContextSourceTextComment;
+}
+
+void Releaser::writeMessage(const TranslatorMessage & msg, QDataStream & stream,
+ TranslatorSaveMode mode, Prefix prefix) const
+{
+ for (int i = 0; i < msg.translations().count(); ++i) {
+ QString str = msg.translations().at(i);
+ str.replace(QChar(Translator::DefaultVariantSeparator),
+ QChar(Translator::InternalVariantSeparator));
+ stream << quint8(Tag_Translation) << str;
+ }
+
+ if (mode == SaveEverything)
+ prefix = HashContextSourceTextComment;
+
+ // lrelease produces "wrong" .qm files for QByteArrays that are .isNull().
+ switch (prefix) {
+ default:
+ case HashContextSourceTextComment:
+ stream << quint8(Tag_Comment) << originalBytes(msg.comment(), msg.isUtf8());
+ // fall through
+ case HashContextSourceText:
+ stream << quint8(Tag_SourceText) << originalBytes(msg.sourceText(), msg.isUtf8());
+ // fall through
+ case HashContext:
+ stream << quint8(Tag_Context) << originalBytes(msg.context(), msg.isUtf8());
+ ;
+ }
+
+ stream << quint8(Tag_End);
+}
+
+
+bool Releaser::save(QIODevice *iod)
+{
+ QDataStream s(iod);
+ s.writeRawData((const char *)magic, MagicLength);
+
+ if (!m_offsetArray.isEmpty()) {
+ quint32 oas = quint32(m_offsetArray.size());
+ s << quint8(Hashes) << oas;
+ s.writeRawData(m_offsetArray.constData(), oas);
+ }
+ if (!m_messageArray.isEmpty()) {
+ quint32 mas = quint32(m_messageArray.size());
+ s << quint8(Messages) << mas;
+ s.writeRawData(m_messageArray.constData(), mas);
+ }
+ if (!m_contextArray.isEmpty()) {
+ quint32 cas = quint32(m_contextArray.size());
+ s << quint8(Contexts) << cas;
+ s.writeRawData(m_contextArray.constData(), cas);
+ }
+ if (!m_numerusRules.isEmpty()) {
+ quint32 nrs = m_numerusRules.size();
+ s << quint8(NumerusRules) << nrs;
+ s.writeRawData(m_numerusRules.constData(), nrs);
+ }
+ return true;
+}
+
+void Releaser::squeeze(TranslatorSaveMode mode)
+{
+ if (m_messages.isEmpty() && mode == SaveEverything)
+ return;
+
+ QMap<TranslatorMessage, void *> messages = m_messages;
+
+ // re-build contents
+ m_messageArray.clear();
+ m_offsetArray.clear();
+ m_contextArray.clear();
+ m_messages.clear();
+
+ QMap<Offset, void *> offsets;
+
+ QDataStream ms(&m_messageArray, QIODevice::WriteOnly);
+ QMap<TranslatorMessage, void *>::const_iterator it, next;
+ int cpPrev = 0, cpNext = 0;
+ for (it = messages.constBegin(); it != messages.constEnd(); ++it) {
+ cpPrev = cpNext;
+ next = it;
+ ++next;
+ if (next == messages.constEnd())
+ cpNext = 0;
+ else
+ cpNext = commonPrefix(it.key(), next.key());
+ offsets.insert(Offset(msgHash(it.key()), ms.device()->pos()), (void *)0);
+ writeMessage(it.key(), ms, mode, Prefix(qMax(cpPrev, cpNext + 1)));
+ }
+
+ QMap<Offset, void *>::Iterator offset;
+ offset = offsets.begin();
+ QDataStream ds(&m_offsetArray, QIODevice::WriteOnly);
+ while (offset != offsets.end()) {
+ Offset k = offset.key();
+ ++offset;
+ ds << quint32(k.h) << quint32(k.o);
+ }
+
+ if (mode == SaveStripped) {
+ QMap<QString, int> contextSet;
+ for (it = messages.constBegin(); it != messages.constEnd(); ++it)
+ ++contextSet[it.key().context()];
+
+ quint16 hTableSize;
+ if (contextSet.size() < 200)
+ hTableSize = (contextSet.size() < 60) ? 151 : 503;
+ else if (contextSet.size() < 2500)
+ hTableSize = (contextSet.size() < 750) ? 1511 : 5003;
+ else
+ hTableSize = (contextSet.size() < 10000) ? 15013 : 3 * contextSet.size() / 2;
+
+ QMultiMap<int, QString> hashMap;
+ QMap<QString, int>::const_iterator c;
+ for (c = contextSet.constBegin(); c != contextSet.constEnd(); ++c)
+ hashMap.insert(elfHash(originalBytes(c.key(), false /*FIXME*/)) % hTableSize, c.key());
+
+ /*
+ The contexts found in this translator are stored in a hash
+ table to provide fast lookup. The context array has the
+ following format:
+
+ quint16 hTableSize;
+ quint16 hTable[hTableSize];
+ quint8 contextPool[...];
+
+ The context pool stores the contexts as Pascal strings:
+
+ quint8 len;
+ quint8 data[len];
+
+ Let's consider the look-up of context "FunnyDialog". A
+ hash value between 0 and hTableSize - 1 is computed, say h.
+ If hTable[h] is 0, "FunnyDialog" is not covered by this
+ translator. Else, we check in the contextPool at offset
+ 2 * hTable[h] to see if "FunnyDialog" is one of the
+ contexts stored there, until we find it or we meet the
+ empty string.
+ */
+ m_contextArray.resize(2 + (hTableSize << 1));
+ QDataStream t(&m_contextArray, QIODevice::WriteOnly);
+
+ quint16 *hTable = new quint16[hTableSize];
+ memset(hTable, 0, hTableSize * sizeof(quint16));
+
+ t << hTableSize;
+ t.device()->seek(2 + (hTableSize << 1));
+ t << quint16(0); // the entry at offset 0 cannot be used
+ uint upto = 2;
+
+ QMap<int, QString>::const_iterator entry = hashMap.constBegin();
+ while (entry != hashMap.constEnd()) {
+ int i = entry.key();
+ hTable[i] = quint16(upto >> 1);
+
+ do {
+ QString context = entry.value();
+ QByteArray ba = context.toUtf8();
+ const char *con = ba.data();
+ uint len = uint(qstrlen(con));
+ len = qMin(len, 255u);
+ t << quint8(len);
+ t.writeRawData(con, len);
+ upto += 1 + len;
+ ++entry;
+ } while (entry != hashMap.constEnd() && entry.key() == i);
+ if (upto & 0x1) {
+ // offsets have to be even
+ t << quint8(0); // empty string
+ ++upto;
+ }
+ }
+ t.device()->seek(2);
+ for (int j = 0; j < hTableSize; j++)
+ t << hTable[j];
+ delete [] hTable;
+
+ if (upto > 131072) {
+ qWarning("Releaser::squeeze: Too many contexts");
+ m_contextArray.clear();
+ }
+ }
+}
+
+bool Releaser::contains(const QString &context, const QString &sourceText,
+ const QString &comment) const
+{
+ return !findMessage(context, sourceText, comment).translation().isNull();
+}
+
+bool Releaser::contains(const QString &context, const QString &comment,
+ const QString &fileName, int lineNumber) const
+{
+ return !findMessage(context, QString(), comment, fileName, lineNumber).isNull();
+}
+
+void Releaser::insert(const TranslatorMessage &message)
+{
+ m_messages.insert(message, 0);
+}
+
+void Releaser::remove(const TranslatorMessage &message)
+{
+ m_messages.remove(message);
+}
+
+
+TranslatorMessage Releaser::findMessage(const QString &context,
+ const QString &sourceText, const QString &comment,
+ const QString &fileName, int lineNumber) const
+{
+ if (m_messages.isEmpty())
+ return TranslatorMessage();
+
+ QMap<TranslatorMessage, void *>::const_iterator it;
+
+ // Either we want to find an item that matches context, sourcetext
+ // (and optionally comment) Or we want to find an item that
+ // matches context, filename, linenumber (and optionally comment)
+ TranslatorMessage msg(context, sourceText, comment, QString(), fileName, lineNumber);
+ it = m_messages.constFind(msg);
+ if (it != m_messages.constEnd())
+ return it.key();
+
+ if (!comment.isEmpty()) {
+ it = m_messages.constFind(TranslatorMessage(context, sourceText, QString(), QString(), fileName, lineNumber));
+ if (it != m_messages.constEnd())
+ return it.key();
+ }
+
+ it = m_messages.constFind(TranslatorMessage(context, QString(), comment, QString(), fileName, lineNumber));
+ if (it != m_messages.constEnd())
+ return it.key();
+ if (comment.isEmpty())
+ return TranslatorMessage();
+
+ it = m_messages.constFind(TranslatorMessage(context, QString(), QString(), QString(), fileName, lineNumber));
+ if (it != m_messages.constEnd())
+ return it.key();
+ return TranslatorMessage();
+}
+
+bool Releaser::isEmpty() const
+{
+ return m_messageArray.isEmpty() && m_offsetArray.isEmpty()
+ && m_contextArray.isEmpty() && m_messages.isEmpty();
+}
+
+void Releaser::setNumerusRules(const QByteArray &rules)
+{
+ m_numerusRules = rules;
+}
+
+QList<TranslatorMessage> Releaser::messages() const
+{
+ return m_messages.keys();
+}
+
+static quint8 read8(const uchar *data)
+{
+ return *data;
+}
+
+static quint32 read32(const uchar *data)
+{
+ return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]);
+}
+
+
+bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ QByteArray ba = dev.readAll();
+ const uchar *data = (uchar*)ba.data();
+ int len = ba.size();
+ if (len < MagicLength || memcmp(data, magic, MagicLength) != 0) {
+ cd.appendError(QLatin1String("QM-Format error: magic marker missing"));
+ return false;
+ }
+
+ enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88 };
+
+ // for squeezed but non-file data, this is what needs to be deleted
+ const uchar *messageArray = 0;
+ const uchar *offsetArray = 0;
+ const uchar *contextArray = 0;
+ const uchar *numerusRulesArray = 0;
+ uint messageLength = 0;
+ uint offsetLength = 0;
+ uint contextLength = 0;
+ uint numerusRulesLength = 0;
+
+ bool ok = true;
+ const uchar *end = data + len;
+
+ data += MagicLength;
+
+ while (data < end - 4) {
+ quint8 tag = read8(data++);
+ quint32 blockLen = read32(data);
+ //qDebug() << "TAG:" << tag << "BLOCKLEN:" << blockLen;
+ data += 4;
+ if (!tag || !blockLen)
+ break;
+ if (data + blockLen > end) {
+ ok = false;
+ break;
+ }
+
+ if (tag == Contexts) {
+ contextArray = data;
+ contextLength = blockLen;
+ //qDebug() << "CONTEXTS: " << contextLength << QByteArray((const char *)contextArray, contextLength).toHex();
+ } else if (tag == Hashes) {
+ offsetArray = data;
+ offsetLength = blockLen;
+ //qDebug() << "HASHES: " << offsetLength << QByteArray((const char *)offsetArray, offsetLength).toHex();
+ } else if (tag == Messages) {
+ messageArray = data;
+ messageLength = blockLen;
+ //qDebug() << "MESSAGES: " << messageLength << QByteArray((const char *)messageArray, messageLength).toHex();
+ } else if (tag == NumerusRules) {
+ numerusRulesArray = data;
+ numerusRulesLength = blockLen;
+ //qDebug() << "NUMERUSRULES: " << numerusRulesLength << QByteArray((const char *)numerusRulesArray, numerusRulesLength).toHex();
+ }
+
+ data += blockLen;
+ }
+
+
+ size_t numItems = offsetLength / (2 * sizeof(quint32));
+ //qDebug() << "NUMITEMS: " << numItems;
+
+ TranslatorMessage msg;
+
+ // FIXME: that's just a guess, the original locale data is lost...
+ QTextCodec *codec = QTextCodec::codecForLocale();
+
+ for (const uchar *start = offsetArray; start != offsetArray + (numItems << 3); start += 8) {
+ //quint32 hash = read32(start);
+ quint32 ro = read32(start + 4);
+ //qDebug() << "\nHASH:" << hash;
+ const uchar *m = messageArray + ro;
+
+ for (;;) {
+ uchar tag = read8(m++);
+ //qDebug() << "Tag:" << tag << " ADDR: " << m;
+ switch(tag) {
+ case Tag_End:
+ goto end;
+ case Tag_Translation: {
+ int len = read32(m);
+ if (len % 1) {
+ cd.appendError(QLatin1String("QM-Format error"));
+ return false;
+ }
+ m += 4;
+ QString str = QString::fromUtf16((const ushort *)m, len/2);
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ for (int i = 0; i < str.length(); ++i)
+ str[i] = QChar((str.at(i).unicode() >> 8) +
+ ((str.at(i).unicode() << 8) & 0xff00));
+ }
+ str.replace(QChar(Translator::InternalVariantSeparator),
+ QChar(Translator::DefaultVariantSeparator));
+ msg.appendTranslation(str);
+ m += len;
+ break;
+ }
+ case Tag_Obsolete1:
+ m += 4;
+ //qDebug() << "OBSOLETE";
+ break;
+ case Tag_SourceText: {
+ quint32 len = read32(m);
+ m += 4;
+ //qDebug() << "SOURCE LEN: " << len;
+ //qDebug() << "SOURCE: " << QByteArray((const char*)m, len);
+ msg.setSourceText(codec->toUnicode(QByteArray((const char*)m, len)));
+ m += len;
+ break;
+ }
+ case Tag_Context: {
+ quint32 len = read32(m);
+ m += 4;
+ //qDebug() << "CONTEXT LEN: " << len;
+ //qDebug() << "CONTEXT: " << QByteArray((const char*)m, len);
+ msg.setContext(codec->toUnicode(QByteArray((const char*)m, len)));
+ m += len;
+ break;
+ }
+ case Tag_Comment: {
+ quint32 len = read32(m);
+ m += 4;
+ //qDebug() << "COMMENT LEN: " << len;
+ //qDebug() << "COMMENT: " << QByteArray((const char*)m, len);
+ msg.setComment(codec->toUnicode(QByteArray((const char*)m, len)));
+ m += len;
+ break;
+ }
+ default:
+ //qDebug() << "UNKNOWN TAG" << tag;
+ break;
+ }
+ }
+ end:;
+ msg.setType(TranslatorMessage::Finished);
+ translator.append(msg);
+ //qDebug() << "\nHASH:" << hash << msg.sourceText() << msg.context();
+ msg.setTranslations(QStringList());
+ }
+ return ok;
+}
+
+
+
+static bool saveQM(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ Releaser releaser;
+ QLocale::Language l;
+ QLocale::Country c;
+ Translator::languageAndCountry(translator.languageCode(), &l, &c);
+ QByteArray rules;
+ if (getNumerusInfo(l, c, &rules, 0))
+ releaser.setNumerusRules(rules);
+ releaser.setCodecName(translator.codecName());
+
+ int finished = 0;
+ int unfinished = 0;
+ int untranslated = 0;
+
+ for (int i = 0; i != translator.messageCount(); ++i) {
+ const TranslatorMessage &msg = translator.message(i);
+ TranslatorMessage::Type typ = msg.type();
+ if (typ != TranslatorMessage::Obsolete) {
+ if (typ == TranslatorMessage::Unfinished) {
+ if (msg.translation().isEmpty())
+ ++untranslated;
+ else
+ ++unfinished;
+ } else {
+ ++finished;
+ }
+ QString context = msg.context();
+ QString sourceText = msg.sourceText();
+ QString comment = msg.comment();
+ QStringList translations = msg.translations();
+
+ if (!cd.ignoreUnfinished() || typ != TranslatorMessage::Unfinished) {
+ /*
+ Drop the comment in (context, sourceText, comment),
+ unless the context is empty,
+ unless (context, sourceText, "") already exists or
+ unless we already dropped the comment of (context,
+ sourceText, comment0).
+ */
+ if (comment.isEmpty()
+ || context.isEmpty()
+ || translator.contains(context, sourceText, QString())
+ || !releaser.findMessage(context, sourceText, QString()).translation()
+ .isNull() ) {
+ releaser.insert(msg);
+ } else {
+ TranslatorMessage tm(context, sourceText, QString(),
+ QString(), QString(), -1, translations);
+ //filename and lineNumbers will be ignored from now.
+ releaser.insert(tm);
+ }
+ }
+ }
+ }
+
+ releaser.squeeze(cd.m_saveMode);
+ bool saved = releaser.save(&dev);
+ if (saved && cd.isVerbose()) {
+ int generatedCount = finished + unfinished;
+ cd.appendError(QCoreApplication::translate("LRelease",
+ " Generated %n translation(s) (%1 finished and %2 unfinished)\n", 0,
+ QCoreApplication::CodecForTr, generatedCount).arg(finished).arg(unfinished));
+ if (untranslated)
+ cd.appendError(QCoreApplication::translate("LRelease",
+ " Ignored %n untranslated source text(s)\n", 0,
+ QCoreApplication::CodecForTr, untranslated));
+ }
+ return saved;
+}
+
+int initQM()
+{
+ Translator::FileFormat format;
+
+ format.extension = QLatin1String("qm");
+ format.description = QObject::tr("Compiled Qt translations");
+ format.fileType = Translator::FileFormat::TranslationBinary;
+ format.priority = 0;
+ format.loader = &loadQM;
+ format.saver = &saveQM;
+ Translator::registerFileFormat(format);
+
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initQM)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/qph.cpp b/tools/linguist/shared/qph.cpp
new file mode 100644
index 0000000000..45d3a20a28
--- /dev/null
+++ b/tools/linguist/shared/qph.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+#include <QtXml/QXmlStreamReader>
+#include <QtXml/QXmlStreamAttribute>
+
+QT_BEGIN_NAMESPACE
+
+class QPHReader : public QXmlStreamReader
+{
+public:
+ QPHReader(QIODevice &dev, ConversionData &cd)
+ : QXmlStreamReader(&dev), m_cd(cd)
+ {}
+
+ // the "real thing"
+ bool read(Translator &translator);
+
+private:
+ bool elementStarts(const QString &str) const
+ {
+ return isStartElement() && name() == str;
+ }
+
+ bool isWhiteSpace() const
+ {
+ return isCharacters() && text().toString().trimmed().isEmpty();
+ }
+
+ // needed to expand <byte ... />
+ QString readContents();
+ // needed to join <lengthvariant>s
+ QString readTransContents();
+
+ void handleError();
+
+ ConversionData &m_cd;
+
+ enum DataField { NoField, SourceField, TargetField, DefinitionField };
+ DataField m_currentField;
+ QString m_currentSource;
+ QString m_currentTarget;
+ QString m_currentDefinition;
+};
+
+bool QPHReader::read(Translator &translator)
+{
+ m_currentField = NoField;
+ QString result;
+ while (!atEnd()) {
+ readNext();
+ if (isStartElement()) {
+ if (name() == QLatin1String("source"))
+ m_currentField = SourceField;
+ else if (name() == QLatin1String("target"))
+ m_currentField = TargetField;
+ else if (name() == QLatin1String("definition"))
+ m_currentField = DefinitionField;
+ else
+ m_currentField = NoField;
+ } else if (isWhiteSpace()) {
+ // ignore these
+ } else if (isCharacters()) {
+ if (m_currentField == SourceField)
+ m_currentSource += text();
+ else if (m_currentField == TargetField)
+ m_currentTarget += text();
+ else if (m_currentField == DefinitionField)
+ m_currentDefinition += text();
+ } else if (isEndElement() && name() == QLatin1String("phrase")) {
+ TranslatorMessage msg;
+ msg.setSourceText(m_currentSource);
+ msg.setTranslation(m_currentTarget);
+ msg.setTranslatorComment(m_currentDefinition);
+ translator.append(msg);
+ m_currentSource.clear();
+ m_currentTarget.clear();
+ m_currentDefinition.clear();
+ }
+ }
+ return true;
+}
+
+static bool loadQPH(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ translator.setLocationsType(Translator::NoLocations);
+ QPHReader reader(dev, cd);
+ return reader.read(translator);
+}
+
+static bool saveQPH(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ QTextStream t(&dev);
+ t << "<!DOCTYPE QPH><QPH>\n";
+ foreach (const TranslatorMessage &msg, translator.messages()) {
+ t << "<phrase>\n";
+ t << " <source>" << msg.sourceText() << "</source>\n";
+ t << " <target>" << msg.translations().join(QLatin1String("@"))
+ << "</target>\n";
+ if (!msg.context().isEmpty() || !msg.comment().isEmpty())
+ t << " <definition>" << msg.context() << msg.comment()
+ << "</definition>\n";
+ t << "</phrase>\n";
+ }
+ t << "</QPH>\n";
+ return true;
+}
+
+int initQPH()
+{
+ Translator::FileFormat format;
+
+ format.extension = QLatin1String("qph");
+ format.description = QObject::tr("Qt Linguist 'Phrase Book'");
+ format.fileType = Translator::FileFormat::TranslationSource;
+ format.priority = 0;
+ format.loader = &loadQPH;
+ format.saver = &saveQPH;
+ Translator::registerFileFormat(format);
+
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initQPH)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/qscript.cpp b/tools/linguist/shared/qscript.cpp
new file mode 100644
index 0000000000..9ab5e160fd
--- /dev/null
+++ b/tools/linguist/shared/qscript.cpp
@@ -0,0 +1,2408 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+class QScriptGrammar
+{
+public:
+ enum {
+ EOF_SYMBOL = 0,
+ T_AND = 1,
+ T_AND_AND = 2,
+ T_AND_EQ = 3,
+ T_AUTOMATIC_SEMICOLON = 62,
+ T_BREAK = 4,
+ T_CASE = 5,
+ T_CATCH = 6,
+ T_COLON = 7,
+ T_COMMA = 8,
+ T_CONST = 81,
+ T_CONTINUE = 9,
+ T_DEBUGGER = 82,
+ T_DEFAULT = 10,
+ T_DELETE = 11,
+ T_DIVIDE_ = 12,
+ T_DIVIDE_EQ = 13,
+ T_DO = 14,
+ T_DOT = 15,
+ T_ELSE = 16,
+ T_EQ = 17,
+ T_EQ_EQ = 18,
+ T_EQ_EQ_EQ = 19,
+ T_FALSE = 80,
+ T_FINALLY = 20,
+ T_FOR = 21,
+ T_FUNCTION = 22,
+ T_GE = 23,
+ T_GT = 24,
+ T_GT_GT = 25,
+ T_GT_GT_EQ = 26,
+ T_GT_GT_GT = 27,
+ T_GT_GT_GT_EQ = 28,
+ T_IDENTIFIER = 29,
+ T_IF = 30,
+ T_IN = 31,
+ T_INSTANCEOF = 32,
+ T_LBRACE = 33,
+ T_LBRACKET = 34,
+ T_LE = 35,
+ T_LPAREN = 36,
+ T_LT = 37,
+ T_LT_LT = 38,
+ T_LT_LT_EQ = 39,
+ T_MINUS = 40,
+ T_MINUS_EQ = 41,
+ T_MINUS_MINUS = 42,
+ T_NEW = 43,
+ T_NOT = 44,
+ T_NOT_EQ = 45,
+ T_NOT_EQ_EQ = 46,
+ T_NULL = 78,
+ T_NUMERIC_LITERAL = 47,
+ T_OR = 48,
+ T_OR_EQ = 49,
+ T_OR_OR = 50,
+ T_PLUS = 51,
+ T_PLUS_EQ = 52,
+ T_PLUS_PLUS = 53,
+ T_QUESTION = 54,
+ T_RBRACE = 55,
+ T_RBRACKET = 56,
+ T_REMAINDER = 57,
+ T_REMAINDER_EQ = 58,
+ T_RESERVED_WORD = 83,
+ T_RETURN = 59,
+ T_RPAREN = 60,
+ T_SEMICOLON = 61,
+ T_STAR = 63,
+ T_STAR_EQ = 64,
+ T_STRING_LITERAL = 65,
+ T_SWITCH = 66,
+ T_THIS = 67,
+ T_THROW = 68,
+ T_TILDE = 69,
+ T_TRUE = 79,
+ T_TRY = 70,
+ T_TYPEOF = 71,
+ T_VAR = 72,
+ T_VOID = 73,
+ T_WHILE = 74,
+ T_WITH = 75,
+ T_XOR = 76,
+ T_XOR_EQ = 77,
+
+ ACCEPT_STATE = 236,
+ RULE_COUNT = 267,
+ STATE_COUNT = 465,
+ TERMINAL_COUNT = 84,
+ NON_TERMINAL_COUNT = 88,
+
+ GOTO_INDEX_OFFSET = 465,
+ GOTO_INFO_OFFSET = 1374,
+ GOTO_CHECK_OFFSET = 1374
+ };
+
+ static const char *const spell [];
+ static const int lhs [];
+ static const int rhs [];
+ static const int goto_default [];
+ static const int action_default [];
+ static const int action_index [];
+ static const int action_info [];
+ static const int action_check [];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int *const goto_index = &action_index [GOTO_INDEX_OFFSET];
+ const int *const goto_check = &action_check [GOTO_CHECK_OFFSET];
+
+ const int yyn = goto_index [state] + nt;
+
+ if (yyn < 0 || goto_check [yyn] != nt)
+ return goto_default [nt];
+
+ const int *const goto_info = &action_info [GOTO_INFO_OFFSET];
+ return goto_info [yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
+};
+
+
+const char *const QScriptGrammar::spell [] = {
+ "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue",
+ "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
+ "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
+ "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
+ "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
+ "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
+ ")", ";", 0, "*", "*=", "string literal", "switch", "this", "throw", "~",
+ "try", "typeof", "var", "void", "while", "with", "^", "^=", "null", "true",
+ "false", "const", "debugger", "reserved word"};
+
+const int QScriptGrammar::lhs [] = {
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 87, 87, 91, 91, 86, 86,
+ 92, 92, 93, 93, 93, 93, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 95, 95, 96,
+ 96, 96, 96, 96, 99, 99, 100, 100, 100, 100,
+ 98, 98, 101, 101, 102, 102, 103, 103, 103, 104,
+ 104, 104, 104, 104, 104, 104, 104, 104, 104, 105,
+ 105, 105, 105, 106, 106, 106, 107, 107, 107, 107,
+ 108, 108, 108, 108, 108, 108, 108, 109, 109, 109,
+ 109, 109, 109, 110, 110, 110, 110, 110, 111, 111,
+ 111, 111, 111, 112, 112, 113, 113, 114, 114, 115,
+ 115, 116, 116, 117, 117, 118, 118, 119, 119, 120,
+ 120, 121, 121, 122, 122, 123, 123, 90, 90, 124,
+ 124, 125, 125, 125, 125, 125, 125, 125, 125, 125,
+ 125, 125, 125, 89, 89, 126, 126, 127, 127, 128,
+ 128, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 130, 146, 146, 145,
+ 145, 131, 131, 147, 147, 148, 148, 150, 150, 149,
+ 151, 154, 152, 152, 155, 153, 153, 132, 133, 133,
+ 134, 134, 135, 135, 135, 135, 135, 135, 135, 136,
+ 136, 136, 136, 137, 137, 137, 137, 138, 138, 139,
+ 141, 156, 156, 159, 159, 157, 157, 160, 158, 140,
+ 142, 142, 143, 143, 143, 161, 162, 144, 163, 97,
+ 167, 167, 164, 164, 165, 165, 168, 84, 169, 169,
+ 170, 170, 166, 166, 88, 88, 171};
+
+const int QScriptGrammar:: rhs[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 3, 5, 3, 3, 2, 4, 1, 2, 0, 1,
+ 3, 5, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 4, 3, 3, 1, 2, 2, 2, 4, 3,
+ 2, 3, 1, 3, 1, 1, 1, 2, 2, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 3, 3, 3, 1, 3, 3, 1, 3, 3, 3,
+ 1, 3, 3, 3, 3, 3, 3, 1, 3, 3,
+ 3, 3, 3, 1, 3, 3, 3, 3, 1, 3,
+ 3, 3, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 1, 3, 1, 5, 1, 5, 1, 3, 1,
+ 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 0, 1, 1, 3, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 3, 1, 2, 0,
+ 1, 3, 3, 1, 1, 1, 3, 1, 3, 2,
+ 2, 2, 0, 1, 2, 0, 1, 1, 2, 2,
+ 7, 5, 7, 7, 5, 9, 10, 7, 8, 2,
+ 2, 3, 3, 2, 2, 3, 3, 3, 3, 5,
+ 5, 3, 5, 1, 2, 0, 1, 4, 3, 3,
+ 3, 3, 3, 3, 4, 5, 2, 1, 8, 8,
+ 1, 3, 0, 1, 0, 1, 1, 1, 1, 2,
+ 1, 1, 0, 1, 0, 1, 2};
+
+const int QScriptGrammar::action_default [] = {
+ 0, 97, 164, 128, 136, 132, 172, 179, 76, 148,
+ 178, 186, 174, 124, 0, 175, 262, 61, 176, 177,
+ 182, 77, 140, 144, 65, 94, 75, 80, 60, 0,
+ 114, 180, 101, 259, 258, 261, 183, 0, 194, 0,
+ 248, 0, 8, 9, 0, 5, 0, 263, 2, 0,
+ 265, 19, 0, 0, 0, 0, 0, 3, 6, 0,
+ 0, 166, 208, 7, 0, 1, 0, 0, 4, 0,
+ 0, 195, 0, 0, 0, 184, 185, 90, 0, 173,
+ 181, 0, 0, 77, 96, 263, 2, 265, 79, 78,
+ 0, 0, 0, 92, 93, 91, 0, 264, 253, 254,
+ 0, 251, 0, 252, 0, 255, 256, 0, 257, 250,
+ 260, 0, 266, 0, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 23,
+ 41, 42, 43, 44, 45, 25, 46, 47, 24, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 0,
+ 21, 0, 0, 0, 22, 13, 95, 0, 125, 0,
+ 0, 0, 0, 115, 0, 0, 0, 0, 0, 0,
+ 105, 0, 0, 0, 99, 100, 98, 103, 107, 106,
+ 104, 102, 117, 116, 118, 0, 133, 0, 129, 68,
+ 0, 0, 0, 70, 59, 58, 0, 0, 69, 165,
+ 0, 73, 71, 0, 72, 74, 209, 210, 0, 161,
+ 154, 152, 159, 160, 158, 157, 163, 156, 155, 153,
+ 162, 149, 0, 137, 0, 0, 141, 0, 0, 145,
+ 67, 0, 0, 63, 0, 62, 267, 224, 0, 225,
+ 226, 227, 220, 0, 221, 222, 223, 81, 0, 0,
+ 0, 0, 0, 213, 214, 170, 168, 130, 138, 134,
+ 150, 126, 171, 0, 77, 142, 146, 119, 108, 0,
+ 0, 127, 0, 0, 0, 0, 120, 0, 0, 0,
+ 0, 0, 112, 110, 113, 111, 109, 122, 121, 123,
+ 0, 135, 0, 131, 0, 169, 77, 0, 151, 166,
+ 167, 0, 166, 0, 0, 216, 0, 0, 0, 218,
+ 0, 139, 0, 0, 143, 0, 0, 147, 206, 0,
+ 198, 207, 201, 0, 205, 0, 166, 199, 0, 166,
+ 0, 0, 217, 0, 0, 0, 219, 264, 253, 0,
+ 0, 255, 0, 249, 0, 240, 0, 0, 0, 212,
+ 0, 211, 188, 191, 0, 27, 30, 31, 248, 34,
+ 35, 5, 39, 40, 2, 41, 44, 3, 6, 166,
+ 7, 48, 1, 50, 4, 52, 53, 54, 55, 56,
+ 57, 189, 187, 65, 66, 64, 0, 228, 229, 0,
+ 0, 0, 231, 236, 234, 237, 0, 0, 235, 236,
+ 0, 232, 0, 233, 190, 239, 0, 190, 238, 0,
+ 241, 242, 0, 190, 243, 244, 0, 0, 245, 0,
+ 0, 0, 246, 247, 83, 82, 0, 0, 0, 215,
+ 0, 0, 0, 230, 0, 20, 0, 17, 19, 11,
+ 0, 16, 12, 18, 15, 10, 0, 14, 87, 85,
+ 89, 86, 84, 88, 203, 196, 0, 204, 200, 0,
+ 202, 192, 0, 193, 197};
+
+const int QScriptGrammar::goto_default [] = {
+ 29, 28, 436, 434, 113, 14, 2, 435, 112, 111,
+ 114, 193, 24, 17, 189, 26, 8, 200, 21, 27,
+ 77, 25, 1, 32, 30, 267, 13, 261, 3, 257,
+ 5, 259, 4, 258, 22, 265, 23, 266, 9, 260,
+ 256, 297, 386, 262, 263, 35, 6, 79, 12, 15,
+ 18, 19, 10, 7, 31, 80, 20, 36, 75, 76,
+ 11, 354, 353, 78, 456, 455, 319, 320, 458, 322,
+ 457, 321, 392, 396, 399, 395, 394, 414, 415, 16,
+ 100, 107, 96, 99, 106, 108, 33, 0};
+
+const int QScriptGrammar::action_index [] = {
+ 1210, 59, -84, 71, 41, -1, -84, -84, 148, -84,
+ -84, -84, -84, 201, 130, -84, -84, -84, -84, -84,
+ -84, 343, 67, 62, 122, 109, -84, -84, -84, 85,
+ 273, -84, 184, -84, 1210, -84, -84, 119, -84, 112,
+ -84, 521, -84, -84, 1130, -84, 45, 54, 58, 38,
+ 1290, 50, 521, 521, 521, 376, 521, -84, -84, 521,
+ 521, 521, -84, -84, 25, -84, 521, 521, -84, 43,
+ 521, -84, 521, 18, 15, -84, -84, -84, 24, -84,
+ -84, 521, 521, 64, 153, 27, -84, 1050, -84, -84,
+ 521, 521, 521, -84, -84, -84, 28, -84, 37, 55,
+ 19, -84, 33, -84, 34, 1210, -84, 16, 1210, -84,
+ -84, 39, 52, -3, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, 521,
+ -84, 1050, 125, 521, -84, -84, 155, 521, 189, 521,
+ 521, 521, 521, 248, 521, 521, 521, 521, 521, 521,
+ 243, 521, 521, 521, 75, 82, 94, 177, 184, 184,
+ 184, 184, 263, 283, 298, 521, 44, 521, 77, -84,
+ 970, 521, 817, -84, -84, -84, 95, 521, -84, -84,
+ 93, -84, -84, 521, -84, -84, -84, -84, 521, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, 521, 41, 521, 521, 68, 66, 521, -84,
+ -84, 970, 521, -84, 103, -84, -84, -84, 63, -84,
+ -84, -84, -84, 69, -84, -84, -84, -84, -27, 12,
+ 521, 92, 100, -84, -84, 890, -84, 31, -13, -45,
+ -84, 210, 32, -28, 387, 20, 73, 304, 117, -5,
+ 521, 212, 521, 521, 521, 521, 213, 521, 521, 521,
+ 521, 521, 151, 150, 176, 158, 168, 304, 304, 228,
+ 521, -72, 521, 4, 521, -84, 306, 521, -84, 521,
+ 8, -50, 521, -48, 1130, -84, 521, 80, 1130, -84,
+ 521, -33, 521, 521, 5, 48, 521, -84, 17, 88,
+ 11, -84, -84, 521, -84, -29, 521, -84, -41, 521,
+ -39, 1130, -84, 521, 87, 1130, -84, -8, -2, -35,
+ 10, 1210, -16, -84, 1130, -84, 521, 86, 1130, -14,
+ 1130, -84, -84, 1130, -36, 107, -21, 165, 3, 521,
+ 1130, 6, 14, 61, 7, -19, 448, -4, -6, 671,
+ 29, 13, 23, 521, 30, -10, 521, 9, 521, -30,
+ -18, -84, -84, 164, -84, -84, 46, -84, -84, 521,
+ 111, -24, -84, 36, -84, 40, 99, 521, -84, 21,
+ 22, -84, -11, -84, 1130, -84, 106, 1130, -84, 178,
+ -84, -84, 98, 1130, 57, -84, 56, 60, -84, 51,
+ 26, 35, -84, -84, -84, -84, 521, 97, 1130, -84,
+ 521, 90, 1130, -84, 79, 76, 744, -84, 49, -84,
+ 594, -84, -84, -84, -84, -84, 83, -84, -84, -84,
+ -84, -84, -84, -84, 42, -84, 162, -84, -84, 521,
+ -84, -84, 53, -84, -84,
+
+ -61, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -4, -88, -88, 22, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -51, -88, -88, -88, -88, -88,
+ -88, 105, -88, -88, -12, -88, -88, -88, -88, -88,
+ -7, -88, 35, 132, 62, 154, 79, -88, -88, 100,
+ 75, 36, -88, -88, -88, -88, 37, 70, -88, -1,
+ 86, -88, 92, -88, -88, -88, -88, -88, -88, -88,
+ -88, 90, 95, -88, -88, -88, -88, -88, -88, -88,
+ 87, 82, 74, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -47, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, 28,
+ -88, 20, -88, 19, -88, -88, -88, 39, -88, 42,
+ 43, 106, 61, -88, 63, 55, 52, 53, 91, 125,
+ -88, 120, 123, 118, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, 116, -88, 59, -88, -88,
+ 16, 18, 15, -88, -88, -88, -88, 21, -88, -88,
+ -88, -88, -88, 24, -88, -88, -88, -88, 38, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, 97, -88, 115, 25, -88, -88, 26, -88,
+ -88, 111, 14, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ 23, -88, -88, -88, -88, 108, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ 160, -88, 171, 163, 145, 179, -88, 135, 45, 41,
+ 66, 80, -88, -88, -88, -88, -88, -88, -88, -88,
+ 172, -88, 156, -88, 142, -88, -88, 144, -88, 122,
+ -88, -88, 114, -88, -23, -88, 48, -88, 29, -88,
+ 224, -88, 157, 175, -88, -88, 182, -88, -88, -88,
+ -88, -88, -88, 183, -88, -21, 134, -88, -88, 49,
+ -88, 3, -88, 44, -88, 2, -88, -88, -37, -88,
+ -88, -31, -88, -88, 10, -88, 47, -88, 17, -88,
+ 27, -88, -88, 13, -88, -88, -88, -88, -88, 117,
+ 6, -88, -88, -88, -88, -88, 154, -88, -88, 1,
+ -88, -88, -88, 7, -88, -35, 137, -88, 141, -88,
+ -88, -88, -88, -6, -88, -88, -88, -88, -88, 78,
+ -88, -88, -88, -88, -88, -69, -88, 11, -88, -59,
+ -88, -88, -88, -88, 83, -88, -88, 56, -88, -88,
+ -88, -88, -88, -40, -58, -88, -88, -29, -88, -88,
+ -88, -45, -88, -88, -88, -88, -3, -88, -42, -88,
+ -5, -88, -32, -88, -88, -88, 9, -88, 8, -88,
+ -2, -88, -88, -88, -88, -88, -88, -88, -88, -88,
+ -88, -88, -88, -88, -88, -88, -88, -88, -88, 12,
+ -88, -88, -56, -88, -88};
+
+const int QScriptGrammar::action_info [] = {
+ 318, -25, 350, -45, 292, 270, 426, 310, -194, 393,
+ -32, 302, 304, -37, 344, 290, 197, 346, 430, 382,
+ 329, 331, 310, 413, 318, 340, 397, 101, 338, 404,
+ -49, 292, 270, 299, 323, 290, -24, -51, -195, 343,
+ 294, 397, 333, 341, 403, 397, 149, 249, 250, 389,
+ 255, 430, 155, 454, 426, 316, 97, 437, 437, 459,
+ 151, 389, 103, 102, 98, 344, 101, 105, 413, 222,
+ 222, 109, 157, 228, 346, 187, 413, 417, 157, 104,
+ 420, 255, 454, 337, 443, 236, 421, 438, 197, 185,
+ 97, 197, 419, 413, 197, 197, 325, -263, 197, 81,
+ 197, 203, 0, 197, 416, 197, 88, 388, 387, 400,
+ 82, 197, 224, 407, 197, 81, 225, 89, 417, 197,
+ 187, 90, 81, 312, 241, 240, 82, 313, 0, 0,
+ 246, 245, 153, 82, 81, 439, 238, 231, 197, 0,
+ 308, 243, 171, 447, 172, 82, 348, 335, 238, 326,
+ 432, 198, 252, 204, 401, 173, 232, 428, 192, 235,
+ 0, 254, 253, 190, 0, 90, 91, 90, 239, 237,
+ 462, 391, 92, 244, 242, 171, 171, 172, 172, 231,
+ 239, 237, 191, 171, 192, 172, 197, 0, 173, 173,
+ 0, 207, 206, 171, 243, 172, 173, 0, 232, 0,
+ 192, 171, 171, 172, 172, 0, 173, 159, 160, 171,
+ 91, 172, 91, 0, 173, 173, 92, 0, 92, 159,
+ 160, 0, 173, 463, 461, 0, 244, 242, 272, 273,
+ 272, 273, 0, 0, 161, 162, 277, 278, 0, 411,
+ 410, 0, 0, 0, 0, 279, 161, 162, 280, 0,
+ 281, 277, 278, 0, 0, 274, 275, 274, 275, 0,
+ 279, 0, 0, 280, 0, 281, 0, 0, 171, 0,
+ 172, 164, 165, 0, 0, 0, 0, 0, 0, 166,
+ 167, 173, 0, 168, 0, 169, 164, 165, 0, 0,
+ 0, 0, 0, 0, 166, 167, 164, 165, 168, 0,
+ 169, 0, 0, 0, 166, 167, 164, 165, 168, 209,
+ 169, 0, 0, 0, 166, 167, 0, 0, 168, 210,
+ 169, 164, 165, 211, 0, 0, 0, 277, 278, 166,
+ 167, 0, 212, 168, 213, 169, 279, 0, 0, 280,
+ 0, 281, 0, 0, 0, 214, 209, 215, 88, 0,
+ 0, 0, 0, 0, 0, 216, 210, 0, 217, 89,
+ 211, 0, 0, 0, 218, 0, 0, 0, 0, 212,
+ 219, 213, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 214, 220, 215, 88, 0, 0, 42, 43,
+ 209, 0, 216, 0, 0, 217, 89, 0, 85, 0,
+ 210, 218, 0, 0, 211, 86, 0, 219, 0, 87,
+ 51, 0, 52, 212, 0, 213, 0, 0, 306, 55,
+ 220, 0, 0, 58, 0, 0, 214, 0, 215, 88,
+ 0, 0, 0, 0, 0, 0, 216, 0, 0, 217,
+ 89, 63, 0, 65, 0, 218, 0, 0, 0, 0,
+ 0, 219, 0, 0, 57, 68, 45, 0, 0, 0,
+ 42, 43, 0, 0, 220, 0, 0, 0, 0, 0,
+ 85, 0, 0, 0, 0, 0, 0, 86, 0, 0,
+ 0, 87, 51, 0, 52, 0, 0, 0, 0, 0,
+ 0, 55, 0, 0, 0, 58, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 63, 0, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 57, 68, 45, 0,
+ 0, 0, 41, 42, 43, 0, 0, 0, 0, 0,
+ 0, 0, 0, 85, 0, 0, 0, 0, 0, 0,
+ 86, 0, 0, 0, 87, 51, 0, 52, 0, 0,
+ 0, 53, 0, 54, 55, 56, 0, 0, 58, 0,
+ 0, 0, 59, 0, 60, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 63, 0, 65, 0,
+ 67, 0, 70, 0, 72, 0, 0, 0, 0, 57,
+ 68, 45, 0, 0, 0, 41, 42, 43, 0, 0,
+ 0, 0, 0, 0, 0, 0, 85, 0, 0, 0,
+ 0, 0, 0, 86, 0, 0, 0, 87, 51, 0,
+ 52, 0, 0, 0, 53, 0, 54, 55, 56, 0,
+ 0, 58, 0, 0, 0, 59, 0, 60, 0, 0,
+ 442, 0, 0, 0, 0, 0, 0, 0, 0, 63,
+ 0, 65, 0, 67, 0, 70, 0, 72, 0, 0,
+ 0, 0, 57, 68, 45, 0, 0, 0, -47, 0,
+ 0, 0, 41, 42, 43, 0, 0, 0, 0, 0,
+ 0, 0, 0, 85, 0, 0, 0, 0, 0, 0,
+ 86, 0, 0, 0, 87, 51, 0, 52, 0, 0,
+ 0, 53, 0, 54, 55, 56, 0, 0, 58, 0,
+ 0, 0, 59, 0, 60, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 63, 0, 65, 0,
+ 67, 0, 70, 0, 72, 0, 0, 0, 0, 57,
+ 68, 45, 0, 0, 0, 41, 42, 43, 0, 0,
+ 0, 0, 0, 0, 0, 0, 85, 0, 0, 0,
+ 0, 0, 0, 86, 0, 0, 0, 87, 51, 0,
+ 52, 0, 0, 0, 53, 0, 54, 55, 56, 0,
+ 0, 58, 0, 0, 0, 59, 0, 60, 0, 0,
+ 445, 0, 0, 0, 0, 0, 0, 0, 0, 63,
+ 0, 65, 0, 67, 0, 70, 0, 72, 0, 0,
+ 0, 0, 57, 68, 45, 0, 0, 0, 41, 42,
+ 43, 0, 0, 0, 0, 0, 0, 0, 0, 85,
+ 0, 0, 0, 0, 0, 0, 86, 0, 0, 0,
+ 87, 51, 0, 52, 0, 0, 0, 53, 0, 54,
+ 55, 56, 0, 0, 58, 0, 0, 0, 59, 0,
+ 60, 0, 0, 0, 0, 0, 0, 202, 0, 0,
+ 0, 0, 63, 0, 65, 0, 67, 0, 70, 0,
+ 72, 0, 0, 0, 0, 57, 68, 45, 0, 0,
+ 0, 41, 42, 43, 0, 0, 0, 0, 0, 0,
+ 0, 0, 85, 0, 0, 0, 0, 0, 0, 86,
+ 0, 0, 0, 87, 51, 0, 52, 0, 0, 0,
+ 53, 0, 54, 55, 56, 0, 0, 58, 0, 0,
+ 0, 59, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 63, 0, 65, 0, 67,
+ 0, 70, 269, 72, 0, 0, 0, 0, 57, 68,
+ 45, 0, 0, 0, 115, 116, 117, 0, 0, 119,
+ 121, 122, 0, 0, 123, 0, 124, 0, 0, 0,
+ 126, 127, 128, 0, 0, 0, 0, 0, 0, 195,
+ 130, 131, 132, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 133, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 137,
+ 0, 0, 0, 0, 0, 0, 139, 140, 141, 0,
+ 143, 144, 145, 146, 147, 148, 0, 0, 134, 142,
+ 125, 118, 120, 136, 115, 116, 117, 0, 0, 119,
+ 121, 122, 0, 0, 123, 0, 124, 0, 0, 0,
+ 126, 127, 128, 0, 0, 0, 0, 0, 0, 129,
+ 130, 131, 132, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 133, 0, 0, 0, 135, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 137,
+ 0, 0, 0, 0, 0, 138, 139, 140, 141, 0,
+ 143, 144, 145, 146, 147, 148, 0, 0, 134, 142,
+ 125, 118, 120, 136, 37, 0, 0, 0, 0, 39,
+ 0, 41, 42, 43, 44, 0, 0, 0, 0, 0,
+ 0, 46, 85, 0, 0, 0, 0, 0, 0, 48,
+ 49, 0, 0, 50, 51, 0, 52, 0, 0, 0,
+ 53, 0, 54, 55, 56, 0, 0, 58, 0, 0,
+ 0, 59, 0, 60, 0, 0, 0, 0, 0, 61,
+ 0, 62, 0, 0, 0, 63, 64, 65, 66, 67,
+ 69, 70, 71, 72, 73, 74, 0, 0, 57, 68,
+ 45, 38, 40, 0, 37, 0, 0, 0, 0, 39,
+ 0, 41, 42, 43, 44, 0, 0, 0, 0, 0,
+ 0, 46, 47, 0, 0, 0, 0, 0, 0, 48,
+ 49, 0, 0, 50, 51, 0, 52, 0, 0, 0,
+ 53, 0, 54, 55, 56, 0, 0, 58, 0, 0,
+ 0, 59, 0, 60, 0, 0, 0, 0, 0, 61,
+ 0, 62, 0, 0, 0, 63, 64, 65, 66, 67,
+ 69, 70, 71, 72, 73, 74, 0, 0, 57, 68,
+ 45, 38, 40, 0, 355, 116, 117, 0, 0, 357,
+ 121, 359, 42, 43, 360, 0, 124, 0, 0, 0,
+ 126, 362, 363, 0, 0, 0, 0, 0, 0, 364,
+ 365, 131, 132, 50, 51, 0, 52, 0, 0, 0,
+ 53, 0, 54, 366, 56, 0, 0, 368, 0, 0,
+ 0, 59, 0, 60, 0, -190, 0, 0, 0, 369,
+ 0, 62, 0, 0, 0, 370, 371, 372, 373, 67,
+ 375, 376, 377, 378, 379, 380, 0, 0, 367, 374,
+ 361, 356, 358, 136,
+
+ 431, 422, 427, 429, 441, 352, 300, 398, 385, 464,
+ 440, 412, 409, 433, 402, 444, 406, 423, 460, 234,
+ 418, 201, 305, 196, 34, 154, 194, 199, 251, 152,
+ 205, 227, 229, 248, 150, 110, 230, 208, 352, 110,
+ 446, 300, 409, 339, 221, 412, 327, 336, 332, 334,
+ 342, 248, 347, 307, 300, 345, 0, 83, 381, 83,
+ 83, 83, 349, 83, 284, 158, 163, 182, 283, 0,
+ 83, 83, 351, 83, 309, 178, 179, 83, 177, 83,
+ 83, 83, 449, 390, 83, 184, 170, 188, 83, 285,
+ 453, 330, 83, 83, 95, 452, 0, 83, 83, 450,
+ 83, 352, 94, 286, 83, 83, 424, 93, 83, 83,
+ 83, 84, 425, 83, 180, 83, 156, 408, 83, 300,
+ 451, 194, 233, 83, 83, 247, 264, 300, 352, 223,
+ 183, 268, 0, 83, 83, 83, 83, 247, 83, 300,
+ 176, 83, 174, 83, 405, 175, 186, 0, 181, 226,
+ 83, 0, 448, 83, 0, 83, 303, 424, 282, 83,
+ 296, 425, 296, 83, 301, 268, 383, 268, 268, 384,
+ 288, 0, 0, 0, 83, 83, 328, 0, 83, 268,
+ 268, 83, 295, 268, 298, 293, 268, 271, 287, 83,
+ 83, 0, 314, 296, 268, 268, 276, 83, 268, 0,
+ 296, 296, 268, 291, 289, 268, 268, 0, 0, 0,
+ 0, 0, 0, 0, 0, 315, 0, 0, 0, 0,
+ 0, 0, 317, 324, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 83, 0, 0, 0, 0, 268, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 311, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
+
+const int QScriptGrammar::action_check [] = {
+ 29, 7, 16, 7, 76, 1, 36, 2, 29, 33,
+ 7, 61, 60, 7, 7, 48, 8, 36, 36, 55,
+ 61, 60, 2, 33, 29, 60, 5, 29, 36, 7,
+ 7, 76, 1, 61, 17, 48, 7, 7, 29, 55,
+ 8, 5, 31, 33, 55, 5, 7, 74, 36, 36,
+ 36, 36, 55, 29, 36, 7, 29, 8, 8, 17,
+ 8, 36, 29, 8, 36, 7, 29, 33, 33, 2,
+ 2, 55, 1, 7, 36, 76, 33, 20, 1, 60,
+ 29, 36, 29, 29, 8, 0, 60, 8, 8, 48,
+ 29, 8, 36, 33, 8, 8, 8, 36, 8, 40,
+ 8, 8, -1, 8, 6, 8, 42, 61, 62, 10,
+ 51, 8, 50, 7, 8, 40, 54, 53, 20, 8,
+ 76, 12, 40, 50, 61, 62, 51, 54, -1, -1,
+ 61, 62, 7, 51, 40, 56, 29, 15, 8, -1,
+ 60, 29, 25, 60, 27, 51, 60, 60, 29, 61,
+ 60, 56, 60, 60, 55, 38, 34, 60, 36, 56,
+ -1, 61, 62, 15, -1, 12, 57, 12, 61, 62,
+ 8, 60, 63, 61, 62, 25, 25, 27, 27, 15,
+ 61, 62, 34, 25, 36, 27, 8, -1, 38, 38,
+ -1, 61, 62, 25, 29, 27, 38, -1, 34, -1,
+ 36, 25, 25, 27, 27, -1, 38, 18, 19, 25,
+ 57, 27, 57, -1, 38, 38, 63, -1, 63, 18,
+ 19, -1, 38, 61, 62, -1, 61, 62, 18, 19,
+ 18, 19, -1, -1, 45, 46, 23, 24, -1, 61,
+ 62, -1, -1, -1, -1, 32, 45, 46, 35, -1,
+ 37, 23, 24, -1, -1, 45, 46, 45, 46, -1,
+ 32, -1, -1, 35, -1, 37, -1, -1, 25, -1,
+ 27, 23, 24, -1, -1, -1, -1, -1, -1, 31,
+ 32, 38, -1, 35, -1, 37, 23, 24, -1, -1,
+ -1, -1, -1, -1, 31, 32, 23, 24, 35, -1,
+ 37, -1, -1, -1, 31, 32, 23, 24, 35, 3,
+ 37, -1, -1, -1, 31, 32, -1, -1, 35, 13,
+ 37, 23, 24, 17, -1, -1, -1, 23, 24, 31,
+ 32, -1, 26, 35, 28, 37, 32, -1, -1, 35,
+ -1, 37, -1, -1, -1, 39, 3, 41, 42, -1,
+ -1, -1, -1, -1, -1, 49, 13, -1, 52, 53,
+ 17, -1, -1, -1, 58, -1, -1, -1, -1, 26,
+ 64, 28, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 39, 77, 41, 42, -1, -1, 12, 13,
+ 3, -1, 49, -1, -1, 52, 53, -1, 22, -1,
+ 13, 58, -1, -1, 17, 29, -1, 64, -1, 33,
+ 34, -1, 36, 26, -1, 28, -1, -1, 31, 43,
+ 77, -1, -1, 47, -1, -1, 39, -1, 41, 42,
+ -1, -1, -1, -1, -1, -1, 49, -1, -1, 52,
+ 53, 65, -1, 67, -1, 58, -1, -1, -1, -1,
+ -1, 64, -1, -1, 78, 79, 80, -1, -1, -1,
+ 12, 13, -1, -1, 77, -1, -1, -1, -1, -1,
+ 22, -1, -1, -1, -1, -1, -1, 29, -1, -1,
+ -1, 33, 34, -1, 36, -1, -1, -1, -1, -1,
+ -1, 43, -1, -1, -1, 47, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 65, -1, 67, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 78, 79, 80, -1,
+ -1, -1, 11, 12, 13, -1, -1, -1, -1, -1,
+ -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
+ 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
+ -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
+ -1, -1, 51, -1, 53, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 65, -1, 67, -1,
+ 69, -1, 71, -1, 73, -1, -1, -1, -1, 78,
+ 79, 80, -1, -1, -1, 11, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
+ -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
+ 36, -1, -1, -1, 40, -1, 42, 43, 44, -1,
+ -1, 47, -1, -1, -1, 51, -1, 53, -1, -1,
+ 56, -1, -1, -1, -1, -1, -1, -1, -1, 65,
+ -1, 67, -1, 69, -1, 71, -1, 73, -1, -1,
+ -1, -1, 78, 79, 80, -1, -1, -1, 7, -1,
+ -1, -1, 11, 12, 13, -1, -1, -1, -1, -1,
+ -1, -1, -1, 22, -1, -1, -1, -1, -1, -1,
+ 29, -1, -1, -1, 33, 34, -1, 36, -1, -1,
+ -1, 40, -1, 42, 43, 44, -1, -1, 47, -1,
+ -1, -1, 51, -1, 53, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 65, -1, 67, -1,
+ 69, -1, 71, -1, 73, -1, -1, -1, -1, 78,
+ 79, 80, -1, -1, -1, 11, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
+ -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
+ 36, -1, -1, -1, 40, -1, 42, 43, 44, -1,
+ -1, 47, -1, -1, -1, 51, -1, 53, -1, -1,
+ 56, -1, -1, -1, -1, -1, -1, -1, -1, 65,
+ -1, 67, -1, 69, -1, 71, -1, 73, -1, -1,
+ -1, -1, 78, 79, 80, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, -1, 60, -1, -1,
+ -1, -1, 65, -1, 67, -1, 69, -1, 71, -1,
+ 73, -1, -1, -1, -1, 78, 79, 80, -1, -1,
+ -1, 11, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
+ -1, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 65, -1, 67, -1, 69,
+ -1, 71, 72, 73, -1, -1, -1, -1, 78, 79,
+ 80, -1, -1, -1, 4, 5, 6, -1, -1, 9,
+ 10, 11, -1, -1, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -1, -1, -1, -1, -1, -1, 66, 67, 68, -1,
+ 70, 71, 72, 73, 74, 75, -1, -1, 78, 79,
+ 80, 81, 82, 83, 4, 5, 6, -1, -1, 9,
+ 10, 11, -1, -1, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -1, -1, -1, -1, -1, 65, 66, 67, 68, -1,
+ 70, 71, 72, 73, 74, 75, -1, -1, 78, 79,
+ 80, 81, 82, 83, 4, -1, -1, -1, -1, 9,
+ -1, 11, 12, 13, 14, -1, -1, -1, -1, -1,
+ -1, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, -1, -1, -1, -1, 59,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, -1, -1, 78, 79,
+ 80, 81, 82, -1, 4, -1, -1, -1, -1, 9,
+ -1, 11, 12, 13, 14, -1, -1, -1, -1, -1,
+ -1, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, -1, -1, -1, -1, 59,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, -1, -1, 78, 79,
+ 80, 81, 82, -1, 4, 5, 6, -1, -1, 9,
+ 10, 11, 12, 13, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, 55, -1, -1, -1, 59,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, -1, -1, 78, 79,
+ 80, 81, 82, 83,
+
+ 5, 46, 5, 45, 6, 45, 5, 76, 14, 65,
+ 2, 46, 5, 45, 73, 6, 5, 46, 6, 5,
+ 78, 6, 45, 5, 85, 6, 10, 6, 5, 9,
+ 6, 6, 6, 45, 6, 86, 14, 41, 45, 86,
+ 5, 5, 5, 80, 6, 46, 67, 45, 45, 5,
+ 81, 45, 5, 5, 5, 45, -1, 18, 45, 18,
+ 18, 18, 45, 18, 23, 26, 24, 24, 23, -1,
+ 18, 18, 45, 18, 45, 23, 23, 18, 23, 18,
+ 18, 18, 20, 5, 18, 24, 23, 28, 18, 23,
+ 20, 42, 18, 18, 20, 20, -1, 18, 18, 20,
+ 18, 45, 20, 23, 18, 18, 20, 20, 18, 18,
+ 18, 21, 20, 18, 23, 18, 21, 61, 18, 5,
+ 20, 10, 11, 18, 18, 20, 18, 5, 45, 32,
+ 24, 23, -1, 18, 18, 18, 18, 20, 18, 5,
+ 22, 18, 22, 18, 61, 22, 30, -1, 23, 34,
+ 18, -1, 20, 18, -1, 18, 42, 20, 23, 18,
+ 18, 20, 18, 18, 42, 23, 12, 23, 23, 15,
+ 25, -1, -1, -1, 18, 18, 42, -1, 18, 23,
+ 23, 18, 40, 23, 40, 29, 23, 27, 25, 18,
+ 18, -1, 35, 18, 23, 23, 25, 18, 23, -1,
+ 18, 18, 23, 31, 25, 23, 23, -1, -1, -1,
+ -1, -1, -1, -1, -1, 40, -1, -1, -1, -1,
+ -1, -1, 40, 40, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 18, -1, -1, -1, -1, 23, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 33, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1};
+
+
+#define Q_SCRIPT_REGEXPLITERAL_RULE1 7
+
+#define Q_SCRIPT_REGEXPLITERAL_RULE2 8
+
+#include "translator.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qnumeric.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qtextcodec.h>
+#include <QtCore/qvariant.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+static void recordMessage(
+ Translator *tor, const QString &context, const QString &text, const QString &comment,
+ const QString &extracomment, bool plural, const QString &fileName, int lineNo)
+{
+ TranslatorMessage msg(
+ context, text, comment, QString(),
+ fileName, lineNo, QStringList(),
+ TranslatorMessage::Unfinished, plural);
+ msg.setExtraComment(extracomment.simplified());
+ tor->replace(msg);
+}
+
+
+namespace QScript
+{
+
+class Lexer
+{
+public:
+ Lexer();
+ ~Lexer();
+
+ void setCode(const QString &c, int lineno);
+ int lex();
+
+ int currentLineNo() const { return yylineno; }
+ int currentColumnNo() const { return yycolumn; }
+
+ int startLineNo() const { return startlineno; }
+ int startColumnNo() const { return startcolumn; }
+
+ int endLineNo() const { return currentLineNo(); }
+ int endColumnNo() const
+ { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ enum Error {
+ NoError,
+ IllegalCharacter,
+ UnclosedStringLiteral,
+ IllegalEscapeSequence,
+ IllegalUnicodeEscapeSequence,
+ UnclosedComment,
+ IllegalExponentIndicator,
+ IllegalIdentifier
+ };
+
+ enum ParenthesesState {
+ IgnoreParentheses,
+ CountParentheses,
+ BalancedParentheses
+ };
+
+ enum RegExpBodyPrefix {
+ NoPrefix,
+ EqualPrefix
+ };
+
+ bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+
+ QString pattern;
+ int flags;
+
+ State lexerState() const
+ { return state; }
+
+ QString errorMessage() const
+ { return errmsg; }
+ void setErrorMessage(const QString &err)
+ { errmsg = err; }
+ void setErrorMessage(const char *err)
+ { setErrorMessage(QString::fromLatin1(err)); }
+
+ Error error() const
+ { return err; }
+ void clearError()
+ { err = NoError; }
+
+private:
+ int yylineno;
+ bool done;
+ char *buffer8;
+ QChar *buffer16;
+ uint size8, size16;
+ uint pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ uint pos;
+ void shift(uint p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(ushort c) const;
+ bool isOctalDigit(ushort c) const;
+
+ int matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ ushort singleEscape(ushort c) const;
+ ushort convertOctal(ushort c1, ushort c2,
+ ushort c3) const;
+public:
+ static unsigned char convertHex(ushort c1);
+ static unsigned char convertHex(ushort c1, ushort c2);
+ static QChar convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ static bool isIdentLetter(ushort c);
+ static bool isDecimalDigit(ushort c);
+
+ inline int ival() const { return qsyylval.toInt(); }
+ inline double dval() const { return qsyylval.toDouble(); }
+ inline QString ustr() const { return qsyylval.toString(); }
+ inline QVariant val() const { return qsyylval; }
+
+ const QChar *characterBuffer() const { return buffer16; }
+ int characterCount() const { return pos16; }
+
+private:
+ void record8(ushort c);
+ void record16(QChar c);
+ void recordStartPos();
+
+ int findReservedWord(const QChar *buffer, int size) const;
+
+ void syncProhibitAutomaticSemicolon();
+
+ const QChar *code;
+ uint length;
+ int yycolumn;
+ int startlineno;
+ int startcolumn;
+ int bol; // begin of line
+
+ QVariant qsyylval;
+
+ // current and following unicode characters
+ ushort current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ QString errmsg;
+ Error err;
+
+ bool wantRx;
+ bool check_reserved;
+
+ ParenthesesState parenthesesState;
+ int parenthesesCount;
+ bool prohibitAutomaticSemicolon;
+};
+
+} // namespace QScript
+
+extern double qstrtod(const char *s00, char const **se, bool *ok);
+
+#define shiftWindowsLineBreak() if(current == '\r' && next1 == '\n') shift(1);
+
+namespace QScript {
+
+static int toDigit(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'a') && (c <= 'z'))
+ return 10 + c - 'a';
+ else if ((c >= 'A') && (c <= 'Z'))
+ return 10 + c - 'A';
+ return -1;
+}
+
+double integerFromString(const char *buf, int size, int radix)
+{
+ if (size == 0)
+ return qSNaN();
+
+ double sign = 1.0;
+ int i = 0;
+ if (buf[0] == '+') {
+ ++i;
+ } else if (buf[0] == '-') {
+ sign = -1.0;
+ ++i;
+ }
+
+ if (((size-i) >= 2) && (buf[i] == '0')) {
+ if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ && (radix < 34)) {
+ if ((radix != 0) && (radix != 16))
+ return 0;
+ radix = 16;
+ i += 2;
+ } else {
+ if (radix == 0) {
+ radix = 8;
+ ++i;
+ }
+ }
+ } else if (radix == 0) {
+ radix = 10;
+ }
+
+ int j = i;
+ for ( ; i < size; ++i) {
+ int d = toDigit(buf[i]);
+ if ((d == -1) || (d >= radix))
+ break;
+ }
+ double result;
+ if (j == i) {
+ if (!qstrcmp(buf, "Infinity"))
+ result = qInf();
+ else
+ result = qSNaN();
+ } else {
+ result = 0;
+ double multiplier = 1;
+ for (--i ; i >= j; --i, multiplier *= radix)
+ result += toDigit(buf[i]) * multiplier;
+ }
+ result *= sign;
+ return result;
+}
+
+} // namespace QScript
+
+QScript::Lexer::Lexer()
+ :
+ yylineno(0),
+ size8(128), size16(128), restrKeyword(false),
+ stackToken(-1), pos(0),
+ code(0), length(0),
+ bol(true),
+ current(0), next1(0), next2(0), next3(0),
+ err(NoError),
+ check_reserved(true),
+ parenthesesState(IgnoreParentheses),
+ prohibitAutomaticSemicolon(false)
+{
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new QChar[size16];
+ flags = 0;
+
+}
+
+QScript::Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+void QScript::Lexer::setCode(const QString &c, int lineno)
+{
+ errmsg = QString();
+ yylineno = lineno;
+ yycolumn = 1;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c.unicode();
+ length = c.length();
+ bol = true;
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void QScript::Lexer::shift(uint p)
+{
+ while (p--) {
+ ++pos;
+ ++yycolumn;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void QScript::Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int QScript::Lexer::findReservedWord(const QChar *c, int size) const
+{
+ switch (size) {
+ case 2: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
+ return QScriptGrammar::T_DO;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
+ return QScriptGrammar::T_IF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
+ return QScriptGrammar::T_IN;
+ } break;
+
+ case 3: {
+ if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
+ return QScriptGrammar::T_FOR;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
+ return QScriptGrammar::T_NEW;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
+ return QScriptGrammar::T_TRY;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
+ return QScriptGrammar::T_VAR;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 4: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_CASE;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_ELSE;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
+ return QScriptGrammar::T_THIS;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
+ return QScriptGrammar::T_VOID;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
+ return QScriptGrammar::T_WITH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_TRUE;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
+ return QScriptGrammar::T_NULL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 5: {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('k'))
+ return QScriptGrammar::T_BREAK;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h'))
+ return QScriptGrammar::T_CATCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w'))
+ return QScriptGrammar::T_THROW;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e'))
+ return QScriptGrammar::T_WHILE;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('t'))
+ return QScriptGrammar::T_CONST;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('e'))
+ return QScriptGrammar::T_FALSE;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
+ && c[4] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 6: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
+ return QScriptGrammar::T_DELETE;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
+ return QScriptGrammar::T_RETURN;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
+ return QScriptGrammar::T_SWITCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
+ return QScriptGrammar::T_TYPEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
+ && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 7: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('t'))
+ return QScriptGrammar::T_DEFAULT;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('y'))
+ return QScriptGrammar::T_FINALLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('n'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
+ && c[6] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
+ && c[6] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 8: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
+ return QScriptGrammar::T_CONTINUE;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
+ return QScriptGrammar::T_FUNCTION;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
+ return QScriptGrammar::T_DEBUGGER;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 9: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
+ && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
+ && c[8] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('d'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 10: {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
+ return QScriptGrammar::T_INSTANCEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 12: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
+ && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ } // switch
+
+ return -1;
+}
+
+int QScript::Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ ushort stringType = 0; // either single or double quotes
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = -1;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ recordStartPos();
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ recordStartPos();
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ syncProhibitAutomaticSemicolon();
+ if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
+ // automatic semicolon insertion if program incomplete
+ token = QScriptGrammar::T_SEMICOLON;
+ stackToken = 0;
+ setDone(Other);
+ } else {
+ setDone(Eof);
+ }
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ terminator = true;
+ syncProhibitAutomaticSemicolon();
+ if (restrKeyword) {
+ token = QScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ recordStartPos();
+ state = InString;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ recordStartPos();
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ recordStartPos();
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ recordStartPos();
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ recordStartPos();
+ record8(current);
+ state = InDecimal;
+ } else {
+ recordStartPos();
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ if (terminator && !delimited && !prohibitAutomaticSemicolon
+ && (token == QScriptGrammar::T_PLUS_PLUS
+ || token == QScriptGrammar::T_MINUS_MINUS)) {
+ // automatic semicolon insertion
+ stackToken = token;
+ token = QScriptGrammar::T_SEMICOLON;
+ }
+ setDone(Other);
+ }
+ else {
+ setDone(Bad);
+ err = IllegalCharacter;
+ errmsg = QLatin1String("Illegal character");
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ err = UnclosedStringLiteral;
+ errmsg = QLatin1String("Unclosed string at end of line");
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) &&
+ isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ err = IllegalEscapeSequence;
+ errmsg = QLatin1String("Illegal escape squence");
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ record16(singleEscape(current));
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(QLatin1Char(convertHex(current, next1)));
+ shift(1);
+ } else if (current == stringType) {
+ record16(QLatin1Char('x'));
+ shift(1);
+ setDone(String);
+ } else {
+ record16(QLatin1Char('x'));
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16(QLatin1Char('u'));
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ err = IllegalUnicodeEscapeSequence;
+ errmsg = QLatin1String("Illegal unicode escape sequence");
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ terminator = true;
+ bol = true;
+ if (restrKeyword) {
+ token = QScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ } else
+ state = Start;
+ } else if (current == 0) {
+ setDone(Eof);
+ }
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ err = UnclosedComment;
+ errmsg = QLatin1String("Unclosed comment at end of file");
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current))
+ record8(current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Octal);
+ }
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else {
+ setDone(Bad);
+ err = IllegalExponentIndicator;
+ errmsg = QLatin1String("Illegal syntax for exponential number");
+ }
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Number);
+ }
+ break;
+ default:
+ Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current)) {
+ state = Bad;
+ err = IllegalIdentifier;
+ errmsg = QLatin1String("Identifier cannot start with numeric literal");
+ }
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+ double dval = 0;
+ if (state == Number) {
+ dval = qstrtod(buffer8, 0, 0);
+ } else if (state == Hex) { // scan hex numbers
+ dval = QScript::integerFromString(buffer8, pos8, 16);
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ dval = QScript::integerFromString(buffer8, pos8, 8);
+ state = Number;
+ }
+
+ restrKeyword = false;
+ delimited = false;
+
+ switch (parenthesesState) {
+ case IgnoreParentheses:
+ break;
+ case CountParentheses:
+ if (token == QScriptGrammar::T_RPAREN) {
+ --parenthesesCount;
+ if (parenthesesCount == 0)
+ parenthesesState = BalancedParentheses;
+ } else if (token == QScriptGrammar::T_LPAREN) {
+ ++parenthesesCount;
+ }
+ break;
+ case BalancedParentheses:
+ parenthesesState = IgnoreParentheses;
+ break;
+ }
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if(token == QScriptGrammar::T_RBRACE || token == QScriptGrammar::T_SEMICOLON)
+ delimited = true;
+ return token;
+ case Identifier:
+ if ((token = findReservedWord(buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ qsyylval = QString(buffer16, pos16);
+ return QScriptGrammar::T_IDENTIFIER;
+ }
+ if (token == QScriptGrammar::T_CONTINUE || token == QScriptGrammar::T_BREAK
+ || token == QScriptGrammar::T_RETURN || token == QScriptGrammar::T_THROW) {
+ restrKeyword = true;
+ } else if (token == QScriptGrammar::T_IF || token == QScriptGrammar::T_FOR
+ || token == QScriptGrammar::T_WHILE || token == QScriptGrammar::T_WITH) {
+ parenthesesState = CountParentheses;
+ parenthesesCount = 0;
+ } else if (token == QScriptGrammar::T_DO) {
+ parenthesesState = BalancedParentheses;
+ }
+ return token;
+ case String:
+ qsyylval = QString(buffer16, pos16);
+ return QScriptGrammar::T_STRING_LITERAL;
+ case Number:
+ qsyylval = dval;
+ return QScriptGrammar::T_NUMERIC_LITERAL;
+ case Bad:
+ return -1;
+ default:
+ Q_ASSERT(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool QScript::Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool QScript::Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool QScript::Lexer::isIdentLetter(ushort c)
+{
+ /* TODO: allow other legitimate unicode chars */
+ return ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c == '$'
+ || c == '_');
+}
+
+bool QScript::Lexer::isDecimalDigit(ushort c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool QScript::Lexer::isHexDigit(ushort c) const
+{
+ return ((c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F'));
+}
+
+bool QScript::Lexer::isOctalDigit(ushort c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int QScript::Lexer::matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return QScriptGrammar::T_GT_GT_GT_EQ;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_EQ_EQ_EQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_NOT_EQ_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return QScriptGrammar::T_GT_GT_GT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_LT_LT_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_GT_GT_EQ;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_NOT_EQ;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ return QScriptGrammar::T_PLUS_PLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ return QScriptGrammar::T_MINUS_MINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_EQ_EQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_PLUS_EQ;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_MINUS_EQ;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_STAR_EQ;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_DIVIDE_EQ;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_AND_EQ;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_XOR_EQ;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_REMAINDER_EQ;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_OR_EQ;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return QScriptGrammar::T_LT_LT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return QScriptGrammar::T_GT_GT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return QScriptGrammar::T_AND_AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return QScriptGrammar::T_OR_OR;
+ }
+
+ switch(c1) {
+ case '=': shift(1); return QScriptGrammar::T_EQ;
+ case '>': shift(1); return QScriptGrammar::T_GT;
+ case '<': shift(1); return QScriptGrammar::T_LT;
+ case ',': shift(1); return QScriptGrammar::T_COMMA;
+ case '!': shift(1); return QScriptGrammar::T_NOT;
+ case '~': shift(1); return QScriptGrammar::T_TILDE;
+ case '?': shift(1); return QScriptGrammar::T_QUESTION;
+ case ':': shift(1); return QScriptGrammar::T_COLON;
+ case '.': shift(1); return QScriptGrammar::T_DOT;
+ case '+': shift(1); return QScriptGrammar::T_PLUS;
+ case '-': shift(1); return QScriptGrammar::T_MINUS;
+ case '*': shift(1); return QScriptGrammar::T_STAR;
+ case '/': shift(1); return QScriptGrammar::T_DIVIDE_;
+ case '&': shift(1); return QScriptGrammar::T_AND;
+ case '|': shift(1); return QScriptGrammar::T_OR;
+ case '^': shift(1); return QScriptGrammar::T_XOR;
+ case '%': shift(1); return QScriptGrammar::T_REMAINDER;
+ case '(': shift(1); return QScriptGrammar::T_LPAREN;
+ case ')': shift(1); return QScriptGrammar::T_RPAREN;
+ case '{': shift(1); return QScriptGrammar::T_LBRACE;
+ case '}': shift(1); return QScriptGrammar::T_RBRACE;
+ case '[': shift(1); return QScriptGrammar::T_LBRACKET;
+ case ']': shift(1); return QScriptGrammar::T_RBRACKET;
+ case ';': shift(1); return QScriptGrammar::T_SEMICOLON;
+
+ default: return -1;
+ }
+}
+
+ushort QScript::Lexer::singleEscape(ushort c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+ushort QScript::Lexer::convertOctal(ushort c1, ushort c2,
+ ushort c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char QScript::Lexer::convertHex(ushort c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char QScript::Lexer::convertHex(ushort c1, ushort c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+QChar QScript::Lexer::convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ return QChar((convertHex(c3) << 4) + convertHex(c4),
+ (convertHex(c1) << 4) + convertHex(c2));
+}
+
+void QScript::Lexer::record8(ushort c)
+{
+ Q_ASSERT(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void QScript::Lexer::record16(QChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ QChar *tmp = new QChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(QChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+void QScript::Lexer::recordStartPos()
+{
+ startlineno = yylineno;
+ startcolumn = yycolumn;
+}
+
+bool QScript::Lexer::scanRegExp(RegExpBodyPrefix prefix)
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ if (prefix == EqualPrefix)
+ record16(QLatin1Char('='));
+
+ while (1) {
+ if (isLineTerminator() || current == 0) {
+ errmsg = QLatin1String("Unterminated regular expression literal");
+ return false;
+ }
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape = !lastWasEscape && (current == '\\');
+ }
+ else {
+ pattern = QString(buffer16, pos16);
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ flags = 0;
+ while (isIdentLetter(current)) {
+ record16(current);
+ shift(1);
+ }
+
+ return true;
+}
+
+void QScript::Lexer::syncProhibitAutomaticSemicolon()
+{
+ if (parenthesesState == BalancedParentheses) {
+ // we have seen something like "if (foo)", which means we should
+ // never insert an automatic semicolon at this point, since it would
+ // then be expanded into an empty statement (ECMA-262 7.9.1)
+ prohibitAutomaticSemicolon = true;
+ parenthesesState = IgnoreParentheses;
+ } else {
+ prohibitAutomaticSemicolon = false;
+ }
+}
+
+
+class Translator;
+
+class QScriptParser: protected QScriptGrammar
+{
+public:
+ QVariant val;
+
+ struct Location {
+ int startLine;
+ int startColumn;
+ int endLine;
+ int endColumn;
+ };
+
+public:
+ QScriptParser();
+ ~QScriptParser();
+
+ bool parse(QScript::Lexer *lexer,
+ const QString &fileName,
+ Translator *translator);
+
+ inline QString errorMessage() const
+ { return error_message; }
+ inline int errorLineNumber() const
+ { return error_lineno; }
+ inline int errorColumnNumber() const
+ { return error_column; }
+
+protected:
+ inline void reallocateStack();
+
+ inline QVariant &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline Location &loc(int index)
+ { return location_stack [tos + index - 2]; }
+
+protected:
+ int tos;
+ int stack_size;
+ QVector<QVariant> sym_stack;
+ int *state_stack;
+ Location *location_stack;
+ QString error_message;
+ int error_lineno;
+ int error_column;
+};
+
+inline void QScriptParser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack.resize(stack_size);
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<Location*> (qRealloc(location_stack, stack_size * sizeof(Location)));
+}
+
+inline static bool automatic(QScript::Lexer *lexer, int token)
+{
+ return (token == QScriptGrammar::T_RBRACE)
+ || (token == 0)
+ || lexer->prevTerminator();
+}
+
+QScriptParser::QScriptParser():
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0)
+{
+}
+
+QScriptParser::~QScriptParser()
+{
+ if (stack_size) {
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline QScriptParser::Location location(QScript::Lexer *lexer)
+{
+ QScriptParser::Location loc;
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ loc.endLine = lexer->endLineNo();
+ loc.endColumn = lexer->endColumnNo();
+ return loc;
+}
+
+bool QScriptParser::parse(QScript::Lexer *lexer,
+ const QString &fileName,
+ Translator *translator)
+{
+ const int INITIAL_STATE = 0;
+
+ int yytoken = -1;
+ int saved_yytoken = -1;
+ int identLineNo = -1;
+
+ reallocateStack();
+
+ tos = 0;
+ state_stack[++tos] = INITIAL_STATE;
+
+ while (true)
+ {
+ const int state = state_stack [tos];
+ if (yytoken == -1 && - TERMINAL_COUNT != action_index [state])
+ {
+ if (saved_yytoken == -1)
+ {
+ yytoken = lexer->lex();
+ location_stack [tos] = location(lexer);
+ }
+ else
+ {
+ yytoken = saved_yytoken;
+ saved_yytoken = -1;
+ }
+ }
+
+ int act = t_action (state, yytoken);
+
+ if (act == ACCEPT_STATE)
+ return true;
+
+ else if (act > 0)
+ {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ sym_stack [tos] = lexer->val ();
+ state_stack [tos] = act;
+ location_stack [tos] = location(lexer);
+ yytoken = -1;
+ }
+
+ else if (act < 0)
+ {
+ int r = - act - 1;
+
+ tos -= rhs [r];
+ act = state_stack [tos++];
+
+ switch (r) {
+
+case 1: {
+ sym(1) = sym(1).toByteArray();
+ identLineNo = lexer->startLineNo();
+} break;
+
+case 7: {
+ bool rx = lexer->scanRegExp(QScript::Lexer::NoPrefix);
+ if (!rx) {
+ error_message = lexer->errorMessage();
+ error_lineno = lexer->startLineNo();
+ error_column = lexer->startColumnNo();
+ return false;
+ }
+} break;
+
+case 8: {
+ bool rx = lexer->scanRegExp(QScript::Lexer::EqualPrefix);
+ if (!rx) {
+ error_message = lexer->errorMessage();
+ error_lineno = lexer->startLineNo();
+ error_column = lexer->startColumnNo();
+ return false;
+ }
+} break;
+
+case 66: {
+ QString name = sym(1).toString();
+ if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
+ QVariantList args = sym(2).toList();
+ if (args.size() < 2) {
+ qWarning("%s:%d: %s() requires at least two arguments",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ if ((args.at(0).type() != QVariant::String)
+ || (args.at(1).type() != QVariant::String)) {
+ qWarning("%s:%d: %s(): both arguments must be literal strings",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ QString context = args.at(0).toString();
+ QString text = args.at(1).toString();
+ QString comment = args.value(2).toString();
+ QString extracomment;
+ bool plural = (args.size() > 4);
+ recordMessage(translator, context, text, comment, extracomment,
+ plural, fileName, identLineNo);
+ }
+ }
+ } else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
+ QVariantList args = sym(2).toList();
+ if (args.size() < 1) {
+ qWarning("%s:%d: %s() requires at least one argument",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ if (args.at(0).type() != QVariant::String) {
+ qWarning("%s:%d: %s(): text to translate must be a literal string",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ QString context = QFileInfo(fileName).baseName();
+ QString text = args.at(0).toString();
+ QString comment = args.value(1).toString();
+ QString extracomment;
+ bool plural = (args.size() > 2);
+ recordMessage(translator, context, text, comment, extracomment,
+ plural, fileName, identLineNo);
+ }
+ }
+ }
+} break;
+
+case 70: {
+ sym(1) = QVariantList();
+} break;
+
+case 71: {
+ sym(1) = sym(2);
+} break;
+
+case 72: {
+ sym(1) = QVariantList() << sym(1);
+} break;
+
+case 73: {
+ sym(1) = sym(1).toList() << sym(3);
+} break;
+
+case 94: {
+ if ((sym(1).type() == QVariant::String) || (sym(3).type() == QVariant::String))
+ sym(1) = sym(1).toString() + sym(3).toString();
+ else
+ sym(1) = QVariant();
+} break;
+
+ } // switch
+
+ state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT);
+
+ if (rhs[r] > 1) {
+ location_stack[tos - 1].endLine = location_stack[tos + rhs[r] - 2].endLine;
+ location_stack[tos - 1].endColumn = location_stack[tos + rhs[r] - 2].endColumn;
+ location_stack[tos] = location_stack[tos + rhs[r] - 1];
+ }
+ }
+
+ else
+ {
+ if (saved_yytoken == -1 && automatic (lexer, yytoken) && t_action (state, T_AUTOMATIC_SEMICOLON) > 0)
+ {
+ saved_yytoken = yytoken;
+ yytoken = T_SEMICOLON;
+ continue;
+ }
+
+ else if ((state == INITIAL_STATE) && (yytoken == 0)) {
+ // accept empty input
+ yytoken = T_SEMICOLON;
+ continue;
+ }
+
+ int ers = state;
+ int shifts = 0;
+ int reduces = 0;
+ int expected_tokens [3];
+ for (int tk = 0; tk < TERMINAL_COUNT; ++tk)
+ {
+ int k = t_action (ers, tk);
+
+ if (! k)
+ continue;
+ else if (k < 0)
+ ++reduces;
+ else if (spell [tk])
+ {
+ if (shifts < 3)
+ expected_tokens [shifts] = tk;
+ ++shifts;
+ }
+ }
+
+ error_message.clear ();
+ if (shifts && shifts < 3)
+ {
+ bool first = true;
+
+ for (int s = 0; s < shifts; ++s)
+ {
+ if (first)
+ error_message += QLatin1String ("Expected ");
+ else
+ error_message += QLatin1String (", ");
+
+ first = false;
+ error_message += QLatin1String("`");
+ error_message += QLatin1String (spell [expected_tokens [s]]);
+ error_message += QLatin1String("'");
+ }
+ }
+
+ if (error_message.isEmpty())
+ error_message = lexer->errorMessage();
+
+ error_lineno = lexer->startLineNo();
+ error_column = lexer->startColumnNo();
+
+ return false;
+ }
+ }
+
+ return false;
+}
+
+
+bool loadQScript(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ QTextStream ts(&dev);
+ QByteArray codecName;
+ if (!cd.m_codecForSource.isEmpty())
+ codecName = cd.m_codecForSource;
+ else
+ codecName = translator.codecName(); // Just because it should be latin1 already
+ ts.setCodec(QTextCodec::codecForName(codecName));
+ ts.setAutoDetectUnicode(true);
+
+ QString code = ts.readAll();
+ QScript::Lexer lexer;
+ lexer.setCode(code, /*lineNumber=*/1);
+ QScriptParser parser;
+ if (!parser.parse(&lexer, cd.m_sourceFileName, &translator)) {
+ qWarning("%s:%d: %s", qPrintable(cd.m_sourceFileName), parser.errorLineNumber(),
+ qPrintable(parser.errorMessage()));
+ return false;
+ }
+
+ // Java uses UTF-16 internally and Jambi makes UTF-8 for tr() purposes of it.
+ translator.setCodecName("UTF-8");
+ return true;
+}
+
+bool saveQScript(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ Q_UNUSED(dev);
+ Q_UNUSED(translator);
+ cd.appendError(QLatin1String("Cannot save .js files"));
+ return false;
+}
+
+int initQScript()
+{
+ Translator::FileFormat format;
+ format.extension = QLatin1String("js");
+ format.fileType = Translator::FileFormat::SourceCode;
+ format.priority = 0;
+ format.description = QObject::tr("Qt Script source files");
+ format.loader = &loadQScript;
+ format.saver = &saveQScript;
+ Translator::registerFileFormat(format);
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initQScript)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/qscript.g b/tools/linguist/shared/qscript.g
new file mode 100644
index 0000000000..c7ee80db70
--- /dev/null
+++ b/tools/linguist/shared/qscript.g
@@ -0,0 +1,2039 @@
+----------------------------------------------------------------------------
+--
+-- Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+-- Contact: Qt Software Information (qt-info@nokia.com)
+--
+-- This file is part of the Qt Linguist of the Qt Toolkit.
+--
+-- $QT_BEGIN_LICENSE:LGPL$
+-- No Commercial Usage
+-- This file contains pre-release code and may not be distributed.
+-- You may use this file in accordance with the terms and conditions
+-- contained in the either Technology Preview License Agreement or the
+-- Beta Release License Agreement.
+--
+-- GNU Lesser General Public License Usage
+-- Alternatively, this file may be used under the terms of the GNU Lesser
+-- General Public License version 2.1 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.LGPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU Lesser General Public License version 2.1 requirements
+-- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+--
+-- In addition, as a special exception, Nokia gives you certain
+-- additional rights. These rights are described in the Nokia Qt LGPL
+-- Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+-- package.
+--
+-- GNU General Public License Usage
+-- Alternatively, this file may be used under the terms of the GNU
+-- General Public License version 3.0 as published by the Free Software
+-- Foundation and appearing in the file LICENSE.GPL included in the
+-- packaging of this file. Please review the following information to
+-- ensure the GNU General Public License version 3.0 requirements will be
+-- met: http://www.gnu.org/copyleft/gpl.html.
+--
+-- If you are unsure which license is appropriate for your use, please
+-- contact the sales department at qt-sales@nokia.com.
+-- $QT_END_LICENSE$
+--
+-- This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+-- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+--
+----------------------------------------------------------------------------
+
+%parser QScriptGrammar
+%merged_output qscript.cpp
+%expect 3
+%expect-rr 1
+
+%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&="
+%token T_BREAK "break" T_CASE "case" T_CATCH "catch"
+%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue"
+%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/"
+%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
+%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
+%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
+%token T_FUNCTION "function" T_GE ">=" T_GT ">"
+%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
+%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
+%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{"
+%token T_LBRACKET "[" T_LE "<=" T_LPAREN "("
+%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<="
+%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--"
+%token T_NEW "new" T_NOT "!" T_NOT_EQ "!="
+%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|"
+%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+"
+%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?"
+%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
+%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")"
+%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*"
+%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal"
+%token T_SWITCH "switch" T_THIS "this" T_THROW "throw"
+%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof"
+%token T_VAR "var" T_VOID "void" T_WHILE "while"
+%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
+%token T_NULL "null" T_TRUE "true" T_FALSE "false"
+%token T_CONST "const"
+%token T_DEBUGGER "debugger"
+%token T_RESERVED_WORD "reserved word"
+
+%start Program
+
+/.
+#include "translator.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qnumeric.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qtextcodec.h>
+#include <QtCore/qvariant.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+static void recordMessage(
+ Translator *tor, const QString &context, const QString &text, const QString &comment,
+ const QString &extracomment, bool plural, const QString &fileName, int lineNo)
+{
+ TranslatorMessage msg(
+ context, text, comment, QString(),
+ fileName, lineNo, QStringList(),
+ TranslatorMessage::Unfinished, plural);
+ msg.setExtraComment(extracomment.simplified());
+ tor->replace(msg);
+}
+
+
+namespace QScript
+{
+
+class Lexer
+{
+public:
+ Lexer();
+ ~Lexer();
+
+ void setCode(const QString &c, int lineno);
+ int lex();
+
+ int currentLineNo() const { return yylineno; }
+ int currentColumnNo() const { return yycolumn; }
+
+ int startLineNo() const { return startlineno; }
+ int startColumnNo() const { return startcolumn; }
+
+ int endLineNo() const { return currentLineNo(); }
+ int endColumnNo() const
+ { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ enum Error {
+ NoError,
+ IllegalCharacter,
+ UnclosedStringLiteral,
+ IllegalEscapeSequence,
+ IllegalUnicodeEscapeSequence,
+ UnclosedComment,
+ IllegalExponentIndicator,
+ IllegalIdentifier
+ };
+
+ enum ParenthesesState {
+ IgnoreParentheses,
+ CountParentheses,
+ BalancedParentheses
+ };
+
+ enum RegExpBodyPrefix {
+ NoPrefix,
+ EqualPrefix
+ };
+
+ bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+
+ QString pattern;
+ int flags;
+
+ State lexerState() const
+ { return state; }
+
+ QString errorMessage() const
+ { return errmsg; }
+ void setErrorMessage(const QString &err)
+ { errmsg = err; }
+ void setErrorMessage(const char *err)
+ { setErrorMessage(QString::fromLatin1(err)); }
+
+ Error error() const
+ { return err; }
+ void clearError()
+ { err = NoError; }
+
+private:
+ int yylineno;
+ bool done;
+ char *buffer8;
+ QChar *buffer16;
+ uint size8, size16;
+ uint pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ uint pos;
+ void shift(uint p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(ushort c) const;
+ bool isOctalDigit(ushort c) const;
+
+ int matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ ushort singleEscape(ushort c) const;
+ ushort convertOctal(ushort c1, ushort c2,
+ ushort c3) const;
+public:
+ static unsigned char convertHex(ushort c1);
+ static unsigned char convertHex(ushort c1, ushort c2);
+ static QChar convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ static bool isIdentLetter(ushort c);
+ static bool isDecimalDigit(ushort c);
+
+ inline int ival() const { return qsyylval.toInt(); }
+ inline double dval() const { return qsyylval.toDouble(); }
+ inline QString ustr() const { return qsyylval.toString(); }
+ inline QVariant val() const { return qsyylval; }
+
+ const QChar *characterBuffer() const { return buffer16; }
+ int characterCount() const { return pos16; }
+
+private:
+ void record8(ushort c);
+ void record16(QChar c);
+ void recordStartPos();
+
+ int findReservedWord(const QChar *buffer, int size) const;
+
+ void syncProhibitAutomaticSemicolon();
+
+ const QChar *code;
+ uint length;
+ int yycolumn;
+ int startlineno;
+ int startcolumn;
+ int bol; // begin of line
+
+ QVariant qsyylval;
+
+ // current and following unicode characters
+ ushort current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ QString errmsg;
+ Error err;
+
+ bool wantRx;
+ bool check_reserved;
+
+ ParenthesesState parenthesesState;
+ int parenthesesCount;
+ bool prohibitAutomaticSemicolon;
+};
+
+} // namespace QScript
+
+extern double qstrtod(const char *s00, char const **se, bool *ok);
+
+#define shiftWindowsLineBreak() if(current == '\r' && next1 == '\n') shift(1);
+
+namespace QScript {
+
+static int toDigit(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'a') && (c <= 'z'))
+ return 10 + c - 'a';
+ else if ((c >= 'A') && (c <= 'Z'))
+ return 10 + c - 'A';
+ return -1;
+}
+
+double integerFromString(const char *buf, int size, int radix)
+{
+ if (size == 0)
+ return qSNaN();
+
+ double sign = 1.0;
+ int i = 0;
+ if (buf[0] == '+') {
+ ++i;
+ } else if (buf[0] == '-') {
+ sign = -1.0;
+ ++i;
+ }
+
+ if (((size-i) >= 2) && (buf[i] == '0')) {
+ if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ && (radix < 34)) {
+ if ((radix != 0) && (radix != 16))
+ return 0;
+ radix = 16;
+ i += 2;
+ } else {
+ if (radix == 0) {
+ radix = 8;
+ ++i;
+ }
+ }
+ } else if (radix == 0) {
+ radix = 10;
+ }
+
+ int j = i;
+ for ( ; i < size; ++i) {
+ int d = toDigit(buf[i]);
+ if ((d == -1) || (d >= radix))
+ break;
+ }
+ double result;
+ if (j == i) {
+ if (!qstrcmp(buf, "Infinity"))
+ result = qInf();
+ else
+ result = qSNaN();
+ } else {
+ result = 0;
+ double multiplier = 1;
+ for (--i ; i >= j; --i, multiplier *= radix)
+ result += toDigit(buf[i]) * multiplier;
+ }
+ result *= sign;
+ return result;
+}
+
+} // namespace QScript
+
+QScript::Lexer::Lexer()
+ :
+ yylineno(0),
+ size8(128), size16(128), restrKeyword(false),
+ stackToken(-1), pos(0),
+ code(0), length(0),
+ bol(true),
+ current(0), next1(0), next2(0), next3(0),
+ err(NoError),
+ check_reserved(true),
+ parenthesesState(IgnoreParentheses),
+ prohibitAutomaticSemicolon(false)
+{
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new QChar[size16];
+ flags = 0;
+
+}
+
+QScript::Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+void QScript::Lexer::setCode(const QString &c, int lineno)
+{
+ errmsg = QString();
+ yylineno = lineno;
+ yycolumn = 1;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c.unicode();
+ length = c.length();
+ bol = true;
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void QScript::Lexer::shift(uint p)
+{
+ while (p--) {
+ ++pos;
+ ++yycolumn;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void QScript::Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int QScript::Lexer::findReservedWord(const QChar *c, int size) const
+{
+ switch (size) {
+ case 2: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
+ return QScriptGrammar::T_DO;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
+ return QScriptGrammar::T_IF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
+ return QScriptGrammar::T_IN;
+ } break;
+
+ case 3: {
+ if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
+ return QScriptGrammar::T_FOR;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
+ return QScriptGrammar::T_NEW;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
+ return QScriptGrammar::T_TRY;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
+ return QScriptGrammar::T_VAR;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 4: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_CASE;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_ELSE;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
+ return QScriptGrammar::T_THIS;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
+ return QScriptGrammar::T_VOID;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
+ return QScriptGrammar::T_WITH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_TRUE;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
+ return QScriptGrammar::T_NULL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 5: {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('k'))
+ return QScriptGrammar::T_BREAK;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h'))
+ return QScriptGrammar::T_CATCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w'))
+ return QScriptGrammar::T_THROW;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e'))
+ return QScriptGrammar::T_WHILE;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('t'))
+ return QScriptGrammar::T_CONST;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('e'))
+ return QScriptGrammar::T_FALSE;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
+ && c[4] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 6: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
+ return QScriptGrammar::T_DELETE;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
+ return QScriptGrammar::T_RETURN;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
+ return QScriptGrammar::T_SWITCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
+ return QScriptGrammar::T_TYPEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
+ && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 7: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('t'))
+ return QScriptGrammar::T_DEFAULT;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('y'))
+ return QScriptGrammar::T_FINALLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('n'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
+ && c[6] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
+ && c[6] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 8: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
+ return QScriptGrammar::T_CONTINUE;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
+ return QScriptGrammar::T_FUNCTION;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
+ return QScriptGrammar::T_DEBUGGER;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 9: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
+ && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
+ && c[8] == QLatin1Char('e'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('d'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 10: {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
+ return QScriptGrammar::T_INSTANCEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 12: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
+ && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
+ return QScriptGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ } // switch
+
+ return -1;
+}
+
+int QScript::Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ ushort stringType = 0; // either single or double quotes
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = -1;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ recordStartPos();
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ recordStartPos();
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ syncProhibitAutomaticSemicolon();
+ if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
+ // automatic semicolon insertion if program incomplete
+ token = QScriptGrammar::T_SEMICOLON;
+ stackToken = 0;
+ setDone(Other);
+ } else {
+ setDone(Eof);
+ }
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ terminator = true;
+ syncProhibitAutomaticSemicolon();
+ if (restrKeyword) {
+ token = QScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ recordStartPos();
+ state = InString;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ recordStartPos();
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ recordStartPos();
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ recordStartPos();
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ recordStartPos();
+ record8(current);
+ state = InDecimal;
+ } else {
+ recordStartPos();
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ if (terminator && !delimited && !prohibitAutomaticSemicolon
+ && (token == QScriptGrammar::T_PLUS_PLUS
+ || token == QScriptGrammar::T_MINUS_MINUS)) {
+ // automatic semicolon insertion
+ stackToken = token;
+ token = QScriptGrammar::T_SEMICOLON;
+ }
+ setDone(Other);
+ }
+ else {
+ setDone(Bad);
+ err = IllegalCharacter;
+ errmsg = QLatin1String("Illegal character");
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ err = UnclosedStringLiteral;
+ errmsg = QLatin1String("Unclosed string at end of line");
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) &&
+ isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ err = IllegalEscapeSequence;
+ errmsg = QLatin1String("Illegal escape squence");
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ record16(singleEscape(current));
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(QLatin1Char(convertHex(current, next1)));
+ shift(1);
+ } else if (current == stringType) {
+ record16(QLatin1Char('x'));
+ shift(1);
+ setDone(String);
+ } else {
+ record16(QLatin1Char('x'));
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16(QLatin1Char('u'));
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ err = IllegalUnicodeEscapeSequence;
+ errmsg = QLatin1String("Illegal unicode escape sequence");
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ terminator = true;
+ bol = true;
+ if (restrKeyword) {
+ token = QScriptGrammar::T_SEMICOLON;
+ setDone(Other);
+ } else
+ state = Start;
+ } else if (current == 0) {
+ setDone(Eof);
+ }
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ err = UnclosedComment;
+ errmsg = QLatin1String("Unclosed comment at end of file");
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ }
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current))
+ record8(current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Octal);
+ }
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else {
+ setDone(Bad);
+ err = IllegalExponentIndicator;
+ errmsg = QLatin1String("Illegal syntax for exponential number");
+ }
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Number);
+ }
+ break;
+ default:
+ Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current)) {
+ state = Bad;
+ err = IllegalIdentifier;
+ errmsg = QLatin1String("Identifier cannot start with numeric literal");
+ }
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+ double dval = 0;
+ if (state == Number) {
+ dval = qstrtod(buffer8, 0, 0);
+ } else if (state == Hex) { // scan hex numbers
+ dval = QScript::integerFromString(buffer8, pos8, 16);
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ dval = QScript::integerFromString(buffer8, pos8, 8);
+ state = Number;
+ }
+
+ restrKeyword = false;
+ delimited = false;
+
+ switch (parenthesesState) {
+ case IgnoreParentheses:
+ break;
+ case CountParentheses:
+ if (token == QScriptGrammar::T_RPAREN) {
+ --parenthesesCount;
+ if (parenthesesCount == 0)
+ parenthesesState = BalancedParentheses;
+ } else if (token == QScriptGrammar::T_LPAREN) {
+ ++parenthesesCount;
+ }
+ break;
+ case BalancedParentheses:
+ parenthesesState = IgnoreParentheses;
+ break;
+ }
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if(token == QScriptGrammar::T_RBRACE || token == QScriptGrammar::T_SEMICOLON)
+ delimited = true;
+ return token;
+ case Identifier:
+ if ((token = findReservedWord(buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ qsyylval = QString(buffer16, pos16);
+ return QScriptGrammar::T_IDENTIFIER;
+ }
+ if (token == QScriptGrammar::T_CONTINUE || token == QScriptGrammar::T_BREAK
+ || token == QScriptGrammar::T_RETURN || token == QScriptGrammar::T_THROW) {
+ restrKeyword = true;
+ } else if (token == QScriptGrammar::T_IF || token == QScriptGrammar::T_FOR
+ || token == QScriptGrammar::T_WHILE || token == QScriptGrammar::T_WITH) {
+ parenthesesState = CountParentheses;
+ parenthesesCount = 0;
+ } else if (token == QScriptGrammar::T_DO) {
+ parenthesesState = BalancedParentheses;
+ }
+ return token;
+ case String:
+ qsyylval = QString(buffer16, pos16);
+ return QScriptGrammar::T_STRING_LITERAL;
+ case Number:
+ qsyylval = dval;
+ return QScriptGrammar::T_NUMERIC_LITERAL;
+ case Bad:
+ return -1;
+ default:
+ Q_ASSERT(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool QScript::Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool QScript::Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool QScript::Lexer::isIdentLetter(ushort c)
+{
+ /* TODO: allow other legitimate unicode chars */
+ return ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c == '$'
+ || c == '_');
+}
+
+bool QScript::Lexer::isDecimalDigit(ushort c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool QScript::Lexer::isHexDigit(ushort c) const
+{
+ return ((c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F'));
+}
+
+bool QScript::Lexer::isOctalDigit(ushort c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int QScript::Lexer::matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return QScriptGrammar::T_GT_GT_GT_EQ;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_EQ_EQ_EQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_NOT_EQ_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return QScriptGrammar::T_GT_GT_GT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_LT_LT_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return QScriptGrammar::T_GT_GT_EQ;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_NOT_EQ;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ return QScriptGrammar::T_PLUS_PLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ return QScriptGrammar::T_MINUS_MINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_EQ_EQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_PLUS_EQ;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_MINUS_EQ;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_STAR_EQ;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_DIVIDE_EQ;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_AND_EQ;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_XOR_EQ;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_REMAINDER_EQ;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return QScriptGrammar::T_OR_EQ;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return QScriptGrammar::T_LT_LT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return QScriptGrammar::T_GT_GT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return QScriptGrammar::T_AND_AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return QScriptGrammar::T_OR_OR;
+ }
+
+ switch(c1) {
+ case '=': shift(1); return QScriptGrammar::T_EQ;
+ case '>': shift(1); return QScriptGrammar::T_GT;
+ case '<': shift(1); return QScriptGrammar::T_LT;
+ case ',': shift(1); return QScriptGrammar::T_COMMA;
+ case '!': shift(1); return QScriptGrammar::T_NOT;
+ case '~': shift(1); return QScriptGrammar::T_TILDE;
+ case '?': shift(1); return QScriptGrammar::T_QUESTION;
+ case ':': shift(1); return QScriptGrammar::T_COLON;
+ case '.': shift(1); return QScriptGrammar::T_DOT;
+ case '+': shift(1); return QScriptGrammar::T_PLUS;
+ case '-': shift(1); return QScriptGrammar::T_MINUS;
+ case '*': shift(1); return QScriptGrammar::T_STAR;
+ case '/': shift(1); return QScriptGrammar::T_DIVIDE_;
+ case '&': shift(1); return QScriptGrammar::T_AND;
+ case '|': shift(1); return QScriptGrammar::T_OR;
+ case '^': shift(1); return QScriptGrammar::T_XOR;
+ case '%': shift(1); return QScriptGrammar::T_REMAINDER;
+ case '(': shift(1); return QScriptGrammar::T_LPAREN;
+ case ')': shift(1); return QScriptGrammar::T_RPAREN;
+ case '{': shift(1); return QScriptGrammar::T_LBRACE;
+ case '}': shift(1); return QScriptGrammar::T_RBRACE;
+ case '[': shift(1); return QScriptGrammar::T_LBRACKET;
+ case ']': shift(1); return QScriptGrammar::T_RBRACKET;
+ case ';': shift(1); return QScriptGrammar::T_SEMICOLON;
+
+ default: return -1;
+ }
+}
+
+ushort QScript::Lexer::singleEscape(ushort c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+ushort QScript::Lexer::convertOctal(ushort c1, ushort c2,
+ ushort c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char QScript::Lexer::convertHex(ushort c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char QScript::Lexer::convertHex(ushort c1, ushort c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+QChar QScript::Lexer::convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ return QChar((convertHex(c3) << 4) + convertHex(c4),
+ (convertHex(c1) << 4) + convertHex(c2));
+}
+
+void QScript::Lexer::record8(ushort c)
+{
+ Q_ASSERT(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void QScript::Lexer::record16(QChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ QChar *tmp = new QChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(QChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+void QScript::Lexer::recordStartPos()
+{
+ startlineno = yylineno;
+ startcolumn = yycolumn;
+}
+
+bool QScript::Lexer::scanRegExp(RegExpBodyPrefix prefix)
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ if (prefix == EqualPrefix)
+ record16(QLatin1Char('='));
+
+ while (1) {
+ if (isLineTerminator() || current == 0) {
+ errmsg = QLatin1String("Unterminated regular expression literal");
+ return false;
+ }
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape = !lastWasEscape && (current == '\\');
+ }
+ else {
+ pattern = QString(buffer16, pos16);
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ flags = 0;
+ while (isIdentLetter(current)) {
+ record16(current);
+ shift(1);
+ }
+
+ return true;
+}
+
+void QScript::Lexer::syncProhibitAutomaticSemicolon()
+{
+ if (parenthesesState == BalancedParentheses) {
+ // we have seen something like "if (foo)", which means we should
+ // never insert an automatic semicolon at this point, since it would
+ // then be expanded into an empty statement (ECMA-262 7.9.1)
+ prohibitAutomaticSemicolon = true;
+ parenthesesState = IgnoreParentheses;
+ } else {
+ prohibitAutomaticSemicolon = false;
+ }
+}
+
+
+class Translator;
+
+class QScriptParser: protected $table
+{
+public:
+ QVariant val;
+
+ struct Location {
+ int startLine;
+ int startColumn;
+ int endLine;
+ int endColumn;
+ };
+
+public:
+ QScriptParser();
+ ~QScriptParser();
+
+ bool parse(QScript::Lexer *lexer,
+ const QString &fileName,
+ Translator *translator);
+
+ inline QString errorMessage() const
+ { return error_message; }
+ inline int errorLineNumber() const
+ { return error_lineno; }
+ inline int errorColumnNumber() const
+ { return error_column; }
+
+protected:
+ inline void reallocateStack();
+
+ inline QVariant &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline Location &loc(int index)
+ { return location_stack [tos + index - 2]; }
+
+protected:
+ int tos;
+ int stack_size;
+ QVector<QVariant> sym_stack;
+ int *state_stack;
+ Location *location_stack;
+ QString error_message;
+ int error_lineno;
+ int error_column;
+};
+
+inline void QScriptParser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack.resize(stack_size);
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<Location*> (qRealloc(location_stack, stack_size * sizeof(Location)));
+}
+
+inline static bool automatic(QScript::Lexer *lexer, int token)
+{
+ return (token == $table::T_RBRACE)
+ || (token == 0)
+ || lexer->prevTerminator();
+}
+
+QScriptParser::QScriptParser():
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0)
+{
+}
+
+QScriptParser::~QScriptParser()
+{
+ if (stack_size) {
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline QScriptParser::Location location(QScript::Lexer *lexer)
+{
+ QScriptParser::Location loc;
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ loc.endLine = lexer->endLineNo();
+ loc.endColumn = lexer->endColumnNo();
+ return loc;
+}
+
+bool QScriptParser::parse(QScript::Lexer *lexer,
+ const QString &fileName,
+ Translator *translator)
+{
+ const int INITIAL_STATE = 0;
+
+ int yytoken = -1;
+ int saved_yytoken = -1;
+ int identLineNo = -1;
+
+ reallocateStack();
+
+ tos = 0;
+ state_stack[++tos] = INITIAL_STATE;
+
+ while (true)
+ {
+ const int state = state_stack [tos];
+ if (yytoken == -1 && - TERMINAL_COUNT != action_index [state])
+ {
+ if (saved_yytoken == -1)
+ {
+ yytoken = lexer->lex();
+ location_stack [tos] = location(lexer);
+ }
+ else
+ {
+ yytoken = saved_yytoken;
+ saved_yytoken = -1;
+ }
+ }
+
+ int act = t_action (state, yytoken);
+
+ if (act == ACCEPT_STATE)
+ return true;
+
+ else if (act > 0)
+ {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ sym_stack [tos] = lexer->val ();
+ state_stack [tos] = act;
+ location_stack [tos] = location(lexer);
+ yytoken = -1;
+ }
+
+ else if (act < 0)
+ {
+ int r = - act - 1;
+
+ tos -= rhs [r];
+ act = state_stack [tos++];
+
+ switch (r) {
+./
+
+PrimaryExpression: T_THIS ;
+
+PrimaryExpression: T_IDENTIFIER ;
+/.
+case $rule_number: {
+ sym(1) = sym(1).toByteArray();
+ identLineNo = lexer->startLineNo();
+} break;
+./
+
+PrimaryExpression: T_NULL ;
+PrimaryExpression: T_TRUE ;
+PrimaryExpression: T_FALSE ;
+PrimaryExpression: T_NUMERIC_LITERAL ;
+PrimaryExpression: T_STRING_LITERAL ;
+
+PrimaryExpression: T_DIVIDE_ ;
+/:
+#define Q_SCRIPT_REGEXPLITERAL_RULE1 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(QScript::Lexer::NoPrefix);
+ if (!rx) {
+ error_message = lexer->errorMessage();
+ error_lineno = lexer->startLineNo();
+ error_column = lexer->startColumnNo();
+ return false;
+ }
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_EQ ;
+/:
+#define Q_SCRIPT_REGEXPLITERAL_RULE2 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(QScript::Lexer::EqualPrefix);
+ if (!rx) {
+ error_message = lexer->errorMessage();
+ error_lineno = lexer->startLineNo();
+ error_column = lexer->startColumnNo();
+ return false;
+ }
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElisionOpt T_RBRACKET ;
+PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ;
+PrimaryExpression: T_LBRACKET ElementList T_COMMA ElisionOpt T_RBRACKET ;
+PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ;
+PrimaryExpression: T_LPAREN Expression T_RPAREN ;
+ElementList: ElisionOpt AssignmentExpression ;
+ElementList: ElementList T_COMMA ElisionOpt AssignmentExpression ;
+Elision: T_COMMA ;
+Elision: Elision T_COMMA ;
+ElisionOpt: ;
+ElisionOpt: Elision ;
+PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ;
+PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ;
+PropertyName: T_IDENTIFIER ;
+PropertyName: T_STRING_LITERAL ;
+PropertyName: T_NUMERIC_LITERAL ;
+PropertyName: ReservedIdentifier ;
+ReservedIdentifier: T_BREAK ;
+ReservedIdentifier: T_CASE ;
+ReservedIdentifier: T_CATCH ;
+ReservedIdentifier: T_CONST ;
+ReservedIdentifier: T_CONTINUE ;
+ReservedIdentifier: T_DEBUGGER ;
+ReservedIdentifier: T_DEFAULT ;
+ReservedIdentifier: T_DELETE ;
+ReservedIdentifier: T_DO ;
+ReservedIdentifier: T_ELSE ;
+ReservedIdentifier: T_FALSE ;
+ReservedIdentifier: T_FINALLY ;
+ReservedIdentifier: T_FOR ;
+ReservedIdentifier: T_FUNCTION ;
+ReservedIdentifier: T_IF ;
+ReservedIdentifier: T_IN ;
+ReservedIdentifier: T_INSTANCEOF ;
+ReservedIdentifier: T_NEW ;
+ReservedIdentifier: T_NULL ;
+ReservedIdentifier: T_RESERVED_WORD ;
+ReservedIdentifier: T_RETURN ;
+ReservedIdentifier: T_SWITCH ;
+ReservedIdentifier: T_THIS ;
+ReservedIdentifier: T_THROW ;
+ReservedIdentifier: T_TRUE ;
+ReservedIdentifier: T_TRY ;
+ReservedIdentifier: T_TYPEOF ;
+ReservedIdentifier: T_VAR ;
+ReservedIdentifier: T_VOID ;
+ReservedIdentifier: T_WHILE ;
+ReservedIdentifier: T_WITH ;
+PropertyIdentifier: T_IDENTIFIER ;
+PropertyIdentifier: ReservedIdentifier ;
+
+MemberExpression: PrimaryExpression ;
+MemberExpression: FunctionExpression ;
+MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ;
+MemberExpression: MemberExpression T_DOT PropertyIdentifier ;
+MemberExpression: T_NEW MemberExpression Arguments ;
+NewExpression: MemberExpression ;
+NewExpression: T_NEW NewExpression ;
+
+CallExpression: MemberExpression Arguments ;
+/.
+case $rule_number: {
+ QString name = sym(1).toString();
+ if ((name == QLatin1String("qsTranslate")) || (name == QLatin1String("QT_TRANSLATE_NOOP"))) {
+ QVariantList args = sym(2).toList();
+ if (args.size() < 2) {
+ qWarning("%s:%d: %s() requires at least two arguments",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ if ((args.at(0).type() != QVariant::String)
+ || (args.at(1).type() != QVariant::String)) {
+ qWarning("%s:%d: %s(): both arguments must be literal strings",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ QString context = args.at(0).toString();
+ QString text = args.at(1).toString();
+ QString comment = args.value(2).toString();
+ QString extracomment;
+ bool plural = (args.size() > 4);
+ recordMessage(translator, context, text, comment, extracomment,
+ plural, fileName, identLineNo);
+ }
+ }
+ } else if ((name == QLatin1String("qsTr")) || (name == QLatin1String("QT_TR_NOOP"))) {
+ QVariantList args = sym(2).toList();
+ if (args.size() < 1) {
+ qWarning("%s:%d: %s() requires at least one argument",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ if (args.at(0).type() != QVariant::String) {
+ qWarning("%s:%d: %s(): text to translate must be a literal string",
+ qPrintable(fileName), identLineNo, qPrintable(name));
+ } else {
+ QString context = QFileInfo(fileName).baseName();
+ QString text = args.at(0).toString();
+ QString comment = args.value(1).toString();
+ QString extracomment;
+ bool plural = (args.size() > 2);
+ recordMessage(translator, context, text, comment, extracomment,
+ plural, fileName, identLineNo);
+ }
+ }
+ }
+} break;
+./
+
+CallExpression: CallExpression Arguments ;
+CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ;
+CallExpression: CallExpression T_DOT PropertyIdentifier ;
+
+Arguments: T_LPAREN T_RPAREN ;
+/.
+case $rule_number: {
+ sym(1) = QVariantList();
+} break;
+./
+
+Arguments: T_LPAREN ArgumentList T_RPAREN ;
+/.
+case $rule_number: {
+ sym(1) = sym(2);
+} break;
+./
+
+ArgumentList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1) = QVariantList() << sym(1);
+} break;
+./
+
+ArgumentList: ArgumentList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1) = sym(1).toList() << sym(3);
+} break;
+./
+
+LeftHandSideExpression: NewExpression ;
+LeftHandSideExpression: CallExpression ;
+PostfixExpression: LeftHandSideExpression ;
+PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ;
+PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ;
+UnaryExpression: PostfixExpression ;
+UnaryExpression: T_DELETE UnaryExpression ;
+UnaryExpression: T_VOID UnaryExpression ;
+UnaryExpression: T_TYPEOF UnaryExpression ;
+UnaryExpression: T_PLUS_PLUS UnaryExpression ;
+UnaryExpression: T_MINUS_MINUS UnaryExpression ;
+UnaryExpression: T_PLUS UnaryExpression ;
+UnaryExpression: T_MINUS UnaryExpression ;
+UnaryExpression: T_TILDE UnaryExpression ;
+UnaryExpression: T_NOT UnaryExpression ;
+MultiplicativeExpression: UnaryExpression ;
+MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ;
+MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ;
+MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ;
+AdditiveExpression: MultiplicativeExpression ;
+
+AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ if ((sym(1).type() == QVariant::String) || (sym(3).type() == QVariant::String))
+ sym(1) = sym(1).toString() + sym(3).toString();
+ else
+ sym(1) = QVariant();
+} break;
+./
+
+AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ;
+ShiftExpression: AdditiveExpression ;
+ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ;
+ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ;
+ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ;
+RelationalExpression: ShiftExpression ;
+RelationalExpression: RelationalExpression T_LT ShiftExpression ;
+RelationalExpression: RelationalExpression T_GT ShiftExpression ;
+RelationalExpression: RelationalExpression T_LE ShiftExpression ;
+RelationalExpression: RelationalExpression T_GE ShiftExpression ;
+RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ;
+RelationalExpression: RelationalExpression T_IN ShiftExpression ;
+RelationalExpressionNotIn: ShiftExpression ;
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ;
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ;
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ;
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ;
+RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ;
+EqualityExpression: RelationalExpression ;
+EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ;
+EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ;
+EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ;
+EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ;
+EqualityExpressionNotIn: RelationalExpressionNotIn ;
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ;
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn;
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ;
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ;
+BitwiseANDExpression: EqualityExpression ;
+BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ;
+BitwiseANDExpressionNotIn: EqualityExpressionNotIn ;
+BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ;
+BitwiseXORExpression: BitwiseANDExpression ;
+BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ;
+BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ;
+BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ;
+BitwiseORExpression: BitwiseXORExpression ;
+BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ;
+BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ;
+BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ;
+LogicalANDExpression: BitwiseORExpression ;
+LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ;
+LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ;
+LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ;
+LogicalORExpression: LogicalANDExpression ;
+LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ;
+LogicalORExpressionNotIn: LogicalANDExpressionNotIn ;
+LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ;
+ConditionalExpression: LogicalORExpression ;
+ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ;
+ConditionalExpressionNotIn: LogicalORExpressionNotIn ;
+ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ;
+AssignmentExpression: ConditionalExpression ;
+AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ;
+AssignmentExpressionNotIn: ConditionalExpressionNotIn ;
+AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ;
+AssignmentOperator: T_EQ ;
+AssignmentOperator: T_STAR_EQ ;
+AssignmentOperator: T_DIVIDE_EQ ;
+AssignmentOperator: T_REMAINDER_EQ ;
+AssignmentOperator: T_PLUS_EQ ;
+AssignmentOperator: T_MINUS_EQ ;
+AssignmentOperator: T_LT_LT_EQ ;
+AssignmentOperator: T_GT_GT_EQ ;
+AssignmentOperator: T_GT_GT_GT_EQ ;
+AssignmentOperator: T_AND_EQ ;
+AssignmentOperator: T_XOR_EQ ;
+AssignmentOperator: T_OR_EQ ;
+Expression: AssignmentExpression ;
+Expression: Expression T_COMMA AssignmentExpression ;
+ExpressionOpt: ;
+ExpressionOpt: Expression ;
+ExpressionNotIn: AssignmentExpressionNotIn ;
+ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ;
+ExpressionNotInOpt: ;
+ExpressionNotInOpt: ExpressionNotIn ;
+
+Statement: Block ;
+Statement: VariableStatement ;
+Statement: EmptyStatement ;
+Statement: ExpressionStatement ;
+Statement: IfStatement ;
+Statement: IterationStatement ;
+Statement: ContinueStatement ;
+Statement: BreakStatement ;
+Statement: ReturnStatement ;
+Statement: WithStatement ;
+Statement: LabelledStatement ;
+Statement: SwitchStatement ;
+Statement: ThrowStatement ;
+Statement: TryStatement ;
+Statement: DebuggerStatement ;
+
+Block: T_LBRACE StatementListOpt T_RBRACE ;
+StatementList: Statement ;
+StatementList: StatementList Statement ;
+StatementListOpt: ;
+StatementListOpt: StatementList ;
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
+VariableDeclarationKind: T_CONST ;
+VariableDeclarationKind: T_VAR ;
+VariableDeclarationList: VariableDeclaration ;
+VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ;
+VariableDeclarationListNotIn: VariableDeclarationNotIn ;
+VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ;
+VariableDeclaration: T_IDENTIFIER InitialiserOpt ;
+VariableDeclarationNotIn: T_IDENTIFIER InitialiserNotInOpt ;
+Initialiser: T_EQ AssignmentExpression ;
+InitialiserOpt: ;
+InitialiserOpt: Initialiser ;
+InitialiserNotIn: T_EQ AssignmentExpressionNotIn ;
+InitialiserNotInOpt: ;
+InitialiserNotInOpt: InitialiserNotIn ;
+EmptyStatement: T_SEMICOLON ;
+ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ExpressionStatement: Expression T_SEMICOLON ;
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ;
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ;
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ;
+IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ;
+IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ;
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ;
+ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE T_SEMICOLON ;
+ContinueStatement: T_CONTINUE T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE T_IDENTIFIER T_SEMICOLON ;
+BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK T_SEMICOLON ;
+BreakStatement: T_BREAK T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK T_IDENTIFIER T_SEMICOLON ;
+ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ;
+WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ;
+SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ;
+CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ;
+CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ;
+CaseClauses: CaseClause ;
+CaseClauses: CaseClauses CaseClause ;
+CaseClausesOpt: ;
+CaseClausesOpt: CaseClauses ;
+CaseClause: T_CASE Expression T_COLON StatementListOpt ;
+DefaultClause: T_DEFAULT T_COLON StatementListOpt ;
+LabelledStatement: T_IDENTIFIER T_COLON Statement ;
+ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ThrowStatement: T_THROW Expression T_SEMICOLON ;
+TryStatement: T_TRY Block Catch ;
+TryStatement: T_TRY Block Finally ;
+TryStatement: T_TRY Block Catch Finally ;
+Catch: T_CATCH T_LPAREN T_IDENTIFIER T_RPAREN Block ;
+Finally: T_FINALLY Block ;
+DebuggerStatement: T_DEBUGGER ;
+FunctionDeclaration: T_FUNCTION T_IDENTIFIER T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+FormalParameterList: T_IDENTIFIER ;
+FormalParameterList: FormalParameterList T_COMMA T_IDENTIFIER ;
+FormalParameterListOpt: ;
+FormalParameterListOpt: FormalParameterList ;
+FunctionBodyOpt: ;
+FunctionBodyOpt: FunctionBody ;
+FunctionBody: SourceElements ;
+Program: SourceElements ;
+SourceElements: SourceElement ;
+SourceElements: SourceElements SourceElement ;
+SourceElement: Statement ;
+SourceElement: FunctionDeclaration ;
+IdentifierOpt: ;
+IdentifierOpt: T_IDENTIFIER ;
+PropertyNameAndValueListOpt: ;
+PropertyNameAndValueListOpt: PropertyNameAndValueList ;
+
+/.
+ } // switch
+
+ state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT);
+
+ if (rhs[r] > 1) {
+ location_stack[tos - 1].endLine = location_stack[tos + rhs[r] - 2].endLine;
+ location_stack[tos - 1].endColumn = location_stack[tos + rhs[r] - 2].endColumn;
+ location_stack[tos] = location_stack[tos + rhs[r] - 1];
+ }
+ }
+
+ else
+ {
+ if (saved_yytoken == -1 && automatic (lexer, yytoken) && t_action (state, T_AUTOMATIC_SEMICOLON) > 0)
+ {
+ saved_yytoken = yytoken;
+ yytoken = T_SEMICOLON;
+ continue;
+ }
+
+ else if ((state == INITIAL_STATE) && (yytoken == 0)) {
+ // accept empty input
+ yytoken = T_SEMICOLON;
+ continue;
+ }
+
+ int ers = state;
+ int shifts = 0;
+ int reduces = 0;
+ int expected_tokens [3];
+ for (int tk = 0; tk < TERMINAL_COUNT; ++tk)
+ {
+ int k = t_action (ers, tk);
+
+ if (! k)
+ continue;
+ else if (k < 0)
+ ++reduces;
+ else if (spell [tk])
+ {
+ if (shifts < 3)
+ expected_tokens [shifts] = tk;
+ ++shifts;
+ }
+ }
+
+ error_message.clear ();
+ if (shifts && shifts < 3)
+ {
+ bool first = true;
+
+ for (int s = 0; s < shifts; ++s)
+ {
+ if (first)
+ error_message += QLatin1String ("Expected ");
+ else
+ error_message += QLatin1String (", ");
+
+ first = false;
+ error_message += QLatin1String("`");
+ error_message += QLatin1String (spell [expected_tokens [s]]);
+ error_message += QLatin1String("'");
+ }
+ }
+
+ if (error_message.isEmpty())
+ error_message = lexer->errorMessage();
+
+ error_lineno = lexer->startLineNo();
+ error_column = lexer->startColumnNo();
+
+ return false;
+ }
+ }
+
+ return false;
+}
+
+
+bool loadQScript(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ QTextStream ts(&dev);
+ QByteArray codecName;
+ if (!cd.m_codecForSource.isEmpty())
+ codecName = cd.m_codecForSource;
+ else
+ codecName = translator.codecName(); // Just because it should be latin1 already
+ ts.setCodec(QTextCodec::codecForName(codecName));
+ ts.setAutoDetectUnicode(true);
+
+ QString code = ts.readAll();
+ QScript::Lexer lexer;
+ lexer.setCode(code, /*lineNumber=*/1);
+ QScriptParser parser;
+ if (!parser.parse(&lexer, cd.m_sourceFileName, &translator)) {
+ qWarning("%s:%d: %s", qPrintable(cd.m_sourceFileName), parser.errorLineNumber(),
+ qPrintable(parser.errorMessage()));
+ return false;
+ }
+
+ // Java uses UTF-16 internally and Jambi makes UTF-8 for tr() purposes of it.
+ translator.setCodecName("UTF-8");
+ return true;
+}
+
+bool saveQScript(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ Q_UNUSED(dev);
+ Q_UNUSED(translator);
+ cd.appendError(QLatin1String("Cannot save .js files"));
+ return false;
+}
+
+int initQScript()
+{
+ Translator::FileFormat format;
+ format.extension = QLatin1String("js");
+ format.fileType = Translator::FileFormat::SourceCode;
+ format.priority = 0;
+ format.description = QObject::tr("Qt Script source files");
+ format.loader = &loadQScript;
+ format.saver = &saveQScript;
+ Translator::registerFileFormat(format);
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initQScript)
+
+QT_END_NAMESPACE
+./
diff --git a/tools/linguist/shared/simtexth.cpp b/tools/linguist/shared/simtexth.cpp
new file mode 100644
index 0000000000..0556ed63a7
--- /dev/null
+++ b/tools/linguist/shared/simtexth.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "simtexth.h"
+#include "translator.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<TranslatorMessage> TML;
+
+/*
+ How similar are two texts? The approach used here relies on co-occurrence
+ matrices and is very efficient.
+
+ Let's see with an example: how similar are "here" and "hither"? The
+ co-occurrence matrix M for "here" is M[h,e] = 1, M[e,r] = 1, M[r,e] = 1, and 0
+ elsewhere; the matrix N for "hither" is N[h,i] = 1, N[i,t] = 1, ...,
+ N[h,e] = 1, N[e,r] = 1, and 0 elsewhere. The union U of both matrices is the
+ matrix U[i,j] = max { M[i,j], N[i,j] }, and the intersection V is
+ V[i,j] = min { M[i,j], N[i,j] }. The score for a pair of texts is
+
+ score = (sum of V[i,j] over all i, j) / (sum of U[i,j] over all i, j),
+
+ a formula suggested by Arnt Gulbrandsen. Here we have
+
+ score = 2 / 6,
+
+ or one third.
+
+ The implementation differs from this in a few details. Most importantly,
+ repetitions are ignored; for input "xxx", M[x,x] equals 1, not 2.
+*/
+
+/*
+ Every character is assigned to one of 20 buckets so that the co-occurrence
+ matrix requires only 20 * 20 = 400 bits, not 256 * 256 = 65536 bits or even
+ more if we want the whole Unicode. Which character falls in which bucket is
+ arbitrary.
+
+ The second half of the table is a replica of the first half, because of
+ laziness.
+*/
+static const int indexOf[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// ! " # $ % & ' ( ) * + , - . /
+ 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0,
+// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
+ 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15,
+// @ A B C D E F G H I J K L M N O
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14,
+// P Q R S T U V W X Y Z [ \ ] ^ _
+ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0,
+// ` a b c d e f g h i j k l m n o
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14,
+// p q r s t u v w x y z { | } ~
+ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0,
+ 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14,
+ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14,
+ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0
+};
+
+/*
+ The entry bitCount[i] (for i between 0 and 255) is the number of bits used to
+ represent i in binary.
+*/
+static const int bitCount[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+struct CoMatrix
+{
+ /*
+ The matrix has 20 * 20 = 400 entries. This requires 50 bytes, or 13
+ words. Some operations are performed on words for more efficiency.
+ */
+ union {
+ quint8 b[52];
+ quint32 w[13];
+ };
+
+ CoMatrix() { memset( b, 0, 52 ); }
+
+ CoMatrix(const QString &str)
+ {
+ QByteArray ba = str.toUtf8();
+ const char *text = ba.constData();
+ char c = '\0', d;
+ memset( b, 0, 52 );
+ /*
+ The Knuth books are not in the office only for show; they help make
+ loops 30% faster and 20% as readable.
+ */
+ while ( (d = *text) != '\0' ) {
+ setCoOccurence( c, d );
+ if ( (c = *++text) != '\0' ) {
+ setCoOccurence( d, c );
+ text++;
+ }
+ }
+ }
+
+ void setCoOccurence( char c, char d ) {
+ int k = indexOf[(uchar) c] + 20 * indexOf[(uchar) d];
+ b[k >> 3] |= (1 << (k & 0x7));
+ }
+
+ int worth() const {
+ int w = 0;
+ for ( int i = 0; i < 50; i++ )
+ w += bitCount[b[i]];
+ return w;
+ }
+};
+
+static inline CoMatrix reunion(const CoMatrix &m, const CoMatrix &n)
+{
+ CoMatrix p;
+ for (int i = 0; i < 13; ++i)
+ p.w[i] = m.w[i] | n.w[i];
+ return p;
+}
+
+static inline CoMatrix intersection(const CoMatrix &m, const CoMatrix &n)
+{
+ CoMatrix p;
+ for (int i = 0; i < 13; ++i)
+ p.w[i] = m.w[i] & n.w[i];
+ return p;
+}
+
+StringSimilarityMatcher::StringSimilarityMatcher(const QString &stringToMatch)
+{
+ m_cm = new CoMatrix(stringToMatch);
+ m_length = stringToMatch.length();
+}
+
+int StringSimilarityMatcher::getSimilarityScore(const QString &strCandidate)
+{
+ CoMatrix cmTarget(strCandidate);
+ int delta = qAbs(m_length - strCandidate.size());
+ int score = ( (intersection(*m_cm, cmTarget).worth() + 1) << 10 ) /
+ ( reunion(*m_cm, cmTarget).worth() + (delta << 1) + 1 );
+ return score;
+}
+
+StringSimilarityMatcher::~StringSimilarityMatcher()
+{
+ delete m_cm;
+}
+
+/**
+ * Checks how similar two strings are.
+ * The return value is the score, and a higher score is more similar
+ * than one with a low score.
+ * Linguist considers a score over 190 to be a good match.
+ * \sa StringSimilarityMatcher
+ */
+int getSimilarityScore(const QString &str1, const QString &str2)
+{
+ CoMatrix cmTarget(str2);
+ CoMatrix cm(str1);
+ int delta = qAbs(str1.size() - str2.size());
+
+ int score = ( (intersection(cm, cmTarget).worth() + 1) << 10 )
+ / ( reunion(cm, cmTarget).worth() + (delta << 1) + 1 );
+
+ return score;
+}
+
+CandidateList similarTextHeuristicCandidates(const Translator *tor,
+ const QString &text, int maxCandidates)
+{
+ QList<int> scores;
+ CandidateList candidates;
+
+ TML all = tor->translatedMessages();
+
+ foreach (const TranslatorMessage &mtm, all) {
+ if (mtm.type() == TranslatorMessage::Unfinished
+ || mtm.translation().isEmpty())
+ continue;
+
+ QString s = mtm.sourceText();
+ int score = getSimilarityScore(s, text);
+
+ if (candidates.size() == maxCandidates && score > scores[maxCandidates - 1] )
+ candidates.removeLast();
+
+ if (candidates.size() < maxCandidates && score >= textSimilarityThreshold) {
+ Candidate cand( s, mtm.translation() );
+
+ int i;
+ for (i = 0; i < candidates.size(); i++) {
+ if (score >= scores.at(i)) {
+ if (score == scores.at(i)) {
+ if (candidates.at(i) == cand)
+ goto continue_outer_loop;
+ } else {
+ break;
+ }
+ }
+ }
+ scores.insert(i, score);
+ candidates.insert(i, cand);
+ }
+ continue_outer_loop:
+ ;
+ }
+ return candidates;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/simtexth.h b/tools/linguist/shared/simtexth.h
new file mode 100644
index 0000000000..e3cad91e59
--- /dev/null
+++ b/tools/linguist/shared/simtexth.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SIMTEXTH_H
+#define SIMTEXTH_H
+
+const int textSimilarityThreshold = 190;
+
+#include <QString>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+class Translator;
+
+struct Candidate
+{
+ Candidate() {}
+ Candidate(const QString& source0, const QString &target0)
+ : source(source0), target(target0)
+ {}
+
+ QString source;
+ QString target;
+};
+
+inline bool operator==( const Candidate& c, const Candidate& d ) {
+ return c.target == d.target && c.source == d.source;
+}
+inline bool operator!=( const Candidate& c, const Candidate& d ) {
+ return !operator==( c, d );
+}
+
+typedef QList<Candidate> CandidateList;
+
+struct CoMatrix;
+/**
+ * This class is more efficient for searching through a large array of candidate strings, since we only
+ * have to construct the CoMatrix for the \a stringToMatch once,
+ * after that we just call getSimilarityScore(strCandidate).
+ * \sa getSimilarityScore
+ */
+class StringSimilarityMatcher {
+public:
+ StringSimilarityMatcher(const QString &stringToMatch);
+ ~StringSimilarityMatcher();
+ int getSimilarityScore(const QString &strCandidate);
+
+private:
+ CoMatrix *m_cm;
+ int m_length;
+};
+
+int getSimilarityScore(const QString &str1, const QString &str2);
+
+CandidateList similarTextHeuristicCandidates( const Translator *tor,
+ const QString &text,
+ int maxCandidates );
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/shared/translator.cpp b/tools/linguist/shared/translator.cpp
new file mode 100644
index 0000000000..3b5e8f3fba
--- /dev/null
+++ b/tools/linguist/shared/translator.cpp
@@ -0,0 +1,559 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include "simtexth.h"
+
+#include <stdio.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+#include <private/qtranslator_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Translator::Translator() :
+ m_codecName("ISO-8859-1"),
+ m_locationsType(AbsoluteLocations)
+{
+}
+
+void Translator::registerFileFormat(const FileFormat &format)
+{
+ //qDebug() << "Translator: Registering format " << format.extension;
+ QList<Translator::FileFormat> &formats = registeredFileFormats();
+ for (int i = 0; i < formats.size(); ++i)
+ if (format.fileType == formats[i].fileType && format.priority < formats[i].priority) {
+ formats.insert(i, format);
+ return;
+ }
+ formats.append(format);
+}
+
+QList<Translator::FileFormat> &Translator::registeredFileFormats()
+{
+ static QList<Translator::FileFormat> theFormats;
+ return theFormats;
+}
+
+void Translator::replace(const TranslatorMessage &msg)
+{
+ int index = m_messages.indexOf(msg);
+ if (index == -1)
+ m_messages.append(msg);
+ else
+ m_messages[index] = msg;
+}
+
+void Translator::replaceSorted(const TranslatorMessage &msg)
+{
+ int index = m_messages.indexOf(msg);
+ if (index == -1)
+ appendSorted(msg);
+ else
+ m_messages[index] = msg;
+}
+
+void Translator::extend(const TranslatorMessage &msg)
+{
+ int index = m_messages.indexOf(msg);
+ if (index == -1) {
+ m_messages.append(msg);
+ } else {
+ m_messages[index].addReferenceUniq(msg.fileName(), msg.lineNumber());
+ if (!msg.extraComment().isEmpty()) {
+ QString cmt = m_messages[index].extraComment();
+ if (!cmt.isEmpty())
+ cmt.append(QLatin1String("\n----------\n"));
+ cmt.append(msg.extraComment());
+ m_messages[index].setExtraComment(cmt);
+ }
+ }
+}
+
+void Translator::append(const TranslatorMessage &msg)
+{
+ m_messages.append(msg);
+}
+
+void Translator::appendSorted(const TranslatorMessage &msg)
+{
+ int msgLine = msg.lineNumber();
+ if (msgLine < 0) {
+ m_messages.append(msg);
+ return;
+ }
+
+ int bestIdx = 0; // Best insertion point found so far
+ int bestScore = 0; // Its category: 0 = no hit, 1 = pre or post, 2 = middle
+ int bestSize = 0; // The length of the region. Longer is better within one category.
+
+ // The insertion point to use should this region turn out to be the best one so far
+ int thisIdx = 0;
+ int thisScore = 0;
+ int thisSize = 0;
+ // Working vars
+ int prevLine = 0;
+ int curIdx = 0;
+ foreach (const TranslatorMessage &mit, m_messages) {
+ bool sameFile = mit.fileName() == msg.fileName();
+ int curLine;
+ if (sameFile && (curLine = mit.lineNumber()) >= prevLine) {
+ if (msgLine >= prevLine && msgLine < curLine) {
+ thisIdx = curIdx;
+ thisScore = thisSize ? 2 : 1;
+ }
+ ++thisSize;
+ prevLine = curLine;
+ } else {
+ if (thisSize) {
+ if (!thisScore) {
+ thisIdx = curIdx;
+ thisScore = 1;
+ }
+ if (thisScore > bestScore || (thisScore == bestScore && thisSize > bestSize)) {
+ bestIdx = thisIdx;
+ bestScore = thisScore;
+ bestSize = thisSize;
+ }
+ thisScore = 0;
+ thisSize = sameFile ? 1 : 0;
+ prevLine = 0;
+ }
+ }
+ ++curIdx;
+ }
+ if (thisSize && !thisScore) {
+ thisIdx = curIdx;
+ thisScore = 1;
+ }
+ if (thisScore > bestScore || (thisScore == bestScore && thisSize > bestSize))
+ m_messages.insert(thisIdx, msg);
+ else if (bestScore)
+ m_messages.insert(bestIdx, msg);
+ else
+ m_messages.append(msg);
+}
+
+static QString guessFormat(const QString &filename, const QString &format)
+{
+ if (format != QLatin1String("auto"))
+ return format;
+
+ foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
+ if (filename.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive))
+ return fmt.extension;
+ }
+
+ // the default format.
+ // FIXME: change to something more widely distributed later.
+ return QLatin1String("ts");
+}
+
+bool Translator::load(const QString &filename, ConversionData &cd, const QString &format)
+{
+ cd.m_sourceDir = QFileInfo(filename).absoluteDir();
+ cd.m_sourceFileName = filename;
+
+ QFile file;
+ if (filename.isEmpty() || filename == QLatin1String("-")) {
+ if (!file.open(stdin, QIODevice::ReadOnly)) {
+ cd.appendError(QString::fromLatin1("Cannot open stdin!? (%1)")
+ .arg(file.errorString()));
+ return false;
+ }
+ } else {
+ file.setFileName(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ cd.appendError(QString::fromLatin1("Cannot open %1: %2")
+ .arg(filename, file.errorString()));
+ return false;
+ }
+ }
+
+ QString fmt = guessFormat(filename, format);
+
+ foreach (const FileFormat &format, registeredFileFormats()) {
+ if (fmt == format.extension) {
+ if (format.loader)
+ return (*format.loader)(*this, file, cd);
+ cd.appendError(QString(QLatin1String("No loader for format %1 found"))
+ .arg(fmt));
+ return false;
+ }
+ }
+
+ cd.appendError(QString(QLatin1String("Unknown format %1 for file %2"))
+ .arg(format, filename));
+ return false;
+}
+
+
+bool Translator::save(const QString &filename, ConversionData &cd, const QString &format) const
+{
+ QFile file;
+ if (filename.isEmpty() || filename == QLatin1String("-")) {
+ if (!file.open(stdout, QIODevice::WriteOnly)) {
+ cd.appendError(QString::fromLatin1("Cannot open stdout!? (%1)")
+ .arg(file.errorString()));
+ return false;
+ }
+ } else {
+ file.setFileName(filename);
+ if (!file.open(QIODevice::WriteOnly)) {
+ cd.appendError(QString::fromLatin1("Cannot create %1: %2")
+ .arg(filename, file.errorString()));
+ return false;
+ }
+ }
+
+ QString fmt = guessFormat(filename, format);
+ cd.m_targetDir = QFileInfo(filename).absoluteDir();
+
+ foreach (const FileFormat &format, registeredFileFormats()) {
+ if (fmt == format.extension) {
+ if (format.saver)
+ return (*format.saver)(*this, file, cd);
+ cd.appendError(QString(QLatin1String("Cannot save %1 files")).arg(fmt));
+ return false;
+ }
+ }
+
+ cd.appendError(QString(QLatin1String("Unknown format %1 for file %2"))
+ .arg(format).arg(filename));
+ return false;
+}
+
+QString Translator::makeLanguageCode(QLocale::Language language, QLocale::Country country)
+{
+ QLocale locale(language, country);
+ if (country == QLocale::AnyCountry) {
+ QString languageCode = locale.name().section(QLatin1Char('_'), 0, 0);
+ if (languageCode.length() <= 3)
+ return languageCode;
+ return QString();
+ } else {
+ return locale.name();
+ }
+}
+
+void Translator::languageAndCountry(const QString &languageCode,
+ QLocale::Language *lang, QLocale::Country *country)
+{
+ QLocale locale(languageCode);
+ if (lang)
+ *lang = locale.language();
+
+ if (country) {
+ if (languageCode.indexOf(QLatin1Char('_')) != -1)
+ *country = locale.country();
+ else
+ *country = QLocale::AnyCountry;
+ }
+}
+
+bool Translator::release(QFile *iod, ConversionData &cd) const
+{
+ foreach (const FileFormat &format, registeredFileFormats()) {
+ if (format.extension == QLatin1String("qm"))
+ return (*format.saver)(*this, *iod, cd);
+ }
+ cd.appendError(QLatin1String("No .qm saver available."));
+ return false;
+}
+
+bool Translator::contains(const QString &context,
+ const QString &sourceText, const QString &comment) const
+{
+ return m_messages.contains(TranslatorMessage(context, sourceText, comment,
+ QString(), QString(), 0));
+}
+
+TranslatorMessage Translator::find(const QString &context,
+ const QString &sourceText, const QString &comment) const
+{
+ TranslatorMessage needle(context, sourceText, comment, QString(), QString(), 0);
+ int index = m_messages.indexOf(needle);
+ return index == -1 ? TranslatorMessage() : m_messages.at(index);
+}
+
+TranslatorMessage Translator::find(const QString &context,
+ const QString &comment, const TranslatorMessage::References &refs) const
+{
+ if (!refs.isEmpty()) {
+ for (TMM::ConstIterator it = m_messages.constBegin(); it != m_messages.constEnd(); ++it) {
+ if (it->context() == context && it->comment() == comment)
+ foreach (const TranslatorMessage::Reference &itref, it->allReferences())
+ foreach (const TranslatorMessage::Reference &ref, refs)
+ if (itref == ref)
+ return *it;
+ }
+ }
+ return TranslatorMessage();
+}
+
+bool Translator::contains(const QString &context) const
+{
+ foreach (const TranslatorMessage &msg, m_messages)
+ if (msg.context() == context && msg.sourceText().isEmpty())
+ return true;
+ return false;
+}
+
+TranslatorMessage Translator::find(const QString &context) const
+{
+ foreach (const TranslatorMessage &msg, m_messages)
+ if (msg.context() == context && msg.sourceText().isEmpty())
+ return msg;
+ return TranslatorMessage();
+}
+
+void Translator::stripObsoleteMessages()
+{
+ TMM newmm;
+ for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
+ if (it->type() != TranslatorMessage::Obsolete)
+ newmm.append(*it);
+ m_messages = newmm;
+}
+
+void Translator::stripFinishedMessages()
+{
+ TMM newmm;
+ for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
+ if (it->type() != TranslatorMessage::Finished)
+ newmm.append(*it);
+ m_messages = newmm;
+}
+
+void Translator::stripEmptyContexts()
+{
+ TMM newmm;
+ for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
+ if (it->sourceText() != QLatin1String(ContextComment))
+ newmm.append(*it);
+ m_messages = newmm;
+}
+
+void Translator::stripNonPluralForms()
+{
+ TMM newmm;
+ for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
+ if (it->isPlural())
+ newmm.append(*it);
+ m_messages = newmm;
+}
+
+void Translator::stripIdenticalSourceTranslations()
+{
+ TMM newmm;
+ for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) {
+ // we need to have just one translation, and it be equal to the source
+ if (it->translations().count() != 1)
+ newmm.append(*it);
+ else if (it->translation() != it->sourceText())
+ newmm.append(*it);
+ }
+ m_messages = newmm;
+}
+
+void Translator::dropTranslations()
+{
+ for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ++it) {
+ if (it->type() == TranslatorMessage::Finished)
+ it->setType(TranslatorMessage::Unfinished);
+ it->setTranslation(QString());
+ }
+}
+
+QList<TranslatorMessage> Translator::findDuplicates() const
+{
+ QHash<TranslatorMessage, int> dups;
+ foreach (const TranslatorMessage &msg, m_messages)
+ dups[msg]++;
+ QList<TranslatorMessage> ret;
+ QHash<TranslatorMessage, int>::ConstIterator it = dups.constBegin(), end = dups.constEnd();
+ for (; it != end; ++it)
+ if (it.value() > 1)
+ ret.append(it.key());
+ return ret;
+}
+
+// Used by lupdate to be able to search using absolute paths during merging
+void Translator::makeFileNamesAbsolute(const QDir &originalPath)
+{
+ TMM newmm;
+ for (TMM::iterator it = m_messages.begin(); it != m_messages.end(); ++it) {
+ TranslatorMessage msg = *it;
+ msg.setReferences(TranslatorMessage::References());
+ foreach (const TranslatorMessage::Reference &ref, it->allReferences()) {
+ QString fileName = ref.fileName();
+ QFileInfo fi (fileName);
+ if (fi.isRelative())
+ fileName = originalPath.absoluteFilePath(fileName);
+ msg.addReference(fileName, ref.lineNumber());
+ }
+ newmm.append(msg);
+ }
+ m_messages = newmm;
+}
+
+QList<TranslatorMessage> Translator::messages() const
+{
+ return m_messages;
+}
+
+QList<TranslatorMessage> Translator::translatedMessages() const
+{
+ TMM result;
+ for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
+ if (it->type() == TranslatorMessage::Finished)
+ result.append(*it);
+ return result;
+}
+
+QStringList Translator::normalizedTranslations(const TranslatorMessage &msg,
+ QLocale::Language language, QLocale::Country country)
+{
+ QStringList translations = msg.translations();
+ int numTranslations = 1;
+ if (msg.isPlural() && language != QLocale::C) {
+ QStringList forms;
+ if (getNumerusInfo(language, country, 0, &forms))
+ numTranslations = forms.count(); // includes singular
+ }
+
+ // make sure that the stringlist always have the size of the
+ // language's current numerus, or 1 if its not plural
+ if (translations.count() > numTranslations) {
+ for (int i = translations.count(); i > numTranslations; --i)
+ translations.removeLast();
+ } else if (translations.count() < numTranslations) {
+ for (int i = translations.count(); i < numTranslations; ++i)
+ translations.append(QString());
+ }
+ return translations;
+}
+
+QStringList Translator::normalizedTranslations(const TranslatorMessage &msg,
+ ConversionData &cd, bool *ok) const
+{
+ QLocale::Language l;
+ QLocale::Country c;
+ languageAndCountry(languageCode(), &l, &c);
+ QStringList translns = normalizedTranslations(msg, l, c);
+ if (msg.translations().size() > translns.size() && ok) {
+ cd.appendError(QLatin1String(
+ "Removed plural forms as the target language has less "
+ "forms.\nIf this sounds wrong, possibly the target language is "
+ "not set or recognized.\n"));
+ *ok = false;
+ }
+ return translns;
+}
+
+QString Translator::guessLanguageCodeFromFileName(const QString &filename)
+{
+ QString str = filename;
+ foreach (const FileFormat &format, registeredFileFormats()) {
+ if (str.endsWith(format.extension)) {
+ str = str.left(str.size() - format.extension.size() - 1);
+ break;
+ }
+ }
+ static QRegExp re(QLatin1String("[\\._]"));
+ while (true) {
+ QLocale locale(str);
+ //qDebug() << "LANGUAGE FROM " << str << "LANG: " << locale.language();
+ if (locale.language() != QLocale::C) {
+ //qDebug() << "FOUND " << locale.name();
+ return locale.name();
+ }
+ int pos = str.indexOf(re);
+ if (pos == -1)
+ break;
+ str = str.mid(pos + 1);
+ }
+ //qDebug() << "LANGUAGE GUESSING UNSUCCESSFUL";
+ return QString();
+}
+
+bool Translator::hasExtra(const QString &key) const
+{
+ return m_extra.contains(key);
+}
+
+QString Translator::extra(const QString &key) const
+{
+ return m_extra[key];
+}
+
+void Translator::setExtra(const QString &key, const QString &value)
+{
+ m_extra[key] = value;
+}
+
+void Translator::setCodecName(const QByteArray &name)
+{
+ QTextCodec *codec = QTextCodec::codecForName(name);
+ if (!codec) {
+ if (!name.isEmpty())
+ qWarning("No QTextCodec for %s available. Using Latin1\n", name.constData());
+ m_codecName.clear();
+ } else {
+ m_codecName = codec->name();
+ }
+}
+
+void Translator::dump() const
+{
+ for (int i = 0; i != messageCount(); ++i)
+ message(i).dump();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/translator.h b/tools/linguist/shared/translator.h
new file mode 100644
index 0000000000..f4279da436
--- /dev/null
+++ b/tools/linguist/shared/translator.h
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef METATRANSLATOR_H
+#define METATRANSLATOR_H
+
+#include "translatormessage.h"
+
+#include <QDir>
+#include <QList>
+#include <QLocale>
+#include <QString>
+
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_TYPEINFO(TranslatorMessage, Q_MOVABLE_TYPE);
+
+class QIODevice;
+
+// A struct of "interesting" data passed to and from the load and save routines
+class ConversionData
+{
+public:
+ ConversionData() :
+ m_verbose(false),
+ m_ignoreUnfinished(false),
+ m_sortContexts(false),
+ m_noUiLines(false),
+ m_saveMode(SaveEverything)
+ {}
+
+ // tag manipulation
+ const QStringList &dropTags() const { return m_dropTags; }
+ QStringList &dropTags() { return m_dropTags; }
+ const QDir &targetDir() const { return m_targetDir; }
+ bool isVerbose() const { return m_verbose; }
+ bool ignoreUnfinished() const { return m_ignoreUnfinished; }
+ bool sortContexts() const { return m_sortContexts; }
+
+ void appendError(const QString &error) { m_errors.append(error); }
+ QString error() const { return m_errors.join(QLatin1String("\n")); }
+ QStringList errors() const { return m_errors; }
+ void clearErrors() { m_errors.clear(); }
+
+public:
+ QString m_defaultContext;
+ QByteArray m_codecForSource; // CPP specific
+ QString m_sourceFileName;
+ QString m_targetFileName;
+ QDir m_sourceDir;
+ QDir m_targetDir; // FIXME: TS spefic
+ QStringList m_dropTags; // tags to be dropped
+ QStringList m_errors;
+ bool m_verbose;
+ bool m_ignoreUnfinished;
+ bool m_sortContexts;
+ bool m_noUiLines;
+ TranslatorSaveMode m_saveMode;
+};
+
+class Translator
+{
+public:
+ Translator();
+
+ bool load(const QString &filename, ConversionData &err, const QString &format /*= "auto"*/);
+ bool save(const QString &filename, ConversionData &err, const QString &format /*= "auto"*/) const;
+ bool release(QFile *iod, ConversionData &cd) const;
+
+ bool contains(const QString &context, const QString &sourceText,
+ const QString &comment) const;
+ TranslatorMessage find(const QString &context,
+ const QString &sourceText, const QString &comment) const;
+
+ TranslatorMessage find(const QString &context,
+ const QString &comment, const TranslatorMessage::References &refs) const;
+
+ bool contains(const QString &context) const;
+ TranslatorMessage find(const QString &context) const;
+
+ void replace(const TranslatorMessage &msg);
+ void replaceSorted(const TranslatorMessage &msg);
+ void extend(const TranslatorMessage &msg); // Only for single-location messages
+ void append(const TranslatorMessage &msg);
+ void appendSorted(const TranslatorMessage &msg);
+
+ void stripObsoleteMessages();
+ void stripFinishedMessages();
+ void stripEmptyContexts();
+ void stripNonPluralForms();
+ void stripIdenticalSourceTranslations();
+ void dropTranslations();
+ QList<TranslatorMessage> findDuplicates() const;
+ void makeFileNamesAbsolute(const QDir &originalPath);
+
+ void setCodecName(const QByteArray &name);
+ QByteArray codecName() const { return m_codecName; }
+
+ QString languageCode() const { return m_language; }
+ QString sourceLanguageCode() const { return m_sourceLanguage; }
+
+ enum LocationsType { NoLocations, RelativeLocations, AbsoluteLocations };
+ void setLocationsType(LocationsType lt) { m_locationsType = lt; }
+ LocationsType locationsType() const { return m_locationsType; }
+
+ static QString makeLanguageCode(QLocale::Language language, QLocale::Country country);
+ static void languageAndCountry(const QString &languageCode,
+ QLocale::Language *lang, QLocale::Country *country);
+ void setLanguageCode(const QString &languageCode) { m_language = languageCode; }
+ void setSourceLanguageCode(const QString &languageCode) { m_sourceLanguage = languageCode; }
+ static QString guessLanguageCodeFromFileName(const QString &fileName);
+ QList<TranslatorMessage> messages() const;
+ QList<TranslatorMessage> translatedMessages() const;
+ static QStringList normalizedTranslations(const TranslatorMessage &m,
+ QLocale::Language lang, QLocale::Country country);
+ QStringList normalizedTranslations(const TranslatorMessage &m, ConversionData &cd, bool *ok) const;
+
+ int messageCount() const { return m_messages.size(); }
+ TranslatorMessage &message(int i) { return m_messages[i]; }
+ const TranslatorMessage &message(int i) const { return m_messages.at(i); }
+ void dump() const;
+
+ // additional file format specific data
+ // note: use '<fileformat>:' as prefix for file format specific members,
+ // e.g. "po-flags", "po-msgid_plural"
+ typedef TranslatorMessage::ExtraData ExtraData;
+ QString extra(const QString &ba) const;
+ void setExtra(const QString &ba, const QString &var);
+ bool hasExtra(const QString &ba) const;
+ const ExtraData &extras() const { return m_extra; }
+ void setExtras(const ExtraData &extras) { m_extra = extras; }
+
+ // registration of file formats
+ typedef bool (*SaveFunction)(const Translator &, QIODevice &out, ConversionData &data);
+ typedef bool (*LoadFunction)(Translator &, QIODevice &in, ConversionData &data);
+ struct FileFormat {
+ FileFormat() : loader(0), saver(0), priority(-1) {}
+ QString extension; // such as "ts", "xlf", ...
+ QString description; // human-readable description
+ LoadFunction loader;
+ SaveFunction saver;
+ enum FileType { SourceCode, TranslationSource, TranslationBinary } fileType;
+ int priority; // 0 = highest, -1 = invisible
+ };
+ static void registerFileFormat(const FileFormat &format);
+ static QList<FileFormat> &registeredFileFormats();
+
+ enum VariantSeparators {
+ DefaultVariantSeparator = 0x2762, // some weird character nobody ever heard of :-D
+ InternalVariantSeparator = 0x9c // unicode "STRING TERMINATOR"
+ };
+
+private:
+ typedef QList<TranslatorMessage> TMM; // int stores the sequence position.
+
+ TMM m_messages;
+ QByteArray m_codecName;
+ LocationsType m_locationsType;
+
+ // A string beginning with a 2 or 3 letter language code (ISO 639-1
+ // or ISO-639-2), followed by the optional country variant to distinguish
+ // between country-specific variations of the language. The language code
+ // and country code are always separated by '_'
+ // Note that the language part can also be a 3-letter ISO 639-2 code.
+ // Legal examples:
+ // 'pt' portuguese, assumes portuguese from portugal
+ // 'pt_BR' Brazilian portuguese (ISO 639-1 language code)
+ // 'por_BR' Brazilian portuguese (ISO 639-2 language code)
+ QString m_language;
+ QString m_sourceLanguage;
+ ExtraData m_extra;
+};
+
+bool getNumerusInfo(QLocale::Language language, QLocale::Country country,
+ QByteArray *rules, QStringList *forms);
+
+/*
+ This is a quick hack. The proper way to handle this would be
+ to extend Translator's interface.
+*/
+#define ContextComment "QT_LINGUIST_INTERNAL_CONTEXT_COMMENT"
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/shared/translatormessage.cpp b/tools/linguist/shared/translatormessage.cpp
new file mode 100644
index 0000000000..ab4301fbb3
--- /dev/null
+++ b/tools/linguist/shared/translatormessage.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translatormessage.h"
+
+#include <qplatformdefs.h>
+
+#ifndef QT_NO_TRANSLATION
+
+#include <QDataStream>
+#include <QDebug>
+
+#include <stdlib.h>
+
+
+QT_BEGIN_NAMESPACE
+
+TranslatorMessage::TranslatorMessage()
+ : m_lineNumber(-1), m_type(Unfinished), m_utf8(false), m_plural(false)
+{
+}
+
+TranslatorMessage::TranslatorMessage(const QString &context,
+ const QString &sourceText, const QString &comment,
+ const QString &userData,
+ const QString &fileName, int lineNumber, const QStringList &translations,
+ Type type, bool plural)
+ : m_context(context), m_sourcetext(sourceText), m_comment(comment),
+ m_userData(userData),
+ m_translations(translations), m_fileName(fileName), m_lineNumber(lineNumber),
+ m_type(type), m_utf8(false), m_plural(plural)
+{
+}
+
+void TranslatorMessage::addReference(const QString &fileName, int lineNumber)
+{
+ if (m_fileName.isEmpty()) {
+ m_fileName = fileName;
+ m_lineNumber = lineNumber;
+ } else {
+ m_extraRefs.append(Reference(fileName, lineNumber));
+ }
+}
+
+void TranslatorMessage::addReferenceUniq(const QString &fileName, int lineNumber)
+{
+ if (m_fileName.isEmpty()) {
+ m_fileName = fileName;
+ m_lineNumber = lineNumber;
+ } else {
+ if (fileName == m_fileName && lineNumber == m_lineNumber)
+ return;
+ if (!m_extraRefs.isEmpty()) // Rather common case, so special-case it
+ foreach (const Reference &ref, m_extraRefs)
+ if (fileName == ref.fileName() && lineNumber == ref.lineNumber())
+ return;
+ m_extraRefs.append(Reference(fileName, lineNumber));
+ }
+}
+
+void TranslatorMessage::clearReferences()
+{
+ m_fileName.clear();
+ m_lineNumber = -1;
+ m_extraRefs.clear();
+}
+
+void TranslatorMessage::setReferences(const TranslatorMessage::References &refs0)
+{
+ if (!refs0.isEmpty()) {
+ References refs = refs0;
+ const Reference &ref = refs.takeFirst();
+ m_fileName = ref.fileName();
+ m_lineNumber = ref.lineNumber();
+ m_extraRefs = refs;
+ } else {
+ clearReferences();
+ }
+}
+
+TranslatorMessage::References TranslatorMessage::allReferences() const
+{
+ References refs;
+ if (!m_fileName.isEmpty()) {
+ refs.append(Reference(m_fileName, m_lineNumber));
+ refs += m_extraRefs;
+ }
+ return refs;
+}
+
+static bool needs8BitHelper(const QString &ba)
+{
+ for (int i = ba.size(); --i >= 0; )
+ if (ba.at(i).unicode() >= 0x80)
+ return true;
+ return false;
+}
+
+bool TranslatorMessage::needs8Bit() const
+{
+ //dump();
+ return needs8BitHelper(m_sourcetext)
+ || needs8BitHelper(m_comment)
+ || needs8BitHelper(m_context);
+}
+
+
+bool TranslatorMessage::operator==(const TranslatorMessage& m) const
+{
+ static QString msgIdPlural = QLatin1String("po-msgid_plural");
+
+ // Special treatment for context comments (empty source).
+ return (m_context == m.m_context)
+ && m_sourcetext == m.m_sourcetext
+ && m_extra[msgIdPlural] == m.m_extra[msgIdPlural]
+ && (m_sourcetext.isEmpty() || m_comment == m.m_comment);
+}
+
+
+bool TranslatorMessage::operator<(const TranslatorMessage& m) const
+{
+ if (m_context != m.m_context)
+ return m_context < m.m_context;
+ if (m_sourcetext != m.m_sourcetext)
+ return m_sourcetext < m.m_sourcetext;
+ return m_comment < m.m_comment;
+}
+
+int qHash(const TranslatorMessage &msg)
+{
+ return
+ qHash(msg.context()) ^
+ qHash(msg.sourceText()) ^
+ qHash(msg.extra(QLatin1String("po-msgid_plural"))) ^
+ qHash(msg.comment());
+}
+
+bool TranslatorMessage::hasExtra(const QString &key) const
+{
+ return m_extra.contains(key);
+}
+
+QString TranslatorMessage::extra(const QString &key) const
+{
+ return m_extra[key];
+}
+
+void TranslatorMessage::setExtra(const QString &key, const QString &value)
+{
+ m_extra[key] = value;
+}
+
+void TranslatorMessage::unsetExtra(const QString &key)
+{
+ m_extra.remove(key);
+}
+
+void TranslatorMessage::dump() const
+{
+ qDebug()
+ << "\nId : " << m_id
+ << "\nContext : " << m_context
+ << "\nSource : " << m_sourcetext
+ << "\nComment : " << m_comment
+ << "\nUserData : " << m_userData
+ << "\nExtraComment : " << m_extraComment
+ << "\nTranslatorComment : " << m_translatorComment
+ << "\nTranslations : " << m_translations
+ << "\nFileName : " << m_fileName
+ << "\nLineNumber : " << m_lineNumber
+ << "\nType : " << m_type
+ << "\nPlural : " << m_plural
+ << "\nExtra : " << m_extra;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TRANSLATION
diff --git a/tools/linguist/shared/translatormessage.h b/tools/linguist/shared/translatormessage.h
new file mode 100644
index 0000000000..fa37ff5ce7
--- /dev/null
+++ b/tools/linguist/shared/translatormessage.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRANSLATORMESSAGE_H
+#define TRANSLATORMESSAGE_H
+
+#ifndef QT_NO_TRANSLATION
+
+#include <QString>
+#include <QStringList>
+#include <QHash>
+
+
+QT_BEGIN_NAMESPACE
+
+enum TranslatorSaveMode { SaveEverything, SaveStripped };
+
+class TranslatorMessage
+{
+public:
+ enum Type { Unfinished, Finished, Obsolete };
+ typedef QHash<QString, QString> ExtraData;
+ class Reference
+ {
+ QString m_fileName;
+ int m_lineNumber;
+ public:
+ Reference(const QString &n, int l) : m_fileName(n), m_lineNumber(l) {}
+ bool operator==(const Reference &other) const
+ { return fileName() == other.fileName() && lineNumber() == other.lineNumber(); }
+ QString fileName() const { return m_fileName; }
+ int lineNumber() const { return m_lineNumber; }
+ };
+ typedef QList<Reference> References;
+
+ TranslatorMessage();
+ TranslatorMessage(const QString &context, const QString &sourceText,
+ const QString &comment, const QString &userData,
+ const QString &fileName, int lineNumber,
+ const QStringList &translations = QStringList(),
+ Type type = Unfinished, bool plural = false);
+
+ uint hash() const;
+
+ QString id() const { return m_id; }
+ void setId(const QString &id) { m_id = id; }
+
+ QString context() const { return m_context; }
+ void setContext(const QString &context) { m_context = context; }
+
+ QString sourceText() const { return m_sourcetext; }
+ void setSourceText(const QString &sourcetext) { m_sourcetext = sourcetext; }
+ QString oldSourceText() const { return m_oldsourcetext; }
+ void setOldSourceText(const QString &oldsourcetext) { m_oldsourcetext = oldsourcetext; }
+
+ QString comment() const { return m_comment; }
+ void setComment(const QString &comment) { m_comment = comment; }
+ QString oldComment() const { return m_oldcomment; }
+ void setOldComment(const QString &oldcomment) { m_oldcomment = oldcomment; }
+
+ QStringList translations() const { return m_translations; }
+ void setTranslations(const QStringList &translations) { m_translations = translations; }
+ QString translation() const { return m_translations.value(0); }
+ void setTranslation(const QString &translation) { m_translations = QStringList(translation); }
+ void appendTranslation(const QString &translation) { m_translations.append(translation); }
+ bool isTranslated() const
+ {
+ foreach (const QString &trans, m_translations)
+ if (!trans.isEmpty())
+ return true;
+ return false;
+ }
+
+ bool operator==(const TranslatorMessage& m) const;
+ bool operator<(const TranslatorMessage& m) const;
+
+ QString fileName() const { return m_fileName; }
+ void setFileName(const QString &fileName) { m_fileName = fileName; }
+ int lineNumber() const { return m_lineNumber; }
+ void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; }
+ void clearReferences();
+ void setReferences(const References &refs);
+ void addReference(const QString &fileName, int lineNumber);
+ void addReference(const Reference &ref) { addReference(ref.fileName(), ref.lineNumber()); }
+ void addReferenceUniq(const QString &fileName, int lineNumber);
+ References extraReferences() const { return m_extraRefs; }
+ References allReferences() const;
+ QString userData() const { return m_userData; }
+ void setUserData(const QString &userData) { m_userData = userData; }
+ QString extraComment() const { return m_extraComment; }
+ void setExtraComment(const QString &extraComment) { m_extraComment = extraComment; }
+ QString translatorComment() const { return m_translatorComment; }
+ void setTranslatorComment(const QString &translatorComment) { m_translatorComment = translatorComment; }
+
+ bool isNull() const { return m_sourcetext.isNull() && m_lineNumber == -1 && m_translations.isEmpty(); }
+
+ Type type() const { return m_type; }
+ void setType(Type t) { m_type = t; }
+ bool isUtf8() const { return m_utf8; } // codecForTr override
+ void setUtf8(bool on) { m_utf8 = on; }
+ bool isPlural() const { return m_plural; }
+ void setPlural(bool isplural) { m_plural = isplural; }
+
+ // note: use '<fileformat>:' as prefix for file format specific members,
+ // e.g. "po-msgid_plural"
+ QString extra(const QString &ba) const;
+ void setExtra(const QString &ba, const QString &var);
+ bool hasExtra(const QString &ba) const;
+ const ExtraData &extras() const { return m_extra; }
+ void setExtras(const ExtraData &extras) { m_extra = extras; }
+ void unsetExtra(const QString &key);
+
+ bool needs8Bit() const;
+ void dump() const;
+
+private:
+ QString m_id;
+ QString m_context;
+ QString m_sourcetext;
+ QString m_oldsourcetext;
+ QString m_comment;
+ QString m_oldcomment;
+ QString m_userData;
+ ExtraData m_extra; // PO flags, PO plurals
+ QString m_extraComment;
+ QString m_translatorComment;
+ QStringList m_translations;
+ QString m_fileName;
+ int m_lineNumber;
+ References m_extraRefs;
+
+ Type m_type;
+ bool m_utf8;
+ bool m_plural;
+};
+
+int qHash(const TranslatorMessage &msg);
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TRANSLATION
+
+#endif // TRANSLATORMESSAGE_H
diff --git a/tools/linguist/shared/translatortools.cpp b/tools/linguist/shared/translatortools.cpp
new file mode 100644
index 0000000000..dcff5468b4
--- /dev/null
+++ b/tools/linguist/shared/translatortools.cpp
@@ -0,0 +1,505 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translatortools.h"
+
+#include "simtexth.h"
+#include "translator.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMap>
+#include <QtCore/QStringList>
+#include <QtCore/QTextCodec>
+#include <QtCore/QVector>
+
+typedef QList<TranslatorMessage> TML;
+typedef QMap<QString, TranslatorMessage> TMM;
+
+
+QT_BEGIN_NAMESPACE
+
+static bool isDigitFriendly(QChar c)
+{
+ return c.isPunct() || c.isSpace();
+}
+
+static int numberLength(const QString &s, int i)
+{
+ if (i < s.size() || !s.at(i).isDigit())
+ return 0;
+
+ int pos = i;
+ do {
+ ++i;
+ } while (i < s.size()
+ && (s.at(i).isDigit()
+ || (isDigitFriendly(s[i])
+ && i + 1 < s.size()
+ && (s[i + 1].isDigit()
+ || (isDigitFriendly(s[i + 1])
+ && i + 2 < s.size()
+ && s[i + 2].isDigit())))));
+ return i - pos;
+}
+
+
+/*
+ Returns a version of 'key' where all numbers have been replaced by zeroes. If
+ there were none, returns "".
+*/
+static QString zeroKey(const QString &key)
+{
+ QString zeroed;
+ bool metSomething = false;
+
+ for (int i = 0; i != key.size(); ++i) {
+ int len = numberLength(key, i);
+ if (len > 0) {
+ i += len;
+ zeroed.append(QLatin1Char('0'));
+ metSomething = true;
+ } else {
+ zeroed.append(key.at(i));
+ }
+ }
+ return metSomething ? zeroed : QString();
+}
+
+static QString translationAttempt(const QString &oldTranslation,
+ const QString &oldSource, const QString &newSource)
+{
+ int p = zeroKey(oldSource).count(QLatin1Char('0'));
+ QString attempt;
+ QStringList oldNumbers;
+ QStringList newNumbers;
+ QVector<bool> met(p);
+ QVector<int> matchedYet(p);
+ int i, j;
+ int k = 0, ell, best;
+ int m, n;
+ int pass;
+
+ /*
+ This algorithm is hard to follow, so we'll consider an example
+ all along: oldTranslation is "XeT 3.0", oldSource is "TeX 3.0"
+ and newSource is "XeT 3.1".
+
+ First, we set up two tables: oldNumbers and newNumbers. In our
+ example, oldNumber[0] is "3.0" and newNumber[0] is "3.1".
+ */
+ for (i = 0, j = 0; i < oldSource.size(); i++, j++) {
+ m = numberLength(oldSource, i);
+ n = numberLength(newSource, j);
+ if (m > 0) {
+ oldNumbers.append(oldSource.mid(i, m + 1));
+ newNumbers.append(newSource.mid(j, n + 1));
+ i += m;
+ j += n;
+ met[k] = false;
+ matchedYet[k] = 0;
+ k++;
+ }
+ }
+
+ /*
+ We now go over the old translation, "XeT 3.0", one letter at a
+ time, looking for numbers found in oldNumbers. Whenever such a
+ number is met, it is replaced with its newNumber equivalent. In
+ our example, the "3.0" of "XeT 3.0" becomes "3.1".
+ */
+ for (i = 0; i < oldTranslation.length(); i++) {
+ attempt += oldTranslation[i];
+ for (k = 0; k < p; k++) {
+ if (oldTranslation[i] == oldNumbers[k][matchedYet[k]])
+ matchedYet[k]++;
+ else
+ matchedYet[k] = 0;
+ }
+
+ /*
+ Let's find out if the last character ended a match. We make
+ two passes over the data. In the first pass, we try to
+ match only numbers that weren't matched yet; if that fails,
+ the second pass does the trick. This is useful in some
+ suspicious cases, flagged below.
+ */
+ for (pass = 0; pass < 2; pass++) {
+ best = p; // an impossible value
+ for (k = 0; k < p; k++) {
+ if ((!met[k] || pass > 0) &&
+ matchedYet[k] == oldNumbers[k].length() &&
+ numberLength(oldTranslation, i + 1 - matchedYet[k]) == matchedYet[k]) {
+ // the longer the better
+ if (best == p || matchedYet[k] > matchedYet[best])
+ best = k;
+ }
+ }
+ if (best != p) {
+ attempt.truncate(attempt.length() - matchedYet[best]);
+ attempt += newNumbers[best];
+ met[best] = true;
+ for (k = 0; k < p; k++)
+ matchedYet[k] = 0;
+ break;
+ }
+ }
+ }
+
+ /*
+ We flag two kinds of suspicious cases. They are identified as
+ such with comments such as "{2000?}" at the end.
+
+ Example of the first kind: old source text "TeX 3.0" translated
+ as "XeT 2.0" is flagged "TeX 2.0 {3.0?}", no matter what the
+ new text is.
+ */
+ for (k = 0; k < p; k++) {
+ if (!met[k])
+ attempt += QString(QLatin1String(" {")) + newNumbers[k] + QString(QLatin1String("?}"));
+ }
+
+ /*
+ Example of the second kind: "1 of 1" translated as "1 af 1",
+ with new source text "1 of 2", generates "1 af 2 {1 or 2?}"
+ because it's not clear which of "1 af 2" and "2 af 1" is right.
+ */
+ for (k = 0; k < p; k++) {
+ for (ell = 0; ell < p; ell++) {
+ if (k != ell && oldNumbers[k] == oldNumbers[ell] &&
+ newNumbers[k] < newNumbers[ell])
+ attempt += QString(QLatin1String(" {")) + newNumbers[k] + QString(QLatin1String(" or ")) +
+ newNumbers[ell] + QString(QLatin1String("?}"));
+ }
+ }
+ return attempt;
+}
+
+
+/*
+ Augments a Translator with translations easily derived from
+ similar existing (probably obsolete) translations.
+
+ For example, if "TeX 3.0" is translated as "XeT 3.0" and "TeX 3.1"
+ has no translation, "XeT 3.1" is added to the translator and is
+ marked Unfinished.
+
+ Returns the number of additional messages that this heuristic translated.
+*/
+int applyNumberHeuristic(Translator &tor)
+{
+ TMM translated, untranslated;
+ TMM::Iterator t, u;
+ TML all = tor.messages();
+ TML::Iterator it;
+ int inserted = 0;
+
+ for (it = all.begin(); it != all.end(); ++it) {
+ bool hasTranslation = it->isTranslated();
+ if (it->type() == TranslatorMessage::Unfinished) {
+ if (!hasTranslation)
+ untranslated.insert(it->context() + QLatin1Char('\n')
+ + it->sourceText() + QLatin1Char('\n')
+ + it->comment(), *it);
+ } else if (hasTranslation && it->translations().count() == 1) {
+ translated.insert(zeroKey(it->sourceText()), *it);
+ }
+ }
+
+ for (u = untranslated.begin(); u != untranslated.end(); ++u) {
+ t = translated.find(zeroKey((*u).sourceText()));
+ if (t != translated.end() && !t.key().isEmpty()
+ && t->sourceText() != u->sourceText()) {
+ TranslatorMessage m = *u;
+ m.setTranslation(translationAttempt(t->translation(), t->sourceText(),
+ u->sourceText()));
+ tor.replace(m);
+ inserted++;
+ }
+ }
+ return inserted;
+}
+
+
+/*
+ Augments a Translator with trivially derived translations.
+
+ For example, if "Enabled:" is consistendly translated as "Eingeschaltet:" no
+ matter the context or the comment, "Eingeschaltet:" is added as the
+ translation of any untranslated "Enabled:" text and is marked Unfinished.
+
+ Returns the number of additional messages that this heuristic translated.
+*/
+
+int applySameTextHeuristic(Translator &tor)
+{
+ TMM translated;
+ TMM avoid;
+ TMM::Iterator t;
+ TML untranslated;
+ TML::Iterator u;
+ TML all = tor.messages();
+ TML::Iterator it;
+ int inserted = 0;
+
+ for (it = all.begin(); it != all.end(); ++it) {
+ if (!it->isTranslated()) {
+ if (it->type() == TranslatorMessage::Unfinished)
+ untranslated.append(*it);
+ } else {
+ QString key = it->sourceText();
+ t = translated.find(key);
+ if (t != translated.end()) {
+ /*
+ The same source text is translated at least two
+ different ways. Do nothing then.
+ */
+ if (t->translations() != it->translations()) {
+ translated.remove(key);
+ avoid.insert(key, *it);
+ }
+ } else if (!avoid.contains(key)) {
+ translated.insert(key, *it);
+ }
+ }
+ }
+
+ for (u = untranslated.begin(); u != untranslated.end(); ++u) {
+ QString key = u->sourceText();
+ t = translated.find(key);
+ if (t != translated.end()) {
+ TranslatorMessage m = *u;
+ m.setTranslations(t->translations());
+ tor.replace(m);
+ ++inserted;
+ }
+ }
+ return inserted;
+}
+
+
+
+/*
+ Merges two Translator objects. The first one
+ is a set of source texts and translations for a previous version of
+ the internationalized program; the second one is a set of fresh
+ source texts newly extracted from the source code, without any
+ translation yet.
+*/
+
+Translator merge(const Translator &tor, const Translator &virginTor,
+ UpdateOptions options, QString &err)
+{
+ int known = 0;
+ int neww = 0;
+ int obsoleted = 0;
+ int similarTextHeuristicCount = 0;
+
+ Translator outTor;
+ outTor.setLanguageCode(tor.languageCode());
+ outTor.setSourceLanguageCode(tor.sourceLanguageCode());
+ outTor.setLocationsType(tor.locationsType());
+ outTor.setCodecName(tor.codecName());
+
+ /*
+ The types of all the messages from the vernacular translator
+ are updated according to the virgin translator.
+ */
+ foreach (TranslatorMessage m, tor.messages()) {
+ TranslatorMessage::Type newType = TranslatorMessage::Finished;
+
+ if (m.sourceText().isEmpty()) {
+ // context/file comment
+ TranslatorMessage mv = virginTor.find(m.context());
+ if (!mv.isNull())
+ m.setComment(mv.comment());
+ } else {
+ TranslatorMessage mv = virginTor.find(m.context(), m.sourceText(), m.comment());
+ if (mv.isNull()) {
+ if (!(options & HeuristicSimilarText)) {
+ newType = TranslatorMessage::Obsolete;
+ if (m.type() != TranslatorMessage::Obsolete)
+ obsoleted++;
+ m.clearReferences();
+ } else {
+ mv = virginTor.find(m.context(), m.comment(), m.allReferences());
+ if (mv.isNull()) {
+ // did not find it in the virgin, mark it as obsolete
+ newType = TranslatorMessage::Obsolete;
+ if (m.type() != TranslatorMessage::Obsolete)
+ obsoleted++;
+ m.clearReferences();
+ } else {
+ // Do not just accept it if its on the same line number,
+ // but different source text.
+ // Also check if the texts are more or less similar before
+ // we consider them to represent the same message...
+ if (getSimilarityScore(m.sourceText(), mv.sourceText()) >= textSimilarityThreshold) {
+ // It is just slightly modified, assume that it is the same string
+
+ // Mark it as unfinished. (Since the source text
+ // was changed it might require re-translating...)
+ newType = TranslatorMessage::Unfinished;
+ ++similarTextHeuristicCount;
+ neww++;
+
+ m.setOldSourceText(m.sourceText());
+ m.setSourceText(mv.sourceText());
+ const QString &oldpluralsource = m.extra(QLatin1String("po-msgid_plural"));
+ if (!oldpluralsource.isEmpty()) {
+ m.setExtra(QLatin1String("po-old_msgid_plural"), oldpluralsource);
+ m.unsetExtra(QLatin1String("po-msgid_plural"));
+ }
+ m.setReferences(mv.allReferences()); // Update secondary references
+ m.setPlural(mv.isPlural());
+ m.setUtf8(mv.isUtf8());
+ m.setExtraComment(mv.extraComment());
+ } else {
+ // The virgin and vernacular sourceTexts are so
+ // different that we could not find it.
+ newType = TranslatorMessage::Obsolete;
+ if (m.type() != TranslatorMessage::Obsolete)
+ obsoleted++;
+ m.clearReferences();
+ }
+ }
+ }
+ } else {
+ switch (m.type()) {
+ case TranslatorMessage::Finished:
+ default:
+ if (m.isPlural() == mv.isPlural()) {
+ newType = TranslatorMessage::Finished;
+ } else {
+ newType = TranslatorMessage::Unfinished;
+ }
+ known++;
+ break;
+ case TranslatorMessage::Unfinished:
+ newType = TranslatorMessage::Unfinished;
+ known++;
+ break;
+ case TranslatorMessage::Obsolete:
+ newType = TranslatorMessage::Unfinished;
+ neww++;
+ }
+
+ // Always get the filename and linenumber info from the
+ // virgin Translator, in case it has changed location.
+ // This should also enable us to read a file that does not
+ // have the <location> element.
+ // why not use operator=()? Because it overwrites e.g. userData.
+ m.setReferences(mv.allReferences());
+ m.setPlural(mv.isPlural());
+ m.setUtf8(mv.isUtf8());
+ m.setExtraComment(mv.extraComment());
+ }
+ }
+
+ m.setType(newType);
+ outTor.append(m);
+ }
+
+ /*
+ Messages found only in the virgin translator are added to the
+ vernacular translator.
+ */
+ foreach (const TranslatorMessage &mv, virginTor.messages()) {
+ if (mv.sourceText().isEmpty()) {
+ if (tor.contains(mv.context()))
+ continue;
+ } else {
+ if (tor.contains(mv.context(), mv.sourceText(), mv.comment()))
+ continue;
+ if (options & HeuristicSimilarText) {
+ TranslatorMessage m = tor.find(mv.context(), mv.comment(), mv.allReferences());
+ if (!m.isNull()) {
+ if (getSimilarityScore(m.sourceText(), mv.sourceText()) >= textSimilarityThreshold)
+ continue;
+ }
+ }
+ }
+ if (options & NoLocations)
+ outTor.append(mv);
+ else
+ outTor.appendSorted(mv);
+ if (!mv.sourceText().isEmpty())
+ ++neww;
+ }
+
+ /*
+ The same-text heuristic handles cases where a message has an
+ obsolete counterpart with a different context or comment.
+ */
+ int sameTextHeuristicCount = (options & HeuristicSameText) ? applySameTextHeuristic(outTor) : 0;
+
+ /*
+ The number heuristic handles cases where a message has an
+ obsolete counterpart with mostly numbers differing in the
+ source text.
+ */
+ int sameNumberHeuristicCount = (options & HeuristicNumber) ? applyNumberHeuristic(outTor) : 0;
+
+ if (options & Verbose) {
+ int totalFound = neww + known;
+ err += QObject::tr(" Found %n source text(s) (%1 new and %2 already existing)\n", 0, totalFound).arg(neww).arg(known);
+
+ if (obsoleted) {
+ if (options & NoObsolete) {
+ err += QObject::tr(" Removed %n obsolete entries\n", 0, obsoleted);
+ } else {
+ err += QObject::tr(" Kept %n obsolete entries\n", 0, obsoleted);
+ }
+ }
+
+ if (sameNumberHeuristicCount)
+ err += QObject::tr(" Number heuristic provided %n translation(s)\n",
+ 0, sameNumberHeuristicCount);
+ if (sameTextHeuristicCount)
+ err += QObject::tr(" Same-text heuristic provided %n translation(s)\n",
+ 0, sameTextHeuristicCount);
+ if (similarTextHeuristicCount)
+ err += QObject::tr(" Similar-text heuristic provided %n translation(s)\n",
+ 0, similarTextHeuristicCount);
+ }
+ return outTor;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/translatortools.h b/tools/linguist/shared/translatortools.h
new file mode 100644
index 0000000000..9eaf024061
--- /dev/null
+++ b/tools/linguist/shared/translatortools.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LUPDATE_H
+#define LUPDATE_H
+
+#include "qglobal.h"
+
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class Translator;
+class TranslatorMessage;
+
+enum UpdateOption {
+ Verbose = 1,
+ NoObsolete = 2,
+ PluralOnly = 4,
+ NoSort = 8,
+ HeuristicSameText = 16,
+ HeuristicSimilarText = 32,
+ HeuristicNumber = 64,
+ AbsoluteLocations = 256,
+ RelativeLocations = 512,
+ NoLocations = 1024,
+ NoUiLines = 2048
+};
+
+Q_DECLARE_FLAGS(UpdateOptions, UpdateOption)
+Q_DECLARE_OPERATORS_FOR_FLAGS(UpdateOptions)
+
+Translator merge(const Translator &tor, const Translator &virginTor,
+ UpdateOptions options, QString &err);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/linguist/shared/translatortools.pri b/tools/linguist/shared/translatortools.pri
new file mode 100644
index 0000000000..2b6de8caa9
--- /dev/null
+++ b/tools/linguist/shared/translatortools.pri
@@ -0,0 +1,11 @@
+
+
+INCLUDEPATH *= $$PWD
+
+SOURCES += \
+ $$PWD/translatortools.cpp \
+ $$PWD/simtexth.cpp
+
+HEADERS += \
+ $$PWD/translatortools.h
+
diff --git a/tools/linguist/shared/ts.cpp b/tools/linguist/shared/ts.cpp
new file mode 100644
index 0000000000..2e7d40f331
--- /dev/null
+++ b/tools/linguist/shared/ts.cpp
@@ -0,0 +1,755 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+#include <QtXml/QXmlStreamReader>
+#include <QtXml/QXmlStreamAttribute>
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+#define STRING(s) static QString str##s(QLatin1String(STRINGIFY(s)))
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * The encodings are a total mess.
+ * A Translator has a codecForTr(). Each message's text will be passed to tr()
+ * in that encoding or as UTF-8 to trUtf8() if it is flagged as such.
+ * For ts 2.0, the file content is always uniformly in UTF-8. The file stores
+ * the codecForTr default and marks deviating messages accordingly.
+ * For ts 1.1, the file content is in mixed encoding. Each message is encoded
+ * the way it will be passed to tr() (with 8-bit characters encoded as numeric
+ * entities) or trUtf8(). The file stores the encoding and codecForTr in one
+ * attribute, for both the default and each deviating message.
+ */
+
+
+QDebug &operator<<(QDebug &d, const QXmlStreamAttribute &attr)
+{
+ return d << "[" << attr.name().toString() << "," << attr.value().toString() << "]";
+}
+
+
+class TSReader : public QXmlStreamReader
+{
+public:
+ TSReader(QIODevice &dev, ConversionData &cd)
+ : QXmlStreamReader(&dev), m_cd(cd)
+ {}
+
+ // the "real thing"
+ bool read(Translator &translator);
+
+private:
+ bool elementStarts(const QString &str) const
+ {
+ return isStartElement() && name() == str;
+ }
+
+ bool isWhiteSpace() const
+ {
+ return isCharacters() && text().toString().trimmed().isEmpty();
+ }
+
+ // needed to expand <byte ... />
+ QString readContents();
+ // needed to join <lengthvariant>s
+ QString readTransContents();
+
+ void handleError();
+
+ ConversionData &m_cd;
+};
+
+void TSReader::handleError()
+{
+ if (isComment())
+ return;
+ if (hasError() && error() == CustomError) // raised by readContents
+ return;
+
+ const QString loc = QString::fromLatin1("at %3:%1:%2")
+ .arg(lineNumber()).arg(columnNumber()).arg(m_cd.m_sourceFileName);
+
+ switch (tokenType()) {
+ case NoToken: // Cannot happen
+ default: // likewise
+ case Invalid:
+ raiseError(QString::fromLatin1("Parse error %1: %2").arg(loc, errorString()));
+ break;
+ case StartElement:
+ raiseError(QString::fromLatin1("Unexpected tag <%1> %2").arg(name().toString(), loc));
+ break;
+ case Characters:
+ {
+ QString tok = text().toString();
+ if (tok.length() > 30)
+ tok = tok.left(30) + QLatin1String("[...]");
+ raiseError(QString::fromLatin1("Unexpected characters '%1' %2").arg(tok, loc));
+ }
+ break;
+ case EntityReference:
+ raiseError(QString::fromLatin1("Unexpected entity '&%1;' %2").arg(name().toString(), loc));
+ break;
+ case ProcessingInstruction:
+ raiseError(QString::fromLatin1("Unexpected processing instruction %1").arg(loc));
+ break;
+ }
+}
+
+static QString byteValue(QString value)
+{
+ int base = 10;
+ if (value.startsWith(QLatin1String("x"))) {
+ base = 16;
+ value.remove(0, 1);
+ }
+ int n = value.toUInt(0, base);
+ return (n != 0) ? QString(QChar(n)) : QString();
+}
+
+QString TSReader::readContents()
+{
+ STRING(byte);
+ STRING(value);
+
+ QString result;
+ while (!atEnd()) {
+ readNext();
+ if (isEndElement()) {
+ break;
+ } else if (isCharacters()) {
+ result += text();
+ } else if (elementStarts(strbyte)) {
+ // <byte value="...">
+ result += byteValue(attributes().value(strvalue).toString());
+ readNext();
+ if (!isEndElement()) {
+ handleError();
+ break;
+ }
+ } else {
+ handleError();
+ break;
+ }
+ }
+ //qDebug() << "TEXT: " << result;
+ return result;
+}
+
+QString TSReader::readTransContents()
+{
+ STRING(lengthvariant);
+ STRING(variants);
+ STRING(yes);
+
+ if (attributes().value(strvariants) == stryes) {
+ QString result;
+ while (!atEnd()) {
+ readNext();
+ if (isEndElement()) {
+ break;
+ } else if (isWhiteSpace()) {
+ // ignore these, just whitespace
+ } else if (elementStarts(strlengthvariant)) {
+ if (!result.isEmpty())
+ result += QChar(Translator::DefaultVariantSeparator);
+ result += readContents();
+ } else {
+ handleError();
+ break;
+ }
+ }
+ return result;
+ } else {
+ return readContents();
+ }
+}
+
+bool TSReader::read(Translator &translator)
+{
+ STRING(byte);
+ STRING(comment);
+ STRING(context);
+ STRING(defaultcodec);
+ STRING(encoding);
+ STRING(extracomment);
+ STRING(filename);
+ STRING(id);
+ STRING(language);
+ STRING(line);
+ STRING(location);
+ STRING(message);
+ STRING(name);
+ STRING(numerus);
+ STRING(numerusform);
+ STRING(obsolete);
+ STRING(oldcomment);
+ STRING(oldsource);
+ STRING(source);
+ STRING(sourcelanguage);
+ STRING(translation);
+ STRING(translatorcomment);
+ STRING(true);
+ STRING(TS);
+ STRING(type);
+ STRING(unfinished);
+ STRING(userdata);
+ STRING(utf8);
+ STRING(value);
+ STRING(version);
+ STRING(yes);
+
+ static const QString strextrans(QLatin1String("extra-"));
+ static const QString strUtf8(QLatin1String("UTF-8"));
+
+ while (!atEnd()) {
+ readNext();
+ if (isStartDocument()) {
+ // <!DOCTYPE TS>
+ //qDebug() << attributes();
+ } else if (isEndDocument()) {
+ // <!DOCTYPE TS>
+ //qDebug() << attributes();
+ } else if (isDTD()) {
+ // <!DOCTYPE TS>
+ //qDebug() << tokenString();
+ } else if (elementStarts(strTS)) {
+ // <TS>
+ //qDebug() << "TS " << attributes();
+ QHash<QString, int> currentLine;
+ QString currentFile;
+
+ QXmlStreamAttributes atts = attributes();
+ //QString version = atts.value(strversion).toString();
+ translator.setLanguageCode(atts.value(strlanguage).toString());
+ translator.setSourceLanguageCode(atts.value(strsourcelanguage).toString());
+ while (!atEnd()) {
+ readNext();
+ if (isEndElement()) {
+ // </TS> found, finish local loop
+ break;
+ } else if (isWhiteSpace()) {
+ // ignore these, just whitespace
+ } else if (elementStarts(strdefaultcodec)) {
+ // <defaultcodec>
+ translator.setCodecName(readElementText().toLatin1());
+ // </defaultcodec>
+ } else if (isStartElement()
+ && name().toString().startsWith(strextrans)) {
+ // <extra-...>
+ QString tag = name().toString();
+ translator.setExtra(tag.mid(6), readContents());
+ // </extra-...>
+ } else if (elementStarts(strcontext)) {
+ // <context>
+ QString context;
+ while (!atEnd()) {
+ readNext();
+ if (isEndElement()) {
+ // </context> found, finish local loop
+ break;
+ } else if (isWhiteSpace()) {
+ // ignore these, just whitespace
+ } else if (elementStarts(strname)) {
+ // <name>
+ context = readElementText();
+ // </name>
+ } else if (elementStarts(strmessage)) {
+ // <message>
+ TranslatorMessage::References refs;
+ QString currentMsgFile = currentFile;
+
+ TranslatorMessage msg;
+ msg.setId(attributes().value(strid).toString());
+ msg.setContext(context);
+ msg.setType(TranslatorMessage::Finished);
+ msg.setPlural(attributes().value(strnumerus) == stryes);
+ msg.setUtf8(attributes().value(strutf8) == strtrue
+ || attributes().value(strencoding) == strUtf8);
+ while (!atEnd()) {
+ readNext();
+ if (isEndElement()) {
+ // </message> found, finish local loop
+ msg.setReferences(refs);
+ translator.append(msg);
+ break;
+ } else if (isWhiteSpace()) {
+ // ignore these, just whitespace
+ } else if (elementStarts(strsource)) {
+ // <source>...</source>
+ msg.setSourceText(readContents());
+ } else if (elementStarts(stroldsource)) {
+ // <oldsource>...</oldsource>
+ msg.setOldSourceText(readContents());
+ } else if (elementStarts(stroldcomment)) {
+ // <oldcomment>...</oldcomment>
+ msg.setOldComment(readContents());
+ } else if (elementStarts(strextracomment)) {
+ // <extracomment>...</extracomment>
+ msg.setExtraComment(readContents());
+ } else if (elementStarts(strtranslatorcomment)) {
+ // <translatorcomment>...</translatorcomment>
+ msg.setTranslatorComment(readContents());
+ } else if (elementStarts(strlocation)) {
+ // <location/>
+ QXmlStreamAttributes atts = attributes();
+ QString fileName = atts.value(strfilename).toString();
+ if (fileName.isEmpty()) {
+ fileName = currentMsgFile;
+ } else {
+ if (refs.isEmpty())
+ currentFile = fileName;
+ currentMsgFile = fileName;
+ }
+ const QString lin = atts.value(strline).toString();
+ if (lin.isEmpty()) {
+ translator.setLocationsType(Translator::RelativeLocations);
+ refs.append(TranslatorMessage::Reference(fileName, -1));
+ } else {
+ bool bOK;
+ int lineNo = lin.toInt(&bOK);
+ if (bOK) {
+ if (lin.startsWith(QLatin1Char('+')) || lin.startsWith(QLatin1Char('-'))) {
+ lineNo = (currentLine[fileName] += lineNo);
+ translator.setLocationsType(Translator::RelativeLocations);
+ } else {
+ translator.setLocationsType(Translator::AbsoluteLocations);
+ }
+ refs.append(TranslatorMessage::Reference(fileName, lineNo));
+ }
+ }
+ readContents();
+ } else if (elementStarts(strcomment)) {
+ // <comment>...</comment>
+ msg.setComment(readContents());
+ } else if (elementStarts(struserdata)) {
+ // <userdata>...</userdata>
+ msg.setUserData(readContents());
+ } else if (elementStarts(strtranslation)) {
+ // <translation>
+ QXmlStreamAttributes atts = attributes();
+ QStringRef type = atts.value(strtype);
+ if (type == strunfinished)
+ msg.setType(TranslatorMessage::Unfinished);
+ else if (type == strobsolete)
+ msg.setType(TranslatorMessage::Obsolete);
+ if (msg.isPlural()) {
+ QStringList translations;
+ while (!atEnd()) {
+ readNext();
+ if (isEndElement()) {
+ break;
+ } else if (isWhiteSpace()) {
+ // ignore these, just whitespace
+ } else if (elementStarts(strnumerusform)) {
+ translations.append(readTransContents());
+ } else {
+ handleError();
+ break;
+ }
+ }
+ msg.setTranslations(translations);
+ } else {
+ msg.setTranslation(readTransContents());
+ }
+ // </translation>
+ } else if (isStartElement()
+ && name().toString().startsWith(strextrans)) {
+ // <extra-...>
+ QString tag = name().toString();
+ msg.setExtra(tag.mid(6), readContents());
+ // </extra-...>
+ } else {
+ handleError();
+ }
+ }
+ // </message>
+ } else {
+ handleError();
+ }
+ }
+ // </context>
+ } else {
+ handleError();
+ }
+ } // </TS>
+ } else {
+ handleError();
+ }
+ }
+ if (hasError()) {
+ m_cd.appendError(errorString());
+ return false;
+ }
+ return true;
+}
+
+static QString numericEntity(int ch)
+{
+ return QString(ch <= 0x20 ? QLatin1String("<byte value=\"x%1\"/>")
+ : QLatin1String("&#x%1;")) .arg(ch, 0, 16);
+}
+
+static QString protect(const QString &str)
+{
+ QString result;
+ result.reserve(str.length() * 12 / 10);
+ for (int i = 0; i != str.size(); ++i) {
+ uint c = str.at(i).unicode();
+ switch (c) {
+ case '\"':
+ result += QLatin1String("&quot;");
+ break;
+ case '&':
+ result += QLatin1String("&amp;");
+ break;
+ case '>':
+ result += QLatin1String("&gt;");
+ break;
+ case '<':
+ result += QLatin1String("&lt;");
+ break;
+ case '\'':
+ result += QLatin1String("&apos;");
+ break;
+ default:
+ if (c < 0x20 && c != '\r' && c != '\n' && c != '\t')
+ result += numericEntity(c);
+ else // this also covers surrogates
+ result += QChar(c);
+ }
+ }
+ return result;
+}
+
+static QString evilBytes(const QString& str,
+ bool isUtf8, int format, const QByteArray &codecName)
+{
+ //qDebug() << "EVIL: " << str << isUtf8 << format << codecName;
+ if (isUtf8)
+ return protect(str);
+ if (format == 20)
+ return protect(str);
+ if (codecName == "UTF-8")
+ return protect(str);
+ QTextCodec *codec = QTextCodec::codecForName(codecName);
+ if (!codec)
+ return protect(str);
+ QString t = QString::fromLatin1(codec->fromUnicode(protect(str)).data());
+ int len = (int) t.length();
+ QString result;
+ // FIXME: Factor is sensible only for latin scripts, probably.
+ result.reserve(t.length() * 2);
+ for (int k = 0; k < len; k++) {
+ if (t[k].unicode() >= 0x7f)
+ result += numericEntity(t[k].unicode());
+ else
+ result += t[k];
+ }
+ return result;
+}
+
+static void writeExtras(QTextStream &t, const char *indent,
+ const TranslatorMessage::ExtraData &extras, const QRegExp &drops)
+{
+ for (Translator::ExtraData::ConstIterator it = extras.begin(); it != extras.end(); ++it) {
+ if (!drops.exactMatch(it.key())) {
+ t << indent << "<extra-" << it.key() << '>'
+ << protect(it.value())
+ << "</extra-" << it.key() << ">\n";
+ }
+ }
+}
+
+static void writeVariants(QTextStream &t, const char *indent, const QString &input)
+{
+ int offset;
+ if ((offset = input.indexOf(QChar(Translator::DefaultVariantSeparator))) >= 0) {
+ t << " variants=\"yes\">";
+ int start = 0;
+ forever {
+ t << "\n " << indent << "<lengthvariant>"
+ << protect(input.mid(start, offset - start))
+ << "</lengthvariant>";
+ if (offset == input.length())
+ break;
+ start = offset + 1;
+ offset = input.indexOf(QChar(Translator::DefaultVariantSeparator), start);
+ if (offset < 0)
+ offset = input.length();
+ }
+ t << "\n" << indent;
+ } else {
+ t << ">" << protect(input);
+ }
+}
+
+bool saveTS(const Translator &translator, QIODevice &dev, ConversionData &cd, int format)
+{
+ bool result = true;
+ QTextStream t(&dev);
+ t.setCodec(QTextCodec::codecForName("UTF-8"));
+ bool trIsUtf8 = (translator.codecName() == "UTF-8");
+ //qDebug() << translator.codecName();
+ bool fileIsUtf8 = (format == 20 || trIsUtf8);
+
+ // The xml prolog allows processors to easily detect the correct encoding
+ t << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE TS>\n";
+
+ if (format == 11)
+ t << "<TS version=\"1.1\"";
+ else
+ t << "<TS version=\"2.0\"";
+
+ QString languageCode = translator.languageCode();
+ if (!languageCode.isEmpty() && languageCode != QLatin1String("C"))
+ t << " language=\"" << languageCode << "\"";
+ if (format == 20) {
+ languageCode = translator.sourceLanguageCode();
+ if (!languageCode.isEmpty() && languageCode != QLatin1String("C"))
+ t << " sourcelanguage=\"" << languageCode << "\"";
+ }
+ t << ">\n";
+
+ QByteArray codecName = translator.codecName();
+ if (codecName != "ISO-8859-1")
+ t << "<defaultcodec>" << codecName << "</defaultcodec>\n";
+
+ QRegExp drops(cd.dropTags().join(QLatin1String("|")));
+
+ if (format == 20)
+ writeExtras(t, " ", translator.extras(), drops);
+
+ QHash<QString, QList<TranslatorMessage> > messageOrder;
+ QList<QString> contextOrder;
+ foreach (const TranslatorMessage &msg, translator.messages()) {
+ // no need for such noise
+ if (msg.type() == TranslatorMessage::Obsolete && msg.translation().isEmpty())
+ continue;
+
+ QList<TranslatorMessage> &context = messageOrder[msg.context()];
+ if (context.isEmpty())
+ contextOrder.append(msg.context());
+ context.append(msg);
+ }
+ if (cd.sortContexts())
+ qSort(contextOrder);
+
+ QHash<QString, int> currentLine;
+ QString currentFile;
+ foreach (const QString &context, contextOrder) {
+ const TranslatorMessage &firstMsg = messageOrder[context].first();
+ t << "<context" << ((!fileIsUtf8 && firstMsg.isUtf8()) ? " encoding=\"UTF-8\"" : "") << ">\n";
+
+ t << " <name>"
+ << evilBytes(context, firstMsg.isUtf8() || fileIsUtf8, format, codecName)
+ << "</name>\n";
+ foreach (const TranslatorMessage &msg, messageOrder[context]) {
+ //msg.dump();
+
+ t << " <message";
+ if (!msg.id().isEmpty())
+ t << " id=\"" << msg.id() << "\"";
+ if (format == 11 && !trIsUtf8 && msg.isUtf8())
+ t << " encoding=\"UTF-8\"";
+ if (format == 20 && !trIsUtf8 && msg.isUtf8())
+ t << " utf8=\"true\"";
+ if (msg.isPlural())
+ t << " numerus=\"yes\"";
+ t << ">\n";
+ if (translator.locationsType() != Translator::NoLocations) {
+ QString cfile = currentFile;
+ bool first = true;
+ foreach (const TranslatorMessage::Reference &ref, msg.allReferences()) {
+ QString fn = cd.m_targetDir.relativeFilePath(ref.fileName())
+ .replace(QLatin1Char('\\'),QLatin1Char('/'));
+ int ln = ref.lineNumber();
+ QString ld;
+ if (translator.locationsType() == Translator::RelativeLocations) {
+ if (ln != -1) {
+ int dlt = ln - currentLine[fn];
+ if (dlt >= 0)
+ ld.append(QLatin1Char('+'));
+ ld.append(QString::number(dlt));
+ currentLine[fn] = ln;
+ }
+
+ if (fn != cfile) {
+ if (first)
+ currentFile = fn;
+ cfile = fn;
+ } else {
+ fn.clear();
+ }
+ first = false;
+ } else {
+ if (ln != -1)
+ ld = QString::number(ln);
+ }
+ t << " <location";
+ if (!fn.isEmpty())
+ t << " filename=\"" << fn << "\"";
+ if (!ld.isEmpty())
+ t << " line=\"" << ld << "\"";
+ t << "/>\n";
+ }
+ }
+
+ t << " <source>"
+ << evilBytes(msg.sourceText(), msg.isUtf8(), format, codecName)
+ << "</source>\n";
+
+ if (format != 11 && !msg.oldSourceText().isEmpty())
+ t << " <oldsource>" << protect(msg.oldSourceText()) << "</oldsource>\n";
+
+ if (!msg.comment().isEmpty()) {
+ t << " <comment>"
+ << evilBytes(msg.comment(), msg.isUtf8(), format, codecName)
+ << "</comment>\n";
+ }
+
+ if (format != 11) {
+
+ if (!msg.oldComment().isEmpty())
+ t << " <oldcomment>" << protect(msg.oldComment()) << "</oldcomment>\n";
+
+ if (!msg.extraComment().isEmpty())
+ t << " <extracomment>" << protect(msg.extraComment())
+ << "</extracomment>\n";
+
+ if (!msg.translatorComment().isEmpty())
+ t << " <translatorcomment>" << protect(msg.translatorComment())
+ << "</translatorcomment>\n";
+
+ }
+
+ t << " <translation";
+ if (msg.type() == TranslatorMessage::Unfinished)
+ t << " type=\"unfinished\"";
+ else if (msg.type() == TranslatorMessage::Obsolete)
+ t << " type=\"obsolete\"";
+ if (msg.isPlural()) {
+ t << ">";
+ QStringList translns = translator.normalizedTranslations(msg, cd, &result);
+ for (int j = 0; j < qMax(1, translns.count()); ++j) {
+ t << "\n <numerusform";
+ writeVariants(t, " ", translns[j]);
+ t << "</numerusform>";
+ }
+ t << "\n ";
+ } else {
+ writeVariants(t, " ", msg.translation());
+ }
+ t << "</translation>\n";
+
+ if (format != 11)
+ writeExtras(t, " ", msg.extras(), drops);
+
+ if (!msg.userData().isEmpty())
+ t << " <userdata>" << msg.userData() << "</userdata>\n";
+ t << " </message>\n";
+ }
+ t << "</context>\n";
+ }
+
+ t << "</TS>\n";
+ return result;
+}
+
+bool loadTS(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ translator.setLocationsType(Translator::NoLocations);
+ TSReader reader(dev, cd);
+ return reader.read(translator);
+}
+
+bool saveTS11(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ return saveTS(translator, dev, cd, 11);
+}
+
+bool saveTS20(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ return saveTS(translator, dev, cd, 20);
+}
+
+int initTS()
+{
+ Translator::FileFormat format;
+
+ format.extension = QLatin1String("ts11");
+ format.fileType = Translator::FileFormat::TranslationSource;
+ format.priority = -1;
+ format.description = QObject::tr("Qt translation sources (format 1.1)");
+ format.loader = &loadTS;
+ format.saver = &saveTS11;
+ Translator::registerFileFormat(format);
+
+ format.extension = QLatin1String("ts20");
+ format.fileType = Translator::FileFormat::TranslationSource;
+ format.priority = -1;
+ format.description = QObject::tr("Qt translation sources (format 2.0)");
+ format.loader = &loadTS;
+ format.saver = &saveTS20;
+ Translator::registerFileFormat(format);
+
+ // "ts" is always the latest. right now it's ts20.
+ format.extension = QLatin1String("ts");
+ format.fileType = Translator::FileFormat::TranslationSource;
+ format.priority = 0;
+ format.description = QObject::tr("Qt translation sources (latest format)");
+ format.loader = &loadTS;
+ format.saver = &saveTS20;
+ Translator::registerFileFormat(format);
+
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initTS)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/ts.dtd b/tools/linguist/shared/ts.dtd
new file mode 100644
index 0000000000..ab77f64604
--- /dev/null
+++ b/tools/linguist/shared/ts.dtd
@@ -0,0 +1,113 @@
+<!--
+ !
+ ! Some notes to the DTD:
+ !
+ ! The location element is set as optional since it was introduced first in Qt 4.2.
+ ! The userdata element is set as optional since it was introduced first in Qt 4.4.
+ ! The source and translation elements are optional starting with version 3.0
+ ! (Qt 4.6) to support S60 blank messages.
+ !
+ -->
+<!--
+ ! Macro used in order to escape byte entities not allowed in an xml document
+ ! for instance, only #x9, #xA and #xD are allowed characters below #x20.
+ -->
+<!ENTITY % evilstring '(#PCDATA | byte)*' >
+<!ELEMENT byte EMPTY>
+<!-- value contains decimal (e.g. 1000) or hex (e.g. x3e8) unicode encoding of one char -->
+<!ATTLIST byte
+ value CDATA #REQUIRED>
+<!--
+ ! This element wildcard is no valid DTD. No better solution available.
+ ! extra elements may appear in TS and message elements. Each element may appear
+ ! only once within each scope. The contents are preserved verbatim; any
+ ! attributes are dropped. Currently recognized extra tags include:
+ ! extra-po-msgid_plural, extra-po-old_msgid_plural
+ ! extra-po-flags (comma-space separated list)
+ ! extra-loc-layout_id
+ ! extra-loc-feature
+ ! extra-loc-blank
+ -->
+<!ELEMENT extra-* %evilstring; >
+<!ELEMENT TS (defaultcodec?, extra-**, (context|message)+) >
+<!ATTLIST TS
+ version CDATA #IMPLIED
+ sourcelanguage CDATA #IMPLIED
+ language CDATA #IMPLIED>
+<!-- The encoding to use in the .qm file by default. Default is ISO-8859-1. -->
+<!ELEMENT defaultcodec (#PCDATA) >
+<!ELEMENT context (name?, comment?, (context|message)+) >
+<!ATTLIST context
+ encoding CDATA #IMPLIED>
+<!ELEMENT name %evilstring; >
+<!-- If "no", then the context nesting is for informational puposes only -->
+<!ATTLIST name
+ nest (yes|no) "yes">
+<!-- This is "disambiguation" in the (new) API, or "msgctxt" in gettext speak -->
+<!ELEMENT comment %evilstring; >
+<!-- Previous content of comment (result of merge) -->
+<!ELEMENT oldcomment %evilstring; >
+<!-- The real comment (added by developer/designer) -->
+<!ELEMENT extracomment %evilstring; >
+<!-- Comment added by translator -->
+<!ELEMENT translatorcomment %evilstring; >
+<!ELEMENT message (location*, source?, oldsource?, comment?, oldcomment?, extracomment?, translatorcomment?, translation?, userdata?, extra-**) >
+<!--
+ ! If utf8 is true, the defaultcodec is overridden and the message is encoded
+ ! in UTF-8 in the .qm file.
+ -->
+<!ATTLIST message
+ id CDATA #IMPLIED
+ utf8 (true|false) "false"
+ numerus (yes|no) "no">
+<!ELEMENT location EMPTY>
+<!--
+ ! If the line is omitted, the location specifies only a file.
+ !
+ ! location supports relative specifications as well. Line numbers are
+ ! relative (explicitly positive or negative) to the last reference to a
+ ! given filename; each file starts with current line 0. If the filename
+ ! is omitted, the "current" one is used. For the 1st location in a message,
+ ! "current" is the filename used for the 1st location of the previous message.
+ ! For subsequent locations, it is the filename used for the previous location.
+ ! A single .ts file has either all absolute or all relative locations.
+ -->
+<!ATTLIST location
+ filename CDATA #IMPLIED
+ line CDATA #IMPLIED>
+<!ELEMENT source %evilstring;>
+<!-- Previous content of source (result of merge) -->
+<!ELEMENT oldsource %evilstring;>
+<!--
+ ! The following should really say one evilstring macro or several
+ ! numerusform or lengthvariant elements, but the DTD can't express this.
+ -->
+<!ELEMENT translation (#PCDATA|byte|numerusform|lengthvariant)* >
+<!--
+ ! If no type is set, the message is "finished".
+ ! Length variants must be ordered by falling display length.
+ ! variants may not be yes if the message has numerus yes.
+ -->
+<!ATTLIST translation
+ type (unfinished|obsolete) #IMPLIED
+ variants (yes|no) "no">
+<!-- Deprecated. Use extra-* -->
+<!ELEMENT userdata (#PCDATA)* >
+<!--
+ ! The following should really say one evilstring macro or several
+ ! lengthvariant elements, but the DTD can't express this.
+ ! Length variants must be ordered by falling display length.
+ -->
+<!ELEMENT numerusform (#PCDATA|byte|lengthvariant)* >
+<!ATTLIST numerusform
+ plurality (nullar|singular|dual|trial|paucal|greaterpaucal|plural|greaterplural) #IMPLIED>
+ variants (yes|no) "no">
+<!ELEMENT lengthvariant %evilstring; >
+<!--
+ ! The translation variants have a priority between 1 ("highest") and 9 ("lowest")
+ ! Typically longer translations get a higher priority.
+ ! If omitted, the order of appearance of the variants in the .ts files is used.
+ -->
+<!ATTLIST lengthvariant
+ priority (1|2|3|4|5|6|7|8|9) #IMPLIED>
+
diff --git a/tools/linguist/shared/ui.cpp b/tools/linguist/shared/ui.cpp
new file mode 100644
index 0000000000..4b86714ee1
--- /dev/null
+++ b/tools/linguist/shared/ui.cpp
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QString>
+
+#include <QtXml/QXmlAttributes>
+#include <QtXml/QXmlDefaultHandler>
+#include <QtXml/QXmlLocator>
+#include <QtXml/QXmlParseException>
+
+
+QT_BEGIN_NAMESPACE
+
+// in cpp.cpp
+void fetchtrInlinedCpp(const QString &in, Translator &tor, const QString &context);
+
+class UiReader : public QXmlDefaultHandler
+{
+public:
+ UiReader(Translator &translator, ConversionData &cd)
+ : m_translator(translator), m_cd(cd), m_lineNumber(-1),
+ m_needUtf8(translator.codecName() != "UTF-8")
+ {}
+
+ bool startElement(const QString &namespaceURI, const QString &localName,
+ const QString &qName, const QXmlAttributes &atts);
+ bool endElement(const QString &namespaceURI, const QString &localName,
+ const QString &qName);
+ bool characters(const QString &ch);
+ bool fatalError(const QXmlParseException &exception);
+
+ void setDocumentLocator(QXmlLocator *locator) { m_locator = locator; }
+
+private:
+ void flush();
+
+ Translator &m_translator;
+ ConversionData &m_cd;
+ QString m_context;
+ QString m_source;
+ QString m_comment;
+ QXmlLocator *m_locator;
+
+ QString m_accum;
+ int m_lineNumber;
+ bool m_isTrString;
+ bool m_needUtf8;
+};
+
+bool UiReader::startElement(const QString &namespaceURI,
+ const QString &localName, const QString &qName, const QXmlAttributes &atts)
+{
+ Q_UNUSED(namespaceURI);
+ Q_UNUSED(localName);
+
+ if (qName == QLatin1String("item")) {
+ flush();
+ if (!atts.value(QLatin1String("text")).isEmpty())
+ m_source = atts.value(QLatin1String("text"));
+ } else if (qName == QLatin1String("string")) {
+ flush();
+ if (atts.value(QLatin1String("notr")).isEmpty() ||
+ atts.value(QLatin1String("notr")) != QLatin1String("true")) {
+ m_isTrString = true;
+ m_comment = atts.value(QLatin1String("comment"));
+ } else {
+ m_isTrString = false;
+ }
+ }
+ if (m_isTrString && !m_cd.m_noUiLines)
+ m_lineNumber = m_locator->lineNumber();
+ m_accum.clear();
+ return true;
+}
+
+bool UiReader::endElement(const QString &namespaceURI,
+ const QString &localName, const QString &qName)
+{
+ Q_UNUSED(namespaceURI);
+ Q_UNUSED(localName);
+
+ m_accum.replace(QLatin1String("\r\n"), QLatin1String("\n"));
+
+ if (qName == QLatin1String("class")) {
+ if (m_context.isEmpty())
+ m_context = m_accum;
+ } else if (qName == QLatin1String("string") && m_isTrString) {
+ m_source = m_accum;
+ } else if (qName == QLatin1String("comment")) {
+ m_comment = m_accum;
+ flush();
+ } else if (qName == QLatin1String("function")) {
+ fetchtrInlinedCpp(m_accum, m_translator, m_context);
+ } else {
+ flush();
+ }
+ return true;
+}
+
+bool UiReader::characters(const QString &ch)
+{
+ m_accum += ch;
+ return true;
+}
+
+bool UiReader::fatalError(const QXmlParseException &exception)
+{
+ QString msg;
+ msg.sprintf("XML error: Parse error at line %d, column %d (%s).",
+ exception.lineNumber(), exception.columnNumber(),
+ exception.message().toLatin1().data());
+ m_cd.appendError(msg);
+ return false;
+}
+
+void UiReader::flush()
+{
+ if (!m_context.isEmpty() && !m_source.isEmpty()) {
+ TranslatorMessage msg(m_context, m_source,
+ m_comment, QString(), m_cd.m_sourceFileName,
+ m_lineNumber, QStringList());
+ if (m_needUtf8 && msg.needs8Bit())
+ msg.setUtf8(true);
+ m_translator.extend(msg);
+ }
+ m_source.clear();
+ m_comment.clear();
+}
+
+bool loadUI(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ QXmlInputSource in(&dev);
+ QXmlSimpleReader reader;
+ reader.setFeature(QLatin1String("http://xml.org/sax/features/namespaces"), false);
+ reader.setFeature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"), true);
+ reader.setFeature(QLatin1String(
+ "http://trolltech.com/xml/features/report-whitespace-only-CharData"), false);
+ UiReader handler(translator, cd);
+ reader.setContentHandler(&handler);
+ reader.setErrorHandler(&handler);
+ bool result = reader.parse(in);
+ if (!result)
+ cd.appendError(QLatin1String("Parse error in UI file"));
+ reader.setContentHandler(0);
+ reader.setErrorHandler(0);
+ return result;
+}
+
+bool saveUI(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ Q_UNUSED(dev);
+ Q_UNUSED(translator);
+ cd.appendError(QLatin1String("Cannot save .ui files"));
+ return false;
+}
+
+int initUI()
+{
+ Translator::FileFormat format;
+
+ // "real" Qt Designer
+ format.extension = QLatin1String("ui");
+ format.description = QObject::tr("Qt Designer form files");
+ format.fileType = Translator::FileFormat::SourceCode;
+ format.priority = 0;
+ format.loader = &loadUI;
+ format.saver = &saveUI;
+ Translator::registerFileFormat(format);
+
+ // same for jambi
+ format.extension = QLatin1String("jui");
+ format.description = QObject::tr("Qt Jambi form files");
+ format.fileType = Translator::FileFormat::SourceCode;
+ format.priority = 0;
+ format.loader = &loadUI;
+ format.saver = &saveUI;
+ Translator::registerFileFormat(format);
+
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initUI)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/shared/xliff.cpp b/tools/linguist/shared/xliff.cpp
new file mode 100644
index 0000000000..6acf67abf3
--- /dev/null
+++ b/tools/linguist/shared/xliff.cpp
@@ -0,0 +1,828 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt Linguist of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translator.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMap>
+#include <QtCore/QStack>
+#include <QtCore/QString>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+
+#include <QtXml/QXmlAttributes>
+#include <QtXml/QXmlDefaultHandler>
+#include <QtXml/QXmlParseException>
+
+
+QT_BEGIN_NAMESPACE
+
+/**
+ * Implementation of XLIFF file format for Linguist
+ */
+//static const char *restypeDomain = "x-gettext-domain";
+static const char *restypeContext = "x-trolltech-linguist-context";
+static const char *restypePlurals = "x-gettext-plurals";
+static const char *restypeDummy = "x-dummy";
+static const char *dataTypeUIFile = "x-trolltech-designer-ui";
+static const char *contextMsgctxt = "x-gettext-msgctxt"; // XXX Troll invention, so far.
+static const char *contextOldMsgctxt = "x-gettext-previous-msgctxt"; // XXX Troll invention, so far.
+static const char *attribPlural = "trolltech:plural";
+static const char *XLIFF11namespaceURI = "urn:oasis:names:tc:xliff:document:1.1";
+static const char *XLIFF12namespaceURI = "urn:oasis:names:tc:xliff:document:1.2";
+static const char *TrollTsNamespaceURI = "urn:trolltech:names:ts:document:1.0";
+
+#define COMBINE4CHARS(c1, c2, c3, c4) \
+ (int(c1) << 24 | int(c2) << 16 | int(c3) << 8 | int(c4) )
+
+static QString dataType(const TranslatorMessage &m)
+{
+ QByteArray fileName = m.fileName().toAscii();
+ unsigned int extHash = 0;
+ int pos = fileName.count() - 1;
+ for (int pass = 0; pass < 4 && pos >=0; ++pass, --pos) {
+ if (fileName.at(pos) == '.')
+ break;
+ extHash |= ((int)fileName.at(pos) << (8*pass));
+ }
+
+ switch (extHash) {
+ case COMBINE4CHARS(0,'c','p','p'):
+ case COMBINE4CHARS(0,'c','x','x'):
+ case COMBINE4CHARS(0,'c','+','+'):
+ case COMBINE4CHARS(0,'h','p','p'):
+ case COMBINE4CHARS(0,'h','x','x'):
+ case COMBINE4CHARS(0,'h','+','+'):
+ return QLatin1String("cpp");
+ case COMBINE4CHARS(0, 0 , 0 ,'c'):
+ case COMBINE4CHARS(0, 0 , 0 ,'h'):
+ case COMBINE4CHARS(0, 0 ,'c','c'):
+ case COMBINE4CHARS(0, 0 ,'c','h'):
+ case COMBINE4CHARS(0, 0 ,'h','h'):
+ return QLatin1String("c");
+ case COMBINE4CHARS(0, 0 ,'u','i'):
+ return QLatin1String(dataTypeUIFile); //### form?
+ default:
+ return QLatin1String("plaintext"); // we give up
+ }
+}
+
+static void writeIndent(QTextStream &ts, int indent)
+{
+ ts << QString().fill(QLatin1Char(' '), indent * 2);
+}
+
+struct CharMnemonic
+{
+ char ch;
+ char escape;
+ const char *mnemonic;
+};
+
+static const CharMnemonic charCodeMnemonics[] = {
+ {0x07, 'a', "bel"},
+ {0x08, 'b', "bs"},
+ {0x09, 't', "tab"},
+ {0x0a, 'n', "lf"},
+ {0x0b, 'v', "vt"},
+ {0x0c, 'f', "ff"},
+ {0x0d, 'r', "cr"}
+};
+
+static char charFromEscape(char escape)
+{
+ for (uint i = 0; i < sizeof(charCodeMnemonics)/sizeof(CharMnemonic); ++i) {
+ CharMnemonic cm = charCodeMnemonics[i];
+ if (cm.escape == escape)
+ return cm.ch;
+ }
+ Q_ASSERT(0);
+ return escape;
+}
+
+static QString numericEntity(int ch, bool makePhs)
+{
+ // ### This needs to be reviewed, to reflect the updated XLIFF-PO spec.
+ if (!makePhs || ch < 7 || ch > 0x0d)
+ return QString::fromAscii("&#x%1;").arg(QString::number(ch, 16));
+
+ CharMnemonic cm = charCodeMnemonics[int(ch) - 7];
+ QString name = QLatin1String(cm.mnemonic);
+ char escapechar = cm.escape;
+
+ static int id = 0;
+ return QString::fromAscii("<ph id=\"ph%1\" ctype=\"x-ch-%2\">\\%3</ph>")
+ .arg(++id) .arg(name) .arg(escapechar);
+}
+
+static QString protect(const QString &str, bool makePhs = true)
+{
+ QString result;
+ int len = str.size();
+ for (int i = 0; i != len; ++i) {
+ uint c = str.at(i).unicode();
+ switch (c) {
+ case '\"':
+ result += QLatin1String("&quot;");
+ break;
+ case '&':
+ result += QLatin1String("&amp;");
+ break;
+ case '>':
+ result += QLatin1String("&gt;");
+ break;
+ case '<':
+ result += QLatin1String("&lt;");
+ break;
+ case '\'':
+ result += QLatin1String("&apos;");
+ break;
+ default:
+ if (c < 0x20 && c != '\r' && c != '\n' && c != '\t')
+ result += numericEntity(c, makePhs);
+ else // this also covers surrogates
+ result += QChar(c);
+ }
+ }
+ return result;
+}
+
+
+static void writeExtras(QTextStream &ts, int indent,
+ const TranslatorMessage::ExtraData &extras, const QRegExp &drops)
+{
+ for (Translator::ExtraData::ConstIterator it = extras.begin(); it != extras.end(); ++it) {
+ if (!drops.exactMatch(it.key())) {
+ writeIndent(ts, indent);
+ ts << "<trolltech:" << it.key() << '>'
+ << protect(it.value())
+ << "</trolltech:" << it.key() << ">\n";
+ }
+ }
+}
+
+static void writeLineNumber(QTextStream &ts, const TranslatorMessage &msg, int indent)
+{
+ if (msg.lineNumber() == -1)
+ return;
+ writeIndent(ts, indent);
+ ts << "<context-group purpose=\"location\"><context context-type=\"linenumber\">"
+ << msg.lineNumber() << "</context></context-group>\n";
+ foreach (const TranslatorMessage::Reference &ref, msg.extraReferences()) {
+ writeIndent(ts, indent);
+ ts << "<context-group purpose=\"location\">";
+ if (ref.fileName() != msg.fileName())
+ ts << "<context context-type=\"sourcefile\">" << ref.fileName() << "</context>";
+ ts << "<context context-type=\"linenumber\">" << ref.lineNumber()
+ << "</context></context-group>\n";
+ }
+}
+
+static void writeComment(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent)
+{
+ if (!msg.comment().isEmpty()) {
+ writeIndent(ts, indent);
+ ts << "<context-group><context context-type=\"" << contextMsgctxt << "\">"
+ << protect(msg.comment(), false)
+ << "</context></context-group>\n";
+ }
+ if (!msg.oldComment().isEmpty()) {
+ writeIndent(ts, indent);
+ ts << "<context-group><context context-type=\"" << contextOldMsgctxt << "\">"
+ << protect(msg.oldComment(), false)
+ << "</context></context-group>\n";
+ }
+ writeExtras(ts, indent, msg.extras(), drops);
+ if (!msg.extraComment().isEmpty()) {
+ writeIndent(ts, indent);
+ ts << "<note annotates=\"source\" from=\"developer\">"
+ << protect(msg.extraComment()) << "</note>\n";
+ }
+ if (!msg.translatorComment().isEmpty()) {
+ writeIndent(ts, indent);
+ ts << "<note from=\"translator\">"
+ << protect(msg.translatorComment()) << "</note>\n";
+ }
+}
+
+static void writeTransUnits(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent,
+ const Translator &translator, ConversionData &cd, bool *ok)
+{
+ static int msgid;
+ QString msgidstr = !msg.id().isEmpty() ? msg.id() : QString::fromAscii("_msg%1").arg(++msgid);
+
+ QStringList translns = translator.normalizedTranslations(msg, cd, ok);
+ QHash<QString, QString>::const_iterator it;
+ QString pluralStr;
+ QStringList sources(msg.sourceText());
+ if ((it = msg.extras().find(QString::fromLatin1("po-msgid_plural"))) != msg.extras().end())
+ sources.append(*it);
+ QStringList oldsources;
+ if (!msg.oldSourceText().isEmpty())
+ oldsources.append(msg.oldSourceText());
+ if ((it = msg.extras().find(QString::fromLatin1("po-old_msgid_plural"))) != msg.extras().end()) {
+ if (oldsources.isEmpty()) {
+ if (sources.count() == 2)
+ oldsources.append(QString());
+ else
+ pluralStr = QLatin1Char(' ') + QLatin1String(attribPlural) + QLatin1String("=\"yes\"");
+ }
+ oldsources.append(*it);
+ }
+
+ QStringList::const_iterator
+ srcit = sources.begin(), srcend = sources.end(),
+ oldsrcit = oldsources.begin(), oldsrcend = oldsources.end(),
+ transit = translns.begin(), transend = translns.end();
+ int plural = 0;
+ QString source;
+ while (srcit != srcend || oldsrcit != oldsrcend || transit != transend) {
+ QByteArray attribs;
+ QByteArray state;
+ if (msg.type() == TranslatorMessage::Obsolete) {
+ if (!msg.isPlural())
+ attribs = " translate=\"no\"";
+ } else if (msg.type() == TranslatorMessage::Finished) {
+ attribs = " approved=\"yes\"";
+ } else if (transit != transend && !transit->isEmpty()) {
+ state = " state=\"needs-review-translation\"";
+ }
+ writeIndent(ts, indent);
+ ts << "<trans-unit id=\"" << msgidstr;
+ if (msg.isPlural())
+ ts << "[" << plural++ << "]";
+ ts << "\"" << attribs << ">\n";
+ ++indent;
+
+ writeIndent(ts, indent);
+ if (srcit != srcend) {
+ source = *srcit;
+ ++srcit;
+ } // else just repeat last element
+ ts << "<source xml:space=\"preserve\">" << protect(source) << "</source>\n";
+
+ bool puttrans = false;
+ QString translation;
+ if (transit != transend) {
+ translation = *transit;
+ ++transit;
+ puttrans = true;
+ }
+ do {
+ if (oldsrcit != oldsrcend && !oldsrcit->isEmpty()) {
+ writeIndent(ts, indent);
+ ts << "<alt-trans>\n";
+ ++indent;
+ writeIndent(ts, indent);
+ ts << "<source xml:space=\"preserve\"" << pluralStr << '>' << protect(*oldsrcit) << "</source>\n";
+ if (!puttrans) {
+ writeIndent(ts, indent);
+ ts << "<target restype=\"" << restypeDummy << "\"/>\n";
+ }
+ }
+
+ if (puttrans) {
+ writeIndent(ts, indent);
+ ts << "<target xml:space=\"preserve\"" << state << ">" << protect(translation) << "</target>\n";
+ }
+
+ if (oldsrcit != oldsrcend) {
+ if (!oldsrcit->isEmpty()) {
+ --indent;
+ writeIndent(ts, indent);
+ ts << "</alt-trans>\n";
+ }
+ ++oldsrcit;
+ }
+
+ puttrans = false;
+ } while (srcit == srcend && oldsrcit != oldsrcend);
+
+ if (!msg.isPlural()) {
+ writeLineNumber(ts, msg, indent);
+ writeComment(ts, msg, drops, indent);
+ }
+
+ --indent;
+ writeIndent(ts, indent);
+ ts << "</trans-unit>\n";
+ }
+}
+
+static void writeMessage(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent,
+ const Translator &translator, ConversionData &cd, bool *ok)
+{
+ if (msg.isPlural()) {
+ writeIndent(ts, indent);
+ ts << "<group restype=\"" << restypePlurals << "\"";
+ if (!msg.id().isEmpty())
+ ts << " id=\"" << msg.id() << "\"";
+ if (msg.type() == TranslatorMessage::Obsolete)
+ ts << " translate=\"no\"";
+ ts << ">\n";
+ ++indent;
+ writeLineNumber(ts, msg, indent);
+ writeComment(ts, msg, drops, indent);
+
+ writeTransUnits(ts, msg, drops, indent, translator, cd, ok);
+ --indent;
+ writeIndent(ts, indent);
+ ts << "</group>\n";
+ } else {
+ writeTransUnits(ts, msg, drops, indent, translator, cd, ok);
+ }
+}
+
+
+class XLIFFHandler : public QXmlDefaultHandler
+{
+public:
+ XLIFFHandler(Translator &translator, ConversionData &cd);
+
+ bool startElement(const QString& namespaceURI, const QString &localName,
+ const QString &qName, const QXmlAttributes &atts );
+ bool endElement(const QString& namespaceURI, const QString &localName,
+ const QString &qName );
+ bool characters(const QString &ch);
+ bool fatalError(const QXmlParseException &exception);
+
+ bool endDocument();
+
+private:
+ enum XliffContext {
+ XC_xliff,
+ XC_group,
+ XC_trans_unit,
+ XC_context_group,
+ XC_context_group_any,
+ XC_context,
+ XC_context_filename,
+ XC_context_linenumber,
+ XC_context_context,
+ XC_context_comment,
+ XC_context_old_comment,
+ XC_ph,
+ XC_extra_comment,
+ XC_translator_comment,
+ XC_restype_context,
+ XC_restype_translation,
+ XC_restype_plurals,
+ XC_alt_trans
+ };
+ void pushContext(XliffContext ctx);
+ bool popContext(XliffContext ctx);
+ XliffContext currentContext() const;
+ bool hasContext(XliffContext ctx) const;
+ bool finalizeMessage(bool isPlural);
+
+private:
+ Translator &m_translator;
+ ConversionData &m_cd;
+ TranslatorMessage::Type m_type;
+ QString m_language;
+ QString m_sourceLanguage;
+ QString m_context;
+ QString m_id;
+ QStringList m_sources;
+ QStringList m_oldSources;
+ QString m_comment;
+ QString m_oldComment;
+ QString m_extraComment;
+ QString m_translatorComment;
+ bool m_isPlural;
+ bool m_hadAlt;
+ QStringList m_translations;
+ QString m_fileName;
+ int m_lineNumber;
+ QString m_extraFileName;
+ TranslatorMessage::References m_refs;
+ TranslatorMessage::ExtraData m_extra;
+
+ QString accum;
+ QString m_ctype;
+ const QString m_URITT; // convenience and efficiency
+ const QString m_URI; // ...
+ const QString m_URI12; // ...
+ QStack<int> m_contextStack;
+};
+
+XLIFFHandler::XLIFFHandler(Translator &translator, ConversionData &cd)
+ : m_translator(translator), m_cd(cd),
+ m_type(TranslatorMessage::Finished),
+ m_lineNumber(-1),
+ m_URITT(QLatin1String(TrollTsNamespaceURI)),
+ m_URI(QLatin1String(XLIFF11namespaceURI)),
+ m_URI12(QLatin1String(XLIFF12namespaceURI))
+{}
+
+
+void XLIFFHandler::pushContext(XliffContext ctx)
+{
+ m_contextStack.push_back(ctx);
+}
+
+// Only pops it off if the top of the stack contains ctx
+bool XLIFFHandler::popContext(XliffContext ctx)
+{
+ if (!m_contextStack.isEmpty() && m_contextStack.top() == ctx) {
+ m_contextStack.pop();
+ return true;
+ }
+ return false;
+}
+
+XLIFFHandler::XliffContext XLIFFHandler::currentContext() const
+{
+ if (!m_contextStack.isEmpty())
+ return (XliffContext)m_contextStack.top();
+ return XC_xliff;
+}
+
+// traverses to the top to check all of the parent contexes.
+bool XLIFFHandler::hasContext(XliffContext ctx) const
+{
+ for (int i = m_contextStack.count() - 1; i >= 0; --i) {
+ if (m_contextStack.at(i) == ctx)
+ return true;
+ }
+ return false;
+}
+
+bool XLIFFHandler::startElement(const QString& namespaceURI,
+ const QString &localName, const QString &qName, const QXmlAttributes &atts )
+{
+ Q_UNUSED(qName);
+ if (namespaceURI == m_URITT)
+ goto bail;
+ if (namespaceURI != m_URI && namespaceURI != m_URI12)
+ return false;
+ if (localName == QLatin1String("xliff")) {
+ // make sure that the stack is not empty during parsing
+ pushContext(XC_xliff);
+ } else if (localName == QLatin1String("file")) {
+ m_fileName = atts.value(QLatin1String("original"));
+ m_language = atts.value(QLatin1String("target-language"));
+ m_sourceLanguage = atts.value(QLatin1String("source-language"));
+ } else if (localName == QLatin1String("group")) {
+ if (atts.value(QLatin1String("restype")) == QLatin1String(restypeContext)) {
+ m_context = atts.value(QLatin1String("resname"));
+ pushContext(XC_restype_context);
+ } else {
+ if (atts.value(QLatin1String("restype")) == QLatin1String(restypePlurals)) {
+ pushContext(XC_restype_plurals);
+ m_id = atts.value(QLatin1String("id"));
+ if (atts.value(QLatin1String("translate")) == QLatin1String("no"))
+ m_type = TranslatorMessage::Obsolete;
+ } else {
+ pushContext(XC_group);
+ }
+ }
+ } else if (localName == QLatin1String("trans-unit")) {
+ if (!hasContext(XC_restype_plurals) || m_sources.isEmpty() /* who knows ... */)
+ if (atts.value(QLatin1String("translate")) == QLatin1String("no"))
+ m_type = TranslatorMessage::Obsolete;
+ if (!hasContext(XC_restype_plurals)) {
+ m_id = atts.value(QLatin1String("id"));
+ if (m_id.startsWith(QLatin1String("_msg")))
+ m_id.clear();
+ }
+ if (m_type != TranslatorMessage::Obsolete &&
+ atts.value(QLatin1String("approved")) != QLatin1String("yes"))
+ m_type = TranslatorMessage::Unfinished;
+ pushContext(XC_trans_unit);
+ m_hadAlt = false;
+ } else if (localName == QLatin1String("alt-trans")) {
+ pushContext(XC_alt_trans);
+ } else if (localName == QLatin1String("source")) {
+ m_isPlural = atts.value(QLatin1String(attribPlural)) == QLatin1String("yes");
+ } else if (localName == QLatin1String("target")) {
+ if (atts.value(QLatin1String("restype")) != QLatin1String(restypeDummy))
+ pushContext(XC_restype_translation);
+ } else if (localName == QLatin1String("context-group")) {
+ QString purpose = atts.value(QLatin1String("purpose"));
+ if (purpose == QLatin1String("location"))
+ pushContext(XC_context_group);
+ else
+ pushContext(XC_context_group_any);
+ } else if (currentContext() == XC_context_group && localName == QLatin1String("context")) {
+ QString ctxtype = atts.value(QLatin1String("context-type"));
+ if (ctxtype == QLatin1String("linenumber"))
+ pushContext(XC_context_linenumber);
+ else if (ctxtype == QLatin1String("sourcefile"))
+ pushContext(XC_context_filename);
+ } else if (currentContext() == XC_context_group_any && localName == QLatin1String("context")) {
+ QString ctxtype = atts.value(QLatin1String("context-type"));
+ if (ctxtype == QLatin1String(contextMsgctxt))
+ pushContext(XC_context_comment);
+ else if (ctxtype == QLatin1String(contextOldMsgctxt))
+ pushContext(XC_context_old_comment);
+ } else if (localName == QLatin1String("note")) {
+ if (atts.value(QLatin1String("annotates")) == QLatin1String("source") &&
+ atts.value(QLatin1String("from")) == QLatin1String("developer"))
+ pushContext(XC_extra_comment);
+ else
+ pushContext(XC_translator_comment);
+ } else if (localName == QLatin1String("ph")) {
+ QString ctype = atts.value(QLatin1String("ctype"));
+ if (ctype.startsWith(QLatin1String("x-ch-")))
+ m_ctype = ctype.mid(5);
+ pushContext(XC_ph);
+ }
+bail:
+ if (currentContext() != XC_ph)
+ accum.clear();
+ return true;
+}
+
+bool XLIFFHandler::endElement(const QString &namespaceURI, const QString& localName,
+ const QString &qName)
+{
+ Q_UNUSED(qName);
+ if (namespaceURI == m_URITT) {
+ if (hasContext(XC_trans_unit) || hasContext(XC_restype_plurals))
+ m_extra[localName] = accum;
+ else
+ m_translator.setExtra(localName, accum);
+ return true;
+ }
+ if (namespaceURI != m_URI && namespaceURI != m_URI12)
+ return false;
+ //qDebug() << "URI:" << namespaceURI << "QNAME:" << qName;
+ if (localName == QLatin1String("xliff")) {
+ popContext(XC_xliff);
+ } else if (localName == QLatin1String("source")) {
+ if (hasContext(XC_alt_trans)) {
+ if (m_isPlural && m_oldSources.isEmpty())
+ m_oldSources.append(QString());
+ m_oldSources.append(accum);
+ m_hadAlt = true;
+ } else {
+ m_sources.append(accum);
+ }
+ } else if (localName == QLatin1String("target")) {
+ if (popContext(XC_restype_translation))
+ m_translations.append(accum);
+ } else if (localName == QLatin1String("context-group")) {
+ if (popContext(XC_context_group)) {
+ m_refs.append(TranslatorMessage::Reference(
+ m_extraFileName.isEmpty() ? m_fileName : m_extraFileName, m_lineNumber));
+ m_extraFileName.clear();
+ m_lineNumber = -1;
+ } else {
+ popContext(XC_context_group_any);
+ }
+ } else if (localName == QLatin1String("context")) {
+ if (popContext(XC_context_linenumber)) {
+ bool ok;
+ m_lineNumber = accum.trimmed().toInt(&ok);
+ if (!ok)
+ m_lineNumber = -1;
+ } else if (popContext(XC_context_filename)) {
+ m_extraFileName = accum;
+ } else if (popContext(XC_context_comment)) {
+ m_comment = accum;
+ } else if (popContext(XC_context_old_comment)) {
+ m_oldComment = accum;
+ }
+ } else if (localName == QLatin1String("note")) {
+ if (popContext(XC_extra_comment))
+ m_extraComment = accum;
+ else if (popContext(XC_translator_comment))
+ m_translatorComment = accum;
+ } else if (localName == QLatin1String("ph")) {
+ m_ctype.clear();
+ popContext(XC_ph);
+ } else if (localName == QLatin1String("trans-unit")) {
+ popContext(XC_trans_unit);
+ if (!m_hadAlt)
+ m_oldSources.append(QString());
+ if (!hasContext(XC_restype_plurals)) {
+ if (!finalizeMessage(false))
+ return false;
+ }
+ } else if (localName == QLatin1String("alt-trans")) {
+ popContext(XC_alt_trans);
+ } else if (localName == QLatin1String("group")) {
+ if (popContext(XC_restype_plurals)) {
+ if (!finalizeMessage(true))
+ return false;
+ } else if (popContext(XC_restype_context)) {
+ m_context.clear();
+ } else {
+ popContext(XC_group);
+ }
+ }
+ return true;
+}
+
+bool XLIFFHandler::characters(const QString &ch)
+{
+ if (currentContext() == XC_ph) {
+ // handle the content of <ph> elements
+ for (int i = 0; i < ch.count(); ++i) {
+ QChar chr = ch.at(i);
+ if (accum.endsWith(QLatin1Char('\\')))
+ accum[accum.size() - 1] = QLatin1Char(charFromEscape(chr.toAscii()));
+ else
+ accum.append(chr);
+ }
+ } else {
+ QString t = ch;
+ t.replace(QLatin1String("\r"), QLatin1String(""));
+ accum.append(t);
+ }
+ return true;
+}
+
+bool XLIFFHandler::endDocument()
+{
+ m_translator.setLanguageCode(m_language);
+ m_translator.setSourceLanguageCode(m_sourceLanguage);
+ return true;
+}
+
+bool XLIFFHandler::finalizeMessage(bool isPlural)
+{
+ if (m_sources.isEmpty()) {
+ m_cd.appendError(QLatin1String("XLIFF syntax error: Message without source string."));
+ return false;
+ }
+ TranslatorMessage msg(m_context, m_sources[0],
+ m_comment, QString(), QString(), -1,
+ m_translations, m_type, isPlural);
+ msg.setId(m_id);
+ msg.setReferences(m_refs);
+ msg.setOldComment(m_oldComment);
+ msg.setExtraComment(m_extraComment);
+ msg.setTranslatorComment(m_translatorComment);
+ if (m_sources.count() > 1 && m_sources[1] != m_sources[0])
+ m_extra.insert(QLatin1String("po-msgid_plural"), m_sources[1]);
+ if (!m_oldSources.isEmpty()) {
+ if (!m_oldSources[0].isEmpty())
+ msg.setOldSourceText(m_oldSources[0]);
+ if (m_oldSources.count() > 1 && m_oldSources[1] != m_oldSources[0])
+ m_extra.insert(QLatin1String("po-old_msgid_plural"), m_oldSources[1]);
+ }
+ msg.setExtras(m_extra);
+ m_translator.append(msg);
+
+ m_id.clear();
+ m_sources.clear();
+ m_oldSources.clear();
+ m_translations.clear();
+ m_comment.clear();
+ m_oldComment.clear();
+ m_extraComment.clear();
+ m_translatorComment.clear();
+ m_extra.clear();
+ m_refs.clear();
+ m_type = TranslatorMessage::Finished;
+ return true;
+}
+
+bool XLIFFHandler::fatalError(const QXmlParseException &exception)
+{
+ QString msg;
+ msg.sprintf("XML error: Parse error at line %d, column %d (%s).\n",
+ exception.lineNumber(), exception.columnNumber(),
+ exception.message().toLatin1().data() );
+ m_cd.appendError(msg);
+ return false;
+}
+
+bool loadXLIFF(Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ QXmlInputSource in(&dev);
+ QXmlSimpleReader reader;
+ XLIFFHandler hand(translator, cd);
+ reader.setContentHandler(&hand);
+ reader.setErrorHandler(&hand);
+ return reader.parse(in);
+}
+
+bool saveXLIFF(const Translator &translator, QIODevice &dev, ConversionData &cd)
+{
+ bool ok = true;
+ int indent = 0;
+
+ QTextStream ts(&dev);
+ ts.setCodec(QTextCodec::codecForName("UTF-8"));
+
+ QStringList dtgs = cd.dropTags();
+ dtgs << QLatin1String("po-(old_)?msgid_plural");
+ QRegExp drops(dtgs.join(QLatin1String("|")));
+
+ QHash<QString, QHash<QString, QList<TranslatorMessage> > > messageOrder;
+ QHash<QString, QList<QString> > contextOrder;
+ QList<QString> fileOrder;
+ foreach (const TranslatorMessage &msg, translator.messages()) {
+ QHash<QString, QList<TranslatorMessage> > &file = messageOrder[msg.fileName()];
+ if (file.isEmpty())
+ fileOrder.append(msg.fileName());
+ QList<TranslatorMessage> &context = file[msg.context()];
+ if (context.isEmpty())
+ contextOrder[msg.fileName()].append(msg.context());
+ context.append(msg);
+ }
+
+ ts.setFieldAlignment(QTextStream::AlignRight);
+ ts << "<?xml version=\"1.0\"";
+ ts << " encoding=\"utf-8\"?>\n";
+ ts << "<xliff version=\"1.2\" xmlns=\"" << XLIFF12namespaceURI
+ << "\" xmlns:trolltech=\"" << TrollTsNamespaceURI << "\">\n";
+ ++indent;
+ writeExtras(ts, indent, translator.extras(), drops);
+ foreach (const QString &fn, fileOrder) {
+ writeIndent(ts, indent);
+ ts << "<file original=\"" << fn << "\""
+ << " datatype=\"" << dataType(messageOrder[fn].begin()->first()) << "\""
+ << " source-language=\""
+ << (translator.sourceLanguageCode().isEmpty() ?
+ QByteArray("en") : translator.sourceLanguageCode().toLatin1()) << "\""
+ << " target-language=\"" << translator.languageCode() << "\""
+ << "><body>\n";
+ ++indent;
+
+ foreach (const QString &ctx, contextOrder[fn]) {
+ if (!ctx.isEmpty()) {
+ writeIndent(ts, indent);
+ ts << "<group restype=\"" << restypeContext << "\""
+ << " resname=\"" << protect(ctx) << "\">\n";
+ ++indent;
+ }
+
+ foreach (const TranslatorMessage &msg, messageOrder[fn][ctx])
+ writeMessage(ts, msg, drops, indent, translator, cd, &ok);
+
+ if (!ctx.isEmpty()) {
+ --indent;
+ writeIndent(ts, indent);
+ ts << "</group>\n";
+ }
+ }
+
+ --indent;
+ writeIndent(ts, indent);
+ ts << "</body></file>\n";
+ }
+ --indent;
+ writeIndent(ts, indent);
+ ts << "</xliff>\n";
+
+ return ok;
+}
+
+int initXLIFF()
+{
+ Translator::FileFormat format;
+ format.extension = QLatin1String("xlf");
+ format.description = QObject::tr("XLIFF localization files");
+ format.fileType = Translator::FileFormat::TranslationSource;
+ format.priority = 1;
+ format.loader = &loadXLIFF;
+ format.saver = &saveXLIFF;
+ Translator::registerFileFormat(format);
+ return 1;
+}
+
+Q_CONSTRUCTOR_FUNCTION(initXLIFF)
+
+QT_END_NAMESPACE
diff --git a/tools/linguist/tests/data/main.cpp b/tools/linguist/tests/data/main.cpp
new file mode 100644
index 0000000000..ebbda0a577
--- /dev/null
+++ b/tools/linguist/tests/data/main.cpp
@@ -0,0 +1,35 @@
+
+#include <QtGui>
+#include <QtCore>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QStringList args = app.arguments();
+
+ if (argc <= 1) {
+ qDebug() << "Usage: " << qPrintable(args[0]) << " <ts-file>";
+ return 1;
+ }
+
+ QTranslator trans;
+ trans.load(args[1], ".");
+ app.installTranslator(&trans);
+
+ QWidget w;
+ QVBoxLayout *layout = new QVBoxLayout(&w);
+
+ QLabel label1(QObject::tr("XXXXXXXXX \33 XXXXXXXXXXX • and → "), 0);
+ QLabel label2(QObject::tr("\32"), 0);
+ QLabel label3(QObject::tr("\176"), 0);
+ QLabel label4(QObject::tr("\301"), 0);
+
+ layout->addWidget(&label1);
+ layout->addWidget(&label2);
+ layout->addWidget(&label3);
+ layout->addWidget(&label4);
+
+ w.show();
+
+ return app.exec();
+}
diff --git a/tools/linguist/tests/data/test.pro b/tools/linguist/tests/data/test.pro
new file mode 100644
index 0000000000..90e5704b46
--- /dev/null
+++ b/tools/linguist/tests/data/test.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET +=
+DEPENDPATH += .
+INCLUDEPATH += .
+
+SOURCES += main.cpp
+
+TRANSLATIONS += t1_en.ts
+TRANSLATIONS += t1_de.ts
diff --git a/tools/linguist/tests/tests.pro b/tools/linguist/tests/tests.pro
new file mode 100644
index 0000000000..a67725c46d
--- /dev/null
+++ b/tools/linguist/tests/tests.pro
@@ -0,0 +1,16 @@
+load(qttest_p4)
+
+QT += xml
+
+HEADERS += \
+ tst_linguist.h \
+ ../shared/translator.h
+
+SOURCES += \
+ tst_linguist.cpp \
+ tst_lupdate.cpp \
+ tst_simtexth.cpp \
+ ../shared/simtexth.cpp \
+ ../shared/translator.cpp \
+ ../shared/translatormessage.cpp \
+ ../shared/xliff.cpp
diff --git a/tools/linguist/tests/tst_linguist.cpp b/tools/linguist/tests/tst_linguist.cpp
new file mode 100644
index 0000000000..199ddbbd1b
--- /dev/null
+++ b/tools/linguist/tests/tst_linguist.cpp
@@ -0,0 +1,4 @@
+#include "tst_linguist.h"
+#include "moc_tst_linguist.cpp"
+
+QTEST_MAIN(tst_linguist)
diff --git a/tools/linguist/tests/tst_linguist.h b/tools/linguist/tests/tst_linguist.h
new file mode 100644
index 0000000000..27a53bbacc
--- /dev/null
+++ b/tools/linguist/tests/tst_linguist.h
@@ -0,0 +1,22 @@
+#ifndef TST_LINGUIST
+#define TST_LINGUIST
+
+#include <QtTest/QtTest>
+#include <QtCore/QtCore>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+
+class tst_linguist : public QObject
+{
+ Q_OBJECT
+private slots:
+ void fetchtr();
+ void fetchtr_data();
+
+ void simtexth();
+ void simtexth_data();
+};
+
+#endif
diff --git a/tools/linguist/tests/tst_lupdate.cpp b/tools/linguist/tests/tst_lupdate.cpp
new file mode 100644
index 0000000000..043e65349a
--- /dev/null
+++ b/tools/linguist/tests/tst_lupdate.cpp
@@ -0,0 +1,165 @@
+
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QtCore>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+#include "tst_linguist.h"
+
+void tst_linguist::fetchtr()
+{
+ // FIXME: This probably should use some yet-to-be-invented
+ // binary interface to 'lupdate' instead of playing around
+ // with the filesystem,
+
+ QRegExp reg("\\s*");
+ QString lupdate("lupdate");
+
+ QFETCH(QString, input);
+
+ QFETCH(QString, name);
+ QFETCH(QString, file);
+ QFETCH(QString, line);
+ QFETCH(QString, src);
+
+ QString result;
+
+ QTemporaryFile profile("tst_lu_XXXXXX.pro");
+ QTemporaryFile cppfile("tst_lu_XXXXXX.cpp");
+ QTemporaryFile tsfile("tst_lu_XXXXXX.ts");
+
+ profile.open();
+ cppfile.open();
+ tsfile.open();
+
+#if 0
+ profile.setAutoRemove(false);
+ cppfile.setAutoRemove(false);
+ tsfile.setAutoRemove(false);
+
+ qDebug() << ".pro: " << profile.fileName();
+ qDebug() << ".cpp: " << cppfile.fileName();
+ qDebug() << ".ts: " << tsfile.fileName();
+#endif
+
+ QTextStream prots(&profile);
+ prots << "SOURCES += " << cppfile.fileName() << "\n";
+ prots << "TRANSLATIONS += " << tsfile.fileName() << "\n";
+ prots.flush();
+
+ QTextStream cppts(&cppfile);
+ cppts.setCodec("ISO 8859-1");
+ cppts << input << '\n';
+ cppts.flush();
+
+ QProcess proc;
+ proc.start(lupdate, QStringList() << profile.fileName());
+ proc.waitForFinished();
+
+ result = tsfile.readAll();
+
+ static QRegExp re(
+ "<name>(.+)</name>\\s*"
+ "<message.*>\\s*" // there might be a numerus="yes" attribiute
+ "<location filename=\"(.+)\" line=\"(\\d+)\"/>\\s*"
+ "<source>(.+)</source>\\s*"
+ "<translation type=\"unfinished\">.*</translation>\\s*"
+ );
+
+ re.indexIn(result);
+ QString resname = re.cap(1);
+ //QString resfile = re.cap(2);
+ QString resline = re.cap(3);
+ QString ressrc = re.cap(4);
+
+ //qDebug() << "pattern:" << re.pattern();
+ //qDebug() << "result:" << result;
+ //qDebug() << "resname:" << resname;
+ ////qDebug() << "resfile:" << resfile;
+ //qDebug() << "resline:" << resline;
+ //qDebug() << "ressource:" << ressrc;
+
+ QCOMPARE(src + ": " + resname, src + ": " + name);
+ QCOMPARE(src + ": " + resline, src + ": " + line);
+ QCOMPARE(src + ": " + ressrc, src + ": " + src);
+}
+
+void tst_linguist::fetchtr_data()
+{
+ using namespace QTest;
+
+ addColumn<QString>("input");
+ addColumn<QString>("name");
+ addColumn<QString>("file");
+ addColumn<QString>("line");
+ addColumn<QString>("src");
+
+ // plain stuff
+ newRow("00") << "int main() { tr(\"foo\"); }"
+ << "@default" << "XXXXXX" << "1" << "foo";
+
+ // space at beginning of text
+ newRow("01") << "int main() { tr(\" foo\"); }"
+ << "@default" << "XXXXXX" << "1" << " foo";
+ // space at end of text
+ newRow("02") << "int main() { tr(\"foo \"); }"
+ << "@default" << "XXXXXX" << "1" << "foo ";
+ // space in the middle of the text
+ newRow("03") << "int main() { tr(\"foo bar\"); }"
+ << "@default" << "XXXXXX" << "1" << "foo bar";
+
+ // tab at beginning of text
+ newRow("04") << "int main() { tr(\"\tfoo\"); }"
+ << "@default" << "XXXXXX" << "1" << "<byte value=\"x9\"/>foo";
+ // tab at end of text
+ newRow("05") << "int main() { tr(\"foo\t\"); }"
+ << "@default" << "XXXXXX" << "1" << "foo<byte value=\"x9\"/>";
+ // tab in the middle of the text
+ newRow("06") << "int main() { tr(\"foo\tbar\"); }"
+ << "@default" << "XXXXXX" << "1" << "foo<byte value=\"x9\"/>bar";
+
+ // check for unicode
+ newRow("07") << "int main() { tr(\"\32\"); }" // 26 dec
+ << "@default" << "XXXXXX" << "1" << "<byte value=\"x1a\"/>";
+ // check for unicode
+ newRow("08") << "int main() { tr(\"\33\"); }" // 27 dec
+ << "@default" << "XXXXXX" << "1" << "<byte value=\"x1b\"/>";
+ // check for unicode
+ newRow("09") << "int main() { tr(\"\176\"); }" // 124 dec
+ << "@default" << "XXXXXX" << "1" << "~";
+ // check for unicode
+ newRow("10") << "int main() { tr(\"\301\"); }" // 193 dec
+ << "@default" << "XXXXXX" << "1" << "&#xc1;";
+
+ // Bug 162562: lupdate does not find QCoreApplication::translate() strings
+ newRow("11") << "int main() { QString s = QCoreApplication::translate"
+ "(\"mycontext\", \"msg\", \"\", QCoreApplication::CodecForTr, 2);"
+ << "mycontext" << "XXXXXX" << "1" << "msg";
+
+ // Bug 161504: lupdate produces wrong ts file with context "N::QObject"
+ newRow("12") << "namespace N { QString foo() "
+ "{ return QObject::tr(\"msg\"); }"
+ << "QObject" << "XXXXXX" << "1" << "msg";
+
+ // Correct example from 161504:
+ newRow("13") << "namespace N { QString foo(); }"
+ "QString N::anyfunc() { return QObject::tr(\"msg\"); }"
+ << "QObject" << "XXXXXX" << "1" << "msg";
+
+ // Bug 161106: When specifying ::QObject::tr() then lupdate will
+ // take the previous word as being the namespace
+ newRow("14") << " std::cout << ::QObject::tr(\"msg\");"
+ << "QObject" << "XXXXXX" << "1" << "msg";
+
+}
diff --git a/tools/linguist/tests/tst_simtexth.cpp b/tools/linguist/tests/tst_simtexth.cpp
new file mode 100644
index 0000000000..81a7f193df
--- /dev/null
+++ b/tools/linguist/tests/tst_simtexth.cpp
@@ -0,0 +1,43 @@
+
+/****************************************************************************
+ **
+ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ **
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QtCore>
+
+//int getSimilarityScore(const QString &str1, const char* str2);
+#include "../shared/simtexth.h"
+#include "tst_linguist.h"
+
+void tst_linguist::simtexth()
+{
+ QFETCH(QString, one);
+ QFETCH(QString, two);
+ QFETCH(int, expected);
+
+ int measured = getSimilarityScore(one, two.toLatin1());
+ QCOMPARE(measured, expected);
+}
+
+
+void tst_linguist::simtexth_data()
+{
+ using namespace QTest;
+
+ addColumn<QString>("one");
+ addColumn<QString>("two");
+ addColumn<int>("expected");
+
+ newRow("00") << "" << "" << 1024;
+ newRow("01") << "a" << "a" << 1024;
+ newRow("02") << "ab" << "ab" << 1024;
+ newRow("03") << "abc" << "abc" << 1024;
+ newRow("04") << "abcd" << "abcd" << 1024;
+}
diff --git a/tools/macdeployqt/macchangeqt/macchangeqt.pro b/tools/macdeployqt/macchangeqt/macchangeqt.pro
new file mode 100644
index 0000000000..c09fea3be1
--- /dev/null
+++ b/tools/macdeployqt/macchangeqt/macchangeqt.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET = macchangeqt
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp ../shared/shared.cpp
+CONFIG += qt warn_on
+CONFIG -= app_bundle
diff --git a/tools/macdeployqt/macchangeqt/main.cpp b/tools/macdeployqt/macchangeqt/main.cpp
new file mode 100644
index 0000000000..e94e8a3dab
--- /dev/null
+++ b/tools/macdeployqt/macchangeqt/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "../shared/shared.h"
+
+int main(int argc, char **argv)
+{
+ if (argc != 3) {
+ qDebug() << "Changeqt changes witch qt frameworks an application links against.";
+ qDebug() << "Usage: changeqt app-bundle qt-dir";
+ return 0;
+ }
+
+ const QString appPath = QString::fromLocal8Bit(argv[1]);
+ const QString qtPath = QString::fromLocal8Bit(argv[2]);
+ changeQtFrameworks(appPath, qtPath);
+}
diff --git a/tools/macdeployqt/macdeployqt.pro b/tools/macdeployqt/macdeployqt.pro
new file mode 100644
index 0000000000..09ed6989aa
--- /dev/null
+++ b/tools/macdeployqt/macdeployqt.pro
@@ -0,0 +1,7 @@
+
+mac {
+
+TEMPLATE = subdirs
+SUBDIRS = macdeployqt macchangeqt
+
+}
diff --git a/tools/macdeployqt/macdeployqt/macdeployqt.pro b/tools/macdeployqt/macdeployqt/macdeployqt.pro
new file mode 100644
index 0000000000..3e56024fde
--- /dev/null
+++ b/tools/macdeployqt/macdeployqt/macdeployqt.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = macdeployqt
+DEPENDPATH += .
+INCLUDEPATH += .
+DESTDIR = ../../../bin
+
+# Input
+SOURCES += main.cpp ../shared/shared.cpp
+CONFIG += qt warn_on
+CONFIG -= app_bundle
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/tools/macdeployqt/macdeployqt/main.cpp b/tools/macdeployqt/macdeployqt/main.cpp
new file mode 100644
index 0000000000..d6f7e5f7b7
--- /dev/null
+++ b/tools/macdeployqt/macdeployqt/main.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "../shared/shared.h"
+#include <qdir.h>
+
+int main(int argc, char **argv)
+{
+ QString appBundlePath;
+ if (argc > 1)
+ appBundlePath = QString::fromLocal8Bit(argv[1]);
+
+ if (argc < 2 || appBundlePath.startsWith("-")) {
+ qDebug() << "Usage: macdeployqt app-bundle [options]";
+ qDebug() << "";
+ qDebug() << "Options:";
+ qDebug() << " -no-plugins: Skip plugin deployment";
+ qDebug() << " -dmg : Create a .dmg disk image";
+ qDebug() << " -no-strip : Don't run 'strip' on the binaries";
+ qDebug() << "";
+ qDebug() << "macdeployqt takes an application bundle as input and makes it";
+ qDebug() << "self-contained by copying in the Qt frameworks and plugins that";
+ qDebug() << "the application uses.";
+ qDebug() << "";
+ qDebug() << "Plugins related to a framework are copied in with the";
+ qDebug() << "framework. The accessibilty, image formats, and text codec";
+ qDebug() << "plugins are always copied, unless \"-no-plugins\" is specified.";
+ qDebug() << "";
+ qDebug() << "See the \"Deploying an Application on Qt/Mac\" typic in the";
+ qDebug() << "documentation for more information about deployment on Mac OS X.";
+
+ return 0;
+ }
+
+ if (appBundlePath.endsWith("/"))
+ appBundlePath.chop(1);
+
+ if (QDir().exists(appBundlePath) == false) {
+ qDebug() << "Error: Could not find app bundle" << appBundlePath;
+ return 0;
+ }
+
+ bool plugins = true;
+ bool dmg = false;
+ extern bool runStripEnabled;
+
+ for (int i = 2; i < argc; ++i) {
+ QByteArray argument = QByteArray(argv[i]);
+ if (argument == QByteArray("-no-plugins")) {
+ plugins = false;
+ } else if (argument == QByteArray("-dmg")) {
+ dmg = true;
+ } else if (argument == QByteArray("-no-strip")) {
+ runStripEnabled = false;
+ } else if (argument.startsWith("-")) {
+ qDebug() << "Error: Unknown option" << argument << "\n";
+ return 0;
+ }
+ }
+
+ DeploymentInfo deploymentInfo = deployQtFrameworks(appBundlePath);
+
+ if (plugins) {
+ if (deploymentInfo.qtPath.isEmpty())
+ deploymentInfo.pluginPath = "/Developer/Applications/Qt/plugins"; // Assume binary package.
+ else
+ deploymentInfo.pluginPath = deploymentInfo.qtPath + "/plugins";
+
+ qDebug() << "";
+ qDebug() << "Deploying plugins from" << deploymentInfo.pluginPath;
+ deployPlugins(appBundlePath, deploymentInfo);
+ createQtConf(appBundlePath);
+ }
+
+ if (dmg) {
+ createDiskImage(appBundlePath);
+ }
+}
+
diff --git a/tools/macdeployqt/shared/shared.cpp b/tools/macdeployqt/shared/shared.cpp
new file mode 100644
index 0000000000..db76ef25a5
--- /dev/null
+++ b/tools/macdeployqt/shared/shared.cpp
@@ -0,0 +1,563 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QString>
+#include <QStringList>
+#include <QDebug>
+#include <iostream>
+#include <QProcess>
+#include <QDir>
+#include <QRegExp>
+#include <QSet>
+#include <QDirIterator>
+#include "shared.h"
+
+bool runStripEnabled = true;
+
+using std::cout;
+using std::endl;
+
+bool operator==(const FrameworkInfo &a, const FrameworkInfo &b)
+{
+ return ((a.frameworkPath == b.frameworkPath) && (a.binaryPath == b.binaryPath));
+}
+
+QDebug operator<<(QDebug debug, const FrameworkInfo &info)
+{
+ debug << "Framework directory" << info.frameworkDirectory << "\n";
+ debug << "Framework name" << info.frameworkName << "\n";
+ debug << "Framework path" << info.frameworkPath << "\n";
+ debug << "Binary directory" << info.binaryDirectory << "\n";
+ debug << "Binary name" << info.binaryName << "\n";
+ debug << "Binary path" << info.binaryPath << "\n";
+ debug << "Version" << info.version << "\n";
+ debug << "Install name" << info.installName << "\n";
+ debug << "Deployed install name" << info.deployedInstallName << "\n";
+ debug << "Source file Path" << info.sourceFilePath << "\n";
+ debug << "Deployed Directtory (relative to bundle)" << info.destinationDirectory << "\n";
+
+ return debug;
+}
+
+const QString bundleFrameworkDirectory = "Contents/Frameworks";
+const QString bundleBinaryDirectory = "Contents/MacOS";
+
+inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info)
+{
+ debug << "Application bundle path" << info.path << "\n";
+ debug << "Binary path" << info.binaryPath << "\n";
+ return debug;
+}
+
+bool copyFilePrintStatus(const QString &from, const QString &to)
+{
+ if (QFile::copy(from, to)) {
+ qDebug() << "copied" << from << "to" << to;
+ return true;
+ } else {
+ qDebug() << "ERROR: file copy failed from" << from << "to" << to;
+ return false;
+ }
+}
+
+
+FrameworkInfo parseOtoolLibraryLine(const QString &line)
+{
+ FrameworkInfo info;
+ QString trimmed = line.trimmed();
+
+ if (trimmed.isEmpty())
+ return info;
+
+ // Don't deploy system libraries.
+ if (trimmed.startsWith("/System/Library/") ||
+ (trimmed.startsWith("/usr/lib/") && trimmed.contains("libQt") == false) // exception for libQtuitools and libQtlucene
+ || trimmed.startsWith("@executable_path"))
+ return info;
+
+ enum State {QtPath, FrameworkName, DylibName, Version, End};
+ State state = QtPath;
+ int part = 0;
+ QString name;
+ QString qtPath;
+
+ // Split the line into [Qt-path]/lib/qt[Module].framework/Versions/[Version]/
+ QStringList parts = trimmed.split("/");
+ while (part < parts.count()) {
+ const QString currentPart = parts.at(part).simplified() ;
+// qDebug() << "currentPart" << currentPart;
+ ++part;
+ if (currentPart == "")
+ continue;
+
+ if (state == QtPath) {
+ // Check for library name part
+ if (part < parts.count() && parts.at(part).contains(".dylib ")) {
+ state = DylibName;
+ info.installName += "/" + (qtPath + "lib/").simplified();
+ info.frameworkDirectory = info.installName;
+ state = DylibName;
+ continue;
+ } else if (part < parts.count() && parts.at(part).endsWith(".framework")) {
+ info.installName += "/" + (qtPath + "lib/").simplified();
+ info.frameworkDirectory = info.installName;
+ state = FrameworkName;
+ continue;
+ } else if (trimmed.startsWith("/") == false) { // If the line does not contain a full path, the app is using a binary Qt package.
+ if (currentPart.contains(".framework")) {
+ info.frameworkDirectory = "/Library/Frameworks/";
+ state = FrameworkName;
+ } else {
+ info.frameworkDirectory = "/usr/lib/";
+ state = DylibName;
+ }
+
+ --part;
+ continue;
+ }
+ qtPath += (currentPart + "/");
+
+ } if (state == FrameworkName) {
+ // remove ".framework"
+ name = currentPart;
+ name.chop(QString(".framework").length());
+ info.frameworkName = currentPart;
+ state = Version;
+ ++part;
+ continue;
+ } if (state == DylibName) {
+ name = currentPart.split(" (compatibility").at(0);
+ info.frameworkName = name;
+ info.installName += info.frameworkName;
+ info.deployedInstallName = "@executable_path/../Frameworks/" + info.frameworkName;
+ info.binaryName = name;
+ info.frameworkPath = info.frameworkDirectory + info.frameworkName;
+ info.sourceFilePath = info.frameworkPath;
+ info.destinationDirectory = bundleFrameworkDirectory + "/";
+ state = End;
+ ++part;
+ continue;
+ } else if (state == Version) {
+ info.version = currentPart;
+ info.binaryDirectory = "Versions/" + info.version;
+ info.binaryName = name;
+ info.binaryPath = "/" + info.binaryDirectory + "/" + info.binaryName;
+ info.installName += info.frameworkName + info.binaryPath;
+ info.deployedInstallName = "@executable_path/../Frameworks/" + info.frameworkName + info.binaryPath;
+ info.frameworkPath = info.frameworkDirectory + info.frameworkName;
+ info.sourceFilePath = info.frameworkPath + info.binaryPath;
+ info.destinationDirectory = bundleFrameworkDirectory + "/" + info.frameworkName + "/" + info.binaryDirectory;
+
+ state = End;
+ } else if (state == End) {
+ break;
+ }
+ }
+
+ return info;
+}
+
+QString findAppBinary(const QString &appBundlePath)
+{
+ QString appName = QFileInfo(appBundlePath).completeBaseName();
+ QString binaryPath = appBundlePath + "/Contents/MacOS/" + appName;
+
+ if (QFile::exists(binaryPath))
+ return binaryPath;
+ qDebug() << "Error: Could not find bundle binary for" << appBundlePath;
+ return QString();
+}
+
+QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines)
+{
+ QList<FrameworkInfo> libraries;
+ foreach(const QString line, otoolLines) {
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+ if (info.frameworkName.isEmpty() == false) {
+ libraries.append(info);
+ }
+ }
+ return libraries;
+}
+
+QList<FrameworkInfo> getQtFrameworks(const QString &path)
+{
+ QProcess otool;
+ otool.start("otool", QStringList() << "-L" << path);
+ otool.waitForFinished();
+
+ if (otool.exitCode() != 0) {
+ qDebug() << otool.readAllStandardError();
+ }
+
+ QString output = otool.readAllStandardOutput();
+ QStringList outputLines = output.split("\n");
+ outputLines.removeFirst(); // remove line containing the binary path
+ if (path.contains(".framework") || path.contains(".dylib"))
+ outputLines.removeFirst(); // frameworks and dylibs lists themselves as a dependency.
+
+ return getQtFrameworks(outputLines);
+}
+
+// copies everything _inside_ sourcePath to destinationPath
+void recursiveCopy(const QString &sourcePath, const QString &destinationPath)
+{
+ QDir().mkpath(destinationPath);
+
+ QStringList files = QDir(sourcePath).entryList(QStringList() << "*", QDir::Files | QDir::NoDotAndDotDot);
+ foreach (QString file, files) {
+ const QString fileSourcePath = sourcePath + "/" + file;
+ const QString fileDestinationPath = destinationPath + "/" + file;
+ copyFilePrintStatus(fileSourcePath, fileDestinationPath);
+ }
+
+ QStringList subdirs = QDir(sourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (QString dir, subdirs) {
+ recursiveCopy(sourcePath + "/" + dir, destinationPath + "/" + dir);
+ }
+}
+
+QString copyFramework(const FrameworkInfo &framework, const QString path)
+{
+ const QString from = framework.sourceFilePath;
+ const QString toDir = path + "/" + framework.destinationDirectory;
+ const QString to = toDir + "/" + framework.binaryName;
+
+ if (QFile::exists(from) == false) {
+ qDebug() << "ERROR: no file at" << from;
+ return QString();
+ }
+
+
+ QDir dir;
+ if (dir.mkpath(toDir) == false) {
+ qDebug() << "ERROR: could not create destination directory" << to;
+ return QString();
+ }
+
+
+ if (QFile::exists(to)) {
+// qDebug() << framework.frameworkName << "already deployed, skip";
+ return QString();
+ }
+
+ copyFilePrintStatus(from, to);
+
+ const QString resourcesSourcePath = framework.frameworkPath + "/Resources";
+ const QString resourcesDestianationPath = path + "/Contents/Frameworks/" + framework.frameworkName + "/Resources";
+ recursiveCopy(resourcesSourcePath, resourcesDestianationPath);
+
+ return to;
+}
+
+void runInstallNameTool(QStringList options)
+{
+ QProcess installNametool;
+ installNametool.start("install_name_tool", options);
+ installNametool.waitForFinished();
+ if (installNametool.exitCode() != 0) {
+ qDebug() << installNametool.readAllStandardError();
+ qDebug() << installNametool.readAllStandardOutput();
+ }
+}
+
+void changeIdentification(const QString &id, const QString &binaryPath)
+{
+// qDebug() << "change identification on" << binaryPath << id;
+ runInstallNameTool(QStringList() << "-id" << id << binaryPath);
+}
+
+void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath)
+{
+// qDebug() << "change install name on" << binaryPath << oldName << newName;
+ runInstallNameTool(QStringList() << "-change" << oldName << newName << binaryPath);
+}
+
+void runStrip(const QString &binaryPath)
+{
+ if (runStripEnabled == false)
+ return;
+
+ QProcess strip;
+ strip.start("strip", QStringList() << "-x" << binaryPath);
+ strip.waitForFinished();
+ if (strip.exitCode() != 0) {
+ qDebug() << strip.readAllStandardError();
+ qDebug() << strip.readAllStandardOutput();
+ } else {
+ qDebug() << "stripped" << binaryPath;
+ }
+}
+
+/*
+ Deploys the the listed frameworks listed into an app bundle.
+ The frameworks are searched for dependencies, which are also deployed.
+ (deploying Qt3Support will also deploy QtNetwork and QtSql for example.)
+ Returns a DeploymentInfo structure containing the Qt path used and a
+ a list of actually deployed frameworks.
+*/
+DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, const QString &bundlePath, const QString &binaryPath)
+{
+ QStringList copiedFrameworks;
+ DeploymentInfo deploymenInfo;
+
+ while (frameworks.isEmpty() == false) {
+ const FrameworkInfo framework = frameworks.takeFirst();
+ copiedFrameworks.append(framework.frameworkName);
+
+ // Get the qt path from one of the Qt frameworks;
+ if (deploymenInfo.qtPath == QString() && framework.frameworkName.contains("Qt")
+ && framework.frameworkDirectory.contains("/lib"))
+ {
+ deploymenInfo.qtPath = framework.frameworkDirectory;
+ deploymenInfo.qtPath.chop(5); // remove "/lib/"
+ }
+
+// qDebug() << "";
+// qDebug() << "deploy" << framework.frameworkName;
+
+ if (framework.installName.startsWith("/@executable_path/")) {
+ qDebug() << framework.frameworkName << "already deployed, skipping.";
+ continue;
+ }
+
+ // Install_name_tool the new id into the binary
+ changeInstallName(framework.installName, framework.deployedInstallName, binaryPath);
+
+ // Copy farmework to app bundle.
+ const QString deployedBinaryPath = copyFramework(framework, bundlePath);
+ // Skip the rest if already was deployed.
+ if (deployedBinaryPath == QString())
+ continue;
+
+ runStrip(deployedBinaryPath);
+
+ // Install_name_tool it a new id.
+ changeIdentification(framework.deployedInstallName, deployedBinaryPath);
+ // Check for framework dependencies
+ QList<FrameworkInfo> dependencies = getQtFrameworks(deployedBinaryPath);
+
+ foreach (FrameworkInfo dependency, dependencies) {
+// qDebug() << "dependent framework" << dependency.installName << deployedBinaryPath;
+ changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath);
+
+ // Deploy framework if neccesary.
+ if (copiedFrameworks.contains(dependency.frameworkName) == false && frameworks.contains(dependency) == false) {
+ frameworks.append(dependency);
+ }
+ }
+ }
+ deploymenInfo.deployedFrameworks = copiedFrameworks;
+ return deploymenInfo;
+}
+
+DeploymentInfo deployQtFrameworks(const QString &appBundlePath)
+{
+ ApplicationBundleInfo applicationBundle;
+ applicationBundle.path = appBundlePath;
+ applicationBundle.binaryPath = findAppBinary(appBundlePath);
+ return deployQtFrameworks(getQtFrameworks(applicationBundle.binaryPath), applicationBundle.path, applicationBundle.binaryPath);
+}
+
+void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pluginSourcePath, const QString pluginDestinationPath, DeploymentInfo deploymentInfo)
+{
+ QStringList plugins = QDir(pluginSourcePath).entryList(QStringList() << "*.dylib");
+
+ foreach (QString pluginName, plugins) {
+
+ // Skip some Qt plugins based on what frameworks were deployed:
+ //qDebug() << pluginSourcePath << deploymentInfo.pluginPath;
+
+ if (pluginSourcePath.contains(deploymentInfo.pluginPath)) {
+ QStringList deployedFrameworks = deploymentInfo.deployedFrameworks;
+
+ // Skip the debug versions of the plugins
+ if (pluginName.endsWith("_debug.dylib"))
+ continue;
+
+ // Skip the designer plugins
+ if (pluginSourcePath.contains("plugins/designer"))
+ continue;
+
+#ifndef QT_GRAPHICSSYSTEM_OPENGL
+ // SKip the opengl graphicssystem plugin when not in use.
+ if (pluginName.contains("libqglgraphicssystem"))
+ continue;
+#endif
+ // Deploy accessibility for Qt3Support only if the Qt3Support.framework is in use
+ if (deployedFrameworks.indexOf("Qt3Support.framework") == -1 && pluginName.contains("accessiblecompatwidgets"))
+ continue;
+
+ // Deploy the svg icon plugin if QtSvg.framework is in use.
+ if (deployedFrameworks.indexOf("QtSvg.framework") == -1 && pluginName.contains("svg"))
+ continue;
+
+ // Deploy the phonon plugins if phonon.framework is in use
+ if (deployedFrameworks.indexOf("phonon.framework") == -1 && pluginName.contains("phonon"))
+ continue;
+
+ // Deploy the sql plugins if QtSql.framework is in use
+ if (deployedFrameworks.indexOf("QtSql.framework") == -1 && pluginName.contains("sql"))
+ continue;
+
+ // Deploy the script plugins if QtScript.framework is in use
+ if (deployedFrameworks.indexOf("QtScript.framework") == -1 && pluginName.contains("script"))
+ continue;
+ }
+
+ QDir dir;
+ dir.mkpath(pluginDestinationPath);
+
+ const QString sourcePath = pluginSourcePath + "/" + pluginName;
+ const QString destinationPath = pluginDestinationPath + "/" + pluginName;
+ if (copyFilePrintStatus(sourcePath, destinationPath)) {
+
+ runStrip(destinationPath);
+
+ // Special case for the phonon plugin: CoreVideo is not available as a separate framework
+ // on panther, link against the QuartzCore framework instead. (QuartzCore contians CoreVideo.)
+ if (pluginName.contains("libphonon_qt7")) {
+ changeInstallName("/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo",
+ "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore",
+ destinationPath);
+ }
+
+// qDebug() << "deploy plugin depedencies:";
+ QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath);
+// qDebug() << frameworks;
+ deployQtFrameworks(frameworks, appBundleInfo.path, destinationPath);
+// qDebug() << "deploy plugin depedencies done";
+ }
+ } // foreach plugins
+
+ QStringList subdirs = QDir(pluginSourcePath).entryList(QStringList() << "*", QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QString &subdir, subdirs)
+ deployPlugins(appBundleInfo, pluginSourcePath + "/" + subdir, pluginDestinationPath + "/" + subdir, deploymentInfo);
+}
+
+void createQtConf(const QString &appBundlePath)
+{
+ QByteArray contents = "[Paths]\nPlugins = PlugIns\n";
+ QString filePath = appBundlePath + "/Contents/Resources/";
+ QString fileName = filePath + "qt.conf";
+
+ QDir().mkpath(filePath);
+
+ QFile qtconf(fileName);
+ if (qtconf.exists()) {
+ qDebug() << "";
+ qDebug() << "Warning:" << fileName << "already exists, will not overwrite.";
+ qDebug() << "To make sure the plugins are loaded from the correct location,";
+ qDebug() << "please make sure qt.conf contains the following lines:";
+ qDebug() << contents;
+ qDebug() << "";
+ return;
+ }
+
+ qtconf.open(QIODevice::WriteOnly);
+ if (qtconf.write(contents) != -1) {
+ qDebug() << "";
+ qDebug() << "Created configuration file:" << fileName;
+ qDebug() << "This file sets the plugin search path to" << appBundlePath + "/Contents/PlugIns";
+ qDebug() << "";
+ }
+}
+
+void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo)
+{
+ ApplicationBundleInfo applicationBundle;
+ applicationBundle.path = appBundlePath;
+ applicationBundle.binaryPath = findAppBinary(appBundlePath);
+
+ const QString pluginDestinationPath = appBundlePath + "/" + "Contents/PlugIns";
+
+// qDebug() << "";
+// qDebug() << "recursively copying plugins from" << deploymentInfo.pluginPath << "to" << pluginDestinationPath;
+ deployPlugins(applicationBundle, deploymentInfo.pluginPath, pluginDestinationPath, deploymentInfo);
+}
+
+
+void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QString &appBinaryPath, const QString &absoluteQtPath)
+{
+ qDebug() << "Changing" << appBinaryPath << "to link against Qt in" << absoluteQtPath;
+ QString finalQtPath = absoluteQtPath;
+
+ if (absoluteQtPath.startsWith("/Library/Frameworks") == false)
+ finalQtPath += "/lib/";
+
+ foreach (FrameworkInfo framework, frameworks) {
+ const QString oldBinaryId = framework.installName;
+ const QString newBinaryId = finalQtPath + framework.frameworkName + framework.binaryPath;
+ qDebug() << "Changing" << oldBinaryId << "to" << newBinaryId;
+ changeInstallName(oldBinaryId, newBinaryId, appBinaryPath);
+ }
+}
+
+void changeQtFrameworks(const QString appPath, const QString &qtPath)
+{
+ const QString appBinaryPath = findAppBinary(appPath);
+ const QList<FrameworkInfo> qtFrameworks = getQtFrameworks(appBinaryPath);
+ const QString absoluteQtPath = QDir(qtPath).absolutePath();
+ changeQtFrameworks(qtFrameworks, appBinaryPath, absoluteQtPath);
+}
+
+
+void createDiskImage(const QString &appBundlePath)
+{
+ QString appBaseName = appBundlePath;
+ appBaseName.chop(4); // remove ".app" from end
+
+ QString dmgName = appBaseName + ".dmg";
+
+ QFile dmg(dmgName);
+
+ if (dmg.exists()) {
+ qDebug() << "Disk image already exists, skipping .dmg creation for" << dmg.fileName();
+ } else {
+ qDebug() << "Creating disk image (.dmg) for" << appBundlePath;
+ }
+
+ // More dmg options can be found in the hdiutil man page.
+ QString options = QString("create %1.dmg -srcfolder %1.app -format UDZO -volname %1").arg(appBaseName);
+
+ QProcess hdutil;
+ hdutil.start("hdiutil", options.split(' '));
+ hdutil.waitForFinished(-1);
+}
diff --git a/tools/macdeployqt/shared/shared.h b/tools/macdeployqt/shared/shared.h
new file mode 100644
index 0000000000..5f30dade1f
--- /dev/null
+++ b/tools/macdeployqt/shared/shared.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MAC_DEPLOMYMENT_SHARED_H
+#define MAC_DEPLOMYMENT_SHARED_H
+
+#include <QString>
+#include <QStringList>
+#include <QDebug>
+
+extern bool runStripEnabled;
+
+class FrameworkInfo
+{
+public:
+ QString frameworkDirectory;
+ QString frameworkName;
+ QString frameworkPath;
+ QString binaryDirectory;
+ QString binaryName;
+ QString binaryPath;
+ QString version;
+ QString installName;
+ QString deployedInstallName;
+ QString sourceFilePath;
+ QString destinationDirectory;
+};
+
+bool operator==(const FrameworkInfo &a, const FrameworkInfo &b);
+QDebug operator<<(QDebug debug, const FrameworkInfo &info);
+
+class ApplicationBundleInfo
+{
+public:
+ QString path;
+ QString binaryPath;
+};
+
+class DeploymentInfo
+{
+public:
+ QString qtPath;
+ QString pluginPath;
+ QStringList deployedFrameworks;
+};
+
+
+inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info);
+
+void changeQtFrameworks(const QString appPath, const QString &qtPath);
+void changeQtFrameworks(const QList<FrameworkInfo> frameworks, const QString &appBinaryPath, const QString &qtPath);
+
+FrameworkInfo parseOtoolLibraryLine(const QString &line);
+QString findAppBinary(const QString &appBundlePath);
+QList<FrameworkInfo> getQtFrameworks(const QString &path);
+QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines);
+QString copyFramework(const FrameworkInfo &framework, const QString path);
+DeploymentInfo deployQtFrameworks(const QString &appBundlePath);
+DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks, const QString &bundlePath, const QString &binaryPath);
+void createQtConf(const QString &appBundlePath);
+void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo);
+void changeIdentification(const QString &id, const QString &binaryPath);
+void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath);
+QString findAppBinary(const QString &appBundlePath);
+void createDiskImage(const QString &appBundlePath);
+
+#endif
diff --git a/tools/macdeployqt/tests/deployment_mac.pro b/tools/macdeployqt/tests/deployment_mac.pro
new file mode 100644
index 0000000000..1bde1fdc5c
--- /dev/null
+++ b/tools/macdeployqt/tests/deployment_mac.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+DEPENDPATH += . ../shared/
+INCLUDEPATH += . ../shared/
+TARGET=tst_deployment_mac
+CONFIG += qtestlib
+
+# Input
+SOURCES += tst_deployment_mac.cpp ../shared/shared.cpp
+HEADERS += ../shared/shared.h
+
diff --git a/tools/macdeployqt/tests/tst_deployment_mac.cpp b/tools/macdeployqt/tests/tst_deployment_mac.cpp
new file mode 100644
index 0000000000..5f9c99082d
--- /dev/null
+++ b/tools/macdeployqt/tests/tst_deployment_mac.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore>
+#include <QtTest/QTest>
+#include <shared.h>
+
+class tst_deployment_mac : public QObject
+{
+Q_OBJECT
+private slots:
+ void testParseOtoolLibraryLine();
+ void testgetQtFrameworks();
+ void testFindAppBinarty();
+};
+
+void tst_deployment_mac::testParseOtoolLibraryLine()
+{
+{
+ QString line = " /Users/foo/build/qt-4.4/lib/QtGui.framework/Versions/4/QtGui (compatibility version 4.4.0, current version 4.4.0)";
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+// qDebug() << info;
+ QCOMPARE(info.frameworkDirectory, QLatin1String("/Users/foo/build/qt-4.4/lib/"));
+ QCOMPARE(info.frameworkName, QLatin1String("QtGui.framework"));
+ QCOMPARE(info.frameworkPath, QLatin1String("/Users/foo/build/qt-4.4/lib/QtGui.framework"));
+ QCOMPARE(info.binaryDirectory, QLatin1String("Versions/4"));
+ QCOMPARE(info.binaryName, QLatin1String("QtGui"));
+ QCOMPARE(info.binaryPath, QLatin1String("/Versions/4/QtGui"));
+ QCOMPARE(info.version, QLatin1String("4"));
+ QCOMPARE(info.installName, QLatin1String("/Users/foo/build/qt-4.4/lib/QtGui.framework/Versions/4/QtGui"));
+ QCOMPARE(info.deployedInstallName, QLatin1String("@executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui"));
+ QCOMPARE(info.sourceFilePath, QLatin1String("/Users/foo/build/qt-4.4/lib/QtGui.framework/Versions/4/QtGui"));
+ QCOMPARE(info.destinationDirectory, QLatin1String("Contents/Frameworks/QtGui.framework/Versions/4"));
+}
+{
+ QString line = " /Users/foo/build/qt-4.4/lib/phonon.framework/Versions/4/phonon (compatibility version 4.1.0, current version 4.1.0)";
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+// qDebug() << info;
+ QCOMPARE(info.frameworkDirectory, QLatin1String("/Users/foo/build/qt-4.4/lib/"));
+ QCOMPARE(info.frameworkName, QLatin1String("phonon.framework"));
+ QCOMPARE(info.frameworkPath, QLatin1String("/Users/foo/build/qt-4.4/lib/phonon.framework"));
+ QCOMPARE(info.binaryDirectory, QLatin1String("Versions/4"));
+ QCOMPARE(info.binaryName, QLatin1String("phonon"));
+ QCOMPARE(info.binaryPath, QLatin1String("/Versions/4/phonon"));
+ QCOMPARE(info.version, QLatin1String("4"));
+ QCOMPARE(info.installName, QLatin1String("/Users/foo/build/qt-4.4/lib/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.deployedInstallName, QLatin1String("@executable_path/../Frameworks/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.sourceFilePath, QLatin1String("/Users/foo/build/qt-4.4/lib/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.destinationDirectory, QLatin1String("Contents/Frameworks/phonon.framework/Versions/4"));
+}
+
+{
+ QString line = " /usr/local/Trolltech/Qt-4.4.0/lib/phonon.framework/Versions/4/phonon (compatibility version 4.1.0, current version 4.1.0)";
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+// qDebug() << info;
+ QCOMPARE(info.frameworkDirectory, QLatin1String("/usr/local/Trolltech/Qt-4.4.0/lib/"));
+ QCOMPARE(info.frameworkName, QLatin1String("phonon.framework"));
+ QCOMPARE(info.frameworkPath, QLatin1String("/usr/local/Trolltech/Qt-4.4.0/lib/phonon.framework"));
+ QCOMPARE(info.binaryDirectory, QLatin1String("Versions/4"));
+ QCOMPARE(info.binaryName, QLatin1String("phonon"));
+ QCOMPARE(info.binaryPath, QLatin1String("/Versions/4/phonon"));
+ QCOMPARE(info.version, QLatin1String("4"));
+ QCOMPARE(info.installName, QLatin1String("/usr/local/Trolltech/Qt-4.4.0/lib/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.deployedInstallName, QLatin1String("@executable_path/../Frameworks/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.sourceFilePath, QLatin1String("/usr/local/Trolltech/Qt-4.4.0/lib/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.destinationDirectory, QLatin1String("Contents/Frameworks/phonon.framework/Versions/4"));
+}
+
+{
+ QString line = " QtGui.framework/Versions/4/QtGui (compatibility version 4.1.0, current version 4.1.0)";
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+// qDebug() << info;
+ QCOMPARE(info.frameworkDirectory, QLatin1String("/Library/Frameworks/"));
+ QCOMPARE(info.frameworkName, QLatin1String("QtGui.framework"));
+ QCOMPARE(info.frameworkPath, QLatin1String("/Library/Frameworks/QtGui.framework"));
+ QCOMPARE(info.binaryDirectory, QLatin1String("Versions/4"));
+ QCOMPARE(info.binaryName, QLatin1String("QtGui"));
+ QCOMPARE(info.binaryPath, QLatin1String("/Versions/4/QtGui"));
+ QCOMPARE(info.version, QLatin1String("4"));
+ QCOMPARE(info.installName, QLatin1String("QtGui.framework/Versions/4/QtGui"));
+ QCOMPARE(info.deployedInstallName, QLatin1String("@executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui"));
+ QCOMPARE(info.sourceFilePath, QLatin1String("/Library/Frameworks/QtGui.framework/Versions/4/QtGui"));
+ QCOMPARE(info.destinationDirectory, QLatin1String("Contents/Frameworks/QtGui.framework/Versions/4"));
+}
+
+{
+ QString line = " phonon.framework/Versions/4/QtGui (compatibility version 4.1.0, current version 4.1.0)";
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+// qDebug() << info;
+ QCOMPARE(info.frameworkDirectory, QLatin1String("/Library/Frameworks/"));
+ QCOMPARE(info.frameworkName, QLatin1String("phonon.framework"));
+ QCOMPARE(info.frameworkPath, QLatin1String("/Library/Frameworks/phonon.framework"));
+ QCOMPARE(info.binaryDirectory, QLatin1String("Versions/4"));
+ QCOMPARE(info.binaryName, QLatin1String("phonon"));
+ QCOMPARE(info.binaryPath, QLatin1String("/Versions/4/phonon"));
+ QCOMPARE(info.version, QLatin1String("4"));
+ QCOMPARE(info.installName, QLatin1String("phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.deployedInstallName, QLatin1String("@executable_path/../Frameworks/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.sourceFilePath, QLatin1String("/Library/Frameworks/phonon.framework/Versions/4/phonon"));
+ QCOMPARE(info.destinationDirectory, QLatin1String("Contents/Frameworks/phonon.framework/Versions/4"));
+}
+
+{
+ QString line = " /Users/foo/build/qt-4.4/lib/libQtCLucene.4.dylib (compatibility version 4.4.0, current version 4.4.0)";
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+// qDebug() << info;
+ QCOMPARE(info.frameworkDirectory, QLatin1String("/Users/foo/build/qt-4.4/lib/"));
+ QCOMPARE(info.binaryName, QLatin1String("libQtCLucene.4.dylib"));
+ QCOMPARE(info.frameworkName, QLatin1String("libQtCLucene.4.dylib"));
+ QCOMPARE(info.frameworkPath, QLatin1String("/Users/foo/build/qt-4.4/lib/libQtCLucene.4.dylib"));
+ QCOMPARE(info.installName, QLatin1String("/Users/foo/build/qt-4.4/lib/libQtCLucene.4.dylib"));
+ QCOMPARE(info.deployedInstallName, QLatin1String("@executable_path/../Frameworks/libQtCLucene.4.dylib"));
+ QCOMPARE(info.sourceFilePath, QLatin1String("/Users/foo/build/qt-4.4/lib/libQtCLucene.4.dylib"));
+ QCOMPARE(info.destinationDirectory, QLatin1String("Contents/Frameworks/"));
+}
+{
+ QString line = "libQtCLucene.4.dylib (compatibility version 4.4.0, current version 4.4.0)";
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+// qDebug() << info;
+ QCOMPARE(info.frameworkDirectory, QLatin1String("/usr/lib/"));
+ QCOMPARE(info.binaryName, QLatin1String("libQtCLucene.4.dylib"));
+ QCOMPARE(info.frameworkName, QLatin1String("libQtCLucene.4.dylib"));
+ QCOMPARE(info.frameworkPath, QLatin1String("/usr/lib/libQtCLucene.4.dylib"));
+ QCOMPARE(info.installName, QLatin1String("libQtCLucene.4.dylib"));
+ QCOMPARE(info.deployedInstallName, QLatin1String("@executable_path/../Frameworks/libQtCLucene.4.dylib"));
+ QCOMPARE(info.sourceFilePath, QLatin1String("/usr/lib/libQtCLucene.4.dylib"));
+ QCOMPARE(info.destinationDirectory, QLatin1String("Contents/Frameworks/"));
+}
+{
+ QString line = "/foo"; //invalid
+ FrameworkInfo info = parseOtoolLibraryLine(line);
+ QCOMPARE(info.frameworkName, QString());
+}
+
+}
+
+void tst_deployment_mac::testgetQtFrameworks()
+{
+{
+ QStringList otool = QStringList()
+ << "/Users/foo/build/qt-4.4/lib/phonon.framework/Versions/4/phonon (compatibility version 4.1.0, current version 4.1.0)"
+ << "/Users/foo/build/qt-4.4/lib/QtGui.framework/Versions/4/QtGui (compatibility version 4.4.0, current version 4.4.0)"
+ << "/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 136.0.0)"
+ << "/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 949.27.0)"
+ << "/Users/foo/build/qt-4.4/lib/QtCore.framework/Versions/4/QtCore (compatibility version 4.4.0, current version 4.4.0)"
+ << "/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.3)"
+ << "/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)"
+ << "/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.4.0)"
+ << "/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)"
+ << " "
+ ;
+
+ QList<FrameworkInfo> frameworks = getQtFrameworks(otool);
+ QCOMPARE(frameworks.count(), 3);
+ QCOMPARE(frameworks.at(0).binaryName, QLatin1String("phonon"));
+ QCOMPARE(frameworks.at(1).binaryName, QLatin1String("QtGui"));
+ QCOMPARE(frameworks.at(2).binaryName, QLatin1String("QtCore"));
+}
+{
+ QStringList otool = QStringList()
+ << "QtHelp.framework/Versions/4/QtHelp (compatibility version 4.4.0, current version 4.4.0)"
+ << "libQtCLucene.4.dylib (compatibility version 4.4.0, current version 4.4.0)"
+ << "QtSql.framework/Versions/4/QtSql (compatibility version 4.4.0, current version 4.4.0)"
+ << "QtXml.framework/Versions/4/QtXml (compatibility version 4.4.0, current version 4.4.0)"
+ << "QtGui.framework/Versions/4/QtGui (compatibility version 4.4.0, current version 4.4.0)"
+ << "/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 128.0.0)"
+ << "/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 824.42.0)"
+ << "QtNetwork.framework/Versions/4/QtNetwork (compatibility version 4.4.0, current version 4.4.0)"
+ << "QtCore.framework/Versions/4/QtCore (compatibility version 4.4.0, current version 4.4.0)"
+ << "/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.3)"
+ << "/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.6)"
+ << "/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.4.0)"
+ << "/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)"
+ ;
+
+ QList<FrameworkInfo> frameworks = getQtFrameworks(otool);
+ QCOMPARE(frameworks.count(), 7);
+ QCOMPARE(frameworks.at(0).binaryName, QLatin1String("QtHelp"));
+ QCOMPARE(frameworks.at(1).binaryName, QLatin1String("libQtCLucene.4.dylib"));
+ QCOMPARE(frameworks.at(2).binaryName, QLatin1String("QtSql"));
+ QCOMPARE(frameworks.at(3).binaryName, QLatin1String("QtXml"));
+ QCOMPARE(frameworks.at(4).binaryName, QLatin1String("QtGui"));
+ QCOMPARE(frameworks.at(5).binaryName, QLatin1String("QtNetwork"));
+ QCOMPARE(frameworks.at(6).binaryName, QLatin1String("QtCore"));
+}
+
+}
+
+void tst_deployment_mac::testFindAppBinarty()
+{
+ QCOMPARE(findAppBinary("tst_deployment_mac.app"), QLatin1String("tst_deployment_mac.app/Contents/MacOS/tst_deployment_mac"));
+}
+
+QTEST_MAIN(tst_deployment_mac)
+
+#include "tst_deployment_mac.moc" \ No newline at end of file
diff --git a/tools/makeqpf/Blocks.txt b/tools/makeqpf/Blocks.txt
new file mode 100644
index 0000000000..9cc87547f2
--- /dev/null
+++ b/tools/makeqpf/Blocks.txt
@@ -0,0 +1,185 @@
+# Blocks-5.0.0.txt
+# Date: 2006-02-15, 15:40:00 [KW]
+#
+# Unicode Character Database
+# Copyright (c) 1991-2006 Unicode, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+# For documentation, see UCD.html
+#
+# Note: The casing of block names is not normative.
+# For example, "Basic Latin" and "BASIC LATIN" are equivalent.
+#
+# Format:
+# Start Code..End Code; Block Name
+
+# ================================================
+
+# Note: When comparing block names, casing, whitespace, hyphens,
+# and underbars are ignored.
+# For example, "Latin Extended-A" and "latin extended a" are equivalent.
+# For more information on the comparison of property values,
+# see UCD.html.
+#
+# All code points not explicitly listed for Block
+# have the value No_Block.
+
+# Property: Block
+#
+# @missing: 0000..10FFFF; No_Block
+
+0000..007F; Basic Latin
+0080..00FF; Latin-1 Supplement
+0100..017F; Latin Extended-A
+0180..024F; Latin Extended-B
+0250..02AF; IPA Extensions
+02B0..02FF; Spacing Modifier Letters
+0300..036F; Combining Diacritical Marks
+0370..03FF; Greek and Coptic
+0400..04FF; Cyrillic
+0500..052F; Cyrillic Supplement
+0530..058F; Armenian
+0590..05FF; Hebrew
+0600..06FF; Arabic
+0700..074F; Syriac
+0750..077F; Arabic Supplement
+0780..07BF; Thaana
+07C0..07FF; NKo
+0900..097F; Devanagari
+0980..09FF; Bengali
+0A00..0A7F; Gurmukhi
+0A80..0AFF; Gujarati
+0B00..0B7F; Oriya
+0B80..0BFF; Tamil
+0C00..0C7F; Telugu
+0C80..0CFF; Kannada
+0D00..0D7F; Malayalam
+0D80..0DFF; Sinhala
+0E00..0E7F; Thai
+0E80..0EFF; Lao
+0F00..0FFF; Tibetan
+1000..109F; Myanmar
+10A0..10FF; Georgian
+1100..11FF; Hangul Jamo
+1200..137F; Ethiopic
+1380..139F; Ethiopic Supplement
+13A0..13FF; Cherokee
+1400..167F; Unified Canadian Aboriginal Syllabics
+1680..169F; Ogham
+16A0..16FF; Runic
+1700..171F; Tagalog
+1720..173F; Hanunoo
+1740..175F; Buhid
+1760..177F; Tagbanwa
+1780..17FF; Khmer
+1800..18AF; Mongolian
+1900..194F; Limbu
+1950..197F; Tai Le
+1980..19DF; New Tai Lue
+19E0..19FF; Khmer Symbols
+1A00..1A1F; Buginese
+1B00..1B7F; Balinese
+1D00..1D7F; Phonetic Extensions
+1D80..1DBF; Phonetic Extensions Supplement
+1DC0..1DFF; Combining Diacritical Marks Supplement
+1E00..1EFF; Latin Extended Additional
+1F00..1FFF; Greek Extended
+2000..206F; General Punctuation
+2070..209F; Superscripts and Subscripts
+20A0..20CF; Currency Symbols
+20D0..20FF; Combining Diacritical Marks for Symbols
+2100..214F; Letterlike Symbols
+2150..218F; Number Forms
+2190..21FF; Arrows
+2200..22FF; Mathematical Operators
+2300..23FF; Miscellaneous Technical
+2400..243F; Control Pictures
+2440..245F; Optical Character Recognition
+2460..24FF; Enclosed Alphanumerics
+2500..257F; Box Drawing
+2580..259F; Block Elements
+25A0..25FF; Geometric Shapes
+2600..26FF; Miscellaneous Symbols
+2700..27BF; Dingbats
+27C0..27EF; Miscellaneous Mathematical Symbols-A
+27F0..27FF; Supplemental Arrows-A
+2800..28FF; Braille Patterns
+2900..297F; Supplemental Arrows-B
+2980..29FF; Miscellaneous Mathematical Symbols-B
+2A00..2AFF; Supplemental Mathematical Operators
+2B00..2BFF; Miscellaneous Symbols and Arrows
+2C00..2C5F; Glagolitic
+2C60..2C7F; Latin Extended-C
+2C80..2CFF; Coptic
+2D00..2D2F; Georgian Supplement
+2D30..2D7F; Tifinagh
+2D80..2DDF; Ethiopic Extended
+2E00..2E7F; Supplemental Punctuation
+2E80..2EFF; CJK Radicals Supplement
+2F00..2FDF; Kangxi Radicals
+2FF0..2FFF; Ideographic Description Characters
+3000..303F; CJK Symbols and Punctuation
+3040..309F; Hiragana
+30A0..30FF; Katakana
+3100..312F; Bopomofo
+3130..318F; Hangul Compatibility Jamo
+3190..319F; Kanbun
+31A0..31BF; Bopomofo Extended
+31C0..31EF; CJK Strokes
+31F0..31FF; Katakana Phonetic Extensions
+3200..32FF; Enclosed CJK Letters and Months
+3300..33FF; CJK Compatibility
+3400..4DBF; CJK Unified Ideographs Extension A
+4DC0..4DFF; Yijing Hexagram Symbols
+4E00..9FFF; CJK Unified Ideographs
+A000..A48F; Yi Syllables
+A490..A4CF; Yi Radicals
+A700..A71F; Modifier Tone Letters
+A720..A7FF; Latin Extended-D
+A800..A82F; Syloti Nagri
+A840..A87F; Phags-pa
+AC00..D7AF; Hangul Syllables
+D800..DB7F; High Surrogates
+DB80..DBFF; High Private Use Surrogates
+DC00..DFFF; Low Surrogates
+E000..F8FF; Private Use Area
+F900..FAFF; CJK Compatibility Ideographs
+FB00..FB4F; Alphabetic Presentation Forms
+FB50..FDFF; Arabic Presentation Forms-A
+FE00..FE0F; Variation Selectors
+FE10..FE1F; Vertical Forms
+FE20..FE2F; Combining Half Marks
+FE30..FE4F; CJK Compatibility Forms
+FE50..FE6F; Small Form Variants
+FE70..FEFF; Arabic Presentation Forms-B
+FF00..FFEF; Halfwidth and Fullwidth Forms
+FFF0..FFFF; Specials
+10000..1007F; Linear B Syllabary
+10080..100FF; Linear B Ideograms
+10100..1013F; Aegean Numbers
+10140..1018F; Ancient Greek Numbers
+10300..1032F; Old Italic
+10330..1034F; Gothic
+10380..1039F; Ugaritic
+103A0..103DF; Old Persian
+10400..1044F; Deseret
+10450..1047F; Shavian
+10480..104AF; Osmanya
+10800..1083F; Cypriot Syllabary
+10900..1091F; Phoenician
+10A00..10A5F; Kharoshthi
+12000..123FF; Cuneiform
+12400..1247F; Cuneiform Numbers and Punctuation
+1D000..1D0FF; Byzantine Musical Symbols
+1D100..1D1FF; Musical Symbols
+1D200..1D24F; Ancient Greek Musical Notation
+1D300..1D35F; Tai Xuan Jing Symbols
+1D360..1D37F; Counting Rod Numerals
+1D400..1D7FF; Mathematical Alphanumeric Symbols
+20000..2A6DF; CJK Unified Ideographs Extension B
+2F800..2FA1F; CJK Compatibility Ideographs Supplement
+E0000..E007F; Tags
+E0100..E01EF; Variation Selectors Supplement
+F0000..FFFFF; Supplementary Private Use Area-A
+100000..10FFFF; Supplementary Private Use Area-B
+
+# EOF \ No newline at end of file
diff --git a/tools/makeqpf/README b/tools/makeqpf/README
new file mode 100644
index 0000000000..6656355459
--- /dev/null
+++ b/tools/makeqpf/README
@@ -0,0 +1 @@
+This tool is used to create pre-rendered fonts for use with Qtopia Core.
diff --git a/tools/makeqpf/main.cpp b/tools/makeqpf/main.cpp
new file mode 100644
index 0000000000..919841cc9f
--- /dev/null
+++ b/tools/makeqpf/main.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "qpf2.h"
+#include "mainwindow.h"
+
+#include <private/qfontengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static void help()
+{
+ printf("usage:\n");
+ printf("makeqpf fontname pixelsize [italic] [bold] [--exclude-cmap] [-v]\n");
+ printf("makeqpf -dump [-v] file.qpf2\n");
+ exit(0);
+}
+
+static int gui(const QString &customFont = QString())
+{
+ MainWindow mw(customFont);
+ mw.show();
+ return qApp->exec();
+}
+
+QT_END_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ QT_USE_NAMESPACE
+
+ QApplication app(argc, argv);
+ app.setOrganizationName(QLatin1String("Trolltech"));
+ app.setApplicationName(QLatin1String("MakeQPF"));
+
+ const QStringList arguments = app.arguments();
+
+ if (arguments.count() <= 1) {
+ return gui();
+ } else if (arguments.count() == 2
+ && QFile::exists(arguments.at(1))) {
+ return gui(arguments.at(1));
+ }
+
+ const QString &firstArg = arguments.at(1);
+ if (firstArg == QLatin1String("-h") || firstArg == QLatin1String("--help"))
+ help();
+ if (firstArg == QLatin1String("-dump")) {
+ QString file;
+ for (int i = 2; i < arguments.count(); ++i) {
+ if (arguments.at(i).startsWith(QLatin1String("-v")))
+ QPF::debugVerbosity += arguments.at(i).length() - 1;
+ else if (file.isEmpty())
+ file = arguments.at(i);
+ else
+ help();
+ }
+
+ if (file.isEmpty())
+ help();
+
+ QFile f(file);
+ if (!f.open(QIODevice::ReadOnly)) {
+ printf("cannot open %s\n", qPrintable(file));
+ exit(1);
+ }
+
+ QByteArray qpf = f.readAll();
+ f.close();
+
+ QPF::dump(qpf);
+ return 0;
+ }
+
+ if (arguments.count() < 3) help();
+
+ QFont font;
+
+ QString fontName = firstArg;
+ if (QFile::exists(fontName)) {
+ int id = QFontDatabase::addApplicationFont(fontName);
+ if (id == -1) {
+ printf("cannot open font %s", qPrintable(fontName));
+ help();
+ }
+ QStringList families = QFontDatabase::applicationFontFamilies(id);
+ if (families.isEmpty()) {
+ printf("cannot find any font families in %s", qPrintable(fontName));
+ help();
+ }
+ fontName = families.first();
+ }
+ font.setFamily(fontName);
+
+ bool ok = false;
+ int pixelSize = arguments.at(2).toInt(&ok);
+ if (!ok) help();
+ font.setPixelSize(pixelSize);
+
+ int generationOptions = QPF::IncludeCMap | QPF::RenderGlyphs;
+
+ for (int i = 3; i < arguments.count(); ++i) {
+ const QString &arg = arguments.at(i);
+ if (arg == QLatin1String("italic")) {
+ font.setItalic(true);
+ } else if (arg == QLatin1String("bold")) {
+ font.setBold(true);
+ } else if (arg == QLatin1String("--exclude-cmap")) {
+ generationOptions &= ~QPF::IncludeCMap;
+ } else if (arg == QLatin1String("--exclude-glyphs")) {
+ generationOptions &= ~QPF::RenderGlyphs;
+ } else if (arg == QLatin1String("-v")) {
+ ++QPF::debugVerbosity;
+ } else {
+ printf("unknown option %s\n", qPrintable(arg));
+ help();
+ }
+ }
+
+ font.setStyleStrategy(QFont::NoFontMerging);
+
+ QList<QPF::CharacterRange> ranges;
+ ranges.append(QPF::CharacterRange()); // default range from 0 to 0xffff
+
+ QString origFont;
+ QByteArray qpf = QPF::generate(font, generationOptions, ranges, &origFont);
+
+ QString fileName = QPF::fileNameForFont(font);
+ QFile f(fileName);
+ f.open(QIODevice::WriteOnly | QIODevice::Truncate);
+ f.write(qpf);
+ f.close();
+
+ if (generationOptions & QPF::IncludeCMap) {
+ printf("Created %s from %s\n", qPrintable(fileName), qPrintable(origFont));
+ } else {
+ printf("Created %s from %s excluding the character-map\n", qPrintable(fileName), qPrintable(origFont));
+ printf("The TrueType font file is therefore required for the font to work\n");
+ }
+
+ return 0;
+}
+
diff --git a/tools/makeqpf/mainwindow.cpp b/tools/makeqpf/mainwindow.cpp
new file mode 100644
index 0000000000..8a4da8c8bd
--- /dev/null
+++ b/tools/makeqpf/mainwindow.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QFontComboBox>
+#include <QFontDatabase>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QListWidget>
+#include <QDebug>
+#include <QShortcut>
+#include <QCompleter>
+#include <QDirModel>
+#include <QTextCodec>
+
+QT_BEGIN_NAMESPACE
+
+MainWindow::MainWindow(const QString &customFont)
+{
+ setupUi(this);
+ pixelSize->setValue(QFontInfo(QFont()).pixelSize());
+ populateCharacterRanges();
+
+ {
+ weightCombo->addItem(QLatin1String("Light"), QVariant(int(QFont::Light)));
+ const int normalIdx = weightCombo->count();
+ weightCombo->addItem(QLatin1String("Normal"), QVariant(int(QFont::Normal)));
+ weightCombo->addItem(QLatin1String("DemiBold"), QVariant(int(QFont::DemiBold)));
+ weightCombo->addItem(QLatin1String("Bold"), QVariant(int(QFont::Bold)));
+ weightCombo->addItem(QLatin1String("Black"), QVariant(int(QFont::Black)));
+
+ weightCombo->setCurrentIndex(normalIdx);
+ }
+
+ QShortcut *sc = new QShortcut(Qt::ControlModifier + Qt::Key_A, this);
+ connect(sc, SIGNAL(activated()),
+ this, SLOT(on_selectAll_clicked()));
+ sc = new QShortcut(Qt::ControlModifier + Qt::Key_D, this);
+ connect(sc, SIGNAL(activated()),
+ this, SLOT(on_deselectAll_clicked()));
+ sc = new QShortcut(Qt::ControlModifier + Qt::Key_I, this);
+ connect(sc, SIGNAL(activated()),
+ this, SLOT(on_invertSelection_clicked()));
+
+ QCompleter *completer = new QCompleter(this);
+ completer->setModel(new QDirModel(this));
+ path->setCompleter(completer);
+ path->setText(QDir::currentPath());
+
+ completer = new QCompleter(this);
+ completer->setModel(new QDirModel(this));
+ sampleFile->setCompleter(completer);
+ charCount->setText(QString());
+
+ if (!customFont.isEmpty())
+ addCustomFont(customFont);
+
+ fontChanged();
+
+ connect(fontComboBox, SIGNAL(currentFontChanged(QFont)),
+ this, SLOT(fontChanged()));
+ connect(pixelSize, SIGNAL(valueChanged(int)),
+ this, SLOT(fontChanged()));
+ connect(italic, SIGNAL(stateChanged(int)),
+ this, SLOT(fontChanged()));
+ connect(weightCombo, SIGNAL(currentIndexChanged(int)),
+ this, SLOT(fontChanged()));
+}
+
+void MainWindow::on_actionAdd_Custom_Font_triggered()
+{
+ QString fontFile = QFileDialog::getOpenFileName(this, tr("Add Custom Font"));
+ if (fontFile.isEmpty())
+ return;
+ addCustomFont(fontFile);
+}
+
+void MainWindow::on_selectAll_clicked()
+{
+ for (int i = 0; i < characterRangeView->count(); ++i)
+ characterRangeView->item(i)->setCheckState(Qt::Checked);
+}
+
+void MainWindow::on_deselectAll_clicked()
+{
+ for (int i = 0; i < characterRangeView->count(); ++i)
+ characterRangeView->item(i)->setCheckState(Qt::Unchecked);
+}
+
+void MainWindow::on_invertSelection_clicked()
+{
+ for (int i = 0; i < characterRangeView->count(); ++i) {
+ QListWidgetItem *item = characterRangeView->item(i);
+ if (item->checkState() == Qt::Checked)
+ item->setCheckState(Qt::Unchecked);
+ else
+ item->setCheckState(Qt::Checked);
+ }
+}
+
+void MainWindow::fontChanged()
+{
+ QFont f = preview->font();
+ f.setStyleStrategy(QFont::NoFontMerging);
+ f.setPixelSize(pixelSize->value());
+ f.setFamily(fontComboBox->currentFont().family());
+ f.setItalic(italic->isChecked());
+ f.setWeight(weightCombo->itemData(weightCombo->currentIndex()).toInt());
+
+ if (!preview->isModified()) {
+ QFontDatabase db;
+ QFontDatabase::WritingSystem ws = db.writingSystems(f.family()).value(0, QFontDatabase::Any);
+ QString sample = db.writingSystemSample(ws);
+ preview->setText(sample);
+ preview->setModified(false);
+ }
+
+ fileName->setText(QPF::fileNameForFont(f));
+
+ preview->setFont(f);
+}
+
+void MainWindow::on_browsePath_clicked()
+{
+ QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
+ if (!dir.isEmpty())
+ path->setText(dir);
+}
+
+void MainWindow::on_browseSampleFile_clicked()
+{
+ QString dir = QFileDialog::getOpenFileName(this, tr("Select Sample File"));
+ if (!dir.isEmpty()) {
+ sampleFile->setText(dir);
+ on_sampleFile_editingFinished();
+ }
+}
+
+void MainWindow::on_generate_clicked()
+{
+ QFile f(path->text() + QDir::separator() + fileName->text());
+ if (f.exists()) {
+ if (QMessageBox::warning(this, QString(),
+ tr("%1 already exists.\nDo you want to replace it?").arg(f.fileName()),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
+ != QMessageBox::Yes) {
+ statusBar()->showMessage(tr("Pre-rendering aborted..."));
+ return;
+ }
+ }
+
+ QList<QPF::CharacterRange> ranges;
+
+ if (chooseFromSampleFile->isChecked()) {
+ ranges = sampleFileRanges;
+ } else if (chooseFromCodePoints->isChecked()) {
+ ranges.clear();
+ for (int i = 0; i < characterRangeView->count(); ++i) {
+ QListWidgetItem *item = characterRangeView->item(i);
+ if (item->checkState() != Qt::Checked)
+ continue;
+
+ QPF::CharacterRange range = qVariantValue<QPF::CharacterRange>(item->data(Qt::UserRole));
+ ranges.append(range);
+ }
+ }
+
+ const int generationOptions = QPF::IncludeCMap | QPF::RenderGlyphs;
+ QByteArray qpf = QPF::generate(preview->font(), generationOptions, ranges);
+ f.open(QIODevice::WriteOnly | QIODevice::Truncate);
+ f.write(qpf);
+ f.close();
+
+ statusBar()->showMessage(tr("Font successfully pre-rendered to %1").arg(fileName->text()));
+}
+
+void MainWindow::on_sampleFile_editingFinished()
+{
+ sampleFileRanges.clear();
+ QFile f(sampleFile->text());
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ sampleFileRanges.append(QPF::CharacterRange()); // default = all
+ return;
+ }
+ QTextStream stream(&f);
+ stream.setCodec(QTextCodec::codecForName("utf-8"));
+ stream.setAutoDetectUnicode(true);
+ QString text = stream.readAll();
+
+ QSet<QChar> coverage;
+ for (int i = 0; i < text.length(); ++i)
+ coverage.insert(text.at(i));
+
+ QList<QChar> sortedCoverage = QList<QChar>::fromSet(coverage);
+ qSort(sortedCoverage);
+ // play simple :)
+ foreach (QChar ch, sortedCoverage) {
+ QPF::CharacterRange r;
+ r.start = ch.unicode();
+ r.end = r.start + 1;
+ sampleFileRanges.append(r);
+ }
+
+ charCount->setText(tr("(%1 unique characters found)").arg(sortedCoverage.count()));
+}
+
+void MainWindow::populateCharacterRanges()
+{
+ QFile f(":/Blocks.txt");
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
+
+ QRegExp rangeExpr("([0-9a-f]+)\\.\\.([0-9a-f]+); (.+)");
+ rangeExpr.setCaseSensitivity(Qt::CaseInsensitive);
+
+ QString ellipsis(QChar(0x2026));
+ if (!characterRangeView->fontMetrics().inFont(ellipsis.at(0)))
+ ellipsis = QLatin1String("...");
+
+ while (!f.atEnd()) {
+ QString line = QString::fromAscii(f.readLine());
+
+ if (line.endsWith(QLatin1Char('\n')))
+ line.chop(1);
+ if (line.endsWith(QLatin1Char('\r')))
+ line.chop(1);
+
+ line = line.trimmed();
+
+ if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
+ continue;
+
+ if (!rangeExpr.exactMatch(line) || rangeExpr.numCaptures() != 3)
+ continue;
+
+ QPF::CharacterRange range;
+
+ bool ok = false;
+ range.start = rangeExpr.cap(1).toUInt(&ok, /*base*/16);
+ if (!ok)
+ continue;
+ range.end = rangeExpr.cap(2).toUInt(&ok, /*base*/16);
+ if (!ok)
+ continue;
+
+ if (range.start >= 0xffff || range.end >= 0xffff)
+ continue;
+
+ QString description = rangeExpr.cap(3);
+
+ QListWidgetItem *item = new QListWidgetItem(characterRangeView);
+ QString text = description;
+ text.append(QLatin1String(" ("));
+ text.append(rangeExpr.cap(1));
+ text.append(ellipsis);
+ text.append(rangeExpr.cap(2));
+ text.append(QLatin1String(")"));
+ item->setText(text);
+ item->setCheckState(Qt::Checked);
+
+ item->setData(Qt::UserRole, qVariantFromValue(range));
+ }
+}
+
+void MainWindow::addCustomFont(const QString &fontFile)
+{
+ int id = QFontDatabase::addApplicationFont(fontFile);
+ if (id < 0) {
+ QMessageBox::warning(this, tr("Error Adding Custom Font"),
+ tr("The custom font %s could not be loaded.").arg(fontFile));
+ return;
+ }
+ const QStringList families = QFontDatabase::applicationFontFamilies(id);
+ if (families.isEmpty()) {
+ QMessageBox::warning(this, tr("Error Adding Custom Font"),
+ tr("The custom font %s provides no font families.").arg(fontFile));
+ return;
+ }
+ QFont f(families.first());
+ fontComboBox->setCurrentFont(f);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/makeqpf/mainwindow.h b/tools/makeqpf/mainwindow.h
new file mode 100644
index 0000000000..dad684bd45
--- /dev/null
+++ b/tools/makeqpf/mainwindow.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+
+#include "ui_mainwindow.h"
+#include "qpf2.h"
+
+QT_BEGIN_NAMESPACE
+
+class QListWidgetItem;
+
+class MainWindow : public QMainWindow, Ui::MainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow(const QString &customFont);
+
+private Q_SLOTS:
+ void on_actionAdd_Custom_Font_triggered();
+ void on_selectAll_clicked();
+ void on_deselectAll_clicked();
+ void on_invertSelection_clicked();
+ void fontChanged();
+ void on_browsePath_clicked();
+ void on_browseSampleFile_clicked();
+ void on_generate_clicked();
+ void on_sampleFile_editingFinished();
+
+private:
+ void populateCharacterRanges();
+ void addCustomFont(const QString &fontFile);
+
+private:
+ QList<QPF::CharacterRange> sampleFileRanges;
+};
+
+QT_END_NAMESPACE
+
+#endif // MAINWINDOW_H
diff --git a/tools/makeqpf/mainwindow.ui b/tools/makeqpf/mainwindow.ui
new file mode 100644
index 0000000000..f6eda4fdd6
--- /dev/null
+++ b/tools/makeqpf/mainwindow.ui
@@ -0,0 +1,502 @@
+<ui version="4.0" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>829</width>
+ <height>813</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>MakeQPF</string>
+ </property>
+ <widget class="QWidget" name="centralwidget" >
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Font Properties</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Family:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFontComboBox" name="fontComboBox" />
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Pixel Size:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="pixelSize" >
+ <property name="minimum" >
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_7" >
+ <property name="text" >
+ <string>Weight:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="weightCombo" />
+ </item>
+ <item>
+ <widget class="QCheckBox" name="italic" >
+ <property name="text" >
+ <string>Italic</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="title" >
+ <string>Glyph Coverage</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="chooseFromCodePoints" >
+ <property name="text" >
+ <string>Choose from Unicode Codepoints:</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QListWidget" name="characterRangeView" />
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="selectAll" >
+ <property name="text" >
+ <string>Select &amp;All</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deselectAll" >
+ <property name="text" >
+ <string>&amp;Deselect All</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="invertSelection" >
+ <property name="text" >
+ <string>&amp;Invert Selection</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="chooseFromSampleFile" >
+ <property name="text" >
+ <string>Choose from Sample Text File (UTF-8 Encoded):</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_5" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Path:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="sampleFile" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="browseSampleFile" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="charCount" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3" >
+ <property name="title" >
+ <string>Preview</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="preview" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_4" >
+ <property name="title" >
+ <string>Output Options</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Path:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="path" />
+ </item>
+ <item>
+ <widget class="QPushButton" name="browsePath" >
+ <property name="text" >
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4" >
+ <property name="text" >
+ <string>Filename:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="fileName" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="generate" >
+ <property name="text" >
+ <string>Generate Pre-Rendered Font...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>829</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFile" >
+ <property name="title" >
+ <string>File</string>
+ </property>
+ <addaction name="actionAdd_Custom_Font" />
+ <addaction name="separator" />
+ <addaction name="action_Exit" />
+ </widget>
+ <addaction name="menuFile" />
+ </widget>
+ <widget class="QStatusBar" name="statusbar" />
+ <action name="actionAdd_Custom_Font" >
+ <property name="text" >
+ <string>&amp;Add Custom Font...</string>
+ </property>
+ </action>
+ <action name="action_Exit" >
+ <property name="text" >
+ <string>&amp;Exit</string>
+ </property>
+ </action>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>action_Exit</sender>
+ <signal>triggered()</signal>
+ <receiver>MainWindow</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>-1</x>
+ <y>-1</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>383</x>
+ <y>215</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromCodePoints</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>characterRangeView</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>183</x>
+ <y>144</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>146</x>
+ <y>295</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromCodePoints</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>selectAll</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>236</x>
+ <y>146</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>46</x>
+ <y>508</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromCodePoints</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>deselectAll</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>280</x>
+ <y>147</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>158</x>
+ <y>502</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromCodePoints</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>invertSelection</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>364</x>
+ <y>143</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>281</x>
+ <y>509</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromSampleFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>sampleFile</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>134</x>
+ <y>544</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>64</x>
+ <y>569</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromSampleFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>browseSampleFile</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>79</x>
+ <y>545</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>710</x>
+ <y>582</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromSampleFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>charCount</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>274</x>
+ <y>544</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>790</x>
+ <y>569</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>chooseFromSampleFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>label_5</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>112</x>
+ <y>541</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>37</x>
+ <y>579</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/makeqpf/makeqpf.pro b/tools/makeqpf/makeqpf.pro
new file mode 100644
index 0000000000..c2dc9cc387
--- /dev/null
+++ b/tools/makeqpf/makeqpf.pro
@@ -0,0 +1,20 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Wed Nov 29 16:21:49 2006
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += . ../../src/3rdparty/harfbuzz/src
+CONFIG += console
+DESTDIR = ../../bin
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+# Input
+HEADERS += qpf2.h mainwindow.h
+SOURCES += main.cpp qpf2.cpp mainwindow.cpp
+DEFINES += QT_NO_FREETYPE
+FORMS += mainwindow.ui
+RESOURCES += makeqpf.qrc
diff --git a/tools/makeqpf/makeqpf.qrc b/tools/makeqpf/makeqpf.qrc
new file mode 100644
index 0000000000..b1d73b0107
--- /dev/null
+++ b/tools/makeqpf/makeqpf.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+ <file>Blocks.txt</file>
+</qresource>
+</RCC>
diff --git a/tools/makeqpf/qpf2.cpp b/tools/makeqpf/qpf2.cpp
new file mode 100644
index 0000000000..b97b9d4c6d
--- /dev/null
+++ b/tools/makeqpf/qpf2.cpp
@@ -0,0 +1,767 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpf2.h"
+
+#include <math.h>
+#include <private/qfontengine_p.h>
+#include <QFile>
+#include <qendian.h>
+
+QT_BEGIN_NAMESPACE
+
+#include "../../src/gui/text/qpfutil.cpp"
+
+int QPF::debugVerbosity = 0;
+
+// ### copied from qfontdatabase.cpp
+
+// see the Unicode subset bitfields in the MSDN docs
+static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
+ // Any,
+ { 127, 127 },
+ // Latin,
+ { 0, 127 },
+ // Greek,
+ { 7, 127 },
+ // Cyrillic,
+ { 9, 127 },
+ // Armenian,
+ { 10, 127 },
+ // Hebrew,
+ { 11, 127 },
+ // Arabic,
+ { 13, 127 },
+ // Syriac,
+ { 71, 127 },
+ //Thaana,
+ { 72, 127 },
+ //Devanagari,
+ { 15, 127 },
+ //Bengali,
+ { 16, 127 },
+ //Gurmukhi,
+ { 17, 127 },
+ //Gujarati,
+ { 18, 127 },
+ //Oriya,
+ { 19, 127 },
+ //Tamil,
+ { 20, 127 },
+ //Telugu,
+ { 21, 127 },
+ //Kannada,
+ { 22, 127 },
+ //Malayalam,
+ { 23, 127 },
+ //Sinhala,
+ { 73, 127 },
+ //Thai,
+ { 24, 127 },
+ //Lao,
+ { 25, 127 },
+ //Tibetan,
+ { 70, 127 },
+ //Myanmar,
+ { 74, 127 },
+ // Georgian,
+ { 26, 127 },
+ // Khmer,
+ { 80, 127 },
+ // SimplifiedChinese,
+ { 126, 127 },
+ // TraditionalChinese,
+ { 126, 127 },
+ // Japanese,
+ { 126, 127 },
+ // Korean,
+ { 56, 127 },
+ // Vietnamese,
+ { 0, 127 }, // same as latin1
+ // Other,
+ { 126, 127 }
+};
+
+#define SimplifiedChineseCsbBit 18
+#define TraditionalChineseCsbBit 20
+#define JapaneseCsbBit 17
+#define KoreanCsbBit 21
+
+static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2])
+{
+ QList<QFontDatabase::WritingSystem> writingSystems;
+ bool hasScript = false;
+
+ int i;
+ for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) {
+ int bit = requiredUnicodeBits[i][0];
+ int index = bit/32;
+ int flag = 1 << (bit&31);
+ if (bit != 126 && unicodeRange[index] & flag) {
+ bit = requiredUnicodeBits[i][1];
+ index = bit/32;
+
+ flag = 1 << (bit&31);
+ if (bit == 127 || unicodeRange[index] & flag) {
+ writingSystems.append(QFontDatabase::WritingSystem(i));
+ hasScript = true;
+ // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i);
+ }
+ }
+ }
+ if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) {
+ writingSystems.append(QFontDatabase::SimplifiedChinese);
+ hasScript = true;
+ //qDebug("font %s supports Simplified Chinese", familyName.latin1());
+ }
+ if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) {
+ writingSystems.append(QFontDatabase::TraditionalChinese);
+ hasScript = true;
+ //qDebug("font %s supports Traditional Chinese", familyName.latin1());
+ }
+ if(codePageRange[0] & (1 << JapaneseCsbBit)) {
+ writingSystems.append(QFontDatabase::Japanese);
+ hasScript = true;
+ //qDebug("font %s supports Japanese", familyName.latin1());
+ }
+ if(codePageRange[0] & (1 << KoreanCsbBit)) {
+ writingSystems.append(QFontDatabase::Korean);
+ hasScript = true;
+ //qDebug("font %s supports Korean", familyName.latin1());
+ }
+ if (!hasScript)
+ writingSystems.append(QFontDatabase::Symbol);
+
+ return writingSystems;
+}
+
+static QByteArray getWritingSystems(QFontEngine *fontEngine)
+{
+ QByteArray os2Table = fontEngine->getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ if (os2Table.isEmpty())
+ return QByteArray();
+
+ const uchar *data = reinterpret_cast<const uchar *>(os2Table.constData());
+
+ quint32 unicodeRange[4] = {
+ qFromBigEndian<quint32>(data + 42),
+ qFromBigEndian<quint32>(data + 46),
+ qFromBigEndian<quint32>(data + 50),
+ qFromBigEndian<quint32>(data + 54)
+ };
+ quint32 codePageRange[2] = { qFromBigEndian<quint32>(data + 78), qFromBigEndian<quint32>(data + 82) };
+ QList<QFontDatabase::WritingSystem> systems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+
+ QByteArray bitField((QFontDatabase::WritingSystemsCount + 7) / 8, 0);
+
+ for (int i = 0; i < systems.count(); ++i) {
+ int bitPos = systems.at(i);
+ bitField[bitPos / 8] = bitField.at(bitPos / 8) | (1 << (bitPos % 8));
+ }
+
+ return bitField;
+}
+
+static QString stringify(const QByteArray &bits)
+{
+ QString result;
+ for (int i = 0; i < bits.count(); ++i) {
+ uchar currentByte = bits.at(i);
+ for (int j = 0; j < 8; ++j) {
+ if (currentByte & 1)
+ result += '1';
+ else
+ result += '0';
+ currentByte >>= 1;
+ }
+ }
+ return result;
+}
+
+static void dumpWritingSystems(const QByteArray &bits)
+{
+ QStringList writingSystems;
+
+ QString bitString = stringify(bits);
+ for (int i = 0; i < qMin(int(QFontDatabase::WritingSystemsCount), bitString.length()); ++i) {
+ if (bitString.at(i) == QLatin1Char('1'))
+ writingSystems << QFontDatabase::writingSystemName(QFontDatabase::WritingSystem(i));
+ }
+
+ qDebug() << "Supported writing systems:" << writingSystems;
+}
+
+static const char *headerTagNames[QFontEngineQPF::NumTags] = {
+ "FontName",
+ "FileName",
+ "FileIndex",
+ "FontRevision",
+ "FreeText",
+ "Ascent",
+ "Descent",
+ "Leading",
+ "XHeight",
+ "AverageCharWidth",
+ "MaxCharWidth",
+ "LineThickness",
+ "MinLeftBearing",
+ "MinRightBearing",
+ "UnderlinePosition",
+ "GlyphFormat",
+ "PixelSize",
+ "Weight",
+ "Style",
+ "EndOfHeader",
+ "WritingSystems"
+};
+
+QString QPF::fileNameForFont(const QFont &f)
+{
+ QString fileName = f.family().toLower() + "_" + QString::number(f.pixelSize())
+ + "_" + QString::number(f.weight())
+ + (f.italic() ? "_italic" : "")
+ + ".qpf2";
+ fileName.replace(QLatin1Char(' '), QLatin1Char('_'));
+ return fileName;
+}
+
+QByteArray QPF::generate(const QFont &font, int options, const QList<CharacterRange> &ranges, QString *originalFontFile)
+{
+ QTextEngine engine("Test", font);
+ engine.itemize();
+ engine.shape(0);
+ QFontEngine *fontEngine = engine.fontEngine(engine.layoutData->items[0]);
+ if (fontEngine->type() == QFontEngine::Multi)
+ fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(0);
+
+ if (originalFontFile)
+ *originalFontFile = QFile::decodeName(fontEngine->faceId().filename);
+
+ return generate(fontEngine, options, ranges);
+}
+
+QByteArray QPF::generate(QFontEngine *fontEngine, int options, const QList<CharacterRange> &ranges)
+{
+ QPF font;
+
+ font.options = options;
+ font.addHeader(fontEngine);
+ if (options & IncludeCMap)
+ font.addCMap(fontEngine);
+ font.addGlyphs(fontEngine, ranges);
+
+ return font.qpf;
+}
+
+void QPF::addHeader(QFontEngine *fontEngine)
+{
+ QFontEngineQPF::Header *header = reinterpret_cast<QFontEngineQPF::Header *>(addBytes(sizeof(QFontEngineQPF::Header)));
+
+ header->magic[0] = 'Q';
+ header->magic[1] = 'P';
+ header->magic[2] = 'F';
+ header->magic[3] = '2';
+ if (options & RenderGlyphs)
+ header->lock = 0xffffffff;
+ else
+ header->lock = 0;
+ header->majorVersion = QFontEngineQPF::CurrentMajorVersion;
+ header->minorVersion = QFontEngineQPF::CurrentMinorVersion;
+ header->dataSize = 0;
+ int oldSize = qpf.size();
+
+ addTaggedString(QFontEngineQPF::Tag_FontName, fontEngine->fontDef.family.toUtf8());
+
+ QFontEngine::FaceId face = fontEngine->faceId();
+ addTaggedString(QFontEngineQPF::Tag_FileName, face.filename);
+ addTaggedUInt32(QFontEngineQPF::Tag_FileIndex, face.index);
+
+ {
+ const QByteArray head = fontEngine->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd'));
+ const quint32 revision = qFromBigEndian<quint32>(reinterpret_cast<const uchar *>(head.constData()) + 4);
+ addTaggedUInt32(QFontEngineQPF::Tag_FontRevision, revision);
+ }
+
+ addTaggedQFixed(QFontEngineQPF::Tag_Ascent, fontEngine->ascent());
+ addTaggedQFixed(QFontEngineQPF::Tag_Descent, fontEngine->descent());
+ addTaggedQFixed(QFontEngineQPF::Tag_Leading, fontEngine->leading());
+ addTaggedQFixed(QFontEngineQPF::Tag_XHeight, fontEngine->xHeight());
+ addTaggedQFixed(QFontEngineQPF::Tag_AverageCharWidth, fontEngine->averageCharWidth());
+ addTaggedQFixed(QFontEngineQPF::Tag_MaxCharWidth, QFixed::fromReal(fontEngine->maxCharWidth()));
+ addTaggedQFixed(QFontEngineQPF::Tag_LineThickness, fontEngine->lineThickness());
+ addTaggedQFixed(QFontEngineQPF::Tag_MinLeftBearing, QFixed::fromReal(fontEngine->minLeftBearing()));
+ addTaggedQFixed(QFontEngineQPF::Tag_MinRightBearing, QFixed::fromReal(fontEngine->minRightBearing()));
+ addTaggedQFixed(QFontEngineQPF::Tag_UnderlinePosition, fontEngine->underlinePosition());
+ addTaggedUInt8(QFontEngineQPF::Tag_PixelSize, fontEngine->fontDef.pixelSize);
+ addTaggedUInt8(QFontEngineQPF::Tag_Weight, fontEngine->fontDef.weight);
+ addTaggedUInt8(QFontEngineQPF::Tag_Style, fontEngine->fontDef.style);
+
+ QByteArray writingSystemBitField = getWritingSystems(fontEngine);
+ if (!writingSystemBitField.isEmpty())
+ addTaggedString(QFontEngineQPF::Tag_WritingSystems, writingSystemBitField);
+
+ addTaggedUInt8(QFontEngineQPF::Tag_GlyphFormat, QFontEngineQPF::AlphamapGlyphs);
+
+ addTaggedString(QFontEngineQPF::Tag_EndOfHeader, QByteArray());
+ align4();
+ header = reinterpret_cast<QFontEngineQPF::Header *>(qpf.data());
+ header->dataSize = qToBigEndian<quint16>(qpf.size() - oldSize);
+}
+
+static uchar *appendBytes(QByteArray &array, int size)
+{
+ int oldSize = array.size();
+ array.resize(array.size() + size);
+ return reinterpret_cast<uchar *>(array.data() + oldSize);
+}
+
+#define APPEND(type, value) \
+ qToBigEndian<type>(value, appendBytes(cmap, sizeof(type)))
+
+struct CMapSegment
+{
+ int start; // codepoints
+ int end;
+ int startGlyphIndex;
+};
+
+static QByteArray generateTrueTypeCMap(QFontEngine *fe)
+{
+ QByteArray cmap;
+ const int glyphCount = fe->glyphCount();
+ if (!glyphCount)
+ return cmap;
+
+ // cmap header
+ APPEND(quint16, 0); // table version number
+ APPEND(quint16, 1); // number of tables
+
+ // encoding record
+ APPEND(quint16, 3); // platform-id
+ APPEND(quint16, 10); // encoding-id (ucs-4)
+ const int cmapOffset = cmap.size() + sizeof(quint32);
+ APPEND(quint32, cmapOffset); // offset to sub-table
+
+ APPEND(quint16, 4); // subtable format
+ const int cmapTableLengthOffset = cmap.size();
+ APPEND(quint16, 0); // length in bytes, will fill in later
+ APPEND(quint16, 0); // language field
+
+ QList<CMapSegment> segments;
+ CMapSegment currentSegment;
+ currentSegment.start = 0xffff;
+ currentSegment.end = 0;
+ currentSegment.startGlyphIndex = 0;
+ quint32 previousGlyphIndex = 0xfffffffe;
+ bool inSegment = false;
+
+ QGlyphLayoutArray<10> layout;
+ for (uint uc = 0; uc < 0x10000; ++uc) {
+ QChar ch(uc);
+ int nglyphs = 10;
+
+ bool validGlyph = fe->stringToCMap(&ch, 1, &layout, &nglyphs, /*flags*/ 0)
+ && nglyphs == 1 && layout.glyphs[0];
+
+ // leaving a segment?
+ if (inSegment && (!validGlyph || layout.glyphs[0] != previousGlyphIndex + 1)) {
+ Q_ASSERT(currentSegment.start != 0xffff);
+ // store the current segment
+ currentSegment.end = uc - 1;
+ segments.append(currentSegment);
+ currentSegment.start = 0xffff;
+ inSegment = false;
+ }
+ // entering a new segment?
+ if (validGlyph && (!inSegment || layout.glyphs[0] != previousGlyphIndex + 1)) {
+ currentSegment.start = uc;
+ currentSegment.startGlyphIndex = layout.glyphs[0];
+ inSegment = true;
+ }
+
+ if (validGlyph)
+ previousGlyphIndex = layout.glyphs[0];
+ else
+ previousGlyphIndex = 0xfffffffe;
+ }
+
+ currentSegment.start = 0xffff;
+ currentSegment.end = 0xffff;
+ currentSegment.startGlyphIndex = 0;
+ segments.append(currentSegment);
+
+ if (QPF::debugVerbosity > 3)
+ qDebug() << "segments:" << segments.count();
+
+ Q_ASSERT(!inSegment);
+
+ const quint16 entrySelector = int(log2(segments.count()));
+ const quint16 searchRange = 2 * (1 << entrySelector);
+ const quint16 rangeShift = segments.count() * 2 - searchRange;
+
+ if (QPF::debugVerbosity > 3)
+ qDebug() << "entrySelector" << entrySelector << "searchRange" << searchRange
+ << "rangeShift" << rangeShift;
+
+ APPEND(quint16, segments.count() * 2); // segCountX2
+ APPEND(quint16, searchRange);
+ APPEND(quint16, entrySelector);
+ APPEND(quint16, rangeShift);
+
+ // end character codes
+ for (int i = 0; i < segments.count(); ++i)
+ APPEND(quint16, segments.at(i).end);
+
+ APPEND(quint16, 0); // pad
+
+ // start character codes
+ for (int i = 0; i < segments.count(); ++i)
+ APPEND(quint16, segments.at(i).start);
+
+ // id deltas
+ for (int i = 0; i < segments.count(); ++i)
+ APPEND(quint16, segments.at(i).startGlyphIndex - segments.at(i).start);
+
+ // id range offsets
+ for (int i = 0; i < segments.count(); ++i)
+ APPEND(quint16, 0);
+
+ uchar *lengthPtr = reinterpret_cast<uchar *>(cmap.data()) + cmapTableLengthOffset;
+ qToBigEndian<quint16>(cmap.size() - cmapOffset, lengthPtr);
+
+ return cmap;
+}
+
+void QPF::addCMap(QFontEngine *fontEngine)
+{
+ QByteArray cmapTable = fontEngine->getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
+ if (cmapTable.isEmpty())
+ cmapTable = generateTrueTypeCMap(fontEngine);
+ addBlock(QFontEngineQPF::CMapBlock, cmapTable);
+}
+
+void QPF::addGlyphs(QFontEngine *fe, const QList<CharacterRange> &ranges)
+{
+ const quint16 glyphCount = fe->glyphCount();
+
+ QByteArray gmap;
+ gmap.resize(glyphCount * sizeof(quint32));
+ gmap.fill(char(0xff));
+ //qDebug() << "glyphCount" << glyphCount;
+
+ QByteArray glyphs;
+ if (options & RenderGlyphs) {
+ // this is only a rough estimation
+ glyphs.reserve(glyphCount
+ * (sizeof(QFontEngineQPF::Glyph)
+ + qRound(fe->maxCharWidth() * (fe->ascent() + fe->descent()).toReal())));
+
+ QGlyphLayoutArray<10> layout;
+
+ foreach (CharacterRange range, ranges) {
+ if (debugVerbosity > 2)
+ qDebug() << "rendering range from" << range.start << "to" << range.end;
+ for (uint uc = range.start; uc < range.end; ++uc) {
+ QChar ch(uc);
+ int nglyphs = 10;
+ if (!fe->stringToCMap(&ch, 1, &layout, &nglyphs, /*flags*/ 0))
+ continue;
+
+ if (nglyphs != 1)
+ continue;
+
+ const quint32 glyphIndex = layout.glyphs[0];
+
+ if (!glyphIndex)
+ continue;
+
+ Q_ASSERT(glyphIndex < glyphCount);
+
+ QImage img = fe->alphaMapForGlyph(glyphIndex).convertToFormat(QImage::Format_Indexed8);
+ glyph_metrics_t metrics = fe->boundingBox(glyphIndex);
+
+ const quint32 oldSize = glyphs.size();
+ glyphs.resize(glyphs.size() + sizeof(QFontEngineQPF::Glyph) + img.numBytes());
+ uchar *data = reinterpret_cast<uchar *>(glyphs.data() + oldSize);
+
+ uchar *gmapPtr = reinterpret_cast<uchar *>(gmap.data() + glyphIndex * sizeof(quint32));
+ qToBigEndian(oldSize, gmapPtr);
+
+ QFontEngineQPF::Glyph *glyph = reinterpret_cast<QFontEngineQPF::Glyph *>(data);
+ glyph->width = img.width();
+ glyph->height = img.height();
+ glyph->bytesPerLine = img.bytesPerLine();
+ glyph->x = qRound(metrics.x);
+ glyph->y = qRound(metrics.y);
+ glyph->advance = qRound(metrics.xoff);
+ data += sizeof(QFontEngineQPF::Glyph);
+
+ if (debugVerbosity && uc >= 'A' && uc <= 'z' || debugVerbosity > 1) {
+ qDebug() << "adding glyph with index" << glyphIndex << " uc =" << char(uc) << ":\n"
+ << " glyph->x =" << glyph->x << "rounded from" << metrics.x << "\n"
+ << " glyph->y =" << glyph->y << "rounded from" << metrics.y << "\n"
+ << " width =" << glyph->width << "height =" << glyph->height
+ << " advance =" << glyph->advance << "rounded from" << metrics.xoff
+ ;
+ }
+
+ qMemCopy(data, img.bits(), img.numBytes());
+ }
+ }
+ }
+
+ addBlock(QFontEngineQPF::GMapBlock, gmap);
+ addBlock(QFontEngineQPF::GlyphBlock, glyphs);
+}
+
+void QPF::addBlock(QFontEngineQPF::BlockTag tag, const QByteArray &blockData)
+{
+ addUInt16(tag);
+ addUInt16(0); // padding
+ const int padSize = ((blockData.size() + 3) / 4) * 4 - blockData.size();
+ addUInt32(blockData.size() + padSize);
+ addByteArray(blockData);
+ for (int i = 0; i < padSize; ++i)
+ addUInt8(0);
+}
+
+#define ADD_TAGGED_DATA(tag, qtype, type, value) \
+ addUInt16(tag); \
+ addUInt16(sizeof(qtype)); \
+ add##type(value)
+
+void QPF::addTaggedString(QFontEngineQPF::HeaderTag tag, const QByteArray &string)
+{
+ addUInt16(tag);
+ addUInt16(string.length());
+ addByteArray(string);
+}
+
+void QPF::addTaggedQFixed(QFontEngineQPF::HeaderTag tag, QFixed value)
+{
+ ADD_TAGGED_DATA(tag, quint32, UInt32, value.value());
+}
+
+void QPF::addTaggedUInt8(QFontEngineQPF::HeaderTag tag, quint8 value)
+{
+ ADD_TAGGED_DATA(tag, quint8, UInt8, value);
+}
+
+void QPF::addTaggedInt8(QFontEngineQPF::HeaderTag tag, qint8 value)
+{
+ ADD_TAGGED_DATA(tag, qint8, Int8, value);
+}
+
+void QPF::addTaggedUInt16(QFontEngineQPF::HeaderTag tag, quint16 value)
+{
+ ADD_TAGGED_DATA(tag, quint16, UInt16, value);
+}
+
+void QPF::addTaggedUInt32(QFontEngineQPF::HeaderTag tag, quint32 value)
+{
+ ADD_TAGGED_DATA(tag, quint32, UInt32, value);
+}
+
+void QPF::dump(const QByteArray &qpf)
+{
+ QPF font;
+ font.qpf = qpf;
+
+ const uchar *data = reinterpret_cast<const uchar *>(qpf.constData());
+ const uchar *endPtr = reinterpret_cast<const uchar *>(qpf.constData() + qpf.size());
+ data = font.dumpHeader(data);
+
+ const quint32 *gmap = 0;
+ quint32 glyphCount = 0;
+
+ while (data < endPtr) {
+ const QFontEngineQPF::Block *block = reinterpret_cast<const QFontEngineQPF::Block *>(data);
+ quint32 tag = qFromBigEndian(block->tag);
+ quint32 blockSize = qFromBigEndian(block->dataSize);
+ qDebug() << "Block: Tag =" << qFromBigEndian(block->tag) << "; Size =" << blockSize << "; Offset =" << hex << data - reinterpret_cast<const uchar *>(qpf.constData());
+ data += sizeof(QFontEngineQPF::Block);
+
+ if (debugVerbosity) {
+ if (tag == QFontEngineQPF::GMapBlock) {
+ gmap = reinterpret_cast<const quint32 *>(data);
+ glyphCount = blockSize / 4;
+ font.dumpGMapBlock(gmap, glyphCount);
+ } else if (tag == QFontEngineQPF::GlyphBlock
+ && gmap && debugVerbosity > 1) {
+ font.dumpGlyphBlock(gmap, glyphCount, data, data + blockSize);
+ }
+ }
+
+ data += blockSize;
+ }
+}
+
+const uchar *QPF::dumpHeader(const uchar *data)
+{
+ const QFontEngineQPF::Header *header = reinterpret_cast<const QFontEngineQPF::Header *>(data);
+ qDebug() << "Header:";
+ qDebug() << "magic ="
+ << header->magic[0]
+ << header->magic[1]
+ << header->magic[2]
+ << header->magic[3];
+ qDebug() << "lock =" << qFromBigEndian(header->lock);
+ qDebug() << "majorVersion =" << header->majorVersion;
+ qDebug() << "minorVersion =" << header->minorVersion;
+ qDebug() << "dataSize =" << qFromBigEndian(header->dataSize);
+
+ data += sizeof(QFontEngineQPF::Header);
+
+ const uchar *endPtr = data + qFromBigEndian(header->dataSize);
+
+ while (data && data < endPtr) {
+ data = dumpHeaderTag(data);
+ }
+
+ return endPtr;
+}
+
+const uchar *QPF::dumpHeaderTag(const uchar *data)
+{
+ const QFontEngineQPF::Tag *tagPtr = reinterpret_cast<const QFontEngineQPF::Tag *>(data);
+ quint16 tag = qFromBigEndian(tagPtr->tag);
+ quint16 size = qFromBigEndian(tagPtr->size);
+
+ qDebug() << "Tag =" << tag << headerTagNames[tag];
+ qDebug() << "Size =" << size;
+
+ if (tag == QFontEngineQPF::Tag_EndOfHeader)
+ return 0;
+
+ data += sizeof(QFontEngineQPF::Tag);
+
+ Q_ASSERT(tag < QFontEngineQPF::NumTags);
+
+ switch (tagTypes[tag]) {
+ case QFontEngineQPF::StringType:
+ qDebug() << "Payload =" << QString::fromUtf8(QByteArray(reinterpret_cast<const char *>(data), size));
+ break;
+ case QFontEngineQPF::FixedType:
+ Q_ASSERT(size == sizeof(quint32));
+ qDebug() << "Payload =" << QFixed::fromFixed(qFromBigEndian<quint32>(data)).toReal();
+ break;
+ case QFontEngineQPF::UInt8Type:
+ Q_ASSERT(size == sizeof(quint8));
+ qDebug() << "Payload =" << *data;
+ break;
+ case QFontEngineQPF::UInt32Type:
+ Q_ASSERT(size == sizeof(quint32));
+ qDebug() << "Payload =" << qFromBigEndian<quint32>(data);
+ break;
+ case QFontEngineQPF::BitFieldType: {
+ QByteArray bits(reinterpret_cast<const char *>(data), size);
+ qDebug() << "Payload =" << stringify(bits);
+ if (QPF::debugVerbosity > 2 && tag == QFontEngineQPF::Tag_WritingSystems)
+ dumpWritingSystems(bits);
+ } break;
+ }
+
+ data += size;
+ return data;
+}
+
+void QPF::dumpGMapBlock(const quint32 *gmap, int glyphCount)
+{
+ qDebug() << "glyphCount =" << glyphCount;
+ int renderedGlyphs = 0;
+ for (int i = 0; i < glyphCount; ++i) {
+ if (gmap[i] != 0xffffffff) {
+ const quint32 glyphPos = qFromBigEndian(gmap[i]);
+ qDebug("gmap[%d] = 0x%x / %u", i, glyphPos, glyphPos);
+ ++renderedGlyphs;
+ }
+ }
+ qDebug() << "Glyphs rendered:" << renderedGlyphs << "; Glyphs missing from the font:" << glyphCount - renderedGlyphs;
+}
+
+void QPF::dumpGlyphBlock(const quint32 *gmap, int glyphCount, const uchar *data, const uchar *endPtr)
+{
+ // glyphPos -> glyphIndex
+ QMap<quint32, quint32> reverseGlyphMap;
+ for (int i = 0; i < glyphCount; ++i) {
+ if (gmap[i] == 0xffffffff)
+ continue;
+ const quint32 glyphPos = qFromBigEndian(gmap[i]);
+ reverseGlyphMap[glyphPos] = i;
+ }
+
+ const uchar *glyphBlockBegin = data;
+ while (data < endPtr) {
+ const QFontEngineQPF::Glyph *g = reinterpret_cast<const QFontEngineQPF::Glyph *>(data);
+
+ const quint64 glyphOffset = data - glyphBlockBegin;
+ const quint32 glyphIndex = reverseGlyphMap.value(glyphOffset, 0xffffffff);
+
+ if (glyphIndex == 0xffffffff)
+ qDebug() << "############: Glyph present in glyph block is not listed in glyph map!";
+ qDebug("glyph at offset 0x%x glyphIndex = %u", quint32(glyphOffset), glyphIndex);
+ qDebug() << " width =" << g->width << "height =" << g->height << "x =" << g->x << "y =" << g->y;
+ qDebug() << " advance =" << g->advance << "bytesPerLine =" << g->bytesPerLine;
+
+ data += sizeof(*g);
+ if (glyphIndex == 0xffffffff || debugVerbosity > 4) {
+ dumpGlyph(data, g);
+ }
+
+ data += g->height * g->bytesPerLine;
+ }
+}
+
+void QPF::dumpGlyph(const uchar *data, const QFontEngineQPF::Glyph *glyph)
+{
+ fprintf(stderr, "---- glyph data:\n");
+ const char *alphas = " .o#";
+ for (int y = 0; y < glyph->height; ++y) {
+ for (int x = 0; x < glyph->width; ++x) {
+ const uchar value = data[y * glyph->bytesPerLine + x];
+ fprintf(stderr, "%c", alphas[value >> 6]);
+ }
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "----\n");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/makeqpf/qpf2.h b/tools/makeqpf/qpf2.h
new file mode 100644
index 0000000000..211ac4db2f
--- /dev/null
+++ b/tools/makeqpf/qpf2.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPF2_H
+#define QPF2_H
+
+#include <private/qfontengine_qpf_p.h>
+#include <qmetatype.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFontEngine;
+
+class QPF
+{
+public:
+ static int debugVerbosity;
+
+ enum GenerationOption {
+ IncludeCMap = 0x1,
+ RenderGlyphs = 0x2
+ };
+
+ struct CharacterRange
+ {
+ inline CharacterRange() : start(0), end(0x10000) {}
+ uint start;
+ uint end;
+ };
+
+ static QString fileNameForFont(const QFont &f);
+
+ static QByteArray generate(const QFont &font, int options,
+ const QList<CharacterRange> &ranges,
+ QString *originalFontFile = 0);
+ static QByteArray generate(QFontEngine *fontEngine, int options, const QList<CharacterRange> &ranges);
+ void addHeader(QFontEngine *fontEngine);
+ void addCMap(QFontEngine *fontEngine);
+ void addGlyphs(QFontEngine *fontEngine, const QList<CharacterRange> &ranges);
+ void addBlock(QFontEngineQPF::BlockTag tag, const QByteArray &data);
+
+ void addTaggedString(QFontEngineQPF::HeaderTag tag, const QByteArray &string);
+ void addTaggedQFixed(QFontEngineQPF::HeaderTag tag, QFixed value);
+ void addTaggedUInt8(QFontEngineQPF::HeaderTag tag, quint8 value);
+ void addTaggedInt8(QFontEngineQPF::HeaderTag tag, qint8 value);
+ void addTaggedUInt16(QFontEngineQPF::HeaderTag tag, quint16 value);
+ void addTaggedUInt32(QFontEngineQPF::HeaderTag tag, quint32 value);
+
+ static void dump(const QByteArray &qpf);
+ const uchar *dumpHeader(const uchar *data);
+ const uchar *dumpHeaderTag(const uchar *data);
+ void dumpGMapBlock(const quint32 *gmap, int glyphCount);
+ void dumpGlyphBlock(const quint32 *gmap, int glyphCount, const uchar *data, const uchar *endPtr);
+ void dumpGlyph(const uchar *data, const QFontEngineQPF::Glyph *glyph);
+
+ void addUInt16(quint16 value) { qToBigEndian(value, addBytes(sizeof(value))); }
+ void addUInt32(quint32 value) { qToBigEndian(value, addBytes(sizeof(value))); }
+ void addUInt8(quint8 value) { *addBytes(sizeof(value)) = value; }
+ void addInt8(qint8 value) { *addBytes(sizeof(value)) = quint8(value); }
+ void addByteArray(const QByteArray &string) {
+ uchar *data = addBytes(string.length());
+ qMemCopy(data, string.constData(), string.length());
+ }
+
+ void align4() { while (qpf.size() & 3) { addUInt8('\0'); } }
+
+ uchar *addBytes(int size) {
+ const int oldSize = qpf.size();
+ qpf.resize(qpf.size() + size);
+ return reinterpret_cast<uchar *>(qpf.data() + oldSize);
+ }
+
+ QByteArray qpf;
+ int options;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QPF::CharacterRange)
+
+#endif // QPF2_H
diff --git a/tools/pixeltool/Info_mac.plist b/tools/pixeltool/Info_mac.plist
new file mode 100644
index 0000000000..294db21b06
--- /dev/null
+++ b/tools/pixeltool/Info_mac.plist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.trolltech.pixeltool</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+</dict>
+</plist>
diff --git a/tools/pixeltool/main.cpp b/tools/pixeltool/main.cpp
new file mode 100644
index 0000000000..aa0c95c971
--- /dev/null
+++ b/tools/pixeltool/main.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpixeltool.h"
+
+#include <qapplication.h>
+#include <qfileinfo.h>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QPixelTool pt;
+
+ if (app.arguments().size() > 1 && QFileInfo(app.arguments().at(1)).exists()) {
+ pt.setPreviewImage(QImage(app.arguments().at(1)));
+ }
+
+ pt.show();
+
+ QObject::connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
+
+ int ret = app.exec();
+ return ret;
+}
diff --git a/tools/pixeltool/pixeltool.pro b/tools/pixeltool/pixeltool.pro
new file mode 100644
index 0000000000..c24e6edc75
--- /dev/null
+++ b/tools/pixeltool/pixeltool.pro
@@ -0,0 +1,25 @@
+TEMPLATE = app
+CONFIG += qt warn_on
+QT += network
+
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+DESTDIR = ../../bin
+
+DEPENDPATH += .
+INCLUDEPATH += .
+TARGET = pixeltool
+
+mac {
+ QMAKE_INFO_PLIST=Info_mac.plist
+}
+
+# Input
+SOURCES += main.cpp qpixeltool.cpp
+HEADERS += qpixeltool.h
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/tools/pixeltool/qpixeltool.cpp b/tools/pixeltool/qpixeltool.cpp
new file mode 100644
index 0000000000..6de7741940
--- /dev/null
+++ b/tools/pixeltool/qpixeltool.cpp
@@ -0,0 +1,536 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpixeltool.h"
+
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qpainter.h>
+#include <qevent.h>
+#include <qfiledialog.h>
+#include <qsettings.h>
+#include <qmenu.h>
+#include <qactiongroup.h>
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QPixelTool::QPixelTool(QWidget *parent)
+ : QWidget(parent)
+{
+ setWindowTitle(QLatin1String("PixelTool"));
+ QSettings settings(QLatin1String("Trolltech"), QLatin1String("QPixelTool"));
+
+ m_freeze = false;
+
+ m_autoUpdate = settings.value(QLatin1String("autoUpdate"), 0).toBool();
+
+ m_gridSize = settings.value(QLatin1String("gridSize"), 1).toInt();
+ m_gridActive = settings.value(QLatin1String("gridActive"), 1).toInt();
+ m_displayGridSize = false;
+ m_displayGridSizeId = 0;
+
+ m_zoom = settings.value(QLatin1String("zoom"), 4).toInt();
+
+ m_displayZoom = false;
+ m_displayZoomId = 0;
+
+ m_preview_mode = false;
+
+ m_currentColor = 0;
+
+ m_mouseDown = false;
+
+ m_initialSize = settings.value(QLatin1String("initialSize"), QSize(250, 200)).toSize();
+
+ move(settings.value(QLatin1String("position")).toPoint());
+
+ setMouseTracking(true);
+ setAttribute(Qt::WA_NoBackground);
+ m_updateId = startTimer(30);
+}
+
+QPixelTool::~QPixelTool()
+{
+ QSettings settings(QLatin1String("Trolltech"), QLatin1String("QPixelTool"));
+ settings.setValue(QLatin1String("autoUpdate"), int(m_autoUpdate));
+ settings.setValue(QLatin1String("gridSize"), m_gridSize);
+ settings.setValue(QLatin1String("gridActive"), m_gridActive);
+ settings.setValue(QLatin1String("zoom"), m_zoom);
+ settings.setValue(QLatin1String("initialSize"), size());
+ settings.setValue(QLatin1String("position"), pos());
+}
+
+void QPixelTool::setPreviewImage(const QImage &image)
+{
+ m_preview_mode = true;
+ m_preview_image = image;
+ m_freeze = true;
+}
+
+void QPixelTool::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_updateId && !m_freeze) {
+ grabScreen();
+ } else if (event->timerId() == m_displayZoomId) {
+ killTimer(m_displayZoomId);
+ setZoomVisible(false);
+ } else if (event->timerId() == m_displayGridSizeId) {
+ killTimer(m_displayGridSizeId);
+ m_displayGridSize = false;
+ }
+}
+
+void render_string(QPainter *p, int w, int h, const QString &text, int flags)
+{
+ p->setBrush(QColor(255, 255, 255, 191));
+ p->setPen(Qt::black);
+ QRect bounds;
+ p->drawText(0, 0, w, h, Qt::TextDontPrint | flags, text, &bounds);
+
+ if (bounds.x() == 0) bounds.adjust(0, 0, 10, 0);
+ else bounds.adjust(-10, 0, 0, 0);
+
+ if (bounds.y() == 0) bounds.adjust(0, 0, 0, 10);
+ else bounds.adjust(0, -10, 0, 0);
+
+ p->drawRect(bounds);
+ p->drawText(bounds, flags, text);
+}
+
+void QPixelTool::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+
+ if (m_preview_mode) {
+ QPixmap pixmap(40, 40);
+ QPainter pt(&pixmap);
+ pt.fillRect(0, 0, 20, 20, Qt::white);
+ pt.fillRect(20, 20, 20, 20, Qt::white);
+ pt.fillRect(20, 0, 20, 20, Qt::lightGray);
+ pt.fillRect(0, 20, 20, 20, Qt::lightGray);
+ pt.end();
+ p.fillRect(0, 0, width(), height(), pixmap);
+ }
+
+ int w = width();
+ int h = height();
+
+ p.save();
+ p.scale(m_zoom, m_zoom);
+ p.drawPixmap(0, 0, m_buffer);
+ p.scale(1/m_zoom, 1/m_zoom);
+ p.restore();
+
+ // Draw the grid on top.
+ if (m_gridActive) {
+ p.setPen(m_gridActive == 1 ? Qt::black : Qt::white);
+ int incr = m_gridSize * m_zoom;
+ for (int x=0; x<w; x+=incr)
+ p.drawLine(x, 0, x, h);
+ for (int y=0; y<h; y+=incr)
+ p.drawLine(0, y, w, y);
+ }
+
+ QFont f(QLatin1String("courier"));
+ f.setBold(true);
+ p.setFont(f);
+
+ if (m_displayZoom) {
+ render_string(&p, w, h,
+ QString(QLatin1String("Zoom: x%1")).arg(m_zoom),
+ Qt::AlignTop | Qt::AlignRight);
+ }
+
+ if (m_displayGridSize) {
+ render_string(&p, w, h,
+ QString(QLatin1String("Grid size: %1")).arg(m_gridSize),
+ Qt::AlignBottom | Qt::AlignLeft);
+ }
+
+ if (m_freeze) {
+ QString str;
+ str.sprintf("%8X (%3d,%3d,%3d,%3d)",
+ m_currentColor,
+ (0xff000000 & m_currentColor) >> 24,
+ (0x00ff0000 & m_currentColor) >> 16,
+ (0x0000ff00 & m_currentColor) >> 8,
+ (0x000000ff & m_currentColor));
+ render_string(&p, w, h,
+ str,
+ Qt::AlignBottom | Qt::AlignRight);
+ }
+
+ if (m_mouseDown && m_dragStart != m_dragCurrent) {
+ int x1 = (m_dragStart.x() / m_zoom) * m_zoom;
+ int y1 = (m_dragStart.y() / m_zoom) * m_zoom;
+ int x2 = (m_dragCurrent.x() / m_zoom) * m_zoom;
+ int y2 = (m_dragCurrent.y() / m_zoom) * m_zoom;
+ QRect r = QRect(x1, y1, x2 - x1, y2 - y1).normalized();
+ p.setBrush(Qt::NoBrush);
+ p.setPen(QPen(Qt::red, 3, Qt::SolidLine));
+ p.drawRect(r);
+ p.setPen(QPen(Qt::black, 1, Qt::SolidLine));
+ p.drawRect(r);
+
+ QString str;
+ str.sprintf("Rect: x=%d, y=%d, w=%d, h=%d",
+ r.x() / m_zoom,
+ r.y() / m_zoom,
+ r.width() / m_zoom,
+ r.height() / m_zoom);
+ render_string(&p, w, h, str, Qt::AlignBottom | Qt::AlignLeft);
+ }
+
+
+}
+
+void QPixelTool::keyPressEvent(QKeyEvent *e)
+{
+ switch (e->key()) {
+ case Qt::Key_Space:
+ toggleFreeze();
+ break;
+ case Qt::Key_Plus:
+ setZoom(m_zoom + 1);
+ break;
+ case Qt::Key_Minus:
+ setZoom(m_zoom - 1);
+ break;
+ case Qt::Key_PageUp:
+ setGridSize(m_gridSize + 1);
+ break;
+ case Qt::Key_PageDown:
+ setGridSize(m_gridSize - 1);
+ break;
+ case Qt::Key_G:
+ toggleGrid();
+ break;
+ case Qt::Key_A:
+ m_autoUpdate = !m_autoUpdate;
+ break;
+ case Qt::Key_C:
+ if (e->modifiers() & Qt::ControlModifier)
+ copyToClipboard();
+ break;
+ case Qt::Key_S:
+ if (e->modifiers() & Qt::ControlModifier) {
+ releaseKeyboard();
+ saveToFile();
+ }
+ break;
+ case Qt::Key_Control:
+ grabKeyboard();
+ break;
+ }
+}
+
+void QPixelTool::keyReleaseEvent(QKeyEvent *e)
+{
+ switch(e->key()) {
+ case Qt::Key_Control:
+ releaseKeyboard();
+ break;
+ default:
+ break;
+ }
+}
+
+void QPixelTool::resizeEvent(QResizeEvent *)
+{
+ grabScreen();
+}
+
+void QPixelTool::mouseMoveEvent(QMouseEvent *e)
+{
+ if (m_mouseDown)
+ m_dragCurrent = e->pos();
+
+ int x = e->x() / m_zoom;
+ int y = e->y() / m_zoom;
+
+ QImage im = m_buffer.toImage().convertToFormat(QImage::Format_ARGB32);
+ if (x < im.width() && y < im.height() && x >= 0 && y >= 0) {
+ m_currentColor = im.pixel(x, y);
+ update();
+ }
+}
+
+void QPixelTool::mousePressEvent(QMouseEvent *e)
+{
+ if (!m_freeze)
+ return;
+ m_mouseDown = true;
+ m_dragStart = e->pos();
+}
+
+void QPixelTool::mouseReleaseEvent(QMouseEvent *)
+{
+ m_mouseDown = false;
+}
+
+void QPixelTool::contextMenuEvent(QContextMenuEvent *e)
+{
+ bool tmpFreeze = m_freeze;
+ m_freeze = true;
+
+ QMenu menu;
+
+ QAction title(QLatin1String("Qt Pixel Zooming Tool"), &menu);
+ title.setEnabled(false);
+
+ // Grid color options...
+ QActionGroup gridGroup(this);
+ QAction whiteGrid(QLatin1String("White grid"), &gridGroup);
+ whiteGrid.setCheckable(true);
+ whiteGrid.setChecked(m_gridActive == 2);
+ whiteGrid.setShortcut(QKeySequence(Qt::Key_G));
+ QAction blackGrid(QLatin1String("Black grid"), &gridGroup);
+ blackGrid.setCheckable(true);
+ blackGrid.setChecked(m_gridActive == 1);
+ blackGrid.setShortcut(QKeySequence(Qt::Key_G));
+ QAction noGrid(QLatin1String("No grid"), &gridGroup);
+ noGrid.setCheckable(true);
+ noGrid.setChecked(m_gridActive == 0);
+ noGrid.setShortcut(QKeySequence(Qt::Key_G));
+
+ // Grid size options
+ QAction incrGrid(QLatin1String("Increase grid size"), &menu);
+ incrGrid.setShortcut(QKeySequence(Qt::Key_PageUp));
+ connect(&incrGrid, SIGNAL(triggered()), this, SLOT(increaseGridSize()));
+ QAction decrGrid(QLatin1String("Decrease grid size"), &menu);
+ decrGrid.setShortcut(QKeySequence(Qt::Key_PageDown));
+ connect(&decrGrid, SIGNAL(triggered()), this, SLOT(decreaseGridSize()));
+
+ // Zoom options
+ QAction incrZoom(QLatin1String("Zoom in"), &menu);
+ incrZoom.setShortcut(QKeySequence(Qt::Key_Plus));
+ connect(&incrZoom, SIGNAL(triggered()), this, SLOT(increaseZoom()));
+ QAction decrZoom(QLatin1String("Zoom out"), &menu);
+ decrZoom.setShortcut(QKeySequence(Qt::Key_Minus));
+ connect(&decrZoom, SIGNAL(triggered()), this, SLOT(decreaseZoom()));
+
+ // Freeze / Autoupdate
+ QAction freeze(QLatin1String("Frozen"), &menu);
+ freeze.setCheckable(true);
+ freeze.setChecked(tmpFreeze);
+ freeze.setShortcut(QKeySequence(Qt::Key_Space));
+ QAction autoUpdate(QLatin1String("Continous update"), &menu);
+ autoUpdate.setCheckable(true);
+ autoUpdate.setChecked(m_autoUpdate);
+ autoUpdate.setShortcut(QKeySequence(Qt::Key_A));
+
+ // Copy to clipboard / save
+ QAction save(QLatin1String("Save as image"), &menu);
+ save.setShortcut(QKeySequence(QLatin1String("Ctrl+S")));
+ connect(&save, SIGNAL(triggered()), this, SLOT(saveToFile()));
+ QAction copy(QLatin1String("Copy to clipboard"), &menu);
+ copy.setShortcut(QKeySequence(QLatin1String("Ctrl+C")));
+ connect(&copy, SIGNAL(triggered()), this, SLOT(copyToClipboard()));
+
+ menu.addAction(&title);
+ menu.addSeparator();
+ menu.addAction(&whiteGrid);
+ menu.addAction(&blackGrid);
+ menu.addAction(&noGrid);
+ menu.addSeparator();
+ menu.addAction(&incrGrid);
+ menu.addAction(&decrGrid);
+ menu.addSeparator();
+ menu.addAction(&incrZoom);
+ menu.addAction(&decrZoom);
+ menu.addSeparator();
+ menu.addAction(&freeze);
+ menu.addAction(&autoUpdate);
+ menu.addSeparator();
+ menu.addAction(&save);
+ menu.addAction(&copy);
+
+ menu.exec(mapToGlobal(e->pos()));
+
+ // Read out grid settings
+ if (noGrid.isChecked()) m_gridActive = 0;
+ else if (blackGrid.isChecked()) m_gridActive = 1;
+ else m_gridActive = 2;
+
+ m_autoUpdate = autoUpdate.isChecked();
+ tmpFreeze = freeze.isChecked();
+
+
+ m_freeze = tmpFreeze;
+}
+
+QSize QPixelTool::sizeHint() const
+{
+ return m_initialSize;
+}
+
+void QPixelTool::grabScreen()
+{
+ if (m_preview_mode) {
+ int w = qMin(width() / m_zoom + 1, m_preview_image.width());
+ int h = qMin(height() / m_zoom + 1, m_preview_image.height());
+ m_buffer = QPixmap::fromImage(m_preview_image).copy(0, 0, w, h);
+ update();
+ return;
+ }
+
+ QPoint mousePos = QCursor::pos();
+ if (mousePos == m_lastMousePos && !m_autoUpdate)
+ return;
+
+ int w = int(width() / float(m_zoom));
+ int h = int(height() / float(m_zoom));
+
+ if (width() % m_zoom > 0)
+ ++w;
+ if (height() % m_zoom > 0)
+ ++h;
+
+ int x = mousePos.x() - w/2;
+ int y = mousePos.y() - h/2;
+
+ m_buffer = QPixmap::grabWindow(qApp->desktop()->winId(), x, y, w, h);
+
+ QRegion geom(x, y, w, h);
+ QRect screenRect;
+ for (int i=0; i<qApp->desktop()->numScreens(); ++i)
+ screenRect |= qApp->desktop()->screenGeometry(i);
+ geom -= screenRect;
+ QVector<QRect> rects = geom.rects();
+ if (rects.size() > 0) {
+ QPainter p(&m_buffer);
+ p.translate(-x, -y);
+ p.setPen(Qt::NoPen);
+ p.setBrush(palette().color(QPalette::Dark));
+ p.drawRects(rects);
+ }
+
+ update();
+
+ m_lastMousePos = mousePos;
+}
+
+void QPixelTool::startZoomVisibleTimer()
+{
+ if (m_displayZoomId > 0) {
+ killTimer(m_displayZoomId);
+ }
+ m_displayZoomId = startTimer(5000);
+ setZoomVisible(true);
+}
+
+void QPixelTool::startGridSizeVisibleTimer()
+{
+ if (m_gridActive) {
+ if (m_displayGridSizeId > 0)
+ killTimer(m_displayGridSizeId);
+ m_displayGridSizeId = startTimer(5000);
+ m_displayGridSize = true;
+ update();
+ }
+}
+
+void QPixelTool::setZoomVisible(bool visible)
+{
+ m_displayZoom = visible;
+ update();
+}
+
+void QPixelTool::toggleFreeze()
+{
+ m_freeze = !m_freeze;
+ if (!m_freeze)
+ m_dragStart = m_dragCurrent = QPoint();
+}
+
+void QPixelTool::setZoom(int zoom)
+{
+ if (zoom > 0) {
+ QPoint pos = m_lastMousePos;
+ m_lastMousePos = QPoint();
+ m_zoom = zoom;
+ grabScreen();
+ m_lastMousePos = pos;
+ m_dragStart = m_dragCurrent = QPoint();
+ startZoomVisibleTimer();
+ }
+}
+
+void QPixelTool::toggleGrid()
+{
+ if (++m_gridActive > 2)
+ m_gridActive = 0;
+ update();
+}
+
+void QPixelTool::setGridSize(int gridSize)
+{
+ if (m_gridActive && gridSize > 0) {
+ m_gridSize = gridSize;
+ startGridSizeVisibleTimer();
+ update();
+ }
+}
+
+void QPixelTool::copyToClipboard()
+{
+ QClipboard *cb = QApplication::clipboard();
+ cb->setPixmap(m_buffer);
+}
+
+void QPixelTool::saveToFile()
+{
+ bool oldFreeze = m_freeze;
+ m_freeze = true;
+ QString name = QFileDialog::getSaveFileName(this, QLatin1String("Save as image"), QString(), QLatin1String("*.png"));
+ if (!name.isEmpty()) {
+ if (!name.endsWith(QLatin1String(".png")))
+ name.append(QLatin1String(".png"));
+ m_buffer.save(name, "PNG");
+ }
+ m_freeze = oldFreeze;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/pixeltool/qpixeltool.h b/tools/pixeltool/qpixeltool.h
new file mode 100644
index 0000000000..0c8520ac01
--- /dev/null
+++ b/tools/pixeltool/qpixeltool.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXELTOOL_H
+#define QPIXELTOOL_H
+
+#include <qwidget.h>
+#include <qpixmap.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPixelTool : public QWidget
+{
+ Q_OBJECT
+public:
+ QPixelTool(QWidget *parent = 0);
+ ~QPixelTool();
+
+ void timerEvent(QTimerEvent *event);
+ void paintEvent(QPaintEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void contextMenuEvent(QContextMenuEvent *event);
+
+ QSize sizeHint() const;
+
+ void setPreviewImage(const QImage &image);
+
+public slots:
+ void setZoom(int zoom);
+ void setGridSize(int gridSize);
+ void toggleGrid();
+ void toggleFreeze();
+ void setZoomVisible(bool visible);
+ void copyToClipboard();
+ void saveToFile();
+ void increaseGridSize() { setGridSize(m_gridSize + 1); }
+ void decreaseGridSize() { setGridSize(m_gridSize - 1); }
+ void increaseZoom() { setZoom(m_zoom + 1); }
+ void decreaseZoom() { setZoom(m_zoom - 1); }
+
+private:
+ void grabScreen();
+ void startZoomVisibleTimer();
+ void startGridSizeVisibleTimer();
+
+ bool m_freeze;
+ bool m_displayZoom;
+ bool m_displayGridSize;
+ bool m_mouseDown;
+ bool m_autoUpdate;
+ bool m_preview_mode;
+
+ int m_gridActive;
+ int m_zoom;
+ int m_gridSize;
+
+ int m_updateId;
+ int m_displayZoomId;
+ int m_displayGridSizeId;
+
+ int m_currentColor;
+
+ QPoint m_lastMousePos;
+ QPoint m_dragStart;
+ QPoint m_dragCurrent;
+ QPixmap m_buffer;
+
+ QSize m_initialSize;
+
+ QImage m_preview_image;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPIXELTOOL_H
diff --git a/tools/porting/porting.pro b/tools/porting/porting.pro
new file mode 100644
index 0000000000..65d926226c
--- /dev/null
+++ b/tools/porting/porting.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = src
diff --git a/tools/porting/src/ast.cpp b/tools/porting/src/ast.cpp
new file mode 100644
index 0000000000..9e8ce94c62
--- /dev/null
+++ b/tools/porting/src/ast.cpp
@@ -0,0 +1,1215 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ast.h"
+#include <QStringList>
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+int AST::N = 0;
+
+// ------------------------------------------------------------------------
+AST::AST(int startToken, int count)
+ : m_scope(0),
+ m_startToken(startToken),
+ m_endToken(startToken + count),
+ m_parent(0),
+ m_children(0)
+{
+ ++N;
+}
+
+void AST::setParent(AST *parent)
+{
+ if (m_parent)
+ m_parent->removeChild(this);
+
+ m_parent = parent;
+
+ if (m_parent)
+ m_parent->appendChild(this);
+}
+
+void AST::appendChild(AST *child)
+{
+ m_children = snoc(m_children, child, _pool);
+}
+
+void AST::removeChild(AST *child)
+{
+ fprintf(stderr, "AST::removeChild child: %p not implemented yet\n", child);
+}
+
+// ------------------------------------------------------------------------
+NameAST::NameAST()
+ : m_global(false), m_unqualifiedName(0), m_classOrNamespaceNameList(0)
+{
+}
+
+void NameAST::setGlobal(bool b)
+{
+ m_global = b;
+}
+
+void NameAST::setUnqualifiedName(ClassOrNamespaceNameAST *unqualifiedName)
+{
+ m_unqualifiedName = unqualifiedName;
+ if (m_unqualifiedName) m_unqualifiedName->setParent(this);
+}
+
+void NameAST::addClassOrNamespaceName(ClassOrNamespaceNameAST *classOrNamespaceName)
+{
+ if(!classOrNamespaceName)
+ return;
+
+ classOrNamespaceName->setParent(this);
+ m_classOrNamespaceNameList = snoc(m_classOrNamespaceNameList, classOrNamespaceName, _pool);
+}
+
+// ------------------------------------------------------------------------
+DeclarationAST::DeclarationAST()
+{
+}
+
+// ------------------------------------------------------------------------
+LinkageBodyAST::LinkageBodyAST()
+ : m_declarationList(0)
+{
+}
+
+void LinkageBodyAST::addDeclaration(DeclarationAST *ast)
+{
+ if(!ast)
+ return;
+
+ ast->setParent(this);
+ m_declarationList = snoc(m_declarationList, ast, _pool);
+}
+
+// ------------------------------------------------------------------------
+LinkageSpecificationAST::LinkageSpecificationAST()
+ : m_externType(0),
+ m_linkageBody(0),
+ m_declaration(0)
+{
+}
+
+void LinkageSpecificationAST::setExternType(AST *externType)
+{
+ m_externType = externType;
+ if (m_externType) m_externType->setParent(this);
+}
+
+void LinkageSpecificationAST::setLinkageBody(LinkageBodyAST *linkageBody)
+{
+ m_linkageBody = linkageBody;
+ if (m_linkageBody) m_linkageBody->setParent(this);
+}
+
+void LinkageSpecificationAST::setDeclaration(DeclarationAST *decl)
+{
+ m_declaration = decl;
+ if (m_declaration) m_declaration->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+TranslationUnitAST::TranslationUnitAST()
+ : m_declarationList(0)
+{
+ //kdDebug(9007) << "++ TranslationUnitAST::TranslationUnitAST()" << endl;
+}
+
+void TranslationUnitAST::addDeclaration(DeclarationAST *ast)
+{
+ if(!ast)
+ return;
+
+ ast->setParent(this);
+ m_declarationList = snoc(m_declarationList, ast, _pool);
+}
+
+// ------------------------------------------------------------------------
+NamespaceAST::NamespaceAST()
+ : m_namespaceName(0),
+ m_linkageBody(0)
+{
+}
+
+void NamespaceAST::setNamespaceName(AST *namespaceName)
+{
+ m_namespaceName = namespaceName;
+ if (m_namespaceName) m_namespaceName->setParent(this);
+}
+
+void NamespaceAST::setLinkageBody(LinkageBodyAST *linkageBody)
+{
+ m_linkageBody = linkageBody;
+ if (m_linkageBody) m_linkageBody->setParent(this);
+}
+
+
+// ------------------------------------------------------------------------
+NamespaceAliasAST::NamespaceAliasAST()
+ : m_namespaceName(0),
+ m_aliasName(0)
+{
+}
+
+void NamespaceAliasAST::setNamespaceName(AST *namespaceName)
+{
+ m_namespaceName = namespaceName;
+ if (m_namespaceName) m_namespaceName->setParent(this);
+}
+
+void NamespaceAliasAST::setAliasName(NameAST *name)
+{
+ m_aliasName = name;
+ if (m_aliasName) m_aliasName->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+UsingAST::UsingAST()
+ : m_typeName(0),
+ m_name(0)
+{
+}
+
+void UsingAST::setTypeName(AST *typeName)
+{
+ m_typeName = typeName;
+ if (m_typeName) m_typeName->setParent(this);
+}
+
+void UsingAST::setName(NameAST *name)
+{
+ m_name = name;
+ if (m_name) m_name->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+UsingDirectiveAST::UsingDirectiveAST()
+ : m_name(0)
+{
+}
+
+void UsingDirectiveAST::setName(NameAST *name)
+{
+ m_name = name;
+ if (m_name) m_name->setParent(this);
+}
+
+TypedefAST::TypedefAST()
+ : m_typeSpec(0),
+ m_initDeclaratorList(0)
+{
+}
+
+void TypeSpecifierAST::setName(NameAST *name)
+{
+ m_name = name;
+ if (m_name) m_name->setParent(this);
+}
+
+void TypedefAST::setTypeSpec(TypeSpecifierAST *typeSpec)
+{
+ m_typeSpec = typeSpec;
+ if (m_typeSpec) m_typeSpec->setParent(this);
+}
+
+void TypedefAST::setInitDeclaratorList(InitDeclaratorListAST *initDeclaratorList)
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if (m_initDeclaratorList) m_initDeclaratorList->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+TemplateArgumentListAST::TemplateArgumentListAST()
+ : m_argumentList(0)
+{
+}
+
+void TemplateArgumentListAST::addArgument(AST *arg)
+{
+ if(!arg)
+ return;
+
+ arg->setParent(this);
+ m_argumentList = snoc(m_argumentList, arg, _pool);
+}
+
+// ------------------------------------------------------------------------
+TemplateDeclarationAST::TemplateDeclarationAST()
+ : m_exported(0),
+ m_templateParameterList(0),
+ m_declaration(0)
+{
+}
+
+void TemplateDeclarationAST::setExported(AST *exported)
+{
+ m_exported = exported;
+ if (m_exported) m_exported->setParent(this);
+}
+
+void TemplateDeclarationAST::setTemplateParameterList(TemplateParameterListAST *templateParameterList)
+{
+ m_templateParameterList = templateParameterList;
+ if (m_templateParameterList) m_templateParameterList->setParent(this);
+}
+
+void TemplateDeclarationAST::setDeclaration(DeclarationAST *declaration)
+{
+ m_declaration = declaration;
+ if (m_declaration) m_declaration->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+ClassOrNamespaceNameAST::ClassOrNamespaceNameAST()
+ : m_name(0), m_templateArgumentList(0)
+{
+}
+
+void ClassOrNamespaceNameAST::setName(AST *name)
+{
+ m_name = name;
+ if (m_name) m_name->setParent(this);
+}
+
+void ClassOrNamespaceNameAST::setTemplateArgumentList(TemplateArgumentListAST *templateArgumentList)
+{
+ m_templateArgumentList = templateArgumentList;
+ if (m_templateArgumentList) m_templateArgumentList->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+TypeSpecifierAST::TypeSpecifierAST()
+ : m_name(0), m_cvQualify(0), m_cv2Qualify(0)
+
+{
+}
+
+void TypeSpecifierAST::setCvQualify(AST *cvQualify)
+{
+ m_cvQualify = cvQualify;
+ if (m_cvQualify) m_cvQualify->setParent(this);
+}
+
+void TypeSpecifierAST::setCv2Qualify(AST *cv2Qualify)
+{
+ m_cv2Qualify = cv2Qualify;
+ if (m_cv2Qualify) m_cv2Qualify->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+ClassSpecifierAST::ClassSpecifierAST()
+ : m_winDeclSpec(0),
+ m_classKey(0),
+ m_baseClause(0),
+ m_declarationList(0)
+{
+}
+
+void ClassSpecifierAST::setClassKey(AST *classKey)
+{
+ m_classKey = classKey;
+ if (m_classKey) m_classKey->setParent(this);
+}
+
+void ClassSpecifierAST::addDeclaration(DeclarationAST *declaration)
+{
+ if(!declaration)
+ return;
+
+ declaration->setParent(this);
+ m_declarationList = snoc(m_declarationList, declaration, _pool);
+}
+
+void ClassSpecifierAST::setBaseClause(BaseClauseAST *baseClause)
+{
+ m_baseClause = baseClause;
+ if (m_baseClause) m_baseClause->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+EnumSpecifierAST::EnumSpecifierAST()
+ : m_enumeratorList(0)
+{
+}
+
+void EnumSpecifierAST::addEnumerator(EnumeratorAST *enumerator)
+{
+ if(!enumerator)
+ return;
+
+ enumerator->setParent(this);
+ m_enumeratorList = snoc(m_enumeratorList, enumerator, _pool);
+}
+
+
+// ------------------------------------------------------------------------
+ElaboratedTypeSpecifierAST::ElaboratedTypeSpecifierAST()
+ : m_kind(0)
+{
+}
+
+void ElaboratedTypeSpecifierAST::setKind(AST *kind)
+{
+ m_kind = kind;
+ if (m_kind) m_kind->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+EnumeratorAST::EnumeratorAST()
+ : m_id(0),
+ m_expression(0)
+{
+}
+
+void EnumeratorAST::setId(AST *id)
+{
+ m_id = id;
+ if (m_id) m_id->setParent(this);
+}
+
+void EnumeratorAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression) m_expression->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+BaseClauseAST::BaseClauseAST()
+ : m_baseSpecifierList(0)
+{
+}
+
+void BaseClauseAST::addBaseSpecifier(BaseSpecifierAST *baseSpecifier)
+{
+ if(!baseSpecifier)
+ return;
+
+ baseSpecifier->setParent(this);
+ m_baseSpecifierList = snoc(m_baseSpecifierList, baseSpecifier, _pool);
+}
+
+// ------------------------------------------------------------------------
+BaseSpecifierAST::BaseSpecifierAST()
+ : m_isVirtual(0), m_access(0), m_name(0)
+
+{
+}
+
+void BaseSpecifierAST::setIsVirtual(AST *isVirtual)
+{
+ m_isVirtual = isVirtual;
+ if (m_isVirtual) m_isVirtual->setParent(this);
+}
+
+void BaseSpecifierAST::setAccess(AST *access)
+{
+ m_access = access;
+ if (m_access) m_access->setParent(this);
+}
+
+void BaseSpecifierAST::setName(NameAST *name)
+{
+ m_name = name;
+ if (m_name) m_name->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+SimpleDeclarationAST::SimpleDeclarationAST()
+ : m_functionSpecifier(0),
+ m_storageSpecifier(0),
+ m_typeSpec(0),
+ m_initDeclaratorList(0),
+ m_winDeclSpec(0)
+{
+}
+
+void SimpleDeclarationAST::setFunctionSpecifier(AST *functionSpecifier)
+{
+ m_functionSpecifier = functionSpecifier;
+ if (m_functionSpecifier) m_functionSpecifier->setParent(this);
+}
+
+void SimpleDeclarationAST::setStorageSpecifier(AST *storageSpecifier)
+{
+ m_storageSpecifier = storageSpecifier;
+ if (m_storageSpecifier) m_storageSpecifier->setParent(this);
+}
+
+void SimpleDeclarationAST::setTypeSpec(TypeSpecifierAST *typeSpec)
+{
+ m_typeSpec = typeSpec;
+ if (m_typeSpec) m_typeSpec->setParent(this);
+}
+
+void SimpleDeclarationAST::setInitDeclaratorList(InitDeclaratorListAST *initDeclaratorList)
+{
+ m_initDeclaratorList = initDeclaratorList;
+ if (m_initDeclaratorList) m_initDeclaratorList->setParent(this);
+}
+
+void SimpleDeclarationAST::setWinDeclSpec(AST *winDeclSpec)
+{
+ m_winDeclSpec = winDeclSpec;
+ if (m_winDeclSpec) m_winDeclSpec->setParent(this);
+}
+
+// ------------------------------------------------------------------------
+InitDeclaratorListAST::InitDeclaratorListAST()
+ : m_initDeclaratorList(0)
+{
+}
+
+void InitDeclaratorListAST::addInitDeclarator(InitDeclaratorAST *decl)
+{
+ if(!decl)
+ return;
+
+ decl->setParent(this);
+ m_initDeclaratorList = snoc(m_initDeclaratorList, decl, _pool);
+}
+
+// ------------------------------------------------------------------------
+DeclaratorAST::DeclaratorAST()
+ : m_ptrOpList(0),
+ m_subDeclarator(0),
+ m_declaratorId(0),
+ m_bitfieldInitialization(0),
+ m_arrayDimensionList(0),
+ m_parameterDeclarationClause(0),
+ m_constant(0),
+ m_exceptionSpecification(0)
+{
+}
+
+void DeclaratorAST::setSubDeclarator(DeclaratorAST *subDeclarator)
+{
+ m_subDeclarator = subDeclarator;
+ if (m_subDeclarator) m_subDeclarator->setParent(this);
+}
+
+void DeclaratorAST::setDeclaratorId(NameAST *declaratorId)
+{
+ m_declaratorId = declaratorId;
+ if (m_declaratorId) m_declaratorId->setParent(this);
+}
+
+void DeclaratorAST::setBitfieldInitialization(AST *bitfieldInitialization)
+{
+ m_bitfieldInitialization = bitfieldInitialization;
+ if (m_bitfieldInitialization) m_bitfieldInitialization->setParent(this);
+}
+
+void DeclaratorAST::addArrayDimension(AST *arrayDimension)
+{
+ if(!arrayDimension)
+ return;
+
+ arrayDimension->setParent(this);
+ m_arrayDimensionList = snoc(m_arrayDimensionList, arrayDimension, _pool);
+}
+
+void DeclaratorAST::setParameterDeclarationClause(ParameterDeclarationClauseAST *parameterDeclarationClause)
+{
+ m_parameterDeclarationClause = parameterDeclarationClause;
+ if (m_parameterDeclarationClause) m_parameterDeclarationClause->setParent(this);
+}
+
+void DeclaratorAST::setConstant(AST *constant)
+{
+ m_constant = constant;
+ if (m_constant) m_constant->setParent(this);
+}
+
+void DeclaratorAST::setExceptionSpecification(AST *exceptionSpecification)
+{
+ m_exceptionSpecification = exceptionSpecification;
+ if (m_exceptionSpecification) m_exceptionSpecification->setParent(this);
+}
+
+void DeclaratorAST::addPtrOp(AST *ptrOp)
+{
+ if(!ptrOp)
+ return;
+
+ ptrOp->setParent(this);
+ m_ptrOpList = snoc(m_ptrOpList, ptrOp, _pool);
+}
+
+// --------------------------------------------------------------------------
+InitDeclaratorAST::InitDeclaratorAST()
+ : m_declarator(0),
+ m_initializer(0)
+{
+}
+
+void InitDeclaratorAST::setDeclarator(DeclaratorAST *declarator)
+{
+ m_declarator = declarator;
+ if (m_declarator) m_declarator->setParent(this);
+}
+
+void InitDeclaratorAST::setInitializer(AST *initializer)
+{
+ m_initializer = initializer;
+ if (m_initializer) m_initializer->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+FunctionDefinitionAST::FunctionDefinitionAST()
+ : m_functionSpecifier(0),
+ m_storageSpecifier(0),
+ m_typeSpec(0),
+ m_initDeclarator(0),
+ m_functionBody(0),
+ m_winDeclSpec(0)
+{
+}
+
+void FunctionDefinitionAST::setFunctionSpecifier(AST *functionSpecifier)
+{
+ m_functionSpecifier = functionSpecifier;
+ if (m_functionSpecifier) m_functionSpecifier->setParent(this);
+}
+
+void FunctionDefinitionAST::setStorageSpecifier(AST *storageSpecifier)
+{
+ m_storageSpecifier = storageSpecifier;
+ if (m_storageSpecifier) m_storageSpecifier->setParent(this);
+}
+
+void FunctionDefinitionAST::setTypeSpec(TypeSpecifierAST *typeSpec)
+{
+ m_typeSpec = typeSpec;
+ if (m_typeSpec) m_typeSpec->setParent(this);
+}
+
+void FunctionDefinitionAST::setInitDeclarator(InitDeclaratorAST *initDeclarator)
+{
+ m_initDeclarator = initDeclarator;
+ if (m_initDeclarator) m_initDeclarator->setParent(this);
+}
+
+void FunctionDefinitionAST::setFunctionBody(StatementListAST *functionBody)
+{
+ m_functionBody = functionBody;
+ if (m_functionBody) m_functionBody->setParent(this);
+}
+
+void FunctionDefinitionAST::setWinDeclSpec(AST *winDeclSpec)
+{
+ m_winDeclSpec = winDeclSpec;
+ if (m_winDeclSpec) m_winDeclSpec->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+StatementListAST::StatementListAST()
+ : m_statementList(0)
+{
+}
+
+void StatementListAST::addStatement(StatementAST *statement)
+{
+ if(!statement)
+ return;
+
+ statement->setParent(this);
+ m_statementList = snoc(m_statementList, statement, _pool);
+}
+
+// --------------------------------------------------------------------------
+IfStatementAST::IfStatementAST()
+ : m_condition(0),
+ m_statement(0),
+ m_elseStatement(0)
+{
+}
+
+void IfStatementAST::setCondition(ConditionAST *condition)
+{
+ m_condition = condition;
+ if (m_condition) m_condition->setParent(this);
+}
+
+void IfStatementAST::setStatement(StatementAST *statement)
+{
+ m_statement = statement;
+ if (m_statement) m_statement->setParent(this);
+}
+
+void IfStatementAST::setElseStatement(StatementAST *elseStatement)
+{
+ m_elseStatement = elseStatement;
+ if (m_elseStatement) m_elseStatement->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+WhileStatementAST::WhileStatementAST()
+ : m_condition(0),
+ m_statement(0)
+{
+}
+
+void WhileStatementAST::setCondition(ConditionAST *condition)
+{
+ m_condition = condition;
+ if (m_condition) m_condition->setParent(this);
+}
+
+void WhileStatementAST::setStatement(StatementAST *statement)
+{
+ m_statement = statement;
+ if (m_statement) m_statement->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+DoStatementAST::DoStatementAST()
+ : m_condition(0),
+ m_statement(0)
+{
+}
+
+void DoStatementAST::setCondition(ConditionAST *condition)
+{
+ m_condition = condition;
+ if (m_condition) m_condition->setParent(this);
+}
+
+void DoStatementAST::setStatement(StatementAST *statement)
+{
+ m_statement = statement;
+ if (m_statement) m_statement->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+ForStatementAST::ForStatementAST()
+ : m_condition(0),
+ m_initStatement(0),
+ m_statement(0),
+ m_expression(0)
+{
+}
+
+void ForStatementAST::setCondition(ConditionAST *condition)
+{
+ m_condition = condition;
+ if (m_condition) m_condition->setParent(this);
+}
+
+void ForStatementAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression) m_expression->setParent(this);
+}
+
+void ForStatementAST::setStatement(StatementAST *statement)
+{
+ m_statement = statement;
+ if (m_statement) m_statement->setParent(this);
+}
+
+void ForStatementAST::setInitStatement(StatementAST *initStatement)
+{
+ m_initStatement = initStatement;
+ if (m_initStatement) m_initStatement->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+SwitchStatementAST::SwitchStatementAST()
+ : m_condition(0),
+ m_statement(0)
+{
+}
+
+void SwitchStatementAST::setCondition(ConditionAST *condition)
+{
+ m_condition = condition;
+ if (m_condition) m_condition->setParent(this);
+}
+
+void SwitchStatementAST::setStatement(StatementAST *statement)
+{
+ m_statement = statement;
+ if (m_statement) m_statement->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+DeclarationStatementAST::DeclarationStatementAST()
+ : m_declaration(0)
+{
+}
+
+void DeclarationStatementAST::setDeclaration(DeclarationAST *declaration)
+{
+ m_declaration = declaration;
+ if (m_declaration) m_declaration->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+LabeledStatementAST::LabeledStatementAST()
+ : m_statement(0), m_expression(0)
+{
+}
+
+void LabeledStatementAST::setStatement(StatementAST *statement)
+{
+ m_statement = statement;
+ if (m_statement) m_statement->setParent(this);
+}
+
+void LabeledStatementAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression) m_expression->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+ExpressionStatementAST::ExpressionStatementAST()
+ : m_expression(0)
+{
+}
+
+void ExpressionStatementAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression) m_expression->setParent(this);
+}
+
+
+// --------------------------------------------------------------------------
+ParameterDeclarationAST::ParameterDeclarationAST()
+ : m_typeSpec(0),
+ m_declarator(0),
+ m_expression(0)
+{
+}
+
+void ParameterDeclarationAST::setTypeSpec(TypeSpecifierAST *typeSpec)
+{
+ m_typeSpec = typeSpec;
+ if (m_typeSpec) m_typeSpec->setParent(this);
+}
+
+void ParameterDeclarationAST::setDeclarator(DeclaratorAST *declarator)
+{
+ m_declarator = declarator;
+ if (m_declarator) m_declarator->setParent(this);
+}
+
+void ParameterDeclarationAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression) m_expression->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+ParameterDeclarationListAST::ParameterDeclarationListAST()
+ : m_parameterList(0)
+{
+}
+
+void ParameterDeclarationListAST::addParameter(ParameterDeclarationAST *parameter)
+{
+ if(!parameter)
+ return;
+
+ parameter->setParent(this);
+ m_parameterList = snoc(m_parameterList, parameter, _pool);
+}
+
+// --------------------------------------------------------------------------
+ParameterDeclarationClauseAST::ParameterDeclarationClauseAST()
+ : m_parameterDeclarationList(0),
+ m_ellipsis(0)
+{
+}
+
+void ParameterDeclarationClauseAST::setParameterDeclarationList(ParameterDeclarationListAST *parameterDeclarationList)
+{
+ m_parameterDeclarationList = parameterDeclarationList;
+ if (m_parameterDeclarationList) m_parameterDeclarationList->setParent(this);
+}
+
+void ParameterDeclarationClauseAST::setEllipsis(AST *ellipsis)
+{
+ m_ellipsis = ellipsis;
+ if (m_ellipsis) m_ellipsis->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+AccessDeclarationAST::AccessDeclarationAST()
+ : m_accessList(0)
+{
+}
+
+void AccessDeclarationAST::addAccess(AST *access)
+{
+ if(!access)
+ return;
+
+ access->setParent(this);
+ m_accessList = snoc(m_accessList, access, _pool);
+}
+
+// --------------------------------------------------------------------------
+TypeParameterAST::TypeParameterAST()
+ : m_kind(0), m_templateParameterList(0),
+ m_name(0), m_typeId(0)
+
+{
+}
+
+void TypeParameterAST::setKind(AST *kind)
+{
+ m_kind = kind;
+}
+
+void TypeParameterAST::setTemplateParameterList(TemplateParameterListAST *templateParameterList)
+{
+ m_templateParameterList = templateParameterList;
+ if (m_templateParameterList) m_templateParameterList->setParent(this);
+}
+
+void TypeParameterAST::setName(NameAST *name)
+{
+ m_name = name;
+ if (m_name) m_name->setParent(this);
+}
+
+void TypeParameterAST::setTypeId(AST *typeId)
+{
+ m_typeId = typeId;
+ if (m_typeId) m_typeId->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterAST::TemplateParameterAST()
+ : m_typeParameter(0),
+ m_typeValueParameter(0)
+{
+}
+
+void TemplateParameterAST::setTypeParameter(TypeParameterAST *typeParameter)
+{
+ m_typeParameter = typeParameter;
+ if (m_typeParameter) m_typeParameter->setParent(this);
+}
+
+void TemplateParameterAST::setTypeValueParameter(ParameterDeclarationAST *typeValueParameter)
+{
+ m_typeValueParameter = typeValueParameter;
+ if (m_typeValueParameter) m_typeValueParameter->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+TemplateParameterListAST::TemplateParameterListAST()
+ : m_templateParameterList(0)
+{
+}
+
+void TemplateParameterListAST::addTemplateParameter(TemplateParameterAST *templateParameter)
+{
+ if(!templateParameter)
+ return;
+
+ templateParameter->setParent(this);
+ m_templateParameterList = snoc(m_templateParameterList, templateParameter, _pool);
+}
+
+// --------------------------------------------------------------------------
+ConditionAST::ConditionAST()
+ : m_typeSpec(0),
+ m_declarator(0),
+ m_expression(0)
+{
+}
+
+void ConditionAST::setTypeSpec(TypeSpecifierAST *typeSpec)
+{
+ m_typeSpec = typeSpec;
+ if (m_typeSpec) m_typeSpec->setParent(this);
+}
+
+void ConditionAST::setDeclarator(DeclaratorAST *declarator)
+{
+ m_declarator = declarator;
+ if (m_declarator) m_declarator->setParent(this);
+}
+
+void ConditionAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression) m_expression->setParent(this);
+}
+
+void ClassSpecifierAST::setWinDeclSpec(AST *winDeclSpec)
+{
+ m_winDeclSpec = winDeclSpec;
+ if (m_winDeclSpec) m_winDeclSpec->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+ReturnStatementAST::ReturnStatementAST()
+ : m_expression(0)
+{
+}
+
+void ReturnStatementAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression) m_expression->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+BinaryExpressionAST::BinaryExpressionAST()
+ : m_op(0), m_left(0), m_right(0)
+{
+}
+
+void BinaryExpressionAST::setOp(AST *op)
+{
+ m_op = op;
+ if (m_op)
+ m_op->setParent(this);
+}
+
+void BinaryExpressionAST::setLeftExpression(AbstractExpressionAST *left)
+{
+ m_left = left;
+ if (m_left)
+ m_left->setParent(this);
+}
+
+void BinaryExpressionAST::setRightExpression(AbstractExpressionAST *right)
+{
+ m_right = right;
+ if (m_right)
+ m_right->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+ConditionalExpressionAST::ConditionalExpressionAST()
+ : m_condition(0), m_left(0), m_right(0)
+{
+}
+
+void ConditionalExpressionAST::setCondition(AbstractExpressionAST *condition)
+{
+ m_condition = condition;
+ if (m_condition)
+ m_condition->setParent(this);
+}
+
+void ConditionalExpressionAST::setLeftExpression(AbstractExpressionAST *left)
+{
+ m_left = left;
+ if (m_left)
+ m_left->setParent(this);
+}
+
+void ConditionalExpressionAST::setRightExpression(AbstractExpressionAST *right)
+{
+ m_right = right;
+ if (m_right)
+ m_right->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+CppCastExpressionAST::CppCastExpressionAST()
+ : m_castOp(0), m_typeId(0), m_expression(0)
+{
+}
+
+void CppCastExpressionAST::setCastOp(AST *castOp)
+{
+ m_castOp = castOp;
+ if (m_castOp)
+ m_castOp->setParent(this);
+}
+
+void CppCastExpressionAST::setTypeId(AST *typeId)
+{
+ m_typeId = typeId;
+ if (m_typeId)
+ m_typeId->setParent(this);
+}
+
+void CppCastExpressionAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression)
+ m_expression->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+SubscriptingAST::SubscriptingAST()
+ : m_expression(0), m_subscript(0)
+{
+}
+
+void SubscriptingAST::setSubscript(AbstractExpressionAST *subscript)
+{
+ m_subscript = subscript;
+ if (m_subscript)
+ m_subscript->setParent(this);
+}
+
+void SubscriptingAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression)
+ m_expression->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+FunctionCallAST::FunctionCallAST()
+ : m_expression(0), m_arguments(0)
+{
+}
+
+void FunctionCallAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression)
+ m_expression->setParent(this);
+}
+
+void FunctionCallAST::setArguments(AbstractExpressionAST *arguments)
+{
+ m_arguments = arguments;
+ if (m_arguments)
+ m_arguments->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+ExplicitTypeConversionAST::ExplicitTypeConversionAST()
+{
+}
+
+// --------------------------------------------------------------------------
+PseudoDestructorCallAST::PseudoDestructorCallAST()
+{
+}
+
+// --------------------------------------------------------------------------
+ClassMemberAccessAST::ClassMemberAccessAST()
+ : m_op(0), m_expression(0), m_templ(0), m_name(0)
+{
+}
+
+void ClassMemberAccessAST::setOp(AST *op)
+{
+ m_op = op;
+ if (m_op)
+ m_op->setParent(this);
+}
+
+void ClassMemberAccessAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression)
+ m_expression->setParent(this);
+}
+
+void ClassMemberAccessAST::setName(NameAST *name)
+{
+ m_name = name;
+ if (m_name)
+ m_name->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+IncrDecrAST::IncrDecrAST()
+ : m_op(0), m_expression(0)
+{
+}
+
+void IncrDecrAST::setOp(AST *op)
+{
+ m_op = op;
+ if (m_op)
+ m_op->setParent(this);
+}
+
+void IncrDecrAST::setExpression(AbstractExpressionAST *expression)
+{
+ m_expression = expression;
+ if (m_expression)
+ m_expression->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+TypeIdentificationAST::TypeIdentificationAST()
+{
+}
+
+// --------------------------------------------------------------------------
+TypeIdAST::TypeIdAST()
+ : m_typeSpecifier(0), m_declarator(0)
+{
+}
+
+void TypeIdAST::setTypeSpecifier(TypeSpecifierAST *typeSpecifier)
+{
+ m_typeSpecifier = typeSpecifier;
+ if (m_typeSpecifier)
+ m_typeSpecifier->setParent(this);
+}
+
+void TypeIdAST::setDeclarator(DeclaratorAST *declarator)
+{
+ m_declarator = declarator;
+ if (m_declarator)
+ m_declarator->setParent(this);
+}
+
+// --------------------------------------------------------------------------
+AbstractExpressionAST::AbstractExpressionAST()
+{
+ m_symbol = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/ast.h b/tools/porting/src/ast.h
new file mode 100644
index 0000000000..7daa6805c6
--- /dev/null
+++ b/tools/porting/src/ast.h
@@ -0,0 +1,1598 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef AST_H
+#define AST_H
+
+#include "smallobject.h"
+#include "list.h"
+
+QT_BEGIN_NAMESPACE
+
+class AST;
+class NameAST;
+class TypeIdAST;
+class TypeSpecifierAST;
+class DeclaratorAST;
+
+class Symbol;
+class Scope;
+
+enum NodeType
+{
+ NodeType_Generic = 0,
+
+ NodeType_TemplateArgumentList = 1000,
+ NodeType_ClassOrNamespaceName,
+ NodeType_Name,
+ NodeType_Declaration,
+ NodeType_TypeSpecifier,
+ NodeType_BaseSpecifier,
+ NodeType_BaseClause,
+ NodeType_ClassSpecifier,
+ NodeType_Enumerator,
+ NodeType_EnumSpecifier,
+ NodeType_ElaboratedTypeSpecifier,
+ NodeType_LinkageBody,
+ NodeType_LinkageSpecification,
+ NodeType_Namespace,
+ NodeType_NamespaceAlias,
+ NodeType_Using,
+ NodeType_UsingDirective,
+ NodeType_InitDeclaratorList,
+ NodeType_Typedef,
+ NodeType_Declarator,
+ NodeType_InitDeclarator,
+ NodeType_TemplateDeclaration,
+ NodeType_SimpleDeclaration,
+ NodeType_Statement,
+ NodeType_StatementList,
+ NodeType_IfStatement,
+ NodeType_WhileStatement,
+ NodeType_DoStatement,
+ NodeType_ForStatement,
+ NodeType_SwitchStatement,
+ NodeType_DeclarationStatement,
+ NodeType_LabeledStatement,
+ NodeType_ReturnStatement,
+ NodeType_TranslationUnit,
+ NodeType_FunctionDefinition,
+ NodeType_ExpressionStatement,
+ NodeType_ParameterDeclaration,
+ NodeType_ParameterDeclarationList,
+ NodeType_ParameterDeclarationClause,
+ NodeType_AccessDeclaration,
+ NodeType_TypeParameter,
+ NodeType_TemplateParameter,
+ NodeType_TemplateParameterList,
+ NodeType_Condition,
+
+ NodeType_TypeId,
+
+ NodeType_Expression = 2000,
+ NodeType_BinaryExpression,
+ NodeType_PrimaryExpression,
+
+//
+// postfix expression
+//
+ NodeType_PostfixExpression,
+ NodeType_Subscripting,
+ NodeType_FunctionCall,
+ NodeType_ExplicitTypeConversion,
+ NodeType_PseudoConstructorCall,
+ NodeType_ClassMemberAccess,
+ NodeType_IncrDecr,
+ NodeType_CppCastExpression,
+ NodeType_TypeIdentification,
+
+ NodeType_UnaryExpression,
+ NodeType_NewExpression,
+ NodeType_NewTypeId,
+ NodeType_NewDeclarator,
+ NodeType_NewInitializer,
+ NodeType_DeleteExpression,
+ NodeType_CastExpression,
+ NodeType_ConditionalExpression,
+ NodeType_ThrowExpression,
+
+ NodeType_Custom = 3000
+};
+
+
+template <typename T>
+inline int length(List<T> *e)
+{
+ return e ? e->size() : 0;
+}
+
+class AST
+{
+public:
+ enum { Type=NodeType_Generic };
+
+ pool *_pool;
+
+ static int N;
+
+public:
+ AST(int startToken=0, int count=1);
+ virtual ~AST() { --N; }
+
+ inline int startToken() const
+ { return m_startToken; }
+
+ inline int endToken() const
+ { return m_endToken; }
+
+ inline void setPosition(int startToken, int endToken)
+ {
+ m_startToken = startToken;
+ m_endToken = endToken;
+ }
+
+ inline int nodeType() const
+ { return m_nodeType; }
+
+ inline void setNodeType(int nodeType)
+ { m_nodeType = nodeType; }
+
+ inline AST *parent() const
+ { return m_parent; }
+
+ void setParent(AST *parent);
+
+ inline List<AST *> *children() const
+ { return m_children; }
+
+ void appendChild(AST *child);
+ void removeChild(AST *child);
+
+// ### move
+ inline Scope *scope() const
+ {
+ if (m_scope)
+ return m_scope;
+
+ return m_parent ? m_parent->scope() : 0;
+ }
+
+ inline void setScope(Scope *scope)
+ { m_scope = scope; }
+
+private:
+ Scope *m_scope;
+ int m_nodeType;
+ int m_startToken;
+ int m_endToken;
+ AST *m_parent;
+ List<AST *> *m_children;
+
+private:
+ AST(const AST &source);
+ void operator = (const AST &source);
+};
+
+class AbstractExpressionAST: public AST
+{
+public:
+ enum { Type = NodeType_Expression };
+
+ AbstractExpressionAST();
+
+ inline Symbol *symbol() const
+ { return m_symbol; }
+
+ inline void setSymbol(Symbol *symbol)
+ { m_symbol = symbol; }
+
+private:
+ Symbol *m_symbol;
+};
+
+// ### remove me
+template <int kind, class Base = AbstractExpressionAST>
+class ExpressionAST: public Base
+{
+public:
+ enum { Type = kind };
+
+public:
+ inline ExpressionAST() {}
+
+private:
+ ExpressionAST(const ExpressionAST &source);
+ void operator = (const ExpressionAST &source);
+};
+
+class BinaryExpressionAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_BinaryExpression };
+
+public:
+ BinaryExpressionAST();
+
+ inline AST *op() const
+ { return m_op; }
+
+ inline AbstractExpressionAST *leftExpression() const
+ { return m_left; }
+
+ inline AbstractExpressionAST *rightExpression() const
+ { return m_right; }
+
+ void setOp(AST *op);
+ void setLeftExpression(AbstractExpressionAST *left);
+ void setRightExpression(AbstractExpressionAST *right);
+
+private:
+ AST *m_op;
+ AbstractExpressionAST *m_left;
+ AbstractExpressionAST *m_right;
+
+private:
+ BinaryExpressionAST(const BinaryExpressionAST &source);
+ void operator = (const BinaryExpressionAST &source);
+};
+
+class ConditionalExpressionAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_ConditionalExpression };
+
+public:
+ ConditionalExpressionAST();
+
+ inline AbstractExpressionAST *condition() const
+ { return m_condition; }
+
+ inline AbstractExpressionAST *leftExpression() const
+ { return m_left; }
+
+ inline AbstractExpressionAST *rightExpression() const
+ { return m_right; }
+
+ void setCondition(AbstractExpressionAST *condition);
+ void setLeftExpression(AbstractExpressionAST *left);
+ void setRightExpression(AbstractExpressionAST *right);
+
+private:
+ AbstractExpressionAST *m_condition;
+ AbstractExpressionAST *m_left;
+ AbstractExpressionAST *m_right;
+
+private:
+ ConditionalExpressionAST(const ConditionalExpressionAST& source);
+ void operator = (const ConditionalExpressionAST &source);
+};
+
+
+//
+// postfix expression
+//
+
+class SubscriptingAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_Subscripting };
+
+public:
+ SubscriptingAST();
+
+ inline AbstractExpressionAST *expression() const
+ { return m_expression; }
+
+ inline AbstractExpressionAST *subscript() const
+ { return m_subscript; }
+
+ void setExpression(AbstractExpressionAST *expression);
+ void setSubscript(AbstractExpressionAST *subscript);
+
+private:
+ AbstractExpressionAST *m_expression;
+ AbstractExpressionAST *m_subscript;
+
+private:
+ SubscriptingAST(const SubscriptingAST &source);
+ void operator = (const SubscriptingAST &source);
+};
+
+class FunctionCallAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_FunctionCall };
+
+public:
+ FunctionCallAST();
+
+ inline AbstractExpressionAST *expression() const
+ { return m_expression; }
+
+ inline AbstractExpressionAST *arguments() const
+ { return m_arguments; }
+
+ void setExpression(AbstractExpressionAST *expression);
+ void setArguments(AbstractExpressionAST *arguments);
+
+private:
+ AbstractExpressionAST *m_expression;
+ AbstractExpressionAST *m_arguments;
+
+private:
+ FunctionCallAST(const FunctionCallAST &source);
+ void operator = (const FunctionCallAST &source);
+};
+
+class ExplicitTypeConversionAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_ExplicitTypeConversion };
+
+public:
+ ExplicitTypeConversionAST();
+
+private:
+ ExplicitTypeConversionAST(const ExplicitTypeConversionAST &source);
+ void operator = (const ExplicitTypeConversionAST &source);
+};
+
+class PseudoDestructorCallAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_PseudoConstructorCall };
+
+public:
+ PseudoDestructorCallAST();
+
+private:
+ PseudoDestructorCallAST(const PseudoDestructorCallAST &source);
+ void operator = (const PseudoDestructorCallAST &source);
+};
+
+class ClassMemberAccessAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_ClassMemberAccess };
+
+public:
+ ClassMemberAccessAST();
+
+ inline AST *op() const
+ { return m_op; }
+
+ inline AbstractExpressionAST *expression() const
+ { return m_expression; }
+
+ inline NameAST *name() const
+ { return m_name; }
+
+ void setOp(AST *op);
+ void setExpression(AbstractExpressionAST *expression);
+ void setName(NameAST *name);
+
+private:
+ AST *m_op;
+ AbstractExpressionAST *m_expression;
+ AST *m_templ;
+ NameAST *m_name;
+
+private:
+ ClassMemberAccessAST(const ClassMemberAccessAST &source);
+ void operator = (const ClassMemberAccessAST &source);
+};
+
+class IncrDecrAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_IncrDecr };
+
+public:
+ IncrDecrAST();
+
+ inline AST *op() const
+ { return m_op; }
+
+ inline AbstractExpressionAST *expression() const
+ { return m_expression; }
+
+ void setOp(AST *op);
+ void setExpression(AbstractExpressionAST *expression);
+
+private:
+ AST *m_op;
+ AbstractExpressionAST *m_expression;
+
+private:
+ IncrDecrAST(const IncrDecrAST &source);
+ void operator = (const IncrDecrAST &source);
+};
+
+class CppCastExpressionAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_CppCastExpression };
+
+public:
+ CppCastExpressionAST();
+
+ inline AST *castOp() const
+ { return m_castOp; }
+
+ inline AST *typeId() const
+ { return m_typeId; }
+
+ inline AbstractExpressionAST *expression() const
+ { return m_expression; }
+
+ void setCastOp(AST *castOp);
+ void setTypeId(AST *typeId);
+ void setExpression(AbstractExpressionAST *expression);
+
+private:
+ AST *m_castOp;
+ AST *m_typeId;
+ AbstractExpressionAST *m_expression;
+
+private:
+ CppCastExpressionAST(const CppCastExpressionAST &source);
+ void operator = (const CppCastExpressionAST &source);
+};
+
+class TypeIdentificationAST: public AbstractExpressionAST
+{
+public:
+ enum { Type = NodeType_TypeIdentification };
+
+public:
+ TypeIdentificationAST();
+
+private:
+ TypeIdentificationAST(const TypeIdentificationAST &source);
+ void operator = (const TypeIdentificationAST &source);
+};
+
+class TypeIdAST: public AST
+{
+public:
+ enum { Type = NodeType_TypeId };
+
+public:
+ TypeIdAST();
+
+ inline TypeSpecifierAST *typeSpecifier() const
+ { return m_typeSpecifier; }
+
+ inline DeclaratorAST *declarator() const
+ { return m_declarator; }
+
+ void setTypeSpecifier(TypeSpecifierAST *typeSpecifier);
+ void setDeclarator(DeclaratorAST *declarator);
+
+private:
+ TypeSpecifierAST *m_typeSpecifier;
+ DeclaratorAST *m_declarator;
+
+private:
+ TypeIdAST(const TypeIdAST &source);
+ void operator = (const TypeIdAST &source);
+};
+
+class StatementAST: public AST
+{
+public:
+ enum { Type = NodeType_Statement };
+};
+
+class TemplateArgumentListAST: public AST
+{
+public:
+ enum { Type = NodeType_TemplateArgumentList };
+
+public:
+ TemplateArgumentListAST();
+
+ void addArgument(AST *arg);
+ inline List<AST *> *argumentList() const { return m_argumentList; }
+
+private:
+ List<AST *> *m_argumentList;
+
+private:
+ TemplateArgumentListAST(const TemplateArgumentListAST &source);
+ void operator = (const TemplateArgumentListAST &source);
+};
+
+class ClassOrNamespaceNameAST: public AST
+{
+public:
+ enum { Type = NodeType_ClassOrNamespaceName };
+
+public:
+ ClassOrNamespaceNameAST();
+
+ inline AST *name() const { return m_name; }
+ void setName(AST *name);
+
+ inline TemplateArgumentListAST *templateArgumentList() const { return m_templateArgumentList; }
+ void setTemplateArgumentList(TemplateArgumentListAST *templateArgumentList);
+
+private:
+ AST* m_name;
+ TemplateArgumentListAST* m_templateArgumentList;
+
+private:
+ ClassOrNamespaceNameAST(const ClassOrNamespaceNameAST &source);
+ void operator = (const ClassOrNamespaceNameAST &source);
+};
+
+class NameAST: public AST
+{
+public:
+ enum { Type = NodeType_Name };
+
+public:
+ NameAST();
+
+ inline bool isGlobal() const { return m_global; }
+ void setGlobal(bool b);
+
+ void addClassOrNamespaceName(ClassOrNamespaceNameAST *classOrNamespaceName);
+ inline List<ClassOrNamespaceNameAST *> *classOrNamespaceNameList() const { return m_classOrNamespaceNameList; }
+
+ inline ClassOrNamespaceNameAST *unqualifiedName() const { return m_unqualifiedName; }
+ void setUnqualifiedName(ClassOrNamespaceNameAST *unqualifiedName);
+
+private:
+ bool m_global;
+ ClassOrNamespaceNameAST* m_unqualifiedName;
+ List<ClassOrNamespaceNameAST *> *m_classOrNamespaceNameList;
+
+private:
+ NameAST(const NameAST &source);
+ void operator = (const NameAST &source);
+};
+
+class TypeParameterAST: public AST
+{
+public:
+ enum { Type = NodeType_TypeParameter };
+
+public:
+ TypeParameterAST();
+
+ inline AST *kind() const { return m_kind; }
+ void setKind(AST *kind);
+
+ inline class TemplateParameterListAST *templateParameterList() const { return m_templateParameterList; }
+ void setTemplateParameterList(class TemplateParameterListAST *templateParameterList);
+
+ inline NameAST *name() const { return m_name; }
+ void setName(NameAST *name);
+
+ inline AST *typeId() const { return m_typeId; }
+ void setTypeId(AST *typeId);
+
+private:
+ AST* m_kind;
+ class TemplateParameterListAST *m_templateParameterList;
+ NameAST* m_name;
+ AST* m_typeId;
+
+private:
+ TypeParameterAST(const TypeParameterAST &source);
+ void operator = (const TypeParameterAST &source);
+};
+
+class DeclarationAST: public AST
+{
+public:
+ enum { Type = NodeType_Declaration };
+
+public:
+ DeclarationAST();
+
+private:
+ DeclarationAST(const DeclarationAST &source);
+ void operator = (const DeclarationAST &source);
+};
+
+class AccessDeclarationAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_AccessDeclaration };
+
+public:
+ AccessDeclarationAST();
+
+ inline List<AST *> *accessList() const { return m_accessList; }
+ void addAccess(AST *access);
+
+private:
+ List<AST *> *m_accessList;
+
+private:
+ AccessDeclarationAST(const AccessDeclarationAST &source);
+ void operator = (const AccessDeclarationAST &source);
+};
+
+class TypeSpecifierAST: public AST
+{
+public:
+ enum { Type = NodeType_TypeSpecifier };
+
+public:
+ TypeSpecifierAST();
+
+ inline virtual NameAST *name() const { return m_name; }
+ virtual void setName(NameAST *name);
+
+ inline AST *cvQualify() const { return m_cvQualify; }
+ void setCvQualify(AST *cvQualify);
+
+ inline AST *cv2Qualify() const { return m_cv2Qualify; }
+ void setCv2Qualify(AST *cv2Qualify);
+
+private:
+ NameAST* m_name;
+ AST* m_cvQualify;
+ AST* m_cv2Qualify;
+
+private:
+ TypeSpecifierAST(const TypeSpecifierAST &source);
+ void operator = (const TypeSpecifierAST &source);
+};
+
+class BaseSpecifierAST: public AST
+{
+public:
+ enum { Type = NodeType_BaseSpecifier };
+
+public:
+ BaseSpecifierAST();
+
+ inline AST *isVirtual() const { return m_isVirtual; }
+ void setIsVirtual(AST *isVirtual);
+
+ inline AST *access() const { return m_access; }
+ void setAccess(AST *access);
+
+ inline NameAST *name() const { return m_name; }
+ void setName(NameAST *name);
+
+private:
+ AST* m_isVirtual;
+ AST* m_access;
+ NameAST* m_name;
+
+private:
+ BaseSpecifierAST(const BaseSpecifierAST &source);
+ void operator = (const BaseSpecifierAST &source);
+};
+
+class BaseClauseAST: public AST
+{
+public:
+ enum { Type = NodeType_BaseClause };
+
+public:
+ BaseClauseAST();
+
+ void addBaseSpecifier(BaseSpecifierAST *baseSpecifier);
+ inline List<BaseSpecifierAST *> *baseSpecifierList() const { return m_baseSpecifierList; }
+
+private:
+ List<BaseSpecifierAST *> *m_baseSpecifierList;
+
+private:
+ BaseClauseAST(const BaseClauseAST &source);
+ void operator = (const BaseClauseAST &source);
+};
+
+class ClassSpecifierAST: public TypeSpecifierAST
+{
+public:
+ enum { Type = NodeType_ClassSpecifier };
+
+public:
+ ClassSpecifierAST();
+
+ inline AST *winDeclSpec() const { return m_winDeclSpec; }
+ void setWinDeclSpec(AST *winDeclSpec);
+
+ inline AST *classKey() const { return m_classKey; }
+ void setClassKey(AST *classKey);
+
+ inline BaseClauseAST *baseClause() const { return m_baseClause; }
+ void setBaseClause(BaseClauseAST *baseClause);
+
+ inline List<DeclarationAST *> *declarationList() const { return m_declarationList; }
+ void addDeclaration(DeclarationAST *declaration);
+
+private:
+ AST* m_winDeclSpec;
+ AST* m_classKey;
+ BaseClauseAST* m_baseClause;
+ List<DeclarationAST *> *m_declarationList;
+
+private:
+ ClassSpecifierAST(const ClassSpecifierAST &source);
+ void operator = (const ClassSpecifierAST &source);
+};
+
+class EnumeratorAST: public AST
+{
+public:
+ enum { Type = NodeType_Enumerator };
+
+public:
+ EnumeratorAST();
+
+ inline AST *id() const { return m_id; }
+ void setId(AST *id);
+
+ inline AbstractExpressionAST *expression() const { return m_expression; }
+ void setExpression(AbstractExpressionAST *expr);
+
+private:
+ AST* m_id;
+ AbstractExpressionAST* m_expression;
+
+private:
+ EnumeratorAST(const EnumeratorAST &source);
+ void operator = (const EnumeratorAST &source);
+};
+
+class EnumSpecifierAST: public TypeSpecifierAST
+{
+public:
+ enum { Type = NodeType_EnumSpecifier };
+
+public:
+ EnumSpecifierAST();
+
+ void addEnumerator(EnumeratorAST *enumerator);
+ inline List<EnumeratorAST *> *enumeratorList() const { return m_enumeratorList; }
+
+private:
+ List<EnumeratorAST *> *m_enumeratorList;
+
+private:
+ EnumSpecifierAST(const EnumSpecifierAST &source);
+ void operator = (const EnumSpecifierAST &source);
+};
+
+class ElaboratedTypeSpecifierAST: public TypeSpecifierAST
+{
+public:
+ enum { Type = NodeType_ElaboratedTypeSpecifier };
+
+public:
+ ElaboratedTypeSpecifierAST();
+
+ inline AST *kind() const { return m_kind; }
+ void setKind(AST *kind);
+
+private:
+ AST* m_kind;
+
+private:
+ ElaboratedTypeSpecifierAST(const ElaboratedTypeSpecifierAST &source);
+ void operator = (const ElaboratedTypeSpecifierAST &source);
+};
+
+
+class LinkageBodyAST: public AST
+{
+public:
+ enum { Type = NodeType_LinkageBody };
+
+public:
+ LinkageBodyAST();
+
+ void addDeclaration(DeclarationAST *ast);
+ inline List<DeclarationAST *> *declarationList() const { return m_declarationList; }
+
+private:
+ List<DeclarationAST *> *m_declarationList;
+
+private:
+ LinkageBodyAST(const LinkageBodyAST &source);
+ void operator = (const LinkageBodyAST &source);
+};
+
+class LinkageSpecificationAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_LinkageSpecification };
+
+public:
+ LinkageSpecificationAST();
+
+ inline AST *externType() const { return m_externType; }
+ void setExternType(AST *externType);
+
+ inline LinkageBodyAST *linkageBody() const { return m_linkageBody; }
+ void setLinkageBody(LinkageBodyAST *linkageBody);
+
+ inline DeclarationAST *declaration() const { return m_declaration; }
+ void setDeclaration(DeclarationAST *decl);
+
+private:
+ AST* m_externType;
+ LinkageBodyAST* m_linkageBody;
+ DeclarationAST* m_declaration;
+
+private:
+ LinkageSpecificationAST(const LinkageSpecificationAST &source);
+ void operator = (const LinkageSpecificationAST &source);
+};
+
+class NamespaceAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_Namespace };
+
+public:
+ NamespaceAST();
+
+ inline AST *namespaceName() const { return m_namespaceName; }
+ void setNamespaceName(AST *namespaceName);
+
+ inline LinkageBodyAST *linkageBody() const { return m_linkageBody; }
+ void setLinkageBody(LinkageBodyAST *linkageBody);
+
+private:
+ AST* m_namespaceName;
+ LinkageBodyAST* m_linkageBody;
+
+private:
+ NamespaceAST(const NamespaceAST &source);
+ void operator = (const NamespaceAST &source);
+};
+
+class NamespaceAliasAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_NamespaceAlias };
+
+public:
+ NamespaceAliasAST();
+
+ inline AST *namespaceName() const { return m_namespaceName; }
+ void setNamespaceName(AST *name);
+
+ inline NameAST *aliasName() const { return m_aliasName; }
+ void setAliasName(NameAST *name);
+
+private:
+ AST* m_namespaceName;
+ NameAST* m_aliasName;
+
+private:
+ NamespaceAliasAST(const NamespaceAliasAST &source);
+ void operator = (const NamespaceAliasAST &source);
+};
+
+class UsingAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_Using };
+
+public:
+ UsingAST();
+
+ inline AST *typeName() const { return m_typeName; }
+ void setTypeName(AST *typeName);
+
+ inline NameAST *name() const { return m_name; }
+ void setName(NameAST *name);
+
+private:
+ AST* m_typeName;
+ NameAST* m_name;
+
+private:
+ UsingAST(const UsingAST &source);
+ void operator = (const UsingAST &source);
+};
+
+class UsingDirectiveAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_UsingDirective };
+
+public:
+ UsingDirectiveAST();
+
+ inline NameAST *name() const { return m_name; }
+ void setName(NameAST *name);
+
+private:
+ NameAST* m_name;
+
+private:
+ UsingDirectiveAST(const UsingDirectiveAST &source);
+ void operator = (const UsingDirectiveAST &source);
+};
+
+class DeclaratorAST: public AST
+{
+public:
+ enum { Type = NodeType_Declarator };
+
+public:
+ DeclaratorAST();
+
+ inline List<AST *> *ptrOpList() const { return m_ptrOpList; }
+ void addPtrOp(AST *ptrOp);
+
+ inline DeclaratorAST *subDeclarator() const { return m_subDeclarator; }
+ void setSubDeclarator(DeclaratorAST *subDeclarator);
+
+ inline NameAST *declaratorId() const { return m_declaratorId; }
+ void setDeclaratorId(NameAST *declaratorId);
+
+ inline AST *bitfieldInitialization() const { return m_bitfieldInitialization; }
+ void setBitfieldInitialization(AST *bitfieldInitialization);
+
+ inline List<AST *> *arrayDimensionList() const { return m_arrayDimensionList; }
+ void addArrayDimension(AST *arrayDimension);
+
+ inline class ParameterDeclarationClauseAST *parameterDeclarationClause() const { return m_parameterDeclarationClause; }
+ void setParameterDeclarationClause(class ParameterDeclarationClauseAST *parameterDeclarationClause);
+
+ // ### replace 'constant' with cvQualify
+ inline AST *constant() const { return m_constant; }
+ void setConstant(AST *constant);
+
+ inline AST *exceptionSpecification() const { return m_exceptionSpecification; }
+ void setExceptionSpecification(AST *exceptionSpecification);
+
+private:
+ List<AST *> *m_ptrOpList;
+ DeclaratorAST * m_subDeclarator;
+ NameAST* m_declaratorId;
+ AST* m_bitfieldInitialization;
+ List<AST *> *m_arrayDimensionList;
+ class ParameterDeclarationClauseAST * m_parameterDeclarationClause;
+ AST* m_constant;
+ AST* m_exceptionSpecification;
+
+private:
+ DeclaratorAST(const DeclaratorAST &source);
+ void operator = (const DeclaratorAST &source);
+};
+
+class ParameterDeclarationAST: public AST
+{
+public:
+ enum { Type = NodeType_ParameterDeclaration };
+
+public:
+ ParameterDeclarationAST();
+
+ inline TypeSpecifierAST *typeSpec() const { return m_typeSpec; }
+ void setTypeSpec(TypeSpecifierAST *typeSpec);
+
+ inline DeclaratorAST *declarator() const { return m_declarator; }
+ void setDeclarator(DeclaratorAST *declarator);
+
+ inline AbstractExpressionAST *expression() const { return m_expression; }
+ void setExpression(AbstractExpressionAST *expression);
+
+private:
+ TypeSpecifierAST* m_typeSpec;
+ DeclaratorAST* m_declarator;
+ AbstractExpressionAST* m_expression;
+
+private:
+ ParameterDeclarationAST(const ParameterDeclarationAST &source);
+ void operator = (const ParameterDeclarationAST &source);
+};
+
+class ParameterDeclarationListAST: public AST
+{
+public:
+ enum { Type = NodeType_ParameterDeclarationList };
+
+public:
+ ParameterDeclarationListAST();
+
+ inline List<ParameterDeclarationAST *> *parameterList() const { return m_parameterList; }
+ void addParameter(ParameterDeclarationAST *parameter);
+
+private:
+ List<ParameterDeclarationAST *> *m_parameterList;
+
+private:
+ ParameterDeclarationListAST(const ParameterDeclarationListAST &source);
+ void operator = (const ParameterDeclarationListAST &source);
+};
+
+class ParameterDeclarationClauseAST: public AST
+{
+public:
+ enum { Type = NodeType_ParameterDeclarationClause };
+
+public:
+ ParameterDeclarationClauseAST();
+
+ inline ParameterDeclarationListAST *parameterDeclarationList() const { return m_parameterDeclarationList; }
+ void setParameterDeclarationList(ParameterDeclarationListAST *parameterDeclarationList);
+
+ inline AST *ellipsis() const { return m_ellipsis; }
+ void setEllipsis(AST *ellipsis);
+
+private:
+ ParameterDeclarationListAST* m_parameterDeclarationList;
+ AST* m_ellipsis;
+
+private:
+ ParameterDeclarationClauseAST(const ParameterDeclarationClauseAST &source);
+ void operator = (const ParameterDeclarationClauseAST &source);
+};
+
+
+class InitDeclaratorAST: public AST
+{
+public:
+ enum { Type = NodeType_InitDeclarator };
+
+public:
+ InitDeclaratorAST();
+
+ inline DeclaratorAST *declarator() const { return m_declarator; }
+ void setDeclarator(DeclaratorAST *declarator);
+
+ inline AST *initializer() const { return m_initializer; }
+ void setInitializer(AST *initializer);
+
+private:
+ DeclaratorAST* m_declarator;
+ AST* m_initializer;
+
+private:
+ InitDeclaratorAST(const InitDeclaratorAST &source);
+ void operator = (const InitDeclaratorAST &source);
+};
+
+class InitDeclaratorListAST: public AST
+{
+public:
+ enum { Type = NodeType_InitDeclaratorList };
+
+public:
+ InitDeclaratorListAST();
+
+ inline List<InitDeclaratorAST *> *initDeclaratorList() const { return m_initDeclaratorList; }
+ void addInitDeclarator(InitDeclaratorAST *decl);
+
+private:
+ List<InitDeclaratorAST *> *m_initDeclaratorList;
+
+private:
+ InitDeclaratorListAST(const InitDeclaratorListAST &source);
+ void operator = (const InitDeclaratorListAST &source);
+};
+
+class TypedefAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_Typedef };
+
+public:
+ TypedefAST();
+
+ inline TypeSpecifierAST *typeSpec() const { return m_typeSpec; }
+ void setTypeSpec(TypeSpecifierAST *typeSpec);
+
+ inline InitDeclaratorListAST *initDeclaratorList() const { return m_initDeclaratorList; }
+ void setInitDeclaratorList(InitDeclaratorListAST *initDeclaratorList);
+
+private:
+ TypeSpecifierAST* m_typeSpec;
+ InitDeclaratorListAST* m_initDeclaratorList;
+
+private:
+ void operator = (const TypedefAST &source);
+};
+
+class TemplateParameterAST: public AST
+{
+public:
+ enum { Type = NodeType_TemplateParameter };
+
+public:
+ TemplateParameterAST();
+
+ inline TypeParameterAST *typeParameter() const { return m_typeParameter; }
+ void setTypeParameter(TypeParameterAST *typeParameter);
+
+ inline ParameterDeclarationAST *typeValueParameter() const { return m_typeValueParameter; }
+ void setTypeValueParameter(ParameterDeclarationAST *typeValueParameter);
+
+private:
+ TypeParameterAST* m_typeParameter;
+ ParameterDeclarationAST* m_typeValueParameter;
+
+private:
+ TemplateParameterAST(const TemplateParameterAST &source);
+ void operator = (const TemplateParameterAST &source);
+};
+
+class TemplateParameterListAST: public AST
+{
+public:
+ enum { Type = NodeType_TemplateParameterList };
+
+public:
+ TemplateParameterListAST();
+
+ inline List<TemplateParameterAST *> *templateParameterList() const { return m_templateParameterList; }
+ void addTemplateParameter(TemplateParameterAST *templateParameter);
+
+private:
+ List<TemplateParameterAST *> *m_templateParameterList;
+
+private:
+ TemplateParameterListAST(const TemplateParameterListAST &source);
+ void operator = (const TemplateParameterListAST &source);
+};
+
+class TemplateDeclarationAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_TemplateDeclaration };
+
+public:
+ TemplateDeclarationAST();
+
+ inline AST *exported() const { return m_exported; }
+ void setExported(AST *exported);
+
+ inline TemplateParameterListAST *templateParameterList() const { return m_templateParameterList; }
+ void setTemplateParameterList(TemplateParameterListAST *templateParameterList);
+
+ inline DeclarationAST *declaration() const { return m_declaration; }
+ void setDeclaration(DeclarationAST *declaration);
+
+private:
+ AST* m_exported;
+ TemplateParameterListAST* m_templateParameterList;
+ DeclarationAST* m_declaration;
+
+private:
+ TemplateDeclarationAST(const TemplateDeclarationAST &source);
+ void operator = (const TemplateDeclarationAST &source);
+};
+
+class SimpleDeclarationAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_SimpleDeclaration };
+
+public:
+ SimpleDeclarationAST();
+
+ inline AST *functionSpecifier() const { return m_functionSpecifier; }
+ void setFunctionSpecifier(AST *functionSpecifier);
+
+ inline AST *storageSpecifier() const { return m_storageSpecifier; }
+ void setStorageSpecifier(AST *storageSpecifier);
+
+ inline TypeSpecifierAST *typeSpec() const { return m_typeSpec; }
+ void setTypeSpec(TypeSpecifierAST *typeSpec);
+
+ inline InitDeclaratorListAST *initDeclaratorList() const { return m_initDeclaratorList; }
+ void setInitDeclaratorList(InitDeclaratorListAST *initDeclaratorList);
+
+ inline AST *winDeclSpec() const { return m_winDeclSpec; }
+ void setWinDeclSpec(AST *winDeclSpec);
+
+private:
+ AST* m_functionSpecifier;
+ AST* m_storageSpecifier;
+ TypeSpecifierAST* m_typeSpec;
+ InitDeclaratorListAST* m_initDeclaratorList;
+ AST* m_winDeclSpec;
+
+private:
+ SimpleDeclarationAST(const SimpleDeclarationAST &source);
+ void operator = (const SimpleDeclarationAST &source);
+};
+
+class ExpressionStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_ExpressionStatement };
+
+public:
+ ExpressionStatementAST();
+
+ inline AbstractExpressionAST *expression() const { return m_expression; }
+ void setExpression(AbstractExpressionAST *expression);
+
+private:
+ AbstractExpressionAST* m_expression;
+
+private:
+ ExpressionStatementAST(const ExpressionStatementAST &source);
+ void operator = (const ExpressionStatementAST &source);
+};
+
+class ReturnStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_ReturnStatement };
+
+public:
+ ReturnStatementAST();
+
+ inline AbstractExpressionAST *expression() const { return m_expression; }
+ void setExpression(AbstractExpressionAST *expression);
+
+private:
+ AbstractExpressionAST* m_expression;
+
+private:
+ ReturnStatementAST(const ReturnStatementAST &source);
+ void operator = (const ReturnStatementAST &source);
+};
+
+
+class ConditionAST: public AST
+{
+public:
+ enum { Type = NodeType_Condition };
+
+public:
+ ConditionAST();
+
+ inline TypeSpecifierAST *typeSpec() const { return m_typeSpec; }
+ void setTypeSpec(TypeSpecifierAST *typeSpec);
+
+ inline DeclaratorAST *declarator() const { return m_declarator; }
+ void setDeclarator(DeclaratorAST *declarator);
+
+ inline AbstractExpressionAST *expression() const { return m_expression; }
+ void setExpression(AbstractExpressionAST *expression);
+
+private:
+ TypeSpecifierAST* m_typeSpec;
+ DeclaratorAST* m_declarator;
+ AbstractExpressionAST* m_expression;
+
+private:
+ ConditionAST(const ConditionAST &source);
+ void operator = (const ConditionAST &source);
+};
+
+class IfStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_IfStatement };
+
+public:
+ IfStatementAST();
+
+ inline ConditionAST *condition() const { return m_condition; }
+ void setCondition(ConditionAST *condition);
+
+ inline StatementAST *statement() const { return m_statement; }
+ void setStatement(StatementAST *statement);
+
+ inline StatementAST *elseStatement() const { return m_elseStatement; }
+ void setElseStatement(StatementAST *statement);
+
+private:
+ ConditionAST* m_condition;
+ StatementAST* m_statement;
+ StatementAST* m_elseStatement;
+
+private:
+ IfStatementAST(const IfStatementAST &source);
+ void operator = (const IfStatementAST &source);
+};
+
+class WhileStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_WhileStatement };
+
+public:
+ WhileStatementAST();
+
+ inline ConditionAST *condition() const { return m_condition; }
+ void setCondition(ConditionAST *condition);
+
+ inline StatementAST *statement() const { return m_statement; }
+ void setStatement(StatementAST *statement);
+
+private:
+ ConditionAST* m_condition;
+ StatementAST* m_statement;
+
+private:
+ WhileStatementAST(const WhileStatementAST &source);
+ void operator = (const WhileStatementAST &source);
+};
+
+class DoStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_DoStatement };
+
+public:
+ DoStatementAST();
+
+ inline ConditionAST *condition() const { return m_condition; }
+ void setCondition(ConditionAST *condition);
+
+ inline StatementAST *statement() const { return m_statement; }
+ void setStatement(StatementAST *statement);
+
+private:
+ ConditionAST* m_condition;
+ StatementAST* m_statement;
+
+private:
+ DoStatementAST(const DoStatementAST &source);
+ void operator = (const DoStatementAST &source);
+};
+
+class ForStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_ForStatement };
+
+public:
+ ForStatementAST();
+
+ inline StatementAST *initStatement() const { return m_initStatement; }
+ void setInitStatement(StatementAST *statement);
+
+ inline ConditionAST *condition() const { return m_condition; }
+ void setCondition(ConditionAST *condition);
+
+ inline AbstractExpressionAST *expression() const { return m_expression; }
+ void setExpression(AbstractExpressionAST *expression);
+
+ inline StatementAST *statement() const { return m_statement; }
+ void setStatement(StatementAST *statement);
+
+private:
+ ConditionAST* m_condition;
+ StatementAST* m_initStatement;
+ StatementAST* m_statement;
+ AbstractExpressionAST* m_expression;
+
+private:
+ ForStatementAST(const ForStatementAST &source);
+ void operator = (const ForStatementAST &source);
+};
+
+class SwitchStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_SwitchStatement };
+
+public:
+ SwitchStatementAST();
+
+ inline ConditionAST *condition() const { return m_condition; }
+ void setCondition(ConditionAST *condition);
+
+ inline StatementAST *statement() const { return m_statement; }
+ void setStatement(StatementAST *statement);
+
+private:
+ ConditionAST* m_condition;
+ StatementAST* m_statement;
+
+private:
+ SwitchStatementAST(const SwitchStatementAST &source);
+ void operator = (const SwitchStatementAST &source);
+};
+
+class StatementListAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_StatementList };
+
+public:
+ StatementListAST();
+
+ inline List<StatementAST *> *statementList() const { return m_statementList; }
+ void addStatement(StatementAST *statement);
+
+private:
+ List<StatementAST *> *m_statementList;
+
+private:
+ StatementListAST(const StatementListAST &source);
+ void operator = (const StatementListAST &source);
+};
+
+class DeclarationStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_DeclarationStatement };
+
+public:
+ DeclarationStatementAST();
+
+ inline DeclarationAST *declaration() const { return m_declaration; }
+ void setDeclaration(DeclarationAST *declaration);
+
+private:
+ DeclarationAST* m_declaration;
+
+private:
+ DeclarationStatementAST(const DeclarationStatementAST &source);
+ void operator = (const DeclarationStatementAST &source);
+};
+
+/*
+ LabeledStatementAST:
+ case constant-expression : statement
+ default : statement (expression is 0)
+*/
+class LabeledStatementAST: public StatementAST
+{
+public:
+ enum { Type = NodeType_LabeledStatement };
+public:
+ LabeledStatementAST();
+
+ inline StatementAST *statement() const { return m_statement; }
+ void setStatement(StatementAST *statement);
+
+ inline AbstractExpressionAST *expression() const { return m_expression; }
+ void setExpression(AbstractExpressionAST *expression);
+private:
+ StatementAST* m_statement;
+ AbstractExpressionAST *m_expression;
+
+private:
+ LabeledStatementAST(const LabeledStatementAST &source);
+ void operator = (const LabeledStatementAST &source);
+};
+
+class FunctionDefinitionAST: public DeclarationAST
+{
+public:
+ enum { Type = NodeType_FunctionDefinition };
+
+public:
+ FunctionDefinitionAST();
+
+ inline AST *functionSpecifier() const { return m_functionSpecifier; }
+ void setFunctionSpecifier(AST *functionSpecifier);
+
+ inline AST *storageSpecifier() const { return m_storageSpecifier; }
+ void setStorageSpecifier(AST *storageSpecifier);
+
+ inline TypeSpecifierAST *typeSpec() const { return m_typeSpec; }
+ void setTypeSpec(TypeSpecifierAST *typeSpec);
+
+ inline InitDeclaratorAST *initDeclarator() const { return m_initDeclarator; }
+ void setInitDeclarator(InitDeclaratorAST *initDeclarator);
+
+ inline StatementListAST *functionBody() const { return m_functionBody; }
+ void setFunctionBody(StatementListAST *functionBody);
+
+ inline AST *winDeclSpec() const { return m_winDeclSpec; }
+ void setWinDeclSpec(AST *winDeclSpec);
+
+private:
+ AST* m_functionSpecifier;
+ AST* m_storageSpecifier;
+ TypeSpecifierAST* m_typeSpec;
+ InitDeclaratorAST* m_initDeclarator;
+ StatementListAST* m_functionBody;
+ AST* m_winDeclSpec;
+
+private:
+ FunctionDefinitionAST(const FunctionDefinitionAST &source);
+ void operator = (const FunctionDefinitionAST &source);
+};
+
+class TranslationUnitAST: public AST
+{
+public:
+ enum { Type = NodeType_TranslationUnit };
+
+public:
+ TranslationUnitAST();
+
+ void addDeclaration(DeclarationAST *ast);
+ inline List<DeclarationAST *> *declarationList() const { return m_declarationList; }
+
+private:
+ List<DeclarationAST *> *m_declarationList;
+
+private:
+ TranslationUnitAST(const TranslationUnitAST &source);
+ void operator = (const TranslationUnitAST &source);
+};
+
+template <class T> T* CreateNode(pool *p)
+{
+ T* node = new (p->allocate(sizeof(T))) T;
+ node->setNodeType(T::Type);
+ node->_pool = p;
+ return node;
+}
+
+template <int kind> ExpressionAST<kind> *CreateExpression(pool *p)
+{
+ ExpressionAST<kind>* node = new (p->allocate(sizeof(ExpressionAST<kind>))) ExpressionAST<kind>;
+ node->setNodeType(kind);
+ node->_pool = p;
+ return node;
+}
+
+/*
+template <typename T>
+inline List<T *> *snoc(List<T *> *e, T *d, pool *p)
+{ if (!e) e = new (p->allocate(sizeof(List<T*>))) List<T *>(p); e->append(d); return e; }
+*/
+
+//Workaround for ICE on MSVC, use macro instead of template.
+#define SNOC(ListType, ListValueType) \
+inline ListType *snoc(ListType *e, ListValueType *d, pool *p) \
+{ if (!e) e = new (p->allocate(sizeof(ListType))) ListType(p); e->append(d); return e; }
+
+SNOC(List<AST *>, AST)
+SNOC(List<ClassOrNamespaceNameAST *>, ClassOrNamespaceNameAST)
+SNOC(List<BaseSpecifierAST *>, BaseSpecifierAST)
+SNOC(List<DeclarationAST *>, DeclarationAST)
+SNOC(List<EnumeratorAST *>, EnumeratorAST)
+SNOC(List<ParameterDeclarationAST *>, ParameterDeclarationAST)
+SNOC(List<InitDeclaratorAST *>, InitDeclaratorAST)
+SNOC(List<TemplateParameterAST *>, TemplateParameterAST)
+SNOC(List<StatementAST *>, StatementAST)
+
+QT_END_NAMESPACE
+
+#endif // AST_H
diff --git a/tools/porting/src/codemodel.cpp b/tools/porting/src/codemodel.cpp
new file mode 100644
index 0000000000..46228338bd
--- /dev/null
+++ b/tools/porting/src/codemodel.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "codemodel.h"
+
+#include <QList>
+#include <QByteArray>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace CodeModel {
+
+BuiltinType BuiltinType::Bool("bool", 0 );
+BuiltinType BuiltinType::Void("void", 0 );
+BuiltinType BuiltinType::Char("char", 0 );
+BuiltinType BuiltinType::Short("short", 0 );
+BuiltinType BuiltinType::Int("int", 0 );
+BuiltinType BuiltinType::Long("long", 0 );
+BuiltinType BuiltinType::Double("double", 0 );
+BuiltinType BuiltinType::Float("float", 0 );
+BuiltinType BuiltinType::Unsigned("unsigned", 0 );
+BuiltinType BuiltinType::Signed("signed", 0 );
+
+void Scope::addScope(Scope *scope)
+{
+ scope->setParent(this);
+ m_scopes.add(scope);
+}
+
+void Scope::addType(Type *type)
+{
+ if (ClassType *klass = type->toClassType())
+ klass->setParent(this);
+ m_types.add(type);
+}
+
+void Scope::addMember(Member *member)
+{
+ member->setParent(this);
+ m_members.add(member);
+}
+
+void Scope::addNameUse(NameUse *nameUse)
+{
+ nameUse->setParent(this);
+ m_nameUses.add(nameUse);
+}
+
+} //namepsace CodeModel
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/codemodel.h b/tools/porting/src/codemodel.h
new file mode 100644
index 0000000000..017191e2d6
--- /dev/null
+++ b/tools/porting/src/codemodel.h
@@ -0,0 +1,777 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CODEMODEL_H
+#define CODEMODEL_H
+
+#include "smallobject.h"
+#include "tokenengine.h"
+
+#include <QByteArray>
+#include <QList>
+#include <QMap>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+namespace CodeModel
+{
+
+// types
+struct Type;
+struct EnumType;
+struct EnumeratorType;
+struct ClassType;
+struct BuiltinType;
+struct PointerType;
+struct ReferenceType;
+struct GenericType;
+struct AliasType;
+struct FunctionType;
+struct UnknownType;
+
+// Scopes contain child scopes, members and types.
+struct Scope;
+struct ClassScope;
+struct NamespaceScope;
+struct BlockScope;
+
+// Members introduces names into scopes, and are also linked to a specific
+// token in a source file.
+struct Member;
+struct FunctionMember;
+struct VariableMember;
+struct UsingDeclarationMember;
+struct NamespaceMember;
+struct TypeMember;
+
+// Name uses links uses of a name to its declaration (a Member), and also to a
+// token in a source file.
+struct NameUse;
+
+struct Argument;
+struct UsingDirectiveLink;
+
+template <typename CollectedType>
+class Collection: public QMultiHash<QByteArray, CollectedType *>
+{
+public:
+ void add(CollectedType *collectedItem)
+ { insert(collectedItem->name(), collectedItem); }
+};
+
+typedef Collection<Scope> ScopeCollection;
+typedef Collection<Member> MemberCollection;
+typedef Collection<Type> TypeCollection;
+typedef Collection<NameUse> NameUseCollection;
+typedef Collection<Argument> ArgumentCollection;
+
+struct SemanticInfo
+{
+ CodeModel::NamespaceScope *codeModel;
+
+ // tokenindex -> NameUse* map. Use map here bacause we expect name uses to
+ // be sparesly distributed among the tokens.
+ QMap<int, NameUse*> nameUses;
+};
+
+
+struct Item
+{
+ Item() {}
+ virtual ~Item() {}
+ virtual QByteArray name() const = 0;
+};
+
+struct Type: public Item
+{
+ virtual QByteArray name() const =0;
+
+ virtual EnumType *toEnumType() const
+ { return 0; }
+
+ virtual ClassType *toClassType() const
+ { return 0; }
+
+ virtual UnknownType *toUnknownType() const
+ { return 0; }
+
+ virtual BuiltinType *toBuiltinType() const
+ { return 0; }
+
+ virtual PointerType *toPointerType() const
+ { return 0; }
+
+ virtual ReferenceType *toReferenceType() const
+ { return 0; }
+
+ virtual GenericType *toGenericType() const
+ { return 0; }
+
+ virtual AliasType *toAliasType() const
+ { return 0; }
+};
+
+struct Scope: public Item
+{
+ Scope()
+ : m_parent(0) {}
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ QByteArray name() const
+ { return m_name; }
+
+ void setName(const QByteArray &name)
+ { m_name=name; }
+
+ virtual NamespaceScope *toNamespaceScope() const
+ { return 0; }
+
+ virtual ClassScope *toClassScope() const
+ { return 0; }
+
+ virtual BlockScope *toBlockScope() const
+ { return 0; }
+
+ const Collection<Scope> scopes() const
+ { return m_scopes; }
+ const Collection<Type> types() const
+ { return m_types; }
+ const Collection<Member> members() const
+ { return m_members; }
+ const Collection<NameUse> nameUses() const
+ { return m_nameUses; }
+
+ void addScope(Scope *scope);
+ void addType(Type *type);
+ void addMember(Member *member);
+ void addNameUse(NameUse *nameUse);
+private:
+ Scope *m_parent;
+ QByteArray m_name;
+ Collection<Scope> m_scopes;
+ Collection<Type> m_types;
+ Collection<Member> m_members;
+ Collection<NameUse> m_nameUses;
+};
+
+struct Member: public Item
+{
+ enum Binding // ### not used yet
+ {
+ Static,
+ Instance
+ };
+
+ enum Access // ### not used yet
+ {
+ Public,
+ Protected,
+ Private
+ };
+
+ Member()
+ : m_binding(Static), m_access(Public),
+ m_parent(0), m_constant(0), m_static(0) {}
+
+ QByteArray name() const
+ { return m_name; }
+
+ void setName(const QByteArray &name)
+ { m_name = name; }
+
+ TokenEngine::TokenRef nameToken() const
+ { return m_nameToken; }
+
+ void setNameToken(TokenEngine::TokenRef nameToken)
+ { m_nameToken = nameToken; }
+
+ Binding binding() const
+ { return m_binding; }
+
+ void setBinding(Binding binding)
+ { m_binding = binding; }
+
+ Access access() const
+ { return m_access; }
+
+ void setAccess(Access access)
+ { m_access = access; }
+
+ bool isConstant() const
+ { return m_constant; }
+
+ void setConstant(bool b)
+ { m_constant = b; }
+
+ bool isStatic() const
+ { return m_static; }
+
+ void setStatic(bool b)
+ { m_static = b; }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ virtual FunctionMember *toFunctionMember() const
+ { return 0; }
+
+ virtual VariableMember *toVariableMember() const
+ { return 0; }
+
+ virtual UsingDeclarationMember *toUsingDeclarationMember() const
+ { return 0; }
+
+ virtual NamespaceMember *toNamespaceMember() const
+ { return 0; }
+
+ virtual TypeMember *toTypeMember() const
+ { return 0; }
+
+ private:
+ Binding m_binding;
+ Access m_access;
+ Scope *m_parent;
+ QByteArray m_name;
+ TokenEngine::TokenRef m_nameToken;
+ uint m_constant : 1;
+ uint m_static : 1;
+};
+
+struct ClassScope: public Scope
+{
+ const Collection<Type> baseClasses() const
+ { return m_baseClasses; }
+
+ void addBaseClass(Type *baseClass)
+ {
+ Q_ASSERT(baseClass->toClassType());
+ m_baseClasses.add(baseClass);
+ }
+
+ virtual ClassScope *toClassScope() const
+ { return const_cast<ClassScope*>(this); }
+
+private:
+ Collection<Type> m_baseClasses;
+};
+
+struct UsingDirectiveLinkable : public Scope
+{
+ const QList<UsingDirectiveLink *> usingDirectiveLinks() const
+ { return m_usingDirectiveLinks; }
+
+ void addUsingDirectiveLink(UsingDirectiveLink *usingDirectiveLink)
+ { m_usingDirectiveLinks.append(usingDirectiveLink); }
+private:
+ QList<UsingDirectiveLink *> m_usingDirectiveLinks;
+};
+
+struct NamespaceScope: public UsingDirectiveLinkable
+{
+ NamespaceScope() {}
+
+ virtual NamespaceScope *toNamespaceScope() const
+ { return const_cast<NamespaceScope*>(this); }
+};
+
+struct BlockScope: public UsingDirectiveLinkable
+{
+ BlockScope() {}
+
+ virtual BlockScope *toBlockScope() const
+ { return const_cast<BlockScope*>(this); }
+};
+
+struct EnumType: public Type
+{
+ EnumType()
+ : m_parent(0) {}
+
+ QByteArray name() const
+ { return m_name; }
+
+ void setName(const QByteArray &name)
+ { m_name = name; }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ virtual EnumType *toEnumType() const
+ { return const_cast<EnumType*>(this); }
+
+private:
+ Scope *m_parent;
+ QByteArray m_name;
+};
+
+struct UnknownType: public Type
+{
+ UnknownType()
+ : m_parent(0) {}
+
+ QByteArray name() const
+ { return m_name; }
+
+ void setName(const QByteArray &name)
+ { m_name = name; }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ virtual UnknownType *toUnknownType() const
+ { return const_cast<UnknownType*>(this); }
+
+private:
+ Scope *m_parent;
+ QByteArray m_name;
+};
+
+struct ClassType: public Type
+{
+ ClassType()
+ : m_parent(0), m_scope(0) {}
+
+ ClassScope *scope() const
+ { return m_scope; }
+
+ void setScope(ClassScope *scope)
+ { m_scope = scope; }
+
+ QByteArray name() const
+ { return m_scope ? m_scope->name() : /*anonymous*/ QByteArray(); }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ virtual ClassType *toClassType() const
+ { return const_cast<ClassType*>(this); }
+
+private:
+ Scope *m_parent;
+ ClassScope *m_scope;
+
+};
+
+struct BuiltinType: public Type
+{
+protected:
+ BuiltinType(const QByteArray &name, Scope *parent)
+ : m_name(name), m_parent(parent) {}
+
+public:
+ QByteArray name() const
+ { return m_name; }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ virtual BuiltinType *toBuiltinType() const
+ { return const_cast<BuiltinType*>(this); }
+
+ static BuiltinType Bool;
+ static BuiltinType Void;
+ static BuiltinType Char;
+ static BuiltinType Short;
+ static BuiltinType Int;
+ static BuiltinType Long;
+ static BuiltinType Double;
+ static BuiltinType Float;
+ static BuiltinType Unsigned;
+ static BuiltinType Signed;
+ // ### more
+
+private:
+ QByteArray m_name;
+ Scope *m_parent;
+};
+
+struct PointerType: public Type
+{
+ PointerType()
+ : m_parent(0), m_baseType(0) {}
+
+ Type *baseType() const
+ { return m_baseType; }
+
+ void setBaseType(Type *baseType)
+ { m_baseType = baseType; }
+
+ QByteArray name() const
+ { return m_baseType->name(); }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ virtual PointerType *toPointerType() const
+ { return const_cast<PointerType*>(this); }
+
+private:
+ Scope *m_parent;
+ Type *m_baseType;
+};
+
+struct ReferenceType: public Type
+{
+ ReferenceType()
+ : m_parent(0), m_baseType(0) {}
+
+ Type *baseType() const
+ { return m_baseType; }
+
+ void setBaseType(Type *baseType)
+ { m_baseType = baseType; }
+
+ QByteArray name() const
+ { return m_baseType->name(); }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ virtual ReferenceType *toReferenceType() const
+ { return const_cast<ReferenceType*>(this); }
+
+private:
+ Scope *m_parent;
+ Type *m_baseType;
+};
+
+struct GenericType: public Type // ### implement me
+{
+ virtual GenericType *toGenericType() const
+ { return const_cast<GenericType*>(this); }
+};
+
+struct AliasType: public Type // ### implement me
+{
+ AliasType ()
+ : m_parent(0) {}
+
+ QByteArray name() const
+ { return m_name; }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ virtual AliasType *toAliasType() const
+ { return const_cast<AliasType*>(this); }
+private:
+ QByteArray m_name;
+ Scope *m_parent;
+};
+
+struct Argument: public Item
+{
+ Argument()
+ : m_parent(0), m_type(0) {}
+
+ Type *type() const
+ { return m_type; }
+
+ void setType(Type *type)
+ { m_type = type; }
+
+ QByteArray name() const
+ { return m_name; }
+
+ void setName(const QByteArray &name)
+ { m_name = name; }
+
+ TokenEngine::TokenRef nameToken() const
+ { return m_nameToken; }
+
+ void setNameToken(TokenEngine::TokenRef nameToken)
+ { m_nameToken = nameToken; }
+
+ virtual FunctionMember *parent() const
+ { return m_parent; }
+
+ void setParent(FunctionMember *parent)
+ { m_parent = parent; }
+
+private:
+ FunctionMember *m_parent;
+ Type *m_type;
+ QByteArray m_name;
+ TokenEngine::TokenRef m_nameToken;
+};
+
+struct FunctionMember: public Member
+{
+ inline FunctionMember()
+ : m_returnType(0),
+ m_functionBodyScope(0),
+ m_signal(0),
+ m_virtual(0), m_abstract(0) { m_slot = 0; }
+
+ virtual FunctionMember *toFunctionMember() const
+ { return const_cast<FunctionMember*>(this); }
+
+ Type *returnType() const
+ { return m_returnType; }
+
+ void setReturnType(Type *type)
+ { m_returnType = type; }
+
+ const Collection<Argument> arguments() const
+ { return m_arguments; }
+
+ void addArgument(Argument *argument)
+ { m_arguments.insert(argument->name(), argument); }
+
+ void setFunctionBodyScope(BlockScope *functionBodyScope)
+ { m_functionBodyScope = functionBodyScope; }
+
+ BlockScope *functionBodyScope() const
+ {return m_functionBodyScope;}
+
+ bool isSignal() const
+ { return m_signal; }
+
+ void setSignal(bool b)
+ { m_signal = b; }
+
+ bool isSlot() const
+ { return m_slot; }
+
+ void setSlot(bool b)
+ { m_slot = b; }
+
+ bool isVirtual() const
+ { return m_virtual; }
+
+ void setVirtual(bool b)
+ { m_virtual = b; }
+
+ bool isAbstract() const
+ { return m_abstract; }
+
+ void setAbstract(bool b)
+ { m_abstract = b; }
+
+private:
+ Type *m_returnType;
+ Collection<Argument> m_arguments;
+ BlockScope *m_functionBodyScope;
+ uint m_signal: 1;
+ uint m_slot: 1;
+ uint m_virtual: 1;
+ uint m_abstract: 1;
+};
+
+struct VariableMember: public Member
+{
+ VariableMember()
+ : m_type(0) {}
+
+ Type *type() const
+ { return m_type; }
+
+ void setType(Type *type)
+ { m_type = type; }
+
+ virtual VariableMember *toVariableMember() const
+ { return const_cast<VariableMember*>(this); }
+
+private:
+ Type *m_type;
+};
+
+struct UsingDeclarationMember: public Member
+{
+ UsingDeclarationMember()
+ : m_member(0) {}
+
+ virtual UsingDeclarationMember *toUsingDeclarationMember() const
+ { return const_cast<UsingDeclarationMember*>(this); }
+
+ Member *member() const
+ { return m_member; }
+
+ void setMember(Member *member)
+ { m_member = member; }
+
+private:
+ Member *m_member;
+};
+
+struct NamespaceMember: public Member
+{
+ NamespaceMember()
+ :m_namespaceScope(0) {}
+
+ virtual NamespaceMember *toNamespaceMember() const
+ { return const_cast<NamespaceMember*>(this); }
+
+ NamespaceScope *namespaceScope() const
+ { return m_namespaceScope; }
+
+ void setNamespaceScope(NamespaceScope *namespaceScope)
+ { m_namespaceScope = namespaceScope; }
+private:
+ NamespaceScope *m_namespaceScope;
+};
+
+struct TypeMember: public Member
+{
+ TypeMember()
+ :m_type(0) {}
+
+ virtual TypeMember *toTypeMember() const
+ { return const_cast<TypeMember*>(this); }
+
+ Type *type() const
+ { return m_type; }
+
+ void setType(Type *type)
+ { m_type = type; }
+private:
+ Type *m_type;
+
+};
+
+struct NameUse: public Item
+{
+ NameUse()
+ : m_declaration(0), m_parent(0) {}
+
+ QByteArray name() const
+ { return m_name; }
+
+ void setName(const QByteArray &name)
+ { m_name = name; }
+
+ TokenEngine::TokenRef nameToken() const
+ { return m_nameToken; }
+
+ void setNameToken(TokenEngine::TokenRef nameToken)
+ { m_nameToken = nameToken; }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ Member *declaration() const
+ { return m_declaration; }
+
+ void setDeclaration(Member *parent)
+ { m_declaration = parent; }
+
+private:
+ QByteArray m_name;
+ TokenEngine::TokenRef m_nameToken;
+ Member *m_declaration;
+ Scope *m_parent;
+};
+
+struct UsingDirectiveLink: public Item
+{
+ UsingDirectiveLink()
+ : m_parent(0), m_targetNamespace(0), m_insertionNamespace(0) {}
+
+ QByteArray name() const
+ { return QByteArray(); }
+
+ Scope *parent() const
+ { return m_parent; }
+
+ void setParent(Scope *parent)
+ { m_parent = parent; }
+
+ NamespaceScope *targetNamespace() const
+ { return m_targetNamespace; }
+
+ void setTargetNamespace(NamespaceScope *targetNamespace)
+ { m_targetNamespace = targetNamespace; }
+
+ NamespaceScope *insertionNamespace() const
+ { return m_insertionNamespace; }
+
+ void setInsertionNamespace(NamespaceScope *insertionNamespace)
+ { m_insertionNamespace = insertionNamespace; }
+private:
+ Scope *m_parent;
+ // targetNamespace is the namespace specified by the using directive.
+ NamespaceScope *m_targetNamespace;
+ // m_insertionNamespace is the namespace where the names from
+ // targetNamespace will be inserted. The C++ standard (7.3.4.1)
+ // defines this as the nearest namespace that includes both m_parent
+ // and m_targetNamespace.
+ NamespaceScope *m_insertionNamespace;
+};
+
+template <class T>
+T *Create(TypedPool<CodeModel::Item> *p)
+{
+ return new (p->allocate(sizeof(T))) T();
+}
+
+} // namespace CodeModel
+
+QT_END_NAMESPACE
+
+#endif // CODEMODEL_H
diff --git a/tools/porting/src/codemodelattributes.cpp b/tools/porting/src/codemodelattributes.cpp
new file mode 100644
index 0000000000..eccd11d2f9
--- /dev/null
+++ b/tools/porting/src/codemodelattributes.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "codemodelattributes.h"
+#include "tokenengine.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace CodeModel;
+using namespace TokenEngine;
+
+/*
+ Walk the codemodel.
+*/
+void CodeModelAttributes::createAttributes(TranslationUnit translationUnit)
+{
+ m_translationUnit = translationUnit;
+ parseScope(const_cast<CodeModel::NamespaceScope *>(translationUnit.codeModel()));
+}
+
+/*
+ Create attributes for each name use and assign to the token.
+*/
+void CodeModelAttributes::parseNameUse(CodeModel::NameUse *nameUse)
+{
+ // Get the container for this token.
+ TokenRef ref = nameUse->nameToken();
+ const int containerIndex = ref.containerIndex();
+ TokenAttributes *attributes = ref.tokenContainer().tokenAttributes();
+
+ if (!areAttributesEnabled(attributes))
+ return;
+
+ // Test if the nameUse refers to a UnknownType. If so we add and
+ // "unknown" attribute.
+ if (TypeMember *typeMember = nameUse->declaration()->toTypeMember()) {
+ if (typeMember->type()->toUnknownType()) {
+ attributes->addAttribute(containerIndex, "unknown", nameUse->name());
+ return;
+ }
+ }
+
+ // Add attributes this namnUse.
+ attributes->addAttribute(containerIndex, "nameUse", nameUse->name());
+ attributes->addAttribute(containerIndex, "parentScope",
+ nameUse->declaration()->parent()->name() );
+ if (CodeModel::Scope * skop = nameUse->declaration()->parent()->parent()) {
+ attributes->addAttribute(containerIndex, "grandParentScope", skop->name());
+ }
+
+ createNameTypeAttribute(nameUse);
+}
+
+/*
+ Create attributes for members and assign to token.
+*/
+void CodeModelAttributes::parseMember(CodeModel::Member *member)
+{
+ if(!member || member->name() == QByteArray())
+ return;
+
+ //get the container for this token
+ TokenRef ref = member->nameToken();
+ const int containerIndex = ref.containerIndex();
+ TokenAttributes *attributes = ref.tokenContainer().tokenAttributes();
+
+ if (areAttributesEnabled(attributes)) {
+ //add attributes for this declaration
+ static const QByteArray textDeclaration = "declaration";
+ attributes->addAttribute(containerIndex, textDeclaration, member->name());
+ createNameTypeAttribute(member);
+ }
+ CodeModelWalker::parseMember(member);
+}
+
+void CodeModelAttributes::parseFunctionMember(CodeModel::FunctionMember *member)
+{
+ CodeModel::ArgumentCollection arguments = member->arguments();
+ CodeModel::ArgumentCollection::ConstIterator it = arguments.constBegin();
+ TokenRef ref = member->nameToken();
+ TokenAttributes *attributes = ref.tokenContainer().tokenAttributes();
+
+ if (areAttributesEnabled(attributes)) {
+ while (it != arguments.constEnd()) {
+ const int containerIndex = (*it)->nameToken().containerIndex();
+ const QByteArray name = (*it)->name();
+ attributes->addAttribute(containerIndex, "declaration", name);
+ attributes->addAttribute(containerIndex, "nameType", "variable");
+ ++it;
+ }
+ }
+ CodeModelWalker::parseFunctionMember(member);
+}
+
+/*
+ NameType attributes gives information on what kind of member this is.
+*/
+void CodeModelAttributes::createNameTypeAttribute(CodeModel::Member *member)
+{
+ if(!member)
+ return;
+ //get the container for the token accosiated with this member.
+ TokenRef ref = member->nameToken();
+ const int containerIndex = ref.containerIndex();
+ TokenAttributes *attributes = ref.tokenContainer().tokenAttributes();
+
+ createNameTypeAttributeAtIndex(attributes, containerIndex, member);
+}
+
+/*
+ A NameUse has the same NameType as the declaration it is referring to.
+*/
+void CodeModelAttributes::createNameTypeAttribute(CodeModel::NameUse *nameUse)
+{
+ if(!nameUse)
+ return;
+
+ //get the container for the token accosiated with this NameUse.
+ TokenRef ref = nameUse->nameToken();
+ const int containerIndex = ref.containerIndex();
+ TokenAttributes *attributes = ref.tokenContainer().tokenAttributes();
+
+ createNameTypeAttributeAtIndex(attributes, containerIndex, nameUse->declaration());
+}
+
+void CodeModelAttributes::createNameTypeAttributeAtIndex(TokenEngine::TokenAttributes *attributes,
+ int index, CodeModel::Member *member)
+{
+ QByteArray nameType = "unknown";
+ if (member->toFunctionMember()) {
+ nameType = "function";
+ } else if (CodeModel::VariableMember *variableMember = member->toVariableMember()) {
+ if (variableMember->type()->toEnumType())
+ nameType = "enumerator";
+ else
+ nameType = "variable";
+ } else if (CodeModel::TypeMember *typeMember = member->toTypeMember()) {
+ if (CodeModel::Type *type = typeMember->type()) {
+ if (type->toClassType()) {
+ nameType = "class";
+ } else if (type->toEnumType()) {
+ nameType = "enum";
+ }
+ }
+ }
+ attributes->addAttribute(index, "nameType", nameType);
+}
+
+bool CodeModelAttributes::areAttributesEnabled(const TokenAttributes *attributes) const
+{
+ static const QByteArray tstCreateAttributes("CreateAttributes");
+ static const QByteArray tstTrue("True");
+ return (attributes->attribute(tstCreateAttributes) == tstTrue);
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/codemodelattributes.h b/tools/porting/src/codemodelattributes.h
new file mode 100644
index 0000000000..e02f3834b6
--- /dev/null
+++ b/tools/porting/src/codemodelattributes.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CODEMODELATTRIBUTES_H
+#define CODEMODELATTRIBUTES_H
+
+#include "codemodelwalker.h"
+#include "translationunit.h"
+
+QT_BEGIN_NAMESPACE
+
+class CodeModelAttributes : public CodeModelWalker
+{
+public:
+ void createAttributes(TranslationUnit translationUnit);
+protected:
+ void parseNameUse(CodeModel::NameUse *);
+ void parseMember(CodeModel::Member *member);
+ void parseFunctionMember(CodeModel::FunctionMember *member);
+
+ void createNameTypeAttribute(CodeModel::Member *member);
+ void createNameTypeAttribute(CodeModel::NameUse *nameUse);
+
+private:
+ void createNameTypeAttributeAtIndex(TokenEngine::TokenAttributes *attributes,
+ int index, CodeModel::Member *member);
+ bool areAttributesEnabled(const TokenEngine::TokenAttributes *attributes) const;
+
+ TranslationUnit m_translationUnit;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/codemodelwalker.cpp b/tools/porting/src/codemodelwalker.cpp
new file mode 100644
index 0000000000..641bc0223f
--- /dev/null
+++ b/tools/porting/src/codemodelwalker.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "codemodelwalker.h"
+
+QT_BEGIN_NAMESPACE
+using namespace CodeModel;
+
+void CodeModelWalker::parseScope(CodeModel::Scope *scope)
+{
+ if(!scope)
+ return;
+
+ if(scope->toClassScope())
+ parseClassScope(scope->toClassScope());
+ if(scope->toNamespaceScope())
+ parseNamespaceScope(scope->toNamespaceScope());
+ if(scope->toBlockScope())
+ parseBlockScope(scope->toBlockScope());
+
+
+ {
+ MemberCollection collection = scope->members();
+ MemberCollection::ConstIterator it = collection.constBegin();
+ while(it != collection.constEnd())
+ parseMember(*it++);
+ }
+ {
+ ScopeCollection collection = scope->scopes();
+ ScopeCollection::ConstIterator it = collection.constBegin();
+ while(it != collection.constEnd())
+ parseScope(*it++);
+ }
+ {
+ NameUseCollection collection = scope->nameUses();
+ NameUseCollection::ConstIterator it = collection.constBegin();
+ while(it != collection.constEnd())
+ parseNameUse(*it++);
+ }
+}
+
+void CodeModelWalker::parseType(CodeModel::Type *type)
+{
+ if(!type)
+ return;
+ if (type->toEnumType())
+ parseEnumType(type->toEnumType());
+ else if (type->toClassType())
+ parseClassType(type->toClassType());
+ else if (type->toBuiltinType())
+ parseBuiltinType(type->toBuiltinType());
+ else if (type->toPointerType())
+ parsePointerType(type->toPointerType());
+ else if (type->toReferenceType())
+ parseReferenceType(type->toReferenceType());
+ else if (type->toGenericType())
+ parseGenericType(type->toGenericType());
+ else if (type->toAliasType())
+ parseAliasType(type->toAliasType());
+ else if (type->toUnknownType())
+ parseUnknownType(type->toUnknownType());
+}
+
+void CodeModelWalker::parseMember(CodeModel::Member *member)
+{
+ if(!member)
+ return;
+
+ if (member->toFunctionMember())
+ parseFunctionMember(member->toFunctionMember());
+ else if (member->toVariableMember())
+ parseVariableMember(member->toVariableMember());
+ else if (member->toUsingDeclarationMember())
+ parseUsingDeclarationMember(member->toUsingDeclarationMember());
+ else if (member->toTypeMember())
+ parseTypeMember(member->toTypeMember());
+}
+
+void CodeModelWalker::parseFunctionMember(CodeModel::FunctionMember *member)
+{
+ if(!member)
+ return;
+ if(member->functionBodyScope())
+ parseScope(member->functionBodyScope());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/codemodelwalker.h b/tools/porting/src/codemodelwalker.h
new file mode 100644
index 0000000000..446ea93b82
--- /dev/null
+++ b/tools/porting/src/codemodelwalker.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CODEMODELWALKER_H
+#define CODEMODELWALKER_H
+
+#include "codemodel.h"
+
+QT_BEGIN_NAMESPACE
+
+class CodeModelWalker
+{
+public:
+ virtual ~CodeModelWalker(){};
+ virtual void parseScope(CodeModel::Scope *scope);
+ virtual void parseClassScope(CodeModel::ClassScope *){};
+ virtual void parseNamespaceScope(CodeModel::NamespaceScope *){};
+ virtual void parseBlockScope(CodeModel::BlockScope *){};
+
+ virtual void parseType(CodeModel::Type *type);
+ virtual void parseEnumType(CodeModel::EnumType *){};
+ virtual void parseClassType(CodeModel::ClassType *){};
+ virtual void parseUnknownType(CodeModel::UnknownType *){};
+ virtual void parseBuiltinType(CodeModel::BuiltinType *){};
+ virtual void parsePointerType(CodeModel::PointerType *){};
+ virtual void parseReferenceType(CodeModel::ReferenceType *){};
+ virtual void parseGenericType(CodeModel::GenericType *){};
+ virtual void parseAliasType(CodeModel::AliasType *){};
+
+ virtual void parseMember(CodeModel::Member *member);
+ virtual void parseFunctionMember(CodeModel::FunctionMember *);
+ virtual void parseVariableMember(CodeModel::VariableMember *){};
+ virtual void parseUsingDeclarationMember(CodeModel::UsingDeclarationMember *){};
+ virtual void parseTypeMember(CodeModel::TypeMember *){};
+
+ virtual void parseArgument(CodeModel::Argument *){};
+ virtual void parseNameUse(CodeModel::NameUse *){};
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/cpplexer.cpp b/tools/porting/src/cpplexer.cpp
new file mode 100644
index 0000000000..ef6353814a
--- /dev/null
+++ b/tools/porting/src/cpplexer.cpp
@@ -0,0 +1,1297 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "cpplexer.h"
+#include <QChar>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+
+CppLexer::CppLexer()
+ : m_buffer(0), m_ptr(0), m_len(0)
+{
+ setupScanTable();
+}
+
+void CppLexer::setupScanTable()
+{
+ s_scan_keyword_table[0] = &CppLexer::scanKeyword0;
+ s_scan_keyword_table[1] = &CppLexer::scanKeyword0;
+ s_scan_keyword_table[2] = &CppLexer::scanKeyword2;
+ s_scan_keyword_table[3] = &CppLexer::scanKeyword3;
+ s_scan_keyword_table[4] = &CppLexer::scanKeyword4;
+ s_scan_keyword_table[5] = &CppLexer::scanKeyword5;
+ s_scan_keyword_table[6] = &CppLexer::scanKeyword6;
+ s_scan_keyword_table[7] = &CppLexer::scanKeyword7;
+ s_scan_keyword_table[8] = &CppLexer::scanKeyword8;
+ s_scan_keyword_table[9] = &CppLexer::scanKeyword9;
+ s_scan_keyword_table[10] = &CppLexer::scanKeyword10;
+ s_scan_keyword_table[11] = &CppLexer::scanKeyword11;
+ s_scan_keyword_table[12] = &CppLexer::scanKeyword12;
+ s_scan_keyword_table[13] = &CppLexer::scanKeyword0;
+ s_scan_keyword_table[14] = &CppLexer::scanKeyword14;
+ s_scan_keyword_table[15] = &CppLexer::scanKeyword0;
+ s_scan_keyword_table[16] = &CppLexer::scanKeyword16;
+
+ memset(s_attr_table, 0, 256);
+
+ for (int i=0; i<128; ++i) {
+ switch (i) {
+ case ':':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ case '=':
+ case '!':
+ case '&':
+ case '|':
+ case '+':
+ case '<':
+ case '>':
+ case '-':
+ case '.':
+ s_scan_table[i] = &CppLexer::scanOperator;
+ break;
+
+ case '\r':
+ case '\n':
+ s_scan_table[i] = &CppLexer::scanNewline;
+ break;
+
+ case '\'':
+ s_scan_table[i] = &CppLexer::scanCharLiteral;
+ break;
+
+ case '"':
+ s_scan_table[i] = &CppLexer::scanStringLiteral;
+ break;
+
+ default:
+ if (isspace(i)) {
+ s_scan_table[i] = &CppLexer::scanWhiteSpaces;
+ s_attr_table[i] |= A_Whitespace;
+ } else if (isalpha(i) || i == '_') {
+ s_scan_table[i] = &CppLexer::scanIdentifier;
+ s_attr_table[i] |= A_Alpha;
+ } else if (isdigit(i)) {
+ s_scan_table[i] = &CppLexer::scanNumberLiteral;
+ s_attr_table[i] |= A_Digit;
+ } else
+ s_scan_table[i] = &CppLexer::scanChar;
+ }
+ }
+
+ s_scan_table[128] = &CppLexer::scanUnicodeChar;
+}
+
+QVector<Type> CppLexer::lex(TokenSectionSequence tokenSectionSequence)
+{
+ QVector<Type> tokenTypes;
+ tokenTypes.reserve(tokenSectionSequence.count());
+ TokenSectionSequenceIterator it(tokenSectionSequence);
+ while(it.nextToken()) {
+ tokenTypes.append(identify(it.tokenTempRef()));
+ }
+ return tokenTypes;
+}
+
+Type CppLexer::identify(const TokenTempRef &tokenTempRef)
+{
+ Q_ASSERT(tokenTempRef.length() >= 0 );
+ m_buffer = tokenTempRef.constData();
+ m_len = tokenTempRef.length();
+ m_ptr = 0;
+ const unsigned char ch = m_buffer[0];
+ int kind = 0;
+ (this->*s_scan_table[ch < 128 ? ch : 128])(&kind);
+ return (Type)kind;
+}
+
+void CppLexer::scanKeyword0(int *kind)
+{
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword2(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'i':
+ if (m_buffer[m_ptr+1] == 'f')
+ {
+ *kind = Token_if;
+ return;
+ }
+ break;
+
+ case 'd':
+ if (m_buffer[m_ptr+1] == 'o')
+ {
+ *kind = Token_do;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (m_buffer[m_ptr+1] == 'r')
+ {
+ *kind = Token_or;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword3(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'a':
+ if (m_buffer[m_ptr+1] == 'n' &&
+ m_buffer[m_ptr+2] == 'd')
+ {
+ *kind = Token_and;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 's' &&
+ m_buffer[m_ptr+2] == 'm')
+ {
+ *kind = Token_asm;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'r')
+ {
+ *kind = Token_for;
+ return;
+ }
+ break;
+
+ case 'i':
+ if (m_buffer[m_ptr+1] == 'n' &&
+ m_buffer[m_ptr+2] == 't')
+ {
+ *kind = Token_int;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (m_buffer[m_ptr+1] == 'e' &&
+ m_buffer[m_ptr+2] == 'w')
+ {
+ *kind = Token_new;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 't')
+ {
+ *kind = Token_not;
+ return;
+ }
+ break;
+
+ case 't':
+ if (m_buffer[m_ptr+1] == 'r' &&
+ m_buffer[m_ptr+2] == 'y')
+ {
+ *kind = Token_try;
+ return;
+ }
+ break;
+
+ case 'x':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'r')
+ {
+ *kind = Token_xor;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword4(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'a':
+ if (m_buffer[m_ptr+1] == 'u' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'o')
+ {
+ *kind = Token_auto;
+ return;
+ }
+ break;
+
+ case 'c':
+ if (m_buffer[m_ptr+1] == 'a' &&
+ m_buffer[m_ptr+2] == 's' &&
+ m_buffer[m_ptr+3] == 'e')
+ {
+ *kind = Token_case;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'h' &&
+ m_buffer[m_ptr+2] == 'a' &&
+ m_buffer[m_ptr+3] == 'r')
+ {
+ *kind = Token_char;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'o' &&
+ m_buffer[m_ptr+3] == 'l')
+ {
+ *kind = Token_bool;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (m_buffer[m_ptr+1] == 'l' &&
+ m_buffer[m_ptr+2] == 's' &&
+ m_buffer[m_ptr+3] == 'e')
+ {
+ *kind = Token_else;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'm' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 't')
+ {
+ *kind = Token_emit;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'n' &&
+ m_buffer[m_ptr+2] == 'u' &&
+ m_buffer[m_ptr+3] == 'm')
+ {
+ *kind = Token_enum;
+ return;
+ }
+ break;
+
+ case 'g':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'o')
+ {
+ *kind = Token_goto;
+ return;
+ }
+ break;
+
+ case 'l':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'n' &&
+ m_buffer[m_ptr+3] == 'g')
+ {
+ *kind = Token_long;
+ return;
+ }
+ break;
+
+ case 't':
+ if (m_buffer[m_ptr+1] == 'h' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 's')
+ {
+ *kind = Token_this;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 'd')
+ {
+ *kind = Token_void;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword5(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'c':
+ if (m_buffer[m_ptr+1] == 'a' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'c' &&
+ m_buffer[m_ptr+4] == 'h')
+ {
+ *kind = Token_catch;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'l' &&
+ m_buffer[m_ptr+2] == 'a' &&
+ m_buffer[m_ptr+3] == 's' &&
+ m_buffer[m_ptr+4] == 's')
+ {
+ *kind = Token_class;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'm' &&
+ m_buffer[m_ptr+3] == 'p' &&
+ m_buffer[m_ptr+4] == 'l')
+ {
+ *kind = Token_compl;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'n' &&
+ m_buffer[m_ptr+3] == 's' &&
+ m_buffer[m_ptr+4] == 't')
+ {
+ *kind = Token_const;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (m_buffer[m_ptr+1] == 'i' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'o' &&
+ m_buffer[m_ptr+4] == 'r')
+ {
+ *kind = Token_bitor;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'r' &&
+ m_buffer[m_ptr+2] == 'e' &&
+ m_buffer[m_ptr+3] == 'a' &&
+ m_buffer[m_ptr+4] == 'k')
+ {
+ *kind = Token_break;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (m_buffer[m_ptr+1] == 'l' &&
+ m_buffer[m_ptr+2] == 'o' &&
+ m_buffer[m_ptr+3] == 'a' &&
+ m_buffer[m_ptr+4] == 't')
+ {
+ *kind = Token_float;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (m_buffer[m_ptr+1] == 'r' &&
+ m_buffer[m_ptr+2] == '_' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 'q')
+ {
+ *kind = Token_or_eq;
+ return;
+ }
+ break;
+
+ case 's':
+ if (m_buffer[m_ptr+1] == 'h' &&
+ m_buffer[m_ptr+2] == 'o' &&
+ m_buffer[m_ptr+3] == 'r' &&
+ m_buffer[m_ptr+4] == 't')
+ {
+ *kind = Token_short;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'l' &&
+ m_buffer[m_ptr+2] == 'o' &&
+ m_buffer[m_ptr+3] == 't' &&
+ m_buffer[m_ptr+4] == 's')
+ {
+ *kind = Token_slots;
+ return;
+ }
+ break;
+
+ case 'u':
+ if (m_buffer[m_ptr+1] == 'n' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 'o' &&
+ m_buffer[m_ptr+4] == 'n')
+ {
+ *kind = Token_union;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 's' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 'n' &&
+ m_buffer[m_ptr+4] == 'g')
+ {
+ *kind = Token_using;
+ return;
+ }
+ break;
+
+ case 't':
+ if (m_buffer[m_ptr+1] == 'h' &&
+ m_buffer[m_ptr+2] == 'r' &&
+ m_buffer[m_ptr+3] == 'o' &&
+ m_buffer[m_ptr+4] == 'w')
+ {
+ *kind = Token_throw;
+ return;
+ }
+ break;
+
+ case 'w':
+ if (m_buffer[m_ptr+1] == 'h' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 'l' &&
+ m_buffer[m_ptr+4] == 'e')
+ {
+ *kind = Token_while;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword6(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'a':
+ if (m_buffer[m_ptr+1] == 'n' &&
+ m_buffer[m_ptr+2] == 'd' &&
+ m_buffer[m_ptr+3] == '_' &&
+ m_buffer[m_ptr+4] == 'e' &&
+ m_buffer[m_ptr+5] == 'q')
+ {
+ *kind = Token_and_eq;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (m_buffer[m_ptr+1] == 'i' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'a' &&
+ m_buffer[m_ptr+4] == 'n' &&
+ m_buffer[m_ptr+5] == 'd')
+ {
+ *kind = Token_bitand;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (m_buffer[m_ptr+1] == 'x' &&
+ m_buffer[m_ptr+2] == 'p' &&
+ m_buffer[m_ptr+3] == 'o' &&
+ m_buffer[m_ptr+4] == 'r' &&
+ m_buffer[m_ptr+5] == 't')
+ {
+ *kind = Token_export;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'x' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 'r' &&
+ m_buffer[m_ptr+5] == 'n')
+ {
+ *kind = Token_extern;
+ return;
+ }
+ break;
+
+ case 'd':
+ if (m_buffer[m_ptr+1] == 'e' &&
+ m_buffer[m_ptr+2] == 'l' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 't' &&
+ m_buffer[m_ptr+5] == 'e')
+ {
+ *kind = Token_delete;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'u' &&
+ m_buffer[m_ptr+3] == 'b' &&
+ m_buffer[m_ptr+4] == 'l' &&
+ m_buffer[m_ptr+5] == 'e')
+ {
+ *kind = Token_double;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (m_buffer[m_ptr+1] == 'r' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 'n' &&
+ m_buffer[m_ptr+5] == 'd')
+ {
+ *kind = Token_friend;
+ return;
+ }
+ break;
+
+ case 'i':
+ if (m_buffer[m_ptr+1] == 'n' &&
+ m_buffer[m_ptr+2] == 'l' &&
+ m_buffer[m_ptr+3] == 'i' &&
+ m_buffer[m_ptr+4] == 'n' &&
+ m_buffer[m_ptr+5] == 'e')
+ {
+ *kind = Token_inline;
+ return;
+ }
+ break;
+
+ case 'K':
+ if (m_buffer[m_ptr+1] == '_' &&
+ m_buffer[m_ptr+2] == 'D' &&
+ m_buffer[m_ptr+3] == 'C' &&
+ m_buffer[m_ptr+4] == 'O' &&
+ m_buffer[m_ptr+5] == 'P')
+ {
+ *kind = Token_K_DCOP;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == '_' &&
+ m_buffer[m_ptr+4] == 'e' &&
+ m_buffer[m_ptr+5] == 'q')
+ {
+ *kind = Token_not_eq;
+ return;
+ }
+ break;
+
+ case 'p':
+ if (m_buffer[m_ptr+1] == 'u' &&
+ m_buffer[m_ptr+2] == 'b' &&
+ m_buffer[m_ptr+3] == 'l' &&
+ m_buffer[m_ptr+4] == 'i' &&
+ m_buffer[m_ptr+5] == 'c')
+ {
+ *kind = Token_public;
+ return;
+ }
+ break;
+
+ case 's':
+ if (m_buffer[m_ptr+1] == 'i' &&
+ m_buffer[m_ptr+2] == 'g' &&
+ m_buffer[m_ptr+3] == 'n' &&
+ m_buffer[m_ptr+4] == 'e' &&
+ m_buffer[m_ptr+5] == 'd')
+ {
+ *kind = Token_signed;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'i' &&
+ m_buffer[m_ptr+2] == 'z' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 'o' &&
+ m_buffer[m_ptr+5] == 'f')
+ {
+ *kind = Token_sizeof;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 't' &&
+ m_buffer[m_ptr+2] == 'a' &&
+ m_buffer[m_ptr+3] == 't' &&
+ m_buffer[m_ptr+4] == 'i' &&
+ m_buffer[m_ptr+5] == 'c')
+ {
+ *kind = Token_static;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 't' &&
+ m_buffer[m_ptr+2] == 'r' &&
+ m_buffer[m_ptr+3] == 'u' &&
+ m_buffer[m_ptr+4] == 'c' &&
+ m_buffer[m_ptr+5] == 't')
+ {
+ *kind = Token_struct;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'w' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 't' &&
+ m_buffer[m_ptr+4] == 'c' &&
+ m_buffer[m_ptr+5] == 'h')
+ {
+ *kind = Token_switch;
+ return;
+ }
+ break;
+
+ case 'r':
+ if (m_buffer[m_ptr+1] == 'e' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'u' &&
+ m_buffer[m_ptr+4] == 'r' &&
+ m_buffer[m_ptr+5] == 'n')
+ {
+ *kind = Token_return;
+ return;
+ }
+ break;
+
+ case 't':
+ if (m_buffer[m_ptr+1] == 'y' &&
+ m_buffer[m_ptr+2] == 'p' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 'i' &&
+ m_buffer[m_ptr+5] == 'd')
+ {
+ *kind = Token_typeid;
+ return;
+ }
+ break;
+
+ case 'x':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'r' &&
+ m_buffer[m_ptr+3] == '_' &&
+ m_buffer[m_ptr+4] == 'e' &&
+ m_buffer[m_ptr+5] == 'q')
+ {
+ *kind = Token_xor_eq;
+ return;
+ }
+ break;
+
+ case 'k':
+ if (m_buffer[m_ptr+1] == '_' &&
+ m_buffer[m_ptr+2] == 'd' &&
+ m_buffer[m_ptr+3] == 'c' &&
+ m_buffer[m_ptr+4] == 'o' &&
+ m_buffer[m_ptr+5] == 'p')
+ {
+ *kind = Token_k_dcop;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword7(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'd':
+ if (m_buffer[m_ptr+1] == 'e' &&
+ m_buffer[m_ptr+2] == 'f' &&
+ m_buffer[m_ptr+3] == 'a' &&
+ m_buffer[m_ptr+4] == 'u' &&
+ m_buffer[m_ptr+5] == 'l' &&
+ m_buffer[m_ptr+6] == 't')
+ {
+ *kind = Token_default;
+ return;
+ }
+ break;
+
+ case 'm':
+ if (m_buffer[m_ptr+1] == 'u' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'a' &&
+ m_buffer[m_ptr+4] == 'b' &&
+ m_buffer[m_ptr+5] == 'l' &&
+ m_buffer[m_ptr+6] == 'e')
+ {
+ *kind = Token_mutable;
+ return;
+ }
+ break;
+
+ case 'p':
+ if (m_buffer[m_ptr+1] == 'r' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 'v' &&
+ m_buffer[m_ptr+4] == 'a' &&
+ m_buffer[m_ptr+5] == 't' &&
+ m_buffer[m_ptr+6] == 'e')
+ {
+ *kind = Token_private;
+ return;
+ }
+ break;
+#if 0
+ case 's':
+ if (m_buffer[m_ptr+1] == 'i' &&
+ m_buffer[m_ptr+2] == 'g' &&
+ m_buffer[m_ptr+3] == 'n' &&
+ m_buffer[m_ptr+4] == 'a' &&
+ m_buffer[m_ptr+5] == 'l' &&
+ m_buffer[m_ptr+6] == 's')
+ {
+ *kind = Token_signals;
+ return;
+ }
+ break;
+#endif
+ case 't':
+ if (m_buffer[m_ptr+1] == 'y' &&
+ m_buffer[m_ptr+2] == 'p' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 'd' &&
+ m_buffer[m_ptr+5] == 'e' &&
+ m_buffer[m_ptr+6] == 'f')
+ {
+ *kind = Token_typedef;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (m_buffer[m_ptr+1] == 'i' &&
+ m_buffer[m_ptr+2] == 'r' &&
+ m_buffer[m_ptr+3] == 't' &&
+ m_buffer[m_ptr+4] == 'u' &&
+ m_buffer[m_ptr+5] == 'a' &&
+ m_buffer[m_ptr+6] == 'l')
+ {
+ *kind = Token_virtual;
+ return;
+ }
+ break;
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword8(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case '_':
+ if (m_buffer[m_ptr+1] == '_' &&
+ m_buffer[m_ptr+2] == 't' &&
+ m_buffer[m_ptr+3] == 'y' &&
+ m_buffer[m_ptr+4] == 'p' &&
+ m_buffer[m_ptr+5] == 'e' &&
+ m_buffer[m_ptr+6] == 'o' &&
+ m_buffer[m_ptr+7] == 'f')
+ {
+ *kind = Token___typeof;
+ return;
+ }
+ break;
+
+ case 'c':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'n' &&
+ m_buffer[m_ptr+3] == 't' &&
+ m_buffer[m_ptr+4] == 'i' &&
+ m_buffer[m_ptr+5] == 'n' &&
+ m_buffer[m_ptr+6] == 'u' &&
+ m_buffer[m_ptr+7] == 'e')
+ {
+ *kind = Token_continue;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (m_buffer[m_ptr+1] == 'x' &&
+ m_buffer[m_ptr+2] == 'p' &&
+ m_buffer[m_ptr+3] == 'l' &&
+ m_buffer[m_ptr+4] == 'i' &&
+ m_buffer[m_ptr+5] == 'c' &&
+ m_buffer[m_ptr+6] == 'i' &&
+ m_buffer[m_ptr+7] == 't')
+ {
+ *kind = Token_explicit;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (m_buffer[m_ptr+1] == 'p' &&
+ m_buffer[m_ptr+2] == 'e' &&
+ m_buffer[m_ptr+3] == 'r' &&
+ m_buffer[m_ptr+4] == 'a' &&
+ m_buffer[m_ptr+5] == 't' &&
+ m_buffer[m_ptr+6] == 'o' &&
+ m_buffer[m_ptr+7] == 'r')
+ {
+ *kind = Token_operator;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (m_buffer[m_ptr+1] == '_' &&
+ m_buffer[m_ptr+2] == 'O' &&
+ m_buffer[m_ptr+3] == 'B' &&
+ m_buffer[m_ptr+4] == 'J' &&
+ m_buffer[m_ptr+5] == 'E' &&
+ m_buffer[m_ptr+6] == 'C' &&
+ m_buffer[m_ptr+7] == 'T')
+ {
+ *kind = Token_Q_OBJECT;
+ return;
+ }
+ break;
+
+ case 'r':
+ if (m_buffer[m_ptr+1] == 'e' &&
+ m_buffer[m_ptr+2] == 'g' &&
+ m_buffer[m_ptr+3] == 'i' &&
+ m_buffer[m_ptr+4] == 's' &&
+ m_buffer[m_ptr+5] == 't' &&
+ m_buffer[m_ptr+6] == 'e' &&
+ m_buffer[m_ptr+7] == 'r')
+ {
+ *kind = Token_register;
+ return;
+ }
+ break;
+
+ case 'u':
+ if (m_buffer[m_ptr+1] == 'n' &&
+ m_buffer[m_ptr+2] == 's' &&
+ m_buffer[m_ptr+3] == 'i' &&
+ m_buffer[m_ptr+4] == 'g' &&
+ m_buffer[m_ptr+5] == 'n' &&
+ m_buffer[m_ptr+6] == 'e' &&
+ m_buffer[m_ptr+7] == 'd')
+ {
+ *kind = Token_unsigned;
+ return;
+ }
+ break;
+
+ case 't':
+ if (m_buffer[m_ptr+1] == 'e' &&
+ m_buffer[m_ptr+2] == 'm' &&
+ m_buffer[m_ptr+3] == 'p' &&
+ m_buffer[m_ptr+4] == 'l' &&
+ m_buffer[m_ptr+5] == 'a' &&
+ m_buffer[m_ptr+6] == 't' &&
+ m_buffer[m_ptr+7] == 'e')
+ {
+ *kind = Token_template;
+ return;
+ }
+ if (m_buffer[m_ptr+1] == 'y' &&
+ m_buffer[m_ptr+2] == 'p' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 'n' &&
+ m_buffer[m_ptr+5] == 'a' &&
+ m_buffer[m_ptr+6] == 'm' &&
+ m_buffer[m_ptr+7] == 'e')
+ {
+ *kind = Token_typename;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'l' &&
+ m_buffer[m_ptr+3] == 'a' &&
+ m_buffer[m_ptr+4] == 't' &&
+ m_buffer[m_ptr+5] == 'i' &&
+ m_buffer[m_ptr+6] == 'l' &&
+ m_buffer[m_ptr+7] == 'e')
+ {
+ *kind = Token_volatile;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword9(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'p':
+ if (m_buffer[m_ptr+1] == 'r' &&
+ m_buffer[m_ptr+2] == 'o' &&
+ m_buffer[m_ptr+3] == 't' &&
+ m_buffer[m_ptr+4] == 'e' &&
+ m_buffer[m_ptr+5] == 'c' &&
+ m_buffer[m_ptr+6] == 't' &&
+ m_buffer[m_ptr+7] == 'e' &&
+ m_buffer[m_ptr+8] == 'd')
+ {
+ *kind = Token_protected;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (m_buffer[m_ptr+1] == 'a' &&
+ m_buffer[m_ptr+2] == 'm' &&
+ m_buffer[m_ptr+3] == 'e' &&
+ m_buffer[m_ptr+4] == 's' &&
+ m_buffer[m_ptr+5] == 'p' &&
+ m_buffer[m_ptr+6] == 'a' &&
+ m_buffer[m_ptr+7] == 'c' &&
+ m_buffer[m_ptr+8] == 'e')
+ {
+ *kind = Token_namespace;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword10(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'c':
+ if (m_buffer[m_ptr+1] == 'o' &&
+ m_buffer[m_ptr+2] == 'n' &&
+ m_buffer[m_ptr+3] == 's' &&
+ m_buffer[m_ptr+4] == 't' &&
+ m_buffer[m_ptr+5] == '_' &&
+ m_buffer[m_ptr+6] == 'c' &&
+ m_buffer[m_ptr+7] == 'a' &&
+ m_buffer[m_ptr+8] == 's' &&
+ m_buffer[m_ptr+9] == 't')
+ {
+ *kind = Token_const_cast;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword11(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 's':
+ if (m_buffer[m_ptr+1] == 't' &&
+ m_buffer[m_ptr+2] == 'a' &&
+ m_buffer[m_ptr+3] == 't' &&
+ m_buffer[m_ptr+4] == 'i' &&
+ m_buffer[m_ptr+5] == 'c' &&
+ m_buffer[m_ptr+6] == '_' &&
+ m_buffer[m_ptr+7] == 'c' &&
+ m_buffer[m_ptr+8] == 'a' &&
+ m_buffer[m_ptr+9] == 's' &&
+ m_buffer[m_ptr+10] == 't')
+ {
+ *kind = Token_static_cast;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword12(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'd':
+ if (m_buffer[m_ptr+1] == 'y' &&
+ m_buffer[m_ptr+2] == 'n' &&
+ m_buffer[m_ptr+3] == 'a' &&
+ m_buffer[m_ptr+4] == 'm' &&
+ m_buffer[m_ptr+5] == 'i' &&
+ m_buffer[m_ptr+6] == 'c' &&
+ m_buffer[m_ptr+7] == '_' &&
+ m_buffer[m_ptr+8] == 'c' &&
+ m_buffer[m_ptr+9] == 'a' &&
+ m_buffer[m_ptr+10] == 's' &&
+ m_buffer[m_ptr+11] == 't')
+ {
+ *kind = Token_dynamic_cast;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword14(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'k':
+ if (m_buffer[m_ptr+1] == '_' &&
+ m_buffer[m_ptr+2] == 'd' &&
+ m_buffer[m_ptr+3] == 'c' &&
+ m_buffer[m_ptr+4] == 'o' &&
+ m_buffer[m_ptr+5] == 'p' &&
+ m_buffer[m_ptr+6] == '_' &&
+ m_buffer[m_ptr+7] == 's' &&
+ m_buffer[m_ptr+8] == 'i' &&
+ m_buffer[m_ptr+9] == 'g' &&
+ m_buffer[m_ptr+10] == 'n' &&
+ m_buffer[m_ptr+11] == 'a' &&
+ m_buffer[m_ptr+12] == 'l' &&
+ m_buffer[m_ptr+13] == 's')
+ {
+ *kind = Token_k_dcop_signals;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+void CppLexer::scanKeyword16(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case 'r':
+ if (m_buffer[m_ptr+1] == 'e' &&
+ m_buffer[m_ptr+2] == 'i' &&
+ m_buffer[m_ptr+3] == 'n' &&
+ m_buffer[m_ptr+4] == 't' &&
+ m_buffer[m_ptr+5] == 'e' &&
+ m_buffer[m_ptr+6] == 'r' &&
+ m_buffer[m_ptr+7] == 'p' &&
+ m_buffer[m_ptr+8] == 'r' &&
+ m_buffer[m_ptr+9] == 'e' &&
+ m_buffer[m_ptr+10] == 't' &&
+ m_buffer[m_ptr+11] == '_' &&
+ m_buffer[m_ptr+12] == 'c' &&
+ m_buffer[m_ptr+13] == 'a' &&
+ m_buffer[m_ptr+14] == 's' &&
+ m_buffer[m_ptr+15] == 't')
+ {
+ *kind = Token_reinterpret_cast;
+ return;
+ }
+ break;
+
+ }
+ *kind = Token_identifier;
+}
+
+
+
+void CppLexer::scanChar(int *kind)
+{
+ *kind = m_buffer[m_ptr++];
+}
+
+void CppLexer::scanWhiteSpaces(int *kind)
+{
+ *kind = Token_whitespaces;
+}
+
+void CppLexer::scanNewline(int *kind)
+{
+ *kind = '\n';
+}
+
+void CppLexer::scanUnicodeChar(int *kind)
+{
+ *kind = m_buffer[0];
+}
+
+void CppLexer::scanCharLiteral(int *kind)
+{
+ *kind = Token_char_literal;
+}
+
+void CppLexer::scanStringLiteral(int *kind)
+{
+ *kind = Token_string_literal;
+}
+
+void CppLexer::scanIdentifier(int *kind)
+{
+ if (m_len <16)
+ (this->*s_scan_keyword_table[m_len])(kind);
+ else
+ (this->*s_scan_keyword_table[0])(kind);
+}
+
+void CppLexer::scanNumberLiteral(int *kind)
+{
+ *kind = Token_number_literal;
+}
+
+void CppLexer::scanOperator(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case ':':
+ if (m_buffer[m_ptr+1] == ':') {
+ *kind = Token_scope;
+ return;
+ }
+ break;
+
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '=':
+ case '!':
+ if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_eq;
+ return;
+ }
+ break;
+
+ case '&':
+ if (m_buffer[m_ptr+1] == '&') {
+ *kind = Token_and;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '|':
+ if (m_buffer[m_ptr+1] == '|' ) {
+ *kind = Token_or;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '+':
+ if (m_buffer[m_ptr+1] == '+' ) {
+ *kind = Token_incr;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '<':
+ if (m_buffer[m_ptr+1] == '<') {
+ if (m_buffer[m_ptr+2] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ *kind = Token_shift;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_leq;
+ return;
+ }
+ break;
+
+ case '>':
+ if (m_buffer[m_ptr+1] == '>') {
+ if (m_buffer[m_ptr+2] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ *kind = Token_shift;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_geq;
+ return;
+ }
+ break;
+
+ case '-':
+ if (m_buffer[m_ptr+1] == '>') {
+ if (m_buffer[m_ptr+2] == '*') {
+ *kind = Token_ptrmem;
+ return;
+ }
+ *kind = Token_arrow;
+ return;
+ } else if (m_buffer[m_ptr+1] == '-') {
+ *kind = Token_decr;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '.':
+ if (m_buffer[m_ptr+1] == '.' && m_buffer[m_ptr+2] == '.') {
+ *kind = Token_ellipsis;
+ return;
+ } else if (m_buffer[m_ptr+1] == '*') {
+ *kind = Token_ptrmem;
+ return;
+ }
+ break;
+
+ }
+
+ *kind = m_buffer[m_ptr++];
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/cpplexer.h b/tools/porting/src/cpplexer.h
new file mode 100644
index 0000000000..ae84f1dbe1
--- /dev/null
+++ b/tools/porting/src/cpplexer.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CPPLEXER_H
+#define CPPLEXER_H
+
+#include "tokenengine.h"
+#include "tokens.h"
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+class CppLexer
+{
+public:
+ CppLexer();
+ typedef void (CppLexer::*scan_fun_ptr)(int *kind);
+ QVector<Type> lex(TokenEngine::TokenSectionSequence tokenContainer);
+private:
+ Type identify(const TokenEngine::TokenTempRef &tokenTempRef);
+ void setupScanTable();
+
+ void scanChar(int *kind);
+ void scanUnicodeChar(int *kind);
+ void scanNewline(int *kind);
+ void scanWhiteSpaces(int *kind);
+ void scanCharLiteral(int *kind);
+ void scanStringLiteral(int *kind);
+ void scanNumberLiteral(int *kind);
+ void scanIdentifier(int *kind);
+ void scanPreprocessor(int *kind);
+ void scanOperator(int *kind);
+
+ void scanKeyword0(int *kind);
+ void scanKeyword2(int *kind);
+ void scanKeyword3(int *kind);
+ void scanKeyword4(int *kind);
+ void scanKeyword5(int *kind);
+ void scanKeyword6(int *kind);
+ void scanKeyword7(int *kind);
+ void scanKeyword8(int *kind);
+ void scanKeyword9(int *kind);
+ void scanKeyword10(int *kind);
+ void scanKeyword11(int *kind);
+ void scanKeyword12(int *kind);
+ void scanKeyword14(int *kind);
+ void scanKeyword16(int *kind);
+
+ CppLexer::scan_fun_ptr s_scan_table[128+1];
+ int s_attr_table[256];
+ CppLexer::scan_fun_ptr s_scan_keyword_table[17];
+
+ enum
+ {
+ A_Alpha = 0x01,
+ A_Digit = 0x02,
+ A_Alphanum = A_Alpha | A_Digit,
+ A_Whitespace = 0x04
+ };
+
+ const char *m_buffer;
+ int m_ptr;
+ int m_len;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/errors.cpp b/tools/porting/src/errors.cpp
new file mode 100644
index 0000000000..76292c9c51
--- /dev/null
+++ b/tools/porting/src/errors.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "errors.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_STATIC_CONST_IMPL Error& Errors::InternalError = Error( 1, -1, QLatin1String("Internal Error") );
+QT_STATIC_CONST_IMPL Error& Errors::SyntaxError = Error( 2, -1, QLatin1String("Syntax Error before '%1'") );
+QT_STATIC_CONST_IMPL Error& Errors::ParseError = Error( 3, -1, QLatin1String("Parse Error before '%1'") );
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/errors.h b/tools/porting/src/errors.h
new file mode 100644
index 0000000000..11c23765ce
--- /dev/null
+++ b/tools/porting/src/errors.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ERRORS_H
+#define ERRORS_H
+
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+class Error
+{
+public:
+ int code;
+ int level;
+ QString text;
+
+ inline Error(int c, int l, const QString &s)
+ : code(c), level(l), text(s) {}
+};
+
+class Errors
+{
+public:
+ QT_STATIC_CONST Error& InternalError;
+ QT_STATIC_CONST Error& SyntaxError;
+ QT_STATIC_CONST Error& ParseError;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/fileporter.cpp b/tools/porting/src/fileporter.cpp
new file mode 100644
index 0000000000..9a5a458ba7
--- /dev/null
+++ b/tools/porting/src/fileporter.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "preprocessorcontrol.h"
+#include "fileporter.h"
+#include "replacetoken.h"
+#include "logger.h"
+#include "tokenizer.h"
+#include "filewriter.h"
+#include <QFile>
+#include <QDir>
+#include <QFileInfo>
+#include <QHash>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+using namespace Rpp;
+
+FilePorter::FilePorter(PreprocessorCache &preprocessorCache)
+:preprocessorCache(preprocessorCache)
+,tokenReplacementRules(PortingRules::instance()->getTokenReplacementRules())
+,headerReplacements(PortingRules::instance()->getHeaderReplacements())
+,replaceToken(tokenReplacementRules)
+{
+ foreach (const QString &headerName, PortingRules::instance()->getHeaderList(PortingRules::Qt4)) {
+ qt4HeaderNames.insert(headerName.toLatin1());
+ }
+}
+
+/*
+ Ports a file given by fileName, which should be an absolute file path.
+*/
+void FilePorter::port(QString fileName)
+{
+ // Get file tokens from cache.
+ TokenContainer sourceTokens = preprocessorCache.sourceTokens(fileName);
+ if(sourceTokens.count() == 0)
+ return;
+
+ Logger::instance()->beginSection();
+
+ // Get include directive replacements.
+ const Rpp::Source * source = preprocessorCache.sourceTree(fileName);
+ PreprocessReplace preprocessReplace(source, PortingRules::instance()->getHeaderReplacements());
+ TextReplacements sourceReplacements = preprocessReplace.getReplacements();
+
+ // Get token replacements.
+ sourceReplacements += replaceToken.getTokenTextReplacements(sourceTokens);
+
+ // Apply the replacements to the source text.
+ QByteArray portedContents = sourceReplacements.apply(sourceTokens.fullText());
+
+ // Add include directives for classes that are no longer implicitly
+ // included via other headers. This step needs to be done after the token
+ // replacements, since we need to know which new class names that has been
+ // inserted in the source.
+ portedContents = includeAnalyse(portedContents);
+
+ // Check if any changes has been made.
+ if(portedContents == sourceTokens.fullText()) {
+ Logger::instance()->addEntry(
+ new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), QLatin1String("No changes made to file ") + fileName));
+ Logger::instance()->commitSection();
+ return;
+ }
+
+ // Write file, commit log if write was successful.
+ FileWriter::WriteResult result = FileWriter::instance()->writeFileVerbously(fileName, portedContents);
+ Logger *logger = Logger::instance();
+ if (result == FileWriter::WriteSucceeded) {
+ logger->commitSection();
+ } else if (result == FileWriter::WriteFailed) {
+ logger->revertSection();
+ logger->addEntry(
+ new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), QLatin1String("Error writing to file ") + fileName));
+ } else if (result == FileWriter::WriteSkipped) {
+ logger->revertSection();
+ logger->addEntry(
+ new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), QLatin1String("User skipped file ") + fileName));
+ } else {
+ // Internal error.
+ logger->revertSection();
+ const QString errorString = QLatin1String("Internal error in qt3to4 - FileWriter returned invalid result code while writing to ") + fileName;
+ logger->addEntry(new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), errorString));
+ }
+}
+
+QSet<QByteArray> FilePorter::usedQtModules()
+{
+ return m_usedQtModules;
+}
+
+TextReplacements FilePorter::includeDirectiveReplacements()
+{
+ return TextReplacements();
+}
+
+QByteArray FilePorter::includeAnalyse(QByteArray fileContents)
+{
+ // Tokenize file contents agein, since it has changed.
+ QVector<TokenEngine::Token> tokens = tokenizer.tokenize(fileContents);
+ TokenEngine::TokenContainer tokenContainer(fileContents, tokens);
+ IncludeDirectiveAnalyzer includeDirectiveAnalyzer(tokenContainer);
+
+ // Get list of used classes.
+ QSet<QByteArray> classes = includeDirectiveAnalyzer.usedClasses();
+
+ // Iterate class list and find which modules are used. This info is used elswhere
+ // by when porting the .pro file.
+ const QHash<QByteArray, QByteArray> classLibraryList = PortingRules::instance()->getClassLibraryList();
+ foreach (const QByteArray &className, classes) {
+ m_usedQtModules.insert(classLibraryList.value(className));
+ }
+
+ // Get list of included headers.
+ QSet<QByteArray> headers = includeDirectiveAnalyzer.includedHeaders();
+
+ // Find classes that is missing an include directive and that has a needHeader rule.
+ const QHash<QByteArray, QByteArray> neededHeaders = PortingRules::instance()->getNeededHeaders();
+ QList<QByteArray> insertHeaders;
+ foreach (const QByteArray &className, classes) {
+ if (!headers.contains((className.toLower() + QByteArray(".h"))) &&
+ !headers.contains(className)) {
+ const QByteArray insertHeader = neededHeaders.value(className);
+ if (insertHeader != QByteArray())
+ insertHeaders.append((QByteArray("#include <") + insertHeader + QByteArray(">")));
+ }
+ }
+
+ const QByteArray lineEnding = detectLineEndings(fileContents);
+
+ // Insert include directives undeclared classes.
+ int insertCount = insertHeaders.count();
+ if (insertCount > 0) {
+ QByteArray insertText;
+ QByteArray logText;
+
+ insertText += QByteArray("//Added by qt3to4:") + lineEnding;
+ logText += QByteArray("In file ");
+ logText += Logger::instance()->globalState.value(QLatin1String("currentFileName")).toLocal8Bit();
+ logText += QByteArray(": Added the following include directives:\n");
+ foreach (const QByteArray &headerName, insertHeaders) {
+ insertText = insertText + headerName + lineEnding;
+ logText += QByteArray("\t");
+ logText += headerName + QByteArray(" ");
+ }
+
+ const int insertLine = 0;
+ Logger::instance()->updateLineNumbers(insertLine, insertCount + 1);
+ const int insertPos = includeDirectiveAnalyzer.insertPos();
+ fileContents.insert(insertPos, insertText);
+ Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), QString::fromLatin1(logText.constData())));
+ }
+
+ return fileContents;
+}
+
+PreprocessReplace::PreprocessReplace(const Rpp::Source *source, const QHash<QByteArray, QByteArray> &headerReplacements)
+:headerReplacements(headerReplacements)
+{
+ // Walk preprocessor tree.
+ evaluateItem(source);
+}
+
+TextReplacements PreprocessReplace::getReplacements()
+{
+ return replacements;
+}
+/*
+ Replaces headers no longer present with support headers.
+*/
+void PreprocessReplace::evaluateIncludeDirective(const Rpp::IncludeDirective *directive)
+{
+ const QByteArray headerPathName = directive->filename();
+ const TokenEngine::TokenList headerPathTokens = directive->filenameTokens();
+
+ // Get the file name part of the file path.
+ const QByteArray headerFileName = QFileInfo(QString::fromLatin1(headerPathName.constData())).fileName().toUtf8();
+
+ // Check if we should replace the filename.
+ QByteArray replacement = headerReplacements.value(headerFileName);
+
+ // Also check lower-case version to catch incorrectly capitalized file names on Windows.
+ if (replacement.isEmpty())
+ replacement = headerReplacements.value(headerFileName.toLower());
+
+ const int numTokens = headerPathTokens.count();
+ if (numTokens > 0 && !replacement.isEmpty()) {
+ // Here we assume that the last token contains a part of the file name.
+ const TokenEngine::Token lastToken = headerPathTokens.token(numTokens -1);
+ int endPos = lastToken.start + lastToken.length;
+ // If the file name is specified in quotes, then the quotes will be a part
+ // of the token. Decrement endpos to leave out the ending quote when replacing.
+ if (directive->includeType() == IncludeDirective::QuoteInclude)
+ --endPos;
+ const int length = headerFileName.count();
+ const int startPos = endPos - length;
+ replacements.insert(replacement, startPos, length);
+ addLogSourceEntry(QString::fromLatin1((headerFileName + QByteArray(" -> ") + replacement).constData()),
+ headerPathTokens.tokenContainer(0), headerPathTokens.containerIndex(0));
+ }
+}
+
+/*
+ Replace line comments containing MOC_SKIP_BEGIN with #ifdef Q_MOC_RUN and MOC_SKIP_END with #endif
+*/
+void PreprocessReplace::evaluateText(const Rpp::Text *textLine)
+{
+ if (textLine->count() < 1)
+ return;
+
+ const TokenEngine::TokenContainer container = textLine->text().tokenContainer(0);
+ foreach (Rpp::Token *token, textLine->tokenList()) {
+ if (token->toLineComment()) {
+ const int tokenIndex = token->index();
+ const QByteArray text = container.text(tokenIndex);
+ const TokenEngine::Token containerToken = container.token(tokenIndex);
+
+ if (text.contains(QByteArray("MOC_SKIP_BEGIN"))) {
+ replacements.insert(QByteArray("#ifndef Q_MOC_RUN"), containerToken.start, containerToken.length);
+ addLogSourceEntry(QLatin1String("MOC_SKIP_BEGIN -> #ifndef Q_MOC_RUN"), container, tokenIndex);
+ }
+ if (text.contains(QByteArray("MOC_SKIP_END"))) {
+ replacements.insert(QByteArray("#endif"), containerToken.start, containerToken.length);
+ addLogSourceEntry(QLatin1String("MOC_SKIP_END -> #endif"), container, tokenIndex);
+ }
+ }
+ }
+}
+
+IncludeDirectiveAnalyzer::IncludeDirectiveAnalyzer(const TokenEngine::TokenContainer &fileContents)
+:fileContents(fileContents)
+{
+ const QVector<Type> lexical = RppLexer().lex(fileContents);
+ source = Preprocessor().parse(fileContents, lexical, &mempool);
+ foundInsertPos = false;
+ foundQtHeader = false;
+ ifSectionCount = 0;
+ insertTokenIndex = 0;
+
+ evaluateItem(source);
+}
+
+/*
+ Returns a position indicating where new include directives should be inserted.
+*/
+int IncludeDirectiveAnalyzer::insertPos()
+{
+ const TokenEngine::Token insertToken = fileContents.token(insertTokenIndex);
+ return insertToken.start;
+}
+
+/*
+ Returns a set of all headers included from this file.
+*/
+QSet<QByteArray> IncludeDirectiveAnalyzer::includedHeaders()
+{
+ return m_includedHeaders;
+}
+
+/*
+ Returns a list of used Qt classes.
+*/
+QSet<QByteArray> IncludeDirectiveAnalyzer::usedClasses()
+{
+ return m_usedClasses;
+}
+
+/*
+ Set insetionTokenindex to a token near other #include directives, preferably
+ just after a block of include directives that includes other Qt headers.
+*/
+void IncludeDirectiveAnalyzer::evaluateIncludeDirective(const IncludeDirective *directive)
+{
+ const QByteArray filename = directive->filename();
+ if (filename.isEmpty())
+ return;
+
+ m_includedHeaders.insert(filename);
+
+ if (foundInsertPos || ifSectionCount > 1)
+ return;
+
+ const bool isQtHeader = (filename.at(0) == 'q' || filename.at(0) == 'Q');
+ if (!isQtHeader && foundQtHeader) {
+ foundInsertPos = true;
+ return;
+ }
+
+ if (isQtHeader)
+ foundQtHeader = true;
+
+ // Get the last token for this directive.
+ TokenEngine::TokenSection tokenSection = directive->text();
+ const int newLineToken = 1;
+ insertTokenIndex = tokenSection.containerIndex(tokenSection.count() - 1) + newLineToken;
+}
+
+/*
+ Avoid inserting inside IfSections, except in the first one
+ we see, which probably is the header multiple inclusion guard.
+*/
+void IncludeDirectiveAnalyzer::evaluateIfSection(const IfSection *ifSection)
+{
+ ++ifSectionCount;
+ RppTreeWalker::evaluateIfSection(ifSection);
+ --ifSectionCount;
+}
+
+/*
+ Read all IdTokens and look for Qt class names. Also, on
+ the first IdToken set foundInsertPos to true
+
+*/
+void IncludeDirectiveAnalyzer::evaluateText(const Text *textLine)
+{
+ const int numTokens = textLine->count();
+ for (int t = 0; t < numTokens; ++t) {
+ Rpp::Token *token = textLine->token(t);
+ if (token->toIdToken()) {
+ foundInsertPos = true;
+ const int containerIndex = token->index();
+ const QByteArray tokenText = fileContents.text(containerIndex);
+ m_usedClasses.insert(tokenText);
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/fileporter.h b/tools/porting/src/fileporter.h
new file mode 100644
index 0000000000..000e2fdaf2
--- /dev/null
+++ b/tools/porting/src/fileporter.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILEPORTER_H
+#define FILEPORTER_H
+
+#include "portingrules.h"
+#include "replacetoken.h"
+#include "filewriter.h"
+#include "preprocessorcontrol.h"
+#include <QString>
+#include <QSet>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class FilePorter
+{
+public:
+ FilePorter(PreprocessorCache &preprocessorCache);
+ void port(QString fileName);
+ QSet<QByteArray> usedQtModules();
+private:
+ QByteArray loadFile(const QString &fileName);
+ QByteArray includeAnalyse(QByteArray fileContents);
+ TextReplacements includeDirectiveReplacements();
+
+ PreprocessorCache &preprocessorCache;
+ const QList<TokenReplacement*> tokenReplacementRules;
+ const QHash<QByteArray, QByteArray> headerReplacements;
+
+ ReplaceToken replaceToken;
+ Tokenizer tokenizer; //used by includeAnalyse
+
+ QSet<QByteArray> qt4HeaderNames;
+ QSet<QByteArray> m_usedQtModules;
+};
+
+class PreprocessReplace : public Rpp::RppTreeWalker
+{
+public:
+ PreprocessReplace(const Rpp::Source *source, const QHash<QByteArray, QByteArray> &headerReplacements);
+ TextReplacements getReplacements();
+private:
+ void evaluateIncludeDirective(const Rpp::IncludeDirective *directive);
+ void evaluateText(const Rpp::Text *textLine);
+ const QHash<QByteArray, QByteArray> headerReplacements;
+ TextReplacements replacements;
+
+};
+
+class IncludeDirectiveAnalyzer : public Rpp::RppTreeWalker
+{
+public:
+ IncludeDirectiveAnalyzer(const TokenEngine::TokenContainer &fileContents);
+ int insertPos();
+ QSet<QByteArray> includedHeaders();
+ QSet<QByteArray> usedClasses();
+private:
+ void evaluateIncludeDirective(const Rpp::IncludeDirective *directive);
+ void evaluateIfSection(const Rpp::IfSection *ifSection);
+ void evaluateText(const Rpp::Text *textLine);
+
+ int insertTokenIndex;
+ bool foundInsertPos;
+ bool foundQtHeader;
+ int ifSectionCount;
+
+ const TokenEngine::TokenContainer &fileContents;
+ Rpp::Source *source;
+ TypedPool<Rpp::Item> mempool;
+ QSet<QByteArray> m_includedHeaders;
+ QSet<QByteArray> m_usedClasses;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/filewriter.cpp b/tools/porting/src/filewriter.cpp
new file mode 100644
index 0000000000..e1ba0aa862
--- /dev/null
+++ b/tools/porting/src/filewriter.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "filewriter.h"
+#include <QFile>
+#include <QFileInfo>
+#include <QDir>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+FileWriter *FileWriter::theInstance = 0;
+
+FileWriter *FileWriter::instance()
+{
+ if(!theInstance)
+ theInstance = new FileWriter();
+
+ return theInstance;
+}
+
+void FileWriter::deleteInstance()
+{
+ if(theInstance) {
+ delete theInstance;
+ theInstance=0;
+ }
+}
+
+FileWriter::FileWriter(OverWriteFiles overWrite, QString overwriteMsg)
+:overWriteFiles(overWrite)
+,overwriteMessage(overwriteMsg)
+{
+ if(overwriteMessage.isEmpty())
+ overwriteMessage = QLatin1String("Convert file ");
+}
+
+FileWriter::WriteResult FileWriter::writeFileVerbously(QString filePath, QByteArray contents)
+{
+ const WriteResult result = writeFile(filePath, contents);
+ if (result == WriteSucceeded) {
+ QString cleanPath = QDir::cleanPath(filePath);
+ printf("Wrote to file: %s \n", QDir::toNativeSeparators(cleanPath).toLocal8Bit().constData());
+ }
+ return result;
+}
+
+FileWriter::WriteResult FileWriter::writeFile(QString filePath, QByteArray contents)
+{
+ if(filePath.isEmpty())
+ return WriteFailed;
+ QString path = QFileInfo(filePath).path();
+ if (!QDir().mkpath(path)){
+ printf("Error creating path %s \n", QDir::toNativeSeparators(path).toLocal8Bit().constData());
+ }
+
+ QString cleanPath = QDir::cleanPath(filePath);
+ QFile f(cleanPath);
+ if (f.exists()) {
+ if (overWriteFiles == DontOverWrite) {
+ printf("Error writing file %s: It already exists \n",
+ QDir::toNativeSeparators(cleanPath).toLatin1().constData());
+ return WriteFailed;
+ } else if(overWriteFiles == AskOnOverWrite) {
+ printf("%s%s? (Y)es, (N)o, (A)ll ", overwriteMessage.toLatin1().constData(),
+ QDir::toNativeSeparators(cleanPath).toLatin1().constData());
+
+ char answer = 0;
+ while (answer != 'y' && answer != 'n' && answer != 'a') {
+#if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400
+ scanf_s("%c", &answer);
+#else
+ scanf("%c", &answer);
+#endif
+ answer = tolower(answer);
+ }
+
+ if(answer == 'n')
+ return WriteSkipped;
+ else if(answer == 'a')
+ overWriteFiles=AlwaysOverWrite;
+ }
+ }
+
+ f.open(QFile::WriteOnly);
+ if (f.isOpen() && f.write(contents) == contents.size())
+ return WriteSucceeded;
+
+ printf("Could not write to to file: %s. Is it write protected?\n",
+ QDir::toNativeSeparators(filePath).toLatin1().constData());
+
+ return WriteFailed;
+}
+
+/*
+ Sets the write mode for the file writer. writeMode is one of
+ DontOverWrite, AlwaysOverWrite, AskOnOverWrite.
+*/
+void FileWriter::setOverwriteFiles(OverWriteFiles writeMode)
+{
+ overWriteFiles = writeMode;
+}
+
+QByteArray detectLineEndings(const QByteArray &array)
+{
+ if (array.contains("\r\n")) {
+ return "\r\n";
+ } else {
+ return "\n";
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/filewriter.h b/tools/porting/src/filewriter.h
new file mode 100644
index 0000000000..a58e8e0c44
--- /dev/null
+++ b/tools/porting/src/filewriter.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FILEWRITER_H
+#define FILEWRITER_H
+
+#include <QMap>
+#include <QString>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+class FileWriter
+{
+public:
+ enum OverWriteFiles{DontOverWrite, AlwaysOverWrite, AskOnOverWrite};
+ enum WriteResult { WriteFailed = 0, WriteSucceeded = 1, WriteSkipped };
+ static FileWriter *instance();
+ static void deleteInstance();
+
+ FileWriter(OverWriteFiles overWRite = AskOnOverWrite,
+ QString overwriteMessage = QString());
+ WriteResult writeFile(QString filePath, QByteArray contents);
+ WriteResult writeFileVerbously(QString filePath, QByteArray contents);
+ void setOverwriteFiles(OverWriteFiles writeMode);
+private:
+ QMap<QString, int> processedFilesSet;
+ OverWriteFiles overWriteFiles;
+ QString overwriteMessage;
+ static FileWriter *theInstance;
+};
+
+QByteArray detectLineEndings(const QByteArray &array);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/list.h b/tools/porting/src/list.h
new file mode 100644
index 0000000000..0021f2519f
--- /dev/null
+++ b/tools/porting/src/list.h
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIST_H
+#define LIST_H
+
+#include "smallobject.h"
+#include <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+
+template <typename T>
+class List
+{
+ struct Data
+ {
+ int alloc, size;
+ T array[1];
+ };
+ pool *p;
+ Data *d;
+
+public:
+ inline List(pool *_pool) : p(_pool), d(0) { d = malloc(16); d->size = 0; d->alloc = 16; }
+
+ inline List(const List &v) : d(0) { operator=(v); }
+ inline ~List() { d = 0; }
+ List &operator=(const List &v);
+
+ bool operator==(const List &v) const;
+ inline bool operator!=(const List &v) const { return !(*this == v); }
+
+ inline int size() const { return d->size; }
+ inline bool isEmpty() const { return d->size == 0; }
+
+ inline int capacity() const { return d->alloc; }
+ void reserve(int alloc);
+
+ inline T* data() { return d->array; }
+ inline const T* data() const { return d->array; }
+ void clear();
+
+ const T &at(int i) const;
+ T &operator[](int i);
+ const T &operator[](int i) const;
+ void append(const T &t);
+ void prepend(const T &t);
+ void insert(int i, const T &t);
+ void insert(int i, int n, const T &t);
+ void replace(int i, const T &t);
+ void remove(int i);
+ void remove(int i, int n);
+
+ List &fill(const T &t, int size = -1);
+
+ int indexOf(const T &t, int from = 0) const;
+ int lastIndexOf(const T &t, int from = -1) const;
+ bool contains(const T &t) const;
+ int count(const T &t) const;
+
+ // STL-style
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ inline iterator begin() { return d->array; }
+ inline const_iterator begin() const { return d->array; }
+ inline iterator end() { return d->array + d->size; }
+ inline const_iterator end() const { return d->array + d->size; }
+ iterator insert(iterator before, int n, const T &x);
+ inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
+ iterator erase(iterator begin, iterator end);
+ inline iterator erase(iterator pos) { return erase(pos, pos+1); }
+
+ // more Qt
+ inline int count() const { return d->size; }
+ inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); }
+ inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
+ inline const T& last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
+
+ T value(int i) const;
+ T value(int i, const T &defaultValue) const;
+
+ // STL compatibility
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+#ifndef QT_NO_STL
+ typedef ptrdiff_t difference_type;
+#else
+ typedef int difference_type;
+#endif
+ typedef iterator Iterator;
+ typedef const_iterator ConstIterator;
+ typedef int size_type;
+ inline void push_back(const T &t) { append(t); }
+ inline void push_front(const T &t) { prepend(t); }
+ void pop_back() { Q_ASSERT(!isEmpty()); erase(end()-1); }
+ void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); }
+ inline bool empty() const
+ { return d->size == 0; }
+ inline T& front() { return first(); }
+ inline const_reference front() const { return first(); }
+ inline reference back() { return last(); }
+ inline const_reference back() const { return last(); }
+
+ //comfort
+ List &operator+=(const List &l);
+ inline List operator+(const List &l) const
+ { List n = *this; n += l; return n; }
+ inline void operator+=(const T &t)
+ { append(t); }
+ inline List &operator<< (const T &t)
+ { append(t); return *this; }
+
+private:
+ Data *malloc(int alloc);
+};
+
+template <typename T>
+inline void List<T>::clear()
+{ d->size = 0; }
+
+template <typename T>
+inline const T &List<T>::at(int i) const
+{ Q_ASSERT_X(i >= 0 && i < d->size, "List<T>::at", "index out of range");
+ return d->array[i]; }
+template <typename T>
+inline const T &List<T>::operator[](int i) const
+{ Q_ASSERT_X(i >= 0 && i < d->size, "List<T>::operator[]", "index out of range");
+ return d->array[i]; }
+template <typename T>
+inline T &List<T>::operator[](int i)
+{ Q_ASSERT_X(i >= 0 && i < d->size, "List<T>::operator[]", "index out of range");
+ return d->array[i]; }
+template <typename T>
+inline void List<T>::insert(int i, const T &t)
+{ Q_ASSERT_X(i >= 0 && i <= d->size, "List<T>::insert", "index out of range");
+ insert(begin()+i, 1, t); }
+template <typename T>
+inline void List<T>::insert(int i, int n, const T &t)
+{ Q_ASSERT_X(i >= 0 && i <= d->size, "List<T>::insert", "index out of range");
+ insert(begin() + i, n, t); }
+template <typename T>
+inline void List<T>::remove(int i, int n)
+{ Q_ASSERT_X(i >= 0 && i + n <= d->size, "List<T>::remove", "index out of range");
+ erase(begin() + i, begin() + i + n); }
+template <typename T>
+inline void List<T>::remove(int i)
+{ Q_ASSERT_X(i >= 0 && i < d->size, "List<T>::remove", "index out of range");
+ erase(begin() + i, begin() + i + 1); }
+template <typename T>
+inline void List<T>::prepend(const T &t)
+{ insert(begin(), 1, t); }
+template <typename T>
+inline void List<T>::replace(int i, const T &t)
+{ Q_ASSERT_X(i >= 0 && i < d->size, "List<T>::replace", "index out of range");
+ data()[i] = t; }
+
+template <typename T>
+List<T> &List<T>::operator=(const List<T> &v)
+{
+ p = v.p;
+ d = malloc(v.d->alloc);
+ memcpy(d, v.d, sizeof(Data) + (v.d->size - 1) * sizeof(T));
+ return *this;
+}
+
+template <typename T>
+inline typename List<T>::Data *List<T>::malloc(int alloc)
+{
+ return static_cast<Data *>(p->allocate(sizeof(Data) + (alloc - 1) * sizeof(T)));
+}
+
+template <typename T>
+void List<T>::reserve(int alloc)
+{
+ if (alloc <= d->alloc)
+ return;
+ alloc <<= 2;
+ d = static_cast<Data *>(p->reallocate(d, sizeof(Data) + d->alloc * sizeof(T),
+ sizeof(Data) + (alloc - 1) * sizeof(T)));
+ d->alloc = alloc;
+}
+
+template<typename T>
+T List<T>::value(int i) const
+{
+ if(i < 0 || i >= d->size) {
+ return T();
+ }
+ return d->array[i];
+}
+template<typename T>
+T List<T>::value(int i, const T& defaultValue) const
+{
+ return ((i < 0 || i >= d->size) ? defaultValue : d->array[i]);
+}
+
+template <typename T>
+void List<T>::append(const T &t)
+{
+ reserve(d->size + 1);
+ d->array[d->size++] = t;
+}
+
+
+template <typename T>
+typename List<T>::iterator List<T>::insert(iterator before, size_type n, const T& t)
+{
+ int p = before - d->array;
+ if (n != 0) {
+ reserve(d->size + n);
+ T *b = d->array+p;
+ T *i = b+n;
+ memmove(i, b, (d->size-p)*sizeof(T));
+ while (i != b)
+ *(--i) = t;
+ }
+ d->size += n;
+ return d->array+p;
+}
+
+template <typename T>
+typename List<T>::iterator List<T>::erase(iterator begin, iterator end)
+{
+ int f = begin - d->array;
+ int l = end - d->array;
+ int n = l - f;
+ memmove(d->array + f, d->array + l, (d->size-l)*sizeof(T));
+ d->size -= n;
+ return d->array + f;
+}
+
+template <typename T>
+bool List<T>::operator==(const List<T> &v) const
+{
+ if (d->size != v.d->size)
+ return false;
+ T* b = d->array;
+ T* i = b + d->size;
+ T* j = v.d->array + d->size;
+ while (i != b)
+ if (!(*--i == *--j))
+ return false;
+ return true;
+}
+
+template <typename T>
+List<T> &List<T>::fill(const T &t, int size)
+{
+ resize(size < 0 ? d->size : size);
+ if (d->size) {
+ T* i = d->array + d->size;
+ T* b = d->array;
+ while (i != b)
+ *--i = t;
+ }
+ return *this;
+}
+
+template <typename T>
+List<T> &List<T>::operator+=(const List &l)
+{
+ int newSize = d->size + l.d->size;
+ reserve(newSize);
+
+ T *w = d->array + newSize;
+ T *i = l.d->array + l.d->size;
+ T *b = l.d->array;
+ while (i != b)
+ *--w = *--i;
+ d->size = newSize;
+ return *this;
+}
+
+template <typename T>
+int List<T>::indexOf(const T &t, int from) const
+{
+ if (from < 0)
+ from = qMax(from + d->size, 0);
+ if (from < d->size) {
+ T* n = d->array + from - 1;
+ T* e = d->array + d->size;
+ while (++n != e)
+ if (*n == t)
+ return n - d->array;
+ }
+ return -1;
+}
+
+template <typename T>
+int List<T>::lastIndexOf(const T &t, int from) const
+{
+ if (from < 0)
+ from += d->size;
+ else if (from >= d->size)
+ from = d->size-1;
+ if (from >= 0) {
+ T* b = d->array;
+ T* n = d->array + from + 1;
+ while (n != b) {
+ if (*--n == t)
+ return n - b;
+ }
+ }
+ return -1;
+}
+
+template <typename T>
+bool List<T>::contains(const T &t) const
+{
+ T* b = d->array;
+ T* i = d->array + d->size;
+ while (i != b)
+ if (*--i == t)
+ return true;
+ return false;
+}
+
+template <typename T>
+int List<T>::count(const T &t) const
+{
+ int c = 0;
+ T* b = d->array;
+ T* i = d->array + d->size;
+ while (i != b)
+ if (*--i == t)
+ ++c;
+ return c;
+}
+
+QT_END_NAMESPACE
+
+#endif // LIST_H
diff --git a/tools/porting/src/logger.cpp b/tools/porting/src/logger.cpp
new file mode 100644
index 0000000000..fb44de79d4
--- /dev/null
+++ b/tools/porting/src/logger.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "logger.h"
+#include <QFile>
+#include <QDateTime>
+
+QT_BEGIN_NAMESPACE
+
+LogEntry::LogEntry(QString type, QString location)
+:type(type), location(location)
+{}
+
+PlainLogEntry::PlainLogEntry(QString type, QString location, QString text)
+:LogEntry(type, location), text(text)
+{}
+
+SourcePointLogEntry::SourcePointLogEntry(QString type, QString location, QString file, int line, int column, QString text)
+:LogEntry(type, location), file(file), line(line), column(column), text(text)
+{}
+
+QString SourcePointLogEntry::description() const
+{
+ return QLatin1String("In file ") + file +
+ QLatin1String(" at line ") + QString(QLatin1String("%1")).arg(line + 1) + //line count is zero based, adjust here.
+ QLatin1String(" column ") + QString(QLatin1String("%1")).arg(column) +
+ QLatin1String(": ") + text ;
+}
+
+void SourcePointLogEntry::updateLinePos(int threshold, int delta)
+{
+ if (line >= threshold)
+ line += delta;
+}
+
+/////////////////////////////////////////////////////
+
+
+Logger::~Logger()
+{
+ qDeleteAll(logEntries);
+}
+
+Logger *Logger::theInstance = 0;
+Logger *Logger::instance()
+{
+ if(!theInstance)
+ theInstance = new Logger();
+ return theInstance;
+}
+
+void Logger::deleteInstance()
+{
+ if(theInstance)
+ delete theInstance;
+}
+
+void Logger::addEntry(LogEntry *entry)
+{
+ Q_ASSERT(entry);
+ pendingLogEntries.append(entry);
+}
+
+void Logger::beginSection()
+{
+ commitSection();
+}
+
+void Logger::commitSection()
+{
+ logEntries += pendingLogEntries;
+ pendingLogEntries.clear();
+}
+
+void Logger::revertSection()
+{
+ qDeleteAll(pendingLogEntries);
+ pendingLogEntries.clear();
+}
+
+int Logger::numEntries()
+{
+ commitSection();
+ return logEntries.size();
+}
+
+QStringList Logger::fullReport()
+{
+ commitSection();
+ QStringList report;
+ report << QLatin1String("Log for qt3to4 on ") + QDateTime::currentDateTime().toString() +
+ QLatin1String(". Number of log entries: ") + QString(QLatin1String("%1")).arg(logEntries.size());
+ foreach(LogEntry *logEntry, logEntries) {
+ report << logEntry->description();
+ }
+ return report;
+}
+
+/*
+ Update the line for all SourcePointLogEntrys in the list of pending log
+ entries located on or after insertLine.
+*/
+void Logger::updateLineNumbers(int insertLine, int numLines)
+{
+ foreach(LogEntry *logEntry, pendingLogEntries) {
+ logEntry->updateLinePos(insertLine, numLines);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/logger.h b/tools/porting/src/logger.h
new file mode 100644
index 0000000000..20e7dd5b91
--- /dev/null
+++ b/tools/porting/src/logger.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LOGGER_H
+#define LOGGER_H
+
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+/*
+ Base class for logger entries;
+ description() should return a text for this entry,
+*/
+class LogEntry
+{
+public:
+ LogEntry(QString type, QString location);
+ virtual ~LogEntry(){};
+ virtual QString description() const =0;
+ virtual void updateLinePos(int threshold, int delta) {Q_UNUSED(threshold); Q_UNUSED(delta)};
+protected:
+ QString type; // Error, Warning, Info, etc
+ QString location;// preprocessor, c++parser, porting, etc
+};
+
+class PlainLogEntry: public LogEntry
+{
+public:
+ PlainLogEntry(QString type, QString lcation, QString text);
+ QString description() const {return text;};
+protected:
+ QString text;
+};
+
+/*
+ A log entry that stores a source point: file, line and column.
+*/
+class SourcePointLogEntry : public LogEntry
+{
+public:
+ SourcePointLogEntry(QString type, QString location, QString file, int line, int column, QString text);
+ QString description() const;
+ void updateLinePos(int threshold, int delta);
+protected:
+ QString file;
+ int line;
+ int column;
+ QString text;
+};
+
+
+class Logger
+{
+public:
+ Logger(){};
+ ~Logger();
+ static Logger *instance();
+ static void deleteInstance();
+
+ void beginSection();
+ void commitSection();
+ void revertSection();
+ void addEntry(LogEntry *entry);
+
+ QStringList fullReport();
+ int numEntries();
+ void updateLineNumbers(int insertLine, int numLines);
+ /*
+ glabalState can be used for storage of application state
+ together with the logger. This can be useful in some cases,
+ for example the current filename is stored here when processing
+ files.
+ */
+ QMap<QString, QString> globalState;
+private:
+ static Logger *theInstance;
+ QList<LogEntry*> logEntries;
+ QList<LogEntry*> pendingLogEntries;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/parser.cpp b/tools/porting/src/parser.cpp
new file mode 100644
index 0000000000..a903ece20a
--- /dev/null
+++ b/tools/porting/src/parser.cpp
@@ -0,0 +1,4526 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "parser.h"
+#include "tokens.h"
+#include "errors.h"
+
+#include <QString>
+#include <QStringList>
+#include <QDateTime>
+
+QT_BEGIN_NAMESPACE
+
+#define TT (tokenStream->currentTokenText().data())
+
+#define ADVANCE(tk, descr) \
+{ \
+ if (tokenStream->lookAhead() != tk) { \
+ reportError(QString::fromLatin1("'%1' expected found '%2'").arg(QLatin1String(descr)).arg(QString::fromLatin1((tokenStream->currentTokenText().constData())))); \
+ return false; \
+ } \
+ advance(); \
+}
+
+#define ADVANCE_NR(tk, descr) \
+ do { \
+ if (tokenStream->lookAhead() != tk) { \
+ reportError(i18n("'%1' expected found '%2'").arg(QLatin1String(descr)).arg(QString::fromLatin1(tokenStream->currentTokenText().constData()))); \
+ } \
+ else \
+ advance(); \
+ } while (0)
+
+#define CHECK(tk, descr) \
+ do { \
+ if (tokenStream->lookAhead() != tk) { \
+ return false; \
+ } \
+ advance(); \
+ } while (0)
+
+#define MATCH(tk, descr) \
+ do { \
+ if (tokenStream->lookAhead() != tk) { \
+ reportError(Errors::SyntaxError); \
+ return false; \
+ } \
+ } while (0)
+
+#define UPDATE_POS(_node, start, end) \
+ do { \
+ (_node)->setPosition(start, end); \
+ } while (0)
+
+#define AST_FROM_TOKEN(node, tk) \
+ AST *node = CreateNode<AST>(m_pool); \
+ UPDATE_POS(node, (tk), (tk)+1);
+
+#define DUMP_AST(node) \
+ do { \
+ fprintf(stderr, "\n=================================================\n"); \
+ for (int i=node->startToken(); i<node->endToken(); ++i) \
+ fprintf(stderr, "%s", tokenStream->tokenText(i).constData()); \
+ fprintf(stderr, "\n=================================================\n"); \
+ } while (0)
+
+#define RXX_NO_ERROR
+
+QString i18n(const char *arg)
+{
+ return QLatin1String(arg);
+}
+
+
+//@todo remove me
+enum
+{
+ OBJC_CLASS,
+ OBJC_PROTOCOL,
+ OBJC_ALIAS
+};
+
+Parser::Parser()
+{
+ m_maxProblems = 5;
+ objcp = false;
+}
+
+Parser::~Parser()
+{
+}
+
+TranslationUnitAST *Parser::parse(TokenStreamAdapter::TokenStream *p_tokenStream, pool *p)
+{
+ //tokenStream->rewind(0);
+ m_pool = p;
+ tokenStream = p_tokenStream;
+ TranslationUnitAST *ast = 0;
+ parseTranslationUnit(ast);
+ return ast;
+}
+
+/*
+ Parses a part of the translation unit given by tokenStream. When the number
+ of nodes in the AST exeeds targetMaxASTnodes, this function will return as
+ soon as possible. The progress is stored by updating the cursor inside
+ tokenStream. done is set to true if the parser finished parsing the
+ tokenStream, and to false otherwise.
+*/
+TranslationUnitAST *Parser::parse(TokenStreamAdapter::TokenStream *p_tokenStream, pool *p, int targetMaxASTNodes, bool &done)
+{
+ m_pool = p;
+ tokenStream = p_tokenStream;
+ TranslationUnitAST *ast = 0;
+ // we always create one node, so target max nodes cannot be < 2.
+ if (targetMaxASTNodes < 2)
+ targetMaxASTNodes = 2;
+
+ // Advance past whitespace and comment tokens at the start.
+ while (tokenStream->isHidden(tokenStream->cursor())) {
+ tokenStream->nextToken();
+ }
+ int start = tokenStream->cursor();
+
+ AST::N = 0;
+ m_problems = 0;
+ ast = CreateNode<TranslationUnitAST>(m_pool);
+ while (tokenStream->lookAhead() && AST::N < targetMaxASTNodes) {
+ DeclarationAST *def = 0;
+ int startDecl = tokenStream->cursor();
+ if (!parseDeclaration(def)) {
+ // error recovery
+ if (startDecl == tokenStream->cursor())
+ advance(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ ast->addDeclaration(def);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+
+ done = tokenStream->tokenAtEnd();
+ return ast;
+}
+
+
+bool Parser::reportError(const Error& err)
+{
+Q_UNUSED(err);
+#ifndef RXX_NO_ERROR
+ if (m_problems < m_maxProblems) {
+ ++m_problems;
+ int line=0, col=0;
+ QByteArray fileName;
+ tokenStream->getTokenStartPosition(tokenStream->cursor(), &line, &col, &fileName);
+
+ QString s = tokenStream->currentTokenText();
+ s = s.left(30).trimmed();
+ if (s.isEmpty())
+ s = i18n("<eof>");
+
+ if (fileName.isEmpty())
+ //fileName = m_file->fileName;
+ fileName = "implement me";
+
+ // m_driver->addProblem(m_driver->currentFileName(), Problem(err.text.arg(s), line, col));
+ fprintf(stderr, "%s: error %s at line %d column %d\n",
+ fileName.constData(),
+ err.text.arg(s).toLatin1().constData(), line, col);
+ }
+#endif // RXX_NO_ERROR
+ return true;
+}
+
+bool Parser::reportError(const QString& msg)
+{
+Q_UNUSED(msg);
+#ifndef RXX_NO_ERROR
+ if (m_problems < m_maxProblems) {
+ ++m_problems;
+ int line=0, col=0;
+ QByteArray fileName;
+ tokenStream->getTokenStartPosition(tokenStream->cursor(), &line, &col, &fileName);
+
+ if (fileName.isEmpty())
+ //fileName = m_file->fileName;
+ fileName = "implement me";
+
+ // m_driver->addProblem(m_driver->currentFileName(), Problem(msg, line, col));
+ fprintf(stderr, "%s: error %s at line %d column %d\n",
+ fileName.constData(),
+ msg.toLatin1().constData(), line, col);
+ }
+#endif // RXX_NO_ERROR
+ return true;
+}
+
+void Parser::syntaxError()
+{
+ (void) reportError(Errors::SyntaxError);
+}
+
+bool Parser::skipUntil(int token)
+{
+ while (tokenStream->lookAhead()) {
+ if (tokenStream->lookAhead() == token)
+ return true;
+
+ advance();
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+ while (tokenStream->lookAhead()) {
+
+ switch(tokenStream->lookAhead()) {
+ case ';':
+ case '~':
+ case Token_scope:
+ case Token_identifier:
+ case Token_operator:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_extern:
+ case Token_namespace:
+ case Token_using:
+ case Token_typedef:
+ case Token_asm:
+ case Token_template:
+ case Token_export:
+
+ case Token_const: // cv
+ case Token_volatile: // cv
+
+ case Token_public:
+ case Token_protected:
+ case Token_private:
+ case Token_signals: // Qt
+ case Token_slots: // Qt
+ return true;
+
+ default:
+ advance();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+ while (tokenStream->lookAhead()) {
+ switch(tokenStream->lookAhead()) {
+ case ';':
+ case '{':
+ case '}':
+ case Token_const:
+ case Token_volatile:
+ case Token_identifier:
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_switch:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ case Token_try:
+ case Token_catch:
+ case Token_throw:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_class:
+ case Token_struct:
+ case Token_union:
+ case Token_enum:
+ case Token_scope:
+ case Token_template:
+ case Token_using:
+ return true;
+
+ default:
+ advance();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skip(int l, int r)
+{
+ int count = 0;
+ while (tokenStream->lookAhead()) {
+ int tk = tokenStream->lookAhead();
+
+ if (tk == l)
+ ++count;
+ else if (tk == r)
+ --count;
+ else if (l != '{' && (tk == '{' || tk == '}' || tk == ';'))
+ return false;
+
+ if (count == 0)
+ return true;
+
+ advance();
+ }
+
+ return false;
+}
+
+bool Parser::skipCommaExpression(AbstractExpressionAST *&node)
+{
+#ifndef RXX_NO_PARSE_EXPRESSION
+ return parseCommaExpression(node);
+#else
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *expr = 0;
+ if (!skipExpression(expr))
+ return false;
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (!skipExpression(expr)) {
+ reportError(i18n("expression expected"));
+ return false;
+ }
+ }
+
+ AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+#endif // RXX_NO_PARSE_EXPRESSION
+}
+
+bool Parser::skipExpression(AbstractExpressionAST *&node)
+{
+#ifndef RXX_NO_PARSE_EXPRESSION
+ return parseExpression(node);
+#else
+ int start = tokenStream->cursor();
+ int count = 0;
+
+ while (tokenStream->lookAhead()) {
+ int tk = tokenStream->lookAhead();
+
+ switch(tk) {
+ case '(':
+ case '[':
+ case '{':
+ ++count;
+ advance();
+ break;
+
+ case ']':
+ case ')':
+ case '}':
+ if (count == 0) {
+ AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ }
+ --count;
+ advance();
+ break;
+
+ case Token_struct:
+ case Token_union:
+ case Token_class: {
+ int c = tokenStream->cursor();
+ TypeSpecifierAST *spec = 0;
+ if (!parseClassSpecifier(spec))
+ tokenStream->rewind(c + 1);
+ }
+ break;
+
+ case ',':
+ case ';':
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ {
+ if ((tk == ',' || tk == ';') && count > 0) {
+ advance();
+ break;
+ }
+
+ AbstractExpressionAST *ast = CreateNode<AbstractExpressionAST>(m_pool);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ }
+ return true;
+
+ default:
+ advance();
+ }
+ }
+
+ return false;
+#endif // RXX_NO_PARSE_EXPRESSION
+}
+
+bool Parser::parseName(NameAST *&node, bool parseTemplateId)
+{
+ AST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ int start = tokenStream->cursor();
+
+ NameAST *ast = CreateNode<NameAST>(m_pool);
+
+ if (tokenStream->lookAhead() == Token_scope) {
+ ast->setGlobal(true);
+ advance();
+ }
+
+ int idx = tokenStream->cursor();
+
+ while (true) {
+ ClassOrNamespaceNameAST *n = 0;
+ if (!parseUnqualifiedName(n))
+ return false;
+
+ if (tokenStream->lookAhead() == Token_scope) {
+ advance();
+ ast->addClassOrNamespaceName(n);
+ if (tokenStream->lookAhead() == Token_template)
+ advance(); /// skip optional template #### @todo CHECK
+ } else if (!parseTemplateId && n) {
+ tokenStream->rewind(n->startToken());
+ parseUnqualifiedName(n, parseTemplateId);
+ ast->setUnqualifiedName(n);
+ break;
+ } else {
+ ast->setUnqualifiedName(n);
+ break;
+ }
+ }
+
+ if (idx == tokenStream->cursor())
+ return false;
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
+{
+ QTime t;
+ t.start();
+
+ advance();
+ int start = tokenStream->cursor();
+
+ m_problems = 0;
+ TranslationUnitAST *tun = CreateNode<TranslationUnitAST>(m_pool);
+ node = tun;
+ while (tokenStream->lookAhead()) {
+ DeclarationAST *def = 0;
+ int startDecl = tokenStream->cursor();
+ if (!parseDeclaration(def)) {
+ // error recovery
+ if (startDecl == tokenStream->cursor())
+ advance(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ node->addDeclaration(def);
+ }
+
+ UPDATE_POS(node, start, tokenStream->cursor());
+
+ return m_problems == 0;
+}
+
+bool Parser::parseDeclaration(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ switch(tokenStream->lookAhead()) {
+
+ case ';':
+ advance();
+ return true;
+
+ case Token_extern:
+ return parseLinkageSpecification(node);
+
+ case Token_namespace:
+ return parseNamespace(node);
+
+ case Token_using:
+ return parseUsing(node);
+
+ case Token_typedef:
+ return parseTypedef(node);
+
+ case Token_asm:
+ return parseAsmDefinition(node);
+
+ case Token_template:
+ case Token_export:
+ return parseTemplateDeclaration(node);
+
+ default:
+ {
+ // tokenStream->rewind(start);
+
+ if (objcp && parseObjcDef(node))
+ return true;
+
+ tokenStream->rewind(start);
+
+ AST *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) {
+ spec->setCvQualify(cv);
+
+ AST *cv2 = 0;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify(cv2);
+
+ InitDeclaratorListAST *declarators = 0;
+ parseInitDeclaratorList(declarators);
+ ADVANCE(';', ";");
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+ ast->setStorageSpecifier(storageSpec);
+ ast->setTypeSpec(spec);
+ ast->setInitDeclaratorList(declarators);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+ }
+
+ tokenStream->rewind(start);
+ return parseDeclarationInternal(node);
+ }
+
+ } // end switch
+}
+
+bool Parser::parseLinkageSpecification(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_extern) {
+ return false;
+ }
+ advance();
+
+ LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(m_pool);
+
+ int startExternType = tokenStream->cursor();
+ if (tokenStream->lookAhead() == Token_string_literal) {
+ advance();
+ AST *externType = CreateNode<AST>(m_pool);
+ UPDATE_POS(externType, startExternType, tokenStream->cursor());
+
+ ast->setExternType(externType);
+ }
+
+ if (tokenStream->lookAhead() == '{') {
+ LinkageBodyAST *linkageBody = 0;
+ parseLinkageBody(linkageBody);
+ ast->setLinkageBody(linkageBody);
+ } else {
+ DeclarationAST *decl = 0;
+ if (!parseDeclaration(decl)) {
+ reportError(i18n("Declaration syntax error"));
+ }
+ ast->setDeclaration(decl);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLinkageBody(LinkageBodyAST *&node)
+{
+
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != '{') {
+ return false;
+ }
+ advance();
+
+ LinkageBodyAST *lba = CreateNode<LinkageBodyAST>(m_pool);
+ node = lba;
+
+ while (tokenStream->lookAhead()) {
+ int tk = tokenStream->lookAhead();
+
+ if (tk == '}')
+ break;
+
+ DeclarationAST *def = 0;
+ int startDecl = tokenStream->cursor();
+ if (parseDeclaration(def)) {
+ node->addDeclaration(def);
+ } else {
+ // error recovery
+ if (startDecl == tokenStream->cursor())
+ advance(); // skip at least one token
+ skipUntilDeclaration();
+ }
+ }
+
+ if (tokenStream->lookAhead() != '}') {
+ reportError(i18n("} expected"));
+ } else
+ advance();
+
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+}
+
+bool Parser::parseNamespace(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_namespace) {
+ return false;
+ }
+ advance();
+
+ int startNamespaceName = tokenStream->cursor();
+ if (tokenStream->lookAhead() == Token_identifier) {
+ advance();
+ }
+ AST *namespaceName = CreateNode<AST>(m_pool);
+ UPDATE_POS(namespaceName, startNamespaceName, tokenStream->cursor());
+
+ if (tokenStream->lookAhead() == '=') {
+ // namespace alias
+ advance();
+
+ NameAST *name = 0;
+ if (parseName(name)) {
+ ADVANCE(';', ";");
+
+ NamespaceAliasAST *ast = CreateNode<NamespaceAliasAST>(m_pool);
+ ast->setNamespaceName(namespaceName);
+ ast->setAliasName(name);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ } else {
+ reportError(i18n("namespace expected"));
+ return false;
+ }
+ } else if (tokenStream->lookAhead() != '{') {
+ reportError(i18n("{ expected"));
+ return false;
+ }
+
+ NamespaceAST *ast = CreateNode<NamespaceAST>(m_pool);
+ ast->setNamespaceName(namespaceName);
+
+ LinkageBodyAST *linkageBody = 0;
+ parseLinkageBody(linkageBody);
+
+ ast->setLinkageBody(linkageBody);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsing(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_using) {
+ return false;
+ }
+ advance();
+
+ if (tokenStream->lookAhead() == Token_namespace) {
+ if (!parseUsingDirective(node)) {
+ return false;
+ }
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+
+ UsingAST *ast = CreateNode<UsingAST>(m_pool);
+
+ int startTypeName = tokenStream->cursor();
+ if (tokenStream->lookAhead() == Token_typename) {
+ advance();
+ AST *tn = CreateNode<AST>(m_pool);
+ UPDATE_POS(tn, startTypeName, tokenStream->cursor());
+ ast->setTypeName(tn);
+ }
+
+ NameAST *name = 0;
+ if (!parseName(name))
+ return false;
+
+ ast->setName(name);
+
+ ADVANCE(';', ";");
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsingDirective(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_namespace) {
+ return false;
+ }
+ advance();
+
+ NameAST *name = 0;
+ if (!parseName(name)) {
+ reportError(i18n("Namespace name expected"));
+ return false;
+ }
+
+ ADVANCE(';', ";");
+
+ UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(m_pool);
+ ast->setName(name);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseOperatorFunctionId(AST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_operator) {
+ return false;
+ }
+ advance();
+
+ AST *op = 0;
+ if (parseOperator(op)) {
+ AST *asn = CreateNode<AST>(m_pool);
+ node = asn;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ } else {
+ // parse cast operator
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseSimpleTypeSpecifier(spec)) {
+ syntaxError();
+ return false;
+ }
+ spec->setCvQualify(cv);
+
+ AST *cv2 = 0;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify(cv2);
+
+ AST *ptrOp = 0;
+ while (parsePtrOperator(ptrOp))
+ ;
+
+ AST *asn = CreateNode<AST>(m_pool);
+ node = asn;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+}
+
+bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node, bool reportError)
+{
+ int start = tokenStream->cursor();
+
+ TemplateArgumentListAST *ast = CreateNode<TemplateArgumentListAST>(m_pool);
+
+ AST *templArg = 0;
+ if (!parseTemplateArgument(templArg))
+ return false;
+ ast->addArgument(templArg);
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (!parseTemplateArgument(templArg)) {
+ if (reportError) {
+ syntaxError();
+ break;
+ } else
+ return false;
+ }
+ ast->addArgument(templArg);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypedef(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_typedef) {
+ return false;
+ }
+ advance();
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifierOrClassSpec(spec)) {
+ reportError(i18n("Need a type specifier to declare"));
+ return false;
+ }
+
+ InitDeclaratorListAST *declarators = 0;
+ if (!parseInitDeclaratorList(declarators)) {
+ //reportError(i18n("Need an identifier to declare"));
+ //return false;
+ }
+
+ ADVANCE(';', ";");
+
+ TypedefAST *ast = CreateNode<TypedefAST>(m_pool);
+ ast->setTypeSpec(spec);
+ ast->setInitDeclaratorList(declarators);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAsmDefinition(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ADVANCE(Token_asm, "asm");
+
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ skip('(', ')');
+ advance();
+ ADVANCE(';', ";");
+
+ DeclarationAST *ast = CreateNode<DeclarationAST>(m_pool);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AST *exp = 0;
+
+ int startExport = tokenStream->cursor();
+ if (tokenStream->lookAhead() == Token_export) {
+ advance();
+ AST *n = CreateNode<AST>(m_pool);
+ UPDATE_POS(n, startExport, tokenStream->cursor());
+ exp = n;
+ }
+
+ if (tokenStream->lookAhead() != Token_template) {
+ return false;
+ }
+ advance();
+
+ TemplateParameterListAST *params = 0;
+ if (tokenStream->lookAhead() == '<') {
+ advance();
+ parseTemplateParameterList(params);
+
+ ADVANCE('>', ">");
+ }
+
+ DeclarationAST *def = 0;
+ if (!parseDeclaration(def)) {
+ reportError(i18n("expected a declaration"));
+ }
+
+ TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(m_pool);
+ ast->setExported(exp);
+ ast->setTemplateParameterList(params);
+ ast->setDeclaration(def);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseOperator(AST *&/*node*/)
+{
+ QString text(QString::fromLatin1(tokenStream->currentTokenText().constData()));
+
+ switch(tokenStream->lookAhead()) {
+ case Token_new:
+ case Token_delete:
+ advance();
+ if (tokenStream->lookAhead() == '[' && tokenStream->lookAhead(1) == ']') {
+ advance();
+ advance();
+ text += QLatin1String("[]");
+ }
+ return true;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ case '&':
+ case '|':
+ case '~':
+ case '!':
+ case '=':
+ case '<':
+ case '>':
+ case ',':
+ case Token_assign:
+ case Token_shift:
+ case Token_eq:
+ case Token_not_eq:
+ case Token_leq:
+ case Token_geq:
+ case Token_and:
+ case Token_or:
+ case Token_incr:
+ case Token_decr:
+ case Token_ptrmem:
+ case Token_arrow:
+ advance();
+ return true;
+
+ default:
+ if (tokenStream->lookAhead() == '(' && tokenStream->lookAhead(1) == ')') {
+ advance();
+ advance();
+ return true;
+ } else if (tokenStream->lookAhead() == '[' && tokenStream->lookAhead(1) == ']') {
+ advance();
+ advance();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseCvQualify(AST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AST *ast = CreateNode<AST>(m_pool);
+
+ int n = 0;
+ while (tokenStream->lookAhead()) {
+ int tk = tokenStream->lookAhead();
+ if (tk == Token_const || tk == Token_volatile) {
+ ++n;
+ int startWord = tokenStream->cursor();
+ advance();
+ AST *word = CreateNode<AST>(m_pool);
+ UPDATE_POS(word, startWord, tokenStream->cursor());
+ word->setParent(ast);
+ } else
+ break;
+ }
+
+ if (n == 0)
+ return false;
+
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+
+ node = ast;
+ return true;
+}
+
+bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node, bool onlyIntegral)
+{
+ int start = tokenStream->cursor();
+ bool isIntegral = false;
+ bool done = false;
+
+ while (!done) {
+ switch(tokenStream->lookAhead()) {
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ isIntegral = true;
+ advance();
+ break;
+
+ default:
+ done = true;
+ }
+ }
+
+ TypeSpecifierAST *ast = CreateNode<TypeSpecifierAST>(m_pool);
+ if (isIntegral) {
+ ClassOrNamespaceNameAST *cl = CreateNode<ClassOrNamespaceNameAST>(m_pool);
+
+ AST *n = CreateNode<AST>(m_pool);
+ UPDATE_POS(n, start, tokenStream->cursor());
+ cl->setName(n);
+ UPDATE_POS(cl, start, tokenStream->cursor());
+
+ NameAST *name = CreateNode<NameAST>(m_pool);
+ name->setUnqualifiedName(cl);
+ UPDATE_POS(name, start, tokenStream->cursor());
+ ast->setName(name);
+ } else if (tokenStream->lookAhead() == Token___typeof) {
+ advance();
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+ TypeIdAST *typeId = 0;
+ parseTypeId(typeId);
+ ADVANCE(')', ")");
+ } else {
+ AbstractExpressionAST *e = 0;
+ parseUnaryExpression(e);
+ }
+ } else if (onlyIntegral) {
+ tokenStream->rewind(start);
+ return false;
+ } else {
+ NameAST *name = 0;
+ if (!parseName(name)) {
+ tokenStream->rewind(start);
+ return false;
+ }
+ ast->setName(name);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parsePtrOperator(AST *&node)
+{
+ int start = tokenStream->cursor();
+ int tok = tokenStream->lookAhead();
+ AST *memPtr = 0;
+
+ switch (tok) {
+ case '&':
+ case '*':
+ advance();
+ break;
+
+ case Token_scope:
+ case Token_identifier:
+ if (!parsePtrToMember(memPtr)) {
+ tokenStream->rewind(start);
+ return false;
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ AST *ast = CreateNode<AST>(m_pool);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseTemplateArgument(AST *&node)
+{
+ int start = tokenStream->cursor();
+
+ TypeIdAST *typeId = 0;
+ if (parseTypeId(typeId)) {
+ if (tokenStream->lookAhead() == ',' || tokenStream->lookAhead() == '>') {
+ node = typeId;
+ return true;
+ }
+ }
+
+ tokenStream->rewind(start);
+ AbstractExpressionAST *expr = 0;
+ if (!parseLogicalOrExpression(expr, true)) {
+ return false;
+ }
+ node = expr;
+
+ return true;
+}
+
+bool Parser::parseTypeSpecifier(TypeSpecifierAST *&spec)
+{
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ if (parseElaboratedTypeSpecifier(spec) || parseSimpleTypeSpecifier(spec)) {
+ spec->setCvQualify(cv);
+
+ AST *cv2 = 0;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify(cv2);
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseDeclarator(DeclaratorAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ DeclaratorAST *ast = CreateNode<DeclaratorAST>(m_pool);
+
+ DeclaratorAST *decl = 0;
+ NameAST *declId = 0;
+
+ AST *ptrOp = 0;
+ while (parsePtrOperator(ptrOp)) {
+ ast->addPtrOp(ptrOp);
+ }
+
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+
+ if (!parseDeclarator(decl)) {
+ return false;
+ }
+ ast->setSubDeclarator(decl);
+
+ if (tokenStream->lookAhead() != ')') {
+ return false;
+ }
+ advance();
+ } else {
+ if (tokenStream->lookAhead() == ':') {
+ // unnamed bitfield
+ } else if (parseDeclaratorId(declId)) {
+ ast->setDeclaratorId(declId);
+ } else {
+ tokenStream->rewind(start);
+ return false;
+ }
+
+ if (tokenStream->lookAhead() == ':') {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ if (!parseConstantExpression(expr)) {
+ reportError(i18n("Constant expression expected"));
+ }
+ goto update_pos;
+ }
+ }
+
+ {
+ bool isVector = false;
+
+ while (tokenStream->lookAhead() == '[') {
+ int startArray = tokenStream->cursor();
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(']', "]");
+ AST *array = CreateNode<AST>(m_pool);
+ UPDATE_POS(array, startArray, tokenStream->cursor());
+ ast->addArrayDimension(array);
+ isVector = true;
+ }
+
+ bool skipParen = false;
+ if (tokenStream->lookAhead() == Token_identifier
+ && tokenStream->lookAhead(1) == '('
+ && tokenStream->lookAhead(2) == '(') {
+ advance();
+ advance();
+ skipParen = true;
+ }
+
+ int tok = tokenStream->lookAhead();
+ if (ast->subDeclarator() && !(isVector || tok == '(' || tok == ',' || tok == ';' || tok == '=')) {
+ tokenStream->rewind(start);
+ return false;
+ }
+
+ int index = tokenStream->cursor();
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+
+ ParameterDeclarationClauseAST *params = 0;
+ if (!parseParameterDeclarationClause(params)) {
+ tokenStream->rewind(index);
+ goto update_pos;
+ }
+ ast->setParameterDeclarationClause(params);
+
+ if (tokenStream->lookAhead() != ')') {
+ tokenStream->rewind(index);
+ goto update_pos;
+ }
+
+ advance(); // skip ')'
+
+ AST *constant = 0;
+ parseCvQualify(constant);
+ ast->setConstant(constant);
+
+ AST *except = 0;
+ if (parseExceptionSpecification(except)) {
+ ast->setExceptionSpecification(except);
+ }
+ }
+
+ if (skipParen) {
+ if (tokenStream->lookAhead() != ')') {
+ reportError(i18n("')' expected"));
+ } else
+ advance();
+ }
+ }
+
+update_pos:
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAbstractDeclarator(DeclaratorAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ DeclaratorAST *ast = CreateNode<DeclaratorAST>(m_pool);
+ DeclaratorAST *decl = 0;
+
+ AST *ptrOp = 0;
+ while (parsePtrOperator(ptrOp)) {
+ ast->addPtrOp(ptrOp);
+ }
+
+ int index = tokenStream->cursor();
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+
+ if (!parseAbstractDeclarator(decl)) {
+ tokenStream->rewind(index);
+ goto label1;
+ }
+
+ ast->setSubDeclarator(decl);
+
+ if (tokenStream->lookAhead() != ')'){
+ tokenStream->rewind(start);
+ return false;
+ }
+ advance();
+ } else if (tokenStream->lookAhead() == ':') {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ if (!parseConstantExpression(expr)) {
+ reportError(i18n("Constant expression expected"));
+ }
+ goto update_pos;
+ }
+
+label1:
+ {
+ bool isVector = false;
+
+ while (tokenStream->lookAhead() == '[') {
+ int startArray = tokenStream->cursor();
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(']', "]");
+ AST *array = CreateNode<AST>(m_pool);
+ UPDATE_POS(array, startArray, tokenStream->cursor());
+ ast->addArrayDimension(array);
+ isVector = true;
+ }
+
+ int tok = tokenStream->lookAhead();
+ if (ast->subDeclarator() && !(isVector || tok == '(' || tok == ',' || tok == ';' || tok == '=')) {
+ tokenStream->rewind(start);
+ return false;
+ }
+
+ int index = tokenStream->cursor();
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+
+ ParameterDeclarationClauseAST *params = 0;
+ if (!parseParameterDeclarationClause(params)) {
+ tokenStream->rewind(index);
+ goto update_pos;
+ }
+ ast->setParameterDeclarationClause(params);
+
+ if (tokenStream->lookAhead() != ')') {
+ tokenStream->rewind(index);
+ goto update_pos;
+ }
+
+ advance(); // skip ')'
+
+ AST *constant = 0;
+ parseCvQualify(constant);
+ ast->setConstant(constant);
+
+ AST *except = 0;
+ if (parseExceptionSpecification(except)) {
+ ast->setExceptionSpecification(except);
+ }
+ }
+ }
+
+update_pos:
+ if (tokenStream->cursor() == start)
+ return false;
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_enum) {
+ return false;
+ }
+
+ advance();
+
+ NameAST *name = 0;
+ parseName(name);
+
+ if (tokenStream->lookAhead() != '{') {
+ tokenStream->rewind(start);
+ return false;
+ }
+ advance();
+
+ EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(m_pool);
+ ast->setName(name);
+
+ EnumeratorAST *enumerator = 0;
+ if (parseEnumerator(enumerator)) {
+ ast->addEnumerator(enumerator);
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (!parseEnumerator(enumerator)) {
+ //reportError(i18n("Enumerator expected"));
+ break;
+ }
+
+ ast->addEnumerator(enumerator);
+ }
+ }
+
+ if (tokenStream->lookAhead() != '}')
+ reportError(i18n("} missing"));
+ else
+ advance();
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameterList(TemplateParameterListAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ TemplateParameterListAST *ast = CreateNode<TemplateParameterListAST>(m_pool);
+
+ TemplateParameterAST *param = 0;
+ if (!parseTemplateParameter(param)) {
+ return false;
+ }
+ ast->addTemplateParameter(param);
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (!parseTemplateParameter(param)) {
+ syntaxError();
+ break;
+ } else {
+ ast->addTemplateParameter(param);
+ }
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameter(TemplateParameterAST *&node)
+{
+ int start = tokenStream->cursor();
+ TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(m_pool);
+
+ TypeParameterAST *typeParameter = 0;
+ ParameterDeclarationAST *param = 0;
+
+ int tk = tokenStream->lookAhead();
+
+ if ((tk == Token_class || tk == Token_typename || tk == Token_template) && parseTypeParameter(typeParameter)) {
+ ast->setTypeParameter(typeParameter);
+ goto ok;
+ }
+
+ if (!parseParameterDeclaration(param))
+ return false;
+ ast->setTypeValueParameter(param);
+
+ok:
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeParameter(TypeParameterAST *&node)
+{
+ int start = tokenStream->cursor();
+ TypeParameterAST *ast = CreateNode<TypeParameterAST>(m_pool);
+
+ AST_FROM_TOKEN(kind, tokenStream->cursor());
+ ast->setKind(kind);
+
+ switch(tokenStream->lookAhead()) {
+
+ case Token_class:
+ case Token_typename:
+ {
+ advance(); // skip class
+
+ // parse optional name
+ NameAST *name = 0;
+ if(parseName(name)){
+ ast->setName(name);
+
+ if (tokenStream->lookAhead() == '='){
+ advance();
+
+ TypeIdAST *typeId = 0;
+ if(!parseTypeId(typeId)){
+ //syntaxError();
+ tokenStream->rewind(start);
+ return false;
+ }
+ ast->setTypeId(typeId);
+ } else if (!(tokenStream->lookAhead() == ',' || tokenStream->lookAhead() == '>')) {
+ tokenStream->rewind(start);
+ return false;
+ }
+ }
+ }
+ break;
+
+ case Token_template:
+ {
+ advance(); // skip template
+ ADVANCE('<', "<");
+
+ TemplateParameterListAST *params = 0;
+ if (!parseTemplateParameterList(params)) {
+ return false;
+ }
+ ast->setTemplateParameterList(params);
+
+ ADVANCE('>', ">");
+
+ if (tokenStream->lookAhead() == Token_class)
+ advance();
+
+ // parse optional name
+ NameAST *name = 0;
+ if (parseName(name)) {
+ ast->setName(name);
+ if (tokenStream->lookAhead() == '=') {
+ advance();
+
+ TypeIdAST *typeId = 0;
+ if (!parseTypeId(typeId)) {
+ syntaxError();
+ return false;
+ }
+ ast->setTypeId(typeId);
+ }
+ }
+
+ if (tokenStream->lookAhead() == '=') {
+ advance();
+
+ NameAST *templ_name = 0;
+ parseName(templ_name);
+ }
+ }
+ break;
+
+ default:
+ return false;
+
+ } // end switch
+
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseStorageClassSpecifier(AST *&node)
+{
+ int start = tokenStream->cursor();
+ AST *ast = CreateNode<AST>(m_pool);
+
+ while (tokenStream->lookAhead()) {
+ int tk = tokenStream->lookAhead();
+ if (tk == Token_friend || tk == Token_auto || tk == Token_register || tk == Token_static ||
+ tk == Token_extern || tk == Token_mutable) {
+ int startNode = tokenStream->cursor();
+ advance();
+
+ AST *n = CreateNode<AST>(m_pool);
+ UPDATE_POS(n, startNode, tokenStream->cursor());
+ n->setParent(ast);
+ } else
+ break;
+ }
+
+ if (length(ast->children()) == 0)
+ return false;
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseFunctionSpecifier(AST *&node)
+{
+ int start = tokenStream->cursor();
+ AST *ast = CreateNode<AST>(m_pool);
+
+ while (tokenStream->lookAhead()) {
+ int tk = tokenStream->lookAhead();
+ if (tk == Token_inline || tk == Token_virtual || tk == Token_explicit) {
+ int startNode = tokenStream->cursor();
+ advance();
+
+ AST *n = CreateNode<AST>(m_pool);
+ UPDATE_POS(n, startNode, tokenStream->cursor());
+ n->setParent(ast);
+ } else {
+ break;
+ }
+ }
+
+ if (length(ast->children()) == 0)
+ return false;
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseTypeId(TypeIdAST *&node)
+{
+ /// @todo implement the AST for typeId
+ int start = tokenStream->cursor();
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifier(spec)) {
+ tokenStream->rewind(start);
+ return false;
+ }
+
+ DeclaratorAST *decl = 0;
+ parseAbstractDeclarator(decl);
+
+ TypeIdAST *ast = CreateNode<TypeIdAST>(m_pool);
+ ast->setTypeSpecifier(spec);
+ ast->setDeclarator(decl);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclaratorList(InitDeclaratorListAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ InitDeclaratorListAST *ast = CreateNode<InitDeclaratorListAST>(m_pool);
+ InitDeclaratorAST *decl = 0;
+
+ if (!parseInitDeclarator(decl)) {
+ return false;
+ }
+ ast->addInitDeclarator(decl);
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (!parseInitDeclarator(decl)) {
+ syntaxError();
+ break;
+ }
+ ast->addInitDeclarator(decl);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ParameterDeclarationClauseAST *ast = CreateNode<ParameterDeclarationClauseAST>(m_pool);
+
+ ParameterDeclarationListAST *params = 0;
+ if (!parseParameterDeclarationList(params)) {
+
+ if (tokenStream->lookAhead() == ')')
+ goto good;
+
+ if (tokenStream->lookAhead() == Token_ellipsis && tokenStream->lookAhead(1) == ')') {
+ AST_FROM_TOKEN(ellipsis, tokenStream->cursor());
+ ast->setEllipsis(ellipsis);
+ advance();
+ goto good;
+ }
+ return false;
+ }
+
+ if (tokenStream->lookAhead() == Token_ellipsis) {
+ AST_FROM_TOKEN(ellipsis, tokenStream->cursor());
+ ast->setEllipsis(ellipsis);
+ advance();
+ }
+
+good:
+ ast->setParameterDeclarationList(params);
+
+ /// @todo add ellipsis
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationList(ParameterDeclarationListAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ParameterDeclarationListAST *ast = CreateNode<ParameterDeclarationListAST>(m_pool);
+
+ ParameterDeclarationAST *param = 0;
+ if (!parseParameterDeclaration(param)) {
+ tokenStream->rewind(start);
+ return false;
+ }
+ ast->addParameter(param);
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (tokenStream->lookAhead() == Token_ellipsis)
+ break;
+
+ if (!parseParameterDeclaration(param)) {
+ tokenStream->rewind(start);
+ return false;
+ }
+ ast->addParameter(param);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AST *storage = 0;
+ parseStorageClassSpecifier(storage);
+
+ // parse decl spec
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifier(spec)) {
+ tokenStream->rewind(start);
+ return false;
+ }
+
+ int index = tokenStream->cursor();
+
+ DeclaratorAST *decl = 0;
+ if (!parseDeclarator(decl)) {
+ tokenStream->rewind(index);
+
+ // try with abstract declarator
+ parseAbstractDeclarator(decl);
+ }
+
+ AbstractExpressionAST *expr = 0;
+ if (tokenStream->lookAhead() == '=') {
+ advance();
+ if (!parseLogicalOrExpression(expr,true)) {
+ //reportError(i18n("Expression expected"));
+ }
+ }
+
+ ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(m_pool);
+ ast->setTypeSpec(spec);
+ ast->setDeclarator(decl);
+ ast->setExpression(expr);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseClassSpecifier(TypeSpecifierAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AST *classKey = 0;
+ int classKeyStart = tokenStream->cursor();
+
+ int kind = tokenStream->lookAhead();
+ if (kind == Token_class || kind == Token_struct || kind == Token_union) {
+ AST *asn = CreateNode<AST>(m_pool);
+ classKey = asn;
+ advance();
+ UPDATE_POS(classKey, classKeyStart, tokenStream->cursor());
+ } else {
+ return false;
+ }
+
+ AST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ while (tokenStream->lookAhead() == Token_identifier && tokenStream->lookAhead(1) == Token_identifier)
+ advance();
+
+ NameAST *name = 0;
+ parseName(name);
+
+ BaseClauseAST *bases = 0;
+ if (tokenStream->lookAhead() == ':') {
+ if (!parseBaseClause(bases)) {
+ skipUntil('{');
+ }
+ }
+
+ if (tokenStream->lookAhead() != '{') {
+ tokenStream->rewind(start);
+ return false;
+ }
+
+ ADVANCE('{', "{");
+
+ ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(m_pool);
+ ast->setWinDeclSpec(winDeclSpec);
+ ast->setClassKey(classKey);
+ ast->setName(name);
+ ast->setBaseClause(bases);
+
+ while (tokenStream->lookAhead()) {
+ if (tokenStream->lookAhead() == '}')
+ break;
+
+ DeclarationAST *memSpec = 0;
+ int startDecl = tokenStream->cursor();
+ if (!parseMemberSpecification(memSpec)) {
+ if (startDecl == tokenStream->cursor())
+ advance(); // skip at least one token
+ skipUntilDeclaration();
+ } else
+ ast->addDeclaration(memSpec);
+ }
+
+ if (tokenStream->lookAhead() != '}') {
+ reportError(i18n("} missing"));
+ } else
+ advance();
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAccessSpecifier(AST *&node)
+{
+ int start = tokenStream->cursor();
+
+ switch(tokenStream->lookAhead()) {
+ case Token_public:
+ case Token_protected:
+ case Token_private: {
+ AST *asn = CreateNode<AST>(m_pool);
+ node = asn;
+ advance();
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Parser::parseMemberSpecification(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AST *access = 0;
+
+ if (tokenStream->lookAhead() == ';') {
+ advance();
+ return true;
+ } else if (tokenStream->lookAhead() == Token_Q_OBJECT || tokenStream->lookAhead() == Token_K_DCOP) {
+ advance();
+ return true;
+ } else if (tokenStream->lookAhead() == Token_signals
+ || tokenStream->lookAhead() == Token_k_dcop
+ || tokenStream->lookAhead() == Token_k_dcop_signals) {
+ AccessDeclarationAST *ast = CreateNode<AccessDeclarationAST>(m_pool);
+ advance();
+ AST *n = CreateNode<AST>(m_pool);
+ UPDATE_POS(n, start, tokenStream->cursor());
+ ast->addAccess(n);
+ ADVANCE(':', ":");
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ } else if (parseTypedef(node)) {
+ return true;
+ } else if (parseUsing(node)) {
+ return true;
+ } else if (parseTemplateDeclaration(node)) {
+ return true;
+ } else if (parseAccessSpecifier(access)) {
+ AccessDeclarationAST *ast = CreateNode<AccessDeclarationAST>(m_pool);
+ ast->addAccess(access);
+
+ int startSlot = tokenStream->cursor();
+ if (tokenStream->lookAhead() == Token_slots) {
+ advance();
+ AST *sl = CreateNode<AST>(m_pool);
+ UPDATE_POS(sl, startSlot, tokenStream->cursor());
+ ast->addAccess(sl);
+ }
+ ADVANCE(':', ":");
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ }
+
+ tokenStream->rewind(start);
+
+ AST *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) {
+ spec->setCvQualify(cv);
+
+ AST *cv2 = 0;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify(cv2);
+
+ InitDeclaratorListAST *declarators = 0;
+ parseInitDeclaratorList(declarators);
+ ADVANCE(';', ";");
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+ ast->setTypeSpec(spec);
+ ast->setInitDeclaratorList(declarators);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+ }
+
+ tokenStream->rewind(start);
+ return parseDeclarationInternal(node);
+}
+
+bool Parser::parseCtorInitializer(AST *&/*node*/)
+{
+ if (tokenStream->lookAhead() != ':') {
+ return false;
+ }
+ advance();
+
+ AST *inits = 0;
+ if (!parseMemInitializerList(inits)) {
+ reportError(i18n("Member initializers expected"));
+ }
+
+ return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ int tk = tokenStream->lookAhead();
+ if (tk == Token_class ||
+ tk == Token_struct ||
+ tk == Token_union ||
+ tk == Token_enum ||
+ tk == Token_typename)
+ {
+ AST *kind = CreateNode<AST>(m_pool);
+ advance();
+ UPDATE_POS(kind, start, tokenStream->cursor());
+
+ NameAST *name = 0;
+
+ if (parseName(name)) {
+ ElaboratedTypeSpecifierAST *ast = CreateNode<ElaboratedTypeSpecifierAST>(m_pool);
+ ast->setKind(kind);
+ ast->setName(name);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+
+ tokenStream->rewind(start);
+ return false;
+}
+
+bool Parser::parseDeclaratorId(NameAST *&node)
+{
+ return parseName(node);
+}
+
+bool Parser::parseExceptionSpecification(AST *&node)
+{
+ if (tokenStream->lookAhead() != Token_throw) {
+ return false;
+ }
+ advance();
+
+ ADVANCE('(', "(");
+ if (tokenStream->lookAhead() == Token_ellipsis) {
+ // extension found in MSVC++ 7.x headers
+ int start = tokenStream->cursor();
+ AST *ast = CreateNode<AST>(m_pool);
+ AST_FROM_TOKEN(ellipsis, tokenStream->cursor());
+ ellipsis->setParent(ast);
+ advance();
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ } else {
+ parseTypeIdList(node);
+ }
+ ADVANCE(')', ")");
+
+ return true;
+}
+
+bool Parser::parseEnumerator(EnumeratorAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_identifier) {
+ return false;
+ }
+ advance();
+
+ EnumeratorAST *ena = CreateNode<EnumeratorAST>(m_pool);
+ node = ena;
+
+ AST *id = CreateNode<AST>(m_pool);
+ UPDATE_POS(id, start, tokenStream->cursor());
+ node->setId(id);
+
+ if (tokenStream->lookAhead() == '=') {
+ advance();
+
+ AbstractExpressionAST *expr = 0;
+ if (!parseConstantExpression(expr)) {
+ reportError(i18n("Constant expression expected"));
+ }
+ node->setExpression(expr);
+ }
+
+ UPDATE_POS(node, start, tokenStream->cursor());
+
+ return true;
+}
+
+bool Parser::parseInitDeclarator(InitDeclaratorAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ DeclaratorAST *decl = 0;
+ AST *init = 0;
+ if (!parseDeclarator(decl)) {
+ return false;
+ }
+
+ parseInitializer(init);
+
+ InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(m_pool);
+ ast->setDeclarator(decl);
+ ast->setInitializer(init);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+
+
+bool Parser::parseBaseClause(BaseClauseAST *&node)
+{
+ int start = tokenStream->cursor();
+ if (tokenStream->lookAhead() != ':') {
+ return false;
+ }
+ advance();
+
+ BaseClauseAST *bca = CreateNode<BaseClauseAST>(m_pool);
+
+ BaseSpecifierAST *baseSpec = 0;
+ if (parseBaseSpecifier(baseSpec)) {
+ bca->addBaseSpecifier(baseSpec);
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (!parseBaseSpecifier(baseSpec)) {
+ reportError(i18n("Base class specifier expected"));
+ return false;
+ }
+ bca->addBaseSpecifier(baseSpec);
+ }
+ } else
+ return false;
+
+ UPDATE_POS(bca, start, tokenStream->cursor());
+ node = bca;
+
+ return true;
+}
+
+bool Parser::parseInitializer(AST *&node)
+{
+ if (tokenStream->lookAhead() == '=') {
+ advance();
+
+ if (!parseInitializerClause(node)) {
+ reportError(i18n("Initializer clause expected"));
+ return false;
+ }
+ return true;
+ } else if (tokenStream->lookAhead() == '(') {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ skipCommaExpression(expr);
+ CHECK(')', ")");
+ node = expr;
+ return true;
+ }
+
+ return false;
+}
+
+bool Parser::parseMemInitializerList(AST *&/*node*/)
+{
+ AST *init = 0;
+ if (!parseMemInitializer(init)) {
+ return false;
+ }
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+
+ if (!parseMemInitializer(init)) {
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializer(AST *&/*node*/)
+{
+ NameAST *initId = 0;
+ if (!parseMemInitializerId(initId)) {
+ reportError(i18n("Identifier expected"));
+ return false;
+ }
+ ADVANCE('(', "(");
+ AbstractExpressionAST *expr = 0;
+ skipCommaExpression(expr);
+ ADVANCE(')', ")");
+
+ return true;
+}
+
+bool Parser::parseTypeIdList(AST *&node)
+{
+
+ int start = tokenStream->cursor();
+
+ TypeIdAST *typeId = 0;
+ if (!parseTypeId(typeId)) {
+ return false;
+ }
+
+ AST *ast = CreateNode<AST>(m_pool);
+ typeId->setParent(ast);
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+ if (parseTypeId(typeId)) {
+ typeId->setParent(ast);
+ } else {
+ reportError(i18n("Type id expected"));
+ break;
+ }
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node)
+{
+ int start = tokenStream->cursor();
+ BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(m_pool);
+
+ AST *access = 0;
+ if (tokenStream->lookAhead() == Token_virtual) {
+ AST_FROM_TOKEN(virt, tokenStream->cursor());
+ ast->setIsVirtual(virt);
+
+ advance();
+
+ parseAccessSpecifier(access);
+ } else {
+ parseAccessSpecifier(access);
+
+ if (tokenStream->lookAhead() == Token_virtual) {
+ AST_FROM_TOKEN(virt, tokenStream->cursor());
+ ast->setIsVirtual(virt);
+ advance();
+ }
+ }
+
+ NameAST *name = 0;
+ if (!parseName(name)) {
+ reportError(i18n("Class name expected"));
+ }
+
+ ast->setAccess(access);
+ ast->setName(name);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseInitializerClause(AST *&node)
+{
+ if (tokenStream->lookAhead() == '{') {
+ if (!skip('{','}')) {
+ reportError(i18n("} missing"));
+ } else
+ advance();
+ } else {
+ AbstractExpressionAST *expr = 0;
+ if (!parseAssignmentExpression(expr)) {
+ //reportError(i18n("Expression expected"));
+ }
+ node = expr;
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializerId(NameAST *&node)
+{
+
+ return parseName(node);
+}
+
+bool Parser::parsePtrToMember(AST *&/*node*/) /// ### create the AST node
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() == Token_scope)
+ advance();
+
+ ClassOrNamespaceNameAST *name = 0;
+ while (tokenStream->lookAhead() == Token_identifier) {
+
+ if (!parseUnqualifiedName(name))
+ break;
+
+ if (tokenStream->lookAhead() == Token_scope
+ && tokenStream->lookAhead(1) == '*') {
+ advance();
+ advance();
+ return true;
+ }
+
+ if (tokenStream->lookAhead() == Token_scope)
+ advance();
+ }
+
+ tokenStream->rewind(start);
+ return false;
+}
+
+bool Parser::parseUnqualifiedName(ClassOrNamespaceNameAST *&node, bool parseTemplateId)
+{
+ int start = tokenStream->cursor();
+ bool isDestructor = false;
+
+ ClassOrNamespaceNameAST *ast = CreateNode<ClassOrNamespaceNameAST>(m_pool);
+
+ if (tokenStream->lookAhead() == Token_identifier) {
+ int startName = tokenStream->cursor();
+ AST *n = CreateNode<AST>(m_pool);
+ advance();
+ UPDATE_POS(n, startName, tokenStream->cursor());
+ ast->setName(n);
+ } else if (tokenStream->lookAhead() == '~' && tokenStream->lookAhead(1) == Token_identifier) {
+ int startName = tokenStream->cursor();
+ AST *n = CreateNode<AST>(m_pool);
+ advance(); // skip ~
+ advance(); // skip classname
+ UPDATE_POS(n, startName, tokenStream->cursor());
+ ast->setName(n);
+ isDestructor = true;
+ } else if (tokenStream->lookAhead() == Token_operator) {
+ AST *n = 0;
+ if (!parseOperatorFunctionId(n))
+ return false;
+ ast->setName(n);
+ } else {
+ return false;
+ }
+
+ if (parseTemplateId && !isDestructor) {
+
+ int index = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() == '<') {
+ advance();
+
+ // optional template arguments
+ TemplateArgumentListAST *args = 0;
+ parseTemplateArgumentList(args);
+
+ if (tokenStream->lookAhead() != '>') {
+ tokenStream->rewind(index);
+ } else {
+ advance();
+ ast->setTemplateArgumentList(args);
+ }
+ }
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStringLiteral(AST *&node)
+{
+ int start = tokenStream->cursor();
+
+ while (tokenStream->lookAhead()) {
+ if (tokenStream->lookAhead() == Token_identifier &&
+ tokenStream->currentTokenText() == "L" && tokenStream->lookAhead(1) == Token_string_literal) {
+
+ advance();
+ advance();
+ } else if (tokenStream->lookAhead() == Token_string_literal) {
+ advance();
+ } else
+ return false;
+ }
+
+ AST *ast = CreateNode<AST>(m_pool);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::skipExpressionStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *expr = 0;
+ skipCommaExpression(expr);
+
+ ADVANCE(';', ";");
+
+ ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(m_pool);
+ ast->setExpression(expr);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ switch(tokenStream->lookAhead()) {
+
+ case Token_while:
+ return parseWhileStatement(node);
+
+ case Token_do:
+ return parseDoStatement(node);
+
+ case Token_for:
+ return parseForStatement(node);
+
+ case Token_if:
+ return parseIfStatement(node);
+
+ case Token_switch:
+ return parseSwitchStatement(node);
+
+ case Token_try:
+ return parseTryBlockStatement(node);
+
+ case Token_case:
+ case Token_default:
+ return parseLabeledStatement(node);
+
+ case Token_break:
+ case Token_continue:
+ advance();
+ ADVANCE(';', ";");
+ return true;
+
+ case Token_goto:
+ advance();
+ ADVANCE(Token_identifier, "identifier");
+ ADVANCE(';', ";");
+ return true;
+
+ case Token_return:
+ {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ skipCommaExpression(expr);
+
+ ADVANCE(';', ";");
+
+ ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(m_pool);
+ ast->setExpression(expr);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ }
+ return true;
+
+ case '{':
+ return parseCompoundStatement(node);
+
+ case Token_identifier:
+ if (parseLabeledStatement(node))
+ return true;
+ break;
+ }
+
+ if (parseDeclarationStatement(node))
+ return true;
+
+ return skipExpressionStatement(node);
+}
+
+bool Parser::parseCondition(ConditionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ConditionAST *ast = CreateNode<ConditionAST>(m_pool);
+ TypeSpecifierAST *spec = 0;
+
+ if (parseTypeSpecifier(spec)) {
+ DeclaratorAST *decl = 0;
+ if (parseDeclarator(decl) && tokenStream->lookAhead() == '=') {
+ advance();
+
+ AbstractExpressionAST *expr = 0;
+ if (parseExpression(expr)) {
+ ast->setTypeSpec(spec);
+ ast->setDeclarator(decl);
+ ast->setExpression(expr);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ }
+
+ tokenStream->rewind(start);
+
+ AbstractExpressionAST *expr = 0;
+ if (!skipCommaExpression(expr)) {
+ return false;
+ }
+
+ ast->setExpression(expr);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+
+bool Parser::parseWhileStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ADVANCE(Token_while, "while");
+ ADVANCE('(' , "(");
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(i18n("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body)) {
+ reportError(i18n("statement expected"));
+ return false;
+ }
+
+ WhileStatementAST *ast = CreateNode<WhileStatementAST>(m_pool);
+ ast->setCondition(cond);
+ ast->setStatement(body);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDoStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ADVANCE(Token_do, "do");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body)) {
+ reportError(i18n("statement expected"));
+ //return false;
+ }
+
+ ADVANCE_NR(Token_while, "while");
+ ADVANCE_NR('(' , "(");
+
+ AbstractExpressionAST *expr = 0;
+ if (!skipCommaExpression(expr)) {
+ reportError(i18n("expression expected"));
+ //return false;
+ }
+
+ ADVANCE_NR(')', ")");
+ ADVANCE_NR(';', ";");
+
+ DoStatementAST *ast = CreateNode<DoStatementAST>(m_pool);
+ ast->setStatement(body);
+ //ast->setCondition(condition);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ADVANCE(Token_for, "for");
+ ADVANCE('(', "(");
+
+ StatementAST *init = 0;
+ if (!parseForInitStatement(init)) {
+ reportError(i18n("for initialization expected"));
+ return false;
+ }
+
+ ConditionAST *cond = 0;
+ parseCondition(cond);
+ ADVANCE(';', ";");
+
+ AbstractExpressionAST *expr = 0;
+ skipCommaExpression(expr);
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body))
+ return false;
+
+ ForStatementAST *ast = CreateNode<ForStatementAST>(m_pool);
+ ast->setInitStatement(init);
+ ast->setCondition(cond);
+ // ast->setExpression(expression);
+ ast->setStatement(body);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForInitStatement(StatementAST *&node)
+{
+ if (parseDeclarationStatement(node))
+ return true;
+
+ return skipExpressionStatement(node);
+}
+
+bool Parser::parseCompoundStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != '{') {
+ return false;
+ }
+ advance();
+
+ StatementListAST *ast = CreateNode<StatementListAST>(m_pool);
+
+ while (tokenStream->lookAhead()) {
+ if (tokenStream->lookAhead() == '}')
+ break;
+
+ StatementAST *stmt = 0;
+ int startStmt = tokenStream->cursor();
+ if (!parseStatement(stmt)) {
+ if (startStmt == tokenStream->cursor())
+ advance();
+ skipUntilStatement();
+ } else {
+ ast->addStatement(stmt);
+ }
+ }
+
+ if (tokenStream->lookAhead() != '}') {
+ reportError(i18n("} expected"));
+ } else {
+ advance();
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseIfStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ ADVANCE(Token_if, "if");
+
+ ADVANCE('(' , "(");
+
+ IfStatementAST *ast = CreateNode<IfStatementAST>(m_pool);
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(i18n("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *stmt = 0;
+ if (!parseStatement(stmt)) {
+ reportError(i18n("statement expected"));
+ return false;
+ }
+
+ ast->setCondition(cond);
+ ast->setStatement(stmt);
+
+ if (tokenStream->lookAhead() == Token_else) {
+ advance();
+ StatementAST *elseStmt = 0;
+ if (!parseStatement(elseStmt)) {
+ reportError(i18n("statement expected"));
+ return false;
+ }
+ ast->setElseStatement(elseStmt);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseSwitchStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+ ADVANCE(Token_switch, "switch");
+
+ ADVANCE('(' , "(");
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(i18n("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *stmt = 0;
+ if (!parseStatement(stmt)) {
+ syntaxError();
+ return false;
+ }
+
+ SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(m_pool);
+ ast->setCondition(cond);
+ ast->setStatement(stmt);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLabeledStatement(StatementAST *&node)
+{
+ switch(tokenStream->lookAhead()) {
+ case Token_identifier:
+ case Token_default:
+ if (tokenStream->lookAhead(1) == ':') {
+ advance();
+ advance();
+
+ StatementAST *stmt = 0;
+ LabeledStatementAST *ast = CreateNode<LabeledStatementAST>(m_pool);
+ node = ast;
+ if (parseStatement(stmt)) {
+ ast->setStatement(stmt);
+ return true;
+ }
+ }
+ break;
+
+ case Token_case:
+ {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ if (!parseConstantExpression(expr)) {
+ reportError(i18n("expression expected"));
+ } else if (tokenStream->lookAhead() == Token_ellipsis) {
+ advance();
+
+ AbstractExpressionAST *expr2 = 0;
+ if (!parseConstantExpression(expr2)) {
+ reportError(i18n("expression expected"));
+ }
+ }
+ ADVANCE(':', ":");
+
+ StatementAST *stmt = 0;
+ LabeledStatementAST *ast = CreateNode<LabeledStatementAST>(m_pool);
+ node = ast;
+ ast->setExpression(expr);
+
+ if (parseStatement(stmt)) {
+ ast->setStatement(stmt);
+ return true;
+ }
+ }
+ break;
+
+ }
+ return false;
+}
+
+bool Parser::parseBlockDeclaration(DeclarationAST *&node)
+{
+ switch(tokenStream->lookAhead()) {
+ case Token_typedef:
+ return parseTypedef(node);
+ case Token_using:
+ return parseUsing(node);
+ case Token_asm:
+ return parseAsmDefinition(node);
+ case Token_namespace:
+ return parseNamespaceAliasDefinition(node);
+ }
+
+ int start = tokenStream->cursor();
+
+ AST *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifierOrClassSpec(spec)) { // replace with simpleTypeSpecifier?!?!
+ tokenStream->rewind(start);
+ return false;
+ }
+ spec->setCvQualify(cv);
+
+ AST *cv2 = 0;
+ parseCvQualify(cv2);
+ spec->setCv2Qualify(cv2);
+
+ InitDeclaratorListAST *declarators = 0;
+ parseInitDeclaratorList(declarators);
+
+ if (tokenStream->lookAhead() != ';') {
+ tokenStream->rewind(start);
+ return false;
+ }
+ advance();
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+ ast->setTypeSpec(spec);
+ ast->setInitDeclaratorList(declarators);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&/*node*/)
+{
+ if (tokenStream->lookAhead() != Token_namespace) {
+ return false;
+ }
+ advance();
+
+ ADVANCE(Token_identifier, "identifier");
+ ADVANCE('=', "=");
+
+ NameAST *name = 0;
+ if (!parseName(name)) {
+ reportError(i18n("Namespace name expected"));
+ }
+
+ ADVANCE(';', ";");
+
+ return true;
+
+}
+
+bool Parser::parseDeclarationStatement(StatementAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ DeclarationAST *decl = 0;
+ if (!parseBlockDeclaration(decl))
+ return false;
+
+ DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(m_pool);
+ ast->setDeclaration(decl);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclarationInternal(DeclarationAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ // that is for the case '__declspec(dllexport) int ...' or
+ // '__declspec(dllexport) inline int ...', etc.
+ AST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ AST *funSpec = 0;
+ bool hasFunSpec = parseFunctionSpecifier(funSpec);
+
+ AST *storageSpec = 0;
+ bool hasStorageSpec = parseStorageClassSpecifier(storageSpec);
+
+ if (hasStorageSpec && !hasFunSpec)
+ hasFunSpec = parseFunctionSpecifier(funSpec);
+
+ // that is for the case 'friend __declspec(dllexport) ....'
+ AST *winDeclSpec2 = 0;
+ parseWinDeclSpec(winDeclSpec2);
+
+ AST *cv = 0;
+ parseCvQualify(cv);
+
+ int index = tokenStream->cursor();
+ NameAST *name = 0;
+ if (parseName(name) && tokenStream->lookAhead() == '(') {
+ // no type specifier, maybe a constructor or a cast operator??
+
+ tokenStream->rewind(index);
+
+ InitDeclaratorAST *declarator = 0;
+ if (parseInitDeclarator(declarator)) {
+ switch(tokenStream->lookAhead()) {
+ case ';':
+ {
+ advance();
+
+ InitDeclaratorListAST *declarators = CreateNode<InitDeclaratorListAST>(m_pool);
+
+ // update declarators position
+ if (declarator)
+ declarators->setPosition(declarator->startToken(), declarator->endToken());
+ declarators->addInitDeclarator(declarator);
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+ ast->setInitDeclaratorList(declarators);
+ node = ast;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+
+ }
+ break;
+
+ case ':':
+ {
+ AST *ctorInit = 0;
+ StatementListAST *funBody = 0;
+ if (parseCtorInitializer(ctorInit) && parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool);
+ ast->setStorageSpecifier(storageSpec);
+ ast->setFunctionSpecifier(funSpec);
+ ast->setInitDeclarator(declarator);
+ ast->setFunctionBody(funBody);
+ node = ast;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+ }
+ break;
+
+ case '{':
+ {
+ StatementListAST *funBody = 0;
+ if (parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool);
+ ast->setStorageSpecifier(storageSpec);
+ ast->setFunctionSpecifier(funSpec);
+ ast->setInitDeclarator(declarator);
+ ast->setFunctionBody(funBody);
+ node = ast;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+ }
+ break;
+
+ case '(':
+ case '[':
+ // ops!! it seems a declarator
+ goto start_decl;
+ break;
+ }
+
+ }
+ }
+
+start_decl:
+ tokenStream->rewind(index);
+
+ if (tokenStream->lookAhead() == Token_const && tokenStream->lookAhead(1) == Token_identifier && tokenStream->lookAhead(2) == '=') {
+ // constant definition
+ advance();
+ InitDeclaratorListAST *declarators = 0;
+ if (parseInitDeclaratorList(declarators)) {
+ ADVANCE(';', ";");
+ DeclarationAST *ast = CreateNode<DeclarationAST>(m_pool);
+ node = ast;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+ syntaxError();
+ return false;
+ }
+
+ TypeSpecifierAST *spec = 0;
+ if (parseTypeSpecifier(spec)) {
+ if (!hasFunSpec)
+ parseFunctionSpecifier(funSpec); // e.g. "void inline"
+ spec->setCvQualify(cv);
+
+ InitDeclaratorListAST *declarators = 0;
+
+ InitDeclaratorAST *decl = 0;
+ int startDeclarator = tokenStream->cursor();
+ bool maybeFunctionDefinition = false;
+
+ if (tokenStream->lookAhead() != ';') {
+ if (parseInitDeclarator(decl) && tokenStream->lookAhead() == '{') {
+ // function definition
+ maybeFunctionDefinition = true;
+ } else {
+ tokenStream->rewind(startDeclarator);
+ if (!parseInitDeclaratorList(declarators)) {
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ switch(tokenStream->lookAhead()) {
+ case ';':
+ {
+ advance();
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(m_pool);
+ ast->setStorageSpecifier(storageSpec);
+ ast->setFunctionSpecifier(funSpec);
+ ast->setTypeSpec(spec);
+ ast->setWinDeclSpec(winDeclSpec);
+ ast->setInitDeclaratorList(declarators);
+ node = ast;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ }
+ return true;
+
+ case '{':
+ {
+ if (!maybeFunctionDefinition) {
+ syntaxError();
+ return false;
+ }
+ StatementListAST *funBody = 0;
+ if (parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast = CreateNode<FunctionDefinitionAST>(m_pool);
+ ast->setWinDeclSpec(winDeclSpec);
+ ast->setStorageSpecifier(storageSpec);
+ ast->setFunctionSpecifier(funSpec);
+ ast->setTypeSpec(spec);
+ ast->setInitDeclarator(decl);
+ ast->setFunctionBody(funBody);
+ node = ast;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+ }
+ break;
+
+ }
+ }
+
+ syntaxError();
+ return false;
+}
+
+bool Parser::parseFunctionBody(StatementListAST *&node)
+{
+ int start = tokenStream->cursor();
+ if (tokenStream->lookAhead() != '{') {
+ return false;
+ }
+ advance();
+
+ StatementListAST *ast = CreateNode<StatementListAST>(m_pool);
+
+ while (tokenStream->lookAhead()) {
+ if (tokenStream->lookAhead() == '}')
+ break;
+
+ StatementAST *stmt = 0;
+ int startStmt = tokenStream->cursor();
+ if (!parseStatement(stmt)) {
+ syntaxError();
+ if (startStmt == tokenStream->cursor())
+ advance();
+ skipUntilStatement();
+ } else
+ ast->addStatement(stmt);
+ }
+
+ if (tokenStream->lookAhead() != '}') {
+ reportError(i18n("} expected"));
+ } else
+ advance();
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node)
+{
+ if (parseClassSpecifier(node))
+ return true;
+ else if (parseEnumSpecifier(node))
+ return true;
+ else if (parseTypeSpecifier(node))
+ return true;
+
+ return false;
+}
+
+bool Parser::parseTryBlockStatement(StatementAST *&node)
+{
+ if (tokenStream->lookAhead() != Token_try) {
+ return false;
+ }
+ advance();
+
+ StatementAST *stmt = 0;
+ if (!parseCompoundStatement(stmt)) {
+ syntaxError();
+ return false;
+ }
+
+ if (tokenStream->lookAhead() != Token_catch) {
+ reportError(i18n("catch expected"));
+ return false;
+ }
+
+ while (tokenStream->lookAhead() == Token_catch) {
+ advance();
+ ADVANCE('(', "(");
+ ConditionAST *cond = 0;
+ if (tokenStream->lookAhead() == Token_ellipsis) {
+ advance();
+ } else if (!parseCondition(cond)) {
+ reportError(i18n("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseCompoundStatement(body)) {
+ syntaxError();
+ return false;
+ }
+ }
+
+ node = stmt;
+ return true;
+}
+
+bool Parser::parsePrimaryExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_PrimaryExpression>(m_pool);
+
+ switch(tokenStream->lookAhead()) {
+ case Token_string_literal:
+ {
+ AST *lit = 0;
+ parseStringLiteral(lit);
+ if (lit)
+ lit->setParent(ast);
+ }
+ break;
+
+ case Token_number_literal:
+ case Token_char_literal:
+ case Token_true:
+ case Token_false:
+ case Token_this:
+ {
+ AST_FROM_TOKEN(opNode, tokenStream->cursor());
+ opNode->setParent(ast);
+ advance();
+ }
+ break;
+
+ case '(':
+ {
+ advance();
+
+ if (tokenStream->lookAhead() == '{') {
+ StatementAST *stmt = 0;
+ if (!parseCompoundStatement(stmt))
+ return false;
+ if (stmt)
+ stmt->setParent(ast);
+ } else {
+ AbstractExpressionAST *expr = 0;
+ if (!parseExpression(expr)) {
+ return false;
+ }
+ if (expr)
+ expr->setParent(ast);
+ }
+ CHECK(')', ")");
+ }
+ break;
+
+ default:
+ {
+/* ### reenable me
+ TypeSpecifierAST *typeSpec = 0;
+ if (parseSimpleTypeSpecifier(typeSpec) && tokenStream->lookAhead() == '(') {
+ Q_ASSERT (0);
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')', ")");
+ break;
+
+ if (typeSpec)
+ typeSpec->setParent(ast);
+
+ if (expr)
+ expr->setParent(ast);
+ }
+
+ tokenStream->rewind(start);
+*/
+
+ NameAST *name = 0;
+ if (!parseName(name, false))
+ return false;
+
+ if (name)
+ name->setParent(ast);
+
+ break;
+ }
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+
+/*
+ postfix-expression-internal:
+ [ expression ]
+ ( expression-list [opt] )
+ (.|->) template [opt] id-expression
+ (.|->) pseudo-destructor-name
+ ++
+ --
+*/
+bool Parser::parsePostfixExpressionInternal(AbstractExpressionAST *postfixExpr, AbstractExpressionAST *&node)
+{
+ Q_ASSERT (postfixExpr);
+
+ int start = tokenStream->cursor();
+
+ switch (tokenStream->lookAhead()) {
+ case '[':
+ {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseExpression(expr);
+ CHECK(']', "]");
+
+ SubscriptingAST *ast = CreateNode<SubscriptingAST>(m_pool);
+ ast->setExpression(postfixExpr);
+ ast->setSubscript(expr);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ }
+ return true;
+
+ case '(':
+ {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseExpression(expr);
+ CHECK(')', ")");
+
+ FunctionCallAST *ast = CreateNode<FunctionCallAST>(m_pool);
+ ast->setExpression(postfixExpr);
+ ast->setArguments(expr);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ }
+ return true;
+
+ case '.':
+ case Token_arrow:
+ {
+ AST_FROM_TOKEN(op, tokenStream->cursor());
+
+ advance();
+ if (tokenStream->lookAhead() == Token_template)
+ advance();
+
+ NameAST *name = 0;
+ if (!parseName(name))
+ return false;
+
+ ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(m_pool);
+ ast->setOp(op);
+ ast->setExpression(postfixExpr);
+ ast->setName(name);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_incr:
+ case Token_decr:
+ {
+ AST_FROM_TOKEN(op, tokenStream->cursor());
+ advance();
+
+ IncrDecrAST *ast = CreateNode<IncrDecrAST>(m_pool);
+ ast->setExpression(postfixExpr);
+ ast->setOp(op);
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ }
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/*
+ postfix-expression:
+ simple-type-specifier ( expression-list [opt] )
+ primary-expression postfix-expression-internal*
+*/
+bool Parser::parsePostfixExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ switch (tokenStream->lookAhead()) {
+ case Token_dynamic_cast:
+ case Token_static_cast:
+ case Token_reinterpret_cast:
+ case Token_const_cast:
+ {
+ AST_FROM_TOKEN(castOp, tokenStream->cursor());
+
+ advance();
+ CHECK('<', "<");
+ TypeIdAST *typeId = 0;
+ parseTypeId(typeId);
+ CHECK('>', ">");
+
+ CHECK('(', ")");
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')', ")");
+
+ CppCastExpressionAST *tmp = CreateNode<CppCastExpressionAST>(m_pool);
+ tmp->setCastOp(castOp);
+ tmp->setTypeId(typeId);
+ tmp->setExpression(expr);
+
+ AbstractExpressionAST *ast = tmp;
+ AbstractExpressionAST *e = 0;
+ while (parsePostfixExpressionInternal(ast, e)) {
+ ast = e;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_typename:
+ {
+ advance();
+
+ NameAST* name = 0;
+ if (!parseName(name))
+ return false;
+
+ CHECK('(', "(");
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')', ")");
+
+ // ### AST
+ }
+ return true;
+
+ case Token_typeid:
+ {
+ advance();
+
+ CHECK('(', "(");
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')', ")");
+
+ // ### AST
+ }
+ return true;
+
+ default:
+ break;
+ }
+
+ TypeSpecifierAST *typeSpec = 0;
+ AbstractExpressionAST *expr = 0;
+
+ if (parseSimpleTypeSpecifier(typeSpec/*, true*/) && tokenStream->lookAhead() == '(') {
+ advance(); // skip '('
+ parseCommaExpression(expr);
+ CHECK(')', ")");
+ } else {
+ tokenStream->rewind(start);
+
+ if (!parsePrimaryExpression(expr))
+ return false;
+ }
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_PostfixExpression>(m_pool);
+ if (typeSpec)
+ typeSpec->setParent(ast);
+
+ if (expr)
+ expr->setParent(ast);
+
+ AbstractExpressionAST *e = 0;
+ while (parsePostfixExpressionInternal(ast, e)) {
+ ast = e;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseUnaryExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ switch(tokenStream->lookAhead()) {
+ case Token_incr:
+ case Token_decr:
+ case '*':
+ case '&':
+ case '+':
+ case '-':
+ case '!':
+ case '~':
+ {
+ AST_FROM_TOKEN(opNode, tokenStream->cursor());
+
+ advance();
+ AbstractExpressionAST *expr = 0;
+ if (!parseCastExpression(expr))
+ return false;
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_UnaryExpression>(m_pool);
+
+ opNode->setParent(ast);
+ if (expr)
+ expr->setParent(ast);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ }
+
+ case Token_sizeof:
+ {
+ AbstractExpressionAST *ast = CreateExpression<NodeType_UnaryExpression>(m_pool);
+
+ AST_FROM_TOKEN(opNode, tokenStream->cursor());
+ opNode->setParent(ast);
+
+ advance();
+ int index = tokenStream->cursor();
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+ TypeIdAST *typeId = 0;
+ if (parseTypeId(typeId) && tokenStream->lookAhead() == ')') {
+ if (typeId)
+ typeId->setParent(ast);
+
+ advance();
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ }
+ tokenStream->rewind(index);
+ }
+ AbstractExpressionAST *expr = 0;
+ if (!parseUnaryExpression(expr))
+ return false;
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ }
+
+ case Token_new:
+ return parseNewExpression(node);
+
+ case Token_delete:
+ return parseDeleteExpression(node);
+ }
+
+ return parsePostfixExpression(node);
+}
+
+bool Parser::parseNewExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_NewExpression>(m_pool);
+
+ if (tokenStream->lookAhead() == Token_scope && tokenStream->lookAhead(1) == Token_new) {
+ AST_FROM_TOKEN(scopeNode, tokenStream->cursor());
+ scopeNode->setParent(ast);
+ advance();
+ }
+
+ AST_FROM_TOKEN(newNode, tokenStream->cursor());
+ newNode->setParent(ast);
+
+ CHECK(Token_new, "new");
+
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ if (expr)
+ expr->setParent(ast);
+ CHECK(')', ")");
+ }
+
+ if (tokenStream->lookAhead() == '(') {
+ advance();
+ TypeIdAST *typeId = 0;
+ parseTypeId(typeId);
+ if (typeId)
+ typeId->setParent(ast);
+ CHECK(')', ")");
+ } else {
+ AbstractExpressionAST *typeId = 0;
+ parseNewTypeId(typeId);
+ if (typeId)
+ typeId->setParent(ast);
+ }
+
+ AbstractExpressionAST *init = 0;
+ parseNewInitializer(init);
+ if (init)
+ init->setParent(ast);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseNewTypeId(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ TypeSpecifierAST *typeSpec = 0;
+ if (!parseTypeSpecifier(typeSpec))
+ return false;
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_NewTypeId>(m_pool);
+
+ if (typeSpec)
+ typeSpec->setParent(ast);
+
+ AbstractExpressionAST *declarator = 0;
+ parseNewDeclarator(declarator);
+ if (declarator)
+ declarator->setParent(ast);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseNewDeclarator(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_NewInitializer>(m_pool);
+
+ AST *ptrOp = 0;
+ if (parsePtrOperator(ptrOp)) {
+ if (ptrOp)
+ ptrOp->setParent(ast);
+
+ AbstractExpressionAST *declarator = 0;
+ parseNewDeclarator(declarator);
+
+ if (declarator)
+ declarator->setParent(ast);
+ }
+
+ while (tokenStream->lookAhead() == '[') {
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseExpression(expr);
+ ADVANCE(']', "]");
+
+ if (expr)
+ expr->setParent(ast);
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseNewInitializer(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != '(')
+ return false;
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_NewInitializer>(m_pool);
+
+ advance();
+ AbstractExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ if (expr)
+ expr->setParent(ast);
+
+ CHECK(')', ")");
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseDeleteExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_DeleteExpression>(m_pool);
+
+ if (tokenStream->lookAhead() == Token_scope && tokenStream->lookAhead(1) == Token_delete) {
+ AST_FROM_TOKEN(scopeNode, tokenStream->cursor());
+ scopeNode->setParent(ast);
+ advance();
+ }
+
+ AST_FROM_TOKEN(deleteNode, tokenStream->cursor());
+ deleteNode->setParent(ast);
+
+ CHECK(Token_delete, "delete");
+
+ if (tokenStream->lookAhead() == '[') {
+ int beg = tokenStream->cursor();
+ advance();
+ CHECK(']', "]");
+
+ AST *n = CreateNode<AST>(m_pool);
+ UPDATE_POS(n, beg, tokenStream->cursor());
+ n->setParent(ast);
+ }
+
+ AbstractExpressionAST *expr = 0;
+ if (!parseCastExpression(expr))
+ return false;
+
+ if (expr)
+ expr->setParent(ast);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseCastExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() == '(') {
+ AbstractExpressionAST *ast = CreateExpression<NodeType_CastExpression>(m_pool);
+
+ advance();
+ TypeIdAST *typeId = 0;
+ if (parseTypeId(typeId)) {
+
+ if (typeId)
+ typeId->setParent(ast);
+
+ if (tokenStream->lookAhead() == ')') {
+ advance();
+
+ AbstractExpressionAST *expr = 0;
+ if (parseCastExpression(expr)) {
+ if (expr)
+ expr->setParent(ast);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+ }
+ }
+ }
+ }
+
+ tokenStream->rewind(start);
+ return parseUnaryExpression(node);
+}
+
+bool Parser::parsePmExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseCastExpression(ast) || !ast) // ### fixme
+ return false;
+
+ while (tokenStream->lookAhead() == Token_ptrmem) {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseCastExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseMultiplicativeExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parsePmExpression(ast))
+ return false;
+
+ while (tokenStream->lookAhead() == '*' || tokenStream->lookAhead() == '/' || tokenStream->lookAhead() == '%') {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parsePmExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+
+bool Parser::parseAdditiveExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseMultiplicativeExpression(ast))
+ return false;
+
+ while (tokenStream->lookAhead() == '+' || tokenStream->lookAhead() == '-') {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseMultiplicativeExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseShiftExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseAdditiveExpression(ast))
+ return false;
+
+ while (tokenStream->lookAhead() == Token_shift) {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseAdditiveExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseRelationalExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseShiftExpression(ast))
+ return false;
+
+ while (tokenStream->lookAhead() == '<' || (tokenStream->lookAhead() == '>' && !templArgs) ||
+ tokenStream->lookAhead() == Token_leq || tokenStream->lookAhead() == Token_geq) {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseShiftExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseEqualityExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseRelationalExpression(ast, templArgs))
+ return false;
+
+ while (tokenStream->lookAhead() == Token_eq || tokenStream->lookAhead() == Token_not_eq) {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseRelationalExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseAndExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseEqualityExpression(ast, templArgs))
+ return false;
+
+ while (tokenStream->lookAhead() == '&') {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseEqualityExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseExclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseAndExpression(ast, templArgs))
+ return false;
+
+ while (tokenStream->lookAhead() == '^') {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseAndExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseInclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseExclusiveOrExpression(ast, templArgs))
+ return false;
+
+ while (tokenStream->lookAhead() == '|') {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseExclusiveOrExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseLogicalAndExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseInclusiveOrExpression(ast, templArgs))
+ return false;
+
+ while (tokenStream->lookAhead() == Token_and) {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseInclusiveOrExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseLogicalOrExpression(AbstractExpressionAST *&node, bool templArgs)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseLogicalAndExpression(ast, templArgs))
+ return false;
+
+ while (tokenStream->lookAhead() == Token_or) {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseLogicalAndExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConditionalExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+ AbstractExpressionAST *ast = 0;
+ if (!parseLogicalOrExpression(ast))
+ return false;
+
+ if (tokenStream->lookAhead() == '?') {
+ advance();
+
+ AbstractExpressionAST *leftExpr = 0;
+ if (!parseExpression(leftExpr))
+ return false;
+
+ CHECK(':', ":");
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseAssignmentExpression(rightExpr))
+ return false;
+
+ ConditionalExpressionAST *tmp = CreateNode<ConditionalExpressionAST>(m_pool);
+ tmp->setCondition(ast);
+ tmp->setLeftExpression(leftExpr);
+ tmp->setRightExpression(rightExpr);
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseAssignmentExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (tokenStream->lookAhead() == Token_throw && !parseThrowExpression(ast))
+ return false;
+ else if (!parseConditionalExpression(ast))
+ return false;
+
+ while (tokenStream->lookAhead() == Token_assign || tokenStream->lookAhead() == '=') {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseConditionalExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseConstantExpression(AbstractExpressionAST *&node)
+{
+ return parseConditionalExpression(node);
+}
+
+bool Parser::parseExpression(AbstractExpressionAST *&node)
+{
+ return parseCommaExpression(node);
+}
+
+bool Parser::parseCommaExpression(AbstractExpressionAST *&node)
+{
+ int start = tokenStream->cursor();
+
+ AbstractExpressionAST *ast = 0;
+ if (!parseAssignmentExpression(ast))
+ return false;
+
+ while (tokenStream->lookAhead() == ',') {
+ int startOp = tokenStream->cursor();
+ AST_FROM_TOKEN(op, startOp);
+ advance();
+
+ AbstractExpressionAST *rightExpr = 0;
+ if (!parseAssignmentExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *tmp = CreateNode<BinaryExpressionAST>(m_pool);
+ tmp->setOp(op);
+ tmp->setLeftExpression(ast);
+ tmp->setRightExpression(rightExpr);
+ UPDATE_POS(tmp, startOp, tokenStream->cursor());
+ ast = tmp;
+ }
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseThrowExpression(AbstractExpressionAST *&node)
+{
+ if (tokenStream->lookAhead() != Token_throw)
+ return false;
+
+ int start = tokenStream->cursor();
+
+ AST_FROM_TOKEN(throwNode, tokenStream->cursor());
+ CHECK(Token_throw, "throw");
+ AbstractExpressionAST *expr = 0;
+ if (!parseAssignmentExpression(expr))
+ return false;
+
+ AbstractExpressionAST *ast = CreateExpression<NodeType_ThrowExpression>(m_pool);
+ throwNode->setParent(ast);
+ if (expr)
+ expr->setParent(ast);
+
+ UPDATE_POS(ast, start, tokenStream->cursor());
+ node = ast;
+
+ return true;
+}
+
+
+// ### Objective C++
+bool Parser::parseIvarDeclList(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseIvarDecls(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseIvarDecl(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseIvars(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseIvarDeclarator(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseMethodDecl(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseUnarySelector(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseKeywordSelector(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseSelector(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseKeywordDecl(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseReceiver(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcMessageExpr(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseMessageArgs(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseKeywordExpr(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseKeywordArgList(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseKeywordArg(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseReservedWord(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseMyParms(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseMyParm(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseOptParmList(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcSelectorExpr(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseSelectorArg(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseKeywordNameList(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseKeywordName(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcEncodeExpr(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcString(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseProtocolRefs(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseIdentifierList(AST *& node)
+{
+ int start = tokenStream->cursor();
+
+ if (tokenStream->lookAhead() != Token_identifier)
+ return false;
+
+ AST *ast = CreateNode<AST>(m_pool);
+
+ AST_FROM_TOKEN(tk, tokenStream->cursor());
+ tk->setParent(ast);
+ advance();
+
+ while (tokenStream->lookAhead() == ',') {
+ advance();
+ if (tokenStream->lookAhead() == Token_identifier) {
+ AST_FROM_TOKEN(tk, tokenStream->cursor());
+ tk->setParent(ast);
+ advance();
+ }
+ ADVANCE(Token_identifier, "identifier");
+ }
+
+ node = ast;
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+}
+
+bool Parser::parseIdentifierColon(AST *& node)
+{
+ Q_UNUSED(node);
+
+ if (tokenStream->lookAhead() == Token_identifier && tokenStream->lookAhead(1) == ':') {
+ advance();
+ advance();
+ return true;
+ } // ### else if PTYPENAME -> return true ;
+
+ return false;
+}
+
+bool Parser::parseObjcProtocolExpr(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcOpenBracketExpr(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcCloseBracket(AST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcDef(DeclarationAST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcClassDef(DeclarationAST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcClassDecl(DeclarationAST *& node)
+{
+ Q_UNUSED(node);
+
+ ADVANCE(OBJC_CLASS, "@class");
+
+ AST *idList = 0;
+ parseIdentifierList(idList);
+ ADVANCE(';', ";");
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDecl(DeclarationAST *& node)
+{
+ Q_UNUSED(node);
+
+ ADVANCE(OBJC_PROTOCOL, "@protocol");
+
+ AST *idList = 0;
+ parseIdentifierList(idList);
+ ADVANCE(';', ";");
+
+ return true;
+}
+
+bool Parser::parseObjcAliasDecl(DeclarationAST *& node)
+{
+ Q_UNUSED(node);
+
+ ADVANCE(OBJC_ALIAS, "@alias");
+
+ AST *idList = 0;
+ parseIdentifierList(idList);
+ ADVANCE(';', ";");
+
+ return true;
+}
+
+bool Parser::parseObjcProtocolDef(DeclarationAST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseObjcMethodDef(DeclarationAST *& node)
+{
+ Q_UNUSED(node);
+ return false;
+}
+
+bool Parser::parseWinDeclSpec(AST *& node)
+{
+ if (tokenStream->lookAhead() == Token_identifier
+ && tokenStream->lookAhead(1) == '('
+ && tokenStream->currentTokenText() == "__declspec") {
+ int start = tokenStream->cursor();
+ advance();
+ advance(); // skip '('
+
+ parseIdentifierList(node);
+ ADVANCE(')', ")");
+
+ UPDATE_POS(node, start, tokenStream->cursor());
+ return true;
+ }
+
+ return false;
+}
+
+void Parser::advance()
+{
+ for (;;) {
+ tokenStream->nextToken();
+ if (!tokenStream->isHidden(tokenStream->cursor()))
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/parser.h b/tools/porting/src/parser.h
new file mode 100644
index 0000000000..45278d4492
--- /dev/null
+++ b/tools/porting/src/parser.h
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "ast.h"
+#include "tokenstreamadapter.h"
+
+#include <QString>
+#include <QStringList>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+class FileSymbol;
+class TokenStream;
+class Error;
+
+class Parser
+{
+public:
+ Parser();
+ ~Parser();
+
+// TranslationUnitAST *parse(FileSymbol *file, pool *p);
+ TranslationUnitAST *parse(TokenStreamAdapter::TokenStream *tokenStream, pool *p);
+ TranslationUnitAST *parse(TokenStreamAdapter::TokenStream *tokenStream, pool *p, int targetMaxASTnodes, bool &done);
+private:
+ bool reportError(const Error& err);
+ /** @todo remove*/ bool reportError(const QString& msg);
+ /** @todo remove*/ void syntaxError();
+
+public /*rules*/ :
+
+ bool parseTranslationUnit(TranslationUnitAST *&node);
+
+ bool parseDeclaration(DeclarationAST *&node);
+ bool parseBlockDeclaration(DeclarationAST *&node);
+ bool parseLinkageSpecification(DeclarationAST *&node);
+ bool parseLinkageBody(LinkageBodyAST *&node);
+ bool parseNamespace(DeclarationAST *&node);
+ bool parseNamespaceAliasDefinition(DeclarationAST *&node);
+ bool parseUsing(DeclarationAST *&node);
+ bool parseUsingDirective(DeclarationAST *&node);
+ bool parseTypedef(DeclarationAST *&node);
+ bool parseAsmDefinition(DeclarationAST *&node);
+ bool parseTemplateDeclaration(DeclarationAST *&node);
+ bool parseDeclarationInternal(DeclarationAST *&node);
+
+ bool parseStringLiteral(AST *&node);
+ bool parseUnqualifiedName(ClassOrNamespaceNameAST *&node, bool parseTemplateId = true);
+ bool parseName(NameAST *&node, bool parseTemplateId = true);
+ bool parseOperatorFunctionId(AST *&node);
+ bool parseTemplateArgumentList(TemplateArgumentListAST *&node, bool reportError = true);
+ bool parseOperator(AST *&node);
+ bool parseCvQualify(AST *&node);
+ bool parseSimpleTypeSpecifier(TypeSpecifierAST *&node, bool onlyIntegral = false);
+ bool parsePtrOperator(AST *&node);
+ bool parseTemplateArgument(AST *&node);
+ bool parseTypeSpecifier(TypeSpecifierAST *&node);
+ bool parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node);
+ bool parseDeclarator(DeclaratorAST *&node);
+ bool parseTemplateParameterList(TemplateParameterListAST *&node);
+ bool parseTemplateParameter(TemplateParameterAST *&node);
+ bool parseStorageClassSpecifier(AST *&node);
+ bool parseFunctionSpecifier(AST *&node);
+ bool parseInitDeclaratorList(InitDeclaratorListAST *&node);
+ bool parseInitDeclarator(InitDeclaratorAST *&node);
+ bool parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node);
+ bool parseCtorInitializer(AST *&node);
+ bool parsePtrToMember(AST *&node);
+ bool parseEnumSpecifier(TypeSpecifierAST *&node);
+ bool parseClassSpecifier(TypeSpecifierAST *&node);
+ bool parseWinDeclSpec(AST *&node);
+ bool parseElaboratedTypeSpecifier(TypeSpecifierAST *&node);
+ bool parseDeclaratorId(NameAST *&node);
+ bool parseExceptionSpecification(AST *&node);
+ bool parseEnumerator(EnumeratorAST *&node);
+ bool parseTypeParameter(TypeParameterAST *&node);
+ bool parseParameterDeclaration(ParameterDeclarationAST *&node);
+ bool parseTypeId(TypeIdAST *&node);
+ bool parseAbstractDeclarator(DeclaratorAST *&node);
+ bool parseParameterDeclarationList(ParameterDeclarationListAST *&node);
+ bool parseMemberSpecification(DeclarationAST *&node);
+ bool parseAccessSpecifier(AST *&node);
+ bool parseTypeIdList(AST *&node);
+ bool parseMemInitializerList(AST *&node);
+ bool parseMemInitializer(AST *&node);
+ bool parseInitializer(AST *&node);
+ bool parseBaseClause(BaseClauseAST *&node);
+ bool parseBaseSpecifier(BaseSpecifierAST *&node);
+ bool parseInitializerClause(AST *&node);
+ bool parseMemInitializerId(NameAST *&node);
+ bool parseFunctionBody(StatementListAST *&node);
+
+ // expression
+ bool skipExpression(AbstractExpressionAST *&node);
+ bool skipCommaExpression(AbstractExpressionAST *&node);
+ bool skipExpressionStatement(StatementAST *&node);
+
+ bool parseExpression(AbstractExpressionAST *&node);
+ bool parsePrimaryExpression(AbstractExpressionAST *&node);
+ bool parsePostfixExpression(AbstractExpressionAST *&node);
+ bool parsePostfixExpressionInternal(AbstractExpressionAST *expr, AbstractExpressionAST *&node);
+ bool parseUnaryExpression(AbstractExpressionAST *&node);
+ bool parseNewExpression(AbstractExpressionAST *&node);
+ bool parseNewTypeId(AbstractExpressionAST *&node);
+ bool parseNewDeclarator(AbstractExpressionAST *&node);
+ bool parseNewInitializer(AbstractExpressionAST *&node);
+ bool parseDeleteExpression(AbstractExpressionAST *&node);
+ bool parseCastExpression(AbstractExpressionAST *&node);
+ bool parsePmExpression(AbstractExpressionAST *&node);
+ bool parseMultiplicativeExpression(AbstractExpressionAST *&node);
+ bool parseAdditiveExpression(AbstractExpressionAST *&node);
+ bool parseShiftExpression(AbstractExpressionAST *&node);
+ bool parseRelationalExpression(AbstractExpressionAST *&node, bool templArgs = false);
+ bool parseEqualityExpression(AbstractExpressionAST *&node, bool templArgs = false);
+ bool parseAndExpression(AbstractExpressionAST *&node, bool templArgs = false);
+ bool parseExclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs = false);
+ bool parseInclusiveOrExpression(AbstractExpressionAST *&node, bool templArgs = false);
+ bool parseLogicalAndExpression(AbstractExpressionAST *&node, bool templArgs = false);
+ bool parseLogicalOrExpression(AbstractExpressionAST *&node, bool templArgs = false);
+ bool parseConditionalExpression(AbstractExpressionAST *&node);
+ bool parseAssignmentExpression(AbstractExpressionAST *&node);
+ bool parseConstantExpression(AbstractExpressionAST *&node);
+ bool parseCommaExpression(AbstractExpressionAST *&node);
+ bool parseThrowExpression(AbstractExpressionAST *&node);
+
+ // statement
+ bool parseCondition(ConditionAST *&node);
+ bool parseStatement(StatementAST *&node);
+ bool parseWhileStatement(StatementAST *&node);
+ bool parseDoStatement(StatementAST *&node);
+ bool parseForStatement(StatementAST *&node);
+ bool parseCompoundStatement(StatementAST *&node);
+ bool parseForInitStatement(StatementAST *&node);
+ bool parseIfStatement(StatementAST *&node);
+ bool parseSwitchStatement(StatementAST *&node);
+ bool parseLabeledStatement(StatementAST *&node);
+ bool parseDeclarationStatement(StatementAST *&node);
+ bool parseTryBlockStatement(StatementAST *&node);
+
+ // objective c
+ bool parseObjcDef(DeclarationAST *&node);
+ bool parseObjcClassDef(DeclarationAST *&node);
+ bool parseObjcClassDecl(DeclarationAST *&node);
+ bool parseObjcProtocolDecl(DeclarationAST *&node);
+ bool parseObjcAliasDecl(DeclarationAST *&node);
+ bool parseObjcProtocolDef(DeclarationAST *&node);
+ bool parseObjcMethodDef(DeclarationAST *&node);
+
+ bool parseIvarDeclList(AST *&node);
+ bool parseIvarDecls(AST *&node);
+ bool parseIvarDecl(AST *&node);
+ bool parseIvars(AST *&node);
+ bool parseIvarDeclarator(AST *&node);
+ bool parseMethodDecl(AST *&node);
+ bool parseUnarySelector(AST *&node);
+ bool parseKeywordSelector(AST *&node);
+ bool parseSelector(AST *&node);
+ bool parseKeywordDecl(AST *&node);
+ bool parseReceiver(AST *&node);
+ bool parseObjcMessageExpr(AST *&node);
+ bool parseMessageArgs(AST *&node);
+ bool parseKeywordExpr(AST *&node);
+ bool parseKeywordArgList(AST *&node);
+ bool parseKeywordArg(AST *&node);
+ bool parseReservedWord(AST *&node);
+ bool parseMyParms(AST *&node);
+ bool parseMyParm(AST *&node);
+ bool parseOptParmList(AST *&node);
+ bool parseObjcSelectorExpr(AST *&node);
+ bool parseSelectorArg(AST *&node);
+ bool parseKeywordNameList(AST *&node);
+ bool parseKeywordName(AST *&node);
+ bool parseObjcEncodeExpr(AST *&node);
+ bool parseObjcString(AST *&node);
+ bool parseProtocolRefs(AST *&node);
+ bool parseIdentifierList(AST *&node);
+ bool parseIdentifierColon(AST *&node);
+ bool parseObjcProtocolExpr(AST *&node);
+ bool parseObjcOpenBracketExpr(AST *&node);
+ bool parseObjcCloseBracket(AST *&node);
+
+ bool skipUntil(int token);
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip(int l, int r);
+
+ void advance();
+
+private:
+ int m_problems;
+ int m_maxProblems;
+ bool objcp;
+ TokenStreamAdapter::TokenStream *tokenStream;
+ pool *m_pool;
+ FileSymbol *m_file;
+
+private:
+ Parser(const Parser& source);
+ void operator = (const Parser& source);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/port.cpp b/tools/porting/src/port.cpp
new file mode 100644
index 0000000000..eeb1f2e66d
--- /dev/null
+++ b/tools/porting/src/port.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "projectporter.h"
+#include "fileporter.h"
+#include "logger.h"
+#include "preprocessorcontrol.h"
+
+#include <QString>
+#include <QFile>
+#include <QFileInfo>
+#include <QDir>
+#include <QByteArray>
+#include <QBuffer>
+#include <QTextStream>
+#include <QCoreApplication>
+#include <QLibraryInfo>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+QString rulesFilePath;
+QString applicationDirPath;
+
+QString findRulesFile(const QString &fileName)
+{
+ // Check QLibraryInfo::DataPath/filename
+ QString filePath;
+ filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1String("/") + fileName) ;
+ if (QFile::exists(filePath))
+ return QFileInfo(filePath).canonicalFilePath();
+
+ // Check QLibraryInfo::PrefixPath/tools/porting/src/filename
+ filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::PrefixPath) + QLatin1String("/tools/porting/src/") + fileName);
+ if (QFile::exists(filePath))
+ return QFileInfo(filePath).canonicalFilePath();
+
+ //no luck
+ return QString();
+}
+
+/*
+ A option contains an argument and its help text.
+*/
+class Option
+{
+public:
+ Option(const QString &argument, const QString &description)
+ :argument(argument), description(description) {}
+
+ /*
+ Checks if candidateArgument matches the options argument.
+ */
+ bool checkArgument(const QString &candidateArgument) const
+ {
+ return (candidateArgument == argument) ||
+ (candidateArgument.toLower() == argument.toLower());
+ }
+
+ QString argument;
+ QString description;
+};
+
+typedef QList<Option> OptionList;
+
+void usage(const OptionList &optionList)
+{
+ printf("Tool for porting Qt 3 applications to Qt 4, using the compatibility library\n");
+ printf("and compatibility functions in the core library.\n");
+ printf("Usage: qt3to4 [options] <Infile>, [Infile], ...\n");
+ printf("\n");
+ printf("Infile can be a source file or a project file.\n");
+ printf("If you specify a project file, ending with .pro or .pri,\n");
+ printf("qt3to4 will port all files specified in that project.\n");
+ printf("\n");
+ printf("Options:\n");
+
+ // Find the length of the longest argument.
+ int argumentMaxLenght = 0;
+ foreach (const Option option, optionList) {
+ if (option.argument.count() > argumentMaxLenght)
+ argumentMaxLenght = option.argument.count();
+ }
+
+ // Print the options, pad with spaces between the argument and description where needed.
+ const int extraSpaces = 5;
+ foreach (const Option option, optionList) {
+ printf("%s", option.argument.toLocal8Bit().constData());
+ for (int i = 0; i < argumentMaxLenght - option.argument.count() + extraSpaces; ++i)
+ printf(" ");
+ puts(option.description.toLocal8Bit().constData());
+ }
+
+ printf("\n");
+ printf("The porting documentation contains more information on how\n");
+ printf("to use qt3to4 as well as general porting information.\n");
+}
+
+int runPort(int argc, char**argv)
+{
+ QCoreApplication app(argc, argv);
+ applicationDirPath = app.applicationDirPath();
+ QString defaultRulesFileName = QLatin1String("q3porting.xml");
+ QStringList inFileNames;
+ QStringList includeSearchDirectories;
+ bool enableCppParsing = true;
+ bool useBuildtinQt3Headers = true;
+ bool showMissingFilesWarnings = false;
+ bool alwaysOverwrite = false;
+ int currentArg = 1;
+
+ const Option helpOption(QLatin1String("-h"), QLatin1String("Display this help."));
+ const Option rulesFileOption(QLatin1String("-rulesFile"), QLatin1String("Specify the location for the rules file."));
+ const Option includeDirectoryOption(QLatin1String("-I"), QLatin1String("Add directory to the list of directories to be searched for header files."));
+ const Option disableCppParsingOption(QLatin1String("-disableCppParsing"), QLatin1String("Disable the C++ parsing component."));
+ const Option disableBuiltinQt3HeadersOption(QLatin1String("-disableBuiltinQt3Headers"), QLatin1String("Do not use the built-in Qt 3 headers."));
+ const Option missingFileWarningsOption(QLatin1String("-missingFileWarnings"), QLatin1String("Warn about files not found while searching for header files."));
+ const Option alwaysOverwriteOption(QLatin1String("-alwaysOverwrite"), QLatin1String("Port all files without prompting."));
+ const Option strictOption(QLatin1String("-strict"), QLatin1String("Be stricter when selecting which tokens to replace."));
+
+ const OptionList optionList = OptionList() << helpOption << alwaysOverwriteOption << rulesFileOption
+ << includeDirectoryOption << disableCppParsingOption
+ << disableBuiltinQt3HeadersOption << missingFileWarningsOption
+ << strictOption;
+
+ if (argc == 1) {
+ usage(optionList);
+ return 0;
+ }
+
+ // Read arguments.
+ while (currentArg < argc) {
+ QString argText = QLatin1String(argv[currentArg]);
+ if(argText.isEmpty()) {
+ continue;
+ } else if (argText == QLatin1String("--help") || argText == QLatin1String("/h") || argText == QLatin1String("-help")
+ || argText == QLatin1String("-h") || argText == QLatin1String("-?") || argText == QLatin1String("/?")) {
+ usage(optionList);
+ return 0;
+ } else if (rulesFileOption.checkArgument(argText)) {
+ ++currentArg;
+ if (currentArg >= argc) {
+ printf("You must specify a file name along with %s \n", argText.toLocal8Bit().constData());
+ return 0;
+ }
+ rulesFilePath = QLatin1String(argv[currentArg]);
+
+ if (!QFile::exists(rulesFilePath)) {
+ printf("File not found: %s\n", rulesFilePath.toLocal8Bit().constData());
+ return 0;
+ }
+ } else if (includeDirectoryOption.checkArgument(argText)) {
+ ++currentArg;
+ if (currentArg >= argc) {
+ printf("You must specify a directory name along with %s\n",
+ argText.toLocal8Bit().constData());
+ return 0;
+ }
+ includeSearchDirectories += QLatin1String(argv[currentArg]);
+ } else if (disableCppParsingOption.checkArgument(argText)) {
+ enableCppParsing = false;
+ } else if (strictOption.checkArgument(argText)) {
+ // Enable strict mode, this is used by the ScopedTokenReplacement constructor.
+ Logger::instance()->globalState.insert(QLatin1String("strictMode"), QLatin1String(""));
+ } else if (disableBuiltinQt3HeadersOption.checkArgument(argText)) {
+ useBuildtinQt3Headers = false;
+ } else if (missingFileWarningsOption.checkArgument(argText)) {
+ showMissingFilesWarnings = true;
+ } else if (alwaysOverwriteOption.checkArgument(argText)) {
+ alwaysOverwrite = true;
+ FileWriter::instance()->setOverwriteFiles(FileWriter::AlwaysOverWrite);
+ } else if (argText[0] == QLatin1Char('-')) {
+ printf("Unknown option %s\n", argText.toLocal8Bit().constData());
+ return 0;
+ } else {
+ inFileNames.append(argText);
+ }
+ ++currentArg;
+ }
+
+ if (rulesFilePath.isEmpty())
+ rulesFilePath = findRulesFile(defaultRulesFileName);
+
+ // Check if we have a rule file.
+ if (!QFile::exists(rulesFilePath)) {
+ printf("Error: Could not find the %s rule file: ", defaultRulesFileName.toLocal8Bit().constData());
+ printf("Please try specifying the location of the file with the %s option \n",
+ rulesFileOption.argument.toLocal8Bit().constData());
+ return 0;
+ }
+
+ // Check if we have any infiles
+ if (inFileNames.isEmpty()) {
+ printf("You must specify a file name. \n");
+ return 0;
+ }
+
+ // Read rule file and create PortingRules instance.
+ printf("Using rules file: ");
+ puts(QDir::toNativeSeparators(rulesFilePath).toLocal8Bit().constData());
+ PortingRules::createInstance(rulesFilePath);
+
+
+ // Construct a ProjectPorter object add pass it the options.
+ QStringList builtinQtheaders;
+ if (useBuildtinQt3Headers) {
+ builtinQtheaders += QLatin1String(":qt3headers0.resource");
+ builtinQtheaders += QLatin1String(":qt3headers1.resource");
+ builtinQtheaders += QLatin1String(":qt3headers2.resource");
+ builtinQtheaders += QLatin1String(":qt3headers3.resource");
+ }
+
+ ProjectPorter porter(QDir::currentPath(), includeSearchDirectories, builtinQtheaders);
+ porter.enableCppParsing(enableCppParsing);
+ porter.enableMissingFilesWarnings(showMissingFilesWarnings);
+
+ // Determine mode based on file exstesions and port.
+ // (The ProjectPorter class is also used for porting single files :)
+ foreach (QString inFileName, inFileNames) {
+ const QString canonicalFileName = QFileInfo(inFileName).canonicalFilePath();
+ if (QFile::exists(canonicalFileName)) {
+ if (canonicalFileName.endsWith(QLatin1String(".pro")) || canonicalFileName.endsWith(QLatin1String(".pri")))
+ porter.portProject(canonicalFileName);
+ else
+ porter.portFile(canonicalFileName);
+ } else {
+ printf("File not found: %s \n", QDir::toNativeSeparators(inFileName).toLocal8Bit().constData());
+ }
+ }
+
+ // Write log
+ if (Logger::instance()->numEntries() > 0) {
+ QStringList report = Logger::instance()->fullReport();
+ QString logFileName = QLatin1String("portinglog.txt");
+ printf("Writing log to %s \n", logFileName.toLocal8Bit().constData());
+ QByteArray logContents;
+ QBuffer logBuffer(&logContents);
+ logBuffer.open(QIODevice::Text | QIODevice::WriteOnly);
+ QTextStream logStream(&logBuffer);
+ foreach (QString logLine, report) {
+ logStream << logLine << endl;
+ }
+ logStream << endl;
+
+ QFile logFile(logFileName);
+ logFile.open(QIODevice::WriteOnly | QIODevice::Append);
+ logFile.write(logContents);
+ }
+ Logger::deleteInstance();
+ PortingRules::deleteInstance();
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+int main(int argc, char**argv)
+{
+ return QT_PREPEND_NAMESPACE(runPort)(argc, argv);
+}
diff --git a/tools/porting/src/portingrules.cpp b/tools/porting/src/portingrules.cpp
new file mode 100644
index 0000000000..4931064222
--- /dev/null
+++ b/tools/porting/src/portingrules.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "portingrules.h"
+#include "logger.h"
+#include "qtsimplexml.h"
+#include <QFile>
+#include <QFileInfo>
+#include <QDir>
+
+QT_BEGIN_NAMESPACE
+
+PortingRules *PortingRules::theInstance = 0;
+
+void PortingRules::createInstance(QString xmlFilePath)
+{
+ deleteInstance();
+ theInstance = new PortingRules(xmlFilePath);
+}
+
+PortingRules *PortingRules::instance()
+{
+ if(theInstance) {
+ return theInstance;
+ } else {
+ qWarning("Error: must create a PortingRules instance with createInstance() before calling instance()\n");
+ return 0;
+ }
+}
+
+void PortingRules::deleteInstance()
+{
+ if(theInstance) {
+ delete theInstance;
+ theInstance = 0;
+ }
+}
+
+PortingRules::PortingRules(QString xmlFilePath)
+{
+ parseXml(xmlFilePath);
+}
+
+QList<TokenReplacement*> PortingRules::getTokenReplacementRules()
+{
+ if(tokenRules.isEmpty())
+ addLogWarning(QLatin1String("Warning: token rules list is empty"));
+ return tokenRules;
+}
+
+QStringList PortingRules::getHeaderList(QtVersion qtVersion)
+{
+ if(qt3Headers.isEmpty() || qt4Headers.isEmpty())
+ addLogWarning(QLatin1String("Warning: headers list is empty"));
+
+ if (qtVersion==Qt3)
+ return qt3Headers;
+ else //Qt4
+ return qt4Headers;
+}
+
+QHash<QByteArray, QByteArray> PortingRules::getNeededHeaders()
+{
+ if(neededHeaders.isEmpty())
+ addLogWarning(QLatin1String("Warning: needed headers list is empty"));
+ return neededHeaders;
+}
+
+QStringList PortingRules::getInheritsQt()
+{
+ if(tokenRules.isEmpty())
+ addLogWarning(QLatin1String("Warning: inheritsQtClass list is empty"));
+ return inheritsQtClass;
+}
+
+QHash<QByteArray, QByteArray> PortingRules::getClassLibraryList()
+{
+ if(classLibraryList.isEmpty())
+ addLogWarning(QLatin1String("Warning: classLibraryList list is empty"));
+ return classLibraryList;
+}
+
+QHash<QByteArray, QByteArray> PortingRules::getHeaderReplacements()
+{
+ return headerReplacements;
+}
+
+/*
+ Loads rule xml file given by fileName, and sets up data structures.
+ The rules can generally be divided into to types, replacement rules and
+ info rules.
+
+ Replacement rules has the form Qt3Symobl -> Qt4Symbol
+ Info rules includes the NeedHeader, Qt3Header, Qt4Header, InhertitsQt
+ rule types.
+*/
+void PortingRules::parseXml(QString fileName)
+{
+ QtSimpleXml *xmlPointer = loadXml(fileName);
+ QtSimpleXml &xml = *xmlPointer;
+
+ int ruleCount = xml[QLatin1String("Rules")].numChildren();
+ ++ruleCount;
+
+ for(int rule=0; rule<ruleCount; ++rule) {
+ QtSimpleXml &currentRule = xml[QLatin1String("Rules")][rule];
+ QString ruleType = currentRule.attribute(QLatin1String("Type"));
+
+ if(isReplacementRule(ruleType)) {
+ QString qt3Symbol = currentRule[QLatin1String("Qt3")].text();
+ QString qt4Symbol = currentRule[QLatin1String("Qt4")].text();
+
+ QString disable = currentRule.attribute(QLatin1String("Disable"));
+ if(disable == QLatin1String("True") || disable == QLatin1String("true")) {
+ disableRule(currentRule);
+ continue;
+ }
+
+ if (isRuleDisabled(currentRule))
+ continue;
+
+ if(ruleType == QLatin1String("RenamedHeader")) {
+ headerReplacements.insert(qt3Symbol.toLatin1(), qt4Symbol.toLatin1());
+ } else if(ruleType == QLatin1String("RenamedClass") || ruleType == QLatin1String("RenamedToken") ) {
+ tokenRules.append(new ClassNameReplacement(
+ qt3Symbol.toLatin1(), qt4Symbol.toLatin1()));
+ } else if(ruleType == QLatin1String("RenamedEnumvalue") || ruleType == QLatin1String("RenamedType") ||
+ ruleType == QLatin1String("RenamedQtSymbol") ) {
+ checkScopeAddRule(currentRule);
+ }
+ } else if(ruleType == QLatin1String("NeedHeader")) {
+ const QByteArray className = currentRule[QLatin1String("Class")].text().toLatin1();
+ const QByteArray headerName = currentRule[QLatin1String("Header")].text().toLatin1();
+ neededHeaders.insert(className, headerName);
+ }
+ else if(ruleType == QLatin1String("qt3Header")) {
+ qt3Headers += currentRule.text();
+ }
+ else if(ruleType == QLatin1String("qt4Header")) {
+ qt4Headers += currentRule.text();
+ }
+ else if(ruleType == QLatin1String("InheritsQt")) {
+ inheritsQtClass += currentRule.text();
+ }
+ else if(ruleType == QLatin1String("Qt4Class")) {
+ // Get library name, make it lowercase and chop of the "Qt" prefix.
+ const QByteArray libraryName = currentRule[QLatin1String("Library")].text().toLatin1().toLower().mid(2);
+ classLibraryList.insert(currentRule[QLatin1String("Name")].text().toLatin1(), libraryName);
+ }
+ }
+
+ QString includeFile = xml[QLatin1String("Rules")][QLatin1String("Include")].text();
+
+ if(includeFile != QString()) {
+ QString resolvedIncludeFile = resolveFileName(fileName, includeFile);
+ if (!resolvedIncludeFile.isEmpty())
+ parseXml(resolvedIncludeFile);
+ }
+
+ delete xmlPointer;
+}
+
+/*
+ Check if the rule in currentRule describes a qualified name
+ (like QButton::ToggleState). If so, create a scoped ScopedTokenReplacement,
+ else create a GenericTokenReplacement
+*/
+void PortingRules::checkScopeAddRule(/*const */QtSimpleXml &currentRule)
+{
+ QByteArray oldToken = currentRule[QLatin1String("Qt3")].text().toLatin1();
+ QByteArray newToken = currentRule[QLatin1String("Qt4")].text().toLatin1();
+
+ if (oldToken.contains(QByteArray("::")))
+ tokenRules.append(new ScopedTokenReplacement(oldToken, newToken));
+ else
+ tokenRules.append(new GenericTokenReplacement(oldToken, newToken));
+}
+
+/*
+ Loads the xml-file given by fileName into a new'ed QtSimpleXml, which is
+ returned by pointer.
+*/
+QtSimpleXml *PortingRules::loadXml(const QString fileName) const
+{
+ QFile f(fileName);
+ if(!f.open(QIODevice::ReadOnly)) {
+ qFatal("Could not find rule file %s", fileName.toLatin1().constData());
+ }
+ QtSimpleXml *xml = new QtSimpleXml();
+ if(!xml->setContent(&f))
+ addLogError(QLatin1String("Xml parsing failed: ") + xml->errorString());
+
+ return xml;
+}
+
+/*
+ Resolves includeFilePath against currentFilePath. If currentFilePath
+ contains foo/bar.xml, and includeFilePath contains bar2.xml, the returned
+ result will be foo/bar2.xml. If includeFilePath is absolute, it is returned
+ unmodified.
+*/
+QString PortingRules::resolveFileName(const QString currentFilePath,
+ const QString includeFilePath) const
+{
+ if(QFileInfo(includeFilePath).isAbsolute())
+ return includeFilePath;
+ QString relativeDirectory = QFileInfo(currentFilePath).dir().dirName();
+ QString testFileName = relativeDirectory + QLatin1String("/") + includeFilePath;
+ if (QFile::exists(testFileName))
+ return testFileName;
+
+ return QString();
+}
+/*
+ Checks if a rule is a replacement rule.
+*/
+bool PortingRules::isReplacementRule(const QString ruleType) const
+{
+ return (ruleType == QLatin1String("RenamedHeader") || ruleType == QLatin1String("RenamedClass") ||
+ ruleType == QLatin1String("RenamedToken") || ruleType == QLatin1String("RenamedEnumvalue") ||
+ ruleType == QLatin1String("RenamedType") || ruleType == QLatin1String("RenamedQtSymbol") );
+}
+
+/*
+ Disables a replacement rule given by the replacementRule parameter
+*/
+void PortingRules::disableRule(QtSimpleXml &replacementRule)
+{
+ RuleDescription ruleDescription(replacementRule);
+ disabledRules.append(ruleDescription);
+}
+
+/*
+ Checks if a replacement rule is disabled or not
+*/
+bool PortingRules::isRuleDisabled(QtSimpleXml &replacementRule) const
+{
+ RuleDescription ruleDescription(replacementRule);
+ return disabledRules.contains(ruleDescription);
+}
+
+/*
+ Adds a warning to the global logger.
+*/
+void PortingRules::addLogWarning(const QString text) const
+{
+ Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Warning"), QLatin1String("Porting"), text));
+}
+
+/*
+ Adds an error to the global logger.
+*/
+void PortingRules::addLogError(const QString text) const
+{
+ Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), text));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/portingrules.h b/tools/porting/src/portingrules.h
new file mode 100644
index 0000000000..ac9064ba07
--- /dev/null
+++ b/tools/porting/src/portingrules.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PORTINGRULES_H
+#define PORTINGRULES_H
+
+#include "qtsimplexml.h"
+#include "tokenreplacements.h"
+#include <QList>
+#include <QPair>
+#include <QHash>
+#include <QSet>
+#include <QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class RuleDescription
+{
+public:
+ explicit RuleDescription(QtSimpleXml &replacementRule) {
+ qt3 = replacementRule[QLatin1String("Qt3")].text();
+ qt4 = replacementRule[QLatin1String("Qt4")].text();
+ ruleType = replacementRule.attribute(QLatin1String("Type"));
+ }
+ QString qt3;
+ QString qt4;
+ QString ruleType;
+ bool operator==(const RuleDescription &other) const
+ {
+ return (qt3 == other.qt3 && qt4 == other.qt4 && ruleType == other.ruleType);
+ }
+};
+
+class PortingRules
+{
+public:
+ static void createInstance(QString xmlFilePath);
+ static PortingRules *instance();
+ static void deleteInstance();
+
+ enum QtVersion{Qt3, Qt4};
+ PortingRules(QString xmlFilePath);
+ QList<TokenReplacement*> getTokenReplacementRules();
+ QStringList getHeaderList(QtVersion qtVersion);
+ QHash<QByteArray, QByteArray> getNeededHeaders();
+ QStringList getInheritsQt();
+ QHash<QByteArray, QByteArray> getClassLibraryList();
+ QHash<QByteArray, QByteArray> getHeaderReplacements();
+private:
+ static PortingRules *theInstance;
+
+ QList<TokenReplacement*> tokenRules;
+ QStringList qt3Headers;
+ QStringList qt4Headers;
+ QHash<QByteArray, QByteArray> neededHeaders;
+ QStringList inheritsQtClass;
+ QList<RuleDescription> disabledRules;
+ QHash<QByteArray, QByteArray> classLibraryList;
+ QHash<QByteArray, QByteArray> headerReplacements;
+
+
+ void parseXml(const QString fileName);
+ void checkScopeAddRule(/*const */QtSimpleXml &currentRule);
+ QtSimpleXml *loadXml(const QString fileName) const ;
+ QString resolveFileName(const QString currentFileName,
+ const QString includeFileName) const;
+ bool isReplacementRule(const QString ruleType) const;
+ void disableRule(QtSimpleXml &replacementRule);
+ bool isRuleDisabled(QtSimpleXml &replacementRule) const;
+ void addLogWarning(const QString text) const;
+ void addLogError(const QString text) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // PORTINGRULES_H
diff --git a/tools/porting/src/preprocessorcontrol.cpp b/tools/porting/src/preprocessorcontrol.cpp
new file mode 100644
index 0000000000..4bfe197935
--- /dev/null
+++ b/tools/porting/src/preprocessorcontrol.cpp
@@ -0,0 +1,430 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "preprocessorcontrol.h"
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QTemporaryFile>
+
+QT_BEGIN_NAMESPACE
+using namespace TokenEngine;
+using namespace Rpp;
+
+IncludeFiles::IncludeFiles(const QString &basePath, const QStringList &searchPaths)
+:m_basePath(basePath)
+{
+ //prepend basePath to all relative paths in searchPaths
+ foreach (QString path, searchPaths) {
+ QString finalPath;
+ if (QDir::isAbsolutePath(path))
+ finalPath = QDir::cleanPath(path);
+ else
+ finalPath = QDir::cleanPath(m_basePath + QLatin1String("/") + path);
+
+ if(QFile::exists(finalPath))
+ m_searchPaths.append(finalPath);
+ }
+}
+
+/*
+ Performs an #include "..." style file lookup.
+ Aboslute filenames are checked directly. Relative filenames are first
+ looked for relative to the current file path, then the includepaths
+ are searched if not found.
+*/
+QString IncludeFiles::quoteLookup(const QString &currentFile,
+ const QString &includeFile) const
+{
+ //if includeFile is absolute, check if it exists
+ if (QDir::isAbsolutePath(includeFile)) {
+ if(QFile::exists(includeFile))
+ return includeFile;
+ else
+ return QString();
+ }
+
+ //If currentFile is not an absolute file path, make it one by
+ //prepending m_baspath
+ QString currentFilePath;
+ if(QDir::isAbsolutePath(currentFile))
+ currentFilePath = currentFile;
+ else
+ currentFilePath = QDir::cleanPath(m_basePath + QLatin1String("/") + currentFile);
+
+ //Check if it includeFile exists in the same dir as currentFilePath
+ const QString currentPath = QFileInfo(currentFilePath).path();
+ QString localFile = QDir::cleanPath(currentPath + QLatin1String("/") + includeFile);
+ if(QFile::exists(localFile))
+ return localFile;
+
+ return searchIncludePaths(includeFile);
+}
+
+/*
+ Performs an #include <...> style file lookup.
+ Aboslute filenames are checked directly.
+ Relative paths are searched for in the includepaths.
+*/
+QString IncludeFiles::angleBracketLookup(const QString &includeFile) const
+{
+ //if includeFile is absolute, check if it exists
+ if (QDir::isAbsolutePath(includeFile)) {
+ if(QFile::exists(includeFile))
+ return includeFile;
+ else
+ return QString();
+ }
+
+ return searchIncludePaths(includeFile);
+}
+
+QString IncludeFiles::resolve(const QString &filename) const
+{
+ if(QDir::isAbsolutePath(filename))
+ return filename;
+
+ QString prepended = QDir::cleanPath(m_basePath + QLatin1String("/") + filename);
+ if(QFile::exists(prepended))
+ return prepended;
+ else
+ return QString();
+}
+
+
+/*
+ Searches for includeFile paths by appending it to all includePaths
+ and checking if the file exists. Returns QString() if the file is not
+ found.
+*/
+QString IncludeFiles::searchIncludePaths(const QString &includeFile) const
+{
+ QString foundFile;
+ foreach(QString includePath, m_searchPaths) {
+ QString testFile = includePath + QLatin1String("/") + includeFile;
+ if(QFile::exists(testFile)){
+ foundFile = testFile;
+ break;
+ }
+ }
+ return foundFile;
+}
+
+QByteArray PreprocessorCache::readFile(const QString &filename) const
+{
+ // If anybody is connected to the readFile signal we tell them to
+ // read the file for us.
+ if (receivers(SIGNAL(readFile(QByteArray&,QString))) > 0) {
+ QByteArray array;
+ // Workaround for "not beeing able to emit from const function"
+ PreprocessorCache *cache = const_cast<PreprocessorCache *>(this);
+ emit cache->readFile(array, filename);
+ return array;
+ }
+
+ QFile f(filename);
+ if (!f.exists())
+ return QByteArray();
+ f.open(QIODevice::ReadOnly);
+ if (!f.isOpen())
+ return QByteArray();
+ return f.readAll();
+}
+
+PreprocessorCache::PreprocessorCache()
+{
+ connect(&m_preprocessor, SIGNAL(error(QString,QString)),
+ this, SIGNAL(error(QString,QString)));
+}
+
+
+/*
+ Return a TokenSequence with the contents of filname.
+ Assumens filename exists and is readable, returns a empty
+ TokenSequence if not.
+
+ The result is cached.
+*/
+TokenContainer PreprocessorCache::sourceTokens(const QString &filename)
+{
+ // Check if the source tokens are already in the cache.
+ if(m_sourceTokens.contains(filename))
+ return m_sourceTokens.value(filename);
+
+ // Read and tokenize file.
+ QByteArray fileContents = readFile(filename);
+ if(fileContents == QByteArray())
+ return TokenContainer();
+
+ QVector<TokenEngine::Token> tokenList = m_tokenizer.tokenize(fileContents);
+
+ // Create a FileInfo object that holds the filename for this container.
+ FileInfo *containterFileInfo = new FileInfo;
+ containterFileInfo->filename = filename;
+
+ // Create container.
+ TokenContainer tokenContainer(fileContents, tokenList, containterFileInfo);
+
+ // Insert into cache.
+ m_sourceTokens.insert(filename, tokenContainer);
+ return tokenContainer;
+}
+
+/*
+ Return a Source* tree representing the contents of filename.
+ Assumens filename exists and is readable, returns a empty
+ Source object if not.
+
+ The result is cached.
+*/
+Source *PreprocessorCache::sourceTree(const QString &filename)
+{
+ // Check if the Rpp tree for this file is already in the cache.
+ if(m_sourceTrees.contains(filename))
+ return m_sourceTrees.value(filename);
+
+ // Get the tokens for the contents of this file.
+ TokenContainer tokenContainer = sourceTokens(filename);
+
+ // Run lexer and the preprocessor-parser.
+ QVector<Type> tokenTypes = m_lexer.lex(tokenContainer);
+ Source *source = m_preprocessor.parse(tokenContainer, tokenTypes, &m_memoryPool);
+ source->setFileName(filename);
+
+ // Insert into cache.
+ if(tokenContainer.count() > 0) //don't cache empty files.
+ m_sourceTrees.insert(filename, source);
+
+ return source;
+}
+
+
+/*
+ Returns whether the cache contains a TokenContainer for the given filename.
+*/
+bool PreprocessorCache::containsSourceTokens(const QString &filename)
+{
+ return m_sourceTokens.contains(filename);
+}
+
+/*
+ Returns whether the cache contains a Preprocessor tree for the given filename.
+*/
+bool PreprocessorCache::containsSourceTree(const QString &filename)
+{
+ return m_sourceTrees.contains(filename);
+}
+
+PreprocessorController::PreprocessorController(IncludeFiles includeFiles,
+ PreprocessorCache &preprocessorCache,
+ QStringList preLoadFilesFilenames)
+:m_includeFiles(includeFiles),
+ m_preprocessorCache(preprocessorCache)
+ {
+ // Load qt3 headers from resources. The headers are stored as
+ // QHash<QString, QByteArray>, serialized using QDataStream. The hash
+ // maps filename -> contents.
+ if (preLoadFilesFilenames != QStringList()) {
+ foreach (QString filename, preLoadFilesFilenames) {
+ QFile f(filename);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray buffer = f.readAll();
+ f.close();
+ QDataStream stream(buffer);
+ QHash<QString, QByteArray> files;
+ stream >> files;
+ m_preLoadFiles.unite(files);
+ }
+ }
+ }
+
+ //connect include callback
+ connect(&m_rppTreeEvaluator,
+ SIGNAL(includeCallback(Rpp::Source *&, const Rpp::Source *,
+ const QString &, Rpp::RppTreeEvaluator::IncludeType)),
+ SLOT(includeSlot(Rpp::Source *&, const Rpp::Source *,
+ const QString &, Rpp::RppTreeEvaluator::IncludeType)));
+
+ // connect readFile callback
+ connect(&m_preprocessorCache, SIGNAL(readFile(QByteArray&,QString)),
+ SLOT(readFile(QByteArray&,QString)));
+
+ //connect error handlers
+ connect(&m_preprocessorCache , SIGNAL(error(QString,QString)),
+ this, SIGNAL(error(QString,QString)));
+}
+
+/*
+ Callback from RppTreeEvaluator, called when we evaluate an #include
+ directive. We do a filename lookup based on the type of include, and then ask
+ the cache to give us the source tree for that file.
+*/
+void PreprocessorController::includeSlot(Source *&includee,
+ const Source *includer,
+ const QString &filename,
+ RppTreeEvaluator::IncludeType includeType)
+{
+ QString newFilename;
+ if(includeType == RppTreeEvaluator::QuoteInclude)
+ newFilename = m_includeFiles.quoteLookup(includer->fileName(), filename);
+ else //AngleBracketInclude
+ newFilename = m_includeFiles.angleBracketLookup(filename);
+
+ if (QFile::exists(newFilename)) {
+ includee = m_preprocessorCache.sourceTree(newFilename);
+ return;
+ }
+
+ if (m_preLoadFiles.contains(filename)) {
+ includee = m_preprocessorCache.sourceTree(filename);
+ return;
+ }
+
+ includee = m_preprocessorCache.sourceTree(newFilename);
+ emit error(QLatin1String("Error"), QLatin1String("Could not find file ") + filename);
+}
+
+/*
+ Callback connected to preprocessorCache. Tries to load a file from
+ m_preLoadFiles before going to disk.
+*/
+void PreprocessorController::readFile(QByteArray &contents, QString filename)
+{
+ if (m_preLoadFiles.contains(filename)) {
+ contents = m_preLoadFiles.value(filename);
+ return;
+ }
+
+ QFile f(filename);
+ if (!f.exists())
+ return;
+ f.open(QIODevice::ReadOnly);
+ if (!f.isOpen())
+ return;
+ contents = f.readAll();
+}
+
+/*
+ Preprocess file give by filename. Filename is resloved agains the basepath
+ set in IncludeFiles.
+*/
+TokenSectionSequence PreprocessorController::evaluate(const QString &filename, Rpp::DefineMap *activedefinitions)
+{
+ QString resolvedFilename = m_includeFiles.resolve(filename);
+ if(!QFile::exists(resolvedFilename))
+ emit error(QLatin1String("Error"), QLatin1String("Could not find file: ") + filename);
+ Source *source = m_preprocessorCache.sourceTree(resolvedFilename);
+
+ return m_rppTreeEvaluator.evaluate(source, activedefinitions);
+}
+
+QByteArray defaultDefines =
+ "#define __attribute__(a...) \n \
+ #define __attribute__ \n \
+ #define __extension \n \
+ #define __extension__ \n \
+ #define __restrict \n \
+ #define __restrict__ \n \
+ #define __volatile volatile\n \
+ #define __volatile__ volatile\n \
+ #define __inline inline\n \
+ #define __inline__ inline\n \
+ #define __const const\n \
+ #define __const__ const\n \
+ #define __asm asm\n \
+ #define __asm__ asm\n \
+ #define __GNUC__ 2\n \
+ #define __GNUC_MINOR__ 95\n \
+ #define __cplusplus \n \
+ #define __linux__ \n";
+
+
+/*
+ Returns a DefineMap containing the above macro definitions. The DefineMap
+ will contain pointers to data stored in the provided cache object.
+*/
+Rpp::DefineMap *defaultMacros(PreprocessorCache &cache)
+{
+ DefineMap *defineMap = new DefineMap();
+ //write out default macros to a temp file
+ QTemporaryFile tempfile;
+ tempfile.open();
+ tempfile.write(defaultDefines);
+ tempfile.flush();
+
+ IncludeFiles *includeFiles = new IncludeFiles(QString(), QStringList());
+ PreprocessorController preprocessorController(*includeFiles, cache);
+ //evaluate default macro file.
+ preprocessorController.evaluate(tempfile.fileName(), defineMap);
+ delete includeFiles;
+ return defineMap;
+}
+
+void StandardOutErrorHandler::error(QString type, QString text)
+{
+ Q_UNUSED(type);
+ puts(qPrintable(text));
+}
+
+/*
+ RppPreprocessor is a convenience class that contains all the components
+ needed to preprocess files. Error messages are printed to standard out.
+*/
+RppPreprocessor::RppPreprocessor(QString basePath, QStringList includePaths, QStringList preLoadFilesFilenames)
+:m_includeFiles(basePath, includePaths)
+,m_activeDefinitions(defaultMacros(m_cache))
+,m_controller(m_includeFiles, m_cache, preLoadFilesFilenames)
+{
+ QObject::connect(&m_controller, SIGNAL(error(QString,QString)), &m_errorHandler, SLOT(error(QString,QString)));
+}
+
+RppPreprocessor::~RppPreprocessor()
+{
+ delete m_activeDefinitions;
+}
+
+TokenEngine::TokenSectionSequence RppPreprocessor::evaluate(const QString &filename)
+{
+ DefineMap defMap = *m_activeDefinitions;
+ return m_controller.evaluate(filename, &defMap);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/preprocessorcontrol.h b/tools/porting/src/preprocessorcontrol.h
new file mode 100644
index 0000000000..0c1c2f98f0
--- /dev/null
+++ b/tools/porting/src/preprocessorcontrol.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREPROCESSORCONTROL_H
+#define PREPROCESSORCONTROL_H
+
+#include "tokenengine.h"
+#include "tokenizer.h"
+#include "rpplexer.h"
+#include "rpptreeevaluator.h"
+#include "rpp.h"
+#include <QString>
+#include <QStringList>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+class IncludeFiles
+{
+public:
+ IncludeFiles(const QString &basePath, const QStringList &searchPaths);
+ QString quoteLookup(const QString &currentFile,
+ const QString &includeFile)const;
+ QString angleBracketLookup(const QString &includeFile) const;
+ QString resolve(const QString &filename) const;
+private:
+ QString searchIncludePaths(const QString &includeFile)const;
+ QStringList m_searchPaths;
+ QString m_basePath;
+};
+
+class PreprocessorCache: public QObject
+{
+Q_OBJECT
+public:
+ PreprocessorCache();
+ TokenEngine::TokenContainer sourceTokens(const QString &filename);
+ Rpp::Source *sourceTree(const QString &filename);
+ bool containsSourceTokens(const QString &filename);
+ bool containsSourceTree(const QString &filename);
+signals:
+ void error(QString type, QString text);
+ void readFile(QByteArray &contents, QString filename);
+private:
+ QByteArray readFile(const QString & filename) const;
+ Tokenizer m_tokenizer;
+ Rpp::RppLexer m_lexer;
+ Rpp::Preprocessor m_preprocessor;
+ TypedPool<Rpp::Item> m_memoryPool;
+ QHash<QString, Rpp::Source *> m_sourceTrees;
+ QHash<QString, TokenEngine::TokenContainer> m_sourceTokens;
+};
+
+class PreprocessorController: public QObject
+{
+Q_OBJECT
+public:
+ PreprocessorController(IncludeFiles includefiles,
+ PreprocessorCache &preprocessorCache,
+ QStringList preLoadFilesFilenames = QStringList());
+
+ TokenEngine::TokenSectionSequence evaluate(const QString &filename, Rpp::DefineMap *activedefinitions);
+public slots:
+ void includeSlot(Rpp::Source *&includee, const Rpp::Source *includer,
+ const QString &filename, Rpp::RppTreeEvaluator::IncludeType includeType);
+ void readFile(QByteArray &contents, QString filename);
+signals:
+ void error(QString type, QString text);
+private:
+ IncludeFiles m_includeFiles;
+ Rpp::RppTreeEvaluator m_rppTreeEvaluator;
+ PreprocessorCache &m_preprocessorCache;
+ QHash<QString, QByteArray> m_preLoadFiles;
+};
+
+Rpp::DefineMap *defaultMacros(PreprocessorCache &preprocessorCache);
+
+class StandardOutErrorHandler : public QObject
+{
+Q_OBJECT
+public slots:
+ void error(QString type, QString text);
+};
+
+class RppPreprocessor
+{
+public:
+ RppPreprocessor(QString basePath, QStringList includePaths, QStringList preLoadFilesFilename = QStringList());
+ ~RppPreprocessor();
+ TokenEngine::TokenSectionSequence evaluate(const QString &filename);
+private:
+ IncludeFiles m_includeFiles;
+ PreprocessorCache m_cache;
+ Rpp::DefineMap *m_activeDefinitions;
+ PreprocessorController m_controller;
+ StandardOutErrorHandler m_errorHandler;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/projectporter.cpp b/tools/porting/src/projectporter.cpp
new file mode 100644
index 0000000000..404c6726f2
--- /dev/null
+++ b/tools/porting/src/projectporter.cpp
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "projectporter.h"
+#include "proparser.h"
+#include "textreplacement.h"
+#include "fileporter.h"
+#include "logger.h"
+#include "translationunit.h"
+#include "codemodelattributes.h"
+#include <QtDebug>
+#include <QFile>
+#include <QDir>
+#include <QStringList>
+#include <QFileInfo>
+#include <QBuffer>
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+
+ProjectPorter::ProjectPorter(QString basePath, QStringList includeDirectories, QStringList qt3HeadersFilenames)
+:basePath(basePath)
+,includeDirectories(includeDirectories)
+,defaultDefinitions(defaultMacros(preprocessorCache))
+,filePorter(preprocessorCache)
+,qt3HeadersFilenames(qt3HeadersFilenames)
+,analyze(true)
+,warnings(false)
+{}
+
+void ProjectPorter::enableCppParsing(bool enable)
+{
+ analyze = enable;
+}
+
+void ProjectPorter::enableMissingFilesWarnings(bool enable)
+{
+ warnings = enable;
+}
+
+void ProjectPorter::portProject(QString fileName)
+{
+ QFileInfo fileInfo(fileName);
+ portProject(fileInfo.path(), fileInfo.fileName());
+}
+
+/*
+ Port a single file
+*/
+void ProjectPorter::portFile(QString fileName)
+{
+ if (analyze) {
+ IncludeFiles includeFiles(basePath, includeDirectories);
+
+ PreprocessorController preprocessor(includeFiles, preprocessorCache, qt3HeadersFilenames);
+ connect(&preprocessor, SIGNAL(error(QString,QString)), SLOT(error(QString,QString)));
+
+ Rpp::DefineMap definitionsCopy = *defaultDefinitions;
+ // Preprocess
+ TokenSectionSequence translationUnit = preprocessor.evaluate(fileName, &definitionsCopy);
+ // Parse
+ TranslationUnit translationUnitData = TranslationUnitAnalyzer().analyze(translationUnit);
+
+ // Enable attribute generation for this file.
+ enableAttributes(includeFiles, fileName);
+ // Generate attributes.
+ CodeModelAttributes().createAttributes(translationUnitData);
+ }
+
+ portFiles(QString(), QStringList() << fileName);
+}
+
+void ProjectPorter::error(QString type, QString text)
+{
+ if (warnings && type == QLatin1String("Error"))
+ printf("Warning: %s\n", text.toLocal8Bit().constData());
+}
+
+void ProjectPorter::portProject(QString basePath, QString proFileName)
+{
+ QString fullInFileName = basePath + QLatin1String("/") + proFileName;
+ QFileInfo infileInfo(fullInFileName);
+ if (!infileInfo.exists()) {
+ printf("Could not open file: %s\n", QDir::toNativeSeparators(fullInFileName).toLocal8Bit().constData());
+ return;
+ }
+
+ QString proFileContents = loadFile(fullInFileName);
+ QMap<QString, QString> proFileMap = proFileTagMap(proFileContents, QDir(basePath).absolutePath());
+
+
+ // Check if this is a TEMPLATE = subdirs .pro file, in that case we
+ // process each subdir (recursively).
+
+ QString templateTag = proFileMap[QLatin1String("TEMPLATE")];
+ if (templateTag == QLatin1String("subdirs")) {
+ QStringList subdirs = proFileMap[QLatin1String("SUBDIRS")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ foreach(QString subdir, subdirs) {
+ QString newBasePath = basePath + QLatin1String("/") + subdir;
+ QStringList dirsInSubdir = subdir.split(QRegExp(QLatin1String("/|\\\\")), QString::SkipEmptyParts);
+ QString newProFileName = dirsInSubdir.last() + QLatin1String(".pro");
+ portProject(newBasePath, newProFileName);
+ }
+ return;
+ }
+
+ // Get headers and sources file names from .pro file.
+ QStringList sources = proFileMap[QLatin1String("SOURCES")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ QStringList headers = proFileMap[QLatin1String("HEADERS")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ QStringList forms = proFileMap[QLatin1String("FORMS")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ QStringList uidoth;
+ for (int i = 0; i < forms.size(); ++i) {
+ QString ui_h = forms.at(i) + QLatin1String(".h");
+ if (QFile::exists(basePath + QLatin1String("/") + ui_h))
+ uidoth += ui_h;
+ }
+
+ if (analyze) {
+ printf("Parsing");
+ // Get include paths from the pro file.
+ QStringList includeProPaths = proFileMap[QLatin1String("INCLUDEPATH")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ QStringList dependProPaths = proFileMap[QLatin1String("DEPENDPATH")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ IncludeFiles includeFiles(basePath, includeDirectories + includeProPaths + dependProPaths);
+
+ PreprocessorController preprocessorController(includeFiles, preprocessorCache, qt3HeadersFilenames);
+ connect(&preprocessorController, SIGNAL(error(QString,QString)), SLOT(error(QString,QString)));
+
+ TranslationUnitAnalyzer translationUnitAnalyzer;
+ CodeModelAttributes codeModelAttributes;
+
+ // Enable attribute generation for header files.
+ foreach(QString headerFile, headers)
+ enableAttributes(includeFiles, headerFile);
+
+ // Enable attribute generation for ui.h files.
+ foreach(QString headerFile, uidoth)
+ enableAttributes(includeFiles, headerFile);
+
+ // Analyze each translation unit. (one per cpp file)
+ foreach(QString sourceFile, sources) {
+ printf(".");
+ fflush(stdout);
+ Rpp::DefineMap definitionsCopy = *defaultDefinitions;
+ TokenSectionSequence translationUnit =
+ preprocessorController.evaluate(sourceFile, &definitionsCopy);
+ TranslationUnit translationUnitData =
+ translationUnitAnalyzer.analyze(translationUnit);
+
+ // Enable attribute generation for this file.
+ enableAttributes(includeFiles, sourceFile);
+
+ codeModelAttributes.createAttributes(translationUnitData);
+ }
+ puts("");
+ }
+
+
+ // Port files.
+ portFiles(basePath, sources);
+ portFiles(basePath, headers);
+ if (!uidoth.isEmpty())
+ portFiles(basePath, uidoth);
+
+ Logger::instance()->globalState[QLatin1String("currentFileName")] = proFileName;
+ Logger::instance()->beginSection();
+ portProFile(fullInFileName, proFileMap);
+}
+
+/*
+ Port each file given in the fileNames list. If a file name is relative
+ it is assumed to be relative to basePath.
+*/
+void ProjectPorter::portFiles(QString basePath, QStringList fileNames)
+{
+ foreach(QString fileName, fileNames) {
+ QString fullFilePath;
+ QFileInfo fileInfo(fileName);
+ if (fileInfo.isAbsolute()) {
+ fullFilePath = QDir::cleanPath(fileName);
+ } else {
+ fullFilePath = QDir::cleanPath(basePath + QLatin1String("/") + fileName);
+ }
+
+ QFileInfo fullFilePathInfo(fullFilePath);
+ if (!fullFilePathInfo.exists()) {
+ printf("Could not find file: %s\n", QDir::toNativeSeparators(fullFilePath).toLocal8Bit().constData());
+ continue;
+ }
+
+ if (!processedFilesSet.contains(fullFilePath)){
+ Logger::instance()->globalState[QLatin1String("currentFileName")] = fullFilePath;
+ filePorter.port(fullFilePath);
+ processedFilesSet.insert(fullFilePath);
+ }
+ }
+}
+
+void ProjectPorter::portProFile(QString fileName, QMap<QString, QString> tagMap)
+{
+ // Read pro file.
+ QFile proFile(fileName);
+ if (!proFile.open(QIODevice::ReadOnly))
+ return;
+
+ const QByteArray contents = proFile.readAll();
+ const QByteArray lineEnding = detectLineEndings(contents);
+ proFile.seek(0);
+
+ QTextStream proTextStream(&proFile);
+ QStringList lines;
+ while (!proTextStream.atEnd())
+ lines += proTextStream.readLine();
+
+ proFile.close();
+
+ // Find out what modules we should add to the QT variable.
+ QSet<QByteArray> qtModules;
+
+ // Add qt3support to the Qt tag
+ qtModules.insert(QByteArray("qt3support"));
+
+ // Read CONFIG and add other modules.
+ QStringList config = tagMap[QLatin1String("CONFIG")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ if (config.contains(QLatin1String("opengl")))
+ qtModules.insert(QByteArray("opengl"));
+ if (config.contains(QLatin1String("xml")))
+ qtModules.insert(QByteArray("xml"));
+ if (config.contains(QLatin1String("sql")))
+ qtModules.insert(QByteArray("sql"));
+ if (config.contains(QLatin1String("network")))
+ qtModules.insert(QByteArray("network"));
+
+ // Get set of used modules from the file porter.
+ qtModules += filePorter.usedQtModules();
+
+ // Remove gui and core.
+ qtModules.remove(QByteArray("gui"));
+ qtModules.remove(QByteArray("core"));
+
+ // Qt3Support is already added.
+ qtModules.remove(QByteArray("3support"));
+
+ // Remove modules already present in the QT variable.
+ QStringList qt = tagMap[QLatin1String("QT")].split(QLatin1String(" "), QString::SkipEmptyParts);
+ foreach(QString name, qt) {
+ qtModules.remove(name.toLatin1());
+ }
+
+ Logger *logger = Logger::instance();
+ bool changesMade = false;
+
+ if (!qtModules.isEmpty()) {
+ changesMade = true;
+ QString insertText = QLatin1String("QT += ");
+ foreach(QByteArray module, qtModules) {
+ insertText += QString::fromLatin1(module) + QLatin1Char(' ');
+ }
+ lines += QString(QLatin1String("#The following line was inserted by qt3to4"));
+ lines += insertText;
+ QString logText = QLatin1String("In file ")
+ + logger->globalState.value(QLatin1String("currentFileName"))
+ + QLatin1String(": Added entry ")
+ + insertText;
+ logger->addEntry(new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), logText));
+ }
+
+ // Add uic3 if we have forms, and change FORMS and INTERFACES to FORMS3
+ if (!tagMap[QLatin1String("FORMS")].isEmpty() || !tagMap[QLatin1String("INTERFACES")].isEmpty()) {
+ changesMade = true;
+ lines += QString(QLatin1String("#The following line was inserted by qt3to4"));
+ QString insertText = QLatin1String("CONFIG += uic3") + QString::fromLatin1(lineEnding.constData());
+ lines += insertText;
+ QString logText = QLatin1String("In file ")
+ + logger->globalState.value(QLatin1String("currentFileName"))
+ + QLatin1String(": Added entry ")
+ + insertText;
+ logger->addEntry(new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), logText));
+
+ const QString formsToForms3(QLatin1String("#The following line was changed from FORMS to FORMS3 by qt3to4"));
+ const QString interfacesToForms3(QLatin1String("#The following line was changed from INTERFACES to FORMS3 by qt3to4"));
+ for (int i = 0; i < lines.count(); ++i) {
+ QString cLine = lines.at(i);
+ cLine = cLine.trimmed();
+ if (cLine.startsWith(QLatin1String("FORMS"))) {
+ lines[i].replace(QLatin1String("FORMS"), QLatin1String("FORMS3"));
+ lines.insert(i, formsToForms3);
+ ++i;
+ QString logText = QLatin1String("In file ")
+ + logger->globalState.value(QLatin1String("currentFileName"))
+ + QLatin1String(": Renamed FORMS to FORMS3");
+ logger->addEntry(new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), logText));
+ } else if (cLine.startsWith(QLatin1String("INTERFACES"))) {
+ lines[i].replace(QLatin1String("INTERFACES"), QLatin1String("FORMS3"));
+ lines.insert(i, interfacesToForms3);
+ ++i;
+ QString logText = QLatin1String("In file ")
+ + logger->globalState.value(QLatin1String("currentFileName"))
+ + QLatin1String(": Renamed INTERFACES to FORMS3");
+ logger->addEntry(new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), logText));
+ }
+ }
+ }
+
+ // Comment out any REQUIRES tag.
+ if (!tagMap[QLatin1String("REQUIRES")].isEmpty()) {
+ changesMade = true;
+ QString insertText(QLatin1String("#The following line was commented out by qt3to4"));
+ for (int i = 0; i < lines.count(); ++i) {
+ if (lines.at(i).startsWith(QLatin1String("REQUIRES"))) {
+ QString lineCopy = lines.at(i);
+ lineCopy.prepend(QLatin1Char('#'));
+ lines[i] = lineCopy;
+ lines.insert(i, insertText);
+ ++i; //skip ahead, we just insertet a line at i.
+ QString logText = QLatin1String("In file ")
+ + logger->globalState.value(QLatin1String("currentFileName"))
+ + QLatin1String(": Commented out REQUIRES section");
+ logger->addEntry(new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), logText));
+ }
+ }
+ }
+
+ // Check if any changes has been made.
+ if (!changesMade) {
+ Logger::instance()->addEntry(
+ new PlainLogEntry(QLatin1String("Info"), QLatin1String("Porting"), QLatin1String("No changes made to file ") + fileName));
+ Logger::instance()->commitSection();
+ return;
+ }
+
+ // Write lines to array.
+ QByteArray bob;
+ QTextStream outProFileStream(&bob);
+ foreach(QString line, lines)
+ outProFileStream << line << lineEnding;
+ outProFileStream.flush();
+
+ // Write array to file, commit log if write was successful.
+ FileWriter::WriteResult result = FileWriter::instance()->writeFileVerbously(fileName, bob);
+ if (result == FileWriter::WriteSucceeded) {
+ logger->commitSection();
+ } else if (result == FileWriter::WriteFailed) {
+ logger->revertSection();
+ logger->addEntry(
+ new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), QLatin1String("Error writing to file ") + fileName));
+ } else if (result == FileWriter::WriteSkipped) {
+ logger->revertSection();
+ logger->addEntry(
+ new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), QLatin1String("User skipped file ") + fileName));
+ } else {
+ // Internal error.
+ logger->revertSection();
+ const QString errorString = QLatin1String("Internal error in qt3to4 - FileWriter returned invalid result code while writing to ") + fileName;
+ logger->addEntry(new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), errorString));
+ }
+}
+
+/*
+ Enables attribute generation for fileName. The file is looked up using the
+ provied includeFiles object.
+*/
+void ProjectPorter::enableAttributes(const IncludeFiles &includeFiles, const QString &fileName)
+{
+ QString resolvedFilePath = includeFiles.resolve(fileName);
+ if (!QFile::exists(resolvedFilePath))
+ resolvedFilePath = includeFiles.angleBracketLookup(fileName);
+ if (!QFile::exists(resolvedFilePath))
+ return;
+
+ TokenContainer tokenContainer = preprocessorCache.sourceTokens(resolvedFilePath);
+ TokenAttributes *attributes = tokenContainer.tokenAttributes();
+ attributes->addAttribute("CreateAttributes", "True");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/projectporter.h b/tools/porting/src/projectporter.h
new file mode 100644
index 0000000000..e86c29a6fc
--- /dev/null
+++ b/tools/porting/src/projectporter.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROJECTPORTER_H
+#define PROJECTPORTER_H
+
+#include "fileporter.h"
+#include "preprocessorcontrol.h"
+#include <QString>
+#include <QSet>
+
+QT_BEGIN_NAMESPACE
+
+class ProjectPorter : public QObject
+{
+Q_OBJECT
+public:
+ ProjectPorter(QString basePath, QStringList includeDirectories, QStringList qt3HeadersFilenames = QStringList());
+ void enableCppParsing(bool enable);
+ void enableMissingFilesWarnings(bool enable);
+ void portProject(QString filePath);
+ void portFile(QString filePath);
+private slots:
+ void error(QString type, QString text);
+private:
+ void portProject(QString inPath, QString proFileName);
+ void portProFile(QString fileName, QMap<QString, QString> tagMap);
+ void portFiles(QString basePath, QStringList fileNames);
+ void enableAttributes(const IncludeFiles &includeFiles, const QString &fileName);
+
+ QSet<QString> processedFilesSet;
+ QString basePath;
+ QStringList includeDirectories;
+ PreprocessorCache preprocessorCache;
+ Rpp::DefineMap *defaultDefinitions;
+ FilePorter filePorter;
+ QStringList qt3HeadersFilenames;
+ bool analyze;
+ bool warnings;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/proparser.cpp b/tools/porting/src/proparser.cpp
new file mode 100644
index 0000000000..db3876ddf1
--- /dev/null
+++ b/tools/porting/src/proparser.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "proparser.h"
+
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QRegExp>
+#include <QStringList>
+#include <QTextStream>
+
+#ifdef Q_OS_UNIX
+#include <unistd.h>
+#endif
+
+#ifdef Q_OS_WIN32
+#define QT_POPEN _popen
+#else
+#define QT_POPEN popen
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QString loadFile( const QString &fileName )
+{
+ QFile file( fileName );
+ if ( !file.open(QIODevice::ReadOnly) ) {
+ fprintf( stderr, "error: Cannot load '%s': %s\n",
+ file.fileName().toLocal8Bit().constData(),
+ file.errorString().toLatin1().constData() );
+ return QString();
+ }
+
+ QTextStream in( &file );
+ return in.readAll();
+}
+
+QMap<QString, QString> proFileTagMap( const QString& text, QString currentPath )
+{
+ QString t = text;
+ if (currentPath.isEmpty())
+ currentPath = QDir::currentPath();
+
+
+ QMap<QString, QString> tagMap;
+ /*
+ Strip any commments before we try to include. We
+ still need to do it after we include to make sure the
+ included file does not have comments
+ */
+ t.replace( QRegExp(QLatin1String("#[^\n]*\n")), QLatin1String(" ") );
+ /*
+ Strip comments, merge lines ending with backslash, add
+ spaces around '=' and '+=', replace '\n' with ';', and
+ simplify white spaces.
+ */
+ t.replace( QRegExp(QLatin1String("#[^\n]*\n")), QLatin1String(" ") );
+ t.replace( QRegExp(QLatin1String("\\\\[^\n\\S]*\n")), QLatin1String(" ") );
+ t.replace( QLatin1String("="), QLatin1String(" = ") );
+ t.replace( QLatin1String("+ ="), QLatin1String(" += ") );
+ t.replace( QLatin1String("\n"), QLatin1String(";") );
+ t = t.simplified();
+
+ /*
+ Populate tagMap with 'key = value' entries.
+ */
+ QStringList lines = t.split(QLatin1Char(';'));
+ QStringList::Iterator line;
+ for ( line = lines.begin(); line != lines.end(); ++line ) {
+ QStringList toks = (*line).split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ if ( toks.count() >= 3 &&
+ (toks[1] == QLatin1String("=") || toks[1] == QLatin1String("+=") ||
+ toks[1] == QLatin1String("*=")) ) {
+ QString tag = toks.first();
+ int k = tag.lastIndexOf( QLatin1Char(':') ); // as in 'unix:'
+ if ( k != -1 )
+ tag = tag.mid( k + 1 );
+ toks.erase( toks.begin() );
+
+ QString action = toks.first();
+ toks.erase( toks.begin() );
+
+ if ( tagMap.contains(tag) ) {
+ if ( action == QLatin1String("=") )
+ tagMap.insert( tag, toks.join(QLatin1String(" ")) );
+ else
+ tagMap[tag] += QLatin1Char( ' ' ) + toks.join( QLatin1String(" ") );
+ } else {
+ tagMap[tag] = toks.join( QLatin1String(" ") );
+ }
+ }
+ }
+ /*
+ Expand $$variables within the 'value' part of a 'key = value'
+ pair.
+ */
+ QRegExp var( QLatin1String("\\$\\$[({]?([a-zA-Z0-9_]+)[)}]?") );
+ QMap<QString, QString>::Iterator it;
+ for ( it = tagMap.begin(); it != tagMap.end(); ++it ) {
+ int i = 0;
+ while ( (i = var.indexIn((*it), i)) != -1 ) {
+ int len = var.matchedLength();
+ QString invocation = var.cap(1);
+ QString after;
+
+ if ( invocation == QLatin1String("system") ) {
+ // skip system(); it will be handled in the next pass
+ ++i;
+ } else {
+ if ( tagMap.contains(invocation) )
+ after = tagMap[invocation];
+ else if (invocation.toLower() == QLatin1String("pwd"))
+ after = currentPath;
+ (*it).replace( i, len, after );
+ i += after.length();
+ }
+ }
+ }
+
+ /*
+ Execute system() calls.
+ */
+ QRegExp callToSystem( QLatin1String("\\$\\$system\\s*\\(([^()]*)\\)") );
+ for ( it = tagMap.begin(); it != tagMap.end(); ++it ) {
+ int i = 0;
+ while ( (i = callToSystem.indexIn((*it), i)) != -1 ) {
+ /*
+ This code is stolen from qmake's project.cpp file.
+ Ideally we would use the same parser, so we wouldn't
+ have this code duplication.
+ */
+ QString after;
+ char buff[256];
+ FILE *proc = QT_POPEN( callToSystem.cap(1).toLatin1().constData(), "r" );
+ while ( proc && !feof(proc) ) {
+ int read_in = int(fread( buff, 1, 255, proc ));
+ if ( !read_in )
+ break;
+ for ( int i = 0; i < read_in; i++ ) {
+ if ( buff[i] == '\n' || buff[i] == '\t' )
+ buff[i] = ' ';
+ }
+ buff[read_in] = '\0';
+ after += QLatin1String(buff);
+ }
+ (*it).replace( i, callToSystem.matchedLength(), after );
+ i += after.length();
+ }
+ }
+ return tagMap;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/proparser.h b/tools/porting/src/proparser.h
new file mode 100644
index 0000000000..8fdf46be40
--- /dev/null
+++ b/tools/porting/src/proparser.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROPARSER_H
+#define PROPARSER_H
+
+#include <QMap>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+QMap<QString, QString> proFileTagMap( const QString& text, QString currentPath = QString() );
+QString loadFile( const QString &fileName );
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/q3porting.xml b/tools/porting/src/q3porting.xml
new file mode 100644
index 0000000000..42a9ae69db
--- /dev/null
+++ b/tools/porting/src/q3porting.xml
@@ -0,0 +1,10567 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+**************************************************************************-->
+<Rules>
+ <Count>3796</Count>
+ <item Type="RenamedHeader" >
+ <Qt4>q3buttongroup.h</Qt4>
+ <Qt3>qvbuttongroup.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qcombobox.h</Qt4>
+ <Qt3>qcombo.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qtextstream.h</Qt4>
+ <Qt3>qtstream.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3objectdict.h</Qt4>
+ <Qt3>qobjcoll.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3accel.h</Qt4>
+ <Qt3>qaccel.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3asciicache.h</Qt4>
+ <Qt3>qasciicache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3asciidict.h</Qt4>
+ <Qt3>qasciidict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3buttongroup.h</Qt4>
+ <Qt3>qbuttongroup.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3cache.h</Qt4>
+ <Qt3>qcache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3canvas.h</Qt4>
+ <Qt3>qcanvas.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3cleanuphandler.h</Qt4>
+ <Qt3>qcleanuphandler.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3cstring.h</Qt4>
+ <Qt3>qcstring.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3databrowser.h</Qt4>
+ <Qt3>qdatabrowser.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3datatable.h</Qt4>
+ <Qt3>qdatatable.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dataview.h</Qt4>
+ <Qt3>qdataview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3datetimeedit.h</Qt4>
+ <Qt3>qdatetimeedit.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3deepcopy.h</Qt4>
+ <Qt3>qdeepcopy.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dict.h</Qt4>
+ <Qt3>qdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dns.h</Qt4>
+ <Qt3>qdns.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dockarea.h</Qt4>
+ <Qt3>qdockarea.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dockwindow.h</Qt4>
+ <Qt3>qdockwindow.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dragobject.h</Qt4>
+ <Qt3>qdragobject.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dropsite.h</Qt4>
+ <Qt3>qdropsite.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3editorfactory.h</Qt4>
+ <Qt3>qeditorfactory.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3filedialog.h</Qt4>
+ <Qt3>qfiledialog.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3frame.h</Qt4>
+ <Qt3>qframe.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ftp.h</Qt4>
+ <Qt3>qftp.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3garray.h</Qt4>
+ <Qt3>qgarray.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gcache.h</Qt4>
+ <Qt3>qgcache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gdict.h</Qt4>
+ <Qt3>qgdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3glist.h</Qt4>
+ <Qt3>qglist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3grid.h</Qt4>
+ <Qt3>qgrid.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gridview.h</Qt4>
+ <Qt3>qgridview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3groupbox.h</Qt4>
+ <Qt3>qgroupbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gvector.h</Qt4>
+ <Qt3>qgvector.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3hbox.h</Qt4>
+ <Qt3>qhbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3header.h</Qt4>
+ <Qt3>qheader.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3hgroupbox.h</Qt4>
+ <Qt3>qhgroupbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3http.h</Qt4>
+ <Qt3>qhttp.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3iconview.h</Qt4>
+ <Qt3>qiconview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3intcache.h</Qt4>
+ <Qt3>qintcache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3intdict.h</Qt4>
+ <Qt3>qintdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3listbox.h</Qt4>
+ <Qt3>qlistbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3listview.h</Qt4>
+ <Qt3>qlistview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3localfs.h</Qt4>
+ <Qt3>qlocalfs.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3mainwindow.h</Qt4>
+ <Qt3>qmainwindow.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3memarray.h</Qt4>
+ <Qt3>qmemarray.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3multilineedit.h</Qt4>
+ <Qt3>qmultilineedit.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3network.h</Qt4>
+ <Qt3>qnetwork.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3networkprotocol.h</Qt4>
+ <Qt3>qnetworkprotocol.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3objectdict.h</Qt4>
+ <Qt3>qobjectdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3paintdevicemetrics.h</Qt4>
+ <Qt3>qpaintdevicemetrics.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3picture.h</Qt4>
+ <Qt3>qpicture.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3pointarray.h</Qt4>
+ <Qt3>qpointarray.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3polygonscanner.h</Qt4>
+ <Qt3>qpolygonscanner.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3popupmenu.h</Qt4>
+ <Qt3>qpopupmenu.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3process.h</Qt4>
+ <Qt3>qprocess.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3progressbar.h</Qt4>
+ <Qt3>qprogressbar.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3progressdialog.h</Qt4>
+ <Qt3>qprogressdialog.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrcollection.h</Qt4>
+ <Qt3>qptrcollection.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrdict.h</Qt4>
+ <Qt3>qptrdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrlist.h</Qt4>
+ <Qt3>qptrlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrqueue.h</Qt4>
+ <Qt3>qptrqueue.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrstack.h</Qt4>
+ <Qt3>qptrstack.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrvector.h</Qt4>
+ <Qt3>qptrvector.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3rangecontrol.h</Qt4>
+ <Qt3>qrangecontrol.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3scrollview.h</Qt4>
+ <Qt3>qscrollview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3semaphore.h</Qt4>
+ <Qt3>qsemaphore.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3serversocket.h</Qt4>
+ <Qt3>qserversocket.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3shared.h</Qt4>
+ <Qt3>qshared.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3signal.h</Qt4>
+ <Qt3>qsignal.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3simplerichtext.h</Qt4>
+ <Qt3>qsimplerichtext.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3socket.h</Qt4>
+ <Qt3>qsocket.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3socketdevice.h</Qt4>
+ <Qt3>qsocketdevice.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sortedlist.h</Qt4>
+ <Qt3>qsortedlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlcursor.h</Qt4>
+ <Qt3>qsqlcursor.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqleditorfactory.h</Qt4>
+ <Qt3>qsqleditorfactory.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlform.h</Qt4>
+ <Qt3>qsqlform.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlpropertymap.h</Qt4>
+ <Qt3>qsqlpropertymap.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlselectcursor.h</Qt4>
+ <Qt3>qsqlselectcursor.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3strlist.h</Qt4>
+ <Qt3>qstrlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3strvec.h</Qt4>
+ <Qt3>qstrvec.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3stylesheet.h</Qt4>
+ <Qt3>qstylesheet.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3syntaxhighlighter.h</Qt4>
+ <Qt3>qsyntaxhighlighter.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3tabdialog.h</Qt4>
+ <Qt3>qtabdialog.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3table.h</Qt4>
+ <Qt3>qtable.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textbrowser.h</Qt4>
+ <Qt3>qtextbrowser.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textedit.h</Qt4>
+ <Qt3>qtextedit.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textstream.h</Qt4>
+ <Qt3>qtextstream.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textview.h</Qt4>
+ <Qt3>qtextview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3tl.h</Qt4>
+ <Qt3>qtl.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3toolbar.h</Qt4>
+ <Qt3>qtoolbar.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3url.h</Qt4>
+ <Qt3>qurl.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3urloperator.h</Qt4>
+ <Qt3>qurloperator.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3valuelist.h</Qt4>
+ <Qt3>qvaluelist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3valuestack.h</Qt4>
+ <Qt3>qvaluestack.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3valuevector.h</Qt4>
+ <Qt3>qvaluevector.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3vbox.h</Qt4>
+ <Qt3>qvbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3vgroupbox.h</Qt4>
+ <Qt3>qvgroupbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3whatsthis.h</Qt4>
+ <Qt3>qwhatsthis.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3widgetstack.h</Qt4>
+ <Qt3>qwidgetstack.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3wizard.h</Qt4>
+ <Qt3>qwizard.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3accel.h</Qt4>
+ <Qt3>qaccel.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3asciicache.h</Qt4>
+ <Qt3>qasciicache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3asciidict.h</Qt4>
+ <Qt3>qasciidict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3buttongroup.h</Qt4>
+ <Qt3>qbuttongroup.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3cache.h</Qt4>
+ <Qt3>qcache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3canvas.h</Qt4>
+ <Qt3>qcanvas.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3cleanuphandler.h</Qt4>
+ <Qt3>qcleanuphandler.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3cstring.h</Qt4>
+ <Qt3>qcstring.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3databrowser.h</Qt4>
+ <Qt3>qdatabrowser.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3datatable.h</Qt4>
+ <Qt3>qdatatable.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dataview.h</Qt4>
+ <Qt3>qdataview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3datetimeedit.h</Qt4>
+ <Qt3>qdatetimeedit.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3deepcopy.h</Qt4>
+ <Qt3>qdeepcopy.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dict.h</Qt4>
+ <Qt3>qdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dns.h</Qt4>
+ <Qt3>qdns.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dockarea.h</Qt4>
+ <Qt3>qdockarea.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dockwindow.h</Qt4>
+ <Qt3>qdockwindow.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dragobject.h</Qt4>
+ <Qt3>qdragobject.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3dropsite.h</Qt4>
+ <Qt3>qdropsite.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3editorfactory.h</Qt4>
+ <Qt3>qeditorfactory.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3filedialog.h</Qt4>
+ <Qt3>qfiledialog.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3frame.h</Qt4>
+ <Qt3>qframe.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ftp.h</Qt4>
+ <Qt3>qftp.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3garray.h</Qt4>
+ <Qt3>qgarray.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gcache.h</Qt4>
+ <Qt3>qgcache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gdict.h</Qt4>
+ <Qt3>qgdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3glist.h</Qt4>
+ <Qt3>qglist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3grid.h</Qt4>
+ <Qt3>qgrid.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gridview.h</Qt4>
+ <Qt3>qgridview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3groupbox.h</Qt4>
+ <Qt3>qgroupbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3gvector.h</Qt4>
+ <Qt3>qgvector.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3hbox.h</Qt4>
+ <Qt3>qhbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3header.h</Qt4>
+ <Qt3>qheader.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3hgroupbox.h</Qt4>
+ <Qt3>qhgroupbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3http.h</Qt4>
+ <Qt3>qhttp.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3iconview.h</Qt4>
+ <Qt3>qiconview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3intcache.h</Qt4>
+ <Qt3>qintcache.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3intdict.h</Qt4>
+ <Qt3>qintdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3listbox.h</Qt4>
+ <Qt3>qlistbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3listview.h</Qt4>
+ <Qt3>qlistview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3localfs.h</Qt4>
+ <Qt3>qlocalfs.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3mainwindow.h</Qt4>
+ <Qt3>qmainwindow.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3memarray.h</Qt4>
+ <Qt3>qmemarray.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3multilineedit.h</Qt4>
+ <Qt3>qmultilineedit.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3network.h</Qt4>
+ <Qt3>qnetwork.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3networkprotocol.h</Qt4>
+ <Qt3>qnetworkprotocol.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3objectdict.h</Qt4>
+ <Qt3>qobjectdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3paintdevicemetrics.h</Qt4>
+ <Qt3>qpaintdevicemetrics.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3picture.h</Qt4>
+ <Qt3>qpicture.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3pointarray.h</Qt4>
+ <Qt3>qpointarray.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3polygonscanner.h</Qt4>
+ <Qt3>qpolygonscanner.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3popupmenu.h</Qt4>
+ <Qt3>qpopupmenu.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3process.h</Qt4>
+ <Qt3>qprocess.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3progressbar.h</Qt4>
+ <Qt3>qprogressbar.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3progressdialog.h</Qt4>
+ <Qt3>qprogressdialog.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrcollection.h</Qt4>
+ <Qt3>qptrcollection.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrdict.h</Qt4>
+ <Qt3>qptrdict.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrlist.h</Qt4>
+ <Qt3>qptrlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrqueue.h</Qt4>
+ <Qt3>qptrqueue.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrstack.h</Qt4>
+ <Qt3>qptrstack.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3ptrvector.h</Qt4>
+ <Qt3>qptrvector.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3rangecontrol.h</Qt4>
+ <Qt3>qrangecontrol.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3scrollview.h</Qt4>
+ <Qt3>qscrollview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3semaphore.h</Qt4>
+ <Qt3>qsemaphore.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3serversocket.h</Qt4>
+ <Qt3>qserversocket.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3shared.h</Qt4>
+ <Qt3>qshared.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3signal.h</Qt4>
+ <Qt3>qsignal.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3simplerichtext.h</Qt4>
+ <Qt3>qsimplerichtext.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3socket.h</Qt4>
+ <Qt3>qsocket.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3socketdevice.h</Qt4>
+ <Qt3>qsocketdevice.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sortedlist.h</Qt4>
+ <Qt3>qsortedlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlcursor.h</Qt4>
+ <Qt3>qsqlcursor.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqleditorfactory.h</Qt4>
+ <Qt3>qsqleditorfactory.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlform.h</Qt4>
+ <Qt3>qsqlform.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlpropertymap.h</Qt4>
+ <Qt3>qsqlpropertymap.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3sqlselectcursor.h</Qt4>
+ <Qt3>qsqlselectcursor.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3strlist.h</Qt4>
+ <Qt3>qstrlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3strvec.h</Qt4>
+ <Qt3>qstrvec.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3stylesheet.h</Qt4>
+ <Qt3>qstylesheet.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3syntaxhighlighter.h</Qt4>
+ <Qt3>qsyntaxhighlighter.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3tabdialog.h</Qt4>
+ <Qt3>qtabdialog.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3table.h</Qt4>
+ <Qt3>qtable.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textbrowser.h</Qt4>
+ <Qt3>qtextbrowser.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textedit.h</Qt4>
+ <Qt3>qtextedit.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textstream.h</Qt4>
+ <Qt3>qtextstream.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3textview.h</Qt4>
+ <Qt3>qtextview.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3tl.h</Qt4>
+ <Qt3>qtl.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3toolbar.h</Qt4>
+ <Qt3>qtoolbar.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3url.h</Qt4>
+ <Qt3>qurl.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3urloperator.h</Qt4>
+ <Qt3>qurloperator.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3valuelist.h</Qt4>
+ <Qt3>qvaluelist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3valuestack.h</Qt4>
+ <Qt3>qvaluestack.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3valuevector.h</Qt4>
+ <Qt3>qvaluevector.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3vbox.h</Qt4>
+ <Qt3>qvbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3vgroupbox.h</Qt4>
+ <Qt3>qvgroupbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3whatsthis.h</Qt4>
+ <Qt3>qwhatsthis.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3widgetstack.h</Qt4>
+ <Qt3>qwidgetstack.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>q3wizard.h</Qt4>
+ <Qt3>qwizard.h</Qt3>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxAggregated</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxBase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxBindable</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxClass</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxScript</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxScriptEngine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxScriptManager</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxSelect</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>ActiveQt</Library>
+ <Name>QAxWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Accel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Action</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ActionGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3AsciiBucket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3AsciiCache</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3AsciiCacheIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3AsciiDict</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3AsciiDictIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3BaseBucket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3BoxLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Button</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ButtonGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Cache</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CacheIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Canvas</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasEllipse</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasItemList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasLine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasPixmap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasPixmapArray</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasPolygon</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasPolygonalItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasRectangle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasSpline</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasSprite</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasText</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CanvasView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CheckListItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CheckTableItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CleanupHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ColorDrag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ComboBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ComboTableItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3CString</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DataBrowser</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DataTable</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DataView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DateEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DateTimeEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DateTimeEditBase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DeepCopy</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Dict</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DictIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Dns</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DnsSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DockArea</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DockAreaLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DockWindow</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DragObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3DropSite</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3EditorFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3FileDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3FileIconProvider</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3FilePreview</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Frame</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Ftp</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GArray</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GCache</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GCacheIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GDict</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GDictIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GListStdIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Grid</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GridLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GridView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GroupBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3GVector</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3HBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3HBoxLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3HButtonGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Header</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3HGroupBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Http</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3HttpHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3HttpRequestHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3HttpResponseHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IconDrag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IconDragItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IconView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IconViewItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ImageDrag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IntBucket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IntCache</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IntCacheIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IntDict</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3IntDictIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ListBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ListBoxItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ListBoxPixmap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ListBoxText</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ListView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ListViewItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ListViewItemIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3LNode</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3LocalFs</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3MainWindow</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3MemArray</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3MimeSourceFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3MultiLineEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3NetworkOperation</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3NetworkProtocol</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3NetworkProtocolDict</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3NetworkProtocolFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3NetworkProtocolFactoryBase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ObjectDictionary</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PaintDeviceMetrics</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Painter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Picture</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PointArray</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PolygonScanner</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PopupMenu</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Process</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ProgressBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ProgressDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrBucket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrCollection</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrDict</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrDictIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrListStdIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrQueue</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrStack</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3PtrVector</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3RangeControl</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ScrollView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Semaphore</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ServerSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Shared</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Signal</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SimpleRichText</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SingleCleanupHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Socket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SocketDevice</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SortedList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SpinWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlCursor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlEditorFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlFieldInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlFieldInfoList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlForm</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlPropertyMap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlRecordInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SqlSelectCursor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StoredDrag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StrIList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StringBucket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StrIVec</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StrList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StrListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StrVec</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StyleSheet</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3StyleSheetItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3SyntaxHighlighter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TabDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Table</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TableItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TableSelection</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TextBrowser</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TextDrag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TextEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TextEditOptimPrivate</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TextStream</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TextView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TimeEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ToolBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3TSFUNC</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3UriDrag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Url</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3UrlOperator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ValueList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ValueListConstIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ValueListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ValueStack</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3ValueVector</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3VBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3VBoxLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3VButtonGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3VGroupBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3WhatsThis</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3WidgetStack</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>Qt3Support</Library>
+ <Name>Q3Wizard</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtAssistant</Library>
+ <Name>QAssistantClient</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAbstractEventDispatcher</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAbstractFileEngine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAbstractFileEngineHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAbstractItemModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAbstractListModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAbstractTableModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QArgument</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAtomic</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QAtomicPointer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QBasicAtomic</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QBasicAtomicPointer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QBasicTimer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QBitArray</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QBitRef</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QBool</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QBuffer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QByteArray</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QByteArrayMatcher</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QByteRef</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QCache</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QChar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QCharRef</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QChildEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QConstString</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QCOORD</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QCoreApplication</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QCustomEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QDataStream</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QDate</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QDateTime</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QDebug</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QDir</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QDynamicPropertyChangeEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QEventLoop</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFile</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFileInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFileInfoList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFileInfoListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFileSystemWatcher</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFlag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFlags</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QForeachContainer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QForeachContainerBase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QFSFileEngine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QGenericArgument</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QGenericReturnArgument</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QGlobalStatic</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QHash</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QHashData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QHashDummyNode</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QHashDummyValue</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QHashIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QHashNode</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QInternal</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QIntForSize</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QIntForType</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QIODevice</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLatin1Char</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLatin1String</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLibrary</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLibraryInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLineF</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLinkedList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLinkedListData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLinkedListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLinkedListNode</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QListData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QLocale</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMapData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMapIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaClassInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaEnum</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaMethod</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaProperty</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaType</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaTypeId</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMetaTypeId2</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMimeData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QModelIndex</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QModelIndexList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMultiHash</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMultiMap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutableHashIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutableLinkedListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutableListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutableMapIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutableSetIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutableStringListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutableVectorIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutex</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QMutexLocker</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QNoDebug</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QNoImplicitBoolCast</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QObjectCleanupHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QObjectData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QObjectList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QObjectUserData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QPair</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QPersistentModelIndex</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QPluginLoader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QPoint</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QPointer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QPointF</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QProcess</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QQueue</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QReadLocker</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QReadWriteLock</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QRect</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QRectF</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QRegExp</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QResource</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QReturnArgument</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSemaphore</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSet</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSetIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSettings</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSharedData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSharedDataPointer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSignalMapper</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSize</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSizeF</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSocketNotifier</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QStack</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QStdWString</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QString</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QStringList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QStringListIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QStringMatcher</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSysInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QSystemLocale</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTemporaryFile</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextCodec</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextCodecFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextCodecPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextDecoder</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextEncoder</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextIStream</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextOStream</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextStream</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextStreamFunction</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTextStreamManipulator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QThread</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QThreadStorage</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QThreadStorageData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTime</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTimeLine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTimer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTimerEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTranslator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTS</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QTypeInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QUintForSize</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QUintForType</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QUrl</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QUuid</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVariant</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVariantComparisonHelper</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVariantList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVariantMap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVarLengthArray</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVector</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVectorData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVectorIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QVectorTypedData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QWaitCondition</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtCore</Library>
+ <Name>QWriteLocker</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusAbstractAdaptor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusAbstractInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusArgument</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusConnection</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusConnectionInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusError</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusInterfacePtr</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusMessage</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusMetaType</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusObjectPath</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusReply</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusServer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusSignature</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDBus</Library>
+ <Name>QDBusVariant</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QAbstractExtensionFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QAbstractExtensionManager</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QAbstractFormBuilder</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerActionEditorInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerBrushManagerInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerComponents</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerContainerExtension</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerCustomWidgetCollectionInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerCustomWidgetInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerDnDItemInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerExportWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerExtraInfoExtension</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerFormEditorInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerFormEditorPluginInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerFormWindowCursorInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerFormWindowInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerFormWindowManagerInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerFormWindowToolInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerIconCacheInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerLayoutDecorationExtension</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerMemberSheetExtension</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerMetaDataBaseInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerMetaDataBaseItemInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerObjectInspectorInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerPropertyEditorInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerPropertySheetExtension</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerTaskMenuExtension</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerWidgetBoxInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerWidgetDataBaseInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerWidgetDataBaseItemInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QDesignerWidgetFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QExtensionFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QExtensionManager</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtDesigner</Library>
+ <Name>QFormBuilder</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractButton</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractGraphicsPathItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractGraphicsShapeItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractItemDelegate</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractItemView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractPageSetupDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractPrintDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractProxyModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractScrollArea</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractSlider</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractSpinBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractTextDocumentLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAbstractUndoItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessible</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleApplication</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleBridge</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleBridgeFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleBridgePlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleInterfaceEx</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleObjectEx</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessiblePlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAccessibleWidgetEx</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QAction</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QActionEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QActionGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QApplication</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QBitmap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QBoxLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QBrush</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QBrushData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QButtonGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCalendarWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCDEStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCheckBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCleanLooksStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCleanlooksStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QClipboard</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QClipboardEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCloseEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QColor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QColorDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QColorGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QColormap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QComboBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCommonStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCompleter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QConicalGradient</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QContextMenuEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCopChannel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCursor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QCursorShape</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDataWidgetMapper</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDateEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDateTimeEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecoration</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecorationAction</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecorationDefault</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecorationFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecorationFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecorationPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecorationStyled</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDecorationWindows</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDesktopServices</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDesktopWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDial</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDialogButtonBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDirectPainter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDirModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDockWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDoubleSpinBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDoubleValidator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDrag</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDragEnterEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDragLeaveEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDragMoveEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDragResponseEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QDropEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QErrorMessage</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFileDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFileIconProvider</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFileOpenEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFocusEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFocusFrame</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFont</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFontComboBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFontDatabase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFontDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFontInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFontMetrics</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFontMetricsF</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QFrame</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGradient</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGradientStop</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGradientStops</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsEllipseItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsItemAnimation</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsItemGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsLineItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsPathItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsPixmapItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsPolygonItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsRectItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsScene</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSceneContextMenuEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSceneDragDropEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSceneEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSceneHelpEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSceneHoverEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSceneMouseEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSceneWheelEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsSimpleTextItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsTextItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGraphicsView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGridLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QGroupBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QHBoxLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QHeaderView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QHelpEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QHideEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QHoverEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QIcon</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QIconDragEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QIconEngine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QIconEngineFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QIconEnginePlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QIconSet</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QImage</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QImageIOHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QImageIOHandlerFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QImageIOPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QImageReader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QImageTextKeyLang</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QImageWriter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QInputContext</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QInputContextFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QInputContextFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QInputContextPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QInputDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QInputEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QInputMethodEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QIntValidator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QItemDelegate</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QItemEditorCreator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QItemEditorCreatorBase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QItemEditorFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QItemSelection</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QItemSelectionModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QItemSelectionRange</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QKbdDriverFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QKbdDriverPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QKeyEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QKeySequence</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLabel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLayoutItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLayoutIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLCDNumber</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLinearGradient</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLineEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLinuxFb_Shared</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QLinuxFbScreen</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QListView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QListWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QListWidgetItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMacMime</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMacPasteBoardMime</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMacStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMainWindow</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMatrix</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMenu</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMenuBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMenubarUpdatedEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMenuItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMessageBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMimeSource</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMotifStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMouseDriverFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMouseDriverPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMouseEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMoveEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QMovie</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPageSetupDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPaintDevice</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPaintEngine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPaintEngineState</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPainter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPainterPath</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPainterPathPrivate</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPainterPathStroker</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPaintEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPalette</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPen</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPicture</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPictureFormatInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPictureFormatPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPictureIO</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPixmap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPixmapCache</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPlastiqueStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPolygon</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPolygonF</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPoolEntry</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPrintDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPrintEngine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPrinter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QProgressBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QProgressDialog</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QProxyModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QPushButton</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QRadialGradient</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QRadioButton</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QRegExpValidator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QRegion</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QResizeEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QRgb</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QRubberBand</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QScreen</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QScreenCursor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QScreenDriverFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QScreenDriverFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QScreenDriverPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QScrollArea</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QScrollBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSessionManager</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QShortcut</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QShortcutEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QShowEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSizeGrip</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSizePolicy</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSlider</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSortFilterProxyModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSound</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSpacerItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSpinBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSplashScreen</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSplitter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSplitterHandle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStackedLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStackedWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStandardItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStandardItemEditorCreator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStandardItemModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStatusBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStatusTipEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStringListModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleFactory</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleHintReturn</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleHintReturnMask</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOption</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionButton</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionComboBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionComplex</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionDockWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionFocusRect</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionFrame</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionFrameV2</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionGraphicsItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionGroupBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionMenuItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionProgressBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionProgressBarV2</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionQ3DockWindow</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionQ3ListView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionQ3ListViewItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionRubberBand</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionSizeGrip</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionSlider</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionSpinBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionTab</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionTabBarBase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionTabV2</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionTabWidgetFrame</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionTitleBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionToolBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionToolBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionToolButton</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionViewItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStyleOptionViewItemV2</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStylePainter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QStylePlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSyntaxHighlighter</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QSystemTrayIcon</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTabBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTabletEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTableView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTableWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTableWidgetItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTableWidgetSelectionRange</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTabWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextBlock</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextBlockFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextBlockGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextBlockUserData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextBrowser</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextCharFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextCursor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextDocument</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextDocumentFragment</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextFragment</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextFrame</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextFrameFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextFrameLayoutData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextImageFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextInlineObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextLength</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextLine</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextListFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextObjectInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextOption</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextTable</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextTableCell</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTextTableFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTimeEdit</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QToolBar</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QToolBarChangeEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QToolBox</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QToolButton</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QToolTip</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTransformedScreen</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTransportAuth</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTreeView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTreeWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTreeWidgetItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QTreeWidgetItemIterator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QUndoCommand</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QUndoGroup</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QUndoStack</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QUndoView</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QUpdateLaterEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QValidator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QVBoxLayout</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QVFbHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QVFbKeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QVFbKeyData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QVFbMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QVFbScreen</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QVNCScreen</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWhatsThis</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWhatsThisClickedEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWheelEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWidgetAction</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWidgetData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWidgetItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWidgetList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWidgetMapper</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWidgetSet</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWindowsMime</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWindowsStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWindowStateChangeEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWindowsXPStyle</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWMatrix</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWorkspace</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSBusMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSCalibratedMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSClient</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSCursor</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSCursorMap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSDisplay</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSEmbedWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSInputMethod</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSInternalWindowInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSKeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSKeyboardHandlerFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSLinuxTPMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSManager</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSMouseHandlerFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSPC101KeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSPcMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSPointerCalibrationData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSPropertyManager</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSProtocolItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSScreenSaver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSServer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSServerSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSSL5000KeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSSoundClient</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSSoundServer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSSoundServerSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSTslibMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSTtyKeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSUmKeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSUsbKeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSVr41xxKeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSVr41xxMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSWindow</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSWindowInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSYopyKeyboardHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QWSYopyMouseHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QX11EmbedContainer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QX11EmbedWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtGui</Library>
+ <Name>QX11Info</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QAbstractSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QFtp</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QHostAddress</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QHostInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QHttp</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QHttpHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QHttpRequestHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QHttpResponseHeader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QIPv6Address</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QNetworkAddressEntry</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QNetworkInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QNetworkProxy</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QTcpServer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QTcpSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QUdpSocket</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtNetwork</Library>
+ <Name>QUrlInfo</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtOpenGL</Library>
+ <Name>QGLColormap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtOpenGL</Library>
+ <Name>QGLContext</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtOpenGL</Library>
+ <Name>QGLFormat</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtOpenGL</Library>
+ <Name>QGLFramebufferObject</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtOpenGL</Library>
+ <Name>QGLPixelBuffer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtOpenGL</Library>
+ <Name>QGLWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QDB2Driver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QDB2Result</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QIBaseDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QIBaseResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QMYSQLDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QMYSQLResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QOCIDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QOCIResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QODBCDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QODBCResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QPSQLDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QPSQLResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlDatabase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlDriverCreator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlDriverCreatorBase</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlDriverFactoryInterface</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlDriverPlugin</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlError</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlField</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlIndex</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSQLite2Driver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSQLite2Result</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSQLiteDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSQLiteResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlQuery</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlQueryModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlRecord</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlRelation</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlRelationalDelegate</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlRelationalTableModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QSqlTableModel</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QTDSDriver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSql</Library>
+ <Name>QTDSResult</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSvg</Library>
+ <Name>QGraphicsSvgItem</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSvg</Library>
+ <Name>QSvgRenderer</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtSvg</Library>
+ <Name>QSvgWidget</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QEventSizeOfChecker</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QSignalSpy</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QSpontaneKeyEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTest</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestAccessibility</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestAccessibilityEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestDelayEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestEventList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestEventLoop</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestKeyClicksEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestKeyEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtTest</Library>
+ <Name>QTestMouseEvent</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtUiTools</Library>
+ <Name>QUiLoader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomAttr</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomCDATASection</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomCharacterData</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomComment</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomDocument</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomDocumentFragment</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomDocumentType</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomElement</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomEntity</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomEntityReference</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomImplementation</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomNamedNodeMap</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomNode</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomNodeList</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomNotation</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomProcessingInstruction</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QDomText</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlAttributes</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlContentHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlDeclHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlDefaultHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlDTDHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlEntityResolver</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlErrorHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlInputSource</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlLexicalHandler</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlLocator</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlNamespaceSupport</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlParseException</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlReader</Name>
+ </item>
+ <item Type="Qt4Class" >
+ <Library>QtXml</Library>
+ <Name>QXmlSimpleReader</Name>
+ </item>
+ <item Type="qt3Header" >jri.h</item>
+ <item Type="qt3Header" >jri_md.h</item>
+ <item Type="qt3Header" >jritypes.h</item>
+ <item Type="qt3Header" >moc_yacc.h</item>
+ <item Type="qt3Header" >mwerks_mac.h</item>
+ <item Type="qt3Header" >npapi.h</item>
+ <item Type="qt3Header" >npupp.h</item>
+ <item Type="qt3Header" >q1xcompatibility.h</item>
+ <item Type="qt3Header" >qabstractlayout.h</item>
+ <item Type="qt3Header" >qaccel.h</item>
+ <item Type="qt3Header" >qaccessible.h</item>
+ <item Type="qt3Header" >qaction.h</item>
+ <item Type="qt3Header" >qapp.h</item>
+ <item Type="qt3Header" >qapplication.h</item>
+ <item Type="qt3Header" >qaquastyle.h</item>
+ <item Type="qt3Header" >qarray.h</item>
+ <item Type="qt3Header" >qasciicache.h</item>
+ <item Type="qt3Header" >qasciidict.h</item>
+ <item Type="qt3Header" >qassistantclient.h</item>
+ <item Type="qt3Header" >qasyncimageio.h</item>
+ <item Type="qt3Header" >qasyncio.h</item>
+ <item Type="qt3Header" >qaxbase.h</item>
+ <item Type="qt3Header" >qaxbindable.h</item>
+ <item Type="qt3Header" >qaxfactory.h</item>
+ <item Type="qt3Header" >qaxobject.h</item>
+ <item Type="qt3Header" >qaxscript.h</item>
+ <item Type="qt3Header" >qaxwidget.h</item>
+ <item Type="qt3Header" >qbig5codec.h</item>
+ <item Type="qt3Header" >qbitarray.h</item>
+ <item Type="qt3Header" >qbitarry.h</item>
+ <item Type="qt3Header" >qbitmap.h</item>
+ <item Type="qt3Header" >qbrush.h</item>
+ <item Type="qt3Header" >qbttngrp.h</item>
+ <item Type="qt3Header" >qbuffer.h</item>
+ <item Type="qt3Header" >qbutton.h</item>
+ <item Type="qt3Header" >qbuttongroup.h</item>
+ <item Type="qt3Header" >qcache.h</item>
+ <item Type="qt3Header" >qcanvas.h</item>
+ <item Type="qt3Header" >qcdestyle.h</item>
+ <item Type="qt3Header" >qcheckbox.h</item>
+ <item Type="qt3Header" >qchkbox.h</item>
+ <item Type="qt3Header" >qcleanuphandler.h</item>
+ <item Type="qt3Header" >qclipboard.h</item>
+ <item Type="qt3Header" >qclipbrd.h</item>
+ <item Type="qt3Header" >qcollect.h</item>
+ <item Type="qt3Header" >qcollection.h</item>
+ <item Type="qt3Header" >qcolor.h</item>
+ <item Type="qt3Header" >qcolordialog.h</item>
+ <item Type="qt3Header" >qcombo.h</item>
+ <item Type="qt3Header" >qcombobox.h</item>
+ <item Type="qt3Header" >qcommonstyle.h</item>
+ <item Type="qt3Header" >qcompactstyle.h</item>
+ <item Type="qt3Header" >qconfig-dist.h</item>
+ <item Type="qt3Header" >qconfig-large.h</item>
+ <item Type="qt3Header" >qconfig-medium.h</item>
+ <item Type="qt3Header" >qconfig-minimal.h</item>
+ <item Type="qt3Header" >qconfig-small.h</item>
+ <item Type="qt3Header" >qconfig.h</item>
+ <item Type="qt3Header" >qconnect.h</item>
+ <item Type="qt3Header" >qconnection.h</item>
+ <item Type="qt3Header" >qcopchannel_qws.h</item>
+ <item Type="qt3Header" >qcstring.h</item>
+ <item Type="qt3Header" >qcursor.h</item>
+ <item Type="qt3Header" >qdatabrowser.h</item>
+ <item Type="qt3Header" >qdatastream.h</item>
+ <item Type="qt3Header" >qdatatable.h</item>
+ <item Type="qt3Header" >qdataview.h</item>
+ <item Type="qt3Header" >qdatetime.h</item>
+ <item Type="qt3Header" >qdatetimeedit.h</item>
+ <item Type="qt3Header" >qdatetm.h</item>
+ <item Type="qt3Header" >qdeepcopy.h</item>
+ <item Type="qt3Header" >qdesktopwidget.h</item>
+ <item Type="qt3Header" >qdial.h</item>
+ <item Type="qt3Header" >qdialog.h</item>
+ <item Type="qt3Header" >qdict.h</item>
+ <item Type="qt3Header" >qdir.h</item>
+ <item Type="qt3Header" >qdirectpainter_qws.h</item>
+ <item Type="qt3Header" >qdns.h</item>
+ <item Type="qt3Header" >qdockarea.h</item>
+ <item Type="qt3Header" >qdockwindow.h</item>
+ <item Type="qt3Header" >qdom.h</item>
+ <item Type="qt3Header" >qdragobject.h</item>
+ <item Type="qt3Header" >qdrawutil.h</item>
+ <item Type="qt3Header" >qdrawutl.h</item>
+ <item Type="qt3Header" >qdropsite.h</item>
+ <item Type="qt3Header" >qdstream.h</item>
+ <item Type="qt3Header" >qeditorfactory.h</item>
+ <item Type="qt3Header" >qerrormessage.h</item>
+ <item Type="qt3Header" >qeucjpcodec.h</item>
+ <item Type="qt3Header" >qeuckrcodec.h</item>
+ <item Type="qt3Header" >qevent.h</item>
+ <item Type="qt3Header" >qeventloop.h</item>
+ <item Type="qt3Header" >qfeatures.h</item>
+ <item Type="qt3Header" >qfile.h</item>
+ <item Type="qt3Header" >qfiledef.h</item>
+ <item Type="qt3Header" >qfiledialog.h</item>
+ <item Type="qt3Header" >qfiledlg.h</item>
+ <item Type="qt3Header" >qfileinf.h</item>
+ <item Type="qt3Header" >qfileinfo.h</item>
+ <item Type="qt3Header" >qfocusdata.h</item>
+ <item Type="qt3Header" >qfont.h</item>
+ <item Type="qt3Header" >qfontdatabase.h</item>
+ <item Type="qt3Header" >qfontdialog.h</item>
+ <item Type="qt3Header" >qfontfactorybdf_qws.h</item>
+ <item Type="qt3Header" >qfontfactoryttf_qws.h</item>
+ <item Type="qt3Header" >qfontinf.h</item>
+ <item Type="qt3Header" >qfontinfo.h</item>
+ <item Type="qt3Header" >qfontmanager_qws.h</item>
+ <item Type="qt3Header" >qfontmet.h</item>
+ <item Type="qt3Header" >qfontmetrics.h</item>
+ <item Type="qt3Header" >qframe.h</item>
+ <item Type="qt3Header" >qftp.h</item>
+ <item Type="qt3Header" >qfunctions_wce.h</item>
+ <item Type="qt3Header" >qgarray.h</item>
+ <item Type="qt3Header" >qgb18030codec.h</item>
+ <item Type="qt3Header" >qgbkcodec.h</item>
+ <item Type="qt3Header" >qgcache.h</item>
+ <item Type="qt3Header" >qgdict.h</item>
+ <item Type="qt3Header" >qgeneric.h</item>
+ <item Type="qt3Header" >qgfx_qws.h</item>
+ <item Type="qt3Header" >qgfxdriverfactory_qws.h</item>
+ <item Type="qt3Header" >qgfxdriverplugin_qws.h</item>
+ <item Type="qt3Header" >qgfxlinuxfb_qws.h</item>
+ <item Type="qt3Header" >qgfxmach64_qws.h</item>
+ <item Type="qt3Header" >qgfxmach64defs_qws.h</item>
+ <item Type="qt3Header" >qgfxmatrox_qws.h</item>
+ <item Type="qt3Header" >qgfxmatroxdefs_qws.h</item>
+ <item Type="qt3Header" >qgfxraster_qws.h</item>
+ <item Type="qt3Header" >qgfxrepeater_qws.h</item>
+ <item Type="qt3Header" >qgfxshadowfb_qws.h</item>
+ <item Type="qt3Header" >qgfxsnap_qws.h</item>
+ <item Type="qt3Header" >qgfxtransformed_qws.h</item>
+ <item Type="qt3Header" >qgfxvfb_qws.h</item>
+ <item Type="qt3Header" >qgfxvga16_qws.h</item>
+ <item Type="qt3Header" >qgfxvnc_qws.h</item>
+ <item Type="qt3Header" >qgfxvoodoo_qws.h</item>
+ <item Type="qt3Header" >qgfxvoodoodefs_qws.h</item>
+ <item Type="qt3Header" >qgif.h</item>
+ <item Type="qt3Header" >qgl.h</item>
+ <item Type="qt3Header" >qglcolormap.h</item>
+ <item Type="qt3Header" >qglist.h</item>
+ <item Type="qt3Header" >qglobal.h</item>
+ <item Type="qt3Header" >qgplugin.h</item>
+ <item Type="qt3Header" >qgrid.h</item>
+ <item Type="qt3Header" >qgridview.h</item>
+ <item Type="qt3Header" >qgroupbox.h</item>
+ <item Type="qt3Header" >qgrpbox.h</item>
+ <item Type="qt3Header" >qguardedptr.h</item>
+ <item Type="qt3Header" >qgvector.h</item>
+ <item Type="qt3Header" >qhbox.h</item>
+ <item Type="qt3Header" >qhbuttongroup.h</item>
+ <item Type="qt3Header" >qheader.h</item>
+ <item Type="qt3Header" >qhgroupbox.h</item>
+ <item Type="qt3Header" >qhostaddress.h</item>
+ <item Type="qt3Header" >qhttp.h</item>
+ <item Type="qt3Header" >qiconset.h</item>
+ <item Type="qt3Header" >qiconview.h</item>
+ <item Type="qt3Header" >qimage.h</item>
+ <item Type="qt3Header" >qimageformatplugin.h</item>
+ <item Type="qt3Header" >qinputdialog.h</item>
+ <item Type="qt3Header" >qintcach.h</item>
+ <item Type="qt3Header" >qintcache.h</item>
+ <item Type="qt3Header" >qintdict.h</item>
+ <item Type="qt3Header" >qinterlacestyle.h</item>
+ <item Type="qt3Header" >qiodev.h</item>
+ <item Type="qt3Header" >qiodevice.h</item>
+ <item Type="qt3Header" >qjiscodec.h</item>
+ <item Type="qt3Header" >qjpegio.h</item>
+ <item Type="qt3Header" >qjpunicode.h</item>
+ <item Type="qt3Header" >qkbd_qws.h</item>
+ <item Type="qt3Header" >qkbddriverfactory_qws.h</item>
+ <item Type="qt3Header" >qkbddriverplugin_qws.h</item>
+ <item Type="qt3Header" >qkbdpc101_qws.h</item>
+ <item Type="qt3Header" >qkbdsl5000_qws.h</item>
+ <item Type="qt3Header" >qkbdtty_qws.h</item>
+ <item Type="qt3Header" >qkbdusb_qws.h</item>
+ <item Type="qt3Header" >qkbdvr41xx_qws.h</item>
+ <item Type="qt3Header" >qkbdyopy_qws.h</item>
+ <item Type="qt3Header" >qkeyboard_qws.h</item>
+ <item Type="qt3Header" >qkeycode.h</item>
+ <item Type="qt3Header" >qkeysequence.h</item>
+ <item Type="qt3Header" >qlabel.h</item>
+ <item Type="qt3Header" >qlayout.h</item>
+ <item Type="qt3Header" >qlcdnum.h</item>
+ <item Type="qt3Header" >qlcdnumber.h</item>
+ <item Type="qt3Header" >qlibrary.h</item>
+ <item Type="qt3Header" >qlined.h</item>
+ <item Type="qt3Header" >qlineedit.h</item>
+ <item Type="qt3Header" >qlist.h</item>
+ <item Type="qt3Header" >qlistbox.h</item>
+ <item Type="qt3Header" >qlistview.h</item>
+ <item Type="qt3Header" >qlocale.h</item>
+ <item Type="qt3Header" >qlocalfs.h</item>
+ <item Type="qt3Header" >qmacstyle_mac.h</item>
+ <item Type="qt3Header" >qmainwindow.h</item>
+ <item Type="qt3Header" >qmap.h</item>
+ <item Type="qt3Header" >qmemarray.h</item>
+ <item Type="qt3Header" >qmemorymanager_qws.h</item>
+ <item Type="qt3Header" >qmenubar.h</item>
+ <item Type="qt3Header" >qmenudata.h</item>
+ <item Type="qt3Header" >qmenudta.h</item>
+ <item Type="qt3Header" >qmessagebox.h</item>
+ <item Type="qt3Header" >qmetaobj.h</item>
+ <item Type="qt3Header" >qmetaobject.h</item>
+ <item Type="qt3Header" >qmime.h</item>
+ <item Type="qt3Header" >qmlined.h</item>
+ <item Type="qt3Header" >qmngio.h</item>
+ <item Type="qt3Header" >qmodules.h</item>
+ <item Type="qt3Header" >qmotif.h</item>
+ <item Type="qt3Header" >qmotifdialog.h</item>
+ <item Type="qt3Header" >qmotifplusstyle.h</item>
+ <item Type="qt3Header" >qmotifstyle.h</item>
+ <item Type="qt3Header" >qmotifwidget.h</item>
+ <item Type="qt3Header" >qmouse_qws.h</item>
+ <item Type="qt3Header" >qmousebus_qws.h</item>
+ <item Type="qt3Header" >qmousedriverfactory_qws.h</item>
+ <item Type="qt3Header" >qmousedriverplugin_qws.h</item>
+ <item Type="qt3Header" >qmouselinuxtp_qws.h</item>
+ <item Type="qt3Header" >qmousepc_qws.h</item>
+ <item Type="qt3Header" >qmousevr41xx_qws.h</item>
+ <item Type="qt3Header" >qmouseyopy_qws.h</item>
+ <item Type="qt3Header" >qmovie.h</item>
+ <item Type="qt3Header" >qmsgbox.h</item>
+ <item Type="qt3Header" >qmultilinedit.h</item>
+ <item Type="qt3Header" >qmultilineedit.h</item>
+ <item Type="qt3Header" >qmutex.h</item>
+ <item Type="qt3Header" >qnamespace.h</item>
+ <item Type="qt3Header" >qnetwork.h</item>
+ <item Type="qt3Header" >qnetworkprotocol.h</item>
+ <item Type="qt3Header" >qnp.h</item>
+ <item Type="qt3Header" >qobjcoll.h</item>
+ <item Type="qt3Header" >qobjdefs.h</item>
+ <item Type="qt3Header" >qobject.h</item>
+ <item Type="qt3Header" >qobjectcleanuphandler.h</item>
+ <item Type="qt3Header" >qobjectdefs.h</item>
+ <item Type="qt3Header" >qobjectdict.h</item>
+ <item Type="qt3Header" >qobjectlist.h</item>
+ <item Type="qt3Header" >qpaintd.h</item>
+ <item Type="qt3Header" >qpaintdc.h</item>
+ <item Type="qt3Header" >qpaintdevice.h</item>
+ <item Type="qt3Header" >qpaintdevicedefs.h</item>
+ <item Type="qt3Header" >qpaintdevicemetrics.h</item>
+ <item Type="qt3Header" >qpainter.h</item>
+ <item Type="qt3Header" >qpair.h</item>
+ <item Type="qt3Header" >qpalette.h</item>
+ <item Type="qt3Header" >qpdevmet.h</item>
+ <item Type="qt3Header" >qpen.h</item>
+ <item Type="qt3Header" >qpicture.h</item>
+ <item Type="qt3Header" >qpixmap.h</item>
+ <item Type="qt3Header" >qpixmapcache.h</item>
+ <item Type="qt3Header" >qplatinumstyle.h</item>
+ <item Type="qt3Header" >qpmcache.h</item>
+ <item Type="qt3Header" >qpngio.h</item>
+ <item Type="qt3Header" >qpntarry.h</item>
+ <item Type="qt3Header" >qpocketpcstyle_wce.h</item>
+ <item Type="qt3Header" >qpoint.h</item>
+ <item Type="qt3Header" >qpointarray.h</item>
+ <item Type="qt3Header" >qpolygonscanner.h</item>
+ <item Type="qt3Header" >qpopmenu.h</item>
+ <item Type="qt3Header" >qpopupmenu.h</item>
+ <item Type="qt3Header" >qprintdialog.h</item>
+ <item Type="qt3Header" >qprinter.h</item>
+ <item Type="qt3Header" >qprndlg.h</item>
+ <item Type="qt3Header" >qprocess.h</item>
+ <item Type="qt3Header" >qprogbar.h</item>
+ <item Type="qt3Header" >qprogdlg.h</item>
+ <item Type="qt3Header" >qprogressbar.h</item>
+ <item Type="qt3Header" >qprogressdialog.h</item>
+ <item Type="qt3Header" >qpsprn.h</item>
+ <item Type="qt3Header" >qptrcollection.h</item>
+ <item Type="qt3Header" >qptrdict.h</item>
+ <item Type="qt3Header" >qptrlist.h</item>
+ <item Type="qt3Header" >qptrqueue.h</item>
+ <item Type="qt3Header" >qptrstack.h</item>
+ <item Type="qt3Header" >qptrvector.h</item>
+ <item Type="qt3Header" >qpushbt.h</item>
+ <item Type="qt3Header" >qpushbutton.h</item>
+ <item Type="qt3Header" >qqueue.h</item>
+ <item Type="qt3Header" >qradiobt.h</item>
+ <item Type="qt3Header" >qradiobutton.h</item>
+ <item Type="qt3Header" >qrangecontrol.h</item>
+ <item Type="qt3Header" >qrangect.h</item>
+ <item Type="qt3Header" >qrect.h</item>
+ <item Type="qt3Header" >qregexp.h</item>
+ <item Type="qt3Header" >qregion.h</item>
+ <item Type="qt3Header" >qrtlcodec.h</item>
+ <item Type="qt3Header" >qscrbar.h</item>
+ <item Type="qt3Header" >qscrollbar.h</item>
+ <item Type="qt3Header" >qscrollview.h</item>
+ <item Type="qt3Header" >qsemaphore.h</item>
+ <item Type="qt3Header" >qsemimodal.h</item>
+ <item Type="qt3Header" >qserversocket.h</item>
+ <item Type="qt3Header" >qsession.h</item>
+ <item Type="qt3Header" >qsessionmanager.h</item>
+ <item Type="qt3Header" >qsettings.h</item>
+ <item Type="qt3Header" >qsgistyle.h</item>
+ <item Type="qt3Header" >qshared.h</item>
+ <item Type="qt3Header" >qsignal.h</item>
+ <item Type="qt3Header" >qsignalmapper.h</item>
+ <item Type="qt3Header" >qsignalslotimp.h</item>
+ <item Type="qt3Header" >qsimplerichtext.h</item>
+ <item Type="qt3Header" >qsize.h</item>
+ <item Type="qt3Header" >qsizegrip.h</item>
+ <item Type="qt3Header" >qsizepolicy.h</item>
+ <item Type="qt3Header" >qsjiscodec.h</item>
+ <item Type="qt3Header" >qslider.h</item>
+ <item Type="qt3Header" >qsocket.h</item>
+ <item Type="qt3Header" >qsocketdevice.h</item>
+ <item Type="qt3Header" >qsocketnotifier.h</item>
+ <item Type="qt3Header" >qsocknot.h</item>
+ <item Type="qt3Header" >qsortedlist.h</item>
+ <item Type="qt3Header" >qsound.h</item>
+ <item Type="qt3Header" >qsoundqss_qws.h</item>
+ <item Type="qt3Header" >qspinbox.h</item>
+ <item Type="qt3Header" >qsplashscreen.h</item>
+ <item Type="qt3Header" >qsplitter.h</item>
+ <item Type="qt3Header" >qsql.h</item>
+ <item Type="qt3Header" >qsqlcursor.h</item>
+ <item Type="qt3Header" >qsqldatabase.h</item>
+ <item Type="qt3Header" >qsqldriver.h</item>
+ <item Type="qt3Header" >qsqldriverplugin.h</item>
+ <item Type="qt3Header" >qsqleditorfactory.h</item>
+ <item Type="qt3Header" >qsqlerror.h</item>
+ <item Type="qt3Header" >qsqlfield.h</item>
+ <item Type="qt3Header" >qsqlform.h</item>
+ <item Type="qt3Header" >qsqlindex.h</item>
+ <item Type="qt3Header" >qsqlpropertymap.h</item>
+ <item Type="qt3Header" >qsqlquery.h</item>
+ <item Type="qt3Header" >qsqlrecord.h</item>
+ <item Type="qt3Header" >qsqlresult.h</item>
+ <item Type="qt3Header" >qsqlselectcursor.h</item>
+ <item Type="qt3Header" >qstack.h</item>
+ <item Type="qt3Header" >qstatusbar.h</item>
+ <item Type="qt3Header" >qstring.h</item>
+ <item Type="qt3Header" >qstringlist.h</item>
+ <item Type="qt3Header" >qstrlist.h</item>
+ <item Type="qt3Header" >qstrvec.h</item>
+ <item Type="qt3Header" >qstyle.h</item>
+ <item Type="qt3Header" >qstylefactory.h</item>
+ <item Type="qt3Header" >qstyleplugin.h</item>
+ <item Type="qt3Header" >qstylesheet.h</item>
+ <item Type="qt3Header" >qsyntaxhighlighter.h</item>
+ <item Type="qt3Header" >qt.h</item>
+ <item Type="qt3Header" >qt_mac.h</item>
+ <item Type="qt3Header" >qt_mac9.h</item>
+ <item Type="qt3Header" >qt_windows.h</item>
+ <item Type="qt3Header" >qtabbar.h</item>
+ <item Type="qt3Header" >qtabdialog.h</item>
+ <item Type="qt3Header" >qtabdlg.h</item>
+ <item Type="qt3Header" >qtable.h</item>
+ <item Type="qt3Header" >qtabwidget.h</item>
+ <item Type="qt3Header" >qtextbrowser.h</item>
+ <item Type="qt3Header" >qtextcodec.h</item>
+ <item Type="qt3Header" >qtextcodecfactory.h</item>
+ <item Type="qt3Header" >qtextcodecplugin.h</item>
+ <item Type="qt3Header" >qtextedit.h</item>
+ <item Type="qt3Header" >qtextstream.h</item>
+ <item Type="qt3Header" >qtextview.h</item>
+ <item Type="qt3Header" >qthread.h</item>
+ <item Type="qt3Header" >qthreadstorage.h</item>
+ <item Type="qt3Header" >qtimer.h</item>
+ <item Type="qt3Header" >qtl.h</item>
+ <item Type="qt3Header" >qtoolbar.h</item>
+ <item Type="qt3Header" >qtoolbox.h</item>
+ <item Type="qt3Header" >qtoolbutton.h</item>
+ <item Type="qt3Header" >qtooltip.h</item>
+ <item Type="qt3Header" >qtranslator.h</item>
+ <item Type="qt3Header" >qtsciicodec.h</item>
+ <item Type="qt3Header" >qtstream.h</item>
+ <item Type="qt3Header" >qurl.h</item>
+ <item Type="qt3Header" >qurlinfo.h</item>
+ <item Type="qt3Header" >qurloperator.h</item>
+ <item Type="qt3Header" >qutfcodec.h</item>
+ <item Type="qt3Header" >quuid.h</item>
+ <item Type="qt3Header" >qvalidator.h</item>
+ <item Type="qt3Header" >qvaluelist.h</item>
+ <item Type="qt3Header" >qvaluestack.h</item>
+ <item Type="qt3Header" >qvaluevector.h</item>
+ <item Type="qt3Header" >qvariant.h</item>
+ <item Type="qt3Header" >qvbox.h</item>
+ <item Type="qt3Header" >qvbuttongroup.h</item>
+ <item Type="qt3Header" >qvector.h</item>
+ <item Type="qt3Header" >qvfbhdr.h</item>
+ <item Type="qt3Header" >qvgroupbox.h</item>
+ <item Type="qt3Header" >qwaitcondition.h</item>
+ <item Type="qt3Header" >qwhatsthis.h</item>
+ <item Type="qt3Header" >qwidcoll.h</item>
+ <item Type="qt3Header" >qwidget.h</item>
+ <item Type="qt3Header" >qwidgetfactory.h</item>
+ <item Type="qt3Header" >qwidgetintdict.h</item>
+ <item Type="qt3Header" >qwidgetlist.h</item>
+ <item Type="qt3Header" >qwidgetplugin.h</item>
+ <item Type="qt3Header" >qwidgetstack.h</item>
+ <item Type="qt3Header" >qwindefs.h</item>
+ <item Type="qt3Header" >qwindow.h</item>
+ <item Type="qt3Header" >qwindowdefs.h</item>
+ <item Type="qt3Header" >qwindowdefs_win.h</item>
+ <item Type="qt3Header" >qwindowsstyle.h</item>
+ <item Type="qt3Header" >qwindowsxpstyle.h</item>
+ <item Type="qt3Header" >qwindowsystem_qws.h</item>
+ <item Type="qt3Header" >qwinexport.h</item>
+ <item Type="qt3Header" >qwinfunctions_wce.h</item>
+ <item Type="qt3Header" >qwizard.h</item>
+ <item Type="qt3Header" >qwmatrix.h</item>
+ <item Type="qt3Header" >qworkspace.h</item>
+ <item Type="qt3Header" >qwsbeosdecoration_qws.h</item>
+ <item Type="qt3Header" >qwscommand_qws.h</item>
+ <item Type="qt3Header" >qwscursor_qws.h</item>
+ <item Type="qt3Header" >qwsdecoration_qws.h</item>
+ <item Type="qt3Header" >qwsdefaultdecoration_qws.h</item>
+ <item Type="qt3Header" >qwsdisplay_qws.h</item>
+ <item Type="qt3Header" >qwsevent_qws.h</item>
+ <item Type="qt3Header" >qwsgfx_qnx6.h</item>
+ <item Type="qt3Header" >qwshydrodecoration_qws.h</item>
+ <item Type="qt3Header" >qwskde2decoration_qws.h</item>
+ <item Type="qt3Header" >qwskdedecoration_qws.h</item>
+ <item Type="qt3Header" >qwskeyboard_qnx4.h</item>
+ <item Type="qt3Header" >qwsmanager_qws.h</item>
+ <item Type="qt3Header" >qwsmouse_qnx4.h</item>
+ <item Type="qt3Header" >qwsproperty_qws.h</item>
+ <item Type="qt3Header" >qwsregionmanager_qws.h</item>
+ <item Type="qt3Header" >qwssocket_qws.h</item>
+ <item Type="qt3Header" >qwsutils_qws.h</item>
+ <item Type="qt3Header" >qwswindowsdecoration_qws.h</item>
+ <item Type="qt3Header" >qxml.h</item>
+ <item Type="qt3Header" >qxt.h</item>
+ <item Type="qt3Header" >qxtwidget.h</item>
+ <item Type="qt4Header" >Q3Accel</item>
+ <item Type="qt4Header" >Q3Action</item>
+ <item Type="qt4Header" >Q3ActionGroup</item>
+ <item Type="qt4Header" >Q3AsciiBucket</item>
+ <item Type="qt4Header" >Q3AsciiCache</item>
+ <item Type="qt4Header" >Q3AsciiCacheIterator</item>
+ <item Type="qt4Header" >Q3AsciiDict</item>
+ <item Type="qt4Header" >Q3AsciiDictIterator</item>
+ <item Type="qt4Header" >Q3BaseBucket</item>
+ <item Type="qt4Header" >Q3BoxLayout</item>
+ <item Type="qt4Header" >Q3Button</item>
+ <item Type="qt4Header" >Q3ButtonGroup</item>
+ <item Type="qt4Header" >Q3CString</item>
+ <item Type="qt4Header" >Q3Cache</item>
+ <item Type="qt4Header" >Q3CacheIterator</item>
+ <item Type="qt4Header" >Q3Canvas</item>
+ <item Type="qt4Header" >Q3CanvasEllipse</item>
+ <item Type="qt4Header" >Q3CanvasItem</item>
+ <item Type="qt4Header" >Q3CanvasItemList</item>
+ <item Type="qt4Header" >Q3CanvasLine</item>
+ <item Type="qt4Header" >Q3CanvasPixmap</item>
+ <item Type="qt4Header" >Q3CanvasPixmapArray</item>
+ <item Type="qt4Header" >Q3CanvasPolygon</item>
+ <item Type="qt4Header" >Q3CanvasPolygonalItem</item>
+ <item Type="qt4Header" >Q3CanvasRectangle</item>
+ <item Type="qt4Header" >Q3CanvasSpline</item>
+ <item Type="qt4Header" >Q3CanvasSprite</item>
+ <item Type="qt4Header" >Q3CanvasText</item>
+ <item Type="qt4Header" >Q3CanvasView</item>
+ <item Type="qt4Header" >Q3CheckListItem</item>
+ <item Type="qt4Header" >Q3CheckTableItem</item>
+ <item Type="qt4Header" >Q3CleanupHandler</item>
+ <item Type="qt4Header" >Q3ColorDrag</item>
+ <item Type="qt4Header" >Q3ComboBox</item>
+ <item Type="qt4Header" >Q3ComboTableItem</item>
+ <item Type="qt4Header" >Q3DataBrowser</item>
+ <item Type="qt4Header" >Q3DataTable</item>
+ <item Type="qt4Header" >Q3DataView</item>
+ <item Type="qt4Header" >Q3DateEdit</item>
+ <item Type="qt4Header" >Q3DateTimeEdit</item>
+ <item Type="qt4Header" >Q3DateTimeEditBase</item>
+ <item Type="qt4Header" >Q3DeepCopy</item>
+ <item Type="qt4Header" >Q3Dict</item>
+ <item Type="qt4Header" >Q3DictIterator</item>
+ <item Type="qt4Header" >Q3Dns</item>
+ <item Type="qt4Header" >Q3DnsSocket</item>
+ <item Type="qt4Header" >Q3DockArea</item>
+ <item Type="qt4Header" >Q3DockAreaLayout</item>
+ <item Type="qt4Header" >Q3DockWindow</item>
+ <item Type="qt4Header" >Q3DragObject</item>
+ <item Type="qt4Header" >Q3DropSite</item>
+ <item Type="qt4Header" >Q3EditorFactory</item>
+ <item Type="qt4Header" >Q3FileDialog</item>
+ <item Type="qt4Header" >Q3FileIconProvider</item>
+ <item Type="qt4Header" >Q3FilePreview</item>
+ <item Type="qt4Header" >Q3Frame</item>
+ <item Type="qt4Header" >Q3Ftp</item>
+ <item Type="qt4Header" >Q3GArray</item>
+ <item Type="qt4Header" >Q3GCache</item>
+ <item Type="qt4Header" >Q3GCacheIterator</item>
+ <item Type="qt4Header" >Q3GDict</item>
+ <item Type="qt4Header" >Q3GDictIterator</item>
+ <item Type="qt4Header" >Q3GList</item>
+ <item Type="qt4Header" >Q3GListIterator</item>
+ <item Type="qt4Header" >Q3GListStdIterator</item>
+ <item Type="qt4Header" >Q3GVector</item>
+ <item Type="qt4Header" >Q3Grid</item>
+ <item Type="qt4Header" >Q3GridLayout</item>
+ <item Type="qt4Header" >Q3GridView</item>
+ <item Type="qt4Header" >Q3GroupBox</item>
+ <item Type="qt4Header" >Q3HBox</item>
+ <item Type="qt4Header" >Q3HBoxLayout</item>
+ <item Type="qt4Header" >Q3HButtonGroup</item>
+ <item Type="qt4Header" >Q3HGroupBox</item>
+ <item Type="qt4Header" >Q3Header</item>
+ <item Type="qt4Header" >Q3Http</item>
+ <item Type="qt4Header" >Q3HttpHeader</item>
+ <item Type="qt4Header" >Q3HttpRequestHeader</item>
+ <item Type="qt4Header" >Q3HttpResponseHeader</item>
+ <item Type="qt4Header" >Q3IconDrag</item>
+ <item Type="qt4Header" >Q3IconDragItem</item>
+ <item Type="qt4Header" >Q3IconView</item>
+ <item Type="qt4Header" >Q3IconViewItem</item>
+ <item Type="qt4Header" >Q3ImageDrag</item>
+ <item Type="qt4Header" >Q3IntBucket</item>
+ <item Type="qt4Header" >Q3IntCache</item>
+ <item Type="qt4Header" >Q3IntCacheIterator</item>
+ <item Type="qt4Header" >Q3IntDict</item>
+ <item Type="qt4Header" >Q3IntDictIterator</item>
+ <item Type="qt4Header" >Q3LNode</item>
+ <item Type="qt4Header" >Q3ListBox</item>
+ <item Type="qt4Header" >Q3ListBoxItem</item>
+ <item Type="qt4Header" >Q3ListBoxPixmap</item>
+ <item Type="qt4Header" >Q3ListBoxText</item>
+ <item Type="qt4Header" >Q3ListView</item>
+ <item Type="qt4Header" >Q3ListViewItem</item>
+ <item Type="qt4Header" >Q3ListViewItemIterator</item>
+ <item Type="qt4Header" >Q3LocalFs</item>
+ <item Type="qt4Header" >Q3MainWindow</item>
+ <item Type="qt4Header" >Q3MemArray</item>
+ <item Type="qt4Header" >Q3MimeSourceFactory</item>
+ <item Type="qt4Header" >Q3MultiLineEdit</item>
+ <item Type="qt4Header" >Q3NetworkOperation</item>
+ <item Type="qt4Header" >Q3NetworkProtocol</item>
+ <item Type="qt4Header" >Q3NetworkProtocolDict</item>
+ <item Type="qt4Header" >Q3NetworkProtocolFactory</item>
+ <item Type="qt4Header" >Q3NetworkProtocolFactoryBase</item>
+ <item Type="qt4Header" >Q3ObjectDictionary</item>
+ <item Type="qt4Header" >Q3PaintDeviceMetrics</item>
+ <item Type="qt4Header" >Q3Painter</item>
+ <item Type="qt4Header" >Q3Picture</item>
+ <item Type="qt4Header" >Q3PointArray</item>
+ <item Type="qt4Header" >Q3PolygonScanner</item>
+ <item Type="qt4Header" >Q3PopupMenu</item>
+ <item Type="qt4Header" >Q3Process</item>
+ <item Type="qt4Header" >Q3ProgressBar</item>
+ <item Type="qt4Header" >Q3ProgressDialog</item>
+ <item Type="qt4Header" >Q3PtrBucket</item>
+ <item Type="qt4Header" >Q3PtrCollection</item>
+ <item Type="qt4Header" >Q3PtrDict</item>
+ <item Type="qt4Header" >Q3PtrDictIterator</item>
+ <item Type="qt4Header" >Q3PtrList</item>
+ <item Type="qt4Header" >Q3PtrListIterator</item>
+ <item Type="qt4Header" >Q3PtrListStdIterator</item>
+ <item Type="qt4Header" >Q3PtrQueue</item>
+ <item Type="qt4Header" >Q3PtrStack</item>
+ <item Type="qt4Header" >Q3PtrVector</item>
+ <item Type="qt4Header" >Q3RangeControl</item>
+ <item Type="qt4Header" >Q3ScrollView</item>
+ <item Type="qt4Header" >Q3Semaphore</item>
+ <item Type="qt4Header" >Q3ServerSocket</item>
+ <item Type="qt4Header" >Q3Shared</item>
+ <item Type="qt4Header" >Q3Signal</item>
+ <item Type="qt4Header" >Q3SimpleRichText</item>
+ <item Type="qt4Header" >Q3SingleCleanupHandler</item>
+ <item Type="qt4Header" >Q3Socket</item>
+ <item Type="qt4Header" >Q3SocketDevice</item>
+ <item Type="qt4Header" >Q3SortedList</item>
+ <item Type="qt4Header" >Q3SpinWidget</item>
+ <item Type="qt4Header" >Q3SqlCursor</item>
+ <item Type="qt4Header" >Q3SqlEditorFactory</item>
+ <item Type="qt4Header" >Q3SqlFieldInfo</item>
+ <item Type="qt4Header" >Q3SqlFieldInfoList</item>
+ <item Type="qt4Header" >Q3SqlForm</item>
+ <item Type="qt4Header" >Q3SqlPropertyMap</item>
+ <item Type="qt4Header" >Q3SqlRecordInfo</item>
+ <item Type="qt4Header" >Q3SqlSelectCursor</item>
+ <item Type="qt4Header" >Q3StoredDrag</item>
+ <item Type="qt4Header" >Q3StrIList</item>
+ <item Type="qt4Header" >Q3StrIVec</item>
+ <item Type="qt4Header" >Q3StrList</item>
+ <item Type="qt4Header" >Q3StrListIterator</item>
+ <item Type="qt4Header" >Q3StrVec</item>
+ <item Type="qt4Header" >Q3StringBucket</item>
+ <item Type="qt4Header" >Q3StyleSheet</item>
+ <item Type="qt4Header" >Q3StyleSheetItem</item>
+ <item Type="qt4Header" >Q3SyntaxHighlighter</item>
+ <item Type="qt4Header" >Q3TSFUNC</item>
+ <item Type="qt4Header" >Q3TabDialog</item>
+ <item Type="qt4Header" >Q3Table</item>
+ <item Type="qt4Header" >Q3TableItem</item>
+ <item Type="qt4Header" >Q3TableSelection</item>
+ <item Type="qt4Header" >Q3TextBrowser</item>
+ <item Type="qt4Header" >Q3TextDrag</item>
+ <item Type="qt4Header" >Q3TextEdit</item>
+ <item Type="qt4Header" >Q3TextEditOptimPrivate</item>
+ <item Type="qt4Header" >Q3TextStream</item>
+ <item Type="qt4Header" >Q3TextView</item>
+ <item Type="qt4Header" >Q3TimeEdit</item>
+ <item Type="qt4Header" >Q3ToolBar</item>
+ <item Type="qt4Header" >Q3UriDrag</item>
+ <item Type="qt4Header" >Q3Url</item>
+ <item Type="qt4Header" >Q3UrlOperator</item>
+ <item Type="qt4Header" >Q3VBox</item>
+ <item Type="qt4Header" >Q3VBoxLayout</item>
+ <item Type="qt4Header" >Q3VButtonGroup</item>
+ <item Type="qt4Header" >Q3VGroupBox</item>
+ <item Type="qt4Header" >Q3ValueList</item>
+ <item Type="qt4Header" >Q3ValueListConstIterator</item>
+ <item Type="qt4Header" >Q3ValueListIterator</item>
+ <item Type="qt4Header" >Q3ValueStack</item>
+ <item Type="qt4Header" >Q3ValueVector</item>
+ <item Type="qt4Header" >Q3WhatsThis</item>
+ <item Type="qt4Header" >Q3WidgetStack</item>
+ <item Type="qt4Header" >Q3Wizard</item>
+ <item Type="qt4Header" >QAbstractButton</item>
+ <item Type="qt4Header" >QAbstractEventDispatcher</item>
+ <item Type="qt4Header" >QAbstractExtensionFactory</item>
+ <item Type="qt4Header" >QAbstractExtensionManager</item>
+ <item Type="qt4Header" >QAbstractFileEngine</item>
+ <item Type="qt4Header" >QAbstractFileEngineHandler</item>
+ <item Type="qt4Header" >QAbstractFormBuilder</item>
+ <item Type="qt4Header" >QAbstractGraphicsPathItem</item>
+ <item Type="qt4Header" >QAbstractGraphicsShapeItem</item>
+ <item Type="qt4Header" >QAbstractItemDelegate</item>
+ <item Type="qt4Header" >QAbstractItemModel</item>
+ <item Type="qt4Header" >QAbstractItemView</item>
+ <item Type="qt4Header" >QAbstractListModel</item>
+ <item Type="qt4Header" >QAbstractPageSetupDialog</item>
+ <item Type="qt4Header" >QAbstractPrintDialog</item>
+ <item Type="qt4Header" >QAbstractProxyModel</item>
+ <item Type="qt4Header" >QAbstractScrollArea</item>
+ <item Type="qt4Header" >QAbstractSlider</item>
+ <item Type="qt4Header" >QAbstractSocket</item>
+ <item Type="qt4Header" >QAbstractSpinBox</item>
+ <item Type="qt4Header" >QAbstractTableModel</item>
+ <item Type="qt4Header" >QAbstractTextDocumentLayout</item>
+ <item Type="qt4Header" >QAbstractUndoItem</item>
+ <item Type="qt4Header" >QAccessible</item>
+ <item Type="qt4Header" >QAccessibleApplication</item>
+ <item Type="qt4Header" >QAccessibleBridge</item>
+ <item Type="qt4Header" >QAccessibleBridgeFactoryInterface</item>
+ <item Type="qt4Header" >QAccessibleBridgePlugin</item>
+ <item Type="qt4Header" >QAccessibleEvent</item>
+ <item Type="qt4Header" >QAccessibleFactoryInterface</item>
+ <item Type="qt4Header" >QAccessibleInterface</item>
+ <item Type="qt4Header" >QAccessibleInterfaceEx</item>
+ <item Type="qt4Header" >QAccessibleObject</item>
+ <item Type="qt4Header" >QAccessibleObjectEx</item>
+ <item Type="qt4Header" >QAccessiblePlugin</item>
+ <item Type="qt4Header" >QAccessibleWidget</item>
+ <item Type="qt4Header" >QAccessibleWidgetEx</item>
+ <item Type="qt4Header" >QAction</item>
+ <item Type="qt4Header" >QActionEvent</item>
+ <item Type="qt4Header" >QActionGroup</item>
+ <item Type="qt4Header" >QApplication</item>
+ <item Type="qt4Header" >QArgument</item>
+ <item Type="qt4Header" >QAssistantClient</item>
+ <item Type="qt4Header" >QAtomic</item>
+ <item Type="qt4Header" >QAtomicPointer</item>
+ <item Type="qt4Header" >QAxAggregated</item>
+ <item Type="qt4Header" >QAxBase</item>
+ <item Type="qt4Header" >QAxBindable</item>
+ <item Type="qt4Header" >QAxClass</item>
+ <item Type="qt4Header" >QAxFactory</item>
+ <item Type="qt4Header" >QAxObject</item>
+ <item Type="qt4Header" >QAxScript</item>
+ <item Type="qt4Header" >QAxScriptEngine</item>
+ <item Type="qt4Header" >QAxScriptManager</item>
+ <item Type="qt4Header" >QAxSelect</item>
+ <item Type="qt4Header" >QAxWidget</item>
+ <item Type="qt4Header" >QBasicAtomic</item>
+ <item Type="qt4Header" >QBasicAtomicPointer</item>
+ <item Type="qt4Header" >QBasicTimer</item>
+ <item Type="qt4Header" >QBitArray</item>
+ <item Type="qt4Header" >QBitRef</item>
+ <item Type="qt4Header" >QBitmap</item>
+ <item Type="qt4Header" >QBool</item>
+ <item Type="qt4Header" >QBoxLayout</item>
+ <item Type="qt4Header" >QBrush</item>
+ <item Type="qt4Header" >QBrushData</item>
+ <item Type="qt4Header" >QBuffer</item>
+ <item Type="qt4Header" >QButtonGroup</item>
+ <item Type="qt4Header" >QByteArray</item>
+ <item Type="qt4Header" >QByteArrayMatcher</item>
+ <item Type="qt4Header" >QByteRef</item>
+ <item Type="qt4Header" >QCDEStyle</item>
+ <item Type="qt4Header" >QCOORD</item>
+ <item Type="qt4Header" >QCache</item>
+ <item Type="qt4Header" >QCalendarWidget</item>
+ <item Type="qt4Header" >QChar</item>
+ <item Type="qt4Header" >QCharRef</item>
+ <item Type="qt4Header" >QCheckBox</item>
+ <item Type="qt4Header" >QChildEvent</item>
+ <item Type="qt4Header" >QCleanLooksStyle</item>
+ <item Type="qt4Header" >QCleanlooksStyle</item>
+ <item Type="qt4Header" >QClipboard</item>
+ <item Type="qt4Header" >QClipboardEvent</item>
+ <item Type="qt4Header" >QCloseEvent</item>
+ <item Type="qt4Header" >QColor</item>
+ <item Type="qt4Header" >QColorDialog</item>
+ <item Type="qt4Header" >QColorGroup</item>
+ <item Type="qt4Header" >QColormap</item>
+ <item Type="qt4Header" >QComboBox</item>
+ <item Type="qt4Header" >QCommonStyle</item>
+ <item Type="qt4Header" >QCompleter</item>
+ <item Type="qt4Header" >QConicalGradient</item>
+ <item Type="qt4Header" >QConstString</item>
+ <item Type="qt4Header" >QContextMenuEvent</item>
+ <item Type="qt4Header" >QCopChannel</item>
+ <item Type="qt4Header" >QCoreApplication</item>
+ <item Type="qt4Header" >QCursor</item>
+ <item Type="qt4Header" >QCursorShape</item>
+ <item Type="qt4Header" >QCustomEvent</item>
+ <item Type="qt4Header" >QDB2Driver</item>
+ <item Type="qt4Header" >QDB2Result</item>
+ <item Type="qt4Header" >QDBusAbstractAdaptor</item>
+ <item Type="qt4Header" >QDBusAbstractInterface</item>
+ <item Type="qt4Header" >QDBusArgument</item>
+ <item Type="qt4Header" >QDBusConnection</item>
+ <item Type="qt4Header" >QDBusConnectionInterface</item>
+ <item Type="qt4Header" >QDBusError</item>
+ <item Type="qt4Header" >QDBusInterface</item>
+ <item Type="qt4Header" >QDBusInterfacePtr</item>
+ <item Type="qt4Header" >QDBusMessage</item>
+ <item Type="qt4Header" >QDBusMetaType</item>
+ <item Type="qt4Header" >QDBusObjectPath</item>
+ <item Type="qt4Header" >QDBusReply</item>
+ <item Type="qt4Header" >QDBusServer</item>
+ <item Type="qt4Header" >QDBusSignature</item>
+ <item Type="qt4Header" >QDBusVariant</item>
+ <item Type="qt4Header" >QDataStream</item>
+ <item Type="qt4Header" >QDataWidgetMapper</item>
+ <item Type="qt4Header" >QDate</item>
+ <item Type="qt4Header" >QDateEdit</item>
+ <item Type="qt4Header" >QDateTime</item>
+ <item Type="qt4Header" >QDateTimeEdit</item>
+ <item Type="qt4Header" >QDebug</item>
+ <item Type="qt4Header" >QDecoration</item>
+ <item Type="qt4Header" >QDecorationAction</item>
+ <item Type="qt4Header" >QDecorationDefault</item>
+ <item Type="qt4Header" >QDecorationFactory</item>
+ <item Type="qt4Header" >QDecorationFactoryInterface</item>
+ <item Type="qt4Header" >QDecorationPlugin</item>
+ <item Type="qt4Header" >QDecorationStyled</item>
+ <item Type="qt4Header" >QDecorationWindows</item>
+ <item Type="qt4Header" >QDesignerActionEditorInterface</item>
+ <item Type="qt4Header" >QDesignerBrushManagerInterface</item>
+ <item Type="qt4Header" >QDesignerComponents</item>
+ <item Type="qt4Header" >QDesignerContainerExtension</item>
+ <item Type="qt4Header" >QDesignerCustomWidgetCollectionInterface</item>
+ <item Type="qt4Header" >QDesignerCustomWidgetInterface</item>
+ <item Type="qt4Header" >QDesignerDnDItemInterface</item>
+ <item Type="qt4Header" >QDesignerExportWidget</item>
+ <item Type="qt4Header" >QDesignerExtraInfoExtension</item>
+ <item Type="qt4Header" >QDesignerFormEditorInterface</item>
+ <item Type="qt4Header" >QDesignerFormEditorPluginInterface</item>
+ <item Type="qt4Header" >QDesignerFormWindowCursorInterface</item>
+ <item Type="qt4Header" >QDesignerFormWindowInterface</item>
+ <item Type="qt4Header" >QDesignerFormWindowManagerInterface</item>
+ <item Type="qt4Header" >QDesignerFormWindowToolInterface</item>
+ <item Type="qt4Header" >QDesignerIconCacheInterface</item>
+ <item Type="qt4Header" >QDesignerLayoutDecorationExtension</item>
+ <item Type="qt4Header" >QDesignerMemberSheetExtension</item>
+ <item Type="qt4Header" >QDesignerMetaDataBaseInterface</item>
+ <item Type="qt4Header" >QDesignerMetaDataBaseItemInterface</item>
+ <item Type="qt4Header" >QDesignerObjectInspectorInterface</item>
+ <item Type="qt4Header" >QDesignerPropertyEditorInterface</item>
+ <item Type="qt4Header" >QDesignerPropertySheetExtension</item>
+ <item Type="qt4Header" >QDesignerTaskMenuExtension</item>
+ <item Type="qt4Header" >QDesignerWidgetBoxInterface</item>
+ <item Type="qt4Header" >QDesignerWidgetDataBaseInterface</item>
+ <item Type="qt4Header" >QDesignerWidgetDataBaseItemInterface</item>
+ <item Type="qt4Header" >QDesignerWidgetFactoryInterface</item>
+ <item Type="qt4Header" >QDesktopServices</item>
+ <item Type="qt4Header" >QDesktopWidget</item>
+ <item Type="qt4Header" >QDial</item>
+ <item Type="qt4Header" >QDialog</item>
+ <item Type="qt4Header" >QDialogButtonBox</item>
+ <item Type="qt4Header" >QDir</item>
+ <item Type="qt4Header" >QDirModel</item>
+ <item Type="qt4Header" >QDirectPainter</item>
+ <item Type="qt4Header" >QDockWidget</item>
+ <item Type="qt4Header" >QDomAttr</item>
+ <item Type="qt4Header" >QDomCDATASection</item>
+ <item Type="qt4Header" >QDomCharacterData</item>
+ <item Type="qt4Header" >QDomComment</item>
+ <item Type="qt4Header" >QDomDocument</item>
+ <item Type="qt4Header" >QDomDocumentFragment</item>
+ <item Type="qt4Header" >QDomDocumentType</item>
+ <item Type="qt4Header" >QDomElement</item>
+ <item Type="qt4Header" >QDomEntity</item>
+ <item Type="qt4Header" >QDomEntityReference</item>
+ <item Type="qt4Header" >QDomImplementation</item>
+ <item Type="qt4Header" >QDomNamedNodeMap</item>
+ <item Type="qt4Header" >QDomNode</item>
+ <item Type="qt4Header" >QDomNodeList</item>
+ <item Type="qt4Header" >QDomNotation</item>
+ <item Type="qt4Header" >QDomProcessingInstruction</item>
+ <item Type="qt4Header" >QDomText</item>
+ <item Type="qt4Header" >QDoubleSpinBox</item>
+ <item Type="qt4Header" >QDoubleValidator</item>
+ <item Type="qt4Header" >QDrag</item>
+ <item Type="qt4Header" >QDragEnterEvent</item>
+ <item Type="qt4Header" >QDragLeaveEvent</item>
+ <item Type="qt4Header" >QDragMoveEvent</item>
+ <item Type="qt4Header" >QDragResponseEvent</item>
+ <item Type="qt4Header" >QDropEvent</item>
+ <item Type="qt4Header" >QDynamicPropertyChangeEvent</item>
+ <item Type="qt4Header" >QErrorMessage</item>
+ <item Type="qt4Header" >QEvent</item>
+ <item Type="qt4Header" >QEventLoop</item>
+ <item Type="qt4Header" >QEventSizeOfChecker</item>
+ <item Type="qt4Header" >QExtensionFactory</item>
+ <item Type="qt4Header" >QExtensionManager</item>
+ <item Type="qt4Header" >QFSFileEngine</item>
+ <item Type="qt4Header" >QFactoryInterface</item>
+ <item Type="qt4Header" >QFile</item>
+ <item Type="qt4Header" >QFileDialog</item>
+ <item Type="qt4Header" >QFileIconProvider</item>
+ <item Type="qt4Header" >QFileInfo</item>
+ <item Type="qt4Header" >QFileInfoList</item>
+ <item Type="qt4Header" >QFileInfoListIterator</item>
+ <item Type="qt4Header" >QFileOpenEvent</item>
+ <item Type="qt4Header" >QFileSystemWatcher</item>
+ <item Type="qt4Header" >QFlag</item>
+ <item Type="qt4Header" >QFlags</item>
+ <item Type="qt4Header" >QFocusEvent</item>
+ <item Type="qt4Header" >QFocusFrame</item>
+ <item Type="qt4Header" >QFont</item>
+ <item Type="qt4Header" >QFontComboBox</item>
+ <item Type="qt4Header" >QFontDatabase</item>
+ <item Type="qt4Header" >QFontDialog</item>
+ <item Type="qt4Header" >QFontInfo</item>
+ <item Type="qt4Header" >QFontMetrics</item>
+ <item Type="qt4Header" >QFontMetricsF</item>
+ <item Type="qt4Header" >QForeachContainer</item>
+ <item Type="qt4Header" >QForeachContainerBase</item>
+ <item Type="qt4Header" >QFormBuilder</item>
+ <item Type="qt4Header" >QFrame</item>
+ <item Type="qt4Header" >QFtp</item>
+ <item Type="qt4Header" >QGLColormap</item>
+ <item Type="qt4Header" >QGLContext</item>
+ <item Type="qt4Header" >QGLFormat</item>
+ <item Type="qt4Header" >QGLFramebufferObject</item>
+ <item Type="qt4Header" >QGLPixelBuffer</item>
+ <item Type="qt4Header" >QGLWidget</item>
+ <item Type="qt4Header" >QGenericArgument</item>
+ <item Type="qt4Header" >QGenericReturnArgument</item>
+ <item Type="qt4Header" >QGlobalStatic</item>
+ <item Type="qt4Header" >QGradient</item>
+ <item Type="qt4Header" >QGradientStop</item>
+ <item Type="qt4Header" >QGradientStops</item>
+ <item Type="qt4Header" >QGraphicsEllipseItem</item>
+ <item Type="qt4Header" >QGraphicsItem</item>
+ <item Type="qt4Header" >QGraphicsItemAnimation</item>
+ <item Type="qt4Header" >QGraphicsItemGroup</item>
+ <item Type="qt4Header" >QGraphicsLineItem</item>
+ <item Type="qt4Header" >QGraphicsPathItem</item>
+ <item Type="qt4Header" >QGraphicsPixmapItem</item>
+ <item Type="qt4Header" >QGraphicsPolygonItem</item>
+ <item Type="qt4Header" >QGraphicsRectItem</item>
+ <item Type="qt4Header" >QGraphicsScene</item>
+ <item Type="qt4Header" >QGraphicsSceneContextMenuEvent</item>
+ <item Type="qt4Header" >QGraphicsSceneDragDropEvent</item>
+ <item Type="qt4Header" >QGraphicsSceneEvent</item>
+ <item Type="qt4Header" >QGraphicsSceneHelpEvent</item>
+ <item Type="qt4Header" >QGraphicsSceneHoverEvent</item>
+ <item Type="qt4Header" >QGraphicsSceneMouseEvent</item>
+ <item Type="qt4Header" >QGraphicsSceneWheelEvent</item>
+ <item Type="qt4Header" >QGraphicsSimpleTextItem</item>
+ <item Type="qt4Header" >QGraphicsSvgItem</item>
+ <item Type="qt4Header" >QGraphicsTextItem</item>
+ <item Type="qt4Header" >QGraphicsView</item>
+ <item Type="qt4Header" >QGridLayout</item>
+ <item Type="qt4Header" >QGroupBox</item>
+ <item Type="qt4Header" >QHBoxLayout</item>
+ <item Type="qt4Header" >QHash</item>
+ <item Type="qt4Header" >QHashData</item>
+ <item Type="qt4Header" >QHashDummyNode</item>
+ <item Type="qt4Header" >QHashDummyValue</item>
+ <item Type="qt4Header" >QHashIterator</item>
+ <item Type="qt4Header" >QHashNode</item>
+ <item Type="qt4Header" >QHeaderView</item>
+ <item Type="qt4Header" >QHelpEvent</item>
+ <item Type="qt4Header" >QHideEvent</item>
+ <item Type="qt4Header" >QHostAddress</item>
+ <item Type="qt4Header" >QHostInfo</item>
+ <item Type="qt4Header" >QHoverEvent</item>
+ <item Type="qt4Header" >QHttp</item>
+ <item Type="qt4Header" >QHttpHeader</item>
+ <item Type="qt4Header" >QHttpRequestHeader</item>
+ <item Type="qt4Header" >QHttpResponseHeader</item>
+ <item Type="qt4Header" >QIBaseDriver</item>
+ <item Type="qt4Header" >QIBaseResult</item>
+ <item Type="qt4Header" >QIODevice</item>
+ <item Type="qt4Header" >QIPv6Address</item>
+ <item Type="qt4Header" >QIcon</item>
+ <item Type="qt4Header" >QIconDragEvent</item>
+ <item Type="qt4Header" >QIconEngine</item>
+ <item Type="qt4Header" >QIconEngineFactoryInterface</item>
+ <item Type="qt4Header" >QIconEnginePlugin</item>
+ <item Type="qt4Header" >QIconSet</item>
+ <item Type="qt4Header" >QImage</item>
+ <item Type="qt4Header" >QImageIOHandler</item>
+ <item Type="qt4Header" >QImageIOHandlerFactoryInterface</item>
+ <item Type="qt4Header" >QImageIOPlugin</item>
+ <item Type="qt4Header" >QImageReader</item>
+ <item Type="qt4Header" >QImageTextKeyLang</item>
+ <item Type="qt4Header" >QImageWriter</item>
+ <item Type="qt4Header" >QInputContext</item>
+ <item Type="qt4Header" >QInputContextFactory</item>
+ <item Type="qt4Header" >QInputContextFactoryInterface</item>
+ <item Type="qt4Header" >QInputContextPlugin</item>
+ <item Type="qt4Header" >QInputDialog</item>
+ <item Type="qt4Header" >QInputEvent</item>
+ <item Type="qt4Header" >QInputMethodEvent</item>
+ <item Type="qt4Header" >QIntForSize</item>
+ <item Type="qt4Header" >QIntForType</item>
+ <item Type="qt4Header" >QIntValidator</item>
+ <item Type="qt4Header" >QInternal</item>
+ <item Type="qt4Header" >QItemDelegate</item>
+ <item Type="qt4Header" >QItemEditorCreator</item>
+ <item Type="qt4Header" >QItemEditorCreatorBase</item>
+ <item Type="qt4Header" >QItemEditorFactory</item>
+ <item Type="qt4Header" >QItemSelection</item>
+ <item Type="qt4Header" >QItemSelectionModel</item>
+ <item Type="qt4Header" >QItemSelectionRange</item>
+ <item Type="qt4Header" >QKbdDriverFactory</item>
+ <item Type="qt4Header" >QKbdDriverPlugin</item>
+ <item Type="qt4Header" >QKeyEvent</item>
+ <item Type="qt4Header" >QKeySequence</item>
+ <item Type="qt4Header" >QLCDNumber</item>
+ <item Type="qt4Header" >QLabel</item>
+ <item Type="qt4Header" >QLatin1Char</item>
+ <item Type="qt4Header" >QLatin1String</item>
+ <item Type="qt4Header" >QLayout</item>
+ <item Type="qt4Header" >QLayoutItem</item>
+ <item Type="qt4Header" >QLayoutIterator</item>
+ <item Type="qt4Header" >QLibrary</item>
+ <item Type="qt4Header" >QLibraryInfo</item>
+ <item Type="qt4Header" >QLine</item>
+ <item Type="qt4Header" >QLineEdit</item>
+ <item Type="qt4Header" >QLineF</item>
+ <item Type="qt4Header" >QLinearGradient</item>
+ <item Type="qt4Header" >QLinkedList</item>
+ <item Type="qt4Header" >QLinkedListData</item>
+ <item Type="qt4Header" >QLinkedListIterator</item>
+ <item Type="qt4Header" >QLinkedListNode</item>
+ <item Type="qt4Header" >QLinuxFbScreen</item>
+ <item Type="qt4Header" >QLinuxFb_Shared</item>
+ <item Type="qt4Header" >QList</item>
+ <item Type="qt4Header" >QListData</item>
+ <item Type="qt4Header" >QListIterator</item>
+ <item Type="qt4Header" >QListView</item>
+ <item Type="qt4Header" >QListWidget</item>
+ <item Type="qt4Header" >QListWidgetItem</item>
+ <item Type="qt4Header" >QLocale</item>
+ <item Type="qt4Header" >QMYSQLDriver</item>
+ <item Type="qt4Header" >QMYSQLResult</item>
+ <item Type="qt4Header" >QMacMime</item>
+ <item Type="qt4Header" >QMacPasteBoardMime</item>
+ <item Type="qt4Header" >QMacStyle</item>
+ <item Type="qt4Header" >QMainWindow</item>
+ <item Type="qt4Header" >QMap</item>
+ <item Type="qt4Header" >QMapData</item>
+ <item Type="qt4Header" >QMapIterator</item>
+ <item Type="qt4Header" >QMatrix</item>
+ <item Type="qt4Header" >QMenu</item>
+ <item Type="qt4Header" >QMenuBar</item>
+ <item Type="qt4Header" >QMenuItem</item>
+ <item Type="qt4Header" >QMenubarUpdatedEvent</item>
+ <item Type="qt4Header" >QMessageBox</item>
+ <item Type="qt4Header" >QMetaClassInfo</item>
+ <item Type="qt4Header" >QMetaEnum</item>
+ <item Type="qt4Header" >QMetaMethod</item>
+ <item Type="qt4Header" >QMetaObject</item>
+ <item Type="qt4Header" >QMetaProperty</item>
+ <item Type="qt4Header" >QMetaType</item>
+ <item Type="qt4Header" >QMetaTypeId</item>
+ <item Type="qt4Header" >QMetaTypeId2</item>
+ <item Type="qt4Header" >QMimeData</item>
+ <item Type="qt4Header" >QMimeSource</item>
+ <item Type="qt4Header" >QModelIndex</item>
+ <item Type="qt4Header" >QModelIndexList</item>
+ <item Type="qt4Header" >QMotifStyle</item>
+ <item Type="qt4Header" >QMouseDriverFactory</item>
+ <item Type="qt4Header" >QMouseDriverPlugin</item>
+ <item Type="qt4Header" >QMouseEvent</item>
+ <item Type="qt4Header" >QMoveEvent</item>
+ <item Type="qt4Header" >QMovie</item>
+ <item Type="qt4Header" >QMultiHash</item>
+ <item Type="qt4Header" >QMultiMap</item>
+ <item Type="qt4Header" >QMutableHashIterator</item>
+ <item Type="qt4Header" >QMutableLinkedListIterator</item>
+ <item Type="qt4Header" >QMutableListIterator</item>
+ <item Type="qt4Header" >QMutableMapIterator</item>
+ <item Type="qt4Header" >QMutableSetIterator</item>
+ <item Type="qt4Header" >QMutableStringListIterator</item>
+ <item Type="qt4Header" >QMutableVectorIterator</item>
+ <item Type="qt4Header" >QMutex</item>
+ <item Type="qt4Header" >QMutexLocker</item>
+ <item Type="qt4Header" >QNetworkAddressEntry</item>
+ <item Type="qt4Header" >QNetworkInterface</item>
+ <item Type="qt4Header" >QNetworkProxy</item>
+ <item Type="qt4Header" >QNoDebug</item>
+ <item Type="qt4Header" >QNoImplicitBoolCast</item>
+ <item Type="qt4Header" >QOCIDriver</item>
+ <item Type="qt4Header" >QOCIResult</item>
+ <item Type="qt4Header" >QODBCDriver</item>
+ <item Type="qt4Header" >QODBCResult</item>
+ <item Type="qt4Header" >QObject</item>
+ <item Type="qt4Header" >QObjectCleanupHandler</item>
+ <item Type="qt4Header" >QObjectData</item>
+ <item Type="qt4Header" >QObjectList</item>
+ <item Type="qt4Header" >QObjectUserData</item>
+ <item Type="qt4Header" >QPSQLDriver</item>
+ <item Type="qt4Header" >QPSQLResult</item>
+ <item Type="qt4Header" >QPageSetupDialog</item>
+ <item Type="qt4Header" >QPaintDevice</item>
+ <item Type="qt4Header" >QPaintEngine</item>
+ <item Type="qt4Header" >QPaintEngineState</item>
+ <item Type="qt4Header" >QPaintEvent</item>
+ <item Type="qt4Header" >QPainter</item>
+ <item Type="qt4Header" >QPainterPath</item>
+ <item Type="qt4Header" >QPainterPathPrivate</item>
+ <item Type="qt4Header" >QPainterPathStroker</item>
+ <item Type="qt4Header" >QPair</item>
+ <item Type="qt4Header" >QPalette</item>
+ <item Type="qt4Header" >QPen</item>
+ <item Type="qt4Header" >QPersistentModelIndex</item>
+ <item Type="qt4Header" >QPicture</item>
+ <item Type="qt4Header" >QPictureFormatInterface</item>
+ <item Type="qt4Header" >QPictureFormatPlugin</item>
+ <item Type="qt4Header" >QPictureIO</item>
+ <item Type="qt4Header" >QPixmap</item>
+ <item Type="qt4Header" >QPixmapCache</item>
+ <item Type="qt4Header" >QPlastiqueStyle</item>
+ <item Type="qt4Header" >QPluginLoader</item>
+ <item Type="qt4Header" >QPoint</item>
+ <item Type="qt4Header" >QPointF</item>
+ <item Type="qt4Header" >QPointer</item>
+ <item Type="qt4Header" >QPolygon</item>
+ <item Type="qt4Header" >QPolygonF</item>
+ <item Type="qt4Header" >QPoolEntry</item>
+ <item Type="qt4Header" >QPrintDialog</item>
+ <item Type="qt4Header" >QPrintEngine</item>
+ <item Type="qt4Header" >QPrinter</item>
+ <item Type="qt4Header" >QProcess</item>
+ <item Type="qt4Header" >QProgressBar</item>
+ <item Type="qt4Header" >QProgressDialog</item>
+ <item Type="qt4Header" >QProxyModel</item>
+ <item Type="qt4Header" >QPushButton</item>
+ <item Type="qt4Header" >QQueue</item>
+ <item Type="qt4Header" >QRadialGradient</item>
+ <item Type="qt4Header" >QRadioButton</item>
+ <item Type="qt4Header" >QReadLocker</item>
+ <item Type="qt4Header" >QReadWriteLock</item>
+ <item Type="qt4Header" >QRect</item>
+ <item Type="qt4Header" >QRectF</item>
+ <item Type="qt4Header" >QRegExp</item>
+ <item Type="qt4Header" >QRegExpValidator</item>
+ <item Type="qt4Header" >QRegion</item>
+ <item Type="qt4Header" >QResizeEvent</item>
+ <item Type="qt4Header" >QResource</item>
+ <item Type="qt4Header" >QReturnArgument</item>
+ <item Type="qt4Header" >QRgb</item>
+ <item Type="qt4Header" >QRubberBand</item>
+ <item Type="qt4Header" >QSQLite2Driver</item>
+ <item Type="qt4Header" >QSQLite2Result</item>
+ <item Type="qt4Header" >QSQLiteDriver</item>
+ <item Type="qt4Header" >QSQLiteResult</item>
+ <item Type="qt4Header" >QScreen</item>
+ <item Type="qt4Header" >QScreenCursor</item>
+ <item Type="qt4Header" >QScreenDriverFactory</item>
+ <item Type="qt4Header" >QScreenDriverFactoryInterface</item>
+ <item Type="qt4Header" >QScreenDriverPlugin</item>
+ <item Type="qt4Header" >QScrollArea</item>
+ <item Type="qt4Header" >QScrollBar</item>
+ <item Type="qt4Header" >QSemaphore</item>
+ <item Type="qt4Header" >QSessionManager</item>
+ <item Type="qt4Header" >QSet</item>
+ <item Type="qt4Header" >QSetIterator</item>
+ <item Type="qt4Header" >QSettings</item>
+ <item Type="qt4Header" >QSharedData</item>
+ <item Type="qt4Header" >QSharedDataPointer</item>
+ <item Type="qt4Header" >QShortcut</item>
+ <item Type="qt4Header" >QShortcutEvent</item>
+ <item Type="qt4Header" >QShowEvent</item>
+ <item Type="qt4Header" >QSignalMapper</item>
+ <item Type="qt4Header" >QSignalSpy</item>
+ <item Type="qt4Header" >QSize</item>
+ <item Type="qt4Header" >QSizeF</item>
+ <item Type="qt4Header" >QSizeGrip</item>
+ <item Type="qt4Header" >QSizePolicy</item>
+ <item Type="qt4Header" >QSlider</item>
+ <item Type="qt4Header" >QSocketNotifier</item>
+ <item Type="qt4Header" >QSortFilterProxyModel</item>
+ <item Type="qt4Header" >QSound</item>
+ <item Type="qt4Header" >QSpacerItem</item>
+ <item Type="qt4Header" >QSpinBox</item>
+ <item Type="qt4Header" >QSplashScreen</item>
+ <item Type="qt4Header" >QSplitter</item>
+ <item Type="qt4Header" >QSplitterHandle</item>
+ <item Type="qt4Header" >QSpontaneKeyEvent</item>
+ <item Type="qt4Header" >QSqlDatabase</item>
+ <item Type="qt4Header" >QSqlDriver</item>
+ <item Type="qt4Header" >QSqlDriverCreator</item>
+ <item Type="qt4Header" >QSqlDriverCreatorBase</item>
+ <item Type="qt4Header" >QSqlDriverFactoryInterface</item>
+ <item Type="qt4Header" >QSqlDriverPlugin</item>
+ <item Type="qt4Header" >QSqlError</item>
+ <item Type="qt4Header" >QSqlField</item>
+ <item Type="qt4Header" >QSqlIndex</item>
+ <item Type="qt4Header" >QSqlQuery</item>
+ <item Type="qt4Header" >QSqlQueryModel</item>
+ <item Type="qt4Header" >QSqlRecord</item>
+ <item Type="qt4Header" >QSqlRelation</item>
+ <item Type="qt4Header" >QSqlRelationalDelegate</item>
+ <item Type="qt4Header" >QSqlRelationalTableModel</item>
+ <item Type="qt4Header" >QSqlResult</item>
+ <item Type="qt4Header" >QSqlTableModel</item>
+ <item Type="qt4Header" >QStack</item>
+ <item Type="qt4Header" >QStackedLayout</item>
+ <item Type="qt4Header" >QStackedWidget</item>
+ <item Type="qt4Header" >QStandardItem</item>
+ <item Type="qt4Header" >QStandardItemEditorCreator</item>
+ <item Type="qt4Header" >QStandardItemModel</item>
+ <item Type="qt4Header" >QStatusBar</item>
+ <item Type="qt4Header" >QStatusTipEvent</item>
+ <item Type="qt4Header" >QStdWString</item>
+ <item Type="qt4Header" >QString</item>
+ <item Type="qt4Header" >QStringList</item>
+ <item Type="qt4Header" >QStringListIterator</item>
+ <item Type="qt4Header" >QStringListModel</item>
+ <item Type="qt4Header" >QStringMatcher</item>
+ <item Type="qt4Header" >QStyle</item>
+ <item Type="qt4Header" >QStyleFactory</item>
+ <item Type="qt4Header" >QStyleFactoryInterface</item>
+ <item Type="qt4Header" >QStyleHintReturn</item>
+ <item Type="qt4Header" >QStyleHintReturnMask</item>
+ <item Type="qt4Header" >QStyleOption</item>
+ <item Type="qt4Header" >QStyleOptionButton</item>
+ <item Type="qt4Header" >QStyleOptionComboBox</item>
+ <item Type="qt4Header" >QStyleOptionComplex</item>
+ <item Type="qt4Header" >QStyleOptionDockWidget</item>
+ <item Type="qt4Header" >QStyleOptionFocusRect</item>
+ <item Type="qt4Header" >QStyleOptionFrame</item>
+ <item Type="qt4Header" >QStyleOptionFrameV2</item>
+ <item Type="qt4Header" >QStyleOptionGraphicsItem</item>
+ <item Type="qt4Header" >QStyleOptionGroupBox</item>
+ <item Type="qt4Header" >QStyleOptionHeader</item>
+ <item Type="qt4Header" >QStyleOptionMenuItem</item>
+ <item Type="qt4Header" >QStyleOptionProgressBar</item>
+ <item Type="qt4Header" >QStyleOptionProgressBarV2</item>
+ <item Type="qt4Header" >QStyleOptionQ3DockWindow</item>
+ <item Type="qt4Header" >QStyleOptionQ3ListView</item>
+ <item Type="qt4Header" >QStyleOptionQ3ListViewItem</item>
+ <item Type="qt4Header" >QStyleOptionRubberBand</item>
+ <item Type="qt4Header" >QStyleOptionSizeGrip</item>
+ <item Type="qt4Header" >QStyleOptionSlider</item>
+ <item Type="qt4Header" >QStyleOptionSpinBox</item>
+ <item Type="qt4Header" >QStyleOptionTab</item>
+ <item Type="qt4Header" >QStyleOptionTabBarBase</item>
+ <item Type="qt4Header" >QStyleOptionTabV2</item>
+ <item Type="qt4Header" >QStyleOptionTabWidgetFrame</item>
+ <item Type="qt4Header" >QStyleOptionTitleBar</item>
+ <item Type="qt4Header" >QStyleOptionToolBar</item>
+ <item Type="qt4Header" >QStyleOptionToolBox</item>
+ <item Type="qt4Header" >QStyleOptionToolButton</item>
+ <item Type="qt4Header" >QStyleOptionViewItem</item>
+ <item Type="qt4Header" >QStyleOptionViewItemV2</item>
+ <item Type="qt4Header" >QStylePainter</item>
+ <item Type="qt4Header" >QStylePlugin</item>
+ <item Type="qt4Header" >QSvgRenderer</item>
+ <item Type="qt4Header" >QSvgWidget</item>
+ <item Type="qt4Header" >QSyntaxHighlighter</item>
+ <item Type="qt4Header" >QSysInfo</item>
+ <item Type="qt4Header" >QSystemLocale</item>
+ <item Type="qt4Header" >QSystemTrayIcon</item>
+ <item Type="qt4Header" >QTDSDriver</item>
+ <item Type="qt4Header" >QTDSResult</item>
+ <item Type="qt4Header" >QTS</item>
+ <item Type="qt4Header" >QTabBar</item>
+ <item Type="qt4Header" >QTabWidget</item>
+ <item Type="qt4Header" >QTableView</item>
+ <item Type="qt4Header" >QTableWidget</item>
+ <item Type="qt4Header" >QTableWidgetItem</item>
+ <item Type="qt4Header" >QTableWidgetSelectionRange</item>
+ <item Type="qt4Header" >QTabletEvent</item>
+ <item Type="qt4Header" >QTcpServer</item>
+ <item Type="qt4Header" >QTcpSocket</item>
+ <item Type="qt4Header" >QTemporaryFile</item>
+ <item Type="qt4Header" >QTest</item>
+ <item Type="qt4Header" >QTestAccessibility</item>
+ <item Type="qt4Header" >QTestAccessibilityEvent</item>
+ <item Type="qt4Header" >QTestData</item>
+ <item Type="qt4Header" >QTestDelayEvent</item>
+ <item Type="qt4Header" >QTestEvent</item>
+ <item Type="qt4Header" >QTestEventList</item>
+ <item Type="qt4Header" >QTestEventLoop</item>
+ <item Type="qt4Header" >QTestKeyClicksEvent</item>
+ <item Type="qt4Header" >QTestKeyEvent</item>
+ <item Type="qt4Header" >QTestMouseEvent</item>
+ <item Type="qt4Header" >QTextBlock</item>
+ <item Type="qt4Header" >QTextBlockFormat</item>
+ <item Type="qt4Header" >QTextBlockGroup</item>
+ <item Type="qt4Header" >QTextBlockUserData</item>
+ <item Type="qt4Header" >QTextBrowser</item>
+ <item Type="qt4Header" >QTextCharFormat</item>
+ <item Type="qt4Header" >QTextCodec</item>
+ <item Type="qt4Header" >QTextCodecFactoryInterface</item>
+ <item Type="qt4Header" >QTextCodecPlugin</item>
+ <item Type="qt4Header" >QTextCursor</item>
+ <item Type="qt4Header" >QTextDecoder</item>
+ <item Type="qt4Header" >QTextDocument</item>
+ <item Type="qt4Header" >QTextDocumentFragment</item>
+ <item Type="qt4Header" >QTextEdit</item>
+ <item Type="qt4Header" >QTextEncoder</item>
+ <item Type="qt4Header" >QTextFormat</item>
+ <item Type="qt4Header" >QTextFragment</item>
+ <item Type="qt4Header" >QTextFrame</item>
+ <item Type="qt4Header" >QTextFrameFormat</item>
+ <item Type="qt4Header" >QTextFrameLayoutData</item>
+ <item Type="qt4Header" >QTextIStream</item>
+ <item Type="qt4Header" >QTextImageFormat</item>
+ <item Type="qt4Header" >QTextInlineObject</item>
+ <item Type="qt4Header" >QTextItem</item>
+ <item Type="qt4Header" >QTextLayout</item>
+ <item Type="qt4Header" >QTextLength</item>
+ <item Type="qt4Header" >QTextLine</item>
+ <item Type="qt4Header" >QTextList</item>
+ <item Type="qt4Header" >QTextListFormat</item>
+ <item Type="qt4Header" >QTextOStream</item>
+ <item Type="qt4Header" >QTextObject</item>
+ <item Type="qt4Header" >QTextObjectInterface</item>
+ <item Type="qt4Header" >QTextOption</item>
+ <item Type="qt4Header" >QTextStream</item>
+ <item Type="qt4Header" >QTextStreamFunction</item>
+ <item Type="qt4Header" >QTextStreamManipulator</item>
+ <item Type="qt4Header" >QTextTable</item>
+ <item Type="qt4Header" >QTextTableCell</item>
+ <item Type="qt4Header" >QTextTableFormat</item>
+ <item Type="qt4Header" >QThread</item>
+ <item Type="qt4Header" >QThreadStorage</item>
+ <item Type="qt4Header" >QThreadStorageData</item>
+ <item Type="qt4Header" >QTime</item>
+ <item Type="qt4Header" >QTimeEdit</item>
+ <item Type="qt4Header" >QTimeLine</item>
+ <item Type="qt4Header" >QTimer</item>
+ <item Type="qt4Header" >QTimerEvent</item>
+ <item Type="qt4Header" >QToolBar</item>
+ <item Type="qt4Header" >QToolBarChangeEvent</item>
+ <item Type="qt4Header" >QToolBox</item>
+ <item Type="qt4Header" >QToolButton</item>
+ <item Type="qt4Header" >QToolTip</item>
+ <item Type="qt4Header" >QTransformedScreen</item>
+ <item Type="qt4Header" >QTranslator</item>
+ <item Type="qt4Header" >QTransportAuth</item>
+ <item Type="qt4Header" >QTreeView</item>
+ <item Type="qt4Header" >QTreeWidget</item>
+ <item Type="qt4Header" >QTreeWidgetItem</item>
+ <item Type="qt4Header" >QTreeWidgetItemIterator</item>
+ <item Type="qt4Header" >QTypeInfo</item>
+ <item Type="qt4Header" >QUdpSocket</item>
+ <item Type="qt4Header" >QUiLoader</item>
+ <item Type="qt4Header" >QUintForSize</item>
+ <item Type="qt4Header" >QUintForType</item>
+ <item Type="qt4Header" >QUndoCommand</item>
+ <item Type="qt4Header" >QUndoGroup</item>
+ <item Type="qt4Header" >QUndoStack</item>
+ <item Type="qt4Header" >QUndoView</item>
+ <item Type="qt4Header" >QUpdateLaterEvent</item>
+ <item Type="qt4Header" >QUrl</item>
+ <item Type="qt4Header" >QUrlInfo</item>
+ <item Type="qt4Header" >QUuid</item>
+ <item Type="qt4Header" >QVBoxLayout</item>
+ <item Type="qt4Header" >QVFbHeader</item>
+ <item Type="qt4Header" >QVFbKeyData</item>
+ <item Type="qt4Header" >QVFbKeyboardHandler</item>
+ <item Type="qt4Header" >QVFbMouseHandler</item>
+ <item Type="qt4Header" >QVFbScreen</item>
+ <item Type="qt4Header" >QVNCScreen</item>
+ <item Type="qt4Header" >QValidator</item>
+ <item Type="qt4Header" >QVarLengthArray</item>
+ <item Type="qt4Header" >QVariant</item>
+ <item Type="qt4Header" >QVariantComparisonHelper</item>
+ <item Type="qt4Header" >QVariantList</item>
+ <item Type="qt4Header" >QVariantMap</item>
+ <item Type="qt4Header" >QVector</item>
+ <item Type="qt4Header" >QVectorData</item>
+ <item Type="qt4Header" >QVectorIterator</item>
+ <item Type="qt4Header" >QVectorTypedData</item>
+ <item Type="qt4Header" >QWMatrix</item>
+ <item Type="qt4Header" >QWSBusMouseHandler</item>
+ <item Type="qt4Header" >QWSCalibratedMouseHandler</item>
+ <item Type="qt4Header" >QWSClient</item>
+ <item Type="qt4Header" >QWSCursor</item>
+ <item Type="qt4Header" >QWSCursorMap</item>
+ <item Type="qt4Header" >QWSDisplay</item>
+ <item Type="qt4Header" >QWSEmbedWidget</item>
+ <item Type="qt4Header" >QWSEvent</item>
+ <item Type="qt4Header" >QWSInputMethod</item>
+ <item Type="qt4Header" >QWSInternalWindowInfo</item>
+ <item Type="qt4Header" >QWSKeyboardHandler</item>
+ <item Type="qt4Header" >QWSKeyboardHandlerFactoryInterface</item>
+ <item Type="qt4Header" >QWSLinuxTPMouseHandler</item>
+ <item Type="qt4Header" >QWSManager</item>
+ <item Type="qt4Header" >QWSMouseHandler</item>
+ <item Type="qt4Header" >QWSMouseHandlerFactoryInterface</item>
+ <item Type="qt4Header" >QWSPC101KeyboardHandler</item>
+ <item Type="qt4Header" >QWSPcMouseHandler</item>
+ <item Type="qt4Header" >QWSPointerCalibrationData</item>
+ <item Type="qt4Header" >QWSPropertyManager</item>
+ <item Type="qt4Header" >QWSProtocolItem</item>
+ <item Type="qt4Header" >QWSSL5000KeyboardHandler</item>
+ <item Type="qt4Header" >QWSScreenSaver</item>
+ <item Type="qt4Header" >QWSServer</item>
+ <item Type="qt4Header" >QWSServerSocket</item>
+ <item Type="qt4Header" >QWSSocket</item>
+ <item Type="qt4Header" >QWSSoundClient</item>
+ <item Type="qt4Header" >QWSSoundServer</item>
+ <item Type="qt4Header" >QWSSoundServerSocket</item>
+ <item Type="qt4Header" >QWSTslibMouseHandler</item>
+ <item Type="qt4Header" >QWSTtyKeyboardHandler</item>
+ <item Type="qt4Header" >QWSUmKeyboardHandler</item>
+ <item Type="qt4Header" >QWSUsbKeyboardHandler</item>
+ <item Type="qt4Header" >QWSVr41xxKeyboardHandler</item>
+ <item Type="qt4Header" >QWSVr41xxMouseHandler</item>
+ <item Type="qt4Header" >QWSWindow</item>
+ <item Type="qt4Header" >QWSWindowInfo</item>
+ <item Type="qt4Header" >QWSYopyKeyboardHandler</item>
+ <item Type="qt4Header" >QWSYopyMouseHandler</item>
+ <item Type="qt4Header" >QWaitCondition</item>
+ <item Type="qt4Header" >QWhatsThis</item>
+ <item Type="qt4Header" >QWhatsThisClickedEvent</item>
+ <item Type="qt4Header" >QWheelEvent</item>
+ <item Type="qt4Header" >QWidget</item>
+ <item Type="qt4Header" >QWidgetAction</item>
+ <item Type="qt4Header" >QWidgetData</item>
+ <item Type="qt4Header" >QWidgetItem</item>
+ <item Type="qt4Header" >QWidgetList</item>
+ <item Type="qt4Header" >QWidgetMapper</item>
+ <item Type="qt4Header" >QWidgetSet</item>
+ <item Type="qt4Header" >QWindowStateChangeEvent</item>
+ <item Type="qt4Header" >QWindowsMime</item>
+ <item Type="qt4Header" >QWindowsStyle</item>
+ <item Type="qt4Header" >QWindowsXPStyle</item>
+ <item Type="qt4Header" >QWorkspace</item>
+ <item Type="qt4Header" >QWriteLocker</item>
+ <item Type="qt4Header" >QX11EmbedContainer</item>
+ <item Type="qt4Header" >QX11EmbedWidget</item>
+ <item Type="qt4Header" >QX11Info</item>
+ <item Type="qt4Header" >QXmlAttributes</item>
+ <item Type="qt4Header" >QXmlContentHandler</item>
+ <item Type="qt4Header" >QXmlDTDHandler</item>
+ <item Type="qt4Header" >QXmlDeclHandler</item>
+ <item Type="qt4Header" >QXmlDefaultHandler</item>
+ <item Type="qt4Header" >QXmlEntityResolver</item>
+ <item Type="qt4Header" >QXmlErrorHandler</item>
+ <item Type="qt4Header" >QXmlInputSource</item>
+ <item Type="qt4Header" >QXmlLexicalHandler</item>
+ <item Type="qt4Header" >QXmlLocator</item>
+ <item Type="qt4Header" >QXmlNamespaceSupport</item>
+ <item Type="qt4Header" >QXmlParseException</item>
+ <item Type="qt4Header" >QXmlReader</item>
+ <item Type="qt4Header" >QXmlSimpleReader</item>
+ <item Type="RenamedClass" >
+ <Qt4>QIcon</Qt4>
+ <Qt3>QIconSet</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>QMatrix</Qt4>
+ <Qt3>QWMatrix</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>QPointer</Qt4>
+ <Qt3>QGuardedPtr</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Accel</Qt4>
+ <Qt3>QAccel</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ActionGroup</Qt4>
+ <Qt3>QActionGroup</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3AsciiBucket</Qt4>
+ <Qt3>QAsciiBucket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3AsciiCache</Qt4>
+ <Qt3>QAsciiCache</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3AsciiCacheIterator</Qt4>
+ <Qt3>QAsciiCacheIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3AsciiDict</Qt4>
+ <Qt3>QAsciiDict</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3AsciiDictIterator</Qt4>
+ <Qt3>QAsciiDictIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3BaseBucket</Qt4>
+ <Qt3>QBaseBucket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3BoxLayout</Qt4>
+ <Qt3>QBoxLayout</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ButtonGroup</Qt4>
+ <Qt3>QButtonGroup</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CString</Qt4>
+ <Qt3>QCString</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Cache</Qt4>
+ <Qt3>QCache</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CacheIterator</Qt4>
+ <Qt3>QCacheIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Canvas</Qt4>
+ <Qt3>QCanvas</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasEllipse</Qt4>
+ <Qt3>QCanvasEllipse</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasItem</Qt4>
+ <Qt3>QCanvasItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasItemList</Qt4>
+ <Qt3>QCanvasItemList</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasLine</Qt4>
+ <Qt3>QCanvasLine</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasPixmap</Qt4>
+ <Qt3>QCanvasPixmap</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasPixmapArray</Qt4>
+ <Qt3>QCanvasPixmapArray</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasPolygon</Qt4>
+ <Qt3>QCanvasPolygon</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasPolygonalItem</Qt4>
+ <Qt3>QCanvasPolygonalItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasRectangle</Qt4>
+ <Qt3>QCanvasRectangle</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasSpline</Qt4>
+ <Qt3>QCanvasSpline</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasSprite</Qt4>
+ <Qt3>QCanvasSprite</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasText</Qt4>
+ <Qt3>QCanvasText</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CanvasView</Qt4>
+ <Qt3>QCanvasView</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CheckListItem</Qt4>
+ <Qt3>QCheckListItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CheckTableItem</Qt4>
+ <Qt3>QCheckTableItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3CleanupHandler</Qt4>
+ <Qt3>QCleanupHandler</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ColorDrag</Qt4>
+ <Qt3>QColorDrag</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ComboTableItem</Qt4>
+ <Qt3>QComboTableItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DataBrowser</Qt4>
+ <Qt3>QDataBrowser</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DataTable</Qt4>
+ <Qt3>QDataTable</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DataView</Qt4>
+ <Qt3>QDataView</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DateEdit</Qt4>
+ <Qt3>QDateEdit</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DateTimeEdit</Qt4>
+ <Qt3>QDateTimeEdit</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DateTimeEditBase</Qt4>
+ <Qt3>QDateTimeEditBase</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Dict</Qt4>
+ <Qt3>QDict</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DictIterator</Qt4>
+ <Qt3>QDictIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Dns</Qt4>
+ <Qt3>QDns</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DnsSocket</Qt4>
+ <Qt3>QDnsSocket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DockArea</Qt4>
+ <Qt3>QDockArea</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DockAreaLayout</Qt4>
+ <Qt3>QDockAreaLayout</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DockWindow</Qt4>
+ <Qt3>QDockWindow</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DragObject</Qt4>
+ <Qt3>QDragObject</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DropSite</Qt4>
+ <Qt3>QDropSite</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3EditorFactory</Qt4>
+ <Qt3>QEditorFactory</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3FileDialog</Qt4>
+ <Qt3>QFileDialog</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3FileIconProvider</Qt4>
+ <Qt3>QFileIconProvider</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3FilePreview</Qt4>
+ <Qt3>QFilePreview</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Frame</Qt4>
+ <Qt3>QFrame</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Ftp</Qt4>
+ <Qt3>QFtp</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GArray</Qt4>
+ <Qt3>QGArray</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GCache</Qt4>
+ <Qt3>QGCache</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GCacheIterator</Qt4>
+ <Qt3>QGCacheIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GDict</Qt4>
+ <Qt3>QGDict</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GDictIterator</Qt4>
+ <Qt3>QGDictIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GList</Qt4>
+ <Qt3>QGList</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GListIterator</Qt4>
+ <Qt3>QGListIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GListStdIterator</Qt4>
+ <Qt3>QGListStdIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GVector</Qt4>
+ <Qt3>QGVector</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Grid</Qt4>
+ <Qt3>QGrid</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GridLayout</Qt4>
+ <Qt3>QGridLayout</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GridView</Qt4>
+ <Qt3>QGridView</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3GroupBox</Qt4>
+ <Qt3>QGroupBox</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3HBox</Qt4>
+ <Qt3>QHBox</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3HBoxLayout</Qt4>
+ <Qt3>QHBoxLayout</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3HButtonGroup</Qt4>
+ <Qt3>QHButtonGroup</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3HGroupBox</Qt4>
+ <Qt3>QHGroupBox</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Header</Qt4>
+ <Qt3>QHeader</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Http</Qt4>
+ <Qt3>QHttp</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3HttpHeader</Qt4>
+ <Qt3>QHttpHeader</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3HttpRequestHeader</Qt4>
+ <Qt3>QHttpRequestHeader</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3HttpResponseHeader</Qt4>
+ <Qt3>QHttpResponseHeader</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IconDrag</Qt4>
+ <Qt3>QIconDrag</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IconDragItem</Qt4>
+ <Qt3>QIconDragItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IconView</Qt4>
+ <Qt3>QIconView</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IconViewItem</Qt4>
+ <Qt3>QIconViewItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ImageDrag</Qt4>
+ <Qt3>QImageDrag</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IntBucket</Qt4>
+ <Qt3>QIntBucket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IntCache</Qt4>
+ <Qt3>QIntCache</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IntCacheIterator</Qt4>
+ <Qt3>QIntCacheIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IntDict</Qt4>
+ <Qt3>QIntDict</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3IntDictIterator</Qt4>
+ <Qt3>QIntDictIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3LNode</Qt4>
+ <Qt3>QLNode</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ListBox</Qt4>
+ <Qt3>QListBox</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ListBoxItem</Qt4>
+ <Qt3>QListBoxItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ListBoxPixmap</Qt4>
+ <Qt3>QListBoxPixmap</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ListBoxText</Qt4>
+ <Qt3>QListBoxText</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ListView</Qt4>
+ <Qt3>QListView</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ListViewItem</Qt4>
+ <Qt3>QListViewItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ListViewItemIterator</Qt4>
+ <Qt3>QListViewItemIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3LocalFs</Qt4>
+ <Qt3>QLocalFs</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3MainWindow</Qt4>
+ <Qt3>QMainWindow</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3MemArray</Qt4>
+ <Qt3>QMemArray</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3MimeSourceFactory</Qt4>
+ <Qt3>QMimeSourceFactory</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3MultiLineEdit</Qt4>
+ <Qt3>QMultiLineEdit</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3NetworkOperation</Qt4>
+ <Qt3>QNetworkOperation</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3NetworkProtocol</Qt4>
+ <Qt3>QNetworkProtocol</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3NetworkProtocolFactory</Qt4>
+ <Qt3>QNetworkProtocolFactory</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3NetworkProtocolFactoryBase</Qt4>
+ <Qt3>QNetworkProtocolFactoryBase</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ObjectDictionary</Qt4>
+ <Qt3>QObjectDictionary</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PaintDeviceMetrics</Qt4>
+ <Qt3>QPaintDeviceMetrics</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Picture</Qt4>
+ <Qt3>QPicture</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PointArray</Qt4>
+ <Qt3>QPointArray</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PolygonScanner</Qt4>
+ <Qt3>QPolygonScanner</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PopupMenu</Qt4>
+ <Qt3>QPopupMenu</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Process</Qt4>
+ <Qt3>QProcess</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ProgressBar</Qt4>
+ <Qt3>QProgressBar</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ProgressDialog</Qt4>
+ <Qt3>QProgressDialog</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrBucket</Qt4>
+ <Qt3>QPtrBucket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrCollection</Qt4>
+ <Qt3>QPtrCollection</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrDict</Qt4>
+ <Qt3>QPtrDict</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrDictIterator</Qt4>
+ <Qt3>QPtrDictIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrList</Qt4>
+ <Qt3>QPtrList</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrListIterator</Qt4>
+ <Qt3>QPtrListIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrListStdIterator</Qt4>
+ <Qt3>QPtrListStdIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrQueue</Qt4>
+ <Qt3>QPtrQueue</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrStack</Qt4>
+ <Qt3>QPtrStack</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrVector</Qt4>
+ <Qt3>QPtrVector</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3RangeControl</Qt4>
+ <Qt3>QRangeControl</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ScrollView</Qt4>
+ <Qt3>QScrollView</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ServerSocket</Qt4>
+ <Qt3>QServerSocket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Shared</Qt4>
+ <Qt3>QShared</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Signal</Qt4>
+ <Qt3>QSignal</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SimpleRichText</Qt4>
+ <Qt3>QSimpleRichText</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SingleCleanupHandler</Qt4>
+ <Qt3>QSingleCleanupHandler</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Socket</Qt4>
+ <Qt3>QSocket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SocketDevice</Qt4>
+ <Qt3>QSocketDevice</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SortedList</Qt4>
+ <Qt3>QSortedList</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SpinWidget</Qt4>
+ <Qt3>QSpinWidget</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SqlCursor</Qt4>
+ <Qt3>QSqlCursor</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SqlEditorFactory</Qt4>
+ <Qt3>QSqlEditorFactory</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SqlFieldInfo</Qt4>
+ <Qt3>QSqlFieldInfo</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SqlForm</Qt4>
+ <Qt3>QSqlForm</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SqlPropertyMap</Qt4>
+ <Qt3>QSqlPropertyMap</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SqlRecordInfo</Qt4>
+ <Qt3>QSqlRecordInfo</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SqlSelectCursor</Qt4>
+ <Qt3>QSqlSelectCursor</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StoredDrag</Qt4>
+ <Qt3>QStoredDrag</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StrIList</Qt4>
+ <Qt3>QStrIList</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StrIVec</Qt4>
+ <Qt3>QStrIVec</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StrList</Qt4>
+ <Qt3>QStrList</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StrListIterator</Qt4>
+ <Qt3>QStrListIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StrVec</Qt4>
+ <Qt3>QStrVec</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StringBucket</Qt4>
+ <Qt3>QStringBucket</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StyleSheet</Qt4>
+ <Qt3>QStyleSheet</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3StyleSheetItem</Qt4>
+ <Qt3>QStyleSheetItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3SyntaxHighlighter</Qt4>
+ <Qt3>QSyntaxHighlighter</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TSManip</Qt4>
+ <Qt3>QTSManip</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TabDialog</Qt4>
+ <Qt3>QTabDialog</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Table</Qt4>
+ <Qt3>QTable</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TableItem</Qt4>
+ <Qt3>QTableItem</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TableSelection</Qt4>
+ <Qt3>QTableSelection</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TextBrowser</Qt4>
+ <Qt3>QTextBrowser</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TextDrag</Qt4>
+ <Qt3>QTextDrag</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TextEdit</Qt4>
+ <Qt3>QTextEdit</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TextEditOptimPrivate</Qt4>
+ <Qt3>QTextEditOptimPrivate</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TextStream</Qt4>
+ <Qt3>QTextStream</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TextView</Qt4>
+ <Qt3>QTextView</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3TimeEdit</Qt4>
+ <Qt3>QTimeEdit</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ToolBar</Qt4>
+ <Qt3>QToolBar</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3UriDrag</Qt4>
+ <Qt3>QUriDrag</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Url</Qt4>
+ <Qt3>QUrl</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3UrlOperator</Qt4>
+ <Qt3>QUrlOperator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3VBox</Qt4>
+ <Qt3>QVBox</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3VBoxLayout</Qt4>
+ <Qt3>QVBoxLayout</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3VButtonGroup</Qt4>
+ <Qt3>QVButtonGroup</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3VGroupBox</Qt4>
+ <Qt3>QVGroupBox</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ValueList</Qt4>
+ <Qt3>QValueList</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ValueListConstIterator</Qt4>
+ <Qt3>QValueListConstIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ValueListIterator</Qt4>
+ <Qt3>QValueListIterator</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ValueStack</Qt4>
+ <Qt3>QValueStack</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3ValueVector</Qt4>
+ <Qt3>QValueVector</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3WhatsThis</Qt4>
+ <Qt3>QWhatsThis</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3WidgetStack</Qt4>
+ <Qt3>QWidgetStack</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3Wizard</Qt4>
+ <Qt3>QWizard</Qt3>
+ </item>
+ <item Type="InheritsQt" >Qt</item>
+ <item Type="InheritsQt" >QKeySequence</item>
+ <item Type="InheritsQt" >QEvent</item>
+ <item Type="InheritsQt" >QTimerEvent</item>
+ <item Type="InheritsQt" >QMouseEvent</item>
+ <item Type="InheritsQt" >QWheelEvent</item>
+ <item Type="InheritsQt" >QTabletEvent</item>
+ <item Type="InheritsQt" >QKeyEvent</item>
+ <item Type="InheritsQt" >QFocusEvent</item>
+ <item Type="InheritsQt" >QPaintEvent</item>
+ <item Type="InheritsQt" >QMoveEvent</item>
+ <item Type="InheritsQt" >QResizeEvent</item>
+ <item Type="InheritsQt" >QCloseEvent</item>
+ <item Type="InheritsQt" >QIconDragEvent</item>
+ <item Type="InheritsQt" >QShowEvent</item>
+ <item Type="InheritsQt" >QHideEvent</item>
+ <item Type="InheritsQt" >QContextMenuEvent</item>
+ <item Type="InheritsQt" >QIMEvent</item>
+ <item Type="InheritsQt" >QIMComposeEvent</item>
+ <item Type="InheritsQt" >QDropEvent</item>
+ <item Type="InheritsQt" >QDragMoveEvent</item>
+ <item Type="InheritsQt" >QDragEnterEvent</item>
+ <item Type="InheritsQt" >QDragResponseEvent</item>
+ <item Type="InheritsQt" >QDragLeaveEvent</item>
+ <item Type="InheritsQt" >QChildEvent</item>
+ <item Type="InheritsQt" >QCustomEvent</item>
+ <item Type="InheritsQt" >QObject</item>
+ <item Type="InheritsQt" >QBrush</item>
+ <item Type="InheritsQt" >QWidget</item>
+ <item Type="InheritsQt" >QStyle</item>
+ <item Type="InheritsQt" >QFrame</item>
+ <item Type="InheritsQt" >QComboBox</item>
+ <item Type="InheritsQt" >QGroupBox</item>
+ <item Type="InheritsQt" >QDialog</item>
+ <item Type="InheritsQt" >QDataView</item>
+ <item Type="InheritsQt" >QDockWindow</item>
+ <item Type="InheritsQt" >QCommonStyle</item>
+ <item Type="InheritsQt" >QNetworkProtocol</item>
+ <item Type="InheritsQt" >QNetworkOperation</item>
+ <item Type="InheritsQt" >QPixmap</item>
+ <item Type="InheritsQt" >QGPlugin</item>
+ <item Type="InheritsQt" >QGrid</item>
+ <item Type="InheritsQt" >QSpinWidget</item>
+ <item Type="InheritsQt" >QButtonGroup</item>
+ <item Type="InheritsQt" >QDateTimeEditBase</item>
+ <item Type="InheritsQt" >QDateEdit</item>
+ <item Type="InheritsQt" >QTimeEdit</item>
+ <item Type="InheritsQt" >QDateTimeEdit</item>
+ <item Type="InheritsQt" >QHBox</item>
+ <item Type="InheritsQt" >QHButtonGroup</item>
+ <item Type="InheritsQt" >QHGroupBox</item>
+ <item Type="InheritsQt" >QSocketNotifier</item>
+ <item Type="InheritsQt" >QEventLoop</item>
+ <item Type="InheritsQt" >QHttp</item>
+ <item Type="InheritsQt" >QAction</item>
+ <item Type="InheritsQt" >QActionGroup</item>
+ <item Type="InheritsQt" >QImageFormatPlugin</item>
+ <item Type="InheritsQt" >QLineEdit</item>
+ <item Type="InheritsQt" >QMotifStyle</item>
+ <item Type="InheritsQt" >QAccel</item>
+ <item Type="InheritsQt" >QLabel</item>
+ <item Type="InheritsQt" >QLayout</item>
+ <item Type="InheritsQt" >QGridLayout</item>
+ <item Type="InheritsQt" >QBoxLayout</item>
+ <item Type="InheritsQt" >QHBoxLayout</item>
+ <item Type="InheritsQt" >QVBoxLayout</item>
+ <item Type="InheritsQt" >QLCDNumber</item>
+ <item Type="InheritsQt" >QInputDialog</item>
+ <item Type="InheritsQt" >QScrollBar</item>
+ <item Type="InheritsQt" >QScrollView</item>
+ <item Type="InheritsQt" >QWindowsStyle</item>
+ <item Type="InheritsQt" >QBitmap</item>
+ <item Type="InheritsQt" >QSignal</item>
+ <item Type="InheritsQt" >QMessageBox</item>
+ <item Type="InheritsQt" >QHeader</item>
+ <item Type="InheritsQt" >QMotifPlusStyle</item>
+ <item Type="InheritsQt" >QCDEStyle</item>
+ <item Type="InheritsQt" >QButton</item>
+ <item Type="InheritsQt" >QFtp</item>
+ <item Type="InheritsQt" >QGuardedPtrPrivate</item>
+ <item Type="InheritsQt" >QObjectCleanupHandler</item>
+ <item Type="InheritsQt" >QColorDialog</item>
+ <item Type="InheritsQt" >QCustomMenuItem</item>
+ <item Type="InheritsQt" >QListViewItem</item>
+ <item Type="InheritsQt" >QListView</item>
+ <item Type="InheritsQt" >QCheckListItem</item>
+ <item Type="InheritsQt" >QPen</item>
+ <item Type="InheritsQt" >QDragObject</item>
+ <item Type="InheritsQt" >QStoredDrag</item>
+ <item Type="InheritsQt" >QTextDrag</item>
+ <item Type="InheritsQt" >QImageDrag</item>
+ <item Type="InheritsQt" >QUriDrag</item>
+ <item Type="InheritsQt" >QColorDrag</item>
+ <item Type="InheritsQt" >QDragManager</item>
+ <item Type="InheritsQt" >QIconDrag</item>
+ <item Type="InheritsQt" >QIconViewItem</item>
+ <item Type="InheritsQt" >QIconView</item>
+ <item Type="InheritsQt" >QPlatinumStyle</item>
+ <item Type="InheritsQt" >QCursor</item>
+ <item Type="InheritsQt" >QErrorMessage</item>
+ <item Type="InheritsQt" >QPopupMenu</item>
+ <item Type="InheritsQt" >QPrintDialog</item>
+ <item Type="InheritsQt" >QProcess</item>
+ <item Type="InheritsQt" >QProgressBar</item>
+ <item Type="InheritsQt" >QSemiModal</item>
+ <item Type="InheritsQt" >QStyleSheetItem</item>
+ <item Type="InheritsQt" >QStyleSheet</item>
+ <item Type="InheritsQt" >QPushButton</item>
+ <item Type="InheritsQt" >QRadioButton</item>
+ <item Type="InheritsQt" >QDial</item>
+ <item Type="InheritsQt" >QDockAreaLayout</item>
+ <item Type="InheritsQt" >QDockArea</item>
+ <item Type="InheritsQt" >QClipboard</item>
+ <item Type="InheritsQt" >QListBox</item>
+ <item Type="InheritsQt" >QGridView</item>
+ <item Type="InheritsQt" >QProgressDialog</item>
+ <item Type="InheritsQt" >QSessionManager</item>
+ <item Type="InheritsQt" >QSGIStyle</item>
+ <item Type="InheritsQt" >QFontDialog</item>
+ <item Type="InheritsQt" >QTimer</item>
+ <item Type="InheritsQt" >QSignalMapper</item>
+ <item Type="InheritsQt" >QSizeGrip</item>
+ <item Type="InheritsQt" >QSlider</item>
+ <item Type="InheritsQt" >QSocket</item>
+ <item Type="InheritsQt" >QServerSocket</item>
+ <item Type="InheritsQt" >QDns</item>
+ <item Type="InheritsQt" >QDnsSocket</item>
+ <item Type="InheritsQt" >QSound</item>
+ <item Type="InheritsQt" >QAuServer</item>
+ <item Type="InheritsQt" >QSpinBox</item>
+ <item Type="InheritsQt" >QSplashScreen</item>
+ <item Type="InheritsQt" >QSplitter</item>
+ <item Type="InheritsQt" >QEditorFactory</item>
+ <item Type="InheritsQt" >QSqlResultShared</item>
+ <item Type="InheritsQt" >QSqlDriverPlugin</item>
+ <item Type="InheritsQt" >QSqlDriver</item>
+ <item Type="InheritsQt" >QSqlForm</item>
+ <item Type="InheritsQt" >QTableItem</item>
+ <item Type="InheritsQt" >QComboTableItem</item>
+ <item Type="InheritsQt" >QCheckTableItem</item>
+ <item Type="InheritsQt" >QTable</item>
+ <item Type="InheritsQt" >QSqlDatabase</item>
+ <item Type="InheritsQt" >QDataBrowser</item>
+ <item Type="InheritsQt" >QStatusBar</item>
+ <item Type="InheritsQt" >QMenuBar</item>
+ <item Type="InheritsQt" >QCanvasItem</item>
+ <item Type="InheritsQt" >QCanvas</item>
+ <item Type="InheritsQt" >QCanvasView</item>
+ <item Type="InheritsQt" >QCanvasPixmap</item>
+ <item Type="InheritsQt" >QCanvasSprite</item>
+ <item Type="InheritsQt" >QCanvasPolygonalItem</item>
+ <item Type="InheritsQt" >QCanvasRectangle</item>
+ <item Type="InheritsQt" >QCanvasPolygon</item>
+ <item Type="InheritsQt" >QCanvasSpline</item>
+ <item Type="InheritsQt" >QCanvasLine</item>
+ <item Type="InheritsQt" >QCanvasEllipse</item>
+ <item Type="InheritsQt" >QCanvasText</item>
+ <item Type="InheritsQt" >QTranslator</item>
+ <item Type="InheritsQt" >QStylePlugin</item>
+ <item Type="InheritsQt" >QTextEdit</item>
+ <item Type="InheritsQt" >QSyntaxHighlighter</item>
+ <item Type="InheritsQt" >QTab</item>
+ <item Type="InheritsQt" >QTabBar</item>
+ <item Type="InheritsQt" >QTabDialog</item>
+ <item Type="InheritsQt" >QSqlEditorFactory</item>
+ <item Type="InheritsQt" >QTabWidget</item>
+ <item Type="InheritsQt" >QTextBrowser</item>
+ <item Type="InheritsQt" >QTextCodecPlugin</item>
+ <item Type="InheritsQt" >QMultiLineEdit</item>
+ <item Type="InheritsQt" >QToolBar</item>
+ <item Type="InheritsQt" >QTextView</item>
+ <item Type="InheritsQt" >QDataPump</item>
+ <item Type="InheritsQt" >QMainWindow</item>
+ <item Type="InheritsQt" >QToolBox</item>
+ <item Type="InheritsQt" >QToolButton</item>
+ <item Type="InheritsQt" >QToolTipGroup</item>
+ <item Type="InheritsQt" >QToolTip</item>
+ <item Type="InheritsQt" >QDesktopWidget</item>
+ <item Type="InheritsQt" >QUrlOperator</item>
+ <item Type="InheritsQt" >QFileIconProvider</item>
+ <item Type="InheritsQt" >QFileDialog</item>
+ <item Type="InheritsQt" >QValidator</item>
+ <item Type="InheritsQt" >QIntValidator</item>
+ <item Type="InheritsQt" >QDoubleValidator</item>
+ <item Type="InheritsQt" >QRegExpValidator</item>
+ <item Type="InheritsQt" >QDataTable</item>
+ <item Type="InheritsQt" >QVBox</item>
+ <item Type="InheritsQt" >QVButtonGroup</item>
+ <item Type="InheritsQt" >QVGroupBox</item>
+ <item Type="InheritsQt" >QWhatsThis</item>
+ <item Type="InheritsQt" >QApplication</item>
+ <item Type="InheritsQt" >QWidgetPlugin</item>
+ <item Type="InheritsQt" >QWidgetStack</item>
+ <item Type="InheritsQt" >QCheckBox</item>
+ <item Type="InheritsQt" >QCompactStyle</item>
+ <item Type="InheritsQt" >QWizard</item>
+ <item Type="InheritsQt" >QPainter</item>
+ <item Type="InheritsQt" >QWorkspace</item>
+ <item Type="InheritsQt" >QLocalFs</item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QIODevice::Append</Qt4>
+ <Qt3>IO_Append</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QIODevice::ReadOnly</Qt4>
+ <Qt3>IO_ReadOnly</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QIODevice::ReadWrite</Qt4>
+ <Qt3>IO_ReadWrite</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QIODevice::Text</Qt4>
+ <Qt3>IO_Translate</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QIODevice::Truncate</Qt4>
+ <Qt3>IO_Truncate</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QIODevice::WriteOnly</Qt4>
+ <Qt3>IO_WriteOnly</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QIODevice::Unbuffered</Qt4>
+ <Qt3>IO_Raw</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QAccessible::Movable</Qt4>
+ <Qt3>QAccessible::Moveable</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QApplication::CustomColor</Qt4>
+ <Qt3>QApplication::CustomColors</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QApplication::NormalColor</Qt4>
+ <Qt3>QApplication::NormalColors</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QCheckBox::NoChange</Qt4>
+ <Qt3>QButton::NoChange</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QCheckBox::Off</Qt4>
+ <Qt3>QButton::Off</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QCheckBox::On</Qt4>
+ <Qt3>QButton::On</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QChar::NoDecomposition</Qt4>
+ <Qt3>QChar::Single</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QChar::ByteOrderMark</Qt4>
+ <Qt3>QChar::byteOrderMark</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QChar::ByteOrderSwapped</Qt4>
+ <Qt3>QChar::byteOrderSwapped</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QChar::Nbsp</Qt4>
+ <Qt3>QChar::nbsp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QChar::Null</Qt4>
+ <Qt3>QChar::null</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QChar::ReplacementCharacter</Qt4>
+ <Qt3>QChar::replacement</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QComboBox::InsertAfterCurrent</Qt4>
+ <Qt3>QComboBox::AfterCurrent</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QComboBox::InsertAtBottom</Qt4>
+ <Qt3>QComboBox::AtBottom</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QComboBox::InsertAtCurrent</Qt4>
+ <Qt3>QComboBox::AtCurrent</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QComboBox::InsertAtTop</Qt4>
+ <Qt3>QComboBox::AtTop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QComboBox::InsertBeforeCurrent</Qt4>
+ <Qt3>QComboBox::BeforeCurrent</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QComboBox::NoInsert</Qt4>
+ <Qt3>QComboBox::NoInsertion</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QDir::NoFilter</Qt4>
+ <Qt3>QDir::DefaultFilter</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QDir::NoSort</Qt4>
+ <Qt3>QDir::DefaultSort</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::Box</Qt4>
+ <Qt3>Q3Frame::GroupBoxPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>Q3Frame::LineEditPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>Q3Frame::PopupPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>Q3Frame::MenuBarPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>Q3Frame::ToolBarPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>Q3Frame::TabWidgetPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::Shortcut</Qt4>
+ <Qt3>QEvent::Accel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::ShortcutOverride</Qt4>
+ <Qt3>QEvent::AccelOverride</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::WindowTitleChange</Qt4>
+ <Qt3>QEvent::CaptionChange</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::ChildAdded</Qt4>
+ <Qt3>QEvent::ChildInserted</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::InputMethodCompose</Qt4>
+ <Qt3>QEvent::IMCompose</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::InputMethodEnd</Qt4>
+ <Qt3>QEvent::IMEnd</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::InputMethodStart</Qt4>
+ <Qt3>QEvent::IMStart</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::WindowIconChange</Qt4>
+ <Qt3>QEvent::IconChange</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::LayoutRequest</Qt4>
+ <Qt3>QEvent::LayoutHint</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QEvent::ParentChange</Qt4>
+ <Qt3>QEvent::Reparent</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ExeGroup</Qt4>
+ <Qt3>QFileInfo::ExeGroup</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ExeOther</Qt4>
+ <Qt3>QFileInfo::ExeOther</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ExeOwner</Qt4>
+ <Qt3>QFileInfo::ExeOwner</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ExeUser</Qt4>
+ <Qt3>QFileInfo::ExeUser</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ReadGroup</Qt4>
+ <Qt3>QFileInfo::ReadGroup</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ReadOther</Qt4>
+ <Qt3>QFileInfo::ReadOther</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ReadOwner</Qt4>
+ <Qt3>QFileInfo::ReadOwner</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::ReadUser</Qt4>
+ <Qt3>QFileInfo::ReadUser</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::WriteGroup</Qt4>
+ <Qt3>QFileInfo::WriteGroup</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::WriteOther</Qt4>
+ <Qt3>QFileInfo::WriteOther</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::WriteOwner</Qt4>
+ <Qt3>QFileInfo::WriteOwner</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFile::WriteUser</Qt4>
+ <Qt3>QFileInfo::WriteUser</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>QFrame::GroupBoxPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>QFrame::LineEditPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>QFrame::MenuBarPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>QFrame::PopupPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>QFrame::TabWidgetPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QFrame::StyledPanel</Qt4>
+ <Qt3>QFrame::ToolBarPanel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::IgnoreAspectRatio</Qt4>
+ <Qt3>QImage::ScaleFree</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::KeepAspectRatioByExpanding</Qt4>
+ <Qt3>QImage::ScaleMax</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::KeepAspectRatio</Qt4>
+ <Qt3>QImage::ScaleMin</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QKeySequence::ExactMatch</Qt4>
+ <Qt3>Qt::Identical</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QKeySequence::NoMatch</Qt4>
+ <Qt3>Qt::NoMatch</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QKeySequence::PartialMatch</Qt4>
+ <Qt3>Qt::PartialMatch</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QLayout::SetDefaultConstraint</Qt4>
+ <Qt3>QLayout::Auto</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QLayout::SetFixedSize</Qt4>
+ <Qt3>QLayout::Fixed</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QLayout::SetNoConstraint</Qt4>
+ <Qt3>QLayout::FreeResize</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QLayout::SetMinimumSize</Qt4>
+ <Qt3>QLayout::Minimum</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QMacStyle::SizeDefault</Qt4>
+ <Qt3>QMacStyle::SizeNone</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSettings::SystemScope</Qt4>
+ <Qt3>QSettings::Global</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSettings::UserScope</Qt4>
+ <Qt3>QSettings::User</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::IgnoreAspectRatio</Qt4>
+ <Qt3>QSize::ScaleFree</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::KeepAspectRatioByExpanding</Qt4>
+ <Qt3>QSize::ScaleMax</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::KeepAspectRatio</Qt4>
+ <Qt3>QSize::ScaleMin</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSizePolicy::Horizontally</Qt4>
+ <Qt3>QSizePolicy::Horizontal</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSizePolicy::Vertically</Qt4>
+ <Qt3>QSizePolicy::Vertical</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSlider::TicksAbove</Qt4>
+ <Qt3>QSlider::Above</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSlider::TicksBelow</Qt4>
+ <Qt3>QSlider::Below</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSlider::TicksBothSides</Qt4>
+ <Qt3>QSlider::Both</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSlider::TicksLeft</Qt4>
+ <Qt3>QSlider::Left</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSlider::NoTicks</Qt4>
+ <Qt3>QSlider::NoMarks</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSlider::TicksRight</Qt4>
+ <Qt3>QSlider::Right</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Q3Socket::Closing</Qt4>
+ <Qt3>QSocket::Closing</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Q3Socket::Connected</Qt4>
+ <Qt3>QSocket::Connected</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Q3Socket::Connecting</Qt4>
+ <Qt3>QSocket::Connecting</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Q3Socket::Connection</Qt4>
+ <Qt3>QSocket::Connection</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Q3Socket::ErrConnectionRefused</Qt4>
+ <Qt3>QSocket::ErrConnectionRefused</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Q3Socket::ErrHostNotFound</Qt4>
+ <Qt3>QSocket::ErrHostNotFound</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Q3Socket::ErrSocketRead</Qt4>
+ <Qt3>QSocket::ErrSocketRead</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QAbstractSocket::HostLookupState</Qt4>
+ <Qt3>QSocket::HostLookup</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QAbstractSocket::UnconnectedState</Qt4>
+ <Qt3>QSocket::Idle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSqlError::ConnectionError</Qt4>
+ <Qt3>QSqlError::Connection</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSqlError::NoError</Qt4>
+ <Qt3>QSqlError::None</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSqlError::StatementError</Qt4>
+ <Qt3>QSqlError::Statement</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSqlError::TransactionError</Qt4>
+ <Qt3>QSqlError::Transaction</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSqlError::UnknownError</Qt4>
+ <Qt3>QSqlError::Unknown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::CC_Q3ListView</Qt4>
+ <Qt3>QStyle::CC_ListView</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::SH_UnderlineShortcut</Qt4>
+ <Qt3>QStyle::SH_UnderlineAccelerator</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Active</Qt4>
+ <Qt3>QStyle::Style_Active</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_AutoRaise</Qt4>
+ <Qt3>QStyle::Style_AutoRaise</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Bottom</Qt4>
+ <Qt3>QStyle::Style_Bottom</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Children</Qt4>
+ <Qt3>QStyle::Style_Children</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_None</Qt4>
+ <Qt3>QStyle::Style_Default</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_DownArrow</Qt4>
+ <Qt3>QStyle::Style_Down</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Editing</Qt4>
+ <Qt3>QStyle::Style_Editing</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Enabled</Qt4>
+ <Qt3>QStyle::Style_Enabled</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_FocusAtBorder</Qt4>
+ <Qt3>QStyle::Style_FocusAtBorder</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_HasFocus</Qt4>
+ <Qt3>QStyle::Style_HasFocus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Horizontal</Qt4>
+ <Qt3>QStyle::Style_Horizontal</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Item</Qt4>
+ <Qt3>QStyle::Style_Item</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_MouseOver</Qt4>
+ <Qt3>QStyle::Style_MouseOver</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_NoChange</Qt4>
+ <Qt3>QStyle::Style_NoChange</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_None</Qt4>
+ <Qt3>QStyle::Style_None</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Off</Qt4>
+ <Qt3>QStyle::Style_Off</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_On</Qt4>
+ <Qt3>QStyle::Style_On</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Open</Qt4>
+ <Qt3>QStyle::Style_Open</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Raised</Qt4>
+ <Qt3>QStyle::Style_Raised</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Rectangle</Qt4>
+ <Qt3>QStyle::Style_Rectangle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Selected</Qt4>
+ <Qt3>QStyle::Style_Selected</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Sibling</Qt4>
+ <Qt3>QStyle::Style_Sibling</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Sunken</Qt4>
+ <Qt3>QStyle::Style_Sunken</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Top</Qt4>
+ <Qt3>QStyle::Style_Top</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QStyle::State_Up</Qt4>
+ <Qt3>QStyle::Style_Up</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QTabBar::RoundedNorth</Qt4>
+ <Qt3>QTabBar::RoundedAbove</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QTabBar:: RoundedSouth</Qt4>
+ <Qt3>QTabBar::RoundedBelow</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QTabBar:: TriangularNorth</Qt4>
+ <Qt3>QTabBar::TriangularAbove</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QTabBar:: TriangularSouth</Qt4>
+ <Qt3>QTabBar::TriangularBelow</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QTextEdit::MovePageDown</Qt4>
+ <Qt3>QTextEdit::MovePgDown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QTextEdit::MovePageUp</Qt4>
+ <Qt3>QTextEdit::MovePgUp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QToolButton::BesideIcon</Qt4>
+ <Qt3>QToolButton::Right</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QToolButton::BelowIcon</Qt4>
+ <Qt3>QToolButton::Under</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QValidator::Intermediate</Qt4>
+ <Qt3>QValidator::Valid</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QCoreVariant::Icon</Qt4>
+ <Qt3>QVariant::IconSet</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ClickFocus</Qt4>
+ <Qt3>QWidget::ClickFocus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::NoFocus</Qt4>
+ <Qt3>QWidget::NoFocus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::StrongFocus</Qt4>
+ <Qt3>QWidget::StrongFocus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TabFocus</Qt4>
+ <Qt3>QWidget::TabFocus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WheelFocus</Qt4>
+ <Qt3>QWidget::WheelFocus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignLeft</Qt4>
+ <Qt3>Qt::AlignAuto</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AltModifier</Qt4>
+ <Qt3>Qt::AltButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AscendingOrder</Qt4>
+ <Qt3>Qt::Ascending</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockBottom</Qt4>
+ <Qt3>Qt::Bottom</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BottomLeftCorner</Qt4>
+ <Qt3>Qt::BottomLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BottomRightCorner</Qt4>
+ <Qt3>Qt::BottomRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextWrapAnywhere</Qt4>
+ <Qt3>Qt::BreakAnywhere</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ControlModifier</Qt4>
+ <Qt3>Qt::ControlButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TexturePattern</Qt4>
+ <Qt3>Qt::CustomPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DescendingOrder</Qt4>
+ <Qt3>Qt::Descending</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextDontClip</Qt4>
+ <Qt3>Qt::DontClip</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextDontPrint</Qt4>
+ <Qt3>Qt::DontPrint</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextExpandTabs</Qt4>
+ <Qt3>Qt::ExpandTabs</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextIncludeTrailingSpaces</Qt4>
+ <Qt3>Qt::IncludeTrailingSpaces</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::KeyboardModifierMask</Qt4>
+ <Qt3>Qt::KeyButtonMask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Backspace</Qt4>
+ <Qt3>Qt::Key_BackSpace</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Backtab</Qt4>
+ <Qt3>Qt::Key_BackTab</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_MediaPrevious</Qt4>
+ <Qt3>Qt::Key_MediaPrev</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_PageDown</Qt4>
+ <Qt3>Qt::Key_Next</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_PageUp</Qt4>
+ <Qt3>Qt::Key_Prior</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Aacute</Qt4>
+ <Qt3>Qt::Key_aacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Acircumflex</Qt4>
+ <Qt3>Qt::Key_acircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Adiaeresis</Qt4>
+ <Qt3>Qt::Key_adiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_AE</Qt4>
+ <Qt3>Qt::Key_ae</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Agrave</Qt4>
+ <Qt3>Qt::Key_agrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Aring</Qt4>
+ <Qt3>Qt::Key_aring</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Atilde</Qt4>
+ <Qt3>Qt::Key_atilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ccedilla</Qt4>
+ <Qt3>Qt::Key_ccedilla</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Eacute</Qt4>
+ <Qt3>Qt::Key_eacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ecircumflex</Qt4>
+ <Qt3>Qt::Key_ecircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ediaeresis</Qt4>
+ <Qt3>Qt::Key_ediaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Egrave</Qt4>
+ <Qt3>Qt::Key_egrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ETH</Qt4>
+ <Qt3>Qt::Key_eth</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Iacute</Qt4>
+ <Qt3>Qt::Key_iacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Icircumflex</Qt4>
+ <Qt3>Qt::Key_icircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Idiaeresis</Qt4>
+ <Qt3>Qt::Key_idiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Igrave</Qt4>
+ <Qt3>Qt::Key_igrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ntilde</Qt4>
+ <Qt3>Qt::Key_ntilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Oacute</Qt4>
+ <Qt3>Qt::Key_oacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ocircumflex</Qt4>
+ <Qt3>Qt::Key_ocircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Odiaeresis</Qt4>
+ <Qt3>Qt::Key_odiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ograve</Qt4>
+ <Qt3>Qt::Key_ograve</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ooblique</Qt4>
+ <Qt3>Qt::Key_oslash</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Otilde</Qt4>
+ <Qt3>Qt::Key_otilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_THORN</Qt4>
+ <Qt3>Qt::Key_thorn</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Uacute</Qt4>
+ <Qt3>Qt::Key_uacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ucircumflex</Qt4>
+ <Qt3>Qt::Key_ucircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Udiaeresis</Qt4>
+ <Qt3>Qt::Key_udiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ugrave</Qt4>
+ <Qt3>Qt::Key_ugrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Yacute</Qt4>
+ <Qt3>Qt::Key_yacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::KeypadModifier</Qt4>
+ <Qt3>Qt::Keypad</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockLeft</Qt4>
+ <Qt3>Qt::Left</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_0</Qt4>
+ <Qt3>Qt::MV_10_DOT_0</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_1</Qt4>
+ <Qt3>Qt::MV_10_DOT_1</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_2</Qt4>
+ <Qt3>Qt::MV_10_DOT_2</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_3</Qt4>
+ <Qt3>Qt::MV_10_DOT_3</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_4</Qt4>
+ <Qt3>Qt::MV_10_DOT_4</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_9</Qt4>
+ <Qt3>Qt::MV_9</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_0</Qt4>
+ <Qt3>Qt::MV_CHEETAH</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_2</Qt4>
+ <Qt3>Qt::MV_JAGUAR</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_3</Qt4>
+ <Qt3>Qt::MV_PANTHER</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_1</Qt4>
+ <Qt3>Qt::MV_PUMA</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_10_4</Qt4>
+ <Qt3>Qt::MV_TIGER</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::MV_Unknown</Qt4>
+ <Qt3>Qt::MV_Unknown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MetaModifier</Qt4>
+ <Qt3>Qt::MetaButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockMinimized</Qt4>
+ <Qt3>Qt::Minimized</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextHideMnemonic</Qt4>
+ <Qt3>Qt::NoAccel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextOverline</Qt4>
+ <Qt3>Qt::Overline</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockRight</Qt4>
+ <Qt3>Qt::Right</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ShiftModifier</Qt4>
+ <Qt3>Qt::ShiftButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextShowMnemonic</Qt4>
+ <Qt3>Qt::ShowPrefix</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextSingleLine</Qt4>
+ <Qt3>Qt::SingleLine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextStrikeOut</Qt4>
+ <Qt3>Qt::StrikeOut</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockTop</Qt4>
+ <Qt3>Qt::Top</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TopLeftCorner</Qt4>
+ <Qt3>Qt::TopLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TopRightCorner</Qt4>
+ <Qt3>Qt::TopRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockTornOff</Qt4>
+ <Qt3>Qt::TornOff</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextUnderline</Qt4>
+ <Qt3>Qt::Underline</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockUnmanaged</Qt4>
+ <Qt3>Qt::Unmanaged</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStaticContents</Qt4>
+ <Qt3>Qt::WNorthWestGravity</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WNoAutoErase</Qt4>
+ <Qt3>Qt::WRepaintNoErase</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WType_Dialog</Qt4>
+ <Qt3>Qt::WStyle_Dialog</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_NoBorder</Qt4>
+ <Qt3>Qt::WStyle_NoBorderEx</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>(Qt::WType_Dialog | Qt::WShowModal)</Qt4>
+ <Qt3>Qt::WType_Modal</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_2000</Qt4>
+ <Qt3>Qt::WV_2000</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_2003</Qt4>
+ <Qt3>Qt::WV_2003</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_32s</Qt4>
+ <Qt3>Qt::WV_32s</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_95</Qt4>
+ <Qt3>Qt::WV_95</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_98</Qt4>
+ <Qt3>Qt::WV_98</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_CE</Qt4>
+ <Qt3>Qt::WV_CE</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_CENET</Qt4>
+ <Qt3>Qt::WV_CENET</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_CE_based</Qt4>
+ <Qt3>Qt::WV_CE_based</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_DOS_based</Qt4>
+ <Qt3>Qt::WV_DOS_based</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_Me</Qt4>
+ <Qt3>Qt::WV_Me</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_NT</Qt4>
+ <Qt3>Qt::WV_NT</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_NT_based</Qt4>
+ <Qt3>Qt::WV_NT_based</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>QSysInfo::WV_XP</Qt4>
+ <Qt3>Qt::WV_XP</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextWordWrap</Qt4>
+ <Qt3>Qt::WordBreak</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::IBeamCursor</Qt4>
+ <Qt3>Qt::IbeamCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::NoButton</Qt4>
+ <Qt3>Qt::NoButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LeftButton</Qt4>
+ <Qt3>Qt::LeftButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::RightButton</Qt4>
+ <Qt3>Qt::RightButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MidButton</Qt4>
+ <Qt3>Qt::MidButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MouseButtonMask</Qt4>
+ <Qt3>Qt::MouseButtonMask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ShiftButton</Qt4>
+ <Qt3>Qt::ShiftButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ControlButton</Qt4>
+ <Qt3>Qt::ControlButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AltButton</Qt4>
+ <Qt3>Qt::AltButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MetaButton</Qt4>
+ <Qt3>Qt::MetaButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::KeyButtonMask</Qt4>
+ <Qt3>Qt::KeyButtonMask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Keypad</Qt4>
+ <Qt3>Qt::Keypad</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Horizontal</Qt4>
+ <Qt3>Qt::Horizontal</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Vertical</Qt4>
+ <Qt3>Qt::Vertical</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignAuto</Qt4>
+ <Qt3>Qt::AlignAuto</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignLeft</Qt4>
+ <Qt3>Qt::AlignLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignRight</Qt4>
+ <Qt3>Qt::AlignRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignHCenter</Qt4>
+ <Qt3>Qt::AlignHCenter</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignJustify</Qt4>
+ <Qt3>Qt::AlignJustify</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignHorizontal_Mask</Qt4>
+ <Qt3>Qt::AlignHorizontal_Mask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignTop</Qt4>
+ <Qt3>Qt::AlignTop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignBottom</Qt4>
+ <Qt3>Qt::AlignBottom</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignVCenter</Qt4>
+ <Qt3>Qt::AlignVCenter</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignVertical_Mask</Qt4>
+ <Qt3>Qt::AlignVertical_Mask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlignCenter</Qt4>
+ <Qt3>Qt::AlignCenter</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SingleLine</Qt4>
+ <Qt3>Qt::SingleLine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DontClip</Qt4>
+ <Qt3>Qt::DontClip</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ExpandTabs</Qt4>
+ <Qt3>Qt::ExpandTabs</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ShowPrefix</Qt4>
+ <Qt3>Qt::ShowPrefix</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WordBreak</Qt4>
+ <Qt3>Qt::WordBreak</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BreakAnywhere</Qt4>
+ <Qt3>Qt::BreakAnywhere</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DontPrint</Qt4>
+ <Qt3>Qt::DontPrint</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::IncludeTrailingSpaces</Qt4>
+ <Qt3>Qt::IncludeTrailingSpaces</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::NoAccel</Qt4>
+ <Qt3>Qt::NoAccel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WType_TopLevel</Qt4>
+ <Qt3>Qt::WType_TopLevel</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WType_Dialog</Qt4>
+ <Qt3>Qt::WType_Dialog</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WType_Popup</Qt4>
+ <Qt3>Qt::WType_Popup</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WType_Desktop</Qt4>
+ <Qt3>Qt::WType_Desktop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WType_Mask</Qt4>
+ <Qt3>Qt::WType_Mask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_Customize</Qt4>
+ <Qt3>Qt::WStyle_Customize</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_NormalBorder</Qt4>
+ <Qt3>Qt::WStyle_NormalBorder</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_DialogBorder</Qt4>
+ <Qt3>Qt::WStyle_DialogBorder</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_NoBorder</Qt4>
+ <Qt3>Qt::WStyle_NoBorder</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_Title</Qt4>
+ <Qt3>Qt::WStyle_Title</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_SysMenu</Qt4>
+ <Qt3>Qt::WStyle_SysMenu</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_Minimize</Qt4>
+ <Qt3>Qt::WStyle_Minimize</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_Maximize</Qt4>
+ <Qt3>Qt::WStyle_Maximize</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_MinMax</Qt4>
+ <Qt3>Qt::WStyle_MinMax</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_Tool</Qt4>
+ <Qt3>Qt::WStyle_Tool</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_StaysOnTop</Qt4>
+ <Qt3>Qt::WStyle_StaysOnTop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_ContextHelp</Qt4>
+ <Qt3>Qt::WStyle_ContextHelp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WDestructiveClose</Qt4>
+ <Qt3>Qt::WDestructiveClose</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WPaintDesktop</Qt4>
+ <Qt3>Qt::WPaintDesktop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WPaintClever</Qt4>
+ <Qt3>Qt::WPaintClever</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WResizeNoErase</Qt4>
+ <Qt3>Qt::WResizeNoErase</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WMouseNoMask</Qt4>
+ <Qt3>Qt::WMouseNoMask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStaticContents</Qt4>
+ <Qt3>Qt::WStaticContents</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WRepaintNoErase</Qt4>
+ <Qt3>Qt::WRepaintNoErase</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WX11BypassWM</Qt4>
+ <Qt3>Qt::WX11BypassWM</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WWinOwnDC</Qt4>
+ <Qt3>Qt::WWinOwnDC</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WMacNoSheet</Qt4>
+ <Qt3>Qt::WMacNoSheet</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WMacDrawer</Qt4>
+ <Qt3>Qt::WMacDrawer</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WGroupLeader</Qt4>
+ <Qt3>Qt::WGroupLeader</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WShowModal</Qt4>
+ <Qt3>Qt::WShowModal</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WNoMousePropagation</Qt4>
+ <Qt3>Qt::WNoMousePropagation</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_Splash</Qt4>
+ <Qt3>Qt::WStyle_Splash</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WNoAutoErase</Qt4>
+ <Qt3>Qt::WNoAutoErase</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WNorthWestGravity</Qt4>
+ <Qt3>Qt::WNorthWestGravity</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WType_Modal</Qt4>
+ <Qt3>Qt::WType_Modal</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_Dialog</Qt4>
+ <Qt3>Qt::WStyle_Dialog</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WStyle_NoBorderEx</Qt4>
+ <Qt3>Qt::WStyle_NoBorderEx</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WindowNoState</Qt4>
+ <Qt3>Qt::WindowNoState</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WindowMinimized</Qt4>
+ <Qt3>Qt::WindowMinimized</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WindowMaximized</Qt4>
+ <Qt3>Qt::WindowMaximized</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WindowFullScreen</Qt4>
+ <Qt3>Qt::WindowFullScreen</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WindowActive</Qt4>
+ <Qt3>Qt::WindowActive</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ColorMode_Mask</Qt4>
+ <Qt3>Qt::ColorMode_Mask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AutoColor</Qt4>
+ <Qt3>Qt::AutoColor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ColorOnly</Qt4>
+ <Qt3>Qt::ColorOnly</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MonoOnly</Qt4>
+ <Qt3>Qt::MonoOnly</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AlphaDither_Mask</Qt4>
+ <Qt3>Qt::AlphaDither_Mask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ThresholdAlphaDither</Qt4>
+ <Qt3>Qt::ThresholdAlphaDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::OrderedAlphaDither</Qt4>
+ <Qt3>Qt::OrderedAlphaDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DiffuseAlphaDither</Qt4>
+ <Qt3>Qt::DiffuseAlphaDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::NoAlpha</Qt4>
+ <Qt3>Qt::NoAlpha</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dither_Mask</Qt4>
+ <Qt3>Qt::Dither_Mask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DiffuseDither</Qt4>
+ <Qt3>Qt::DiffuseDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::OrderedDither</Qt4>
+ <Qt3>Qt::OrderedDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ThresholdDither</Qt4>
+ <Qt3>Qt::ThresholdDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DitherMode_Mask</Qt4>
+ <Qt3>Qt::DitherMode_Mask</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AutoDither</Qt4>
+ <Qt3>Qt::AutoDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PreferDither</Qt4>
+ <Qt3>Qt::PreferDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AvoidDither</Qt4>
+ <Qt3>Qt::AvoidDither</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TransparentMode</Qt4>
+ <Qt3>Qt::TransparentMode</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::OpaqueMode</Qt4>
+ <Qt3>Qt::OpaqueMode</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PixelUnit</Qt4>
+ <Qt3>Qt::PixelUnit</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LoMetricUnit</Qt4>
+ <Qt3>Qt::LoMetricUnit</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::HiMetricUnit</Qt4>
+ <Qt3>Qt::HiMetricUnit</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LoEnglishUnit</Qt4>
+ <Qt3>Qt::LoEnglishUnit</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::HiEnglishUnit</Qt4>
+ <Qt3>Qt::HiEnglishUnit</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TwipsUnit</Qt4>
+ <Qt3>Qt::TwipsUnit</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MacStyle</Qt4>
+ <Qt3>Qt::MacStyle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WindowsStyle</Qt4>
+ <Qt3>Qt::WindowsStyle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Win3Style</Qt4>
+ <Qt3>Qt::Win3Style</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PMStyle</Qt4>
+ <Qt3>Qt::PMStyle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MotifStyle</Qt4>
+ <Qt3>Qt::MotifStyle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::META</Qt4>
+ <Qt3>Qt::META</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SHIFT</Qt4>
+ <Qt3>Qt::SHIFT</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::CTRL</Qt4>
+ <Qt3>Qt::CTRL</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ALT</Qt4>
+ <Qt3>Qt::ALT</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MODIFIER_MASK</Qt4>
+ <Qt3>Qt::MODIFIER_MASK</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UNICODE_ACCEL</Qt4>
+ <Qt3>Qt::UNICODE_ACCEL</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Escape</Qt4>
+ <Qt3>Qt::Key_Escape</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Tab</Qt4>
+ <Qt3>Qt::Key_Tab</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Backtab</Qt4>
+ <Qt3>Qt::Key_Backtab</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BackTab</Qt4>
+ <Qt3>Qt::Key_BackTab</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Backspace</Qt4>
+ <Qt3>Qt::Key_Backspace</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BackSpace</Qt4>
+ <Qt3>Qt::Key_BackSpace</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Return</Qt4>
+ <Qt3>Qt::Key_Return</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Enter</Qt4>
+ <Qt3>Qt::Key_Enter</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Insert</Qt4>
+ <Qt3>Qt::Key_Insert</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Delete</Qt4>
+ <Qt3>Qt::Key_Delete</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Pause</Qt4>
+ <Qt3>Qt::Key_Pause</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Print</Qt4>
+ <Qt3>Qt::Key_Print</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_SysReq</Qt4>
+ <Qt3>Qt::Key_SysReq</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Clear</Qt4>
+ <Qt3>Qt::Key_Clear</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Home</Qt4>
+ <Qt3>Qt::Key_Home</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_End</Qt4>
+ <Qt3>Qt::Key_End</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Left</Qt4>
+ <Qt3>Qt::Key_Left</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Up</Qt4>
+ <Qt3>Qt::Key_Up</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Right</Qt4>
+ <Qt3>Qt::Key_Right</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Down</Qt4>
+ <Qt3>Qt::Key_Down</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Prior</Qt4>
+ <Qt3>Qt::Key_Prior</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_PageUp</Qt4>
+ <Qt3>Qt::Key_PageUp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Next</Qt4>
+ <Qt3>Qt::Key_Next</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_PageDown</Qt4>
+ <Qt3>Qt::Key_PageDown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Shift</Qt4>
+ <Qt3>Qt::Key_Shift</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Control</Qt4>
+ <Qt3>Qt::Key_Control</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Meta</Qt4>
+ <Qt3>Qt::Key_Meta</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Alt</Qt4>
+ <Qt3>Qt::Key_Alt</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_CapsLock</Qt4>
+ <Qt3>Qt::Key_CapsLock</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_NumLock</Qt4>
+ <Qt3>Qt::Key_NumLock</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ScrollLock</Qt4>
+ <Qt3>Qt::Key_ScrollLock</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F1</Qt4>
+ <Qt3>Qt::Key_F1</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F2</Qt4>
+ <Qt3>Qt::Key_F2</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F3</Qt4>
+ <Qt3>Qt::Key_F3</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F4</Qt4>
+ <Qt3>Qt::Key_F4</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F5</Qt4>
+ <Qt3>Qt::Key_F5</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F6</Qt4>
+ <Qt3>Qt::Key_F6</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F7</Qt4>
+ <Qt3>Qt::Key_F7</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F8</Qt4>
+ <Qt3>Qt::Key_F8</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F9</Qt4>
+ <Qt3>Qt::Key_F9</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F10</Qt4>
+ <Qt3>Qt::Key_F10</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F11</Qt4>
+ <Qt3>Qt::Key_F11</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F12</Qt4>
+ <Qt3>Qt::Key_F12</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F13</Qt4>
+ <Qt3>Qt::Key_F13</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F14</Qt4>
+ <Qt3>Qt::Key_F14</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F15</Qt4>
+ <Qt3>Qt::Key_F15</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F16</Qt4>
+ <Qt3>Qt::Key_F16</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F17</Qt4>
+ <Qt3>Qt::Key_F17</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F18</Qt4>
+ <Qt3>Qt::Key_F18</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F19</Qt4>
+ <Qt3>Qt::Key_F19</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F20</Qt4>
+ <Qt3>Qt::Key_F20</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F21</Qt4>
+ <Qt3>Qt::Key_F21</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F22</Qt4>
+ <Qt3>Qt::Key_F22</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F23</Qt4>
+ <Qt3>Qt::Key_F23</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F24</Qt4>
+ <Qt3>Qt::Key_F24</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F25</Qt4>
+ <Qt3>Qt::Key_F25</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F26</Qt4>
+ <Qt3>Qt::Key_F26</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F27</Qt4>
+ <Qt3>Qt::Key_F27</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F28</Qt4>
+ <Qt3>Qt::Key_F28</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F29</Qt4>
+ <Qt3>Qt::Key_F29</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F30</Qt4>
+ <Qt3>Qt::Key_F30</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F31</Qt4>
+ <Qt3>Qt::Key_F31</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F32</Qt4>
+ <Qt3>Qt::Key_F32</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F33</Qt4>
+ <Qt3>Qt::Key_F33</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F34</Qt4>
+ <Qt3>Qt::Key_F34</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F35</Qt4>
+ <Qt3>Qt::Key_F35</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Super_L</Qt4>
+ <Qt3>Qt::Key_Super_L</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Super_R</Qt4>
+ <Qt3>Qt::Key_Super_R</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Menu</Qt4>
+ <Qt3>Qt::Key_Menu</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Hyper_L</Qt4>
+ <Qt3>Qt::Key_Hyper_L</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Hyper_R</Qt4>
+ <Qt3>Qt::Key_Hyper_R</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Help</Qt4>
+ <Qt3>Qt::Key_Help</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Direction_L</Qt4>
+ <Qt3>Qt::Key_Direction_L</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Direction_R</Qt4>
+ <Qt3>Qt::Key_Direction_R</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Space</Qt4>
+ <Qt3>Qt::Key_Space</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Any</Qt4>
+ <Qt3>Qt::Key_Any</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Exclam</Qt4>
+ <Qt3>Qt::Key_Exclam</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_QuoteDbl</Qt4>
+ <Qt3>Qt::Key_QuoteDbl</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_NumberSign</Qt4>
+ <Qt3>Qt::Key_NumberSign</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Dollar</Qt4>
+ <Qt3>Qt::Key_Dollar</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Percent</Qt4>
+ <Qt3>Qt::Key_Percent</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ampersand</Qt4>
+ <Qt3>Qt::Key_Ampersand</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Apostrophe</Qt4>
+ <Qt3>Qt::Key_Apostrophe</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ParenLeft</Qt4>
+ <Qt3>Qt::Key_ParenLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ParenRight</Qt4>
+ <Qt3>Qt::Key_ParenRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Asterisk</Qt4>
+ <Qt3>Qt::Key_Asterisk</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Plus</Qt4>
+ <Qt3>Qt::Key_Plus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Comma</Qt4>
+ <Qt3>Qt::Key_Comma</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Minus</Qt4>
+ <Qt3>Qt::Key_Minus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Period</Qt4>
+ <Qt3>Qt::Key_Period</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Slash</Qt4>
+ <Qt3>Qt::Key_Slash</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_0</Qt4>
+ <Qt3>Qt::Key_0</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_1</Qt4>
+ <Qt3>Qt::Key_1</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_2</Qt4>
+ <Qt3>Qt::Key_2</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_3</Qt4>
+ <Qt3>Qt::Key_3</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_4</Qt4>
+ <Qt3>Qt::Key_4</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_5</Qt4>
+ <Qt3>Qt::Key_5</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_6</Qt4>
+ <Qt3>Qt::Key_6</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_7</Qt4>
+ <Qt3>Qt::Key_7</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_8</Qt4>
+ <Qt3>Qt::Key_8</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_9</Qt4>
+ <Qt3>Qt::Key_9</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Colon</Qt4>
+ <Qt3>Qt::Key_Colon</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Semicolon</Qt4>
+ <Qt3>Qt::Key_Semicolon</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Less</Qt4>
+ <Qt3>Qt::Key_Less</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Equal</Qt4>
+ <Qt3>Qt::Key_Equal</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Greater</Qt4>
+ <Qt3>Qt::Key_Greater</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Question</Qt4>
+ <Qt3>Qt::Key_Question</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_At</Qt4>
+ <Qt3>Qt::Key_At</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_A</Qt4>
+ <Qt3>Qt::Key_A</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_B</Qt4>
+ <Qt3>Qt::Key_B</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_C</Qt4>
+ <Qt3>Qt::Key_C</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_D</Qt4>
+ <Qt3>Qt::Key_D</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_E</Qt4>
+ <Qt3>Qt::Key_E</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_F</Qt4>
+ <Qt3>Qt::Key_F</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_G</Qt4>
+ <Qt3>Qt::Key_G</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_H</Qt4>
+ <Qt3>Qt::Key_H</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_I</Qt4>
+ <Qt3>Qt::Key_I</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_J</Qt4>
+ <Qt3>Qt::Key_J</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_K</Qt4>
+ <Qt3>Qt::Key_K</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_L</Qt4>
+ <Qt3>Qt::Key_L</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_M</Qt4>
+ <Qt3>Qt::Key_M</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_N</Qt4>
+ <Qt3>Qt::Key_N</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_O</Qt4>
+ <Qt3>Qt::Key_O</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_P</Qt4>
+ <Qt3>Qt::Key_P</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Q</Qt4>
+ <Qt3>Qt::Key_Q</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_R</Qt4>
+ <Qt3>Qt::Key_R</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_S</Qt4>
+ <Qt3>Qt::Key_S</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_T</Qt4>
+ <Qt3>Qt::Key_T</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_U</Qt4>
+ <Qt3>Qt::Key_U</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_V</Qt4>
+ <Qt3>Qt::Key_V</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_W</Qt4>
+ <Qt3>Qt::Key_W</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_X</Qt4>
+ <Qt3>Qt::Key_X</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Y</Qt4>
+ <Qt3>Qt::Key_Y</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Z</Qt4>
+ <Qt3>Qt::Key_Z</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BracketLeft</Qt4>
+ <Qt3>Qt::Key_BracketLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Backslash</Qt4>
+ <Qt3>Qt::Key_Backslash</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BracketRight</Qt4>
+ <Qt3>Qt::Key_BracketRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_AsciiCircum</Qt4>
+ <Qt3>Qt::Key_AsciiCircum</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Underscore</Qt4>
+ <Qt3>Qt::Key_Underscore</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_QuoteLeft</Qt4>
+ <Qt3>Qt::Key_QuoteLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BraceLeft</Qt4>
+ <Qt3>Qt::Key_BraceLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Bar</Qt4>
+ <Qt3>Qt::Key_Bar</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BraceRight</Qt4>
+ <Qt3>Qt::Key_BraceRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_AsciiTilde</Qt4>
+ <Qt3>Qt::Key_AsciiTilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_nobreakspace</Qt4>
+ <Qt3>Qt::Key_nobreakspace</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_exclamdown</Qt4>
+ <Qt3>Qt::Key_exclamdown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_cent</Qt4>
+ <Qt3>Qt::Key_cent</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_sterling</Qt4>
+ <Qt3>Qt::Key_sterling</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_currency</Qt4>
+ <Qt3>Qt::Key_currency</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_yen</Qt4>
+ <Qt3>Qt::Key_yen</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_brokenbar</Qt4>
+ <Qt3>Qt::Key_brokenbar</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_section</Qt4>
+ <Qt3>Qt::Key_section</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_diaeresis</Qt4>
+ <Qt3>Qt::Key_diaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_copyright</Qt4>
+ <Qt3>Qt::Key_copyright</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ordfeminine</Qt4>
+ <Qt3>Qt::Key_ordfeminine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_guillemotleft</Qt4>
+ <Qt3>Qt::Key_guillemotleft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_notsign</Qt4>
+ <Qt3>Qt::Key_notsign</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_hyphen</Qt4>
+ <Qt3>Qt::Key_hyphen</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_registered</Qt4>
+ <Qt3>Qt::Key_registered</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_macron</Qt4>
+ <Qt3>Qt::Key_macron</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_degree</Qt4>
+ <Qt3>Qt::Key_degree</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_plusminus</Qt4>
+ <Qt3>Qt::Key_plusminus</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_twosuperior</Qt4>
+ <Qt3>Qt::Key_twosuperior</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_threesuperior</Qt4>
+ <Qt3>Qt::Key_threesuperior</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_acute</Qt4>
+ <Qt3>Qt::Key_acute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_mu</Qt4>
+ <Qt3>Qt::Key_mu</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_paragraph</Qt4>
+ <Qt3>Qt::Key_paragraph</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_periodcentered</Qt4>
+ <Qt3>Qt::Key_periodcentered</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_cedilla</Qt4>
+ <Qt3>Qt::Key_cedilla</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_onesuperior</Qt4>
+ <Qt3>Qt::Key_onesuperior</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_masculine</Qt4>
+ <Qt3>Qt::Key_masculine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_guillemotright</Qt4>
+ <Qt3>Qt::Key_guillemotright</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_onequarter</Qt4>
+ <Qt3>Qt::Key_onequarter</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_onehalf</Qt4>
+ <Qt3>Qt::Key_onehalf</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_threequarters</Qt4>
+ <Qt3>Qt::Key_threequarters</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_questiondown</Qt4>
+ <Qt3>Qt::Key_questiondown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Agrave</Qt4>
+ <Qt3>Qt::Key_Agrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Aacute</Qt4>
+ <Qt3>Qt::Key_Aacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Acircumflex</Qt4>
+ <Qt3>Qt::Key_Acircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Atilde</Qt4>
+ <Qt3>Qt::Key_Atilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Adiaeresis</Qt4>
+ <Qt3>Qt::Key_Adiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Aring</Qt4>
+ <Qt3>Qt::Key_Aring</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_AE</Qt4>
+ <Qt3>Qt::Key_AE</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ccedilla</Qt4>
+ <Qt3>Qt::Key_Ccedilla</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Egrave</Qt4>
+ <Qt3>Qt::Key_Egrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Eacute</Qt4>
+ <Qt3>Qt::Key_Eacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ecircumflex</Qt4>
+ <Qt3>Qt::Key_Ecircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ediaeresis</Qt4>
+ <Qt3>Qt::Key_Ediaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Igrave</Qt4>
+ <Qt3>Qt::Key_Igrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Iacute</Qt4>
+ <Qt3>Qt::Key_Iacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Icircumflex</Qt4>
+ <Qt3>Qt::Key_Icircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Idiaeresis</Qt4>
+ <Qt3>Qt::Key_Idiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ETH</Qt4>
+ <Qt3>Qt::Key_ETH</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ntilde</Qt4>
+ <Qt3>Qt::Key_Ntilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ograve</Qt4>
+ <Qt3>Qt::Key_Ograve</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Oacute</Qt4>
+ <Qt3>Qt::Key_Oacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ocircumflex</Qt4>
+ <Qt3>Qt::Key_Ocircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Otilde</Qt4>
+ <Qt3>Qt::Key_Otilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Odiaeresis</Qt4>
+ <Qt3>Qt::Key_Odiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_multiply</Qt4>
+ <Qt3>Qt::Key_multiply</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ooblique</Qt4>
+ <Qt3>Qt::Key_Ooblique</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ugrave</Qt4>
+ <Qt3>Qt::Key_Ugrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Uacute</Qt4>
+ <Qt3>Qt::Key_Uacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Ucircumflex</Qt4>
+ <Qt3>Qt::Key_Ucircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Udiaeresis</Qt4>
+ <Qt3>Qt::Key_Udiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Yacute</Qt4>
+ <Qt3>Qt::Key_Yacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_THORN</Qt4>
+ <Qt3>Qt::Key_THORN</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ssharp</Qt4>
+ <Qt3>Qt::Key_ssharp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_agrave</Qt4>
+ <Qt3>Qt::Key_agrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_aacute</Qt4>
+ <Qt3>Qt::Key_aacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_acircumflex</Qt4>
+ <Qt3>Qt::Key_acircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_atilde</Qt4>
+ <Qt3>Qt::Key_atilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_adiaeresis</Qt4>
+ <Qt3>Qt::Key_adiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_aring</Qt4>
+ <Qt3>Qt::Key_aring</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ae</Qt4>
+ <Qt3>Qt::Key_ae</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ccedilla</Qt4>
+ <Qt3>Qt::Key_ccedilla</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_egrave</Qt4>
+ <Qt3>Qt::Key_egrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_eacute</Qt4>
+ <Qt3>Qt::Key_eacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ecircumflex</Qt4>
+ <Qt3>Qt::Key_ecircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ediaeresis</Qt4>
+ <Qt3>Qt::Key_ediaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_igrave</Qt4>
+ <Qt3>Qt::Key_igrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_iacute</Qt4>
+ <Qt3>Qt::Key_iacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_icircumflex</Qt4>
+ <Qt3>Qt::Key_icircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_idiaeresis</Qt4>
+ <Qt3>Qt::Key_idiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_eth</Qt4>
+ <Qt3>Qt::Key_eth</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ntilde</Qt4>
+ <Qt3>Qt::Key_ntilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ograve</Qt4>
+ <Qt3>Qt::Key_ograve</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_oacute</Qt4>
+ <Qt3>Qt::Key_oacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ocircumflex</Qt4>
+ <Qt3>Qt::Key_ocircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_otilde</Qt4>
+ <Qt3>Qt::Key_otilde</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_odiaeresis</Qt4>
+ <Qt3>Qt::Key_odiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_division</Qt4>
+ <Qt3>Qt::Key_division</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_oslash</Qt4>
+ <Qt3>Qt::Key_oslash</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ugrave</Qt4>
+ <Qt3>Qt::Key_ugrave</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_uacute</Qt4>
+ <Qt3>Qt::Key_uacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ucircumflex</Qt4>
+ <Qt3>Qt::Key_ucircumflex</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_udiaeresis</Qt4>
+ <Qt3>Qt::Key_udiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_yacute</Qt4>
+ <Qt3>Qt::Key_yacute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_thorn</Qt4>
+ <Qt3>Qt::Key_thorn</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_ydiaeresis</Qt4>
+ <Qt3>Qt::Key_ydiaeresis</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Back</Qt4>
+ <Qt3>Qt::Key_Back</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Forward</Qt4>
+ <Qt3>Qt::Key_Forward</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Stop</Qt4>
+ <Qt3>Qt::Key_Stop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Refresh</Qt4>
+ <Qt3>Qt::Key_Refresh</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_VolumeDown</Qt4>
+ <Qt3>Qt::Key_VolumeDown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_VolumeMute</Qt4>
+ <Qt3>Qt::Key_VolumeMute</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_VolumeUp</Qt4>
+ <Qt3>Qt::Key_VolumeUp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BassBoost</Qt4>
+ <Qt3>Qt::Key_BassBoost</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BassUp</Qt4>
+ <Qt3>Qt::Key_BassUp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_BassDown</Qt4>
+ <Qt3>Qt::Key_BassDown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_TrebleUp</Qt4>
+ <Qt3>Qt::Key_TrebleUp</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_TrebleDown</Qt4>
+ <Qt3>Qt::Key_TrebleDown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_MediaPlay</Qt4>
+ <Qt3>Qt::Key_MediaPlay</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_MediaStop</Qt4>
+ <Qt3>Qt::Key_MediaStop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_MediaPrev</Qt4>
+ <Qt3>Qt::Key_MediaPrev</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_MediaNext</Qt4>
+ <Qt3>Qt::Key_MediaNext</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_MediaRecord</Qt4>
+ <Qt3>Qt::Key_MediaRecord</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_HomePage</Qt4>
+ <Qt3>Qt::Key_HomePage</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Favorites</Qt4>
+ <Qt3>Qt::Key_Favorites</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Search</Qt4>
+ <Qt3>Qt::Key_Search</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Standby</Qt4>
+ <Qt3>Qt::Key_Standby</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_OpenUrl</Qt4>
+ <Qt3>Qt::Key_OpenUrl</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchMail</Qt4>
+ <Qt3>Qt::Key_LaunchMail</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchMedia</Qt4>
+ <Qt3>Qt::Key_LaunchMedia</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch0</Qt4>
+ <Qt3>Qt::Key_Launch0</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch1</Qt4>
+ <Qt3>Qt::Key_Launch1</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch2</Qt4>
+ <Qt3>Qt::Key_Launch2</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch3</Qt4>
+ <Qt3>Qt::Key_Launch3</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch4</Qt4>
+ <Qt3>Qt::Key_Launch4</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch5</Qt4>
+ <Qt3>Qt::Key_Launch5</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch6</Qt4>
+ <Qt3>Qt::Key_Launch6</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch7</Qt4>
+ <Qt3>Qt::Key_Launch7</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch8</Qt4>
+ <Qt3>Qt::Key_Launch8</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_Launch9</Qt4>
+ <Qt3>Qt::Key_Launch9</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchA</Qt4>
+ <Qt3>Qt::Key_LaunchA</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchB</Qt4>
+ <Qt3>Qt::Key_LaunchB</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchC</Qt4>
+ <Qt3>Qt::Key_LaunchC</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchD</Qt4>
+ <Qt3>Qt::Key_LaunchD</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchE</Qt4>
+ <Qt3>Qt::Key_LaunchE</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_LaunchF</Qt4>
+ <Qt3>Qt::Key_LaunchF</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_MediaLast</Qt4>
+ <Qt3>Qt::Key_MediaLast</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Key_unknown</Qt4>
+ <Qt3>Qt::Key_unknown</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UpArrow</Qt4>
+ <Qt3>Qt::UpArrow</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DownArrow</Qt4>
+ <Qt3>Qt::DownArrow</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LeftArrow</Qt4>
+ <Qt3>Qt::LeftArrow</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::RightArrow</Qt4>
+ <Qt3>Qt::RightArrow</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::NoPen</Qt4>
+ <Qt3>Qt::NoPen</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SolidLine</Qt4>
+ <Qt3>Qt::SolidLine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DashLine</Qt4>
+ <Qt3>Qt::DashLine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DotLine</Qt4>
+ <Qt3>Qt::DotLine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DashDotLine</Qt4>
+ <Qt3>Qt::DashDotLine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DashDotDotLine</Qt4>
+ <Qt3>Qt::DashDotDotLine</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MPenStyle</Qt4>
+ <Qt3>Qt::MPenStyle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::FlatCap</Qt4>
+ <Qt3>Qt::FlatCap</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SquareCap</Qt4>
+ <Qt3>Qt::SquareCap</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::RoundCap</Qt4>
+ <Qt3>Qt::RoundCap</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MPenCapStyle</Qt4>
+ <Qt3>Qt::MPenCapStyle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MiterJoin</Qt4>
+ <Qt3>Qt::MiterJoin</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BevelJoin</Qt4>
+ <Qt3>Qt::BevelJoin</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::RoundJoin</Qt4>
+ <Qt3>Qt::RoundJoin</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::MPenJoinStyle</Qt4>
+ <Qt3>Qt::MPenJoinStyle</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::NoBrush</Qt4>
+ <Qt3>Qt::NoBrush</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SolidPattern</Qt4>
+ <Qt3>Qt::SolidPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dense1Pattern</Qt4>
+ <Qt3>Qt::Dense1Pattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dense2Pattern</Qt4>
+ <Qt3>Qt::Dense2Pattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dense3Pattern</Qt4>
+ <Qt3>Qt::Dense3Pattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dense4Pattern</Qt4>
+ <Qt3>Qt::Dense4Pattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dense5Pattern</Qt4>
+ <Qt3>Qt::Dense5Pattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dense6Pattern</Qt4>
+ <Qt3>Qt::Dense6Pattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Dense7Pattern</Qt4>
+ <Qt3>Qt::Dense7Pattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::HorPattern</Qt4>
+ <Qt3>Qt::HorPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::VerPattern</Qt4>
+ <Qt3>Qt::VerPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::CrossPattern</Qt4>
+ <Qt3>Qt::CrossPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BDiagPattern</Qt4>
+ <Qt3>Qt::BDiagPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::FDiagPattern</Qt4>
+ <Qt3>Qt::FDiagPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DiagCrossPattern</Qt4>
+ <Qt3>Qt::DiagCrossPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::CustomPattern</Qt4>
+ <Qt3>Qt::CustomPattern</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UI_General</Qt4>
+ <Qt3>Qt::UI_General</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UI_AnimateMenu</Qt4>
+ <Qt3>Qt::UI_AnimateMenu</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UI_FadeMenu</Qt4>
+ <Qt3>Qt::UI_FadeMenu</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UI_AnimateCombo</Qt4>
+ <Qt3>Qt::UI_AnimateCombo</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UI_AnimateTooltip</Qt4>
+ <Qt3>Qt::UI_AnimateTooltip</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UI_FadeTooltip</Qt4>
+ <Qt3>Qt::UI_FadeTooltip</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UI_AnimateToolBox</Qt4>
+ <Qt3>Qt::UI_AnimateToolBox</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ArrowCursor</Qt4>
+ <Qt3>Qt::ArrowCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UpArrowCursor</Qt4>
+ <Qt3>Qt::UpArrowCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::CrossCursor</Qt4>
+ <Qt3>Qt::CrossCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WaitCursor</Qt4>
+ <Qt3>Qt::WaitCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SizeVerCursor</Qt4>
+ <Qt3>Qt::SizeVerCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SizeHorCursor</Qt4>
+ <Qt3>Qt::SizeHorCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SizeBDiagCursor</Qt4>
+ <Qt3>Qt::SizeBDiagCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SizeFDiagCursor</Qt4>
+ <Qt3>Qt::SizeFDiagCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SizeAllCursor</Qt4>
+ <Qt3>Qt::SizeAllCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BlankCursor</Qt4>
+ <Qt3>Qt::BlankCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SplitVCursor</Qt4>
+ <Qt3>Qt::SplitVCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::SplitHCursor</Qt4>
+ <Qt3>Qt::SplitHCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PointingHandCursor</Qt4>
+ <Qt3>Qt::PointingHandCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ForbiddenCursor</Qt4>
+ <Qt3>Qt::ForbiddenCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::WhatsThisCursor</Qt4>
+ <Qt3>Qt::WhatsThisCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BusyCursor</Qt4>
+ <Qt3>Qt::BusyCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LastCursor</Qt4>
+ <Qt3>Qt::LastCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BitmapCursor</Qt4>
+ <Qt3>Qt::BitmapCursor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PlainText</Qt4>
+ <Qt3>Qt::PlainText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::RichText</Qt4>
+ <Qt3>Qt::RichText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AutoText</Qt4>
+ <Qt3>Qt::AutoText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LogText</Qt4>
+ <Qt3>Qt::LogText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AnchorName</Qt4>
+ <Qt3>Qt::AnchorName</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::AnchorHref</Qt4>
+ <Qt3>Qt::AnchorHref</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockUnmanaged</Qt4>
+ <Qt3>Qt::DockUnmanaged</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockTornOff</Qt4>
+ <Qt3>Qt::DockTornOff</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockTop</Qt4>
+ <Qt3>Qt::DockTop</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockBottom</Qt4>
+ <Qt3>Qt::DockBottom</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockRight</Qt4>
+ <Qt3>Qt::DockRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockLeft</Qt4>
+ <Qt3>Qt::DockLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::DockMinimized</Qt4>
+ <Qt3>Qt::DockMinimized</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Unmanaged</Qt4>
+ <Qt3>Qt::Unmanaged</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TornOff</Qt4>
+ <Qt3>Qt::TornOff</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Top</Qt4>
+ <Qt3>Qt::Top</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Bottom</Qt4>
+ <Qt3>Qt::Bottom</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Right</Qt4>
+ <Qt3>Qt::Right</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Left</Qt4>
+ <Qt3>Qt::Left</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::Minimized</Qt4>
+ <Qt3>Qt::Minimized</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TextDate</Qt4>
+ <Qt3>Qt::TextDate</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::ISODate</Qt4>
+ <Qt3>Qt::ISODate</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LocalDate</Qt4>
+ <Qt3>Qt::LocalDate</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::LocalTime</Qt4>
+ <Qt3>Qt::LocalTime</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::UTC</Qt4>
+ <Qt3>Qt::UTC</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::FixedColor</Qt4>
+ <Qt3>Qt::FixedColor</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::FixedPixmap</Qt4>
+ <Qt3>Qt::FixedPixmap</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::NoBackground</Qt4>
+ <Qt3>Qt::NoBackground</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteForeground</Qt4>
+ <Qt3>Qt::PaletteForeground</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteButton</Qt4>
+ <Qt3>Qt::PaletteButton</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteLight</Qt4>
+ <Qt3>Qt::PaletteLight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteMidlight</Qt4>
+ <Qt3>Qt::PaletteMidlight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteDark</Qt4>
+ <Qt3>Qt::PaletteDark</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteMid</Qt4>
+ <Qt3>Qt::PaletteMid</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteText</Qt4>
+ <Qt3>Qt::PaletteText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteBrightText</Qt4>
+ <Qt3>Qt::PaletteBrightText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteBase</Qt4>
+ <Qt3>Qt::PaletteBase</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteBackground</Qt4>
+ <Qt3>Qt::PaletteBackground</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteShadow</Qt4>
+ <Qt3>Qt::PaletteShadow</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteHighlight</Qt4>
+ <Qt3>Qt::PaletteHighlight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteHighlightedText</Qt4>
+ <Qt3>Qt::PaletteHighlightedText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteButtonText</Qt4>
+ <Qt3>Qt::PaletteButtonText</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteLink</Qt4>
+ <Qt3>Qt::PaletteLink</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::PaletteLinkVisited</Qt4>
+ <Qt3>Qt::PaletteLinkVisited</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::X11ParentRelative</Qt4>
+ <Qt3>Qt::X11ParentRelative</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::CaseSensitive</Qt4>
+ <Qt3>Qt::CaseSensitive</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TopLeft</Qt4>
+ <Qt3>Qt::TopLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::TopRight</Qt4>
+ <Qt3>Qt::TopRight</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BottomLeft</Qt4>
+ <Qt3>Qt::BottomLeft</Qt3>
+ </item>
+ <item Type="RenamedEnumvalue" >
+ <Qt4>Qt::BottomRight</Qt4>
+ <Qt3>Qt::BottomRight</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QApplication::ColorSpec</Qt4>
+ <Qt3>QApplication::ColorMode</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QCheckBox::ToggleState</Qt4>
+ <Qt3>QButton::ToggleState</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::CursorShape</Qt4>
+ <Qt3>QCursorShape</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QFile::Filters</Qt4>
+ <Qt3>QFile::FilterSpec</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QFile::Permission</Qt4>
+ <Qt3>QFile::PermissionSpec</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QFile::SortFlags</Qt4>
+ <Qt3>QFile::SortSpec</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QFile::Error</Qt4>
+ <Qt3>QFile::Status</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QFile::Permission</Qt4>
+ <Qt3>QFileInfo::PermissionSpec</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::Orientation</Qt4>
+ <Qt3>QGrid::Direction</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::Orientation</Qt4>
+ <Qt3>QGridWidget::Direction</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>qlonglong</Qt4>
+ <Qt3>QIODevice::Offset</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::AspectRatioMode</Qt4>
+ <Qt3>QImage::ScaleMode</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::AspectRatioMode</Qt4>
+ <Qt3>QSize::ScaleMode</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Q3Socket::Error</Qt4>
+ <Qt3>QSocket::Error</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Q3Socket::State</Qt4>
+ <Qt3>QSocket::State</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QStyle::SubControls</Qt4>
+ <Qt3>QStyle::SCFlags</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QStyle::State</Qt4>
+ <Qt3>QStyle::SFlags</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QTextStream</Qt4>
+ <Qt3>QTS</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QUriDrag</Qt4>
+ <Qt3>QUrlDrag</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::FocusPolicy</Qt4>
+ <Qt3>QWidget::FocusPolicy</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>qlonglong</Qt4>
+ <Qt3>Q_LLONG</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>qulonglong</Qt4>
+ <Qt3>Q_ULLONG</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::ToolBarDock</Qt4>
+ <Qt3>Qt::Dock</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QSysInfo::MacVersion</Qt4>
+ <Qt3>Qt::MacintoshVersion</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::TextFlag</Qt4>
+ <Qt3>Qt::TextFlags</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>QSysInfo::WinVersion</Qt4>
+ <Qt3>Qt::WindowsVersion</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::Orientation</Qt4>
+ <Qt3>Qt::Orientation</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::SortOrder</Qt4>
+ <Qt3>Qt::SortOrder</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::WindowState</Qt4>
+ <Qt3>Qt::WindowState</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::BGMode</Qt4>
+ <Qt3>Qt::BGMode</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::PaintUnit</Qt4>
+ <Qt3>Qt::PaintUnit</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::GUIStyle</Qt4>
+ <Qt3>Qt::GUIStyle</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::Modifier</Qt4>
+ <Qt3>Qt::Modifier</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::Key</Qt4>
+ <Qt3>Qt::Key</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::ArrowType</Qt4>
+ <Qt3>Qt::ArrowType</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::PenStyle</Qt4>
+ <Qt3>Qt::PenStyle</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::PenCapStyle</Qt4>
+ <Qt3>Qt::PenCapStyle</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::PenJoinStyle</Qt4>
+ <Qt3>Qt::PenJoinStyle</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::BrushStyle</Qt4>
+ <Qt3>Qt::BrushStyle</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::UIEffect</Qt4>
+ <Qt3>Qt::UIEffect</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::CursorShape</Qt4>
+ <Qt3>Qt::CursorShape</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::TextFormat</Qt4>
+ <Qt3>Qt::TextFormat</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::AnchorAttribute</Qt4>
+ <Qt3>Qt::AnchorAttribute</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::Dock</Qt4>
+ <Qt3>Qt::Dock</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::DateFormat</Qt4>
+ <Qt3>Qt::DateFormat</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::TimeSpec</Qt4>
+ <Qt3>Qt::TimeSpec</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::BackgroundMode</Qt4>
+ <Qt3>Qt::BackgroundMode</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::Corner</Qt4>
+ <Qt3>Qt::Corner</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::WFlags</Qt4>
+ <Qt3>Qt::WFlags</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::ToolBarDock</Qt4>
+ <Qt3>Qt::ToolBarDock</Qt3>
+ </item>
+ <item Type="RenamedType" >
+ <Qt4>Qt::HANDLE</Qt4>
+ <Qt3>Qt::HANDLE</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::color0</Qt4>
+ <Qt3>Qt::color0</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::color1</Qt4>
+ <Qt3>Qt::color1</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::black</Qt4>
+ <Qt3>Qt::black</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::white</Qt4>
+ <Qt3>Qt::white</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::darkGray</Qt4>
+ <Qt3>Qt::darkGray</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::gray</Qt4>
+ <Qt3>Qt::gray</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::lightGray</Qt4>
+ <Qt3>Qt::lightGray</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::red</Qt4>
+ <Qt3>Qt::red</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::green</Qt4>
+ <Qt3>Qt::green</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::blue</Qt4>
+ <Qt3>Qt::blue</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::cyan</Qt4>
+ <Qt3>Qt::cyan</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::magenta</Qt4>
+ <Qt3>Qt::magenta</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::yellow</Qt4>
+ <Qt3>Qt::yellow</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::darkRed</Qt4>
+ <Qt3>Qt::darkRed</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::darkGreen</Qt4>
+ <Qt3>Qt::darkGreen</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::darkBlue</Qt4>
+ <Qt3>Qt::darkBlue</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::darkCyan</Qt4>
+ <Qt3>Qt::darkCyan</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::darkMagenta</Qt4>
+ <Qt3>Qt::darkMagenta</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::darkYellow</Qt4>
+ <Qt3>Qt::darkYellow</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::ButtonState</Qt4>
+ <Qt3>Qt::ButtonState</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::TextFlags</Qt4>
+ <Qt3>Qt::TextFlags</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::ImageConversionFlags</Qt4>
+ <Qt3>Qt::ImageConversionFlags</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::arrowCursor</Qt4>
+ <Qt3>Qt::arrowCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::upArrowCursor</Qt4>
+ <Qt3>Qt::upArrowCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::crossCursor</Qt4>
+ <Qt3>Qt::crossCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::waitCursor</Qt4>
+ <Qt3>Qt::waitCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::ibeamCursor</Qt4>
+ <Qt3>Qt::ibeamCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::sizeVerCursor</Qt4>
+ <Qt3>Qt::sizeVerCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::sizeHorCursor</Qt4>
+ <Qt3>Qt::sizeHorCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::sizeBDiagCursor</Qt4>
+ <Qt3>Qt::sizeBDiagCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::sizeFDiagCursor</Qt4>
+ <Qt3>Qt::sizeFDiagCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::sizeAllCursor</Qt4>
+ <Qt3>Qt::sizeAllCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::blankCursor</Qt4>
+ <Qt3>Qt::blankCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::splitVCursor</Qt4>
+ <Qt3>Qt::splitVCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::splitHCursor</Qt4>
+ <Qt3>Qt::splitHCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::pointingHandCursor</Qt4>
+ <Qt3>Qt::pointingHandCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::forbiddenCursor</Qt4>
+ <Qt3>Qt::forbiddenCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>Qt::whatsThisCursor</Qt4>
+ <Qt3>Qt::whatsThisCursor</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>qPixmapFromMimeSource</Qt4>
+ <Qt3>QPixmap::fromMimeSource</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>QImageReader::supportedImageFormats</Qt4>
+ <Qt3>QImage::inputFormats</Qt3>
+ </item>
+ <item Type="RenamedQtSymbol" >
+ <Qt4>QImageWriter::supportedImageFormats</Qt4>
+ <Qt3>QImage::outputFormats</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>QPointer</Qt4>
+ <Qt3>QGuardedPtr</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3DeepCopy</Qt4>
+ <Qt3>QDeepCopy</Qt3>
+ </item>
+ <item Type="RenamedClass" >
+ <Qt4>Q3PtrCollection</Qt4>
+ <Qt3>QCollection</Qt3>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlFieldInfo</Class>
+ <Header>Q3SqlFieldInfo</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3TextStream</Class>
+ <Header>Q3TextStream</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QCloseEvent</Class>
+ <Header>QCloseEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QHelpEvent</Class>
+ <Header>QHelpEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QDragMoveEvent</Class>
+ <Header>QDragMoveEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QDropEvent</Class>
+ <Header>QDropEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QKeyEvent</Class>
+ <Header>QKeyEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QClipboardEvent</Class>
+ <Header>QClipboardEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QHideEvent</Class>
+ <Header>QHideEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QDragLeaveEvent</Class>
+ <Header>QDragLeaveEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QWhatsThisClickedEvent</Class>
+ <Header>QWhatsThisClickedEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QMoveEvent</Class>
+ <Header>QMoveEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QFileOpenEvent</Class>
+ <Header>QFileOpenEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QResizeEvent</Class>
+ <Header>QResizeEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QContextMenuEvent</Class>
+ <Header>QContextMenuEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QActionEvent</Class>
+ <Header>QActionEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QWSUpdateEvent</Class>
+ <Header>QWSUpdateEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QInputMethodEvent</Class>
+ <Header>QInputMethodEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QShortcutEvent</Class>
+ <Header>QShortcutEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QDragEnterEvent</Class>
+ <Header>QDragEnterEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QDragResponseEvent</Class>
+ <Header>QDragResponseEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QToolBarChangeEvent</Class>
+ <Header>QToolBarChangeEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QShowEvent</Class>
+ <Header>QShowEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QWSEvent</Class>
+ <Header>QWSEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QFocusEvent</Class>
+ <Header>QFocusEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QInputEvent</Class>
+ <Header>QInputEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QStatusTipEvent</Class>
+ <Header>QStatusTipEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QWheelEvent</Class>
+ <Header>QWheelEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QMouseEvent</Class>
+ <Header>QMouseEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QTabletEvent</Class>
+ <Header>QTabletEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QPaintEvent</Class>
+ <Header>QPaintEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QIconDragEvent</Class>
+ <Header>QIconDragEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QChildEvent</Class>
+ <Header>QChildEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QEvent</Class>
+ <Header>QEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QWinEventNotifier</Class>
+ <Header>QWinEventNotifier</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QTimerEvent</Class>
+ <Header>QTimerEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QEventLoop</Class>
+ <Header>QEventLoop</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QCustomEvent</Class>
+ <Header>QCustomEvent</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3PtrList</Class>
+ <Header>Q3PtrList</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3ValueList</Class>
+ <Header>Q3ValueList</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3MemArray</Class>
+ <Header>Q3MemArray</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3StrList</Class>
+ <Header>Q3StrList</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3Painter</Class>
+ <Header>Q3Painter</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QTextStream</Class>
+ <Header>QTextStream</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3Frame</Class>
+ <Header>Q3Frame</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QBoxLayout</Class>
+ <Header>QBoxLayout</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3VBoxLayout</Class>
+ <Header>Q3VBoxLayout</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3HBoxLayout</Class>
+ <Header>Q3HBoxLayout</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3GridLayout</Class>
+ <Header>Q3GridLayout</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3CString</Class>
+ <Header>Q3CString</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QPixmap</Class>
+ <Header>QPixmap</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QTranslator</Class>
+ <Header>QTranslator</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QLabel</Class>
+ <Header>QLabel</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QListBoxItem</Class>
+ <Header>QListBoxItem</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3Action</Class>
+ <Header>Q3Action</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3ActionGroup</Class>
+ <Header>Q3ActionGroup</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>qPixmapFromMimeSource</Class>
+ <Header>q3mimefactory.h</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlFieldInfo</Class>
+ <Header>Q3SqlFieldInfo</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlFieldInfoList</Class>
+ <Header>Q3SqlFieldInfoList</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlCursor</Class>
+ <Header>Q3SqlCursor</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlEditorFactory</Class>
+ <Header>Q3SqlEditorFactory</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlForm</Class>
+ <Header>Q3SqlForm</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlPropertyMap</Class>
+ <Header>Q3SqlPropertyMap</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlRecordInfo</Class>
+ <Header>Q3SqlRecordInfo</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3SqlSelectCursor</Class>
+ <Header>Q3SqlSelectCursor</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QSqlError</Class>
+ <Header>QSqlError</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QSqlQuery</Class>
+ <Header>QSqlQuery</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3PointArray</Class>
+ <Header>Q3PointArray</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3PopupMenu</Class>
+ <Header>Q3PopupMenu</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3Button</Class>
+ <Header>Q3Button</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3BoxLayout</Class>
+ <Header>Q3BoxLayout</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3Signal</Class>
+ <Header>Q3Signal</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QTextIStream</Class>
+ <Header>QTextIStream</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>QTextOStream</Class>
+ <Header>QTextOStream</Header>
+ </item>
+ <item Type="NeedHeader" >
+ <Class>Q3PtrCollection</Class>
+ <Header>Q3PtrCollection</Header>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qnamespace.h</Qt4>
+ <Qt3>qkeycode.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qobject.h</Qt4>
+ <Qt3>qobjectlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qwidget.h</Qt4>
+ <Qt3>qwidgetlist.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qapplication.h</Qt4>
+ <Qt3>qapp.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qmessagebox.h</Qt4>
+ <Qt3>qmsgbox.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qicon.h</Qt4>
+ <Qt3>qiconset.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qmatrix.h</Qt4>
+ <Qt3>qwmatrix.h</Qt3>
+ </item>
+ <item Type="RenamedHeader" >
+ <Qt4>qpointer.h</Qt4>
+ <Qt3>qguardedptr.h</Qt3>
+ </item>
+ <item Type="RenamedToken" >
+ <Qt4>q3InitNetworkProtocols</Qt4>
+ <Qt3>qInitNetworkProtocols</Qt3>
+ </item>
+ <item Type="RenamedToken" >
+ <Qt4>qSort</Qt4>
+ <Qt3>qHeapSort</Qt3>
+ </item>
+</Rules>
diff --git a/tools/porting/src/qt3headers0.qrc b/tools/porting/src/qt3headers0.qrc
new file mode 100644
index 0000000000..3fa52d8200
--- /dev/null
+++ b/tools/porting/src/qt3headers0.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file compress="9">qt3headers0.resource</file>
+ </qresource>
+</RCC> \ No newline at end of file
diff --git a/tools/porting/src/qt3headers0.resource b/tools/porting/src/qt3headers0.resource
new file mode 100644
index 0000000000..13be468d45
--- /dev/null
+++ b/tools/porting/src/qt3headers0.resource
Binary files differ
diff --git a/tools/porting/src/qt3headers1.qrc b/tools/porting/src/qt3headers1.qrc
new file mode 100644
index 0000000000..3178598750
--- /dev/null
+++ b/tools/porting/src/qt3headers1.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file compress="9">qt3headers1.resource</file>
+ </qresource>
+</RCC> \ No newline at end of file
diff --git a/tools/porting/src/qt3headers1.resource b/tools/porting/src/qt3headers1.resource
new file mode 100644
index 0000000000..e06d27048e
--- /dev/null
+++ b/tools/porting/src/qt3headers1.resource
Binary files differ
diff --git a/tools/porting/src/qt3headers2.qrc b/tools/porting/src/qt3headers2.qrc
new file mode 100644
index 0000000000..dad47b68d6
--- /dev/null
+++ b/tools/porting/src/qt3headers2.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file compress="9">qt3headers2.resource</file>
+ </qresource>
+</RCC> \ No newline at end of file
diff --git a/tools/porting/src/qt3headers2.resource b/tools/porting/src/qt3headers2.resource
new file mode 100644
index 0000000000..e44c81deee
--- /dev/null
+++ b/tools/porting/src/qt3headers2.resource
Binary files differ
diff --git a/tools/porting/src/qt3headers3.qrc b/tools/porting/src/qt3headers3.qrc
new file mode 100644
index 0000000000..77a6661acc
--- /dev/null
+++ b/tools/porting/src/qt3headers3.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource>
+ <file compress="9">qt3headers3.resource</file>
+ </qresource>
+</RCC> \ No newline at end of file
diff --git a/tools/porting/src/qt3headers3.resource b/tools/porting/src/qt3headers3.resource
new file mode 100644
index 0000000000..6d259f2139
--- /dev/null
+++ b/tools/porting/src/qt3headers3.resource
Binary files differ
diff --git a/tools/porting/src/qt3to4.pri b/tools/porting/src/qt3to4.pri
new file mode 100644
index 0000000000..c10c2f8b02
--- /dev/null
+++ b/tools/porting/src/qt3to4.pri
@@ -0,0 +1,68 @@
+DEPENDPATH += $$PWD
+INCLUDEPATH += $$PWD
+
+QT += XML
+HEADERS += $$PWD/smallobject.h \
+ $$PWD/tokenengine.h \
+ $$PWD/tokenizer.h \
+ $$PWD/rpplexer.h \
+ $$PWD/rpp.h \
+ $$PWD/rpptreewalker.h \
+ $$PWD/rpptreeevaluator.h \
+ $$PWD/rppexpressionbuilder.h \
+ $$PWD/preprocessorcontrol.h \
+ $$PWD/replacetoken.h \
+ $$PWD/tokenreplacements.h \
+ $$PWD/textreplacement.h \
+ $$PWD/portingrules.h \
+ $$PWD/qtsimplexml.h \
+ $$PWD/projectporter.h \
+ $$PWD/proparser.h \
+ $$PWD/fileporter.h \
+ $$PWD/logger.h \
+ $$PWD/tokens.h \
+ $$PWD/filewriter.h \
+ $$PWD/cpplexer.h \
+ $$PWD/smallobject.h \
+ $$PWD/ast.h \
+ $$PWD/errors.h \
+ $$PWD/parser.h \
+ $$PWD/translationunit.h \
+ $$PWD/treewalker.h \
+ $$PWD/semantic.h \
+ $$PWD/codemodel.h \
+ $$PWD/codemodelwalker.h \
+ $$PWD/codemodelattributes.h
+
+SOURCES += \
+ $$PWD/smallobject.cpp \
+ $$PWD/tokenengine.cpp \
+ $$PWD/tokenizer.cpp \
+ $$PWD/rpplexer.cpp \
+ $$PWD/rpp.cpp \
+ $$PWD/rpptreewalker.cpp \
+ $$PWD/rpptreeevaluator.cpp \
+ $$PWD/rppexpressionbuilder.cpp \
+ $$PWD/preprocessorcontrol.cpp \
+ $$PWD/replacetoken.cpp \
+ $$PWD/tokenreplacements.cpp \
+ $$PWD/textreplacement.cpp \
+ $$PWD/portingrules.cpp \
+ $$PWD/qtsimplexml.cpp \
+ $$PWD/projectporter.cpp \
+ $$PWD/proparser.cpp \
+ $$PWD/fileporter.cpp \
+ $$PWD/logger.cpp \
+ $$PWD/filewriter.cpp \
+ $$PWD/cpplexer.cpp \
+ $$PWD/ast.cpp \
+ $$PWD/errors.cpp \
+ $$PWD/parser.cpp \
+ $$PWD/translationunit.cpp \
+ $$PWD/treewalker.cpp \
+ $$PWD/semantic.cpp \
+ $$PWD/codemodel.cpp \
+ $$PWD/codemodelwalker.cpp \
+ $$PWD/codemodelattributes.cpp
+
+
diff --git a/tools/porting/src/qtsimplexml.cpp b/tools/porting/src/qtsimplexml.cpp
new file mode 100644
index 0000000000..7803d7dfdf
--- /dev/null
+++ b/tools/porting/src/qtsimplexml.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtsimplexml.h"
+#include <QDomDocument>
+
+QT_BEGIN_NAMESPACE
+
+QtSimpleXml::QtSimpleXml(const QString &name)
+{
+ valid = false;
+ n = name;
+ parent = 0;
+}
+
+QtSimpleXml &QtSimpleXml::operator [](int index)
+{
+ if (index < 0)
+ return *this;
+
+ if (index > children.size()) {
+ static QtSimpleXml NIL;
+ qWarning("QtSimpleXml::operator[], Out of range access: size is %i, index is %i",
+ children.size(), index);
+ return NIL;
+ }
+
+ if (index == children.size()) {
+ QtSimpleXml *item = new QtSimpleXml(QLatin1String("item"));
+ item->parent = this;
+ children.insert(item->name(), item);
+ return *item;
+ }
+
+ QMultiMap<QString, QtSimpleXml *>::Iterator it = children.begin();
+ while (index--) ++it;
+ return *it.value();
+}
+
+QtSimpleXml &QtSimpleXml::operator [](const QString &key)
+{
+ if (!children.contains(key)) {
+ QtSimpleXml *item = new QtSimpleXml(key);
+ item->parent = this;
+ children.insert(item->name(), item);
+ return *item;
+ }
+
+ return *children.find(key).value();
+}
+
+QtSimpleXml &QtSimpleXml::operator =(const QString &text)
+{
+ valid = true;
+ QtSimpleXml *p = parent;
+ while (p && !p->valid) {
+ p->valid = true;
+ p = p->parent;
+ }
+
+ s = text;
+ return *this;
+}
+
+QDomDocument QtSimpleXml::toDomDocument() const
+{
+ QDomDocument doc;
+ QString data = QLatin1String("version=\"1.0\" encoding=\"UTF-8\"");
+ doc.appendChild(doc.createProcessingInstruction(QLatin1String("xml"), data));
+
+ if (!valid)
+ return doc;
+
+ if(!s.isEmpty())
+ doc.appendChild(doc.createTextNode(s));
+
+ {
+ QMultiMap<QString, QtSimpleXml *>::ConstIterator it = children.constBegin();
+ for (; it != children.end(); ++it) {
+ QtSimpleXml *item = it.value();
+ if (item->valid) {
+ QDomNode node = item->toDomElement(&doc);
+ doc.appendChild(node);
+ }
+ }
+ }
+
+ return doc;
+}
+
+QDomElement QtSimpleXml::toDomElement(QDomDocument *doc) const
+{
+ QDomElement elem = doc->createElement(n);
+ QMap<QString, QString>::ConstIterator ita = attr.constBegin();
+ for (; ita != attr.constEnd(); ++ita)
+ elem.setAttribute(ita.key(), ita.value());
+
+ if(!s.isEmpty())
+ elem.appendChild(doc->createTextNode(s));
+
+ {
+ QMultiMap<QString, QtSimpleXml *>::ConstIterator it = children.constBegin();
+ for (; it != children.constEnd(); ++it) {
+ QtSimpleXml *item = it.value();
+ if (item->valid) {
+ QDomNode node = item->toDomElement(doc);
+ elem.appendChild(node);
+ }
+ }
+ }
+
+ return elem;
+}
+
+QString QtSimpleXml::name() const
+{
+ return n;
+}
+
+QString QtSimpleXml::text() const
+{
+ return s;
+}
+
+int QtSimpleXml::numChildren() const
+{
+ return children.count();
+}
+
+bool QtSimpleXml::isValid() const
+{
+ return valid;
+}
+
+void QtSimpleXml::setAttribute(const QString &key, const QString &value)
+{
+ attr.insert(key, QString(value));
+}
+
+QString QtSimpleXml::attribute(const QString &key)
+{
+ return attr[key];
+}
+
+bool QtSimpleXml::setContent(const QString &content)
+{
+ QDomDocument doc;
+ QString errorMsg;
+ int errorLine;
+ int errorColumn;
+
+ if (!doc.setContent(content, false, &errorMsg, &errorLine, &errorColumn)) {
+ errorStr = errorMsg;
+ errorStr += QLatin1String(" at ") + QString::number(errorLine) + QLatin1String(":") + QString::number(errorColumn);
+ return false;
+ }
+
+ parse(doc);
+ return true;
+}
+
+bool QtSimpleXml::setContent(QIODevice *device)
+{
+ QDomDocument doc;
+ QString errorMsg;
+ int errorLine;
+ int errorColumn;
+ if (!doc.setContent(device, false, &errorMsg, &errorLine, &errorColumn)) {
+ errorStr = errorMsg;
+ errorStr += QLatin1String(" at ") + QString::number(errorLine) + QLatin1String(":") + QString::number(errorColumn);
+ return false;
+ }
+
+ QDomNode child = doc.firstChild();
+ while (!child.isNull() && !child.isElement())
+ child = child.nextSibling();
+
+ while (!child.isNull()) {
+ QtSimpleXml *xmlNode = new QtSimpleXml;
+ xmlNode->parse(child);
+ xmlNode->parent=this;
+ children.insert(xmlNode->name(), xmlNode);
+ do {
+ child = child.nextSibling();
+ } while (!child.isNull() && !child.isElement());
+ }
+
+ return true;
+}
+
+
+void QtSimpleXml::parse(QDomNode node)
+{
+ // puts("parse");
+ if (node.isNull())
+ return;
+
+ valid = true;
+ n = node.nodeName();
+ QDomElement element = node.toElement();
+
+ QDomNamedNodeMap attrs = element.attributes();
+ for (int i = 0; i < (int) attrs.count(); ++i) {
+ QDomAttr attribute = attrs.item(i).toAttr();
+ attr.insert(attribute.name(), attribute.value());
+ }
+
+ if (element.firstChild().isText()) {
+ // printf("Got text %s\n", element.text().stripWhiteSpace().latin1());
+ s = element.text().trimmed();
+ return;
+ }
+
+ if (node.hasChildNodes()) {
+
+ // Skip to first element child
+ QDomNode child = node.firstChild();
+ while (!child.isNull() && !child.isElement())
+ child = child.nextSibling();
+
+ while (!child.isNull()) {
+ QtSimpleXml *xmlNode = new QtSimpleXml;
+ xmlNode->parse(child);
+ children.insert(xmlNode->name(), xmlNode);
+
+ node = node.nextSibling();
+
+ do {
+ child = child.nextSibling();
+ } while (!child.isNull() && !child.isElement());
+ }
+ }
+}
+
+QString QtSimpleXml::errorString() const
+{
+ return errorStr;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/qtsimplexml.h b/tools/porting/src/qtsimplexml.h
new file mode 100644
index 0000000000..b3d67326fa
--- /dev/null
+++ b/tools/porting/src/qtsimplexml.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTSIMPLEXML_H
+#define QTSIMPLEXML_H
+
+#include <QString>
+#include <QMultiMap>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QDomDocument;
+class QDomElement;
+class QDomNode;
+class QIODevice;
+
+class QtSimpleXml
+{
+public:
+ QtSimpleXml(const QString &name = QString());
+
+ QString name() const;
+ QString text() const;
+ int numChildren() const;
+ bool isValid() const;
+
+ const QtSimpleXml &operator [](int index) const;
+ QtSimpleXml &operator [](int index);
+ QtSimpleXml &operator [](const QString &key);
+ QtSimpleXml &operator =(const QString &text);
+
+ void setAttribute(const QString &key, const QString &value);
+ QString attribute(const QString &key);
+
+ bool setContent(const QString &content);
+ bool setContent(QIODevice *device);
+ QString errorString() const;
+
+ QDomDocument toDomDocument() const;
+ QDomElement toDomElement(QDomDocument *doc) const;
+private:
+ void parse(QDomNode node);
+
+ QtSimpleXml *parent;
+
+ QMultiMap<QString, QtSimpleXml *> children;
+ QMap<QString, QString> attr;
+
+ QString s;
+ QString n;
+ bool valid;
+
+ QString errorStr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/replacetoken.cpp b/tools/porting/src/replacetoken.cpp
new file mode 100644
index 0000000000..52757a1a65
--- /dev/null
+++ b/tools/porting/src/replacetoken.cpp
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "replacetoken.h"
+#include "tokenreplacements.h"
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Add an entry to the tokenRuleLookup map for each token replacement rule.
+*/
+ReplaceToken::ReplaceToken(const QList<TokenReplacement*> &tokenReplacementRules)
+:tokenReplacementRules(tokenReplacementRules)
+{
+ foreach (TokenReplacement* rep, tokenReplacementRules) {
+ QByteArray key = rep->getReplaceKey();
+ if(!key.isEmpty()) {
+ tokenRuleLookup.insert(key, rep);
+ }
+ }
+}
+
+TextReplacements ReplaceToken::getTokenTextReplacements(const TokenEngine::TokenContainer &container)
+{
+ TextReplacements textReplacements;
+
+ int t=0;
+ const int numTokens = container.count();
+ while(t < numTokens) {
+ QByteArray tokenText = container.text(t);
+ bool changed = false;
+
+ if(isPreprocessorDirective(tokenText)) {
+ foreach(TokenReplacement *tokenReplacementRule, tokenReplacementRules) {
+ if(!changed)
+ changed = tokenReplacementRule->doReplace(container, t, textReplacements);
+ if(changed)
+ break;
+ }
+ } else if (isInterestingToken(tokenText.trimmed())) {
+ foreach (TokenReplacement* value, tokenRuleLookup.values(tokenText)) {
+ changed = value->doReplace(container, t, textReplacements);
+ if(changed) {
+ goto end;
+ }
+ }
+ }
+ end:
+ ++t;
+ }
+ return textReplacements;
+}
+
+bool ReplaceToken::isInterestingToken(const QByteArray &text)
+{
+ return !(text.isEmpty() || text==";" || text=="(" || text==")" || text=="{" || text=="}" || text=="="
+ || text=="+=" || text=="-=" || text=="if" || text=="then" || text=="else"
+ );
+}
+
+bool ReplaceToken::isPreprocessorDirective(const QByteArray &token)
+{
+ return (token[0]=='#');
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/replacetoken.h b/tools/porting/src/replacetoken.h
new file mode 100644
index 0000000000..5df0575703
--- /dev/null
+++ b/tools/porting/src/replacetoken.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REPLACETOKEN_H
+#define REPLACETOKEN_H
+
+#include "tokenengine.h"
+#include "tokenreplacements.h"
+#include "textreplacement.h"
+#include <QList>
+#include <QMultiMap>
+
+QT_BEGIN_NAMESPACE
+
+class ReplaceToken
+{
+public:
+ ReplaceToken(const QList<TokenReplacement*> &tokenReplacementRules);
+ TextReplacements getTokenTextReplacements(const TokenEngine::TokenContainer &tokenContainer);
+private:
+ bool isInterestingToken(const QByteArray &token);
+ bool isPreprocessorDirective(const QByteArray &token);
+ QMultiMap<QByteArray, TokenReplacement*> tokenRuleLookup;
+ const QList<TokenReplacement*> tokenReplacementRules;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/rpp.cpp b/tools/porting/src/rpp.cpp
new file mode 100644
index 0000000000..e95138bea6
--- /dev/null
+++ b/tools/porting/src/rpp.cpp
@@ -0,0 +1,728 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rpp.h"
+#include "rppexpressionbuilder.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+
+namespace Rpp
+{
+
+Preprocessor::Preprocessor()
+ : lexerTokenIndex(0), numTokens(0)
+{
+
+}
+
+Source *Preprocessor::parse(const TokenEngine::TokenContainer &tokenContainer,
+ const QVector<Type> &tokenTypeList, TypedPool<Item> *memoryPool)
+{
+ m_memoryPool = memoryPool;
+ Source *m_source = createNode<Source>(m_memoryPool); //node whith no parent
+ m_tokenContainer = tokenContainer;
+ m_tokenTypeList = tokenTypeList;
+ lexerTokenIndex = 0;
+ numTokens = m_tokenContainer.count();
+
+ if(m_tokenContainer.count() != tokenTypeList.count()) {
+ emit error(QLatin1String("Error"), QLatin1String("Internal error in preprocessor: Number of tokens is not equal to number of types in type list"));
+ return m_source;
+ }
+
+ if(tokenTypeList.isEmpty()) {
+ // emit error("Warning:", "Trying to parse empty source file");
+ return m_source;
+ }
+ Q_ASSERT(m_source->toItemComposite());
+ parseGroup(m_source);
+
+ return m_source;
+}
+
+// group-part
+// group group-part
+bool Preprocessor::parseGroup(Item *group)
+{
+ Q_ASSERT(group->toItemComposite());
+ bool gotGroup = false;
+ while(lexerTokenIndex < numTokens) {
+ if (!parseGroupPart(group))
+ break;
+ gotGroup = true;
+ }
+ return gotGroup;
+}
+
+//if-section (# if / # ifdef / #ifndef )
+//control-line ( #include / etc )
+//# non-directive ( # text newline
+//text-line (text newline )
+bool Preprocessor::parseGroupPart(Item *group)
+{
+ //cout << "parse group part" << endl;
+ Q_ASSERT(group->toItemComposite());
+
+ //look up first significant token
+ Type token = lookAhead();
+ if(token == Token_eof)
+ return false;
+
+ //look for '#'
+ if(token != Token_preproc)
+ return parseTextLine(group);
+
+ //look up first significant token after the '#'
+ token = lookAheadSkipHash();
+ if(token == Token_eof)
+ return false;
+
+ // Check if we are at the end of a group. This is not an neccesarely an
+ // error, it happens when we reach an #endif for example.
+ if (token == Token_directive_elif || token == Token_directive_else ||
+ token == Token_directive_endif)
+ return false;
+
+ // if-section?
+ if(token == Token_directive_if || token == Token_directive_ifdef ||
+ token == Token_directive_ifndef)
+ return parseIfSection(group);
+
+ // control-line?
+ if (token == Token_directive_define)
+ return parseDefineDirective(group);
+ if (token == Token_directive_undef)
+ return parseUndefDirective(group);
+ if (token == Token_directive_include)
+ return parseIncludeDirective(group);
+ if (token == Token_directive_error)
+ return parseErrorDirective(group);
+ if (token == Token_directive_pragma)
+ return parsePragmaDirective(group);
+
+ return parseNonDirective(group);
+}
+
+// if-section -> if-group elif-groups[opt] else-group[opt] endif-line
+bool Preprocessor::parseIfSection(Item *group)
+{
+ // cout << "parse if section" << endl ;
+ Q_ASSERT(group->toItemComposite());
+ IfSection *ifSection = createNode<IfSection>(m_memoryPool, group);
+ group->toItemComposite()->add(ifSection);
+
+ if (!parseIfGroup(ifSection))
+ return false;
+
+ Type type = lookAheadSkipHash();
+ if(type == Token_directive_elif)
+ if(!parseElifGroups(ifSection))
+ return false;
+
+ type = lookAheadSkipHash();
+ if(type == Token_directive_else)
+ if(!parseElseGroup(ifSection))
+ return false;
+
+ return parseEndifLine(ifSection);
+}
+
+bool Preprocessor::parseNonDirective(Item *group)
+{
+ // cout << "parsenondirective" << endl;
+ Q_ASSERT(group->toItemComposite());
+ TokenSection tokenSection = readLine();
+ if(tokenSection.count() == 0)
+ return false;
+
+ NonDirective *nonDirective = createNode<NonDirective>(m_memoryPool, group);
+ group->toItemComposite()->add(nonDirective);
+ nonDirective->setTokenSection(tokenSection);
+ return true;
+}
+
+
+bool Preprocessor::parseTextLine(Item *group)
+{
+ //cout << "parsetextline" << endl;
+ Q_ASSERT(group->toItemComposite());
+ const TokenSection tokenSection = readLine();
+ // cout << tokenSection.fullText().constData() << endl;
+
+ if(tokenSection.count() == 0)
+ return false;
+
+ Text *text = createNode<Text>(m_memoryPool, group);
+ group->toItemComposite()->add(text);
+ text->setTokenSection(tokenSection);
+
+ // Create Token-derived nodes and atach to text
+ QVector<Token *> tokens;
+ tokens.reserve(tokenSection.count());
+ for (int t = 0; t < tokenSection.count(); ++t) {
+ Token *node = 0;
+ const int containerIndex = tokenSection.containerIndex(t);
+ switch(m_tokenTypeList.at(containerIndex)) {
+ case Token_identifier:
+ case Token_defined:
+ case Token_directive_if:
+ case Token_directive_elif:
+ case Token_directive_else:
+ case Token_directive_undef:
+ case Token_directive_endif:
+ case Token_directive_ifdef:
+ case Token_directive_ifndef:
+ case Token_directive_define:
+ case Token_directive_include:
+ node = createNode<IdToken>(m_memoryPool, text);
+ break;
+ case Token_line_comment:
+ node = createNode<LineComment>(m_memoryPool, text);
+ break;
+ case Token_multiline_comment:
+ node = createNode<MultiLineComment>(m_memoryPool, text);
+ break;
+ case Token_whitespaces:
+ case Token_char_literal:
+ case Token_string_literal:
+ default:
+ node = createNode<NonIdToken>(m_memoryPool, text);
+ break;
+ }
+ Q_ASSERT(node);
+ node->setToken(containerIndex);
+ tokens.append(node);
+ }
+
+ text->setTokens(tokens);
+
+ return true;
+}
+
+// if-group -> ifDirective
+// if-group -> ifdefDirevtive
+// if-group -> ifndefDirevtive
+bool Preprocessor::parseIfGroup(IfSection *ifSection)
+{
+ // cout << "parse if group" << endl;
+ Q_ASSERT(ifSection->toItemComposite());
+ bool result;
+ const Type type = lookAheadSkipHash();
+ if (type == Token_directive_ifdef) {
+ IfdefDirective *d = createNode<IfdefDirective>(m_memoryPool, ifSection);
+ result = parseIfdefLikeDirective(d);
+ ifSection->setIfGroup(d);
+ } else if (type == Token_directive_ifndef) {
+ IfndefDirective *d = createNode<IfndefDirective>(m_memoryPool, ifSection);
+ result = parseIfdefLikeDirective(d);
+ ifSection->setIfGroup(d);
+ } else if (type == Token_directive_if) {
+ IfDirective *d = createNode<IfDirective>(m_memoryPool, ifSection);
+ result = parseIfLikeDirective(d);
+ ifSection->setIfGroup(d);
+ } else {
+ result = false;
+ }
+ return result;
+}
+
+bool Preprocessor::parseElifGroups(IfSection *ifSection)
+{
+ //cout << "parse ElifGroups" << endl;
+ bool gotElif = false;
+ while(lookAheadSkipHash() == Token_directive_elif ) {
+ if (!parseElifGroup(ifSection))
+ break;
+ gotElif = true;
+ }
+ return gotElif;
+}
+
+bool Preprocessor::parseElifGroup(IfSection *ifSection)
+{
+ //cout << "parse ElifGroup" << endl;
+ ElifDirective *elifDirective = createNode<ElifDirective>(m_memoryPool, ifSection);
+ ifSection->addElifGroup(elifDirective);
+ return parseIfLikeDirective(elifDirective);
+}
+
+bool Preprocessor::parseElseGroup(IfSection *ifSection)
+{
+ //cout << "parse else group" << endl;
+ TokenSection tokenSection = readLine();
+ if(tokenSection.count() == 0)
+ return false;
+
+ ElseDirective *elseDirective = createNode<ElseDirective>(m_memoryPool, ifSection);
+ ifSection->setElseGroup(elseDirective);
+ elseDirective->setTokenSection(tokenSection);
+ parseGroup(elseDirective);
+ return true;
+}
+
+//# endif newline
+bool Preprocessor::parseEndifLine(IfSection *ifSection)
+{
+ //cout << "parse endifline" << endl;
+ TokenSection tokenSection = readLine();
+ if(tokenSection.count() == 0)
+ return false;
+
+ EndifDirective *endifDirective = createNode<EndifDirective>(m_memoryPool, ifSection);
+ ifSection->setEndifLine(endifDirective);
+ endifDirective->setTokenSection(tokenSection);
+
+ return true;
+}
+
+//parses an "ifdef-like" directive, like #ifdef and #ifndef :)
+//# ifdef identifier newline group[opt]
+bool Preprocessor::parseIfdefLikeDirective(IfdefLikeDirective *node)
+{
+ Q_ASSERT(node->toItemComposite());
+ const TokenSection tokenSection = readLine();
+ const QVector<int> cleanedLine = cleanTokenRange(tokenSection);
+
+ if(cleanedLine.count() < 3)
+ return false;
+
+ node->setTokenSection(tokenSection);
+ node->setIdentifier(TokenList(m_tokenContainer, QVector<int>() << cleanedLine.at(2)));
+ parseGroup(node);
+
+ return true;
+}
+
+//# if constant-expression newline group[opt]
+bool Preprocessor::parseIfLikeDirective(IfLikeDirective *node)
+{
+ //cout << "parse if-like directive" << endl;
+ Q_ASSERT(node->toItemComposite());
+ TokenSection tokenSection = readLine();
+ QVector<int> cleanedSection = cleanTokenRange(tokenSection);
+ if(cleanedSection.count() < 3)
+ return false;
+
+ cleanedSection.erase(cleanedSection.begin(), cleanedSection.begin() + 2); //remove # and if
+ cleanedSection.pop_back(); //remove endl;
+
+ const TokenList sectionList(m_tokenContainer, cleanedSection);
+ ExpressionBuilder expressionBuilder(sectionList, m_tokenTypeList, m_memoryPool);
+ Expression *expr = expressionBuilder.parse();
+ node->setTokenSection(tokenSection);
+ node->setExpression(expr);
+
+ parseGroup(node);
+ return true;
+}
+
+/*
+ # define identifier replacement-list new-line
+ # define identifier lparen identifier-list[opt] ) replacement-list new-line
+ # define identifier lparen ... ) replacement-list new-line
+ # define identifier lparen identifier-list, ... ) replacement-list new-line
+*/
+bool Preprocessor::parseDefineDirective(Item *group)
+{
+ Q_ASSERT(group->toItemComposite());
+ const TokenSection line = readLine();
+ const QVector<int> cleanedLine = cleanTokenRange(line);
+ if(cleanedLine.count() < 3)
+ return false;
+
+ // get identifier
+ const int identifier = cleanedLine.at(2); //skip "#" and "define"
+ DefineDirective *defineDirective = 0;
+ int replacementListStart;
+
+ // check if this is a macro function
+ if (cleanedLine.count() >= 4
+ && m_tokenContainer.text(cleanedLine.at(3)) == "("
+ && !isWhiteSpace(cleanedLine.at(3) - 1)) {
+ MacroFunctionDefinition *macro;
+ macro = createNode<MacroFunctionDefinition>(m_memoryPool, group);
+
+ int tokenIndex = 4; //point to first argument or ')'
+ QVector<int> macroParameterList;
+ while(tokenIndex < cleanedLine.count()) {
+ QByteArray currentText = m_tokenContainer.text(cleanedLine.at(tokenIndex));
+ ++tokenIndex;
+ if(currentText == ")")
+ break;
+ if(currentText == ",")
+ continue;
+ macroParameterList.append(cleanedLine.at(tokenIndex - 1));
+ }
+ macro->setParameters(TokenList(m_tokenContainer, macroParameterList));
+ defineDirective = macro;
+ replacementListStart = tokenIndex;
+ } else {
+ MacroDefinition *macro;
+ macro = createNode<MacroDefinition>(m_memoryPool, group);
+ defineDirective = macro;
+ replacementListStart = 3;
+ }
+ Q_ASSERT(defineDirective);
+
+ // This is a bit hackish.. we want the replacement list with whitepspace
+ // tokens, but cleanedLine() has already removed those. And we can't use
+ // the original line, because that may contain escaped newline tokens.
+ // So we remove the esacped newlines and search for the token number
+ // given by cleanedLine.at(replacementListStart)
+ QVector<int> replacementList;
+ const QVector<int> noEscNewline = cleanEscapedNewLines(line);
+ if (replacementListStart < cleanedLine.count()) {
+ const int cleanedLineReplacementListStart = cleanedLine.at(replacementListStart);
+ const int rListStart = noEscNewline.indexOf(cleanedLineReplacementListStart);
+ if (rListStart != -1) {
+ const int skipNewLineToken = 1;
+ for (int i = rListStart; i < noEscNewline.count() - skipNewLineToken; ++i) {
+ const int tokenContainerIndex = noEscNewline.at(i);
+ const Type type = m_tokenTypeList.at(tokenContainerIndex);
+ // Don't append comment tokens.
+ if (type != Token_line_comment && type != Token_multiline_comment) {
+ replacementList.append(tokenContainerIndex);
+
+ }
+ }
+ }
+ }
+
+ defineDirective->setTokenSection(line);
+ defineDirective->setIdentifier(TokenList(m_tokenContainer, QVector<int>() << identifier));
+ defineDirective->setReplacementList(TokenList(m_tokenContainer, replacementList));
+ group->toItemComposite()->add(defineDirective);
+ return true;
+}
+
+
+// # undef identifier newline
+bool Preprocessor::parseUndefDirective(Item *group)
+{
+ Q_ASSERT(group->toItemComposite());
+ const TokenSection tokenSection = readLine();
+ const QVector<int> cleanedLine = cleanTokenRange(tokenSection);
+
+ if(cleanedLine.count() < 3)
+ return false;
+
+ UndefDirective *undefDirective = createNode<UndefDirective>(m_memoryPool, group);
+ group->toItemComposite()->add(undefDirective);
+ undefDirective->setIdentifier(TokenList(m_tokenContainer, QVector<int>() << cleanedLine.at(2)));
+ undefDirective->setTokenSection(tokenSection);
+ return true;
+}
+
+//include pp-tokens new-line
+bool Preprocessor::parseIncludeDirective(Item *group)
+{
+ // cout << "parseIncludeDirective" << endl;
+ Q_ASSERT(group->toItemComposite());
+ TokenSection tokenSection = readLine();
+ if(tokenSection.count() == 0)
+ return false;
+
+ const TokenEngine::TokenContainer tokenContainer = tokenSection.tokenContainer(0);
+ IncludeDirective *includeDirective = createNode<IncludeDirective>(m_memoryPool, group);
+ group->toItemComposite()->add(includeDirective);
+ includeDirective->setTokenSection(tokenSection);
+
+ //remove whitepspace and comment tokens
+ TokenList tokenList(m_tokenContainer, cleanTokenRange(tokenSection));
+
+ //iterate through the tokens, look for a string literal or a '<'.
+ int tokenIndex = 0;
+ const int endIndex = tokenList.count();
+ while (tokenIndex < endIndex) {
+ const int containerTokenIndex = tokenList.containerIndex(tokenIndex);
+ if(m_tokenTypeList.at(containerTokenIndex) == Token_string_literal) {
+ QByteArray tokenText = tokenList.text(tokenIndex);
+ includeDirective->setFilename(tokenText.mid(1, tokenText.size() -2)); //remove quotes
+ includeDirective->setFilenameTokens(TokenEngine::TokenList(tokenContainer, QVector<int>() << containerTokenIndex));
+ includeDirective->setIncludeType(IncludeDirective::QuoteInclude);
+ break;
+ } else if(tokenList.text(tokenIndex) == "<") {
+ // We found a <, all following tokens until we read a
+ // > is a part of the file anme
+ QByteArray filename;
+ ++tokenIndex; //skip '<'
+ QVector<int> filenameTokens;
+ while(tokenIndex < endIndex) {
+ const QByteArray tokenText = tokenList.text(tokenIndex);
+ if(tokenText == ">")
+ break;
+ filenameTokens.append(tokenList.containerIndex(tokenIndex));
+ filename += tokenText;
+ ++tokenIndex;
+ }
+ if(tokenIndex < endIndex) {
+ includeDirective->setFilename(filename);
+ includeDirective->setFilenameTokens(TokenEngine::TokenList(tokenContainer, filenameTokens));
+ includeDirective->setIncludeType(IncludeDirective::AngleBracketInclude);
+ }
+ break;
+ }
+ ++tokenIndex;
+ }
+
+ return true;
+}
+
+//# error pp-tokens[opt] new-line
+bool Preprocessor::parseErrorDirective(Item *group)
+{
+ Q_ASSERT(group->toItemComposite());
+ TokenSection tokenSection = readLine();
+ if(tokenSection.count() == 0)
+ return false;
+
+ ErrorDirective *errorDirective = createNode<ErrorDirective>(m_memoryPool, group);
+ group->toItemComposite()->add(errorDirective);
+ errorDirective->setTokenSection(tokenSection);
+ return true;
+}
+
+//# pragma pp-tokens[opt] new-line
+bool Preprocessor::parsePragmaDirective(Item *group)
+{
+ Q_ASSERT(group->toItemComposite());
+ TokenSection tokenSection = readLine();
+ if(tokenSection.count() == 0)
+ return false;
+
+ PragmaDirective *pragmaDirective = createNode<PragmaDirective>(m_memoryPool, group);
+ group->toItemComposite()->add(pragmaDirective);
+ pragmaDirective->setTokenSection(tokenSection);
+ return true;
+}
+/*
+ Reads a preprocessor line from the source by advancing lexerTokenIndex and
+ returing a TokenSection containg the read line. Text lines separated by
+ an escaped newline are joined.
+*/
+TokenSection Preprocessor::readLine()
+{
+ const int startIndex = lexerTokenIndex;
+ bool gotNewline = false;
+
+ while(isValidIndex(lexerTokenIndex) && !gotNewline) {
+ if(m_tokenTypeList.at(lexerTokenIndex) == Token_newline) {
+ if (lexerTokenIndex == 0 || m_tokenTypeList.at(lexerTokenIndex-1) != '\\') {
+ gotNewline = true;
+ break;
+ }
+ }
+ ++lexerTokenIndex;
+ }
+
+ if(gotNewline)
+ ++lexerTokenIndex; //include newline
+ else
+ emit error(QLatin1String("Error"), QLatin1String("Unexpected end of source"));
+
+ return TokenSection(m_tokenContainer, startIndex, lexerTokenIndex - startIndex);
+}
+
+/*
+ Returns false if index is past the end of m_tokenContainer.
+*/
+inline bool Preprocessor::isValidIndex(const int index) const
+{
+ return (index < m_tokenContainer.count());
+}
+
+/*
+ Returns true if the token at index is a whitepsace token.
+*/
+inline bool Preprocessor::isWhiteSpace(const int index) const
+{
+ return (m_tokenTypeList.at(index) == Token_whitespaces);
+}
+
+/*
+ Looks ahead from lexerTokenIndex, returns the token type found at the first
+ token that is not a comment or whitespace token.
+*/
+Type Preprocessor::lookAhead() const
+{
+ const int index = skipWhiteSpaceAndComments();
+ if (index == -1)
+ return Token_eof;
+ return m_tokenTypeList.at(index);
+}
+/*
+ Looks ahead from lexerTokenIndex, returns the token type found at the first
+ token that is not a comment, whitespace or '#' token.
+*/
+Type Preprocessor::lookAheadSkipHash() const
+{
+ const int index = skipWhiteSpaceCommentsHash();
+ if (index == -1)
+ return Token_eof;
+ return m_tokenTypeList.at(index);
+}
+
+/*
+ Returns the index for the first token after lexerTokenIndex that is not a
+ whitespace or comment token.
+*/
+inline int Preprocessor::skipWhiteSpaceAndComments() const
+{
+ int index = lexerTokenIndex;
+ if(!isValidIndex(index))
+ return -1;
+ while(m_tokenTypeList.at(index) == Token_whitespaces
+ || m_tokenTypeList.at(index) == Token_comment
+ || m_tokenTypeList.at(index) == Token_line_comment
+ || m_tokenTypeList.at(index) == Token_multiline_comment ) {
+ ++index;
+ if(!isValidIndex(index))
+ return -1;
+ }
+ return index;
+}
+
+/*
+ Returns the index for the first token after lexerTokenIndex that is not a
+ whitespace, comment or '#' token.
+*/
+inline int Preprocessor::skipWhiteSpaceCommentsHash() const
+{
+ int index = lexerTokenIndex;
+ if(!isValidIndex(index))
+ return -1;
+ while(m_tokenTypeList.at(index) == Token_whitespaces
+ || m_tokenTypeList.at(index) == Token_comment
+ || m_tokenTypeList.at(index) == Token_line_comment
+ || m_tokenTypeList.at(index) == Token_multiline_comment
+ || m_tokenTypeList.at(index) == Token_preproc ) {
+ ++index;
+ if(!isValidIndex(index))
+ return -1;
+ }
+ return index;
+}
+
+/*
+ Removes escaped newlines from tokenSection. Both the escape token ('\')
+ and the newline token ('\n') are removed.
+*/
+QVector<int> Preprocessor::cleanEscapedNewLines(const TokenSection &tokenSection) const
+{
+ QVector<int> indexList;
+
+ int t = 0;
+ const int numTokens = tokenSection.count();
+ while (t < numTokens) {
+ const int containerIndex = tokenSection.containerIndex(t);
+ const int currentToken = t;
+ ++t;
+
+ //handle escaped newlines
+ if (tokenSection.text(currentToken) == "\\"
+ && currentToken + 1 < numTokens
+ && m_tokenTypeList.at(containerIndex + 1) == Token_newline)
+ continue;
+
+ indexList.append(containerIndex);
+ }
+ return indexList;
+}
+
+/*
+ Removes escaped newlines, whitespace and comment tokens from tokenSection
+*/
+QVector<int> Preprocessor::cleanTokenRange(const TokenSection &tokenSection) const
+{
+ QVector<int> indexList;
+
+ int t = 0;
+ const int numTokens = tokenSection.count();
+ while (t < numTokens) {
+ const int containerIndex = tokenSection.containerIndex(t);
+ const Type tokenType = m_tokenTypeList.at(containerIndex);
+ const int currentToken = t;
+ ++t;
+
+ if(tokenType == Token_whitespaces ||
+ tokenType == Token_line_comment ||
+ tokenType == Token_multiline_comment )
+ continue;
+
+ //handle escaped newlines
+ if(tokenSection.text(currentToken) == "\\" &&
+ currentToken + 1 < numTokens &&
+ m_tokenTypeList.at(containerIndex + 1) == Token_newline)
+ continue;
+
+ indexList.append(containerIndex);
+ }
+ return indexList;
+}
+/*
+ Returns the text for an Item node and all its children.
+*/
+QByteArray visitGetText(Item *item)
+{
+ QByteArray text;
+
+ text += item->text().fullText();
+
+ if(item->toItemComposite()) {
+ ItemComposite *composite = item->toItemComposite();
+ for (int i=0; i <composite->count(); ++i)
+ text += visitGetText(composite->item(i));
+ }
+
+ return text;
+}
+
+void Source::setFileName(const QString &fileName)
+{
+ m_fileName = fileName;
+}
+
+} // namespace Rpp
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/rpp.h b/tools/porting/src/rpp.h
new file mode 100644
index 0000000000..ae19e2783a
--- /dev/null
+++ b/tools/porting/src/rpp.h
@@ -0,0 +1,1072 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RPP_H
+#define RPP_H
+
+#include "tokenengine.h"
+#include "rpplexer.h"
+#include "tokens.h"
+#include "smallobject.h"
+#include <QHash>
+#include <QStringList>
+#include <QFile>
+#include <QByteArray>
+#include <QDir>
+#include <QMultiMap>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Rpp
+{
+
+struct Item;
+struct ItemComposite;
+
+struct Source;
+
+struct Directive;
+struct EmptyDirective;
+struct ErrorDirective;
+struct PragmaDirective;
+struct IncludeDirective;
+struct ConditionalDirective;
+struct DefineDirective;
+struct UndefDirective;
+struct LineDirective;
+struct NonDirective;
+
+struct IfSection;
+struct IfLikeDirective;
+struct IfDirective;
+struct ElifDirective;
+struct IfdefLikeDirective;
+struct IfdefDirective;
+struct IfndefDirective;
+struct ElseDirective;
+struct EndifDirective;
+
+struct Text;
+struct Token;
+struct TokenComposite;
+struct IdToken;
+struct NonIdToken;
+struct PastingToken;
+struct LineComment;
+struct MultiLineComment;
+struct WhiteSpace;
+
+struct MacroDefinition;
+struct MacroFunctionDefinition;
+struct MacroParameters;
+struct MacroParameter;
+
+struct Expression;
+struct UnaryExpression;
+struct BinaryExpression;
+struct ConditionalExpression;
+
+struct StringLiteral;
+struct IntLiteral;
+struct MacroReference;
+struct MacroFunctionReference;
+struct MacroArguments;
+struct MacroArgument;
+
+struct Item
+{
+ virtual ~Item() {}
+
+ virtual Item *parent() const = 0;
+
+ virtual ItemComposite *toItemComposite() const
+ { return 0; }
+
+ virtual Item *toItem() const
+ { return const_cast<Item *>(this); }
+
+ virtual Directive *toDirective() const
+ { return 0; }
+
+ virtual Text *toText() const
+ { return 0; }
+
+ virtual Token *toToken() const
+ { return 0; }
+
+ virtual Source *toSource() const
+ { return 0; }
+
+ virtual Expression *toExpression() const
+ { return 0; }
+
+ virtual IfSection *toIfSection() const
+ { return 0; }
+
+ // Text returns the original text for an item, e.g.
+ // the way it is found in the source
+ virtual TokenEngine::TokenSection text() const
+ { return TokenEngine::TokenSection(); }
+
+protected:
+ //using the default constructor for an item is
+ //only allowded for subclasses.
+ Item() {};
+};
+
+struct ItemComposite
+{
+ virtual ~ItemComposite() {}
+ virtual int count() const = 0;
+ virtual Item *item(int index) const = 0;
+ virtual void add(Item *item) = 0;
+/*
+ Classes that inherit ItemComposite must implement this
+ function themselves
+ virtual ItemComposite *toItemComposite() const
+ { return const_cast<ItemComposite *>(this); }
+*/
+};
+
+struct Directive: public Item
+{
+ inline Directive(Item *parent = 0)
+ : m_parent(parent), m_numLines(0) {}
+
+ virtual Item *parent() const
+ { return m_parent; }
+
+ inline void setParent(Item *parent)
+ { m_parent = parent;}
+
+ void setNumLines(const int numLines)
+ {m_numLines = numLines;}
+
+ virtual Directive *toDirective() const
+ { return const_cast<Directive *>(this); }
+
+ virtual EmptyDirective *toEmptyDirective() const
+ { return 0; }
+
+ virtual ErrorDirective *toErrorDirective() const
+ { return 0; }
+
+ virtual PragmaDirective *toPragmaDirective() const
+ { return 0; }
+
+ virtual IncludeDirective *toIncludeDirective() const
+ { return 0; }
+
+ virtual ConditionalDirective *toConditionalDirective() const
+ { return 0; }
+
+ virtual DefineDirective *toDefineDirective() const
+ { return 0; }
+
+ virtual UndefDirective *toUndefDirective() const
+ { return 0; }
+
+ virtual LineDirective *toLineDirective() const
+ { return 0; }
+
+ virtual NonDirective *toNonDirective() const
+ { return 0; }
+
+ void setTokenSection(TokenEngine::TokenSection section)
+ { m_tokenSection = section; }
+
+ TokenEngine::TokenSection text() const
+ { return m_tokenSection; }
+
+protected:
+ Item *m_parent;
+ int m_numLines;
+ TokenEngine::TokenSection m_tokenSection;
+};
+
+
+struct Token: public Item
+{
+ inline Token(Item *parent = 0)
+ : m_tokenIndex(0), m_parent(parent) {}
+
+ virtual Item *parent() const
+ { return m_parent; }
+
+ virtual MacroArguments *toMacroArguments() const
+ { return 0; }
+
+ virtual IdToken *toIdToken() const
+ { return 0; }
+
+ virtual NonIdToken *toNonIdToken() const
+ { return 0; }
+
+ virtual LineComment *toLineComment() const
+ { return 0; }
+
+ virtual MultiLineComment *toMultiLineComment() const
+ { return 0; }
+
+ virtual WhiteSpace *toWhiteSpace() const
+ { return 0; }
+
+ virtual Token *toToken() const
+ { return const_cast<Token *>(this); }
+
+ void setToken(int tokenIndex)
+ { m_tokenIndex = tokenIndex;}
+
+ int index() const
+ { return m_tokenIndex; }
+
+protected:
+ int m_tokenIndex;
+ Item *m_parent;
+};
+
+struct Text: public Item
+{
+ inline Text(Item *parent = 0)
+ : m_parent(parent) {}
+
+ virtual Text *toText() const
+ { return const_cast<Text *>(this); }
+
+ virtual Item *parent() const
+ { return m_parent; }
+
+ void setTokenSection(TokenEngine::TokenSection tokenSection)
+ {m_tokenSection = tokenSection; }
+
+ TokenEngine::TokenSection text() const
+ { return m_tokenSection; }
+
+ QVector<TokenEngine::TokenSection> cleanedText() const
+ { return m_cleanedSection; }
+
+ void setTokens( const QVector<Token *> &tokens )
+ { m_tokens = tokens; }
+
+ void addToken(Token *token)
+ {m_tokens.append(token);}
+
+ Token *token(int index) const
+ {return m_tokens.at(index);}
+
+ inline int count() const
+ {return m_tokens.count();}
+
+ QVector<Token *> tokenList() const
+ { return m_tokens; }
+
+protected:
+ Item *m_parent;
+ TokenEngine::TokenSection m_tokenSection; // all tokens
+ QVector<TokenEngine::TokenSection> m_cleanedSection; //comments removed
+ QVector<Token *> m_tokens;
+};
+
+struct IdToken: public Token
+{
+ inline IdToken(Item *parent = 0)
+ : Token(parent) {}
+
+ virtual IdToken *toIdToken() const
+ { return const_cast<IdToken *>(this); }
+};
+
+struct NonIdToken: public Token
+{
+ inline NonIdToken(Item *parent = 0)
+ : Token(parent) {}
+
+ virtual NonIdToken *toNonIdToken() const
+ { return const_cast< NonIdToken *>(this); }
+};
+
+struct LineComment : public NonIdToken
+{
+ inline LineComment(Item *parent = 0)
+ : NonIdToken(parent) {}
+
+ virtual LineComment *toLineComment() const
+ { return const_cast< LineComment *>(this); }
+};
+
+struct MultiLineComment: public NonIdToken
+{
+ inline MultiLineComment(Item *parent = 0)
+ : NonIdToken(parent) {}
+
+ virtual MultiLineComment *toMultiLineComment() const
+ { return const_cast< MultiLineComment *>(this); }
+protected:
+};
+
+struct WhiteSpace: public NonIdToken
+{
+ inline WhiteSpace(Item *parent = 0)
+ : NonIdToken(parent) {}
+
+ virtual WhiteSpace *toWhiteSpace() const
+ { return const_cast<WhiteSpace *>(this); }
+};
+
+struct Source: public Item, public ItemComposite
+{
+ Source(Item *parent = 0)
+ :m_parent(parent) {}
+
+ virtual Source *toSource() const
+ { return const_cast<Source *>(this); }
+
+ ItemComposite *toItemComposite() const
+ { return const_cast<Source *>(this); }
+
+ virtual int count() const
+ { return m_items.count(); }
+
+ virtual Item *item(int index) const
+ { return m_items.at(index); }
+
+ inline QString fileName() const
+ { return m_fileName; }
+
+ void setFileName(const QString &fileName);
+
+ virtual Item *parent() const
+ { return m_parent; }
+
+ inline void add(Item *item)
+ { m_items.append(item); }
+
+private:
+ Item *m_parent;
+ QVector<Item *> m_items;
+ QString m_fileName;
+};
+
+struct EmptyDirective: public Directive
+{
+ EmptyDirective(Item *item)
+ : Directive(item) {}
+
+ virtual EmptyDirective *toEmptyDirective() const
+ { return const_cast<EmptyDirective *>(this); }
+};
+
+struct ErrorDirective: public Directive
+{
+ ErrorDirective(Item *item)
+ : Directive(item) {}
+
+ virtual ErrorDirective *toErrorDirective() const
+ { return const_cast<ErrorDirective *>(this); }
+};
+
+struct PragmaDirective: public Directive
+{
+ PragmaDirective(Item *item)
+ : Directive(item) {}
+
+ virtual PragmaDirective *toPragmaDirective() const
+ { return const_cast<PragmaDirective *>(this); }
+};
+
+struct IncludeDirective: public Directive
+{
+ enum IncludeType {QuoteInclude, AngleBracketInclude};
+
+ IncludeDirective(Item *item)
+ : Directive(item), m_includeType(QuoteInclude) {}
+
+ IncludeDirective() : Directive() {}
+
+ virtual IncludeDirective *toIncludeDirective() const
+ { return const_cast<IncludeDirective *>(this); }
+
+ void setFilenameTokens(const TokenEngine::TokenList &filenameTokens)
+ { m_filenameTokens = filenameTokens; }
+
+ TokenEngine::TokenList filenameTokens() const
+ { return m_filenameTokens; }
+
+ void setFilename(const QByteArray &filename)
+ { m_filename = filename; }
+
+ QByteArray filename() const
+ { return m_filename;}
+
+ void setIncludeType(IncludeType includeType)
+ { m_includeType = includeType; }
+
+ IncludeType includeType() const
+ { return m_includeType; }
+private:
+ TokenEngine::TokenList m_filenameTokens;
+ QByteArray m_filename;
+ IncludeType m_includeType;
+};
+
+struct ConditionalDirective: public Directive, public ItemComposite
+{
+ inline ConditionalDirective(Item *parent = 0)
+ :Directive(parent) {}
+
+ virtual ConditionalDirective *toConditionalDirective() const
+ { return const_cast<ConditionalDirective *>(this); }
+
+ ItemComposite *toItemComposite() const
+ { return const_cast<ConditionalDirective *>(this); }
+
+ virtual IfDirective *toIfDirective() const
+ { return 0; }
+
+ virtual IfdefDirective *toIfdefDirective() const
+ { return 0; }
+
+ virtual IfndefDirective *toIfndefDirective() const
+ { return 0; }
+
+ virtual ElifDirective *toElifDirective() const
+ { return 0; }
+
+ virtual ElseDirective *toElseDirective() const
+ { return 0; }
+
+ int count() const
+ { return m_items.count(); }
+
+ Item *item(int index) const
+ { return m_items.at(index); }
+
+ void add(Item *item)
+ { m_items.append(item); }
+protected:
+ QVector<Item *> m_items;
+};
+
+struct IfSection: public Item, public ItemComposite
+{
+ IfSection(Item *parent)
+ :m_parent(parent), m_ifGroup(0), m_elseGroup(0), m_endifLine(0) {}
+
+ IfSection *toIfSection() const
+ { return const_cast<IfSection *>(this); }
+
+ ItemComposite *toItemComposite() const
+ { return const_cast<IfSection *>(this); }
+
+ void setParent(Item *parent)
+ { m_parent = parent; }
+
+ Item *parent() const
+ { return m_parent; }
+
+ void setIfGroup(ConditionalDirective *ifGroup)
+ { m_ifGroup = ifGroup; m_items.append(ifGroup); }
+
+ ConditionalDirective *ifGroup() const
+ { return m_ifGroup; }
+
+ void addElifGroup(ConditionalDirective *elifGroup)
+ { m_elifGroups.append(elifGroup); m_items.append(elifGroup); }
+
+ QVector<ConditionalDirective *> elifGroups() const
+ { return m_elifGroups; }
+
+ void setElseGroup(ConditionalDirective *elseGroup)
+ { m_elseGroup = elseGroup; m_items.append(elseGroup); }
+
+ ConditionalDirective *elseGroup() const
+ { return m_elseGroup; }
+
+ void setEndifLine(Directive *endifLine)
+ { m_endifLine = endifLine; m_items.append(endifLine); }
+
+ Directive *endifLine() const
+ { return m_endifLine; }
+
+ int count() const
+ { return m_items.count(); }
+
+ Item *item(int index) const
+ { return m_items.at(index);}
+
+ private:
+ void add(Item *item)
+ { Q_UNUSED(item); }
+
+ Item *m_parent;
+ QVector<Item *> m_items;
+ ConditionalDirective *m_ifGroup;
+ QVector<ConditionalDirective *> m_elifGroups;
+ ConditionalDirective *m_elseGroup;
+ Directive *m_endifLine;
+};
+
+struct Expression: public Item
+{
+ enum Operator
+ {
+ LtEqOp = 300,
+ GtEqOp,
+ LtOp,
+ GtOp,
+ EqOp,
+ NotEqOp,
+ OrOp,
+ AndOp,
+ LShiftOp,
+ RShiftOp
+ };
+
+ inline Expression(Item *parent = 0)
+ : m_parent(parent) {}
+
+ inline Expression *parentExpression() const
+ { return m_parent ? m_parent->toExpression() : 0; }
+
+ virtual Item *parent() const
+ { return m_parent; }
+
+ virtual Expression *toExpression() const
+ { return const_cast<Expression *>(this); }
+
+ virtual UnaryExpression *toUnaryExpression() const
+ { return 0; }
+
+ virtual BinaryExpression *toBinaryExpression() const
+ { return 0; }
+
+ virtual StringLiteral *toStringLiteral() const
+ { return 0; }
+
+ virtual IntLiteral *toIntLiteral() const
+ { return 0; }
+
+ virtual MacroReference *toMacroReference() const
+ { return 0; }
+
+ virtual MacroFunctionReference *toMacroFunctionReference() const
+ { return 0; }
+
+ virtual ConditionalExpression *toConditionalExpression() const
+ { return 0; }
+
+ int evaluate(bool *ok = 0);
+
+private:
+ Item *m_parent;
+};
+
+struct StringLiteral: public Expression
+{
+ inline StringLiteral(const QByteArray &value, Item *parent)
+ : Expression(parent), m_value(value) {}
+
+ QByteArray value() const
+ { return m_value; }
+
+ virtual StringLiteral *toStringLiteral() const
+ { return const_cast<StringLiteral *>(this); }
+
+private:
+ QByteArray m_value;
+};
+
+struct IntLiteral: public Expression
+{
+ inline IntLiteral(int value, Item *parent = 0)
+ : Expression(parent), m_value(value) {}
+
+ inline int value() const
+ { return m_value; }
+
+ virtual IntLiteral *toIntLiteral() const
+ { return const_cast<IntLiteral *>(this); }
+
+private:
+ int m_value;
+};
+
+struct MacroReference: public Expression
+{
+ enum Type {
+ DefinedRef, //#if defined(foo)
+ ValueRef
+ };
+
+ inline MacroReference(const TokenEngine::TokenList &name, Type type, Item *parent = 0)
+ : Expression(parent), m_type(type), m_name(name) {}
+
+ virtual MacroReference *toMacroReference() const
+ { return const_cast<MacroReference *>(this); }
+
+ inline TokenEngine::TokenList name() const
+ { return m_name; }
+
+ inline void setName(const TokenEngine::TokenList &name)
+ { m_name = name; }
+
+ inline int type() const
+ { return m_type; }
+
+private:
+ int m_type;
+ TokenEngine::TokenList m_name;
+};
+
+struct MacroFunctionReference: public Expression
+{
+ MacroFunctionReference(const QByteArray &name, Item *parent);
+
+ inline QByteArray name() const
+ { return m_name; }
+
+ inline void setName(const QByteArray &name)
+ { m_name = name; }
+
+ inline MacroArguments *arguments() const
+ { return m_arguments; }
+
+ virtual MacroFunctionReference *toMacroFunctionReference() const
+ { return const_cast<MacroFunctionReference *>(this); }
+
+private:
+ QByteArray m_name;
+ MacroArguments *m_arguments;
+};
+
+struct UnaryExpression: public Expression
+{
+ inline UnaryExpression(int op, Expression *e, Expression *parent = 0)
+ : Expression(parent), m_op(op), m_expression(e) {}
+
+ inline int op() const
+ { return m_op; }
+
+ inline Expression *expression() const
+ { return m_expression; }
+
+ virtual UnaryExpression *toUnaryExpression() const
+ { return const_cast<UnaryExpression *>(this); }
+
+private:
+ int m_op;
+ Expression *m_expression;
+};
+
+struct BinaryExpression: public Expression
+{
+ inline BinaryExpression(int op, Expression *left, Expression *right, Expression *parent = 0)
+ : Expression(parent),
+ m_op(op),
+ m_leftExpression(left),
+ m_rightExpression(right) {}
+
+ inline int op() const
+ { return m_op; }
+
+ inline Expression *leftExpression() const
+ { return m_leftExpression; }
+
+ inline Expression *rightExpression() const
+ { return m_rightExpression; }
+
+ virtual BinaryExpression *toBinaryExpression() const
+ { return const_cast<BinaryExpression *>(this); }
+
+private:
+ int m_op;
+ Expression *m_leftExpression;
+ Expression *m_rightExpression;
+};
+
+struct ConditionalExpression: public Expression
+{
+ inline ConditionalExpression(Expression *condition, Expression *left, Expression *right, Expression *parent = 0)
+ : Expression(parent),
+ m_condition(condition),
+ m_leftExpression(left),
+ m_rightExpression(right) {}
+
+ inline Expression *condition() const
+ { return m_condition; }
+
+ inline Expression *leftExpression() const
+ { return m_leftExpression; }
+
+ inline Expression *rightExpression() const
+ { return m_rightExpression; }
+
+ virtual ConditionalExpression *toConditionalExpression() const
+ { return const_cast<ConditionalExpression *>(this); }
+
+private:
+ Expression *m_condition;
+ Expression *m_leftExpression;
+ Expression *m_rightExpression;
+};
+
+
+struct IfLikeDirective: public ConditionalDirective
+{
+ inline IfLikeDirective(Item *parent = 0)
+ :ConditionalDirective(parent), m_expression(0) {}
+
+ void setExpression(Expression *expression)
+ { m_expression = expression; }
+
+ Expression *expression() const
+ { return m_expression; }
+
+protected:
+ Expression *m_expression;
+};
+
+struct IfDirective: public IfLikeDirective
+{
+ inline IfDirective(Item *parent = 0)
+ :IfLikeDirective(parent) {}
+
+ virtual IfDirective *toIfDirective() const
+ { return const_cast<IfDirective *>(this); }
+};
+
+
+struct ElifDirective: public IfLikeDirective
+{
+ inline ElifDirective(Item *parent = 0)
+ :IfLikeDirective(parent) {}
+
+ virtual ElifDirective *toElifDirective() const
+ { return const_cast<ElifDirective *>(this); }
+};
+
+struct IfdefLikeDirective: public ConditionalDirective
+{
+ inline IfdefLikeDirective(Item *parent = 0)
+ :ConditionalDirective(parent) {}
+
+ inline TokenEngine::TokenList identifier() const
+ { return m_identifier; }
+
+ inline void setIdentifier(const TokenEngine::TokenList &identifier)
+ { m_identifier = identifier; }
+protected:
+ TokenEngine::TokenList m_identifier;
+};
+
+struct IfdefDirective: public IfdefLikeDirective
+{
+ IfdefDirective(Item *parent)
+ :IfdefLikeDirective(parent) {}
+
+ virtual IfdefDirective *toIfdefDirective() const
+ { return const_cast<IfdefDirective *>(this); }
+};
+
+struct IfndefDirective: public IfdefLikeDirective
+{
+ inline IfndefDirective(Item *parent)
+ :IfdefLikeDirective(parent) {}
+
+ virtual IfndefDirective *toIfndefDirective() const
+ { return const_cast<IfndefDirective *>(this); }
+};
+
+struct ElseDirective: public ConditionalDirective
+{
+ ElseDirective(Item *parent)
+ :ConditionalDirective(parent) {}
+
+ virtual ElseDirective *toElseDirective() const
+ { return const_cast<ElseDirective *>(this); }
+};
+
+struct EndifDirective : public Directive
+{
+ EndifDirective(Item *parent)
+ :Directive(parent) {}
+
+ EndifDirective *toEndifDirective() const
+ { return const_cast<EndifDirective *>(this); }
+};
+
+struct DefineDirective: public Directive
+{
+ DefineDirective(Item *parent)
+ : Directive(parent) {};
+
+ inline TokenEngine::TokenList identifier() const
+ { return m_identifier; }
+
+ inline void setIdentifier(TokenEngine::TokenList identifier)
+ { m_identifier = identifier; }
+
+ inline void setReplacementList(TokenEngine::TokenList replacementList)
+ { m_replacementList = replacementList; }
+
+ inline TokenEngine::TokenList replacementList() const
+ { return m_replacementList; }
+
+ virtual DefineDirective *toDefineDirective() const
+ { return const_cast<DefineDirective *>(this); }
+
+ virtual MacroDefinition *toMacroDefinition() const
+ { return 0; }
+
+ virtual MacroFunctionDefinition *toMacroFunctionDefinition() const
+ { return 0; }
+private:
+ TokenEngine::TokenList m_identifier;
+ TokenEngine::TokenList m_replacementList;
+};
+
+struct MacroDefinition: public DefineDirective
+{
+ MacroDefinition(Item *parent)
+ : DefineDirective(parent) {};
+
+ virtual MacroDefinition *toMacroDefinition() const
+ { return const_cast<MacroDefinition *>(this); }
+};
+
+struct MacroFunctionDefinition: public DefineDirective
+{
+ MacroFunctionDefinition(Item *parent)
+ : DefineDirective(parent) {}
+
+ virtual MacroFunctionDefinition *toMacroFunctionDefinition() const
+ { return const_cast<MacroFunctionDefinition *>(this); }
+
+ void setParameters(TokenEngine::TokenList macroParameters)
+ { m_parameters = macroParameters;}
+
+ inline TokenEngine::TokenList parameters() const
+ { return m_parameters; }
+
+private:
+ TokenEngine::TokenList m_parameters;
+};
+
+struct MacroParameter: public Item
+{
+ inline MacroParameter(Item *parent)
+ : m_parent(parent) {}
+
+ inline QByteArray name() const
+ { return m_name; }
+
+ inline void setName(const QByteArray &name)
+ { m_name = name; }
+
+ virtual Item *parent() const
+ { return m_parent; }
+
+private:
+ Item *m_parent;
+ QByteArray m_name;
+};
+
+struct MacroParameters: public Item, public ItemComposite
+{
+ MacroParameters(MacroFunctionDefinition *parent)
+ : m_parent(parent) {}
+
+ ItemComposite *toItemComposite() const
+ { return const_cast<MacroParameters *>(this); }
+
+ virtual Item *parent() const
+ { return m_parent; }
+
+ virtual int count() const
+ { return m_items.count(); }
+
+ virtual Item *item(int index) const
+ { return m_items.at(index); }
+
+ void addParameter(MacroParameter *param)
+ { Q_ASSERT(param->parent() == this); m_items.append(param); }
+
+ int indexOf(const QByteArray &param) const
+ {
+ for (int i=0; i<m_items.count(); ++i) {
+ // cout <<"checking |" << param.constData() << "| against |" << m_items.at(i)->name().constData() <<"|" << endl;
+ if (m_items.at(i)->name() == param)
+ return i;
+ }
+ return -1;
+ }
+
+ inline bool contains(const QByteArray &param) const
+ { return indexOf(param) != -1; }
+/*
+ void add(const QByteArray &param)
+ {
+ MacroParameter *p = createNode<MacroParameter>(this);
+ p->setName(param);
+ addParameter(p);
+ }
+*/
+private:
+ MacroFunctionDefinition *m_parent;
+ QVector<MacroParameter*> m_items;
+};
+
+struct UndefDirective: public Directive
+{
+ UndefDirective(Item *parent)
+ :Directive(parent) {}
+
+ inline TokenEngine::TokenList identifier() const
+ { return m_identifier; }
+
+ inline void setIdentifier(const TokenEngine::TokenList &identifier)
+ { m_identifier = identifier; }
+
+ virtual UndefDirective *toUndefDirective() const
+ { return const_cast<UndefDirective *>(this); }
+private:
+ TokenEngine::TokenList m_identifier;
+};
+
+struct LineDirective: public Directive
+{
+ LineDirective(Item *parent)
+ :Directive(parent) {}
+
+ virtual LineDirective *toLineDirective() const
+ { return const_cast<LineDirective *>(this); }
+};
+
+struct NonDirective: public Directive
+{
+ NonDirective(Item *parent)
+ :Directive(parent) {}
+
+ virtual NonDirective *toNonDirective() const
+ { return const_cast<NonDirective *>(this); }
+};
+
+class Preprocessor : public QObject
+{
+Q_OBJECT
+public:
+ Preprocessor();
+ Source *parse(const TokenEngine::TokenContainer &tokenContainer,
+ const QVector<Type> &tokenTypeList, TypedPool<Item> *memoryPool);
+signals:
+ void error(const QString type, const QString message);
+private:
+ bool parseGroup(Item *node);
+ bool parseGroupPart(Item *node);
+
+ bool parseIfSection(Item *node);
+ bool parseNonDirective(Item *node);
+ bool parseTextLine(Item *node);
+
+ bool parseIfGroup(IfSection *node);
+ bool parseElifGroups(IfSection *node);
+ bool parseElifGroup(IfSection *node);
+ bool parseElseGroup(IfSection *node);
+ bool parseEndifLine(IfSection *node);
+
+ bool parseIfdefLikeDirective(IfdefLikeDirective *node);
+ bool parseIfLikeDirective(IfLikeDirective *node);
+
+ bool parseDefineDirective(Item *node);
+ bool parseUndefDirective(Item *node);
+ bool parseIncludeDirective(Item *node);
+ bool parseErrorDirective(Item *node);
+ bool parsePragmaDirective(Item*node);
+
+ TokenEngine::TokenSection readLine();
+ inline bool isValidIndex(const int index) const;
+ inline bool isWhiteSpace(const int index) const;
+ Type lookAhead() const;
+ Type lookAheadSkipHash() const;
+ inline int skipWhiteSpaceAndComments() const;
+ inline int skipWhiteSpaceCommentsHash() const;
+ QVector<int> cleanEscapedNewLines(const TokenEngine::TokenSection &tokenSection) const;
+ QVector<int> cleanTokenRange(const TokenEngine::TokenSection &tokenSection) const;
+
+ Source *m_source;
+ TokenEngine::TokenContainer m_tokenContainer;
+ QVector<Type> m_tokenTypeList;
+ TypedPool<Item> *m_memoryPool;
+ int lexerTokenIndex;
+ int numTokens;
+};
+
+/*
+ T must be a subclass of Item, parent must implment
+ the ItemComposite interface
+*/
+template <typename T>
+T *createNode(TypedPool<Item> *memPool, Item *parent)
+{
+ Q_ASSERT(parent);
+ T* node = new (memPool->allocate(sizeof(T))) T(parent);
+ Q_ASSERT(node);
+ return node;
+}
+
+template <typename T>
+T *createNode(TypedPool<Item> *memPool)
+{
+ T* node = new (memPool->allocate(sizeof(T))) T(0);
+ Q_ASSERT(node);
+ return node;
+}
+
+
+QByteArray visitGetText(Item *item);
+
+} // namespace Rpp
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/rppexpressionbuilder.cpp b/tools/porting/src/rppexpressionbuilder.cpp
new file mode 100644
index 0000000000..6695924cd4
--- /dev/null
+++ b/tools/porting/src/rppexpressionbuilder.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rppexpressionbuilder.h"
+#include "tokens.h"
+#include "rpp.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+namespace Rpp {
+
+ExpressionBuilder::ExpressionBuilder(const TokenList &tokenList, const QVector<Type> &typeList, TypedPool<Item> *memoryPool)
+:i(0)
+,m_tokenList(tokenList)
+,m_typeList(typeList)
+,m_memoryPool(memoryPool)
+{}
+
+Rpp::Expression *ExpressionBuilder::parse()
+{
+ if(unary_expression_lookup())
+ return conditional_expression();
+ else
+ return createIntLiteral(0);
+}
+Type ExpressionBuilder::next()
+{
+ if(!hasNext())
+ return Token_eof;
+ return typeAt(i++);
+}
+
+inline bool ExpressionBuilder::test(int token)
+{
+ if (i < m_tokenList.count() && typeAt(i) == token) {
+ ++i;
+ return true;
+ }
+ return false;
+}
+
+inline bool ExpressionBuilder::moreTokens(int delta)
+{
+ return (i + delta < m_tokenList.count());
+}
+
+inline Type ExpressionBuilder::lookup(int k)
+{
+ const int l = i - 1 + k;
+ return l < m_tokenList.count() ? typeAt(l) : Token_eof;
+}
+
+Expression *ExpressionBuilder::conditional_expression()
+{
+ Expression *value = logical_OR_expression();
+ if (test('?')) {
+ Expression *leftExpression = conditional_expression();
+ Expression *rightExpression;
+ if(test(':'))
+ rightExpression = conditional_expression();
+ else
+ rightExpression = createIntLiteral(0);
+ return createConditionalExpression(value, leftExpression, rightExpression);
+ }
+ return value;
+}
+
+Expression *ExpressionBuilder::logical_OR_expression()
+{
+ Expression *value = logical_AND_expression();
+ if (test(Token_or))
+ return createBinaryExpression(Expression::OrOp, value, logical_OR_expression());
+ return value;
+}
+
+Expression *ExpressionBuilder::logical_AND_expression()
+{
+ Expression *value = inclusive_OR_expression();
+ if (test(Token_and))
+ return createBinaryExpression(Expression::AndOp, value, logical_AND_expression());
+ return value;
+}
+
+Expression *ExpressionBuilder::inclusive_OR_expression()
+{
+ Expression *value = exclusive_OR_expression();
+ if (test('|'))
+ return createBinaryExpression('|', value, inclusive_OR_expression());
+ return value;
+}
+
+Expression *ExpressionBuilder::exclusive_OR_expression()
+{
+ Expression *value = AND_expression();
+ if (test('^'))
+ return createBinaryExpression('^', value, exclusive_OR_expression());
+ return value;
+}
+
+Expression *ExpressionBuilder::AND_expression()
+{
+ Expression *value = equality_expression();
+ if (test('&'))
+ return createBinaryExpression('&', value, AND_expression());
+ return value;
+}
+
+Expression *ExpressionBuilder::equality_expression()
+{
+ Expression *value = relational_expression();
+ switch (next()) {
+ case Token_eq:
+ return createBinaryExpression(Expression::EqOp, value, equality_expression());
+ case Token_not_eq:
+ return createBinaryExpression(Expression::NotEqOp, value, equality_expression());
+ default:
+ prev();
+ return value;
+ }
+}
+
+Expression *ExpressionBuilder::relational_expression()
+{
+ Expression *value = shift_expression();
+ switch (next()) {
+ case '<':
+ return createBinaryExpression('<', value, relational_expression());
+ case '>':
+ return createBinaryExpression('>', value, relational_expression());
+ case Token_leq:
+ return createBinaryExpression(Expression::LtEqOp, value, relational_expression());
+ case Token_geq:
+ return createBinaryExpression(Expression::GtEqOp, value, relational_expression());
+ default:
+ prev();
+ return value;
+ }
+}
+
+Expression *ExpressionBuilder::shift_expression()
+{
+ Expression *value = additive_expression();
+ switch (next()) {
+ case Token_left_shift:
+ return createBinaryExpression(Expression::LShiftOp, value, shift_expression());
+ case Token_right_shift:
+ return createBinaryExpression(Expression::RShiftOp, value, shift_expression());
+ default:
+ prev();
+ return value;
+ }
+}
+
+Expression *ExpressionBuilder::additive_expression()
+{
+ Expression *value = multiplicative_expression();
+ switch (next()) {
+ case '+':
+ return createBinaryExpression('+', value, additive_expression());
+ case '-':
+ return createBinaryExpression('-', value, additive_expression());
+ default:
+ prev();
+ return value;
+ }
+}
+
+Expression *ExpressionBuilder::multiplicative_expression()
+{
+ Expression *value = unary_expression();
+ switch (next()) {
+ case '*':
+ return createBinaryExpression('*', value, multiplicative_expression());
+ case '%':
+ return createBinaryExpression('%', value, multiplicative_expression());
+ case '/':
+ return createBinaryExpression('/', value, multiplicative_expression());
+ default:
+ prev();
+ return value;
+ };
+}
+
+Expression *ExpressionBuilder::unary_expression()
+{
+ switch (next()) {
+ case '+':
+ return createUnaryExpression('+', unary_expression());
+ case '-':
+ return createUnaryExpression('-', unary_expression());
+ case '!':
+ return createUnaryExpression('!', unary_expression());
+ case '~':
+ return createUnaryExpression('~', unary_expression());
+ case Token_defined:
+ {
+ int identifierIndex = 0;
+ if (test(Token_identifier)) {
+ identifierIndex = i - 1;
+ } else if (test('(')) {
+ if (test(Token_identifier))
+ identifierIndex = i -1;
+ test(')');
+ }
+ return createMacroReference(MacroReference::DefinedRef, createTokenList(identifierIndex));
+ }
+ default:
+ prev();
+ return primary_expression();
+ }
+}
+
+bool ExpressionBuilder::unary_expression_lookup()
+{
+ Type t = lookup();
+ return (primary_expression_lookup()
+ || t == '+'
+ || t == '-'
+ || t == '!'
+ || t == '~'
+ || t == Token_defined);
+}
+
+Expression *ExpressionBuilder::primary_expression()
+{
+ Expression *value;
+ if (test('(')) {
+ if (moreTokens(1))
+ value = conditional_expression();
+ else
+ value = createIntLiteral(0); // Syntax error.
+ test(')');
+ } else {
+ next();
+ bool ok;
+ int val = QString::fromLatin1(lexem()).toInt(&ok, 0);
+ if(ok)
+ value = createIntLiteral(val);
+ else
+ value = createMacroReference(MacroReference::ValueRef, createTokenList(i -1));
+ }
+ return value;
+}
+
+bool ExpressionBuilder::primary_expression_lookup()
+{
+ Type t = lookup();
+ return (t == Token_identifier
+ || t == Token_number_literal
+/* || t == PP_FLOATING_LITERAL*/
+ || t == '(');
+}
+/*
+ Creates a tokenList containing one token
+*/
+TokenList ExpressionBuilder::createTokenList(int tokenIndex) const
+{
+ return TokenList(m_tokenList.tokenContainer(tokenIndex),
+ QVector<int>() << m_tokenList.containerIndex(tokenIndex));
+}
+/*
+ Node cration helper functions
+*/
+UnaryExpression *ExpressionBuilder::createUnaryExpression(int op, Expression *expression)
+{
+ return new (m_memoryPool->allocate(sizeof(UnaryExpression))) UnaryExpression(op, expression);
+}
+
+BinaryExpression *ExpressionBuilder::createBinaryExpression(int op, Expression *leftExpresson, Expression *rightExpression)
+{
+ return new (m_memoryPool->allocate(sizeof(BinaryExpression))) BinaryExpression(op, leftExpresson, rightExpression);
+}
+
+ConditionalExpression *ExpressionBuilder::createConditionalExpression(Expression *condition, Expression *leftExpression, Expression *rightExpression)
+{
+ return new (m_memoryPool->allocate(sizeof(ConditionalExpression))) ConditionalExpression(condition, leftExpression, rightExpression);
+}
+
+MacroReference *ExpressionBuilder::createMacroReference(MacroReference::Type type, TokenEngine::TokenList token)
+{
+ return new (m_memoryPool->allocate(sizeof(MacroReference))) MacroReference(token, type);
+}
+
+IntLiteral *ExpressionBuilder::createIntLiteral(const int arg)
+{
+ return new (m_memoryPool->allocate(sizeof(IntLiteral))) IntLiteral(arg);
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/rppexpressionbuilder.h b/tools/porting/src/rppexpressionbuilder.h
new file mode 100644
index 0000000000..bca90b129d
--- /dev/null
+++ b/tools/porting/src/rppexpressionbuilder.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RPPEXPRESSIONBUILDER_H
+#define RPPEXPRESSIONBUILDER_H
+
+#include "tokens.h"
+#include "tokenengine.h"
+#include "smallobject.h"
+#include "rpp.h"
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+namespace Rpp {
+
+class ExpressionBuilder
+{
+public:
+ ExpressionBuilder(const TokenEngine::TokenList &tokenList, const QVector<Type> &typeList, TypedPool<Item> *memoryPool);
+ Rpp::Expression *parse();
+private:
+
+ inline bool hasNext() const { return (i < m_tokenList.count()); }
+ Type next();
+ bool test(int);
+ bool moreTokens(int delta);
+ inline void prev() {--i;}
+ Type lookup(int k = 1);
+ inline Type token() { return typeAt(i-1);}
+ inline QByteArray lexem() { return m_tokenList.text(i-1);}
+ inline Type typeAt(int t) { return m_typeList.at(m_tokenList.containerIndex(t));}
+
+ Expression *conditional_expression();
+ Expression *logical_OR_expression();
+ Expression *logical_AND_expression();
+ Expression *inclusive_OR_expression();
+ Expression *exclusive_OR_expression();
+ Expression *AND_expression();
+ Expression *equality_expression();
+ Expression *relational_expression();
+ Expression *shift_expression();
+ Expression *additive_expression();
+ Expression *multiplicative_expression();
+ Expression *unary_expression();
+ Expression *primary_expression();
+
+ bool unary_expression_lookup();
+ bool primary_expression_lookup();
+
+ UnaryExpression *createUnaryExpression(int op, Expression *expression);
+ BinaryExpression *createBinaryExpression(int op, Expression *leftExpresson, Expression *rightExpression);
+ ConditionalExpression *createConditionalExpression(Expression *condition, Expression *leftExpression, Expression *rightExpression);
+ MacroReference *createMacroReference(MacroReference::Type type, TokenEngine::TokenList token);
+ IntLiteral *createIntLiteral(const int arg);
+
+ TokenEngine::TokenList createTokenList(int tokenIndex) const;
+
+ int i;
+ TokenEngine::TokenList m_tokenList;
+ QVector<Type> m_typeList;
+ TypedPool<Item> *m_memoryPool;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/rpplexer.cpp b/tools/porting/src/rpplexer.cpp
new file mode 100644
index 0000000000..7a606bfc60
--- /dev/null
+++ b/tools/porting/src/rpplexer.cpp
@@ -0,0 +1,381 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rpplexer.h"
+#include <QChar>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+
+namespace Rpp {
+RppLexer::RppLexer()
+ : m_buffer(0), m_ptr(0), m_len(0)
+{
+ setupScanTable();
+}
+
+void RppLexer::setupScanTable()
+{
+ memset(s_attr_table, 0, 256);
+
+ for (int i=0; i<128; ++i) {
+ switch (i) {
+ case ':':
+ case '*':
+ case '%':
+ case '^':
+ case '=':
+ case '!':
+ case '&':
+ case '|':
+ case '+':
+ case '<':
+ case '>':
+ case '-':
+ case '.':
+ s_scan_table[i] = &RppLexer::scanOperator;
+ break;
+
+ case '\r':
+ case '\n':
+ s_scan_table[i] = &RppLexer::scanNewline;
+ break;
+
+ case '\'':
+ s_scan_table[i] = &RppLexer::scanCharLiteral;
+ break;
+
+ case '"':
+ s_scan_table[i] = &RppLexer::scanStringLiteral;
+ break;
+ case '#':
+ s_scan_table[i] = &RppLexer::scanPreprocessor;
+ break;
+
+ case '/':
+ s_scan_table[i] = &RppLexer::scanComment;
+ break;
+
+ default:
+ if (isspace(i)) {
+ s_scan_table[i] = &RppLexer::scanWhiteSpaces;
+ s_attr_table[i] |= A_Whitespace;
+ } else if (isalpha(i) || i == '_') {
+ s_scan_table[i] = &RppLexer::scanKeyword;
+ s_attr_table[i] |= A_Alpha;
+ } else if (isdigit(i)) {
+ s_scan_table[i] = &RppLexer::scanNumberLiteral;
+ s_attr_table[i] |= A_Digit;
+ } else
+ s_scan_table[i] = &RppLexer::scanChar;
+ }
+ }
+
+ s_scan_table[128] = &RppLexer::scanUnicodeChar;
+}
+
+QVector<Type> RppLexer::lex(const TokenContainer &tokenContainer)
+{
+ QVector<Type> tokenTypes;
+ const int numTokens = tokenContainer.count();
+ tokenTypes.reserve(numTokens);
+ QByteArray text = tokenContainer.fullText();
+ m_buffer = text.constData();
+ for(int t=0; t<numTokens; ++t) {
+ TokenEngine::Token token = tokenContainer.token(t);
+ tokenTypes.append(indentify(token.start, token.length));
+ }
+ return tokenTypes;
+}
+
+Type RppLexer::indentify(int pos, int length)
+{
+ Q_ASSERT(length > 0);
+ m_ptr = pos;
+ m_len = length;
+ int kind = 0;
+ const unsigned char ch = m_buffer[pos];
+ (this->*s_scan_table[ch < 128 ? ch : 128])(&kind);
+ return (Type)kind;
+}
+
+void RppLexer::scanChar(int *kind)
+{
+ *kind = m_buffer[m_ptr];
+}
+
+void RppLexer::scanWhiteSpaces(int *kind)
+{
+ *kind = Token_whitespaces;
+
+ while (unsigned char ch = m_buffer[m_ptr]) {
+ if (s_attr_table[ch] & A_Whitespace)
+ ++m_ptr;
+ else
+ break;
+ }
+}
+
+void RppLexer::scanNewline(int *kind)
+{
+ *kind = '\n';
+}
+
+void RppLexer::scanUnicodeChar(int *kind)
+{
+ *kind = m_buffer[m_ptr];
+}
+
+void RppLexer::scanCharLiteral(int *kind)
+{
+ *kind = Token_char_literal;
+}
+
+void RppLexer::scanStringLiteral(int *kind)
+{
+ *kind = Token_string_literal;
+}
+
+void RppLexer::scanIdentifier(int *kind)
+{
+ *kind = Token_identifier;
+}
+
+void RppLexer::scanNumberLiteral(int *kind)
+{
+ *kind = Token_number_literal;
+}
+
+void RppLexer::scanPreprocessor(int *kind)
+{
+ *kind = Token_preproc;
+}
+
+void RppLexer::scanComment(int *kind)
+{
+ switch(m_buffer[m_ptr + 1]) {
+ case '/':
+ *kind = Token_line_comment;
+ break;
+ case '*':
+ *kind = Token_multiline_comment;
+ break;
+ default:
+ scanOperator(kind);
+ }
+}
+
+void RppLexer::scanOperator(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case ':':
+ if (m_buffer[m_ptr+1] == ':') {
+ *kind = Token_scope;
+ return;
+ }
+ break;
+
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '=':
+ if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_eq;
+ return;
+ }
+ break;
+ case '!':
+ if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_not_eq;
+ return;
+ }
+ break;
+
+ case '&':
+ if (m_buffer[m_ptr+1] == '&') {
+ *kind = Token_and;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '|':
+ if (m_buffer[m_ptr+1] == '|' ) {
+ *kind = Token_or;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '+':
+ if (m_buffer[m_ptr+1] == '+' ) {
+ *kind = Token_incr;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '<':
+ if (m_buffer[m_ptr+1] == '<') {
+ if (m_buffer[m_ptr+2] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ *kind = Token_left_shift;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_leq;
+ return;
+ }
+ break;
+
+ case '>':
+ if (m_buffer[m_ptr+1] == '>') {
+ if (m_buffer[m_ptr+2] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ *kind = Token_right_shift;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_geq;
+ return;
+ }
+ break;
+
+ case '-':
+ if (m_buffer[m_ptr+1] == '>') {
+ if (m_buffer[m_ptr+2] == '*') {
+ *kind = Token_ptrmem;
+ return;
+ }
+ *kind = Token_arrow;
+ return;
+ } else if (m_buffer[m_ptr+1] == '-') {
+ *kind = Token_decr;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '.':
+ if (m_buffer[m_ptr+1] == '.' && m_buffer[m_ptr+2] == '.') {
+ *kind = Token_ellipsis;
+ return;
+ } else if (m_buffer[m_ptr+1] == '*') {
+ *kind = Token_ptrmem;
+ return;
+ }
+ break;
+
+ }
+
+ *kind = m_buffer[m_ptr++];
+}
+
+bool RppLexer::match(const char *buf, int len)
+{
+ if (m_len != len)
+ return false;
+ for (int i = 0; i < len; ++i) {
+ if(m_buffer[m_ptr + i] != buf[i])
+ return false;
+ }
+ return true;
+}
+
+void RppLexer::scanKeyword(int *kind)
+{
+ if(match("if", 2))
+ *kind = Token_directive_if;
+ else if(match("elif", 4))
+ *kind = Token_directive_elif;
+ else if(match("else", 4))
+ *kind = Token_directive_else;
+ else if(match("line", 4))
+ *kind = Token_directive_line;
+ else if(match("else", 4))
+ *kind = Token_directive_else;
+ else if(match("line", 4))
+ *kind = Token_directive_line;
+ else if(match("endif", 5))
+ *kind = Token_directive_endif;
+ else if(match("ifdef", 5))
+ *kind = Token_directive_ifdef;
+ else if(match("error", 5))
+ *kind = Token_directive_error;
+ else if(match("undef", 5))
+ *kind = Token_directive_undef;
+ else if(match("pragma", 6))
+ *kind = Token_directive_pragma;
+ else if(match("ifndef", 6))
+ *kind = Token_directive_ifndef;
+ else if(match("define", 6))
+ *kind = Token_directive_define;
+ else if(match("include", 7))
+ *kind = Token_directive_include;
+ else if(match("defined", 7))
+ *kind = Token_defined;
+ else
+ *kind = Token_identifier;
+}
+
+} //namespace Rpp
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/rpplexer.h b/tools/porting/src/rpplexer.h
new file mode 100644
index 0000000000..2d725f422a
--- /dev/null
+++ b/tools/porting/src/rpplexer.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RPPLEXER_H
+#define RPPLEXER_H
+
+#include "tokens.h"
+#include "tokenengine.h"
+#include <QByteArray>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+namespace Rpp {
+
+class RppLexer
+{
+public:
+
+ RppLexer();
+ QVector<Type> lex(const TokenEngine::TokenContainer &tokenContainer);
+private:
+ Type indentify(int pos, int length);
+ void setupScanTable();
+
+ void scanChar(int *kind);
+ void scanUnicodeChar(int *kind);
+ void scanNewline(int *kind);
+ void scanWhiteSpaces(int *kind);
+ void scanCharLiteral(int *kind);
+ void scanStringLiteral(int *kind);
+ void scanNumberLiteral(int *kind);
+ void scanIdentifier(int *kind);
+ void scanPreprocessor(int *kind);
+ void scanComment(int *kind);
+ void scanOperator(int *kind);
+ void scanKeyword(int *kind);
+
+ bool match(const char *buf, int len);
+ typedef void (RppLexer::*scan_fun_ptr)(int *kind);
+ RppLexer::scan_fun_ptr s_scan_table[128+1];
+ int s_attr_table[256];
+
+ enum
+ {
+ A_Alpha = 0x01,
+ A_Digit = 0x02,
+ A_Alphanum = A_Alpha | A_Digit,
+ A_Whitespace = 0x04
+ };
+
+ const char *m_buffer;
+ int m_ptr;
+ int m_len;
+};
+
+} //namespace Rpp
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/rpptreeevaluator.cpp b/tools/porting/src/rpptreeevaluator.cpp
new file mode 100644
index 0000000000..4fbd58162a
--- /dev/null
+++ b/tools/porting/src/rpptreeevaluator.cpp
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rpptreeevaluator.h"
+#include <QChar>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+namespace Rpp {
+
+RppTreeEvaluator::RppTreeEvaluator()
+{
+ QByteArray text(" ");
+ TokenEngine::Token token;
+ token.start = 0;
+ token.length = 1;
+ QVector<TokenEngine::Token> tokenList;
+ tokenList.append(token);
+ TokenContainer newLineContainer(text, tokenList, new TokenEngine::GeneratedInfo());
+ newlineSection= new TokenSection(newLineContainer, 0, 1);
+}
+
+RppTreeEvaluator::~RppTreeEvaluator()
+{
+ delete newlineSection;
+}
+
+TokenSectionSequence RppTreeEvaluator::evaluate(const Source *source,
+ DefineMap *activeDefinitions)
+{
+ m_tokenSections.clear();
+ m_activeDefinitions = activeDefinitions;
+ evaluateSource(source);
+ return TokenSectionSequence(m_tokenSections);
+}
+
+void RppTreeEvaluator::evaluateText(const Text *textLine)
+{
+ const int numTokens = textLine->count();
+ const TokenContainer tokenContainer = textLine->text().tokenContainer(0);
+
+ int t = 0;
+ int startTokenRun = 0;
+ while(t < numTokens) {
+ const Token *currentToken = textLine->token(t);
+ int currentContainerIndex = currentToken->index();
+ //handle macro replacements
+ if(currentToken->toIdToken()) {
+ const int tokenIndex = currentToken->index();
+ const QByteArray tokenText = tokenContainer.tempText(tokenIndex);
+ if(m_activeDefinitions->contains(tokenText)) {
+ //crate section
+ TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun);
+ m_tokenSections.append(section);
+ //evaluate macro
+ const int oldContainerIndex = currentContainerIndex;
+ TokenContainer evaluatedText = evaluateMacro(tokenContainer, currentContainerIndex);
+ TokenSection evalSection(evaluatedText, 0, evaluatedText.count());
+ m_tokenSections.append(evalSection);
+ t += currentContainerIndex - oldContainerIndex;
+ startTokenRun = t;
+ }
+ ++t;
+ continue;
+ }
+
+ //handle comments
+ if(currentToken->toLineComment() || currentToken->toMultiLineComment()) {
+ //create section
+ TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun );
+ m_tokenSections.append(section);
+ t++; //skip comment
+ startTokenRun = t;
+ t++;
+ continue;
+ }
+
+ // handle escaped newlines
+ if (currentContainerIndex + 1 < numTokens) {
+ const TokenTempRef tokenRef1 = tokenContainer.tokenTempRef(currentContainerIndex);
+ const TokenTempRef tokenRef2 = tokenContainer.tokenTempRef(currentContainerIndex + 1);
+ // This is i slight hack. We want to check if the next token is a newline token,
+ // but since we don't have any lexical info at this point we just check if it starts
+ // with \r or \n
+ if (tokenRef1.at(0) == '\\' && (tokenRef2.at(0) == '\n' || tokenRef2.at(0) == '\r')) {
+ //create section
+ TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun );
+ m_tokenSections.append(section);
+ t += 2;
+ startTokenRun = t;
+ t++;
+ continue;
+ }
+ }
+
+ t++;
+ }
+ //round up any tokens at the end and put them in a section
+ if(t - startTokenRun > 1) {
+ TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun );
+ m_tokenSections.append(section);
+ }
+
+ m_tokenSections.append(*newlineSection);
+}
+
+/*
+ Evaluates and ifsection by selecting which one of the if-elif-else
+ groups and then evaling that.
+*/
+void RppTreeEvaluator::evaluateIfSection(const IfSection *ifSection)
+{
+ ConditionalDirective *ifGroup = ifSection->ifGroup();
+ if(evaluateCondition(ifGroup)) {
+ evaluateConditionalDirective(ifGroup);
+ return;
+ }
+
+ QVector<ConditionalDirective *> elifGroups = ifSection->elifGroups();
+ foreach(ConditionalDirective *elifGroup, elifGroups) {
+ if(evaluateCondition(elifGroup)) {
+ evaluateConditionalDirective(elifGroup);
+ return;
+ }
+ }
+
+ ConditionalDirective *elseGroup = ifSection->elseGroup();
+ if(elseGroup)
+ evaluateConditionalDirective(elseGroup);
+}
+
+/*
+ Evaluate an IncludeDirective by evaluating the Source for the included
+ file. The source is found by emitting the includeCallback signal, which
+ must be handled outside RppTreeEvaluator.
+*/
+void RppTreeEvaluator::evaluateIncludeDirective(const IncludeDirective *directive)
+{
+ Source *currentSource = getParentSource(directive);
+ IncludeType includeType = includeTypeFromDirective(directive);
+ Source *newSource = 0;
+ emit includeCallback(newSource, currentSource, QString::fromLatin1(directive->filename().constData()), includeType);
+ Q_ASSERT(newSource); // If you get an assert here you probably
+ // forgot to connect to the includeCallback signal
+ evaluateSource(newSource);
+}
+
+void RppTreeEvaluator::evaluateDefineDirective(const DefineDirective *directive)
+{
+ m_tokenSections.append(*newlineSection);
+ m_activeDefinitions->insert(directive->identifier().fullText(), directive);
+}
+
+void RppTreeEvaluator::evaluateUndefDirective(const UndefDirective *directive)
+{
+ m_tokenSections.append(*newlineSection);
+ const QByteArray text = directive->identifier().fullText();
+ m_activeDefinitions->remove(text);
+}
+
+/*
+ Evaluate the truth-value of an conditionalDirective
+*/
+bool RppTreeEvaluator::evaluateCondition(const ConditionalDirective *conditionalDirective)
+{
+ if (IfDirective *ifDirective = conditionalDirective->toIfDirective())
+ return (evaluateExpression(ifDirective->expression()) != 0);
+ if (ElifDirective *elifDirective = conditionalDirective->toElifDirective())
+ return (evaluateExpression(elifDirective->expression()) != 0);
+ if (IfdefDirective *ifdefDirective = conditionalDirective->toIfdefDirective())
+ return m_activeDefinitions->contains(ifdefDirective->identifier().fullText());
+ if (IfndefDirective *ifndefDirective = conditionalDirective->toIfndefDirective())
+ return !m_activeDefinitions->contains(ifndefDirective->identifier().fullText());
+ else
+ return false; //error!
+}
+
+/*
+ Recursively evaluates an Expression
+*/
+int RppTreeEvaluator::evaluateExpression(Expression *expression)
+{
+ if (IntLiteral *e = expression->toIntLiteral()) {
+ return e->value();
+ } else if (StringLiteral *e = expression->toStringLiteral()) {
+ return e->value().size();
+ } else if (MacroReference *e = expression->toMacroReference()) {
+ switch(e->type()) {
+ case MacroReference::DefinedRef: {
+ return m_activeDefinitions->contains(e->name().fullText()) ? 1 : 0;
+ } case MacroReference::ValueRef: {
+ const QByteArray identifier = e->name().fullText();
+ if (m_activeDefinitions->contains(identifier)) {
+ int token = e->name().containerIndex(0);
+ TokenContainer value = evaluateMacro(e->name().tokenContainer(token), token);
+ return QString(QLatin1String(value.fullText())).toInt(0, 0);
+ } else {
+ return 0; // error
+ }
+ }
+ default: Q_ASSERT(0);
+ }
+ } else if (MacroFunctionReference *e = expression->toMacroFunctionReference()) {
+ Q_UNUSED(e);
+ //TODO handle MacroFunctionReference
+// DefineDirective *def = e->findDefinition(e->name());
+// Q_ASSERT(def->toMacroFunctionDefinition());
+// qWarning("not implemented yet");
+ return 0;
+ } else if (UnaryExpression *e = expression->toUnaryExpression()) {
+ int result = evaluateExpression(e->expression());
+ switch (e->op()) {
+ case '+': return + result;
+ case '-': return - result;
+ case '!': return ! result;
+ case '~': return ~ result;
+ default: Q_ASSERT(0);
+ }
+ } else if (BinaryExpression *e = expression->toBinaryExpression()) {
+ int v1 = evaluateExpression(e->leftExpression());
+ int v2 = evaluateExpression(e->rightExpression());
+
+ switch (e->op()) {
+ case '/': { return v2 ? v1 / v2 : 0; } //avoid division by zero
+ case '*': return v1 * v2;
+ case '%': { return v2 ? v1 % v2 : 0; } //avoid modulus by zero
+ case '+': return v1 + v2;
+ case '-': return v1 - v2;
+ case '<': return v1 < v2;
+ case '>': return v1 > v2;
+ case '&': return v1 & v2;
+ case '^': return v1 ^ v2;
+ case '|': return v1 | v2;
+ case Expression::LtEqOp: return v1 <= v2;
+ case Expression::GtEqOp: return v1 >= v2;
+ case Expression::EqOp: return v1 == v2;
+ case Expression::NotEqOp: return v1 != v2;
+ case Expression::AndOp: return v1 && v2;
+ case Expression::OrOp: return v1 || v2;
+ case Expression::LShiftOp: return v1 << v2;
+ case Expression::RShiftOp: return v1 >> v2;
+ default: Q_ASSERT(0);
+ }
+
+ } else if ( ConditionalExpression *e = expression->toConditionalExpression()){
+ return e->condition() ? evaluateExpression(e->leftExpression()) : evaluateExpression(e->rightExpression());
+ }
+ return 0;
+}
+/*
+ Expands a macro at index identiferTokenIndex in tokenContainer. Returns
+ the expanded macro text, and updates identiferTokenIndex to point after
+ the last token consumed.
+
+ Given the construct 'FN(a)', the '(a)' part will be consumed if FN is
+ defined to be a macro function, but not if it is an ordenary macro.
+*/
+TokenContainer RppTreeEvaluator::evaluateMacro(TokenContainer tokenContainer, int &identiferTokenIndex)
+{
+ QByteArray identifierText = tokenContainer.text(identiferTokenIndex);
+ if(!m_activeDefinitions->contains(identifierText))
+ return TokenContainer();
+
+ const Rpp::DefineDirective *directive = m_activeDefinitions->value(identifierText);
+ Q_ASSERT(directive);
+
+ // To prevent infinite recursive macro expansions, the skip set contains
+ // a set of identifers already seen.
+ QSet<QByteArray> skip;
+
+ if(directive->toMacroDefinition()) {
+ ++identiferTokenIndex;
+ QVector<TokenEngine::Token> tokenList;
+ tokenList.append(TokenEngine::Token(0, identifierText.count()));
+ return evaluateMacroInternal(skip, TokenContainer(identifierText, tokenList));
+ } else if (Rpp::MacroFunctionDefinition *macro = directive->toMacroFunctionDefinition()) {
+ MacroFunctionParser macroFunctionParser(tokenContainer, identiferTokenIndex);
+ if (macroFunctionParser.isValid() && macro->parameters().count() == macroFunctionParser.argumentCount()) {
+ TokenContainer macroFunctionContainer =
+ TokenEngine::copy(tokenContainer, identiferTokenIndex, macroFunctionParser.tokenCount());
+ identiferTokenIndex += macroFunctionParser.tokenCount();
+ return evaluateMacroInternal(skip, macroFunctionContainer);
+ } else {
+ // Error case, such as calling a macro function with the wrong number of parameters,
+ // or calling a macro function witout a parameter list.
+ return TokenEngine::copy(tokenContainer, identiferTokenIndex++, 1);
+ }
+ }
+ return TokenContainer();
+}
+
+/*
+ Recursively expands all macroes in macroInvokeTokens, returns a
+ TokenContainer with the new tokens.
+*/
+TokenEngine::TokenContainer RppTreeEvaluator::evaluateMacroInternal(QSet<QByteArray> skip, TokenEngine::TokenContainer macroInvokeTokens)
+{
+ bool changed = false;
+ QByteArray tokenText;
+ QVector<TokenEngine::Token> tokenList;
+ const int numTokens = macroInvokeTokens.count();
+
+ for (int t = 0; t < numTokens; ++t) {
+ const QByteArray identifierText = macroInvokeTokens.text(t);
+
+ // if the current token text is not a part of a macro definition we just copy it.
+ if (!m_activeDefinitions->contains(identifierText)) {
+ tokenList.append(TokenEngine::Token(tokenText.count(), identifierText.count()));
+ tokenText.append(identifierText);
+ continue;
+ }
+
+ // If the token text is in the skip list we copy it.
+ if (skip.contains(identifierText)) {
+ tokenList.append(TokenEngine::Token(tokenText.count(), identifierText.count()));
+ tokenText.append(identifierText);
+ continue;
+ }
+
+ skip.insert(identifierText);
+ changed = true;
+ const Rpp::DefineDirective *directive = m_activeDefinitions->value(identifierText);
+ Q_ASSERT(directive);
+ // if it is a macro, we copy in the replacement list.
+ if (Rpp::MacroDefinition *macro = directive->toMacroDefinition()) {
+ TokenList replacementList = macro->replacementList();
+ TokenEngine::copy(tokenText, tokenList, replacementList, 0, replacementList.count());
+
+ // To avoid infinite loops, set changed to false if the replacement
+ // text is identical to the identifier text.
+ if (replacementList.fullText().simplified() == identifierText.simplified())
+ changed = false;
+ } else if (Rpp::MacroFunctionDefinition *macro = directive->toMacroFunctionDefinition()) {
+ TokenList replacementList = macro->replacementList();
+ TokenList paramenterList = macro->parameters();
+
+ MacroFunctionParser macroFunctionParser(macroInvokeTokens, t);
+ if (macroFunctionParser.isValid() && macro->parameters().count() == macroFunctionParser.argumentCount()) {
+ t += macroFunctionParser.tokenCount();
+ // For each token in the replacement list: If the token matches a
+ // token in the parameter list, replace it with the
+ // corresponding argument tokens from the argument list.
+ for (int replacementToken = 0; replacementToken < replacementList.count(); ++replacementToken) {
+ const QByteArray replacementTokenText = replacementList.text(replacementToken);
+ bool replaced = false;
+ for (int parameterToken = 0; parameterToken < paramenterList.count(); ++parameterToken) {
+ const QByteArray parameterTokenText = paramenterList.text(parameterToken);
+ if (parameterTokenText == replacementTokenText) {
+ TokenSection argumentTokenSection = macroFunctionParser.argument(parameterToken);
+ TokenEngine::copy(tokenText, tokenList, argumentTokenSection, 0, argumentTokenSection.count());
+ replaced = true;
+ break;
+ }
+ }
+ if (! replaced) {
+ TokenEngine::copy(tokenText, tokenList, replacementList, replacementToken, 1);
+ }
+ }
+ }
+ }
+ }
+ if (!changed)
+ return macroInvokeTokens;
+ return evaluateMacroInternal(skip, TokenContainer(tokenText, tokenList));
+}
+
+TokenContainer RppTreeEvaluator::cloneTokenList(const TokenList &list)
+{
+ QByteArray text;
+ QVector<TokenEngine::Token> tokens;
+ int index = 0;
+ for (int t = 0; t<list.count(); ++t) {
+ const QByteArray tokenText = list.text(t);
+ const int textLength = tokenText.count();
+ text += tokenText;
+ TokenEngine::Token token;
+ token.start = index;
+ token.length = textLength;
+ tokens.append(token);
+ index += textLength;
+ }
+ TokenContainer container(text, tokens, new GeneratedInfo());
+ return container;
+}
+
+/*
+ Returns the parent Source for a given item.
+*/
+Source *RppTreeEvaluator::getParentSource(const Item *item) const
+{
+ Q_ASSERT(item);
+ while(item->toSource() == 0) {
+ item = item->parent();
+ Q_ASSERT(item);
+ }
+
+ return item->toSource();
+}
+/*
+ We have two IncludeType enums, one in IncludeDirective and one in
+ RppTreeEvaluator. This function translates between them.
+*/
+RppTreeEvaluator::IncludeType RppTreeEvaluator::includeTypeFromDirective(
+ const IncludeDirective *includeDirective) const
+{
+ if(includeDirective->includeType() == IncludeDirective::QuoteInclude)
+ return QuoteInclude;
+ else
+ return AngleBracketInclude;
+}
+
+/*
+ The MacrofunctionParser class is used to parse a macro function call (not
+ a macro function definition.)
+
+ startToken should give the token index for the identifier token for the macro function.
+*/
+MacroFunctionParser::MacroFunctionParser(const TokenEngine::TokenContainer &tokenContainer, int startToken)
+:m_tokenContainer(tokenContainer)
+,m_startToken(startToken)
+,m_numTokens(0)
+,m_valid(false)
+{
+ int tokenIndex = startToken;
+ ++tokenIndex; //skip identifier token
+ int parenthesisCount = 0;
+ int currentArgumentStartToken = tokenIndex;
+
+ // Parse argument tokens, add arguments to the m_arguments list.
+ // Arguments may consist of multiple tokens. Parenthesis in arguments
+ // are allowed, as long as they match. Inside a pair of argument
+ // parenthesis, ',' no longer signals a new argument. For example,
+ // FN((a,b)) is legal and contains one argument.
+ while(tokenIndex < tokenContainer.count()) {
+ QByteArray currentText = tokenContainer.text(tokenIndex);
+ ++tokenIndex;
+ if (currentText == "(") {
+ ++parenthesisCount;
+ if (parenthesisCount == 1) {
+ // first parenthesis
+ currentArgumentStartToken = tokenIndex;
+ continue;
+ }
+ }
+ if (currentText == ")") {
+ --parenthesisCount;
+ if (parenthesisCount == 0) {
+ //end of argument
+ m_arguments.append(TokenSection(tokenContainer, currentArgumentStartToken, tokenIndex - currentArgumentStartToken - 1));
+ currentArgumentStartToken = tokenIndex;
+ //end of argument list
+ break;
+ }
+ }
+ if (currentText == "," && parenthesisCount == 1) {
+ //end of argument
+ m_arguments.append(TokenSection(tokenContainer, currentArgumentStartToken, tokenIndex - currentArgumentStartToken - 1));
+ currentArgumentStartToken = tokenIndex;
+ continue;
+ }
+
+ if (QChar::fromLatin1(currentText.at(0)).isSpace()) {
+ continue;
+ }
+
+ // If we get here without having seen a paranthesis we have a syntax
+ // error in the macro function call.
+ if (parenthesisCount == 0) {
+ parenthesisCount = -1;
+ break;
+ }
+ }
+ m_numTokens = tokenIndex - startToken;
+ m_valid = (parenthesisCount == 0);
+}
+
+/*
+ Returns true if the MacroFunctionParser contains a valid macro function
+*/
+bool MacroFunctionParser::isValid()
+{
+ return m_valid;
+}
+
+/*
+ Returns the number of tokens in the tokenContainer that is covered by
+ the macro function.
+*/
+int MacroFunctionParser::tokenCount()
+{
+ return m_numTokens;
+}
+
+/*
+ Returns the number of arguments for the macro function.
+*/
+int MacroFunctionParser::argumentCount()
+{
+ return m_arguments.count();
+}
+
+/*
+ Returns the tokens for the argument given by argumentIndex.
+*/
+TokenSection MacroFunctionParser::argument(int argumentIndex)
+{
+ Q_ASSERT(argumentIndex < m_arguments.count());
+ return m_arguments.at(argumentIndex);
+}
+
+} //namespace Rpp
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/rpptreeevaluator.h b/tools/porting/src/rpptreeevaluator.h
new file mode 100644
index 0000000000..4492d64a91
--- /dev/null
+++ b/tools/porting/src/rpptreeevaluator.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RPPTREEEVALUATOR_H
+#define RPPTREEEVALUATOR_H
+
+#include "tokenengine.h"
+#include "rpp.h"
+#include "rpptreewalker.h"
+#include <QObject>
+#include <QList>
+#include <QHash>
+#include <QSet>
+
+QT_BEGIN_NAMESPACE
+
+namespace Rpp {
+
+class DefineMap : public QHash<QByteArray, const DefineDirective *>
+{
+
+};
+
+class RppTreeEvaluator: public QObject, public RppTreeWalker
+{
+Q_OBJECT
+public:
+ RppTreeEvaluator();
+ ~RppTreeEvaluator();
+ TokenEngine::TokenSectionSequence evaluate(const Source *source,
+ DefineMap *activedefinitions);
+ enum IncludeType {QuoteInclude, AngleBracketInclude};
+signals:
+ void includeCallback(Rpp::Source *&includee,
+ const Rpp::Source *includer,
+ const QString &filename,
+ Rpp::RppTreeEvaluator::IncludeType includeType);
+protected:
+ void evaluateIncludeDirective(const IncludeDirective *directive);
+ void evaluateDefineDirective(const DefineDirective *directive);
+ void evaluateUndefDirective(const UndefDirective *directive);
+ void evaluateIfSection(const IfSection *ifSection);
+ void evaluateText(const Text *text);
+ bool evaluateCondition(const ConditionalDirective *conditionalDirective);
+ int evaluateExpression(Expression *expression);
+
+ TokenEngine::TokenContainer evaluateMacro(TokenEngine::TokenContainer tokenContainer, int &identiferTokenIndex);
+ TokenEngine::TokenContainer evaluateMacroInternal(QSet<QByteArray> skip, TokenEngine::TokenContainer tokenContainer);
+ TokenEngine::TokenContainer cloneTokenList(const TokenEngine::TokenList &list);
+ Source *getParentSource(const Item *item) const;
+ IncludeType includeTypeFromDirective(
+ const IncludeDirective *includeDirective) const;
+private:
+ QVector<TokenEngine::TokenSection> m_tokenSections;
+ DefineMap *m_activeDefinitions;
+ TokenEngine::TokenSection *newlineSection;
+};
+
+class MacroFunctionParser
+{
+public:
+ MacroFunctionParser(const TokenEngine::TokenContainer &tokenContainer, int startToken);
+ bool isValid();
+ int tokenCount();
+ int argumentCount();
+ TokenEngine::TokenSection argument(int argumentIndex);
+private:
+ const TokenEngine::TokenContainer &m_tokenContainer;
+ const int m_startToken;
+ int m_numTokens;
+ bool m_valid;
+ QVector<TokenEngine::TokenSection> m_arguments;
+};
+
+}//namespace Rpp
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/rpptreewalker.cpp b/tools/porting/src/rpptreewalker.cpp
new file mode 100644
index 0000000000..be2fedac6f
--- /dev/null
+++ b/tools/porting/src/rpptreewalker.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "rpptreewalker.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Rpp {
+
+void RppTreeWalker::evaluateItem(const Item *item)
+{
+ if(!item)
+ return;
+ if (Source *source = item->toSource())
+ evaluateSource(source);
+ else if (Directive *directive = item->toDirective())
+ evaluateDirective(directive);
+ else if (IfSection *ifSection = item->toIfSection())
+ evaluateIfSection(ifSection);
+ else if (Text *text = item->toText())
+ evaluateText(text);
+}
+
+void RppTreeWalker::evaluateItemComposite(const ItemComposite *itemComposite)
+{
+ if (!itemComposite)
+ return;
+ for (int i = 0; i < itemComposite->count(); ++i) {
+ evaluateItem(itemComposite->item(i));
+ }
+}
+
+void RppTreeWalker::evaluateSource(const Source *source)
+{
+ evaluateItemComposite(source->toItemComposite());
+}
+
+void RppTreeWalker::evaluateDirective(const Directive *directive)
+{
+ if (!directive)
+ return;
+ if (EmptyDirective *dir = directive->toEmptyDirective())
+ evaluateEmptyDirective(dir);
+ else if (ErrorDirective *dir = directive->toErrorDirective())
+ evaluateErrorDirective(dir);
+ else if (PragmaDirective *dir = directive->toPragmaDirective())
+ evaluatePragmaDirective(dir);
+ else if (IncludeDirective *dir = directive->toIncludeDirective())
+ evaluateIncludeDirective(dir);
+ else if (DefineDirective *dir = directive->toDefineDirective())
+ evaluateDefineDirective(dir);
+ else if (UndefDirective *dir = directive->toUndefDirective())
+ evaluateUndefDirective(dir);
+ else if (LineDirective *dir = directive->toLineDirective())
+ evaluateLineDirective(dir);
+ else if (NonDirective *dir = directive->toNonDirective())
+ evaluateNonDirective(dir);
+ else if (NonDirective *dir = directive->toNonDirective())
+ evaluateNonDirective(dir);
+ else if (ConditionalDirective *dir = directive->toConditionalDirective())
+ evaluateConditionalDirective(dir);
+}
+
+/*
+ This function evaluates all the branches of an IfSection. You should
+ override it if you want to only evaluate the "correct" branch.
+*/
+void RppTreeWalker::evaluateIfSection(const IfSection *ifSection)
+{
+ if (!ifSection)
+ return;
+ evaluateItemComposite(ifSection->toItemComposite());
+}
+
+void RppTreeWalker::evaluateConditionalDirective(const ConditionalDirective *conditionalDirective)
+{
+ if (!conditionalDirective)
+ return;
+ if (IfdefDirective *dir = conditionalDirective->toIfdefDirective())
+ evaluateIfdefDirective(dir);
+ else if (IfndefDirective *dir = conditionalDirective->toIfndefDirective())
+ evaluateIfndefDirective(dir);
+ else if (IfDirective *dir = conditionalDirective->toIfDirective())
+ evaluateIfDirective(dir);
+ else if (ElifDirective *dir = conditionalDirective->toElifDirective())
+ evaluateElifDirective(dir);
+ else if (ElseDirective *dir = conditionalDirective->toElseDirective())
+ evaluateElseDirective(dir);
+}
+
+void RppTreeWalker::evaluateIfdefDirective(const IfdefDirective *directive)
+{
+ if (!directive)
+ return;
+ evaluateItemComposite(directive->toItemComposite());
+}
+
+void RppTreeWalker::evaluateIfndefDirective(const IfndefDirective *directive)
+{
+ if (!directive)
+ return;
+ evaluateItemComposite(directive->toItemComposite());
+}
+
+void RppTreeWalker::evaluateIfDirective(const IfDirective *directive)
+{
+ if (!directive)
+ return;
+ evaluateItemComposite(directive->toItemComposite());
+}
+
+void RppTreeWalker::evaluateElifDirective(const ElifDirective *directive)
+{
+ if (!directive)
+ return;
+ evaluateItemComposite(directive->toItemComposite());
+}
+
+void RppTreeWalker::evaluateElseDirective(const ElseDirective *directive)
+{
+ if (!directive)
+ return;
+ evaluateItemComposite(directive->toItemComposite());
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/rpptreewalker.h b/tools/porting/src/rpptreewalker.h
new file mode 100644
index 0000000000..a0af41867f
--- /dev/null
+++ b/tools/porting/src/rpptreewalker.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RPPTREEWALKER_H
+#define RPPTREEWALKER_H
+
+#include "rpp.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Rpp {
+
+class RppTreeWalker
+{
+public:
+ virtual ~RppTreeWalker(){};
+ virtual void evaluateItem(const Item *item);
+ virtual void evaluateItemComposite(const ItemComposite *itemComposite);
+ virtual void evaluateSource(const Source *source);
+ virtual void evaluateDirective(const Directive *directive);
+ virtual void evaluateIfSection(const IfSection *ifSection);
+ virtual void evaluateConditionalDirective(const ConditionalDirective *conditionalDirective);
+
+ virtual void evaluateText(const Text *textLine) {Q_UNUSED(textLine);}
+ virtual void evaluateEmptyDirective(const EmptyDirective *directive) {Q_UNUSED(directive);}
+ virtual void evaluateErrorDirective(const ErrorDirective *directive) {Q_UNUSED(directive);}
+ virtual void evaluatePragmaDirective(const PragmaDirective *directive) {Q_UNUSED(directive);}
+ virtual void evaluateIncludeDirective(const IncludeDirective *directive) {Q_UNUSED(directive);}
+ virtual void evaluateDefineDirective(const DefineDirective *directive) {Q_UNUSED(directive);}
+ virtual void evaluateUndefDirective(const UndefDirective *directive) {Q_UNUSED(directive);}
+ virtual void evaluateLineDirective(const LineDirective *directive) {Q_UNUSED(directive);}
+ virtual void evaluateNonDirective(const NonDirective *directive) {Q_UNUSED(directive);}
+
+ virtual void evaluateIfdefDirective(const IfdefDirective *directive);
+ virtual void evaluateIfndefDirective(const IfndefDirective *directive);
+ virtual void evaluateIfDirective(const IfDirective *directive);
+ virtual void evaluateElifDirective(const ElifDirective *directive);
+ virtual void evaluateElseDirective(const ElseDirective *directive);
+
+ virtual void evaluateEndifDirective(const EndifDirective *directive) {Q_UNUSED(directive);}
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/semantic.cpp b/tools/porting/src/semantic.cpp
new file mode 100644
index 0000000000..0f9a2d7c31
--- /dev/null
+++ b/tools/porting/src/semantic.cpp
@@ -0,0 +1,1227 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "smallobject.h"
+#include "tokenengine.h"
+#include "semantic.h"
+#include <QtDebug>
+#include <QString>
+#include <QRegExp>
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenStreamAdapter;
+using namespace TokenEngine;
+using namespace CodeModel;
+
+Semantic::Semantic(CodeModel::NamespaceScope *globalScope,
+ TokenStreamAdapter::TokenStream *tokenStream,
+ TypedPool<CodeModel::Item> *storage)
+{
+ m_storage = storage;
+ m_tokenStream = tokenStream;
+
+ m_currentAccess = CodeModel::Member::Public;
+ m_inSlots = false;
+ m_inSignals = false;
+ m_inStorageSpec = false;
+ m_inTypedef = false;
+
+ globalScope->setName("::");
+ currentScope.push(globalScope);
+
+ //create global UnknownType and UnknownTypeMember
+ UnknownType *type = Create<UnknownType>(m_storage);
+ type->setName("__UnknownType");
+ globalScope->addType(type);
+ type->setParent(globalScope);
+
+ m_sharedUnknownMember = Create<TypeMember>(m_storage);
+ m_sharedUnknownMember->setNameToken(TokenRef());
+ m_sharedUnknownMember->setName("Unknown");
+ m_sharedUnknownMember->setType(type);
+ globalScope->addMember(m_sharedUnknownMember);
+ m_sharedUnknownMember->setParent(globalScope);
+
+}
+
+void Semantic::parseAST(TranslationUnitAST *node)
+{
+ TreeWalker::parseTranslationUnit(node);
+}
+
+
+void Semantic::parseLinkageSpecification(LinkageSpecificationAST *ast)
+{
+ if(!ast)
+ return;
+ int inStorageSpec = m_inStorageSpec;
+ m_inStorageSpec = true;
+ TreeWalker::parseLinkageSpecification(ast);
+ m_inStorageSpec = inStorageSpec;
+}
+
+void Semantic::parseNamespace(NamespaceAST *ast)
+{
+ CodeModel::NamespaceScope *parent = currentScope.top()->toNamespaceScope();
+ if(!parent->toNamespaceScope()) {
+ emit error("Error in Semantic::parseNamespace: parent scope was not a namespace");
+ return;
+ }
+
+ QByteArray nsName;
+ if (!ast->namespaceName() || textOf(ast->namespaceName()).isEmpty()){
+ nsName = "(__QT_ANON_NAMESPACE)";
+ } else {
+ nsName = textOf(ast->namespaceName());
+ }
+
+ CodeModel::NamespaceScope *namespaceScope = 0;
+
+ // Look up namespace scope in case it is already defined.
+ // (Unlike classes, C++ namespaces are "open" and can be added to.)
+ CodeModel::Scope *scope = parent->scopes().value(nsName);
+ if (scope)
+ namespaceScope = scope->toNamespaceScope();
+
+ // Create new namespace if not found.
+ if (!namespaceScope) {
+ namespaceScope = CodeModel::Create<CodeModel::NamespaceScope>(m_storage);
+ namespaceScope->setName(nsName);
+ parent->addScope(namespaceScope);
+
+ NamespaceMember *namespaceMember = Create<NamespaceMember>(m_storage);
+ namespaceMember->setNameToken(tokenRefFromAST(ast->namespaceName()));
+ namespaceMember->setName(nsName);
+ namespaceMember->setNamespaceScope(namespaceScope);
+ currentScope.top()->addMember(namespaceMember);
+ namespaceMember->setParent(currentScope.top());
+ }
+
+ currentScope.push(namespaceScope);
+ TreeWalker::parseNamespace(ast);
+ currentScope.pop();
+}
+
+void Semantic::parseClassSpecifier(ClassSpecifierAST *ast)
+{
+ if (!ast->name()){
+ return;
+ }
+
+ QByteArray kind = textOf(ast->classKey());
+ if (kind == "class")
+ m_currentAccess = CodeModel::Member::Private;
+ else // kind =="struct"
+ m_currentAccess = CodeModel::Member::Public;
+
+ QByteArray className = textOf(ast->name()->unqualifiedName());
+
+ //create ClassScope
+ CodeModel::ClassScope *klass = CodeModel::Create<CodeModel::ClassScope>(m_storage);
+ klass->setName(className);
+ currentScope.top()->addScope(klass);
+
+ //create ClassType
+ CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage);
+ type->setScope(klass);
+ currentScope.top()->addType(type);
+ type->setParent(currentScope.top());
+
+ //create TypeMember
+ CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+ typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName()));
+ typeMember->setName(className);
+ typeMember->setType(type);
+ currentScope.top()->addMember(typeMember);
+ typeMember->setParent(currentScope.top());
+
+ currentScope.push(klass);
+ if (ast->baseClause())
+ parseBaseClause(ast->baseClause(), klass);
+
+ //TreeWalker::parseClassSpecifier(ast);
+ parseNode(ast->winDeclSpec());
+ parseNode(ast->classKey());
+ parseNode(ast->baseClause());
+
+ // Here's the trick for parsing c++ classes:
+ // All inline function definitions must be interpreted as if they were
+ // written after any other declarations in the class.
+ QList<DeclarationAST *> functionDefinitions;
+ if (ast->declarationList())
+ foreach(DeclarationAST *decl, *ast->declarationList()) {
+ if(decl->nodeType() == NodeType_FunctionDefinition)
+ functionDefinitions.append(decl);
+ else
+ parseNode(decl);
+ }
+ foreach(DeclarationAST *decl, functionDefinitions)
+ parseNode(decl);
+
+ currentScope.pop();
+}
+/*
+ Parse a class, struct or enum forward decalration.
+*/
+void Semantic::parseElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
+{
+ if (!node)
+ return;
+ AST *kind = node->kind();
+ if (!kind)
+ return;
+
+ const QByteArray kindText = textOf(kind);
+ const QByteArray nameText = textOf(node->name());
+
+ // Don't do anything if the class, struct or enum has already been declared or defined.
+ if (lookupNameInScope(currentScope.top(), node->name()).count() > 0)
+ return;
+
+ if (kindText == "class" || kindText == "struct") {
+ // Create ClassType.
+ CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage);
+ type->setScope(0);
+ currentScope.top()->addType(type);
+ type->setParent(currentScope.top());
+
+ // Create TypeMember.
+ CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+ typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName()));
+ typeMember->setName(nameText);
+ typeMember->setType(type);
+ currentScope.top()->addMember(typeMember);
+ typeMember->setParent(currentScope.top());
+ } else if (kindText == "enum") {
+ //create a Type
+ CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage);
+ enumType->setName(nameText);
+ currentScope.top()->addType(enumType);
+ enumType->setParent(currentScope.top());
+
+ //create a TypeMember
+ CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+ if(node->name())
+ typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName()));
+ typeMember->setName(nameText);
+ typeMember->setType(enumType);
+ currentScope.top()->addMember(typeMember);
+ typeMember->setParent(currentScope.top());
+ }
+}
+
+void Semantic::parseSimpleDeclaration(SimpleDeclarationAST *ast)
+{
+ TypeSpecifierAST *typeSpec = ast->typeSpec();
+ InitDeclaratorListAST *declarators = ast->initDeclaratorList();
+
+ if (typeSpec)
+ parseTypeSpecifier(typeSpec);
+
+ if (declarators){
+ List<InitDeclaratorAST*> l = *declarators->initDeclaratorList();
+
+ foreach (InitDeclaratorAST *current, l) {
+ parseDeclaration(ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, current);
+ }
+ }
+}
+
+void Semantic::parseDeclaration(AST *funSpec, AST *storageSpec, TypeSpecifierAST *typeSpec, InitDeclaratorAST *decl)
+{
+ if (m_inStorageSpec)
+ return;
+
+ if(!decl)
+ return;
+
+ DeclaratorAST *d = decl->declarator();
+ if (!d)
+ return;
+
+ if (!d->subDeclarator() && d->parameterDeclarationClause()) {
+ parseFunctionDeclaration(funSpec, storageSpec, typeSpec, decl);
+ return;
+ }
+ if(!typeSpec || !typeSpec->name())
+ return;
+
+ DeclaratorAST *t = d;
+ while (t && t->subDeclarator())
+ t = t->subDeclarator();
+
+ QByteArray id;
+ if (t && t->declaratorId() && t->declaratorId()->unqualifiedName())
+ id = textOf(t->declaratorId()->unqualifiedName());
+
+ if (!t || !t->declaratorId() || !t->declaratorId()->unqualifiedName())
+ return;
+ AST *nameAST = t->declaratorId()->unqualifiedName();
+ QByteArray name = textOf(nameAST);
+
+
+ if (!scopeOfDeclarator(d, QList<QByteArray>()).isEmpty()){
+ return;
+ }
+
+ //Check if this is possibly a function call by searching for '(' and ')'
+ const QByteArray declText = textOf(decl);
+ if (declText.contains("(") && declText.contains(")")) {
+ if (decl->declarator() && decl->declarator()->subDeclarator()) {
+
+ NameAST * name = decl->declarator()->subDeclarator()->declaratorId();
+ if (name)
+ parseNameUse(name);
+ return;
+ }
+ }
+
+ //create VariableMember
+ CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage);
+ variableMember->setNameToken(tokenRefFromAST(nameAST));
+ variableMember->setName(name);
+ variableMember->setAccess(m_currentAccess);
+ variableMember->setParent(currentScope.top());
+ currentScope.top()->addMember(variableMember);
+
+ //look up type of variableMember,
+
+ TypeMember *typeMember = typeLookup(currentScope.top(), typeSpec->name());
+ if(typeMember) {
+ variableMember->setType(typeMember->type());
+ } else {
+ QByteArray text = typeOfDeclaration(typeSpec, d);
+ CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
+ type->setName(text);
+ variableMember->setType(type);
+ }
+
+ if (decl)
+ parseNode(decl->initializer());
+
+}
+
+void Semantic::parseFunctionDeclaration(AST *funSpec, AST *storageSpec,
+ TypeSpecifierAST * typeSpec, InitDeclaratorAST * initDeclarator)
+{
+ bool isFriend = false;
+ bool isVirtual = false;
+ bool isStatic = false;
+ bool isInline = false;
+ bool isPure = initDeclarator->initializer() != 0;
+
+ if (funSpec){
+ List<AST*> l = *funSpec->children();
+ foreach (AST *current, l) {
+ QByteArray text = textOf(current);
+ if (text == "virtual") isVirtual = true;
+ else if (text == "inline") isInline = true;
+ }
+ }
+
+ if (storageSpec){
+ List<AST*> l = *storageSpec->children();
+ foreach (AST *current, l) {
+ QByteArray text = textOf(current);
+ if (text == "friend") isFriend = true;
+ else if (text == "static") isStatic = true;
+ }
+ }
+ DeclaratorAST *declarator = initDeclarator->declarator();
+ if(!declarator || !declarator->declaratorId())
+ return;
+ AST *nameAST = declarator->declaratorId()->unqualifiedName();
+ QByteArray name = textOf(nameAST);
+
+ CodeModel::FunctionMember *method = CodeModel::Create<CodeModel::FunctionMember>(m_storage);
+ method->setNameToken(tokenRefFromAST(nameAST));
+ method->setName(name);
+ method->setAccess(m_currentAccess);
+ method->setStatic(isStatic);
+ method->setVirtual(isVirtual);
+ method->setAbstract(isPure);
+
+ parseFunctionArguments(declarator, method);
+
+ if (m_inSignals)
+ method->setSignal(true);
+
+ if (m_inSlots)
+ method->setSlot(true);
+
+ method->setConstant(declarator->constant() != 0);
+
+ QByteArray text = typeOfDeclaration(typeSpec, declarator);
+ if (!text.isEmpty()) {
+ CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
+ type->setName(text);
+ method->setReturnType(type);
+ }
+
+ method->setParent(currentScope.top());
+ currentScope.top()->addMember(method);
+}
+
+
+void Semantic::parseBaseClause(BaseClauseAST * baseClause, CodeModel::ClassScope *klass)
+{
+ if(!baseClause)
+ return;
+ if(!klass)
+ return;
+ List<BaseSpecifierAST*> *l = baseClause->baseSpecifierList();
+ if (!l)
+ return;
+ foreach (BaseSpecifierAST *baseSpecifier, *l) {
+ QByteArray baseName;
+ if (!baseSpecifier->name())
+ continue;
+
+ // Look up a class with the correct name.
+ QList<Member *> candidates = nameLookup(klass, baseSpecifier->name());
+ if (candidates.count() == 1 ) {
+ Member *member = candidates.at(0);
+ Q_ASSERT(member);
+ TypeMember *typeMember = member->toTypeMember();
+ if (typeMember) {
+ Q_ASSERT(typeMember->type());
+ ClassType *classType = typeMember->type()->toClassType();
+ if (classType) {
+ klass->addBaseClass(classType);
+ }
+ }
+ }
+ }
+}
+void Semantic::parseFunctionArguments(const DeclaratorAST *declarator, CodeModel::FunctionMember *method)
+{
+ if(!declarator || !method)
+ return;
+
+ ParameterDeclarationClauseAST *clause = declarator->parameterDeclarationClause();
+
+ if (clause && clause->parameterDeclarationList()){
+ ParameterDeclarationListAST *params = clause->parameterDeclarationList();
+ List<ParameterDeclarationAST*> *l = params->parameterList();
+ if (!l)
+ return;
+ foreach (ParameterDeclarationAST *param, *l) {
+ CodeModel::Argument *arg = CodeModel::Create<CodeModel::Argument>(m_storage);
+ arg->setParent(method);
+
+ if (param->declarator()){
+ QByteArray text = declaratorToString(param->declarator(), QByteArray(), true);
+ if(param->declarator()->declaratorId())
+ arg->setNameToken(tokenRefFromAST(param->declarator()->declaratorId()->unqualifiedName()));
+ if (!text.isEmpty())
+ arg->setName(text);
+ }
+
+ QByteArray tp = typeOfDeclaration(param->typeSpec(), param->declarator());
+ if (!tp.isEmpty()) {
+ CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage);
+ type->setName(tp);
+ arg->setType(type);
+ }
+
+ method->addArgument(arg);
+ }
+ }
+}
+
+// using directive (using namespace A)
+void Semantic::parseUsingDirective(UsingDirectiveAST *ast)
+{
+ QByteArray qualifiedname = textOf(ast->name());
+ QByteArray name = textOf(ast->name()->unqualifiedName());
+
+ //look up target namespace name
+ QList<Member *> memberList = nameLookup(currentScope.top(), ast->name());
+
+ NamespaceScope *targetNamespace = 0;
+
+ // search for namespace in member list.
+ QList<Member *>::ConstIterator it = memberList.constBegin();
+ while(it != memberList.constEnd()) {
+ if (NamespaceMember *namespaceMember = (*it)->toNamespaceMember()) {
+ targetNamespace = namespaceMember->namespaceScope();
+ break;
+ }
+ ++it;
+ }
+
+ if (targetNamespace == 0)
+ return;
+
+ // Find the insertion namespace, which is the first common
+ // ancesotor namespace for the current scope and the target namespace
+
+ // currentScope might be a block scope, find its first namespace parent
+ CodeModel::Scope *currentParent = currentScope.top();
+ while (currentParent->toNamespaceScope() == 0) {
+ currentParent = currentParent->parent();
+ }
+
+ CodeModel::Scope *namespaceA = currentParent;
+ while (namespaceA != 0) {
+ CodeModel::Scope *namespaceB = targetNamespace;
+ while (namespaceB != 0) {
+ if (namespaceB == namespaceA)
+ break;
+ namespaceB = namespaceB->parent();
+ }
+ if (namespaceB == namespaceA)
+ break;
+ namespaceA = namespaceA->parent();
+ }
+
+ if (namespaceA == 0 || namespaceA->toNamespaceScope() == 0)
+ return;
+
+ NamespaceScope *insertionNamespace = namespaceA->toNamespaceScope();
+
+ // Create using directive link
+ UsingDirectiveLink *usingDirectiveLink = Create<UsingDirectiveLink>(m_storage);
+ usingDirectiveLink->setParent(currentScope.top());
+ usingDirectiveLink->setTargetNamespace(targetNamespace);
+ usingDirectiveLink->setInsertionNamespace(insertionNamespace);
+
+ // add it to current namespace
+ if (NamespaceScope *namespaceScope = currentScope.top()->toNamespaceScope())
+ namespaceScope->addUsingDirectiveLink(usingDirectiveLink);
+ else if (BlockScope *blockScope = currentScope.top()->toBlockScope())
+ blockScope->addUsingDirectiveLink(usingDirectiveLink);
+}
+
+void Semantic::parseFunctionDefinition(FunctionDefinitionAST *ast)
+{
+ AST *funSpec = ast->functionSpecifier();
+ AST *storageSpec = ast->storageSpecifier();
+ TypeSpecifierAST *typeSpec = ast->typeSpec();
+ InitDeclaratorAST *initDeclarator = ast->initDeclarator();
+ if (!ast->initDeclarator())
+ return;
+
+ DeclaratorAST *d = initDeclarator->declarator();
+
+ if (!d->declaratorId())
+ return;
+
+ parseFunctionDeclaration(funSpec, storageSpec, typeSpec, initDeclarator);
+ CodeModel::FunctionMember *method = functionLookup(currentScope.top(), d);
+
+ if(!method) {
+ emit error("Error in Semantic::parseFunctionDefinition: Could not find declaration for function definition");
+ return;
+ }
+
+ CodeModel::Scope *parent = method->parent();
+
+ if(!ast->functionBody()) {
+ emit error("Error in Semantic::parseFunctionDefinition: no function body in function definition");
+ return;
+ }
+
+ //create child function scope
+ QByteArray id = textOf(d->declaratorId()->unqualifiedName());
+ CodeModel::BlockScope *functionScope = CodeModel::Create<CodeModel::BlockScope>(m_storage);
+ functionScope->setName(QByteArray("__QT_ANON_BLOCK_SCOPE(Function: ") + id + QByteArray(")"));
+ functionScope->setParent(parent);
+ method->setFunctionBodyScope(functionScope);
+
+ //add arguments to child scope
+ ArgumentCollection arguments = method->arguments();
+ ArgumentCollection::ConstIterator it = arguments.constBegin();
+ while(it != arguments.constEnd()) {
+ CodeModel::Argument *argument = *it;
+ CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage);
+ variableMember->setNameToken(argument->nameToken());
+ variableMember->setType(argument->type());
+ variableMember->setName(argument->name());
+ variableMember->setParent(functionScope);
+ functionScope->addMember(variableMember);
+ ++it;
+ }
+
+ //push function scope and parse function body
+ currentScope.push(functionScope);
+ parseStatementList(ast->functionBody());
+ currentScope.pop();
+}
+
+void Semantic::parseStatementList(StatementListAST *statemenList)
+{
+ if(!statemenList)
+ return;
+ CodeModel::BlockScope *blockScope = CodeModel::Create<CodeModel::BlockScope>(m_storage);
+ blockScope->setName("__QT_ANON_BLOCK_SCOPE");
+ blockScope->setParent(currentScope.top());
+ currentScope.top()->addScope(blockScope);
+
+ currentScope.push(blockScope);
+ TreeWalker::parseStatementList(statemenList);
+ currentScope.pop();
+}
+
+void Semantic::parseExpression(AbstractExpressionAST* node)
+{
+ if(!node)
+ return;
+ if(node->nodeType() == NodeType_ClassMemberAccess)
+ parseClassMemberAccess(static_cast<ClassMemberAccessAST *>(node));
+ else
+ TreeWalker::parseExpression(node);
+}
+
+/*
+ Pretty hardwired code for handling class member access of the types:
+ object.member and objectPtr->member.
+
+ This function creates a name use for object to its declaration, and a
+ name use from member to its declaration in the class.
+*/
+void Semantic::parseClassMemberAccess(ClassMemberAccessAST *node)
+{
+ if(!node)
+ return;
+ parseExpression(node->expression());
+ // Get a name use for the 'object' name.
+ NameUse *nameUse = findNameUse(node->expression());
+ // Since the NameUse refers to an object, its decalaration must be
+ // a ClassType. Get the scope of this class type.
+ if( nameUse
+ && nameUse->declaration()
+ && nameUse->declaration()->toVariableMember()
+ && nameUse->declaration()->toVariableMember()->type()
+ && nameUse->declaration()->toVariableMember()->type()->toClassType()
+ && nameUse->declaration()->toVariableMember()->type()->toClassType()->scope()) {
+
+ CodeModel::Scope *scope = nameUse->declaration()->toVariableMember()->type()->toClassType()->scope();
+ QList<CodeModel::Member *> members = lookupNameInScope(scope, node->name());
+ if(members.count() != 0) {
+ createNameUse(members.at(0), node->name());
+ return;
+ }
+ }
+ // Create a NameUse that refers to the global shared unknown type.
+ createNameUse(m_sharedUnknownMember, node->name());
+}
+
+void Semantic::parseExpressionStatement(ExpressionStatementAST *node)
+{
+ TreeWalker::parseExpressionStatement(node);
+}
+
+// using declaration (using A::b)
+void Semantic::parseUsing(UsingAST *ast)
+{
+ //CodeModel::Scope *s = lookUpScope(currentScope.top(), ast->name());
+ QList<CodeModel::Member *> members = nameLookup(currentScope.top(), ast->name());
+ if(members.isEmpty()) {
+ emit error("Error in Semantic::parseUsing: could not look up using target");
+ return;
+ }
+ //TODO: handle multiple members (when nameLookup returns a set of overloded functions)
+ CodeModel::Member *member = members[0];
+ CodeModel::Scope *targetScope = member->parent();
+ if(!targetScope) {
+ emit error("Error in Semantic::parseUsing: target has no parent scope");
+ return;
+ }
+
+ if(!ast->name())
+ return;
+ AST *nameAST = ast->name()->unqualifiedName();
+ if(!nameAST)
+ return;
+ QByteArray name = textOf(nameAST);
+}
+
+void Semantic::parseEnumSpecifier(EnumSpecifierAST *ast)
+{
+ if (!ast->name())
+ return;
+
+ QByteArray name = textOf(ast->name());
+
+ //create a Type
+ CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage);
+ enumType->setName(name);
+ currentScope.top()->addType(enumType);
+ enumType->setParent(currentScope.top());
+
+ //create a TypeMember
+ CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+ if(ast->name())
+ typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName()));
+ typeMember->setName(name);
+ typeMember->setType(enumType);
+ currentScope.top()->addMember(typeMember);
+ typeMember->setParent(currentScope.top());
+
+ //parse the eneumerators
+ List<EnumeratorAST*> *list = ast->enumeratorList();
+ if (!list)
+ return;
+ foreach (EnumeratorAST *current, *list) {
+ CodeModel::VariableMember *enumerator = CodeModel::Create<CodeModel::VariableMember>(m_storage);
+ enumerator->setNameToken(tokenRefFromAST(current->id()));
+ enumerator->setName(textOf(current->id()));
+ enumerator->setAccess(m_currentAccess);
+ enumerator->setStatic(true);
+ enumerator->setType(enumType);
+ currentScope.top()->addMember(enumerator);
+ enumerator->setParent(currentScope.top());
+ }
+
+}
+
+void Semantic::parseTypedef(TypedefAST *ast)
+{
+ TypeSpecifierAST *typeSpec = ast->typeSpec();
+ InitDeclaratorListAST *declarators = ast->initDeclaratorList();
+
+ if (typeSpec && declarators){
+ QByteArray typeId;
+
+ if (typeSpec->name())
+ typeId = textOf(typeSpec->name());
+
+ List<InitDeclaratorAST*> *l = declarators->initDeclaratorList();
+ if (!l)
+ return;
+ foreach (InitDeclaratorAST *initDecl, *l) {
+ QByteArray type, id;
+ if (initDecl->declarator()){
+ type = typeOfDeclaration(typeSpec, initDecl->declarator());
+
+ DeclaratorAST *d = initDecl->declarator();
+ while (d->subDeclarator()){
+ d = d->subDeclarator();
+ }
+
+ if (d->declaratorId())
+ id = textOf(d->declaratorId());
+ }
+
+ //create a type
+ CodeModel::Scope *scope = currentScope.top();
+ CodeModel::AliasType *typeAlias = CodeModel::Create<CodeModel::AliasType>(m_storage);
+ //typeAlias->setName(id);
+ //typeAlias->setParent(scope);
+ scope->addType(typeAlias);
+
+ //create a TypeMember
+ CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage);
+ if(typeSpec->name())
+ typeMember->setNameToken(tokenRefFromAST(typeSpec->name()->unqualifiedName()));
+ typeMember->setName(id);
+ typeMember->setType(typeAlias);
+ currentScope.top()->addMember(typeMember);
+ typeMember->setParent(currentScope.top());
+
+ }
+
+ }
+}
+
+void Semantic::parseTypeSpecifier(TypeSpecifierAST *ast)
+{
+ // If this is a classSpecifier or a EnumSpecifier we skip the name lookup,
+ // becuase looking up the name "E" in a class definition like
+ // "class E { ..." makes no sense. (There might be a variable named E
+ // already declared, but that variable is now shadowed by the class type.)
+ if( ast->nodeType() != NodeType_EnumSpecifier
+ && ast->nodeType() != NodeType_ClassSpecifier
+ && ast->nodeType() != NodeType_ElaboratedTypeSpecifier )
+ parseNameUse(ast->name());
+ TreeWalker::parseTypeSpecifier(ast);
+}
+
+/*
+ Parses a name: looks up name, creates name use.
+*/
+void Semantic::parseNameUse(NameAST* name)
+{
+ if(!name)
+ return;
+
+ // Look up name
+ QList<CodeModel::Member *> members = nameLookup(currentScope.top(), name);
+ if(members.isEmpty()) {
+ //cout << "no declaration found for " << textOf(name).constData() << endl;
+ // Create NameUse that refer to a shared UnknownMember
+ createNameUse(m_sharedUnknownMember, name);
+ return;
+ }
+
+ //TODO: handle multiple members (when nameLookup returns a set of overloaded functions)
+ CodeModel::Member *member = members[0];
+ if(!member->parent()) {
+ emit error("Error in Semantic::parseUsing: target has no parent scope");
+ return;
+ }
+
+ createNameUse(member, name);
+}
+
+/*
+ looks up name used in basescope. If name->isGlobal() is true or if classOrNamespaceList()
+ returns a non-emty list, the C++ qualified name lookup rules are used. Otherwise the
+ unquialified name lookup rules are used. Returns the a list of members that was found,
+ In most cases this list will contain zero or one element, exept in the case of overloaded functions.
+ TODO: Argument-dependent name lookup
+*/
+QList<CodeModel::Member *> Semantic::nameLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+ if (name->isGlobal() || (name->classOrNamespaceNameList()
+ && name->classOrNamespaceNameList()->size()>0 )) {
+ return qualifiedNameLookup(baseScope, name);
+ } else {
+ return unqualifiedNameLookup(baseScope, name);
+ }
+}
+
+//look up an unqualified name
+QList<CodeModel::Member *> Semantic::unqualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+ QList<UsingDirectiveLink *> usingDirectiveLinks;
+ CodeModel::Scope *currentScope = baseScope;
+ QList<CodeModel::Member *> entities;
+
+ while (currentScope != 0) {
+ // Add any "using namespace" directive links for the current scope to
+ // usingDirectiveLinks
+ if (NamespaceScope *namespaceScope = currentScope->toNamespaceScope())
+ usingDirectiveLinks += namespaceScope->usingDirectiveLinks();
+ if (BlockScope *blockScope = currentScope->toBlockScope())
+ usingDirectiveLinks += blockScope->usingDirectiveLinks();
+
+ // Search usingDirectiveLinks for a link where currentScope is the
+ // insertion namespace. If found look up name in the target namespace
+ // for that link.
+ if (NamespaceScope *namespaceScope = currentScope->toNamespaceScope()) {
+ QList<UsingDirectiveLink *>::ConstIterator it = usingDirectiveLinks.constBegin();
+ while (it != usingDirectiveLinks.constEnd()) {
+ if ((*it)->insertionNamespace() == namespaceScope)
+ entities = lookupNameInScope((*it)->targetNamespace(), name);
+ ++it;
+ }
+ }
+
+ // Look up names in this scope.
+ entities += lookupNameInScope(currentScope, name);
+ if (!entities.isEmpty())
+ break;
+ currentScope = currentScope->parent();
+ }
+ return entities;
+}
+
+//look up a qualified name
+QList<CodeModel::Member *> Semantic::qualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+ QList<CodeModel::Member *> entities;
+ CodeModel::Scope *currentScope = baseScope;
+
+ // Check if the global ("::") scope has been specified.
+ if(name->isGlobal()) {
+ while (currentScope->parent())
+ currentScope = currentScope->parent();
+ }
+
+ while (entities.isEmpty() && currentScope != 0) {
+ CodeModel::Scope *targetScope = scopeLookup(currentScope, name);
+ entities = lookupNameInScope(targetScope, name);
+ currentScope = currentScope->parent();
+ }
+
+ return entities;
+}
+
+//looks up a name in a scope, includes base classes if scope is a class scope
+QList<CodeModel::Member *> Semantic::lookupNameInScope(CodeModel::Scope *scope, const NameAST* name)
+{
+ QList<CodeModel::Member *> entities;
+
+ if(!scope || !name)
+ return entities;
+
+ QByteArray nameText = textOf(name->unqualifiedName()->name());
+ //look up name in members of current scope
+ const CodeModel::MemberCollection members = scope->members();
+ if (members.contains(nameText))
+ entities.append(members.value(nameText));
+
+ // if not found, look up name in base classes (if any)
+ CodeModel::ClassScope *classScope = scope->toClassScope();
+ if (entities.isEmpty() && classScope) {
+ const TypeCollection baseClasses = classScope->baseClasses();
+ TypeCollection::ConstIterator it = baseClasses.constBegin();
+ while (it != baseClasses.constEnd()) {
+ CodeModel::Scope *baseClass = it.value()->toClassType()->scope();
+ if (scope != baseClass)
+ entities += lookupNameInScope(baseClass, name);
+ ++it;
+ }
+
+ if (entities.count() > 1)
+ emit error("Error in Semantic::lookupNameInScope: name "
+ + nameText + " is ambigous");
+ }
+ return entities;
+}
+
+/*
+ Resolves the classOrNamespaceNameList part of a NameAST against a base scope.
+*/
+CodeModel::Scope *Semantic::scopeLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+ CodeModel::Scope *currentScope = baseScope;
+ const List<ClassOrNamespaceNameAST *> *scopeList = name->classOrNamespaceNameList();
+ // if there is no scope list, then the scope we are looking for is baseScope
+ if (!scopeList)
+ return baseScope;
+
+ // Check if the global ("::") scope has been specified.
+ if(name->isGlobal()) {
+ while (currentScope->parent())
+ currentScope = currentScope->parent();
+ }
+
+ while(currentScope != 0) {
+ int nestingCounter = 0;
+ CodeModel::Scope *nestedScope = currentScope;
+ while (nestingCounter < scopeList->count()) {
+ const QByteArray nameText = textOf((*scopeList)[nestingCounter]->name());
+ nestedScope = nestedScope->scopes().value(nameText);
+ if (!nestedScope)
+ break;
+ ++nestingCounter;
+ }
+ if(nestedScope) // found target scope?
+ return nestedScope;
+
+ currentScope = currentScope->parent(); //look in parent scope
+ }
+
+ return 0;
+}
+
+TypeMember *Semantic::typeLookup(CodeModel::Scope *baseScope, const NameAST* name)
+{
+ QList<CodeModel::Member *> memberList = nameLookup(baseScope, name);
+
+ foreach(Member *member, memberList) {
+ if(TypeMember *typeMember = member->toTypeMember())
+ return typeMember;
+ }
+ return 0;
+}
+
+FunctionMember *Semantic::functionLookup(CodeModel::Scope *baseScope,
+ const DeclaratorAST *functionDeclarator)
+{
+
+ QList<CodeModel::Member*> candidateList =
+ nameLookup(baseScope, functionDeclarator->declaratorId());
+ return selectFunction(candidateList, functionDeclarator);
+}
+
+/*
+ This is a simplified function lookup routine, for matching member function
+ definitions with member function declarations. It does not implement
+ the general C++ function overload resolution rules.
+*/
+FunctionMember *Semantic::selectFunction(QList<CodeModel::Member*> candidatateList, const DeclaratorAST *functionDeclarator)
+{
+ // get arguments for funciton we are looking for
+ FunctionMember testFunction;
+ parseFunctionArguments(functionDeclarator, &testFunction);
+ const ArgumentCollection testArgumentCollection = testFunction.arguments();
+
+ //test againts functions in overload list.
+ foreach(Member* member, candidatateList) {
+ FunctionMember *function = member->toFunctionMember();
+ if (!function)
+ continue;
+ const ArgumentCollection argumentCollection = function->arguments();
+
+ //test argument types and number of arguments
+ ArgumentCollection::ConstIterator arg1 = argumentCollection.constBegin();
+ ArgumentCollection::ConstIterator arg2 = testArgumentCollection.constBegin();
+ bool match = true;
+ while(arg1 != argumentCollection.constEnd() && arg2 != testArgumentCollection.constEnd()) {
+ if( arg1.value()->type()->name() != arg2.value()->type()->name() ) {
+ match = false;
+ break;
+ }
+ ++arg1;
+ ++arg2;
+ }
+ if(match)
+ return function;
+ }
+ return 0;
+}
+
+QByteArray Semantic::typeOfDeclaration(TypeSpecifierAST *typeSpec, DeclaratorAST *declarator)
+{
+ if (!typeSpec)
+ return QByteArray();
+
+ QByteArray text;
+
+ if (typeSpec->cvQualify()) {
+ List<AST*> cv = *typeSpec->cvQualify()->children();
+ foreach (AST *current, cv) {
+ text += " " + textOf(current);
+ }
+ text += " ";
+ }
+
+
+ text += textOf(typeSpec);
+
+ if (typeSpec->cv2Qualify()) {
+ List<AST*> cv = *typeSpec->cv2Qualify()->children();
+ foreach (AST *current, cv) {
+ text += textOf(current) + " ";
+ }
+ }
+
+ if (declarator && declarator->ptrOpList()) {
+ List<AST*> ptrOpList = *declarator->ptrOpList();
+ foreach (AST *current, ptrOpList) {
+ text += " " + textOf(current);
+ }
+ text += " ";
+ }
+
+ return text.trimmed().simplified();
+}
+
+
+
+QList<QByteArray> Semantic::scopeOfName(NameAST *id, const QList<QByteArray>& startScope)
+{
+ QList<QByteArray> scope = startScope;
+ if (id && id->classOrNamespaceNameList()){
+ if (id->isGlobal())
+ scope.clear();
+
+ List<ClassOrNamespaceNameAST*> l = *id->classOrNamespaceNameList();
+ foreach (ClassOrNamespaceNameAST *current, l) {
+ if (current->name())
+ scope << textOf(current->name());
+ }
+ }
+
+ return scope;
+}
+
+QList<QByteArray> Semantic::scopeOfDeclarator(DeclaratorAST *d, const QList<QByteArray>& startScope)
+{
+ if(!d)
+ return QList<QByteArray>();
+ return scopeOfName(d->declaratorId(), startScope);
+}
+
+QByteArray Semantic::typeSpecToString(TypeSpecifierAST* typeSpec)
+{
+ if (!typeSpec)
+ return QByteArray();
+
+ QByteArray tp;
+ if (typeSpec->cvQualify()) {
+ tp += "const ";
+ }
+
+ tp += (QString::fromLatin1(textOf(typeSpec)).replace(QRegExp(QLatin1String(" :: ")), QString::fromUtf8("::"))).toLatin1();
+ return tp;
+}
+
+QByteArray Semantic::declaratorToString(DeclaratorAST* declarator, const QByteArray& scope, bool skipPtrOp)
+{
+ if (!declarator)
+ return QByteArray();
+
+ QByteArray text;
+
+ if (!skipPtrOp && declarator->ptrOpList()){
+ List<AST*> ptrOpList = *declarator->ptrOpList();
+ foreach (AST *current, ptrOpList) {
+ text += textOf(current);
+ }
+ text += QByteArray(" ");
+ }
+
+ text += scope;
+
+ if (declarator->subDeclarator())
+ text += QByteArray("(") + declaratorToString(declarator->subDeclarator()) + QByteArray(")");
+
+ if (declarator->declaratorId())
+ text += textOf(declarator->declaratorId());
+
+ if (declarator->arrayDimensionList()) {
+ List<AST*> arrays = *declarator->arrayDimensionList();
+ foreach (AST *current, arrays) {
+ current=current; //silence unused symbol warning
+ text += QByteArray("[]");
+ }
+ }
+
+ if (declarator->parameterDeclarationClause()){
+ text += QByteArray("(");
+
+ ParameterDeclarationListAST* l = declarator->parameterDeclarationClause()->parameterDeclarationList();
+ if (l != 0){
+ List<ParameterDeclarationAST*> params = *l->parameterList();
+ foreach (ParameterDeclarationAST *current, params) {
+ QByteArray type = typeSpecToString(current->typeSpec());
+ text += type;
+ if (!type.isEmpty())
+ text += QByteArray(" ");
+ text += declaratorToString(current->declarator());
+
+ // ### FIXME if (it.current())
+ text += QByteArray(", ");
+ }
+ }
+
+ text += QByteArray(")");
+
+ if (declarator->constant() != 0)
+ text += QByteArray(" const");
+ }
+
+ return QString::fromLatin1(text).replace(QRegExp(QLatin1String(" :: ")), QLatin1String("::")).simplified().toLatin1();
+}
+
+QByteArray Semantic::textOf(const AST *node) const
+{
+ if (!node)
+ return QByteArray();
+ QByteArray text;
+ for (int i = node->startToken(); i < node->endToken(); ++i) {
+ if (!m_tokenStream->isHidden(i)) {
+ if (i != node->startToken())
+ text += QByteArray(" ");
+ text += m_tokenStream->tokenText(i);
+ }
+ }
+ return text;
+}
+
+void Semantic::createNameUse(Member *member, NameAST *name)
+{
+ if (!name)
+ return;
+
+ AST *unqualifedName = name->unqualifiedName()->name();
+
+ if(!unqualifedName || !member)
+ return;
+
+ CodeModel::NameUse *nameUse = CodeModel::Create<CodeModel::NameUse>(m_storage);
+ nameUse->setParent(currentScope.top());
+ nameUse->setNameToken(tokenRefFromAST(unqualifedName));
+ nameUse->setName(textOf(unqualifedName));
+ nameUse->setDeclaration(member);
+
+ currentScope.top()->addNameUse(nameUse);
+ addNameUse(unqualifedName, nameUse);
+}
+
+void Semantic::addNameUse(AST *node, NameUse *nameUse)
+{
+ const int tokenIndex = node->startToken();
+ m_nameUses.insert(tokenIndex, nameUse);
+}
+
+/*
+ Searches a AST node and all its children for a nameUse. The name use is
+ found by looking up each node's tokens in the m_nameUses map. A depth-first
+ search is used.
+*/
+NameUse *Semantic::findNameUse(AST *node)
+{
+ if(!node)
+ return 0;
+
+ List<AST*> *children = node->children();
+ if(children) {
+ NameUse *nameUse = 0;
+ foreach(AST* child , *children) {
+ nameUse = findNameUse(child);
+ if(nameUse)
+ break;
+ }
+ if (nameUse)
+ return nameUse;
+ }
+
+ for (int t = node->startToken(); t < node->endToken(); ++t) {
+ // cout << t <<" |" <<m_tokenStream->tokenText(t).constData() << "|" << endl;
+ if (m_nameUses.contains(t))
+ return m_nameUses.value(t);
+ }
+ return 0;
+}
+
+/*
+ Gets a TokenRef from an AST node.
+ Assumes that the node only covers one token, which means that
+ node->statToken() == node->endToken(). If this is not the case
+ then the TokenRef will reference the token at startToken.
+*/
+TokenEngine::TokenRef Semantic::tokenRefFromAST(AST *node)
+{
+ const int startTokenIndex = node->startToken();
+ const TokenEngine::TokenContainer tokenContainer = m_tokenStream->tokenContainer(startTokenIndex);
+ const int containerIndex = m_tokenStream->containerIndex(startTokenIndex);
+ return TokenEngine::TokenRef(tokenContainer, containerIndex);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/semantic.h b/tools/porting/src/semantic.h
new file mode 100644
index 0000000000..18d41b37e7
--- /dev/null
+++ b/tools/porting/src/semantic.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SEMANTIC_H
+#define SEMANTIC_H
+
+#include "treewalker.h"
+#include "codemodel.h"
+#include "tokenstreamadapter.h"
+
+#include <QObject>
+#include <QStack>
+#include <QList>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+class Semantic: public QObject, public TreeWalker
+{
+Q_OBJECT
+public:
+ Semantic(CodeModel::NamespaceScope *globalScope,
+ TokenStreamAdapter::TokenStream *tokenStream,
+ TypedPool<CodeModel::Item> *storage);
+
+ void parseAST(TranslationUnitAST *node);
+signals:
+ void error(const QByteArray &message);
+ void warning(const QByteArray &message);
+protected:
+ virtual void parseNamespace(NamespaceAST *);
+ virtual void parseClassSpecifier(ClassSpecifierAST *);
+ virtual void parseElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node);
+ virtual void parseSimpleDeclaration(SimpleDeclarationAST *);
+ virtual void parseDeclaration(AST *funSpec, AST *storageSpec, TypeSpecifierAST *typeSpec, InitDeclaratorAST *decl);
+ virtual void parseFunctionDeclaration(AST *funSpec, AST *storageSpec, TypeSpecifierAST *typeSpec, InitDeclaratorAST *decl);
+ virtual void parseFunctionArguments(const DeclaratorAST *declarator, CodeModel::FunctionMember *method);
+ virtual void parseFunctionDefinition(FunctionDefinitionAST *);
+ virtual void parseStatementList(StatementListAST *);
+ virtual void parseBaseClause(BaseClauseAST *baseClause, CodeModel::ClassScope * klass);
+ virtual void parseLinkageSpecification(LinkageSpecificationAST *);
+ virtual void parseUsing(UsingAST *);
+ virtual void parseUsingDirective(UsingDirectiveAST *);
+ virtual void parseExpression(AbstractExpressionAST*);
+ virtual void parseExpressionStatement(ExpressionStatementAST *node);
+ virtual void parseClassMemberAccess(ClassMemberAccessAST *node);
+ virtual void parseNameUse(NameAST*);
+ virtual void parseEnumSpecifier(EnumSpecifierAST *);
+ virtual void parseTypedef(TypedefAST *);
+ virtual void parseTypeSpecifier(TypeSpecifierAST *);
+
+ QList<CodeModel::Member *> nameLookup(CodeModel::Scope *baseScope, const NameAST* name);
+ QList<CodeModel::Member *> unqualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name);
+ QList<CodeModel::Member *> qualifiedNameLookup(CodeModel::Scope *baseScope, const NameAST* name);
+ QList<CodeModel::Member *> lookupNameInScope(CodeModel::Scope *scope, const NameAST* name);
+
+ CodeModel::TypeMember *typeLookup(CodeModel::Scope *baseScope, const NameAST* name);
+ CodeModel::FunctionMember *functionLookup(CodeModel::Scope *baseScope, const DeclaratorAST *functionDeclarator);
+ CodeModel::Scope *scopeLookup(CodeModel::Scope *baseScope, const NameAST* name);
+ CodeModel::FunctionMember *selectFunction(QList<CodeModel::Member*> candidatateList, const DeclaratorAST *functionDeclarator);
+
+ QByteArray typeOfDeclaration(TypeSpecifierAST *typeSpec, DeclaratorAST *declarator);
+ QList<QByteArray> scopeOfName(NameAST *id, const QList<QByteArray> &scope);
+ QList<QByteArray> scopeOfDeclarator(DeclaratorAST *d, const QList<QByteArray> &scope);
+ QByteArray declaratorToString(DeclaratorAST* declarator, const QByteArray& scope = QByteArray(), bool skipPtrOp = false);
+ QByteArray typeSpecToString(TypeSpecifierAST* typeSpec);
+
+ QByteArray textOf(const AST *node) const;
+ void createNameUse(CodeModel::Member *member, NameAST *name);
+ void addNameUse(AST *node, CodeModel::NameUse *nameUse);
+ CodeModel::NameUse *findNameUse(AST *node);
+ TokenEngine::TokenRef tokenRefFromAST(AST *node);
+private:
+ TokenStreamAdapter::TokenStream *m_tokenStream;
+ TypedPool<CodeModel::Item> *m_storage;
+ CodeModel::Member::Access m_currentAccess;
+ bool m_inSlots;
+ bool m_inSignals;
+ bool m_inStorageSpec;
+ bool m_inTypedef;
+
+ QMap<int, CodeModel::NameUse *> m_nameUses;
+ QStack<CodeModel::Scope *> currentScope;
+ CodeModel::TypeMember *m_sharedUnknownMember;
+private:
+ Semantic(const Semantic &source);
+ void operator = (const Semantic &source);
+};
+
+QT_END_NAMESPACE
+
+#endif // SEMANTIC_H
diff --git a/tools/porting/src/smallobject.cpp b/tools/porting/src/smallobject.cpp
new file mode 100644
index 0000000000..704e802035
--- /dev/null
+++ b/tools/porting/src/smallobject.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "smallobject.h"
+
+QT_BEGIN_NAMESPACE
+
+int block_t::N = 0;
+static pool mem_pool;
+
+void *SmallObject::operator new(size_t size)
+{
+ return mem_pool.allocate(size);
+}
+
+void SmallObject::operator delete(void * /*p*/ )
+{
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/smallobject.h b/tools/porting/src/smallobject.h
new file mode 100644
index 0000000000..f086b706ed
--- /dev/null
+++ b/tools/porting/src/smallobject.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SMALLOBJECT_H
+#define SMALLOBJECT_H
+
+#include <QList>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+struct block_t
+{
+ static int N;
+
+ block_t *chain;
+ char *data;
+ char *ptr;
+ char *end;
+
+ inline void init(int block_size = 256)
+ {
+ ++N;
+ chain = 0;
+ data = (char*) malloc(block_size);
+ ptr = data;
+ end = data + block_size;
+ }
+
+ inline void init0(int block_size)
+ {
+ init();
+ memset(data, '0', block_size);
+ }
+
+ inline void destroy()
+ {
+ --N;
+ if (chain) {
+ chain->destroy();
+ free(chain);
+ }
+
+ free(data);
+ }
+
+ inline void *allocate(size_t size, block_t **right_most)
+ {
+ const unsigned int block_size = 1 << 16;
+ if (end < ptr + size) {
+ assert( size < block_size );
+
+ if (!chain) {
+ chain = (block_t*) malloc(sizeof(block_t));
+ Q_ASSERT(chain);
+ chain->init(block_size);
+ }
+
+ return chain->allocate(size, right_most);
+ }
+
+ char *r = ptr;
+ ptr += size;
+
+ if (right_most)
+ *right_most = this;
+
+ return r;
+ }
+
+};
+
+// a stupid memory pool
+struct pool
+{
+ block_t blk;
+ block_t *right_most;
+
+ inline pool() { blk.init(); right_most = &blk; }
+ inline ~pool() { blk.destroy(); }
+
+ inline void *allocate(size_t size)
+ {
+ void *ptr = right_most->allocate(size, &right_most);
+ Q_ASSERT(ptr);
+ return ptr;
+
+ }
+ inline void *reallocate(void *old, size_t old_size, size_t size)
+ {
+ void *alloc = right_most->allocate(size, &right_most);
+ memcpy(alloc, old, old_size);
+ return alloc;
+ }
+private:
+ Q_DISABLE_COPY(pool)
+};
+
+/*
+ A memory pool that calls the destructor for each stored item when memory is
+ freed, at the expence storing one BaseType* per item.
+
+ Note that allocations for types that does not inherit BaseType
+ is not allowed and will result in a crash when the memory is freed.
+*/
+template <typename BaseType>
+class TypedPool
+{
+public:
+ inline TypedPool() { blk.init(); right_most = &blk; }
+ inline ~TypedPool()
+ {
+ foreach(BaseType *item, allocated)
+ item->~BaseType();
+ blk.destroy();
+ }
+
+ inline void *allocate(size_t size)
+ {
+ void *memory = right_most->allocate(size, &right_most);
+ allocated.append(reinterpret_cast<BaseType *>(memory));
+ Q_ASSERT(memory);
+ return memory;
+ }
+private:
+ Q_DISABLE_COPY(TypedPool)
+ block_t blk;
+ block_t *right_most;
+ QList<BaseType *> allocated;
+};
+
+struct SmallObject
+{
+ static void *operator new(size_t size);
+ static void operator delete(void *p);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/src.pro b/tools/porting/src/src.pro
new file mode 100644
index 0000000000..d626b19416
--- /dev/null
+++ b/tools/porting/src/src.pro
@@ -0,0 +1,93 @@
+TEMPLATE = app
+CONFIG -= moc
+CONFIG += console
+CONFIG -= app_bundle
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+QT = xml core
+DEPENDPATH += .
+TARGET =qt3to4
+DESTDIR = ../../../bin
+DEFINES += QT_NO_CAST_TO_ASCII
+
+HEADERS += smallobject.h \
+ tokenengine.h \
+ tokenizer.h \
+ rpplexer.h \
+ rpp.h \
+ rpptreewalker.h \
+ rpptreeevaluator.h \
+ rppexpressionbuilder.h \
+ preprocessorcontrol.h \
+ replacetoken.h \
+ tokenreplacements.h \
+ textreplacement.h \
+ portingrules.h \
+ qtsimplexml.h \
+ projectporter.h \
+ proparser.h \
+ fileporter.h \
+ logger.h \
+ tokens.h \
+ filewriter.h \
+ cpplexer.h \
+ smallobject.h \
+ ast.h \
+ errors.h \
+ parser.h \
+ translationunit.h \
+ treewalker.h \
+ semantic.h \
+ codemodel.h \
+ codemodelwalker.h \
+ codemodelattributes.h
+
+SOURCES += port.cpp \
+ smallobject.cpp \
+ tokenengine.cpp \
+ tokenizer.cpp \
+ rpplexer.cpp \
+ rpp.cpp \
+ rpptreewalker.cpp \
+ rpptreeevaluator.cpp \
+ rppexpressionbuilder.cpp \
+ preprocessorcontrol.cpp \
+ replacetoken.cpp \
+ tokenreplacements.cpp \
+ textreplacement.cpp \
+ portingrules.cpp \
+ qtsimplexml.cpp \
+ projectporter.cpp \
+ proparser.cpp \
+ fileporter.cpp \
+ logger.cpp \
+ filewriter.cpp \
+ cpplexer.cpp \
+ ast.cpp \
+ errors.cpp \
+ parser.cpp \
+ translationunit.cpp \
+ treewalker.cpp \
+ semantic.cpp \
+ codemodel.cpp \
+ codemodelwalker.cpp \
+ codemodelattributes.cpp
+
+RESOURCES += qt3headers0.qrc qt3headers1.qrc qt3headers2.qrc qt3headers3.qrc
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+RULESXML = q3porting.xml
+RULESXML.files = q3porting.xml
+RULESXML.path = $$[QT_INSTALL_DATA]
+INSTALLS += RULESXML
+
+win32-msvc.net|win32-msvc2* {
+ QMAKE_CXXFLAGS -= -Zm200 -Zm300
+ QMAKE_CXXFLAGS += -Zm1000
+ QMAKE_CFLAGS -= -Zm200 -Zm300
+ QMAKE_CFLAGS += -Zm1000
+}
diff --git a/tools/porting/src/textreplacement.cpp b/tools/porting/src/textreplacement.cpp
new file mode 100644
index 0000000000..1123e4f737
--- /dev/null
+++ b/tools/porting/src/textreplacement.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "textreplacement.h"
+
+QT_BEGIN_NAMESPACE
+
+bool TextReplacements::insert(QByteArray newText, int insertPosition, int currentLenght)
+{
+ //bubble sort the new replacement into the list
+ int i;
+ for(i=0; i<textReplacementList.size(); ++i) {
+ if (insertPosition == textReplacementList.at(i).insertPosition)
+ return false; // multiple replacements on the same insertPosition is not allowed.
+ if(insertPosition < textReplacementList.at(i).insertPosition)
+ break; //we found the right position
+ }
+ //++i;
+ // cout << "inserting new text " << newText.constData() << endl;
+ // %s at %d overwriting %d bytes at list pos %d\n", newText.constData(), insertPosition, currentLenght, i);
+ TextReplacement rep;
+ rep.newText=newText;
+ rep.insertPosition=insertPosition;
+ rep.currentLenght=currentLenght;
+
+ textReplacementList.insert(i, rep);
+ return true;
+}
+
+void TextReplacements::clear()
+{
+ textReplacementList.clear();
+}
+
+QByteArray TextReplacements::apply(QByteArray current)
+{
+ QByteArray newData=current;
+ int i;
+ int replacementOffset=0;
+
+ for(i=0; i<textReplacementList.size(); ++i) {
+ TextReplacement rep=textReplacementList.at(i);
+ //printf("applying new text %s insert at %d overwriting %d bytes \n", rep.newText.constData(), rep.insertPosition, rep.currentLenght);
+ newData.remove(rep.insertPosition+replacementOffset, rep.currentLenght);
+ newData.insert(rep.insertPosition+replacementOffset, rep.newText);
+
+ //modify all remaining replacements if we change the document length
+ replacementOffset+=(rep.newText.size() - rep.currentLenght);
+ }
+
+ return newData;
+}
+
+TextReplacements &TextReplacements::operator+=(const TextReplacements &other)
+{
+ foreach(TextReplacement rep, other.replacements()) {
+ insert(rep.newText, rep.insertPosition, rep.currentLenght);
+ }
+ return *this;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/textreplacement.h b/tools/porting/src/textreplacement.h
new file mode 100644
index 0000000000..e8bfaf1049
--- /dev/null
+++ b/tools/porting/src/textreplacement.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTREPLACEMENT_H
+#define TEXTREPLACEMENT_H
+
+#include <QByteArray>
+#include <QList>
+#include <QtAlgorithms>
+
+QT_BEGIN_NAMESPACE
+
+class TextReplacement
+{
+public:
+ QByteArray newText;
+ int insertPosition;
+ int currentLenght; //lenght of the text that is going to be replaced.
+ bool operator<(const TextReplacement &other) const
+ {
+ return (insertPosition < other.insertPosition);
+ }
+};
+
+class TextReplacements
+{
+public:
+ /*
+ creates a TextReplacement that inserts newText at insertPosition. currentLength bytes
+ are overwritten in the original text. If there already is an insert at insertPosition,
+ the insert will not be performed.
+
+ insert maintains the TextReplacement list in sorted order.
+
+ Returns true if the insert was successfull, false otherwise;
+ */
+ bool insert(QByteArray newText, int insertPosition, int currentLenght);
+ void clear();
+ QList<TextReplacement> replacements() const
+ {
+ return textReplacementList;
+ }
+ QByteArray apply(QByteArray current);
+
+ TextReplacements &operator+=(const TextReplacements &other);
+
+private:
+ QList<TextReplacement> textReplacementList;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/tokenengine.cpp b/tools/porting/src/tokenengine.cpp
new file mode 100644
index 0000000000..151d18e156
--- /dev/null
+++ b/tools/porting/src/tokenengine.cpp
@@ -0,0 +1,402 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tokenengine.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace TokenEngine {
+
+/*
+ Add a container-global attribute.
+*/
+void TokenAttributes::addAttribute(const QByteArray &name, const QByteArray &value)
+{
+ const QByteArray keyText = makeKeyText(-1, name);
+ attributes.insert(keyText, value);
+}
+
+/*
+ Retrieve container-global attribute.
+*/
+QByteArray TokenAttributes::attribute(const QByteArray &name) const
+{
+ const QByteArray keyText = makeKeyText(-1, name);
+ return attributes.value(keyText);
+}
+
+/*
+ Add an attribute. Note: Don't use names starting with a number, that will
+ break the indexing.
+*/
+void TokenAttributes::addAttribute(const int index, const QByteArray &name, const QByteArray &value)
+{
+ const QByteArray keyText = makeKeyText(index, name);
+ attributes.insert(keyText, value);
+}
+
+QByteArray TokenAttributes::attribute(const int index, const QByteArray &name) const
+{
+ const QByteArray keyText = makeKeyText(index, name);
+ return attributes.value(keyText);
+}
+
+QByteArray TokenAttributes::makeKeyText(const int index, const QByteArray &name) const
+{
+ QByteArray indexText;
+ return indexText.setNum(index) + name;
+}
+
+
+/*
+ Construnct an empty TokenContainer.
+*/
+TokenContainer::TokenContainer()
+{
+ d = new TokenContainerData();
+ d->typeInfo = 0;
+}
+
+/*
+ Construnct a TokenContainer from data
+*/
+TokenContainer::TokenContainer(QByteArray text, QVector<Token> tokens, TypeInfo *typeInfo)
+{
+ d = new TokenContainerData();
+ d->text = text;
+ d->tokens = tokens;
+ if(typeInfo == 0)
+ d->typeInfo = new TypeInfo();
+ else
+ d->typeInfo = typeInfo;
+}
+
+int TokenContainer::count() const
+{
+ return d->tokens.count();
+}
+
+QByteArray TokenContainer::text(const int index) const
+{
+ Token token = d->tokens.at(index);
+ return d->text.mid(token.start, token.length);
+}
+
+QByteArray TokenContainer::tempText(const int index) const
+{
+ Token token = d->tokens.at(index);
+ return QByteArray::fromRawData(d->text.constData() + token.start, token.length);
+}
+
+QByteArray TokenContainer::fullText() const
+{
+ return d->text;
+}
+
+TokenContainer TokenContainer::tokenContainer(const int index) const
+{
+ Q_UNUSED(index);
+ return *this;
+}
+
+Token TokenContainer::token(const int index) const
+{
+ return d->tokens.at(index);
+}
+
+TypeInfo *TokenContainer::typeInfo()
+{
+ return d->typeInfo;
+}
+
+TokenAttributes *TokenContainer::tokenAttributes()
+{
+ return d->tokenAttributes;
+}
+
+const TokenAttributes *TokenContainer::tokenAttributes() const
+{
+ return d->tokenAttributes;
+}
+
+/*
+ Returns the line number for the given index.
+*/
+int TokenContainer::line(int index) const
+{
+ //This algorithm is a bit more complicated than it should be,
+ //since we have to search for newlines inside comments.
+ //(Comments are tokenized as one token)
+ QByteArray contents = fullText();
+ int pos=0;
+ int lines=0;
+ for(int t=0; t < index; ++t) {
+ int tokenLength = d->tokens.at(t).length;
+ if((tokenLength == 1) && (text(t) == "\n")) {
+ ++lines;
+ } else if(tokenLength > 2) {// 3 is the minimum size for a comment (// + newline)
+ int newpos = d->tokens.at(t).length;
+ for(int p = pos; p < newpos; ++p) {
+ if(contents[p] == '\n')
+ ++lines;
+ }
+ }
+ pos += d->tokens.at(t).length;
+ }
+ return lines;
+}
+
+/*
+ Returns the column number for the given index.
+*/
+int TokenContainer::column(int index) const
+{
+ //Scan backwards, find \n.
+ int chars = 0;
+ int t = index;
+ while (t>0) {
+ if((d->tokens.at(t).length == 1) && (text(t) == "\n"))
+ break;
+ chars += d->tokens.at(t).length;
+ --t;
+ }
+ return chars;
+}
+
+TokenTempRef TokenContainer::tokenTempRef(const int index) const
+{
+ Q_ASSERT(index < d->tokens.count());
+ const Token token = d->tokens.at(index);
+ return TokenTempRef(d->text.constData() + token.start, token.length);
+}
+
+QByteArray TokenSection::fullText() const
+{
+ QByteArray text;
+ for (int t = m_start; t < m_start + m_count; ++t) {
+ text += m_tokenContainer.text(t);
+ }
+ return text;
+}
+
+QByteArray TokenList::fullText() const
+{
+ QByteArray text;
+ for (int t = 0; t < m_tokenList.count(); ++t) {
+ text += m_tokenContainer.text(m_tokenList.at(t));
+ }
+ return text;
+}
+
+TokenSectionSequence::TokenSectionSequence(QVector<TokenSection> tokenSections)
+:m_tokenSections(tokenSections), m_count(0)
+{
+ for(int s = 0; s < m_tokenSections.count(); ++s) {
+ m_startIndexes.append(m_count);
+ m_count += m_tokenSections.at(s).count();
+ }
+}
+
+QByteArray TokenSectionSequence::fullText() const
+{
+ QByteArray text;
+ foreach(TokenSection section, m_tokenSections) {
+ text += section.fullText();
+ }
+ return text;
+}
+
+int TokenSectionSequence::count() const
+{
+ return m_count;
+}
+
+QVector<TokenSection> TokenSectionSequence::tokenSections() const
+{
+ return m_tokenSections;
+}
+
+QByteArray TokenSectionSequence::text(const int index) const
+{
+ const int sectionIndex = findSection(index);
+ const int sectionInternalIndex = calculateInternalIndex(index, sectionIndex);
+ return m_tokenSections.at(sectionIndex).text(sectionInternalIndex);
+}
+
+QByteArray TokenSectionSequence::tempText(const int index) const
+{
+ const int sectionIndex = findSection(index);
+ const int sectionInternalIndex = calculateInternalIndex(index, sectionIndex);
+ return m_tokenSections.at(sectionIndex).tempText(sectionInternalIndex);
+}
+
+
+TokenContainer TokenSectionSequence::tokenContainer(const int index) const
+{
+ const int sectionIndex = findSection(index);
+ const int sectionInternalIndex = calculateInternalIndex(index, sectionIndex);
+ return m_tokenSections.at(sectionIndex).tokenContainer(sectionInternalIndex);
+}
+
+int TokenSectionSequence::containerIndex(const int index) const
+{
+ const int sectionIndex = findSection(index);
+ const int sectionInternalIndex = calculateInternalIndex(index, sectionIndex);
+ return m_tokenSections.at(sectionIndex).containerIndex(sectionInternalIndex);
+}
+
+int TokenSectionSequence::findSection(const int index) const
+{
+ int c = 0;
+ bool found = false;
+ //Here we do a linear search through all collections in the list,
+ //which could turn out to be to slow.
+ while(!found && c < m_tokenSections.count()) {
+ const int sectionEnd = m_startIndexes.at(c)
+ + m_tokenSections.at(c).count();
+ if (index < sectionEnd)
+ found = true;
+ else
+ ++c;
+ }
+ if(!found) {
+ //error
+ Q_ASSERT(0);
+ return -1;
+ }
+ Q_ASSERT(c < m_tokenSections.count());
+ return c;
+}
+
+int TokenSectionSequence::calculateInternalIndex(const int index, const int sectionIndex) const
+{
+ const int sectionInternalIndex =
+ index - m_startIndexes.at(sectionIndex);
+ Q_ASSERT(sectionInternalIndex < m_tokenSections.at(sectionIndex).count());
+ return sectionInternalIndex;
+}
+
+
+TokenSectionSequenceIterator::TokenSectionSequenceIterator(const TokenSectionSequence &tokenSectionSequence)
+:m_currentSection(0)
+,m_currentToken(-1)
+,m_numSections(tokenSectionSequence.m_tokenSections.count())
+,m_tokenSectionSequence(tokenSectionSequence)
+
+{ }
+
+/*
+ Resets the token iterator.
+*/
+void TokenSectionSequenceIterator::reset()
+{
+ m_currentSection = 0;
+ m_currentToken = -1;
+}
+
+/*
+ Advances the token iterator.
+*/
+bool TokenSectionSequenceIterator::nextToken()
+{
+ if(m_tokenSectionSequence.m_tokenSections.isEmpty())
+ return false;
+ ++m_currentToken;
+ //check of we are past the end of the current section
+ if(m_currentToken < m_tokenSectionSequence.m_tokenSections.at(m_currentSection).count())
+ return true;
+ //Advance to the next non-empty section.
+ m_currentToken = 0;
+ do {
+ ++m_currentSection;
+ //return false if no more sections
+ if(m_currentSection >= m_numSections)
+ return false;
+ //skip empty sections
+ } while(m_tokenSectionSequence.m_tokenSections.at(m_currentSection).count() == 0);
+
+ return true;
+}
+
+/*
+ Returns the text for the current token;
+*/
+QByteArray TokenSectionSequenceIterator::text() const
+{
+ return m_tokenSectionSequence.m_tokenSections.at(m_currentSection).text(m_currentToken);
+}
+
+/*
+ Returns the text for the current token as a temporary QByteArray;
+*/
+QByteArray TokenSectionSequenceIterator::tempText() const
+{
+ return m_tokenSectionSequence.m_tokenSections.at(m_currentSection).tempText(m_currentToken);
+}
+
+/*
+ Returns the container for the current token;
+*/
+TokenContainer TokenSectionSequenceIterator::tokenContainer() const
+{
+ return m_tokenSectionSequence.m_tokenSections.at(m_currentSection).tokenContainer(m_currentToken);
+}
+
+/*
+ Returns the containerIndex for the current token;
+*/
+int TokenSectionSequenceIterator::containerIndex() const
+{
+ return m_tokenSectionSequence.m_tokenSections.at(m_currentSection).containerIndex(m_currentToken);
+}
+
+/*
+ Returns a temporary token reference for the current token for the current token;
+*/
+TokenTempRef TokenSectionSequenceIterator::tokenTempRef() const
+{
+ return m_tokenSectionSequence.m_tokenSections.at(m_currentSection).tokenTempRef(m_currentToken);
+}
+
+
+} //namespace TokenEngine
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/tokenengine.h b/tools/porting/src/tokenengine.h
new file mode 100644
index 0000000000..7fcfaeccc2
--- /dev/null
+++ b/tools/porting/src/tokenengine.h
@@ -0,0 +1,391 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOKENENGINE_H
+#define TOKENENGINE_H
+
+#include <QByteArray>
+#include <QVector>
+#include <QString>
+#include <QSharedData>
+#include <QSharedDataPointer>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+namespace TokenEngine {
+
+class TokenContainer;
+/*
+ A token is defined as a start-postion and a lenght. Since the actual text
+ storage is not reffered to here, Token needs to be used together with
+ a TokenContainer in order to be useful.
+*/
+class Token
+{
+public:
+ Token()
+ :start(0), length(0) {}
+ Token(int p_start, int p_lenght)
+ :start(p_start), length(p_lenght) {}
+ int start;
+ int length;
+};
+
+/*
+ Each TokenContainer has a TypeInfo object with meta-information.
+*/
+class FileInfo;
+class GeneratedInfo;
+class TypeInfo
+{
+public:
+ virtual ~TypeInfo() {};
+ virtual FileInfo *toFileInfo() const {return 0;}
+ virtual GeneratedInfo *toGeneratedInfo() const {return 0;}
+};
+
+/*
+ MetaInfo for containers that contains tokens from a file
+*/
+class FileInfo: public TypeInfo
+{
+public:
+ FileInfo *toFileInfo() const
+ {return const_cast<FileInfo *>(this);}
+
+ QString filename;
+};
+
+/*
+ MetaInfo for containers that contains generated tokens.
+*/
+class GeneratedInfo: public TypeInfo
+{
+public:
+ GeneratedInfo *toGeneratedInfo() const
+ {return const_cast<GeneratedInfo *>(this);}
+
+ //preprocessor tree pointer?
+};
+
+class TokenAttributes
+{
+public:
+ void addAttribute(const QByteArray &name, const QByteArray &value);
+ QByteArray attribute(const QByteArray &name) const;
+ void addAttribute(const int index, const QByteArray &name, const QByteArray &value);
+ QByteArray attribute(const int index, const QByteArray &name) const;
+
+private:
+ inline QByteArray makeKeyText(const int index, const QByteArray &name) const;
+ QMap<QByteArray, QByteArray> attributes;
+};
+
+
+/*
+ A TokenSequence that stores text and tokens referencing
+ that text.
+*/
+class TokenContainerData : public QSharedData
+{
+public:
+ TokenContainerData()
+ : typeInfo(0)
+ {tokenAttributes = new TokenAttributes();}
+ ~TokenContainerData()
+ {delete tokenAttributes; delete typeInfo; }
+ QByteArray text;
+ QVector<Token> tokens;
+ TypeInfo *typeInfo;
+ TokenAttributes *tokenAttributes;
+};
+class TokenTempRef;
+class TokenContainer
+{
+public:
+ TokenContainer();
+ TokenContainer(QByteArray text, QVector<Token> tokens, TypeInfo *typeInfo = 0);
+ int count() const;
+ QByteArray text(const int index) const;
+ QByteArray tempText(const int index) const;
+ QByteArray fullText() const;
+ TokenContainer tokenContainer(const int index) const;
+ inline int containerIndex(const int index) const
+ { return index; }
+ Token token(const int index) const;
+ TypeInfo *typeInfo();
+ TokenAttributes *tokenAttributes();
+ const TokenAttributes *tokenAttributes() const;
+ int line(int index) const;
+ int column(int index) const;
+ TokenTempRef tokenTempRef(const int index) const;
+private:
+ const QByteArray &textRef()
+ { return d->text; }
+ QExplicitlySharedDataPointer<TokenContainerData> d;
+};
+
+/*
+ A reference to a single token in a container
+*/
+class TokenRef
+{
+public:
+ TokenRef(): m_index(-1) {}
+ TokenRef(TokenContainer tokenContainer, int containerIndex)
+ : m_tokenContainer(tokenContainer), m_index(containerIndex) {}
+ inline int count() const
+ { return m_index == -1 ? 0 : 1; }
+ inline QByteArray text(const int index = 0) const
+ { Q_UNUSED(index); return m_tokenContainer.text(m_index); }
+ inline QByteArray tempText(const int index) const
+ { Q_UNUSED(index); return m_tokenContainer.tempText(m_index); }
+ inline QByteArray fullText() const
+ { return text(); }
+ inline TokenContainer tokenContainer(const int index = 0) const
+ { Q_UNUSED(index); return m_tokenContainer; }
+ inline int containerIndex(const int index = 0) const
+ { Q_UNUSED(index); return m_index; }
+private:
+ TokenContainer m_tokenContainer;
+ int m_index;
+};
+
+/*
+ A temporary reference to a single token in a container. This reference does
+ not increase the refcount on the TokenContainer.
+*/
+class TokenTempRef
+{
+public:
+ TokenTempRef(const char *text, int length)
+ : m_text(text), m_length(length) {}
+ inline const char *constData() const
+ { return m_text; }
+ inline int length() const
+ { return m_length; }
+ char at(int index) const
+ { Q_ASSERT(index < m_length); return m_text[index]; }
+private:
+ const char *m_text;
+ int m_length;
+};
+
+/*
+ Contains a selected range from a TokenSequence.
+*/
+class TokenSection
+{
+public:
+ TokenSection() : m_start(0), m_count(0) {}
+ TokenSection(TokenContainer tokenContainer,
+ const int start, const int count)
+ :m_tokenContainer(tokenContainer), m_start(start), m_count(count) {}
+
+ inline int count() const
+ { return m_count; }
+ inline QByteArray text(const int index) const
+ {
+ const int cIndex = containerIndex(index);
+ Q_ASSERT(cIndex < m_tokenContainer.count());
+ return m_tokenContainer.text(cIndex);
+ }
+ inline QByteArray tempText(const int index) const
+ {
+ const int cIndex = containerIndex(index);
+ Q_ASSERT(cIndex < m_tokenContainer.count());
+ return m_tokenContainer.tempText(cIndex);
+ }
+ QByteArray fullText() const;
+ inline TokenContainer tokenContainer(const int index = 0) const
+ { Q_UNUSED(index); return m_tokenContainer; }
+ inline int containerIndex(const int index) const
+ { return m_start + index; }
+ TokenTempRef tokenTempRef(const int index) const
+ {
+ const int cIndex = containerIndex(index);
+ Q_ASSERT(cIndex < m_tokenContainer.count());
+ return m_tokenContainer.tokenTempRef(cIndex);
+ }
+private:
+ TokenContainer m_tokenContainer;
+ int m_start;
+ int m_count;
+};
+
+/*
+ A list of tokens from a tokenContainer
+*/
+class TokenList
+{
+public:
+ TokenList() {};
+ TokenList(TokenContainer tokenContainer, QVector<int> tokenList)
+ :m_tokenContainer(tokenContainer), m_tokenList(tokenList) {}
+ inline int count() const
+ { return m_tokenList.count(); }
+ inline QByteArray text(const int index) const
+ {
+ const int cIndex = containerIndex(index);
+ Q_ASSERT(cIndex < m_tokenContainer.count());
+ return m_tokenContainer.text(cIndex);
+ }
+ inline QByteArray tempText(const int index) const
+ {
+ const int cIndex = containerIndex(index);
+ Q_ASSERT(cIndex < m_tokenContainer.count());
+ return m_tokenContainer.tempText(cIndex);
+ }
+ QByteArray fullText() const;
+ inline TokenContainer tokenContainer(const int index) const
+ { Q_UNUSED(index); return m_tokenContainer; }
+ inline int containerIndex(const int index) const
+ { return m_tokenList.at(index); }
+ Token token(const int index) const
+ {
+ const int cIndex = containerIndex(index);
+ Q_ASSERT(cIndex < m_tokenContainer.count());
+ return m_tokenContainer.token(cIndex);
+ }
+
+private:
+ TokenContainer m_tokenContainer;
+ QVector<int> m_tokenList;
+};
+
+/*
+ Combines a list of TokenSequences into one TokenSectionSequence
+*/
+class TokenSectionSequenceIterator;
+class TokenSectionSequence
+{
+public:
+ TokenSectionSequence() :m_count(0) {};
+ TokenSectionSequence(QVector<TokenSection> tokenSections);
+
+ QByteArray fullText() const;
+ int count() const;
+ QVector<TokenSection> tokenSections() const;
+
+ //random access interface, access time is linear on the number of sections
+ QByteArray text(const int index) const;
+ QByteArray tempText(const int index) const;
+ TokenContainer tokenContainer(const int index) const;
+ int containerIndex(const int index) const;
+
+protected:
+ int findSection(const int index) const;
+ int calculateInternalIndex(const int index, const int sectionIndex) const;
+private:
+ QVector<TokenSection> m_tokenSections;
+ QVector<int> m_startIndexes;
+ int m_count;
+ friend class TokenSectionSequenceIterator;
+};
+
+//sequental access interface, constant access time.
+class TokenSectionSequenceIterator
+{
+public:
+ TokenSectionSequenceIterator(const TokenSectionSequence &tokenSectionSequence);
+ void reset();
+ bool nextToken();
+ QByteArray text() const;
+ QByteArray tempText() const;
+ TokenContainer tokenContainer() const;
+ int containerIndex() const;
+ TokenTempRef tokenTempRef() const;
+private:
+ int m_currentSection;
+ int m_currentToken; // token index in currentTokenSequence;
+ const int m_numSections;
+ const TokenSectionSequence &m_tokenSectionSequence;
+};
+
+template <typename TokenSequence>
+QByteArray getText(TokenSequence tokenSequence)
+{
+ QByteArray text;
+ for (int t = 0; t<tokenSequence.count(); ++t) {
+ text += tokenSequence.text(t);
+ }
+ return text;
+}
+
+/*
+ Append the text and the tokens from the range [startToken, startToken + numTokens>
+ to text and tokenList.
+*/
+template <typename TokenSequenceType>
+void copy(QByteArray &text, QVector<TokenEngine::Token> &tokenList, const TokenSequenceType &tokenSequence, int startToken, int numTokens)
+{
+ const int endToken = startToken + numTokens;
+ int textIndex = text.count();
+ for(int t = startToken; t < endToken; ++t) {
+ const QByteArray tokenText = tokenSequence.text(t);
+ const int tokenLength = tokenText.count();
+ TokenEngine::Token token(textIndex, tokenLength);
+ tokenList.append(token);
+ text += tokenSequence.text(t);
+ textIndex += tokenText.count();
+ }
+}
+
+/*
+ Copy a the range [startToken, startToken + numTokens> from a tokenSequence to a new
+ TokenConrtainer.
+*/
+template <typename TokenSequenceType>
+TokenContainer copy(const TokenSequenceType &tokenSequence, int startToken, int numTokens)
+{
+ QByteArray containerText;
+ QVector<Token> tokens;
+ tokens.reserve(numTokens);
+ TokenEngine::copy(containerText, tokens, tokenSequence, startToken, numTokens);
+ return TokenContainer(containerText, tokens);
+}
+
+} //namespace TokenEngine
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/tokenizer.cpp b/tools/porting/src/tokenizer.cpp
new file mode 100644
index 0000000000..4dcaa466c8
--- /dev/null
+++ b/tools/porting/src/tokenizer.cpp
@@ -0,0 +1,491 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tokenizer.h"
+#include "tokens.h"
+#include <QDateTime>
+#include <QHash>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+using TokenEngine::Token;
+
+static QHash<QByteArray, bool> preprocessed;
+bool Tokenizer::s_initialized = false;
+Tokenizer::scan_fun_ptr Tokenizer::s_scan_table[128 + 1];
+int Tokenizer::s_attr_table[256];
+
+Tokenizer::Tokenizer()
+ : m_buffer(0), m_ptr(0)
+{
+ if (!s_initialized)
+ setupScanTable();
+}
+
+Tokenizer::~Tokenizer()
+{
+}
+
+enum
+{
+ A_Alpha = 0x01,
+ A_Digit = 0x02,
+ A_Alphanum = A_Alpha | A_Digit,
+ A_Whitespace = 0x04
+};
+
+void Tokenizer::setupScanTable()
+{
+ s_initialized = true;
+
+ memset(s_attr_table, 0, 256);
+
+ for (int i=0; i<128; ++i) {
+ switch (i) {
+ case ':':
+ case '*':
+ case '%':
+ case '^':
+ case '=':
+ case '!':
+ case '&':
+ case '|':
+ case '+':
+ case '<':
+ case '>':
+ case '-':
+ case '.':
+ s_scan_table[i] = &Tokenizer::scanOperator;
+ break;
+
+ case '\r':
+ case '\n':
+ s_scan_table[i] = &Tokenizer::scanNewline;
+ break;
+
+ case '#':
+ s_scan_table[i] = &Tokenizer::scanPreprocessor;
+ break;
+
+ case '/':
+ s_scan_table[i] = &Tokenizer::scanComment;
+ break;
+
+ case '\'':
+ s_scan_table[i] = &Tokenizer::scanCharLiteral;
+ break;
+
+ case '"':
+ s_scan_table[i] = &Tokenizer::scanStringLiteral;
+ break;
+
+ default:
+ if (isspace(i)) {
+ s_scan_table[i] = &Tokenizer::scanWhiteSpaces;
+ s_attr_table[i] |= A_Whitespace;
+ } else if (isalpha(i) || i == '_') {
+ s_scan_table[i] = &Tokenizer::scanIdentifier;
+ s_attr_table[i] |= A_Alpha;
+ } else if (isdigit(i)) {
+ s_scan_table[i] = &Tokenizer::scanNumberLiteral;
+ s_attr_table[i] |= A_Digit;
+ } else
+ s_scan_table[i] = &Tokenizer::scanChar;
+ }
+ }
+
+ s_scan_table[128] = &Tokenizer::scanUnicodeChar;
+}
+
+QVector<TokenEngine::Token> Tokenizer::tokenize(QByteArray text)
+{
+ m_tokens.clear();
+
+ m_buffer = text;
+ m_ptr = 0;
+
+ // tokenize
+ for (;;) {
+ Token tk;
+ bool endOfFile = nextToken(tk);
+ if (endOfFile) {
+ break;
+ }
+ m_tokens.append(tk);
+ }
+
+ return m_tokens;
+}
+
+bool Tokenizer::nextToken(Token &tok)
+{
+ int start = m_ptr;
+ unsigned char ch = (unsigned char)m_buffer[m_ptr];
+
+ int kind = 0;
+ (this->*s_scan_table[ch < 128 ? ch : 128])(&kind);
+
+ tok.start = start;
+ tok.length = m_ptr - start;
+
+ return (kind == 0);
+}
+
+void Tokenizer::scanChar(int *kind)
+{
+ *kind = m_buffer[m_ptr++];
+}
+
+void Tokenizer::scanWhiteSpaces(int *kind)
+{
+ *kind = Token_whitespaces;
+ while (unsigned char ch = m_buffer[m_ptr]) {
+ if (s_attr_table[ch] & A_Whitespace)
+ ++m_ptr;
+ else
+ break;
+ }
+}
+
+void Tokenizer::scanNewline(int *kind)
+{
+ Q_UNUSED(kind);
+ const unsigned char ch = m_buffer[m_ptr++];
+ // Check for \n.
+ if (ch == '\n') {
+ *kind = '\n';
+ return;
+ }
+
+ // Check for \r\n.
+ if (ch == '\r' && m_buffer[m_ptr] == '\n') {
+ *kind = '\n';
+ ++ m_ptr;
+ return;
+ }
+
+ *kind = ch;
+}
+
+void Tokenizer::scanUnicodeChar(int *kind)
+{
+ *kind = m_buffer[m_ptr++];
+}
+
+void Tokenizer::scanCharLiteral(int *kind)
+{
+ ++m_ptr;
+ for (;;) {
+ unsigned char ch = m_buffer[m_ptr];
+ switch (ch) {
+ case '\0':
+ case '\n':
+ // ### error
+ *kind = Token_char_literal;
+ return;
+ case '\\':
+ if (m_buffer[m_ptr+1] == '\'' || m_buffer[m_ptr+1] == '\\')
+ m_ptr += 2;
+ else
+ ++m_ptr;
+ break;
+ case '\'':
+ ++m_ptr;
+ *kind = Token_char_literal;
+ return;
+ default:
+ ++m_ptr;
+ break;
+ }
+ }
+
+ // ### error
+ *kind = Token_char_literal;
+}
+
+void Tokenizer::scanStringLiteral(int *kind)
+{
+ ++m_ptr;
+ while (m_buffer[m_ptr]) {
+ switch (m_buffer[m_ptr]) {
+ case '\n':
+ // ### error
+ *kind = Token_string_literal;
+ return;
+ case '\\':
+ if (m_buffer[m_ptr+1] == '"' || m_buffer[m_ptr+1] == '\\')
+ m_ptr += 2;
+ else
+ ++m_ptr;
+ break;
+ case '"':
+ ++m_ptr;
+ *kind = Token_string_literal;
+ return;
+ default:
+ ++m_ptr;
+ break;
+ }
+ }
+
+ // ### error
+ *kind = Token_string_literal;
+}
+
+void Tokenizer::scanIdentifier(int *kind)
+{
+ unsigned char ch;
+ for (;;) {
+ ch = m_buffer[m_ptr];
+ if (s_attr_table[ch] & A_Alphanum)
+ ++m_ptr;
+ else
+ break;
+ }
+ *kind = Token_identifier;
+}
+
+void Tokenizer::scanNumberLiteral(int *kind)
+{
+ unsigned char ch;
+ for (;;) {
+ ch = m_buffer[m_ptr];
+ if (s_attr_table[ch] & A_Alphanum || ch == '.')
+ ++m_ptr;
+ else
+ break;
+ }
+
+ // ### finish to implement me!!
+ *kind = Token_number_literal;
+}
+
+void Tokenizer::scanComment(int *kind)
+{
+ if (!(m_buffer[m_ptr+1] == '/' || m_buffer[m_ptr+1] == '*')) {
+ scanOperator(kind);
+ return;
+ }
+
+ ++m_ptr; // skip '/'
+
+ bool multiLineComment = m_buffer[m_ptr++] == '*';
+
+ while (m_buffer[m_ptr]) {
+ switch (m_buffer[m_ptr]) {
+ case '\r':
+ case '\n':
+ if (!multiLineComment) {
+ *kind = Token_comment;
+ return;
+ }
+
+ (void) scanNewline(kind);
+ break;
+
+ case '*':
+ if (multiLineComment && m_buffer[m_ptr+1] == '/') {
+ m_ptr += 2;
+ *kind = Token_comment;
+ return;
+ }
+ ++m_ptr;
+ break;
+
+ default:
+ ++m_ptr;
+ }
+ }
+
+ // ### error
+ *kind = Token_comment;
+}
+
+
+void Tokenizer::scanPreprocessor(int *kind)
+{
+ ++m_ptr;
+ *kind = Token_preproc;
+}
+
+
+void Tokenizer::scanOperator(int *kind)
+{
+ switch (m_buffer[m_ptr]) {
+ case ':':
+ if (m_buffer[m_ptr+1] == ':') {
+ m_ptr += 2;
+ *kind = Token_scope;
+ return;
+ }
+ break;
+
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '=':
+ case '!':
+ if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_eq;
+ return;
+ }
+ break;
+
+ case '&':
+ if (m_buffer[m_ptr+1] == '&') {
+ m_ptr += 2;
+ *kind = Token_and;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '|':
+ if (m_buffer[m_ptr+1] == '|' ) {
+ m_ptr += 2;
+ *kind = Token_or;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '+':
+ if (m_buffer[m_ptr+1] == '+' ) {
+ m_ptr += 2;
+ *kind = Token_incr;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '<':
+ if (m_buffer[m_ptr+1] == '<') {
+ if (m_buffer[m_ptr+2] == '=') {
+ m_ptr += 3;
+ *kind = Token_assign;
+ return;
+ }
+ m_ptr += 2;
+ *kind = Token_shift;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_leq;
+ return;
+ }
+ break;
+
+ case '>':
+ if (m_buffer[m_ptr+1] == '>') {
+ if (m_buffer[m_ptr+2] == '=') {
+ m_ptr += 3;
+ *kind = Token_assign;
+ return;
+ }
+ m_ptr += 2;
+ *kind = Token_shift;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_geq;
+ return;
+ }
+ break;
+
+ case '-':
+ if (m_buffer[m_ptr+1] == '>') {
+ if (m_buffer[m_ptr+2] == '*') {
+ m_ptr += 3;
+ *kind = Token_ptrmem;
+ return;
+ }
+ m_ptr += 2;
+ *kind = Token_arrow;
+ return;
+ } else if (m_buffer[m_ptr+1] == '-') {
+ m_ptr += 2;
+ *kind = Token_decr;
+ return;
+ } else if (m_buffer[m_ptr+1] == '=') {
+ m_ptr += 2;
+ *kind = Token_assign;
+ return;
+ }
+ break;
+
+ case '.':
+ if (m_buffer[m_ptr+1] == '.' && m_buffer[m_ptr+2] == '.') {
+ m_ptr += 3;
+ *kind = Token_ellipsis;
+ return;
+ } else if (m_buffer[m_ptr+1] == '*') {
+ m_ptr += 2;
+ *kind = Token_ptrmem;
+ return;
+ }
+ break;
+
+ }
+
+ *kind = m_buffer[m_ptr++];
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/tokenizer.h b/tools/porting/src/tokenizer.h
new file mode 100644
index 0000000000..b41aaf2063
--- /dev/null
+++ b/tools/porting/src/tokenizer.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOKENIZER_H
+#define TOKENIZER_H
+
+#include "tokenengine.h"
+#include <QVector>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+class Tokenizer
+{
+public:
+ Tokenizer();
+ ~Tokenizer();
+ typedef void (Tokenizer::*scan_fun_ptr)(int *kind);
+ QVector<TokenEngine::Token> tokenize(QByteArray text);
+private:
+ bool nextToken(TokenEngine::Token &tok);
+
+ void scanChar(int *kind);
+ void scanUnicodeChar(int *kind);
+ void scanNewline(int *kind);
+ void scanWhiteSpaces(int *kind);
+ void scanCharLiteral(int *kind);
+ void scanStringLiteral(int *kind);
+ void scanNumberLiteral(int *kind);
+ void scanIdentifier(int *kind);
+ void scanComment(int *kind);
+ void scanPreprocessor(int *kind);
+ void scanOperator(int *kind);
+
+ void setupScanTable();
+private:
+ static bool s_initialized;
+ static scan_fun_ptr s_scan_table[];
+ static int s_attr_table[];
+
+ const char *m_buffer;
+ int m_ptr;
+
+ QVector<TokenEngine::Token> m_tokens;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/tokenreplacements.cpp b/tools/porting/src/tokenreplacements.cpp
new file mode 100644
index 0000000000..acf9ab9a00
--- /dev/null
+++ b/tools/porting/src/tokenreplacements.cpp
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tokenreplacements.h"
+#include "logger.h"
+#include "portingrules.h"
+
+QT_BEGIN_NAMESPACE
+using namespace TokenEngine;
+
+void addLogSourceEntry(const QString &text, const TokenContainer &tokenContainer, const int index)
+{
+ Logger *logger = Logger::instance();
+ int line = tokenContainer.line(index);
+ int col = tokenContainer.column(index);
+ SourcePointLogEntry *logEntry =
+ new SourcePointLogEntry(QLatin1String("Info"), QLatin1String("Porting"),
+ logger->globalState.value(QLatin1String("currentFileName")),
+ line, col, text);
+ logger->addEntry(logEntry);
+}
+
+void addLogWarning(const QString &text)
+{
+ Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Warning"), QLatin1String("Porting"), text));
+}
+
+QualifiedNameParser::QualifiedNameParser(const TokenContainer &tokenContainer, const int tokenIndex)
+:tokenContainer(tokenContainer)
+,currentIndex(tokenIndex)
+{
+ Q_ASSERT(isValidIndex(currentIndex));
+}
+
+bool QualifiedNameParser::isPartOfQualifiedName()
+{
+ return ((nextScopeToken(Left) != -1) || (nextScopeToken(Right) != -1));
+}
+
+
+bool QualifiedNameParser::isValidIndex(int index)
+{
+ return (index < tokenContainer.count() && index >= 0);
+}
+
+/*
+ A qualifier is a the leftmost or middle part of a qualified name
+*/
+bool QualifiedNameParser::isQualifier()
+{
+ return (nextScopeToken(Right) != -1);
+}
+
+/*
+ A name is a the rightmost part of a qualified name.
+*/
+bool QualifiedNameParser::isName()
+{
+ return (nextScopeToken(Left) != -1);
+}
+
+/*
+ Peek for a qualifier or name in the given direction
+*/
+int QualifiedNameParser::peek(Direction direction)
+{
+ return nextScopeToken(direction);
+}
+
+/*
+ Look for a qualifier or name in the given direction,update
+ current position if found.
+*/
+int QualifiedNameParser::move(Direction direction)
+{
+ int tokenIndex = nextScopeToken(direction);
+ if(tokenIndex != -1)
+ currentIndex = tokenIndex;
+ return tokenIndex;
+}
+
+/*
+ Looks for "::" starting at currentIndex, returns the token index
+ for it if found. If the first non-whitespace token found is something else,
+ -1 is returned.
+*/
+int QualifiedNameParser::findScopeOperator(Direction direction)
+{
+ int tokenIndex = currentIndex;
+ QByteArray tokenText;
+ //loop until we get a token containg text or we pass the beginning/end of the source
+ tokenIndex += direction;
+ while(tokenText.isEmpty() && isValidIndex(tokenIndex)) {
+ tokenText = tokenContainer.text(tokenIndex).trimmed();
+ if(tokenText==QByteArray("::"))
+ return tokenIndex;
+ tokenIndex += direction;
+ }
+ return -1;
+}
+/*
+ Walks a qualified name. Returns the token index
+ for the next identifer in the qualified name, or -1 if its not found.
+*/
+int QualifiedNameParser::nextScopeToken(Direction direction)
+{
+ int tokenIndex = findScopeOperator(direction);
+ if (tokenIndex == -1)
+ return -1;
+ QByteArray tokenText;
+ //loop until we get a token containg text or we pass the start of the source
+ tokenIndex += direction;
+ while(tokenText.isEmpty() && isValidIndex(tokenIndex)) {
+ tokenText = tokenContainer.text(tokenIndex).trimmed();
+ tokenIndex += direction;
+ }
+ return tokenIndex - direction;
+}
+
+/////////////////////
+GenericTokenReplacement::GenericTokenReplacement(QByteArray oldToken, QByteArray newToken)
+:oldToken(oldToken)
+,newToken(newToken)
+{}
+
+QByteArray GenericTokenReplacement::getReplaceKey()
+{
+ return QByteArray(oldToken);
+}
+
+bool GenericTokenReplacement::doReplace(const TokenContainer &tokenContainer,
+ int index, TextReplacements &textReplacements)
+{
+ QByteArray tokenText = tokenContainer.text(index);
+ if(tokenText == oldToken){
+ addLogSourceEntry(QString::fromLatin1(tokenText + QByteArray(" -> ") + newToken), tokenContainer, index);
+ TokenEngine::Token token = tokenContainer.token(index);
+ textReplacements.insert(newToken, token.start, token.length);
+ return true;
+ }
+ return false;
+
+}
+
+///////////////////
+ClassNameReplacement::ClassNameReplacement(QByteArray oldToken, QByteArray newToken)
+:oldToken(oldToken)
+,newToken(newToken)
+{}
+
+QByteArray ClassNameReplacement::getReplaceKey()
+{
+ return QByteArray(oldToken);
+}
+
+/*
+ Replace a class name token. If the class name is a scope specifier (a "qualifier")
+ in a qualified name, we check if qualified name will be replaced by a porting rule.
+ If so, we don't do the class name replacement.
+*/
+bool ClassNameReplacement::doReplace(const TokenContainer &tokenContainer, int index, TextReplacements &textReplacements)
+{
+ QByteArray tokenText = tokenContainer.text(index);
+ if(tokenText != oldToken)
+ return false;
+
+ QualifiedNameParser nameParser(tokenContainer, index);
+ if(nameParser.isPartOfQualifiedName() &&
+ nameParser.peek(QualifiedNameParser::Right) != -1) {
+ int nameTokenIndex = nameParser.peek(QualifiedNameParser::Right);
+ QByteArray name = tokenContainer.text(nameTokenIndex);
+ TextReplacements textReplacements;
+ QList<TokenReplacement*> tokenReplacements
+ = PortingRules::instance()->getTokenReplacementRules();
+ bool changed = false;
+ foreach(TokenReplacement *tokenReplacement, tokenReplacements) {
+ changed = tokenReplacement->doReplace(tokenContainer, nameTokenIndex, textReplacements);
+ if(changed)
+ break;
+ }
+ if(changed)
+ return false;
+ }
+ addLogSourceEntry(QString::fromLatin1(tokenText + QByteArray(" -> ") + newToken), tokenContainer, index);
+ TokenEngine::Token token = tokenContainer.token(index);
+ textReplacements.insert(newToken, token.start, token.length);
+ return true;
+}
+
+///////////////////
+
+ScopedTokenReplacement::ScopedTokenReplacement(const QByteArray &oldToken,
+ const QByteArray &newToken)
+:newScopedName(newToken)
+{
+ Q_ASSERT(oldToken.contains(QByteArray("::")));
+
+ // Split oldToken into scope and name parts.
+ oldName = oldToken.mid(oldToken.lastIndexOf(':')+1);
+ oldScope = oldToken.mid(0, oldToken.indexOf(':'));
+
+ // Split newToken into scope and name parts, execept if we have a spcial
+ // case like Qt::WType_Modal -> (Qt::WType_Dialog | Qt::WShowModal)
+ if (newToken.count(QByteArray("::")) != 1 || newToken.contains(QByteArray("("))) {
+ newName = newToken;
+ } else {
+ newName = newToken.mid(newToken.lastIndexOf(':')+1);
+ newScope = newToken.mid(0, newToken.indexOf(':'));
+ }
+
+ strictMode = Logger::instance()->globalState.contains(QString::fromLatin1("strictMode"));
+}
+
+bool ScopedTokenReplacement::doReplace(const TokenContainer &tokenContainer, int sourceIndex, TextReplacements &textReplacements)
+{
+ const QByteArray sourceName = tokenContainer.text(sourceIndex);
+
+ // Check if the token texts matches.
+ if (sourceName != oldName)
+ return false;
+
+ // Get token attributes. The attributes are created by the the C++ parser/analyzer.
+ const TokenAttributes *attributes = tokenContainer.tokenAttributes();
+ // If the declaration attribute is set we don't replace.
+ if (!attributes->attribute(sourceIndex, "declaration").isEmpty())
+ return false;
+ // If the unknown (undeclared) attribute is set we don't replace.
+ if (!attributes->attribute(sourceIndex, "unknown").isEmpty())
+ return false;
+ // If nameUse is set we test if the nameUse refers to the correct declaration.
+ // This is done by checking the parentScope attriute, wich returns the scope
+ // for the declaration associated with this name use.
+ const bool haveNameUseInfo = !attributes->attribute(sourceIndex, "nameUse").isEmpty();
+ if (haveNameUseInfo) {
+ if (attributes->attribute(sourceIndex, "parentScope") != oldScope)
+ return false;
+ // If the user has specified -strict, we don't replace tokens when we don't have name use info.
+ } else if (strictMode) {
+ return false;
+ }
+
+ // The token might have a qualifier, and in that case we need to check if
+ // we should replace the qualifier as well.
+ QualifiedNameParser nameParser(tokenContainer, sourceIndex);
+
+ // This is a pretty special case, it means that in a qualified
+ // name like aaa::bbb the replacement rule has been triggered for
+ // the aaa part. Since this is not what we'd normally use a
+ // ScopedReplacement for, we just return here.
+ if (nameParser.isQualifier())
+ return false;
+
+ // If the token is unqualified, just replace it.
+ if (!nameParser.isPartOfQualifiedName()) {
+ // If we have no name use info we try to avoid replacements of
+ // e.g. Vertical with QSizePolicy::Vertically. Unqualified tokens
+ // can't happen for classes one does not usually inherit from, so
+ // we only let them pass for stuff that people usually inherited from.
+ if (!haveNameUseInfo && newScope != "Qt" && newScope != "QFrame" && newScope != "QValidator")
+ return false;
+
+ const Token sourceToken = tokenContainer.token(sourceIndex);
+ addLogSourceEntry(QString::fromLatin1(sourceName + QByteArray(" -> ") + newScopedName), tokenContainer, sourceIndex);
+ textReplacements.insert(newScopedName, sourceToken.start, sourceName.size());
+ return true;
+ }
+
+ // Peek left for the qualifer token.
+ const int sourceScopeIndex = nameParser.peek(QualifiedNameParser::Left);
+ if (sourceScopeIndex == -1) {
+ return false;
+ }
+
+ const Token sourceNameToken = tokenContainer.token(sourceIndex);
+ const Token sourceScopeToken = tokenContainer.token(sourceScopeIndex);
+ const QByteArray sourceScope = tokenContainer.text(sourceScopeIndex);
+
+ // If we have no name use info and the source and old scopes don't match,
+ // we generally dont't do a replace, unless the old scope is Qt and
+ // the source scope inherits Qt. For example, QWidget::ButtonState should
+ // be renamed to Qt::ButtonState.
+ if (!haveNameUseInfo && sourceScope != oldScope) {
+ if (oldScope != "Qt")
+ return false;
+ // Check if sourceScope inherits the Qt class.
+ if (!PortingRules::instance()->getInheritsQt().contains(QString::fromLatin1(sourceScope.constData()))) //TODO optimize: linear search
+ return false;
+ }
+
+ // Spcecial cases, such as QIODevice::Offset -> Q_LONGLONG
+ // or Qt::WType_Modal -> (Qt::WType_Dialog | Qt::WShowModal).
+ if (newScope.isEmpty()) {
+ addLogSourceEntry(QString::fromLatin1((sourceScope + QByteArray("::") + sourceName +
+ QByteArray(" -> ") + newScopedName).constData()), tokenContainer, sourceIndex);
+ const int qualiferLength = sourceNameToken.start - sourceScopeToken.start;
+ const int length = qualiferLength + sourceNameToken.length;
+ textReplacements.insert(newName, sourceScopeToken.start, length);
+ return true;
+ }
+
+ // If the old and new scopes are equal, we replace the name part only.
+ if (newScope == sourceScope) {
+ // If the names are equal, there is no need to do anything.
+ if (newName == sourceName)
+ return true;
+ addLogSourceEntry(QString::fromLatin1((sourceName + QByteArray(" -> ") + newName).constData()), tokenContainer, sourceIndex);
+ textReplacements.insert(newName, sourceNameToken.start, sourceNameToken.length);
+ return true;
+ }
+
+ // If the names are equal, replace scope only.
+ if (newName == sourceName) {
+ addLogSourceEntry(QString::fromLatin1((sourceScope + QByteArray(" -> ") + newScope).constData()), tokenContainer, sourceScopeIndex);
+ textReplacements.insert(newScope, sourceScopeToken.start, sourceScopeToken.length);
+ return true;
+ }
+
+ // Replace scope and name.
+ addLogSourceEntry(QString::fromLatin1((sourceScope + QByteArray("::") + sourceName +
+ QByteArray(" -> ") + newScopedName).constData()),
+ tokenContainer, sourceScopeIndex);
+ textReplacements.insert(newScope, sourceScopeToken.start, sourceScopeToken.length);
+ textReplacements.insert(newName, sourceNameToken.start, sourceNameToken.length);
+ return true;
+}
+
+QByteArray ScopedTokenReplacement::getReplaceKey()
+{
+ return oldName;
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/tokenreplacements.h b/tools/porting/src/tokenreplacements.h
new file mode 100644
index 0000000000..e92a68c137
--- /dev/null
+++ b/tools/porting/src/tokenreplacements.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOKENREPLACEMENTS_H
+#define TOKENREPLACEMENTS_H
+
+#include "tokenengine.h"
+#include "textreplacement.h"
+#include <QStringList>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+void addLogSourceEntry(const QString &text, const TokenEngine::TokenContainer&, const int index);
+void addLogWarning(const QString &text);
+
+class TokenReplacement
+{
+public:
+
+ virtual bool doReplace(const TokenEngine::TokenContainer& ,
+ int /*tokenIndex*/,
+ TextReplacements&){return false;};
+ /*
+ returns the replace key for this replacement. Every time a token matches the replace key,
+ doReplace() will be called for this TokenReplacement.
+ */
+ virtual QByteArray getReplaceKey(){return QByteArray();};
+ virtual ~TokenReplacement(){};
+};
+
+/*
+ A TokenReplacement that change any token
+*/
+class GenericTokenReplacement : public TokenReplacement
+{
+public:
+ GenericTokenReplacement(QByteArray oldToken, QByteArray newToken);
+ bool doReplace(const TokenEngine::TokenContainer &tokenContainer,
+ int tokenIndex, TextReplacements &textReplacements);
+ QByteArray getReplaceKey();
+private:
+ QByteArray oldToken;
+ QByteArray newToken;
+};
+
+/*
+ A TokenReplacement that changes tokens that specify class names.
+ In some cases where the class name token is a part of a qualified name
+ it is not correct to rename it. ex:
+
+ QButton::toggleState
+
+ Here it is wrong to rename QButton -> Q3Button, since there is
+ a rule that says QButton::ToggleState -> QCheckBox::ToggleState,
+ but no rule for Q3Button::ToggleState.
+*/
+class ClassNameReplacement : public TokenReplacement
+{
+public:
+ ClassNameReplacement(QByteArray oldToken, QByteArray newToken);
+ bool doReplace(const TokenEngine::TokenContainer &tokenContainer,
+ int tokenIndex, TextReplacements &textReplacements);
+ QByteArray getReplaceKey();
+private:
+ QByteArray oldToken;
+ QByteArray newToken;
+};
+
+/*
+ Changes scoped tokens:
+ AA::BB -> CC::DD
+ oldToken corresponds to the AA::BB part, newToken corresponds CC::DD.
+ Since this is a token replacement, the AA part of oldToken is typically
+ unknown. This means that we might change tokens named BB that does not belong
+ to the AA scope. Ast replacemnts will fix this.
+
+*/
+class ScopedTokenReplacement : public TokenReplacement
+{
+public:
+ ScopedTokenReplacement(const QByteArray &oldToken, const QByteArray &newToken);
+ bool doReplace(const TokenEngine::TokenContainer &tokenContainer,
+ int tokenIndex, TextReplacements &textReplacements);
+ QByteArray getReplaceKey();
+private:
+ QByteArray oldName;
+ QByteArray oldScope;
+ QByteArray newName;
+ QByteArray newScope;
+ QByteArray newScopedName;
+ bool strictMode;
+};
+
+class QualifiedNameParser
+{
+public:
+ QualifiedNameParser(const TokenEngine::TokenContainer &tokenContainer,
+ const int tokenIndex);
+ enum Direction { Left=-1, Right=1 };
+ bool isPartOfQualifiedName();
+ bool isValidIndex(int index);
+ bool isQualifier();
+ bool isName();
+ int peek(Direction direction);
+ int move(Direction direction);
+private:
+ int nextScopeToken(Direction direction);
+ int findScopeOperator(Direction direction);
+ const TokenEngine::TokenContainer tokenContainer;
+ int currentIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/tokens.h b/tools/porting/src/tokens.h
new file mode 100644
index 0000000000..09154fdc3f
--- /dev/null
+++ b/tools/porting/src/tokens.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOKENS_H
+#define TOKENS_H
+
+#include <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+enum Type
+{
+ Token_eof = 0,
+ Token_newline = 10,
+ Token_identifier = 1000,
+ Token_number_literal,
+ Token_char_literal,
+ Token_string_literal,
+ Token_whitespaces,
+ Token_comment,
+ Token_preproc,
+ Token_line_comment,
+ Token_multiline_comment,
+
+ Token_assign = 2000,
+ Token_ptrmem,
+ Token_ellipsis,
+ Token_scope,
+ Token_shift,
+ Token_eq,
+ Token_leq,
+ Token_geq,
+ Token_incr,
+ Token_decr,
+ Token_arrow,
+
+ Token_concat,
+
+ Token___typeof,
+
+ Token_K_DCOP,
+ Token_k_dcop,
+ Token_k_dcop_signals,
+
+ Token_Q_OBJECT,
+ Token_signals,
+ Token_slots,
+ Token_emit,
+
+ Token_and,
+ Token_and_eq,
+ Token_asm,
+ Token_auto,
+ Token_bitand,
+ Token_bitor,
+ Token_bool,
+ Token_break,
+ Token_case,
+ Token_catch,
+ Token_char,
+ Token_class,
+ Token_compl,
+ Token_const,
+ Token_const_cast,
+ Token_continue,
+ Token_default,
+ Token_delete,
+ Token_do,
+ Token_double,
+ Token_dynamic_cast,
+ Token_else,
+ Token_enum,
+ Token_explicit,
+ Token_export,
+ Token_extern,
+ Token_false,
+ Token_float,
+ Token_for,
+ Token_friend,
+ Token_goto,
+ Token_if,
+ Token_inline,
+ Token_int,
+ Token_long,
+ Token_mutable,
+ Token_namespace,
+ Token_new,
+ Token_not,
+ Token_not_eq,
+ Token_operator,
+ Token_or,
+ Token_or_eq,
+ Token_private,
+ Token_protected,
+ Token_public,
+ Token_register,
+ Token_reinterpret_cast,
+ Token_return,
+ Token_short,
+ Token_signed,
+ Token_sizeof,
+ Token_static,
+ Token_static_cast,
+ Token_struct,
+ Token_switch,
+ Token_template,
+ Token_this,
+ Token_throw,
+ Token_true,
+ Token_try,
+ Token_typedef,
+ Token_typeid,
+ Token_typename,
+ Token_union,
+ Token_unsigned,
+ Token_using,
+ Token_virtual,
+ Token_void,
+ Token_volatile,
+ Token_wchar_t,
+ Token_while,
+ Token_xor,
+ Token_xor_eq,
+
+ Token_left_shift,
+ Token_right_shift,
+
+ // preprecessor
+ Token_directive_identifier,
+ Token_directive_if,
+ Token_directive_elif,
+ Token_directive_else,
+ Token_directive_undef,
+ Token_directive_endif,
+ Token_directive_ifdef,
+ Token_directive_ifndef,
+ Token_directive_define,
+ Token_directive_include,
+ Token_directive_line,
+ Token_directive_error,
+ Token_directive_pragma,
+ Token_defined
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/tokenstreamadapter.h b/tools/porting/src/tokenstreamadapter.h
new file mode 100644
index 0000000000..8983053851
--- /dev/null
+++ b/tools/porting/src/tokenstreamadapter.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOKENSTREAMADAPTER_H
+#define TOKENSTREAMADAPTER_H
+
+#include "tokenengine.h"
+#include "tokens.h"
+
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+namespace TokenStreamAdapter {
+struct TokenStream
+{
+ TokenStream(TokenEngine::TokenSectionSequence translationUnit, QVector<Type> tokenKindList)
+ :m_translationUnit(translationUnit),
+ m_tokenKindList(tokenKindList),
+ m_cursor(0),
+ m_numTokens(tokenKindList.count())
+ {
+ Q_ASSERT(translationUnit.count() == m_numTokens);
+
+ // Copy out the container and containerIndex for each token so we can have
+ // constant time random access to it.
+ TokenEngine::TokenSectionSequenceIterator it(translationUnit);
+ while(it.nextToken()) {
+ m_tokenContainers.append(it.tokenContainer());
+ m_containerIndices.append(it.containerIndex());
+ }
+ }
+
+ bool isHidden(int index) const
+ {
+ if(index >= m_numTokens)
+ return false;
+ QT_PREPEND_NAMESPACE(Type) type = m_tokenKindList.at(index);
+ return (type == Token_whitespaces || type == 10 /*newline*/ ||
+ type == Token_comment || type == Token_preproc );
+ }
+
+ inline int lookAhead(int n = 0) const
+ {
+ if(m_cursor + n >= m_numTokens)
+ return 0;
+ return m_tokenKindList.at(m_cursor + n);
+ }
+
+ inline int currentToken() const
+ { return lookAhead(); }
+
+ inline QByteArray currentTokenText() const
+ {
+ return tokenText(m_cursor);
+ }
+
+ inline TokenEngine::TokenContainer tokenContainer(int index = 0) const
+ {
+ if (index < m_numTokens)
+ return m_tokenContainers.at(index);
+ else
+ return TokenEngine::TokenContainer();
+ }
+
+ inline int containerIndex(int index = 0) const
+ {
+ if (index < m_numTokens)
+ return m_containerIndices.at(index);
+ else
+ return -1;
+ }
+
+ inline QByteArray tokenText(int index = 0) const
+ {
+ if (index < m_numTokens) {
+ const TokenEngine::TokenContainer container = tokenContainer(index);
+ const int cIndex = containerIndex(index);
+ return container.text(cIndex);
+ } else {
+ return QByteArray();
+ }
+ }
+
+ inline void rewind(int index)
+ { m_cursor = index; }
+
+ inline int cursor() const
+ { return m_cursor; }
+
+ inline void nextToken()
+ { ++m_cursor; }
+
+ inline bool tokenAtEnd()
+ { return m_cursor >= m_numTokens; }
+
+ TokenEngine::TokenSectionSequence tokenSections() const
+ { return m_translationUnit; }
+
+private:
+ TokenEngine::TokenSectionSequence m_translationUnit;
+ QVector<Type> m_tokenKindList;
+ QList<TokenEngine::TokenContainer> m_tokenContainers;
+ QList<int> m_containerIndices;
+ int m_cursor;
+ int m_numTokens;
+};
+
+} //namespace TokenStreamAdapter
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/translationunit.cpp b/tools/porting/src/translationunit.cpp
new file mode 100644
index 0000000000..b49225b58f
--- /dev/null
+++ b/tools/porting/src/translationunit.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "translationunit.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace TokenEngine;
+using namespace CodeModel;
+using namespace TokenStreamAdapter;
+
+TranslationUnit::TranslationUnit()
+{
+ TokenSectionSequence empty;
+ d = new TranslationUnitData(empty);
+}
+
+TranslationUnit::TranslationUnit(const TokenEngine::TokenSectionSequence &tokens)
+{ d = new TranslationUnitData(tokens); }
+
+TokenSectionSequence TranslationUnit::tokens() const
+{ return d->tokens; }
+
+void TranslationUnit::setCodeModel(NamespaceScope *globalScope)
+{ d->globalScope = globalScope; }
+
+NamespaceScope *TranslationUnit::codeModel()
+{ return d->globalScope; }
+
+TypedPool<CodeModel::Item> *TranslationUnit::codeModelMemoryPool()
+{ return &d->codeModelMemoryPool; }
+
+
+
+/*
+ Performs C++ parsing and semantic analysis on a translation unit.
+ Returns a TranslationUnit, which contains all the data.
+*/
+TranslationUnit TranslationUnitAnalyzer::analyze
+ (const TokenSectionSequence &translationUnitTokens, int targetMaxASTNodes)
+{
+ TranslationUnit translationUnit(translationUnitTokens);
+ CodeModel::NamespaceScope *codeModel =
+ CodeModel::Create<CodeModel::NamespaceScope>(translationUnit.codeModelMemoryPool());
+ translationUnit.setCodeModel(codeModel);
+
+ // run lexical analysis
+ QVector<QT_PREPEND_NAMESPACE(Type)> typeList = lexer.lex(translationUnitTokens);
+ TokenStreamAdapter::TokenStream tokenStream(translationUnitTokens, typeList);
+
+ Semantic semantic(codeModel, &tokenStream, translationUnit.codeModelMemoryPool());
+
+ // parse and run semantic on the translation unit
+ bool done = false;
+ while(!done) {
+ pool p;
+ TranslationUnitAST *node = parser.parse(&tokenStream, &p, targetMaxASTNodes, done);
+ semantic.parseTranslationUnit(node);
+ }
+
+ return translationUnit;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/translationunit.h b/tools/porting/src/translationunit.h
new file mode 100644
index 0000000000..0a378aed3a
--- /dev/null
+++ b/tools/porting/src/translationunit.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TRANSLATIONUNIT_H
+#define TRANSLATIONUNIT_H
+
+#include "tokenengine.h"
+#include "tokenstreamadapter.h"
+#include "ast.h"
+#include "codemodel.h"
+#include "smallobject.h"
+#include "cpplexer.h"
+#include "parser.h"
+#include "semantic.h"
+#include <QSharedData>
+
+QT_BEGIN_NAMESPACE
+
+class TranslationUnitData : public QSharedData
+{
+public:
+ TranslationUnitData(const TokenEngine::TokenSectionSequence &t)
+ :tokens(t), globalScope(0) {};
+ TokenEngine::TokenSectionSequence tokens;
+ CodeModel::NamespaceScope *globalScope;
+ TypedPool<CodeModel::Item> codeModelMemoryPool;
+};
+
+class TranslationUnit
+{
+public:
+ TranslationUnit();
+ TranslationUnit(const TokenEngine::TokenSectionSequence &tokens);
+ TokenEngine::TokenSectionSequence tokens() const;
+ CodeModel::NamespaceScope *codeModel();
+ TypedPool<CodeModel::Item> *codeModelMemoryPool();
+private:
+ friend class TranslationUnitAnalyzer;
+ void setCodeModel(CodeModel::NamespaceScope *globalScope);
+ QExplicitlySharedDataPointer<TranslationUnitData> d;
+};
+
+class TranslationUnitAnalyzer
+{
+public:
+ TranslationUnit analyze
+ (const TokenEngine::TokenSectionSequence &translationUnitTokens, int targetMaxASTNodes = 10000);
+private:
+ CppLexer lexer;
+ Parser parser;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/porting/src/treewalker.cpp b/tools/porting/src/treewalker.cpp
new file mode 100644
index 0000000000..98ab60c1f3
--- /dev/null
+++ b/tools/porting/src/treewalker.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "treewalker.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+template <class T>
+inline void parseAll(TreeWalker *w, const List<T *> *l)
+{
+ if (!l)
+ return;
+
+ foreach(T *e, *l)
+ w->parseNode(e);
+}
+*/
+
+//Workaround for ICE on MSVC, use macro instead of template.
+#define PARSE_ALL(ListType, ListValueType) \
+inline void parseAll(TreeWalker *w, const ListType *l) \
+{ \
+ if (!l) \
+ return; \
+ foreach(ListValueType *e, *l) \
+ w->parseNode(e); \
+} \
+
+PARSE_ALL(List<AST *>, AST)
+PARSE_ALL(List<ClassOrNamespaceNameAST *>, ClassOrNamespaceNameAST)
+PARSE_ALL(List<BaseSpecifierAST *>, BaseSpecifierAST)
+PARSE_ALL(List<DeclarationAST *>, DeclarationAST)
+PARSE_ALL(List<EnumeratorAST *>, EnumeratorAST)
+PARSE_ALL(List<ParameterDeclarationAST *>, ParameterDeclarationAST)
+PARSE_ALL(List<InitDeclaratorAST *>, InitDeclaratorAST)
+PARSE_ALL(List<TemplateParameterAST *>, TemplateParameterAST)
+PARSE_ALL(List<StatementAST *>, StatementAST)
+
+
+void TreeWalker::parseTemplateArgumentList(TemplateArgumentListAST *node)
+{
+ List<AST *> *arglist = node->argumentList();
+ parseAll(this, arglist);
+}
+
+void TreeWalker::parseClassOrNamespaceName(ClassOrNamespaceNameAST *node)
+{
+ parseNode(node->name());
+ parseNode(node->templateArgumentList());
+}
+
+void TreeWalker::parseName(NameAST *node)
+{
+ parseAll(this, node->classOrNamespaceNameList());
+ parseNode(node->unqualifiedName());
+}
+
+void TreeWalker::parseTypeParameter(TypeParameterAST *node)
+{
+ parseNode(node->templateParameterList());
+ parseNode(node->name());
+ parseNode(node->typeId());
+}
+
+void TreeWalker::parseDeclaration(DeclarationAST *node)
+{
+ switch (node->nodeType()) {
+ case NodeType_AccessDeclaration:
+ parseAccessDeclaration(static_cast<AccessDeclarationAST*>(node));
+ break;
+ case NodeType_LinkageSpecification:
+ parseLinkageSpecification(static_cast<LinkageSpecificationAST*>(node));
+ break;
+ case NodeType_Namespace:
+ parseNamespace(static_cast<NamespaceAST*>(node));
+ break;
+ case NodeType_NamespaceAlias:
+ parseNamespaceAlias(static_cast<NamespaceAliasAST*>(node));
+ break;
+ case NodeType_Using:
+ parseUsing(static_cast<UsingAST*>(node));
+ break;
+ case NodeType_UsingDirective:
+ parseUsingDirective(static_cast<UsingDirectiveAST*>(node));
+ break;
+ case NodeType_Typedef:
+ parseTypedef(static_cast<TypedefAST*>(node));
+ break;
+ case NodeType_TemplateDeclaration:
+ parseTemplateDeclaration(static_cast<TemplateDeclarationAST*>(node));
+ break;
+ case NodeType_SimpleDeclaration:
+ parseSimpleDeclaration(static_cast<SimpleDeclarationAST*>(node));
+ break;
+ case NodeType_FunctionDefinition:
+ parseFunctionDefinition(static_cast<FunctionDefinitionAST*>(node));
+ break;
+ default:
+ break;
+ }
+}
+
+void TreeWalker::parseAccessDeclaration(AccessDeclarationAST *node)
+{
+ parseAll(this, node->accessList());
+}
+
+void TreeWalker::parseTypeSpecifier(TypeSpecifierAST *node)
+{
+ parseNode(node->name());
+ parseNode(node->cvQualify());
+ parseNode(node->cv2Qualify());
+
+ switch (node->nodeType()) {
+ case NodeType_ClassSpecifier:
+ parseClassSpecifier(static_cast<ClassSpecifierAST*>(node));
+ break;
+ case NodeType_EnumSpecifier:
+ parseEnumSpecifier(static_cast<EnumSpecifierAST*>(node));
+ break;
+ case NodeType_ElaboratedTypeSpecifier:
+ parseElaboratedTypeSpecifier(static_cast<ElaboratedTypeSpecifierAST*>(node));
+ break;
+ default:
+ break;
+ }
+}
+
+void TreeWalker::parseBaseSpecifier(BaseSpecifierAST *node)
+{
+ parseNode(node->isVirtual());
+ parseNode(node->access());
+ parseNode(node->name());
+}
+
+void TreeWalker::parseBaseClause(BaseClauseAST *node)
+{
+ parseAll(this, node->baseSpecifierList());
+}
+
+void TreeWalker::parseClassSpecifier(ClassSpecifierAST *node)
+{
+ parseNode(node->winDeclSpec());
+ parseNode(node->classKey());
+ parseNode(node->baseClause());
+ parseAll(this, node->declarationList());
+}
+
+void TreeWalker::parseEnumerator(EnumeratorAST *node)
+{
+ parseNode(node->id());
+ parseNode(node->expression());
+}
+
+void TreeWalker::parseEnumSpecifier(EnumSpecifierAST *node)
+{
+ parseAll(this, node->enumeratorList());
+}
+
+void TreeWalker::parseElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
+{
+ parseNode(node->kind());
+}
+
+void TreeWalker::parseLinkageBody(LinkageBodyAST *node)
+{
+ parseAll(this, node->declarationList());
+}
+
+void TreeWalker::parseLinkageSpecification(LinkageSpecificationAST *node)
+{
+ parseNode(node->externType());
+ parseNode(node->linkageBody());
+ parseNode(node->declaration());
+}
+
+void TreeWalker::parseNamespace(NamespaceAST *node)
+{
+ parseNode(node->namespaceName());
+ parseNode(node->linkageBody());
+}
+
+void TreeWalker::parseNamespaceAlias(NamespaceAliasAST *node)
+{
+ parseNode(node->namespaceName());
+ parseNode(node->aliasName());
+}
+
+void TreeWalker::parseUsing(UsingAST *node)
+{
+ parseNode(node->typeName());
+ parseNode(node->name());
+}
+
+void TreeWalker::parseUsingDirective(UsingDirectiveAST *node)
+{
+ parseNode(node->name());
+}
+
+void TreeWalker::parseDeclarator(DeclaratorAST *node)
+{
+ parseAll(this, node->ptrOpList());
+ parseNode(node->subDeclarator());
+ parseNode(node->declaratorId());
+ parseNode(node->bitfieldInitialization());
+ parseAll(this, node->arrayDimensionList());
+ parseNode(node->parameterDeclarationClause());
+ parseNode(node->constant());
+ parseNode(node->exceptionSpecification());
+}
+
+void TreeWalker::parseParameterDeclaration(ParameterDeclarationAST *node)
+{
+ parseNode(node->typeSpec());
+ parseNode(node->declarator());
+ parseNode(node->expression());
+}
+
+void TreeWalker::parseParameterDeclarationList(ParameterDeclarationListAST *node)
+{
+ parseAll(this, node->parameterList());
+}
+
+void TreeWalker::parseParameterDeclarationClause(ParameterDeclarationClauseAST *node)
+{
+ parseNode(node->parameterDeclarationList());
+ parseNode(node->ellipsis());
+}
+
+void TreeWalker::parseInitDeclarator(InitDeclaratorAST *node)
+{
+ parseNode(node->declarator());
+ parseNode(node->initializer());
+}
+
+void TreeWalker::parseInitDeclaratorList(InitDeclaratorListAST *node)
+{
+ parseAll(this, node->initDeclaratorList());
+}
+
+void TreeWalker::parseTypedef(TypedefAST *node)
+{
+ parseNode(node->typeSpec());
+ parseNode(node->initDeclaratorList());
+}
+
+void TreeWalker::parseTemplateParameter(TemplateParameterAST *node)
+{
+ parseNode(node->typeParameter());
+ parseNode(node->typeValueParameter());
+}
+
+void TreeWalker::parseTemplateParameterList(TemplateParameterListAST *node)
+{
+ parseAll(this, node->templateParameterList());
+}
+
+void TreeWalker::parseTemplateDeclaration(TemplateDeclarationAST *node)
+{
+ parseNode(node->exported());
+ parseNode(node->templateParameterList());
+ parseNode(node->declaration());
+}
+
+void TreeWalker::parseSimpleDeclaration(SimpleDeclarationAST *node)
+{
+ parseNode(node->functionSpecifier());
+ parseNode(node->storageSpecifier());
+ parseNode(node->typeSpec());
+ parseNode(node->initDeclaratorList());
+ parseNode(node->winDeclSpec());
+}
+
+void TreeWalker::parseStatement(StatementAST *node)
+{
+ switch (node->nodeType()) {
+ case NodeType_ExpressionStatement:
+ parseExpressionStatement(static_cast<ExpressionStatementAST*>(node));
+ break;
+
+ case NodeType_IfStatement:
+ parseIfStatement(static_cast<IfStatementAST*>(node));
+ break;
+
+ case NodeType_WhileStatement:
+ parseWhileStatement(static_cast<WhileStatementAST*>(node));
+ return;
+
+ case NodeType_DoStatement:
+ parseDoStatement(static_cast<DoStatementAST*>(node));
+ break;
+
+ case NodeType_ForStatement:
+ parseForStatement(static_cast<ForStatementAST*>(node));
+ break;
+
+ case NodeType_SwitchStatement:
+ parseSwitchStatement(static_cast<SwitchStatementAST*>(node));
+ break;
+
+ case NodeType_LabeledStatement:
+ parseLabeledStatement(static_cast<LabeledStatementAST*>(node));
+ break;
+
+ case NodeType_StatementList:
+ parseStatementList(static_cast<StatementListAST*>(node));
+ break;
+
+ case NodeType_DeclarationStatement:
+ parseDeclarationStatement(static_cast<DeclarationStatementAST*>(node));
+ break;
+
+ case NodeType_ReturnStatement:
+ parseReturnStatement(static_cast<ReturnStatementAST*>(node));
+ break;
+
+ default:
+ break;
+ }
+}
+
+void TreeWalker::parseExpressionStatement(ExpressionStatementAST *node)
+{
+ parseNode(node->expression());
+}
+
+void TreeWalker::parseCondition(ConditionAST *node)
+{
+ parseNode(node->typeSpec());
+ parseNode(node->declarator());
+ parseNode(node->expression());
+}
+
+void TreeWalker::parseIfStatement(IfStatementAST *node)
+{
+ parseNode(node->condition());
+ parseNode(node->statement());
+ parseNode(node->elseStatement());
+}
+
+void TreeWalker::parseWhileStatement(WhileStatementAST *node)
+{
+ parseNode(node->condition());
+ parseNode(node->statement());
+}
+
+void TreeWalker::parseDoStatement(DoStatementAST *node)
+{
+ parseNode(node->condition());
+ parseNode(node->statement());
+}
+
+void TreeWalker::parseForStatement(ForStatementAST *node)
+{
+ parseNode(node->initStatement());
+ parseNode(node->condition());
+ parseNode(node->expression());
+ parseNode(node->statement());
+}
+
+void TreeWalker::parseSwitchStatement(SwitchStatementAST *node)
+{
+ parseNode(node->condition());
+ parseNode(node->statement());
+}
+
+void TreeWalker::parseLabeledStatement(LabeledStatementAST *node)
+{
+ parseNode(node->expression());
+ parseNode(node->statement());
+}
+
+void TreeWalker::parseStatementList(StatementListAST *node)
+{
+ parseAll(this, node->statementList());
+}
+
+void TreeWalker::parseDeclarationStatement(DeclarationStatementAST *node)
+{
+ parseNode(node->declaration());
+}
+
+void TreeWalker::parseFunctionDefinition(FunctionDefinitionAST *node)
+{
+ parseNode(node->functionSpecifier());
+ parseNode(node->storageSpecifier());
+ parseNode(node->typeSpec());
+ parseNode(node->initDeclarator());
+ parseNode(node->functionBody());
+ parseNode(node->winDeclSpec());
+}
+
+void TreeWalker::parseTranslationUnit(TranslationUnitAST *node)
+{
+ parseAll(this, node->declarationList());
+}
+
+
+void TreeWalker::parseExpression(AbstractExpressionAST *node)
+{
+ parseAll(this, node->children());
+}
+
+
+void TreeWalker::parseBinaryExpression(BinaryExpressionAST *node)
+{
+ parseNode(node->op());
+ parseNode(node->leftExpression());
+ parseNode(node->rightExpression());
+}
+
+void TreeWalker::parseReturnStatement(ReturnStatementAST *node)
+{
+ parseNode(node->expression());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/porting/src/treewalker.h b/tools/porting/src/treewalker.h
new file mode 100644
index 0000000000..77ca951b03
--- /dev/null
+++ b/tools/porting/src/treewalker.h
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2001-2004 Roberto Raggi
+**
+** This file is part of the qt3to4 porting application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TREEWALKER_H
+#define TREEWALKER_H
+
+#include "ast.h"
+
+QT_BEGIN_NAMESPACE
+
+class TreeWalker
+{
+public:
+ TreeWalker() {}
+ virtual ~TreeWalker() {}
+
+ virtual void parseNode(AST *node);
+ virtual void parseTemplateArgumentList(TemplateArgumentListAST *node);
+ virtual void parseClassOrNamespaceName(ClassOrNamespaceNameAST *node);
+ virtual void parseName(NameAST *node);
+ virtual void parseTypeParameter(TypeParameterAST *node);
+ virtual void parseDeclaration(DeclarationAST *node);
+ virtual void parseAccessDeclaration(AccessDeclarationAST *node);
+ virtual void parseTypeSpecifier(TypeSpecifierAST *node);
+ virtual void parseBaseSpecifier(BaseSpecifierAST *node);
+ virtual void parseBaseClause(BaseClauseAST *node);
+ virtual void parseClassSpecifier(ClassSpecifierAST *node);
+ virtual void parseEnumerator(EnumeratorAST *node);
+ virtual void parseEnumSpecifier(EnumSpecifierAST *node);
+ virtual void parseElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node);
+ virtual void parseLinkageBody(LinkageBodyAST *node);
+ virtual void parseLinkageSpecification(LinkageSpecificationAST *node);
+ virtual void parseNamespace(NamespaceAST *node);
+ virtual void parseNamespaceAlias(NamespaceAliasAST *node);
+ virtual void parseUsing(UsingAST *node);
+ virtual void parseUsingDirective(UsingDirectiveAST *node);
+ virtual void parseDeclarator(DeclaratorAST *node);
+ virtual void parseParameterDeclaration(ParameterDeclarationAST *node);
+ virtual void parseParameterDeclarationList(ParameterDeclarationListAST *node);
+ virtual void parseParameterDeclarationClause(ParameterDeclarationClauseAST *node);
+ virtual void parseInitDeclarator(InitDeclaratorAST *node);
+ virtual void parseInitDeclaratorList(InitDeclaratorListAST *node);
+ virtual void parseTypedef(TypedefAST *node);
+ virtual void parseTemplateParameter(TemplateParameterAST *node);
+ virtual void parseTemplateParameterList(TemplateParameterListAST *node);
+ virtual void parseTemplateDeclaration(TemplateDeclarationAST *node);
+ virtual void parseSimpleDeclaration(SimpleDeclarationAST *node);
+ virtual void parseStatement(StatementAST *node);
+ virtual void parseExpressionStatement(ExpressionStatementAST *node);
+ virtual void parseCondition(ConditionAST *node);
+ virtual void parseIfStatement(IfStatementAST *node);
+ virtual void parseWhileStatement(WhileStatementAST *node);
+ virtual void parseDoStatement(DoStatementAST *node);
+ virtual void parseForStatement(ForStatementAST *node);
+ virtual void parseSwitchStatement(SwitchStatementAST *node);
+ virtual void parseLabeledStatement(LabeledStatementAST *node);
+ virtual void parseReturnStatement(ReturnStatementAST *node);
+ virtual void parseStatementList(StatementListAST *node);
+ virtual void parseDeclarationStatement(DeclarationStatementAST *node);
+ virtual void parseFunctionDefinition(FunctionDefinitionAST *node);
+ virtual void parseTranslationUnit(TranslationUnitAST *node);
+ virtual void parseExpression(AbstractExpressionAST *node);
+ virtual void parseBinaryExpression(BinaryExpressionAST *node);
+};
+
+inline void TreeWalker::parseNode(AST *node)
+{
+ if (!node)
+ return;
+
+ switch(node->nodeType()) {
+
+ case NodeType_Declaration:
+ case NodeType_AccessDeclaration:
+ case NodeType_LinkageSpecification:
+ case NodeType_Namespace:
+ case NodeType_NamespaceAlias:
+ case NodeType_Using:
+ case NodeType_UsingDirective:
+ case NodeType_Typedef:
+ case NodeType_TemplateDeclaration:
+ case NodeType_SimpleDeclaration:
+ case NodeType_FunctionDefinition:
+ parseDeclaration(static_cast<DeclarationAST*>(node));
+ break;
+
+ case NodeType_Statement:
+ case NodeType_ExpressionStatement:
+ case NodeType_IfStatement:
+ case NodeType_WhileStatement:
+ case NodeType_DoStatement:
+ case NodeType_ForStatement:
+ case NodeType_SwitchStatement:
+ case NodeType_LabeledStatement:
+ case NodeType_StatementList:
+ case NodeType_DeclarationStatement:
+ case NodeType_ReturnStatement:
+ parseStatement(static_cast<StatementAST*>(node));
+ break;
+
+ case NodeType_TypeSpecifier:
+ case NodeType_ClassSpecifier:
+ case NodeType_EnumSpecifier:
+ case NodeType_ElaboratedTypeSpecifier:
+ parseTypeSpecifier(static_cast<TypeSpecifierAST*>(node));
+ break;
+
+ case NodeType_TemplateArgumentList:
+ parseTemplateArgumentList(static_cast<TemplateArgumentListAST*>(node));
+ break;
+ case NodeType_ClassOrNamespaceName:
+ parseClassOrNamespaceName(static_cast<ClassOrNamespaceNameAST*>(node));
+ break;
+ case NodeType_Name:
+ parseName(static_cast<NameAST*>(node));
+ break;
+ case NodeType_TypeParameter:
+ parseTypeParameter(static_cast<TypeParameterAST*>(node));
+ break;
+ case NodeType_BaseSpecifier:
+ parseBaseSpecifier(static_cast<BaseSpecifierAST*>(node));
+ break;
+ case NodeType_BaseClause:
+ parseBaseClause(static_cast<BaseClauseAST*>(node));
+ break;
+ case NodeType_Enumerator:
+ parseEnumerator(static_cast<EnumeratorAST*>(node));
+ break;
+ case NodeType_LinkageBody:
+ parseLinkageBody(static_cast<LinkageBodyAST*>(node));
+ break;
+ case NodeType_Declarator:
+ parseDeclarator(static_cast<DeclaratorAST*>(node));
+ break;
+ case NodeType_ParameterDeclaration:
+ parseParameterDeclaration(static_cast<ParameterDeclarationAST*>(node));
+ break;
+ case NodeType_ParameterDeclarationList:
+ parseParameterDeclarationList(static_cast<ParameterDeclarationListAST*>(node));
+ break;
+ case NodeType_ParameterDeclarationClause:
+ parseParameterDeclarationClause(static_cast<ParameterDeclarationClauseAST*>(node));
+ break;
+ case NodeType_InitDeclarator:
+ parseInitDeclarator(static_cast<InitDeclaratorAST*>(node));
+ break;
+ case NodeType_InitDeclaratorList:
+ parseInitDeclaratorList(static_cast<InitDeclaratorListAST*>(node));
+ break;
+ case NodeType_TemplateParameter:
+ parseTemplateParameter(static_cast<TemplateParameterAST*>(node));
+ break;
+ case NodeType_TemplateParameterList:
+ parseTemplateParameterList(static_cast<TemplateParameterListAST*>(node));
+ break;
+ case NodeType_Condition:
+ parseCondition(static_cast<ConditionAST*>(node));
+ break;
+ case NodeType_TranslationUnit:
+ parseTranslationUnit(static_cast<TranslationUnitAST*>(node));
+ break;
+
+ case NodeType_BinaryExpression:
+ parseBinaryExpression(static_cast<BinaryExpressionAST*>(node));
+ break;
+
+ case NodeType_Expression:
+ case NodeType_PrimaryExpression:
+
+ case NodeType_PostfixExpression:
+ case NodeType_Subscripting:
+ case NodeType_FunctionCall:
+ case NodeType_ExplicitTypeConversion:
+ case NodeType_PseudoConstructorCall:
+ case NodeType_ClassMemberAccess:
+ case NodeType_IncrDecr:
+ case NodeType_CppCastExpression:
+ case NodeType_TypeIdentification:
+
+ case NodeType_UnaryExpression:
+ case NodeType_NewExpression:
+ case NodeType_NewTypeId:
+ case NodeType_NewDeclarator:
+ case NodeType_NewInitializer:
+ case NodeType_DeleteExpression:
+ case NodeType_CastExpression:
+ case NodeType_ConditionalExpression:
+ case NodeType_ThrowExpression:
+ parseExpression(static_cast<AbstractExpressionAST*>(node));
+ break;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // TREEWALKER_H
diff --git a/tools/qconfig/LICENSE.GPL b/tools/qconfig/LICENSE.GPL
new file mode 100644
index 0000000000..b6e1c33e04
--- /dev/null
+++ b/tools/qconfig/LICENSE.GPL
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/tools/qconfig/feature.cpp b/tools/qconfig/feature.cpp
new file mode 100644
index 0000000000..829573a6d9
--- /dev/null
+++ b/tools/qconfig/feature.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "feature.h"
+#include <QTextStream>
+#include <QRegExp>
+#include <QLibraryInfo>
+#include <QFileInfo>
+#include <QApplication>
+#include <QPalette>
+
+QT_BEGIN_NAMESPACE
+
+QMap<QString, Feature*> Feature::instances;
+
+Feature* Feature::getInstance(const QString &key)
+{
+ QString ukey = key.toUpper();
+ if (!instances.contains(ukey))
+ instances[ukey] = new Feature(ukey);
+ return instances[ukey];
+}
+
+Feature::~Feature()
+{
+ delete d;
+}
+
+void Feature::clear()
+{
+ foreach (Feature *f, instances.values())
+ delete f;
+ instances.clear();
+}
+
+static QString listToHtml(const QString &title, const QStringList &list)
+{
+ if (list.isEmpty())
+ return QString();
+
+ QString str;
+ QTextStream stream(&str);
+
+ stream << "<h3>" << title << ":</h3>";
+ stream << "<ul>";
+ foreach (QString l, list)
+ stream << "<li>" << l << "</li>";
+ stream << "</ul>";
+
+ return str;
+}
+
+static QString listToHtml(const QString &title, const QList<Feature*> &list)
+{
+ QStringList stringlist;
+ foreach (Feature *f, list) {
+ QString s("[%3] <a href=\"feature://%1\">%2</a>");
+ s = s.arg(f->key()).arg(f->key());
+ s = s.arg(f->selectable() && f->enabled() ? "On" : "Off");
+ stringlist << s;
+ }
+ return listToHtml(title, stringlist);
+}
+
+static QString linkify(const QString &src)
+{
+ static QRegExp classRegexp("\\b(Q[\\w]+)");
+ QString docRoot = QLibraryInfo::location(QLibraryInfo::DocumentationPath);
+ QString result = src;
+ int pos = 0;
+ while ((pos = classRegexp.indexIn(result, pos)) != -1) {
+ QString className = classRegexp.cap(1);
+ QString file = docRoot + "/html/" + className.toLower() + ".html";
+ QFileInfo info(file);
+ if (info.isFile()) {
+ QString link = QString("<a href=\"file://%1\">%2</a>")
+ .arg(file).arg(className);
+ result.replace(pos, className.length(), link);
+ pos += link.length();
+ } else {
+ pos += className.length();
+ }
+ }
+
+ return result;
+}
+
+QString Feature::toHtml() const
+{
+ QString str;
+ QTextStream stream(&str);
+
+ const QString linkColor = QApplication::palette().color(QPalette::Link).name();
+ stream << "<h2><font size=\"+2\" color=\"" << linkColor << "\">"
+ << key() << "</font></h2>"
+ << "<h2><font size=\"+2\">" << title() << "</font></h2>";
+ if (!description().isEmpty())
+ stream << "<p>" << description() << "</p>";
+ stream << listToHtml("Section", QStringList(section()))
+ << listToHtml("Requires", dependencies())
+ << listToHtml("Required for", supports())
+ << listToHtml("See also", relations());
+
+ return linkify(str);
+}
+
+Feature::Feature(const QString &key) : d(new FeaturePrivate(key)) {}
+
+void Feature::setTitle(const QString &title)
+{
+ d->title = title;
+}
+
+void Feature::setSection(const QString &section)
+{
+ d->section = section;
+}
+
+void Feature::setDescription(const QString &description)
+{
+ d->description = description;
+}
+
+void Feature::addRelation(const QString &key)
+{
+ d->relations.insert(getInstance(key));
+}
+
+void Feature::setRelations(const QStringList &keys)
+{
+ foreach(QString key, keys)
+ if (key != "???")
+ addRelation(key);
+}
+
+QList<Feature*> Feature::relations() const
+{
+ return d->relations.toList();
+}
+
+void Feature::addDependency(const QString &key)
+{
+ Feature *f = getInstance(key);
+ d->dependencies.insert(f);
+ f->d->supports.insert(this);
+}
+
+void Feature::setDependencies(const QStringList &keys)
+{
+ foreach(QString key, keys)
+ addDependency(key);
+}
+
+QList<Feature*> Feature::dependencies() const
+{
+ return d->dependencies.toList();
+}
+
+QList<Feature*> Feature::supports() const
+{
+ return d->supports.toList();
+}
+
+/*
+ Returns a html formatted detailed description of this Feature.
+*/
+QString Feature::getDocumentation() const
+{
+ return QString() + "<h2>" + d->title + "</h2>";
+
+}
+
+void Feature::setEnabled(bool on)
+{
+ if (on == d->enabled)
+ return;
+
+ d->enabled = on;
+ foreach (Feature *f, supports())
+ f->updateSelectable();
+ emit changed();
+}
+
+/*
+ Update whether this feature should be selectable.
+ A feature is selectable if all its dependencies are enabled.
+*/
+void Feature::updateSelectable()
+{
+ bool selectable = true;
+ foreach (Feature *f, dependencies())
+ if (!f->selectable() || !f->enabled())
+ selectable = false;
+ if (selectable != d->selectable) {
+ d->selectable = selectable;
+ foreach (Feature *f, supports())
+ f->updateSelectable();
+ emit changed();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qconfig/feature.h b/tools/qconfig/feature.h
new file mode 100644
index 0000000000..8e502ee17b
--- /dev/null
+++ b/tools/qconfig/feature.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FEATURE_H
+#define FEATURE_H
+
+#include <QString>
+#include <QStringList>
+#include <QMap>
+#include <QSet>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+class Feature;
+
+class FeaturePrivate
+{
+public:
+ FeaturePrivate(const QString &k)
+ : key(k), enabled(true), selectable(true) {};
+
+ const QString key;
+ QString section;
+ QString title;
+ QString description;
+ QSet<Feature*> dependencies;
+ QSet<Feature*> supports; // features who depends on this one
+ QSet<Feature*> relations;
+ bool enabled;
+ bool selectable;
+};
+
+class Feature : public QObject
+{
+ Q_OBJECT
+
+public:
+ static Feature* getInstance(const QString &key);
+ static void clear();
+
+public:
+ QString key() const { return d->key; }
+
+ void setTitle(const QString &title);
+ QString title() const { return d->title; }
+
+ void setSection(const QString &section);
+ QString section() const { return d->section; }
+
+ void setDescription(const QString &description);
+ QString description() const { return d->description; };
+
+ void addRelation(const QString &key);
+ void setRelations(const QStringList &keys);
+ QList<Feature*> relations() const;
+
+ void addDependency(const QString &dependency);
+ void setDependencies(const QStringList &dependencies);
+ QList<Feature*> dependencies() const;
+
+ QList<Feature*> supports() const;
+ QString getDocumentation() const;
+
+ void setEnabled(bool on);
+ bool enabled() const { return d->enabled; };
+
+ bool selectable() const { return d->selectable; }
+
+ QString toHtml() const;
+
+ ~Feature();
+
+signals:
+ void changed();
+
+private:
+ Feature(const QString &key);
+ void updateSelectable();
+
+ static QMap<QString, Feature*> instances;
+ FeaturePrivate *d;
+};
+
+QT_END_NAMESPACE
+
+#endif // FEATURE_H
diff --git a/tools/qconfig/featuretreemodel.cpp b/tools/qconfig/featuretreemodel.cpp
new file mode 100644
index 0000000000..2bd5f003cb
--- /dev/null
+++ b/tools/qconfig/featuretreemodel.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "featuretreemodel.h"
+#include "feature.h"
+#include <QPalette>
+#include <QColor>
+#include <QApplication>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+class Node
+{
+public:
+ Node(Feature *f, Node *p = 0) : feature(f), parent(p) {}
+ ~Node();
+ Node* find(const Feature *child) const;
+ bool contains(const Feature *child) const { return find(child) != 0; }
+ bool insert(Node *n);
+
+ Feature *feature;
+ Node *parent;
+ QList<Node*> children; // maybe convert to Map to get keys sorted
+};
+
+Node::~Node()
+{
+ while (!children.isEmpty())
+ delete children.takeFirst();
+}
+
+Node* Node::find(const Feature *f) const
+{
+ if (this->feature == f)
+ return const_cast<Node*>(this);
+
+ foreach (Node *n, children)
+ if (Node *m = n->find(f))
+ return m;
+
+ return 0;
+}
+
+static bool nodePtrLessThan(const Node *n1, const Node *n2)
+{
+ return (n1->feature->key() < n2->feature->key());
+}
+
+/*
+ Try insert \a n into the tree with this node as root.
+ n is inserted as a child if it has a dependency to this node.
+ Returns true if child is inserted into the tree, false otherwise.
+*/
+bool Node::insert(Node *n)
+{
+ Feature *f = const_cast<Feature*>(n->feature);
+ if (feature->supports().contains(f)) {
+ children.append(n);
+ qSort(children.begin(), children.end(), nodePtrLessThan);
+ n->parent = this;
+ return true;
+ }
+ foreach (Node *child, children)
+ if (child->insert(n))
+ return true;
+ return false;
+}
+
+static bool isSection(const QModelIndex &index)
+{
+ return index.isValid() && (index.internalId() == 0);
+}
+
+FeatureTreeModel::FeatureTreeModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+}
+
+FeatureTreeModel::~FeatureTreeModel()
+{
+ foreach (QString section, sections.keys())
+ while (!sections[section].isEmpty())
+ delete sections[section].takeFirst();
+}
+
+/*
+ Returns true if the model already contains \a in \a section, false otherwise.
+*/
+bool FeatureTreeModel::contains(const QString &section, const Feature *f) const
+{
+ return (find(section, f) != 0);
+}
+
+Node* FeatureTreeModel::find(const QString &section, const Feature *f) const
+{
+ QList<Node*> roots = sections[section];
+ foreach (Node *root, roots)
+ if (Node *n = root->find(f))
+ return n;
+ return 0;
+}
+
+/*
+ Add new \a feature to the tree.
+ When all feature is added, buildTree() must be called to build the
+ dependency tree.
+*/
+void FeatureTreeModel::addFeature(Feature *feature)
+{
+ const QString section = feature->section();
+ Q_ASSERT(!contains(section, feature));
+
+ connect(feature, SIGNAL(changed()), this, SLOT(featureChanged()));
+
+ Node *node = new Node(feature, 0);
+
+ // try insert any toplevel nodes as child of this one
+ foreach (Node *n, sections[section])
+ if (node->insert(n))
+ sections[section].removeAll(n);
+
+ // try insert this node as a child of any existing node
+ foreach (Node *n, sections[section])
+ if (n->insert(node)) {
+ emit layoutChanged();
+ return;
+ }
+
+ // not a child, insert as a toplevel node
+ sections[section].append(node);
+ qSort(sections[section].begin(), sections[section].end(), nodePtrLessThan);
+ emit layoutChanged();
+}
+
+QModelIndex FeatureTreeModel::createIndex(int row, int column,
+ const QModelIndex &parent,
+ const Node *node) const
+{
+ QModelIndex index = QAbstractItemModel::createIndex(row, column,
+ (void*)node);
+ if (parent.isValid())
+ parentMap[index] = parent;
+ if (node)
+ featureIndexMap[node->feature] = index;
+ return index;
+}
+
+QModelIndex FeatureTreeModel::index(int row, int column,
+ const QModelIndex &parent) const
+{
+ if (!parent.isValid()) { // index is a section
+ if (row < sections.size() && column == 0)
+ return QAbstractItemModel::createIndex(row, column, 0);
+ return QModelIndex();
+ }
+
+ if (isSection(parent)) { // index is a toplevel feature
+ const int parentRow = parent.row();
+ if (parentRow < sections.size()) {
+ QString section = sections.keys().at(parentRow);
+ QList<Node*> nodes = sections[section];
+ if (row < nodes.size() && column < 2)
+ return createIndex(row, column, parent, nodes.at(row));
+ }
+ return QModelIndex();
+ }
+
+ // parent is a feature
+ Node *parentNode = static_cast<Node*>(parent.internalPointer());
+ QList<Node*> children = parentNode->children;
+ if (row < children.size() && column < 2)
+ return createIndex(row, column, parent, children.at(row));
+
+ return QModelIndex();
+}
+
+QModelIndex FeatureTreeModel::index(const QModelIndex &parent,
+ const Feature *feature) const
+{
+ const int rows = rowCount(parent);
+ for (int i = 0; i < rows; ++i) {
+ QModelIndex child = index(i, 0, parent);
+ Node *node = static_cast<Node*>(child.internalPointer());
+ if (node && node->feature == feature)
+ return child;
+ QModelIndex childSearch = index(child, feature);
+ if (childSearch.isValid())
+ return childSearch;
+ }
+ return QModelIndex();
+}
+
+QModelIndex FeatureTreeModel::index(const Feature *feature) const
+{
+ if (featureIndexMap.contains(feature))
+ return featureIndexMap.value(feature);
+
+ // exhaustive search
+ int sectionRow = sections.keys().indexOf(feature->section());
+ QModelIndex sectionIndex = index(sectionRow, 0, QModelIndex());
+
+ return index(sectionIndex, feature);
+}
+
+QModelIndex FeatureTreeModel::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ if (parentMap.contains(index))
+ return parentMap.value(index);
+ return QModelIndex();
+}
+
+int FeatureTreeModel::rowCount(const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return sections.size();
+
+ if (isSection(parent)) {
+ const QString section = sections.keys().at(parent.row());
+ return sections[section].size();
+ }
+
+ const Node *node = static_cast<Node*>(parent.internalPointer());
+ return node->children.size();
+}
+
+int FeatureTreeModel::columnCount(const QModelIndex &parent) const
+{
+#if 0
+ if (!parent.isValid())
+ return 0;
+
+ if (isSection(parent))
+ return 1;
+#endif
+ Q_UNUSED(parent);
+ return 2; // Feature: [key, name]
+}
+
+QVariant FeatureTreeModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ const Node *node = static_cast<Node*>(index.internalPointer());
+
+ switch (role) {
+ case Qt::DisplayRole: {
+ if (node == 0) // index is a section
+ return sections.keys().at(index.row());
+ if (index.column() == 0)
+ return node->feature->key();
+ Q_ASSERT(index.column() == 1);
+ return node->feature->title();
+ }
+ case Qt::CheckStateRole: {
+ if (node && index.column() == 0)
+ return (node->feature->enabled() ?
+ Qt::Checked : Qt::Unchecked);
+ break;
+ }
+ case Qt::TextColorRole: {
+ if (node && index.column() == 0) // feature key
+ if (node->feature->selectable())
+ return QApplication::palette().color(QPalette::Link);
+ break;
+ }
+ case Qt::TextAlignmentRole:
+ case Qt::BackgroundColorRole:
+ case Qt::FontRole:
+ case Qt::ToolTipRole: // TODO
+ case Qt::StatusTipRole: // TODO
+ case Qt::WhatsThisRole: // TODO
+ case Qt::DecorationRole:
+ case Qt::EditRole:
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+bool FeatureTreeModel::setData(const QModelIndex &index,
+ const QVariant &value, int role)
+{
+ if (!index.isValid())
+ return false;
+
+ Node *node = static_cast<Node*>(index.internalPointer());
+ if (!node)
+ return false;
+
+ if (role == Qt::CheckStateRole) {
+ Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
+ if (state == Qt::Checked)
+ node->feature->setEnabled(true);
+ else if (state == Qt::Unchecked)
+ node->feature->setEnabled(false);
+ emit dataChanged(index, index);
+ return true;
+ }
+ return false;
+}
+
+Qt::ItemFlags FeatureTreeModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid() || index.internalPointer() == 0)
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+
+ const Node *node = static_cast<Node*>(index.internalPointer());
+ const Feature *feature = node->feature;
+ Qt::ItemFlags flags = Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
+
+ if (feature->selectable())
+ flags |= Qt::ItemIsEnabled;
+
+ return flags;
+}
+
+QVariant FeatureTreeModel::headerData(int section, Qt::Orientation orientation,
+ int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ if (section == 0)
+ return QString("Id");
+ else if (section == 1)
+ return QString("Name");
+ }
+
+ return QVariant();
+}
+
+Feature* FeatureTreeModel::getFeature(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return 0;
+ if (isSection(index))
+ return 0;
+ Node *node = static_cast<Node*>(index.internalPointer());
+ return const_cast<Feature*>(node->feature);
+}
+
+void FeatureTreeModel::featureChanged()
+{
+ Feature *feature = qobject_cast<Feature*>(sender());
+ if (feature) {
+ QModelIndex featureIndex = index(feature);
+ emit dataChanged(featureIndex, featureIndex);
+ } else {
+ emit layoutChanged();
+ }
+}
+
+void FeatureTreeModel::readConfig(QTextStream &stream)
+{
+ static QRegExp regexp("\\s*#\\s*define\\s+QT_NO_(\\S+)\\s*");
+
+ while (!stream.atEnd()) {
+ QString line = stream.readLine();
+ if (regexp.exactMatch(line)) {
+ Feature *f = Feature::getInstance(regexp.cap(1));
+ f->setEnabled(false);
+ }
+ }
+}
+/*
+ Search for all disabled child features of \a parent.
+ Returns a list of feature keys for the disabled items.
+*/
+QStringList FeatureTreeModel::findDisabled(const QModelIndex &parent) const
+{
+ QStringList stringList;
+
+ const int rows = rowCount(parent);
+ for (int i = 0; i < rows; ++i) {
+ QModelIndex child = index(i, 0, parent);
+ Node *node = static_cast<Node*>(child.internalPointer());
+ if (node && node->feature && !node->feature->enabled())
+ stringList << node->feature->key();
+ stringList << findDisabled(child);
+ }
+ return stringList;
+}
+
+void FeatureTreeModel::writeConfig(QTextStream &stream) const
+{
+ const int sectionCount = rowCount(QModelIndex());
+
+ for (int i = 0; i < sectionCount; ++i) {
+ QModelIndex section = index(i, 0, QModelIndex());
+ QStringList disabled = findDisabled(section);
+ if (disabled.size() > 0) {
+ stream << '\n' << "/* " << sections.keys().at(i) << " */" << '\n';
+ foreach (QString feature, disabled)
+ stream << "#ifndef QT_NO_" << feature << '\n'
+ << "# define QT_NO_" << feature << '\n'
+ << "#endif" << '\n';
+ }
+ }
+}
+
+void FeatureTreeModel::clear()
+{
+ Feature::clear();
+ sections.clear();
+ parentMap.clear();
+ featureIndexMap.clear();
+ emit layoutChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qconfig/featuretreemodel.h b/tools/qconfig/featuretreemodel.h
new file mode 100644
index 0000000000..965d3638af
--- /dev/null
+++ b/tools/qconfig/featuretreemodel.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FEATURETREEMODEL_H
+#define FEATURETREEMODEL_H
+
+#include <QAbstractItemModel>
+#include <QMap>
+#include <QHash>
+#include <QTextStream>
+
+QT_BEGIN_NAMESPACE
+
+class Feature;
+class Node;
+
+uint qHash(const QModelIndex&);
+
+class FeatureTreeModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ FeatureTreeModel(QObject *parent = 0);
+ ~FeatureTreeModel();
+
+ void clear();
+
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+ QModelIndex index(int row, int column,
+ const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex index(const Feature *feature) const;
+ QModelIndex parent(const QModelIndex &index) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+ void addFeature(Feature *feature);
+ Feature* getFeature(const QModelIndex &index) const;
+
+ void readConfig(QTextStream &stream);
+ void writeConfig(QTextStream &stream) const;
+
+public slots:
+ void featureChanged();
+
+private:
+ QModelIndex createIndex(int row, int column,
+ const QModelIndex &parent,
+ const Node *feature) const;
+ QModelIndex index(const QModelIndex &parent, const Feature *feature) const;
+ bool contains(const QString &section, const Feature *f) const;
+ Node* find(const QString &section, const Feature *f) const;
+ QStringList findDisabled(const QModelIndex &parent) const;
+
+ QMap<QString, QList<Node*> > sections;
+ mutable QHash<QModelIndex, QModelIndex> parentMap;
+ mutable QHash<const Feature*, QModelIndex> featureIndexMap;
+};
+
+QT_END_NAMESPACE
+
+#endif // FEATURETREEMODEL_H
diff --git a/tools/qconfig/graphics.h b/tools/qconfig/graphics.h
new file mode 100644
index 0000000000..a67acedbea
--- /dev/null
+++ b/tools/qconfig/graphics.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRAPHICS_H
+#define GRAPHICS_H
+
+static const char *logo_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"50 50 17 1",
+/* colors */
+" c #000000",
+". c #495808",
+"X c #2A3304",
+"o c #242B04",
+"O c #030401",
+"+ c #9EC011",
+"@ c #93B310",
+"# c #748E0C",
+"$ c #A2C511",
+"% c #8BA90E",
+"& c #99BA10",
+"* c #060701",
+"= c #181D02",
+"- c #212804",
+"; c #61770A",
+": c #0B0D01",
+"/ c None",
+/* pixels */
+"/$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$/",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$+++$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$@;.o=::=o.;@$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$+#X* **X#+$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$#oO* O **o#+$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$&.* OO O*.&$$$$$$$$$$$$$",
+"$$$$$$$$$$$$@XOO * OO X&$$$$$$$$$$$$",
+"$$$$$$$$$$$@XO OO O **:::OOO OOO X@$$$$$$$$$$$",
+"$$$$$$$$$$&XO O-;#@++@%.oOO X&$$$$$$$$$$",
+"$$$$$$$$$$.O : *-#+$$$$$$$$+#- : O O*.$$$$$$$$$$",
+"$$$$$$$$$#*OO O*.&$$$$$$$$$$$$+.OOOO **#$$$$$$$$$",
+"$$$$$$$$+-OO O *;$$$$$$$$$$$&$$$$;* o+$$$$$$$$",
+"$$$$$$$$#O* O .+$$$$$$$$$$@X;$$$+.O *#$$$$$$$$",
+"$$$$$$$$X* -&$$$$$$$$$$@- :;$$$&- OX$$$$$$$$",
+"$$$$$$$@*O *O#$$$$$$$$$$@oOO**;$$$# O*%$$$$$$$",
+"$$$$$$$; -+$$$$$$$$$@o O OO ;+$$-O *;$$$$$$$",
+"$$$$$$$. ;$$$$$$$$$@-OO OO X&$$;O .$$$$$$$",
+"$$$$$$$o *#$$$$$$$$@o O O O-@$$$#O *o$$$$$$$",
+"$$$$$$+= *@$$$$$$$@o* OO -@$$$$&: =$$$$$$$",
+"$$$$$$+: :+$$$$$$@- *-@$$$$$$: :+$$$$$$",
+"$$$$$$+: :+$$$$$@o* O *-@$$$$$$: :+$$$$$$",
+"$$$$$$$= :@$$$$@o*OOO -@$$$$@: =+$$$$$$",
+"$$$$$$$- O%$$$@o* O O O O-@$$$#* OX$$$$$$$",
+"$$$$$$$. O *O;$$&o O*O* *O -@$$; O.$$$$$$$",
+"$$$$$$$;* Oo+$$;O*O:OO-- Oo@+= *;$$$$$$$",
+"$$$$$$$@* O O#$$$;*OOOo@@-O Oo;O* **@$$$$$$$",
+"$$$$$$$$X* OOO-+$$$;O o@$$@- O O OX$$$$$$$$",
+"$$$$$$$$#* * O.$$$$;X@$$$$@-O O O#$$$$$$$$",
+"$$$$$$$$+oO O OO.+$$+&$$$$$$@-O o+$$$$$$$$",
+"$$$$$$$$$#* **.&$$$$$$$$$$@o OO:#$$$$$$$$$",
+"$$$$$$$$$+. O* O-#+$$$$$$$$+;O OOO:@$$$$$$$$$",
+"$$$$$$$$$$&X *O -;#@++@#;=O O -@$$$$$$$$",
+"$$$$$$$$$$$&X O O*O::::O OO Oo@$$$$$$$",
+"$$$$$$$$$$$$@XOO OO O*X+$$$$$$",
+"$$$$$$$$$$$$$&.* ** O :: *:#$$$$$$$",
+"$$$$$$$$$$$$$$$#o*OO O Oo#@-OOO=#$$$$$$$$",
+"$$$$$$$$$$$$$$$$+#X:* * O**X#+$$@-*:#$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$%;.o=::=o.#@$$$$$$@X#$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$+++$$$$$$$$$$$+$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$",
+"/$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$/",
+};
+
+static const char *expanded_xpm[] = {
+"32 32 3 1",
+" c None",
+"# c #000000",
+"a c #0000c0",
+" ## ",
+" ## ",
+" #############aaaaaaaaaaaaa ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## #aaaaaaaaaaaaa ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" #############aaaaaaaaaaaaa ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## #aaaaaaaaaaaaa ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" #############aaaaaaaaaaaaa ",
+" ## # ",
+" ## # ",
+" ## # ",
+" ## # "};
+
+static const char *collapsed_xpm[] = {
+"32 32 3 1",
+" c None",
+"# c #000000",
+"a c #0000c0",
+" ## ",
+" ## ",
+" ##aaaaaaaaaaaaaaaaaa ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ##aaaaaaaaaaaaaaaaaa ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ##aaaaaaaaaaaaaaaaaa ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ##aaaaaaaaaaaaaaaaaa ",
+" ## ",
+" ## ",
+" ## ",
+" ## ",
+" ## "};
+
+#endif // GRAPHICS_H
diff --git a/tools/qconfig/main.cpp b/tools/qconfig/main.cpp
new file mode 100644
index 0000000000..dd53e09893
--- /dev/null
+++ b/tools/qconfig/main.cpp
@@ -0,0 +1,552 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "graphics.h"
+#include "feature.h"
+#include "featuretreemodel.h"
+
+#include <QtGui>
+
+QT_BEGIN_NAMESPACE
+
+static QString defaultPath;
+
+class FeatureTextBrowser : public QTextBrowser {
+ Q_OBJECT
+public:
+ FeatureTextBrowser(QWidget *parent) : QTextBrowser(parent) {
+ QString docRoot;
+ docRoot = QLibraryInfo::location(QLibraryInfo::DocumentationPath)
+ + "/html";
+ setSearchPaths(searchPaths() << docRoot);
+ }
+
+signals:
+ void featureClicked(const QString &feature);
+
+public slots:
+ void setSource(const QUrl &url)
+ {
+ if (url.scheme() == "feature")
+ emit featureClicked(url.authority());
+ else
+ QTextBrowser::setSource(url);
+ }
+};
+
+class Main : public QMainWindow {
+ Q_OBJECT
+public:
+ Main();
+ ~Main();
+ void loadFeatures(const QString& filename);
+ void loadConfig(const QString& filename);
+
+public slots:
+ void modelChanged();
+ void showInfo(const QModelIndex &index);
+ void showInfo(const QString &feature);
+ void openConfig();
+ void saveConfig();
+ void expandView();
+ void collapseView();
+ void about();
+ void aboutQt();
+ void quit();
+ void clear();
+ void enableAll();
+ void disableAll();
+
+private:
+ QTextBrowser *textBrowser;
+ QTreeView *featureTree;
+ FeatureTreeModel *featureModel;
+
+ void init();
+ void updateStatus(int numFeatures = -1);
+ void completelyExpandIndex(const QModelIndex &parent);
+};
+
+template<typename Func>
+void foreachIndex_helper(const QModelIndex &parent, Func func)
+{
+ const QAbstractItemModel *model = parent.model();
+ const int rows = model->rowCount(parent);
+ for (int i = 0; i < rows; ++i) {
+ const QModelIndex child = model->index(i, 0, parent);
+ func(child);
+ foreachIndex_helper(child, func);
+ }
+}
+
+template<typename Func>
+void foreachIndex(const QAbstractItemModel *model, Func func)
+{
+ const int rows = model->rowCount(QModelIndex());
+ for (int i = 0; i < rows; ++i) {
+ const QModelIndex child = model->index(i, 0, QModelIndex());
+ func(child);
+ foreachIndex_helper(child, func);
+ }
+}
+
+struct CheckStateSetter {
+
+ CheckStateSetter(Qt::CheckState state, QAbstractItemModel *m)
+ : checkState(state), model(m) {}
+
+ void operator()(const QModelIndex &index) {
+ model->setData(index, checkState, Qt::CheckStateRole);
+ }
+
+ Qt::CheckState checkState;
+ QAbstractItemModel *model;
+};
+
+void Main::disableAll()
+{
+ QAbstractItemModel *model = featureTree->model();
+ foreachIndex(model, CheckStateSetter(Qt::Unchecked, model));
+}
+
+void Main::enableAll()
+{
+ QAbstractItemModel *model = featureTree->model();
+ foreachIndex(model, CheckStateSetter(Qt::Checked, model));
+}
+
+Main::Main()
+{
+ setWindowIcon(QIcon(QPixmap(logo_xpm)));
+
+ QSplitter *splitter = new QSplitter(this);
+
+ featureModel = new FeatureTreeModel(this);
+ featureTree = new QTreeView(splitter);
+ splitter->addWidget(featureTree);
+ featureTree->setRootIsDecorated(true);
+ featureTree->setModel(featureModel);
+ featureTree->show();
+
+ textBrowser = new FeatureTextBrowser(splitter);
+ textBrowser->setFrameStyle(QFrame::WinPanel|QFrame::Sunken);
+ splitter->addWidget(textBrowser);
+ textBrowser->show();
+
+ connect(textBrowser, SIGNAL(featureClicked(const QString&)),
+ this, SLOT(showInfo(const QString&)));
+ connect(featureTree, SIGNAL(activated(QModelIndex)),
+ this, SLOT(showInfo(QModelIndex)));
+ connect(featureModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
+ this, SLOT(modelChanged()));
+ connect(featureTree, SIGNAL(clicked(QModelIndex)),
+ this, SLOT(showInfo(QModelIndex)));
+
+ setCentralWidget(splitter);
+
+ QMenu *file = menuBar()->addMenu("&File");
+ file->addAction("&Open...", this, SLOT(openConfig()),
+ Qt::CTRL + Qt::Key_O);
+ file->addAction("&Save As...", this, SLOT(saveConfig()),
+ Qt::CTRL + Qt::Key_S);
+ file->addSeparator();
+ file->addAction("&Reset", this, SLOT(clear()));
+ file->addSeparator();
+ file->addAction("E&xit", this, SLOT(quit()), Qt::CTRL + Qt::Key_Q);
+
+ QMenu *edit = menuBar()->addMenu("&Tools");
+ edit->addAction("&Enable all features", this, SLOT(enableAll()));
+ edit->addAction("&Disable all features", this, SLOT(disableAll()));
+
+ menuBar()->addSeparator();
+
+ QMenu *help = menuBar()->addMenu("&Help");
+ help->addAction("&About", this, SLOT(about()));
+ help->addAction("About &Qt", this, SLOT(aboutQt()));
+
+ QToolBar *tb = new QToolBar("Expand/Collapse features");
+ QToolButton *button;
+
+ button = new QToolButton(tb);
+ button->setIcon(QIcon(QPixmap(collapsed_xpm)));
+ button->setText("Collapse");
+ button->setToolTip("Collapse");
+ connect(button, SIGNAL(clicked()), this, SLOT(collapseView()));
+ tb->addWidget(button);
+
+ button = new QToolButton(tb);
+ button->setIcon(QIcon(QPixmap(expanded_xpm)));
+ button->setText("Expand");
+ button->setToolTip("Expand");
+ connect(button, SIGNAL(clicked()), this, SLOT(expandView()));
+ tb->addWidget(button);
+ addToolBar(tb);
+
+ init();
+}
+
+Main::~Main()
+{
+ delete textBrowser;
+ delete featureModel;
+ delete featureTree;
+}
+
+void Main::clear()
+{
+ QSettings settings;
+ settings.clear();
+ featureModel->clear();
+ featureTree->reset();
+ init();
+}
+
+void Main::quit()
+{
+ if (isWindowModified()) {
+ int button = QMessageBox::question(this, "Quit Program",
+ "You have unsaved changes.\n"
+ "Do you want to quit anyway?",
+ QMessageBox::Yes,
+ QMessageBox::No);
+ if (static_cast<QMessageBox::Button>(button) != QMessageBox::Yes)
+ return;
+ }
+ QApplication::instance()->quit();
+}
+
+/*
+ Recursively expand expand \a parent and all of its children.
+*/
+void Main::completelyExpandIndex(const QModelIndex &parent)
+{
+ featureTree->setExpanded(parent, true);
+
+ const QAbstractItemModel *model = featureTree->model();
+ const int rows = model->rowCount(parent);
+ for (int i = 0; i < rows; ++i)
+ completelyExpandIndex(model->index(i, 0, parent));
+}
+
+void Main::expandView()
+{
+ completelyExpandIndex(QModelIndex());
+}
+
+void Main::collapseView()
+{
+ const QAbstractItemModel *model = featureTree->model();
+ const int rows = model->rowCount(QModelIndex());
+ for (int i = 0; i < rows; ++i) {
+ QModelIndex index = model->index(i, 0, QModelIndex());
+ featureTree->setExpanded(index, false);
+ }
+}
+
+void Main::updateStatus(int numFeatures)
+{
+ QSettings settings;
+ QString featureFile = settings.value("featureFile").toString();
+ QString configFile = settings.value("lastConfig").toString();
+ QString message("Using features from %1");
+
+ if (numFeatures >= 0) {
+ QString s("%1 features loaded from %2");
+ statusBar()->showMessage(s.arg(numFeatures).arg(featureFile));
+ }
+ QString appName = QApplication::applicationName();
+ if (configFile.isEmpty())
+ configFile = "New File";
+ setWindowTitle(appName + " - " + configFile + "[*]");
+}
+
+void Main::modelChanged()
+{
+ setWindowModified(true);
+}
+
+void Main::init()
+{
+ QSettings settings;
+ QString features = settings.value("featureFile").toString();
+
+ if (features.isEmpty() || !QFileInfo(features).isFile()) {
+ features = QFileDialog::getOpenFileName(this,
+ "Open a feature file",
+ defaultPath,
+ "Qt Features (qfeatures.txt)");
+ }
+ settings.setValue("featureFile", features);
+ loadFeatures(features);
+
+ expandView();
+ collapseView();
+
+ QString confFile = settings.value("lastConfig").toString();
+ if (confFile.isEmpty())
+ return;
+ loadConfig(confFile);
+}
+
+void Main::openConfig()
+{
+ QSettings settings;
+ QString configDir;
+
+ QString prevFile = settings.value("lastConfig").toString();
+ if (!prevFile.isEmpty())
+ configDir = QFileInfo(prevFile).path();
+
+ if (configDir.isEmpty())
+ configDir = defaultPath;
+
+ QString configFile;
+ configFile = QFileDialog::getOpenFileName(this,
+ "Open a configuration file",
+ configDir,
+ "Header files (*.h)");
+ enableAll();
+ if (!configFile.isEmpty())
+ loadConfig(configFile);
+ settings.setValue("lastConfig", QFileInfo(configFile).absoluteFilePath());
+}
+
+void Main::saveConfig()
+{
+ QSettings settings;
+ QString configDir;
+
+ QString prevFile = settings.value("lastConfig").toString();
+ if (!prevFile.isEmpty())
+ configDir = QFileInfo(prevFile).path();
+
+ if (configDir.isEmpty())
+ configDir = defaultPath;
+
+ QString configFile;
+ configFile = QFileDialog::getSaveFileName(this,
+ "Save configuration file",
+ configDir,
+ "Header files (*.h)");
+ if (configFile.isEmpty())
+ return;
+
+ QFile file(configFile);
+ if (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox::warning(this,"Warning",
+ "Cannot write to file " + configFile);
+ return;
+ }
+
+ QTextStream stream(&file);
+ FeatureTreeModel *model;
+ model = static_cast<FeatureTreeModel*>(featureTree->model());
+ model->writeConfig(stream);
+
+ settings.setValue("lastConfig", QFileInfo(configFile).absoluteFilePath());
+ setWindowModified(false);
+ updateStatus();
+}
+
+void Main::loadConfig(const QString &filename)
+{
+ if (!QFileInfo(filename).isFile())
+ return;
+
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ QMessageBox::warning(this,"Warning", "Cannot open file " + filename);
+ return;
+ }
+
+ QTextStream stream(&file);
+ FeatureTreeModel *model;
+ model = static_cast<FeatureTreeModel*>(featureTree->model());
+ model->readConfig(stream);
+
+ QSettings settings;
+ settings.setValue("lastConfig", QFileInfo(filename).absoluteFilePath());
+ setWindowModified(false);
+ updateStatus();
+}
+
+void Main::loadFeatures(const QString &filename)
+{
+ Feature::clear();
+
+ QFile file(filename);
+ if (!file.open(QIODevice::ReadOnly)) {
+ QMessageBox::warning(this,"Warning", "Cannot open file " + filename);
+ return;
+ }
+
+ Feature *feature = 0;
+ int numFeatures = 0;
+ updateStatus(numFeatures);
+ QTextStream s(&file);
+ for (QString line = s.readLine(); !s.atEnd(); line = s.readLine()) {
+ line = line.simplified();
+ if (line.isEmpty())
+ continue;
+ if (line.startsWith('#'))
+ continue;
+
+ int colon = line.indexOf(':');
+ if (colon < 0) { // assume description
+ QString description = feature->description().simplified();
+ description += " " + line;
+ feature->setDescription(description);
+ continue;
+ }
+
+ QString tag = line.left(colon);
+ QString value = line.mid(colon+1).simplified();
+ if (tag == "Feature") {
+ if (feature)
+ featureModel->addFeature(feature);
+ feature = Feature::getInstance(value);
+ updateStatus(++numFeatures);
+ } else if (tag == "Requires") {
+ Q_ASSERT(feature);
+ feature->setDependencies(value.split(' ', QString::SkipEmptyParts));
+ } else if (tag == "Name") {
+ Q_ASSERT(feature);
+ feature->setTitle(value);
+ } else if (tag == "Section") {
+ Q_ASSERT(feature);
+ feature->setSection(value);
+ } else if (tag == "SeeAlso") {
+ Q_ASSERT(feature);
+ feature->setRelations(value.split(' ', QString::SkipEmptyParts));
+ } else if (tag == "Description") {
+ Q_ASSERT(feature);
+ feature->setDescription(value);
+ }
+ }
+ if (feature)
+ featureModel->addFeature(feature);
+
+ featureTree->resizeColumnToContents(0);
+
+ QSettings settings;
+ settings.setValue("featureFile", QFileInfo(filename).absoluteFilePath());
+
+ updateStatus();
+}
+
+void Main::showInfo(const QModelIndex &index)
+{
+ FeatureTreeModel *model;
+ model = static_cast<FeatureTreeModel*>(featureTree->model());
+
+ if (const Feature *feature = model->getFeature(index))
+ textBrowser->setHtml(feature->toHtml());
+
+ // Ensure index is visible
+ QModelIndex parent = model->parent(index);
+ while (parent.isValid()) {
+ featureTree->setExpanded(parent, true);
+ parent = model->parent(parent);
+ }
+
+ featureTree->scrollTo(index);
+ featureTree->setCurrentIndex(index);
+}
+
+void Main::showInfo(const QString &feature)
+{
+ const Feature *f = Feature::getInstance(feature);
+ FeatureTreeModel *model;
+ model = static_cast<FeatureTreeModel*>(featureTree->model());
+ showInfo(model->index(f));
+}
+
+void Main::about()
+{
+ QMessageBox::about(this, "About qconfig",
+ "<p><b><font size=\"+2\">Qtopia Core build configuration</font></b></p>"
+ "<p></p>"
+ "<p>Version 2.0</p>"
+ "<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>"
+ "<p></p>"
+ "<p>This program is licensed to you under the terms of the GNU General "
+ "Public License Version 2 as published by the Free Software Foundation. This "
+ "gives you legal permission to copy, distribute and/or modify this software "
+ "under certain conditions. For details, see the file 'LICENSE.GPL' that came with "
+ "this software distribution. If you did not get the file, send email to "
+ "qt-info@nokia.com.</p>\n\n<p>The program is provided AS IS with NO WARRANTY "
+ "OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS "
+ "FOR A PARTICULAR PURPOSE.</p>"
+ );
+}
+
+void Main::aboutQt()
+{
+ QMessageBox::aboutQt( this, tr("qconfig") );
+}
+
+QT_END_NAMESPACE
+
+int main(int argc, char** argv)
+{
+ QT_USE_NAMESPACE
+ QApplication app(argc,argv);
+ app.setOrganizationDomain("trolltech.com");
+ app.setOrganizationName("Trolltech");
+ app.setApplicationName("QConfig");
+ Main m;
+
+ defaultPath = QLibraryInfo::location(QLibraryInfo::PrefixPath)
+ + "/src/corelib/global";
+
+ for (int i = 1; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-f" && i+1 < argc)
+ m.loadFeatures(argv[++i]);
+ else if (arg == "-c" && i+1 < argc)
+ m.loadConfig(argv[++i]);
+ }
+ m.resize(m.sizeHint() + QSize(500,300));
+ m.show();
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/tools/qconfig/qconfig.pro b/tools/qconfig/qconfig.pro
new file mode 100644
index 0000000000..efbfcf2de1
--- /dev/null
+++ b/tools/qconfig/qconfig.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+CONFIG += qt warn_on
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+HEADERS = feature.h featuretreemodel.h graphics.h
+SOURCES = main.cpp feature.cpp featuretreemodel.cpp
+INTERFACES =
+TARGET = qconfig
diff --git a/tools/qdbus/qdbus.pro b/tools/qdbus/qdbus.pro
new file mode 100644
index 0000000000..01cd2463ae
--- /dev/null
+++ b/tools/qdbus/qdbus.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = qdbus qdbusxml2cpp qdbuscpp2xml qdbusviewer
diff --git a/tools/qdbus/qdbus/qdbus.cpp b/tools/qdbus/qdbus/qdbus.cpp
new file mode 100644
index 0000000000..d290eab65e
--- /dev/null
+++ b/tools/qdbus/qdbus/qdbus.cpp
@@ -0,0 +1,483 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
+#include <QtCore/qmetaobject.h>
+#include <QtXml/QDomDocument>
+#include <QtXml/QDomElement>
+#include <QtDBus/QtDBus>
+#include <private/qdbusutil_p.h>
+
+static QDBusConnection connection(QLatin1String(""));
+static bool printArgumentsLiterally = false;
+
+static void showUsage()
+{
+ printf("Usage: qdbus [--system] [--literal] [servicename] [path] [method] [args]\n"
+ "\n"
+ " servicename the service to connect to (e.g., org.freedesktop.DBus)\n"
+ " path the path to the object (e.g., /)\n"
+ " method the method to call, with or without the interface\n"
+ " args arguments to pass to the call\n"
+ "With 0 arguments, qdbus will list the services available on the bus\n"
+ "With just the servicename, qdbus will list the object paths available on the service\n"
+ "With service name and object path, qdbus will list the methods, signals and properties available on the object\n"
+ "\n"
+ "Options:\n"
+ " --system connect to the system bus\n"
+ " --literal print replies literally\n");
+}
+
+static void printArg(const QVariant &v)
+{
+ if (printArgumentsLiterally) {
+ printf("%s\n", qPrintable(QDBusUtil::argumentToString(v)));
+ return;
+ }
+
+ if (v.userType() == QVariant::StringList) {
+ foreach (QString s, v.toStringList())
+ printf("%s\n", qPrintable(s));
+ } else if (v.userType() == QVariant::List) {
+ foreach (const QVariant &var, v.toList())
+ printArg(var);
+ } else if (v.userType() == QVariant::Map) {
+ const QVariantMap map = v.toMap();
+ QVariantMap::ConstIterator it = map.constBegin();
+ for ( ; it != map.constEnd(); ++it) {
+ printf("%s: ", qPrintable(it.key()));
+ printArg(it.value());
+ }
+ } else if (v.userType() == qMetaTypeId<QDBusVariant>()) {
+ printArg(qvariant_cast<QDBusVariant>(v).variant());
+ } else if (v.userType() == qMetaTypeId<QDBusArgument>()) {
+ QDBusArgument arg = qvariant_cast<QDBusArgument>(v);
+ if (arg.currentSignature() == QLatin1String("av"))
+ printArg(qdbus_cast<QVariantList>(arg));
+ else if (arg.currentSignature() == QLatin1String("a{sv}"))
+ printArg(qdbus_cast<QVariantMap>(arg));
+ else
+ printf("qdbus: I don't know how to display an argument of type '%s'\n",
+ qPrintable(arg.currentSignature()));
+ } else {
+ printf("%s\n", qPrintable(v.toString()));
+ }
+}
+
+static void listObjects(const QString &service, const QString &path)
+{
+ QDBusInterface iface(service, path.isEmpty() ? QLatin1String("/") : path,
+ QLatin1String("org.freedesktop.DBus.Introspectable"), connection);
+ if (!iface.isValid()) {
+ QDBusError err(iface.lastError());
+ fprintf(stderr, "Cannot introspect object %s at %s:\n%s (%s)\n",
+ qPrintable(path.isEmpty() ? QString(QLatin1String("/")) : path), qPrintable(service),
+ qPrintable(err.name()), qPrintable(err.message()));
+ exit(1);
+ }
+ QDBusReply<QString> xml = iface.call(QLatin1String("Introspect"));
+
+ if (!xml.isValid())
+ return; // silently
+
+ QDomDocument doc;
+ doc.setContent(xml);
+ QDomElement node = doc.documentElement();
+ QDomElement child = node.firstChildElement();
+ while (!child.isNull()) {
+ if (child.tagName() == QLatin1String("node")) {
+ QString sub = path + QLatin1Char('/') + child.attribute(QLatin1String("name"));
+ printf("%s\n", qPrintable(sub));
+ listObjects(service, sub);
+ }
+ child = child.nextSiblingElement();
+ }
+}
+
+static void listInterface(const QString &service, const QString &path, const QString &interface)
+{
+ QDBusInterface iface(service, path, interface, connection);
+ if (!iface.isValid()) {
+ QDBusError err(iface.lastError());
+ fprintf(stderr, "Interface '%s' not available in object %s at %s:\n%s (%s)\n",
+ qPrintable(interface), qPrintable(path), qPrintable(service),
+ qPrintable(err.name()), qPrintable(err.message()));
+ exit(1);
+ }
+ const QMetaObject *mo = iface.metaObject();
+
+ // properties
+ for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
+ QMetaProperty mp = mo->property(i);
+ printf("property ");
+
+ if (mp.isReadable() && mp.isWritable())
+ printf("readwrite");
+ else if (mp.isReadable())
+ printf("read");
+ else
+ printf("write");
+
+ printf(" %s %s.%s\n", mp.typeName(), qPrintable(interface), mp.name());
+ }
+
+ // methods (signals and slots)
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ QMetaMethod mm = mo->method(i);
+
+ QByteArray signature = mm.signature();
+ signature.truncate(signature.indexOf('('));
+ printf("%s %s%s%s %s.%s(",
+ mm.methodType() == QMetaMethod::Signal ? "signal" : "method",
+ mm.tag(), *mm.tag() ? " " : "",
+ *mm.typeName() ? mm.typeName() : "void",
+ qPrintable(interface), signature.constData());
+
+ QList<QByteArray> types = mm.parameterTypes();
+ QList<QByteArray> names = mm.parameterNames();
+ bool first = true;
+ for (int i = 0; i < types.count(); ++i) {
+ printf("%s%s",
+ first ? "" : ", ",
+ types.at(i).constData());
+ if (!names.at(i).isEmpty())
+ printf(" %s", names.at(i).constData());
+ first = false;
+ }
+ printf(")\n");
+ }
+}
+
+static void listAllInterfaces(const QString &service, const QString &path)
+{
+ QDBusInterface iface(service, path, QLatin1String("org.freedesktop.DBus.Introspectable"), connection);
+ if (!iface.isValid()) {
+ QDBusError err(iface.lastError());
+ fprintf(stderr, "Cannot introspect object %s at %s:\n%s (%s)\n",
+ qPrintable(path), qPrintable(service),
+ qPrintable(err.name()), qPrintable(err.message()));
+ exit(1);
+ }
+ QDBusReply<QString> xml = iface.call(QLatin1String("Introspect"));
+
+ if (!xml.isValid())
+ return; // silently
+
+ QDomDocument doc;
+ doc.setContent(xml);
+ QDomElement node = doc.documentElement();
+ QDomElement child = node.firstChildElement();
+ while (!child.isNull()) {
+ if (child.tagName() == QLatin1String("interface")) {
+ QString ifaceName = child.attribute(QLatin1String("name"));
+ if (QDBusUtil::isValidInterfaceName(ifaceName))
+ listInterface(service, path, ifaceName);
+ else {
+ qWarning("Invalid D-BUS interface name '%s' found while parsing introspection",
+ qPrintable(ifaceName));
+ }
+ }
+ child = child.nextSiblingElement();
+ }
+}
+
+static QStringList readList(QStringList &args)
+{
+ args.takeFirst();
+
+ QStringList retval;
+ while (!args.isEmpty() && args.at(0) != QLatin1String(")"))
+ retval += args.takeFirst();
+
+ if (args.value(0) == QLatin1String(")"))
+ args.takeFirst();
+
+ return retval;
+}
+
+static void placeCall(const QString &service, const QString &path, const QString &interface,
+ const QString &member, QStringList args)
+{
+ QDBusInterface iface(service, path, interface, connection);
+ if (!iface.isValid()) {
+ QDBusError err(iface.lastError());
+ fprintf(stderr, "Interface '%s' not available in object %s at %s:\n%s (%s)\n",
+ qPrintable(interface), qPrintable(path), qPrintable(service),
+ qPrintable(err.name()), qPrintable(err.message()));
+ exit(1);
+ }
+
+ QVariantList params;
+ if (!args.isEmpty()) {
+ const QMetaObject *mo = iface.metaObject();
+ QByteArray match = member.toLatin1();
+ match += '(';
+
+ int midx = -1;
+ for (int i = mo->methodOffset(); i < mo->methodCount(); ++i) {
+ QMetaMethod mm = mo->method(i);
+ QByteArray signature = mm.signature();
+ if (signature.startsWith(match)) {
+ midx = i;
+ break;
+ }
+ }
+
+ if (midx == -1) {
+ fprintf(stderr, "Cannot find '%s.%s' in object %s at %s\n",
+ qPrintable(interface), qPrintable(member), qPrintable(path),
+ qPrintable(service));
+ exit(1);
+ }
+
+ QMetaMethod mm = mo->method(midx);
+ QList<QByteArray> types = mm.parameterTypes();
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i).endsWith('&')) {
+ // reference (and not a reference to const): output argument
+ // we're done with the inputs
+ while (types.count() > i)
+ types.removeLast();
+ break;
+ }
+ }
+
+ for (int i = 0; !args.isEmpty() && i < types.count(); ++i) {
+ int id = QVariant::nameToType(types.at(i));
+ if (id == QVariant::UserType)
+ id = QMetaType::type(types.at(i));
+ Q_ASSERT(id);
+
+ QVariant p;
+ QString argument;
+ if ((id == QVariant::List || id == QVariant::StringList)
+ && args.at(0) == QLatin1String("("))
+ p = readList(args);
+ else
+ p = argument = args.takeFirst();
+
+ if (id == int(QMetaType::UChar)) {
+ // special case: QVariant::convert doesn't convert to/from
+ // UChar because it can't decide if it's a character or a number
+ p = qVariantFromValue<uchar>(p.toUInt());
+ } else if (id < int(QMetaType::User) && id != int(QVariant::Map)) {
+ p.convert(QVariant::Type(id));
+ if (p.type() == QVariant::Invalid) {
+ fprintf(stderr, "Could not convert '%s' to type '%s'.\n",
+ qPrintable(argument), types.at(i).constData());
+ exit(1);
+ }
+ } else if (id == qMetaTypeId<QDBusVariant>()) {
+ QDBusVariant tmp(p);
+ p = qVariantFromValue(tmp);
+ } else if (id == qMetaTypeId<QDBusObjectPath>()) {
+ QDBusObjectPath path(argument);
+ if (path.path().isNull()) {
+ fprintf(stderr, "Cannot pass argument '%s' because it is not a valid object path.\n",
+ qPrintable(argument));
+ exit(1);
+ }
+ p = qVariantFromValue(path);
+ } else if (id == qMetaTypeId<QDBusSignature>()) {
+ QDBusSignature sig(argument);
+ if (sig.signature().isNull()) {
+ fprintf(stderr, "Cannot pass argument '%s' because it is not a valid signature.\n",
+ qPrintable(argument));
+ exit(1);
+ }
+ p = qVariantFromValue(sig);
+ } else {
+ fprintf(stderr, "Sorry, can't pass arg of type '%s'.\n",
+ types.at(i).constData());
+ exit(1);
+ }
+ params += p;
+ }
+ if (params.count() != types.count() || !args.isEmpty()) {
+ fprintf(stderr, "Invalid number of parameters\n");
+ exit(1);
+ }
+ }
+
+ QDBusMessage reply = iface.callWithArgumentList(QDBus::Block, member, params);
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ QDBusError err = reply;
+ printf("Error: %s\n%s\n", qPrintable(err.name()), qPrintable(err.message()));
+ exit(2);
+ } else if (reply.type() != QDBusMessage::ReplyMessage) {
+ fprintf(stderr, "Invalid reply type %d\n", int(reply.type()));
+ exit(1);
+ }
+
+ foreach (QVariant v, reply.arguments())
+ printArg(v);
+
+ exit(0);
+}
+
+static bool globServices(QDBusConnectionInterface *bus, const QString &glob)
+{
+ QRegExp pattern(glob, Qt::CaseSensitive, QRegExp::Wildcard);
+ if (!pattern.isValid())
+ return false;
+
+ QStringList names = bus->registeredServiceNames();
+ names.sort();
+ foreach (const QString &name, names)
+ if (pattern.exactMatch(name))
+ printf("%s\n", qPrintable(name));
+
+ return true;
+}
+
+static void printAllServices(QDBusConnectionInterface *bus)
+{
+ const QStringList services = bus->registeredServiceNames();
+ QMap<QString, QStringList> servicesWithAliases;
+
+ foreach (QString serviceName, services) {
+ QDBusReply<QString> reply = bus->serviceOwner(serviceName);
+ QString owner = reply;
+ if (owner.isEmpty())
+ owner = serviceName;
+ servicesWithAliases[owner].append(serviceName);
+ }
+
+ for (QMap<QString,QStringList>::const_iterator it = servicesWithAliases.constBegin();
+ it != servicesWithAliases.constEnd(); ++it) {
+ QStringList names = it.value();
+ names.sort();
+ printf("%s\n", qPrintable(names.join(QLatin1String("\n "))));
+ }
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ QStringList args = app.arguments();
+ args.takeFirst();
+
+ bool connectionOpened = false;
+ while (!args.isEmpty() && args.at(0).startsWith(QLatin1Char('-'))) {
+ QString arg = args.takeFirst();
+ if (arg == QLatin1String("--system")) {
+ connection = QDBusConnection::systemBus();
+ connectionOpened = true;
+ } else if (arg == QLatin1String("--literal")) {
+ printArgumentsLiterally = true;
+ } else if (arg == QLatin1String("--help")) {
+ showUsage();
+ return 0;
+ }
+ }
+
+ if (!connectionOpened)
+ connection = QDBusConnection::sessionBus();
+
+ if (!connection.isConnected()) {
+ fprintf(stderr, "Could not connect to D-Bus server: %s: %s\n",
+ qPrintable(connection.lastError().name()),
+ qPrintable(connection.lastError().message()));
+ return 1;
+ }
+
+ QDBusConnectionInterface *bus = connection.interface();
+ if (args.isEmpty()) {
+ printAllServices(bus);
+ exit(0);
+ }
+
+ QString service = args.takeFirst();
+ if (!QDBusUtil::isValidBusName(service)) {
+ if (service.contains(QLatin1Char('*'))) {
+ if (globServices(bus, service))
+ return 0;
+ }
+ fprintf(stderr, "Service '%s' is not a valid name.\n", qPrintable(service));
+ exit(1);
+ }
+ if (!bus->isServiceRegistered(service)) {
+ fprintf(stderr, "Service '%s' does not exist.\n", qPrintable(service));
+ exit(1);
+ }
+
+ if (args.isEmpty()) {
+ printf("/\n");
+ listObjects(service, QString());
+ exit(0);
+ }
+
+ QString path = args.takeFirst();
+ if (!QDBusUtil::isValidObjectPath(path)) {
+ fprintf(stderr, "Path '%s' is not a valid path name.\n", qPrintable(path));
+ exit(1);
+ }
+ if (args.isEmpty()) {
+ listAllInterfaces(service, path);
+ exit(0);
+ }
+
+ QString interface = args.takeFirst();
+ QString member;
+ int pos = interface.lastIndexOf(QLatin1Char('.'));
+ if (pos == -1) {
+ member = interface;
+ interface.clear();
+ } else {
+ member = interface.mid(pos + 1);
+ interface.truncate(pos);
+ }
+ if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) {
+ fprintf(stderr, "Interface '%s' is not a valid interface name.\n", qPrintable(interface));
+ exit(1);
+ }
+ if (!QDBusUtil::isValidMemberName(member)) {
+ fprintf(stderr, "Method name '%s' is not a valid member name.\n", qPrintable(member));
+ exit(1);
+ }
+
+ placeCall(service, path, interface, member, args);
+}
+
diff --git a/tools/qdbus/qdbus/qdbus.pro b/tools/qdbus/qdbus/qdbus.pro
new file mode 100644
index 0000000000..ea732ef288
--- /dev/null
+++ b/tools/qdbus/qdbus/qdbus.pro
@@ -0,0 +1,10 @@
+SOURCES = qdbus.cpp
+DESTDIR = ../../../bin
+TARGET = qdbus
+QT = core xml
+CONFIG += qdbus
+CONFIG -= app_bundle
+win32:CONFIG += console
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.cpp b/tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.cpp
new file mode 100644
index 0000000000..9e789b090c
--- /dev/null
+++ b/tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QByteArray>
+#include <QString>
+#include <QVarLengthArray>
+#include <QFile>
+#include <QProcess>
+#include <QMetaObject>
+#include <QList>
+#include <QRegExp>
+#include <QCoreApplication>
+#include <QLibraryInfo>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "qdbusconnection.h" // for the Export* flags
+
+// copied from dbus-protocol.h:
+static const char docTypeHeader[] =
+ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n";
+
+// in qdbusxmlgenerator.cpp
+QT_BEGIN_NAMESPACE
+extern QDBUS_EXPORT QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo,
+ const QMetaObject *base, int flags);
+QT_END_NAMESPACE
+
+#define PROGRAMNAME "qdbuscpp2xml"
+#define PROGRAMVERSION "0.1"
+#define PROGRAMCOPYRIGHT "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)."
+
+static QString outputFile;
+static int flags;
+
+static const char help[] =
+ "Usage: " PROGRAMNAME " [options...] [files...]\n"
+ "Parses the C++ source or header file containing a QObject-derived class and\n"
+ "produces the D-Bus Introspection XML."
+ "\n"
+ "Options:\n"
+ " -p|-s|-m Only parse scriptable Properties, Signals and Methods (slots)\n"
+ " -P|-S|-M Parse all Properties, Signals and Methods (slots)\n"
+ " -a Output all scriptable contents (equivalent to -psm)\n"
+ " -A Output all contents (equivalent to -PSM)\n"
+ " -o <filename> Write the output to file <filename>\n"
+ " -h Show this information\n"
+ " -V Show the program version and quit.\n"
+ "\n";
+
+class MocParser
+{
+ void parseError();
+ QByteArray readLine();
+ void loadIntData(uint *&data);
+ void loadStringData(char *&stringdata);
+
+ QIODevice *input;
+ const char *filename;
+ int lineNumber;
+public:
+ ~MocParser();
+ void parse(const char *filename, QIODevice *input, int lineNumber = 0);
+
+ QList<QMetaObject> objects;
+};
+
+void MocParser::parseError()
+{
+ fprintf(stderr, PROGRAMNAME ": error parsing input file '%s' line %d \n", filename, lineNumber);
+ exit(1);
+}
+
+QByteArray MocParser::readLine()
+{
+ ++lineNumber;
+ return input->readLine();
+}
+
+void MocParser::loadIntData(uint *&data)
+{
+ data = 0; // initialise
+ QVarLengthArray<uint> array;
+ QRegExp rx(QLatin1String("(\\d+|0x[0-9abcdef]+)"), Qt::CaseInsensitive);
+
+ while (!input->atEnd()) {
+ QString line = QLatin1String(readLine());
+ int pos = line.indexOf(QLatin1String("//"));
+ if (pos != -1)
+ line.truncate(pos); // drop comments
+
+ if (line == QLatin1String("};\n")) {
+ // end of data
+ data = new uint[array.count()];
+ memcpy(data, array.data(), array.count() * sizeof(*data));
+ return;
+ }
+
+ pos = 0;
+ while ((pos = rx.indexIn(line, pos)) != -1) {
+ QString num = rx.cap(1);
+ if (num.startsWith(QLatin1String("0x")))
+ array.append(num.mid(2).toUInt(0, 16));
+ else
+ array.append(num.toUInt());
+ pos += rx.matchedLength();
+ }
+ }
+
+ parseError();
+}
+
+void MocParser::loadStringData(char *&stringdata)
+{
+ stringdata = 0;
+ QVarLengthArray<char, 1024> array;
+
+ while (!input->atEnd()) {
+ QByteArray line = readLine();
+ if (line == "};\n") {
+ // end of data
+ stringdata = new char[array.count()];
+ memcpy(stringdata, array.data(), array.count() * sizeof(*stringdata));
+ return;
+ }
+
+ int start = line.indexOf('"');
+ if (start == -1)
+ parseError();
+
+ int len = line.length() - 1;
+ line.truncate(len); // drop ending \n
+ if (line.at(len - 1) != '"')
+ parseError();
+
+ --len;
+ ++start;
+ for ( ; start < len; ++start)
+ if (line.at(start) == '\\') {
+ // parse escaped sequence
+ ++start;
+ if (start == len)
+ parseError();
+
+ QChar c(QLatin1Char(line.at(start)));
+ if (!c.isDigit()) {
+ switch (c.toLatin1()) {
+ case 'a':
+ array.append('\a');
+ break;
+ case 'b':
+ array.append('\b');
+ break;
+ case 'f':
+ array.append('\f');
+ break;
+ case 'n':
+ array.append('\n');
+ break;
+ case 'r':
+ array.append('\r');
+ break;
+ case 't':
+ array.append('\t');
+ break;
+ case 'v':
+ array.append('\v');
+ break;
+ case '\\':
+ case '?':
+ case '\'':
+ case '"':
+ array.append(c.toLatin1());
+ break;
+
+ case 'x':
+ if (start + 2 <= len)
+ parseError();
+ array.append(char(line.mid(start + 1, 2).toInt(0, 16)));
+ break;
+
+ default:
+ array.append(c.toLatin1());
+ fprintf(stderr, PROGRAMNAME ": warning: invalid escape sequence '\\%c' found in input",
+ c.toLatin1());
+ }
+ } else {
+ // octal
+ QRegExp octal(QLatin1String("([0-7]+)"));
+ if (octal.indexIn(QLatin1String(line), start) == -1)
+ parseError();
+ array.append(char(octal.cap(1).toInt(0, 8)));
+ }
+ } else {
+ array.append(line.at(start));
+ }
+ }
+
+ parseError();
+}
+
+void MocParser::parse(const char *fname, QIODevice *io, int lineNum)
+{
+ filename = fname;
+ input = io;
+ lineNumber = lineNum;
+
+ while (!input->atEnd()) {
+ QByteArray line = readLine();
+ if (line.startsWith("static const uint qt_meta_data_")) {
+ // start of new class data
+ uint *data;
+ loadIntData(data);
+
+ // find the start of the string data
+ do {
+ line = readLine();
+ if (input->atEnd())
+ parseError();
+ } while (!line.startsWith("static const char qt_meta_stringdata_"));
+
+ char *stringdata;
+ loadStringData(stringdata);
+
+ QMetaObject mo;
+ mo.d.superdata = &QObject::staticMetaObject;
+ mo.d.stringdata = stringdata;
+ mo.d.data = data;
+ mo.d.extradata = 0;
+ objects.append(mo);
+ }
+ }
+
+ fname = 0;
+ input = 0;
+}
+
+MocParser::~MocParser()
+{
+ foreach (QMetaObject mo, objects) {
+ delete const_cast<char *>(mo.d.stringdata);
+ delete const_cast<uint *>(mo.d.data);
+ }
+}
+
+static void showHelp()
+{
+ printf("%s", help);
+ exit(0);
+}
+
+static void showVersion()
+{
+ printf("%s version %s\n", PROGRAMNAME, PROGRAMVERSION);
+ printf("D-Bus QObject-to-XML converter\n");
+ exit(0);
+}
+
+static void parseCmdLine(QStringList &arguments)
+{
+ for (int i = 1; i < arguments.count(); ++i) {
+ const QString arg = arguments.at(i);
+
+ if (arg == QLatin1String("--help"))
+ showHelp();
+
+ if (!arg.startsWith(QLatin1Char('-')))
+ continue;
+
+ char c = arg.count() == 2 ? arg.at(1).toLatin1() : char(0);
+ switch (c) {
+ case 'P':
+ flags |= QDBusConnection::ExportNonScriptableProperties;
+ // fall through
+ case 'p':
+ flags |= QDBusConnection::ExportScriptableProperties;
+ break;
+
+ case 'S':
+ flags |= QDBusConnection::ExportNonScriptableSignals;
+ // fall through
+ case 's':
+ flags |= QDBusConnection::ExportScriptableSignals;
+ break;
+
+ case 'M':
+ flags |= QDBusConnection::ExportNonScriptableSlots;
+ // fall through
+ case 'm':
+ flags |= QDBusConnection::ExportScriptableSlots;
+ break;
+
+ case 'A':
+ flags |= QDBusConnection::ExportNonScriptableContents;
+ // fall through
+ case 'a':
+ flags |= QDBusConnection::ExportScriptableContents;
+ break;
+
+ case 'o':
+ if (arguments.count() < i + 2 || arguments.at(i + 1).startsWith(QLatin1Char('-'))) {
+ printf("-o expects a filename\n");
+ exit(1);
+ }
+ outputFile = arguments.takeAt(i + 1);
+ break;
+
+ case 'h':
+ case '?':
+ showHelp();
+ break;
+
+ case 'V':
+ showVersion();
+ break;
+
+ default:
+ printf("unknown option: \"%s\"\n", qPrintable(arg));
+ exit(1);
+ }
+ }
+
+ if (flags == 0)
+ flags = QDBusConnection::ExportScriptableContents
+ | QDBusConnection::ExportNonScriptableContents;
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ QStringList args = app.arguments();
+
+ MocParser parser;
+ parseCmdLine(args);
+
+ for (int i = 1; i < args.count(); ++i) {
+ const QString arg = args.at(i);
+ if (arg.startsWith(QLatin1Char('-')))
+ continue;
+
+ QFile f(arg);
+ if (!f.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ fprintf(stderr, PROGRAMNAME ": could not open '%s': %s\n",
+ qPrintable(arg), qPrintable(f.errorString()));
+ return 1;
+ }
+
+ f.readLine();
+
+ QByteArray line = f.readLine();
+ if (line.contains("Meta object code from reading C++ file"))
+ // this is a moc-generated file
+ parser.parse(argv[i], &f, 3);
+ else {
+ // run moc on this file
+ QProcess proc;
+ proc.start(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/moc"), QStringList() << QFile::decodeName(argv[i]), QIODevice::ReadOnly | QIODevice::Text);
+
+ if (!proc.waitForStarted()) {
+ fprintf(stderr, PROGRAMNAME ": could not execute moc! Aborting.\n");
+ return 1;
+ }
+
+ proc.closeWriteChannel();
+
+ if (!proc.waitForFinished() || proc.exitStatus() != QProcess::NormalExit ||
+ proc.exitCode() != 0) {
+ // output the moc errors:
+ fprintf(stderr, "%s", proc.readAllStandardError().constData());
+ fprintf(stderr, PROGRAMNAME ": exit code %d from moc. Aborting\n", proc.exitCode());
+ return 1;
+ }
+ fprintf(stderr, "%s", proc.readAllStandardError().constData());
+
+ parser.parse(argv[i], &proc, 1);
+ }
+
+ f.close();
+ }
+
+ QFile output;
+ if (outputFile.isEmpty()) {
+ output.open(stdout, QIODevice::WriteOnly);
+ } else {
+ output.setFileName(outputFile);
+ if (!output.open(QIODevice::WriteOnly)) {
+ fprintf(stderr, PROGRAMNAME ": could not open output file '%s': %s",
+ qPrintable(outputFile), qPrintable(output.errorString()));
+ return 1;
+ }
+ }
+
+ output.write(docTypeHeader);
+ output.write("<node>\n");
+ foreach (QMetaObject mo, parser.objects) {
+ QString xml = qDBusGenerateMetaObjectXml(QString(), &mo, &QObject::staticMetaObject,
+ flags);
+ output.write(xml.toLocal8Bit());
+ }
+ output.write("</node>\n");
+
+ return 0;
+}
+
diff --git a/tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.pro b/tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.pro
new file mode 100644
index 0000000000..9ee1d37278
--- /dev/null
+++ b/tools/qdbus/qdbuscpp2xml/qdbuscpp2xml.pro
@@ -0,0 +1,10 @@
+SOURCES = qdbuscpp2xml.cpp
+DESTDIR = ../../../bin
+TARGET = qdbuscpp2xml
+QT = core xml
+CONFIG += qdbus
+CONFIG -= app_bundle
+win32:CONFIG += console
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/tools/qdbus/qdbusviewer/Info_mac.plist b/tools/qdbus/qdbusviewer/Info_mac.plist
new file mode 100644
index 0000000000..b351409971
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/Info_mac.plist
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.trolltech.dbusviewer</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+</dict>
+</plist>
diff --git a/tools/qdbus/qdbusviewer/images/qdbusviewer-128.png b/tools/qdbus/qdbusviewer/images/qdbusviewer-128.png
new file mode 100644
index 0000000000..0754912213
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/images/qdbusviewer-128.png
Binary files differ
diff --git a/tools/qdbus/qdbusviewer/images/qdbusviewer.icns b/tools/qdbus/qdbusviewer/images/qdbusviewer.icns
new file mode 100644
index 0000000000..b6f39b9c23
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/images/qdbusviewer.icns
Binary files differ
diff --git a/tools/qdbus/qdbusviewer/images/qdbusviewer.ico b/tools/qdbus/qdbusviewer/images/qdbusviewer.ico
new file mode 100644
index 0000000000..49edb09f0b
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/images/qdbusviewer.ico
Binary files differ
diff --git a/tools/qdbus/qdbusviewer/images/qdbusviewer.png b/tools/qdbus/qdbusviewer/images/qdbusviewer.png
new file mode 100644
index 0000000000..5a8c5a341c
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/images/qdbusviewer.png
Binary files differ
diff --git a/tools/qdbus/qdbusviewer/main.cpp b/tools/qdbus/qdbusviewer/main.cpp
new file mode 100644
index 0000000000..b670337087
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/main.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qmainwindow.h>
+#include <QtGui/qtabwidget.h>
+#include <QtDBus/qdbusconnection.h>
+#include "qdbusviewer.h"
+
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QMainWindow mw;
+#ifndef Q_WS_MAC
+ app.setWindowIcon(QIcon(QLatin1String(":/trolltech/qdbusviewer/images/qdbusviewer.png")));
+#else
+ mw.setWindowTitle(qApp->translate("QtDBusViewer", "Qt D-Bus Viewer"));
+#endif
+
+
+ QTabWidget *mainWidget = new QTabWidget;
+ mw.setCentralWidget(mainWidget);
+ QDBusViewer *sessionBusViewer = new QDBusViewer(QDBusConnection::sessionBus());
+ QDBusViewer *systemBusViewer = new QDBusViewer(QDBusConnection::systemBus());
+ mainWidget->addTab(sessionBusViewer, QObject::tr("Session Bus"));
+ mainWidget->addTab(systemBusViewer, QObject::tr("System Bus"));
+
+ QMenu *fileMenu = mw.menuBar()->addMenu(QObject::tr("&File"));
+ QAction *quitAction = fileMenu->addAction(QObject::tr("&Quit"), &mw, SLOT(close()));
+ Q_UNUSED(quitAction);
+
+ QMenu *helpMenu = mw.menuBar()->addMenu(QObject::tr("&Help"));
+ QAction *aboutAction = helpMenu->addAction(QObject::tr("&About"));
+ aboutAction->setMenuRole(QAction::AboutRole);
+ QObject::connect(aboutAction, SIGNAL(triggered()), sessionBusViewer, SLOT(about()));
+
+ QAction *aboutQtAction = helpMenu->addAction(QObject::tr("About &Qt"));
+ aboutQtAction->setMenuRole(QAction::AboutQtRole);
+ QObject::connect(aboutQtAction, SIGNAL(triggered()), &app, SLOT(aboutQt()));
+
+ mw.show();
+
+ return app.exec();
+}
+
diff --git a/tools/qdbus/qdbusviewer/propertydialog.cpp b/tools/qdbus/qdbusviewer/propertydialog.cpp
new file mode 100644
index 0000000000..6359cd72c3
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/propertydialog.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "propertydialog.h"
+
+#include <QHeaderView>
+#include <QLayout>
+#include <QDebug>
+
+PropertyDialog::PropertyDialog(QWidget *parent, Qt::WindowFlags f)
+ : QDialog(parent, f)
+{
+ buttonBox = new QDialogButtonBox;
+ propertyTable = new QTableWidget;
+ label = new QLabel;
+
+ buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ propertyTable->setColumnCount(2);
+ const QStringList labels = QStringList() << QLatin1String("Name") << QLatin1String("Value");
+ propertyTable->setHorizontalHeaderLabels(labels);
+ propertyTable->horizontalHeader()->setStretchLastSection(true);
+ propertyTable->setEditTriggers(QAbstractItemView::AllEditTriggers);
+
+ connect(buttonBox, SIGNAL(accepted()), SLOT(accept()), Qt::QueuedConnection);
+ connect(buttonBox, SIGNAL(rejected()), SLOT(reject()), Qt::QueuedConnection);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(label);
+ layout->addWidget(propertyTable);
+ layout->addWidget(buttonBox);
+}
+
+void PropertyDialog::setInfo(const QString &caption)
+{
+ label->setText(caption);
+}
+
+void PropertyDialog::addProperty(const QString &aname, QVariant::Type type)
+{
+ int rowCount = propertyTable->rowCount();
+ propertyTable->setRowCount(rowCount + 1);
+
+ QString name = aname;
+ if (name.isEmpty())
+ name = QLatin1String("argument ") + QString::number(rowCount + 1);
+ name += QLatin1String(" (");
+ name += QLatin1String(QVariant::typeToName(type));
+ name += QLatin1String(")");
+ QTableWidgetItem *nameItem = new QTableWidgetItem(name);
+ nameItem->setFlags(nameItem->flags() &
+ ~(Qt::ItemIsEditable | Qt::ItemIsSelectable));
+ propertyTable->setItem(rowCount, 0, nameItem);
+
+ QTableWidgetItem *valueItem = new QTableWidgetItem;
+ valueItem->setData(Qt::DisplayRole, QVariant(type));
+ propertyTable->setItem(rowCount, 1, valueItem);
+}
+
+int PropertyDialog::exec()
+{
+ propertyTable->resizeColumnToContents(0);
+ propertyTable->setFocus();
+ propertyTable->setCurrentCell(0, 1);
+ return QDialog::exec();
+}
+
+QList<QVariant> PropertyDialog::values() const
+{
+ QList<QVariant> result;
+
+ for (int i = 0; i < propertyTable->rowCount(); ++i)
+ result << propertyTable->item(i, 1)->data(Qt::EditRole);
+
+ return result;
+}
+
diff --git a/tools/qdbus/qdbusviewer/propertydialog.h b/tools/qdbus/qdbusviewer/propertydialog.h
new file mode 100644
index 0000000000..2ba30e175d
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/propertydialog.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROPERTYDIALOG_H
+#define PROPERTYDIALOG_H
+
+#include <QLabel>
+#include <QDialog>
+#include <QTableWidget>
+#include <QDialogButtonBox>
+
+class PropertyDialog: public QDialog
+{
+ Q_OBJECT
+public:
+ explicit PropertyDialog(QWidget *parent = 0, Qt::WindowFlags f = 0);
+
+ void addProperty(const QString &name, QVariant::Type type);
+ void setInfo(const QString &caption);
+
+ QList<QVariant> values() const;
+
+ int exec();
+
+private:
+ QLabel *label;
+ QTableWidget *propertyTable;
+ QDialogButtonBox *buttonBox;
+};
+
+#endif
+
diff --git a/tools/qdbus/qdbusviewer/qdbusmodel.cpp b/tools/qdbus/qdbusviewer/qdbusmodel.cpp
new file mode 100644
index 0000000000..88e352411d
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/qdbusmodel.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdbusmodel.h"
+
+#include <QtCore/qvector.h>
+#include <QtXml/QtXml>
+
+struct QDBusItem
+{
+ inline QDBusItem(QDBusModel::Type aType, const QString &aName, QDBusItem *aParent = 0)
+ : type(aType), parent(aParent), isPrefetched(type != QDBusModel::PathItem), name(aName)
+ {}
+ inline ~QDBusItem()
+ {
+ qDeleteAll(children);
+ }
+
+ QString path() const
+ {
+ Q_ASSERT(type == QDBusModel::PathItem);
+
+ QString s;
+ const QDBusItem *item = this;
+ while (item) {
+ s.prepend(item->name);
+ item = item->parent;
+ }
+ if (s.length() > 1)
+ s.chop(1); // remove tailing slash
+ return s;
+ }
+
+ QDBusModel::Type type;
+ QDBusItem *parent;
+ QVector<QDBusItem *> children;
+ bool isPrefetched;
+ QString name;
+ QString caption;
+};
+
+QDomDocument QDBusModel::introspect(const QString &path)
+{
+ QDomDocument doc;
+
+ QDBusInterface iface(service, path, QLatin1String("org.freedesktop.DBus.Introspectable"), c);
+ if (!iface.isValid()) {
+ QDBusError err(iface.lastError());
+ emit busError(QString::fromLatin1("Cannot introspect object %1 at %2:\n %3 (%4)\n").arg(path).arg(
+ service).arg(err.name()).arg(err.message()));
+ return doc;
+ }
+
+ QDBusReply<QString> xml = iface.call(QLatin1String("Introspect"));
+
+ if (!xml.isValid()) {
+ QDBusError err(xml.error());
+ if (err.isValid()) {
+ emit busError(QString::fromLatin1("Call to object %1 at %2:\n %3 (%4) failed\n").arg(
+ path).arg(service).arg(err.name()).arg(err.message()));
+ } else {
+ emit busError(QString::fromLatin1("Invalid XML received from object %1 at %2\n").arg(
+ path).arg(service));
+ }
+ return doc;
+ }
+
+ doc.setContent(xml);
+ return doc;
+}
+
+void QDBusModel::addMethods(QDBusItem *parent, const QDomElement &iface)
+{
+ Q_ASSERT(parent);
+
+ QDomElement child = iface.firstChildElement();
+ while (!child.isNull()) {
+ QDBusItem *item = 0;
+ if (child.tagName() == QLatin1String("method")) {
+ item = new QDBusItem(QDBusModel::MethodItem,
+ child.attribute(QLatin1String("name")), parent);
+ item->caption = QLatin1String("Method: ") + item->name;
+ } else if (child.tagName() == QLatin1String("signal")) {
+ item = new QDBusItem(QDBusModel::SignalItem,
+ child.attribute(QLatin1String("name")), parent);
+ item->caption = QLatin1String("Signal: ") + item->name;
+ } else if (child.tagName() == QLatin1String("property")) {
+ item = new QDBusItem(QDBusModel::PropertyItem,
+ child.attribute(QLatin1String("name")), parent);
+ item->caption = QLatin1String("Property: ") + item->name;
+ } else {
+ qDebug() << "addMethods: unknown tag:" << child.tagName();
+ }
+ if (item)
+ parent->children.append(item);
+
+ child = child.nextSiblingElement();
+ }
+}
+
+void QDBusModel::addPath(QDBusItem *parent)
+{
+ Q_ASSERT(parent);
+
+ QString path = parent->path();
+
+ QDomDocument doc = introspect(path);
+ QDomElement node = doc.documentElement();
+ QDomElement child = node.firstChildElement();
+ while (!child.isNull()) {
+ if (child.tagName() == QLatin1String("node")) {
+ QDBusItem *item = new QDBusItem(QDBusModel::PathItem,
+ child.attribute(QLatin1String("name")) + QLatin1Char('/'), parent);
+ parent->children.append(item);
+
+ addMethods(item, child);
+ } else if (child.tagName() == QLatin1String("interface")) {
+ QDBusItem *item = new QDBusItem(QDBusModel::InterfaceItem,
+ child.attribute(QLatin1String("name")), parent);
+ parent->children.append(item);
+
+ addMethods(item, child);
+ } else {
+ qDebug() << "addPath: Unknown tag name:" << child.tagName();
+ }
+ child = child.nextSiblingElement();
+ }
+
+ parent->isPrefetched = true;
+}
+
+QDBusModel::QDBusModel(const QString &aService, const QDBusConnection &connection)
+ : service(aService), c(connection), root(0)
+{
+ root = new QDBusItem(QDBusModel::PathItem, QLatin1String("/"));
+}
+
+QDBusModel::~QDBusModel()
+{
+ delete root;
+}
+
+QModelIndex QDBusModel::index(int row, int column, const QModelIndex &parent) const
+{
+ const QDBusItem *item = static_cast<QDBusItem *>(parent.internalPointer());
+ if (!item)
+ item = root;
+
+ if (column != 0 || row < 0 || row >= item->children.count())
+ return QModelIndex();
+
+ return createIndex(row, 0, item->children.at(row));
+}
+
+QModelIndex QDBusModel::parent(const QModelIndex &child) const
+{
+ QDBusItem *item = static_cast<QDBusItem *>(child.internalPointer());
+ if (!item || !item->parent || !item->parent->parent)
+ return QModelIndex();
+
+ return createIndex(item->parent->parent->children.indexOf(item->parent), 0, item->parent);
+}
+
+int QDBusModel::rowCount(const QModelIndex &parent) const
+{
+ QDBusItem *item = static_cast<QDBusItem *>(parent.internalPointer());
+ if (!item)
+ item = root;
+ if (!item->isPrefetched)
+ const_cast<QDBusModel *>(this)->addPath(item);
+
+ return item->children.count();
+}
+
+int QDBusModel::columnCount(const QModelIndex &) const
+{
+ return 1;
+}
+
+QVariant QDBusModel::data(const QModelIndex &index, int role) const
+{
+ const QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
+ if (!item)
+ return QVariant();
+
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ return item->caption.isEmpty() ? item->name : item->caption;
+}
+
+QVariant QDBusModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole || orientation == Qt::Vertical || section != 0)
+ return QVariant();
+
+ return QLatin1String("Methods");
+}
+
+QDBusModel::Type QDBusModel::itemType(const QModelIndex &index) const
+{
+ const QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
+ return item ? item->type : PathItem;
+}
+
+void QDBusModel::refresh(const QModelIndex &aIndex)
+{
+ QModelIndex index = aIndex;
+ while (index.isValid() && static_cast<QDBusItem *>(index.internalPointer())->type != PathItem) {
+ index = index.parent();
+ }
+
+ QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
+ if (!item)
+ item = root;
+
+ if (!item->children.isEmpty()) {
+ beginRemoveRows(index, 0, item->children.count() - 1);
+ qDeleteAll(item->children);
+ item->children.clear();
+ endRemoveRows();
+ }
+
+ addPath(item);
+ if (!item->children.isEmpty()) {
+ beginInsertRows(index, 0, item->children.count() - 1);
+ endInsertRows();
+ }
+}
+
+QString QDBusModel::dBusPath(const QModelIndex &aIndex) const
+{
+ QModelIndex index = aIndex;
+ while (index.isValid() && static_cast<QDBusItem *>(index.internalPointer())->type != PathItem) {
+ index = index.parent();
+ }
+
+ QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
+ if (!item)
+ item = root;
+
+ return item->path();
+}
+
+QString QDBusModel::dBusInterface(const QModelIndex &index) const
+{
+ QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
+ if (!item)
+ return QString();
+ if (item->type == InterfaceItem)
+ return item->name;
+ if (item->parent && item->parent->type == InterfaceItem)
+ return item->parent->name;
+ return QString();
+}
+
+QString QDBusModel::dBusMethodName(const QModelIndex &index) const
+{
+ QDBusItem *item = static_cast<QDBusItem *>(index.internalPointer());
+ return item ? item->name : QString();
+}
+
+QModelIndex QDBusModel::findObject(const QDBusObjectPath &objectPath)
+{
+ QStringList path = objectPath.path().split(QLatin1Char('/'), QString::SkipEmptyParts);
+
+ QDBusItem *item = root;
+ int childIdx = -1;
+ while (item && !path.isEmpty()) {
+ const QString branch = path.takeFirst() + QLatin1Char('/');
+ childIdx = -1;
+
+ // do a linear search over all the children
+ for (int i = 0; i < item->children.count(); ++i) {
+ QDBusItem *child = item->children.at(i);
+ if (child->type == PathItem && child->name == branch) {
+ item = child;
+ childIdx = i;
+
+ // prefetch the found branch
+ if (!item->isPrefetched)
+ addPath(item);
+ break;
+ }
+ }
+
+ // branch not found - bail out
+ if (childIdx == -1)
+ return QModelIndex();
+ }
+
+ // found the right item
+ if (childIdx != -1 && item && path.isEmpty())
+ return createIndex(childIdx, 0, item);
+
+ return QModelIndex();
+}
+
diff --git a/tools/qdbus/qdbusviewer/qdbusmodel.h b/tools/qdbus/qdbusviewer/qdbusmodel.h
new file mode 100644
index 0000000000..50f928e9ba
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/qdbusmodel.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDBUSMODEL_H
+#define QDBUSMODEL_H
+
+#include <QtCore/qabstractitemmodel.h>
+#include <QtDBus/QtDBus>
+
+struct QDBusItem;
+
+QT_FORWARD_DECLARE_CLASS(QDomDocument);
+QT_FORWARD_DECLARE_CLASS(QDomElement);
+
+
+class QDBusModel: public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ enum Type { InterfaceItem, PathItem, MethodItem, SignalItem, PropertyItem };
+
+ QDBusModel(const QString &service, const QDBusConnection &connection);
+ ~QDBusModel();
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &child) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+
+ Type itemType(const QModelIndex &index) const;
+ QString dBusPath(const QModelIndex &index) const;
+ QString dBusInterface(const QModelIndex &index) const;
+ QString dBusMethodName(const QModelIndex &index) const;
+
+ void refresh(const QModelIndex &index = QModelIndex());
+
+ QModelIndex findObject(const QDBusObjectPath &objectPath);
+
+Q_SIGNALS:
+ void busError(const QString &text);
+
+private:
+ QDomDocument introspect(const QString &path);
+ void addMethods(QDBusItem *parent, const QDomElement &iface);
+ void addPath(QDBusItem *parent);
+
+ QString service;
+ QDBusConnection c;
+ QDBusItem *root;
+};
+
+#endif
+
diff --git a/tools/qdbus/qdbusviewer/qdbusviewer.cpp b/tools/qdbus/qdbusviewer/qdbusviewer.cpp
new file mode 100644
index 0000000000..e8ac3a688d
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/qdbusviewer.cpp
@@ -0,0 +1,509 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdbusviewer.h"
+#include "qdbusmodel.h"
+#include "propertydialog.h"
+
+#include <QtXml/QtXml>
+#include <QtDBus/private/qdbusutil_p.h>
+
+class QDBusViewModel: public QDBusModel
+{
+public:
+ inline QDBusViewModel(const QString &service, const QDBusConnection &connection)
+ : QDBusModel(service, connection)
+ {}
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
+ {
+ if (role == Qt::FontRole && itemType(index) == InterfaceItem) {
+ QFont f;
+ f.setItalic(true);
+ return f;
+ }
+ return QDBusModel::data(index, role);
+ }
+};
+
+QDBusViewer::QDBusViewer(const QDBusConnection &connection, QWidget *parent) :
+ QWidget(parent),
+ c(connection),
+ objectPathRegExp(QLatin1String("\\[ObjectPath: (.*)\\]"))
+{
+ services = new QTreeWidget;
+ services->setRootIsDecorated(false);
+ services->setHeaderLabels(QStringList(QLatin1String("Services")));
+
+ tree = new QTreeView;
+ tree->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(tree, SIGNAL(activated(const QModelIndex&)), this, SLOT(activate(const QModelIndex&)));
+
+ refreshAction = new QAction(tr("&Refresh"), tree);
+ refreshAction->setData(42); // increase the amount of 42 used as magic number by one
+ refreshAction->setShortcut(QKeySequence::Refresh);
+ connect(refreshAction, SIGNAL(triggered()), this, SLOT(refreshChildren()));
+
+ QShortcut *refreshShortcut = new QShortcut(QKeySequence::Refresh, tree);
+ connect(refreshShortcut, SIGNAL(activated()), this, SLOT(refreshChildren()));
+
+ QVBoxLayout *topLayout = new QVBoxLayout(this);
+ log = new QTextBrowser;
+ connect(log, SIGNAL(anchorClicked(QUrl)), this, SLOT(anchorClicked(QUrl)));
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(services, 1);
+ layout->addWidget(tree, 2);
+
+ topLayout->addLayout(layout);
+ topLayout->addWidget(log);
+
+ connect(services, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
+ this, SLOT(serviceChanged(QTreeWidgetItem*)));
+ connect(tree, SIGNAL(customContextMenuRequested(QPoint)),
+ this, SLOT(showContextMenu(QPoint)));
+
+ QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
+
+ if (c.isConnected()) {
+ logMessage(QLatin1String("Connected to D-Bus."));
+ QDBusConnectionInterface *iface = c.interface();
+ connect(iface, SIGNAL(serviceRegistered(QString)),
+ this, SLOT(serviceRegistered(QString)));
+ connect(iface, SIGNAL(serviceUnregistered(QString)),
+ this, SLOT(serviceUnregistered(QString)));
+ connect(iface, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
+ this, SLOT(serviceOwnerChanged(QString,QString,QString)));
+ } else {
+ logError(QLatin1String("Cannot connect to D-Bus: ") + c.lastError().message());
+ }
+
+ objectPathRegExp.setMinimal(true);
+
+}
+
+void QDBusViewer::logMessage(const QString &msg)
+{
+ log->append(msg + QLatin1Char('\n'));
+}
+
+void QDBusViewer::logError(const QString &msg)
+{
+ log->append(QLatin1String("<font color=\"red\">Error: </font>") + Qt::escape(msg) + QLatin1String("<br>"));
+}
+
+void QDBusViewer::refresh()
+{
+ services->clear();
+
+ if (c.isConnected()) {
+ const QStringList serviceNames = c.interface()->registeredServiceNames();
+ foreach (QString service, serviceNames)
+ new QTreeWidgetItem(services, QStringList(service));
+ }
+}
+
+void QDBusViewer::activate(const QModelIndex &item)
+{
+ if (!item.isValid())
+ return;
+
+ const QDBusModel *model = static_cast<const QDBusModel *>(item.model());
+
+ BusSignature sig;
+ sig.mService = currentService;
+ sig.mPath = model->dBusPath(item);
+ sig.mInterface = model->dBusInterface(item);
+ sig.mName = model->dBusMethodName(item);
+
+ switch (model->itemType(item)) {
+ case QDBusModel::SignalItem:
+ connectionRequested(sig);
+ break;
+ case QDBusModel::MethodItem:
+ callMethod(sig);
+ break;
+ case QDBusModel::PropertyItem:
+ getProperty(sig);
+ break;
+ default:
+ break;
+ }
+}
+
+void QDBusViewer::getProperty(const BusSignature &sig)
+{
+ QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get"));
+ QList<QVariant> arguments;
+ arguments << sig.mInterface << sig.mName;
+ message.setArguments(arguments);
+ c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage)));
+}
+
+void QDBusViewer::setProperty(const BusSignature &sig)
+{
+ QDBusInterface iface(sig.mService, sig.mPath, sig.mInterface, c);
+ QMetaProperty prop = iface.metaObject()->property(iface.metaObject()->indexOfProperty(sig.mName.toLatin1()));
+
+ bool ok;
+ QString input = QInputDialog::getText(this, tr("Arguments"),
+ tr("Please enter the value of the property %1 (type %2)").arg(
+ sig.mName, QString::fromLatin1(prop.typeName())),
+ QLineEdit::Normal, QString(), &ok);
+ if (!ok)
+ return;
+
+ QVariant value = input;
+ if (!value.convert(prop.type())) {
+ QMessageBox::warning(this, tr("Unable to marshall"),
+ tr("Value conversion failed, unable to set property"));
+ return;
+ }
+
+ QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Set"));
+ QList<QVariant> arguments;
+ arguments << sig.mInterface << sig.mName << qVariantFromValue(QDBusVariant(value));
+ message.setArguments(arguments);
+ c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage)));
+
+}
+
+void QDBusViewer::callMethod(const BusSignature &sig)
+{
+ QDBusInterface iface(sig.mService, sig.mPath, sig.mInterface, c);
+ const QMetaObject *mo = iface.metaObject();
+
+ // find the method
+ QMetaMethod method;
+ for (int i = 0; i < mo->methodCount(); ++i) {
+ const QString signature = QString::fromLatin1(mo->method(i).signature());
+ if (signature.startsWith(sig.mName) && signature.at(sig.mName.length()) == QLatin1Char('('))
+ method = mo->method(i);
+ }
+ if (!method.signature()) {
+ QMessageBox::warning(this, tr("Unable to find method"),
+ tr("Unable to find method %1 on path %2 in interface %3").arg(
+ sig.mName).arg(sig.mPath).arg(sig.mInterface));
+ return;
+ }
+
+ PropertyDialog dialog;
+ QList<QVariant> args;
+
+ const QList<QByteArray> paramTypes = method.parameterTypes();
+ const QList<QByteArray> paramNames = method.parameterNames();
+ QList<int> types; // remember the low-level D-Bus type
+ for (int i = 0; i < paramTypes.count(); ++i) {
+ const QByteArray paramType = paramTypes.at(i);
+ if (paramType.endsWith('&'))
+ continue; // ignore OUT parameters
+
+ QVariant::Type type = QVariant::nameToType(paramType);
+ dialog.addProperty(QString::fromLatin1(paramNames.value(i)), type);
+ types.append(QMetaType::type(paramType));
+ }
+
+ if (!types.isEmpty()) {
+ dialog.setInfo(tr("Please enter parameters for the method \"%1\"").arg(sig.mName));
+
+ if (dialog.exec() != QDialog::Accepted)
+ return;
+
+ args = dialog.values();
+ }
+
+ // Special case - convert a value to a QDBusVariant if the
+ // interface wants a variant
+ for (int i = 0; i < args.count(); ++i) {
+ if (types.at(i) == qMetaTypeId<QDBusVariant>())
+ args[i] = qVariantFromValue(QDBusVariant(args.at(i)));
+ }
+
+ QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, sig.mInterface,
+ sig.mName);
+ message.setArguments(args);
+ c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage)));
+}
+
+void QDBusViewer::showContextMenu(const QPoint &point)
+{
+ QModelIndex item = tree->indexAt(point);
+ if (!item.isValid())
+ return;
+
+ const QDBusModel *model = static_cast<const QDBusModel *>(item.model());
+
+ BusSignature sig;
+ sig.mService = currentService;
+ sig.mPath = model->dBusPath(item);
+ sig.mInterface = model->dBusInterface(item);
+ sig.mName = model->dBusMethodName(item);
+
+ QMenu menu;
+ menu.addAction(refreshAction);
+
+ switch (model->itemType(item)) {
+ case QDBusModel::SignalItem: {
+ QAction *action = new QAction(tr("&Connect"), &menu);
+ action->setData(1);
+ menu.addAction(action);
+ break; }
+ case QDBusModel::MethodItem: {
+ QAction *action = new QAction(tr("&Call"), &menu);
+ action->setData(2);
+ menu.addAction(action);
+ break; }
+ case QDBusModel::PropertyItem: {
+ QAction *actionSet = new QAction(tr("&Set value"), &menu);
+ actionSet->setData(3);
+ QAction *actionGet = new QAction(tr("&Get value"), &menu);
+ actionGet->setData(4);
+ menu.addAction(actionSet);
+ menu.addAction(actionGet);
+ break; }
+ default:
+ break;
+ }
+
+ QAction *selectedAction = menu.exec(tree->viewport()->mapToGlobal(point));
+ if (!selectedAction)
+ return;
+
+ switch (selectedAction->data().toInt()) {
+ case 1:
+ connectionRequested(sig);
+ break;
+ case 2:
+ callMethod(sig);
+ break;
+ case 3:
+ setProperty(sig);
+ break;
+ case 4:
+ getProperty(sig);
+ break;
+ }
+}
+
+void QDBusViewer::connectionRequested(const BusSignature &sig)
+{
+ if (!c.connect(sig.mService, QString(), sig.mInterface, sig.mName, this,
+ SLOT(dumpMessage(QDBusMessage)))) {
+ logError(tr("Unable to connect to service %1, path %2, interface %3, signal %4").arg(
+ sig.mService).arg(sig.mPath).arg(sig.mInterface).arg(sig.mName));
+ }
+}
+
+void QDBusViewer::dumpMessage(const QDBusMessage &message)
+{
+ QList<QVariant> args = message.arguments();
+ QString out = QLatin1String("Received ");
+
+ switch (message.type()) {
+ case QDBusMessage::SignalMessage:
+ out += QLatin1String("signal ");
+ break;
+ case QDBusMessage::ErrorMessage:
+ out += QLatin1String("error message ");
+ break;
+ case QDBusMessage::ReplyMessage:
+ out += QLatin1String("reply ");
+ break;
+ default:
+ out += QLatin1String("message ");
+ break;
+ }
+
+ out += QLatin1String("from ");
+ out += message.service();
+ if (!message.path().isEmpty())
+ out += QLatin1String(", path ") + message.path();
+ if (!message.interface().isEmpty())
+ out += QLatin1String(", interface <i>") + message.interface() + QLatin1String("</i>");
+ if (!message.member().isEmpty())
+ out += QLatin1String(", member ") + message.member();
+ out += QLatin1String("<br>");
+ if (args.isEmpty()) {
+ out += QLatin1String("&nbsp;&nbsp;(no arguments)");
+ } else {
+ out += QLatin1String("&nbsp;&nbsp;Arguments: ");
+ foreach (QVariant arg, args) {
+ QString str = Qt::escape(QDBusUtil::argumentToString(arg));
+ // turn object paths into clickable links
+ str.replace(objectPathRegExp, QLatin1String("[ObjectPath: <a href=\"qdbus://bus\\1\">\\1</a>]"));
+ out += str;
+ out += QLatin1String(", ");
+ }
+ out.chop(2);
+ }
+
+ log->append(out);
+}
+
+void QDBusViewer::serviceChanged(QTreeWidgetItem *item)
+{
+ delete tree->model();
+
+ currentService.clear();
+ if (!item)
+ return;
+ currentService = item->text(0);
+
+ tree->setModel(new QDBusViewModel(currentService, c));
+ connect(tree->model(), SIGNAL(busError(QString)), this, SLOT(logError(QString)));
+}
+
+void QDBusViewer::serviceRegistered(const QString &service)
+{
+ if (service == c.baseService())
+ return;
+
+ new QTreeWidgetItem(services, QStringList(service));
+}
+
+static QTreeWidgetItem *findItem(const QTreeWidget *services, const QString &name)
+{
+ for (int i = 0; i < services->topLevelItemCount(); ++i) {
+ if (services->topLevelItem(i)->text(0) == name)
+ return services->topLevelItem(i);
+ }
+ return 0;
+}
+
+void QDBusViewer::serviceUnregistered(const QString &name)
+{
+ delete findItem(services, name);
+}
+
+void QDBusViewer::serviceOwnerChanged(const QString &name, const QString &oldOwner,
+ const QString &newOwner)
+{
+ QTreeWidgetItem *item = findItem(services, name);
+
+ if (!item && oldOwner.isEmpty() && !newOwner.isEmpty())
+ serviceRegistered(name);
+ else if (item && !oldOwner.isEmpty() && newOwner.isEmpty())
+ delete item;
+ else if (item && !oldOwner.isEmpty() && !newOwner.isEmpty()) {
+ delete item;
+ serviceRegistered(name);
+ }
+}
+
+void QDBusViewer::refreshChildren()
+{
+ QDBusModel *model = qobject_cast<QDBusModel *>(tree->model());
+ if (!model)
+ return;
+ model->refresh(tree->currentIndex());
+}
+
+void QDBusViewer::about()
+{
+ QMessageBox box(this);
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ QString edition = tr("Open Source Edition");
+ QString info = tr("This version of Qt's D-Bus Viewer is part of the Qt Open Source Edition. "
+ "Qt is a comprehensive C++ framework for cross-platform application "
+ "development.");
+ QString moreInfo = tr("You need a commercial Qt license for development of proprietary (closed "
+ "source) applications. Please see <a href=\"http://qtsoftware.com/company/model"
+ ".html\">qtsoftware.com/company/model.html</a> for an overview of Qt licensing.");
+#else
+ QString edition;
+ QString info;
+ QString moreInfo(tr("This program is licensed to you under the terms of the "
+ "Qt Commercial License Agreement. For details, see the file LICENSE "
+ "that came with this software distribution."));
+
+#endif
+
+ box.setText(QString::fromLatin1("<center><img src=\":/trolltech/qdbusviewer/images/qdbusviewer-128.png\">"
+ "<h3>%1</h3>"
+ "<p>Version %2 %3</p></center>"
+ "<p>%4</p>"
+ "<p>%5</p>"
+ "<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>"
+ "<p>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
+ " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
+ " PARTICULAR PURPOSE.<p/>")
+ .arg(tr("D-Bus Viewer")).arg(QLatin1String(QT_VERSION_STR)).arg(edition).arg(info).arg(moreInfo));
+ box.setWindowTitle(tr("D-Bus Viewer"));
+ box.exec();
+}
+
+void QDBusViewer::anchorClicked(const QUrl &url)
+{
+ if (url.scheme() != QLatin1String("qdbus"))
+ // not ours
+ return;
+
+ // swallow the click without setting a new document
+ log->setSource(QUrl());
+
+ QDBusModel *model = qobject_cast<QDBusModel *>(tree->model());
+ if (!model)
+ return;
+
+ QModelIndex idx = model->findObject(QDBusObjectPath(url.path()));
+ if (!idx.isValid())
+ return;
+
+ tree->scrollTo(idx);
+ tree->setCurrentIndex(idx);
+}
+
+/*!
+ \page qdbusviewer.html
+ \title D-Bus Viewer
+ \keyword qdbusviewer
+
+ The Qt D-Bus Viewer is a tool that lets you introspect D-Bus objects and messages. You can
+ choose between the system bus and the session bus. Click on any service on the list
+ on the left side to see all the exported objects.
+
+ You can invoke methods by double-clicking on them. If a method takes one or more IN parameters,
+ a property editor opens.
+
+ Right-click on a signal to connect to it. All emitted signals including their parameters
+ are output in the message view on the lower side of the window.
+*/
diff --git a/tools/qdbus/qdbusviewer/qdbusviewer.h b/tools/qdbus/qdbusviewer/qdbusviewer.h
new file mode 100644
index 0000000000..75511b741a
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/qdbusviewer.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDBUSVIEWER_H
+#define QDBUSVIEWER_H
+
+#include <QtGui/QtGui>
+#include <QtDBus/QtDBus>
+
+QT_FORWARD_DECLARE_CLASS(QTreeView);
+QT_FORWARD_DECLARE_CLASS(QDomDocument);
+QT_FORWARD_DECLARE_CLASS(QDomElement);
+
+struct BusSignature
+{
+ QString mService, mPath, mInterface, mName;
+};
+
+class QDBusViewer: public QWidget
+{
+ Q_OBJECT
+public:
+ QDBusViewer(const QDBusConnection &connection, QWidget *parent = 0);
+
+public slots:
+ void refresh();
+ void about();
+
+private slots:
+ void serviceChanged(QTreeWidgetItem *item);
+ void showContextMenu(const QPoint &);
+ void connectionRequested(const BusSignature &sig);
+ void callMethod(const BusSignature &sig);
+ void getProperty(const BusSignature &sig);
+ void setProperty(const BusSignature &sig);
+ void dumpMessage(const QDBusMessage &msg);
+ void refreshChildren();
+
+ void serviceRegistered(const QString &service);
+ void serviceUnregistered(const QString &service);
+ void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
+
+ void activate(const QModelIndex &item);
+
+ void logError(const QString &msg);
+ void anchorClicked(const QUrl &url);
+
+private:
+ void logMessage(const QString &msg);
+
+ QDBusConnection c;
+ QString currentService;
+ QTreeView *tree;
+ QAction *refreshAction;
+ QTreeWidget *services;
+ QTextBrowser *log;
+ QRegExp objectPathRegExp;
+};
+
+#endif
diff --git a/tools/qdbus/qdbusviewer/qdbusviewer.pro b/tools/qdbus/qdbusviewer/qdbusviewer.pro
new file mode 100644
index 0000000000..6727691c18
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/qdbusviewer.pro
@@ -0,0 +1,30 @@
+TEMPLATE = app
+TARGET = qdbusviewer
+
+HEADERS = qdbusviewer.h \
+ qdbusmodel.h \
+ propertydialog.h
+
+SOURCES = qdbusviewer.cpp \
+ qdbusmodel.cpp \
+ propertydialog.cpp \
+ main.cpp
+
+RESOURCES += qdbusviewer.qrc
+
+DESTDIR = ../../../bin
+
+CONFIG += qdbus
+QT += xml
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+mac {
+ ICON = images/qdbusviewer.icns
+ QMAKE_INFO_PLIST = Info_mac.plist
+}
+
+win32 {
+ RC_FILE = qdbusviewer.rc
+}
diff --git a/tools/qdbus/qdbusviewer/qdbusviewer.qrc b/tools/qdbus/qdbusviewer/qdbusviewer.qrc
new file mode 100644
index 0000000000..7d592f32cc
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/qdbusviewer.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/trolltech/qdbusviewer" >
+ <file>images/qdbusviewer-128.png</file>
+ <file>images/qdbusviewer.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/qdbus/qdbusviewer/qdbusviewer.rc b/tools/qdbus/qdbusviewer/qdbusviewer.rc
new file mode 100644
index 0000000000..c4b1d60b87
--- /dev/null
+++ b/tools/qdbus/qdbusviewer/qdbusviewer.rc
@@ -0,0 +1 @@
+IDI_ICON1 ICON DISCARDABLE "images/qdbusviewer.ico"
diff --git a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp
new file mode 100644
index 0000000000..a871fe4377
--- /dev/null
+++ b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -0,0 +1,1150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qtextstream.h>
+#include <QtCore/qset.h>
+
+#include <QtDBus/QtDBus>
+#include "private/qdbusmetaobject_p.h"
+#include "private/qdbusintrospection_p.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef Q_WS_WIN
+#include <process.h>
+#endif
+
+#define PROGRAMNAME "qdbusxml2cpp"
+#define PROGRAMVERSION "0.7"
+#define PROGRAMCOPYRIGHT "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)."
+
+#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"
+
+static QString globalClassName;
+static QString parentClassName;
+static QString proxyFile;
+static QString adaptorFile;
+static QString inputFile;
+static bool skipNamespaces;
+static bool verbose;
+static bool includeMocs;
+static QString commandLine;
+static QStringList includes;
+static QStringList wantedInterfaces;
+
+static const char help[] =
+ "Usage: " PROGRAMNAME " [options...] [xml-or-xml-file] [interfaces...]\n"
+ "Produces the C++ code to implement the interfaces defined in the input file.\n"
+ "If no options are given, the code is written to the standard output.\n"
+ "\n"
+ "Options:\n"
+ " -a <filename> Write the adaptor code to <filename>\n"
+ " -c <classname> Use <classname> as the class name for the generated classes\n"
+ " -h Show this information\n"
+ " -i <filename> Add #include to the output\n"
+ " -l <classname> When generating an adaptor, use <classname> as the parent class\n"
+ " -m Generate #include \"filename.moc\" statements in the .cpp files\n"
+ " -N Don't use namespaces\n"
+ " -p <filename> Write the proxy code to <filename>\n"
+ " -v Be verbose.\n"
+ " -V Show the program version and quit.\n"
+ "\n"
+ "If the file name given to the options -a and -p does not end in .cpp or .h, the\n"
+ "program will automatically append the suffixes and produce both files.\n"
+ "You can also use a colon (:) to separate the header name from the source file\n"
+ "name, as in '-a filename_p.h:filename.cpp'.\n";
+
+static const char includeList[] =
+ "#include <QtCore/QByteArray>\n"
+ "#include <QtCore/QList>\n"
+ "#include <QtCore/QMap>\n"
+ "#include <QtCore/QString>\n"
+ "#include <QtCore/QStringList>\n"
+ "#include <QtCore/QVariant>\n";
+
+static const char forwardDeclarations[] =
+ "class QByteArray;\n"
+ "template<class T> class QList;\n"
+ "template<class Key, class Value> class QMap;\n"
+ "class QString;\n"
+ "class QStringList;\n"
+ "class QVariant;\n";
+
+static void showHelp()
+{
+ printf("%s", help);
+ exit(0);
+}
+
+static void showVersion()
+{
+ printf("%s version %s\n", PROGRAMNAME, PROGRAMVERSION);
+ printf("D-Bus binding tool for Qt\n");
+ exit(0);
+}
+
+static QString nextArg(QStringList &args, int i, char opt)
+{
+ QString arg = args.value(i);
+ if (arg.isEmpty()) {
+ printf("-%c needs at least one argument\n", opt);
+ exit(1);
+ }
+ return args.takeAt(i);
+}
+
+static void parseCmdLine(QStringList args)
+{
+ args.takeFirst();
+
+ commandLine = QLatin1String(PROGRAMNAME " ");
+ commandLine += args.join(QLatin1String(" "));
+
+ int i = 0;
+ while (i < args.count()) {
+
+ if (!args.at(i).startsWith(QLatin1Char('-'))) {
+ ++i;
+ continue;
+ }
+ QString arg = args.takeAt(i);
+
+ char c = '\0';
+ if (arg.length() == 2)
+ c = arg.at(1).toLatin1();
+ else if (arg == QLatin1String("--help"))
+ c = 'h';
+
+ switch (c) {
+ case 'a':
+ adaptorFile = nextArg(args, i, 'a');
+ break;
+
+ case 'c':
+ globalClassName = nextArg(args, i, 'c');
+ break;
+
+ case 'v':
+ verbose = true;
+ break;
+
+ case 'i':
+ includes << nextArg(args, i, 'i');
+ break;
+
+ case 'l':
+ parentClassName = nextArg(args, i, 'l');
+ break;
+
+ case 'm':
+ includeMocs = true;
+ break;
+
+ case 'N':
+ skipNamespaces = true;
+ break;
+
+ case '?':
+ case 'h':
+ showHelp();
+ break;
+
+ case 'V':
+ showVersion();
+ break;
+
+ case 'p':
+ proxyFile = nextArg(args, i, 'p');
+ break;
+
+ default:
+ printf("unknown option: '%s'\n", qPrintable(arg));
+ exit(1);
+ }
+ }
+
+ if (!args.isEmpty())
+ inputFile = args.takeFirst();
+
+ wantedInterfaces << args;
+}
+
+static QDBusIntrospection::Interfaces readInput()
+{
+ QFile input(inputFile);
+ if (inputFile.isEmpty() || inputFile == QLatin1String("-"))
+ input.open(stdin, QIODevice::ReadOnly);
+ else
+ input.open(QIODevice::ReadOnly);
+
+ QByteArray data = input.readAll();
+
+ // check if the input is already XML
+ data = data.trimmed();
+ if (data.startsWith("<!DOCTYPE ") || data.startsWith("<?xml") ||
+ data.startsWith("<node") || data.startsWith("<interface"))
+ // already XML
+ return QDBusIntrospection::parseInterfaces(QString::fromUtf8(data));
+
+ fprintf(stderr, "Cannot process input: '%s'. Stop.\n", qPrintable(inputFile));
+ exit(1);
+}
+
+static void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces)
+{
+ if (!wantedInterfaces.isEmpty()) {
+ QDBusIntrospection::Interfaces::Iterator it = interfaces.begin();
+ while (it != interfaces.end())
+ if (!wantedInterfaces.contains(it.key()))
+ it = interfaces.erase(it);
+ else
+ ++it;
+ }
+}
+
+// produce a header name from the file name
+static QString header(const QString &name)
+{
+ QStringList parts = name.split(QLatin1Char(':'));
+ QString retval = parts.first();
+
+ if (retval.isEmpty() || retval == QLatin1String("-"))
+ return retval;
+
+ if (!retval.endsWith(QLatin1String(".h")) && !retval.endsWith(QLatin1String(".cpp")) &&
+ !retval.endsWith(QLatin1String(".cc")))
+ retval.append(QLatin1String(".h"));
+
+ return retval;
+}
+
+// produce a cpp name from the file name
+static QString cpp(const QString &name)
+{
+ QStringList parts = name.split(QLatin1Char(':'));
+ QString retval = parts.last();
+
+ if (retval.isEmpty() || retval == QLatin1String("-"))
+ return retval;
+
+ if (!retval.endsWith(QLatin1String(".h")) && !retval.endsWith(QLatin1String(".cpp")) &&
+ !retval.endsWith(QLatin1String(".cc")))
+ retval.append(QLatin1String(".cpp"));
+
+ return retval;
+}
+
+// produce a moc name from the file name
+static QString moc(const QString &name)
+{
+ QString retval = header(name);
+ if (retval.isEmpty())
+ return retval;
+
+ retval.truncate(retval.length() - 1); // drop the h in .h
+ retval += QLatin1String("moc");
+ return retval;
+}
+
+static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost)
+{
+ ts << "/*" << endl
+ << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << endl
+ << " * Command line was: " << commandLine << endl
+ << " *" << endl
+ << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << endl
+ << " *" << endl
+ << " * This is an auto-generated file." << endl;
+
+ if (changesWillBeLost)
+ ts << " * Do not edit! All changes made to it will be lost." << endl;
+ else
+ ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << endl
+ << " * before re-generating it." << endl;
+
+ ts << " */" << endl
+ << endl;
+
+ return ts;
+}
+
+enum ClassType { Proxy, Adaptor };
+static QString classNameForInterface(const QString &interface, ClassType classType)
+{
+ if (!globalClassName.isEmpty())
+ return globalClassName;
+
+ QStringList parts = interface.split(QLatin1Char('.'));
+
+ QString retval;
+ if (classType == Proxy)
+ foreach (QString part, parts) {
+ part[0] = part[0].toUpper();
+ retval += part;
+ }
+ else {
+ retval = parts.last();
+ retval[0] = retval[0].toUpper();
+ }
+
+ if (classType == Proxy)
+ retval += QLatin1String("Interface");
+ else
+ retval += QLatin1String("Adaptor");
+
+ return retval;
+}
+
+static QByteArray qtTypeName(const QString &signature, const QDBusIntrospection::Annotations &annotations, int paramId = -1, const char *direction = "Out")
+{
+ int type = QDBusMetaType::signatureToType(signature.toLatin1());
+ if (type == QVariant::Invalid) {
+ QString annotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName");
+ if (paramId >= 0)
+ annotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId);
+ QString qttype = annotations.value(annotationName);
+ if (!qttype.isEmpty())
+ return qttype.toLatin1();
+
+ fprintf(stderr, "Got unknown type `%s'\n", qPrintable(signature));
+ fprintf(stderr, "You should add <annotation name=\"%s\" value=\"<type>\"/> to the XML description\n",
+ qPrintable(annotationName));
+ exit(1);
+ }
+
+ return QVariant::typeToName(QVariant::Type(type));
+}
+
+static QString nonConstRefArg(const QByteArray &arg)
+{
+ return QLatin1String(arg + " &");
+}
+
+static QString templateArg(const QByteArray &arg)
+{
+ if (!arg.endsWith('>'))
+ return QLatin1String(arg);
+
+ return QLatin1String(arg + ' ');
+}
+
+static QString constRefArg(const QByteArray &arg)
+{
+ if (!arg.startsWith('Q'))
+ return QLatin1String(arg + ' ');
+ else
+ return QString( QLatin1String("const %1 &") ).arg( QLatin1String(arg) );
+}
+
+static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs,
+ const QDBusIntrospection::Arguments &outputArgs =
+ QDBusIntrospection::Arguments())
+{
+ QStringList retval;
+ for (int i = 0; i < inputArgs.count(); ++i) {
+ const QDBusIntrospection::Argument &arg = inputArgs.at(i);
+ QString name = arg.name;
+ if (name.isEmpty())
+ name = QString( QLatin1String("in%1") ).arg(i);
+ while (retval.contains(name))
+ name += QLatin1String("_");
+ retval << name;
+ }
+ for (int i = 0; i < outputArgs.count(); ++i) {
+ const QDBusIntrospection::Argument &arg = outputArgs.at(i);
+ QString name = arg.name;
+ if (name.isEmpty())
+ name = QString( QLatin1String("out%1") ).arg(i);
+ while (retval.contains(name))
+ name += QLatin1String("_");
+ retval << name;
+ }
+ return retval;
+}
+
+static void writeArgList(QTextStream &ts, const QStringList &argNames,
+ const QDBusIntrospection::Annotations &annotations,
+ const QDBusIntrospection::Arguments &inputArgs,
+ const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments())
+{
+ // input args:
+ bool first = true;
+ int argPos = 0;
+ for (int i = 0; i < inputArgs.count(); ++i) {
+ const QDBusIntrospection::Argument &arg = inputArgs.at(i);
+ QString type = constRefArg(qtTypeName(arg.type, annotations, i, "In"));
+
+ if (!first)
+ ts << ", ";
+ ts << type << argNames.at(argPos++);
+ first = false;
+ }
+
+ argPos++;
+
+ // output args
+ // yes, starting from 1
+ for (int i = 1; i < outputArgs.count(); ++i) {
+ const QDBusIntrospection::Argument &arg = outputArgs.at(i);
+ QString name = arg.name;
+
+ if (!first)
+ ts << ", ";
+ ts << nonConstRefArg(qtTypeName(arg.type, annotations, i, "Out"))
+ << argNames.at(argPos++);
+ first = false;
+ }
+}
+
+static QString propertyGetter(const QDBusIntrospection::Property &property)
+{
+ QString getter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertyGetter"));
+ if (getter.isEmpty()) {
+ getter = property.name;
+ getter[0] = getter[0].toLower();
+ }
+ return getter;
+}
+
+static QString propertySetter(const QDBusIntrospection::Property &property)
+{
+ QString setter = property.annotations.value(QLatin1String("com.trolltech.QtDBus.propertySetter"));
+ if (setter.isEmpty()) {
+ setter = QLatin1String("set") + property.name;
+ setter[3] = setter[3].toUpper();
+ }
+ return setter;
+}
+
+static QString stringify(const QString &data)
+{
+ QString retval;
+ int i;
+ for (i = 0; i < data.length(); ++i) {
+ retval += QLatin1Char('\"');
+ for ( ; i < data.length() && data[i] != QLatin1Char('\n'); ++i)
+ if (data[i] == QLatin1Char('\"'))
+ retval += QLatin1String("\\\"");
+ else
+ retval += data[i];
+ retval += QLatin1String("\\n\"\n");
+ }
+ return retval;
+}
+
+static void openFile(const QString &fileName, QFile &file)
+{
+ if (fileName.isEmpty())
+ return;
+
+ bool isOk = false;
+ if (fileName == QLatin1String("-")) {
+ isOk = file.open(stdout, QIODevice::WriteOnly | QIODevice::Text);
+ } else {
+ file.setFileName(fileName);
+ isOk = file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
+ }
+
+ if (!isOk)
+ fprintf(stderr, "Unable to open '%s': %s\n", qPrintable(fileName),
+ qPrintable(file.errorString()));
+}
+
+static void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces)
+{
+ // open the file
+ QString headerName = header(filename);
+ QByteArray headerData;
+ QTextStream hs(&headerData);
+
+ QString cppName = cpp(filename);
+ QByteArray cppData;
+ QTextStream cs(&cppData);
+
+ // write the header:
+ writeHeader(hs, true);
+ if (cppName != headerName)
+ writeHeader(cs, false);
+
+ // include guards:
+ QString includeGuard;
+ if (!headerName.isEmpty() && headerName != QLatin1String("-")) {
+ includeGuard = headerName.toUpper().replace(QLatin1Char('.'), QLatin1Char('_'));
+ int pos = includeGuard.lastIndexOf(QLatin1Char('/'));
+ if (pos != -1)
+ includeGuard = includeGuard.mid(pos + 1);
+ } else {
+ includeGuard = QLatin1String("QDBUSXML2CPP_PROXY");
+ }
+ includeGuard = QString(QLatin1String("%1_%2"))
+ .arg(includeGuard)
+ .arg(QDateTime::currentDateTime().toTime_t());
+ hs << "#ifndef " << includeGuard << endl
+ << "#define " << includeGuard << endl
+ << endl;
+
+ // include our stuff:
+ hs << "#include <QtCore/QObject>" << endl
+ << includeList
+ << "#include <QtDBus/QtDBus>" << endl;
+
+ foreach (QString include, includes) {
+ hs << "#include \"" << include << "\"" << endl;
+ if (headerName.isEmpty())
+ cs << "#include \"" << include << "\"" << endl;
+ }
+
+ hs << endl;
+
+ if (cppName != headerName) {
+ if (!headerName.isEmpty() && headerName != QLatin1String("-"))
+ cs << "#include \"" << headerName << "\"" << endl << endl;
+ }
+
+ foreach (const QDBusIntrospection::Interface *interface, interfaces) {
+ QString className = classNameForInterface(interface->name, Proxy);
+
+ // comment:
+ hs << "/*" << endl
+ << " * Proxy class for interface " << interface->name << endl
+ << " */" << endl;
+ cs << "/*" << endl
+ << " * Implementation of interface class " << className << endl
+ << " */" << endl
+ << endl;
+
+ // class header:
+ hs << "class " << className << ": public QDBusAbstractInterface" << endl
+ << "{" << endl
+ << " Q_OBJECT" << endl;
+
+ // the interface name
+ hs << "public:" << endl
+ << " static inline const char *staticInterfaceName()" << endl
+ << " { return \"" << interface->name << "\"; }" << endl
+ << endl;
+
+ // constructors/destructors:
+ hs << "public:" << endl
+ << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);" << endl
+ << endl
+ << " ~" << className << "();" << endl
+ << endl;
+ cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << endl
+ << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << endl
+ << "{" << endl
+ << "}" << endl
+ << endl
+ << className << "::~" << className << "()" << endl
+ << "{" << endl
+ << "}" << endl
+ << endl;
+
+ // properties:
+ foreach (const QDBusIntrospection::Property &property, interface->properties) {
+ QByteArray type = qtTypeName(property.type, property.annotations);
+ QString templateType = templateArg(type);
+ QString constRefType = constRefArg(type);
+ QString getter = propertyGetter(property);
+ QString setter = propertySetter(property);
+
+ hs << " Q_PROPERTY(" << type << " " << property.name;
+
+ // getter:
+ if (property.access != QDBusIntrospection::Property::Write)
+ // it's readble
+ hs << " READ " << getter;
+
+ // setter
+ if (property.access != QDBusIntrospection::Property::Read)
+ // it's writeable
+ hs << " WRITE " << setter;
+
+ hs << ")" << endl;
+
+ // getter:
+ if (property.access != QDBusIntrospection::Property::Write) {
+ hs << " inline " << type << " " << getter << "() const" << endl;
+ if (type != "QVariant")
+ hs << " { return qvariant_cast< " << type << " >(internalPropGet(\""
+ << property.name << "\")); }" << endl;
+ else
+ hs << " { return internalPropGet(\"" << property.name << "\"); }" << endl;
+ }
+
+ // setter:
+ if (property.access != QDBusIntrospection::Property::Read) {
+ hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl
+ << " { internalPropSet(\"" << property.name
+ << "\", qVariantFromValue(value)); }" << endl;
+ }
+
+ hs << endl;
+ }
+
+ // methods:
+ hs << "public Q_SLOTS: // METHODS" << endl;
+ foreach (const QDBusIntrospection::Method &method, interface->methods) {
+ bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true");
+ bool isNoReply =
+ method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true");
+ if (isNoReply && !method.outputArgs.isEmpty()) {
+ fprintf(stderr, "warning: method %s in interface %s is marked 'no-reply' but has output arguments.\n",
+ qPrintable(method.name), qPrintable(interface->name));
+ continue;
+ }
+
+ hs << " inline "
+ << (isDeprecated ? "Q_DECL_DEPRECATED " : "");
+
+ if (isNoReply) {
+ hs << "Q_NOREPLY void ";
+ } else {
+ hs << "QDBusPendingReply<";
+ for (int i = 0; i < method.outputArgs.count(); ++i)
+ hs << (i > 0 ? ", " : "")
+ << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out"));
+ hs << "> ";
+ }
+
+ hs << method.name << "(";
+
+ QStringList argNames = makeArgNames(method.inputArgs);
+ writeArgList(hs, argNames, method.annotations, method.inputArgs);
+
+ hs << ")" << endl
+ << " {" << endl
+ << " QList<QVariant> argumentList;" << endl;
+
+ if (!method.inputArgs.isEmpty()) {
+ hs << " argumentList";
+ for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos)
+ hs << " << qVariantFromValue(" << argNames.at(argPos) << ')';
+ hs << ";" << endl;
+ }
+
+ if (isNoReply)
+ hs << " callWithArgumentList(QDBus::NoBlock, "
+ << "QLatin1String(\"" << method.name << "\"), argumentList);" << endl;
+ else
+ hs << " return asyncCallWithArgumentList(QLatin1String(\""
+ << method.name << "\"), argumentList);" << endl;
+
+ // close the function:
+ hs << " }" << endl;
+
+ if (method.outputArgs.count() > 1) {
+ // generate the old-form QDBusReply methods with multiple incoming parameters
+ hs << " inline "
+ << (isDeprecated ? "Q_DECL_DEPRECATED " : "")
+ << "QDBusReply<"
+ << templateArg(qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out")) << "> ";
+ hs << method.name << "(";
+
+ QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
+ writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
+
+ hs << ")" << endl
+ << " {" << endl
+ << " QList<QVariant> argumentList;" << endl;
+
+ int argPos = 0;
+ if (!method.inputArgs.isEmpty()) {
+ hs << " argumentList";
+ for (argPos = 0; argPos < method.inputArgs.count(); ++argPos)
+ hs << " << qVariantFromValue(" << argNames.at(argPos) << ')';
+ hs << ";" << endl;
+ }
+
+ hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, "
+ << "QLatin1String(\"" << method.name << "\"), argumentList);" << endl;
+
+ argPos++;
+ hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == "
+ << method.outputArgs.count() << ") {" << endl;
+
+ // yes, starting from 1
+ for (int i = 1; i < method.outputArgs.count(); ++i)
+ hs << " " << argNames.at(argPos++) << " = qdbus_cast<"
+ << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out"))
+ << ">(reply.arguments().at(" << i << "));" << endl;
+ hs << " }" << endl
+ << " return reply;" << endl
+ << " }" << endl;
+ }
+
+ hs << endl;
+ }
+
+ hs << "Q_SIGNALS: // SIGNALS" << endl;
+ foreach (const QDBusIntrospection::Signal &signal, interface->signals_) {
+ hs << " ";
+ if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
+ QLatin1String("true"))
+ hs << "Q_DECL_DEPRECATED ";
+
+ hs << "void " << signal.name << "(";
+
+ QStringList argNames = makeArgNames(signal.outputArgs);
+ writeArgList(hs, argNames, signal.annotations, signal.outputArgs);
+
+ hs << ");" << endl; // finished for header
+ }
+
+ // close the class:
+ hs << "};" << endl
+ << endl;
+ }
+
+ if (!skipNamespaces) {
+ QStringList last;
+ QDBusIntrospection::Interfaces::ConstIterator it = interfaces.constBegin();
+ do
+ {
+ QStringList current;
+ QString name;
+ if (it != interfaces.constEnd()) {
+ current = it->constData()->name.split(QLatin1Char('.'));
+ name = current.takeLast();
+ }
+
+ int i = 0;
+ while (i < current.count() && i < last.count() && current.at(i) == last.at(i))
+ ++i;
+
+ // i parts matched
+ // close last.arguments().count() - i namespaces:
+ for (int j = i; j < last.count(); ++j)
+ hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << endl;
+
+ // open current.arguments().count() - i namespaces
+ for (int j = i; j < current.count(); ++j)
+ hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << endl;
+
+ // add this class:
+ if (!name.isEmpty()) {
+ hs << QString(current.count() * 2, QLatin1Char(' '))
+ << "typedef ::" << classNameForInterface(it->constData()->name, Proxy)
+ << " " << name << ";" << endl;
+ }
+
+ if (it == interfaces.constEnd())
+ break;
+ ++it;
+ last = current;
+ } while (true);
+ }
+
+ // close the include guard
+ hs << "#endif" << endl;
+
+ QString mocName = moc(filename);
+ if (includeMocs && !mocName.isEmpty())
+ cs << endl
+ << "#include \"" << mocName << "\"" << endl;
+
+ cs.flush();
+ hs.flush();
+
+ QFile file;
+ openFile(headerName, file);
+ file.write(headerData);
+
+ if (headerName == cppName) {
+ file.write(cppData);
+ } else {
+ QFile cppFile;
+ openFile(cppName, cppFile);
+ cppFile.write(cppData);
+ }
+}
+
+static void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces)
+{
+ // open the file
+ QString headerName = header(filename);
+ QByteArray headerData;
+ QTextStream hs(&headerData);
+
+ QString cppName = cpp(filename);
+ QByteArray cppData;
+ QTextStream cs(&cppData);
+
+ // write the headers
+ writeHeader(hs, false);
+ if (cppName != headerName)
+ writeHeader(cs, true);
+
+ // include guards:
+ QString includeGuard;
+ if (!headerName.isEmpty() && headerName != QLatin1String("-")) {
+ includeGuard = headerName.toUpper().replace(QLatin1Char('.'), QLatin1Char('_'));
+ int pos = includeGuard.lastIndexOf(QLatin1Char('/'));
+ if (pos != -1)
+ includeGuard = includeGuard.mid(pos + 1);
+ } else {
+ includeGuard = QLatin1String("QDBUSXML2CPP_ADAPTOR");
+ }
+ includeGuard = QString(QLatin1String("%1_%2"))
+ .arg(includeGuard)
+ .arg(QDateTime::currentDateTime().toTime_t());
+ hs << "#ifndef " << includeGuard << endl
+ << "#define " << includeGuard << endl
+ << endl;
+
+ // include our stuff:
+ hs << "#include <QtCore/QObject>" << endl;
+ if (cppName == headerName)
+ hs << "#include <QtCore/QMetaObject>" << endl
+ << "#include <QtCore/QVariant>" << endl;
+ hs << "#include <QtDBus/QtDBus>" << endl;
+
+ foreach (QString include, includes) {
+ hs << "#include \"" << include << "\"" << endl;
+ if (headerName.isEmpty())
+ cs << "#include \"" << include << "\"" << endl;
+ }
+
+ if (cppName != headerName) {
+ if (!headerName.isEmpty() && headerName != QLatin1String("-"))
+ cs << "#include \"" << headerName << "\"" << endl;
+
+ cs << "#include <QtCore/QMetaObject>" << endl
+ << includeList
+ << endl;
+ hs << forwardDeclarations;
+ } else {
+ hs << includeList;
+ }
+
+ hs << endl;
+
+ QString parent = parentClassName;
+ if (parentClassName.isEmpty())
+ parent = QLatin1String("QObject");
+
+ foreach (const QDBusIntrospection::Interface *interface, interfaces) {
+ QString className = classNameForInterface(interface->name, Adaptor);
+
+ // comment:
+ hs << "/*" << endl
+ << " * Adaptor class for interface " << interface->name << endl
+ << " */" << endl;
+ cs << "/*" << endl
+ << " * Implementation of adaptor class " << className << endl
+ << " */" << endl
+ << endl;
+
+ // class header:
+ hs << "class " << className << ": public QDBusAbstractAdaptor" << endl
+ << "{" << endl
+ << " Q_OBJECT" << endl
+ << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << endl
+ << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << endl
+ << stringify(interface->introspection)
+ << " \"\")" << endl
+ << "public:" << endl
+ << " " << className << "(" << parent << " *parent);" << endl
+ << " virtual ~" << className << "();" << endl
+ << endl;
+
+ if (!parentClassName.isEmpty())
+ hs << " inline " << parent << " *parent() const" << endl
+ << " { return static_cast<" << parent << " *>(QObject::parent()); }" << endl
+ << endl;
+
+ // constructor/destructor
+ cs << className << "::" << className << "(" << parent << " *parent)" << endl
+ << " : QDBusAbstractAdaptor(parent)" << endl
+ << "{" << endl
+ << " // constructor" << endl
+ << " setAutoRelaySignals(true);" << endl
+ << "}" << endl
+ << endl
+ << className << "::~" << className << "()" << endl
+ << "{" << endl
+ << " // destructor" << endl
+ << "}" << endl
+ << endl;
+
+ hs << "public: // PROPERTIES" << endl;
+ foreach (const QDBusIntrospection::Property &property, interface->properties) {
+ QByteArray type = qtTypeName(property.type, property.annotations);
+ QString constRefType = constRefArg(type);
+ QString getter = propertyGetter(property);
+ QString setter = propertySetter(property);
+
+ hs << " Q_PROPERTY(" << type << " " << property.name;
+ if (property.access != QDBusIntrospection::Property::Write)
+ hs << " READ " << getter;
+ if (property.access != QDBusIntrospection::Property::Read)
+ hs << " WRITE " << setter;
+ hs << ")" << endl;
+
+ // getter:
+ if (property.access != QDBusIntrospection::Property::Write) {
+ hs << " " << type << " " << getter << "() const;" << endl;
+ cs << type << " "
+ << className << "::" << getter << "() const" << endl
+ << "{" << endl
+ << " // get the value of property " << property.name << endl
+ << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl
+ << "}" << endl
+ << endl;
+ }
+
+ // setter
+ if (property.access != QDBusIntrospection::Property::Read) {
+ hs << " void " << setter << "(" << constRefType << "value);" << endl;
+ cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl
+ << "{" << endl
+ << " // set the value of property " << property.name << endl
+ << " parent()->setProperty(\"" << property.name << "\", qVariantFromValue(value";
+ if (constRefType.contains(QLatin1String("QDBusVariant")))
+ cs << ".variant()";
+ cs << "));" << endl
+ << "}" << endl
+ << endl;
+ }
+
+ hs << endl;
+ }
+
+ hs << "public Q_SLOTS: // METHODS" << endl;
+ foreach (const QDBusIntrospection::Method &method, interface->methods) {
+ bool isNoReply =
+ method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true");
+ if (isNoReply && !method.outputArgs.isEmpty()) {
+ fprintf(stderr, "warning: method %s in interface %s is marked 'no-reply' but has output arguments.\n",
+ qPrintable(method.name), qPrintable(interface->name));
+ continue;
+ }
+
+ hs << " ";
+ if (method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
+ QLatin1String("true"))
+ hs << "Q_DECL_DEPRECATED ";
+
+ QByteArray returnType;
+ if (isNoReply) {
+ hs << "Q_NOREPLY void ";
+ cs << "void ";
+ } else if (method.outputArgs.isEmpty()) {
+ hs << "void ";
+ cs << "void ";
+ } else {
+ returnType = qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out");
+ hs << returnType << " ";
+ cs << returnType << " ";
+ }
+
+ QString name = method.name;
+ hs << name << "(";
+ cs << className << "::" << name << "(";
+
+ QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
+ writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
+ writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs);
+
+ hs << ");" << endl; // finished for header
+ cs << ")" << endl
+ << "{" << endl
+ << " // handle method call " << interface->name << "." << method.name << endl;
+
+ // make the call
+ bool usingInvokeMethod = false;
+ if (parentClassName.isEmpty() && method.inputArgs.count() <= 10
+ && method.outputArgs.count() <= 1)
+ usingInvokeMethod = true;
+
+ if (usingInvokeMethod) {
+ // we are using QMetaObject::invokeMethod
+ if (!returnType.isEmpty())
+ cs << " " << returnType << " " << argNames.at(method.inputArgs.count())
+ << ";" << endl;
+
+ static const char invoke[] = " QMetaObject::invokeMethod(parent(), \"";
+ cs << invoke << name << "\"";
+
+ if (!method.outputArgs.isEmpty())
+ cs << ", Q_RETURN_ARG("
+ << qtTypeName(method.outputArgs.at(0).type, method.annotations,
+ 0, "Out")
+ << ", "
+ << argNames.at(method.inputArgs.count())
+ << ")";
+
+ for (int i = 0; i < method.inputArgs.count(); ++i)
+ cs << ", Q_ARG("
+ << qtTypeName(method.inputArgs.at(i).type, method.annotations,
+ i, "In")
+ << ", "
+ << argNames.at(i)
+ << ")";
+
+ cs << ");" << endl;
+
+ if (!returnType.isEmpty())
+ cs << " return " << argNames.at(method.inputArgs.count()) << ";" << endl;
+ } else {
+ if (parentClassName.isEmpty())
+ cs << " //";
+ else
+ cs << " ";
+
+ if (!method.outputArgs.isEmpty())
+ cs << "return ";
+
+ if (parentClassName.isEmpty())
+ cs << "static_cast<YourObjectType *>(parent())->";
+ else
+ cs << "parent()->";
+ cs << name << "(";
+
+ int argPos = 0;
+ bool first = true;
+ for (int i = 0; i < method.inputArgs.count(); ++i) {
+ cs << (first ? "" : ", ") << argNames.at(argPos++);
+ first = false;
+ }
+ ++argPos; // skip retval, if any
+ for (int i = 1; i < method.outputArgs.count(); ++i) {
+ cs << (first ? "" : ", ") << argNames.at(argPos++);
+ first = false;
+ }
+
+ cs << ");" << endl;
+ }
+ cs << "}" << endl
+ << endl;
+ }
+
+ hs << "Q_SIGNALS: // SIGNALS" << endl;
+ foreach (const QDBusIntrospection::Signal &signal, interface->signals_) {
+ hs << " ";
+ if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) ==
+ QLatin1String("true"))
+ hs << "Q_DECL_DEPRECATED ";
+
+ hs << "void " << signal.name << "(";
+
+ QStringList argNames = makeArgNames(signal.outputArgs);
+ writeArgList(hs, argNames, signal.annotations, signal.outputArgs);
+
+ hs << ");" << endl; // finished for header
+ }
+
+ // close the class:
+ hs << "};" << endl
+ << endl;
+ }
+
+ // close the include guard
+ hs << "#endif" << endl;
+
+ QString mocName = moc(filename);
+ if (includeMocs && !mocName.isEmpty())
+ cs << endl
+ << "#include \"" << mocName << "\"" << endl;
+
+ cs.flush();
+ hs.flush();
+
+ QFile file;
+ openFile(headerName, file);
+ file.write(headerData);
+
+ if (headerName == cppName) {
+ file.write(cppData);
+ } else {
+ QFile cppFile;
+ openFile(cppName, cppFile);
+ cppFile.write(cppData);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ parseCmdLine(app.arguments());
+
+ QDBusIntrospection::Interfaces interfaces = readInput();
+ cleanInterfaces(interfaces);
+
+ if (!proxyFile.isEmpty() || adaptorFile.isEmpty())
+ writeProxy(proxyFile, interfaces);
+
+ if (!adaptorFile.isEmpty())
+ writeAdaptor(adaptorFile, interfaces);
+
+ return 0;
+}
+
+/*!
+ \page qdbusxml2cpp.html
+ \title QtDBus XML compiler (qdbusxml2cpp)
+ \keyword qdbusxml2cpp
+
+ The QtDBus XML compiler is a tool that can be used to parse interface descriptions and produce
+ static code representing those interfaces, which can then be used to make calls to remote
+ objects or implement said interfaces.
+
+ \c qdbusxml2dcpp has two modes of operation, that correspond to the two possible outputs it can
+ produce: the interface (proxy) class or the adaptor class. The latter consists of both a C++
+ header and a source file, which are meant to be edited and adapted to your needs.
+
+ The \c qdbusxml2dcpp tool is not meant to be run every time you compile your
+ application. Instead, it's meant to be used when developing the code or when the interface
+ changes.
+
+ The adaptor classes generated by \c qdbusxml2cpp are just a skeleton that must be completed. It
+ generates, by default, calls to slots with the same name on the object the adaptor is attached
+ to. However, you may modify those slots or the property accessor functions to suit your needs.
+*/
diff --git a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.pro b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.pro
new file mode 100644
index 0000000000..6f78c7ca3a
--- /dev/null
+++ b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.pro
@@ -0,0 +1,10 @@
+SOURCES = qdbusxml2cpp.cpp
+DESTDIR = ../../../bin
+TARGET = qdbusxml2cpp
+QT = core xml
+CONFIG += qdbus
+CONFIG -= app_bundle
+win32:CONFIG += console
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
diff --git a/tools/qdoc3/JAVATODO.txt b/tools/qdoc3/JAVATODO.txt
new file mode 100644
index 0000000000..96df4c1412
--- /dev/null
+++ b/tools/qdoc3/JAVATODO.txt
@@ -0,0 +1,28 @@
+ * index page on "O" and downwards?
+ * flag types, e.g. QTextStream::NumberFlags
+ * example references doc.trolltech.com etc.
+
+ * fix enum value table (e.g. QCoreApplication.Encoding.html)
+ * check reimplementation of interface functions (e.g. QWidget::widthMM())
+ * handle '::' in doc, e.g. in QAbstractEventDispatcher's detailed desc
+ * make sure default constructor logic doesn't interfere with default params (e.g. QAbstractEventDispatcher ctors)
+ * document default constructor provided for Java (e.g.?)
+ * document "protected QAbstractEventDispatcher(QtObject.QPrivateConstructor p)" and the like
+ * memory-managed, type
+
+ * replace QString with String, etc.
+ * nested classes
+ * enum_1
+
+ * fix stylesheet
+ * no link to class itself
+ * support \ifjava
+ * add // C++
+ * support Java-only /*! ... */ comments
+
+ * links to property names have to be fixed
+ * example: version 1 in QStyleOptionFrame
+ * example: foo -> isFoo()
+
+ * lowercase, and remove final stop, in \brief texts for variables and properties
+ * omit "see alsos" that don't work instead of showing them as broken links
diff --git a/tools/qdoc3/README.TXT b/tools/qdoc3/README.TXT
new file mode 100644
index 0000000000..4f9f9248af
--- /dev/null
+++ b/tools/qdoc3/README.TXT
@@ -0,0 +1,6 @@
+qdoc3 is the tool used to generate the Qt reference documentation.
+The source code is included as part of this package primarily to
+fulfill our GPL obligations. We highly recommend using
+Doxygen (http://www.stack.nl/~dimitri/doxygen/) for generating
+documentation for your Qt-based application.
+
diff --git a/tools/qdoc3/TODO.txt b/tools/qdoc3/TODO.txt
new file mode 100644
index 0000000000..6deeb06398
--- /dev/null
+++ b/tools/qdoc3/TODO.txt
@@ -0,0 +1,96 @@
+ * fix QWSPointerCalibrationData::devPoints and qwsServer
+ * Fix QMenu::addAction(QAction *) overload, "using" etc.
+ * fix space between two tables using <p></p>
+ * qpixmap-qt3.html; remove 8 public functions inherited from QPaintDevice
+ * \variable array
+ * Added support for parameterless macros (e.g. \macro Q_OBJECT).
+ * Made qdoc stricter regarding the data types (e.g. can't use \enum to document a typedef).
+ * Parse QT_MODULE() macro and generate proper warnings for the various editions.
+ * Fix parsing of \image following \value (e.g. qt.html).
+ * Don't turn X11 and similar names into links.
+ * Added automatic links from getters to setters and vice versa.
+ * Support \module and show which module each class is from.
+ * Use bullet list for the list of all functions, now that
+ Assistant handles these gracefully.
+ * Fix occasional crash caused by misuse of const_cast().
+ * Provide clearer error messages when resolves fail.
+
+
+
+
+CHECK:
+
+ * Identify editions
+ * Automatic \sa getter setter
+ * \macro Q_OBJECT
+
+MUST HAVES:
+
+ * resolve [gs]etters for \sa using base class
+
+ * fix \overload when one is a signal and the other a normal function
+ * use "project" for .dcf files
+ * functions.html: include the types from QtGlobal as well as the functions (whatever that means)
+
+ * nice template function/class syntax
+ * spellchecker: built-in vs. builtin
+
+ * verbose mode for functions that don't exist
+ * No links to Porting Guide sections (e.g. QStringList)
+ * link toggled(bool)
+ * autolink foo(1)
+ * handle using correctly
+ * QObject "reentrant" list: duplicates
+ * operator<< \overload
+ * \compat \overload
+ * qWarning() link
+ * operator<<() autolink
+
+ * get rid of spurious 'global' functions
+ * Make automatic links in code work
+
+ * Fix encoding bug (see Important email from Simon Hausmann)
+ * Make links to QFoo::bar().baz() work
+ * Fix automatic links in \sectionX (e.g. qt4-getting-started.html)
+ * Provide a "List of all properties" page.
+
+ * expand QObjectList -> QList<QObject *>
+ * make \macro work (?)
+ * warning for unnamed parameters in property access functions
+ * \center...\endcenter
+
+ * warning for undocumented enum values
+
+LINKS:
+
+ * explanation following nonstandard wording warning
+
+ * omit \overload in operator<< and operator>>
+ * make operator-() unary and binary independent functions (no \overload)
+ * fix \overload
+ * fix \legalese
+ * remove warning for undocumented enum item like QLocale::LastLanguage
+ * improve the \a warnings for overloads; if one overload documents a para, fine
+
+ * implement \sidebar
+
+ * implement qbook
+
+ * implement \legalesefile
+
+ * show in which module each class is
+ * list namespaces, list header files
+
+
+NICE FEATURES:
+ * implement inheritance tree for each class (as a PNG)
+ * avoid <p>...</p> in table/item cells without relying on horrible kludge
+ * prevent macros from having same name as commands
+ * be smart about enum types Foo::Bar vs. Bar when comparing functions
+ * be smart about const & non-const when comparing functions
+
+OTHER:
+ * make qdoc run faster
+ * make sure \headerfile works even if specified after \relates
+
+ * use qtstyle.css instead of inline style for each page
diff --git a/tools/qdoc3/apigenerator.cpp b/tools/qdoc3/apigenerator.cpp
new file mode 100644
index 0000000000..d998839fce
--- /dev/null
+++ b/tools/qdoc3/apigenerator.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QFile>
+
+#include "apigenerator.h"
+#include "codemarker.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+static QString indentStr(int indent)
+{
+ QString str;
+ str.fill(QLatin1Char(' '), indent * 4);
+ return str;
+}
+
+static bool lessThanName(Node *node1, Node *node2)
+{
+ return node1->name() < node2->name();
+}
+
+QString ApiGenerator::format()
+{
+ return QLatin1String("API");
+}
+
+void ApiGenerator::generateTree(const Tree *tree, CodeMarker *marker)
+{
+ QFile outFile(QLatin1String("api"));
+ outFile.open(QIODevice::WriteOnly);
+
+ out.setDevice(&outFile);
+ generateNode(tree->root(), marker);
+ out.flush();
+}
+
+void ApiGenerator::generateNode(const Node *node, CodeMarker *marker, int indent)
+{
+ if (node->access() == Node::Private)
+ return;
+
+ switch (node->type()) {
+ case Node::Namespace:
+ if (!node->name().isEmpty()) {
+ out << indentStr(indent) << "Namespace: " << node->name() << "\n";
+ ++indent;
+ }
+ break;
+ case Node::Class:
+ {
+ const ClassNode *classe = static_cast<const ClassNode *>(node);
+ out << indentStr(indent) << "Class: " << node->name();
+ foreach (const RelatedClass &baseClass, classe->baseClasses()) {
+ if (baseClass.access == Node::Public)
+ out << " inherits " << baseClass.dataTypeWithTemplateArgs;
+ }
+ out << "\n";
+ ++indent;
+ }
+ break;
+ case Node::Enum:
+ {
+ const EnumNode *enume = static_cast<const EnumNode *>(node);
+ out << indentStr(indent) << "Enum: " << node->name() << "\n";
+ ++indent;
+
+ QStringList enumNames;
+ foreach (const EnumItem &item, enume->items())
+ enumNames << item.name();
+ qSort(enumNames);
+
+ foreach (const QString &name, enumNames)
+ out << indentStr(indent) << "Enum value: " << name << "\n";
+ }
+ break;
+ case Node::Typedef:
+ out << indentStr(indent) << "Typedef: " << node->name() << "\n";
+ ++indent;
+ break;
+ case Node::Function:
+ {
+ out << indentStr(indent) << "Function: "
+ << plainCode(marker->markedUpSynopsis(node, 0, CodeMarker::Detailed)) << "\n";
+ ++indent;
+ }
+ break;
+ case Node::Property:
+ {
+ const PropertyNode *property = static_cast<const PropertyNode *>(node);
+ out << indentStr(indent) << "Property: " << property->name()
+ << " type " << property->dataType() << "\n";
+ ++indent;
+ }
+ break;
+ default:
+ ;
+ }
+
+ if (node->isInnerNode()) {
+ const InnerNode *inner = static_cast<const InnerNode *>(node);
+ NodeList nodes = inner->childNodes();
+ qSort(nodes.begin(), nodes.end(), lessThanName);
+ foreach (const Node *child, nodes)
+ generateNode(child, marker, indent);
+ }
+
+ out.flush();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/apigenerator.h b/tools/qdoc3/apigenerator.h
new file mode 100644
index 0000000000..9545faec27
--- /dev/null
+++ b/tools/qdoc3/apigenerator.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef APIGENERATOR_H
+#define APIGENERATOR_H
+
+#include <QTextStream>
+
+#include "generator.h"
+
+QT_BEGIN_NAMESPACE
+
+class ApiGenerator : public Generator
+{
+public:
+ QString format();
+ void generateTree(const Tree *tree, CodeMarker *marker);
+
+private:
+ void generateNode(const Node *node, CodeMarker *marker, int indent = 0);
+
+ QTextStream out;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/archiveextractor.cpp b/tools/qdoc3/archiveextractor.cpp
new file mode 100644
index 0000000000..b72d27ad20
--- /dev/null
+++ b/tools/qdoc3/archiveextractor.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ archiveextractor.cpp
+*/
+
+#include "archiveextractor.h"
+
+QT_BEGIN_NAMESPACE
+
+QList<ArchiveExtractor *> ArchiveExtractor::extractors;
+
+/*!
+ \class ArchiveExtractor
+
+ \brief The ArchiveExtractor class is a base class for classes that
+ know how to unpack a certain kind of archive file.
+
+ The archive extractor contains a list of the filename extensions
+ of the files that the archive extractor knows how to unpack.
+
+ It maintains a static list of all the instances of ArchiveExtractor
+ that have been created. It also has a static function for searching
+ that list to find the archive extracter for a file with a certain
+ extension.
+ */
+
+/*!
+ The constructor takes a list of filename extensions, which it
+ copies and saves internally. This archive extractor is prepended
+ to the static list.
+ */
+ArchiveExtractor::ArchiveExtractor( const QStringList& extensions )
+ : fileExts( extensions )
+{
+ extractors.prepend( this );
+}
+
+/*!
+ The destructor deletes all the filename extensions.
+ */
+ArchiveExtractor::~ArchiveExtractor()
+{
+ extractors.removeAll( this );
+}
+
+/*!
+ This function searches the static list of archive extractors
+ to find the first one that can handle \a fileName. If it finds
+ an acceptable extractor, it returns a pointer to it. Otherwise
+ it returns null.
+ */
+ArchiveExtractor*
+ArchiveExtractor::extractorForFileName( const QString& fileName )
+{
+ int dot = -1;
+ while ( (dot = fileName.indexOf(QLatin1Char('.'), dot + 1)) != -1 ) {
+ QString ext = fileName.mid( dot + 1 );
+ QList<ArchiveExtractor *>::ConstIterator e = extractors.begin();
+ while ( e != extractors.end() ) {
+ if ( (*e)->fileExtensions().contains(ext) )
+ return *e;
+ ++e;
+ }
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/archiveextractor.h b/tools/qdoc3/archiveextractor.h
new file mode 100644
index 0000000000..cfa45bde00
--- /dev/null
+++ b/tools/qdoc3/archiveextractor.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ archiveextractor.h
+*/
+
+#ifndef ARCHIVEEXTRACTOR_H
+#define ARCHIVEEXTRACTOR_H
+
+#include <qstringlist.h>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class ArchiveExtractor
+{
+public:
+ ArchiveExtractor( const QStringList& extensions );
+ virtual ~ArchiveExtractor();
+
+ virtual void extractArchive( const Location& location,
+ const QString& filePath,
+ const QString& outputDir ) = 0;
+
+ static ArchiveExtractor *extractorForFileName( const QString& fileName );
+
+protected:
+ const QStringList& fileExtensions() { return fileExts; }
+
+private:
+ QStringList fileExts;
+
+ static QList<ArchiveExtractor *> extractors;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/atom.cpp b/tools/qdoc3/atom.cpp
new file mode 100644
index 0000000000..f341862c7b
--- /dev/null
+++ b/tools/qdoc3/atom.cpp
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qregexp.h>
+#include "atom.h"
+#include "location.h"
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+QString Atom::BOLD_ ("bold");
+QString Atom::INDEX_ ("index");
+QString Atom::ITALIC_ ("italic");
+QString Atom::LINK_ ("link");
+QString Atom::PARAMETER_ ("parameter");
+QString Atom::SUBSCRIPT_ ("subscript");
+QString Atom::SUPERSCRIPT_ ("superscript");
+QString Atom::TELETYPE_ ("teletype");
+QString Atom::UNDERLINE_ ("underline");
+
+QString Atom::BULLET_ ("bullet");
+QString Atom::TAG_ ("tag");
+QString Atom::VALUE_ ("value");
+QString Atom::LOWERALPHA_ ("loweralpha");
+QString Atom::LOWERROMAN_ ("lowerroman");
+QString Atom::NUMERIC_ ("numeric");
+QString Atom::UPPERALPHA_ ("upperalpha");
+QString Atom::UPPERROMAN_ ("upperroman");
+
+/*! \class Atom
+ \brief The Atom class is the fundamental unit for representing
+ documents internally.
+
+ Atoms have a \i type and are completed by a \i string whose
+ meaning depends on the \i type. For example, the string
+ \quotation
+ \i italic text looks nicer than \bold bold text
+ \endquotation
+ is represented by the following atoms:
+ \quotation
+ (FormattingLeft, ATOM_FORMATTING_ITALIC)
+ (String, "italic")
+ (FormattingRight, ATOM_FORMATTING_ITALIC)
+ (String, " text is more attractive than ")
+ (FormattingLeft, ATOM_FORMATTING_BOLD)
+ (String, "bold")
+ (FormattingRight, ATOM_FORMATTING_BOLD)
+ (String, " text")
+ \endquotation
+
+ \also Text
+*/
+
+/*! \enum Atom::Type
+
+ \value AbstractLeft
+ \value AbstractRight
+ \value AutoLink
+ \value BaseName
+ \value BriefLeft
+ \value BriefRight
+ \value C
+ \value CaptionLeft
+ \value CaptionRight
+ \value Code
+ \value CodeBad
+ \value CodeNew
+ \value CodeOld
+ \value CodeQuoteArgument
+ \value CodeQuoteCommand
+ \value EndQmlText
+ \value FormatElse
+ \value FormatEndif
+ \value FormatIf
+ \value FootnoteLeft
+ \value FootnoteRight
+ \value FormattingLeft
+ \value FormattingRight
+ \value GeneratedList
+ \value Image
+ \value ImageText
+ \value InlineImage
+ \value LineBreak
+ \value Link
+ \value LinkNode
+ \value ListLeft
+ \value ListItemNumber
+ \value ListTagLeft
+ \value ListTagRight
+ \value ListItemLeft
+ \value ListItemRight
+ \value ListRight
+ \value Nop
+ \value ParaLeft
+ \value ParaRight
+ \value Qml
+ \value QmlText
+ \value QuotationLeft
+ \value QuotationRight
+ \value RawString
+ \value SectionLeft
+ \value SectionRight
+ \value SectionHeadingLeft
+ \value SectionHeadingRight
+ \value SidebarLeft
+ \value SidebarRight
+ \value String
+ \value TableLeft
+ \value TableRight
+ \value TableHeaderLeft
+ \value TableHeaderRight
+ \value TableRowLeft
+ \value TableRowRight
+ \value TableItemLeft
+ \value TableItemRight
+ \value TableOfContents
+ \value Target
+ \value UnhandledFormat
+ \value UnknownCommand
+*/
+
+static const struct {
+ const char *english;
+ int no;
+} atms[] = {
+ { "AbstractLeft", Atom::AbstractLeft },
+ { "AbstractRight", Atom::AbstractRight },
+ { "AutoLink", Atom::AutoLink },
+ { "BaseName", Atom::BaseName },
+ { "BriefLeft", Atom::BriefLeft },
+ { "BriefRight", Atom::BriefRight },
+ { "C", Atom::C },
+ { "CaptionLeft", Atom::CaptionLeft },
+ { "CaptionRight", Atom::CaptionRight },
+ { "Code", Atom::Code },
+ { "CodeBad", Atom::CodeBad },
+ { "CodeNew", Atom::CodeNew },
+ { "CodeOld", Atom::CodeOld },
+ { "CodeQuoteArgument", Atom::CodeQuoteArgument },
+ { "CodeQuoteCommand", Atom::CodeQuoteCommand },
+#ifdef QDOC_QML
+ { "EndQmlText", Atom::EndQmlText },
+#endif
+ { "FootnoteLeft", Atom::FootnoteLeft },
+ { "FootnoteRight", Atom::FootnoteRight },
+ { "FormatElse", Atom::FormatElse },
+ { "FormatEndif", Atom::FormatEndif },
+ { "FormatIf", Atom::FormatIf },
+ { "FormattingLeft", Atom::FormattingLeft },
+ { "FormattingRight", Atom::FormattingRight },
+ { "GeneratedList", Atom::GeneratedList },
+ { "Image", Atom::Image },
+ { "ImageText", Atom::ImageText },
+ { "InlineImage", Atom::InlineImage },
+ { "LegaleseLeft", Atom::LegaleseLeft },
+ { "LegaleseRight", Atom::LegaleseRight },
+ { "LineBreak", Atom::LineBreak },
+ { "Link", Atom::Link },
+ { "LinkNode", Atom::LinkNode },
+ { "ListLeft", Atom::ListLeft },
+ { "ListItemNumber", Atom::ListItemNumber },
+ { "ListTagLeft", Atom::ListTagLeft },
+ { "ListTagRight", Atom::ListTagRight },
+ { "ListItemLeft", Atom::ListItemLeft },
+ { "ListItemRight", Atom::ListItemRight },
+ { "ListRight", Atom::ListRight },
+ { "Nop", Atom::Nop },
+ { "ParaLeft", Atom::ParaLeft },
+ { "ParaRight", Atom::ParaRight },
+#ifdef QDOC_QML
+ { "Qml", Atom::Qml},
+ { "QmlText", Atom::QmlText },
+#endif
+ { "QuotationLeft", Atom::QuotationLeft },
+ { "QuotationRight", Atom::QuotationRight },
+ { "RawString", Atom::RawString },
+ { "SectionLeft", Atom::SectionLeft },
+ { "SectionRight", Atom::SectionRight },
+ { "SectionHeadingLeft", Atom::SectionHeadingLeft },
+ { "SectionHeadingRight", Atom::SectionHeadingRight },
+ { "SidebarLeft", Atom::SidebarLeft },
+ { "SidebarRight", Atom::SidebarRight },
+ { "SnippetCommand", Atom::SnippetCommand },
+ { "SnippetIdentifier", Atom::SnippetIdentifier },
+ { "SnippetLocation", Atom::SnippetLocation },
+ { "String", Atom::String },
+ { "TableLeft", Atom::TableLeft },
+ { "TableRight", Atom::TableRight },
+ { "TableHeaderLeft", Atom::TableHeaderLeft },
+ { "TableHeaderRight", Atom::TableHeaderRight },
+ { "TableRowLeft", Atom::TableRowLeft },
+ { "TableRowRight", Atom::TableRowRight },
+ { "TableItemLeft", Atom::TableItemLeft },
+ { "TableItemRight", Atom::TableItemRight },
+ { "TableOfContents", Atom::TableOfContents },
+ { "Target", Atom::Target },
+ { "UnhandledFormat", Atom::UnhandledFormat },
+ { "UnknownCommand", Atom::UnknownCommand },
+ { 0, 0 }
+};
+
+/*! \fn Atom::Atom( Type type, const QString& string )
+
+ Constructs an atom (\a type, \a string) outside of any atom list.
+*/
+
+/*! \fn Atom( Atom *prev, Type type, const QString& string )
+
+ Constructs an atom (\a type, \a string) that follows \a prev in \a
+ prev's atom list.
+*/
+
+/*! \fn void Atom::appendChar( QChar ch )
+
+ Appends \a ch to the string parameter of this atom.
+
+ \also string()
+*/
+
+/*! \fn void Atom::appendString( const QString& string )
+
+ Appends \a string to the string parameter of this atom.
+
+ \also string()
+*/
+
+/*! \fn void Atom::chopString()
+
+ \also string()
+*/
+
+/*! \fn Atom *Atom::next()
+ Return the next atom in the atom list.
+ \also type(), string()
+*/
+
+/*!
+ Return the next Atom in the list if it is of Type \a t.
+ Otherwise return 0.
+ */
+const Atom* Atom::next(Type t) const
+{
+ return (nxt && (nxt->type() == t)) ? nxt : 0;
+}
+
+/*!
+ Return the next Atom in the list if it is of Type \a t
+ and its string part is \a s. Otherwise return 0.
+ */
+const Atom* Atom::next(Type t, const QString& s) const
+{
+ return (nxt && (nxt->type() == t) && (nxt->string() == s)) ? nxt : 0;
+}
+
+/*! \fn const Atom *Atom::next() const
+ Return the next atom in the atom list.
+ \also type(), string()
+*/
+
+/*! \fn Type Atom::type() const
+ Return the type of this atom.
+ \also string(), next()
+*/
+
+/*!
+ Return the type of this atom as a string. Return "Invalid" if
+ type() returns an impossible value.
+
+ This is only useful for debugging.
+
+ \also type()
+*/
+QString Atom::typeString() const
+{
+ static bool deja = false;
+
+ if ( !deja ) {
+ int i = 0;
+ while ( atms[i].english != 0 ) {
+ if ( atms[i].no != i )
+ Location::internalError( tr("atom %1 missing").arg(i) );
+ i++;
+ }
+ deja = true;
+ }
+
+ int i = (int) type();
+ if ( i < 0 || i > (int) Last )
+ return QLatin1String("Invalid");
+ return QLatin1String(atms[i].english);
+}
+
+/*! \fn const QString& Atom::string() const
+
+ Returns the string parameter that together with the type
+ characterizes this atom.
+
+ \also type(), next()
+*/
+
+/*!
+ Dumps this Atom to stderr in printer friendly form.
+ */
+void Atom::dump() const
+{
+ QString str = string();
+ str.replace( "\\", "\\\\" );
+ str.replace( "\"", "\\\"" );
+ str.replace( "\n", "\\n" );
+ str.replace( QRegExp("[^\x20-\x7e]"), "?" );
+ if (!str.isEmpty())
+ str = " \"" + str + "\"";
+ fprintf(stderr,
+ " %-15s%s\n",
+ typeString().toLatin1().data(),
+ str.toLatin1().data());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/atom.h b/tools/qdoc3/atom.h
new file mode 100644
index 0000000000..178d9ed23b
--- /dev/null
+++ b/tools/qdoc3/atom.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ atom.h
+*/
+
+#ifndef ATOM_H
+#define ATOM_H
+
+#include <qstring.h>
+
+#define QDOC_QML
+
+QT_BEGIN_NAMESPACE
+
+class Atom
+{
+ public:
+ enum Type {
+ AbstractLeft,
+ AbstractRight,
+ AutoLink,
+ BaseName,
+ BriefLeft,
+ BriefRight,
+ C,
+ CaptionLeft,
+ CaptionRight,
+ Code,
+ CodeBad,
+ CodeNew,
+ CodeOld,
+ CodeQuoteArgument,
+ CodeQuoteCommand,
+#ifdef QDOC_QML
+ EndQmlText,
+#endif
+ FootnoteLeft,
+ FootnoteRight,
+ FormatElse,
+ FormatEndif,
+ FormatIf,
+ FormattingLeft,
+ FormattingRight,
+ GeneratedList,
+ Image,
+ ImageText,
+ InlineImage,
+ LegaleseLeft,
+ LegaleseRight,
+ LineBreak,
+ Link,
+ LinkNode,
+ ListLeft,
+ ListItemNumber,
+ ListTagLeft,
+ ListTagRight,
+ ListItemLeft,
+ ListItemRight,
+ ListRight,
+ Nop,
+ ParaLeft,
+ ParaRight,
+#ifdef QDOC_QML
+ Qml,
+ QmlText,
+#endif
+ QuotationLeft,
+ QuotationRight,
+ RawString,
+ SectionLeft,
+ SectionRight,
+ SectionHeadingLeft,
+ SectionHeadingRight,
+ SidebarLeft, SidebarRight,
+ SnippetCommand,
+ SnippetIdentifier,
+ SnippetLocation,
+ String,
+ TableLeft,
+ TableRight,
+ TableHeaderLeft,
+ TableHeaderRight,
+ TableRowLeft,
+ TableRowRight,
+ TableItemLeft,
+ TableItemRight,
+ TableOfContents,
+ Target,
+ UnhandledFormat,
+ UnknownCommand,
+ Last = UnknownCommand
+ };
+
+ Atom(Type type, const QString &string = "")
+ : nxt(0), typ(type), str(string) { }
+ Atom(Atom *prev, Type type, const QString &string = "")
+ : nxt(prev->nxt), typ(type), str(string) { prev->nxt = this; }
+
+ void appendChar(QChar ch) { str += ch; }
+ void appendString(const QString& string) { str += string; }
+ void chopString() { str.chop(1); }
+ void setString(const QString &string) { str = string; }
+ Atom *next() { return nxt; }
+ void setNext(Atom *newNext) { nxt = newNext; }
+
+ const Atom *next() const { return nxt; }
+ const Atom *next(Type t) const;
+ const Atom *next(Type t, const QString& s) const;
+ Type type() const { return typ; }
+ QString typeString() const;
+ const QString& string() const { return str; }
+ void dump() const;
+
+ static QString BOLD_;
+ static QString INDEX_;
+ static QString ITALIC_;
+ static QString LINK_;
+ static QString PARAMETER_;
+ static QString SUBSCRIPT_;
+ static QString SUPERSCRIPT_;
+ static QString TELETYPE_;
+ static QString UNDERLINE_;
+
+ static QString BULLET_;
+ static QString TAG_;
+ static QString VALUE_;
+ static QString LOWERALPHA_;
+ static QString LOWERROMAN_;
+ static QString NUMERIC_;
+ static QString UPPERALPHA_;
+ static QString UPPERROMAN_;
+
+ private:
+ Atom *nxt;
+ Type typ;
+ QString str;
+};
+
+#define ATOM_FORMATTING_BOLD "bold"
+#define ATOM_FORMATTING_INDEX "index"
+#define ATOM_FORMATTING_ITALIC "italic"
+#define ATOM_FORMATTING_LINK "link"
+#define ATOM_FORMATTING_PARAMETER "parameter"
+#define ATOM_FORMATTING_SUBSCRIPT "subscript"
+#define ATOM_FORMATTING_SUPERSCRIPT "superscript"
+#define ATOM_FORMATTING_TELETYPE "teletype"
+#define ATOM_FORMATTING_UNDERLINE "underline"
+
+#define ATOM_LIST_BULLET "bullet"
+#define ATOM_LIST_TAG "tag"
+#define ATOM_LIST_VALUE "value"
+#define ATOM_LIST_LOWERALPHA "loweralpha"
+#define ATOM_LIST_LOWERROMAN "lowerroman"
+#define ATOM_LIST_NUMERIC "numeric"
+#define ATOM_LIST_UPPERALPHA "upperalpha"
+#define ATOM_LIST_UPPERROMAN "upperroman"
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/bookgenerator.cpp b/tools/qdoc3/bookgenerator.cpp
new file mode 100644
index 0000000000..4e49491393
--- /dev/null
+++ b/tools/qdoc3/bookgenerator.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ bookgenerator.cpp
+*/
+
+#include "bookgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+BookGenerator::BookGenerator()
+{
+}
+
+BookGenerator::~BookGenerator()
+{
+}
+
+void BookGenerator::generateTree( const Tree *tree, CodeMarker *marker )
+{
+ Q_UNUSED( tree )
+ Q_UNUSED( marker )
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/bookgenerator.h b/tools/qdoc3/bookgenerator.h
new file mode 100644
index 0000000000..15b830e7bb
--- /dev/null
+++ b/tools/qdoc3/bookgenerator.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ bookgenerator.h
+*/
+
+#ifndef BOOKGENERATOR_H
+#define BOOKGENERATOR_H
+
+#include "generator.h"
+
+QT_BEGIN_NAMESPACE
+
+class BookGenerator : public Generator
+{
+public:
+ BookGenerator();
+ ~BookGenerator();
+
+ virtual void generateTree( const Tree *tree, CodeMarker *marker );
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/ccodeparser.cpp b/tools/qdoc3/ccodeparser.cpp
new file mode 100644
index 0000000000..d6318f5738
--- /dev/null
+++ b/tools/qdoc3/ccodeparser.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ ccodeparser.cpp
+*/
+
+#include "ccodeparser.h"
+
+QT_BEGIN_NAMESPACE
+
+CCodeParser::CCodeParser()
+{
+}
+
+CCodeParser::~CCodeParser()
+{
+}
+
+QString CCodeParser::language()
+{
+ return QLatin1String("C");
+}
+
+QString CCodeParser::headerFileNameFilter()
+{
+ return QLatin1String("*.ch *.h");
+}
+
+QString CCodeParser::sourceFileNameFilter()
+{
+ return QLatin1String("*.c");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/ccodeparser.h b/tools/qdoc3/ccodeparser.h
new file mode 100644
index 0000000000..4e1877ae80
--- /dev/null
+++ b/tools/qdoc3/ccodeparser.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ ccodeparser.h
+*/
+
+#ifndef CCODEPARSER_H
+#define CCODEPARSER_H
+
+#include "cppcodeparser.h"
+
+QT_BEGIN_NAMESPACE
+
+class CCodeParser : public CppCodeParser
+{
+public:
+ CCodeParser();
+ ~CCodeParser();
+
+ virtual QString language();
+ virtual QString headerFileNameFilter();
+ virtual QString sourceFileNameFilter();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/codechunk.cpp b/tools/qdoc3/codechunk.cpp
new file mode 100644
index 0000000000..77c2a3eb33
--- /dev/null
+++ b/tools/qdoc3/codechunk.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ codechunk.cpp
+*/
+
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include "codechunk.h"
+
+QT_BEGIN_NAMESPACE
+
+enum { Other, Alnum, Gizmo, Comma, LParen, RParen, RAngle, Colon };
+
+// entries 128 and above are Other
+static const int charCategory[256] = {
+ Other, Other, Other, Other, Other, Other, Other, Other,
+ Other, Other, Other, Other, Other, Other, Other, Other,
+ Other, Other, Other, Other, Other, Other, Other, Other,
+ Other, Other, Other, Other, Other, Other, Other, Other,
+// ! " # $ % & '
+ Other, Other, Other, Other, Other, Gizmo, Gizmo, Other,
+// ( ) * + , - . /
+ LParen, RParen, Gizmo, Gizmo, Comma, Other, Other, Gizmo,
+// 0 1 2 3 4 5 6 7
+ Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum,
+// 8 9 : ; < = > ?
+ Alnum, Alnum, Colon, Other, Other, Gizmo, RAngle, Gizmo,
+// @ A B C D E F G
+ Other, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum,
+// H I J K L M N O
+ Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum,
+// P Q R S T U V W
+ Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum,
+// X Y Z [ \ ] ^ _
+ Alnum, Alnum, Alnum, Other, Other, Other, Gizmo, Alnum,
+// ` a b c d e f g
+ Other, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum,
+// h i j k l m n o
+ Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum,
+// p q r s t u v w
+ Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum,
+// x y z { | } ~
+ Alnum, Alnum, Alnum, LParen, Gizmo, RParen, Other, Other
+};
+
+static const bool needSpace[8][8] = {
+ /* [ a + , ( ) > : */
+ /* [ */ { false, false, false, false, false, true, false, false },
+ /* a */ { false, true, true, false, false, true, false, false },
+ /* + */ { false, true, false, false, false, true, false, true },
+ /* , */ { true, true, true, true, true, true, true, true },
+ /* ( */ { true, true, true, false, true, false, true, true },
+ /* ) */ { true, true, true, false, true, true, true, true },
+ /* > */ { true, true, true, false, true, true, true, false },
+ /* : */ { false, false, true, true, true, true, true, false }
+};
+
+static int category( QChar ch )
+{
+ return charCategory[(int)ch.toLatin1()];
+}
+
+CodeChunk::CodeChunk()
+ : hotspot( -1 )
+{
+}
+
+CodeChunk::CodeChunk( const QString& str )
+ : s( str ), hotspot( -1 )
+{
+}
+
+void CodeChunk::append( const QString& lexeme )
+{
+ if ( !s.isEmpty() && !lexeme.isEmpty() ) {
+ /*
+ Should there be a space or not between the code chunk so far and the
+ new lexeme?
+ */
+ int cat1 = category(s.at(s.size() - 1));
+ int cat2 = category(lexeme[0]);
+ if ( needSpace[cat1][cat2] )
+ s += QLatin1Char( ' ' );
+ }
+ s += lexeme;
+}
+
+void CodeChunk::appendHotspot()
+{
+ /*
+ The first hotspot is the right one.
+ */
+ if ( hotspot == -1 )
+ hotspot = s.length();
+}
+
+QString CodeChunk::toString() const
+{
+ return s;
+}
+
+QStringList CodeChunk::toPath() const
+{
+ QString t = s;
+ t.remove(QRegExp(QLatin1String("<([^<>]|<([^<>]|<[^<>]*>)*>)*>")));
+ return t.split(QLatin1String("::"));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/codechunk.h b/tools/qdoc3/codechunk.h
new file mode 100644
index 0000000000..f7ac863cdd
--- /dev/null
+++ b/tools/qdoc3/codechunk.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ codechunk.h
+*/
+
+#ifndef CODECHUNK_H
+#define CODECHUNK_H
+
+#include <qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+// ### get rid of that class
+
+/*
+ The CodeChunk class represents a tiny piece of C++ code.
+
+ The class provides convertion between a list of lexemes and a string. It adds
+ spaces at the right place for consistent style. The tiny pieces of code it
+ represents are data types, enum values, and default parameter values.
+
+ Apart from the piece of code itself, there are two bits of metainformation
+ stored in CodeChunk: the base and the hotspot. The base is the part of the
+ piece that may be a hypertext link. The base of
+
+ QMap<QString, QString>
+
+ is QMap.
+
+ The hotspot is the place the variable name should be inserted in the case of a
+ variable (or parameter) declaration. The base of
+
+ char * []
+
+ is between '*' and '[]'.
+*/
+class CodeChunk
+{
+public:
+ CodeChunk();
+ CodeChunk( const QString& str );
+
+ void append( const QString& lexeme );
+ void appendHotspot();
+
+ bool isEmpty() const { return s.isEmpty(); }
+ QString toString() const;
+ QStringList toPath() const;
+ QString left() const { return s.left(hotspot == -1 ? s.length() : hotspot); }
+ QString right() const { return s.mid(hotspot == -1 ? s.length() : hotspot); }
+
+private:
+ QString s;
+ int hotspot;
+};
+
+inline bool operator==( const CodeChunk& c, const CodeChunk& d ) {
+ return c.toString() == d.toString();
+}
+
+inline bool operator!=( const CodeChunk& c, const CodeChunk& d ) {
+ return !( c == d );
+}
+
+inline bool operator<( const CodeChunk& c, const CodeChunk& d ) {
+ return c.toString() < d.toString();
+}
+
+inline bool operator>( const CodeChunk& c, const CodeChunk& d ) {
+ return d < c;
+}
+
+inline bool operator<=( const CodeChunk& c, const CodeChunk& d ) {
+ return !( c > d );
+}
+
+inline bool operator>=( const CodeChunk& c, const CodeChunk& d ) {
+ return !( c < d );
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/codemarker.cpp b/tools/qdoc3/codemarker.cpp
new file mode 100644
index 0000000000..a803281407
--- /dev/null
+++ b/tools/qdoc3/codemarker.cpp
@@ -0,0 +1,538 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QMetaObject>
+#include <QDebug>
+#include "codemarker.h"
+#include "config.h"
+#include "node.h"
+
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+QString CodeMarker::defaultLang;
+QList<CodeMarker *> CodeMarker::markers;
+
+/*!
+ When a code marker constructs itself, it puts itself into
+ the static list of code markers. All the code markers in
+ the static list get initialized in initialize(), which is
+ not called until after the qdoc configuration file has
+ been read.
+ */
+CodeMarker::CodeMarker()
+ : slow(false)
+{
+ markers.prepend(this);
+}
+
+/*!
+ When a code marker destroys itself, it removes itself from
+ the static list of code markers.
+ */
+CodeMarker::~CodeMarker()
+{
+ markers.removeAll(this);
+}
+
+/*!
+ The only thing a code market initializes is its \e{slow}
+ flag. The \e{slow} flag indicates whether the operations
+ that slow down qdoc are to be performed or not. It is
+ turned off by default.
+ */
+void CodeMarker::initializeMarker(const Config &config)
+{
+ slow = config.getBool(QLatin1String(CONFIG_SLOW));
+}
+
+/*!
+ Terminating a code marker is trivial.
+ */
+void CodeMarker::terminateMarker()
+{
+ // nothing.
+}
+
+/*!
+ All the code markers in the static list are initialized
+ here, after the qdoc configuration file has been loaded.
+ */
+void CodeMarker::initialize(const Config& config)
+{
+ defaultLang = config.getString(QLatin1String(CONFIG_LANGUAGE));
+ QList<CodeMarker *>::ConstIterator m = markers.begin();
+ while (m != markers.end()) {
+ (*m)->initializeMarker(config);
+ ++m;
+ }
+}
+
+/*!
+ All the code markers in the static list are terminated here.
+ */
+void CodeMarker::terminate()
+{
+ QList<CodeMarker *>::ConstIterator m = markers.begin();
+ while (m != markers.end()) {
+ (*m)->terminateMarker();
+ ++m;
+ }
+}
+
+CodeMarker *CodeMarker::markerForCode(const QString& code)
+{
+ CodeMarker *defaultMarker = markerForLanguage(defaultLang);
+ if (defaultMarker != 0 && defaultMarker->recognizeCode(code))
+ return defaultMarker;
+
+ QList<CodeMarker *>::ConstIterator m = markers.begin();
+ while (m != markers.end()) {
+ if ((*m)->recognizeCode(code))
+ return *m;
+ ++m;
+ }
+ return defaultMarker;
+}
+
+CodeMarker *CodeMarker::markerForFileName(const QString& fileName)
+{
+ CodeMarker *defaultMarker = markerForLanguage(defaultLang);
+ int dot = -1;
+ while ((dot = fileName.lastIndexOf(QLatin1Char('.'), dot)) != -1) {
+ QString ext = fileName.mid(dot + 1);
+ if (defaultMarker != 0 && defaultMarker->recognizeExtension(ext))
+ return defaultMarker;
+ QList<CodeMarker *>::ConstIterator m = markers.begin();
+ while (m != markers.end()) {
+ if ((*m)->recognizeExtension(ext))
+ return *m;
+ ++m;
+ }
+ --dot;
+ }
+ return defaultMarker;
+}
+
+CodeMarker *CodeMarker::markerForLanguage(const QString& lang)
+{
+ QList<CodeMarker *>::ConstIterator m = markers.begin();
+ while (m != markers.end()) {
+ if ((*m)->recognizeLanguage(lang))
+ return *m;
+ ++m;
+ }
+ return 0;
+}
+
+const Node *CodeMarker::nodeForString(const QString& string)
+{
+ if (sizeof(const Node *) == sizeof(uint)) {
+ return reinterpret_cast<const Node *>(string.toUInt());
+ } else {
+ return reinterpret_cast<const Node *>(string.toULongLong());
+ }
+}
+
+QString CodeMarker::stringForNode(const Node *node)
+{
+ if (sizeof(const Node *) == sizeof(ulong)) {
+ return QString::number(reinterpret_cast<ulong>(node));
+ } else {
+ return QString::number(reinterpret_cast<qulonglong>(node));
+ }
+}
+
+static const QString samp = QLatin1String("&amp;");
+static const QString slt = QLatin1String("&lt;");
+static const QString sgt = QLatin1String("&gt;");
+static const QString squot = QLatin1String("&quot;");
+
+QString CodeMarker::protect(const QString& str)
+{
+ int n = str.length();
+ QString marked;
+ marked.reserve(n * 2 + 30);
+ const QChar *data = str.constData();
+ for (int i = 0; i != n; ++i) {
+ switch (data[i].unicode()) {
+ case '&': marked += samp; break;
+ case '<': marked += slt; break;
+ case '>': marked += sgt; break;
+ case '"': marked += squot; break;
+ default : marked += data[i];
+ }
+ }
+ return marked;
+}
+
+QString CodeMarker::typified(const QString &string)
+{
+ QString result;
+ QString pendingWord;
+
+ for (int i = 0; i <= string.size(); ++i) {
+ QChar ch;
+ if (i != string.size())
+ ch = string.at(i);
+
+ QChar lower = ch.toLower();
+ if ((lower >= QLatin1Char('a') && lower <= QLatin1Char('z'))
+ || ch.digitValue() >= 0 || ch == QLatin1Char('_')
+ || ch == QLatin1Char(':')) {
+ pendingWord += ch;
+ } else {
+ if (!pendingWord.isEmpty()) {
+ bool isProbablyType = (pendingWord != QLatin1String("const"));
+ if (isProbablyType)
+ result += QLatin1String("<@type>");
+ result += pendingWord;
+ if (isProbablyType)
+ result += QLatin1String("</@type>");
+ }
+ pendingWord.clear();
+
+ switch (ch.unicode()) {
+ case '\0':
+ break;
+ case '&':
+ result += QLatin1String("&amp;");
+ break;
+ case '<':
+ result += QLatin1String("&lt;");
+ break;
+ case '>':
+ result += QLatin1String("&gt;");
+ break;
+ default:
+ result += ch;
+ }
+ }
+ }
+ return result;
+}
+
+QString CodeMarker::taggedNode(const Node *node)
+{
+ QString tag;
+
+ switch (node->type()) {
+ case Node::Namespace:
+ tag = QLatin1String("@namespace");
+ break;
+ case Node::Class:
+ tag = QLatin1String("@class");
+ break;
+ case Node::Enum:
+ tag = QLatin1String("@enum");
+ break;
+ case Node::Typedef:
+ tag = QLatin1String("@typedef");
+ break;
+ case Node::Function:
+ tag = QLatin1String("@function");
+ break;
+ case Node::Property:
+ tag = QLatin1String("@property");
+ break;
+ default:
+ tag = QLatin1String("@unknown");
+ }
+ return QLatin1Char('<') + tag + QLatin1Char('>') + protect(node->name())
+ + QLatin1String("</") + tag + QLatin1Char('>');
+}
+
+QString CodeMarker::linkTag(const Node *node, const QString& body)
+{
+ return QLatin1String("<@link node=\"") + stringForNode(node)
+ + QLatin1String("\">") + body + QLatin1String("</@link>");
+}
+
+QString CodeMarker::sortName(const Node *node)
+{
+ QString nodeName = node->name();
+ int numDigits = 0;
+ for (int i = nodeName.size() - 1; i > 0; --i) {
+ if (nodeName.at(i).digitValue() == -1)
+ break;
+ ++numDigits;
+ }
+
+ // we want 'qint8' to appear before 'qint16'
+ if (numDigits > 0) {
+ for (int i = 0; i < 4 - numDigits; ++i)
+ nodeName.insert(nodeName.size()-numDigits-1, QLatin1String("0"));
+ }
+
+ if (node->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+ QString sortNo;
+ if (func->metaness() == FunctionNode::Ctor) {
+ sortNo = QLatin1String("C");
+ } else if (func->metaness() == FunctionNode::Dtor) {
+ sortNo = QLatin1String("D");
+ } else {
+ if (nodeName.startsWith(QLatin1String("operator"))
+ && nodeName.length() > 8
+ && !nodeName[8].isLetterOrNumber())
+ sortNo = QLatin1String("F");
+ else
+ sortNo = QLatin1String("E");
+ }
+ return sortNo + nodeName + QLatin1Char(' ')
+ + QString::number(func->overloadNumber(), 36);
+ }
+
+ if (node->type() == Node::Class)
+ return QLatin1Char('A') + nodeName;
+
+ if (node->type() == Node::Property || node->type() == Node::Variable)
+ return QLatin1Char('E') + nodeName;
+
+ return QLatin1Char('B') + nodeName;
+}
+
+void CodeMarker::insert(FastSection &fastSection, Node *node, SynopsisStyle style, Status status)
+{
+ bool inheritedMember = (!node->relates() &&
+ (node->parent() != (const InnerNode *)fastSection.innerNode));
+ bool irrelevant = false;
+
+ if (node->access() == Node::Private) {
+ irrelevant = true;
+ } else if (node->type() == Node::Function) {
+ FunctionNode *func = (FunctionNode *) node;
+ irrelevant = (inheritedMember
+ && (func->metaness() == FunctionNode::Ctor ||
+ func->metaness() == FunctionNode::Dtor));
+ } else if (node->type() == Node::Class || node->type() == Node::Enum
+ || node->type() == Node::Typedef) {
+ irrelevant = (inheritedMember && style != SeparateList);
+ if (!irrelevant && style == Detailed && node->type() == Node::Typedef) {
+ const TypedefNode* typedeffe = static_cast<const TypedefNode*>(node);
+ if (typedeffe->associatedEnum())
+ irrelevant = true;
+ }
+ }
+
+ if (!irrelevant) {
+ if (status == Compat) {
+ irrelevant = (node->status() != Node::Compat);
+ } else if (status == Obsolete) {
+ irrelevant = (node->status() != Node::Obsolete);
+ } else {
+ irrelevant = (node->status() == Node::Compat ||
+ node->status() == Node::Obsolete);
+ }
+ }
+
+ if (!irrelevant) {
+ if (!inheritedMember || style == SeparateList) {
+ QString key = sortName(node);
+ if (!fastSection.memberMap.contains(key))
+ fastSection.memberMap.insert(key, node);
+ } else {
+ if (node->parent()->type() == Node::Class) {
+ if (fastSection.inherited.isEmpty()
+ || fastSection.inherited.last().first != node->parent()) {
+ QPair<ClassNode *, int> p((ClassNode *)node->parent(), 0);
+ fastSection.inherited.append(p);
+ }
+ fastSection.inherited.last().second++;
+ }
+ }
+ }
+}
+
+void CodeMarker::append(QList<Section>& sectionList,
+ const FastSection& fastSection)
+{
+ if (!fastSection.memberMap.isEmpty() ||
+ !fastSection.inherited.isEmpty()) {
+ Section section(fastSection.name,
+ fastSection.singularMember,
+ fastSection.pluralMember);
+ section.members = fastSection.memberMap.values();
+ section.inherited = fastSection.inherited;
+ sectionList.append(section);
+ }
+}
+
+static QString encode(const QString &string)
+{
+#if 0
+ QString result = string;
+
+ for (int i = string.size() - 1; i >= 0; --i) {
+ uint ch = string.at(i).unicode();
+ if (ch > 0xFF)
+ ch = '?';
+ if ((ch - '0') >= 10 && (ch - 'a') >= 26 && (ch - 'A') >= 26
+ && ch != '/' && ch != '(' && ch != ')' && ch != ',' && ch != '*'
+ && ch != '&' && ch != '_' && ch != '<' && ch != '>' && ch != ':'
+ && ch != '~')
+ result.replace(i, 1, QString("%") + QString("%1").arg(ch, 2, 16));
+ }
+ return result;
+#else
+ return string;
+#endif
+}
+
+QStringList CodeMarker::macRefsForNode(const Node *node)
+{
+ QString result = QLatin1String("cpp/");
+ switch (node->type()) {
+ case Node::Class:
+ {
+ const ClassNode *classe = static_cast<const ClassNode *>(node);
+#if 0
+ if (!classe->templateStuff().isEmpty()) {
+ result += QLatin1String("tmplt/");
+ } else
+#endif
+ {
+ result += QLatin1String("cl/");
+ }
+ result += macName(classe); // ### Maybe plainName?
+ }
+ break;
+ case Node::Enum:
+ {
+ QStringList stringList;
+ stringList << encode(result + QLatin1String("tag/") +
+ macName(node));
+ foreach (const QString &enumName, node->doc().enumItemNames()) {
+ // ### Write a plainEnumValue() and use it here
+ stringList << encode(result + QLatin1String("econst/") +
+ macName(node->parent(), enumName));
+ }
+ return stringList;
+ }
+ case Node::Typedef:
+ result += QLatin1String("tdef/") + macName(node);
+ break;
+ case Node::Function:
+ {
+ bool isMacro = false;
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+
+ // overloads are too clever for the Xcode documentation browser
+ if (func->isOverload())
+ return QStringList();
+
+ if (func->metaness() == FunctionNode::MacroWithParams
+ || func->metaness() == FunctionNode::MacroWithoutParams) {
+ result += QLatin1String("macro/");
+ isMacro = true;
+#if 0
+ } else if (!func->templateStuff().isEmpty()) {
+ result += QLatin1String("ftmplt/");
+#endif
+ } else if (func->isStatic()) {
+ result += QLatin1String("clm/");
+ } else if (!func->parent()->name().isEmpty()) {
+ result += QLatin1String("instm/");
+ } else {
+ result += QLatin1String("func/");
+ }
+
+ result += macName(func);
+ if (result.endsWith(QLatin1String("()")))
+ result.chop(2);
+#if 0
+ // this code is too clever for the Xcode documentation
+ // browser and/or pbhelpindexer
+ if (!isMacro) {
+ result += "/" + QLatin1String(QMetaObject::normalizedSignature(func->returnType().toLatin1().constData())) + "/(";
+ const QList<Parameter> &params = func->parameters();
+ for (int i = 0; i < params.count(); ++i) {
+ QString type = params.at(i).leftType() + params.at(i).rightType();
+ type = QLatin1String(QMetaObject::normalizedSignature(type.toLatin1().constData()));
+ if (i != 0)
+ result += ",";
+ result += type;
+ }
+ result += ")";
+ }
+#endif
+ }
+ break;
+ case Node::Variable:
+ result += QLatin1String("data/") + macName(node);
+ break;
+ case Node::Property:
+ {
+ NodeList list = static_cast<const PropertyNode*>(node)->functions();
+ QStringList stringList;
+ foreach (const Node *node, list) {
+ stringList += macRefsForNode(node);
+ }
+ return stringList;
+ }
+ case Node::Namespace:
+ case Node::Fake:
+ case Node::Target:
+ default:
+ return QStringList();
+ }
+
+ return QStringList(encode(result));
+}
+
+QString CodeMarker::macName(const Node *node, const QString &name)
+{
+ QString myName = name;
+ if (myName.isEmpty()) {
+ myName = node->name();
+ node = node->parent();
+ }
+
+ if (node->name().isEmpty()) {
+ return QLatin1Char('/') + myName;
+ } else {
+ return plainFullName(node) + QLatin1Char('/') + myName;
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/codemarker.h b/tools/qdoc3/codemarker.h
new file mode 100644
index 0000000000..2bb1f2b4eb
--- /dev/null
+++ b/tools/qdoc3/codemarker.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ codemarker.h
+*/
+
+#ifndef CODEMARKER_H
+#define CODEMARKER_H
+
+#include <qpair.h>
+
+#include "node.h"
+
+QT_BEGIN_NAMESPACE
+
+class Config;
+class Tree;
+
+struct Section
+{
+ QString name;
+ QString singularMember;
+ QString pluralMember;
+ NodeList members;
+ QList<QPair<ClassNode *, int> > inherited;
+
+ Section() { }
+ Section(const QString& name0,
+ const QString& singularMember0,
+ const QString& pluralMember0)
+ : name(name0),
+ singularMember(singularMember0),
+ pluralMember(pluralMember0) { }
+};
+
+struct FastSection
+{
+ const InnerNode *innerNode;
+ QString name;
+ QString singularMember;
+ QString pluralMember;
+ QMap<QString, Node *> memberMap;
+ QList<QPair<ClassNode *, int> > inherited;
+
+ FastSection(const InnerNode *innerNode0,
+ const QString& name0 = "",
+ const QString& singularMember0 = "member",
+ const QString& pluralMember0 = "members")
+ : innerNode(innerNode0),
+ name(name0),
+ singularMember(singularMember0),
+ pluralMember(pluralMember0) { }
+};
+
+class CodeMarker
+{
+ public:
+ enum SynopsisStyle { Summary, Detailed, SeparateList, Accessors };
+ enum Status { Compat, Obsolete, Okay };
+
+ CodeMarker();
+ virtual ~CodeMarker();
+
+ virtual void initializeMarker(const Config& config);
+ virtual void terminateMarker();
+ virtual bool recognizeCode(const QString& code) = 0;
+ virtual bool recognizeExtension(const QString& ext) = 0;
+ virtual bool recognizeLanguage(const QString& lang) = 0;
+ virtual QString plainName(const Node *node) = 0;
+ virtual QString plainFullName(const Node *node,
+ const Node *relative = 0) = 0;
+ virtual QString markedUpCode(const QString& code,
+ const Node *relative,
+ const QString& dirPath) = 0;
+ virtual QString markedUpSynopsis(const Node *node,
+ const Node *relative,
+ SynopsisStyle style) = 0;
+ virtual QString markedUpName(const Node *node) = 0;
+ virtual QString markedUpFullName(const Node *node,
+ const Node *relative = 0) = 0;
+ virtual QString markedUpEnumValue(const QString &enumValue,
+ const Node *relative) = 0;
+ virtual QString markedUpIncludes(const QStringList& includes) = 0;
+ virtual QString functionBeginRegExp(const QString& funcName) = 0;
+ virtual QString functionEndRegExp(const QString& funcName) = 0;
+ virtual QList<Section> sections(const InnerNode *inner,
+ SynopsisStyle style,
+ Status status) = 0;
+ virtual const Node *resolveTarget(const QString& target,
+ const Tree *tree,
+ const Node *relative) = 0;
+ virtual QStringList macRefsForNode(const Node *node);
+
+ static void initialize(const Config& config);
+ static void terminate();
+ static CodeMarker *markerForCode(const QString& code);
+ static CodeMarker *markerForFileName(const QString& fileName);
+ static CodeMarker *markerForLanguage(const QString& lang);
+ static const Node *nodeForString(const QString& string);
+ static QString stringForNode(const Node *node);
+
+ protected:
+ bool hurryUp() const { return !slow; }
+
+ virtual QString sortName(const Node *node);
+ QString protect(const QString &string);
+ QString typified(const QString &string);
+ QString taggedNode(const Node *node);
+ QString linkTag(const Node *node, const QString& body);
+ void insert(FastSection &fastSection,
+ Node *node,
+ SynopsisStyle style,
+ Status status);
+ void append(QList<Section>& sectionList, const FastSection& fastSection);
+
+ private:
+ QString macName(const Node *parent, const QString &name = QString());
+
+ bool slow;
+
+ static QString defaultLang;
+ static QList<CodeMarker *> markers;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/codeparser.cpp b/tools/qdoc3/codeparser.cpp
new file mode 100644
index 0000000000..9a58bc6c81
--- /dev/null
+++ b/tools/qdoc3/codeparser.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ codeparser.cpp
+*/
+
+#include <QtCore>
+#include "codeparser.h"
+#include "node.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+#define COMMAND_COMPAT Doc::alias(QLatin1String("compat"))
+#define COMMAND_DEPRECATED Doc::alias(QLatin1String("deprecated")) // ### don't document
+#define COMMAND_INGROUP Doc::alias(QLatin1String("ingroup"))
+#define COMMAND_INMODULE Doc::alias(QLatin1String("inmodule")) // ### don't document
+#define COMMAND_INTERNAL Doc::alias(QLatin1String("internal"))
+#define COMMAND_MAINCLASS Doc::alias(QLatin1String("mainclass"))
+#define COMMAND_NONREENTRANT Doc::alias(QLatin1String("nonreentrant"))
+#define COMMAND_OBSOLETE Doc::alias(QLatin1String("obsolete"))
+#define COMMAND_PRELIMINARY Doc::alias(QLatin1String("preliminary"))
+#define COMMAND_INPUBLICGROUP Doc::alias(QLatin1String("inpublicgroup"))
+#define COMMAND_REENTRANT Doc::alias(QLatin1String("reentrant"))
+#define COMMAND_SINCE Doc::alias(QLatin1String("since"))
+#define COMMAND_SUBTITLE Doc::alias(QLatin1String("subtitle"))
+#define COMMAND_THREADSAFE Doc::alias(QLatin1String("threadsafe"))
+#define COMMAND_TITLE Doc::alias(QLatin1String("title"))
+
+QList<CodeParser *> CodeParser::parsers;
+
+/*!
+ The constructor adds this code parser to the static
+ list of code parsers.
+ */
+CodeParser::CodeParser()
+{
+ parsers.prepend(this);
+}
+
+/*!
+ The destructor removes this code parser from the static
+ list of code parsers.
+ */
+CodeParser::~CodeParser()
+{
+ parsers.removeAll(this);
+}
+
+/*!
+ Initializing a code parser is trivial.
+ */
+void CodeParser::initializeParser(const Config & /* config */)
+{
+ // nothing.
+}
+
+/*!
+ Teerminating a code parser is trivial.
+ */
+void CodeParser::terminateParser()
+{
+ // nothing.
+}
+
+QString CodeParser::headerFileNameFilter()
+{
+ return sourceFileNameFilter();
+}
+
+void CodeParser::parseHeaderFile(const Location& location,
+ const QString& filePath,
+ Tree *tree)
+{
+ parseSourceFile(location, filePath, tree);
+}
+
+void CodeParser::doneParsingHeaderFiles(Tree *tree)
+{
+ doneParsingSourceFiles(tree);
+}
+
+/*!
+ All the code parsers in the static list are initialized here,
+ after the qdoc configuration variables have been set.
+ */
+void CodeParser::initialize(const Config& config)
+{
+ QList<CodeParser *>::ConstIterator p = parsers.begin();
+ while (p != parsers.end()) {
+ (*p)->initializeParser(config);
+ ++p;
+ }
+}
+
+/*!
+ All the code parsers in the static list are terminated here.
+ */
+void CodeParser::terminate()
+{
+ QList<CodeParser *>::ConstIterator p = parsers.begin();
+ while (p != parsers.end()) {
+ (*p)->terminateParser();
+ ++p;
+ }
+}
+
+CodeParser *CodeParser::parserForLanguage(const QString& language)
+{
+ QList<CodeParser *>::ConstIterator p = parsers.begin();
+ while (p != parsers.end()) {
+ if ((*p)->language() == language)
+ return *p;
+ ++p;
+ }
+ return 0;
+}
+
+/*!
+ Returns the set of strings representing the common metacommands.
+ */
+QSet<QString> CodeParser::commonMetaCommands()
+{
+ return QSet<QString>() << COMMAND_COMPAT
+ << COMMAND_DEPRECATED
+ << COMMAND_INGROUP
+ << COMMAND_INMODULE
+ << COMMAND_INTERNAL
+ << COMMAND_MAINCLASS
+ << COMMAND_NONREENTRANT
+ << COMMAND_OBSOLETE
+ << COMMAND_PRELIMINARY
+ << COMMAND_INPUBLICGROUP
+ << COMMAND_REENTRANT
+ << COMMAND_SINCE
+ << COMMAND_SUBTITLE
+ << COMMAND_THREADSAFE
+ << COMMAND_TITLE;
+}
+
+/*!
+ The topic command has been processed. Now process the other
+ metacommands that were found. These are not the text markup
+ commands.
+ */
+void CodeParser::processCommonMetaCommand(const Location &location,
+ const QString &command,
+ const QString &arg,
+ Node *node,
+ Tree *tree)
+{
+ if (command == COMMAND_COMPAT) {
+ node->setStatus(Node::Compat);
+ }
+ else if (command == COMMAND_DEPRECATED) {
+ node->setStatus(Node::Deprecated);
+ }
+ else if (command == COMMAND_INGROUP) {
+ tree->addToGroup(node, arg);
+ }
+ else if (command == COMMAND_INPUBLICGROUP) {
+ tree->addToPublicGroup(node, arg);
+ }
+ else if (command == COMMAND_INMODULE) {
+ node->setModuleName(arg);
+ }
+ else if (command == COMMAND_MAINCLASS) {
+ node->setStatus(Node::Main);
+ }
+ else if (command == COMMAND_OBSOLETE) {
+ if (node->status() != Node::Compat)
+ node->setStatus(Node::Obsolete);
+ }
+ else if (command == COMMAND_NONREENTRANT) {
+ node->setThreadSafeness(Node::NonReentrant);
+ }
+ else if (command == COMMAND_PRELIMINARY) {
+ node->setStatus(Node::Preliminary);
+ }
+ else if (command == COMMAND_INTERNAL) {
+ node->setAccess(Node::Private);
+ node->setStatus(Node::Internal);
+ }
+ else if (command == COMMAND_REENTRANT) {
+ node->setThreadSafeness(Node::Reentrant);
+ }
+ else if (command == COMMAND_SINCE) {
+ node->setSince(arg);
+ }
+ else if (command == COMMAND_SUBTITLE) {
+ if (node->type() == Node::Fake) {
+ FakeNode *fake = static_cast<FakeNode *>(node);
+ fake->setSubTitle(arg);
+ }
+ else
+ location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
+ }
+ else if (command == COMMAND_THREADSAFE) {
+ node->setThreadSafeness(Node::ThreadSafe);
+ }
+ else if (command == COMMAND_TITLE) {
+ if (node->type() == Node::Fake) {
+ FakeNode *fake = static_cast<FakeNode *>(node);
+ fake->setTitle(arg);
+#ifdef QDOC2DOX
+ /* qdoc -> doxygen.
+ I think this must be done here, because there can be multiple
+ "\externalpage" and "\title" metacommands in a single qdoc
+ comment, which means, among other things, that the "\title"
+ commands are not inserted into the metacommand map used by
+ the Doc class. I'm sure there4 is a better way to do this in
+ the DoxWriter class using the information in the FakeNode,
+ but I don't have time to figure it out right now.
+ */
+ if (DoxWriter::isDoxPass(1))
+ DoxWriter::insertTitle(fake,arg);
+#endif
+ }
+ else
+ location.warning(tr("Ignored '\\%1'").arg(COMMAND_TITLE));
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/codeparser.h b/tools/qdoc3/codeparser.h
new file mode 100644
index 0000000000..019e806bad
--- /dev/null
+++ b/tools/qdoc3/codeparser.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ codeparser.h
+*/
+
+#ifndef CODEPARSER_H
+#define CODEPARSER_H
+
+#include <QSet>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class Config;
+class Node;
+class QString;
+class Tree;
+
+class CodeParser
+{
+ public:
+ CodeParser();
+ virtual ~CodeParser();
+
+ virtual void initializeParser(const Config& config);
+ virtual void terminateParser();
+ virtual QString language() = 0;
+ virtual QString headerFileNameFilter();
+ virtual QString sourceFileNameFilter() = 0;
+ virtual void parseHeaderFile(const Location& location,
+ const QString& filePath, Tree *tree);
+ virtual void parseSourceFile(const Location& location,
+ const QString& filePath, Tree *tree) = 0;
+ virtual void doneParsingHeaderFiles(Tree *tree);
+ virtual void doneParsingSourceFiles(Tree *tree) = 0;
+
+ static void initialize(const Config& config);
+ static void terminate();
+ static CodeParser *parserForLanguage(const QString& language);
+
+ protected:
+ QSet<QString> commonMetaCommands();
+ void processCommonMetaCommand(const Location& location,
+ const QString& command, const QString& arg,
+ Node *node, Tree *tree);
+
+ private:
+ static QList<CodeParser *> parsers;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/command.cpp b/tools/qdoc3/command.cpp
new file mode 100644
index 0000000000..a82494dacb
--- /dev/null
+++ b/tools/qdoc3/command.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ command.cpp
+*/
+
+#include <QProcess>
+
+#include "command.h"
+
+QT_BEGIN_NAMESPACE
+
+void executeCommand( const Location& location, const QString& format,
+ const QStringList& args )
+{
+ QString actualCommand;
+ for ( int i = 0; i < (int) format.length(); i++ ) {
+ int ch = format[i].unicode();
+ if ( ch > 0 && ch < 8 ) {
+ actualCommand += args[ch - 1];
+ } else {
+ actualCommand += format[i];
+ }
+ }
+
+ QString toolName = actualCommand;
+ int space = toolName.indexOf( QLatin1Char(' ') );
+ if ( space != -1 )
+ toolName.truncate( space );
+
+ QProcess process;
+ process.start(QLatin1String("sh"),
+ QStringList() << QLatin1String("-c") << actualCommand );
+ process.waitForFinished();
+
+ if (process.exitCode() == 127)
+ location.fatal( tr("Couldn't launch the '%1' tool")
+ .arg(toolName),
+ tr("Make sure the tool is installed and in the"
+ " path.") );
+
+ QString errors = QString::fromLocal8Bit(process.readAllStandardError());
+ while ( errors.endsWith(QLatin1Char('\n')) )
+ errors.truncate( errors.length() - 1 );
+ if ( !errors.isEmpty() )
+ location.fatal( tr("The '%1' tool encountered some problems")
+ .arg(toolName),
+ tr("The tool was invoked like this:\n%1\n"
+ "It emitted these errors:\n%2")
+ .arg(actualCommand).arg(errors) );
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/command.h b/tools/qdoc3/command.h
new file mode 100644
index 0000000000..4b86c38ef0
--- /dev/null
+++ b/tools/qdoc3/command.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ command.h
+*/
+
+#ifndef COMMAND_H
+#define COMMAND_H
+
+#include <qstringlist.h>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+void executeCommand( const Location& location, const QString& commandFormat,
+ const QStringList& args );
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/config.cpp b/tools/qdoc3/config.cpp
new file mode 100644
index 0000000000..c8488f3b0f
--- /dev/null
+++ b/tools/qdoc3/config.cpp
@@ -0,0 +1,892 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ config.cpp
+*/
+
+#include <QtCore>
+
+#include "archiveextractor.h"
+#include "config.h"
+#include "uncompressor.h"
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ An entry on the MetaStack.
+ */
+class MetaStackEntry
+{
+public:
+ void open();
+ void close();
+
+ QStringList accum;
+ QStringList next;
+};
+
+/*
+ */
+void MetaStackEntry::open()
+{
+ next.append(QString());
+}
+
+/*
+ */
+void MetaStackEntry::close()
+{
+ accum += next;
+ next.clear();
+}
+
+/*
+ ###
+*/
+class MetaStack : private QStack<MetaStackEntry>
+{
+public:
+ MetaStack();
+
+ void process(QChar ch, const Location& location);
+ QStringList getExpanded(const Location& location);
+};
+
+MetaStack::MetaStack()
+{
+ push(MetaStackEntry());
+ top().open();
+}
+
+void MetaStack::process(QChar ch, const Location& location)
+{
+ if (ch == QLatin1Char('{')) {
+ push(MetaStackEntry());
+ top().open();
+ }
+ else if (ch == QLatin1Char('}')) {
+ if (count() == 1)
+ location.fatal(tr("Unexpected '}'"));
+
+ top().close();
+ QStringList suffixes = pop().accum;
+ QStringList prefixes = top().next;
+
+ top().next.clear();
+ QStringList::ConstIterator pre = prefixes.begin();
+ while (pre != prefixes.end()) {
+ QStringList::ConstIterator suf = suffixes.begin();
+ while (suf != suffixes.end()) {
+ top().next << (*pre + *suf);
+ ++suf;
+ }
+ ++pre;
+ }
+ }
+ else if (ch == QLatin1Char(',') && count() > 1) {
+ top().close();
+ top().open();
+ }
+ else {
+ QStringList::Iterator pre = top().next.begin();
+ while (pre != top().next.end()) {
+ *pre += ch;
+ ++pre;
+ }
+ }
+}
+
+QStringList MetaStack::getExpanded(const Location& location)
+{
+ if (count() > 1)
+ location.fatal(tr("Missing '}'"));
+
+ top().close();
+ return top().accum;
+}
+
+QT_STATIC_CONST_IMPL QString Config::dot = QLatin1String(".");
+QMap<QString, QString> Config::uncompressedFiles;
+QMap<QString, QString> Config::extractedDirs;
+int Config::numInstances;
+
+/*!
+ \class Config
+ \brief The Config class contains the configuration variables
+ for controlling how qdoc produces documentation.
+
+ Its load() function, reads, parses, and processes a qdocconf file.
+ */
+
+/*!
+ The constructor sets the \a programName and initializes all
+ internal state variables to empty values.
+ */
+Config::Config(const QString& programName)
+ : prog(programName)
+{
+ loc = Location::null;
+ lastLoc = Location::null;
+ locMap.clear();
+ stringValueMap.clear();
+ stringListValueMap.clear();
+ numInstances++;
+}
+
+/*!
+ The destructor deletes all the temporary files and
+ directories it built.
+ */
+Config::~Config()
+{
+ if (--numInstances == 0) {
+ QMap<QString, QString>::ConstIterator f = uncompressedFiles.begin();
+ while (f != uncompressedFiles.end()) {
+ QDir().remove(*f);
+ ++f;
+ }
+ uncompressedFiles.clear();
+
+ QMap<QString, QString>::ConstIterator d = extractedDirs.begin();
+ while (d != extractedDirs.end()) {
+ removeDirContents(*d);
+ QDir dir(*d);
+ QString name = dir.dirName();
+ dir.cdUp();
+ dir.rmdir(name);
+ ++d;
+ }
+ extractedDirs.clear();
+ }
+}
+
+/*!
+ Loads and parses the qdoc configuration file \a fileName.
+ This function calls the other load() function, which does
+ the loading, parsing, and processing of the configuration
+ file.
+
+ Intializes the location variables returned by location()
+ and lastLocation().
+ */
+void Config::load(const QString& fileName)
+{
+ load(Location::null, fileName);
+ if (loc.isEmpty()) {
+ loc = Location(fileName);
+ }
+ else {
+ loc.setEtc(true);
+ }
+ lastLoc = Location::null;
+}
+
+/*!
+ Joins all the strings in \a values into a single string with the
+ individual \a values separated by ' '. Then it inserts the result
+ into the string list map with \a var as the key.
+
+ It also inserts the \a values string list into a separate map,
+ also with \a var as the key.
+ */
+void Config::setStringList(const QString& var, const QStringList& values)
+{
+ stringValueMap[var] = values.join(QLatin1String(" "));
+ stringListValueMap[var] = values;
+}
+
+/*!
+ Looks up the configuarion variable \a var in the string
+ map and returns the boolean value.
+ */
+bool Config::getBool(const QString& var) const
+{
+ return QVariant(getString(var)).toBool();
+}
+
+/*!
+ Looks up the configuration variable \a var in the string list
+ map. Iterates through the string list found, interpreting each
+ string in the list as an integer and adding it to a total sum.
+ Returns the sum.
+ */
+int Config::getInt(const QString& var) const
+{
+ QStringList strs = getStringList(var);
+ QStringList::ConstIterator s = strs.begin();
+ int sum = 0;
+
+ while (s != strs.end()) {
+ sum += (*s).toInt();
+ ++s;
+ }
+ return sum;
+}
+
+/*!
+ First, this function looks up the configuration variable \a var
+ in the location map and, if found, sets the internal variable
+ \c{lastLoc} to the Location that \a var maps to.
+
+ Then it looks up the configuration variable \a var in the string
+ map, and returns the string that \a var maps to.
+ */
+QString Config::getString(const QString& var) const
+{
+ if (!locMap[var].isEmpty())
+ (Location&) lastLoc = locMap[var];
+ return stringValueMap[var];
+}
+
+/*!
+ Looks up the configuration variable \a var in the string
+ list map, converts the string list it maps to into a set
+ of strings, and returns the set.
+ */
+QSet<QString> Config::getStringSet(const QString& var) const
+{
+ return QSet<QString>::fromList(getStringList(var));
+}
+
+/*!
+ First, this function looks up the configuration variable \a var
+ in the location map and, if found, sets the internal variable
+ \c{lastLoc} the Location that \a var maps to.
+
+ Then it looks up the configuration variable \a var in the string
+ list map, and returns the string list that \a var maps to.
+ */
+QStringList Config::getStringList(const QString& var) const
+{
+ if (!locMap[var].isEmpty())
+ (Location&) lastLoc = locMap[var];
+ return stringListValueMap[var];
+}
+
+/*!
+ Calls getRegExpList() with the control variable \a var and
+ iterates through the resulting list of regular expressions,
+ concatening them with some extras characters to form a single
+ QRegExp, which is returned/
+
+ \sa getRegExpList()
+ */
+QRegExp Config::getRegExp(const QString& var) const
+{
+ QString pattern;
+ QList<QRegExp> subRegExps = getRegExpList(var);
+ QList<QRegExp>::ConstIterator s = subRegExps.begin();
+
+ while (s != subRegExps.end()) {
+ if (!(*s).isValid())
+ return *s;
+ if (!pattern.isEmpty())
+ pattern += QLatin1Char('|');
+ pattern += QLatin1String("(?:") + (*s).pattern() + QLatin1Char(')');
+ ++s;
+ }
+ if (pattern.isEmpty())
+ pattern = QLatin1String("$x"); // cannot match
+ return QRegExp(pattern);
+}
+
+/*!
+ Looks up the configuration variable \a var in the string list
+ map, converts the string list to a list of regular expressions,
+ and returns it.
+ */
+QList<QRegExp> Config::getRegExpList(const QString& var) const
+{
+ QStringList strs = getStringList(var);
+ QStringList::ConstIterator s = strs.begin();
+ QList<QRegExp> regExps;
+
+ while (s != strs.end()) {
+ regExps += QRegExp(*s);
+ ++s;
+ }
+ return regExps;
+}
+
+/*!
+ This function is slower than it could be.
+ */
+QSet<QString> Config::subVars(const QString& var) const
+{
+ QSet<QString> result;
+ QString varDot = var + QLatin1Char('.');
+ QMap<QString, QString>::ConstIterator v = stringValueMap.begin();
+ while (v != stringValueMap.end()) {
+ if (v.key().startsWith(varDot)) {
+ QString subVar = v.key().mid(varDot.length());
+ int dot = subVar.indexOf(QLatin1Char('.'));
+ if (dot != -1)
+ subVar.truncate(dot);
+ result.insert(subVar);
+ }
+ ++v;
+ }
+ return result;
+}
+
+/*!
+ Builds and returns a list of file pathnames for the file
+ type specified by \a filesVar (e.g. "headers" or "sources").
+ The files are found in the directories specified by
+ \a dirsVar, and they are filtered by \a defaultNameFilter
+ if a better filter can't be constructed from \a filesVar.
+ The directories in \a excludedDirs are avoided.
+ */
+QStringList Config::getAllFiles(const QString &filesVar,
+ const QString &dirsVar,
+ const QString &defaultNameFilter,
+ const QSet<QString> &excludedDirs)
+{
+ QStringList result = getStringList(filesVar);
+ QStringList dirs = getStringList(dirsVar);
+
+ QString nameFilter = getString(filesVar + dot +
+ QLatin1String(CONFIG_FILEEXTENSIONS));
+ if (nameFilter.isEmpty())
+ nameFilter = defaultNameFilter;
+
+ QStringList::ConstIterator d = dirs.begin();
+ while (d != dirs.end()) {
+ result += getFilesHere(*d, nameFilter, excludedDirs);
+ ++d;
+ }
+ return result;
+}
+
+/*!
+ */
+QString Config::findFile(const Location& location,
+ const QStringList& files,
+ const QStringList& dirs,
+ const QString& fileName,
+ QString& userFriendlyFilePath)
+{
+ if (fileName.isEmpty() || fileName.startsWith(QLatin1Char('/'))) {
+ userFriendlyFilePath = fileName;
+ return fileName;
+ }
+
+ QFileInfo fileInfo;
+ QStringList components = fileName.split(QLatin1Char('?'));
+ QString firstComponent = components.first();
+
+ QStringList::ConstIterator f = files.begin();
+ while (f != files.end()) {
+ if (*f == firstComponent ||
+ (*f).endsWith(QLatin1Char('/') + firstComponent)) {
+ fileInfo.setFile(*f);
+ if (!fileInfo.exists())
+ location.fatal(tr("File '%1' does not exist").arg(*f));
+ break;
+ }
+ ++f;
+ }
+
+ if (fileInfo.fileName().isEmpty()) {
+ QStringList::ConstIterator d = dirs.begin();
+ while (d != dirs.end()) {
+ fileInfo.setFile(QDir(*d), firstComponent);
+ if (fileInfo.exists()) {
+ break;
+ }
+ ++d;
+ }
+ }
+
+ userFriendlyFilePath = QString();
+ if (!fileInfo.exists())
+ return QString();
+
+ QStringList::ConstIterator c = components.begin();
+ for (;;) {
+ bool isArchive = (c != components.end() - 1);
+ ArchiveExtractor *extractor = 0;
+ QString userFriendly = *c;
+
+ if (isArchive) {
+ extractor = ArchiveExtractor::extractorForFileName(userFriendly);
+ }
+
+ if (extractor == 0) {
+ Uncompressor *uncompressor =
+ Uncompressor::uncompressorForFileName(userFriendly);
+ if (uncompressor != 0) {
+ QString fileNameWithCorrectExtension =
+ uncompressor->uncompressedFilePath(
+ fileInfo.filePath());
+ QString uncompressed = uncompressedFiles[fileInfo.filePath()];
+ if (uncompressed.isEmpty()) {
+ uncompressed =
+ QTemporaryFile(fileInfo.filePath()).fileName();
+ uncompressor->uncompressFile(location,
+ fileInfo.filePath(),
+ uncompressed);
+ uncompressedFiles[fileInfo.filePath()] = uncompressed;
+ }
+ fileInfo.setFile(uncompressed);
+
+ if (isArchive) {
+ extractor = ArchiveExtractor::extractorForFileName(
+ fileNameWithCorrectExtension);
+ }
+ else {
+ userFriendly = fileNameWithCorrectExtension;
+ }
+ }
+ }
+ userFriendlyFilePath += userFriendly;
+
+ if (isArchive) {
+ if (extractor == 0)
+ location.fatal(tr("Unknown archive type '%1'")
+ .arg(userFriendlyFilePath));
+ QString extracted = extractedDirs[fileInfo.filePath()];
+ if (extracted.isEmpty()) {
+ extracted = QTemporaryFile(fileInfo.filePath()).fileName();
+ if (!QDir().mkdir(extracted))
+ location.fatal(tr("Cannot create temporary directory '%1'")
+ .arg(extracted));
+ extractor->extractArchive(location, fileInfo.filePath(),
+ extracted);
+ extractedDirs[fileInfo.filePath()] = extracted;
+ }
+ ++c;
+ fileInfo.setFile(QDir(extracted), *c);
+ }
+ else {
+ break;
+ }
+ userFriendlyFilePath += "?";
+ }
+ return fileInfo.filePath();
+}
+
+/*!
+ */
+QString Config::findFile(const Location& location,
+ const QStringList& files,
+ const QStringList& dirs,
+ const QString& fileBase,
+ const QStringList& fileExtensions,
+ QString& userFriendlyFilePath)
+{
+ QStringList::ConstIterator e = fileExtensions.begin();
+ while (e != fileExtensions.end()) {
+ QString filePath = findFile(location, files, dirs, fileBase + "." + *e,
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ return filePath;
+ ++e;
+ }
+ return findFile(location, files, dirs, fileBase, userFriendlyFilePath);
+}
+
+/*!
+ */
+QString Config::copyFile(const Location& location,
+ const QString& sourceFilePath,
+ const QString& userFriendlySourceFilePath,
+ const QString& targetDirPath)
+{
+ QFile inFile(sourceFilePath);
+ if (!inFile.open(QFile::ReadOnly)) {
+ location.fatal(tr("Cannot open input file '%1': %2")
+ .arg(inFile.fileName()).arg(inFile.errorString()));
+ return "";
+ }
+
+ QString outFileName = userFriendlySourceFilePath;
+ int slash = outFileName.lastIndexOf("/");
+ if (slash != -1)
+ outFileName = outFileName.mid(slash);
+
+ QFile outFile(targetDirPath + "/" + outFileName);
+ if (!outFile.open(QFile::WriteOnly)) {
+ location.fatal(tr("Cannot open output file '%1': %2")
+ .arg(outFile.fileName()).arg(outFile.errorString()));
+ return "";
+ }
+
+ char buffer[1024];
+ int len;
+ while ((len = inFile.read(buffer, sizeof(buffer))) > 0) {
+ outFile.write(buffer, len);
+ }
+ return outFileName;
+}
+
+/*!
+ Finds the largest unicode digit in \a value in the range
+ 1..7 and returns it.
+ */
+int Config::numParams(const QString& value)
+{
+ int max = 0;
+ for (int i = 0; i != value.length(); i++) {
+ uint c = value[i].unicode();
+ if (c > 0 && c < 8)
+ max = qMax(max, (int)c);
+ }
+ return max;
+}
+
+/*!
+ Removes everything from \a dir. This function is recursive.
+ It doesn't remove \a dir itself, but if it was called
+ recursively, then the caller will remove \a dir.
+ */
+bool Config::removeDirContents(const QString& dir)
+{
+ QDir dirInfo(dir);
+ QFileInfoList entries = dirInfo.entryInfoList();
+
+ bool ok = true;
+
+ QFileInfoList::Iterator it = entries.begin();
+ while (it != entries.end()) {
+ if ((*it).isFile()) {
+ if (!dirInfo.remove((*it).fileName()))
+ ok = false;
+ }
+ else if ((*it).isDir()) {
+ if ((*it).fileName() != "." && (*it).fileName() != "..") {
+ if (removeDirContents((*it).absoluteFilePath())) {
+ if (!dirInfo.rmdir((*it).fileName()))
+ ok = false;
+ }
+ else {
+ ok = false;
+ }
+ }
+ }
+ ++it;
+ }
+ return ok;
+}
+
+/*!
+ Returns true if \a ch is a letter, number, '_', '.',
+ '{', '}', or ','.
+ */
+bool Config::isMetaKeyChar(QChar ch)
+{
+ return ch.isLetterOrNumber()
+ || ch == QLatin1Char('_')
+ || ch == QLatin1Char('.')
+ || ch == QLatin1Char('{')
+ || ch == QLatin1Char('}')
+ || ch == QLatin1Char(',');
+}
+
+/*!
+ Load, parse, and process a qdoc configuration file. This
+ function is only called by the other load() function, but
+ this one is recursive, i.e., it calls itself when it sees
+ an \c{include} statement in the qdog configuration file.
+ */
+void Config::load(Location location, const QString& fileName)
+{
+ QRegExp keySyntax("\\w+(?:\\.\\w+)*");
+
+#define SKIP_CHAR() \
+ do { \
+ location.advance(c); \
+ ++i; \
+ c = text.at(i); \
+ cc = c.unicode(); \
+ } while (0)
+
+#define SKIP_SPACES() \
+ while (c.isSpace() && cc != '\n') \
+ SKIP_CHAR()
+
+#define PUT_CHAR() \
+ word += c; \
+ SKIP_CHAR();
+
+ if (location.depth() > 16)
+ location.fatal(tr("Too many nested includes"));
+
+ QFile fin(fileName);
+ if (!fin.open(QFile::ReadOnly | QFile::Text)) {
+ fin.setFileName(fileName + ".qdoc");
+ if (!fin.open(QFile::ReadOnly | QFile::Text))
+ location.fatal(tr("Cannot open file '%1': %2").arg(fileName).arg(fin.errorString()));
+ }
+
+ QString text = fin.readAll();
+ text += QLatin1String("\n\n");
+ text += QChar('\0');
+ fin.close();
+
+ location.push(fileName);
+ location.start();
+
+ int i = 0;
+ QChar c = text.at(0);
+ uint cc = c.unicode();
+ while (i < (int) text.length()) {
+ if (cc == 0)
+ ++i;
+ else if (c.isSpace()) {
+ SKIP_CHAR();
+ }
+ else if (cc == '#') {
+ do {
+ SKIP_CHAR();
+ } while (cc != '\n');
+ }
+ else if (isMetaKeyChar(c)) {
+ Location keyLoc = location;
+ bool plus = false;
+ QString stringValue;
+ QStringList stringListValue;
+ QString word;
+ bool inQuote = false;
+ bool prevWordQuoted = true;
+ bool metWord = false;
+
+ MetaStack stack;
+ do {
+ stack.process(c, location);
+ SKIP_CHAR();
+ } while (isMetaKeyChar(c));
+
+ QStringList keys = stack.getExpanded(location);
+ SKIP_SPACES();
+
+ if (keys.count() == 1 && keys.first() == "include") {
+ QString includeFile;
+
+ if (cc != '(')
+ location.fatal(tr("Bad include syntax"));
+ SKIP_CHAR();
+ SKIP_SPACES();
+ while (!c.isSpace() && cc != '#' && cc != ')') {
+ includeFile += c;
+ SKIP_CHAR();
+ }
+ SKIP_SPACES();
+ if (cc != ')')
+ location.fatal(tr("Bad include syntax"));
+ SKIP_CHAR();
+ SKIP_SPACES();
+ if (cc != '#' && cc != '\n')
+ location.fatal(tr("Trailing garbage"));
+
+ /*
+ Here is the recursive call.
+ */
+ load(location,
+ QFileInfo(QFileInfo(fileName).dir(), includeFile)
+ .filePath());
+ }
+ else {
+ /*
+ It wasn't an include statement, so it;s something else.
+ */
+ if (cc == '+') {
+ plus = true;
+ SKIP_CHAR();
+ }
+ if (cc != '=')
+ location.fatal(tr("Expected '=' or '+=' after key"));
+ SKIP_CHAR();
+ SKIP_SPACES();
+
+ for (;;) {
+ if (cc == '\\') {
+ int metaCharPos;
+
+ SKIP_CHAR();
+ if (cc == '\n') {
+ SKIP_CHAR();
+ }
+ else if (cc > '0' && cc < '8') {
+ word += QChar(c.digitValue());
+ SKIP_CHAR();
+ }
+ else if ((metaCharPos = QString(QLatin1String("abfnrtv")).indexOf(c)) != -1) {
+ word += "\a\b\f\n\r\t\v"[metaCharPos];
+ SKIP_CHAR();
+ }
+ else {
+ PUT_CHAR();
+ }
+ }
+ else if (c.isSpace() || cc == '#') {
+ if (inQuote) {
+ if (cc == '\n')
+ location.fatal(tr("Unterminated string"));
+ PUT_CHAR();
+ }
+ else {
+ if (!word.isEmpty()) {
+ if (metWord)
+ stringValue += QLatin1Char(' ');
+ stringValue += word;
+ stringListValue << word;
+ metWord = true;
+ word.clear();
+ prevWordQuoted = false;
+ }
+ if (cc == '\n' || cc == '#')
+ break;
+ SKIP_SPACES();
+ }
+ }
+ else if (cc == '"') {
+ if (inQuote) {
+ if (!prevWordQuoted)
+ stringValue += QLatin1Char(' ');
+ stringValue += word;
+ if (!word.isEmpty())
+ stringListValue << word;
+ metWord = true;
+ word.clear();
+ prevWordQuoted = true;
+ }
+ inQuote = !inQuote;
+ SKIP_CHAR();
+ }
+ else if (cc == '$') {
+ QString var;
+ SKIP_CHAR();
+ while (c.isLetterOrNumber() || cc == '_') {
+ var += c;
+ SKIP_CHAR();
+ }
+ if (!var.isEmpty()) {
+ char *val = getenv(var.toLatin1().data());
+ if (val == 0) {
+ location.fatal(tr("Environment variable '%1' undefined").arg(var));
+ }
+ else {
+ word += QString(val);
+ }
+ }
+ }
+ else {
+ if (!inQuote && cc == '=')
+ location.fatal(tr("Unexpected '='"));
+ PUT_CHAR();
+ }
+ }
+
+ QStringList::ConstIterator key = keys.begin();
+ while (key != keys.end()) {
+ if (!keySyntax.exactMatch(*key))
+ keyLoc.fatal(tr("Invalid key '%1'").arg(*key));
+
+ if (plus) {
+ if (locMap[*key].isEmpty()) {
+ locMap[*key] = keyLoc;
+ }
+ else {
+ locMap[*key].setEtc(true);
+ }
+ if (stringValueMap[*key].isEmpty()) {
+ stringValueMap[*key] = stringValue;
+ }
+ else {
+ stringValueMap[*key] +=
+ QLatin1Char(' ') + stringValue;
+ }
+ stringListValueMap[*key] += stringListValue;
+ }
+ else {
+ locMap[*key] = keyLoc;
+ stringValueMap[*key] = stringValue;
+ stringListValueMap[*key] = stringListValue;
+ }
+ ++key;
+ }
+ }
+ }
+ else {
+ location.fatal(tr("Unexpected character '%1' at beginning of line")
+ .arg(c));
+ }
+ }
+}
+
+QStringList Config::getFilesHere(const QString& dir,
+ const QString& nameFilter,
+ const QSet<QString> &excludedDirs)
+{
+ QStringList result;
+ if (excludedDirs.contains(dir))
+ return result;
+
+ QDir dirInfo(dir);
+ QStringList fileNames;
+ QStringList::const_iterator fn;
+
+ dirInfo.setNameFilters(nameFilter.split(' '));
+ dirInfo.setSorting(QDir::Name);
+ dirInfo.setFilter(QDir::Files);
+ fileNames = dirInfo.entryList();
+ fn = fileNames.constBegin();
+ while (fn != fileNames.constEnd()) {
+ if (!fn->startsWith(QLatin1Char('~')))
+ result.append(dirInfo.filePath(*fn));
+ ++fn;
+ }
+
+ dirInfo.setNameFilters(QStringList("*"));
+ dirInfo.setFilter(QDir::Dirs|QDir::NoDotAndDotDot);
+ fileNames = dirInfo.entryList();
+ fn = fileNames.constBegin();
+ while (fn != fileNames.constEnd()) {
+ result += getFilesHere(dirInfo.filePath(*fn), nameFilter, excludedDirs);
+ ++fn;
+ }
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/config.h b/tools/qdoc3/config.h
new file mode 100644
index 0000000000..9443f0dfac
--- /dev/null
+++ b/tools/qdoc3/config.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ config.h
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <QMap>
+#include <QSet>
+#include <QStringList>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class Config
+{
+ public:
+ Config(const QString& programName);
+ ~Config();
+
+ void load(const QString& fileName);
+ void setStringList(const QString& var, const QStringList& values);
+
+ const QString& programName() const { return prog; }
+ const Location& location() const { return loc; }
+ const Location& lastLocation() const { return lastLoc; }
+ bool getBool(const QString& var) const;
+ int getInt(const QString& var) const;
+ QString getString(const QString& var) const;
+ QSet<QString> getStringSet(const QString& var) const;
+ QStringList getStringList(const QString& var) const;
+ QRegExp getRegExp(const QString& var) const;
+ QList<QRegExp> getRegExpList(const QString& var) const;
+ QSet<QString> subVars(const QString& var) const;
+ QStringList getAllFiles(const QString& filesVar,
+ const QString& dirsVar,
+ const QString& defaultNameFilter,
+ const QSet<QString> &excludedDirs = QSet<QString>());
+
+ static QStringList getFilesHere(const QString& dir,
+ const QString& nameFilter,
+ const QSet<QString> &excludedDirs = QSet<QString>());
+ static QString findFile(const Location& location,
+ const QStringList &files,
+ const QStringList& dirs,
+ const QString& fileName,
+ QString& userFriendlyFilePath);
+ static QString findFile(const Location &location,
+ const QStringList &files,
+ const QStringList &dirs,
+ const QString &fileBase,
+ const QStringList &fileExtensions,
+ QString &userFriendlyFilePath);
+ static QString copyFile(const Location& location,
+ const QString& sourceFilePath,
+ const QString& userFriendlySourceFilePath,
+ const QString& targetDirPath);
+ static int numParams(const QString& value);
+ static bool removeDirContents(const QString& dir);
+
+ QT_STATIC_CONST QString dot;
+
+ private:
+ static bool isMetaKeyChar(QChar ch);
+ void load(Location location, const QString& fileName);
+
+ QString prog;
+ Location loc;
+ Location lastLoc;
+ QMap<QString, Location> locMap;
+ QMap<QString, QStringList> stringListValueMap;
+ QMap<QString, QString> stringValueMap;
+
+ static QMap<QString, QString> uncompressedFiles;
+ static QMap<QString, QString> extractedDirs;
+ static int numInstances;
+};
+
+#define CONFIG_ALIAS "alias"
+#define CONFIG_BASE "base" // ### don't document for now
+#define CONFIG_CODEINDENT "codeindent"
+#define CONFIG_DEFINES "defines"
+#define CONFIG_DESCRIPTION "description"
+#define CONFIG_EDITION "edition"
+#define CONFIG_EXAMPLEDIRS "exampledirs"
+#define CONFIG_EXAMPLES "examples"
+#define CONFIG_EXCLUDEDIRS "excludedirs"
+#define CONFIG_EXTRAIMAGES "extraimages"
+#define CONFIG_FALSEHOODS "falsehoods"
+#define CONFIG_FORMATTING "formatting"
+#define CONFIG_GENERATEINDEX "generateindex"
+#define CONFIG_HEADERDIRS "headerdirs"
+#define CONFIG_HEADERS "headers"
+#define CONFIG_IGNOREDIRECTIVES "ignoredirectives"
+#define CONFIG_IGNORETOKENS "ignoretokens"
+#define CONFIG_IMAGEDIRS "imagedirs"
+#define CONFIG_IMAGES "images"
+#define CONFIG_INDEXES "indexes"
+#define CONFIG_LANGUAGE "language"
+#define CONFIG_MACRO "macro"
+#define CONFIG_OUTPUTDIR "outputdir"
+#define CONFIG_OUTPUTLANGUAGE "outputlanguage"
+#define CONFIG_OUTPUTFORMATS "outputformats"
+#define CONFIG_PROJECT "project"
+#define CONFIG_QHP "qhp"
+#define CONFIG_QUOTINGINFORMATION "quotinginformation"
+#define CONFIG_SLOW "slow"
+#define CONFIG_SOURCEDIRS "sourcedirs"
+#define CONFIG_SOURCES "sources"
+#define CONFIG_SPURIOUS "spurious"
+#define CONFIG_STYLESHEETS "stylesheets"
+#define CONFIG_TABSIZE "tabsize"
+#define CONFIG_TAGFILE "tagfile"
+#define CONFIG_TRANSLATORS "translators" // ### don't document for now
+#define CONFIG_URL "url"
+#define CONFIG_VERSION "version"
+#define CONFIG_VERSIONSYM "versionsym"
+
+#define CONFIG_FILEEXTENSIONS "fileextensions"
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp
new file mode 100644
index 0000000000..59b967b928
--- /dev/null
+++ b/tools/qdoc3/cppcodemarker.cpp
@@ -0,0 +1,1009 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ cppcodemarker.cpp
+*/
+
+#include "atom.h"
+#include "cppcodemarker.h"
+#include "node.h"
+#include "text.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+static int insertTagAround(QString &result, int pos, int len, const QString &tagName,
+ const QString &attributes = QString())
+{
+ QString s;
+ //s.reserve(result.size() + tagName.size() * 2 + attributes.size() + 20);
+ s += result.midRef(0, pos);
+ s += QLatin1Char('<');
+ s += tagName;
+ if (!attributes.isEmpty()) {
+ s += QLatin1Char(' ');
+ s += attributes;
+ }
+ s += QLatin1Char('>');
+ s += result.midRef(pos, len);
+ s += QLatin1String("</");
+ s += tagName;
+ s += QLatin1Char('>');
+ s += result.midRef(pos + len);
+ int diff = s.length() - result.length();
+ result = s;
+ return diff;
+}
+
+/*!
+ The constructor does nothing.
+ */
+CppCodeMarker::CppCodeMarker()
+{
+ // nothing.
+}
+
+/*!
+ The destructor does nothing.
+ */
+CppCodeMarker::~CppCodeMarker()
+{
+ // nothing.
+}
+
+/*!
+ Returns true.
+ */
+bool CppCodeMarker::recognizeCode(const QString & /* code */)
+{
+ return true;
+}
+
+/*!
+ Returns true if \a ext is any of a list of file extensions
+ for the C++ language.
+ */
+bool CppCodeMarker::recognizeExtension(const QString& ext)
+{
+ return ext == "c" ||
+ ext == "c++" ||
+ ext == "cc" ||
+ ext == "cpp" ||
+ ext == "cxx" ||
+ ext == "ch" ||
+ ext == "h" ||
+ ext == "h++" ||
+ ext == "hh" ||
+ ext == "hpp" ||
+ ext == "hxx";
+}
+
+/*!
+ Returns true if \a lang is either "C" or "Cpp".
+ */
+bool CppCodeMarker::recognizeLanguage(const QString &lang)
+{
+ return lang == "C" || lang == "Cpp";
+}
+
+/*!
+ Returns the \a node name, or "()" if \a node is a
+ Node::Function node.
+ */
+QString CppCodeMarker::plainName(const Node *node)
+{
+ QString name = node->name();
+ if (node->type() == Node::Function)
+ name += "()";
+ return name;
+}
+
+QString CppCodeMarker::plainFullName(const Node *node, const Node *relative)
+{
+ if (node->name().isEmpty()) {
+ return "global";
+ }
+ else {
+ QString fullName;
+ for (;;) {
+ fullName.prepend(plainName(node));
+ if (node->parent() == relative || node->parent()->name().isEmpty())
+ break;
+ fullName.prepend("::");
+ node = node->parent();
+ }
+ return fullName;
+ }
+}
+
+QString CppCodeMarker::markedUpCode(const QString &code,
+ const Node *relative,
+ const QString &dirPath)
+{
+ return addMarkUp(protect(code), relative, dirPath);
+}
+
+QString CppCodeMarker::markedUpSynopsis(const Node *node,
+ const Node * /* relative */,
+ SynopsisStyle style)
+{
+ const int MaxEnumValues = 6;
+ const FunctionNode *func;
+ const PropertyNode *property;
+ const VariableNode *variable;
+ const EnumNode *enume;
+ const TypedefNode *typedeff;
+ QString synopsis;
+ QString extra;
+ QString name;
+
+ name = taggedNode(node);
+ if (style != Detailed)
+ name = linkTag(node, name);
+ name = "<@name>" + name + "</@name>";
+
+ if (style == Detailed && !node->parent()->name().isEmpty() &&
+ node->type() != Node::Property)
+ name.prepend(taggedNode(node->parent()) + "::");
+
+ switch (node->type()) {
+ case Node::Namespace:
+ synopsis = "namespace " + name;
+ break;
+ case Node::Class:
+ synopsis = "class " + name;
+ break;
+ case Node::Function:
+ func = (const FunctionNode *) node;
+ if (style != SeparateList && !func->returnType().isEmpty())
+ synopsis = typified(func->returnType()) + " ";
+ synopsis += name;
+ if (func->metaness() != FunctionNode::MacroWithoutParams) {
+ synopsis += " (";
+ if (!func->parameters().isEmpty()) {
+ synopsis += " ";
+ QList<Parameter>::ConstIterator p = func->parameters().begin();
+ while (p != func->parameters().end()) {
+ if (p != func->parameters().begin())
+ synopsis += ", ";
+ synopsis += typified((*p).leftType());
+ if (style != SeparateList && !(*p).name().isEmpty())
+ synopsis +=
+ " <@param>" + protect((*p).name()) + "</@param>";
+ synopsis += protect((*p).rightType());
+ if (style != SeparateList && !(*p).defaultValue().isEmpty())
+ synopsis += " = " + protect((*p).defaultValue());
+ ++p;
+ }
+ synopsis += " ";
+ }
+ synopsis += ")";
+ }
+ if (func->isConst())
+ synopsis += " const";
+
+ if (style == Summary || style == Accessors) {
+ if (func->virtualness() != FunctionNode::NonVirtual)
+ synopsis.prepend("virtual ");
+ if (func->virtualness() == FunctionNode::PureVirtual)
+ synopsis.append(" = 0");
+ }
+ else if (style == SeparateList) {
+ if (!func->returnType().isEmpty() && func->returnType() != "void")
+ synopsis += " : " + typified(func->returnType());
+ }
+ else {
+ QStringList bracketed;
+ if (func->isStatic()) {
+ bracketed += "static";
+ }
+ else if (func->virtualness() != FunctionNode::NonVirtual) {
+ if (func->virtualness() == FunctionNode::PureVirtual)
+ bracketed += "pure";
+ bracketed += "virtual";
+ }
+
+ if (func->access() == Node::Protected) {
+ bracketed += "protected";
+ }
+ else if (func->access() == Node::Private) {
+ bracketed += "private";
+ }
+
+ if (func->metaness() == FunctionNode::Signal) {
+ bracketed += "signal";
+ }
+ else if (func->metaness() == FunctionNode::Slot) {
+ bracketed += "slot";
+ }
+ if (!bracketed.isEmpty())
+ extra += " [" + bracketed.join(" ") + "]";
+ }
+ break;
+ case Node::Enum:
+ enume = static_cast<const EnumNode *>(node);
+ synopsis = "enum " + name;
+ if (style == Summary) {
+ synopsis += " { ";
+
+ QStringList documentedItems = enume->doc().enumItemNames();
+ if (documentedItems.isEmpty()) {
+ foreach (const EnumItem &item, enume->items())
+ documentedItems << item.name();
+ }
+ QStringList omitItems = enume->doc().omitEnumItemNames();
+ foreach (const QString &item, omitItems)
+ documentedItems.removeAll(item);
+
+ if (documentedItems.size() <= MaxEnumValues) {
+ for (int i = 0; i < documentedItems.size(); ++i) {
+ if (i != 0)
+ synopsis += ", ";
+ synopsis += documentedItems.at(i);
+ }
+ }
+ else {
+ for (int i = 0; i < documentedItems.size(); ++i) {
+ if (i < MaxEnumValues - 2 || i == documentedItems.size() - 1) {
+ if (i != 0)
+ synopsis += ", ";
+ synopsis += documentedItems.at(i);
+ }
+ else if (i == MaxEnumValues - 1) {
+ synopsis += ", ...";
+ }
+ }
+ }
+ if (!documentedItems.isEmpty())
+ synopsis += " ";
+ synopsis += "}";
+ }
+ break;
+ case Node::Typedef:
+ typedeff = static_cast<const TypedefNode *>(node);
+ if (typedeff->associatedEnum()) {
+ synopsis = "flags " + name;
+ }
+ else {
+ synopsis = "typedef " + name;
+ }
+ break;
+ case Node::Property:
+ property = static_cast<const PropertyNode *>(node);
+ synopsis = name + " : " + typified(property->qualifiedDataType());
+ break;
+ case Node::Variable:
+ variable = static_cast<const VariableNode *>(node);
+ if (style == SeparateList) {
+ synopsis = name + " : " + typified(variable->dataType());
+ }
+ else {
+ synopsis = typified(variable->leftType()) + " " +
+ name + protect(variable->rightType());
+ }
+ break;
+ default:
+ synopsis = name;
+ }
+
+ if (style == Summary) {
+ if (node->status() == Node::Preliminary) {
+ extra += " (preliminary)";
+ }
+ else if (node->status() == Node::Deprecated) {
+ extra += " (deprecated)";
+ }
+ else if (node->status() == Node::Obsolete) {
+ extra += " (obsolete)";
+ }
+ }
+
+ if (!extra.isEmpty()) {
+ extra.prepend("<@extra>");
+ extra.append("</@extra>");
+ }
+ return synopsis + extra;
+}
+
+QString CppCodeMarker::markedUpName(const Node *node)
+{
+ QString name = linkTag(node, taggedNode(node));
+ if (node->type() == Node::Function)
+ name += "()";
+ return name;
+}
+
+QString CppCodeMarker::markedUpFullName(const Node *node, const Node *relative)
+{
+ if (node->name().isEmpty()) {
+ return "global";
+ }
+ else {
+ QString fullName;
+ for (;;) {
+ fullName.prepend(markedUpName(node));
+ if (node->parent() == relative || node->parent()->name().isEmpty())
+ break;
+ fullName.prepend("<@op>::</@op>");
+ node = node->parent();
+ }
+ return fullName;
+ }
+}
+
+QString CppCodeMarker::markedUpEnumValue(const QString &enumValue,
+ const Node *relative)
+{
+ const Node *node = relative->parent();
+ QString fullName;
+ while (node->parent()) {
+ fullName.prepend(markedUpName(node));
+ if (node->parent() == relative || node->parent()->name().isEmpty())
+ break;
+ fullName.prepend("<@op>::</@op>");
+ node = node->parent();
+ }
+ if (!fullName.isEmpty())
+ fullName.append("<@op>::</@op>");
+ fullName.append(enumValue);
+ return fullName;
+}
+
+QString CppCodeMarker::markedUpIncludes(const QStringList& includes)
+{
+ QString code;
+
+ QStringList::ConstIterator inc = includes.begin();
+ while (inc != includes.end()) {
+ code += "#include &lt;<@headerfile>" + *inc + "</@headerfile>&gt;\n";
+ ++inc;
+ }
+ return addMarkUp(code, 0, "");
+}
+
+QString CppCodeMarker::functionBeginRegExp(const QString& funcName)
+{
+ return "^" + QRegExp::escape(funcName) + "$";
+
+}
+
+QString CppCodeMarker::functionEndRegExp(const QString& /* funcName */)
+{
+ return "^\\}$";
+}
+
+QList<Section> CppCodeMarker::sections(const InnerNode *inner,
+ SynopsisStyle style,
+ Status status)
+{
+ QList<Section> sections;
+
+ if (inner->type() == Node::Class) {
+ const ClassNode *classe = static_cast<const ClassNode *>(inner);
+
+ if (style == Summary) {
+ FastSection privateFunctions(classe, "Private Functions", "private function",
+ "private functions");
+ FastSection privateSlots(classe, "Private Slots", "private slot", "private slots");
+ FastSection privateTypes(classe, "Private Types", "private type", "private types");
+ FastSection protectedFunctions(classe, "Protected Functions", "protected function",
+ "protected functions");
+ FastSection protectedSlots(classe, "Protected Slots", "protected slot", "protected slots");
+ FastSection protectedTypes(classe, "Protected Types", "protected type", "protected types");
+ FastSection protectedVariables(classe, "Protected Variables", "protected type", "protected variables");
+ FastSection publicFunctions(classe, "Public Functions", "public function",
+ "public functions");
+ FastSection publicSignals(classe, "Signals", "signal", "signals");
+ FastSection publicSlots(classe, "Public Slots", "public slot", "public slots");
+ FastSection publicTypes(classe, "Public Types", "public type", "public types");
+ FastSection publicVariables(classe, "Public Variables", "public type", "public variables");
+ FastSection properties(classe, "Properties", "property", "properties");
+ FastSection relatedNonMembers(classe, "Related Non-Members", "related non-member",
+ "related non-members");
+ FastSection staticPrivateMembers(classe, "Static Private Members", "static private member",
+ "static private members");
+ FastSection staticProtectedMembers(classe, "Static Protected Members",
+ "static protected member", "static protected members");
+ FastSection staticPublicMembers(classe, "Static Public Members", "static public member",
+ "static public members");
+ FastSection macros(inner, "Macros", "macro", "macros");
+
+ NodeList::ConstIterator r = classe->relatedNodes().begin();
+ while (r != classe->relatedNodes().end()) {
+ if ((*r)->type() == Node::Function) {
+ FunctionNode *func = static_cast<FunctionNode *>(*r);
+ if (func->isMacro())
+ insert(macros, *r, style, status);
+ else
+ insert(relatedNonMembers, *r, style, status);
+ }
+ else {
+ insert(relatedNonMembers, *r, style, status);
+ }
+ ++r;
+ }
+
+ QStack<const ClassNode *> stack;
+ stack.push(classe);
+
+ while (!stack.isEmpty()) {
+ const ClassNode *ancestorClass = stack.pop();
+
+ NodeList::ConstIterator c = ancestorClass->childNodes().begin();
+ while (c != ancestorClass->childNodes().end()) {
+ bool isSlot = false;
+ bool isSignal = false;
+ bool isStatic = false;
+ if ((*c)->type() == Node::Function) {
+ const FunctionNode *func = (const FunctionNode *) *c;
+ isSlot = (func->metaness() == FunctionNode::Slot);
+ isSignal = (func->metaness() == FunctionNode::Signal);
+ isStatic = func->isStatic();
+ }
+ else if ((*c)->type() == Node::Variable) {
+ const VariableNode *var = static_cast<const VariableNode *>(*c);
+ isStatic = var->isStatic();
+ }
+
+ switch ((*c)->access()) {
+ case Node::Public:
+ if (isSlot) {
+ insert(publicSlots, *c, style, status);
+ }
+ else if (isSignal) {
+ insert(publicSignals, *c, style, status);
+ }
+ else if (isStatic) {
+ if ((*c)->type() != Node::Variable
+ || !(*c)->doc().isEmpty())
+ insert(staticPublicMembers, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Property) {
+ insert(properties, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Variable) {
+ if (!(*c)->doc().isEmpty())
+ insert(publicVariables, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Function) {
+ insert(publicFunctions, *c, style, status);
+ }
+ else {
+ insert(publicTypes, *c, style, status);
+ }
+ break;
+ case Node::Protected:
+ if (isSlot) {
+ insert(protectedSlots, *c, style, status);
+ }
+ else if (isStatic) {
+ if ((*c)->type() != Node::Variable
+ || !(*c)->doc().isEmpty())
+ insert(staticProtectedMembers, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Variable) {
+ if (!(*c)->doc().isEmpty())
+ insert(protectedVariables, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Function) {
+ insert(protectedFunctions, *c, style, status);
+ }
+ else {
+ insert(protectedTypes, *c, style, status);
+ }
+ break;
+ case Node::Private:
+ if (isSlot) {
+ insert(privateSlots, *c, style, status);
+ }
+ else if (isStatic) {
+ if ((*c)->type() != Node::Variable
+ || !(*c)->doc().isEmpty())
+ insert(staticPrivateMembers, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Function) {
+ insert(privateFunctions, *c, style, status);
+ }
+ else {
+ insert(privateTypes, *c, style, status);
+ }
+ }
+ ++c;
+ }
+
+ QList<RelatedClass>::ConstIterator r =
+ ancestorClass->baseClasses().begin();
+ while (r != ancestorClass->baseClasses().end()) {
+ stack.prepend((*r).node);
+ ++r;
+ }
+ }
+
+ append(sections, publicTypes);
+ append(sections, properties);
+ append(sections, publicFunctions);
+ append(sections, publicSlots);
+ append(sections, publicSignals);
+ append(sections, publicVariables);
+ append(sections, staticPublicMembers);
+ append(sections, protectedTypes);
+ append(sections, protectedFunctions);
+ append(sections, protectedSlots);
+ append(sections, protectedVariables);
+ append(sections, staticProtectedMembers);
+ append(sections, privateTypes);
+ append(sections, privateFunctions);
+ append(sections, privateSlots);
+ append(sections, staticPrivateMembers);
+ append(sections, relatedNonMembers);
+ append(sections, macros);
+ }
+ else if (style == Detailed) {
+ FastSection memberFunctions(classe,"Member Function Documentation");
+ FastSection memberTypes(classe,"Member Type Documentation");
+ FastSection memberVariables(classe,"Member Variable Documentation");
+ FastSection properties(classe,"Property Documentation");
+ FastSection relatedNonMembers(classe,"Related Non-Members");
+ FastSection macros(classe,"Macro Documentation");
+
+ NodeList::ConstIterator r = classe->relatedNodes().begin();
+ while (r != classe->relatedNodes().end()) {
+ if ((*r)->type() == Node::Function) {
+ FunctionNode *func = static_cast<FunctionNode *>(*r);
+ if (func->isMacro())
+ insert(macros, *r, style, status);
+ else
+ insert(relatedNonMembers, *r, style, status);
+ }
+ else {
+ insert(relatedNonMembers, *r, style, status);
+ }
+ ++r;
+ }
+
+ NodeList::ConstIterator c = classe->childNodes().begin();
+ while (c != classe->childNodes().end()) {
+ if ((*c)->type() == Node::Enum ||
+ (*c)->type() == Node::Typedef) {
+ insert(memberTypes, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Property) {
+ insert(properties, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Variable) {
+ if (!(*c)->doc().isEmpty())
+ insert(memberVariables, *c, style, status);
+ }
+ else if ((*c)->type() == Node::Function) {
+ FunctionNode *function = static_cast<FunctionNode *>(*c);
+ if (!function->associatedProperty())
+ insert(memberFunctions, function, style, status);
+ }
+ ++c;
+ }
+
+ append(sections, memberTypes);
+ append(sections, properties);
+ append(sections, memberFunctions);
+ append(sections, memberVariables);
+ append(sections, relatedNonMembers);
+ append(sections, macros);
+ }
+ else {
+ FastSection all(classe);
+
+ QStack<const ClassNode *> stack;
+ stack.push(classe);
+
+ while (!stack.isEmpty()) {
+ const ClassNode *ancestorClass = stack.pop();
+
+ NodeList::ConstIterator c = ancestorClass->childNodes().begin();
+ while (c != ancestorClass->childNodes().end()) {
+ if ((*c)->access() != Node::Private &&
+ (*c)->type() != Node::Property)
+ insert(all, *c, style, status);
+ ++c;
+ }
+
+ QList<RelatedClass>::ConstIterator r =
+ ancestorClass->baseClasses().begin();
+ while (r != ancestorClass->baseClasses().end()) {
+ stack.prepend((*r).node);
+ ++r;
+ }
+ }
+ append(sections, all);
+ }
+ }
+ else {
+ if (style == Summary || style == Detailed) {
+ FastSection namespaces(inner,
+ "Namespaces",
+ "namespace",
+ "namespaces");
+ FastSection classes(inner, "Classes", "class", "classes");
+ FastSection types(inner,
+ style == Summary ? "Types" : "Type Documentation",
+ "type",
+ "types");
+ FastSection functions(inner,
+ style == Summary ? "Functions" : "Function Documentation",
+ "function",
+ "functions");
+ FastSection macros(inner,
+ style == Summary ? "Macros" : "Macro Documentation",
+ "macro",
+ "macros");
+
+ NodeList nodeList = inner->childNodes();
+ nodeList += inner->relatedNodes();
+
+ NodeList::ConstIterator n = nodeList.begin();
+ while (n != nodeList.end()) {
+ switch ((*n)->type()) {
+ case Node::Namespace:
+ insert(namespaces, *n, style, status);
+ break;
+ case Node::Class:
+ insert(classes, *n, style, status);
+ break;
+ case Node::Enum:
+ case Node::Typedef:
+ insert(types, *n, style, status);
+ break;
+ case Node::Function:
+ {
+ FunctionNode *func = static_cast<FunctionNode *>(*n);
+ if (func->isMacro())
+ insert(macros, *n, style, status);
+ else
+ insert(functions, *n, style, status);
+ }
+ break;
+ default:
+ ;
+ }
+ ++n;
+ }
+ append(sections, namespaces);
+ append(sections, classes);
+ append(sections, types);
+ append(sections, functions);
+ append(sections, macros);
+ }
+ }
+
+ return sections;
+}
+
+const Node *CppCodeMarker::resolveTarget(const QString &target,
+ const Tree *tree,
+ const Node *relative)
+{
+ if (target.endsWith("()")) {
+ const FunctionNode *func;
+ QString funcName = target;
+ funcName.chop(2);
+
+ QStringList path = funcName.split("::");
+ if ((func = tree->findFunctionNode(path,
+ relative,
+ Tree::SearchBaseClasses))
+ && func->metaness() != FunctionNode::MacroWithoutParams)
+ return func;
+ }
+ else if (target.contains("#")) {
+ // ### this doesn't belong here; get rid of TargetNode hack
+ int hashAt = target.indexOf("#");
+ QString link = target.left(hashAt);
+ QString ref = target.mid(hashAt + 1);
+ const Node *node;
+ if (link.isEmpty()) {
+ node = relative;
+ }
+ else {
+ QStringList path(link);
+ node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses);
+ }
+ if (node && node->isInnerNode()) {
+ const Atom *atom = node->doc().body().firstAtom();
+ while (atom) {
+ if (atom->type() == Atom::Target && atom->string() == ref) {
+ Node *parentNode = const_cast<Node *>(node);
+ return new TargetNode(static_cast<InnerNode*>(parentNode),
+ ref);
+ }
+ atom = atom->next();
+ }
+ }
+ }
+ else {
+ QStringList path = target.split("::");
+ const Node *node;
+ if ((node = tree->findNode(path,
+ relative,
+ Tree::SearchBaseClasses |
+ Tree::SearchEnumValues |
+ Tree::NonFunction)))
+ return node;
+ }
+ return 0;
+}
+
+QString CppCodeMarker::addMarkUp(const QString& protectedCode,
+ const Node * /* relative */,
+ const QString& /* dirPath */)
+{
+ static QRegExp globalInclude("#include +&lt;([^<>&]+)&gt;");
+ static QRegExp yHasTypeX("(?:^|\n *)([a-zA-Z_][a-zA-Z_0-9]*)"
+ "(?:&lt;[^;{}]+&gt;)?(?: *(?:\\*|&amp;) *| +)"
+ "([a-zA-Z_][a-zA-Z_0-9]*)? *[,;()=]");
+ static QRegExp xNewY("([a-zA-Z_][a-zA-Z_0-9]*) *= *new +([a-zA-Z_0-9]+)");
+ static QRegExp xDotY("\\b([a-zA-Z_][a-zA-Z_0-9]*) *(?:\\.|-&gt;|,[ \n]*S(?:IGNAL|LOT)\\() *"
+ "([a-zA-Z_][a-zA-Z_0-9]*)(?= *\\()");
+ static QRegExp xIsStaticZOfY("[\n:;{(=] *(([a-zA-Z_0-9]+)::([a-zA-Z_0-9]+))(?= *\\()");
+ static QRegExp classX("[:,][ \n]*(?:p(?:ublic|r(?:otected|ivate))[ \n]+)?"
+ "([a-zA-Z_][a-zA-Z_0-9]*)");
+ static QRegExp globalX("[\n{()=] *([a-zA-Z_][a-zA-Z_0-9]*)[ \n]*\\(");
+ static QRegExp multiLineComment("/(?:( )?\\*(?:[^*]+|\\*(?! /))*\\*\\1/)");
+ multiLineComment.setMinimal(true);
+ static QRegExp singleLineComment("//(?!!)[^!\n]*");
+ static QRegExp preprocessor("(?:^|\n)(#[ \t]*(?:include|if|elif|endif|error|pragma|define"
+ "|warning)(?:(?:\\\\\n|\\n#)[^\n]*)*)");
+ static QRegExp literals("&quot;(?:[^\\\\&]|\\\\[^\n]|&(?!quot;))*&quot;"
+ "|'(?:[^\\\\]|\\\\(?:[^x0-9']|x[0-9a-f]{1,4}|[0-9]{1,3}))'");
+
+ QString result = protectedCode;
+ int pos;
+
+ if (!hurryUp()) {
+ /*
+ Mark global includes. For example:
+
+ #include &lt;<@headerfile>QString</@headerfile>
+ */
+ pos = 0;
+ while ((pos = result.indexOf(globalInclude, pos)) != -1)
+ pos += globalInclude.matchedLength()
+ + insertTagAround(result,
+ globalInclude.pos(1),
+ globalInclude.cap(1).length(),
+ "@headerfile");
+
+ /*
+ Look for variable definitions and similar constructs, mark
+ the data type, and remember the type of the variable.
+ */
+ QMap<QString, QSet<QString> > typesForVariable;
+ pos = 0;
+ while ((pos = yHasTypeX.indexIn(result, pos)) != -1) {
+ QString x = yHasTypeX.cap(1);
+ QString y = yHasTypeX.cap(2);
+
+ if (!y.isEmpty())
+ typesForVariable[y].insert(x);
+
+ /*
+ Without the minus one at the end, 'void member(Class
+ var)' would give 'member' as a variable of type 'void',
+ but would ignore 'Class var'. (### Is that true?)
+ */
+ pos += yHasTypeX.matchedLength()
+ + insertTagAround(result,
+ yHasTypeX.pos(1),
+ x.length(),
+ "@type") - 1;
+ }
+
+ /*
+ Do syntax highlighting of preprocessor directives.
+ */
+ pos = 0;
+ while ((pos = preprocessor.indexIn(result, pos)) != -1)
+ pos += preprocessor.matchedLength()
+ + insertTagAround(result,
+ preprocessor.pos(1),
+ preprocessor.cap(1).length(),
+ "@preprocessor");
+
+ /*
+ Deal with string and character literals.
+ */
+ pos = 0;
+ while ((pos = literals.indexIn(result, pos)) != -1)
+ pos += literals.matchedLength()
+ + insertTagAround(result,
+ pos,
+ literals.matchedLength(),
+ result.at(pos) ==
+ QLatin1Char(' ') ? "@string" : "@char");
+
+ /*
+ Look for 'var = new Class'.
+ */
+ pos = 0;
+ while ((pos = xNewY.indexIn(result, pos)) != -1) {
+ QString x = xNewY.cap(1);
+ QString y = xNewY.cap(2);
+ typesForVariable[x].insert(y);
+
+ pos += xNewY.matchedLength() + insertTagAround(result,
+ xNewY.pos(2),
+ y.length(),
+ "@type");
+ }
+
+ /*
+ Insert some stuff that cannot harm.
+ */
+ typesForVariable["qApp"].insert("QApplication");
+
+ /*
+ Add link to ': Class'.
+ */
+ pos = 0;
+ while ((pos = classX.indexIn(result, pos)) != -1)
+ pos += classX.matchedLength()
+ + insertTagAround(result,
+ classX.pos(1),
+ classX.cap(1).length(),
+ "@type") - 1;
+
+ /*
+ Find use of any of
+
+ var.method()
+ var->method()
+ var, SIGNAL(method())
+ var, SLOT(method()).
+ */
+ pos = 0;
+ while ((pos = xDotY.indexIn(result, pos)) != -1) {
+ QString x = xDotY.cap(1);
+ QString y = xDotY.cap(2);
+
+ QSet<QString> types = typesForVariable.value(x);
+ pos += xDotY.matchedLength()
+ + insertTagAround(result,
+ xDotY.pos(2),
+ xDotY.cap(2).length(),
+ "@func",
+ (types.count() == 1) ? "target=\""
+ + protect(*types.begin() + "::" + y)
+ + "()\"" : QString());
+ }
+
+ /*
+ Add link to 'Class::method()'.
+ */
+ pos = 0;
+ while ((pos = xIsStaticZOfY.indexIn(result, pos)) != -1) {
+ QString x = xIsStaticZOfY.cap(1);
+ QString z = xIsStaticZOfY.cap(3);
+
+ pos += insertTagAround(result,
+ xIsStaticZOfY.pos(3),
+ z.length(),
+ "@func",
+ "target=\"" + protect(x) + "()\"");
+ pos += insertTagAround(result,
+ xIsStaticZOfY.pos(2),
+ xIsStaticZOfY.cap(2).length(),
+ "@type");
+ pos += xIsStaticZOfY.matchedLength() - 1;
+ }
+
+ /*
+ Add link to 'globalFunction()'.
+ */
+ pos = 0;
+ while ((pos = globalX.indexIn(result, pos)) != -1) {
+ QString x = globalX.cap(1);
+ if (x != "QT_FORWARD_DECLARE_CLASS") {
+ pos += globalX.matchedLength()
+ + insertTagAround(result,
+ globalX.pos(1),
+ x.length(),
+ "@func",
+ "target=\"" + protect(x) + "()\"") - 1;
+ }
+ else
+ pos += globalX.matchedLength();
+ }
+ }
+
+ /*
+ Do syntax highlighting of comments. Also alter the code in a
+ minor way, so that we can include comments in documentation
+ comments.
+ */
+ pos = 0;
+ while (pos != -1) {
+ int mlpos;
+ int slpos;
+ int len;
+ slpos = singleLineComment.indexIn(result, pos);
+ mlpos = multiLineComment.indexIn(result, pos);
+
+ if (slpos == -1 && mlpos == -1)
+ break;
+
+ if (slpos == -1) {
+ pos = mlpos;
+ len = multiLineComment.matchedLength();
+ }
+ else if (mlpos == -1) {
+ pos = slpos;
+ len = singleLineComment.matchedLength();
+ }
+ else {
+ if (slpos < mlpos) {
+ pos = slpos;
+ len = singleLineComment.matchedLength();
+ }
+ else {
+ pos = mlpos;
+ len = multiLineComment.matchedLength();
+ }
+ }
+
+ if (result.at(pos + 1) == QLatin1Char(' ')) {
+ result.remove(pos + len - 2, 1);
+ result.remove(pos + 1, 1);
+ len -= 2;
+
+ forever {
+ int endcodePos = result.indexOf("\\ endcode", pos);
+ if (endcodePos == -1 || endcodePos >= pos + len)
+ break;
+ result.remove(endcodePos + 1, 1);
+ len -= 1;
+ }
+ }
+ pos += len + insertTagAround(result, pos, len, "@comment");
+ }
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/cppcodemarker.h b/tools/qdoc3/cppcodemarker.h
new file mode 100644
index 0000000000..8b68bc0a49
--- /dev/null
+++ b/tools/qdoc3/cppcodemarker.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ cppcodemarker.h
+*/
+
+#ifndef CPPCODEMARKER_H
+#define CPPCODEMARKER_H
+
+#include "codemarker.h"
+
+QT_BEGIN_NAMESPACE
+
+class CppCodeMarker : public CodeMarker
+{
+ public:
+ CppCodeMarker();
+ ~CppCodeMarker();
+
+ bool recognizeCode(const QString& code);
+ bool recognizeExtension(const QString& ext);
+ bool recognizeLanguage(const QString& lang);
+ QString plainName(const Node *node);
+ QString plainFullName(const Node *node, const Node *relative);
+ QString markedUpCode(const QString& code,
+ const Node *relative,
+ const QString& dirPath);
+ QString markedUpSynopsis(const Node *node,
+ const Node *relative,
+ SynopsisStyle style);
+ QString markedUpName(const Node *node);
+ QString markedUpFullName(const Node *node, const Node *relative);
+ QString markedUpEnumValue(const QString &enumValue, const Node *relative);
+ QString markedUpIncludes(const QStringList& includes);
+ QString functionBeginRegExp(const QString& funcName);
+ QString functionEndRegExp(const QString& funcName);
+ QList<Section> sections(const InnerNode *innerNode,
+ SynopsisStyle style,
+ Status status);
+ const Node *resolveTarget(const QString& target,
+ const Tree *tree,
+ const Node *relative);
+
+private:
+ QString addMarkUp(const QString& protectedCode,
+ const Node *relative,
+ const QString& dirPath);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp
new file mode 100644
index 0000000000..1ad5843078
--- /dev/null
+++ b/tools/qdoc3/cppcodeparser.cpp
@@ -0,0 +1,2014 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ cppcodeparser.cpp
+*/
+
+#include <QtCore>
+#include <qfile.h>
+
+#include <stdio.h>
+
+#include "codechunk.h"
+#include "config.h"
+#include "cppcodeparser.h"
+#include "tokenizer.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+/* qmake ignore Q_OBJECT */
+
+#define COMMAND_CLASS Doc::alias("class")
+#define COMMAND_CONTENTSPAGE Doc::alias("contentspage")
+#define COMMAND_ENUM Doc::alias("enum")
+#define COMMAND_EXAMPLE Doc::alias("example")
+#define COMMAND_EXTERNALPAGE Doc::alias("externalpage")
+#define COMMAND_FILE Doc::alias("file") // ### don't document
+#define COMMAND_FN Doc::alias("fn")
+#define COMMAND_GROUP Doc::alias("group")
+#define COMMAND_HEADERFILE Doc::alias("headerfile")
+#define COMMAND_INDEXPAGE Doc::alias("indexpage")
+#define COMMAND_INHEADERFILE Doc::alias("inheaderfile") // ### don't document
+#define COMMAND_MACRO Doc::alias("macro")
+#define COMMAND_MODULE Doc::alias("module") // ### don't document
+#define COMMAND_NAMESPACE Doc::alias("namespace")
+#define COMMAND_OVERLOAD Doc::alias("overload")
+#define COMMAND_NEXTPAGE Doc::alias("nextpage")
+#define COMMAND_PAGE Doc::alias("page")
+#define COMMAND_PREVIOUSPAGE Doc::alias("previouspage")
+#define COMMAND_PROPERTY Doc::alias("property")
+#define COMMAND_REIMP Doc::alias("reimp")
+#define COMMAND_RELATES Doc::alias("relates")
+#define COMMAND_SERVICE Doc::alias("service")
+#define COMMAND_STARTPAGE Doc::alias("startpage")
+#define COMMAND_TYPEDEF Doc::alias("typedef")
+#define COMMAND_VARIABLE Doc::alias("variable")
+
+#ifdef QDOC_QML
+#define COMMAND_QMLCLASS Doc::alias("qmlclass")
+#define COMMAND_QMLPROPERTY Doc::alias("qmlproperty")
+#endif
+
+QStringList CppCodeParser::exampleFiles;
+QStringList CppCodeParser::exampleDirs;
+
+static void extractPageLinkAndDesc(const QString &arg,
+ QString *link,
+ QString *desc)
+{
+ QRegExp bracedRegExp("\\{([^{}]*)\\}(?:\\{([^{}]*)\\})?");
+
+ if (bracedRegExp.exactMatch(arg)) {
+ *link = bracedRegExp.cap(1);
+ *desc = bracedRegExp.cap(2);
+ if (desc->isEmpty())
+ *desc = *link;
+ }
+ else {
+ int spaceAt = arg.indexOf(" ");
+ if (arg.contains(".html") && spaceAt != -1) {
+ *link = arg.left(spaceAt).trimmed();
+ *desc = arg.mid(spaceAt).trimmed();
+ } else {
+ *link = arg;
+ *desc = arg;
+ }
+ }
+}
+
+static void setLink(Node *node, Node::LinkType linkType, const QString &arg)
+{
+ QString link;
+ QString desc;
+ extractPageLinkAndDesc(arg, &link, &desc);
+ node->setLink(linkType, link, desc);
+}
+
+/*
+ This is used for fuzzy matching only, which in turn is only used
+ for Qt Jambi.
+*/
+static QString cleanType(const QString &type, const Tree *tree)
+{
+ QString result = type;
+ result.replace("qlonglong", "long long");
+ result.replace("qulonglong", "unsigned long long");
+ result.replace("qreal", "double");
+ result.replace(QRegExp("\\bu(int|short|char|long)\\b"), "unsigned \\1");
+ result.replace("QRgb", "unsigned int");
+ result.replace(" >", ">");
+ result.remove(" const[]");
+ result.replace("QStringList<QString>", "QStringList");
+ result.replace("qint8", "char");
+ result.replace("qint16", "short");
+ result.replace("qint32", "int");
+ result.replace("qint64", "long long");
+ result.replace("quint8", "unsigned char");
+ result.replace("quint16", "unsigned short");
+ result.replace("quint32", "unsigned int");
+ result.replace("quint64", "unsigned long long");
+
+ if (result.contains("QFlags")) {
+ QRegExp regExp("QFlags<(((?:[^<>]+::)*)([^<>:]+))>");
+ int pos = 0;
+ while ((pos = result.indexOf(regExp, pos)) != -1) {
+ // we assume that the path for the associated enum
+ // is the same as for the flag typedef
+ QStringList path = regExp.cap(2).split("::",
+ QString::SkipEmptyParts);
+ const EnumNode *enume = static_cast<const EnumNode *>(
+ tree->findNode(QStringList(path) << regExp.cap(3),
+ Node::Enum));
+ if (enume && enume->flagsType())
+ result.replace(pos, regExp.matchedLength(),
+ (QStringList(path) << enume->flagsType()->name()).join("::"));
+ ++pos;
+ }
+ }
+ if (result.contains("::")) {
+ // remove needless (and needful) class prefixes
+ QRegExp regExp("[A-Za-z0-9_]+::");
+ result.replace(regExp, "");
+ }
+ return result;
+}
+
+/*!
+ The constructor initializes some regular expressions
+ and calls reset().
+ */
+CppCodeParser::CppCodeParser()
+ : varComment("/\\*\\s*([a-zA-Z_0-9]+)\\s*\\*/"), sep("(?:<[^>]+>)?::")
+{
+ reset(0);
+}
+
+/*!
+ The destructor is trivial.
+ */
+CppCodeParser::~CppCodeParser()
+{
+}
+
+void CppCodeParser::initializeParser(const Config &config)
+{
+ CodeParser::initializeParser(config);
+
+ nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace);
+ nodeTypeMap.insert(COMMAND_CLASS, Node::Class);
+ nodeTypeMap.insert(COMMAND_SERVICE, Node::Class);
+ nodeTypeMap.insert(COMMAND_ENUM, Node::Enum);
+ nodeTypeMap.insert(COMMAND_TYPEDEF, Node::Typedef);
+ nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property);
+ nodeTypeMap.insert(COMMAND_VARIABLE, Node::Variable);
+
+#ifdef QDOC_QML
+ // nodeTypeMap.insert(COMMAND_QMLCLASS, Node::Class);
+ nodeTypeMap.insert(COMMAND_QMLPROPERTY, Node::Property);
+#endif
+
+ exampleFiles = config.getStringList(CONFIG_EXAMPLES);
+ exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS);
+ QStringList exampleFilePatterns = config.getStringList(
+ CONFIG_EXAMPLES + Config::dot + CONFIG_FILEEXTENSIONS);
+
+ if (!exampleFilePatterns.isEmpty())
+ exampleNameFilter = exampleFilePatterns.join(" ");
+ else
+ exampleNameFilter = "*.cpp *.h *.js *.xq *.svg *.xml *.ui";
+}
+
+void CppCodeParser::terminateParser()
+{
+ nodeTypeMap.clear();
+ CodeParser::terminateParser();
+}
+
+QString CppCodeParser::language()
+{
+ return "Cpp";
+}
+
+QString CppCodeParser::headerFileNameFilter()
+{
+ return "*.ch *.h *.h++ *.hh *.hpp *.hxx";
+}
+
+QString CppCodeParser::sourceFileNameFilter()
+{
+ return "*.c++ *.cc *.cpp *.cxx";
+}
+
+/*!
+ Parse the C++ header file identified by \a filePath
+ and add the parsed contents to the big \a tree. The
+ \a location is used for reporting errors.
+ */
+void CppCodeParser::parseHeaderFile(const Location& location,
+ const QString& filePath,
+ Tree *tree)
+{
+ FILE *in = fopen(QFile::encodeName(filePath), "r");
+ if (!in) {
+ location.error(tr("Cannot open C++ header file '%1'").arg(filePath));
+ return;
+ }
+
+ reset(tree);
+ Location fileLocation(filePath);
+ Tokenizer fileTokenizer(fileLocation, in);
+ tokenizer = &fileTokenizer;
+ readToken();
+ matchDeclList(tree->root());
+ if (!fileTokenizer.version().isEmpty())
+ tree->setVersion(fileTokenizer.version());
+ fclose(in);
+
+ if (fileLocation.fileName() == "qiterator.h")
+ parseQiteratorDotH(location, filePath);
+}
+
+/*!
+ Get ready to parse the C++ cpp file identified by \a filePath
+ and add its parsed contents to the big \a tree. \a location is
+ used for reporting errors.
+
+ Call matchDocsAndStuff() to do all the parsing and tree building.
+ */
+void CppCodeParser::parseSourceFile(const Location& location,
+ const QString& filePath,
+ Tree *tree)
+{
+ FILE *in = fopen(QFile::encodeName(filePath), "r");
+ if (!in) {
+ location.error(tr("Cannot open C++ source file '%1'").arg(filePath));
+ return;
+ }
+
+ reset(tree);
+ Location fileLocation(filePath);
+ Tokenizer fileTokenizer(fileLocation, in);
+ tokenizer = &fileTokenizer;
+ readToken();
+ usedNamespaces.clear();
+ matchDocsAndStuff();
+ fclose(in);
+}
+
+void CppCodeParser::doneParsingHeaderFiles(Tree *tree)
+{
+ tree->resolveInheritance();
+
+ QMapIterator<QString, QString> i(sequentialIteratorClasses);
+ while (i.hasNext()) {
+ i.next();
+ instantiateIteratorMacro(i.key(),
+ i.value(),
+ sequentialIteratorDefinition,
+ tree);
+ }
+ i = mutableSequentialIteratorClasses;
+ while (i.hasNext()) {
+ i.next();
+ instantiateIteratorMacro(i.key(),
+ i.value(),
+ mutableSequentialIteratorDefinition,
+ tree);
+ }
+ i = associativeIteratorClasses;
+ while (i.hasNext()) {
+ i.next();
+ instantiateIteratorMacro(i.key(),
+ i.value(),
+ associativeIteratorDefinition,
+ tree);
+ }
+ i = mutableAssociativeIteratorClasses;
+ while (i.hasNext()) {
+ i.next();
+ instantiateIteratorMacro(i.key(),
+ i.value(),
+ mutableAssociativeIteratorDefinition,
+ tree);
+ }
+ sequentialIteratorDefinition.clear();
+ mutableSequentialIteratorDefinition.clear();
+ associativeIteratorDefinition.clear();
+ mutableAssociativeIteratorDefinition.clear();
+ sequentialIteratorClasses.clear();
+ mutableSequentialIteratorClasses.clear();
+ associativeIteratorClasses.clear();
+ mutableAssociativeIteratorClasses.clear();
+}
+
+void CppCodeParser::doneParsingSourceFiles(Tree *tree)
+{
+ tree->root()->makeUndocumentedChildrenInternal();
+ tree->root()->normalizeOverloads();
+ tree->fixInheritance();
+ tree->resolveProperties();
+}
+
+const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis,
+ Tree *tree,
+ Node *relative,
+ bool fuzzy)
+{
+ QStringList parentPath;
+ FunctionNode *clone;
+ FunctionNode *func = 0;
+ int flags = fuzzy ? int(Tree::SearchBaseClasses) : 0;
+
+ reset(tree);
+ if (makeFunctionNode(synopsis, &parentPath, &clone)) {
+ func = tree->findFunctionNode(parentPath, clone, relative, flags);
+
+ /*
+ This is necessary because Roberto's parser resolves typedefs.
+ */
+ if (!func && fuzzy) {
+ func = tre->findFunctionNode(parentPath +
+ QStringList(clone->name()),
+ relative,
+ flags);
+ if (!func && clone->name().contains('_')) {
+ QStringList path = parentPath;
+ path << clone->name().split('_');
+ func = tre->findFunctionNode(path, relative, flags);
+ }
+
+ if (func) {
+ NodeList overloads = func->parent()->overloads(func->name());
+ NodeList candidates;
+ for (int i = 0; i < overloads.count(); ++i) {
+ FunctionNode *overload = static_cast<FunctionNode *>(overloads.at(i));
+ if (overload->status() != Node::Compat
+ && overload->parameters().count() == clone->parameters().count()
+ && !overload->isConst() == !clone->isConst())
+ candidates << overload;
+ }
+ if (candidates.count() == 0)
+ return 0;
+
+ /*
+ There's only one function with the correct number
+ of parameters. That must be the one.
+ */
+ if (candidates.count() == 1)
+ return static_cast<FunctionNode *>(candidates.first());
+
+ overloads = candidates;
+ candidates.clear();
+ for (int i = 0; i < overloads.count(); ++i) {
+ FunctionNode *overload = static_cast<FunctionNode *>(overloads.at(i));
+ QList<Parameter> params1 = overload->parameters();
+ QList<Parameter> params2 = clone->parameters();
+
+ int j;
+ for (j = 0; j < params1.count(); ++j) {
+ if (!params2.at(j).name().startsWith(params1.at(j).name()))
+ break;
+ }
+ if (j == params1.count())
+ candidates << overload;
+ }
+
+ /*
+ There are several functions with the correct
+ parameter count, but only one has the correct
+ parameter names.
+ */
+ if (candidates.count() == 1)
+ return static_cast<FunctionNode *>(candidates.first());
+
+ candidates.clear();
+ for (int i = 0; i < overloads.count(); ++i) {
+ FunctionNode *overload = static_cast<FunctionNode *>(overloads.at(i));
+ QList<Parameter> params1 = overload->parameters();
+ QList<Parameter> params2 = clone->parameters();
+
+ int j;
+ for (j = 0; j < params1.count(); ++j) {
+ if (params1.at(j).rightType() != params2.at(j).rightType())
+ break;
+
+ if (cleanType(params1.at(j).leftType(), tree)
+ != cleanType(params2.at(j).leftType(), tree))
+ break;
+ }
+ if (j == params1.count())
+ candidates << overload;
+ }
+
+
+ /*
+ There are several functions with the correct
+ parameter count, but only one has the correct
+ types, loosely compared.
+ */
+ if (candidates.count() == 1)
+ return static_cast<FunctionNode *>(candidates.first());
+
+ return 0;
+ }
+ }
+ delete clone;
+ }
+ return func;
+}
+
+/*!
+ Returns the set of strings reopresenting the topic commands.
+ */
+QSet<QString> CppCodeParser::topicCommands()
+{
+ return QSet<QString>() << COMMAND_CLASS
+ << COMMAND_ENUM
+ << COMMAND_EXAMPLE
+ << COMMAND_EXTERNALPAGE
+ << COMMAND_FILE
+ << COMMAND_FN
+ << COMMAND_GROUP
+ << COMMAND_HEADERFILE
+ << COMMAND_MACRO
+ << COMMAND_MODULE
+ << COMMAND_NAMESPACE
+ << COMMAND_PAGE
+ << COMMAND_PROPERTY
+ << COMMAND_SERVICE
+ << COMMAND_TYPEDEF
+#ifdef QDOC_QML
+ << COMMAND_VARIABLE
+ << COMMAND_QMLCLASS
+ << COMMAND_QMLPROPERTY;
+#else
+ << COMMAND_VARIABLE;
+#endif
+}
+
+/*!
+ Process the topic \a command in context \a doc with argument \a arg.
+ */
+Node *CppCodeParser::processTopicCommand(const Doc& doc,
+ const QString& command,
+ const QString& arg)
+{
+ if (command == COMMAND_FN) {
+ QStringList parentPath;
+ FunctionNode *func = 0;
+ FunctionNode *clone = 0;
+
+ if (!makeFunctionNode(arg, &parentPath, &clone) &&
+ !makeFunctionNode("void " + arg, &parentPath, &clone)) {
+ doc.location().warning(tr("Invalid syntax in '\\%1'")
+ .arg(COMMAND_FN));
+ }
+ else {
+ if (!usedNamespaces.isEmpty()) {
+ foreach (const QString &usedNamespace, usedNamespaces) {
+ QStringList newPath = usedNamespace.split("::") + parentPath;
+ func = tre->findFunctionNode(newPath, clone);
+ if (func)
+ break;
+ }
+ }
+ // Search the root namespace if no match was found.
+ if (func == 0)
+ func = tre->findFunctionNode(parentPath, clone);
+
+ if (func == 0) {
+ if (parentPath.isEmpty() && !lastPath.isEmpty())
+ func = tre->findFunctionNode(lastPath, clone);
+ if (func == 0) {
+ doc.location().warning(tr("Cannot find '%1' in '\\%2'")
+ .arg(clone->name() + "(...)")
+ .arg(COMMAND_FN),
+ tr("I cannot find any function of that name with the "
+ "specified signature. Make sure that the signature "
+ "is identical to the declaration, including 'const' "
+ "qualifiers."));
+ }
+ else {
+ doc.location().warning(tr("Missing '%1::' for '%2' in '\\%3'")
+ .arg(lastPath.join("::"))
+ .arg(clone->name() + "()")
+ .arg(COMMAND_FN));
+ }
+ }
+ else {
+ lastPath = parentPath;
+ }
+
+ if (func)
+ func->borrowParameterNames(clone);
+ delete clone;
+ }
+ return func;
+ }
+ else if (command == COMMAND_MACRO) {
+ QStringList parentPath;
+ FunctionNode *func = 0;
+
+ if (makeFunctionNode(arg, &parentPath, &func, tre->root())) {
+ if (!parentPath.isEmpty()) {
+ doc.location().warning(tr("Invalid syntax in '\\%1'")
+ .arg(COMMAND_MACRO));
+ delete func;
+ func = 0;
+ }
+ else {
+ func->setMetaness(FunctionNode::MacroWithParams);
+ QList<Parameter> params = func->parameters();
+ for (int i = 0; i < params.size(); ++i) {
+ Parameter &param = params[i];
+ if (param.name().isEmpty() && !param.leftType().isEmpty()
+ && param.leftType() != "...")
+ param = Parameter("", "", param.leftType());
+ }
+ func->setParameters(params);
+ }
+ return func;
+ }
+ else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg)) {
+ func = new FunctionNode(tre->root(), arg);
+ func->setAccess(Node::Public);
+ func->setLocation(doc.location());
+ func->setMetaness(FunctionNode::MacroWithoutParams);
+ }
+ else {
+ doc.location().warning(tr("Invalid syntax in '\\%1'")
+ .arg(COMMAND_MACRO));
+
+ }
+ return func;
+ }
+ else if (nodeTypeMap.contains(command)) {
+ /*
+ The command was neither "fn" nor "macro" .
+ */
+ // ### split(" ") hack is there to support header file syntax
+ QStringList paths = arg.split(" ");
+ QStringList path = paths[0].split("::");
+
+#if QDOC2DOX
+ // qdoc -> doxygen.
+ if (Doc::isDoxPass(1)) {
+ if (command == COMMAND_PROPERTY) {
+ Doc::insertProperty(path);
+ }
+ else if (command == COMMAND_VARIABLE) {
+ Doc::insertVariable(path);
+ }
+ else if (command == COMMAND_ENUM) {
+ // zzz
+ }
+ }
+#endif
+
+ Node *node = 0;
+ if (!usedNamespaces.isEmpty()) {
+ foreach (const QString &usedNamespace, usedNamespaces) {
+ QStringList newPath = usedNamespace.split("::") + path;
+ node = tre->findNode(newPath, nodeTypeMap[command]);
+ if (node) {
+ path = newPath;
+ break;
+ }
+ }
+ }
+ // Search the root namespace if no match was found.
+ if (node == 0)
+ node = tre->findNode(path, nodeTypeMap[command]);
+
+ if (node == 0) {
+ doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file")
+ .arg(arg).arg(command));
+ lastPath = path;
+
+ }
+ else if (command == COMMAND_SERVICE) {
+ // If the command is "\service", then we need to tag the
+ // class with the actual service name.
+ QStringList args = arg.split(" ");
+ if (args.size() > 1) {
+ ClassNode *cnode = static_cast<ClassNode *>(node);
+ cnode->setServiceName(args[1]);
+ cnode->setHideFromMainList(true);
+ }
+ }
+ else if (node->isInnerNode()) {
+ if (path.size() > 1) {
+ path.pop_back();
+ usedNamespaces.insert(path.join("::"));
+ }
+ }
+
+ return node;
+ }
+ else if (command == COMMAND_EXAMPLE) {
+ FakeNode *fake = new FakeNode(tre->root(), arg, FakeNode::Example);
+ createExampleFileNodes(fake);
+ return fake;
+ }
+ else if (command == COMMAND_EXTERNALPAGE) {
+ return new FakeNode(tre->root(), arg, FakeNode::ExternalPage);
+ }
+ else if (command == COMMAND_FILE) {
+ return new FakeNode(tre->root(), arg, FakeNode::File);
+ }
+ else if (command == COMMAND_GROUP) {
+ return new FakeNode(tre->root(), arg, FakeNode::Group);
+ }
+ else if (command == COMMAND_HEADERFILE) {
+ return new FakeNode(tre->root(), arg, FakeNode::HeaderFile);
+ }
+ else if (command == COMMAND_MODULE) {
+ return new FakeNode(tre->root(), arg, FakeNode::Module);
+ }
+ else if (command == COMMAND_PAGE) {
+ return new FakeNode(tre->root(), arg, FakeNode::Page);
+ }
+#ifdef QDOC_QML
+ else if (command == COMMAND_QMLCLASS) {
+ const ClassNode* classNode = 0;
+ QStringList names = arg.split(" ");
+ //qDebug() << "QMLCLASS" << names;
+ if (names.size() > 1) {
+ Node* n = tre->findNode(names[1].split("::"),Node::Class);
+ if (n) {
+ classNode = static_cast<const ClassNode*>(n);
+ //qDebug() << "FOUND IT!" << classNode->name();
+ }
+ }
+ return new QmlNode(tre->root(), names[0], classNode);
+ }
+#endif
+ return 0;
+}
+
+/*!
+ Returns the set of strings representing the common metacommands
+ plus some other metacommands.
+ */
+QSet<QString> CppCodeParser::otherMetaCommands()
+{
+ return commonMetaCommands() << COMMAND_INHEADERFILE
+ << COMMAND_OVERLOAD
+ << COMMAND_REIMP
+ << COMMAND_RELATES
+ << COMMAND_CONTENTSPAGE
+ << COMMAND_NEXTPAGE
+ << COMMAND_PREVIOUSPAGE
+ << COMMAND_INDEXPAGE
+ << COMMAND_STARTPAGE;
+}
+
+/*!
+ Process the metacommand \a command in the context of the
+ \a node associated with the topic command and the \a doc.
+ \a arg is the argument to the metacommand.
+ */
+void CppCodeParser::processOtherMetaCommand(const Doc& doc,
+ const QString& command,
+ const QString& arg,
+ Node *node)
+{
+ if (command == COMMAND_INHEADERFILE) {
+ if (node != 0 && node->isInnerNode()) {
+ ((InnerNode *) node)->addInclude(arg);
+ }
+ else {
+ doc.location().warning(tr("Ignored '\\%1'")
+ .arg(COMMAND_INHEADERFILE));
+ }
+ }
+ else if (command == COMMAND_OVERLOAD) {
+ if (node != 0 && node->type() == Node::Function) {
+ ((FunctionNode *) node)->setOverload(true);
+ }
+ else {
+ doc.location().warning(tr("Ignored '\\%1'")
+ .arg(COMMAND_OVERLOAD));
+ }
+ }
+ else if (command == COMMAND_REIMP) {
+ if (node != 0 && node->type() == Node::Function) {
+ FunctionNode *func = (FunctionNode *) node;
+ const FunctionNode *from = func->reimplementedFrom();
+ if (from == 0) {
+ doc.location().warning(
+ tr("Cannot find base function for '\\%1' in %2()")
+ .arg(COMMAND_REIMP).arg(node->name()),
+ tr("The function either doesn't exist in any base class "
+ "with the same signature or it exists but isn't virtual."));
+ }
+#if 0 // Ideally, we would enable this check to warn whenever \reimp is used
+ // incorrectly, and only make the node internal if the function is a
+ // reimplementation of another function in a base class.
+ else if (from->access() == Node::Private
+ || from->parent()->access() == Node::Private) {
+ doc.location().warning(
+ tr("Base function for '\\%1' in %2() is private or internal")
+ .arg(COMMAND_REIMP).arg(node->name()));
+ }
+#endif
+ // Note: Setting the access to Private hides the documentation,
+ // but setting the status to Internal makes the node available
+ // in the XML output when the WebXMLGenerator is used.
+ func->setAccess(Node::Private);
+ func->setStatus(Node::Internal);
+ }
+ else {
+ doc.location().warning(tr("Ignored '\\%1' in %2")
+ .arg(COMMAND_REIMP)
+ .arg(node->name()));
+ }
+ }
+ else if (command == COMMAND_RELATES) {
+ InnerNode *pseudoParent;
+ if (arg.startsWith("<") || arg.startsWith("\"")) {
+ pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(arg), Node::Fake));
+ }
+ else {
+ QStringList newPath = arg.split("::");
+ pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath), Node::Class));
+ if (!pseudoParent)
+ pseudoParent = static_cast<InnerNode *>(tre->findNode(QStringList(newPath),
+ Node::Namespace));
+ }
+ if (!pseudoParent) {
+ doc.location().warning(tr("Cannot find '%1' in '\\%2'")
+ .arg(arg).arg(COMMAND_RELATES));
+ }
+ else {
+ node->setRelates(pseudoParent);
+ }
+ }
+ else if (command == COMMAND_CONTENTSPAGE) {
+ setLink(node, Node::ContentsLink, arg);
+ }
+ else if (command == COMMAND_NEXTPAGE) {
+ setLink(node, Node::NextLink, arg);
+ }
+ else if (command == COMMAND_PREVIOUSPAGE) {
+ setLink(node, Node::PreviousLink, arg);
+ }
+ else if (command == COMMAND_INDEXPAGE) {
+ setLink(node, Node::IndexLink, arg);
+ }
+ else if (command == COMMAND_STARTPAGE) {
+ setLink(node, Node::StartLink, arg);
+ }
+ else {
+ processCommonMetaCommand(doc.location(),command,arg,node,tre);
+ }
+}
+
+/*!
+ The topic command has been processed resulting in the \a doc
+ and \a node passed in here. Process the other meta commands,
+ which are found in \a doc, in the context of the topic \a node.
+ */
+void CppCodeParser::processOtherMetaCommands(const Doc& doc, Node *node)
+{
+ const QSet<QString> metaCommands = doc.metaCommandsUsed();
+ QSet<QString>::ConstIterator cmd = metaCommands.begin();
+ while (cmd != metaCommands.end()) {
+ QStringList args = doc.metaCommandArgs(*cmd);
+ QStringList::ConstIterator arg = args.begin();
+ while (arg != args.end()) {
+ processOtherMetaCommand(doc, *cmd, *arg, node);
+ ++arg;
+ }
+ ++cmd;
+ }
+}
+
+/*!
+ Resets the C++ code parser to its default initialized state.
+ */
+void CppCodeParser::reset(Tree *tree)
+{
+ tre = tree;
+ tokenizer = 0;
+ tok = 0;
+ access = Node::Public;
+ metaness = FunctionNode::Plain;
+ lastPath.clear();
+ moduleName = "";
+}
+
+/*!
+ Get the next token from the file being parsed and store it
+ in the token variable.
+ */
+void CppCodeParser::readToken()
+{
+ tok = tokenizer->getToken();
+}
+
+/*!
+ Return the current location in the file being parsed,
+ i.e. the file name, line number, and column number.
+ */
+const Location& CppCodeParser::location()
+{
+ return tokenizer->location();
+}
+
+/*!
+ Return the previous string read from the file being parsed.
+ */
+QString CppCodeParser::previousLexeme()
+{
+ return tokenizer->previousLexeme();
+}
+
+/*!
+ Return the current string string from the file being parsed.
+ */
+QString CppCodeParser::lexeme()
+{
+ return tokenizer->lexeme();
+}
+
+bool CppCodeParser::match(int target)
+{
+ if (tok == target) {
+ readToken();
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/*!
+ If the current token is one of the keyword thingees that
+ are used in Qt, skip over it to the next token and return
+ true. Otherwise just return false without reading the
+ next token.
+ */
+bool CppCodeParser::matchCompat()
+{
+ switch (tok) {
+ case Tok_QT_COMPAT:
+ case Tok_QT_COMPAT_CONSTRUCTOR:
+ case Tok_QT_DEPRECATED:
+ case Tok_QT_MOC_COMPAT:
+ case Tok_QT3_SUPPORT:
+ case Tok_QT3_SUPPORT_CONSTRUCTOR:
+ case Tok_QT3_MOC_SUPPORT:
+ readToken();
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool CppCodeParser::matchTemplateAngles(CodeChunk *dataType)
+{
+ bool matches = (tok == Tok_LeftAngle);
+ if (matches) {
+ int leftAngleDepth = 0;
+ int parenAndBraceDepth = 0;
+ do {
+ if (tok == Tok_LeftAngle) {
+ leftAngleDepth++;
+ } else if (tok == Tok_RightAngle) {
+ leftAngleDepth--;
+ } else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) {
+ ++parenAndBraceDepth;
+ } else if (tok == Tok_RightParen || tok == Tok_RightBrace) {
+ if (--parenAndBraceDepth < 0)
+ return false;
+ }
+
+ if (dataType != 0)
+ dataType->append(lexeme());
+ readToken();
+ } while (leftAngleDepth > 0 && tok != Tok_Eoi);
+ }
+ return matches;
+}
+
+bool CppCodeParser::matchTemplateHeader()
+{
+ readToken();
+ return matchTemplateAngles();
+}
+
+bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var)
+{
+ /*
+ This code is really hard to follow... sorry. The loop is there to match
+ Alpha::Beta::Gamma::...::Omega.
+ */
+ for (;;) {
+ bool virgin = true;
+
+ if (tok != Tok_Ident) {
+ /*
+ There is special processing for 'Foo::operator int()'
+ and such elsewhere. This is the only case where we
+ return something with a trailing gulbrandsen ('Foo::').
+ */
+ if (tok == Tok_operator)
+ return true;
+
+ /*
+ People may write 'const unsigned short' or
+ 'short unsigned const' or any other permutation.
+ */
+ while (match(Tok_const) || match(Tok_volatile))
+ dataType->append(previousLexeme());
+ while (match(Tok_signed) || match(Tok_unsigned) ||
+ match(Tok_short) || match(Tok_long) || match(Tok_int64)) {
+ dataType->append(previousLexeme());
+ virgin = false;
+ }
+ while (match(Tok_const) || match(Tok_volatile))
+ dataType->append(previousLexeme());
+
+ if (match(Tok_Tilde))
+ dataType->append(previousLexeme());
+ }
+
+ if (virgin) {
+ if (match(Tok_Ident))
+ dataType->append(previousLexeme());
+ else if (match(Tok_void) || match(Tok_int) || match(Tok_char) ||
+ match(Tok_double) || match(Tok_Ellipsis))
+ dataType->append(previousLexeme());
+ else
+ return false;
+ } else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) {
+ dataType->append(previousLexeme());
+ }
+
+ matchTemplateAngles(dataType);
+
+ while (match(Tok_const) || match(Tok_volatile))
+ dataType->append(previousLexeme());
+
+ if (match(Tok_Gulbrandsen))
+ dataType->append(previousLexeme());
+ else
+ break;
+ }
+
+ while (match(Tok_Ampersand) || match(Tok_Aster) || match(Tok_const) ||
+ match(Tok_Caret))
+ dataType->append(previousLexeme());
+
+ if (match(Tok_LeftParenAster)) {
+ /*
+ A function pointer. This would be rather hard to handle without a
+ tokenizer hack, because a type can be followed with a left parenthesis
+ in some cases (e.g., 'operator int()'). The tokenizer recognizes '(*'
+ as a single token.
+ */
+ dataType->append(previousLexeme());
+ dataType->appendHotspot();
+ if (var != 0 && match(Tok_Ident))
+ *var = previousLexeme();
+ if (!match(Tok_RightParen) || tok != Tok_LeftParen)
+ return false;
+ dataType->append(previousLexeme());
+
+ int parenDepth0 = tokenizer->parenDepth();
+ while (tokenizer->parenDepth() >= parenDepth0 && tok != Tok_Eoi) {
+ dataType->append(lexeme());
+ readToken();
+ }
+ if (match(Tok_RightParen))
+ dataType->append(previousLexeme());
+ }
+ else {
+ /*
+ The common case: Look for an optional identifier, then for
+ some array brackets.
+ */
+ dataType->appendHotspot();
+
+ if (var != 0) {
+ if (match(Tok_Ident)) {
+ *var = previousLexeme();
+ }
+ else if (match(Tok_Comment)) {
+ /*
+ A neat hack: Commented-out parameter names are
+ recognized by qdoc. It's impossible to illustrate
+ here inside a C-style comment, because it requires
+ an asterslash. It's also impossible to illustrate
+ inside a C++-style comment, because the explanation
+ does not fit on one line.
+ */
+ if (varComment.exactMatch(previousLexeme()))
+ *var = varComment.cap(1);
+ }
+ }
+
+ if (tok == Tok_LeftBracket) {
+ int bracketDepth0 = tokenizer->bracketDepth();
+ while ((tokenizer->bracketDepth() >= bracketDepth0 &&
+ tok != Tok_Eoi) ||
+ tok == Tok_RightBracket) {
+ dataType->append(lexeme());
+ readToken();
+ }
+ }
+ }
+ return true;
+}
+
+bool CppCodeParser::matchParameter(FunctionNode *func)
+{
+ CodeChunk dataType;
+ QString name;
+ CodeChunk defaultValue;
+
+ if (!matchDataType(&dataType, &name))
+ return false;
+ match(Tok_Comment);
+ if (match(Tok_Equal)) {
+ int parenDepth0 = tokenizer->parenDepth();
+
+ while (tokenizer->parenDepth() >= parenDepth0 &&
+ (tok != Tok_Comma ||
+ tokenizer->parenDepth() > parenDepth0) &&
+ tok != Tok_Eoi) {
+ defaultValue.append(lexeme());
+ readToken();
+ }
+ }
+ func->addParameter(Parameter(dataType.toString(), "", name,
+ defaultValue.toString())); // ###
+ return true;
+}
+
+bool CppCodeParser::matchFunctionDecl(InnerNode *parent,
+ QStringList *parentPathPtr,
+ FunctionNode **funcPtr,
+ const QString &templateStuff)
+{
+ CodeChunk returnType;
+ QStringList parentPath;
+ QString name;
+
+ bool compat = false;
+
+ if (match(Tok_friend))
+ return false;
+ match(Tok_explicit);
+ if (matchCompat())
+ compat = true;
+ bool sta = false;
+ if (match(Tok_static)) {
+ sta = true;
+ if (matchCompat())
+ compat = true;
+ }
+ FunctionNode::Virtualness vir = FunctionNode::NonVirtual;
+ if (match(Tok_virtual)) {
+ vir = FunctionNode::ImpureVirtual;
+ if (matchCompat())
+ compat = true;
+ }
+
+ if (!matchDataType(&returnType)) {
+ if (tokenizer->parsingFnOrMacro()
+ && (match(Tok_Q_DECLARE_FLAGS) || match(Tok_Q_PROPERTY)))
+ returnType = CodeChunk(previousLexeme());
+ else
+ return false;
+ }
+
+ if (returnType.toString() == "QBool")
+ returnType = CodeChunk("bool");
+
+ if (matchCompat())
+ compat = true;
+
+ if (tok == Tok_operator &&
+ (returnType.toString().isEmpty() || returnType.toString().endsWith("::"))) {
+ // 'QString::operator const char *()'
+ parentPath = returnType.toString().split(sep);
+ parentPath.removeAll(QString());
+ returnType = CodeChunk();
+ readToken();
+
+ CodeChunk restOfName;
+ if (tok != Tok_Tilde && matchDataType(&restOfName)) {
+ name = "operator " + restOfName.toString();
+ }
+ else {
+ name = previousLexeme() + lexeme();
+ readToken();
+ while (tok != Tok_LeftParen && tok != Tok_Eoi) {
+ name += lexeme();
+ readToken();
+ }
+ }
+ if (tok != Tok_LeftParen)
+ return false;
+ }
+ else if (tok == Tok_LeftParen) {
+ // constructor or destructor
+ parentPath = returnType.toString().split(sep);
+ if (!parentPath.isEmpty()) {
+ name = parentPath.last();
+ parentPath.erase(parentPath.end() - 1);
+ }
+ returnType = CodeChunk();
+ }
+ else {
+ while (match(Tok_Ident)) {
+ name = previousLexeme();
+ matchTemplateAngles();
+
+ if (match(Tok_Gulbrandsen)) {
+ parentPath.append(name);
+ } else {
+ break;
+ }
+ }
+
+ if (tok == Tok_operator) {
+ name = lexeme();
+ readToken();
+ while (tok != Tok_Eoi) {
+ name += lexeme();
+ readToken();
+ if (tok == Tok_LeftParen)
+ break;
+ }
+ }
+ if (parent && (tok == Tok_Semicolon || tok == Tok_LeftBracket || tok == Tok_Colon)
+ && access != Node::Private) {
+ if (tok == Tok_LeftBracket) {
+ returnType.appendHotspot();
+
+ int bracketDepth0 = tokenizer->bracketDepth();
+ while ((tokenizer->bracketDepth() >= bracketDepth0 &&
+ tok != Tok_Eoi) ||
+ tok == Tok_RightBracket) {
+ returnType.append(lexeme());
+ readToken();
+ }
+ if (tok != Tok_Semicolon)
+ return false;
+ } else if (tok == Tok_Colon) {
+ returnType.appendHotspot();
+
+ while (tok != Tok_Semicolon && tok != Tok_Eoi) {
+ returnType.append(lexeme());
+ readToken();
+ }
+ if (tok != Tok_Semicolon)
+ return false;
+ }
+
+ VariableNode *var = new VariableNode(parent, name);
+ var->setAccess(access);
+ var->setLocation(location());
+ var->setLeftType(returnType.left());
+ var->setRightType(returnType.right());
+ if (compat)
+ var->setStatus(Node::Compat);
+ var->setStatic(sta);
+ return false;
+ }
+ if (tok != Tok_LeftParen)
+ return false;
+ }
+ readToken();
+
+ FunctionNode *func = new FunctionNode(parent, name);
+ func->setAccess(access);
+ func->setLocation(location());
+ func->setReturnType(returnType.toString());
+ func->setTemplateStuff(templateStuff);
+ if (compat)
+ func->setStatus(Node::Compat);
+
+ func->setMetaness(metaness);
+ if (parent) {
+ if (name == parent->name()) {
+ func->setMetaness(FunctionNode::Ctor);
+ } else if (name.startsWith("~")) {
+ func->setMetaness(FunctionNode::Dtor);
+ }
+ }
+ func->setStatic(sta);
+
+ if (tok != Tok_RightParen) {
+ do {
+ if (!matchParameter(func))
+ return false;
+ } while (match(Tok_Comma));
+ }
+ if (!match(Tok_RightParen))
+ return false;
+
+ func->setConst(match(Tok_const));
+
+ if (match(Tok_Equal) && match(Tok_Number))
+ vir = FunctionNode::PureVirtual;
+ func->setVirtualness(vir);
+
+ if (match(Tok_Colon)) {
+ while (tok != Tok_LeftBrace && tok != Tok_Eoi)
+ readToken();
+ }
+
+ if (!match(Tok_Semicolon) && tok != Tok_Eoi) {
+ int braceDepth0 = tokenizer->braceDepth();
+
+ if (!match(Tok_LeftBrace))
+ return false;
+ while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi)
+ readToken();
+ match(Tok_RightBrace);
+ }
+ if (parentPathPtr != 0)
+ *parentPathPtr = parentPath;
+ if (funcPtr != 0)
+ *funcPtr = func;
+ return true;
+}
+
+bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass)
+{
+ Node::Access access;
+
+ switch (tok) {
+ case Tok_public:
+ access = Node::Public;
+ readToken();
+ break;
+ case Tok_protected:
+ access = Node::Protected;
+ readToken();
+ break;
+ case Tok_private:
+ access = Node::Private;
+ readToken();
+ break;
+ default:
+ access = isClass ? Node::Private : Node::Public;
+ }
+
+ if (tok == Tok_virtual)
+ readToken();
+
+ CodeChunk baseClass;
+ if (!matchDataType(&baseClass))
+ return false;
+
+ tre->addBaseClass(classe,
+ access,
+ baseClass.toPath(),
+ baseClass.toString(),
+ classe->parent());
+ return true;
+}
+
+bool CppCodeParser::matchBaseList(ClassNode *classe, bool isClass)
+{
+ for (;;) {
+ if (!matchBaseSpecifier(classe, isClass))
+ return false;
+ if (tok == Tok_LeftBrace)
+ return true;
+ if (!match(Tok_Comma))
+ return false;
+ }
+}
+
+/*!
+ Parse a C++ class, union, or struct declarion.
+ */
+bool CppCodeParser::matchClassDecl(InnerNode *parent,
+ const QString &templateStuff)
+{
+ bool isClass = (tok == Tok_class);
+ readToken();
+
+ bool compat = matchCompat();
+
+ if (tok != Tok_Ident)
+ return false;
+ while (tok == Tok_Ident)
+ readToken();
+ if (tok != Tok_Colon && tok != Tok_LeftBrace)
+ return false;
+
+ /*
+ So far, so good. We have 'class Foo {' or 'class Foo :'.
+ This is enough to recognize a class definition.
+ */
+ ClassNode *classe = new ClassNode(parent, previousLexeme());
+ classe->setAccess(access);
+ classe->setLocation(location());
+ if (compat)
+ classe->setStatus(Node::Compat);
+ if (!moduleName.isEmpty())
+ classe->setModuleName(moduleName);
+ classe->setTemplateStuff(templateStuff);
+
+ if (match(Tok_Colon) && !matchBaseList(classe, isClass))
+ return false;
+ if (!match(Tok_LeftBrace))
+ return false;
+
+ Node::Access outerAccess = access;
+ access = isClass ? Node::Private : Node::Public;
+ FunctionNode::Metaness outerMetaness = metaness;
+ metaness = FunctionNode::Plain;
+
+ bool matches = (matchDeclList(classe) && match(Tok_RightBrace) &&
+ match(Tok_Semicolon));
+ access = outerAccess;
+ metaness = outerMetaness;
+ return matches;
+}
+
+bool CppCodeParser::matchNamespaceDecl(InnerNode *parent)
+{
+ readToken(); // skip 'namespace'
+ if (tok != Tok_Ident)
+ return false;
+ while (tok == Tok_Ident)
+ readToken();
+ if (tok != Tok_LeftBrace)
+ return false;
+
+ /*
+ So far, so good. We have 'namespace Foo {'.
+ */
+ QString namespaceName = previousLexeme();
+ NamespaceNode *namespasse = 0;
+ if (parent)
+ namespasse = static_cast<NamespaceNode *>(parent->findNode(namespaceName, Node::Namespace));
+ if (!namespasse) {
+ namespasse = new NamespaceNode(parent, namespaceName);
+ namespasse->setAccess(access);
+ namespasse->setLocation(location());
+ }
+
+ readToken(); // skip '{'
+ bool matched = matchDeclList(namespasse);
+
+ return matched && match(Tok_RightBrace);
+}
+
+bool CppCodeParser::matchUsingDecl()
+{
+ readToken(); // skip 'using'
+
+ // 'namespace'
+ if (tok != Tok_namespace)
+ return false;
+
+ readToken();
+ // identifier
+ if (tok != Tok_Ident)
+ return false;
+
+ QString name;
+ while (tok == Tok_Ident) {
+ name += lexeme();
+ readToken();
+ if (tok == Tok_Semicolon)
+ break;
+ else if (tok != Tok_Gulbrandsen)
+ return false;
+ name += "::";
+ readToken();
+ }
+
+ /*
+ So far, so good. We have 'using namespace Foo;'.
+ */
+ usedNamespaces.insert(name);
+ return true;
+}
+
+bool CppCodeParser::matchEnumItem(InnerNode *parent, EnumNode *enume)
+{
+ if (!match(Tok_Ident))
+ return false;
+
+ QString name = previousLexeme();
+ CodeChunk val;
+
+ if (match(Tok_Equal)) {
+ while (tok != Tok_Comma && tok != Tok_RightBrace &&
+ tok != Tok_Eoi) {
+ val.append(lexeme());
+ readToken();
+ }
+ }
+
+ if (enume) {
+ QString strVal = val.toString();
+ if (strVal.isEmpty()) {
+ if (enume->items().isEmpty()) {
+ strVal = "0";
+ } else {
+ QString last = enume->items().last().value();
+ bool ok;
+ int n = last.toInt(&ok);
+ if (ok) {
+ if (last.startsWith("0") && last.size() > 1) {
+ if (last.startsWith("0x") || last.startsWith("0X"))
+ strVal = last.left(2) + QString::number(n + 1, 16);
+ else
+ strVal = "0" + QString::number(n + 1, 8);
+ } else {
+ strVal = QString::number(n + 1);
+ }
+ }
+ }
+ }
+
+ enume->addItem(EnumItem(name, strVal));
+ } else {
+ VariableNode *var = new VariableNode(parent, name);
+ var->setAccess(access);
+ var->setLocation(location());
+ var->setLeftType("const int");
+ var->setStatic(true);
+ }
+ return true;
+}
+
+bool CppCodeParser::matchEnumDecl(InnerNode *parent)
+{
+ QString name;
+
+ if (!match(Tok_enum))
+ return false;
+ if (match(Tok_Ident))
+ name = previousLexeme();
+ if (tok != Tok_LeftBrace)
+ return false;
+
+ EnumNode *enume = 0;
+
+ if (!name.isEmpty()) {
+ enume = new EnumNode(parent, name);
+ enume->setAccess(access);
+ enume->setLocation(location());
+ }
+
+ readToken();
+
+ if (!matchEnumItem(parent, enume))
+ return false;
+
+ while (match(Tok_Comma)) {
+ if (!matchEnumItem(parent, enume))
+ return false;
+ }
+ return match(Tok_RightBrace) && match(Tok_Semicolon);
+}
+
+bool CppCodeParser::matchTypedefDecl(InnerNode *parent)
+{
+ CodeChunk dataType;
+ QString name;
+
+ if (!match(Tok_typedef))
+ return false;
+ if (!matchDataType(&dataType, &name))
+ return false;
+ if (!match(Tok_Semicolon))
+ return false;
+
+ if (parent && !parent->findNode(name, Node::Typedef)) {
+ TypedefNode *typedeffe = new TypedefNode(parent, name);
+ typedeffe->setAccess(access);
+ typedeffe->setLocation(location());
+ }
+ return true;
+}
+
+bool CppCodeParser::matchProperty(InnerNode *parent)
+{
+ if (!match(Tok_Q_PROPERTY) &&
+ !match(Tok_Q_OVERRIDE) &&
+ !match(Tok_QDOC_PROPERTY))
+ return false;
+ if (!match(Tok_LeftParen))
+ return false;
+
+ QString name;
+ CodeChunk dataType;
+ if (!matchDataType(&dataType, &name))
+ return false;
+
+ PropertyNode *property = new PropertyNode(parent, name);
+ property->setAccess(Node::Public);
+ property->setLocation(location());
+ property->setDataType(dataType.toString());
+
+ while (tok != Tok_RightParen && tok != Tok_Eoi) {
+ if (!match(Tok_Ident))
+ return false;
+ QString key = previousLexeme();
+ QString value;
+
+ if (match(Tok_Ident)) {
+ value = previousLexeme();
+ } else if (match(Tok_LeftParen)) {
+ int depth = 1;
+ while (tok != Tok_Eoi) {
+ if (tok == Tok_LeftParen) {
+ readToken();
+ ++depth;
+ } else if (tok == Tok_RightParen) {
+ readToken();
+ if (--depth == 0)
+ break;
+ } else {
+ readToken();
+ }
+ }
+ value = "?";
+ }
+
+ if (key == "READ")
+ tre->addPropertyFunction(property, value, PropertyNode::Getter);
+ else if (key == "WRITE")
+ tre->addPropertyFunction(property, value, PropertyNode::Setter);
+ else if (key == "STORED")
+ property->setStored(value.toLower() == "true");
+ else if (key == "DESIGNABLE")
+ property->setDesignable(value.toLower() == "true");
+ else if (key == "RESET")
+ tre->addPropertyFunction(property, value, PropertyNode::Resetter);
+ }
+ match(Tok_RightParen);
+ return true;
+}
+
+/*!
+ Parse a C++ declaration.
+ */
+bool CppCodeParser::matchDeclList(InnerNode *parent)
+{
+ QString templateStuff;
+ int braceDepth0 = tokenizer->braceDepth();
+ if (tok == Tok_RightBrace) // prevents failure on empty body
+ braceDepth0++;
+
+ while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi) {
+ switch (tok) {
+ case Tok_Colon:
+ readToken();
+ break;
+ case Tok_class:
+ case Tok_struct:
+ case Tok_union:
+ matchClassDecl(parent, templateStuff);
+ break;
+ case Tok_namespace:
+ matchNamespaceDecl(parent);
+ break;
+ case Tok_using:
+ matchUsingDecl();
+ break;
+ case Tok_template:
+ templateStuff = matchTemplateHeader();
+ continue;
+ case Tok_enum:
+ matchEnumDecl(parent);
+ break;
+ case Tok_typedef:
+ matchTypedefDecl(parent);
+ break;
+ case Tok_private:
+ readToken();
+ access = Node::Private;
+ metaness = FunctionNode::Plain;
+ break;
+ case Tok_protected:
+ readToken();
+ access = Node::Protected;
+ metaness = FunctionNode::Plain;
+ break;
+ case Tok_public:
+ readToken();
+ access = Node::Public;
+ metaness = FunctionNode::Plain;
+ break;
+ case Tok_signals:
+ case Tok_Q_SIGNALS:
+ readToken();
+ access = Node::Public;
+ metaness = FunctionNode::Signal;
+ break;
+ case Tok_slots:
+ case Tok_Q_SLOTS:
+ readToken();
+ metaness = FunctionNode::Slot;
+ break;
+ case Tok_Q_OBJECT:
+ readToken();
+ break;
+ case Tok_Q_OVERRIDE:
+ case Tok_Q_PROPERTY:
+ case Tok_QDOC_PROPERTY:
+ matchProperty(parent);
+ break;
+ case Tok_Q_DECLARE_SEQUENTIAL_ITERATOR:
+ readToken();
+ if (match(Tok_LeftParen) && match(Tok_Ident))
+ sequentialIteratorClasses.insert(previousLexeme(),
+ location().fileName());
+ match(Tok_RightParen);
+ break;
+ case Tok_Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR:
+ readToken();
+ if (match(Tok_LeftParen) && match(Tok_Ident))
+ mutableSequentialIteratorClasses.insert(previousLexeme(),
+ location().fileName());
+ match(Tok_RightParen);
+ break;
+ case Tok_Q_DECLARE_ASSOCIATIVE_ITERATOR:
+ readToken();
+ if (match(Tok_LeftParen) && match(Tok_Ident))
+ associativeIteratorClasses.insert(previousLexeme(),
+ location().fileName());
+ match(Tok_RightParen);
+ break;
+ case Tok_Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR:
+ readToken();
+ if (match(Tok_LeftParen) && match(Tok_Ident))
+ mutableAssociativeIteratorClasses.insert(previousLexeme(),
+ location().fileName());
+ match(Tok_RightParen);
+ break;
+ case Tok_Q_DECLARE_FLAGS:
+ readToken();
+ if (match(Tok_LeftParen) && match(Tok_Ident)) {
+ QString flagsType = previousLexeme();
+ if (match(Tok_Comma) && match(Tok_Ident)) {
+ QString enumType = previousLexeme();
+ TypedefNode *flagsNode = new TypedefNode(parent, flagsType);
+ flagsNode->setAccess(access);
+ flagsNode->setLocation(location());
+ EnumNode *enumNode =
+ static_cast<EnumNode*>(parent->findNode(enumType,
+ Node::Enum));
+ if (enumNode)
+ enumNode->setFlagsType(flagsNode);
+ }
+ }
+ match(Tok_RightParen);
+ break;
+ case Tok_QT_MODULE:
+ readToken();
+ if (match(Tok_LeftParen) && match(Tok_Ident))
+ moduleName = previousLexeme();
+ if (!moduleName.startsWith("Qt"))
+ moduleName.prepend("Qt");
+ match(Tok_RightParen);
+ break;
+ default:
+ if (!matchFunctionDecl(parent, 0, 0, templateStuff)) {
+ while (tok != Tok_Eoi &&
+ (tokenizer->braceDepth() > braceDepth0 ||
+ (!match(Tok_Semicolon) &&
+ tok != Tok_public && tok != Tok_protected &&
+ tok != Tok_private)))
+ readToken();
+ }
+ }
+ templateStuff.clear();
+ }
+ return true;
+}
+
+/*!
+ This is called by parseSourceFile() to do the actual parsing
+ and tree building.
+ */
+bool CppCodeParser::matchDocsAndStuff()
+{
+ QSet<QString> topicCommandsAllowed = topicCommands();
+ QSet<QString> otherMetacommandsAllowed = otherMetaCommands();
+ QSet<QString> metacommandsAllowed = topicCommandsAllowed +
+ otherMetacommandsAllowed;
+
+ while (tok != Tok_Eoi) {
+ if (tok == Tok_Doc) {
+ /*
+ lexeme() returns an entire qdoc comment.
+ */
+ QString comment = lexeme();
+ Location start_loc(location());
+ readToken();
+
+ Doc::trimCStyleComment(start_loc,comment);
+ /*
+ qdoc --> doxygen
+ We must also remember the location of the end
+ of the comment, so we can construct a diff for
+ it.
+ */
+ Location end_loc(location());
+
+ /*
+ Doc parses the comment.
+ */
+ Doc doc(start_loc,end_loc,comment,metacommandsAllowed);
+
+ QString topic;
+ QStringList args;
+
+ QSet<QString> topicCommandsUsed = topicCommandsAllowed &
+ doc.metaCommandsUsed();
+
+ /*
+ There should be one topic command in the set,
+ or none. If the set is empty, then the comment
+ should be a function description.
+ */
+ if (topicCommandsUsed.count() > 0) {
+ topic = *topicCommandsUsed.begin();
+ args = doc.metaCommandArgs(topic);
+ }
+
+ NodeList nodes;
+ QList<Doc> docs;
+
+ if (topic.isEmpty()) {
+ QStringList parentPath;
+ FunctionNode *clone;
+ FunctionNode *func = 0;
+
+ if (matchFunctionDecl(0, &parentPath, &clone)) {
+ foreach (const QString &usedNamespace, usedNamespaces) {
+ QStringList newPath = usedNamespace.split("::") + parentPath;
+ func = tre->findFunctionNode(newPath, clone);
+ if (func)
+ break;
+ }
+ if (func == 0)
+ func = tre->findFunctionNode(parentPath, clone);
+
+ if (func) {
+ func->borrowParameterNames(clone);
+ nodes.append(func);
+ docs.append(doc);
+ }
+ delete clone;
+ }
+ else {
+ doc.location().warning(
+ tr("Cannot tie this documentation to anything"),
+ tr("I found a /*! ... */ comment, but there was no "
+ "topic command (e.g., '\\%1', '\\%2') in the "
+ "comment and no function definition following "
+ "the comment.")
+ .arg(COMMAND_FN).arg(COMMAND_PAGE));
+ }
+ }
+ else {
+ /*
+ There is a topic command. Process it.
+ */
+ QStringList::ConstIterator a = args.begin();
+ while (a != args.end()) {
+ Doc nodeDoc = doc;
+ Node *node = processTopicCommand(nodeDoc, topic, *a);
+ if (node != 0) {
+ nodes.append(node);
+ docs.append(nodeDoc);
+ }
+ ++a;
+ }
+ }
+
+ NodeList::Iterator n = nodes.begin();
+ QList<Doc>::Iterator d = docs.begin();
+ while (n != nodes.end()) {
+ processOtherMetaCommands(*d, *n);
+ (*n)->setDoc(*d);
+ if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) {
+ InnerNode *m = static_cast<InnerNode *>(*n);
+ while (m->parent() != tre->root())
+ m = m->parent();
+ if (m == *n)
+ ((InnerNode *)*n)->addInclude((*n)->name());
+ else
+ ((InnerNode *)*n)->setIncludes(m->includes());
+ }
+ ++d;
+ ++n;
+ }
+ }
+ else if (tok == Tok_using) {
+ matchUsingDecl();
+ }
+ else {
+ QStringList parentPath;
+ FunctionNode *clone;
+ FunctionNode *node = 0;
+
+ if (matchFunctionDecl(0, &parentPath, &clone)) {
+ /*
+ The location of the definition is more interesting
+ than that of the declaration. People equipped with
+ a sophisticated text editor can respond to warnings
+ concerning undocumented functions very quickly.
+
+ Signals are implemented in uninteresting files
+ generated by moc.
+ */
+ node = tre->findFunctionNode(parentPath, clone);
+ if (node != 0 && node->metaness() != FunctionNode::Signal)
+ node->setLocation(clone->location());
+ delete clone;
+ }
+ else {
+ if (tok != Tok_Doc)
+ readToken();
+ }
+ }
+ }
+ return true;
+}
+
+bool CppCodeParser::makeFunctionNode(const QString& synopsis,
+ QStringList *parentPathPtr,
+ FunctionNode **funcPtr,
+ InnerNode *root)
+{
+ Tokenizer *outerTokenizer = tokenizer;
+ int outerTok = tok;
+
+ Location loc;
+ QByteArray latin1 = synopsis.toLatin1();
+ Tokenizer stringTokenizer(loc, latin1);
+ stringTokenizer.setParsingFnOrMacro(true);
+ tokenizer = &stringTokenizer;
+ readToken();
+
+ bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr);
+ // potential memory leak with funcPtr
+
+ tokenizer = outerTokenizer;
+ tok = outerTok;
+
+ return ok;
+}
+
+void CppCodeParser::parseQiteratorDotH(const Location &location,
+ const QString &filePath)
+{
+ QFile file(filePath);
+ if (!file.open(QFile::ReadOnly))
+ return;
+
+ QString text = file.readAll();
+ text.remove("\r");
+ text.replace("\\\n", "");
+ QStringList lines = text.split("\n");
+ lines = lines.filter("Q_DECLARE");
+ lines.replaceInStrings(QRegExp("#define Q[A-Z_]*\\(C\\)"), "");
+
+ if (lines.size() == 4) {
+ sequentialIteratorDefinition = lines[0];
+ mutableSequentialIteratorDefinition = lines[1];
+ associativeIteratorDefinition = lines[2];
+ mutableAssociativeIteratorDefinition = lines[3];
+ } else {
+ location.warning(tr("The qiterator.h hack failed"));
+ }
+}
+
+void CppCodeParser::instantiateIteratorMacro(const QString &container,
+ const QString &includeFile,
+ const QString &macroDef,
+ Tree * /* tree */)
+{
+ QString resultingCode = macroDef;
+ resultingCode.replace(QRegExp("\\bC\\b"), container);
+ resultingCode.replace(QRegExp("\\s*##\\s*"), "");
+
+ Location loc(includeFile); // hack to get the include file for free
+ QByteArray latin1 = resultingCode.toLatin1();
+ Tokenizer stringTokenizer(loc, latin1);
+ tokenizer = &stringTokenizer;
+ readToken();
+ matchDeclList(tre->root());
+}
+
+void CppCodeParser::createExampleFileNodes(FakeNode *fake)
+{
+ QString examplePath = fake->name();
+
+ // we can assume that this file always exists
+ QString proFileName = examplePath + "/" +
+ examplePath.split("/").last() + ".pro";
+
+ QString userFriendlyFilePath;
+ QString fullPath = Config::findFile(fake->doc().location(),
+ exampleFiles,
+ exampleDirs,
+ proFileName,
+ userFriendlyFilePath);
+ if (fullPath.isEmpty()) {
+ QString tmp = proFileName;
+ proFileName = examplePath + "/" + "qbuild.pro";
+ userFriendlyFilePath.clear();
+ fullPath = Config::findFile(fake->doc().location(),
+ exampleFiles,
+ exampleDirs,
+ proFileName,
+ userFriendlyFilePath);
+ if (fullPath.isEmpty()) {
+ fake->doc().location().warning(
+ tr("Cannot find file '%1' or '%2'").arg(tmp).arg(proFileName));
+ return;
+ }
+ }
+
+ int sizeOfBoringPartOfName = fullPath.size() - proFileName.size();
+ fullPath.truncate(fullPath.lastIndexOf('/'));
+
+ QStringList exampleFiles = Config::getFilesHere(fullPath,
+ exampleNameFilter);
+ if (!exampleFiles.isEmpty()) {
+ // move main.cpp and to the end, if it exists
+ QString mainCpp;
+ QMutableStringListIterator i(exampleFiles);
+ i.toBack();
+ while (i.hasPrevious()) {
+ QString fileName = i.previous();
+ if (fileName.endsWith("/main.cpp")) {
+ mainCpp = fileName;
+ i.remove();
+ }
+ else if (fileName.contains("/qrc_") || fileName.contains("/moc_")
+ || fileName.contains("/ui_"))
+ i.remove();
+ }
+ if (!mainCpp.isEmpty())
+ exampleFiles.append(mainCpp);
+
+ // add any qmake Qt resource files and qmake project files
+ exampleFiles += Config::getFilesHere(fullPath, "*.qrc *.pro");
+ }
+
+ foreach (const QString &exampleFile, exampleFiles)
+ (void) new FakeNode(fake,
+ exampleFile.mid(sizeOfBoringPartOfName),
+ FakeNode::File);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/cppcodeparser.h b/tools/qdoc3/cppcodeparser.h
new file mode 100644
index 0000000000..e672654567
--- /dev/null
+++ b/tools/qdoc3/cppcodeparser.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ cppcodeparser.h
+*/
+
+#ifndef CPPCODEPARSER_H
+#define CPPCODEPARSER_H
+
+#include <qregexp.h>
+
+#include "codeparser.h"
+#include "node.h"
+
+QT_BEGIN_NAMESPACE
+
+class ClassNode;
+class CodeChunk;
+class CppCodeParserPrivate;
+class FunctionNode;
+class InnerNode;
+class Tokenizer;
+
+class CppCodeParser : public CodeParser
+{
+ public:
+ CppCodeParser();
+ ~CppCodeParser();
+
+ virtual void initializeParser(const Config& config);
+ virtual void terminateParser();
+ virtual QString language();
+ virtual QString headerFileNameFilter();
+ virtual QString sourceFileNameFilter();
+ virtual void parseHeaderFile(const Location& location,
+ const QString& filePath,
+ Tree *tree);
+ virtual void parseSourceFile(const Location& location,
+ const QString& filePath,
+ Tree *tree);
+ virtual void doneParsingHeaderFiles(Tree *tree);
+ virtual void doneParsingSourceFiles(Tree *tree);
+
+ const FunctionNode *findFunctionNode(const QString& synopsis,
+ Tree *tree,
+ Node *relative = 0,
+ bool fuzzy = false);
+
+ protected:
+ virtual QSet<QString> topicCommands();
+ virtual Node *processTopicCommand(const Doc& doc,
+ const QString& command,
+ const QString& arg);
+ virtual QSet<QString> otherMetaCommands();
+ virtual void processOtherMetaCommand(const Doc& doc,
+ const QString& command,
+ const QString& arg,
+ Node *node);
+ void processOtherMetaCommands(const Doc& doc, Node *node);
+
+ private:
+ void reset(Tree *tree);
+ void readToken();
+ const Location& location();
+ QString previousLexeme();
+ QString lexeme();
+ bool match(int target);
+ bool matchCompat();
+ bool matchTemplateAngles(CodeChunk *type = 0);
+ bool matchTemplateHeader();
+ bool matchDataType(CodeChunk *type, QString *var = 0);
+ bool matchParameter(FunctionNode *func);
+ bool matchFunctionDecl(InnerNode *parent,
+ QStringList *parentPathPtr = 0,
+ FunctionNode **funcPtr = 0,
+ const QString &templateStuff = QString());
+ bool matchBaseSpecifier(ClassNode *classe, bool isClass);
+ bool matchBaseList(ClassNode *classe, bool isClass);
+ bool matchClassDecl(InnerNode *parent,
+ const QString &templateStuff = QString());
+ bool matchNamespaceDecl(InnerNode *parent);
+ bool matchUsingDecl();
+ bool matchEnumItem(InnerNode *parent, EnumNode *enume);
+ bool matchEnumDecl(InnerNode *parent);
+ bool matchTypedefDecl(InnerNode *parent);
+ bool matchProperty(InnerNode *parent);
+ bool matchDeclList(InnerNode *parent);
+ bool matchDocsAndStuff();
+ bool makeFunctionNode(const QString &synopsis,
+ QStringList *parentPathPtr,
+ FunctionNode **funcPtr,
+ InnerNode *root = 0);
+ void parseQiteratorDotH(const Location &location, const QString &filePath);
+ void instantiateIteratorMacro(const QString &container,
+ const QString &includeFile,
+ const QString &macroDef,
+ Tree *tree);
+ void createExampleFileNodes(FakeNode *fake);
+
+ QMap<QString, Node::Type> nodeTypeMap;
+ Tree *tre;
+ Tokenizer *tokenizer;
+ int tok;
+ Node::Access access;
+ FunctionNode::Metaness metaness;
+ QString moduleName;
+ QStringList lastPath;
+ QRegExp varComment;
+ QRegExp sep;
+
+ QString sequentialIteratorDefinition;
+ QString mutableSequentialIteratorDefinition;
+ QString associativeIteratorDefinition;
+ QString mutableAssociativeIteratorDefinition;
+ QSet<QString> usedNamespaces;
+ QMap<QString, QString> sequentialIteratorClasses;
+ QMap<QString, QString> mutableSequentialIteratorClasses;
+ QMap<QString, QString> associativeIteratorClasses;
+ QMap<QString, QString> mutableAssociativeIteratorClasses;
+
+ static QStringList exampleFiles;
+ static QStringList exampleDirs;
+ QString exampleNameFilter;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/cpptoqsconverter.cpp b/tools/qdoc3/cpptoqsconverter.cpp
new file mode 100644
index 0000000000..dfc81bcbfa
--- /dev/null
+++ b/tools/qdoc3/cpptoqsconverter.cpp
@@ -0,0 +1,415 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ cpptoqsconverter.cpp
+*/
+
+#include "config.h"
+#include "cpptoqsconverter.h"
+
+QT_BEGIN_NAMESPACE
+
+#define CONFIG_QUICK "quick"
+#define CONFIG_INDENTSIZE "indentsize"
+
+void setTabSize( int size );
+void setIndentSize( int size );
+int columnForIndex( const QString& t, int index );
+int indentForBottomLine( const QStringList& program, QChar typedIn );
+
+static QString balancedParens = "(?:[^()]+|\\([^()]*\\))*";
+
+QRegExp CppToQsConverter::qClassRegExp;
+QRegExp CppToQsConverter::addressOperatorRegExp;
+QRegExp CppToQsConverter::gulbrandsenRegExp;
+int CppToQsConverter::tabSize;
+
+ClassNode *CppToQsConverter::findClassNode( Tree *qsTree,
+ const QString& qtName )
+{
+ ClassNode *classe = (ClassNode *) qsTree->findNode( QStringList(qtName), Node::Class );
+ if ( classe == 0 )
+ classe = (ClassNode *) qsTree->findNode( QStringList(qtName.mid(1)), Node::Class );
+ return classe;
+}
+
+QString CppToQsConverter::convertedDataType( Tree *qsTree,
+ const QString& leftType,
+ const QString& /* rightType */ )
+{
+ QString s = leftType;
+
+ if ( s.startsWith("const ") )
+ s = s.mid( 6 );
+ while ( s.endsWith("*") || s.endsWith("&") || s.endsWith(" ") )
+ s.truncate( s.length() - 1 );
+
+ switch ( s[0].unicode() ) {
+ case 'Q':
+ if ( s == "QCString" ) {
+ return "String";
+ } else {
+ Node *node = findClassNode( qsTree, s );
+ if ( node == 0 ) {
+ return "";
+ } else {
+ return node->name();
+ }
+ }
+ break;
+ case 'b':
+ if ( s == "bool" )
+ return "Boolean";
+ break;
+ case 'c':
+ if ( s == "char" ) {
+ if ( leftType == "const char *" ) {
+ return "String";
+ } else {
+ return "Number";
+ }
+ }
+ break;
+ case 'd':
+ if ( s == "double" )
+ return "Number";
+ break;
+ case 'f':
+ if ( s == "float" )
+ return "Number";
+ case 'i':
+ if ( s == "int" )
+ return "Number";
+ break;
+ case 'l':
+ if ( s == "long" || s == "long int" || s == "long long" ||
+ s == "long long int" || s == "long double" )
+ return "Number";
+ break;
+ case 's':
+ if ( s == "short" || s == "short int" || s == "signed char" ||
+ s == "signed short" || s == "signed short int" || s == "signed" ||
+ s == "signed int" || s == "signed long" || s == "signed long int" )
+ return "Number";
+ break;
+ case 'u':
+ if ( s == "uchar" || s == "unsigned" || s == "unsigned char" ||
+ s == "ushort" || s == "unsigned short" ||
+ s == "unsigned short int" || s == "uint" || s == "unsigned int" ||
+ s == "ulong" || s == "unsigned long" || s == "unsigned long int" )
+ return "Number";
+ break;
+ case 'v':
+ if ( s == "void" )
+ return "";
+ }
+ return s;
+}
+
+QString CppToQsConverter::convertedCode( Tree *qsTree, const QString& code,
+ const QSet<QString>& classesWithNoQ )
+{
+ QString result;
+ QStringList program;
+ QStringList comments;
+ int programWidth = 0;
+
+ QStringList originalLines = code.split("\n");
+ QStringList::ConstIterator ol = originalLines.begin();
+ while ( ol != originalLines.end() ) {
+ QString code = (*ol).trimmed();
+ QString comment;
+
+ int slashSlash = code.indexOf( "//" );
+ if ( slashSlash != -1 ) {
+ comment = code.mid( slashSlash );
+ code.truncate( slashSlash );
+ code = code.trimmed();
+ }
+
+ code = convertCodeLine( qsTree, program, code, classesWithNoQ );
+ program.append( code );
+
+ comment = convertComment( qsTree, comment, classesWithNoQ );
+ comments.append( comment );
+
+ int n = indentForBottomLine( program, QChar::Null );
+ for ( int i = 0; i < n; i++ )
+ program.last().prepend( " " );
+
+ int width = columnForIndex( program.last(), program.last().length() );
+ if ( !comment.isEmpty() && width > programWidth )
+ programWidth = width;
+ ++ol;
+ }
+
+ programWidth = ( (programWidth + (tabSize - 1) + 2) / tabSize ) * tabSize;
+
+ QStringList::ConstIterator p = program.begin();
+ QStringList::ConstIterator c = comments.begin();
+ while ( c != comments.end() ) {
+ if ( c != comments.begin() )
+ result += "\n";
+
+ if ( (*p).trimmed().isEmpty() ) {
+ if ( !(*c).isEmpty() )
+ result += *p;
+ } else {
+ result += *p;
+ if ( !(*c).isEmpty() ) {
+ int i = columnForIndex( *p, (*p).length() );
+ while ( i++ < programWidth )
+ result += " ";
+ }
+ }
+ result += *c;
+ ++p;
+ ++c;
+ }
+ return result;
+}
+
+void CppToQsConverter::initialize( const Config& config )
+{
+ qClassRegExp.setPattern( "\\bQ([A-Z][A-Za-z]+)\\b" );
+ addressOperatorRegExp.setPattern( "([(\\s])[*&]([a-zA-Z])" );
+ gulbrandsenRegExp.setPattern( "\\b::\\b|->" );
+
+ tabSize = config.getInt( CONFIG_TABSIZE );
+ setTabSize( tabSize );
+
+ int size = config.getInt( CONFIG_QUICK + Config::dot + CONFIG_INDENTSIZE );
+ if ( size > 0 )
+ setIndentSize( size );
+}
+
+void CppToQsConverter::terminate()
+{
+}
+
+QString CppToQsConverter::convertCodeLine( Tree *qsTree,
+ const QStringList& program,
+ const QString& code,
+ const QSet<QString>& classesWithNoQ )
+{
+ static QString dataTypeFmt =
+ "(?!return)(?:const\\b\\s*)?[A-Za-z_]+(?:\\s*[*&])?";
+ static QRegExp funcPrototypeRegExp(
+ "(" + dataTypeFmt + ")\\s*\\b([A-Z][a-zA-Z_0-9]*::)?"
+ "([a-z][a-zA-Z_0-9]*)\\(([^);]*)(\\)?)(?:\\s*const)?" );
+ static QRegExp paramRegExp(
+ "^\\s*(" + dataTypeFmt + ")\\s*\\b([a-z][a-zA-Z_0-9]*)\\s*(,)?\\s*" );
+ static QRegExp uninitVarRegExp(
+ "(" + dataTypeFmt + ")\\s*\\b([a-z][a-zA-Z_0-9]*);" );
+ static QRegExp eqVarRegExp(
+ dataTypeFmt + "\\s*\\b([a-z][a-zA-Z_0-9]*)\\s*=(\\s*)(.*)" );
+ static QRegExp ctorVarRegExp(
+ "(" + dataTypeFmt + ")\\s*\\b([a-z][a-zA-Z_0-9]*)\\((.*)\\);" );
+ static QRegExp qdebugRegExp(
+ "q(?:Debug|Warning|Fatal)\\(\\s*(\"(?:\\\\.|[^\"])*\")\\s*"
+ "(?:,\\s*(\\S(?:[^,]*\\S)?))?\\s*\\);" );
+ static QRegExp coutRegExp( "c(?:out|err)\\b(.*);" );
+ static QRegExp lshiftRegExp( "\\s*<<\\s*" );
+ static QRegExp endlRegExp( "^endl$" );
+
+ if ( code.isEmpty() || code == "{" || code == "}" )
+ return code;
+
+ QString result;
+
+ if ( funcPrototypeRegExp.exactMatch(code) ) {
+ QString returnType = funcPrototypeRegExp.cap( 1 );
+ QString className = funcPrototypeRegExp.cap( 2 );
+ QString funcName = funcPrototypeRegExp.cap( 3 );
+ QString params = funcPrototypeRegExp.cap( 4 ).trimmed();
+ bool toBeContinued = funcPrototypeRegExp.cap( 5 ).isEmpty();
+ // ### unused
+ Q_UNUSED(toBeContinued);
+
+ className.replace( "::", "." );
+
+ result = "function " + className + funcName + "(";
+
+ if ( !params.isEmpty() && params != "void" ) {
+ result += " ";
+ int i = funcPrototypeRegExp.pos( 4 );
+ while ( (i = paramRegExp.indexIn(code, i,
+ QRegExp::CaretAtOffset)) != -1 ) {
+ QString dataType = paramRegExp.cap( 1 );
+ QString paramName = paramRegExp.cap( 2 );
+ QString comma = paramRegExp.cap( 3 );
+
+ result += paramName + " : " +
+ convertedDataType( qsTree, dataType );
+ if ( comma.isEmpty() )
+ break;
+ result += ", ";
+ i += paramRegExp.matchedLength();
+ }
+ result += " ";
+ }
+
+ result += ")";
+ returnType = convertedDataType( qsTree, returnType );
+ if ( !returnType.isEmpty() )
+ result += " : " + returnType;
+ } else if ( uninitVarRegExp.exactMatch(code) ) {
+ QString dataType = uninitVarRegExp.cap( 1 );
+ QString varName = uninitVarRegExp.cap( 2 );
+
+ result = "var " + varName;
+ dataType = convertedDataType( qsTree, dataType );
+ if ( !dataType.isEmpty() )
+ result += " : " + dataType;
+ result += ";";
+ } else if ( eqVarRegExp.exactMatch(code) ) {
+ QString varName = eqVarRegExp.cap( 1 );
+ QString value = eqVarRegExp.cap( 3 );
+
+ value = convertExpr( qsTree, value, classesWithNoQ );
+ result += "var " + varName + " = " + value;
+ } else if ( ctorVarRegExp.exactMatch(code) ) {
+ QString dataType = ctorVarRegExp.cap( 1 );
+ QString varName = ctorVarRegExp.cap( 2 );
+ QString value = ctorVarRegExp.cap( 3 ).trimmed();
+
+ result += "var " + varName + " = ";
+
+ dataType = convertedDataType( qsTree, dataType );
+ value = convertExpr( qsTree, value, classesWithNoQ );
+
+ if ( dataType.isEmpty() || dataType == "String" ) {
+ if ( value.contains(",") ) {
+ result += "...";
+ } else {
+ result += value;
+ }
+ } else {
+ result += "new " + dataType;
+ if ( !value.isEmpty() )
+ result += "( " + value + " )";
+ }
+ result += ";";
+ } else if ( qdebugRegExp.exactMatch(code) ) {
+ QString fmt = qdebugRegExp.cap( 1 );
+ QString arg1 = qdebugRegExp.cap( 2 );
+
+ result += "println ";
+ int i = 0;
+ while ( i < (int) fmt.length() ) {
+ if ( fmt[i] == '%' ) {
+ int percent = i;
+ i++;
+ while ( i < (int) fmt.length() &&
+ QString("diouxXeEfFgGaAcsCSpn%\"").indexOf(fmt[i]) == -1 )
+ i++;
+ if ( fmt[i] == '%' ) {
+ result += fmt[i++];
+ } else if ( fmt[i] != '"' ) {
+ if ( percent == 1 ) {
+ result.truncate( result.length() - 1 );
+ } else {
+ result += "\" + ";
+ }
+ i++;
+ if ( arg1.endsWith(".latin1()") )
+ arg1.truncate( arg1.length() - 9 );
+ result += arg1;
+ if ( i == (int) fmt.length() - 1 ) {
+ i++;
+ } else {
+ result += " + \"";
+ }
+ }
+ } else {
+ result += fmt[i++];
+ }
+ }
+ result += ";";
+ } else if ( coutRegExp.exactMatch(code) &&
+ program.filter("var cout").isEmpty() ) {
+ QStringList args = coutRegExp.cap(1).split(lshiftRegExp);
+ args.replaceInStrings( endlRegExp, "\"\\n\"" );
+ if ( args.last() == "\"\\n\"" ) {
+ args.erase( args.end() - 1 );
+ if ( args.isEmpty() )
+ args << "\"\"";
+ result += "println ";
+ } else {
+ result += "print ";
+ }
+ result += args.join( " + " ) + ";";
+ } else {
+ result = convertExpr( qsTree, code, classesWithNoQ );
+ }
+ return result;
+}
+
+QString CppToQsConverter::convertComment( Tree * /* qsTree */,
+ const QString& comment,
+ const QSet<QString>& classesWithNoQ )
+
+{
+ QString result = comment;
+
+ result.replace( "TRUE", "true" );
+ result.replace( "FALSE", "false" );
+ result.replace( addressOperatorRegExp, "\\1\\2" );
+ result.replace( gulbrandsenRegExp, "." );
+
+ int i = 0;
+ while ( (i = result.indexOf(qClassRegExp, i)) != -1 ) {
+ if ( classesWithNoQ.contains(qClassRegExp.cap(1)) )
+ result.remove( i, 1 );
+ i++;
+ }
+ return result;
+}
+
+QString CppToQsConverter::convertExpr( Tree *qsTree, const QString& expr,
+ const QSet<QString>& classesWithNoQ )
+{
+ // suboptimal
+ return convertComment( qsTree, expr, classesWithNoQ );
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/cpptoqsconverter.h b/tools/qdoc3/cpptoqsconverter.h
new file mode 100644
index 0000000000..baf801c7a7
--- /dev/null
+++ b/tools/qdoc3/cpptoqsconverter.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ cpptoqsconverter.h
+*/
+
+#ifndef CPPTOQSCONVERTER_H
+#define CPPTOQSCONVERTER_H
+
+#include <qregexp.h>
+
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+class CppToQsConverter
+{
+public:
+ CppToQsConverter() { }
+
+ ClassNode *findClassNode( Tree *qsTree, const QString& qtName );
+ QString convertedDataType( Tree *qsTree, const QString& leftType,
+ const QString& rightType = "" );
+ QString convertedCode( Tree *qsTree, const QString& code,
+ const QSet<QString>& classesWithNoQ );
+
+ static void initialize( const Config& config );
+ static void terminate();
+
+private:
+ void clearState();
+ QString convertCodeLine( Tree *qsTree, const QStringList& program,
+ const QString& code,
+ const QSet<QString>& classesWithNoQ );
+ QString convertComment( Tree *qsTree, const QString& comment,
+ const QSet<QString>& classesWithNoQ );
+ QString convertExpr( Tree *qsTree, const QString& expr,
+ const QSet<QString>& classesWithNoQ );
+ void updateDelimDepths( const QString& code );
+
+ static QRegExp qClassRegExp;
+ static QRegExp addressOperatorRegExp;
+ static QRegExp gulbrandsenRegExp;
+ static int tabSize;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/dcfsection.cpp b/tools/qdoc3/dcfsection.cpp
new file mode 100644
index 0000000000..5bff0708a5
--- /dev/null
+++ b/tools/qdoc3/dcfsection.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+
+#include "dcfsection.h"
+#include "htmlgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+void appendDcfSubSection( DcfSection *dcfSect, const DcfSection& sub )
+{
+ dcfSect->subsections.append( sub );
+}
+
+void appendDcfSubSections( DcfSection *dcfSect, const QList<DcfSection>& subs )
+{
+ dcfSect->subsections += subs;
+}
+
+void generateDcfSubSections( QString indent, QTextStream& out, const DcfSection& sect )
+{
+ QList<DcfSection>::const_iterator ss = sect.subsections.constBegin();
+ while ( ss != sect.subsections.constEnd() ) {
+ out << indent << "<section ref=\"" << HtmlGenerator::cleanRef(HtmlGenerator::protect((*ss).ref))
+ << "\" title=\"" << HtmlGenerator::protect((*ss).title) << "\"";
+ if ((*ss).keywords.isEmpty() && (*ss).subsections.isEmpty()) {
+ out << "/>\n";
+ } else {
+ out << ">\n";
+ QString indentIndent = indent + " ";
+ QList<QPair<QString, QString> >::const_iterator k = (*ss).keywords.constBegin();
+ while ( k != (*ss).keywords.constEnd() ) {
+ out << indentIndent << "<keyword ref=\"" << HtmlGenerator::cleanRef((*k).second) << "\">"
+ << HtmlGenerator::protect((*k).first) << "</keyword>\n";
+ ++k;
+ }
+
+ generateDcfSubSections( indentIndent, out, *ss );
+ out << indent << "</section>\n";
+ }
+ ++ss;
+ }
+ out.flush();
+}
+
+void generateDcfSections( const DcfSection& rootSect, const QString& fileName,
+ const QString& /* category */ )
+{
+ QFile file(fileName);
+ if (!file.open(QFile::WriteOnly | QFile::Text))
+ return ;
+
+ QTextStream out(&file);
+
+ QString icon = QFileInfo(fileName).baseName() + ".png";
+
+ out << "<!DOCTYPE DCF>\n";
+ out << "<DCF ref=\"" << HtmlGenerator::cleanRef(HtmlGenerator::protect(rootSect.ref));
+ if (icon != "qmake.png")
+ out << "\" icon=\"" << HtmlGenerator::protect(icon);
+ out << "\" imagedir=\"../../gif\" title=\"" << HtmlGenerator::protect(rootSect.title) +
+ "\">\n";
+
+ generateDcfSubSections( "", out, rootSect );
+
+ out << "</DCF>\n";
+ out.flush();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/dcfsection.h b/tools/qdoc3/dcfsection.h
new file mode 100644
index 0000000000..91d31ed3de
--- /dev/null
+++ b/tools/qdoc3/dcfsection.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DCFSECTION_H
+#define DCFSECTION_H
+
+#include <qlist.h>
+#include <qpair.h>
+#include <qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTextStream;
+
+struct DcfSection
+{
+ QString title;
+ QString ref;
+ QList<QPair<QString, QString> > keywords;
+ QList<DcfSection> subsections;
+};
+
+inline bool operator<( const DcfSection& s1, const DcfSection& s2 ) {
+ QString title1 = s1.title;
+ QString title2 = s2.title;
+
+ // cheat with Q3 classes
+ if (title1.startsWith("Q3"))
+ title1.insert(1, '~');
+ if (title2.startsWith("Q3"))
+ title2.insert(1, '~');
+
+ int delta = title1.toLower().compare( title2.toLower() );
+ if ( delta == 0 ) {
+ delta = title1.compare( title2 );
+ if ( delta == 0 )
+ delta = s1.ref.localeAwareCompare( s2.ref );
+ }
+ return delta < 0;
+}
+
+inline bool operator>( const DcfSection& s1, const DcfSection& s2 ) { return s2 < s1; }
+inline bool operator<=( const DcfSection& s1, const DcfSection& s2 ) { return !( s2 < s1 ); }
+inline bool operator>=( const DcfSection& s1, const DcfSection& s2 ) { return !( s1 < s2 ); }
+inline bool operator==( const DcfSection& s1, const DcfSection& s2 ) { return &s1 == &s2; }
+inline bool operator!=( const DcfSection& s1, const DcfSection& s2 ) { return !( s1 == s2 ); }
+
+void appendDcfSubSection(DcfSection *dcfSect, const DcfSection &sub);
+void appendDcfSubSections(DcfSection *dcfSect, const QList<DcfSection> &subs);
+void generateDcfSubSections(QString indent, QTextStream &out, const DcfSection &sect);
+void generateDcfSections(const DcfSection &rootSect, const QString& fileName,
+ const QString& category );
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp
new file mode 100644
index 0000000000..61d0ed6c93
--- /dev/null
+++ b/tools/qdoc3/doc.cpp
@@ -0,0 +1,5036 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "doc.h"
+#include "codemarker.h"
+#include "editdistance.h"
+#include "openedlist.h"
+#include "quoter.h"
+#include "text.h"
+#include "tokenizer.h"
+#include <qdatetime.h>
+#include <qdebug.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qhash.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <ctype.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QSet<QString>, null_Set_QString)
+Q_GLOBAL_STATIC(QStringList, null_QStringList)
+Q_GLOBAL_STATIC(QList<Text>, null_QList_Text)
+Q_GLOBAL_STATIC(QStringMap, null_QStringMap)
+
+struct Macro
+{
+ QString defaultDef;
+ Location defaultDefLocation;
+ QStringMap otherDefs;
+ int numParams;
+};
+
+enum {
+ CMD_A, CMD_ABSTRACT, CMD_BADCODE, CMD_BASENAME, CMD_BOLD,
+ CMD_BRIEF, CMD_C, CMD_CAPTION, CMD_CHAPTER, CMD_CODE,
+ CMD_CODELINE, CMD_DOTS, CMD_ELSE, CMD_ENDABSTRACT,
+ CMD_ENDCHAPTER, CMD_ENDCODE, CMD_ENDFOOTNOTE, CMD_ENDIF,
+ CMD_ENDLEGALESE, CMD_ENDLINK, CMD_ENDLIST, CMD_ENDOMIT,
+ CMD_ENDPART, CMD_ENDQUOTATION, CMD_ENDRAW, CMD_ENDSECTION1,
+ CMD_ENDSECTION2, CMD_ENDSECTION3, CMD_ENDSECTION4,
+ CMD_ENDSIDEBAR, CMD_ENDTABLE, CMD_EXPIRE, CMD_FOOTNOTE,
+ CMD_GENERATELIST, CMD_GRANULARITY, CMD_HEADER, CMD_I,
+ CMD_IF, CMD_IMAGE, CMD_INCLUDE, CMD_INLINEIMAGE, CMD_INDEX,
+ CMD_KEYWORD, CMD_L, CMD_LEGALESE, CMD_LINK, CMD_LIST,
+ CMD_META, CMD_NEWCODE, CMD_O, CMD_OLDCODE, CMD_OMIT,
+ CMD_OMITVALUE, CMD_OVERLOAD,
+ CMD_PART, CMD_PRINTLINE, CMD_PRINTTO,
+ CMD_PRINTUNTIL, CMD_QUOTATION, CMD_QUOTEFILE,
+ CMD_QUOTEFROMFILE, CMD_QUOTEFUNCTION, CMD_RAW, CMD_ROW,
+ CMD_SA, CMD_SECTION1, CMD_SECTION2, CMD_SECTION3,
+ CMD_SECTION4, CMD_SIDEBAR, CMD_SKIPLINE, CMD_SKIPTO,
+ CMD_SKIPUNTIL, CMD_SNIPPET, CMD_SUB, CMD_SUP, CMD_TABLE,
+ CMD_TABLEOFCONTENTS, CMD_TARGET, CMD_TT, CMD_UNDERLINE,
+ CMD_UNICODE, CMD_VALUE, CMD_WARNING,
+#ifdef QDOC_QML
+ CMD_QML, CMD_ENDQML, CMD_CPP, CMD_ENDCPP, CMD_QMLTEXT,
+ CMD_ENDQMLTEXT, CMD_CPPTEXT, CMD_ENDCPPTEXT,
+#endif
+ NOT_A_CMD
+};
+
+static struct {
+ const char *english;
+ int no;
+ QString *alias;
+} cmds[] = {
+ { "a", CMD_A, 0 },
+ { "abstract", CMD_ABSTRACT, 0 },
+ { "badcode", CMD_BADCODE, 0 },
+ { "basename", CMD_BASENAME, 0 }, // ### don't document for now
+ { "bold", CMD_BOLD, 0 },
+ { "brief", CMD_BRIEF, 0 },
+ { "c", CMD_C, 0 },
+ { "caption", CMD_CAPTION, 0 },
+ { "chapter", CMD_CHAPTER, 0 },
+ { "code", CMD_CODE, 0 },
+ { "codeline", CMD_CODELINE, 0},
+ { "dots", CMD_DOTS, 0 },
+ { "else", CMD_ELSE, 0 },
+ { "endabstract", CMD_ENDABSTRACT, 0 },
+ { "endchapter", CMD_ENDCHAPTER, 0 },
+ { "endcode", CMD_ENDCODE, 0 },
+ { "endfootnote", CMD_ENDFOOTNOTE, 0 },
+ { "endif", CMD_ENDIF, 0 },
+ { "endlegalese", CMD_ENDLEGALESE, 0 },
+ { "endlink", CMD_ENDLINK, 0 },
+ { "endlist", CMD_ENDLIST, 0 },
+ { "endomit", CMD_ENDOMIT, 0 },
+ { "endpart", CMD_ENDPART, 0 },
+ { "endquotation", CMD_ENDQUOTATION, 0 },
+ { "endraw", CMD_ENDRAW, 0 },
+ { "endsection1", CMD_ENDSECTION1, 0 }, // ### don't document for now
+ { "endsection2", CMD_ENDSECTION2, 0 }, // ### don't document for now
+ { "endsection3", CMD_ENDSECTION3, 0 }, // ### don't document for now
+ { "endsection4", CMD_ENDSECTION4, 0 }, // ### don't document for now
+ { "endsidebar", CMD_ENDSIDEBAR, 0 },
+ { "endtable", CMD_ENDTABLE, 0 },
+ { "expire", CMD_EXPIRE, 0 },
+ { "footnote", CMD_FOOTNOTE, 0 },
+ { "generatelist", CMD_GENERATELIST, 0 },
+ { "granularity", CMD_GRANULARITY, 0 }, // ### don't document for now
+ { "header", CMD_HEADER, 0 },
+ { "i", CMD_I, 0 },
+ { "if", CMD_IF, 0 },
+ { "image", CMD_IMAGE, 0 },
+ { "include", CMD_INCLUDE, 0 },
+ { "inlineimage", CMD_INLINEIMAGE, 0 },
+ { "index", CMD_INDEX, 0 }, // ### don't document for now
+ { "keyword", CMD_KEYWORD, 0 },
+ { "l", CMD_L, 0 },
+ { "legalese", CMD_LEGALESE, 0 },
+ { "link", CMD_LINK, 0 },
+ { "list", CMD_LIST, 0 },
+ { "meta", CMD_META, 0 },
+ { "newcode", CMD_NEWCODE, 0 },
+ { "o", CMD_O, 0 },
+ { "oldcode", CMD_OLDCODE, 0 },
+ { "omit", CMD_OMIT, 0 },
+ { "omitvalue", CMD_OMITVALUE, 0 },
+ { "overload", CMD_OVERLOAD, 0 },
+ { "part", CMD_PART, 0 },
+ { "printline", CMD_PRINTLINE, 0 },
+ { "printto", CMD_PRINTTO, 0 },
+ { "printuntil", CMD_PRINTUNTIL, 0 },
+ { "quotation", CMD_QUOTATION, 0 },
+ { "quotefile", CMD_QUOTEFILE, 0 },
+ { "quotefromfile", CMD_QUOTEFROMFILE, 0 },
+ { "quotefunction", CMD_QUOTEFUNCTION, 0 }, // ### don't document for now
+ { "raw", CMD_RAW, 0 },
+ { "row", CMD_ROW, 0 },
+ { "sa", CMD_SA, 0 },
+ { "section1", CMD_SECTION1, 0 },
+ { "section2", CMD_SECTION2, 0 },
+ { "section3", CMD_SECTION3, 0 },
+ { "section4", CMD_SECTION4, 0 },
+ { "sidebar", CMD_SIDEBAR, 0 }, // ### don't document for now
+ { "skipline", CMD_SKIPLINE, 0 },
+ { "skipto", CMD_SKIPTO, 0 },
+ { "skipuntil", CMD_SKIPUNTIL, 0 },
+ { "snippet", CMD_SNIPPET, 0 },
+ { "sub", CMD_SUB, 0 },
+ { "sup", CMD_SUP, 0 },
+ { "table", CMD_TABLE, 0 },
+ { "tableofcontents", CMD_TABLEOFCONTENTS, 0 },
+ { "target", CMD_TARGET, 0 },
+ { "tt", CMD_TT, 0 },
+ { "underline", CMD_UNDERLINE, 0 },
+ { "unicode", CMD_UNICODE, 0 },
+ { "value", CMD_VALUE, 0 },
+ { "warning", CMD_WARNING, 0 },
+#ifdef QDOC_QML
+ { "qml", CMD_QML, 0 },
+ { "endqml", CMD_ENDQML, 0 },
+ { "cpp", CMD_CPP, 0 },
+ { "endcpp", CMD_ENDCPP, 0 },
+ { "qmltext", CMD_QMLTEXT, 0 },
+ { "endqmltext", CMD_ENDQMLTEXT, 0 },
+ { "cpptext", CMD_CPPTEXT, 0 },
+ { "endcpptext", CMD_ENDCPPTEXT, 0 },
+#endif
+ { 0, 0, 0 }
+};
+
+typedef QHash<QString, int> QHash_QString_int;
+typedef QHash<QString, Macro> QHash_QString_Macro;
+
+Q_GLOBAL_STATIC(QStringMap, aliasMap)
+Q_GLOBAL_STATIC(QHash_QString_int, cmdHash)
+Q_GLOBAL_STATIC(QHash_QString_Macro, macroHash)
+
+class DocPrivateExtra
+{
+ public:
+ QString baseName;
+ Doc::SectioningUnit granularity;
+ Doc::SectioningUnit sectioningUnit; // ###
+ QList<Atom*> tableOfContents;
+ QList<int> tableOfContentsLevels;
+ QList<Atom*> keywords;
+ QList<Atom*> targets;
+ QStringMap metaMap;
+
+ DocPrivateExtra()
+ : granularity(Doc::Part) { }
+};
+
+struct Shared // ### get rid of
+{
+ Shared()
+ : count(1) { }
+ void ref() { ++count; }
+ bool deref() { return (--count == 0); }
+
+ int count;
+};
+
+static QString cleanLink(const QString &link)
+{
+ int colonPos = link.indexOf(':');
+ if ((colonPos == -1) ||
+ (!link.startsWith("file:") && !link.startsWith("mailto:")))
+ return link;
+ return link.mid(colonPos + 1).simplified();
+}
+
+class DocPrivate : public Shared
+{
+ public:
+ DocPrivate(const Location& start = Location::null,
+ const Location& end = Location::null,
+ const QString& source = "");
+ ~DocPrivate();
+
+ void addAlso(const Text& also);
+ void constructExtra();
+ bool isEnumDocSimplifiable() const;
+
+ // ### move some of this in DocPrivateExtra
+ Location start_loc;
+ Location end_loc;
+ QString src;
+ Text text;
+ QSet<QString> params;
+ QList<Text> alsoList;
+ QStringList enumItemList;
+ QStringList omitEnumItemList;
+ QSet<QString> metacommandsUsed;
+ QCommandMap metaCommandMap;
+ bool hasLegalese : 1;
+ bool hasSectioningUnits : 1;
+ DocPrivateExtra *extra;
+};
+
+DocPrivate::DocPrivate(const Location& start,
+ const Location& end,
+ const QString& source)
+ : start_loc(start),
+ end_loc(end),
+ src(source),
+ hasLegalese(false),
+ hasSectioningUnits(false),
+ extra(0)
+{
+ // nothing.
+}
+
+DocPrivate::~DocPrivate()
+{
+ delete extra;
+}
+
+void DocPrivate::addAlso(const Text& also)
+{
+ alsoList.append(also);
+}
+
+void DocPrivate::constructExtra()
+{
+ if (extra == 0)
+ extra = new DocPrivateExtra;
+}
+
+bool DocPrivate::isEnumDocSimplifiable() const
+{
+ bool justMetColon = false;
+ int numValueTables = 0;
+
+ const Atom *atom = text.firstAtom();
+ while (atom) {
+ if (atom->type() == Atom::AutoLink || atom->type() == Atom::String) {
+ justMetColon = atom->string().endsWith(":");
+ }
+ else if ((atom->type() == Atom::ListLeft) &&
+ (atom->string() == ATOM_LIST_VALUE)) {
+ if (justMetColon || numValueTables > 0)
+ return false;
+ ++numValueTables;
+ }
+ atom = atom->next();
+ }
+ return true;
+}
+
+class DocParser
+{
+ public:
+ void parse(const QString &source,
+ DocPrivate *docPrivate,
+ const QSet<QString> &metaCommandSet);
+
+ static int endCmdFor(int cmd);
+ static QString cmdName(int cmd);
+ static QString endCmdName(int cmd);
+ static QString untabifyEtc(const QString& str);
+ static int indentLevel(const QString& str);
+ static QString unindent(int level, const QString& str);
+ static QString slashed(const QString& str);
+
+ static int tabSize;
+ static QStringList exampleFiles;
+ static QStringList exampleDirs;
+ static QStringList sourceFiles;
+ static QStringList sourceDirs;
+ static bool quoting;
+
+ private:
+ Location& location();
+ QString detailsUnknownCommand(const QSet<QString>& metaCommandSet,
+ const QString& str);
+ void checkExpiry(const QString& date);
+ void insertBaseName(const QString &baseName);
+ void insertTarget(const QString& target, bool keyword);
+ void include(const QString& fileName);
+ void startFormat(const QString& format, int cmd);
+ bool openCommand(int cmd);
+ bool closeCommand(int endCmd);
+ void startSection(Doc::SectioningUnit unit, int cmd);
+ void endSection(int unit, int endCmd);
+ void parseAlso();
+ void append(Atom::Type type, const QString& string = "");
+ void appendChar(QChar ch);
+ void appendWord(const QString &word);
+ void appendToCode(const QString &code);
+ void startNewPara();
+ void enterPara(Atom::Type leftType = Atom::ParaLeft,
+ Atom::Type rightType = Atom::ParaRight,
+ const QString& string = "");
+ void leavePara();
+ void leaveValue();
+ void leaveValueList();
+ void leaveTableRow();
+ CodeMarker *quoteFromFile();
+ void expandMacro(const QString& name, const QString& def, int numParams);
+ Doc::SectioningUnit getSectioningUnit();
+ QString getArgument(bool verbatim = false);
+ QString getOptionalArgument();
+ QString getRestOfLine();
+ QString getMetaCommandArgument(const QString &cmdStr);
+ QString getUntilEnd(int cmd);
+ QString getCode(int cmd, CodeMarker *marker);
+ QString getUnmarkedCode(int cmd);
+
+ bool isBlankLine();
+ bool isLeftBraceAhead();
+ void skipSpacesOnLine();
+ void skipSpacesOrOneEndl();
+ void skipAllSpaces();
+ void skipToNextPreprocessorCommand();
+
+ QStack<int> openedInputs;
+
+ QString in;
+ int pos;
+ int len;
+ Location cachedLoc;
+ int cachedPos;
+
+ DocPrivate *priv;
+ enum ParaState { OutsidePara, InsideSingleLinePara, InsideMultiLinePara };
+ ParaState paraState;
+ bool inTableHeader;
+ bool inTableRow;
+ bool inTableItem;
+ bool indexStartedPara; // ### rename
+ Atom::Type pendingParaLeftType;
+ Atom::Type pendingParaRightType;
+ QString pendingParaString;
+
+ int braceDepth;
+ int minIndent;
+ Doc::SectioningUnit currentSectioningUnit;
+ QMap<QString, Location> targetMap;
+ QMap<int, QString> pendingFormats;
+ QStack<int> openedCommands;
+ QStack<OpenedList> openedLists;
+ Quoter quoter;
+};
+
+int DocParser::tabSize;
+QStringList DocParser::exampleFiles;
+QStringList DocParser::exampleDirs;
+QStringList DocParser::sourceFiles;
+QStringList DocParser::sourceDirs;
+bool DocParser::quoting;
+
+/*!
+ Parse the \a source string to build a Text data structure
+ in \a docPrivate. The Text data structure is a linked list
+ of Atoms.
+
+ \a metaCommandSet is the set of metacommands that may be
+ found in \a source. These metacommands are not markup text
+ commands. They are topic commands and related metacommands.
+ */
+void DocParser::parse(const QString& source,
+ DocPrivate *docPrivate,
+ const QSet<QString>& metaCommandSet)
+{
+ in = source;
+ pos = 0;
+ len = in.length();
+ cachedLoc = docPrivate->start_loc;
+ cachedPos = 0;
+ priv = docPrivate;
+ priv->text << Atom::Nop;
+
+ paraState = OutsidePara;
+ inTableHeader = false;
+ inTableRow = false;
+ inTableItem = false;
+ indexStartedPara = false;
+ pendingParaLeftType = Atom::Nop;
+ pendingParaRightType = Atom::Nop;
+
+ braceDepth = 0;
+ minIndent = INT_MAX;
+ currentSectioningUnit = Doc::Book;
+ openedCommands.push(CMD_OMIT);
+ quoter.reset();
+
+ CodeMarker *marker = 0;
+ Atom *currentLinkAtom = 0;
+ QString x;
+ QStack<bool> preprocessorSkipping;
+ int numPreprocessorSkipping = 0;
+
+ while (pos < len) {
+ QChar ch = in.at(pos);
+
+ switch (ch.unicode()) {
+ case '\\':
+ {
+ QString cmdStr;
+ pos++;
+ while (pos < len) {
+ ch = in.at(pos);
+ if (ch.isLetterOrNumber()) {
+ cmdStr += ch;
+ pos++;
+ }
+ else {
+ break;
+ }
+ }
+ if (cmdStr.isEmpty()) {
+ if (pos < len) {
+ enterPara();
+ if (in.at(pos).isSpace()) {
+ skipAllSpaces();
+ appendChar(QLatin1Char(' '));
+ }
+ else {
+ appendChar(in.at(pos++));
+ }
+ }
+ }
+ else {
+ int cmd = cmdHash()->value(cmdStr,NOT_A_CMD);
+ switch (cmd) {
+ case CMD_A:
+ enterPara();
+ x = getArgument();
+ append(Atom::FormattingLeft,ATOM_FORMATTING_PARAMETER);
+ append(Atom::String, x);
+ append(Atom::FormattingRight,ATOM_FORMATTING_PARAMETER);
+ priv->params.insert(x);
+ break;
+ case CMD_ABSTRACT:
+ if (openCommand(cmd)) {
+ leavePara();
+ append(Atom::AbstractLeft);
+ }
+ break;
+ case CMD_BADCODE:
+ leavePara();
+#ifdef QDOC2DOX
+ if (DoxWriter::isDoxPass())
+ append(Atom::CodeBad,getUnmarkedCode(CMD_BADCODE));
+ else
+ append(Atom::CodeBad,getCode(CMD_BADCODE, marker));
+#else
+ append(Atom::CodeBad,getCode(CMD_BADCODE, marker));
+#endif
+ break;
+ case CMD_BASENAME:
+ leavePara();
+ insertBaseName(getArgument());
+ break;
+ case CMD_BOLD:
+ startFormat(ATOM_FORMATTING_BOLD, cmd);
+ break;
+ case CMD_BRIEF:
+ leavePara();
+ enterPara(Atom::BriefLeft, Atom::BriefRight);
+ break;
+ case CMD_C:
+ enterPara();
+ x = untabifyEtc(getArgument(true));
+#ifdef QDOC2DOX
+ if (DoxWriter::isDoxPass())
+ append(Atom::C, x);
+ else {
+ marker = CodeMarker::markerForCode(x);
+ append(Atom::C, marker->markedUpCode(x, 0, ""));
+ }
+#else
+ marker = CodeMarker::markerForCode(x);
+ append(Atom::C, marker->markedUpCode(x, 0, ""));
+#endif
+ break;
+ case CMD_CAPTION:
+ leavePara();
+ /* ... */
+ break;
+ case CMD_CHAPTER:
+ startSection(Doc::Chapter, cmd);
+ break;
+ case CMD_CODE:
+ leavePara();
+#ifdef QDOC2DOX
+ if (DoxWriter::isDoxPass())
+ append(Atom::Code, getUnmarkedCode(CMD_CODE));
+ else
+ append(Atom::Code, getCode(CMD_CODE, marker));
+#else
+ append(Atom::Code, getCode(CMD_CODE, marker));
+#endif
+ break;
+#ifdef QDOC_QML
+ case CMD_QML:
+ leavePara();
+ append(Atom::Qml, getCode(CMD_QML, marker));
+ break;
+ case CMD_QMLTEXT:
+ append(Atom::QmlText);
+ break;
+#endif
+ case CMD_CODELINE:
+ {
+#ifdef QDOC2DOX
+ if (!quoting && !DoxWriter::isDoxPass()) {
+ if (priv->text.lastAtom()->type() == Atom::Code
+ && priv->text.lastAtom()->string().endsWith("\n\n"))
+ priv->text.lastAtom()->chopString();
+ appendToCode("\n");
+ } lse {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, " ");
+ }
+#else
+ if (!quoting) {
+ if (priv->text.lastAtom()->type() == Atom::Code
+ && priv->text.lastAtom()->string().endsWith("\n\n"))
+ priv->text.lastAtom()->chopString();
+ appendToCode("\n");
+ }
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, " ");
+ }
+#endif
+ }
+ break;
+ case CMD_DOTS:
+ {
+#ifdef QDOC2DOX
+ if (DoxWriter::isDoxPass()) {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, " ...");
+ }
+ else if (!quoting) {
+ if (priv->text.lastAtom()->type() == Atom::Code
+ && priv->text.lastAtom()->string().endsWith("\n\n"))
+ priv->text.lastAtom()->chopString();
+
+ QString arg = getOptionalArgument();
+ int indent = 4;
+ if (!arg.isEmpty())
+ indent = arg.toInt();
+ for (int i = 0; i < indent; ++i)
+ appendToCode(" ");
+ appendToCode("...\n");
+ }
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ QString arg = getOptionalArgument();
+ if (arg.isEmpty())
+ arg = "4";
+ append(Atom::CodeQuoteArgument, arg);
+ }
+#else
+ if (!quoting) {
+ if (priv->text.lastAtom()->type() == Atom::Code
+ && priv->text.lastAtom()->string().endsWith("\n\n"))
+ priv->text.lastAtom()->chopString();
+
+ QString arg = getOptionalArgument();
+ int indent = 4;
+ if (!arg.isEmpty())
+ indent = arg.toInt();
+ for (int i = 0; i < indent; ++i)
+ appendToCode(" ");
+ appendToCode("...\n");
+ }
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ QString arg = getOptionalArgument();
+ if (arg.isEmpty())
+ arg = "4";
+ append(Atom::CodeQuoteArgument, arg);
+ }
+#endif
+ }
+ break;
+ case CMD_ELSE:
+ if (preprocessorSkipping.size() > 0) {
+ if (preprocessorSkipping.top()) {
+ --numPreprocessorSkipping;
+ }
+ else {
+ ++numPreprocessorSkipping;
+ }
+ preprocessorSkipping.top() = !preprocessorSkipping.top();
+ (void)getRestOfLine(); // ### should ensure that it's empty
+ if (numPreprocessorSkipping)
+ skipToNextPreprocessorCommand();
+ }
+ else {
+ location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_ELSE)));
+ }
+ break;
+ case CMD_ENDABSTRACT:
+ if (closeCommand(cmd)) {
+ leavePara();
+ append(Atom::AbstractRight);
+ }
+ break;
+ case CMD_ENDCHAPTER:
+ endSection(0, cmd);
+ break;
+ case CMD_ENDCODE:
+ closeCommand(cmd);
+ break;
+#ifdef QDOC_QML
+ case CMD_ENDQML:
+ closeCommand(cmd);
+ break;
+ case CMD_ENDQMLTEXT:
+ append(Atom::EndQmlText);
+ break;
+#endif
+ case CMD_ENDFOOTNOTE:
+ if (closeCommand(cmd)) {
+ leavePara();
+ append(Atom::FootnoteRight);
+ paraState = InsideMultiLinePara; // ###
+ }
+ break;
+ case CMD_ENDIF:
+ if (preprocessorSkipping.count() > 0) {
+ if (preprocessorSkipping.pop())
+ --numPreprocessorSkipping;
+ (void)getRestOfLine(); // ### should ensure that it's empty
+ if (numPreprocessorSkipping)
+ skipToNextPreprocessorCommand();
+ }
+ else {
+ location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_ENDIF)));
+ }
+ break;
+ case CMD_ENDLEGALESE:
+ if (closeCommand(cmd)) {
+ leavePara();
+ append(Atom::LegaleseRight);
+ }
+ break;
+ case CMD_ENDLINK:
+ if (closeCommand(cmd)) {
+ if (priv->text.lastAtom()->type() == Atom::String
+ && priv->text.lastAtom()->string().endsWith(" "))
+ priv->text.lastAtom()->chopString();
+ append(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ }
+ break;
+ case CMD_ENDLIST:
+ if (closeCommand(cmd)) {
+ leavePara();
+ if (openedLists.top().isStarted()) {
+ append(Atom::ListItemRight,
+ openedLists.top().styleString());
+ append(Atom::ListRight,
+ openedLists.top().styleString());
+ }
+ openedLists.pop();
+ }
+ break;
+ case CMD_ENDOMIT:
+ closeCommand(cmd);
+ break;
+ case CMD_ENDPART:
+ endSection(-1, cmd);
+ break;
+ case CMD_ENDQUOTATION:
+ if (closeCommand(cmd)) {
+ leavePara();
+ append(Atom::QuotationRight);
+ }
+ break;
+ case CMD_ENDRAW:
+ location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_ENDRAW)));
+ break;
+ case CMD_ENDSECTION1:
+ endSection(1, cmd);
+ break;
+ case CMD_ENDSECTION2:
+ endSection(2, cmd);
+ break;
+ case CMD_ENDSECTION3:
+ endSection(3, cmd);
+ break;
+ case CMD_ENDSECTION4:
+ endSection(4, cmd);
+ break;
+ case CMD_ENDSIDEBAR:
+ if (closeCommand(cmd)) {
+ leavePara();
+ append(Atom::SidebarRight);
+ }
+ break;
+ case CMD_ENDTABLE:
+ if (closeCommand(cmd)) {
+ leaveTableRow();
+ append(Atom::TableRight);
+ }
+ break;
+ case CMD_EXPIRE:
+ checkExpiry(getArgument());
+ break;
+ case CMD_FOOTNOTE:
+ if (openCommand(cmd)) {
+ enterPara();
+ append(Atom::FootnoteLeft);
+ paraState = OutsidePara; // ###
+ }
+ break;
+ case CMD_GENERATELIST:
+ append(Atom::GeneratedList, getArgument());
+ break;
+ case CMD_GRANULARITY:
+ priv->constructExtra();
+ priv->extra->granularity = getSectioningUnit();
+ break;
+ case CMD_HEADER:
+ if (openedCommands.top() == CMD_TABLE) {
+ leaveTableRow();
+ append(Atom::TableHeaderLeft);
+ inTableHeader = true;
+ }
+ else {
+ if (openedCommands.contains(CMD_TABLE)) {
+ location().warning(tr("Cannot use '\\%1' within '\\%2'")
+ .arg(cmdName(CMD_HEADER))
+ .arg(cmdName(openedCommands.top())));
+ }
+ else {
+ location().warning(tr("Cannot use '\\%1' outside of '\\%2'")
+ .arg(cmdName(CMD_HEADER))
+ .arg(cmdName(CMD_TABLE)));
+ }
+ }
+ break;
+ case CMD_I:
+ startFormat(ATOM_FORMATTING_ITALIC, cmd);
+ break;
+ case CMD_IF:
+ preprocessorSkipping.push(!Tokenizer::isTrue(getRestOfLine()));
+ if (preprocessorSkipping.top())
+ ++numPreprocessorSkipping;
+ if (numPreprocessorSkipping)
+ skipToNextPreprocessorCommand();
+ break;
+ case CMD_IMAGE:
+ leaveValueList();
+ append(Atom::Image, getArgument());
+ append(Atom::ImageText, getRestOfLine());
+ break;
+ case CMD_INCLUDE:
+ include(getArgument());
+ break;
+ case CMD_INLINEIMAGE:
+ enterPara();
+ append(Atom::InlineImage, getArgument());
+ append(Atom::ImageText, getRestOfLine());
+ append(Atom::String, " ");
+ break;
+ case CMD_INDEX:
+ if (paraState == OutsidePara) {
+ enterPara();
+ indexStartedPara = true;
+ }
+ else {
+ const Atom *last = priv->text.lastAtom();
+ if (indexStartedPara &&
+ (last->type() != Atom::FormattingRight ||
+ last->string() != ATOM_FORMATTING_INDEX))
+ indexStartedPara = false;
+ }
+ startFormat(ATOM_FORMATTING_INDEX, cmd);
+ break;
+ case CMD_KEYWORD:
+ insertTarget(getRestOfLine(),true);
+ break;
+ case CMD_L:
+ enterPara();
+ if (isLeftBraceAhead()) {
+ x = getArgument();
+ append(Atom::Link, x);
+ if (isLeftBraceAhead()) {
+ currentLinkAtom = priv->text.lastAtom();
+ startFormat(ATOM_FORMATTING_LINK, cmd);
+ }
+ else {
+ append(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ append(Atom::String, cleanLink(x));
+ append(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ }
+ }
+ else {
+ x = getArgument();
+ append(Atom::Link, x);
+ append(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ append(Atom::String, cleanLink(x));
+ append(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ }
+ break;
+ case CMD_LEGALESE:
+ leavePara();
+ if (openCommand(cmd))
+ append(Atom::LegaleseLeft);
+ docPrivate->hasLegalese = true;
+ break;
+ case CMD_LINK:
+ if (openCommand(cmd)) {
+ enterPara();
+ x = getArgument();
+ append(Atom::Link, x);
+ append(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
+ skipSpacesOrOneEndl();
+ }
+ break;
+ case CMD_LIST:
+ if (openCommand(cmd)) {
+ leavePara();
+ openedLists.push(OpenedList(location(),
+ getOptionalArgument()));
+ }
+ break;
+ case CMD_META:
+ priv->constructExtra();
+ x = getArgument();
+ priv->extra->metaMap.insert(x, getRestOfLine());
+ break;
+ case CMD_NEWCODE:
+ location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_NEWCODE)));
+ break;
+ case CMD_O:
+ leavePara();
+ if (openedCommands.top() == CMD_LIST) {
+ if (openedLists.top().isStarted()) {
+ append(Atom::ListItemRight,
+ openedLists.top().styleString());
+ }
+ else {
+ append(Atom::ListLeft,
+ openedLists.top().styleString());
+ }
+ openedLists.top().next();
+ append(Atom::ListItemNumber,
+ openedLists.top().numberString());
+ append(Atom::ListItemLeft,
+ openedLists.top().styleString());
+ enterPara();
+ }
+ else if (openedCommands.top() == CMD_TABLE) {
+ x = "1,1";
+ if (isLeftBraceAhead())
+ x = getArgument();
+
+ if (!inTableHeader && !inTableRow) {
+ location().warning(tr("Missing '\\%1' or '\\%1' before '\\%3'")
+ .arg(cmdName(CMD_HEADER))
+ .arg(cmdName(CMD_ROW))
+ .arg(cmdName(CMD_O)));
+ append(Atom::TableRowLeft);
+ inTableRow = true;
+ }
+ else if (inTableItem) {
+ append(Atom::TableItemRight);
+ inTableItem = false;
+ }
+
+ append(Atom::TableItemLeft, x);
+ inTableItem = true;
+ }
+ else {
+ location().warning(tr("Command '\\%1' outside of '\\%2' and '\\%3'")
+ .arg(cmdName(cmd))
+ .arg(cmdName(CMD_LIST))
+ .arg(cmdName(CMD_TABLE)));
+ }
+ break;
+ case CMD_OLDCODE:
+ leavePara();
+#ifdef QDOC2DOX
+ if (DoxWriter::isDoxPass()) {
+ append(Atom::CodeOld, getUnmarkedCode(CMD_OLDCODE));
+ append(Atom::CodeNew, getUnmarkedCode(CMD_NEWCODE));
+ }
+ else {
+ append(Atom::CodeOld, getCode(CMD_OLDCODE, marker));
+ append(Atom::CodeNew, getCode(CMD_NEWCODE, marker));
+ }
+#else
+ append(Atom::CodeOld, getCode(CMD_OLDCODE, marker));
+ append(Atom::CodeNew, getCode(CMD_NEWCODE, marker));
+#endif
+ break;
+ case CMD_OMIT:
+ getUntilEnd(cmd);
+ break;
+ case CMD_OMITVALUE:
+ x = getArgument();
+ if (!priv->enumItemList.contains(x))
+ priv->enumItemList.append(x);
+ if (!priv->omitEnumItemList.contains(x))
+ priv->omitEnumItemList.append(x);
+ break;
+ case CMD_PART:
+ startSection(Doc::Part, cmd);
+ break;
+ case CMD_PRINTLINE:
+ leavePara();
+ if (!quoting)
+ appendToCode(quoter.quoteLine(location(), cmdStr,
+ getRestOfLine()));
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, getRestOfLine());
+ }
+ break;
+ case CMD_PRINTTO:
+ leavePara();
+ if (!quoting)
+ appendToCode(quoter.quoteTo(location(), cmdStr,
+ getRestOfLine()));
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, getRestOfLine());
+ }
+ break;
+ case CMD_PRINTUNTIL:
+ leavePara();
+ if (!quoting)
+ appendToCode(quoter.quoteUntil(location(), cmdStr,
+ getRestOfLine()));
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, getRestOfLine());
+ }
+ break;
+ case CMD_QUOTATION:
+ if (openCommand(cmd)) {
+ leavePara();
+ append(Atom::QuotationLeft);
+ }
+ break;
+ case CMD_QUOTEFILE:
+ {
+ leavePara();
+ QString fileName = getArgument();
+ Doc::quoteFromFile(location(), quoter, fileName);
+ if (!quoting) {
+ append(Atom::Code,
+ quoter.quoteTo(location(), cmdStr, ""));
+ quoter.reset();
+ }
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, fileName);
+ }
+ break;
+ }
+ case CMD_QUOTEFROMFILE:
+ leavePara();
+ if (!quoting)
+ quoteFromFile();
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, getArgument());
+ }
+ break;
+ case CMD_QUOTEFUNCTION:
+ leavePara();
+ marker = quoteFromFile();
+ x = getRestOfLine();
+ if (!quoting) {
+ quoter.quoteTo(location(), cmdStr,
+ slashed(marker->functionBeginRegExp(x)));
+ append(Atom::Code,
+ quoter.quoteUntil(location(), cmdStr,
+ slashed(marker->functionEndRegExp(x))));
+ quoter.reset();
+ }
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, slashed(marker->functionEndRegExp(x)));
+ }
+ break;
+ case CMD_RAW:
+ leavePara();
+ x = getRestOfLine();
+ if (x.isEmpty())
+ location().warning(tr("Missing format name after '\\%1")
+ .arg(cmdName(CMD_RAW)));
+ append(Atom::FormatIf, x);
+ append(Atom::RawString, untabifyEtc(getUntilEnd(cmd)));
+ append(Atom::FormatElse);
+ append(Atom::FormatEndif);
+ break;
+ case CMD_ROW:
+ if (openedCommands.top() == CMD_TABLE) {
+ leaveTableRow();
+ append(Atom::TableRowLeft);
+ inTableRow = true;
+ }
+ else {
+ if (openedCommands.contains(CMD_TABLE)) {
+ location().warning(tr("Cannot use '\\%1' within '\\%2'")
+ .arg(cmdName(CMD_ROW))
+ .arg(cmdName(openedCommands.top())));
+ }
+ else {
+ location().warning(tr("Cannot use '\\%1' outside of '\\%2'")
+ .arg(cmdName(CMD_ROW))
+ .arg(cmdName(CMD_TABLE)));
+ }
+ }
+ break;
+ case CMD_SA:
+ parseAlso();
+ break;
+ case CMD_SECTION1:
+ startSection(Doc::Section1, cmd);
+ break;
+ case CMD_SECTION2:
+ startSection(Doc::Section2, cmd);
+ break;
+ case CMD_SECTION3:
+ startSection(Doc::Section3, cmd);
+ break;
+ case CMD_SECTION4:
+ startSection(Doc::Section4, cmd);
+ break;
+ case CMD_SIDEBAR:
+ if (openCommand(cmd)) {
+ leavePara();
+ append(Atom::SidebarLeft);
+ }
+ break;
+ case CMD_SKIPLINE:
+ leavePara();
+ if (!quoting)
+ quoter.quoteLine(location(),
+ cmdStr,
+ getRestOfLine());
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, getRestOfLine());
+ }
+ break;
+ case CMD_SKIPTO:
+ leavePara();
+ if (!quoting)
+ quoter.quoteTo(location(),
+ cmdStr,
+ getRestOfLine());
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, getRestOfLine());
+ }
+ break;
+ case CMD_SKIPUNTIL:
+ leavePara();
+ if (!quoting)
+ quoter.quoteUntil(location(),
+ cmdStr,
+ getRestOfLine());
+ else {
+ append(Atom::CodeQuoteCommand, cmdStr);
+ append(Atom::CodeQuoteArgument, getRestOfLine());
+ }
+ break;
+ case CMD_SNIPPET:
+ leavePara();
+ {
+ QString snippet = getArgument();
+ QString identifier = getRestOfLine();
+#ifdef QDOC2DOX
+ if (quoting || DoxWriter::isDoxPass()) {
+ append(Atom::SnippetCommand, cmdStr);
+ append(Atom::SnippetLocation, snippet);
+ append(Atom::SnippetIdentifier, identifier);
+ }
+ else {
+ Doc::quoteFromFile(location(),quoter,snippet);
+ appendToCode(quoter.quoteSnippet(location(),
+ identifier));
+ }
+#else
+ if (quoting) {
+ append(Atom::SnippetCommand, cmdStr);
+ append(Atom::SnippetLocation, snippet);
+ append(Atom::SnippetIdentifier, identifier);
+ }
+ else {
+ Doc::quoteFromFile(location(),quoter,snippet);
+ appendToCode(quoter.quoteSnippet(location(),
+ identifier));
+ }
+#endif
+ }
+ break;
+ case CMD_SUB:
+ startFormat(ATOM_FORMATTING_SUBSCRIPT, cmd);
+ break;
+ case CMD_SUP:
+ startFormat(ATOM_FORMATTING_SUPERSCRIPT, cmd);
+ break;
+ case CMD_TABLE:
+ x = getRestOfLine();
+ if (openCommand(cmd)) {
+ leavePara();
+ append(Atom::TableLeft, x);
+ inTableHeader = false;
+ inTableRow = false;
+ inTableItem = false;
+ }
+ break;
+ case CMD_TABLEOFCONTENTS:
+ x = "1";
+ if (isLeftBraceAhead())
+ x = getArgument();
+ x += ",";
+ x += QString::number((int)getSectioningUnit());
+ append(Atom::TableOfContents, x);
+ break;
+ case CMD_TARGET:
+ insertTarget(getRestOfLine(),false);
+ break;
+ case CMD_TT:
+ startFormat(ATOM_FORMATTING_TELETYPE, cmd);
+ break;
+ case CMD_UNDERLINE:
+ startFormat(ATOM_FORMATTING_UNDERLINE, cmd);
+ break;
+ case CMD_UNICODE:
+ enterPara();
+ x = getArgument();
+ {
+ bool ok;
+ uint unicodeChar = x.toUInt(&ok, 0);
+ if (!ok ||
+ (unicodeChar == 0x0000) ||
+ (unicodeChar > 0xFFFE)) {
+ location().warning(tr("Invalid Unicode character '%1' specified "
+ "with '%2'")
+ .arg(x, cmdName(CMD_UNICODE)));
+ }
+ else {
+ append(Atom::String, QChar(unicodeChar));
+ }
+ }
+ break;
+ case CMD_VALUE:
+ leaveValue();
+ if (openedLists.top().style() == OpenedList::Value) {
+ x = getArgument();
+ if (!priv->enumItemList.contains(x))
+ priv->enumItemList.append(x);
+
+ openedLists.top().next();
+ append(Atom::ListTagLeft, ATOM_LIST_VALUE);
+ append(Atom::String, x);
+ append(Atom::ListTagRight, ATOM_LIST_VALUE);
+ append(Atom::ListItemLeft, ATOM_LIST_VALUE);
+
+ skipSpacesOrOneEndl();
+ if (isBlankLine())
+ append(Atom::Nop);
+ }
+ else {
+ // ### problems
+ }
+ break;
+ case CMD_WARNING:
+ startNewPara();
+ append(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
+ append(Atom::String, "Warning:");
+ append(Atom::FormattingRight, ATOM_FORMATTING_BOLD);
+ append(Atom::String, " ");
+ break;
+ case CMD_OVERLOAD: // qdoc --> doxygen
+ priv->metacommandsUsed.insert(cmdStr);
+ x.clear();
+ if (!isBlankLine())
+ x = getRestOfLine();
+ if (!x.isEmpty()) {
+ append(Atom::ParaLeft);
+ append(Atom::String, "This function overloads ");
+ append(Atom::AutoLink,x);
+ append(Atom::String, ".");
+ append(Atom::ParaRight);
+ }
+ else {
+ append(Atom::ParaLeft);
+ append(Atom::String,
+ "This is an overloaded member function, "
+ "provided for convenience.");
+ append(Atom::ParaRight);
+ x = getMetaCommandArgument(cmdStr);
+ }
+ priv->metaCommandMap[cmdStr].append(x);
+ break;
+ case NOT_A_CMD:
+ if (metaCommandSet.contains(cmdStr)) {
+ priv->metacommandsUsed.insert(cmdStr);
+ QString xxx = getMetaCommandArgument(cmdStr);
+ priv->metaCommandMap[cmdStr].append(xxx);
+ }
+ else if (macroHash()->contains(cmdStr)) {
+ const Macro &macro = macroHash()->value(cmdStr);
+ int numPendingFi = 0;
+ QStringMap::ConstIterator d;
+ d = macro.otherDefs.begin();
+ while (d != macro.otherDefs.end()) {
+ append(Atom::FormatIf, d.key());
+ expandMacro(cmdStr, *d, macro.numParams);
+ ++d;
+
+ if (d == macro.otherDefs.end()) {
+ append(Atom::FormatEndif);
+ }
+ else {
+ append(Atom::FormatElse);
+ numPendingFi++;
+ }
+ }
+ while (numPendingFi-- > 0)
+ append(Atom::FormatEndif);
+
+ if (!macro.defaultDef.isEmpty()) {
+ if (!macro.otherDefs.isEmpty()) {
+ macro.defaultDefLocation.warning(
+ tr("Macro cannot have both "
+ "format-specific and qdoc- "
+ "syntax definitions"));
+ }
+ else {
+ location().push(macro.defaultDefLocation.filePath());
+ in.insert(pos, macro.defaultDef);
+ len = in.length();
+ openedInputs.push(pos + macro.defaultDef.length());
+ }
+ }
+ }
+ else {
+ location().warning(
+ tr("Unknown command '\\%1'").arg(cmdStr),
+ detailsUnknownCommand(metaCommandSet,cmdStr));
+ enterPara();
+ append(Atom::UnknownCommand, cmdStr);
+ }
+ }
+ }
+ }
+ break;
+ case '{':
+ enterPara();
+ appendChar('{');
+ braceDepth++;
+ pos++;
+ break;
+ case '}':
+ {
+ braceDepth--;
+ pos++;
+
+ QMap<int, QString>::Iterator f =
+ pendingFormats.find(braceDepth);
+ if (f == pendingFormats.end()) {
+ enterPara();
+ appendChar('}');
+ }
+ else {
+ append(Atom::FormattingRight, *f);
+ if (*f == ATOM_FORMATTING_INDEX) {
+ if (indexStartedPara)
+ skipAllSpaces();
+ }
+ else if (*f == ATOM_FORMATTING_LINK) {
+ // hack for C++ to support links like
+ // \l{QString::}{count()}
+ if (currentLinkAtom &&
+ currentLinkAtom->string().endsWith("::")) {
+ QString suffix = Text::subText(currentLinkAtom,
+ priv->text.lastAtom()).toString();
+ currentLinkAtom->appendString(suffix);
+ }
+ currentLinkAtom = 0;
+ }
+ pendingFormats.erase(f);
+ }
+ }
+ break;
+ default:
+ {
+ bool newWord;
+ switch (priv->text.lastAtom()->type()) {
+ case Atom::ParaLeft:
+ newWord = true;
+ break;
+ default:
+ newWord = false;
+ }
+
+ if (paraState == OutsidePara) {
+ if (ch.isSpace()) {
+ ++pos;
+ newWord = false;
+ }
+ else {
+ enterPara();
+ newWord = true;
+ }
+ }
+ else {
+ if (ch.isSpace()) {
+ ++pos;
+ if ((ch == '\n') &&
+ (paraState == InsideSingleLinePara ||
+ isBlankLine())) {
+ leavePara();
+ newWord = false;
+ }
+ else {
+ appendChar(' ');
+ newWord = true;
+ }
+ }
+ else {
+ newWord = true;
+ }
+ }
+
+ if (newWord) {
+ int startPos = pos;
+ int numInternalUppercase = 0;
+ int numLowercase = 0;
+ int numStrangeSymbols = 0;
+
+ while (pos < len) {
+ unsigned char latin1Ch = in.at(pos).toLatin1();
+ if (islower(latin1Ch)) {
+ ++numLowercase;
+ ++pos;
+ }
+ else if (isupper(latin1Ch)) {
+ if (pos > startPos)
+ ++numInternalUppercase;
+ ++pos;
+ }
+ else if (isdigit(latin1Ch)) {
+ if (pos > startPos) {
+ ++pos;
+ }
+ else {
+ break;
+ }
+ }
+ else if (latin1Ch == '_' || latin1Ch == '@') {
+ ++numStrangeSymbols;
+ ++pos;
+ }
+ else if (latin1Ch == ':' && pos < len - 1
+ && in.at(pos + 1) == QLatin1Char(':')) {
+ ++numStrangeSymbols;
+ pos += 2;
+ }
+ else if (latin1Ch == '(') {
+ if (pos > startPos) {
+ if (pos < len - 1 &&
+ in.at(pos + 1) == QLatin1Char(')')) {
+ ++numStrangeSymbols;
+ pos += 2;
+ break;
+ }
+ else {
+ // ### handle functions with signatures
+ // and function calls
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ if (pos == startPos) {
+ if (!ch.isSpace()) {
+ appendChar(ch);
+ ++pos;
+ }
+ }
+ else {
+ QString word = in.mid(startPos, pos - startPos);
+ // is word a C++ symbol or an English word?
+ if ((numInternalUppercase >= 1 && numLowercase >= 2)
+ || numStrangeSymbols >= 1) {
+ append(Atom::AutoLink, word);
+ }
+ else {
+ appendWord(word);
+ }
+ }
+ }
+ }
+ }
+ }
+ leaveValueList();
+
+ // for compatibility
+ if (openedCommands.top() == CMD_LEGALESE) {
+ append(Atom::LegaleseRight);
+ openedCommands.pop();
+ }
+
+ if (openedCommands.top() != CMD_OMIT) {
+ location().warning(tr("Missing '\\%1'").arg(endCmdName(openedCommands.top())));
+ }
+ else if (preprocessorSkipping.count() > 0) {
+ location().warning(tr("Missing '\\%1'").arg(cmdName(CMD_ENDIF)));
+ }
+
+ while (currentSectioningUnit > Doc::Chapter) {
+ int delta = currentSectioningUnit - priv->extra->sectioningUnit;
+ append(Atom::SectionRight, QString::number(delta));
+ currentSectioningUnit = Doc::SectioningUnit(int(currentSectioningUnit) - 1);
+ }
+
+ if (priv->extra && priv->extra->granularity < priv->extra->sectioningUnit)
+ priv->extra->granularity = priv->extra->sectioningUnit;
+ priv->text.stripFirstAtom();
+}
+
+Location &DocParser::location()
+{
+ while (!openedInputs.isEmpty() && openedInputs.top() <= pos) {
+ cachedLoc.pop();
+ cachedPos = openedInputs.pop();
+ }
+ while (cachedPos < pos)
+ cachedLoc.advance(in.at(cachedPos++));
+ return cachedLoc;
+}
+
+QString DocParser::detailsUnknownCommand(const QSet<QString> &metaCommandSet,
+ const QString &str)
+{
+ QSet<QString> commandSet = metaCommandSet;
+ int i = 0;
+ while (cmds[i].english != 0) {
+ commandSet.insert(*cmds[i].alias);
+ i++;
+ }
+
+ if (aliasMap()->contains(str))
+ return tr("The command '\\%1' was renamed '\\%2' by the configuration"
+ " file. Use the new name.")
+ .arg(str).arg((*aliasMap())[str]);
+
+ QString best = nearestName(str, commandSet);
+ if (best.isEmpty())
+ return QString();
+ return tr("Maybe you meant '\\%1'?").arg(best);
+}
+
+void DocParser::checkExpiry(const QString& date)
+{
+ QRegExp ymd("(\\d{4})(?:-(\\d{2})(?:-(\\d{2})))");
+
+ if (ymd.exactMatch(date)) {
+ int y = ymd.cap(1).toInt();
+ int m = ymd.cap(2).toInt();
+ int d = ymd.cap(3).toInt();
+
+ if (m == 0)
+ m = 1;
+ if (d == 0)
+ d = 1;
+ QDate expiryDate(y, m, d);
+ if (expiryDate.isValid()) {
+ int days = expiryDate.daysTo(QDate::currentDate());
+ if (days == 0) {
+ location().warning(tr("Documentation expires today"));
+ }
+ else if (days == 1) {
+ location().warning(tr("Documentation expired yesterday"));
+ }
+ else if (days >= 2) {
+ location().warning(tr("Documentation expired %1 days ago")
+ .arg(days));
+ }
+ }
+ else {
+ location().warning(tr("Date '%1' invalid").arg(date));
+ }
+ }
+ else {
+ location().warning(tr("Date '%1' not in YYYY-MM-DD format")
+ .arg(date));
+ }
+}
+
+void DocParser::insertBaseName(const QString &baseName)
+{
+ priv->constructExtra();
+ if (currentSectioningUnit == priv->extra->sectioningUnit) {
+ priv->extra->baseName = baseName;
+ }
+ else {
+ Atom *atom = priv->text.firstAtom();
+ Atom *sectionLeft = 0;
+
+ int delta = currentSectioningUnit - priv->extra->sectioningUnit;
+
+ while (atom != 0) {
+ if (atom->type() == Atom::SectionLeft &&
+ atom->string().toInt() == delta)
+ sectionLeft = atom;
+ atom = atom->next();
+ }
+ if (sectionLeft != 0)
+ (void) new Atom(sectionLeft, Atom::BaseName, baseName);
+ }
+}
+
+void DocParser::insertTarget(const QString &target, bool keyword)
+{
+ if (targetMap.contains(target)) {
+ location().warning(tr("Duplicate target name '%1'").arg(target));
+ targetMap[target].warning(tr("(The previous occurrence is here)"));
+ }
+ else {
+ targetMap.insert(target, location());
+ append(Atom::Target, target);
+ priv->constructExtra();
+ if (keyword)
+ priv->extra->keywords.append(priv->text.lastAtom());
+ else
+ priv->extra->targets.append(priv->text.lastAtom());
+ }
+}
+
+void DocParser::include(const QString& fileName)
+{
+ if (location().depth() > 16)
+ location().fatal(tr("Too many nested '\\%1's")
+ .arg(cmdName(CMD_INCLUDE)));
+
+ QString userFriendlyFilePath;
+ // ### use current directory?
+ QString filePath = Config::findFile(location(),
+ sourceFiles,
+ sourceDirs,
+ fileName,
+ userFriendlyFilePath);
+ if (filePath.isEmpty()) {
+ location().warning(tr("Cannot find leaf file '%1'").arg(fileName));
+ }
+ else {
+ QFile inFile(filePath);
+ if (!inFile.open(QFile::ReadOnly)) {
+ location().warning(tr("Cannot open leaf file '%1'")
+ .arg(userFriendlyFilePath));
+ }
+ else {
+ location().push(userFriendlyFilePath);
+
+ QTextStream inStream(&inFile);
+ QString includedStuff = inStream.readAll();
+ inFile.close();
+
+ in.insert(pos, includedStuff);
+ len = in.length();
+ openedInputs.push(pos + includedStuff.length());
+ }
+ }
+}
+
+void DocParser::startFormat(const QString& format, int cmd)
+{
+ enterPara();
+
+ QMap<int, QString>::ConstIterator f = pendingFormats.begin();
+ while (f != pendingFormats.end()) {
+ if (*f == format) {
+ location().warning(tr("Cannot nest '\\%1' commands")
+ .arg(cmdName(cmd)));
+ return;
+ }
+ ++f;
+ }
+
+ append(Atom::FormattingLeft, format);
+
+ if (isLeftBraceAhead()) {
+ skipSpacesOrOneEndl();
+ pendingFormats.insert(braceDepth, format);
+ ++braceDepth;
+ ++pos;
+ }
+ else {
+ append(Atom::String, getArgument());
+ append(Atom::FormattingRight, format);
+ if (format == ATOM_FORMATTING_INDEX && indexStartedPara) {
+ skipAllSpaces();
+ indexStartedPara = false;
+ }
+ }
+}
+
+bool DocParser::openCommand(int cmd)
+{
+ int outer = openedCommands.top();
+ bool ok = true;
+
+ if (cmd != CMD_LINK) {
+ if (outer == CMD_LIST) {
+ ok = (cmd == CMD_FOOTNOTE || cmd == CMD_LIST);
+ }
+ else if (outer == CMD_ABSTRACT) {
+ ok = (cmd == CMD_LIST ||
+ cmd == CMD_QUOTATION ||
+ cmd == CMD_TABLE);
+ }
+ else if (outer == CMD_SIDEBAR) {
+ ok = (cmd == CMD_LIST ||
+ cmd == CMD_QUOTATION ||
+ cmd == CMD_SIDEBAR);
+ }
+ else if (outer == CMD_QUOTATION) {
+ ok = (cmd == CMD_LIST);
+ }
+ else if (outer == CMD_TABLE) {
+ ok = (cmd == CMD_LIST ||
+ cmd == CMD_FOOTNOTE ||
+ cmd == CMD_QUOTATION);
+ }
+ else if (outer == CMD_FOOTNOTE || outer == CMD_LINK) {
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ openedCommands.push(cmd);
+ }
+ else {
+ location().warning(tr("Cannot use '\\%1' within '\\%2'")
+ .arg(cmdName(cmd)).arg(cmdName(outer)));
+ }
+ return ok;
+}
+
+bool DocParser::closeCommand(int endCmd)
+{
+ if (endCmdFor(openedCommands.top()) == endCmd && openedCommands.size() > 1) {
+ openedCommands.pop();
+ return true;
+ }
+ else {
+ bool contains = false;
+ QStack<int> opened2 = openedCommands;
+ while (opened2.size() > 1) {
+ if (endCmdFor(opened2.top()) == endCmd) {
+ contains = true;
+ break;
+ }
+ opened2.pop();
+ }
+
+ if (contains) {
+ while (endCmdFor(openedCommands.top()) != endCmd && openedCommands.size() > 1) {
+ location().warning(tr("Missing '\\%1' before '\\%2'")
+ .arg(endCmdName(openedCommands.top()))
+ .arg(cmdName(endCmd)));
+ openedCommands.pop();
+ }
+ }
+ else {
+ location().warning(tr("Unexpected '\\%1'")
+ .arg(cmdName(endCmd)));
+ }
+ return false;
+ }
+}
+
+void DocParser::startSection(Doc::SectioningUnit unit, int cmd)
+{
+ leavePara();
+
+ if (currentSectioningUnit == Doc::Book) {
+ if (unit > Doc::Section1)
+ location().warning(tr("Unexpected '\\%1' without '\\%2'")
+ .arg(cmdName(cmd))
+ .arg(cmdName(CMD_SECTION1)));
+ currentSectioningUnit = (Doc::SectioningUnit) (unit - 1);
+ priv->constructExtra();
+ priv->extra->sectioningUnit = currentSectioningUnit;
+ }
+
+ if (unit <= priv->extra->sectioningUnit) {
+ location().warning(tr("Unexpected '\\%1' in this documentation")
+ .arg(cmdName(cmd)));
+ }
+ else if (unit - currentSectioningUnit > 1) {
+ location().warning(tr("Unexpected '\\%1' at this point")
+ .arg(cmdName(cmd)));
+ }
+ else {
+ if (currentSectioningUnit >= unit)
+ endSection(unit, cmd);
+
+ int delta = unit - priv->extra->sectioningUnit;
+ append(Atom::SectionLeft, QString::number(delta));
+ priv->constructExtra();
+ priv->extra->tableOfContents.append(priv->text.lastAtom());
+ priv->extra->tableOfContentsLevels.append(unit);
+ enterPara(Atom::SectionHeadingLeft,
+ Atom::SectionHeadingRight,
+ QString::number(delta));
+ currentSectioningUnit = unit;
+ }
+}
+
+void DocParser::endSection(int unit, int endCmd)
+{
+ leavePara();
+
+ if (unit < priv->extra->sectioningUnit) {
+ location().warning(tr("Unexpected '\\%1' in this documentation")
+ .arg(cmdName(endCmd)));
+ }
+ else if (unit > currentSectioningUnit) {
+ location().warning(tr("Unexpected '\\%1' at this point")
+ .arg(cmdName(endCmd)));
+ }
+ else {
+ while (currentSectioningUnit >= unit) {
+ int delta = currentSectioningUnit - priv->extra->sectioningUnit;
+ append(Atom::SectionRight, QString::number(delta));
+ currentSectioningUnit =
+ (Doc::SectioningUnit) (currentSectioningUnit - 1);
+ }
+ }
+}
+
+void DocParser::parseAlso()
+{
+ leavePara();
+ skipSpacesOnLine();
+ while (pos < len && in[pos] != '\n') {
+ QString target;
+ QString str;
+
+ if (in[pos] == '{') {
+ target = getArgument();
+ skipSpacesOnLine();
+ if (in[pos] == '{') {
+ str = getArgument();
+
+ // hack for C++ to support links like \l{QString::}{count()}
+ if (target.endsWith("::"))
+ target += str;
+ }
+ else {
+ str = target;
+ }
+#ifdef QDOC2_COMPAT
+ }
+ else if (in[pos] == '\\' && in.mid(pos, 5) == "\\link") {
+ pos += 6;
+ target = getArgument();
+ int endPos = in.indexOf("\\endlink", pos);
+ if (endPos != -1) {
+ str = in.mid(pos, endPos - pos).trimmed();
+ pos = endPos + 8;
+ }
+#endif
+ }
+ else {
+ target = getArgument();
+ str = cleanLink(target);
+ }
+
+ Text also;
+ also << Atom(Atom::Link, target)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << str
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ priv->addAlso(also);
+
+ skipSpacesOnLine();
+ if (pos < len && in[pos] == ',') {
+ pos++;
+ skipSpacesOrOneEndl();
+ }
+ else if (in[pos] != '\n') {
+ location().warning(tr("Missing comma in '\\%1'").arg(cmdName(CMD_SA)));
+ }
+ }
+}
+
+void DocParser::append(Atom::Type type, const QString &string)
+{
+ Atom::Type lastType = priv->text.lastAtom()->type();
+#ifdef QDOC_QML
+ if (((lastType == Atom::Code) || (lastType == Atom::Code)) &&
+#else
+ if ((lastType == Atom::Code) &&
+#endif
+ priv->text.lastAtom()->string().endsWith(QLatin1String("\n\n")))
+ priv->text.lastAtom()->chopString();
+ priv->text << Atom(type, string);
+}
+
+void DocParser::appendChar(QChar ch)
+{
+ if (priv->text.lastAtom()->type() != Atom::String)
+ append(Atom::String);
+ Atom *atom = priv->text.lastAtom();
+ if (ch == QLatin1Char(' ')) {
+ if (!atom->string().endsWith(QLatin1Char(' ')))
+ atom->appendChar(QLatin1Char(' '));
+ }
+ else
+ atom->appendChar(ch);
+}
+
+void DocParser::appendWord(const QString &word)
+{
+ if (priv->text.lastAtom()->type() != Atom::String) {
+ append(Atom::String, word);
+ }
+ else
+ priv->text.lastAtom()->appendString(word);
+}
+
+void DocParser::appendToCode(const QString& markedCode)
+{
+ Atom::Type lastType = priv->text.lastAtom()->type();
+#ifdef QDOC_QML
+ if (lastType != Atom::Qml)
+ append(Atom::Qml);
+#else
+ if (lastType != Atom::Code)
+ append(Atom::Code);
+#endif
+ priv->text.lastAtom()->appendString(markedCode);
+}
+
+void DocParser::startNewPara()
+{
+ leavePara();
+ enterPara();
+}
+
+void DocParser::enterPara(Atom::Type leftType,
+ Atom::Type rightType,
+ const QString& string)
+{
+ if (paraState == OutsidePara) {
+ if (priv->text.lastAtom()->type() != Atom::ListItemLeft)
+ leaveValueList();
+ append(leftType, string);
+ indexStartedPara = false;
+ pendingParaLeftType = leftType;
+ pendingParaRightType = rightType;
+ pendingParaString = string;
+ if (
+#if 0
+ leftType == Atom::BriefLeft ||
+#endif
+ leftType == Atom::SectionHeadingLeft) {
+ paraState = InsideSingleLinePara;
+ }
+ else {
+ paraState = InsideMultiLinePara;
+ }
+ skipSpacesOrOneEndl();
+ }
+}
+
+void DocParser::leavePara()
+{
+ if (paraState != OutsidePara) {
+ if (!pendingFormats.isEmpty()) {
+ location().warning(tr("Missing '}'"));
+ pendingFormats.clear();
+ }
+
+ if (priv->text.lastAtom()->type() == pendingParaLeftType) {
+ priv->text.stripLastAtom();
+ }
+ else {
+ if (priv->text.lastAtom()->type() == Atom::String &&
+ priv->text.lastAtom()->string().endsWith(" ")) {
+ priv->text.lastAtom()->chopString();
+ }
+ append(pendingParaRightType, pendingParaString);
+ }
+ paraState = OutsidePara;
+ indexStartedPara = false;
+ pendingParaRightType = Atom::Nop;
+ pendingParaString = "";
+ }
+}
+
+void DocParser::leaveValue()
+{
+ leavePara();
+ if (openedLists.isEmpty()) {
+ openedLists.push(OpenedList(OpenedList::Value));
+ append(Atom::ListLeft, ATOM_LIST_VALUE);
+ }
+ else {
+ if (priv->text.lastAtom()->type() == Atom::Nop)
+ priv->text.stripLastAtom();
+ append(Atom::ListItemRight, ATOM_LIST_VALUE);
+ }
+}
+
+void DocParser::leaveValueList()
+{
+ leavePara();
+ if (!openedLists.isEmpty() &&
+ (openedLists.top().style() == OpenedList::Value)) {
+ if (priv->text.lastAtom()->type() == Atom::Nop)
+ priv->text.stripLastAtom();
+ append(Atom::ListItemRight, ATOM_LIST_VALUE);
+ append(Atom::ListRight, ATOM_LIST_VALUE);
+ openedLists.pop();
+ }
+}
+
+void DocParser::leaveTableRow()
+{
+ if (inTableItem) {
+ leavePara();
+ append(Atom::TableItemRight);
+ inTableItem = false;
+ }
+ if (inTableHeader) {
+ append(Atom::TableHeaderRight);
+ inTableHeader = false;
+ }
+ if (inTableRow) {
+ append(Atom::TableRowRight);
+ inTableRow = false;
+ }
+}
+
+CodeMarker *DocParser::quoteFromFile()
+{
+ return Doc::quoteFromFile(location(), quoter, getArgument());
+}
+
+void DocParser::expandMacro(const QString &name,
+ const QString &def,
+ int numParams)
+{
+ if (numParams == 0) {
+ append(Atom::RawString, def);
+ }
+ else {
+ QStringList args;
+ QString rawString;
+
+ for (int i = 0; i < numParams; i++) {
+ if (numParams == 1 || isLeftBraceAhead()) {
+ args << getArgument(true);
+ }
+ else {
+ location().warning(tr("Macro '\\%1' invoked with too few"
+ " arguments (expected %2, got %3)")
+ .arg(name).arg(numParams).arg(i));
+ break;
+ }
+ }
+
+ int j = 0;
+ while (j < def.size()) {
+ int paramNo;
+ if ((def[j] == '\\') && (j < def.size() - 1) &&
+ ((paramNo = def[j + 1].digitValue()) >= 1) &&
+ (paramNo <= numParams)) {
+ if (!rawString.isEmpty()) {
+ append(Atom::RawString, rawString);
+ rawString = "";
+ }
+ append(Atom::String, args[paramNo - 1]);
+ j += 2;
+ }
+ else {
+ rawString += def[j++];
+ }
+ }
+ if (!rawString.isEmpty())
+ append(Atom::RawString, rawString);
+ }
+}
+
+Doc::SectioningUnit DocParser::getSectioningUnit()
+{
+ QString name = getOptionalArgument();
+
+ if (name == "part") {
+ return Doc::Part;
+ }
+ else if (name == "chapter") {
+ return Doc::Chapter;
+ }
+ else if (name == "section1") {
+ return Doc::Section1;
+ }
+ else if (name == "section2") {
+ return Doc::Section2;
+ }
+ else if (name == "section3") {
+ return Doc::Section3;
+ }
+ else if (name == "section4") {
+ return Doc::Section4;
+ }
+ else if (name.isEmpty()) {
+ return Doc::Section4;
+ }
+ else {
+ location().warning(tr("Invalid sectioning unit '%1'").arg(name));
+ return Doc::Book;
+ }
+}
+
+QString DocParser::getArgument(bool verbatim)
+{
+ QString arg;
+ int delimDepth = 0;
+
+ skipSpacesOrOneEndl();
+
+ int startPos = pos;
+
+ /*
+ Typically, an argument ends at the next white-space. However,
+ braces can be used to group words:
+
+ {a few words}
+
+ Also, opening and closing parentheses have to match. Thus,
+
+ printf("%d\n", x)
+
+ is an argument too, although it contains spaces. Finally,
+ trailing punctuation is not included in an argument, nor is 's.
+ */
+ if (pos < (int) in.length() && in[pos] == '{') {
+ pos++;
+ while (pos < (int) in.length() && delimDepth >= 0) {
+ switch (in[pos].unicode()) {
+ case '{':
+ delimDepth++;
+ arg += "{";
+ pos++;
+ break;
+ case '}':
+ delimDepth--;
+ if (delimDepth >= 0)
+ arg += "}";
+ pos++;
+ break;
+ case '\\':
+ if (verbatim) {
+ arg += in[pos];
+ pos++;
+ }
+ else {
+ pos++;
+ if (pos < (int) in.length()) {
+ if (in[pos].isLetterOrNumber())
+ break;
+ arg += in[pos];
+ if (in[pos].isSpace()) {
+ skipAllSpaces();
+ }
+ else {
+ pos++;
+ }
+ }
+ }
+ break;
+ default:
+ arg += in[pos];
+ pos++;
+ }
+ }
+ if (delimDepth > 0)
+ location().warning(tr("Missing '}'"));
+ }
+ else {
+ while (pos < in.length() &&
+ ((delimDepth > 0) ||
+ ((delimDepth == 0) &&
+ !in[pos].isSpace()))) {
+ switch (in[pos].unicode()) {
+ case '(':
+ case '[':
+ case '{':
+ delimDepth++;
+ arg += in[pos];
+ pos++;
+ break;
+ case ')':
+ case ']':
+ case '}':
+ delimDepth--;
+ if (pos == startPos || delimDepth >= 0) {
+ arg += in[pos];
+ pos++;
+ }
+ break;
+ case '\\':
+ if (verbatim) {
+ arg += in[pos];
+ pos++;
+ }
+ else {
+ pos++;
+ if (pos < (int) in.length()) {
+ if (in[pos].isLetterOrNumber())
+ break;
+ arg += in[pos];
+ if (in[pos].isSpace()) {
+ skipAllSpaces();
+ }
+ else {
+ pos++;
+ }
+ }
+ }
+ break;
+ default:
+ arg += in[pos];
+ pos++;
+ }
+ }
+ if ((arg.length() > 1) &&
+ (QString(".,:;!?").indexOf(in[pos - 1]) != -1) &&
+ !arg.endsWith("...")) {
+ arg.truncate(arg.length() - 1);
+ pos--;
+ }
+ if (arg.length() > 2 && in.mid(pos - 2, 2) == "'s") {
+ arg.truncate(arg.length() - 2);
+ pos -= 2;
+ }
+ }
+ return arg.simplified();
+}
+
+QString DocParser::getOptionalArgument()
+{
+ skipSpacesOrOneEndl();
+ if (pos + 1 < (int) in.length() && in[pos] == '\\' &&
+ in[pos + 1].isLetterOrNumber()) {
+ return "";
+ }
+ else {
+ return getArgument();
+ }
+}
+
+QString DocParser::getRestOfLine()
+{
+ QString t;
+
+ skipSpacesOnLine();
+
+ bool trailingSlash = false;
+
+ do {
+ int begin = pos;
+
+ while (pos < in.size() && in[pos] != '\n') {
+ if (in[pos] == '\\' && !trailingSlash) {
+ trailingSlash = true;
+ ++pos;
+ while ((pos < in.size()) &&
+ in[pos].isSpace() &&
+ (in[pos] != '\n'))
+ ++pos;
+ }
+ else {
+ trailingSlash = false;
+ ++pos;
+ }
+ }
+
+ if (!t.isEmpty())
+ t += " ";
+ t += in.mid(begin, pos - begin).simplified();
+
+ if (trailingSlash) {
+ t.chop(1);
+ t = t.simplified();
+ }
+ if (pos < in.size())
+ ++pos;
+ } while (pos < in.size() && trailingSlash);
+
+ return t;
+}
+
+/*!
+ The metacommand argument is normally the remaining text to
+ the right of the metacommand itself. The extra blanks are
+ stripped and the argument string is returned.
+ */
+QString DocParser::getMetaCommandArgument(const QString &cmdStr)
+{
+ skipSpacesOnLine();
+
+ int begin = pos;
+ int parenDepth = 0;
+
+ while (pos < in.size() && (in[pos] != '\n' || parenDepth > 0)) {
+ if (in.at(pos) == '(')
+ ++parenDepth;
+ else if (in.at(pos) == ')')
+ --parenDepth;
+
+ ++pos;
+ }
+ if (pos == in.size() && parenDepth > 0) {
+ pos = begin;
+ location().warning(tr("Unbalanced parentheses in '%1'").arg(cmdStr));
+ }
+
+ QString t = in.mid(begin, pos - begin).simplified();
+ skipSpacesOnLine();
+ return t;
+}
+
+QString DocParser::getUntilEnd(int cmd)
+{
+ int endCmd = endCmdFor(cmd);
+ QRegExp rx("\\\\" + cmdName(endCmd) + "\\b");
+ QString t;
+ int end = rx.indexIn(in, pos);
+
+ if (end == -1) {
+ location().warning(tr("Missing '\\%1'").arg(cmdName(endCmd)));
+ pos = in.length();
+ }
+ else {
+ t = in.mid(pos, end - pos);
+ pos = end + rx.matchedLength();
+ }
+ return t;
+}
+
+QString DocParser::getCode(int cmd, CodeMarker *marker)
+{
+ QString code = untabifyEtc(getUntilEnd(cmd));
+ int indent = indentLevel(code);
+ if (indent < minIndent)
+ minIndent = indent;
+ code = unindent(minIndent, code);
+ marker = CodeMarker::markerForCode(code);
+ return marker->markedUpCode(code, 0, "");
+}
+
+/*!
+ Used only for generating doxygen output.
+ */
+QString DocParser::getUnmarkedCode(int cmd)
+{
+ QString code = getUntilEnd(cmd);
+#if 0
+ int indent = indentLevel(code);
+ if (indent < minIndent)
+ minIndent = indent;
+ code = unindent(minIndent, code);
+#endif
+ return code;
+}
+
+bool DocParser::isBlankLine()
+{
+ int i = pos;
+
+ while (i < len && in[i].isSpace()) {
+ if (in[i] == '\n')
+ return true;
+ i++;
+ }
+ return false;
+}
+
+bool DocParser::isLeftBraceAhead()
+{
+ int numEndl = 0;
+ int i = pos;
+
+ while (i < len && in[i].isSpace() && numEndl < 2) {
+ // ### bug with '\\'
+ if (in[i] == '\n')
+ numEndl++;
+ i++;
+ }
+ return numEndl < 2 && i < len && in[i] == '{';
+}
+
+void DocParser::skipSpacesOnLine()
+{
+ while ((pos < in.length()) &&
+ in[pos].isSpace() &&
+ (in[pos].unicode() != '\n'))
+ ++pos;
+}
+
+void DocParser::skipSpacesOrOneEndl()
+{
+ int firstEndl = -1;
+ while (pos < (int) in.length() && in[pos].isSpace()) {
+ QChar ch = in[pos];
+ if (ch == '\n') {
+ if (firstEndl == -1) {
+ firstEndl = pos;
+ }
+ else {
+ pos = firstEndl;
+ break;
+ }
+ }
+ pos++;
+ }
+}
+
+void DocParser::skipAllSpaces()
+{
+ while (pos < len && in[pos].isSpace())
+ pos++;
+}
+
+void DocParser::skipToNextPreprocessorCommand()
+{
+ QRegExp rx("\\\\(?:" + cmdName(CMD_IF) + "|" +
+ cmdName(CMD_ELSE) + "|" +
+ cmdName(CMD_ENDIF) + ")\\b");
+ int end = rx.indexIn(in, pos + 1); // ### + 1 necessary?
+
+ if (end == -1)
+ pos = in.length();
+ else
+ pos = end;
+}
+
+int DocParser::endCmdFor(int cmd)
+{
+ switch (cmd) {
+ case CMD_ABSTRACT:
+ return CMD_ENDABSTRACT;
+ case CMD_BADCODE:
+ return CMD_ENDCODE;
+ case CMD_CHAPTER:
+ return CMD_ENDCHAPTER;
+ case CMD_CODE:
+ return CMD_ENDCODE;
+#ifdef QDOC_QML
+ case CMD_QML:
+ return CMD_ENDQML;
+ case CMD_QMLTEXT:
+ return CMD_ENDQMLTEXT;
+#endif
+ case CMD_FOOTNOTE:
+ return CMD_ENDFOOTNOTE;
+ case CMD_LEGALESE:
+ return CMD_ENDLEGALESE;
+ case CMD_LINK:
+ return CMD_ENDLINK;
+ case CMD_LIST:
+ return CMD_ENDLIST;
+ case CMD_NEWCODE:
+ return CMD_ENDCODE;
+ case CMD_OLDCODE:
+ return CMD_NEWCODE;
+ case CMD_OMIT:
+ return CMD_ENDOMIT;
+ case CMD_PART:
+ return CMD_ENDPART;
+ case CMD_QUOTATION:
+ return CMD_ENDQUOTATION;
+ case CMD_RAW:
+ return CMD_ENDRAW;
+ case CMD_SECTION1:
+ return CMD_ENDSECTION1;
+ case CMD_SECTION2:
+ return CMD_ENDSECTION2;
+ case CMD_SECTION3:
+ return CMD_ENDSECTION3;
+ case CMD_SECTION4:
+ return CMD_ENDSECTION4;
+ case CMD_SIDEBAR:
+ return CMD_ENDSIDEBAR;
+ case CMD_TABLE:
+ return CMD_ENDTABLE;
+ default:
+ return cmd;
+ }
+}
+
+QString DocParser::cmdName(int cmd)
+{
+ return *cmds[cmd].alias;
+}
+
+QString DocParser::endCmdName(int cmd)
+{
+ return cmdName(endCmdFor(cmd));
+}
+
+QString DocParser::untabifyEtc(const QString& str)
+{
+ QString result;
+ result.reserve(str.length());
+ int column = 0;
+
+ for (int i = 0; i < str.length(); i++) {
+ const QChar c = str.at(i);
+ if (c == QLatin1Char('\r'))
+ continue;
+ if (c == QLatin1Char('\t')) {
+ result += " " + (column % tabSize);
+ column = ((column / tabSize) + 1) * tabSize;
+ continue;
+ }
+ if (c == QLatin1Char('\n')) {
+ while (result.endsWith(QLatin1Char(' ')))
+ result.chop(1);
+ result += c;
+ column = 0;
+ continue;
+ }
+ result += c;
+ column++;
+ }
+
+ while (result.endsWith("\n\n"))
+ result.truncate(result.length() - 1);
+ while (result.startsWith("\n"))
+ result = result.mid(1);
+
+ return result;
+}
+
+int DocParser::indentLevel(const QString& str)
+{
+ int minIndent = INT_MAX;
+ int column = 0;
+
+ for (int i = 0; i < (int) str.length(); i++) {
+ if (str[i] == '\n') {
+ column = 0;
+ }
+ else {
+ if (str[i] != ' ' && column < minIndent)
+ minIndent = column;
+ column++;
+ }
+ }
+ return minIndent;
+}
+
+QString DocParser::unindent(int level, const QString& str)
+{
+ if (level == 0)
+ return str;
+
+ QString t;
+ int column = 0;
+
+ for (int i = 0; i < (int) str.length(); i++) {
+ if (str[i] == QLatin1Char('\n')) {
+ t += '\n';
+ column = 0;
+ }
+ else {
+ if (column >= level)
+ t += str[i];
+ column++;
+ }
+ }
+ return t;
+}
+
+QString DocParser::slashed(const QString& str)
+{
+ QString result = str;
+ result.replace("/", "\\/");
+ return "/" + result + "/";
+}
+
+#define COMMAND_BRIEF Doc::alias("brief")
+
+#ifdef QDOC_QML
+#define COMMAND_QMLBRIEF Doc::alias("qmlbrief")
+#endif
+
+#ifdef QDOC2DOX
+#define DOXYGEN_INDENT 2
+#define DOXYGEN_TAB_SIZE 4
+#define DOXYGEN_INDENT_STRING " "
+#define DOXYGEN_TAB_STRING " "
+
+static QRegExp ws_rx("\\s");
+static QRegExp not_ws_rx("\\S");
+
+int DoxWriter::doxPass = 0;
+QString DoxWriter::currentClass;
+QSet<QString> DoxWriter::anchors;
+QStringMap DoxWriter::exampleTitles;
+QStringMap DoxWriter::headerFileTitles;
+QStringMap DoxWriter::fileTitles;
+QStringMap DoxWriter::groupTitles;
+QStringMap DoxWriter::moduleTitles;
+QStringMap DoxWriter::pageTitles;
+QStringMap DoxWriter::externalPageTitles;
+QStringMap DoxWriter::exampleTitlesInverse;
+QStringMap DoxWriter::headerFileTitlesInverse;
+QStringMap DoxWriter::fileTitlesInverse;
+QStringMap DoxWriter::groupTitlesInverse;
+QStringMap DoxWriter::moduleTitlesInverse;
+QStringMap DoxWriter::pageTitlesInverse;
+QStringMap DoxWriter::externalPageTitlesInverse;
+QStringMultiMap DoxWriter::variables;
+QStringMultiMap DoxWriter::properties;
+QStringMultiMap DoxWriter::enums;
+#endif
+
+Doc::Doc(const Location& start_loc,
+ const Location& end_loc,
+ const QString& source,
+ const QSet<QString>& metaCommandSet)
+{
+ priv = new DocPrivate(start_loc,end_loc,source);
+ DocParser parser;
+ parser.parse(source,priv,metaCommandSet);
+#ifdef QDOC2DOX
+ if (DoxWriter::isDoxPass()) {
+ DoxWriter doxWriter(source,priv);
+ if (DoxWriter::isDoxPass(1))
+ doxWriter.pass1();
+ else
+ doxWriter.pass2();
+ }
+#endif
+}
+
+Doc::Doc(const Doc& doc)
+ : priv(0)
+{
+ operator=(doc);
+}
+
+Doc::~Doc()
+{
+ if (priv && priv->deref())
+ delete priv;
+}
+
+Doc &Doc::operator=(const Doc& doc)
+{
+ if (doc.priv)
+ doc.priv->ref();
+ if (priv && priv->deref())
+ delete priv;
+ priv = doc.priv;
+ return *this;
+}
+
+void Doc::renameParameters(const QStringList &oldNames,
+ const QStringList &newNames)
+{
+ if (priv && oldNames != newNames) {
+ detach();
+
+ priv->params = newNames.toSet();
+
+ Atom *atom = priv->text.firstAtom();
+ while (atom) {
+ if (atom->type() == Atom::FormattingLeft
+ && atom->string() == ATOM_FORMATTING_PARAMETER) {
+ atom = atom->next();
+ if (!atom)
+ return;
+ int index = oldNames.indexOf(atom->string());
+ if (index != -1 && index < newNames.count())
+ atom->setString(newNames.at(index));
+ }
+ atom = atom->next();
+ }
+ }
+}
+
+void Doc::simplifyEnumDoc()
+{
+ if (priv) {
+ if (priv->isEnumDocSimplifiable()) {
+ detach();
+
+ Text newText;
+
+ Atom *atom = priv->text.firstAtom();
+ while (atom) {
+ if ((atom->type() == Atom::ListLeft) &&
+ (atom->string() == ATOM_LIST_VALUE)) {
+ while (atom && ((atom->type() != Atom::ListRight) ||
+ (atom->string() != ATOM_LIST_VALUE)))
+ atom = atom->next();
+ if (atom)
+ atom = atom->next();
+ }
+ else {
+ newText << *atom;
+ atom = atom->next();
+ }
+ }
+ priv->text = newText;
+ }
+ }
+}
+
+void Doc::setBody(const Text &text)
+{
+ detach();
+ priv->text = text;
+}
+
+/*!
+ Returns the starting location of a qdoc comment.
+ */
+const Location &Doc::location() const
+{
+ static const Location dummy;
+ return priv == 0 ? dummy : priv->start_loc;
+}
+
+const QString &Doc::source() const
+{
+ static QString null;
+ return priv == 0 ? null : priv->src;
+}
+
+bool Doc::isEmpty() const
+{
+ return priv == 0 || priv->src.isEmpty();
+}
+
+const Text& Doc::body() const
+{
+ static const Text dummy;
+ return priv == 0 ? dummy : priv->text;
+}
+
+Text Doc::briefText() const
+{
+ return body().subText(Atom::BriefLeft, Atom::BriefRight);
+}
+
+Text Doc::trimmedBriefText(const QString &className) const
+{
+ QString classNameOnly = className;
+ if (className.contains("::"))
+ classNameOnly = className.split("::").last();
+
+ Text originalText = briefText();
+ Text resultText;
+ const Atom *atom = originalText.firstAtom();
+ if (atom) {
+ QString briefStr;
+ QString whats;
+ bool standardWording = true;
+
+ /*
+ This code is really ugly. The entire \brief business
+ should be rethought.
+ */
+ while (atom && (atom->type() == Atom::AutoLink || atom->type() == Atom::String)) {
+ briefStr += atom->string();
+ atom = atom->next();
+ }
+
+ QStringList w = briefStr.split(" ");
+ if (!w.isEmpty() && w.first() == "The")
+ w.removeFirst();
+ else {
+ location().warning(
+ tr("Nonstandard wording in '\\%1' text for '%2' (expected 'The')")
+ .arg(COMMAND_BRIEF).arg(className));
+ standardWording = false;
+ }
+
+ if (!w.isEmpty() && (w.first() == className || w.first() == classNameOnly))
+ w.removeFirst();
+ else {
+ location().warning(
+ tr("Nonstandard wording in '\\%1' text for '%2' (expected '%3')")
+ .arg(COMMAND_BRIEF).arg(className).arg(className));
+ standardWording = false;
+ }
+
+ if (!w.isEmpty() && (w.first() == "class" || w.first() == "widget"
+ || w.first() == "namespace" || w.first() == "header"))
+ w.removeFirst();
+ else {
+ location().warning(
+ tr("Nonstandard wording in '\\%1' text for '%2' ("
+ "expected 'class', 'widget', 'namespace' or 'header')")
+ .arg(COMMAND_BRIEF).arg(className));
+ standardWording = false;
+ }
+
+ if (!w.isEmpty() && (w.first() == "is" || w.first() == "provides"))
+ w.removeFirst();
+
+ if (!w.isEmpty() && (w.first() == "a" || w.first() == "an"))
+ w.removeFirst();
+
+ whats = w.join(" ");
+ if (whats.endsWith("."))
+ whats.truncate(whats.length() - 1);
+
+ if (whats.isEmpty()) {
+ location().warning(
+ tr("Nonstandard wording in '\\%1' text for '%2' (expected more text)")
+ .arg(COMMAND_BRIEF).arg(className));
+ standardWording = false;
+ }
+ else
+ whats[0] = whats[0].toUpper();
+
+ // ### move this once \brief is abolished for properties
+ if (standardWording)
+ resultText << whats;
+ }
+ return resultText;
+}
+
+Text Doc::legaleseText() const
+{
+ if (priv == 0 || !priv->hasLegalese)
+ return Text();
+ else
+ return body().subText(Atom::LegaleseLeft, Atom::LegaleseRight);
+}
+
+const QString& Doc::baseName() const
+{
+ static QString null;
+ if (priv == 0 || priv->extra == 0) {
+ return null;
+ }
+ else {
+ return priv->extra->baseName;
+ }
+}
+
+Doc::SectioningUnit Doc::granularity() const
+{
+ if (priv == 0 || priv->extra == 0) {
+ return DocPrivateExtra().granularity;
+ }
+ else {
+ return priv->extra->granularity;
+ }
+}
+
+#if notyet // ###
+Doc::SectioningUnit Doc::sectioningUnit() const
+{
+ if (priv == 0 || priv->extra == 0) {
+ return DocPrivateExtra().sectioningUnit;
+ }
+ else {
+ return priv->extra->sectioningUnit;
+ }
+}
+#endif
+
+const QSet<QString> &Doc::parameterNames() const
+{
+ return priv == 0 ? *null_Set_QString() : priv->params;
+}
+
+const QStringList &Doc::enumItemNames() const
+{
+ return priv == 0 ? *null_QStringList() : priv->enumItemList;
+}
+
+const QStringList &Doc::omitEnumItemNames() const
+{
+ return priv == 0 ? *null_QStringList() : priv->omitEnumItemList;
+}
+
+const QSet<QString> &Doc::metaCommandsUsed() const
+{
+ return priv == 0 ? *null_Set_QString() : priv->metacommandsUsed;
+}
+
+QStringList Doc::metaCommandArgs(const QString& metacommand) const
+{
+ return priv == 0 ? QStringList() : priv->metaCommandMap.value(metacommand);
+}
+
+const QList<Text> &Doc::alsoList() const
+{
+ return priv == 0 ? *null_QList_Text() : priv->alsoList;
+}
+
+bool Doc::hasTableOfContents() const
+{
+ return priv && priv->extra && !priv->extra->tableOfContents.isEmpty();
+}
+
+bool Doc::hasKeywords() const
+{
+ return priv && priv->extra && !priv->extra->keywords.isEmpty();
+}
+
+bool Doc::hasTargets() const
+{
+ return priv && priv->extra && !priv->extra->targets.isEmpty();
+}
+
+const QList<Atom *> &Doc::tableOfContents() const
+{
+ priv->constructExtra();
+ return priv->extra->tableOfContents;
+}
+
+const QList<int> &Doc::tableOfContentsLevels() const
+{
+ priv->constructExtra();
+ return priv->extra->tableOfContentsLevels;
+}
+
+const QList<Atom *> &Doc::keywords() const
+{
+ priv->constructExtra();
+ return priv->extra->keywords;
+}
+
+const QList<Atom *> &Doc::targets() const
+{
+ priv->constructExtra();
+ return priv->extra->targets;
+}
+
+const QStringMap &Doc::metaTagMap() const
+{
+ return priv && priv->extra ? priv->extra->metaMap : *null_QStringMap();
+}
+
+void Doc::initialize(const Config& config)
+{
+ DocParser::tabSize = config.getInt(CONFIG_TABSIZE);
+ DocParser::exampleFiles = config.getStringList(CONFIG_EXAMPLES);
+ DocParser::exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS);
+ DocParser::sourceFiles = config.getStringList(CONFIG_SOURCES);
+ DocParser::sourceDirs = config.getStringList(CONFIG_SOURCEDIRS);
+ DocParser::quoting = config.getBool(CONFIG_QUOTINGINFORMATION);
+
+ QStringMap reverseAliasMap;
+
+ QSet<QString> commands = config.subVars(CONFIG_ALIAS);
+ QSet<QString>::ConstIterator c = commands.begin();
+ while (c != commands.end()) {
+ QString alias = config.getString(CONFIG_ALIAS + Config::dot + *c);
+ if (reverseAliasMap.contains(alias)) {
+ config.lastLocation().warning(tr("Command name '\\%1' cannot stand"
+ " for both '\\%2' and '\\%3'")
+ .arg(alias)
+ .arg(reverseAliasMap[alias])
+ .arg(*c));
+ }
+ else {
+ reverseAliasMap.insert(alias, *c);
+ }
+ aliasMap()->insert(*c, alias);
+ ++c;
+ }
+
+ int i = 0;
+ while (cmds[i].english) {
+ cmds[i].alias = new QString(alias(cmds[i].english));
+ cmdHash()->insert(*cmds[i].alias, cmds[i].no);
+
+ if (cmds[i].no != i)
+ Location::internalError(tr("command %1 missing").arg(i));
+ i++;
+ }
+
+ QSet<QString> macroNames = config.subVars(CONFIG_MACRO);
+ QSet<QString>::ConstIterator n = macroNames.begin();
+ while (n != macroNames.end()) {
+ QString macroDotName = CONFIG_MACRO + Config::dot + *n;
+ Macro macro;
+ macro.numParams = -1;
+ macro.defaultDef = config.getString(macroDotName);
+ if (!macro.defaultDef.isEmpty()) {
+ macro.defaultDefLocation = config.lastLocation();
+ macro.numParams = Config::numParams(macro.defaultDef);
+ }
+ bool silent = false;
+
+ QSet<QString> formats = config.subVars(macroDotName);
+ QSet<QString>::ConstIterator f = formats.begin();
+ while (f != formats.end()) {
+ QString def = config.getString(macroDotName + Config::dot + *f);
+ if (!def.isEmpty()) {
+ macro.otherDefs.insert(*f, def);
+ int m = Config::numParams(macro.defaultDef);
+ if (macro.numParams == -1) {
+ macro.numParams = m;
+ }
+ else if (macro.numParams != m) {
+ if (!silent) {
+ QString other = tr("default");
+ if (macro.defaultDef.isEmpty())
+ other = macro.otherDefs.begin().key();
+ config.lastLocation().warning(tr("Macro '\\%1' takes"
+ " inconsistent number"
+ " of arguments (%2"
+ " %3, %4 %5)")
+ .arg(*n)
+ .arg(*f)
+ .arg(m)
+ .arg(other)
+ .arg(macro.numParams));
+ silent = true;
+ }
+ if (macro.numParams < m)
+ macro.numParams = m;
+ }
+ }
+ ++f;
+ }
+
+ if (macro.numParams != -1)
+ macroHash()->insert(*n, macro);
+ ++n;
+ }
+}
+
+void Doc::terminate()
+{
+ DocParser::exampleFiles.clear();
+ DocParser::exampleDirs.clear();
+ DocParser::sourceFiles.clear();
+ DocParser::sourceDirs.clear();
+ aliasMap()->clear();
+ cmdHash()->clear();
+ macroHash()->clear();
+
+ int i = 0;
+ while (cmds[i].english) {
+ delete cmds[i].alias;
+ cmds[i].alias = 0;
+ ++i;
+ }
+}
+
+QString Doc::alias(const QString &english)
+{
+ return aliasMap()->value(english, english);
+}
+
+/*!
+ Trims the deadwood out of \a str. i.e., this function
+ cleans up \a str.
+ */
+void Doc::trimCStyleComment(Location& location, QString& str)
+{
+ QString cleaned;
+ Location m = location;
+ bool metAsterColumn = true;
+ int asterColumn = location.columnNo() + 1;
+ int i;
+
+ for (i = 0; i < (int) str.length(); i++) {
+ if (m.columnNo() == asterColumn) {
+ if (str[i] != '*')
+ break;
+ cleaned += ' ';
+ metAsterColumn = true;
+ }
+ else {
+ if (str[i] == '\n') {
+ if (!metAsterColumn)
+ break;
+ metAsterColumn = false;
+ }
+ cleaned += str[i];
+ }
+ m.advance(str[i]);
+ }
+ if (cleaned.length() == str.length())
+ str = cleaned;
+
+ for (int i = 0; i < 3; i++)
+ location.advance(str[i]);
+ str = str.mid(3, str.length() - 5);
+}
+
+CodeMarker *Doc::quoteFromFile(const Location &location,
+ Quoter &quoter,
+ const QString &fileName)
+{
+ quoter.reset();
+
+ QString code;
+
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(location,
+ DocParser::exampleFiles,
+ DocParser::exampleDirs,
+ fileName, userFriendlyFilePath);
+ if (filePath.isEmpty()) {
+ location.warning(tr("Cannot find example file '%1'").arg(fileName));
+ }
+ else {
+ QFile inFile(filePath);
+ if (!inFile.open(QFile::ReadOnly)) {
+ location.warning(tr("Cannot open example file '%1'").arg(userFriendlyFilePath));
+ }
+ else {
+ QTextStream inStream(&inFile);
+ code = DocParser::untabifyEtc(inStream.readAll());
+ }
+ }
+
+ QString dirPath = QFileInfo(filePath).path();
+ CodeMarker *marker = CodeMarker::markerForFileName(fileName);
+ quoter.quoteFromFile(userFriendlyFilePath,
+ code,
+ marker->markedUpCode(code, 0, dirPath));
+ return marker;
+}
+
+QString Doc::canonicalTitle(const QString &title)
+{
+ // The code below is equivalent to the following chunk, but _much_
+ // faster (accounts for ~10% of total running time)
+ //
+ // QRegExp attributeExpr("[^A-Za-z0-9]+");
+ // QString result = title.toLower();
+ // result.replace(attributeExpr, " ");
+ // result = result.simplified();
+ // result.replace(QLatin1Char(' '), QLatin1Char('-'));
+
+ QString result;
+ result.reserve(title.size());
+
+ bool slurping = false;
+ bool begun = false;
+ int lastAlnum = 0;
+ for (int i = 0; i != title.size(); ++i) {
+ uint c = title.at(i).unicode();
+ if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 'a';
+ bool alnum = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');
+ if (alnum) {
+ result += QLatin1Char(c);
+ begun = true;
+ slurping = false;
+ lastAlnum = result.size();
+ }
+ else if (!slurping) {
+ if (begun)
+ result += QLatin1Char('-');
+ slurping = true;
+ }
+ else {
+ // !alnum && slurping -> nothin
+ }
+ }
+ result.truncate(lastAlnum);
+ return result;
+}
+
+void Doc::detach()
+{
+ if (!priv) {
+ priv = new DocPrivate;
+ return;
+ }
+ if (priv->count == 1)
+ return;
+
+ --priv->count;
+
+ DocPrivate *newPriv = new DocPrivate(*priv);
+ newPriv->count = 1;
+ if (priv->extra)
+ newPriv->extra = new DocPrivateExtra(*priv->extra);
+
+ priv = newPriv;
+}
+
+#ifdef QDOC2DOX
+/*!
+ Sets the doxygen writer pass to \a pass. You can use
+ isDoxPass(), with or without a parameter, to test if
+ you are in a doxygen writer run or in a specific pass
+ of a doxygen writer run.
+
+ This function is only called from main() if either the
+ \e doxygen1 or \e doxygen2 flag is passed to qdoc3 on
+ the command line.
+ */
+void DoxWriter::setDoxPass(int pass)
+{
+ qDebug() << "SETTING doxygen pass to " << pass
+ << " in DoxWriter::setDoxPass()";
+ doxPass = pass;
+}
+
+/*!
+ Returns true if the doxygen pass is set to \a pass,
+ which means we are in the specified \a pass of a doxygen
+ writer run of qdoc3.
+ */
+bool DoxWriter::isDoxPass(int pass) { return (doxPass == pass); }
+
+/*!
+ Returns true if the doxygen pass is 1 or 2, which
+ means this is a doxygen writer run to transform qdoc
+ comments into doxygen comments.
+ */
+bool DoxWriter::isDoxPass() { return (doxPass > 0); }
+
+bool DoxWriter::conversionRequired() const
+{
+ /*
+ Loop through all the topic commands searching for
+ one that must be transformed to doxygen format. If
+ one is found, return true.
+ */
+ QCommandMap::const_iterator i;
+ i = priv->metaCommandMap.constBegin();
+ while (i != priv->metaCommandMap.constEnd()) {
+ QString s = i.key();
+ if (s == "enum")
+ return true;
+ else if (s == "example")
+ return true;
+ else if (s == "externalpage")
+ return true;
+ else if (s == "group")
+ return true;
+ else if (s == "headerfile")
+ return true;
+ else if (s == "module")
+ return true;
+ else if (s == "page")
+ return true;
+ else if (s == "property")
+ return true;
+ else if (s == "typedef")
+ return true;
+ else if (s == "variable")
+ return true;
+ else if (s == "overload")
+ return true;
+ else if (s == "reimp")
+ return true;
+ else if (s == "relates")
+ return true;
+ else if (s == "macro")
+ return true;
+ else {
+#if 0
+ if (s == "class")
+ else if (s == "namespace")
+ else if (s == "service")
+ else if (s == "inheaderfile")
+ else if (s == "file")
+ else if (s == "fn")
+ else if (s == "contentspage")
+ else if (s == "nextpage")
+ else if (s == "previous")
+ else if (s == "indexpage")
+ else if (s == "startpage")
+#endif
+ }
+ ++i;
+ }
+
+ /*
+ Loop through all the qdoc atoms searching for one
+ that must be transformed to doxygen format. If one
+ is found, return true.
+ */
+ const Atom* next = priv->text.firstAtom();
+ while (next != 0) {
+ Atom::Type atomType = next->type();
+ switch (atomType) {
+ case Atom::C:
+ case Atom::CaptionLeft:
+ case Atom::Code:
+ case Atom::CodeBad:
+ case Atom::CodeNew:
+ case Atom::CodeOld:
+ case Atom::CodeQuoteArgument:
+ case Atom::CodeQuoteCommand:
+ case Atom::FootnoteLeft:
+ case Atom::FormatElse:
+ case Atom::FormatEndif:
+ case Atom::FormatIf:
+ case Atom::GeneratedList:
+ case Atom::Image:
+ case Atom::ImageText:
+ case Atom::InlineImage:
+ case Atom::LegaleseLeft:
+ case Atom::LineBreak:
+ case Atom::Link:
+ case Atom::LinkNode:
+ case Atom::ListLeft:
+ case Atom::ListItemNumber:
+ case Atom::ListTagLeft:
+ case Atom::ListItemLeft:
+ case Atom::QuotationLeft:
+ case Atom::RawString:
+ case Atom::SectionLeft:
+ case Atom::SectionHeadingLeft:
+ case Atom::SidebarLeft:
+ case Atom::SnippetCommand:
+ case Atom::SnippetIdentifier:
+ case Atom::SnippetLocation:
+ case Atom::TableLeft:
+ case Atom::TableHeaderLeft:
+ case Atom::TableRowLeft:
+ case Atom::TableItemLeft:
+ case Atom::TableOfContents:
+ case Atom::Target:
+ return true;
+ case Atom::AbstractLeft:
+ case Atom::AbstractRight:
+ case Atom::AutoLink:
+ case Atom::BaseName:
+ case Atom::BriefLeft:
+ case Atom::BriefRight:
+ case Atom::CaptionRight:
+ case Atom::FormattingLeft:
+ case Atom::FormattingRight:
+ case Atom::Nop:
+ case Atom::ParaLeft:
+ case Atom::ParaRight:
+ case Atom::FootnoteRight:
+ case Atom::LegaleseRight:
+ case Atom::ListTagRight:
+ case Atom::ListItemRight:
+ case Atom::ListRight:
+ case Atom::QuotationRight:
+ case Atom::SectionRight:
+ case Atom::SectionHeadingRight:
+ case Atom::SidebarRight:
+ case Atom::String:
+ case Atom::TableRight:
+ case Atom::TableHeaderRight:
+ case Atom::TableRowRight:
+ case Atom::TableItemRight:
+ default:
+ break;
+ }
+ next = next->next();
+ }
+ return false;
+}
+
+/*!
+ A convenience function to write a qdoc metacommand as a
+ doxygen command, without conversion. i.e., some of the
+ qdoc metacommands don't require conversion for doxygen.
+ */
+void DoxWriter::writeCommand(QCommandMap::const_iterator cmd)
+{
+ concatenate("\\" + cmd.key() + " " + cmd.value()[0]);
+ newLine();
+}
+
+/*!
+ Convert the qdoc commands in the metacommand map to
+ doxygen format. This function is called only in pass2().
+ The metacommand map contains all the metacommands that
+ were found in the qdoc comment that is being converted.
+ The metacommands are the ones that begin with the '\'.
+ These are not considered part of the text of the comment.
+ The text is converted by convertText().
+ */
+void DoxWriter::convertMetaCommands()
+{
+ QCommandMap& metaCmdMap = priv->metaCommandMap;
+ QCommandMap::iterator cmd;
+ int c;
+
+ currentPage.clear();
+ currentFn.clear();
+ currentTitle.clear();
+ currentEnum.clear();
+ currentProperty.clear();
+ currentVariable.clear();
+ currentClass.clear();
+ currentExample.clear();
+ currentGroup.clear();
+ currentModule.clear();
+ currentMacro.clear();
+ currentService.clear();
+ currentTypedef.clear();
+ currentHeaderFile.clear();
+ commentType = OtherComment;
+
+ if ((cmd = metaCmdMap.find("class")) != metaCmdMap.end()) {
+ currentClass = cmd.value()[0];
+ if ((c = currentClass.indexOf(' ')) > 0)
+ currentClass = currentClass.left(c);
+ writeCommand(cmd);
+ metaCmdMap.erase(cmd);
+ commentType = ClassComment;
+ }
+ else if ((cmd = metaCmdMap.find("fn")) != metaCmdMap.end()) {
+ currentFn = cmd.value()[0];
+ writeCommand(cmd);
+ metaCmdMap.erase(cmd);
+ commentType = FnComment;
+ }
+ else if ((cmd = metaCmdMap.find("enum")) != metaCmdMap.end()) {
+ currentEnum = cmd.value()[0];
+ if ((c = currentEnum.lastIndexOf("::")) > 0) {
+ currentClass = currentEnum.left(c);
+ currentEnum = currentEnum.right(currentEnum.size()-c-2);
+ qDebug() << "currentEnum =" << currentEnum;
+ qDebug() << "currentClass =" << currentClass;
+ }
+ writeCommand(cmd);
+ metaCmdMap.erase(cmd);
+ commentType = EnumComment;
+ }
+ else if ((cmd = metaCmdMap.find("property")) != metaCmdMap.end()) {
+ currentClass = cmd.value()[0];
+ if ((c = currentClass.lastIndexOf("::")) > 0) {
+ currentProperty = currentClass.right(currentClass.size()-c-2);
+ currentClass = currentClass.left(c);
+ qDebug() << "currentProperty =" << currentProperty;
+ qDebug() << "currentClass =" << currentClass;
+ }
+ writeCommand(cmd);
+ metaCmdMap.erase(cmd);
+ commentType = PropertyComment;
+ }
+ else if ((cmd = metaCmdMap.find("variable")) != metaCmdMap.end()) {
+ currentClass = cmd.value()[0];
+ if ((c = currentClass.lastIndexOf("::")) > 0) {
+ currentVariable = currentClass.right(currentClass.size()-c-2);
+ currentClass = currentClass.left(c);
+ qDebug() << "currentVariable =" << currentVariable;
+ qDebug() << "currentClass =" << currentClass;
+ }
+ concatenate("\\var " + cmd.value()[0]);
+ newLine();
+ metaCmdMap.erase(cmd);
+ commentType = VariableComment;
+ }
+
+ if ((cmd = metaCmdMap.find("page")) != metaCmdMap.end()) {
+ currentPage = cmd.value()[0];
+ QString htmlFile = currentPage;
+ const QString* title = getPageTitle(htmlFile);
+ QStringList parts = htmlFile.split('.');
+ metaCmdMap.erase(cmd);
+ if (title) {
+ concatenate("\\page " + parts[0] + " " + *title);
+ newLine();
+ }
+ commentType = PageComment;
+ qDebug() << "currentPage =" << currentPage;
+ }
+
+ if ((cmd = metaCmdMap.find("example")) != metaCmdMap.end()) {
+ currentExample = cmd.value()[0];
+ metaCmdMap.erase(cmd);
+ commentType = ExampleComment;
+ qDebug() << "currentExample =" << currentExample;
+ }
+
+ if ((cmd = metaCmdMap.find("macro")) != metaCmdMap.end()) {
+ currentMacro = cmd.value()[0];
+ metaCmdMap.erase(cmd);
+ commentType = MacroComment;
+ qDebug() << "currentMacro =" << currentMacro;
+ }
+
+ if ((cmd = metaCmdMap.find("group")) != metaCmdMap.end()) {
+ currentGroup = cmd.value()[0];
+ metaCmdMap.erase(cmd);
+ commentType = GroupComment;
+ qDebug() << "currentGroup =" << currentGroup;
+ }
+
+ if ((cmd = metaCmdMap.find("module")) != metaCmdMap.end()) {
+ currentModule = cmd.value()[0];
+ metaCmdMap.erase(cmd);
+ commentType = ModuleComment;
+ qDebug() << "currentModule =" << currentModule;
+ }
+
+ if ((cmd = metaCmdMap.find("headerfile")) != metaCmdMap.end()) {
+ currentHeaderFile = cmd.value()[0];
+ metaCmdMap.erase(cmd);
+ commentType = HeaderFileComment;
+ qDebug() << "currentHeaderFile =" << currentHeaderFile;
+ }
+
+ if ((cmd = metaCmdMap.find("typedef")) != metaCmdMap.end()) {
+ currentClass = cmd.value()[0];
+ if ((c = currentClass.lastIndexOf("::")) > 0) {
+ currentTypedef = currentClass.right(currentClass.size()-c-2);
+ currentClass = currentClass.left(c);
+ }
+ metaCmdMap.erase(cmd);
+ commentType = TypedefComment;
+ qDebug() << "currentTypedef =" << currentTypedef;
+ qDebug() << "currentClass =" << currentClass;
+ }
+
+ cmd = priv->metaCommandMap.begin();
+ while (cmd != priv->metaCommandMap.end()) {
+ for (int i=0; i<cmd.value().size(); i++) {
+ concatenate("\\" + cmd.key() + " " + cmd.value()[i]);
+ newLine();
+ }
+ //qDebug() << " " << cmd.key() << ": " << cmd.value();
+ ++cmd;
+ }
+}
+
+/*!
+ Convert the qdoc text to doxygen format. The metacommands
+ are converted by convertMetaCommands(). This function is
+ called in pass2().
+ */
+void DoxWriter::convertText()
+{
+ const Atom* prev = 0;
+ const Atom* next = priv->text.firstAtom();
+ while (next != 0) {
+ next->dump();
+ Atom::Type atomType = next->type();
+ switch (atomType) {
+ case Atom::AbstractLeft:
+ break;
+ case Atom::AbstractRight:
+ break;
+ case Atom::AutoLink:
+ concatenate(next->string());
+ break;
+ case Atom::BaseName:
+ break;
+ case Atom::BriefLeft:
+ concatenate("\\brief ");
+ break;
+ case Atom::BriefRight:
+ newLine();
+ break;
+ case Atom::C:
+ tt(next);
+ break;
+ case Atom::CaptionLeft:
+ unhandled(next);
+ break;
+ case Atom::CaptionRight:
+ unhandled(next);
+ break;
+ case Atom::Code:
+ code(next);
+ break;
+ case Atom::CodeBad:
+ code(next);
+ break;
+ case Atom::CodeNew:
+ newLine();
+ concatenate("you can rewrite it as");
+ code(next);
+ break;
+ case Atom::CodeOld:
+ newLine();
+ concatenate("For example, if you have code like");
+ code(next);
+ break;
+ case Atom::CodeQuoteArgument:
+ unhandled(next);
+ break;
+ case Atom::CodeQuoteCommand:
+ next = codeQuoteCommand(next);
+ break;
+ case Atom::FootnoteLeft:
+ break;
+ case Atom::FootnoteRight:
+ break;
+ case Atom::FormatElse:
+ formatElse();
+ break;
+ case Atom::FormatEndif:
+ formatEndif();
+ break;
+ case Atom::FormatIf:
+ formatIf(next);
+ break;
+ case Atom::FormattingLeft:
+ formattingLeft(next,next->next());
+ break;
+ case Atom::FormattingRight:
+ formattingRight(next,prev);
+ break;
+ case Atom::GeneratedList:
+ break;
+ case Atom::Image:
+ break;
+ case Atom::ImageText:
+ break;
+ case Atom::InlineImage:
+ break;
+ case Atom::LegaleseLeft:
+ break;
+ case Atom::LegaleseRight:
+ break;
+ case Atom::LineBreak:
+ break;
+ case Atom::Link:
+ next = link(next);
+ break;
+ case Atom::LinkNode:
+ break;
+ case Atom::ListLeft:
+ {
+ bool nested = false;
+ if (structs.isEmpty()) {
+ const Atom* i = next->next();
+ while (i->type() != Atom::ListRight) {
+ if ((i->type() == Atom::ListLeft) ||
+ (i->type() == Atom::TableLeft)) {
+ nested = true;
+ break;
+ }
+ i = i->next();
+ }
+ }
+ else
+ nested = true;
+ StructDesc d(BulletList,nested);
+ if (next->string() == "numeric")
+ d.structType = NumericList;
+ else if (next->string() == "value") {
+ d.structType = ValueList;
+ }
+ else if (next->string() != "bullet")
+ qDebug() << "UNKNOWN LIST TYPE" << next->string();
+ structs.push(d);
+ if (nested || (d.structType != BulletList)) {
+ if (d.structType == BulletList)
+ concatenate("<ul>");
+ else if (d.structType == NumericList)
+ concatenate("<ol>");
+ else if (d.structType == ValueList)
+ concatenate("<dl>");
+ newLine();
+ }
+ }
+ break;
+ case Atom::ListItemNumber:
+ structs.top().count = next->string().toInt();
+ break;
+ case Atom::ListTagLeft:
+ {
+ structs.top().count++;
+ concatenate("<dt>");
+ const Atom* n = next->next();
+ if (n->type() == Atom::String) {
+ qDebug() << "ENUM VALUE" << n->string();
+ }
+ else
+ qDebug() << "NOT EN ENUM";
+ }
+ break;
+ case Atom::ListTagRight:
+ concatenate("</dt>");
+ break;
+ case Atom::ListItemLeft:
+ {
+ newLine();
+ const StructDesc& d = structs.top();
+ if (d.structType == BulletList) {
+ if (!d.nested)
+ concatenate("\\arg ");
+ else
+ concatenate("<li>");
+ }
+ else if (d.structType == NumericList)
+ concatenate("<li>");
+ else if (d.structType == ValueList)
+ concatenate("<dd>");
+ }
+ break;
+ case Atom::ListItemRight:
+ {
+ const StructDesc& d = structs.top();
+ if (d.structType == BulletList) {
+ if (d.nested) {
+ concatenate("</li>");
+ newLine();
+ }
+ }
+ else if (d.structType == NumericList) {
+ concatenate("</li>");
+ newLine();
+ }
+ else if (d.structType == ValueList) {
+ concatenate("</dd>");
+ newLine();
+ }
+ }
+ break;
+ case Atom::ListRight:
+ {
+ if (!structs.isEmpty()) {
+ const StructDesc& d = structs.top();
+ if (d.nested || (d.structType != BulletList)) {
+ if (d.structType == BulletList)
+ concatenate("</ul>");
+ else if (d.structType == NumericList)
+ concatenate("</ol>");
+ else if (d.structType == ValueList)
+ concatenate("</dl>");
+ newLine();
+ }
+ structs.pop();
+ }
+ }
+ break;
+ case Atom::Nop:
+ // nothing.
+ break;
+ case Atom::ParaLeft:
+ if (structs.isEmpty())
+ newLine();
+ break;
+ case Atom::ParaRight:
+ {
+ if (structs.isEmpty())
+ newLine();
+ else {
+ const StructDesc& d = structs.top();
+ if (d.nested || (d.structType != BulletList)) {
+ Atom::Type t = next->next()->type();
+ if ((t != Atom::ListItemRight) &&
+ (t != Atom::TableItemRight))
+ newLine();
+ }
+ else
+ newLine();
+ }
+ }
+ break;
+ case Atom::QuotationLeft:
+ break;
+ case Atom::QuotationRight:
+ break;
+ case Atom::RawString:
+ concatenate(next->string());
+ break;
+ case Atom::SectionLeft:
+ // nothing.
+ break;
+ case Atom::SectionRight:
+ // nothing.
+ break;
+ case Atom::SectionHeadingLeft:
+ next = sectionHeading(next);
+ break;
+ case Atom::SectionHeadingRight:
+ newLine();
+ break;
+ case Atom::SidebarLeft:
+ break;
+ case Atom::SidebarRight:
+ break;
+ case Atom::SnippetCommand:
+ newLine();
+ concatenate("\\snippet ");
+ break;
+ case Atom::SnippetIdentifier:
+ newText += next->string();
+ lineLength += next->string().size();
+ newLine();
+ break;
+ case Atom::SnippetLocation:
+ newText += next->string() + " ";
+ lineLength += next->string().size() + 1;
+ break;
+ case Atom::String:
+ wrap(next->string());
+ break;
+ case Atom::TableLeft:
+ {
+ bool nested = false;
+ if (structs.isEmpty()) {
+ const Atom* i = next->next();
+ while (i->type() != Atom::TableRight) {
+ if ((i->type() == Atom::ListLeft) ||
+ (i->type() == Atom::TableLeft)) {
+ nested = true;
+ break;
+ }
+ i = i->next();
+ }
+ }
+ else
+ nested = true;
+ StructDesc d(Table,nested);
+ structs.push(d);
+ if (next->string().isEmpty())
+ concatenate("<table>");
+ else {
+ QString attrs = "width=\"" + next->string() + "\"";
+ attrs += " align=\"center\"";
+ concatenate("<table " + attrs + ">");
+ }
+ newLine();
+ }
+ break;
+ case Atom::TableRight:
+ concatenate("</table>");
+ if (!structs.isEmpty())
+ structs.pop();
+ newLine();
+ break;
+ case Atom::TableHeaderLeft:
+ concatenate("<tr>");
+ if (!structs.isEmpty())
+ structs.top().inTableHeader = true;
+ newLine();
+ break;
+ case Atom::TableHeaderRight:
+ concatenate("</tr>");
+ if (!structs.isEmpty())
+ structs.top().inTableHeader = false;
+ newLine();
+ break;
+ case Atom::TableRowLeft:
+ if (!structs.isEmpty()) {
+ structs.top().inTableRow = true;
+ concatenate("<tr valign=\"top\" class=\"");
+ if (structs.top().odd)
+ concatenate("odd\">");
+ else
+ concatenate("even\">");
+ structs.top().odd = !structs.top().odd;
+ }
+ newLine();
+ break;
+ case Atom::TableRowRight:
+ concatenate("</tr>");
+ if (!structs.isEmpty())
+ structs.top().inTableRow = false;
+ newLine();
+ break;
+ case Atom::TableItemLeft:
+ if (!structs.isEmpty()) {
+ structs.top().inTableItem = true;
+ concatenate("<td>");
+ if (structs.top().inTableHeader)
+ concatenate("<b> ");
+ }
+ break;
+ case Atom::TableItemRight:
+ if (!structs.isEmpty()) {
+ structs.top().inTableItem = false;
+ if (structs.top().inTableHeader)
+ concatenate(" </b>");
+ concatenate("</td>");
+ }
+ newLine();
+ break;
+ case Atom::TableOfContents:
+ break;
+ case Atom::Target:
+ {
+ QString text = next->string();
+ text.remove(ws_rx);
+ newLine();
+ concatenate("\\anchor ");
+ newText += text;
+ lineLength += text.size();
+ newLine();
+ }
+ break;
+ case Atom::UnhandledFormat:
+ unhandled(next);
+ break;
+ case Atom::UnknownCommand:
+ unhandled(next);
+ break;
+ default:
+ //next->dump();
+ break;
+ }
+ prev = next;
+ next = next->next();
+ }
+}
+
+/*!
+
+ Pass one looks for topic commands and target and section
+ commands, and maybe other stuff. These are serialized to
+ text files, which are read back in by pass2().
+ */
+void DoxWriter::pass1()
+{
+ QCommandMap& metaCmdMap = priv->metaCommandMap;
+ if (!metaCmdMap.isEmpty()) {
+ int c;
+ QCommandMap::iterator cmd;
+ if ((cmd = metaCmdMap.find("enum")) != metaCmdMap.end()) {
+ commentType = EnumComment;
+ currentEnum = cmd.value()[0];
+ if ((c = currentEnum.lastIndexOf("::")) > 0) {
+ currentClass = currentEnum.left(c);
+ currentEnum = currentEnum.right(currentEnum.size()-c-2);
+ qDebug() << "currentEnum =" << currentEnum;
+ qDebug() << "currentClass =" << currentClass;
+ if (enums.contains(currentEnum,currentClass)) {
+ qWarning() << "DoxWriter::pass1():"
+ << "Duplicate enum:"
+ << currentClass << currentEnum;
+ }
+ else
+ enums.insert(currentEnum,currentClass);
+ }
+ }
+ else if ((cmd = metaCmdMap.find("property")) != metaCmdMap.end()) {
+ commentType = PropertyComment;
+ currentClass = cmd.value()[0];
+ if ((c = currentClass.lastIndexOf("::")) > 0) {
+ currentProperty = currentClass.right(currentClass.size()-c-2);
+ currentClass = currentClass.left(c);
+ qDebug() << "currentProperty =" << currentProperty;
+ qDebug() << "currentClass =" << currentClass;
+ if (properties.contains(currentProperty,currentClass)) {
+ qWarning() << "DoxWriter::pass1():"
+ << "Duplicate property:"
+ << currentClass << currentProperty;
+ }
+ else
+ properties.insert(currentProperty,currentClass);
+ }
+ }
+ else if ((cmd = metaCmdMap.find("variable")) != metaCmdMap.end()) {
+ commentType = VariableComment;
+ currentClass = cmd.value()[0];
+ if ((c = currentClass.lastIndexOf("::")) > 0) {
+ currentVariable = currentClass.right(currentClass.size()-c-2);
+ currentClass = currentClass.left(c);
+ qDebug() << "currentVariable =" << currentVariable;
+ qDebug() << "currentClass =" << currentClass;
+ if (variables.contains(currentVariable,currentClass)) {
+ qWarning() << "DoxWriter::pass1():"
+ << "Duplicate variable:"
+ << currentClass << currentVariable;
+ }
+ else
+ variables.insert(currentVariable,currentClass);
+ }
+ }
+ }
+
+ /*
+ */
+ const Atom* next = priv->text.firstAtom();
+ while (next != 0) {
+ switch (next->type()) {
+ case Atom::SectionHeadingLeft:
+ {
+ QString text;
+ next = next->next();
+ while (next) {
+ if (next->type() == Atom::SectionHeadingRight)
+ break;
+ else
+ text += next->string();
+ next = next->next();
+ }
+ //text.remove(ws_rx);
+ insertAnchor(text);
+ }
+ break;
+ case Atom::Target:
+ {
+ QString text = next->string();
+ //text.remove(ws_rx);
+ insertAnchor(text);
+ }
+ default:
+ break;
+ }
+ next = next->next();
+ }
+}
+
+/*!
+ Output a parsed, tokenized qdoc comment as a doxygen
+ comment in diff format for input to the patch command.
+ */
+void DoxWriter::pass2()
+{
+ if (!conversionRequired()) {
+ qDebug() << "NO CONVERSION - FILE:" << priv->start_loc.fileName()
+ << "START:" << priv->start_loc.lineNo()
+ << "END:" << priv->end_loc.lineNo() - 1;
+ return;
+ }
+
+ /*
+ Transformation to doxygen required...
+ */
+ newText = "\n/*! \n";
+ convertMetaCommands();
+ convertText();
+ if (newText[newText.size()-1] == ' ')
+ newText.remove(newText.size()-1,1);
+ newText += " */\n";
+ qDebug() << "CONVERTED COMMENT - FILE:" << priv->start_loc.fileName()
+ << "START:" << priv->start_loc.lineNo()
+ << "END:" << priv->end_loc.lineNo() - 1;
+ qDebug() << newText;
+}
+
+/*!
+ Unparse the second parameter of a "\l" command.
+ */
+const Atom* DoxWriter::link(const Atom* atom)
+{
+ QString first_text = atom->string();
+ QString second_text;
+ const QString* value = 0;
+
+ const Atom* next = atom->next(Atom::FormattingLeft,Atom::LINK_);
+ if (next) {
+ next->dump();
+ while (1) {
+ next = next->next();
+ next->dump();
+ if (next->type() == Atom::FormattingRight) {
+ if (next->string() == Atom::LINK_)
+ break;
+ else {
+ // ignore it.
+ }
+ }
+ else
+ second_text += next->string();
+ }
+ int i = first_text.indexOf('#');
+ if (i >= 0)
+ first_text = first_text.right(first_text.size() - i - 1);
+ //newLine();
+ if ((value = getExternalPage(first_text))) {
+ //qDebug() << "USED AN EXTERNAL PAGE TITLE" << first_text;
+ QString href = "<a href=\""+*value+"\">"+first_text+"</a>";
+ concatenate(href);
+ }
+ else if (first_text.startsWith("http:",Qt::CaseInsensitive)) {
+ if (first_text == second_text) {
+ concatenate(first_text);
+ }
+ else {
+ QString href = "<a href=\""+first_text+"\">"+second_text+"</a>";
+ concatenate(href);
+ }
+ }
+ else if ((value = getPageFile(first_text))) {
+ //qDebug() << "USED A PAGE TITLE" << first_text;
+ QStringList parts = (*value).split('.');
+ QString ref = "\\ref " + parts[0] + " \"" + second_text + "\"";
+ concatenate(ref);
+ }
+ else if ((value = getGroup(first_text))) {
+ //qDebug() << "USED A GROUP TITLE" << first_text;
+ concatenate("\\ref " + *value + " \"" + second_text + "\"");
+ }
+ else if ((value = getModule(first_text))) {
+ //qDebug() << "USED A MODULE TITLE" << first_text;
+ concatenate("\\ref " + *value + " \"" + second_text + "\"");
+ }
+ else if ((value = getExamplePath(first_text))) {
+ //qDebug() << "USED AN EXAMPLE TITLE" << first_text;
+ first_text.remove(ws_rx);
+ QString ref = "\\ref " + first_text + " \"" + second_text + "\"";
+ concatenate(ref);
+ }
+ else if ((value = getFile(first_text))) {
+ //qDebug() << "USED A FILE TITLE" << first_text;
+ // I think this command is no longer available.
+ first_text.remove(ws_rx);
+ QString ref = "\\ref " + first_text + " \"" + second_text + "\"";
+ concatenate(ref);
+ }
+ else if ((value = getHeaderFile(first_text))) {
+ //qDebug() << "USED A HEADER FILE TITLE" << first_text;
+ first_text.remove(ws_rx);
+ QString ref = "\\ref " + first_text + " \"" + second_text + "\"";
+ concatenate(ref);
+ }
+ else if (isAnchor(first_text)) {
+ //qDebug() << "USED AN ANCHOR" << first_text;
+ first_text.remove(ws_rx);
+ QString ref = "\\ref " + first_text + " \"" + second_text + "\"";
+ concatenate(ref);
+ }
+ else if ((value = getPageTitle(first_text))) {
+ //qDebug() << "USED AN INVERSE PAGE TITLE" << first_text;
+ QStringList parts = first_text.split('.');
+ QString ref = "\\ref " + parts[0] + " \"" + second_text + "\"";
+ concatenate(ref);
+ }
+ else if ((value = getExampleTitle(first_text))) {
+ //qDebug() << "USED AN INVERSE EXAMPLE TITLE" << first_text;
+ QString title = *value;
+ title.remove(ws_rx);
+ QString ref = "\\ref " + title + " \"" + second_text + "\"";
+ concatenate(ref);
+ }
+ else if ((value = getGroupTitle(first_text))) {
+ //qDebug() << "USED AN INVERSE GROUP TITLE" << first_text;
+ concatenate("\\ref " + first_text + " \"" + second_text + "\"");
+ }
+ else if ((value = getModuleTitle(first_text))) {
+ //qDebug() << "USED AN INVERSE MODULE TITLE" << first_text;
+ concatenate("\\ref " + first_text + " \"" + second_text + "\"");
+ }
+ else if ((value = getFileTitle(first_text))) {
+ qDebug() << "USED AN INVERSE FILE TITLE" << first_text;
+ }
+ else if ((value = getHeaderFileTitle(first_text))) {
+ qDebug() << "USED AN INVERSE HEADER FILE TITLE" << first_text;
+ }
+ else if ((first_text.indexOf("::") >= 0) ||
+ (first_text.indexOf("()") >= 0) ||
+ (first_text[0] == 'Q')) {
+ //qDebug() << "AUTO-LINKABLE" << first_text;
+ if (first_text == second_text)
+ concatenate(first_text);
+ else {
+ QString link = first_text + " " + second_text;
+ concatenate("\\link " + link + "\\endlink");
+ }
+ }
+ else {
+ QString link;
+ QStringList propertyClasses;
+ QStringList variableClasses;
+ QStringList enumClasses;
+ bool p = isProperty(first_text,propertyClasses);
+ bool v = isVariable(first_text,variableClasses);
+ bool e = isEnum(first_text,enumClasses);
+ if (e) {
+ if (enumClasses.size() == 1)
+ link = enumClasses[0];
+ else if (enumClasses.contains(currentClass))
+ link = currentClass;
+ else {
+ QString msg = "Unqualified enum name: " + first_text;
+ QString details = "Classes: " + enumClasses.join(", ");
+ priv->start_loc.error(msg,details);
+ }
+ if (!link.isEmpty())
+ qDebug() << "FOUND ENUM" << link << first_text;
+ }
+ else if (p && v) {
+ if (propertyClasses.size() == 1) {
+ if (variableClasses.size() == 1) {
+ if (propertyClasses[0] == variableClasses[0])
+ link = propertyClasses[0];
+ }
+ }
+ if (link.isEmpty()) {
+ if (propertyClasses.contains(currentClass) ||
+ variableClasses.contains(currentClass))
+ link = currentClass;
+ else {
+ propertyClasses += variableClasses;
+ QString msg = "Unqualified property or variable name: "
+ + first_text;
+ QString details = "Classes: " +
+ propertyClasses.join(", ");
+ priv->start_loc.error(msg,details);
+ }
+ }
+ }
+ else if (p) {
+ if (propertyClasses.size() == 1)
+ link = propertyClasses[0];
+ else if (propertyClasses.contains(currentClass))
+ link = currentClass;
+ else {
+ QString msg = "Unqualified property name: " + first_text;
+ QString details = "Classes: " + propertyClasses.join(", ");
+ priv->start_loc.error(msg,details);
+ }
+ }
+ else if (v) {
+ if (variableClasses.size() == 1)
+ link = variableClasses[0];
+ else if (variableClasses.contains(currentClass))
+ link = currentClass;
+ else {
+ QString msg = "Unqualified variable name: " + first_text;
+ QString details = "Classes: " + variableClasses.join(", ");
+ priv->start_loc.error(msg,details);
+ }
+ }
+ else {
+ qDebug() << "NOT AUTO-LINKABLE" << first_text;
+ QString s = first_text + " " + second_text;
+ concatenate("\\link " + s + "\\endlink");
+ }
+ if (!link.isEmpty()) {
+ link += "::" + first_text + " " + second_text;
+ concatenate("\\link " + link + "\\endlink");
+ }
+ }
+ }
+ else
+ qDebug() << "LINK with no second parameter!!!!";
+ return next? next : atom;
+}
+
+/*!
+ If the current line length is 0, the current line is
+ indented according to the context.
+ */
+void DoxWriter::indentLine()
+{
+ if (lineLength == 0) {
+ newText += DOXYGEN_INDENT_STRING;
+ lineLength = DOXYGEN_INDENT;
+ if (!structs.isEmpty()) {
+ for (int i=1; i<structs.size(); ++i) {
+ newText += DOXYGEN_TAB_STRING;
+ lineLength += DOXYGEN_TAB_SIZE;
+ }
+ }
+ }
+}
+
+/*!
+ Concatenates a newline to the doxygen text, increments the
+ line count, and resets the line length to 0.
+ */
+void DoxWriter::newLine()
+{
+ newText += "\n";
+ ++lineCount;
+ lineLength = 0;
+}
+
+static const int maxLineLength = 70;
+
+/*!
+ Concatenate the \a text to the doxygen comment currently
+ under construction and increment the current line length
+ by the size of the \a text.
+
+ If incrementing the current line length by the \a text size
+ would make the current line length longer than the maximum
+ line length, then call newLine() and indentLine() \e before
+ concatenating the \a text.
+ */
+void DoxWriter::concatenate(QString text)
+{
+ if ((lineLength + text.size()) > maxLineLength)
+ newLine();
+ indentLine();
+ newText += text;
+ lineLength += text.size();
+}
+
+static bool punctuation(QChar c)
+{
+ switch (c.toAscii()) {
+ case '.':
+ case ',':
+ case ':':
+ case ';':
+ case '/':
+ case '+':
+ case '-':
+ case '?':
+ case '!':
+ case '\"':
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+/*!
+ Concatenate the \a text string to the doxygen text, doing
+ line wrapping where necessary.
+ */
+void DoxWriter::wrap(QString text)
+{
+ int from = 0;
+ int to = -1;
+
+ if ((lineLength == 0) || (lineLength >= maxLineLength)) {
+ if (!text.isEmpty() && (text[0] == ' '))
+ text = text.right(text.size() - 1);
+ }
+
+ indentLine();
+ while (text.size()) {
+ int avail = maxLineLength - lineLength;
+ from = text.indexOf(' ',from);
+ if (from >= 0) {
+ if (from < avail)
+ to = from++;
+ else if (from == 1 && punctuation(text[0]))
+ to = from++;
+ else {
+ if (to >= 0) {
+ newText += text.left(to+1);
+ lineLength += to + 1;
+ text = text.right(text.size() - to - 1);
+ }
+ else {
+ newLine();
+ indentLine();
+ newText += text.left(from+1);
+ lineLength += from + 1;
+ text = text.right(text.size() - from - 1);
+ }
+ from = 0;
+ to = -1;
+ if (text.size() && (lineLength > maxLineLength)) {
+ newLine();
+ indentLine();
+ }
+ }
+ }
+ else
+ break;
+ }
+ if (text.size()) {
+ if (lineLength >= maxLineLength) {
+ newLine();
+ indentLine();
+ }
+ newText += text;
+ lineLength += text.size();
+ }
+}
+
+/*!
+ This will output something, but it depends on what the
+ \a atom string and the \a next atom string are.
+ */
+void DoxWriter::formattingLeft(const Atom* atom, const Atom* next)
+{
+ if (atom->string() == "parameter") {
+ concatenate("\\a ");
+ return;
+ }
+ else if (atom->string() == "underline") {
+ concatenate("<u>");
+ return;
+ }
+ else if (atom->string() == "superscript") {
+ concatenate("<sup>");
+ return;
+ }
+ else if (atom->string() == "subscript") {
+ concatenate("<sub>");
+ return;
+ }
+ int ws = -1;
+ if (next)
+ ws = next->string().indexOf(ws_rx);
+ if (atom->string() == "bold") {
+ if (ws < 0)
+ concatenate("\\b ");
+ else
+ concatenate("<b>");
+ }
+ else if (atom->string() == "italic") {
+ if (ws < 0)
+ concatenate("\\e ");
+ else
+ concatenate("<i>");
+ }
+ else if (atom->string() == "teletype") {
+ if (ws < 0)
+ concatenate("\\c ");
+ else
+ concatenate("<tt>");
+ }
+ else
+ qDebug() << "UNHANDLED FormattingLeft: " << atom->string();
+}
+
+/*!
+ This will output something, but it depends on what the
+ \a atom string and the \a prev atom string are.
+ */
+void DoxWriter::formattingRight(const Atom* atom, const Atom* prev)
+{
+ if (atom->string() == "parameter")
+ return;
+ else if (atom->string() == "underline") {
+ concatenate("</u>");
+ return;
+ }
+ else if (atom->string() == "superscript") {
+ concatenate("</sup>");
+ return;
+ }
+ else if (atom->string() == "subscript") {
+ concatenate("</sub>");
+ return;
+ }
+ int ws = -1;
+ if (prev)
+ ws = prev->string().indexOf(ws_rx);
+ if (ws < 0)
+ return;
+ if (atom->string() == "bold")
+ concatenate("</b>");
+ else if (atom->string() == "italic")
+ concatenate("</i>");
+ else if (atom->string() == "teletype")
+ concatenate("</tt>");
+ else
+ qDebug() << "UNHANDLED FormattingRight: " << atom->string();
+}
+
+/*!
+ Output a \c or a <tt>...</tt>.
+ */
+void DoxWriter::tt(const Atom* atom)
+{
+ if (atom->string().indexOf(ws_rx) < 0) {
+ concatenate("\\c ");
+ concatenate(atom->string());
+ }
+ else {
+ concatenate("<tt>");
+ concatenate(atom->string());
+ concatenate("</tt>");
+ }
+}
+
+/*!
+ */
+void DoxWriter::formatIf(const Atom* atom)
+{
+ if (atom->string() == "HTML") {
+ newLine();
+ concatenate("\\htmlonly");
+ newLine();
+ }
+}
+
+/*!
+ */
+void DoxWriter::formatEndif()
+{
+ newLine();
+ concatenate("\\endhtmlonly");
+ newLine();
+}
+
+/*!
+ */
+void DoxWriter::formatElse()
+{
+ // nothing.
+}
+
+/*!
+ Pass 1: Construct a section identifier and insert it into
+ the anchor set.
+
+ Pass 2: Convert section1, section2, and section3 commands
+ to section, subsection, and subsubsection respectively.
+ Warn if a section command higher than 3 is seen.
+ */
+const Atom* DoxWriter::sectionHeading(const Atom* atom)
+{
+ QString heading_level = atom->string();
+ QString heading_text;
+ const Atom* next = atom->next();
+ while (next) {
+ next->dump();
+ if (next->type() == Atom::SectionHeadingRight) {
+ if (next->string() == heading_level)
+ break;
+ else {
+ qDebug() << "WRONG SectionHeading number!!!!";
+ }
+ }
+ else
+ heading_text += next->string();
+ next = next->next();
+ }
+
+ QString heading_identifier = heading_text;
+ heading_identifier.remove(ws_rx);
+
+ newLine();
+ if (heading_level == "1")
+ heading_level = "\\section ";
+ else if (heading_level == "2")
+ heading_level = "\\subsection ";
+ else if (heading_level == "3")
+ heading_level = "\\subsubsection ";
+ else if (heading_level == "4") {
+ heading_level = "\\subsubsection ";
+ qDebug() << "WARNING section4 converted to \\subsubsection";
+ }
+ else {
+ heading_level = "\\subsubsection ";
+ qDebug() << "WARNING section5 converted to \\subsubsection";
+ }
+ concatenate(heading_level);
+ newText += heading_identifier + " ";
+ lineLength += heading_identifier.size() + 1;
+ newText += heading_text;
+ lineLength += heading_text.size();
+ newLine();
+ return next? next : atom;
+}
+
+/*!
+ Report an unhandled atom.
+ */
+void DoxWriter::unhandled(const Atom* atom)
+{
+ qDebug() << "UNHANDLED ATOM";
+ atom->dump();
+}
+
+/*!
+ Output a code/endcode block.
+ */
+void DoxWriter::code(const Atom* atom)
+{
+ newLine();
+ concatenate("\\code");
+ writeCode(atom->string());
+ concatenate("\\endcode");
+ newLine();
+}
+
+/*!
+ Output a code/endcode block depending on the
+ CodeQuote Command and CodeQuoteArgument parameters.
+ */
+const Atom* DoxWriter::codeQuoteCommand(const Atom* atom)
+{
+ QString command = atom->string();
+ atom = atom->next();
+ concatenate("\\code");
+ if (command == "codeline") {
+ newLine();
+ concatenate(atom->string());
+ newLine();
+ }
+ else if (command == "dots") {
+ newLine();
+ concatenate(atom->string());
+ newLine();
+ }
+ else {
+ writeCode(atom->string());
+ }
+ concatenate("\\endcode");
+ return atom;
+}
+
+/*!
+ Appends a block of code to the comment.
+ */
+void DoxWriter::writeCode(QString text)
+{
+ int cr_count = text.count('\n') - 1;
+ if (cr_count >= 0) {
+ int last_cr = text.lastIndexOf('\n');
+ newText += text.left(last_cr);
+ lineCount += cr_count;
+ }
+ else
+ newText += text;
+ newLine();
+}
+
+/*!
+ Inserts \a text into the anchor set. This function is called
+ during doxygen pass 1.
+ */
+void DoxWriter::insertAnchor(const QString& text)
+{
+ anchors.insert(text);
+}
+
+/*!
+ Returns true if \a text identifies an anchor, section,
+ subsection, subsubsection, or page.
+ */
+bool DoxWriter::isAnchor(const QString& text)
+{
+ return anchors.contains(text);
+}
+
+/*!
+ Write the set of anchors to a file, one per line.
+ */
+void DoxWriter::writeAnchors()
+{
+ QFile file("anchors.txt");
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("Unable to open anchors.txt for writing.");
+ return;
+ }
+
+ QTextStream out(&file);
+ QSet<QString>::const_iterator i = anchors.constBegin();
+ while (i != anchors.constEnd()) {
+ out << *i << "\n";
+ ++i;
+ }
+ file.close();
+}
+
+/*!
+ Read the set of anchors from the anchors file, one per line,
+ and insert each one into the anchor set.
+ */
+void DoxWriter::readAnchors()
+{
+ QFile file("anchors.txt");
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("Unable to open anchors.txt for reading.");
+ return;
+ }
+
+ QTextStream in(&file);
+ while (!in.atEnd()) {
+ QString line = in.readLine();
+ anchors.insert(line);
+ }
+ file.close();
+#if 0
+ QSet<QString>::const_iterator i = anchors.constBegin();
+ while (i != anchors.constEnd()) {
+ qDebug() << *i;
+ ++i;
+ }
+#endif
+}
+
+/*!
+ Inserts \a title into one of the title maps. \a title is
+ mapped to the \a node name. This function is called during
+ doxygen pass 1.
+ */
+void DoxWriter::insertTitle(FakeNode* node, const QString& title)
+{
+ switch (node->subType()) {
+ case FakeNode::Example:
+ if (exampleTitles.contains(title)) {
+ qWarning() << "DoxWriter::insertTitle():"
+ << "Duplicate example title:"
+ << title;
+ }
+ else {
+ exampleTitles[title] = node->name();
+ exampleTitlesInverse[node->name()] = title;
+ }
+ break;
+ case FakeNode::HeaderFile:
+ if (headerFileTitles.contains(title)) {
+ qWarning() << "DoxWriter::insertTitle():"
+ << "Duplicate header file title:"
+ << title;
+ }
+ else {
+ headerFileTitles[title] = node->name();
+ headerFileTitlesInverse[node->name()] = title;
+ }
+ break;
+ case FakeNode::File:
+ if (fileTitles.contains(title)) {
+ qWarning() << "DoxWriter::insertTitle():"
+ << "Duplicate file title:"
+ << title;
+ }
+ else {
+ fileTitles[title] = node->name();
+ fileTitlesInverse[node->name()] = title;
+ }
+ break;
+ case FakeNode::Group:
+ if (groupTitles.contains(title)) {
+ qWarning() << "DoxWriter::insertTitle():"
+ << "Duplicate group title:"
+ << title;
+ }
+ else {
+ groupTitles[title] = node->name();
+ groupTitlesInverse[node->name()] = title;
+ }
+ break;
+ case FakeNode::Module:
+ if (moduleTitles.contains(title)) {
+ qWarning() << "DoxWriter::insertTitle():"
+ << "Duplicate module title:"
+ << title;
+ }
+ else {
+ moduleTitles[title] = node->name();
+ moduleTitlesInverse[node->name()] = title;
+ }
+ break;
+ case FakeNode::Page:
+ if (pageTitles.contains(title)) {
+ qWarning() << "DoxWriter::insertTitle():"
+ << "Duplicate page title:"
+ << title;
+ }
+ else {
+ pageTitles[title] = node->name();
+ pageTitlesInverse[node->name()] = title;
+ }
+ break;
+ case FakeNode::ExternalPage:
+ if (externalPageTitles.contains(title)) {
+ qWarning() << "DoxWriter::insertTitle():"
+ << "Duplicate external page title:"
+ << title;
+ }
+ else {
+ externalPageTitles[title] = node->name();
+ externalPageTitlesInverse[node->name()] = title;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ */
+const QString* DoxWriter::getPageFile(const QString& title)
+{
+ QStringMapEntry entry = pageTitles.find(title);
+ return (entry == pageTitles.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getExamplePath(const QString& title)
+{
+ QStringMapEntry entry = exampleTitles.find(title);
+ return (entry == exampleTitles.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getFile(const QString& title)
+{
+ QStringMapEntry entry = fileTitles.find(title);
+ return (entry == fileTitles.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getHeaderFile(const QString& title)
+{
+ QStringMapEntry entry = headerFileTitles.find(title);
+ return (entry == headerFileTitles.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getGroup(const QString& title)
+{
+ QStringMapEntry entry = groupTitles.find(title);
+ return (entry == groupTitles.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getModule(const QString& title)
+{
+ QStringMapEntry entry = moduleTitles.find(title);
+ return (entry == moduleTitles.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getExternalPage(const QString& title)
+{
+ QStringMapEntry entry = externalPageTitles.find(title);
+ return (entry == externalPageTitles.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getPageTitle(const QString& text)
+{
+ QStringMapEntry entry = pageTitlesInverse.find(text);
+ return (entry == pageTitlesInverse.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getExampleTitle(const QString& text)
+{
+ QStringMapEntry entry = exampleTitlesInverse.find(text);
+ return (entry == exampleTitlesInverse.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getFileTitle(const QString& text)
+{
+ QStringMapEntry entry = fileTitlesInverse.find(text);
+ return (entry == fileTitlesInverse.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getHeaderFileTitle(const QString& text)
+{
+ QStringMapEntry entry = headerFileTitlesInverse.find(text);
+ return (entry == headerFileTitlesInverse.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getGroupTitle(const QString& text)
+{
+ QStringMapEntry entry = groupTitlesInverse.find(text);
+ return (entry == groupTitlesInverse.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getModuleTitle(const QString& text)
+{
+ QStringMapEntry entry = moduleTitlesInverse.find(text);
+ return (entry == moduleTitlesInverse.end()) ? 0 : &entry.value();
+}
+
+/*!
+ */
+const QString* DoxWriter::getExternalPageTitle(const QString& text)
+{
+ QStringMapEntry entry = externalPageTitlesInverse.find(text);
+ return (entry == externalPageTitlesInverse.end()) ? 0 : &entry.value();
+}
+
+/*!
+ Serialize \a map to file \a name.
+ */
+void DoxWriter::writeMap(const QStringMap& map, const QString& name)
+{
+
+ QFile file(name);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning() << "Unable to open" << name << "for writing.";
+ return;
+ }
+
+ QTextStream out(&file);
+ QStringMap::const_iterator i = map.constBegin();
+ while (i != map.constEnd()) {
+ out << i.key() << "\n";
+ out << i.value() << "\n";
+ ++i;
+ }
+ file.close();
+}
+
+/*!
+ Read file \a name into the \a map.
+ */
+void DoxWriter::readMap(QStringMap& map, QStringMap& inverseMap, const QString& name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning() << "Unable to open" << name << "for reading.";
+ return;
+ }
+
+ QTextStream in(&file);
+ while (!in.atEnd()) {
+ QString title = in.readLine();
+ QString value = in.readLine();
+ map[title] = value;
+ inverseMap[value] = title;
+ }
+ file.close();
+}
+
+/*!
+ Write the sets of titles to text files, one per line.
+ */
+void DoxWriter::writeTitles()
+{
+ if (!pageTitles.isEmpty())
+ writeMap(pageTitles,"pagetitles.txt");
+ if (!fileTitles.isEmpty())
+ writeMap(fileTitles,"filetitles.txt");
+ if (!headerFileTitles.isEmpty())
+ writeMap(headerFileTitles,"headerfiletitles.txt");
+ if (!exampleTitles.isEmpty())
+ writeMap(exampleTitles,"exampletitles.txt");
+ if (!moduleTitles.isEmpty())
+ writeMap(moduleTitles,"moduletitles.txt");
+ if (!groupTitles.isEmpty())
+ writeMap(groupTitles,"grouptitles.txt");
+ if (!externalPageTitles.isEmpty())
+ writeMap(externalPageTitles,"externalpagetitles.txt");
+}
+
+/*!
+ Read the sets of titles from the titles files, one per line,
+ and insert each one into the appropriate title set.
+ */
+void DoxWriter::readTitles()
+{
+ readMap(pageTitles,pageTitlesInverse,"pagetitles.txt");
+ readMap(fileTitles,fileTitlesInverse,"filetitles.txt");
+ readMap(headerFileTitles,headerFileTitlesInverse,"headerfiletitles.txt");
+ readMap(exampleTitles,exampleTitlesInverse,"exampletitles.txt");
+ readMap(moduleTitles,moduleTitlesInverse,"moduletitles.txt");
+ readMap(groupTitles,groupTitlesInverse,"grouptitles.txt");
+ readMap(externalPageTitles,
+ externalPageTitlesInverse,
+ "externalpagetitles.txt");
+}
+
+/*!
+ Serialize \a map to file \a name.
+ */
+void DoxWriter::writeMultiMap(const QStringMultiMap& map, const QString& name)
+{
+
+ QFile file(name);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning() << "Unable to open" << name << "for writing.";
+ return;
+ }
+
+ QTextStream out(&file);
+ QStringMultiMap::const_iterator i = map.constBegin();
+ while (i != map.constEnd()) {
+ out << i.key() << "\n";
+ out << i.value() << "\n";
+ ++i;
+ }
+ file.close();
+}
+
+/*!
+ Write the4 property names and variable names to text files.
+ */
+void DoxWriter::writeMembers()
+{
+ if (!variables.isEmpty())
+ writeMultiMap(variables,"variables.txt");
+ if (!properties.isEmpty())
+ writeMultiMap(properties,"properties.txt");
+ if (!enums.isEmpty())
+ writeMultiMap(enums,"enums.txt");
+}
+
+/*!
+ Read file \a name into the \a map.
+ */
+void DoxWriter::readMultiMap(QStringMultiMap& map, const QString& name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning() << "Unable to open" << name << "for reading.";
+ return;
+ }
+
+ QTextStream in(&file);
+ while (!in.atEnd()) {
+ QString member = in.readLine();
+ QString className = in.readLine();
+ map.insert(member,className);
+ }
+ file.close();
+}
+
+/*!
+ Read the property names and variable names from the test files.
+ */
+void DoxWriter::readMembers()
+{
+ readMultiMap(variables,"variables.txt");
+ readMultiMap(properties,"properties.txt");
+ readMultiMap(enums,"enums.txt");
+}
+
+/*!
+ Return true if \a name is a property. Loads \a classes with
+ the names of all the classes in which \a name is a property.
+ */
+bool DoxWriter::isProperty(const QString& name, QStringList& classes)
+{
+ classes = properties.values(name);
+ return !classes.isEmpty();
+}
+
+/*!
+ Return true if \a name is a variable. Loads \a classes with
+ the names of all the classes in which \a name is a variable.
+ */
+bool DoxWriter::isVariable(const QString& name, QStringList& classes)
+{
+ classes = variables.values(name);
+ return !classes.isEmpty();
+}
+
+/*!
+ Return true if \a name is an enum type. Loads \a classes with
+ the names of all the classes in which \a name is an enum type.
+ */
+bool DoxWriter::isEnum(const QString& name, QStringList& classes)
+{
+ classes = enums.values(name);
+ return !classes.isEmpty();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/doc.h b/tools/qdoc3/doc.h
new file mode 100644
index 0000000000..6cb6f0a069
--- /dev/null
+++ b/tools/qdoc3/doc.h
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ doc.h
+*/
+
+#ifndef DOC_H
+#define DOC_H
+
+#include <QSet>
+#include <QString>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class Atom;
+class CodeMarker;
+class Config;
+class DocPrivate;
+class Quoter;
+class Text;
+class FakeNode;
+
+typedef QMap<QString, QStringList> QCommandMap;
+typedef QMap<QString, QString> QStringMap;
+typedef QStringMap::const_iterator QStringMapEntry;
+typedef QMultiMap<QString, QString> QStringMultiMap;
+
+class Doc
+{
+ public:
+ // the order is important
+ enum SectioningUnit {
+ Book = -2,
+ Part,
+ Chapter,
+ Section1,
+ Section2,
+ Section3,
+ Section4
+ };
+
+ Doc() : priv(0) {}
+ Doc(const Location &start_loc,
+ const Location &end_loc,
+ const QString &source,
+ const QSet<QString> &metaCommandSet);
+ Doc(const Doc &doc);
+ ~Doc();
+
+ Doc& operator=( const Doc& doc );
+
+ void renameParameters(const QStringList &oldNames,
+ const QStringList &newNames);
+ void simplifyEnumDoc();
+ void setBody(const Text &body);
+
+ const Location &location() const;
+ bool isEmpty() const;
+ const QString& source() const;
+ const Text& body() const;
+ Text briefText() const;
+ Text trimmedBriefText(const QString &className) const;
+ Text legaleseText() const;
+ const QString& baseName() const;
+ SectioningUnit granularity() const;
+ const QSet<QString> &parameterNames() const;
+ const QStringList &enumItemNames() const;
+ const QStringList &omitEnumItemNames() const;
+ const QSet<QString> &metaCommandsUsed() const;
+ QStringList metaCommandArgs( const QString& metaCommand ) const;
+ const QList<Text> &alsoList() const;
+ bool hasTableOfContents() const;
+ bool hasKeywords() const;
+ bool hasTargets() const;
+ const QList<Atom *> &tableOfContents() const;
+ const QList<int> &tableOfContentsLevels() const;
+ const QList<Atom *> &keywords() const;
+ const QList<Atom *> &targets() const;
+ const QStringMap &metaTagMap() const;
+
+ static void initialize( const Config &config );
+ static void terminate();
+ static QString alias( const QString &english );
+ static void trimCStyleComment( Location& location, QString& str );
+ static CodeMarker *quoteFromFile(const Location &location,
+ Quoter &quoter,
+ const QString &fileName);
+ static QString canonicalTitle(const QString &title);
+
+ private:
+ void detach();
+ DocPrivate *priv;
+};
+
+#ifdef QDOC2DOX
+
+class DoxWriter
+{
+ public:
+ DoxWriter(const QString& source, DocPrivate* docPrivate)
+ : commentType(OtherComment),
+ lineLength(0),
+ lineCount(0),
+ priv(docPrivate),
+ oldText(source) {}
+ ~DoxWriter() {}
+
+ void pass1();
+ void pass2();
+
+ static void setDoxPass(int pass);
+ static bool isDoxPass(int pass);
+ static bool isDoxPass();
+ static void insertTitle(FakeNode* node, const QString& title);
+ static void writeTitles();
+ static void readTitles();
+ static void writeMembers();
+ static void readMembers();
+ static void writeAnchors();
+ static void readAnchors();
+
+ private:
+ void indentLine();
+ void newLine();
+ void concatenate(QString text);
+ void wrap(QString text);
+ bool conversionRequired() const;
+ void convertMetaCommands();
+ void convertText();
+ const Atom* link(const Atom* atom);
+ void formattingLeft(const Atom* atom, const Atom* next);
+ void formattingRight(const Atom* atom, const Atom* prev);
+ void tt(const Atom* atom);
+ void formatIf(const Atom* atom);
+ void formatEndif();
+ void formatElse();
+ const Atom* sectionHeading(const Atom* atom);
+ void unhandled(const Atom* atom);
+ void code(const Atom* atom);
+ const Atom* codeQuoteCommand(const Atom* atom);
+ void writeCode(QString text);
+ void writeCommand(QCommandMap::const_iterator cmd);
+
+ static void insertAnchor(const QString& text);
+ static bool isAnchor(const QString& text);
+
+ static const QString* getPageFile(const QString& title);
+ static const QString* getFile(const QString& title);
+ static const QString* getExamplePath(const QString& title);
+ static const QString* getHeaderFile(const QString& title);
+ static const QString* getGroup(const QString& title);
+ static const QString* getModule(const QString& title);
+ static const QString* getExternalPage(const QString& title);
+ static const QString* getPageTitle(const QString& text);
+ static const QString* getFileTitle(const QString& text);
+ static const QString* getExampleTitle(const QString& text);
+ static const QString* getHeaderFileTitle(const QString& text);
+ static const QString* getGroupTitle(const QString& text);
+ static const QString* getModuleTitle(const QString& text);
+ static const QString* getExternalPageTitle(const QString& text);
+
+ static bool isProperty(const QString& title, QStringList& classes);
+ static bool isVariable(const QString& title, QStringList& classes);
+ static bool isEnum(const QString& title, QStringList& classes);
+
+ private:
+ static void writeMap(const QStringMap& map, const QString& name);
+ static void readMap(QStringMap& map,
+ QStringMap& inverseMap,
+ const QString& name);
+ static void writeMultiMap(const QStringMultiMap& map, const QString& name);
+ static void readMultiMap(QStringMultiMap& map, const QString& name);
+
+ public: // VS 6, SunCC need this to be public
+ enum StructType { BulletList, NumericList, ValueList, Table };
+ private:
+ struct StructDesc {
+ StructType structType;
+ int count;
+ bool nested;
+ bool inTableHeader;
+ bool inTableRow;
+ bool inTableItem;
+ bool odd;
+
+ StructDesc()
+ : structType(BulletList),
+ count(0),
+ nested(false),
+ inTableHeader(false),
+ inTableRow(false),
+ inTableItem(false),
+ odd(true) { }
+
+ StructDesc(StructType t, bool n)
+ : structType(t),
+ count(0),
+ nested(n),
+ inTableHeader(false),
+ inTableRow(false),
+ inTableItem(false),
+ odd(true) { }
+ };
+
+ typedef QStack<StructDesc> StructStack;
+
+ enum CommentType {
+ ClassComment,
+ EnumComment,
+ ExampleComment,
+ FnComment,
+ GroupComment,
+ HeaderFileComment,
+ MacroComment,
+ ModuleComment,
+ PageComment,
+ PropertyComment,
+ ServiceComment,
+ TypedefComment,
+ VariableComment,
+ OtherComment
+ };
+
+ private:
+ CommentType commentType;
+ int lineLength;
+ int lineCount;
+ DocPrivate* priv;
+ QString oldText;
+ QString newText;
+ StructStack structs;
+
+ QString currentPage;
+ QString currentFn;
+ QString currentTitle;
+ QString currentEnum;
+ QString currentProperty;
+ QString currentVariable;
+ QString currentExample;
+ QString currentGroup;
+ QString currentModule;
+ QString currentMacro;
+ QString currentService;
+ QString currentTypedef;
+ QString currentHeaderFile;
+ static QString currentClass;
+
+ static int doxPass;
+ static QSet<QString> anchors;
+ static QStringMap exampleTitles;
+ static QStringMap headerFileTitles;
+ static QStringMap fileTitles;
+ static QStringMap groupTitles;
+ static QStringMap moduleTitles;
+ static QStringMap pageTitles;
+ static QStringMap externalPageTitles;
+ static QStringMap exampleTitlesInverse;
+ static QStringMap headerFileTitlesInverse;
+ static QStringMap fileTitlesInverse;
+ static QStringMap groupTitlesInverse;
+ static QStringMap moduleTitlesInverse;
+ static QStringMap pageTitlesInverse;
+ static QStringMap externalPageTitlesInverse;
+
+ static QStringMultiMap variables;
+ static QStringMultiMap properties;
+ static QStringMultiMap enums;
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/documentation.pri b/tools/qdoc3/documentation.pri
new file mode 100644
index 0000000000..d95218339b
--- /dev/null
+++ b/tools/qdoc3/documentation.pri
@@ -0,0 +1,5 @@
+# NOTE: THIS FILE IS SHARED BY qdoc3.pro AND projects.pro
+#
+# So while changing this file, please make sure to that your changes
+# work in root qt soure dir with (n)make docs and for building with qdoc
+#
diff --git a/tools/qdoc3/editdistance.cpp b/tools/qdoc3/editdistance.cpp
new file mode 100644
index 0000000000..11cc18fe6b
--- /dev/null
+++ b/tools/qdoc3/editdistance.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ editdistance.cpp
+*/
+
+#include "editdistance.h"
+
+QT_BEGIN_NAMESPACE
+
+int editDistance( const QString& s, const QString& t )
+{
+#define D( i, j ) d[(i) * n + (j)]
+ int i;
+ int j;
+ int m = s.length() + 1;
+ int n = t.length() + 1;
+ int *d = new int[m * n];
+ int result;
+
+ for ( i = 0; i < m; i++ )
+ D( i, 0 ) = i;
+ for ( j = 0; j < n; j++ )
+ D( 0, j ) = j;
+ for ( i = 1; i < m; i++ ) {
+ for ( j = 1; j < n; j++ ) {
+ if ( s[i - 1] == t[j - 1] ) {
+ D( i, j ) = D( i - 1, j - 1 );
+ } else {
+ int x = D( i - 1, j );
+ int y = D( i - 1, j - 1 );
+ int z = D( i, j - 1 );
+ D( i, j ) = 1 + qMin( qMin(x, y), z );
+ }
+ }
+ }
+ result = D( m - 1, n - 1 );
+ delete[] d;
+ return result;
+#undef D
+}
+
+QString nearestName( const QString& actual, const QSet<QString>& candidates )
+{
+ int deltaBest = 10000;
+ int numBest = 0;
+ QString best;
+
+ QSet<QString>::ConstIterator c = candidates.begin();
+ while ( c != candidates.end() ) {
+ if ( (*c)[0] == actual[0] ) {
+ int delta = editDistance( actual, *c );
+ if ( delta < deltaBest ) {
+ deltaBest = delta;
+ numBest = 1;
+ best = *c;
+ } else if ( delta == deltaBest ) {
+ numBest++;
+ }
+ }
+ ++c;
+ }
+
+ if ( numBest == 1 && deltaBest <= 2 &&
+ actual.length() + best.length() >= 5 ) {
+ return best;
+ } else {
+ return "";
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/editdistance.h b/tools/qdoc3/editdistance.h
new file mode 100644
index 0000000000..d69f6b9dbe
--- /dev/null
+++ b/tools/qdoc3/editdistance.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ editdistance.h
+*/
+
+#ifndef EDITDISTANCE_H
+#define EDITDISTANCE_H
+
+#include <QSet>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+
+int editDistance( const QString& s, const QString& t );
+QString nearestName( const QString& actual, const QSet<QString>& candidates );
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp
new file mode 100644
index 0000000000..d89d6af7e7
--- /dev/null
+++ b/tools/qdoc3/generator.cpp
@@ -0,0 +1,995 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ generator.cpp
+*/
+
+#include <qdir.h>
+
+#include "codemarker.h"
+#include "config.h"
+#include "doc.h"
+#include "editdistance.h"
+#include "generator.h"
+#include "node.h"
+#include "openedlist.h"
+#include "quoter.h"
+#include "separator.h"
+#include "tokenizer.h"
+
+QT_BEGIN_NAMESPACE
+
+QList<Generator *> Generator::generators;
+QMap<QString, QMap<QString, QString> > Generator::fmtLeftMaps;
+QMap<QString, QMap<QString, QString> > Generator::fmtRightMaps;
+QMap<QString, QStringList> Generator::imgFileExts;
+QSet<QString> Generator::outputFormats;
+QStringList Generator::imageFiles;
+QStringList Generator::imageDirs;
+QString Generator::outDir;
+QString Generator::project;
+
+static Text stockLink(const QString &target)
+{
+ return Text() << Atom(Atom::Link, target) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << target << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+}
+
+Generator::Generator()
+ : amp("&amp;"), lt("&lt;"), gt("&gt;"), quot("&quot;"), tag("</?@[^>]*>")
+{
+ generators.prepend(this);
+}
+
+Generator::~Generator()
+{
+ generators.removeAll(this);
+}
+
+void Generator::initializeGenerator(const Config & /* config */)
+{
+}
+
+void Generator::terminateGenerator()
+{
+}
+
+void Generator::initialize(const Config &config)
+{
+ outputFormats = config.getStringSet(CONFIG_OUTPUTFORMATS);
+ if (!outputFormats.isEmpty()) {
+ outDir = config.getString(CONFIG_OUTPUTDIR);
+ if (outDir.isEmpty())
+ config.lastLocation().fatal(tr("No output directory specified in configuration file"));
+
+ QDir dirInfo;
+ if (dirInfo.exists(outDir)) {
+ if (!Config::removeDirContents(outDir))
+ config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir));
+ }
+ else {
+ if (!dirInfo.mkpath(outDir))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir));
+ }
+
+ if (!dirInfo.mkdir(outDir + "/images"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir + "/images"));
+ }
+
+ imageFiles = config.getStringList(CONFIG_IMAGES);
+ imageDirs = config.getStringList(CONFIG_IMAGEDIRS);
+
+ QString imagesDotFileExtensions = CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS;
+ QSet<QString> formats = config.subVars(imagesDotFileExtensions);
+ QSet<QString>::ConstIterator f = formats.begin();
+ while (f != formats.end()) {
+ imgFileExts[*f] = config.getStringList(imagesDotFileExtensions + Config::dot + *f);
+ ++f;
+ }
+
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if (outputFormats.contains((*g)->format())) {
+ (*g)->initializeGenerator(config);
+ QStringList extraImages = config.getStringList(CONFIG_EXTRAIMAGES + Config::dot
+ + (*g)->format());
+ QStringList::ConstIterator e = extraImages.begin();
+ while (e != extraImages.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(), imageFiles, imageDirs, *e,
+ imgFileExts[(*g)->format()], userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(), filePath, userFriendlyFilePath,
+ (*g)->outputDir() + "/images");
+ ++e;
+ }
+ }
+ ++g;
+ }
+
+ QRegExp secondParamAndAbove("[\2-\7]");
+ QSet<QString> formattingNames = config.subVars(CONFIG_FORMATTING);
+ QSet<QString>::ConstIterator n = formattingNames.begin();
+ while (n != formattingNames.end()) {
+ QString formattingDotName = CONFIG_FORMATTING + Config::dot + *n;
+
+ QSet<QString> formats = config.subVars(formattingDotName);
+ QSet<QString>::ConstIterator f = formats.begin();
+ while (f != formats.end()) {
+ QString def = config.getString(formattingDotName + Config::dot +
+ *f);
+ if (!def.isEmpty()) {
+ int numParams = Config::numParams(def);
+ int numOccs = def.count("\1");
+
+ if (numParams != 1) {
+ config.lastLocation().warning(tr("Formatting '%1' must have exactly one"
+ " parameter (found %2)")
+ .arg(*n).arg(numParams));
+ }
+ else if (numOccs > 1) {
+ config.lastLocation().fatal(tr("Formatting '%1' must contain exactly one"
+ " occurrence of '\\1' (found %2)")
+ .arg(*n).arg(numOccs));
+ }
+ else {
+ int paramPos = def.indexOf("\1");
+ fmtLeftMaps[*f].insert(*n, def.left(paramPos));
+ fmtRightMaps[*f].insert(*n, def.mid(paramPos + 1));
+ }
+ }
+ ++f;
+ }
+ ++n;
+ }
+
+ project = config.getString(CONFIG_PROJECT);
+}
+
+void Generator::terminate()
+{
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if (outputFormats.contains((*g)->format()))
+ (*g)->terminateGenerator();
+ ++g;
+ }
+
+ fmtLeftMaps.clear();
+ fmtRightMaps.clear();
+ imgFileExts.clear();
+ imageFiles.clear();
+ imageDirs.clear();
+ outDir = "";
+}
+
+Generator *Generator::generatorForFormat(const QString& format)
+{
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if ((*g)->format() == format)
+ return *g;
+ ++g;
+ }
+ return 0;
+}
+
+void Generator::startText(const Node * /* relative */,
+ CodeMarker * /* marker */)
+{
+}
+
+void Generator::endText(const Node * /* relative */,
+ CodeMarker * /* marker */)
+{
+}
+
+int Generator::generateAtom(const Atom * /* atom */,
+ const Node * /* relative */,
+ CodeMarker * /* marker */)
+{
+ return 0;
+}
+
+void Generator::generateClassLikeNode(const InnerNode * /* classe */,
+ CodeMarker * /* marker */)
+{
+}
+
+void Generator::generateFakeNode(const FakeNode * /* fake */,
+ CodeMarker * /* marker */)
+{
+}
+
+void Generator::generateText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ if (text.firstAtom() != 0) {
+ int numAtoms = 0;
+ startText(relative, marker);
+ generateAtomList(text.firstAtom(),
+ relative,
+ marker,
+ true,
+ numAtoms);
+ endText(relative, marker);
+ }
+}
+
+#ifdef QDOC_QML
+void Generator::generateQmlText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ if (text.firstAtom() != 0) {
+ startText(relative, marker);
+ const Atom *atom = text.firstAtom();
+ while (atom) {
+ if (atom->type() != Atom::QmlText)
+ atom = atom->next();
+ else {
+ atom = atom->next();
+ while (atom && (atom->type() != Atom::EndQmlText)) {
+ int n = 1 + generateAtom(atom, relative, marker);
+ while (n-- > 0)
+ atom = atom->next();
+ }
+ }
+ }
+ endText(relative, marker);
+ }
+}
+#endif
+
+void Generator::generateBody(const Node *node, CodeMarker *marker)
+{
+ bool quiet = false;
+
+ if (node->type() == Node::Function) {
+#if 0
+ const FunctionNode *func = (const FunctionNode *) node;
+ if (func->isOverload() && func->metaness() != FunctionNode::Ctor)
+ generateOverload(node, marker);
+#endif
+ }
+ else if (node->type() == Node::Fake) {
+ const FakeNode *fake = static_cast<const FakeNode *>(node);
+ if (fake->subType() == FakeNode::Example)
+ generateExampleFiles(fake, marker);
+ else if (fake->subType() == FakeNode::File)
+ quiet = true;
+ }
+
+ if (node->doc().isEmpty()) {
+ if (!quiet) // ### might be unnecessary
+ node->location().warning(tr("No documentation for '%1'")
+ .arg(marker->plainFullName(node)));
+ }
+ else {
+ generateText(node->doc().body(), node, marker);
+
+ if (node->type() == Node::Enum) {
+ const EnumNode *enume = (const EnumNode *) node;
+
+ QSet<QString> definedItems;
+ QList<EnumItem>::ConstIterator it = enume->items().begin();
+ while (it != enume->items().end()) {
+ definedItems.insert((*it).name());
+ ++it;
+ }
+
+ QSet<QString> documentedItems = enume->doc().enumItemNames().toSet();
+ QSet<QString> allItems = definedItems + documentedItems;
+ if (allItems.count() > definedItems.count() ||
+ allItems.count() > documentedItems.count()) {
+ QSet<QString>::ConstIterator a = allItems.begin();
+ while (a != allItems.end()) {
+ if (!definedItems.contains(*a)) {
+ QString details;
+ QString best = nearestName(*a, definedItems);
+ if (!best.isEmpty() && !documentedItems.contains(best))
+ details = tr("Maybe you meant '%1'?").arg(best);
+
+ node->doc().location().warning(
+ tr("No such enum item '%1' in %2").arg(*a).arg(marker->plainFullName(node)),
+ details);
+ }
+ else if (!documentedItems.contains(*a)) {
+ node->doc().location().warning(
+ tr("Undocumented enum item '%1' in %2").arg(*a).arg(marker->plainFullName(node)));
+ }
+ ++a;
+ }
+ }
+ }
+ else if (node->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+
+ QSet<QString> definedParams;
+ QList<Parameter>::ConstIterator p = func->parameters().begin();
+ while (p != func->parameters().end()) {
+ if ((*p).name().isEmpty() && (*p).leftType() != QLatin1String("...")
+ && func->name() != QLatin1String("operator++")
+ && func->name() != QLatin1String("operator--")) {
+ node->doc().location().warning(tr("Missing parameter name"));
+ }
+ else {
+ definedParams.insert((*p).name());
+ }
+ ++p;
+ }
+
+ QSet<QString> documentedParams = func->doc().parameterNames();
+ QSet<QString> allParams = definedParams + documentedParams;
+ if (allParams.count() > definedParams.count()
+ || allParams.count() > documentedParams.count()) {
+ QSet<QString>::ConstIterator a = allParams.begin();
+ while (a != allParams.end()) {
+ if (!definedParams.contains(*a)) {
+ QString details;
+ QString best = nearestName(*a, definedParams);
+ if (!best.isEmpty())
+ details = tr("Maybe you meant '%1'?").arg(best);
+
+ node->doc().location().warning(
+ tr("No such parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node)),
+ details);
+ }
+ else if (!(*a).isEmpty() && !documentedParams.contains(*a)) {
+ bool needWarning = (func->status() > Node::Obsolete);
+ if (func->overloadNumber() > 1) {
+ FunctionNode *primaryFunc =
+ func->parent()->findFunctionNode(func->name());
+ if (primaryFunc) {
+ foreach (const Parameter &param, primaryFunc->parameters()) {
+ if (param.name() == *a) {
+ needWarning = false;
+ break;
+ }
+ }
+ }
+ }
+ if (needWarning)
+ node->doc().location().warning(
+ tr("Undocumented parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node)));
+ }
+ ++a;
+ }
+ }
+/* Something like this return value check should be implemented at some point. */
+ if (func->status() > Node::Obsolete && func->returnType() == "bool"
+ && func->reimplementedFrom() == 0 && !func->isOverload()) {
+ QString body = func->doc().body().toString();
+ if (!body.contains("return", Qt::CaseInsensitive))
+ node->doc().location().warning(tr("Undocumented return value"));
+ }
+
+ if (func->reimplementedFrom() != 0)
+ generateReimplementedFrom(func, marker);
+ }
+ }
+
+ if (node->type() == Node::Fake) {
+ const FakeNode *fake = static_cast<const FakeNode *>(node);
+ if (fake->subType() == FakeNode::File) {
+ Text text;
+ Quoter quoter;
+ Doc::quoteFromFile(fake->doc().location(), quoter, fake->name());
+ QString code = quoter.quoteTo(fake->location(), "", "");
+ text << Atom(Atom::Code, code);
+ generateText(text, fake, marker);
+ }
+ }
+}
+
+void Generator::generateAlsoList(const Node *node, CodeMarker *marker)
+{
+ QList<Text> alsoList = node->doc().alsoList();
+ supplementAlsoList(node, alsoList);
+
+ if (!alsoList.isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft << "See also ";
+
+ for (int i = 0; i < alsoList.size(); ++i)
+ text << alsoList.at(i) << separator(i, alsoList.size());
+
+ text << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
+}
+
+void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
+{
+ QList<RelatedClass>::ConstIterator r;
+ int index;
+
+ if (!classe->baseClasses().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft << "Inherits ";
+
+ r = classe->baseClasses().begin();
+ index = 0;
+ while (r != classe->baseClasses().end()) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access == Node::Protected) {
+ text << " (protected)";
+ } else if ((*r).access == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
+ ++r;
+ }
+ text << Atom::ParaRight;
+ generateText(text, classe, marker);
+ }
+}
+
+void Generator::generateInheritedBy(const ClassNode *classe,
+ CodeMarker *marker)
+{
+ if (!classe->derivedClasses().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft << "Inherited by ";
+
+ appendSortedNames(text, classe, classe->derivedClasses(), marker);
+ text << Atom::ParaRight;
+ generateText(text, classe, marker);
+ }
+}
+
+void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker)
+{
+ if (fake->childNodes().isEmpty())
+ return;
+
+ OpenedList openedList(OpenedList::Bullet);
+
+ Text text;
+ text << Atom::ParaLeft << "Files:" << Atom::ParaRight
+ << Atom(Atom::ListLeft, openedList.styleString());
+ foreach (const Node *child, fake->childNodes()) {
+ QString exampleFile = child->name();
+ openedList.next();
+ text << Atom(Atom::ListItemNumber, openedList.numberString())
+ << Atom(Atom::ListItemLeft, openedList.styleString()) << Atom::ParaLeft
+ << Atom(Atom::Link, exampleFile)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << exampleFile
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
+ << Atom::ParaRight << Atom(Atom::ListItemRight, openedList.styleString());
+ }
+ text << Atom(Atom::ListRight, openedList.styleString());
+ generateText(text, fake, marker);
+}
+
+void Generator::generateModuleWarning(const ClassNode *classe, CodeMarker *marker)
+{
+ QString module = classe->moduleName();
+ if (!module.isEmpty()) {
+ Text text;
+ if (Tokenizer::isTrue("defined(consoleedition)")
+ && !editionModuleMap["Console"].contains(module)) {
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "This class is not part of the Qt Console Edition."
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << Atom::ParaRight;
+ }
+ else if (Tokenizer::isTrue("defined(desktoplightedition)")
+ && !editionModuleMap["DesktopLight"].contains(module)) {
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "This class is not part of the Qt Desktop Light Edition."
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << Atom::ParaRight;
+ }
+ else if (module == "Qt3Support" && Tokenizer::isTrue("defined(opensourceedition)")) {
+ text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "Note to Qt Desktop Light Edition users:"
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << " This class is only available in the "
+ << Atom(Atom::AutoLink, "Qt Desktop Edition")
+ << "." << Atom::ParaRight;
+ }
+
+ generateText(text, classe, marker);
+ }
+}
+
+QString Generator::indent(int level, const QString& markedCode)
+{
+ if (level == 0)
+ return markedCode;
+
+ QString t;
+ int column = 0;
+
+ int i = 0;
+ while (i < (int) markedCode.length()) {
+ if (markedCode.at(i) == QLatin1Char('<')) {
+ while (i < (int) markedCode.length()) {
+ t += markedCode.at(i++);
+ if (markedCode.at(i - 1) == QLatin1Char('>'))
+ break;
+ }
+ } else {
+ if (markedCode.at(i) == QLatin1Char('\n')) {
+ column = 0;
+ } else {
+ if (column == 0) {
+ for (int j = 0; j < level; j++)
+ t += QLatin1Char(' ');
+ }
+ column++;
+ }
+ t += markedCode.at(i++);
+ }
+ }
+ return t;
+}
+
+QString Generator::plainCode(const QString& markedCode)
+{
+ QString t = markedCode;
+ t.replace(tag, QString());
+ t.replace(quot, QLatin1String("\""));
+ t.replace(gt, QLatin1String(">"));
+ t.replace(lt, QLatin1String("<"));
+ t.replace(amp, QLatin1String("&"));
+ return t;
+}
+
+QString Generator::typeString(const Node *node)
+{
+ switch (node->type()) {
+ case Node::Namespace:
+ return "namespace";
+ case Node::Class:
+ return "class";
+ case Node::Fake:
+ default:
+ return "documentation";
+ case Node::Enum:
+ return "enum";
+ case Node::Typedef:
+ return "typedef";
+ case Node::Function:
+ return "function";
+ case Node::Property:
+ return "property";
+ }
+}
+
+QString Generator::imageFileName(const Node *relative, const QString& fileBase)
+{
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(
+ relative->doc().location(), imageFiles, imageDirs, fileBase,
+ imgFileExts[format()], userFriendlyFilePath);
+
+ if (filePath.isEmpty())
+ return QString();
+
+ return QLatin1String("images/")
+ + Config::copyFile(relative->doc().location(),
+ filePath, userFriendlyFilePath,
+ outputDir() + QLatin1String("/images"));
+}
+
+void Generator::setImageFileExtensions(const QStringList& extensions)
+{
+ imgFileExts[format()] = extensions;
+}
+
+void Generator::unknownAtom(const Atom *atom)
+{
+ Location::internalError(tr("unknown atom type '%1' in %2 generator")
+ .arg(atom->typeString()).arg(format()));
+}
+
+bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType)
+{
+ return atom->next() != 0 && atom->next()->type() == expectedAtomType;
+}
+
+void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
+{
+ if (node->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+ if (func->overloadNumber() == 1) {
+ QString alternateName;
+ const FunctionNode *alternateFunc = 0;
+
+ if (func->name().startsWith("set") && func->name().size() >= 4) {
+ alternateName = func->name()[3].toLower();
+ alternateName += func->name().mid(4);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+
+ if (!alternateFunc) {
+ alternateName = "is" + func->name().mid(3);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ if (!alternateFunc) {
+ alternateName = "has" + func->name().mid(3);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ }
+ }
+ } else if (!func->name().isEmpty()) {
+ alternateName = "set";
+ alternateName += func->name()[0].toUpper();
+ alternateName += func->name().mid(1);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ }
+
+ if (alternateFunc && alternateFunc->access() != Node::Private) {
+ int i;
+ for (i = 0; i < alsoList.size(); ++i) {
+ if (alsoList.at(i).toString().contains(alternateName))
+ break;
+ }
+
+ if (i == alsoList.size()) {
+ alternateName += "()";
+
+ Text also;
+ also << Atom(Atom::Link, alternateName)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << alternateName
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ alsoList.prepend(also);
+ }
+ }
+ }
+ }
+}
+
+QMap<QString, QString>& Generator::formattingLeftMap()
+{
+ return fmtLeftMaps[format()];
+}
+
+QMap<QString, QString>& Generator::formattingRightMap()
+{
+ return fmtRightMaps[format()];
+}
+
+QString Generator::trimmedTrailing(const QString &string)
+{
+ QString trimmed = string;
+ while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace())
+ trimmed.truncate(trimmed.length() - 1);
+ return trimmed;
+}
+
+void Generator::generateStatus(const Node *node, CodeMarker *marker)
+{
+ Text text;
+
+ switch (node->status()) {
+ case Node::Commendable:
+ case Node::Main:
+ break;
+ case Node::Preliminary:
+ text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This "
+ << typeString(node) << " is under development and is subject to change."
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight;
+ break;
+ case Node::Deprecated:
+ text << Atom::ParaLeft;
+ if (node->isInnerNode())
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
+ text << "This " << typeString(node) << " is deprecated.";
+ if (node->isInnerNode())
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD);
+ text << Atom::ParaRight;
+ break;
+ case Node::Obsolete:
+ text << Atom::ParaLeft;
+ if (node->isInnerNode())
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
+ text << "This " << typeString(node) << " is obsolete.";
+ if (node->isInnerNode())
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD);
+ text << " It is provided to keep old source code working. We strongly advise against "
+ << "using it in new code." << Atom::ParaRight;
+ break;
+ case Node::Compat:
+ // reimplemented in HtmlGenerator subclass
+ if (node->isInnerNode()) {
+ text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This "
+ << typeString(node) << " is part of the Qt 3 compatibility layer."
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << " It is provided to keep old source code working. We strongly advise against "
+ << "using it in new code. See "
+ << Atom(Atom::AutoLink, "Porting to Qt 4")
+ << " for more information."
+ << Atom::ParaRight;
+ }
+ break;
+ case Node::Internal:
+ default:
+ break;
+ }
+ generateText(text, node, marker);
+}
+
+void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
+{
+ Text text;
+ Text theStockLink;
+ Node::ThreadSafeness parent = node->parent()->inheritedThreadSafeness();
+
+ switch (node->threadSafeness()) {
+ case Node::UnspecifiedSafeness:
+ break;
+ case Node::NonReentrant:
+ text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "Warning:"
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " This "
+ << typeString(node) << " is not " << stockLink("reentrant") << "." << Atom::ParaRight;
+ break;
+ case Node::Reentrant:
+ case Node::ThreadSafe:
+ text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
+ if (parent == Node::ThreadSafe) {
+ text << "Warning:";
+ } else {
+ text << "Note:";
+ }
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " ";
+
+ if (node->threadSafeness() == Node::ThreadSafe)
+ theStockLink = stockLink("thread-safe");
+ else
+ theStockLink = stockLink("reentrant");
+
+ if (node->isInnerNode()) {
+ const InnerNode *innerNode = static_cast<const InnerNode *>(node);
+ text << "All the functions in this " << typeString(node) << " are "
+ << theStockLink;
+
+ NodeList except;
+ NodeList::ConstIterator c = innerNode->childNodes().begin();
+ while (c != innerNode->childNodes().end()) {
+ if ((*c)->threadSafeness() != Node::UnspecifiedSafeness)
+ except.append(*c);
+ ++c;
+ }
+ if (except.isEmpty()) {
+ text << ".";
+ }
+ else {
+ text << ", except ";
+
+ NodeList::ConstIterator e = except.begin();
+ int index = 0;
+ while (e != except.end()) {
+ appendFullName(text, *e, innerNode, marker);
+ text << separator(index++, except.count());
+ ++e;
+ }
+ }
+ }
+ else {
+ text << "This " << typeString(node) << " is " << theStockLink << ".";
+ }
+ text << Atom::ParaRight;
+ }
+ generateText(text, node, marker);
+}
+
+void Generator::generateSince(const Node *node, CodeMarker *marker)
+{
+ if (!node->since().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft << "This " << typeString(node)
+ << " was introduced in ";
+ if (project.isEmpty())
+ text << "version";
+ else
+ text << project;
+ text << " " << node->since() << "." << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
+}
+
+/*!
+ No longer in use.
+ */
+void Generator::generateOverload(const Node *node, CodeMarker *marker)
+{
+ Text text;
+ text << Atom::ParaLeft
+ << "This function overloads ";
+ QString t = node->name() + "()";
+ text << Atom::AutoLink << t
+ << Atom::ParaRight;
+ generateText(text, node, marker);
+}
+
+void Generator::generateReimplementedFrom(const FunctionNode *func,
+ CodeMarker *marker)
+{
+ if (func->reimplementedFrom() != 0) {
+ const FunctionNode *from = func->reimplementedFrom();
+ if (from->access() != Node::Private && from->parent()->access() != Node::Private) {
+ Text text;
+ text << Atom::ParaLeft << "Reimplemented from ";
+ appendFullName(text, from->parent(), func, marker, from);
+ text << "." << Atom::ParaRight;
+ generateText(text, func, marker);
+ }
+ }
+}
+
+const Atom *Generator::generateAtomList(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker,
+ bool generate,
+ int &numAtoms)
+{
+ while (atom) {
+ if (atom->type() == Atom::FormatIf) {
+ int numAtoms0 = numAtoms;
+ bool rightFormat = canHandleFormat(atom->string());
+ atom = generateAtomList(atom->next(),
+ relative,
+ marker,
+ generate && rightFormat,
+ numAtoms);
+ if (!atom)
+ return 0;
+
+ if (atom->type() == Atom::FormatElse) {
+ ++numAtoms;
+ atom = generateAtomList(atom->next(),
+ relative,
+ marker,
+ generate && !rightFormat,
+ numAtoms);
+ if (!atom)
+ return 0;
+ }
+
+ if (atom->type() == Atom::FormatEndif) {
+ if (generate && numAtoms0 == numAtoms) {
+ relative->location().warning(tr("Output format %1 not handled").
+ arg(format()));
+ Atom unhandledFormatAtom(Atom::UnhandledFormat, format());
+ generateAtomList(&unhandledFormatAtom,
+ relative,
+ marker,
+ generate,
+ numAtoms);
+ }
+ atom = atom->next();
+ }
+ }
+ else if (atom->type() == Atom::FormatElse || atom->type() == Atom::FormatEndif) {
+ return atom;
+ }
+ else {
+ int n = 1;
+ if (generate) {
+ n += generateAtom(atom, relative, marker);
+ numAtoms += n;
+ }
+ while (n-- > 0)
+ atom = atom->next();
+ }
+ }
+ return 0;
+}
+
+void Generator::appendFullName(Text& text,
+ const Node *apparentNode,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *actualNode)
+{
+ if (actualNode == 0)
+ actualNode = apparentNode;
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, marker->plainFullName(apparentNode, relative))
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+}
+
+void Generator::appendSortedNames(Text& text,
+ const ClassNode *classe,
+ const QList<RelatedClass> &classes,
+ CodeMarker *marker)
+{
+ QList<RelatedClass>::ConstIterator r;
+ QMap<QString,Text> classMap;
+ int index = 0;
+
+ r = classes.begin();
+ while (r != classes.end()) {
+ if ((*r).node->access() == Node::Public && (*r).node->status() != Node::Internal
+ && !(*r).node->doc().isEmpty()) {
+ Text className;
+ appendFullName(className, (*r).node, classe, marker);
+ classMap[className.toString().toLower()] = className;
+ }
+ ++r;
+ }
+
+ QStringList classNames = classMap.keys();
+ classNames.sort();
+
+ foreach (const QString &className, classNames) {
+ text << classMap[className];
+ text << separator(index++, classNames.count());
+ }
+}
+
+int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
+{
+ int skipAhead = 0;
+ atom = atom->next();
+ while (atom != 0 && atom->type() != type) {
+ skipAhead++;
+ atom = atom->next();
+ }
+ return skipAhead;
+}
+
+QString Generator::fullName(const Node *node,
+ const Node *relative,
+ CodeMarker *marker) const
+{
+ if (node->type() == Node::Fake)
+ return static_cast<const FakeNode *>(node)->title();
+ else if (node->type() == Node::Class &&
+ !(static_cast<const ClassNode *>(node))->serviceName().isEmpty())
+ return (static_cast<const ClassNode *>(node))->serviceName();
+ else
+ return marker->plainFullName(node, relative);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/generator.h b/tools/qdoc3/generator.h
new file mode 100644
index 0000000000..3db2d8df79
--- /dev/null
+++ b/tools/qdoc3/generator.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ generator.h
+*/
+
+#ifndef GENERATOR_H
+#define GENERATOR_H
+
+#include <qlist.h>
+#include <qmap.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include "node.h"
+#include "text.h"
+
+QT_BEGIN_NAMESPACE
+
+class ClassNode;
+class Config;
+class CodeMarker;
+class FakeNode;
+class FunctionNode;
+class InnerNode;
+class Location;
+class NamespaceNode;
+class Node;
+class Tree;
+
+class Generator
+{
+ public:
+ Generator();
+ virtual ~Generator();
+
+ virtual void initializeGenerator(const Config &config);
+ virtual void terminateGenerator();
+ virtual QString format() = 0;
+ virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
+ virtual void generateTree(const Tree *tree, CodeMarker *marker) = 0;
+
+ static void initialize(const Config& config);
+ static void terminate();
+ static Generator *generatorForFormat(const QString& format);
+
+ protected:
+ virtual void startText(const Node *relative, CodeMarker *marker);
+ virtual void endText(const Node *relative, CodeMarker *marker);
+ virtual int generateAtom(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker);
+ virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
+ virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker);
+
+ virtual void generateText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker);
+#ifdef QDOC_QML
+ virtual void generateQmlText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker);
+#endif
+ virtual void generateBody(const Node *node, CodeMarker *marker);
+ virtual void generateAlsoList(const Node *node, CodeMarker *marker);
+ virtual void generateInherits(const ClassNode *classe,
+ CodeMarker *marker);
+ virtual void generateInheritedBy(const ClassNode *classe,
+ CodeMarker *marker);
+
+ void generateThreadSafeness(const Node *node, CodeMarker *marker);
+ void generateSince(const Node *node, CodeMarker *marker);
+ void generateStatus(const Node *node, CodeMarker *marker);
+ const Atom *generateAtomList(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker,
+ bool generate,
+ int& numGeneratedAtoms);
+ void generateExampleFiles(const FakeNode *fake, CodeMarker *marker);
+ void generateModuleWarning(const ClassNode *classe, CodeMarker *marker);
+
+ virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
+ virtual QString fullName(const Node *node,
+ const Node *relative,
+ CodeMarker *marker) const;
+
+ const QString& outputDir() { return outDir; }
+ QString indent(int level, const QString& markedCode);
+ QString plainCode(const QString& markedCode);
+ virtual QString typeString(const Node *node);
+ virtual QString imageFileName(const Node *relative, const QString& fileBase);
+ void setImageFileExtensions(const QStringList& extensions);
+ void unknownAtom(const Atom *atom);
+ QMap<QString, QString> &formattingLeftMap();
+ QMap<QString, QString> &formattingRightMap();
+
+ QMap<QString, QStringList> editionModuleMap;
+ QMap<QString, QStringList> editionGroupMap;
+
+ static QString trimmedTrailing(const QString &string);
+ static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType);
+ static void supplementAlsoList(const Node *node, QList<Text> &alsoList);
+
+ private:
+ void generateOverload(const Node *node, CodeMarker *marker);
+ void generateReimplementedFrom(const FunctionNode *func,
+ CodeMarker *marker);
+ void appendFullName(Text& text,
+ const Node *apparentNode,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *actualNode = 0);
+ void appendSortedNames(Text& text,
+ const ClassNode *classe,
+ const QList<RelatedClass> &classes,
+ CodeMarker *marker);
+
+ QString amp;
+ QString lt;
+ QString gt;
+ QString quot;
+ QRegExp tag;
+
+ static QList<Generator *> generators;
+ static QMap<QString, QMap<QString, QString> > fmtLeftMaps;
+ static QMap<QString, QMap<QString, QString> > fmtRightMaps;
+ static QMap<QString, QStringList> imgFileExts;
+ static QSet<QString> outputFormats;
+ static QStringList imageFiles;
+ static QStringList imageDirs;
+ static QString outDir;
+ static QString project;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp
new file mode 100644
index 0000000000..d0fa7c0a65
--- /dev/null
+++ b/tools/qdoc3/helpprojectwriter.cpp
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtXml>
+#include <QHash>
+#include <QMap>
+
+#include "atom.h"
+#include "helpprojectwriter.h"
+#include "htmlgenerator.h"
+#include "config.h"
+#include "node.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+HelpProjectWriter::HelpProjectWriter(const Config &config, const QString &defaultFileName)
+{
+ // The output directory should already have been checked by the calling
+ // generator.
+ outputDir = config.getString(CONFIG_OUTPUTDIR);
+
+ QStringList names = config.getStringList(CONFIG_QHP + Config::dot + "projects");
+
+ foreach (const QString &projectName, names) {
+ HelpProject project;
+ project.name = projectName;
+
+ QString prefix = CONFIG_QHP + Config::dot + projectName + Config::dot;
+ project.helpNamespace = config.getString(prefix + "namespace");
+ project.virtualFolder = config.getString(prefix + "virtualFolder");
+ project.fileName = config.getString(prefix + "file");
+ if (project.fileName.isEmpty())
+ project.fileName = defaultFileName;
+ project.extraFiles = config.getStringSet(prefix + "extraFiles");
+ project.indexTitle = config.getString(prefix + "indexTitle");
+ project.indexRoot = config.getString(prefix + "indexRoot");
+ project.filterAttributes = config.getStringList(prefix + "filterAttributes").toSet();
+ QSet<QString> customFilterNames = config.subVars(prefix + "customFilters");
+ foreach (const QString &filterName, customFilterNames) {
+ QString name = config.getString(prefix + "customFilters" + Config::dot + filterName + Config::dot + "name");
+ QSet<QString> filters = config.getStringList(prefix + "customFilters" + Config::dot + filterName + Config::dot + "filterAttributes").toSet();
+ project.customFilters[name] = filters;
+ }
+ //customFilters = config.defs.
+
+ foreach (QString name, config.getStringSet(prefix + "excluded"))
+ project.excluded.insert(name.replace("\\", "/"));
+
+ foreach (const QString &name, config.getStringList(prefix + "subprojects")) {
+ SubProject subproject;
+ QString subprefix = prefix + "subprojects" + Config::dot + name + Config::dot;
+ subproject.title = config.getString(subprefix + "title");
+ subproject.indexTitle = config.getString(subprefix + "indexTitle");
+ subproject.sortPages = config.getBool(subprefix + "sortPages");
+ readSelectors(subproject, config.getStringList(subprefix + "selectors"));
+ project.subprojects[name] = subproject;
+ }
+
+ if (project.subprojects.isEmpty()) {
+ SubProject subproject;
+ readSelectors(subproject, config.getStringList(prefix + "selectors"));
+ project.subprojects[""] = subproject;
+ }
+
+ projects.append(project);
+ }
+}
+
+void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList &selectors)
+{
+ QHash<QString, Node::Type> typeHash;
+ typeHash["namespace"] = Node::Namespace;
+ typeHash["class"] = Node::Class;
+ typeHash["fake"] = Node::Fake;
+ typeHash["enum"] = Node::Enum;
+ typeHash["typedef"] = Node::Typedef;
+ typeHash["function"] = Node::Function;
+ typeHash["property"] = Node::Property;
+ typeHash["variable"] = Node::Variable;
+ typeHash["target"] = Node::Target;
+
+ QHash<QString, FakeNode::SubType> subTypeHash;
+ subTypeHash["example"] = FakeNode::Example;
+ subTypeHash["headerfile"] = FakeNode::HeaderFile;
+ subTypeHash["file"] = FakeNode::File;
+ subTypeHash["group"] = FakeNode::Group;
+ subTypeHash["module"] = FakeNode::Module;
+ subTypeHash["page"] = FakeNode::Page;
+ subTypeHash["externalpage"] = FakeNode::ExternalPage;
+
+ QSet<FakeNode::SubType> allSubTypes = QSet<FakeNode::SubType>::fromList(subTypeHash.values());
+
+ foreach (const QString &selector, selectors) {
+ QStringList pieces = selector.split(":");
+ if (pieces.size() == 1) {
+ QString lower = selector.toLower();
+ if (typeHash.contains(lower))
+ subproject.selectors[typeHash[lower]] = allSubTypes;
+ } else if (pieces.size() >= 2) {
+ QString lower = pieces[0].toLower();
+ pieces = pieces[1].split(",");
+ if (typeHash.contains(lower)) {
+ QSet<FakeNode::SubType> subTypes;
+ for (int i = 0; i < pieces.size(); ++i) {
+ QString lower = pieces[i].toLower();
+ if (subTypeHash.contains(lower))
+ subTypes.insert(subTypeHash[lower]);
+ }
+ subproject.selectors[typeHash[lower]] = subTypes;
+ }
+ }
+ }
+}
+
+void HelpProjectWriter::addExtraFile(const QString &file)
+{
+ for (int i = 0; i < projects.size(); ++i)
+ projects[i].extraFiles.insert(file);
+}
+
+void HelpProjectWriter::addExtraFiles(const QSet<QString> &files)
+{
+ for (int i = 0; i < projects.size(); ++i)
+ projects[i].extraFiles.unite(files);
+}
+
+/*
+ Returns a list of strings describing the keyword details for a given node.
+
+ The first string is the human-readable name to be shown in Assistant.
+ The second string is a unique identifier.
+ The third string is the location of the documentation for the keyword.
+*/
+QStringList HelpProjectWriter::keywordDetails(const Node *node) const
+{
+ QStringList details;
+
+ if (node->parent() && !node->parent()->name().isEmpty()) {
+ // "name"
+ if (node->type() == Node::Enum || node->type() == Node::Typedef)
+ details << node->parent()->name()+"::"+node->name();
+ else
+ details << node->name();
+ // "id"
+ details << node->parent()->name()+"::"+node->name();
+ } else if (node->type() == Node::Fake) {
+ const FakeNode *fake = static_cast<const FakeNode *>(node);
+ details << fake->fullTitle();
+ details << fake->fullTitle();
+ } else {
+ details << node->name();
+ details << node->name();
+ }
+ details << tree->fullDocumentLocation(node);
+
+ return details;
+}
+
+bool HelpProjectWriter::generateSection(HelpProject &project,
+ QXmlStreamWriter & /* writer */, const Node *node)
+{
+ if (!node->url().isEmpty())
+ return false;
+
+ if (node->access() == Node::Private || node->status() == Node::Internal)
+ return false;
+
+ if (node->name().isEmpty())
+ return true;
+
+ QString docPath = node->doc().location().filePath();
+ if (!docPath.isEmpty() && project.excluded.contains(docPath))
+ return false;
+
+ QString objName;
+ if (node->type() == Node::Fake) {
+ const FakeNode *fake = static_cast<const FakeNode *>(node);
+ objName = fake->fullTitle();
+ } else
+ objName = tree->fullDocumentName(node);
+
+ // Only add nodes to the set for each subproject if they match a selector.
+ // Those that match will be listed in the table of contents.
+
+ foreach (const QString &name, project.subprojects.keys()) {
+ SubProject subproject = project.subprojects[name];
+ // No selectors: accept all nodes.
+ if (subproject.selectors.isEmpty())
+ project.subprojects[name].nodes[objName] = node;
+ else if (subproject.selectors.contains(node->type())) {
+ // Accept only the node types in the selectors hash.
+ if (node->type() != Node::Fake)
+ project.subprojects[name].nodes[objName] = node;
+ else {
+ // Accept only fake nodes with subtypes contained in the selector's
+ // mask.
+ const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
+ if (subproject.selectors[node->type()].contains(fakeNode->subType()) &&
+ fakeNode->subType() != FakeNode::ExternalPage &&
+ !fakeNode->fullTitle().isEmpty())
+
+ project.subprojects[name].nodes[objName] = node;
+ }
+ }
+ }
+
+ switch (node->type()) {
+
+ case Node::Class:
+ project.keywords.append(keywordDetails(node));
+ project.files.insert(tree->fullDocumentLocation(node));
+ break;
+
+ case Node::Namespace:
+ project.keywords.append(keywordDetails(node));
+ project.files.insert(tree->fullDocumentLocation(node));
+ break;
+
+ case Node::Enum:
+ project.keywords.append(keywordDetails(node));
+ {
+ const EnumNode *enumNode = static_cast<const EnumNode*>(node);
+ foreach (const EnumItem &item, enumNode->items()) {
+ QStringList details;
+
+ if (enumNode->itemAccess(item.name()) == Node::Private)
+ continue;
+
+ if (!node->parent()->name().isEmpty()) {
+ details << node->parent()->name()+"::"+item.name(); // "name"
+ details << node->parent()->name()+"::"+item.name(); // "id"
+ } else {
+ details << item.name(); // "name"
+ details << item.name(); // "id"
+ }
+ details << tree->fullDocumentLocation(node);
+ project.keywords.append(details);
+ }
+ }
+ break;
+
+ case Node::Property:
+ project.keywords.append(keywordDetails(node));
+ break;
+
+ case Node::Function:
+ {
+ const FunctionNode *funcNode = static_cast<const FunctionNode *>(node);
+
+ // Only insert keywords for non-constructors. Constructors are covered
+ // by the classes themselves.
+
+ if (funcNode->metaness() != FunctionNode::Ctor)
+ project.keywords.append(keywordDetails(node));
+
+ // Insert member status flags into the entries for the parent
+ // node of the function, or the node it is related to.
+ // Since parent nodes should have already been inserted into
+ // the set of files, we only need to ensure that related nodes
+ // are inserted.
+
+ if (node->relates()) {
+ project.memberStatus[node->relates()].insert(node->status());
+ project.files.insert(tree->fullDocumentLocation(node->relates()));
+ } else if (node->parent())
+ project.memberStatus[node->parent()].insert(node->status());
+ }
+ break;
+
+ case Node::Typedef:
+ {
+ const TypedefNode *typedefNode = static_cast<const TypedefNode *>(node);
+ QStringList typedefDetails = keywordDetails(node);
+ const EnumNode *enumNode = typedefNode->associatedEnum();
+ // Use the location of any associated enum node in preference
+ // to that of the typedef.
+ if (enumNode)
+ typedefDetails[2] = tree->fullDocumentLocation(enumNode);
+
+ project.keywords.append(typedefDetails);
+ }
+ break;
+
+ // Fake nodes (such as manual pages) contain subtypes, titles and other
+ // attributes.
+ case Node::Fake: {
+ const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
+ if (fakeNode->subType() != FakeNode::ExternalPage &&
+ !fakeNode->fullTitle().isEmpty()) {
+
+ if (fakeNode->subType() != FakeNode::File) {
+ if (fakeNode->doc().hasKeywords()) {
+ foreach (const Atom *keyword, fakeNode->doc().keywords()) {
+ if (!keyword->string().isEmpty()) {
+ QStringList details;
+ details << keyword->string()
+ << keyword->string()
+ << tree->fullDocumentLocation(node) + "#" + Doc::canonicalTitle(keyword->string());
+ project.keywords.append(details);
+ } else
+ fakeNode->doc().location().warning(
+ tr("Bad keyword in %1").arg(tree->fullDocumentLocation(node))
+ );
+ }
+ }
+ project.keywords.append(keywordDetails(node));
+ }
+/*
+ if (fakeNode->doc().hasTableOfContents()) {
+ foreach (const Atom *item, fakeNode->doc().tableOfContents()) {
+ QString title = Text::sectionHeading(item).toString();
+ if (!title.isEmpty()) {
+ QStringList details;
+ details << title
+ << title
+ << tree->fullDocumentLocation(node) + "#" + Doc::canonicalTitle(title);
+ project.keywords.append(details);
+ } else
+ fakeNode->doc().location().warning(
+ tr("Bad contents item in %1").arg(tree->fullDocumentLocation(node))
+ );
+ }
+ }
+*/
+ project.files.insert(tree->fullDocumentLocation(node));
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ // Add all images referenced in the page to the set of files to include.
+ const Atom *atom = node->doc().body().firstAtom();
+ while (atom) {
+ if (atom->type() == Atom::Image || atom->type() == Atom::InlineImage) {
+ // Images are all placed within a single directory regardless of
+ // whether the source images are in a nested directory structure.
+ QStringList pieces = atom->string().split("/");
+ project.files.insert("images/" + pieces.last());
+ }
+ atom = atom->next();
+ }
+
+ return true;
+}
+
+void HelpProjectWriter::generateSections(HelpProject &project,
+ QXmlStreamWriter &writer, const Node *node)
+{
+ if (!generateSection(project, writer, node))
+ return;
+
+ if (node->isInnerNode()) {
+ const InnerNode *inner = static_cast<const InnerNode *>(node);
+
+ // Ensure that we don't visit nodes more than once.
+ QMap<QString, const Node*> childMap;
+ foreach (const Node *node, inner->childNodes()) {
+ if (node->access() == Node::Private)
+ continue;
+ if (node->type() == Node::Fake)
+ childMap[static_cast<const FakeNode *>(node)->fullTitle()] = node;
+ else {
+ if (node->type() == Node::Function) {
+ const FunctionNode *funcNode = static_cast<const FunctionNode *>(node);
+ if (funcNode->isOverload())
+ continue;
+ }
+ childMap[tree->fullDocumentName(node)] = node;
+ }
+ }
+
+ foreach (const Node *child, childMap)
+ generateSections(project, writer, child);
+ }
+}
+
+void HelpProjectWriter::generate(const Tree *tre)
+{
+ this->tree = tre;
+ for (int i = 0; i < projects.size(); ++i)
+ generateProject(projects[i]);
+}
+
+void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer,
+ const Node *node)
+{
+ QString href = tree->fullDocumentLocation(node);
+ QString objName = node->name();
+
+ switch (node->type()) {
+
+ case Node::Class:
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", href);
+ if (node->parent() && !node->parent()->name().isEmpty())
+ writer.writeAttribute("title", tr("%1::%2 Class Reference").arg(node->parent()->name()).arg(objName));
+ else
+ writer.writeAttribute("title", tr("%1 Class Reference").arg(objName));
+
+ // Write subsections for all members, obsolete members and Qt 3
+ // members.
+ if (!project.memberStatus[node].isEmpty()) {
+ QString membersPath = href.left(href.size()-5) + "-members.html";
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", membersPath);
+ writer.writeAttribute("title", tr("List of all members"));
+ writer.writeEndElement(); // section
+ project.files.insert(membersPath);
+ }
+ if (project.memberStatus[node].contains(Node::Compat)) {
+ QString compatPath = href.left(href.size()-5) + "-qt3.html";
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", compatPath);
+ writer.writeAttribute("title", tr("Qt 3 support members"));
+ writer.writeEndElement(); // section
+ project.files.insert(compatPath);
+ }
+ if (project.memberStatus[node].contains(Node::Obsolete)) {
+ QString obsoletePath = href.left(href.size()-5) + "-obsolete.html";
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", obsoletePath);
+ writer.writeAttribute("title", tr("Obsolete members"));
+ writer.writeEndElement(); // section
+ project.files.insert(obsoletePath);
+ }
+
+ writer.writeEndElement(); // section
+ break;
+
+ case Node::Namespace:
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", href);
+ writer.writeAttribute("title", objName);
+ writer.writeEndElement(); // section
+ break;
+
+ case Node::Fake: {
+ // Fake nodes (such as manual pages) contain subtypes, titles and other
+ // attributes.
+ const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
+
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", href);
+ writer.writeAttribute("title", fakeNode->fullTitle());
+ // qDebug() << "Title:" << fakeNode->fullTitle();
+
+ if (fakeNode->subType() == FakeNode::HeaderFile) {
+
+ // Write subsections for all members, obsolete members and Qt 3
+ // members.
+ if (!project.memberStatus[node].isEmpty()) {
+ QString membersPath = href.left(href.size()-5) + "-members.html";
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", membersPath);
+ writer.writeAttribute("title", tr("List of all members"));
+ writer.writeEndElement(); // section
+ project.files.insert(membersPath);
+ }
+ if (project.memberStatus[node].contains(Node::Compat)) {
+ QString compatPath = href.left(href.size()-5) + "-qt3.html";
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", compatPath);
+ writer.writeAttribute("title", tr("Qt 3 support members"));
+ writer.writeEndElement(); // section
+ project.files.insert(compatPath);
+ }
+ if (project.memberStatus[node].contains(Node::Obsolete)) {
+ QString obsoletePath = href.left(href.size()-5) + "-obsolete.html";
+ writer.writeStartElement("section");
+ writer.writeAttribute("ref", obsoletePath);
+ writer.writeAttribute("title", tr("Obsolete members"));
+ writer.writeEndElement(); // section
+ project.files.insert(obsoletePath);
+ }
+ }
+
+ writer.writeEndElement(); // section
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+void HelpProjectWriter::generateProject(HelpProject &project)
+{
+ const Node *rootNode;
+ if (!project.indexRoot.isEmpty())
+ rootNode = tree->findFakeNodeByTitle(project.indexRoot);
+ else
+ rootNode = tree->root();
+
+ if (!rootNode)
+ return;
+
+ project.files.clear();
+ project.keywords.clear();
+
+ QFile file(outputDir + QDir::separator() + project.fileName);
+ if (!file.open(QFile::WriteOnly | QFile::Text))
+ return;
+
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument();
+ writer.writeStartElement("QtHelpProject");
+ writer.writeAttribute("version", "1.0");
+
+ // Write metaData, virtualFolder and namespace elements.
+ writer.writeTextElement("namespace", project.helpNamespace);
+ writer.writeTextElement("virtualFolder", project.virtualFolder);
+
+ // Write customFilter elements.
+ QHash<QString, QSet<QString> >::ConstIterator it;
+ for (it = project.customFilters.begin(); it != project.customFilters.end(); ++it) {
+ writer.writeStartElement("customFilter");
+ writer.writeAttribute("name", it.key());
+ foreach (const QString &filter, it.value())
+ writer.writeTextElement("filterAttribute", filter);
+ writer.writeEndElement(); // customFilter
+ }
+
+ // Start the filterSection.
+ writer.writeStartElement("filterSection");
+
+ // Write filterAttribute elements.
+ foreach (const QString &filterName, project.filterAttributes)
+ writer.writeTextElement("filterAttribute", filterName);
+
+ writer.writeStartElement("toc");
+ writer.writeStartElement("section");
+ QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(project.indexTitle));
+ if (indexPath.isEmpty())
+ indexPath = "index.html";
+ writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath));
+ writer.writeAttribute("title", project.indexTitle);
+ project.files.insert(tree->fullDocumentLocation(rootNode));
+
+ generateSections(project, writer, rootNode);
+
+ foreach (const QString &name, project.subprojects.keys()) {
+ SubProject subproject = project.subprojects[name];
+
+ if (!name.isEmpty()) {
+ writer.writeStartElement("section");
+ QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle));
+ writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath));
+ writer.writeAttribute("title", subproject.title);
+ project.files.insert(indexPath);
+ }
+ if (subproject.sortPages) {
+ QStringList titles = subproject.nodes.keys();
+ titles.sort();
+ foreach (const QString &title, titles)
+ writeNode(project, writer, subproject.nodes[title]);
+ } else {
+ // Find a contents node and navigate from there, using the NextLink values.
+ foreach (const Node *node, subproject.nodes) {
+ QString nextTitle = node->links().value(Node::NextLink).first;
+ if (!nextTitle.isEmpty() &&
+ node->links().value(Node::ContentsLink).first.isEmpty()) {
+
+ FakeNode *nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle));
+
+ // Write the contents node.
+ writeNode(project, writer, node);
+
+ while (nextPage) {
+ writeNode(project, writer, nextPage);
+ nextTitle = nextPage->links().value(Node::NextLink).first;
+ if (nextTitle.isEmpty())
+ break;
+ nextPage = const_cast<FakeNode *>(tree->findFakeNodeByTitle(nextTitle));
+ }
+ break;
+ }
+ }
+ }
+
+ if (!name.isEmpty())
+ writer.writeEndElement(); // section
+ }
+
+ writer.writeEndElement(); // section
+ writer.writeEndElement(); // toc
+
+ writer.writeStartElement("keywords");
+ foreach (const QStringList &details, project.keywords) {
+ writer.writeStartElement("keyword");
+ writer.writeAttribute("name", details[0]);
+ writer.writeAttribute("id", details[1]);
+ writer.writeAttribute("ref", HtmlGenerator::cleanRef(details[2]));
+ writer.writeEndElement(); //keyword
+ }
+ writer.writeEndElement(); // keywords
+
+ writer.writeStartElement("files");
+ foreach (const QString &usedFile, project.files) {
+ if (!usedFile.isEmpty())
+ writer.writeTextElement("file", usedFile);
+ }
+ foreach (const QString &usedFile, project.extraFiles)
+ writer.writeTextElement("file", usedFile);
+ writer.writeEndElement(); // files
+
+ writer.writeEndElement(); // filterSection
+ writer.writeEndElement(); // QtHelpProject
+ writer.writeEndDocument();
+ file.close();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/helpprojectwriter.h b/tools/qdoc3/helpprojectwriter.h
new file mode 100644
index 0000000000..f90b2a403a
--- /dev/null
+++ b/tools/qdoc3/helpprojectwriter.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HELPPROJECTWRITER_H
+#define HELPPROJECTWRITER_H
+
+#include <QString>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+#include "config.h"
+#include "node.h"
+
+QT_BEGIN_NAMESPACE
+
+class Tree;
+typedef QPair<QString, const Node*> QStringNodePair;
+
+struct SubProject
+{
+ QString title;
+ QString indexTitle;
+ QHash<Node::Type, QSet<FakeNode::SubType> > selectors;
+ bool sortPages;
+ QHash<QString, const Node *> nodes;
+};
+
+struct HelpProject
+{
+ QString name;
+ QString helpNamespace;
+ QString virtualFolder;
+ QString fileName;
+ QString indexRoot;
+ QString indexTitle;
+ QList<QStringList> keywords;
+ QSet<QString> files;
+ QSet<QString> extraFiles;
+ QSet<QString> filterAttributes;
+ QHash<QString, QSet<QString> > customFilters;
+ QSet<QString> excluded;
+ QMap<QString, SubProject> subprojects;
+ QHash<const Node *, QSet<Node::Status> > memberStatus;
+};
+
+class HelpProjectWriter
+{
+public:
+ HelpProjectWriter(const Config &config, const QString &defaultFileName);
+ void addExtraFile(const QString &file);
+ void addExtraFiles(const QSet<QString> &files);
+ void generate(const Tree *tre);
+
+private:
+ void generateProject(HelpProject &project);
+ void generateSections(HelpProject &project, QXmlStreamWriter &writer,
+ const Node *node);
+ bool generateSection(HelpProject &project, QXmlStreamWriter &writer,
+ const Node *node);
+ QStringList keywordDetails(const Node *node) const;
+ void writeNode(HelpProject &project, QXmlStreamWriter &writer, const Node *node);
+ void readSelectors(SubProject &subproject, const QStringList &selectors);
+
+ const Tree *tree;
+
+ QString outputDir;
+ QList<HelpProject> projects;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp
new file mode 100644
index 0000000000..13d52bfdf4
--- /dev/null
+++ b/tools/qdoc3/htmlgenerator.cpp
@@ -0,0 +1,3195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ htmlgenerator.cpp
+*/
+
+#include "codemarker.h"
+#include "helpprojectwriter.h"
+#include "htmlgenerator.h"
+#include "node.h"
+#include "separator.h"
+#include "tree.h"
+#include <ctype.h>
+
+#include <qdebug.h>
+#include <qlist.h>
+#include <qiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+#define COMMAND_VERSION Doc::alias("version")
+
+static bool showBrokenLinks = false;
+
+HtmlGenerator::HtmlGenerator()
+ : helpProjectWriter(0), inLink(false), inContents(false),
+ inSectionHeading(false), inTableHeader(false), numTableRows(0),
+ threeColumnEnumValueTable(true), funcLeftParen("\\S(\\()"),
+ tre(0), slow(false)
+{
+}
+
+HtmlGenerator::~HtmlGenerator()
+{
+ if (helpProjectWriter)
+ delete helpProjectWriter;
+}
+
+void HtmlGenerator::initializeGenerator(const Config &config)
+{
+ static const struct {
+ const char *key;
+ const char *left;
+ const char *right;
+ } defaults[] = {
+ { ATOM_FORMATTING_BOLD, "<b>", "</b>" },
+ { ATOM_FORMATTING_INDEX, "<!--", "-->" },
+ { ATOM_FORMATTING_ITALIC, "<i>", "</i>" },
+ { ATOM_FORMATTING_PARAMETER, "<i>", "</i>" },
+ { ATOM_FORMATTING_SUBSCRIPT, "<sub>", "</sub>" },
+ { ATOM_FORMATTING_SUPERSCRIPT, "<sup>", "</sup>" },
+ { ATOM_FORMATTING_TELETYPE, "<tt>", "</tt>" },
+ { ATOM_FORMATTING_UNDERLINE, "<u>", "</u>" },
+ { 0, 0, 0 }
+ };
+
+ Generator::initializeGenerator(config);
+ setImageFileExtensions(QStringList() << "png" << "jpg" << "jpeg" << "gif");
+ int i = 0;
+ while (defaults[i].key) {
+ formattingLeftMap().insert(defaults[i].key, defaults[i].left);
+ formattingRightMap().insert(defaults[i].key, defaults[i].right);
+ i++;
+ }
+
+ style = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLE);
+ postHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTHEADER);
+ footer = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_FOOTER);
+ address = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_ADDRESS);
+ pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_GENERATEMACREFS);
+
+ project = config.getString(CONFIG_PROJECT);
+
+ projectDescription = config.getString(CONFIG_DESCRIPTION);
+ if (projectDescription.isEmpty() && !project.isEmpty())
+ projectDescription = project + " Reference Documentation";
+
+ projectUrl = config.getString(CONFIG_URL);
+
+ QSet<QString> editionNames = config.subVars(CONFIG_EDITION);
+ QSet<QString>::ConstIterator edition = editionNames.begin();
+ while (edition != editionNames.end()) {
+ QString editionName = *edition;
+ QStringList editionModules = config.getStringList(
+ CONFIG_EDITION + Config::dot + editionName + Config::dot + "modules");
+ QStringList editionGroups = config.getStringList(
+ CONFIG_EDITION + Config::dot + editionName + Config::dot + "groups");
+
+ if (!editionModules.isEmpty())
+ editionModuleMap[editionName] = editionModules;
+ if (!editionGroups.isEmpty())
+ editionGroupMap[editionName] = editionGroups;
+
+ ++edition;
+ }
+
+ slow = config.getBool(CONFIG_SLOW);
+
+ stylesheets = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLESHEETS);
+ customHeadElements = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_CUSTOMHEADELEMENTS);
+ codeIndent = config.getInt(CONFIG_CODEINDENT);
+
+ helpProjectWriter = new HelpProjectWriter(config, project.toLower() + ".qhp");
+}
+
+void HtmlGenerator::terminateGenerator()
+{
+ Generator::terminateGenerator();
+}
+
+QString HtmlGenerator::format()
+{
+ return "HTML";
+}
+
+/*!
+ This is where the html files and dcf files are written.
+ \note The html file generation is done in the base class,
+ PageGenerator::generateTree().
+ */
+void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
+{
+ // Copy the stylesheets from the directory containing the qdocconf file.
+ // ### This should be changed to use a special directory in doc/src.
+ QStringList::ConstIterator styleIter = stylesheets.begin();
+ QDir configPath = QDir::current();
+ while (styleIter != stylesheets.end()) {
+ QString filePath = configPath.absoluteFilePath(*styleIter);
+ Config::copyFile(Location(), filePath, filePath, outputDir());
+ ++styleIter;
+ }
+
+ tre = tree;
+ nonCompatClasses.clear();
+ mainClasses.clear();
+ compatClasses.clear();
+ moduleClassMap.clear();
+ moduleNamespaceMap.clear();
+ funcIndex.clear();
+ legaleseTexts.clear();
+ serviceClasses.clear();
+ findAllClasses(tree->root());
+ findAllFunctions(tree->root());
+ findAllLegaleseTexts(tree->root());
+ findAllNamespaces(tree->root());
+#ifdef ZZZ_QDOC_QML
+ findAllQmlClasses(tree->root());
+#endif
+
+ PageGenerator::generateTree(tree, marker);
+
+ dcfClassesRoot.ref = "classes.html";
+ dcfClassesRoot.title = "Classes";
+ qSort(dcfClassesRoot.subsections);
+
+ dcfOverviewsRoot.ref = "overviews.html";
+ dcfOverviewsRoot.title = "Overviews";
+ qSort(dcfOverviewsRoot.subsections);
+
+ dcfExamplesRoot.ref = "examples.html";
+ dcfExamplesRoot.title = "Tutorial & Examples";
+ qSort(dcfExamplesRoot.subsections);
+
+ DcfSection qtRoot;
+ appendDcfSubSection(&qtRoot, dcfClassesRoot);
+ appendDcfSubSection(&qtRoot, dcfOverviewsRoot);
+ appendDcfSubSection(&qtRoot, dcfExamplesRoot);
+
+ generateDcf(project.toLower().simplified().replace(" ", "-"),
+ "index.html",
+ projectDescription, qtRoot);
+ generateDcf("designer",
+ "designer-manual.html",
+ "Qt Designer Manual",
+ dcfDesignerRoot);
+ generateDcf("linguist",
+ "linguist-manual.html",
+ "Qt Linguist Manual",
+ dcfLinguistRoot);
+ generateDcf("assistant",
+ "assistant-manual.html",
+ "Qt Assistant Manual",
+ dcfAssistantRoot);
+ generateDcf("qmake",
+ "qmake-manual.html",
+ "qmake Manual",
+ dcfQmakeRoot);
+
+ generateIndex(project.toLower().simplified().replace(" ", "-"),
+ projectUrl,
+ projectDescription);
+
+ helpProjectWriter->generate(tre);
+}
+
+void HtmlGenerator::startText(const Node * /* relative */,
+ CodeMarker * /* marker */)
+{
+ inLink = false;
+ inContents = false;
+ inSectionHeading = false;
+ inTableHeader = false;
+ numTableRows = 0;
+ threeColumnEnumValueTable = true;
+ link.clear();
+ sectionNumber.clear();
+}
+
+int HtmlGenerator::generateAtom(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ int skipAhead = 0;
+ static bool in_para = false;
+
+ switch (atom->type()) {
+ case Atom::AbstractLeft:
+ break;
+ case Atom::AbstractRight:
+ break;
+ case Atom::AutoLink:
+ if (!inLink && !inContents && !inSectionHeading) {
+ const Node *node = 0;
+ QString link = getLink(atom, relative, marker, node);
+ if (!link.isEmpty()) {
+ beginLink(link, node, relative, marker);
+ generateLink(atom, relative, marker);
+ endLink();
+ }
+ else {
+ out() << protect(atom->string());
+ }
+ }
+ else {
+ out() << protect(atom->string());
+ }
+ break;
+ case Atom::BaseName:
+ break;
+ case Atom::BriefLeft:
+ if (relative->type() == Node::Fake) {
+ skipAhead = skipAtoms(atom, Atom::BriefRight);
+ break;
+ }
+
+ out() << "<p>";
+ if (relative->type() == Node::Property ||
+ relative->type() == Node::Variable) {
+ QString str;
+ atom = atom->next();
+ while (atom != 0 && atom->type() != Atom::BriefRight) {
+ if (atom->type() == Atom::String || atom->type() == Atom::AutoLink)
+ str += atom->string();
+ skipAhead++;
+ atom = atom->next();
+ }
+ str[0] = str[0].toLower();
+ if (str.right(1) == ".")
+ str.truncate(str.length() - 1);
+ out() << "This ";
+ if (relative->type() == Node::Property)
+ out() << "property";
+ else
+ out() << "variable";
+ QStringList words = str.split(" ");
+ if (!(words.first() == "contains" || words.first() == "specifies"
+ || words.first() == "describes" || words.first() == "defines"
+ || words.first() == "holds" || words.first() == "determines"))
+ out() << " holds ";
+ else
+ out() << " ";
+ out() << str << ".";
+ }
+ break;
+ case Atom::BriefRight:
+ if (relative->type() != Node::Fake)
+ out() << "</p>\n";
+ break;
+ case Atom::C:
+ out() << formattingLeftMap()[ATOM_FORMATTING_TELETYPE];
+ if (inLink) {
+ out() << protect(plainCode(atom->string()));
+ }
+ else {
+ out() << highlightedCode(atom->string(), marker, relative);
+ }
+ out() << formattingRightMap()[ATOM_FORMATTING_TELETYPE];
+ break;
+ case Atom::Code:
+ out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
+ marker, relative))
+ << "</pre>\n";
+ break;
+#ifdef QDOC_QML
+ case Atom::Qml:
+ out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
+ marker, relative))
+ << "</pre>\n";
+ break;
+#endif
+ case Atom::CodeNew:
+ out() << "<p>you can rewrite it as</p>\n"
+ << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
+ marker, relative))
+ << "</pre>\n";
+ break;
+ case Atom::CodeOld:
+ out() << "<p>For example, if you have code like</p>\n";
+ // fallthrough
+ case Atom::CodeBad:
+ out() << "<pre><font color=\"#404040\">"
+ << trimmedTrailing(protect(plainCode(indent(codeIndent, atom->string()))))
+ << "</font></pre>\n";
+ break;
+ case Atom::FootnoteLeft:
+ // ### For now
+ if (in_para) {
+ out() << "</p>\n";
+ in_para = false;
+ }
+ out() << "<!-- ";
+ break;
+ case Atom::FootnoteRight:
+ // ### For now
+ out() << "-->";
+ break;
+ case Atom::FormatElse:
+ case Atom::FormatEndif:
+ case Atom::FormatIf:
+ break;
+ case Atom::FormattingLeft:
+ out() << formattingLeftMap()[atom->string()];
+ if (atom->string() == ATOM_FORMATTING_PARAMETER) {
+ if (atom->next() != 0 && atom->next()->type() == Atom::String) {
+ QRegExp subscriptRegExp("([a-z]+)_([0-9n])");
+ if (subscriptRegExp.exactMatch(atom->next()->string())) {
+ out() << subscriptRegExp.cap(1) << "<sub>"
+ << subscriptRegExp.cap(2) << "</sub>";
+ skipAhead = 1;
+ }
+ }
+ }
+ break;
+ case Atom::FormattingRight:
+ if (atom->string() == ATOM_FORMATTING_LINK) {
+ endLink();
+ }
+ else {
+ out() << formattingRightMap()[atom->string()];
+ }
+ break;
+ case Atom::GeneratedList:
+ if (atom->string() == "annotatedclasses") {
+ generateAnnotatedList(relative, marker, nonCompatClasses);
+ }
+ else if (atom->string() == "classes") {
+ generateCompactList(relative, marker, nonCompatClasses);
+ }
+ else if (atom->string().contains("classesbymodule")) {
+ QString arg = atom->string().trimmed();
+ QString moduleName = atom->string().mid(atom->string().indexOf(
+ "classesbymodule") + 15).trimmed();
+ if (moduleClassMap.contains(moduleName))
+ generateAnnotatedList(relative, marker, moduleClassMap[moduleName]);
+ }
+ else if (atom->string().contains("classesbyedition")) {
+
+ QString arg = atom->string().trimmed();
+ QString editionName = atom->string().mid(atom->string().indexOf(
+ "classesbyedition") + 16).trimmed();
+
+ if (editionModuleMap.contains(editionName)) {
+
+ // Add all classes in the modules listed for that edition.
+ QMap<QString, const Node *> editionClasses;
+ foreach (const QString &moduleName, editionModuleMap[editionName]) {
+ if (moduleClassMap.contains(moduleName))
+ editionClasses.unite(moduleClassMap[moduleName]);
+ }
+
+ // Add additional groups and remove groups of classes that
+ // should be excluded from the edition.
+
+ QMultiMap <QString, Node *> groups = tre->groups();
+ foreach (const QString &groupName, editionGroupMap[editionName]) {
+ QList<Node *> groupClasses;
+ if (groupName.startsWith("-")) {
+ groupClasses = groups.values(groupName.mid(1));
+ foreach (const Node *node, groupClasses)
+ editionClasses.remove(node->name());
+ }
+ else {
+ groupClasses = groups.values(groupName);
+ foreach (const Node *node, groupClasses)
+ editionClasses.insert(node->name(), node);
+ }
+ }
+ generateAnnotatedList(relative, marker, editionClasses);
+ }
+ }
+ else if (atom->string() == "classhierarchy") {
+ generateClassHierarchy(relative, marker, nonCompatClasses);
+ }
+ else if (atom->string() == "compatclasses") {
+ generateCompactList(relative, marker, compatClasses);
+ }
+ else if (atom->string() == "functionindex") {
+ generateFunctionIndex(relative, marker);
+ }
+ else if (atom->string() == "legalese") {
+ generateLegaleseList(relative, marker);
+ }
+ else if (atom->string() == "mainclasses") {
+ generateCompactList(relative, marker, mainClasses);
+ }
+ else if (atom->string() == "services") {
+ generateCompactList(relative, marker, serviceClasses);
+ }
+ else if (atom->string() == "overviews") {
+ generateOverviewList(relative, marker);
+ }
+ else if (atom->string() == "namespaces") {
+ generateAnnotatedList(relative, marker, namespaceIndex);
+ }
+ else if (atom->string() == "related") {
+ const FakeNode *fake = static_cast<const FakeNode *>(relative);
+ if (fake && !fake->groupMembers().isEmpty()) {
+ QMap<QString, const Node *> groupMembersMap;
+ foreach (const Node *node, fake->groupMembers()) {
+ if (node->type() == Node::Fake)
+ groupMembersMap[fullName(node, relative, marker)] = node;
+ }
+ generateAnnotatedList(fake, marker, groupMembersMap);
+ }
+ }
+ else if (atom->string() == "relatedinline") {
+ const FakeNode *fake = static_cast<const FakeNode *>(relative);
+ if (fake && !fake->groupMembers().isEmpty()) {
+ // Reverse the list into the original scan order.
+ // Should be sorted. But on what? It may not be a
+ // regular class or page definition.
+ QList<const Node *> list;
+ foreach (const Node *node, fake->groupMembers())
+ list.prepend(node);
+ foreach (const Node *node, list)
+ generateBody(node, marker);
+ }
+ }
+ break;
+ case Atom::Image:
+ case Atom::InlineImage:
+ {
+ QString fileName = imageFileName(relative, atom->string());
+ QString text;
+ if (atom->next() != 0)
+ text = atom->next()->string();
+ if (atom->type() == Atom::Image)
+ out() << "<p align=\"center\">";
+ if (fileName.isEmpty()) {
+ out() << "<font color=\"red\">[Missing image "
+ << protect(atom->string()) << "]</font>";
+ }
+ else {
+ out() << "<img src=\"" << protect(fileName) << "\"";
+ if (!text.isEmpty())
+ out() << " alt=\"" << protect(text) << "\"";
+ out() << " />";
+ helpProjectWriter->addExtraFile(fileName);
+ }
+ if (atom->type() == Atom::Image)
+ out() << "</p>";
+ }
+ break;
+ case Atom::ImageText:
+ break;
+ case Atom::LegaleseLeft:
+ out() << "<div style=\"padding: 0.5em; background: #e0e0e0; color: black\">";
+ break;
+ case Atom::LegaleseRight:
+ out() << "</div>";
+ break;
+ case Atom::LineBreak:
+ out() << "<br />";
+ break;
+ case Atom::Link:
+ {
+ const Node *node = 0;
+ QString myLink = getLink(atom, relative, marker, node);
+ if (myLink.isEmpty())
+ relative->doc().location().warning(tr("Cannot link to '%1' in %2")
+ .arg(atom->string())
+ .arg(marker->plainFullName(relative)));
+ beginLink(myLink, node, relative, marker);
+ skipAhead = 1;
+ }
+ break;
+ case Atom::LinkNode:
+ {
+ const Node *node = CodeMarker::nodeForString(atom->string());
+ beginLink(linkForNode(node, relative), node, relative, marker);
+ skipAhead = 1;
+ }
+ break;
+ case Atom::ListLeft:
+ if (in_para) {
+ out() << "</p>\n";
+ in_para = false;
+ }
+ if (atom->string() == ATOM_LIST_BULLET) {
+ out() << "<ul>\n";
+ }
+ else if (atom->string() == ATOM_LIST_TAG) {
+ out() << "<dl>\n";
+ }
+ else if (atom->string() == ATOM_LIST_VALUE) {
+ threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
+ if (threeColumnEnumValueTable) {
+ out() << "<p><table border=\"1\" cellpadding=\"2\" cellspacing=\"1\" width=\"100%\">\n"
+ "<tr><th width=\"25%\">Constant</th><th width=\"15%\">Value</th>"
+ "<th width=\"60%\">Description</th></tr>\n";
+ }
+ else {
+ out() << "<p><table border=\"1\" cellpadding=\"2\" cellspacing=\"1\" width=\"40%\">\n"
+ << "<tr><th width=\"60%\">Constant</th><th width=\"40%\">Value</th></tr>\n";
+ }
+ }
+ else {
+ out() << "<ol type=";
+ if (atom->string() == ATOM_LIST_UPPERALPHA) {
+ out() << "\"A\"";
+ }
+ else if (atom->string() == ATOM_LIST_LOWERALPHA) {
+ out() << "\"a\"";
+ }
+ else if (atom->string() == ATOM_LIST_UPPERROMAN) {
+ out() << "\"I\"";
+ }
+ else if (atom->string() == ATOM_LIST_LOWERROMAN) {
+ out() << "\"i\"";
+ }
+ else { // (atom->string() == ATOM_LIST_NUMERIC)
+ out() << "\"1\"";
+ }
+ if (atom->next() != 0 && atom->next()->string().toInt() != 1)
+ out() << " start=\"" << atom->next()->string() << "\"";
+ out() << ">\n";
+ }
+ break;
+ case Atom::ListItemNumber:
+ break;
+ case Atom::ListTagLeft:
+ if (atom->string() == ATOM_LIST_TAG) {
+ out() << "<dt>";
+ }
+ else { // (atom->string() == ATOM_LIST_VALUE)
+ // ### Trenton
+
+ out() << "<tr><td valign=\"top\"><tt>"
+ << protect(plainCode(marker->markedUpEnumValue(atom->next()->string(),
+ relative)))
+ << "</tt></td><td align=\"center\" valign=\"top\">";
+
+ QString itemValue;
+ if (relative->type() == Node::Enum) {
+ const EnumNode *enume = static_cast<const EnumNode *>(relative);
+ itemValue = enume->itemValue(atom->next()->string());
+ }
+
+ if (itemValue.isEmpty())
+ out() << "?";
+ else
+ out() << "<tt>" << protect(itemValue) << "</tt>";
+
+ skipAhead = 1;
+ }
+ break;
+ case Atom::ListTagRight:
+ if (atom->string() == ATOM_LIST_TAG)
+ out() << "</dt>\n";
+ break;
+ case Atom::ListItemLeft:
+ if (atom->string() == ATOM_LIST_TAG) {
+ out() << "<dd>";
+ }
+ else if (atom->string() == ATOM_LIST_VALUE) {
+ if (threeColumnEnumValueTable) {
+ out() << "</td><td valign=\"top\">";
+ if (matchAhead(atom, Atom::ListItemRight))
+ out() << "&nbsp;";
+ }
+ }
+ else {
+ out() << "<li>";
+ }
+ if (matchAhead(atom, Atom::ParaLeft))
+ skipAhead = 1;
+ break;
+ case Atom::ListItemRight:
+ if (atom->string() == ATOM_LIST_TAG) {
+ out() << "</dd>\n";
+ }
+ else if (atom->string() == ATOM_LIST_VALUE) {
+ out() << "</td></tr>\n";
+ }
+ else {
+ out() << "</li>\n";
+ }
+ break;
+ case Atom::ListRight:
+ if (atom->string() == ATOM_LIST_BULLET) {
+ out() << "</ul>\n";
+ }
+ else if (atom->string() == ATOM_LIST_TAG) {
+ out() << "</dl>\n";
+ }
+ else if (atom->string() == ATOM_LIST_VALUE) {
+ out() << "</table></p>\n";
+ }
+ else {
+ out() << "</ol>\n";
+ }
+ break;
+ case Atom::Nop:
+ break;
+ case Atom::ParaLeft:
+ out() << "<p>";
+ in_para = true;
+ break;
+ case Atom::ParaRight:
+ endLink();
+ if (in_para) {
+ out() << "</p>\n";
+ in_para = false;
+ }
+ //if (!matchAhead(atom, Atom::ListItemRight) && !matchAhead(atom, Atom::TableItemRight))
+ // out() << "</p>\n";
+ break;
+ case Atom::QuotationLeft:
+ out() << "<blockquote>";
+ break;
+ case Atom::QuotationRight:
+ out() << "</blockquote>\n";
+ break;
+ case Atom::RawString:
+ out() << atom->string();
+ break;
+ case Atom::SectionLeft:
+#if 0
+ {
+ int nextLevel = atom->string().toInt();
+ if (sectionNumber.size() < nextLevel) {
+ do {
+ sectionNumber.append("1");
+ } while (sectionNumber.size() < nextLevel);
+ }
+ else {
+ while (sectionNumber.size() > nextLevel) {
+ sectionNumber.removeLast();
+ }
+ sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
+ }
+ out() << "<a name=\"sec-" << sectionNumber.join("-") << "\"></a>\n";
+ }
+#else
+ out() << "<a name=\"" << Doc::canonicalTitle(Text::sectionHeading(atom).toString())
+ << "\"></a>\n";
+#endif
+ break;
+ case Atom::SectionRight:
+ break;
+ case Atom::SectionHeadingLeft:
+ out() << "<h" + QString::number(atom->string().toInt() + hOffset(relative)) + ">";
+ inSectionHeading = true;
+ break;
+ case Atom::SectionHeadingRight:
+ out() << "</h" + QString::number(atom->string().toInt() + hOffset(relative)) + ">\n";
+ inSectionHeading = false;
+ break;
+ case Atom::SidebarLeft:
+ break;
+ case Atom::SidebarRight:
+ break;
+ case Atom::String:
+ if (inLink && !inContents && !inSectionHeading) {
+ generateLink(atom, relative, marker);
+ }
+ else {
+ out() << protect(atom->string());
+ }
+ break;
+ case Atom::TableLeft:
+ if (in_para) {
+ out() << "</p>\n";
+ in_para = false;
+ }
+ if (!atom->string().isEmpty()) {
+ if (atom->string().contains("%"))
+ out() << "<p><table width=\"" << atom->string() << "\" "
+ << "align=\"center\" cellpadding=\"2\" "
+ << "cellspacing=\"1\" border=\"0\">\n";
+ else
+ out() << "<p><table align=\"center\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
+ }
+ else {
+ out() << "<p><table align=\"center\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
+ }
+ numTableRows = 0;
+ break;
+ case Atom::TableRight:
+ out() << "</table></p>\n";
+ break;
+ case Atom::TableHeaderLeft:
+ out() << "<thead><tr valign=\"top\" class=\"qt-style\">";
+ inTableHeader = true;
+ break;
+ case Atom::TableHeaderRight:
+ out() << "</tr>";
+ if (matchAhead(atom, Atom::TableHeaderLeft)) {
+ skipAhead = 1;
+ out() << "\n<tr valign=\"top\" class=\"qt-style\">";
+ }
+ else {
+ out() << "</thead>\n";
+ inTableHeader = false;
+ }
+ break;
+ case Atom::TableRowLeft:
+ if (++numTableRows % 2 == 1)
+ out() << "<tr valign=\"top\" class=\"odd\">";
+ else
+ out() << "<tr valign=\"top\" class=\"even\">";
+ break;
+ case Atom::TableRowRight:
+ out() << "</tr>\n";
+ break;
+ case Atom::TableItemLeft:
+ {
+ if (inTableHeader)
+ out() << "<th";
+ else
+ out() << "<td";
+
+ QStringList spans = atom->string().split(",");
+ if (spans.size() == 2) {
+ if (spans.at(0) != "1")
+ out() << " colspan=\"" << spans.at(0) << "\"";
+ if (spans.at(1) != "1")
+ out() << " rowspan=\"" << spans.at(1) << "\"";
+ out() << ">";
+ }
+ if (matchAhead(atom, Atom::ParaLeft))
+ skipAhead = 1;
+ }
+ break;
+ case Atom::TableItemRight:
+ if (inTableHeader)
+ out() << "</th>";
+ else
+ out() << "</td>";
+ if (matchAhead(atom, Atom::ParaLeft))
+ skipAhead = 1;
+ break;
+ case Atom::TableOfContents:
+ {
+ int numColumns = 1;
+ const Node *node = relative;
+
+ Doc::SectioningUnit sectioningUnit = Doc::Section4;
+ QStringList params = atom->string().split(",");
+ QString columnText = params.at(0);
+ QStringList pieces = columnText.split(" ", QString::SkipEmptyParts);
+ if (pieces.size() >= 2) {
+ columnText = pieces.at(0);
+ pieces.pop_front();
+ QString path = pieces.join(" ").trimmed();
+ node = findNodeForTarget(path, relative, marker, atom);
+ }
+
+ if (params.size() == 2) {
+ numColumns = qMax(columnText.toInt(), numColumns);
+ sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt();
+ }
+
+ if (node)
+ generateTableOfContents(node, marker, sectioningUnit, numColumns,
+ relative);
+ }
+ break;
+ case Atom::Target:
+ out() << "<a name=\"" << Doc::canonicalTitle(atom->string()) << "\"></a>";
+ break;
+ case Atom::UnhandledFormat:
+ out() << "<font color=\"red\"><b>&lt;Missing HTML&gt;</b></font>";
+ break;
+ case Atom::UnknownCommand:
+ out() << "<font color=\"red\"><b><code>\\" << protect(atom->string())
+ << "</code></b></font>";
+ break;
+#ifdef QDOC_QML
+ case Atom::QmlText:
+ case Atom::EndQmlText:
+ // don't do anything with these. They are just tags.
+ break;
+#endif
+ default:
+ unknownAtom(atom);
+ }
+ return skipAhead;
+}
+
+void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
+ CodeMarker *marker)
+{
+ QList<Section> sections;
+ QList<Section>::ConstIterator s;
+
+ const ClassNode *classe = 0;
+ const NamespaceNode *namespasse = 0;
+
+ QString title;
+ QString rawTitle;
+ QString fullTitle;
+ if (inner->type() == Node::Namespace) {
+ namespasse = static_cast<const NamespaceNode *>(inner);
+ rawTitle = marker->plainName(inner);
+ fullTitle = marker->plainFullName(inner);
+ title = rawTitle + " Namespace Reference";
+ }
+ else if (inner->type() == Node::Class) {
+ classe = static_cast<const ClassNode *>(inner);
+ rawTitle = marker->plainName(inner);
+ fullTitle = marker->plainFullName(inner);
+ title = rawTitle + " Class Reference";
+ }
+
+ DcfSection classSection;
+ classSection.title = title;
+ classSection.ref = linkForNode(inner, 0);
+ classSection.keywords += qMakePair(inner->name(), classSection.ref);
+
+ Text subtitleText;
+ if (rawTitle != fullTitle)
+ subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")"
+ << Atom(Atom::LineBreak);
+
+ QString fixedModule = inner->moduleName();
+ if (fixedModule == "Qt3SupportLight")
+ fixedModule = "Qt3Support";
+ if (!fixedModule.isEmpty())
+ subtitleText << "[" << Atom(Atom::AutoLink, fixedModule) << " module]";
+
+ if (fixedModule.isEmpty()) {
+ QMultiMap<QString, QString> publicGroups = tre->publicGroups();
+ QList<QString> groupNames = publicGroups.values(inner->name());
+ if (!groupNames.isEmpty()) {
+ qSort(groupNames.begin(), groupNames.end());
+ subtitleText << "[";
+ for (int j=0; j<groupNames.count(); j++) {
+ subtitleText << Atom(Atom::AutoLink, groupNames[j]);
+ if (j<groupNames.count()-1)
+ subtitleText <<", ";
+ }
+ subtitleText << "]";
+ }
+ }
+
+ generateHeader(title, inner, marker, true);
+ generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
+
+ generateBrief(inner, marker);
+ generateIncludes(inner, marker);
+ generateStatus(inner, marker);
+ if (classe) {
+ generateModuleWarning(classe, marker);
+ generateInherits(classe, marker);
+ generateInheritedBy(classe, marker);
+ }
+ generateThreadSafeness(inner, marker);
+ generateSince(inner, marker);
+
+ out() << "<ul>\n";
+
+ QString membersLink = generateListOfAllMemberFile(inner, marker);
+ if (!membersLink.isEmpty())
+ out() << "<li><a href=\"" << membersLink << "\">"
+ << "List of all members, including inherited members</a></li>\n";
+
+ QString obsoleteLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Obsolete);
+ if (!obsoleteLink.isEmpty())
+ out() << "<li><a href=\"" << obsoleteLink << "\">"
+ << "Obsolete members</a></li>\n";
+
+ QString compatLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Compat);
+ if (!compatLink.isEmpty())
+ out() << "<li><a href=\"" << compatLink << "\">"
+ << "Qt 3 support members</a></li>\n";
+
+ out() << "</ul>\n";
+
+ bool needOtherSection = false;
+
+ sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
+ s = sections.begin();
+ while (s != sections.end()) {
+ if (s->members.isEmpty()) {
+ if (!s->inherited.isEmpty())
+ needOtherSection = true;
+ } else {
+ out() << "<a name=\"" << registerRef((*s).name.toLower()) << "\"></a>\n";
+ out() << "<h3>" << protect((*s).name) << "</h3>\n";
+
+ generateSectionList(*s, inner, marker, CodeMarker::Summary);
+ }
+ ++s;
+ }
+
+ if (needOtherSection) {
+ out() << "<h3>Additional Inherited Members</h3>\n"
+ "<ul>\n";
+
+ s = sections.begin();
+ while (s != sections.end()) {
+ if (s->members.isEmpty() && !s->inherited.isEmpty())
+ generateSectionInheritedList(*s, inner, marker);
+ ++s;
+ }
+ out() << "</ul>\n";
+ }
+
+ out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
+
+ if (!inner->doc().isEmpty()) {
+ out() << "<hr />\n"
+ << "<h2>" << "Detailed Description" << "</h2>\n";
+ generateBody(inner, marker);
+ generateAlsoList(inner, marker);
+ }
+
+ sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
+ s = sections.begin();
+ while (s != sections.end()) {
+ out() << "<hr />\n";
+ out() << "<h2>" << protect((*s).name) << "</h2>\n";
+
+ NodeList::ConstIterator m = (*s).members.begin();
+ while (m != (*s).members.end()) {
+ if ((*m)->access() != Node::Private) { // ### check necessary?
+ if ((*m)->type() != Node::Class)
+ generateDetailedMember(*m, inner, marker);
+ else {
+ out() << "<h3> class ";
+ generateFullName(*m, inner, marker);
+ out() << "</h3>";
+ generateBrief(*m, marker, inner);
+ }
+
+ QStringList names;
+ names << (*m)->name();
+ if ((*m)->type() == Node::Function) {
+ const FunctionNode *func = reinterpret_cast<const FunctionNode *>(*m);
+ if (func->metaness() == FunctionNode::Ctor || func->metaness() == FunctionNode::Dtor
+ || func->overloadNumber() != 1)
+ names.clear();
+ } else if ((*m)->type() == Node::Property) {
+ const PropertyNode *prop = reinterpret_cast<const PropertyNode *>(*m);
+ if (!prop->getters().isEmpty() && !names.contains(prop->getters().first()->name()))
+ names << prop->getters().first()->name();
+ if (!prop->setters().isEmpty())
+ names << prop->setters().first()->name();
+ if (!prop->resetters().isEmpty())
+ names << prop->resetters().first()->name();
+ } else if ((*m)->type() == Node::Enum) {
+ const EnumNode *enume = reinterpret_cast<const EnumNode *>(*m);
+ if (enume->flagsType())
+ names << enume->flagsType()->name();
+
+ foreach (const QString &enumName,
+ enume->doc().enumItemNames().toSet()
+ - enume->doc().omitEnumItemNames().toSet())
+ names << plainCode(marker->markedUpEnumValue(enumName, enume));
+ }
+ foreach (const QString &name, names)
+ classSection.keywords += qMakePair(name, linkForNode(*m, 0));
+ }
+ ++m;
+ }
+ ++s;
+ }
+ generateFooter(inner);
+
+ if (!membersLink.isEmpty()) {
+ DcfSection membersSection;
+ membersSection.title = "List of all members";
+ membersSection.ref = membersLink;
+ appendDcfSubSection(&classSection, membersSection);
+ }
+ if (!obsoleteLink.isEmpty()) {
+ DcfSection obsoleteSection;
+ obsoleteSection.title = "Obsolete members";
+ obsoleteSection.ref = obsoleteLink;
+ appendDcfSubSection(&classSection, obsoleteSection);
+ }
+ if (!compatLink.isEmpty()) {
+ DcfSection compatSection;
+ compatSection.title = "Qt 3 support members";
+ compatSection.ref = compatLink;
+ appendDcfSubSection(&classSection, compatSection);
+ }
+
+ appendDcfSubSection(&dcfClassesRoot, classSection);
+}
+
+void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
+{
+ SubTitleSize subTitleSize = LargeSubTitle;
+ DcfSection fakeSection;
+ fakeSection.title = fake->fullTitle();
+ fakeSection.ref = linkForNode(fake, 0);
+
+ QList<Section> sections;
+ QList<Section>::const_iterator s;
+
+ QString htmlTitle = fake->fullTitle();
+ if (fake->subType() == FakeNode::File && !fake->subTitle().isEmpty()) {
+ subTitleSize = SmallSubTitle;
+ htmlTitle += " (" + fake->subTitle() + ")";
+ }
+
+ generateHeader(htmlTitle, fake, marker, true);
+ generateTitle(fake->fullTitle(), Text() << fake->subTitle(), subTitleSize,
+ fake, marker);
+
+ if (fake->subType() == FakeNode::Module) {
+ // Generate brief text and status for modules.
+ generateBrief(fake, marker);
+ generateStatus(fake, marker);
+
+ if (moduleNamespaceMap.contains(fake->name())) {
+ out() << "<h2>Namespaces</h2>\n";
+ generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]);
+ }
+ if (moduleClassMap.contains(fake->name())) {
+ out() << "<h2>Classes</h2>\n";
+ generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
+ }
+ }
+ else if (fake->subType() == FakeNode::HeaderFile) {
+ // Generate brief text and status for modules.
+ generateBrief(fake, marker);
+ generateStatus(fake, marker);
+
+ out() << "<ul>\n";
+
+ QString membersLink = generateListOfAllMemberFile(fake, marker);
+ if (!membersLink.isEmpty())
+ out() << "<li><a href=\"" << membersLink << "\">"
+ << "List of all members, including inherited members</a></li>\n";
+
+ QString obsoleteLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Obsolete);
+ if (!obsoleteLink.isEmpty())
+ out() << "<li><a href=\"" << obsoleteLink << "\">"
+ << "Obsolete members</a></li>\n";
+
+ QString compatLink = generateLowStatusMemberFile(fake, marker, CodeMarker::Compat);
+ if (!compatLink.isEmpty())
+ out() << "<li><a href=\"" << compatLink << "\">"
+ << "Qt 3 support members</a></li>\n";
+
+ out() << "</ul>\n";
+
+ if (!membersLink.isEmpty()) {
+ DcfSection membersSection;
+ membersSection.title = "List of all members";
+ membersSection.ref = membersLink;
+ appendDcfSubSection(&fakeSection, membersSection);
+ }
+ if (!obsoleteLink.isEmpty()) {
+ DcfSection obsoleteSection;
+ obsoleteSection.title = "Obsolete members";
+ obsoleteSection.ref = obsoleteLink;
+ appendDcfSubSection(&fakeSection, obsoleteSection);
+ }
+ if (!compatLink.isEmpty()) {
+ DcfSection compatSection;
+ compatSection.title = "Qt 3 support members";
+ compatSection.ref = compatLink;
+ appendDcfSubSection(&fakeSection, compatSection);
+ }
+ }
+
+ sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay);
+ s = sections.begin();
+ while (s != sections.end()) {
+ out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n";
+ out() << "<h3>" << protect((*s).name) << "</h3>\n";
+ generateSectionList(*s, fake, marker, CodeMarker::Summary);
+ ++s;
+ }
+
+ Text brief = fake->doc().briefText();
+ if (fake->subType() == FakeNode::Module && !brief.isEmpty()) {
+ out() << "<a name=\"" << registerRef("details") << "\"></a>\n";
+ out() << "<h2>" << "Detailed Description" << "</h2>\n";
+ }
+
+ generateBody(fake, marker);
+#ifdef QDOC_QML
+ if (fake->subType() == FakeNode::QmlClass) {
+ //qDebug() << "generateFakeNode(): QML CLASS" << fake->name();
+ const QmlNode* qmlNode = static_cast<const QmlNode*>(fake);
+ const ClassNode* cn = qmlNode->classNode();
+ if (cn) {
+ //qDebug() << " CPP CLASS" << cn->name();
+ generateQmlText(cn->doc().body(), cn, marker);
+ }
+ }
+#endif
+
+ generateAlsoList(fake, marker);
+
+ if (!fake->groupMembers().isEmpty()) {
+ QMap<QString, const Node *> groupMembersMap;
+ foreach (const Node *node, fake->groupMembers()) {
+ if (node->type() == Node::Class || node->type() == Node::Namespace)
+ groupMembersMap[node->name()] = node;
+ }
+ generateAnnotatedList(fake, marker, groupMembersMap);
+ }
+
+ fakeSection.keywords += qMakePair(fakeSection.title, fakeSection.ref);
+
+ sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay);
+ s = sections.begin();
+ while (s != sections.end()) {
+ out() << "<hr />\n";
+ out() << "<h2>" << protect((*s).name) << "</h2>\n";
+
+ NodeList::ConstIterator m = (*s).members.begin();
+ while (m != (*s).members.end()) {
+ generateDetailedMember(*m, fake, marker);
+ fakeSection.keywords += qMakePair((*m)->name(), linkForNode(*m, 0));
+ ++m;
+ }
+ ++s;
+ }
+ generateFooter(fake);
+
+ if (fake->subType() == FakeNode::Example) {
+ appendDcfSubSection(&dcfExamplesRoot, fakeSection);
+ }
+ else if (fake->subType() != FakeNode::File) {
+ QString contentsPage = fake->links().value(Node::ContentsLink).first;
+
+ if (contentsPage == "Qt Designer Manual") {
+ appendDcfSubSection(&dcfDesignerRoot, fakeSection);
+ }
+ else if (contentsPage == "Qt Linguist Manual") {
+ appendDcfSubSection(&dcfLinguistRoot, fakeSection);
+ }
+ else if (contentsPage == "Qt Assistant Manual") {
+ appendDcfSubSection(&dcfAssistantRoot, fakeSection);
+ }
+ else if (contentsPage == "qmake Manual") {
+ appendDcfSubSection(&dcfQmakeRoot, fakeSection);
+ }
+ else {
+ appendDcfSubSection(&dcfOverviewsRoot, fakeSection);
+ }
+ }
+}
+
+QString HtmlGenerator::fileExtension(const Node * /* node */)
+{
+ return "html";
+}
+
+void HtmlGenerator::generateHeader(const QString& title,
+ const Node *node,
+ CodeMarker *marker,
+ bool mainPage)
+{
+ out() << "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";
+
+ out() << "<!DOCTYPE html\n"
+ " PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
+
+ QString shortVersion;
+ if ((project != "Qtopia") && (project != "Qt Extended")) {
+ shortVersion = project + " " + shortVersion + ": ";
+ if (node && !node->doc().location().isEmpty())
+ out() << "<!-- " << node->doc().location().filePath() << " -->\n";
+
+ shortVersion = tre->version();
+ if (shortVersion.count(QChar('.')) == 2)
+ shortVersion.truncate(shortVersion.lastIndexOf(QChar('.')));
+ if (!shortVersion.isEmpty()) {
+ if (project == "QSA")
+ shortVersion = "QSA " + shortVersion + ": ";
+ else
+ shortVersion = "Qt " + shortVersion + ": ";
+ }
+ }
+
+ out() << "<head>\n"
+ " <title>" << shortVersion << protect(title) << "</title>\n";
+ if (!style.isEmpty())
+ out() << " <style type=\"text/css\">" << style << "</style>\n";
+
+ const QMap<QString, QString> &metaMap = node->doc().metaTagMap();
+ if (!metaMap.isEmpty()) {
+ QMapIterator<QString, QString> i(metaMap);
+ while (i.hasNext()) {
+ i.next();
+ out() << " <meta name=\"" << protect(i.key()) << "\" contents=\""
+ << protect(i.value()) << "\" />\n";
+ }
+ }
+
+ navigationLinks.clear();
+
+ if (node && !node->links().empty()) {
+ QPair<QString,QString> linkPair;
+ QPair<QString,QString> anchorPair;
+ const Node *linkNode;
+
+ if (node->links().contains(Node::PreviousLink)) {
+ linkPair = node->links()[Node::PreviousLink];
+ linkNode = findNodeForTarget(linkPair.first, node, marker);
+ if (!linkNode || linkNode == node)
+ anchorPair = linkPair;
+ else
+ anchorPair = anchorForNode(linkNode);
+
+ out() << " <link rel=\"prev\" href=\""
+ << anchorPair.first << "\" />\n";
+
+ navigationLinks += "[Previous: <a href=\"" + anchorPair.first + "\">";
+ if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
+ navigationLinks += protect(anchorPair.second);
+ else
+ navigationLinks += protect(linkPair.second);
+ navigationLinks += "</a>]\n";
+ }
+ if (node->links().contains(Node::ContentsLink)) {
+ linkPair = node->links()[Node::ContentsLink];
+ linkNode = findNodeForTarget(linkPair.first, node, marker);
+ if (!linkNode || linkNode == node)
+ anchorPair = linkPair;
+ else
+ anchorPair = anchorForNode(linkNode);
+
+ out() << " <link rel=\"contents\" href=\""
+ << anchorPair.first << "\" />\n";
+
+ navigationLinks += "[<a href=\"" + anchorPair.first + "\">";
+ if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
+ navigationLinks += protect(anchorPair.second);
+ else
+ navigationLinks += protect(linkPair.second);
+ navigationLinks += "</a>]\n";
+ }
+ if (node->links().contains(Node::NextLink)) {
+ linkPair = node->links()[Node::NextLink];
+ linkNode = findNodeForTarget(linkPair.first, node, marker);
+ if (!linkNode || linkNode == node)
+ anchorPair = linkPair;
+ else
+ anchorPair = anchorForNode(linkNode);
+
+ out() << " <link rel=\"next\" href=\""
+ << anchorPair.first << "\" />\n";
+
+ navigationLinks += "[Next: <a href=\"" + anchorPair.first + "\">";
+ if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
+ navigationLinks += protect(anchorPair.second);
+ else
+ navigationLinks += protect(linkPair.second);
+ navigationLinks += "</a>]\n";
+ }
+ if (node->links().contains(Node::IndexLink)) {
+ linkPair = node->links()[Node::IndexLink];
+ linkNode = findNodeForTarget(linkPair.first, node, marker);
+ if (!linkNode || linkNode == node)
+ anchorPair = linkPair;
+ else
+ anchorPair = anchorForNode(linkNode);
+ out() << " <link rel=\"index\" href=\""
+ << anchorPair.first << "\" />\n";
+ }
+ if (node->links().contains(Node::StartLink)) {
+ linkPair = node->links()[Node::StartLink];
+ linkNode = findNodeForTarget(linkPair.first, node, marker);
+ if (!linkNode || linkNode == node)
+ anchorPair = linkPair;
+ else
+ anchorPair = anchorForNode(linkNode);
+ out() << " <link rel=\"start\" href=\""
+ << anchorPair.first << "\" />\n";
+ }
+ }
+
+ foreach (const QString &stylesheet, stylesheets) {
+ out() << " <link href=\"" << stylesheet << "\" rel=\"stylesheet\" "
+ << "type=\"text/css\" />\n";
+ }
+
+ foreach (const QString &customHeadElement, customHeadElements) {
+ out() << " " << customHeadElement << "\n";
+ }
+
+ out() << "</head>\n"
+ "<body>\n";
+ if (mainPage)
+ generateMacRef(node, marker);
+ out() << QString(postHeader).replace("\\" + COMMAND_VERSION, tre->version());
+
+
+ if (node && !node->links().empty())
+ out() << "<p>\n" << navigationLinks << "</p>\n";
+}
+
+void HtmlGenerator::generateTitle(const QString& title,
+ const Text &subTitle,
+ SubTitleSize subTitleSize,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ out() << "<h1 class=\"title\">" << protect(title);
+ if (!subTitle.isEmpty()) {
+ out() << "<br />";
+ if (subTitleSize == SmallSubTitle)
+ out() << "<span class=\"small-subtitle\">";
+ else
+ out() << "<span class=\"subtitle\">";
+ generateText(subTitle, relative, marker);
+ out() << "</span>\n";
+ }
+ out() << "</h1>\n";
+}
+
+void HtmlGenerator::generateFooter(const Node *node)
+{
+ if (node && !node->links().empty())
+ out() << "<p>\n" << navigationLinks << "</p>\n";
+
+ out() << QString(footer).replace("\\" + COMMAND_VERSION, tre->version())
+ << QString(address).replace("\\" + COMMAND_VERSION, tre->version())
+ << "</body>\n"
+ "</html>\n";
+}
+
+void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker,
+ const Node *relative)
+{
+ Text brief = node->doc().briefText();
+ if (!brief.isEmpty()) {
+ out() << "<p>";
+ generateText(brief, node, marker);
+ if (!relative || node == relative)
+ out() << " <a href=\"#";
+ else
+ out() << " <a href=\"" << linkForNode(node, relative) << "#";
+ out() << registerRef("details") << "\">More...</a></p>\n";
+ }
+}
+
+void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker)
+{
+ if (!inner->includes().isEmpty()) {
+ out() << "<pre>" << trimmedTrailing(highlightedCode(indent(codeIndent,
+ marker->markedUpIncludes(
+ inner->includes())),
+ marker, inner))
+ << "</pre>";
+ }
+}
+
+void HtmlGenerator::generateTableOfContents(const Node *node, CodeMarker *marker,
+ Doc::SectioningUnit sectioningUnit,
+ int numColumns, const Node *relative)
+
+{
+ if (!node->doc().hasTableOfContents())
+ return;
+ QList<Atom *> toc = node->doc().tableOfContents();
+ if (toc.isEmpty())
+ return;
+
+ QString nodeName = "";
+ if (node != relative)
+ nodeName = node->name();
+
+ QStringList sectionNumber;
+ int columnSize = 0;
+
+ QString tdTag;
+ if (numColumns > 1) {
+ tdTag = "<td width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";
+ out() << "<p><table width=\"100%\">\n<tr valign=\"top\">" << tdTag << "\n";
+ }
+
+ // disable nested links in table of contents
+ inContents = true;
+ inLink = true;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ Atom *atom = toc.at(i);
+
+ int nextLevel = atom->string().toInt();
+ if (nextLevel > (int)sectioningUnit)
+ continue;
+
+ if (sectionNumber.size() < nextLevel) {
+ do {
+ out() << "<ul>";
+ sectionNumber.append("1");
+ } while (sectionNumber.size() < nextLevel);
+ } else {
+ while (sectionNumber.size() > nextLevel) {
+ out() << "</ul>\n";
+ sectionNumber.removeLast();
+ }
+ sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
+ }
+ int numAtoms;
+ Text headingText = Text::sectionHeading(atom);
+
+ if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) {
+ out() << "</ul></td>" << tdTag << "<ul>\n";
+ columnSize = 0;
+ }
+ out() << "<li>";
+ out() << "<a href=\"" << nodeName << "#" << Doc::canonicalTitle(headingText.toString())
+ << "\">";
+ generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
+ out() << "</a></li>\n";
+
+ ++columnSize;
+ }
+ while (!sectionNumber.isEmpty()) {
+ out() << "</ul>\n";
+ sectionNumber.removeLast();
+ }
+
+ if (numColumns > 1)
+ out() << "</td></tr></table></p>\n";
+
+ inContents = false;
+ inLink = false;
+}
+
+#if 0
+void HtmlGenerator::generateNavigationBar(const NavigationBar& bar,
+ const Node *node,
+ CodeMarker *marker)
+{
+ if (bar.prev.begin() != 0 || bar.current.begin() != 0 ||
+ bar.next.begin() != 0) {
+ out() << "<p align=\"right\">";
+ if (bar.prev.begin() != 0) {
+#if 0
+ out() << "[<a href=\"" << section.previousBaseName()
+ << ".html\">Prev: ";
+ generateText(section.previousHeading(), node, marker);
+ out() << "</a>]\n";
+#endif
+ }
+ if (bar.current.begin() != 0) {
+ out() << "[<a href=\"" << "home"
+ << ".html\">Home</a>]\n";
+ }
+ if (bar.next.begin() != 0) {
+ out() << "[<a href=\"" << fileBase(node, bar.next)
+ << ".html\">Next: ";
+ generateText(Text::sectionHeading(bar.next.begin()), node, marker);
+ out() << "</a>]\n";
+ }
+ out() << "</p>\n";
+ }
+}
+#endif
+
+QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker)
+{
+ QList<Section> sections;
+ QList<Section>::ConstIterator s;
+
+ sections = marker->sections(inner, CodeMarker::SeparateList, CodeMarker::Okay);
+ if (sections.isEmpty())
+ return QString();
+
+ QString fileName = fileBase(inner) + "-members." + fileExtension(inner);
+ beginSubPage(inner->location(), fileName);
+ QString title = "List of All Members for " + inner->name();
+ generateHeader(title, inner, marker, false);
+ generateTitle(title, Text(), SmallSubTitle, inner, marker);
+ out() << "<p>This is the complete list of members for ";
+ generateFullName(inner, 0, marker);
+ out() << ", including inherited members.</p>\n";
+
+ Section section = sections.first();
+ generateSectionList(section, 0, marker, CodeMarker::SeparateList);
+
+ generateFooter();
+ endSubPage();
+ return fileName;
+}
+
+QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeMarker *marker,
+ CodeMarker::Status status)
+{
+ QList<Section> sections = marker->sections(inner, CodeMarker::Summary, status);
+ QMutableListIterator<Section> j(sections);
+ while (j.hasNext()) {
+ if (j.next().members.size() == 0)
+ j.remove();
+ }
+ if (sections.isEmpty())
+ return QString();
+
+ int i;
+
+ QString title;
+ QString fileName;
+
+ if (status == CodeMarker::Compat) {
+ title = "Qt 3 Support Members for " + inner->name();
+ fileName = fileBase(inner) + "-qt3." + fileExtension(inner);
+ } else {
+ title = "Obsolete Members for " + inner->name();
+ fileName = fileBase(inner) + "-obsolete." + fileExtension(inner);
+ }
+
+ beginSubPage(inner->location(), fileName);
+ generateHeader(title, inner, marker, false);
+ generateTitle(title, Text(), SmallSubTitle, inner, marker);
+
+ if (status == CodeMarker::Compat) {
+ out() << "<p><b>The following class members are part of the "
+ "<a href=\"qt3support.html\">Qt 3 support layer</a>.</b> "
+ "They are provided to help you port old code to Qt 4. We advise against "
+ "using them in new code.</p>\n";
+ } else {
+ out() << "<p><b>The following class members are obsolete.</b> They are provided to keep "
+ "old source code working. We strongly advise against using them in new "
+ "code.</p>\n";
+ }
+
+ out() << "<p><ul><li><a href=\"" << linkForNode(inner, 0) << "\">" << protect(inner->name())
+ << " class reference</a></li></ul></p>\n";
+
+ for (i = 0; i < sections.size(); ++i) {
+ out() << "<h3>" << protect(sections.at(i).name) << "</h3>\n";
+
+ generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary);
+ }
+
+ sections = marker->sections(inner, CodeMarker::Detailed, status);
+ for (i = 0; i < sections.size(); ++i) {
+ out() << "<hr />\n";
+ out() << "<h2>" << protect(sections.at(i).name) << "</h2>\n";
+
+ NodeList::ConstIterator m = sections.at(i).members.begin();
+ while (m != sections.at(i).members.end()) {
+ if ((*m)->access() != Node::Private)
+ generateDetailedMember(*m, inner, marker);
+ ++m;
+ }
+ }
+
+ generateFooter();
+ endSubPage();
+ return fileName;
+}
+
+void HtmlGenerator::generateClassHierarchy(const Node *relative, CodeMarker *marker,
+ const QMap<QString, const Node *> &classMap)
+{
+ if (classMap.isEmpty())
+ return;
+
+ QMap<QString, const Node *> topLevel;
+ QMap<QString, const Node *>::ConstIterator c = classMap.begin();
+ while (c != classMap.end()) {
+ const ClassNode *classe = static_cast<const ClassNode *>(*c);
+ if (classe->baseClasses().isEmpty())
+ topLevel.insert(classe->name(), classe);
+ ++c;
+ }
+
+ QStack<QMap<QString, const Node *> > stack;
+ stack.push(topLevel);
+
+ out() << "<ul>\n";
+ while (!stack.isEmpty()) {
+ if (stack.top().isEmpty()) {
+ stack.pop();
+ out() << "</ul>\n";
+ } else {
+ const ClassNode *child = static_cast<const ClassNode *>(*stack.top().begin());
+ out() << "<li>";
+ generateFullName(child, relative, marker);
+ out() << "</li>\n";
+ stack.top().erase(stack.top().begin());
+
+ QMap<QString, const Node *> newTop;
+ foreach (const RelatedClass &d, child->derivedClasses()) {
+ if (d.access != Node::Private)
+ newTop.insert(d.node->name(), d.node);
+ }
+ if (!newTop.isEmpty()) {
+ stack.push(newTop);
+ out() << "<ul>\n";
+ }
+ }
+ }
+}
+
+void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker,
+ const QMap<QString, const Node *> &nodeMap)
+{
+ out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
+
+ int row = 0;
+ foreach (const QString &name, nodeMap.keys()) {
+ const Node *node = nodeMap[name];
+
+ if (++row % 2 == 1)
+ out() << "<tr valign=\"top\" class=\"odd\">";
+ else
+ out() << "<tr valign=\"top\" class=\"even\">";
+ out() << "<th>";
+ generateFullName(node, relative, marker);
+ out() << "</th>";
+
+ if (!(node->type() == Node::Fake)) {
+ Text brief = node->doc().trimmedBriefText(name);
+ if (!brief.isEmpty()) {
+ out() << "<td>";
+ generateText(brief, node, marker);
+ out() << "</td>";
+ }
+ } else {
+ out() << "<td>";
+ out() << protect(node->doc().briefText().toString());
+ out() << "</td>";
+ }
+ out() << "</tr>\n";
+ }
+ out() << "</table></p>\n";
+}
+
+void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker,
+ const QMap<QString, const Node *> &classMap)
+{
+ const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_'
+ const int NumColumns = 4; // number of columns in the result
+
+ if (classMap.isEmpty())
+ return;
+
+ /*
+ First, find out the common prefix of all non-namespaced classes.
+ For Qt, the prefix is Q. It can easily be derived from the first
+ and last classes in alphabetical order (QAccel and QXtWidget in Qt 2.1).
+ */
+ int commonPrefixLen = 0;
+ QString commonPrefix;
+ QString first;
+ QString last;
+
+ QMap<QString, const Node *>::const_iterator iter = classMap.begin();
+ while (iter != classMap.end()) {
+ if (!iter.key().contains("::")) {
+ first = iter.key();
+ break;
+ }
+ ++iter;
+ }
+
+ if (first.isEmpty())
+ first = classMap.begin().key();
+
+ iter = classMap.end();
+ while (iter != classMap.begin()) {
+ --iter;
+ if (!iter.key().contains("::")) {
+ last = iter.key();
+ break;
+ }
+ }
+
+ if (last.isEmpty())
+ last = classMap.begin().key();
+
+ if (classMap.size() > 1) {
+ while (commonPrefixLen < first.length() + 1 && commonPrefixLen < last.length() + 1
+ && first[commonPrefixLen] == last[commonPrefixLen])
+ ++commonPrefixLen;
+ }
+
+ commonPrefix = first.left(commonPrefixLen);
+
+ /*
+ Divide the data into 37 paragraphs: 0, ..., 9, A, ..., Z,
+ underscore (_). QAccel will fall in paragraph 10 (A) and
+ QXtWidget in paragraph 33 (X). This is the only place where we
+ assume that NumParagraphs is 37. Each paragraph is a
+ QMap<QString, const Node *>.
+ */
+ QMap<QString, const Node *> paragraph[NumParagraphs];
+ QString paragraphName[NumParagraphs];
+
+ QMap<QString, const Node *>::ConstIterator c = classMap.begin();
+ while (c != classMap.end()) {
+ QStringList pieces = c.key().split("::");
+ QString key;
+ if (pieces.size() == 1)
+ key = pieces.last().mid(commonPrefixLen).toLower();
+ else
+ key = pieces.last().toLower();
+
+ int paragraphNo = NumParagraphs - 1;
+
+ if (key[0].digitValue() != -1) {
+ paragraphNo = key[0].digitValue();
+ } else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
+ paragraphNo = 10 + key[0].unicode() - 'a';
+ }
+
+ paragraphName[paragraphNo] = key[0].toUpper();
+ paragraph[paragraphNo].insert(key, c.value());
+ ++c;
+ }
+
+ /*
+ Each paragraph j has a size: paragraph[j].count(). In the
+ discussion, we will assume paragraphs 0 to 5 will have sizes
+ 3, 1, 4, 1, 5, 9.
+
+ We now want to compute the paragraph offset. Paragraphs 0 to 6
+ start at offsets 0, 3, 4, 8, 9, 14, 23.
+ */
+ int paragraphOffset[NumParagraphs + 1];
+ int i, j, k;
+
+ paragraphOffset[0] = 0;
+ for (j = 0; j < NumParagraphs; j++)
+ paragraphOffset[j + 1] = paragraphOffset[j] + paragraph[j].count();
+
+ int firstOffset[NumColumns + 1];
+ int currentOffset[NumColumns];
+ int currentParagraphNo[NumColumns];
+ int currentOffsetInParagraph[NumColumns];
+
+ int numRows = (classMap.count() + NumColumns - 1) / NumColumns;
+ int curParagNo = 0;
+
+ for (i = 0; i < NumColumns; i++) {
+ firstOffset[i] = qMin(i * numRows, classMap.size());
+ currentOffset[i] = firstOffset[i];
+
+ for (j = curParagNo; j < NumParagraphs; j++) {
+ if (paragraphOffset[j] > firstOffset[i])
+ break;
+ if (paragraphOffset[j] <= firstOffset[i])
+ curParagNo = j;
+ }
+ currentParagraphNo[i] = curParagNo;
+ currentOffsetInParagraph[i] = firstOffset[i] -
+ paragraphOffset[curParagNo];
+ }
+ firstOffset[NumColumns] = classMap.count();
+
+ out() << "<p><table width=\"100%\">\n";
+ for (k = 0; k < numRows; k++) {
+ out() << "<tr>\n";
+ for (i = 0; i < NumColumns; i++) {
+ if (currentOffset[i] >= firstOffset[i + 1]) {
+ // this column is finished
+ out() << "<td>\n</td>\n";
+ } else {
+ while (currentOffsetInParagraph[i] == paragraph[currentParagraphNo[i]].count()) {
+ ++currentParagraphNo[i];
+ currentOffsetInParagraph[i] = 0;
+ }
+
+ out() << "<td align=\"right\">";
+ if (currentOffsetInParagraph[i] == 0) {
+ // start a new paragraph
+ out() << "<b>" << paragraphName[currentParagraphNo[i]] << "&nbsp;</b>";
+ }
+ out() << "</td>\n";
+
+ // bad loop
+ QMap<QString, const Node *>::Iterator it;
+ it = paragraph[currentParagraphNo[i]].begin();
+ for (j = 0; j < currentOffsetInParagraph[i]; j++)
+ ++it;
+
+ out() << "<td>";
+ // Previously, we used generateFullName() for this, but we
+ // require some special formatting.
+ out() << "<a href=\"" << linkForNode(it.value(), relative) << "\">";
+ QStringList pieces = fullName(it.value(), relative, marker).split("::");
+ out() << protect(pieces.last());
+ out() << "</a>";
+ if (pieces.size() > 1) {
+ out() << " (";
+ generateFullName(it.value()->parent(), relative, marker);
+ out() << ")";
+ }
+ out() << "</td>\n";
+
+ currentOffset[i]++;
+ currentOffsetInParagraph[i]++;
+ }
+ }
+ out() << "</tr>\n";
+ }
+ out() << "</table></p>\n";
+}
+
+void HtmlGenerator::generateFunctionIndex(const Node *relative, CodeMarker *marker)
+{
+ out() << "<p align=\"center\"><font size=\"+1\"><b>";
+ for (int i = 0; i < 26; i++) {
+ QChar ch('a' + i);
+ out() << QString("<a href=\"#%1\">%2</a>&nbsp;").arg(ch).arg(ch.toUpper());
+ }
+ out() << "</b></font></p>\n";
+
+ char nextLetter = 'a';
+ char currentLetter;
+
+#if 1
+ out() << "<ul>\n";
+#endif
+ QMap<QString, QMap<QString, const Node *> >::ConstIterator f = funcIndex.begin();
+ while (f != funcIndex.end()) {
+#if 1
+ out() << "<li>";
+#else
+ out() << "<p>";
+#endif
+ out() << protect(f.key()) << ":";
+
+ currentLetter = f.key()[0].unicode();
+ while (islower(currentLetter) && currentLetter >= nextLetter) {
+ out() << QString("<a name=\"%1\"></a>").arg(nextLetter);
+ nextLetter++;
+ }
+
+ QMap<QString, const Node *>::ConstIterator s = (*f).begin();
+ while (s != (*f).end()) {
+ out() << " ";
+ generateFullName((*s)->parent(), relative, marker, *s);
+ ++s;
+ }
+#if 1
+ out() << "</li>";
+#else
+ out() << "</p>";
+#endif
+ out() << "\n";
+ ++f;
+ }
+#if 1
+ out() << "</ul>\n";
+#endif
+}
+
+void HtmlGenerator::generateLegaleseList(const Node *relative, CodeMarker *marker)
+{
+ QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin();
+ while (it != legaleseTexts.end()) {
+ Text text = it.key();
+ out() << "<hr />\n";
+ generateText(text, relative, marker);
+ out() << "<ul>\n";
+ do {
+ out() << "<li>";
+ generateFullName(it.value(), relative, marker);
+ out() << "</li>\n";
+ ++it;
+ } while (it != legaleseTexts.end() && it.key() == text);
+ out() << "</ul>\n";
+ }
+}
+
+void HtmlGenerator::generateSynopsis(const Node *node, const Node *relative,
+ CodeMarker *marker, CodeMarker::SynopsisStyle style)
+{
+ QString marked = marker->markedUpSynopsis(node, relative, style);
+ QRegExp templateTag("(<[^@>]*>)");
+ if (marked.indexOf(templateTag) != -1) {
+ QString contents = protect(marked.mid(templateTag.pos(1),
+ templateTag.cap(1).length()));
+ marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
+ contents);
+ }
+ marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"), "<i>\\1<sub>\\2</sub></i>");
+ marked.replace("<@param>", "<i>");
+ marked.replace("</@param>", "</i>");
+
+ if (style == CodeMarker::Summary)
+ marked.replace("@name>", "b>");
+
+ if (style == CodeMarker::SeparateList) {
+ QRegExp extraRegExp("<@extra>.*</@extra>");
+ extraRegExp.setMinimal(true);
+ marked.replace(extraRegExp, "");
+ } else {
+ marked.replace("<@extra>", "&nbsp;&nbsp;<tt>");
+ marked.replace("</@extra>", "</tt>");
+ }
+
+ if (style != CodeMarker::Detailed) {
+ marked.replace("<@type>", "");
+ marked.replace("</@type>", "");
+ }
+ out() << highlightedCode(marked, marker, relative);
+}
+
+void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */)
+{
+ QMap<const FakeNode *, QMap<QString, FakeNode *> > fakeNodeMap;
+ QMap<QString, const FakeNode *> groupTitlesMap;
+ QMap<QString, FakeNode *> uncategorizedNodeMap;
+ QRegExp singleDigit("\\b([0-9])\\b");
+
+ const NodeList children = tre->root()->childNodes();
+ foreach (Node *child, children) {
+ if (child->type() == Node::Fake && child != relative) {
+ FakeNode *fakeNode = static_cast<FakeNode *>(child);
+
+ // Check whether the page is part of a group or is the group
+ // definition page.
+ QString group;
+ bool isGroupPage = false;
+ if (fakeNode->doc().metaCommandsUsed().contains("group")) {
+ group = fakeNode->doc().metaCommandArgs("group")[0];
+ isGroupPage = true;
+ }
+
+ // there are too many examples; they would clutter the list
+ if (fakeNode->subType() == FakeNode::Example)
+ continue;
+
+ // not interested either in individual (Qt Designer etc.) manual chapters
+ if (fakeNode->links().contains(Node::ContentsLink))
+ continue;
+
+ // Discard external nodes.
+ if (fakeNode->subType() == FakeNode::ExternalPage)
+ continue;
+
+ QString sortKey = fakeNode->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+
+ if (!group.isEmpty()) {
+ if (isGroupPage) {
+ // If we encounter a group definition page, we add all
+ // the pages in that group to the list for that group.
+ foreach (Node *member, fakeNode->groupMembers()) {
+ if (member->type() != Node::Fake)
+ continue;
+ FakeNode *page = static_cast<FakeNode *>(member);
+ if (page) {
+ QString sortKey = page->fullTitle().toLower();
+ if (sortKey.startsWith("the "))
+ sortKey.remove(0, 4);
+ sortKey.replace(singleDigit, "0\\1");
+ fakeNodeMap[const_cast<const FakeNode *>(fakeNode)].insert(sortKey, page);
+ groupTitlesMap[fakeNode->fullTitle()] = const_cast<const FakeNode *>(fakeNode);
+ }
+ }
+ } else if (!isGroupPage) {
+ // If we encounter a page that belongs to a group then
+ // we add that page to the list for that group.
+ const FakeNode *groupNode = static_cast<const FakeNode *>(tre->root()->findNode(group, Node::Fake));
+ if (groupNode)
+ fakeNodeMap[groupNode].insert(sortKey, fakeNode);
+ //else
+ // uncategorizedNodeMap.insert(sortKey, fakeNode);
+ }// else
+ // uncategorizedNodeMap.insert(sortKey, fakeNode);
+ }// else
+ // uncategorizedNodeMap.insert(sortKey, fakeNode);
+ }
+ }
+
+ // We now list all the pages found that belong to groups.
+ // If only certain pages were found for a group, but the definition page
+ // for that group wasn't listed, the list of pages will be intentionally
+ // incomplete. However, if the group definition page was listed, all the
+ // pages in that group are listed for completeness.
+
+ if (!fakeNodeMap.isEmpty()) {
+ foreach (const QString &groupTitle, groupTitlesMap.keys()) {
+ const FakeNode *groupNode = groupTitlesMap[groupTitle];
+ out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg(
+ linkForNode(groupNode, relative)).arg(
+ protect(groupNode->fullTitle()));
+
+ if (fakeNodeMap[groupNode].count() == 0)
+ continue;
+
+ out() << "<ul>\n";
+
+ foreach (const FakeNode *fakeNode, fakeNodeMap[groupNode]) {
+ QString title = fakeNode->fullTitle();
+ if (title.startsWith("The "))
+ title.remove(0, 4);
+ out() << "<li><a href=\"" << linkForNode(fakeNode, relative) << "\">"
+ << protect(title) << "</a></li>\n";
+ }
+ out() << "</ul>\n";
+ }
+ }
+
+ if (!uncategorizedNodeMap.isEmpty()) {
+ out() << QString("<h3>Miscellaneous</h3>\n");
+ out() << "<ul>\n";
+ foreach (const FakeNode *fakeNode, uncategorizedNodeMap) {
+ QString title = fakeNode->fullTitle();
+ if (title.startsWith("The "))
+ title.remove(0, 4);
+ out() << "<li><a href=\"" << linkForNode(fakeNode, relative) << "\">"
+ << protect(title) << "</a></li>\n";
+ }
+ out() << "</ul>\n";
+ }
+}
+
+void HtmlGenerator::generateSectionList(const Section& section, const Node *relative,
+ CodeMarker *marker, CodeMarker::SynopsisStyle style)
+{
+ if (!section.members.isEmpty()) {
+ bool twoColumn = false;
+ if (style == CodeMarker::SeparateList) {
+ twoColumn = (section.members.count() >= 16);
+ } else if (section.members.first()->type() == Node::Property) {
+ twoColumn = (section.members.count() >= 5);
+ }
+ if (twoColumn)
+ out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\""
+ " cellspacing=\"0\">\n"
+ << "<tr><td width=\"45%\" valign=\"top\">";
+ out() << "<ul>\n";
+
+ int i = 0;
+ NodeList::ConstIterator m = section.members.begin();
+ while (m != section.members.end()) {
+ if ((*m)->access() == Node::Private) {
+ ++m;
+ continue;
+ }
+
+ if (twoColumn && i == (int) (section.members.count() + 1) / 2)
+ out() << "</ul></td><td valign=\"top\"><ul>\n";
+
+ out() << "<li><div class=\"fn\"></div>";
+ if (style == CodeMarker::Accessors)
+ out() << "<b>";
+ generateSynopsis(*m, relative, marker, style);
+ if (style == CodeMarker::Accessors)
+ out() << "</b>";
+ out() << "</li>\n";
+ i++;
+ ++m;
+ }
+ out() << "</ul>\n";
+ if (twoColumn)
+ out() << "</td></tr>\n</table></p>\n";
+ }
+
+ if (style == CodeMarker::Summary && !section.inherited.isEmpty()) {
+ out() << "<ul>\n";
+ generateSectionInheritedList(section, relative, marker);
+ out() << "</ul>\n";
+ }
+}
+
+void HtmlGenerator::generateSectionInheritedList(const Section& section, const Node *relative,
+ CodeMarker *marker)
+{
+ QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin();
+ while (p != section.inherited.end()) {
+ out() << "<li><div class=\"fn\"></div>";
+ out() << (*p).second << " ";
+ if ((*p).second == 1) {
+ out() << section.singularMember;
+ } else {
+ out() << section.pluralMember;
+ }
+ out() << " inherited from <a href=\"" << fileName((*p).first)
+ << "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">"
+ << protect(marker->plainFullName((*p).first, relative))
+ << "</a></li>\n";
+ ++p;
+ }
+}
+
+void HtmlGenerator::generateLink(const Atom *atom, const Node * /* relative */, CodeMarker *marker)
+{
+ static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_");
+
+ if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) {
+ // hack for C++: move () outside of link
+ int k = funcLeftParen.pos(1);
+ out() << protect(atom->string().left(k));
+ if (link.isEmpty()) {
+ if (showBrokenLinks)
+ out() << "</i>";
+ } else {
+ out() << "</a>";
+ }
+ inLink = false;
+ out() << protect(atom->string().mid(k));
+ } else if (marker->recognizeLanguage("Java")) {
+ // hack for Java: remove () and use <tt> when appropriate
+ bool func = atom->string().endsWith("()");
+ bool tt = (func || atom->string().contains(camelCase));
+ if (tt)
+ out() << "<tt>";
+ if (func) {
+ out() << protect(atom->string().left(atom->string().length() - 2));
+ } else {
+ out() << protect(atom->string());
+ }
+ out() << "</tt>";
+ } else {
+ out() << protect(atom->string());
+ }
+}
+
+QString HtmlGenerator::cleanRef(const QString& ref)
+{
+ QString clean;
+
+ if (ref.isEmpty())
+ return clean;
+
+ clean.reserve(ref.size() + 20);
+ const QChar c = ref[0];
+ const uint u = c.unicode();
+
+ if ((u >= 'a' && u <= 'z') ||
+ (u >= 'A' && u <= 'Z') ||
+ (u >= '0' && u <= '9')) {
+ clean += c;
+ } else if (u == '~') {
+ clean += "dtor.";
+ } else if (u == '_') {
+ clean += "underscore.";
+ } else {
+ clean += "A";
+ }
+
+ for (int i = 1; i < (int) ref.length(); i++) {
+ const QChar c = ref[i];
+ const uint u = c.unicode();
+ if ((u >= 'a' && u <= 'z') ||
+ (u >= 'A' && u <= 'Z') ||
+ (u >= '0' && u <= '9') || u == '-' ||
+ u == '_' || u == ':' || u == '.') {
+ clean += c;
+ } else if (c.isSpace()) {
+ clean += "-";
+ } else if (u == '!') {
+ clean += "-not";
+ } else if (u == '&') {
+ clean += "-and";
+ } else if (u == '<') {
+ clean += "-lt";
+ } else if (u == '=') {
+ clean += "-eq";
+ } else if (u == '>') {
+ clean += "-gt";
+ } else if (u == '#') {
+ clean += "#";
+ } else {
+ clean += "-";
+ clean += QString::number((int)u, 16);
+ }
+ }
+ return clean;
+}
+
+QString HtmlGenerator::registerRef(const QString& ref)
+{
+ QString clean = HtmlGenerator::cleanRef(ref);
+
+ for (;;) {
+ QString& prevRef = refMap[clean.toLower()];
+ if (prevRef.isEmpty()) {
+ prevRef = ref;
+ break;
+ } else if (prevRef == ref) {
+ break;
+ }
+ clean += "x";
+ }
+ return clean;
+}
+
+QString HtmlGenerator::protect(const QString& string)
+{
+#define APPEND(x) \
+ if (html.isEmpty()) { \
+ html = string; \
+ html.truncate(i); \
+ } \
+ html += (x);
+
+ QString html;
+ int n = string.length();
+
+ for (int i = 0; i < n; ++i) {
+ QChar ch = string.at(i);
+
+ if (ch == QLatin1Char('&')) {
+ APPEND("&amp;");
+ } else if (ch == QLatin1Char('<')) {
+ APPEND("&lt;");
+ } else if (ch == QLatin1Char('>')) {
+ APPEND("&gt;");
+ } else if (ch == QLatin1Char('"')) {
+ APPEND("&quot;");
+ } else if (ch.unicode() > 0x007F
+ || (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/'))
+ || (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) {
+ // we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator
+ APPEND("&#x");
+ html += QString::number(ch.unicode(), 16);
+ html += QLatin1Char(';');
+ } else {
+ if (!html.isEmpty())
+ html += ch;
+ }
+ }
+
+ if (!html.isEmpty())
+ return html;
+ return string;
+
+#undef APPEND
+}
+
+static QRegExp linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
+static QRegExp funcTag("(<@func target=\"([^\"]*)\">)(.*)(</@func>)");
+static QRegExp typeTag("(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)");
+static QRegExp spanTag("</@(?:comment|preprocessor|string|char)>");
+static QRegExp unknownTag("</?@[^>]*>");
+
+bool parseArg(const QString &src,
+ const QString &tag,
+ int *pos,
+ int n,
+ QStringRef *contents,
+ QStringRef *par1 = 0,
+ bool debug = false)
+{
+#define SKIP_CHAR(c) \
+ if (debug) \
+ qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
+ if (i >= n || src[i] != c) { \
+ if (debug) \
+ qDebug() << " char '" << c << "' not found"; \
+ return false; \
+ } \
+ ++i;
+
+
+#define SKIP_SPACE \
+ while (i < n && src[i] == ' ') \
+ ++i;
+
+ int i = *pos;
+ int j = i;
+
+ // assume "<@" has been parsed outside
+ //SKIP_CHAR('<');
+ //SKIP_CHAR('@');
+
+ if (tag != QStringRef(&src, i, tag.length())) {
+ if (0 && debug)
+ qDebug() << "tag " << tag << " not found at " << i;
+ return false;
+ }
+
+ if (debug)
+ qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
+
+ // skip tag
+ i += tag.length();
+
+ // parse stuff like: linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
+ if (par1) {
+ SKIP_SPACE;
+ // read parameter name
+ j = i;
+ while (i < n && src[i].isLetter())
+ ++i;
+ if (src[i] == '=') {
+ if (debug)
+ qDebug() << "read parameter" << QString(src.data() + j, i - j);
+ SKIP_CHAR('=');
+ SKIP_CHAR('"');
+ // skip parameter name
+ j = i;
+ while (i < n && src[i] != '"')
+ ++i;
+ *par1 = QStringRef(&src, j, i - j);
+ SKIP_CHAR('"');
+ SKIP_SPACE;
+ } else {
+ if (debug)
+ qDebug() << "no optional parameter found";
+ }
+ }
+ SKIP_SPACE;
+ SKIP_CHAR('>');
+
+ // find contents up to closing "</@tag>
+ j = i;
+ for (; true; ++i) {
+ if (i + 4 + tag.length() > n)
+ return false;
+ if (src[i] != '<')
+ continue;
+ if (src[i + 1] != '/')
+ continue;
+ if (src[i + 2] != '@')
+ continue;
+ if (tag != QStringRef(&src, i + 3, tag.length()))
+ continue;
+ if (src[i + 3 + tag.length()] != '>')
+ continue;
+ break;
+ }
+
+ *contents = QStringRef(&src, j, i - j);
+
+ i += tag.length() + 4;
+
+ *pos = i;
+ if (debug)
+ qDebug() << " tag " << tag << " found: pos now: " << i;
+ return true;
+#undef SKIP_CHAR
+}
+
+static void addLink(const QString &linkTarget,
+ const QStringRef &nestedStuff,
+ QString *res)
+{
+ if (!linkTarget.isEmpty()) {
+ *res += "<a href=\"";
+ *res += linkTarget;
+ *res += "\">";
+ *res += nestedStuff;
+ *res += "</a>";
+ }
+ else {
+ *res += nestedStuff;
+ }
+}
+
+QString HtmlGenerator::highlightedCode(const QString& markedCode,
+ CodeMarker *marker,
+ const Node *relative)
+{
+ QString src = markedCode;
+ QString html;
+ QStringRef arg;
+ QStringRef par1;
+
+ const QChar charLangle = '<';
+ const QChar charAt = '@';
+
+ // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
+ static const QString linkTag("link");
+ for (int i = 0, n = src.size(); i < n;) {
+ if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
+ i += 2;
+ if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
+ QString link = linkForNode(
+ CodeMarker::nodeForString(par1.toString()), relative);
+ addLink(link, arg, &html);
+ }
+ else {
+ html += charLangle;
+ html += charAt;
+ }
+ }
+ else {
+ html += src.at(i++);
+ }
+ }
+
+
+ if (slow) {
+ // is this block ever used at all?
+ // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)"
+ src = html;
+ html = QString();
+ static const QString funcTag("func");
+ for (int i = 0, n = src.size(); i < n;) {
+ if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
+ i += 2;
+ if (parseArg(src, funcTag, &i, n, &arg, &par1)) {
+ QString link = linkForNode(
+ marker->resolveTarget(par1.toString(),
+ tre,
+ relative),
+ relative);
+ addLink(link, arg, &html);
+ par1 = QStringRef();
+ }
+ else {
+ html += charLangle;
+ html += charAt;
+ }
+ }
+ else {
+ html += src.at(i++);
+ }
+ }
+ }
+
+ // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
+ src = html;
+ html = QString();
+ static const QString typeTags[] = { "type", "headerfile", "func" };
+ for (int i = 0, n = src.size(); i < n;) {
+ if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
+ i += 2;
+ bool handled = false;
+ for (int k = 0; k != 3; ++k) {
+ if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) {
+ par1 = QStringRef();
+ QString link = linkForNode(
+ marker->resolveTarget(arg.toString(), tre, relative),
+ relative);
+ addLink(link, arg, &html);
+ handled = true;
+ break;
+ }
+ }
+ if (!handled) {
+ html += charLangle;
+ html += charAt;
+ }
+ }
+ else {
+ html += src.at(i++);
+ }
+ }
+
+ // replace all
+ // "<@comment>" -> "<span class=\"comment\">";
+ // "<@preprocessor>" -> "<span class=\"preprocessor\">";
+ // "<@string>" -> "<span class=\"string\">";
+ // "<@char>" -> "<span class=\"char\">";
+ // "</@(?:comment|preprocessor|string|char)>" -> "</span>"
+ src = html;
+ html = QString();
+ static const QString spanTags[] = {
+ "<@comment>", "<span class=\"comment\">",
+ "<@preprocessor>", "<span class=\"preprocessor\">",
+ "<@string>", "<span class=\"string\">",
+ "<@char>", "<span class=\"char\">",
+ "</@comment>", "</span>",
+ "</@preprocessor>","</span>",
+ "</@string>", "</span>",
+ "</@char>", "</span>"
+ // "<@char>", "<font color=blue>",
+ // "</@char>", "</font>",
+ // "<@func>", "<font color=green>",
+ // "</@func>", "</font>",
+ // "<@id>", "<i>",
+ // "</@id>", "</i>",
+ // "<@keyword>", "<b>",
+ // "</@keyword>", "</b>",
+ // "<@number>", "<font color=yellow>",
+ // "</@number>", "</font>",
+ // "<@op>", "<b>",
+ // "</@op>", "</b>",
+ // "<@param>", "<i>",
+ // "</@param>", "</i>",
+ // "<@string>", "<font color=green>",
+ // "</@string>", "</font>",
+ };
+ for (int i = 0, n = src.size(); i < n;) {
+ if (src.at(i) == charLangle) {
+ bool handled = false;
+ for (int k = 0; k != 8; ++k) {
+ const QString & tag = spanTags[2 * k];
+ if (tag == QStringRef(&src, i, tag.length())) {
+ html += spanTags[2 * k + 1];
+ i += tag.length();
+ handled = true;
+ break;
+ }
+ }
+ if (!handled) {
+ ++i;
+ if (src.at(i) == charAt ||
+ (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) {
+ // drop 'our' unknown tags (the ones still containing '@')
+ while (i < n && src.at(i) != QLatin1Char('>'))
+ ++i;
+ ++i;
+ }
+ else {
+ // retain all others
+ html += charLangle;
+ }
+ }
+ }
+ else {
+ html += src.at(i);
+ ++i;
+ }
+ }
+
+ return html;
+}
+
+QString HtmlGenerator::fileBase(const Node *node)
+{
+ QString result;
+
+ result = PageGenerator::fileBase(node);
+
+ if (!node->isInnerNode()) {
+ switch (node->status()) {
+ case Node::Compat:
+ result += "-qt3";
+ break;
+ case Node::Obsolete:
+ result += "-obsolete";
+ break;
+ default:
+ ;
+ }
+ }
+ return result;
+}
+
+#if 0
+QString HtmlGenerator::fileBase(const Node *node,
+ const SectionIterator& section)
+{
+ QStringList::ConstIterator s = section.sectionNumber().end();
+ QStringList::ConstIterator b = section.baseNameStack().end();
+
+ QString suffix;
+ QString base = fileBase(node);
+
+ while (s != section.sectionNumber().begin()) {
+ --s;
+ --b;
+ if (!(*b).isEmpty()) {
+ base = *b;
+ break;
+ }
+ suffix.prepend("-" + *s);
+ }
+ return base + suffix;
+}
+#endif
+
+QString HtmlGenerator::fileName(const Node *node)
+{
+ if (node->type() == Node::Fake) {
+ if (static_cast<const FakeNode *>(node)->subType() == FakeNode::ExternalPage)
+ return node->name();
+ }
+
+ return PageGenerator::fileName(node);
+}
+
+QString HtmlGenerator::refForNode(const Node *node)
+{
+ const FunctionNode *func;
+ const TypedefNode *typedeffe;
+ QString ref;
+
+ switch (node->type()) {
+ case Node::Namespace:
+ case Node::Class:
+ default:
+ break;
+ case Node::Enum:
+ ref = node->name() + "-enum";
+ break;
+ case Node::Typedef:
+ typedeffe = static_cast<const TypedefNode *>(node);
+ if (typedeffe->associatedEnum()) {
+ return refForNode(typedeffe->associatedEnum());
+ } else {
+ ref = node->name() + "-typedef";
+ }
+ break;
+ case Node::Function:
+ func = static_cast<const FunctionNode *>(node);
+ if (func->associatedProperty()) {
+ return refForNode(func->associatedProperty());
+ } else {
+ ref = func->name();
+ if (func->overloadNumber() != 1)
+ ref += "-" + QString::number(func->overloadNumber());
+ }
+ break;
+ case Node::Property:
+ ref = node->name() + "-prop";
+ break;
+ case Node::Variable:
+ ref = node->name() + "-var";
+ break;
+ case Node::Target:
+ return protect(node->name());
+ }
+ return registerRef(ref);
+}
+
+QString HtmlGenerator::linkForNode(const Node *node, const Node *relative)
+{
+ QString link;
+ QString fn;
+ QString ref;
+
+ if (node == 0 || node == relative)
+ return QString();
+ if (!node->url().isEmpty())
+ return node->url();
+ if (fileBase(node).isEmpty())
+ return QString();
+ if (node->access() == Node::Private)
+ return QString();
+
+ fn = fileName(node);
+/* if (!node->url().isEmpty())
+ return fn;*/
+#if 0
+ // ### reintroduce this test, without breaking .dcf files
+ if (fn != outFileName())
+#endif
+ link += fn;
+
+ if (!node->isInnerNode()) {
+ ref = refForNode(node);
+ if (relative && fn == fileName(relative) && ref == refForNode(relative))
+ return QString();
+
+ link += "#";
+ link += ref;
+ }
+ return link;
+}
+
+QString HtmlGenerator::refForAtom(Atom *atom, const Node * /* node */)
+{
+ if (atom->type() == Atom::SectionLeft) {
+ return Doc::canonicalTitle(Text::sectionHeading(atom).toString());
+ } else if (atom->type() == Atom::Target) {
+ return Doc::canonicalTitle(atom->string());
+ } else {
+ return QString();
+ }
+}
+
+void HtmlGenerator::generateFullName(const Node *apparentNode,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *actualNode)
+{
+ if (actualNode == 0)
+ actualNode = apparentNode;
+ out() << "<a href=\"" << linkForNode(actualNode, relative);
+ if (true || relative == 0 || relative->status() != actualNode->status()) {
+ switch (actualNode->status()) {
+ case Node::Obsolete:
+ out() << "\" class=\"obsolete";
+ break;
+ case Node::Compat:
+ out() << "\" class=\"compat";
+ break;
+ default:
+ ;
+ }
+ }
+ out() << "\">";
+ out() << protect(fullName(apparentNode, relative, marker));
+ out() << "</a>";
+}
+
+void HtmlGenerator::generateDetailedMember(const Node *node,
+ const InnerNode *relative,
+ CodeMarker *marker)
+{
+ const EnumNode *enume;
+
+ generateMacRef(node, marker);
+ if (node->type() == Node::Enum
+ && (enume = static_cast<const EnumNode *>(node))->flagsType()) {
+ generateMacRef(enume->flagsType(), marker);
+ out() << "<h3 class=\"flags\">";
+ out() << "<a name=\"" + refForNode(node) + "\"></a>";
+ generateSynopsis(enume, relative, marker, CodeMarker::Detailed);
+ out() << "<br />";
+ generateSynopsis(enume->flagsType(), relative, marker, CodeMarker::Detailed);
+ out() << "</h3>\n";
+ }
+ else {
+ out() << "<h3 class=\"fn\">";
+ out() << "<a name=\"" + refForNode(node) + "\"></a>";
+ generateSynopsis(node, relative, marker, CodeMarker::Detailed);
+ out() << "</h3>\n";
+ }
+
+ generateStatus(node, marker);
+ generateBody(node, marker);
+ generateThreadSafeness(node, marker);
+ generateSince(node, marker);
+
+ if (node->type() == Node::Property) {
+ const PropertyNode *property = static_cast<const PropertyNode *>(node);
+ Section section;
+
+ section.members += property->getters();
+ section.members += property->setters();
+ section.members += property->resetters();
+
+ if (!section.members.isEmpty()) {
+ out() << "<p>Access functions:</p>\n";
+ generateSectionList(section, node, marker, CodeMarker::Accessors);
+ }
+ }
+ else if (node->type() == Node::Enum) {
+ const EnumNode *enume = static_cast<const EnumNode *>(node);
+ if (enume->flagsType()) {
+ out() << "<p>The " << protect(enume->flagsType()->name())
+ << " type is a typedef for "
+ << "<a href=\"qflags.html\">QFlags</a>&lt;"
+ << protect(enume->name())
+ << "&gt;. It stores an OR combination of " << protect(enume->name())
+ << " values.</p>\n";
+ }
+ }
+ generateAlsoList(node, marker);
+}
+
+void HtmlGenerator::findAllClasses(const InnerNode *node)
+{
+ NodeList::const_iterator c = node->childNodes().constBegin();
+ while (c != node->childNodes().constEnd()) {
+ if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) {
+ if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
+ QString className = (*c)->name();
+ if ((*c)->parent() && (*c)->parent()->type() == Node::Namespace &&
+ !(*c)->parent()->name().isEmpty())
+ className = (*c)->parent()->name()+"::"+className;
+
+ if (!(static_cast<const ClassNode *>(*c))->hideFromMainList()) {
+ if ((*c)->status() == Node::Compat) {
+ compatClasses.insert(className, *c);
+ }
+ else {
+ nonCompatClasses.insert(className, *c);
+ if ((*c)->status() == Node::Main)
+ mainClasses.insert(className, *c);
+ }
+ }
+
+ QString moduleName = (*c)->moduleName();
+ if (moduleName == "Qt3SupportLight") {
+ moduleClassMap[moduleName].insert((*c)->name(), *c);
+ moduleName = "Qt3Support";
+ }
+ if (!moduleName.isEmpty())
+ moduleClassMap[moduleName].insert((*c)->name(), *c);
+
+ QString serviceName =
+ (static_cast<const ClassNode *>(*c))->serviceName();
+ if (!serviceName.isEmpty())
+ serviceClasses.insert(serviceName, *c);
+ }
+ else if ((*c)->isInnerNode()) {
+ findAllClasses(static_cast<InnerNode *>(*c));
+ }
+ }
+ ++c;
+ }
+}
+
+void HtmlGenerator::findAllFunctions(const InnerNode *node)
+{
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while (c != node->childNodes().end()) {
+ if ((*c)->access() != Node::Private) {
+ if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
+ findAllFunctions(static_cast<const InnerNode *>(*c));
+ }
+ else if ((*c)->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(*c);
+ if (func->status() > Node::Obsolete && func->metaness() != FunctionNode::Ctor
+ && func->metaness() != FunctionNode::Dtor) {
+ funcIndex[(*c)->name()].insert((*c)->parent()->name(), *c);
+ }
+ }
+ }
+ ++c;
+ }
+}
+
+void HtmlGenerator::findAllLegaleseTexts(const InnerNode *node)
+{
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while (c != node->childNodes().end()) {
+ if ((*c)->access() != Node::Private) {
+ if (!(*c)->doc().legaleseText().isEmpty())
+ legaleseTexts.insertMulti((*c)->doc().legaleseText(), *c);
+ if ((*c)->isInnerNode())
+ findAllLegaleseTexts(static_cast<const InnerNode *>(*c));
+ }
+ ++c;
+ }
+}
+
+void HtmlGenerator::findAllNamespaces(const InnerNode *node)
+{
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while (c != node->childNodes().end()) {
+ if ((*c)->access() != Node::Private) {
+ if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
+ findAllNamespaces(static_cast<const InnerNode *>(*c));
+ if ((*c)->type() == Node::Namespace) {
+ const NamespaceNode *nspace = static_cast<const NamespaceNode *>(*c);
+ // Ensure that the namespace's name is not empty (the root
+ // namespace has no name).
+ if (!nspace->name().isEmpty()) {
+ namespaceIndex.insert(nspace->name(), *c);
+ QString moduleName = (*c)->moduleName();
+ if (moduleName == "Qt3SupportLight") {
+ moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
+ moduleName = "Qt3Support";
+ }
+ if (!moduleName.isEmpty())
+ moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
+ }
+ }
+ }
+ }
+ ++c;
+ }
+}
+
+#ifdef ZZZ_QDOC_QML
+/*!
+ This function finds all the qml element nodes and
+ stores them in a map for later use.
+ */
+void HtmlGenerator::findAllQmlClasses(const InnerNode *node)
+{
+ NodeList::const_iterator c = node->childNodes().constBegin();
+ while (c != node->childNodes().constEnd()) {
+ if ((*c)->type() == Node::Fake) {
+ const FakeNode* fakeNode = static_cast<const FakeNode *>(*c);
+ if (fakeNode->subType() == FakeNode::QmlClass) {
+ const QmlNode* qmlNode = static_cast<const QmlNode*>(fakeNode);
+ //qDebug() << "HtmlGenerator: QML CLASS" << qmlNode->name();
+ const Node* n = qmlNode->classNode();
+ if (n)
+ //qDebug() << " FOUND IT!" << n->name();
+ }
+ qmlClasses.insert(fakeNode->name(),*c);
+ }
+ ++c;
+ }
+}
+#endif
+
+#if 0
+ else if ((*c)->isInnerNode()) {
+ findAllClasses(static_cast<InnerNode *>(*c));
+ }
+#endif
+
+int HtmlGenerator::hOffset(const Node *node)
+{
+ switch (node->type()) {
+ case Node::Namespace:
+ case Node::Class:
+ return 2;
+ case Node::Fake:
+ if (node->doc().briefText().isEmpty())
+ return 1;
+ else
+ return 2;
+ case Node::Enum:
+ case Node::Typedef:
+ case Node::Function:
+ case Node::Property:
+ default:
+ return 3;
+ }
+}
+
+bool HtmlGenerator::isThreeColumnEnumValueTable(const Atom *atom)
+{
+ while (atom != 0 && !(atom->type() == Atom::ListRight && atom->string() == ATOM_LIST_VALUE)) {
+ if (atom->type() == Atom::ListItemLeft && !matchAhead(atom, Atom::ListItemRight))
+ return true;
+ atom = atom->next();
+ }
+ return false;
+}
+
+const Node *HtmlGenerator::findNodeForTarget(const QString &target,
+ const Node *relative,
+ CodeMarker *marker,
+ const Atom *atom)
+{
+ const Node *node = 0;
+
+ if (target.isEmpty()) {
+ node = relative;
+ }
+ else if (target.endsWith(".html")) {
+ node = tre->root()->findNode(target, Node::Fake);
+ }
+ else if (marker) {
+ node = marker->resolveTarget(target, tre, relative);
+ if (!node)
+ node = tre->findFakeNodeByTitle(target);
+ if (!node && atom) {
+ node = tre->findUnambiguousTarget(target,
+ *const_cast<Atom**>(&atom));
+ }
+ }
+
+ if (!node)
+ relative->doc().location().warning(tr("Cannot link to '%1'").arg(target));
+
+ return node;
+}
+
+const QPair<QString,QString> HtmlGenerator::anchorForNode(const Node *node)
+{
+ QPair<QString,QString> anchorPair;
+
+ anchorPair.first = PageGenerator::fileName(node);
+ if (node->type() == Node::Fake) {
+ const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
+ anchorPair.second = fakeNode->title();
+ }
+
+ return anchorPair;
+}
+
+QString HtmlGenerator::getLink(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *node)
+{
+ QString link;
+ node = 0;
+
+ if (atom->string().contains(":") &&
+ (atom->string().startsWith("file:")
+ || atom->string().startsWith("http:")
+ || atom->string().startsWith("https:")
+ || atom->string().startsWith("ftp:")
+ || atom->string().startsWith("mailto:"))) {
+
+ link = atom->string();
+ }
+ else {
+ QStringList path;
+ if (atom->string().contains('#')) {
+ path = atom->string().split('#');
+ }
+ else {
+ path.append(atom->string());
+ }
+
+ Atom *targetAtom = 0;
+
+ QString first = path.first().trimmed();
+ if (first.isEmpty()) {
+ node = relative;
+ }
+ else if (first.endsWith(".html")) {
+ node = tre->root()->findNode(first, Node::Fake);
+ }
+ else {
+ node = marker->resolveTarget(first, tre, relative);
+ if (!node)
+ node = tre->findFakeNodeByTitle(first);
+ if (!node)
+ node = tre->findUnambiguousTarget(first, targetAtom);
+ }
+
+ if (node) {
+ if (!node->url().isEmpty())
+ return node->url();
+ else
+ path.removeFirst();
+ }
+ else {
+ node = relative;
+ }
+
+ while (!path.isEmpty()) {
+ targetAtom = tre->findTarget(path.first(), node);
+ if (targetAtom == 0)
+ break;
+ path.removeFirst();
+ }
+
+ if (path.isEmpty()) {
+ link = linkForNode(node, relative);
+ if (targetAtom)
+ link += "#" + refForAtom(targetAtom, node);
+ }
+ }
+ return link;
+}
+
+void HtmlGenerator::generateDcf(const QString &fileBase,
+ const QString &startPage,
+ const QString &title,
+ DcfSection &dcfRoot)
+{
+ dcfRoot.ref = startPage;
+ dcfRoot.title = title;
+ generateDcfSections(dcfRoot, outputDir() + "/" + fileBase + ".dcf", fileBase + "/reference");
+}
+
+void HtmlGenerator::generateIndex(const QString &fileBase,
+ const QString &url,
+ const QString &title)
+{
+ tre->generateIndex(outputDir() + "/" + fileBase + ".index", url, title);
+}
+
+void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker)
+{
+ Text text;
+
+ switch (node->status()) {
+ case Node::Obsolete:
+ if (node->isInnerNode())
+ Generator::generateStatus(node, marker);
+ break;
+ case Node::Compat:
+ if (node->isInnerNode()) {
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) << "This "
+ << typeString(node) << " is part of the Qt 3 support library."
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << " It is provided to keep old source code working. We strongly advise against "
+ << "using it in new code. See ";
+
+ const FakeNode *fakeNode = tre->findFakeNodeByTitle("Porting To Qt 4");
+ Atom *targetAtom = 0;
+ if (fakeNode && node->type() == Node::Class) {
+ QString oldName(node->name());
+ targetAtom = tre->findTarget(oldName.replace("3", ""),
+ fakeNode);
+ }
+
+ if (targetAtom) {
+ text << Atom(Atom::Link, linkForNode(fakeNode, node) + "#" +
+ refForAtom(targetAtom, fakeNode));
+ }
+ else
+ text << Atom(Atom::Link, "Porting to Qt 4");
+
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, "Porting to Qt 4")
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
+ << " for more information."
+ << Atom::ParaRight;
+ }
+ generateText(text, node, marker);
+ break;
+ default:
+ Generator::generateStatus(node, marker);
+ }
+}
+
+void HtmlGenerator::generateMacRef(const Node *node, CodeMarker *marker)
+{
+ if (!pleaseGenerateMacRef || marker == 0)
+ return;
+
+ QStringList macRefs = marker->macRefsForNode(node);
+ foreach (const QString &macRef, macRefs)
+ out() << "<a name=\"" << "//apple_ref/" << macRef << "\" />\n";
+}
+
+void HtmlGenerator::beginLink(const QString &link,
+ const Node *node,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ Q_UNUSED(marker)
+ Q_UNUSED(relative)
+
+ this->link = link;
+ if (link.isEmpty()) {
+ if (showBrokenLinks)
+ out() << "<i>";
+ }
+ else if (node == 0 || (relative != 0 &&
+ node->status() == relative->status())) {
+ out() << "<a href=\"" << link << "\">";
+ }
+ else {
+ switch (node->status()) {
+ case Node::Obsolete:
+ out() << "<a href=\"" << link << "\" class=\"obsolete\">";
+ break;
+ case Node::Compat:
+ out() << "<a href=\"" << link << "\" class=\"compat\">";
+ break;
+ default:
+ out() << "<a href=\"" << link << "\">";
+ }
+ }
+ inLink = true;
+}
+
+void HtmlGenerator::endLink()
+{
+ if (inLink) {
+ if (link.isEmpty()) {
+ if (showBrokenLinks)
+ out() << "</i>";
+ }
+ else {
+ out() << "</a>";
+ }
+ }
+ inLink = false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h
new file mode 100644
index 0000000000..de64190d14
--- /dev/null
+++ b/tools/qdoc3/htmlgenerator.h
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ htmlgenerator.h
+*/
+
+#ifndef HTMLGENERATOR_H
+#define HTMLGENERATOR_H
+
+#include <qmap.h>
+#include <qregexp.h>
+
+#include "codemarker.h"
+#include "config.h"
+#include "dcfsection.h"
+#include "pagegenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+#if 0
+struct NavigationBar
+{
+ SectionIterator prev;
+ SectionIterator current;
+ SectionIterator next;
+};
+#endif
+
+class HelpProjectWriter;
+
+class HtmlGenerator : public PageGenerator
+{
+ public:
+ HtmlGenerator();
+ ~HtmlGenerator();
+
+ virtual void initializeGenerator(const Config& config);
+ virtual void terminateGenerator();
+ virtual QString format();
+ virtual void generateTree(const Tree *tree, CodeMarker *marker);
+
+ static QString protect(const QString& string);
+ static QString cleanRef(const QString& ref);
+
+ protected:
+ virtual void startText(const Node *relative, CodeMarker *marker);
+ virtual int generateAtom(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker);
+ virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
+ virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker);
+ virtual QString fileExtension(const Node *node);
+ virtual QString refForNode(const Node *node);
+ virtual QString linkForNode(const Node *node, const Node *relative);
+ virtual QString refForAtom(Atom *atom, const Node *node);
+
+ private:
+ enum SubTitleSize { SmallSubTitle, LargeSubTitle };
+
+ const QPair<QString,QString> anchorForNode(const Node *node);
+ const Node *findNodeForTarget(const QString &target,
+ const Node *relative,
+ CodeMarker *marker,
+ const Atom *atom = 0);
+ void generateHeader(const QString& title, const Node *node = 0,
+ CodeMarker *marker = 0, bool mainPage = true);
+ void generateTitle(const QString& title,
+ const Text &subTitle,
+ SubTitleSize subTitleSize,
+ const Node *relative,
+ CodeMarker *marker);
+ void generateFooter(const Node *node = 0);
+ void generateBrief(const Node *node,
+ CodeMarker *marker,
+ const Node *relative = 0);
+ void generateIncludes(const InnerNode *inner, CodeMarker *marker);
+#if 0
+ void generateNavigationBar(const NavigationBar& bar,
+ const Node *node,
+ CodeMarker *marker);
+#endif
+ void generateTableOfContents(const Node *node,
+ CodeMarker *marker,
+ Doc::SectioningUnit sectioningUnit,
+ int numColumns,
+ const Node *relative = 0);
+ QString generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker);
+ QString generateLowStatusMemberFile(const InnerNode *inner,
+ CodeMarker *marker,
+ CodeMarker::Status status);
+ void generateClassHierarchy(const Node *relative,
+ CodeMarker *marker,
+ const QMap<QString,const Node *> &classMap);
+ void generateAnnotatedList(const Node *relative,
+ CodeMarker *marker,
+ const QMap<QString, const Node *> &nodeMap);
+ void generateCompactList(const Node *relative,
+ CodeMarker *marker,
+ const QMap<QString, const Node *> &classMap);
+ void generateFunctionIndex(const Node *relative, CodeMarker *marker);
+ void generateLegaleseList(const Node *relative, CodeMarker *marker);
+ void generateOverviewList(const Node *relative, CodeMarker *marker);
+ void generateSynopsis(const Node *node,
+ const Node *relative,
+ CodeMarker *marker,
+ CodeMarker::SynopsisStyle style);
+ void generateSectionList(const Section& section,
+ const Node *relative,
+ CodeMarker *marker,
+ CodeMarker::SynopsisStyle style);
+ void generateSectionInheritedList(const Section& section,
+ const Node *relative,
+ CodeMarker *marker);
+ void generateFullName(const Node *apparentNode,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *actualNode = 0);
+ void generateDetailedMember(const Node *node, const InnerNode *relative, CodeMarker *marker);
+ void generateLink(const Atom *atom, const Node *relative, CodeMarker *marker);
+ void generateStatus(const Node *node, CodeMarker *marker);
+
+ QString registerRef(const QString& ref);
+ QString highlightedCode(const QString& markedCode, CodeMarker *marker, const Node *relative);
+ QString fileBase(const Node *node);
+#if 0
+ QString fileBase(const Node *node, const SectionIterator& section);
+#endif
+ QString fileName(const Node *node);
+ void findAllClasses(const InnerNode *node);
+ void findAllFunctions(const InnerNode *node);
+ void findAllLegaleseTexts(const InnerNode *node);
+ void findAllNamespaces(const InnerNode *node);
+#ifdef ZZZ_QDOC_QML
+ void findAllQmlClasses(const InnerNode *node);
+#endif
+ static int hOffset(const Node *node);
+ static bool isThreeColumnEnumValueTable(const Atom *atom);
+ virtual QString getLink(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *node = 0);
+ virtual void generateDcf(const QString &fileBase,
+ const QString &startPage,
+ const QString &title, DcfSection &dcfRoot);
+ virtual void generateIndex(const QString &fileBase,
+ const QString &url,
+ const QString &title);
+ void generateMacRef(const Node *node, CodeMarker *marker);
+ void beginLink(const QString &link,
+ const Node *node,
+ const Node *relative,
+ CodeMarker *marker);
+ void endLink();
+
+#if 0
+ NavigationBar currentNavigationBar;
+#endif
+ QMap<QString, QString> refMap;
+ int codeIndent;
+ DcfSection dcfClassesRoot;
+ DcfSection dcfOverviewsRoot;
+ DcfSection dcfExamplesRoot;
+ DcfSection dcfDesignerRoot;
+ DcfSection dcfLinguistRoot;
+ DcfSection dcfAssistantRoot;
+ DcfSection dcfQmakeRoot;
+ HelpProjectWriter *helpProjectWriter;
+ bool inLink;
+ bool inContents;
+ bool inSectionHeading;
+ bool inTableHeader;
+ int numTableRows;
+ bool threeColumnEnumValueTable;
+ QString link;
+ QStringList sectionNumber;
+ QRegExp funcLeftParen;
+ QString style;
+ QString postHeader;
+ QString footer;
+ QString address;
+ bool pleaseGenerateMacRef;
+ QString project;
+ QString projectDescription;
+ QString projectUrl;
+ QString navigationLinks;
+ QStringList stylesheets;
+ QStringList customHeadElements;
+ const Tree *tre;
+ bool slow;
+ QMap<QString, QMap<QString, const Node *> > moduleClassMap;
+ QMap<QString, QMap<QString, const Node *> > moduleNamespaceMap;
+ QMap<QString, const Node *> nonCompatClasses;
+ QMap<QString, const Node *> mainClasses;
+ QMap<QString, const Node *> compatClasses;
+ QMap<QString, const Node *> namespaceIndex;
+ QMap<QString, const Node *> serviceClasses;
+#ifdef QDOC_QML
+ QMap<QString, const Node *> qmlClasses;
+#endif
+ QMap<QString, QMap<QString, const Node *> > funcIndex;
+ QMap<Text, const Node *> legaleseTexts;
+};
+
+#define HTMLGENERATOR_ADDRESS "address"
+#define HTMLGENERATOR_FOOTER "footer"
+#define HTMLGENERATOR_GENERATEMACREFS "generatemacrefs" // ### document me
+#define HTMLGENERATOR_POSTHEADER "postheader"
+#define HTMLGENERATOR_STYLE "style"
+#define HTMLGENERATOR_STYLESHEETS "stylesheets"
+#define HTMLGENERATOR_CUSTOMHEADELEMENTS "customheadelements"
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/jambiapiparser.cpp b/tools/qdoc3/jambiapiparser.cpp
new file mode 100644
index 0000000000..73d10a6148
--- /dev/null
+++ b/tools/qdoc3/jambiapiparser.cpp
@@ -0,0 +1,547 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ jambiapiparser.cpp
+*/
+
+#include <QtXml>
+
+#include "cppcodeparser.h"
+#include "jambiapiparser.h"
+#include "node.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+static const char USED_INTERNALLY[] = "";
+
+static Text textWithFixedBrief(const Text &text, const Text &beforeBrief,
+ const Text &afterBrief)
+{
+ Text result;
+
+ const Atom *atom = text.firstAtom();
+ while (atom) {
+ if (atom->type() == Atom::BriefLeft) {
+ result << Atom::ParaLeft << beforeBrief;
+ } else if (atom->type() == Atom::BriefRight) {
+ result << afterBrief << Atom::ParaRight;
+ } else {
+ result << *atom;
+ }
+ atom = atom->next();
+ }
+
+ return result;
+}
+
+static void setPass1JambifiedDoc(Node *javaNode, const Node *cppNode, const QString &qName = "")
+{
+ Doc newDoc(cppNode->doc());
+
+ if (javaNode->type() == Node::Function) {
+ const FunctionNode *javaFunc = static_cast<const FunctionNode *>(javaNode);
+ if (cppNode->type() == Node::Function) {
+ const FunctionNode *cppFunc = static_cast<const FunctionNode *>(cppNode);
+ if (const PropertyNode *property = cppFunc->associatedProperty()) {
+ newDoc = property->doc();
+ Text text(newDoc.body());
+
+ Node *mutableCppNode = const_cast<Node *>(cppNode);
+ if (property->getters().contains(mutableCppNode)) {
+ text = textWithFixedBrief(text, Text("Returns "), Text("."));
+ } else if (property->setters().contains(mutableCppNode)) {
+ Text afterBrief;
+ if (javaFunc->parameterNames().count() == 1
+ && !javaFunc->parameterNames().first().isEmpty()) {
+ afterBrief << " to "
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_PARAMETER)
+ << javaFunc->parameterNames().first()
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_PARAMETER);
+ }
+ afterBrief << ".";
+ text = textWithFixedBrief(text, Text("Sets "), afterBrief);
+ } else if (property->resetters().contains(mutableCppNode)) {
+ text = textWithFixedBrief(text, Text("Resets "), Text("."));
+ }
+
+ newDoc.setBody(text);
+ } else {
+ QStringList javaParams = javaFunc->parameterNames();
+ QStringList cppParams = cppFunc->parameterNames();
+ newDoc.renameParameters(cppParams, javaParams);
+
+ if (cppNode->access() == Node::Private) {
+ Text text;
+ text << Atom::ParaLeft;
+ if (cppFunc->reimplementedFrom()) {
+ text << "This function is reimplemented for internal reasons.";
+ } else {
+ text << USED_INTERNALLY;
+ }
+ text << Atom::ParaRight;
+ newDoc.setBody(text);
+ }
+ }
+ } else if (cppNode->type() == Node::Variable) {
+ Text text(newDoc.body());
+
+ if (qName == "variablegetter") {
+ text = textWithFixedBrief(text, Text("Returns "), Text("."));
+ } else if (qName == "variablesetter") {
+ Text afterBrief;
+ if (javaFunc->parameterNames().count() == 1
+ && !javaFunc->parameterNames().first().isEmpty()) {
+ afterBrief << " to "
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_PARAMETER)
+ << javaFunc->parameterNames().first()
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_PARAMETER);
+ }
+ afterBrief << ".";
+ text = textWithFixedBrief(text, Text("Sets "), afterBrief);
+ }
+
+ newDoc.setBody(text);
+ }
+ } else { // ### enum value names?
+
+ }
+
+ javaNode->setDoc(newDoc, true);
+}
+
+static void setStatus(Node *javaNode, const Node *cppNode)
+{
+ if (cppNode->status() == Node::Compat) {
+ javaNode->setStatus(Node::Obsolete);
+ } else {
+ javaNode->setStatus(cppNode->status());
+ }
+}
+
+static Text findEnumText(Node *javaEnum, const QString &enumItemName)
+{
+ const Text &body = javaEnum->doc().body();
+ const Atom *atom = body.firstAtom();
+ while (atom) {
+ if (atom->type() == Atom::ListTagLeft && atom->string() == ATOM_LIST_VALUE) {
+ atom = atom->next();
+ if (atom) {
+ // ### paras?
+ if (atom->string() == enumItemName)
+ return body.subText(Atom::ListItemLeft, Atom::ListItemRight, atom);
+ }
+ } else {
+ atom = atom->next();
+ }
+ }
+ return Text();
+}
+
+JambiApiParser::JambiApiParser(Tree *cppTree)
+ : cppTre(cppTree), javaTre(0), metJapiTag(false)
+{
+}
+
+JambiApiParser::~JambiApiParser()
+{
+}
+
+void JambiApiParser::initializeParser(const Config &config)
+{
+ CodeParser::initializeParser(config);
+}
+
+void JambiApiParser::terminateParser()
+{
+ CodeParser::terminateParser();
+}
+
+QString JambiApiParser::language()
+{
+ return "Java";
+}
+
+QString JambiApiParser::sourceFileNameFilter()
+{
+ return "*.japi";
+}
+
+void JambiApiParser::parseSourceFile(const Location &location, const QString &filePath, Tree *tree)
+{
+ javaTre = tree;
+ metJapiTag = false;
+
+ QXmlSimpleReader reader;
+ reader.setContentHandler(this);
+ reader.setErrorHandler(this);
+
+ QFile file(filePath);
+ if (!file.open(QFile::ReadOnly)) {
+ location.warning(tr("Cannot open JAPI file '%1'").arg(filePath));
+ return;
+ }
+
+ japiLocation = Location(filePath);
+ QXmlInputSource xmlSource(&file);
+ reader.parse(xmlSource);
+}
+
+void JambiApiParser::doneParsingSourceFiles(Tree * /* tree */)
+{
+ /*
+ Also import the overview documents.
+ */
+ foreach (Node *cppNode, cppTre->root()->childNodes()) {
+ if (cppNode->type() == Node::Fake) {
+ FakeNode *cppFake = static_cast<FakeNode *>(cppNode);
+ if (cppFake->subType() == FakeNode::Page) {
+ FakeNode *javaFake = new FakeNode(javaTre->root(), cppFake->name(),
+ cppFake->subType());
+ javaFake->setModuleName("com.trolltech.qt"); // ### hard-coded
+ javaFake->setTitle(cppFake->title());
+ javaFake->setSubTitle(cppFake->subTitle());
+ setStatus(javaFake, cppFake);
+ setPass1JambifiedDoc(javaFake, cppFake);
+ }
+ }
+ }
+
+ /*
+ Fix the docs.
+ */
+ if (javaTre) {
+ javaTre->resolveInheritance();
+ jambifyDocsPass2(javaTre->root());
+ javaTre = 0;
+ }
+}
+
+bool JambiApiParser::startElement(const QString & /* namespaceURI */,
+ const QString & /* localName */,
+ const QString &qName,
+ const QXmlAttributes &attributes)
+{
+ if (!metJapiTag && qName != "japi") {
+ // ### The file is not a JAPI file.
+ return true;
+ }
+ metJapiTag = true;
+
+ EnumNode *javaEnum = 0;
+ EnumNode *cppEnum = 0;
+ InnerNode *javaParent = javaTre->root();
+ InnerNode *cppParent = cppTre->root();
+
+ for (int i = 0; i < classAndEnumStack.count(); ++i) {
+ const ClassOrEnumInfo &info = classAndEnumStack.at(i);
+ if (info.cppNode) {
+ if (info.cppNode->type() == Node::Enum) {
+ Q_ASSERT(info.javaNode->type() == Node::Enum);
+ javaEnum = static_cast<EnumNode *>(info.javaNode);
+ cppEnum = static_cast<EnumNode *>(info.cppNode);
+ } else {
+ Q_ASSERT(info.javaNode->type() == Node::Class
+ || info.javaNode->type() == Node::Namespace);
+ javaParent = static_cast<InnerNode *>(info.javaNode);
+ cppParent = static_cast<InnerNode *>(info.cppNode);
+ }
+ }
+ }
+
+ if (qName == "class" || qName == "enum") {
+ Node::Type type = (qName == "class") ? Node::Class : Node::Enum;
+
+ QString javaExtends = attributes.value("java-extends");
+ QString javaImplements = attributes.value("javaimplements");
+
+ ClassOrEnumInfo info;
+ info.tag = qName;
+ info.javaName = attributes.value("java");
+ info.cppName = attributes.value("cpp");
+ info.cppNode = cppTre->findNode(info.cppName.split("::"), type, cppParent);
+ if (!info.cppNode && type == Node::Class) {
+ type = Node::Namespace;
+ info.cppNode = cppTre->findNode(info.cppName.split("::"), type, cppParent);
+ }
+
+ if (!info.cppNode) {
+ japiLocation.warning(tr("Cannot find C++ class or enum '%1'").arg(info.cppName));
+ } else {
+ if (qName == "class") {
+ ClassNode *javaClass = new ClassNode(javaParent, info.javaName);
+ javaClass->setModuleName(attributes.value("package"));
+ if (!javaExtends.isEmpty())
+ javaTre->addBaseClass(javaClass, Node::Public, javaExtends.split('.'),
+ javaExtends);
+ if (!javaImplements.isEmpty())
+ javaTre->addBaseClass(javaClass, Node::Public, javaImplements.split('.'),
+ javaExtends);
+
+ info.javaNode = javaClass;
+ } else {
+ info.javaNode = new EnumNode(javaParent, info.javaName);
+ }
+ info.javaNode->setLocation(japiLocation);
+ setStatus(info.javaNode, info.cppNode);
+
+ setPass1JambifiedDoc(info.javaNode, info.cppNode);
+ }
+ classAndEnumStack.push(info);
+ } else if (qName == "method" || qName == "signal") {
+ QString javaSignature = attributes.value("java");
+ if (javaSignature.startsWith("private"))
+ return true;
+
+ QString cppSignature = attributes.value("cpp");
+
+ CppCodeParser cppParser;
+ const FunctionNode *cppNode = cppParser.findFunctionNode(cppSignature, cppTre,
+ cppParent,
+ true /* fuzzy */);
+ if (!cppNode) {
+ bool quiet = false;
+
+ /*
+ Default constructors sometimes don't exist in C++.
+ */
+ if (!quiet && javaSignature == "public " + javaParent->name() + "()")
+ quiet = true;
+
+ if (!quiet)
+ japiLocation.warning(tr("Cannot find C++ function '%1' ('%2')")
+ .arg(cppSignature).arg(cppParent->name()));
+ }
+
+ FunctionNode *javaNode;
+ if (makeFunctionNode(javaParent, javaSignature, &javaNode)) {
+ javaNode->setLocation(japiLocation);
+ if (qName == "signal")
+ javaNode->setMetaness(FunctionNode::Signal);
+
+ if (cppNode) {
+ setStatus(javaNode, cppNode);
+
+ int overloadNo = cppNode->parameters().count() - javaNode->parameters().count() + 1;
+ if (overloadNo == 1) {
+ setPass1JambifiedDoc(javaNode, cppNode);
+ } else {
+ Text text;
+
+ text << Atom::ParaLeft << "Equivalent to "
+ << Atom(Atom::Link, javaNode->name() + "()")
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << javaNode->name()
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK)
+ << "(";
+
+ for (int i = 0; i < cppNode->parameters().count(); ++i) {
+ if (i > 0)
+ text << ", ";
+ if (i < javaNode->parameters().count()) {
+ text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_PARAMETER)
+ << javaNode->parameters().at(i).name()
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_PARAMETER);
+ } else {
+ // ### convert to Java
+ text << cppNode->parameters().at(i).defaultValue();
+ }
+ }
+
+ text << ").";
+
+ Doc doc;
+ doc.setBody(text);
+ javaNode->setDoc(doc, true);
+ }
+ javaNode->setOverload(overloadNo > 1);
+ }
+ }
+ } else if (qName == "variablesetter" || qName == "variablegetter") {
+ QString javaSignature = attributes.value("java");
+ if (javaSignature.startsWith("private"))
+ return true;
+
+ QString cppVariable = attributes.value("cpp");
+
+ VariableNode *cppNode = static_cast<VariableNode *>(cppParent->findNode(cppVariable,
+ Node::Variable));
+ FunctionNode *javaNode;
+ if (makeFunctionNode(javaParent, javaSignature, &javaNode)) {
+ javaNode->setLocation(japiLocation);
+
+ if (!cppNode) {
+#if 0
+ japiLocation.warning(tr("Cannot find C++ variable '%1' ('%2')")
+ .arg(cppVariable).arg(cppParent->name()));
+#endif
+ javaNode->setDoc(Doc(japiLocation, japiLocation,
+ USED_INTERNALLY,
+ QSet<QString>()), true);
+ } else {
+ setPass1JambifiedDoc(javaNode, cppNode, qName);
+ setStatus(javaNode, cppNode);
+ }
+ }
+ } else if (qName == "enum-value") {
+ QString javaName = attributes.value("java");
+ QString cppName = attributes.value("cpp");
+ QString value = attributes.value("value");
+
+ if (javaEnum) {
+ EnumItem item(javaName, value, findEnumText(javaEnum, javaName));
+ javaEnum->addItem(item);
+ }
+ }
+
+ return true;
+}
+
+bool JambiApiParser::endElement(const QString & /* namespaceURI */,
+ const QString & /* localName */,
+ const QString &qName)
+{
+ if (qName == "class" || qName == "enum")
+ classAndEnumStack.pop();
+ return true;
+}
+
+bool JambiApiParser::fatalError(const QXmlParseException &exception)
+{
+ japiLocation.setLineNo(exception.lineNumber());
+ japiLocation.setColumnNo(exception.columnNumber());
+ japiLocation.warning(tr("Syntax error in JAPI file (%1)").arg(exception.message()));
+ return true;
+}
+
+void JambiApiParser::jambifyDocsPass2(Node *node)
+{
+ const Doc &doc = node->doc();
+ if (!doc.isEmpty()) {
+ if (node->type() == Node::Enum) {
+ Doc newDoc(doc);
+ newDoc.simplifyEnumDoc();
+ node->setDoc(newDoc, true);
+ }
+ }
+
+ if (node->isInnerNode()) {
+ InnerNode *innerNode = static_cast<InnerNode *>(node);
+ foreach (Node *child, innerNode->childNodes())
+ jambifyDocsPass2(child);
+ }
+}
+
+bool JambiApiParser::makeFunctionNode(InnerNode *parent, const QString &synopsis,
+ FunctionNode **funcPtr)
+{
+ Node::Access access = Node::Public;
+ FunctionNode::Metaness metaness = FunctionNode::Plain;
+ bool final = false;
+ bool statique = false;
+
+ QString mySynopsis = synopsis.simplified();
+ int oldLen;
+ do {
+ oldLen = mySynopsis.length();
+
+ if (mySynopsis.startsWith("public ")) {
+ mySynopsis.remove(0, 7);
+ access = Node::Public;
+ }
+ if (mySynopsis.startsWith("protected ")) {
+ mySynopsis.remove(0, 10);
+ access = Node::Protected;
+ }
+ if (mySynopsis.startsWith("private ")) {
+ mySynopsis.remove(0, 8);
+ access = Node::Private;
+ }
+ if (mySynopsis.startsWith("native ")) {
+ mySynopsis.remove(0, 7);
+ metaness = FunctionNode::Native;
+ }
+ if (mySynopsis.startsWith("final ")) {
+ mySynopsis.remove(0, 6);
+ final = true;
+ }
+ if (mySynopsis.startsWith("static ")) {
+ mySynopsis.remove(0, 7);
+ statique = true;
+ }
+ } while (oldLen != mySynopsis.length());
+
+ // method or constructor
+ QRegExp funcRegExp("(?:(.*) )?([A-Za-z_0-9]+)\\((.*)\\)");
+ if (!funcRegExp.exactMatch(mySynopsis))
+ return false;
+
+ QString retType = funcRegExp.cap(1);
+ QString funcName = funcRegExp.cap(2);
+ QStringList params = funcRegExp.cap(3).split(",");
+
+ FunctionNode *func = new FunctionNode(parent, funcName);
+ func->setReturnType(retType);
+ func->setAccess(access);
+ func->setStatic(statique);
+ func->setConst(final);
+ func->setMetaness(metaness);
+
+ QRegExp paramRegExp(" ?([^ ].*) ([A-Za-z_0-9]+) ?");
+
+ foreach (const QString &param, params) {
+ if (paramRegExp.exactMatch(param)) {
+ func->addParameter(Parameter(paramRegExp.cap(1), "", paramRegExp.cap(2)));
+ } else {
+ // problem
+ }
+ }
+
+ if (funcPtr) {
+ *funcPtr = func;
+ } else if (!parent) {
+ delete func;
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/jambiapiparser.h b/tools/qdoc3/jambiapiparser.h
new file mode 100644
index 0000000000..e0dfe3d4c4
--- /dev/null
+++ b/tools/qdoc3/jambiapiparser.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ jambiapiparser.h
+*/
+
+#ifndef JAMBIAPIPARSER_H
+#define JAMBIAPIPARSER_H
+
+#include <QStack>
+#include <QXmlDefaultHandler>
+
+#include "codeparser.h"
+
+QT_BEGIN_NAMESPACE
+
+struct ClassOrEnumInfo
+{
+ QString tag;
+ QString javaName;
+ QString cppName;
+ Node *javaNode;
+ Node *cppNode;
+
+ ClassOrEnumInfo() : javaNode(0), cppNode(0) {}
+};
+
+class JambiApiParser : public CodeParser, private QXmlDefaultHandler
+{
+public:
+ JambiApiParser(Tree *cppTree);
+ ~JambiApiParser();
+
+ void initializeParser(const Config &config);
+ void terminateParser();
+ QString language();
+ QString sourceFileNameFilter();
+ void parseSourceFile(const Location &location, const QString &filePath, Tree *tree);
+ virtual void doneParsingSourceFiles(Tree *tree);
+
+private:
+ bool startElement(const QString &namespaceURI, const QString &localName,
+ const QString &qName, const QXmlAttributes &attributes);
+ bool endElement(const QString &namespaceURI, const QString &localName,
+ const QString &qName);
+ bool fatalError(const QXmlParseException &exception);
+ void jambifyDocsPass2(Node *node);
+ bool makeFunctionNode(InnerNode *parent, const QString &synopsis, FunctionNode **funcPtr);
+
+ Tree *cppTre;
+ Tree *javaTre;
+
+ bool metJapiTag;
+ Location japiLocation;
+ QStack<ClassOrEnumInfo> classAndEnumStack;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/javacodemarker.cpp b/tools/qdoc3/javacodemarker.cpp
new file mode 100644
index 0000000000..813f505655
--- /dev/null
+++ b/tools/qdoc3/javacodemarker.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ javacodemarker.cpp
+*/
+
+#include "javacodemarker.h"
+#include "node.h"
+#include "text.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+JavaCodeMarker::JavaCodeMarker()
+{
+}
+
+JavaCodeMarker::~JavaCodeMarker()
+{
+}
+
+bool JavaCodeMarker::recognizeCode( const QString& /* code */ )
+{
+ return true;
+}
+
+bool JavaCodeMarker::recognizeExtension( const QString& ext )
+{
+ return ext == "java";
+}
+
+bool JavaCodeMarker::recognizeLanguage( const QString& lang )
+{
+ return lang == "Java";
+}
+
+QString JavaCodeMarker::plainName( const Node *node )
+{
+ return node->name();
+}
+
+QString JavaCodeMarker::plainFullName( const Node *node, const Node * /* relative */ )
+{
+ if (!node)
+ return QString();
+
+ QString fullName;
+ for ( ;; ) {
+ fullName.prepend( plainName(node) );
+ if ( node->parent() && node->parent()->name().isEmpty() )
+ break;
+ node = node->parent();
+ if (!node)
+ break;
+ fullName.prepend(".");
+ }
+ return fullName;
+}
+
+QString JavaCodeMarker::markedUpCode( const QString& code,
+ const Node * /* relative */,
+ const QString& /* dirPath */ )
+{
+ return protect( code );
+}
+
+QString JavaCodeMarker::markedUpSynopsis(const Node * /* node */,
+ const Node * /* relative */,
+ SynopsisStyle /* style */)
+{
+ return QString();
+}
+
+QString JavaCodeMarker::markedUpName( const Node *node )
+{
+ return linkTag(node, taggedNode(node));
+}
+
+QString JavaCodeMarker::markedUpFullName(const Node *node, const Node * /* relative */ )
+{
+ QString fullName;
+ for ( ;; ) {
+ fullName.prepend( markedUpName(node) );
+ if ( node->parent()->name().isEmpty() )
+ break;
+ node = node->parent();
+ fullName.prepend( "." );
+ }
+ return fullName;
+}
+
+QString JavaCodeMarker::markedUpEnumValue(const QString &enumValue,
+ const Node * /* relative */)
+{
+ return protect(enumValue);
+}
+
+QString JavaCodeMarker::markedUpIncludes( const QStringList& /* includes */ )
+{
+ return QString();
+}
+
+QString JavaCodeMarker::functionBeginRegExp( const QString& /* funcName */)
+{
+ return "^x$"; // ### invalid regexp
+}
+
+QString JavaCodeMarker::functionEndRegExp( const QString& /* funcName */ )
+{
+ return "^}";
+}
+
+QList<Section> JavaCodeMarker::sections(const InnerNode * /* inner */, SynopsisStyle /* style */,
+ Status /* status */)
+{
+ return QList<Section>();
+}
+
+const Node *JavaCodeMarker::resolveTarget(const QString &target, const Tree *tree,
+ const Node *relative)
+{
+ if (target.endsWith("()")) {
+ const FunctionNode *func;
+ QString funcName = target;
+ funcName.chop(2);
+
+ QStringList path = funcName.split('.');
+ if ((func = tree->findFunctionNode(path, relative, Tree::SearchBaseClasses)))
+ return func;
+ } else if (target.contains("#")) {
+ int hashAt = target.indexOf("#");
+ QString link = target.left(hashAt);
+ QString ref = target.mid(hashAt + 1);
+ const Node *node;
+ if (link.isEmpty()) {
+ node = relative;
+ } else {
+ QStringList path(link);
+ node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses);
+ }
+ if (node && node->isInnerNode()) {
+ const Atom *atom = node->doc().body().firstAtom();
+ while (atom) {
+ if (atom->type() == Atom::Target && atom->string() == ref) {
+ Node *parentNode = const_cast<Node *>(node);
+ return new TargetNode(static_cast<InnerNode*>(parentNode),
+ ref);
+ }
+ atom = atom->next();
+ }
+ }
+ } else {
+ QStringList path = target.split('.');
+ const Node *node;
+ if ((node = tree->findNode(path, relative,
+ Tree::SearchBaseClasses | Tree::SearchEnumValues)))
+ return node;
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/javacodemarker.h b/tools/qdoc3/javacodemarker.h
new file mode 100644
index 0000000000..3381fc3759
--- /dev/null
+++ b/tools/qdoc3/javacodemarker.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ javacodemarker.h
+*/
+
+#ifndef JAVACODEMARKER_H
+#define JAVACODEMARKER_H
+
+#include "codemarker.h"
+
+QT_BEGIN_NAMESPACE
+
+class JavaCodeMarker : public CodeMarker
+{
+public:
+ JavaCodeMarker();
+ ~JavaCodeMarker();
+
+ bool recognizeCode( const QString& code );
+ bool recognizeExtension( const QString& ext );
+ bool recognizeLanguage( const QString& lang );
+ QString plainName(const Node *node);
+ QString plainFullName(const Node *node, const Node *relative);
+ QString markedUpCode( const QString& code, const Node *relative,
+ const QString& dirPath );
+ QString markedUpSynopsis( const Node *node, const Node *relative,
+ SynopsisStyle style );
+ QString markedUpName( const Node *node );
+ QString markedUpFullName( const Node *node, const Node *relative );
+ QString markedUpEnumValue(const QString &enumValue, const Node *relative);
+ QString markedUpIncludes( const QStringList& includes );
+ QList<Section> sections(const InnerNode *innerNode, SynopsisStyle style, Status status);
+ QString functionBeginRegExp( const QString& funcName );
+ QString functionEndRegExp( const QString& funcName );
+ const Node *resolveTarget( const QString& target, const Tree *tree, const Node *relative );
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/javadocgenerator.cpp b/tools/qdoc3/javadocgenerator.cpp
new file mode 100644
index 0000000000..872699de89
--- /dev/null
+++ b/tools/qdoc3/javadocgenerator.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "javadocgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+enum JavaSignatureSyntax {
+ GeneratedJdocFile,
+ JavadocRef,
+ SlotSignature
+};
+
+static QString javaSignature(const FunctionNode *func, JavaSignatureSyntax syntax,
+ int maxParams = 65535)
+{
+ maxParams = qMin(maxParams, func->parameters().count());
+
+ QString result;
+
+ if (syntax == GeneratedJdocFile) {
+ if (func->access() == Node::Public) {
+ result += "public ";
+ } else if (func->access() == Node::Protected) {
+ result += "protected ";
+ } else {
+ result += "private ";
+ }
+
+ if (func->metaness() == FunctionNode::Native)
+ result += "native ";
+
+ if (func->isConst())
+ result += "final ";
+
+ // ### func->metaness() == FunctionNode::Abstract
+
+ if (func->isStatic())
+ result += "static ";
+
+ if (!func->returnType().isEmpty()) {
+ result += func->returnType();
+ result += ' ';
+ }
+ }
+
+ if (syntax == SlotSignature) {
+ result += "void mySlot";
+ } else {
+ result += func->name();
+ }
+ result += '(';
+ for (int i = 0; i < maxParams; ++i) {
+ if (i != 0)
+ result += ", ";
+ result += func->parameters().at(i).leftType();
+ if (syntax != JavadocRef) {
+ result += ' ';
+ result += func->parameters().at(i).name();
+ }
+ }
+ result += ')';
+
+ return result;
+}
+
+static QString packageName(const Node *node)
+{
+ while (node && node->type() != Node::Class && node->type() != Node::Fake)
+ node = node->parent();
+ if (!node)
+ return QString();
+ return node->moduleName();
+}
+
+JavadocGenerator::JavadocGenerator()
+ : oldDevice(0), currentDepth(0)
+{
+}
+
+JavadocGenerator::~JavadocGenerator()
+{
+}
+
+void JavadocGenerator::initializeGenerator(const Config &config)
+{
+ HtmlGenerator::initializeGenerator(config);
+
+ formattingLeftMap().insert(ATOM_FORMATTING_PARAMETER,
+ formattingLeftMap().value(ATOM_FORMATTING_TELETYPE));
+ formattingRightMap().insert(ATOM_FORMATTING_PARAMETER,
+ formattingRightMap().value(ATOM_FORMATTING_TELETYPE));
+}
+
+void JavadocGenerator::terminateGenerator()
+{
+ HtmlGenerator::terminateGenerator();
+}
+
+QString JavadocGenerator::format()
+{
+ return "javadoc";
+}
+
+void JavadocGenerator::generateTree(const Tree *tree, CodeMarker *marker)
+{
+ HtmlGenerator::generateTree(tree, marker);
+}
+
+QString JavadocGenerator::fileExtension(const Node *node)
+{
+ if (node->type() == Node::Fake) {
+ return "html";
+ } else {
+ return "jdoc";
+ }
+}
+
+QString JavadocGenerator::typeString(const Node *node)
+{
+ if (node->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+ return func->metaness() == FunctionNode::Signal ? "signal" : "method";
+ } else {
+ return HtmlGenerator::typeString(node);
+ }
+}
+
+QString JavadocGenerator::imageFileName(const Node *relative, const QString& fileBase)
+{
+ QString result = HtmlGenerator::imageFileName(relative, fileBase);
+ if (!result.isEmpty()) {
+ QString package = packageName(relative);
+ int numSubPackages = package.count('.') - 2;
+ while (numSubPackages > 0) {
+ result.prepend("%2E%2E/"); // javadoc 1.5.0_06 chokes on '../'
+ --numSubPackages;
+ }
+ }
+ return result;
+}
+
+static int textDepth = 0;
+
+void JavadocGenerator::startText(const Node *relative, CodeMarker *marker)
+{
+ if (textDepth++ == 0 && relative->type() != Node::Fake) {
+ Q_ASSERT(!oldDevice);
+ oldDevice = out().device();
+ Q_ASSERT(oldDevice);
+ out().setString(&buffer);
+ }
+ HtmlGenerator::startText(relative, marker);
+}
+
+void JavadocGenerator::endText(const Node *relative, CodeMarker *marker)
+{
+ HtmlGenerator::endText(relative, marker);
+ if (--textDepth == 0 && relative->type() != Node::Fake) {
+ Q_ASSERT(oldDevice);
+ out().setDevice(oldDevice);
+ oldDevice = 0;
+
+ /*
+ Need to escape XML metacharacters in .jdoc files.
+ */
+ buffer.replace("*/", "*&lt;!-- noop --&gt;/");
+ buffer.replace("&", "&amp;");
+ buffer.replace("\"", "&quot;");
+ buffer.replace("<", "&lt;");
+ buffer.replace(">", "&gt;");
+ out() << buffer;
+ buffer.clear();
+ }
+}
+
+int JavadocGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker)
+{
+ return HtmlGenerator::generateAtom(atom, relative, marker);
+}
+
+void JavadocGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker)
+{
+ generateIndent();
+ out() << "<class name=\"" << protect(inner->name()) << "\"";
+ generateDoc(inner, marker);
+ out() << ">\n";
+
+ ++currentDepth;
+ foreach (Node *node, inner->childNodes()) {
+ if (node->isInnerNode()) {
+ generateClassLikeNode(static_cast<InnerNode *>(node), marker);
+ } else {
+ if (node->type() == Node::Enum) {
+ EnumNode *enume = static_cast<EnumNode *>(node);
+
+ generateIndent();
+ out() << "<enum name=\"" << protect(node->name()) << "\"";
+ generateDoc(node, marker);
+ out() << ">\n";
+
+ ++currentDepth;
+ const QList<EnumItem> &items = enume->items();
+ for (int i = 0; i < items.count(); ++i) {
+ const EnumItem &item = items.at(i);
+ generateIndent();
+ out() << "<enum-value name=\"" << protect(item.name()) << "\"";
+ generateEnumItemDoc(item.text(), enume, marker);
+ out() << "/>\n";
+ }
+ --currentDepth;
+
+ out() << "</enum>\n";
+ } else if (node->type() == Node::Function) {
+ FunctionNode *func = static_cast<FunctionNode *>(node);
+ generateIndent();
+ out() << (func->metaness() == FunctionNode::Signal ? "<signal" : "<method")
+ << " name=\""
+ << protect(javaSignature(func, GeneratedJdocFile))
+ << "\"";
+ generateDoc(node, marker);
+ out() << "/>\n";
+ }
+ }
+ }
+ --currentDepth;
+
+ generateIndent();
+ out() << "</class>\n";
+}
+
+void JavadocGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
+{
+ HtmlGenerator::generateFakeNode(fake, marker);
+}
+
+void JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker)
+{
+ HtmlGenerator::generateText(text, relative, marker);
+}
+
+void JavadocGenerator::generateBody(const Node *node, CodeMarker *marker)
+{
+ generateText(node->doc().body(), node, marker);
+}
+
+void JavadocGenerator::generateAlsoList( const Node *node, CodeMarker *marker )
+{
+ QList<Text> alsoList = node->doc().alsoList();
+ supplementAlsoList(node, alsoList);
+
+ if (node->type() == Node::Fake
+ || (node->type() == Node::Function
+ && static_cast<const FunctionNode *>(node)->metaness() == FunctionNode::Signal)) {
+ Text text;
+
+ if (!alsoList.isEmpty()) {
+ text << Atom(Atom::ListLeft, ATOM_LIST_TAG)
+ << Atom(Atom::ListTagLeft, ATOM_LIST_TAG)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "See Also:"
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << Atom(Atom::ListTagRight, ATOM_LIST_TAG)
+ << Atom(Atom::ListItemLeft, ATOM_LIST_TAG);
+
+ for (int i = 0; i < alsoList.count(); ++i) {
+ if (i != 0)
+ text << ", ";
+ text << alsoList.at(i);
+ }
+ text << Atom(Atom::ListItemRight, ATOM_LIST_TAG)
+ << Atom(Atom::ListRight, ATOM_LIST_TAG);
+ }
+
+ generateText(text, node, marker);
+ } else {
+ foreach (const Text &text, alsoList) {
+ out() << "\n@see ";
+ generateText(text, node, marker);
+ }
+ }
+}
+
+QString JavadocGenerator::refForNode( const Node *node )
+{
+ if (node->type() == Node::Function)
+ return javaSignature(static_cast<const FunctionNode *>(node), JavadocRef);
+
+ return HtmlGenerator::refForNode(node);
+}
+
+QString JavadocGenerator::linkForNode( const Node *node, const Node *relative )
+{
+ // ### EVIL, relative should never be null
+ if (!relative)
+ relative = node;
+
+ if (packageName(node).isEmpty()) {
+ // ### jasmin: Fixme
+ return QString();
+ }
+
+ QString result;
+ if (node->type() == Node::Fake) {
+ result = node->name();
+ } else {
+ if (!node->isInnerNode()) {
+ result = linkForNode(node->parent(), relative) + "#" + refForNode(node);
+ } else {
+ result = node->name() + ".html";
+ }
+ }
+
+ QStringList nodePackage = packageName(node).split(".");
+ QStringList relativePackage = packageName(relative).split(".");
+ if (nodePackage == QStringList(QString()) || relativePackage == QStringList(QString())) {
+ qWarning("I'm in trouble [%s][%s]", qPrintable(node->name()), qPrintable(relative->name()));
+ return QString();
+ }
+
+ int i = nodePackage.count() - 1;
+ while (nodePackage.value(i) != relativePackage.value(i)) {
+ result.prepend(nodePackage.at(i) + "/");
+ --i;
+ }
+
+ ++i;
+ while (i < relativePackage.count()) {
+ result.prepend("%2E%2E/"); // javadoc 1.5.0_06 chokes on '../'
+ ++i;
+ }
+
+ return result;
+}
+
+QString JavadocGenerator::refForAtom(Atom *atom, const Node *node)
+{
+ return HtmlGenerator::refForAtom(atom, node);
+}
+
+/*
+ Neutralize dumb functions called from HtmlGenerator.
+*/
+void JavadocGenerator::generateDcf(const QString & /* fileBase */, const QString & /* startPage */,
+ const QString & /* title */, DcfSection & /* dcfRoot */)
+{
+}
+
+void JavadocGenerator::generateIndex(const QString & /* fileBase */, const QString & /* url */,
+ const QString & /* title */)
+{
+}
+
+void JavadocGenerator::generateIndent()
+{
+ for (int i = 0; i < currentDepth; ++i)
+ out() << " ";
+}
+
+void JavadocGenerator::generateDoc(const Node *node, CodeMarker *marker)
+{
+ const Text &text = node->doc().body();
+ if (!text.isEmpty()) {
+ out() << " doc=\"/**\n";
+ Generator::generateStatus(node, marker);
+ generateText(text, node, marker);
+ if (node && node->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+ if (func->metaness() == FunctionNode::Signal) {
+ QStringList slotSignatures;
+ for (int i = func->parameters().count(); i >= 0; --i)
+ slotSignatures += javaSignature(func, SlotSignature, i);
+
+ Text text;
+
+ text << Atom(Atom::ListLeft, ATOM_LIST_TAG)
+ << Atom(Atom::ListTagLeft, ATOM_LIST_TAG)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD);
+
+ if (slotSignatures.count() == 1) {
+ text << "Compatible Slot Signature:";
+ } else {
+ text << "Compatible Slot Signatures:";
+ }
+
+ text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << Atom(Atom::ListTagRight, ATOM_LIST_TAG);
+
+ for (int i = 0; i < slotSignatures.count(); ++i) {
+ text << Atom(Atom::ListItemLeft, ATOM_LIST_TAG)
+ << Atom(Atom::C, marker->markedUpCode(slotSignatures.at(i), 0, ""))
+ << Atom(Atom::ListItemRight, ATOM_LIST_TAG);
+ }
+ text << Atom(Atom::ListRight, ATOM_LIST_TAG);
+ generateText(text, node, marker);
+ }
+ }
+ if (node)
+ generateAlsoList(node, marker);
+ out() << " */\"";
+ }
+}
+
+void JavadocGenerator::generateEnumItemDoc(const Text &text, const Node *node, CodeMarker *marker)
+{
+ out() << " doc=\"/**\n";
+ if (text.isEmpty()) {
+ out() << "Internal.";
+ } else {
+ generateText(text, node, marker);
+ }
+ out() << " */\"";
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/javadocgenerator.h b/tools/qdoc3/javadocgenerator.h
new file mode 100644
index 0000000000..aac938ed93
--- /dev/null
+++ b/tools/qdoc3/javadocgenerator.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef JAVADOCGENERATOR_H
+#define JAVADOCGENERATOR_H
+
+#include "htmlgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+class JavadocGenerator : public HtmlGenerator
+{
+public:
+ JavadocGenerator();
+ ~JavadocGenerator();
+
+ void initializeGenerator(const Config &config);
+ void terminateGenerator();
+ QString format();
+ bool canHandleFormat(const QString &format) { return format == "HTML" || format == "javadoc"; }
+ void generateTree(const Tree *tree, CodeMarker *marker);
+ QString typeString(const Node *node);
+ QString imageFileName(const Node *relative, const QString &fileBase);
+
+protected:
+ QString fileExtension(const Node *node);
+ void startText( const Node *relative, CodeMarker *marker );
+ void endText( const Node *relative, CodeMarker *marker );
+ int generateAtom( const Atom *atom, const Node *relative, CodeMarker *marker );
+ void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
+ void generateFakeNode( const FakeNode *fake, CodeMarker *marker );
+
+ void generateText( const Text& text, const Node *relative, CodeMarker *marker );
+ void generateBody( const Node *node, CodeMarker *marker );
+ void generateAlsoList( const Node *node, CodeMarker *marker );
+
+ QString refForNode( const Node *node );
+ QString linkForNode( const Node *node, const Node *relative );
+ QString refForAtom(Atom *atom, const Node *node);
+
+private:
+ void generateDcf(const QString &fileBase, const QString &startPage,
+ const QString &title, DcfSection &dcfRoot);
+ void generateIndex(const QString &fileBase, const QString &url,
+ const QString &title);
+ void generateIndent();
+ void generateDoc(const Node *node, CodeMarker *marker);
+ void generateEnumItemDoc(const Text &text, const Node *node, CodeMarker *marker);
+
+ QString buffer;
+ QIODevice *oldDevice;
+ int currentDepth;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/linguistgenerator.cpp b/tools/qdoc3/linguistgenerator.cpp
new file mode 100644
index 0000000000..1350654824
--- /dev/null
+++ b/tools/qdoc3/linguistgenerator.cpp
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ linguistgenerator.cpp
+*/
+
+#include "codemarker.h"
+#include "pagegenerator.h"
+#include "linguistgenerator.h"
+#include "node.h"
+#include "separator.h"
+#include "tree.h"
+#include <ctype.h>
+
+#include <qlist.h>
+#include <qiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+#define COMMAND_VERSION Doc::alias("version")
+
+LinguistGenerator::LinguistGenerator()
+ : PageGenerator()
+{
+}
+
+LinguistGenerator::~LinguistGenerator()
+{
+}
+
+void LinguistGenerator::initializeGenerator(const Config &config)
+{
+ Generator::initializeGenerator(config);
+}
+
+void LinguistGenerator::terminateGenerator()
+{
+ PageGenerator::terminateGenerator();
+}
+
+QString LinguistGenerator::format()
+{
+ return "Linguist";
+}
+
+QString LinguistGenerator::fileExtension(const Node * /* node */)
+{
+ return "ts";
+}
+
+void LinguistGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker)
+{
+ out().setCodec("utf-8");
+
+ QDomDocument document("TS");
+ QDomElement documentElement = document.createElement("TS");
+ documentElement.setAttribute("version", "1.1");
+
+ QList<QDomElement> contextElements = generateIndexSections(document, inner, marker);
+ foreach (const QDomElement &element, contextElements)
+ documentElement.appendChild(element);
+
+ QDomProcessingInstruction process = document.createProcessingInstruction(
+ "xml", QString("version=\"1.0\" encoding=\"%1\"").arg("utf-8"));
+ document.appendChild(process);
+ document.appendChild(documentElement);
+
+ out() << document;
+ out().flush();
+}
+
+void LinguistGenerator::generateFakeNode( const FakeNode *fake, CodeMarker *marker )
+{
+ out().setCodec("utf-8");
+
+ QDomDocument document("TS");
+ QDomElement documentElement = document.createElement("TS");
+ documentElement.setAttribute("version", "1.1");
+
+ QList<QDomElement> contextElements = generateIndexSections(document, fake, marker);
+ foreach (const QDomElement &element, contextElements)
+ documentElement.appendChild(element);
+
+ QDomProcessingInstruction process = document.createProcessingInstruction(
+ "xml", QString("version=\"1.0\" encoding=\"%1\"").arg("utf-8"));
+ document.appendChild(process);
+ document.appendChild(documentElement);
+
+ out() << document;
+ out().flush();
+}
+
+QList<QDomElement> LinguistGenerator::generateIndexSections(
+ QDomDocument &document, const Node *node, CodeMarker *marker)
+{
+ QList<QDomElement> contexts;
+
+ if (node->isInnerNode()) {
+ const InnerNode *inner = static_cast<const InnerNode *>(node);
+
+ foreach (const Node *child, inner->childNodes()) {
+ // Recurse to generate a DOM element for this child node and all
+ // its children.
+ contexts += generateIndexSections(document, child, marker);
+ }
+/*
+ foreach (const Node *child, inner->relatedNodes()) {
+ QDomElement childElement = generateIndexSections(document, child, marker);
+ element.appendChild(childElement);
+ }
+*/
+ }
+
+ // Add documentation to this node if it exists.
+ if (!node->doc().isEmpty()) {
+
+ QString nodeName = fullName(node);
+ QString signature;
+
+ if (node->type() == Node::Function) {
+ QStringList pieces;
+ const FunctionNode *functionNode = static_cast<const FunctionNode*>(node);
+ foreach (const Parameter &parameter, functionNode->parameters()) {
+ QString typeString = parameter.leftType() + parameter.rightType();
+ if (typeString.split(" ").size() > 1)
+ pieces.append(typeString + parameter.name());
+ else
+ pieces.append(typeString + " " + parameter.name());
+ }
+ signature = "(" + pieces.join(", ") + ")";
+ }
+
+ QDomElement contextElement = document.createElement("context");
+ QDomElement nameElement = document.createElement("name");
+ nameElement.appendChild(document.createTextNode(nodeName + signature));
+ contextElement.appendChild(nameElement);
+
+ QDomElement messageElement = document.createElement("message");
+ contextElement.appendChild(messageElement);
+
+ QDomElement sourceElement = document.createElement("source");
+ QString sourceText = simplified(node->doc().source());
+ if (!signature.isEmpty() && signature != "()" && !sourceText.contains("\\fn"))
+ sourceText.prepend(QString("\\fn %1%2\n").arg(nodeName).arg(signature));
+ sourceElement.appendChild(document.createTextNode(sourceText));
+ messageElement.appendChild(sourceElement);
+
+ QDomElement translationElement = document.createElement("translation");
+ translationElement.setAttribute("type", "unfinished");
+ messageElement.appendChild(translationElement);
+
+ QDomElement locationElement = document.createElement("location");
+ locationElement.setAttribute("filename", node->doc().location().filePath());
+ locationElement.setAttribute("line", node->doc().location().lineNo());
+ messageElement.appendChild(locationElement);
+
+ contexts.append(contextElement);
+ }
+
+ return contexts;
+}
+
+QString LinguistGenerator::fullName(const Node *node) const
+{
+ if (!node)
+ return "";
+ else if (node->parent() && !node->parent()->name().isEmpty())
+ return fullName(node->parent()) + "::" + node->name();
+ else
+ return node->name();
+}
+
+QString LinguistGenerator::simplified(const QString &text) const
+{
+ QStringList lines = text.split("\n");
+
+ while (lines.size() > 0 && lines.first().trimmed().isEmpty())
+ lines.pop_front();
+
+ while (lines.size() > 0 && lines.last().trimmed().isEmpty())
+ lines.pop_back();
+
+ int min = 0;
+ bool set = false;
+ foreach (const QString &line, lines) {
+ int j = 0;
+ while (j < line.length()) {
+ if (line[j] != ' ')
+ break;
+ ++j;
+ }
+ if (j < line.length()) {
+ if (!set) {
+ min = j;
+ set = true;
+ } else
+ min = qMin(min, j);
+ }
+ }
+ for (int i = 0; i < lines.size(); ++i)
+ lines[i] = lines[i].mid(min);
+
+ return lines.join("\n");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/linguistgenerator.h b/tools/qdoc3/linguistgenerator.h
new file mode 100644
index 0000000000..cae7e33295
--- /dev/null
+++ b/tools/qdoc3/linguistgenerator.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ LinguistGenerator.h
+*/
+
+#ifndef LINGUISTGENERATOR_H
+#define LINGUISTGENERATOR_H
+
+#include <qmap.h>
+#include <qregexp.h>
+#include <qdom.h>
+
+#include "codemarker.h"
+#include "config.h"
+#include "pagegenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+class LinguistGenerator : public PageGenerator
+{
+public:
+ LinguistGenerator();
+ ~LinguistGenerator();
+
+ virtual void initializeGenerator( const Config& config );
+ virtual void terminateGenerator();
+ virtual QString format();
+
+protected:
+ virtual void generateClassLikeNode(const InnerNode *inner,
+ CodeMarker *marker);
+ virtual void generateFakeNode( const FakeNode *fake, CodeMarker *marker );
+ virtual QString fileExtension(const Node *node);
+
+ QList<QDomElement> generateIndexSections(QDomDocument &document,
+ const Node *node, CodeMarker *marker);
+ virtual QString fullName(const Node *node) const;
+
+private:
+ QString simplified(const QString &text) const;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/location.cpp b/tools/qdoc3/location.cpp
new file mode 100644
index 0000000000..62a18f0da4
--- /dev/null
+++ b/tools/qdoc3/location.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDebug>
+#include "config.h"
+#include "location.h"
+
+#include <qregexp.h>
+#include <qtranslator.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+QT_STATIC_CONST_IMPL Location Location::null;
+
+int Location::tabSize;
+QString Location::programName;
+QRegExp *Location::spuriousRegExp = 0;
+
+/*!
+ \class Location
+
+ \brief The Location class keeps track of where we are in a file.
+
+ It maintains a stack of file positions. A file position
+ consists of the file path, line number, and column number.
+ The location is used for printing error messages that are
+ tied to a location in a file.
+ */
+
+/*!
+ Constructs an empty location.
+ */
+Location::Location()
+ : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
+{
+ // nothing.
+}
+
+/*!
+ Constructs a location with (fileName, 1, 1) on its file
+ position stack.
+ */
+Location::Location(const QString& fileName)
+ : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
+{
+ push(fileName);
+}
+
+/*!
+ The copy constructor copies the contents of \a other into
+ this Location using the assignment operator.
+ */
+Location::Location(const Location& other)
+ : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false)
+{
+ *this = other;
+}
+
+/*!
+ The assignment operator does a deep copy of the entire
+ state of \a other into this Location.
+ */
+Location& Location::operator=(const Location& other)
+{
+ QStack<StackEntry> *oldStk = stk;
+
+ stkBottom = other.stkBottom;
+ if (other.stk == 0) {
+ stk = 0;
+ stkTop = &stkBottom;
+ }
+ else {
+ stk = new QStack<StackEntry>(*other.stk);
+ stkTop = &stk->top();
+ }
+ stkDepth = other.stkDepth;
+ etcetera = other.etcetera;
+ delete oldStk;
+ return *this;
+}
+
+/*!
+ If the file position on top of the stack has a line number
+ less than 1, set its line number to 1 and its column number
+ to 1. Otherwise, do nothing.
+ */
+void Location::start()
+{
+ if (stkTop->lineNo < 1) {
+ stkTop->lineNo = 1;
+ stkTop->columnNo = 1;
+ }
+}
+
+/*!
+ Advance the current file position, using \a ch to decide how to do
+ that. If \a ch is a \c{'\\n'}, increment the current line number and
+ set the column number to 1. If \ch is a \c{'\\t'}, increment to the
+ next tab column. Otherwise, increment the column number by 1.
+
+ The current file position is the one on top of the position stack.
+ */
+void Location::advance(QChar ch)
+{
+ if (ch == QLatin1Char('\n')) {
+ stkTop->lineNo++;
+ stkTop->columnNo = 1;
+ }
+ else if (ch == QLatin1Char('\t')) {
+ stkTop->columnNo =
+ 1 + tabSize * (stkTop->columnNo + tabSize-1) / tabSize;
+ }
+ else {
+ stkTop->columnNo++;
+ }
+}
+
+/*!
+ Pushes \a filePath onto the file position stack. The current
+ file position becomes (\a filePath, 1, 1).
+
+ \sa pop()
+*/
+void Location::push(const QString& filePath)
+{
+ if (stkDepth++ >= 1) {
+ if (stk == 0)
+ stk = new QStack<StackEntry>;
+ stk->push(StackEntry());
+ stkTop = &stk->top();
+ }
+
+ stkTop->filePath = filePath;
+ stkTop->lineNo = INT_MIN;
+ stkTop->columnNo = 1;
+}
+
+/*!
+ Pops the top of the internal stack. The current file position
+ becomes the next one in the new top of stack.
+
+ \sa push()
+*/
+void Location::pop()
+{
+ if (--stkDepth == 0) {
+ stkBottom = StackEntry();
+ }
+ else {
+ stk->pop();
+ if (stk->isEmpty()) {
+ delete stk;
+ stk = 0;
+ stkTop = &stkBottom;
+ }
+ else {
+ stkTop = &stk->top();
+ }
+ }
+}
+
+/*! \fn bool Location::isEmpty() const
+
+ Returns true if there is no file name set yet; returns false
+ otherwise. The functions filePath(), lineNo() and columnNo()
+ must not be called on an empty Location object.
+ */
+
+/*! \fn const QString& Location::filePath() const
+ Returns the current path and file name.
+ Must not be called on an empty Location object.
+
+ \sa lineNo(), columnNo()
+ */
+
+/*!
+ Returns the file name part of the file path, ie the
+ current file. Must not be called on an empty Location
+ object.
+ */
+QString Location::fileName() const
+{
+ QString fp = filePath();
+ return fp.mid(fp.lastIndexOf('/') + 1);
+}
+
+/*! \fn int Location::lineNo() const
+ Returns the current line number.
+ Must not be called on an empty Location object.
+
+ \sa filePath(), columnNo()
+*/
+
+/*! \fn int Location::columnNo() const
+ Returns the current column number.
+ Must not be called on an empty Location object.
+
+ \sa filePath(), lineNo()
+*/
+
+/*!
+ Writes \a message and \a detals to stderr as a formatted
+ warning message.
+ */
+void Location::warning(const QString& message, const QString& details) const
+{
+ emitMessage(Warning, message, details);
+}
+
+/*!
+ Writes \a message and \a detals to stderr as a formatted
+ error message.
+ */
+void Location::error(const QString& message, const QString& details) const
+{
+ emitMessage(Error, message, details);
+}
+
+/*!
+ Writes \a message and \a detals to stderr as a formatted
+ error message and then exits the program.
+ */
+void Location::fatal(const QString& message, const QString& details) const
+{
+ emitMessage(Error, message, details);
+ information("Aborting");
+ exit(EXIT_FAILURE);
+}
+
+/*!
+ Gets several parameters from the \a config, including
+ tab size, program name, and a regular expression that
+ appears to be used for matching certain error messages
+ so that emitMessage() can avoid printing them.
+ */
+void Location::initialize(const Config& config)
+{
+ tabSize = config.getInt(CONFIG_TABSIZE);
+ programName = config.programName();
+
+ QRegExp regExp = config.getRegExp(CONFIG_SPURIOUS);
+ if (regExp.isValid()) {
+ spuriousRegExp = new QRegExp(regExp);
+ }
+ else {
+ config.lastLocation().warning(tr("Invalid regular expression '%1'")
+ .arg(regExp.pattern()));
+ }
+}
+
+/*!
+ Apparently, all this does is delete the regular expression
+ used for intercepting certain error messages that should
+ not be emitted by emitMessage().
+ */
+void Location::terminate()
+{
+ delete spuriousRegExp;
+ spuriousRegExp = 0;
+}
+
+/*!
+ Prints \a message to \c stdout followed by a \c{'\n'}.
+ */
+void Location::information(const QString& message)
+{
+ printf("%s\n", message.toLatin1().data());
+ fflush(stdout);
+}
+
+/*!
+ Report a program bug, including the \a hint.
+ */
+void Location::internalError(const QString& hint)
+{
+ Location::null.fatal(tr("Internal error (%1)").arg(hint),
+ tr("There is a bug in %1. Seek advice from your local"
+ " %2 guru.")
+ .arg(programName).arg(programName));
+}
+
+/*!
+ Formats \a message and \a details into a single string
+ and outputs that string to \c stderr. \a type specifies
+ whether the \a message is an error or a warning.
+ */
+void Location::emitMessage(MessageType type,
+ const QString& message,
+ const QString& details) const
+{
+ if (type == Warning &&
+ spuriousRegExp != 0 &&
+ spuriousRegExp->exactMatch(message))
+ return;
+
+ QString result = message;
+ if (!details.isEmpty())
+ result += "\n[" + details + "]";
+ result.replace("\n", "\n ");
+ if (type == Error)
+ result.prepend(tr("error: "));
+ result.prepend(toString());
+ fprintf(stderr, "%s\n", result.toLatin1().data());
+ fflush(stderr);
+}
+
+/*!
+ Converts the location to a string to be prepended to error
+ messages.
+ */
+QString Location::toString() const
+{
+ QString str;
+
+ if (isEmpty()) {
+ str = programName;
+ }
+ else {
+ Location loc2 = *this;
+ loc2.setEtc(false);
+ loc2.pop();
+ if (!loc2.isEmpty()) {
+ QString blah = tr("In file included from ");
+ for (;;) {
+ str += blah;
+ str += loc2.top();
+ loc2.pop();
+ if (loc2.isEmpty())
+ break;
+ str += tr(",");
+ str += QLatin1Char('\n');
+ blah.fill(' ');
+ }
+ str += tr(":");
+ str += QLatin1Char('\n');
+ }
+ str += top();
+ }
+ str += QLatin1String(": ");
+ return str;
+}
+
+QString Location::top() const
+{
+ QString str = filePath();
+ if (lineNo() >= 1) {
+ str += QLatin1Char(':');
+ str += QString::number(lineNo());
+#if 0
+ if (columnNo() >= 1)
+ str += ":" + QString::number(columnNo());
+#endif
+ }
+ if (etc())
+ str += QLatin1String(" (etc.)");
+ return str;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/location.h b/tools/qdoc3/location.h
new file mode 100644
index 0000000000..d8f3106b89
--- /dev/null
+++ b/tools/qdoc3/location.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ location.h
+*/
+
+#ifndef LOCATION_H
+#define LOCATION_H
+
+#include <qstack.h>
+
+#include "tr.h"
+
+#define QDOC_QML
+
+QT_BEGIN_NAMESPACE
+
+class Config;
+class QRegExp;
+
+class Location
+{
+ public:
+ Location();
+ Location(const QString& filePath);
+ Location(const Location& other);
+ ~Location() { delete stk; }
+
+ Location& operator=(const Location& other);
+
+ void start();
+ void advance(QChar ch);
+ void advanceLines(int n) { stkTop->lineNo += n; stkTop->columnNo = 1; }
+
+ void push(const QString& filePath);
+ void pop();
+ void setEtc(bool etc) { etcetera = etc; }
+ void setLineNo(int no) { stkTop->lineNo = no; }
+ void setColumnNo(int no) { stkTop->columnNo = no; }
+
+ bool isEmpty() const { return stkDepth == 0; }
+ int depth() const { return stkDepth; }
+ const QString& filePath() const { return stkTop->filePath; }
+ QString fileName() const;
+ int lineNo() const { return stkTop->lineNo; }
+ int columnNo() const { return stkTop->columnNo; }
+ bool etc() const { return etcetera; }
+ void warning(const QString& message,
+ const QString& details = QString()) const;
+ void error(const QString& message,
+ const QString& details = QString()) const;
+ void fatal(const QString& message,
+ const QString& details = QString()) const;
+
+ QT_STATIC_CONST Location null;
+
+ static void initialize(const Config& config);
+ static void terminate();
+ static void information(const QString& message);
+ static void internalError(const QString& hint);
+
+ private:
+ enum MessageType { Warning, Error };
+
+ struct StackEntry
+ {
+ QString filePath;
+ int lineNo;
+ int columnNo;
+ };
+
+ void emitMessage(MessageType type,
+ const QString& message,
+ const QString& details) const;
+ QString toString() const;
+ QString top() const;
+
+ private:
+ StackEntry stkBottom;
+ QStack<StackEntry> *stk;
+ StackEntry *stkTop;
+ int stkDepth;
+ bool etcetera;
+
+ static int tabSize;
+ static QString programName;
+ static QRegExp *spuriousRegExp;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/loutgenerator.cpp b/tools/qdoc3/loutgenerator.cpp
new file mode 100644
index 0000000000..0d1f6465c4
--- /dev/null
+++ b/tools/qdoc3/loutgenerator.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ loutgenerator.cpp
+*/
+
+#include "loutgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+LoutGenerator::LoutGenerator()
+{
+}
+
+LoutGenerator::~LoutGenerator()
+{
+}
+
+QString LoutGenerator::format()
+{
+ return "lout";
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/loutgenerator.h b/tools/qdoc3/loutgenerator.h
new file mode 100644
index 0000000000..0d6f5f1b49
--- /dev/null
+++ b/tools/qdoc3/loutgenerator.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ loutgenerator.h
+*/
+
+#ifndef LOUTGENERATOR_H
+#define LOUTGENERATOR_H
+
+#include "bookgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+class LoutGenerator : public BookGenerator
+{
+public:
+ LoutGenerator();
+ ~LoutGenerator();
+
+ virtual QString format();
+
+protected:
+ // ###
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/main.cpp b/tools/qdoc3/main.cpp
new file mode 100644
index 0000000000..3e6f832652
--- /dev/null
+++ b/tools/qdoc3/main.cpp
@@ -0,0 +1,496 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ main.cpp
+*/
+
+#include <QtCore>
+#include <stdlib.h>
+#include "apigenerator.h"
+#include "codemarker.h"
+#include "codeparser.h"
+#include "config.h"
+#include "cppcodemarker.h"
+#include "cppcodeparser.h"
+#include "cpptoqsconverter.h"
+#include "doc.h"
+#include "htmlgenerator.h"
+#include "jambiapiparser.h"
+#include "javacodemarker.h"
+#include "javadocgenerator.h"
+#include "linguistgenerator.h"
+#include "loutgenerator.h"
+#include "mangenerator.h"
+#include "plaincodemarker.h"
+#include "polyarchiveextractor.h"
+#include "polyuncompressor.h"
+#include "qsakernelparser.h"
+#include "qscodemarker.h"
+#include "qscodeparser.h"
+#include "sgmlgenerator.h"
+#include "webxmlgenerator.h"
+#include "tokenizer.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ The default indent for code is 4.
+ The default value for false is 0.
+ The default language is c++.
+ The default output format is html.
+ The default tab size is 8.
+ And those are all the default values for configuration variables.
+ */
+static const struct {
+ const char *key;
+ const char *value;
+} defaults[] = {
+ { CONFIG_CODEINDENT, "4" },
+ { CONFIG_FALSEHOODS, "0" },
+ { CONFIG_LANGUAGE, "Cpp" },
+ { CONFIG_OUTPUTFORMATS, "HTML" },
+ { CONFIG_TABSIZE, "8" },
+ { 0, 0 }
+};
+
+static bool slow = false;
+static QStringList defines;
+static QHash<QString, Tree *> trees;
+
+//static int doxygen = 0;
+
+/*!
+ Find the Tree for language \a lang and return a pointer to it.
+ If there is no Tree for language \a lang in the Tree table, add
+ a new one. The Tree table is indexed by \a lang strings.
+ */
+static Tree* treeForLanguage(const QString &lang)
+{
+ Tree* tree = trees.value(lang);
+ if (tree == 0) {
+ tree = new Tree;
+ trees.insert( lang, tree );
+ }
+ return tree;
+}
+
+/*!
+ Print the help message to \c stdout.
+ */
+static void printHelp()
+{
+ Location::information(tr("Usage: qdoc [options] file1.qdocconf ...\n"
+ "Options:\n"
+ " -help "
+ "Display this information and exit\n"
+ " -version "
+ "Display version of qdoc and exit\n"
+ " -D<name> "
+ "Define <name> as a macro while parsing sources\n"
+ " -slow "
+ "Turn on features that slow down qdoc") );
+}
+
+/*!
+ Prints the qdoc version number to stdout.
+ */
+static void printVersion()
+{
+ Location::information(tr("qdoc version 4.4.1"));
+}
+
+/*!
+ Processes the qdoc config file \a fileName. This is the
+ controller for all of qdoc.
+ */
+static void processQdocconfFile(const QString &fileName)
+{
+ QList<QTranslator *> translators;
+
+ /*
+ The Config instance represents the configuration data for qdoc.
+ All the other classes are initialized with the config. Here we
+ initialize the configuration with some default values.
+ */
+ Config config(tr("qdoc"));
+ int i = 0;
+ while (defaults[i].key) {
+ config.setStringList(defaults[i].key,
+ QStringList() << defaults[i].value);
+ ++i;
+ }
+ config.setStringList(CONFIG_SLOW, QStringList(slow ? "true" : "false"));
+
+ /*
+ With the default configuration values in place, load
+ the qdoc configuration file. Note that the configuration
+ file may include other configuration files.
+
+ The Location class keeps track of the current location
+ in the file being processed, mainly for error reporting
+ purposes.
+ */
+ Location::initialize(config);
+ config.load(fileName);
+
+ /*
+ Add the defines to the configuration variables.
+ */
+ QStringList defs = defines + config.getStringList(CONFIG_DEFINES);
+ config.setStringList(CONFIG_DEFINES,defs);
+ Location::terminate();
+
+ QString prevCurrentDir = QDir::currentPath();
+ QString dir = QFileInfo(fileName).path();
+ if (!dir.isEmpty())
+ QDir::setCurrent(dir);
+
+ /*
+ Initialize all the classes and data structures with the
+ qdoc configuration.
+ */
+ Location::initialize(config);
+ Tokenizer::initialize(config);
+ Doc::initialize(config);
+ CppToQsConverter::initialize(config);
+ CodeMarker::initialize(config);
+ CodeParser::initialize(config);
+ Generator::initialize(config);
+
+ /*
+ Load the language translators, if the configuration specifies any.
+ */
+ QStringList fileNames = config.getStringList(CONFIG_TRANSLATORS);
+ QStringList::Iterator fn = fileNames.begin();
+ while (fn != fileNames.end()) {
+ QTranslator *translator = new QTranslator(0);
+ if (!translator->load(*fn))
+ config.lastLocation().error(tr("Cannot load translator '%1'")
+ .arg(*fn));
+ QCoreApplication::instance()->installTranslator(translator);
+ translators.append(translator);
+ ++fn;
+ }
+
+ //QSet<QString> outputLanguages = config.getStringSet(CONFIG_OUTPUTLANGUAGES);
+
+ /*
+ Get the source language (Cpp) from the configuration
+ and the location in the configuration file where the
+ source language was set.
+ */
+ QString lang = config.getString(CONFIG_LANGUAGE);
+ Location langLocation = config.lastLocation();
+
+#ifdef QDOC2DOX
+ // qdoc -> doxygen
+ if (doxygen == 2) {
+ qDebug() << "READING anchors.txt";
+ DoxWriter::readAnchors();
+ qDebug() << "READING title maps";
+ DoxWriter::readTitles();
+ qDebug() << "READING member multimaps";
+ DoxWriter::readMembers();
+ }
+#endif
+
+ /*
+ Initialize the tree where all the parsed sources will be stored.
+ The tree gets built as the source files are parsed, and then the
+ documentation output is generated by traversing the tree.
+ */
+ Tree *tree = new Tree;
+ tree->setVersion(config.getString(CONFIG_VERSION));
+
+ /*
+ There must be a code parser for the source code language, e.g. C++.
+ If there isn't one, give up.
+ */
+ CodeParser *codeParser = CodeParser::parserForLanguage(lang);
+ if (codeParser == 0)
+ config.lastLocation().fatal(tr("Cannot parse programming language '%1'").arg(lang));
+
+ /*
+ By default, the only output format is HTML.
+ */
+ QSet<QString> outputFormats = config.getStringSet(CONFIG_OUTPUTFORMATS);
+ Location outputFormatsLocation = config.lastLocation();
+
+ /*
+ There must be a code marker for the source code language, e.g. C++.
+ If there isn't one, give up.
+ */
+ CodeMarker *marker = CodeMarker::markerForLanguage(lang);
+ if (!marker && !outputFormats.isEmpty())
+ langLocation.fatal(tr("Cannot output documentation for programming language '%1'").arg(lang));
+
+ /*
+ Read some XML indexes. What are they???
+ */
+ QStringList indexFiles = config.getStringList(CONFIG_INDEXES);
+ tree->readIndexes(indexFiles);
+
+ /*
+ Get all the header files: "*.ch *.h *.h++ *.hh *.hpp *.hxx"
+ Put them in a set.
+ */
+ QSet<QString> excludedDirs;
+ QStringList excludedDirsList = config.getStringList(CONFIG_EXCLUDEDIRS);
+ foreach (const QString &excludeDir, excludedDirsList)
+ excludedDirs.insert(QDir::fromNativeSeparators(excludeDir));
+ QSet<QString> headers = QSet<QString>::fromList(
+ config.getAllFiles(CONFIG_HEADERS, CONFIG_HEADERDIRS,
+ codeParser->headerFileNameFilter(),
+ excludedDirs));
+
+ /*
+ Parse each header file in the set and add it to the big tree.
+ */
+ QSet<QString>::ConstIterator h = headers.begin();
+ while (h != headers.end()) {
+ codeParser->parseHeaderFile(config.location(), *h, tree);
+ ++h;
+ }
+ codeParser->doneParsingHeaderFiles(tree);
+
+ /*
+ Get all the source text files: "*.cpp *.qdoc *.mm"
+ Put them in a set.
+ */
+ QSet<QString> sources = QSet<QString>::fromList(
+ config.getAllFiles(CONFIG_SOURCES, CONFIG_SOURCEDIRS,
+ codeParser->sourceFileNameFilter(),
+ excludedDirs));
+
+ /*
+ Parse each source text file in the set and add it to the big tree.
+ */
+ QSet<QString>::ConstIterator s = sources.begin();
+ while (s != sources.end()) {
+ codeParser->parseSourceFile(config.location(), *s, tree);
+ ++s;
+ }
+ codeParser->doneParsingSourceFiles(tree);
+
+ /*
+ Now the big tree has been built from all the header and
+ source files. Resolve all the class names, function names,
+ targets, URLs, links, and other stuff that needs resolving.
+ */
+ tree->resolveGroups();
+ tree->resolveTargets();
+
+#ifdef QDOC2DOX
+ // qdoc -> doxygen
+ if (doxygen == 1) {
+ DoxWriter::writeAnchors();
+ DoxWriter::writeTitles();
+ DoxWriter::writeMembers();
+ }
+
+ if (doxygen == 0) {
+#endif
+
+ /*
+ Now the tree has been built, and all the stuff that needed
+ resolving has been resolved. Now it is time to traverse
+ the big tree and generate the documentation output.
+ */
+ QSet<QString>::ConstIterator of = outputFormats.begin();
+ while (of != outputFormats.end()) {
+ Generator *generator = Generator::generatorForFormat(*of);
+ if (generator == 0)
+ outputFormatsLocation.fatal(tr("Unknown output format '%1'")
+ .arg(*of));
+ generator->generateTree(tree, marker);
+ ++of;
+ }
+
+ /*
+ Generate the XML tag file, if it was requested.
+ */
+ QString tagFile = config.getString(CONFIG_TAGFILE);
+ if (!tagFile.isEmpty())
+ tree->generateTagFile(tagFile);
+
+ tree->setVersion("");
+ Generator::terminate();
+
+#ifdef QDOC2DOX
+ }
+#endif
+
+ CodeParser::terminate();
+ CodeMarker::terminate();
+ CppToQsConverter::terminate();
+ Doc::terminate();
+ Tokenizer::terminate();
+ Location::terminate();
+ QDir::setCurrent(prevCurrentDir);
+
+ foreach (QTranslator *translator, translators)
+ delete translator;
+
+ delete tree;
+}
+
+QT_END_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ QT_USE_NAMESPACE
+
+ QCoreApplication app(argc, argv);
+ QString cf = "qsauncompress \1 \2";
+ PolyArchiveExtractor qsaExtractor(QStringList() << "qsa",cf);
+ cf = "tar -C \2 -xf \1";
+ PolyArchiveExtractor tarExtractor(QStringList() << "tar",cf);
+ cf = "tar -C \2 -Zxf \1";
+ PolyArchiveExtractor tazExtractor(QStringList() << "taz",cf);
+ cf = "tar -C \2 -jxf \1";
+ PolyArchiveExtractor tbz2Extractor(QStringList() << "tbz" << "tbz2",cf);
+ cf = "tar -C \2 -zxf \1";
+ PolyArchiveExtractor tgzExtractor(QStringList() << "tgz",cf);
+ cf = "unzip \1 -d \2";
+ PolyArchiveExtractor zipExtractor(QStringList() << "zip",cf);
+ cf = "bunzip2 -c \1 > \2";
+ PolyUncompressor bz2Uncompressor(QStringList() << "bz" << "bz2",cf);
+ cf = "gunzip -c \1 > \2";
+ PolyUncompressor gzAndZUncompressor(QStringList() << "gz" << "z" << "Z",cf);
+ cf = "unzip -c \1 > \2";
+ PolyUncompressor zipUncompressor(QStringList() << "zip",cf);
+
+ /*
+ Create code parsers for the languages to be parsed,
+ and create a tree for C++.
+ */
+ CppCodeParser cppParser;
+ Tree *cppTree = treeForLanguage(cppParser.language());
+
+ QsCodeParser qsParser(cppTree);
+ QsaKernelParser qsaKernelParser(cppTree);
+ JambiApiParser jambiParser(cppTree);
+
+ /*
+ Create code markers for plain text, C++, Java, and qs.
+ */
+ PlainCodeMarker plainMarker;
+ CppCodeMarker cppMarker;
+ JavaCodeMarker javaMarker;
+ QsCodeMarker qsMarker;
+
+ ApiGenerator apiGenerator;
+ HtmlGenerator htmlGenerator;
+ JavadocGenerator javadocGenerator;
+ LinguistGenerator linguistGenerator;
+ LoutGenerator loutGenerator;
+ ManGenerator manGenerator;
+ SgmlGenerator smglGenerator;
+ WebXMLGenerator webxmlGenerator;
+
+ QStringList qdocFiles;
+ QString opt;
+ int i = 1;
+
+ while (i < argc) {
+ opt = argv[i++];
+
+ if (opt == "-help") {
+ printHelp();
+ return EXIT_SUCCESS;
+ }
+ else if (opt == "-version") {
+ printVersion();
+ return EXIT_SUCCESS;
+ }
+ else if (opt == "--") {
+ while (i < argc)
+ qdocFiles.append(argv[i++]);
+ }
+ else if (opt.startsWith("-D")) {
+ QString define = opt.mid(2);
+ defines += define;
+ }
+ else if (opt == "-slow") {
+ slow = true;
+ }
+
+#ifdef QDOC2DOX
+ else if (opt == "-doxygen1") {
+ // qdoc -> doxygen
+ // Don't use this; it isn't ready yet.
+ // Now it's a fossil.
+ qDebug() << "doxygen pass 1";
+ doxygen = 1;
+ DoxWriter::setDoxPass(1);
+ }
+ else if (opt == "-doxygen2") {
+ // qdoc -> doxygen
+ // Don't use this; it isn't ready yet.
+ // Now it's a fossil.
+ qDebug() << "doxygen pass 2";
+ doxygen = 2;
+ DoxWriter::setDoxPass(2);
+ }
+#endif
+
+ else {
+ qdocFiles.append(opt);
+ }
+ }
+
+ if (qdocFiles.isEmpty()) {
+ printHelp();
+ return EXIT_FAILURE;
+ }
+
+ /*
+ Main loop.
+ */
+ foreach (QString qf, qdocFiles)
+ processQdocconfFile(qf);
+
+ qDeleteAll(trees);
+ return EXIT_SUCCESS;
+}
+
diff --git a/tools/qdoc3/mangenerator.cpp b/tools/qdoc3/mangenerator.cpp
new file mode 100644
index 0000000000..619a680834
--- /dev/null
+++ b/tools/qdoc3/mangenerator.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ mangenerator.cpp
+*/
+
+#include <qdatetime.h>
+#include <qregexp.h>
+
+#include "mangenerator.h"
+#include "node.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+ManGenerator::ManGenerator()
+{
+ date = QDate::currentDate().toString( "d MMMM yyyy" );
+}
+
+ManGenerator::~ManGenerator()
+{
+}
+
+QString ManGenerator::format()
+{
+ return "man";
+}
+
+int ManGenerator::generateAtom( const Atom *atom, const Node * /* relative */,
+ CodeMarker * /* marker */ )
+{
+#if 0
+ switch ( atom->type() ) {
+ case Atom::AbstractBegin:
+ break;
+ case Atom::AbstractEnd:
+ break;
+ case Atom::Alias:
+ break;
+ case Atom::AliasArg:
+ break;
+ case Atom::BaseName:
+ break;
+ case Atom::BriefBegin:
+ break;
+ case Atom::BriefEnd:
+ break;
+ case Atom::C:
+ break;
+ case Atom::CaptionBegin:
+ break;
+ case Atom::CaptionEnd:
+ break;
+ case Atom::CitationBegin:
+ break;
+ case Atom::CitationEnd:
+ break;
+ case Atom::Code:
+ break;
+ case Atom::FootnoteBegin:
+ break;
+ case Atom::FootnoteEnd:
+ break;
+ case Atom::FormatBegin:
+ break;
+ case Atom::FormatEnd:
+ break;
+ case Atom::GeneratedList:
+ break;
+ case Atom::Image:
+ break;
+ case Atom::ImageText:
+ break;
+ case Atom::Link:
+ break;
+ case Atom::LinkNode:
+ break;
+ case Atom::ListBegin:
+ break;
+ case Atom::ListItemNumber:
+ break;
+ case Atom::ListItemBegin:
+ out() << ".IP " << atom->string() << ".\n";
+ break;
+ case Atom::ListItemEnd:
+ break;
+ case Atom::ListEnd:
+ break;
+ case Atom::Nop:
+ break;
+ case Atom::ParaBegin:
+ out() << ".PP\n";
+ break;
+ case Atom::ParaEnd:
+ out() << "\n";
+ break;
+ case Atom::RawFormat:
+ break;
+ case Atom::RawString:
+ break;
+ case Atom::SectionBegin:
+ break;
+ case Atom::SectionEnd:
+ break;
+ case Atom::SectionHeadingBegin:
+ break;
+ case Atom::SectionHeadingEnd:
+ break;
+ case Atom::SidebarBegin:
+ break;
+ case Atom::SidebarEnd:
+ break;
+ case Atom::String:
+ out() << protectTextLine( atom->string() );
+ break;
+ case Atom::TableBegin:
+ break;
+ case Atom::TableEnd:
+ break;
+ case Atom::TableOfContents:
+ break;
+ case Atom::Target:
+ break;
+ case Atom::UnknownCommand:
+ ;
+ }
+#endif
+ unknownAtom( atom );
+ return 0;
+}
+
+void ManGenerator::generateClassLikeNode( const InnerNode *classe,
+ CodeMarker *marker )
+{
+ generateHeader( classe->name() );
+ out() << ".SH NAME\n"
+ << classe->name() << "\n"
+ << ".SH SYNOPSYS\n";
+ generateBody( classe, marker );
+ generateFooter();
+}
+
+void ManGenerator::generateFakeNode( const FakeNode *fake, CodeMarker *marker )
+{
+ generateHeader( "foo" );
+ generateBody( fake, marker );
+ generateFooter();
+}
+
+QString ManGenerator::fileExtension(const Node * /* node */)
+{
+ return "3qt";
+}
+
+void ManGenerator::generateHeader( const QString& name )
+{
+ out() << ".TH " << protectArg( name )
+ << " " << protectArg( "3qt" )
+ << " " << protectArg( date )
+ << " " << protectArg( "Nokia Corporation and/or its subsidiary(-ies)" )
+ << " " << protectArg( "Qt Toolkit" ) << "\n";
+}
+
+void ManGenerator::generateFooter()
+{
+}
+
+QString ManGenerator::protectArg( const QString& str )
+{
+ for ( int i = 0; i < (int) str.length(); i++ ) {
+ if ( str[i] == ' ' || str[i].isSpace() ) {
+ QString quoted = str;
+ quoted.replace( "\"", "\"\"" );
+ return "\"" + quoted + "\"";
+ }
+ }
+ return str;
+}
+
+QString ManGenerator::protectTextLine( const QString& str )
+{
+ QString t = str;
+ if ( t.startsWith(".") || t.startsWith("'") )
+ t.prepend( "\\&" );
+ return t;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/mangenerator.h b/tools/qdoc3/mangenerator.h
new file mode 100644
index 0000000000..0136c5d9f8
--- /dev/null
+++ b/tools/qdoc3/mangenerator.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ mangenerator.h
+*/
+
+#ifndef MANGENERATOR_H
+#define MANGENERATOR_H
+
+#include "pagegenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+class ManGenerator : public PageGenerator
+{
+public:
+ ManGenerator();
+ ~ManGenerator();
+
+ virtual QString format();
+
+protected:
+ virtual int generateAtom( const Atom *atom, const Node *relative,
+ CodeMarker *marker );
+ virtual void generateClassLikeNode(const InnerNode *node, CodeMarker *marker);
+ virtual void generateFakeNode( const FakeNode *fake, CodeMarker *marker );
+ virtual QString fileExtension(const Node *node);
+
+private:
+ void generateHeader( const QString& name );
+ void generateFooter();
+ QString protectArg( const QString& str );
+ QString protectTextLine( const QString& str );
+
+ QString date;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp
new file mode 100644
index 0000000000..231149e7b3
--- /dev/null
+++ b/tools/qdoc3/node.cpp
@@ -0,0 +1,1024 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ node.cpp
+*/
+
+#include "node.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class Node
+ \brief A node in a Tree.
+ */
+
+/*!
+ */
+Node::~Node()
+{
+ if (par)
+ par->removeChild(this);
+ if (rel)
+ rel->removeRelated(this);
+}
+
+/*!
+ */
+void Node::setDoc(const Doc& doc, bool replace)
+{
+ if (!d.isEmpty() && !replace) {
+ doc.location().warning(tr("Overrides a previous doc"));
+ d.location().warning(tr("(The previous doc is here)"));
+ }
+ d = doc;
+}
+
+/*!
+ */
+Node::Node(Type type, InnerNode *parent, const QString& name)
+ : typ(type),
+ acc(Public),
+ sta(Commendable),
+ saf(UnspecifiedSafeness),
+ par(parent),
+ rel(0),
+ nam(name)
+{
+ if (par)
+ par->addChild(this);
+}
+
+/*!
+ */
+QString Node::url() const
+{
+ return u;
+}
+
+/*!
+ */
+void Node::setUrl(const QString &url)
+{
+ u = url;
+}
+
+/*!
+ */
+void Node::setRelates(InnerNode *pseudoParent)
+{
+ if (rel)
+ rel->removeRelated(this);
+ rel = pseudoParent;
+ pseudoParent->related.append(this);
+}
+
+/*!
+ */
+void Node::setLink(LinkType linkType, const QString &link, const QString &desc)
+{
+ QPair<QString,QString> linkPair;
+ linkPair.first = link;
+ linkPair.second = desc;
+ linkMap[linkType] = linkPair;
+}
+
+/*!
+ */
+Node::Status Node::inheritedStatus() const
+{
+ Status parentStatus = Commendable;
+ if (par)
+ parentStatus = par->inheritedStatus();
+ return (Status)qMin((int)sta, (int)parentStatus);
+}
+
+/*!
+ */
+Node::ThreadSafeness Node::threadSafeness() const
+{
+ if (par && saf == par->inheritedThreadSafeness())
+ return UnspecifiedSafeness;
+ return saf;
+}
+
+/*!
+ */
+Node::ThreadSafeness Node::inheritedThreadSafeness() const
+{
+ if (par && saf == UnspecifiedSafeness)
+ return par->inheritedThreadSafeness();
+ return saf;
+}
+
+/*!
+ */
+QString Node::fileBase() const
+{
+ QString base = name();
+ if (base.endsWith(".html"))
+ base.chop(5);
+ base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
+ base = base.trimmed();
+ base.replace(" ", "-");
+ return base.toLower();
+}
+
+/*!
+ \class InnerNode
+ */
+
+/*!
+ */
+InnerNode::~InnerNode()
+{
+ deleteChildren();
+ removeFromRelated();
+}
+
+/*!
+ */
+Node *InnerNode::findNode(const QString& name)
+{
+ Node *node = childMap.value(name);
+ if (node)
+ return node;
+ return primaryFunctionMap.value(name);
+}
+
+/*!
+ */
+Node *InnerNode::findNode(const QString& name, Type type)
+{
+ if (type == Function) {
+ return primaryFunctionMap.value(name);
+ }
+ else {
+ Node *node = childMap.value(name);
+ if (node && node->type() == type) {
+ return node;
+ }
+ else {
+ return 0;
+ }
+ }
+}
+
+/*!
+ */
+FunctionNode *InnerNode::findFunctionNode(const QString& name)
+{
+ return static_cast<FunctionNode *>(primaryFunctionMap.value(name));
+}
+
+/*!
+ */
+FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone)
+{
+ QMap<QString, Node *>::ConstIterator c =
+ primaryFunctionMap.find(clone->name());
+ if (c != primaryFunctionMap.end()) {
+ if (isSameSignature(clone, (FunctionNode *) *c)) {
+ return (FunctionNode *) *c;
+ }
+ else if (secondaryFunctionMap.contains(clone->name())) {
+ const NodeList& secs = secondaryFunctionMap[clone->name()];
+ NodeList::ConstIterator s = secs.begin();
+ while (s != secs.end()) {
+ if (isSameSignature(clone, (FunctionNode *) *s))
+ return (FunctionNode *) *s;
+ ++s;
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ */
+void InnerNode::setOverload(const FunctionNode *func, bool overlode)
+{
+ Node *node = (Node *) func;
+ Node *&primary = primaryFunctionMap[func->name()];
+
+ if (secondaryFunctionMap.contains(func->name())) {
+ NodeList& secs = secondaryFunctionMap[func->name()];
+ if (overlode) {
+ if (primary == node) {
+ primary = secs.first();
+ secs.erase(secs.begin());
+ secs.append(node);
+ }
+ else {
+ secs.removeAll(node);
+ secs.append(node);
+ }
+ }
+ else {
+ if (primary != node) {
+ secs.removeAll(node);
+ secs.prepend(primary);
+ primary = node;
+ }
+ }
+ }
+}
+
+/*!
+ */
+void InnerNode::makeUndocumentedChildrenInternal()
+{
+ foreach (Node *child, childNodes()) {
+ if (child->doc().isEmpty()) {
+ child->setAccess(Node::Private);
+ child->setStatus(Node::Internal);
+ }
+ }
+}
+
+/*!
+ */
+void InnerNode::normalizeOverloads()
+{
+ QMap<QString, Node *>::Iterator p1 = primaryFunctionMap.begin();
+ while (p1 != primaryFunctionMap.end()) {
+ FunctionNode *primaryFunc = (FunctionNode *) *p1;
+ if (secondaryFunctionMap.contains(primaryFunc->name()) &&
+ (primaryFunc->status() != Commendable ||
+ primaryFunc->access() == Private)) {
+
+ NodeList& secs = secondaryFunctionMap[primaryFunc->name()];
+ NodeList::ConstIterator s = secs.begin();
+ while (s != secs.end()) {
+ FunctionNode *secondaryFunc = (FunctionNode *) *s;
+
+ // Any non-obsolete, non-compatibility, non-private functions
+ // (i.e, visible functions) are preferable to the primary
+ // function.
+
+ if (secondaryFunc->status() == Commendable &&
+ secondaryFunc->access() != Private) {
+
+ *p1 = secondaryFunc;
+ int index = secondaryFunctionMap[primaryFunc->name()].indexOf(secondaryFunc);
+ secondaryFunctionMap[primaryFunc->name()].replace(index, primaryFunc);
+ break;
+ }
+ ++s;
+ }
+ }
+ ++p1;
+ }
+
+ QMap<QString, Node *>::ConstIterator p = primaryFunctionMap.begin();
+ while (p != primaryFunctionMap.end()) {
+ FunctionNode *primaryFunc = (FunctionNode *) *p;
+ if (primaryFunc->isOverload())
+ primaryFunc->ove = false;
+ if (secondaryFunctionMap.contains(primaryFunc->name())) {
+ NodeList& secs = secondaryFunctionMap[primaryFunc->name()];
+ NodeList::ConstIterator s = secs.begin();
+ while (s != secs.end()) {
+ FunctionNode *secondaryFunc = (FunctionNode *) *s;
+ if (!secondaryFunc->isOverload())
+ secondaryFunc->ove = true;
+ ++s;
+ }
+ }
+ ++p;
+ }
+
+ NodeList::ConstIterator c = childNodes().begin();
+ while (c != childNodes().end()) {
+ if ((*c)->isInnerNode())
+ ((InnerNode *) *c)->normalizeOverloads();
+ ++c;
+ }
+}
+
+/*!
+ */
+void InnerNode::removeFromRelated()
+{
+ while (!related.isEmpty()) {
+ Node *p = static_cast<Node *>(related.takeFirst());
+
+ if (p != 0 && p->relates() == this) p->clearRelated();
+ }
+}
+
+/*!
+ */
+void InnerNode::deleteChildren()
+{
+ qDeleteAll(children);
+}
+
+/*!
+ Returns true.
+ */
+bool InnerNode::isInnerNode() const
+{
+ return true;
+}
+
+/*!
+ */
+const Node *InnerNode::findNode(const QString& name) const
+{
+ InnerNode *that = (InnerNode *) this;
+ return that->findNode(name);
+}
+
+/*!
+ */
+const Node *InnerNode::findNode(const QString& name, Type type) const
+{
+ InnerNode *that = (InnerNode *) this;
+ return that->findNode(name, type);
+}
+
+/*!
+ */
+const FunctionNode *InnerNode::findFunctionNode(const QString& name) const
+{
+ InnerNode *that = (InnerNode *) this;
+ return that->findFunctionNode(name);
+}
+
+/*!
+ */
+const FunctionNode *InnerNode::findFunctionNode(
+ const FunctionNode *clone) const
+{
+ InnerNode *that = (InnerNode *) this;
+ return that->findFunctionNode(clone);
+}
+
+/*!
+ */
+const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const
+{
+ foreach (const Node *node, enumChildren) {
+ const EnumNode *enume = static_cast<const EnumNode *>(node);
+ if (enume->hasItem(enumValue))
+ return enume;
+ }
+ return 0;
+}
+
+/*!
+ */
+int InnerNode::overloadNumber(const FunctionNode *func) const
+{
+ Node *node = (Node *) func;
+ if (primaryFunctionMap[func->name()] == node) {
+ return 1;
+ }
+ else {
+ return secondaryFunctionMap[func->name()].indexOf(node) + 2;
+ }
+}
+
+/*!
+ */
+int InnerNode::numOverloads(const QString& funcName) const
+{
+ if (primaryFunctionMap.contains(funcName)) {
+ return secondaryFunctionMap[funcName].count() + 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*!
+ */
+NodeList InnerNode::overloads(const QString &funcName) const
+{
+ NodeList result;
+ Node *primary = primaryFunctionMap.value(funcName);
+ if (primary) {
+ result << primary;
+ result += secondaryFunctionMap[funcName];
+ }
+ return result;
+}
+
+/*!
+ */
+InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name)
+ : Node(type, parent, name)
+{
+}
+
+/*!
+ */
+void InnerNode::addInclude(const QString& include)
+{
+ inc.append(include);
+}
+
+/*!
+ */
+void InnerNode::setIncludes(const QStringList& includes)
+{
+ inc = includes;
+}
+
+/*!
+ f1 is always the clone
+ */
+bool InnerNode::isSameSignature(const FunctionNode *f1, const FunctionNode *f2)
+{
+ if (f1->parameters().count() != f2->parameters().count())
+ return false;
+ if (f1->isConst() != f2->isConst())
+ return false;
+
+ QList<Parameter>::ConstIterator p1 = f1->parameters().begin();
+ QList<Parameter>::ConstIterator p2 = f2->parameters().begin();
+ while (p2 != f2->parameters().end()) {
+ if ((*p1).hasType() && (*p2).hasType()) {
+ if ((*p1).rightType() != (*p2).rightType())
+ return false;
+
+ QString t1 = p1->leftType();
+ QString t2 = p2->leftType();
+
+ if (t1.length() < t2.length())
+ qSwap(t1, t2);
+
+ /*
+ ### hack for C++ to handle superfluous
+ "Foo::" prefixes gracefully
+ */
+ if (t1 != t2 && t1 != (f2->parent()->name() + "::" + t2))
+ return false;
+ }
+ ++p1;
+ ++p2;
+ }
+ return true;
+}
+
+/*!
+ */
+void InnerNode::addChild(Node *child)
+{
+ children.append(child);
+ if (child->type() == Function) {
+ FunctionNode *func = (FunctionNode *) child;
+ if (!primaryFunctionMap.contains(func->name())) {
+ primaryFunctionMap.insert(func->name(), func);
+ }
+ else {
+ NodeList &secs = secondaryFunctionMap[func->name()];
+ secs.append(func);
+ }
+ }
+ else {
+ if (child->type() == Enum)
+ enumChildren.append(child);
+ childMap.insert(child->name(), child);
+ }
+}
+
+/*!
+ */
+void InnerNode::removeChild(Node *child)
+{
+ children.removeAll(child);
+ enumChildren.removeAll(child);
+ if (child->type() == Function) {
+ QMap<QString, Node *>::Iterator prim =
+ primaryFunctionMap.find(child->name());
+ NodeList& secs = secondaryFunctionMap[child->name()];
+ if (*prim == child) {
+ if (secs.isEmpty()) {
+ primaryFunctionMap.remove(child->name());
+ }
+ else {
+ primaryFunctionMap.insert(child->name(), secs.takeFirst());
+ }
+ }
+ else {
+ secs.removeAll(child);
+ }
+ QMap<QString, Node *>::Iterator ent = childMap.find( child->name() );
+ if ( *ent == child )
+ childMap.erase( ent );
+ }
+ else {
+ QMap<QString, Node *>::Iterator ent = childMap.find(child->name());
+ if (*ent == child)
+ childMap.erase(ent);
+ }
+}
+
+/*!
+ Find the module (QtCore, QtGui, etc.) to which the class belongs.
+ We do this by obtaining the full path to the header file's location
+ and examine everything between "src/" and the filename. This is
+ semi-dirty because we are assuming a particular directory structure.
+
+ This function is only really useful if the class's module has not
+ been defined in the header file with a QT_MODULE macro or with an
+ \inmodule command in the documentation.
+*/
+QString Node::moduleName() const
+{
+ if (!mod.isEmpty())
+ return mod;
+
+ QString path = location().filePath();
+ QString pattern = QString("src") + QDir::separator();
+ int start = path.lastIndexOf(pattern);
+
+ if (start == -1)
+ return "";
+
+ QString moduleDir = path.mid(start + pattern.size());
+ int finish = moduleDir.indexOf(QDir::separator());
+
+ if (finish == -1)
+ return "";
+
+ QString moduleName = moduleDir.left(finish);
+
+ if (moduleName == "corelib")
+ return "QtCore";
+ else if (moduleName == "uitools")
+ return "QtUiTools";
+ else if (moduleName == "gui")
+ return "QtGui";
+ else if (moduleName == "network")
+ return "QtNetwork";
+ else if (moduleName == "opengl")
+ return "QtOpenGL";
+ else if (moduleName == "qt3support")
+ return "Qt3Support";
+ else if (moduleName == "svg")
+ return "QtSvg";
+ else if (moduleName == "sql")
+ return "QtSql";
+ else if (moduleName == "qtestlib")
+ return "QtTest";
+ else if (moduleDir.contains("webkit"))
+ return "QtWebKit";
+ else if (moduleName == "xml")
+ return "QtXml";
+ else
+ return "";
+}
+
+/*!
+ */
+void InnerNode::removeRelated(Node *pseudoChild)
+{
+ related.removeAll(pseudoChild);
+}
+
+/*!
+ \class LeafNode
+ */
+
+/*!
+ Returns false because this is an InnerNode.
+ */
+bool LeafNode::isInnerNode() const
+{
+ return false;
+}
+
+/*!
+ */
+LeafNode::LeafNode(Type type, InnerNode *parent, const QString& name)
+ : Node(type, parent, name)
+{
+}
+
+/*!
+ \class NamespaceNode
+ */
+
+/*!
+ */
+NamespaceNode::NamespaceNode(InnerNode *parent, const QString& name)
+ : InnerNode(Namespace, parent, name)
+{
+}
+
+/*!
+ \class ClassNode
+ */
+
+/*!
+ */
+ClassNode::ClassNode(InnerNode *parent, const QString& name)
+ : InnerNode(Class, parent, name)
+{
+ hidden = false;
+}
+
+/*!
+ */
+void ClassNode::addBaseClass(Access access,
+ ClassNode *node,
+ const QString &dataTypeWithTemplateArgs)
+{
+ bas.append(RelatedClass(access, node, dataTypeWithTemplateArgs));
+ node->der.append(RelatedClass(access, this));
+}
+
+/*!
+ */
+void ClassNode::fixBaseClasses()
+{
+ int i;
+
+ i = 0;
+ while (i < bas.size()) {
+ ClassNode *baseClass = bas.at(i).node;
+ if (baseClass->access() == Node::Private) {
+ bas.removeAt(i);
+
+ const QList<RelatedClass> &basesBases = baseClass->baseClasses();
+ for (int j = basesBases.size() - 1; j >= 0; --j)
+ bas.insert(i, basesBases.at(j));
+ }
+ else {
+ ++i;
+ }
+ }
+
+ i = 0;
+ while (i < der.size()) {
+ ClassNode *derivedClass = der.at(i).node;
+ if (derivedClass->access() == Node::Private) {
+ der.removeAt(i);
+
+ const QList<RelatedClass> &dersDers =
+ derivedClass->derivedClasses();
+ for (int j = dersDers.size() - 1; j >= 0; --j)
+ der.insert(i, dersDers.at(j));
+ }
+ else {
+ ++i;
+ }
+ }
+}
+
+/*!
+ \class FakeNode
+ */
+
+/*!
+ */
+FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subType)
+ : InnerNode(Fake, parent, name), sub(subType)
+{
+}
+
+/*!
+ */
+QString FakeNode::fullTitle() const
+{
+ if (sub == File) {
+ if (title().isEmpty())
+ return name().mid(name().lastIndexOf('/') + 1) + " Example File";
+ else
+ return title();
+ }
+ else if (sub == HeaderFile) {
+ if (title().isEmpty())
+ return name();
+ else
+ return name() + " - " + title();
+ }
+ else {
+ return title();
+ }
+}
+
+/*!
+ */
+QString FakeNode::subTitle() const
+{
+ if (!stle.isEmpty())
+ return stle;
+
+ if (sub == File) {
+ if (title().isEmpty() && name().contains("/"))
+ return name();
+ }
+ return QString();
+}
+
+/*!
+ \class EnumNode
+ */
+
+/*!
+ */
+EnumNode::EnumNode(InnerNode *parent, const QString& name)
+ : LeafNode(Enum, parent, name), ft(0)
+{
+}
+
+/*!
+ */
+void EnumNode::addItem(const EnumItem& item)
+{
+ itms.append(item);
+ names.insert(item.name());
+}
+
+/*!
+ */
+Node::Access EnumNode::itemAccess(const QString &name) const
+{
+ if (doc().omitEnumItemNames().contains(name)) {
+ return Private;
+ }
+ else {
+ return Public;
+ }
+}
+
+/*!
+ Returns the enum value associated with the enum \a name.
+ */
+QString EnumNode::itemValue(const QString &name) const
+{
+ foreach (const EnumItem &item, itms) {
+ if (item.name() == name)
+ return item.value();
+ }
+ return QString();
+}
+
+/*!
+ \class TypedefNode
+ */
+
+/*!
+ */
+TypedefNode::TypedefNode(InnerNode *parent, const QString& name)
+ : LeafNode(Typedef, parent, name), ae(0)
+{
+}
+
+/*!
+ */
+void TypedefNode::setAssociatedEnum(const EnumNode *enume)
+{
+ ae = enume;
+}
+
+/*!
+ \class Parameter
+ */
+
+/*!
+ */
+Parameter::Parameter(const QString& leftType,
+ const QString& rightType,
+ const QString& name,
+ const QString& defaultValue)
+ : lef(leftType), rig(rightType), nam(name), def(defaultValue)
+{
+}
+
+/*!
+ */
+Parameter::Parameter(const Parameter& p)
+ : lef(p.lef), rig(p.rig), nam(p.nam), def(p.def)
+{
+}
+
+/*!
+ */
+Parameter& Parameter::operator=(const Parameter& p)
+{
+ lef = p.lef;
+ rig = p.rig;
+ nam = p.nam;
+ def = p.def;
+ return *this;
+}
+
+/*!
+ \class FunctionNode
+ */
+
+/*!
+ */
+FunctionNode::FunctionNode(InnerNode *parent, const QString& name)
+ : LeafNode(Function, parent, name), met(Plain), vir(NonVirtual),
+ con(false), sta(false), ove(false), rf(0), ap(0)
+{
+}
+
+/*!
+ */
+void FunctionNode::setOverload(bool overlode)
+{
+ parent()->setOverload(this, overlode);
+ ove = overlode;
+}
+
+/*!
+ */
+void FunctionNode::addParameter(const Parameter& parameter)
+{
+ params.append(parameter);
+}
+
+/*!
+ */
+void FunctionNode::borrowParameterNames(const FunctionNode *source)
+{
+ QList<Parameter>::Iterator t = params.begin();
+ QList<Parameter>::ConstIterator s = source->params.begin();
+ while (s != source->params.end() && t != params.end()) {
+ if (!(*s).name().isEmpty())
+ (*t).setName((*s).name());
+ ++s;
+ ++t;
+ }
+}
+
+/*!
+ */
+void FunctionNode::setReimplementedFrom(FunctionNode *from)
+{
+ rf = from;
+ from->rb.append(this);
+}
+
+/*!
+ */
+void FunctionNode::setAssociatedProperty(PropertyNode *property)
+{
+ ap = property;
+}
+
+/*!
+ */
+int FunctionNode::overloadNumber() const
+{
+ return parent()->overloadNumber(this);
+}
+
+/*!
+ */
+int FunctionNode::numOverloads() const
+{
+ return parent()->numOverloads(name());
+}
+
+/*!
+ */
+QStringList FunctionNode::parameterNames() const
+{
+ QStringList names;
+ QList<Parameter>::ConstIterator p = parameters().begin();
+ while (p != parameters().end()) {
+ names << (*p).name();
+ ++p;
+ }
+ return names;
+}
+
+/*!
+ \class PropertyNode
+ */
+
+/*!
+ */
+PropertyNode::PropertyNode(InnerNode *parent, const QString& name)
+ : LeafNode(Property, parent, name),
+ sto(Trool_Default),
+ des(Trool_Default),
+ overrides(0)
+{
+}
+
+/*!
+ */
+void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty)
+{
+ for (int i = 0; i < NumFunctionRoles; ++i) {
+ if (funcs[i].isEmpty())
+ funcs[i] = baseProperty->funcs[i];
+ }
+ if (sto == Trool_Default)
+ sto = baseProperty->sto;
+ if (des == Trool_Default)
+ des = baseProperty->des;
+ overrides = baseProperty;
+}
+
+/*!
+ */
+QString PropertyNode::qualifiedDataType() const
+{
+ if (setters().isEmpty() && resetters().isEmpty()) {
+ if (dt.contains("*") || dt.contains("&")) {
+ // 'QWidget *' becomes 'QWidget *' const
+ return dt + " const";
+ }
+ else {
+ /*
+ 'int' becomes 'const int' ('int const' is
+ correct C++, but looks wrong)
+ */
+ return "const " + dt;
+ }
+ }
+ else {
+ return dt;
+ }
+}
+
+/*!
+ */
+PropertyNode::Trool PropertyNode::toTrool(bool boolean)
+{
+ return boolean ? Trool_True : Trool_False;
+}
+
+/*!
+ */
+bool PropertyNode::fromTrool(Trool troolean, bool defaultValue)
+{
+ switch (troolean) {
+ case Trool_True:
+ return true;
+ case Trool_False:
+ return false;
+ default:
+ return defaultValue;
+ }
+}
+
+/*!
+ \class TargetNode
+ */
+
+/*!
+ */
+TargetNode::TargetNode(InnerNode *parent, const QString& name)
+ : LeafNode(Target, parent, name)
+{
+}
+
+/*!
+ Returns false because this is a TargetNode.
+ */
+bool TargetNode::isInnerNode() const
+{
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h
new file mode 100644
index 0000000000..c34b82b7ed
--- /dev/null
+++ b/tools/qdoc3/node.h
@@ -0,0 +1,587 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ node.h
+*/
+
+#ifndef NODE_H
+#define NODE_H
+
+#include <qdir.h>
+#include <qmap.h>
+#include <qpair.h>
+#include <qstringlist.h>
+
+#include "codechunk.h"
+#include "doc.h"
+#include "location.h"
+#include "text.h"
+
+QT_BEGIN_NAMESPACE
+
+class InnerNode;
+
+class Node
+{
+ public:
+ enum Type {
+ Namespace,
+ Class,
+ Fake,
+ Enum,
+ Typedef,
+ Function,
+ Property,
+ Variable,
+ Target
+ };
+
+ enum Access { Public, Protected, Private };
+
+ enum Status {
+ Compat,
+ Obsolete,
+ Deprecated,
+ Preliminary,
+ Commendable,
+ Main,
+ Internal
+ }; // don't reorder thisw enum
+
+ enum ThreadSafeness {
+ UnspecifiedSafeness,
+ NonReentrant,
+ Reentrant,
+ ThreadSafe
+ };
+
+ enum LinkType {
+ StartLink,
+ NextLink,
+ PreviousLink,
+ ContentsLink,
+ IndexLink /*,
+ GlossaryLink,
+ CopyrightLink,
+ ChapterLink,
+ SectionLink,
+ SubsectionLink,
+ AppendixLink */
+ };
+
+ virtual ~Node();
+
+ void setAccess(Access access) { acc = access; }
+ void setLocation(const Location& location) { loc = location; }
+ void setDoc(const Doc& doc, bool replace = false);
+ void setStatus(Status status) { sta = status; }
+ void setThreadSafeness(ThreadSafeness safeness) { saf = safeness; }
+ void setSince(const QString &since) { sinc = since; }
+ void setRelates(InnerNode *pseudoParent);
+ void setModuleName(const QString &module) { mod = module; }
+ void setLink(LinkType linkType, const QString &link, const QString &desc);
+ void setUrl(const QString &url);
+ void setTemplateStuff(const QString &templateStuff) { tpl = templateStuff; }
+
+ virtual bool isInnerNode() const = 0;
+ Type type() const { return typ; }
+ InnerNode *parent() const { return par; }
+ InnerNode *relates() const { return rel; }
+ const QString& name() const { return nam; }
+ QMap<LinkType, QPair<QString,QString> > links() const { return linkMap; }
+ QString moduleName() const;
+ QString url() const;
+
+ Access access() const { return acc; }
+ const Location& location() const { return loc; }
+ const Doc& doc() const { return d; }
+ Status status() const { return sta; }
+ Status inheritedStatus() const;
+ ThreadSafeness threadSafeness() const;
+ ThreadSafeness inheritedThreadSafeness() const;
+ QString since() const { return sinc; }
+ QString templateStuff() const { return tpl; }
+
+ void clearRelated() { rel = 0; }
+
+ QString fileBase() const;
+
+ protected:
+ Node(Type type, InnerNode *parent, const QString& name);
+
+ private:
+#ifdef Q_WS_WIN
+ Type typ;
+ Access acc;
+ Status sta;
+ ThreadSafeness saf;
+#else
+ Type typ : 4;
+ Access acc : 2;
+ Status sta : 3;
+ ThreadSafeness saf : 2;
+#endif
+ InnerNode *par;
+ InnerNode *rel;
+ QString nam;
+ Location loc;
+ Doc d;
+ QMap<LinkType, QPair<QString, QString> > linkMap;
+ QString mod;
+ QString u;
+ QString sinc;
+ QString tpl;
+};
+
+class FunctionNode;
+class EnumNode;
+
+typedef QList<Node *> NodeList;
+
+class InnerNode : public Node
+{
+ public:
+ ~InnerNode();
+
+ Node *findNode(const QString& name);
+ Node *findNode(const QString& name, Type type);
+ FunctionNode *findFunctionNode(const QString& name);
+ FunctionNode *findFunctionNode(const FunctionNode *clone);
+ void addInclude(const QString &include);
+ void setIncludes(const QStringList &includes);
+ void setOverload(const FunctionNode *func, bool overlode);
+ void normalizeOverloads();
+ void makeUndocumentedChildrenInternal();
+ void deleteChildren();
+ void removeFromRelated();
+
+ virtual bool isInnerNode() const;
+ const Node *findNode(const QString& name) const;
+ const Node *findNode(const QString& name, Type type) const;
+ const FunctionNode *findFunctionNode(const QString& name) const;
+ const FunctionNode *findFunctionNode(const FunctionNode *clone) const;
+ const EnumNode *findEnumNodeForValue(const QString &enumValue) const;
+ const NodeList & childNodes() const { return children; }
+ const NodeList & relatedNodes() const { return related; }
+ int overloadNumber(const FunctionNode *func) const;
+ int numOverloads(const QString& funcName) const;
+ NodeList overloads(const QString &funcName) const;
+ const QStringList& includes() const { return inc; }
+
+ protected:
+ InnerNode(Type type, InnerNode *parent, const QString& name);
+
+ private:
+ friend class Node;
+
+ static bool isSameSignature(const FunctionNode *f1, const FunctionNode *f2);
+ void addChild(Node *child);
+ void removeChild(Node *child);
+ void removeRelated(Node *pseudoChild);
+
+ QStringList inc;
+ NodeList children;
+ NodeList enumChildren;
+ NodeList related;
+ QMap<QString, Node *> childMap;
+ QMap<QString, Node *> primaryFunctionMap;
+ QMap<QString, NodeList> secondaryFunctionMap;
+};
+
+class LeafNode : public Node
+{
+ public:
+ LeafNode();
+
+ virtual bool isInnerNode() const;
+
+ protected:
+ LeafNode(Type type, InnerNode *parent, const QString& name);
+};
+
+class NamespaceNode : public InnerNode
+{
+ public:
+ NamespaceNode(InnerNode *parent, const QString& name);
+};
+
+class ClassNode;
+
+struct RelatedClass
+{
+ RelatedClass() { }
+ RelatedClass(Node::Access access0,
+ ClassNode* node0,
+ const QString& dataTypeWithTemplateArgs0 = "")
+ : access(access0),
+ node(node0),
+ dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0) { }
+
+ Node::Access access;
+ ClassNode* node;
+ QString dataTypeWithTemplateArgs;
+};
+
+class ClassNode : public InnerNode
+{
+ public:
+ ClassNode(InnerNode *parent, const QString& name);
+
+ void addBaseClass(Access access,
+ ClassNode *node,
+ const QString &dataTypeWithTemplateArgs = "");
+ void fixBaseClasses();
+
+ const QList<RelatedClass> &baseClasses() const { return bas; }
+ const QList<RelatedClass> &derivedClasses() const { return der; }
+
+ bool hideFromMainList() const { return hidden; }
+ void setHideFromMainList(bool value) { hidden = value; }
+
+ QString serviceName() const { return sname; }
+ void setServiceName(const QString& value) { sname = value; }
+
+ private:
+ QList<RelatedClass> bas;
+ QList<RelatedClass> der;
+ bool hidden;
+ QString sname;
+};
+
+class FakeNode : public InnerNode
+{
+ public:
+ enum SubType {
+ Example,
+ HeaderFile,
+ File,
+ Group,
+ Module,
+ Page,
+ ExternalPage,
+ QmlClass
+ };
+
+ FakeNode(InnerNode *parent, const QString& name, SubType subType);
+
+ void setTitle(const QString &title) { tle = title; }
+ void setSubTitle(const QString &subTitle) { stle = subTitle; }
+ void addGroupMember(Node *node) { gr.append(node); }
+
+ SubType subType() const { return sub; }
+ QString title() const { return tle; }
+ QString fullTitle() const;
+ QString subTitle() const;
+ const NodeList &groupMembers() const { return gr; }
+
+ private:
+ SubType sub;
+ QString tle;
+ QString stle;
+ NodeList gr;
+};
+
+class QmlNode : public FakeNode
+{
+ public:
+ QmlNode(InnerNode *parent, const QString& name, const ClassNode* cn)
+ : FakeNode(parent, name, QmlClass), cnode(cn) { }
+
+ const ClassNode* classNode() const { return cnode; }
+
+ private:
+ const ClassNode* cnode;
+};
+
+class EnumItem
+{
+ public:
+ EnumItem() { }
+ EnumItem(const QString& name, const QString& value)
+ : nam(name), val(value) { }
+ EnumItem(const QString& name, const QString& value, const Text &txt)
+ : nam(name), val(value), txt(txt) { }
+
+ const QString& name() const { return nam; }
+ const QString& value() const { return val; }
+ const Text &text() const { return txt; }
+
+ private:
+ QString nam;
+ QString val;
+ Text txt;
+};
+
+class TypedefNode;
+
+class EnumNode : public LeafNode
+{
+ public:
+ EnumNode(InnerNode *parent, const QString& name);
+
+ void addItem(const EnumItem& item);
+ void setFlagsType(TypedefNode *typedeff);
+ bool hasItem(const QString &name) const { return names.contains(name); }
+
+ const QList<EnumItem>& items() const { return itms; }
+ Access itemAccess(const QString& name) const;
+ const TypedefNode *flagsType() const { return ft; }
+ QString itemValue(const QString &name) const;
+
+ private:
+ QList<EnumItem> itms;
+ QSet<QString> names;
+ const TypedefNode *ft;
+};
+
+class TypedefNode : public LeafNode
+{
+ public:
+ TypedefNode(InnerNode *parent, const QString& name);
+
+ const EnumNode *associatedEnum() const { return ae; }
+
+ private:
+ void setAssociatedEnum(const EnumNode *enume);
+
+ friend class EnumNode;
+
+ const EnumNode *ae;
+};
+
+inline void EnumNode::setFlagsType(TypedefNode *typedeff)
+{
+ ft = typedeff;
+ typedeff->setAssociatedEnum(this);
+}
+
+
+class Parameter
+{
+ public:
+ Parameter() {}
+ Parameter(const QString& leftType, const QString& rightType = "",
+ const QString& name = "", const QString& defaultValue = "");
+ Parameter(const Parameter& p);
+
+ Parameter& operator=(const Parameter& p);
+
+ void setName(const QString& name) { nam = name; }
+
+ bool hasType() const { return lef.length() + rig.length() > 0; }
+ const QString& leftType() const { return lef; }
+ const QString& rightType() const { return rig; }
+ const QString& name() const { return nam; }
+ const QString& defaultValue() const { return def; }
+
+ private:
+ QString lef;
+ QString rig;
+ QString nam;
+ QString def;
+};
+
+class PropertyNode;
+
+class FunctionNode : public LeafNode
+{
+ public:
+ enum Metaness {
+ Plain,
+ Signal,
+ Slot,
+ Ctor,
+ Dtor,
+ MacroWithParams,
+ MacroWithoutParams,
+ Native };
+ enum Virtualness { NonVirtual, ImpureVirtual, PureVirtual };
+
+ FunctionNode(InnerNode *parent, const QString &name);
+
+ void setReturnType(const QString& returnType) { rt = returnType; }
+ void setMetaness(Metaness metaness) { met = metaness; }
+ void setVirtualness(Virtualness virtualness) { vir = virtualness; }
+ void setConst(bool conste) { con = conste; }
+ void setStatic(bool statique) { sta = statique; }
+ void setOverload(bool overlode);
+ void addParameter(const Parameter& parameter);
+ inline void setParameters(const QList<Parameter>& parameters);
+ void borrowParameterNames(const FunctionNode *source);
+ void setReimplementedFrom(FunctionNode *from);
+
+ const QString& returnType() const { return rt; }
+ Metaness metaness() const { return met; }
+ bool isMacro() const {
+ return met == MacroWithParams || met == MacroWithoutParams;
+ }
+ Virtualness virtualness() const { return vir; }
+ bool isConst() const { return con; }
+ bool isStatic() const { return sta; }
+ bool isOverload() const { return ove; }
+ int overloadNumber() const;
+ int numOverloads() const;
+ const QList<Parameter>& parameters() const { return params; }
+ QStringList parameterNames() const;
+ const FunctionNode *reimplementedFrom() const { return rf; }
+ const QList<FunctionNode *> &reimplementedBy() const { return rb; }
+ const PropertyNode *associatedProperty() const { return ap; }
+
+ private:
+ void setAssociatedProperty(PropertyNode *property);
+
+ friend class InnerNode;
+ friend class PropertyNode;
+
+ QString rt;
+#ifdef Q_WS_WIN
+ Metaness met;
+ Virtualness vir;
+#else
+ Metaness met : 4;
+ Virtualness vir : 2;
+#endif
+ bool con : 1;
+ bool sta : 1;
+ bool ove : 1;
+ QList<Parameter> params;
+ const FunctionNode *rf;
+ const PropertyNode *ap;
+ QList<FunctionNode *> rb;
+};
+
+class PropertyNode : public LeafNode
+{
+ public:
+ enum FunctionRole { Getter, Setter, Resetter };
+ enum { NumFunctionRoles = Resetter + 1 };
+
+ PropertyNode(InnerNode *parent, const QString& name);
+
+ void setDataType(const QString& dataType) { dt = dataType; }
+ void addFunction(FunctionNode *function, FunctionRole role);
+ void setStored(bool stored) { sto = toTrool(stored); }
+ void setDesignable(bool designable) { des = toTrool(designable); }
+ void setOverriddenFrom(const PropertyNode *baseProperty);
+
+ const QString &dataType() const { return dt; }
+ QString qualifiedDataType() const;
+ NodeList functions() const;
+ NodeList functions(FunctionRole role) const { return funcs[(int)role]; }
+ NodeList getters() const { return functions(Getter); }
+ NodeList setters() const { return functions(Setter); }
+ NodeList resetters() const { return functions(Resetter); }
+ bool isStored() const { return fromTrool(sto, storedDefault()); }
+ bool isDesignable() const { return fromTrool(des, designableDefault()); }
+ const PropertyNode *overriddenFrom() const { return overrides; }
+
+ private:
+ enum Trool { Trool_True, Trool_False, Trool_Default };
+
+ static Trool toTrool(bool boolean);
+ static bool fromTrool(Trool troolean, bool defaultValue);
+
+ bool storedDefault() const { return true; }
+ bool designableDefault() const { return !setters().isEmpty(); }
+
+ QString dt;
+ NodeList funcs[NumFunctionRoles];
+ Trool sto;
+ Trool des;
+ const PropertyNode *overrides;
+};
+
+inline void FunctionNode::setParameters(const QList<Parameter> &parameters)
+{
+ params = parameters;
+}
+
+inline void PropertyNode::addFunction(FunctionNode *function, FunctionRole role)
+{
+ funcs[(int)role].append(function);
+ function->setAssociatedProperty(this);
+}
+
+inline NodeList PropertyNode::functions() const
+{
+ NodeList list;
+ for (int i = 0; i < NumFunctionRoles; ++i)
+ list += funcs[i];
+ return list;
+}
+
+class VariableNode : public LeafNode
+{
+ public:
+ VariableNode(InnerNode *parent, const QString &name);
+
+ void setLeftType(const QString &leftType) { lt = leftType; }
+ void setRightType(const QString &rightType) { rt = rightType; }
+ void setStatic(bool statique) { sta = statique; }
+
+ const QString &leftType() const { return lt; }
+ const QString &rightType() const { return rt; }
+ QString dataType() const { return lt + rt; }
+ bool isStatic() const { return sta; }
+
+ private:
+ QString lt;
+ QString rt;
+ bool sta;
+};
+
+inline VariableNode::VariableNode(InnerNode *parent, const QString &name)
+ : LeafNode(Variable, parent, name), sta(false)
+{
+}
+
+class TargetNode : public LeafNode
+{
+ public:
+ TargetNode(InnerNode *parent, const QString& name);
+
+ virtual bool isInnerNode() const;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/openedlist.cpp b/tools/qdoc3/openedlist.cpp
new file mode 100644
index 0000000000..04d9871d49
--- /dev/null
+++ b/tools/qdoc3/openedlist.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ openedlist.cpp
+*/
+
+#include <qregexp.h>
+
+#include "atom.h"
+#include "openedlist.h"
+
+QT_BEGIN_NAMESPACE
+
+static const char roman[] = "m\2d\5c\2l\5x\2v\5i";
+
+OpenedList::OpenedList( Style style )
+ : sty( style ), ini( 1 ), nex( 0 )
+{
+}
+
+OpenedList::OpenedList( const Location& location, const QString& hint )
+ : sty( Bullet ), ini( 1 )
+{
+ QRegExp hintSyntax( "(\\W*)([0-9]+|[A-Z]+|[a-z]+)(\\W*)" );
+
+ if ( hintSyntax.exactMatch(hint) ) {
+ bool ok;
+ int asNumeric = hint.toInt( &ok );
+ int asRoman = fromRoman( hintSyntax.cap(2) );
+ int asAlpha = fromAlpha( hintSyntax.cap(2) );
+
+ if ( ok ) {
+ sty = Numeric;
+ ini = asNumeric;
+ } else if ( asRoman > 0 && asRoman != 100 && asRoman != 500 ) {
+ sty = ( hint == hint.toLower() ) ? LowerRoman : UpperRoman;
+ ini = asRoman;
+ } else {
+ sty = ( hint == hint.toLower() ) ? LowerAlpha : UpperAlpha;
+ ini = asAlpha;
+ }
+ pref = hintSyntax.cap( 1 );
+ suff = hintSyntax.cap( 3 );
+ } else if ( !hint.isEmpty() ) {
+ location.warning( tr("Unrecognized list style '%1'").arg(hint) );
+ }
+ nex = ini - 1;
+}
+
+QString OpenedList::styleString() const
+{
+ switch ( style() ) {
+ case Bullet:
+ default:
+ return ATOM_LIST_BULLET;
+ case Tag:
+ return ATOM_LIST_TAG;
+ case Value:
+ return ATOM_LIST_VALUE;
+ case Numeric:
+ return ATOM_LIST_NUMERIC;
+ case UpperAlpha:
+ return ATOM_LIST_UPPERALPHA;
+ case LowerAlpha:
+ return ATOM_LIST_LOWERALPHA;
+ case UpperRoman:
+ return ATOM_LIST_UPPERROMAN;
+ case LowerRoman:
+ return ATOM_LIST_LOWERROMAN;
+ }
+}
+
+QString OpenedList::numberString() const
+{
+ return QString::number( number() );
+/*
+ switch ( style() ) {
+ case Numeric:
+ return QString::number( number() );
+ case UpperAlpha:
+ return toAlpha( number() ).toUpper();
+ case LowerAlpha:
+ return toAlpha( number() );
+ case UpperRoman:
+ return toRoman( number() ).toUpper();
+ case LowerRoman:
+ return toRoman( number() );
+ case Bullet:
+ default:
+ return "*";
+ }*/
+}
+
+QString OpenedList::toAlpha( int n )
+{
+ QString str;
+
+ while ( n > 0 ) {
+ n--;
+ str.prepend( (n % 26) + 'a' );
+ n /= 26;
+ }
+ return str;
+}
+
+int OpenedList::fromAlpha( const QString& str )
+{
+ int n = 0;
+ int u;
+
+ for ( int i = 0; i < (int) str.length(); i++ ) {
+ u = str[i].toLower().unicode();
+ if ( u >= 'a' && u <= 'z' ) {
+ n *= 26;
+ n += u - 'a' + 1;
+ } else {
+ return 0;
+ }
+ }
+ return n;
+}
+
+QString OpenedList::toRoman( int n )
+{
+ /*
+ See p. 30 of Donald E. Knuth's "TeX: The Program".
+ */
+ QString str;
+ int j = 0;
+ int k;
+ int u;
+ int v = 1000;
+
+ for ( ;; ) {
+ while ( n >= v ) {
+ str += roman[j];
+ n -= v;
+ }
+
+ if ( n <= 0 )
+ break;
+
+ k = j + 2;
+ u = v / roman[k - 1];
+ if ( roman[k - 1] == 2 ) {
+ k += 2;
+ u /= 5;
+ }
+ if ( n + u >= v ) {
+ str += roman[k];
+ n += u;
+ } else {
+ j += 2;
+ v /= roman[j - 1];
+ }
+ }
+ return str;
+}
+
+int OpenedList::fromRoman( const QString& str )
+{
+ int n = 0;
+ int j;
+ int u;
+ int v = 0;
+
+ for ( int i = str.length() - 1; i >= 0; i-- ) {
+ j = 0;
+ u = 1000;
+ while ( roman[j] != 'i' && roman[j] != str[i].toLower() ) {
+ j += 2;
+ u /= roman[j - 1];
+ }
+ if ( u < v ) {
+ n -= u;
+ } else {
+ n += u;
+ }
+ v = u;
+ }
+
+ if ( str.toLower() == toRoman(n) ) {
+ return n;
+ } else {
+ return 0;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/openedlist.h b/tools/qdoc3/openedlist.h
new file mode 100644
index 0000000000..0506e7983d
--- /dev/null
+++ b/tools/qdoc3/openedlist.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ openedlist.h
+*/
+
+#ifndef OPENEDLIST_H
+#define OPENEDLIST_H
+
+#include <qstring.h>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class OpenedList
+{
+public:
+ enum Style { Bullet, Tag, Value, Numeric, UpperAlpha, LowerAlpha,
+ UpperRoman, LowerRoman };
+
+ OpenedList()
+ : sty( Bullet ), ini( 1 ), nex( 0 ) { }
+ OpenedList( Style style );
+ OpenedList( const Location& location, const QString& hint );
+
+ void next() { nex++; }
+
+ bool isStarted() const { return nex >= ini; }
+ Style style() const { return sty; }
+ QString styleString() const;
+ int number() const { return nex; }
+ QString numberString() const;
+ QString prefix() const { return pref; }
+ QString suffix() const { return suff; }
+
+private:
+ static QString toAlpha( int n );
+ static int fromAlpha( const QString& str );
+ static QString toRoman( int n );
+ static int fromRoman( const QString& str );
+
+ Style sty;
+ int ini;
+ int nex;
+ QString pref;
+ QString suff;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/pagegenerator.cpp b/tools/qdoc3/pagegenerator.cpp
new file mode 100644
index 0000000000..2d5027958b
--- /dev/null
+++ b/tools/qdoc3/pagegenerator.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ pagegenerator.cpp
+*/
+
+#include <QtCore>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+#include "pagegenerator.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Nothing to do in the constructor.
+ */
+PageGenerator::PageGenerator()
+{
+ // nothing.
+}
+
+/*!
+ The destructor
+ */
+PageGenerator::~PageGenerator()
+{
+ while (!outStreamStack.isEmpty())
+ endSubPage();
+}
+
+/*!
+ This function is recursive.
+ */
+void PageGenerator::generateTree(const Tree *tree, CodeMarker *marker)
+{
+ generateInnerNode(tree->root(), marker);
+}
+
+QString PageGenerator::fileBase(const Node *node)
+{
+ if (node->relates())
+ node = node->relates();
+ else if (!node->isInnerNode())
+ node = node->parent();
+
+ QString base = node->doc().baseName();
+ if (!base.isEmpty())
+ return base;
+
+ const Node *p = node;
+
+ forever {
+ base.prepend(p->name());
+ const Node *pp = p->parent();
+ if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake)
+ break;
+ base.prepend(QLatin1Char('-'));
+ p = pp;
+ }
+
+ if (node->type() == Node::Fake) {
+#ifdef QDOC2_COMPAT
+ if (base.endsWith(".html"))
+ base.truncate(base.length() - 5);
+#endif
+ }
+
+ // the code below is effectively equivalent to:
+ // base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
+ // base = base.trimmed();
+ // base.replace(" ", "-");
+ // base = base.toLower();
+ // as this function accounted for ~8% of total running time
+ // we optimize a bit...
+
+ QString res;
+ // +5 prevents realloc in fileName() below
+ res.reserve(base.size() + 5);
+ bool begun = false;
+ for (int i = 0; i != base.size(); ++i) {
+ QChar c = base.at(i);
+ uint u = c.unicode();
+ if (u >= 'A' && u <= 'Z')
+ u -= 'A' - 'a';
+ if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) {
+ res += QLatin1Char(u);
+ begun = true;
+ } else if (begun) {
+ res += QLatin1Char('-');
+ begun = false;
+ }
+ }
+ while (res.endsWith(QLatin1Char('-')))
+ res.chop(1);
+ return res;
+}
+
+QString PageGenerator::fileName(const Node *node)
+{
+ if (!node->url().isEmpty())
+ return node->url();
+
+ QString name = fileBase(node);
+ name += QLatin1Char('.');
+ name += fileExtension(node);
+ return name;
+}
+
+QString PageGenerator::outFileName()
+{
+ return QFileInfo(static_cast<QFile *>(out().device())->fileName()).fileName();
+}
+
+void PageGenerator::beginSubPage(const Location& location,
+ const QString& fileName)
+{
+ QFile *outFile = new QFile(outputDir() + "/" + fileName);
+ if (!outFile->open(QFile::WriteOnly))
+ location.fatal(tr("Cannot open output file '%1'")
+ .arg(outFile->fileName()));
+ QTextStream *out = new QTextStream(outFile);
+ out->setCodec("ISO-8859-1");
+ outStreamStack.push(out);
+}
+
+void PageGenerator::endSubPage()
+{
+ outStreamStack.top()->flush();
+ delete outStreamStack.top()->device();
+ delete outStreamStack.pop();
+}
+
+QTextStream &PageGenerator::out()
+{
+ return *outStreamStack.top();
+}
+
+/*!
+ Recursive writing of html files from the root \a node.
+ */
+void PageGenerator::generateInnerNode(const InnerNode *node,
+ CodeMarker *marker)
+{
+ if (!node->url().isNull())
+ return;
+
+ if (node->type() == Node::Fake) {
+ const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
+ if (fakeNode->subType() == FakeNode::ExternalPage)
+ return;
+ }
+
+ if (node->parent() != 0) {
+ beginSubPage(node->location(), fileName(node));
+ if (node->type() == Node::Namespace || node->type() == Node::Class) {
+ generateClassLikeNode(node, marker);
+ }
+ else if (node->type() == Node::Fake) {
+ const FakeNode* fakeNode = static_cast<const FakeNode *>(node);
+#ifdef QDOC_QML
+ if (fakeNode->subType() == FakeNode::QmlClass) {
+ //qDebug() << "FILENAME:" << fileName(node);
+ }
+#endif
+ generateFakeNode(static_cast<const FakeNode *>(node), marker);
+ }
+ endSubPage();
+ }
+
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while (c != node->childNodes().end()) {
+ if ((*c)->isInnerNode() && (*c)->access() != Node::Private)
+ generateInnerNode((const InnerNode *) *c, marker);
+ ++c;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/pagegenerator.h b/tools/qdoc3/pagegenerator.h
new file mode 100644
index 0000000000..002d390406
--- /dev/null
+++ b/tools/qdoc3/pagegenerator.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ pagegenerator.h
+*/
+
+#ifndef PAGEGENERATOR_H
+#define PAGEGENERATOR_H
+
+#include <QStack>
+#include <qtextstream.h>
+
+#include "generator.h"
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class ClassNode;
+class InnerNode;
+class NamespaceNode;
+
+class PageGenerator : public Generator
+{
+ public:
+ PageGenerator();
+ ~PageGenerator();
+
+ virtual void generateTree(const Tree *tree, CodeMarker *marker);
+
+ protected:
+ virtual QString fileBase(const Node *node);
+ virtual QString fileExtension(const Node *node) = 0;
+ QString fileName(const Node *node);
+ QString outFileName();
+ void beginSubPage(const Location& location, const QString& fileName);
+ void endSubPage();
+ virtual void generateInnerNode(const InnerNode *node, CodeMarker *marker);
+ QTextStream& out();
+
+ private:
+ QStack<QTextStream *> outStreamStack;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/plaincodemarker.cpp b/tools/qdoc3/plaincodemarker.cpp
new file mode 100644
index 0000000000..5ed4bbe489
--- /dev/null
+++ b/tools/qdoc3/plaincodemarker.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "plaincodemarker.h"
+
+QT_BEGIN_NAMESPACE
+
+PlainCodeMarker::PlainCodeMarker()
+{
+}
+
+PlainCodeMarker::~PlainCodeMarker()
+{
+}
+
+bool PlainCodeMarker::recognizeCode( const QString& /* code */ )
+{
+ return true;
+}
+
+bool PlainCodeMarker::recognizeExtension( const QString& /* ext */ )
+{
+ return true;
+}
+
+bool PlainCodeMarker::recognizeLanguage( const QString& /* lang */ )
+{
+ return false;
+}
+
+QString PlainCodeMarker::plainName( const Node * /* node */ )
+{
+ return "";
+}
+
+QString PlainCodeMarker::plainFullName(const Node * /* node */, const Node * /* relative */)
+{
+ return "";
+}
+
+QString PlainCodeMarker::markedUpCode( const QString& code,
+ const Node * /* relative */,
+ const QString& /* dirPath */ )
+{
+ return protect( code );
+}
+
+QString PlainCodeMarker::markedUpSynopsis( const Node * /* node */,
+ const Node * /* relative */,
+ SynopsisStyle /* style */ )
+{
+ return "foo";
+}
+
+QString PlainCodeMarker::markedUpName( const Node * /* node */ )
+{
+ return "";
+}
+
+QString PlainCodeMarker::markedUpFullName( const Node * /* node */,
+ const Node * /* relative */ )
+{
+ return "";
+}
+
+QString PlainCodeMarker::markedUpEnumValue(const QString & /* enumValue */,
+ const Node * /* relative */)
+{
+ return "";
+}
+
+QString PlainCodeMarker::markedUpIncludes( const QStringList& /* includes */ )
+{
+ return "";
+}
+
+QString PlainCodeMarker::functionBeginRegExp( const QString& /* funcName */ )
+{
+ return "";
+}
+
+QString PlainCodeMarker::functionEndRegExp( const QString& /* funcName */ )
+{
+ return "";
+}
+
+QList<Section> PlainCodeMarker::sections(const InnerNode * /* innerNode */,
+ SynopsisStyle /* style */,
+ Status /* status */)
+{
+ return QList<Section>();
+}
+
+const Node *PlainCodeMarker::resolveTarget( const QString& /* target */,
+ const Tree * /* tree */,
+ const Node * /* relative */ )
+{
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/plaincodemarker.h b/tools/qdoc3/plaincodemarker.h
new file mode 100644
index 0000000000..24a1dfee46
--- /dev/null
+++ b/tools/qdoc3/plaincodemarker.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ plaincodemarker.h
+*/
+
+#ifndef PLAINCODEMARKER_H
+#define PLAINCODEMARKER_H
+
+#include "codemarker.h"
+
+QT_BEGIN_NAMESPACE
+
+class PlainCodeMarker : public CodeMarker
+{
+public:
+ PlainCodeMarker();
+ ~PlainCodeMarker();
+
+ bool recognizeCode( const QString& code );
+ bool recognizeExtension( const QString& ext );
+ bool recognizeLanguage( const QString& lang );
+ QString plainName( const Node *node );
+ QString plainFullName( const Node *node, const Node *relative );
+ QString markedUpCode( const QString& code, const Node *relative, const QString& dirPath );
+ QString markedUpSynopsis( const Node *node, const Node *relative,
+ SynopsisStyle style );
+ QString markedUpName( const Node *node );
+ QString markedUpFullName( const Node *node, const Node *relative );
+ QString markedUpEnumValue(const QString &enumValue, const Node *relative);
+ QString markedUpIncludes( const QStringList& includes );
+ QString functionBeginRegExp( const QString& funcName );
+ QString functionEndRegExp( const QString& funcName );
+ QList<Section> sections(const InnerNode *innerNode, SynopsisStyle style, Status status);
+ const Node *resolveTarget(const QString &target, const Tree *tree, const Node *relative);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/polyarchiveextractor.cpp b/tools/qdoc3/polyarchiveextractor.cpp
new file mode 100644
index 0000000000..b7fdfef5af
--- /dev/null
+++ b/tools/qdoc3/polyarchiveextractor.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ polyarchiveextractor.cpp
+*/
+
+#include "command.h"
+#include "polyarchiveextractor.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class PolyArchiveExtractor
+
+ \brief The PolyArchiveExtractor class is a class for unpacking
+ archive files.
+
+ This subclass of ArchiveExtractor contains a parameterized
+ command for doing the archive extraction.
+
+ It has an extractArchive() function you call to do the
+ actual archive extraction.
+ */
+
+/*!
+ The constructor takes the list of filename \a extensions,
+ which it passes to the base class, and the \a commandFormat,
+ which it stores locally. The \a commandFormat is a command
+ template string.
+ */
+PolyArchiveExtractor::PolyArchiveExtractor( const QStringList& extensions,
+ const QString& commandFormat )
+ : ArchiveExtractor( extensions ), cmd( commandFormat )
+{
+}
+
+/*!
+ The destructor doesn't have to do anything.
+ */
+PolyArchiveExtractor::~PolyArchiveExtractor()
+{
+}
+
+/*!
+ Call this function to do the actual archive extraction. It calls
+ the executeCommand() function to do the work. That's all it does.
+ */
+void PolyArchiveExtractor::extractArchive( const Location& location,
+ const QString& filePath,
+ const QString& outputDir )
+{
+ executeCommand( location, cmd, QStringList() << filePath << outputDir );
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/polyarchiveextractor.h b/tools/qdoc3/polyarchiveextractor.h
new file mode 100644
index 0000000000..9c637da577
--- /dev/null
+++ b/tools/qdoc3/polyarchiveextractor.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ polyarchiveextractor.h
+*/
+
+#ifndef POLYARCHIVEEXTRACTOR_H
+#define POLYARCHIVEEXTRACTOR_H
+
+#include "archiveextractor.h"
+
+QT_BEGIN_NAMESPACE
+
+class PolyArchiveExtractor : public ArchiveExtractor
+{
+ public:
+ PolyArchiveExtractor(const QStringList& extensions,
+ const QString& commandFormat);
+ ~PolyArchiveExtractor();
+
+ virtual void extractArchive(const Location& location,
+ const QString& filePath,
+ const QString& outputDir);
+
+ private:
+ QString cmd;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/polyuncompressor.cpp b/tools/qdoc3/polyuncompressor.cpp
new file mode 100644
index 0000000000..c08ede6df6
--- /dev/null
+++ b/tools/qdoc3/polyuncompressor.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "command.h"
+#include "polyuncompressor.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class PolyUncompressor
+
+ \brief The PolyUncompressor class is a class for uncompressing
+ compressed files.
+
+ This subclass of Uncompressor contains a parameterized
+ command for doing the uncompression
+
+ It has an uncompressFile() function you call to do the
+ actual uncompression.
+ */
+
+/*!
+ The constructor takes the list of filename \a extensions,
+ which it passes to the base class, and the \a commandFormat,
+ which it stores locally. The \a commandFormat is a command
+ template string.
+ */
+PolyUncompressor::PolyUncompressor( const QStringList& extensions,
+ const QString& commandFormat )
+ : Uncompressor( extensions ), cmd( commandFormat )
+{
+}
+
+/*!
+ The destructor doesn't have to do anything.
+ */
+PolyUncompressor::~PolyUncompressor()
+{
+}
+
+/*!
+ From \a filePath, derive a file path for the uncompressed
+ file and return it. If it can't figure out what the file
+ path should be, it just concatenates ".out" to the
+ \a filePath and returns that.
+ */
+QString PolyUncompressor::uncompressedFilePath( const QString& filePath )
+{
+ QStringList::ConstIterator e = fileExtensions().begin();
+ while ( e != fileExtensions().end() ) {
+ QString dotExt = "." + *e;
+ if ( filePath.endsWith(dotExt) )
+ return filePath.left( filePath.length() - dotExt.length() );
+ ++e;
+ }
+ return filePath + ".out"; // doesn't really matter
+}
+
+/*!
+ Call this function to do the actual uncompressing. It calls
+ the executeCommand() function to do the work. That's all it does.
+ */
+void PolyUncompressor::uncompressFile( const Location& location,
+ const QString& filePath,
+ const QString& outputFilePath )
+{
+ executeCommand( location, cmd,
+ QStringList() << filePath << outputFilePath );
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/polyuncompressor.h b/tools/qdoc3/polyuncompressor.h
new file mode 100644
index 0000000000..162f67271f
--- /dev/null
+++ b/tools/qdoc3/polyuncompressor.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ polyuncompressor.h
+*/
+
+#ifndef POLYUNCOMPRESSOR_H
+#define POLYUNCOMPRESSOR_H
+
+#include "uncompressor.h"
+
+QT_BEGIN_NAMESPACE
+
+class PolyUncompressor : public Uncompressor
+{
+ public:
+ PolyUncompressor(const QStringList& extensions,
+ const QString& commandFormat);
+ ~PolyUncompressor();
+
+ virtual QString uncompressedFilePath(const QString& filePath);
+ virtual void uncompressFile(const Location& location,
+ const QString& filePath,
+ const QString& outputFilePath);
+
+ private:
+ QString cmd;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/qdoc3.pro b/tools/qdoc3/qdoc3.pro
new file mode 100644
index 0000000000..3268585aab
--- /dev/null
+++ b/tools/qdoc3/qdoc3.pro
@@ -0,0 +1,108 @@
+DEFINES += QDOC2_COMPAT
+#DEFINES += QT_NO_CAST_TO_ASCII
+#DEFINES += QT_NO_CAST_FROM_ASCII
+
+QT = core xml
+CONFIG += console
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+mac:CONFIG -= app_bundle
+HEADERS += apigenerator.h \
+ archiveextractor.h \
+ atom.h \
+ bookgenerator.h \
+ ccodeparser.h \
+ codechunk.h \
+ codemarker.h \
+ codeparser.h \
+ command.h \
+ config.h \
+ cppcodemarker.h \
+ cppcodeparser.h \
+ cpptoqsconverter.h \
+ dcfsection.h \
+ doc.h \
+ editdistance.h \
+ generator.h \
+ helpprojectwriter.h \
+ htmlgenerator.h \
+ jambiapiparser.h \
+ javacodemarker.h \
+ javadocgenerator.h \
+ linguistgenerator.h \
+ location.h \
+ loutgenerator.h \
+ mangenerator.h \
+ node.h \
+ openedlist.h \
+ pagegenerator.h \
+ plaincodemarker.h \
+ polyarchiveextractor.h \
+ polyuncompressor.h \
+ qsakernelparser.h \
+ qscodemarker.h \
+ qscodeparser.h \
+ quoter.h \
+ separator.h \
+ sgmlgenerator.h \
+ text.h \
+ tokenizer.h \
+ tr.h \
+ tree.h \
+ uncompressor.h \
+ webxmlgenerator.h
+SOURCES += apigenerator.cpp \
+ archiveextractor.cpp \
+ atom.cpp \
+ bookgenerator.cpp \
+ ccodeparser.cpp \
+ codechunk.cpp \
+ codemarker.cpp \
+ codeparser.cpp \
+ command.cpp \
+ config.cpp \
+ cppcodemarker.cpp \
+ cppcodeparser.cpp \
+ cpptoqsconverter.cpp \
+ dcfsection.cpp \
+ doc.cpp \
+ editdistance.cpp \
+ generator.cpp \
+ helpprojectwriter.cpp \
+ htmlgenerator.cpp \
+ jambiapiparser.cpp \
+ javacodemarker.cpp \
+ javadocgenerator.cpp \
+ linguistgenerator.cpp \
+ location.cpp \
+ loutgenerator.cpp \
+ mangenerator.cpp \
+ main.cpp \
+ node.cpp \
+ openedlist.cpp \
+ pagegenerator.cpp \
+ plaincodemarker.cpp \
+ polyarchiveextractor.cpp \
+ polyuncompressor.cpp \
+ qsakernelparser.cpp \
+ qscodemarker.cpp \
+ qscodeparser.cpp \
+ quoter.cpp \
+ separator.cpp \
+ sgmlgenerator.cpp \
+ text.cpp \
+ tokenizer.cpp \
+ tree.cpp \
+ uncompressor.cpp \
+ webxmlgenerator.cpp \
+ yyindent.cpp
+
+
+win32 {
+ QT_WINCONFIG = release
+ CONFIG(debug, debug|release) {
+ QT_WINCONFIG = debug
+ }
+}
diff --git a/tools/qdoc3/qsakernelparser.cpp b/tools/qdoc3/qsakernelparser.cpp
new file mode 100644
index 0000000000..b856957c6a
--- /dev/null
+++ b/tools/qdoc3/qsakernelparser.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qfile.h>
+
+#include "qsakernelparser.h"
+#include "tokenizer.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+QsaKernelParser::QsaKernelParser( Tree *cppTree )
+ : cppTre( cppTree )
+{
+}
+
+QsaKernelParser::~QsaKernelParser()
+{
+}
+
+QString QsaKernelParser::language()
+{
+ return "QSA Kernel C++";
+}
+
+QString QsaKernelParser::sourceFileNameFilter()
+{
+ return "*.cpp";
+}
+
+void QsaKernelParser::parseSourceFile( const Location& location,
+ const QString& filePath,
+ Tree * /* tree */ )
+{
+ FILE *in = fopen( QFile::encodeName(filePath), "r" );
+ if ( in == 0 ) {
+ location.error( tr("Cannot open QSA kernel file '%1'").arg(filePath) );
+ return;
+ }
+
+ Location fileLocation( filePath );
+ Tokenizer fileTokenizer( fileLocation, in );
+ tokenizer = &fileTokenizer;
+ readToken();
+
+ QString ident;
+ QString className;
+ int delimDepth = 0;
+
+ while ( tok != Tok_Eoi ) {
+ if ( tok == Tok_Ident ) {
+ ident = tokenizer->lexeme();
+ readToken();
+ if ( tok == Tok_Gulbrandsen && tokenizer->braceDepth() == 0 &&
+ tokenizer->parenDepth() == 0 ) {
+ className = ident;
+ } else if ( ident.startsWith("add") && ident.endsWith("Member") &&
+ tok == Tok_LeftParen ) {
+ bool isProperty = ident.endsWith( "VariableMember" );
+ bool isStatic = ident.startsWith( "addStatic" );
+ bool isWritable = !isStatic;
+
+ readToken();
+ if ( tok == Tok_String ) {
+ QString member = tokenizer->lexeme();
+ member = member.mid( 1, member.length() - 2 );
+
+ readToken();
+ if ( tok == Tok_Comma )
+ readToken();
+ if ( tok == Tok_Ident && tokenizer->lexeme() == "QSMember" )
+ readToken();
+ if ( tok == Tok_LeftParen ) {
+ delimDepth++;
+ readToken();
+ }
+
+ while ( tok != Tok_Eoi && tok != Tok_RightParen &&
+ tok != Tok_Semicolon ) {
+ if ( tok == Tok_Ident ) {
+ ident = tokenizer->lexeme();
+ if ( ident == "Custom" ) {
+ isProperty = true;
+ } else if ( ident == "AttributeNonWritable" ) {
+ isWritable = false;
+ } else if ( ident == "AttributeStatic" ) {
+ isStatic = true;
+ }
+ }
+ readToken();
+ }
+
+ ClassNode *classe =
+ (ClassNode *) cppTre->findNode( QStringList(className),
+ Node::Class );
+ if ( classe == 0 ) {
+ classe = new ClassNode( cppTre->root(), className );
+ classe->setLocation( tokenizer->location() );
+ }
+
+ if ( isProperty ) {
+ PropertyNode *property = new PropertyNode(classe, member);
+ property->setLocation( tokenizer->location() );
+ property->setDataType( "Object" );
+#if 0
+ property->setGetter( member );
+ if ( isWritable ) {
+ QString setter = member;
+ setter[0] = setter[0].toUpper();
+ setter.prepend( "set" );
+ property->setSetter( setter );
+ }
+#endif
+ } else {
+ FunctionNode *func = new FunctionNode( classe, member );
+ func->setLocation( tokenizer->location() );
+ func->setAccess( FunctionNode::Public );
+ func->setMetaness( FunctionNode::Slot );
+ if ( member == "toLocaleString" ||
+ member == "toString" ) {
+ func->setReturnType( "QString" );
+ } else if ( member == "valueOf" ) {
+ func->setReturnType( "Object" );
+ } else {
+ func->setReturnType( "Object" );
+ func->addParameter( Parameter("...") );
+ }
+ func->setStatic( false ); // ###
+ }
+ }
+ }
+ } else {
+ readToken();
+ }
+ }
+ fclose( in );
+}
+
+void QsaKernelParser::doneParsingSourceFiles( Tree * /* tree */ )
+{
+}
+
+void QsaKernelParser::readToken()
+{
+ tok = tokenizer->getToken();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/qsakernelparser.h b/tools/qdoc3/qsakernelparser.h
new file mode 100644
index 0000000000..59273cdc7c
--- /dev/null
+++ b/tools/qdoc3/qsakernelparser.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ qsakernelparser.h
+*/
+
+#ifndef QSAKERNELPARSER_H
+#define QSAKERNELPARSER_H
+
+#include "codeparser.h"
+
+QT_BEGIN_NAMESPACE
+
+class Tokenizer;
+
+class QsaKernelParser : public CodeParser
+{
+public:
+ QsaKernelParser( Tree *cppTree );
+ ~QsaKernelParser();
+
+ virtual QString language();
+ virtual QString sourceFileNameFilter();
+ virtual void parseSourceFile( const Location& location,
+ const QString& filePath, Tree *tree );
+ virtual void doneParsingSourceFiles( Tree *tree );
+
+private:
+ void readToken();
+
+ Tree *cppTre;
+ Tokenizer *tokenizer;
+ int tok;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/qscodemarker.cpp b/tools/qdoc3/qscodemarker.cpp
new file mode 100644
index 0000000000..ed89b60527
--- /dev/null
+++ b/tools/qdoc3/qscodemarker.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ qscodemarker.cpp
+*/
+
+#include "node.h"
+#include "qscodemarker.h"
+
+QT_BEGIN_NAMESPACE
+
+QsCodeMarker::QsCodeMarker()
+{
+}
+
+QsCodeMarker::~QsCodeMarker()
+{
+}
+
+bool QsCodeMarker::recognizeCode( const QString& /* code */ )
+{
+ return true;
+}
+
+bool QsCodeMarker::recognizeExtension( const QString& ext )
+{
+ return ext == "js" || ext == "qs";
+}
+
+bool QsCodeMarker::recognizeLanguage( const QString& lang )
+{
+ return lang == "JavaScript" || lang == "Qt Script";
+}
+
+QString QsCodeMarker::plainName( const Node *node )
+{
+ QString name = node->name();
+ if ( node->type() == Node::Function )
+ name += "()";
+ return name;
+}
+
+QString QsCodeMarker::plainFullName( const Node *node, const Node * /* relative */ )
+{
+ QString fullName;
+ for ( ;; ) {
+ fullName.prepend( plainName(node) );
+ if ( node->parent()->name().isEmpty() )
+ break;
+ node = node->parent();
+ fullName.prepend(".");
+ }
+ return fullName;
+}
+
+QString QsCodeMarker::markedUpCode( const QString& code,
+ const Node * /* relative */,
+ const QString& /* dirPath */ )
+{
+ return protect( code );
+}
+
+QString QsCodeMarker::markedUpSynopsis( const Node *node,
+ const Node * /* relative */,
+ SynopsisStyle style )
+{
+ QString synopsis;
+ QStringList extras;
+ QString name;
+
+ name = taggedNode( node );
+ if ( style != Detailed )
+ name = linkTag( node, name );
+ name = "<@name>" + name + "</@name>";
+
+ if ( style == Detailed && !node->parent()->name().isEmpty() &&
+ node->type() != Node::Enum )
+ name.prepend( taggedNode(node->parent()) + "." );
+
+ switch ( node->type() ) {
+ case Node::Class:
+ synopsis = "class " + name;
+ break;
+ case Node::Function:
+ {
+ const FunctionNode *func = (const FunctionNode *) node;
+
+ synopsis = name;
+
+ if ( style == SeparateList ) {
+ synopsis += "()";
+ } else {
+ synopsis += " (";
+ if ( !func->parameters().isEmpty() ) {
+ synopsis += " ";
+ int numOptional = 0;
+ QList<Parameter>::ConstIterator p = func->parameters().begin();
+ while ( p != func->parameters().end() ) {
+ if ( !(*p).defaultValue().isEmpty() ) {
+ if ( p == func->parameters().begin() ) {
+ synopsis += "[ ";
+ } else {
+ synopsis += " [ , ";
+ }
+ numOptional++;
+ } else {
+ if ( p != func->parameters().begin() )
+ synopsis += ", ";
+ }
+ if ( !(*p).name().isEmpty() )
+ synopsis += "<@param>" + protect( (*p).name() ) +
+ "</@param> : ";
+ synopsis += protect( (*p).leftType() );
+ ++p;
+ }
+ for ( int i = 0; i < numOptional; i++ )
+ synopsis += " ]";
+ synopsis += " ";
+ }
+ synopsis += ")";
+ }
+
+ if ( style != SeparateList && !func->returnType().isEmpty() )
+ synopsis += " : " + protect( func->returnType() );
+
+ if ( style == Detailed && func->metaness() == FunctionNode::Signal )
+ extras << "[signal]";
+ }
+ break;
+ case Node::Property:
+ {
+ const PropertyNode *property = (const PropertyNode *) node;
+
+ synopsis = name;
+ if ( style != SeparateList )
+ synopsis += " : " + property->dataType();
+ if ( style == Detailed && property->setters().isEmpty() )
+ extras << "[read only]";
+ }
+ break;
+ case Node::Enum:
+ {
+ /*
+ The letters A to F and X (upper- and lower-case) can
+ appear in a hexadecimal constant (e.g. 0x3F).
+ */
+ QRegExp letterRegExp( "[G-WYZg-wyz_]" );
+ const EnumNode *enume = (const EnumNode *) node;
+
+ synopsis = name;
+ if ( style == Summary && !enume->items().isEmpty() ) {
+ synopsis += " : ";
+ QString comma;
+ QList<EnumItem>::ConstIterator it = enume->items().begin();
+ while ( it != enume->items().end() ) {
+ if ( enume->itemAccess((*it).name()) == Node::Public ) {
+ synopsis += comma;
+ synopsis += (*it).name();
+ if ( (*it).value().indexOf(letterRegExp) != -1 )
+ synopsis += " = " + (*it).value();
+ comma = ", ";
+ }
+ ++it;
+ }
+ }
+ }
+ break;
+ case Node::Namespace:
+ case Node::Typedef:
+ default:
+ synopsis = name;
+ }
+
+ if ( style == Summary ) {
+ if ( node->status() == Node::Preliminary ) {
+ extras << "(preliminary)";
+ } else if ( node->status() == Node::Deprecated ) {
+ extras << "(deprecated)";
+ } else if ( node->status() == Node::Obsolete ) {
+ extras << "(obsolete)";
+ }
+ }
+
+ QString extra;
+ if ( !extras.isEmpty() )
+ extra = "<@extra>" + extras.join(" ") + "</@extra>";
+ return synopsis + extra;
+}
+
+QString QsCodeMarker::markedUpName( const Node *node )
+{
+ QString name = linkTag( node, taggedNode(node) );
+ if ( node->type() == Node::Function )
+ name += "()";
+ return name;
+}
+
+QString QsCodeMarker::markedUpFullName( const Node *node,
+ const Node * /* relative */ )
+{
+ QString fullName;
+ for ( ;; ) {
+ fullName.prepend( markedUpName(node) );
+ if ( node->parent()->name().isEmpty() )
+ break;
+ node = node->parent();
+ fullName.prepend( "<@op>.</@op>" );
+ }
+ return fullName;
+}
+
+QString QsCodeMarker::markedUpEnumValue(const QString & /* enumValue */,
+ const Node * /* relative */)
+{
+ return QString();
+}
+
+QString QsCodeMarker::markedUpIncludes( const QStringList& /* includes */ )
+{
+ return QString();
+}
+
+QString QsCodeMarker::functionBeginRegExp( const QString& funcName )
+{
+ return "^function[ \t].*\\b" + QRegExp::escape( funcName );
+}
+
+QString QsCodeMarker::functionEndRegExp( const QString& /* funcName */ )
+{
+ return "^}";
+}
+
+QList<Section> QsCodeMarker::sections( const InnerNode *inner, SynopsisStyle style, Status status )
+{
+ QList<Section> sections;
+
+ if (inner->type() != Node::Class)
+ return sections;
+
+ const ClassNode *classe = static_cast<const ClassNode *>(inner);
+
+ if ( style == Summary ) {
+ FastSection enums(classe, "Enums", "enum", "enums");
+ FastSection functions(classe, "Functions", "function", "functions");
+ FastSection readOnlyProperties(classe, "Read-Only Properties", "property", "properties");
+ FastSection signalz(classe, "Signals", "signal", "signals");
+ FastSection writableProperties(classe, "Writable Properties", "property", "properties");
+
+ QStack<const ClassNode *> stack;
+ stack.push( classe );
+
+ while ( !stack.isEmpty() ) {
+ const ClassNode *ancestorClass = stack.pop();
+
+ NodeList::ConstIterator c = ancestorClass->childNodes().begin();
+ while ( c != ancestorClass->childNodes().end() ) {
+ if ( (*c)->access() == Node::Public ) {
+ if ( (*c)->type() == Node::Enum ) {
+ insert( enums, *c, style, status );
+ } else if ( (*c)->type() == Node::Function ) {
+ const FunctionNode *func = (const FunctionNode *) *c;
+ if ( func->metaness() == FunctionNode::Signal ) {
+ insert( signalz, *c, style, status );
+ } else {
+ insert( functions, *c, style, status );
+ }
+ } else if ( (*c)->type() == Node::Property ) {
+ const PropertyNode *property =
+ (const PropertyNode *) *c;
+ if ( property->setters().isEmpty() ) {
+ insert( readOnlyProperties, *c, style, status );
+ } else {
+ insert( writableProperties, *c, style, status );
+ }
+ }
+ }
+ ++c;
+ }
+
+ QList<RelatedClass>::ConstIterator r = ancestorClass->baseClasses().begin();
+ while ( r != ancestorClass->baseClasses().end() ) {
+ stack.prepend( (*r).node );
+ ++r;
+ }
+ }
+ append( sections, enums );
+ append( sections, writableProperties );
+ append( sections, readOnlyProperties );
+ append( sections, functions );
+ append( sections, signalz );
+ } else if ( style == Detailed ) {
+ FastSection enums( classe, "Enum Documentation" );
+ FastSection functionsAndSignals( classe, "Function and Signal Documentation" );
+ FastSection properties( classe, "Property Documentation" );
+
+ NodeList::ConstIterator c = classe->childNodes().begin();
+ while ( c != classe->childNodes().end() ) {
+ if ( (*c)->access() == Node::Public ) {
+ if ( (*c)->type() == Node::Enum ) {
+ insert( enums, *c, style, status );
+ } else if ( (*c)->type() == Node::Function ) {
+ insert( functionsAndSignals, *c, style, status );
+ } else if ( (*c)->type() == Node::Property ) {
+ insert( properties, *c, style, status );
+ }
+ }
+ ++c;
+ }
+ append( sections, enums );
+ append( sections, properties );
+ append( sections, functionsAndSignals );
+ } else { // ( style == SeparateList )
+ FastSection all( classe );
+
+ QStack<const ClassNode *> stack;
+ stack.push( classe );
+
+ while ( !stack.isEmpty() ) {
+ const ClassNode *ancestorClass = stack.pop();
+
+ NodeList::ConstIterator c = ancestorClass->childNodes().begin();
+ while ( c != ancestorClass->childNodes().end() ) {
+ if ( (*c)->access() == Node::Public )
+ insert( all, *c, style, status );
+ ++c;
+ }
+
+ QList<RelatedClass>::ConstIterator r = ancestorClass->baseClasses().begin();
+ while ( r != ancestorClass->baseClasses().end() ) {
+ stack.prepend( (*r).node );
+ ++r;
+ }
+ }
+ append( sections, all );
+ }
+ return sections;
+}
+
+const Node *QsCodeMarker::resolveTarget( const QString& /* target */,
+ const Tree * /* tree */,
+ const Node * /* relative */ )
+{
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/qscodemarker.h b/tools/qdoc3/qscodemarker.h
new file mode 100644
index 0000000000..a283e88cff
--- /dev/null
+++ b/tools/qdoc3/qscodemarker.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ qscodemarker.h
+*/
+
+#ifndef QSCODEMARKER_H
+#define QSCODEMARKER_H
+
+#include "codemarker.h"
+
+QT_BEGIN_NAMESPACE
+
+class QsCodeMarker : public CodeMarker
+{
+public:
+ QsCodeMarker();
+ ~QsCodeMarker();
+
+ bool recognizeCode( const QString& code );
+ bool recognizeExtension( const QString& ext );
+ bool recognizeLanguage( const QString& lang );
+ QString plainName(const Node *node);
+ QString plainFullName(const Node *node, const Node *relative);
+ QString markedUpCode( const QString& code, const Node *relative,
+ const QString& dirPath );
+ QString markedUpSynopsis( const Node *node, const Node *relative,
+ SynopsisStyle style );
+ QString markedUpName( const Node *node );
+ QString markedUpFullName( const Node *node, const Node *relative );
+ QString markedUpEnumValue(const QString &enumValue, const Node *relative);
+ QString markedUpIncludes( const QStringList& includes );
+ QList<Section> sections(const InnerNode *innerNode, SynopsisStyle style, Status status);
+ QString functionBeginRegExp( const QString& funcName );
+ QString functionEndRegExp( const QString& funcName );
+ const Node *resolveTarget( const QString& target, const Tree *tree, const Node *relative );
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/qscodeparser.cpp b/tools/qdoc3/qscodeparser.cpp
new file mode 100644
index 0000000000..1a8902e331
--- /dev/null
+++ b/tools/qdoc3/qscodeparser.cpp
@@ -0,0 +1,944 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ qscodeparser.cpp
+*/
+
+#include <qfile.h>
+#include <qregexp.h>
+
+#include "config.h"
+#include "qscodeparser.h"
+#include "text.h"
+#include "tokenizer.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+#define CONFIG_QUICK "quick"
+#define CONFIG_REPLACES "replaces"
+
+#define COMMAND_BRIEF Doc::alias( "brief")
+#define COMMAND_CODE Doc::alias( "code")
+#define COMMAND_ENDCODE Doc::alias( "endcode")
+#define COMMAND_ENDQUICKCODE Doc::alias( "endquickcode")
+#define COMMAND_FILE Doc::alias( "file")
+#define COMMAND_GROUP Doc::alias( "group")
+#define COMMAND_MODULE Doc::alias( "module")
+#define COMMAND_PAGE Doc::alias( "page")
+#define COMMAND_QUICKCLASS Doc::alias( "quickclass")
+#define COMMAND_QUICKCODE Doc::alias( "quickcode")
+#define COMMAND_QUICKENUM Doc::alias( "quickenum")
+#define COMMAND_QUICKFN Doc::alias( "quickfn")
+#define COMMAND_QUICKIFY Doc::alias( "quickify")
+#define COMMAND_QUICKPROPERTY Doc::alias( "quickproperty")
+#define COMMAND_PROTECTED Doc::alias( "protected")
+#define COMMAND_REPLACE Doc::alias( "replace")
+
+static QString balancedParens = "(?:[^()]+|\\([^()]*\\))*";
+
+QsCodeParser::QsCodeParser(Tree *cppTree)
+ : cppTre(cppTree), qsTre(0), replaceRegExp("/(.+)/([^/]*)/")
+{
+}
+
+QsCodeParser::~QsCodeParser()
+{
+}
+
+void QsCodeParser::initializeParser(const Config& config)
+{
+ CppCodeParser::initializeParser(config);
+
+ nodeTypeMap.insert(COMMAND_QUICKCLASS, Node::Class);
+ nodeTypeMap.insert(COMMAND_QUICKENUM, Node::Enum);
+ nodeTypeMap.insert(COMMAND_QUICKPROPERTY, Node::Property);
+ nodeTypeMap.insert(COMMAND_QUICKFN, Node::Function);
+
+ QString quickDotReplaces = CONFIG_QUICK + Config::dot + CONFIG_REPLACES;
+ QStringList replaces = config.getStringList(quickDotReplaces);
+ QStringList::ConstIterator r = replaces.begin();
+ while (r != replaces.end()) {
+ if (replaceRegExp.exactMatch(*r)) {
+ QRegExp before(replaceRegExp.cap(1));
+ before.setMinimal(true);
+ QString after = replaceRegExp.cap(2);
+
+ if (before.isValid()) {
+ replaceBefores << before;
+ replaceAfters << after;
+ }
+ else {
+ config.lastLocation().warning(
+ tr("Invalid regular expression '%1'")
+ .arg(before.pattern()));
+ }
+ }
+ else {
+ config.lastLocation().warning(tr("Bad syntax in '%1'")
+ .arg(quickDotReplaces));
+ }
+ ++r;
+ }
+}
+
+void QsCodeParser::terminateParser()
+{
+ nodeTypeMap.clear();
+ classesWithNoQuickDoc.clear();
+ replaceBefores.clear();
+ replaceAfters.clear();
+ CppCodeParser::terminateParser();
+}
+
+QString QsCodeParser::language()
+{
+ return "Qt Script";
+}
+
+QString QsCodeParser::headerFileNameFilter()
+{
+ return "*";
+}
+
+QString QsCodeParser::sourceFileNameFilter()
+{
+ return "*.qs *.qsd";
+}
+
+void QsCodeParser::parseHeaderFile(const Location& location,
+ const QString& filePath,
+ Tree *tree)
+{
+ qsTre = tree;
+
+ FILE *in = fopen(QFile::encodeName(filePath), "r");
+ if (in == 0) {
+ location.error(tr("Cannot open Qt Script class list '%1'")
+ .arg(filePath));
+ return;
+ }
+
+ Location fileLocation(filePath);
+ Tokenizer fileTokenizer(fileLocation, in);
+ int tok = fileTokenizer.getToken();
+ while (tok != Tok_Eoi) {
+ if (tok == Tok_Ident) {
+ ClassNode *quickClass = new ClassNode(qsTre->root(),
+ fileTokenizer.lexeme());
+ quickClass->setLocation(fileTokenizer.location());
+ }
+ else {
+ fileTokenizer.location().error(tr("Unexpected token '%1' in Qt"
+ " Script class list")
+ .arg(fileTokenizer.lexeme()));
+ break;
+ }
+ tok = fileTokenizer.getToken();
+ }
+ fclose(in);
+}
+
+void QsCodeParser::parseSourceFile(const Location& location,
+ const QString& filePath,
+ Tree *tree)
+{
+ qsTre = tree;
+ CppCodeParser::parseSourceFile(location, filePath, tree);
+}
+
+void QsCodeParser::doneParsingHeaderFiles(Tree *tree)
+{
+ NodeList::ConstIterator c = tree->root()->childNodes().begin();
+ while (c != tree->root()->childNodes().end()) {
+ if ((*c)->type() == Node::Class)
+ quickifyClass((ClassNode *) *c);
+ ++c;
+ }
+ cppTre->root()->deleteChildren(); // save memory
+ tree->resolveInheritance();
+ tree->resolveProperties();
+}
+
+void QsCodeParser::doneParsingSourceFiles(Tree *tree)
+{
+ tree->root()->normalizeOverloads();
+
+ NodeList::ConstIterator c = tree->root()->childNodes().begin();
+ while (c != tree->root()->childNodes().end()) {
+ if ((*c)->type() == Node::Class) {
+ QMap<QString, Node *>::ConstIterator cwnqd =
+ classesWithNoQuickDoc.find((*c)->name());
+ if (cwnqd != classesWithNoQuickDoc.end()) {
+ (*cwnqd)->location().warning(tr("No '\\%1' documentation for"
+ " class '%2'")
+ .arg(COMMAND_QUICKCLASS)
+ .arg(cwnqd.key()));
+ (*cwnqd)->setDoc(Doc(), true);
+ }
+ }
+ ++c;
+ }
+
+ // ### check which enum types are used
+}
+
+FunctionNode *QsCodeParser::findFunctionNode(const QString& synopsis,
+ Tree *tree)
+{
+ QStringList parentPath;
+ FunctionNode *clone;
+ FunctionNode *func = 0;
+
+ if (makeFunctionNode(synopsis, &parentPath, &clone)) {
+ func = tree->findFunctionNode(parentPath, clone);
+ delete clone;
+ }
+ return func;
+}
+
+QSet<QString> QsCodeParser::topicCommands()
+{
+ return QSet<QString>() << COMMAND_FILE << COMMAND_GROUP << COMMAND_MODULE
+ << COMMAND_PAGE << COMMAND_QUICKCLASS
+ << COMMAND_QUICKENUM << COMMAND_QUICKFN
+ << COMMAND_QUICKPROPERTY;
+}
+
+Node *QsCodeParser::processTopicCommand(const Doc& doc,
+ const QString& command,
+ const QString& arg)
+{
+ if (command == COMMAND_QUICKFN) {
+ QStringList parentPath;
+ FunctionNode *quickFunc = 0;
+ FunctionNode *clone;
+
+ if (makeFunctionNode(arg, &parentPath, &clone)) {
+ FunctionNode *kernelFunc = findKernelFunction(parentPath,
+ clone->name());
+ if (kernelFunc != 0)
+ kernelFunc->setAccess(Node::Private);
+
+ quickFunc = qsTre->findFunctionNode(parentPath, clone);
+ if (quickFunc == 0 && kernelFunc != 0) {
+ quickFunc = new FunctionNode(kernelFunc->parent(),
+ kernelFunc->name());
+ quickFunc->setLocation(kernelFunc->location());
+ quickFunc->setReturnType(clone->returnType());
+ quickFunc->setParameters(clone->parameters());
+ }
+
+ if (quickFunc == 0) {
+ doc.location().warning(tr("Cannot find '%1' specified with '\\%2'")
+ .arg(arg).arg(command));
+ }
+ else {
+ quickFunc->setAccess(Node::Public);
+ QStringList qtParams = quickFunc->parameterNames();
+ quickFunc->borrowParameterNames(clone);
+ QStringList quickParams = quickFunc->parameterNames();
+ setQuickDoc(quickFunc, doc, qtParams, quickParams);
+ }
+ delete clone;
+ }
+ else {
+ doc.location().warning(tr("Cannot find '%1' specified with '\\%2'")
+ .arg(arg).arg(command));
+ }
+ return 0;
+ }
+ else if (nodeTypeMap.contains(command)) {
+ QStringList subArgs = arg.split(" ");
+ QString dataType;
+
+ if (subArgs.count() == 3 && subArgs[1] == ":") {
+ dataType = subArgs[2];
+ }
+ else if (subArgs.count() != 1) {
+ doc.location().warning(tr("Invalid syntax in '\\%1'")
+ .arg(command));
+ }
+
+ QStringList path = subArgs[0].split(".");
+ Node *quickNode = qsTre->findNode(path, nodeTypeMap[command]);
+ if (quickNode == 0) {
+ doc.location().warning(tr("Cannot find '%1' specified with '\\%2'")
+ .arg(arg).arg(command));
+ }
+ else {
+ setQuickDoc(quickNode, doc);
+ if (quickNode->type() == Node::Class) {
+ classesWithNoQuickDoc.remove(quickNode->name());
+ if (doc.briefText().isEmpty())
+ doc.location().warning(tr("Missing '\\%1' for class '%2'")
+ .arg(COMMAND_BRIEF)
+ .arg(quickNode->name()));
+ }
+ else if (quickNode->type() == Node::Property) {
+ PropertyNode *quickProperty = (PropertyNode *) quickNode;
+ if (quickProperty->dataType() == "Object") {
+ if (dataType.isEmpty()) {
+ doc.location().warning(tr("Missing data type in '\\%1'"
+ " (assuming 'Object')")
+ .arg(command));
+ }
+ else {
+ quickProperty->setDataType(dataType);
+ }
+ }
+ else if (dataType != quickProperty->dataType()) {
+ doc.location().warning(tr("Ignored contradictory data type"
+ " in '\\%1'")
+ .arg(command));
+ }
+ }
+ }
+ return 0;
+ }
+ else {
+ return CppCodeParser::processTopicCommand(doc, command, arg);
+ }
+}
+
+QSet<QString> QsCodeParser::otherMetaCommands()
+{
+ return commonMetaCommands() << COMMAND_ENDQUICKCODE << COMMAND_QUICKCODE
+ << COMMAND_QUICKIFY << COMMAND_REPLACE;
+}
+
+void QsCodeParser::processOtherMetaCommand(const Doc& doc,
+ const QString& command,
+ const QString& arg,
+ Node *node)
+{
+ if (command == COMMAND_PROTECTED) {
+ doc.location().warning(tr("Cannot use '\\%1' in %2")
+ .arg(COMMAND_PROTECTED).arg(language()));
+ }
+ else {
+ CppCodeParser::processOtherMetaCommand(doc,command,arg,node);
+ }
+}
+
+ClassNode *QsCodeParser::tryClass(const QString& className)
+{
+ return (ClassNode*) cppTre->findNode(QStringList(className),Node::Class);
+}
+
+FunctionNode *QsCodeParser::findKernelFunction(const QStringList& parentPath,
+ const QString& name)
+{
+ FunctionNode clone(0, name);
+ clone.setReturnType("Object");
+ clone.addParameter(Parameter("..."));
+ return qsTre->findFunctionNode(parentPath, &clone);
+}
+
+void QsCodeParser::extractRegExp(const QRegExp& regExp,
+ QString& source,
+ const Doc& doc)
+{
+ QRegExp blankLineRegExp(
+ "[ \t]*(?:\n(?:[ \t]*\n)+[ \t]*|[ \n\t]*\\\\code|"
+ "\\\\endcode[ \n\t]*)");
+ QStringList paras = source.trimmed().split(blankLineRegExp);
+ paras = paras.filter(regExp);
+ if (paras.count() == 0) {
+ doc.location().warning(tr("Cannot find regular expression '%1'")
+ .arg(regExp.pattern()));
+ }
+ else if (paras.count() > 1) {
+ doc.location().warning(tr("Regular rexpression '%1' matches multiple"
+ "times").arg(regExp.pattern()));
+ }
+ else {
+ source = paras.first() + "\n\n";
+ }
+}
+
+void QsCodeParser::extractTarget(const QString& target,
+ QString& source,
+ const Doc& doc)
+{
+ QRegExp targetRegExp(
+ "(\\\\target\\s+(\\S+)[^\n]*\n"
+ "(?:(?!\\s*\\\\code)[^\n]+\n|\\s*\\\\code.*\\\\endcode\\s*\n)*)"
+ "(?:\\s*\n|[^\n]*$)");
+ targetRegExp.setMinimal(true);
+
+ int pos = 0;
+ while ((pos = source.indexOf(targetRegExp, pos)) != -1) {
+ if (targetRegExp.cap(2) == target) {
+ source = targetRegExp.cap(1) + "\n\n";
+ return;
+ }
+ pos += targetRegExp.matchedLength();
+ }
+ doc.location().warning(tr("Cannot find target '%1'").arg(target));
+}
+
+void QsCodeParser::renameParameters(QString& source,
+ const Doc& /* doc */,
+ const QStringList& qtParams,
+ const QStringList& quickParams)
+{
+ QRegExp paramRegExp("(\\\\a\\s*\\{?\\s*)([A-Za-z0-9_]+)");
+
+ int pos = 0;
+ while ((pos = paramRegExp.indexIn(source, pos)) != -1) {
+ pos += paramRegExp.cap(1).length();
+ QString before = paramRegExp.cap(2);
+ int index = qtParams.indexOf(before);
+ if (index != -1) {
+ QString after = quickParams[index];
+ source.replace(pos, before.size(), after);
+ }
+ }
+}
+
+void QsCodeParser::applyReplacementList(QString& source, const Doc& doc)
+{
+ QStringList args = doc.metaCommandArgs(COMMAND_REPLACE);
+ QStringList::ConstIterator a = args.begin();
+ while (a != args.end()) {
+ if (replaceRegExp.exactMatch(*a)) {
+ QRegExp before(replaceRegExp.cap(1));
+ before.setMinimal(true);
+ QString after = replaceRegExp.cap(2);
+
+ if (before.isValid()) {
+ int oldLen = source.size();
+ source.replace(before, after);
+
+ // this condition is sufficient but not necessary
+ if (oldLen == source.size() && !source.contains(after))
+ doc.location().warning(
+ tr("Regular expression '%1' did not match anything")
+ .arg(before.pattern()));
+ }
+ else {
+ doc.location().warning(
+ tr("Invalid regular expression '%1'")
+ .arg(before.pattern()));
+ }
+ }
+ else {
+ doc.location().warning(tr("Bad syntax in '\\%1'")
+ .arg(COMMAND_REPLACE));
+ }
+ ++a;
+ }
+
+ QRegExp codeRegExp("\\\\" + COMMAND_CODE + "(.*)\\\\" + COMMAND_ENDCODE);
+ codeRegExp.setMinimal(true);
+
+ QRegExp quickcodeRegExp(
+ "\\\\" + COMMAND_QUICKCODE + "(.*)\\\\" + COMMAND_ENDQUICKCODE);
+ quickcodeRegExp.setMinimal(true);
+
+ int quickcodePos = doc.source().indexOf(quickcodeRegExp);
+ if (quickcodePos != -1) {
+ int codePos = source.indexOf(codeRegExp);
+ if (codePos == -1) {
+ doc.location().warning(
+ tr("Cannot find any '\\%1' snippet corresponding to '\\%2'")
+ .arg(COMMAND_CODE).arg(COMMAND_QUICKCODE));
+ }
+ else {
+ source.replace(codeRegExp.pos(1), codeRegExp.cap(1).length(),
+ quickcodeRegExp.cap(1));
+ codePos = codeRegExp.pos(1) + quickcodeRegExp.cap(1).length();
+
+ if (doc.source().indexOf(quickcodeRegExp, quickcodePos + 1) != -1) {
+ doc.location().warning(
+ tr("Cannot use '\\%1' twice in a row")
+ .arg(COMMAND_QUICKCODE));
+ }
+ else if (source.indexOf(codeRegExp, codePos + 1) != -1) {
+ doc.location().warning(tr("Ambiguous '\\%1'")
+ .arg(COMMAND_QUICKCODE));
+ }
+ }
+ }
+}
+
+void QsCodeParser::quickifyClass(ClassNode *quickClass)
+{
+ QString qtClassName = quickClass->name();
+ QString bare = quickClass->name();
+ if (bare != "Qt" && bare != "Object") {
+ if (bare.startsWith("Q")) {
+ bare = bare.mid(1);
+ }
+ else {
+ qtClassName.prepend("Q");
+ classesWithNoQ.insert(bare);
+ }
+ }
+
+ ClassNode *qtClass = 0;
+ ClassNode *wrapperClass = 0;
+
+ if ((wrapperClass = tryClass("Quick" + bare)) != 0 ||
+ (wrapperClass = tryClass("QS" + bare + "Class")) != 0) {
+ qtClass = tryClass(qtClassName);
+ if (qtClass == 0) {
+ qtClass = wrapperClass;
+ wrapperClass = 0;
+ }
+ }
+ else if ((wrapperClass = tryClass("Quick" + bare + "Ptr")) != 0) {
+ QRegExp ptrToQtType("(Q[A-Za-z0-9_]+)\\s*\\*");
+ FunctionNode *ctor =
+ wrapperClass->findFunctionNode(wrapperClass->name());
+ if (ctor != 0 && !ctor->parameters().isEmpty() &&
+ ptrToQtType.exactMatch(ctor->parameters().first().leftType()))
+ qtClassName = ptrToQtType.cap(1);
+ qtClass = tryClass(qtClassName);
+ }
+ else {
+ wrapperClass = tryClass("Q" + bare + "Ptr");
+ if (wrapperClass == 0)
+ wrapperClass = tryClass("Quick" + bare + "Interface");
+ qtClass = tryClass(qtClassName);
+ }
+
+ if (qtClass == 0) {
+ if (wrapperClass == 0) {
+ quickClass->location().warning(tr("Cannot find Qt class '%1'")
+ .arg(qtClassName));
+ }
+ else {
+ quickClass->location().warning(tr("Cannot find Qt class '%1'"
+ " wrapped by '%2'")
+ .arg(qtClassName)
+ .arg(wrapperClass->name()));
+ }
+ return;
+ }
+
+ QList<RelatedClass>::ConstIterator r = qtClass->baseClasses().begin();
+ while (r != qtClass->baseClasses().end()) {
+ ClassNode *quickBaseClass = cpp2qs.findClassNode(qsTre,
+ (*r).node->name());
+ if (quickBaseClass)
+ quickClass->addBaseClass((*r).access, quickBaseClass);
+ ++r;
+ }
+ if (quickClass->baseClasses().isEmpty() && quickClass->name() != "Object")
+ quickClass->addBaseClass(Node::Public,
+ cpp2qs.findClassNode(qsTre,"Object"));
+
+ QSet<QString> funcBlackList;
+ QSet<QString> propertyBlackList;
+
+ NodeList children;
+ if (wrapperClass != 0) {
+ children = wrapperClass->childNodes();
+
+ funcBlackList.insert(wrapperClass->name());
+ funcBlackList.insert("~" + wrapperClass->name());
+ }
+ children += qtClass->childNodes();
+
+ for (int pass = 0; pass < 2; pass++) {
+ NodeList::ConstIterator c = children.begin();
+ while (c != children.end()) {
+ if ((*c)->access() != Node::Private &&
+ (*c)->status() == Node::Commendable) {
+ if (pass == 0) {
+ if ((*c)->type() == Node::Enum) {
+ EnumNode *enume = (EnumNode *) *c;
+ quickifyEnum(quickClass, enume);
+ }
+ else if ((*c)->type() == Node::Property) {
+ if (!propertyBlackList.contains((*c)->name())) {
+ PropertyNode *property = (PropertyNode *) *c;
+ quickifyProperty(quickClass, qtClass, property);
+ if (!property->getters().isEmpty())
+ funcBlackList.insert(property->getters().first()->name());
+ if (!property->setters().isEmpty())
+ funcBlackList.insert(property->setters().first()->name());
+ if (!property->resetters().isEmpty())
+ funcBlackList.insert(property->resetters().first()->name());
+ propertyBlackList.insert(property->name());
+ }
+ }
+ }
+ else if ((*c)->type() == Node::Function) {
+ FunctionNode *func = (FunctionNode *) *c;
+ quickifyFunction(quickClass, qtClass, func,
+ funcBlackList.contains((*c)->name()) &&
+ func->parameters().count() < 2);
+ }
+ }
+ ++c;
+ }
+ }
+ setQtDoc(quickClass, qtClass->doc());
+ classesWithNoQuickDoc.insert(quickClass->name(), quickClass);
+}
+
+void QsCodeParser::quickifyEnum(ClassNode *quickClass, EnumNode *enume)
+{
+ EnumNode *quickEnum = new EnumNode(quickClass, enume->name());
+ quickEnum->setLocation(enume->location());
+#if 0 // ### not yet
+ quickEnum->setAccess(Node::Protected);
+#endif
+
+ QList<EnumItem>::ConstIterator it = enume->items().begin();
+ while (it != enume->items().end()) {
+ QString name = (*it).name();
+ QString value = (*it).value();
+ quickEnum->addItem(EnumItem(name, value));
+ ++it;
+ }
+ setQtDoc(quickEnum, enume->doc());
+}
+
+void QsCodeParser::quickifyFunction(ClassNode *quickClass, ClassNode *qtClass,
+ FunctionNode *func, bool onBlackList)
+{
+ if (func->metaness() == FunctionNode::Dtor)
+ return;
+
+ FunctionNode *kernelFunc = findKernelFunction(
+ QStringList() << quickClass->name(), func->name());
+
+ QString quickName = func->name();
+ if (func->metaness() == FunctionNode::Ctor)
+ quickName = quickClass->name();
+ FunctionNode *quickFunc = new FunctionNode(quickClass, quickName);
+ quickFunc->setLocation(func->location());
+
+ if (onBlackList) {
+ quickFunc->setAccess(Node::Protected);
+ }
+ else {
+ if (kernelFunc != 0 && func->numOverloads() == 1 &&
+ (func->parameters().count() == 0 ||
+ func->parameters().last().defaultValue().isEmpty())) {
+ kernelFunc->setAccess(Node::Private);
+ }
+ else {
+ if (func->metaness() == FunctionNode::Plain)
+ quickFunc->setAccess(Node::Protected);
+ }
+ }
+
+ quickFunc->setReturnType(cpp2qs.convertedDataType(qsTre,
+ func->returnType()));
+ if (func->metaness() != FunctionNode::Slot)
+ quickFunc->setMetaness(func->metaness());
+ quickFunc->setVirtualness(FunctionNode::ImpureVirtual);
+ quickFunc->setOverload(func->isOverload());
+
+ QList<Parameter>::ConstIterator q = func->parameters().begin();
+ while (q != func->parameters().end()) {
+ QString dataType = cpp2qs.convertedDataType(qsTre, (*q).leftType(),
+ (*q).rightType());
+ if (dataType.isEmpty()) {
+ dataType = "UNKNOWN";
+ quickFunc->setAccess(Node::Private);
+ }
+ Parameter param(dataType, "", (*q).name(),
+ (*q).defaultValue().isEmpty() ? "" : "undefined");
+ quickFunc->addParameter(param);
+ ++q;
+ }
+
+ if (func->doc().isEmpty()) {
+ if (func->parent() != (InnerNode *) qtClass) {
+ func = qtClass->findFunctionNode(func);
+ if (func != 0)
+ setQtDoc(quickFunc, func->doc());
+ }
+ }
+ else {
+ setQtDoc(quickFunc, func->doc());
+ }
+}
+
+void QsCodeParser::quickifyProperty(ClassNode *quickClass,
+ ClassNode * /* qtClass */,
+ PropertyNode *property)
+{
+ PropertyNode *quickProperty = new PropertyNode(quickClass,
+ property->name());
+ quickProperty->setLocation(property->location());
+ quickProperty->setDataType(cpp2qs.convertedDataType(qsTre,
+ property->dataType()));
+#if 0
+ quickProperty->setGetter(property->getter());
+ quickProperty->setSetter(property->setter());
+ quickProperty->setResetter(property->resetter());
+#endif
+ quickProperty->setStored(property->isStored());
+ quickProperty->setDesignable(property->isDesignable());
+
+ setQtDoc(quickProperty, property->doc());
+}
+
+QString QsCodeParser::quickifiedDoc(const QString& source)
+{
+ QString result;
+ int i = 0;
+
+ while (i < (int) source.length()) {
+ if (leftWordBoundary(source, i)) {
+ if (source[i] == 'Q') {
+ if (source[i + 1] == 'C' && source.mid(i, 8) == "QCString") {
+ i += 2;
+ }
+ else {
+ int end = i + 1;
+ while (isWord(source[end]))
+ ++end;
+ if (!classesWithNoQ.contains(
+ source.mid(i + 1, end - (i + 1))))
+ result += "Q";
+ i++;
+ }
+ }
+ else if (source[i] == 'T' && source.mid(i, 4) == "TRUE" &&
+ rightWordBoundary(source, i + 4)) {
+ result += "\\c{true}";
+ i += 4;
+ }
+ else if (source[i] == 'F' && source.mid(i, 5) == "FALSE" &&
+ rightWordBoundary(source, i + 5)) {
+ result += "\\c{false}";
+ i += 5;
+ }
+ else if (source[i] == 'c' && source.mid(i, 6) == "const ") {
+ i += 6;
+ }
+ else {
+ result += source[i++];
+ }
+ }
+ else if ((source[i] == ':' && source[i + 1] == ':') ||
+ (source[i] == '-' && source[i + 1] == '>')) {
+ result += '.';
+ i += 2;
+ }
+ else if (source[i] == '\\') {
+ // ### make independent of the command name
+ if (source.mid(i, 5) == "\\code") {
+ do {
+ result += source[i++];
+ } while (source[i - 1] != '\n');
+
+ int begin = i;
+ int end = source.indexOf("\\endcode", i);
+ if (end != -1) {
+ QString code = source.mid(begin, end - begin);
+ result += cpp2qs.convertedCode(qsTre, code,
+ classesWithNoQ);
+ i = end;
+ }
+ }
+ else {
+ result += source[i++];
+ }
+ }
+ else {
+ result += source[i++];
+ }
+ }
+
+ QList<QRegExp>::ConstIterator b = replaceBefores.begin();
+ QStringList::ConstIterator a = replaceAfters.begin();
+ while (a != replaceAfters.end()) {
+ result.replace(*b, *a);
+ ++b;
+ ++a;
+ }
+ return result;
+}
+
+void QsCodeParser::setQtDoc(Node *quickNode, const Doc& doc)
+{
+ if (!doc.isEmpty()) {
+ Doc quickDoc(doc.location(), doc.location(),
+ quickifiedDoc(doc.source()),
+ CppCodeParser::topicCommands() +
+ CppCodeParser::otherMetaCommands());
+ quickNode->setDoc(quickDoc, true);
+ }
+}
+
+void QsCodeParser::setQuickDoc(Node *quickNode,
+ const Doc& doc,
+ const QStringList& qtParams,
+ const QStringList& quickParams)
+{
+ QRegExp quickifyCommand("\\\\" + COMMAND_QUICKIFY + "([^\n]*)(?:\n|$)");
+
+ if (quickNode->type() == Node::Function) {
+ FunctionNode *quickFunc = (FunctionNode *) quickNode;
+ quickFunc->setOverload(false);
+ }
+
+ if (doc.metaCommandsUsed().contains(COMMAND_QUICKIFY)) {
+ QString source = doc.source();
+ int pos = source.indexOf(quickifyCommand);
+ if (pos != -1) {
+ QString quickifiedSource = quickNode->doc().source();
+ if (!qtParams.isEmpty() && qtParams != quickParams)
+ renameParameters(quickifiedSource, doc, qtParams,
+ quickParams);
+ applyReplacementList(quickifiedSource, doc);
+
+ do {
+ QString extract = quickifiedSource;
+ QString arg = quickifyCommand.cap(1).simplified();
+ if (!arg.isEmpty()) {
+ if (arg.startsWith("/") && arg.endsWith("/") &&
+ arg.length() > 2) {
+ QString pattern = arg.mid(1, arg.length() - 2);
+ extractRegExp(QRegExp(pattern), extract, doc);
+ }
+ else {
+ extractTarget(arg, extract, doc);
+ }
+ }
+ source.replace(pos, quickifyCommand.matchedLength(), extract);
+ pos += extract.length();
+ } while ((pos = source.indexOf(quickifyCommand, pos)) != -1);
+
+ QRegExp quickcodeRegExp(
+ "\\\\" + COMMAND_QUICKCODE + "(.*)\\\\" +
+ COMMAND_ENDQUICKCODE);
+ quickcodeRegExp.setMinimal(true);
+ source.replace(quickcodeRegExp, "");
+ }
+
+ Doc quickDoc(doc.location(),
+ doc.location(),
+ source,
+ (CppCodeParser::topicCommands() + topicCommands() +
+ CppCodeParser::otherMetaCommands()) << COMMAND_REPLACE);
+ quickNode->setDoc(quickDoc, true);
+ processOtherMetaCommands(quickDoc, quickNode);
+ }
+ else {
+ quickNode->setDoc(doc, true);
+ processOtherMetaCommands(doc, quickNode);
+ }
+}
+
+bool QsCodeParser::makeFunctionNode(const QString& synopsis,
+ QStringList *parentPathPtr,
+ FunctionNode **funcPtr)
+{
+ QRegExp funcRegExp(
+ "\\s*([A-Za-z0-9_]+)\\.([A-Za-z0-9_]+)\\s*\\((" +
+ balancedParens +
+ ")\\)(?:\\s*:\\s*([A-Za-z0-9_]+))?\\s*");
+ QRegExp paramRegExp(
+ "\\s*(\\[)?\\s*(?:([A-Za-z0-9_]+)\\s*:\\s*)?"
+ "([A-Za-z0-9_]+|\\.\\.\\.)\\s*(\\[)?[\\s\\]]*");
+
+ if (!funcRegExp.exactMatch(synopsis))
+ return false;
+
+ ClassNode *classe = (ClassNode*)
+ qsTre->findNode(QStringList(funcRegExp.cap(1)),Node::Class);
+ if (classe == 0)
+ return false;
+
+ FunctionNode *clone = new FunctionNode(0, funcRegExp.cap(2));
+ bool optional = false;
+
+ QString paramStr = funcRegExp.cap(3);
+ QStringList params = paramStr.split(",");
+ QStringList::ConstIterator p = params.begin();
+ while (p != params.end()) {
+ if (paramRegExp.exactMatch(*p)) {
+ if (!paramRegExp.cap(1).isEmpty())
+ optional = true;
+ clone->addParameter(Parameter(paramRegExp.cap(3),
+ "",
+ paramRegExp.cap(2),
+ optional ? "undefined" : ""));
+ if (!paramRegExp.cap(4).isEmpty())
+ optional = true;
+ }
+ else {
+ delete clone;
+ return false;
+ }
+ ++p;
+ }
+ QString returnType = funcRegExp.cap(4);
+ if (!returnType.isEmpty())
+ clone->setReturnType(returnType);
+ if (parentPathPtr != 0)
+ *parentPathPtr = QStringList() << classe->name();
+ if (funcPtr != 0) {
+ *funcPtr = clone;
+ }
+ else {
+ delete clone;
+ }
+ return true;
+}
+
+bool QsCodeParser::isWord(QChar ch)
+{
+ return ch.isLetterOrNumber() || ch == QChar('_');
+}
+
+bool QsCodeParser::leftWordBoundary(const QString& str, int pos)
+{
+ return !isWord(str[pos - 1]) && isWord(str[pos]);
+}
+
+bool QsCodeParser::rightWordBoundary(const QString& str, int pos)
+{
+ return isWord(str[pos - 1]) && !isWord(str[pos]);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/qscodeparser.h b/tools/qdoc3/qscodeparser.h
new file mode 100644
index 0000000000..bd599a81c6
--- /dev/null
+++ b/tools/qdoc3/qscodeparser.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ qscodeparser.h
+*/
+
+#ifndef QSCODEPARSER_H
+#define QSCODEPARSER_H
+
+#include "cppcodeparser.h"
+#include "cpptoqsconverter.h"
+
+QT_BEGIN_NAMESPACE
+
+class QsCodeParser : public CppCodeParser
+{
+ public:
+ QsCodeParser(Tree *cppTree);
+ ~QsCodeParser();
+
+ virtual void initializeParser(const Config& config);
+ virtual void terminateParser();
+ virtual QString language();
+ virtual QString headerFileNameFilter();
+ virtual QString sourceFileNameFilter();
+ virtual void parseHeaderFile(const Location& location,
+ const QString& filePath, Tree *tree);
+ virtual void parseSourceFile(const Location& location,
+ const QString& filePath, Tree *tree);
+ virtual void doneParsingHeaderFiles(Tree *tree);
+ virtual void doneParsingSourceFiles(Tree *tree);
+
+ FunctionNode *findFunctionNode(const QString& synopsis, Tree *tree);
+
+ protected:
+ virtual QSet<QString> topicCommands();
+ virtual Node *processTopicCommand(const Doc& doc, const QString& command,
+ const QString& arg);
+ virtual QSet<QString> otherMetaCommands();
+ virtual void processOtherMetaCommand(const Doc& doc,
+ const QString& command,
+ const QString& arg, Node *node);
+
+ private:
+ ClassNode *tryClass(const QString& className);
+ FunctionNode *findKernelFunction(const QStringList& parentPath,
+ const QString& name);
+ void extractRegExp(const QRegExp& regExp, QString& source,
+ const Doc& doc);
+ void extractTarget(const QString& target, QString& source,
+ const Doc& doc);
+ void renameParameters(QString& source, const Doc& doc,
+ const QStringList& qtNames,
+ const QStringList& quickNames);
+ void applyReplacementList(QString& source, const Doc& doc);
+ void quickifyClass(ClassNode *quickClass);
+ void quickifyEnum(ClassNode *quickClass, EnumNode *enume);
+ void quickifyFunction(ClassNode *quickClass, ClassNode *qtClass,
+ FunctionNode *func, bool onBlackList);
+ void quickifyProperty(ClassNode *quickClass, ClassNode *qtClass,
+ PropertyNode *property);
+ QString quickifiedDoc(const QString& source);
+ void setQtDoc(Node *quickNode, const Doc& doc);
+ void setQuickDoc(Node *quickNode, const Doc& doc,
+ const QStringList& qtParams = QStringList(),
+ const QStringList& quickParams = QStringList());
+ bool makeFunctionNode(const QString& synopsis, QStringList *parentPathPtr,
+ FunctionNode **funcPtr);
+
+ static bool isWord(QChar ch);
+ static bool leftWordBoundary(const QString& str, int pos);
+ static bool rightWordBoundary(const QString& str, int pos);
+
+ QMap<QString,Node::Type> nodeTypeMap;
+ QMap<QString,Node*> classesWithNoQuickDoc;
+ QList<QRegExp> replaceBefores;
+ QStringList replaceAfters;
+ QSet<QString> classesWithNoQ;
+ Tree* cppTre;
+ Tree* qsTre;
+ QRegExp replaceRegExp;
+ CppToQsConverter cpp2qs;
+
+ static int tabSize;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/quoter.cpp b/tools/qdoc3/quoter.cpp
new file mode 100644
index 0000000000..40ca15a7f7
--- /dev/null
+++ b/tools/qdoc3/quoter.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qdebug.h>
+
+#include "quoter.h"
+
+QT_BEGIN_NAMESPACE
+
+static void replaceMultipleNewlines(QString &s)
+{
+ const int n = s.size();
+ bool slurping = false;
+ int j = -1;
+ const QChar newLine = QLatin1Char('\n');
+ QChar *d = s.data();
+ for (int i = 0; i != n; ++i) {
+ const QChar c = d[i];
+ bool hit = (c == newLine);
+ if (slurping && hit)
+ continue;
+ d[++j] = c;
+ slurping = hit;
+ }
+ s.resize(++j);
+}
+
+// This is equivalent to line.split( QRegExp("\n(?!\n|$)") ) but much faster
+static QStringList splitLines(const QString &line)
+{
+ QStringList result;
+ int i = line.size();
+ while (true) {
+ int j = i - 1;
+ while (j >= 0 && line.at(j) == QLatin1Char('\n'))
+ --j;
+ while (j >= 0 && line.at(j) != QLatin1Char('\n'))
+ --j;
+ result.prepend(line.mid(j + 1, i - j - 1));
+ if (j < 0)
+ break;
+ i = j;
+ }
+ return result;
+}
+
+/*
+ Transforms 'int x = 3 + 4' into 'int x=3+4'. A white space is kept
+ between 'int' and 'x' because it is meaningful in C++.
+*/
+static void trimWhiteSpace( QString& str )
+{
+ enum { Normal, MetAlnum, MetSpace } state = Normal;
+ const int n = str.length();
+
+ int j = -1;
+ QChar *d = str.data();
+ for ( int i = 0; i != n; ++i ) {
+ const QChar c = d[i];
+ if ( c.isLetterOrNumber() ) {
+ if ( state == Normal ) {
+ state = MetAlnum;
+ } else {
+ if ( state == MetSpace )
+ str[++j] = c;
+ state = Normal;
+ }
+ str[++j] = c;
+ } else if ( c.isSpace() ) {
+ if ( state == MetAlnum )
+ state = MetSpace;
+ } else {
+ state = Normal;
+ str[++j] = c;
+ }
+ }
+ str.resize(++j);
+}
+
+Quoter::Quoter()
+ : silent( false )
+{
+ /* We're going to hard code these delimiters:
+ * C++, Qt, Qt Script, Java:
+ //! [<id>]
+ * .pro files:
+ #! [<id>]
+ * .xq, .xml, .html files:
+ <!-- [<id>] -->
+ */
+ commentHash["pro"] = "#!";
+ commentHash["py"] = "#!";
+ commentHash["html"] = "<!--";
+ commentHash["qrc"] = "<!--";
+ commentHash["ui"] = "<!--";
+ commentHash["xml"] = "<!--";
+ commentHash["xq"] = "<!--";
+}
+
+void Quoter::reset()
+{
+ silent = false;
+ plainLines.clear();
+ markedLines.clear();
+ codeLocation = Location::null;
+}
+
+void Quoter::quoteFromFile( const QString& userFriendlyFilePath,
+ const QString& plainCode,
+ const QString& markedCode )
+{
+ silent = false;
+
+ /*
+ Split the source code into logical lines. Empty lines are
+ treated specially. Before:
+
+ p->alpha();
+ p->beta();
+
+ p->gamma();
+
+
+ p->delta();
+
+ After:
+
+ p->alpha();
+ p->beta();\n
+ p->gamma();\n\n
+ p->delta();
+
+ Newlines are preserved because they affect codeLocation.
+ */
+ codeLocation = Location( userFriendlyFilePath );
+
+ plainLines = splitLines(plainCode);
+ markedLines = splitLines(markedCode);
+ if (markedLines.count() != plainLines.count()) {
+ codeLocation.warning(tr("Something is wrong with qdoc's handling of marked code"));
+ markedLines = plainLines;
+ }
+
+ /*
+ Squeeze blanks (cat -s).
+ */
+ QStringList::Iterator m = markedLines.begin();
+ while ( m != markedLines.end() ) {
+ replaceMultipleNewlines( *m );
+ ++m;
+ }
+ codeLocation.start();
+}
+
+QString Quoter::quoteLine( const Location& docLocation, const QString& command,
+ const QString& pattern )
+{
+ if ( plainLines.isEmpty() ) {
+ failedAtEnd( docLocation, command );
+ return QString();
+ }
+
+ if ( pattern.isEmpty() ) {
+ docLocation.warning( tr("Missing pattern after '\\%1'").arg(command) );
+ return QString();
+ }
+
+ if ( match(docLocation, pattern, plainLines.first()) )
+ return getLine();
+
+ if ( !silent ) {
+ docLocation.warning( tr("Command '\\%1' failed").arg(command) );
+ codeLocation.warning( tr("Pattern '%1' didn't match here")
+ .arg(pattern) );
+ silent = true;
+ }
+ return QString();
+}
+
+QString Quoter::quoteSnippet(const Location &docLocation, const QString &identifier)
+{
+ QString comment = commentForCode();
+ QString delimiter = comment + QString(" [%1]").arg(identifier);
+ QString t;
+
+ while (!plainLines.isEmpty()) {
+ if (match(docLocation, delimiter, plainLines.first())) {
+ getLine();
+ break;
+ }
+ getLine();
+ }
+ while (!plainLines.isEmpty()) {
+ QString line = plainLines.first();
+ if (match(docLocation, delimiter, line)) {
+ QString lastLine = getLine();
+ int dIndex = lastLine.indexOf(delimiter);
+ if (dIndex > 0) {
+ QString leading = lastLine.left(dIndex);
+ dIndex = leading.indexOf(comment);
+ if (dIndex != -1)
+ leading = leading.left(dIndex);
+ if (!leading.trimmed().isEmpty())
+ t += leading;
+ }
+ return t;
+ }
+ // Remove special macros to support Qt namespacing.
+ if (line.startsWith("QT_BEGIN_NAMESPACE")) {
+ getLine();
+ } else if (line.startsWith("QT_END_NAMESPACE")) {
+ getLine();
+ t += QLatin1Char('\n');
+ } else if (!line.startsWith(comment)) {
+ // Ordinary code
+ t += getLine();
+ } else {
+ // Normal comments
+ if (line.contains(QLatin1Char('\n')))
+ t += QLatin1Char('\n');
+ getLine();
+ }
+ }
+ failedAtEnd(docLocation, QString("snippet (%1)").arg(delimiter));
+ return t;
+}
+
+QString Quoter::quoteTo( const Location& docLocation, const QString& command,
+ const QString& pattern )
+{
+ QString t;
+ QString comment = commentForCode();
+
+ if ( pattern.isEmpty() ) {
+ while ( !plainLines.isEmpty() ) {
+ QString line = plainLines.first();
+ // Remove special macros to support Qt namespacing.
+ if (line.startsWith("QT_BEGIN_NAMESPACE")) {
+ getLine();
+ } else if (line.startsWith("QT_END_NAMESPACE")) {
+ getLine();
+ t += QLatin1Char('\n');
+ } else if (!line.startsWith(comment))
+ // Ordinary code
+ t += getLine();
+ else {
+ // Normal comments
+ if (line.contains(QLatin1Char('\n')))
+ t += QLatin1Char('\n');
+ getLine();
+ }
+ }
+ } else {
+ while ( !plainLines.isEmpty() ) {
+ if ( match(docLocation, pattern, plainLines.first()) ) {
+ return t;
+ }
+ t += getLine();
+ }
+ failedAtEnd( docLocation, command );
+ }
+ return t;
+}
+
+QString Quoter::quoteUntil( const Location& docLocation, const QString& command,
+ const QString& pattern )
+{
+ QString t = quoteTo( docLocation, command, pattern );
+ t += getLine();
+ return t;
+}
+
+QString Quoter::getLine()
+{
+ if ( plainLines.isEmpty() )
+ return QString();
+
+ plainLines.removeFirst();
+
+ QString t = markedLines.takeFirst();
+ t += QLatin1Char('\n');
+ codeLocation.advanceLines( t.count( QLatin1Char('\n') ) );
+ return t;
+}
+
+bool Quoter::match( const Location& docLocation, const QString& pattern0,
+ const QString& line )
+{
+ QString str = line;
+ while ( str.endsWith(QLatin1Char('\n')) )
+ str.truncate( str.length() - 1 );
+
+ QString pattern = pattern0;
+ if ( pattern.startsWith(QLatin1Char('/'))
+ && pattern.endsWith(QLatin1Char('/'))
+ && pattern.length() > 2 ) {
+ QRegExp rx( pattern.mid(1, pattern.length() - 2) );
+ if ( !silent && !rx.isValid() ) {
+ docLocation.warning( tr("Invalid regular expression '%1'")
+ .arg(rx.pattern()) );
+ silent = true;
+ }
+ return str.indexOf( rx ) != -1;
+ }
+ trimWhiteSpace(str);
+ trimWhiteSpace(pattern);
+ return str.indexOf(pattern) != -1;
+}
+
+void Quoter::failedAtEnd( const Location& docLocation, const QString& command )
+{
+ if (!silent && !command.isEmpty()) {
+ if ( codeLocation.filePath().isEmpty() ) {
+ docLocation.warning( tr("Unexpected '\\%1'").arg(command) );
+ } else {
+ docLocation.warning( tr("Command '\\%1' failed at end of file '%2'")
+ .arg(command).arg(codeLocation.filePath()) );
+ }
+ silent = true;
+ }
+}
+
+QString Quoter::commentForCode() const
+{
+ QString suffix = QFileInfo(codeLocation.fileName()).suffix();
+ return commentHash.value(suffix, "//!");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/quoter.h b/tools/qdoc3/quoter.h
new file mode 100644
index 0000000000..7906754474
--- /dev/null
+++ b/tools/qdoc3/quoter.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ quoter.h
+*/
+
+#ifndef QUOTER_H
+#define QUOTER_H
+
+#include <qhash.h>
+#include <qstringlist.h>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class Quoter
+{
+public:
+ Quoter();
+
+ void reset();
+ void quoteFromFile( const QString& userFriendlyFileName,
+ const QString& plainCode, const QString& markedCode );
+ QString quoteLine( const Location& docLocation, const QString& command,
+ const QString& pattern );
+ QString quoteTo( const Location& docLocation, const QString& command,
+ const QString& pattern );
+ QString quoteUntil( const Location& docLocation, const QString& command,
+ const QString& pattern );
+ QString quoteSnippet(const Location &docLocation, const QString &identifier);
+
+private:
+ QString getLine();
+ void failedAtEnd( const Location& docLocation, const QString& command );
+ bool match( const Location& docLocation, const QString& pattern,
+ const QString& line );
+ QString commentForCode() const;
+
+ bool silent;
+ bool validRegExp;
+ QStringList plainLines;
+ QStringList markedLines;
+ Location codeLocation;
+ QHash<QString,QString> commentHash;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/separator.cpp b/tools/qdoc3/separator.cpp
new file mode 100644
index 0000000000..0d730e1e72
--- /dev/null
+++ b/tools/qdoc3/separator.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ separator.cpp
+*/
+
+#include "separator.h"
+#include "tr.h"
+
+QT_BEGIN_NAMESPACE
+
+QString separator( int index, int count )
+{
+ if ( index == count - 1 )
+ return tr( ".", "terminator" );
+
+ if ( count == 2 ) {
+ return tr( " and ", "separator when N = 2" );
+ } else {
+ if ( index == 0 ) {
+ return tr( ", ", "first separator when N > 2" );
+ } else if ( index < count - 2 ) {
+ return tr( ", ", "general separator when N > 2" );
+ } else {
+ return tr( ", and ", "last separator when N > 2" );
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/separator.h b/tools/qdoc3/separator.h
new file mode 100644
index 0000000000..f29868c9ca
--- /dev/null
+++ b/tools/qdoc3/separator.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ separator.h
+*/
+
+#ifndef SEPARATOR_H
+#define SEPARATOR_H
+
+#include <qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+QString separator( int index, int count );
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/sgmlgenerator.cpp b/tools/qdoc3/sgmlgenerator.cpp
new file mode 100644
index 0000000000..575bb53206
--- /dev/null
+++ b/tools/qdoc3/sgmlgenerator.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ sgmlgenerator.cpp
+*/
+
+#include "sgmlgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+SgmlGenerator::SgmlGenerator()
+{
+}
+
+SgmlGenerator::~SgmlGenerator()
+{
+}
+
+QString SgmlGenerator::format()
+{
+ return "SGML";
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/sgmlgenerator.h b/tools/qdoc3/sgmlgenerator.h
new file mode 100644
index 0000000000..e4ffa804a1
--- /dev/null
+++ b/tools/qdoc3/sgmlgenerator.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ sgmlgenerator.h
+*/
+
+#ifndef SGMLGENERATOR_H
+#define SGMLGENERATOR_H
+
+#include "bookgenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+class SgmlGenerator : public BookGenerator
+{
+public:
+ SgmlGenerator();
+ ~SgmlGenerator();
+
+ virtual QString format();
+
+protected:
+ // ###
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/test/arthurtext.qdocconf b/tools/qdoc3/test/arthurtext.qdocconf
new file mode 100644
index 0000000000..473152dec0
--- /dev/null
+++ b/tools/qdoc3/test/arthurtext.qdocconf
@@ -0,0 +1,6 @@
+include(qt.qdocconf)
+headerdirs =
+sourcedirs =
+sources = $QTDIR/doc/src/qt4-arthur.qdoc
+outputdir = $QTDIR/demos/arthur/html
+HTML.{postheader,address} = "" \ No newline at end of file
diff --git a/tools/qdoc3/test/assistant.qdocconf b/tools/qdoc3/test/assistant.qdocconf
new file mode 100644
index 0000000000..7bb6bbfaf4
--- /dev/null
+++ b/tools/qdoc3/test/assistant.qdocconf
@@ -0,0 +1,45 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = Qt Assistant
+description = Qt Assistant Manual
+url = http://doc.trolltech.com/4.5
+
+indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index
+
+qhp.projects = Assistant
+
+qhp.Assistant.file = assistant.qhp
+qhp.Assistant.namespace = com.trolltech.assistant.450
+qhp.Assistant.virtualFolder = qdoc
+qhp.Assistant.indexTitle = Qt Assistant Manual
+qhp.Assistant.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png
+qhp.Assistant.filterAttributes = qt 4.5.0 tools assistant
+qhp.Assistant.customFilters.Assistant.name = Qt Assistant Manual
+qhp.Assistant.customFilters.Assistant.filterAttributes = qt tools assistant
+qhp.Assistant.subprojects = manual examples
+qhp.Assistant.subprojects.manual.title = Manual
+qhp.Assistant.subprojects.manual.indexTitle = Qt Assistant Manual
+qhp.Assistant.subprojects.manual.selectors = fake:page
+qhp.Assistant.subprojects.examples.title = Examples
+qhp.Assistant.subprojects.examples.indexTitle = Qt Examples
+qhp.Assistant.subprojects.examples.selectors = fake:example
+qhp.Assistant.subprojects.examples.sortPages = true
+
+language = Cpp
+
+sources = $QT_SOURCE_TREE/doc/src/assistant-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/simpletextviewer.qdoc
+
+sources.fileextensions = "*.cpp *.qdoc"
+
+exampledirs = $QT_SOURCE_TREE \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src
+
+imagedirs = $QT_SOURCE_TREE/doc/src/images
+outputdir = $QT_BUILD_TREE/doc-build/html-assistant
+base = file:$QT_BUILD_TREE/doc-build/html-assistant
diff --git a/tools/qdoc3/test/carbide-eclipse-integration.qdocconf b/tools/qdoc3/test/carbide-eclipse-integration.qdocconf
new file mode 100644
index 0000000000..683048d98e
--- /dev/null
+++ b/tools/qdoc3/test/carbide-eclipse-integration.qdocconf
@@ -0,0 +1,12 @@
+include(eclipse-integration.qdocconf)
+
+defines += NO_QT_ECLIPSE_INSTALLATION_PAGE
+macro.theEclipseIntegration = Carbide.c++
+macro.TheEclipseIntegration = Carbide.c++
+
+HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
+ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
+ "<td width=\"40%\" align="left">Copyright &copy; 2009 <a href=\"http://doc.trolltech.com/trolltech.html\">Nokia Corporation</a></td>\n" \
+ "<td width=\"30%\" align=\"center\"><a href=\"http://doc.trolltech.com\">Trademarks</a></td>\n" \
+ "<td width=\"40%\" align=\"right\"><div align=\"right\">Carbide.c++</div></td>\n" \
+ "</tr></table></div></address>"
diff --git a/tools/qdoc3/test/classic.css b/tools/qdoc3/test/classic.css
new file mode 100644
index 0000000000..0d0b664d32
--- /dev/null
+++ b/tools/qdoc3/test/classic.css
@@ -0,0 +1,131 @@
+h3.fn,span.fn
+{
+ margin-left: 1cm;
+ text-indent: -1cm;
+}
+
+a:link
+{
+ color: #004faf;
+ text-decoration: none
+}
+
+a:visited
+{
+ color: #672967;
+ text-decoration: none
+}
+
+a.obsolete
+{
+ color: #661100;
+ text-decoration: none
+}
+
+a.compat
+{
+ color: #661100;
+ text-decoration: none
+}
+
+a.obsolete:visited
+{
+ color: #995500;
+ text-decoration: none
+}
+
+a.compat:visited
+{
+ color: #995500;
+ text-decoration: none
+}
+
+td.postheader
+{
+ font-family: sans-serif
+}
+
+tr.address
+{
+ font-family: sans-serif
+}
+
+body
+{
+ background: #ffffff;
+ color: black
+}
+
+table tr.odd {
+ background: #f0f0f0;
+ color: black;
+}
+
+table tr.even {
+ background: #e4e4e4;
+ color: black;
+}
+
+table.annotated th {
+ padding: 3px;
+ text-align: left
+}
+
+table.annotated td {
+ padding: 3px;
+}
+
+table tr pre
+{
+ padding-top: none;
+ padding-bottom: none;
+ padding-left: none;
+ padding-right: none;
+ border: none;
+ background: none
+}
+
+tr.qt-style
+{
+ background: #96E066;
+ color: black
+}
+
+body pre
+{
+ padding: 0.2em;
+ border: #e7e7e7 1px solid;
+ background: #f1f1f1;
+ color: black
+}
+
+span.preprocessor, span.preprocessor a
+{
+ color: darkblue;
+}
+
+span.comment
+{
+ color: darkred;
+ font-style: italic
+}
+
+span.string,span.char
+{
+ color: darkgreen;
+}
+
+.title
+{
+ text-align: center
+}
+
+.subtitle
+{
+ font-size: 0.8em
+}
+
+.small-subtitle
+{
+ font-size: 0.65em
+}
diff --git a/tools/qdoc3/test/compat.qdocconf b/tools/qdoc3/test/compat.qdocconf
new file mode 100644
index 0000000000..5745ed93b0
--- /dev/null
+++ b/tools/qdoc3/test/compat.qdocconf
@@ -0,0 +1,31 @@
+alias.i = e
+alias.include = input
+
+macro.0 = "\\\\0"
+macro.b = "\\\\b"
+macro.n = "\\\\n"
+macro.r = "\\\\r"
+macro.i = "\\o"
+macro.i11 = "\\o{1,1}"
+macro.i12 = "\\o{1,2}"
+macro.i13 = "\\o{1,3}"
+macro.i14 = "\\o{1,4}"
+macro.i15 = "\\o{1,5}"
+macro.i16 = "\\o{1,6}"
+macro.i17 = "\\o{1,7}"
+macro.i18 = "\\o{1,8}"
+macro.i19 = "\\o{1,9}"
+macro.i21 = "\\o{2,1}"
+macro.i31 = "\\o{3,1}"
+macro.i41 = "\\o{4,1}"
+macro.i51 = "\\o{5,1}"
+macro.i61 = "\\o{6,1}"
+macro.i71 = "\\o{7,1}"
+macro.i81 = "\\o{8,1}"
+macro.i91 = "\\o{9,1}"
+macro.img = "\\image"
+macro.endquote = "\\endquotation"
+macro.relatesto = "\\relates"
+
+spurious = "Missing comma in .*" \
+ "Missing pattern .*"
diff --git a/tools/qdoc3/test/designer.qdocconf b/tools/qdoc3/test/designer.qdocconf
new file mode 100644
index 0000000000..26636cd953
--- /dev/null
+++ b/tools/qdoc3/test/designer.qdocconf
@@ -0,0 +1,51 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = Qt Designer
+description = Qt Designer Manual
+url = http://doc.trolltech.com/4.5
+
+indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index
+
+qhp.projects = Designer
+
+qhp.Designer.file = designer.qhp
+qhp.Designer.namespace = com.trolltech.designer.450
+qhp.Designer.virtualFolder = qdoc
+qhp.Designer.indexTitle = Qt Designer Manual
+qhp.Designer.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png
+qhp.Designer.filterAttributes = qt 4.5.0 tools designer
+qhp.Designer.customFilters.Designer.name = Qt Designer Manual
+qhp.Designer.customFilters.Designer.filterAttributes = qt tools designer
+qhp.Designer.subprojects = manual examples
+qhp.Designer.subprojects.manual.title = Manual
+qhp.Designer.subprojects.manual.indexTitle = Qt Designer Manual
+qhp.Designer.subprojects.manual.selectors = fake:page
+qhp.Designer.subprojects.examples.title = Examples
+qhp.Designer.subprojects.examples.indexTitle = Qt Examples
+qhp.Designer.subprojects.examples.selectors = fake:example
+qhp.Designer.subprojects.examples.sortPages = true
+
+language = Cpp
+
+sources = $QT_SOURCE_TREE/doc/src/designer-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/calculatorbuilder.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/calculatorform.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/customwidgetplugin.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/taskmenuextension.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/containerextension.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/worldtimeclockbuilder.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/worldtimeclockplugin.qdoc
+
+sources.fileextensions = "*.cpp *.qdoc"
+
+exampledirs = $QT_SOURCE_TREE \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src
+
+imagedirs = $QT_SOURCE_TREE/doc/src/images
+outputdir = $QT_BUILD_TREE/doc-build/html-designer
+base = file:$QT_BUILD_TREE/doc-build/html-designer
diff --git a/tools/qdoc3/test/eclipse-integration.qdocconf b/tools/qdoc3/test/eclipse-integration.qdocconf
new file mode 100644
index 0000000000..1fdaa1b3c4
--- /dev/null
+++ b/tools/qdoc3/test/eclipse-integration.qdocconf
@@ -0,0 +1,13 @@
+include(qt.qdocconf)
+
+headerdirs =
+sourcedirs =
+sourcedirs = $QTDIR/../qteclipsetools/main/doc
+imagedirs = $QTDIR/../qteclipsetools/main/doc
+outputdir = $QTDIR/../qteclipsetools/main/doc/html
+
+project = Qt Eclipse Integration
+description = "Qt Eclipse Integration"
+url = http://doc.trolltech.com/eclipse-integration-4.4
+
+HTML.{postheader,address} = ""
diff --git a/tools/qdoc3/test/jambi.qdocconf b/tools/qdoc3/test/jambi.qdocconf
new file mode 100644
index 0000000000..3644b69988
--- /dev/null
+++ b/tools/qdoc3/test/jambi.qdocconf
@@ -0,0 +1,47 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+
+project = Qt Jambi
+description = Qt Jambi Reference Documentation
+url = http://doc.trolltech.com/qtjambi
+
+version = 4.4.0_01
+
+language = Java
+
+sources = $JAMBI/doc/japi/qdoc.japi
+outputformats = javadoc HTML
+outputdir = $JAMBI/doc/html/com/trolltech/qt
+
+imagedirs = $QTDIR/doc/src/images \
+ $QTDIR/examples \
+ $JAMBI/doc/src/images \
+ ../doc/src/images
+
+extraimages.javadoc = qt-logo \
+ qt-logo.png
+
+HTML.stylesheets = classic.css
+
+HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \
+ "<tr>\n" \
+ "<td align=\"left\" valign=\"top\" width=\"32\">" \
+ "<img src=\"images/qt-logo.png\" align=\"left\" width=\"32\" height=\"32\" border=\"0\" />" \
+ "</td>\n" \
+ "<td width=\"1\">&nbsp;&nbsp;</td>" \
+ "<td class=\"postheader\" valign=\"center\">" \
+ "<a href=\"qtjambi-index.html\">" \
+ "<font color=\"#004faf\">Home</font></a>&nbsp;&middot;" \
+ " <a href=\"qtjambi-overviews.html\">" \
+ "<font color=\"#004faf\">Overviews</font></a>&nbsp;&middot;" \
+ " <a href=\"qtjambi-examples.html\">" \
+ "<font color=\"#004faf\">Examples</font></a>&nbsp;" \
+ "</td>\n" \
+ "</tr></table>"
+
+HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
+ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
+ "<td width=\"30%\">Copyright &copy; \$THISYEAR\$ <a href=\"trolltech.html\">Trolltech</a></td>\n" \
+ "<td width=\"40%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \
+ "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt Jambi \\version</div></td>\n" \
+ "</tr></table></div></address>"
diff --git a/tools/qdoc3/test/linguist.qdocconf b/tools/qdoc3/test/linguist.qdocconf
new file mode 100644
index 0000000000..5e889a8e32
--- /dev/null
+++ b/tools/qdoc3/test/linguist.qdocconf
@@ -0,0 +1,47 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = Qt Linguist
+description = Qt Linguist Manual
+url = http://doc.trolltech.com/4.5
+
+indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index
+
+qhp.projects = Linguist
+
+qhp.Linguist.file = linguist.qhp
+qhp.Linguist.namespace = com.trolltech.linguist.450
+qhp.Linguist.virtualFolder = qdoc
+qhp.Linguist.indexTitle = Qt Linguist Manual
+qhp.Linguist.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png
+qhp.Linguist.filterAttributes = qt 4.5.0 tools linguist
+qhp.Linguist.customFilters.Linguist.name = Qt Linguist Manual
+qhp.Linguist.customFilters.Linguist.filterAttributes = qt tools linguist
+qhp.Linguist.subprojects = manual examples
+qhp.Linguist.subprojects.manual.title = Manual
+qhp.Linguist.subprojects.manual.indexTitle = Qt Linguist Manual
+qhp.Linguist.subprojects.manual.selectors = fake:page
+qhp.Linguist.subprojects.examples.title = Examples
+qhp.Linguist.subprojects.examples.indexTitle = Qt Examples
+qhp.Linguist.subprojects.examples.selectors = fake:example
+qhp.Linguist.subprojects.examples.sortPages = true
+
+language = Cpp
+
+sources = $QT_SOURCE_TREE/doc/src/linguist-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/hellotr.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/arrowpad.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/trollprint.qdoc
+
+sources.fileextensions = "*.cpp *.qdoc"
+
+exampledirs = $QT_SOURCE_TREE \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src
+
+imagedirs = $QT_SOURCE_TREE/doc/src/images
+outputdir = $QT_BUILD_TREE/doc-build/html-linguist
+base = file:$QT_BUILD_TREE/doc-build/html-linguist
diff --git a/tools/qdoc3/test/macros.qdocconf b/tools/qdoc3/test/macros.qdocconf
new file mode 100644
index 0000000000..d14f80aeae
--- /dev/null
+++ b/tools/qdoc3/test/macros.qdocconf
@@ -0,0 +1,27 @@
+macro.Aring.HTML = "&Aring;"
+macro.aring.HTML = "&aring;"
+macro.Auml.HTML = "&Auml;"
+macro.author = "\\bold{Author:}"
+macro.br.HTML = "<br />"
+macro.BR.HTML = "<br />"
+macro.aacute.HTML = "&aacute;"
+macro.eacute.HTML = "&eacute;"
+macro.iacute.HTML = "&iacute;"
+macro.gui = "\\bold"
+macro.hr.HTML = "<hr />"
+macro.key = "\\bold"
+macro.menu = "\\bold"
+macro.note = "\\bold{Note:}"
+macro.oslash.HTML = "&oslash;"
+macro.ouml.HTML = "&ouml;"
+macro.QA = "\\e{Qt Assistant}"
+macro.QD = "\\e{Qt Designer}"
+macro.QL = "\\e{Qt Linguist}"
+macro.param = "\\e"
+macro.raisedaster.HTML = "<sup>*</sup>"
+macro.rarrow.HTML = "&rarr;"
+macro.reg.HTML = "<sup>&reg;</sup>"
+macro.return = "Returns"
+macro.starslash = "\\c{*/}"
+macro.uuml.HTML = "&uuml;"
+macro.mdash.HTML = "&mdash;"
diff --git a/tools/qdoc3/test/qmake.qdocconf b/tools/qdoc3/test/qmake.qdocconf
new file mode 100644
index 0000000000..c357cfb76c
--- /dev/null
+++ b/tools/qdoc3/test/qmake.qdocconf
@@ -0,0 +1,40 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = QMake
+description = QMake Manual
+url = http://doc.trolltech.com/4.5
+
+indexes = $QT_BUILD_TREE/doc-build/html-qt/qt.index
+
+qhp.projects = qmake
+
+qhp.qmake.file = qmake.qhp
+qhp.qmake.namespace = com.trolltech.qmake.450
+qhp.qmake.virtualFolder = qdoc
+qhp.qmake.indexTitle = QMake Manual
+qhp.qmake.extraFiles = classic.css images/qt-logo.png images/trolltech-logo.png
+qhp.qmake.filterAttributes = qt 4.5.0 tools qmake
+qhp.qmake.customFilters.qmake.name = qmake Manual
+qhp.qmake.customFilters.qmake.filterAttributes = qt tools qmake
+qhp.qmake.subprojects = manual
+qhp.qmake.subprojects.manual.title = Manual
+qhp.qmake.subprojects.manual.indexTitle = qmake Manual
+qhp.qmake.subprojects.manual.selectors = fake:page
+
+language = Cpp
+
+sources = $QT_SOURCE_TREE/doc/src/qmake-manual.qdoc
+
+sources.fileextensions = "*.cpp *.qdoc"
+
+exampledirs = $QT_SOURCE_TREE \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/doc/src
+
+imagedirs = $QT_SOURCE_TREE/doc/src/images
+outputdir = $QT_BUILD_TREE/doc-build/html-qmake
+base = file:$QT_BUILD_TREE/doc-build/html-qmake
diff --git a/tools/qdoc3/test/qt-api-only-with-xcode.qdocconf b/tools/qdoc3/test/qt-api-only-with-xcode.qdocconf
new file mode 100644
index 0000000000..03893865f0
--- /dev/null
+++ b/tools/qdoc3/test/qt-api-only-with-xcode.qdocconf
@@ -0,0 +1,29 @@
+include(qt-build-docs-with-xcode.qdocconf)
+
+# Ensures that the generated index contains a URL that can be used by the
+# tools documentation (assistant.qdocconf, designer.qdocconf, linguist.qdocconf,
+# qmake.qdocconf).
+
+url = ./
+
+# Ensures that the documentation for the tools is not included in the generated
+# .qhp file.
+
+qhp.Qt.excluded = $QT_SOURCE_TREE/doc/src/assistant-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/simpletextviewer.qdoc \
+ $QT_SOURCE_TREE/doc/src/designer-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/calculatorbuilder.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/calculatorform.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/customwidgetplugin.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/taskmenuextension.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/containerextension.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/worldtimeclockbuilder.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/worldtimeclockplugin.qdoc \
+ $QT_SOURCE_TREE/doc/src/linguist-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/hellotr.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/arrowpad.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/trollprint.qdoc \
+ $QT_SOURCE_TREE/doc/src/qmake-manual.qdoc
+
+outputdir = $QT_BUILD_TREE/doc-build/html-qt
+base = file:$QT_BUILD_TREE/doc-build/html-qt
diff --git a/tools/qdoc3/test/qt-api-only.qdocconf b/tools/qdoc3/test/qt-api-only.qdocconf
new file mode 100644
index 0000000000..2e91ba2122
--- /dev/null
+++ b/tools/qdoc3/test/qt-api-only.qdocconf
@@ -0,0 +1,30 @@
+include(qt-build-docs.qdocconf)
+
+# Ensures that the generated index contains a URL that can be used by the
+# tools documentation (assistant.qdocconf, designer.qdocconf, linguist.qdocconf,
+# qmake.qdocconf).
+
+url = ./
+
+# Ensures that the documentation for the tools is not included in the generated
+# .qhp file.
+
+qhp.Qt.excluded = $QT_SOURCE_TREE/doc/src/assistant-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/simpletextviewer.qdoc \
+ $QT_SOURCE_TREE/doc/src/designer-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/calculatorbuilder.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/calculatorform.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/customwidgetplugin.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/taskmenuextension.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/containerextension.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/worldtimeclockbuilder.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/worldtimeclockplugin.qdoc \
+ $QT_SOURCE_TREE/doc/src/linguist-manual.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/hellotr.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/arrowpad.qdoc \
+ $QT_SOURCE_TREE/doc/src/examples/trollprint.qdoc \
+ $QT_SOURCE_TREE/doc/src/qmake-manual.qdoc
+
+outputdir = $QT_BUILD_TREE/doc-build/html-qt
+tagfile = $QT_BUILD_TREE/doc-build/html-qt/qt.tags
+base = file:$QT_BUILD_TREE/doc-build/html-qt
diff --git a/tools/qdoc3/test/qt-build-docs-with-xcode.qdocconf b/tools/qdoc3/test/qt-build-docs-with-xcode.qdocconf
new file mode 100644
index 0000000000..e4be4760e5
--- /dev/null
+++ b/tools/qdoc3/test/qt-build-docs-with-xcode.qdocconf
@@ -0,0 +1,3 @@
+include( qt-build-docs.qdocconf )
+
+HTML.generatemacrefs = "true"
diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf
new file mode 100644
index 0000000000..a08576808d
--- /dev/null
+++ b/tools/qdoc3/test/qt-build-docs.qdocconf
@@ -0,0 +1,109 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = Qt
+description = Qt Reference Documentation
+url = http://doc.trolltech.com/4.5
+
+edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \
+ QtXmlPatterns QtTest
+edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtSql QtSvg \
+ QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \
+ QtDesigner QtAssistant QAxContainer Phonon \
+ QAxServer QtUiTools QtTest QtDBus
+edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest
+edition.DesktopLight.groups = -graphicsview-api
+
+qhp.projects = Qt
+
+qhp.Qt.file = qt.qhp
+qhp.Qt.namespace = com.trolltech.qt.450
+qhp.Qt.virtualFolder = qdoc
+qhp.Qt.indexTitle = Qt Reference Documentation
+qhp.Qt.indexRoot =
+
+# Files not referenced in any qdoc file (last four are needed by qtdemo)
+# See also extraimages.HTML
+qhp.Qt.extraFiles = classic.css \
+ images/qt-logo.png \
+ images/trolltech-logo \
+ images/taskmenuextension-example.png \
+ images/coloreditorfactoryimage.png \
+ images/dynamiclayouts-example.png \
+ images/stylesheet-coffee-plastique.png
+
+qhp.Qt.filterAttributes = qt 4.5.0 qtrefdoc
+qhp.Qt.customFilters.Qt.name = Qt 4.5.0
+qhp.Qt.customFilters.Qt.filterAttributes = qt 4.5.0
+qhp.Qt.subprojects = classes overviews examples
+qhp.Qt.subprojects.classes.title = Classes
+qhp.Qt.subprojects.classes.indexTitle = Qt's Classes
+qhp.Qt.subprojects.classes.selectors = class fake:headerfile
+qhp.Qt.subprojects.classes.sortPages = true
+qhp.Qt.subprojects.overviews.title = Overviews
+qhp.Qt.subprojects.overviews.indexTitle = All Overviews and HOWTOs
+qhp.Qt.subprojects.overviews.selectors = fake:page,group,module
+qhp.Qt.subprojects.examples.title = Tutorials and Examples
+qhp.Qt.subprojects.examples.indexTitle = Qt Examples
+qhp.Qt.subprojects.examples.selectors = fake:example
+
+language = Cpp
+
+headerdirs = $QT_SOURCE_TREE/src \
+ $QT_SOURCE_TREE/extensions/activeqt \
+ $QT_SOURCE_TREE/tools/assistant/lib \
+ $QT_SOURCE_TREE/tools/assistant/compat/lib \
+ $QT_SOURCE_TREE/tools/designer/src/uitools \
+ $QT_SOURCE_TREE/tools/designer/src/lib/extension \
+ $QT_SOURCE_TREE/tools/designer/src/lib/sdk \
+ $QT_SOURCE_TREE/tools/designer/src/lib/uilib \
+ $QT_SOURCE_TREE/tools/qtestlib/src \
+ $QT_SOURCE_TREE/tools/qdbus/src
+sourcedirs = $QT_SOURCE_TREE/src \
+ $QT_SOURCE_TREE/doc/src \
+ $QT_SOURCE_TREE/extensions/activeqt \
+ $QT_SOURCE_TREE/tools/assistant/lib \
+ $QT_SOURCE_TREE/tools/assistant/compat/lib \
+ $QT_SOURCE_TREE/tools/designer/src/uitools \
+ $QT_SOURCE_TREE/tools/designer/src/lib/extension \
+ $QT_SOURCE_TREE/tools/designer/src/lib/sdk \
+ $QT_SOURCE_TREE/tools/designer/src/lib/uilib \
+ $QT_SOURCE_TREE/tools/qtestlib/src \
+ $QT_SOURCE_TREE/tools/qdbus
+
+excludedirs = $QT_SOURCE_TREE/src/3rdparty/clucene \
+ $QT_SOURCE_TREE/src/3rdparty/des \
+ $QT_SOURCE_TREE/src/3rdparty/freetype \
+ $QT_SOURCE_TREE/src/3rdparty/harfbuzz \
+ $QT_SOURCE_TREE/src/3rdparty/kdebase \
+ $QT_SOURCE_TREE/src/3rdparty/libjpeg \
+ $QT_SOURCE_TREE/src/3rdparty/libmng \
+ $QT_SOURCE_TREE/src/3rdparty/libpng \
+ $QT_SOURCE_TREE/src/3rdparty/libtiff \
+ $QT_SOURCE_TREE/src/3rdparty/md4 \
+ $QT_SOURCE_TREE/src/3rdparty/md5 \
+ $QT_SOURCE_TREE/src/3rdparty/patches \
+ $QT_SOURCE_TREE/src/3rdparty/sha1 \
+ $QT_SOURCE_TREE/src/3rdparty/sqlite \
+ $QT_SOURCE_TREE/src/3rdparty/webkit/JavaScriptCore \
+ $QT_SOURCE_TREE/src/3rdparty/webkit/WebCore \
+ $QT_SOURCE_TREE/src/3rdparty/wintab \
+ $QT_SOURCE_TREE/src/3rdparty/zlib \
+ $QT_SOURCE_TREE/doc/src/snippets
+
+sources.fileextensions = "*.cpp *.qdoc *.mm"
+examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp"
+
+exampledirs = $QT_SOURCE_TREE/doc/src \
+ $QT_SOURCE_TREE/examples \
+ $QT_SOURCE_TREE/examples/tutorials \
+ $QT_SOURCE_TREE \
+ $QT_SOURCE_TREE/qmake/examples
+imagedirs = $QT_SOURCE_TREE/doc/src/images \
+ $QT_SOURCE_TREE/examples
+outputdir = $QT_BUILD_TREE/doc/html
+tagfile = $QT_BUILD_TREE/doc/html/qt.tags
+base = file:$QT_BUILD_TREE/doc/html
diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf
new file mode 100644
index 0000000000..107c6926b9
--- /dev/null
+++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf
@@ -0,0 +1,87 @@
+Cpp.ignoretokens = QAXFACTORY_EXPORT \
+ QDESIGNER_COMPONENTS_LIBRARY \
+ QDESIGNER_EXTENSION_LIBRARY \
+ QDESIGNER_SDK_LIBRARY \
+ QDESIGNER_SHARED_LIBRARY \
+ QDESIGNER_UILIB_LIBRARY \
+ QM_EXPORT_CANVAS \
+ QM_EXPORT_DNS \
+ QM_EXPORT_DOM \
+ QM_EXPORT_FTP \
+ QM_EXPORT_HTTP \
+ QM_EXPORT_ICONVIEW \
+ QM_EXPORT_NETWORK \
+ QM_EXPORT_OPENGL \
+ QM_EXPORT_SQL \
+ QM_EXPORT_TABLE \
+ QM_EXPORT_WORKSPACE \
+ QM_EXPORT_XML \
+ QT_ASCII_CAST_WARN \
+ QT_ASCII_CAST_WARN_CONSTRUCTOR \
+ QT_BEGIN_HEADER \
+ QT_DESIGNER_STATIC \
+ QT_END_HEADER \
+ QT_FASTCALL \
+ QT_WIDGET_PLUGIN_EXPORT \
+ Q_COMPAT_EXPORT \
+ Q_CORE_EXPORT \
+ Q_EXPLICIT \
+ Q_EXPORT \
+ Q_EXPORT_CODECS_CN \
+ Q_EXPORT_CODECS_JP \
+ Q_EXPORT_CODECS_KR \
+ Q_EXPORT_PLUGIN \
+ Q_GFX_INLINE \
+ Q_AUTOTEST_EXPORT \
+ Q_GUI_EXPORT \
+ Q_GUI_EXPORT_INLINE \
+ Q_GUI_EXPORT_STYLE_CDE \
+ Q_GUI_EXPORT_STYLE_COMPACT \
+ Q_GUI_EXPORT_STYLE_MAC \
+ Q_GUI_EXPORT_STYLE_MOTIF \
+ Q_GUI_EXPORT_STYLE_MOTIFPLUS \
+ Q_GUI_EXPORT_STYLE_PLATINUM \
+ Q_GUI_EXPORT_STYLE_POCKETPC \
+ Q_GUI_EXPORT_STYLE_SGI \
+ Q_GUI_EXPORT_STYLE_WINDOWS \
+ Q_GUI_EXPORT_STYLE_WINDOWSXP \
+ QHELP_EXPORT \
+ Q_INLINE_TEMPLATE \
+ Q_INTERNAL_WIN_NO_THROW \
+ Q_NETWORK_EXPORT \
+ Q_OPENGL_EXPORT \
+ Q_OUTOFLINE_TEMPLATE \
+ Q_SQL_EXPORT \
+ Q_SVG_EXPORT \
+ Q_SCRIPT_EXPORT \
+ Q_SCRIPTTOOLS_EXPORT \
+ Q_TESTLIB_EXPORT \
+ Q_TYPENAME \
+ Q_XML_EXPORT \
+ Q_XMLSTREAM_EXPORT \
+ Q_XMLPATTERNS_EXPORT \
+ QDBUS_EXPORT \
+ QT_BEGIN_NAMESPACE \
+ QT_BEGIN_INCLUDE_NAMESPACE \
+ QT_END_NAMESPACE \
+ QT_END_INCLUDE_NAMESPACE \
+ PHONON_EXPORT
+Cpp.ignoredirectives = Q_DECLARE_HANDLE \
+ Q_DECLARE_INTERFACE \
+ Q_DECLARE_METATYPE \
+ Q_DECLARE_OPERATORS_FOR_FLAGS \
+ Q_DECLARE_PRIVATE \
+ Q_DECLARE_PUBLIC \
+ Q_DECLARE_SHARED \
+ Q_DECLARE_TR_FUNCTIONS \
+ Q_DECLARE_TYPEINFO \
+ Q_DISABLE_COPY \
+ QT_FORWARD_DECLARE_CLASS \
+ Q_DUMMY_COMPARISON_OPERATOR \
+ Q_ENUMS \
+ Q_FLAGS \
+ Q_INTERFACES \
+ __attribute__ \
+ K_DECLARE_PRIVATE \
+ PHONON_OBJECT \
+ PHONON_HEIR
diff --git a/tools/qdoc3/test/qt-defines.qdocconf b/tools/qdoc3/test/qt-defines.qdocconf
new file mode 100644
index 0000000000..b22727f787
--- /dev/null
+++ b/tools/qdoc3/test/qt-defines.qdocconf
@@ -0,0 +1,26 @@
+defines = Q_QDOC \
+ QT_.*_SUPPORT \
+ QT_.*_LIB \
+ QT_COMPAT \
+ QT_KEYPAD_NAVIGATION \
+ QT3_SUPPORT \
+ Q_WS_.* \
+ Q_OS_.* \
+ Q_BYTE_ORDER \
+ QT_DEPRECATED \
+ Q_NO_USING_KEYWORD \
+ __cplusplus
+
+versionsym = QT_VERSION_STR
+
+codeindent = 1
+
+# Files not referenced in any qdoc file (last four needed by qtdemo)
+# See also qhp.Qt.extraFiles
+extraimages.HTML = qt-logo \
+ trolltech-logo \
+ taskmenuextension-example.png \
+ coloreditorfactoryimage.png \
+ dynamiclayouts-example.png \
+ stylesheet-coffee-plastique.png
+ \ No newline at end of file
diff --git a/tools/qdoc3/test/qt-for-jambi.qdocconf b/tools/qdoc3/test/qt-for-jambi.qdocconf
new file mode 100644
index 0000000000..2285e0ef44
--- /dev/null
+++ b/tools/qdoc3/test/qt-for-jambi.qdocconf
@@ -0,0 +1,12 @@
+include(qt.qdocconf)
+
+# Comment out for full run:
+# sourcedirs = $QTDIR/doc/src $QTDIR/src/corelib/tools
+
+sourcedirs += $JAMBI/doc/src
+exampledirs += $JAMBI/com/trolltech/examples
+
+macro.QJ = "Qt Jambi"
+macro.QC = "Qt/C++"
+
+outputformats =
diff --git a/tools/qdoc3/test/qt-html-templates.qdocconf b/tools/qdoc3/test/qt-html-templates.qdocconf
new file mode 100644
index 0000000000..f09192a592
--- /dev/null
+++ b/tools/qdoc3/test/qt-html-templates.qdocconf
@@ -0,0 +1,32 @@
+HTML.stylesheets = classic.css
+HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \
+ "<tr>\n" \
+ "<td align=\"left\" valign=\"top\" width=\"32\">" \
+ "<a href=\"http://qtsoftware.com/products/qt\"><img src=\"images/qt-logo.png\" align=\"left\" border=\"0\" /></a>" \
+ "</td>\n" \
+ "<td width=\"1\">&nbsp;&nbsp;</td>" \
+ "<td class=\"postheader\" valign=\"center\">" \
+ "<a href=\"index.html\">" \
+ "<font color=\"#004faf\">Home</font></a>&nbsp;&middot;" \
+ " <a href=\"namespaces.html\">" \
+ "<font color=\"#004faf\">All&nbsp;Namespaces</font></a>&nbsp;&middot;" \
+ " <a href=\"classes.html\">" \
+ "<font color=\"#004faf\">All&nbsp;Classes</font></a>&nbsp;&middot;" \
+ " <a href=\"mainclasses.html\">" \
+ "<font color=\"#004faf\">Main&nbsp;Classes</font></a>&nbsp;&middot;" \
+ " <a href=\"groups.html\">" \
+ "<font color=\"#004faf\">Grouped&nbsp;Classes</font></a>&nbsp;&middot;" \
+ " <a href=\"modules.html\">" \
+ "<font color=\"#004faf\">Modules</font></a>&nbsp;&middot;" \
+ " <a href=\"functions.html\">" \
+ "<font color=\"#004faf\">Functions</font></a>" \
+ "</td>\n" \
+ "<td align=\"right\" valign=\"top\" width=\"230\"></td></tr></table>"
+
+HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
+ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
+ "<td width=\"30%\" align=\"left\">Copyright &copy; %THISYEAR% Nokia Corporation " \
+ "and/or its subsidiary(-ies)</td>\n" \
+ "<td width=\"40%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \
+ "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt \\version</div></td>\n" \
+ "</tr></table></div></address>"
diff --git a/tools/qdoc3/test/qt-inc.qdocconf b/tools/qdoc3/test/qt-inc.qdocconf
new file mode 100644
index 0000000000..97893dc064
--- /dev/null
+++ b/tools/qdoc3/test/qt-inc.qdocconf
@@ -0,0 +1,146 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+
+project = Qt
+description = Qt Reference Documentation
+url = http://doc.trolltech.com/4.5
+
+edition.Console = QtCore QtNetwork QtSql QtXml QtScript QtTest
+edition.Desktop = QtCore QtGui QtNetwork QtOpenGL QtSql QtSvg QtXml QtScript \
+ QtDesigner QtAssistant Qt3Support QAxContainer \
+ QAxServer QtUiTools QtTest QtDBus
+edition.DesktopLight = QtCore QtGui Qt3SupportLight QtTest
+
+language = Cpp
+
+norecursion = true
+sources.fileextensions = "*.cpp *.qdoc"
+sourcedirs = $QDOC_CURRENT_DIR
+headerdirs = $QDOC_CURRENT_DIR
+exampledirs = $QTDIR/doc/src \
+ $QTDIR/examples \
+ $QTDIR \
+ $QTDIR/qmake/examples
+imagedirs = $QTDIR/doc/src/images \
+ $QTDIR/examples
+outputdir = $QTDIR/doc/html
+indexdir = $QTDIR/doc/indexes
+indexes = $QDOC_INPUT_INDEXES
+outputindex = $QDOC_OUTPUT_INDEX
+base = file:$QTDIR/doc/html
+versionsym = QT_VERSION_STR
+defines = Q_QDOC \
+ QT_.*_SUPPORT \
+ QT_.*_LIB \
+ QT_COMPAT \
+ QT_KEYPAD_NAVIGATION \
+ QT3_SUPPORT \
+ Q_WS_.* \
+ Q_OS_.* \
+ Q_BYTE_ORDER \
+ __cplusplus
+
+codeindent = 1
+extraimages.HTML = qt-logo \
+ trolltech-logo
+
+Cpp.ignoretokens = QAXFACTORY_EXPORT \
+ QDESIGNER_COMPONENTS_LIBRARY \
+ QDESIGNER_EXTENSION_LIBRARY \
+ QDESIGNER_SDK_LIBRARY \
+ QDESIGNER_SHARED_LIBRARY \
+ QDESIGNER_UILIB_LIBRARY \
+ QM_EXPORT_CANVAS \
+ QM_EXPORT_DNS \
+ QM_EXPORT_DOM \
+ QM_EXPORT_FTP \
+ QM_EXPORT_HTTP \
+ QM_EXPORT_ICONVIEW \
+ QM_EXPORT_NETWORK \
+ QM_EXPORT_OPENGL \
+ QM_EXPORT_SQL \
+ QM_EXPORT_TABLE \
+ QM_EXPORT_WORKSPACE \
+ QM_EXPORT_XML \
+ QT_ASCII_CAST_WARN \
+ QT_BEGIN_HEADER \
+ QT_DESIGNER_STATIC \
+ QT_END_HEADER \
+ QT_WIDGET_PLUGIN_EXPORT \
+ Q_COMPAT_EXPORT \
+ Q_CORE_EXPORT \
+ Q_EXPLICIT \
+ Q_EXPORT \
+ Q_EXPORT_CODECS_CN \
+ Q_EXPORT_CODECS_JP \
+ Q_EXPORT_CODECS_KR \
+ Q_EXPORT_PLUGIN \
+ Q_GFX_INLINE \
+ Q_GUI_EXPORT \
+ Q_GUI_EXPORT_INLINE \
+ Q_GUI_EXPORT_STYLE_CDE \
+ Q_GUI_EXPORT_STYLE_COMPACT \
+ Q_GUI_EXPORT_STYLE_MAC \
+ Q_GUI_EXPORT_STYLE_MOTIF \
+ Q_GUI_EXPORT_STYLE_MOTIFPLUS \
+ Q_GUI_EXPORT_STYLE_PLATINUM \
+ Q_GUI_EXPORT_STYLE_POCKETPC \
+ Q_GUI_EXPORT_STYLE_SGI \
+ Q_GUI_EXPORT_STYLE_WINDOWS \
+ Q_GUI_EXPORT_STYLE_WINDOWSXP \
+ Q_INLINE_TEMPLATE \
+ Q_NETWORK_EXPORT \
+ Q_OPENGL_EXPORT \
+ Q_OUTOFLINE_TEMPLATE \
+ Q_SQL_EXPORT \
+ Q_SVG_EXPORT \
+ Q_SCRIPT_EXPORT \
+ Q_TESTLIB_EXPORT \
+ Q_TYPENAME \
+ Q_XML_EXPORT \
+ QDBUS_EXPORT
+Cpp.ignoredirectives = Q_DECLARE_HANDLE \
+ Q_DECLARE_INTERFACE \
+ Q_DECLARE_METATYPE \
+ Q_DECLARE_OPERATORS_FOR_FLAGS \
+ Q_DECLARE_PRIVATE \
+ Q_DECLARE_PUBLIC \
+ Q_DECLARE_SHARED \
+ Q_DECLARE_TR_FUNCTIONS \
+ Q_DECLARE_TYPEINFO \
+ Q_DISABLE_COPY \
+ Q_DUMMY_COMPARISON_OPERATOR \
+ Q_ENUMS \
+ Q_FLAGS \
+ Q_INTERFACES \
+ __attribute__
+
+HTML.stylesheets = $QTDIR/util/qdoc3/test/classic.css
+HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \
+ "<tr>\n" \
+ "<td align=\"left\" valign=\"top\" width=\"32\">" \
+ "<a href=\"http://qtsoftware.com/products/qt\"><img src=\"images/qt-logo.png\" align=\"left\" width=\"32\" height=\"32\" border=\"0\" /></a>" \
+ "</td>\n" \
+ "<td width=\"1\">&nbsp;&nbsp;</td>" \
+ "<td class=\"postheader\" valign=\"center\">" \
+ "<a href=\"index.html\">" \
+ "<font color=\"#004faf\">Home</font></a>&nbsp;&middot;" \
+ " <a href=\"classes.html\">" \
+ "<font color=\"#004faf\">All&nbsp;Classes</font></a>&nbsp;&middot;" \
+ " <a href=\"mainclasses.html\">" \
+ "<font color=\"#004faf\">Main&nbsp;Classes</font></a>&nbsp;&middot;" \
+ " <a href=\"groups.html\">" \
+ "<font color=\"#004faf\">Grouped&nbsp;Classes</font></a>&nbsp;&middot;" \
+ " <a href=\"modules.html\">" \
+ "<font color=\"#004faf\">Modules</font></a>&nbsp;&middot;" \
+ " <a href=\"functions.html\">" \
+ "<font color=\"#004faf\">Functions</font></a>" \
+ "</td>\n" \
+ "<td align=\"right\" valign=\"top\" width=\"230\"><a href=\"http://qtsoftware.com\"><img src=\"images/trolltech-logo.png\" align=\"right\" width=\"203\" height=\"32\" border=\"0\" /></a></td></tr></table>"
+
+HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
+ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
+ "<td width=\"30%\">Copyright &copy; %THISYEAR% <a href=\"trolltech.html\">Trolltech</a></td>\n" \
+ "<td width=\"40%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \
+ "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt \\version</div></td>\n" \
+ "</tr></table></div></address>"
diff --git a/tools/qdoc3/test/qt-linguist.qdocconf b/tools/qdoc3/test/qt-linguist.qdocconf
new file mode 100644
index 0000000000..7564226292
--- /dev/null
+++ b/tools/qdoc3/test/qt-linguist.qdocconf
@@ -0,0 +1,4 @@
+include(qt.qdocconf)
+
+outputdir = $QTDIR/doc/linguist
+outputformats = Linguist
diff --git a/tools/qdoc3/test/qt-webxml.qdocconf b/tools/qdoc3/test/qt-webxml.qdocconf
new file mode 100644
index 0000000000..3ad0457708
--- /dev/null
+++ b/tools/qdoc3/test/qt-webxml.qdocconf
@@ -0,0 +1,11 @@
+include(qt.qdocconf)
+
+quotinginformation = true
+imagedirs = $QTDIR/doc/src/images \
+ $QTDIR/examples
+
+outputdir = $QTDIR/doc/webxml
+outputformats = WebXML
+
+generateindex = true
+url = .
diff --git a/tools/qdoc3/test/qt-with-extensions.qdocconf b/tools/qdoc3/test/qt-with-extensions.qdocconf
new file mode 100644
index 0000000000..45188c763e
--- /dev/null
+++ b/tools/qdoc3/test/qt-with-extensions.qdocconf
@@ -0,0 +1,8 @@
+include( qt.qdocconf )
+
+project = Qt with Extensions
+headerdirs += $QUICK/src/extensions
+headers += qsa/date.h
+sourcedirs += $QUICK/src/extensions
+spurious = ".*"
+outputformats = ""
diff --git a/tools/qdoc3/test/qt-with-xcode.qdocconf b/tools/qdoc3/test/qt-with-xcode.qdocconf
new file mode 100644
index 0000000000..932f6d9041
--- /dev/null
+++ b/tools/qdoc3/test/qt-with-xcode.qdocconf
@@ -0,0 +1,3 @@
+include( qt.qdocconf )
+
+HTML.generatemacrefs = "true"
diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf
new file mode 100644
index 0000000000..298311e820
--- /dev/null
+++ b/tools/qdoc3/test/qt.qdocconf
@@ -0,0 +1,115 @@
+include(compat.qdocconf)
+include(macros.qdocconf)
+include(qt-cpp-ignore.qdocconf)
+include(qt-html-templates.qdocconf)
+include(qt-defines.qdocconf)
+
+project = Qt
+versionsym =
+version = %VERSION%
+description = Qt Reference Documentation
+url = http://doc.trolltech.com/4.5
+
+edition.Console.modules = QtCore QtDBus QtNetwork QtScript QtSql QtXml \
+ QtXmlPatterns QtTest
+edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtScriptTools QtSql QtSvg \
+ QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \
+ QtDesigner QtAssistant QAxContainer Phonon \
+ QAxServer QtUiTools QtTest QtDBus
+edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest
+edition.DesktopLight.groups = -graphicsview-api
+
+qhp.projects = Qt
+
+qhp.Qt.file = qt.qhp
+qhp.Qt.namespace = com.trolltech.qt.450
+qhp.Qt.virtualFolder = qdoc
+qhp.Qt.indexTitle = Qt Reference Documentation
+qhp.Qt.indexRoot =
+
+# Files not referenced in any qdoc file (last four are needed by qtdemo)
+# See also extraimages.HTML
+qhp.Qt.extraFiles = classic.css \
+ images/qt-logo.png \
+ images/trolltech-logo \
+ images/taskmenuextension-example.png \
+ images/coloreditorfactoryimage.png \
+ images/dynamiclayouts-example.png \
+ images/stylesheet-coffee-plastique.png
+
+qhp.Qt.filterAttributes = qt 4.5.0 qtrefdoc
+qhp.Qt.customFilters.Qt.name = Qt 4.5.0
+qhp.Qt.customFilters.Qt.filterAttributes = qt 4.5.0
+qhp.Qt.subprojects = classes overviews examples
+qhp.Qt.subprojects.classes.title = Classes
+qhp.Qt.subprojects.classes.indexTitle = Qt's Classes
+qhp.Qt.subprojects.classes.selectors = class fake:headerfile
+qhp.Qt.subprojects.classes.sortPages = true
+qhp.Qt.subprojects.overviews.title = Overviews
+qhp.Qt.subprojects.overviews.indexTitle = All Overviews and HOWTOs
+qhp.Qt.subprojects.overviews.selectors = fake:page,group,module
+qhp.Qt.subprojects.examples.title = Tutorials and Examples
+qhp.Qt.subprojects.examples.indexTitle = Qt Examples
+qhp.Qt.subprojects.examples.selectors = fake:example
+
+language = Cpp
+
+headerdirs = $QTDIR/src \
+ $QTDIR/extensions/activeqt \
+ $QTDIR/tools/assistant/lib \
+ $QTDIR/tools/assistant/compat/lib \
+ $QTDIR/tools/designer/src/uitools \
+ $QTDIR/tools/designer/src/lib/extension \
+ $QTDIR/tools/designer/src/lib/sdk \
+ $QTDIR/tools/designer/src/lib/uilib \
+ $QTDIR/tools/qtestlib/src \
+ $QTDIR/tools/qdbus/src
+sourcedirs = $QTDIR/src \
+ $QTDIR/doc/src \
+ $QTDIR/extensions/activeqt \
+ $QTDIR/tools/assistant/lib \
+ $QTDIR/tools/assistant/compat/lib \
+ $QTDIR/tools/designer/src/uitools \
+ $QTDIR/tools/designer/src/lib/extension \
+ $QTDIR/tools/designer/src/lib/sdk \
+ $QTDIR/tools/designer/src/lib/uilib \
+ $QTDIR/tools/qtestlib/src \
+ $QTDIR/tools/qdbus
+
+excludedirs = $QTDIR/src/3rdparty/clucene \
+ $QTDIR/src/3rdparty/des \
+ $QTDIR/src/3rdparty/freetype \
+ $QTDIR/src/3rdparty/harfbuzz \
+ $QTDIR/src/3rdparty/kdebase \
+ $QTDIR/src/3rdparty/libjpeg \
+ $QTDIR/src/3rdparty/libmng \
+ $QTDIR/src/3rdparty/libpng \
+ $QTDIR/src/3rdparty/libtiff \
+ $QTDIR/src/3rdparty/md4 \
+ $QTDIR/src/3rdparty/md5 \
+ $QTDIR/src/3rdparty/patches \
+ $QTDIR/src/3rdparty/sha1 \
+ $QTDIR/src/3rdparty/sqlite \
+ $QTDIR/src/3rdparty/webkit/JavaScriptCore \
+ $QTDIR/src/3rdparty/webkit/WebCore \
+ $QTDIR/src/3rdparty/wintab \
+ $QTDIR/src/3rdparty/zlib \
+ $QTDIR/doc/src/snippets \
+ $QTDIR/src/3rdparty/phonon/gstreamer \
+ $QTDIR/src/3rdparty/phonon/ds9 \
+ $QTDIR/src/3rdparty/phonon/qt7 \
+ $QTDIR/src/3rdparty/phonon/waveout
+
+sources.fileextensions = "*.cpp *.qdoc *.mm"
+examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp"
+
+exampledirs = $QTDIR/doc/src \
+ $QTDIR/examples \
+ $QTDIR/examples/tutorials \
+ $QTDIR \
+ $QTDIR/qmake/examples
+imagedirs = $QTDIR/doc/src/images \
+ $QTDIR/examples
+outputdir = $QTDIR/doc/html
+tagfile = $QTDIR/doc/html/qt.tags
+base = file:$QTDIR/doc/html
diff --git a/tools/qdoc3/test/standalone-eclipse-integration.qdocconf b/tools/qdoc3/test/standalone-eclipse-integration.qdocconf
new file mode 100644
index 0000000000..c3c429188a
--- /dev/null
+++ b/tools/qdoc3/test/standalone-eclipse-integration.qdocconf
@@ -0,0 +1,11 @@
+include(eclipse-integration.qdocconf)
+
+macro.theEclipseIntegration = the Qt Eclipse Integration
+macro.TheEclipseIntegration = The Qt Eclipse Integration
+
+HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \
+ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \
+ "<td width=\"40%\" align="left">Copyright &copy; 2009 <a href=\"http://doc.trolltech.com\">Nokia Corporation</a></td>\n" \
+ "<td width=\"30%\" align=\"center\"><a href=\"http://doc.trolltech.com/trademarks.html\">Trademarks</a></td>\n" \
+ "<td width=\"40%\" align=\"right\"><div align=\"right\">Qt Eclipse Integration 1.4.3</div></td>\n" \
+ "</tr></table></div></address>"
diff --git a/tools/qdoc3/text.cpp b/tools/qdoc3/text.cpp
new file mode 100644
index 0000000000..0b0a8d7a4c
--- /dev/null
+++ b/tools/qdoc3/text.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ text.cpp
+*/
+
+#include <qregexp.h>
+#include "text.h"
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+Text::Text()
+ : first(0), last(0)
+{
+}
+
+Text::Text(const QString &str)
+ : first(0), last(0)
+{
+ operator<<(str);
+}
+
+Text::Text( const Text& text )
+ : first(0), last(0)
+{
+ operator=( text );
+}
+
+Text::~Text()
+{
+ clear();
+}
+
+Text& Text::operator=( const Text& text )
+{
+ if ( this != &text ) {
+ clear();
+ operator<<( text );
+ }
+ return *this;
+}
+
+Text& Text::operator<<( Atom::Type atomType )
+{
+ return operator<<( Atom(atomType) );
+}
+
+Text& Text::operator<<( const QString& string )
+{
+ return operator<<( Atom(Atom::String, string) );
+}
+
+Text& Text::operator<<( const Atom& atom )
+{
+ if ( first == 0 ) {
+ first = new Atom( atom.type(), atom.string() );
+ last = first;
+ } else {
+ last = new Atom( last, atom.type(), atom.string() );
+ }
+ return *this;
+}
+
+Text& Text::operator<<( const Text& text )
+{
+ const Atom *atom = text.firstAtom();
+ while ( atom != 0 ) {
+ operator<<( *atom );
+ atom = atom->next();
+ }
+ return *this;
+}
+
+void Text::stripFirstAtom()
+{
+ if ( first != 0 ) {
+ if ( first == last )
+ last = 0;
+ Atom *oldFirst = first;
+ first = first->next();
+ delete oldFirst;
+ }
+}
+
+void Text::stripLastAtom()
+{
+ if ( last != 0 ) {
+ Atom *oldLast = last;
+ if ( first == last ) {
+ first = 0;
+ last = 0;
+ } else {
+ last = first;
+ while ( last->next() != oldLast )
+ last = last->next();
+ last->setNext( 0 );
+ }
+ delete oldLast;
+ }
+}
+
+QString Text::toString() const
+{
+ QString str;
+ const Atom *atom = firstAtom();
+ while ( atom != 0 ) {
+ if ( atom->type() == Atom::String || atom->type() == Atom::AutoLink )
+ str += atom->string();
+ atom = atom->next();
+ }
+ return str;
+}
+
+Text Text::subText( Atom::Type left, Atom::Type right, const Atom *from ) const
+{
+ const Atom *begin = from ? from : firstAtom();
+ const Atom *end;
+
+ while ( begin != 0 && begin->type() != left )
+ begin = begin->next();
+ if ( begin != 0 )
+ begin = begin->next();
+
+ end = begin;
+ while ( end != 0 && end->type() != right )
+ end = end->next();
+ if ( end == 0 )
+ begin = 0;
+ return subText( begin, end );
+}
+
+Text Text::sectionHeading(const Atom *sectionLeft)
+{
+ if ( sectionLeft != 0 ) {
+ const Atom *begin = sectionLeft;
+ while ( begin != 0 && begin->type() != Atom::SectionHeadingLeft )
+ begin = begin->next();
+ if ( begin != 0 )
+ begin = begin->next();
+
+ const Atom *end = begin;
+ while ( end != 0 && end->type() != Atom::SectionHeadingRight )
+ end = end->next();
+
+ if ( end != 0 )
+ return subText( begin, end );
+ }
+ return Text();
+}
+
+const Atom *Text::sectionHeadingAtom(const Atom *sectionLeft)
+{
+ if ( sectionLeft != 0 ) {
+ const Atom *begin = sectionLeft;
+ while ( begin != 0 && begin->type() != Atom::SectionHeadingLeft )
+ begin = begin->next();
+ if ( begin != 0 )
+ begin = begin->next();
+
+ return begin;
+ }
+ return 0;
+}
+
+void Text::dump() const
+{
+ const Atom *atom = firstAtom();
+ while ( atom != 0 ) {
+ QString str = atom->string();
+ str.replace( "\\", "\\\\" );
+ str.replace( "\"", "\\\"" );
+ str.replace( "\n", "\\n" );
+ str.replace( QRegExp("[^\x20-\x7e]"), "?" );
+ if ( !str.isEmpty() )
+ str = " \"" + str + "\"";
+ fprintf(stderr, " %-15s%s\n", atom->typeString().toLatin1().data(), str.toLatin1().data() );
+ atom = atom->next();
+ }
+}
+
+Text Text::subText( const Atom *begin, const Atom *end )
+{
+ Text text;
+ if ( begin != 0 ) {
+ while ( begin != end ) {
+ text << *begin;
+ begin = begin->next();
+ }
+ }
+ return text;
+}
+
+void Text::clear()
+{
+ while ( first != 0 ) {
+ Atom *atom = first;
+ first = first->next();
+ delete atom;
+ }
+ first = 0;
+ last = 0;
+}
+
+int Text::compare(const Text &text1, const Text &text2)
+{
+ if (text1.isEmpty())
+ return text2.isEmpty() ? 0 : -1;
+ if (text2.isEmpty())
+ return 1;
+
+ const Atom *atom1 = text1.firstAtom();
+ const Atom *atom2 = text2.firstAtom();
+
+ for (;;) {
+ if (atom1->type() != atom2->type())
+ return (int)atom1->type() - (int)atom2->type();
+ int cmp = QString::compare(atom1->string(), atom2->string());
+ if (cmp != 0)
+ return cmp;
+
+ if (atom1 == text1.lastAtom())
+ return atom2 == text2.lastAtom() ? 0 : -1;
+ if (atom2 == text2.lastAtom())
+ return 1;
+ atom1 = atom1->next();
+ atom2 = atom2->next();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/text.h b/tools/qdoc3/text.h
new file mode 100644
index 0000000000..82506dfa07
--- /dev/null
+++ b/tools/qdoc3/text.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ text.h
+*/
+
+#ifndef TEXT_H
+#define TEXT_H
+
+#include "atom.h"
+
+QT_BEGIN_NAMESPACE
+
+class Text
+{
+ public:
+ Text();
+ explicit Text(const QString &str);
+ Text(const Text& text);
+ ~Text();
+
+ Text& operator=(const Text& text);
+
+ Atom *firstAtom() { return first; }
+ Atom *lastAtom() { return last; }
+ Text& operator<<(Atom::Type atomType);
+ Text& operator<<(const QString& string);
+ Text& operator<<(const Atom& atom);
+ Text& operator<<(const Text& text);
+ void stripFirstAtom();
+ void stripLastAtom();
+
+ bool isEmpty() const { return first == 0; }
+ QString toString() const;
+ const Atom *firstAtom() const { return first; }
+ const Atom *lastAtom() const { return last; }
+ Text subText(Atom::Type left, Atom::Type right, const Atom *from = 0) const;
+ void dump() const;
+
+ static Text subText(const Atom *begin, const Atom *end = 0);
+ static Text sectionHeading(const Atom *sectionBegin);
+ static const Atom *sectionHeadingAtom(const Atom *sectionLeft);
+ static int compare(const Text &text1, const Text &text2);
+
+ private:
+ void clear();
+
+ Atom *first;
+ Atom *last;
+};
+
+inline bool operator==(const Text &text1, const Text &text2)
+{ return Text::compare(text1, text2) == 0; }
+inline bool operator!=(const Text &text1, const Text &text2)
+{ return Text::compare(text1, text2) != 0; }
+inline bool operator<(const Text &text1, const Text &text2)
+{ return Text::compare(text1, text2) < 0; }
+inline bool operator<=(const Text &text1, const Text &text2)
+{ return Text::compare(text1, text2) <= 0; }
+inline bool operator>(const Text &text1, const Text &text2)
+{ return Text::compare(text1, text2) > 0; }
+inline bool operator>=(const Text &text1, const Text &text2)
+{ return Text::compare(text1, text2) >= 0; }
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/tokenizer.cpp b/tools/qdoc3/tokenizer.cpp
new file mode 100644
index 0000000000..24b1b5aa3a
--- /dev/null
+++ b/tools/qdoc3/tokenizer.cpp
@@ -0,0 +1,753 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "tokenizer.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qhash.h>
+#include <qregexp.h>
+#include <qstring.h>
+
+#include <ctype.h>
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+#define LANGUAGE_CPP "Cpp"
+
+/* qmake ignore Q_OBJECT */
+
+/*
+ Keep in sync with tokenizer.h.
+*/
+static const char *kwords[] = {
+ "char", "class", "const", "double", "enum", "explicit",
+ "friend", "inline", "int", "long", "namespace", "operator",
+ "private", "protected", "public", "short", "signals", "signed",
+ "slots", "static", "struct", "template", "typedef", "typename",
+ "union", "unsigned", "using", "virtual", "void", "volatile",
+ "__int64", "Q_OBJECT", "Q_OVERRIDE", "Q_PROPERTY",
+ "Q_DECLARE_SEQUENTIAL_ITERATOR",
+ "Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR",
+ "Q_DECLARE_ASSOCIATIVE_ITERATOR",
+ "Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR",
+ "Q_DECLARE_FLAGS",
+ "Q_SIGNALS",
+ "Q_SLOTS",
+ "QT_COMPAT",
+ "QT_COMPAT_CONSTRUCTOR",
+ "QT_DEPRECATED",
+ "QT_MOC_COMPAT",
+ "QT_MODULE",
+ "QT3_SUPPORT",
+ "QT3_SUPPORT_CONSTRUCTOR",
+ "QT3_MOC_SUPPORT",
+ "QDOC_PROPERTY"
+};
+
+static const int KwordHashTableSize = 4096;
+static int kwordHashTable[KwordHashTableSize];
+
+static QHash<QByteArray, bool> *ignoredTokensAndDirectives = 0;
+
+static QRegExp *comment = 0;
+static QRegExp *versionX = 0;
+static QRegExp *definedX = 0;
+
+static QRegExp *defines = 0;
+static QRegExp *falsehoods = 0;
+
+/*
+ This function is a perfect hash function for the 37 keywords of C99
+ (with a hash table size of 512). It should perform well on our
+ Qt-enhanced C++ subset.
+*/
+static int hashKword(const char *s, int len)
+{
+ return (((uchar) s[0]) + (((uchar) s[2]) << 5) +
+ (((uchar) s[len - 1]) << 3)) % KwordHashTableSize;
+}
+
+static void insertKwordIntoHash(const char *s, int number)
+{
+ int k = hashKword(s, strlen(s));
+ while (kwordHashTable[k]) {
+ if (++k == KwordHashTableSize)
+ k = 0;
+ }
+ kwordHashTable[k] = number;
+}
+
+Tokenizer::Tokenizer(const Location& loc, FILE *in)
+{
+ init();
+ QFile file;
+ file.open(in, QIODevice::ReadOnly);
+ yyIn = file.readAll();
+ file.close();
+ yyPos = 0;
+ start(loc);
+}
+
+Tokenizer::Tokenizer(const Location& loc, const QByteArray &in)
+ : yyIn(in)
+{
+ init();
+ yyPos = 0;
+ start(loc);
+}
+
+Tokenizer::~Tokenizer()
+{
+ delete[] yyLexBuf1;
+ delete[] yyLexBuf2;
+}
+
+int Tokenizer::getToken()
+{
+ char *t = yyPrevLex;
+ yyPrevLex = yyLex;
+ yyLex = t;
+
+ while (yyCh != EOF) {
+ yyTokLoc = yyCurLoc;
+ yyLexLen = 0;
+
+ if (isspace(yyCh)) {
+ do {
+ yyCh = getChar();
+ } while (isspace(yyCh));
+ }
+ else if (isalpha(yyCh) || yyCh == '_') {
+ do {
+ yyCh = getChar();
+ } while (isalnum(yyCh) || yyCh == '_');
+
+ int k = hashKword(yyLex, yyLexLen);
+ for (;;) {
+ int i = kwordHashTable[k];
+ if (i == 0) {
+ return Tok_Ident;
+ }
+ else if (i == -1) {
+ if (!parsingMacro && ignoredTokensAndDirectives->contains(yyLex)) {
+ if (ignoredTokensAndDirectives->value(yyLex)) { // it's a directive
+ int parenDepth = 0;
+ while (yyCh != EOF && (yyCh != ')' || parenDepth > 1)) {
+ if (yyCh == '(')
+ ++parenDepth;
+ else if (yyCh == ')')
+ --parenDepth;
+ yyCh = getChar();
+ }
+ if (yyCh == ')')
+ yyCh = getChar();
+ }
+ break;
+ }
+ }
+ else if (strcmp(yyLex, kwords[i - 1]) == 0) {
+ int ret = (int) Tok_FirstKeyword + i - 1;
+ if (ret != Tok_explicit && ret != Tok_inline && ret != Tok_typename)
+ return ret;
+ break;
+ }
+
+ if (++k == KwordHashTableSize)
+ k = 0;
+ }
+ }
+ else if (isdigit(yyCh)) {
+ do {
+ yyCh = getChar();
+ } while (isalnum(yyCh) || yyCh == '.' || yyCh == '+' ||
+ yyCh == '-');
+ return Tok_Number;
+ }
+ else {
+ switch (yyCh) {
+ case '!':
+ case '%':
+ yyCh = getChar();
+ if (yyCh == '=')
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ case '"':
+ yyCh = getChar();
+
+ while (yyCh != EOF && yyCh != '"') {
+ if (yyCh == '\\')
+ yyCh = getChar();
+ yyCh = getChar();
+ }
+ yyCh = getChar();
+
+ if (yyCh == EOF)
+ yyTokLoc.warning(tr("Unterminated C++ string literal"),
+ tr("Maybe you forgot '/*!' at the beginning of the file?"));
+ else
+ return Tok_String;
+ break;
+ case '#':
+ return getTokenAfterPreprocessor();
+ case '&':
+ yyCh = getChar();
+ if (yyCh == '&' || yyCh == '=') {
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ }
+ else {
+ return Tok_Ampersand;
+ }
+ case '\'':
+ yyCh = getChar();
+ if (yyCh == '\\')
+ yyCh = getChar();
+ do {
+ yyCh = getChar();
+ } while (yyCh != EOF && yyCh != '\'');
+
+ if (yyCh == EOF) {
+ yyTokLoc.warning(tr("Unterminated C++ character"
+ " literal"));
+ }
+ else {
+ yyCh = getChar();
+ return Tok_Number;
+ }
+ break;
+ case '(':
+ yyCh = getChar();
+ if (yyNumPreprocessorSkipping == 0)
+ yyParenDepth++;
+ if (isspace(yyCh)) {
+ do {
+ yyCh = getChar();
+ } while (isspace(yyCh));
+ yyLexLen = 1;
+ yyLex[1] = '\0';
+ }
+ if (yyCh == '*') {
+ yyCh = getChar();
+ return Tok_LeftParenAster;
+ }
+ return Tok_LeftParen;
+ case ')':
+ yyCh = getChar();
+ if (yyNumPreprocessorSkipping == 0)
+ yyParenDepth--;
+ return Tok_RightParen;
+ case '*':
+ yyCh = getChar();
+ if (yyCh == '=') {
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ } else {
+ return Tok_Aster;
+ }
+ case '^':
+ yyCh = getChar();
+ if (yyCh == '=') {
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ } else {
+ return Tok_Caret;
+ }
+ case '+':
+ yyCh = getChar();
+ if (yyCh == '+' || yyCh == '=')
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ case ',':
+ yyCh = getChar();
+ return Tok_Comma;
+ case '-':
+ yyCh = getChar();
+ if (yyCh == '-' || yyCh == '=') {
+ yyCh = getChar();
+ } else if (yyCh == '>') {
+ yyCh = getChar();
+ if (yyCh == '*')
+ yyCh = getChar();
+ }
+ return Tok_SomeOperator;
+ case '.':
+ yyCh = getChar();
+ if (yyCh == '*') {
+ yyCh = getChar();
+ } else if (yyCh == '.') {
+ do {
+ yyCh = getChar();
+ } while (yyCh == '.');
+ return Tok_Ellipsis;
+ } else if (isdigit(yyCh)) {
+ do {
+ yyCh = getChar();
+ } while (isalnum(yyCh) || yyCh == '.' || yyCh == '+' ||
+ yyCh == '-');
+ return Tok_Number;
+ }
+ return Tok_SomeOperator;
+ case '/':
+ yyCh = getChar();
+ if (yyCh == '/') {
+ do {
+ yyCh = getChar();
+ } while (yyCh != EOF && yyCh != '\n');
+ } else if (yyCh == '*') {
+ bool metDoc = false; // empty doc is no doc
+ bool metSlashAsterBang = false;
+ bool metAster = false;
+ bool metAsterSlash = false;
+
+ yyCh = getChar();
+ if (yyCh == '!')
+ metSlashAsterBang = true;
+
+ while (!metAsterSlash) {
+ if (yyCh == EOF) {
+ yyTokLoc.warning(tr("Unterminated C++ comment"));
+ break;
+ } else {
+ if (yyCh == '*') {
+ metAster = true;
+ } else if (metAster && yyCh == '/') {
+ metAsterSlash = true;
+ } else {
+ metAster = false;
+ if (isgraph(yyCh))
+ metDoc = true;
+ }
+ }
+ yyCh = getChar();
+ }
+ if (metSlashAsterBang && metDoc)
+ return Tok_Doc;
+ else if (yyParenDepth > 0)
+ return Tok_Comment;
+ } else {
+ if (yyCh == '=')
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ }
+ break;
+ case ':':
+ yyCh = getChar();
+ if (yyCh == ':') {
+ yyCh = getChar();
+ return Tok_Gulbrandsen;
+ } else {
+ return Tok_Colon;
+ }
+ case ';':
+ yyCh = getChar();
+ return Tok_Semicolon;
+ case '<':
+ yyCh = getChar();
+ if (yyCh == '<') {
+ yyCh = getChar();
+ if (yyCh == '=')
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ } else if (yyCh == '=') {
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ } else {
+ return Tok_LeftAngle;
+ }
+ case '=':
+ yyCh = getChar();
+ if (yyCh == '=') {
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ } else {
+ return Tok_Equal;
+ }
+ case '>':
+ yyCh = getChar();
+ if (yyCh == '>') {
+ yyCh = getChar();
+ if (yyCh == '=')
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ } else if (yyCh == '=') {
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ } else {
+ return Tok_RightAngle;
+ }
+ case '?':
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ case '[':
+ yyCh = getChar();
+ if (yyNumPreprocessorSkipping == 0)
+ yyBracketDepth++;
+ return Tok_LeftBracket;
+ case '\\':
+ yyCh = getChar();
+ yyCh = getChar(); // skip one character
+ break;
+ case ']':
+ yyCh = getChar();
+ if (yyNumPreprocessorSkipping == 0)
+ yyBracketDepth--;
+ return Tok_RightBracket;
+ case '{':
+ yyCh = getChar();
+ if (yyNumPreprocessorSkipping == 0)
+ yyBraceDepth++;
+ return Tok_LeftBrace;
+ case '}':
+ yyCh = getChar();
+ if (yyNumPreprocessorSkipping == 0)
+ yyBraceDepth--;
+ return Tok_RightBrace;
+ case '|':
+ yyCh = getChar();
+ if (yyCh == '|' || yyCh == '=')
+ yyCh = getChar();
+ return Tok_SomeOperator;
+ case '~':
+ yyCh = getChar();
+ return Tok_Tilde;
+ case '@':
+ yyCh = getChar();
+ return Tok_At;
+ default:
+ // ### We should really prevent qdoc from looking at snippet files rather than
+ // ### suppress warnings when reading them.
+ if (yyNumPreprocessorSkipping == 0 && !yyTokLoc.fileName().endsWith(".qdoc")) {
+ yyTokLoc.warning(tr("Hostile character 0x%1 in C++ source")
+ .arg((uchar)yyCh, 1, 16));
+ }
+ yyCh = getChar();
+ }
+ }
+ }
+
+ if (yyPreprocessorSkipping.count() > 1) {
+ yyTokLoc.warning(tr("Expected #endif before end of file"));
+ // clear it out or we get an infinite loop!
+ while (!yyPreprocessorSkipping.isEmpty()) {
+ popSkipping();
+ }
+ }
+
+ strcpy(yyLex, "end-of-input");
+ yyLexLen = strlen(yyLex);
+ return Tok_Eoi;
+}
+
+void Tokenizer::initialize(const Config &config)
+{
+ QString versionSym = config.getString(CONFIG_VERSIONSYM);
+
+ comment = new QRegExp("/(?:\\*.*\\*/|/.*\n|/[^\n]*$)");
+ comment->setMinimal(true);
+ versionX = new QRegExp("$cannot possibly match^");
+ if (!versionSym.isEmpty())
+ versionX->setPattern("[ \t]*(?:" + QRegExp::escape(versionSym)
+ + ")[ \t]+\"([^\"]*)\"[ \t]*");
+ definedX = new QRegExp("defined ?\\(?([A-Z_0-9a-z]+) ?\\)");
+
+ QStringList d = config.getStringList(CONFIG_DEFINES);
+ d += "qdoc";
+ defines = new QRegExp(d.join("|"));
+ falsehoods = new QRegExp(config.getStringList(CONFIG_FALSEHOODS).join("|"));
+
+ memset(kwordHashTable, 0, sizeof(kwordHashTable));
+ for (int i = 0; i < Tok_LastKeyword - Tok_FirstKeyword + 1; i++)
+ insertKwordIntoHash(kwords[i], i + 1);
+
+ ignoredTokensAndDirectives = new QHash<QByteArray, bool>;
+
+ QStringList tokens = config.getStringList(LANGUAGE_CPP + Config::dot + CONFIG_IGNORETOKENS);
+ foreach (const QString &t, tokens) {
+ const QByteArray tb = t.toAscii();
+ ignoredTokensAndDirectives->insert(tb, false);
+ insertKwordIntoHash(tb.data(), -1);
+ }
+
+ QStringList directives = config.getStringList(LANGUAGE_CPP + Config::dot
+ + CONFIG_IGNOREDIRECTIVES);
+ foreach (const QString &d, directives) {
+ const QByteArray db = d.toAscii();
+ ignoredTokensAndDirectives->insert(db, true);
+ insertKwordIntoHash(db.data(), -1);
+ }
+}
+
+void Tokenizer::terminate()
+{
+ delete comment;
+ comment = 0;
+ delete versionX;
+ versionX = 0;
+ delete definedX;
+ definedX = 0;
+ delete defines;
+ defines = 0;
+ delete falsehoods;
+ falsehoods = 0;
+ delete ignoredTokensAndDirectives;
+ ignoredTokensAndDirectives = 0;
+}
+
+void Tokenizer::init()
+{
+ yyLexBuf1 = new char[(int) yyLexBufSize];
+ yyLexBuf2 = new char[(int) yyLexBufSize];
+ yyPrevLex = yyLexBuf1;
+ yyPrevLex[0] = '\0';
+ yyLex = yyLexBuf2;
+ yyLex[0] = '\0';
+ yyLexLen = 0;
+ yyPreprocessorSkipping.push(false);
+ yyNumPreprocessorSkipping = 0;
+ yyBraceDepth = 0;
+ yyParenDepth = 0;
+ yyBracketDepth = 0;
+ yyCh = '\0';
+ parsingMacro = false;
+}
+
+void Tokenizer::start(const Location& loc)
+{
+ yyTokLoc = loc;
+ yyCurLoc = loc;
+ yyCurLoc.start();
+ strcpy(yyPrevLex, "beginning-of-input");
+ strcpy(yyLex, "beginning-of-input");
+ yyLexLen = strlen(yyLex);
+ yyBraceDepth = 0;
+ yyParenDepth = 0;
+ yyBracketDepth = 0;
+ yyCh = '\0';
+ yyCh = getChar();
+}
+
+/*
+ Returns the next token, if # was met. This function interprets the
+ preprocessor directive, skips over any #ifdef'd out tokens, and returns the
+ token after all of that.
+*/
+int Tokenizer::getTokenAfterPreprocessor()
+{
+ yyCh = getChar();
+ while (isspace(yyCh) && yyCh != '\n')
+ yyCh = getChar();
+
+ /*
+ #directive condition
+ */
+ QString directive;
+ QString condition;
+
+ while (isalpha(yyCh)) {
+ directive += QChar(yyCh);
+ yyCh = getChar();
+ }
+ if (!directive.isEmpty()) {
+ while (yyCh != EOF && yyCh != '\n') {
+ if (yyCh == '\\')
+ yyCh = getChar();
+ condition += yyCh;
+ yyCh = getChar();
+ }
+ condition.replace(*comment, "");
+ condition = condition.simplified();
+
+ /*
+ The #if, #ifdef, #ifndef, #elif, #else, and #endif
+ directives have an effect on the skipping stack. For
+ instance, if the code processed so far is
+
+ #if 1
+ #if 0
+ #if 1
+ // ...
+ #else
+
+ the skipping stack contains, from bottom to top, false true
+ true (assuming 0 is false and 1 is true). If at least one
+ entry of the stack is true, the tokens are skipped.
+
+ This mechanism is simple yet hard to understand.
+ */
+ if (directive[0] == QChar('i')) {
+ if (directive == QString("if"))
+ pushSkipping(!isTrue(condition));
+ else if (directive == QString("ifdef"))
+ pushSkipping(!defines->exactMatch(condition));
+ else if (directive == QString("ifndef"))
+ pushSkipping(defines->exactMatch(condition));
+ } else if (directive[0] == QChar('e')) {
+ if (directive == QString("elif")) {
+ bool old = popSkipping();
+ if (old)
+ pushSkipping(!isTrue(condition));
+ else
+ pushSkipping(true);
+ } else if (directive == QString("else")) {
+ pushSkipping(!popSkipping());
+ } else if (directive == QString("endif")) {
+ popSkipping();
+ }
+ } else if (directive == QString("define")) {
+ if (versionX->exactMatch(condition))
+ yyVersion = versionX->cap(1);
+ }
+ }
+
+ int tok;
+ do {
+ /*
+ We set yyLex now, and after getToken() this will be
+ yyPrevLex. This way, we skip over the preprocessor
+ directive.
+ */
+ qstrcpy(yyLex, yyPrevLex);
+
+ /*
+ If getToken() meets another #, it will call
+ getTokenAfterPreprocessor() once again, which could in turn
+ call getToken() again, etc. Unless there are 10,000 or so
+ preprocessor directives in a row, this shouldn't overflow
+ the stack.
+ */
+ tok = getToken();
+ } while (yyNumPreprocessorSkipping > 0);
+ return tok;
+}
+
+/*
+ Pushes a new skipping value onto the stack. This corresponds to entering a
+ new #if block.
+*/
+void Tokenizer::pushSkipping(bool skip)
+{
+ yyPreprocessorSkipping.push(skip);
+ if (skip)
+ yyNumPreprocessorSkipping++;
+}
+
+/*
+ Pops a skipping value from the stack. This corresponds to reaching a #endif.
+*/
+bool Tokenizer::popSkipping()
+{
+ if (yyPreprocessorSkipping.isEmpty()) {
+ yyTokLoc.warning(tr("Unexpected #elif, #else or #endif"));
+ return true;
+ }
+
+ bool skip = yyPreprocessorSkipping.pop();
+ if (skip)
+ yyNumPreprocessorSkipping--;
+ return skip;
+}
+
+/*
+ Returns true if the condition evaluates as true, otherwise false. The
+ condition is represented by a string. Unsophisticated parsing techniques are
+ used. The preprocessing method could be named StriNg-Oriented PreProcessing,
+ as SNOBOL stands for StriNg-Oriented symBOlic Language.
+*/
+bool Tokenizer::isTrue(const QString &condition)
+{
+ int firstOr = -1;
+ int firstAnd = -1;
+ int parenDepth = 0;
+
+ /*
+ Find the first logical operator at top level, but be careful
+ about precedence. Examples:
+
+ X || Y // the or
+ X || Y || Z // the leftmost or
+ X || Y && Z // the or
+ X && Y || Z // the or
+ (X || Y) && Z // the and
+ */
+ for (int i = 0; i < (int) condition.length() - 1; i++) {
+ QChar ch = condition[i];
+ if (ch == QChar('(')) {
+ parenDepth++;
+ } else if (ch == QChar(')')) {
+ parenDepth--;
+ } else if (parenDepth == 0) {
+ if (condition[i + 1] == ch) {
+ if (ch == QChar('|')) {
+ firstOr = i;
+ break;
+ } else if (ch == QChar('&')) {
+ if (firstAnd == -1)
+ firstAnd = i;
+ }
+ }
+ }
+ }
+ if (firstOr != -1)
+ return isTrue(condition.left(firstOr)) ||
+ isTrue(condition.mid(firstOr + 2));
+ if (firstAnd != -1)
+ return isTrue(condition.left(firstAnd)) &&
+ isTrue(condition.mid(firstAnd + 2));
+
+ QString t = condition.simplified();
+ if (t.isEmpty())
+ return true;
+
+ if (t[0] == QChar('!'))
+ return !isTrue(t.mid(1));
+ if (t[0] == QChar('(') && t.right(1)[0] == QChar(')'))
+ return isTrue(t.mid(1, t.length() - 2));
+
+ if (definedX->exactMatch(t))
+ return defines->exactMatch(definedX->cap(1));
+ else
+ return !falsehoods->exactMatch(t);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/tokenizer.h b/tools/qdoc3/tokenizer.h
new file mode 100644
index 0000000000..745c427a1a
--- /dev/null
+++ b/tools/qdoc3/tokenizer.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ tokenizer.h
+*/
+
+#ifndef TOKENIZER_H
+#define TOKENIZER_H
+
+#include <qstack.h>
+#include <qstring.h>
+
+#include <stdio.h>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Here come the C++ tokens we support. The first part contains
+ all-purpose tokens; then come keywords.
+
+ If you add a keyword, make sure to modify the keyword array in
+ tokenizer.cpp as well, and possibly adjust Tok_FirstKeyword and
+ Tok_LastKeyword.
+*/
+enum { Tok_Eoi, Tok_Ampersand, Tok_Aster, Tok_Caret, Tok_LeftParen,
+ Tok_RightParen, Tok_LeftParenAster, Tok_Equal, Tok_LeftBrace,
+ Tok_RightBrace, Tok_Semicolon, Tok_Colon, Tok_LeftAngle,
+ Tok_RightAngle, Tok_Comma, Tok_Ellipsis, Tok_Gulbrandsen,
+ Tok_LeftBracket, Tok_RightBracket, Tok_Tilde, Tok_SomeOperator,
+ Tok_Number, Tok_String, Tok_Doc, Tok_Comment, Tok_Ident, Tok_At,
+ Tok_char, Tok_class, Tok_const, Tok_double, Tok_enum,
+ Tok_explicit, Tok_friend, Tok_inline, Tok_int, Tok_long,
+ Tok_namespace, Tok_operator, Tok_private, Tok_protected,
+ Tok_public, Tok_short, Tok_signals, Tok_signed, Tok_slots,
+ Tok_static, Tok_struct, Tok_template, Tok_typedef,
+ Tok_typename, Tok_union, Tok_unsigned, Tok_using, Tok_virtual,
+ Tok_void, Tok_volatile, Tok_int64, Tok_Q_OBJECT, Tok_Q_OVERRIDE,
+ Tok_Q_PROPERTY, Tok_Q_DECLARE_SEQUENTIAL_ITERATOR,
+ Tok_Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR,
+ Tok_Q_DECLARE_ASSOCIATIVE_ITERATOR,
+ Tok_Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR,
+ Tok_Q_DECLARE_FLAGS, Tok_Q_SIGNALS, Tok_Q_SLOTS, Tok_QT_COMPAT,
+ Tok_QT_COMPAT_CONSTRUCTOR, Tok_QT_DEPRECATED, Tok_QT_MOC_COMPAT,
+ Tok_QT_MODULE, Tok_QT3_SUPPORT, Tok_QT3_SUPPORT_CONSTRUCTOR,
+ Tok_QT3_MOC_SUPPORT, Tok_QDOC_PROPERTY,
+ Tok_FirstKeyword = Tok_char, Tok_LastKeyword = Tok_QDOC_PROPERTY };
+
+/*
+ The Tokenizer class implements lexical analysis of C++ source
+ files.
+
+ Not every operator or keyword of C++ is recognized; only those
+ that are interesting to us. Some Qt keywords or macros are also
+ recognized.
+*/
+
+class Tokenizer
+{
+ public:
+ Tokenizer(const Location& loc, const QByteArray &in);
+ Tokenizer(const Location& loc, FILE *in);
+
+ ~Tokenizer();
+
+ int getToken();
+ void setParsingFnOrMacro(bool macro) { parsingMacro = macro; }
+ bool parsingFnOrMacro() const { return parsingMacro; }
+
+ const Location &location() const { return yyTokLoc; }
+ QString previousLexeme() const { return QString(yyPrevLex); }
+ QString lexeme() const { return QString(yyLex); }
+ QString version() const { return yyVersion; }
+ int braceDepth() const { return yyBraceDepth; }
+ int parenDepth() const { return yyParenDepth; }
+ int bracketDepth() const { return yyBracketDepth; }
+
+ static void initialize(const Config &config);
+ static void terminate();
+ static bool isTrue(const QString &condition);
+
+ private:
+ void init();
+ void start(const Location& loc);
+ /*
+ This limit on the length of a lexeme seems fairly high, but a
+ doc comment can be arbitrarily long. The previous 65,536 limit
+ was reached by Mark Summerfield.
+ */
+ enum { yyLexBufSize = 524288 };
+
+ int getch()
+ {
+ return yyPos == yyIn.size() ? EOF : yyIn[yyPos++];
+ }
+
+ inline int getChar()
+ {
+ if (yyCh == EOF)
+ return EOF;
+ if (yyLexLen < yyLexBufSize - 1) {
+ yyLex[yyLexLen++] = (char) yyCh;
+ yyLex[yyLexLen] = '\0';
+ }
+ yyCurLoc.advance(yyCh);
+ int ch = getch();
+ if (ch == EOF)
+ return EOF;
+ // cast explicitely to make sure the value of ch
+ // is in range [0..255] to avoid assert messages
+ // when using debug CRT that checks its input.
+ return int(uint(uchar(ch)));
+ }
+
+ int getTokenAfterPreprocessor();
+ void pushSkipping(bool skip);
+ bool popSkipping();
+
+ Location yyTokLoc;
+ Location yyCurLoc;
+ char *yyLexBuf1;
+ char *yyLexBuf2;
+ char *yyPrevLex;
+ char *yyLex;
+ size_t yyLexLen;
+ QStack<bool> yyPreprocessorSkipping;
+ int yyNumPreprocessorSkipping;
+ int yyBraceDepth;
+ int yyParenDepth;
+ int yyBracketDepth;
+ int yyCh;
+
+ QString yyVersion;
+ bool parsingMacro;
+
+ protected:
+ QByteArray yyIn;
+ int yyPos;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/tr.h b/tools/qdoc3/tr.h
new file mode 100644
index 0000000000..0966e4559e
--- /dev/null
+++ b/tools/qdoc3/tr.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ tr.h
+*/
+
+#ifndef TR_H
+#define TR_H
+
+#include <qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+inline QString tr( const char *sourceText, const char * /* comment */ = 0 )
+{
+ return QString( QLatin1String(sourceText) );
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp
new file mode 100644
index 0000000000..0fbd438bc3
--- /dev/null
+++ b/tools/qdoc3/tree.cpp
@@ -0,0 +1,2012 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ tree.cpp
+*/
+
+#include <QtCore>
+#include <QDomDocument>
+
+#include "atom.h"
+#include "doc.h"
+#include "htmlgenerator.h"
+#include "location.h"
+#include "node.h"
+#include "text.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+struct InheritanceBound
+{
+ Node::Access access;
+ QStringList basePath;
+ QString dataTypeWithTemplateArgs;
+ InnerNode *parent;
+
+ InheritanceBound()
+ : access(Node::Public) { }
+ InheritanceBound(Node::Access access0,
+ const QStringList& basePath0,
+ const QString &dataTypeWithTemplateArgs0,
+ InnerNode *parent)
+ : access(access0), basePath(basePath0),
+ dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0),
+ parent(parent) { }
+};
+
+struct Target
+{
+ Node *node;
+ Atom *atom;
+ int priority;
+};
+
+typedef QMap<PropertyNode::FunctionRole, QString> RoleMap;
+typedef QMap<PropertyNode *, RoleMap> PropertyMap;
+typedef QMultiMap<QString, Node *> GroupMap;
+typedef QMultiHash<QString, FakeNode *> FakeNodeHash;
+typedef QMultiHash<QString, Target> TargetHash;
+
+class TreePrivate
+{
+public:
+ QMap<ClassNode *, QList<InheritanceBound> > unresolvedInheritanceMap;
+ PropertyMap unresolvedPropertyMap;
+ GroupMap groupMap;
+ QMultiMap<QString, QString> publicGroupMap;
+ FakeNodeHash fakeNodesByTitle;
+ TargetHash targetHash;
+ QList<QPair<ClassNode*,QString> > basesList;
+ QList<QPair<FunctionNode*,QString> > relatedList;
+};
+
+/*!
+ \class Tree
+ */
+
+/*!
+ The default constructor is the only constructor.
+ */
+Tree::Tree()
+ : roo(0, "")
+{
+ priv = new TreePrivate;
+}
+
+/*!
+ The destructor deletes the internal, private tree.
+ */
+Tree::~Tree()
+{
+ delete priv;
+}
+
+/*!
+ */
+Node *Tree::findNode(const QStringList &path, Node *relative, int findFlags)
+{
+ return const_cast<Node*>(const_cast<const Tree*>(this)->findNode(path,
+ relative,
+ findFlags));
+}
+
+/*!
+ */
+const Node *Tree::findNode(const QStringList &path,
+ const Node *relative,
+ int findFlags) const
+{
+ if (!relative)
+ relative = root();
+
+ do {
+ const Node *node = relative;
+ int i;
+
+ for (i = 0; i < path.size(); ++i) {
+ if (node == 0 || !node->isInnerNode())
+ break;
+
+ const Node *next =
+ static_cast<const InnerNode*>(node)->findNode(path.at(i));
+ if (!next && (findFlags & SearchEnumValues) && i == path.size()-1)
+ next = static_cast<const InnerNode*>(node)->findEnumNodeForValue(path.at(i));
+
+ if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
+ NodeList baseClasses = allBaseClasses(static_cast<const ClassNode *>(node));
+ foreach (const Node *baseClass, baseClasses) {
+ next = static_cast<const InnerNode *>(baseClass)->findNode(path.at(i));
+ if (!next && (findFlags & SearchEnumValues) && i == path.size() - 1)
+ next = static_cast<const InnerNode *>(baseClass)
+ ->findEnumNodeForValue(path.at(i));
+ if (next)
+ break;
+ }
+ }
+ node = next;
+ }
+ if (node && i == path.size()
+ && (!(findFlags & NonFunction) || node->type() != Node::Function
+ || ((FunctionNode *)node)->metaness() == FunctionNode::MacroWithoutParams))
+ return node;
+ relative = relative->parent();
+ } while (relative);
+
+ return 0;
+}
+
+/*!
+ */
+Node *Tree::findNode(const QStringList &path,
+ Node::Type type,
+ Node *relative,
+ int findFlags)
+{
+ return const_cast<Node*>(const_cast<const Tree*>(this)->findNode(path,
+ type,
+ relative,
+ findFlags));
+}
+
+/*!
+ */
+const Node *Tree::findNode(const QStringList &path,
+ Node::Type type,
+ const Node *relative,
+ int findFlags) const
+{
+ const Node *node = findNode(path, relative, findFlags);
+ if (node != 0 && node->type() == type)
+ return node;
+ return 0;
+}
+
+/*!
+ */
+FunctionNode *Tree::findFunctionNode(const QStringList& path,
+ Node *relative,
+ int findFlags)
+{
+ return const_cast<FunctionNode *>(
+ const_cast<const Tree *>(this)->findFunctionNode(path, relative, findFlags));
+}
+
+/*!
+ */
+const FunctionNode *Tree::findFunctionNode(const QStringList &path,
+ const Node *relative,
+ int findFlags) const
+{
+ if (!relative)
+ relative = root();
+ do {
+ const Node *node = relative;
+ int i;
+
+ for (i = 0; i < path.size(); ++i) {
+ if (node == 0 || !node->isInnerNode())
+ break;
+
+ const Node *next;
+ if (i == path.size() - 1)
+ next = ((InnerNode *) node)->findFunctionNode(path.at(i));
+ else
+ next = ((InnerNode *) node)->findNode(path.at(i));
+
+ if (!next && node->type() == Node::Class && (findFlags & SearchBaseClasses)) {
+ NodeList baseClasses = allBaseClasses(static_cast<const ClassNode *>(node));
+ foreach (const Node *baseClass, baseClasses) {
+ if (i == path.size() - 1)
+ next = static_cast<const InnerNode *>(baseClass)->
+ findFunctionNode(path.at(i));
+ else
+ next = static_cast<const InnerNode *>(baseClass)->findNode(path.at(i));
+
+ if (next)
+ break;
+ }
+ }
+
+ node = next;
+ }
+ if (node && i == path.size() && node->type() == Node::Function) {
+ // CppCodeParser::processOtherMetaCommand ensures that reimplemented
+ // functions are private.
+ const FunctionNode *func = static_cast<const FunctionNode*>(node);
+
+ while (func->access() == Node::Private) {
+ const FunctionNode *from = func->reimplementedFrom();
+ if (from != 0) {
+ if (from->access() != Node::Private)
+ return from;
+ else
+ func = from;
+ } else
+ break;
+ }
+ return func;
+ }
+ relative = relative->parent();
+ } while (relative);
+
+ return 0;
+}
+
+/*!
+ */
+FunctionNode *Tree::findFunctionNode(const QStringList &parentPath,
+ const FunctionNode *clone,
+ Node *relative,
+ int findFlags)
+{
+ return const_cast<FunctionNode *>(
+ const_cast<const Tree *>(this)->findFunctionNode(parentPath,
+ clone,
+ relative,
+ findFlags));
+}
+
+/*!
+ */
+const FunctionNode *Tree::findFunctionNode(const QStringList &parentPath,
+ const FunctionNode *clone,
+ const Node *relative,
+ int findFlags) const
+{
+ const Node *parent = findNode(parentPath, relative, findFlags);
+ if (parent == 0 || !parent->isInnerNode()) {
+ return 0;
+ } else {
+ return ((InnerNode *)parent)->findFunctionNode(clone);
+ }
+}
+
+static const int NumSuffixes = 3;
+static const char * const suffixes[NumSuffixes] = { "", "s", "es" };
+
+/*!
+ */
+const FakeNode *Tree::findFakeNodeByTitle(const QString &title) const
+{
+ for (int pass = 0; pass < NumSuffixes; ++pass) {
+ FakeNodeHash::const_iterator i =
+ priv->fakeNodesByTitle.find(Doc::canonicalTitle(title + suffixes[pass]));
+ if (i != priv->fakeNodesByTitle.constEnd()) {
+ FakeNodeHash::const_iterator j = i;
+ ++j;
+ if (j != priv->fakeNodesByTitle.constEnd() && j.key() == i.key()) {
+ QList<Location> internalLocations;
+ while (j != priv->fakeNodesByTitle.constEnd()) {
+ if (j.key() == i.key() && j.value()->url().isEmpty())
+ internalLocations.append(j.value()->doc().location());
+ ++j;
+ }
+ if (internalLocations.size() > 0) {
+ i.value()->doc().location().warning(
+ tr("Page '%1' defined in more than one location:").arg(title));
+ foreach (const Location &location, internalLocations)
+ location.warning(tr("(defined here)"));
+ }
+ }
+ return i.value();
+ }
+ }
+ return 0;
+}
+
+/*!
+ */
+const Node*
+Tree::findUnambiguousTarget(const QString &target, Atom *&atom) const
+{
+ Target bestTarget = {0, 0, INT_MAX};
+ int numBestTargets = 0;
+
+ for (int pass = 0; pass < NumSuffixes; ++pass) {
+ TargetHash::const_iterator i =
+ priv->targetHash.find(Doc::canonicalTitle(target + suffixes[pass]));
+ if (i != priv->targetHash.constEnd()) {
+ TargetHash::const_iterator j = i;
+ do {
+ const Target &candidate = j.value();
+ if (candidate.priority < bestTarget.priority) {
+ bestTarget = candidate;
+ numBestTargets = 1;
+ } else if (candidate.priority == bestTarget.priority) {
+ ++numBestTargets;
+ }
+ ++j;
+ } while (j != priv->targetHash.constEnd() && j.key() == i.key());
+
+ if (numBestTargets == 1) {
+ atom = bestTarget.atom;
+ return bestTarget.node;
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ */
+Atom *Tree::findTarget(const QString &target, const Node *node) const
+{
+ for (int pass = 0; pass < NumSuffixes; ++pass) {
+ QString key = Doc::canonicalTitle(target + suffixes[pass]);
+ TargetHash::const_iterator i = priv->targetHash.find(key);
+
+ if (i != priv->targetHash.constEnd()) {
+ do {
+ if (i.value().node == node)
+ return i.value().atom;
+ ++i;
+ } while (i != priv->targetHash.constEnd() && i.key() == key);
+ }
+ }
+ return 0;
+}
+
+/*!
+ */
+void Tree::addBaseClass(ClassNode *subclass, Node::Access access,
+ const QStringList &basePath,
+ const QString &dataTypeWithTemplateArgs,
+ InnerNode *parent)
+{
+ priv->unresolvedInheritanceMap[subclass].append(
+ InheritanceBound(access,
+ basePath,
+ dataTypeWithTemplateArgs,
+ parent)
+ );
+}
+
+
+/*!
+ */
+void Tree::addPropertyFunction(PropertyNode *property,
+ const QString &funcName,
+ PropertyNode::FunctionRole funcRole)
+{
+ priv->unresolvedPropertyMap[property].insert(funcRole, funcName);
+}
+
+/*!
+ */
+void Tree::addToGroup(Node *node, const QString &group)
+{
+ priv->groupMap.insert(group, node);
+}
+
+/*!
+ */
+QMultiMap<QString, Node *> Tree::groups() const
+{
+ return priv->groupMap;
+}
+
+/*!
+ */
+void Tree::addToPublicGroup(Node *node, const QString &group)
+{
+ priv->publicGroupMap.insert(node->name(), group);
+ addToGroup(node, group);
+}
+
+/*!
+ */
+QMultiMap<QString, QString> Tree::publicGroups() const
+{
+ return priv->publicGroupMap;
+}
+
+/*!
+ */
+void Tree::resolveInheritance(NamespaceNode *rootNode)
+{
+ if (!rootNode)
+ rootNode = root();
+
+ for (int pass = 0; pass < 2; pass++) {
+ NodeList::ConstIterator c = rootNode->childNodes().begin();
+ while (c != rootNode->childNodes().end()) {
+ if ((*c)->type() == Node::Class)
+ resolveInheritance(pass, (ClassNode *) *c);
+ else if ((*c)->type() == Node::Namespace) {
+ NamespaceNode *ns = static_cast<NamespaceNode*>(*c);
+ resolveInheritance(ns);
+ }
+ ++c;
+ }
+ if (rootNode == root())
+ priv->unresolvedInheritanceMap.clear();
+ }
+}
+
+/*!
+ */
+void Tree::resolveProperties()
+{
+ PropertyMap::ConstIterator propEntry;
+
+ propEntry = priv->unresolvedPropertyMap.begin();
+ while (propEntry != priv->unresolvedPropertyMap.end()) {
+ PropertyNode *property = propEntry.key();
+ InnerNode *parent = property->parent();
+ QString getterName = (*propEntry)[PropertyNode::Getter];
+ QString setterName = (*propEntry)[PropertyNode::Setter];
+ QString resetterName = (*propEntry)[PropertyNode::Resetter];
+
+ NodeList::ConstIterator c = parent->childNodes().begin();
+ while (c != parent->childNodes().end()) {
+ if ((*c)->type() == Node::Function) {
+ FunctionNode *function = static_cast<FunctionNode *>(*c);
+ if (function->access() == property->access() &&
+ (function->status() == property->status() ||
+ function->doc().isEmpty())) {
+ if (function->name() == getterName) {
+ property->addFunction(function, PropertyNode::Getter);
+ } else if (function->name() == setterName) {
+ property->addFunction(function, PropertyNode::Setter);
+ } else if (function->name() == resetterName) {
+ property->addFunction(function, PropertyNode::Resetter);
+ }
+ }
+ }
+ ++c;
+ }
+ ++propEntry;
+ }
+
+ propEntry = priv->unresolvedPropertyMap.begin();
+ while (propEntry != priv->unresolvedPropertyMap.end()) {
+ PropertyNode *property = propEntry.key();
+ // redo it to set the property functions
+ if (property->overriddenFrom())
+ property->setOverriddenFrom(property->overriddenFrom());
+ ++propEntry;
+ }
+
+ priv->unresolvedPropertyMap.clear();
+}
+
+/*!
+ */
+void Tree::resolveInheritance(int pass, ClassNode *classe)
+{
+ if (pass == 0) {
+ QList<InheritanceBound> bounds = priv->unresolvedInheritanceMap[classe];
+ QList<InheritanceBound>::ConstIterator b = bounds.begin();
+ while (b != bounds.end()) {
+ ClassNode *baseClass = (ClassNode*)findNode((*b).basePath,
+ Node::Class);
+ if (!baseClass && (*b).parent)
+ baseClass = (ClassNode*)findNode((*b).basePath,
+ Node::Class,
+ (*b).parent);
+ if (baseClass)
+ classe->addBaseClass((*b).access,
+ baseClass,
+ (*b).dataTypeWithTemplateArgs);
+ ++b;
+ }
+ }
+ else {
+ NodeList::ConstIterator c = classe->childNodes().begin();
+ while (c != classe->childNodes().end()) {
+ if ((*c)->type() == Node::Function) {
+ FunctionNode *func = (FunctionNode *) *c;
+ FunctionNode *from = findVirtualFunctionInBaseClasses(classe, func);
+ if (from != 0) {
+ if (func->virtualness() == FunctionNode::NonVirtual)
+ func->setVirtualness(FunctionNode::ImpureVirtual);
+ func->setReimplementedFrom(from);
+ }
+ }
+ else if ((*c)->type() == Node::Property) {
+ fixPropertyUsingBaseClasses(classe, static_cast<PropertyNode *>(*c));
+ }
+ ++c;
+ }
+ }
+}
+
+/*!
+ */
+void Tree::resolveGroups()
+{
+ GroupMap::const_iterator i;
+ QString prevGroup;
+ for (i = priv->groupMap.constBegin(); i != priv->groupMap.constEnd(); ++i) {
+ if (i.value()->access() == Node::Private)
+ continue;
+
+ FakeNode *fake =
+ static_cast<FakeNode*>(findNode(QStringList(i.key()),Node::Fake));
+ if (fake && fake->subType() == FakeNode::Group) {
+ fake->addGroupMember(i.value());
+ }
+ else {
+ if (prevGroup != i.key())
+ i.value()->doc().location().warning(tr("No such group '%1'").arg(i.key()));
+ }
+
+ prevGroup = i.key();
+ }
+
+ //priv->groupMap.clear();
+}
+
+/*!
+ */
+void Tree::resolveTargets()
+{
+ // need recursion
+
+ foreach (Node *child, roo.childNodes()) {
+ if (child->type() == Node::Fake) {
+ FakeNode *node = static_cast<FakeNode *>(child);
+ priv->fakeNodesByTitle.insert(Doc::canonicalTitle(node->title()), node);
+ }
+
+ if (child->doc().hasTableOfContents()) {
+ const QList<Atom *> &toc = child->doc().tableOfContents();
+ Target target;
+ target.node = child;
+ target.priority = 3;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ target.atom = toc.at(i);
+ QString title = Text::sectionHeading(target.atom).toString();
+ if (!title.isEmpty())
+ priv->targetHash.insert(Doc::canonicalTitle(title), target);
+ }
+ }
+ if (child->doc().hasKeywords()) {
+ const QList<Atom *> &keywords = child->doc().keywords();
+ Target target;
+ target.node = child;
+ target.priority = 1;
+
+ for (int i = 0; i < keywords.size(); ++i) {
+ target.atom = keywords.at(i);
+ priv->targetHash.insert(Doc::canonicalTitle(target.atom->string()), target);
+ }
+ }
+ if (child->doc().hasTargets()) {
+ const QList<Atom *> &toc = child->doc().targets();
+ Target target;
+ target.node = child;
+ target.priority = 2;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ target.atom = toc.at(i);
+ priv->targetHash.insert(Doc::canonicalTitle(target.atom->string()), target);
+ }
+ }
+ }
+}
+
+/*!
+ */
+void Tree::fixInheritance(NamespaceNode *rootNode)
+{
+ if (!rootNode)
+ rootNode = root();
+
+ NodeList::ConstIterator c = rootNode->childNodes().begin();
+ while (c != rootNode->childNodes().end()) {
+ if ((*c)->type() == Node::Class)
+ static_cast<ClassNode *>(*c)->fixBaseClasses();
+ else if ((*c)->type() == Node::Namespace) {
+ NamespaceNode *ns = static_cast<NamespaceNode*>(*c);
+ fixInheritance(ns);
+ }
+ ++c;
+ }
+}
+
+/*!
+ */
+FunctionNode *Tree::findVirtualFunctionInBaseClasses(ClassNode *classe,
+ FunctionNode *clone)
+{
+ QList<RelatedClass>::ConstIterator r = classe->baseClasses().begin();
+ while (r != classe->baseClasses().end()) {
+ FunctionNode *func;
+ if (((func = findVirtualFunctionInBaseClasses((*r).node, clone)) != 0 ||
+ (func = (*r).node->findFunctionNode(clone)) != 0)) {
+ if (func->virtualness() != FunctionNode::NonVirtual)
+ return func;
+ }
+ ++r;
+ }
+ return 0;
+}
+
+/*!
+ */
+void Tree::fixPropertyUsingBaseClasses(ClassNode *classe,
+ PropertyNode *property)
+{
+ QList<RelatedClass>::const_iterator r = classe->baseClasses().begin();
+ while (r != classe->baseClasses().end()) {
+ PropertyNode *baseProperty =
+ static_cast<PropertyNode *>(r->node->findNode(property->name(),
+ Node::Property));
+ if (baseProperty) {
+ fixPropertyUsingBaseClasses(r->node, baseProperty);
+ property->setOverriddenFrom(baseProperty);
+ }
+ else {
+ fixPropertyUsingBaseClasses(r->node, property);
+ }
+ ++r;
+ }
+}
+
+/*!
+ */
+NodeList Tree::allBaseClasses(const ClassNode *classe) const
+{
+ NodeList result;
+ foreach (const RelatedClass &r, classe->baseClasses()) {
+ result += r.node;
+ result += allBaseClasses(r.node);
+ }
+ return result;
+}
+
+/*!
+ */
+void Tree::readIndexes(const QStringList &indexFiles)
+{
+ foreach (const QString &indexFile, indexFiles)
+ readIndexFile(indexFile);
+}
+
+/*!
+ Read the QDomDocument at \a path and get the index from it.
+ */
+void Tree::readIndexFile(const QString &path)
+{
+ QFile file(path);
+ if (file.open(QFile::ReadOnly)) {
+ QDomDocument document;
+ document.setContent(&file);
+ file.close();
+
+ QDomElement indexElement = document.documentElement();
+ QString indexUrl = indexElement.attribute("url", "");
+ priv->basesList.clear();
+ priv->relatedList.clear();
+
+ // Scan all elements in the XML file, constructing a map that contains
+ // base classes for each class found.
+
+ QDomElement child = indexElement.firstChildElement();
+ while (!child.isNull()) {
+ readIndexSection(child, root(), indexUrl);
+ child = child.nextSiblingElement();
+ }
+
+ // Now that all the base classes have been found for this index,
+ // arrange them into an inheritance hierarchy.
+
+ resolveIndex();
+ }
+}
+
+/*!
+ */
+void Tree::readIndexSection(const QDomElement &element,
+ InnerNode *parent,
+ const QString &indexUrl)
+{
+ QString name = element.attribute("name");
+ QString href = element.attribute("href");
+
+ Node *section;
+ Location location;
+
+ if (element.nodeName() == "namespace") {
+ section = new NamespaceNode(parent, name);
+
+ if (!indexUrl.isEmpty())
+ location = Location(indexUrl + "/" + name.toLower() + ".html");
+ else if (!indexUrl.isNull())
+ location = Location(name.toLower() + ".html");
+
+ }
+ else if (element.nodeName() == "class") {
+ section = new ClassNode(parent, name);
+ priv->basesList.append(QPair<ClassNode*,QString>(
+ static_cast<ClassNode*>(section), element.attribute("bases")));
+
+ if (!indexUrl.isEmpty())
+ location = Location(indexUrl + "/" + name.toLower() + ".html");
+ else if (!indexUrl.isNull())
+ location = Location(name.toLower() + ".html");
+
+ }
+ else if (element.nodeName() == "page") {
+ FakeNode::SubType subtype;
+ if (element.attribute("subtype") == "example")
+ subtype = FakeNode::Example;
+ else if (element.attribute("subtype") == "header")
+ subtype = FakeNode::HeaderFile;
+ else if (element.attribute("subtype") == "file")
+ subtype = FakeNode::File;
+ else if (element.attribute("subtype") == "group")
+ subtype = FakeNode::Group;
+ else if (element.attribute("subtype") == "module")
+ subtype = FakeNode::Module;
+ else if (element.attribute("subtype") == "page")
+ subtype = FakeNode::Page;
+ else if (element.attribute("subtype") == "externalpage")
+ subtype = FakeNode::ExternalPage;
+ else
+ return;
+
+ FakeNode *fakeNode = new FakeNode(parent, name, subtype);
+ fakeNode->setTitle(element.attribute("title"));
+
+ if (element.hasAttribute("location"))
+ name = element.attribute("location", "");
+
+ if (!indexUrl.isEmpty())
+ location = Location(indexUrl + "/" + name);
+ else if (!indexUrl.isNull())
+ location = Location(name);
+
+ section = fakeNode;
+
+ }
+ else if (element.nodeName() == "enum") {
+ EnumNode *enumNode = new EnumNode(parent, name);
+
+ if (!indexUrl.isEmpty())
+ location =
+ Location(indexUrl + "/" + parent->name().toLower() + ".html");
+ else if (!indexUrl.isNull())
+ location = Location(parent->name().toLower() + ".html");
+
+ QDomElement child = element.firstChildElement("value");
+ while (!child.isNull()) {
+ EnumItem item(child.attribute("name"), child.attribute("value"));
+ enumNode->addItem(item);
+ child = child.nextSiblingElement("value");
+ }
+
+ section = enumNode;
+
+ } else if (element.nodeName() == "typedef") {
+ section = new TypedefNode(parent, name);
+
+ if (!indexUrl.isEmpty())
+ location =
+ Location(indexUrl + "/" + parent->name().toLower() + ".html");
+ else if (!indexUrl.isNull())
+ location = Location(parent->name().toLower() + ".html");
+
+ }
+ else if (element.nodeName() == "property") {
+ section = new PropertyNode(parent, name);
+
+ if (!indexUrl.isEmpty())
+ location =
+ Location(indexUrl + "/" + parent->name().toLower() + ".html");
+ else if (!indexUrl.isNull())
+ location = Location(parent->name().toLower() + ".html");
+
+ } else if (element.nodeName() == "function") {
+ FunctionNode::Virtualness virt;
+ if (element.attribute("virtual") == "non")
+ virt = FunctionNode::NonVirtual;
+ else if (element.attribute("virtual") == "impure")
+ virt = FunctionNode::ImpureVirtual;
+ else if (element.attribute("virtual") == "pure")
+ virt = FunctionNode::PureVirtual;
+ else
+ return;
+
+ FunctionNode::Metaness meta;
+ if (element.attribute("meta") == "plain")
+ meta = FunctionNode::Plain;
+ else if (element.attribute("meta") == "signal")
+ meta = FunctionNode::Signal;
+ else if (element.attribute("meta") == "slot")
+ meta = FunctionNode::Slot;
+ else if (element.attribute("meta") == "constructor")
+ meta = FunctionNode::Ctor;
+ else if (element.attribute("meta") == "destructor")
+ meta = FunctionNode::Dtor;
+ else if (element.attribute("meta") == "macro")
+ meta = FunctionNode::MacroWithParams;
+ else if (element.attribute("meta") == "macrowithparams")
+ meta = FunctionNode::MacroWithParams;
+ else if (element.attribute("meta") == "macrowithoutparams")
+ meta = FunctionNode::MacroWithoutParams;
+ else
+ return;
+
+ FunctionNode *functionNode = new FunctionNode(parent, name);
+ functionNode->setReturnType(element.attribute("return"));
+ functionNode->setVirtualness(virt);
+ functionNode->setMetaness(meta);
+ functionNode->setConst(element.attribute("const") == "true");
+ functionNode->setStatic(element.attribute("static") == "true");
+ functionNode->setOverload(element.attribute("overload") == "true");
+
+ if (element.hasAttribute("relates")
+ && element.attribute("relates") != parent->name()) {
+ priv->relatedList.append(
+ QPair<FunctionNode*,QString>(functionNode,
+ element.attribute("relates")));
+ }
+
+ QDomElement child = element.firstChildElement("parameter");
+ while (!child.isNull()) {
+ // Do not use the default value for the parameter; it is not
+ // required, and has been known to cause problems.
+ Parameter parameter(child.attribute("left"),
+ child.attribute("right"),
+ child.attribute("name"),
+ ""); // child.attribute("default")
+ functionNode->addParameter(parameter);
+ child = child.nextSiblingElement("parameter");
+ }
+
+ section = functionNode;
+
+ if (!indexUrl.isEmpty())
+ location =
+ Location(indexUrl + "/" + parent->name().toLower() + ".html");
+ else if (!indexUrl.isNull())
+ location = Location(parent->name().toLower() + ".html");
+
+ }
+ else if (element.nodeName() == "variable") {
+ section = new VariableNode(parent, name);
+
+ if (!indexUrl.isEmpty())
+ location = Location(indexUrl + "/" + parent->name().toLower() + ".html");
+ else if (!indexUrl.isNull())
+ location = Location(parent->name().toLower() + ".html");
+
+ }
+ else if (element.nodeName() == "keyword") {
+ Target target;
+ target.node = parent;
+ target.priority = 1;
+ target.atom = new Atom(Atom::Target, name);
+ priv->targetHash.insert(name, target);
+ return;
+
+ }
+ else if (element.nodeName() == "target") {
+ Target target;
+ target.node = parent;
+ target.priority = 2;
+ target.atom = new Atom(Atom::Target, name);
+ priv->targetHash.insert(name, target);
+ return;
+
+ }
+ else if (element.nodeName() == "contents") {
+ Target target;
+ target.node = parent;
+ target.priority = 3;
+ target.atom = new Atom(Atom::Target, name);
+ priv->targetHash.insert(name, target);
+ return;
+
+ }
+ else
+ return;
+
+ QString access = element.attribute("access");
+ if (access == "public")
+ section->setAccess(Node::Public);
+ else if (access == "protected")
+ section->setAccess(Node::Protected);
+ else if (access == "private")
+ section->setAccess(Node::Private);
+ else
+ section->setAccess(Node::Public);
+
+ if (element.nodeName() != "page") {
+ QString threadSafety = element.attribute("threadsafety");
+ if (threadSafety == "non-reentrant")
+ section->setThreadSafeness(Node::NonReentrant);
+ else if (threadSafety == "reentrant")
+ section->setThreadSafeness(Node::Reentrant);
+ else if (threadSafety == "thread safe")
+ section->setThreadSafeness(Node::ThreadSafe);
+ else
+ section->setThreadSafeness(Node::UnspecifiedSafeness);
+ }
+ else
+ section->setThreadSafeness(Node::UnspecifiedSafeness);
+
+ QString status = element.attribute("status");
+ if (status == "compat")
+ section->setStatus(Node::Compat);
+ else if (status == "obsolete")
+ section->setStatus(Node::Obsolete);
+ else if (status == "deprecated")
+ section->setStatus(Node::Deprecated);
+ else if (status == "preliminary")
+ section->setStatus(Node::Preliminary);
+ else if (status == "commendable")
+ section->setStatus(Node::Commendable);
+ else if (status == "internal")
+ section->setStatus(Node::Internal);
+ else if (status == "main")
+ section->setStatus(Node::Main);
+ else
+ section->setStatus(Node::Commendable);
+
+ section->setModuleName(element.attribute("module"));
+ if (!indexUrl.isEmpty()) {
+ if (indexUrl.startsWith("."))
+ section->setUrl(href);
+ else
+ section->setUrl(indexUrl + "/" + href);
+ }
+
+ // Create some content for the node.
+ QSet<QString> emptySet;
+
+ Doc doc(location, location, " ", emptySet); // placeholder
+ section->setDoc(doc);
+
+ if (section->isInnerNode()) {
+ InnerNode *inner = static_cast<InnerNode*>(section);
+ if (inner) {
+ QDomElement child = element.firstChildElement();
+
+ while (!child.isNull()) {
+ if (element.nodeName() == "class")
+ readIndexSection(child, inner, indexUrl);
+ else if (element.nodeName() == "page")
+ readIndexSection(child, inner, indexUrl);
+ else if (element.nodeName() == "namespace" && !name.isEmpty())
+ // The root node in the index is a namespace with an empty name.
+ readIndexSection(child, inner, indexUrl);
+ else
+ readIndexSection(child, parent, indexUrl);
+
+ child = child.nextSiblingElement();
+ }
+ }
+ }
+}
+
+/*!
+ */
+QString Tree::readIndexText(const QDomElement &element)
+{
+ QString text;
+ QDomNode child = element.firstChild();
+ while (!child.isNull()) {
+ if (child.isText())
+ text += child.toText().nodeValue();
+ child = child.nextSibling();
+ }
+ return text;
+}
+
+/*!
+ */
+void Tree::resolveIndex()
+{
+ QPair<ClassNode*,QString> pair;
+
+ foreach (pair, priv->basesList) {
+ foreach (const QString &base, pair.second.split(",")) {
+ Node *baseClass = root()->findNode(base, Node::Class);
+ if (baseClass) {
+ pair.first->addBaseClass(Node::Public,
+ static_cast<ClassNode*>(baseClass));
+ }
+ }
+ }
+
+ QPair<FunctionNode*,QString> relatedPair;
+
+ foreach (relatedPair, priv->relatedList) {
+ Node *classNode = root()->findNode(relatedPair.second, Node::Class);
+ if (classNode)
+ relatedPair.first->setRelates(static_cast<ClassNode*>(classNode));
+ }
+}
+
+/*!
+ Generate the index section with the given \a writer for the \a node
+ specified, returning true if an element was written; otherwise returns
+ false.
+ */
+bool Tree::generateIndexSection(QXmlStreamWriter &writer,
+ const Node *node,
+ bool generateInternalNodes) const
+{
+ if (!node->url().isEmpty())
+ return false;
+
+ QString nodeName;
+ switch (node->type()) {
+ case Node::Namespace:
+ nodeName = "namespace";
+ break;
+ case Node::Class:
+ nodeName = "class";
+ break;
+ case Node::Fake:
+ nodeName = "page";
+ break;
+ case Node::Enum:
+ nodeName = "enum";
+ break;
+ case Node::Typedef:
+ nodeName = "typedef";
+ break;
+ case Node::Property:
+ nodeName = "property";
+ break;
+ case Node::Function:
+ nodeName = "function";
+ break;
+ case Node::Variable:
+ nodeName = "variable";
+ break;
+ case Node::Target:
+ nodeName = "target";
+ break;
+ default:
+ return false;
+ }
+
+ QString access;
+ switch (node->access()) {
+ case Node::Public:
+ access = "public";
+ break;
+ case Node::Protected:
+ access = "protected";
+ break;
+ case Node::Private:
+ // Do not include private non-internal nodes in the index.
+ // (Internal public and protected nodes are marked as private
+ // by qdoc. We can check their internal status to determine
+ // whether they were really private to begin with.)
+ if (node->status() == Node::Internal && generateInternalNodes)
+ access = "internal";
+ else
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ QString objName = node->name();
+
+ // Special case: only the root node should have an empty name.
+ if (objName.isEmpty() && node != root())
+ return false;
+
+ writer.writeStartElement(nodeName);
+
+ QXmlStreamAttributes attributes;
+ writer.writeAttribute("access", access);
+
+ if (node->type() != Node::Fake) {
+ QString threadSafety;
+ switch (node->threadSafeness()) {
+ case Node::NonReentrant:
+ threadSafety = "non-reentrant";
+ break;
+ case Node::Reentrant:
+ threadSafety = "reentrant";
+ break;
+ case Node::ThreadSafe:
+ threadSafety = "thread safe";
+ break;
+ case Node::UnspecifiedSafeness:
+ default:
+ threadSafety = "unspecified";
+ break;
+ }
+ writer.writeAttribute("threadsafety", threadSafety);
+ }
+
+ QString status;
+ switch (node->status()) {
+ case Node::Compat:
+ status = "compat";
+ break;
+ case Node::Obsolete:
+ status = "obsolete";
+ break;
+ case Node::Deprecated:
+ status = "deprecated";
+ break;
+ case Node::Preliminary:
+ status = "preliminary";
+ break;
+ case Node::Commendable:
+ status = "commendable";
+ break;
+ case Node::Internal:
+ status = "internal";
+ break;
+ case Node::Main:
+ default:
+ status = "main";
+ break;
+ }
+ writer.writeAttribute("status", status);
+
+ writer.writeAttribute("name", objName);
+ QString fullName = fullDocumentName(node);
+ if (fullName != objName)
+ writer.writeAttribute("fullname", fullName);
+ writer.writeAttribute("href", fullDocumentLocation(node));
+ if (node->type() != Node::Fake)
+ writer.writeAttribute("location", node->location().fileName());
+
+ switch (node->type()) {
+
+ case Node::Class:
+ {
+ // Classes contain information about their base classes.
+
+ const ClassNode *classNode = static_cast<const ClassNode*>(node);
+ QList<RelatedClass> bases = classNode->baseClasses();
+ QSet<QString> baseStrings;
+ foreach (const RelatedClass &related, bases) {
+ ClassNode *baseClassNode = related.node;
+ baseStrings.insert(baseClassNode->name());
+ }
+ writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
+ writer.writeAttribute("module", node->moduleName());
+ }
+ break;
+
+ case Node::Namespace:
+ writer.writeAttribute("module", node->moduleName());
+ break;
+
+ case Node::Fake:
+ {
+ /*
+ Fake nodes (such as manual pages) contain subtypes,
+ titles and other attributes.
+ */
+
+ const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
+ switch (fakeNode->subType()) {
+ case FakeNode::Example:
+ writer.writeAttribute("subtype", "example");
+ break;
+ case FakeNode::HeaderFile:
+ writer.writeAttribute("subtype", "header");
+ break;
+ case FakeNode::File:
+ writer.writeAttribute("subtype", "file");
+ break;
+ case FakeNode::Group:
+ writer.writeAttribute("subtype", "group");
+ break;
+ case FakeNode::Module:
+ writer.writeAttribute("subtype", "module");
+ break;
+ case FakeNode::Page:
+ writer.writeAttribute("subtype", "page");
+ break;
+ case FakeNode::ExternalPage:
+ writer.writeAttribute("subtype", "externalpage");
+ break;
+ default:
+ break;
+ }
+ writer.writeAttribute("title", fakeNode->title());
+ writer.writeAttribute("fulltitle", fakeNode->fullTitle());
+ writer.writeAttribute("subtitle", fakeNode->subTitle());
+ writer.writeAttribute("location", fakeNode->doc().location().fileName());
+ }
+ break;
+
+ case Node::Function:
+ {
+ /*
+ Function nodes contain information about the type of
+ function being described.
+ */
+
+ const FunctionNode *functionNode =
+ static_cast<const FunctionNode*>(node);
+
+ switch (functionNode->virtualness()) {
+ case FunctionNode::NonVirtual:
+ writer.writeAttribute("virtual", "non");
+ break;
+ case FunctionNode::ImpureVirtual:
+ writer.writeAttribute("virtual", "impure");
+ break;
+ case FunctionNode::PureVirtual:
+ writer.writeAttribute("virtual", "pure");
+ break;
+ default:
+ break;
+ }
+ switch (functionNode->metaness()) {
+ case FunctionNode::Plain:
+ writer.writeAttribute("meta", "plain");
+ break;
+ case FunctionNode::Signal:
+ writer.writeAttribute("meta", "signal");
+ break;
+ case FunctionNode::Slot:
+ writer.writeAttribute("meta", "slot");
+ break;
+ case FunctionNode::Ctor:
+ writer.writeAttribute("meta", "constructor");
+ break;
+ case FunctionNode::Dtor:
+ writer.writeAttribute("meta", "destructor");
+ break;
+ case FunctionNode::MacroWithParams:
+ writer.writeAttribute("meta", "macrowithparams");
+ break;
+ case FunctionNode::MacroWithoutParams:
+ writer.writeAttribute("meta", "macrowithoutparams");
+ break;
+ default:
+ break;
+ }
+ writer.writeAttribute("const", functionNode->isConst()?"true":"false");
+ writer.writeAttribute("static", functionNode->isStatic()?"true":"false");
+ writer.writeAttribute("overload", functionNode->isOverload()?"true":"false");
+ if (functionNode->isOverload())
+ writer.writeAttribute("overload-number", QString::number(functionNode->overloadNumber()));
+ if (functionNode->relates())
+ writer.writeAttribute("relates", functionNode->relates()->name());
+ const PropertyNode *propertyNode = functionNode->associatedProperty();
+ if (propertyNode)
+ writer.writeAttribute("associated-property", propertyNode->name());
+ writer.writeAttribute("type", functionNode->returnType());
+ }
+ break;
+
+ case Node::Property:
+ {
+ const PropertyNode *propertyNode = static_cast<const PropertyNode*>(node);
+ writer.writeAttribute("type", propertyNode->dataType());
+ foreach (const Node *fnNode, propertyNode->getters()) {
+ if (fnNode) {
+ const FunctionNode *functionNode = static_cast<const FunctionNode*>(fnNode);
+ writer.writeStartElement("getter");
+ writer.writeAttribute("name", functionNode->name());
+ writer.writeEndElement(); // getter
+ }
+ }
+ foreach (const Node *fnNode, propertyNode->setters()) {
+ if (fnNode) {
+ const FunctionNode *functionNode = static_cast<const FunctionNode*>(fnNode);
+ writer.writeStartElement("setter");
+ writer.writeAttribute("name", functionNode->name());
+ writer.writeEndElement(); // getter
+ }
+ }
+ foreach (const Node *fnNode, propertyNode->resetters()) {
+ if (fnNode) {
+ const FunctionNode *functionNode = static_cast<const FunctionNode*>(fnNode);
+ writer.writeStartElement("resetter");
+ writer.writeAttribute("name", functionNode->name());
+ writer.writeEndElement(); // getter
+ }
+ }
+ }
+ break;
+
+ case Node::Variable:
+ {
+ const VariableNode *variableNode =
+ static_cast<const VariableNode*>(node);
+ writer.writeAttribute("type", variableNode->dataType());
+ writer.writeAttribute("static",
+ variableNode->isStatic() ? "true" : "false");
+ }
+ break;
+ default:
+ break;
+ }
+
+ // Inner nodes and function nodes contain child nodes of some sort, either
+ // actual child nodes or function parameters. For these, we close the
+ // opening tag, create child elements, then add a closing tag for the
+ // element. Elements for all other nodes are closed in the opening tag.
+
+ if (node->isInnerNode()) {
+
+ const InnerNode *inner = static_cast<const InnerNode*>(node);
+
+ // For internal pages, we canonicalize the target, keyword and content
+ // item names so that they can be used by qdoc for other sets of
+ // documentation.
+ // The reason we do this here is that we don't want to ruin
+ // externally composed indexes, containing non-qdoc-style target names
+ // when reading in indexes.
+
+ if (inner->doc().hasTargets()) {
+ bool external = false;
+ if (inner->type() == Node::Fake) {
+ const FakeNode *fakeNode = static_cast<const FakeNode *>(inner);
+ if (fakeNode->subType() == FakeNode::ExternalPage)
+ external = true;
+ }
+
+ foreach (const Atom *target, inner->doc().targets()) {
+ QString targetName = target->string();
+ if (!external)
+ targetName = Doc::canonicalTitle(targetName);
+
+ writer.writeStartElement("target");
+ writer.writeAttribute("name", targetName);
+ writer.writeEndElement(); // target
+ }
+ }
+ if (inner->doc().hasKeywords()) {
+ foreach (const Atom *keyword, inner->doc().keywords()) {
+ writer.writeStartElement("keyword");
+ writer.writeAttribute("name",
+ Doc::canonicalTitle(keyword->string()));
+ writer.writeEndElement(); // keyword
+ }
+ }
+ if (inner->doc().hasTableOfContents()) {
+ for (int i = 0; i < inner->doc().tableOfContents().size(); ++i) {
+ Atom *item = inner->doc().tableOfContents()[i];
+ int level = inner->doc().tableOfContentsLevels()[i];
+
+ QString title = Text::sectionHeading(item).toString();
+ writer.writeStartElement("contents");
+ writer.writeAttribute("name", Doc::canonicalTitle(title));
+ writer.writeAttribute("title", title);
+ writer.writeAttribute("level", QString::number(level));
+ writer.writeEndElement(); // contents
+ }
+ }
+
+ }
+ else if (node->type() == Node::Function) {
+
+ const FunctionNode *functionNode = static_cast<const FunctionNode*>(node);
+ // Write a signature attribute for convenience.
+ QStringList signatureList;
+ QStringList resolvedParameters;
+
+ foreach (const Parameter &parameter, functionNode->parameters()) {
+ QString leftType = parameter.leftType();
+ const Node *leftNode =
+ const_cast<Tree*>(this)->findNode(parameter.leftType().split("::"),
+ Node::Typedef, 0, SearchBaseClasses|NonFunction);
+ if (!leftNode) {
+ leftNode = const_cast<Tree *>(this)->findNode(
+ parameter.leftType().split("::"), Node::Typedef,
+ node->parent(), SearchBaseClasses|NonFunction);
+ }
+ if (leftNode) {
+ if (leftNode->type() == Node::Typedef) {
+ const TypedefNode *typedefNode =
+ static_cast<const TypedefNode *>(leftNode);
+ if (typedefNode->associatedEnum()) {
+ leftType = "QFlags<"+fullDocumentName(typedefNode->associatedEnum())+">";
+ }
+ }
+ else
+ leftType = fullDocumentName(leftNode);
+ }
+ resolvedParameters.append(leftType);
+ signatureList.append(leftType + " " + parameter.name());
+ }
+
+ QString signature = functionNode->name()+"("+signatureList.join(", ")+")";
+ if (functionNode->isConst())
+ signature += " const";
+ writer.writeAttribute("signature", signature);
+
+ for (int i = 0; i < functionNode->parameters().size(); ++i) {
+ Parameter parameter = functionNode->parameters()[i];
+ writer.writeStartElement("parameter");
+ writer.writeAttribute("left", resolvedParameters[i]);
+ writer.writeAttribute("right", parameter.rightType());
+ writer.writeAttribute("name", parameter.name());
+ writer.writeAttribute("default", parameter.defaultValue());
+ writer.writeEndElement(); // parameter
+ }
+
+ }
+ else if (node->type() == Node::Enum) {
+
+ const EnumNode *enumNode = static_cast<const EnumNode*>(node);
+ if (enumNode->flagsType()) {
+ writer.writeAttribute("typedef",
+ fullDocumentName(enumNode->flagsType()));
+ }
+ foreach (const EnumItem &item, enumNode->items()) {
+ writer.writeStartElement("value");
+ writer.writeAttribute("name", item.name());
+ writer.writeAttribute("value", item.value());
+ writer.writeEndElement(); // value
+ }
+
+ }
+ else if (node->type() == Node::Typedef) {
+
+ const TypedefNode *typedefNode = static_cast<const TypedefNode*>(node);
+ if (typedefNode->associatedEnum()) {
+ writer.writeAttribute("enum",
+ fullDocumentName(typedefNode->associatedEnum()));
+ }
+ }
+
+ return true;
+}
+
+/*!
+ */
+void Tree::generateIndexSections(QXmlStreamWriter &writer,
+ const Node *node,
+ bool generateInternalNodes) const
+{
+ if (generateIndexSection(writer, node, generateInternalNodes)) {
+
+ if (node->isInnerNode()) {
+ const InnerNode *inner = static_cast<const InnerNode *>(node);
+
+ // Recurse to write an element for this child node and all its children.
+ foreach (const Node *child, inner->childNodes())
+ generateIndexSections(writer, child, generateInternalNodes);
+
+/*
+ foreach (const Node *child, inner->relatedNodes()) {
+ QDomElement childElement = generateIndexSections(document, child);
+ element.appendChild(childElement);
+ }
+*/
+ }
+ writer.writeEndElement();
+ }
+}
+
+/*!
+ Outputs an index file.
+ */
+void Tree::generateIndex(const QString &fileName,
+ const QString &url,
+ const QString &title,
+ bool generateInternalNodes) const
+{
+ QFile file(fileName);
+ if (!file.open(QFile::WriteOnly | QFile::Text))
+ return ;
+
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument();
+ writer.writeDTD("<!DOCTYPE QDOCINDEX>");
+
+ writer.writeStartElement("INDEX");
+ writer.writeAttribute("url", url);
+ writer.writeAttribute("title", title);
+ writer.writeAttribute("version", version());
+
+ generateIndexSections(writer, root(), generateInternalNodes);
+
+ writer.writeEndElement(); // INDEX
+ writer.writeEndElement(); // QDOCINDEX
+ writer.writeEndDocument();
+ file.close();
+}
+
+/*!
+ Generate the tag file section with the given \a writer for the \a node
+ specified, returning true if an element was written; otherwise returns
+ false.
+ */
+void Tree::generateTagFileCompounds(QXmlStreamWriter &writer,
+ const InnerNode *inner) const
+{
+ foreach (const Node *node, inner->childNodes()) {
+
+ if (!node->url().isEmpty())
+ continue;
+
+ QString kind;
+ switch (node->type()) {
+ case Node::Namespace:
+ kind = "namespace";
+ break;
+ case Node::Class:
+ kind = "class";
+ break;
+ case Node::Enum:
+ case Node::Typedef:
+ case Node::Property:
+ case Node::Function:
+ case Node::Variable:
+ case Node::Target:
+ default:
+ continue;
+ }
+
+ QString access;
+ switch (node->access()) {
+ case Node::Public:
+ access = "public";
+ break;
+ case Node::Protected:
+ access = "protected";
+ break;
+ case Node::Private:
+ default:
+ continue;
+ }
+
+ QString objName = node->name();
+
+ // Special case: only the root node should have an empty name.
+ if (objName.isEmpty() && node != root())
+ continue;
+
+ // *** Write the starting tag for the element here. ***
+ writer.writeStartElement("compound");
+ writer.writeAttribute("kind", kind);
+
+ if (node->type() == Node::Class) {
+ writer.writeTextElement("name", fullDocumentName(node));
+ writer.writeTextElement("filename", fullDocumentLocation(node));
+
+ // Classes contain information about their base classes.
+ const ClassNode *classNode = static_cast<const ClassNode*>(node);
+ QList<RelatedClass> bases = classNode->baseClasses();
+ foreach (const RelatedClass &related, bases) {
+ ClassNode *baseClassNode = related.node;
+ writer.writeTextElement("base", baseClassNode->name());
+ }
+
+ // Recurse to write all members.
+ generateTagFileMembers(writer, static_cast<const InnerNode *>(node));
+ writer.writeEndElement();
+
+ // Recurse to write all compounds.
+ generateTagFileCompounds(writer, static_cast<const InnerNode *>(node));
+ } else {
+ writer.writeTextElement("name", fullDocumentName(node));
+ writer.writeTextElement("filename", fullDocumentLocation(node));
+
+ // Recurse to write all members.
+ generateTagFileMembers(writer, static_cast<const InnerNode *>(node));
+ writer.writeEndElement();
+
+ // Recurse to write all compounds.
+ generateTagFileCompounds(writer, static_cast<const InnerNode *>(node));
+ }
+ }
+}
+
+/*!
+ */
+void Tree::generateTagFileMembers(QXmlStreamWriter &writer,
+ const InnerNode *inner) const
+{
+ foreach (const Node *node, inner->childNodes()) {
+
+ if (!node->url().isEmpty())
+ continue;
+
+ QString nodeName;
+ QString kind;
+ switch (node->type()) {
+ case Node::Enum:
+ nodeName = "member";
+ kind = "enum";
+ break;
+ case Node::Typedef:
+ nodeName = "member";
+ kind = "typedef";
+ break;
+ case Node::Property:
+ nodeName = "member";
+ kind = "property";
+ break;
+ case Node::Function:
+ nodeName = "member";
+ kind = "function";
+ break;
+ case Node::Namespace:
+ nodeName = "namespace";
+ break;
+ case Node::Class:
+ nodeName = "class";
+ break;
+ case Node::Variable:
+ case Node::Target:
+ default:
+ continue;
+ }
+
+ QString access;
+ switch (node->access()) {
+ case Node::Public:
+ access = "public";
+ break;
+ case Node::Protected:
+ access = "protected";
+ break;
+ case Node::Private:
+ default:
+ continue;
+ }
+
+ QString objName = node->name();
+
+ // Special case: only the root node should have an empty name.
+ if (objName.isEmpty() && node != root())
+ continue;
+
+ // *** Write the starting tag for the element here. ***
+ writer.writeStartElement(nodeName);
+ if (!kind.isEmpty())
+ writer.writeAttribute("kind", kind);
+
+ switch (node->type()) {
+
+ case Node::Class:
+ writer.writeCharacters(fullDocumentName(node));
+ writer.writeEndElement();
+ break;
+ case Node::Namespace:
+ writer.writeCharacters(fullDocumentName(node));
+ writer.writeEndElement();
+ break;
+ case Node::Function:
+ {
+ /*
+ Function nodes contain information about
+ the type of function being described.
+ */
+
+ const FunctionNode *functionNode =
+ static_cast<const FunctionNode*>(node);
+ writer.writeAttribute("protection", access);
+
+ switch (functionNode->virtualness()) {
+ case FunctionNode::NonVirtual:
+ writer.writeAttribute("virtualness", "non");
+ break;
+ case FunctionNode::ImpureVirtual:
+ writer.writeAttribute("virtualness", "virtual");
+ break;
+ case FunctionNode::PureVirtual:
+ writer.writeAttribute("virtual", "pure");
+ break;
+ default:
+ break;
+ }
+ writer.writeAttribute("static",
+ functionNode->isStatic() ? "yes" : "no");
+
+ if (functionNode->virtualness() == FunctionNode::NonVirtual)
+ writer.writeTextElement("type", functionNode->returnType());
+ else
+ writer.writeTextElement("type",
+ "virtual " + functionNode->returnType());
+
+ writer.writeTextElement("name", objName);
+ QStringList pieces = fullDocumentLocation(node).split("#");
+ writer.writeTextElement("anchorfile", pieces[0]);
+ writer.writeTextElement("anchor", pieces[1]);
+
+ // Write a signature attribute for convenience.
+ QStringList signatureList;
+
+ foreach (const Parameter &parameter, functionNode->parameters()) {
+ QString leftType = parameter.leftType();
+ const Node *leftNode = const_cast<Tree *>(this)->findNode(parameter.leftType().split("::"),
+ Node::Typedef, 0, SearchBaseClasses|NonFunction);
+ if (!leftNode) {
+ leftNode = const_cast<Tree *>(this)->findNode(
+ parameter.leftType().split("::"), Node::Typedef,
+ node->parent(), SearchBaseClasses|NonFunction);
+ }
+ if (leftNode) {
+ const TypedefNode *typedefNode = static_cast<const TypedefNode *>(leftNode);
+ if (typedefNode->associatedEnum()) {
+ leftType = "QFlags<"+fullDocumentName(typedefNode->associatedEnum())+">";
+ }
+ }
+ signatureList.append(leftType + " " + parameter.name());
+ }
+
+ QString signature = "("+signatureList.join(", ")+")";
+ if (functionNode->isConst())
+ signature += " const";
+ if (functionNode->virtualness() == FunctionNode::PureVirtual)
+ signature += " = 0";
+ writer.writeTextElement("arglist", signature);
+ }
+ writer.writeEndElement(); // member
+ break;
+
+ case Node::Property:
+ {
+ const PropertyNode *propertyNode = static_cast<const PropertyNode*>(node);
+ writer.writeAttribute("type", propertyNode->dataType());
+ writer.writeTextElement("name", objName);
+ QStringList pieces = fullDocumentLocation(node).split("#");
+ writer.writeTextElement("anchorfile", pieces[0]);
+ writer.writeTextElement("anchor", pieces[1]);
+ writer.writeTextElement("arglist", "");
+ }
+ writer.writeEndElement(); // member
+ break;
+
+ case Node::Enum:
+ {
+ const EnumNode *enumNode = static_cast<const EnumNode*>(node);
+ writer.writeTextElement("name", objName);
+ QStringList pieces = fullDocumentLocation(node).split("#");
+ writer.writeTextElement("anchor", pieces[1]);
+ writer.writeTextElement("arglist", "");
+ writer.writeEndElement(); // member
+
+ for (int i = 0; i < enumNode->items().size(); ++i) {
+ EnumItem item = enumNode->items().value(i);
+ writer.writeStartElement("member");
+ writer.writeAttribute("name", item.name());
+ writer.writeTextElement("anchor", pieces[1]);
+ writer.writeTextElement("arglist", "");
+ writer.writeEndElement(); // member
+ }
+ }
+ break;
+
+ case Node::Typedef:
+ {
+ const TypedefNode *typedefNode = static_cast<const TypedefNode*>(node);
+ if (typedefNode->associatedEnum())
+ writer.writeAttribute("type", fullDocumentName(typedefNode->associatedEnum()));
+ else
+ writer.writeAttribute("type", "");
+ writer.writeTextElement("name", objName);
+ QStringList pieces = fullDocumentLocation(node).split("#");
+ writer.writeTextElement("anchorfile", pieces[0]);
+ writer.writeTextElement("anchor", pieces[1]);
+ writer.writeTextElement("arglist", "");
+ }
+ writer.writeEndElement(); // member
+ break;
+
+ case Node::Variable:
+ case Node::Target:
+ default:
+ break;
+ }
+ }
+}
+
+/*!
+ */
+void Tree::generateTagFile(const QString &fileName) const
+{
+ QFile file(fileName);
+ if (!file.open(QFile::WriteOnly | QFile::Text))
+ return ;
+
+ QXmlStreamWriter writer(&file);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument();
+
+ writer.writeStartElement("tagfile");
+
+ generateTagFileCompounds(writer, root());
+
+ writer.writeEndElement(); // tagfile
+ writer.writeEndDocument();
+ file.close();
+}
+
+/*!
+ */
+void Tree::addExternalLink(const QString &url, const Node *relative)
+{
+ FakeNode *fakeNode = new FakeNode(root(), url, FakeNode::ExternalPage);
+ fakeNode->setAccess(Node::Public);
+
+ // Create some content for the node.
+ QSet<QString> emptySet;
+ Location location(relative->doc().location());
+ Doc doc(location, location, " ", emptySet); // placeholder
+ fakeNode->setDoc(doc);
+}
+
+/*!
+ Returns the full document location for HTML-based documentation.
+ This should be moved into the HTML generator.
+ */
+QString Tree::fullDocumentLocation(const Node *node) const
+{
+ if (!node)
+ return "";
+ if (!node->url().isEmpty())
+ return node->url();
+
+ if (node->type() == Node::Namespace) {
+
+ // The root namespace has no name - check for this before creating
+ // an attribute containing the location of any documentation.
+
+ if (!node->fileBase().isEmpty())
+ return node->fileBase() + ".html";
+ else
+ return "";
+ }
+ else if (node->type() == Node::Fake) {
+ return node->fileBase() + ".html";
+ }
+ else if (node->fileBase().isEmpty())
+ return "";
+
+ QString parentName;
+ Node *parentNode = 0;
+
+ if ((parentNode = node->relates()))
+ parentName = fullDocumentLocation(node->relates());
+ else if ((parentNode = node->parent()))
+ parentName = fullDocumentLocation(node->parent());
+
+ switch (node->type()) {
+ case Node::Class:
+ case Node::Namespace:
+ if (parentNode && !parentNode->name().isEmpty())
+ return parentName.replace(".html", "") + "-"
+ + node->fileBase().toLower() + ".html";
+ else
+ return node->fileBase() + ".html";
+ case Node::Function:
+ {
+ /*
+ Functions can be destructors, overloaded, or
+ have associated properties.
+ */
+ const FunctionNode *functionNode =
+ static_cast<const FunctionNode *>(node);
+
+ // Functions can be compatibility functions or be obsolete.
+ switch (node->status()) {
+ case Node::Compat:
+ parentName.replace(".html", "-qt3.html");
+ break;
+ case Node::Obsolete:
+ parentName.replace(".html", "-obsolete.html");
+ break;
+ default:
+ ;
+ }
+
+ if (functionNode->metaness() == FunctionNode::Dtor)
+ return parentName + "#dtor." + functionNode->name().mid(1);
+
+ if (functionNode->associatedProperty())
+ return fullDocumentLocation(functionNode->associatedProperty());
+
+ if (functionNode->overloadNumber() > 1)
+ return parentName + "#" + functionNode->name()
+ + "-" + QString::number(functionNode->overloadNumber());
+ else
+ return parentName + "#" + functionNode->name();
+ }
+
+ /*
+ Use node->name() instead of node->fileBase() as
+ the latter returns the name in lower-case. For
+ HTML anchors, we need to preserve the case.
+ */
+ case Node::Enum:
+ return parentName + "#" + node->name() + "-enum";
+ case Node::Typedef:
+ return parentName + "#" + node->name() + "-typedef";
+ case Node::Property:
+ return parentName + "#" + node->name() + "-prop";
+ case Node::Variable:
+ return parentName + "#" + node->name() + "-var";
+ case Node::Target:
+ return parentName + "#" + Doc::canonicalTitle(node->name());
+ case Node::Fake:
+ {
+ QString pageName = node->name();
+ return pageName.replace("/", "-").replace(".", "-") + ".html";
+ }
+ break;
+ default:
+ break;
+ }
+
+ return "";
+}
+
+/*!
+ */
+QString Tree::fullDocumentName(const Node *node) const
+{
+ if (!node)
+ return "";
+
+ QStringList pieces;
+ const Node *n = node;
+
+ do {
+ if (!n->name().isEmpty())
+ pieces.insert(0, n->name());
+
+ if (n->type() == Node::Fake)
+ break;
+
+ // Examine the parent node if one exists.
+ if (n->parent())
+ n = n->parent();
+ else
+ break;
+ } while (true);
+
+ // Create a name based on the type of the ancestor node.
+ if (n->type() == Node::Fake)
+ return pieces.join("#");
+ else
+ return pieces.join("::");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/tree.h b/tools/qdoc3/tree.h
new file mode 100644
index 0000000000..8aebcaa099
--- /dev/null
+++ b/tools/qdoc3/tree.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ tree.h
+*/
+
+#ifndef TREE_H
+#define TREE_H
+
+#include "node.h"
+#include <QDomElement>
+#include <QXmlStreamWriter>
+
+QT_BEGIN_NAMESPACE
+
+class QStringList;
+class TreePrivate;
+
+class Tree
+{
+ public:
+ enum FindFlag { SearchBaseClasses = 0x1,
+ SearchEnumValues = 0x2,
+ NonFunction = 0x4 };
+
+ Tree();
+ ~Tree();
+
+ Node *findNode(const QStringList &path, Node *relative=0, int findFlags=0);
+ Node *findNode(const QStringList &path,
+ Node::Type type,
+ Node *relative = 0,
+ int findFlags = 0);
+ FunctionNode *findFunctionNode(const QStringList &path,
+ Node *relative = 0,
+ int findFlags = 0);
+ FunctionNode *findFunctionNode(const QStringList &parentPath,
+ const FunctionNode *clone,
+ Node *relative = 0,
+ int findFlags = 0);
+ void addBaseClass(ClassNode *subclass,
+ Node::Access access,
+ const QStringList &basePath,
+ const QString &dataTypeWithTemplateArgs,
+ InnerNode *parent = 0);
+ void addPropertyFunction(PropertyNode *property,
+ const QString &funcName,
+ PropertyNode::FunctionRole funcRole);
+ void addToGroup(Node *node, const QString &group);
+ void addToPublicGroup(Node *node, const QString &group);
+ QMultiMap<QString, Node *> groups() const;
+ QMultiMap<QString, QString> publicGroups() const;
+ void resolveInheritance(NamespaceNode *rootNode = 0);
+ void resolveProperties();
+ void resolveGroups();
+ void resolveTargets();
+ void fixInheritance(NamespaceNode *rootNode = 0);
+ void setVersion(const QString &version) { vers = version; }
+ NamespaceNode *root() { return &roo; }
+
+ QString version() const { return vers; }
+ const Node *findNode(const QStringList &path,
+ const Node *relative = 0,
+ int findFlags = 0) const;
+ const Node *findNode(const QStringList &path,
+ Node::Type type, const
+ Node *relative = 0,
+ int findFlags = 0) const;
+ const FunctionNode *findFunctionNode(const QStringList &path,
+ const Node *relative = 0,
+ int findFlags = 0) const;
+ const FunctionNode *findFunctionNode(const QStringList &parentPath,
+ const FunctionNode *clone,
+ const Node *relative = 0,
+ int findFlags = 0) const;
+ const FakeNode *findFakeNodeByTitle(const QString &title) const;
+ const Node *findUnambiguousTarget(const QString &target, Atom *&atom) const;
+ Atom *findTarget(const QString &target, const Node *node) const;
+ const NamespaceNode *root() const { return &roo; }
+ void readIndexes(const QStringList &indexFiles);
+ bool generateIndexSection(QXmlStreamWriter &writer, const Node *node,
+ bool generateInternalNodes = false) const;
+ void generateIndexSections(QXmlStreamWriter &writer, const Node *node,
+ bool generateInternalNodes = false) const;
+ void generateIndex(const QString &fileName,
+ const QString &url,
+ const QString &title,
+ bool generateInternalNodes = false) const;
+ void generateTagFileCompounds(QXmlStreamWriter &writer,
+ const InnerNode *inner) const;
+ void generateTagFileMembers(QXmlStreamWriter &writer,
+ const InnerNode *inner) const;
+ void generateTagFile(const QString &fileName) const;
+ void addExternalLink(const QString &url, const Node *relative);
+ QString fullDocumentName(const Node *node) const;
+ QString fullDocumentLocation(const Node *node) const;
+
+ private:
+ void resolveInheritance(int pass, ClassNode *classe);
+ FunctionNode *findVirtualFunctionInBaseClasses(ClassNode *classe,
+ FunctionNode *clone);
+ void fixPropertyUsingBaseClasses(ClassNode *classe, PropertyNode *property);
+ NodeList allBaseClasses(const ClassNode *classe) const;
+ void readIndexFile(const QString &path);
+ void readIndexSection(const QDomElement &element, InnerNode *parent,
+ const QString &indexUrl);
+ QString readIndexText(const QDomElement &element);
+ void resolveIndex();
+
+ private:
+ NamespaceNode roo;
+ QString vers;
+ TreePrivate *priv;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/uncompressor.cpp b/tools/qdoc3/uncompressor.cpp
new file mode 100644
index 0000000000..8f3897d826
--- /dev/null
+++ b/tools/qdoc3/uncompressor.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ uncompressor.cpp
+*/
+
+#include "uncompressor.h"
+
+QT_BEGIN_NAMESPACE
+
+QList<Uncompressor *> Uncompressor::uncompressors;
+
+
+/*!
+ \class Uncompressor
+
+ \brief The Uncompressor class is a base class for classes that
+ know how to uncompress a certain kind of compressed file.
+
+ The uncompressor contains a list of the filename extensions
+ of the file types that the uncompressor knows how to uncompress.
+
+ It maintains a static list of all the instances of Uncompressor
+ that have been created. It also has a static function for searching
+ that list to find the uncompressor to use for uncompressing a file
+ with a certain extension.
+ */
+
+/*!
+ The constructor takes a list of filename extensions, which it
+ copies and saves internally. This uncompressor is prepended
+ to the stack list.
+ */
+Uncompressor::Uncompressor( const QStringList& extensions )
+ : fileExts( extensions )
+{
+ uncompressors.prepend( this );
+}
+
+/*!
+ The destructor deletes all the filename extensions.
+ */
+Uncompressor::~Uncompressor()
+{
+ uncompressors.removeAll( this );
+}
+
+/*!
+ This function searches the static list of uncompressors to find the
+ first one that can handle \a fileName. If it finds an acceptable
+ uncompressor, it returns a pointer to it. Otherwise it returns null.
+*/
+Uncompressor*
+Uncompressor::uncompressorForFileName( const QString& fileName )
+{
+ int dot = -1;
+ while ( (dot = fileName.indexOf(".", dot + 1)) != -1 ) {
+ QString ext = fileName.mid( dot + 1 );
+ QList<Uncompressor *>::ConstIterator u = uncompressors.begin();
+ while ( u != uncompressors.end() ) {
+ if ( (*u)->fileExtensions().contains(ext) )
+ return *u;
+ ++u;
+ }
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/uncompressor.h b/tools/qdoc3/uncompressor.h
new file mode 100644
index 0000000000..4d5c9af503
--- /dev/null
+++ b/tools/qdoc3/uncompressor.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ uncompressor.h
+*/
+
+#ifndef UNCOMPRESSOR_H
+#define UNCOMPRESSOR_H
+
+#include <qstringlist.h>
+
+#include "location.h"
+
+QT_BEGIN_NAMESPACE
+
+class Uncompressor
+{
+public:
+ Uncompressor( const QStringList& extensions );
+ virtual ~Uncompressor();
+
+ virtual QString uncompressedFilePath( const QString& filePath ) = 0;
+ virtual void uncompressFile( const Location& location,
+ const QString& filePath,
+ const QString& outputFilePath ) = 0;
+
+ static Uncompressor *uncompressorForFileName( const QString& fileName );
+
+protected:
+ const QStringList& fileExtensions() const { return fileExts; }
+
+private:
+ QStringList fileExts;
+
+ static QList<Uncompressor *> uncompressors;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/webxmlgenerator.cpp b/tools/qdoc3/webxmlgenerator.cpp
new file mode 100644
index 0000000000..0438adfdfd
--- /dev/null
+++ b/tools/qdoc3/webxmlgenerator.cpp
@@ -0,0 +1,1195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ webxmlgenerator.cpp
+*/
+
+#include <QtXml>
+
+#include "codemarker.h"
+#include "pagegenerator.h"
+#include "webxmlgenerator.h"
+#include "node.h"
+#include "separator.h"
+#include "tree.h"
+
+QT_BEGIN_NAMESPACE
+
+#define COMMAND_VERSION Doc::alias("version")
+
+WebXMLGenerator::WebXMLGenerator()
+ : PageGenerator()
+{
+}
+
+WebXMLGenerator::~WebXMLGenerator()
+{
+}
+
+void WebXMLGenerator::initializeGenerator(const Config &config)
+{
+ Generator::initializeGenerator(config);
+
+ project = config.getString(CONFIG_PROJECT);
+
+ projectDescription = config.getString(CONFIG_DESCRIPTION);
+ if (projectDescription.isEmpty() && !project.isEmpty())
+ projectDescription = project + " Reference Documentation";
+
+ projectUrl = config.getString(CONFIG_URL);
+
+ generateIndex = config.getBool(CONFIG_GENERATEINDEX);
+}
+
+void WebXMLGenerator::terminateGenerator()
+{
+ PageGenerator::terminateGenerator();
+}
+
+QString WebXMLGenerator::format()
+{
+ return "WebXML";
+}
+
+QString WebXMLGenerator::fileExtension(const Node * /* node */)
+{
+ return "xml";
+}
+
+void WebXMLGenerator::generateTree(const Tree *tree, CodeMarker *marker)
+{
+ tre = tree;
+ moduleClassMap.clear();
+ moduleNamespaceMap.clear();
+ serviceClasses.clear();
+ findAllClasses(tree->root());
+ findAllNamespaces(tree->root());
+
+ PageGenerator::generateTree(tree, marker);
+
+ if (generateIndex)
+ tre->generateIndex(outputDir() + "/" + project.toLower() + ".index",
+ projectUrl, projectDescription, false);
+}
+
+void WebXMLGenerator::startText(const Node *relative, CodeMarker *marker)
+{
+ inLink = false;
+ inContents = false;
+ inSectionHeading = false;
+ numTableRows = 0;
+ sectionNumber.clear();
+ PageGenerator::startText(relative, marker);
+}
+
+int WebXMLGenerator::generateAtom(QXmlStreamWriter &writer, const Atom *atom,
+ const Node *relative, CodeMarker *marker)
+{
+ Q_UNUSED(writer);
+
+ int skipAhead = 0;
+
+ switch (atom->type()) {
+ default:
+ PageGenerator::generateAtom(atom, relative, marker);
+ }
+ return skipAhead;
+}
+
+void WebXMLGenerator::generateClassLikeNode(const InnerNode *inner,
+ CodeMarker *marker)
+{
+ QByteArray data;
+ QXmlStreamWriter writer(&data);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument();
+ writer.writeStartElement("WebXML");
+ writer.writeStartElement("document");
+
+ generateIndexSections(writer, inner, marker);
+
+ writer.writeEndElement(); // document
+ writer.writeEndElement(); // WebXML
+ writer.writeEndDocument();
+
+ out() << data;
+ out().flush();
+}
+
+void WebXMLGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
+{
+ QByteArray data;
+ QXmlStreamWriter writer(&data);
+ writer.setAutoFormatting(true);
+ writer.writeStartDocument();
+ writer.writeStartElement("WebXML");
+ writer.writeStartElement("document");
+
+ generateIndexSections(writer, fake, marker);
+
+ writer.writeEndElement(); // document
+ writer.writeEndElement(); // WebXML
+ writer.writeEndDocument();
+
+ out() << data;
+ out().flush();
+}
+
+void WebXMLGenerator::generateIndexSections(QXmlStreamWriter &writer,
+ const Node *node, CodeMarker *marker)
+{
+ if (tre->generateIndexSection(writer, node, true)) {
+
+ // Add documentation to this node if it exists.
+ writer.writeStartElement("description");
+ writer.writeAttribute("path", node->doc().location().filePath());
+ writer.writeAttribute("line", QString::number(node->doc().location().lineNo()));
+ writer.writeAttribute("column", QString::number(node->doc().location().columnNo()));
+
+ if (node->type() == Node::Fake) {
+
+ const FakeNode *fake = static_cast<const FakeNode *>(node);
+
+ generateRelations(writer, node, marker);
+
+ if (fake->subType() == FakeNode::Module) {
+ writer.writeStartElement("generatedlist");
+ writer.writeAttribute("contents", "classesbymodule");
+
+ if (moduleNamespaceMap.contains(fake->name())) {
+ writer.writeStartElement("section");
+ writer.writeStartElement("heading");
+ writer.writeAttribute("level", "1");
+ writer.writeCharacters("Namespaces");
+ writer.writeEndElement(); // heading
+ generateAnnotatedList(writer, fake, marker, moduleNamespaceMap[fake->name()]);
+ writer.writeEndElement(); // section
+ }
+ if (moduleClassMap.contains(fake->name())) {
+ writer.writeStartElement("section");
+ writer.writeStartElement("heading");
+ writer.writeAttribute("level", "1");
+ writer.writeCharacters("Classes");
+ writer.writeEndElement(); // heading
+ generateAnnotatedList(writer, fake, marker, moduleClassMap[fake->name()]);
+ writer.writeEndElement(); // section
+ }
+
+ writer.writeEndElement(); // generatedlist
+ }
+ }
+
+ startText(node, marker);
+
+ const Atom *atom = node->doc().body().firstAtom();
+ while (atom)
+ atom = addAtomElements(writer, atom, node, marker);
+
+ QList<Text> alsoList = node->doc().alsoList();
+ supplementAlsoList(node, alsoList);
+
+ if (!alsoList.isEmpty()) {
+ writer.writeStartElement("see-also");
+ for (int i = 0; i < alsoList.size(); ++i) {
+ const Atom *atom = alsoList.at(i).firstAtom();
+ while (atom)
+ atom = addAtomElements(writer, atom, node, marker);
+ }
+ writer.writeEndElement(); // see-also
+ }
+
+ writer.writeEndElement(); // description
+
+ if (node->isInnerNode()) {
+ const InnerNode *inner = static_cast<const InnerNode *>(node);
+
+ // Recurse to generate an element for this child node and all its children.
+ foreach (const Node *child, inner->childNodes())
+ generateIndexSections(writer, child, marker);
+
+ writer.writeStartElement("related");
+ if (inner->relatedNodes().size() > 0) {
+ foreach (const Node *child, inner->relatedNodes())
+ generateIndexSections(writer, child, marker);
+ }
+ writer.writeEndElement(); // related
+ }
+ writer.writeEndElement();
+ }
+}
+
+void WebXMLGenerator::generateInnerNode(const InnerNode *node, CodeMarker *marker)
+{
+ if (!node->url().isNull())
+ return;
+
+ if (node->type() == Node::Fake) {
+ const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
+ if (fakeNode->subType() == FakeNode::ExternalPage)
+ return;
+ }
+
+ if ( node->parent() != 0 ) {
+ beginSubPage( node->location(), fileName(node) );
+ if ( node->type() == Node::Namespace || node->type() == Node::Class) {
+ generateClassLikeNode(node, marker);
+ } else if ( node->type() == Node::Fake ) {
+ generateFakeNode(static_cast<const FakeNode *>(node), marker);
+ }
+ endSubPage();
+ }
+
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while ( c != node->childNodes().end() ) {
+ if ((*c)->isInnerNode() && (
+ (*c)->access() != Node::Private || (*c)->status() == Node::Internal))
+ generateInnerNode( (const InnerNode *) *c, marker );
+ ++c;
+ }
+}
+
+const Atom *WebXMLGenerator::addAtomElements(QXmlStreamWriter &writer,
+ const Atom *atom, const Node *relative, CodeMarker *marker)
+{
+ switch (atom->type()) {
+ case Atom::AbstractLeft:
+ case Atom::AbstractRight:
+ break;
+ case Atom::AutoLink:
+ if (!inLink && !inSectionHeading) {
+ const Node *node = findNode(atom, relative, marker);
+ if (node) {
+ startLink(writer, atom, node, relative);
+ if (inLink) {
+ writer.writeCharacters(atom->string());
+ writer.writeEndElement(); // link
+ inLink = false;
+ }
+ } else
+ writer.writeCharacters(atom->string());
+ } else
+ writer.writeCharacters(atom->string());
+ break;
+ case Atom::BaseName:
+ break;
+ case Atom::BriefLeft:
+
+ writer.writeStartElement("brief");
+ switch (relative->type()) {
+ case Node::Property:
+ writer.writeCharacters("This property");
+ break;
+ case Node::Variable:
+ writer.writeCharacters("This variable");
+ break;
+ default:
+ break;
+ }
+ if (relative->type() == Node::Property || relative->type() == Node::Variable) {
+ QString str;
+ const Atom *a = atom->next();
+ while (a != 0 && a->type() != Atom::BriefRight) {
+ if (a->type() == Atom::String || a->type() == Atom::AutoLink)
+ str += a->string();
+ a = a->next();
+ }
+ str[0] = str[0].toLower();
+ if (str.right(1) == ".")
+ str.chop(1);
+
+ QStringList words = str.split(" ");
+ if (!(words.first() == "contains" || words.first() == "specifies"
+ || words.first() == "describes" || words.first() == "defines"
+ || words.first() == "holds" || words.first() == "determines"))
+ writer.writeCharacters(" holds ");
+ else
+ writer.writeCharacters(" ");
+ }
+ break;
+
+ case Atom::BriefRight:
+ if (relative->type() == Node::Property || relative->type() == Node::Variable)
+ writer.writeCharacters(".");
+
+ writer.writeEndElement(); // brief
+ break;
+
+ case Atom::C:
+ writer.writeStartElement("teletype");
+ if (inLink)
+ writer.writeAttribute("type", "normal");
+ else
+ writer.writeAttribute("type", "highlighted");
+
+ writer.writeCharacters(plainCode(atom->string()));
+ writer.writeEndElement(); // teletype
+ break;
+
+ case Atom::Code:
+ writer.writeTextElement("code", trimmedTrailing(plainCode(atom->string())));
+ break;
+
+#ifdef QDOC_QML
+ case Atom::Qml:
+ writer.writeTextElement("qml", trimmedTrailing(plainCode(atom->string())));
+#endif
+
+ case Atom::CodeBad:
+ writer.writeTextElement("badcode", trimmedTrailing(plainCode(atom->string())));
+ break;
+
+ case Atom::CodeNew:
+ writer.writeTextElement("para", "you can rewrite it as");
+ writer.writeTextElement("newcode", trimmedTrailing(plainCode(atom->string())));
+ break;
+
+ case Atom::CodeOld:
+ writer.writeTextElement("para", "For example, if you have code like");
+ writer.writeTextElement("oldcode", trimmedTrailing(plainCode(atom->string())));
+ break;
+
+ case Atom::CodeQuoteArgument:
+ if (quoteCommand == "dots") {
+ writer.writeAttribute("indent", atom->string());
+ writer.writeCharacters("...");
+ } else
+ writer.writeCharacters(atom->string());
+ writer.writeEndElement(); // code
+ break;
+
+ case Atom::CodeQuoteCommand:
+ quoteCommand = atom->string();
+ writer.writeStartElement(quoteCommand);
+ break;
+
+ case Atom::FootnoteLeft:
+ writer.writeStartElement("footnote");
+ break;
+
+ case Atom::FootnoteRight:
+ writer.writeEndElement(); // footnote
+ break;
+/*
+ case Atom::FormatElse:
+ writer.writeStartElement("else");
+ writer.writeEndElement(); // else
+ break;
+*/
+ case Atom::FormatEndif:
+ writer.writeEndElement(); // raw
+ break;
+ case Atom::FormatIf:
+ writer.writeStartElement("raw");
+ writer.writeAttribute("format", atom->string());
+ break;
+ case Atom::FormattingLeft:
+ {
+ if (atom->string() == ATOM_FORMATTING_BOLD)
+ writer.writeStartElement("bold");
+ else if (atom->string() == ATOM_FORMATTING_ITALIC)
+ writer.writeStartElement("italic");
+ else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
+ writer.writeStartElement("underline");
+ else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
+ writer.writeStartElement("subscript");
+ else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
+ writer.writeStartElement("superscript");
+ else if (atom->string() == ATOM_FORMATTING_TELETYPE)
+ writer.writeStartElement("teletype");
+ else if (atom->string() == ATOM_FORMATTING_PARAMETER)
+ writer.writeStartElement("argument");
+ else if (atom->string() == ATOM_FORMATTING_INDEX)
+ writer.writeStartElement("index");
+ }
+ break;
+/* out() << formattingLeftMap()[atom->string()];
+ if ( atom->string() == ATOM_FORMATTING_PARAMETER ) {
+ if ( atom->next() != 0 && atom->next()->type() == Atom::String ) {
+ QRegExp subscriptRegExp( "([a-z]+)_([0-9n])" );
+ if ( subscriptRegExp.exactMatch(atom->next()->string()) ) {
+ out() << subscriptRegExp.cap( 1 ) << "<sub>"
+ << subscriptRegExp.cap( 2 ) << "</sub>";
+ skipAhead = 1;
+ }
+ }
+ }*/
+ case Atom::FormattingRight:
+ {
+ if (atom->string() == ATOM_FORMATTING_BOLD)
+ writer.writeEndElement();
+ else if (atom->string() == ATOM_FORMATTING_ITALIC)
+ writer.writeEndElement();
+ else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
+ writer.writeEndElement();
+ else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
+ writer.writeEndElement();
+ else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
+ writer.writeEndElement();
+ else if (atom->string() == ATOM_FORMATTING_TELETYPE)
+ writer.writeEndElement();
+ else if (atom->string() == ATOM_FORMATTING_PARAMETER)
+ writer.writeEndElement();
+ else if (atom->string() == ATOM_FORMATTING_INDEX)
+ writer.writeEndElement();
+ }
+ if (inLink) {
+ writer.writeEndElement(); // link
+ inLink = false;
+ }
+ break;
+/* if ( atom->string() == ATOM_FORMATTING_LINK ) {
+ if (inLink) {
+ if ( link.isEmpty() ) {
+ if (showBrokenLinks)
+ out() << "</i>";
+ } else {
+ out() << "</a>";
+ }
+ }
+ inLink = false;
+ } else {
+ out() << formattingRightMap()[atom->string()];
+ }*/
+ case Atom::GeneratedList:
+ writer.writeStartElement("generatedlist");
+ writer.writeAttribute("contents", atom->string());
+ writer.writeEndElement(); // generatedlist
+/*
+ if (atom->string() == "annotatedclasses") {
+ generateAnnotatedList(relative, marker, nonCompatClasses);
+ } else if (atom->string() == "classes") {
+ generateCompactList(relative, marker, nonCompatClasses);
+ } else if (atom->string().contains("classesbymodule")) {
+ QString arg = atom->string().trimmed();
+ QString moduleName = atom->string().mid(atom->string().indexOf(
+ "classesbymodule") + 15).trimmed();
+ if (moduleClassMap.contains(moduleName))
+ generateAnnotatedList(relative, marker, moduleClassMap[moduleName]);
+ } else if (atom->string().contains("classesbyedition")) {
+ QString arg = atom->string().trimmed();
+ QString editionName = atom->string().mid(atom->string().indexOf(
+ "classesbyedition") + 16).trimmed();
+ if (editionModuleMap.contains(editionName)) {
+ QMap<QString, const Node *> editionClasses;
+ foreach (const QString &moduleName, editionModuleMap[editionName]) {
+ if (moduleClassMap.contains(moduleName))
+ editionClasses.unite(moduleClassMap[moduleName]);
+ }
+ generateAnnotatedList(relative, marker, editionClasses);
+ }
+ } else if (atom->string() == "classhierarchy") {
+ generateClassHierarchy(relative, marker, nonCompatClasses);
+ } else if (atom->string() == "compatclasses") {
+ generateCompactList(relative, marker, compatClasses);
+ } else if (atom->string() == "functionindex") {
+ generateFunctionIndex(relative, marker);
+ } else if (atom->string() == "legalese") {
+ generateLegaleseList(relative, marker);
+ } else if (atom->string() == "mainclasses") {
+ generateCompactList(relative, marker, mainClasses);
+ } else if (atom->string() == "services") {
+ generateCompactList(relative, marker, serviceClasses);
+ } else if (atom->string() == "overviews") {
+ generateOverviewList(relative, marker);
+ } else if (atom->string() == "namespaces") {
+ generateAnnotatedList(relative, marker, namespaceIndex);
+ } else if (atom->string() == "related") {
+ const FakeNode *fake = static_cast<const FakeNode *>(relative);
+ if (fake && !fake->groupMembers().isEmpty()) {
+ QMap<QString, const Node *> groupMembersMap;
+ foreach (Node *node, fake->groupMembers()) {
+ if (node->type() == Node::Fake)
+ groupMembersMap[fullName(node, relative, marker)] = node;
+ }
+ generateAnnotatedList(fake, marker, groupMembersMap);
+ }
+ } else if (atom->string() == "relatedinline") {
+ const FakeNode *fake = static_cast<const FakeNode *>(relative);
+ if (fake && !fake->groupMembers().isEmpty()) {
+ // Reverse the list into the original scan order.
+ // Should be sorted. But on what? It may not be a
+ // regular class or page definition.
+ QList<const Node *> list;
+ foreach (const Node *node, fake->groupMembers())
+ list.prepend(node);
+ foreach (const Node *node, list)
+ generateBody(node, marker );
+ }
+ }
+ break;
+*/
+ break;
+ case Atom::Image:
+ writer.writeStartElement("image");
+ writer.writeAttribute("href", imageFileName(relative, atom->string()));
+ writer.writeEndElement(); // image
+ break;
+
+ case Atom::InlineImage:
+ writer.writeStartElement("inlineimage");
+ writer.writeAttribute("href", imageFileName(relative, atom->string()));
+ writer.writeEndElement(); // inlineimage
+ break;
+
+ case Atom::ImageText:
+ break;
+
+ case Atom::LegaleseLeft:
+ writer.writeStartElement("legalese");
+ break;
+
+ case Atom::LegaleseRight:
+ writer.writeEndElement(); // legalese
+ break;
+
+ case Atom::Link:
+ case Atom::LinkNode:
+ if (!inLink) {
+ const Node *node = findNode(atom, relative, marker);
+ if (node)
+ startLink(writer, atom, node, relative);
+ }
+ break;
+
+ case Atom::ListLeft:
+ writer.writeStartElement("list");
+
+ if (atom->string() == ATOM_LIST_BULLET)
+ writer.writeAttribute("type", "bullet");
+ else if (atom->string() == ATOM_LIST_TAG)
+ writer.writeAttribute("type", "definition");
+ else if (atom->string() == ATOM_LIST_VALUE)
+ writer.writeAttribute("type", "enum");
+ else {
+ writer.writeAttribute("type", "ordered");
+ if (atom->string() == ATOM_LIST_UPPERALPHA)
+ writer.writeAttribute("start", "A");
+ else if (atom->string() == ATOM_LIST_LOWERALPHA)
+ writer.writeAttribute("start", "a");
+ else if (atom->string() == ATOM_LIST_UPPERROMAN)
+ writer.writeAttribute("start", "I");
+ else if (atom->string() == ATOM_LIST_LOWERROMAN)
+ writer.writeAttribute("start", "i");
+ else // (atom->string() == ATOM_LIST_NUMERIC)
+ writer.writeAttribute("start", "1");
+ }
+ break;
+
+ case Atom::ListItemNumber:
+ break;
+
+ case Atom::ListTagLeft:
+ {
+ writer.writeStartElement("definition");
+
+ writer.writeTextElement("term", plainCode(
+ marker->markedUpEnumValue(atom->next()->string(), relative)));
+ }
+ break;
+
+ case Atom::ListTagRight:
+ writer.writeEndElement(); // definition
+ break;
+
+ case Atom::ListItemLeft:
+ writer.writeStartElement("item");
+ break;
+
+ case Atom::ListItemRight:
+ writer.writeEndElement(); // item
+ break;
+
+ case Atom::ListRight:
+ writer.writeEndElement(); // list
+ break;
+
+ case Atom::Nop:
+ break;
+
+ case Atom::ParaLeft:
+ writer.writeStartElement("para");
+ break;
+
+ case Atom::ParaRight:
+ writer.writeEndElement(); // para
+ break;
+
+ case Atom::QuotationLeft:
+ writer.writeStartElement("quote");
+ break;
+
+ case Atom::QuotationRight:
+ writer.writeEndElement(); // quote
+ break;
+
+ case Atom::RawString:
+ writer.writeCharacters(atom->string());
+ break;
+
+ case Atom::SectionLeft:
+ writer.writeStartElement("section");
+ writer.writeAttribute("id", Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
+ break;
+
+ case Atom::SectionRight:
+ writer.writeEndElement(); // section
+ break;
+
+ case Atom::SectionHeadingLeft:
+ writer.writeStartElement("heading");
+ writer.writeAttribute("level", atom->string()); // + hOffset(relative)
+ inSectionHeading = true;
+ break;
+
+ case Atom::SectionHeadingRight:
+ writer.writeEndElement(); // heading
+ inSectionHeading = false;
+ break;
+
+ case Atom::SidebarLeft:
+ case Atom::SidebarRight:
+ break;
+
+ case Atom::SnippetCommand:
+ writer.writeStartElement(atom->string());
+ break;
+
+ case Atom::SnippetIdentifier:
+ writer.writeAttribute("identifier", atom->string());
+ writer.writeEndElement(); // snippet
+ break;
+
+ case Atom::SnippetLocation:
+ writer.writeAttribute("location", atom->string());
+ break;
+
+ case Atom::String:
+ writer.writeCharacters(atom->string());
+ break;
+
+ case Atom::TableLeft:
+ writer.writeStartElement("table");
+ if (atom->string().contains("%"))
+ writer.writeAttribute("width", atom->string());
+ break;
+
+ case Atom::TableRight:
+ writer.writeEndElement(); // table
+ break;
+
+ case Atom::TableHeaderLeft:
+ writer.writeStartElement("header");
+ break;
+
+ case Atom::TableHeaderRight:
+ writer.writeEndElement(); // header
+ break;
+
+ case Atom::TableRowLeft:
+ writer.writeStartElement("row");
+ break;
+
+ case Atom::TableRowRight:
+ writer.writeEndElement(); // row
+ break;
+
+ case Atom::TableItemLeft:
+ {
+ writer.writeStartElement("item");
+ QStringList spans = atom->string().split(",");
+ if (spans.size() == 2) {
+ if (spans.at(0) != "1")
+ writer.writeAttribute("colspan", spans.at(0).trimmed());
+ if (spans.at(1) != "1")
+ writer.writeAttribute("rowspan", spans.at(1).trimmed());
+ }
+ }
+ break;
+
+ case Atom::TableItemRight:
+ writer.writeEndElement(); // item
+ break;
+
+ case Atom::TableOfContents:
+ writer.writeStartElement("tableofcontents");
+ writer.writeAttribute("details", atom->string());
+ {
+ int numColumns = 1;
+ const Node *node = relative;
+
+ Doc::SectioningUnit sectioningUnit = Doc::Section4;
+ QStringList params = atom->string().split(",");
+ QString columnText = params.at(0);
+ QStringList pieces = columnText.split(" ", QString::SkipEmptyParts);
+ if (pieces.size() >= 2) {
+ columnText = pieces.at(0);
+ pieces.pop_front();
+ QString path = pieces.join(" ").trimmed();
+ node = findNode(path, relative, marker);
+ if (node)
+ writer.writeAttribute("href", fileName(node));
+ }
+
+ if (params.size() == 2) {
+ numColumns = qMax(columnText.toInt(), numColumns);
+ sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt();
+ writer.writeAttribute("columns", QString::number(numColumns));
+ writer.writeAttribute("unit", QString::number(sectioningUnit));
+ }
+
+ if (node)
+ generateTableOfContents(writer, node, sectioningUnit, numColumns,
+ relative);
+ }
+ writer.writeEndElement(); // tableofcontents
+ break;
+
+ case Atom::Target:
+ writer.writeStartElement("target");
+ writer.writeAttribute("name", Doc::canonicalTitle(atom->string()));
+ writer.writeEndElement(); // target
+ break;
+
+ case Atom::UnhandledFormat:
+ case Atom::UnknownCommand:
+ writer.writeCharacters(atom->typeString());
+ break;
+ default:
+ break;
+ }
+
+ if (atom)
+ return atom->next();
+
+ return 0;
+}
+/*
+ QDomElement atomElement = document.createElement(atom->typeString().toLower());
+ QDomText atomValue = document.createTextNode(atom->string());
+ atomElement.appendChild(atomValue);
+ descriptionElement.appendChild(atomElement);
+*/
+
+/*
+ ### Warning: findNode() is a modified version of HtmlGenerator::getLink().
+*/
+const Node *WebXMLGenerator::findNode(const Atom *atom, const Node *relative, CodeMarker *marker)
+{
+ return findNode(atom->string(), relative, marker);
+}
+
+const Node *WebXMLGenerator::findNode(const QString &title, const Node *relative, CodeMarker *marker)
+{
+ QString link;
+ if (title.contains(":") &&
+ (title.startsWith("file:")
+ || title.startsWith("http:")
+ || title.startsWith("https:")
+ || title.startsWith("ftp:")
+ || title.startsWith("mailto:"))) {
+
+ return 0;
+ } else if (title.count('@') == 1) {
+ return 0;
+ } else {
+ QStringList path;
+ if (title.contains('#')) {
+ path = title.split('#');
+ } else {
+ path.append(title);
+ }
+
+ const Node *node = 0;
+ Atom *targetAtom = 0;
+
+ QString first = path.first().trimmed();
+ if (first.isEmpty()) {
+ node = relative;
+ } else if (first.endsWith(".html")) {
+ node = tre->root()->findNode(first, Node::Fake);
+ } else {
+ node = marker->resolveTarget(first, tre, relative);
+ if (!node)
+ node = tre->findFakeNodeByTitle(first);
+ if (!node)
+ node = tre->findUnambiguousTarget(first, targetAtom);
+ }
+
+ if (node) {
+ if (!node->url().isEmpty())
+ return node;
+ else
+ path.removeFirst();
+ } else {
+ return 0;
+ }
+
+ while (!path.isEmpty()) {
+ targetAtom = tre->findTarget(path.first(), node);
+ if (targetAtom == 0)
+ break;
+ path.removeFirst();
+ }
+/* We would ideally treat targets as nodes to be consistent.
+ if (targetAtom && node && node->isInnerNode()) {
+ Node *parentNode = const_cast<Node *>(node);
+ node = new TargetNode(static_cast<InnerNode*>(parentNode), first);
+ }
+*/
+ return node;
+ }
+ return 0;
+}
+
+void WebXMLGenerator::startLink(QXmlStreamWriter &writer, const Atom *atom,
+ const Node *node, const Node *relative)
+{
+ QString location = tre->fullDocumentLocation(node);
+ if (!location.isEmpty()) {
+ writer.writeStartElement("link");
+ writer.writeAttribute("raw", atom->string());
+ if (atom->string().contains("#") || node == relative) {
+ QString target = atom->string().split("#").last();
+ Atom *targetAtom = tre->findTarget(target, node);
+ if (targetAtom)
+ location += "#" + Doc::canonicalTitle(target);
+ }
+ writer.writeAttribute("href", location);
+ QString type = targetType(node);
+ writer.writeAttribute("type", type);
+ switch (node->type()) {
+ case Node::Enum:
+ writer.writeAttribute("enum", tre->fullDocumentName(node));
+ break;
+ case Node::Fake:
+ writer.writeAttribute("page", tre->fullDocumentName(node));
+ break;
+ case Node::Property:
+ {
+ const PropertyNode *propertyNode = static_cast<const PropertyNode *>(node);
+ if (propertyNode->getters().size() > 0)
+ writer.writeAttribute("getter", tre->fullDocumentName(propertyNode->getters()[0]));
+ }
+ default:
+ ;
+ }
+ inLink = true;
+ }
+}
+
+QString WebXMLGenerator::targetType(const Node *node)
+{
+ switch (node->type()) {
+ case Node::Namespace:
+ return "namespace";
+ break;
+ case Node::Class:
+ return "class";
+ break;
+ case Node::Fake:
+ return "page";
+ break;
+ case Node::Enum:
+ return "enum";
+ break;
+ case Node::Typedef:
+ return "typedef";
+ break;
+ case Node::Property:
+ return "property";
+ break;
+ case Node::Function:
+ return "function";
+ break;
+ case Node::Variable:
+ return "variable";
+ break;
+ case Node::Target:
+ return "target";
+ break;
+ default:
+ return "";
+ }
+ return "";
+}
+
+void WebXMLGenerator::generateRelations(QXmlStreamWriter &writer, const Node *node, CodeMarker *marker)
+{
+ if (node && !node->links().empty()) {
+ QPair<QString,QString> linkPair;
+ QPair<QString,QString> anchorPair;
+ const Node *linkNode;
+
+ foreach (Node::LinkType relation, node->links().keys()) {
+
+ linkPair = node->links()[relation];
+ linkNode = findNode(linkPair.first, node, marker);
+
+ if (!linkNode)
+ linkNode = node;
+
+ if (linkNode == node)
+ anchorPair = linkPair;
+ else
+ anchorPair = anchorForNode(linkNode);
+
+ writer.writeStartElement("relation");
+ writer.writeAttribute("href", anchorPair.first);
+ writer.writeAttribute("type", targetType(linkNode));
+
+ switch (relation) {
+ case Node::StartLink:
+ writer.writeAttribute("meta", "start");
+ break;
+ case Node::NextLink:
+ writer.writeAttribute("meta", "next");
+ break;
+ case Node::PreviousLink:
+ writer.writeAttribute("meta", "previous");
+ break;
+ case Node::ContentsLink:
+ writer.writeAttribute("meta", "contents");
+ break;
+ case Node::IndexLink:
+ writer.writeAttribute("meta", "index");
+ break;
+ default:
+ writer.writeAttribute("meta", "");
+ }
+ writer.writeAttribute("description", anchorPair.second);
+ writer.writeEndElement(); // link
+ }
+ }
+}
+
+// Classes adapted from HtmlGenerator.
+
+void WebXMLGenerator::generateTableOfContents(QXmlStreamWriter &writer, const Node *node,
+ Doc::SectioningUnit sectioningUnit,
+ int numColumns, const Node *relative)
+
+{
+ if (!node->doc().hasTableOfContents())
+ return;
+ QList<Atom *> toc = node->doc().tableOfContents();
+ if (toc.isEmpty())
+ return;
+
+ QString nodeName = "";
+ if (node != relative)
+ nodeName = node->name();
+
+ QStringList sectionNumber;
+ int columnSize = 0;
+
+ if (numColumns > 1) {
+ writer.writeStartElement("table");
+ writer.writeAttribute("width", "100%");
+ writer.writeStartElement("row");
+ writer.writeStartElement("item");
+ writer.writeAttribute("width", QString::number((100 + numColumns - 1) / numColumns) + "%");
+ }
+
+ // disable nested links in table of contents
+ inContents = true;
+ inLink = true;
+
+ for (int i = 0; i < toc.size(); ++i) {
+ Atom *atom = toc.at(i);
+
+ int nextLevel = atom->string().toInt();
+ if (nextLevel > (int)sectioningUnit)
+ continue;
+
+ if (sectionNumber.size() < nextLevel) {
+ do {
+ writer.writeStartElement("list");
+ sectionNumber.append("1");
+ } while (sectionNumber.size() < nextLevel);
+ } else {
+ while (sectionNumber.size() > nextLevel) {
+ writer.writeEndElement();
+ sectionNumber.removeLast();
+ }
+ sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
+ }
+ Text headingText = Text::sectionHeading(atom);
+
+ if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) {
+ writer.writeEndElement(); // list
+ writer.writeEndElement(); // item
+ writer.writeStartElement("item");
+ writer.writeAttribute("width", QString::number((100 + numColumns - 1) / numColumns) + "%");
+ writer.writeStartElement("list");
+ columnSize = 0;
+ }
+
+ writer.writeStartElement("item");
+ writer.writeStartElement("para");
+ writer.writeStartElement("link");
+ writer.writeAttribute("href", nodeName + "#" + Doc::canonicalTitle(headingText.toString()));
+ writer.writeAttribute("type", "page");
+ writer.writeCharacters(headingText.toString());
+ writer.writeEndElement(); // link
+ writer.writeEndElement(); // para
+ writer.writeEndElement(); // item
+
+ ++columnSize;
+ }
+ while (!sectionNumber.isEmpty()) {
+ writer.writeEndElement(); // list
+ sectionNumber.removeLast();
+ }
+
+ if (numColumns > 1) {
+ writer.writeEndElement(); // item
+ writer.writeEndElement(); // row
+ writer.writeEndElement(); // table
+ }
+
+ inContents = false;
+ inLink = false;
+}
+
+void WebXMLGenerator::generateAnnotatedList(QXmlStreamWriter &writer,
+ const Node *relative, CodeMarker *marker, const QMap<QString, const Node *> &nodeMap)
+{
+ writer.writeStartElement("table");
+ writer.writeAttribute("width", "100%");
+
+ foreach (QString name, nodeMap.keys()) {
+ const Node *node = nodeMap[name];
+
+ writer.writeStartElement("row");
+ writer.writeStartElement("heading");
+ generateFullName(writer, node, relative, marker);
+ writer.writeEndElement(); // heading
+
+ writer.writeStartElement("item");
+ writer.writeCharacters(node->doc().briefText().toString());
+ writer.writeEndElement(); // item
+ writer.writeEndElement(); // row
+ }
+ writer.writeEndElement(); // table
+}
+
+void WebXMLGenerator::generateFullName(QXmlStreamWriter &writer,
+ const Node *apparentNode, const Node *relative, CodeMarker *marker,
+ const Node *actualNode)
+{
+ if ( actualNode == 0 )
+ actualNode = apparentNode;
+ writer.writeStartElement("link");
+ writer.writeAttribute("href", tre->fullDocumentLocation(actualNode));
+ writer.writeAttribute("type", targetType(actualNode));
+ writer.writeCharacters(fullName(apparentNode, relative, marker));
+ writer.writeEndElement(); // link
+}
+
+// Classes copied (and slightly adapted) from the HtmlGenerator. These need
+// refactoring into a common ancestor class.
+
+void WebXMLGenerator::findAllClasses(const InnerNode *node)
+{
+ NodeList::const_iterator c = node->childNodes().constBegin();
+ while (c != node->childNodes().constEnd()) {
+ if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) {
+ if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) {
+ QString className = (*c)->name();
+ if ((*c)->parent() && (*c)->parent()->type() == Node::Namespace &&
+ !(*c)->parent()->name().isEmpty())
+ className = (*c)->parent()->name()+"::"+className;
+
+ QString moduleName = (*c)->moduleName();
+ if (!moduleName.isEmpty())
+ moduleClassMap[moduleName].insert((*c)->name(), *c);
+
+ QString serviceName =
+ (static_cast<const ClassNode *>(*c))->serviceName();
+ if (!serviceName.isEmpty())
+ serviceClasses.insert(serviceName, *c);
+ } else if ((*c)->isInnerNode()) {
+ findAllClasses(static_cast<InnerNode *>(*c));
+ }
+ }
+ ++c;
+ }
+}
+
+void WebXMLGenerator::findAllNamespaces(const InnerNode *node)
+{
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while (c != node->childNodes().end()) {
+ if ((*c)->access() != Node::Private) {
+ if ((*c)->isInnerNode() && (*c)->url().isEmpty()) {
+ findAllNamespaces(static_cast<const InnerNode *>(*c));
+ if ((*c)->type() == Node::Namespace) {
+ const NamespaceNode *nspace = static_cast<const NamespaceNode *>(*c);
+ // Ensure that the namespace's name is not empty (the root
+ // namespace has no name).
+ if (!nspace->name().isEmpty()) {
+ namespaceIndex.insert(nspace->name(), *c);
+ QString moduleName = (*c)->moduleName();
+ if (!moduleName.isEmpty())
+ moduleNamespaceMap[moduleName].insert((*c)->name(), *c);
+ }
+ }
+ }
+ }
+ ++c;
+ }
+}
+
+const QPair<QString,QString> WebXMLGenerator::anchorForNode(const Node *node)
+{
+ QPair<QString,QString> anchorPair;
+
+ anchorPair.first = PageGenerator::fileName(node);
+ if (node->type() == Node::Fake) {
+ const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
+ anchorPair.second = fakeNode->title();
+ }
+
+ return anchorPair;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qdoc3/webxmlgenerator.h b/tools/qdoc3/webxmlgenerator.h
new file mode 100644
index 0000000000..f7b4445376
--- /dev/null
+++ b/tools/qdoc3/webxmlgenerator.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ WebXMLGenerator.h
+*/
+
+#ifndef WEBXMLGENERATOR_H
+#define WEBXMLGENERATOR_H
+
+#include "codemarker.h"
+#include "config.h"
+#include "pagegenerator.h"
+
+QT_BEGIN_NAMESPACE
+
+class WebXMLGenerator : public PageGenerator
+{
+public:
+ WebXMLGenerator();
+ ~WebXMLGenerator();
+
+ virtual void initializeGenerator(const Config &config);
+ virtual void terminateGenerator();
+ virtual QString format();
+ virtual void generateTree(const Tree *tree, CodeMarker *marker);
+
+protected:
+ virtual void startText( const Node *relative, CodeMarker *marker );
+ virtual int generateAtom(QXmlStreamWriter &writer, const Atom *atom,
+ const Node *relative, CodeMarker *marker );
+ virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
+ virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker);
+ virtual QString fileExtension(const Node *node);
+
+ virtual const Atom *addAtomElements(QXmlStreamWriter &writer, const Atom *atom,
+ const Node *relative, CodeMarker *marker);
+ virtual void generateIndexSections(QXmlStreamWriter &writer, const Node *node,
+ CodeMarker *marker);
+ virtual void generateInnerNode( const InnerNode *node, CodeMarker *marker );
+
+private:
+ const QPair<QString,QString> anchorForNode(const Node *node);
+ void findAllClasses(const InnerNode *node);
+ void findAllNamespaces(const InnerNode *node);
+ const Node *findNode(const Atom *atom, const Node *relative, CodeMarker *marker);
+ const Node *findNode(const QString &title, const Node *relative, CodeMarker *marker);
+ void generateAnnotatedList(QXmlStreamWriter &writer, const Node *relative,
+ CodeMarker *marker, const QMap<QString,
+ const Node *> &nodeMap);
+ void generateFullName(QXmlStreamWriter &writer, const Node *apparentNode,
+ const Node *relative, CodeMarker *marker,
+ const Node *actualNode = 0);
+ void generateRelations(QXmlStreamWriter &writer, const Node *node, CodeMarker *marker);
+ void generateTableOfContents(QXmlStreamWriter &writer, const Node *node,
+ Doc::SectioningUnit sectioningUnit,
+ int numColumns, const Node *relative);
+ void startLink(QXmlStreamWriter &writer, const Atom *atom, const Node *node,
+ const Node *relative);
+ QString targetType(const Node *node);
+
+ const Tree *tre;
+ bool generateIndex;
+ bool inLink;
+ bool inContents;
+ bool inSectionHeading;
+ bool inTableHeader;
+ int numTableRows;
+ bool threeColumnEnumValueTable;
+ QMap<QString, QMap<QString, const Node *> > moduleClassMap;
+ QMap<QString, QMap<QString, const Node *> > moduleNamespaceMap;
+ QMap<QString, const Node *> namespaceIndex;
+ QMap<QString, const Node *> serviceClasses;
+ QString link;
+ QString project;
+ QString projectDescription;
+ QString projectUrl;
+ QString quoteCommand;
+ QStringList sectionNumber;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qdoc3/yyindent.cpp b/tools/qdoc3/yyindent.cpp
new file mode 100644
index 0000000000..bbca39b9e0
--- /dev/null
+++ b/tools/qdoc3/yyindent.cpp
@@ -0,0 +1,1190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ This file is a self-contained interactive indenter for C++ and Qt
+ Script.
+
+ The general problem of indenting a C++ program is ill posed. On
+ the one hand, an indenter has to analyze programs written in a
+ free-form formal language that is best described in terms of
+ tokens, not characters, not lines. On the other hand, indentation
+ applies to lines and white space characters matter, and otherwise
+ the programs to indent are formally invalid in general, as they
+ are begin edited.
+
+ The approach taken here works line by line. We receive a program
+ consisting of N lines or more, and we want to compute the
+ indentation appropriate for the Nth line. Lines beyond the Nth
+ lines are of no concern to us, so for simplicity we pretend the
+ program has exactly N lines and we call the Nth line the "bottom
+ line". Typically, we have to indent the bottom line when it's
+ still empty, so we concentrate our analysis on the N - 1 lines
+ that precede.
+
+ By inspecting the (N - 1)-th line, the (N - 2)-th line, ...
+ backwards, we determine the kind of the bottom line and indent it
+ accordingly.
+
+ * The bottom line is a comment line. See
+ bottomLineStartsInCComment() and
+ indentWhenBottomLineStartsInCComment().
+ * The bottom line is a continuation line. See isContinuationLine()
+ and indentForContinuationLine().
+ * The bottom line is a standalone line. See
+ indentForStandaloneLine().
+
+ Certain tokens that influence the indentation, notably braces,
+ are looked for in the lines. This is done by simple string
+ comparison, without a real tokenizer. Confusing constructs such
+ as comments and string literals are removed beforehand.
+*/
+
+#include <qregexp.h>
+#include <qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/* qmake ignore Q_OBJECT */
+
+/*
+ The indenter avoids getting stuck in almost infinite loops by
+ imposing arbitrary limits on the number of lines it analyzes when
+ looking for a construct.
+
+ For example, the indenter never considers more than BigRoof lines
+ backwards when looking for the start of a C-style comment.
+*/
+static const int SmallRoof = 40;
+static const int BigRoof = 400;
+
+/*
+ The indenter supports a few parameters:
+
+ * ppHardwareTabSize is the size of a '\t' in your favorite editor.
+ * ppIndentSize is the size of an indentation, or software tab
+ size.
+ * ppContinuationIndentSize is the extra indent for a continuation
+ line, when there is nothing to align against on the previous
+ line.
+ * ppCommentOffset is the indentation within a C-style comment,
+ when it cannot be picked up.
+*/
+
+static int ppHardwareTabSize = 8;
+static int ppIndentSize = 4;
+static int ppContinuationIndentSize = 8;
+
+static const int ppCommentOffset = 2;
+
+void setTabSize( int size )
+{
+ ppHardwareTabSize = size;
+}
+
+void setIndentSize( int size )
+{
+ ppIndentSize = size;
+ ppContinuationIndentSize = 2 * size;
+}
+
+static QRegExp *literal = 0;
+static QRegExp *label = 0;
+static QRegExp *inlineCComment = 0;
+static QRegExp *braceX = 0;
+static QRegExp *iflikeKeyword = 0;
+
+/*
+ Returns the first non-space character in the string t, or
+ QChar::Null if the string is made only of white space.
+*/
+static QChar firstNonWhiteSpace( const QString& t )
+{
+ int i = 0;
+ while ( i < (int) t.length() ) {
+ if ( !t[i].isSpace() )
+ return t[i];
+ i++;
+ }
+ return QChar::Null;
+}
+
+/*
+ Returns true if string t is made only of white space; otherwise
+ returns false.
+*/
+static bool isOnlyWhiteSpace( const QString& t )
+{
+ return firstNonWhiteSpace( t ).isNull();
+}
+
+/*
+ Assuming string t is a line, returns the column number of a given
+ index. Column numbers and index are identical for strings that don't
+ contain '\t's.
+*/
+int columnForIndex( const QString& t, int index )
+{
+ int col = 0;
+ if ( index > (int) t.length() )
+ index = t.length();
+
+ for ( int i = 0; i < index; i++ ) {
+ if ( t[i] == QChar('\t') ) {
+ col = ( (col / ppHardwareTabSize) + 1 ) * ppHardwareTabSize;
+ } else {
+ col++;
+ }
+ }
+ return col;
+}
+
+/*
+ Returns the indentation size of string t.
+*/
+int indentOfLine( const QString& t )
+{
+ return columnForIndex( t, t.indexOf(firstNonWhiteSpace(t)) );
+}
+
+/*
+ Replaces t[k] by ch, unless t[k] is '\t'. Tab characters are better
+ left alone since they break the "index equals column" rule. No
+ provisions are taken against '\n' or '\r', which shouldn't occur in
+ t anyway.
+*/
+static inline void eraseChar( QString& t, int k, QChar ch )
+{
+ if ( t[k] != '\t' )
+ t[k] = ch;
+}
+
+/*
+ Removes some nefast constructs from a code line and returns the
+ resulting line.
+*/
+static QString trimmedCodeLine( const QString& t )
+{
+ QString trimmed = t;
+ int k;
+
+ /*
+ Replace character and string literals by X's, since they may
+ contain confusing characters (such as '{' and ';'). "Hello!" is
+ replaced by XXXXXXXX. The literals are rigourously of the same
+ length before and after; otherwise, we would break alignment of
+ continuation lines.
+ */
+ k = 0;
+ while ( (k = trimmed.indexOf(*literal, k)) != -1 ) {
+ for ( int i = 0; i < literal->matchedLength(); i++ )
+ eraseChar( trimmed, k + i, 'X' );
+ k += literal->matchedLength();
+ }
+
+ /*
+ Replace inline C-style comments by spaces. Other comments are
+ handled elsewhere.
+ */
+ k = 0;
+ while ( (k = trimmed.indexOf(*inlineCComment, k)) != -1 ) {
+ for ( int i = 0; i < inlineCComment->matchedLength(); i++ )
+ eraseChar( trimmed, k + i, ' ' );
+ k += inlineCComment->matchedLength();
+ }
+
+ /*
+ Replace goto and switch labels by whitespace, but be careful
+ with this case:
+
+ foo1: bar1;
+ bar2;
+ */
+ while ( trimmed.lastIndexOf(':') != -1 && trimmed.indexOf(*label) != -1 ) {
+ QString cap1 = label->cap( 1 );
+ int pos1 = label->pos( 1 );
+ int stop = cap1.length();
+
+ if ( pos1 + stop < (int) trimmed.length() && ppIndentSize < stop )
+ stop = ppIndentSize;
+
+ int i = 0;
+ while ( i < stop ) {
+ eraseChar( trimmed, pos1 + i, ' ' );
+ i++;
+ }
+ while ( i < (int) cap1.length() ) {
+ eraseChar( trimmed, pos1 + i, ';' );
+ i++;
+ }
+ }
+
+ /*
+ Remove C++-style comments.
+ */
+ k = trimmed.indexOf( "//" );
+ if ( k != -1 )
+ trimmed.truncate( k );
+
+ return trimmed;
+}
+
+/*
+ Returns '(' if the last parenthesis is opening, ')' if it is
+ closing, and QChar::Null if there are no parentheses in t.
+*/
+static inline QChar lastParen( const QString& t )
+{
+ int i = t.length();
+ while ( i > 0 ) {
+ i--;
+ if ( t[i] == QChar('(') || t[i] == QChar(')') )
+ return t[i];
+ }
+ return QChar::Null;
+}
+
+/*
+ Returns true if typedIn the same as okayCh or is null; otherwise
+ returns false.
+*/
+static inline bool okay( QChar typedIn, QChar okayCh )
+{
+ return typedIn == QChar::Null || typedIn == okayCh;
+}
+
+/*
+ The "linizer" is a group of functions and variables to iterate
+ through the source code of the program to indent. The program is
+ given as a list of strings, with the bottom line being the line
+ to indent. The actual program might contain extra lines, but
+ those are uninteresting and not passed over to us.
+*/
+
+struct LinizerState
+{
+ QString line;
+ int braceDepth;
+ bool leftBraceFollows;
+
+ QStringList::ConstIterator iter;
+ bool inCComment;
+ bool pendingRightBrace;
+};
+
+static QStringList *yyProgram = 0;
+static LinizerState *yyLinizerState = 0;
+
+// shorthands
+static const QString *yyLine = 0;
+static const int *yyBraceDepth = 0;
+static const bool *yyLeftBraceFollows = 0;
+
+/*
+ Saves and restores the state of the global linizer. This enables
+ backtracking.
+*/
+#define YY_SAVE() \
+ LinizerState savedState = *yyLinizerState
+#define YY_RESTORE() \
+ *yyLinizerState = savedState
+
+/*
+ Advances to the previous line in yyProgram and update yyLine
+ accordingly. yyLine is cleaned from comments and other damageable
+ constructs. Empty lines are skipped.
+*/
+static bool readLine()
+{
+ int k;
+
+ yyLinizerState->leftBraceFollows =
+ ( firstNonWhiteSpace(yyLinizerState->line) == QChar('{') );
+
+ do {
+ if ( yyLinizerState->iter == yyProgram->begin() ) {
+ yyLinizerState->line.clear();
+ return false;
+ }
+
+ --yyLinizerState->iter;
+ yyLinizerState->line = *yyLinizerState->iter;
+
+ yyLinizerState->line = trimmedCodeLine( yyLinizerState->line );
+
+ /*
+ Remove C-style comments that span multiple lines. If the
+ bottom line starts in a C-style comment, we are not aware
+ of that and eventually yyLine will contain a slash-aster.
+
+ Notice that both if's can be executed, since
+ yyLinizerState->inCComment is potentially set to false in
+ the first if. The order of the if's is also important.
+ */
+
+ if ( yyLinizerState->inCComment ) {
+ QString slashAster( "/*" );
+
+ k = yyLinizerState->line.indexOf( slashAster );
+ if ( k == -1 ) {
+ yyLinizerState->line.clear();
+ } else {
+ yyLinizerState->line.truncate( k );
+ yyLinizerState->inCComment = false;
+ }
+ }
+
+ if ( !yyLinizerState->inCComment ) {
+ QString asterSlash( "*/" );
+
+ k = yyLinizerState->line.indexOf( asterSlash );
+ if ( k != -1 ) {
+ for ( int i = 0; i < k + 2; i++ )
+ eraseChar( yyLinizerState->line, i, ' ' );
+ yyLinizerState->inCComment = true;
+ }
+ }
+
+ /*
+ Remove preprocessor directives.
+ */
+ k = 0;
+ while ( k < (int) yyLinizerState->line.length() ) {
+ QChar ch = yyLinizerState->line[k];
+ if ( ch == QChar('#') ) {
+ yyLinizerState->line.clear();
+ } else if ( !ch.isSpace() ) {
+ break;
+ }
+ k++;
+ }
+
+ /*
+ Remove trailing spaces.
+ */
+ k = yyLinizerState->line.length();
+ while ( k > 0 && yyLinizerState->line[k - 1].isSpace() )
+ k--;
+ yyLinizerState->line.truncate( k );
+
+ /*
+ '}' increment the brace depth and '{' decrements it and not
+ the other way around, as we are parsing backwards.
+ */
+ yyLinizerState->braceDepth +=
+ yyLinizerState->line.count( '}' ) -
+ yyLinizerState->line.count( '{' );
+
+ /*
+ We use a dirty trick for
+
+ } else ...
+
+ We don't count the '}' yet, so that it's more or less
+ equivalent to the friendly construct
+
+ }
+ else ...
+ */
+ if ( yyLinizerState->pendingRightBrace )
+ yyLinizerState->braceDepth++;
+ yyLinizerState->pendingRightBrace =
+ ( yyLinizerState->line.indexOf(*braceX) == 0 );
+ if ( yyLinizerState->pendingRightBrace )
+ yyLinizerState->braceDepth--;
+ } while ( yyLinizerState->line.isEmpty() );
+
+ return true;
+}
+
+/*
+ Resets the linizer to its initial state, with yyLine containing the
+ line above the bottom line of the program.
+*/
+static void startLinizer()
+{
+ yyLinizerState->braceDepth = 0;
+ yyLinizerState->inCComment = false;
+ yyLinizerState->pendingRightBrace = false;
+
+ yyLine = &yyLinizerState->line;
+ yyBraceDepth = &yyLinizerState->braceDepth;
+ yyLeftBraceFollows = &yyLinizerState->leftBraceFollows;
+
+ yyLinizerState->iter = yyProgram->end();
+ --yyLinizerState->iter;
+ yyLinizerState->line = *yyLinizerState->iter;
+ readLine();
+}
+
+/*
+ Returns true if the start of the bottom line of yyProgram (and
+ potentially the whole line) is part of a C-style comment;
+ otherwise returns false.
+*/
+static bool bottomLineStartsInCComment()
+{
+ QString slashAster( "/*" );
+ QString asterSlash( "*/" );
+
+ /*
+ We could use the linizer here, but that would slow us down
+ terribly. We are better to trim only the code lines we need.
+ */
+ QStringList::ConstIterator p = yyProgram->end();
+ --p; // skip bottom line
+
+ for ( int i = 0; i < BigRoof; i++ ) {
+ if ( p == yyProgram->begin() )
+ return false;
+ --p;
+
+ if ( (*p).indexOf(slashAster) != -1 || (*p).indexOf(asterSlash) != -1 ) {
+ QString trimmed = trimmedCodeLine( *p );
+
+ if ( trimmed.indexOf(slashAster) != -1 ) {
+ return true;
+ } else if ( trimmed.indexOf(asterSlash) != -1 ) {
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+/*
+ Returns the recommended indent for the bottom line of yyProgram
+ assuming that it starts in a C-style comment, a condition that is
+ tested elsewhere.
+
+ Essentially, we're trying to align against some text on the
+ previous line.
+*/
+static int indentWhenBottomLineStartsInCComment()
+{
+ int k = yyLine->lastIndexOf( "/*" );
+ if ( k == -1 ) {
+ /*
+ We found a normal text line in a comment. Align the
+ bottom line with the text on this line.
+ */
+ return indentOfLine( *yyLine );
+ } else {
+ /*
+ The C-style comment starts on this line. If there is
+ text on the same line, align with it. Otherwise, align
+ with the slash-aster plus a given offset.
+ */
+ int indent = columnForIndex( *yyLine, k );
+ k += 2;
+ while ( k < (int) yyLine->length() ) {
+ if ( !(*yyLine)[k].isSpace() )
+ return columnForIndex( *yyLine, k );
+ k++;
+ }
+ return indent + ppCommentOffset;
+ }
+}
+
+/*
+ A function called match...() modifies the linizer state. If it
+ returns true, yyLine is the top line of the matched construct;
+ otherwise, the linizer is left in an unknown state.
+
+ A function called is...() keeps the linizer state intact.
+*/
+
+/*
+ Returns true if the current line (and upwards) forms a braceless
+ control statement; otherwise returns false.
+
+ The first line of the following example is a "braceless control
+ statement":
+
+ if ( x )
+ y;
+*/
+static bool matchBracelessControlStatement()
+{
+ int delimDepth = 0;
+
+ if ( yyLine->endsWith("else") )
+ return true;
+
+ if ( !yyLine->endsWith(")") )
+ return false;
+
+ for ( int i = 0; i < SmallRoof; i++ ) {
+ int j = yyLine->length();
+ while ( j > 0 ) {
+ j--;
+ QChar ch = (*yyLine)[j];
+
+ switch ( ch.unicode() ) {
+ case ')':
+ delimDepth++;
+ break;
+ case '(':
+ delimDepth--;
+ if ( delimDepth == 0 ) {
+ if ( yyLine->indexOf(*iflikeKeyword) != -1 ) {
+ /*
+ We have
+
+ if ( x )
+ y
+
+ "if ( x )" is not part of the statement
+ "y".
+ */
+ return true;
+ }
+ }
+ if ( delimDepth == -1 ) {
+ /*
+ We have
+
+ if ( (1 +
+ 2)
+
+ and not
+
+ if ( 1 +
+ 2 )
+ */
+ return false;
+ }
+ break;
+ case '{':
+ case '}':
+ case ';':
+ /*
+ We met a statement separator, but not where we
+ expected it. What follows is probably a weird
+ continuation line. Be careful with ';' in for,
+ though.
+ */
+ if ( ch != QChar(';') || delimDepth == 0 )
+ return false;
+ }
+ }
+
+ if ( !readLine() )
+ break;
+ }
+ return false;
+}
+
+/*
+ Returns true if yyLine is an unfinished line; otherwise returns
+ false.
+
+ In many places we'll use the terms "standalone line", "unfinished
+ line" and "continuation line". The meaning of these should be
+ evident from this code example:
+
+ a = b; // standalone line
+ c = d + // unfinished line
+ e + // unfinished continuation line
+ f + // unfinished continuation line
+ g; // continuation line
+*/
+static bool isUnfinishedLine()
+{
+ bool unf = false;
+
+ YY_SAVE();
+
+ if ( yyLine->isEmpty() )
+ return false;
+
+ QChar lastCh = (*yyLine)[(int) yyLine->length() - 1];
+ if ( QString("{};").indexOf(lastCh) == -1 && !yyLine->endsWith("...") ) {
+ /*
+ It doesn't end with ';' or similar. If it's neither
+ "Q_OBJECT" nor "if ( x )", it must be an unfinished line.
+ */
+ unf = ( yyLine->indexOf("Q_OBJECT") == -1 &&
+ !matchBracelessControlStatement() );
+ } else if ( lastCh == QChar(';') ) {
+ if ( lastParen(*yyLine) == QChar('(') ) {
+ /*
+ Exception:
+
+ for ( int i = 1; i < 10;
+ */
+ unf = true;
+ } else if ( readLine() && yyLine->endsWith(";") &&
+ lastParen(*yyLine) == QChar('(') ) {
+ /*
+ Exception:
+
+ for ( int i = 1;
+ i < 10;
+ */
+ unf = true;
+ }
+ }
+
+ YY_RESTORE();
+ return unf;
+}
+
+/*
+ Returns true if yyLine is a continuation line; otherwise returns
+ false.
+*/
+static bool isContinuationLine()
+{
+ bool cont = false;
+
+ YY_SAVE();
+ if ( readLine() )
+ cont = isUnfinishedLine();
+ YY_RESTORE();
+ return cont;
+}
+
+/*
+ Returns the recommended indent for the bottom line of yyProgram,
+ assuming it's a continuation line.
+
+ We're trying to align the continuation line against some parenthesis
+ or other bracked left opened on a previous line, or some interesting
+ operator such as '='.
+*/
+static int indentForContinuationLine()
+{
+ int braceDepth = 0;
+ int delimDepth = 0;
+
+ bool leftBraceFollowed = *yyLeftBraceFollows;
+
+ for ( int i = 0; i < SmallRoof; i++ ) {
+ int hook = -1;
+
+ int j = yyLine->length();
+ while ( j > 0 && hook < 0 ) {
+ j--;
+ QChar ch = (*yyLine)[j];
+
+ switch ( ch.unicode() ) {
+ case ')':
+ case ']':
+ delimDepth++;
+ break;
+ case '}':
+ braceDepth++;
+ break;
+ case '(':
+ case '[':
+ delimDepth--;
+ /*
+ An unclosed delimiter is a good place to align at,
+ at least for some styles (including Trolltech's).
+ */
+ if ( delimDepth == -1 )
+ hook = j;
+ break;
+ case '{':
+ braceDepth--;
+ /*
+ A left brace followed by other stuff on the same
+ line is typically for an enum or an initializer.
+ Such a brace must be treated just like the other
+ delimiters.
+ */
+ if ( braceDepth == -1 ) {
+ if ( j < (int) yyLine->length() - 1 ) {
+ hook = j;
+ } else {
+ return 0; // shouldn't happen
+ }
+ }
+ break;
+ case '=':
+ /*
+ An equal sign is a very natural alignment hook
+ because it's usually the operator with the lowest
+ precedence in statements it appears in. Case in
+ point:
+
+ int x = 1 +
+ 2;
+
+ However, we have to beware of constructs such as
+ default arguments and explicit enum constant
+ values:
+
+ void foo( int x = 0,
+ int y = 0 );
+
+ And not
+
+ void foo( int x = 0,
+ int y = 0 );
+
+ These constructs are caracterized by a ',' at the
+ end of the unfinished lines or by unbalanced
+ parentheses.
+ */
+ if ( QString("!=<>").indexOf((*yyLine)[j - 1]) == -1 &&
+ (*yyLine)[j + 1] != '=' ) {
+ if ( braceDepth == 0 && delimDepth == 0 &&
+ j < (int) yyLine->length() - 1 &&
+ !yyLine->endsWith(",") &&
+ (yyLine->contains('(') == yyLine->contains(')')) )
+ hook = j;
+ }
+ }
+ }
+
+ if ( hook >= 0 ) {
+ /*
+ Yes, we have a delimiter or an operator to align
+ against! We don't really align against it, but rather
+ against the following token, if any. In this example,
+ the following token is "11":
+
+ int x = ( 11 +
+ 2 );
+
+ If there is no such token, we use a continuation indent:
+
+ static QRegExp foo( QString(
+ "foo foo foo foo foo foo foo foo foo") );
+ */
+ hook++;
+ while ( hook < (int) yyLine->length() ) {
+ if ( !(*yyLine)[hook].isSpace() )
+ return columnForIndex( *yyLine, hook );
+ hook++;
+ }
+ return indentOfLine( *yyLine ) + ppContinuationIndentSize;
+ }
+
+ if ( braceDepth != 0 )
+ break;
+
+ /*
+ The line's delimiters are balanced. It looks like a
+ continuation line or something.
+ */
+ if ( delimDepth == 0 ) {
+ if ( leftBraceFollowed ) {
+ /*
+ We have
+
+ int main()
+ {
+
+ or
+
+ Bar::Bar()
+ : Foo( x )
+ {
+
+ The "{" should be flush left.
+ */
+ if ( !isContinuationLine() )
+ return indentOfLine( *yyLine );
+ } else if ( isContinuationLine() || yyLine->endsWith(",") ) {
+ /*
+ We have
+
+ x = a +
+ b +
+ c;
+
+ or
+
+ int t[] = {
+ 1, 2, 3,
+ 4, 5, 6
+
+ The "c;" should fall right under the "b +", and the
+ "4, 5, 6" right under the "1, 2, 3,".
+ */
+ return indentOfLine( *yyLine );
+ } else {
+ /*
+ We have
+
+ stream << 1 +
+ 2;
+
+ We could, but we don't, try to analyze which
+ operator has precedence over which and so on, to
+ obtain the excellent result
+
+ stream << 1 +
+ 2;
+
+ We do have a special trick above for the assignment
+ operator above, though.
+ */
+ return indentOfLine( *yyLine ) + ppContinuationIndentSize;
+ }
+ }
+
+ if ( !readLine() )
+ break;
+ }
+ return 0;
+}
+
+/*
+ Returns the recommended indent for the bottom line of yyProgram if
+ that line is standalone (or should be indented likewise).
+
+ Indenting a standalone line is tricky, mostly because of braceless
+ control statements. Grossly, we are looking backwards for a special
+ line, a "hook line", that we can use as a starting point to indent,
+ and then modify the indentation level according to the braces met
+ along the way to that hook.
+
+ Let's consider a few examples. In all cases, we want to indent the
+ bottom line.
+
+ Example 1:
+
+ x = 1;
+ y = 2;
+
+ The hook line is "x = 1;". We met 0 opening braces and 0 closing
+ braces. Therefore, "y = 2;" inherits the indent of "x = 1;".
+
+ Example 2:
+
+ if ( x ) {
+ y;
+
+ The hook line is "if ( x ) {". No matter what precedes it, "y;" has
+ to be indented one level deeper than the hook line, since we met one
+ opening brace along the way.
+
+ Example 3:
+
+ if ( a )
+ while ( b ) {
+ c;
+ }
+ d;
+
+ To indent "d;" correctly, we have to go as far as the "if ( a )".
+ Compare with
+
+ if ( a ) {
+ while ( b ) {
+ c;
+ }
+ d;
+
+ Still, we're striving to go back as little as possible to
+ accommodate people with irregular indentation schemes. A hook line
+ near at hand is much more reliable than a remote one.
+*/
+static int indentForStandaloneLine()
+{
+ for ( int i = 0; i < SmallRoof; i++ ) {
+ if ( !*yyLeftBraceFollows ) {
+ YY_SAVE();
+
+ if ( matchBracelessControlStatement() ) {
+ /*
+ The situation is this, and we want to indent "z;":
+
+ if ( x &&
+ y )
+ z;
+
+ yyLine is "if ( x &&".
+ */
+ return indentOfLine( *yyLine ) + ppIndentSize;
+ }
+ YY_RESTORE();
+ }
+
+ if ( yyLine->endsWith(";") || yyLine->contains('{') ) {
+ /*
+ The situation is possibly this, and we want to indent
+ "z;":
+
+ while ( x )
+ y;
+ z;
+
+ We return the indent of "while ( x )". In place of "y;",
+ any arbitrarily complex compound statement can appear.
+ */
+
+ if ( *yyBraceDepth > 0 ) {
+ do {
+ if ( !readLine() )
+ break;
+ } while ( *yyBraceDepth > 0 );
+ }
+
+ LinizerState hookState;
+
+ while ( isContinuationLine() )
+ readLine();
+ hookState = *yyLinizerState;
+
+ readLine();
+ if ( *yyBraceDepth <= 0 ) {
+ do {
+ if ( !matchBracelessControlStatement() )
+ break;
+ hookState = *yyLinizerState;
+ } while ( readLine() );
+ }
+
+ *yyLinizerState = hookState;
+
+ while ( isContinuationLine() )
+ readLine();
+
+ /*
+ Never trust lines containing only '{' or '}', as some
+ people (Richard M. Stallman) format them weirdly.
+ */
+ if ( yyLine->trimmed().length() > 1 )
+ return indentOfLine( *yyLine ) - *yyBraceDepth * ppIndentSize;
+ }
+
+ if ( !readLine() )
+ return -*yyBraceDepth * ppIndentSize;
+ }
+ return 0;
+}
+
+/*
+ Constructs global variables used by the indenter.
+*/
+static void initializeIndenter()
+{
+ literal = new QRegExp( "([\"'])(?:\\\\.|[^\\\\])*\\1" );
+ literal->setMinimal( true );
+ label = new QRegExp(
+ "^\\s*((?:case\\b([^:]|::)+|[a-zA-Z_0-9]+)(?:\\s+slots)?:)(?!:)" );
+ inlineCComment = new QRegExp( "/\\*.*\\*/" );
+ inlineCComment->setMinimal( true );
+ braceX = new QRegExp( "^\\s*\\}\\s*(?:else|catch)\\b" );
+ iflikeKeyword = new QRegExp( "\\b(?:catch|do|for|if|while)\\b" );
+
+ yyLinizerState = new LinizerState;
+}
+
+/*
+ Destroys global variables used by the indenter.
+*/
+static void terminateIndenter()
+{
+ delete literal;
+ delete label;
+ delete inlineCComment;
+ delete braceX;
+ delete iflikeKeyword;
+ delete yyLinizerState;
+}
+
+/*
+ Returns the recommended indent for the bottom line of program.
+ Unless null, typedIn stores the character of yyProgram that
+ triggered reindentation.
+
+ This function works better if typedIn is set properly; it is
+ slightly more conservative if typedIn is completely wild, and
+ slighly more liberal if typedIn is always null. The user might be
+ annoyed by the liberal behavior.
+*/
+int indentForBottomLine( const QStringList& program, QChar typedIn )
+{
+ if ( program.isEmpty() )
+ return 0;
+
+ initializeIndenter();
+
+ yyProgram = new QStringList( program );
+ startLinizer();
+
+ const QString& bottomLine = program.last();
+ QChar firstCh = firstNonWhiteSpace( bottomLine );
+ int indent;
+
+ if ( bottomLineStartsInCComment() ) {
+ /*
+ The bottom line starts in a C-style comment. Indent it
+ smartly, unless the user has already played around with it,
+ in which case it's better to leave her stuff alone.
+ */
+ if ( isOnlyWhiteSpace(bottomLine) ) {
+ indent = indentWhenBottomLineStartsInCComment();
+ } else {
+ indent = indentOfLine( bottomLine );
+ }
+ } else if ( okay(typedIn, '#') && firstCh == QChar('#') ) {
+ /*
+ Preprocessor directives go flush left.
+ */
+ indent = 0;
+ } else {
+ if ( isUnfinishedLine() ) {
+ indent = indentForContinuationLine();
+ } else {
+ indent = indentForStandaloneLine();
+ }
+
+ if ( okay(typedIn, '}') && firstCh == QChar('}') ) {
+ /*
+ A closing brace is one level more to the left than the
+ code it follows.
+ */
+ indent -= ppIndentSize;
+ } else if ( okay(typedIn, ':') ) {
+ QRegExp caseLabel(
+ "\\s*(?:case\\b(?:[^:]|::)+"
+ "|(?:public|protected|private|signals|default)(?:\\s+slots)?\\s*"
+ ")?:.*" );
+
+ if ( caseLabel.exactMatch(bottomLine) ) {
+ /*
+ Move a case label (or the ':' in front of a
+ constructor initialization list) one level to the
+ left, but only if the user did not play around with
+ it yet. Some users have exotic tastes in the
+ matter, and most users probably are not patient
+ enough to wait for the final ':' to format their
+ code properly.
+
+ We don't attempt the same for goto labels, as the
+ user is probably the middle of "foo::bar". (Who
+ uses goto, anyway?)
+ */
+ if ( indentOfLine(bottomLine) <= indent )
+ indent -= ppIndentSize;
+ else
+ indent = indentOfLine( bottomLine );
+ }
+ }
+ }
+ delete yyProgram;
+ terminateIndenter();
+ return qMax( 0, indent );
+}
+
+QT_END_NAMESPACE
+
+#ifdef Q_TEST_YYINDENT
+/*
+ Test driver.
+*/
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+static QString fileContents( const QString& fileName )
+{
+ QFile f( fileName );
+ if ( !f.open(QFile::ReadOnly) ) {
+ qWarning( "yyindent error: Cannot open file '%s' for reading: %s",
+ fileName.toLatin1().data(), strerror(errno) );
+ return QString();
+ }
+
+ QTextStream t( &f );
+ QString contents = t.read();
+ f.close();
+ if ( contents.isEmpty() )
+ qWarning( "yyindent error: File '%s' is empty", fileName.toLatin1().data() );
+ return contents;
+}
+
+QT_END_NAMESPACE
+
+int main( int argc, char **argv )
+{
+ QT_USE_NAMESPACE
+
+ if ( argc != 2 ) {
+ qWarning( "usage: yyindent file.cpp" );
+ return 1;
+ }
+
+ QString code = fileContents( argv[1] );
+ QStringList program = QStringList::split( '\n', code, true );
+ QStringList p;
+ QString out;
+
+ while ( !program.isEmpty() && program.last().trimmed().isEmpty() )
+ program.remove( program.fromLast() );
+
+ QStringList::ConstIterator line = program.begin();
+ while ( line != program.end() ) {
+ p.push_back( *line );
+ QChar typedIn = firstNonWhiteSpace( *line );
+ if ( p.last().endsWith(":") )
+ typedIn = ':';
+
+ int indent = indentForBottomLine( p, typedIn );
+
+ if ( !(*line).trimmed().isEmpty() ) {
+ for ( int j = 0; j < indent; j++ )
+ out += " ";
+ out += (*line).trimmed();
+ }
+ out += "\n";
+ ++line;
+ }
+
+ while ( out.endsWith("\n") )
+ out.truncate( out.length() - 1 );
+
+ printf( "%s\n", out.toLatin1().data() );
+ return 0;
+}
+
+#endif // Q_TEST_YYINDENT
diff --git a/tools/qev/README b/tools/qev/README
new file mode 100644
index 0000000000..b695200cc2
--- /dev/null
+++ b/tools/qev/README
@@ -0,0 +1,2 @@
+This tool allows introspection of incoming events for a QWidget, similar to the X11 xev tool.
+
diff --git a/tools/qev/qev.cpp b/tools/qev/qev.cpp
new file mode 100644
index 0000000000..577c683658
--- /dev/null
+++ b/tools/qev/qev.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+QT_USE_NAMESPACE
+
+class Widget : public QWidget
+{
+public:
+ Widget(){ setAttribute(Qt::WA_InputMethodEnabled); }
+ QSize sizeHint() const { return QSize(20, 20); }
+ bool event(QEvent *e) {
+ if (e->type() == QEvent::ContextMenu)
+ return false;
+ qDebug() << e;
+ return QWidget::event(e);
+ }
+};
+
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Widget w;
+ w.show();
+ return app.exec();
+}
diff --git a/tools/qev/qev.pro b/tools/qev/qev.pro
new file mode 100644
index 0000000000..28383c605a
--- /dev/null
+++ b/tools/qev/qev.pro
@@ -0,0 +1,13 @@
+######################################################################
+# Automatically generated by qmake (1.08a) Mon Oct 18 13:59:36 2004
+######################################################################
+
+TEMPLATE = app
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += qev.cpp
+CONFIG += qt warn_on create_prl link_prl
+OBJECTS_DIR=.obj/debug-shared
+MOC_DIR=.moc/debug-shared
diff --git a/tools/qtconcurrent/codegenerator/codegenerator.pri b/tools/qtconcurrent/codegenerator/codegenerator.pri
new file mode 100644
index 0000000000..0aeabab912
--- /dev/null
+++ b/tools/qtconcurrent/codegenerator/codegenerator.pri
@@ -0,0 +1,5 @@
+SOURCES += $$PWD/src/codegenerator.cpp
+HEADERS += $$PWD/src/codegenerator.h
+INCLUDEPATH += $$PWD/src
+DEPENDPATH += $$PWD/src
+
diff --git a/tools/qtconcurrent/codegenerator/example/example.pro b/tools/qtconcurrent/codegenerator/example/example.pro
new file mode 100644
index 0000000000..df266fe637
--- /dev/null
+++ b/tools/qtconcurrent/codegenerator/example/example.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET +=
+DEPENDPATH += .
+INCLUDEPATH += .
+
+include (../codegenerator.pri)
+
+# Input
+SOURCES += main.cpp
diff --git a/tools/qtconcurrent/codegenerator/example/main.cpp b/tools/qtconcurrent/codegenerator/example/main.cpp
new file mode 100644
index 0000000000..0cd4c498a4
--- /dev/null
+++ b/tools/qtconcurrent/codegenerator/example/main.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QDebug>
+#include "codegenerator.h"
+using namespace CodeGenerator;
+
+int main()
+{
+ // The code generator works on items. Each item has a generate() function:
+ Item item("");
+ qDebug() << item.generate(); // produces "".
+
+ // There are several Item subclasses. Text items contains a text string which they
+ // reproduce when generate is called:
+ Text text(" Hi there");
+ qDebug() << text.generate(); // produces " Hi there".
+
+ // Items can be concatenated:
+ Item sentence = text + Text(" Bye there") ;
+ qDebug() << sentence.generate(); // produces "Hi there Bye there".
+ // (Internally, this creates a tree of items, and generate is called recursively
+ // for items that have children.)
+
+ // Repeater items repeat their content when generate is called:
+ Repeater repeater = text;
+ repeater.setRepeatCount(3);
+ qDebug() << repeater.generate(); // produces "Hi there Hi there Hi there".
+
+ // Counters evaluate to the current repeat index.
+ Repeater repeater2 = text + Counter();
+ repeater2.setRepeatCount(3);
+ qDebug() << repeater2.generate(); // produces "Hi there0 Hi there1 Hi there2".
+
+ // Groups provide sub-groups which are repeated according to the current repeat index.
+ // Counters inside Groups evaluate to the local repeat index for the Group.
+ Group arguments("Arg" + Counter() + " arg" + Counter());
+ Repeater function("void foo(" + arguments + ");\n");
+ function.setRepeatCount(3);
+ qDebug() << function.generate();
+
+ // Produces:
+ // void foo(Arg1 arg1);
+ // void foo(Arg1 arg1, Arg2 arg2);
+ // void foo(Arg1 arg1, Arg2 arg2, Arg3 arg3);
+}
diff --git a/tools/qtconcurrent/codegenerator/src/codegenerator.cpp b/tools/qtconcurrent/codegenerator/src/codegenerator.cpp
new file mode 100644
index 0000000000..62b66ccb9a
--- /dev/null
+++ b/tools/qtconcurrent/codegenerator/src/codegenerator.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "codegenerator.h"
+#include <qdebug.h>
+namespace CodeGenerator
+{
+
+//Convenience constructor so you can say Item("foo")
+Item::Item(const char * const text) : generator(Text(QByteArray(text)).generator) {}
+
+int BaseGenerator::currentCount(GeneratorStack * const stack) const
+{
+ const int stackSize = stack->count();
+ for (int i = stackSize - 1; i >= 0; --i) {
+ BaseGenerator const * const generator = stack->at(i);
+ switch (generator->type) {
+ case RepeaterType: {
+ RepeaterGenerator const * const repeater = static_cast<RepeaterGenerator const * const>(generator);
+ return repeater->currentRepeat;
+ } break;
+ case GroupType: {
+ GroupGenerator const * const group = static_cast<GroupGenerator const * const>(generator);
+ return group->currentRepeat;
+ } break;
+ default:
+ break;
+ }
+ }
+ return -1;
+}
+
+int BaseGenerator::repeatCount(GeneratorStack * const stack) const
+{
+ const int stackSize = stack->count();
+ for (int i = stackSize - 1; i >= 0; --i) {
+ BaseGenerator const * const generator = stack->at(i);
+ switch (generator->type) {
+ case RepeaterType: {
+ RepeaterGenerator const * const repeater = static_cast<RepeaterGenerator const * const>(generator);
+ return repeater->currentRepeat;
+ } break;
+/* case GroupType: {
+ GroupGenerator const * const group = static_cast<GroupGenerator const * const>(generator);
+ return group->currentRepeat;
+ } break;
+*/
+ default:
+ break;
+ }
+ }
+ return -1;
+}
+
+QByteArray RepeaterGenerator::generate(GeneratorStack * const stack)
+{
+ GeneratorStacker stacker(stack, this);
+ QByteArray generated;
+ for (int i = repeatOffset; i < repeatCount + repeatOffset; ++i) {
+ currentRepeat = i;
+ generated += childGenerator->generate(stack);
+ }
+ return generated;
+};
+
+QByteArray GroupGenerator::generate(GeneratorStack * const stack)
+{
+ const int repeatCount = currentCount(stack);
+ GeneratorStacker stacker(stack, this);
+ QByteArray generated;
+
+ if (repeatCount > 0)
+ generated += prefix->generate(stack);
+
+ for (int i = 1; i <= repeatCount; ++i) {
+ currentRepeat = i;
+ generated += childGenerator->generate(stack);
+ if (i != repeatCount)
+ generated += separator->generate(stack);
+ }
+
+ if (repeatCount > 0)
+ generated += postfix->generate(stack);
+
+ return generated;
+};
+
+const Compound operator+(const Item &a, const Item &b)
+{
+ return Compound(a, b);
+}
+
+const Compound operator+(const Item &a, const char * const text)
+{
+ return Compound(a, Text(text));
+}
+
+const Compound operator+(const char * const text, const Item &b)
+{
+ return Compound(Text(text), b);
+}
+
+} \ No newline at end of file
diff --git a/tools/qtconcurrent/codegenerator/src/codegenerator.h b/tools/qtconcurrent/codegenerator/src/codegenerator.h
new file mode 100644
index 0000000000..260ba8cf92
--- /dev/null
+++ b/tools/qtconcurrent/codegenerator/src/codegenerator.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef CODEGENERATOR_H
+#define CODEGENERATOR_H
+
+#include <QByteArray>
+#include <QString>
+#include <QList>
+#include <QStack>
+
+namespace CodeGenerator
+{
+ enum GeneratorType {NoopType, CompoundType, TextType, RepeaterType, CounterType, GroupType};
+ class BaseGenerator;
+ typedef QStack<BaseGenerator *> GeneratorStack;
+
+ template <typename ValueType>
+ class Stacker {
+ public:
+ Stacker(QStack<ValueType> *stack, ValueType value) : stack(stack) { stack->push(value); }
+ ~Stacker() { stack->pop();}
+ private:
+ QStack<ValueType> *stack;
+ };
+ typedef Stacker<BaseGenerator *> GeneratorStacker;
+
+ class BaseGenerator
+ {
+ public:
+ BaseGenerator(GeneratorType type = NoopType) : type(type) {}
+ virtual ~BaseGenerator() {};
+ virtual QByteArray generate(GeneratorStack *stack) { Q_UNUSED(stack); return QByteArray(); };
+ int currentCount(GeneratorStack *stack) const;
+ int repeatCount(GeneratorStack *stack) const;
+ GeneratorType type;
+ };
+
+ class Item
+ {
+ public:
+ Item(BaseGenerator * const base) : generator(base) {}
+ Item(const char * const text);
+ QByteArray generate() const
+ { GeneratorStack stack; return generator->generate(&stack); }
+ // ### TODO: Fix memory leak!
+ // QExplicitlySharedDataPointer<BaseGenerator> generator;
+ BaseGenerator * const generator;
+ };
+
+ class CompoundGenerator : public BaseGenerator
+ {
+ public:
+ CompoundGenerator(BaseGenerator * const a, BaseGenerator * const b)
+ : BaseGenerator(CompoundType), a(a), b(b) {}
+ virtual QByteArray generate(GeneratorStack *stack)
+ { return a->generate(stack) + b->generate(stack); };
+ protected:
+ BaseGenerator * const a;
+ BaseGenerator * const b;
+ };
+
+ class Compound : public Item
+ {
+ public:
+ Compound(const Item &a, const Item &b) : Item(new CompoundGenerator(a.generator, b.generator)) {}
+ };
+
+ class TextGenerator : public BaseGenerator
+ {
+ public:
+ TextGenerator(const QByteArray &text) : BaseGenerator(TextType), text(text) {}
+ virtual QByteArray generate(GeneratorStack *) { return text; };
+ protected:
+ QByteArray text;
+ };
+
+ class Text : public Item {
+ public:
+ Text(const QByteArray &text) : Item(new TextGenerator(text)) {}
+ Text(const char * const text) : Item(new TextGenerator(QByteArray(text))) {}
+ };
+
+ class RepeaterGenerator : public BaseGenerator
+ {
+ public:
+ RepeaterGenerator(BaseGenerator * const childGenerator)
+ : BaseGenerator(RepeaterType), repeatCount(1), repeatOffset(0), childGenerator(childGenerator) {}
+ virtual QByteArray generate(GeneratorStack *stack);
+
+ int repeatCount;
+ int repeatOffset;
+ int currentRepeat;
+ BaseGenerator * const childGenerator;
+ };
+
+ class Repeater : public Item {
+ public:
+ Repeater(const Item &item) : Item(new RepeaterGenerator(item.generator)) {}
+ void setRepeatCount(int count)
+ { static_cast<RepeaterGenerator * const>(generator)->repeatCount = count; }
+ void setRepeatOffset(int offset)
+ { static_cast<RepeaterGenerator * const>(generator)->repeatOffset = offset; }
+ };
+
+ class CounterGenerator : public BaseGenerator
+ {
+ public:
+ CounterGenerator() : BaseGenerator(CounterType), offset(0), increment(1), reverse(false) {}
+ QByteArray generate(GeneratorStack *stack)
+ {
+ if (reverse)
+ return QByteArray::number(repeatCount(stack) - (currentCount(stack) * increment) + offset + 1);
+ else
+ return QByteArray::number((currentCount(stack) * increment) + offset);
+ }
+ int offset;
+ int increment;
+ bool reverse;
+ };
+
+ class Counter : public Item {
+ public:
+ Counter() : Item(new CounterGenerator()) {}
+ Counter(int offset) : Item(new CounterGenerator()) { setOffset(offset); }
+ void setOffset(int offset)
+ { static_cast<CounterGenerator *>(generator)->offset = offset; }
+ void setIncrement(int increment)
+ { static_cast<CounterGenerator *>(generator)->increment = increment; }
+ void setReverse(bool reverse)
+ { static_cast<CounterGenerator *>(generator)->reverse = reverse; }
+
+ };
+
+ class GroupGenerator : public BaseGenerator
+ {
+ public:
+ GroupGenerator(BaseGenerator * const childGenerator)
+ : BaseGenerator(GroupType), currentRepeat(0), childGenerator(childGenerator),
+ separator(new BaseGenerator()), prefix(new BaseGenerator()), postfix(new BaseGenerator()) { }
+ virtual QByteArray generate(GeneratorStack *stack);
+ int currentRepeat;
+ BaseGenerator * const childGenerator;
+ BaseGenerator *separator;
+ BaseGenerator *prefix;
+ BaseGenerator *postfix;
+ };
+
+ class Group : public Item
+ {
+ public:
+ Group(const Item &item) : Item(new GroupGenerator(item.generator)) { setSeparator(", "); }
+ void setSeparator(const Item &separator)
+ { static_cast<GroupGenerator *>(generator)->separator = separator.generator; }
+ void setPrefix(const Item &prefix)
+ { static_cast<GroupGenerator *>(generator)->prefix = prefix.generator; }
+ void setPostfix(const Item &postfix)
+ { static_cast<GroupGenerator *>(generator)->postfix = postfix.generator; }
+ };
+
+ const Compound operator+(const Item &a, const Item &b);
+ const Compound operator+(const Item &a, const char * const text);
+ const Compound operator+(const char * const text, const Item &b);
+
+} //namespace CodeGenerator
+
+#endif
diff --git a/tools/qtconcurrent/generaterun/main.cpp b/tools/qtconcurrent/generaterun/main.cpp
new file mode 100644
index 0000000000..5dd18fbcf4
--- /dev/null
+++ b/tools/qtconcurrent/generaterun/main.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QApplication>
+#include <QDebug>
+#include <QFile>
+
+#include "codegenerator.h"
+using namespace CodeGenerator;
+
+const Item argument = "arg" + Counter();
+const Item argumentRef = "&arg" + Counter();
+const Item argumentType = "Arg" + Counter();
+const Item constArgumentType = "const Arg" + Counter();
+const Item parameterType = "Param" + Counter();
+
+Group argumentTypes(argumentType); // expands to ",Arg1, Arg2, ..."
+Group argumentTypesNoPrefix(argumentType); // expands to "Arg1, Arg2, ..."
+Group arguments(argument); // expands to ",arg1, arg2, ..."
+Group argumentsNoPrefix(argument); // expands to "arg1, arg2, ..."
+Group parameterTypes(parameterType); // expands to ",Param1, Param2, ..."
+Group parameterTypesNoPrefix(parameterType); // expands to "Param1, Param2, ..."
+Group typenameTypes("typename " + parameterType + ", typename " + argumentType); // expands to " ,typename Param1, typename Arg1, ..."
+Group types(parameterType + ", " + argumentType); // expands to ", Param1, Arg1, ..."
+Group functionParameters(constArgumentType + " " + argumentRef);
+Group typenameArgumentTypes("typename " + argumentType);
+
+Group initializers(argument + "(" + argument + ")");
+Group classData(argumentType +" " + argument + ";");
+Group arglist(argument);
+Group typeList(argumentTypes);
+
+void init()
+{
+ argumentTypes.setPrefix(", ");
+ arguments.setPrefix(", ");
+ parameterTypes.setPrefix(", ");
+ typenameTypes.setPrefix(", ");
+ types.setPrefix(", ");
+ functionParameters.setPrefix(", ");
+ typenameArgumentTypes.setPrefix(", ");
+
+ initializers.setPrefix(", ");
+ classData.setSeparator(" ");
+ classData.setPrefix(" ");
+ arglist.setPrefix(", ");
+ typeList.setPrefix(", ");
+}
+
+
+Item Line(Item item)
+{
+ return item + "\n";
+}
+
+Item generateRunFunctions(int repeats)
+{
+ Item functionPointerType = "T (*)(" + parameterTypesNoPrefix + ")";
+
+ Item functionPointerParameter = "T (*functionPointer)(" + parameterTypesNoPrefix + ")";
+
+
+
+ // plain functions
+ Repeater functions = Line ("template <typename T" + typenameTypes + ">") +
+ Line ("QFuture<T> run(" + functionPointerParameter + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new QT_TYPENAME SelectStoredFunctorCall" + Counter() + "<T, " +
+ functionPointerType + argumentTypes + ">::type(functionPointer" + arguments + "))->start();") +
+ Line("}");
+ functions.setRepeatCount(repeats);
+
+ // function objects by value
+ Repeater functionObjects = Line ("template <typename FunctionObject" + typenameArgumentTypes + ">") +
+ Line ("QFuture<typename FunctionObject::result_type> run(FunctionObject functionObject" + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new QT_TYPENAME SelectStoredFunctorCall" + Counter() +
+ "<QT_TYPENAME FunctionObject::result_type, FunctionObject" +
+ argumentTypes + ">::type(functionObject" + arguments + "))->start();") +
+ Line("}");
+ functionObjects.setRepeatCount(repeats);
+
+ // function objects by pointer
+ Repeater functionObjectsPointer = Line ("template <typename FunctionObject" + typenameArgumentTypes + ">") +
+ Line ("QFuture<typename FunctionObject::result_type> run(FunctionObject *functionObject" + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new QT_TYPENAME SelectStoredFunctorPointerCall" + Counter() +
+ "<QT_TYPENAME FunctionObject::result_type, FunctionObject" +
+ argumentTypes + ">::type(functionObject" + arguments + "))->start();") +
+ Line("}");
+ functionObjectsPointer.setRepeatCount(repeats);
+
+ // member functions by value
+ Repeater memberFunction = Line ("template <typename T, typename Class" + typenameTypes + ">") +
+ Line ("QFuture<T> run(const Class &object, T (Class::*fn)(" + parameterTypesNoPrefix + ")" + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new QT_TYPENAME SelectStoredMemberFunctionCall" + Counter() +
+ "<T, Class" +
+ types + ">::type(fn, object" + arguments + "))->start();") +
+ Line("}");
+ memberFunction.setRepeatCount(repeats);
+
+ // const member functions by value
+ Repeater constMemberFunction = Line ("template <typename T, typename Class" + typenameTypes + ">") +
+ Line ("QFuture<T> run(const Class &object, T (Class::*fn)(" + parameterTypesNoPrefix + ") const" + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new QT_TYPENAME SelectStoredConstMemberFunctionCall" + Counter() +
+ "<T, Class" +
+ types + ">::type(fn, object" + arguments + "))->start();") +
+ Line("}");
+ constMemberFunction.setRepeatCount(repeats);
+
+ // member functions by class pointer
+ Repeater memberFunctionPointer = Line ("template <typename T, typename Class" + typenameTypes + ">") +
+ Line ("QFuture<T> run(Class *object, T (Class::*fn)(" + parameterTypesNoPrefix + ")" + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new QT_TYPENAME SelectStoredMemberFunctionPointerCall" + Counter() +
+ "<T, Class" +
+ types + ">::type(fn, object" + arguments + "))->start();") +
+ Line("}");
+ memberFunctionPointer.setRepeatCount(repeats);
+
+ // const member functions by class pointer
+ Repeater constMemberFunctionPointer = Line ("template <typename T, typename Class" + typenameTypes + ">") +
+ Line ("QFuture<T> run(const Class *object, T (Class::*fn)(" + parameterTypesNoPrefix + ") const" + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new QT_TYPENAME SelectStoredConstMemberFunctionPointerCall" + Counter() +
+ "<T, Class" +
+ types + ">::type(fn, object" + arguments + "))->start();") +
+ Line("}");
+ constMemberFunctionPointer.setRepeatCount(repeats);
+
+
+ Item interfaceFunctionPointerType = "void (*)(QFutureInterface<T> &" + argumentTypes + ")";
+ Item interfaceFunctionPointerParameter = "void (*functionPointer)(QFutureInterface<T> &" + argumentTypes + ")";
+/*
+ // QFutureInterface functions
+ Repeater interfaceFunctions = Line ("template <typename T" + typenameTypes + ">") +
+ Line ("QFuture<T> run(" + interfaceFunctionPointerParameter + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new StoredInterfaceFunctionCall" + Counter() + "<T, " +
+ interfaceFunctionPointerType + typenameArgumentTypes + ">(functionPointer" + arguments + "))->start();") +
+ Line("}");
+ functions.setRepeatCount(repeats);
+ interfaceFunctions.setRepeatCount(repeats);
+
+ // member functions by class pointer
+ Repeater interfaceMemberFunction = Line ("template <typename Class, typename T" + typenameTypes + ">") +
+ Line ("QFuture<T> run(void (Class::*fn)(QFutureInterface<T> &), Class *object" + functionParameters + ")") +
+ Line("{") +
+ Line(" return (new StoredInterfaceMemberFunctionCall" + Counter() +
+ "<T, void (Class::*)(QFutureInterface<T> &), Class" +
+ typenameArgumentTypes + ">(fn, object" + arguments + "))->start();") +
+ Line("}");
+ memberFunctionPointer.setRepeatCount(repeats);
+*/
+ return functions + Line("") + functionObjects + Line("") + functionObjectsPointer + Line("")
+ + memberFunction + Line("") + constMemberFunction + Line("")
+ + memberFunctionPointer + Line("") + constMemberFunctionPointer + Line("")
+ /* + interfaceFunctions + Line("") + interfaceMemberFunction + Line("")*/
+ ;
+}
+
+
+Item functions(Item className, Item functorType, Item callLine)
+{
+ return
+ Line("template <typename T, typename FunctionPointer" + typenameArgumentTypes + ">") +
+ Line("struct " + className + Counter() +": public RunFunctionTask<T>") +
+ Line("{") +
+ Line(" inline " + className + Counter() + "(" + functorType + " function" + functionParameters +")") +
+ Line(" : function(function)" + initializers + " {}") +
+ Line(" void runFunctor() {" + callLine + argumentsNoPrefix + "); }") +
+ Line(" " + functorType + " function;") +
+ Line( classData) +
+ Line("};") +
+ Line("");
+}
+
+Item functionSelector(Item classNameBase)
+{
+ return
+ Line("template <typename T, typename FunctionPointer" + typenameArgumentTypes + ">") +
+ Line("struct Select" + classNameBase + Counter()) +
+ Line("{") +
+ Line(" typedef typename SelectSpecialization<T>::template") +
+ Line(" Type<" + classNameBase + Counter() + " <T, FunctionPointer" + argumentTypes + ">,") +
+ Line(" Void" + classNameBase + Counter() + "<T, FunctionPointer" + argumentTypes + "> >::type type;") +
+ Line("};");
+}
+
+Item memberFunctions(Item className, Item constFunction, Item objectArgument, Item objectMember, Item callLine)
+{
+ return
+ Line("template <typename T, typename Class" + typenameTypes + ">") +
+ Line("class " + className + Counter() + " : public RunFunctionTask<T>") +
+ Line("{") +
+ Line("public:")+
+ Line(" " + className + Counter() + "(T (Class::*fn)(" + parameterTypesNoPrefix + ") " + constFunction + ", " + objectArgument + functionParameters + ")") +
+ Line(" : fn(fn), object(object)" + initializers + "{ }" ) +
+ Line("")+
+ Line(" void runFunctor()")+
+ Line(" {")+
+ Line(" " + callLine + argumentsNoPrefix + ");")+
+ Line(" }")+
+ Line("private:")+
+ Line(" T (Class::*fn)(" + parameterTypesNoPrefix + ")" + constFunction + ";")+
+ Line(" " + objectMember + ";") +
+ Line( classData) +
+ Line("};");
+}
+
+Item memberFunctionSelector(Item classNameBase)
+{
+ return
+ Line("template <typename T, typename Class" + typenameTypes + ">") +
+ Line("struct Select" + classNameBase + Counter()) +
+ Line("{") +
+ Line(" typedef typename SelectSpecialization<T>::template") +
+ Line(" Type<" + classNameBase + Counter() + " <T, Class" + types + ">,") +
+ Line(" Void" + classNameBase + Counter() + "<T, Class" + types + "> >::type type;") +
+ Line("};");
+}
+
+Item generateSFCs(int repeats)
+{
+
+ Item functionPointerTypedef = "typedef void (*FunctionPointer)(" + argumentTypesNoPrefix + ");";
+
+ Repeater dataStructures =
+
+ // Function objects by value
+ functions(Item("StoredFunctorCall"), Item("FunctionPointer"), Item(" this->result = function(")) +
+ functions(Item("VoidStoredFunctorCall"), Item("FunctionPointer"), Item(" function(")) +
+ functionSelector(Item("StoredFunctorCall")) +
+
+ // Function objects by pointer
+ functions(Item("StoredFunctorPointerCall"), Item("FunctionPointer *"), Item(" this->result =(*function)(")) +
+ functions(Item("VoidStoredFunctorPointerCall"), Item("FunctionPointer *"), Item("(*function)(")) +
+ functionSelector(Item("StoredFunctorPointerCall")) +
+
+ // Member functions by value
+ memberFunctions(Item("StoredMemberFunctionCall"), Item(""), Item("const Class &object"), Item("Class object"), Item("this->result = (object.*fn)(")) +
+ memberFunctions(Item("VoidStoredMemberFunctionCall"), Item(""), Item("const Class &object"), Item("Class object"), Item("(object.*fn)(")) +
+ memberFunctionSelector(Item("StoredMemberFunctionCall")) +
+
+ // Const Member functions by value
+ memberFunctions(Item("StoredConstMemberFunctionCall"), Item("const"), Item("const Class &object"), Item("const Class object"), Item("this->result = (object.*fn)(")) +
+ memberFunctions(Item("VoidStoredConstMemberFunctionCall"), Item("const"), Item("const Class &object"), Item("const Class object"), Item("(object.*fn)(")) +
+ memberFunctionSelector(Item("StoredConstMemberFunctionCall")) +
+
+ // Member functions by pointer
+ memberFunctions(Item("StoredMemberFunctionPointerCall"), Item(""), Item("Class *object"), Item("Class *object"), Item("this->result = (object->*fn)(")) +
+ memberFunctions(Item("VoidStoredMemberFunctionPointerCall"), Item(""), Item("Class *object"), Item("Class *object"), Item("(object->*fn)(")) +
+ memberFunctionSelector(Item("StoredMemberFunctionPointerCall")) +
+
+ // const member functions by pointer
+ memberFunctions(Item("StoredConstMemberFunctionPointerCall"), Item("const"), Item("Class const *object"), Item("Class const *object"), Item("this->result = (object->*fn)(")) +
+ memberFunctions(Item("VoidStoredConstMemberFunctionPointerCall"), Item("const"), Item("Class const *object"), Item("Class const *object"), Item("(object->*fn)(")) +
+ memberFunctionSelector(Item("StoredConstMemberFunctionPointerCall"));
+
+ dataStructures.setRepeatCount(repeats);
+ return dataStructures;
+}
+
+void writeFile(QString fileName, QByteArray contents)
+{
+ QFile runFile(fileName);
+ if (runFile.open(QIODevice::WriteOnly) == false) {
+ qDebug() << "Write to" << fileName << "failed";
+ return;
+ }
+
+ runFile.write(contents);
+ runFile.close();
+ qDebug() << "Write to" << fileName << "Ok";
+}
+
+Item dollarQuote(Item item)
+{
+ return Item("$") + item + Item("$");
+}
+
+int main()
+{
+ const int repeats = 6;
+ init();
+ Item run = (
+ Line("/****************************************************************************") +
+ Line("**") +
+ Line("** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).") +
+ Line("** Contact: Qt Software Information (qt-info@nokia.com)") +
+ Line("**") +
+ Line("** This file is part of the " + dollarQuote("MODULE") + " of the Qt Toolkit.") +
+ Line("**") +
+ Line("** " + dollarQuote("TROLLTECH_DUAL_LICENSE")) +
+ Line("**") +
+ Line("****************************************************************************/") +
+ Line("") +
+ Line("// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/") +
+ Line("#ifndef QTCONCURRENT_RUN_H") +
+ Line("#define QTCONCURRENT_RUN_H") +
+ Line("") +
+ Line("#ifndef QT_NO_CONCURRENT") +
+ Line("") +
+ Line("#include <QtCore/qtconcurrentrunbase.h>") +
+ Line("#include <QtCore/qtconcurrentstoredfunctioncall.h>") +
+ Line("") +
+ Line("QT_BEGIN_HEADER") +
+ Line("QT_BEGIN_NAMESPACE") +
+ Line("") +
+ Line("QT_MODULE(Core)") +
+ Line("") +
+ Line("#ifdef qdoc") +
+ Line("") +
+ Line("namespace QtConcurrent {") +
+ Line("") +
+ Line(" template <typename T>") +
+ Line(" QFuture<T> run(Function function, ...);") +
+ Line("") +
+ Line("} // namespace QtConcurrent") +
+ Line("") +
+ Line("#else") +
+ Line("") +
+ Line("namespace QtConcurrent {") +
+ Line("") +
+ generateRunFunctions(repeats) +
+ Line("} //namespace QtConcurrent") +
+ Line("") +
+ Line("#endif // qdoc") +
+ Line("") +
+ Line("QT_END_NAMESPACE") +
+ Line("QT_END_HEADER") +
+ Line("") +
+ Line("#endif")
+ );
+
+ writeFile("../../../src/corelib/concurrent/qtconcurrentrun.h", run.generate());
+
+ Item storedFunctionCall = (
+ Line("/****************************************************************************") +
+ Line("**") +
+ Line("** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).") +
+ Line("** Contact: Qt Software Information (qt-info@nokia.com)") +
+ Line("**") +
+ Line("** This file is part of the " + dollarQuote("MODULE") + " of the Qt Toolkit.") +
+ Line("**") +
+ Line("** " + dollarQuote("TROLLTECH_DUAL_LICENSE")) +
+ Line("**") +
+ Line("****************************************************************************/") +
+ Line("") +
+ Line("// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/") +
+ Line("#ifndef QTCONCURRENT_STOREDFUNCTIONCALL_H") +
+ Line("#define QTCONCURRENT_STOREDFUNCTIONCALL_H") +
+ Line("") +
+ Line("#include <QtCore/qglobal.h>") +
+ Line("") +
+ Line("#ifndef QT_NO_CONCURRENT") +
+ Line("#include <QtCore/qtconcurrentrunbase.h>") +
+ Line("") +
+ Line("QT_BEGIN_HEADER") +
+ Line("QT_BEGIN_NAMESPACE") +
+ Line("") +
+ Line("QT_MODULE(Core)") +
+ Line("") +
+ Line("#ifndef qdoc") +
+ Line("") +
+ Line("namespace QtConcurrent {") +
+ generateSFCs(repeats) +
+ Line("} //namespace QtConcurrent") +
+ Line("") +
+ Line("#endif // qdoc") +
+ Line("") +
+ Line("QT_END_NAMESPACE") +
+ Line("QT_END_HEADER") +
+ Line("") +
+ Line("#endif // QT_NO_CONCURRENT") +
+ Line("") +
+ Line("#endif")
+ );
+
+ writeFile("../../../src/corelib/concurrent/qtconcurrentstoredfunctioncall.h", storedFunctionCall.generate());
+}
+
+
diff --git a/tools/qtconcurrent/generaterun/run.pro b/tools/qtconcurrent/generaterun/run.pro
new file mode 100644
index 0000000000..76bc661eca
--- /dev/null
+++ b/tools/qtconcurrent/generaterun/run.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET +=
+DEPENDPATH += .
+INCLUDEPATH += .
+
+include(../codegenerator/codegenerator.pri)
+
+# Input
+SOURCES += main.cpp
diff --git a/tools/qtconfig/LICENSE.GPL b/tools/qtconfig/LICENSE.GPL
new file mode 100644
index 0000000000..b6e1c33e04
--- /dev/null
+++ b/tools/qtconfig/LICENSE.GPL
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/tools/qtconfig/colorbutton.cpp b/tools/qtconfig/colorbutton.cpp
new file mode 100644
index 0000000000..d700507311
--- /dev/null
+++ b/tools/qtconfig/colorbutton.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "colorbutton.h"
+
+#include <QApplication>
+#include <QtEvents>
+#include <QColorDialog>
+#include <QPainter>
+#include <QMimeData>
+#include <QStyle>
+#include <QStyleOption>
+
+QT_BEGIN_NAMESPACE
+
+ColorButton::ColorButton(QWidget *parent)
+ : QAbstractButton(parent), mousepressed(false)
+{
+ setAcceptDrops(true);
+ col = Qt::black;
+ connect(this, SIGNAL(clicked()), SLOT(changeColor()));
+}
+
+
+ColorButton::ColorButton(const QColor &c, QWidget *parent)
+ : QAbstractButton(parent)
+{
+ setAcceptDrops(true);
+ col = c;
+ connect(this, SIGNAL(clicked()), SLOT(changeColor()));
+}
+
+
+void ColorButton::setColor(const QColor &c)
+{
+ col = c;
+ update();
+}
+
+
+void ColorButton::changeColor()
+{
+ QColor c = QColorDialog::getColor(col, qApp->activeWindow());
+
+ if (c.isValid()) {
+ setColor(c);
+ emit colorChanged(color());
+ }
+}
+
+
+QSize ColorButton::sizeHint() const
+{
+ return QSize(40, 25);
+}
+
+
+QSize ColorButton::minimumSizeHint() const
+{
+ return QSize(40, 25);
+}
+
+
+void ColorButton::drawButton(QPainter *p)
+{
+ QStyleOptionButton buttonOptions;
+ buttonOptions.init(this);
+ buttonOptions.features = QStyleOptionButton::None;
+ buttonOptions.rect = rect();
+ buttonOptions.palette = palette();
+ buttonOptions.state = (isDown() ? QStyle::State_Sunken : QStyle::State_Raised);
+ style()->drawPrimitive(QStyle::PE_PanelButtonBevel, &buttonOptions, p, this);
+
+ p->save();
+ drawButtonLabel(p);
+ p->restore();
+
+ QStyleOptionFocusRect frectOptions;
+ frectOptions.init(this);
+ frectOptions.rect = style()->subElementRect(QStyle::SE_PushButtonFocusRect, &buttonOptions, this);
+ if (hasFocus())
+ style()->drawPrimitive(QStyle::PE_FrameFocusRect, &frectOptions, p, this);
+}
+
+
+void ColorButton::drawButtonLabel(QPainter *p)
+{
+ QPalette::ColorGroup cg =
+ (isEnabled() ? (hasFocus() ? QPalette::Active : QPalette::Inactive) : QPalette::Disabled);
+
+ p->setPen(palette().color(cg, QPalette::ButtonText));
+ p->setBrush(col);
+ p->drawRect(width() / 4, height() / 4, width() / 2 - 1, height() / 2 - 1);
+}
+
+
+void ColorButton::dragEnterEvent(QDragEnterEvent *e)
+{
+ if (!e->mimeData()->hasColor()) {
+ e->ignore();
+ return;
+ }
+}
+
+
+void ColorButton::dragMoveEvent(QDragMoveEvent *e)
+{
+ if (!e->mimeData()->hasColor()) {
+ e->ignore();
+ return;
+ }
+
+ e->accept();
+}
+
+
+void ColorButton::dropEvent(QDropEvent *e)
+{
+ if (!e->mimeData()->hasColor()) {
+ e->ignore();
+ return;
+ }
+
+ QColor c = qvariant_cast<QColor>(e->mimeData()->colorData());
+ setColor(c);
+ emit colorChanged(color());
+}
+
+
+void ColorButton::mousePressEvent(QMouseEvent *e)
+{
+ presspos = e->pos();
+ mousepressed = true;
+ QAbstractButton::mousePressEvent(e);
+}
+
+
+void ColorButton::mouseReleaseEvent(QMouseEvent *e)
+{
+ mousepressed = false;
+ QAbstractButton::mouseReleaseEvent(e);
+}
+
+
+void ColorButton::mouseMoveEvent(QMouseEvent *e)
+{
+ if (! mousepressed)
+ return;
+
+ if ((presspos - e->pos()).manhattanLength() > QApplication::startDragDistance()) {
+ mousepressed = false;
+ setDown(false);
+
+ QDrag *drag = new QDrag(this);
+ QMimeData *data = new QMimeData;
+ data->setColorData(color());
+ drag->setMimeData(data);
+ drag->start(Qt::CopyAction);
+ }
+}
+
+void ColorButton::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ drawButton(&p);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/colorbutton.h b/tools/qtconfig/colorbutton.h
new file mode 100644
index 0000000000..01f6760396
--- /dev/null
+++ b/tools/qtconfig/colorbutton.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COLORBUTTON_H
+#define COLORBUTTON_H
+
+#include <QAbstractButton>
+
+QT_BEGIN_NAMESPACE
+
+class ColorButton : public QAbstractButton
+{
+ Q_OBJECT
+
+public:
+ ColorButton(QWidget *);
+ ColorButton(const QColor &, QWidget *);
+
+ const QColor &color() const { return col; }
+
+ void setColor(const QColor &);
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void dragEnterEvent(QDragEnterEvent *);
+ void dragMoveEvent(QDragMoveEvent *);
+ void dropEvent(QDropEvent *);
+
+signals:
+ void colorChanged(const QColor &);
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void drawButton(QPainter *);
+ void drawButtonLabel(QPainter *);
+
+private slots:
+ void changeColor();
+
+
+private:
+ QColor col;
+ QPoint presspos;
+ bool mousepressed;
+};
+
+QT_END_NAMESPACE
+
+#endif // COLORBUTTON_H
diff --git a/tools/qtconfig/images/appicon.png b/tools/qtconfig/images/appicon.png
new file mode 100644
index 0000000000..0093177787
--- /dev/null
+++ b/tools/qtconfig/images/appicon.png
Binary files differ
diff --git a/tools/qtconfig/main.cpp b/tools/qtconfig/main.cpp
new file mode 100644
index 0000000000..e6b7630ab2
--- /dev/null
+++ b/tools/qtconfig/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ui_previewwidgetbase.h"
+#include "mainwindow.h"
+#include <QApplication>
+
+QT_USE_NAMESPACE
+
+int main(int argc, char **argv)
+{
+ Q_INIT_RESOURCE(qtconfig);
+
+ QApplication app(argc, argv);
+ MainWindow mw;
+ mw.show();
+ return app.exec();
+}
diff --git a/tools/qtconfig/mainwindow.cpp b/tools/qtconfig/mainwindow.cpp
new file mode 100644
index 0000000000..498a6b6197
--- /dev/null
+++ b/tools/qtconfig/mainwindow.cpp
@@ -0,0 +1,1073 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "colorbutton.h"
+#include "previewframe.h"
+#include "paletteeditoradvanced.h"
+
+#include <QLabel>
+#include <QApplication>
+#include <QComboBox>
+#include <QStyleFactory>
+#include <QFontDatabase>
+#include <QLineEdit>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QFileDialog>
+#include <QAction>
+#include <QStatusBar>
+#include <QSettings>
+#include <QMessageBox>
+#include <QStyle>
+#include <QtEvents>
+#include <Q3ValueList>
+#include <QInputContext>
+#include <QInputContextFactory>
+#include <QtDebug>
+
+#include <stdlib.h>
+
+#ifndef QT_NO_GSTREAMER
+#include <gst/gst.h>
+#include <phonon/phononnamespace.h>
+#endif
+
+#include <QtGui/private/qt_x11_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// from qapplication.cpp and qapplication_x11.cpp - These are NOT for
+// external use ignore them
+// extern bool Q_CORE_EXPORT qt_resolve_symlinks;
+
+static const char *appearance_text =
+"<p><b><font size+=2>Appearance</font></b></p>"
+"<hr>"
+"<p>Use this tab to customize the appearance of your Qt applications.</p>"
+"<p>You can select the default GUI Style from the drop down list and "
+"customize the colors.</p>"
+"<p>Any GUI Style plugins in your plugin path will automatically be added "
+"to the list of built-in Qt styles. (See the Library Paths tab for "
+"information on adding new plugin paths.)</p>"
+"<p>When you choose 3-D Effects and Window Background colors, the Qt "
+"Configuration program will automatically generate a palette for you. "
+"To customize colors further, press the Tune Palette button to open "
+"the advanced palette editor."
+"<p>The Preview Window shows what the selected Style and colors look "
+"like.";
+
+static const char *font_text =
+"<p><b><font size+=2>Fonts</font></b></p>"
+"<hr>"
+"<p>Use this tab to select the default font for your Qt applications. "
+"The selected font is shown (initially as 'Sample Text') in the line "
+"edit below the Family, "
+"Style and Point Size drop down lists.</p>"
+"<p>Qt has a powerful font substitution feature that allows you to "
+"specify a list of substitute fonts. Substitute fonts are used "
+"when a font cannot be loaded, or if the specified font doesn't have "
+"a particular character."
+"<p>For example, if you select the font Lucida, which doesn't have Korean "
+"characters, but need to show some Korean text using the Mincho font family "
+"you can do so by adding Mincho to the list. Once Mincho is added, any "
+"Korean characters that are not found in the Lucida font will be taken "
+"from the Mincho font. Because the font substitutions are "
+"lists, you can also select multiple families, such as Song Ti (for "
+"use with Chinese text).";
+
+static const char *interface_text =
+"<p><b><font size+=2>Interface</font></b></p>"
+"<hr>"
+"<p>Use this tab to customize the feel of your Qt applications.</p>"
+"<p>If the Resolve Symlinks checkbox is checked Qt will follow symlinks "
+"when handling URLs. For example, in the file dialog, if this setting is turned "
+"on and /usr/tmp is a symlink to /var/tmp, entering the /usr/tmp directory "
+"will cause the file dialog to change to /var/tmp. With this setting turned "
+"off, symlinks are not resolved or followed.</p>"
+"<p>The Global Strut setting is useful for people who require a "
+"minimum size for all widgets (e.g. when using a touch panel or for users "
+"who are visually impaired). Leaving the Global Strut width and height "
+"at 0 will disable the Global Strut feature</p>"
+"<p>XIM (Extended Input Methods) are used for entering characters in "
+"languages that have large character sets, for example, Chinese and "
+"Japanese.";
+// ### What does the 'Enhanced support for languages written R2L do?
+
+static const char *printer_text =
+"<p><b><font size+=2>Printer</font></b></p>"
+"<hr>"
+"<p>Use this tab to configure the way Qt generates output for the printer."
+"You can specify if Qt should try to embed fonts into its generated output."
+"If you enable font embedding, the resulting postscript will be more "
+"portable and will more accurately reflect the "
+"visual output on the screen; however the resulting postscript file "
+"size will be bigger."
+"<p>When using font embedding you can select additional directories where "
+"Qt should search for embeddable font files. By default, the X "
+"server font path is used.";
+
+static const char *phonon_text =
+"<p><b><font size+=2>Phonon</font></b></p>"
+"<hr>"
+"<p>Use this tab to configure the Phonon GStreamer multimedia backend. "
+"<p>It is reccommended to leave all settings on \"Auto\" to let "
+"Phonon determine your settings automatically.";
+
+static QColorGroup::ColorRole centralFromItem( int item )
+{
+ switch( item ) {
+ case 0: return QColorGroup::Window;
+ case 1: return QColorGroup::WindowText;
+ case 2: return QColorGroup::Button;
+ case 3: return QColorGroup::Base;
+ case 4: return QColorGroup::Text;
+ case 5: return QColorGroup::BrightText;
+ case 6: return QColorGroup::ButtonText;
+ case 7: return QColorGroup::Highlight;
+ case 8: return QColorGroup::HighlightedText;
+ default: return QColorGroup::NColorRoles;
+ }
+}
+
+
+static QColorGroup::ColorRole effectFromItem( int item )
+{
+ switch( item ) {
+ case 0: return QColorGroup::Light;
+ case 1: return QColorGroup::Midlight;
+ case 2: return QColorGroup::Mid;
+ case 3: return QColorGroup::Dark;
+ case 4: return QColorGroup::Shadow;
+ default: return QColorGroup::NColorRoles;
+ }
+}
+
+
+static void setStyleHelper(QWidget *w, QStyle *s)
+{
+ const QObjectList children = w->children();
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *child = children.at(i);
+ if (child->isWidgetType())
+ setStyleHelper((QWidget *) child, s);
+ }
+ w->setStyle(s);
+}
+
+
+MainWindow::MainWindow()
+ : MainWindowBase(0, "main window"),
+ editPalette(palette()), previewPalette(palette()), previewstyle(0)
+{
+ modified = true;
+ desktopThemeName = tr("Desktop Settings (Default)");
+ QStringList gstyles = QStyleFactory::keys();
+ gstyles.sort();
+ gstylecombo->addItem(desktopThemeName);
+ gstylecombo->setItemData(gstylecombo->findText(desktopThemeName),
+ tr("Choose style and palette based on your desktop settings."), Qt::ToolTipRole);
+ gstylecombo->insertStringList(gstyles);
+
+ QSettings settings(QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+
+ QString currentstyle = settings.value(QLatin1String("style")).toString();
+ if (currentstyle.isEmpty()) {
+ gstylecombo->setCurrentItem(gstylecombo->findText(desktopThemeName));
+ currentstyle = QLatin1String(QApplication::style()->name());
+ } else {
+ int index = gstylecombo->findText(currentstyle, Qt::MatchFixedString);
+ if (index != -1) {
+ gstylecombo->setCurrentItem(index);
+ } else { // we give up
+ gstylecombo->insertItem(QLatin1String("Unknown"));
+ gstylecombo->setCurrentItem(gstylecombo->count() - 1);
+ }
+ }
+ buttonMainColor->setColor(palette().color(QPalette::Active,
+ QColorGroup::Button));
+ buttonMainColor2->setColor(palette().color(QPalette::Active,
+ QColorGroup::Window));
+ connect(buttonMainColor, SIGNAL(colorChanged(QColor)),
+ this, SLOT(buildPalette()));
+ connect(buttonMainColor2, SIGNAL(colorChanged(QColor)),
+ this, SLOT(buildPalette()));
+
+ if (X11->desktopEnvironment == DE_KDE)
+ colorConfig->hide();
+ else
+ labelKDENote->hide();
+
+ QFontDatabase db;
+ QStringList families = db.families();
+ familycombo->insertStringList(families);
+
+ QStringList fs = families;
+ QStringList fs2 = QFont::substitutions();
+ QStringList::Iterator fsit = fs2.begin();
+ while (fsit != fs2.end()) {
+ if (! fs.contains(*fsit))
+ fs += *fsit;
+ fsit++;
+ }
+ fs.sort();
+ familysubcombo->insertStringList(fs);
+
+ choosesubcombo->insertStringList(families);
+ Q3ValueList<int> sizes = db.standardSizes();
+ Q3ValueList<int>::Iterator it = sizes.begin();
+ while (it != sizes.end())
+ psizecombo->insertItem(QString::number(*it++));
+
+ dcispin->setValue(QApplication::doubleClickInterval());
+ cfispin->setValue(QApplication::cursorFlashTime());
+ wslspin->setValue(QApplication::wheelScrollLines());
+ // #############
+// resolvelinks->setChecked(qt_resolve_symlinks);
+
+ effectcheckbox->setChecked(QApplication::isEffectEnabled(Qt::UI_General));
+ effectbase->setEnabled(effectcheckbox->isChecked());
+
+ if (QApplication::isEffectEnabled(Qt::UI_FadeMenu))
+ menueffect->setCurrentItem(2);
+ else if (QApplication::isEffectEnabled(Qt::UI_AnimateMenu))
+ menueffect->setCurrentItem(1);
+
+ if (QApplication::isEffectEnabled(Qt::UI_AnimateCombo))
+ comboeffect->setCurrentItem(1);
+
+ if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip))
+ tooltipeffect->setCurrentItem(2);
+ else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip))
+ tooltipeffect->setCurrentItem(1);
+
+ if ( QApplication::isEffectEnabled( Qt::UI_AnimateToolBox ) )
+ toolboxeffect->setCurrentItem( 1 );
+
+ QSize globalStrut = QApplication::globalStrut();
+ strutwidth->setValue(globalStrut.width());
+ strutheight->setValue(globalStrut.height());
+
+ // find the default family
+ QStringList::Iterator sit = families.begin();
+ int i = 0, possible = -1;
+ while (sit != families.end()) {
+ if (*sit == QApplication::font().family())
+ break;
+ if ((*sit).contains(QApplication::font().family()))
+ possible = i;
+
+ i++;
+ sit++;
+ }
+ if (sit == families.end())
+ i = possible;
+ if (i == -1) // no clue about the current font
+ i = 0;
+
+ familycombo->setCurrentItem(i);
+
+ QStringList styles = db.styles(familycombo->currentText());
+ stylecombo->insertStringList(styles);
+
+ QString stylestring = db.styleString(QApplication::font());
+ sit = styles.begin();
+ i = 0;
+ possible = -1;
+ while (sit != styles.end()) {
+ if (*sit == stylestring)
+ break;
+ if ((*sit).contains(stylestring))
+ possible = i;
+
+ i++;
+ sit++;
+ }
+ if (sit == styles.end())
+ i = possible;
+ if (i == -1) // no clue about the current font
+ i = 0;
+ stylecombo->setCurrentItem(i);
+
+ i = 0;
+ for (int psize = QApplication::font().pointSize(); i < psizecombo->count(); ++i) {
+ const int sz = psizecombo->text(i).toInt();
+ if (sz == psize) {
+ psizecombo->setCurrentItem(i);
+ break;
+ } else if(sz > psize) {
+ psizecombo->insertItem(i, QString::number(psize));
+ psizecombo->setCurrentItem(i);
+ break;
+ }
+ }
+
+ QStringList subs = QFont::substitutes(familysubcombo->currentText());
+ sublistbox->clear();
+ sublistbox->insertStringList(subs);
+
+ rtlExtensions->setChecked(settings.value(QLatin1String("useRtlExtensions"), false).toBool());
+
+#ifdef Q_WS_X11
+ inputStyle->setCurrentText(settings.value(QLatin1String("XIMInputStyle"), trUtf8("On The Spot")).toString());
+#else
+ inputStyle->hide();
+ inputStyleLabel->hide();
+#endif
+
+#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
+ QStringList inputMethods = QInputContextFactory::keys();
+ int inputMethodIndex = -1;
+ QString defaultInputMethod = settings.value(QLatin1String("DefaultInputMethod"), QLatin1String("xim")).toString();
+ for (int i = inputMethods.size()-1; i >= 0; --i) {
+ const QString &im = inputMethods.at(i);
+ if (im.contains(QLatin1String("imsw"))) {
+ inputMethods.removeAt(i);
+ if (inputMethodIndex > i)
+ --inputMethodIndex;
+ } else if (im == defaultInputMethod) {
+ inputMethodIndex = i;
+ }
+ }
+ if (inputMethodIndex == -1 && !inputMethods.isEmpty())
+ inputMethodIndex = 0;
+ inputMethod->addItems(inputMethods);
+ inputMethod->setCurrentIndex(inputMethodIndex);
+#else
+ inputMethod->hide();
+ inputMethodLabel->hide();
+#endif
+
+ fontembeddingcheckbox->setChecked(settings.value(QLatin1String("embedFonts"), true).toBool());
+ fontpaths = settings.value(QLatin1String("fontPath")).toStringList();
+ fontpathlistbox->insertStringList(fontpaths);
+
+ audiosinkCombo->addItem(tr("Auto (default)"), QLatin1String("Auto"));
+ audiosinkCombo->setItemData(audiosinkCombo->findText(tr("Auto (default)")),
+ tr("Choose audio output automatically."), Qt::ToolTipRole);
+ audiosinkCombo->addItem(tr("aRts"), QLatin1String("artssink"));
+ audiosinkCombo->setItemData(audiosinkCombo->findText(tr("aRts")),
+ tr("Experimental aRts support for GStreamer."), Qt::ToolTipRole);
+#ifndef QT_NO_GSTREAMER
+ phononVersionLabel->setText(QLatin1String(Phonon::phononVersion()));
+ if (gst_init_check(0, 0, 0)) {
+ gchar *versionString = gst_version_string();
+ gstversionLabel->setText(QLatin1String(versionString));
+ g_free(versionString);
+ GList* factoryList = gst_registry_get_feature_list(gst_registry_get_default (), GST_TYPE_ELEMENT_FACTORY);
+ QString name, klass, description;
+ for (GList* iter = g_list_first(factoryList) ; iter != NULL ; iter = g_list_next(iter)) {
+ GstPluginFeature *feature = GST_PLUGIN_FEATURE(iter->data);
+ klass = QLatin1String(gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature)));
+ if (klass == QLatin1String("Sink/Audio")) {
+ name = QLatin1String(GST_PLUGIN_FEATURE_NAME(feature));
+ if (name == QLatin1String("sfsink"))
+ continue; //useless to output audio to file when you cannot set the file path
+ else if (name == QLatin1String("autoaudiosink"))
+ continue; //This is used implicitly from the auto setting
+ GstElement *sink = gst_element_factory_make (qPrintable(name), NULL);
+ if (sink) {
+ description = QLatin1String(gst_element_factory_get_description (GST_ELEMENT_FACTORY(feature)));
+ audiosinkCombo->addItem(name, name);
+ audiosinkCombo->setItemData(audiosinkCombo->findText(name), description, Qt::ToolTipRole);
+ gst_object_unref (sink);
+ }
+ }
+ }
+ g_list_free(factoryList);
+ }
+#else
+ tab4->setEnabled(false);
+ phononLabel->setText(tr("Phonon GStreamer backend not available."));
+#endif
+
+ videomodeCombo->addItem(tr("Auto (default)"), QLatin1String("Auto"));
+ videomodeCombo->setItemData(videomodeCombo->findText(tr("Auto (default)")), tr("Choose render method automatically"), Qt::ToolTipRole);
+#ifdef Q_WS_X11
+ videomodeCombo->addItem(tr("X11"), QLatin1String("X11"));
+ videomodeCombo->setItemData(videomodeCombo->findText(tr("X11")), tr("Use X11 Overlays"), Qt::ToolTipRole);
+#endif
+#ifndef QT_NO_OPENGL
+ videomodeCombo->addItem(tr("OpenGL"), QLatin1String("OpenGL"));
+ videomodeCombo->setItemData(videomodeCombo->findText(tr("OpenGL")), tr("Use OpenGL if avaiable"), Qt::ToolTipRole);
+#endif
+ videomodeCombo->addItem(tr("Software"), QLatin1String("Software"));
+ videomodeCombo->setItemData(videomodeCombo->findText(tr("Software")), tr("Use simple software rendering"), Qt::ToolTipRole);
+
+ QString audioSink = settings.value(QLatin1String("audiosink"), QLatin1String("Auto")).toString();
+ QString videoMode = settings.value(QLatin1String("videomode"), QLatin1String("Auto")).toString();
+ audiosinkCombo->setCurrentItem(audiosinkCombo->findData(audioSink));
+ videomodeCombo->setCurrentItem(videomodeCombo->findData(videoMode));
+
+ settings.endGroup(); // Qt
+
+ helpview->setText(tr(appearance_text));
+
+ setModified(false);
+ updateStyleLayout();
+}
+
+
+MainWindow::~MainWindow()
+{
+}
+
+#ifdef Q_WS_X11
+extern void qt_x11_apply_settings_in_all_apps();
+#endif
+
+void MainWindow::fileSave()
+{
+ if (! modified) {
+ statusBar()->showMessage(tr("No changes to be saved."), 2000);
+ return;
+ }
+
+ statusBar()->showMessage(tr("Saving changes..."));
+
+ {
+ QSettings settings(QLatin1String("Trolltech"));
+ settings.beginGroup(QLatin1String("Qt"));
+ QFontDatabase db;
+ QFont font = db.font(familycombo->currentText(),
+ stylecombo->currentText(),
+ psizecombo->currentText().toInt());
+
+ QStringList actcg, inactcg, discg;
+ bool overrideDesktopSettings = (gstylecombo->currentText() != desktopThemeName);
+ if (overrideDesktopSettings) {
+ int i;
+ for (i = 0; i < QColorGroup::NColorRoles; i++)
+ actcg << editPalette.color(QPalette::Active,
+ (QColorGroup::ColorRole) i).name();
+ for (i = 0; i < QColorGroup::NColorRoles; i++)
+ inactcg << editPalette.color(QPalette::Inactive,
+ (QColorGroup::ColorRole) i).name();
+ for (i = 0; i < QColorGroup::NColorRoles; i++)
+ discg << editPalette.color(QPalette::Disabled,
+ (QColorGroup::ColorRole) i).name();
+ }
+
+ settings.setValue(QLatin1String("font"), font.toString());
+ settings.setValue(QLatin1String("Palette/active"), actcg);
+ settings.setValue(QLatin1String("Palette/inactive"), inactcg);
+ settings.setValue(QLatin1String("Palette/disabled"), discg);
+
+ settings.setValue(QLatin1String("fontPath"), fontpaths);
+ settings.setValue(QLatin1String("embedFonts"), fontembeddingcheckbox->isChecked());
+ settings.setValue(QLatin1String("style"), overrideDesktopSettings ? gstylecombo->currentText() : QString());
+
+ settings.setValue(QLatin1String("doubleClickInterval"), dcispin->value());
+ settings.setValue(QLatin1String("cursorFlashTime"), cfispin->value() == 9 ? 0 : cfispin->value() );
+ settings.setValue(QLatin1String("wheelScrollLines"), wslspin->value());
+ settings.setValue(QLatin1String("resolveSymlinks"), resolvelinks->isChecked());
+
+ QSize strut(strutwidth->value(), strutheight->value());
+ settings.setValue(QLatin1String("globalStrut/width"), strut.width());
+ settings.setValue(QLatin1String("globalStrut/height"), strut.height());
+
+ settings.setValue(QLatin1String("useRtlExtensions"), rtlExtensions->isChecked());
+
+#ifdef Q_WS_X11
+ QString style = inputStyle->currentText();
+ QString str = QLatin1String("On The Spot");
+ if ( style == trUtf8( "Over The Spot" ) )
+ str = QLatin1String("Over The Spot");
+ else if ( style == trUtf8( "Off The Spot" ) )
+ str = QLatin1String("Off The Spot");
+ else if ( style == trUtf8( "Root" ) )
+ str = QLatin1String("Root");
+ settings.setValue( QLatin1String("XIMInputStyle"), str );
+#endif
+#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
+ settings.setValue(QLatin1String("DefaultInputMethod"), inputMethod->currentText());
+#endif
+
+ QString audioSink = settings.value(QLatin1String("audiosink"), QLatin1String("Auto")).toString();
+ QString videoMode = settings.value(QLatin1String("videomode"), QLatin1String("Auto")).toString();
+ settings.setValue(QLatin1String("audiosink"), audiosinkCombo->itemData(audiosinkCombo->currentIndex()));
+ settings.setValue(QLatin1String("videomode"), videomodeCombo->itemData(videomodeCombo->currentIndex()));
+
+ QStringList effects;
+ if (effectcheckbox->isChecked()) {
+ effects << QLatin1String("general");
+
+ switch (menueffect->currentItem()) {
+ case 1: effects << QLatin1String("animatemenu"); break;
+ case 2: effects << QLatin1String("fademenu"); break;
+ }
+
+ switch (comboeffect->currentItem()) {
+ case 1: effects << QLatin1String("animatecombo"); break;
+ }
+
+ switch (tooltipeffect->currentItem()) {
+ case 1: effects << QLatin1String("animatetooltip"); break;
+ case 2: effects << QLatin1String("fadetooltip"); break;
+ }
+
+ switch ( toolboxeffect->currentItem() ) {
+ case 1: effects << QLatin1String("animatetoolbox"); break;
+ }
+ } else
+ effects << QLatin1String("none");
+ settings.setValue(QLatin1String("GUIEffects"), effects);
+
+ QStringList familysubs = QFont::substitutions();
+ QStringList::Iterator fit = familysubs.begin();
+ settings.beginGroup(QLatin1String("Font Substitutions"));
+ while (fit != familysubs.end()) {
+ QStringList subs = QFont::substitutes(*fit);
+ settings.setValue(*fit, subs);
+ fit++;
+ }
+ settings.endGroup(); // Font Substitutions
+ settings.endGroup(); // Qt
+ }
+
+#if defined(Q_WS_X11)
+ qt_x11_apply_settings_in_all_apps();
+#endif // Q_WS_X11
+
+ setModified(false);
+ statusBar()->showMessage(QLatin1String("Saved changes."));
+}
+
+
+void MainWindow::fileExit()
+{
+ qApp->closeAllWindows();
+}
+
+
+void MainWindow::setModified(bool m)
+{
+ if (modified == m)
+ return;
+
+ modified = m;
+ fileSaveAction->setEnabled(m);
+}
+
+
+void MainWindow::buildPalette()
+{
+ int i;
+ QColorGroup cg;
+ QColor btn = buttonMainColor->color();
+ QColor back = buttonMainColor2->color();
+ QPalette automake( btn, back );
+
+ for (i = 0; i<9; i++)
+ cg.setColor( centralFromItem(i), automake.active().color( centralFromItem(i) ) );
+
+ editPalette.setActive( cg );
+ buildActiveEffect();
+
+ cg = editPalette.inactive();
+
+ QPalette temp( editPalette.active().color( QColorGroup::Button ),
+ editPalette.active().color( QColorGroup::Window ) );
+
+ for (i = 0; i<9; i++)
+ cg.setColor( centralFromItem(i), temp.inactive().color( centralFromItem(i) ) );
+
+ editPalette.setInactive( cg );
+ buildInactiveEffect();
+
+ cg = editPalette.disabled();
+
+ for (i = 0; i<9; i++)
+ cg.setColor( centralFromItem(i), temp.disabled().color( centralFromItem(i) ) );
+
+ editPalette.setDisabled( cg );
+ buildDisabledEffect();
+
+ updateColorButtons();
+
+ setModified(true);
+}
+
+
+void MainWindow::buildActiveEffect()
+{
+ QColorGroup cg = editPalette.active();
+ QColor btn = cg.color( QColorGroup::Button );
+
+ QPalette temp( btn, btn );
+
+ for (int i = 0; i<5; i++)
+ cg.setColor( effectFromItem(i), temp.active().color( effectFromItem(i) ) );
+
+ editPalette.setActive( cg );
+ setPreviewPalette( editPalette );
+
+ updateColorButtons();
+}
+
+
+void MainWindow::buildInactive()
+{
+ editPalette.setInactive( editPalette.active() );
+ buildInactiveEffect();
+}
+
+
+void MainWindow::buildInactiveEffect()
+{
+ QColorGroup cg = editPalette.inactive();
+
+ QColor light, midlight, mid, dark, shadow;
+ QColor btn = cg.color( QColorGroup::Button );
+
+ light = btn.light(150);
+ midlight = btn.light(115);
+ mid = btn.dark(150);
+ dark = btn.dark();
+ shadow = Qt::black;
+
+ cg.setColor( QColorGroup::Light, light );
+ cg.setColor( QColorGroup::Midlight, midlight );
+ cg.setColor( QColorGroup::Mid, mid );
+ cg.setColor( QColorGroup::Dark, dark );
+ cg.setColor( QColorGroup::Shadow, shadow );
+
+ editPalette.setInactive( cg );
+ setPreviewPalette( editPalette );
+ updateColorButtons();
+}
+
+
+void MainWindow::buildDisabled()
+{
+ QColorGroup cg = editPalette.active();
+ cg.setColor( QColorGroup::ButtonText, Qt::darkGray );
+ cg.setColor( QColorGroup::WindowText, Qt::darkGray );
+ cg.setColor( QColorGroup::Text, Qt::darkGray );
+ cg.setColor( QColorGroup::HighlightedText, Qt::darkGray );
+ editPalette.setDisabled( cg );
+
+ buildDisabledEffect();
+}
+
+
+void MainWindow::buildDisabledEffect()
+{
+ QColorGroup cg = editPalette.disabled();
+
+ QColor light, midlight, mid, dark, shadow;
+ QColor btn = cg.color( QColorGroup::Button );
+
+ light = btn.light(150);
+ midlight = btn.light(115);
+ mid = btn.dark(150);
+ dark = btn.dark();
+ shadow = Qt::black;
+
+ cg.setColor( QColorGroup::Light, light );
+ cg.setColor( QColorGroup::Midlight, midlight );
+ cg.setColor( QColorGroup::Mid, mid );
+ cg.setColor( QColorGroup::Dark, dark );
+ cg.setColor( QColorGroup::Shadow, shadow );
+
+ editPalette.setDisabled( cg );
+ setPreviewPalette( editPalette );
+ updateColorButtons();
+}
+
+
+void MainWindow::setPreviewPalette( const QPalette& pal )
+{
+ QColorGroup cg;
+
+ switch (paletteCombo->currentItem()) {
+ case 0:
+ default:
+ cg = pal.active();
+ break;
+ case 1:
+ cg = pal.inactive();
+ break;
+ case 2:
+ cg = pal.disabled();
+ break;
+ }
+ previewPalette.setActive( cg );
+ previewPalette.setInactive( cg );
+ previewPalette.setDisabled( cg );
+
+ previewFrame->setPreviewPalette(previewPalette);
+}
+
+
+void MainWindow::updateColorButtons()
+{
+ buttonMainColor->setColor( editPalette.active().color( QColorGroup::Button ));
+ buttonMainColor2->setColor( editPalette.active().color( QColorGroup::Window ));
+}
+
+
+void MainWindow::tunePalette()
+{
+ bool ok;
+ QPalette pal = PaletteEditorAdvanced::getPalette(&ok, editPalette,
+ backgroundMode(), this);
+ if (! ok)
+ return;
+
+ editPalette = pal;
+ setPreviewPalette(editPalette);
+ setModified(true);
+}
+
+
+void MainWindow::paletteSelected(int)
+{
+ setPreviewPalette(editPalette);
+}
+
+void MainWindow::updateStyleLayout()
+{
+ QString currentStyle = gstylecombo->currentText();
+ bool autoStyle = (currentStyle == desktopThemeName);
+ previewFrame->setPreviewVisible(!autoStyle);
+ groupAutoPalette->setEnabled(currentStyle.toLower() != QLatin1String("gtk") && !autoStyle);
+}
+
+void MainWindow::styleSelected(const QString &stylename)
+{
+ QStyle *style = 0;
+ if (stylename == desktopThemeName) {
+ setModified(true);
+ } else {
+ style = QStyleFactory::create(stylename);
+ if (!style)
+ return;
+ setStyleHelper(previewFrame, style);
+ delete previewstyle;
+ previewstyle = style;
+ setModified(true);
+ }
+ updateStyleLayout();
+}
+
+
+void MainWindow::familySelected(const QString &family)
+{
+ QFontDatabase db;
+ QStringList styles = db.styles(family);
+ stylecombo->clear();
+ stylecombo->insertStringList(styles);
+ familysubcombo->insertItem(family);
+ buildFont();
+}
+
+
+void MainWindow::buildFont()
+{
+ QFontDatabase db;
+ QFont font = db.font(familycombo->currentText(),
+ stylecombo->currentText(),
+ psizecombo->currentText().toInt());
+ samplelineedit->setFont(font);
+ setModified(true);
+}
+
+
+void MainWindow::substituteSelected(const QString &family)
+{
+ QStringList subs = QFont::substitutes(family);
+ sublistbox->clear();
+ sublistbox->insertStringList(subs);
+}
+
+
+void MainWindow::removeSubstitute()
+{
+ if (sublistbox->currentItem() < 0 ||
+ uint(sublistbox->currentItem()) > sublistbox->count())
+ return;
+
+ int item = sublistbox->currentItem();
+ QStringList subs = QFont::substitutes(familysubcombo->currentText());
+ subs.remove(subs.at(sublistbox->currentItem()));
+ sublistbox->clear();
+ sublistbox->insertStringList(subs);
+ if (uint(item) > sublistbox->count())
+ item = int(sublistbox->count()) - 1;
+ sublistbox->setCurrentItem(item);
+ QFont::removeSubstitution(familysubcombo->currentText());
+ QFont::insertSubstitutions(familysubcombo->currentText(), subs);
+ setModified(true);
+}
+
+
+void MainWindow::addSubstitute()
+{
+ if (sublistbox->currentItem() < 0 ||
+ uint(sublistbox->currentItem()) > sublistbox->count()) {
+ QFont::insertSubstitution(familysubcombo->currentText(), choosesubcombo->currentText());
+ QStringList subs = QFont::substitutes(familysubcombo->currentText());
+ sublistbox->clear();
+ sublistbox->insertStringList(subs);
+ setModified(true);
+ return;
+ }
+
+ int item = sublistbox->currentItem();
+ QFont::insertSubstitution(familysubcombo->currentText(), choosesubcombo->currentText());
+ QStringList subs = QFont::substitutes(familysubcombo->currentText());
+ sublistbox->clear();
+ sublistbox->insertStringList(subs);
+ sublistbox->setCurrentItem(item);
+ setModified(true);
+}
+
+
+void MainWindow::downSubstitute()
+{
+ if (sublistbox->currentItem() < 0 ||
+ uint(sublistbox->currentItem()) >= sublistbox->count())
+ return;
+
+ int item = sublistbox->currentItem();
+ QStringList subs = QFont::substitutes(familysubcombo->currentText());
+ QString fam = subs.at(item);
+ subs.removeAt(item);
+ subs.insert(item+1, fam);
+ sublistbox->clear();
+ sublistbox->insertStringList(subs);
+ sublistbox->setCurrentItem(item + 1);
+ QFont::removeSubstitution(familysubcombo->currentText());
+ QFont::insertSubstitutions(familysubcombo->currentText(), subs);
+ setModified(true);
+}
+
+
+void MainWindow::upSubstitute()
+{
+ if (sublistbox->currentItem() < 1)
+ return;
+
+ int item = sublistbox->currentItem();
+ QStringList subs = QFont::substitutes(familysubcombo->currentText());
+ QString fam = subs.at(item);
+ subs.removeAt(item);
+ subs.insert(item-1, fam);
+ sublistbox->clear();
+ sublistbox->insertStringList(subs);
+ sublistbox->setCurrentItem(item - 1);
+ QFont::removeSubstitution(familysubcombo->currentText());
+ QFont::insertSubstitutions(familysubcombo->currentText(), subs);
+ setModified(true);
+}
+
+
+void MainWindow::removeFontpath()
+{
+ if (fontpathlistbox->currentItem() < 0 ||
+ uint(fontpathlistbox->currentItem()) > fontpathlistbox->count())
+ return;
+
+ int item = fontpathlistbox->currentItem();
+ fontpaths.remove(fontpaths.at(fontpathlistbox->currentItem()));
+ fontpathlistbox->clear();
+ fontpathlistbox->insertStringList(fontpaths);
+ if (uint(item) > fontpathlistbox->count())
+ item = int(fontpathlistbox->count()) - 1;
+ fontpathlistbox->setCurrentItem(item);
+ setModified(true);
+}
+
+
+void MainWindow::addFontpath()
+{
+ if (fontpathlineedit->text().isEmpty())
+ return;
+
+ if (fontpathlistbox->currentItem() < 0 ||
+ uint(fontpathlistbox->currentItem()) > fontpathlistbox->count()) {
+ fontpaths.append(fontpathlineedit->text());
+ fontpathlistbox->clear();
+ fontpathlistbox->insertStringList(fontpaths);
+ setModified(true);
+
+ return;
+ }
+
+ int item = fontpathlistbox->currentItem();
+ fontpaths.insert(fontpathlistbox->currentItem()+1,
+ fontpathlineedit->text());
+ fontpathlistbox->clear();
+ fontpathlistbox->insertStringList(fontpaths);
+ fontpathlistbox->setCurrentItem(item);
+ setModified(true);
+}
+
+
+void MainWindow::downFontpath()
+{
+ if (fontpathlistbox->currentItem() < 0 ||
+ uint(fontpathlistbox->currentItem()) >= fontpathlistbox->count() - 1)
+ return;
+
+ int item = fontpathlistbox->currentItem();
+ QString fam = fontpaths.at(item);
+ fontpaths.removeAt(item);
+ fontpaths.insert(item+1, fam);
+ fontpathlistbox->clear();
+ fontpathlistbox->insertStringList(fontpaths);
+ fontpathlistbox->setCurrentItem(item + 1);
+ setModified(true);
+}
+
+
+void MainWindow::upFontpath()
+{
+ if (fontpathlistbox->currentItem() < 1)
+ return;
+
+ int item = fontpathlistbox->currentItem();
+ QString fam = fontpaths.at(item);
+ fontpaths.removeAt(item);
+ fontpaths.insert(item-1, fam);
+ fontpathlistbox->clear();
+ fontpathlistbox->insertStringList(fontpaths);
+ fontpathlistbox->setCurrentItem(item - 1);
+ setModified(true);
+}
+
+
+void MainWindow::browseFontpath()
+{
+ QString dirname = QFileDialog::getExistingDirectory(QString(), this, 0,
+ tr("Select a Directory"));
+ if (dirname.isNull())
+ return;
+
+ fontpathlineedit->setText(dirname);
+}
+
+
+void MainWindow::somethingModified()
+{
+ setModified(true);
+}
+
+
+void MainWindow::helpAbout()
+{
+ QMessageBox box(this);
+ box.setText(tr("<h3>%1</h3>"
+ "<br/>Version %2"
+#if QT_EDITION == QT_EDITION_OPENSOURCE
+ " Open Source Edition</center><p>"
+ "This version of Qt Configuration is part of the Qt Open Source Edition, for use "
+ "in the development of Open Source applications. "
+ "Qt is a comprehensive C++ framework for cross-platform application "
+ "development.<br/><br/>"
+ "You need a commercial Qt license for development of proprietary (closed "
+ "source) applications. Please see <tt>http://qtsoftware.com/company/model"
+ ".html</tt> for an overview of Qt licensing."
+#else
+ "</center><p>This program is licensed to you under the terms of the "
+ "Qt Commercial License Agreement. For details, see the file LICENSE "
+ "that came with this software distribution."
+#endif
+ "<br/><br/>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)."
+ "<br/><br/>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
+ " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
+ " PARTICULAR PURPOSE.<br/> ")
+ .arg(tr("Qt Configuration")).arg(QLatin1String(QT_VERSION_STR)));
+ box.setWindowTitle(tr("Qt Configuration"));
+ box.setIcon(QMessageBox::NoIcon);
+ box.exec();
+}
+
+
+void MainWindow::helpAboutQt()
+{
+ QMessageBox::aboutQt(this, tr("Qt Configuration"));
+}
+
+
+void MainWindow::pageChanged(QWidget *page)
+{
+ if (page == tab)
+ helpview->setText(tr(interface_text));
+ else if (page == tab1)
+ helpview->setText(tr(appearance_text));
+ else if (page == tab2)
+ helpview->setText(tr(font_text));
+ else if (page == tab3)
+ helpview->setText(tr(printer_text));
+ else if (page == tab4)
+ helpview->setText(tr(phonon_text));
+}
+
+
+void MainWindow::closeEvent(QCloseEvent *e)
+{
+ if (modified) {
+ switch(QMessageBox::warning(this, tr("Save Changes"),
+ tr("Save changes to settings?"),
+ tr("&Yes"), tr("&No"), tr("&Cancel"), 0, 2)) {
+ case 0: // save
+ qApp->processEvents();
+ fileSave();
+
+ // fall through intended
+ case 1: // don't save
+ e->accept();
+ break;
+
+ case 2: // cancel
+ e->ignore();
+ break;
+
+ default: break;
+ }
+ } else
+ e->accept();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/mainwindow.h b/tools/qtconfig/mainwindow.h
new file mode 100644
index 0000000000..ac16232526
--- /dev/null
+++ b/tools/qtconfig/mainwindow.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "mainwindowbase.h"
+
+QT_BEGIN_NAMESPACE
+
+class MainWindow : public MainWindowBase
+{
+ Q_OBJECT
+
+public:
+ MainWindow();
+ ~MainWindow();
+
+ void closeEvent(QCloseEvent *);
+
+
+public slots:
+ virtual void buildPalette();
+ virtual void buildFont();
+ virtual void tunePalette();
+ virtual void paletteSelected(int);
+ virtual void styleSelected(const QString &);
+ virtual void familySelected(const QString &);
+ virtual void substituteSelected(const QString &);
+ virtual void removeSubstitute();
+ virtual void addSubstitute();
+ virtual void downSubstitute();
+ virtual void upSubstitute();
+ virtual void removeFontpath();
+ virtual void addFontpath();
+ virtual void downFontpath();
+ virtual void upFontpath();
+ virtual void browseFontpath();
+ virtual void fileSave();
+ virtual void fileExit();
+ virtual void somethingModified();
+ virtual void helpAbout();
+ virtual void helpAboutQt();
+ virtual void pageChanged(QWidget *);
+
+
+private:
+ void buildActive();
+ void buildActiveEffect();
+ void buildInactive();
+ void buildInactiveEffect();
+ void buildDisabled();
+ void buildDisabledEffect();
+
+ void updateColorButtons();
+ void updateFontSample();
+ void updateStyleLayout();
+
+ void setPreviewPalette(const QPalette &);
+
+ void setModified(bool);
+
+ QString desktopThemeName;
+ QPalette editPalette, previewPalette;
+ QStyle *previewstyle;
+ QStringList fontpaths;
+ bool modified;
+};
+
+QT_END_NAMESPACE
+
+#endif // MAINWINDOW_H
diff --git a/tools/qtconfig/mainwindowbase.cpp b/tools/qtconfig/mainwindowbase.cpp
new file mode 100644
index 0000000000..9f90479c75
--- /dev/null
+++ b/tools/qtconfig/mainwindowbase.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindowbase.h"
+#include "colorbutton.h"
+#include "previewframe.h"
+
+#include <QVariant>
+#include <QImage>
+#include <QPixmap>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Constructs a MainWindowBase as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ *
+ */
+MainWindowBase::MainWindowBase(QWidget* parent, const char* name, Qt::WindowFlags fl)
+ : Q3MainWindow(parent, name, fl)
+{
+ setupUi(this);
+
+ (void)statusBar();
+
+ // signals and slots connections
+ connect(fontpathlineedit, SIGNAL(returnPressed()), this, SLOT(addFontpath()));
+ connect(PushButton15, SIGNAL(clicked()), this, SLOT(addFontpath()));
+ connect(PushButton1, SIGNAL(clicked()), this, SLOT(addSubstitute()));
+ connect(PushButton14, SIGNAL(clicked()), this, SLOT(browseFontpath()));
+ connect(stylecombo, SIGNAL(activated(int)), this, SLOT(buildFont()));
+ connect(psizecombo, SIGNAL(activated(int)), this, SLOT(buildFont()));
+ connect(PushButton12, SIGNAL(clicked()), this, SLOT(downFontpath()));
+ connect(PushButton3, SIGNAL(clicked()), this, SLOT(downSubstitute()));
+ connect(familycombo, SIGNAL(activated(QString)), this, SLOT(familySelected(QString)));
+ connect(fileExitAction, SIGNAL(activated()), this, SLOT(fileExit()));
+ connect(fileSaveAction, SIGNAL(activated()), this, SLOT(fileSave()));
+ connect(helpAboutAction, SIGNAL(activated()), this, SLOT(helpAbout()));
+ connect(helpAboutQtAction, SIGNAL(activated()), this, SLOT(helpAboutQt()));
+ connect(TabWidget3, SIGNAL(currentChanged(QWidget*)), this, SLOT(pageChanged(QWidget*)));
+ connect(paletteCombo, SIGNAL(activated(int)), this, SLOT(paletteSelected(int)));
+ connect(PushButton13, SIGNAL(clicked()), this, SLOT(removeFontpath()));
+ connect(PushButton4, SIGNAL(clicked()), this, SLOT(removeSubstitute()));
+ connect(effectcheckbox, SIGNAL(toggled(bool)), effectbase, SLOT(setEnabled(bool)));
+ connect(fontembeddingcheckbox, SIGNAL(toggled(bool)), GroupBox10, SLOT(setEnabled(bool)));
+ connect(toolboxeffect, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(dcispin, SIGNAL(valueChanged(int)), this, SLOT(somethingModified()));
+ connect(cfispin, SIGNAL(valueChanged(int)), this, SLOT(somethingModified()));
+ connect(wslspin, SIGNAL(valueChanged(int)), this, SLOT(somethingModified()));
+ connect(menueffect, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(comboeffect, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(audiosinkCombo, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(videomodeCombo, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(tooltipeffect, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(strutwidth, SIGNAL(valueChanged(int)), this, SLOT(somethingModified()));
+ connect(strutheight, SIGNAL(valueChanged(int)), this, SLOT(somethingModified()));
+ connect(effectcheckbox, SIGNAL(toggled(bool)), this, SLOT(somethingModified()));
+ connect(resolvelinks, SIGNAL(toggled(bool)), this, SLOT(somethingModified()));
+ connect(fontembeddingcheckbox, SIGNAL(clicked()), this, SLOT(somethingModified()));
+ connect(rtlExtensions, SIGNAL(toggled(bool)), this, SLOT(somethingModified()));
+ connect(inputStyle, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(inputMethod, SIGNAL(activated(int)), this, SLOT(somethingModified()));
+ connect(gstylecombo, SIGNAL(activated(QString)), this, SLOT(styleSelected(QString)));
+ connect(familysubcombo, SIGNAL(activated(QString)), this, SLOT(substituteSelected(QString)));
+ connect(btnAdvanced, SIGNAL(clicked()), this, SLOT(tunePalette()));
+ connect(PushButton11, SIGNAL(clicked()), this, SLOT(upFontpath()));
+ connect(PushButton2, SIGNAL(clicked()), this, SLOT(upSubstitute()));
+ init();
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+MainWindowBase::~MainWindowBase()
+{
+ destroy();
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void MainWindowBase::languageChange()
+{
+ retranslateUi(this);
+}
+
+void MainWindowBase::init()
+{
+}
+
+void MainWindowBase::destroy()
+{
+}
+
+void MainWindowBase::addFontpath()
+{
+ qWarning("MainWindowBase::addFontpath(): Not implemented yet");
+}
+
+void MainWindowBase::addSubstitute()
+{
+ qWarning("MainWindowBase::addSubstitute(): Not implemented yet");
+}
+
+void MainWindowBase::browseFontpath()
+{
+ qWarning("MainWindowBase::browseFontpath(): Not implemented yet");
+}
+
+void MainWindowBase::buildFont()
+{
+ qWarning("MainWindowBase::buildFont(): Not implemented yet");
+}
+
+void MainWindowBase::buildPalette()
+{
+ qWarning("MainWindowBase::buildPalette(): Not implemented yet");
+}
+
+void MainWindowBase::downFontpath()
+{
+ qWarning("MainWindowBase::downFontpath(): Not implemented yet");
+}
+
+void MainWindowBase::downSubstitute()
+{
+ qWarning("MainWindowBase::downSubstitute(): Not implemented yet");
+}
+
+void MainWindowBase::familySelected( const QString &)
+{
+ qWarning("MainWindowBase::familySelected( const QString &): Not implemented yet");
+}
+
+void MainWindowBase::fileExit()
+{
+ qWarning("MainWindowBase::fileExit(): Not implemented yet");
+}
+
+void MainWindowBase::fileSave()
+{
+ qWarning("MainWindowBase::fileSave(): Not implemented yet");
+}
+
+void MainWindowBase::helpAbout()
+{
+ qWarning("MainWindowBase::helpAbout(): Not implemented yet");
+}
+
+void MainWindowBase::helpAboutQt()
+{
+ qWarning("MainWindowBase::helpAboutQt(): Not implemented yet");
+}
+
+void MainWindowBase::new_slot()
+{
+ qWarning("MainWindowBase::new_slot(): Not implemented yet");
+}
+
+void MainWindowBase::pageChanged( QWidget *)
+{
+ qWarning("MainWindowBase::pageChanged( QWidget *): Not implemented yet");
+}
+
+void MainWindowBase::paletteSelected(int)
+{
+ qWarning("MainWindowBase::paletteSelected(int): Not implemented yet");
+}
+
+void MainWindowBase::removeFontpath()
+{
+ qWarning("MainWindowBase::removeFontpath(): Not implemented yet");
+}
+
+void MainWindowBase::removeSubstitute()
+{
+ qWarning("MainWindowBase::removeSubstitute(): Not implemented yet");
+}
+
+void MainWindowBase::somethingModified()
+{
+ qWarning("MainWindowBase::somethingModified(): Not implemented yet");
+}
+
+void MainWindowBase::styleSelected( const QString &)
+{
+ qWarning("MainWindowBase::styleSelected( const QString &): Not implemented yet");
+}
+
+void MainWindowBase::substituteSelected( const QString &)
+{
+ qWarning("MainWindowBase::substituteSelected( const QString &): Not implemented yet");
+}
+
+void MainWindowBase::tunePalette()
+{
+ qWarning("MainWindowBase::tunePalette(): Not implemented yet");
+}
+
+void MainWindowBase::upFontpath()
+{
+ qWarning("MainWindowBase::upFontpath(): Not implemented yet");
+}
+
+void MainWindowBase::upSubstitute()
+{
+ qWarning("MainWindowBase::upSubstitute(): Not implemented yet");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/mainwindowbase.h b/tools/qtconfig/mainwindowbase.h
new file mode 100644
index 0000000000..f54b433f80
--- /dev/null
+++ b/tools/qtconfig/mainwindowbase.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOWBASE_H
+#define MAINWINDOWBASE_H
+
+#include "ui_mainwindowbase.h"
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class ColorButton;
+class PreviewFrame;
+
+class MainWindowBase : public Q3MainWindow, public Ui::MainWindowBase
+{
+ Q_OBJECT
+
+public:
+ MainWindowBase(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = Qt::Window);
+ ~MainWindowBase();
+
+public slots:
+ virtual void addFontpath();
+ virtual void addSubstitute();
+ virtual void browseFontpath();
+ virtual void buildFont();
+ virtual void buildPalette();
+ virtual void downFontpath();
+ virtual void downSubstitute();
+ virtual void familySelected( const QString & );
+ virtual void fileExit();
+ virtual void fileSave();
+ virtual void helpAbout();
+ virtual void helpAboutQt();
+ virtual void new_slot();
+ virtual void pageChanged( QWidget * );
+ virtual void paletteSelected( int );
+ virtual void removeFontpath();
+ virtual void removeSubstitute();
+ virtual void somethingModified();
+ virtual void styleSelected( const QString & );
+ virtual void substituteSelected( const QString & );
+ virtual void tunePalette();
+ virtual void upFontpath();
+ virtual void upSubstitute();
+
+protected slots:
+ virtual void languageChange();
+
+ virtual void init();
+ virtual void destroy();
+};
+
+QT_END_NAMESPACE
+
+#endif // MAINWINDOWBASE_H
diff --git a/tools/qtconfig/mainwindowbase.ui b/tools/qtconfig/mainwindowbase.ui
new file mode 100644
index 0000000000..747ca28c5f
--- /dev/null
+++ b/tools/qtconfig/mainwindowbase.ui
@@ -0,0 +1,1384 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>MainWindowBase</class>
+ <widget class="Q3MainWindow" name="MainWindowBase">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>815</width>
+ <height>716</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Qt Configuration</string>
+ </property>
+ <widget class="QWidget" name="widget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>26</y>
+ <width>815</width>
+ <height>690</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QTextEdit" name="helpview">
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QTabWidget" name="TabWidget3">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab1">
+ <attribute name="title">
+ <string>Appearance</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="GroupBox40">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>GUI Style</string>
+ </property>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="gstylebuddy">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Select GUI &amp;Style:</string>
+ </property>
+ <property name="buddy">
+ <cstring>gstylecombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="gstylecombo"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="groupPreview">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Preview</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QLabel" name="TextLabel1">
+ <property name="text">
+ <string>Select &amp;Palette:</string>
+ </property>
+ <property name="buddy">
+ <cstring>paletteCombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="paletteCombo">
+ <item>
+ <property name="text">
+ <string>Active Palette</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Inactive Palette</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled Palette</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="PreviewFrame" name="previewFrame" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>410</width>
+ <height>260</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QGroupBox" name="groupAutoPalette">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>400</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Build Palette</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QWidget" name="colorConfig" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="labelMainColor">
+ <property name="text">
+ <string>&amp;3-D Effects:</string>
+ </property>
+ <property name="buddy">
+ <cstring>buttonMainColor</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ColorButton" name="buttonMainColor" native="true"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelMainColor2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="midLineWidth">
+ <number>0</number>
+ </property>
+ <property name="text">
+ <string>Window Back&amp;ground:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignVCenter</set>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="buddy">
+ <cstring>buttonMainColor2</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ColorButton" name="buttonMainColor2" native="true"/>
+ </item>
+ <item>
+ <spacer name="spacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>70</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAdvanced">
+ <property name="text">
+ <string>&amp;Tune Palette...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelKDENote">
+ <property name="text">
+ <string>Please use the KDE Control Center to set the palette.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab2">
+ <attribute name="title">
+ <string>Fonts</string>
+ </attribute>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QGroupBox" name="GroupBox1">
+ <property name="title">
+ <string>Default Font</string>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="stylecombo">
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="familycombo">
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="psizecombo">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="stylebuddy">
+ <property name="text">
+ <string>&amp;Style:</string>
+ </property>
+ <property name="buddy">
+ <cstring>stylecombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="psizebuddy">
+ <property name="text">
+ <string>&amp;Point Size:</string>
+ </property>
+ <property name="buddy">
+ <cstring>psizecombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="familybuddy">
+ <property name="text">
+ <string>F&amp;amily:</string>
+ </property>
+ <property name="buddy">
+ <cstring>familycombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QLineEdit" name="samplelineedit">
+ <property name="text">
+ <string>Sample Text</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="GroupBox2">
+ <property name="title">
+ <string>Font Substitution</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="famsubbuddy">
+ <property name="text">
+ <string>S&amp;elect or Enter a Family:</string>
+ </property>
+ <property name="buddy">
+ <cstring>familysubcombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="familysubcombo">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="Line1">
+ <property name="frameShape">
+ <enum>QFrame::HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="TextLabel5">
+ <property name="text">
+ <string>Current Substitutions:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Q3ListBox" name="sublistbox"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="PushButton2">
+ <property name="text">
+ <string>Up</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="PushButton3">
+ <property name="text">
+ <string>Down</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="PushButton4">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="Line2">
+ <property name="frameShape">
+ <enum>QFrame::HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="choosebuddy">
+ <property name="text">
+ <string>Select s&amp;ubstitute Family:</string>
+ </property>
+ <property name="buddy">
+ <cstring>choosesubcombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="choosesubcombo">
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="PushButton1">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Interface</string>
+ </attribute>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QGroupBox" name="GroupBox4">
+ <property name="title">
+ <string>Feel Settings</string>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="dcispin">
+ <property name="suffix">
+ <string> ms</string>
+ </property>
+ <property name="minimum">
+ <number>10</number>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="dcibuddy">
+ <property name="text">
+ <string>&amp;Double Click Interval:</string>
+ </property>
+ <property name="buddy">
+ <cstring>dcispin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="cfispin">
+ <property name="specialValueText">
+ <string>No blinking</string>
+ </property>
+ <property name="suffix">
+ <string> ms</string>
+ </property>
+ <property name="minimum">
+ <number>9</number>
+ </property>
+ <property name="maximum">
+ <number>10000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="cfibuddy">
+ <property name="text">
+ <string>&amp;Cursor Flash Time:</string>
+ </property>
+ <property name="buddy">
+ <cstring>cfispin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="wslspin">
+ <property name="suffix">
+ <string> lines</string>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="wslbuddy">
+ <property name="text">
+ <string>Wheel &amp;Scroll Lines:</string>
+ </property>
+ <property name="buddy">
+ <cstring>wslspin</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QCheckBox" name="resolvelinks">
+ <property name="text">
+ <string>Resolve symlinks in URLs</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="GroupBox3">
+ <property name="title">
+ <string>GUI Effects</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="effectcheckbox">
+ <property name="text">
+ <string>&amp;Enable</string>
+ </property>
+ <property name="shortcut">
+ <string>Alt+E</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="Q3Frame" name="effectbase">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="meffectbuddy">
+ <property name="text">
+ <string>&amp;Menu Effect:</string>
+ </property>
+ <property name="buddy">
+ <cstring>menueffect</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="ceffectbuddy">
+ <property name="text">
+ <string>C&amp;omboBox Effect:</string>
+ </property>
+ <property name="buddy">
+ <cstring>comboeffect</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="teffectbuddy">
+ <property name="text">
+ <string>&amp;ToolTip Effect:</string>
+ </property>
+ <property name="buddy">
+ <cstring>tooltipeffect</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="beffectbuddy">
+ <property name="text">
+ <string>Tool&amp;Box Effect:</string>
+ </property>
+ <property name="buddy">
+ <cstring>toolboxeffect</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="menueffect">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Fade</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="comboeffect">
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="tooltipeffect">
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Fade</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="toolboxeffect">
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="GroupBox5">
+ <property name="title">
+ <string>Global Strut</string>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="swbuddy">
+ <property name="text">
+ <string>Minimum &amp;Width:</string>
+ </property>
+ <property name="buddy">
+ <cstring>strutwidth</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="shbuddy">
+ <property name="text">
+ <string>Minimum Hei&amp;ght:</string>
+ </property>
+ <property name="buddy">
+ <cstring>strutheight</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="strutwidth">
+ <property name="suffix">
+ <string> pixels</string>
+ </property>
+ <property name="maximum">
+ <number>1000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="strutheight">
+ <property name="suffix">
+ <string> pixels</string>
+ </property>
+ <property name="maximum">
+ <number>1000</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="rtlExtensions">
+ <property name="text">
+ <string>Enhanced support for languages written right-to-left</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="inputStyleLabel">
+ <property name="text">
+ <string>XIM Input Style:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="inputStyle">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>On The Spot</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Over The Spot</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Off The Spot</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Root</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="inputMethodLabel">
+ <property name="text">
+ <string>Default Input Method:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="inputMethod">
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab3">
+ <attribute name="title">
+ <string>Printer</string>
+ </attribute>
+ <layout class="QVBoxLayout">
+ <item>
+ <widget class="QCheckBox" name="fontembeddingcheckbox">
+ <property name="text">
+ <string>Enable Font embedding</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="GroupBox10">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Font Paths</string>
+ </property>
+ <layout class="QVBoxLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="margin">
+ <number>8</number>
+ </property>
+ <item>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="PushButton11">
+ <property name="text">
+ <string>Up</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="PushButton13">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="PushButton12">
+ <property name="text">
+ <string>Down</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <widget class="Q3ListBox" name="fontpathlistbox"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item row="2" column="0">
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="PushButton15">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QPushButton" name="PushButton14">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <widget class="QLabel" name="TextLabel15_2">
+ <property name="text">
+ <string>Press the &lt;b&gt;Browse&lt;/b&gt; button or enter a directory and press Enter to add them to the list.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="3">
+ <widget class="QLineEdit" name="fontpathlineedit"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab4">
+ <attribute name="title">
+ <string>Phonon</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox_4">
+ <property name="title">
+ <string>About Phonon</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Current Version:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="phononVersionLabel">
+ <property name="text">
+ <string>Not available</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Website:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="gstversionLabel_3">
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://phonon.kde.org&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://phonon.kde.org&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>About GStreamer</string>
+ </property>
+ <layout class="QGridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Current Version:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="gstversionLabel">
+ <property name="text">
+ <string>Not available</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Website:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="gstversionLabel_2">
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;http://gstreamer.freedesktop.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://gstreamer.freedesktop.org/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>GStreamer backend settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Preferred audio sink:</string>
+ </property>
+ <property name="buddy">
+ <cstring>audiosinkCombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="audiosinkCombo"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Preferred render method:</string>
+ </property>
+ <property name="buddy">
+ <cstring>videomodeCombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="videomodeCombo"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Note: changes to these settings may prevent applications from starting up correctly.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="phononLabel">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>815</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="PopupMenu">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>123</width>
+ <height>92</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>&amp;File</string>
+ </property>
+ <action name=""/>
+ <action name=""/>
+ <action name=""/>
+ <addaction name="fileSaveAction"/>
+ <addaction name="separator"/>
+ <addaction name="fileExitAction"/>
+ </widget>
+ <widget class="QMenu" name="PopupMenu_2">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>123</width>
+ <height>90</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="helpAboutAction"/>
+ <addaction name="helpAboutQtAction"/>
+ </widget>
+ <action name=""/>
+ <action name=""/>
+ <action name=""/>
+ <addaction name="PopupMenu"/>
+ <addaction name="separator"/>
+ <addaction name="PopupMenu_2"/>
+ </widget>
+ <action name="fileSaveAction">
+ <property name="text">
+ <string>&amp;Save</string>
+ </property>
+ <property name="iconText">
+ <string>Save</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+S</string>
+ </property>
+ </action>
+ <action name="fileExitAction">
+ <property name="text">
+ <string>E&amp;xit</string>
+ </property>
+ <property name="iconText">
+ <string>Exit</string>
+ </property>
+ <property name="shortcut">
+ <string/>
+ </property>
+ </action>
+ <action name="helpAboutAction">
+ <property name="text">
+ <string>&amp;About</string>
+ </property>
+ <property name="iconText">
+ <string>About</string>
+ </property>
+ <property name="shortcut">
+ <string/>
+ </property>
+ </action>
+ <action name="helpAboutQtAction">
+ <property name="text">
+ <string>About &amp;Qt</string>
+ </property>
+ <property name="iconText">
+ <string>About Qt</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>Q3Frame</class>
+ <extends>QFrame</extends>
+ <header>Qt3Support/Q3Frame</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>Q3MainWindow</class>
+ <extends>QWidget</extends>
+ <header>q3mainwindow.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>Q3ListBox</class>
+ <extends>Q3Frame</extends>
+ <header>q3listbox.h</header>
+ </customwidget>
+ <customwidget>
+ <class>ColorButton</class>
+ <extends></extends>
+ <header>colorbutton.h</header>
+ </customwidget>
+ <customwidget>
+ <class>PreviewFrame</class>
+ <extends></extends>
+ <header>previewframe.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>helpview</tabstop>
+ <tabstop>familycombo</tabstop>
+ <tabstop>stylecombo</tabstop>
+ <tabstop>psizecombo</tabstop>
+ <tabstop>samplelineedit</tabstop>
+ <tabstop>familysubcombo</tabstop>
+ <tabstop>PushButton2</tabstop>
+ <tabstop>PushButton3</tabstop>
+ <tabstop>PushButton4</tabstop>
+ <tabstop>choosesubcombo</tabstop>
+ <tabstop>PushButton1</tabstop>
+ <tabstop>dcispin</tabstop>
+ <tabstop>cfispin</tabstop>
+ <tabstop>wslspin</tabstop>
+ <tabstop>effectcheckbox</tabstop>
+ <tabstop>menueffect</tabstop>
+ <tabstop>comboeffect</tabstop>
+ <tabstop>tooltipeffect</tabstop>
+ <tabstop>strutwidth</tabstop>
+ <tabstop>strutheight</tabstop>
+ <tabstop>sublistbox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/qtconfig/paletteeditoradvanced.cpp b/tools/qtconfig/paletteeditoradvanced.cpp
new file mode 100644
index 0000000000..d9bafebe12
--- /dev/null
+++ b/tools/qtconfig/paletteeditoradvanced.cpp
@@ -0,0 +1,591 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "paletteeditoradvanced.h"
+#include "colorbutton.h"
+
+#include <QCheckBox>
+#include <QComboBox>
+#include <QApplication>
+#include <QPushButton>
+#include <QPainter>
+#include <QGroupBox>
+
+QT_BEGIN_NAMESPACE
+
+PaletteEditorAdvanced::PaletteEditorAdvanced( QWidget * parent,
+ const char * name, bool modal, Qt::WindowFlags f )
+ : PaletteEditorAdvancedBase( parent, name, modal, f ), selectedPalette(0)
+{
+ // work around buggy ui file
+ comboEffect->setEnabled(false);
+ buttonEffect->setEnabled(false);
+ onToggleBuildEffects(true);
+
+ editPalette = QApplication::palette();
+ setPreviewPalette( editPalette );
+}
+
+PaletteEditorAdvanced::~PaletteEditorAdvanced()
+{
+}
+
+void PaletteEditorAdvanced::onToggleBuildInactive( bool v )
+{
+ if (selectedPalette == 1) {
+ groupCentral->setDisabled(v);
+ groupEffect->setDisabled(v);
+ }
+
+ if (v) {
+ buildInactive();
+ updateColorButtons();
+ }
+}
+
+void PaletteEditorAdvanced::onToggleBuildDisabled( bool v )
+{
+ if (selectedPalette == 2) {
+ groupCentral->setDisabled(v);
+ groupEffect->setDisabled(v);
+ }
+
+ if (v) {
+ buildDisabled();
+ updateColorButtons();
+ }
+}
+
+void PaletteEditorAdvanced::paletteSelected(int p)
+{
+ selectedPalette = p;
+
+ if(p == 1) { // inactive
+ groupCentral->setDisabled(checkBuildInactive->isChecked());
+ groupEffect->setDisabled(checkBuildInactive->isChecked());
+ }
+ else if (p == 2) { // disabled
+ groupCentral->setDisabled(checkBuildDisabled->isChecked());
+ groupEffect->setDisabled(checkBuildDisabled->isChecked());
+ }
+ else {
+ groupCentral->setEnabled(true);
+ groupEffect->setEnabled(true);
+ }
+ updateColorButtons();
+}
+
+void PaletteEditorAdvanced::onChooseCentralColor()
+{
+ switch(selectedPalette) {
+ case 0:
+ default:
+ mapToActiveCentralRole( buttonCentral->color() );
+ break;
+ case 1:
+ mapToInactiveCentralRole( buttonCentral->color() );
+ break;
+ case 2:
+ mapToDisabledCentralRole( buttonCentral->color() );
+ break;
+ }
+ updateColorButtons();
+}
+
+void PaletteEditorAdvanced::onChooseEffectColor()
+{
+ switch(selectedPalette) {
+ case 0:
+ default:
+ mapToActiveEffectRole( buttonEffect->color() );
+ break;
+ case 1:
+ mapToInactiveEffectRole( buttonEffect->color() );
+ break;
+ case 2:
+ mapToDisabledEffectRole( buttonEffect->color() );
+ break;
+ }
+ updateColorButtons();
+}
+
+void PaletteEditorAdvanced::onToggleBuildEffects( bool on )
+{
+ if (!on) return;
+ buildActiveEffect();
+ buildInactiveEffect();
+ buildDisabledEffect();
+}
+
+QColorGroup::ColorRole PaletteEditorAdvanced::centralFromItem( int item )
+{
+ switch( item ) {
+ case 0:
+ return QColorGroup::Window;
+ case 1:
+ return QColorGroup::WindowText;
+ case 2:
+ return QColorGroup::Button;
+ case 3:
+ return QColorGroup::Base;
+ case 4:
+ return QColorGroup::Text;
+ case 5:
+ return QColorGroup::BrightText;
+ case 6:
+ return QColorGroup::ButtonText;
+ case 7:
+ return QColorGroup::Highlight;
+ case 8:
+ return QColorGroup::HighlightedText;
+ default:
+ return QColorGroup::NColorRoles;
+ }
+}
+
+QColorGroup::ColorRole PaletteEditorAdvanced::effectFromItem( int item )
+{
+ switch( item ) {
+ case 0:
+ return QColorGroup::Light;
+ case 1:
+ return QColorGroup::Midlight;
+ case 2:
+ return QColorGroup::Mid;
+ case 3:
+ return QColorGroup::Dark;
+ case 4:
+ return QColorGroup::Shadow;
+ default:
+ return QColorGroup::NColorRoles;
+ }
+}
+
+void PaletteEditorAdvanced::onCentral( int item )
+{
+ QColor c;
+
+ switch(selectedPalette) {
+ case 0:
+ default:
+ c = editPalette.active().color( centralFromItem(item) );
+ break;
+ case 1:
+ c = editPalette.inactive().color( centralFromItem(item) );
+ break;
+ case 2:
+ c = editPalette.disabled().color( centralFromItem(item) );
+ break;
+ }
+
+ buttonCentral->setColor(c);
+}
+
+void PaletteEditorAdvanced::onEffect( int item )
+{
+ QColor c;
+ switch(selectedPalette) {
+ case 0:
+ default:
+ c = editPalette.active().color( effectFromItem(item) );
+ break;
+ case 1:
+ editPalette.inactive().color( effectFromItem(item) );
+ break;
+ case 2:
+ editPalette.disabled().color( effectFromItem(item) );
+ break;
+ }
+ buttonEffect->setColor(c);
+}
+
+void PaletteEditorAdvanced::mapToActiveCentralRole( const QColor& c )
+{
+ QColorGroup cg = editPalette.active();
+ cg.setColor( centralFromItem(comboCentral->currentItem()), c );
+ editPalette.setActive( cg );
+
+ buildActiveEffect();
+ if(checkBuildInactive->isChecked())
+ buildInactive();
+ if(checkBuildDisabled->isChecked())
+ buildDisabled();
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToActiveEffectRole( const QColor& c )
+{
+ QColorGroup cg = editPalette.active();
+ cg.setColor( effectFromItem(comboEffect->currentItem()), c );
+ editPalette.setActive( cg );
+
+ if(checkBuildInactive->isChecked())
+ buildInactive();
+ if(checkBuildDisabled->isChecked())
+ buildDisabled();
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToActivePixmapRole( const QPixmap& pm )
+{
+ QColorGroup::ColorRole role = centralFromItem(comboCentral->currentItem());
+ QColorGroup cg = editPalette.active();
+ if ( !pm.isNull() )
+ cg.setBrush( role, QBrush( cg.color( role ), pm ) );
+ else
+ cg.setBrush( role, QBrush( cg.color( role ) ) );
+ editPalette.setActive( cg );
+
+
+ buildActiveEffect();
+ if(checkBuildInactive->isChecked())
+ buildInactive();
+ if(checkBuildDisabled->isChecked())
+ buildDisabled();
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToInactiveCentralRole( const QColor& c )
+{
+ QColorGroup cg = editPalette.inactive();
+ cg.setColor( centralFromItem(comboCentral->currentItem()), c );
+ editPalette.setInactive( cg );
+
+ buildInactiveEffect();
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToInactiveEffectRole( const QColor& c )
+{
+ QColorGroup cg = editPalette.inactive();
+ cg.setColor( effectFromItem(comboEffect->currentItem()), c );
+ editPalette.setInactive( cg );
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToInactivePixmapRole( const QPixmap& pm )
+{
+ QColorGroup::ColorRole role = centralFromItem(comboCentral->currentItem());
+ QColorGroup cg = editPalette.inactive();
+ if ( !pm.isNull() )
+ cg.setBrush( role, QBrush( cg.color( role ), pm ) );
+ else
+ cg.setBrush( role, QBrush( cg.color( role ) ) );
+ editPalette.setInactive( cg );
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToDisabledCentralRole( const QColor& c )
+{
+ QColorGroup cg = editPalette.disabled();
+ cg.setColor( centralFromItem(comboCentral->currentItem()), c );
+ editPalette.setDisabled( cg );
+
+ buildDisabledEffect();
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToDisabledEffectRole( const QColor& c )
+{
+ QColorGroup cg = editPalette.disabled();
+ cg.setColor( effectFromItem(comboEffect->currentItem()), c );
+ editPalette.setDisabled( cg );
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::mapToDisabledPixmapRole( const QPixmap& pm )
+{
+ QColorGroup::ColorRole role = centralFromItem(comboCentral->currentItem());
+ QColorGroup cg = editPalette.disabled();
+ if ( !pm.isNull() )
+ cg.setBrush( role, QBrush( cg.color( role ), pm ) );
+ else
+ cg.setBrush( role, QBrush( cg.color( role ) ) );
+
+ editPalette.setDisabled( cg );
+
+ setPreviewPalette( editPalette );
+}
+
+void PaletteEditorAdvanced::buildActiveEffect()
+{
+ QColorGroup cg = editPalette.active();
+ QColor btn = cg.color( QColorGroup::Button );
+
+ QPalette temp( btn, btn );
+
+ for (int i = 0; i<5; i++)
+ cg.setColor( effectFromItem(i), temp.active().color( effectFromItem(i) ) );
+
+ editPalette.setActive( cg );
+ setPreviewPalette( editPalette );
+
+ updateColorButtons();
+}
+
+void PaletteEditorAdvanced::buildInactive()
+{
+ editPalette.setInactive( editPalette.active() );
+ if ( checkBuildEffect->isChecked() )
+ buildInactiveEffect();
+ else {
+ setPreviewPalette( editPalette );
+ updateColorButtons();
+ }
+
+}
+
+void PaletteEditorAdvanced::buildInactiveEffect()
+{
+ QColorGroup cg = editPalette.inactive();
+
+ QColor light, midlight, mid, dark, shadow;
+ QColor btn = cg.color( QColorGroup::Button );
+
+ light = btn.light(150);
+ midlight = btn.light(115);
+ mid = btn.dark(150);
+ dark = btn.dark();
+ shadow = Qt::black;
+
+ cg.setColor( QColorGroup::Light, light );
+ cg.setColor( QColorGroup::Midlight, midlight );
+ cg.setColor( QColorGroup::Mid, mid );
+ cg.setColor( QColorGroup::Dark, dark );
+ cg.setColor( QColorGroup::Shadow, shadow );
+
+ editPalette.setInactive( cg );
+ setPreviewPalette( editPalette );
+ updateColorButtons();
+}
+
+void PaletteEditorAdvanced::buildDisabled()
+{
+ QColorGroup cg = editPalette.active();
+ cg.setColor( QColorGroup::ButtonText, Qt::darkGray );
+ cg.setColor( QColorGroup::WindowText, Qt::darkGray );
+ cg.setColor( QColorGroup::Text, Qt::darkGray );
+ cg.setColor( QColorGroup::HighlightedText, Qt::darkGray );
+ editPalette.setDisabled( cg );
+
+ if ( checkBuildEffect->isChecked() )
+ buildDisabledEffect();
+ else {
+ setPreviewPalette( editPalette );
+ updateColorButtons();
+ }
+}
+
+void PaletteEditorAdvanced::buildDisabledEffect()
+{
+ QColorGroup cg = editPalette.disabled();
+
+ QColor light, midlight, mid, dark, shadow;
+ QColor btn = cg.color( QColorGroup::Button );
+
+ light = btn.light(150);
+ midlight = btn.light(115);
+ mid = btn.dark(150);
+ dark = btn.dark();
+ shadow = Qt::black;
+
+ cg.setColor( QColorGroup::Light, light );
+ cg.setColor( QColorGroup::Midlight, midlight );
+ cg.setColor( QColorGroup::Mid, mid );
+ cg.setColor( QColorGroup::Dark, dark );
+ cg.setColor( QColorGroup::Shadow, shadow );
+
+ editPalette.setDisabled( cg );
+ setPreviewPalette( editPalette );
+ updateColorButtons();
+}
+
+void PaletteEditorAdvanced::setPreviewPalette( const QPalette& pal )
+{
+ QColorGroup cg;
+
+ switch (selectedPalette) {
+ case 0:
+ default:
+ cg = pal.active();
+ break;
+ case 1:
+ cg = pal.inactive();
+ break;
+ case 2:
+ cg = pal.disabled();
+ break;
+ }
+ previewPalette.setActive( cg );
+ previewPalette.setInactive( cg );
+ previewPalette.setDisabled( cg );
+}
+
+void PaletteEditorAdvanced::updateColorButtons()
+{
+ QColor central, effect;
+ switch (selectedPalette) {
+ case 0:
+ default:
+ central = editPalette.active().color( centralFromItem( comboCentral->currentItem() ) );
+ effect = editPalette.active().color( effectFromItem( comboEffect->currentItem() ) );
+ break;
+ case 1:
+ central = editPalette.inactive().color( centralFromItem( comboCentral->currentItem() ) );
+ effect = editPalette.inactive().color( effectFromItem( comboEffect->currentItem() ) );
+ break;
+ case 2:
+ central = editPalette.disabled().color( centralFromItem( comboCentral->currentItem() ) );
+ effect = editPalette.disabled().color( effectFromItem( comboEffect->currentItem() ) );
+ break;
+ }
+
+ buttonCentral->setColor(central);
+ buttonEffect->setColor(effect);
+}
+
+void PaletteEditorAdvanced::setPal( const QPalette& pal )
+{
+ editPalette = pal;
+ setPreviewPalette( pal );
+ updateColorButtons();
+}
+
+QPalette PaletteEditorAdvanced::pal() const
+{
+ return editPalette;
+}
+
+void PaletteEditorAdvanced::setupBackgroundMode( Qt::BackgroundMode mode )
+{
+ int initRole = 0;
+
+ switch( mode ) {
+ case Qt::PaletteBackground:
+ initRole = 0;
+ break;
+ case Qt::PaletteForeground:
+ initRole = 1;
+ break;
+ case Qt::PaletteButton:
+ initRole = 2;
+ break;
+ case Qt::PaletteBase:
+ initRole = 3;
+ break;
+ case Qt::PaletteText:
+ initRole = 4;
+ break;
+ case Qt::PaletteBrightText:
+ initRole = 5;
+ break;
+ case Qt::PaletteButtonText:
+ initRole = 6;
+ break;
+ case Qt::PaletteHighlight:
+ initRole = 7;
+ break;
+ case Qt::PaletteHighlightedText:
+ initRole = 8;
+ break;
+ case Qt::PaletteLight:
+ initRole = 9;
+ break;
+ case Qt::PaletteMidlight:
+ initRole = 10;
+ break;
+ case Qt::PaletteDark:
+ initRole = 11;
+ break;
+ case Qt::PaletteMid:
+ initRole = 12;
+ break;
+ case Qt::PaletteShadow:
+ initRole = 13;
+ break;
+ default:
+ initRole = -1;
+ break;
+ }
+
+ if ( initRole <= -1 ) return;
+
+ if (initRole > 8 ) {
+ comboEffect->setCurrentItem( initRole - 9 );
+ }
+ else {
+ comboCentral->setCurrentItem( initRole );
+ }
+}
+
+QPalette PaletteEditorAdvanced::getPalette( bool *ok, const QPalette &init,
+ Qt::BackgroundMode mode, QWidget* parent,
+ const char* name )
+{
+ PaletteEditorAdvanced* dlg = new PaletteEditorAdvanced( parent, name, true );
+ dlg->setupBackgroundMode( mode );
+
+ if ( init != QPalette() )
+ dlg->setPal( init );
+ int resultCode = dlg->exec();
+
+ QPalette result = init;
+ if ( resultCode == QDialog::Accepted ) {
+ if ( ok )
+ *ok = true;
+ result = dlg->pal();
+ } else {
+ if ( ok )
+ *ok = false;
+ }
+ delete dlg;
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/paletteeditoradvanced.h b/tools/qtconfig/paletteeditoradvanced.h
new file mode 100644
index 0000000000..7dc80db661
--- /dev/null
+++ b/tools/qtconfig/paletteeditoradvanced.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PALETTEEDITORADVANCED_H
+#define PALETTEEDITORADVANCED_H
+
+#include "paletteeditoradvancedbase.h"
+
+QT_BEGIN_NAMESPACE
+
+class PaletteEditorAdvanced : public PaletteEditorAdvancedBase
+{
+ Q_OBJECT
+public:
+ PaletteEditorAdvanced( QWidget * parent=0, const char * name=0,
+ bool modal=false, Qt::WindowFlags f=0 );
+ ~PaletteEditorAdvanced();
+
+ static QPalette getPalette( bool *ok, const QPalette &pal, Qt::BackgroundMode mode = Qt::PaletteBackground,
+ QWidget* parent = 0, const char* name = 0 );
+
+protected slots:
+ void paletteSelected(int);
+
+ void onCentral( int );
+ void onEffect( int );
+
+ void onChooseCentralColor();
+ void onChooseEffectColor();
+
+ void onToggleBuildEffects( bool );
+ void onToggleBuildInactive( bool );
+ void onToggleBuildDisabled( bool );
+
+protected:
+ void mapToActiveCentralRole( const QColor& );
+ void mapToActiveEffectRole( const QColor& );
+ void mapToActivePixmapRole( const QPixmap& );
+ void mapToInactiveCentralRole( const QColor& );
+ void mapToInactiveEffectRole( const QColor& );
+ void mapToInactivePixmapRole( const QPixmap& );
+ void mapToDisabledCentralRole( const QColor& );
+ void mapToDisabledEffectRole( const QColor& );
+ void mapToDisabledPixmapRole( const QPixmap& );
+
+
+ void buildPalette();
+ void buildActiveEffect();
+ void buildInactive();
+ void buildInactiveEffect();
+ void buildDisabled();
+ void buildDisabledEffect();
+
+private:
+ void setPreviewPalette( const QPalette& );
+ void updateColorButtons();
+ void setupBackgroundMode( Qt::BackgroundMode );
+
+ QPalette pal() const;
+ void setPal( const QPalette& );
+
+ QColorGroup::ColorRole centralFromItem( int );
+ QColorGroup::ColorRole effectFromItem( int );
+ QPalette editPalette;
+ QPalette previewPalette;
+
+ int selectedPalette;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qtconfig/paletteeditoradvancedbase.cpp b/tools/qtconfig/paletteeditoradvancedbase.cpp
new file mode 100644
index 0000000000..4e107a22f9
--- /dev/null
+++ b/tools/qtconfig/paletteeditoradvancedbase.cpp
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "paletteeditoradvancedbase.h"
+#include "colorbutton.h"
+
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Constructs a PaletteEditorAdvancedBase as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * true to construct a modal dialog.
+ */
+PaletteEditorAdvancedBase::PaletteEditorAdvancedBase(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl)
+ : QDialog(parent, name, modal, fl)
+{
+ setupUi(this);
+
+
+ // signals and slots connections
+ connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(paletteCombo, SIGNAL(activated(int)), this, SLOT(paletteSelected(int)));
+ connect(comboCentral, SIGNAL(activated(int)), this, SLOT(onCentral(int)));
+ connect(buttonCentral, SIGNAL(clicked()), this, SLOT(onChooseCentralColor()));
+ connect(buttonEffect, SIGNAL(clicked()), this, SLOT(onChooseEffectColor()));
+ connect(comboEffect, SIGNAL(activated(int)), this, SLOT(onEffect(int)));
+ connect(checkBuildEffect, SIGNAL(toggled(bool)), this, SLOT(onToggleBuildEffects(bool)));
+ connect(checkBuildEffect, SIGNAL(toggled(bool)), comboEffect, SLOT(setDisabled(bool)));
+ connect(checkBuildEffect, SIGNAL(toggled(bool)), buttonEffect, SLOT(setDisabled(bool)));
+ connect(checkBuildInactive, SIGNAL(toggled(bool)), this, SLOT(onToggleBuildInactive(bool)));
+ connect(checkBuildDisabled, SIGNAL(toggled(bool)), this, SLOT(onToggleBuildDisabled(bool)));
+ init();
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+PaletteEditorAdvancedBase::~PaletteEditorAdvancedBase()
+{
+ destroy();
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void PaletteEditorAdvancedBase::languageChange()
+{
+ retranslateUi(this);
+}
+
+void PaletteEditorAdvancedBase::init()
+{
+}
+
+void PaletteEditorAdvancedBase::destroy()
+{
+}
+
+void PaletteEditorAdvancedBase::onCentral(int)
+{
+ qWarning("PaletteEditorAdvancedBase::onCentral(int): Not implemented yet");
+}
+
+void PaletteEditorAdvancedBase::onChooseCentralColor()
+{
+ qWarning("PaletteEditorAdvancedBase::onChooseCentralColor(): Not implemented yet");
+}
+
+void PaletteEditorAdvancedBase::onChooseEffectColor()
+{
+ qWarning("PaletteEditorAdvancedBase::onChooseEffectColor(): Not implemented yet");
+}
+
+void PaletteEditorAdvancedBase::onEffect(int)
+{
+ qWarning("PaletteEditorAdvancedBase::onEffect(int): Not implemented yet");
+}
+
+void PaletteEditorAdvancedBase::onToggleBuildDisabled(bool)
+{
+ qWarning("PaletteEditorAdvancedBase::onToggleBuildDisabled(bool): Not implemented yet");
+}
+
+void PaletteEditorAdvancedBase::onToggleBuildEffects(bool)
+{
+ qWarning("PaletteEditorAdvancedBase::onToggleBuildEffects(bool): Not implemented yet");
+}
+
+void PaletteEditorAdvancedBase::onToggleBuildInactive(bool)
+{
+ qWarning("PaletteEditorAdvancedBase::onToggleBuildInactive(bool): Not implemented yet");
+}
+
+void PaletteEditorAdvancedBase::paletteSelected(int)
+{
+ qWarning("PaletteEditorAdvancedBase::paletteSelected(int): Not implemented yet");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/paletteeditoradvancedbase.h b/tools/qtconfig/paletteeditoradvancedbase.h
new file mode 100644
index 0000000000..f7920d8712
--- /dev/null
+++ b/tools/qtconfig/paletteeditoradvancedbase.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PALETTEEDITORADVANCEDBASE_H
+#define PALETTEEDITORADVANCEDBASE_H
+
+#include "ui_paletteeditoradvancedbase.h"
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class ColorButton;
+
+class PaletteEditorAdvancedBase : public QDialog, public Ui::PaletteEditorAdvancedBase
+{
+ Q_OBJECT
+
+public:
+ PaletteEditorAdvancedBase(QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WindowFlags fl = 0);
+ ~PaletteEditorAdvancedBase();
+
+protected slots:
+ virtual void languageChange();
+
+ virtual void init();
+ virtual void destroy();
+ virtual void onCentral(int);
+ virtual void onChooseCentralColor();
+ virtual void onChooseEffectColor();
+ virtual void onEffect(int);
+ virtual void onToggleBuildDisabled(bool);
+ virtual void onToggleBuildEffects(bool);
+ virtual void onToggleBuildInactive(bool);
+ virtual void paletteSelected(int);
+
+};
+
+QT_END_NAMESPACE
+
+#endif // PALETTEEDITORADVANCEDBASE_H
diff --git a/tools/qtconfig/paletteeditoradvancedbase.ui b/tools/qtconfig/paletteeditoradvancedbase.ui
new file mode 100644
index 0000000000..465569e973
--- /dev/null
+++ b/tools/qtconfig/paletteeditoradvancedbase.ui
@@ -0,0 +1,617 @@
+<ui version="4.0" stdsetdef="1" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>PaletteEditorAdvancedBase</class>
+ <widget class="QDialog" name="PaletteEditorAdvancedBase" >
+ <property name="objectName" >
+ <string notr="true" >PaletteEditorAdvancedBase</string>
+ </property>
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>295</width>
+ <height>346</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Tune Palette</string>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>&lt;b>Edit Palette&lt;/b>&lt;p>Change the palette of the current widget or form.&lt;/p>&lt;p>Use a generated palette or select colors for each color group and each color role.&lt;/p>&lt;p>The palette can be tested with different widget layouts in the preview section.&lt;/p></string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="objectName" >
+ <string notr="true" >TextLabel1</string>
+ </property>
+ <property name="text" >
+ <string>Select &amp;Palette:</string>
+ </property>
+ <property name="buddy" stdset="0" >
+ <cstring>paletteCombo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="paletteCombo" >
+ <property name="objectName" >
+ <string notr="true" >paletteCombo</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>Active Palette</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Inactive Palette</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Disabled Palette</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Q3ButtonGroup" name="ButtonGroup1" >
+ <property name="objectName" >
+ <string notr="true" >ButtonGroup1</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Auto</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="checkBuildInactive" >
+ <property name="objectName" >
+ <string notr="true" >checkBuildInactive</string>
+ </property>
+ <property name="text" >
+ <string>Build inactive palette from active</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBuildDisabled" >
+ <property name="objectName" >
+ <string notr="true" >checkBuildDisabled</string>
+ </property>
+ <property name="text" >
+ <string>Build disabled palette from active</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="Q3GroupBox" name="groupCentral" >
+ <property name="objectName" >
+ <string notr="true" >groupCentral</string>
+ </property>
+ <property name="title" >
+ <string>Central color &amp;roles</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QComboBox" name="comboCentral" >
+ <property name="objectName" >
+ <string notr="true" >comboCentral</string>
+ </property>
+ <property name="toolTip" stdset="0" >
+ <string>Choose central color role</string>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>&lt;b>Select a color role.&lt;/b>&lt;p>Available central roles are: &lt;ul> &lt;li>Window - general background color.&lt;/li> &lt;li>WindowText - general foreground color. &lt;/li> &lt;li>Base - used as background color for e.g. text entry widgets, usually white or another light color. &lt;/li> &lt;li>Text - the foreground color used with Base. Usually this is the same as WindowText, in what case it must provide good contrast both with Window and Base. &lt;/li> &lt;li>Button - general button background color, where buttons need a background different from Window, as in the Macintosh style. &lt;/li> &lt;li>ButtonText - a foreground color used with the Button color. &lt;/li> &lt;li>Highlight - a color to indicate a selected or highlighted item. &lt;/li> &lt;li>HighlightedText - a text color that contrasts to Highlight. &lt;/li> &lt;li>BrightText - a text color that is very different from WindowText and contrasts well with e.g. black. &lt;/li> &lt;/ul> &lt;/p></string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>Window</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>WindowText</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Button</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Base</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Text</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>BrightText</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>ButtonText</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Highlight</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>HighlightedText</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer name="Horizontal_Spacing1" >
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="sizeType" >
+ <enum>Expanding</enum>
+ </property>
+ <property name="orientation" >
+ <enum>Horizontal</enum>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelCentral" >
+ <property name="objectName" >
+ <string notr="true" >labelCentral</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>&amp;Select Color:</string>
+ </property>
+ <property name="buddy" stdset="0" >
+ <cstring>buttonCentral</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ColorButton" name="buttonCentral" >
+ <property name="objectName" >
+ <string notr="true" >buttonCentral</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy" >
+ <enum>Qt::TabFocus</enum>
+ </property>
+ <property name="toolTip" stdset="0" >
+ <string>Choose a color</string>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>Choose a color for the selected central color role.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="Q3GroupBox" name="groupEffect" >
+ <property name="objectName" >
+ <string notr="true" >groupEffect</string>
+ </property>
+ <property name="title" >
+ <string>3-D shadow &amp;effects</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="checkBuildEffect" >
+ <property name="objectName" >
+ <string notr="true" >checkBuildEffect</string>
+ </property>
+ <property name="text" >
+ <string>Build &amp;from button color</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0" >
+ <string>Generate shadings</string>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>Check to let 3D-effect colors be calculated from button-color.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboEffect" >
+ <property name="objectName" >
+ <string notr="true" >comboEffect</string>
+ </property>
+ <property name="toolTip" stdset="0" >
+ <string>Choose 3D-effect color role</string>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>&lt;b>Select a color role.&lt;/b>&lt;p>Available effect roles are: &lt;ul> &lt;li>Light - lighter than Button color. &lt;/li> &lt;li>Midlight - between Button and Light. &lt;/li> &lt;li>Mid - between Button and Dark. &lt;/li> &lt;li>Dark - darker than Button. &lt;/li> &lt;li>Shadow - a very dark color. &lt;/li> &lt;/ul></string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>Light</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Midlight</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Mid</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Dark</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>Shadow</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer name="Horizontal_Spacing3" >
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="sizeType" >
+ <enum>Expanding</enum>
+ </property>
+ <property name="orientation" >
+ <enum>Horizontal</enum>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelEffect" >
+ <property name="objectName" >
+ <string notr="true" >labelEffect</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>Select Co&amp;lor:</string>
+ </property>
+ <property name="buddy" stdset="0" >
+ <cstring>buttonEffect</cstring>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="ColorButton" name="buttonEffect" >
+ <property name="objectName" >
+ <string notr="true" >buttonEffect</string>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy" >
+ <enum>Qt::TabFocus</enum>
+ </property>
+ <property name="toolTip" stdset="0" >
+ <string>Choose a color</string>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>Choose a color for the selected effect color role.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <spacer name="Horizontal_Spacing2" >
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="sizeType" >
+ <enum>Expanding</enum>
+ </property>
+ <property name="orientation" >
+ <enum>Horizontal</enum>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonOk" >
+ <property name="objectName" >
+ <string notr="true" >buttonOk</string>
+ </property>
+ <property name="text" >
+ <string>OK</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>Close dialog and apply all changes.</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonCancel" >
+ <property name="objectName" >
+ <string notr="true" >buttonCancel</string>
+ </property>
+ <property name="text" >
+ <string>Cancel</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0" >
+ <string>Close dialog and discard all changes.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <customwidgets>
+ <customwidget>
+ <class>ColorButton</class>
+ <extends></extends>
+ <header location="local" >colorbutton.h</header>
+ <sizehint>
+ <width>40</width>
+ <height>25</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <properties>
+ <property type="Color" >color</property>
+ <property type="Pixmap" >pixmap</property>
+ </properties>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>buttonOk</tabstop>
+ <tabstop>buttonCancel</tabstop>
+ <tabstop>paletteCombo</tabstop>
+ <tabstop>checkBuildInactive</tabstop>
+ <tabstop>checkBuildDisabled</tabstop>
+ <tabstop>comboCentral</tabstop>
+ <tabstop>buttonCentral</tabstop>
+ <tabstop>checkBuildEffect</tabstop>
+ <tabstop>comboEffect</tabstop>
+ <tabstop>buttonEffect</tabstop>
+ </tabstops>
+ <images>
+ <image name="image0" >
+ <data format="XPM.GZ" length="646" >789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
+ </image>
+ </images>
+</ui>
diff --git a/tools/qtconfig/previewframe.cpp b/tools/qtconfig/previewframe.cpp
new file mode 100644
index 0000000000..5be5b1cbdf
--- /dev/null
+++ b/tools/qtconfig/previewframe.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "previewframe.h"
+
+#include <QBoxLayout>
+#include <QPainter>
+#include <QMdiSubWindow>
+
+QT_BEGIN_NAMESPACE
+
+PreviewFrame::PreviewFrame( QWidget *parent, const char *name )
+ : QFrame( parent, name )
+{
+ setMinimumSize(200, 200);
+ setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ setLineWidth(1);
+
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ vbox->setMargin(0);
+ previewWidget = new PreviewWidget;
+ workspace = new Workspace(this);
+ vbox->addWidget(workspace);
+ previewWidget->setAutoFillBackground(true);
+}
+
+void PreviewFrame::setPreviewPalette(QPalette pal)
+{
+ previewWidget->setPalette(pal);
+}
+
+QString PreviewFrame::previewText() const
+{
+ return m_previewWindowText;
+}
+
+void PreviewFrame::setPreviewVisible(bool visible)
+{
+ previewWidget->parentWidget()->setVisible(visible);
+ if (visible)
+ m_previewWindowText = QLatin1String("The moose in the noose\nate the goose who was loose.");
+ else
+ m_previewWindowText = tr("Desktop settings will only take effect after an application restart.");
+ workspace->viewport()->update();
+}
+
+Workspace::Workspace(PreviewFrame* parent, const char* name)
+ : QMdiArea(parent)
+{
+ previewFrame = parent;
+ PreviewWidget *previewWidget = previewFrame->widget();
+ setObjectName(QLatin1String(name));
+ QMdiSubWindow *frame = addSubWindow(previewWidget, Qt::Window);
+ frame->move(10,10);
+ frame->show();
+}
+
+void Workspace::paintEvent( QPaintEvent* )
+{
+ QPainter p (viewport());
+ p.fillRect(rect(), palette().color(backgroundRole()).dark());
+ p.setPen( QPen( Qt::white ) );
+ p.drawText ( 0, height() / 2, width(), height(), Qt::AlignHCenter, previewFrame->previewText());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/previewframe.h b/tools/qtconfig/previewframe.h
new file mode 100644
index 0000000000..ce98ffe264
--- /dev/null
+++ b/tools/qtconfig/previewframe.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREVIEWFRAME_H
+#define PREVIEWFRAME_H
+
+#include "previewwidget.h"
+
+#include <QMdiArea>
+
+QT_BEGIN_NAMESPACE
+
+class PreviewFrame;
+class Workspace : public QMdiArea
+{
+ Q_OBJECT
+
+public:
+ Workspace( PreviewFrame* parent = 0, const char* name = 0 );
+ ~Workspace() {}
+
+protected:
+ void paintEvent( QPaintEvent* );
+private:
+ PreviewFrame *previewFrame;
+};
+
+class PreviewFrame : public QFrame
+{
+ Q_OBJECT
+
+public:
+ PreviewFrame( QWidget *parent = 0, const char *name = 0 );
+ void setPreviewPalette(QPalette);
+ void setPreviewVisible(bool val);
+ QString previewText() const;
+ PreviewWidget *widget() const { return previewWidget; }
+private:
+ Workspace *workspace;
+ PreviewWidget *previewWidget;
+ QString m_previewWindowText;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qtconfig/previewwidget.cpp b/tools/qtconfig/previewwidget.cpp
new file mode 100644
index 0000000000..00b1738b10
--- /dev/null
+++ b/tools/qtconfig/previewwidget.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "previewwidget.h"
+#include <QtEvents>
+
+QT_BEGIN_NAMESPACE
+
+PreviewWidget::PreviewWidget( QWidget *parent, const char *name )
+ : PreviewWidgetBase( parent, name )
+{
+ // install event filter on child widgets
+ QObjectList l = queryList("QWidget");
+ for (int i = 0; i < l.size(); ++i) {
+ QObject * obj = l.at(i);
+ obj->installEventFilter(this);
+ ((QWidget*)obj)->setFocusPolicy(Qt::NoFocus);
+ }
+}
+
+
+void PreviewWidget::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+}
+
+
+bool PreviewWidget::eventFilter(QObject *, QEvent *e)
+{
+ switch ( e->type() ) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ case QEvent::Enter:
+ case QEvent::Leave:
+ return true; // ignore;
+ default:
+ break;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/previewwidget.h b/tools/qtconfig/previewwidget.h
new file mode 100644
index 0000000000..c29eb20ddb
--- /dev/null
+++ b/tools/qtconfig/previewwidget.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREVIEWWIDGET_H
+#define PREVIEWWIDGET_H
+
+#include "previewwidgetbase.h"
+
+QT_BEGIN_NAMESPACE
+
+class PreviewWidget : public PreviewWidgetBase
+{
+ Q_OBJECT
+
+public:
+ PreviewWidget( QWidget *parent = 0, const char *name = 0 );
+
+ void closeEvent(QCloseEvent *);
+ bool eventFilter(QObject *, QEvent *);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qtconfig/previewwidgetbase.cpp b/tools/qtconfig/previewwidgetbase.cpp
new file mode 100644
index 0000000000..56e92941a0
--- /dev/null
+++ b/tools/qtconfig/previewwidgetbase.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "previewwidgetbase.h"
+
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Constructs a PreviewWidgetBase as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ */
+PreviewWidgetBase::PreviewWidgetBase(QWidget* parent, const char* name, Qt::WindowFlags fl)
+ : QWidget(parent, name, fl)
+{
+ setupUi(this);
+
+
+ // signals and slots connections
+ init();
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+PreviewWidgetBase::~PreviewWidgetBase()
+{
+ destroy();
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void PreviewWidgetBase::languageChange()
+{
+ retranslateUi(this);
+}
+
+void PreviewWidgetBase::init()
+{
+}
+
+void PreviewWidgetBase::destroy()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qtconfig/previewwidgetbase.h b/tools/qtconfig/previewwidgetbase.h
new file mode 100644
index 0000000000..aa510cd851
--- /dev/null
+++ b/tools/qtconfig/previewwidgetbase.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PREVIEWWIDGETBASE_H
+#define PREVIEWWIDGETBASE_H
+
+#include "ui_previewwidgetbase.h"
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class PreviewWidgetBase : public QWidget, public Ui::PreviewWidgetBase
+{
+ Q_OBJECT
+
+public:
+ PreviewWidgetBase(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = 0);
+ ~PreviewWidgetBase();
+
+protected slots:
+ virtual void languageChange();
+
+ virtual void init();
+ virtual void destroy();
+
+};
+
+QT_END_NAMESPACE
+
+#endif // PREVIEWWIDGETBASE_H
diff --git a/tools/qtconfig/previewwidgetbase.ui b/tools/qtconfig/previewwidgetbase.ui
new file mode 100644
index 0000000000..2c4e05d8e2
--- /dev/null
+++ b/tools/qtconfig/previewwidgetbase.ui
@@ -0,0 +1,340 @@
+<ui version="4.0" stdsetdef="1" >
+ <author></author>
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <exportmacro></exportmacro>
+ <class>PreviewWidgetBase</class>
+ <widget class="QWidget" name="PreviewWidgetBase" >
+ <property name="objectName" >
+ <string notr="true" >PreviewWidgetBase</string>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>378</width>
+ <height>236</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle" >
+ <string>Preview Window</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="Q3ButtonGroup" name="ButtonGroup1" >
+ <property name="objectName" >
+ <string notr="true" >ButtonGroup1</string>
+ </property>
+ <property name="title" >
+ <string>ButtonGroup</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="RadioButton1" >
+ <property name="objectName" >
+ <string notr="true" >RadioButton1</string>
+ </property>
+ <property name="text" >
+ <string>RadioButton1</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="RadioButton2" >
+ <property name="objectName" >
+ <string notr="true" >RadioButton2</string>
+ </property>
+ <property name="text" >
+ <string>RadioButton2</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="RadioButton3" >
+ <property name="objectName" >
+ <string notr="true" >RadioButton3</string>
+ </property>
+ <property name="text" >
+ <string>RadioButton3</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="Q3ButtonGroup" name="ButtonGroup2" >
+ <property name="objectName" >
+ <string notr="true" >ButtonGroup2</string>
+ </property>
+ <property name="title" >
+ <string>ButtonGroup2</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>11</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QCheckBox" name="CheckBox1" >
+ <property name="objectName" >
+ <string notr="true" >CheckBox1</string>
+ </property>
+ <property name="text" >
+ <string>CheckBox1</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="CheckBox2" >
+ <property name="objectName" >
+ <string notr="true" >CheckBox2</string>
+ </property>
+ <property name="text" >
+ <string>CheckBox2</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="ProgressBar1" >
+ <property name="objectName" >
+ <string notr="true" >ProgressBar1</string>
+ </property>
+ <property name="value" >
+ <number>50</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="LineEdit1" >
+ <property name="objectName" >
+ <string notr="true" >LineEdit1</string>
+ </property>
+ <property name="text" >
+ <string>LineEdit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="ComboBox1" >
+ <property name="objectName" >
+ <string notr="true" >ComboBox1</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>ComboBox</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="objectName" >
+ <string notr="true" >unnamed</string>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="SpinBox1" >
+ <property name="objectName" >
+ <string notr="true" >SpinBox1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="PushButton1" >
+ <property name="objectName" >
+ <string notr="true" >PushButton1</string>
+ </property>
+ <property name="text" >
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QScrollBar" name="ScrollBar1" >
+ <property name="objectName" >
+ <string notr="true" >ScrollBar1</string>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="Slider1" >
+ <property name="objectName" >
+ <string notr="true" >Slider1</string>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="textView" >
+ <property name="objectName" >
+ <string notr="true" >textView</string>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>32767</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>&lt;p>
+&lt;a href=&quot;http://qtsoftware.com&quot;>http://qtsoftware.com&lt;/a>
+&lt;/p>
+&lt;p>
+&lt;a href=&quot;http://www.kde.org&quot;>http://www.kde.org&lt;/a>
+&lt;/p></string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="Spacer2" >
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="sizeType" >
+ <enum>Expanding</enum>
+ </property>
+ <property name="orientation" >
+ <enum>Vertical</enum>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <pixmapfunction>qPixmapFromMimeSource</pixmapfunction>
+</ui>
diff --git a/tools/qtconfig/qtconfig.pro b/tools/qtconfig/qtconfig.pro
new file mode 100644
index 0000000000..8ab3f03593
--- /dev/null
+++ b/tools/qtconfig/qtconfig.pro
@@ -0,0 +1,28 @@
+TEMPLATE = app
+CONFIG += qt warn_on x11
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+LANGUAGE = C++
+QT += qt3support
+
+contains(QT_CONFIG, gstreamer):LIBS += $$QT_LIBS_GSTREAMER -lgstinterfaces-0.10 -lgstvideo-0.10 -lgstbase-0.10
+contains(QT_CONFIG, gstreamer):QMAKE_CXXFLAGS += $$QT_CFLAGS_GSTREAMER
+contains(QT_CONFIG, gstreamer):QT += phonon
+SOURCES += colorbutton.cpp main.cpp previewframe.cpp previewwidget.cpp mainwindow.cpp paletteeditoradvanced.cpp \
+ mainwindowbase.cpp paletteeditoradvancedbase.cpp previewwidgetbase.cpp
+HEADERS += colorbutton.h previewframe.h previewwidget.h mainwindow.h paletteeditoradvanced.h \
+ mainwindowbase.h paletteeditoradvancedbase.h previewwidgetbase.h
+
+FORMS = mainwindowbase.ui paletteeditoradvancedbase.ui previewwidgetbase.ui
+RESOURCES = qtconfig.qrc
+
+PROJECTNAME = Qt Configuration
+TARGET = qtconfig
+DESTDIR = ../../bin
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+INCLUDEPATH += .
+DBFILE = qtconfig.db
diff --git a/tools/qtconfig/qtconfig.qrc b/tools/qtconfig/qtconfig.qrc
new file mode 100644
index 0000000000..cd6656727d
--- /dev/null
+++ b/tools/qtconfig/qtconfig.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/trolltech/qtconfig/">
+ <file>images/appicon.png</file>
+</qresource>
+</RCC>
diff --git a/tools/qtconfig/translations/translations.pro b/tools/qtconfig/translations/translations.pro
new file mode 100644
index 0000000000..fbbdb2bba2
--- /dev/null
+++ b/tools/qtconfig/translations/translations.pro
@@ -0,0 +1,13 @@
+# Include those manually as they do not contain any directory specification
+
+SOURCES += ../colorbutton.cpp ../main.cpp ../previewframe.cpp ../previewwidget.cpp ../mainwindow.cpp ../paletteeditoradvanced.cpp \
+ ../mainwindowbase.cpp ../paletteeditoradvancedbase.cpp ../previewwidgetbase.cpp
+HEADERS += ../colorbutton.h ../previewframe.h ../previewwidget.h ../mainwindow.h ../paletteeditoradvanced.h \
+ ../mainwindowbase.h ../paletteeditoradvancedbase.h ../previewwidgetbase.h
+
+FORMS = ../mainwindowbase.ui ../paletteeditoradvancedbase.ui ../previewwidgetbase.ui
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/qtconfig_pl.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qtconfig_untranslated.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qtconfig_zh_CN.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qtconfig_zh_TW.ts
diff --git a/tools/qtestlib/qtestlib.pro b/tools/qtestlib/qtestlib.pro
new file mode 100644
index 0000000000..da94e81ec1
--- /dev/null
+++ b/tools/qtestlib/qtestlib.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+!wince*: SUBDIRS += updater
+wince*: contains(QT_CONFIG, cetest): SUBDIRS += wince
+CONFIG += ordered
diff --git a/tools/qtestlib/updater/main.cpp b/tools/qtestlib/updater/main.cpp
new file mode 100644
index 0000000000..38628cffab
--- /dev/null
+++ b/tools/qtestlib/updater/main.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtCore>
+
+#include <stdio.h>
+
+QT_USE_NAMESPACE
+
+static void printHelp(char *argv[])
+{
+ qDebug("Usage: %s [-diff] FILES", argv[0] ? argv[0] : "qtest2to4");
+ qDebug("updates files from QtTestLib 2.x to QTestLib 4.1");
+ qDebug("\noptions:\n -diff Don't write any changes, output differences instead.");
+ exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+ bool printDiff = false;
+ int i = 1;
+
+ if (argc == 1)
+ printHelp(argv);
+ if (argv[1][0] == '-') {
+ if (qstrcmp(argv[1], "-diff") == 0) {
+ printDiff = true;
+ ++i;
+ } else {
+ qDebug("Unknown option: %s\n", argv[1]);
+ printHelp(argv);
+ }
+ }
+
+ QRegExp dataHeaderRx(QLatin1String("_data(\\s*)\\((\\s*)QtTestTable\\s*\\&\\s*\\w*\\s*\\)"));
+ QRegExp defElemRx(QLatin1String("\\w+\\.defineElement\\s*\\(\\s*\"(.+)\"\\s*,\\s*\"(.+)\"\\s*\\)"));
+ defElemRx.setMinimal(true);
+ QRegExp addDataRx(QLatin1String("\\*\\w+\\.newData(\\s*)(\\(\\s*\".*\"\\s*\\))"));
+ addDataRx.setMinimal(true);
+ QRegExp nsRx(QLatin1String("namespace(\\s+)QtTest"));
+ QRegExp callRx(QLatin1String("QtTest(\\s*)::"));
+
+ enum { MacroCount = 11 };
+ static const char *macroNames[MacroCount] = {
+ "VERIFY", "FAIL", "VERIFY2", "COMPARE", "SKIP", "VERIFY_EVENT",
+ "EXPECT_FAIL", "FETCH", "FETCH_GLOBAL", "TEST", "WARN"
+ };
+
+ for (; i < argc; ++i) {
+ QFile f(QString::fromLocal8Bit(argv[i]));
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ qFatal("Unable to open file '%s' for reading: %s", argv[i], qPrintable(f.errorString()));
+
+ if (printDiff)
+ printf("diff %s\n", argv[i]);
+
+ QStringList contents;
+ int lineNumber = 0;
+ int changedLines = 0;
+ while (!f.atEnd()) {
+ QString origLine = QString::fromLatin1(f.readLine());
+ QString line = origLine;
+ ++lineNumber;
+
+ if (dataHeaderRx.indexIn(line) != -1) {
+ QString ws = dataHeaderRx.cap(1);
+ line.replace(dataHeaderRx, QString::fromLatin1("_data%1()").arg(ws));
+ }
+ if (defElemRx.indexIn(line) != -1) {
+ QString type = defElemRx.cap(1);
+ QString name = defElemRx.cap(2);
+ if (type.endsWith(QLatin1Char('>')))
+ type.append(QLatin1Char(' '));
+ line.replace(defElemRx, QString::fromLatin1("QTest::addColumn<%1>(\"%2\")").arg(
+ type).arg(name));
+ }
+ if (addDataRx.indexIn(line) != -1) {
+ QString repl = QLatin1String("QTest::newRow");
+ repl += addDataRx.cap(1);
+ repl += addDataRx.cap(2);
+ line.replace(addDataRx, repl);
+ }
+ if (nsRx.indexIn(line) != -1)
+ line.replace(nsRx, QString::fromLatin1("namespace%1QTest").arg(nsRx.cap(1)));
+ int pos = 0;
+ while ((pos = callRx.indexIn(line, pos)) != -1) {
+ line.replace(callRx, QString::fromLatin1("QTest%1::").arg(callRx.cap(1)));
+ pos += callRx.matchedLength();
+ }
+
+ line.replace(QLatin1String("QTTEST_MAIN"), QLatin1String("QTEST_MAIN"));
+ line.replace(QLatin1String("QTTEST_APPLESS_MAIN"), QLatin1String("QTEST_APPLESS_MAIN"));
+ line.replace(QLatin1String("QTTEST_NOOP_MAIN"), QLatin1String("QTEST_NOOP_MAIN"));
+ line.replace(QLatin1String("QtTestEventLoop"), QLatin1String("QTestEventLoop"));
+ line.replace(QLatin1String("QtTestEventList"), QLatin1String("QTestEventList"));
+ line.replace(QLatin1String("QtTestAccessibility"), QLatin1String("QTestAccessibility"));
+ line.replace(QLatin1String("QTest::sleep"), QLatin1String("QTest::qSleep"));
+ line.replace(QLatin1String("QTest::wait"), QLatin1String("QTest::qWait"));
+
+ for (int m = 0; m < MacroCount; ++m) {
+ QRegExp macroRe(QString::fromLatin1("\\b%1(\\s*\\()").arg(
+ QLatin1String(macroNames[m])));
+ QString newMacroName = QLatin1Char('Q') + QString::fromLatin1(macroNames[m]);
+ int pos = 0;
+ while ((pos = macroRe.indexIn(line)) != -1) {
+ line.replace(macroRe, newMacroName + macroRe.cap(1));
+ pos += macroRe.matchedLength();
+ }
+ }
+
+ if (line != origLine) {
+ if (printDiff) {
+ printf("%dc%d\n", lineNumber, lineNumber);
+ printf("<%s", qPrintable(origLine));
+ printf("---\n");
+ printf(">%s", qPrintable(line));
+ }
+ ++changedLines;
+ }
+
+ contents.append(line);
+ }
+ f.close();
+
+ if (printDiff)
+ continue;
+ qDebug("%s: %d change%s made.", argv[i], changedLines, changedLines == 1 ? "" : "s");
+ if (!changedLines)
+ continue;
+
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
+ qFatal("Unable to open file '%s' for writing: %s", argv[i], qPrintable(f.errorString()));
+ foreach (QString s, contents)
+ f.write(s.toLatin1());
+ f.close();
+ }
+
+ return 0;
+}
+
diff --git a/tools/qtestlib/updater/updater.pro b/tools/qtestlib/updater/updater.pro
new file mode 100644
index 0000000000..42e1b74bdf
--- /dev/null
+++ b/tools/qtestlib/updater/updater.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET +=
+DEPENDPATH += .
+INCLUDEPATH += .
+
+SOURCES += main.cpp
+
+QT = core
+
+DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp
new file mode 100644
index 0000000000..fc0e7b43b2
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp
@@ -0,0 +1,485 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "activesyncconnection.h"
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo>
+#include <rapi.h>
+
+extern void debugOutput(const QString& text, int level);
+
+ActiveSyncConnection::ActiveSyncConnection()
+ : AbstractRemoteConnection()
+ , connected(false)
+{
+}
+
+ActiveSyncConnection::~ActiveSyncConnection()
+{
+ if (isConnected())
+ disconnect();
+}
+
+bool ActiveSyncConnection::connect(QVariantList&)
+{
+ if (connected)
+ return true;
+ connected = false;
+ RAPIINIT init;
+ init.cbSize = sizeof(init);
+ if (CeRapiInitEx(&init) != S_OK)
+ return connected;
+
+ DWORD res;
+ res = WaitForMultipleObjects(1,&(init.heRapiInit),true, 5000);
+ if ((res == -1) || (res == WAIT_TIMEOUT) || (init.hrRapiInit != S_OK))
+ return connected;
+
+ connected = true;
+ return connected;
+}
+
+void ActiveSyncConnection::disconnect()
+{
+ connected = false;
+ CeRapiUninit();
+}
+
+bool ActiveSyncConnection::isConnected() const
+{
+ return connected;
+}
+
+bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists)
+{
+ if (failIfExists) {
+ CE_FIND_DATA search;
+ HANDLE searchHandle = CeFindFirstFile(deviceDest.utf16(), &search);
+ if (searchHandle != INVALID_HANDLE_VALUE) {
+ CeFindClose(searchHandle);
+ return false;
+ }
+ }
+
+ QFile file(localSource);
+ if (!file.exists())
+ return false;
+ if (!file.open(QIODevice::ReadOnly)) {
+ debugOutput(QString::fromLatin1(" Could not open source file"),2);
+ if (file.size() == 0) {
+ // Create an empy file
+ deleteFile(deviceDest);
+ HANDLE deviceHandle = CeCreateFile(deviceDest.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (deviceHandle != INVALID_HANDLE_VALUE) {
+ CeCloseHandle(deviceHandle);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ deleteFile(deviceDest);
+ HANDLE deviceHandle = CeCreateFile(deviceDest.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (deviceHandle == INVALID_HANDLE_VALUE) {
+ debugOutput(QString::fromLatin1(" Could not create target file"), 2);
+ return false;
+ }
+
+ DWORD written = 0;
+ int currentPos = 0;
+ int size = file.size();
+ DWORD toWrite = 0;
+ const int bufferSize = 65000;
+ QByteArray data;
+ data.reserve(bufferSize);
+ while (currentPos < size) {
+ data = file.read(bufferSize);
+ if (data.size() <= 0) {
+ wprintf( L"Error while reading file!\n");
+ return false;
+ }
+ if (size - currentPos > bufferSize )
+ toWrite = bufferSize;
+ else
+ toWrite = size - currentPos;
+ if (toWrite == 0)
+ break;
+ if (!CeWriteFile(deviceHandle, data.data() , toWrite, &written, NULL)) {
+ debugOutput(QString::fromLatin1(" Could not write File"), 2);
+ return false;
+ }
+ currentPos += written;
+ data.clear();
+ wprintf( L"%s -> %s (%d / %d) %d %%\r", localSource.utf16() , deviceDest.utf16(), currentPos , size, (100*currentPos)/size );
+ }
+ wprintf(L"\n");
+
+ // Copy FileTime for update verification
+ FILETIME creationTime, accessTime, writeTime;
+ HANDLE localHandle = CreateFile(localSource.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (localHandle != INVALID_HANDLE_VALUE) {
+ if (GetFileTime(localHandle, &creationTime, &accessTime, &writeTime)) {
+ LocalFileTimeToFileTime(&writeTime, &writeTime);
+ if (!CeSetFileTime(deviceHandle, &writeTime, NULL, NULL)) {
+ debugOutput(QString::fromLatin1(" Could not write time values"), 0);
+ }
+ }
+ CloseHandle(localHandle);
+ }
+ CeCloseHandle(deviceHandle);
+
+ DWORD attributes = GetFileAttributes(localSource.utf16());
+ if (attributes != -1 )
+ CeSetFileAttributes(deviceDest.utf16(), attributes);
+ return true;
+}
+
+bool ActiveSyncConnection::copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive)
+{
+ QDir dir(localSource);
+ if (!dir.exists())
+ return false;
+
+ deleteDirectory(deviceDest, recursive);
+ CeCreateDirectory(deviceDest.utf16(), NULL);
+ foreach(QString entry, dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot)) {
+ QString source = localSource + "\\" + entry;
+ QString target = deviceDest + "\\" + entry;
+ QFileInfo info(source);
+ if (info.isDir()) {
+ if (recursive) {
+ if (!copyDirectoryToDevice(source, target, recursive))
+ return false;
+ }
+ } else {
+ if (!copyFileToDevice(source, target))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ActiveSyncConnection::copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists)
+{
+ QFile target(localDest);
+ if (failIfExists && target.exists()) {
+ debugOutput(QString::fromLatin1(" Not allowed to overwrite file"), 2);
+ return false;
+ }
+
+ if (target.exists())
+ target.remove();
+
+ HANDLE deviceHandle = CeCreateFile(deviceSource.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (deviceHandle == INVALID_HANDLE_VALUE) {
+ debugOutput(QString::fromLatin1(" Could not open file on device"), 2);
+ return false;
+ }
+
+ DWORD fileSize = CeGetFileSize( deviceHandle, NULL );
+ if (fileSize == -1) {
+ debugOutput(QString::fromLatin1(" Could not stat filesize of remote file"), 2);
+ CeCloseHandle(deviceHandle);
+ return false;
+ }
+
+ if (!target.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ debugOutput(QString::fromLatin1(" Could not open local file for writing"), 2);
+ CeCloseHandle(deviceHandle);
+ return false;
+ }
+
+ int bufferSize = 65000;
+ char *buffer = (char*) malloc(bufferSize);
+ DWORD bufferRead = 0;
+ DWORD bufferWritten = 0;
+ bool readUntilEnd = false;
+ while(CeReadFile(deviceHandle, buffer, bufferSize, &bufferRead, NULL)) {
+ if (bufferRead == 0) {
+ readUntilEnd = true;
+ break;
+ }
+ target.write(buffer, bufferRead);
+ bufferWritten += bufferRead;
+ wprintf(L"%s -> %s (%d / %d) %d %%\r", deviceSource.utf16(), localDest.utf16(), bufferWritten, fileSize, (100*bufferWritten)/fileSize);
+ }
+ wprintf(L"\n");
+
+ if (!readUntilEnd) {
+ debugOutput(QString::fromLatin1(" an error occured during copy"), 2);
+ return false;
+ }
+
+ CeCloseHandle(deviceHandle);
+ return true;
+}
+
+bool ActiveSyncConnection::copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive)
+{
+ if (!QDir(localDest).exists() && !QDir(localDest).mkpath(QDir(localDest).absolutePath())) {
+ debugOutput(QString::fromLatin1(" Could not create local path"), 2);
+ }
+
+ QString searchArg = deviceSource + "\\*";
+ CE_FIND_DATA data;
+ HANDLE searchHandle = CeFindFirstFile(searchArg.utf16(), &data);
+ if (searchHandle == INVALID_HANDLE_VALUE) {
+ // We return true because we might be in a recursive call
+ // where nothing is to copy and the copy process
+ // might still be correct
+ return true;
+ }
+
+ do {
+ QString srcFile = deviceSource + "\\" + QString::fromUtf16(data.cFileName);
+ QString destFile = localDest + "\\" + QString::fromUtf16(data.cFileName);
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (recursive && !copyDirectoryFromDevice(srcFile, destFile, recursive)) {
+ wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16());
+ return false;
+ }
+ } else {
+ copyFileFromDevice(srcFile, destFile, false);
+ }
+ } while(CeFindNextFile(searchHandle, &data));
+ CeFindClose(searchHandle);
+ return true;
+}
+
+bool ActiveSyncConnection::copyFile(const QString &srcFile, const QString &destFile, bool failIfExists)
+{
+ return CeCopyFile(QDir::toNativeSeparators(srcFile).utf16(),
+ QDir::toNativeSeparators(destFile).utf16(), failIfExists);
+}
+
+bool ActiveSyncConnection::copyDirectory(const QString &srcDirectory, const QString &destDirectory,
+ bool recursive)
+{
+ CeCreateDirectory(destDirectory.utf16(), NULL);
+ QString searchArg = srcDirectory + "\\*";
+ CE_FIND_DATA data;
+ HANDLE searchHandle = CeFindFirstFile(searchArg.utf16(), &data);
+ if (searchHandle == INVALID_HANDLE_VALUE) {
+ // We return true because we might be in a recursive call
+ // where nothing is to copy and the copy process
+ // might still be correct
+ return true;
+ }
+
+ do {
+ QString srcFile = srcDirectory + "\\" + QString::fromUtf16(data.cFileName);
+ QString destFile = destDirectory + "\\" + QString::fromUtf16(data.cFileName);
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (recursive && !copyDirectory(srcFile, destFile, recursive)) {
+ wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16());
+ return false;
+ }
+ } else {
+ debugOutput(QString::fromLatin1("Copy %1 -> %2\n").arg(srcFile).arg(destFile), 0);
+ CeCopyFile(srcFile.utf16(), destFile.utf16(), false);
+ }
+ } while(CeFindNextFile(searchHandle, &data));
+ CeFindClose(searchHandle);
+ return true;
+}
+
+bool ActiveSyncConnection::deleteFile(const QString &fileName)
+{
+ CeSetFileAttributes(fileName.utf16(), FILE_ATTRIBUTE_NORMAL);
+ return CeDeleteFile(fileName.utf16());
+}
+
+bool ActiveSyncConnection::deleteDirectory(const QString &directory, bool recursive, bool failIfContentExists)
+{
+ HANDLE hFind;
+ CE_FIND_DATA FindFileData;
+ QString FileName = directory + "\\*";
+ hFind = CeFindFirstFile(FileName.utf16(), &FindFileData);
+ if( hFind == INVALID_HANDLE_VALUE )
+ return CeRemoveDirectory(directory.utf16());
+
+ if (failIfContentExists)
+ return false;
+
+ do {
+ QString FileName = directory + "\\" + QString::fromUtf16(FindFileData.cFileName);
+ if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (recursive)
+ if (!deleteDirectory(FileName, recursive, failIfContentExists))
+ return false;
+ } else {
+ if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ CeSetFileAttributes(FileName.utf16(), FILE_ATTRIBUTE_NORMAL);
+ if( !CeDeleteFile(FileName.utf16()) )
+ break;
+ }
+ } while(CeFindNextFile(hFind,&FindFileData));
+ CeFindClose(hFind);
+
+ return CeRemoveDirectory(directory.utf16());
+}
+
+bool ActiveSyncConnection::execute(QString program, QString arguments, int timeout, int *returnValue)
+{
+ if (!isConnected()) {
+ qWarning("Cannot execute, connect to device first!");
+ return false;
+ }
+
+ PROCESS_INFORMATION* pid = new PROCESS_INFORMATION;
+ bool result = false;
+ if (timeout != 0) {
+ // If we want to wait, we have to use CeRapiInvoke, as CeCreateProcess has no way to wait
+ // until the process ends. The lib must have been build and also deployed already.
+ if (!isConnected() && !connect())
+ return false;
+
+ QString dllLocation = "\\Windows\\QtRemote.dll";
+ QString functionName = "qRemoteLaunch";
+
+ DWORD outputSize;
+ BYTE* output;
+ IRAPIStream *stream;
+ int returned = 0;
+ HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0);
+ if (S_OK != res) {
+ if (S_OK != CeGetLastError())
+ debugOutput(QString::fromLatin1("Error: Could not invoke method on QtRemote"),1);
+ else
+ debugOutput(QString::fromLatin1("Error: QtRemote return unexpectedly with error Code %1").arg(res), 1);
+ } else {
+ DWORD written;
+ int strSize = program.length();
+ if (S_OK != stream->Write(&strSize, sizeof(strSize), &written)) {
+ qWarning(" Could not write appSize to process");
+ return false;
+ }
+ if (S_OK != stream->Write(program.utf16(), program.length()*sizeof(wchar_t), &written)) {
+ qWarning(" Could not write appName to process");
+ return false;
+ }
+ strSize = arguments.length();
+ if (S_OK != stream->Write(&strSize, sizeof(strSize), &written)) {
+ qWarning(" Could not write argumentSize to process");
+ return false;
+ }
+ if (S_OK != stream->Write(arguments.utf16(), arguments.length()*sizeof(wchar_t), &written)) {
+ qWarning(" Could not write arguments to process");
+ return false;
+ }
+ if (S_OK != stream->Write(&timeout, sizeof(timeout), &written)) {
+ qWarning(" Could not write waiting option to process");
+ return false;
+ }
+
+ if (S_OK != stream->Read(&returned, sizeof(returned), &written)) {
+ qWarning(" Could not access return value of process");
+ }
+ result = true;
+ }
+
+
+ if (returnValue)
+ *returnValue = returned;
+ } else {
+ // We do not need to invoke another lib etc, if we are not interested in results anyway...
+ result = CeCreateProcess(program.utf16(), arguments.utf16(), 0, 0, false, 0, 0, 0, 0, pid);
+ }
+ return result;
+}
+
+bool ActiveSyncConnection::createDirectory(const QString &path, bool deleteBefore)
+{
+ if (deleteBefore)
+ deleteDirectory(path);
+ QStringList separated = path.split(QLatin1Char('\\'));
+ QString current = QLatin1String("\\");
+ bool result;
+ for (int i=1; i < separated.size(); ++i) {
+ current += separated.at(i);
+ result = CeCreateDirectory(current.utf16(), NULL);
+ current += QLatin1String("\\");
+ }
+ return result;
+}
+
+bool ActiveSyncConnection::timeStampForLocalFileTime(FILETIME* fTime) const
+{
+ QString tmpFile = QString::fromLatin1("\\qt_tmp_ftime_convert");
+ HANDLE remoteHandle = CeCreateFile(tmpFile.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (remoteHandle == INVALID_HANDLE_VALUE)
+ return false;
+
+ LocalFileTimeToFileTime(fTime, fTime);
+
+ if (!CeSetFileTime(remoteHandle, fTime, NULL, NULL)) {
+ CeCloseHandle(remoteHandle);
+ return false;
+ }
+
+ CeCloseHandle(remoteHandle);
+ remoteHandle = CeCreateFile(tmpFile.utf16(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (remoteHandle == INVALID_HANDLE_VALUE)
+ return false;
+ if (!CeGetFileTime(remoteHandle, fTime, NULL, NULL)) {
+ CeCloseHandle(remoteHandle);
+ return false;
+ }
+
+ CeCloseHandle(remoteHandle);
+ CeDeleteFile(tmpFile.utf16());
+ return true;
+}
+
+bool ActiveSyncConnection::fileCreationTime(const QString &fileName, FILETIME* deviceCreationTime) const
+{
+ HANDLE deviceHandle = CeCreateFile(fileName.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (deviceHandle == INVALID_HANDLE_VALUE)
+ return false;
+
+ bool result = true;
+ if (!CeGetFileTime(deviceHandle, deviceCreationTime, NULL, NULL))
+ result = false;
+
+ CeCloseHandle(deviceHandle);
+ return result;
+}
diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.h b/tools/qtestlib/wince/cetest/activesyncconnection.h
new file mode 100644
index 0000000000..44ff356b6f
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/activesyncconnection.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ACTIVESYNC_REMOTECONNECTION_H
+#define ACTIVESYNC_REMOTECONNECTION_H
+
+#include "remoteconnection.h"
+
+#if defined(Q_OS_WIN32)
+#define REMOTELIBNAME "remotecommands"
+#endif
+
+class ActiveSyncConnection : public AbstractRemoteConnection
+{
+public:
+ ActiveSyncConnection();
+ virtual ~ActiveSyncConnection();
+
+ bool connect(QVariantList &list = QVariantList());
+ void disconnect();
+ bool isConnected() const;
+
+ // These functions are designed for transfer between desktop and device
+ // Caution: deviceDest path has to be device specific (eg. no drive letters for CE)
+ bool copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists = false);
+ bool copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive = true);
+ bool copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists = false);
+ bool copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive = true);
+
+ bool timeStampForLocalFileTime(FILETIME*) const;
+ bool fileCreationTime(const QString &fileName, FILETIME*) const;
+
+ // These functions only work on files existing on the device
+ bool copyFile(const QString&, const QString&, bool failIfExists = false);
+ bool copyDirectory(const QString&, const QString&, bool recursive = true);
+ bool deleteFile(const QString&);
+ bool deleteDirectory(const QString&, bool recursive = true, bool failIfContentExists = false);
+ bool moveFile(const QString&, const QString&, bool FailIfExists = false);
+ bool moveDirectory(const QString&, const QString&, bool recursive = true);
+
+ bool createDirectory(const QString&, bool deleteBefore=false);
+
+ bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL);
+private:
+ bool connected;
+};
+
+#endif
diff --git a/tools/qtestlib/wince/cetest/bootstrapped.pri b/tools/qtestlib/wince/cetest/bootstrapped.pri
new file mode 100644
index 0000000000..39f24c2577
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/bootstrapped.pri
@@ -0,0 +1,38 @@
+# Bootstrapped Input
+SOURCES += \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstring.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qbuffer.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qurl.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qsettings.cpp \
+ $$QT_SOURCE_TREE/src/corelib/io/qsettings_win.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qdatetime.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlocale.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearray.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbytearraymatcher.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvector.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qvsnprintf.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qlistdata.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qhash.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qglobal.cpp \
+ $$QT_BUILD_TREE/src/corelib/global/qconfig.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qmalloc.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qnumeric.cpp \
+ $$QT_SOURCE_TREE/src/corelib/global/qlibraryinfo.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qregexp.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \
+ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qmetatype.cpp \
+ $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp
diff --git a/tools/qtestlib/wince/cetest/cetest.pro b/tools/qtestlib/wince/cetest/cetest.pro
new file mode 100644
index 0000000000..d66fa33182
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/cetest.pro
@@ -0,0 +1,47 @@
+TEMPLATE = app
+TARGET = cetest
+DESTDIR = ../../../../bin
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+CONFIG += console no_batch
+CONFIG -= qt
+
+DEFINES += QT_BUILD_QMAKE QT_BOOTSTRAPPED QT_NO_CODECS QT_LITE_UNICODE QT_NO_LIBRARY \
+ QT_NO_STL QT_NO_COMPRESS QT_NO_DATASTREAM \
+ QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_NO_THREAD \
+ QT_NO_SYSTEMLOCALE QT_NO_GEOM_VARIANT \
+ QT_NODLL QT_NO_QOBJECT
+
+INCLUDEPATH = \
+ $$QT_SOURCE_TREE/tools/qtestlib/ce/cetest \
+ $$QT_SOURCE_TREE/qmake \
+ $$QT_BUILD_TREE/include \
+ $$QT_BUILD_TREE/include/QtCore \
+ $$QT_BUILD_TREE/include/QtScript \
+ $$QT_BUILD_TREE/src/corelib/global
+
+DEPENDPATH += $$QT_BUILD_TREE/src/corelib/tools $$QT_BUILD_TREE/src/corelib/io
+
+# Input
+HEADERS += \
+ remoteconnection.h \
+ activesyncconnection.h \
+ deployment.h
+
+SOURCES += \
+ remoteconnection.cpp \
+ activesyncconnection.cpp \
+ deployment.cpp \
+ main.cpp
+
+win32-msvc*:LIBS += ole32.lib advapi32.lib rapi.lib
+
+include(qmake_include.pri)
+include(bootstrapped.pri)
+include($$QT_SOURCE_TREE/src/script/script.pri)
+
+INCLUDEPATH += $$QT_CE_RAPI_INC
+LIBS += -L$$QT_CE_RAPI_LIB
diff --git a/tools/qtestlib/wince/cetest/deployment.cpp b/tools/qtestlib/wince/cetest/deployment.cpp
new file mode 100644
index 0000000000..99ea532161
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/deployment.cpp
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deployment.h"
+#include "remoteconnection.h"
+#include <option.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qstring.h>
+
+extern void debugOutput(const QString& text, int level);
+
+bool DeploymentHandler::deviceCopy(const DeploymentList &deploymentList)
+{
+ for (int i=0; i<deploymentList.size(); ++i) {
+ CopyItem item = deploymentList.at(i);
+ m_connection->createDirectory(item.to.left(item.to.lastIndexOf(QLatin1Char('\\'))));
+ if (!m_connection->copyFileToDevice(item.from , item.to)) {
+ debugOutput(QString::fromLatin1("Error while copy: %1 -> %2").arg(item.from).arg(item.to),0);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DeploymentHandler::deviceDeploy(const DeploymentList &deploymentList)
+{
+ DeploymentList copyList;
+ for (int i=0; i<deploymentList.size(); ++i) {
+#if defined(Q_OS_WIN)
+ HANDLE localHandle = CreateFile(deploymentList.at(i).from.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (localHandle == INVALID_HANDLE_VALUE) {
+ copyList.append(deploymentList.at(i));
+ continue;
+ }
+ FILETIME localCreationTime;
+ if (!GetFileTime(localHandle, NULL, NULL, &localCreationTime) || !m_connection->timeStampForLocalFileTime(&localCreationTime)) {
+ copyList.append(deploymentList.at(i));
+ CloseHandle(localHandle);
+ continue;
+ }
+ CloseHandle(localHandle);
+
+ FILETIME deviceCreationTime;
+ if (!m_connection->fileCreationTime(deploymentList.at(i).to , &deviceCreationTime)) {
+ copyList.append(deploymentList.at(i));
+ continue;
+ }
+
+ int res = CompareFileTime(&localCreationTime, &deviceCreationTime);
+ if (res != 0)
+ copyList.append(deploymentList.at(i));
+ else
+ debugOutput(QString::fromLatin1("Skipping File %1, already latest version").arg(deploymentList.at(i).from),0);
+#else
+ copyList.append(deploymentList.at(i));
+#endif
+ }
+ return deviceCopy(copyList);
+}
+
+void DeploymentHandler::cleanup(const DeploymentList &deploymentList)
+{
+ for (int i=0; i<deploymentList.size(); ++i) {
+ m_connection->deleteFile(deploymentList.at(i).to);
+#ifdef Q_OS_WIN
+ QString path = deploymentList.at(i).to;
+ int pos;
+ while ( (pos = path.lastIndexOf(QLatin1Char('\\'))) > 0) {
+ path = path.left(pos);
+ if (!m_connection->deleteDirectory(path, false, true))
+ break;
+ }
+#endif
+ }
+}
+
+void DeploymentHandler::initQtDeploy(QMakeProject *project, DeploymentList &deploymentList, const QString &testPath)
+{
+ QString targetPath = project->values("deploy.path").join(" ");
+ if (targetPath.isEmpty())
+ targetPath = testPath;
+ if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
+ targetPath = targetPath.mid(0,targetPath.size()-1);
+
+ // Only deploy Qt libs for shared build
+ if (!project->values("QMAKE_QT_DLL").isEmpty() && !project->values("QMAKE_LIBDIR").isEmpty()) {
+ QStringList libs = project->values("LIBS");
+ QStringList qtLibs;
+ foreach (QString item, libs) {
+ if (item.startsWith("-lQt")) {
+ qtLibs += project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + item.mid(2) + QLatin1String("4.dll");
+ } else {
+ QFileInfo info(item);
+ if (info.exists() && info.isAbsolute() && info.fileName().startsWith(QLatin1String("Qt")))
+ qtLibs += info.dir().absoluteFilePath(info.fileName().replace(QLatin1String(".lib"), QLatin1String(".dll")));
+ }
+ }
+ for (QStringList::ConstIterator it = qtLibs.constBegin(); it != qtLibs.constEnd(); ++it) {
+ QString dllName = *it;
+ QFileInfo info(dllName);
+ if (!info.exists())
+ continue;
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absoluteFilePath()) ,
+ Option::fixPathToLocalOS(targetPath + "/" + info.fileName())));
+ }
+ }
+
+ // QtRemote deployment. We always deploy to \Windows
+ if (!project->values("QMAKE_LIBDIR").isEmpty()) {
+ QString remoteLibName = QLatin1String("QtRemote.dll");
+ QString remoteLib = Option::fixPathToLocalOS(project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + remoteLibName);
+ if (QFile::exists(remoteLib))
+ deploymentList.append(CopyItem(remoteLib, QString::fromLatin1("\\Windows\\") + remoteLibName));
+ else
+ debugOutput(QString::fromLatin1("Could not find QtRemote. Might not be able to launch target executable"),0);
+ }
+
+ // C-runtime deployment
+ QString runtime = project->values("QT_CE_C_RUNTIME").join(QLatin1String(" "));
+ debugOutput(QString::fromLatin1("Runtime:%1").arg(runtime), 2);
+ if (!runtime.isEmpty() && (runtime != QLatin1String("no"))) {
+ QString runtimeVersion = QLatin1String("msvcr");
+ const QString mkspec = project->values("QMAKESPEC").first();
+ if (mkspec.endsWith("2008"))
+ runtimeVersion.append("90");
+ else
+ runtimeVersion.append("80");
+ if (project->isActiveConfig("debug"))
+ runtimeVersion.append("d");
+ runtimeVersion.append(".dll");
+
+ if (runtime == "yes") {
+ // Auto-find C-runtime
+ QString vcInstallDir = qgetenv("VCINSTALLDIR");
+ if (!vcInstallDir.isEmpty()) {
+ vcInstallDir += "\\ce\\dll\\";
+ vcInstallDir += project->values("CE_ARCH").join(QLatin1String(" "));
+ if (!QFileInfo(vcInstallDir + QDir::separator() + runtimeVersion).exists())
+ runtime.clear();
+ else
+ runtime = vcInstallDir;
+ }
+ }
+
+ if (!runtime.isEmpty()) {
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(runtime + "/" + runtimeVersion ) ,
+ Option::fixPathToLocalOS(targetPath + "/" + runtimeVersion)));
+ }
+ }
+}
+
+void DeploymentHandler::initProjectDeploy(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath)
+{
+ QString targetPath = project->values("deploy.path").join(" ");
+ if (targetPath.isEmpty())
+ targetPath = testPath;
+ if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
+ targetPath = targetPath.mid(0,targetPath.size()-1);
+
+ QStringList& list = project->values("DEPLOYMENT");
+ if (list.isEmpty())
+ return;
+
+ for (int it = 0; it < list.size(); ++it) {
+ QString argSource = list.at(it) + QString(".sources");
+ QString argPath = list.at(it) + QString(".path");
+ if ((project->values(argSource).isEmpty() || project->values(argPath).isEmpty()) && list.at(it) != "deploy") {
+ debugOutput(QString::fromLatin1("cannot deploy \"%1\" because of missing data.").arg(list.at(it)), 0);
+ continue;
+ }
+
+ QString addPath = project->values(argPath).join(QLatin1String(" "));
+ if (addPath == QLatin1String("."))
+ addPath.clear();
+ if (!addPath.startsWith("/") && !addPath.startsWith(QLatin1String("\\")))
+ addPath = targetPath + "/" + addPath;
+
+ QStringList addSources = project->values(argSource);
+ addSources.replaceInStrings(QLatin1String("/"), QLatin1String("\\"));
+ for(int index=0; index < addSources.size(); ++index) {
+ QString dirstr = qmake_getpwd();
+ QString filestr = Option::fixPathToLocalOS(addSources.at(index), false, false);
+ int slsh = filestr.lastIndexOf(Option::dir_sep);
+ if(slsh != -1) {
+ dirstr = filestr.left(slsh+1);
+ filestr = filestr.right(filestr.length() - slsh - 1);
+ }
+ if(dirstr.right(Option::dir_sep.length()) != Option::dir_sep)
+ dirstr += Option::dir_sep;
+ QFileInfo info(dirstr + filestr);
+
+ static int addQMakeDeployCounter = 0;
+ QStringList entryList = info.absoluteDir().entryList(QStringList() << info.fileName());
+ if (entryList.size() > 1) {
+ foreach(QString s, entryList) {
+ // We do not include directories when using wildcards
+ QFileInfo wildInfo(info.absolutePath() + "/" + s);
+ if (wildInfo.isDir()) {
+ continue;
+ }
+ QString appendedQmakeDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++);
+ project->parse(appendedQmakeDeploy + QLatin1String(".sources = \"") + wildInfo.absoluteFilePath());
+ project->parse(appendedQmakeDeploy + QLatin1String(".path = \"") + addPath);
+ list.append(appendedQmakeDeploy);
+ }
+ continue;
+ }
+
+ if (info.isDir()) {
+ QDir additionalDir(dirstr + filestr);
+ QStringList additionalEntries = additionalDir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::NoSymLinks);
+ foreach(QString item, additionalEntries) {
+ QString appendedDeploy = QString::fromLatin1("_q_make_additional_deploy_%1").arg(addQMakeDeployCounter++);
+ project->parse(appendedDeploy + QLatin1String(".sources = \"") + Option::fixPathToLocalOS(additionalDir.absoluteFilePath(item)) + QLatin1String("\""));
+ QString appendTargetPath = project->values(argPath).join(QLatin1String(" "));
+ if (appendTargetPath == QLatin1String("."))
+ appendTargetPath = filestr;
+ else
+ appendTargetPath.append(QLatin1String("\\") + filestr);
+ project->parse(appendedDeploy + QLatin1String(".path = ") + appendTargetPath);
+ list.append(appendedDeploy);
+ }
+ } else if (entryList.size() == 1)
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absolutePath() + "/" + entryList.at(0)) ,
+ Option::fixPathToLocalOS(addPath + "/" + entryList.at(0))));
+ }
+ }
+}
diff --git a/tools/qtestlib/wince/cetest/deployment.h b/tools/qtestlib/wince/cetest/deployment.h
new file mode 100644
index 0000000000..aa994ef6a9
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/deployment.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEPLOYMENT_INCL
+#define DEPLOYMENT_INCL
+
+#include <qstring.h>
+#include <qlist.h>
+#include <project.h>
+
+class AbstractRemoteConnection;
+
+struct CopyItem
+{
+ CopyItem(const QString& f, const QString& t) : from(f) , to(t) { }
+ QString from;
+ QString to;
+};
+typedef QList<CopyItem> DeploymentList;
+
+class DeploymentHandler
+{
+public:
+ inline void setConnection(AbstractRemoteConnection*);
+ inline AbstractRemoteConnection* connection() const;
+ bool deviceCopy(const DeploymentList &deploymentList);
+ bool deviceDeploy(const DeploymentList &deploymentList);
+ void cleanup(const DeploymentList &deploymentList);
+ static void initProjectDeploy(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath = "\\Program Files\\qt_test");
+ static void initQtDeploy(QMakeProject* project, DeploymentList &deploymentList, const QString &testPath = "\\Program Files\\qt_test");
+private:
+ AbstractRemoteConnection* m_connection;
+};
+
+inline void DeploymentHandler::setConnection(AbstractRemoteConnection *connection) { m_connection = connection; }
+inline AbstractRemoteConnection* DeploymentHandler::connection() const { return m_connection; }
+#endif \ No newline at end of file
diff --git a/tools/qtestlib/wince/cetest/main.cpp b/tools/qtestlib/wince/cetest/main.cpp
new file mode 100644
index 0000000000..17f681070e
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/main.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "activesyncconnection.h"
+#include "deployment.h"
+#include <option.h>
+#include <project.h>
+#include <property.h>
+#include <qstringlist.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <iostream>
+using namespace std;
+
+const int debugLevel = 0;
+void debugOutput(const QString& text, int level)
+{
+ if (level <= debugLevel)
+ cout << qPrintable(text) << endl;
+}
+
+// needed for QMake sources to compile
+QString project_builtin_regx() { return QString();}
+static QString pwd;
+QString qmake_getpwd()
+{
+ if(pwd.isNull())
+ pwd = QDir::currentPath();
+ return pwd;
+}
+bool qmake_setpwd(const QString &p)
+{
+ if(QDir::setCurrent(p)) {
+ pwd = QDir::currentPath();
+ return true;
+ }
+ return false;
+}
+
+namespace TestConfiguration {
+ QString localExecutable;
+ QString localQtConf;
+ QString remoteTestPath;
+ QString remoteLibraryPath;
+ QString remoteExecutable;
+ QString remoteResultFile;
+
+ bool testDebug;
+ void init()
+ {
+ testDebug = true;
+ localQtConf = QLatin1String("no");
+ remoteTestPath = QLatin1String("\\Program Files\\qt_test");
+ remoteLibraryPath = remoteTestPath;
+ remoteResultFile = QLatin1String("\\qt_test_results.txt");
+ }
+}
+
+void usage()
+{
+ cout <<
+ "QTestLib options\n"
+ " -functions : Returns a list of current testfunctions\n"
+ " -xml : Outputs results as XML document\n"
+ " -lightxml : Outputs results as stream of XML tags\n"
+ " -o filename: Writes all output into a file\n"
+ " -silent : Only outputs warnings and failures\n"
+ " -v1 : Print enter messages for each testfunction\n"
+ " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n"
+ " -vs : Print every signal emitted\n"
+ " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
+ " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
+ " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
+ " -keyevent-verbose : Turn on verbose messages for keyboard simulation\n"
+ " -maxwarnings n : Sets the maximum amount of messages to output.\n"
+ " 0 means unlimited, default: 2000\n"
+ " -help : This help\n";
+ cout <<
+ "cetest specific options\n"
+ " -debug : Test debug version[default]\n"
+ " -release : Test release version\n"
+ " -libpath <path> : Remote path to deploy Qt libraries to\n"
+ " -qt-delete : Delete the Qt libraries after execution\n"
+ " -project-delete : Delete the project file(s) after execution\n"
+ " -delete : Delete everything deployed after execution\n"
+ " -conf : Specify location of qt.conf file\n"
+ " -f <file> : Specify project file\n"
+ " -cache <file> : Specify .qmake.cache file to use\n"
+ " -timeout <value> : Specify a timeout value after which the test will be terminated\n"
+ " -1 specifies waiting forever (default)\n"
+ " 0 specifies starting the process detached\n"
+ " >0 wait <value> seconds\n"
+ "\n";
+}
+
+int main(int argc, char **argv)
+{
+ QStringList arguments;
+ for (int i=0; i<argc; ++i)
+ arguments.append(QString::fromLatin1(argv[i]));
+
+ TestConfiguration::init();
+
+ QStringList launchArguments;
+ QString resultFile;
+ QString proFile;
+ QString cacheFile;
+ int timeout = -1;
+ bool cleanupQt = false;
+ bool cleanupProject = false;
+
+ for (int i=1; i<arguments.size(); ++i) {
+ if (arguments.at(i).toLower() == QLatin1String("-help")
+ || arguments.at(i).toLower() == QLatin1String("--help")
+ || arguments.at(i).toLower() == QLatin1String("/?")) {
+ usage();
+ return 0;
+ } else if (arguments.at(i).toLower() == QLatin1String("-o")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No output file specified!" << endl;
+ return -1;
+ }
+ resultFile = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-eventdelay")
+ || arguments.at(i).toLower() == QLatin1String("-keydelay")
+ || arguments.at(i).toLower() == QLatin1String("-mousedelay")
+ || arguments.at(i).toLower() == QLatin1String("-maxwarnings")) {
+ launchArguments.append(arguments.at(i++));
+ if (i == arguments.size()) {
+ cout << "Please specify value for:" << qPrintable(arguments.at(i-1).mid(1)) << endl;
+ return -1;
+ }
+ launchArguments.append(arguments.at(i));
+ } else if (arguments.at(i).toLower() == QLatin1String("-debug")) {
+ TestConfiguration::testDebug = true;
+ Option::before_user_vars.append("CONFIG-=release");
+ Option::before_user_vars.append("CONFIG+=debug");
+ } else if (arguments.at(i).toLower() == QLatin1String("-release")) {
+ TestConfiguration::testDebug = false;
+ Option::before_user_vars.append("CONFIG-=debug");
+ Option::before_user_vars.append("CONFIG+=release");
+ } else if (arguments.at(i).toLower() == QLatin1String("-libpath")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No library path specified!" << endl;
+ return -1;
+ }
+ TestConfiguration::remoteLibraryPath = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-qt-delete")) {
+ cleanupQt = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-project-delete")) {
+ cleanupProject = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-delete")) {
+ cleanupQt = true;
+ cleanupProject = true;
+ } else if (arguments.at(i).toLower() == QLatin1String("-conf")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No qt.conf file specified!" << endl;
+ return -1;
+ }
+ if (!QFileInfo(arguments.at(i)).exists())
+ cout << "Warning: could not find qt.conf file at:" << qPrintable(arguments.at(i)) << endl;
+ else
+ TestConfiguration::localQtConf = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-f")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No output file specified!" << endl;
+ return -1;
+ }
+ proFile = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-cache")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No cache file specified!" << endl;
+ return -1;
+ }
+ cacheFile = arguments.at(i);
+ } else if (arguments.at(i).toLower() == QLatin1String("-timeout")) {
+ if (++i == arguments.size()) {
+ cout << "Error: No timeout value specified!" << endl;
+ return -1;
+ }
+ timeout = QString(arguments.at(i)).toInt();
+ } else {
+ launchArguments.append(arguments.at(i));
+ }
+ }
+
+ // check for .pro file
+ if (proFile.isEmpty()) {
+ proFile = QDir::current().dirName() + QLatin1String(".pro");
+ if (!QFileInfo(proFile).exists()) {
+ cout << "Error: Could not find project file in current directory." << endl;
+ return -1;
+ }
+ debugOutput(QString::fromLatin1("Using Project File:").append(proFile),1);
+ }
+
+ // read target and deployment rules
+ int qmakeArgc = 1;
+ char* qmakeArgv[] = { "qmake.exe" };
+ Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
+ Option::output_dir = qmake_getpwd();
+ if (!cacheFile.isEmpty())
+ Option::mkfile::cachefile = cacheFile;
+ int ret = Option::init(qmakeArgc, qmakeArgv);
+ if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
+ cout << "Error: could not parse " << qPrintable(proFile) << endl;
+ return -1;
+ }
+
+ QMakeProperty prop;
+ QMakeProject project(&prop);
+
+ project.read(proFile);
+ if (project.values("TEMPLATE").join(" ").toLower() != QString("app")) {
+ cout << "Error: Can only test executables!" << endl;
+ return -1;
+ }
+ // Check wether the project is still in debug/release mode after reading
+ // If .pro specifies to be one mode only, we need to accept this
+ if (project.isActiveConfig("debug"))
+ TestConfiguration::testDebug = true;
+ else
+ TestConfiguration::testDebug = false;
+
+ QString destDir = project.values("DESTDIR").join(" ");
+ if (!destDir.isEmpty()) {
+ if (QDir::isRelativePath(destDir)) {
+ QFileInfo fi(proFile);
+ if (destDir == QLatin1String("."))
+ destDir = fi.absolutePath() + "/" + destDir + "/" + (TestConfiguration::testDebug ? "debug" : "release");
+ else
+ destDir = fi.absolutePath() + QDir::separator() + destDir;
+ }
+ } else {
+ QFileInfo fi(proFile);
+ destDir = fi.absolutePath();
+ destDir += QDir::separator() + QLatin1String(TestConfiguration::testDebug ? "debug" : "release");
+ }
+
+ DeploymentList qtDeploymentList;
+ DeploymentList projectDeploymentList;
+
+ TestConfiguration::localExecutable = Option::fixPathToLocalOS(destDir + QDir::separator() + project.values("TARGET").join(" ") + QLatin1String(".exe"));
+ TestConfiguration::remoteTestPath = QLatin1String("\\Program Files\\") + Option::fixPathToLocalOS(project.values("TARGET").join(QLatin1String(" ")));
+ if (!arguments.contains(QLatin1String("-libpath"), Qt::CaseInsensitive))
+ TestConfiguration::remoteLibraryPath = TestConfiguration::remoteTestPath;
+
+ QString targetExecutable = Option::fixPathToLocalOS(project.values("TARGET").join(QLatin1String(" ")));
+ int last = targetExecutable.lastIndexOf(QLatin1Char('\\'));
+ targetExecutable = targetExecutable.mid( last == -1 ? 0 : last+1 );
+ TestConfiguration::remoteExecutable = TestConfiguration::remoteTestPath + QDir::separator() + targetExecutable + QLatin1String(".exe");
+ projectDeploymentList.append(CopyItem(TestConfiguration::localExecutable , TestConfiguration::remoteExecutable));
+
+ // deploy
+ ActiveSyncConnection connection;
+ if (!connection.connect()) {
+ cout << "Error: Could not connect to device!" << endl;
+ return -1;
+ }
+ DeploymentHandler deployment;
+ deployment.setConnection(&connection);
+
+ deployment.initQtDeploy(&project, qtDeploymentList, TestConfiguration::remoteLibraryPath);
+ deployment.initProjectDeploy(&project , projectDeploymentList, TestConfiguration::remoteTestPath);
+
+ // add qt.conf
+ if (TestConfiguration::localQtConf != QLatin1String("no")) {
+ QString qtConfOrigin = QFileInfo(TestConfiguration::localQtConf).absoluteFilePath();
+ QString qtConfTarget = Option::fixPathToLocalOS(TestConfiguration::remoteTestPath + QDir::separator() + QLatin1String("qt.conf"));
+ projectDeploymentList.append(CopyItem(qtConfOrigin, qtConfTarget));
+ }
+
+ if (!deployment.deviceDeploy(qtDeploymentList) || !deployment.deviceDeploy(projectDeploymentList)) {
+ cout << "Error: Could not copy file(s) to device" << endl;
+ return -1;
+ }
+
+ // launch
+ launchArguments.append("-o");
+ launchArguments.append(TestConfiguration::remoteResultFile);
+
+ cout << endl << "Remote Launch:" << qPrintable(TestConfiguration::remoteExecutable) << " " << qPrintable(launchArguments.join(" ")) << endl;
+ if (!connection.execute(TestConfiguration::remoteExecutable, launchArguments.join(" "), timeout)) {
+ cout << "Error: Could not execute target file" << endl;
+ }
+
+
+ // copy result file
+ // show results
+ if (resultFile.isEmpty()) {
+ QString tempResultFile = Option::fixPathToLocalOS(QDir::tempPath() + "/qt_ce_temp_result_file.txt");
+ if (connection.copyFileFromDevice(TestConfiguration::remoteResultFile, tempResultFile)) {
+ QFile file(tempResultFile);
+ QByteArray arr;
+ if (file.open(QIODevice::ReadOnly)) {
+ arr = file.readAll();
+ cout << arr.constData() << endl;
+ }
+ file.close();
+ file.remove();
+ }
+ } else {
+ connection.copyFileFromDevice(TestConfiguration::remoteResultFile, resultFile);
+ }
+
+ // delete
+ connection.deleteFile(TestConfiguration::remoteResultFile);
+ if (cleanupQt)
+ deployment.cleanup(qtDeploymentList);
+ if (cleanupProject)
+ deployment.cleanup(projectDeploymentList);
+ return 0;
+}
diff --git a/tools/qtestlib/wince/cetest/qmake_include.pri b/tools/qtestlib/wince/cetest/qmake_include.pri
new file mode 100644
index 0000000000..383163419a
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/qmake_include.pri
@@ -0,0 +1,7 @@
+#qmake source files needed for cetest
+HEADERS += \
+ $$QT_SOURCE_TREE/qmake/option.h
+SOURCES += \
+ $$QT_SOURCE_TREE/qmake/option.cpp \
+ $$QT_SOURCE_TREE/qmake/project.cpp \
+ $$QT_SOURCE_TREE/qmake/property.cpp
diff --git a/tools/qtestlib/wince/cetest/remoteconnection.cpp b/tools/qtestlib/wince/cetest/remoteconnection.cpp
new file mode 100644
index 0000000000..7033ed61d1
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/remoteconnection.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "remoteconnection.h"
+
+AbstractRemoteConnection::AbstractRemoteConnection()
+{
+}
+
+AbstractRemoteConnection::~AbstractRemoteConnection()
+{
+}
+
+
+// Slow but should be ok...
+bool AbstractRemoteConnection::moveFile(const QString &src, const QString &dest, bool FailIfExists)
+{
+ bool result = copyFile(src, dest, FailIfExists);
+ deleteFile(src);
+ return result;
+}
+
+// Slow but should be ok...
+bool AbstractRemoteConnection::moveDirectory(const QString &src, const QString &dest, bool recursive)
+{
+ bool result = copyDirectory(src, dest, true);
+ deleteDirectory(src, recursive);
+ return result;
+}
+
diff --git a/tools/qtestlib/wince/cetest/remoteconnection.h b/tools/qtestlib/wince/cetest/remoteconnection.h
new file mode 100644
index 0000000000..8e8b3fd9c6
--- /dev/null
+++ b/tools/qtestlib/wince/cetest/remoteconnection.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef REMOTECONNECTION_H
+#define REMOTECONNECTION_H
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+#include <windows.h>
+class AbstractRemoteConnection
+{
+public:
+ AbstractRemoteConnection();
+ virtual ~AbstractRemoteConnection();
+
+ virtual bool connect(QVariantList&) = 0;
+ virtual void disconnect() = 0;
+ virtual bool isConnected() const = 0;
+
+ // These functions are designed for transfer between desktop and device
+ // Caution: deviceDest path has to be device specific (eg. no drive letters for CE)
+ virtual bool copyFileToDevice(const QString &localSource, const QString &deviceDest, bool failIfExists = false) = 0;
+ virtual bool copyDirectoryToDevice(const QString &localSource, const QString &deviceDest, bool recursive = true) = 0;
+ virtual bool copyFileFromDevice(const QString &deviceSource, const QString &localDest, bool failIfExists = false) = 0;
+ virtual bool copyDirectoryFromDevice(const QString &deviceSource, const QString &localDest, bool recursive = true) = 0;
+
+ // For "intelligent deployment" we need to investigate on filetimes on the device
+ virtual bool timeStampForLocalFileTime(FILETIME*) const = 0;
+ virtual bool fileCreationTime(const QString &fileName, FILETIME*) const = 0;
+
+ // These functions only work on files existing on the device
+ virtual bool copyFile(const QString&, const QString&, bool failIfExists = false) = 0;
+ virtual bool copyDirectory(const QString&, const QString&, bool recursive = true) = 0;
+ virtual bool deleteFile(const QString&) = 0;
+ virtual bool deleteDirectory(const QString&, bool recursive = true, bool failIfContentExists = false) = 0;
+ bool moveFile(const QString&, const QString&, bool FailIfExists = false);
+ bool moveDirectory(const QString&, const QString&, bool recursive = true);
+
+ virtual bool createDirectory(const QString&, bool deleteBefore=false) = 0;
+
+ virtual bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL) = 0;
+};
+
+#endif
diff --git a/tools/qtestlib/wince/remotelib/commands.cpp b/tools/qtestlib/wince/remotelib/commands.cpp
new file mode 100644
index 0000000000..f6113174db
--- /dev/null
+++ b/tools/qtestlib/wince/remotelib/commands.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "commands.h"
+
+#define CLEAN_FAIL(a) {delete appName; \
+ delete arguments; \
+ return (a); }
+
+int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream)
+{
+ if (!stream)
+ return -1;
+
+ DWORD bytesRead;
+ int appLength;
+ wchar_t* appName = 0;
+ int argumentsLength;
+ wchar_t* arguments = 0;
+ int timeout = -1;
+ int returnValue = -2;
+
+ if (S_OK != stream->Read(&appLength, sizeof(appLength), &bytesRead))
+ CLEAN_FAIL(-2);
+ appName = (wchar_t*) malloc(sizeof(wchar_t)*(appLength + 1));
+ if (S_OK != stream->Read(appName, sizeof(wchar_t)*appLength, &bytesRead))
+ CLEAN_FAIL(-2);
+ appName[appLength] = '\0';
+
+ if (S_OK != stream->Read(&argumentsLength, sizeof(argumentsLength), &bytesRead))
+ CLEAN_FAIL(-2);
+ arguments = (wchar_t*) malloc(sizeof(wchar_t)*(argumentsLength + 1));
+ if (S_OK != stream->Read(arguments, sizeof(wchar_t)*argumentsLength, &bytesRead))
+ CLEAN_FAIL(-2);
+ arguments[argumentsLength] = '\0';
+
+ if (S_OK != stream->Read(&timeout, sizeof(timeout), &bytesRead))
+ CLEAN_FAIL(-2);
+
+ bool result = qRemoteExecute(appName, arguments, &returnValue, timeout);
+
+ if (timeout != 0) {
+ if (S_OK != stream->Write(&returnValue, sizeof(returnValue), &bytesRead))
+ CLEAN_FAIL(-4);
+ }
+ delete appName;
+ delete arguments;
+ // We need to fail here for the execute, otherwise the calling application will wait
+ // forever for the returnValue.
+ if (!result)
+ return -3;
+ return S_OK;
+}
+
+
+bool qRemoteExecute(const wchar_t* program, const wchar_t* arguments, int *returnValue, int timeout)
+{
+ if (!program)
+ return false;
+
+ PROCESS_INFORMATION pid;
+ if (!CreateProcess(program, arguments, NULL, NULL, false, 0, NULL, NULL, NULL, &pid)) {
+ wprintf(L"Could not launch: %s\n", program);
+ return false;
+ }
+
+ // Timeout is in seconds
+ DWORD waitingTime = (timeout == -1) ? INFINITE : timeout * 1000;
+
+ if (waitingTime != 0) {
+ DWORD waitStatus = WaitForSingleObject(pid.hProcess, waitingTime);
+ if (waitStatus == WAIT_TIMEOUT) {
+ TerminateProcess(pid.hProcess, 2);
+ return false;
+ } else if (waitStatus == WAIT_OBJECT_0 && returnValue) {
+ *returnValue = 0;
+ DWORD exitCode;
+ if (GetExitCodeProcess(pid.hProcess, &exitCode))
+ *returnValue = exitCode;
+ }
+ }
+ return true;
+}
diff --git a/tools/qtestlib/wince/remotelib/commands.h b/tools/qtestlib/wince/remotelib/commands.h
new file mode 100644
index 0000000000..80a6f13a99
--- /dev/null
+++ b/tools/qtestlib/wince/remotelib/commands.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QREMOTECOMMANDS_H
+#define QREMOTECOMMANDS_H
+#include <winbase.h>
+#include <rapi.h>
+
+extern "C" {
+ int __declspec(dllexport) qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream*);
+ bool __declspec(dllexport) qRemoteExecute(const wchar_t* program, const wchar_t* arguments = NULL, int *returnValue = NULL , int timeout = -1);
+}
+
+#endif
diff --git a/tools/qtestlib/wince/remotelib/remotelib.pro b/tools/qtestlib/wince/remotelib/remotelib.pro
new file mode 100644
index 0000000000..dc61c7ffd9
--- /dev/null
+++ b/tools/qtestlib/wince/remotelib/remotelib.pro
@@ -0,0 +1,15 @@
+TEMPLATE = lib
+CONFIG += dll
+CONFIG -= staticlib
+TARGET = QtRemote
+DESTDIR = ../../../../lib
+DEPENDPATH += .
+INCLUDEPATH += .
+QT =
+# Input
+HEADERS += commands.h
+SOURCES += commands.cpp
+
+INCLUDEPATH += $$QT_CE_RAPI_INC
+LIBS += -L$$QT_CE_RAPI_LIB
+
diff --git a/tools/qtestlib/wince/wince.pro b/tools/qtestlib/wince/wince.pro
new file mode 100644
index 0000000000..7c88d6572c
--- /dev/null
+++ b/tools/qtestlib/wince/wince.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+wince*:SUBDIRS = remotelib \ No newline at end of file
diff --git a/tools/qvfb/ClamshellPhone.qrc b/tools/qvfb/ClamshellPhone.qrc
new file mode 100644
index 0000000000..39cd422746
--- /dev/null
+++ b/tools/qvfb/ClamshellPhone.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>ClamshellPhone.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin
new file mode 100644
index 0000000000..cb24a8e14c
--- /dev/null
+++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone.skin
@@ -0,0 +1,30 @@
+[SkinFile]
+Up=ClamshellPhone1-5.png
+Down=ClamshellPhone1-5-pressed.png
+Closed=ClamshellPhone1-5-closed.png
+Screen=72 84 176 208
+Areas=22
+HasMouseHover=false
+
+"Power" 0x0100000a 205 563 249 586
+"1" 0x0031 62 414 119 438
+"2" 0x0032 130 414 189 438
+"3" 0x0033 198 413 257 438
+"4" 0x0034 54 444 117 470
+"5" 0x0035 128 444 189 471
+"6" 0x0036 202 444 264 471
+"7" 0x0037 47 477 113 507
+"8" 0x0038 126 477 190 507
+"9" 0x0039 205 478 270 509
+"*" 0x002a 39 515 110 552
+"0" 0x0030 122 515 195 553
+"#" 0x0023 207 516 280 553
+"Context1" 0x01100000 137 360 108 383 123 410 90 409 60 387 63 378 100 362
+"Back" 0x01000061 184 361 206 376 213 387 197 410 226 410 256 392 258 381 244 369
+"Backspace" 0x01000003 68 563 113 587
+"Select" 0x01010000 160 391 172 390 181 386 184 381 180 377 173 373 165 372 155 372 145 375 138 378 136 382 138 387 147 390
+"Left" 0x1000012 141 390 136 385 136 381 143 375 132 371 120 380 121 393 129 401
+"Down" 0x1000015 143 389 130 402 162 412 191 404 175 390
+"Right" 0x1000014 186 370 176 375 184 382 182 387 175 390 190 404 201 396 202 375
+"Up" 0x1000013 133 370 143 374 176 374 185 370 169 362 149 362
+"Flip" 0x01100006 98 325 225 353
diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png
new file mode 100644
index 0000000000..88ba3a1472
--- /dev/null
+++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-closed.png
Binary files differ
diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png
new file mode 100644
index 0000000000..971cdef649
--- /dev/null
+++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5-pressed.png
Binary files differ
diff --git a/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png
new file mode 100644
index 0000000000..f3550ee7d7
--- /dev/null
+++ b/tools/qvfb/ClamshellPhone.skin/ClamshellPhone1-5.png
Binary files differ
diff --git a/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf b/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..e349dbc1f2
--- /dev/null
+++ b/tools/qvfb/ClamshellPhone.skin/defaultbuttons.conf
@@ -0,0 +1,78 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Flip
+Key4=Backspace
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#=#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png b/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png
new file mode 100644
index 0000000000..d62ef4a8d3
--- /dev/null
+++ b/tools/qvfb/DualScreenPhone.skin/DualScreen-pressed.png
Binary files differ
diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreen.png b/tools/qvfb/DualScreenPhone.skin/DualScreen.png
new file mode 100644
index 0000000000..cb3d1a72a4
--- /dev/null
+++ b/tools/qvfb/DualScreenPhone.skin/DualScreen.png
Binary files differ
diff --git a/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin b/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin
new file mode 100644
index 0000000000..a82ef23880
--- /dev/null
+++ b/tools/qvfb/DualScreenPhone.skin/DualScreenPhone.skin
@@ -0,0 +1,29 @@
+[SkinFile]
+Up=DualScreen.png
+Down=DualScreen-pressed.png
+Screen=128 155 176 208
+BackScreen=18 44 98 119
+Areas=21
+HasMouseHover=false
+
+"Context1" 0x1100000 144 368 189 368 168 396 176 427 150 398
+"Back" 0x1000061 245 365 291 366 283 398 258 424 265 394
+"Select" 0x1010000 202 401 210 389 224 388 233 402 224 415 208 415
+"Up" 0x1000013 202 381 196 374 218 363 239 373 229 382
+"Left" 0x1000012 199 385 189 375 176 403 185 426 197 415 194 401
+"Right" 0x1000014 235 390 248 379 253 402 246 421 238 413
+"Down" 0x1000015 204 421 233 422 241 432 214 443 191 430
+"Call" 0x1100004 163 452 137 450 125 465 136 484 159 485 169 467
+"Hangup" 0x1100005 266 475 279 448 295 447 309 460 301 480 289 487
+"1" 0x31 175 514 147 504 133 518 161 532 180 534
+"2" 0x32 199 515 229 519 238 533 222 540 195 538
+"2" 0x32 260 512 286 506 299 513 284 527 264 535 248 525
+"4" 0x34 164 541 177 546 182 560 164 565 146 560 135 545 154 539
+"5" 0x35 204 546 225 546 243 560 231 574 205 573 191 558
+"6" 0x36 257 547 281 537 294 540 287 555 274 566 254 561
+"7" 0x37 145 569 176 578 177 595 156 597 138 584
+"8" 0x38 197 582 229 584 241 593 226 604 201 603 189 594
+"9" 0x39 253 577 288 564 301 578 283 593 259 597 251 586
+"*" 0x2a 145 598 181 611 182 623 163 632 144 623 138 607
+"0" 0x30 196 611 233 613 240 630 220 642 193 637 191 622
+"#" 0x23 255 610 286 600 302 615 279 625 258 629 247 616
diff --git a/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf b/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..1103350557
--- /dev/null
+++ b/tools/qvfb/DualScreenPhone.skin/defaultbuttons.conf
@@ -0,0 +1,78 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Call
+Key4=Hangup
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#='#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/tools/qvfb/LICENSE.GPL b/tools/qvfb/LICENSE.GPL
new file mode 100644
index 0000000000..b6e1c33e04
--- /dev/null
+++ b/tools/qvfb/LICENSE.GPL
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/tools/qvfb/PDAPhone.qrc b/tools/qvfb/PDAPhone.qrc
new file mode 100644
index 0000000000..1a1c35a582
--- /dev/null
+++ b/tools/qvfb/PDAPhone.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>PDAPhone.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/PDAPhone.skin/PDAPhone.skin b/tools/qvfb/PDAPhone.skin/PDAPhone.skin
new file mode 100644
index 0000000000..d6a1966594
--- /dev/null
+++ b/tools/qvfb/PDAPhone.skin/PDAPhone.skin
@@ -0,0 +1,18 @@
+[SkinFile]
+Up=pda_up.png
+Down=pda_down.png
+Screen=42 59 176 220
+Cursor=finger.png 20 20
+Areas=10
+HasMouseHover=false
+
+"Power" 0x0100000a 117 21 141 42
+"Context1" 0x01100000 43 284 74 315
+"Call" 0x01100004 74 284 104 315
+"Hangup" 0x01100005 154 284 184 315
+"Back" 0x01000061 184 284 214 315
+"Left" 0x1000012 123 315 110 326 106 307 113 288 123 300 120 307
+"Down" 0x1000015 123 315 130 318 138 315 150 326 129 335 111 325
+"Right" 0x1000014 137 301 149 290 155 308 150 324 138 315 140 308
+"Up" 0x1000013 123 300 112 289 130 282 149 290 137 300 130 298
+"Select" 0x01010000 131 298 137 300 140 307 138 315 130 318 123 316 120 307 123 300
diff --git a/tools/qvfb/PDAPhone.skin/defaultbuttons.conf b/tools/qvfb/PDAPhone.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..e3ae813df2
--- /dev/null
+++ b/tools/qvfb/PDAPhone.skin/defaultbuttons.conf
@@ -0,0 +1,36 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Back
+Key2=Select
+Key3=Call
+Key4=Hangup
+[Device]
+PrimaryInput=Touchscreen
diff --git a/tools/qvfb/PDAPhone.skin/finger.png b/tools/qvfb/PDAPhone.skin/finger.png
new file mode 100644
index 0000000000..24cf0cb2eb
--- /dev/null
+++ b/tools/qvfb/PDAPhone.skin/finger.png
Binary files differ
diff --git a/tools/qvfb/PDAPhone.skin/pda_down.png b/tools/qvfb/PDAPhone.skin/pda_down.png
new file mode 100644
index 0000000000..f65c059302
--- /dev/null
+++ b/tools/qvfb/PDAPhone.skin/pda_down.png
Binary files differ
diff --git a/tools/qvfb/PDAPhone.skin/pda_up.png b/tools/qvfb/PDAPhone.skin/pda_up.png
new file mode 100644
index 0000000000..541e3c404f
--- /dev/null
+++ b/tools/qvfb/PDAPhone.skin/pda_up.png
Binary files differ
diff --git a/tools/qvfb/PortableMedia.qrc b/tools/qvfb/PortableMedia.qrc
new file mode 100644
index 0000000000..a902f1a737
--- /dev/null
+++ b/tools/qvfb/PortableMedia.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>PortableMedia.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/PortableMedia.skin/PortableMedia.skin b/tools/qvfb/PortableMedia.skin/PortableMedia.skin
new file mode 100644
index 0000000000..b76e5cfadd
--- /dev/null
+++ b/tools/qvfb/PortableMedia.skin/PortableMedia.skin
@@ -0,0 +1,14 @@
+[SkinFile]
+Up=portablemedia.png
+Down=portablemedia-pressed.png
+Screen=18 20 480 272
+Areas=7
+HasMouseHover=false
+
+"Context1" 0x01100000 530 192 565 223
+"Back" 0x01000061 530 138 565 173
+"Select" 0x01010000 530 65 565 98
+"Left" 0x1000012 529 67 519 57 511 65 511 104 519 110 529 100 529 98
+"Down" 0x1000015 530 102 520 111 529 120 569 120 577 114 566 103 564 103
+"Right" 0x1000014 565 65 576 52 585 67 585 102 578 113 567 104
+"Up" 0x1000013 530 65 519 55 528 48 567 48 573 51 564 66
diff --git a/tools/qvfb/PortableMedia.skin/defaultbuttons.conf b/tools/qvfb/PortableMedia.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..514e8816ea
--- /dev/null
+++ b/tools/qvfb/PortableMedia.skin/defaultbuttons.conf
@@ -0,0 +1,23 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Map=123
+Default=1
+1=Applications/mediaplayer.desktop
+2=Applications/photoedit.desktop
+3=Settings
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+[Device]
+PrimaryInput=Keypad
diff --git a/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png b/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png
new file mode 100644
index 0000000000..730e76287a
--- /dev/null
+++ b/tools/qvfb/PortableMedia.skin/portablemedia-pressed.png
Binary files differ
diff --git a/tools/qvfb/PortableMedia.skin/portablemedia.png b/tools/qvfb/PortableMedia.skin/portablemedia.png
new file mode 100644
index 0000000000..e44cbe1605
--- /dev/null
+++ b/tools/qvfb/PortableMedia.skin/portablemedia.png
Binary files differ
diff --git a/tools/qvfb/PortableMedia.skin/portablemedia.xcf b/tools/qvfb/PortableMedia.skin/portablemedia.xcf
new file mode 100644
index 0000000000..127e07c8ea
--- /dev/null
+++ b/tools/qvfb/PortableMedia.skin/portablemedia.xcf
Binary files differ
diff --git a/tools/qvfb/README b/tools/qvfb/README
new file mode 100644
index 0000000000..bfab467e0d
--- /dev/null
+++ b/tools/qvfb/README
@@ -0,0 +1,51 @@
+Qt for Embedded Linux Virtual Framebuffer
+===============================
+
+The virtual frame buffer allows a Qt for Embedded Linux program to be developed
+on your desktop machine, without switching between consoles and X11. The virtual
+framebuffer consists of a shared memory region (the virtual frame buffer)
+and a utility to display the framebuffer in a window. The display is updated
+periodically, so you will see discrete snapshots of the framebuffer rather
+than each individual drawing operation. For this reason drawing problems
+such as flickering may not be apparent until the program is run using a real
+framebuffer.
+
+To use the virtual framebuffer:
+
+1. Ensure QT_NO_QWS_VFB is not set in qconfig.h (when you configure Qt,
+ add the -qvfb option).
+2. Start qvfb (qvfb should be compiled as a normal Qt for X11 application,
+ NOT as a Qt for Embedded Linux application!).
+3. Start a Qt for Embedded Linux server (i.e. construct QApplication with
+ QApplication::GuiServer flag, or run a client with the -qws option).
+
+qvfb supports the following command line options:
+
+[-width width] the width of the virtual framebuffer (default: 240).
+[-height height] the height of the virtual framebuffer (default: 320).
+[-depth depth] the depth of the virtual framebuffer (1,4,8 or 32, default: 8).
+[-nocursor] do not display the X11 cursor in the framebuffer window.
+[-qwsdisplay] the Qt for Embedded Linux display ID, e.g. -qwsdisplay :1 (default :0).
+[-skin skinfile] tells qvfb to load a skin file, e.g. -skin pda.skin
+
+Please refer to the file "pda.skin" as an example of what a skin file looks like.
+The format for skin files is:
+ Image filename of skin with buttons in their up positions
+ Image filename of skin with buttons in their down positions
+ X offset of top left corner of the virtual screen on the skin image
+ Y offset of top left corner of the virtual screen on the skin image
+ Width of the virtual screen on the skin image
+ Height of the virtual screen on the skin image
+ Number of defined button regions
+Then for each button region the format is:
+ Button identifier
+ Qt scan codes to generate for the button
+ Top left X coordinate of the button region
+ Top left Y coordinate of the button region
+ Bottom right X coordinate of the button region
+ Bottom right Y coordinate of the button region
+
+The virtual framebuffer is a development tool only. No security issues have
+been considered in the virtual framebuffer design. It should not be used
+in a production environment and QT_NO_QWS_VFB should always be in force
+in production libraries.
diff --git a/tools/qvfb/SmartPhone.qrc b/tools/qvfb/SmartPhone.qrc
new file mode 100644
index 0000000000..8bb53259a8
--- /dev/null
+++ b/tools/qvfb/SmartPhone.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>SmartPhone.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png b/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png
new file mode 100644
index 0000000000..d0db2ed352
--- /dev/null
+++ b/tools/qvfb/SmartPhone.skin/SmartPhone-pressed.png
Binary files differ
diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone.png b/tools/qvfb/SmartPhone.skin/SmartPhone.png
new file mode 100644
index 0000000000..e6ac5a0f38
--- /dev/null
+++ b/tools/qvfb/SmartPhone.skin/SmartPhone.png
Binary files differ
diff --git a/tools/qvfb/SmartPhone.skin/SmartPhone.skin b/tools/qvfb/SmartPhone.skin/SmartPhone.skin
new file mode 100644
index 0000000000..2f44c5aa88
--- /dev/null
+++ b/tools/qvfb/SmartPhone.skin/SmartPhone.skin
@@ -0,0 +1,28 @@
+[SkinFile]
+Up=SmartPhone.png
+Down=SmartPhone-pressed.png
+Screen=90 107 176 208
+Areas=21
+HasMouseHover=false
+
+"1" 0x0031 138 459 149 473 142 483 120 484 102 477 95 464 99 457 121 454
+"2" 0x0032 153 467 202 492
+"3" 0x0033 258 457 260 470 243 483 215 484 207 474 218 460 248 453
+"4" 0x0034 138 492 149 506 142 516 120 517 102 510 95 497 99 490 121 487
+"5" 0x0035 153 499 202 524
+"6" 0x0036 258 489 260 502 243 515 215 516 207 506 218 492 248 485
+"7" 0x0037 138 524 149 538 142 548 120 549 102 542 95 529 99 522 121 519
+"8" 0x0038 153 531 202 556
+"9" 0x0039 258 521 260 534 243 547 215 548 207 538 218 524 248 517
+"*" 0x002a 138 556 149 570 142 580 120 581 102 574 95 561 99 554 121 551
+"0" 0x0030 153 564 202 589
+"#" 0x0023 258 554 260 567 243 580 215 581 207 571 218 557 248 550
+"Call" 0x01100004 88 395 130 439
+"Hangup" 0x01100005 227 395 269 439
+"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318
+"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318
+"Select" 0x01010000 160 338 195 371
+"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369
+"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374
+"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375
+"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337
diff --git a/tools/qvfb/SmartPhone.skin/defaultbuttons.conf b/tools/qvfb/SmartPhone.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..1103350557
--- /dev/null
+++ b/tools/qvfb/SmartPhone.skin/defaultbuttons.conf
@@ -0,0 +1,78 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Call
+Key4=Hangup
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#='#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/tools/qvfb/SmartPhone2.qrc b/tools/qvfb/SmartPhone2.qrc
new file mode 100644
index 0000000000..751e9852b5
--- /dev/null
+++ b/tools/qvfb/SmartPhone2.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>SmartPhone2.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png b/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png
new file mode 100644
index 0000000000..d4eb5b0c86
--- /dev/null
+++ b/tools/qvfb/SmartPhone2.skin/SmartPhone2-pressed.png
Binary files differ
diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2.png b/tools/qvfb/SmartPhone2.skin/SmartPhone2.png
new file mode 100644
index 0000000000..48ccc1c5a6
--- /dev/null
+++ b/tools/qvfb/SmartPhone2.skin/SmartPhone2.png
Binary files differ
diff --git a/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin b/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin
new file mode 100644
index 0000000000..16884bfb58
--- /dev/null
+++ b/tools/qvfb/SmartPhone2.skin/SmartPhone2.skin
@@ -0,0 +1,25 @@
+SmartPhone2.png SmartPhone2-pressed.png
+90 107
+176 220
+21
+"Menu" 0x01100000 70 400 115 427
+"Backspace" 0x01000003 238 400 285 427
+"1" 0x0031 138 437 149 451 142 461 120 462 102 455 95 442 99 435 121 432
+"2" 0x0032 153 445 202 470
+"3" 0x0033 258 435 260 448 243 461 215 462 207 452 218 438 248 431
+"4" 0x0034 138 470 149 484 142 494 120 495 102 488 95 475 99 468 121 465
+"5" 0x0035 153 477 202 502
+"6" 0x0036 258 467 260 480 243 493 215 494 207 484 218 470 248 463
+"7" 0x0037 138 502 149 516 142 526 120 527 102 520 95 507 99 500 121 497
+"8" 0x0038 153 509 202 534
+"9" 0x0039 258 499 260 512 243 525 215 526 207 516 218 502 248 495
+"*" 0x002a 138 534 149 548 142 558 120 559 102 552 95 539 99 532 121 529
+"0" 0x0030 153 542 202 567
+"#" 0x0023 258 532 260 545 243 558 215 559 207 549 218 535 248 528
+"Yes" 0x01010001 91 343 141 393
+"No" 0x01010002 219 343 269 393
+"Select" 0x01010000 160 356 195 389
+"Left" 0x1000012 159 356 149 346 141 354 141 391 149 399 159 389 159 387
+"Down" 0x1000015 160 391 150 400 159 409 199 409 207 403 196 392 194 392
+"Right" 0x1000014 195 354 206 341 215 356 215 391 208 402 197 393
+"Up" 0x1000013 160 354 149 344 158 337 197 337 203 340 194 355
diff --git a/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf b/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..b08320347e
--- /dev/null
+++ b/tools/qvfb/SmartPhone2.skin/defaultbuttons.conf
@@ -0,0 +1,52 @@
+[Button]
+[IMethod]
+key_count = 5
+key_hold_action_1 = insertText
+key_hold_action_2 = insertText
+key_hold_action_3 = insertSymbol
+key_hold_action_4 = changeMode
+key_hold_arg_1 = 1
+key_hold_arg_2 = 0
+key_id_1 = 1
+key_id_2 = 0
+key_id_3 = *
+key_id_4 = #
+key_id_5 = *
+key_mode_1 = Abc
+key_mode_2 = Abc
+key_mode_3 = Abc
+key_mode_4 = Abc
+key_mode_5 = Phone
+key_tap_action_1 = insertText
+key_tap_action_2 = insertSpace
+key_tap_action_3 = modifyText
+key_tap_action_4 = changeShift
+key_tap_action_5 = insertText
+key_tap_arg_1 = .,'?!-@:〓
+key_tap_arg_5 = *+pw
+[Menu]
+1 = Applications/camera.desktop
+2 = Applications/datebook.desktop
+3 = Games
+4 = Applications/qtmail.desktop
+5 = Applications/addressbook.desktop
+6 = Settings
+7 = Settings/Beaming.desktop
+8 = Applications
+9 = Documents
+Columns = 3
+Default = 5
+Map = 123456789
+Rows = 3
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+[SystemButtons]
+Count=5
+Key0=Yes
+Key1=Select
+Key2=No
+Key3=Menu
+Key4=Backspace
+[Device]
+PrimaryInput=Keypad
diff --git a/tools/qvfb/SmartPhoneWithButtons.qrc b/tools/qvfb/SmartPhoneWithButtons.qrc
new file mode 100644
index 0000000000..f3393ba9d2
--- /dev/null
+++ b/tools/qvfb/SmartPhoneWithButtons.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>SmartPhoneWithButtons.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png
new file mode 100644
index 0000000000..456a068eee
--- /dev/null
+++ b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons-pressed.png
Binary files differ
diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png
new file mode 100644
index 0000000000..5ffbd6e4e7
--- /dev/null
+++ b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.png
Binary files differ
diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin
new file mode 100644
index 0000000000..9afa67f30d
--- /dev/null
+++ b/tools/qvfb/SmartPhoneWithButtons.skin/SmartPhoneWithButtons.skin
@@ -0,0 +1,31 @@
+[SkinFile]
+Up=SmartPhoneWithButtons.png
+Down=SmartPhoneWithButtons-pressed.png
+Screen=90 107 176 208
+Areas=24
+HasMouseHover=false
+
+"1" 0x0031 138 459 149 473 142 483 120 484 102 477 95 464 99 457 121 454
+"2" 0x0032 153 467 202 492
+"3" 0x0033 258 457 260 470 243 483 215 484 207 474 218 460 248 453
+"4" 0x0034 138 492 149 506 142 516 120 517 102 510 95 497 99 490 121 487
+"5" 0x0035 153 499 202 524
+"6" 0x0036 258 489 260 502 243 515 215 516 207 506 218 492 248 485
+"7" 0x0037 138 524 149 538 142 548 120 549 102 542 95 529 99 522 121 519
+"8" 0x0038 153 531 202 556
+"9" 0x0039 258 521 260 534 243 547 215 548 207 538 218 524 248 517
+"*" 0x002a 138 556 149 570 142 580 120 581 102 574 95 561 99 554 121 551
+"0" 0x0030 153 564 202 589
+"#" 0x0023 258 554 260 567 243 580 215 581 207 571 218 557 248 550
+"Call" 0x01100004 88 395 130 439
+"Hangup" 0x01100005 227 395 269 439
+"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318
+"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318
+"Select" 0x01010000 160 338 195 371
+"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369
+"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374
+"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375
+"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337
+"Home" 0x1000010 164 402 195 434
+"F1" 0x1000030 138 422 163 448
+"F2" 0x1000031 196 422 220 448
diff --git a/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf b/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..ebd6926ae3
--- /dev/null
+++ b/tools/qvfb/SmartPhoneWithButtons.skin/defaultbuttons.conf
@@ -0,0 +1,103 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Button]
+Count=3
+[Button0]
+Name[]=Calendar Button
+Key=F1
+PressedActionService=Calendar
+PressedActionMessage=raiseToday()
+HeldActionService=Calendar
+HeldActionMessage=newEvent()
+[Button1]
+Name[]=Tasks Button
+Key=F2
+PressedActionService=Tasks
+PressedActionMessage=raise()
+HeldActionService=Tasks
+HeldActionMessage=newTask()
+[Button2]
+Name[]=Home Button
+Key=Home
+PressedActionMappable=0
+PressedActionService=TaskManager
+PressedActionMessage=multitask()
+HeldActionMappable=0
+HeldActionService=TaskManager
+HeldActionMessage=showRunningTasks()
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Call
+Key4=Hangup
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#='#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
diff --git a/tools/qvfb/TouchscreenPhone.qrc b/tools/qvfb/TouchscreenPhone.qrc
new file mode 100644
index 0000000000..023144d2f9
--- /dev/null
+++ b/tools/qvfb/TouchscreenPhone.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>TouchscreenPhone.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png
new file mode 100644
index 0000000000..01acb86547
--- /dev/null
+++ b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone-pressed.png
Binary files differ
diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png
new file mode 100644
index 0000000000..e90de0de46
--- /dev/null
+++ b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.png
Binary files differ
diff --git a/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin
new file mode 100644
index 0000000000..24316a1b4a
--- /dev/null
+++ b/tools/qvfb/TouchscreenPhone.skin/TouchscreenPhone.skin
@@ -0,0 +1,16 @@
+[SkinFile]
+Up=TouchscreenPhone.png
+Down=TouchscreenPhone-pressed.png
+Screen=90 107 176 208
+Areas=9
+HasMouseHover=false
+
+"Context1" 0x01100000 145 321 134 333 132 361 134 374 110 343 109 318
+"Call" 0x01100004 88 395 130 439
+"Hangup" 0x01100005 227 395 269 439
+"Back" 0x01000061 249 322 240 354 219 373 223 344 216 325 208 318
+"Left" 0x1000012 159 338 149 328 141 336 141 373 149 381 159 371 159 369
+"Down" 0x1000015 160 373 150 382 159 391 199 391 207 385 196 374 194 374
+"Right" 0x1000014 195 336 206 323 215 338 215 373 208 384 197 375
+"Up" 0x1000013 160 336 149 326 158 319 197 319 203 322 194 337
+"Select" 0x01010000 160 338 195 371
diff --git a/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf b/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..a13dfdc3b2
--- /dev/null
+++ b/tools/qvfb/TouchscreenPhone.skin/defaultbuttons.conf
@@ -0,0 +1,45 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/datebook.desktop
+3=Applications
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Games
+7=Settings/Beaming.desktop
+8=Applications/simapp.desktop,Applications/calculator.desktop
+9=Settings
+*=Applications/mediarecorder.desktop
+0=Applications/todolist.desktop
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Back
+Key2=Select
+Key3=Call
+Key4=Hangup
+[Button]
+Count=1
+[Button0]
+Name=Power Button
+Key=Hangup
+HeldActionService=Launcher
+HeldActionMessage=execute(QString)
+HeldActionArgs=@ByteArray(\0\0\0\x1\0\0\0\n\0\0\0\0\x10\0s\0h\0u\0t\0\x64\0o\0w\0n)
+[Device]
+PrimaryInput=Touchscreen
+
diff --git a/tools/qvfb/Trolltech-Keypad.qrc b/tools/qvfb/Trolltech-Keypad.qrc
new file mode 100644
index 0000000000..4775068cff
--- /dev/null
+++ b/tools/qvfb/Trolltech-Keypad.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>Trolltech-Keypad.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png
new file mode 100644
index 0000000000..8dd5719341
--- /dev/null
+++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-closed.png
Binary files differ
diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png
new file mode 100644
index 0000000000..5e1e6beff8
--- /dev/null
+++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad-down.png
Binary files differ
diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png
new file mode 100644
index 0000000000..fb3d549759
--- /dev/null
+++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.png
Binary files differ
diff --git a/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin
new file mode 100644
index 0000000000..4d90321f98
--- /dev/null
+++ b/tools/qvfb/Trolltech-Keypad.skin/Trolltech-Keypad.skin
@@ -0,0 +1,35 @@
+[SkinFile]
+Up=Trolltech-Keypad.png
+Down=Trolltech-Keypad-down.png
+Closed=Trolltech-Keypad-closed.png
+ClosedAreas=F1 F2 F3 Flip
+ClosedScreen=95 456 128 96
+Screen=75 85 176 220
+Areas=25
+HasMouseHover=false
+"1" 0x0031 65 542 68 536 76 532 114 536 114 573 64 568
+"2" 0x0032 133 537 188 574
+"3" 0x0033 206 536 246 532 252 536 256 542 258 569 205 572
+"4" 0x0034 64 578 114 618
+"5" 0x0035 133 581 188 618
+"6" 0x0036 206 580 256 577 258 613 206 616
+"7" 0x0037 66 622 116 625 114 662 66 658
+"8" 0x0038 133 626 188 662
+"9" 0x0039 206 625 256 622 256 658 206 661
+"*" 0x002a 68 667 116 670 114 705 86 699 76 693 69 686
+"0" 0x0030 133 671 188 708
+"#" 0x0023 206 670 254 665 254 684 245 692 232 699 206 704
+"Context1" 0x01100000 69 420 75 410 85 404 101 404 102 458 69 458
+"Back" 0x01000061 218 404 234 404 240 408 248 418 248 456 218 457
+"Home" 0x1000010 140 494 180 514
+"Hangup" 0x01100005 218 457 248 456 248 496 243 507 230 514 194 514 194 494 206 492 213 486 218 478
+"Call" 0x01100004 68 458 102 460 102 479 108 487 118 492 126 494 126 514 86 514 77 507 72 496
+"Select" 0x01010000 138 426 182 458
+"Up" 0x1000013 118 406 201 402 184 423 134 422
+"Right" 0x1000014 184 424 201 402 202 476 184 460
+"Down" 0x1000015 135 462 184 461 199 477 118 477
+"Left" 0x1000012 118 406 134 424 134 461 117 476
+"F1" 0x1000030 0 408 45 456
+"F2" 0x1000031 0 456 45 509
+"F3" 0x1000032 0 545 45 582
+"Flip" 0x1100006 32 353 293 386
diff --git a/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf b/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..6a78e67c3e
--- /dev/null
+++ b/tools/qvfb/Trolltech-Keypad.skin/defaultbuttons.conf
@@ -0,0 +1,142 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Button]
+Count=8
+[Button7]
+Name[]=Home Down Button
+Key=Down
+Context=HomeScreen
+PressedActionMappable=0
+HeldActionService=Messaging
+HeldActionMessage=raise()
+[Button6]
+Name[]=Home Up Button
+Key=Up
+Context=HomeScreen
+PressedActionMappable=0
+HeldActionService=Contacts
+HeldActionMessage=raise()
+[Button5]
+Name[]=Home Right Button
+Key=Right
+Context=HomeScreen
+PressedActionMappable=0
+HeldActionService=mediaplayer
+HeldActionMessage=raise()
+[Button4]
+Name[]=Calender Button
+Key=Left
+Context=HomeScreen
+PressedActionMappable=0
+HeldActionService=Calendar
+HeldActionMessage=raiseToday()
+[Button3]
+Name[]=Left Soft Key
+Key=Context1
+HeldActionService=TaskManager
+HeldActionMessage=showRunningTasks()
+HeldActionMappable=0
+PressActionMappable=0
+[Button2]
+Name[]=VoiceNotes Button
+Key=F1
+PressedActionService=mediarecorder
+PressedActionMessage=raise()
+HeldActionService=mediarecorder
+HeldActionMessage=newEvent()
+[Button1]
+Name[]=Camera Button
+Key=F2
+PressedActionService=Camera
+PressedActionMessage=raise()
+HeldActionService=Tasks
+HeldActionMessage=newTask()
+[Button0]
+Name[]=Home Button
+Key=Home
+PressedActionMappable=0
+PressedActionService=TaskManager
+PressedActionMessage=multitask()
+HeldActionMappable=0
+HeldActionService=TaskManager
+HeldActionMessage=showRunningTasks()
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/mediaplayer.desktop
+3=Applications/simapp.desktop,Applications/calculator.desktop
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Applications/datebook.desktop
+7=Games
+8=Settings/Beaming.desktop
+9=Applications/todolist.desktop
+*=Settings
+0=Applications
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=6
+Key0=Context1
+Key1=Select
+Key2=Back
+Key3=Call
+Key4=Hangup
+Key5=Flip
+[TextButtons]
+Buttons=0123456789*#
+Hold0='0
+Hold1='1
+Hold2='2
+Hold3='3
+Hold4='4
+Hold5='5
+Hold6='6
+Hold7='7
+Hold8='8
+Hold9='9
+Hold*=symbol
+Hold#=mode
+Tap0=space
+Tap0=space
+Tap1="\".,'?!-@:1"
+Tap2="\"a\xe4\xe5\xe6\xe0\xe1\xe2\x62\x63\xe7\x32"
+Tap3="\"de\xe8\xe9\xea\x66\x33"
+Tap4="\"ghi\xec\xed\xee\x34"
+Tap5="\"jkl5"
+Tap6="\"mn\xf1o\xf6\xf8\xf2\xf3\x36"
+Tap7="\"pqrs\xdf\x37"
+Tap8="\"tu\xfc\xf9\xfav8"
+Tap9="\"wxyz9"
+Tap*=modify
+Tap#=shift
+[LocaleTextButtons]
+Buttons=23456789
+Tap2[]='abc
+Tap3[]='def
+Tap4[]='ghi
+Tap5[]='jkl
+Tap6[]='mno
+Tap7[]='pqrs
+Tap8[]='tuv
+Tap9[]='wxyz
+[PhoneTextButtons]
+Buttons=*#
+Tap*='*+pw
+Hold*=+
+Tap#='#
+Hold#=mode
+[Device]
+PrimaryInput=Keypad
+[Environment]
+QWS_DISPLAY=Multi: LinuxFb:mmHeight57:0 LinuxFb:offset=0,320:1 :0
diff --git a/tools/qvfb/Trolltech-Touchscreen.qrc b/tools/qvfb/Trolltech-Touchscreen.qrc
new file mode 100644
index 0000000000..40fafeb7ed
--- /dev/null
+++ b/tools/qvfb/Trolltech-Touchscreen.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>Trolltech-Touchscreen.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png
new file mode 100644
index 0000000000..c1a422f4eb
--- /dev/null
+++ b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen-down.png
Binary files differ
diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png
new file mode 100644
index 0000000000..544a425162
--- /dev/null
+++ b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.png
Binary files differ
diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin
new file mode 100644
index 0000000000..5de882eed6
--- /dev/null
+++ b/tools/qvfb/Trolltech-Touchscreen.skin/Trolltech-Touchscreen.skin
@@ -0,0 +1,17 @@
+[SkinFile]
+Up=Trolltech-Touchscreen.png
+Down=Trolltech-Touchscreen-down.png
+Screen=40 109 176 220
+Areas=10
+HasMouseHover=false
+
+"Context1" 0x01100000 38 420 44 408 52 404 68 403 68 458 40 458
+"Back" 0x01000061 185 42 202 398 211 410 216 418 219 456 186 456
+"Call" 0x01100004 38 458 70 458 71 478 75 486 83 492 94 494 94 516 56 516 45 507 38 498
+"Hangup" 0x01100005 186 458 220 458 220 496 214 508 200 516 162 516 161 494 172 492 180 486 185 478
+"Left" 0x1000012 86 405 106 426 106 461 85 478
+"Down" 0x1000015 106 460 151 460 170 480 85 480
+"Right" 0x1000014 151 424 170 404 170 480 151 460
+"Up" 0x1000013 85 403 168 403 150 424 106 424
+"Select" 0x01010000 106 426 150 456
+"Home" 0x1000010 105 493 145 512
diff --git a/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf b/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf
new file mode 100644
index 0000000000..6665125c90
--- /dev/null
+++ b/tools/qvfb/Trolltech-Touchscreen.skin/defaultbuttons.conf
@@ -0,0 +1,53 @@
+[Translation]
+File=QtopiaDefaults
+Context=Buttons
+[Menu]
+Rows=4
+Columns=3
+Map=123456789*0#
+Default=5
+1=Applications/camera.desktop
+2=Applications/mediaplayer.desktop
+3=Applications/simapp.desktop,Applications/calculator.desktop
+4=Applications/qtmail.desktop
+5=Applications/addressbook.desktop
+6=Applications/datebook.desktop
+7=Games
+8=Settings/beaming.desktop
+9=Applications/todolist.desktop
+*=Settings
+0=Applications
+#=Documents
+Animator=Bounce
+AnimatorBackground=Radial
+[SoftKeys]
+Count=3
+Key0=Context1
+Key1=Select
+Key2=Back
+[SystemButtons]
+Count=5
+Key0=Context1
+Key1=Back
+Key2=Select
+Key3=Call
+Key4=Hangup
+[Device]
+PrimaryInput=Touchscreen
+[Button]
+Count=2
+[Button0]
+Name[]=Home Button
+Key=Home
+PressedActionMappable=0
+PressedActionService=TaskManager
+PressedActionMessage=multitask()
+HeldActionMappable=0
+HeldActionService=TaskManager
+HeldActionMessage=showRunningTasks()
+[Button1]
+Name=Power Button
+Key=Hangup
+HeldActionService=Launcher
+HeldActionMessage=execute(QString)
+HeldActionArgs=@ByteArray(\0\0\0\x1\0\0\0\n\0\0\0\0\x10\0s\0h\0u\0t\0\x64\0o\0w\0n)
diff --git a/tools/qvfb/config.ui b/tools/qvfb/config.ui
new file mode 100644
index 0000000000..7a45bfe0a4
--- /dev/null
+++ b/tools/qvfb/config.ui
@@ -0,0 +1,2528 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>Config</class>
+ <widget class="QDialog" name="Config" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>650</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Configure</string>
+ </property>
+ <property name="sizeGripEnabled" >
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>8</number>
+ </property>
+ <property name="topMargin" >
+ <number>8</number>
+ </property>
+ <property name="rightMargin" >
+ <number>8</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>8</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="ButtonGroup1" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Size</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>11</number>
+ </property>
+ <property name="topMargin" >
+ <number>11</number>
+ </property>
+ <property name="rightMargin" >
+ <number>11</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>11</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="size_176_220" >
+ <property name="text" >
+ <string>176x220 "SmartPhone"</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="size_240_320" >
+ <property name="text" >
+ <string>240x320 "PDA"</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="size_320_240" >
+ <property name="text" >
+ <string>320x240 "TV" / "QVGA"</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="size_640_480" >
+ <property name="text" >
+ <string>640x480 "VGA"</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="size_800_600" >
+ <property name="text" >
+ <string>800x600</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="size_1024_768" >
+ <property name="text" >
+ <string>1024x768</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="size_custom" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Custom</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="size_width" >
+ <property name="minimum" >
+ <number>1</number>
+ </property>
+ <property name="maximum" >
+ <number>1280</number>
+ </property>
+ <property name="singleStep" >
+ <number>16</number>
+ </property>
+ <property name="value" >
+ <number>400</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="size_height" >
+ <property name="minimum" >
+ <number>1</number>
+ </property>
+ <property name="maximum" >
+ <number>1024</number>
+ </property>
+ <property name="singleStep" >
+ <number>16</number>
+ </property>
+ <property name="value" >
+ <number>300</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="ButtonGroup2" >
+ <property name="title" >
+ <string>Depth</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>11</number>
+ </property>
+ <property name="topMargin" >
+ <number>11</number>
+ </property>
+ <property name="rightMargin" >
+ <number>11</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>11</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="depth_1" >
+ <property name="text" >
+ <string>1 bit monochrome</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_4gray" >
+ <property name="text" >
+ <string>4 bit grayscale</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_8" >
+ <property name="text" >
+ <string>8 bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_12" >
+ <property name="text" >
+ <string>12 (16) bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_15" >
+ <property name="text" >
+ <string>15 bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_16" >
+ <property name="text" >
+ <string>16 bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_18" >
+ <property name="text" >
+ <string>18 bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_24" >
+ <property name="text" >
+ <string>24 bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_32" >
+ <property name="text" >
+ <string>32 bit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="depth_32_argb" >
+ <property name="text" >
+ <string>32 bit ARGB</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="TextLabel1_3" >
+ <property name="text" >
+ <string>Skin</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="skin" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <item>
+ <property name="text" >
+ <string>None</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="touchScreen" >
+ <property name="text" >
+ <string>Emulate touch screen (no mouse move)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="lcdScreen" >
+ <property name="text" >
+ <string>Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="TextLabel1" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>&lt;p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth &lt;i>above&lt;/i>. You may freely modify the Gamma &lt;i>below&lt;/i>.</string>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="GroupBox1" >
+ <property name="title" >
+ <string>Gamma</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="leftMargin" >
+ <number>11</number>
+ </property>
+ <property name="topMargin" >
+ <number>11</number>
+ </property>
+ <property name="rightMargin" >
+ <number>11</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>11</number>
+ </property>
+ <property name="horizontalSpacing" >
+ <number>6</number>
+ </property>
+ <property name="verticalSpacing" >
+ <number>6</number>
+ </property>
+ <item row="6" column="0" >
+ <widget class="QLabel" name="TextLabel3" >
+ <property name="text" >
+ <string>Blue</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1" >
+ <widget class="QSlider" name="bslider" >
+ <property name="palette" >
+ <palette>
+ <active>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>127</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>38</red>
+ <green>38</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>127</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>38</red>
+ <green>38</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>127</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>38</red>
+ <green>38</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="maximum" >
+ <number>400</number>
+ </property>
+ <property name="value" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="2" >
+ <widget class="QLabel" name="blabel" >
+ <property name="text" >
+ <string>1.0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="TextLabel2" >
+ <property name="text" >
+ <string>Green</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" >
+ <widget class="QSlider" name="gslider" >
+ <property name="palette" >
+ <palette>
+ <active>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>255</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>38</red>
+ <green>255</green>
+ <blue>38</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>127</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>255</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>38</red>
+ <green>255</green>
+ <blue>38</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>127</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>255</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>38</red>
+ <green>255</green>
+ <blue>38</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>127</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="maximum" >
+ <number>400</number>
+ </property>
+ <property name="value" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2" >
+ <widget class="QLabel" name="glabel" >
+ <property name="text" >
+ <string>1.0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="TextLabel7" >
+ <property name="text" >
+ <string>All</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QLabel" name="TextLabel8" >
+ <property name="text" >
+ <string>1.0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QSlider" name="gammaslider" >
+ <property name="palette" >
+ <palette>
+ <active>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="maximum" >
+ <number>400</number>
+ </property>
+ <property name="value" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="TextLabel1_2" >
+ <property name="text" >
+ <string>Red</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" >
+ <widget class="QLabel" name="rlabel" >
+ <property name="text" >
+ <string>1.0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QSlider" name="rslider" >
+ <property name="palette" >
+ <palette>
+ <active>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>38</green>
+ <blue>38</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>38</green>
+ <blue>38</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Button" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Light" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Midlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>38</green>
+ <blue>38</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Dark" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>127</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Mid" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Text" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="BrightText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="ButtonText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Base" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Window" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Shadow" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Highlight" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="HighlightedText" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="Link" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="LinkVisited" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ <colorrole role="AlternateBase" >
+ <brush brushstyle="SolidPattern" >
+ <color alpha="255" >
+ <red>232</red>
+ <green>232</green>
+ <blue>232</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="maximum" >
+ <number>400</number>
+ </property>
+ <property name="value" >
+ <number>100</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0" colspan="3" >
+ <widget class="QPushButton" name="PushButton3" >
+ <property name="text" >
+ <string>Set all to 1.0</string>
+ </property>
+ </widget>
+ </item>
+ <item rowspan="9" row="0" column="3" >
+ <widget class="GammaView" native="1" name="MyCustomWidget1" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonOk" >
+ <property name="text" >
+ <string>&amp;OK</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="buttonCancel" >
+ <property name="text" >
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="autoDefault" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11" />
+ <customwidgets>
+ <customwidget>
+ <class>GammaView</class>
+ <extends></extends>
+ <header>gammaview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>size_width</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>size_custom</receiver>
+ <slot>click()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>152</x>
+ <y>193</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>94</x>
+ <y>199</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>size_height</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>size_custom</receiver>
+ <slot>click()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>259</x>
+ <y>196</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>64</x>
+ <y>188</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/qvfb/gammaview.h b/tools/qvfb/gammaview.h
new file mode 100644
index 0000000000..53717a61f4
--- /dev/null
+++ b/tools/qvfb/gammaview.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GAMMAVIEW_H
+#define GAMMAVIEW_H
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class GammaView: public QWidget
+{
+ Q_OBJECT
+public:
+ GammaView( QWidget *parent = 0, Qt::WindowFlags f = 0 )
+ : QWidget(parent,f) { }
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/images/logo-nt.png b/tools/qvfb/images/logo-nt.png
new file mode 100644
index 0000000000..92f77d86b6
--- /dev/null
+++ b/tools/qvfb/images/logo-nt.png
Binary files differ
diff --git a/tools/qvfb/images/logo.png b/tools/qvfb/images/logo.png
new file mode 100644
index 0000000000..0093177787
--- /dev/null
+++ b/tools/qvfb/images/logo.png
Binary files differ
diff --git a/tools/qvfb/main.cpp b/tools/qvfb/main.cpp
new file mode 100644
index 0000000000..b0eb4e776d
--- /dev/null
+++ b/tools/qvfb/main.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvfb.h"
+
+#include <QApplication>
+#include <QRegExp>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#ifdef Q_WS_X11
+#include <QX11Info>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+void fn_quit_qvfb(int)
+{
+ // pretend that we have quit normally
+ qApp->quit();
+}
+
+
+void usage( const char *app )
+{
+ printf( "Usage: %s [-width width] [-height height] [-depth depth] [-zoom zoom]"
+ "[-mmap] [-nocursor] [-qwsdisplay :id] [-x11display :id] [-skin skindirectory]\n"
+ "Supported depths: 1, 4, 8, 12, 15, 16, 18, 24, 32\n", app );
+}
+int qvfb_protocol = 0;
+
+int runQVfb( int argc, char *argv[] )
+{
+ Q_INIT_RESOURCE(qvfb);
+
+ QApplication app( argc, argv );
+
+ int width = 0;
+ int height = 0;
+ int depth = -32; // default, but overridable by skin
+ bool depthSet = false;
+ int rotation = 0;
+ bool cursor = true;
+ QVFb::DisplayType displayType = QVFb::QWS;
+ double zoom = 1.0;
+ QString displaySpec( ":0" );
+ QString skin;
+
+ for ( int i = 1; i < argc; i++ ){
+ QString arg = argv[i];
+ if ( arg == "-width" ) {
+ width = atoi( argv[++i] );
+ } else if ( arg == "-height" ) {
+ height = atoi( argv[++i] );
+ } else if ( arg == "-skin" ) {
+ skin = argv[++i];
+ } else if ( arg == "-depth" ) {
+ depth = atoi( argv[++i] );
+ depthSet = true;
+ } else if ( arg == "-nocursor" ) {
+ cursor = false;
+ } else if ( arg == "-mmap" ) {
+ qvfb_protocol = 1;
+ } else if ( arg == "-zoom" ) {
+ zoom = atof( argv[++i] );
+ } else if ( arg == "-qwsdisplay" ) {
+ displaySpec = argv[++i];
+ displayType = QVFb::QWS;
+#ifdef Q_WS_X11
+ } else if ( arg == "-x11display" ) {
+ displaySpec = argv[++i];
+ displayType = QVFb::X11;
+
+ // Usually only the default X11 depth will work with Xnest,
+ // so override the default of 32 with the actual X11 depth.
+ if (!depthSet)
+ depth = -QX11Info::appDepth(); // default, but overridable by skin
+#endif
+ } else {
+ printf( "Unknown parameter %s\n", arg.toLatin1().constData() );
+ usage( argv[0] );
+ exit(1);
+ }
+ }
+
+ int displayId = 0;
+ QRegExp r( ":[0-9]+" );
+ int m = r.indexIn( displaySpec, 0 );
+ int len = r.matchedLength();
+ if ( m >= 0 ) {
+ displayId = displaySpec.mid( m+1, len-1 ).toInt();
+ }
+ QRegExp rotRegExp( "Rot[0-9]+" );
+ m = rotRegExp.indexIn( displaySpec, 0 );
+ len = rotRegExp.matchedLength();
+ if ( m >= 0 ) {
+ rotation = displaySpec.mid( m+3, len-3 ).toInt();
+ }
+
+ signal(SIGINT, fn_quit_qvfb);
+ signal(SIGTERM, fn_quit_qvfb);
+
+ QVFb mw( displayId, width, height, depth, rotation, skin, displayType );
+ mw.setZoom(zoom);
+ //app.setMainWidget( &mw );
+ mw.enableCursor(cursor);
+ mw.show();
+
+ return app.exec();
+}
+
+QT_END_NAMESPACE
+
+int main( int argc, char *argv[] )
+{
+ return QT_PREPEND_NAMESPACE(runQVfb)(argc, argv);
+}
diff --git a/tools/qvfb/pda.qrc b/tools/qvfb/pda.qrc
new file mode 100644
index 0000000000..b14e7b3b2a
--- /dev/null
+++ b/tools/qvfb/pda.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/skins">
+ <file>pda.skin</file>
+</qresource>
+</RCC>
diff --git a/tools/qvfb/pda.skin b/tools/qvfb/pda.skin
new file mode 100644
index 0000000000..037f750aa1
--- /dev/null
+++ b/tools/qvfb/pda.skin
@@ -0,0 +1,14 @@
+pda_up.png pda_down.png
+57 81
+240 320
+11
+"Power" 0x0100000a 277 36 302 57
+"F1" 0x01000030 52 439 81 470
+"F2" 0x01000031 101 422 130 451
+"F3" 0x01000032 232 423 260 452
+"F4" 0x01000033 279 445 309 473
+"Left" 0x01000012 155 438 176 472
+"Down" 0x01000015 169 471 203 486
+"Right" 0x01000014 193 448 215 472
+"Up" 0x01000013 166 427 199 451
+"Enter" 0x01000005 177 448 193 468
diff --git a/tools/qvfb/pda_down.png b/tools/qvfb/pda_down.png
new file mode 100644
index 0000000000..0ea157de70
--- /dev/null
+++ b/tools/qvfb/pda_down.png
Binary files differ
diff --git a/tools/qvfb/pda_up.png b/tools/qvfb/pda_up.png
new file mode 100644
index 0000000000..541e3c404f
--- /dev/null
+++ b/tools/qvfb/pda_up.png
Binary files differ
diff --git a/tools/qvfb/qanimationwriter.cpp b/tools/qvfb/qanimationwriter.cpp
new file mode 100644
index 0000000000..caa7e95a92
--- /dev/null
+++ b/tools/qvfb/qanimationwriter.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qanimationwriter.h"
+#include <QFile>
+#include <QString>
+#include <QPainter>
+#include <png.h>
+#include <limits.h>
+#include <netinet/in.h> // for htonl
+
+#ifdef QT_LINUXBASE
+# include <arpa/inet.h> // for htonl (LSB only)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationWriterData
+{
+public:
+ QAnimationWriterData(QIODevice* d) : framerate(1000), dev(d) {}
+ void setFrameRate(int d) { framerate = d; }
+ virtual ~QAnimationWriterData() { }
+ virtual void setImage(const QImage& src)=0;
+ virtual bool canCompose() const { return false; }
+ virtual void composeImage(const QImage&, const QPoint& ) {}
+
+protected:
+ int framerate;
+ QIODevice* dev;
+};
+
+
+class QAnimationWriterMNG : public QAnimationWriterData {
+ bool first;
+ png_structp png_ptr;
+ png_infop info_ptr;
+public:
+ QAnimationWriterMNG(QIODevice* d) : QAnimationWriterData(d)
+ {
+ first = true;
+ begin_png();
+ }
+
+ ~QAnimationWriterMNG()
+ {
+ if (first) {
+ // Eh? Not images.
+ QImage dummy(1,1,QImage::Format_RGB32);
+ setImage(dummy);
+ }
+ writeMEND();
+ end_png();
+ }
+
+ void begin_png()
+ {
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
+ info_ptr = png_create_info_struct(png_ptr);
+ png_set_compression_level(png_ptr,9);
+ png_set_write_fn(png_ptr, (void*)this, write, 0);
+ }
+
+ void end_png()
+ {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ }
+
+ static void write( png_structp png_ptr, png_bytep data, png_size_t length)
+ {
+ QAnimationWriterMNG* that = (QAnimationWriterMNG*)png_get_io_ptr(png_ptr);
+ /*uint nw =*/ that->dev->write((const char*)data,length);
+ }
+
+ void writePNG(const QImage& image)
+ {
+#ifndef QT_LINUXBASE
+ // LSB disallows accessing the info_ptr directly. LSB's png_set_IHDR sets
+ // the channels anyways, so just comment it out for LSB usage
+ info_ptr->channels = 4;
+#endif
+ png_set_sig_bytes(png_ptr, 8); // Pretend we already wrote the sig
+ png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
+ 8, image.hasAlphaChannel()
+ ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
+ 0, 0, 0);
+ png_write_info(png_ptr, info_ptr);
+ if (!image.hasAlphaChannel())
+ png_set_filler(png_ptr, 0,
+ QSysInfo::ByteOrder == QSysInfo::BigEndian ?
+ PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
+ //if ( QImage::systemByteOrder() == QImage::BigEndian ) {
+ //png_set_swap_alpha(png_ptr);
+ //}
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ png_set_bgr(png_ptr);
+ }
+
+ int height = image.height();
+ png_bytep *row_pointers = new png_bytep[height];
+ for (int i = 0; i < height; ++i)
+ row_pointers[i] = (png_bytep)image.scanLine(i);
+ png_write_image(png_ptr, row_pointers);
+ delete [] row_pointers;
+ png_write_end(png_ptr, info_ptr);
+ end_png();
+ begin_png();
+ }
+
+ void writeMHDR(const QSize& size, int framerate)
+ {
+ dev->write("\212MNG\r\n\032\n", 8);
+
+ struct {
+ int width;
+ int height;
+ int framerate;
+ int a,b,c;
+ int profile;
+ } chunk;
+ chunk.width = htonl(size.width());
+ chunk.height = htonl(size.height());
+ chunk.framerate = htonl(framerate);
+ chunk.a=0;
+ chunk.b=0;
+ chunk.c=0;
+ chunk.profile = htonl(0x00000003);
+
+ png_write_chunk(png_ptr, (png_byte*)"MHDR", (png_byte*)&chunk, sizeof(chunk));
+ }
+
+ void writeMEND()
+ {
+ png_write_chunk(png_ptr, (png_byte*)"MEND", 0, 0);
+ }
+
+ void writeDEFI(const QPoint& offset, const QSize& /*size*/)
+ {
+ struct {
+ ushort o;
+ uchar s;
+ uchar concrete;
+ int x,y;
+ int lc,rc,tc,bc;
+ } chunk;
+ chunk.o=0;
+ chunk.s=0;
+ chunk.concrete=1;
+ chunk.x=htonl(offset.x());
+ chunk.y=htonl(offset.y());
+ chunk.lc=0;
+ chunk.rc=0;
+ chunk.tc=htonl(INT_MAX);
+ chunk.bc=htonl(INT_MAX);
+
+ png_write_chunk(png_ptr, (png_byte*)"DEFI", (png_byte*)&chunk, sizeof(chunk));
+ }
+
+ void writeFRAM(const QSize& size)
+ {
+ struct {
+ uchar mode;
+ uchar n;
+ uchar nu;
+ uchar d;
+ uchar t;
+ uchar clip;
+ uchar s;
+ uchar deltatype;
+ uint left;
+ uint right;
+ uint top;
+ uint bottom;
+ } chunk;
+ chunk.mode=1;
+ chunk.n='a';
+ chunk.nu=0;
+ chunk.d=0;
+ chunk.clip=1;
+ chunk.t=0;
+ chunk.s=0;
+ chunk.deltatype=0;
+ chunk.left=0;
+ chunk.right=htonl(size.width());
+ chunk.top=0;
+ chunk.bottom=htonl(size.height());
+
+ png_write_chunk(png_ptr, (png_byte*)"FRAM", (png_byte*)&chunk, sizeof(chunk));
+ }
+
+ void writeMOVE(const QPoint& offset)
+ {
+ struct {
+ uchar filler[3];
+ uchar z[5];
+ int x,y;
+ } chunk;
+ memset(chunk.z,0,5);
+ chunk.x=htonl(offset.x());
+ chunk.y=htonl(offset.y());
+
+ png_write_chunk(png_ptr, (png_byte*)"MOVE", ((png_byte*)&chunk)+3, sizeof(chunk)-3);
+ }
+
+ void setImage(const QImage& src)
+ {
+ if (first) {
+ first = false;
+ writeMHDR(src.size(),framerate);
+ }
+ composeImage(src,QPoint(0,0));
+ }
+
+ bool canCompose() const { return true; }
+
+ void composeImage(const QImage& src, const QPoint& offset)
+ {
+ writeMOVE(offset);
+ //writeFRAM(src.size());
+ writePNG(src);
+ }
+};
+
+QAnimationWriter::QAnimationWriter(const QString& filename, const char* format)
+{
+ if (qstrncmp(format, "MNG", 4)) {
+ qWarning("Format \"%s\" not supported, only MNG", format);
+ dev = 0;
+ d = 0;
+ } else {
+ QFile *f = new QFile(filename);
+ f->open(QIODevice::WriteOnly);
+ dev = f;
+ d = new QAnimationWriterMNG(dev);
+ }
+}
+
+bool QAnimationWriter::okay() const
+{
+ if (!dev)
+ return false;
+ QFile *file = qobject_cast<QFile*>(dev);
+ Q_ASSERT(file);
+ return (file->error() == QFile::NoError);
+}
+
+QAnimationWriter::~QAnimationWriter()
+{
+ delete d;
+ delete dev;
+}
+
+void QAnimationWriter::setFrameRate(int r)
+{
+ if (d)
+ d->setFrameRate(r);
+}
+
+void QAnimationWriter::appendFrame(const QImage& frm, const QPoint& offset)
+{
+ if (!dev)
+ return;
+
+ const QImage frame = frm.convertToFormat(QImage::Format_RGB32);
+ const int alignx = 1;
+ if (prev.isNull() || !d->canCompose()) {
+ d->setImage(frame);
+ } else {
+ bool done;
+ int minx, maxx, miny, maxy;
+ int w = frame.width();
+ int h = frame.height();
+
+ const quint32 *framePtr = reinterpret_cast<const quint32*>(frame.bits());
+ const quint32 *prevPtr = reinterpret_cast<const quint32*>(prev.bits());
+ const int frameStride = frame.bytesPerLine() / sizeof(quint32);
+ const int prevStride = prev.bytesPerLine() / sizeof(quint32);
+
+ // Find left edge of change
+ done = false;
+ for (minx = 0; minx < w && !done; ++minx) {
+ const quint32 *p1 = framePtr + minx;
+ const quint32 *p2 = prevPtr + minx + offset.x();
+ for (int y = 0; y < h; ++y) {
+ if (*p1 != *p2) {
+ done = true;
+ break;
+ }
+ p1 += frameStride;
+ p2 += prevStride;
+ }
+ }
+ --minx;
+
+ // Find right edge of change
+ done = false;
+ for (maxx = w-1; maxx >= 0 && !done; --maxx) {
+ const quint32 *p1 = framePtr + maxx;
+ const quint32 *p2 = prevPtr + maxx + offset.x();
+ for (int y = 0; y < h; ++y) {
+ if (*p1 != *p2) {
+ done = true;
+ break;
+ }
+ p1 += frameStride;
+ p2 += prevStride;
+ }
+ }
+ ++maxx;
+
+ // Find top edge of change
+ done = false;
+ for (miny = 0; miny < h && !done; ++miny) {
+ const quint32 *p1 = framePtr + miny * frameStride;
+ const quint32 *p2 = prevPtr + miny * prevStride + offset.x();
+ for (int x = 0; x < w; ++x) {
+ if (*p1 != *p2) {
+ done = true;
+ break;
+ }
+ ++p1;
+ ++p2;
+ }
+ }
+ --miny;
+
+ // Find right edge of change
+ done = false;
+ for (maxy = h-1; maxy >= 0 && !done; --maxy) {
+ const quint32 *p1 = framePtr + maxy * frameStride;
+ const quint32 *p2 = prevPtr + maxy * prevStride + offset.x();
+ for (int x = 0; x < w; ++x) {
+ if (*p1 != *p2) {
+ done = true;
+ break;
+ }
+ ++p1;
+ ++p2;
+ }
+ }
+ ++maxy;
+
+ if (minx > maxx)
+ minx = maxx = 0;
+ if (miny > maxy)
+ miny = maxy = 0;
+
+ if (alignx > 1) {
+ minx -= minx % alignx;
+ maxx = maxx - maxx % alignx + alignx - 1;
+ }
+
+ int dw = maxx - minx + 1;
+ int dh = maxy - miny + 1;
+
+ QImage diff(dw, dh, QImage::Format_ARGB32);
+
+ int x, y;
+ for (y = 0; y < dh; ++y) {
+ QRgb* li = (QRgb*)frame.scanLine(y+miny)+minx;
+ QRgb* lp = (QRgb*)prev.scanLine(y+miny+offset.y())+minx+offset.x();
+ QRgb* ld = (QRgb*)diff.scanLine(y);
+ if (alignx) {
+ for (x = 0; x < dw; x += alignx) {
+ int i;
+ for (i = 0; i < alignx; ++i) {
+ if (li[x+i] != lp[x+i])
+ break;
+ }
+ if (i == alignx) {
+ // All the same
+ for (i = 0; i < alignx; ++i)
+ ld[x+i] = qRgba(0,0,0,0);
+ } else {
+ // Some different
+ for (i = 0; i < alignx; ++i)
+ ld[x+i] = 0xff000000 | li[x+i];
+ }
+ }
+ } else {
+ for (x = 0; x < dw; ++x) {
+ if (li[x] != lp[x])
+ ld[x] = 0xff000000 | li[x];
+ else
+ ld[x] = qRgba(0,0,0,0);
+ }
+ }
+ }
+
+ d->composeImage(diff, QPoint(minx, miny) + offset);
+ }
+ if (prev.isNull() || (prev.size() == frame.size() && offset == QPoint(0,0))) {
+ prev = frame;
+ } else {
+ QPainter p(&prev);
+ p.drawImage(offset.x(), offset.y(), frame, 0, 0,
+ frame.width(), frame.height());
+ }
+}
+
+void QAnimationWriter::appendFrame(const QImage& frm)
+{
+ appendFrame(frm, QPoint(0,0));
+}
+
+void QAnimationWriter::appendBlankFrame()
+{
+ QImage i(1,1,QImage::Format_ARGB32);
+ i.fill(0);
+ d->composeImage(i, QPoint(0,0));
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/qanimationwriter.h b/tools/qvfb/qanimationwriter.h
new file mode 100644
index 0000000000..8440a89677
--- /dev/null
+++ b/tools/qvfb/qanimationwriter.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONWRITER_H
+#define QANIMATIONWRITER_H
+
+#include <QImage>
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationWriterData;
+
+class QAnimationWriter
+{
+public:
+ QAnimationWriter(const QString& filename, const char* format = "MNG");
+ ~QAnimationWriter();
+
+ bool okay() const;
+ void setFrameRate(int);
+ void appendBlankFrame();
+ void appendFrame(const QImage&);
+ void appendFrame(const QImage&, const QPoint& offset);
+
+private:
+ QImage prev;
+ QIODevice* dev;
+ QAnimationWriterData* d;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/qtopiakeysym.h b/tools/qvfb/qtopiakeysym.h
new file mode 100644
index 0000000000..2641e91d87
--- /dev/null
+++ b/tools/qvfb/qtopiakeysym.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Phone Edition of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTKEYSYM_H
+#define QTKEYSYM_H
+
+/* Special keys used by Qtopia, mapped into the X11 private keypad range */
+#define QTOPIAXK_Select 0x11000601
+#define QTOPIAXK_Yes 0x11000602
+#define QTOPIAXK_No 0x11000603
+
+#define QTOPIAXK_Cancel 0x11000604
+#define QTOPIAXK_Printer 0x11000605
+#define QTOPIAXK_Execute 0x11000606
+#define QTOPIAXK_Sleep 0x11000607
+#define QTOPIAXK_Play 0x11000608
+#define QTOPIAXK_Zoom 0x11000609
+
+#define QTOPIAXK_Context1 0x1100060A
+#define QTOPIAXK_Context2 0x1100060B
+#define QTOPIAXK_Context3 0x1100060C
+#define QTOPIAXK_Context4 0x1100060D
+#define QTOPIAXK_Call 0x1100060E
+#define QTOPIAXK_Hangup 0x1100060F
+#define QTOPIAXK_Flip 0x11000610
+
+#define QTOPIAXK_Min QTOPIAXK_Select
+#define QTOPIAXK_Max QTOPIAXK_Flip
+
+#endif
diff --git a/tools/qvfb/qvfb.cpp b/tools/qvfb/qvfb.cpp
new file mode 100644
index 0000000000..b6a715c1d4
--- /dev/null
+++ b/tools/qvfb/qvfb.cpp
@@ -0,0 +1,1137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvfb.h"
+#include "qvfbview.h"
+#ifdef Q_WS_X11
+#include "qvfbx11view.h"
+#endif
+#include "qvfbratedlg.h"
+#include "ui_config.h"
+#include "qanimationwriter.h"
+
+#include <deviceskin.h>
+
+#include <QMenuBar>
+#include <QMenu>
+#include <QApplication>
+#include <QMessageBox>
+#include <QComboBox>
+#include <QLabel>
+#include <QFileDialog>
+#include <QSlider>
+#include <QSpinBox>
+#include <QLayout>
+#include <QRadioButton>
+#include <QImage>
+#include <QPixmap>
+#include <QCheckBox>
+#include <QCursor>
+#include <QTime>
+#include <QScrollArea>
+#include <QProgressBar>
+#include <QPushButton>
+#include <QTextStream>
+#include <QFile>
+#include <QFileInfo>
+#include <QDebug>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+QT_BEGIN_NAMESPACE
+
+// =====================================================================
+
+static const char *red_on_led_xpm[] = {
+"11 11 10 1",
+" c None",
+". c #FF0000",
+"+ c #FF4C4C",
+"@ c #FF7A7A",
+"# c #D30000",
+"$ c #FF9393",
+"% c #BA0000",
+"& c #FFFFFF",
+"* c #7F0000",
+"= c #000000",
+" ",
+" .++@@ ",
+" .....+@ ",
+" ##...$.+@ ",
+" %#..$&$.+ ",
+" *#...$..+ ",
+" *%#...... ",
+" =*%#..... ",
+" =*%###. ",
+" ===*. ",
+" "};
+
+static const char *red_off_led_xpm[] = {
+"11 11 12 1",
+" c None",
+". c #CDB7B4",
+"+ c #D2BFBD",
+"@ c #DBCBCA",
+"# c #E5D9D8",
+"$ c #BC9E9B",
+"% c #E2D6D5",
+"& c #AD8986",
+"* c #FFFFFF",
+"= c #A8817D",
+"- c #B2908D",
+"; c #6F4D4A",
+" ",
+" .++@# ",
+" .....@# ",
+" $$...%.@# ",
+" &$..%*%.@ ",
+" =-...%..+ ",
+" =&-...... ",
+" ;==-..... ",
+" ;=&-$$. ",
+" ;==&$ ",
+" "};
+
+static bool copyButtonConfiguration(const QString &prefix, int displayId)
+{
+ const QString destDir = QString(QLatin1String("/tmp/qtembedded-%1/")).arg(displayId);
+ const QFileInfo src(prefix + QLatin1String("defaultbuttons.conf"));
+ const QFileInfo dst(destDir + QLatin1String("defaultbuttons.conf"));
+ unlink(dst.absoluteFilePath().toLatin1().constData());
+ if (!src.exists())
+ return false;
+ const bool rc = QFile::copy(src.absoluteFilePath(), dst.absoluteFilePath());
+ if (!rc)
+ qWarning() << "Failed to copy the button configuration file " << src.absoluteFilePath() << " to " << dst.absoluteFilePath() << '.';
+ return rc;
+}
+
+// =====================================================================
+
+class AnimationSaveWidget : public QWidget {
+ Q_OBJECT
+public:
+ AnimationSaveWidget(QVFbAbstractView *v);
+ ~AnimationSaveWidget();
+ bool detectPpmtoMpegCommand();
+ void timerEvent(QTimerEvent *te);
+ void convertToMpeg(QString filename);
+ void removeTemporaryFiles();
+protected slots:
+ void toggleRecord();
+ void reset();
+ void save();
+private:
+ QVFbAbstractView *view;
+ QProgressBar *progressBar;
+ QLabel *statusText;
+ bool haveMpeg, savingAsMpeg, recording;
+ QCheckBox *mpegSave;
+ QAnimationWriter *animation;
+ QPushButton *recBt, *resetBt, *saveBt;
+ QLabel *timeDpy, *recLED;
+ int timerId, progressTimerId;
+ QPixmap recOn, recOff;
+ QTime tm;
+ int elapsed, imageNum;
+};
+
+// =====================================================================
+
+Zoomer::Zoomer(QVFb* target) :
+ qvfb(target)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ QSlider *sl = new QSlider(Qt::Horizontal);
+ sl->setMinimum(10);
+ sl->setMaximum(64);
+ sl->setPageStep(1);
+ sl->setValue(32);
+ layout->addWidget(sl);
+ connect(sl,SIGNAL(valueChanged(int)),this,SLOT(zoom(int)));
+ label = new QLabel();
+ layout->addWidget(label);
+}
+
+void Zoomer::zoom(int z)
+{
+ double d = (double)z/32.0;
+ qvfb->setZoom(d);
+ label->setText(QString::number(d,'g',2));
+}
+
+// =====================================================================
+
+QVFb::QVFb( int display_id, int w, int h, int d, int r, const QString &skin, DisplayType displayType, QWidget *parent, Qt::WindowFlags flags )
+ : QMainWindow( parent, flags )
+{
+ this->displayType = displayType;
+ view = 0;
+ secondaryView = 0;
+ scroller = 0;
+ this->skin = 0;
+ currentSkinIndex = -1;
+ findSkins(skin);
+ zoomer = 0;
+ QPixmap pix(":/res/images/logo.png");
+ setWindowIcon( pix );
+ rateDlg = 0;
+ refreshRate = 30;
+#if QT_VERSION >= 0x030000
+ // When compiling with Qt 3 we need to create the menu first to
+ // avoid scroll bars in the main window
+ createMenu( menuBar() );
+ init( display_id, w, h, d, r, skin );
+ enableCursor( true );
+#else
+ init( display_id, w, h, d, r, skin );
+ createMenu( menuBar() );
+#endif
+}
+
+QVFb::~QVFb()
+{
+}
+
+void QVFb::popupMenu()
+{
+ QMenu *pm = new QMenu( this );
+ createMenu( pm );
+ pm->exec(QCursor::pos());
+}
+
+void QVFb::init( int display_id, int pw, int ph, int d, int r, const QString& skin_name )
+{
+ delete view;
+ view = 0;
+ delete secondaryView;
+ secondaryView = 0;
+ delete scroller;
+ scroller = 0;
+ delete skin;
+ skin = 0;
+
+ skinscaleH = skinscaleV = 1.0;
+ QVFbView::Rotation rot = ((r == 90) ? QVFbView::Rot90 :
+ ((r == 180) ? QVFbView::Rot180 :
+ ((r == 270) ? QVFbView::Rot270 :
+ QVFbView::Rot0 )));
+ if ( !skin_name.isEmpty() ) {
+ const bool vis = isVisible();
+ DeviceSkinParameters parameters;
+ QString readError;
+ if (parameters.read(skin_name,DeviceSkinParameters::ReadAll, &readError)) {
+ skin = new DeviceSkin(parameters, this);
+ connect(skin, SIGNAL(popupMenu()), this, SLOT(popupMenu()));
+ const int sw = parameters.screenSize().width();
+ const int sh = parameters.screenSize().height();
+ const int sd = parameters.screenDepth;
+ if (!pw) pw = sw;
+ if (!ph) ph = sh;
+ if (d < 0) {
+ if (sd)
+ d = sd;
+ else
+ d = -d;
+ }
+ if (vis)
+ hide();
+ menuBar()->hide();
+ scroller = 0;
+#ifdef Q_WS_X11
+ if (displayType == X11)
+ view = new QVFbX11View( display_id, pw, ph, d, rot, skin );
+ else
+#endif
+ view = new QVFbView( display_id, pw, ph, d, rot, skin );
+ skin->setView( view );
+ view->setContentsMargins( 0, 0, 0, 0 );
+ view->setTouchscreenEmulation(!parameters.hasMouseHover);
+ connect(skin, SIGNAL(skinKeyPressEvent(int,QString,bool)), view, SLOT(skinKeyPressEvent(int,QString,bool)));
+ connect(skin, SIGNAL(skinKeyReleaseEvent(int,QString,bool)), view, SLOT(skinKeyReleaseEvent(int,QString,bool)));
+
+ copyButtonConfiguration(skin->prefix(), view->displayId());
+
+ setCentralWidget( skin );
+ adjustSize();
+ skinscaleH = (double)sw/pw;
+ skinscaleV = (double)sh/ph;
+ if ( skinscaleH != 1.0 || skinscaleH != 1.0 )
+ setZoom(skinscaleH);
+ view->show();
+
+ if (parameters.hasSecondaryScreen()) {
+ const QSize ssize = parameters.secondaryScreenSize();
+ // assumes same depth and rotation
+#ifdef Q_WS_X11
+ if (displayType == X11)
+ secondaryView = new QVFbX11View( display_id+1, ssize.width(), ssize.height(), d, rot, skin );
+ else
+#endif
+ secondaryView = new QVFbView( display_id+1, ssize.width(), ssize.height(), d, rot, skin );
+ skin->setSecondaryView(secondaryView);
+ secondaryView->show();
+ }
+
+ if ( vis ) show();
+ } else {
+ qWarning("%s", qPrintable(readError));
+ }
+ }
+
+ // If we failed to get a skin or we were not supplied
+ // with one then fallback to a framebuffer without
+ // a skin
+ if (!skin){
+ // Default values
+ if (!pw)
+ pw = 240;
+ if (!ph)
+ ph = 320;
+ if (!d)
+ d = 32;
+ else if (d < 0)
+ d = -d;
+
+ if (currentSkinIndex != -1) {
+ clearMask();
+ setParent( 0, 0 );
+ move( pos() );
+ show();
+ //unset fixed size:
+ setMinimumSize(0,0);
+ setMaximumSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX);
+ }
+ menuBar()->show();
+ scroller = new QScrollArea(this);
+ scroller->setFocusPolicy(Qt::NoFocus); // don't steal key events from the embedded app
+#ifdef Q_WS_X11
+ if (displayType == X11)
+ view = new QVFbX11View( display_id, pw, ph, d, rot, scroller );
+ else
+#endif
+ view = new QVFbView( display_id, pw, ph, d, rot, scroller );
+ scroller->setWidget(view);
+ view->setContentsMargins( 0, 0, 0, 0 );
+ setCentralWidget(scroller);
+#if QT_VERSION >= 0x030000
+ ph += 2; // avoid scrollbar
+#endif
+ scroller->show();
+ // delete defaultbuttons.conf if it was left behind...
+ unlink(QFileInfo(QString("/tmp/qtembedded-%1/defaultbuttons.conf").arg(view->displayId())).absoluteFilePath().toLatin1().constData());
+ if (secondaryView)
+ unlink(QFileInfo(QString("/tmp/qtembedded-%1/defaultbuttons.conf").arg(view->displayId()+1)).absoluteFilePath().toLatin1().constData());
+ }
+ view->setRate(refreshRate);
+ if (secondaryView) {
+ secondaryView->setRate(refreshRate);
+ }
+ // Resize QVFb to the new size
+ QSize newSize = view->sizeHint();
+
+ // ... fudge factor
+ newSize += QSize(20, 35);
+
+ resize(newSize);
+
+ setWindowTitle(QString("Virtual framebuffer %1x%2 %3bpp Display :%4 Rotate %5")
+ .arg(view->displayWidth()).arg(view->displayHeight())
+ .arg(d).arg(display_id).arg(r));
+}
+
+void QVFb::enableCursor( bool e )
+{
+ if ( skin && skin->hasCursor() ) {
+ view->setCursor( Qt::BlankCursor );
+ if (secondaryView)
+ secondaryView->setCursor( Qt::BlankCursor );
+ } else {
+ view->setCursor( e ? Qt::ArrowCursor : Qt::BlankCursor );
+ if (secondaryView)
+ secondaryView->setCursor( e ? Qt::ArrowCursor : Qt::BlankCursor );
+ }
+ cursorAction->setChecked( e );
+}
+
+template <typename T>
+void QVFb::createMenu(T *menu)
+{
+ menu->addMenu( createFileMenu() );
+ menu->addMenu( createViewMenu() );
+ menu->addSeparator();
+ menu->addMenu( createHelpMenu() );
+}
+
+QMenu* QVFb::createFileMenu()
+{
+ QMenu *file = new QMenu( "File", this );
+ file->addAction( "Configure...", this, SLOT(configure()), 0 );
+ file->addSeparator();
+ file->addAction( "&Save image...", this, SLOT(saveImage()), 0 );
+ file->addAction( "&Animation...", this, SLOT(toggleAnimation()), 0 );
+ file->addSeparator();
+ file->addAction( "&Quit", qApp, SLOT(quit()) );
+ return file;
+}
+
+QMenu* QVFb::createViewMenu()
+{
+ viewMenu = new QMenu( "View", this );
+ cursorAction = viewMenu->addAction( "Show &Cursor", this,
+ SLOT(toggleCursor()) );
+ cursorAction->setCheckable(true);
+ if ( view )
+ enableCursor(true);
+ viewMenu->addAction( "&Refresh Rate...", this, SLOT(changeRate()) );
+ viewMenu->addSeparator();
+ viewMenu->addAction( "No rotation", this, SLOT(setRot0()) );
+ viewMenu->addAction( "90\260 rotation", this, SLOT(setRot90()) );
+ viewMenu->addAction( "180\260 rotation", this, SLOT(setRot180()) );
+ viewMenu->addAction( "270\260 rotation", this, SLOT(setRot270()) );
+ viewMenu->addSeparator();
+ viewMenu->addAction( "Zoom scale &0.5", this, SLOT(setZoomHalf()) );
+ viewMenu->addAction( "Zoom scale 0.75", this, SLOT(setZoom075()) );
+ viewMenu->addAction( "Zoom scale &1", this, SLOT(setZoom1()) );
+ viewMenu->addAction( "Zoom scale &2", this, SLOT(setZoom2()) );
+ viewMenu->addAction( "Zoom scale &3", this, SLOT(setZoom3()) );
+ viewMenu->addAction( "Zoom scale &4", this, SLOT(setZoom4()) );
+ viewMenu->addSeparator();
+ viewMenu->addAction( "Zoom scale...", this, SLOT(setZoom()) );
+ return viewMenu;
+}
+
+
+QMenu* QVFb::createHelpMenu()
+{
+ QMenu *help = new QMenu( "Help", this );
+ help->addAction("About...", this, SLOT(about()));
+ return help;
+}
+
+void QVFb::setZoom(double z)
+{
+ view->setZoom(z,z*skinscaleV/skinscaleH);
+ if (secondaryView)
+ secondaryView->setZoom(z,z*skinscaleV/skinscaleH);
+
+ if (skin) {
+ skin->setTransform(QMatrix().scale(z/skinscaleH,z/skinscaleV).rotate(90*view->displayRotation()));
+ if (secondaryView)
+ secondaryView->setFixedSize(
+ int(secondaryView->displayWidth()*z),
+ int(secondaryView->displayHeight()*z*skinscaleV/skinscaleH));
+ }
+}
+
+void QVFb::setRotation(QVFbView::Rotation r)
+{
+ view->setRotation(r);
+ if (secondaryView)
+ secondaryView->setRotation(r);
+ setZoom(view->zoomH());
+}
+
+void QVFb::setRot0()
+{
+ setRotation(QVFbView::Rot0);
+}
+
+void QVFb::setRot90()
+{
+ setRotation(QVFbView::Rot90);
+}
+
+void QVFb::setRot180()
+{
+ setRotation(QVFbView::Rot180);
+}
+
+void QVFb::setRot270()
+{
+ setRotation(QVFbView::Rot270);
+}
+
+void QVFb::setZoomHalf()
+{
+ setZoom(0.5);
+}
+
+void QVFb::setZoom075()
+{
+ setZoom(0.75);
+}
+
+void QVFb::setZoom1()
+{
+ setZoom(1);
+}
+
+void QVFb::setZoom()
+{
+ if ( !zoomer )
+ zoomer = new Zoomer(this);
+ zoomer->show();
+}
+
+void QVFb::setZoom2()
+{
+ setZoom(2);
+}
+
+void QVFb::setZoom3()
+{
+ setZoom(3);
+}
+
+void QVFb::setZoom4()
+{
+ setZoom(4);
+}
+
+void QVFb::saveImage()
+{
+ QImage img = view->image();
+ QString filename = QFileDialog::getSaveFileName(this, "Save Main Screen image", "snapshot.png", "Portable Network Graphics (*.png)");
+ if (!filename.isEmpty()){
+ if(!img.save(filename,"PNG"))
+ QMessageBox::critical(this, "Save Main Screen Image", "Save failed. Check that you have permission to write to the target directory.");
+ }
+ if (secondaryView) {
+ QImage img = view->image();
+ QString filename = QFileDialog::getSaveFileName(this, "Save Second Screen image", "snapshot.png", "Portable Network Graphics (*.png)");
+ if (!filename.isEmpty()) {
+ if(!img.save(filename,"PNG"))
+ QMessageBox::critical(this, "Save Second Screen Image", "Save failed. Check that you have permission to write to the target directory.");
+ }
+ }
+}
+
+void QVFb::toggleAnimation()
+{
+ static AnimationSaveWidget *animWidget = 0;
+ if ( !animWidget )
+ animWidget = new AnimationSaveWidget(view);
+ if ( animWidget->isVisible() )
+ animWidget->hide();
+ else
+ animWidget->show();
+}
+
+void QVFb::toggleCursor()
+{
+ enableCursor(cursorAction->isChecked());
+}
+
+void QVFb::changeRate()
+{
+ if ( !rateDlg ) {
+ rateDlg = new QVFbRateDialog( refreshRate, this );
+ connect( rateDlg, SIGNAL(updateRate(int)), this, SLOT(setRate(int)) );
+ }
+
+ rateDlg->show();
+}
+
+void QVFb::setRate(int i)
+{
+ refreshRate = i;
+ view->setRate(i);
+ if (secondaryView)
+ secondaryView->setRate(i);
+}
+
+
+void QVFb::about()
+{
+ QMessageBox::about(this, "About QVFB",
+ "<h2>The Qt for Embedded Linux Virtual X11 Framebuffer</h2>"
+ "<p>This application runs under Qt for X11, emulating a simple framebuffer, "
+ "which the Qt for Embedded Linux server and clients can attach to just as if "
+ "it was a hardware Linux framebuffer. "
+ "<p>With the aid of this development tool, you can develop Qt for Embedded "
+ "Linux applications under X11 without having to switch to a virtual console. "
+ "This means you can comfortably use your other development tools such "
+ "as GUI profilers and debuggers."
+ );
+}
+
+void QVFb::findSkins(const QString &currentSkin)
+{
+ skinnames.clear();
+ skinfiles.clear();
+ QDir dir(":/skins/","*.skin");
+ const QFileInfoList l = dir.entryInfoList();
+ int i = 1; // "None" is already in list at index 0
+ for (QFileInfoList::const_iterator it = l.begin(); it != l.end(); ++it) {
+ skinnames.append((*it).baseName()); // should perhaps be in file
+ skinfiles.append((*it).filePath());
+ if (((*it).baseName() + ".skin") == currentSkin)
+ currentSkinIndex = i;
+ i++;
+ }
+}
+
+class Config : public QDialog, public Ui::Config
+{
+public:
+ Config(QWidget *parent)
+ : QDialog(parent)
+ {
+ setupUi(this);
+ setModal(true);
+
+ connect(buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ }
+};
+
+void QVFb::configure()
+{
+ config = new Config(this);
+
+ int w = view->displayWidth();
+ int h = view->displayHeight();
+
+ // Need to block signals, because we connect to animateClick(),
+ // since QCheckBox doesn't have setChecked(bool) in 2.x.
+ chooseSize(QSize(w,h));
+ config->skin->insertItems(config->skin->count(), skinnames);
+ if (currentSkinIndex > 0)
+ config->skin->setCurrentIndex(currentSkinIndex);
+ config->skin->addItem(tr("Browse..."));
+ config->touchScreen->setChecked(view->touchScreenEmulation());
+ config->lcdScreen->setChecked(view->lcdScreenEmulation());
+ chooseDepth(view->displayDepth(), view->displayFormat());
+ connect(config->skin, SIGNAL(activated(int)), this, SLOT(skinConfigChosen(int)));
+ if ( view->gammaRed() == view->gammaGreen() && view->gammaGreen() == view->gammaBlue() ) {
+ config->gammaslider->setValue(int(view->gammaRed()*400));
+ config->rslider->setValue(100);
+ config->gslider->setValue(100);
+ config->bslider->setValue(100);
+ } else {
+ config->gammaslider->setValue(100);
+ config->rslider->setValue(int(view->gammaRed()*400));
+ config->gslider->setValue(int(view->gammaGreen()*400));
+ config->bslider->setValue(int(view->gammaBlue()*400));
+ }
+ connect(config->gammaslider, SIGNAL(valueChanged(int)), this, SLOT(setGamma400(int)));
+ connect(config->rslider, SIGNAL(valueChanged(int)), this, SLOT(setR400(int)));
+ connect(config->gslider, SIGNAL(valueChanged(int)), this, SLOT(setG400(int)));
+ connect(config->bslider, SIGNAL(valueChanged(int)), this, SLOT(setB400(int)));
+ updateGammaLabels();
+
+ double ogr=view->gammaRed(), ogg=view->gammaGreen(), ogb=view->gammaBlue();
+ qApp->setQuitOnLastWindowClosed(false);
+
+ hide();
+ if ( config->exec() ) {
+ int id = view->displayId(); // not settable yet
+ if ( config->size_176_220->isChecked() ) {
+ w=176; h=220;
+ } else if ( config->size_240_320->isChecked() ) {
+ w=240; h=320;
+ } else if ( config->size_320_240->isChecked() ) {
+ w=320; h=240;
+ } else if ( config->size_640_480->isChecked() ) {
+ w=640; h=480;
+ } else if ( config->size_800_600->isChecked() ) {
+ w=800; h=600;
+ } else if ( config->size_1024_768->isChecked() ) {
+ w=1024; h=768;
+ } else {
+ w=config->size_width->value();
+ h=config->size_height->value();
+ }
+ int d;
+ if ( config->depth_1->isChecked() )
+ d=1;
+ else if ( config->depth_4gray->isChecked() )
+ d=4;
+ else if ( config->depth_8->isChecked() )
+ d=8;
+ else if ( config->depth_12->isChecked() )
+ d=12;
+ else if ( config->depth_15->isChecked() )
+ d = 15;
+ else if ( config->depth_16->isChecked() )
+ d=16;
+ else if ( config->depth_18->isChecked() )
+ d=18;
+ else if ( config->depth_24->isChecked() )
+ d=24;
+ else
+ d=32;
+ QVFbView::PixelFormat displayFormat = config->depth_32_argb->isChecked()
+ ? QVFbView::ARGBFormat : QVFbView::DefaultFormat;
+ int skinIndex = config->skin->currentIndex();
+ if ( w != view->displayWidth() || h != view->displayHeight()
+ || d != view->displayDepth() || skinIndex != currentSkinIndex ) {
+ QVFbView::Rotation rot = view->displayRotation();
+ int r = ((rot == QVFbView::Rot90) ? 90 :
+ ((rot == QVFbView::Rot180) ? 180 :
+ ((rot == QVFbView::Rot270) ? 270 : 0 )));
+ currentSkinIndex = skinIndex;
+ init( id, w, h, d, r, skinIndex > 0 ? skinfiles[skinIndex-1] : QString::null );
+ }
+ view->setViewFormat(displayFormat);
+ view->setTouchscreenEmulation( config->touchScreen->isChecked() );
+ bool lcdEmulation = config->lcdScreen->isChecked();
+ view->setLcdScreenEmulation( lcdEmulation );
+ if ( lcdEmulation )
+ setZoom3();
+ } else {
+ view->setGamma(ogr, ogg, ogb);
+ }
+ show();
+ qApp->setQuitOnLastWindowClosed(true);
+ delete config;
+ config=0;
+}
+
+void QVFb::chooseSize(const QSize& sz)
+{
+ config->size_width->blockSignals(true);
+ config->size_height->blockSignals(true);
+ config->size_width->setValue(sz.width());
+ config->size_height->setValue(sz.height());
+ config->size_width->blockSignals(false);
+ config->size_height->blockSignals(false);
+ config->size_custom->setChecked(true); // unless changed by settings below
+ config->size_176_220->setChecked(sz == QSize(176,220));
+ config->size_240_320->setChecked(sz == QSize(240,320));
+ config->size_320_240->setChecked(sz == QSize(320,240));
+ config->size_640_480->setChecked(sz == QSize(640,480));
+ config->size_800_600->setChecked(sz == QSize(800,600));
+ config->size_1024_768->setChecked(sz == QSize(1024,768));
+}
+
+void QVFb::chooseDepth(int depth, QVFbView::PixelFormat displayFormat)
+{
+ config->depth_1->setChecked(depth==1);
+ config->depth_4gray->setChecked(depth==4);
+ config->depth_8->setChecked(depth==8);
+ config->depth_12->setChecked(depth==12);
+ config->depth_15->setChecked(depth==15);
+ config->depth_16->setChecked(depth==16);
+ config->depth_18->setChecked(depth==18);
+ config->depth_24->setChecked(depth==24);
+ config->depth_32->setChecked(depth==32 && displayFormat != QVFbView::ARGBFormat);
+ config->depth_32_argb->setChecked(depth==32 && displayFormat == QVFbView::ARGBFormat);
+}
+
+void QVFb::skinConfigChosen(int i)
+{
+ if (i == config->skin->count() - 1) { // Browse... ?
+ QFileDialog dlg(this);
+ dlg.setFileMode(QFileDialog::DirectoryOnly);
+ dlg.setWindowTitle(tr("Load Custom Skin..."));
+ dlg.setFilter(tr("All QVFB Skins (*.skin)"));
+ dlg.setDirectory(QDir::current());
+ if (dlg.exec() && dlg.selectedFiles().count() == 1) {
+ skinfiles.append(dlg.selectedFiles().first());
+ i = skinfiles.count();
+ config->skin->insertItem(i, QFileInfo(skinfiles.last()).baseName());
+ config->skin->setCurrentIndex(i);
+ } else {
+ i = 0;
+ }
+ }
+ if ( i ) {
+ DeviceSkinParameters parameters;
+ QString readError;
+ if (parameters.read(skinfiles[i-1], DeviceSkinParameters::ReadSizeOnly, &readError)) {
+ chooseSize(parameters.screenSize());
+ if (parameters.screenDepth)
+ chooseDepth(parameters.screenDepth,QVFbView::ARGBFormat);
+ config->touchScreen->setChecked(!parameters.hasMouseHover);
+ } else {
+ qWarning("%s", qPrintable(readError));
+ }
+ }
+}
+
+void QVFb::setGamma400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(config->rslider->value()/100.0*g,
+ config->gslider->value()/100.0*g,
+ config->bslider->value()/100.0*g);
+ updateGammaLabels();
+}
+
+void QVFb::setR400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(config->rslider->value()/100.0*g,
+ view->gammaGreen(),
+ view->gammaBlue());
+ updateGammaLabels();
+}
+
+void QVFb::setG400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(view->gammaRed(),
+ config->gslider->value()/100.0*g,
+ view->gammaBlue());
+ updateGammaLabels();
+}
+
+void QVFb::setB400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(view->gammaRed(),
+ view->gammaGreen(),
+ config->bslider->value()/100.0*g);
+ updateGammaLabels();
+}
+
+void QVFb::updateGammaLabels()
+{
+ config->rlabel->setText(QString::number(view->gammaRed(),'g',2));
+ config->glabel->setText(QString::number(view->gammaGreen(),'g',2));
+ config->blabel->setText(QString::number(view->gammaBlue(),'g',2));
+}
+
+QSize QVFb::sizeHint() const
+{
+ return QSize(int(view->displayWidth()*view->zoomH()),
+ int(menuBar()->height()+view->displayHeight()*view->zoomV()));
+}
+
+// =====================================================================
+
+AnimationSaveWidget::AnimationSaveWidget(QVFbAbstractView *v) :
+ QWidget((QWidget*)0,0),
+ view(v), recording(false), animation(0),
+ timerId(-1), progressTimerId(-1),
+ recOn(red_on_led_xpm), recOff(red_off_led_xpm),
+ imageNum(0)
+{
+ // Create the animation record UI dialog
+ QVBoxLayout *vlayout = new QVBoxLayout( this );
+
+ QWidget *hbox = new QWidget( this );
+ vlayout->addWidget(hbox);
+ QHBoxLayout *hlayout = new QHBoxLayout(hbox);
+ recBt = new QPushButton( tr("Record"), hbox );
+ hlayout->addWidget(recBt);
+ resetBt = new QPushButton( tr("Reset"), hbox );
+ hlayout->addWidget(resetBt);
+ saveBt = new QPushButton( tr("Save"), hbox );
+ hlayout->addWidget(saveBt);
+ recBt->setFixedWidth( 100 );
+ resetBt->setFixedWidth( 100 );
+ saveBt->setFixedWidth( 100 );
+ timeDpy = new QLabel( "00:00", hbox );
+ hlayout->addWidget(timeDpy);
+ recLED = new QLabel( hbox );
+ hlayout->addWidget(recLED);
+ recLED->setPixmap( recOff );
+ timeDpy->setMargin( 5 );
+ connect( recBt, SIGNAL(clicked()), this, SLOT(toggleRecord()) );
+ connect( resetBt, SIGNAL(clicked()), this, SLOT(reset()) );
+ connect( saveBt, SIGNAL(clicked()), this, SLOT(save()) );
+ elapsed = 0;
+ vlayout->setMargin( 5 );
+ vlayout->setSpacing( 5 );
+ haveMpeg = detectPpmtoMpegCommand();
+ mpegSave = new QCheckBox( tr("Save in MPEG format (requires netpbm package installed)"), this );
+ vlayout->addWidget(mpegSave);
+ mpegSave->setChecked( haveMpeg );
+ mpegSave->setEnabled( haveMpeg );
+ savingAsMpeg = haveMpeg;
+ QWidget *hbox2 = new QWidget( this );
+ vlayout->addWidget(hbox2);
+ QHBoxLayout *hlayout2 = new QHBoxLayout( hbox2 );
+ statusText = new QLabel( tr("Click record to begin recording."), hbox2 );
+ hlayout2->addWidget(statusText);
+ progressBar = new QProgressBar( hbox2 );
+ progressBar->setValue( 0 );
+ hlayout2->addWidget(progressBar);
+ progressBar->hide();
+}
+
+AnimationSaveWidget::~AnimationSaveWidget()
+{
+ // clean up
+ removeTemporaryFiles();
+ delete animation;
+}
+
+// returns true if we have ppmtompeg command, else returns false
+bool AnimationSaveWidget::detectPpmtoMpegCommand()
+{
+ // search the PATH for the ppmtompeg command to test we can record to mpeg
+ QStringList paths = QString(::getenv("PATH")).split(":");
+ for ( int i = 0; i < paths.count(); i++ )
+ if ( QFile::exists( paths[i] + "/" + "ppmtompeg" ) )
+ return true;
+ return false;
+}
+
+void AnimationSaveWidget::timerEvent( QTimerEvent *te )
+{
+ QString str;
+
+ // Recording timer
+ if ( te->timerId() == timerId ) {
+
+ // Add a frame to the animation
+ if ( savingAsMpeg && view )
+ view->image().save( str.sprintf("/tmp/qvfb_tmp_image_%04d.ppm", imageNum), "PPM");
+ else if ( animation && view )
+ animation->appendFrame(view->image());//QPoint(0,0));
+ imageNum++;
+
+ // Update the display of number of seconds that have been recorded.
+ int tmMsec = tm.elapsed();
+ timeDpy->setText( str.sprintf("%02d:%02d", tmMsec/60000, (tmMsec%60000)/1000) );
+ QObject::timerEvent( te );
+
+ // Make the recording LED blink
+ static int tick = 0;
+ static bool on = false;
+ if ( tick > 10 ) {
+ tick = 0;
+ if ( on )
+ recLED->setPixmap( recOff );
+ else
+ recLED->setPixmap( recOn );
+ on = !on;
+ }
+ tick++;
+ }
+
+ // Saving progress timer
+ if ( te->timerId() == progressTimerId ) {
+ // Parse output log file to work out the encoding progress.
+ QFile f("/tmp/qvfb_tmp_output.log");
+ f.open(QIODevice::ReadOnly);
+ int largestNum = 0;
+ bool done = false;
+ char buffer[1024];
+ while ( !f.atEnd() ) {
+ // example of the output log entries
+ // During each frame:
+ // "FRAME 764 (B): I BLOCKS: 0......
+ // When complete:
+ // "======FRAMES READ: 766"
+ f.readLine(buffer, 1024);
+ str = QString(buffer);
+ if ( str.left(6) == "FRAME " ) {
+ int num = str.mid(6, str.indexOf(QChar(' '), 6) - 6).toInt();
+ if ( num > largestNum )
+ largestNum = num;
+ } else if ( str.left(18) == "======FRAMES READ:" ) {
+ done = true;
+ }
+ }
+ f.close();
+
+ // Update the progress bar with the frame we are up to
+ progressBar->setValue( largestNum );
+
+ // Finished saving
+ if ( done ) {
+ progressBar->hide();
+ statusText->setText( tr("Finished saving."));
+ removeTemporaryFiles();
+ killTimer( progressTimerId );
+ progressTimerId = -1;
+ reset();
+ }
+ }
+}
+
+// Takes the saved ppm files and converts them to a mpeg file named filename
+void AnimationSaveWidget::convertToMpeg(QString filename)
+{
+ recLED->setPixmap( recOff );
+ killTimer( timerId );
+
+ progressBar->show();
+ progressBar->setRange( 0, imageNum );
+ progressBar->setValue( 0 );
+
+ // Build parameter file required by ppmtompeg
+ QFile file("/tmp/qvfb_tmp_ppmtompeg.params");
+ if ( file.open( QIODevice::WriteOnly ) ) {
+ QTextStream t( &file );
+ t << "PATTERN IBBPBBPBBPBBPBB\n";
+ t << "OUTPUT " << filename << "\n";
+ t << "INPUT_DIR /tmp\n";
+ t << "INPUT\n";
+ QString str;
+ str = str.sprintf("%04d", imageNum - 1);
+ t << "qvfb_tmp_image_*.ppm [0000-" << str << "]\n";
+ t << "END_INPUT\n";
+ t << "BASE_FILE_FORMAT PPM\n";
+ t << "INPUT_CONVERT *\n";
+ t << "GOP_SIZE 15\n";
+ t << "SLICES_PER_FRAME 1\n";
+ t << "PIXEL HALF\n";
+ t << "RANGE 5\n";
+ t << "PSEARCH_ALG LOGARITHMIC\n";
+ t << "BSEARCH_ALG SIMPLE\n";
+ t << "IQSCALE 1\n";
+ t << "PQSCALE 1\n";
+ t << "BQSCALE 1\n";
+ t << "REFERENCE_FRAME DECODED\n";
+ t << "ASPECT_RATIO 1\n";
+ t << "FRAME_RATE 24\n";
+ t << "BIT_RATE 64000\n"; // Quality
+ t << "BUFFER_SIZE 2048\n";
+ }
+ file.close();
+
+ // ### can't use QProcess, not in Qt 2.3
+ // ### but it's certainly in Qt 4! use it?
+ // Execute the ppmtompeg command as a seperate process to do the encoding
+ pid_t pid = ::fork();
+ if ( !pid ) {
+ // Child process
+ // redirect stdout to log file
+ freopen("/tmp/qvfb_tmp_output.log", "w", stdout);
+ // ppmtompeg tool is from the netpbm package
+ ::execlp("ppmtompeg", "ppmtompeg", "/tmp/qvfb_tmp_ppmtompeg.params", (void *)0);
+ exit(0);
+ }
+
+ // Update the saving progress bar every 200ms
+ progressTimerId = startTimer( 200 );
+}
+
+// Cleanup temporary files created during creating a mpeg file
+void AnimationSaveWidget::removeTemporaryFiles()
+{
+ QString str;
+ for ( int i = 0; i < imageNum; i++ )
+ QFile::remove( str.sprintf("/tmp/qvfb_tmp_image_%04d.ppm", i) );
+ QFile::remove("/tmp/qvfb_tmp_ppmtompeg.params");
+ QFile::remove("/tmp/qvfb_tmp_output.log");
+ imageNum = 0;
+}
+
+// toggles between recording and paused (usually when record button clicked)
+void AnimationSaveWidget::toggleRecord()
+{
+ if ( recording ) {
+ recLED->setPixmap( recOff );
+ recBt->setText( tr("Record") );
+ statusText->setText( tr("Paused. Click record to resume, or save if done."));
+ killTimer( timerId );
+ timerId = -1;
+ elapsed = tm.elapsed();
+ } else {
+ recLED->setPixmap( recOn );
+ recBt->setText( tr("Pause") );
+ statusText->setText( tr("Recording..."));
+ tm.start();
+ if ( elapsed == 0 ) {
+ savingAsMpeg = mpegSave->isChecked();
+ if ( !savingAsMpeg ) {
+ delete animation;
+ animation = new QAnimationWriter("/tmp/qvfb_tmp_animation.mng","MNG");
+ animation->setFrameRate(24);
+ if ( view )
+ animation->appendFrame(view->image());
+ }
+ }
+ tm = tm.addMSecs(-elapsed);
+ elapsed = 0;
+ timerId = startTimer(1000 / 24);
+ }
+ recording = !recording;
+}
+
+// Reset everything to initial state of not recording
+void AnimationSaveWidget::reset()
+{
+ if ( recording ) {
+ toggleRecord();
+ statusText->setText( tr("Click record to begin recording."));
+ removeTemporaryFiles();
+ }
+ progressBar->setValue( 0 );
+ timeDpy->setText( "00:00" );
+ elapsed = 0;
+ imageNum = 0;
+ delete animation;
+ animation = 0;
+}
+
+// Prompt for filename to save to and put animation in that file
+void AnimationSaveWidget::save()
+{
+ if ( recording )
+ toggleRecord(); // pauses
+ statusText->setText( tr("Saving... "));
+
+ QString filename;
+ if ( savingAsMpeg ) {
+ filename = QFileDialog::getSaveFileName(this, tr("Save animation..."), "", "*.mpg");
+ if ( !filename.isNull() )
+ convertToMpeg(filename);
+ } else {
+ filename = QFileDialog::getSaveFileName(this, tr("Save animation..."), "", "*.mng");
+ if (filename.isNull()) {
+ statusText->setText(tr("Save canceled."));
+ } else {
+ QFile::remove(filename);
+ bool success = QFile::rename(QLatin1String("/tmp/qvfb_tmp_animation.mng"),
+ filename);
+ if (success) {
+ statusText->setText(tr("Finished saving."));
+ reset();
+ } else {
+ statusText->setText(tr("Save failed!"));
+ }
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qvfb.moc"
diff --git a/tools/qvfb/qvfb.h b/tools/qvfb/qvfb.h
new file mode 100644
index 0000000000..90f2a33a2d
--- /dev/null
+++ b/tools/qvfb/qvfb.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVFB_H
+#define QVFB_H
+
+#include <QMainWindow>
+#include <QStringList>
+#include "qvfbview.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVFbAbstractView;
+class QVFbRateDialog;
+class QPopupMenu;
+class QMenuData;
+class QAction;
+class Config;
+class DeviceSkin;
+class QVFb;
+class QLabel;
+class QMenu;
+class QScrollArea;
+
+class Zoomer : public QWidget {
+ Q_OBJECT
+public:
+ Zoomer(QVFb* target);
+
+private slots:
+ void zoom(int);
+
+private:
+ QVFb *qvfb;
+ QLabel *label;
+};
+
+class QVFb: public QMainWindow
+{
+ Q_OBJECT
+public:
+ enum DisplayType { QWS, X11 };
+
+ QVFb( int display_id, int w, int h, int d, int r, const QString &skin, DisplayType displayType, QWidget *parent = 0, Qt::WindowFlags wflags = 0 );
+ ~QVFb();
+
+ void enableCursor( bool e );
+
+ QSize sizeHint() const;
+
+public slots:
+ void popupMenu();
+
+protected slots:
+ void saveImage();
+ void toggleAnimation();
+ void toggleCursor();
+ void changeRate();
+ void setRate(int);
+ void about();
+
+ void configure();
+ void skinConfigChosen(int i);
+ void chooseSize(const QSize& sz);
+ void chooseDepth(int depth, QVFbView::PixelFormat displayFormat);
+
+ void setZoom1();
+ void setZoom2();
+ void setZoom3();
+ void setZoom4();
+ void setZoomHalf();
+ void setZoom075();
+
+ void setZoom();
+
+ void setRot0();
+ void setRot90();
+ void setRot180();
+ void setRot270();
+
+public slots:
+ void setZoom(double);
+ void setRotation(QVFbView::Rotation);
+
+protected:
+ template <typename T>
+ void createMenu(T *menu);
+ QMenu* createFileMenu();
+ QMenu* createViewMenu();
+ QMenu* createHelpMenu();
+
+private:
+ void findSkins(const QString &currentSkin);
+ void init( int display_id, int w, int h, int d, int r, const QString& skin );
+ DeviceSkin *skin;
+ double skinscaleH,skinscaleV;
+ QVFbAbstractView *view;
+ QVFbAbstractView *secondaryView;
+ QVFbRateDialog *rateDlg;
+ QMenu *viewMenu;
+ QAction *cursorAction;
+ Config* config;
+ QStringList skinnames;
+ QStringList skinfiles;
+ int currentSkinIndex;
+ Zoomer *zoomer;
+ QScrollArea* scroller;
+ DisplayType displayType;
+
+ int refreshRate;
+private slots:
+ void setGamma400(int n);
+ void setR400(int n);
+ void setG400(int n);
+ void setB400(int n);
+ void updateGammaLabels();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/qvfb.pro b/tools/qvfb/qvfb.pro
new file mode 100644
index 0000000000..a3b55aba60
--- /dev/null
+++ b/tools/qvfb/qvfb.pro
@@ -0,0 +1,73 @@
+TEMPLATE = app
+CONFIG += qt warn_on uic
+TARGET = qvfb
+DESTDIR = ../../bin
+
+!win32:!embedded:!mac:CONFIG += x11
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
+
+DEPENDPATH = ../../include
+
+FORMS = config.ui
+HEADERS = qvfb.h \
+ qvfbview.h \
+ qvfbratedlg.h \
+ qanimationwriter.h \
+ gammaview.h \
+ qvfbprotocol.h \
+ qvfbshmem.h \
+ qvfbmmap.h \
+ qvfbhdr.h \
+ qlock_p.h \
+ qwssignalhandler_p.h
+
+SOURCES = qvfb.cpp \
+ qvfbview.cpp \
+ qvfbratedlg.cpp \
+ main.cpp \
+ qanimationwriter.cpp \
+ qvfbprotocol.cpp \
+ qvfbshmem.cpp \
+ qvfbmmap.cpp \
+ qlock.cpp \
+ qwssignalhandler.cpp
+
+include($$QT_SOURCE_TREE/tools/shared/deviceskin/deviceskin.pri)
+
+contains(QT_CONFIG, opengl) {
+ QT += opengl
+}
+
+contains(QT_CONFIG, system-png) {
+ LIBS += -lpng
+} else {
+ INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/libpng
+}
+contains(QT_CONFIG, system-zlib) {
+ LIBS += -lz
+} else {
+ INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/zlib
+}
+
+unix:x11 {
+ HEADERS += qvfbx11view.h \
+ x11keyfaker.h \
+ qtopiakeysym.h
+ SOURCES += qvfbx11view.cpp \
+ x11keyfaker.cpp
+ LIBS += -lXtst
+}
+
+RESOURCES += qvfb.qrc \
+ ClamshellPhone.qrc \
+ PDAPhone.qrc \
+ SmartPhone2.qrc \
+ SmartPhone.qrc \
+ SmartPhoneWithButtons.qrc \
+ TouchscreenPhone.qrc \
+ Trolltech-Keypad.qrc \
+ Trolltech-Touchscreen.qrc \
+ PortableMedia.qrc
+
diff --git a/tools/qvfb/qvfb.qrc b/tools/qvfb/qvfb.qrc
new file mode 100644
index 0000000000..27c39df7a4
--- /dev/null
+++ b/tools/qvfb/qvfb.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/res">
+ <file>images/logo.png</file>
+ <file>images/logo-nt.png</file>
+</qresource>
+</RCC>
+
diff --git a/tools/qvfb/qvfbmmap.cpp b/tools/qvfb/qvfbmmap.cpp
new file mode 100644
index 0000000000..d8230f786b
--- /dev/null
+++ b/tools/qvfb/qvfbmmap.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvfbmmap.h"
+#include "qvfbhdr.h"
+
+#include <QTimer>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <sys/sem.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+QMMapViewProtocol::QMMapViewProtocol(int displayid, const QSize &s,
+ int d, QObject *parent)
+ : QVFbViewProtocol(displayid, parent), hdr(0), dataCache(0), windowId(0)
+{
+ switch (d) {
+ case 1:
+ case 4:
+ case 8:
+ case 12:
+ case 15:
+ case 16:
+ case 18:
+ case 24:
+ case 32:
+ break;
+ default:
+ qFatal("Unsupported bit depth %d\n", d);
+ }
+
+ fileName = QString("/tmp/.qtvfb_map-%1").arg(displayid);
+
+ int w = s.width();
+ int h = s.height();
+
+
+ kh = new QVFbKeyPipeProtocol(displayid);
+ mh = new QVFbMouseLinuxTP(displayid);
+
+ int bpl;
+ if (d < 8)
+ bpl = (w * d + 7) / 8;
+ else
+ bpl = w * ((d + 7) / 8);
+
+ displaySize = bpl * h;
+
+ unsigned char *data;
+ uint data_offset_value = sizeof(QVFbHeader);
+ const int page_size = getpagesize();
+ if (data_offset_value % page_size)
+ data_offset_value += page_size - (data_offset_value % page_size);
+
+ dataSize = bpl * h + data_offset_value;
+
+ unlink(fileName.toLocal8Bit().data());
+ fd = ::open( fileName.toLocal8Bit().data(), O_CREAT|O_RDWR, 0666 );
+ ::lseek(fd, dataSize, SEEK_SET);
+ ::write(fd, "\0", 1);
+ if (fd < 0) {
+ data = (unsigned char *)-1;
+ } else {
+ // might need to do something about size?
+ data = (unsigned char *)mmap(NULL, dataSize, PROT_WRITE | PROT_READ,
+ MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED)
+ data = (unsigned char *)-1;
+ }
+
+ if ( (long)data == -1 ){
+ delete kh;
+ delete mh;
+ qFatal( "Cannot attach to mapped file %s", fileName.toLocal8Bit().data());
+ }
+ dataCache = (unsigned char *)malloc(displaySize);
+ memset(dataCache, 0, displaySize);
+ memset(data+sizeof(QVFbHeader), 0, displaySize);
+
+ hdr = (QVFbHeader *)data;
+ hdr->width = w;
+ hdr->height = h;
+ hdr->depth = d;
+ hdr->linestep = bpl;
+ hdr->numcols = 0;
+ hdr->dataoffset = data_offset_value;
+ hdr->update = QRect();
+ hdr->brightness = 255;
+ hdr->windowId = 0;
+
+ mRefreshTimer = new QTimer(this);
+ connect(mRefreshTimer, SIGNAL(timeout()), this, SLOT(flushChanges()));
+}
+
+QMMapViewProtocol::~QMMapViewProtocol()
+{
+ munmap((char *)hdr, dataSize);
+ ::close(fd);
+ unlink(fileName.toLocal8Bit().constData());
+ free(dataCache);
+ delete kh;
+ delete mh;
+}
+
+int QMMapViewProtocol::brightness() const
+{
+ return hdr->brightness;
+}
+
+int QMMapViewProtocol::width() const
+{
+ return hdr->width;
+}
+
+int QMMapViewProtocol::height() const
+{
+ return hdr->height;
+}
+
+int QMMapViewProtocol::depth() const
+{
+ return hdr->depth;
+}
+
+int QMMapViewProtocol::linestep() const
+{
+ return hdr->linestep;
+}
+
+int QMMapViewProtocol::numcols() const
+{
+ return hdr->numcols;
+}
+
+QVector<QRgb> QMMapViewProtocol::clut() const
+{
+ QVector<QRgb> vector(hdr->numcols);
+ for (int i=0; i < hdr->numcols; ++i)
+ vector[i] = hdr->clut[i];
+
+ return vector;
+}
+
+unsigned char *QMMapViewProtocol::data() const
+{
+ return dataCache;
+ //return ((unsigned char *)hdr)+hdr->dataoffset;
+}
+
+void QMMapViewProtocol::flushChanges()
+{
+ // based of dirty rect, copy changes from hdr to hdrcopy
+ memcpy(dataCache, ((char *)hdr) + hdr->dataoffset, displaySize);
+ emit displayDataChanged(QRect(0, 0, width(), height()));
+}
+
+void QMMapViewProtocol::setRate(int interval)
+{
+ if (interval > 0)
+ return mRefreshTimer->start(1000/interval);
+ else
+ mRefreshTimer->stop();
+}
+
+int QMMapViewProtocol::rate() const
+{
+ int i = mRefreshTimer->interval();
+ if (i > 0)
+ return 1000/i;
+ else
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/qvfbmmap.h b/tools/qvfb/qvfbmmap.h
new file mode 100644
index 0000000000..5b580ac8b4
--- /dev/null
+++ b/tools/qvfb/qvfbmmap.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QVFB_MMAP_PROTOCOL_H
+#define QVFB_MMAP_PROTOCOL_H
+
+#include "qvfbprotocol.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVFbHeader;
+class QTimer;
+class QMMapViewProtocol : public QVFbViewProtocol
+{
+ Q_OBJECT
+public:
+ QMMapViewProtocol(int display_id, const QSize &size, int depth, QObject *parent = 0);
+ ~QMMapViewProtocol();
+
+ int width() const;
+ int height() const;
+ int depth() const;
+ int linestep() const;
+ int numcols() const;
+ QVector<QRgb> clut() const;
+ unsigned char *data() const;
+ int brightness() const;
+
+ void setRate(int);
+ int rate() const;
+
+protected slots:
+ void flushChanges();
+
+protected:
+ QVFbKeyProtocol *keyHandler() const { return kh; }
+ QVFbMouseProtocol *mouseHandler() const { return mh; }
+
+private:
+ QVFbKeyPipeProtocol *kh;
+ QVFbMouseLinuxTP *mh;
+ QVFbHeader *hdr;
+ QString fileName;
+ int fd;
+ size_t dataSize;
+ size_t displaySize;
+ unsigned char *dataCache;
+ QTimer *mRefreshTimer;
+ WId windowId;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/qvfbprotocol.cpp b/tools/qvfb/qvfbprotocol.cpp
new file mode 100644
index 0000000000..08d2973d3b
--- /dev/null
+++ b/tools/qvfb/qvfbprotocol.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvfbprotocol.h"
+#include "qvfbhdr.h"
+
+#include <QDebug>
+#include <QTimer>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <math.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef Q_OS_UNIX
+#include <unistd.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QVFbViewProtocol::QVFbViewProtocol(int display_id, QObject *parent) :
+ QObject(parent), mDisplayId(display_id) { }
+
+QVFbViewProtocol::~QVFbViewProtocol() {}
+
+void QVFbViewProtocol::flushChanges() {}
+
+void QVFbViewProtocol::sendKeyboardData(QString unicode, int keycode,
+ int modifiers, bool press, bool repeat)
+{
+ if (keyHandler())
+ keyHandler()->sendKeyboardData(unicode, keycode, modifiers, press, repeat);
+}
+
+void QVFbViewProtocol::sendMouseData(const QPoint &pos, int buttons, int wheel)
+{
+ if (mouseHandler())
+ mouseHandler()->sendMouseData(pos, buttons, wheel);
+}
+
+static int openPipe(const char *fileName)
+{
+ unlink(fileName);
+
+ mkfifo(fileName, 0666);
+ int fd = ::open(fileName, O_RDWR | O_NDELAY);
+ return fd;
+}
+
+QVFbKeyPipeProtocol::QVFbKeyPipeProtocol(int display_id)
+ : QVFbKeyProtocol(display_id)
+{
+ fileName = QString(QT_VFB_KEYBOARD_PIPE).arg(display_id);
+ fd = openPipe(fileName.toLocal8Bit().constData());
+
+ if (fd == -1)
+ qFatal("Cannot open keyboard pipe %s", fileName.toLocal8Bit().data());
+}
+
+QVFbKeyPipeProtocol::~QVFbKeyPipeProtocol()
+{
+ sendKeyboardData(0, 0, 0, true, false); // magic die key
+ ::close(fd);
+ unlink(fileName.toLocal8Bit().constData());
+}
+
+void QVFbKeyPipeProtocol::sendKeyboardData(QString unicode, int keycode,
+ int modifiers, bool press, bool repeat)
+{
+ QVFbKeyData kd;
+ kd.unicode = unicode[0].unicode();
+ kd.keycode = keycode;
+ kd.modifiers = static_cast<Qt::KeyboardModifier>(modifiers);
+ kd.press = press;
+ kd.repeat = repeat;
+ write(fd, &kd, sizeof(QVFbKeyData));
+}
+
+QVFbMousePipe::QVFbMousePipe(int display_id)
+ : QVFbMouseProtocol(display_id)
+{
+ fileName = QString(QT_VFB_MOUSE_PIPE).arg(display_id);
+ fd = openPipe(fileName.toLocal8Bit().constData());
+
+ if (fd == -1)
+ qFatal("Cannot open mouse pipe %s", fileName.toLocal8Bit().data());
+}
+
+QVFbMousePipe::~QVFbMousePipe()
+{
+ ::close(fd);
+ unlink(fileName.toLocal8Bit().constData());
+}
+
+
+void QVFbMousePipe::sendMouseData(const QPoint &pos, int buttons, int wheel)
+{
+ write(fd, &pos, sizeof(QPoint));
+ write(fd, &buttons, sizeof(int));
+ write(fd, &wheel, sizeof(int));
+}
+
+QVFbMouseLinuxTP::QVFbMouseLinuxTP(int display_id)
+ : QObject(), QVFbMousePipe(display_id), lastPos(-1,-1)
+{
+ /* the timer is needed because a real touch screen send data as long as
+ there is pressure. And the linux tp driver will filter, requiring
+ a minimum of 5 samples before it even registers a press.
+ */
+ repeater = new QTimer(this);
+ connect(repeater, SIGNAL(timeout()), this, SLOT(repeatLastPress()));
+}
+
+QVFbMouseLinuxTP::~QVFbMouseLinuxTP()
+{
+}
+
+
+void QVFbMouseLinuxTP::sendMouseData(const QPoint &pos, int buttons, int)
+{
+ if (buttons & Qt::LeftButton) {
+ // press
+ repeater->start(5);
+ writeToPipe(pos, 1);
+ lastPos = pos;
+ } else {
+ // release
+ if (lastPos == QPoint(-1,-1))
+ return; /* only send one release */
+ repeater->stop();
+ writeToPipe(pos, 0);
+ lastPos = QPoint(-1,-1);
+ }
+}
+
+void QVFbMouseLinuxTP::writeToPipe(const QPoint &pos, ushort pressure)
+{
+ ushort v;
+ write(fd, &pressure, sizeof(ushort));
+ v = pos.x();
+ write(fd, &v, sizeof(ushort));
+ v = pos.y();
+ write(fd, &v, sizeof(ushort));
+ v = 1; // pad
+ write(fd, &v, sizeof(ushort));
+}
+
+void QVFbMouseLinuxTP::repeatLastPress()
+{
+ writeToPipe(lastPos, 1);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/qvfbprotocol.h b/tools/qvfb/qvfbprotocol.h
new file mode 100644
index 0000000000..e7b6f63495
--- /dev/null
+++ b/tools/qvfb/qvfbprotocol.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QVFBPROTOCOL_H
+#define QVFBPROTOCOL_H
+
+#include <QImage>
+#include <QVector>
+#include <QColor>
+
+QT_BEGIN_NAMESPACE
+
+class QVFbKeyProtocol;
+class QVFbMouseProtocol;
+class QVFbViewProtocol : public QObject
+{
+ Q_OBJECT
+public:
+ QVFbViewProtocol(int display_id, QObject *parent = 0);
+
+ virtual ~QVFbViewProtocol();
+
+ int id() const { return mDisplayId; }
+
+ void sendKeyboardData(QString unicode, int keycode,
+ int modifiers, bool press, bool repeat);
+ void sendMouseData(const QPoint &pos, int buttons, int wheel);
+
+ virtual int width() const = 0;
+ virtual int height() const = 0;
+ virtual int depth() const = 0;
+ virtual int linestep() const = 0;
+ virtual int numcols() const = 0;
+ virtual QVector<QRgb> clut() const = 0;
+ virtual unsigned char *data() const = 0;
+ virtual int brightness() const = 0;
+
+ virtual void setRate(int) {}
+public slots:
+ virtual void flushChanges();
+
+signals:
+ void displayDataChanged(const QRect &);
+ void displayEmbedRequested(WId windowId);
+
+protected:
+ virtual QVFbKeyProtocol *keyHandler() const = 0;
+ virtual QVFbMouseProtocol *mouseHandler() const = 0;
+
+private:
+ int mDisplayId;
+};
+
+class QVFbKeyProtocol
+{
+public:
+ QVFbKeyProtocol(int display_id) : mDisplayId(display_id) {}
+ virtual ~QVFbKeyProtocol() {}
+
+ int id() const { return mDisplayId; }
+
+ virtual void sendKeyboardData(QString unicode, int keycode,
+ int modifiers, bool press, bool repeat) = 0;
+
+private:
+ int mDisplayId;
+};
+
+class QVFbMouseProtocol
+{
+public:
+ QVFbMouseProtocol(int display_id) : mDisplayId(display_id) {}
+ virtual ~QVFbMouseProtocol() {}
+
+ int id() const { return mDisplayId; }
+
+ virtual void sendMouseData(const QPoint &pos, int buttons, int wheel) = 0;
+
+private:
+ int mDisplayId;
+};
+
+/* since there is very little variation in input protocols defaults are
+ provided */
+
+class QVFbKeyPipeProtocol : public QVFbKeyProtocol
+{
+public:
+ QVFbKeyPipeProtocol(int display_id);
+ ~QVFbKeyPipeProtocol();
+
+ void sendKeyboardData(QString unicode, int keycode,
+ int modifiers, bool press, bool repeat);
+
+ QString pipeName() const { return fileName; }
+private:
+ int fd;
+ QString fileName;
+};
+
+class QVFbMousePipe: public QVFbMouseProtocol
+{
+public:
+ QVFbMousePipe(int display_id);
+ ~QVFbMousePipe();
+
+ void sendMouseData(const QPoint &pos, int buttons, int wheel);
+
+ QString pipeName() const { return fileName; }
+protected:
+ int fd;
+ QString fileName;
+};
+
+class QTimer;
+class QVFbMouseLinuxTP : public QObject, public QVFbMousePipe
+{
+ Q_OBJECT
+public:
+ QVFbMouseLinuxTP(int display_id);
+ ~QVFbMouseLinuxTP();
+
+ void sendMouseData(const QPoint &pos, int buttons, int wheel);
+
+protected slots:
+ void repeatLastPress();
+
+protected:
+ void writeToPipe(const QPoint &pos, ushort pressure);
+ QPoint lastPos;
+ QTimer *repeater;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/qvfbratedlg.cpp b/tools/qvfb/qvfbratedlg.cpp
new file mode 100644
index 0000000000..594e3f143e
--- /dev/null
+++ b/tools/qvfb/qvfbratedlg.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvfbratedlg.h"
+#include <QLayout>
+#include <QLabel>
+#include <qslider.h>
+#include <QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+QVFbRateDialog::QVFbRateDialog(int rate, QWidget *parent)
+ : QDialog(parent)
+{
+ oldRate = rate;
+
+ QVBoxLayout *tl = new QVBoxLayout(this);
+ tl->setMargin(5);
+
+ QLabel *label = new QLabel("Target frame rate:", this);
+ tl->addWidget(label);
+
+ QHBoxLayout *hl = new QHBoxLayout();
+ tl->addItem(hl);
+ rateSlider = new QSlider(Qt::Horizontal);
+ rateSlider->setMinimum(1);
+ rateSlider->setMaximum(100);
+ rateSlider->setPageStep(10);
+ rateSlider->setValue(rate);
+ hl->addWidget(rateSlider);
+ connect(rateSlider, SIGNAL(valueChanged(int)), this, SLOT(rateChanged(int)));
+ rateLabel = new QLabel(QString("%1fps").arg(rate), this);
+ hl->addWidget(rateLabel);
+
+ hl = new QHBoxLayout();
+ tl->addItem(hl);
+ QPushButton *pb = new QPushButton("OK", this);
+ connect(pb, SIGNAL(clicked()), this, SLOT(ok()));
+ hl->addWidget(pb);
+ pb = new QPushButton("Cancel", this);
+ connect(pb, SIGNAL(clicked()), this, SLOT(cancel()));
+ hl->addWidget(pb);
+}
+
+void QVFbRateDialog::rateChanged(int r)
+{
+ if (rateSlider->value() != r)
+ rateSlider->setValue(r);
+ rateLabel->setText(QString("%1fps").arg(r));
+ emit updateRate(r);
+}
+
+void QVFbRateDialog::cancel()
+{
+ rateChanged(oldRate);
+ reject();
+}
+
+void QVFbRateDialog::ok()
+{
+ oldRate = rateSlider->value();
+ accept();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/qvfbratedlg.h b/tools/qvfb/qvfbratedlg.h
new file mode 100644
index 0000000000..1611c764ca
--- /dev/null
+++ b/tools/qvfb/qvfbratedlg.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVFBRATEDLG_H
+#define QVFBRATEDLG_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QLabel;
+class QSlider;
+
+class QVFbRateDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QVFbRateDialog(int value, QWidget *parent = 0);
+
+signals:
+ void updateRate(int r);
+
+protected slots:
+ void rateChanged(int r);
+ void cancel();
+ void ok();
+
+private:
+ QLabel *rateLabel;
+ QSlider *rateSlider;
+ int oldRate;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/qvfbshmem.cpp b/tools/qvfb/qvfbshmem.cpp
new file mode 100644
index 0000000000..d07cd0fa8e
--- /dev/null
+++ b/tools/qvfb/qvfbshmem.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlock_p.h"
+
+#include "qvfbshmem.h"
+#include "qvfbhdr.h"
+
+#define QTE_PIPE "QtEmbedded-%1"
+
+#include <QFile>
+#include <QTimer>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <sys/sem.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_WS_QWS
+#error qvfb must be compiled with the Qt for X11 package
+#endif
+
+// Get the name of the directory where Qt for Embedded Linux temporary data should
+// live.
+static QString qws_dataDir(int qws_display_id)
+{
+ QByteArray dataDir = QString("/tmp/qtembedded-%1").arg(qws_display_id).toLocal8Bit();
+ if (mkdir(dataDir, 0700)) {
+ if (errno != EEXIST) {
+ qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData());
+ }
+ }
+
+ struct stat buf;
+ if (lstat(dataDir, &buf))
+ qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData());
+
+ if (!S_ISDIR(buf.st_mode))
+ qFatal("%s is not a directory", dataDir.constData());
+ if (buf.st_uid != getuid())
+ qFatal("Qt for Embedded Linux data directory is not owned by user %uh", getuid());
+
+ if ((buf.st_mode & 0677) != 0600)
+ qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData());
+ dataDir += "/";
+
+ return QString(dataDir);
+}
+
+
+static QString displayPipe;
+static QString displayPiped;
+class DisplayLock
+{
+public:
+ DisplayLock() : qlock(0) {
+ if (QFile::exists(displayPiped)) {
+ qlock = new QLock(displayPipe, 'd', false);
+ qlock->lock(QLock::Read);
+ }
+ }
+ ~DisplayLock() {
+ if (qlock) {
+ qlock->unlock();
+ delete qlock;
+ qlock = 0;
+ }
+ }
+private:
+ QLock *qlock;
+};
+
+QShMemViewProtocol::QShMemViewProtocol(int displayid, const QSize &s,
+ int d, QObject *parent)
+ : QVFbViewProtocol(displayid, parent), hdr(0), dataCache(0), lockId(-1),
+ windowId(0)
+{
+ int w = s.width();
+ int h = s.height();
+
+ QString username = "unknown";
+ const char *logname = getenv("LOGNAME");
+ if ( logname )
+ username = logname;
+
+ QString oldPipe = "/tmp/qtembedded-" + username + "/" + QString(QTE_PIPE).arg(displayid);
+ int oldPipeSemkey = ftok(oldPipe.toLatin1().constData(), 'd');
+ if (oldPipeSemkey != -1) {
+ int oldPipeLockId = semget(oldPipeSemkey, 0, 0);
+ if (oldPipeLockId >= 0){
+ sembuf sops;
+ sops.sem_num = 0;
+ sops.sem_op = 1;
+ sops.sem_flg = SEM_UNDO;
+ int rv;
+ do {
+ rv = semop(lockId,&sops,1);
+ } while (rv == -1 && errno == EINTR);
+
+ perror("QShMemViewProtocol::QShMemViewProtocol");
+ qFatal("Cannot create lock file as an old version of QVFb has "
+ "opened %s. Close other QVFb and try again",
+ oldPipe.toLatin1().constData());
+ }
+ }
+
+ kh = new QVFbKeyPipeProtocol(displayid);
+ /* should really depend on receiving qt version, but how can
+ one tell? */
+ mh = new QVFbMousePipe(displayid);
+
+ QString mousePipe = mh->pipeName();
+
+ key_t key = ftok(mousePipe.toLatin1().constData(), 'b');
+
+ int bpl;
+ if (d < 8)
+ bpl = (w * d + 7) / 8;
+ else
+ bpl = w * ((d + 7) / 8);
+
+ displaySize = bpl * h;
+
+ unsigned char *data;
+ uint data_offset_value = sizeof(QVFbHeader);
+
+ int dataSize = bpl * h + data_offset_value;
+ shmId = shmget(key, dataSize, IPC_CREAT | 0666);
+ if (shmId != -1)
+ data = (unsigned char *)shmat(shmId, 0, 0);
+ else {
+ struct shmid_ds shm;
+ shmctl(shmId, IPC_RMID, &shm);
+ shmId = shmget(key, dataSize, IPC_CREAT | 0666);
+ if (shmId == -1) {
+ perror("QShMemViewProtocol::QShMemViewProtocol");
+ qFatal("Cannot get shared memory 0x%08x", key);
+ }
+ data = (unsigned char *)shmat(shmId, 0, 0);
+ }
+
+ if ((long)data == -1) {
+ delete kh;
+ delete mh;
+ perror("QShMemViewProtocol::QShMemViewProtocol");
+ qFatal("Cannot attach to shared memory %d",shmId);
+ }
+ dataCache = (unsigned char *)malloc(displaySize);
+ memset(dataCache, 0, displaySize);
+ memset(data+sizeof(QVFbHeader), 0, displaySize);
+
+ hdr = (QVFbHeader *)data;
+ hdr->width = w;
+ hdr->height = h;
+ hdr->depth = d;
+ hdr->linestep = bpl;
+ hdr->dataoffset = data_offset_value;
+ hdr->update = QRect();
+ hdr->dirty = 0;
+ hdr->numcols = 0;
+ hdr->viewerVersion = QT_VERSION;
+ hdr->brightness = 255;
+ hdr->windowId = 0;
+
+ displayPipe = qws_dataDir(displayid) + QString(QTE_PIPE).arg(displayid);
+
+ displayPiped = displayPipe + 'd';
+
+
+ mRefreshTimer = new QTimer(this);
+ connect(mRefreshTimer, SIGNAL(timeout()), this, SLOT(flushChanges()));
+}
+
+QShMemViewProtocol::~QShMemViewProtocol()
+{
+ struct shmid_ds shm;
+ shmdt( (char*)hdr );
+ shmctl( shmId, IPC_RMID, &shm );
+ free(dataCache);
+ delete kh;
+ delete mh;
+}
+
+int QShMemViewProtocol::width() const
+{
+ return hdr->width;
+}
+
+int QShMemViewProtocol::height() const
+{
+ return hdr->height;
+}
+
+int QShMemViewProtocol::depth() const
+{
+ return hdr->depth;
+}
+
+int QShMemViewProtocol::linestep() const
+{
+ return hdr->linestep;
+}
+
+int QShMemViewProtocol::numcols() const
+{
+ return hdr->numcols;
+}
+
+QVector<QRgb> QShMemViewProtocol::clut() const
+{
+ QVector<QRgb> vector(hdr->numcols);
+ for (int i=0; i < hdr->numcols; ++i)
+ vector[i]=hdr->clut[i];
+
+ return vector;
+}
+
+unsigned char *QShMemViewProtocol::data() const
+{
+ return dataCache;
+ //return ((unsigned char *)hdr)+hdr->dataoffset;
+}
+
+int QShMemViewProtocol::brightness() const
+{
+ return hdr->brightness;
+}
+
+void QShMemViewProtocol::flushChanges()
+{
+ QRect r;
+ if (hdr->dirty) {
+ DisplayLock();
+
+ hdr->dirty = false;
+ r = hdr->update;
+ hdr->update = QRect();
+
+ if (hdr->windowId != windowId) {
+ windowId = hdr->windowId;
+ emit displayEmbedRequested(hdr->windowId);
+ } else if (!hdr->windowId) {
+ // copy the memory area, for now, be inefficient.
+ memcpy(dataCache, ((char *)hdr) + hdr->dataoffset, displaySize);
+ }
+ }
+ emit displayDataChanged(r);
+}
+
+void QShMemViewProtocol::setRate(int interval)
+{
+ if (interval > 0)
+ return mRefreshTimer->start(1000/interval);
+ else
+ mRefreshTimer->stop();
+}
+
+int QShMemViewProtocol::rate() const
+{
+ int i = mRefreshTimer->interval();
+ if (i > 0)
+ return 1000/i;
+ else
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/qvfbshmem.h b/tools/qvfb/qvfbshmem.h
new file mode 100644
index 0000000000..166ff07f7b
--- /dev/null
+++ b/tools/qvfb/qvfbshmem.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QVFB_SHM_PROTOCOL_H
+#define QVFB_SHM_PROTOCOL_H
+
+#include "qvfbprotocol.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVFbHeader;
+class QTimer;
+class QShMemViewProtocol : public QVFbViewProtocol
+{
+ Q_OBJECT
+public:
+ QShMemViewProtocol(int display_id, const QSize &size, int depth, QObject *parent = 0);
+ ~QShMemViewProtocol();
+
+ int width() const;
+ int height() const;
+ int depth() const;
+ int linestep() const;
+ int numcols() const;
+ QVector<QRgb> clut() const;
+ unsigned char *data() const;
+ int brightness() const;
+
+ void setRate(int);
+ int rate() const;
+
+protected slots:
+ void flushChanges();
+
+protected:
+ QVFbKeyProtocol *keyHandler() const { return kh; }
+ QVFbMouseProtocol *mouseHandler() const { return mh; }
+
+private:
+ QVFbKeyPipeProtocol *kh;
+ QVFbMousePipe *mh;
+ QVFbHeader *hdr;
+ size_t displaySize;
+ unsigned char *dataCache;
+ int lockId;
+ int shmId;
+ QTimer *mRefreshTimer;
+ WId windowId;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/qvfbview.cpp b/tools/qvfb/qvfbview.cpp
new file mode 100644
index 0000000000..53a5360e52
--- /dev/null
+++ b/tools/qvfb/qvfbview.cpp
@@ -0,0 +1,824 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvfbview.h"
+#include "qvfbshmem.h"
+#include "qvfbmmap.h"
+
+#include "qanimationwriter.h"
+#include <QApplication>
+#include <QPainter>
+#include <QImage>
+#include <QBitmap>
+#include <QMatrix>
+#include <QPaintEvent>
+#include <QScrollArea>
+#include <QFile>
+#include <QDebug>
+
+#ifdef Q_WS_X11
+#include <QX11EmbedContainer>
+#include <QHBoxLayout>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <sys/sem.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+extern int qvfb_protocol;
+
+QVFbAbstractView::QVFbAbstractView( QWidget *parent )
+#ifdef QVFB_USE_GLWIDGET
+ : QGLWidget( parent )
+#else
+ : QWidget( parent )
+#endif
+{
+}
+
+QVFbAbstractView::~QVFbAbstractView()
+{
+}
+
+QVFbView::QVFbView(int id, int w, int h, int d, Rotation r, QWidget *parent)
+ : QVFbAbstractView(parent),
+ viewdepth(d), viewFormat(DefaultFormat), rsh(0), gsh(0), bsh(0), rmax(15), gmax(15), bmax(15),
+ contentsWidth(w), contentsHeight(h), gred(1.0), ggreen(1.0), gblue(1.0),
+ gammatable(0), refreshRate(30), animation(0),
+ hzm(0.0), vzm(0.0), mView(0),
+ emulateTouchscreen(false), emulateLcdScreen(false), rotation(r)
+#ifdef Q_WS_X11
+ , embedContainer(0)
+#endif
+{
+ switch(qvfb_protocol) {
+ default:
+ case 0:
+ mView = new QShMemViewProtocol(id, QSize(w, h), d, this);
+ break;
+ case 1:
+ mView = new QMMapViewProtocol(id, QSize(w, h), d, this);
+ break;
+ }
+
+ connect(mView, SIGNAL(displayDataChanged(const QRect &)),
+ SLOT(refreshDisplay(const QRect &)));
+#ifdef Q_WS_X11
+ connect(mView, SIGNAL(displayEmbedRequested(WId)),
+ this, SLOT(embedDisplay(WId)));
+#endif
+
+ setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat);
+ setMouseTracking(true);
+ setFocusPolicy(Qt::StrongFocus);
+ setAttribute(Qt::WA_NoSystemBackground);
+
+ setZoom(1.0,1.0);
+
+ setGamma(1.0,1.0,1.0);
+ mView->setRate(30);
+}
+
+QVFbView::~QVFbView()
+{
+ stopAnimation();
+ sendKeyboardData(0, 0, 0, true, false); // magic die key
+#ifdef Q_WS_X11
+ delete embedContainer;
+#endif
+}
+
+QSize QVFbView::sizeHint() const
+{
+ return QSize(contentsWidth, contentsHeight);
+}
+
+void QVFbView::setRate(int i)
+{
+ mView->setRate(i);
+}
+
+void QVFbView::setGamma(double gr, double gg, double gb)
+{
+ gred = gr; ggreen = gg; gblue = gb;
+
+ switch (viewdepth) {
+ case 12:
+ rsh = 12;
+ gsh = 7;
+ bsh = 1;
+ rmax = 15;
+ gmax = 15;
+ bmax = 15;
+ break;
+ case 15:
+ rsh = 10;
+ gsh = 5;
+ bsh = 0;
+ rmax = 31;
+ gmax = 31;
+ bmax = 31;
+ break;
+ case 16:
+ rsh = 11;
+ gsh = 5;
+ bsh = 0;
+ rmax = 31;
+ gmax = 63;
+ bmax = 31;
+ break;
+ case 18:
+ rsh = 12;
+ gsh = 6;
+ bsh = 0;
+ rmax = 63;
+ gmax = 63;
+ bmax = 63;
+ break;
+ case 24:
+ case 32:
+ rsh = 16;
+ gsh = 8;
+ bsh = 0;
+ rmax = 255;
+ gmax = 255;
+ bmax = 255;
+ }
+ int mm = qMax(rmax,qMax(gmax,bmax))+1;
+ if (gammatable)
+ delete [] gammatable;
+ gammatable = new QRgb[mm];
+ for (int i=0; i<mm; i++) {
+ int r = int(pow(i,gr)*255/rmax);
+ int g = int(pow(i,gg)*255/gmax);
+ int b = int(pow(i,gb)*255/bmax);
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ gammatable[i] = qRgb(r,g,b);
+//qDebug("%d: %d,%d,%d",i,r,g,b);
+ }
+
+ mView->flushChanges();
+}
+
+void QVFbView::getGamma(int i, QRgb& rgb)
+{
+ if (i > 255) i = 255;
+ if (i < 0) i = 0;
+ rgb = qRgb(qRed(gammatable[i*rmax/255]),
+ qGreen(gammatable[i*rmax/255]),
+ qBlue(gammatable[i*rmax/255]));
+}
+
+int QVFbView::displayId() const
+{
+ return mView->id();
+}
+
+int QVFbView::displayWidth() const
+{
+ return mView->width();
+}
+
+int QVFbView::displayHeight() const
+{
+ return mView->height();
+}
+
+int QVFbView::displayDepth() const
+{
+ return viewdepth;
+}
+
+QVFbView::PixelFormat QVFbView::displayFormat() const
+{
+ return viewFormat;
+}
+
+QVFbView::Rotation QVFbView::displayRotation() const
+{
+ return rotation;
+}
+
+void QVFbView::setZoom(double hz, double vz)
+{
+ if (hzm != hz || vzm != vz) {
+ hzm = hz;
+ vzm = vz;
+ mView->flushChanges();
+
+ contentsWidth = int(displayWidth()*hz);
+ contentsHeight = int(displayHeight()*vz);
+ if (rotation & 1)
+ qSwap(contentsWidth,contentsHeight);
+ resize(contentsWidth, contentsHeight);
+
+ if (isVisible()) {
+ updateGeometry();
+ qApp->sendPostedEvents();
+ topLevelWidget()->adjustSize();
+ update();
+ }
+ }
+}
+
+void QVFbView::setRotation(QVFbView::Rotation r)
+{
+ rotation = r;
+ // Force update...
+ double ohzm = hzm;
+ hzm=0.0;
+ setZoom(ohzm,vzm);
+}
+
+static QRect mapToDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation)
+{
+ int x1 = r.x();
+ int y1 = r.y();
+ int x2 = r.right();
+ int y2 = r.bottom();
+ int w = s.width();
+ int h = s.height();
+ switch (rotation) {
+ case QVFbView::Rot90:
+ return QRect(
+ QPoint(y1, w - x1),
+ QPoint(y2, w - x2)).normalized();
+ case QVFbView::Rot180:
+ return QRect(
+ QPoint(w - x1, h - y1),
+ QPoint(w - x2, h - y2)).normalized();
+ case QVFbView::Rot270:
+ return QRect(
+ QPoint(h - y1, x1),
+ QPoint(h - y2, x2)).normalized();
+ default:
+ break;
+ }
+ return r;
+}
+
+static QRect mapFromDevice(const QRect &r, const QSize &s, QVFbView::Rotation rotation)
+{
+ return mapToDevice(r,s,QVFbView::Rotation(4-(int)rotation));
+}
+
+void QVFbView::sendMouseData(const QPoint &pos, int buttons, int wheel)
+{
+ QPoint p = mapToDevice(QRect(pos,QSize(1,1)), QSize(int(width()/hzm), int(height()/vzm)), rotation).topLeft();
+ mView->sendMouseData(p, buttons, wheel);
+}
+
+void QVFbView::sendKeyboardData(QString unicode, int keycode, int modifiers,
+ bool press, bool repeat)
+{
+ mView->sendKeyboardData(unicode, keycode, modifiers, press, repeat);
+}
+
+void QVFbView::refreshDisplay(const QRect &r)
+{
+ if (animation) {
+ if (r.isEmpty()) {
+ animation->appendBlankFrame();
+ } else {
+ int l;
+ QImage img = getBuffer(r, l);
+ animation->appendFrame(img,QPoint(r.x(),r.y()));
+ }
+ }
+ if (!r.isNull()) {
+ if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1
+ update(mapFromDevice(r, QSize(displayWidth(), displayHeight()), rotation));
+ else
+ update();
+ }
+}
+
+static void dim(QRgb* rgb, int n, int brightness)
+{
+ uchar* b = (uchar*)rgb;
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ b++;
+#endif
+ while (n--) {
+ b[0] = (uint)b[0] * brightness / 255;
+ b[1] = (uint)b[1] * brightness / 255;
+ b[2] = (uint)b[2] * brightness / 255;
+ b += 4;
+ }
+}
+
+QImage QVFbView::getBuffer(const QRect &r, int &leading) const
+{
+ const int brightness = mView->brightness();
+ if ( brightness == 0 ) {
+ QImage img(r.size(),QImage::Format_RGB32);
+ img.fill(0);
+ leading = 0;
+ return img;
+ }
+
+ static QByteArray buffer;
+
+ const int requiredSize = r.width() * r.height() * 4;
+
+ QImage img;
+ leading = 0;
+
+ switch (viewdepth) {
+ case 1: {
+ if (requiredSize > buffer.size())
+ buffer.resize(requiredSize);
+
+ // XXX: hw: replace by drawhelper functionality
+
+ const int pixelsPerByte = 8;
+ quint8 *src = reinterpret_cast<quint8*>(mView->data())
+ + r.y() * mView->linestep() + r.x() / pixelsPerByte;
+ const int align = qMin(r.width(), (8 - (r.x() & 7)) & 7);
+ const int doAlign = (align > 0 ? 1 : 0);
+ const int tail = qMin(r.width(), (r.width() - align) & 7);
+ const int doTail = (tail > 0 ? 1 : 0);
+ const int width8 = (r.width() - align) / pixelsPerByte;
+ const int stride = mView->linestep() - (width8 + doAlign);
+
+ uchar *b = reinterpret_cast<uchar*>(buffer.data());
+ img = QImage(b, r.width(), r.height(), QImage::Format_RGB32);
+ for (int y = 0; y < r.height(); ++y) {
+ quint32 *dest = reinterpret_cast<quint32*>(img.scanLine(y));
+ quint8 c;
+
+ if (doAlign) {
+ switch (align) {
+ case 7: c = ((*src & 0x40) >> 6) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ case 6: c = ((*src & 0x20) >> 5) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ case 5: c = ((*src & 0x10) >> 4) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ case 4: c = ((*src & 0x08) >> 3) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ case 3: c = ((*src & 0x04) >> 2) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ case 2: c = ((*src & 0x02) >> 1) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ case 1: c = ((*src & 0x01)) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ }
+ ++src;
+ }
+ for (int i = 0; i < width8; ++i) {
+ c = ((*src & 0x80) >> 7) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ c = ((*src & 0x40) >> 6) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ c = ((*src & 0x20) >> 5) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ c = ((*src & 0x10) >> 4) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ c = ((*src & 0x08) >> 3) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ c = ((*src & 0x04) >> 2) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ c = ((*src & 0x02) >> 1) * 0xff;
+ *dest++ = qRgb(c, c, c);
+ c = ((*src & 0x01)) * 0xff;
+ *dest++ = qRgb(c, c, c);
+
+ ++src;
+ }
+ if (doTail) {
+ switch (tail) {
+ case 7: c = ((*src & 0x02) >> 1) * 0xff;
+ dest[6] = qRgb(c, c, c);
+ case 6: c = ((*src & 0x04) >> 2) * 0xff;
+ dest[5] = qRgb(c, c, c);
+ case 5: c = ((*src & 0x08) >> 3) * 0xff;
+ dest[4] = qRgb(c, c, c);
+ case 4: c = ((*src & 0x10) >> 4) * 0xff;
+ dest[3] = qRgb(c, c, c);
+ case 3: c = ((*src & 0x20) >> 5) * 0xff;
+ dest[2] = qRgb(c, c, c);
+ case 2: c = ((*src & 0x40) >> 6) * 0xff;
+ dest[1] = qRgb(c, c, c);
+ case 1: c = ((*src & 0x80) >> 7) * 0xff;
+ dest[0] = qRgb(c, c, c);
+ }
+ }
+ src += stride;
+ }
+ break;
+ }
+ case 4: {
+ if (requiredSize > buffer.size())
+ buffer.resize(requiredSize);
+
+ // XXX: hw: replace by drawhelper functionality
+
+ const int pixelsPerByte = 2;
+ const int doAlign = r.x() & 1;
+ const int doTail = (r.width() - doAlign) & 1;
+ const int width8 = (r.width() - doAlign) / pixelsPerByte;
+
+ uchar *b = reinterpret_cast<uchar*>(buffer.data());
+ img = QImage(b, r.width(), r.height(), QImage::Format_RGB32);
+ for (int y = 0; y < r.height(); ++y) {
+ const quint8 *sptr = mView->data()
+ + (r.y() + y) * mView->linestep()
+ + r.x() / pixelsPerByte;
+ quint32 *dptr = reinterpret_cast<quint32*>(img.scanLine(y));
+
+ if (doAlign) {
+ quint8 c = (*sptr++ & 0x0f);
+ c |= (c << 4);
+ *dptr++ = qRgb(c, c, c);
+ }
+
+ for (int i = 0; i < width8; ++i) {
+ quint8 c1 = (*sptr >> 4);
+ quint8 c2 = (*sptr & 0x0f);
+ c1 |= (c1 << 4);
+ c2 |= (c2 << 4);
+ *dptr++ = qRgb(c1, c1, c1);
+ *dptr++ = qRgb(c2, c2, c2);
+ ++sptr;
+ }
+
+ if (doTail) {
+ quint8 c = *sptr >> 4;
+ c |= (c << 4);
+ *dptr = qRgb(c, c, c);
+ }
+ }
+ break;
+ }
+ case 12:
+ img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2),
+ r.width(), r.height(), mView->linestep(),
+ QImage::Format_RGB444);
+ break;
+ case 15:
+ img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2),
+ r.width(), r.height(), mView->linestep(),
+ QImage::Format_RGB555);
+ break;
+ case 16:
+ img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 2),
+ r.width(), r.height(), mView->linestep(),
+ QImage::Format_RGB16);
+ break;
+ case 18:
+ img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3),
+ r.width(), r.height(), mView->linestep(),
+ QImage::Format_RGB666);
+ break;
+ case 24:
+ img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 3),
+ r.width(), r.height(), mView->linestep(),
+ QImage::Format_RGB888);
+ break;
+ case 32:
+ img = QImage((const uchar*)(mView->data() + r.y() * mView->linestep() + r.x() * 4),
+ r.width(), r.height(), mView->linestep(),
+ viewFormat == ARGBFormat ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
+ break;
+ case 8:
+ img = QImage(mView->data() + r.y() * mView->linestep() + r.x(),
+ r.width(), r.height(), mView->linestep(),
+ QImage::Format_Indexed8);
+ img.setColorTable(mView->clut());
+ if (img.numColors() <= 0)
+ img = QImage();
+ break;
+ }
+
+ if ( brightness != 255 ) {
+ if (img.format() == QImage::Format_Indexed8) {
+ QVector<QRgb> c = img.colorTable();
+ dim(c.data(),c.count(),brightness);
+ img.setColorTable(c);
+ } else {
+ if ( img.format() != QImage::Format_ARGB32_Premultiplied )
+ img = img.convertToFormat(QImage::Format_RGB32);
+
+ // NOTE: calling bits() may change numBytes(), so do not
+ // pass them as parameters (which are evaluated right-to-left).
+ QRgb *b = (QRgb*)img.bits();
+ int n = img.numBytes()/4;
+ dim(b,n,brightness);
+ }
+ }
+
+ return img;
+}
+
+static int findMultiple(int start, double m, int limit, int step)
+{
+ int r = start;
+ while (r != limit) {
+ if (int(int(r * m)/m) == r)
+ break;
+ r += step;
+ }
+ return r;
+}
+
+void QVFbView::drawScreen(const QRect &rect)
+{
+ QRect r = QRect(0, 0, mView->width(), mView->height());
+
+ if (hzm == 1.0 && vzm == 1.0) // hw: workaround for 4.3.1
+ r &= rect;
+
+ if (int(hzm) != hzm || int(vzm) != vzm) {
+ r.setLeft(findMultiple(r.left(),hzm,0,-1));
+ r.setTop(findMultiple(r.top(),vzm,0,-1));
+ int w = findMultiple(r.width(),hzm,mView->width(),1);
+ int h = findMultiple(r.height(),vzm,mView->height(),1);
+ r.setRight(r.left()+w-1);
+ r.setBottom(r.top()+h-1);
+ }
+
+ int leading;
+ const QImage img = getBuffer(r, leading);
+
+ QPixmap pm;
+ if (hzm == 1.0 && vzm == 1.0) {
+ pm = QPixmap::fromImage(img);
+ } else if (emulateLcdScreen && hzm == 3.0 && vzm == 3.0) {
+ QImage img2(img.width()*3, img.height(), QImage::Format_RGB32);
+ for (int row = 0; row < img2.height(); row++) {
+ QRgb *dptr = (QRgb*)img2.scanLine(row);
+ QRgb *sptr = (QRgb*)img.scanLine(row);
+ for (int col = 0; col < img.width(); col++) {
+ QRgb s = *sptr++;
+ *dptr++ = qRgb(qRed(s),0,0);
+ *dptr++ = qRgb(0,qGreen(s),0);
+ *dptr++ = qRgb(0,0,qBlue(s));
+ }
+ }
+ QMatrix m;
+ m.scale(1.0, 3.0);
+ pm = QPixmap::fromImage(img2);
+ pm = pm.transformed(m);
+ } else if (int(hzm) == hzm && int(vzm) == vzm) {
+ QMatrix m;
+ m.scale(hzm,vzm);
+ pm = QPixmap::fromImage(img);
+ pm = pm.transformed(m);
+ } else {
+ pm = QPixmap::fromImage(img.scaled(int(img.width()*hzm),int(img.height()*vzm), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ }
+
+ int x1 = r.x();
+ int y1 = r.y();
+ int leadingX = leading;
+ int leadingY = 0;
+
+ // Do the rotation thing
+ int rotX1 = mView->width() - x1 - img.width();
+ int rotY1 = mView->height() - y1 - img.height();
+ int rotLeadingX = (leading) ? mView->width() - leadingX - img.width() : 0;
+ int rotLeadingY = 0;
+ switch (rotation) {
+ case Rot0:
+ break;
+ case Rot90:
+ leadingY = leadingX;
+ leadingX = rotLeadingY;
+ y1 = x1;
+ x1 = rotY1;
+ break;
+ case Rot180:
+ leadingX = rotLeadingX;
+ leadingY = leadingY;
+ x1 = rotX1;
+ y1 = rotY1;
+ break;
+ case Rot270:
+ leadingX = leadingY;
+ leadingY = rotLeadingX;
+ x1 = y1;
+ y1 = rotX1;
+ break;
+ default:
+ break;
+ }
+ x1 = int(x1*hzm);
+ y1 = int(y1*vzm);
+ leadingX = int(leadingX*hzm);
+ leadingY = int(leadingY*vzm);
+ if (rotation != 0) {
+ QMatrix m;
+ m.rotate(rotation * 90.0);
+ pm = pm.transformed(m);
+ }
+
+ QPainter p(this);
+ if (viewFormat == ARGBFormat) {
+ QPixmap bg(":/res/images/logo-nt.png");
+ p.fillRect(x1,y1,pm.width(), pm.height(), QBrush(bg));
+ }
+ p.drawPixmap(x1, y1, pm, leadingX, leadingY, pm.width(), pm.height());
+}
+
+//bool QVFbView::eventFilter(QObject *obj, QEvent *e)
+//{
+// if (obj == this &&
+// (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut))
+// return true;
+//
+// return QWidgetView::eventFilter(obj, e);
+//}
+
+void QVFbView::paintEvent(QPaintEvent *e)
+{
+ drawScreen(mapToDevice(e->rect(),QSize(int(width()/hzm), int(height()/vzm)),rotation));
+}
+
+void QVFbView::mousePressEvent(QMouseEvent *e)
+{
+ sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
+}
+
+void QVFbView::contextMenuEvent(QContextMenuEvent*)
+{
+
+}
+
+void QVFbView::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
+}
+
+void QVFbView::mouseReleaseEvent(QMouseEvent *e)
+{
+ sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
+}
+
+void QVFbView::skinMouseEvent(QMouseEvent *e)
+{
+ sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
+}
+
+void QVFbView::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!emulateTouchscreen || (e->buttons() & Qt::MouseButtonMask))
+ sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), 0);
+}
+
+void QVFbView::wheelEvent(QWheelEvent *e)
+{
+ if (!e)
+ return;
+ sendMouseData(QPoint(int(e->x()/hzm),int(e->y()/vzm)), e->buttons(), e->delta());
+}
+
+void QVFbView::setTouchscreenEmulation(bool b)
+{
+ emulateTouchscreen = b;
+}
+
+void QVFbView::setLcdScreenEmulation(bool b)
+{
+ emulateLcdScreen = b;
+}
+
+void QVFbView::setViewFormat(PixelFormat f)
+{
+ if (viewFormat == f)
+ return;
+ viewFormat = f;
+ setAttribute(Qt::WA_PaintOnScreen, viewFormat != ARGBFormat);
+}
+
+#ifdef Q_WS_X11
+void QVFbView::embedDisplay(WId windowId)
+{
+ if (windowId == 0) {
+ delete embedContainer;
+ embedContainer = 0;
+ return;
+ }
+
+ if (!embedContainer) {
+ embedContainer = new QX11EmbedContainer(this);
+ embedContainer->setGeometry(rect());
+ embedContainer->show();
+ }
+ embedContainer->embedClient(windowId);
+}
+#endif
+
+bool QVFbView::event(QEvent *e)
+{
+ if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ sendKeyboardData(ke->text(), ke->key(),
+ ke->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier),
+ ke->type() == QEvent::KeyPress, ke->isAutoRepeat());
+ ke->accept();
+ return true;
+ }
+ return QVFbAbstractView::event(e);
+}
+
+void QVFbView::keyPressEvent(QKeyEvent *e)
+{
+ sendKeyboardData(e->text(), e->key(),
+ e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier),
+ true, e->isAutoRepeat());
+}
+
+void QVFbView::keyReleaseEvent(QKeyEvent *e)
+{
+ sendKeyboardData(e->text(), e->key(),
+ e->modifiers()&(Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier),
+ false, e->isAutoRepeat());
+}
+
+
+QImage QVFbView::image() const
+{
+ int l;
+ QImage r = getBuffer(QRect(0, 0, mView->width(), mView->height()), l).copy();
+ return r;
+}
+
+void QVFbView::startAnimation(const QString& filename)
+{
+ delete animation;
+ animation = new QAnimationWriter(filename,"MNG");
+ animation->setFrameRate(refreshRate);
+ animation->appendFrame(QImage(mView->data(),
+ mView->width(), mView->height(), QImage::Format_RGB32));
+}
+
+void QVFbView::stopAnimation()
+{
+ delete animation;
+ animation = 0;
+}
+
+
+void QVFbView::skinKeyPressEvent(int code, const QString& text, bool autorep)
+{
+ QKeyEvent e(QEvent::KeyPress,code,0,text,autorep);
+ keyPressEvent(&e);
+}
+
+void QVFbView::skinKeyReleaseEvent(int code, const QString& text, bool autorep)
+{
+ QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep);
+ keyReleaseEvent(&e);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/qvfbview.h b/tools/qvfb/qvfbview.h
new file mode 100644
index 0000000000..d533613e6b
--- /dev/null
+++ b/tools/qvfb/qvfbview.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVFBVIEW_H
+#define QVFBVIEW_H
+
+//#ifdef QT_NO_OPENGL
+#include <QWidget>
+//#else
+//#define QVFB_USE_GLWIDGET
+//#include <QGLWidget>
+//#endif
+
+QT_BEGIN_NAMESPACE
+
+class QImage;
+class QTimer;
+class QAnimationWriter;
+struct QVFbHeader;
+class QVFbViewProtocol;
+class QX11EmbedContainer;
+
+class QVFbAbstractView :
+#ifdef QVFB_USE_GLWIDGET
+ public QGLWidget
+#else
+ public QWidget
+#endif
+{
+ Q_OBJECT
+public:
+ enum Rotation { Rot0, Rot90, Rot180, Rot270 };
+ enum PixelFormat { DefaultFormat, GrayscaleFormat, RGBFormat, ARGBFormat };
+ QVFbAbstractView( QWidget *parent = 0);
+ virtual ~QVFbAbstractView();
+
+ virtual int displayId() const = 0;
+ virtual int displayWidth() const = 0;
+ virtual int displayHeight() const = 0;
+ virtual int displayDepth() const = 0;
+ virtual PixelFormat displayFormat() const { return DefaultFormat; }
+ virtual Rotation displayRotation() const = 0;
+
+ virtual void setGamma(double gr, double gg, double gb) = 0;
+ virtual double gammaRed() const = 0;
+ virtual double gammaGreen() const = 0;
+ virtual double gammaBlue() const = 0;
+ virtual void getGamma(int i, QRgb& rgb) = 0;
+
+ virtual bool touchScreenEmulation() const = 0;
+ virtual bool lcdScreenEmulation() const = 0;
+ virtual int rate() = 0;
+ virtual bool animating() const = 0;
+ virtual QImage image() const = 0;
+ virtual void setRate(int) = 0;
+
+ virtual double zoomH() const = 0;
+ virtual double zoomV() const = 0;
+
+public slots:
+ virtual void setTouchscreenEmulation( bool ) = 0;
+ virtual void setLcdScreenEmulation( bool ) = 0;
+ virtual void setZoom( double, double ) = 0;
+ virtual void setRotation(Rotation) = 0;
+ virtual void startAnimation( const QString& ) = 0;
+ virtual void stopAnimation() = 0;
+ virtual void skinKeyPressEvent( int code, const QString& text, bool autorep=FALSE ) = 0;
+ virtual void skinKeyReleaseEvent( int code, const QString& text, bool autorep=FALSE ) = 0;
+ virtual void setViewFormat(PixelFormat) {}
+ virtual void embedDisplay(WId) {}
+};
+
+class QVFbView : public QVFbAbstractView
+{
+ Q_OBJECT
+public:
+ QVFbView(int id, int w, int h, int d, Rotation r, QWidget *parent = 0);
+ virtual ~QVFbView();
+
+ int displayId() const;
+ int displayWidth() const;
+ int displayHeight() const;
+ int displayDepth() const;
+ PixelFormat displayFormat() const;
+ Rotation displayRotation() const;
+
+ bool touchScreenEmulation() const { return emulateTouchscreen; }
+ bool lcdScreenEmulation() const { return emulateLcdScreen; }
+ int rate() { return refreshRate; }
+ bool animating() const { return !!animation; }
+ QImage image() const;
+
+ void setGamma(double gr, double gg, double gb);
+ double gammaRed() const { return gred; }
+ double gammaGreen() const { return ggreen; }
+ double gammaBlue() const { return gblue; }
+ void getGamma(int i, QRgb& rgb);
+ void skinMouseEvent(QMouseEvent *e);
+
+ double zoomH() const { return hzm; }
+ double zoomV() const { return vzm; }
+
+ QSize sizeHint() const;
+ void setRate(int);
+
+public slots:
+ void setTouchscreenEmulation(bool);
+ void setLcdScreenEmulation(bool);
+ void setZoom(double, double);
+ void setRotation(Rotation);
+ void startAnimation(const QString&);
+ void stopAnimation();
+ void skinKeyPressEvent(int code, const QString& text, bool autorep=FALSE);
+ void skinKeyReleaseEvent(int code, const QString& text, bool autorep=FALSE);
+ void setViewFormat(PixelFormat);
+#ifdef Q_WS_X11
+ void embedDisplay(WId id);
+#endif
+
+protected slots:
+ void refreshDisplay(const QRect &);
+
+protected:
+ QImage getBuffer(const QRect &r, int &leading) const;
+ void drawScreen(const QRect &r);
+ void sendMouseData(const QPoint &pos, int buttons, int wheel);
+ void sendKeyboardData(QString unicode, int keycode, int modifiers,
+ bool press, bool repeat);
+ //virtual bool eventFilter(QObject *obj, QEvent *e);
+ virtual void paintEvent(QPaintEvent *pe);
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
+ virtual void mouseDoubleClickEvent(QMouseEvent *e);
+ virtual void mouseReleaseEvent(QMouseEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *e);
+ virtual void wheelEvent(QWheelEvent *e);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void keyReleaseEvent(QKeyEvent *e);
+ virtual bool event(QEvent *event);
+
+private:
+ void setDirty(const QRect&);
+ int viewdepth; // "faked" depth
+ PixelFormat viewFormat;
+ int rsh;
+ int gsh;
+ int bsh;
+ int rmax;
+ int gmax;
+ int bmax;
+ int contentsWidth;
+ int contentsHeight;
+ double gred, ggreen, gblue;
+ QRgb* gammatable;
+
+ int refreshRate;
+ QAnimationWriter *animation;
+ double hzm,vzm;
+ QVFbViewProtocol *mView;
+ bool emulateTouchscreen;
+ bool emulateLcdScreen;
+ Rotation rotation;
+
+#ifdef Q_WS_X11
+ QX11EmbedContainer *embedContainer;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/qvfbx11view.cpp b/tools/qvfb/qvfbx11view.cpp
new file mode 100644
index 0000000000..cad0b2cdbe
--- /dev/null
+++ b/tools/qvfb/qvfbx11view.cpp
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Phone Edition of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvfbx11view.h"
+#include "x11keyfaker.h"
+#include <qevent.h>
+#include <QX11Info>
+#include <QTimer>
+#include <QProcess>
+#include <QDebug>
+#include <QUuid>
+#include <QDataStream>
+#include <QTemporaryFile>
+#include <X11/Xlib.h>
+
+QT_BEGIN_NAMESPACE
+
+QVFbX11View::QVFbX11View
+ (int id, int w, int h, int d, Rotation r, QWidget *parent)
+ : QVFbAbstractView(parent)
+{
+ this->id = id;
+ this->w = w;
+ this->h = h;
+ this->d = d;
+ this->rotation = r;
+ this->gr = 1.0;
+ this->gg = 1.0;
+ this->gb = 1.0;
+ this->touchscreen = false;
+ this->lcd = false;
+ this->keyFaker = 0;
+ this->xnest = 0;
+ this->serverAuthFile = 0;
+ this->shutdown = false;
+
+ // Try to find Xephyr, as it is better than Xnest in many ways.
+ if (QFile::exists("/usr/bin/Xephyr"))
+ xserver = "/usr/bin/Xephyr";
+ else if (QFile::exists("/usr/local/bin/Xephyr"))
+ xserver = "/usr/local/bin/Xephyr";
+ else if (QFile::exists("/usr/X11R6/bin/Xephyr"))
+ xserver = "/usr/X11R6/bin/Xephyr";
+ else
+ xserver = "Xnest";
+}
+
+QVFbX11View::~QVFbX11View()
+{
+ shutdown = true;
+ if (xnest) {
+ xnest->terminate();
+ xnestStopped();
+ }
+}
+
+int QVFbX11View::displayId() const
+{
+ return id;
+}
+
+int QVFbX11View::displayWidth() const
+{
+ return ( (int)rotation & 0x01 ) ? h : w;
+}
+
+int QVFbX11View::displayHeight() const
+{
+ return ( (int)rotation & 0x01 ) ? w : h;
+}
+
+int QVFbX11View::displayDepth() const
+{
+ return d;
+}
+
+QVFbX11View::Rotation QVFbX11View::displayRotation() const
+{
+ return rotation;
+}
+
+void QVFbX11View::skinKeyPressEvent(int code, const QString&, bool)
+{
+ if (keyFaker)
+ keyFaker->sendKeyEvent(code, true);
+}
+
+void QVFbX11View::skinKeyReleaseEvent(int code, const QString&, bool)
+{
+ if (keyFaker)
+ keyFaker->sendKeyEvent(code, false);
+}
+
+void QVFbX11View::setGamma(double gr, double gg, double gb)
+{
+ // We remember the values, but don't do anything with them.
+ this->gr = gr;
+ this->gg = gg;
+ this->gb = gb;
+}
+
+double QVFbX11View::gammaRed() const
+{
+ return gr;
+}
+
+double QVFbX11View::gammaGreen() const
+{
+ return gg;
+}
+
+double QVFbX11View::gammaBlue() const
+{
+ return gb;
+}
+
+void QVFbX11View::getGamma(int, QRgb& rgb)
+{
+ rgb = qRgb(255, 255, 255);
+}
+
+bool QVFbX11View::touchScreenEmulation() const
+{
+ return touchscreen;
+}
+
+bool QVFbX11View::lcdScreenEmulation() const
+{
+ return lcd;
+}
+
+int QVFbX11View::rate()
+{
+ // We don't support refresh rates, so return a default value.
+ return 30;
+}
+
+bool QVFbX11View::animating() const
+{
+ // We don't support animation.
+ return false;
+}
+
+QImage QVFbX11View::image() const
+{
+ // We don't support image capture.
+ return QImage();
+}
+
+void QVFbX11View::setRate(int)
+{
+ // We don't support rate adjustments.
+}
+
+
+double QVFbX11View::zoomH() const
+{
+ // Zoom is not possible with Xnest.
+ return 1.0;
+}
+
+double QVFbX11View::zoomV() const
+{
+ // Zoom is not possible with Xnest.
+ return 1.0;
+}
+
+QSize QVFbX11View::sizeHint() const
+{
+ return QSize(w, h);
+}
+
+void QVFbX11View::setTouchscreenEmulation( bool flag )
+{
+ touchscreen = flag;
+}
+
+void QVFbX11View::setLcdScreenEmulation( bool flag )
+{
+ lcd = flag;
+}
+
+void QVFbX11View::setZoom( double, double )
+{
+ // Zoom is not possible with Xnest.
+}
+
+void QVFbX11View::setRotation( Rotation )
+{
+ // Rotation is not possible with Xnest.
+}
+
+void QVFbX11View::startAnimation( const QString& )
+{
+ // Animation is not supported.
+}
+
+void QVFbX11View::stopAnimation()
+{
+ // Animation is not supported.
+}
+
+// Generate a 16-byte magic cookie string.
+static QString generateMagicCookie()
+{
+ static const char hexchars[] = "0123456789abcdef";
+ QUuid uuid = QUuid::createUuid();
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << uuid;
+ QString value;
+ foreach ( char ch, ba ) {
+ value += QChar( hexchars[(ch >> 4) & 0x0F] );
+ value += QChar( hexchars[ch & 0x0F] );
+ }
+ return value;
+}
+
+void QVFbX11View::showEvent(QShowEvent *e)
+{
+ if (!xnest)
+ startXnest();
+ QWidget::showEvent(e);
+}
+
+void QVFbX11View::keyPressEvent(QKeyEvent *e)
+{
+ if (keyFaker)
+ keyFaker->sendKeyEvent(e->key(), true);
+ QWidget::keyPressEvent(e);
+}
+
+void QVFbX11View::keyReleaseEvent(QKeyEvent *e)
+{
+ if (keyFaker)
+ keyFaker->sendKeyEvent(e->key(), false);
+ QWidget::keyReleaseEvent(e);
+}
+
+void QVFbX11View::startXnest()
+{
+ // Add authentication credentials to the XAUTHORITY file.
+ QString cookie = generateMagicCookie();
+ QStringList xauthargs;
+ xauthargs += "add";
+ xauthargs += ":" + QString::number(displayId());
+ xauthargs += "MIT-MAGIC-COOKIE-1";
+ xauthargs += cookie;
+ if (QProcess::execute("xauth", xauthargs) != 0)
+ qWarning() << "xauth: failed to add Xnest client authentication credentials";
+
+ // Write the credentials to another authentication file for the server.
+ serverAuthFile = new QTemporaryFile(this);
+ QString authFilename;
+ if (serverAuthFile->open()) {
+ authFilename = serverAuthFile->fileName();
+ serverAuthFile->close();
+ xauthargs.clear();
+ xauthargs += "-f";
+ xauthargs += authFilename;
+ xauthargs += "add";
+ xauthargs += ":" + QString::number(displayId());
+ xauthargs += "MIT-MAGIC-COOKIE-1";
+ xauthargs += cookie;
+ if (QProcess::execute("xauth", xauthargs) != 0)
+ qWarning() << "xauth: failed to add Xnest server authentication credentials";
+ }
+
+ // Create a raw X11 window to act as the Xnest's root window.
+ // We cannot use winId() directly because qvfb is already
+ // selecting for events that Xnest wants to select for.
+ WId root = XCreateSimpleWindow
+ (QX11Info::display(), winId(), 0, 0, w, h, 0,
+ BlackPixel(QX11Info::display(), QX11Info::appScreen()),
+ BlackPixel(QX11Info::display(), QX11Info::appScreen()));
+ XMapWindow(QX11Info::display(), root);
+
+ // Warn the user if the visual number looks wrong. Xnest expects
+ // its root window to be on the default visual.
+ if (QX11Info::appVisual() != DefaultVisual(QX11Info::display(), QX11Info::appScreen())) {
+ qWarning() << "*** Qt is not using the default visual. Xnest may fail "
+ "with a BadMatch error.";
+ qWarning() << "*** If it fails, then restart qvfb with \" -visual"
+ << DefaultVisual(QX11Info::display(), QX11Info::appScreen())
+ ->visualid << "\"";
+ }
+
+ // Make sure the root window is in the X server before Xnest starts.
+ XSync(QX11Info::display(), False);
+
+ // Start the Xnest process.
+ xnest = new QProcess(this);
+ connect(xnest, SIGNAL(error(QProcess::ProcessError)),
+ this, SLOT(xnestStopped()));
+ connect(xnest, SIGNAL(finished(int,QProcess::ExitStatus)),
+ this, SLOT(xnestStopped()));
+ QStringList args;
+ args += "-auth";
+ args += authFilename;
+ if (!xserver.contains("Xephyr")) {
+ args += "-geometry";
+ args += QString::number(w) + "x" + QString::number(h) + "+0+0";
+ args += "-depth";
+ args += QString::number(d);
+ }
+ args += "-br"; // Start Xnest with a black background.
+ args += "-parent";
+ args += "0x" + QString::number(root, 16);
+ args += ":" + QString::number(displayId());
+ xnest->setProcessChannelMode(QProcess::ForwardedChannels);
+ xnest->start(xserver, args);
+ //qDebug() << args;
+
+ QTimer::singleShot(200, this, SLOT(startKeyFaker()));
+}
+
+void QVFbX11View::xnestStopped()
+{
+ if (!shutdown) {
+ if (xnest && xnest->error() == QProcess::FailedToStart)
+ qWarning() << xserver << "could not be started";
+ else
+ qWarning() << xserver << "stopped unexpectedly";
+ }
+ if (keyFaker) {
+ delete keyFaker;
+ keyFaker = 0;
+ }
+ if (xnest) {
+ xnest->deleteLater();
+ xnest = 0;
+
+ QStringList xauthargs;
+ xauthargs += "remove";
+ xauthargs += ":" + QString::number(displayId());
+ if (QProcess::execute("xauth", xauthargs) != 0)
+ qWarning() << "xauth: failed to remove Xnest authentication credentials";
+ }
+ if (serverAuthFile) {
+ delete serverAuthFile;
+ serverAuthFile = 0;
+ }
+}
+
+void QVFbX11View::startKeyFaker()
+{
+ if (!keyFaker && xnest)
+ keyFaker = new X11KeyFaker(":" + QString::number(displayId()), this);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/qvfbx11view.h b/tools/qvfb/qvfbx11view.h
new file mode 100644
index 0000000000..a96fa6de22
--- /dev/null
+++ b/tools/qvfb/qvfbx11view.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Phone Edition of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVFBX11VIEW_H
+#define QVFBX11VIEW_H
+
+#include "qvfbview.h"
+
+QT_BEGIN_NAMESPACE
+
+class X11KeyFaker;
+class QProcess;
+class QTemporaryFile;
+
+class QVFbX11View : public QVFbAbstractView
+{
+ Q_OBJECT
+public:
+ QVFbX11View( int id, int w, int h, int d, Rotation r, QWidget *parent = 0);
+ virtual ~QVFbX11View();
+
+ QString xServerPath() const { return xserver; }
+ void setXServerPath(const QString& path) { xserver = path; }
+
+ int displayId() const;
+ int displayWidth() const;
+ int displayHeight() const;
+ int displayDepth() const;
+ Rotation displayRotation() const;
+
+ void skinKeyPressEvent( int code, const QString& text, bool autorep=FALSE );
+ void skinKeyReleaseEvent( int code, const QString& text, bool autorep=FALSE );
+
+ void setGamma(double gr, double gg, double gb);
+ double gammaRed() const;
+ double gammaGreen() const;
+ double gammaBlue() const;
+ void getGamma(int i, QRgb& rgb);
+
+ bool touchScreenEmulation() const;
+ bool lcdScreenEmulation() const;
+ int rate();
+ bool animating() const;
+ QImage image() const;
+ void setRate(int);
+
+ double zoomH() const;
+ double zoomV() const;
+
+ QSize sizeHint() const;
+
+public slots:
+ void setTouchscreenEmulation( bool );
+ void setLcdScreenEmulation( bool );
+ void setZoom( double, double );
+ void setRotation(Rotation);
+ void startAnimation( const QString& );
+ void stopAnimation();
+
+protected:
+ void showEvent(QShowEvent *);
+ void keyPressEvent(QKeyEvent *);
+ void keyReleaseEvent(QKeyEvent *);
+
+private slots:
+ void startXnest();
+ void xnestStopped();
+ void startKeyFaker();
+
+private:
+ int id, w, h, d;
+ Rotation rotation;
+ double gr, gg, gb;
+ bool touchscreen, lcd;
+ X11KeyFaker *keyFaker;
+ QProcess *xnest;
+ QTemporaryFile *serverAuthFile;
+ bool shutdown;
+ QString xserver;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qvfb/translations/translations.pro b/tools/qvfb/translations/translations.pro
new file mode 100644
index 0000000000..736a72cd33
--- /dev/null
+++ b/tools/qvfb/translations/translations.pro
@@ -0,0 +1,32 @@
+# Include those manually as they do not contain any directory specification
+
+FORMS = ../config.ui
+HEADERS = ../qvfb.h \
+ ../qvfbview.h \
+ ../qvfbratedlg.h \
+ ../qanimationwriter.h \
+ ../gammaview.h \
+ ../qvfbprotocol.h \
+ ../qvfbshmem.h \
+ ../qvfbmmap.h \
+ ../qvfbhdr.h \
+ ../qlock_p.h \
+ ../qwssignalhandler_p.h \
+ ../../shared/deviceskin/deviceskin.cpp
+
+SOURCES = ../qvfb.cpp \
+ ../qvfbview.cpp \
+ ../qvfbratedlg.cpp \
+ ../main.cpp \
+ ../qanimationwriter.cpp \
+ ../qvfbprotocol.cpp \
+ ../qvfbshmem.cpp \
+ ../qvfbmmap.cpp \
+ ../qlock.cpp \
+ ../qwssignalhandler.cpp \
+ ../../shared/deviceskin/deviceskin.cpp
+
+TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/qvfb_pl.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qvfb_untranslated.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qvfb_zh_CN.ts \
+ $$[QT_INSTALL_TRANSLATIONS]/qvfb_zh_TW.ts
diff --git a/tools/qvfb/x11keyfaker.cpp b/tools/qvfb/x11keyfaker.cpp
new file mode 100644
index 0000000000..76d6e6a112
--- /dev/null
+++ b/tools/qvfb/x11keyfaker.cpp
@@ -0,0 +1,626 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Phone Edition of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "x11keyfaker.h"
+#include <QTimer>
+#include <QSocketNotifier>
+#include <QDebug>
+#include <X11/Xlib.h>
+#include <X11/cursorfont.h>
+#include <X11/extensions/XTest.h>
+#include <X11/keysym.h>
+#include <X11/XF86keysym.h>
+#include "qtopiakeysym.h"
+#include <unistd.h>
+#include <fcntl.h>
+
+QT_BEGIN_NAMESPACE
+
+X11KeyFaker::X11KeyFaker(const QString& displayName, QObject *parent)
+ : QObject(parent)
+{
+ this->displayName = displayName;
+ this->dpy = 0;
+ this->retryCount = 0;
+ this->shiftKeycode = 0;
+ this->modeSwitchKeycode = 0;
+ this->modifiers = 0;
+ connect();
+}
+
+X11KeyFaker::~X11KeyFaker()
+{
+ if (dpy)
+ XCloseDisplay(dpy);
+}
+
+void X11KeyFaker::sendKeyEvent(int qtCode, bool isPress)
+{
+ if (!dpy)
+ return;
+
+ // Convert the Qt key code into an X keysym.
+ KeySym keysym = NoSymbol;
+ switch (qtCode) {
+ case Qt::Key_Escape: keysym = XK_Escape; break;
+ case Qt::Key_Tab: keysym = XK_Tab; break;
+ case Qt::Key_Backtab: keysym = XK_ISO_Left_Tab; break;
+ case Qt::Key_Backspace: keysym = XK_BackSpace; break;
+ case Qt::Key_Return: keysym = XK_Return; break;
+ case Qt::Key_Enter: keysym = XK_KP_Enter; break;
+ case Qt::Key_Insert: keysym = XK_KP_Insert; break;
+ case Qt::Key_Delete: keysym = XK_KP_Delete; break;
+ case Qt::Key_Pause: keysym = XK_Pause; break;
+ case Qt::Key_Print: keysym = XK_Print; break;
+ case Qt::Key_SysReq: keysym = 0x1005FF60; break;
+ case Qt::Key_Clear: keysym = XK_KP_Begin; break;
+ case Qt::Key_Home: keysym = XK_Home; break;
+ case Qt::Key_End: keysym = XK_End; break;
+ case Qt::Key_Left: keysym = XK_Left; break;
+ case Qt::Key_Up: keysym = XK_Up; break;
+ case Qt::Key_Right: keysym = XK_Right; break;
+ case Qt::Key_Down: keysym = XK_Down; break;
+ case Qt::Key_PageUp: keysym = XK_Prior; break;
+ case Qt::Key_PageDown: keysym = XK_Next; break;
+ case Qt::Key_Shift: keysym = XK_Shift_L; break;
+ case Qt::Key_Control: keysym = XK_Control_L; break;
+ case Qt::Key_Meta: keysym = XK_Meta_L; break;
+ case Qt::Key_Alt: keysym = XK_Alt_L; break;
+ case Qt::Key_CapsLock: keysym = XK_Caps_Lock; break;
+ case Qt::Key_NumLock: keysym = XK_Num_Lock; break;
+ case Qt::Key_ScrollLock: keysym = XK_Scroll_Lock; break;
+ case Qt::Key_F1: keysym = XK_F1; break;
+ case Qt::Key_F2: keysym = XK_F2; break;
+ case Qt::Key_F3: keysym = XK_F3; break;
+ case Qt::Key_F4: keysym = XK_F4; break;
+ case Qt::Key_F5: keysym = XK_F5; break;
+ case Qt::Key_F6: keysym = XK_F6; break;
+ case Qt::Key_F7: keysym = XK_F7; break;
+ case Qt::Key_F8: keysym = XK_F8; break;
+ case Qt::Key_F9: keysym = XK_F9; break;
+ case Qt::Key_F10: keysym = XK_F10; break;
+ case Qt::Key_F11: keysym = XK_F11; break;
+ case Qt::Key_F12: keysym = XK_F12; break;
+ case Qt::Key_F13: keysym = XK_F13; break;
+ case Qt::Key_F14: keysym = XK_F14; break;
+ case Qt::Key_F15: keysym = XK_F15; break;
+ case Qt::Key_F16: keysym = XK_F16; break;
+ case Qt::Key_F17: keysym = XK_F17; break;
+ case Qt::Key_F18: keysym = XK_F18; break;
+ case Qt::Key_F19: keysym = XK_F19; break;
+ case Qt::Key_F20: keysym = XK_F20; break;
+ case Qt::Key_F21: keysym = XK_F21; break;
+ case Qt::Key_F22: keysym = XK_F22; break;
+ case Qt::Key_F23: keysym = XK_F23; break;
+ case Qt::Key_F24: keysym = XK_F24; break;
+ case Qt::Key_F25: keysym = XK_F25; break;
+ case Qt::Key_F26: keysym = XK_F26; break;
+ case Qt::Key_F27: keysym = XK_F27; break;
+ case Qt::Key_F28: keysym = XK_F28; break;
+ case Qt::Key_F29: keysym = XK_F29; break;
+ case Qt::Key_F30: keysym = XK_F30; break;
+ case Qt::Key_F31: keysym = XK_F31; break;
+ case Qt::Key_F32: keysym = XK_F32; break;
+ case Qt::Key_F33: keysym = XK_F33; break;
+ case Qt::Key_F34: keysym = XK_F34; break;
+ case Qt::Key_F35: keysym = XK_F35; break;
+ case Qt::Key_Super_L: keysym = XK_Super_L; break;
+ case Qt::Key_Super_R: keysym = XK_Super_R; break;
+ case Qt::Key_Menu: keysym = XK_Menu; break;
+ case Qt::Key_Hyper_L: keysym = XK_Hyper_L; break;
+ case Qt::Key_Hyper_R: keysym = XK_Hyper_R; break;
+ case Qt::Key_Help: keysym = XK_Help; break;
+ case Qt::Key_Direction_L: keysym = NoSymbol; break; // ???
+ case Qt::Key_Direction_R: keysym = NoSymbol; break; // ???
+ case Qt::Key_Space: keysym = XK_space; break;
+ case Qt::Key_Exclam: keysym = XK_exclam; break;
+ case Qt::Key_QuoteDbl: keysym = XK_quotedbl; break;
+ case Qt::Key_NumberSign: keysym = XK_numbersign; break;
+ case Qt::Key_Dollar: keysym = XK_dollar; break;
+ case Qt::Key_Percent: keysym = XK_percent; break;
+ case Qt::Key_Ampersand: keysym = XK_ampersand; break;
+ case Qt::Key_Apostrophe: keysym = XK_apostrophe; break;
+ case Qt::Key_ParenLeft: keysym = XK_parenleft; break;
+ case Qt::Key_ParenRight: keysym = XK_parenright; break;
+ case Qt::Key_Asterisk: keysym = XK_asterisk; break;
+ case Qt::Key_Plus: keysym = XK_plus; break;
+ case Qt::Key_Comma: keysym = XK_comma; break;
+ case Qt::Key_Minus: keysym = XK_minus; break;
+ case Qt::Key_Period: keysym = XK_period; break;
+ case Qt::Key_Slash: keysym = XK_slash; break;
+ case Qt::Key_0: keysym = XK_0; break;
+ case Qt::Key_1: keysym = XK_1; break;
+ case Qt::Key_2: keysym = XK_2; break;
+ case Qt::Key_3: keysym = XK_3; break;
+ case Qt::Key_4: keysym = XK_4; break;
+ case Qt::Key_5: keysym = XK_5; break;
+ case Qt::Key_6: keysym = XK_6; break;
+ case Qt::Key_7: keysym = XK_7; break;
+ case Qt::Key_8: keysym = XK_8; break;
+ case Qt::Key_9: keysym = XK_9; break;
+ case Qt::Key_Colon: keysym = XK_colon; break;
+ case Qt::Key_Semicolon: keysym = XK_semicolon; break;
+ case Qt::Key_Less: keysym = XK_less; break;
+ case Qt::Key_Equal: keysym = XK_equal; break;
+ case Qt::Key_Greater: keysym = XK_greater; break;
+ case Qt::Key_Question: keysym = XK_question; break;
+ case Qt::Key_At: keysym = XK_at; break;
+ case Qt::Key_A: keysym = XK_a; break; // Must be lower case keysyms
+ case Qt::Key_B: keysym = XK_b; break; // for correct shift handling.
+ case Qt::Key_C: keysym = XK_c; break;
+ case Qt::Key_D: keysym = XK_d; break;
+ case Qt::Key_E: keysym = XK_e; break;
+ case Qt::Key_F: keysym = XK_f; break;
+ case Qt::Key_G: keysym = XK_g; break;
+ case Qt::Key_H: keysym = XK_h; break;
+ case Qt::Key_I: keysym = XK_i; break;
+ case Qt::Key_J: keysym = XK_j; break;
+ case Qt::Key_K: keysym = XK_k; break;
+ case Qt::Key_L: keysym = XK_l; break;
+ case Qt::Key_M: keysym = XK_m; break;
+ case Qt::Key_N: keysym = XK_n; break;
+ case Qt::Key_O: keysym = XK_o; break;
+ case Qt::Key_P: keysym = XK_p; break;
+ case Qt::Key_Q: keysym = XK_q; break;
+ case Qt::Key_R: keysym = XK_r; break;
+ case Qt::Key_S: keysym = XK_s; break;
+ case Qt::Key_T: keysym = XK_t; break;
+ case Qt::Key_U: keysym = XK_u; break;
+ case Qt::Key_V: keysym = XK_v; break;
+ case Qt::Key_W: keysym = XK_w; break;
+ case Qt::Key_X: keysym = XK_x; break;
+ case Qt::Key_Y: keysym = XK_y; break;
+ case Qt::Key_Z: keysym = XK_z; break;
+ case Qt::Key_BracketLeft: keysym = XK_bracketleft; break;
+ case Qt::Key_Backslash: keysym = XK_backslash; break;
+ case Qt::Key_BracketRight: keysym = XK_bracketright; break;
+ case Qt::Key_AsciiCircum: keysym = XK_asciicircum; break;
+ case Qt::Key_Underscore: keysym = XK_underscore; break;
+ case Qt::Key_QuoteLeft: keysym = XK_quoteleft; break;
+ case Qt::Key_BraceLeft: keysym = XK_braceleft; break;
+ case Qt::Key_Bar: keysym = XK_bar; break;
+ case Qt::Key_BraceRight: keysym = XK_braceright; break;
+ case Qt::Key_AsciiTilde: keysym = XK_asciitilde; break;
+
+ case Qt::Key_nobreakspace: keysym = XK_nobreakspace; break;
+ case Qt::Key_exclamdown: keysym = XK_exclamdown; break;
+ case Qt::Key_cent: keysym = XK_cent; break;
+ case Qt::Key_sterling: keysym = XK_sterling; break;
+ case Qt::Key_currency: keysym = XK_currency; break;
+ case Qt::Key_yen: keysym = XK_yen; break;
+ case Qt::Key_brokenbar: keysym = XK_brokenbar; break;
+ case Qt::Key_section: keysym = XK_section; break;
+ case Qt::Key_diaeresis: keysym = XK_diaeresis; break;
+ case Qt::Key_copyright: keysym = XK_copyright; break;
+ case Qt::Key_ordfeminine: keysym = XK_ordfeminine; break;
+ case Qt::Key_guillemotleft: keysym = XK_guillemotleft; break;
+ case Qt::Key_notsign: keysym = XK_notsign; break;
+ case Qt::Key_hyphen: keysym = XK_hyphen; break;
+ case Qt::Key_registered: keysym = XK_registered; break;
+ case Qt::Key_macron: keysym = XK_macron; break;
+ case Qt::Key_degree: keysym = XK_degree; break;
+ case Qt::Key_plusminus: keysym = XK_plusminus; break;
+ case Qt::Key_twosuperior: keysym = XK_twosuperior; break;
+ case Qt::Key_threesuperior: keysym = XK_threesuperior; break;
+ case Qt::Key_acute: keysym = XK_acute; break;
+ case Qt::Key_mu: keysym = XK_mu; break;
+ case Qt::Key_paragraph: keysym = XK_paragraph; break;
+ case Qt::Key_periodcentered: keysym = XK_periodcentered; break;
+ case Qt::Key_cedilla: keysym = XK_cedilla; break;
+ case Qt::Key_onesuperior: keysym = XK_onesuperior; break;
+ case Qt::Key_masculine: keysym = XK_masculine; break;
+ case Qt::Key_guillemotright: keysym = XK_guillemotright; break;
+ case Qt::Key_onequarter: keysym = XK_onequarter; break;
+ case Qt::Key_onehalf: keysym = XK_onehalf; break;
+ case Qt::Key_threequarters: keysym = XK_threequarters; break;
+ case Qt::Key_questiondown: keysym = XK_questiondown; break;
+ case Qt::Key_Agrave: keysym = XK_agrave; break; // Lower case keysyms
+ case Qt::Key_Aacute: keysym = XK_aacute; break; // for shift handling.
+ case Qt::Key_Acircumflex: keysym = XK_acircumflex; break;
+ case Qt::Key_Atilde: keysym = XK_atilde; break;
+ case Qt::Key_Adiaeresis: keysym = XK_adiaeresis; break;
+ case Qt::Key_Aring: keysym = XK_aring; break;
+ case Qt::Key_AE: keysym = XK_ae; break;
+ case Qt::Key_Ccedilla: keysym = XK_ccedilla; break;
+ case Qt::Key_Egrave: keysym = XK_egrave; break;
+ case Qt::Key_Eacute: keysym = XK_eacute; break;
+ case Qt::Key_Ecircumflex: keysym = XK_ecircumflex; break;
+ case Qt::Key_Ediaeresis: keysym = XK_ediaeresis; break;
+ case Qt::Key_Igrave: keysym = XK_igrave; break;
+ case Qt::Key_Iacute: keysym = XK_iacute; break;
+ case Qt::Key_Icircumflex: keysym = XK_icircumflex; break;
+ case Qt::Key_Idiaeresis: keysym = XK_idiaeresis; break;
+ case Qt::Key_ETH: keysym = XK_eth; break;
+ case Qt::Key_Ntilde: keysym = XK_ntilde; break;
+ case Qt::Key_Ograve: keysym = XK_ograve; break;
+ case Qt::Key_Oacute: keysym = XK_oacute; break;
+ case Qt::Key_Ocircumflex: keysym = XK_ocircumflex; break;
+ case Qt::Key_Otilde: keysym = XK_otilde; break;
+ case Qt::Key_Odiaeresis: keysym = XK_odiaeresis; break;
+ case Qt::Key_multiply: keysym = XK_multiply; break;
+ case Qt::Key_Ooblique: keysym = XK_ooblique; break;
+ case Qt::Key_Ugrave: keysym = XK_ugrave; break;
+ case Qt::Key_Uacute: keysym = XK_uacute; break;
+ case Qt::Key_Ucircumflex: keysym = XK_ucircumflex; break;
+ case Qt::Key_Udiaeresis: keysym = XK_udiaeresis; break;
+ case Qt::Key_Yacute: keysym = XK_yacute; break;
+ case Qt::Key_THORN: keysym = XK_thorn; break;
+ case Qt::Key_ssharp: keysym = XK_ssharp; break;
+ case Qt::Key_division: keysym = XK_division; break;
+ case Qt::Key_ydiaeresis: keysym = XK_ydiaeresis; break;
+
+ case Qt::Key_AltGr: keysym = XK_ISO_Level3_Shift; break;
+ case Qt::Key_Multi_key: keysym = XK_Multi_key; break;
+ case Qt::Key_Codeinput: keysym = XK_Codeinput; break;
+ case Qt::Key_SingleCandidate: keysym = XK_SingleCandidate; break;
+ case Qt::Key_MultipleCandidate: keysym = XK_MultipleCandidate; break;
+ case Qt::Key_PreviousCandidate: keysym = XK_PreviousCandidate; break;
+
+ case Qt::Key_Mode_switch: keysym = XK_Mode_switch; break;
+
+ case Qt::Key_Kanji: keysym = XK_Kanji; break;
+ case Qt::Key_Muhenkan: keysym = XK_Muhenkan; break;
+ case Qt::Key_Henkan: keysym = XK_Henkan; break;
+ case Qt::Key_Romaji: keysym = XK_Romaji; break;
+ case Qt::Key_Hiragana: keysym = XK_Hiragana; break;
+ case Qt::Key_Katakana: keysym = XK_Katakana; break;
+ case Qt::Key_Hiragana_Katakana: keysym = XK_Hiragana_Katakana; break;
+ case Qt::Key_Zenkaku: keysym = XK_Zenkaku; break;
+ case Qt::Key_Hankaku: keysym = XK_Hankaku; break;
+ case Qt::Key_Zenkaku_Hankaku: keysym = XK_Zenkaku_Hankaku; break;
+ case Qt::Key_Touroku: keysym = XK_Touroku; break;
+ case Qt::Key_Massyo: keysym = XK_Massyo; break;
+ case Qt::Key_Kana_Lock: keysym = XK_Kana_Lock; break;
+ case Qt::Key_Kana_Shift: keysym = XK_Kana_Shift; break;
+ case Qt::Key_Eisu_Shift: keysym = XK_Eisu_Shift; break;
+ case Qt::Key_Eisu_toggle: keysym = XK_Eisu_toggle; break;
+
+ case Qt::Key_Hangul: keysym = XK_Hangul; break;
+ case Qt::Key_Hangul_Start: keysym = XK_Hangul_Start; break;
+ case Qt::Key_Hangul_End: keysym = XK_Hangul_End; break;
+ case Qt::Key_Hangul_Hanja: keysym = XK_Hangul_Hanja; break;
+ case Qt::Key_Hangul_Jamo: keysym = XK_Hangul_Jamo; break;
+ case Qt::Key_Hangul_Romaja: keysym = XK_Hangul_Romaja; break;
+ case Qt::Key_Hangul_Jeonja: keysym = XK_Hangul_Jeonja; break;
+ case Qt::Key_Hangul_Banja: keysym = XK_Hangul_Banja; break;
+ case Qt::Key_Hangul_PreHanja: keysym = XK_Hangul_PreHanja; break;
+ case Qt::Key_Hangul_PostHanja: keysym = XK_Hangul_PostHanja; break;
+ case Qt::Key_Hangul_Special: keysym = XK_Hangul_Special; break;
+
+ case Qt::Key_Dead_Grave: keysym = XK_dead_grave; break;
+ case Qt::Key_Dead_Acute: keysym = XK_dead_acute; break;
+ case Qt::Key_Dead_Circumflex: keysym = XK_dead_circumflex; break;
+ case Qt::Key_Dead_Tilde: keysym = XK_dead_tilde; break;
+ case Qt::Key_Dead_Macron: keysym = XK_dead_macron; break;
+ case Qt::Key_Dead_Breve: keysym = XK_dead_breve; break;
+ case Qt::Key_Dead_Abovedot: keysym = XK_dead_abovedot; break;
+ case Qt::Key_Dead_Diaeresis: keysym = XK_dead_diaeresis; break;
+ case Qt::Key_Dead_Abovering: keysym = XK_dead_abovering; break;
+ case Qt::Key_Dead_Doubleacute: keysym = XK_dead_doubleacute; break;
+ case Qt::Key_Dead_Caron: keysym = XK_dead_caron; break;
+ case Qt::Key_Dead_Cedilla: keysym = XK_dead_cedilla; break;
+ case Qt::Key_Dead_Ogonek: keysym = XK_dead_ogonek; break;
+ case Qt::Key_Dead_Iota: keysym = XK_dead_iota; break;
+ case Qt::Key_Dead_Voiced_Sound: keysym = XK_dead_voiced_sound; break;
+ case Qt::Key_Dead_Semivoiced_Sound: keysym = XK_dead_semivoiced_sound; break;
+ case Qt::Key_Dead_Belowdot: keysym = XK_dead_belowdot; break;
+ case Qt::Key_Dead_Hook: keysym = XK_dead_hook; break;
+ case Qt::Key_Dead_Horn: keysym = XK_dead_horn; break;
+
+ case Qt::Key_Back: keysym = XF86XK_Back; break;
+ case Qt::Key_Forward: keysym = XF86XK_Forward; break;
+ case Qt::Key_Stop: keysym = XF86XK_Stop; break;
+ case Qt::Key_Refresh: keysym = XF86XK_Refresh; break;
+
+ case Qt::Key_VolumeDown: keysym = XF86XK_AudioLowerVolume; break;
+ case Qt::Key_VolumeMute: keysym = XF86XK_AudioMute; break;
+ case Qt::Key_VolumeUp: keysym = XF86XK_AudioRaiseVolume; break;
+ case Qt::Key_BassBoost: keysym = NoSymbol; break; // ???
+ case Qt::Key_BassUp: keysym = NoSymbol; break; // ???
+ case Qt::Key_BassDown: keysym = NoSymbol; break; // ???
+ case Qt::Key_TrebleUp: keysym = NoSymbol; break; // ???
+ case Qt::Key_TrebleDown: keysym = NoSymbol; break; // ???
+
+ case Qt::Key_MediaPlay: keysym = XF86XK_AudioPlay; break;
+ case Qt::Key_MediaStop: keysym = XF86XK_AudioStop; break;
+ case Qt::Key_MediaPrevious: keysym = XF86XK_AudioPrev; break;
+ case Qt::Key_MediaNext: keysym = XF86XK_AudioNext; break;
+ case Qt::Key_MediaRecord: keysym = XF86XK_AudioRecord; break;
+
+ case Qt::Key_HomePage: keysym = XF86XK_HomePage; break;
+ case Qt::Key_Favorites: keysym = XF86XK_Favorites; break;
+ case Qt::Key_Search: keysym = XF86XK_Search; break;
+ case Qt::Key_Standby: keysym = XF86XK_Standby; break;
+ case Qt::Key_OpenUrl: keysym = XF86XK_OpenURL; break;
+
+ case Qt::Key_LaunchMail: keysym = XF86XK_Mail; break;
+ case Qt::Key_LaunchMedia: keysym = XF86XK_AudioMedia; break;
+ case Qt::Key_Launch0: keysym = XF86XK_Launch0; break;
+ case Qt::Key_Launch1: keysym = XF86XK_Launch1; break;
+ case Qt::Key_Launch2: keysym = XF86XK_Launch2; break;
+ case Qt::Key_Launch3: keysym = XF86XK_Launch3; break;
+ case Qt::Key_Launch4: keysym = XF86XK_Launch4; break;
+ case Qt::Key_Launch5: keysym = XF86XK_Launch5; break;
+ case Qt::Key_Launch6: keysym = XF86XK_Launch6; break;
+ case Qt::Key_Launch7: keysym = XF86XK_Launch7; break;
+ case Qt::Key_Launch8: keysym = XF86XK_Launch8; break;
+ case Qt::Key_Launch9: keysym = XF86XK_Launch9; break;
+ case Qt::Key_LaunchA: keysym = XF86XK_LaunchA; break;
+ case Qt::Key_LaunchB: keysym = XF86XK_LaunchB; break;
+ case Qt::Key_LaunchC: keysym = XF86XK_LaunchC; break;
+ case Qt::Key_LaunchD: keysym = XF86XK_LaunchD; break;
+ case Qt::Key_LaunchE: keysym = XF86XK_LaunchE; break;
+ case Qt::Key_LaunchF: keysym = XF86XK_LaunchF; break;
+
+ case Qt::Key_MediaLast: keysym = NoSymbol; break; // ???
+
+ case Qt::Key_Select: keysym = QTOPIAXK_Select; break;
+ case Qt::Key_Yes: keysym = QTOPIAXK_Yes; break;
+ case Qt::Key_No: keysym = QTOPIAXK_No; break;
+
+ case Qt::Key_Cancel: keysym = QTOPIAXK_Cancel; break;
+ case Qt::Key_Printer: keysym = QTOPIAXK_Printer; break;
+ case Qt::Key_Execute: keysym = QTOPIAXK_Execute; break;
+ case Qt::Key_Sleep: keysym = QTOPIAXK_Sleep; break;
+ case Qt::Key_Play: keysym = QTOPIAXK_Play; break;
+ case Qt::Key_Zoom: keysym = QTOPIAXK_Zoom; break;
+
+ case Qt::Key_Context1: keysym = QTOPIAXK_Context1; break;
+ case Qt::Key_Context2: keysym = QTOPIAXK_Context2; break;
+ case Qt::Key_Context3: keysym = QTOPIAXK_Context3; break;
+ case Qt::Key_Context4: keysym = QTOPIAXK_Context4; break;
+ case Qt::Key_Call: keysym = QTOPIAXK_Call; break;
+ case Qt::Key_Hangup: keysym = QTOPIAXK_Hangup; break;
+ case Qt::Key_Flip: keysym = QTOPIAXK_Flip; break;
+
+ case Qt::Key_unknown: keysym = NoSymbol; break;
+ }
+ if (keysym == NoSymbol)
+ return;
+
+ // Convert the X keysym into an X keycode.
+ KeyCode keycode = XKeysymToKeycode(dpy, keysym);
+ if (keycode == NoSymbol)
+ return;
+
+ // Determine if we need to fake shift keys as well.
+ int index = 0;
+ while (index < 4 && XKeycodeToKeysym(dpy, keycode, index) != keysym)
+ ++index;
+ int extraModifiers = 0;
+ if ((index & 1) != 0)
+ extraModifiers |= ShiftMask;
+ if ((index & 2) != 0)
+ extraModifiers |= Mod2Mask;
+ if ((modifiers & LockMask) != 0) {
+ // If Caps Lock is set, then flip the shift state for alphabetic keys.
+ if (qtCode >= Qt::Key_A && qtCode <= Qt::Key_Z)
+ extraModifiers ^= ShiftMask;
+ if (qtCode >= Qt::Key_Agrave && qtCode <= Qt::Key_THORN &&
+ qtCode != Qt::Key_multiply)
+ extraModifiers ^= ShiftMask;
+ }
+
+ // Adjust modifier keys for the shift states. This is needed for
+ // things like the * and # phone keys, which need Shift to be pressed
+ // when entering from a keyboard, but don't need Shift from a skin.
+ unsigned long delay = 0;
+ if (extraModifiers != 0) {
+ if ((extraModifiers & ShiftMask) != 0) {
+ if ((modifiers & ShiftMask) == 0)
+ XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++);
+ } else {
+ if ((modifiers & ShiftMask) != 0)
+ XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++);
+ }
+ if ((extraModifiers & Mod2Mask) != 0) {
+ if ((modifiers & Mod2Mask) == 0)
+ XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++);
+ } else {
+ if ((modifiers & Mod2Mask) != 0)
+ XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++);
+ }
+ }
+
+ // Fake the actual key.
+ XTestFakeKeyEvent(dpy, keycode, (Bool)isPress, delay++);
+
+ // Adjust the modifiers back.
+ if (extraModifiers != 0) {
+ if ((extraModifiers & ShiftMask) != 0) {
+ if ((modifiers & ShiftMask) == 0)
+ XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++);
+ } else {
+ if ((modifiers & ShiftMask) != 0)
+ XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++);
+ }
+ if ((extraModifiers & Mod2Mask) != 0) {
+ if ((modifiers & Mod2Mask) == 0)
+ XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++);
+ } else {
+ if ((modifiers & Mod2Mask) != 0)
+ XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++);
+ }
+ }
+
+ // Flush the key events.
+ XFlush(dpy);
+
+ // Update the modifiers if this was a shift key.
+ if (isPress) {
+ if (qtCode == Qt::Key_Shift)
+ modifiers |= ShiftMask;
+ if (qtCode == Qt::Key_CapsLock)
+ modifiers |= LockMask;
+ if (qtCode == Qt::Key_Mode_switch)
+ modifiers |= Mod2Mask;
+ } else {
+ if (qtCode == Qt::Key_Shift)
+ modifiers &= ~ShiftMask;
+ if (qtCode == Qt::Key_CapsLock)
+ modifiers &= ~LockMask;
+ if (qtCode == Qt::Key_Mode_switch)
+ modifiers &= ~Mod2Mask;
+ }
+}
+
+// Determine if an X11 keycode is currently mapped to one or more keysyms.
+static bool keycodeInUse(Display *dpy, int keycode)
+{
+ for (int index = 0; index < 8; ++index) {
+ if (XKeycodeToKeysym(dpy, keycode, index) != NoSymbol)
+ return true;
+ }
+ return false;
+}
+
+// Allocate a keycode for a special keysym.
+static bool allocateSpecialKeysym
+ (Display *dpy, int& min_keycode, int& max_keycode, KeySym key)
+{
+ if (XKeysymToKeycode(dpy, key) != NoSymbol)
+ return true; // There is already a mapping for this key. Good!
+ while (max_keycode >= min_keycode) {
+ if (!keycodeInUse(dpy, max_keycode))
+ break;
+ --max_keycode;
+ }
+ if (max_keycode < min_keycode)
+ return false;
+ XChangeKeyboardMapping(dpy, max_keycode, 1, &key, 1);
+ --max_keycode;
+ return true;
+}
+
+void X11KeyFaker::connect()
+{
+ // Open the display.
+ dpy = XOpenDisplay(displayName.toLatin1().data());
+ if (!dpy) {
+ // Try again in a few milliseconds. Xnest may not be alive yet.
+ // Give up after 10 seconds.
+ if (++retryCount < 50)
+ QTimer::singleShot(200, this, SLOT(connect()));
+ else
+ QTimer::singleShot(0, this, SIGNAL(couldNotConnect()));
+ return;
+ }
+
+ // Query the XTest extension, which we need to fake the key events.
+ int event_base, error_base, major, minor;
+ if (!XTestQueryExtension
+ (dpy, &event_base, &error_base, &major, &minor)) {
+ XCloseDisplay(dpy);
+ dpy = 0;
+ QTimer::singleShot(0, this, SIGNAL(couldNotConnect()));
+ return;
+ }
+
+ // Modify the Xnest's keyboard mappings to add Qtopia's special keysyms.
+ int min_keycode = 1, max_keycode = 255;
+ XDisplayKeycodes(dpy, &min_keycode, &max_keycode);
+ bool ok = true;
+ for (KeySym key = QTOPIAXK_Max; key >= QTOPIAXK_Min; --key) {
+ // This is an extension keysym, not part of the standard X11 set.
+ if (!allocateSpecialKeysym(dpy, min_keycode, max_keycode, key)) {
+ ok = false;
+ break;
+ }
+ }
+ static const KeySym specials[] = {
+ XF86XK_Back, // Qt::Key_Back
+ XF86XK_AudioLowerVolume, // Qt::Key_VolumeUp
+ XF86XK_AudioRaiseVolume, // Qt::Key_VolumeDown
+ XK_F28, // Qt::Key_F28
+ NoSymbol
+ };
+ int index = 0;
+ while (ok && specials[index] != NoSymbol) {
+ // This is a standard X11/XFree86 keysym that Qtopia uses,
+ // but it may not be on the user's physical keyboard.
+ if (!allocateSpecialKeysym
+ (dpy, min_keycode, max_keycode, specials[index]))
+ ok = false;
+ ++index;
+ }
+ if (!ok)
+ qWarning() << "There are insufficient spare X11 keycodes to allocate the special Qtopia keys";
+
+ // Change the root cursor to something more reasonable than "X".
+ Cursor cursor = XCreateFontCursor(dpy, XC_left_ptr);
+ XDefineCursor(dpy, RootWindow(dpy, DefaultScreen(dpy)), cursor);
+
+ // Look up the shift keys.
+ shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_L);
+ if (shiftKeycode == NoSymbol)
+ shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_R);
+ modeSwitchKeycode = XKeysymToKeycode(dpy, XK_Mode_switch);
+
+ // Make sure all of the above changes are flushed.
+ XFlush(dpy);
+
+ // Set up event handling for the display.
+ QSocketNotifier *notifier = new QSocketNotifier
+ (ConnectionNumber(dpy), QSocketNotifier::Read, this);
+ QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(readyRead()));
+
+ // Make sure the file descriptor is not inherited across exec's.
+ fcntl(ConnectionNumber(dpy), F_SETFD, 1);
+
+ // Notify interested parties that we are now connected to the X display.
+ QTimer::singleShot(0, this, SIGNAL(connected()));
+}
+
+void X11KeyFaker::readyRead()
+{
+ if (dpy) {
+ // Read incoming events and discard them. The only event
+ // we care about is keyboard mapping changes. Since we
+ // don't have any active windows, there's nothing more to do.
+ while (XEventsQueued(dpy, QueuedAfterFlush)) {
+ XEvent event;
+ XNextEvent(dpy, &event);
+ if (event.xany.type == MappingNotify)
+ XRefreshKeyboardMapping(&event.xmapping);
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qvfb/x11keyfaker.h b/tools/qvfb/x11keyfaker.h
new file mode 100644
index 0000000000..32417df880
--- /dev/null
+++ b/tools/qvfb/x11keyfaker.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2006 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Phone Edition of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef X11KEYFAKER_H
+#define X11KEYFAKER_H
+
+#include <QObject>
+#include <QX11Info>
+#include <qnamespace.h>
+
+QT_BEGIN_NAMESPACE
+
+class X11KeyFaker : public QObject
+{
+ Q_OBJECT
+public:
+ X11KeyFaker(const QString& displayName, QObject *parent = 0);
+ ~X11KeyFaker();
+
+ bool isConnected() const { return dpy != 0; }
+
+ void sendKeyEvent(int qtCode, bool isPress);
+
+private slots:
+ void connect();
+ void readyRead();
+
+signals:
+ void connected();
+ void couldNotConnect();
+
+private:
+ QString displayName;
+ Display *dpy;
+ int retryCount;
+ int shiftKeycode;
+ int modeSwitchKeycode;
+ int modifiers;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/deviceskin/deviceskin.cpp b/tools/shared/deviceskin/deviceskin.cpp
new file mode 100644
index 0000000000..3301d24c13
--- /dev/null
+++ b/tools/shared/deviceskin/deviceskin.cpp
@@ -0,0 +1,857 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deviceskin.h"
+
+#include <QtCore/qnamespace.h>
+#include <QtGui/QApplication>
+#include <QtGui/QBitmap>
+#include <QtGui/QPixmap>
+#include <QtGui/QPainter>
+#include <QtCore/QTextStream>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtGui/QImage>
+#include <QtCore/QTimer>
+#include <QtCore/QDir>
+#include <QtCore/QRegExp>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QDebug>
+
+#ifdef TEST_SKIN
+# include <QtGui/QMainWindow>
+# include <QtGui/QDialog>
+# include <QtGui/QDialogButtonBox>
+# include <QtGui/QHBoxLayout>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ enum { joydistance = 10, key_repeat_period = 50, key_repeat_delay = 500 };
+ enum { debugDeviceSkin = 0 };
+}
+
+static void parseRect(const QString &value, QRect *rect) {
+ const QStringList l = value.split(QLatin1Char(' '));
+ rect->setRect(l[0].toInt(), l[1].toInt(), l[2].toInt(), l[3].toInt());
+}
+
+static QString msgImageNotLoaded(const QString &f) {
+ return DeviceSkin::tr("The image file '%1' could not be loaded.").arg(f);
+}
+
+// ------------ DeviceSkinButtonArea
+DeviceSkinButtonArea::DeviceSkinButtonArea() :
+ keyCode(0),
+ activeWhenClosed(0)
+{
+}
+
+QDebug &operator<<(QDebug &str, const DeviceSkinButtonArea &a)
+{
+
+ str << "Area: " << a.name << " keyCode=" << a.keyCode << " area=" << a.area
+ << " text=" << a.text << " activeWhenClosed=" << a.activeWhenClosed;
+ return str;
+}
+
+// ------------ DeviceSkinParameters
+
+QDebug operator<<(QDebug str, const DeviceSkinParameters &p)
+{
+ str << "Images " << p.skinImageUpFileName << ','
+ << p.skinImageDownFileName<< ',' << p.skinImageClosedFileName
+ << ',' << p.skinCursorFileName <<"\nScreen: " << p.screenRect
+ << " back: " << p.backScreenRect << " closed: " << p.closedScreenRect
+ << " cursor: " << p.cursorHot << " Prefix: " << p.prefix
+ << " Joystick: " << p.joystick << " MouseHover" << p.hasMouseHover;
+ const int numAreas = p.buttonAreas.size();
+ for (int i = 0; i < numAreas; i++)
+ str << p.buttonAreas[i];
+ return str;
+}
+
+QSize DeviceSkinParameters::secondaryScreenSize() const
+{
+ return backScreenRect.isNull() ? closedScreenRect .size(): backScreenRect.size();
+}
+
+bool DeviceSkinParameters::hasSecondaryScreen() const
+{
+ return secondaryScreenSize() != QSize(0, 0);
+}
+
+bool DeviceSkinParameters::read(const QString &skinDirectory, ReadMode rm, QString *errorMessage)
+{
+ // Figure out the name. remove ending '/' if present
+ QString skinFile = skinDirectory;
+ if (skinFile.endsWith(QLatin1Char('/')))
+ skinFile.truncate(skinFile.length() - 1);
+
+ QFileInfo fi(skinFile);
+ QString fn;
+ if ( fi.isDir() ) {
+ prefix = skinFile;
+ prefix += QLatin1Char('/');
+ fn = prefix;
+ fn += fi.baseName();
+ fn += QLatin1String(".skin");
+ } else if (fi.isFile()){
+ fn = skinFile;
+ prefix = fi.path();
+ prefix += QLatin1Char('/');
+ } else {
+ *errorMessage = DeviceSkin::tr("The skin directory '%1' does not contain a configuration file.").arg(skinDirectory);
+ return false;
+ }
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly )) {
+ *errorMessage = DeviceSkin::tr("The skin configuration file '%1' could not be opened.").arg(fn);
+ return false;
+ }
+ QTextStream ts(&f);
+ const bool rc = read(ts, rm, errorMessage);
+ if (!rc)
+ *errorMessage = DeviceSkin::tr("The skin configuration file '%1' could not be read: %2").arg(fn).arg(*errorMessage);
+ return rc;
+}
+bool DeviceSkinParameters::read(QTextStream &ts, ReadMode rm, QString *errorMessage)
+{
+ QStringList closedAreas;
+ QStringList toggleAreas;
+ QStringList toggleActiveAreas;
+ int nareas = 0;
+ screenDepth = 0;
+ QString mark;
+ ts >> mark;
+ hasMouseHover = true; // historical default
+ if ( mark == QLatin1String("[SkinFile]") ) {
+ const QString UpKey = QLatin1String("Up");
+ const QString DownKey = QLatin1String("Down");
+ const QString ClosedKey = QLatin1String("Closed");
+ const QString ClosedAreasKey = QLatin1String("ClosedAreas");
+ const QString ScreenKey = QLatin1String("Screen");
+ const QString ScreenDepthKey = QLatin1String("ScreenDepth");
+ const QString BackScreenKey = QLatin1String("BackScreen");
+ const QString ClosedScreenKey = QLatin1String("ClosedScreen");
+ const QString CursorKey = QLatin1String("Cursor");
+ const QString AreasKey = QLatin1String("Areas");
+ const QString ToggleAreasKey = QLatin1String("ToggleAreas");
+ const QString ToggleActiveAreasKey = QLatin1String("ToggleActiveAreas");
+ const QString HasMouseHoverKey = QLatin1String("HasMouseHover");
+ // New
+ while (!nareas) {
+ QString line = ts.readLine();
+ if ( line.isNull() )
+ break;
+ if ( line[0] != QLatin1Char('#') && !line.isEmpty() ) {
+ int eq = line.indexOf(QLatin1Char('='));
+ if ( eq >= 0 ) {
+ const QString key = line.left(eq);
+ eq++;
+ while (eq<line.length()-1 && line[eq].isSpace())
+ eq++;
+ const QString value = line.mid(eq);
+ if ( key == UpKey ) {
+ skinImageUpFileName = value;
+ } else if ( key == DownKey ) {
+ skinImageDownFileName = value;
+ } else if ( key == ClosedKey ) {
+ skinImageClosedFileName = value;
+ } else if ( key == ClosedAreasKey ) {
+ closedAreas = value.split(QLatin1Char(' '));
+ } else if ( key == ScreenKey ) {
+ parseRect( value, &screenRect);
+ } else if ( key == ScreenDepthKey ) {
+ screenDepth = value.toInt();
+ } else if ( key == BackScreenKey ) {
+ parseRect(value, &backScreenRect);
+ } else if ( key == ClosedScreenKey ) {
+ parseRect( value, &closedScreenRect );
+ } else if ( key == CursorKey ) {
+ QStringList l = value.split(QLatin1Char(' '));
+ skinCursorFileName = l[0];
+ cursorHot = QPoint(l[1].toInt(),l[2].toInt());
+ } else if ( key == AreasKey ) {
+ nareas = value.toInt();
+ } else if ( key == ToggleAreasKey ) {
+ toggleAreas = value.split(QLatin1Char(' '));
+ } else if ( key == ToggleActiveAreasKey ) {
+ toggleActiveAreas = value.split(QLatin1Char(' '));
+ } else if ( key == HasMouseHoverKey ) {
+ hasMouseHover = value == QLatin1String("true") || value == QLatin1String("1");
+ }
+ } else {
+ *errorMessage = DeviceSkin::tr("Syntax error: %1").arg(line);
+ return false;
+ }
+ }
+ }
+ } else {
+ // Old
+ skinImageUpFileName = mark;
+ QString s;
+ int x,y,w,h,na;
+ ts >> s >> x >> y >> w >> h >> na;
+ skinImageDownFileName = s;
+ screenRect.setRect(x, y, w, h);
+ nareas = na;
+ }
+ // Done for short mode
+ if (rm == ReadSizeOnly)
+ return true;
+ // verify skin files exist
+ skinImageUpFileName.insert(0, prefix);
+ if (!QFile(skinImageUpFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin \"up\" image file '%1' does not exist.").arg(skinImageUpFileName);
+ return false;
+ }
+ if (!skinImageUp.load(skinImageUpFileName)) {
+ *errorMessage = msgImageNotLoaded(skinImageUpFileName);
+ return false;
+ }
+
+ skinImageDownFileName.insert(0, prefix);
+ if (!QFile(skinImageDownFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin \"down\" image file '%1' does not exist.").arg(skinImageDownFileName);
+ return false;
+ }
+ if (!skinImageDown.load(skinImageDownFileName)) {
+ *errorMessage = msgImageNotLoaded(skinImageDownFileName);
+ return false;
+ }
+
+ if (!skinImageClosedFileName.isEmpty()) {
+ skinImageClosedFileName.insert(0, prefix);
+ if (!QFile(skinImageClosedFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin \"closed\" image file '%1' does not exist.").arg(skinImageClosedFileName);
+ return false;
+ }
+ if (!skinImageClosed.load(skinImageClosedFileName)) {
+ *errorMessage = msgImageNotLoaded(skinImageClosedFileName);
+ return false;
+ }
+ }
+
+ if (!skinCursorFileName.isEmpty()) {
+ skinCursorFileName.insert(0, prefix);
+ if (!QFile(skinCursorFileName).exists()) {
+ *errorMessage = DeviceSkin::tr("The skin cursor image file '%1' does not exist.").arg(skinCursorFileName);
+ return false;
+ }
+ if (!skinCursor.load(skinCursorFileName)) {
+ *errorMessage = msgImageNotLoaded(skinCursorFileName);
+ return false;
+ }
+ }
+
+ // read areas
+ if (!nareas)
+ return true;
+ buttonAreas.reserve(nareas);
+
+ int i = 0;
+ ts.readLine(); // eol
+ joystick = -1;
+ const QString Joystick = QLatin1String("Joystick");
+ while (i < nareas && !ts.atEnd() ) {
+ buttonAreas.push_back(DeviceSkinButtonArea());
+ DeviceSkinButtonArea &area = buttonAreas.back();
+ const QString line = ts.readLine();
+ if ( !line.isEmpty() && line[0] != QLatin1Char('#') ) {
+ const QStringList tok = line.split(QRegExp(QLatin1String("[ \t][ \t]*")));
+ if ( tok.count()<6 ) {
+ *errorMessage = DeviceSkin::tr("Syntax error in area definition: %1").arg(line);
+ return false;
+ } else {
+ area.name = tok[0];
+ QString k = tok[1];
+ if ( k.left(2).toLower() == QLatin1String("0x")) {
+ area.keyCode = k.mid(2).toInt(0,16);
+ } else {
+ area.keyCode = k.toInt();
+ }
+
+ int p=0;
+ for (int j=2; j < tok.count() - 1; ) {
+ const int x = tok[j++].toInt();
+ const int y = tok[j++].toInt();
+ area.area.putPoints(p++,1,x,y);
+ }
+
+ const QChar doubleQuote = QLatin1Char('"');
+ if ( area.name[0] == doubleQuote && area.name.endsWith(doubleQuote)) {
+ area.name.truncate(area.name.size() - 1);
+ area.name.remove(0, 1);
+ }
+ if ( area.name.length() == 1 )
+ area.text = area.name;
+ if ( area.name == Joystick)
+ joystick = i;
+ area.activeWhenClosed = closedAreas.contains(area.name)
+ || area.keyCode == Qt::Key_Flip; // must be to work
+ area.toggleArea = toggleAreas.contains(area.name);
+ area.toggleActiveArea = toggleActiveAreas.contains(area.name);
+ if ( area.toggleArea )
+ toggleAreaList += i;
+ i++;
+ }
+ }
+ }
+ if (i != nareas) {
+ qWarning() << DeviceSkin::tr("Mismatch in number of areas, expected %1, got %2.")
+ .arg(nareas).arg(i);
+ }
+ if (debugDeviceSkin)
+ qDebug() << *this;
+ return true;
+}
+
+// --------- CursorWindow declaration
+
+namespace qvfb_internal {
+
+class CursorWindow : public QWidget
+{
+public:
+ explicit CursorWindow(const QImage &cursor, QPoint hot, QWidget *sk);
+
+ void setView(QWidget*);
+ void setPos(QPoint);
+ bool handleMouseEvent(QEvent *ev);
+
+protected:
+ bool event( QEvent *);
+ bool eventFilter( QObject*, QEvent *);
+
+private:
+ QWidget *mouseRecipient;
+ QWidget *m_view;
+ QWidget *skin;
+ QPoint hotspot;
+};
+}
+
+// --------- Skin
+
+DeviceSkin::DeviceSkin(const DeviceSkinParameters &parameters, QWidget *p ) :
+ QWidget(p),
+ m_parameters(parameters),
+ buttonRegions(parameters.buttonAreas.size(), QRegion()),
+ parent(p),
+ m_view(0),
+ m_secondaryView(0),
+ buttonPressed(false),
+ buttonIndex(0),
+ cursorw(0),
+ joydown(0),
+ t_skinkey(new QTimer(this)),
+ t_parentmove(new QTimer(this)),
+ flipped_open(true)
+{
+ Q_ASSERT(p);
+ setMouseTracking(true);
+ setAttribute(Qt::WA_NoSystemBackground);
+
+ setZoom(1.0);
+ connect( t_skinkey, SIGNAL(timeout()), this, SLOT(skinKeyRepeat()) );
+ t_parentmove->setSingleShot( true );
+ connect( t_parentmove, SIGNAL(timeout()), this, SLOT(moveParent()) );
+}
+
+void DeviceSkin::skinKeyRepeat()
+{
+ if ( m_view ) {
+ const DeviceSkinButtonArea &area = m_parameters.buttonAreas[buttonIndex];
+ emit skinKeyReleaseEvent( area.keyCode,area.text, true );
+ emit skinKeyPressEvent( area.keyCode, area.text, true );
+ t_skinkey->start(key_repeat_period);
+ }
+}
+
+void DeviceSkin::calcRegions()
+{
+ const int numAreas = m_parameters.buttonAreas.size();
+ for (int i=0; i<numAreas; i++) {
+ QPolygon xa(m_parameters.buttonAreas[i].area.count());
+ int n = m_parameters.buttonAreas[i].area.count();
+ for (int p=0; p<n; p++) {
+ xa.setPoint(p,transform.map(m_parameters.buttonAreas[i].area[p]));
+ }
+ if ( n == 2 ) {
+ buttonRegions[i] = QRegion(xa.boundingRect());
+ } else {
+ buttonRegions[i] = QRegion(xa);
+ }
+ }
+}
+
+void DeviceSkin::loadImages()
+{
+ QImage iup = m_parameters.skinImageUp;
+ QImage idown = m_parameters.skinImageDown;
+
+ QImage iclosed;
+ const bool hasClosedImage = !m_parameters.skinImageClosed.isNull();
+
+ if (hasClosedImage)
+ iclosed = m_parameters.skinImageClosed;
+ QImage icurs;
+ const bool hasCursorImage = !m_parameters.skinCursor.isNull();
+ if (hasCursorImage)
+ icurs = m_parameters.skinCursor;
+
+ if (!transform.isIdentity()) {
+ iup = iup.transformed(transform, Qt::SmoothTransformation);
+ idown = idown.transformed(transform, Qt::SmoothTransformation);
+ if (hasClosedImage)
+ iclosed = iclosed.transformed(transform, Qt::SmoothTransformation);
+ if (hasCursorImage)
+ icurs = icurs.transformed(transform, Qt::SmoothTransformation);
+ }
+ const Qt::ImageConversionFlags conv = Qt::ThresholdAlphaDither|Qt::AvoidDither;
+ skinImageUp = QPixmap::fromImage(iup);
+ skinImageDown = QPixmap::fromImage(idown, conv);
+ if (hasClosedImage)
+ skinImageClosed = QPixmap::fromImage(iclosed, conv);
+ if (hasCursorImage)
+ skinCursor = QPixmap::fromImage(icurs, conv);
+
+ setFixedSize( skinImageUp.size() );
+ if (!skinImageUp.mask())
+ skinImageUp.setMask(skinImageUp.createHeuristicMask());
+ if (!skinImageClosed.mask())
+ skinImageClosed.setMask(skinImageClosed.createHeuristicMask());
+
+ QWidget* parent = parentWidget();
+ parent->setMask( skinImageUp.mask() );
+ parent->setFixedSize( skinImageUp.size() );
+
+ delete cursorw;
+ cursorw = 0;
+ if (hasCursorImage) {
+ cursorw = new qvfb_internal::CursorWindow(m_parameters.skinCursor, m_parameters.cursorHot, this);
+ if ( m_view )
+ cursorw->setView(m_view);
+ }
+}
+
+DeviceSkin::~DeviceSkin( )
+{
+ delete cursorw;
+}
+
+void DeviceSkin::setTransform( const QMatrix& wm )
+{
+ transform = QImage::trueMatrix(wm,m_parameters.skinImageUp.width(),m_parameters.skinImageUp.height());
+ calcRegions();
+ loadImages();
+ if ( m_view ) {
+ QPoint p = transform.map(QPolygon(m_parameters.screenRect)).boundingRect().topLeft();
+ m_view->move(p);
+ }
+ updateSecondaryScreen();
+}
+
+void DeviceSkin::setZoom( double z )
+{
+ setTransform(QMatrix().scale(z,z));
+}
+
+void DeviceSkin::updateSecondaryScreen()
+{
+ if (!m_secondaryView)
+ return;
+ if (flipped_open) {
+ if (m_parameters.backScreenRect.isNull()) {
+ m_secondaryView->hide();
+ } else {
+ m_secondaryView->move(transform.map(QPolygon(m_parameters.backScreenRect)).boundingRect().topLeft());
+ m_secondaryView->show();
+ }
+ } else {
+ if (m_parameters.closedScreenRect.isNull()) {
+ m_secondaryView->hide();
+ } else {
+ m_secondaryView->move(transform.map(QPolygon(m_parameters.closedScreenRect)).boundingRect().topLeft());
+ m_secondaryView->show();
+ }
+ }
+}
+
+void DeviceSkin::setView( QWidget *v )
+{
+ m_view = v;
+ m_view->setFocus();
+ m_view->move(transform.map(QPolygon(m_parameters.screenRect)).boundingRect().topLeft());
+ if ( cursorw )
+ cursorw->setView(v);
+}
+
+void DeviceSkin::setSecondaryView( QWidget *v )
+{
+ m_secondaryView = v;
+ updateSecondaryScreen();
+}
+
+void DeviceSkin::paintEvent( QPaintEvent *)
+{
+ QPainter p( this );
+ if ( flipped_open ) {
+ p.drawPixmap( 0, 0, skinImageUp );
+ } else {
+ p.drawPixmap( 0, 0, skinImageClosed );
+ }
+ QList<int> toDraw;
+ if ( buttonPressed == true ) {
+ toDraw += buttonIndex;
+ }
+ foreach (int toggle, m_parameters.toggleAreaList) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[toggle];
+ if ( flipped_open || ba.activeWhenClosed ) {
+ if ( ba.toggleArea && ba.toggleActiveArea )
+ toDraw += toggle;
+ }
+ }
+ foreach (int button, toDraw ) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[button];
+ const QRect r = buttonRegions[button].boundingRect();
+ if ( ba.area.count() > 2 )
+ p.setClipRegion(buttonRegions[button]);
+ p.drawPixmap( r.topLeft(), skinImageDown, r);
+ }
+}
+
+void DeviceSkin::mousePressEvent( QMouseEvent *e )
+{
+ if (e->button() == Qt::RightButton) {
+ emit popupMenu();
+ } else {
+ buttonPressed = false;
+
+ onjoyrelease = -1;
+ const int numAreas = m_parameters.buttonAreas.size();
+ for (int i = 0; i < numAreas ; i++) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[i];
+ if ( buttonRegions[i].contains( e->pos() ) ) {
+ if ( flipped_open || ba.activeWhenClosed ) {
+ if ( m_parameters.joystick == i ) {
+ joydown = true;
+ } else {
+ if ( joydown )
+ onjoyrelease = i;
+ else
+ startPress(i);
+ break;
+ if (debugDeviceSkin)// Debug message to be sure we are clicking the right areas
+ qDebug()<< m_parameters.buttonAreas[i].name << " clicked";
+ }
+ }
+ }
+ }
+ clickPos = e->pos();
+// This is handy for finding the areas to define rectangles for new skins
+ if (debugDeviceSkin)
+ qDebug()<< "Clicked in " << e->pos().x() << ',' << e->pos().y();
+ clickPos = e->pos();
+ }
+}
+
+void DeviceSkin::flip(bool open)
+{
+ if ( flipped_open == open )
+ return;
+ if ( open ) {
+ parent->setMask( skinImageUp.mask() );
+ emit skinKeyReleaseEvent( Qt::Key(Qt::Key_Flip), QString(), false);
+ } else {
+ parent->setMask( skinImageClosed.mask() );
+ emit skinKeyPressEvent( Qt::Key(Qt::Key_Flip), QString(), false);
+ }
+ flipped_open = open;
+ updateSecondaryScreen();
+ repaint();
+}
+
+void DeviceSkin::startPress(int i)
+{
+ buttonPressed = true;
+ buttonIndex = i;
+ if (m_view) {
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[buttonIndex];
+ if ( ba.keyCode == Qt::Key_Flip ) {
+ flip(!flipped_open);
+ } else if ( ba.toggleArea ) {
+ bool active = !ba.toggleActiveArea;
+ const_cast<DeviceSkinButtonArea &>(ba).toggleActiveArea = active;
+ if ( active )
+ emit skinKeyPressEvent( ba.keyCode, ba.text, false);
+ else
+ emit skinKeyReleaseEvent( ba.keyCode, ba.text, false);
+ } else {
+ emit skinKeyPressEvent( ba.keyCode, ba.text, false);
+ t_skinkey->start(key_repeat_delay);
+ }
+ repaint( buttonRegions[buttonIndex].boundingRect() );
+ }
+}
+
+void DeviceSkin::endPress()
+{
+ const DeviceSkinButtonArea &ba = m_parameters.buttonAreas[buttonIndex];
+ if (m_view && ba.keyCode != Qt::Key_Flip && !ba.toggleArea )
+ emit skinKeyReleaseEvent(ba.keyCode, ba.text, false );
+ t_skinkey->stop();
+ buttonPressed = false;
+ repaint( buttonRegions[buttonIndex].boundingRect() );
+}
+
+void DeviceSkin::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( e->buttons() & Qt::LeftButton ) {
+ const int joystick = m_parameters.joystick;
+ QPoint newpos = e->globalPos() - clickPos;
+ if ( joydown ) {
+ int k1=0, k2=0;
+ if ( newpos.x() < -joydistance ) {
+ k1 = joystick+1;
+ } else if ( newpos.x() > +joydistance ) {
+ k1 = joystick+3;
+ }
+ if ( newpos.y() < -joydistance ) {
+ k2 = joystick+2;
+ } else if ( newpos.y() > +joydistance ) {
+ k2 = joystick+4;
+ }
+ if ( k1 || k2 ) {
+ if ( !buttonPressed ) {
+ onjoyrelease = -1;
+ if ( k1 && k2 ) {
+ startPress(k2);
+ endPress();
+ }
+ startPress(k1 ? k1 : k2);
+ }
+ } else if ( buttonPressed ) {
+ endPress();
+ }
+ } else if ( buttonPressed == false ) {
+ parentpos = newpos;
+ if ( !t_parentmove->isActive() )
+ t_parentmove->start(50);
+ }
+ }
+ if ( cursorw )
+ cursorw->setPos(e->globalPos());
+}
+
+void DeviceSkin::moveParent()
+{
+ parent->move( parentpos );
+}
+
+void DeviceSkin::mouseReleaseEvent( QMouseEvent * )
+{
+ if ( buttonPressed )
+ endPress();
+ if ( joydown ) {
+ joydown = false;
+ if ( onjoyrelease >= 0 ) {
+ startPress(onjoyrelease);
+ endPress();
+ }
+ }
+}
+
+bool DeviceSkin::hasCursor() const
+{
+ return !skinCursor.isNull();
+}
+
+// ------------------ CursorWindow implementation
+
+namespace qvfb_internal {
+
+bool CursorWindow::eventFilter( QObject *, QEvent *ev)
+{
+ handleMouseEvent(ev);
+ return false;
+}
+
+bool CursorWindow::event( QEvent *ev )
+{
+ if (handleMouseEvent(ev))
+ return true;
+ return QWidget::event(ev);
+}
+
+bool CursorWindow::handleMouseEvent(QEvent *ev)
+{
+ bool handledEvent = false;
+ static int inhere=0;
+ if ( !inhere ) {
+ inhere++;
+ if ( m_view ) {
+ if ( ev->type() >= QEvent::MouseButtonPress && ev->type() <= QEvent::MouseMove ) {
+ QMouseEvent *e = (QMouseEvent*)ev;
+ QPoint gp = e->globalPos();
+ QPoint vp = m_view->mapFromGlobal(gp);
+ QPoint sp = skin->mapFromGlobal(gp);
+ if ( e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick ) {
+ if ( m_view->rect().contains(vp) )
+ mouseRecipient = m_view;
+ else if ( skin->parentWidget()->geometry().contains(gp) )
+ mouseRecipient = skin;
+ else
+ mouseRecipient = 0;
+ }
+ if ( mouseRecipient ) {
+ setPos(gp);
+ QMouseEvent me(e->type(),mouseRecipient==skin ? sp : vp,gp,e->button(),e->buttons(),e->modifiers());
+ QApplication::sendEvent(mouseRecipient, &me);
+ } else if ( !skin->parentWidget()->geometry().contains(gp) ) {
+ hide();
+ } else {
+ setPos(gp);
+ }
+ if ( e->type() == QEvent::MouseButtonRelease )
+ mouseRecipient = 0;
+ handledEvent = true;
+ }
+ }
+ inhere--;
+ }
+ return handledEvent;
+}
+
+void CursorWindow::setView(QWidget* v)
+{
+ if ( m_view ) {
+ m_view->removeEventFilter(this);
+ m_view->removeEventFilter(this);
+ }
+ m_view = v;
+ m_view->installEventFilter(this);
+ m_view->installEventFilter(this);
+ mouseRecipient = 0;
+}
+
+CursorWindow::CursorWindow(const QImage &img, QPoint hot, QWidget* sk)
+ :QWidget(0),
+ m_view(0), skin(sk),
+ hotspot(hot)
+{
+ setWindowFlags( Qt::FramelessWindowHint );
+ mouseRecipient = 0;
+ setMouseTracking(true);
+#ifndef QT_NO_CURSOR
+ setCursor(Qt::BlankCursor);
+#endif
+ QPixmap p;
+ p = QPixmap::fromImage(img);
+ if (!p.mask()) {
+ if ( img.hasAlphaChannel() ) {
+ QBitmap bm;
+ bm = QPixmap::fromImage(img.createAlphaMask());
+ p.setMask( bm );
+ } else {
+ QBitmap bm;
+ bm = QPixmap::fromImage(img.createHeuristicMask());
+ p.setMask( bm );
+ }
+ }
+ QPalette palette;
+ palette.setBrush(backgroundRole(), QBrush(p));
+ setPalette(palette);
+ setFixedSize( p.size() );
+ if ( !p.mask().isNull() )
+ setMask( p.mask() );
+}
+
+void CursorWindow::setPos(QPoint p)
+{
+ move(p-hotspot);
+ show();
+ raise();
+}
+}
+
+#ifdef TEST_SKIN
+
+int main(int argc,char *argv[])
+{
+ if (argc < 1)
+ return 1;
+ const QString skinFile = QString::fromUtf8(argv[1]);
+ QApplication app(argc,argv);
+ QMainWindow mw;
+
+ DeviceSkinParameters params;
+ QString errorMessage;
+ if (!params.read(skinFile, DeviceSkinParameters::ReadAll, &errorMessage)) {
+ qWarning() << errorMessage;
+ return 1;
+ }
+ DeviceSkin ds(params, &mw);
+ // View Dialog
+ QDialog *dialog = new QDialog();
+ QHBoxLayout *dialogLayout = new QHBoxLayout();
+ dialog->setLayout(dialogLayout);
+ QDialogButtonBox *dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
+ QObject::connect(dialogButtonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
+ QObject::connect(dialogButtonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
+ dialogLayout->addWidget(dialogButtonBox);
+ dialog->setFixedSize(params.screenSize());
+ dialog->setParent(&ds, Qt::SubWindow);
+ dialog->setAutoFillBackground(true);
+ ds.setView(dialog);
+
+ QObject::connect(&ds, SIGNAL(popupMenu()), &mw, SLOT(close()));
+ QObject::connect(&ds, SIGNAL(skinKeyPressEvent(int,QString,bool)), &mw, SLOT(close()));
+ mw.show();
+ return app.exec();
+}
+
+#endif
+
+QT_END_NAMESPACE
+
diff --git a/tools/shared/deviceskin/deviceskin.h b/tools/shared/deviceskin/deviceskin.h
new file mode 100644
index 0000000000..8f3fefd556
--- /dev/null
+++ b/tools/shared/deviceskin/deviceskin.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SKIN_H
+#define SKIN_H
+
+#include <QtGui/QWidget>
+#include <QtGui/QPolygon>
+#include <QtGui/QRegion>
+#include <QtGui/QPixmap>
+#include <QtCore/QVector>
+
+QT_BEGIN_NAMESPACE
+
+namespace qvfb_internal {
+ class CursorWindow;
+}
+
+class QTextStream;
+
+// ------- Button Area
+struct DeviceSkinButtonArea {
+ DeviceSkinButtonArea();
+ QString name;
+ int keyCode;
+ QPolygon area;
+ QString text;
+ bool activeWhenClosed;
+ bool toggleArea;
+ bool toggleActiveArea;
+};
+
+// -------- Parameters
+struct DeviceSkinParameters {
+ enum ReadMode { ReadAll, ReadSizeOnly };
+ bool read(const QString &skinDirectory, ReadMode rm, QString *errorMessage);
+ bool read(QTextStream &ts, ReadMode rm, QString *errorMessage);
+
+ QSize screenSize() const { return screenRect.size(); }
+ QSize secondaryScreenSize() const;
+ bool hasSecondaryScreen() const;
+
+ QString skinImageUpFileName;
+ QString skinImageDownFileName;
+ QString skinImageClosedFileName;
+ QString skinCursorFileName;
+
+ QImage skinImageUp;
+ QImage skinImageDown;
+ QImage skinImageClosed;
+ QImage skinCursor;
+
+ QRect screenRect;
+ QRect backScreenRect;
+ QRect closedScreenRect;
+ int screenDepth;
+ QPoint cursorHot;
+ QVector<DeviceSkinButtonArea> buttonAreas;
+ QList<int> toggleAreaList;
+
+ int joystick;
+ QString prefix;
+ bool hasMouseHover;
+};
+
+// --------- Skin Widget
+class DeviceSkin : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit DeviceSkin(const DeviceSkinParameters &parameters, QWidget *p );
+ ~DeviceSkin( );
+
+ QWidget *view() const { return m_view; }
+ void setView( QWidget *v );
+
+ QWidget *secondaryView() const { return m_secondaryView; }
+ void setSecondaryView( QWidget *v );
+
+ void setZoom( double );
+ void setTransform( const QMatrix& );
+
+ bool hasCursor() const;
+
+ QString prefix() const {return m_parameters.prefix;}
+
+signals:
+ void popupMenu();
+ void skinKeyPressEvent(int code, const QString& text, bool autorep);
+ void skinKeyReleaseEvent(int code, const QString& text, bool autorep);
+
+protected slots:
+ void skinKeyRepeat();
+ void moveParent();
+
+protected:
+ virtual void paintEvent( QPaintEvent * );
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+
+private:
+ void calcRegions();
+ void flip(bool open);
+ void updateSecondaryScreen();
+ void loadImages();
+ void startPress(int);
+ void endPress();
+
+ const DeviceSkinParameters m_parameters;
+ QVector<QRegion> buttonRegions;
+ QPixmap skinImageUp;
+ QPixmap skinImageDown;
+ QPixmap skinImageClosed;
+ QPixmap skinCursor;
+ QWidget *parent;
+ QWidget *m_view;
+ QWidget *m_secondaryView;
+ QPoint parentpos;
+ QPoint clickPos;
+ bool buttonPressed;
+ int buttonIndex;
+ QMatrix transform;
+ qvfb_internal::CursorWindow *cursorw;
+
+ bool joydown;
+ QTimer *t_skinkey;
+ QTimer *t_parentmove;
+ int onjoyrelease;
+
+ bool flipped_open;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/deviceskin/deviceskin.pri b/tools/shared/deviceskin/deviceskin.pri
new file mode 100644
index 0000000000..e4c9ef75a8
--- /dev/null
+++ b/tools/shared/deviceskin/deviceskin.pri
@@ -0,0 +1,3 @@
+INCLUDEPATH += $$PWD
+HEADERS += $$PWD/deviceskin.h
+SOURCES += $$PWD/deviceskin.cpp
diff --git a/tools/shared/findwidget/abstractfindwidget.cpp b/tools/shared/findwidget/abstractfindwidget.cpp
new file mode 100644
index 0000000000..e52722c218
--- /dev/null
+++ b/tools/shared/findwidget/abstractfindwidget.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class AbstractFindWidget
+
+ \brief A search bar that is commonly added below a searchable widget.
+
+ \internal
+
+ This widget implements a search bar which becomes visible when the user
+ wants to start searching. It is a modern replacement for the commonly used
+ search dialog. It is usually placed below the target widget using a QVBoxLayout.
+
+ The search is incremental and can be set to case sensitive or whole words
+ using buttons available on the search bar.
+ */
+
+#include "abstractfindwidget.h"
+
+#include <QtCore/QEvent>
+#include <QtCore/QFile>
+#include <QtCore/QTimer>
+
+#include <QtGui/QCheckBox>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QLabel>
+#include <QtGui/QLayout>
+#include <QtGui/QLineEdit>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+static QIcon createIconSet(const QString &name)
+{
+ QStringList candidates = QStringList()
+ << (QString::fromUtf8(":/trolltech/shared/images/") + name)
+#ifdef Q_WS_MAC
+ << (QString::fromUtf8(":/trolltech/shared/images/mac/") + name);
+#else
+ << (QString::fromUtf8(":/trolltech/shared/images/win/") + name);
+#endif
+
+ foreach (const QString &f, candidates) {
+ if (QFile::exists(f))
+ return QIcon(f);
+ }
+
+ return QIcon();
+}
+
+/*!
+ Constructs an AbstractFindWidget.
+
+ \a flags can change the layout and turn off certain features.
+ \a parent is passed to the QWidget constructor.
+ */
+AbstractFindWidget::AbstractFindWidget(FindFlags flags, QWidget *parent)
+ : QWidget(parent)
+{
+ QBoxLayout *topLayOut;
+ QBoxLayout *layOut;
+ if (flags & NarrowLayout) {
+ topLayOut = new QVBoxLayout(this);
+ layOut = new QHBoxLayout;
+ topLayOut->addLayout(layOut);
+ } else {
+ topLayOut = layOut = new QHBoxLayout(this);
+ }
+#ifndef Q_OS_MAC
+ topLayOut->setSpacing(6);
+ topLayOut->setMargin(0);
+#endif
+
+ m_toolClose = new QToolButton(this);
+ m_toolClose->setIcon(createIconSet(QLatin1String("closetab.png")));
+ m_toolClose->setAutoRaise(true);
+ layOut->addWidget(m_toolClose);
+ connect(m_toolClose, SIGNAL(clicked()), SLOT(deactivate()));
+
+ m_editFind = new QLineEdit(this);
+ layOut->addWidget(m_editFind);
+ connect(m_editFind, SIGNAL(returnPressed()), SLOT(findNext()));
+ connect(m_editFind, SIGNAL(textChanged(QString)), SLOT(findCurrentText()));
+ connect(m_editFind, SIGNAL(textChanged(QString)), SLOT(updateButtons()));
+
+ m_toolPrevious = new QToolButton(this);
+ m_toolPrevious->setAutoRaise(true);
+ m_toolPrevious->setText(tr("&Previous"));
+ m_toolPrevious->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_toolPrevious->setIcon(createIconSet(QLatin1String("previous.png")));
+ layOut->addWidget(m_toolPrevious);
+ connect(m_toolPrevious, SIGNAL(clicked()), SLOT(findPrevious()));
+
+ m_toolNext = new QToolButton(this);
+ m_toolNext->setAutoRaise(true);
+ m_toolNext->setText(tr("&Next"));
+ m_toolNext->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_toolNext->setIcon(createIconSet(QLatin1String("next.png")));
+ layOut->addWidget(m_toolNext);
+ connect(m_toolNext, SIGNAL(clicked()), SLOT(findNext()));
+
+ if (flags & NarrowLayout) {
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ m_toolPrevious->setSizePolicy(sp);
+ m_toolPrevious->setMinimumWidth(m_toolPrevious->minimumSizeHint().height());
+ m_toolNext->setSizePolicy(sp);
+ m_toolNext->setMinimumWidth(m_toolNext->minimumSizeHint().height());
+
+ QSpacerItem *spacerItem =
+ new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ layOut->addItem(spacerItem);
+
+ layOut = new QHBoxLayout;
+ topLayOut->addLayout(layOut);
+ } else {
+ m_editFind->setMinimumWidth(150);
+ }
+
+ if (!(flags & NoCaseSensitive)) {
+ m_checkCase = new QCheckBox(tr("&Case sensitive"), this);
+ layOut->addWidget(m_checkCase);
+ connect(m_checkCase, SIGNAL(toggled(bool)), SLOT(findCurrentText()));
+ } else {
+ m_checkCase = 0;
+ }
+
+ if (!(flags & NoWholeWords)) {
+ m_checkWholeWords = new QCheckBox(tr("Whole &words"), this);
+ layOut->addWidget(m_checkWholeWords);
+ connect(m_checkWholeWords, SIGNAL(toggled(bool)), SLOT(findCurrentText()));
+ } else {
+ m_checkWholeWords = 0;
+ }
+
+ m_labelWrapped = new QLabel(this);
+ m_labelWrapped->setTextFormat(Qt::RichText);
+ m_labelWrapped->setAlignment(
+ Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);
+ m_labelWrapped->setText(
+ tr("<img src=\":/trolltech/shared/images/wrap.png\">"
+ "&nbsp;Search wrapped"));
+ m_labelWrapped->hide();
+ layOut->addWidget(m_labelWrapped);
+
+ QSpacerItem *spacerItem =
+ new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ layOut->addItem(spacerItem);
+
+ setMinimumWidth(minimumSizeHint().width());
+
+ updateButtons();
+ hide();
+}
+
+/*!
+ Destroys the AbstractFindWidget.
+ */
+AbstractFindWidget::~AbstractFindWidget()
+{
+}
+
+/*!
+ Returns the icon set to be used for the action that initiates a search.
+ */
+QIcon AbstractFindWidget::findIconSet()
+{
+ return createIconSet(QLatin1String("searchfind.png"));
+}
+
+/*!
+ Activates the find widget, making it visible and having focus on its input
+ field.
+ */
+void AbstractFindWidget::activate()
+{
+ show();
+ m_editFind->selectAll();
+ m_editFind->setFocus(Qt::ShortcutFocusReason);
+}
+
+/*!
+ Deactivates the find widget, making it invisible and handing focus to any
+ associated QTextEdit.
+ */
+void AbstractFindWidget::deactivate()
+{
+ hide();
+}
+
+void AbstractFindWidget::findNext()
+{
+ findInternal(m_editFind->text(), true, false);
+}
+
+void AbstractFindWidget::findPrevious()
+{
+ findInternal(m_editFind->text(), true, true);
+}
+
+void AbstractFindWidget::findCurrentText()
+{
+ findInternal(m_editFind->text(), false, false);
+}
+
+void AbstractFindWidget::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Escape) {
+ deactivate();
+ return;
+ }
+
+ QWidget::keyPressEvent(event);
+}
+
+void AbstractFindWidget::updateButtons()
+{
+ const bool en = !m_editFind->text().isEmpty();
+ m_toolPrevious->setEnabled(en);
+ m_toolNext->setEnabled(en);
+}
+
+void AbstractFindWidget::findInternal(const QString &ttf, bool skipCurrent, bool backward)
+{
+ bool found = false;
+ bool wrapped = false;
+ find(ttf, skipCurrent, backward, &found, &wrapped);
+ QPalette p;
+ p.setColor(QPalette::Active, QPalette::Base, found ? Qt::white : QColor(255, 102, 102));
+ m_editFind->setPalette(p);
+ m_labelWrapped->setVisible(wrapped);
+}
+
+bool AbstractFindWidget::caseSensitive() const
+{
+ return m_checkCase && m_checkCase->isChecked();
+}
+
+bool AbstractFindWidget::wholeWords() const
+{
+ return m_checkWholeWords && m_checkWholeWords->isChecked();
+}
+
+bool AbstractFindWidget::eventFilter(QObject *object, QEvent *e)
+{
+ if (isVisible() && e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Escape) {
+ hide();
+ return true;
+ }
+ }
+
+ return QWidget::eventFilter(object, e);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/findwidget/abstractfindwidget.h b/tools/shared/findwidget/abstractfindwidget.h
new file mode 100644
index 0000000000..fe0c9325ea
--- /dev/null
+++ b/tools/shared/findwidget/abstractfindwidget.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTFINDWIDGET_H
+#define ABSTRACTFINDWIDGET_H
+
+#include <QtGui/QIcon>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QCheckBox;
+class QEvent;
+class QKeyEvent;
+class QLabel;
+class QLineEdit;
+class QObject;
+class QToolButton;
+
+class AbstractFindWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ enum FindFlag {
+ /// Use a layout that is roughly half as wide and twice as high as the regular one.
+ NarrowLayout = 1,
+ /// Do not show the "Whole words" checkbox.
+ NoWholeWords = 2,
+ /// Do not show the "Case sensitive" checkbox.
+ NoCaseSensitive = 4
+ };
+ Q_DECLARE_FLAGS(FindFlags, FindFlag)
+
+ AbstractFindWidget(FindFlags flags = FindFlags(), QWidget *parent = 0);
+ virtual ~AbstractFindWidget();
+
+ bool eventFilter(QObject *object, QEvent *e);
+
+ static QIcon findIconSet();
+
+public slots:
+ void activate();
+ virtual void deactivate();
+ void findNext();
+ void findPrevious();
+ void findCurrentText();
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+
+private slots:
+ void updateButtons();
+
+protected:
+ virtual void find(const QString &textToFind, bool skipCurrent, bool backward, bool *found, bool *wrapped) = 0;
+
+ bool caseSensitive() const;
+ bool wholeWords() const;
+
+private:
+ void findInternal(const QString &textToFind, bool skipCurrent, bool backward);
+
+ QLineEdit *m_editFind;
+ QLabel *m_labelWrapped;
+ QToolButton *m_toolNext;
+ QToolButton *m_toolClose;
+ QToolButton *m_toolPrevious;
+ QCheckBox *m_checkCase;
+ QCheckBox *m_checkWholeWords;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractFindWidget::FindFlags)
+
+QT_END_NAMESPACE
+
+#endif // ABSTRACTFINDWIDGET_H
diff --git a/tools/shared/findwidget/findwidget.pri b/tools/shared/findwidget/findwidget.pri
new file mode 100644
index 0000000000..6e0f58affb
--- /dev/null
+++ b/tools/shared/findwidget/findwidget.pri
@@ -0,0 +1,4 @@
+INCLUDEPATH += $$PWD
+HEADERS += $$PWD/abstractfindwidget.h $$PWD/texteditfindwidget.h $$PWD/itemviewfindwidget.h
+SOURCES += $$PWD/abstractfindwidget.cpp $$PWD/texteditfindwidget.cpp $$PWD/itemviewfindwidget.cpp
+RESOURCES += $$PWD/findwidget.qrc
diff --git a/tools/shared/findwidget/findwidget.qrc b/tools/shared/findwidget/findwidget.qrc
new file mode 100644
index 0000000000..1d45b25dd2
--- /dev/null
+++ b/tools/shared/findwidget/findwidget.qrc
@@ -0,0 +1,14 @@
+<RCC>
+ <qresource prefix="/trolltech/shared">
+ <file>images/mac/closetab.png</file>
+ <file>images/mac/next.png</file>
+ <file>images/mac/previous.png</file>
+ <file>images/mac/searchfind.png</file>
+ <file>images/win/closetab.png</file>
+ <file>images/win/next.png</file>
+ <file>images/win/previous.png</file>
+ <file>images/win/searchfind.png</file>
+ <file>images/wrap.png</file>
+ </qresource>
+</RCC>
+
diff --git a/tools/shared/findwidget/images/mac/closetab.png b/tools/shared/findwidget/images/mac/closetab.png
new file mode 100644
index 0000000000..ab9d669eee
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/closetab.png
Binary files differ
diff --git a/tools/shared/findwidget/images/mac/next.png b/tools/shared/findwidget/images/mac/next.png
new file mode 100644
index 0000000000..a585cab80c
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/next.png
Binary files differ
diff --git a/tools/shared/findwidget/images/mac/previous.png b/tools/shared/findwidget/images/mac/previous.png
new file mode 100644
index 0000000000..612fb34dce
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/previous.png
Binary files differ
diff --git a/tools/shared/findwidget/images/mac/searchfind.png b/tools/shared/findwidget/images/mac/searchfind.png
new file mode 100644
index 0000000000..3561745f01
--- /dev/null
+++ b/tools/shared/findwidget/images/mac/searchfind.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/closetab.png b/tools/shared/findwidget/images/win/closetab.png
new file mode 100644
index 0000000000..ef9e02086c
--- /dev/null
+++ b/tools/shared/findwidget/images/win/closetab.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/next.png b/tools/shared/findwidget/images/win/next.png
new file mode 100644
index 0000000000..8df4127a00
--- /dev/null
+++ b/tools/shared/findwidget/images/win/next.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/previous.png b/tools/shared/findwidget/images/win/previous.png
new file mode 100644
index 0000000000..0780bc23dd
--- /dev/null
+++ b/tools/shared/findwidget/images/win/previous.png
Binary files differ
diff --git a/tools/shared/findwidget/images/win/searchfind.png b/tools/shared/findwidget/images/win/searchfind.png
new file mode 100644
index 0000000000..6ea35e930d
--- /dev/null
+++ b/tools/shared/findwidget/images/win/searchfind.png
Binary files differ
diff --git a/tools/shared/findwidget/images/wrap.png b/tools/shared/findwidget/images/wrap.png
new file mode 100644
index 0000000000..90f18d9f77
--- /dev/null
+++ b/tools/shared/findwidget/images/wrap.png
Binary files differ
diff --git a/tools/shared/findwidget/itemviewfindwidget.cpp b/tools/shared/findwidget/itemviewfindwidget.cpp
new file mode 100644
index 0000000000..e1f84689e5
--- /dev/null
+++ b/tools/shared/findwidget/itemviewfindwidget.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class ItemViewFindWidget
+
+ \brief A search bar that is commonly added below the searchable item view.
+
+ \internal
+
+ This widget implements a search bar which becomes visible when the user
+ wants to start searching. It is a modern replacement for the commonly used
+ search dialog. It is usually placed below a QAbstractItemView using a QVBoxLayout.
+
+ The QAbstractItemView instance will need to be associated with this class using
+ setItemView().
+
+ The search is incremental and can be set to case sensitive or whole words
+ using buttons available on the search bar.
+
+ The item traversal order should fit QTreeView, QTableView and QListView alike.
+ More complex tree structures will work as well, assuming the branch structure
+ is painted left to the items, without crossing lines.
+
+ \sa QAbstractItemView
+ */
+
+#include "itemviewfindwidget.h"
+
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QCheckBox>
+#include <QtGui/QTreeView>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a ItemViewFindWidget.
+
+ \a flags is passed to the AbstractFindWidget constructor.
+ \a parent is passed to the QWidget constructor.
+ */
+ItemViewFindWidget::ItemViewFindWidget(FindFlags flags, QWidget *parent)
+ : AbstractFindWidget(flags, parent)
+ , m_itemView(0)
+{
+}
+
+/*!
+ Associates a QAbstractItemView with this find widget. Searches done using this find
+ widget will then apply to the given QAbstractItemView.
+
+ An event filter is set on the QAbstractItemView which intercepts the ESC key while
+ the find widget is active, and uses it to deactivate the find widget.
+
+ If the find widget is already associated with a QAbstractItemView, the event filter
+ is removed from this QAbstractItemView first.
+
+ \a itemView may be NULL.
+ */
+void ItemViewFindWidget::setItemView(QAbstractItemView *itemView)
+{
+ if (m_itemView)
+ m_itemView->removeEventFilter(this);
+
+ m_itemView = itemView;
+
+ if (m_itemView)
+ m_itemView->installEventFilter(this);
+}
+
+/*!
+ \reimp
+ */
+void ItemViewFindWidget::deactivate()
+{
+ if (m_itemView)
+ m_itemView->setFocus();
+
+ AbstractFindWidget::deactivate();
+}
+
+// Sorting is needed to find the start/end of the selection.
+// This is utter black magic. And it is damn slow.
+static bool indexLessThan(const QModelIndex &a, const QModelIndex &b)
+{
+ // First determine the nesting of each index in the tree.
+ QModelIndex aa = a;
+ int aDepth = 0;
+ while (aa.parent() != QModelIndex()) {
+ // As a side effect, check if one of the items is the parent of the other.
+ // Children are always displayed below their parents, so sort them further down.
+ if (aa.parent() == b)
+ return true;
+ aa = aa.parent();
+ aDepth++;
+ }
+ QModelIndex ba = b;
+ int bDepth = 0;
+ while (ba.parent() != QModelIndex()) {
+ if (ba.parent() == a)
+ return false;
+ ba = ba.parent();
+ bDepth++;
+ }
+ // Now find indices at comparable depth.
+ for (aa = a; aDepth > bDepth; aDepth--)
+ aa = aa.parent();
+ for (ba = b; aDepth < bDepth; bDepth--)
+ ba = ba.parent();
+ // If they have the same parent, sort them within a top-to-bottom, left-to-right rectangle.
+ if (aa.parent() == ba.parent()) {
+ if (aa.row() < ba.row())
+ return true;
+ if (aa.row() > ba.row())
+ return false;
+ return aa.column() < ba.column();
+ }
+ // Now try to find indices that have the same grandparent. This ends latest at the root node.
+ while (aa.parent().parent() != ba.parent().parent()) {
+ aa = aa.parent();
+ ba = ba.parent();
+ }
+ // A bigger row is always displayed further down.
+ if (aa.parent().row() < ba.parent().row())
+ return true;
+ if (aa.parent().row() > ba.parent().row())
+ return false;
+ // Here's the trick: a child spawned from a bigger column is displayed further *up*.
+ // That's because the tree lines are on the left and are supposed not to cross each other.
+ // This case is mostly academical, as "all" models spawn children from the first column.
+ return aa.parent().column() > ba.parent().column();
+}
+
+/*!
+ \reimp
+ */
+void ItemViewFindWidget::find(const QString &ttf, bool skipCurrent, bool backward, bool *found, bool *wrapped)
+{
+ if (!m_itemView || !m_itemView->model()->hasChildren())
+ return;
+
+ QModelIndex idx;
+ if (skipCurrent && m_itemView->selectionModel()->hasSelection()) {
+ QModelIndexList il = m_itemView->selectionModel()->selectedIndexes();
+ qSort(il.begin(), il.end(), indexLessThan);
+ idx = backward ? il.first() : il.last();
+ } else {
+ idx = m_itemView->currentIndex();
+ }
+
+ *found = true;
+ QModelIndex newIdx = idx;
+
+ if (!ttf.isEmpty()) {
+ if (newIdx.isValid()) {
+ int column = newIdx.column();
+ if (skipCurrent)
+ if (QTreeView *tv = qobject_cast<QTreeView *>(m_itemView))
+ if (tv->allColumnsShowFocus())
+ column = backward ? 0 : m_itemView->model()->columnCount(newIdx.parent()) - 1;
+ newIdx = findHelper(ttf, skipCurrent, backward,
+ newIdx.parent(), newIdx.row(), column);
+ }
+ if (!newIdx.isValid()) {
+ int row = backward ? m_itemView->model()->rowCount() : 0;
+ int column = backward ? 0 : -1;
+ newIdx = findHelper(ttf, true, backward, m_itemView->rootIndex(), row, column);
+ if (!newIdx.isValid()) {
+ *found = false;
+ newIdx = idx;
+ } else {
+ *wrapped = true;
+ }
+ }
+ }
+
+ if (!isVisible())
+ show();
+
+ m_itemView->setCurrentIndex(newIdx);
+}
+
+// You are not expected to understand the following two functions.
+// The traversal order is described in the indexLessThan() comments above.
+
+static inline bool skipForward(const QAbstractItemModel *model, QModelIndex &parent, int &row, int &column)
+{
+ forever {
+ column++;
+ if (column < model->columnCount(parent))
+ return true;
+ forever {
+ while (--column >= 0) {
+ QModelIndex nIdx = model->index(row, column, parent);
+ if (nIdx.isValid()) {
+ if (model->hasChildren(nIdx)) {
+ row = 0;
+ column = 0;
+ parent = nIdx;
+ return true;
+ }
+ }
+ }
+ if (++row < model->rowCount(parent))
+ break;
+ if (!parent.isValid())
+ return false;
+ row = parent.row();
+ column = parent.column();
+ parent = parent.parent();
+ }
+ }
+}
+
+static inline bool skipBackward(const QAbstractItemModel *model, QModelIndex &parent, int &row, int &column)
+{
+ column--;
+ if (column == -1) {
+ if (--row < 0) {
+ if (!parent.isValid())
+ return false;
+ row = parent.row();
+ column = parent.column();
+ parent = parent.parent();
+ }
+ while (++column < model->columnCount(parent)) {
+ QModelIndex nIdx = model->index(row, column, parent);
+ if (nIdx.isValid()) {
+ if (model->hasChildren(nIdx)) {
+ row = model->rowCount(nIdx) - 1;
+ column = -1;
+ parent = nIdx;
+ }
+ }
+ }
+ column--;
+ }
+ return true;
+}
+
+// QAbstractItemModel::match() does not support backwards searching. Still using it would
+// be just a bit inefficient (not much worse than when no match is found).
+// The bigger problem is that QAbstractItemView does not provide a method to sort a
+// set of indices in traversal order (to find the start and end of the selection).
+// Consequently, we do everything by ourselves to be consistent. Of course, this puts
+// constraints on the allowable visualizations.
+QModelIndex ItemViewFindWidget::findHelper(const QString &textToFind, bool skipCurrent, bool backward,
+ QModelIndex parent, int row, int column)
+{
+ const QAbstractItemModel *model = m_itemView->model();
+ forever {
+ if (skipCurrent) {
+ if (backward) {
+ if (!skipBackward(model, parent, row, column))
+ return QModelIndex();
+ } else {
+ if (!skipForward(model, parent, row, column))
+ return QModelIndex();
+ }
+ }
+
+ QModelIndex idx = model->index(row, column, parent);
+ if (idx.isValid()) {
+ Qt::CaseSensitivity cs = caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive;
+
+ if (wholeWords()) {
+ QString rx = QLatin1String("\\b") + QRegExp::escape(textToFind) + QLatin1String("\\b");
+ if (idx.data().toString().indexOf(QRegExp(rx, cs)) >= 0)
+ return idx;
+ } else {
+ if (idx.data().toString().indexOf(textToFind, 0, cs) >= 0)
+ return idx;
+ }
+ }
+
+ skipCurrent = true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/findwidget/itemviewfindwidget.h b/tools/shared/findwidget/itemviewfindwidget.h
new file mode 100644
index 0000000000..71bb8f636c
--- /dev/null
+++ b/tools/shared/findwidget/itemviewfindwidget.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ITEMVIEWFINDWIDGET_H
+#define ITEMVIEWFINDWIDGET_H
+
+#include "abstractfindwidget.h"
+
+#include <QModelIndex>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractItemView;
+
+class ItemViewFindWidget : public AbstractFindWidget
+{
+ Q_OBJECT
+
+public:
+ ItemViewFindWidget(FindFlags flags = FindFlags(), QWidget *parent = 0);
+
+ QAbstractItemView *itemView() const
+ { return m_itemView; }
+
+ void setItemView(QAbstractItemView *itemView);
+
+protected:
+ virtual void deactivate();
+ virtual void find(const QString &textToFind, bool skipCurrent, bool backward, bool *found, bool *wrapped);
+
+private:
+ QModelIndex findHelper(const QString &textToFind, bool skipCurrent, bool backward,
+ QModelIndex parent, int row, int column);
+
+ QAbstractItemView *m_itemView;
+};
+
+QT_END_NAMESPACE
+
+#endif // ITEMVIEWFINDWIDGET_H
diff --git a/tools/shared/findwidget/texteditfindwidget.cpp b/tools/shared/findwidget/texteditfindwidget.cpp
new file mode 100644
index 0000000000..73100f5402
--- /dev/null
+++ b/tools/shared/findwidget/texteditfindwidget.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*! \class TextEditFindWidget
+
+ \brief A search bar that is commonly added below the searchable text.
+
+ \internal
+
+ This widget implements a search bar which becomes visible when the user
+ wants to start searching. It is a modern replacement for the commonly used
+ search dialog. It is usually placed below a QTextEdit using a QVBoxLayout.
+
+ The QTextEdit instance will need to be associated with this class using
+ setTextEdit().
+
+ The search is incremental and can be set to case sensitive or whole words
+ using buttons available on the search bar.
+
+ \sa QTextEdit
+ */
+
+#include "texteditfindwidget.h"
+
+#include <QtGui/QCheckBox>
+#include <QtGui/QTextCursor>
+#include <QtGui/QTextEdit>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a TextEditFindWidget.
+
+ \a flags is passed to the AbstractFindWidget constructor.
+ \a parent is passed to the QWidget constructor.
+ */
+TextEditFindWidget::TextEditFindWidget(FindFlags flags, QWidget *parent)
+ : AbstractFindWidget(flags, parent)
+ , m_textEdit(0)
+{
+}
+
+/*!
+ Associates a QTextEdit with this find widget. Searches done using this find
+ widget will then apply to the given QTextEdit.
+
+ An event filter is set on the QTextEdit which intercepts the ESC key while
+ the find widget is active, and uses it to deactivate the find widget.
+
+ If the find widget is already associated with a QTextEdit, the event filter
+ is removed from this QTextEdit first.
+
+ \a textEdit may be NULL.
+ */
+void TextEditFindWidget::setTextEdit(QTextEdit *textEdit)
+{
+ if (m_textEdit)
+ m_textEdit->removeEventFilter(this);
+
+ m_textEdit = textEdit;
+
+ if (m_textEdit)
+ m_textEdit->installEventFilter(this);
+}
+
+/*!
+ \reimp
+ */
+void TextEditFindWidget::deactivate()
+{
+ // Pass focus to the text edit
+ if (m_textEdit)
+ m_textEdit->setFocus();
+
+ AbstractFindWidget::deactivate();
+}
+
+/*!
+ \reimp
+ */
+void TextEditFindWidget::find(const QString &ttf, bool skipCurrent, bool backward, bool *found, bool *wrapped)
+{
+ if (!m_textEdit)
+ return;
+
+ QTextCursor cursor = m_textEdit->textCursor();
+ QTextDocument *doc = m_textEdit->document();
+
+ if (!doc || cursor.isNull())
+ return;
+
+ if (cursor.hasSelection())
+ cursor.setPosition((skipCurrent && !backward) ? cursor.position() : cursor.anchor());
+
+ *found = true;
+ QTextCursor newCursor = cursor;
+
+ if (!ttf.isEmpty()) {
+ QTextDocument::FindFlags options;
+
+ if (backward)
+ options |= QTextDocument::FindBackward;
+
+ if (caseSensitive())
+ options |= QTextDocument::FindCaseSensitively;
+
+ if (wholeWords())
+ options |= QTextDocument::FindWholeWords;
+
+ newCursor = doc->find(ttf, cursor, options);
+ if (newCursor.isNull()) {
+ QTextCursor ac(doc);
+ ac.movePosition(options & QTextDocument::FindBackward
+ ? QTextCursor::End : QTextCursor::Start);
+ newCursor = doc->find(ttf, ac, options);
+ if (newCursor.isNull()) {
+ *found = false;
+ newCursor = cursor;
+ } else {
+ *wrapped = true;
+ }
+ }
+ }
+
+ if (!isVisible())
+ show();
+
+ m_textEdit->setTextCursor(newCursor);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/findwidget/texteditfindwidget.h b/tools/shared/findwidget/texteditfindwidget.h
new file mode 100644
index 0000000000..4074ff0050
--- /dev/null
+++ b/tools/shared/findwidget/texteditfindwidget.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TEXTEDITFINDWIDGET_H
+#define TEXTEDITFINDWIDGET_H
+
+#include "abstractfindwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTextEdit;
+
+class TextEditFindWidget : public AbstractFindWidget
+{
+ Q_OBJECT
+
+public:
+ TextEditFindWidget(FindFlags flags = FindFlags(), QWidget *parent = 0);
+
+ QTextEdit *textEdit() const
+ { return m_textEdit; }
+
+ void setTextEdit(QTextEdit *textEdit);
+
+protected:
+ virtual void deactivate();
+ virtual void find(const QString &textToFind, bool skipCurrent, bool backward, bool *found, bool *wrapped);
+
+private:
+ QTextEdit *m_textEdit;
+};
+
+QT_END_NAMESPACE
+
+#endif // TEXTEDITFINDWIDGET_H
diff --git a/tools/shared/fontpanel/fontpanel.cpp b/tools/shared/fontpanel/fontpanel.cpp
new file mode 100644
index 0000000000..4545baadfd
--- /dev/null
+++ b/tools/shared/fontpanel/fontpanel.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "fontpanel.h"
+
+#include <QtGui/QLabel>
+#include <QtGui/QComboBox>
+#include <QtGui/QFormLayout>
+#include <QtGui/QSpacerItem>
+#include <QtGui/QFontComboBox>
+#include <QtCore/QTimer>
+#include <QtGui/QLineEdit>
+
+QT_BEGIN_NAMESPACE
+
+FontPanel::FontPanel(QWidget *parentWidget) :
+ QGroupBox(parentWidget),
+ m_previewLineEdit(new QLineEdit),
+ m_writingSystemComboBox(new QComboBox),
+ m_familyComboBox(new QFontComboBox),
+ m_styleComboBox(new QComboBox),
+ m_pointSizeComboBox(new QComboBox),
+ m_previewFontUpdateTimer(0)
+{
+ setTitle(tr("Font"));
+
+ QFormLayout *formLayout = new QFormLayout(this);
+ // writing systems
+ m_writingSystemComboBox->setEditable(false);
+
+ QList<QFontDatabase::WritingSystem> writingSystems = m_fontDatabase.writingSystems();
+ writingSystems.push_front(QFontDatabase::Any);
+ foreach (QFontDatabase::WritingSystem ws, writingSystems)
+ m_writingSystemComboBox->addItem(QFontDatabase::writingSystemName(ws), QVariant(ws));
+ connect(m_writingSystemComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotWritingSystemChanged(int)));
+ formLayout->addRow(tr("&Writing system"), m_writingSystemComboBox);
+
+ connect(m_familyComboBox, SIGNAL( currentFontChanged(QFont)), this, SLOT(slotFamilyChanged(QFont)));
+ formLayout->addRow(tr("&Family"), m_familyComboBox);
+
+ m_styleComboBox->setEditable(false);
+ connect(m_styleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotStyleChanged(int)));
+ formLayout->addRow(tr("&Style"), m_styleComboBox);
+
+ m_pointSizeComboBox->setEditable(false);
+ connect(m_pointSizeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPointSizeChanged(int)));
+ formLayout->addRow(tr("&Point size"), m_pointSizeComboBox);
+
+ m_previewLineEdit->setReadOnly(true);
+ formLayout->addRow(m_previewLineEdit);
+
+ setWritingSystem(QFontDatabase::Any);
+}
+
+QFont FontPanel::selectedFont() const
+{
+ QFont rc = m_familyComboBox->currentFont();
+ const QString family = rc.family();
+ rc.setPointSize(pointSize());
+ const QString styleDescription = styleString();
+ rc.setItalic(m_fontDatabase.italic(family, styleDescription));
+
+ rc.setBold(m_fontDatabase.bold(family, styleDescription));
+
+ // Weight < 0 asserts...
+ const int weight = m_fontDatabase.weight(family, styleDescription);
+ if (weight >= 0)
+ rc.setWeight(weight);
+ return rc;
+}
+
+void FontPanel::setSelectedFont(const QFont &f)
+{
+ m_familyComboBox->setCurrentFont(f);
+ if (m_familyComboBox->currentIndex() < 0) {
+ // family not in writing system - find the corresponding one?
+ QList<QFontDatabase::WritingSystem> familyWritingSystems = m_fontDatabase.writingSystems(f.family());
+ if (familyWritingSystems.empty())
+ return;
+
+ setWritingSystem(familyWritingSystems.front());
+ m_familyComboBox->setCurrentFont(f);
+ }
+
+ updateFamily(family());
+
+ const int pointSizeIndex = closestPointSizeIndex(f.pointSize());
+ m_pointSizeComboBox->setCurrentIndex( pointSizeIndex);
+
+ const QString styleString = m_fontDatabase.styleString(f);
+ const int styleIndex = m_styleComboBox->findText(styleString);
+ m_styleComboBox->setCurrentIndex(styleIndex);
+ slotUpdatePreviewFont();
+}
+
+
+QFontDatabase::WritingSystem FontPanel::writingSystem() const
+{
+ const int currentIndex = m_writingSystemComboBox->currentIndex();
+ if ( currentIndex == -1)
+ return QFontDatabase::Latin;
+ return static_cast<QFontDatabase::WritingSystem>(m_writingSystemComboBox->itemData(currentIndex).toInt());
+}
+
+QString FontPanel::family() const
+{
+ const int currentIndex = m_familyComboBox->currentIndex();
+ return currentIndex != -1 ? m_familyComboBox->currentFont().family() : QString();
+}
+
+int FontPanel::pointSize() const
+{
+ const int currentIndex = m_pointSizeComboBox->currentIndex();
+ return currentIndex != -1 ? m_pointSizeComboBox->itemData(currentIndex).toInt() : 9;
+}
+
+QString FontPanel::styleString() const
+{
+ const int currentIndex = m_styleComboBox->currentIndex();
+ return currentIndex != -1 ? m_styleComboBox->itemText(currentIndex) : QString();
+}
+
+void FontPanel::setWritingSystem(QFontDatabase::WritingSystem ws)
+{
+ m_writingSystemComboBox->setCurrentIndex(m_writingSystemComboBox->findData(QVariant(ws)));
+ updateWritingSystem(ws);
+}
+
+
+void FontPanel::slotWritingSystemChanged(int)
+{
+ updateWritingSystem(writingSystem());
+ delayedPreviewFontUpdate();
+}
+
+void FontPanel::slotFamilyChanged(const QFont &)
+{
+ updateFamily(family());
+ delayedPreviewFontUpdate();
+}
+
+void FontPanel::slotStyleChanged(int)
+{
+ updatePointSizes(family(), styleString());
+ delayedPreviewFontUpdate();
+}
+
+void FontPanel::slotPointSizeChanged(int)
+{
+ delayedPreviewFontUpdate();
+}
+
+void FontPanel::updateWritingSystem(QFontDatabase::WritingSystem ws)
+{
+
+ m_previewLineEdit->setText(QFontDatabase::writingSystemSample(ws));
+ m_familyComboBox->setWritingSystem (ws);
+ // Current font not in WS ... set index 0.
+ if (m_familyComboBox->currentIndex() < 0) {
+ m_familyComboBox->setCurrentIndex(0);
+ updateFamily(family());
+ }
+}
+
+void FontPanel::updateFamily(const QString &family)
+{
+ // Update styles and trigger update of point sizes.
+ // Try to maintain selection or select normal
+ const QString oldStyleString = styleString();
+
+ const QStringList styles = m_fontDatabase.styles(family);
+ const bool hasStyles = !styles.empty();
+
+ m_styleComboBox->setCurrentIndex(-1);
+ m_styleComboBox->clear();
+ m_styleComboBox->setEnabled(hasStyles);
+
+ int normalIndex = -1;
+ const QString normalStyle = QLatin1String("Normal");
+
+ if (hasStyles) {
+ foreach (QString style, styles) {
+ // try to maintain selection or select 'normal' preferably
+ const int newIndex = m_styleComboBox->count();
+ m_styleComboBox->addItem(style);
+ if (oldStyleString == style) {
+ m_styleComboBox->setCurrentIndex(newIndex);
+ } else {
+ if (oldStyleString == normalStyle)
+ normalIndex = newIndex;
+ }
+ }
+ if (m_styleComboBox->currentIndex() == -1 && normalIndex != -1)
+ m_styleComboBox->setCurrentIndex(normalIndex);
+ }
+ updatePointSizes(family, styleString());
+}
+
+int FontPanel::closestPointSizeIndex(int desiredPointSize) const
+{
+ // try to maintain selection or select closest.
+ int closestIndex = -1;
+ int closestAbsError = 0xFFFF;
+
+ const int pointSizeCount = m_pointSizeComboBox->count();
+ for (int i = 0; i < pointSizeCount; i++) {
+ const int itemPointSize = m_pointSizeComboBox->itemData(i).toInt();
+ const int absError = qAbs(desiredPointSize - itemPointSize);
+ if (absError < closestAbsError) {
+ closestIndex = i;
+ closestAbsError = absError;
+ if (closestAbsError == 0)
+ break;
+ } else { // past optimum
+ if (absError > closestAbsError) {
+ break;
+ }
+ }
+ }
+ return closestIndex;
+}
+
+
+void FontPanel::updatePointSizes(const QString &family, const QString &styleString)
+{
+ const int oldPointSize = pointSize();
+
+ QList<int> pointSizes = m_fontDatabase.pointSizes(family, styleString);
+ if (pointSizes.empty())
+ pointSizes = QFontDatabase::standardSizes();
+
+ const bool hasSizes = !pointSizes.empty();
+ m_pointSizeComboBox->clear();
+ m_pointSizeComboBox->setEnabled(hasSizes);
+ m_pointSizeComboBox->setCurrentIndex(-1);
+
+ // try to maintain selection or select closest.
+ if (hasSizes) {
+ QString n;
+ foreach (int pointSize, pointSizes)
+ m_pointSizeComboBox->addItem(n.setNum(pointSize), QVariant(pointSize));
+ const int closestIndex = closestPointSizeIndex(oldPointSize);
+ if (closestIndex != -1)
+ m_pointSizeComboBox->setCurrentIndex(closestIndex);
+ }
+}
+
+void FontPanel::slotUpdatePreviewFont()
+{
+ m_previewLineEdit->setFont(selectedFont());
+}
+
+void FontPanel::delayedPreviewFontUpdate()
+{
+ if (!m_previewFontUpdateTimer) {
+ m_previewFontUpdateTimer = new QTimer(this);
+ connect(m_previewFontUpdateTimer, SIGNAL(timeout()), this, SLOT(slotUpdatePreviewFont()));
+ m_previewFontUpdateTimer->setInterval(0);
+ m_previewFontUpdateTimer->setSingleShot(true);
+ }
+ if (m_previewFontUpdateTimer->isActive())
+ return;
+ m_previewFontUpdateTimer->start();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/fontpanel/fontpanel.h b/tools/shared/fontpanel/fontpanel.h
new file mode 100644
index 0000000000..0f542c6e8b
--- /dev/null
+++ b/tools/shared/fontpanel/fontpanel.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Qt tools. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef FONTPANEL_H
+#define FONTPANEL_H
+
+#include <QtGui/QGroupBox>
+#include <QtGui/QFont>
+#include <QtGui/QFontDatabase>
+
+QT_BEGIN_NAMESPACE
+
+class QComboBox;
+class QFontComboBox;
+class QTimer;
+class QLineEdit;
+
+class FontPanel: public QGroupBox
+{
+ Q_OBJECT
+public:
+ FontPanel(QWidget *parentWidget = 0);
+
+ QFont selectedFont() const;
+ void setSelectedFont(const QFont &);
+
+ QFontDatabase::WritingSystem writingSystem() const;
+ void setWritingSystem(QFontDatabase::WritingSystem ws);
+
+private slots:
+ void slotWritingSystemChanged(int);
+ void slotFamilyChanged(const QFont &);
+ void slotStyleChanged(int);
+ void slotPointSizeChanged(int);
+ void slotUpdatePreviewFont();
+
+private:
+ QString family() const;
+ QString styleString() const;
+ int pointSize() const;
+ int closestPointSizeIndex(int ps) const;
+
+ void updateWritingSystem(QFontDatabase::WritingSystem ws);
+ void updateFamily(const QString &family);
+ void updatePointSizes(const QString &family, const QString &style);
+ void delayedPreviewFontUpdate();
+
+ QFontDatabase m_fontDatabase;
+ QLineEdit *m_previewLineEdit;
+ QComboBox *m_writingSystemComboBox;
+ QFontComboBox* m_familyComboBox;
+ QComboBox *m_styleComboBox;
+ QComboBox *m_pointSizeComboBox;
+ QTimer *m_previewFontUpdateTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif // FONTPANEL_H
diff --git a/tools/shared/fontpanel/fontpanel.pri b/tools/shared/fontpanel/fontpanel.pri
new file mode 100644
index 0000000000..9504853a7d
--- /dev/null
+++ b/tools/shared/fontpanel/fontpanel.pri
@@ -0,0 +1,3 @@
+INCLUDEPATH += $$PWD
+HEADERS += $$PWD/fontpanel.h
+SOURCES += $$PWD/fontpanel.cpp
diff --git a/tools/shared/qtgradienteditor/images/down.png b/tools/shared/qtgradienteditor/images/down.png
new file mode 100644
index 0000000000..29d1d4439a
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/down.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/edit.png b/tools/shared/qtgradienteditor/images/edit.png
new file mode 100644
index 0000000000..4231bd9a90
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/edit.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/editdelete.png b/tools/shared/qtgradienteditor/images/editdelete.png
new file mode 100644
index 0000000000..df2a147d24
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/editdelete.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/minus.png b/tools/shared/qtgradienteditor/images/minus.png
new file mode 100644
index 0000000000..d6f233d739
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/minus.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/plus.png b/tools/shared/qtgradienteditor/images/plus.png
new file mode 100644
index 0000000000..40df1134f8
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/plus.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/spreadpad.png b/tools/shared/qtgradienteditor/images/spreadpad.png
new file mode 100644
index 0000000000..104c0a23d2
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/spreadpad.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/spreadreflect.png b/tools/shared/qtgradienteditor/images/spreadreflect.png
new file mode 100644
index 0000000000..17b82b711a
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/spreadreflect.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/spreadrepeat.png b/tools/shared/qtgradienteditor/images/spreadrepeat.png
new file mode 100644
index 0000000000..7aea898b1d
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/spreadrepeat.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/typeconical.png b/tools/shared/qtgradienteditor/images/typeconical.png
new file mode 100644
index 0000000000..5479811df6
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/typeconical.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/typelinear.png b/tools/shared/qtgradienteditor/images/typelinear.png
new file mode 100644
index 0000000000..dbd8a1f5a1
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/typelinear.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/typeradial.png b/tools/shared/qtgradienteditor/images/typeradial.png
new file mode 100644
index 0000000000..dc5888dca7
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/typeradial.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/up.png b/tools/shared/qtgradienteditor/images/up.png
new file mode 100644
index 0000000000..e437312217
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/up.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/zoomin.png b/tools/shared/qtgradienteditor/images/zoomin.png
new file mode 100644
index 0000000000..2e586fc7bf
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/zoomin.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/images/zoomout.png b/tools/shared/qtgradienteditor/images/zoomout.png
new file mode 100644
index 0000000000..a736d39343
--- /dev/null
+++ b/tools/shared/qtgradienteditor/images/zoomout.png
Binary files differ
diff --git a/tools/shared/qtgradienteditor/qtcolorbutton.cpp b/tools/shared/qtgradienteditor/qtcolorbutton.cpp
new file mode 100644
index 0000000000..6926f60f36
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtcolorbutton.cpp
@@ -0,0 +1,278 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtcolorbutton.h"
+#include <QtGui/QColorDialog>
+#include <QtGui/QPainter>
+#include <QtCore/QMimeData>
+#include <QtGui/QDragEnterEvent>
+#include <QtGui/QApplication>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorButtonPrivate
+{
+ QtColorButton *q_ptr;
+ Q_DECLARE_PUBLIC(QtColorButton)
+public:
+ QColor m_color;
+#ifndef QT_NO_DRAGANDDROP
+ QColor m_dragColor;
+ QPoint m_dragStart;
+ bool m_dragging;
+#endif
+ bool m_backgroundCheckered;
+
+ void slotEditColor();
+ QColor shownColor() const;
+ QPixmap generatePixmap() const;
+};
+
+void QtColorButtonPrivate::slotEditColor()
+{
+ bool ok;
+ const QRgb rgba = QColorDialog::getRgba(m_color.rgba(), &ok, q_ptr);
+ if (!ok)
+ return;
+ const QColor c = QColor::fromRgba(rgba);
+ if (c == q_ptr->color())
+ return;
+ q_ptr->setColor(c);
+ emit q_ptr->colorChanged(m_color);
+}
+
+QColor QtColorButtonPrivate::shownColor() const
+{
+#ifndef QT_NO_DRAGANDDROP
+ if (m_dragging)
+ return m_dragColor;
+#endif
+ return m_color;
+}
+
+QPixmap QtColorButtonPrivate::generatePixmap() const
+{
+ QPixmap pix(24, 24);
+
+ int pixSize = 20;
+ QBrush br(shownColor());
+
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray);
+ pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, shownColor());
+ br = QBrush(pm);
+
+ QPainter p(&pix);
+ int corr = 1;
+ QRect r = pix.rect().adjusted(corr, corr, -corr, -corr);
+ p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr);
+ p.fillRect(r, br);
+
+ p.fillRect(r.width() / 4 + corr, r.height() / 4 + corr,
+ r.width() / 2, r.height() / 2,
+ QColor(shownColor().rgb()));
+ p.drawRect(pix.rect().adjusted(0, 0, -1, -1));
+
+ return pix;
+}
+
+///////////////
+
+QtColorButton::QtColorButton(QWidget *parent)
+ : QToolButton(parent)
+{
+ d_ptr = new QtColorButtonPrivate;
+ d_ptr->q_ptr = this;
+ d_ptr->m_dragging = false;
+ d_ptr->m_backgroundCheckered = true;
+
+ setAcceptDrops(true);
+
+ connect(this, SIGNAL(clicked()), this, SLOT(slotEditColor()));
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
+}
+
+QtColorButton::~QtColorButton()
+{
+ delete d_ptr;
+}
+
+void QtColorButton::setColor(const QColor &color)
+{
+ if (d_ptr->m_color == color)
+ return;
+ d_ptr->m_color = color;
+ update();
+}
+
+QColor QtColorButton::color() const
+{
+ return d_ptr->m_color;
+}
+
+void QtColorButton::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+ d_ptr->m_backgroundCheckered = checkered;
+ update();
+}
+
+bool QtColorButton::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtColorButton::paintEvent(QPaintEvent *event)
+{
+ QToolButton::paintEvent(event);
+ if (!isEnabled())
+ return;
+
+ const int pixSize = 10;
+ QBrush br(d_ptr->shownColor());
+ if (d_ptr->m_backgroundCheckered) {
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+ pmp.fillRect(0, 0, 2 * pixSize, 2 * pixSize, d_ptr->shownColor());
+ br = QBrush(pm);
+ }
+
+ QPainter p(this);
+ const int corr = 4;
+ QRect r = rect().adjusted(corr, corr, -corr, -corr);
+ p.setBrushOrigin((r.width() % pixSize + pixSize) / 2 + corr, (r.height() % pixSize + pixSize) / 2 + corr);
+ p.fillRect(r, br);
+
+ //const int adjX = qRound(r.width() / 4.0);
+ //const int adjY = qRound(r.height() / 4.0);
+ //p.fillRect(r.adjusted(adjX, adjY, -adjX, -adjY),
+ // QColor(d_ptr->shownColor().rgb()));
+ /*
+ p.fillRect(r.adjusted(0, r.height() * 3 / 4, 0, 0),
+ QColor(d_ptr->shownColor().rgb()));
+ p.fillRect(r.adjusted(0, 0, 0, -r.height() * 3 / 4),
+ QColor(d_ptr->shownColor().rgb()));
+ */
+ /*
+ const QColor frameColor0(0, 0, 0, qRound(0.2 * (0xFF - d_ptr->shownColor().alpha())));
+ p.setPen(frameColor0);
+ p.drawRect(r.adjusted(adjX, adjY, -adjX - 1, -adjY - 1));
+ */
+
+ const QColor frameColor1(0, 0, 0, 26);
+ p.setPen(frameColor1);
+ p.drawRect(r.adjusted(1, 1, -2, -2));
+ const QColor frameColor2(0, 0, 0, 51);
+ p.setPen(frameColor2);
+ p.drawRect(r.adjusted(0, 0, -1, -1));
+}
+
+void QtColorButton::mousePressEvent(QMouseEvent *event)
+{
+#ifndef QT_NO_DRAGANDDROP
+ if (event->button() == Qt::LeftButton)
+ d_ptr->m_dragStart = event->pos();
+#endif
+ QToolButton::mousePressEvent(event);
+}
+
+void QtColorButton::mouseMoveEvent(QMouseEvent *event)
+{
+#ifndef QT_NO_DRAGANDDROP
+ if (event->buttons() & Qt::LeftButton &&
+ (d_ptr->m_dragStart - event->pos()).manhattanLength() > QApplication::startDragDistance()) {
+ QMimeData *mime = new QMimeData;
+ mime->setColorData(color());
+ QDrag *drg = new QDrag(this);
+ drg->setMimeData(mime);
+ drg->setPixmap(d_ptr->generatePixmap());
+ setDown(false);
+ event->accept();
+ drg->start();
+ return;
+ }
+#endif
+ QToolButton::mouseMoveEvent(event);
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QtColorButton::dragEnterEvent(QDragEnterEvent *event)
+{
+ const QMimeData *mime = event->mimeData();
+ if (!mime->hasColor())
+ return;
+
+ event->accept();
+ d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData());
+ d_ptr->m_dragging = true;
+ update();
+}
+
+void QtColorButton::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ event->accept();
+ d_ptr->m_dragging = false;
+ update();
+}
+
+void QtColorButton::dropEvent(QDropEvent *event)
+{
+ event->accept();
+ d_ptr->m_dragging = false;
+ if (d_ptr->m_dragColor == color())
+ return;
+ setColor(d_ptr->m_dragColor);
+ emit colorChanged(color());
+}
+#endif
+
+QT_END_NAMESPACE
+
+#include "moc_qtcolorbutton.cpp"
diff --git a/tools/shared/qtgradienteditor/qtcolorbutton.h b/tools/shared/qtgradienteditor/qtcolorbutton.h
new file mode 100644
index 0000000000..fb91452a8e
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtcolorbutton.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCOLORBUTTON_H
+#define QTCOLORBUTTON_H
+
+#include <QtGui/QToolButton>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorButton : public QToolButton
+{
+ Q_OBJECT
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+public:
+ QtColorButton(QWidget *parent = 0);
+ ~QtColorButton();
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ QColor color() const;
+
+public slots:
+
+ void setColor(const QColor &color);
+
+signals:
+ void colorChanged(const QColor &color);
+protected:
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+#ifndef QT_NO_DRAGANDDROP
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
+#endif
+private:
+ class QtColorButtonPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtColorButton)
+ Q_DISABLE_COPY(QtColorButton)
+ Q_PRIVATE_SLOT(d_func(), void slotEditColor())
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtcolorbutton.pri b/tools/shared/qtgradienteditor/qtcolorbutton.pri
new file mode 100644
index 0000000000..0e41068f8a
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtcolorbutton.pri
@@ -0,0 +1,4 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+SOURCES += $$PWD/qtcolorbutton.cpp
+HEADERS += $$PWD/qtcolorbutton.h
diff --git a/tools/shared/qtgradienteditor/qtcolorline.cpp b/tools/shared/qtgradienteditor/qtcolorline.cpp
new file mode 100644
index 0000000000..337726c962
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtcolorline.cpp
@@ -0,0 +1,1124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtcolorline.h"
+#include "qdrawutil.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QStyleOption>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorLinePrivate
+{
+ QtColorLine *q_ptr;
+ Q_DECLARE_PUBLIC(QtColorLine)
+public:
+ QtColorLinePrivate();
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+ QtColorLine::ColorComponent colorComponent() const;
+ void setColorComponent(QtColorLine::ColorComponent component);
+
+ void setIndicatorSize(int size);
+ int indicatorSize() const;
+
+ void setIndicatorSpace(int space);
+ int indicatorSpace() const;
+
+ void setFlip(bool flip);
+ bool flip() const;
+
+ void setBackgroundCheckered(bool checkered);
+ bool isBackgroundCheckered() const;
+
+ void setOrientation(Qt::Orientation orientation);
+ Qt::Orientation orientation() const;
+
+ void resizeEvent(QResizeEvent *event);
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+private:
+ void checkColor();
+ bool isMainPixmapValid() const;
+ void validate();
+ void recreateMainPixmap();
+ QSize pixmapSizeFromGeometrySize(const QSize &geometrySize) const;
+ QPixmap gradientPixmap(int size, Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped = false) const;
+ QPixmap gradientPixmap(Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped = false) const;
+ QPixmap hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped = false,
+ int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const;
+ QPixmap hueGradientPixmap(Qt::Orientation orientation, bool flipped = false,
+ int saturation = 0xFF, int value = 0xFF, int alpha = 0xFF) const;
+
+ QVector<QRect> rects(const QPointF &point) const;
+
+ QColor colorFromPoint(const QPointF &point) const;
+ QPointF pointFromColor(const QColor &color) const;
+
+ QColor m_color;
+ QtColorLine::ColorComponent m_component;
+ bool m_flipped;
+ bool m_backgroundCheckered;
+ Qt::Orientation m_orientation;
+ bool m_dragging;
+ bool m_combiningAlpha;
+ int m_indicatorSize;
+ int m_indicatorSpace;
+ QPointF m_point;
+ QPoint m_clickOffset;
+
+ QPixmap m_mainPixmap;
+ QPixmap m_alphalessPixmap;
+ QPixmap m_semiAlphaPixmap;
+ QSize m_pixmapSize;
+
+ struct PixData {
+ QSize size;
+ QColor color;
+ QtColorLine::ColorComponent component;
+ bool flipped;
+ Qt::Orientation orientation;
+ };
+
+ PixData m_lastValidMainPixmapData;
+};
+
+QtColorLinePrivate::QtColorLinePrivate()
+ : m_color(Qt::black), m_component(QtColorLine::Value),
+ m_flipped(false), m_backgroundCheckered(true), m_orientation(Qt::Horizontal), m_dragging(false), m_combiningAlpha(false)
+{
+ m_indicatorSize = 22;
+ m_indicatorSpace = 0;
+ m_pixmapSize = QSize(0, 0);
+ m_point = pointFromColor(m_color);
+}
+
+void QtColorLinePrivate::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+ if (!color.isValid())
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ m_color = color;
+ checkColor();
+ QColor c = colorFromPoint(m_point);
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+}
+
+QColor QtColorLinePrivate::color() const
+{
+ return m_color;
+}
+
+void QtColorLinePrivate::setColorComponent(QtColorLine::ColorComponent component)
+{
+ if (m_component == component)
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ m_component = component;
+ checkColor();
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+}
+
+QtColorLine::ColorComponent QtColorLinePrivate::colorComponent() const
+{
+ return m_component;
+}
+
+void QtColorLinePrivate::setIndicatorSize(int size)
+{
+ if (size <= 0)
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_indicatorSize == size)
+ return;
+ m_indicatorSize = size;
+ m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size());
+ q_ptr->update();
+ q_ptr->updateGeometry();
+}
+
+int QtColorLinePrivate::indicatorSize() const
+{
+ return m_indicatorSize;
+}
+
+void QtColorLinePrivate::setIndicatorSpace(int space)
+{
+ if (space < 0)
+ return;
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_indicatorSpace == space)
+ return;
+ m_indicatorSpace = space;
+ m_pixmapSize = pixmapSizeFromGeometrySize(q_ptr->contentsRect().size());
+ q_ptr->update();
+}
+
+int QtColorLinePrivate::indicatorSpace() const
+{
+ return m_indicatorSpace;
+}
+
+void QtColorLinePrivate::setFlip(bool flip)
+{
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_flipped == flip)
+ return;
+ m_flipped = flip;
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+}
+
+bool QtColorLinePrivate::flip() const
+{
+ return m_flipped;
+}
+
+void QtColorLinePrivate::setBackgroundCheckered(bool checkered)
+{
+ if (m_backgroundCheckered == checkered)
+ return;
+ m_backgroundCheckered = checkered;
+ q_ptr->update();
+}
+
+bool QtColorLinePrivate::isBackgroundCheckered() const
+{
+ return m_backgroundCheckered;
+}
+
+void QtColorLinePrivate::setOrientation(Qt::Orientation orientation)
+{
+ if (m_dragging) // Warning perhaps here, recursive call
+ return;
+ if (m_orientation == orientation)
+ return;
+
+ m_orientation = orientation;
+ if (!q_ptr->testAttribute(Qt::WA_WState_OwnSizePolicy)) {
+ QSizePolicy sp = q_ptr->sizePolicy();
+ sp.transpose();
+ q_ptr->setSizePolicy(sp);
+ q_ptr->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
+ }
+ m_point = pointFromColor(m_color);
+ q_ptr->update();
+ q_ptr->updateGeometry();
+}
+
+Qt::Orientation QtColorLinePrivate::orientation() const
+{
+ return m_orientation;
+}
+
+void QtColorLinePrivate::checkColor()
+{
+ switch (m_component) {
+ case QtColorLine::Red:
+ case QtColorLine::Green:
+ case QtColorLine::Blue:
+ if (m_color.spec() != QColor::Rgb)
+ m_color = m_color.toRgb();
+ break;
+ case QtColorLine::Hue:
+ case QtColorLine::Saturation:
+ case QtColorLine::Value:
+ if (m_color.spec() != QColor::Hsv)
+ m_color = m_color.toHsv();
+ break;
+ default:
+ break;
+ }
+ if (m_color.spec() == QColor::Hsv) {
+ if (m_color.hue() == 360 || m_color.hue() == -1) {
+ m_color.setHsvF(0.0, m_color.saturationF(), m_color.valueF(), m_color.alphaF());
+ }
+ }
+}
+
+bool QtColorLinePrivate::isMainPixmapValid() const
+{
+ if (m_mainPixmap.isNull()) {
+ if (m_pixmapSize.isEmpty())
+ return true;
+ else
+ return false;
+ }
+ if (m_lastValidMainPixmapData.component != m_component)
+ return false;
+ if (m_lastValidMainPixmapData.size != m_pixmapSize)
+ return false;
+ if (m_lastValidMainPixmapData.flipped != m_flipped)
+ return false;
+ if (m_lastValidMainPixmapData.orientation != m_orientation)
+ return false;
+ if (m_lastValidMainPixmapData.color == m_color)
+ return true;
+ switch (m_component) {
+ case QtColorLine::Red:
+ if (m_color.green() == m_lastValidMainPixmapData.color.green() &&
+ m_color.blue() == m_lastValidMainPixmapData.color.blue() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Green:
+ if (m_color.red() == m_lastValidMainPixmapData.color.red() &&
+ m_color.blue() == m_lastValidMainPixmapData.color.blue() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Blue:
+ if (m_color.red() == m_lastValidMainPixmapData.color.red() &&
+ m_color.green() == m_lastValidMainPixmapData.color.green() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Hue:
+ if (m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
+ m_color.value() == m_lastValidMainPixmapData.color.value() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Saturation:
+ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
+ m_color.value() == m_lastValidMainPixmapData.color.value() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Value:
+ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
+ m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
+ (!m_combiningAlpha || m_color.alpha() == m_lastValidMainPixmapData.color.alpha()))
+ return true;
+ break;
+ case QtColorLine::Alpha:
+ if (m_color.hue() == m_lastValidMainPixmapData.color.hue() &&
+ m_color.saturation() == m_lastValidMainPixmapData.color.saturation() &&
+ m_color.value() == m_lastValidMainPixmapData.color.value())
+ return true;
+ }
+ return false;
+}
+
+void QtColorLinePrivate::validate()
+{
+ if (isMainPixmapValid())
+ return;
+
+ recreateMainPixmap();
+}
+
+QPixmap QtColorLinePrivate::gradientPixmap(Qt::Orientation orientation, const QColor &begin, const QColor &end, bool flipped) const
+{
+ int size = m_pixmapSize.width();
+ if (orientation == Qt::Vertical)
+ size = m_pixmapSize.height();
+ return gradientPixmap(size, orientation, begin, end, flipped);
+}
+
+QPixmap QtColorLinePrivate::gradientPixmap(int size, Qt::Orientation orientation,
+ const QColor &begin, const QColor &end, bool flipped) const
+{
+ int gradW = size;
+ int gradH = size;
+ int w = size;
+ int h = size;
+ if (orientation == Qt::Horizontal) {
+ gradH = 0;
+ h = 1;
+ } else {
+ gradW = 0;
+ w = 1;
+ }
+ QColor c1 = begin;
+ QColor c2 = end;
+ if (flipped) {
+ c1 = end;
+ c2 = begin;
+ }
+ QLinearGradient lg(0, 0, gradW, gradH);
+ lg.setColorAt(0, c1);
+ lg.setColorAt(1, c2);
+ QImage img(w, h, QImage::Format_ARGB32);
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(QRect(0, 0, w, h), lg);
+ return QPixmap::fromImage(img);
+}
+
+QPixmap QtColorLinePrivate::hueGradientPixmap(Qt::Orientation orientation, bool flipped,
+ int saturation, int value, int alpha) const
+{
+ int size = m_pixmapSize.width();
+ if (orientation == Qt::Vertical)
+ size = m_pixmapSize.height();
+ return hueGradientPixmap(size, orientation, flipped, saturation, value, alpha);
+}
+
+QPixmap QtColorLinePrivate::hueGradientPixmap(int size, Qt::Orientation orientation, bool flipped,
+ int saturation, int value, int alpha) const
+{
+ int gradW = size + 1;
+ int gradH = size + 1;
+ int w = size;
+ int h = size;
+ if (orientation == Qt::Horizontal) {
+ gradH = 0;
+ h = 1;
+ } else {
+ gradW = 0;
+ w = 1;
+ }
+ QList<QColor> colorList;
+ colorList << QColor::fromHsv(0, saturation, value, alpha);
+ colorList << QColor::fromHsv(60, saturation, value, alpha);
+ colorList << QColor::fromHsv(120, saturation, value, alpha);
+ colorList << QColor::fromHsv(180, saturation, value, alpha);
+ colorList << QColor::fromHsv(240, saturation, value, alpha);
+ colorList << QColor::fromHsv(300, saturation, value, alpha);
+ colorList << QColor::fromHsv(0, saturation, value, alpha);
+ QLinearGradient lg(0, 0, gradW, gradH);
+ for (int i = 0; i <= 6; i++)
+ lg.setColorAt((double)i / 6.0, flipped ? colorList.at(6 - i) : colorList.at(i));
+ QImage img(w, h, QImage::Format_ARGB32);
+ QPainter p(&img);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(QRect(0, 0, w, h), lg);
+ return QPixmap::fromImage(img);
+}
+
+void QtColorLinePrivate::recreateMainPixmap()
+{
+ m_lastValidMainPixmapData.size = m_pixmapSize;
+ m_lastValidMainPixmapData.component = m_component;
+ m_lastValidMainPixmapData.color = m_color;
+ m_lastValidMainPixmapData.flipped = m_flipped;
+ m_lastValidMainPixmapData.orientation = m_orientation;
+
+ if (m_pixmapSize.isEmpty()) {
+ m_mainPixmap = QPixmap();
+ m_alphalessPixmap = QPixmap();
+ m_semiAlphaPixmap = QPixmap();
+ return;
+ }
+
+ if (m_mainPixmap.size() != m_pixmapSize) {
+ m_mainPixmap = QPixmap(m_pixmapSize);
+ m_alphalessPixmap = QPixmap(m_pixmapSize);
+ m_semiAlphaPixmap = QPixmap(m_pixmapSize);
+ }
+
+ Qt::Orientation orient = m_orientation;
+ const bool flip = m_flipped;
+
+ const int r = m_color.red();
+ const int g = m_color.green();
+ const int b = m_color.blue();
+ const int h = m_color.hue();
+ const int s = m_color.saturation();
+ const int v = m_color.value();
+ const int a = m_color.alpha();
+ const double coef = 0.5;
+ const int semi = qRound(a * coef + 0xFF * (1.0 - coef));
+
+ if (m_component == QtColorLine::Hue) {
+ m_alphalessPixmap = hueGradientPixmap(orient, flip, s, v, 0xFF);
+ if (m_combiningAlpha) {
+ m_mainPixmap = hueGradientPixmap(orient, flip, s, v, a);
+ m_semiAlphaPixmap = hueGradientPixmap(orient, flip, s, v, semi);
+ }
+ } else if (m_component == QtColorLine::Saturation) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, 0xFF), QColor::fromHsv(h, 0xFF, v, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, a), QColor::fromHsv(h, 0xFF, v, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromHsv(h, 0, v, semi), QColor::fromHsv(h, 0xFF, v, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Value) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, 0xFF), QColor::fromHsv(h, s, 0xFF, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, a), QColor::fromHsv(h, s, 0xFF, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, 0, 0, semi), QColor::fromHsv(h, s, 0xFF, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Red) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, 0xFF), QColor::fromRgb(0xFF, g, b, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, a), QColor::fromRgb(0xFF, g, b, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(0, g, b, semi), QColor::fromRgb(0xFF, g, b, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Green) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, 0xFF), QColor::fromRgb(r, 0xFF, b, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, a), QColor::fromRgb(r, 0xFF, b, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, 0, b, semi), QColor::fromRgb(r, 0xFF, b, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Blue) {
+ m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, 0xFF), QColor::fromRgb(r, g, 0xFF, 0xFF), flip);
+ if (m_combiningAlpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, a), QColor::fromRgb(r, g, 0xFF, a), flip);
+ m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, 0, semi), QColor::fromRgb(r, g, 0xFF, semi), flip);
+ }
+ } else if (m_component == QtColorLine::Alpha) {
+ m_mainPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0), QColor::fromRgb(r, g, b, 0xFF), flip);
+
+// m_alphalessPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, 0xFF), QColor::fromRgb(r, g, b, 0xFF), flip);
+// m_semiAlphaPixmap = gradientPixmap(orient, QColor::fromRgb(r, g, b, semi), QColor::fromRgb(r, g, b, semi), flip);
+ }
+ if (!m_combiningAlpha && m_component != QtColorLine::Alpha)
+ m_mainPixmap = m_alphalessPixmap;
+}
+
+QSize QtColorLinePrivate::pixmapSizeFromGeometrySize(
+ const QSize &geometrySize) const
+{
+ QSize size(m_indicatorSize + 2 * m_indicatorSpace - 1,
+ m_indicatorSize + 2 * m_indicatorSpace - 1);
+ if (m_orientation == Qt::Horizontal)
+ size.setHeight(0);
+ else
+ size.setWidth(0);
+ return geometrySize - size;
+}
+
+QColor QtColorLinePrivate::colorFromPoint(const QPointF &point) const
+{
+ QPointF p = point;
+ if (p.x() < 0)
+ p.setX(0.0);
+ else if (p.x() > 1)
+ p.setX(1.0);
+ if (p.y() < 0)
+ p.setY(0.0);
+ else if (p.y() > 1)
+ p.setY(1.0);
+
+ double pos = p.x();
+ if (m_orientation == Qt::Vertical)
+ pos = p.y();
+ if (m_flipped)
+ pos = 1.0 - pos;
+ QColor c;
+ qreal hue;
+ switch (m_component) {
+ case QtColorLine::Red:
+ c.setRgbF(pos, m_color.greenF(), m_color.blueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Green:
+ c.setRgbF(m_color.redF(), pos, m_color.blueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Blue:
+ c.setRgbF(m_color.redF(), m_color.greenF(), pos, m_color.alphaF());
+ break;
+ case QtColorLine::Hue:
+ hue = pos;
+ hue *= 35999.0 / 36000.0;
+ c.setHsvF(hue, m_color.saturationF(), m_color.valueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Saturation:
+ c.setHsvF(m_color.hueF(), pos, m_color.valueF(), m_color.alphaF());
+ break;
+ case QtColorLine::Value:
+ c.setHsvF(m_color.hueF(), m_color.saturationF(), pos, m_color.alphaF());
+ break;
+ case QtColorLine::Alpha:
+ c.setHsvF(m_color.hueF(), m_color.saturationF(), m_color.valueF(), pos);
+ break;
+ }
+ return c;
+}
+
+QPointF QtColorLinePrivate::pointFromColor(const QColor &color) const
+{
+ qreal hue = color.hueF();
+ if (color.hue() == 360)
+ hue = 0.0;
+ else
+ hue *= 36000.0 / 35999.0;
+
+ double pos = 0.0;
+ switch (m_component) {
+ case QtColorLine::Red:
+ pos = color.redF();
+ break;
+ case QtColorLine::Green:
+ pos = color.greenF();
+ break;
+ case QtColorLine::Blue:
+ pos = color.blueF();
+ break;
+ case QtColorLine::Hue:
+ pos = hue;
+ break;
+ case QtColorLine::Saturation:
+ pos = color.saturationF();
+ break;
+ case QtColorLine::Value:
+ pos = color.valueF();
+ break;
+ case QtColorLine::Alpha:
+ pos = color.alphaF();
+ break;
+ }
+ if (m_flipped)
+ pos = 1.0 - pos;
+ QPointF p(pos, pos);
+ if (m_orientation == Qt::Horizontal)
+ p.setY(0);
+ else
+ p.setX(0);
+ return p;
+}
+
+QVector<QRect> QtColorLinePrivate::rects(const QPointF &point) const
+{
+ QRect r = q_ptr->geometry();
+ r.moveTo(0, 0);
+
+ int x1 = (int)((r.width() - m_indicatorSize - 2 * m_indicatorSpace) * point.x() + 0.5);
+ int x2 = x1 + m_indicatorSize + 2 * m_indicatorSpace;
+ int y1 = (int)((r.height() - m_indicatorSize - 2 * m_indicatorSpace) * point.y() + 0.5);
+ int y2 = y1 + m_indicatorSize + 2 * m_indicatorSpace;
+
+ QVector<QRect> rects;
+ if (m_orientation == Qt::Horizontal) {
+ // r0 r1 r2
+ QRect r0(0, 0, x1, r.height());
+ QRect r1(x1 + m_indicatorSpace, 0, m_indicatorSize, r.height());
+ QRect r2(x2, 0, r.width() - x2, r.height());
+
+ rects << r0 << r1 << r2;
+ } else {
+ // r0
+ // r1
+ // r2
+ QRect r0(0, 0, r.width(), y1);
+ QRect r1(0, y1 + m_indicatorSpace, r.width(), m_indicatorSize);
+ QRect r2(0, y2, r.width(), r.height() - y2);
+
+ rects << r0 << r1 << r2;
+ }
+ return rects;
+}
+
+void QtColorLinePrivate::resizeEvent(QResizeEvent *event)
+{
+ m_pixmapSize = pixmapSizeFromGeometrySize(event->size());
+}
+
+void QtColorLinePrivate::paintEvent(QPaintEvent *)
+{
+ QRect rect = q_ptr->rect();
+
+ QVector<QRect> r = rects(m_point);
+
+ QColor cBack = q_ptr->palette().color(QPalette::Active, QPalette::Window);
+ QColor c = colorFromPoint(m_point);
+ if (!m_combiningAlpha && m_component != QtColorLine::Alpha)
+ c.setAlpha(0xFF);
+
+ QPainter p(q_ptr);
+ if (q_ptr->isEnabled()) {
+ if (m_backgroundCheckered) {
+ int pixSize = 20;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+ pmp.end();
+
+ p.setBrushOrigin((rect.width() % pixSize + pixSize) / 2, (rect.height() % pixSize + pixSize) / 2);
+ p.setClipRect(r[1].adjusted(4, 4, -4, -4));
+ p.setClipRect(QRect(rect.topLeft(), QPoint(r[1].left() + 0, rect.bottom())), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(r[1].right() - 0, rect.top()), rect.bottomRight()), Qt::UniteClip);
+ p.setClipRect(QRect(rect.topLeft(), QPoint(rect.right(), r[1].top() + 0)), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(rect.left(), r[1].bottom() - 0), rect.bottomRight()), Qt::UniteClip);
+ /*
+ p.setClipRect(r[1].adjusted(3, 3, -3, -3));
+ p.setClipRect(QRect(rect.topLeft(), QPoint(r[1].left() + 1, rect.bottom())), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(r[1].right() - 1, rect.top()), rect.bottomRight()), Qt::UniteClip);
+ p.setClipRect(QRect(rect.topLeft(), QPoint(rect.right(), r[1].top() + 1)), Qt::UniteClip);
+ p.setClipRect(QRect(QPoint(rect.left(), r[1].bottom() - 1), rect.bottomRight()), Qt::UniteClip);
+ */
+ p.fillRect(rect, pm);
+ p.setBrushOrigin(0, 0);
+ p.setClipping(false);
+ }
+
+ validate();
+
+ QSize fieldSize = pixmapSizeFromGeometrySize(q_ptr->geometry().size());
+
+ QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace);
+ int x = posOnField.x();
+ int y = posOnField.y();
+ int w = fieldSize.width();
+ int h = fieldSize.height();
+
+ QRect r0, r2;
+ if (m_orientation == Qt::Horizontal) {
+ r0 = QRect(0, 0, x, m_pixmapSize.height());
+ r2 = QRect(x + 1, 0, w - x - 1, m_pixmapSize.height());
+ } else {
+ r0 = QRect(0, 0, m_pixmapSize.width(), y);
+ r2 = QRect(0, y + 1, m_pixmapSize.width(), h - y - 1);
+ }
+
+ p.setBrush(m_mainPixmap);
+ p.setPen(Qt::NoPen);
+ if (r[0].isValid()) {
+ p.drawRect(r[0]);
+ }
+ if (r[2].isValid()) {
+ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
+ p.drawRect(r[2]);
+ }
+ if (m_indicatorSpace) {
+ p.setBrush(c);
+ if (m_orientation == Qt::Horizontal) {
+ p.drawRect(r[1].adjusted(-m_indicatorSpace, 0, -r[1].width(), 0));
+ p.drawRect(r[1].adjusted(r[1].width(), 0, m_indicatorSpace, 0));
+ } else {
+ p.drawRect(r[1].adjusted(0, -m_indicatorSpace, 0, -r[1].height()));
+ p.drawRect(r[1].adjusted(0, r[1].height(), 0, m_indicatorSpace));
+ }
+ }
+
+ QPen pen(c);
+ p.setPen(pen);
+ p.setBrush(Qt::NoBrush);
+ if (r[1].isValid()) {
+ p.drawRect(r[1].adjusted(0, 0, -1, -1));
+ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
+ }
+ double coef = 9.0 / 10;
+ p.setPen(Qt::NoPen);
+ if (m_component != QtColorLine::Alpha && m_combiningAlpha) {
+ p.setBrush(m_alphalessPixmap);
+ if (r[0].isValid()) {
+ p.setBrushOrigin(QPoint(0, 0));
+ QRect thinRect1 = r[0];
+ QRect thinRect2 = r[0];
+ QRect thinRect = r[0];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0);
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef));
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0);
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0);
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ if (r[2].isValid()) {
+ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
+ QRect thinRect1 = r[2];
+ QRect thinRect2 = r[2];
+ QRect thinRect = r[2];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef), 0, 0);
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef));
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef), 0, 0, 0);
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef), 0);
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ /*
+
+*/
+
+
+
+
+
+ p.setPen(Qt::NoPen);
+
+ p.setBrush(m_semiAlphaPixmap);
+ if (r[0].isValid()) {
+ p.setBrushOrigin(QPoint(0, 0));
+ QRect thinRect1 = r[0];
+ QRect thinRect2 = r[0];
+ QRect thinRect = r[0];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0);
+ thinRect1.setBottom(thinRect1.top());
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1);
+ thinRect2.setTop(thinRect2.bottom());
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0);
+ thinRect1.setRight(thinRect1.left());
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0);
+ thinRect2.setLeft(thinRect2.right());
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ if (r[2].isValid()) {
+ p.setBrushOrigin(r[2].topLeft() - r2.topLeft());
+ QRect thinRect1 = r[2];
+ QRect thinRect2 = r[2];
+ QRect thinRect = r[2];
+ if (m_orientation == Qt::Horizontal) {
+ thinRect1.adjust(0, qRound(thinRect1.height() * coef) - 1, 0, 0);
+ thinRect1.setBottom(thinRect1.top());
+ thinRect2.adjust(0, 0, 0, -qRound(thinRect2.height() * coef) + 1);
+ thinRect2.setTop(thinRect2.bottom());
+ thinRect.adjust(0, qRound(thinRect.height() * coef), 0, -qRound(thinRect.height() * coef));
+ } else {
+ thinRect1.adjust(qRound(thinRect1.width() * coef) - 1, 0, 0, 0);
+ thinRect1.setRight(thinRect1.left());
+ thinRect2.adjust(0, 0, -qRound(thinRect2.width() * coef) + 1, 0);
+ thinRect2.setLeft(thinRect2.right());
+ thinRect.adjust(qRound(thinRect.width() * coef), 0, -qRound(thinRect.width() * coef), 0);
+ }
+ p.drawRect(thinRect1);
+ p.drawRect(thinRect2);
+ //p.drawRect(thinRect);
+ }
+ p.setBrush(m_alphalessPixmap);
+ if (m_orientation == Qt::Horizontal) {
+ p.setClipRect(r[1].adjusted(0, qRound(r[1].height() * coef), 0, 0));
+ p.setClipRect(r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef)), Qt::UniteClip);
+ } else {
+ p.setClipRect(r[1].adjusted(qRound(r[1].width() * coef), 0, 0, 0));
+ p.setClipRect(r[1].adjusted(0, 0, -qRound(r[1].width() * coef), 0), Qt::UniteClip);
+ }
+ p.setBrush(Qt::NoBrush);
+ p.setPen(QPen(QColor(c.rgb())));
+
+ p.drawRect(r[1].adjusted(0, 0, -1, -1));
+ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
+/*
+ p.setBrush(m_semiAlphaPixmap);
+ if (m_orientation == Qt::Horizontal) {
+ QRect top = r[1].adjusted(0, 0, 0, -qRound(r[1].height() * coef) + 1);
+ top.setTop(top.bottom());
+ QRect bottom = r[1].adjusted(0, qRound(r[1].height() * coef) - 1, 0, 0);
+ top.setBottom(bottom.top());
+ p.setClipRect(top);
+ p.setClipRect(bottom, Qt::UniteClip);
+ } else {
+
+ }
+ QColor semiColor(c.rgb());
+ semiColor.setAlpha((c.alpha() + 0xFF) / 2);
+ p.setPen(QPen(semiColor));
+ p.drawRect(r[1].adjusted(0, 0, -1, -1));
+ // p.drawRect(r[1].adjusted(1, 1, -2, -2));
+*/
+ p.setClipping(false);
+ }
+ }
+
+ p.setBrush(Qt::NoBrush);
+ int lw = 4;
+ //int br = 1;
+ int br = 0;
+ r[1].adjust(br, br, -br, -br);
+ if (r[1].adjusted(lw, lw, -lw, -lw).isValid()) {
+ QStyleOptionFrame opt;
+ opt.init(q_ptr);
+ opt.rect = r[1];
+ opt.lineWidth = 2;
+ opt.midLineWidth = 1;
+ if (m_dragging)
+ opt.state |= QStyle::State_Sunken;
+ else
+ opt.state |= QStyle::State_Raised;
+ q_ptr->style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, q_ptr);
+ QRect colorRect = r[1].adjusted(lw, lw, -lw, -lw);
+ if (q_ptr->isEnabled()) {
+ p.fillRect(colorRect, c);
+ const QColor frameColor(0, 0, 0, 38);
+ p.setPen(frameColor);
+ p.drawRect(colorRect.adjusted(0, 0, -1, -1));
+ /*
+ p.fillRect(colorRect.width() / 4 + colorRect.left(),
+ colorRect.height() / 4 + colorRect.top(),
+ colorRect.width() / 2,
+ colorRect.height() / 2,
+ QColor(c.rgb()));
+ */
+ /*
+ if (m_component != QtColorLine::Alpha) {
+ p.fillRect(colorRect.adjusted(0, colorRect.height() * 4 / 5, 0, 0), QColor(c.rgb()));
+ p.fillRect(colorRect.adjusted(0, 0, 0, -colorRect.height() * 4 / 5), QColor(c.rgb()));
+ }
+ */
+ }
+ }
+}
+
+void QtColorLinePrivate::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ QVector<QRect> r = rects(m_point);
+ QPoint clickPos = event->pos();
+
+ QSize fieldSize = q_ptr->geometry().size() -
+ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
+ QPoint posOnField = r[1].topLeft() - QPoint(m_indicatorSpace, m_indicatorSpace);
+ m_clickOffset = posOnField - clickPos;
+
+ if (!r[1].contains(clickPos))
+ return;
+ m_dragging = true;
+ q_ptr->update();
+}
+
+void QtColorLinePrivate::mouseMoveEvent(QMouseEvent *event)
+{
+ if (!m_dragging)
+ return;
+ QPoint newPos = event->pos();
+
+ QSize fieldSize = q_ptr->geometry().size() -
+ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
+ QPoint newPosOnField = newPos + m_clickOffset;
+ if (newPosOnField.x() < 0)
+ newPosOnField.setX(0);
+ else if (newPosOnField.x() > fieldSize.width())
+ newPosOnField.setX(fieldSize.width());
+ if (newPosOnField.y() < 0)
+ newPosOnField.setY(0);
+ else if (newPosOnField.y() > fieldSize.height())
+ newPosOnField.setY(fieldSize.height());
+
+ double x = (double)newPosOnField.x() / fieldSize.width();
+ double y = (double)newPosOnField.y() / fieldSize.height();
+ m_point = QPointF(x, y);
+ QColor color = colorFromPoint(m_point);
+ if (m_color == color)
+ return;
+ m_color = color;
+ emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above
+ q_ptr->update();
+}
+
+void QtColorLinePrivate::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton)
+ return;
+ m_dragging = false;
+ q_ptr->update();
+}
+
+void QtColorLinePrivate::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ QVector<QRect> r = rects(m_point);
+ QPoint clickPos = event->pos();
+ if (!r[0].contains(clickPos) && !r[2].contains(clickPos))
+ return;
+ QPoint newPosOnField = clickPos;
+ if (r[2].contains(clickPos))
+ newPosOnField -= QPoint(m_indicatorSize + 2 * m_indicatorSpace - 2, m_indicatorSize + 2 * m_indicatorSpace - 2);
+ QSize fieldSize = q_ptr->geometry().size() -
+ QSize(m_indicatorSize + 2 * m_indicatorSpace - 1, m_indicatorSize + 2 * m_indicatorSpace - 1);
+
+ double x = (double)newPosOnField.x() / fieldSize.width();
+ double y = (double)newPosOnField.y() / fieldSize.height();
+ m_point = QPointF(x, y);
+ QColor color = colorFromPoint(m_point);
+ if (m_color == color)
+ return;
+ m_color = color;
+ emit q_ptr->colorChanged(color); // maybe before internal set, 1 line above
+ q_ptr->update();
+}
+
+////////////////////////////////////////////////////
+
+QtColorLine::QtColorLine(QWidget *parent)
+ : QWidget(parent)
+{
+ d_ptr = new QtColorLinePrivate;
+ d_ptr->q_ptr = this;
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+}
+
+QtColorLine::~QtColorLine()
+{
+ delete d_ptr;
+}
+
+QSize QtColorLine::minimumSizeHint() const
+{
+ return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize);
+}
+
+QSize QtColorLine::sizeHint() const
+{
+ return QSize(d_ptr->m_indicatorSize, d_ptr->m_indicatorSize);
+}
+
+void QtColorLine::setColor(const QColor &color)
+{
+ d_ptr->setColor(color);
+}
+
+QColor QtColorLine::color() const
+{
+ return d_ptr->color();
+}
+
+void QtColorLine::setColorComponent(QtColorLine::ColorComponent component)
+{
+ d_ptr->setColorComponent(component);
+}
+
+QtColorLine::ColorComponent QtColorLine::colorComponent() const
+{
+ return d_ptr->colorComponent();
+}
+
+void QtColorLine::setIndicatorSize(int size)
+{
+ d_ptr->setIndicatorSize(size);
+}
+
+int QtColorLine::indicatorSize() const
+{
+ return d_ptr->indicatorSize();
+}
+
+void QtColorLine::setIndicatorSpace(int space)
+{
+ d_ptr->setIndicatorSpace(space);
+}
+
+int QtColorLine::indicatorSpace() const
+{
+ return d_ptr->indicatorSpace();
+}
+
+void QtColorLine::setFlip(bool flip)
+{
+ d_ptr->setFlip(flip);
+}
+
+bool QtColorLine::flip() const
+{
+ return d_ptr->flip();
+}
+
+void QtColorLine::setBackgroundCheckered(bool checkered)
+{
+ d_ptr->setBackgroundCheckered(checkered);
+}
+
+bool QtColorLine::isBackgroundCheckered() const
+{
+ return d_ptr->isBackgroundCheckered();
+}
+
+void QtColorLine::setOrientation(Qt::Orientation orientation)
+{
+ d_ptr->setOrientation(orientation);
+}
+
+Qt::Orientation QtColorLine::orientation() const
+{
+ return d_ptr->orientation();
+}
+void QtColorLine::resizeEvent(QResizeEvent *event)
+{
+ d_ptr->resizeEvent(event);
+}
+
+void QtColorLine::paintEvent(QPaintEvent *event)
+{
+ d_ptr->paintEvent(event);
+}
+
+void QtColorLine::mousePressEvent(QMouseEvent *event)
+{
+ d_ptr->mousePressEvent(event);
+}
+
+void QtColorLine::mouseMoveEvent(QMouseEvent *event)
+{
+ d_ptr->mouseMoveEvent(event);
+}
+
+void QtColorLine::mouseReleaseEvent(QMouseEvent *event)
+{
+ d_ptr->mouseReleaseEvent(event);
+}
+
+void QtColorLine::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ d_ptr->mouseDoubleClickEvent(event);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/qtgradienteditor/qtcolorline.h b/tools/shared/qtgradienteditor/qtcolorline.h
new file mode 100644
index 0000000000..d5535b16e7
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtcolorline.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTCOLORLINE_H
+#define QTCOLORLINE_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QtColorLine : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor)
+ Q_PROPERTY(int indicatorSpace READ indicatorSpace WRITE setIndicatorSpace)
+ Q_PROPERTY(int indicatorSize READ indicatorSize WRITE setIndicatorSize)
+ Q_PROPERTY(bool flip READ flip WRITE setFlip)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(ColorComponent colorComponent READ colorComponent WRITE setColorComponent)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_ENUMS(ColorComponent)
+public:
+
+ enum ColorComponent {
+ Red,
+ Green,
+ Blue,
+ Hue,
+ Saturation,
+ Value,
+ Alpha
+ };
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+
+ QtColorLine(QWidget *parent = 0);
+ ~QtColorLine();
+
+ QColor color() const;
+
+ void setIndicatorSize(int size);
+ int indicatorSize() const;
+
+ void setIndicatorSpace(int space);
+ int indicatorSpace() const;
+
+ void setFlip(bool flip);
+ bool flip() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ void setOrientation(Qt::Orientation orientation);
+ Qt::Orientation orientation() const;
+
+ void setColorComponent(ColorComponent component);
+ ColorComponent colorComponent() const;
+
+public slots:
+
+ void setColor(const QColor &color);
+
+signals:
+
+ void colorChanged(const QColor &color);
+
+protected:
+
+ void resizeEvent(QResizeEvent *event);
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+
+private:
+
+ class QtColorLinePrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtColorLine)
+ Q_DISABLE_COPY(QtColorLine)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientdialog.cpp b/tools/shared/qtgradienteditor/qtgradientdialog.cpp
new file mode 100644
index 0000000000..032cb16628
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientdialog.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::QtGradientDialog
+*/
+
+#include "qtgradientdialog.h"
+#include "ui_qtgradientdialog.h"
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientDialogPrivate
+{
+ QtGradientDialog *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientDialog)
+public:
+
+ void slotAboutToShowDetails(bool details, int extensionWidthHint);
+
+ Ui::QtGradientDialog m_ui;
+};
+
+void QtGradientDialogPrivate::slotAboutToShowDetails(bool details, int extensionWidthHint)
+{
+ if (details) {
+ q_ptr->resize(q_ptr->size() + QSize(extensionWidthHint, 0));
+ } else {
+ q_ptr->setMinimumSize(1, 1);
+ q_ptr->resize(q_ptr->size() - QSize(extensionWidthHint, 0));
+ q_ptr->setMinimumSize(0, 0);
+ }
+}
+
+/*!
+ \class QtGradientDialog
+
+ \brief The QtGradientDialog class provides a dialog for specifying gradients.
+
+ The gradient dialog's function is to allow users to edit gradients.
+ For example, you might use this in a drawing program to allow the user to set the brush gradient.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialog.png
+ \o \inlineimage qtgradientdialogextension.png
+ \header
+ \o Details extension hidden
+ \o Details extension visible
+ \endtable
+
+ Starting from the top of the dialog there are several buttons:
+
+ \image qtgradientdialogtopbuttons.png
+
+ The first three buttons allow for changing a type of the gradient (QGradient::Type), while the second three allow for
+ changing spread of the gradient (QGradient::Spread). The last button shows or hides the details extension of the dialog.
+ Conceptually the default view with hidden details provides the full functional control over gradient editing.
+ The additional extension with details allows to set gradient's parameters more precisely. The visibility
+ of extension can be controlled by detailsVisible property. Moreover, if you don't want the user to
+ switch on or off the visibility of extension you can set the detailsButtonVisible property to false.
+
+ Below top buttons there is an area where edited gradient is interactively previewed.
+ In addition the user can edit gradient type's specific parameters directly in this area by dragging
+ appropriate handles.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialoglineareditor.png
+ \o \inlineimage qtgradientdialogradialeditor.png
+ \o \inlineimage qtgradientdialogconicaleditor.png
+ \header
+ \o Editing linear type
+ \o Editing radial type
+ \o Editing conical type
+ \row
+ \o The user can change the start and final point positions by dragging the circular handles.
+ \o The user can change the center and focal point positions by dragging the circular handles
+ and can change the gradient's radius by dragging horizontal or vertical line.
+ \o The user can change the center point by dragging the circular handle
+ and can change the gradient's angle by dragging the big wheel.
+ \endtable
+
+ In the middle of the dialog there is an area where the user can edit gradient stops.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogstops.png
+ \o \inlineimage qtgradientdialogstopszoomed.png
+ \endtable
+
+ The top part of this area contains stop handles, and bottom part shows the preview of gradient stops path.
+ In order to create a new gradient stop double click inside the view over the desired position.
+ If you double click on existing stop handle in the top part of the view, clicked handle will be duplicated
+ (duplicate will contain the same color).
+ The stop can be activated by clicking on its handle. You can activate previous or next stop by pressing
+ left or right key respectively. To jump to the first or last stop press home or end key respectively.
+ The gradient stops editor supports multiselection.
+ Clicking a handle holding the shift modifier key down will select a range of stops between
+ the active stop and clicked one. Clicking a handle holding control modifier key down will remove from or
+ add to selection the clicked stop depending if it was or wasn't already selected respectively.
+ Multiselection can also be created using rubberband (by pressing the left mouse button outside
+ of any handle and dragging).
+ Sometimes it's hard to select a stop because its handle can be partially covered by other handle.
+ In that case the user can zoom in the view by spinning mouse wheel.
+ The selected stop handles can be moved by drag & drop. In order to remove selected stops press delete key.
+ For convenience context menu is provided with the following actions:
+
+ \list
+ \o New Stop - creates a new gradient stop
+ \o Delete - removes the active and all selected stops
+ \o Flip All - mirrors all stops
+ \o Select All - selects all stops
+ \o Zoom In - zooms in
+ \o Zoom Out - zooms out
+ \o Zoom All - goes back to original 100% zoom
+ \endlist
+
+ The bottom part of the QtGradientDialog contains a set of widgets allowing to control the color of
+ the active and selected stops.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogcolorhsv.png
+ \o \inlineimage qtgradientdialogcolorrgb.png
+ \endtable
+
+
+ The color button shows the color of the active gradient stop. It also allows for choosing
+ a color from standard color dialog and applying it to the
+ active stop and all selected stops. It's also possible to drag a color directly from the color button
+ and to drop it in gradient stops editor at desired position (it will create new stop with dragged color)
+ or at desired stop handle (it will change the color of that handle).
+
+ To the right of color button there is a set of 2 radio buttons which allows to switch between
+ HVS and RGB color spec.
+
+ Finally there are 4 color sliders working either in HSVA (hue saturation value alpha) or
+ RGBA (red green blue alpha) mode, depending on which radio button is chosen. The radio buttons
+ can be controlled programatically by spec() and setSpec() methods. The sliders show the
+ color of the active stop. By double clicking inside color slider you can set directly the desired color.
+ Changes of slider's are applied to stop selection in the way that the color
+ component being changed is applied to stops in selection only, while other components
+ remain unchanged in selected stops (e.g. when the user is changing the saturation,
+ new saturation is applied to selected stops preventing original hue, value and alpha in multiselection).
+
+ The convenient static functions getGradient() provide modal gradient dialogs, e.g.:
+
+ \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 0
+
+ In order to have more control over the properties of QtGradientDialog use
+ standard QDialog::exec() method:
+
+ \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 1
+
+ \sa {Gradient View Example}
+*/
+
+/*!
+ Constructs a gradient dialog with \a parent as parent widget.
+*/
+
+QtGradientDialog::QtGradientDialog(QWidget *parent)
+ : QDialog(parent)
+{
+// setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ d_ptr = new QtGradientDialogPrivate();
+ d_ptr->q_ptr = this;
+ d_ptr->m_ui.setupUi(this);
+ QPushButton *button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Ok);
+ if (button)
+ button->setAutoDefault(false);
+ button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Cancel);
+ if (button)
+ button->setAutoDefault(false);
+ connect(d_ptr->m_ui.gradientEditor, SIGNAL(aboutToShowDetails(bool, int)),
+ this, SLOT(slotAboutToShowDetails(bool, int)));
+}
+
+/*!
+ Destroys the gradient dialog
+*/
+
+QtGradientDialog::~QtGradientDialog()
+{
+ delete d_ptr;
+}
+
+/*!
+ \property QtGradientDialog::gradient
+ \brief the gradient of the dialog
+*/
+void QtGradientDialog::setGradient(const QGradient &gradient)
+{
+ d_ptr->m_ui.gradientEditor->setGradient(gradient);
+}
+
+QGradient QtGradientDialog::gradient() const
+{
+ return d_ptr->m_ui.gradientEditor->gradient();
+}
+
+/*!
+ \property QtGradientDialog::backgroundCheckered
+ \brief whether the background of widgets able to show the colors with alpha channel is checkered.
+
+ \table
+ \row
+ \o \inlineimage qtgradientdialogbackgroundcheckered.png
+ \o \inlineimage qtgradientdialogbackgroundtransparent.png
+ \row
+ \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 2
+ \o \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 3
+ \endtable
+
+ When this property is set to true (the default) widgets inside gradient dialog like color button,
+ color sliders, gradient stops editor and gradient editor will show checkered background
+ in case of transparent colors. Otherwise the background of these widgets is transparent.
+*/
+
+bool QtGradientDialog::isBackgroundCheckered() const
+{
+ return d_ptr->m_ui.gradientEditor->isBackgroundCheckered();
+}
+
+void QtGradientDialog::setBackgroundCheckered(bool checkered)
+{
+ d_ptr->m_ui.gradientEditor->setBackgroundCheckered(checkered);
+}
+
+/*!
+ \property QtGradientDialog::detailsVisible
+ \brief whether details extension is visible.
+
+ When this property is set to true the details extension is visible. By default
+ this property is set to false and the details extension is hidden.
+
+ \sa detailsButtonVisible
+*/
+bool QtGradientDialog::detailsVisible() const
+{
+ return d_ptr->m_ui.gradientEditor->detailsVisible();
+}
+
+void QtGradientDialog::setDetailsVisible(bool visible)
+{
+ d_ptr->m_ui.gradientEditor->setDetailsVisible(visible);
+}
+
+/*!
+ \property QtGradientDialog::detailsButtonVisible
+ \brief whether the details button allowing for showing and hiding details extension is visible.
+
+ When this property is set to true (the default) the details button is visible and the user
+ can show and hide details extension interactively. Otherwise the button is hidden and the details
+ extension is always visible or hidded depending on the value of detailsVisible property.
+
+ \sa detailsVisible
+*/
+bool QtGradientDialog::isDetailsButtonVisible() const
+{
+ return d_ptr->m_ui.gradientEditor->isDetailsButtonVisible();
+}
+
+void QtGradientDialog::setDetailsButtonVisible(bool visible)
+{
+ d_ptr->m_ui.gradientEditor->setDetailsButtonVisible(visible);
+}
+
+/*!
+ Returns the current QColor::Spec used for the color sliders in the dialog.
+*/
+QColor::Spec QtGradientDialog::spec() const
+{
+ return d_ptr->m_ui.gradientEditor->spec();
+}
+
+/*!
+ Sets the current QColor::Spec to \a spec used for the color sliders in the dialog.
+*/
+void QtGradientDialog::setSpec(QColor::Spec spec)
+{
+ d_ptr->m_ui.gradientEditor->setSpec(spec);
+}
+
+/*!
+ Executes a modal gradient dialog, lets the user to specify a gradient, and returns that gradient.
+
+ If the user clicks \gui OK, the gradient specified by the user is returned. If the user clicks \gui Cancel, the \a initial gradient is returned.
+
+ The dialog is constructed with the given \a parent. \a caption is shown as the window title of the dialog and
+ \a initial is the initial gradient shown in the dialog. If the \a ok parameter is not-null,
+ the value it refers to is set to true if the user clicks \gui OK, and set to false if the user clicks \gui Cancel.
+*/
+QGradient QtGradientDialog::getGradient(bool *ok, const QGradient &initial, QWidget *parent, const QString &caption)
+{
+ QtGradientDialog dlg(parent);
+ if (!caption.isEmpty())
+ dlg.setWindowTitle(caption);
+ dlg.setGradient(initial);
+ const int res = dlg.exec();
+ if (ok) {
+ *ok = (res == QDialog::Accepted) ? true : false;
+ }
+ if (res == QDialog::Accepted)
+ return dlg.gradient();
+ return initial;
+}
+
+/*!
+ This method calls getGradient(ok, QLinearGradient(), parent, caption).
+*/
+QGradient QtGradientDialog::getGradient(bool *ok, QWidget *parent, const QString &caption)
+{
+ return getGradient(ok, QLinearGradient(), parent, caption);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradientdialog.cpp"
diff --git a/tools/shared/qtgradienteditor/qtgradientdialog.h b/tools/shared/qtgradienteditor/qtgradientdialog.h
new file mode 100644
index 0000000000..d3bafc9a9f
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientdialog.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTDIALOG_H
+#define QTGRADIENTDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientDialog : public QDialog
+{
+ Q_OBJECT
+ Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible)
+ Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible)
+public:
+ QtGradientDialog(QWidget *parent = 0);
+ ~QtGradientDialog();
+
+ void setGradient(const QGradient &gradient);
+ QGradient gradient() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ bool detailsVisible() const;
+ void setDetailsVisible(bool visible);
+
+ bool isDetailsButtonVisible() const;
+ void setDetailsButtonVisible(bool visible);
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+ static QGradient getGradient(bool *ok, const QGradient &initial, QWidget *parent = 0, const QString &caption = QString());
+ static QGradient getGradient(bool *ok, QWidget *parent = 0, const QString &caption = QString());
+
+private:
+ class QtGradientDialogPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientDialog)
+ Q_DISABLE_COPY(QtGradientDialog)
+ Q_PRIVATE_SLOT(d_func(), void slotAboutToShowDetails(bool details, int extensionWidthHint))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientdialog.ui b/tools/shared/qtgradienteditor/qtgradientdialog.ui
new file mode 100644
index 0000000000..0b3db0b196
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientdialog.ui
@@ -0,0 +1,121 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>QtGradientDialog</class>
+ <widget class="QDialog" name="QtGradientDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>178</width>
+ <height>81</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Edit Gradient</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QtGradientEditor" name="gradientEditor" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtGradientEditor</class>
+ <extends>QFrame</extends>
+ <header>qtgradienteditor.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>QtGradientDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>72</x>
+ <y>224</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>21</x>
+ <y>243</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>QtGradientDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>168</x>
+ <y>233</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>152</x>
+ <y>251</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.cpp b/tools/shared/qtgradienteditor/qtgradienteditor.cpp
new file mode 100644
index 0000000000..9eca9d8e5c
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradienteditor.cpp
@@ -0,0 +1,958 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::QtGradientEditor
+*/
+
+#include "qtgradienteditor.h"
+#include "qtgradientstopscontroller.h"
+#include "ui_qtgradienteditor.h"
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientEditorPrivate
+{
+ QtGradientEditor *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientEditor)
+public:
+ QtGradientEditorPrivate() : m_gradient(QLinearGradient()) {}
+
+ void slotGradientStopsChanged(const QGradientStops &stops);
+ void slotTypeChanged(int type);
+ void slotSpreadChanged(int spread);
+ void slotStartLinearXChanged(double value);
+ void slotStartLinearYChanged(double value);
+ void slotEndLinearXChanged(double value);
+ void slotEndLinearYChanged(double value);
+ void slotCentralRadialXChanged(double value);
+ void slotCentralRadialYChanged(double value);
+ void slotFocalRadialXChanged(double value);
+ void slotFocalRadialYChanged(double value);
+ void slotRadiusRadialChanged(double value);
+ void slotCentralConicalXChanged(double value);
+ void slotCentralConicalYChanged(double value);
+ void slotAngleConicalChanged(double value);
+
+ void slotDetailsChanged(bool details);
+
+ void startLinearChanged(const QPointF &point);
+ void endLinearChanged(const QPointF &point);
+ void centralRadialChanged(const QPointF &point);
+ void focalRadialChanged(const QPointF &point);
+ void radiusRadialChanged(qreal radius);
+ void centralConicalChanged(const QPointF &point);
+ void angleConicalChanged(qreal angle);
+
+ void setStartLinear(const QPointF &point);
+ void setEndLinear(const QPointF &point);
+ void setCentralRadial(const QPointF &point);
+ void setFocalRadial(const QPointF &point);
+ void setRadiusRadial(qreal radius);
+ void setCentralConical(const QPointF &point);
+ void setAngleConical(qreal angle);
+
+ void setType(QGradient::Type type);
+ void showDetails(bool details);
+
+ void setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max = 1.0, double step = 0.01, int decimals = 3);
+ void reset();
+ void setLayout(bool details);
+ void layoutDetails(bool details);
+ bool row4Visible() const;
+ bool row5Visible() const;
+ int extensionWidthHint() const;
+
+ void setCombos(bool combos);
+
+ QGradient gradient() const;
+ void updateGradient(bool emitSignal);
+
+ Ui::QtGradientEditor m_ui;
+ QtGradientStopsController *m_gradientStopsController;
+
+ QDoubleSpinBox *startLinearXSpinBox;
+ QDoubleSpinBox *startLinearYSpinBox;
+ QDoubleSpinBox *endLinearXSpinBox;
+ QDoubleSpinBox *endLinearYSpinBox;
+ QDoubleSpinBox *centralRadialXSpinBox;
+ QDoubleSpinBox *centralRadialYSpinBox;
+ QDoubleSpinBox *focalRadialXSpinBox;
+ QDoubleSpinBox *focalRadialYSpinBox;
+ QDoubleSpinBox *radiusRadialSpinBox;
+ QDoubleSpinBox *centralConicalXSpinBox;
+ QDoubleSpinBox *centralConicalYSpinBox;
+ QDoubleSpinBox *angleConicalSpinBox;
+
+ QButtonGroup *m_typeGroup;
+ QButtonGroup *m_spreadGroup;
+
+ QGradient::Type m_type;
+
+ QGridLayout *m_gridLayout;
+ QWidget *m_hiddenWidget;
+ QGridLayout *m_hiddenLayout;
+ bool m_details;
+ bool m_detailsButtonVisible;
+ bool m_backgroundCheckered;
+
+ QGradient m_gradient;
+
+ bool m_combos;
+};
+
+QGradient QtGradientEditorPrivate::gradient() const
+{
+ QGradient *gradient = 0;
+ switch (m_ui.gradientWidget->gradientType()) {
+ case QGradient::LinearGradient:
+ gradient = new QLinearGradient(m_ui.gradientWidget->startLinear(),
+ m_ui.gradientWidget->endLinear());
+ break;
+ case QGradient::RadialGradient:
+ gradient = new QRadialGradient(m_ui.gradientWidget->centralRadial(),
+ m_ui.gradientWidget->radiusRadial(),
+ m_ui.gradientWidget->focalRadial());
+ break;
+ case QGradient::ConicalGradient:
+ gradient = new QConicalGradient(m_ui.gradientWidget->centralConical(),
+ m_ui.gradientWidget->angleConical());
+ break;
+ default:
+ break;
+ }
+ if (!gradient)
+ return QGradient();
+ gradient->setStops(m_ui.gradientWidget->gradientStops());
+ gradient->setSpread(m_ui.gradientWidget->gradientSpread());
+ gradient->setCoordinateMode(QGradient::StretchToDeviceMode);
+ QGradient gr = *gradient;
+ delete gradient;
+ return gr;
+}
+
+void QtGradientEditorPrivate::updateGradient(bool emitSignal)
+{
+ QGradient grad = gradient();
+ if (m_gradient == grad)
+ return;
+
+ m_gradient = grad;
+ if (emitSignal)
+ emit q_ptr->gradientChanged(m_gradient);
+}
+
+void QtGradientEditorPrivate::setCombos(bool combos)
+{
+ if (m_combos == combos)
+ return;
+
+ m_combos = combos;
+ m_ui.linearButton->setVisible(!m_combos);
+ m_ui.radialButton->setVisible(!m_combos);
+ m_ui.conicalButton->setVisible(!m_combos);
+ m_ui.padButton->setVisible(!m_combos);
+ m_ui.repeatButton->setVisible(!m_combos);
+ m_ui.reflectButton->setVisible(!m_combos);
+ m_ui.typeComboBox->setVisible(m_combos);
+ m_ui.spreadComboBox->setVisible(m_combos);
+}
+
+void QtGradientEditorPrivate::setLayout(bool details)
+{
+ QHBoxLayout *hboxLayout = new QHBoxLayout();
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ hboxLayout->addWidget(m_ui.typeComboBox);
+ hboxLayout->addWidget(m_ui.spreadComboBox);
+ QHBoxLayout *typeLayout = new QHBoxLayout();
+ typeLayout->setSpacing(0);
+ typeLayout->addWidget(m_ui.linearButton);
+ typeLayout->addWidget(m_ui.radialButton);
+ typeLayout->addWidget(m_ui.conicalButton);
+ hboxLayout->addLayout(typeLayout);
+ QHBoxLayout *spreadLayout = new QHBoxLayout();
+ spreadLayout->setSpacing(0);
+ spreadLayout->addWidget(m_ui.padButton);
+ spreadLayout->addWidget(m_ui.repeatButton);
+ spreadLayout->addWidget(m_ui.reflectButton);
+ hboxLayout->addLayout(spreadLayout);
+ hboxLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
+ hboxLayout->addWidget(m_ui.detailsButton);
+ m_gridLayout->addLayout(hboxLayout, 0, 0, 1, 2);
+ int span = 1;
+ if (details)
+ span = 7;
+ m_gridLayout->addWidget(m_ui.frame, 1, 0, span, 2);
+ int row = 2;
+ if (details) {
+ row = 8;
+ span = 4;
+ }
+ m_gridLayout->addWidget(m_ui.gradientStopsWidget, row, 0, span, 2);
+ QHBoxLayout *hboxLayout1 = new QHBoxLayout();
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
+ hboxLayout1->addWidget(m_ui.colorLabel);
+ hboxLayout1->addWidget(m_ui.colorButton);
+ hboxLayout1->addWidget(m_ui.hsvRadioButton);
+ hboxLayout1->addWidget(m_ui.rgbRadioButton);
+ hboxLayout1->addItem(new QSpacerItem(16, 23, QSizePolicy::Expanding, QSizePolicy::Minimum));
+ int addRow = 0;
+ if (details)
+ addRow = 9;
+ m_gridLayout->addLayout(hboxLayout1, 3 + addRow, 0, 1, 2);
+ m_gridLayout->addWidget(m_ui.hLabel, 4 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_2, 4 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.sLabel, 5 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_5, 5 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.vLabel, 6 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_3, 6 + addRow, 1, 1, 1);
+ m_gridLayout->addWidget(m_ui.aLabel, 7 + addRow, 0, 1, 1);
+ m_gridLayout->addWidget(m_ui.frame_4, 7 + addRow, 1, 1, 1);
+
+ if (details) {
+ layoutDetails(details);
+ }
+}
+
+void QtGradientEditorPrivate::layoutDetails(bool details)
+{
+ QGridLayout *gridLayout = m_gridLayout;
+ int col = 2;
+ if (!details) {
+ col = 0;
+ if (!m_hiddenWidget) {
+ m_hiddenWidget = new QWidget();
+ m_hiddenLayout = new QGridLayout(m_hiddenWidget);
+ m_hiddenLayout->setContentsMargins(0, 0, 0, 0);
+ m_hiddenLayout->setSizeConstraint(QLayout::SetFixedSize);
+ }
+ gridLayout = m_hiddenLayout;
+ }
+ gridLayout->addWidget(m_ui.label1, 1, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox1, 1, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label2, 2, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox2, 2, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label3, 3, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox3, 3, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label4, 4, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox4, 4, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.label5, 5, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.spinBox5, 5, col + 1, 1, 1);
+ gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 6, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.line1Widget, 7, col + 0, 1, 2);
+ gridLayout->addWidget(m_ui.zoomLabel, 8, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.zoomWidget, 8, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.zoomButtonsWidget, 9, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.zoomAllButton, 9, col + 1, 1, 1);
+ gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Preferred), 10, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.line2Widget, 11, col + 0, 1, 2);
+ gridLayout->addWidget(m_ui.positionLabel, 12, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.positionWidget, 12, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.hueLabel, 13, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.hueWidget, 13, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.saturationLabel, 14, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.saturationWidget, 14, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.valueLabel, 15, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.valueWidget, 15, col + 1, 1, 1);
+ gridLayout->addWidget(m_ui.alphaLabel, 16, col + 0, 1, 1);
+ gridLayout->addWidget(m_ui.alphaWidget, 16, col + 1, 1, 1);
+
+ if (details) {
+ if (m_hiddenLayout) {
+ delete m_hiddenLayout;
+ m_hiddenLayout = 0;
+ }
+ if (m_hiddenWidget) {
+ delete m_hiddenWidget;
+ m_hiddenWidget = 0;
+ }
+ }
+}
+
+int QtGradientEditorPrivate::extensionWidthHint() const
+{
+ if (m_details)
+ return q_ptr->size().width() - m_ui.gradientStopsWidget->size().width();
+
+ const int space = m_ui.spinBox1->geometry().left() - m_ui.label1->geometry().right();
+
+ return m_hiddenLayout->minimumSize().width() + space;
+}
+
+void QtGradientEditorPrivate::slotDetailsChanged(bool details)
+{
+ showDetails(details);
+}
+
+bool QtGradientEditorPrivate::row4Visible() const
+{
+ if (m_type == QGradient::ConicalGradient)
+ return false;
+ return true;
+}
+
+bool QtGradientEditorPrivate::row5Visible() const
+{
+ if (m_type == QGradient::RadialGradient)
+ return true;
+ return false;
+}
+
+void QtGradientEditorPrivate::showDetails(bool details)
+{
+ if (m_details == details)
+ return;
+
+ bool blocked = m_ui.detailsButton->signalsBlocked();
+ m_ui.detailsButton->blockSignals(true);
+ m_ui.detailsButton->setChecked(details);
+ m_ui.detailsButton->blockSignals(blocked);
+
+ bool updates = q_ptr->updatesEnabled();
+ q_ptr->setUpdatesEnabled(false);
+
+ if (m_gridLayout) {
+ m_gridLayout->setEnabled(false);
+ delete m_gridLayout;
+ m_gridLayout = 0;
+ }
+
+ if (!details) {
+ layoutDetails(details);
+ }
+
+ emit q_ptr->aboutToShowDetails(details, extensionWidthHint());
+ m_details = details;
+
+ m_gridLayout = new QGridLayout(q_ptr);
+ m_gridLayout->setEnabled(false);
+ m_gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ m_gridLayout->setContentsMargins(0, 0, 0, 0);
+
+ m_ui.label4->setVisible(row4Visible());
+ m_ui.label5->setVisible(row5Visible());
+ m_ui.spinBox4->setVisible(row4Visible());
+ m_ui.spinBox5->setVisible(row5Visible());
+
+ setLayout(details);
+ m_gridLayout->setEnabled(true);
+
+ q_ptr->setUpdatesEnabled(updates);
+ q_ptr->update();
+}
+
+void QtGradientEditorPrivate::setSpinBox(QDoubleSpinBox *spinBox, const char *slot, double max, double step, int decimals)
+{
+ bool blocked = spinBox->signalsBlocked();
+ spinBox->blockSignals(true);
+ spinBox->setDecimals(decimals);
+ spinBox->setMaximum(max);
+ spinBox->setSingleStep(step);
+ spinBox->blockSignals(blocked);
+ QObject::connect(spinBox, SIGNAL(valueChanged(double)), q_ptr, slot);
+}
+
+void QtGradientEditorPrivate::reset()
+{
+ startLinearXSpinBox = 0;
+ startLinearYSpinBox = 0;
+ endLinearXSpinBox = 0;
+ endLinearYSpinBox = 0;
+ centralRadialXSpinBox = 0;
+ centralRadialYSpinBox = 0;
+ focalRadialXSpinBox = 0;
+ focalRadialYSpinBox = 0;
+ radiusRadialSpinBox = 0;
+ centralConicalXSpinBox = 0;
+ centralConicalYSpinBox = 0;
+ angleConicalSpinBox = 0;
+}
+
+void QtGradientEditorPrivate::setType(QGradient::Type type)
+{
+ if (m_type == type)
+ return;
+
+ m_type = type;
+ m_ui.spinBox1->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox2->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox3->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox4->disconnect(SIGNAL(valueChanged(double)));
+ m_ui.spinBox5->disconnect(SIGNAL(valueChanged(double)));
+
+ reset();
+
+ bool ena = true;
+
+ if (m_gridLayout) {
+ ena = m_gridLayout->isEnabled();
+ m_gridLayout->setEnabled(false);
+ }
+
+ bool spreadEnabled = true;
+
+ if (type == QGradient::LinearGradient) {
+ startLinearXSpinBox = m_ui.spinBox1;
+ setSpinBox(startLinearXSpinBox, SLOT(slotStartLinearXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Start X", 0, QApplication::UnicodeUTF8));
+
+ startLinearYSpinBox = m_ui.spinBox2;
+ setSpinBox(startLinearYSpinBox, SLOT(slotStartLinearYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Start Y", 0, QApplication::UnicodeUTF8));
+
+ endLinearXSpinBox = m_ui.spinBox3;
+ setSpinBox(endLinearXSpinBox, SLOT(slotEndLinearXChanged(double)));
+ m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Final X", 0, QApplication::UnicodeUTF8));
+
+ endLinearYSpinBox = m_ui.spinBox4;
+ setSpinBox(endLinearYSpinBox, SLOT(slotEndLinearYChanged(double)));
+ m_ui.label4->setText(QApplication::translate("QtGradientEditor", "Final Y", 0, QApplication::UnicodeUTF8));
+
+ setStartLinear(m_ui.gradientWidget->startLinear());
+ setEndLinear(m_ui.gradientWidget->endLinear());
+ } else if (type == QGradient::RadialGradient) {
+ centralRadialXSpinBox = m_ui.spinBox1;
+ setSpinBox(centralRadialXSpinBox, SLOT(slotCentralRadialXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Central X", 0, QApplication::UnicodeUTF8));
+
+ centralRadialYSpinBox = m_ui.spinBox2;
+ setSpinBox(centralRadialYSpinBox, SLOT(slotCentralRadialYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Central Y", 0, QApplication::UnicodeUTF8));
+
+ focalRadialXSpinBox = m_ui.spinBox3;
+ setSpinBox(focalRadialXSpinBox, SLOT(slotFocalRadialXChanged(double)));
+ m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Focal X", 0, QApplication::UnicodeUTF8));
+
+ focalRadialYSpinBox = m_ui.spinBox4;
+ setSpinBox(focalRadialYSpinBox, SLOT(slotFocalRadialYChanged(double)));
+ m_ui.label4->setText(QApplication::translate("QtGradientEditor", "Focal Y", 0, QApplication::UnicodeUTF8));
+
+ radiusRadialSpinBox = m_ui.spinBox5;
+ setSpinBox(radiusRadialSpinBox, SLOT(slotRadiusRadialChanged(double)), 2.0);
+ m_ui.label5->setText(QApplication::translate("QtGradientEditor", "Radius", 0, QApplication::UnicodeUTF8));
+
+ setCentralRadial(m_ui.gradientWidget->centralRadial());
+ setFocalRadial(m_ui.gradientWidget->focalRadial());
+ setRadiusRadial(m_ui.gradientWidget->radiusRadial());
+ } else if (type == QGradient::ConicalGradient) {
+ centralConicalXSpinBox = m_ui.spinBox1;
+ setSpinBox(centralConicalXSpinBox, SLOT(slotCentralConicalXChanged(double)));
+ m_ui.label1->setText(QApplication::translate("QtGradientEditor", "Central X", 0, QApplication::UnicodeUTF8));
+
+ centralConicalYSpinBox = m_ui.spinBox2;
+ setSpinBox(centralConicalYSpinBox, SLOT(slotCentralConicalYChanged(double)));
+ m_ui.label2->setText(QApplication::translate("QtGradientEditor", "Central Y", 0, QApplication::UnicodeUTF8));
+
+ angleConicalSpinBox = m_ui.spinBox3;
+ setSpinBox(angleConicalSpinBox, SLOT(slotAngleConicalChanged(double)), 360.0, 1.0, 1);
+ m_ui.label3->setText(QApplication::translate("QtGradientEditor", "Angle", 0, QApplication::UnicodeUTF8));
+
+ setCentralConical(m_ui.gradientWidget->centralConical());
+ setAngleConical(m_ui.gradientWidget->angleConical());
+
+ spreadEnabled = false;
+ }
+ m_ui.spreadComboBox->setEnabled(spreadEnabled);
+ m_ui.padButton->setEnabled(spreadEnabled);
+ m_ui.repeatButton->setEnabled(spreadEnabled);
+ m_ui.reflectButton->setEnabled(spreadEnabled);
+
+ m_ui.label4->setVisible(row4Visible());
+ m_ui.spinBox4->setVisible(row4Visible());
+ m_ui.label5->setVisible(row5Visible());
+ m_ui.spinBox5->setVisible(row5Visible());
+
+ if (m_gridLayout) {
+ m_gridLayout->setEnabled(ena);
+ }
+}
+
+void QtGradientEditorPrivate::slotGradientStopsChanged(const QGradientStops &stops)
+{
+ m_ui.gradientWidget->setGradientStops(stops);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotTypeChanged(int idx)
+{
+ QGradient::Type type = QGradient::NoGradient;
+ if (idx == 0)
+ type = QGradient::LinearGradient;
+ else if (idx == 1)
+ type = QGradient::RadialGradient;
+ else if (idx == 2)
+ type = QGradient::ConicalGradient;
+ setType(type);
+ m_ui.typeComboBox->setCurrentIndex(idx);
+ m_typeGroup->button(idx)->setChecked(true);
+ m_ui.gradientWidget->setGradientType(type);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotSpreadChanged(int spread)
+{
+ if (spread == 0) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::PadSpread);
+ } else if (spread == 1) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::RepeatSpread);
+ } else if (spread == 2) {
+ m_ui.gradientWidget->setGradientSpread(QGradient::ReflectSpread);
+ }
+ m_ui.spreadComboBox->setCurrentIndex(spread);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotStartLinearXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->startLinear();
+ point.setX(value);
+ m_ui.gradientWidget->setStartLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotStartLinearYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->startLinear();
+ point.setY(value);
+ m_ui.gradientWidget->setStartLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotEndLinearXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->endLinear();
+ point.setX(value);
+ m_ui.gradientWidget->setEndLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotEndLinearYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->endLinear();
+ point.setY(value);
+ m_ui.gradientWidget->setEndLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralRadialXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralRadial();
+ point.setX(value);
+ m_ui.gradientWidget->setCentralRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralRadialYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralRadial();
+ point.setY(value);
+ m_ui.gradientWidget->setCentralRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotFocalRadialXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->focalRadial();
+ point.setX(value);
+ m_ui.gradientWidget->setFocalRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotFocalRadialYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->focalRadial();
+ point.setY(value);
+ m_ui.gradientWidget->setFocalRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotRadiusRadialChanged(double value)
+{
+ m_ui.gradientWidget->setRadiusRadial(value);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralConicalXChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralConical();
+ point.setX(value);
+ m_ui.gradientWidget->setCentralConical(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotCentralConicalYChanged(double value)
+{
+ QPointF point = m_ui.gradientWidget->centralConical();
+ point.setY(value);
+ m_ui.gradientWidget->setCentralConical(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::slotAngleConicalChanged(double value)
+{
+ m_ui.gradientWidget->setAngleConical(value);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::startLinearChanged(const QPointF &point)
+{
+ setStartLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::endLinearChanged(const QPointF &point)
+{
+ setEndLinear(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::centralRadialChanged(const QPointF &point)
+{
+ setCentralRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::focalRadialChanged(const QPointF &point)
+{
+ setFocalRadial(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::radiusRadialChanged(qreal radius)
+{
+ setRadiusRadial(radius);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::centralConicalChanged(const QPointF &point)
+{
+ setCentralConical(point);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::angleConicalChanged(qreal angle)
+{
+ setAngleConical(angle);
+ updateGradient(true);
+}
+
+void QtGradientEditorPrivate::setStartLinear(const QPointF &point)
+{
+ if (startLinearXSpinBox)
+ startLinearXSpinBox->setValue(point.x());
+ if (startLinearYSpinBox)
+ startLinearYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setEndLinear(const QPointF &point)
+{
+ if (endLinearXSpinBox)
+ endLinearXSpinBox->setValue(point.x());
+ if (endLinearYSpinBox)
+ endLinearYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setCentralRadial(const QPointF &point)
+{
+ if (centralRadialXSpinBox)
+ centralRadialXSpinBox->setValue(point.x());
+ if (centralRadialYSpinBox)
+ centralRadialYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setFocalRadial(const QPointF &point)
+{
+ if (focalRadialXSpinBox)
+ focalRadialXSpinBox->setValue(point.x());
+ if (focalRadialYSpinBox)
+ focalRadialYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setRadiusRadial(qreal radius)
+{
+ if (radiusRadialSpinBox)
+ radiusRadialSpinBox->setValue(radius);
+}
+
+void QtGradientEditorPrivate::setCentralConical(const QPointF &point)
+{
+ if (centralConicalXSpinBox)
+ centralConicalXSpinBox->setValue(point.x());
+ if (centralConicalYSpinBox)
+ centralConicalYSpinBox->setValue(point.y());
+}
+
+void QtGradientEditorPrivate::setAngleConical(qreal angle)
+{
+ if (angleConicalSpinBox)
+ angleConicalSpinBox->setValue(angle);
+}
+
+QtGradientEditor::QtGradientEditor(QWidget *parent)
+ : QWidget(parent)
+{
+ d_ptr = new QtGradientEditorPrivate();
+ d_ptr->q_ptr = this;
+ d_ptr->m_type = QGradient::RadialGradient;
+ d_ptr->m_ui.setupUi(this);
+ d_ptr->m_gridLayout = 0;
+ d_ptr->m_hiddenLayout = 0;
+ d_ptr->m_hiddenWidget = 0;
+ bool detailsDefault = false;
+ d_ptr->m_details = !detailsDefault;
+ d_ptr->m_detailsButtonVisible = true;
+ bool checkeredDefault = true;
+ d_ptr->m_backgroundCheckered = !checkeredDefault;
+ d_ptr->m_gradientStopsController = new QtGradientStopsController(this);
+ d_ptr->m_gradientStopsController->setUi(&d_ptr->m_ui);
+ d_ptr->reset();
+ d_ptr->setType(QGradient::LinearGradient);
+ d_ptr->m_combos = true;
+ d_ptr->setCombos(!d_ptr->m_combos);
+
+ d_ptr->showDetails(detailsDefault);
+ setBackgroundCheckered(checkeredDefault);
+
+ d_ptr->setStartLinear(QPointF(0, 0));
+ d_ptr->setEndLinear(QPointF(1, 1));
+ d_ptr->setCentralRadial(QPointF(0.5, 0.5));
+ d_ptr->setFocalRadial(QPointF(0.5, 0.5));
+ d_ptr->setRadiusRadial(0.5);
+ d_ptr->setCentralConical(QPointF(0.5, 0.5));
+ d_ptr->setAngleConical(0);
+
+ QIcon icon;
+ icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowRight), QIcon::Normal, QIcon::Off);
+ icon.addPixmap(style()->standardPixmap(QStyle::SP_ArrowLeft), QIcon::Normal, QIcon::On);
+ d_ptr->m_ui.detailsButton->setIcon(icon);
+
+ connect(d_ptr->m_ui.detailsButton, SIGNAL(clicked(bool)), this, SLOT(slotDetailsChanged(bool)));
+ connect(d_ptr->m_gradientStopsController, SIGNAL(gradientStopsChanged(const QGradientStops &)),
+ this, SLOT(slotGradientStopsChanged(const QGradientStops &)));
+
+ QIcon iconLinear(QLatin1String(":/trolltech/qtgradienteditor/images/typelinear.png"));
+ QIcon iconRadial(QLatin1String(":/trolltech/qtgradienteditor/images/typeradial.png"));
+ QIcon iconConical(QLatin1String(":/trolltech/qtgradienteditor/images/typeconical.png"));
+
+ d_ptr->m_ui.typeComboBox->addItem(iconLinear, tr("Linear"));
+ d_ptr->m_ui.typeComboBox->addItem(iconRadial, tr("Radial"));
+ d_ptr->m_ui.typeComboBox->addItem(iconConical, tr("Conical"));
+
+ d_ptr->m_ui.linearButton->setIcon(iconLinear);
+ d_ptr->m_ui.radialButton->setIcon(iconRadial);
+ d_ptr->m_ui.conicalButton->setIcon(iconConical);
+
+ d_ptr->m_typeGroup = new QButtonGroup(this);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.linearButton, 0);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.radialButton, 1);
+ d_ptr->m_typeGroup->addButton(d_ptr->m_ui.conicalButton, 2);
+
+ connect(d_ptr->m_typeGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(slotTypeChanged(int)));
+ connect(d_ptr->m_ui.typeComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotTypeChanged(int)));
+
+ QIcon iconPad(QLatin1String(":/trolltech/qtgradienteditor/images/spreadpad.png"));
+ QIcon iconRepeat(QLatin1String(":/trolltech/qtgradienteditor/images/spreadrepeat.png"));
+ QIcon iconReflect(QLatin1String(":/trolltech/qtgradienteditor/images/spreadreflect.png"));
+
+ d_ptr->m_ui.spreadComboBox->addItem(iconPad, tr("Pad"));
+ d_ptr->m_ui.spreadComboBox->addItem(iconRepeat, tr("Repeat"));
+ d_ptr->m_ui.spreadComboBox->addItem(iconReflect, tr("Reflect"));
+
+ d_ptr->m_ui.padButton->setIcon(iconPad);
+ d_ptr->m_ui.repeatButton->setIcon(iconRepeat);
+ d_ptr->m_ui.reflectButton->setIcon(iconReflect);
+
+ d_ptr->m_spreadGroup = new QButtonGroup(this);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.padButton, 0);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.repeatButton, 1);
+ d_ptr->m_spreadGroup->addButton(d_ptr->m_ui.reflectButton, 2);
+ connect(d_ptr->m_spreadGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(slotSpreadChanged(int)));
+ connect(d_ptr->m_ui.spreadComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotSpreadChanged(int)));
+
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(startLinearChanged(const QPointF &)),
+ this, SLOT(startLinearChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(endLinearChanged(const QPointF &)),
+ this, SLOT(endLinearChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralRadialChanged(const QPointF &)),
+ this, SLOT(centralRadialChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(focalRadialChanged(const QPointF &)),
+ this, SLOT(focalRadialChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(radiusRadialChanged(qreal)),
+ this, SLOT(radiusRadialChanged(qreal)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(centralConicalChanged(const QPointF &)),
+ this, SLOT(centralConicalChanged(const QPointF &)));
+ connect(d_ptr->m_ui.gradientWidget, SIGNAL(angleConicalChanged(qreal)),
+ this, SLOT(angleConicalChanged(qreal)));
+
+ QGradientStops stops = gradient().stops();
+ d_ptr->m_gradientStopsController->setGradientStops(stops);
+ d_ptr->m_ui.gradientWidget->setGradientStops(stops);
+}
+
+QtGradientEditor::~QtGradientEditor()
+{
+ if (d_ptr->m_hiddenWidget)
+ delete d_ptr->m_hiddenWidget;
+ delete d_ptr;
+}
+
+void QtGradientEditor::setGradient(const QGradient &grad)
+{
+ if (grad == gradient())
+ return;
+
+ QGradient::Type type = grad.type();
+ int idx = 0;
+ switch (type) {
+ case QGradient::LinearGradient: idx = 0; break;
+ case QGradient::RadialGradient: idx = 1; break;
+ case QGradient::ConicalGradient: idx = 2; break;
+ default: return;
+ }
+ d_ptr->setType(type);
+ d_ptr->m_ui.typeComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui.gradientWidget->setGradientType(type);
+ d_ptr->m_typeGroup->button(idx)->setChecked(true);
+
+ QGradient::Spread spread = grad.spread();
+ switch (spread) {
+ case QGradient::PadSpread: idx = 0; break;
+ case QGradient::RepeatSpread: idx = 1; break;
+ case QGradient::ReflectSpread: idx = 2; break;
+ default: idx = 0; break;
+ }
+ d_ptr->m_ui.spreadComboBox->setCurrentIndex(idx);
+ d_ptr->m_ui.gradientWidget->setGradientSpread(spread);
+ d_ptr->m_spreadGroup->button(idx)->setChecked(true);
+
+ if (type == QGradient::LinearGradient) {
+ QLinearGradient *gr = (QLinearGradient *)(&grad);
+ d_ptr->setStartLinear(gr->start());
+ d_ptr->setEndLinear(gr->finalStop());
+ d_ptr->m_ui.gradientWidget->setStartLinear(gr->start());
+ d_ptr->m_ui.gradientWidget->setEndLinear(gr->finalStop());
+ } else if (type == QGradient::RadialGradient) {
+ QRadialGradient *gr = (QRadialGradient *)(&grad);
+ d_ptr->setCentralRadial(gr->center());
+ d_ptr->setFocalRadial(gr->focalPoint());
+ d_ptr->setRadiusRadial(gr->radius());
+ d_ptr->m_ui.gradientWidget->setCentralRadial(gr->center());
+ d_ptr->m_ui.gradientWidget->setFocalRadial(gr->focalPoint());
+ d_ptr->m_ui.gradientWidget->setRadiusRadial(gr->radius());
+ } else if (type == QGradient::ConicalGradient) {
+ QConicalGradient *gr = (QConicalGradient *)(&grad);
+ d_ptr->setCentralConical(gr->center());
+ d_ptr->setAngleConical(gr->angle());
+ d_ptr->m_ui.gradientWidget->setCentralConical(gr->center());
+ d_ptr->m_ui.gradientWidget->setAngleConical(gr->angle());
+ }
+
+ d_ptr->m_gradientStopsController->setGradientStops(grad.stops());
+ d_ptr->m_ui.gradientWidget->setGradientStops(grad.stops());
+ d_ptr->updateGradient(false);
+}
+
+QGradient QtGradientEditor::gradient() const
+{
+ return d_ptr->m_gradient;
+}
+
+bool QtGradientEditor::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtGradientEditor::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+
+ d_ptr->m_backgroundCheckered = checkered;
+ d_ptr->m_ui.hueColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.saturationColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.valueColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.alphaColorLine->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.gradientWidget->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.gradientStopsWidget->setBackgroundCheckered(checkered);
+ d_ptr->m_ui.colorButton->setBackgroundCheckered(checkered);
+}
+
+bool QtGradientEditor::detailsVisible() const
+{
+ return d_ptr->m_details;
+}
+
+void QtGradientEditor::setDetailsVisible(bool visible)
+{
+ d_ptr->showDetails(visible);
+}
+
+bool QtGradientEditor::isDetailsButtonVisible() const
+{
+ return d_ptr->m_detailsButtonVisible;
+}
+
+void QtGradientEditor::setDetailsButtonVisible(bool visible)
+{
+ if (d_ptr->m_detailsButtonVisible == visible)
+ return;
+
+ d_ptr->m_detailsButtonVisible = visible;
+ d_ptr->m_ui.detailsButton->setVisible(visible);
+}
+
+QColor::Spec QtGradientEditor::spec() const
+{
+ return d_ptr->m_gradientStopsController->spec();
+}
+
+void QtGradientEditor::setSpec(QColor::Spec spec)
+{
+ d_ptr->m_gradientStopsController->setSpec(spec);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradienteditor.cpp"
diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.h b/tools/shared/qtgradienteditor/qtgradienteditor.h
new file mode 100644
index 0000000000..9974065685
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradienteditor.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTEDITOR_H
+#define QTGRADIENTEDITOR_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientEditor : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient)
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+ Q_PROPERTY(bool detailsVisible READ detailsVisible WRITE setDetailsVisible)
+ Q_PROPERTY(bool detailsButtonVisible READ isDetailsButtonVisible WRITE setDetailsButtonVisible)
+public:
+ QtGradientEditor(QWidget *parent = 0);
+ ~QtGradientEditor();
+
+ void setGradient(const QGradient &gradient);
+ QGradient gradient() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ bool detailsVisible() const;
+ void setDetailsVisible(bool visible);
+
+ bool isDetailsButtonVisible() const;
+ void setDetailsButtonVisible(bool visible);
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+signals:
+
+ void gradientChanged(const QGradient &gradient);
+ void aboutToShowDetails(bool details, int extenstionWidthHint);
+
+private:
+ class QtGradientEditorPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientEditor)
+ Q_DISABLE_COPY(QtGradientEditor)
+ Q_PRIVATE_SLOT(d_func(), void slotGradientStopsChanged(const QGradientStops &stops))
+ Q_PRIVATE_SLOT(d_func(), void slotTypeChanged(int type))
+ Q_PRIVATE_SLOT(d_func(), void slotSpreadChanged(int type))
+ Q_PRIVATE_SLOT(d_func(), void slotStartLinearXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotStartLinearYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotEndLinearXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotEndLinearYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralRadialXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralRadialYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotFocalRadialXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotFocalRadialYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotRadiusRadialChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralConicalXChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotCentralConicalYChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotAngleConicalChanged(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotDetailsChanged(bool details))
+ Q_PRIVATE_SLOT(d_func(), void startLinearChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void endLinearChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void centralRadialChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void focalRadialChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void radiusRadialChanged(qreal))
+ Q_PRIVATE_SLOT(d_func(), void centralConicalChanged(const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void angleConicalChanged(qreal))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.pri b/tools/shared/qtgradienteditor/qtgradienteditor.pri
new file mode 100644
index 0000000000..4cf059e1f2
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradienteditor.pri
@@ -0,0 +1,33 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+FORMS += $$PWD/qtgradienteditor.ui \
+ $$PWD/qtgradientdialog.ui \
+ $$PWD/qtgradientview.ui \
+ $$PWD/qtgradientviewdialog.ui
+SOURCES += $$PWD/qtgradientstopsmodel.cpp \
+ $$PWD/qtgradientstopswidget.cpp \
+ $$PWD/qtgradientstopscontroller.cpp \
+ $$PWD/qtgradientwidget.cpp \
+ $$PWD/qtgradienteditor.cpp \
+ $$PWD/qtgradientdialog.cpp \
+ $$PWD/qtcolorbutton.cpp \
+ $$PWD/qtcolorline.cpp \
+ $$PWD/qtgradientview.cpp \
+ $$PWD/qtgradientviewdialog.cpp \
+ $$PWD/qtgradientmanager.cpp \
+ $$PWD/qtgradientutils.cpp
+HEADERS += $$PWD/qtgradientstopsmodel.h \
+ $$PWD/qtgradientstopswidget.h \
+ $$PWD/qtgradientstopscontroller.h \
+ $$PWD/qtgradientwidget.h \
+ $$PWD/qtgradienteditor.h \
+ $$PWD/qtgradientdialog.h \
+ $$PWD/qtcolorbutton.h \
+ $$PWD/qtcolorline.h \
+ $$PWD/qtgradientview.h \
+ $$PWD/qtgradientviewdialog.h \
+ $$PWD/qtgradientmanager.h \
+ $$PWD/qtgradientutils.h
+RESOURCES += $$PWD/qtgradienteditor.qrc
+
+QT += xml
diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.qrc b/tools/shared/qtgradienteditor/qtgradienteditor.qrc
new file mode 100644
index 0000000000..cce7ba6224
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradienteditor.qrc
@@ -0,0 +1,18 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource prefix="/trolltech/qtgradienteditor">
+ <file>images/edit.png</file>
+ <file>images/zoomin.png</file>
+ <file>images/zoomout.png</file>
+ <file>images/up.png</file>
+ <file>images/down.png</file>
+ <file>images/plus.png</file>
+ <file>images/minus.png</file>
+ <file>images/editdelete.png</file>
+ <file>images/spreadpad.png</file>
+ <file>images/spreadrepeat.png</file>
+ <file>images/spreadreflect.png</file>
+ <file>images/typelinear.png</file>
+ <file>images/typeradial.png</file>
+ <file>images/typeconical.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/shared/qtgradienteditor/qtgradienteditor.ui b/tools/shared/qtgradienteditor/qtgradienteditor.ui
new file mode 100644
index 0000000000..4d103e342d
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradienteditor.ui
@@ -0,0 +1,1377 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>QtGradientEditor</class>
+ <widget class="QWidget" name="QtGradientEditor" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>364</width>
+ <height>518</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <widget class="QFrame" name="frame" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>69</y>
+ <width>193</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtGradientWidget" native="1" name="gradientWidget" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Gradient Editor</string>
+ </property>
+ <property name="whatsThis" >
+ <string>This area shows a preview of the gradient being edited. It also allows you to edit parameters specific to the gradient's type such as start and final point, radius, etc. by drag &amp; drop.</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="label1" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>69</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>1</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox1" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>69</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label2" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>99</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>2</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox2" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>99</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label3" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>129</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>3</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox3" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>129</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label4" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>159</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>4</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox4" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>159</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label5" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>189</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>5</string>
+ </property>
+ </widget>
+ <widget class="QDoubleSpinBox" name="spinBox5" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>189</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ </widget>
+ <widget class="QtGradientStopsWidget" native="1" name="gradientStopsWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>225</y>
+ <width>193</width>
+ <height>67</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Gradient Stops Editor</string>
+ </property>
+ <property name="whatsThis" >
+ <string>This area allows you to edit gradient stops. Double click on the existing stop handle to duplicate it. Double click outside of the existing stop handles to create a new stop. Drag &amp; drop the handle to reposition it. Use right mouse button to popup context menu with extra actions.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="zoomLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>231</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>Zoom</string>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="zoomAllButton" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>260</y>
+ <width>72</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Reset Zoom</string>
+ </property>
+ <property name="text" >
+ <string>Reset Zoom</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="positionLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>304</y>
+ <width>64</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>Position</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="hLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>335</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Hue</string>
+ </property>
+ <property name="text" >
+ <string>H</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_2" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>333</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="hueColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Hue</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="hueLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>335</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Hue</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="sLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>364</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Saturation</string>
+ </property>
+ <property name="text" >
+ <string>S</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_5" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>362</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="saturationColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Saturation</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="saturationLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>364</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Sat</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="vLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>393</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Value</string>
+ </property>
+ <property name="text" >
+ <string>V</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_3" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>391</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="valueColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Value</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="valueLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>393</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Val</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="aLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>422</y>
+ <width>32</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Alpha</string>
+ </property>
+ <property name="text" >
+ <string>A</string>
+ </property>
+ </widget>
+ <widget class="QFrame" name="frame_4" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>420</y>
+ <width>155</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Ignored" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QtColorLine" native="1" name="alphaColorLine" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Expanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Alpha</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QLabel" name="alphaLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>422</y>
+ <width>64</width>
+ <height>18</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Alpha</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="typeComboBox" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>79</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Type</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="spreadComboBox" >
+ <property name="geometry" >
+ <rect>
+ <x>96</x>
+ <y>40</y>
+ <width>72</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Spread</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="colorLabel" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>298</y>
+ <width>32</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Color</string>
+ </property>
+ </widget>
+ <widget class="QtColorButton" name="colorButton" >
+ <property name="geometry" >
+ <rect>
+ <x>48</x>
+ <y>300</y>
+ <width>26</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Current stop's color</string>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ </widget>
+ <widget class="QRadioButton" name="hsvRadioButton" >
+ <property name="geometry" >
+ <rect>
+ <x>80</x>
+ <y>301</y>
+ <width>49</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Show HSV specification</string>
+ </property>
+ <property name="text" >
+ <string>HSV</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" name="rgbRadioButton" >
+ <property name="geometry" >
+ <rect>
+ <x>135</x>
+ <y>301</y>
+ <width>49</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Show RGB specification</string>
+ </property>
+ <property name="text" >
+ <string>RGB</string>
+ </property>
+ </widget>
+ <widget class="QWidget" native="1" name="positionWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>304</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QDoubleSpinBox" name="positionSpinBox" >
+ <property name="toolTip" >
+ <string>Current stop's position</string>
+ </property>
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="decimals" >
+ <number>3</number>
+ </property>
+ <property name="minimum" >
+ <double>0.000000000000000</double>
+ </property>
+ <property name="maximum" >
+ <double>1.000000000000000</double>
+ </property>
+ <property name="singleStep" >
+ <double>0.010000000000000</double>
+ </property>
+ <property name="value" >
+ <double>0.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="hueWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>333</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="hueSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>359</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="saturationWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>362</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="saturationSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="valueWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>391</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="valueSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="alphaWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>420</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="alphaSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="maximum" >
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="zoomWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>279</x>
+ <y>231</y>
+ <width>73</width>
+ <height>23</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QSpinBox" name="zoomSpinBox" >
+ <property name="keyboardTracking" >
+ <bool>false</bool>
+ </property>
+ <property name="suffix" >
+ <string>%</string>
+ </property>
+ <property name="minimum" >
+ <number>100</number>
+ </property>
+ <property name="maximum" >
+ <number>10000</number>
+ </property>
+ <property name="singleStep" >
+ <number>100</number>
+ </property>
+ <property name="value" >
+ <number>100</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="line1Widget" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>219</y>
+ <width>143</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="Line" name="line1" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="line2Widget" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>292</y>
+ <width>143</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="Line" name="line2" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" native="1" name="zoomButtonsWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>209</x>
+ <y>260</y>
+ <width>64</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="zoomInButton" >
+ <property name="toolTip" >
+ <string>Zoom In</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="zoomOutButton" >
+ <property name="toolTip" >
+ <string>Zoom Out</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QToolButton" name="detailsButton" >
+ <property name="geometry" >
+ <rect>
+ <x>176</x>
+ <y>40</y>
+ <width>25</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Ignored" hsizetype="Fixed" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Toggle details extension</string>
+ </property>
+ <property name="text" >
+ <string>></string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="linearButton" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Linear Type</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="radialButton" >
+ <property name="geometry" >
+ <rect>
+ <x>40</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Radial Type</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="conicalButton" >
+ <property name="geometry" >
+ <rect>
+ <x>70</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Conical Type</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="padButton" >
+ <property name="geometry" >
+ <rect>
+ <x>110</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Pad Spread</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="repeatButton" >
+ <property name="geometry" >
+ <rect>
+ <x>140</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Repeat Spread</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QToolButton" name="reflectButton" >
+ <property name="geometry" >
+ <rect>
+ <x>170</x>
+ <y>10</y>
+ <width>30</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="toolTip" >
+ <string>Reflect Spread</string>
+ </property>
+ <property name="text" >
+ <string>...</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtColorButton</class>
+ <extends>QToolButton</extends>
+ <header>qtcolorbutton.h</header>
+ </customwidget>
+ <customwidget>
+ <class>QtColorLine</class>
+ <extends>QWidget</extends>
+ <header>qtcolorline.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QtGradientStopsWidget</class>
+ <extends>QWidget</extends>
+ <header>qtgradientstopswidget.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>QtGradientWidget</class>
+ <extends>QWidget</extends>
+ <header>qtgradientwidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>typeComboBox</tabstop>
+ <tabstop>spreadComboBox</tabstop>
+ <tabstop>detailsButton</tabstop>
+ <tabstop>spinBox1</tabstop>
+ <tabstop>spinBox2</tabstop>
+ <tabstop>spinBox3</tabstop>
+ <tabstop>spinBox4</tabstop>
+ <tabstop>spinBox5</tabstop>
+ <tabstop>zoomSpinBox</tabstop>
+ <tabstop>zoomInButton</tabstop>
+ <tabstop>zoomOutButton</tabstop>
+ <tabstop>zoomAllButton</tabstop>
+ <tabstop>colorButton</tabstop>
+ <tabstop>hsvRadioButton</tabstop>
+ <tabstop>rgbRadioButton</tabstop>
+ <tabstop>positionSpinBox</tabstop>
+ <tabstop>hueSpinBox</tabstop>
+ <tabstop>saturationSpinBox</tabstop>
+ <tabstop>valueSpinBox</tabstop>
+ <tabstop>alphaSpinBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/shared/qtgradienteditor/qtgradientmanager.cpp b/tools/shared/qtgradienteditor/qtgradientmanager.cpp
new file mode 100644
index 0000000000..51b5d96ff5
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientmanager.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientmanager.h"
+#include <QtGui/QPixmap>
+#include <QtCore/QMetaEnum>
+
+QT_BEGIN_NAMESPACE
+
+QtGradientManager::QtGradientManager(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QMap<QString, QGradient> QtGradientManager::gradients() const
+{
+ return m_idToGradient;
+}
+
+QString QtGradientManager::uniqueId(const QString &id) const
+{
+ if (!m_idToGradient.contains(id))
+ return id;
+
+ QString base = id;
+ while (base.count() > 0 && base.at(base.count() - 1).isDigit())
+ base = base.left(base.count() - 1);
+ QString newId = base;
+ int counter = 0;
+ while (m_idToGradient.contains(newId)) {
+ ++counter;
+ newId = base + QString::number(counter);
+ }
+ return newId;
+}
+
+QString QtGradientManager::addGradient(const QString &id, const QGradient &gradient)
+{
+ QString newId = uniqueId(id);
+
+ m_idToGradient[newId] = gradient;
+
+ emit gradientAdded(newId, gradient);
+
+ return newId;
+}
+
+void QtGradientManager::removeGradient(const QString &id)
+{
+ if (!m_idToGradient.contains(id))
+ return;
+
+ emit gradientRemoved(id);
+
+ m_idToGradient.remove(id);
+}
+
+void QtGradientManager::renameGradient(const QString &id, const QString &newId)
+{
+ if (!m_idToGradient.contains(id))
+ return;
+
+ if (newId == id)
+ return;
+
+ QString changedId = uniqueId(newId);
+ QGradient gradient = m_idToGradient.value(id);
+
+ emit gradientRenamed(id, changedId);
+
+ m_idToGradient.remove(id);
+ m_idToGradient[changedId] = gradient;
+}
+
+void QtGradientManager::changeGradient(const QString &id, const QGradient &newGradient)
+{
+ if (!m_idToGradient.contains(id))
+ return;
+
+ if (m_idToGradient.value(id) == newGradient)
+ return;
+
+ emit gradientChanged(id, newGradient);
+
+ m_idToGradient[id] = newGradient;
+}
+
+void QtGradientManager::clear()
+{
+ QMap<QString, QGradient> grads = gradients();
+ QMapIterator<QString, QGradient> itGrad(grads);
+ while (itGrad.hasNext()) {
+ removeGradient(itGrad.next().key());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/qtgradienteditor/qtgradientmanager.h b/tools/shared/qtgradienteditor/qtgradientmanager.h
new file mode 100644
index 0000000000..ff9ebf7c2d
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientmanager.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTMANAGER_H
+#define GRADIENTMANAGER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+#include <QtCore/QSize>
+#include <QtXml/QDomDocument>
+#include <QtXml/QDomElement>
+#include <QtGui/QGradient>
+
+QT_BEGIN_NAMESPACE
+
+class QGradient;
+class QPixmap;
+class QColor;
+
+class QtGradientManager : public QObject
+{
+ Q_OBJECT
+public:
+ QtGradientManager(QObject *parent = 0);
+
+ QMap<QString, QGradient> gradients() const;
+
+ QString uniqueId(const QString &id) const;
+
+public slots:
+
+ QString addGradient(const QString &id, const QGradient &gradient);
+ void renameGradient(const QString &id, const QString &newId);
+ void changeGradient(const QString &id, const QGradient &newGradient);
+ void removeGradient(const QString &id);
+
+ //utils
+ void clear();
+
+signals:
+
+ void gradientAdded(const QString &id, const QGradient &gradient);
+ void gradientRenamed(const QString &id, const QString &newId);
+ void gradientChanged(const QString &id, const QGradient &newGradient);
+ void gradientRemoved(const QString &id);
+
+private:
+
+ QMap<QString, QGradient> m_idToGradient;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientstopscontroller.cpp b/tools/shared/qtgradienteditor/qtgradientstopscontroller.cpp
new file mode 100644
index 0000000000..cbc53dbaf3
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientstopscontroller.cpp
@@ -0,0 +1,730 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+TRANSLATOR qdesigner_internal::QtGradientStopsController
+*/
+
+#include "qtgradientstopscontroller.h"
+#include "ui_qtgradienteditor.h"
+#include "qtgradientstopsmodel.h"
+
+#include <QtCore/QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopsControllerPrivate
+{
+ QtGradientStopsController *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientStopsController)
+public:
+ typedef QMap<qreal, QColor> PositionColorMap;
+ typedef QMap<qreal, QtGradientStop *> PositionStopMap;
+
+ void slotHsvClicked();
+ void slotRgbClicked();
+
+ void slotCurrentStopChanged(QtGradientStop *stop);
+ void slotStopMoved(QtGradientStop *stop, qreal newPos);
+ void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
+ void slotStopChanged(QtGradientStop *stop, const QColor &newColor);
+ void slotStopSelected(QtGradientStop *stop, bool selected);
+ void slotStopAdded(QtGradientStop *stop);
+ void slotStopRemoved(QtGradientStop *stop);
+ void slotUpdatePositionSpinBox();
+
+ void slotChangeColor(const QColor &color);
+ void slotChangeHue(const QColor &color);
+ void slotChangeSaturation(const QColor &color);
+ void slotChangeValue(const QColor &color);
+ void slotChangeAlpha(const QColor &color);
+ void slotChangeHue(int color);
+ void slotChangeSaturation(int color);
+ void slotChangeValue(int color);
+ void slotChangeAlpha(int color);
+ void slotChangePosition(double value);
+
+ void slotChangeZoom(int value);
+ void slotZoomIn();
+ void slotZoomOut();
+ void slotZoomAll();
+ void slotZoomChanged(double zoom);
+
+ void enableCurrent(bool enable);
+ void setColorSpinBoxes(const QColor &color);
+ PositionColorMap stopsData(const PositionStopMap &stops) const;
+ QGradientStops makeGradientStops(const PositionColorMap &data) const;
+ void updateZoom(double zoom);
+
+ QtGradientStopsModel *m_model;
+ QColor::Spec m_spec;
+
+ Ui::QtGradientEditor *m_ui;
+};
+
+void QtGradientStopsControllerPrivate::enableCurrent(bool enable)
+{
+ m_ui->positionLabel->setEnabled(enable);
+ m_ui->colorLabel->setEnabled(enable);
+ m_ui->hLabel->setEnabled(enable);
+ m_ui->sLabel->setEnabled(enable);
+ m_ui->vLabel->setEnabled(enable);
+ m_ui->aLabel->setEnabled(enable);
+ m_ui->hueLabel->setEnabled(enable);
+ m_ui->saturationLabel->setEnabled(enable);
+ m_ui->valueLabel->setEnabled(enable);
+ m_ui->alphaLabel->setEnabled(enable);
+
+ m_ui->positionSpinBox->setEnabled(enable);
+ m_ui->colorButton->setEnabled(enable);
+
+ m_ui->hueColorLine->setEnabled(enable);
+ m_ui->saturationColorLine->setEnabled(enable);
+ m_ui->valueColorLine->setEnabled(enable);
+ m_ui->alphaColorLine->setEnabled(enable);
+
+ m_ui->hueSpinBox->setEnabled(enable);
+ m_ui->saturationSpinBox->setEnabled(enable);
+ m_ui->valueSpinBox->setEnabled(enable);
+ m_ui->alphaSpinBox->setEnabled(enable);
+}
+
+QtGradientStopsControllerPrivate::PositionColorMap QtGradientStopsControllerPrivate::stopsData(const PositionStopMap &stops) const
+{
+ PositionColorMap data;
+ PositionStopMap::ConstIterator itStop = stops.constBegin();
+ while (itStop != stops.constEnd()) {
+ QtGradientStop *stop = itStop.value();
+ data[stop->position()] = stop->color();
+
+ ++itStop;
+ }
+ return data;
+}
+
+QGradientStops QtGradientStopsControllerPrivate::makeGradientStops(const PositionColorMap &data) const
+{
+ QGradientStops stops;
+ PositionColorMap::ConstIterator itData = data.constBegin();
+ while (itData != data.constEnd()) {
+ stops << QPair<qreal, QColor>(itData.key(), itData.value());
+
+ ++itData;
+ }
+ return stops;
+}
+
+void QtGradientStopsControllerPrivate::updateZoom(double zoom)
+{
+ m_ui->gradientStopsWidget->setZoom(zoom);
+ m_ui->zoomSpinBox->blockSignals(true);
+ m_ui->zoomSpinBox->setValue(qRound(zoom * 100));
+ m_ui->zoomSpinBox->blockSignals(false);
+ bool zoomInEnabled = true;
+ bool zoomOutEnabled = true;
+ bool zoomAllEnabled = true;
+ if (zoom <= 1) {
+ zoomAllEnabled = false;
+ zoomOutEnabled = false;
+ } else if (zoom >= 100) {
+ zoomInEnabled = false;
+ }
+ m_ui->zoomInButton->setEnabled(zoomInEnabled);
+ m_ui->zoomOutButton->setEnabled(zoomOutEnabled);
+ m_ui->zoomAllButton->setEnabled(zoomAllEnabled);
+}
+
+void QtGradientStopsControllerPrivate::slotHsvClicked()
+{
+ QString h = QApplication::translate("qdesigner_internal::QtGradientStopsController", "H", 0, QApplication::UnicodeUTF8);
+ QString s = QApplication::translate("qdesigner_internal::QtGradientStopsController", "S", 0, QApplication::UnicodeUTF8);
+ QString v = QApplication::translate("qdesigner_internal::QtGradientStopsController", "V", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setText(h);
+ m_ui->sLabel->setText(s);
+ m_ui->vLabel->setText(v);
+
+ h = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Hue", 0, QApplication::UnicodeUTF8);
+ s = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Sat", 0, QApplication::UnicodeUTF8);
+ v = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Val", 0, QApplication::UnicodeUTF8);
+
+ const QString hue = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Hue", 0, QApplication::UnicodeUTF8);
+ const QString saturation = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Saturation", 0, QApplication::UnicodeUTF8);
+ const QString value = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Value", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setToolTip(hue);
+ m_ui->hueLabel->setText(h);
+ m_ui->hueColorLine->setToolTip(hue);
+ m_ui->hueColorLine->setColorComponent(QtColorLine::Hue);
+
+ m_ui->sLabel->setToolTip(saturation);
+ m_ui->saturationLabel->setText(s);
+ m_ui->saturationColorLine->setToolTip(saturation);
+ m_ui->saturationColorLine->setColorComponent(QtColorLine::Saturation);
+
+ m_ui->vLabel->setToolTip(value);
+ m_ui->valueLabel->setText(v);
+ m_ui->valueColorLine->setToolTip(value);
+ m_ui->valueColorLine->setColorComponent(QtColorLine::Value);
+
+ setColorSpinBoxes(m_ui->colorButton->color());
+}
+
+void QtGradientStopsControllerPrivate::slotRgbClicked()
+{
+ QString r = QApplication::translate("qdesigner_internal::QtGradientStopsController", "R", 0, QApplication::UnicodeUTF8);
+ QString g = QApplication::translate("qdesigner_internal::QtGradientStopsController", "G", 0, QApplication::UnicodeUTF8);
+ QString b = QApplication::translate("qdesigner_internal::QtGradientStopsController", "B", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setText(r);
+ m_ui->sLabel->setText(g);
+ m_ui->vLabel->setText(b);
+
+ QString red = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Red", 0, QApplication::UnicodeUTF8);
+ QString green = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Green", 0, QApplication::UnicodeUTF8);
+ QString blue = QApplication::translate("qdesigner_internal::QtGradientStopsController", "Blue", 0, QApplication::UnicodeUTF8);
+
+ m_ui->hLabel->setToolTip(red);
+ m_ui->hueLabel->setText(red);
+ m_ui->hueColorLine->setToolTip(red);
+ m_ui->hueColorLine->setColorComponent(QtColorLine::Red);
+
+ m_ui->sLabel->setToolTip(green);
+ m_ui->saturationLabel->setText(green);
+ m_ui->saturationColorLine->setToolTip(green);
+ m_ui->saturationColorLine->setColorComponent(QtColorLine::Green);
+
+ m_ui->vLabel->setToolTip(blue);
+ m_ui->valueLabel->setText(blue);
+ m_ui->valueColorLine->setToolTip(blue);
+ m_ui->valueColorLine->setColorComponent(QtColorLine::Blue);
+
+ setColorSpinBoxes(m_ui->colorButton->color());
+}
+
+void QtGradientStopsControllerPrivate::setColorSpinBoxes(const QColor &color)
+{
+ m_ui->hueSpinBox->blockSignals(true);
+ m_ui->saturationSpinBox->blockSignals(true);
+ m_ui->valueSpinBox->blockSignals(true);
+ m_ui->alphaSpinBox->blockSignals(true);
+ if (m_ui->hsvRadioButton->isChecked()) {
+ if (m_ui->hueSpinBox->maximum() != 359)
+ m_ui->hueSpinBox->setMaximum(359);
+ if (m_ui->hueSpinBox->value() != color.hue())
+ m_ui->hueSpinBox->setValue(color.hue());
+ if (m_ui->saturationSpinBox->value() != color.saturation())
+ m_ui->saturationSpinBox->setValue(color.saturation());
+ if (m_ui->valueSpinBox->value() != color.value())
+ m_ui->valueSpinBox->setValue(color.value());
+ } else {
+ if (m_ui->hueSpinBox->maximum() != 255)
+ m_ui->hueSpinBox->setMaximum(255);
+ if (m_ui->hueSpinBox->value() != color.red())
+ m_ui->hueSpinBox->setValue(color.red());
+ if (m_ui->saturationSpinBox->value() != color.green())
+ m_ui->saturationSpinBox->setValue(color.green());
+ if (m_ui->valueSpinBox->value() != color.blue())
+ m_ui->valueSpinBox->setValue(color.blue());
+ }
+ m_ui->alphaSpinBox->setValue(color.alpha());
+ m_ui->hueSpinBox->blockSignals(false);
+ m_ui->saturationSpinBox->blockSignals(false);
+ m_ui->valueSpinBox->blockSignals(false);
+ m_ui->alphaSpinBox->blockSignals(false);
+}
+
+void QtGradientStopsControllerPrivate::slotCurrentStopChanged(QtGradientStop *stop)
+{
+ if (!stop) {
+ enableCurrent(false);
+ return;
+ }
+ enableCurrent(true);
+
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+
+ m_ui->colorButton->setColor(stop->color());
+ m_ui->hueColorLine->setColor(stop->color());
+ m_ui->saturationColorLine->setColor(stop->color());
+ m_ui->valueColorLine->setColor(stop->color());
+ m_ui->alphaColorLine->setColor(stop->color());
+ setColorSpinBoxes(stop->color());
+}
+
+void QtGradientStopsControllerPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos)
+{
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops.remove(stop->position());
+ stops[newPos] = stop->color();
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)
+{
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+
+ PositionColorMap stops = stopsData(m_model->stops());
+ const qreal pos1 = stop1->position();
+ const qreal pos2 = stop2->position();
+ stops[pos1] = stop2->color();
+ stops[pos2] = stop1->color();
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopAdded(QtGradientStop *stop)
+{
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops[stop->position()] = stop->color();
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopRemoved(QtGradientStop *stop)
+{
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops.remove(stop->position());
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor)
+{
+ if (m_model->currentStop() == stop) {
+ m_ui->colorButton->setColor(newColor);
+ m_ui->hueColorLine->setColor(newColor);
+ m_ui->saturationColorLine->setColor(newColor);
+ m_ui->valueColorLine->setColor(newColor);
+ m_ui->alphaColorLine->setColor(newColor);
+ setColorSpinBoxes(newColor);
+ }
+
+ PositionColorMap stops = stopsData(m_model->stops());
+ stops[stop->position()] = newColor;
+
+ QGradientStops gradStops = makeGradientStops(stops);
+ emit q_ptr->gradientStopsChanged(gradStops);
+}
+
+void QtGradientStopsControllerPrivate::slotStopSelected(QtGradientStop *stop, bool selected)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(selected)
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdatePositionSpinBox()));
+}
+
+void QtGradientStopsControllerPrivate::slotUpdatePositionSpinBox()
+{
+ QtGradientStop *current = m_model->currentStop();
+ if (!current)
+ return;
+
+ qreal min = 0.0;
+ qreal max = 1.0;
+ const qreal pos = current->position();
+
+ QtGradientStop *first = m_model->firstSelected();
+ QtGradientStop *last = m_model->lastSelected();
+
+ if (first && last) {
+ const qreal minPos = pos - first->position() - 0.0004999;
+ const qreal maxPos = pos + 1.0 - last->position() + 0.0004999;
+
+ if (max > maxPos)
+ max = maxPos;
+ if (min < minPos)
+ min = minPos;
+
+ if (first->position() == 0.0)
+ min = pos;
+ if (last->position() == 1.0)
+ max = pos;
+ }
+
+ const int spinMin = qRound(m_ui->positionSpinBox->minimum() * 1000);
+ const int spinMax = qRound(m_ui->positionSpinBox->maximum() * 1000);
+
+ const int newMin = qRound(min * 1000);
+ const int newMax = qRound(max * 1000);
+
+ m_ui->positionSpinBox->blockSignals(true);
+ if (spinMin != newMin || spinMax != newMax) {
+ m_ui->positionSpinBox->setRange((double)newMin / 1000, (double)newMax / 1000);
+ }
+ if (m_ui->positionSpinBox->value() != pos)
+ m_ui->positionSpinBox->setValue(pos);
+ m_ui->positionSpinBox->blockSignals(false);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeColor(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop)
+ m_model->changeStop(s, color);
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeHue(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(color.hueF(), c.saturationF(), c.valueF(), c.alphaF());
+ else
+ c.setRgbF(color.redF(), c.greenF(), c.blueF(), c.alphaF());
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeHue(int color)
+{
+ QColor c = m_ui->hueColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF((qreal)color / 360.0, c.saturationF(), c.valueF(), c.alphaF());
+ else
+ c.setRed(color);
+ slotChangeHue(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeSaturation(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked()) {
+ c.setHsvF(c.hueF(), color.saturationF(), c.valueF(), c.alphaF());
+ int hue = c.hue();
+ if (hue == 360 || hue == -1)
+ c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF());
+ } else {
+ c.setRgbF(c.redF(), color.greenF(), c.blueF(), c.alphaF());
+ }
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeSaturation(int color)
+{
+ QColor c = m_ui->saturationColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(c.hueF(), (qreal)color / 255, c.valueF(), c.alphaF());
+ else
+ c.setGreen(color);
+ slotChangeSaturation(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeValue(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked()) {
+ c.setHsvF(c.hueF(), c.saturationF(), color.valueF(), c.alphaF());
+ int hue = c.hue();
+ if (hue == 360 || hue == -1)
+ c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF());
+ } else {
+ c.setRgbF(c.redF(), c.greenF(), color.blueF(), c.alphaF());
+ }
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeValue(int color)
+{
+ QColor c = m_ui->valueColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(c.hueF(), c.saturationF(), (qreal)color / 255, c.alphaF());
+ else
+ c.setBlue(color);
+ slotChangeValue(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeAlpha(const QColor &color)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+ m_model->changeStop(stop, color);
+ QList<QtGradientStop *> stops = m_model->selectedStops();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (s != stop) {
+ QColor c = s->color();
+ if (m_ui->hsvRadioButton->isChecked()) {
+ c.setHsvF(c.hueF(), c.saturationF(), c.valueF(), color.alphaF());
+ int hue = c.hue();
+ if (hue == 360 || hue == -1)
+ c.setHsvF(0.0, c.saturationF(), c.valueF(), c.alphaF());
+ } else {
+ c.setRgbF(c.redF(), c.greenF(), c.blueF(), color.alphaF());
+ }
+ m_model->changeStop(s, c);
+ }
+ }
+}
+
+void QtGradientStopsControllerPrivate::slotChangeAlpha(int color)
+{
+ QColor c = m_ui->alphaColorLine->color();
+ if (m_ui->hsvRadioButton->isChecked())
+ c.setHsvF(c.hueF(), c.saturationF(), c.valueF(), (qreal)color / 255);
+ else
+ c.setAlpha(color);
+ slotChangeAlpha(c);
+}
+
+void QtGradientStopsControllerPrivate::slotChangePosition(double value)
+{
+ QtGradientStop *stop = m_model->currentStop();
+ if (!stop)
+ return;
+
+ m_model->moveStops(value);
+}
+
+void QtGradientStopsControllerPrivate::slotChangeZoom(int value)
+{
+ updateZoom(value / 100.0);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomIn()
+{
+ double newZoom = m_ui->gradientStopsWidget->zoom() * 2;
+ if (newZoom > 100)
+ newZoom = 100;
+ updateZoom(newZoom);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomOut()
+{
+ double newZoom = m_ui->gradientStopsWidget->zoom() / 2;
+ if (newZoom < 1)
+ newZoom = 1;
+ updateZoom(newZoom);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomAll()
+{
+ updateZoom(1);
+}
+
+void QtGradientStopsControllerPrivate::slotZoomChanged(double zoom)
+{
+ updateZoom(zoom);
+}
+
+QtGradientStopsController::QtGradientStopsController(QObject *parent)
+ : QObject(parent)
+{
+ d_ptr = new QtGradientStopsControllerPrivate();
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_spec = QColor::Hsv;
+}
+
+void QtGradientStopsController::setUi(Ui::QtGradientEditor *ui)
+{
+ d_ptr->m_ui = ui;
+
+ d_ptr->m_ui->hueColorLine->setColorComponent(QtColorLine::Hue);
+ d_ptr->m_ui->saturationColorLine->setColorComponent(QtColorLine::Saturation);
+ d_ptr->m_ui->valueColorLine->setColorComponent(QtColorLine::Value);
+ d_ptr->m_ui->alphaColorLine->setColorComponent(QtColorLine::Alpha);
+
+ d_ptr->m_model = new QtGradientStopsModel(this);
+ d_ptr->m_ui->gradientStopsWidget->setGradientStopsModel(d_ptr->m_model);
+ connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop *)),
+ this, SLOT(slotCurrentStopChanged(QtGradientStop *)));
+ connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop *, qreal)),
+ this, SLOT(slotStopMoved(QtGradientStop *, qreal)));
+ connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop *, QtGradientStop *)),
+ this, SLOT(slotStopsSwapped(QtGradientStop *, QtGradientStop *)));
+ connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop *, const QColor &)),
+ this, SLOT(slotStopChanged(QtGradientStop *, const QColor &)));
+ connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop *, bool)),
+ this, SLOT(slotStopSelected(QtGradientStop *, bool)));
+ connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop *)),
+ this, SLOT(slotStopAdded(QtGradientStop *)));
+ connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop *)),
+ this, SLOT(slotStopRemoved(QtGradientStop *)));
+
+ connect(d_ptr->m_ui->hueColorLine, SIGNAL(colorChanged(const QColor &)),
+ this, SLOT(slotChangeHue(const QColor &)));
+ connect(d_ptr->m_ui->saturationColorLine, SIGNAL(colorChanged(const QColor &)),
+ this, SLOT(slotChangeSaturation(const QColor &)));
+ connect(d_ptr->m_ui->valueColorLine, SIGNAL(colorChanged(const QColor &)),
+ this, SLOT(slotChangeValue(const QColor &)));
+ connect(d_ptr->m_ui->alphaColorLine, SIGNAL(colorChanged(const QColor &)),
+ this, SLOT(slotChangeAlpha(const QColor &)));
+ connect(d_ptr->m_ui->colorButton, SIGNAL(colorChanged(const QColor &)),
+ this, SLOT(slotChangeColor(const QColor &)));
+
+ connect(d_ptr->m_ui->hueSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeHue(int)));
+ connect(d_ptr->m_ui->saturationSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeSaturation(int)));
+ connect(d_ptr->m_ui->valueSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeValue(int)));
+ connect(d_ptr->m_ui->alphaSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeAlpha(int)));
+
+ connect(d_ptr->m_ui->positionSpinBox, SIGNAL(valueChanged(double)),
+ this, SLOT(slotChangePosition(double)));
+
+ connect(d_ptr->m_ui->zoomSpinBox, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeZoom(int)));
+ connect(d_ptr->m_ui->zoomInButton, SIGNAL(clicked()),
+ this, SLOT(slotZoomIn()));
+ connect(d_ptr->m_ui->zoomOutButton, SIGNAL(clicked()),
+ this, SLOT(slotZoomOut()));
+ connect(d_ptr->m_ui->zoomAllButton, SIGNAL(clicked()),
+ this, SLOT(slotZoomAll()));
+ connect(d_ptr->m_ui->gradientStopsWidget, SIGNAL(zoomChanged(double)),
+ this, SLOT(slotZoomChanged(double)));
+
+ connect(d_ptr->m_ui->hsvRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotHsvClicked()));
+ connect(d_ptr->m_ui->rgbRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotRgbClicked()));
+
+ d_ptr->enableCurrent(false);
+ d_ptr->m_ui->zoomInButton->setIcon(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/zoomin.png")));
+ d_ptr->m_ui->zoomOutButton->setIcon(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/zoomout.png")));
+ d_ptr->updateZoom(1);
+}
+
+QtGradientStopsController::~QtGradientStopsController()
+{
+ delete d_ptr;
+}
+
+void QtGradientStopsController::setGradientStops(const QGradientStops &stops)
+{
+ d_ptr->m_model->clear();
+ QVectorIterator<QPair<qreal, QColor> > it(stops);
+ QtGradientStop *first = 0;
+ while (it.hasNext()) {
+ QPair<qreal, QColor> pair = it.next();
+ QtGradientStop *stop = d_ptr->m_model->addStop(pair.first, pair.second);
+ if (!first)
+ first = stop;
+ }
+ if (first)
+ d_ptr->m_model->setCurrentStop(first);
+}
+
+QGradientStops QtGradientStopsController::gradientStops() const
+{
+ QGradientStops stops;
+ QList<QtGradientStop *> stopsList = d_ptr->m_model->stops().values();
+ QListIterator<QtGradientStop *> itStop(stopsList);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+ stops << QPair<qreal, QColor>(stop->position(), stop->color());
+ }
+ return stops;
+}
+
+QColor::Spec QtGradientStopsController::spec() const
+{
+ return d_ptr->m_spec;
+}
+
+void QtGradientStopsController::setSpec(QColor::Spec spec)
+{
+ if (d_ptr->m_spec == spec)
+ return;
+
+ d_ptr->m_spec = spec;
+ if (d_ptr->m_spec == QColor::Rgb) {
+ d_ptr->m_ui->rgbRadioButton->setChecked(true);
+ d_ptr->slotRgbClicked();
+ } else {
+ d_ptr->m_ui->hsvRadioButton->setChecked(true);
+ d_ptr->slotHsvClicked();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradientstopscontroller.cpp"
diff --git a/tools/shared/qtgradienteditor/qtgradientstopscontroller.h b/tools/shared/qtgradienteditor/qtgradientstopscontroller.h
new file mode 100644
index 0000000000..9f16fb085d
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientstopscontroller.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTSTOPSCONTROLLER_H
+#define QTGRADIENTSTOPSCONTROLLER_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+ class QtGradientEditor;
+}
+
+class QtGradientStopsController : public QObject
+{
+ Q_OBJECT
+public:
+ QtGradientStopsController(QObject *parent = 0);
+ ~QtGradientStopsController();
+
+ void setUi(Ui::QtGradientEditor *editor);
+
+ void setGradientStops(const QGradientStops &stops);
+ QGradientStops gradientStops() const;
+
+ QColor::Spec spec() const;
+ void setSpec(QColor::Spec spec);
+
+signals:
+
+ void gradientStopsChanged(const QGradientStops &stops);
+
+private:
+ class QtGradientStopsControllerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientStopsController)
+ Q_DISABLE_COPY(QtGradientStopsController)
+ Q_PRIVATE_SLOT(d_func(), void slotHsvClicked())
+ Q_PRIVATE_SLOT(d_func(), void slotRgbClicked())
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentStopChanged(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopMoved(QtGradientStop *stop, qreal newPos))
+ Q_PRIVATE_SLOT(d_func(), void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2))
+ Q_PRIVATE_SLOT(d_func(), void slotStopChanged(QtGradientStop *stop, const QColor &newColor))
+ Q_PRIVATE_SLOT(d_func(), void slotStopSelected(QtGradientStop *stop, bool selected))
+ Q_PRIVATE_SLOT(d_func(), void slotStopAdded(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopRemoved(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotUpdatePositionSpinBox())
+ Q_PRIVATE_SLOT(d_func(), void slotChangeColor(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeHue(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeSaturation(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeValue(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeAlpha(const QColor &color))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeHue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeSaturation(int))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeValue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeAlpha(int))
+ //Q_PRIVATE_SLOT(d_func(), void slotChangePosition(double newPos))
+ Q_PRIVATE_SLOT(d_func(), void slotChangePosition(double value))
+ Q_PRIVATE_SLOT(d_func(), void slotChangeZoom(int value))
+ Q_PRIVATE_SLOT(d_func(), void slotZoomIn())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomOut())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomAll())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomChanged(double))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp b/tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp
new file mode 100644
index 0000000000..a632c0fc97
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientstopsmodel.cpp
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientstopsmodel.h"
+#include <QtGui/QColor>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopPrivate
+{
+public:
+ qreal m_position;
+ QColor m_color;
+ QtGradientStopsModel *m_model;
+};
+
+qreal QtGradientStop::position() const
+{
+ return d_ptr->m_position;
+}
+
+QColor QtGradientStop::color() const
+{
+ return d_ptr->m_color;
+}
+
+QtGradientStopsModel *QtGradientStop::gradientModel() const
+{
+ return d_ptr->m_model;
+}
+
+void QtGradientStop::setColor(const QColor &color)
+{
+ d_ptr->m_color = color;
+}
+
+void QtGradientStop::setPosition(qreal position)
+{
+ d_ptr->m_position = position;
+}
+
+QtGradientStop::QtGradientStop(QtGradientStopsModel *model)
+{
+ d_ptr = new QtGradientStopPrivate();
+ d_ptr->m_position = 0;
+ d_ptr->m_color = Qt::white;
+ d_ptr->m_model = model;
+}
+
+QtGradientStop::~QtGradientStop()
+{
+ delete d_ptr;
+}
+
+class QtGradientStopsModelPrivate
+{
+ QtGradientStopsModel *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientStopsModel)
+public:
+ QMap<qreal, QtGradientStop *> m_posToStop;
+ QMap<QtGradientStop *, qreal> m_stopToPos;
+ QMap<QtGradientStop *, bool> m_selection;
+ QtGradientStop *m_current;
+};
+
+
+
+QtGradientStopsModel::QtGradientStopsModel(QObject *parent)
+ : QObject(parent)
+{
+ d_ptr = new QtGradientStopsModelPrivate;
+ d_ptr->q_ptr = this;
+ d_ptr->m_current = 0;
+}
+
+QtGradientStopsModel::~QtGradientStopsModel()
+{
+ clear();
+ delete d_ptr;
+}
+
+QtGradientStopsModel::PositionStopMap QtGradientStopsModel::stops() const
+{
+ return d_ptr->m_posToStop;
+}
+
+QtGradientStop *QtGradientStopsModel::at(qreal pos) const
+{
+ if (d_ptr->m_posToStop.contains(pos))
+ return d_ptr->m_posToStop[pos];
+ return 0;
+}
+
+QColor QtGradientStopsModel::color(qreal pos) const
+{
+ PositionStopMap gradStops = stops();
+ if (gradStops.isEmpty())
+ return QColor::fromRgbF(pos, pos, pos, 1.0);
+ if (gradStops.contains(pos))
+ return gradStops[pos]->color();
+
+ gradStops[pos] = 0;
+ PositionStopMap::ConstIterator itStop = gradStops.constFind(pos);
+ if (itStop == gradStops.constBegin()) {
+ ++itStop;
+ return itStop.value()->color();
+ }
+ if (itStop == --gradStops.constEnd()) {
+ --itStop;
+ return itStop.value()->color();
+ }
+ PositionStopMap::ConstIterator itPrev = itStop;
+ PositionStopMap::ConstIterator itNext = itStop;
+ --itPrev;
+ ++itNext;
+
+ double prevX = itPrev.key();
+ double nextX = itNext.key();
+
+ double coefX = (pos - prevX) / (nextX - prevX);
+ QColor prevCol = itPrev.value()->color();
+ QColor nextCol = itNext.value()->color();
+
+ QColor newColor;
+ newColor.setRgbF((nextCol.redF() - prevCol.redF() ) * coefX + prevCol.redF(),
+ (nextCol.greenF() - prevCol.greenF()) * coefX + prevCol.greenF(),
+ (nextCol.blueF() - prevCol.blueF() ) * coefX + prevCol.blueF(),
+ (nextCol.alphaF() - prevCol.alphaF()) * coefX + prevCol.alphaF());
+ return newColor;
+}
+
+QList<QtGradientStop *> QtGradientStopsModel::selectedStops() const
+{
+ return d_ptr->m_selection.keys();
+}
+
+QtGradientStop *QtGradientStopsModel::currentStop() const
+{
+ return d_ptr->m_current;
+}
+
+bool QtGradientStopsModel::isSelected(QtGradientStop *stop) const
+{
+ if (d_ptr->m_selection.contains(stop))
+ return true;
+ return false;
+}
+
+QtGradientStop *QtGradientStopsModel::addStop(qreal pos, const QColor &color)
+{
+ qreal newPos = pos;
+ if (pos < 0.0)
+ newPos = 0.0;
+ if (pos > 1.0)
+ newPos = 1.0;
+ if (d_ptr->m_posToStop.contains(newPos))
+ return 0;
+ QtGradientStop *stop = new QtGradientStop();
+ stop->setPosition(newPos);
+ stop->setColor(color);
+
+ d_ptr->m_posToStop[newPos] = stop;
+ d_ptr->m_stopToPos[stop] = newPos;
+
+ emit stopAdded(stop);
+
+ return stop;
+}
+
+void QtGradientStopsModel::removeStop(QtGradientStop *stop)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (currentStop() == stop)
+ setCurrentStop(0);
+ selectStop(stop, false);
+
+ emit stopRemoved(stop);
+
+ qreal pos = d_ptr->m_stopToPos[stop];
+ d_ptr->m_stopToPos.remove(stop);
+ d_ptr->m_posToStop.remove(pos);
+ delete stop;
+}
+
+void QtGradientStopsModel::moveStop(QtGradientStop *stop, qreal newPos)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (d_ptr->m_posToStop.contains(newPos))
+ return;
+
+ if (newPos > 1.0)
+ newPos = 1.0;
+ else if (newPos < 0.0)
+ newPos = 0.0;
+
+ emit stopMoved(stop, newPos);
+
+ const qreal oldPos = stop->position();
+ stop->setPosition(newPos);
+ d_ptr->m_stopToPos[stop] = newPos;
+ d_ptr->m_posToStop.remove(oldPos);
+ d_ptr->m_posToStop[newPos] = stop;
+}
+
+void QtGradientStopsModel::swapStops(QtGradientStop *stop1, QtGradientStop *stop2)
+{
+ if (stop1 == stop2)
+ return;
+ if (!d_ptr->m_stopToPos.contains(stop1))
+ return;
+ if (!d_ptr->m_stopToPos.contains(stop2))
+ return;
+
+ emit stopsSwapped(stop1, stop2);
+
+ const qreal pos1 = stop1->position();
+ const qreal pos2 = stop2->position();
+ stop1->setPosition(pos2);
+ stop2->setPosition(pos1);
+ d_ptr->m_stopToPos[stop1] = pos2;
+ d_ptr->m_stopToPos[stop2] = pos1;
+ d_ptr->m_posToStop[pos1] = stop2;
+ d_ptr->m_posToStop[pos2] = stop1;
+}
+
+void QtGradientStopsModel::changeStop(QtGradientStop *stop, const QColor &newColor)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (stop->color() == newColor)
+ return;
+
+ emit stopChanged(stop, newColor);
+
+ stop->setColor(newColor);
+}
+
+void QtGradientStopsModel::selectStop(QtGradientStop *stop, bool select)
+{
+ if (!d_ptr->m_stopToPos.contains(stop))
+ return;
+ bool selected = d_ptr->m_selection.contains(stop);
+ if (select == selected)
+ return;
+
+ emit stopSelected(stop, select);
+
+ if (select)
+ d_ptr->m_selection[stop] = true;
+ else
+ d_ptr->m_selection.remove(stop);
+}
+
+void QtGradientStopsModel::setCurrentStop(QtGradientStop *stop)
+{
+ if (stop && !d_ptr->m_stopToPos.contains(stop))
+ return;
+ if (stop == currentStop())
+ return;
+
+ emit currentStopChanged(stop);
+
+ d_ptr->m_current = stop;
+}
+
+QtGradientStop *QtGradientStopsModel::firstSelected() const
+{
+ PositionStopMap stopList = stops();
+ PositionStopMap::ConstIterator itStop = stopList.constBegin();
+ while (itStop != stopList.constEnd()) {
+ QtGradientStop *stop = itStop.value();
+ if (isSelected(stop))
+ return stop;
+ ++itStop;
+ };
+ return 0;
+}
+
+QtGradientStop *QtGradientStopsModel::lastSelected() const
+{
+ PositionStopMap stopList = stops();
+ PositionStopMap::ConstIterator itStop = stopList.constEnd();
+ while (itStop != stopList.constBegin()) {
+ --itStop;
+
+ QtGradientStop *stop = itStop.value();
+ if (isSelected(stop))
+ return stop;
+ };
+ return 0;
+}
+
+QtGradientStopsModel *QtGradientStopsModel::clone() const
+{
+ QtGradientStopsModel *model = new QtGradientStopsModel();
+
+ QMap<qreal, QtGradientStop *> stopsToClone = stops();
+ QMapIterator<qreal, QtGradientStop *> it(stopsToClone);
+ while (it.hasNext()) {
+ it.next();
+ model->addStop(it.key(), it.value()->color());
+ }
+ // clone selection and current also
+ return model;
+}
+
+void QtGradientStopsModel::moveStops(double newPosition)
+{
+ QtGradientStop *current = currentStop();
+ if (!current)
+ return;
+
+ double newPos = newPosition;
+
+ if (newPos > 1)
+ newPos = 1;
+ else if (newPos < 0)
+ newPos = 0;
+
+ if (newPos == current->position())
+ return;
+
+ double offset = newPos - current->position();
+
+ QtGradientStop *first = firstSelected();
+ QtGradientStop *last = lastSelected();
+
+ if (first && last) { // multiselection
+ double maxOffset = 1.0 - last->position();
+ double minOffset = -first->position();
+
+ if (offset > maxOffset)
+ offset = maxOffset;
+ else if (offset < minOffset)
+ offset = minOffset;
+
+ }
+
+ if (offset == 0)
+ return;
+
+ bool forward = (offset > 0) ? false : true;
+
+ PositionStopMap stopList;
+
+ QList<QtGradientStop *> selected = selectedStops();
+ QListIterator<QtGradientStop *> it(selected);
+ while (it.hasNext()) {
+ QtGradientStop *stop = it.next();
+ stopList[stop->position()] = stop;
+ }
+ stopList[current->position()] = current;
+
+ PositionStopMap::ConstIterator itStop = forward ? stopList.constBegin() : stopList.constEnd();
+ while (itStop != (forward ? stopList.constEnd() : stopList.constBegin())) {
+ if (!forward)
+ --itStop;
+ QtGradientStop *stop = itStop.value();
+ double pos = stop->position() + offset;
+ if (pos > 1)
+ pos = 1;
+ if (pos < 0)
+ pos = 0;
+
+ if (current == stop)
+ pos = newPos;
+
+ QtGradientStop *oldStop = at(pos);
+ if (oldStop && !stopList.values().contains(oldStop))
+ removeStop(oldStop);
+ moveStop(stop, pos);
+
+ if (forward)
+ ++itStop;
+ }
+}
+
+void QtGradientStopsModel::clear()
+{
+ QList<QtGradientStop *> stopsList = stops().values();
+ QListIterator<QtGradientStop *> it(stopsList);
+ while (it.hasNext())
+ removeStop(it.next());
+}
+
+void QtGradientStopsModel::clearSelection()
+{
+ QList<QtGradientStop *> stopsList = selectedStops();
+ QListIterator<QtGradientStop *> it(stopsList);
+ while (it.hasNext())
+ selectStop(it.next(), false);
+}
+
+void QtGradientStopsModel::flipAll()
+{
+ QMap<qreal, QtGradientStop *> stopsMap = stops();
+ QMapIterator<qreal, QtGradientStop *> itStop(stopsMap);
+ itStop.toBack();
+
+ QMap<QtGradientStop *, bool> swappedList;
+
+ while (itStop.hasPrevious()) {
+ itStop.previous();
+
+ QtGradientStop *stop = itStop.value();
+ if (swappedList.contains(stop))
+ continue;
+ const double newPos = 1.0 - itStop.key();
+ if (stopsMap.contains(newPos)) {
+ QtGradientStop *swapped = stopsMap.value(newPos);
+ swappedList[swapped] = true;
+ swapStops(stop, swapped);
+ } else {
+ moveStop(stop, newPos);
+ }
+ }
+}
+
+void QtGradientStopsModel::selectAll()
+{
+ QList<QtGradientStop *> stopsList = stops().values();
+ QListIterator<QtGradientStop *> it(stopsList);
+ while (it.hasNext())
+ selectStop(it.next(), true);
+}
+
+void QtGradientStopsModel::deleteStops()
+{
+ QList<QtGradientStop *> selected = selectedStops();
+ QListIterator<QtGradientStop *> itSel(selected);
+ while (itSel.hasNext()) {
+ QtGradientStop *stop = itSel.next();
+ removeStop(stop);
+ }
+ QtGradientStop *current = currentStop();
+ if (current)
+ removeStop(current);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/qtgradienteditor/qtgradientstopsmodel.h b/tools/shared/qtgradienteditor/qtgradientstopsmodel.h
new file mode 100644
index 0000000000..d4e6b3c204
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientstopsmodel.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTSTOPSMODEL_H
+#define QTGRADIENTSTOPSMODEL_H
+
+#include <QtCore/QObject>
+#include <QtCore/QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QColor;
+
+class QtGradientStopsModel;
+
+class QtGradientStop
+{
+public:
+ qreal position() const;
+ QColor color() const;
+ QtGradientStopsModel *gradientModel() const;
+
+private:
+ void setColor(const QColor &color);
+ void setPosition(qreal position);
+ friend class QtGradientStopsModel;
+ QtGradientStop(QtGradientStopsModel *model = 0);
+ ~QtGradientStop();
+ class QtGradientStopPrivate *d_ptr;
+};
+
+class QtGradientStopsModel : public QObject
+{
+ Q_OBJECT
+public:
+ typedef QMap<qreal, QtGradientStop *> PositionStopMap;
+
+ QtGradientStopsModel(QObject *parent = 0);
+ ~QtGradientStopsModel();
+
+ PositionStopMap stops() const;
+ QtGradientStop *at(qreal pos) const;
+ QColor color(qreal pos) const; // calculated between points
+ QList<QtGradientStop *> selectedStops() const;
+ QtGradientStop *currentStop() const;
+ bool isSelected(QtGradientStop *stop) const;
+ QtGradientStop *firstSelected() const;
+ QtGradientStop *lastSelected() const;
+ QtGradientStopsModel *clone() const;
+
+ QtGradientStop *addStop(qreal pos, const QColor &color);
+ void removeStop(QtGradientStop *stop);
+ void moveStop(QtGradientStop *stop, qreal newPos);
+ void swapStops(QtGradientStop *stop1, QtGradientStop *stop2);
+ void changeStop(QtGradientStop *stop, const QColor &newColor);
+ void selectStop(QtGradientStop *stop, bool select);
+ void setCurrentStop(QtGradientStop *stop);
+
+ void moveStops(double newPosition); // moves current stop to newPos and all selected stops are moved accordingly
+ void clear();
+ void clearSelection();
+ void flipAll();
+ void selectAll();
+ void deleteStops();
+
+signals:
+ void stopAdded(QtGradientStop *stop);
+ void stopRemoved(QtGradientStop *stop);
+ void stopMoved(QtGradientStop *stop, qreal newPos);
+ void stopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
+ void stopChanged(QtGradientStop *stop, const QColor &newColor);
+ void stopSelected(QtGradientStop *stop, bool selected);
+ void currentStopChanged(QtGradientStop *stop);
+
+private:
+ class QtGradientStopsModelPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientStopsModel)
+ Q_DISABLE_COPY(QtGradientStopsModel)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientstopswidget.cpp b/tools/shared/qtgradienteditor/qtgradientstopswidget.cpp
new file mode 100644
index 0000000000..adaf57d5b9
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientstopswidget.cpp
@@ -0,0 +1,1156 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientstopswidget.h"
+#include "qtgradientstopsmodel.h"
+
+#include <QtCore/QMap>
+#include <QtGui/QImage>
+#include <QtGui/QPainter>
+#include <QtGui/QScrollBar>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QRubberBand>
+#include <QtGui/QMenu>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopsWidgetPrivate
+{
+ QtGradientStopsWidget *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientStopsWidget)
+public:
+ typedef QMap<qreal, QColor> PositionColorMap;
+ typedef QMap<QtGradientStop *, qreal> StopPositionMap;
+
+ void slotStopAdded(QtGradientStop *stop);
+ void slotStopRemoved(QtGradientStop *stop);
+ void slotStopMoved(QtGradientStop *stop, qreal newPos);
+ void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
+ void slotStopChanged(QtGradientStop *stop, const QColor &newColor);
+ void slotStopSelected(QtGradientStop *stop, bool selected);
+ void slotCurrentStopChanged(QtGradientStop *stop);
+ void slotNewStop();
+ void slotDelete();
+ void slotFlipAll();
+ void slotSelectAll();
+ void slotZoomIn();
+ void slotZoomOut();
+ void slotResetZoom();
+
+ double fromViewport(int x) const;
+ double toViewport(double x) const;
+ QtGradientStop *stopAt(const QPoint &viewportPos) const;
+ QList<QtGradientStop *> stopsAt(const QPoint &viewportPos) const;
+ void setupMove(QtGradientStop *stop, int x);
+ void ensureVisible(double x); // x = stop position
+ void ensureVisible(QtGradientStop *stop);
+ QtGradientStop *newStop(const QPoint &viewportPos);
+
+ bool m_backgroundCheckered;
+ QtGradientStopsModel *m_model;
+ double m_handleSize;
+ int m_scaleFactor;
+ double m_zoom;
+
+#ifndef QT_NO_DRAGANDDROP
+ QtGradientStop *m_dragStop;
+ QtGradientStop *m_changedStop;
+ QtGradientStop *m_clonedStop;
+ QtGradientStopsModel *m_dragModel;
+ QColor m_dragColor;
+ void clearDrag();
+ void removeClonedStop();
+ void restoreChangedStop();
+ void changeStop(qreal pos);
+ void cloneStop(qreal pos);
+#endif
+
+ QRubberBand *m_rubber;
+ QPoint m_clickPos;
+
+ QList<QtGradientStop *> m_stops;
+
+ bool m_moving;
+ int m_moveOffset;
+ StopPositionMap m_moveStops;
+
+ PositionColorMap m_moveOriginal;
+};
+
+double QtGradientStopsWidgetPrivate::fromViewport(int x) const
+{
+ QSize size = q_ptr->viewport()->size();
+ int w = size.width();
+ int max = q_ptr->horizontalScrollBar()->maximum();
+ int val = q_ptr->horizontalScrollBar()->value();
+ return ((double)x * m_scaleFactor + w * val) / (w * (m_scaleFactor + max));
+}
+
+double QtGradientStopsWidgetPrivate::toViewport(double x) const
+{
+ QSize size = q_ptr->viewport()->size();
+ int w = size.width();
+ int max = q_ptr->horizontalScrollBar()->maximum();
+ int val = q_ptr->horizontalScrollBar()->value();
+ return w * (x * (m_scaleFactor + max) - val) / m_scaleFactor;
+}
+
+QtGradientStop *QtGradientStopsWidgetPrivate::stopAt(const QPoint &viewportPos) const
+{
+ double posY = m_handleSize / 2;
+ QListIterator<QtGradientStop *> itStop(m_stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+
+ double posX = toViewport(stop->position());
+
+ double x = viewportPos.x() - posX;
+ double y = viewportPos.y() - posY;
+
+ if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
+ return stop;
+ }
+ return 0;
+}
+
+QList<QtGradientStop *> QtGradientStopsWidgetPrivate::stopsAt(const QPoint &viewportPos) const
+{
+ QList<QtGradientStop *> stops;
+ double posY = m_handleSize / 2;
+ QListIterator<QtGradientStop *> itStop(m_stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+
+ double posX = toViewport(stop->position());
+
+ double x = viewportPos.x() - posX;
+ double y = viewportPos.y() - posY;
+
+ if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
+ stops.append(stop);
+ }
+ return stops;
+}
+
+void QtGradientStopsWidgetPrivate::setupMove(QtGradientStop *stop, int x)
+{
+ m_model->setCurrentStop(stop);
+
+ int viewportX = qRound(toViewport(stop->position()));
+ m_moveOffset = x - viewportX;
+
+ QList<QtGradientStop *> stops = m_stops;
+ m_stops.clear();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (m_model->isSelected(s) || s == stop) {
+ m_moveStops[s] = s->position() - stop->position();
+ m_stops.append(s);
+ } else {
+ m_moveOriginal[s->position()] = s->color();
+ }
+ }
+ itStop.toFront();
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (!m_model->isSelected(s))
+ m_stops.append(s);
+ }
+ m_stops.removeAll(stop);
+ m_stops.prepend(stop);
+}
+
+void QtGradientStopsWidgetPrivate::ensureVisible(double x)
+{
+ double viewX = toViewport(x);
+ if (viewX < 0 || viewX > q_ptr->viewport()->size().width()) {
+ int max = q_ptr->horizontalScrollBar()->maximum();
+ int newVal = qRound(x * (max + m_scaleFactor) - m_scaleFactor / 2);
+ q_ptr->horizontalScrollBar()->setValue(newVal);
+ }
+}
+
+void QtGradientStopsWidgetPrivate::ensureVisible(QtGradientStop *stop)
+{
+ if (!stop)
+ return;
+ ensureVisible(stop->position());
+}
+
+QtGradientStop *QtGradientStopsWidgetPrivate::newStop(const QPoint &viewportPos)
+{
+ QtGradientStop *copyStop = stopAt(viewportPos);
+ double posX = fromViewport(viewportPos.x());
+ QtGradientStop *stop = m_model->at(posX);
+ if (!stop) {
+ QColor newColor;
+ if (copyStop)
+ newColor = copyStop->color();
+ else
+ newColor = m_model->color(posX);
+ if (!newColor.isValid())
+ newColor = Qt::white;
+ stop = m_model->addStop(posX, newColor);
+ }
+ return stop;
+}
+
+void QtGradientStopsWidgetPrivate::slotStopAdded(QtGradientStop *stop)
+{
+ m_stops.append(stop);
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopRemoved(QtGradientStop *stop)
+{
+ m_stops.removeAll(stop);
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(newPos)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)
+{
+ Q_UNUSED(stop1)
+ Q_UNUSED(stop2)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(newColor)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotStopSelected(QtGradientStop *stop, bool selected)
+{
+ Q_UNUSED(stop)
+ Q_UNUSED(selected)
+ q_ptr->viewport()->update();
+}
+
+void QtGradientStopsWidgetPrivate::slotCurrentStopChanged(QtGradientStop *stop)
+{
+ Q_UNUSED(stop)
+
+ if (!m_model)
+ return;
+ q_ptr->viewport()->update();
+ if (stop) {
+ m_stops.removeAll(stop);
+ m_stops.prepend(stop);
+ }
+}
+
+void QtGradientStopsWidgetPrivate::slotNewStop()
+{
+ if (!m_model)
+ return;
+
+ QtGradientStop *stop = newStop(m_clickPos);
+
+ if (!stop)
+ return;
+
+ m_model->clearSelection();
+ m_model->selectStop(stop, true);
+ m_model->setCurrentStop(stop);
+}
+
+void QtGradientStopsWidgetPrivate::slotDelete()
+{
+ if (!m_model)
+ return;
+
+ m_model->deleteStops();
+}
+
+void QtGradientStopsWidgetPrivate::slotFlipAll()
+{
+ if (!m_model)
+ return;
+
+ m_model->flipAll();
+}
+
+void QtGradientStopsWidgetPrivate::slotSelectAll()
+{
+ if (!m_model)
+ return;
+
+ m_model->selectAll();
+}
+
+void QtGradientStopsWidgetPrivate::slotZoomIn()
+{
+ double newZoom = q_ptr->zoom() * 2;
+ if (newZoom > 100)
+ newZoom = 100;
+ if (newZoom == q_ptr->zoom())
+ return;
+
+ q_ptr->setZoom(newZoom);
+ emit q_ptr->zoomChanged(q_ptr->zoom());
+}
+
+void QtGradientStopsWidgetPrivate::slotZoomOut()
+{
+ double newZoom = q_ptr->zoom() / 2;
+ if (newZoom < 1)
+ newZoom = 1;
+ if (newZoom == q_ptr->zoom())
+ return;
+
+ q_ptr->setZoom(newZoom);
+ emit q_ptr->zoomChanged(q_ptr->zoom());
+}
+
+void QtGradientStopsWidgetPrivate::slotResetZoom()
+{
+ if (1 == q_ptr->zoom())
+ return;
+
+ q_ptr->setZoom(1);
+ emit q_ptr->zoomChanged(1);
+}
+
+QtGradientStopsWidget::QtGradientStopsWidget(QWidget *parent)
+ : QAbstractScrollArea(parent)
+{
+ d_ptr = new QtGradientStopsWidgetPrivate;
+ d_ptr->q_ptr = this;
+ d_ptr->m_backgroundCheckered = true;
+ d_ptr->m_model = 0;
+ d_ptr->m_handleSize = 25.0;
+ d_ptr->m_scaleFactor = 1000;
+ d_ptr->m_moving = false;
+ d_ptr->m_zoom = 1;
+ d_ptr->m_rubber = new QRubberBand(QRubberBand::Rectangle, this);
+#ifndef QT_NO_DRAGANDDROP
+ d_ptr->m_dragStop = 0;
+ d_ptr->m_changedStop = 0;
+ d_ptr->m_clonedStop = 0;
+ d_ptr->m_dragModel = 0;
+#endif
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ horizontalScrollBar()->setRange(0, (int)(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1) + 0.5));
+ horizontalScrollBar()->setPageStep(d_ptr->m_scaleFactor);
+ horizontalScrollBar()->setSingleStep(4);
+ viewport()->setAutoFillBackground(false);
+
+ setAcceptDrops(true);
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
+}
+
+QtGradientStopsWidget::~QtGradientStopsWidget()
+{
+ delete d_ptr;
+}
+
+QSize QtGradientStopsWidget::sizeHint() const
+{
+ return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->sizeHint().height());
+}
+
+QSize QtGradientStopsWidget::minimumSizeHint() const
+{
+ return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->minimumSizeHint().height());
+}
+
+void QtGradientStopsWidget::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+ d_ptr->m_backgroundCheckered = checkered;
+ update();
+}
+
+bool QtGradientStopsWidget::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtGradientStopsWidget::setGradientStopsModel(QtGradientStopsModel *model)
+{
+ if (d_ptr->m_model == model)
+ return;
+
+ if (d_ptr->m_model) {
+ disconnect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop *)),
+ this, SLOT(slotStopAdded(QtGradientStop *)));
+ disconnect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop *)),
+ this, SLOT(slotStopRemoved(QtGradientStop *)));
+ disconnect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop *, qreal)),
+ this, SLOT(slotStopMoved(QtGradientStop *, qreal)));
+ disconnect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop *, QtGradientStop *)),
+ this, SLOT(slotStopsSwapped(QtGradientStop *, QtGradientStop *)));
+ disconnect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop *, const QColor &)),
+ this, SLOT(slotStopChanged(QtGradientStop *, const QColor &)));
+ disconnect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop *, bool)),
+ this, SLOT(slotStopSelected(QtGradientStop *, bool)));
+ disconnect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop *)),
+ this, SLOT(slotCurrentStopChanged(QtGradientStop *)));
+
+ d_ptr->m_stops.clear();
+ }
+
+ d_ptr->m_model = model;
+
+ if (d_ptr->m_model) {
+ connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop *)),
+ this, SLOT(slotStopAdded(QtGradientStop *)));
+ connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop *)),
+ this, SLOT(slotStopRemoved(QtGradientStop *)));
+ connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop *, qreal)),
+ this, SLOT(slotStopMoved(QtGradientStop *, qreal)));
+ connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop *, QtGradientStop *)),
+ this, SLOT(slotStopsSwapped(QtGradientStop *, QtGradientStop *)));
+ connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop *, const QColor &)),
+ this, SLOT(slotStopChanged(QtGradientStop *, const QColor &)));
+ connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop *, bool)),
+ this, SLOT(slotStopSelected(QtGradientStop *, bool)));
+ connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop *)),
+ this, SLOT(slotCurrentStopChanged(QtGradientStop *)));
+
+ QList<QtGradientStop *> stops = d_ptr->m_model->stops().values();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext())
+ d_ptr->slotStopAdded(itStop.next());
+
+ QList<QtGradientStop *> selected = d_ptr->m_model->selectedStops();
+ QListIterator<QtGradientStop *> itSelect(selected);
+ while (itSelect.hasNext())
+ d_ptr->slotStopSelected(itSelect.next(), true);
+
+ d_ptr->slotCurrentStopChanged(d_ptr->m_model->currentStop());
+ }
+}
+
+void QtGradientStopsWidget::mousePressEvent(QMouseEvent *e)
+{
+ typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ d_ptr->m_moving = true;
+
+ d_ptr->m_moveStops.clear();
+ d_ptr->m_moveOriginal.clear();
+ d_ptr->m_clickPos = e->pos();
+ QtGradientStop *stop = d_ptr->stopAt(e->pos());
+ if (stop) {
+ if (e->modifiers() & Qt::ControlModifier) {
+ d_ptr->m_model->selectStop(stop, !d_ptr->m_model->isSelected(stop));
+ } else if (e->modifiers() & Qt::ShiftModifier) {
+ QtGradientStop *oldCurrent = d_ptr->m_model->currentStop();
+ if (oldCurrent) {
+ PositionStopMap stops = d_ptr->m_model->stops();
+ PositionStopMap::ConstIterator itSt = stops.constFind(oldCurrent->position());
+ if (itSt != stops.constEnd()) {
+ while (itSt != stops.constFind(stop->position())) {
+ d_ptr->m_model->selectStop(itSt.value(), true);
+ if (oldCurrent->position() < stop->position())
+ ++itSt;
+ else
+ --itSt;
+ }
+ }
+ }
+ d_ptr->m_model->selectStop(stop, true);
+ } else {
+ if (!d_ptr->m_model->isSelected(stop)) {
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_model->selectStop(stop, true);
+ }
+ }
+ d_ptr->setupMove(stop, e->pos().x());
+ } else {
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_rubber->setGeometry(QRect(d_ptr->m_clickPos, QSize()));
+ d_ptr->m_rubber->show();
+ }
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ d_ptr->m_moving = false;
+ d_ptr->m_rubber->hide();
+ d_ptr->m_moveStops.clear();
+ d_ptr->m_moveOriginal.clear();
+}
+
+void QtGradientStopsWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ typedef QtGradientStopsWidgetPrivate::PositionColorMap PositionColorMap;
+ typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
+ typedef QtGradientStopsWidgetPrivate::StopPositionMap StopPositionMap;
+ if (!d_ptr->m_model)
+ return;
+
+ if (!(e->buttons() & Qt::LeftButton))
+ return;
+
+ if (!d_ptr->m_moving)
+ return;
+
+ if (!d_ptr->m_moveStops.isEmpty()) {
+ double maxOffset = 0.0;
+ double minOffset = 0.0;
+ bool first = true;
+ StopPositionMap::ConstIterator itStop = d_ptr->m_moveStops.constBegin();
+ while (itStop != d_ptr->m_moveStops.constEnd()) {
+ double offset = itStop.value();
+
+ if (first) {
+ maxOffset = offset;
+ minOffset = offset;
+ first = false;
+ } else {
+ if (maxOffset < offset)
+ maxOffset = offset;
+ else if (minOffset > offset)
+ minOffset = offset;
+ }
+ ++itStop;
+ }
+
+ double viewportMin = d_ptr->toViewport(-minOffset);
+ double viewportMax = d_ptr->toViewport(1.0 - maxOffset);
+
+ PositionStopMap newPositions;
+
+ int viewportX = e->pos().x() - d_ptr->m_moveOffset;
+
+ if (viewportX > viewport()->size().width())
+ viewportX = viewport()->size().width();
+ else if (viewportX < 0)
+ viewportX = 0;
+
+ double posX = d_ptr->fromViewport(viewportX);
+
+ if (viewportX > viewportMax)
+ posX = 1.0 - maxOffset;
+ else if (viewportX < viewportMin)
+ posX = -minOffset;
+
+ itStop = d_ptr->m_moveStops.constBegin();
+ while (itStop != d_ptr->m_moveStops.constEnd()) {
+ QtGradientStop *stop = itStop.key();
+
+ newPositions[posX + itStop.value()] = stop;
+
+ ++itStop;
+ }
+
+ bool forward = true;
+ PositionStopMap::ConstIterator itNewPos = newPositions.constBegin();
+ if (itNewPos.value()->position() < itNewPos.key())
+ forward = false;
+
+ itNewPos = forward ? newPositions.constBegin() : newPositions.constEnd();
+ while (itNewPos != (forward ? newPositions.constEnd() : newPositions.constBegin())) {
+ if (!forward)
+ --itNewPos;
+ QtGradientStop *stop = itNewPos.value();
+ double newPos = itNewPos.key();
+ if (newPos > 1)
+ newPos = 1;
+ else if (newPos < 0)
+ newPos = 0;
+
+ QtGradientStop *existingStop = d_ptr->m_model->at(newPos);
+ if (existingStop && !d_ptr->m_moveStops.contains(existingStop))
+ d_ptr->m_model->removeStop(existingStop);
+ d_ptr->m_model->moveStop(stop, newPos);
+
+ if (forward)
+ ++itNewPos;
+ }
+
+ PositionColorMap::ConstIterator itOld = d_ptr->m_moveOriginal.constBegin();
+ while (itOld != d_ptr->m_moveOriginal.constEnd()) {
+ double position = itOld.key();
+ if (!d_ptr->m_model->at(position))
+ d_ptr->m_model->addStop(position, itOld.value());
+
+ ++itOld;
+ }
+
+ } else {
+ QRect r(QRect(d_ptr->m_clickPos, e->pos()).normalized());
+ r.translate(1, 0);
+ d_ptr->m_rubber->setGeometry(r);
+ //d_ptr->m_model->clearSelection();
+
+ int xv1 = d_ptr->m_clickPos.x();
+ int xv2 = e->pos().x();
+ if (xv1 > xv2) {
+ int temp = xv1;
+ xv1 = xv2;
+ xv2 = temp;
+ }
+ int yv1 = d_ptr->m_clickPos.y();
+ int yv2 = e->pos().y();
+ if (yv1 > yv2) {
+ int temp = yv1;
+ yv1 = yv2;
+ yv2 = temp;
+ }
+
+ QPoint p1, p2;
+
+ if (yv2 < d_ptr->m_handleSize / 2) {
+ p1 = QPoint(xv1, yv2);
+ p2 = QPoint(xv2, yv2);
+ } else if (yv1 > d_ptr->m_handleSize / 2) {
+ p1 = QPoint(xv1, yv1);
+ p2 = QPoint(xv2, yv1);
+ } else {
+ p1 = QPoint(xv1, qRound(d_ptr->m_handleSize / 2));
+ p2 = QPoint(xv2, qRound(d_ptr->m_handleSize / 2));
+ }
+
+ QList<QtGradientStop *> beginList = d_ptr->stopsAt(p1);
+ QList<QtGradientStop *> endList = d_ptr->stopsAt(p2);
+
+ double x1 = d_ptr->fromViewport(xv1);
+ double x2 = d_ptr->fromViewport(xv2);
+
+ QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next();
+ if ((stop->position() >= x1 && stop->position() <= x2) ||
+ beginList.contains(stop) || endList.contains(stop))
+ d_ptr->m_model->selectStop(stop, true);
+ else
+ d_ptr->m_model->selectStop(stop, false);
+ }
+ }
+}
+
+void QtGradientStopsWidget::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ if (d_ptr->m_clickPos != e->pos()) {
+ mousePressEvent(e);
+ return;
+ }
+ d_ptr->m_moving = true;
+ d_ptr->m_moveStops.clear();
+ d_ptr->m_moveOriginal.clear();
+
+ QtGradientStop *stop = d_ptr->newStop(e->pos());
+
+ if (!stop)
+ return;
+
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_model->selectStop(stop, true);
+
+ d_ptr->setupMove(stop, e->pos().x());
+
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::keyPressEvent(QKeyEvent *e)
+{
+ typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
+ if (!d_ptr->m_model)
+ return;
+
+ if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) {
+ d_ptr->m_model->deleteStops();
+ } else if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right ||
+ e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
+ PositionStopMap stops = d_ptr->m_model->stops();
+ if (stops.isEmpty())
+ return;
+ QtGradientStop *newCurrent = 0;
+ QtGradientStop *current = d_ptr->m_model->currentStop();
+ if (!current || e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
+ if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Home)
+ newCurrent = stops.constBegin().value();
+ else if (e->key() == Qt::Key_Right || e->key() == Qt::Key_End)
+ newCurrent = (--stops.constEnd()).value();
+ } else {
+ PositionStopMap::ConstIterator itStop = stops.constBegin();
+ while (itStop.value() != current)
+ ++itStop;
+ if (e->key() == Qt::Key_Left && itStop != stops.constBegin())
+ --itStop;
+ else if (e->key() == Qt::Key_Right && itStop != --stops.constEnd())
+ ++itStop;
+ newCurrent = itStop.value();
+ }
+ d_ptr->m_model->clearSelection();
+ d_ptr->m_model->selectStop(newCurrent, true);
+ d_ptr->m_model->setCurrentStop(newCurrent);
+ d_ptr->ensureVisible(newCurrent);
+ } else if (e->key() == Qt::Key_A) {
+ if (e->modifiers() & Qt::ControlModifier)
+ d_ptr->m_model->selectAll();
+ }
+}
+
+void QtGradientStopsWidget::paintEvent(QPaintEvent *e)
+{
+ Q_UNUSED(e)
+ if (!d_ptr->m_model)
+ return;
+
+ QtGradientStopsModel *model = d_ptr->m_model;
+#ifndef QT_NO_DRAGANDDROP
+ if (d_ptr->m_dragModel)
+ model = d_ptr->m_dragModel;
+#endif
+
+ QSize size = viewport()->size();
+ int w = size.width();
+ double h = size.height() - d_ptr->m_handleSize;
+ if (w <= 0)
+ return;
+
+ QPixmap pix(size);
+ QPainter p;
+
+ if (d_ptr->m_backgroundCheckered) {
+ int pixSize = 20;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+
+ p.begin(&pix);
+ p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2);
+ p.fillRect(viewport()->rect(), pm);
+ p.setBrushOrigin(0, 0);
+ } else {
+ p.begin(viewport());
+ }
+
+ double viewBegin = (double)w * horizontalScrollBar()->value() / d_ptr->m_scaleFactor;
+
+ int val = horizontalScrollBar()->value();
+ int max = horizontalScrollBar()->maximum();
+
+ double begin = (double)val / (d_ptr->m_scaleFactor + max);
+ double end = (double)(val + d_ptr->m_scaleFactor) / (d_ptr->m_scaleFactor + max);
+ double width = end - begin;
+
+ if (h > 0) {
+ QLinearGradient lg(0, 0, w, 0);
+ QMap<qreal, QtGradientStop *> stops = model->stops();
+ QMapIterator<qreal, QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *stop = itStop.next().value();
+ double pos = stop->position();
+ if (pos >= begin && pos <= end) {
+ double gradPos = (pos - begin) / width;
+ QColor c = stop->color();
+ lg.setColorAt(gradPos, c);
+ }
+ //lg.setColorAt(stop->position(), stop->color());
+ }
+ lg.setColorAt(0, model->color(begin));
+ lg.setColorAt(1, model->color(end));
+ QImage img(w, 1, QImage::Format_ARGB32_Premultiplied);
+ QPainter p1(&img);
+ p1.setCompositionMode(QPainter::CompositionMode_Source);
+
+ /*
+ if (viewBegin != 0)
+ p1.translate(-viewBegin, 0);
+ if (d_ptr->m_zoom != 1)
+ p1.scale(d_ptr->m_zoom, 1);
+ */
+ p1.fillRect(0, 0, w, 1, lg);
+
+ p.fillRect(QRectF(0, d_ptr->m_handleSize, w, h), QPixmap::fromImage(img));
+ }
+
+
+ double handleWidth = d_ptr->m_handleSize * d_ptr->m_scaleFactor / (w * (d_ptr->m_scaleFactor + max));
+
+ QColor insideColor = QColor::fromRgb(0x20, 0x20, 0x20, 0xFF);
+ QColor borderColor = QColor(Qt::white);
+ QColor drawColor;
+ QColor back1 = QColor(Qt::lightGray);
+ QColor back2 = QColor(Qt::darkGray);
+ QColor back = QColor::fromRgb((back1.red() + back2.red()) / 2,
+ (back1.green() + back2.green()) / 2,
+ (back1.blue() + back2.blue()) / 2);
+
+ QPen pen;
+ p.setRenderHint(QPainter::Antialiasing);
+ QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
+ itStop.toBack();
+ while (itStop.hasPrevious()) {
+ QtGradientStop *stop = itStop.previous();
+ double x = stop->position();
+ if (x >= begin - handleWidth / 2 && x <= end + handleWidth / 2) {
+ double viewX = x * w * (d_ptr->m_scaleFactor + max) / d_ptr->m_scaleFactor - viewBegin;
+ p.save();
+ QColor c = stop->color();
+#ifndef QT_NO_DRAGANDDROP
+ if (stop == d_ptr->m_dragStop)
+ c = d_ptr->m_dragColor;
+#endif
+ if ((0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF()) * c.alphaF() +
+ (0.3 * back.redF() + 0.59 * back.greenF() + 0.11 * back.blueF()) * (1.0 - c.alphaF()) < 0.5) {
+ drawColor = QColor::fromRgb(0xC0, 0xC0, 0xC0, 0xB0);
+ } else {
+ drawColor = QColor::fromRgb(0x40, 0x40, 0x40, 0x80);
+ }
+ QRectF rect(viewX - d_ptr->m_handleSize / 2, 0, d_ptr->m_handleSize, d_ptr->m_handleSize);
+ rect.adjust(0.5, 0.5, -0.5, -0.5);
+ if (h > 0) {
+ pen.setWidthF(1);
+ QLinearGradient lg(0, d_ptr->m_handleSize, 0, d_ptr->m_handleSize + h / 2);
+ lg.setColorAt(0, drawColor);
+ QColor alphaZero = drawColor;
+ alphaZero.setAlpha(0);
+ lg.setColorAt(1, alphaZero);
+ pen.setBrush(lg);
+ p.setPen(pen);
+ p.drawLine(QPointF(viewX, d_ptr->m_handleSize), QPointF(viewX, d_ptr->m_handleSize + h / 2));
+
+ pen.setWidthF(1);
+ pen.setBrush(drawColor);
+ p.setPen(pen);
+ QRectF r1 = rect.adjusted(0.5, 0.5, -0.5, -0.5);
+ QRectF r2 = rect.adjusted(1.5, 1.5, -1.5, -1.5);
+ QColor inColor = QColor::fromRgb(0x80, 0x80, 0x80, 0x80);
+ if (!d_ptr->m_model->isSelected(stop)) {
+ p.setBrush(c);
+ p.drawEllipse(rect);
+ } else {
+ pen.setBrush(insideColor);
+ pen.setWidthF(2);
+ p.setPen(pen);
+ p.setBrush(Qt::NoBrush);
+ p.drawEllipse(r1);
+
+ pen.setBrush(inColor);
+ pen.setWidthF(1);
+ p.setPen(pen);
+ p.setBrush(c);
+ p.drawEllipse(r2);
+ }
+
+ if (d_ptr->m_model->currentStop() == stop) {
+ p.setBrush(Qt::NoBrush);
+ pen.setWidthF(5);
+ pen.setBrush(drawColor);
+ int corr = 4;
+ if (!d_ptr->m_model->isSelected(stop)) {
+ corr = 3;
+ pen.setWidthF(7);
+ }
+ p.setPen(pen);
+ p.drawEllipse(rect.adjusted(corr, corr, -corr, -corr));
+ }
+
+ }
+ p.restore();
+ }
+ }
+ if (d_ptr->m_backgroundCheckered) {
+ p.end();
+ p.begin(viewport());
+ p.drawPixmap(0, 0, pix);
+ }
+ p.end();
+}
+
+void QtGradientStopsWidget::focusInEvent(QFocusEvent *e)
+{
+ Q_UNUSED(e)
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::focusOutEvent(QFocusEvent *e)
+{
+ Q_UNUSED(e)
+ viewport()->update();
+}
+
+void QtGradientStopsWidget::contextMenuEvent(QContextMenuEvent *e)
+{
+ if (!d_ptr->m_model)
+ return;
+
+ d_ptr->m_clickPos = e->pos();
+
+ QMenu menu(this);
+ QAction *newStopAction = new QAction(tr("New Stop"), &menu);
+ QAction *deleteAction = new QAction(tr("Delete"), &menu);
+ QAction *flipAllAction = new QAction(tr("Flip All"), &menu);
+ QAction *selectAllAction = new QAction(tr("Select All"), &menu);
+ QAction *zoomInAction = new QAction(tr("Zoom In"), &menu);
+ QAction *zoomOutAction = new QAction(tr("Zoom Out"), &menu);
+ QAction *zoomAllAction = new QAction(tr("Reset Zoom"), &menu);
+ if (d_ptr->m_model->selectedStops().isEmpty() && !d_ptr->m_model->currentStop())
+ deleteAction->setEnabled(false);
+ if (zoom() <= 1) {
+ zoomOutAction->setEnabled(false);
+ zoomAllAction->setEnabled(false);
+ } else if (zoom() >= 100) {
+ zoomInAction->setEnabled(false);
+ }
+ connect(newStopAction, SIGNAL(triggered()), this, SLOT(slotNewStop()));
+ connect(deleteAction, SIGNAL(triggered()), this, SLOT(slotDelete()));
+ connect(flipAllAction, SIGNAL(triggered()), this, SLOT(slotFlipAll()));
+ connect(selectAllAction, SIGNAL(triggered()), this, SLOT(slotSelectAll()));
+ connect(zoomInAction, SIGNAL(triggered()), this, SLOT(slotZoomIn()));
+ connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(slotZoomOut()));
+ connect(zoomAllAction, SIGNAL(triggered()), this, SLOT(slotResetZoom()));
+ menu.addAction(newStopAction);
+ menu.addAction(deleteAction);
+ menu.addAction(flipAllAction);
+ menu.addAction(selectAllAction);
+ menu.addSeparator();
+ menu.addAction(zoomInAction);
+ menu.addAction(zoomOutAction);
+ menu.addAction(zoomAllAction);
+ menu.exec(e->globalPos());
+}
+
+void QtGradientStopsWidget::wheelEvent(QWheelEvent *e)
+{
+ int numDegrees = e->delta() / 8;
+ int numSteps = numDegrees / 15;
+
+ int shift = numSteps;
+ if (shift < 0)
+ shift = -shift;
+ int pow = 1 << shift;
+ //const double c = 0.7071067; // 2 steps per doubled value
+ const double c = 0.5946036; // 4 steps pre doubled value
+ // in general c = pow(2, 1 / n) / 2; where n is the step
+ double factor = pow * c;
+
+ double newZoom = zoom();
+ if (numSteps < 0)
+ newZoom /= factor;
+ else
+ newZoom *= factor;
+ if (newZoom > 100)
+ newZoom = 100;
+ if (newZoom < 1)
+ newZoom = 1;
+
+ if (newZoom == zoom())
+ return;
+
+ setZoom(newZoom);
+ emit zoomChanged(zoom());
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QtGradientStopsWidget::dragEnterEvent(QDragEnterEvent *event)
+{
+ const QMimeData *mime = event->mimeData();
+ if (!mime->hasColor())
+ return;
+ event->accept();
+ d_ptr->m_dragModel = d_ptr->m_model->clone();
+
+ d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData());
+ update();
+}
+
+void QtGradientStopsWidget::dragMoveEvent(QDragMoveEvent *event)
+{
+ QRectF rect = viewport()->rect();
+ rect.adjust(0, d_ptr->m_handleSize, 0, 0);
+ double x = d_ptr->fromViewport(event->pos().x());
+ QtGradientStop *dragStop = d_ptr->stopAt(event->pos());
+ if (dragStop) {
+ event->accept();
+ d_ptr->removeClonedStop();
+ d_ptr->changeStop(dragStop->position());
+ } else if (rect.contains(event->pos())) {
+ event->accept();
+ if (d_ptr->m_model->at(x)) {
+ d_ptr->removeClonedStop();
+ d_ptr->changeStop(x);
+ } else {
+ d_ptr->restoreChangedStop();
+ d_ptr->cloneStop(x);
+ }
+ } else {
+ event->ignore();
+ d_ptr->removeClonedStop();
+ d_ptr->restoreChangedStop();
+ }
+
+ update();
+}
+
+void QtGradientStopsWidget::dragLeaveEvent(QDragLeaveEvent *event)
+{
+ event->accept();
+ d_ptr->clearDrag();
+ update();
+}
+
+void QtGradientStopsWidget::dropEvent(QDropEvent *event)
+{
+ event->accept();
+ if (!d_ptr->m_dragModel)
+ return;
+
+ if (d_ptr->m_changedStop)
+ d_ptr->m_model->changeStop(d_ptr->m_model->at(d_ptr->m_changedStop->position()), d_ptr->m_dragColor);
+ else if (d_ptr->m_clonedStop)
+ d_ptr->m_model->addStop(d_ptr->m_clonedStop->position(), d_ptr->m_dragColor);
+
+ d_ptr->clearDrag();
+ update();
+}
+
+void QtGradientStopsWidgetPrivate::clearDrag()
+{
+ removeClonedStop();
+ restoreChangedStop();
+ delete m_dragModel;
+ m_dragModel = 0;
+}
+
+void QtGradientStopsWidgetPrivate::removeClonedStop()
+{
+ if (!m_clonedStop)
+ return;
+ m_dragModel->removeStop(m_clonedStop);
+ m_clonedStop = 0;
+}
+
+void QtGradientStopsWidgetPrivate::restoreChangedStop()
+{
+ if (!m_changedStop)
+ return;
+ m_dragModel->changeStop(m_changedStop, m_model->at(m_changedStop->position())->color());
+ m_changedStop = 0;
+ m_dragStop = 0;
+}
+
+void QtGradientStopsWidgetPrivate::changeStop(qreal pos)
+{
+ QtGradientStop *stop = m_dragModel->at(pos);
+ if (!stop)
+ return;
+
+ m_dragModel->changeStop(stop, m_dragColor);
+ m_changedStop = stop;
+ m_dragStop = m_model->at(stop->position());
+}
+
+void QtGradientStopsWidgetPrivate::cloneStop(qreal pos)
+{
+ if (m_clonedStop) {
+ m_dragModel->moveStop(m_clonedStop, pos);
+ return;
+ }
+ QtGradientStop *stop = m_dragModel->at(pos);
+ if (stop)
+ return;
+
+ m_clonedStop = m_dragModel->addStop(pos, m_dragColor);
+}
+
+#endif
+
+void QtGradientStopsWidget::setZoom(double zoom)
+{
+ double z = zoom;
+ if (z < 1)
+ z = 1;
+ else if (z > 100)
+ z = 100;
+
+ if (d_ptr->m_zoom == z)
+ return;
+
+ d_ptr->m_zoom = z;
+ int oldMax = horizontalScrollBar()->maximum();
+ int oldVal = horizontalScrollBar()->value();
+ horizontalScrollBar()->setRange(0, qRound(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1)));
+ int newMax = horizontalScrollBar()->maximum();
+ double newVal = (oldVal + (double)d_ptr->m_scaleFactor / 2) * (newMax + d_ptr->m_scaleFactor)
+ / (oldMax + d_ptr->m_scaleFactor) - (double)d_ptr->m_scaleFactor / 2;
+ horizontalScrollBar()->setValue(qRound(newVal));
+ viewport()->update();
+}
+
+double QtGradientStopsWidget::zoom() const
+{
+ return d_ptr->m_zoom;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtgradientstopswidget.cpp"
diff --git a/tools/shared/qtgradienteditor/qtgradientstopswidget.h b/tools/shared/qtgradienteditor/qtgradientstopswidget.h
new file mode 100644
index 0000000000..aafea8b802
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientstopswidget.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTSTOPSWIDGET_H
+#define QTGRADIENTSTOPSWIDGET_H
+
+#include <QtGui/QAbstractScrollArea>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientStopsModel;
+class QtGradientStopsWidgetPrivate;
+
+class QtGradientStopsWidget : public QAbstractScrollArea
+{
+ Q_OBJECT
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+public:
+ QtGradientStopsWidget(QWidget *parent = 0);
+ ~QtGradientStopsWidget();
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ void setGradientStopsModel(QtGradientStopsModel *model);
+
+ void setZoom(double zoom);
+ double zoom() const;
+
+signals:
+
+ void zoomChanged(double zoom);
+
+protected:
+ void paintEvent(QPaintEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void focusInEvent(QFocusEvent *e);
+ void focusOutEvent(QFocusEvent *e);
+ void contextMenuEvent(QContextMenuEvent *e);
+ void wheelEvent(QWheelEvent *e);
+#ifndef QT_NO_DRAGANDDROP
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *event);
+ void dropEvent(QDropEvent *event);
+#endif
+
+private:
+ QtGradientStopsWidgetPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientStopsWidget)
+ Q_DISABLE_COPY(QtGradientStopsWidget)
+ Q_PRIVATE_SLOT(d_func(), void slotStopAdded(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopRemoved(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotStopMoved(QtGradientStop *stop, qreal newPos))
+ Q_PRIVATE_SLOT(d_func(), void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2))
+ Q_PRIVATE_SLOT(d_func(), void slotStopChanged(QtGradientStop *stop, const QColor &newColor))
+ Q_PRIVATE_SLOT(d_func(), void slotStopSelected(QtGradientStop *stop, bool selected))
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentStopChanged(QtGradientStop *stop))
+ Q_PRIVATE_SLOT(d_func(), void slotNewStop())
+ Q_PRIVATE_SLOT(d_func(), void slotDelete())
+ Q_PRIVATE_SLOT(d_func(), void slotFlipAll())
+ Q_PRIVATE_SLOT(d_func(), void slotSelectAll())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomIn())
+ Q_PRIVATE_SLOT(d_func(), void slotZoomOut())
+ Q_PRIVATE_SLOT(d_func(), void slotResetZoom())
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientutils.cpp b/tools/shared/qtgradienteditor/qtgradientutils.cpp
new file mode 100644
index 0000000000..24562336fc
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientutils.cpp
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientutils.h"
+#include "qtgradientmanager.h"
+#include <QtGui/QLinearGradient>
+#include <QtGui/QRadialGradient>
+#include <QtGui/QConicalGradient>
+#include <QtXml/QDomDocument>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+static QString gradientTypeToString(QGradient::Type type)
+{
+ if (type == QGradient::LinearGradient)
+ return QLatin1String("LinearGradient");
+ if (type == QGradient::RadialGradient)
+ return QLatin1String("RadialGradient");
+ if (type == QGradient::ConicalGradient)
+ return QLatin1String("ConicalGradient");
+ return QLatin1String("NoGradient");
+}
+
+static QGradient::Type stringToGradientType(const QString &name)
+{
+ if (name == QLatin1String("LinearGradient"))
+ return QGradient::LinearGradient;
+ if (name == QLatin1String("RadialGradient"))
+ return QGradient::RadialGradient;
+ if (name == QLatin1String("ConicalGradient"))
+ return QGradient::ConicalGradient;
+ return QGradient::NoGradient;
+}
+
+static QString gradientSpreadToString(QGradient::Spread spread)
+{
+ if (spread == QGradient::PadSpread)
+ return QLatin1String("PadSpread");
+ if (spread == QGradient::RepeatSpread)
+ return QLatin1String("RepeatSpread");
+ if (spread == QGradient::ReflectSpread)
+ return QLatin1String("ReflectSpread");
+ return QLatin1String("PadSpread");
+}
+
+static QGradient::Spread stringToGradientSpread(const QString &name)
+{
+ if (name == QLatin1String("PadSpread"))
+ return QGradient::PadSpread;
+ if (name == QLatin1String("RepeatSpread"))
+ return QGradient::RepeatSpread;
+ if (name == QLatin1String("ReflectSpread"))
+ return QGradient::ReflectSpread;
+ return QGradient::PadSpread;
+}
+
+static QString gradientCoordinateModeToString(QGradient::CoordinateMode mode)
+{
+ if (mode == QGradient::LogicalMode)
+ return QLatin1String("LogicalMode");
+ if (mode == QGradient::StretchToDeviceMode)
+ return QLatin1String("StretchToDeviceMode");
+ if (mode == QGradient::ObjectBoundingMode)
+ return QLatin1String("ObjectBoundingMode");
+ return QLatin1String("StretchToDeviceMode");
+}
+
+static QGradient::CoordinateMode stringToGradientCoordinateMode(const QString &name)
+{
+ if (name == QLatin1String("LogicalMode"))
+ return QGradient::LogicalMode;
+ if (name == QLatin1String("StretchToDeviceMode"))
+ return QGradient::StretchToDeviceMode;
+ if (name == QLatin1String("ObjectBoundingMode"))
+ return QGradient::ObjectBoundingMode;
+ return QGradient::StretchToDeviceMode;
+}
+
+static QDomElement saveColor(QDomDocument &doc, const QColor &color)
+{
+ QDomElement colorElem = doc.createElement(QLatin1String("colorData"));
+
+ colorElem.setAttribute(QLatin1String("r"), QString::number(color.red()));
+ colorElem.setAttribute(QLatin1String("g"), QString::number(color.green()));
+ colorElem.setAttribute(QLatin1String("b"), QString::number(color.blue()));
+ colorElem.setAttribute(QLatin1String("a"), QString::number(color.alpha()));
+
+ return colorElem;
+}
+
+static QDomElement saveGradientStop(QDomDocument &doc, const QGradientStop &stop)
+{
+ QDomElement stopElem = doc.createElement(QLatin1String("stopData"));
+
+ stopElem.setAttribute(QLatin1String("position"), QString::number(stop.first));
+
+ const QDomElement colorElem = saveColor(doc, stop.second);
+ stopElem.appendChild(colorElem);
+
+ return stopElem;
+}
+
+static QDomElement saveGradient(QDomDocument &doc, const QGradient &gradient)
+{
+ QDomElement gradElem = doc.createElement(QLatin1String("gradientData"));
+
+ const QGradient::Type type = gradient.type();
+ gradElem.setAttribute(QLatin1String("type"), gradientTypeToString(type));
+ gradElem.setAttribute(QLatin1String("spread"), gradientSpreadToString(gradient.spread()));
+ gradElem.setAttribute(QLatin1String("coordinateMode"), gradientCoordinateModeToString(gradient.coordinateMode()));
+
+ QGradientStops stops = gradient.stops();
+ QVectorIterator<QGradientStop > it(stops);
+ while (it.hasNext())
+ gradElem.appendChild(saveGradientStop(doc, it.next()));
+
+ if (type == QGradient::LinearGradient) {
+ const QLinearGradient &g = *static_cast<const QLinearGradient *>(&gradient);
+ gradElem.setAttribute(QLatin1String("startX"), QString::number(g.start().x()));
+ gradElem.setAttribute(QLatin1String("startY"), QString::number(g.start().y()));
+ gradElem.setAttribute(QLatin1String("endX"), QString::number(g.finalStop().x()));
+ gradElem.setAttribute(QLatin1String("endY"), QString::number(g.finalStop().y()));
+ } else if (type == QGradient::RadialGradient) {
+ const QRadialGradient &g = *static_cast<const QRadialGradient *>(&gradient);
+ gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x()));
+ gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y()));
+ gradElem.setAttribute(QLatin1String("focalX"), QString::number(g.focalPoint().x()));
+ gradElem.setAttribute(QLatin1String("focalY"), QString::number(g.focalPoint().y()));
+ gradElem.setAttribute(QLatin1String("radius"), QString::number(g.radius()));
+ } else if (type == QGradient::ConicalGradient) {
+ const QConicalGradient &g = *static_cast<const QConicalGradient*>(&gradient);
+ gradElem.setAttribute(QLatin1String("centerX"), QString::number(g.center().x()));
+ gradElem.setAttribute(QLatin1String("centerY"), QString::number(g.center().y()));
+ gradElem.setAttribute(QLatin1String("angle"), QString::number(g.angle()));
+ }
+
+ return gradElem;
+}
+
+static QColor loadColor(const QDomElement &elem)
+{
+ if (elem.tagName() != QLatin1String("colorData"))
+ return QColor();
+
+ return QColor(elem.attribute(QLatin1String("r")).toInt(),
+ elem.attribute(QLatin1String("g")).toInt(),
+ elem.attribute(QLatin1String("b")).toInt(),
+ elem.attribute(QLatin1String("a")).toInt());
+}
+
+static QGradientStop loadGradientStop(const QDomElement &elem)
+{
+ if (elem.tagName() != QLatin1String("stopData"))
+ return QGradientStop();
+
+ const qreal pos = static_cast<qreal>(elem.attribute(QLatin1String("position")).toDouble());
+ return qMakePair(pos, loadColor(elem.firstChild().toElement()));
+}
+
+static QGradient loadGradient(const QDomElement &elem)
+{
+ if (elem.tagName() != QLatin1String("gradientData"))
+ return QLinearGradient();
+
+ const QGradient::Type type = stringToGradientType(elem.attribute(QLatin1String("type")));
+ const QGradient::Spread spread = stringToGradientSpread(elem.attribute(QLatin1String("spread")));
+ const QGradient::CoordinateMode mode = stringToGradientCoordinateMode(elem.attribute(QLatin1String("coordinateMode")));
+
+ QGradient gradient = QLinearGradient();
+
+ if (type == QGradient::LinearGradient) {
+ QLinearGradient g;
+ g.setStart(elem.attribute(QLatin1String("startX")).toDouble(), elem.attribute(QLatin1String("startY")).toDouble());
+ g.setFinalStop(elem.attribute(QLatin1String("endX")).toDouble(), elem.attribute(QLatin1String("endY")).toDouble());
+ gradient = g;
+ } else if (type == QGradient::RadialGradient) {
+ QRadialGradient g;
+ g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble());
+ g.setFocalPoint(elem.attribute(QLatin1String("focalX")).toDouble(), elem.attribute(QLatin1String("focalY")).toDouble());
+ g.setRadius(elem.attribute(QLatin1String("radius")).toDouble());
+ gradient = g;
+ } else if (type == QGradient::ConicalGradient) {
+ QConicalGradient g;
+ g.setCenter(elem.attribute(QLatin1String("centerX")).toDouble(), elem.attribute(QLatin1String("centerY")).toDouble());
+ g.setAngle(elem.attribute(QLatin1String("angle")).toDouble());
+ gradient = g;
+ }
+
+ QDomElement stopElem = elem.firstChildElement();
+ while (!stopElem.isNull()) {
+ QGradientStop stop = loadGradientStop(stopElem);
+
+ gradient.setColorAt(stop.first, stop.second);
+
+ stopElem = stopElem.nextSiblingElement();
+ }
+
+ gradient.setSpread(spread);
+ gradient.setCoordinateMode(mode);
+
+ return gradient;
+}
+
+QString QtGradientUtils::saveState(const QtGradientManager *manager)
+{
+ QDomDocument doc;
+
+ QDomElement rootElem = doc.createElement(QLatin1String("gradients"));
+
+ QMap<QString, QGradient> grads = manager->gradients();
+ QMapIterator<QString, QGradient> itGrad(grads);
+ while (itGrad.hasNext()) {
+ itGrad.next();
+ QDomElement idElem = doc.createElement(QLatin1String("gradient"));
+ idElem.setAttribute(QLatin1String("name"), itGrad.key());
+ QDomElement gradElem = saveGradient(doc, itGrad.value());
+ idElem.appendChild(gradElem);
+
+ rootElem.appendChild(idElem);
+ }
+
+ doc.appendChild(rootElem);
+
+ return doc.toString();
+}
+
+void QtGradientUtils::restoreState(QtGradientManager *manager, const QString &state)
+{
+ manager->clear();
+
+ QDomDocument doc;
+ doc.setContent(state);
+
+ QDomElement rootElem = doc.documentElement();
+
+ QDomElement gradElem = rootElem.firstChildElement();
+ while (!gradElem.isNull()) {
+ const QString name = gradElem.attribute(QLatin1String("name"));
+ const QGradient gradient = loadGradient(gradElem.firstChildElement());
+
+ manager->addGradient(name, gradient);
+ gradElem = gradElem.nextSiblingElement();
+ }
+}
+
+QPixmap QtGradientUtils::gradientPixmap(const QGradient &gradient, const QSize &size, bool checkeredBackground)
+{
+ QImage image(size, QImage::Format_ARGB32);
+ QPainter p(&image);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+
+ if (checkeredBackground) {
+ int pixSize = 20;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::lightGray);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::darkGray);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::darkGray);
+
+ p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2);
+ p.fillRect(0, 0, size.width(), size.height(), pm);
+ p.setBrushOrigin(0, 0);
+ p.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ }
+
+ const qreal scaleFactor = 0.999999;
+ p.scale(scaleFactor, scaleFactor);
+ QGradient grad = gradient;
+ grad.setCoordinateMode(QGradient::StretchToDeviceMode);
+ p.fillRect(QRect(0, 0, size.width(), size.height()), grad);
+ p.drawRect(QRect(0, 0, size.width() - 1, size.height() - 1));
+
+ return QPixmap::fromImage(image);
+}
+
+static QString styleSheetFillName(const QGradient &gradient)
+{
+ QString result;
+
+ switch (gradient.type()) {
+ case QGradient::LinearGradient:
+ result += QLatin1String("qlineargradient");
+ break;
+ case QGradient::RadialGradient:
+ result += QLatin1String("qradialgradient");
+ break;
+ case QGradient::ConicalGradient:
+ result += QLatin1String("qconicalgradient");
+ break;
+ default:
+ qWarning() << "QtGradientUtils::styleSheetFillName(): gradient type" << gradient.type() << "not supported!";
+ break;
+ }
+
+ return result;
+}
+
+static QStringList styleSheetParameters(const QGradient &gradient)
+{
+ QStringList result;
+
+ if (gradient.type() != QGradient::ConicalGradient) {
+ QString spread;
+ switch (gradient.spread()) {
+ case QGradient::PadSpread:
+ spread = QLatin1String("pad");
+ break;
+ case QGradient::ReflectSpread:
+ spread = QLatin1String("reflect");
+ break;
+ case QGradient::RepeatSpread:
+ spread = QLatin1String("repeat");
+ break;
+ default:
+ qWarning() << "QtGradientUtils::styleSheetParameters(): gradient spread" << gradient.spread() << "not supported!";
+ break;
+ }
+ result << QLatin1String("spread:") + spread;
+ }
+
+ switch (gradient.type()) {
+ case QGradient::LinearGradient: {
+ const QLinearGradient *linearGradient = static_cast<const QLinearGradient*>(&gradient);
+ result << QLatin1String("x1:") + QString::number(linearGradient->start().x())
+ << QLatin1String("y1:") + QString::number(linearGradient->start().y())
+ << QLatin1String("x2:") + QString::number(linearGradient->finalStop().x())
+ << QLatin1String("y2:") + QString::number(linearGradient->finalStop().y());
+ break;
+ }
+ case QGradient::RadialGradient: {
+ const QRadialGradient *radialGradient = static_cast<const QRadialGradient*>(&gradient);
+ result << QLatin1String("cx:") + QString::number(radialGradient->center().x())
+ << QLatin1String("cy:") + QString::number(radialGradient->center().y())
+ << QLatin1String("radius:") + QString::number(radialGradient->radius())
+ << QLatin1String("fx:") + QString::number(radialGradient->focalPoint().x())
+ << QLatin1String("fy:") + QString::number(radialGradient->focalPoint().y());
+ break;
+ }
+ case QGradient::ConicalGradient: {
+ const QConicalGradient *conicalGradient = static_cast<const QConicalGradient*>(&gradient);
+ result << QLatin1String("cx:") + QString::number(conicalGradient->center().x())
+ << QLatin1String("cy:") + QString::number(conicalGradient->center().y())
+ << QLatin1String("angle:") + QString::number(conicalGradient->angle());
+ break;
+ }
+ default:
+ qWarning() << "QtGradientUtils::styleSheetParameters(): gradient type" << gradient.type() << "not supported!";
+ break;
+ }
+
+ return result;
+}
+
+static QStringList styleSheetStops(const QGradient &gradient)
+{
+ QStringList result;
+ foreach (QGradientStop stop, gradient.stops()) {
+ const QColor color = stop.second;
+
+ const QString stopDescription = QLatin1String("stop:") + QString::number(stop.first) + QLatin1String(" rgba(")
+ + QString::number(color.red()) + QLatin1String(", ")
+ + QString::number(color.green()) + QLatin1String(", ")
+ + QString::number(color.blue()) + QLatin1String(", ")
+ + QString::number(color.alpha()) + QLatin1Char(')');
+ result << stopDescription;
+ }
+
+ return result;
+}
+
+QString QtGradientUtils::styleSheetCode(const QGradient &gradient)
+{
+ QStringList gradientParameters;
+ gradientParameters << styleSheetParameters(gradient) << styleSheetStops(gradient);
+
+ return styleSheetFillName(gradient) + QLatin1Char('(') + gradientParameters.join(QLatin1String(", ")) + QLatin1Char(')');
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/qtgradienteditor/qtgradientutils.h b/tools/shared/qtgradienteditor/qtgradientutils.h
new file mode 100644
index 0000000000..2e356524f4
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientutils.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTUTILS_H
+#define GRADIENTUTILS_H
+
+#include <QtGui/QGradient>
+#include <QtGui/QPainter>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientManager;
+
+class QtGradientUtils
+{
+public:
+ static QString styleSheetCode(const QGradient &gradient);
+ // utils methods, they could be outside of this class
+ static QString saveState(const QtGradientManager *manager);
+ static void restoreState(QtGradientManager *manager, const QString &state);
+
+ static QPixmap gradientPixmap(const QGradient &gradient, const QSize &size = QSize(64, 64), bool checkeredBackground = false);
+
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientview.cpp b/tools/shared/qtgradienteditor/qtgradientview.cpp
new file mode 100644
index 0000000000..ac8ed17d74
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientview.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientview.h"
+#include "qtgradientmanager.h"
+#include "qtgradientdialog.h"
+#include "qtgradientutils.h"
+#include <QtGui/QPainter>
+#include <QtGui/QMessageBox>
+#include <QtGui/QClipboard>
+
+QT_BEGIN_NAMESPACE
+
+void QtGradientView::slotGradientAdded(const QString &id, const QGradient &gradient)
+{
+ QListWidgetItem *item = new QListWidgetItem(QtGradientUtils::gradientPixmap(gradient), id, m_ui.listWidget);
+ item->setToolTip(id);
+ item->setSizeHint(QSize(72, 84));
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+
+ m_idToItem[id] = item;
+ m_itemToId[item] = id;
+}
+
+void QtGradientView::slotGradientRenamed(const QString &id, const QString &newId)
+{
+ if (!m_idToItem.contains(id))
+ return;
+
+ QListWidgetItem *item = m_idToItem.value(id);
+ item->setText(newId);
+ item->setToolTip(newId);
+ m_itemToId[item] = newId;
+ m_idToItem.remove(id);
+ m_idToItem[newId] = item;
+}
+
+void QtGradientView::slotGradientChanged(const QString &id, const QGradient &newGradient)
+{
+ if (!m_idToItem.contains(id))
+ return;
+
+ QListWidgetItem *item = m_idToItem.value(id);
+ item->setIcon(QtGradientUtils::gradientPixmap(newGradient));
+}
+
+void QtGradientView::slotGradientRemoved(const QString &id)
+{
+ if (!m_idToItem.contains(id))
+ return;
+
+ QListWidgetItem *item = m_idToItem.value(id);
+ delete item;
+ m_itemToId.remove(item);
+ m_idToItem.remove(id);
+}
+
+void QtGradientView::slotNewGradient()
+{
+ bool ok;
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ QGradient grad = QLinearGradient();
+ if (item)
+ grad = m_manager->gradients().value(m_itemToId.value(item));
+ QGradient gradient = QtGradientDialog::getGradient(&ok, grad, this);
+ if (!ok)
+ return;
+
+ QString id = m_manager->addGradient(tr("Grad"), gradient);
+ m_ui.listWidget->setCurrentItem(m_idToItem.value(id));
+}
+
+void QtGradientView::slotEditGradient()
+{
+ bool ok;
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ if (!item)
+ return;
+
+ const QString id = m_itemToId.value(item);
+ QGradient grad = m_manager->gradients().value(id);
+ QGradient gradient = QtGradientDialog::getGradient(&ok, grad, this);
+ if (!ok)
+ return;
+
+ m_manager->changeGradient(id, gradient);
+}
+
+void QtGradientView::slotRemoveGradient()
+{
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ if (!item)
+ return;
+
+ if (QMessageBox::question(this, tr("Remove Gradient"),
+ tr("Are you sure you want to remove the selected gradient?"),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Yes)
+ return;
+
+ const QString id = m_itemToId.value(item);
+ m_manager->removeGradient(id);
+}
+
+void QtGradientView::slotRenameGradient()
+{
+ QListWidgetItem *item = m_ui.listWidget->currentItem();
+ if (!item)
+ return;
+
+ m_ui.listWidget->editItem(item);
+}
+
+void QtGradientView::slotRenameGradient(QListWidgetItem *item)
+{
+ if (!item)
+ return;
+
+ const QString id = m_itemToId.value(item);
+ m_manager->renameGradient(id, item->text());
+}
+
+void QtGradientView::slotCurrentItemChanged(QListWidgetItem *item)
+{
+ m_editAction->setEnabled(item);
+ m_renameAction->setEnabled(item);
+ m_removeAction->setEnabled(item);
+ emit currentGradientChanged(m_itemToId.value(item));
+}
+
+void QtGradientView::slotGradientActivated(QListWidgetItem *item)
+{
+ const QString id = m_itemToId.value(item);
+ if (!id.isEmpty())
+ emit gradientActivated(id);
+}
+
+QtGradientView::QtGradientView(QWidget *parent)
+ : QWidget(parent)
+{
+ m_manager = 0;
+
+ m_ui.setupUi(this);
+
+ m_ui.listWidget->setViewMode(QListView::IconMode);
+ m_ui.listWidget->setMovement(QListView::Static);
+ m_ui.listWidget->setTextElideMode(Qt::ElideRight);
+ m_ui.listWidget->setResizeMode(QListWidget::Adjust);
+ m_ui.listWidget->setIconSize(QSize(64, 64));
+ m_ui.listWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+ QPalette pal = m_ui.listWidget->viewport()->palette();
+ int pixSize = 18;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+
+ QColor c1 = palette().color(QPalette::Midlight);
+ QColor c2 = palette().color(QPalette::Dark);
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, c1);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, c1);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, c2);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, c2);
+
+ pal.setBrush(QPalette::Base, QBrush(pm));
+ m_ui.listWidget->viewport()->setPalette(pal);
+
+ connect(m_ui.listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(slotGradientActivated(QListWidgetItem *)));
+ connect(m_ui.listWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(slotRenameGradient(QListWidgetItem *)));
+ connect(m_ui.listWidget, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(slotCurrentItemChanged(QListWidgetItem *)));
+
+ m_newAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/plus.png")), tr("New..."), this);
+ m_editAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/edit.png")), tr("Edit..."), this);
+ m_renameAction = new QAction(tr("Rename"), this);
+ m_removeAction = new QAction(QIcon(QLatin1String(":/trolltech/qtgradienteditor/images/minus.png")), tr("Remove"), this);
+
+ connect(m_newAction, SIGNAL(triggered()), this, SLOT(slotNewGradient()));
+ connect(m_editAction, SIGNAL(triggered()), this, SLOT(slotEditGradient()));
+ connect(m_removeAction, SIGNAL(triggered()), this, SLOT(slotRemoveGradient()));
+ connect(m_renameAction, SIGNAL(triggered()), this, SLOT(slotRenameGradient()));
+
+ m_ui.listWidget->addAction(m_newAction);
+ m_ui.listWidget->addAction(m_editAction);
+ m_ui.listWidget->addAction(m_renameAction);
+ m_ui.listWidget->addAction(m_removeAction);
+
+ m_ui.newButton->setDefaultAction(m_newAction);
+ m_ui.editButton->setDefaultAction(m_editAction);
+ m_ui.renameButton->setDefaultAction(m_renameAction);
+ m_ui.removeButton->setDefaultAction(m_removeAction);
+
+ m_ui.listWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
+}
+
+void QtGradientView::setGradientManager(QtGradientManager *manager)
+{
+ if (m_manager == manager)
+ return;
+
+ if (m_manager) {
+ disconnect(m_manager, SIGNAL(gradientAdded(const QString &, const QGradient &)),
+ this, SLOT(slotGradientAdded(const QString &, const QGradient &)));
+ disconnect(m_manager, SIGNAL(gradientRenamed(const QString &, const QString &)),
+ this, SLOT(slotGradientRenamed(const QString &, const QString &)));
+ disconnect(m_manager, SIGNAL(gradientChanged(const QString &, const QGradient &)),
+ this, SLOT(slotGradientChanged(const QString &, const QGradient &)));
+ disconnect(m_manager, SIGNAL(gradientRemoved(const QString &)),
+ this, SLOT(slotGradientRemoved(const QString &)));
+
+ m_ui.listWidget->clear();
+ m_idToItem.clear();
+ m_itemToId.clear();
+ }
+
+ m_manager = manager;
+
+ if (!m_manager)
+ return;
+
+ QMap<QString, QGradient> gradients = m_manager->gradients();
+ QMapIterator<QString, QGradient> itGrad(gradients);
+ while (itGrad.hasNext()) {
+ itGrad.next();
+ slotGradientAdded(itGrad.key(), itGrad.value());
+ }
+
+ connect(m_manager, SIGNAL(gradientAdded(const QString &, const QGradient &)),
+ this, SLOT(slotGradientAdded(const QString &, const QGradient &)));
+ connect(m_manager, SIGNAL(gradientRenamed(const QString &, const QString &)),
+ this, SLOT(slotGradientRenamed(const QString &, const QString &)));
+ connect(m_manager, SIGNAL(gradientChanged(const QString &, const QGradient &)),
+ this, SLOT(slotGradientChanged(const QString &, const QGradient &)));
+ connect(m_manager, SIGNAL(gradientRemoved(const QString &)),
+ this, SLOT(slotGradientRemoved(const QString &)));
+}
+
+QtGradientManager *QtGradientView::gradientManager() const
+{
+ return m_manager;
+}
+
+void QtGradientView::setCurrentGradient(const QString &id)
+{
+ QListWidgetItem *item = m_idToItem.value(id);
+ if (!item)
+ return;
+
+ m_ui.listWidget->setCurrentItem(item);
+}
+
+QString QtGradientView::currentGradient() const
+{
+ return m_itemToId.value(m_ui.listWidget->currentItem());
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/qtgradienteditor/qtgradientview.h b/tools/shared/qtgradienteditor/qtgradientview.h
new file mode 100644
index 0000000000..b1fafd78fe
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientview.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTVIEW_H
+#define GRADIENTVIEW_H
+
+#include <QtGui/QWidget>
+#include <QtCore/QMap>
+#include "ui_qtgradientview.h"
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientManager;
+class QListViewItem;
+class QAction;
+
+class QtGradientView : public QWidget
+{
+ Q_OBJECT
+public:
+ QtGradientView(QWidget *parent = 0);
+
+ void setGradientManager(QtGradientManager *manager);
+ QtGradientManager *gradientManager() const;
+
+ void setCurrentGradient(const QString &id);
+ QString currentGradient() const;
+
+signals:
+ void currentGradientChanged(const QString &id);
+ void gradientActivated(const QString &id);
+
+private slots:
+ void slotGradientAdded(const QString &id, const QGradient &gradient);
+ void slotGradientRenamed(const QString &id, const QString &newId);
+ void slotGradientChanged(const QString &id, const QGradient &newGradient);
+ void slotGradientRemoved(const QString &id);
+ void slotNewGradient();
+ void slotEditGradient();
+ void slotRemoveGradient();
+ void slotRenameGradient();
+ void slotRenameGradient(QListWidgetItem *item);
+ void slotCurrentItemChanged(QListWidgetItem *item);
+ void slotGradientActivated(QListWidgetItem *item);
+
+private:
+ QMap<QString, QListWidgetItem *> m_idToItem;
+ QMap<QListWidgetItem *, QString> m_itemToId;
+
+ QAction *m_newAction;
+ QAction *m_editAction;
+ QAction *m_renameAction;
+ QAction *m_removeAction;
+
+ QtGradientManager *m_manager;
+ Ui::QtGradientView m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtgradienteditor/qtgradientview.ui b/tools/shared/qtgradienteditor/qtgradientview.ui
new file mode 100644
index 0000000000..af7267ea2b
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientview.ui
@@ -0,0 +1,135 @@
+<ui version="4.0" >
+ <class>QtGradientView</class>
+ <widget class="QWidget" name="QtGradientView" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>484</width>
+ <height>228</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Gradient View</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QToolButton" name="newButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>New...</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="editButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Edit...</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="renameButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Rename</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="removeButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Remove</string>
+ </property>
+ <property name="toolButtonStyle" >
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>71</width>
+ <height>26</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QListWidget" name="listWidget" />
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>listWidget</tabstop>
+ <tabstop>newButton</tabstop>
+ <tabstop>editButton</tabstop>
+ <tabstop>renameButton</tabstop>
+ <tabstop>removeButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/shared/qtgradienteditor/qtgradientviewdialog.cpp b/tools/shared/qtgradienteditor/qtgradientviewdialog.cpp
new file mode 100644
index 0000000000..c139ec4622
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientviewdialog.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientviewdialog.h"
+#include "qtgradientmanager.h"
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+QtGradientViewDialog::QtGradientViewDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ m_ui.setupUi(this);
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+ connect(m_ui.gradientView, SIGNAL(currentGradientChanged(const QString &)),
+ this, SLOT(slotGradientSelected(const QString &)));
+ connect(m_ui.gradientView, SIGNAL(gradientActivated(const QString &)),
+ this, SLOT(slotGradientActivated(const QString &)));
+}
+
+void QtGradientViewDialog::setGradientManager(QtGradientManager *manager)
+{
+ m_ui.gradientView->setGradientManager(manager);
+}
+
+QGradient QtGradientViewDialog::getGradient(bool *ok, QtGradientManager *manager, QWidget *parent, const QString &caption)
+{
+ QtGradientViewDialog dlg(parent);
+ dlg.setGradientManager(manager);
+ dlg.setWindowTitle(caption);
+ QGradient grad = QLinearGradient();
+ const int res = dlg.exec();
+ if (res == QDialog::Accepted)
+ grad = dlg.m_ui.gradientView->gradientManager()->gradients().value(dlg.m_ui.gradientView->currentGradient());
+ if (ok)
+ *ok = res == QDialog::Accepted;
+ return grad;
+}
+
+void QtGradientViewDialog::slotGradientSelected(const QString &id)
+{
+ m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!id.isEmpty());
+}
+
+void QtGradientViewDialog::slotGradientActivated(const QString &id)
+{
+ Q_UNUSED(id)
+ accept();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/qtgradienteditor/qtgradientviewdialog.h b/tools/shared/qtgradienteditor/qtgradientviewdialog.h
new file mode 100644
index 0000000000..2ec7cddb36
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientviewdialog.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GRADIENTVIEWDIALOG_H
+#define GRADIENTVIEWDIALOG_H
+
+#include <QtGui/QWidget>
+#include <QtCore/QMap>
+#include "ui_qtgradientviewdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientManager;
+
+class QtGradientViewDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QtGradientViewDialog(QWidget *parent = 0);
+
+ void setGradientManager(QtGradientManager *manager);
+ QtGradientManager *gradientManager() const;
+
+ static QGradient getGradient(bool *ok, QtGradientManager *manager, QWidget *parent = 0, const QString &caption = tr("Select Gradient", 0));
+
+private slots:
+ void slotGradientSelected(const QString &id);
+ void slotGradientActivated(const QString &id);
+
+private:
+ Ui::QtGradientViewDialog m_ui;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/tools/shared/qtgradienteditor/qtgradientviewdialog.ui b/tools/shared/qtgradienteditor/qtgradientviewdialog.ui
new file mode 100644
index 0000000000..ed53209d48
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientviewdialog.ui
@@ -0,0 +1,121 @@
+<ui version="4.0" >
+ <comment>*********************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+*********************************************************************</comment>
+ <class>QtGradientViewDialog</class>
+ <widget class="QDialog" name="QtGradientViewDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>178</width>
+ <height>72</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Select Gradient</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QtGradientView" name="gradientView" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtGradientView</class>
+ <extends>QFrame</extends>
+ <header>qtgradientview.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>QtGradientViewDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>72</x>
+ <y>224</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>21</x>
+ <y>243</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>QtGradientViewDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>168</x>
+ <y>233</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>152</x>
+ <y>251</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/shared/qtgradienteditor/qtgradientwidget.cpp b/tools/shared/qtgradienteditor/qtgradientwidget.cpp
new file mode 100644
index 0000000000..3f6b48d5c3
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientwidget.cpp
@@ -0,0 +1,817 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgradientwidget.h"
+#include <QtCore/QMap>
+#include <QtGui/QImage>
+#include <QtGui/QPainter>
+#include <QtGui/QScrollBar>
+#include <QtGui/QMouseEvent>
+
+#define _USE_MATH_DEFINES
+
+
+#include "math.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientWidgetPrivate
+{
+ QtGradientWidget *q_ptr;
+ Q_DECLARE_PUBLIC(QtGradientWidget)
+public:
+ QPointF fromViewport(const QPointF &point) const;
+ QPointF toViewport(const QPointF &point) const;
+// void setupDrag(QtGradientStop *stop, int x);
+
+ QPointF checkRange(const QPointF &point) const;
+ QRectF pointRect(const QPointF &point, double size) const;
+
+ double correctAngle(double angle) const;
+ void setAngleConical(double angle);
+
+ void paintPoint(QPainter *painter, const QPointF &point, double size) const;
+
+ double m_handleSize;
+ bool m_backgroundCheckered;
+
+ QGradientStops m_gradientStops;
+ QGradient::Type m_gradientType;
+ QGradient::Spread m_gradientSpread;
+ QPointF m_startLinear;
+ QPointF m_endLinear;
+ QPointF m_centralRadial;
+ QPointF m_focalRadial;
+ qreal m_radiusRadial;
+ QPointF m_centralConical;
+ qreal m_angleConical;
+
+ enum Handle {
+ NoHandle,
+ StartLinearHandle,
+ EndLinearHandle,
+ CentralRadialHandle,
+ FocalRadialHandle,
+ RadiusRadialHandle,
+ CentralConicalHandle,
+ AngleConicalHandle
+ };
+
+ Handle m_dragHandle;
+ QPointF m_dragOffset;
+ //double m_radiusOffset;
+ double m_radiusFactor;
+ double m_dragRadius;
+ double m_angleOffset;
+ double m_dragAngle;
+};
+
+double QtGradientWidgetPrivate::correctAngle(double angle) const
+{
+ double a = angle;
+ while (a >= 360)
+ a -= 360;
+ while (a < 0)
+ a += 360;
+ return a;
+}
+
+void QtGradientWidgetPrivate::setAngleConical(double angle)
+{
+ double a = correctAngle(angle);
+ if (m_angleConical == a)
+ return;
+ m_angleConical = a;
+ emit q_ptr->angleConicalChanged(m_angleConical);
+}
+
+QRectF QtGradientWidgetPrivate::pointRect(const QPointF &point, double size) const
+{
+ return QRectF(point.x() - size / 2, point.y() - size / 2, size, size);
+}
+
+QPointF QtGradientWidgetPrivate::checkRange(const QPointF &point) const
+{
+ QPointF p = point;
+ if (p.x() > 1)
+ p.setX(1);
+ else if (p.x() < 0)
+ p.setX(0);
+ if (p.y() > 1)
+ p.setY(1);
+ else if (p.y() < 0)
+ p.setY(0);
+ return p;
+}
+
+QPointF QtGradientWidgetPrivate::fromViewport(const QPointF &point) const
+{
+ QSize size = q_ptr->size();
+ return QPointF(point.x() / size.width(), point.y() / size.height());
+}
+
+QPointF QtGradientWidgetPrivate::toViewport(const QPointF &point) const
+{
+ QSize size = q_ptr->size();
+ return QPointF(point.x() * size.width(), point.y() * size.height());
+}
+
+void QtGradientWidgetPrivate::paintPoint(QPainter *painter, const QPointF &point, double size) const
+{
+ QPointF pf = toViewport(point);
+ QRectF rf = pointRect(pf, size);
+
+ QPen pen;
+ pen.setWidthF(1);
+ QColor alphaZero = Qt::white;
+ alphaZero.setAlpha(0);
+
+ painter->save();
+ painter->drawEllipse(rf);
+
+ /*
+ painter->save();
+
+ QLinearGradient lgV(0, rf.top(), 0, rf.bottom());
+ lgV.setColorAt(0, alphaZero);
+ lgV.setColorAt(0.25, Qt::white);
+ lgV.setColorAt(0.25, Qt::white);
+ lgV.setColorAt(1, alphaZero);
+ pen.setBrush(lgV);
+ painter->setPen(pen);
+
+ painter->drawLine(QPointF(pf.x(), rf.top()), QPointF(pf.x(), rf.bottom()));
+
+ QLinearGradient lgH(rf.left(), 0, rf.right(), 0);
+ lgH.setColorAt(0, alphaZero);
+ lgH.setColorAt(0.5, Qt::white);
+ lgH.setColorAt(1, alphaZero);
+ pen.setBrush(lgH);
+ painter->setPen(pen);
+
+ painter->drawLine(QPointF(rf.left(), pf.y()), QPointF(rf.right(), pf.y()));
+
+ painter->restore();
+ */
+
+ painter->restore();
+}
+
+/*
+void QtGradientWidgetPrivate::setupDrag(QtGradientStop *stop, int x)
+{
+ m_model->setCurrentStop(stop);
+
+ int viewportX = qRound(toViewport(stop->position()));
+ m_dragOffset = x - viewportX;
+
+ QList<QtGradientStop *> stops = m_stops;
+ m_stops.clear();
+ QListIterator<QtGradientStop *> itStop(stops);
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (m_model->isSelected(s) || s == stop) {
+ m_dragStops[s] = s->position() - stop->position();
+ m_stops.append(s);
+ } else {
+ m_dragOriginal[s->position()] = s->color();
+ }
+ }
+ itStop.toFront();
+ while (itStop.hasNext()) {
+ QtGradientStop *s = itStop.next();
+ if (!m_model->isSelected(s))
+ m_stops.append(s);
+ }
+ m_stops.removeAll(stop);
+ m_stops.prepend(stop);
+}
+*/
+////////////////////////////
+
+QtGradientWidget::QtGradientWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ d_ptr = new QtGradientWidgetPrivate;
+ d_ptr->q_ptr = this;
+ d_ptr->m_backgroundCheckered = true;
+ d_ptr->m_handleSize = 20.0;
+ d_ptr->m_gradientType = QGradient::LinearGradient;
+ d_ptr->m_startLinear = QPointF(0, 0);
+ d_ptr->m_endLinear = QPointF(1, 1);
+ d_ptr->m_centralRadial = QPointF(0.5, 0.5);
+ d_ptr->m_focalRadial = QPointF(0.5, 0.5);
+ d_ptr->m_radiusRadial = 0.5;
+ d_ptr->m_centralConical = QPointF(0.5, 0.5);
+ d_ptr->m_angleConical = 0;
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle;
+
+ setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
+}
+
+QtGradientWidget::~QtGradientWidget()
+{
+ delete d_ptr;
+}
+
+QSize QtGradientWidget::sizeHint() const
+{
+ return QSize(176, 176);
+}
+
+QSize QtGradientWidget::minimumSizeHint() const
+{
+ return QSize(128, 128);
+}
+
+int QtGradientWidget::heightForWidth(int w) const
+{
+ return w;
+}
+
+void QtGradientWidget::setBackgroundCheckered(bool checkered)
+{
+ if (d_ptr->m_backgroundCheckered == checkered)
+ return;
+ d_ptr->m_backgroundCheckered = checkered;
+ update();
+}
+
+bool QtGradientWidget::isBackgroundCheckered() const
+{
+ return d_ptr->m_backgroundCheckered;
+}
+
+void QtGradientWidget::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ QPoint p = e->pos();
+ if (d_ptr->m_gradientType == QGradient::LinearGradient) {
+ QPointF startPoint = d_ptr->toViewport(d_ptr->m_startLinear);
+ double x = p.x() - startPoint.x();
+ double y = p.y() - startPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::StartLinearHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+
+ QPointF endPoint = d_ptr->toViewport(d_ptr->m_endLinear);
+ x = p.x() - endPoint.x();
+ y = p.y() - endPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::EndLinearHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+ } else if (d_ptr->m_gradientType == QGradient::RadialGradient) {
+ QPointF focalPoint = d_ptr->toViewport(d_ptr->m_focalRadial);
+ double x = p.x() - focalPoint.x();
+ double y = p.y() - focalPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 9) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::FocalRadialHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial);
+ x = p.x() - centralPoint.x();
+ y = p.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralRadialHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial);
+ QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3);
+ QRectF r1(0, r.y(), size().width(), r.height());
+ QRectF r2(r.x(), 0, r.width(), r.y());
+ QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height());
+ QPointF pF(p.x(), p.y());
+ if (r1.contains(pF) || r2.contains(pF) || r3.contains(pF)) {
+ x = pF.x() / size().width() - d_ptr->m_centralRadial.x();
+ y = pF.y() / size().height() - d_ptr->m_centralRadial.y();
+ double clickRadius = sqrt(x * x + y * y);
+ //d_ptr->m_radiusOffset = d_ptr->m_radiusRadial - clickRadius;
+ d_ptr->m_radiusFactor = d_ptr->m_radiusRadial / clickRadius;
+ if (d_ptr->m_radiusFactor == 0)
+ d_ptr->m_radiusFactor = 1;
+ d_ptr->m_dragRadius = d_ptr->m_radiusRadial;
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::RadiusRadialHandle;
+ mouseMoveEvent(e);
+ update();
+ return;
+ }
+ } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) {
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical);
+ double x = p.x() - centralPoint.x();
+ double y = p.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::CentralConicalHandle;
+ d_ptr->m_dragOffset = QPointF(x, y);
+ update();
+ return;
+ }
+ double radius = size().width();
+ if (size().height() < radius)
+ radius = size().height();
+ radius /= 2;
+ double corr = d_ptr->m_handleSize / 3;
+ radius -= corr;
+ QPointF vp = d_ptr->toViewport(d_ptr->m_centralConical);
+ x = p.x() - vp.x();
+ y = p.y() - vp.y();
+ if (((radius - corr) * (radius - corr) < (x * x + y * y)) &&
+ ((radius + corr) * (radius + corr) > (x * x + y * y))) {
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
+ QPointF current(e->pos().x(), e->pos().y());
+ x = current.x() - central.x();
+ y = current.y() - central.y();
+ x /= size().width() / 2;
+ y /= size().height() / 2;
+ double r = sqrt(x * x + y * y);
+
+ double arcSin = asin(y / r);
+ double arcCos = acos(x / r);
+
+ double angle = arcCos * 180 / M_PI;
+ if (arcSin > 0) {
+ angle = -angle;
+ }
+
+ d_ptr->m_angleOffset = d_ptr->m_angleConical - angle;
+ d_ptr->m_dragAngle = d_ptr->m_angleConical;
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::AngleConicalHandle;
+ update();
+ return;
+ }
+ }
+}
+
+void QtGradientWidget::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_UNUSED(e)
+ d_ptr->m_dragHandle = QtGradientWidgetPrivate::NoHandle;
+ update();
+}
+
+void QtGradientWidget::mouseMoveEvent(QMouseEvent *e)
+{
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::NoHandle)
+ return;
+
+ QPointF newPos = QPointF((double)e->pos().x() - d_ptr->m_dragOffset.x(),
+ (double)e->pos().y() - d_ptr->m_dragOffset.y());
+ QPointF newPoint = d_ptr->fromViewport(newPos);
+ if (newPoint.x() < 0)
+ newPoint.setX(0);
+ else if (newPoint.x() > 1)
+ newPoint.setX(1);
+ if (newPoint.y() < 0)
+ newPoint.setY(0);
+ else if (newPoint.y() > 1)
+ newPoint.setY(1);
+
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle) {
+ d_ptr->m_startLinear = newPoint;
+ emit startLinearChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle) {
+ d_ptr->m_endLinear = newPoint;
+ emit endLinearChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle) {
+ d_ptr->m_centralRadial = newPoint;
+ emit centralRadialChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle) {
+ d_ptr->m_focalRadial = newPoint;
+ emit focalRadialChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) {
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralRadial);
+ QPointF pF(e->pos().x(), e->pos().y());
+ double x = pF.x() - centralPoint.x();
+ double y = pF.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ if (d_ptr->m_radiusRadial != d_ptr->m_dragRadius) {
+ d_ptr->m_radiusRadial = d_ptr->m_dragRadius;
+ emit radiusRadialChanged(d_ptr->m_radiusRadial);
+ }
+ } else {
+ x = pF.x() / size().width() - d_ptr->m_centralRadial.x();
+ y = pF.y() / size().height() - d_ptr->m_centralRadial.y();
+ double moveRadius = sqrt(x * x + y * y);
+ //double newRadius = moveRadius + d_ptr->m_radiusOffset;
+ double newRadius = moveRadius * d_ptr->m_radiusFactor;
+ if (newRadius > 2)
+ newRadius = 2;
+ d_ptr->m_radiusRadial = newRadius;
+ emit radiusRadialChanged(d_ptr->m_radiusRadial);
+ }
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle) {
+ d_ptr->m_centralConical = newPoint;
+ emit centralConicalChanged(newPoint);
+ } else if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) {
+ QPointF centralPoint = d_ptr->toViewport(d_ptr->m_centralConical);
+ QPointF pF(e->pos().x(), e->pos().y());
+ double x = pF.x() - centralPoint.x();
+ double y = pF.y() - centralPoint.y();
+
+ if ((d_ptr->m_handleSize * d_ptr->m_handleSize / 4) > (x * x + y * y)) {
+ if (d_ptr->m_angleConical != d_ptr->m_dragAngle) {
+ d_ptr->m_angleConical = d_ptr->m_dragAngle;
+ emit angleConicalChanged(d_ptr->m_angleConical);
+ }
+ } else {
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
+ QPointF current = pF;
+ x = current.x() - central.x();
+ y = current.y() - central.y();
+ x /= size().width() / 2;
+ y /= size().height() / 2;
+ double r = sqrt(x * x + y * y);
+
+ double arcSin = asin(y / r);
+ double arcCos = acos(x / r);
+
+ double angle = arcCos * 180 / M_PI;
+ if (arcSin > 0) {
+ angle = -angle;
+ }
+
+ angle += d_ptr->m_angleOffset;
+
+ d_ptr->setAngleConical(angle);
+ }
+ }
+ update();
+}
+
+void QtGradientWidget::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ mousePressEvent(e);
+}
+
+void QtGradientWidget::paintEvent(QPaintEvent *e)
+{
+ Q_UNUSED(e)
+
+ QPainter p(this);
+
+ if (d_ptr->m_backgroundCheckered) {
+ int pixSize = 40;
+ QPixmap pm(2 * pixSize, 2 * pixSize);
+
+ QPainter pmp(&pm);
+ pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
+ pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
+ pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
+ pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
+
+ p.setBrushOrigin((size().width() % pixSize + pixSize) / 2, (size().height() % pixSize + pixSize) / 2);
+ p.fillRect(rect(), pm);
+ p.setBrushOrigin(0, 0);
+ }
+
+ QGradient *gradient = 0;
+ switch (d_ptr->m_gradientType) {
+ case QGradient::LinearGradient:
+ gradient = new QLinearGradient(d_ptr->m_startLinear, d_ptr->m_endLinear);
+ break;
+ case QGradient::RadialGradient:
+ gradient = new QRadialGradient(d_ptr->m_centralRadial, d_ptr->m_radiusRadial, d_ptr->m_focalRadial);
+ break;
+ case QGradient::ConicalGradient:
+ gradient = new QConicalGradient(d_ptr->m_centralConical, d_ptr->m_angleConical);
+ break;
+ default:
+ break;
+ }
+ if (!gradient)
+ return;
+
+ gradient->setStops(d_ptr->m_gradientStops);
+ gradient->setSpread(d_ptr->m_gradientSpread);
+
+ p.save();
+ p.scale(size().width(), size().height());
+ p.fillRect(QRect(0, 0, 1, 1), *gradient);
+ p.restore();
+
+ p.setRenderHint(QPainter::Antialiasing);
+
+ QColor c = QColor::fromRgbF(0.5, 0.5, 0.5, 0.5);
+ QBrush br(c);
+ p.setBrush(br);
+ QPen pen(Qt::white);
+ pen.setWidthF(1);
+ p.setPen(pen);
+ QPen dragPen = pen;
+ dragPen.setWidthF(2);
+ if (d_ptr->m_gradientType == QGradient::LinearGradient) {
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::StartLinearHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_startLinear, d_ptr->m_handleSize);
+ p.restore();
+
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::EndLinearHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_endLinear, d_ptr->m_handleSize);
+ p.restore();
+ } else if (d_ptr->m_gradientType == QGradient::RadialGradient) {
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralRadial);
+
+ p.save();
+ QRectF r = d_ptr->pointRect(central, 2 * d_ptr->m_handleSize / 3);
+ QRectF r1(0, r.y(), size().width(), r.height());
+ QRectF r2(r.x(), 0, r.width(), r.y());
+ QRectF r3(r.x(), r.y() + r.height(), r.width(), size().height() - r.y() - r.height());
+ p.fillRect(r1, c);
+ p.fillRect(r2, c);
+ p.fillRect(r3, c);
+ p.setBrush(Qt::NoBrush);
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralRadialHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_centralRadial, d_ptr->m_handleSize);
+ p.restore();
+
+ QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial * size().width(),
+ central.y() - d_ptr->m_radiusRadial * size().height(),
+ 2 * d_ptr->m_radiusRadial * size().width(),
+ 2 * d_ptr->m_radiusRadial * size().height());
+ p.setClipRect(r1);
+ p.setClipRect(r2, Qt::UniteClip);
+ p.setClipRect(r3, Qt::UniteClip);
+ p.drawEllipse(rect);
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::RadiusRadialHandle) {
+ p.save();
+ p.setPen(dragPen);
+ QRectF rect = QRectF(central.x() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(),
+ central.y() - d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height(),
+ 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().width(),
+ 2 * d_ptr->m_radiusRadial / d_ptr->m_radiusFactor * size().height());
+ p.drawEllipse(rect);
+
+ p.restore();
+ }
+ p.restore();
+
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::FocalRadialHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_focalRadial, 2 * d_ptr->m_handleSize / 3);
+ p.restore();
+ } else if (d_ptr->m_gradientType == QGradient::ConicalGradient) {
+ double radius = size().width();
+ if (size().height() < radius)
+ radius = size().height();
+ radius /= 2;
+ double corr = d_ptr->m_handleSize / 3;
+ radius -= corr;
+ QPointF central = d_ptr->toViewport(d_ptr->m_centralConical);
+
+ p.save();
+ p.setBrush(Qt::NoBrush);
+ QPen pen2(c);
+ pen2.setWidthF(2 * d_ptr->m_handleSize / 3);
+ p.setPen(pen2);
+ p.drawEllipse(d_ptr->pointRect(central, 2 * radius));
+ p.restore();
+
+ p.save();
+ p.setBrush(Qt::NoBrush);
+ int pointCount = 2;
+ for (int i = 0; i < pointCount; i++) {
+ QPointF ang(cos(M_PI * (i * 180.0 / pointCount + d_ptr->m_angleConical) / 180) * size().width() / 2,
+ -sin(M_PI * (i * 180.0 / pointCount + d_ptr->m_angleConical) / 180) * size().height() / 2);
+ double mod = sqrt(ang.x() * ang.x() + ang.y() * ang.y());
+ p.drawLine(QPointF(central.x() + ang.x() * (radius - corr) / mod,
+ central.y() + ang.y() * (radius - corr) / mod),
+ QPointF(central.x() + ang.x() * (radius + corr) / mod,
+ central.y() + ang.y() * (radius + corr) / mod));
+ p.drawLine(QPointF(central.x() - ang.x() * (radius - corr) / mod,
+ central.y() - ang.y() * (radius - corr) / mod),
+ QPointF(central.x() - ang.x() * (radius + corr) / mod,
+ central.y() - ang.y() * (radius + corr) / mod));
+ }
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::AngleConicalHandle) {
+ p.save();
+ p.setPen(dragPen);
+ QPointF ang(cos(M_PI * (d_ptr->m_angleConical - d_ptr->m_angleOffset) / 180) * size().width() / 2,
+ -sin(M_PI * (d_ptr->m_angleConical - d_ptr->m_angleOffset) / 180) * size().height() / 2);
+ double mod = sqrt(ang.x() * ang.x() + ang.y() * ang.y());
+ p.drawLine(QPointF(central.x() + ang.x() * (radius - corr) / mod,
+ central.y() + ang.y() * (radius - corr) / mod),
+ QPointF(central.x() + ang.x() * (radius + corr) / mod,
+ central.y() + ang.y() * (radius + corr) / mod));
+ p.restore();
+ }
+
+ p.restore();
+
+ p.save();
+ if (d_ptr->m_dragHandle == QtGradientWidgetPrivate::CentralConicalHandle)
+ p.setPen(dragPen);
+ d_ptr->paintPoint(&p, d_ptr->m_centralConical, d_ptr->m_handleSize);
+ p.restore();
+
+ }
+
+ delete gradient;
+}
+
+void QtGradientWidget::setGradientStops(const QGradientStops &stops)
+{
+ d_ptr->m_gradientStops = stops;
+ update();
+}
+
+QGradientStops QtGradientWidget::gradientStops() const
+{
+ return d_ptr->m_gradientStops;
+}
+
+void QtGradientWidget::setGradientType(QGradient::Type type)
+{
+ if (type == QGradient::NoGradient)
+ return;
+ if (d_ptr->m_gradientType == type)
+ return;
+
+ d_ptr->m_gradientType = type;
+ update();
+}
+
+QGradient::Type QtGradientWidget::gradientType() const
+{
+ return d_ptr->m_gradientType;
+}
+
+void QtGradientWidget::setGradientSpread(QGradient::Spread spread)
+{
+ if (d_ptr->m_gradientSpread == spread)
+ return;
+
+ d_ptr->m_gradientSpread = spread;
+ update();
+}
+
+QGradient::Spread QtGradientWidget::gradientSpread() const
+{
+ return d_ptr->m_gradientSpread;
+}
+
+void QtGradientWidget::setStartLinear(const QPointF &point)
+{
+ if (d_ptr->m_startLinear == point)
+ return;
+
+ d_ptr->m_startLinear = d_ptr->checkRange(point);
+ update();
+}
+
+QPointF QtGradientWidget::startLinear() const
+{
+ return d_ptr->m_startLinear;
+}
+
+void QtGradientWidget::setEndLinear(const QPointF &point)
+{
+ if (d_ptr->m_endLinear == point)
+ return;
+
+ d_ptr->m_endLinear = d_ptr->checkRange(point);
+ update();
+}
+
+QPointF QtGradientWidget::endLinear() const
+{
+ return d_ptr->m_endLinear;
+}
+
+void QtGradientWidget::setCentralRadial(const QPointF &point)
+{
+ if (d_ptr->m_centralRadial == point)
+ return;
+
+ d_ptr->m_centralRadial = point;
+ update();
+}
+
+QPointF QtGradientWidget::centralRadial() const
+{
+ return d_ptr->m_centralRadial;
+}
+
+void QtGradientWidget::setFocalRadial(const QPointF &point)
+{
+ if (d_ptr->m_focalRadial == point)
+ return;
+
+ d_ptr->m_focalRadial = point;
+ update();
+}
+
+QPointF QtGradientWidget::focalRadial() const
+{
+ return d_ptr->m_focalRadial;
+}
+
+void QtGradientWidget::setRadiusRadial(qreal radius)
+{
+ if (d_ptr->m_radiusRadial == radius)
+ return;
+
+ d_ptr->m_radiusRadial = radius;
+ update();
+}
+
+qreal QtGradientWidget::radiusRadial() const
+{
+ return d_ptr->m_radiusRadial;
+}
+
+void QtGradientWidget::setCentralConical(const QPointF &point)
+{
+ if (d_ptr->m_centralConical == point)
+ return;
+
+ d_ptr->m_centralConical = point;
+ update();
+}
+
+QPointF QtGradientWidget::centralConical() const
+{
+ return d_ptr->m_centralConical;
+}
+
+void QtGradientWidget::setAngleConical(qreal angle)
+{
+ if (d_ptr->m_angleConical == angle)
+ return;
+
+ d_ptr->m_angleConical = angle;
+ update();
+}
+
+qreal QtGradientWidget::angleConical() const
+{
+ return d_ptr->m_angleConical;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/shared/qtgradienteditor/qtgradientwidget.h b/tools/shared/qtgradienteditor/qtgradientwidget.h
new file mode 100644
index 0000000000..4dc740b939
--- /dev/null
+++ b/tools/shared/qtgradienteditor/qtgradientwidget.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGRADIENTWIDGET_H
+#define QTGRADIENTWIDGET_H
+
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class QtGradientWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(bool backgroundCheckered READ isBackgroundCheckered WRITE setBackgroundCheckered)
+public:
+ QtGradientWidget(QWidget *parent = 0);
+ ~QtGradientWidget();
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+ int heightForWidth(int w) const;
+
+ bool isBackgroundCheckered() const;
+ void setBackgroundCheckered(bool checkered);
+
+ QGradientStops gradientStops() const;
+
+ void setGradientType(QGradient::Type type);
+ QGradient::Type gradientType() const;
+
+ void setGradientSpread(QGradient::Spread spread);
+ QGradient::Spread gradientSpread() const;
+
+ void setStartLinear(const QPointF &point);
+ QPointF startLinear() const;
+
+ void setEndLinear(const QPointF &point);
+ QPointF endLinear() const;
+
+ void setCentralRadial(const QPointF &point);
+ QPointF centralRadial() const;
+
+ void setFocalRadial(const QPointF &point);
+ QPointF focalRadial() const;
+
+ void setRadiusRadial(qreal radius);
+ qreal radiusRadial() const;
+
+ void setCentralConical(const QPointF &point);
+ QPointF centralConical() const;
+
+ void setAngleConical(qreal angle);
+ qreal angleConical() const;
+
+public slots:
+ void setGradientStops(const QGradientStops &stops);
+signals:
+
+ void startLinearChanged(const QPointF &point);
+ void endLinearChanged(const QPointF &point);
+ void centralRadialChanged(const QPointF &point);
+ void focalRadialChanged(const QPointF &point);
+ void radiusRadialChanged(qreal radius);
+ void centralConicalChanged(const QPointF &point);
+ void angleConicalChanged(qreal angle);
+
+protected:
+ void paintEvent(QPaintEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseDoubleClickEvent(QMouseEvent *e);
+
+private:
+ class QtGradientWidgetPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtGradientWidget)
+ Q_DISABLE_COPY(QtGradientWidget)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qtpropertybrowser/images/cursor-arrow.png b/tools/shared/qtpropertybrowser/images/cursor-arrow.png
new file mode 100644
index 0000000000..a69ef4eb61
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-arrow.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-busy.png b/tools/shared/qtpropertybrowser/images/cursor-busy.png
new file mode 100644
index 0000000000..53717e4992
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-busy.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-closedhand.png b/tools/shared/qtpropertybrowser/images/cursor-closedhand.png
new file mode 100644
index 0000000000..b78dd1dac5
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-closedhand.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-cross.png b/tools/shared/qtpropertybrowser/images/cursor-cross.png
new file mode 100644
index 0000000000..fe38e74480
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-cross.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-forbidden.png b/tools/shared/qtpropertybrowser/images/cursor-forbidden.png
new file mode 100644
index 0000000000..2b08c4e2a3
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-forbidden.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-hand.png b/tools/shared/qtpropertybrowser/images/cursor-hand.png
new file mode 100644
index 0000000000..d2004aefa7
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-hand.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-hsplit.png b/tools/shared/qtpropertybrowser/images/cursor-hsplit.png
new file mode 100644
index 0000000000..a5667e3ffb
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-hsplit.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-ibeam.png b/tools/shared/qtpropertybrowser/images/cursor-ibeam.png
new file mode 100644
index 0000000000..097fc5fa72
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-ibeam.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-openhand.png b/tools/shared/qtpropertybrowser/images/cursor-openhand.png
new file mode 100644
index 0000000000..9181c859ed
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-openhand.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-sizeall.png b/tools/shared/qtpropertybrowser/images/cursor-sizeall.png
new file mode 100644
index 0000000000..69f13eb347
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-sizeall.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-sizeb.png b/tools/shared/qtpropertybrowser/images/cursor-sizeb.png
new file mode 100644
index 0000000000..f37d7b91e8
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-sizeb.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-sizef.png b/tools/shared/qtpropertybrowser/images/cursor-sizef.png
new file mode 100644
index 0000000000..3b127a05d3
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-sizef.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-sizeh.png b/tools/shared/qtpropertybrowser/images/cursor-sizeh.png
new file mode 100644
index 0000000000..a9f40cbc3d
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-sizeh.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-sizev.png b/tools/shared/qtpropertybrowser/images/cursor-sizev.png
new file mode 100644
index 0000000000..1edbab27a5
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-sizev.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-uparrow.png b/tools/shared/qtpropertybrowser/images/cursor-uparrow.png
new file mode 100644
index 0000000000..d3e70ef4c2
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-uparrow.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-vsplit.png b/tools/shared/qtpropertybrowser/images/cursor-vsplit.png
new file mode 100644
index 0000000000..1beda2570e
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-vsplit.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-wait.png b/tools/shared/qtpropertybrowser/images/cursor-wait.png
new file mode 100644
index 0000000000..69056c479e
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-wait.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/images/cursor-whatsthis.png b/tools/shared/qtpropertybrowser/images/cursor-whatsthis.png
new file mode 100644
index 0000000000..b47601c378
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/images/cursor-whatsthis.png
Binary files differ
diff --git a/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.cpp b/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.cpp
new file mode 100644
index 0000000000..ecdaf16a4a
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.cpp
@@ -0,0 +1,633 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtbuttonpropertybrowser.h"
+#include <QtCore/QSet>
+#include <QtGui/QGridLayout>
+#include <QtGui/QLabel>
+#include <QtCore/QTimer>
+#include <QtCore/QMap>
+#include <QtGui/QToolButton>
+#include <QtGui/QStyle>
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtButtonPropertyBrowserPrivate
+{
+ QtButtonPropertyBrowser *q_ptr;
+ Q_DECLARE_PUBLIC(QtButtonPropertyBrowser)
+public:
+
+ void init(QWidget *parent);
+
+ void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex);
+ void propertyRemoved(QtBrowserItem *index);
+ void propertyChanged(QtBrowserItem *index);
+ QWidget *createEditor(QtProperty *property, QWidget *parent) const
+ { return q_ptr->createEditor(property, parent); }
+
+ void slotEditorDestroyed();
+ void slotUpdate();
+ void slotToggled(bool checked);
+
+ struct WidgetItem
+ {
+ WidgetItem() : widget(0), label(0), widgetLabel(0),
+ button(0), container(0), layout(0), /*line(0), */parent(0), expanded(false) { }
+ QWidget *widget; // can be null
+ QLabel *label; // main label with property name
+ QLabel *widgetLabel; // label substitute showing the current value if there is no widget
+ QToolButton *button; // expandable button for items with children
+ QWidget *container; // container which is expanded when the button is clicked
+ QGridLayout *layout; // layout in container
+ WidgetItem *parent;
+ QList<WidgetItem *> children;
+ bool expanded;
+ };
+private:
+ void updateLater();
+ void updateItem(WidgetItem *item);
+ void insertRow(QGridLayout *layout, int row) const;
+ void removeRow(QGridLayout *layout, int row) const;
+ int gridRow(WidgetItem *item) const;
+ int gridSpan(WidgetItem *item) const;
+ void setExpanded(WidgetItem *item, bool expanded);
+ QToolButton *createButton(QWidget *panret = 0) const;
+
+ QMap<QtBrowserItem *, WidgetItem *> m_indexToItem;
+ QMap<WidgetItem *, QtBrowserItem *> m_itemToIndex;
+ QMap<QWidget *, WidgetItem *> m_widgetToItem;
+ QMap<QObject *, WidgetItem *> m_buttonToItem;
+ QGridLayout *m_mainLayout;
+ QList<WidgetItem *> m_children;
+ QList<WidgetItem *> m_recreateQueue;
+};
+
+QToolButton *QtButtonPropertyBrowserPrivate::createButton(QWidget *parent) const
+{
+ QToolButton *button = new QToolButton(parent);
+ button->setCheckable(true);
+ button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
+ button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ button->setArrowType(Qt::DownArrow);
+ button->setIconSize(QSize(3, 16));
+ /*
+ QIcon icon;
+ icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowDown), QIcon::Normal, QIcon::Off);
+ icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowUp), QIcon::Normal, QIcon::On);
+ button->setIcon(icon);
+ */
+ return button;
+}
+
+int QtButtonPropertyBrowserPrivate::gridRow(WidgetItem *item) const
+{
+ QList<WidgetItem *> siblings;
+ if (item->parent)
+ siblings = item->parent->children;
+ else
+ siblings = m_children;
+
+ int row = 0;
+ QListIterator<WidgetItem *> it(siblings);
+ while (it.hasNext()) {
+ WidgetItem *sibling = it.next();
+ if (sibling == item)
+ return row;
+ row += gridSpan(sibling);
+ }
+ return -1;
+}
+
+int QtButtonPropertyBrowserPrivate::gridSpan(WidgetItem *item) const
+{
+ if (item->container && item->expanded)
+ return 2;
+ return 1;
+}
+
+void QtButtonPropertyBrowserPrivate::init(QWidget *parent)
+{
+ m_mainLayout = new QGridLayout();
+ parent->setLayout(m_mainLayout);
+ QLayoutItem *item = new QSpacerItem(0, 0,
+ QSizePolicy::Fixed, QSizePolicy::Expanding);
+ m_mainLayout->addItem(item, 0, 0);
+}
+
+void QtButtonPropertyBrowserPrivate::slotEditorDestroyed()
+{
+ QWidget *editor = qobject_cast<QWidget *>(q_ptr->sender());
+ if (!editor)
+ return;
+ if (!m_widgetToItem.contains(editor))
+ return;
+ m_widgetToItem[editor]->widget = 0;
+ m_widgetToItem.remove(editor);
+}
+
+void QtButtonPropertyBrowserPrivate::slotUpdate()
+{
+ QListIterator<WidgetItem *> itItem(m_recreateQueue);
+ while (itItem.hasNext()) {
+ WidgetItem *item = itItem.next();
+
+ WidgetItem *parent = item->parent;
+ QWidget *w = 0;
+ QGridLayout *l = 0;
+ const int oldRow = gridRow(item);
+ if (parent) {
+ w = parent->container;
+ l = parent->layout;
+ } else {
+ w = q_ptr;
+ l = m_mainLayout;
+ }
+
+ int span = 1;
+ if (!item->widget && !item->widgetLabel)
+ span = 2;
+ item->label = new QLabel(w);
+ item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ l->addWidget(item->label, oldRow, 0, 1, span);
+
+ updateItem(item);
+ }
+ m_recreateQueue.clear();
+}
+
+void QtButtonPropertyBrowserPrivate::setExpanded(WidgetItem *item, bool expanded)
+{
+ if (item->expanded == expanded)
+ return;
+
+ if (!item->container)
+ return;
+
+ item->expanded = expanded;
+ const int row = gridRow(item);
+ WidgetItem *parent = item->parent;
+ QGridLayout *l = 0;
+ if (parent)
+ l = parent->layout;
+ else
+ l = m_mainLayout;
+
+ if (expanded) {
+ insertRow(l, row + 1);
+ l->addWidget(item->container, row + 1, 0, 1, 2);
+ item->container->show();
+ } else {
+ l->removeWidget(item->container);
+ item->container->hide();
+ removeRow(l, row + 1);
+ }
+
+ item->button->setChecked(expanded);
+ item->button->setArrowType(expanded ? Qt::UpArrow : Qt::DownArrow);
+}
+
+void QtButtonPropertyBrowserPrivate::slotToggled(bool checked)
+{
+ WidgetItem *item = m_buttonToItem.value(q_ptr->sender());
+ if (!item)
+ return;
+
+ setExpanded(item, checked);
+
+ if (checked)
+ emit q_ptr->expanded(m_itemToIndex.value(item));
+ else
+ emit q_ptr->collapsed(m_itemToIndex.value(item));
+}
+
+void QtButtonPropertyBrowserPrivate::updateLater()
+{
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdate()));
+}
+
+void QtButtonPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex)
+{
+ WidgetItem *afterItem = m_indexToItem.value(afterIndex);
+ WidgetItem *parentItem = m_indexToItem.value(index->parent());
+
+ WidgetItem *newItem = new WidgetItem();
+ newItem->parent = parentItem;
+
+ QGridLayout *layout = 0;
+ QWidget *parentWidget = 0;
+ int row = -1;
+ if (!afterItem) {
+ row = 0;
+ if (parentItem)
+ parentItem->children.insert(0, newItem);
+ else
+ m_children.insert(0, newItem);
+ } else {
+ row = gridRow(afterItem) + gridSpan(afterItem);
+ if (parentItem)
+ parentItem->children.insert(parentItem->children.indexOf(afterItem) + 1, newItem);
+ else
+ m_children.insert(m_children.indexOf(afterItem) + 1, newItem);
+ }
+
+ if (!parentItem) {
+ layout = m_mainLayout;
+ parentWidget = q_ptr;
+ } else {
+ if (!parentItem->container) {
+ m_recreateQueue.removeAll(parentItem);
+ WidgetItem *grandParent = parentItem->parent;
+ QWidget *w = 0;
+ QGridLayout *l = 0;
+ const int oldRow = gridRow(parentItem);
+ if (grandParent) {
+ w = grandParent->container;
+ l = grandParent->layout;
+ } else {
+ w = q_ptr;
+ l = m_mainLayout;
+ }
+ QFrame *container = new QFrame();
+ container->setFrameShape(QFrame::Panel);
+ container->setFrameShadow(QFrame::Raised);
+ parentItem->container = container;
+ parentItem->button = createButton();
+ m_buttonToItem[parentItem->button] = parentItem;
+ q_ptr->connect(parentItem->button, SIGNAL(toggled(bool)), q_ptr, SLOT(slotToggled(bool)));
+ parentItem->layout = new QGridLayout();
+ container->setLayout(parentItem->layout);
+ if (parentItem->label) {
+ l->removeWidget(parentItem->label);
+ delete parentItem->label;
+ parentItem->label = 0;
+ }
+ int span = 1;
+ if (!parentItem->widget && !parentItem->widgetLabel)
+ span = 2;
+ l->addWidget(parentItem->button, oldRow, 0, 1, span);
+ updateItem(parentItem);
+ }
+ layout = parentItem->layout;
+ parentWidget = parentItem->container;
+ }
+
+ newItem->label = new QLabel(parentWidget);
+ newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ newItem->widget = createEditor(index->property(), parentWidget);
+ if (newItem->widget) {
+ QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed()));
+ m_widgetToItem[newItem->widget] = newItem;
+ } else if (index->property()->hasValue()) {
+ newItem->widgetLabel = new QLabel(parentWidget);
+ newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
+ }
+
+ insertRow(layout, row);
+ int span = 1;
+ if (newItem->widget)
+ layout->addWidget(newItem->widget, row, 1);
+ else if (newItem->widgetLabel)
+ layout->addWidget(newItem->widgetLabel, row, 1);
+ else
+ span = 2;
+ layout->addWidget(newItem->label, row, 0, span, 1);
+
+ m_itemToIndex[newItem] = index;
+ m_indexToItem[index] = newItem;
+
+ updateItem(newItem);
+}
+
+void QtButtonPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index)
+{
+ WidgetItem *item = m_indexToItem.value(index);
+
+ m_indexToItem.remove(index);
+ m_itemToIndex.remove(item);
+
+ WidgetItem *parentItem = item->parent;
+
+ const int row = gridRow(item);
+
+ if (parentItem)
+ parentItem->children.removeAt(parentItem->children.indexOf(item));
+ else
+ m_children.removeAt(m_children.indexOf(item));
+
+ const int colSpan = gridSpan(item);
+
+ m_buttonToItem.remove(item->button);
+
+ if (item->widget)
+ delete item->widget;
+ if (item->label)
+ delete item->label;
+ if (item->widgetLabel)
+ delete item->widgetLabel;
+ if (item->button)
+ delete item->button;
+ if (item->container)
+ delete item->container;
+
+ if (!parentItem) {
+ removeRow(m_mainLayout, row);
+ if (colSpan > 1)
+ removeRow(m_mainLayout, row);
+ } else if (parentItem->children.count() != 0) {
+ removeRow(parentItem->layout, row);
+ if (colSpan > 1)
+ removeRow(parentItem->layout, row);
+ } else {
+ const WidgetItem *grandParent = parentItem->parent;
+ QGridLayout *l = 0;
+ if (grandParent) {
+ l = grandParent->layout;
+ } else {
+ l = m_mainLayout;
+ }
+
+ const int parentRow = gridRow(parentItem);
+ const int parentSpan = gridSpan(parentItem);
+
+ l->removeWidget(parentItem->button);
+ l->removeWidget(parentItem->container);
+ delete parentItem->button;
+ delete parentItem->container;
+ parentItem->button = 0;
+ parentItem->container = 0;
+ parentItem->layout = 0;
+ if (!m_recreateQueue.contains(parentItem))
+ m_recreateQueue.append(parentItem);
+ if (parentSpan > 1)
+ removeRow(l, parentRow + 1);
+
+ updateLater();
+ }
+ m_recreateQueue.removeAll(item);
+
+ delete item;
+}
+
+void QtButtonPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const
+{
+ QMap<QLayoutItem *, QRect> itemToPos;
+ int idx = 0;
+ while (idx < layout->count()) {
+ int r, c, rs, cs;
+ layout->getItemPosition(idx, &r, &c, &rs, &cs);
+ if (r >= row) {
+ itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs);
+ } else {
+ idx++;
+ }
+ }
+
+ const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
+ for(QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
+ const QRect r = it.value();
+ layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
+ }
+}
+
+void QtButtonPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const
+{
+ QMap<QLayoutItem *, QRect> itemToPos;
+ int idx = 0;
+ while (idx < layout->count()) {
+ int r, c, rs, cs;
+ layout->getItemPosition(idx, &r, &c, &rs, &cs);
+ if (r > row) {
+ itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs);
+ } else {
+ idx++;
+ }
+ }
+
+ const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
+ for(QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
+ const QRect r = it.value();
+ layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
+ }
+}
+
+void QtButtonPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index)
+{
+ WidgetItem *item = m_indexToItem.value(index);
+
+ updateItem(item);
+}
+
+void QtButtonPropertyBrowserPrivate::updateItem(WidgetItem *item)
+{
+ QtProperty *property = m_itemToIndex[item]->property();
+ if (item->button) {
+ QFont font = item->button->font();
+ font.setUnderline(property->isModified());
+ item->button->setFont(font);
+ item->button->setText(property->propertyName());
+ item->button->setToolTip(property->toolTip());
+ item->button->setStatusTip(property->statusTip());
+ item->button->setWhatsThis(property->whatsThis());
+ item->button->setEnabled(property->isEnabled());
+ }
+ if (item->label) {
+ QFont font = item->label->font();
+ font.setUnderline(property->isModified());
+ item->label->setFont(font);
+ item->label->setText(property->propertyName());
+ item->label->setToolTip(property->toolTip());
+ item->label->setStatusTip(property->statusTip());
+ item->label->setWhatsThis(property->whatsThis());
+ item->label->setEnabled(property->isEnabled());
+ }
+ if (item->widgetLabel) {
+ QFont font = item->widgetLabel->font();
+ font.setUnderline(false);
+ item->widgetLabel->setFont(font);
+ item->widgetLabel->setText(property->valueText());
+ item->widgetLabel->setToolTip(property->valueText());
+ item->widgetLabel->setEnabled(property->isEnabled());
+ }
+ if (item->widget) {
+ QFont font = item->widget->font();
+ font.setUnderline(false);
+ item->widget->setFont(font);
+ item->widget->setEnabled(property->isEnabled());
+ item->widget->setToolTip(property->valueText());
+ }
+}
+
+
+
+/*!
+ \class QtButtonPropertyBrowser
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtButtonPropertyBrowser class provides a drop down QToolButton
+ based property browser.
+
+ A property browser is a widget that enables the user to edit a
+ given set of properties. Each property is represented by a label
+ specifying the property's name, and an editing widget (e.g. a line
+ edit or a combobox) holding its value. A property can have zero or
+ more subproperties.
+
+ QtButtonPropertyBrowser provides drop down button for all nested
+ properties, i.e. subproperties are enclosed by a container associated with
+ the drop down button. The parent property's name is displayed as button text. For example:
+
+ \image qtbuttonpropertybrowser.png
+
+ Use the QtAbstractPropertyBrowser API to add, insert and remove
+ properties from an instance of the QtButtonPropertyBrowser
+ class. The properties themselves are created and managed by
+ implementations of the QtAbstractPropertyManager class.
+
+ \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser
+*/
+
+/*!
+ \fn void QtButtonPropertyBrowser::collapsed(QtBrowserItem *item)
+
+ This signal is emitted when the \a item is collapsed.
+
+ \sa expanded(), setExpanded()
+*/
+
+/*!
+ \fn void QtButtonPropertyBrowser::expanded(QtBrowserItem *item)
+
+ This signal is emitted when the \a item is expanded.
+
+ \sa collapsed(), setExpanded()
+*/
+
+/*!
+ Creates a property browser with the given \a parent.
+*/
+QtButtonPropertyBrowser::QtButtonPropertyBrowser(QWidget *parent)
+ : QtAbstractPropertyBrowser(parent)
+{
+ d_ptr = new QtButtonPropertyBrowserPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->init(this);
+}
+
+/*!
+ Destroys this property browser.
+
+ Note that the properties that were inserted into this browser are
+ \e not destroyed since they may still be used in other
+ browsers. The properties are owned by the manager that created
+ them.
+
+ \sa QtProperty, QtAbstractPropertyManager
+*/
+QtButtonPropertyBrowser::~QtButtonPropertyBrowser()
+{
+ const QMap<QtButtonPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator icend = d_ptr->m_itemToIndex.constEnd();
+ for (QMap<QtButtonPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it)
+ delete it.key();
+ delete d_ptr;
+}
+
+/*!
+ \reimp
+*/
+void QtButtonPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem)
+{
+ d_ptr->propertyInserted(item, afterItem);
+}
+
+/*!
+ \reimp
+*/
+void QtButtonPropertyBrowser::itemRemoved(QtBrowserItem *item)
+{
+ d_ptr->propertyRemoved(item);
+}
+
+/*!
+ \reimp
+*/
+void QtButtonPropertyBrowser::itemChanged(QtBrowserItem *item)
+{
+ d_ptr->propertyChanged(item);
+}
+
+/*!
+ Sets the \a item to either collapse or expanded, depending on the value of \a expanded.
+
+ \sa isExpanded(), expanded(), collapsed()
+*/
+
+void QtButtonPropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded)
+{
+ QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item);
+ if (itm)
+ d_ptr->setExpanded(itm, expanded);
+}
+
+/*!
+ Returns true if the \a item is expanded; otherwise returns false.
+
+ \sa setExpanded()
+*/
+
+bool QtButtonPropertyBrowser::isExpanded(QtBrowserItem *item) const
+{
+ QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item);
+ if (itm)
+ return itm->expanded;
+ return false;
+}
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#include "moc_qtbuttonpropertybrowser.cpp"
diff --git a/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h b/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h
new file mode 100644
index 0000000000..0833c2d123
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtbuttonpropertybrowser.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTBUTTONPROPERTYBROWSER_H
+#define QTBUTTONPROPERTYBROWSER_H
+
+#include "qtpropertybrowser.h"
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtButtonPropertyBrowserPrivate;
+
+class QtButtonPropertyBrowser : public QtAbstractPropertyBrowser
+{
+ Q_OBJECT
+public:
+
+ QtButtonPropertyBrowser(QWidget *parent = 0);
+ ~QtButtonPropertyBrowser();
+
+ void setExpanded(QtBrowserItem *item, bool expanded);
+ bool isExpanded(QtBrowserItem *item) const;
+
+Q_SIGNALS:
+
+ void collapsed(QtBrowserItem *item);
+ void expanded(QtBrowserItem *item);
+
+protected:
+ virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem);
+ virtual void itemRemoved(QtBrowserItem *item);
+ virtual void itemChanged(QtBrowserItem *item);
+
+private:
+
+ QtButtonPropertyBrowserPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtButtonPropertyBrowser)
+ Q_DISABLE_COPY(QtButtonPropertyBrowser)
+ Q_PRIVATE_SLOT(d_func(), void slotUpdate())
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed())
+ Q_PRIVATE_SLOT(d_func(), void slotToggled(bool))
+
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#endif
diff --git a/tools/shared/qtpropertybrowser/qteditorfactory.cpp b/tools/shared/qtpropertybrowser/qteditorfactory.cpp
new file mode 100644
index 0000000000..3e9336ff82
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qteditorfactory.cpp
@@ -0,0 +1,2591 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qteditorfactory.h"
+#include "qtpropertybrowserutils_p.h"
+#include <QtGui/QSpinBox>
+#include <QtGui/QScrollBar>
+#include <QtGui/QComboBox>
+#include <QtGui/QAbstractItemView>
+#include <QtGui/QLineEdit>
+#include <QtGui/QDateTimeEdit>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QMenu>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QApplication>
+#include <QtGui/QLabel>
+#include <QtGui/QToolButton>
+#include <QtGui/QColorDialog>
+#include <QtGui/QFontDialog>
+#include <QtGui/QSpacerItem>
+#include <QtCore/QMap>
+
+#if defined(Q_CC_MSVC)
+# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */
+#endif
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+// Set a hard coded left margin to account for the indentation
+// of the tree view icon when switching to an editor
+
+static inline void setupTreeViewEditorMargin(QLayout *lt)
+{
+ enum { DecorationMargin = 4 };
+ if (QApplication::layoutDirection() == Qt::LeftToRight)
+ lt->setContentsMargins(DecorationMargin, 0, 0, 0);
+ else
+ lt->setContentsMargins(0, 0, DecorationMargin, 0);
+}
+
+// ---------- EditorFactoryPrivate :
+// Base class for editor factory private classes. Manages mapping of properties to editors and vice versa.
+
+template <class Editor>
+class EditorFactoryPrivate
+{
+public:
+
+ typedef QList<Editor *> EditorList;
+ typedef QMap<QtProperty *, EditorList> PropertyToEditorListMap;
+ typedef QMap<Editor *, QtProperty *> EditorToPropertyMap;
+
+ Editor *createEditor(QtProperty *property, QWidget *parent);
+ void initializeEditor(QtProperty *property, Editor *e);
+ void slotEditorDestroyed(QObject *object);
+
+ PropertyToEditorListMap m_createdEditors;
+ EditorToPropertyMap m_editorToProperty;
+};
+
+template <class Editor>
+Editor *EditorFactoryPrivate<Editor>::createEditor(QtProperty *property, QWidget *parent)
+{
+ Editor *editor = new Editor(parent);
+ initializeEditor(property, editor);
+ return editor;
+}
+
+template <class Editor>
+void EditorFactoryPrivate<Editor>::initializeEditor(QtProperty *property, Editor *editor)
+{
+ Q_TYPENAME PropertyToEditorListMap::iterator it = m_createdEditors.find(property);
+ if (it == m_createdEditors.end())
+ it = m_createdEditors.insert(property, EditorList());
+ it.value().append(editor);
+ m_editorToProperty.insert(editor, property);
+}
+
+template <class Editor>
+void EditorFactoryPrivate<Editor>::slotEditorDestroyed(QObject *object)
+{
+ const Q_TYPENAME EditorToPropertyMap::iterator ecend = m_editorToProperty.end();
+ for (Q_TYPENAME EditorToPropertyMap::iterator itEditor = m_editorToProperty.begin(); itEditor != ecend; ++itEditor) {
+ if (itEditor.key() == object) {
+ Editor *editor = itEditor.key();
+ QtProperty *property = itEditor.value();
+ const Q_TYPENAME PropertyToEditorListMap::iterator pit = m_createdEditors.find(property);
+ if (pit != m_createdEditors.end()) {
+ pit.value().removeAll(editor);
+ if (pit.value().empty())
+ m_createdEditors.erase(pit);
+ }
+ m_editorToProperty.erase(itEditor);
+ return;
+ }
+ }
+}
+
+// ------------ QtSpinBoxFactory
+
+class QtSpinBoxFactoryPrivate : public EditorFactoryPrivate<QSpinBox>
+{
+ QtSpinBoxFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtSpinBoxFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, int value);
+ void slotRangeChanged(QtProperty *property, int min, int max);
+ void slotSingleStepChanged(QtProperty *property, int step);
+ void slotSetValue(int value);
+};
+
+void QtSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, int value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+ QListIterator<QSpinBox *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QSpinBox *editor = itEditor.next();
+ if (editor->value() != value) {
+ editor->blockSignals(true);
+ editor->setValue(value);
+ editor->blockSignals(false);
+ }
+ }
+}
+
+void QtSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtIntPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QListIterator<QSpinBox *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QSpinBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setRange(min, max);
+ editor->setValue(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+ QListIterator<QSpinBox *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QSpinBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setSingleStep(step);
+ editor->blockSignals(false);
+ }
+}
+
+void QtSpinBoxFactoryPrivate::slotSetValue(int value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QSpinBox *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QSpinBox *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) {
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtIntPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+ }
+}
+
+/*!
+ \class QtSpinBoxFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtSpinBoxFactory class provides QSpinBox widgets for
+ properties created by QtIntPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtIntPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtSpinBoxFactory::QtSpinBoxFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtIntPropertyManager>(parent)
+{
+ d_ptr = new QtSpinBoxFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtSpinBoxFactory::~QtSpinBoxFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtSpinBoxFactory::connectPropertyManager(QtIntPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, int)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtSpinBoxFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QSpinBox *editor = d_ptr->createEditor(property, parent);
+ editor->setSingleStep(manager->singleStep(property));
+ editor->setRange(manager->minimum(property), manager->maximum(property));
+ editor->setValue(manager->value(property));
+ editor->setKeyboardTracking(false);
+
+ connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtSpinBoxFactory::disconnectPropertyManager(QtIntPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, int)));
+}
+
+// QtSliderFactory
+
+class QtSliderFactoryPrivate : public EditorFactoryPrivate<QSlider>
+{
+ QtSliderFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtSliderFactory)
+public:
+ void slotPropertyChanged(QtProperty *property, int value);
+ void slotRangeChanged(QtProperty *property, int min, int max);
+ void slotSingleStepChanged(QtProperty *property, int step);
+ void slotSetValue(int value);
+};
+
+void QtSliderFactoryPrivate::slotPropertyChanged(QtProperty *property, int value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+ QListIterator<QSlider *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QSlider *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setValue(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtSliderFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtIntPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QListIterator<QSlider *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QSlider *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setRange(min, max);
+ editor->setValue(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtSliderFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+ QListIterator<QSlider *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QSlider *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setSingleStep(step);
+ editor->blockSignals(false);
+ }
+}
+
+void QtSliderFactoryPrivate::slotSetValue(int value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QSlider *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QSlider *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor ) {
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtIntPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+ }
+}
+
+/*!
+ \class QtSliderFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtSliderFactory class provides QSlider widgets for
+ properties created by QtIntPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtIntPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtSliderFactory::QtSliderFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtIntPropertyManager>(parent)
+{
+ d_ptr = new QtSliderFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtSliderFactory::~QtSliderFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtSliderFactory::connectPropertyManager(QtIntPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, int)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtSliderFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QSlider *editor = new QSlider(Qt::Horizontal, parent);
+ d_ptr->initializeEditor(property, editor);
+ editor->setSingleStep(manager->singleStep(property));
+ editor->setRange(manager->minimum(property), manager->maximum(property));
+ editor->setValue(manager->value(property));
+
+ connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtSliderFactory::disconnectPropertyManager(QtIntPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, int)));
+}
+
+// QtSliderFactory
+
+class QtScrollBarFactoryPrivate : public EditorFactoryPrivate<QScrollBar>
+{
+ QtScrollBarFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtScrollBarFactory)
+public:
+ void slotPropertyChanged(QtProperty *property, int value);
+ void slotRangeChanged(QtProperty *property, int min, int max);
+ void slotSingleStepChanged(QtProperty *property, int step);
+ void slotSetValue(int value);
+};
+
+void QtScrollBarFactoryPrivate::slotPropertyChanged(QtProperty *property, int value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QListIterator<QScrollBar *> itEditor( m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QScrollBar *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setValue(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtScrollBarFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtIntPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QListIterator<QScrollBar *> itEditor( m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QScrollBar *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setRange(min, max);
+ editor->setValue(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtScrollBarFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+ QListIterator<QScrollBar *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QScrollBar *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setSingleStep(step);
+ editor->blockSignals(false);
+ }
+}
+
+void QtScrollBarFactoryPrivate::slotSetValue(int value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QScrollBar *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QScrollBar *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtIntPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtScrollBarFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtScrollBarFactory class provides QScrollBar widgets for
+ properties created by QtIntPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtIntPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtScrollBarFactory::QtScrollBarFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtIntPropertyManager>(parent)
+{
+ d_ptr = new QtScrollBarFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtScrollBarFactory::~QtScrollBarFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtScrollBarFactory::connectPropertyManager(QtIntPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, int)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtScrollBarFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QScrollBar *editor = new QScrollBar(Qt::Horizontal, parent);
+ d_ptr->initializeEditor(property, editor);
+ editor->setSingleStep(manager->singleStep(property));
+ editor->setRange(manager->minimum(property), manager->maximum(property));
+ editor->setValue(manager->value(property));
+ connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtScrollBarFactory::disconnectPropertyManager(QtIntPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, int)));
+}
+
+// QtCheckBoxFactory
+
+class QtCheckBoxFactoryPrivate : public EditorFactoryPrivate<QtBoolEdit>
+{
+ QtCheckBoxFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtCheckBoxFactory)
+public:
+ void slotPropertyChanged(QtProperty *property, bool value);
+ void slotSetValue(bool value);
+};
+
+void QtCheckBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, bool value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QListIterator<QtBoolEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QtBoolEdit *editor = itEditor.next();
+ editor->blockCheckBoxSignals(true);
+ editor->setChecked(value);
+ editor->blockCheckBoxSignals(false);
+ }
+}
+
+void QtCheckBoxFactoryPrivate::slotSetValue(bool value)
+{
+ QObject *object = q_ptr->sender();
+
+ const QMap<QtBoolEdit *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QtBoolEdit *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtBoolPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtCheckBoxFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtCheckBoxFactory class provides QCheckBox widgets for
+ properties created by QtBoolPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtBoolPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtCheckBoxFactory::QtCheckBoxFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtBoolPropertyManager>(parent)
+{
+ d_ptr = new QtCheckBoxFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtCheckBoxFactory::~QtCheckBoxFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtCheckBoxFactory::connectPropertyManager(QtBoolPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, bool)),
+ this, SLOT(slotPropertyChanged(QtProperty *, bool)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtCheckBoxFactory::createEditor(QtBoolPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QtBoolEdit *editor = d_ptr->createEditor(property, parent);
+ editor->setChecked(manager->value(property));
+
+ connect(editor, SIGNAL(toggled(bool)), this, SLOT(slotSetValue(bool)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtCheckBoxFactory::disconnectPropertyManager(QtBoolPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, bool)),
+ this, SLOT(slotPropertyChanged(QtProperty *, bool)));
+}
+
+// QtDoubleSpinBoxFactory
+
+class QtDoubleSpinBoxFactoryPrivate : public EditorFactoryPrivate<QDoubleSpinBox>
+{
+ QtDoubleSpinBoxFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtDoubleSpinBoxFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, double value);
+ void slotRangeChanged(QtProperty *property, double min, double max);
+ void slotSingleStepChanged(QtProperty *property, double step);
+ void slotDecimalsChanged(QtProperty *property, int prec);
+ void slotSetValue(double value);
+};
+
+void QtDoubleSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, double value)
+{
+ QList<QDoubleSpinBox *> editors = m_createdEditors[property];
+ QListIterator<QDoubleSpinBox *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QDoubleSpinBox *editor = itEditor.next();
+ if (editor->value() != value) {
+ editor->blockSignals(true);
+ editor->setValue(value);
+ editor->blockSignals(false);
+ }
+ }
+}
+
+void QtDoubleSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property,
+ double min, double max)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtDoublePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QList<QDoubleSpinBox *> editors = m_createdEditors[property];
+ QListIterator<QDoubleSpinBox *> itEditor(editors);
+ while (itEditor.hasNext()) {
+ QDoubleSpinBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setRange(min, max);
+ editor->setValue(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtDoubleSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, double step)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtDoublePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QList<QDoubleSpinBox *> editors = m_createdEditors[property];
+ QListIterator<QDoubleSpinBox *> itEditor(editors);
+ while (itEditor.hasNext()) {
+ QDoubleSpinBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setSingleStep(step);
+ editor->blockSignals(false);
+ }
+}
+
+void QtDoubleSpinBoxFactoryPrivate::slotDecimalsChanged(QtProperty *property, int prec)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtDoublePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QList<QDoubleSpinBox *> editors = m_createdEditors[property];
+ QListIterator<QDoubleSpinBox *> itEditor(editors);
+ while (itEditor.hasNext()) {
+ QDoubleSpinBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setDecimals(prec);
+ editor->setValue(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtDoubleSpinBoxFactoryPrivate::slotSetValue(double value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QDoubleSpinBox *, QtProperty *>::ConstIterator itcend = m_editorToProperty.constEnd();
+ for (QMap<QDoubleSpinBox *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != itcend; ++itEditor) {
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtDoublePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+ }
+}
+
+/*! \class QtDoubleSpinBoxFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtDoubleSpinBoxFactory class provides QDoubleSpinBox
+ widgets for properties created by QtDoublePropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtDoublePropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtDoubleSpinBoxFactory::QtDoubleSpinBoxFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtDoublePropertyManager>(parent)
+{
+ d_ptr = new QtDoubleSpinBoxFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtDoubleSpinBoxFactory::~QtDoubleSpinBoxFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtDoubleSpinBoxFactory::connectPropertyManager(QtDoublePropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotPropertyChanged(QtProperty *, double)));
+ connect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)),
+ this, SLOT(slotRangeChanged(QtProperty *, double, double)));
+ connect(manager, SIGNAL(singleStepChanged(QtProperty *, double)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, double)));
+ connect(manager, SIGNAL(decimalsChanged(QtProperty *, int)),
+ this, SLOT(slotDecimalsChanged(QtProperty *, int)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtDoubleSpinBoxFactory::createEditor(QtDoublePropertyManager *manager,
+ QtProperty *property, QWidget *parent)
+{
+ QDoubleSpinBox *editor = d_ptr->createEditor(property, parent);
+ editor->setSingleStep(manager->singleStep(property));
+ editor->setDecimals(manager->decimals(property));
+ editor->setRange(manager->minimum(property), manager->maximum(property));
+ editor->setValue(manager->value(property));
+ editor->setKeyboardTracking(false);
+
+ connect(editor, SIGNAL(valueChanged(double)), this, SLOT(slotSetValue(double)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtDoubleSpinBoxFactory::disconnectPropertyManager(QtDoublePropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotPropertyChanged(QtProperty *, double)));
+ disconnect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)),
+ this, SLOT(slotRangeChanged(QtProperty *, double, double)));
+ disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, double)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, double)));
+ disconnect(manager, SIGNAL(decimalsChanged(QtProperty *, int)),
+ this, SLOT(slotDecimalsChanged(QtProperty *, int)));
+}
+
+// QtLineEditFactory
+
+class QtLineEditFactoryPrivate : public EditorFactoryPrivate<QLineEdit>
+{
+ QtLineEditFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtLineEditFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QString &value);
+ void slotRegExpChanged(QtProperty *property, const QRegExp &regExp);
+ void slotSetValue(const QString &value);
+};
+
+void QtLineEditFactoryPrivate::slotPropertyChanged(QtProperty *property,
+ const QString &value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QListIterator<QLineEdit *> itEditor( m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QLineEdit *editor = itEditor.next();
+ if (editor->text() != value)
+ editor->setText(value);
+ }
+}
+
+void QtLineEditFactoryPrivate::slotRegExpChanged(QtProperty *property,
+ const QRegExp &regExp)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtStringPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QListIterator<QLineEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QLineEdit *editor = itEditor.next();
+ editor->blockSignals(true);
+ const QValidator *oldValidator = editor->validator();
+ QValidator *newValidator = 0;
+ if (regExp.isValid()) {
+ newValidator = new QRegExpValidator(regExp, editor);
+ }
+ editor->setValidator(newValidator);
+ if (oldValidator)
+ delete oldValidator;
+ editor->blockSignals(false);
+ }
+}
+
+void QtLineEditFactoryPrivate::slotSetValue(const QString &value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QLineEdit *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QLineEdit *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtStringPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtLineEditFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtLineEditFactory class provides QLineEdit widgets for
+ properties created by QtStringPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtStringPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtLineEditFactory::QtLineEditFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtStringPropertyManager>(parent)
+{
+ d_ptr = new QtLineEditFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtLineEditFactory::~QtLineEditFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtLineEditFactory::connectPropertyManager(QtStringPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QString &)));
+ connect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)),
+ this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtLineEditFactory::createEditor(QtStringPropertyManager *manager,
+ QtProperty *property, QWidget *parent)
+{
+
+ QLineEdit *editor = d_ptr->createEditor(property, parent);
+ QRegExp regExp = manager->regExp(property);
+ if (regExp.isValid()) {
+ QValidator *validator = new QRegExpValidator(regExp, editor);
+ editor->setValidator(validator);
+ }
+ editor->setText(manager->value(property));
+
+ connect(editor, SIGNAL(textEdited(const QString &)),
+ this, SLOT(slotSetValue(const QString &)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtLineEditFactory::disconnectPropertyManager(QtStringPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QString &)));
+ disconnect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)),
+ this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &)));
+}
+
+// QtDateEditFactory
+
+class QtDateEditFactoryPrivate : public EditorFactoryPrivate<QDateEdit>
+{
+ QtDateEditFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtDateEditFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QDate &value);
+ void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max);
+ void slotSetValue(const QDate &value);
+};
+
+void QtDateEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QDate &value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+ QListIterator<QDateEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QDateEdit *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setDate(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtDateEditFactoryPrivate::slotRangeChanged(QtProperty *property,
+ const QDate &min, const QDate &max)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtDatePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QListIterator<QDateEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QDateEdit *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setDateRange(min, max);
+ editor->setDate(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtDateEditFactoryPrivate::slotSetValue(const QDate &value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QDateEdit *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QDateEdit *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtDatePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtDateEditFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtDateEditFactory class provides QDateEdit widgets for
+ properties created by QtDatePropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtDatePropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtDateEditFactory::QtDateEditFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtDatePropertyManager>(parent)
+{
+ d_ptr = new QtDateEditFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtDateEditFactory::~QtDateEditFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtDateEditFactory::connectPropertyManager(QtDatePropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QDate &)));
+ connect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)),
+ this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtDateEditFactory::createEditor(QtDatePropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QDateEdit *editor = d_ptr->createEditor(property, parent);
+ editor->setCalendarPopup(true);
+ editor->setDateRange(manager->minimum(property), manager->maximum(property));
+ editor->setDate(manager->value(property));
+
+ connect(editor, SIGNAL(dateChanged(const QDate &)),
+ this, SLOT(slotSetValue(const QDate &)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtDateEditFactory::disconnectPropertyManager(QtDatePropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QDate &)));
+ disconnect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)),
+ this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &)));
+}
+
+// QtTimeEditFactory
+
+class QtTimeEditFactoryPrivate : public EditorFactoryPrivate<QTimeEdit>
+{
+ QtTimeEditFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtTimeEditFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QTime &value);
+ void slotSetValue(const QTime &value);
+};
+
+void QtTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QTime &value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+ QListIterator<QTimeEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QTimeEdit *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setTime(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtTimeEditFactoryPrivate::slotSetValue(const QTime &value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QTimeEdit *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QTimeEdit *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtTimePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtTimeEditFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtTimeEditFactory class provides QTimeEdit widgets for
+ properties created by QtTimePropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtTimePropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtTimeEditFactory::QtTimeEditFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtTimePropertyManager>(parent)
+{
+ d_ptr = new QtTimeEditFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtTimeEditFactory::~QtTimeEditFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtTimeEditFactory::connectPropertyManager(QtTimePropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QTime &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtTimeEditFactory::createEditor(QtTimePropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QTimeEdit *editor = d_ptr->createEditor(property, parent);
+ editor->setTime(manager->value(property));
+
+ connect(editor, SIGNAL(timeChanged(const QTime &)),
+ this, SLOT(slotSetValue(const QTime &)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtTimeEditFactory::disconnectPropertyManager(QtTimePropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QTime &)));
+}
+
+// QtDateTimeEditFactory
+
+class QtDateTimeEditFactoryPrivate : public EditorFactoryPrivate<QDateTimeEdit>
+{
+ QtDateTimeEditFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtDateTimeEditFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QDateTime &value);
+ void slotSetValue(const QDateTime &value);
+
+};
+
+void QtDateTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property,
+ const QDateTime &value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QListIterator<QDateTimeEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QDateTimeEdit *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setDateTime(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtDateTimeEditFactoryPrivate::slotSetValue(const QDateTime &value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QDateTimeEdit *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QDateTimeEdit *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtDateTimePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtDateTimeEditFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtDateTimeEditFactory class provides QDateTimeEdit
+ widgets for properties created by QtDateTimePropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtDateTimePropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtDateTimeEditFactory::QtDateTimeEditFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtDateTimePropertyManager>(parent)
+{
+ d_ptr = new QtDateTimeEditFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtDateTimeEditFactory::~QtDateTimeEditFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtDateTimeEditFactory::connectPropertyManager(QtDateTimePropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtDateTimeEditFactory::createEditor(QtDateTimePropertyManager *manager,
+ QtProperty *property, QWidget *parent)
+{
+ QDateTimeEdit *editor = d_ptr->createEditor(property, parent);
+ editor->setDateTime(manager->value(property));
+
+ connect(editor, SIGNAL(dateTimeChanged(const QDateTime &)),
+ this, SLOT(slotSetValue(const QDateTime &)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtDateTimeEditFactory::disconnectPropertyManager(QtDateTimePropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &)));
+}
+
+// QtKeySequenceEditorFactory
+
+class QtKeySequenceEditorFactoryPrivate : public EditorFactoryPrivate<QtKeySequenceEdit>
+{
+ QtKeySequenceEditorFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtKeySequenceEditorFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QKeySequence &value);
+ void slotSetValue(const QKeySequence &value);
+};
+
+void QtKeySequenceEditorFactoryPrivate::slotPropertyChanged(QtProperty *property,
+ const QKeySequence &value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QListIterator<QtKeySequenceEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QtKeySequenceEdit *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setKeySequence(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtKeySequenceEditorFactoryPrivate::slotSetValue(const QKeySequence &value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QtKeySequenceEdit *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QtKeySequenceEdit *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtKeySequencePropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtKeySequenceEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtKeySequenceEditorFactory class provides editor
+ widgets for properties created by QtKeySequencePropertyManager objects.
+
+ \sa QtAbstractEditorFactory
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtKeySequenceEditorFactory::QtKeySequenceEditorFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtKeySequencePropertyManager>(parent)
+{
+ d_ptr = new QtKeySequenceEditorFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtKeySequenceEditorFactory::~QtKeySequenceEditorFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtKeySequenceEditorFactory::connectPropertyManager(QtKeySequencePropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtKeySequenceEditorFactory::createEditor(QtKeySequencePropertyManager *manager,
+ QtProperty *property, QWidget *parent)
+{
+ QtKeySequenceEdit *editor = d_ptr->createEditor(property, parent);
+ editor->setKeySequence(manager->value(property));
+
+ connect(editor, SIGNAL(keySequenceChanged(const QKeySequence &)),
+ this, SLOT(slotSetValue(const QKeySequence &)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtKeySequenceEditorFactory::disconnectPropertyManager(QtKeySequencePropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &)));
+}
+
+// QtCharEdit
+
+class QtCharEdit : public QWidget
+{
+ Q_OBJECT
+public:
+ QtCharEdit(QWidget *parent = 0);
+
+ QChar value() const;
+ bool eventFilter(QObject *o, QEvent *e);
+public Q_SLOTS:
+ void setValue(const QChar &value);
+Q_SIGNALS:
+ void valueChanged(const QChar &value);
+protected:
+ void focusInEvent(QFocusEvent *e);
+ void focusOutEvent(QFocusEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void keyReleaseEvent(QKeyEvent *e);
+ bool event(QEvent *e);
+private slots:
+ void slotClearChar();
+private:
+ void handleKeyEvent(QKeyEvent *e);
+
+ QChar m_value;
+ QLineEdit *m_lineEdit;
+};
+
+QtCharEdit::QtCharEdit(QWidget *parent)
+ : QWidget(parent), m_lineEdit(new QLineEdit(this))
+{
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ layout->addWidget(m_lineEdit);
+ layout->setMargin(0);
+ m_lineEdit->installEventFilter(this);
+ m_lineEdit->setReadOnly(true);
+ m_lineEdit->setFocusProxy(this);
+ setFocusPolicy(m_lineEdit->focusPolicy());
+ setAttribute(Qt::WA_InputMethodEnabled);
+}
+
+bool QtCharEdit::eventFilter(QObject *o, QEvent *e)
+{
+ if (o == m_lineEdit && e->type() == QEvent::ContextMenu) {
+ QContextMenuEvent *c = static_cast<QContextMenuEvent *>(e);
+ QMenu *menu = m_lineEdit->createStandardContextMenu();
+ QList<QAction *> actions = menu->actions();
+ QListIterator<QAction *> itAction(actions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ action->setShortcut(QKeySequence());
+ QString actionString = action->text();
+ const int pos = actionString.lastIndexOf(QLatin1Char('\t'));
+ if (pos > 0)
+ actionString = actionString.remove(pos, actionString.length() - pos);
+ action->setText(actionString);
+ }
+ QAction *actionBefore = 0;
+ if (actions.count() > 0)
+ actionBefore = actions[0];
+ QAction *clearAction = new QAction(tr("Clear Char"), menu);
+ menu->insertAction(actionBefore, clearAction);
+ menu->insertSeparator(actionBefore);
+ clearAction->setEnabled(!m_value.isNull());
+ connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearChar()));
+ menu->exec(c->globalPos());
+ delete menu;
+ e->accept();
+ return true;
+ }
+
+ return QWidget::eventFilter(o, e);
+}
+
+void QtCharEdit::slotClearChar()
+{
+ if (m_value.isNull())
+ return;
+ setValue(QChar());
+ emit valueChanged(m_value);
+}
+
+void QtCharEdit::handleKeyEvent(QKeyEvent *e)
+{
+ const int key = e->key();
+ switch (key) {
+ case Qt::Key_Control:
+ case Qt::Key_Shift:
+ case Qt::Key_Meta:
+ case Qt::Key_Alt:
+ case Qt::Key_Super_L:
+ case Qt::Key_Return:
+ return;
+ default:
+ break;
+ }
+
+ const QString text = e->text();
+ if (text.count() != 1)
+ return;
+
+ const QChar c = text.at(0);
+ if (!c.isPrint())
+ return;
+
+ if (m_value == c)
+ return;
+
+ m_value = c;
+ const QString str = m_value.isNull() ? QString() : QString(m_value);
+ m_lineEdit->setText(str);
+ e->accept();
+ emit valueChanged(m_value);
+}
+
+void QtCharEdit::setValue(const QChar &value)
+{
+ if (value == m_value)
+ return;
+
+ m_value = value;
+ QString str = value.isNull() ? QString() : QString(value);
+ m_lineEdit->setText(str);
+}
+
+QChar QtCharEdit::value() const
+{
+ return m_value;
+}
+
+void QtCharEdit::focusInEvent(QFocusEvent *e)
+{
+ m_lineEdit->event(e);
+ m_lineEdit->selectAll();
+ QWidget::focusInEvent(e);
+}
+
+void QtCharEdit::focusOutEvent(QFocusEvent *e)
+{
+ m_lineEdit->event(e);
+ QWidget::focusOutEvent(e);
+}
+
+void QtCharEdit::keyPressEvent(QKeyEvent *e)
+{
+ handleKeyEvent(e);
+ e->accept();
+}
+
+void QtCharEdit::keyReleaseEvent(QKeyEvent *e)
+{
+ m_lineEdit->event(e);
+}
+
+bool QtCharEdit::event(QEvent *e)
+{
+ switch(e->type()) {
+ case QEvent::Shortcut:
+ case QEvent::ShortcutOverride:
+ case QEvent::KeyRelease:
+ e->accept();
+ return true;
+ default:
+ break;
+ }
+ return QWidget::event(e);
+}
+
+// QtCharEditorFactory
+
+class QtCharEditorFactoryPrivate : public EditorFactoryPrivate<QtCharEdit>
+{
+ QtCharEditorFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtCharEditorFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QChar &value);
+ void slotSetValue(const QChar &value);
+
+};
+
+void QtCharEditorFactoryPrivate::slotPropertyChanged(QtProperty *property,
+ const QChar &value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QListIterator<QtCharEdit *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QtCharEdit *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setValue(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtCharEditorFactoryPrivate::slotSetValue(const QChar &value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QtCharEdit *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QtCharEdit *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtCharPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtCharEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtCharEditorFactory class provides editor
+ widgets for properties created by QtCharPropertyManager objects.
+
+ \sa QtAbstractEditorFactory
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtCharEditorFactory::QtCharEditorFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtCharPropertyManager>(parent)
+{
+ d_ptr = new QtCharEditorFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtCharEditorFactory::~QtCharEditorFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtCharEditorFactory::connectPropertyManager(QtCharPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QChar &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtCharEditorFactory::createEditor(QtCharPropertyManager *manager,
+ QtProperty *property, QWidget *parent)
+{
+ QtCharEdit *editor = d_ptr->createEditor(property, parent);
+ editor->setValue(manager->value(property));
+
+ connect(editor, SIGNAL(valueChanged(const QChar &)),
+ this, SLOT(slotSetValue(const QChar &)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtCharEditorFactory::disconnectPropertyManager(QtCharPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QChar &)));
+}
+
+// QtEnumEditorFactory
+
+class QtEnumEditorFactoryPrivate : public EditorFactoryPrivate<QComboBox>
+{
+ QtEnumEditorFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtEnumEditorFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, int value);
+ void slotEnumNamesChanged(QtProperty *property, const QStringList &);
+ void slotEnumIconsChanged(QtProperty *property, const QMap<int, QIcon> &);
+ void slotSetValue(int value);
+};
+
+void QtEnumEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, int value)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QListIterator<QComboBox *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QComboBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->setCurrentIndex(value);
+ editor->blockSignals(false);
+ }
+}
+
+void QtEnumEditorFactoryPrivate::slotEnumNamesChanged(QtProperty *property,
+ const QStringList &enumNames)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtEnumPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ QMap<int, QIcon> enumIcons = manager->enumIcons(property);
+
+ QListIterator<QComboBox *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QComboBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ editor->clear();
+ editor->addItems(enumNames);
+ const int nameCount = enumNames.count();
+ for (int i = 0; i < nameCount; i++)
+ editor->setItemIcon(i, enumIcons.value(i));
+ editor->setCurrentIndex(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtEnumEditorFactoryPrivate::slotEnumIconsChanged(QtProperty *property,
+ const QMap<int, QIcon> &enumIcons)
+{
+ if (!m_createdEditors.contains(property))
+ return;
+
+ QtEnumPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+
+ const QStringList enumNames = manager->enumNames(property);
+ QListIterator<QComboBox *> itEditor(m_createdEditors[property]);
+ while (itEditor.hasNext()) {
+ QComboBox *editor = itEditor.next();
+ editor->blockSignals(true);
+ const int nameCount = enumNames.count();
+ for (int i = 0; i < nameCount; i++)
+ editor->setItemIcon(i, enumIcons.value(i));
+ editor->setCurrentIndex(manager->value(property));
+ editor->blockSignals(false);
+ }
+}
+
+void QtEnumEditorFactoryPrivate::slotSetValue(int value)
+{
+ QObject *object = q_ptr->sender();
+ const QMap<QComboBox *, QtProperty *>::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (QMap<QComboBox *, QtProperty *>::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtEnumPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtEnumEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtEnumEditorFactory class provides QComboBox widgets for
+ properties created by QtEnumPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtEnumPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtEnumEditorFactory::QtEnumEditorFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtEnumPropertyManager>(parent)
+{
+ d_ptr = new QtEnumEditorFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtEnumEditorFactory::~QtEnumEditorFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtEnumEditorFactory::connectPropertyManager(QtEnumPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ connect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)),
+ this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtEnumEditorFactory::createEditor(QtEnumPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QComboBox *editor = d_ptr->createEditor(property, parent);
+ editor->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
+ editor->view()->setTextElideMode(Qt::ElideRight);
+ QStringList enumNames = manager->enumNames(property);
+ editor->addItems(enumNames);
+ QMap<int, QIcon> enumIcons = manager->enumIcons(property);
+ const int enumNamesCount = enumNames.count();
+ for (int i = 0; i < enumNamesCount; i++)
+ editor->setItemIcon(i, enumIcons.value(i));
+ editor->setCurrentIndex(manager->value(property));
+
+ connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int)));
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtEnumEditorFactory::disconnectPropertyManager(QtEnumPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotPropertyChanged(QtProperty *, int)));
+ disconnect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)),
+ this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &)));
+}
+
+// QtCursorEditorFactory
+
+Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase)
+
+class QtCursorEditorFactoryPrivate
+{
+ QtCursorEditorFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtCursorEditorFactory)
+public:
+ QtCursorEditorFactoryPrivate();
+
+ void slotPropertyChanged(QtProperty *property, const QCursor &cursor);
+ void slotEnumChanged(QtProperty *property, int value);
+ void slotEditorDestroyed(QObject *object);
+
+ QtEnumEditorFactory *m_enumEditorFactory;
+ QtEnumPropertyManager *m_enumPropertyManager;
+
+ QMap<QtProperty *, QtProperty *> m_propertyToEnum;
+ QMap<QtProperty *, QtProperty *> m_enumToProperty;
+ QMap<QtProperty *, QList<QWidget *> > m_enumToEditors;
+ QMap<QWidget *, QtProperty *> m_editorToEnum;
+ bool m_updatingEnum;
+};
+
+QtCursorEditorFactoryPrivate::QtCursorEditorFactoryPrivate()
+ : m_updatingEnum(false)
+{
+
+}
+
+void QtCursorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QCursor &cursor)
+{
+ // update enum property
+ QtProperty *enumProp = m_propertyToEnum.value(property);
+ if (!enumProp)
+ return;
+
+ m_updatingEnum = true;
+ m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(cursor));
+ m_updatingEnum = false;
+}
+
+void QtCursorEditorFactoryPrivate::slotEnumChanged(QtProperty *property, int value)
+{
+ if (m_updatingEnum)
+ return;
+ // update cursor property
+ QtProperty *prop = m_enumToProperty.value(property);
+ if (!prop)
+ return;
+ QtCursorPropertyManager *cursorManager = q_ptr->propertyManager(prop);
+ if (!cursorManager)
+ return;
+#ifndef QT_NO_CURSOR
+ cursorManager->setValue(prop, QCursor(cursorDatabase()->valueToCursor(value)));
+#endif
+}
+
+void QtCursorEditorFactoryPrivate::slotEditorDestroyed(QObject *object)
+{
+ // remove from m_editorToEnum map;
+ // remove from m_enumToEditors map;
+ // if m_enumToEditors doesn't contains more editors delete enum property;
+ const QMap<QWidget *, QtProperty *>::ConstIterator ecend = m_editorToEnum.constEnd();
+ for (QMap<QWidget *, QtProperty *>::ConstIterator itEditor = m_editorToEnum.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QWidget *editor = itEditor.key();
+ QtProperty *enumProp = itEditor.value();
+ m_editorToEnum.remove(editor);
+ m_enumToEditors[enumProp].removeAll(editor);
+ if (m_enumToEditors[enumProp].isEmpty()) {
+ m_enumToEditors.remove(enumProp);
+ QtProperty *property = m_enumToProperty.value(enumProp);
+ m_enumToProperty.remove(enumProp);
+ m_propertyToEnum.remove(property);
+ delete enumProp;
+ }
+ return;
+ }
+}
+
+/*!
+ \class QtCursorEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtCursorEditorFactory class provides QComboBox widgets for
+ properties created by QtCursorPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtCursorPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtCursorEditorFactory::QtCursorEditorFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtCursorPropertyManager>(parent)
+{
+ d_ptr = new QtCursorEditorFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_enumEditorFactory = new QtEnumEditorFactory(this);
+ d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this);
+ connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotEnumChanged(QtProperty *, int)));
+ d_ptr->m_enumEditorFactory->addPropertyManager(d_ptr->m_enumPropertyManager);
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtCursorEditorFactory::~QtCursorEditorFactory()
+{
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtCursorEditorFactory::connectPropertyManager(QtCursorPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtCursorEditorFactory::createEditor(QtCursorPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ QtProperty *enumProp = 0;
+ if (d_ptr->m_propertyToEnum.contains(property)) {
+ enumProp = d_ptr->m_propertyToEnum[property];
+ } else {
+ enumProp = d_ptr->m_enumPropertyManager->addProperty(property->propertyName());
+ d_ptr->m_enumPropertyManager->setEnumNames(enumProp, cursorDatabase()->cursorShapeNames());
+ d_ptr->m_enumPropertyManager->setEnumIcons(enumProp, cursorDatabase()->cursorShapeIcons());
+#ifndef QT_NO_CURSOR
+ d_ptr->m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(manager->value(property)));
+#endif
+ d_ptr->m_propertyToEnum[property] = enumProp;
+ d_ptr->m_enumToProperty[enumProp] = property;
+ }
+ QtAbstractEditorFactoryBase *af = d_ptr->m_enumEditorFactory;
+ QWidget *editor = af->createEditor(enumProp, parent);
+ d_ptr->m_enumToEditors[enumProp].append(editor);
+ d_ptr->m_editorToEnum[editor] = enumProp;
+ connect(editor, SIGNAL(destroyed(QObject *)),
+ this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtCursorEditorFactory::disconnectPropertyManager(QtCursorPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)),
+ this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &)));
+}
+
+// QtColorEditWidget
+
+class QtColorEditWidget : public QWidget {
+ Q_OBJECT
+
+public:
+ QtColorEditWidget(QWidget *parent);
+
+ bool eventFilter(QObject *obj, QEvent *ev);
+
+public Q_SLOTS:
+ void setValue(const QColor &value);
+
+private Q_SLOTS:
+ void buttonClicked();
+
+Q_SIGNALS:
+ void valueChanged(const QColor &value);
+
+private:
+ QColor m_color;
+ QLabel *m_pixmapLabel;
+ QLabel *m_label;
+ QToolButton *m_button;
+};
+
+QtColorEditWidget::QtColorEditWidget(QWidget *parent) :
+ QWidget(parent),
+ m_pixmapLabel(new QLabel),
+ m_label(new QLabel),
+ m_button(new QToolButton)
+{
+ QHBoxLayout *lt = new QHBoxLayout(this);
+ setupTreeViewEditorMargin(lt);
+ lt->setSpacing(0);
+ lt->addWidget(m_pixmapLabel);
+ lt->addWidget(m_label);
+ lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
+
+ m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
+ m_button->setFixedWidth(20);
+ setFocusProxy(m_button);
+ setFocusPolicy(m_button->focusPolicy());
+ m_button->setText(tr("..."));
+ m_button->installEventFilter(this);
+ connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
+ lt->addWidget(m_button);
+ m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(m_color)));
+ m_label->setText(QtPropertyBrowserUtils::colorValueText(m_color));
+}
+
+void QtColorEditWidget::setValue(const QColor &c)
+{
+ if (m_color != c) {
+ m_color = c;
+ m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(c)));
+ m_label->setText(QtPropertyBrowserUtils::colorValueText(c));
+ }
+}
+
+void QtColorEditWidget::buttonClicked()
+{
+ bool ok = false;
+ QRgb oldRgba = m_color.rgba();
+ QRgb newRgba = QColorDialog::getRgba(oldRgba, &ok, this);
+ if (ok && newRgba != oldRgba) {
+ setValue(QColor::fromRgba(newRgba));
+ emit valueChanged(m_color);
+ }
+}
+
+bool QtColorEditWidget::eventFilter(QObject *obj, QEvent *ev)
+{
+ if (obj == m_button) {
+ switch (ev->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate
+ switch (static_cast<const QKeyEvent*>(ev)->key()) {
+ case Qt::Key_Escape:
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ ev->ignore();
+ return true;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QWidget::eventFilter(obj, ev);
+}
+
+// QtColorEditorFactoryPrivate
+
+class QtColorEditorFactoryPrivate : public EditorFactoryPrivate<QtColorEditWidget>
+{
+ QtColorEditorFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtColorEditorFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QColor &value);
+ void slotSetValue(const QColor &value);
+};
+
+void QtColorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property,
+ const QColor &value)
+{
+ const PropertyToEditorListMap::iterator it = m_createdEditors.find(property);
+ if (it == m_createdEditors.end())
+ return;
+ QListIterator<QtColorEditWidget *> itEditor(it.value());
+
+ while (itEditor.hasNext())
+ itEditor.next()->setValue(value);
+}
+
+void QtColorEditorFactoryPrivate::slotSetValue(const QColor &value)
+{
+ QObject *object = q_ptr->sender();
+ const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtColorPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtColorEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtColorEditorFactory class provides color editing for
+ properties created by QtColorPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtColorPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtColorEditorFactory::QtColorEditorFactory(QObject *parent) :
+ QtAbstractEditorFactory<QtColorPropertyManager>(parent),
+ d_ptr(new QtColorEditorFactoryPrivate())
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtColorEditorFactory::~QtColorEditorFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtColorEditorFactory::connectPropertyManager(QtColorPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty*,QColor)),
+ this, SLOT(slotPropertyChanged(QtProperty*,QColor)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtColorEditorFactory::createEditor(QtColorPropertyManager *manager,
+ QtProperty *property, QWidget *parent)
+{
+ QtColorEditWidget *editor = d_ptr->createEditor(property, parent);
+ editor->setValue(manager->value(property));
+ connect(editor, SIGNAL(valueChanged(QColor)), this, SLOT(slotSetValue(QColor)));
+ connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtColorEditorFactory::disconnectPropertyManager(QtColorPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty*,QColor)), this, SLOT(slotPropertyChanged(QtProperty*,QColor)));
+}
+
+// QtFontEditWidget
+
+class QtFontEditWidget : public QWidget {
+ Q_OBJECT
+
+public:
+ QtFontEditWidget(QWidget *parent);
+
+ bool eventFilter(QObject *obj, QEvent *ev);
+
+public Q_SLOTS:
+ void setValue(const QFont &value);
+
+private Q_SLOTS:
+ void buttonClicked();
+
+Q_SIGNALS:
+ void valueChanged(const QFont &value);
+
+private:
+ QFont m_font;
+ QLabel *m_pixmapLabel;
+ QLabel *m_label;
+ QToolButton *m_button;
+};
+
+QtFontEditWidget::QtFontEditWidget(QWidget *parent) :
+ QWidget(parent),
+ m_pixmapLabel(new QLabel),
+ m_label(new QLabel),
+ m_button(new QToolButton)
+{
+ QHBoxLayout *lt = new QHBoxLayout(this);
+ setupTreeViewEditorMargin(lt);
+ lt->setSpacing(0);
+ lt->addWidget(m_pixmapLabel);
+ lt->addWidget(m_label);
+ lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
+
+ m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
+ m_button->setFixedWidth(20);
+ setFocusProxy(m_button);
+ setFocusPolicy(m_button->focusPolicy());
+ m_button->setText(tr("..."));
+ m_button->installEventFilter(this);
+ connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
+ lt->addWidget(m_button);
+ m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(m_font));
+ m_label->setText(QtPropertyBrowserUtils::fontValueText(m_font));
+}
+
+void QtFontEditWidget::setValue(const QFont &f)
+{
+ if (m_font != f) {
+ m_font = f;
+ m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(f));
+ m_label->setText(QtPropertyBrowserUtils::fontValueText(f));
+ }
+}
+
+void QtFontEditWidget::buttonClicked()
+{
+ bool ok = false;
+ QFont newFont = QFontDialog::getFont(&ok, m_font, this, tr("Select Font"));
+ if (ok && newFont != m_font) {
+ QFont f = m_font;
+ // prevent mask for unchanged attributes, don't change other attributes (like kerning, etc...)
+ if (m_font.family() != newFont.family())
+ f.setFamily(newFont.family());
+ if (m_font.pointSize() != newFont.pointSize())
+ f.setPointSize(newFont.pointSize());
+ if (m_font.bold() != newFont.bold())
+ f.setBold(newFont.bold());
+ if (m_font.italic() != newFont.italic())
+ f.setItalic(newFont.italic());
+ if (m_font.underline() != newFont.underline())
+ f.setUnderline(newFont.underline());
+ if (m_font.strikeOut() != newFont.strikeOut())
+ f.setStrikeOut(newFont.strikeOut());
+ setValue(f);
+ emit valueChanged(m_font);
+ }
+}
+
+bool QtFontEditWidget::eventFilter(QObject *obj, QEvent *ev)
+{
+ if (obj == m_button) {
+ switch (ev->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate
+ switch (static_cast<const QKeyEvent*>(ev)->key()) {
+ case Qt::Key_Escape:
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ ev->ignore();
+ return true;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QWidget::eventFilter(obj, ev);
+}
+
+// QtFontEditorFactoryPrivate
+
+class QtFontEditorFactoryPrivate : public EditorFactoryPrivate<QtFontEditWidget>
+{
+ QtFontEditorFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtFontEditorFactory)
+public:
+
+ void slotPropertyChanged(QtProperty *property, const QFont &value);
+ void slotSetValue(const QFont &value);
+};
+
+void QtFontEditorFactoryPrivate::slotPropertyChanged(QtProperty *property,
+ const QFont &value)
+{
+ const PropertyToEditorListMap::iterator it = m_createdEditors.find(property);
+ if (it == m_createdEditors.end())
+ return;
+ QListIterator<QtFontEditWidget *> itEditor(it.value());
+
+ while (itEditor.hasNext())
+ itEditor.next()->setValue(value);
+}
+
+void QtFontEditorFactoryPrivate::slotSetValue(const QFont &value)
+{
+ QObject *object = q_ptr->sender();
+ const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd();
+ for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor)
+ if (itEditor.key() == object) {
+ QtProperty *property = itEditor.value();
+ QtFontPropertyManager *manager = q_ptr->propertyManager(property);
+ if (!manager)
+ return;
+ manager->setValue(property, value);
+ return;
+ }
+}
+
+/*!
+ \class QtFontEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtFontEditorFactory class provides font editing for
+ properties created by QtFontPropertyManager objects.
+
+ \sa QtAbstractEditorFactory, QtFontPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtFontEditorFactory::QtFontEditorFactory(QObject *parent) :
+ QtAbstractEditorFactory<QtFontPropertyManager>(parent),
+ d_ptr(new QtFontEditorFactoryPrivate())
+{
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtFontEditorFactory::~QtFontEditorFactory()
+{
+ qDeleteAll(d_ptr->m_editorToProperty.keys());
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtFontEditorFactory::connectPropertyManager(QtFontPropertyManager *manager)
+{
+ connect(manager, SIGNAL(valueChanged(QtProperty*,QFont)),
+ this, SLOT(slotPropertyChanged(QtProperty*,QFont)));
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtFontEditorFactory::createEditor(QtFontPropertyManager *manager,
+ QtProperty *property, QWidget *parent)
+{
+ QtFontEditWidget *editor = d_ptr->createEditor(property, parent);
+ editor->setValue(manager->value(property));
+ connect(editor, SIGNAL(valueChanged(QFont)), this, SLOT(slotSetValue(QFont)));
+ connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ return editor;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtFontEditorFactory::disconnectPropertyManager(QtFontPropertyManager *manager)
+{
+ disconnect(manager, SIGNAL(valueChanged(QtProperty*,QFont)), this, SLOT(slotPropertyChanged(QtProperty*,QFont)));
+}
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#include "moc_qteditorfactory.cpp"
+#include "qteditorfactory.moc"
diff --git a/tools/shared/qtpropertybrowser/qteditorfactory.h b/tools/shared/qtpropertybrowser/qteditorfactory.h
new file mode 100644
index 0000000000..044dd5eea3
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qteditorfactory.h
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEDITORFACTORY_H
+#define QTEDITORFACTORY_H
+
+#include "qtpropertymanager.h"
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtSpinBoxFactoryPrivate;
+
+class QtSpinBoxFactory : public QtAbstractEditorFactory<QtIntPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtSpinBoxFactory(QObject *parent = 0);
+ ~QtSpinBoxFactory();
+protected:
+ void connectPropertyManager(QtIntPropertyManager *manager);
+ QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtIntPropertyManager *manager);
+private:
+ QtSpinBoxFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtSpinBoxFactory)
+ Q_DISABLE_COPY(QtSpinBoxFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtSliderFactoryPrivate;
+
+class QtSliderFactory : public QtAbstractEditorFactory<QtIntPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtSliderFactory(QObject *parent = 0);
+ ~QtSliderFactory();
+protected:
+ void connectPropertyManager(QtIntPropertyManager *manager);
+ QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtIntPropertyManager *manager);
+private:
+ QtSliderFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtSliderFactory)
+ Q_DISABLE_COPY(QtSliderFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtScrollBarFactoryPrivate;
+
+class QtScrollBarFactory : public QtAbstractEditorFactory<QtIntPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtScrollBarFactory(QObject *parent = 0);
+ ~QtScrollBarFactory();
+protected:
+ void connectPropertyManager(QtIntPropertyManager *manager);
+ QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtIntPropertyManager *manager);
+private:
+ QtScrollBarFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtScrollBarFactory)
+ Q_DISABLE_COPY(QtScrollBarFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtCheckBoxFactoryPrivate;
+
+class QtCheckBoxFactory : public QtAbstractEditorFactory<QtBoolPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtCheckBoxFactory(QObject *parent = 0);
+ ~QtCheckBoxFactory();
+protected:
+ void connectPropertyManager(QtBoolPropertyManager *manager);
+ QWidget *createEditor(QtBoolPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtBoolPropertyManager *manager);
+private:
+ QtCheckBoxFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtCheckBoxFactory)
+ Q_DISABLE_COPY(QtCheckBoxFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, bool))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(bool))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtDoubleSpinBoxFactoryPrivate;
+
+class QtDoubleSpinBoxFactory : public QtAbstractEditorFactory<QtDoublePropertyManager>
+{
+ Q_OBJECT
+public:
+ QtDoubleSpinBoxFactory(QObject *parent = 0);
+ ~QtDoubleSpinBoxFactory();
+protected:
+ void connectPropertyManager(QtDoublePropertyManager *manager);
+ QWidget *createEditor(QtDoublePropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtDoublePropertyManager *manager);
+private:
+ QtDoubleSpinBoxFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtDoubleSpinBoxFactory)
+ Q_DISABLE_COPY(QtDoubleSpinBoxFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, double))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double))
+ Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double))
+ Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(double))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtLineEditFactoryPrivate;
+
+class QtLineEditFactory : public QtAbstractEditorFactory<QtStringPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtLineEditFactory(QObject *parent = 0);
+ ~QtLineEditFactory();
+protected:
+ void connectPropertyManager(QtStringPropertyManager *manager);
+ QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtStringPropertyManager *manager);
+private:
+ QtLineEditFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtLineEditFactory)
+ Q_DISABLE_COPY(QtLineEditFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QString &))
+ Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegExp &))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QString &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtDateEditFactoryPrivate;
+
+class QtDateEditFactory : public QtAbstractEditorFactory<QtDatePropertyManager>
+{
+ Q_OBJECT
+public:
+ QtDateEditFactory(QObject *parent = 0);
+ ~QtDateEditFactory();
+protected:
+ void connectPropertyManager(QtDatePropertyManager *manager);
+ QWidget *createEditor(QtDatePropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtDatePropertyManager *manager);
+private:
+ QtDateEditFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtDateEditFactory)
+ Q_DISABLE_COPY(QtDateEditFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDate &))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *,
+ const QDate &, const QDate &))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDate &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtTimeEditFactoryPrivate;
+
+class QtTimeEditFactory : public QtAbstractEditorFactory<QtTimePropertyManager>
+{
+ Q_OBJECT
+public:
+ QtTimeEditFactory(QObject *parent = 0);
+ ~QtTimeEditFactory();
+protected:
+ void connectPropertyManager(QtTimePropertyManager *manager);
+ QWidget *createEditor(QtTimePropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtTimePropertyManager *manager);
+private:
+ QtTimeEditFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtTimeEditFactory)
+ Q_DISABLE_COPY(QtTimeEditFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QTime &))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QTime &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtDateTimeEditFactoryPrivate;
+
+class QtDateTimeEditFactory : public QtAbstractEditorFactory<QtDateTimePropertyManager>
+{
+ Q_OBJECT
+public:
+ QtDateTimeEditFactory(QObject *parent = 0);
+ ~QtDateTimeEditFactory();
+protected:
+ void connectPropertyManager(QtDateTimePropertyManager *manager);
+ QWidget *createEditor(QtDateTimePropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtDateTimePropertyManager *manager);
+private:
+ QtDateTimeEditFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtDateTimeEditFactory)
+ Q_DISABLE_COPY(QtDateTimeEditFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDateTime &))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDateTime &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtKeySequenceEditorFactoryPrivate;
+
+class QtKeySequenceEditorFactory : public QtAbstractEditorFactory<QtKeySequencePropertyManager>
+{
+ Q_OBJECT
+public:
+ QtKeySequenceEditorFactory(QObject *parent = 0);
+ ~QtKeySequenceEditorFactory();
+protected:
+ void connectPropertyManager(QtKeySequencePropertyManager *manager);
+ QWidget *createEditor(QtKeySequencePropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtKeySequencePropertyManager *manager);
+private:
+ QtKeySequenceEditorFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtKeySequenceEditorFactory)
+ Q_DISABLE_COPY(QtKeySequenceEditorFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QKeySequence &))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QKeySequence &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtCharEditorFactoryPrivate;
+
+class QtCharEditorFactory : public QtAbstractEditorFactory<QtCharPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtCharEditorFactory(QObject *parent = 0);
+ ~QtCharEditorFactory();
+protected:
+ void connectPropertyManager(QtCharPropertyManager *manager);
+ QWidget *createEditor(QtCharPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtCharPropertyManager *manager);
+private:
+ QtCharEditorFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtCharEditorFactory)
+ Q_DISABLE_COPY(QtCharEditorFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QChar &))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QChar &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtEnumEditorFactoryPrivate;
+
+class QtEnumEditorFactory : public QtAbstractEditorFactory<QtEnumPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtEnumEditorFactory(QObject *parent = 0);
+ ~QtEnumEditorFactory();
+protected:
+ void connectPropertyManager(QtEnumPropertyManager *manager);
+ QWidget *createEditor(QtEnumPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtEnumPropertyManager *manager);
+private:
+ QtEnumEditorFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtEnumEditorFactory)
+ Q_DISABLE_COPY(QtEnumEditorFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *,
+ const QStringList &))
+ Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *,
+ const QMap<int, QIcon> &))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(int))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtCursorEditorFactoryPrivate;
+
+class QtCursorEditorFactory : public QtAbstractEditorFactory<QtCursorPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtCursorEditorFactory(QObject *parent = 0);
+ ~QtCursorEditorFactory();
+protected:
+ void connectPropertyManager(QtCursorPropertyManager *manager);
+ QWidget *createEditor(QtCursorPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtCursorPropertyManager *manager);
+private:
+ QtCursorEditorFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtCursorEditorFactory)
+ Q_DISABLE_COPY(QtCursorEditorFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QCursor &))
+ Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+};
+
+class QtColorEditorFactoryPrivate;
+
+class QtColorEditorFactory : public QtAbstractEditorFactory<QtColorPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtColorEditorFactory(QObject *parent = 0);
+ ~QtColorEditorFactory();
+protected:
+ void connectPropertyManager(QtColorPropertyManager *manager);
+ QWidget *createEditor(QtColorPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtColorPropertyManager *manager);
+private:
+ QtColorEditorFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtColorEditorFactory)
+ Q_DISABLE_COPY(QtColorEditorFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QColor &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QColor &))
+};
+
+class QtFontEditorFactoryPrivate;
+
+class QtFontEditorFactory : public QtAbstractEditorFactory<QtFontPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtFontEditorFactory(QObject *parent = 0);
+ ~QtFontEditorFactory();
+protected:
+ void connectPropertyManager(QtFontPropertyManager *manager);
+ QWidget *createEditor(QtFontPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtFontPropertyManager *manager);
+private:
+ QtFontEditorFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtFontEditorFactory)
+ Q_DISABLE_COPY(QtFontEditorFactory)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QFont &))
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *))
+ Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QFont &))
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#endif
diff --git a/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.cpp b/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.cpp
new file mode 100644
index 0000000000..d7c8f0b596
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtgroupboxpropertybrowser.h"
+#include <QtCore/QSet>
+#include <QtGui/QGridLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QGroupBox>
+#include <QtCore/QTimer>
+#include <QtCore/QMap>
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtGroupBoxPropertyBrowserPrivate
+{
+ QtGroupBoxPropertyBrowser *q_ptr;
+ Q_DECLARE_PUBLIC(QtGroupBoxPropertyBrowser)
+public:
+
+ void init(QWidget *parent);
+
+ void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex);
+ void propertyRemoved(QtBrowserItem *index);
+ void propertyChanged(QtBrowserItem *index);
+ QWidget *createEditor(QtProperty *property, QWidget *parent) const
+ { return q_ptr->createEditor(property, parent); }
+
+ void slotEditorDestroyed();
+ void slotUpdate();
+
+ struct WidgetItem
+ {
+ WidgetItem() : widget(0), label(0), widgetLabel(0),
+ groupBox(0), layout(0), line(0), parent(0) { }
+ QWidget *widget; // can be null
+ QLabel *label;
+ QLabel *widgetLabel;
+ QGroupBox *groupBox;
+ QGridLayout *layout;
+ QFrame *line;
+ WidgetItem *parent;
+ QList<WidgetItem *> children;
+ };
+private:
+ void updateLater();
+ void updateItem(WidgetItem *item);
+ void insertRow(QGridLayout *layout, int row) const;
+ void removeRow(QGridLayout *layout, int row) const;
+
+ bool hasHeader(WidgetItem *item) const;
+
+ QMap<QtBrowserItem *, WidgetItem *> m_indexToItem;
+ QMap<WidgetItem *, QtBrowserItem *> m_itemToIndex;
+ QMap<QWidget *, WidgetItem *> m_widgetToItem;
+ QGridLayout *m_mainLayout;
+ QList<WidgetItem *> m_children;
+ QList<WidgetItem *> m_recreateQueue;
+};
+
+void QtGroupBoxPropertyBrowserPrivate::init(QWidget *parent)
+{
+ m_mainLayout = new QGridLayout();
+ parent->setLayout(m_mainLayout);
+ QLayoutItem *item = new QSpacerItem(0, 0,
+ QSizePolicy::Fixed, QSizePolicy::Expanding);
+ m_mainLayout->addItem(item, 0, 0);
+}
+
+void QtGroupBoxPropertyBrowserPrivate::slotEditorDestroyed()
+{
+ QWidget *editor = qobject_cast<QWidget *>(q_ptr->sender());
+ if (!editor)
+ return;
+ if (!m_widgetToItem.contains(editor))
+ return;
+ m_widgetToItem[editor]->widget = 0;
+ m_widgetToItem.remove(editor);
+}
+
+void QtGroupBoxPropertyBrowserPrivate::slotUpdate()
+{
+ QListIterator<WidgetItem *> itItem(m_recreateQueue);
+ while (itItem.hasNext()) {
+ WidgetItem *item = itItem.next();
+
+ WidgetItem *par = item->parent;
+ QWidget *w = 0;
+ QGridLayout *l = 0;
+ int oldRow = -1;
+ if (!par) {
+ w = q_ptr;
+ l = m_mainLayout;
+ oldRow = m_children.indexOf(item);
+ } else {
+ w = par->groupBox;
+ l = par->layout;
+ oldRow = par->children.indexOf(item);
+ if (hasHeader(par))
+ oldRow += 2;
+ }
+
+ if (item->widget) {
+ item->widget->setParent(w);
+ } else if (item->widgetLabel) {
+ item->widgetLabel->setParent(w);
+ } else {
+ item->widgetLabel = new QLabel(w);
+ }
+ int span = 1;
+ if (item->widget)
+ l->addWidget(item->widget, oldRow, 1, 1, 1);
+ else if (item->widgetLabel)
+ l->addWidget(item->widgetLabel, oldRow, 1, 1, 1);
+ else
+ span = 2;
+ item->label = new QLabel(w);
+ item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ l->addWidget(item->label, oldRow, 0, 1, span);
+
+ updateItem(item);
+ }
+ m_recreateQueue.clear();
+}
+
+void QtGroupBoxPropertyBrowserPrivate::updateLater()
+{
+ QTimer::singleShot(0, q_ptr, SLOT(slotUpdate()));
+}
+
+void QtGroupBoxPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex)
+{
+ WidgetItem *afterItem = m_indexToItem.value(afterIndex);
+ WidgetItem *parentItem = m_indexToItem.value(index->parent());
+
+ WidgetItem *newItem = new WidgetItem();
+ newItem->parent = parentItem;
+
+ QGridLayout *layout = 0;
+ QWidget *parentWidget = 0;
+ int row = -1;
+ if (!afterItem) {
+ row = 0;
+ if (parentItem)
+ parentItem->children.insert(0, newItem);
+ else
+ m_children.insert(0, newItem);
+ } else {
+ if (parentItem) {
+ row = parentItem->children.indexOf(afterItem) + 1;
+ parentItem->children.insert(row, newItem);
+ } else {
+ row = m_children.indexOf(afterItem) + 1;
+ m_children.insert(row, newItem);
+ }
+ }
+ if (parentItem && hasHeader(parentItem))
+ row += 2;
+
+ if (!parentItem) {
+ layout = m_mainLayout;
+ parentWidget = q_ptr;;
+ } else {
+ if (!parentItem->groupBox) {
+ m_recreateQueue.removeAll(parentItem);
+ WidgetItem *par = parentItem->parent;
+ QWidget *w = 0;
+ QGridLayout *l = 0;
+ int oldRow = -1;
+ if (!par) {
+ w = q_ptr;
+ l = m_mainLayout;
+ oldRow = m_children.indexOf(parentItem);
+ } else {
+ w = par->groupBox;
+ l = par->layout;
+ oldRow = par->children.indexOf(parentItem);
+ if (hasHeader(par))
+ oldRow += 2;
+ }
+ parentItem->groupBox = new QGroupBox(w);
+ parentItem->layout = new QGridLayout();
+ parentItem->groupBox->setLayout(parentItem->layout);
+ if (parentItem->label) {
+ l->removeWidget(parentItem->label);
+ delete parentItem->label;
+ parentItem->label = 0;
+ }
+ if (parentItem->widget) {
+ l->removeWidget(parentItem->widget);
+ parentItem->widget->setParent(parentItem->groupBox);
+ parentItem->layout->addWidget(parentItem->widget, 0, 0, 1, 2);
+ parentItem->line = new QFrame(parentItem->groupBox);
+ } else if (parentItem->widgetLabel) {
+ l->removeWidget(parentItem->widgetLabel);
+ delete parentItem->widgetLabel;
+ parentItem->widgetLabel = 0;
+ }
+ if (parentItem->line) {
+ parentItem->line->setFrameShape(QFrame::HLine);
+ parentItem->line->setFrameShadow(QFrame::Sunken);
+ parentItem->layout->addWidget(parentItem->line, 1, 0, 1, 2);
+ }
+ l->addWidget(parentItem->groupBox, oldRow, 0, 1, 2);
+ updateItem(parentItem);
+ }
+ layout = parentItem->layout;
+ parentWidget = parentItem->groupBox;
+ }
+
+ newItem->label = new QLabel(parentWidget);
+ newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ newItem->widget = createEditor(index->property(), parentWidget);
+ if (!newItem->widget) {
+ newItem->widgetLabel = new QLabel(parentWidget);
+ } else {
+ QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed()));
+ m_widgetToItem[newItem->widget] = newItem;
+ }
+
+ insertRow(layout, row);
+ int span = 1;
+ if (newItem->widget)
+ layout->addWidget(newItem->widget, row, 1);
+ else if (newItem->widgetLabel)
+ layout->addWidget(newItem->widgetLabel, row, 1);
+ else
+ span = 2;
+ layout->addWidget(newItem->label, row, 0, 1, span);
+
+ m_itemToIndex[newItem] = index;
+ m_indexToItem[index] = newItem;
+
+ updateItem(newItem);
+}
+
+void QtGroupBoxPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index)
+{
+ WidgetItem *item = m_indexToItem.value(index);
+
+ m_indexToItem.remove(index);
+ m_itemToIndex.remove(item);
+
+ WidgetItem *parentItem = item->parent;
+
+ int row = -1;
+
+ if (parentItem) {
+ row = parentItem->children.indexOf(item);
+ parentItem->children.removeAt(row);
+ if (hasHeader(parentItem))
+ row += 2;
+ } else {
+ row = m_children.indexOf(item);
+ m_children.removeAt(row);
+ }
+
+ if (item->widget)
+ delete item->widget;
+ if (item->label)
+ delete item->label;
+ if (item->widgetLabel)
+ delete item->widgetLabel;
+ if (item->groupBox)
+ delete item->groupBox;
+
+ if (!parentItem) {
+ removeRow(m_mainLayout, row);
+ } else if (parentItem->children.count() != 0) {
+ removeRow(parentItem->layout, row);
+ } else {
+ WidgetItem *par = parentItem->parent;
+ QWidget *w = 0;
+ QGridLayout *l = 0;
+ int oldRow = -1;
+ if (!par) {
+ w = q_ptr;
+ l = m_mainLayout;
+ oldRow = m_children.indexOf(parentItem);
+ } else {
+ w = par->groupBox;
+ l = par->layout;
+ oldRow = par->children.indexOf(parentItem);
+ if (hasHeader(par))
+ oldRow += 2;
+ }
+
+ if (parentItem->widget) {
+ parentItem->widget->hide();
+ parentItem->widget->setParent(0);
+ } else if (parentItem->widgetLabel) {
+ parentItem->widgetLabel->hide();
+ parentItem->widgetLabel->setParent(0);
+ } else {
+ //parentItem->widgetLabel = new QLabel(w);
+ }
+ l->removeWidget(parentItem->groupBox);
+ delete parentItem->groupBox;
+ parentItem->groupBox = 0;
+ parentItem->line = 0;
+ parentItem->layout = 0;
+ if (!m_recreateQueue.contains(parentItem))
+ m_recreateQueue.append(parentItem);
+ updateLater();
+ }
+ m_recreateQueue.removeAll(item);
+
+ delete item;
+}
+
+void QtGroupBoxPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const
+{
+ QMap<QLayoutItem *, QRect> itemToPos;
+ int idx = 0;
+ while (idx < layout->count()) {
+ int r, c, rs, cs;
+ layout->getItemPosition(idx, &r, &c, &rs, &cs);
+ if (r >= row) {
+ itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs);
+ } else {
+ idx++;
+ }
+ }
+
+ const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
+ for (QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
+ const QRect r = it.value();
+ layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
+ }
+}
+
+void QtGroupBoxPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const
+{
+ QMap<QLayoutItem *, QRect> itemToPos;
+ int idx = 0;
+ while (idx < layout->count()) {
+ int r, c, rs, cs;
+ layout->getItemPosition(idx, &r, &c, &rs, &cs);
+ if (r > row) {
+ itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs);
+ } else {
+ idx++;
+ }
+ }
+
+ const QMap<QLayoutItem *, QRect>::ConstIterator icend = itemToPos.constEnd();
+ for (QMap<QLayoutItem *, QRect>::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) {
+ const QRect r = it.value();
+ layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height());
+ }
+}
+
+bool QtGroupBoxPropertyBrowserPrivate::hasHeader(WidgetItem *item) const
+{
+ if (item->widget)
+ return true;
+ return false;
+}
+
+void QtGroupBoxPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index)
+{
+ WidgetItem *item = m_indexToItem.value(index);
+
+ updateItem(item);
+}
+
+void QtGroupBoxPropertyBrowserPrivate::updateItem(WidgetItem *item)
+{
+ QtProperty *property = m_itemToIndex[item]->property();
+ if (item->groupBox) {
+ QFont font = item->groupBox->font();
+ font.setUnderline(property->isModified());
+ item->groupBox->setFont(font);
+ item->groupBox->setTitle(property->propertyName());
+ item->groupBox->setToolTip(property->toolTip());
+ item->groupBox->setStatusTip(property->statusTip());
+ item->groupBox->setWhatsThis(property->whatsThis());
+ item->groupBox->setEnabled(property->isEnabled());
+ }
+ if (item->label) {
+ QFont font = item->label->font();
+ font.setUnderline(property->isModified());
+ item->label->setFont(font);
+ item->label->setText(property->propertyName());
+ item->label->setToolTip(property->toolTip());
+ item->label->setStatusTip(property->statusTip());
+ item->label->setWhatsThis(property->whatsThis());
+ item->label->setEnabled(property->isEnabled());
+ }
+ if (item->widgetLabel) {
+ QFont font = item->widgetLabel->font();
+ font.setUnderline(false);
+ item->widgetLabel->setFont(font);
+ item->widgetLabel->setText(property->valueText());
+ item->widgetLabel->setEnabled(property->isEnabled());
+ }
+ if (item->widget) {
+ QFont font = item->widget->font();
+ font.setUnderline(false);
+ item->widget->setFont(font);
+ item->widget->setEnabled(property->isEnabled());
+ item->widget->setToolTip(property->valueText());
+ }
+ //item->setIcon(1, property->valueIcon());
+}
+
+
+
+/*!
+ \class QtGroupBoxPropertyBrowser
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtGroupBoxPropertyBrowser class provides a QGroupBox
+ based property browser.
+
+ A property browser is a widget that enables the user to edit a
+ given set of properties. Each property is represented by a label
+ specifying the property's name, and an editing widget (e.g. a line
+ edit or a combobox) holding its value. A property can have zero or
+ more subproperties.
+
+ QtGroupBoxPropertyBrowser provides group boxes for all nested
+ properties, i.e. subproperties are enclosed by a group box with
+ the parent property's name as its title. For example:
+
+ \image qtgroupboxpropertybrowser.png
+
+ Use the QtAbstractPropertyBrowser API to add, insert and remove
+ properties from an instance of the QtGroupBoxPropertyBrowser
+ class. The properties themselves are created and managed by
+ implementations of the QtAbstractPropertyManager class.
+
+ \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser
+*/
+
+/*!
+ Creates a property browser with the given \a parent.
+*/
+QtGroupBoxPropertyBrowser::QtGroupBoxPropertyBrowser(QWidget *parent)
+ : QtAbstractPropertyBrowser(parent)
+{
+ d_ptr = new QtGroupBoxPropertyBrowserPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->init(this);
+}
+
+/*!
+ Destroys this property browser.
+
+ Note that the properties that were inserted into this browser are
+ \e not destroyed since they may still be used in other
+ browsers. The properties are owned by the manager that created
+ them.
+
+ \sa QtProperty, QtAbstractPropertyManager
+*/
+QtGroupBoxPropertyBrowser::~QtGroupBoxPropertyBrowser()
+{
+ const QMap<QtGroupBoxPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator icend = d_ptr->m_itemToIndex.constEnd();
+ for (QMap<QtGroupBoxPropertyBrowserPrivate::WidgetItem *, QtBrowserItem *>::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it)
+ delete it.key();
+ delete d_ptr;
+}
+
+/*!
+ \reimp
+*/
+void QtGroupBoxPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem)
+{
+ d_ptr->propertyInserted(item, afterItem);
+}
+
+/*!
+ \reimp
+*/
+void QtGroupBoxPropertyBrowser::itemRemoved(QtBrowserItem *item)
+{
+ d_ptr->propertyRemoved(item);
+}
+
+/*!
+ \reimp
+*/
+void QtGroupBoxPropertyBrowser::itemChanged(QtBrowserItem *item)
+{
+ d_ptr->propertyChanged(item);
+}
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#include "moc_qtgroupboxpropertybrowser.cpp"
diff --git a/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h b/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h
new file mode 100644
index 0000000000..29422bd810
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtgroupboxpropertybrowser.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTGROUPBOXPROPERTYBROWSER_H
+#define QTGROUPBOXPROPERTYBROWSER_H
+
+#include "qtpropertybrowser.h"
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtGroupBoxPropertyBrowserPrivate;
+
+class QtGroupBoxPropertyBrowser : public QtAbstractPropertyBrowser
+{
+ Q_OBJECT
+public:
+
+ QtGroupBoxPropertyBrowser(QWidget *parent = 0);
+ ~QtGroupBoxPropertyBrowser();
+
+protected:
+ virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem);
+ virtual void itemRemoved(QtBrowserItem *item);
+ virtual void itemChanged(QtBrowserItem *item);
+
+private:
+
+ QtGroupBoxPropertyBrowserPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtGroupBoxPropertyBrowser)
+ Q_DISABLE_COPY(QtGroupBoxPropertyBrowser)
+ Q_PRIVATE_SLOT(d_func(), void slotUpdate())
+ Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed())
+
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#endif
diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowser.cpp b/tools/shared/qtpropertybrowser/qtpropertybrowser.cpp
new file mode 100644
index 0000000000..72542454ff
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertybrowser.cpp
@@ -0,0 +1,1965 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtpropertybrowser.h"
+#include <QtCore/QSet>
+#include <QtCore/QMap>
+#include <QtGui/QIcon>
+
+#if defined(Q_CC_MSVC)
+# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */
+#endif
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtPropertyPrivate
+{
+public:
+ QtPropertyPrivate(QtAbstractPropertyManager *manager) : m_enabled(true), m_modified(false), m_manager(manager) {}
+ QtProperty *q_ptr;
+
+ QSet<QtProperty *> m_parentItems;
+ QList<QtProperty *> m_subItems;
+
+ QString m_toolTip;
+ QString m_statusTip;
+ QString m_whatsThis;
+ QString m_name;
+ bool m_enabled;
+ bool m_modified;
+
+ QtAbstractPropertyManager * const m_manager;
+};
+
+class QtAbstractPropertyManagerPrivate
+{
+ QtAbstractPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtAbstractPropertyManager)
+public:
+ void propertyDestroyed(QtProperty *property);
+ void propertyChanged(QtProperty *property) const;
+ void propertyRemoved(QtProperty *property,
+ QtProperty *parentProperty) const;
+ void propertyInserted(QtProperty *property, QtProperty *parentProperty,
+ QtProperty *afterProperty) const;
+
+ QSet<QtProperty *> m_properties;
+};
+
+/*!
+ \class QtProperty
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtProperty class encapsulates an instance of a property.
+
+ Properties are created by objects of QtAbstractPropertyManager
+ subclasses; a manager can create properties of a given type, and
+ is used in conjunction with the QtAbstractPropertyBrowser class. A
+ property is always owned by the manager that created it, which can
+ be retrieved using the propertyManager() function.
+
+ QtProperty contains the most common property attributes, and
+ provides functions for retrieving as well as setting their values:
+
+ \table
+ \header \o Getter \o Setter
+ \row
+ \o propertyName() \o setPropertyName()
+ \row
+ \o statusTip() \o setStatusTip()
+ \row
+ \o toolTip() \o setToolTip()
+ \row
+ \o whatsThis() \o setWhatsThis()
+ \row
+ \o isEnabled() \o setEnabled()
+ \row
+ \o isModified() \o setModified()
+ \row
+ \o valueText() \o Nop
+ \row
+ \o valueIcon() \o Nop
+ \endtable
+
+ It is also possible to nest properties: QtProperty provides the
+ addSubProperty(), insertSubProperty() and removeSubProperty() functions to
+ manipulate the set of subproperties. Use the subProperties()
+ function to retrieve a property's current set of subproperties.
+ Note that nested properties are not owned by the parent property,
+ i.e. each subproperty is owned by the manager that created it.
+
+ \sa QtAbstractPropertyManager, QtBrowserItem
+*/
+
+/*!
+ Creates a property with the given \a manager.
+
+ This constructor is only useful when creating a custom QtProperty
+ subclass (e.g. QtVariantProperty). To create a regular QtProperty
+ object, use the QtAbstractPropertyManager::addProperty()
+ function instead.
+
+ \sa QtAbstractPropertyManager::addProperty()
+*/
+QtProperty::QtProperty(QtAbstractPropertyManager *manager)
+{
+ d_ptr = new QtPropertyPrivate(manager);
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this property.
+
+ Note that subproperties are detached but not destroyed, i.e. they
+ can still be used in another context.
+
+ \sa QtAbstractPropertyManager::clear()
+
+*/
+QtProperty::~QtProperty()
+{
+ QSetIterator<QtProperty *> itParent(d_ptr->m_parentItems);
+ while (itParent.hasNext()) {
+ QtProperty *property = itParent.next();
+ property->d_ptr->m_manager->d_ptr->propertyRemoved(this, property);
+ }
+
+ d_ptr->m_manager->d_ptr->propertyDestroyed(this);
+
+ QListIterator<QtProperty *> itChild(d_ptr->m_subItems);
+ while (itChild.hasNext()) {
+ QtProperty *property = itChild.next();
+ property->d_ptr->m_parentItems.remove(this);
+ }
+
+ itParent.toFront();
+ while (itParent.hasNext()) {
+ QtProperty *property = itParent.next();
+ property->d_ptr->m_subItems.removeAll(this);
+ }
+ delete d_ptr;
+}
+
+/*!
+ Returns the set of subproperties.
+
+ Note that subproperties are not owned by \e this property, but by
+ the manager that created them.
+
+ \sa insertSubProperty(), removeSubProperty()
+*/
+QList<QtProperty *> QtProperty::subProperties() const
+{
+ return d_ptr->m_subItems;
+}
+
+/*!
+ Returns a pointer to the manager that owns this property.
+*/
+QtAbstractPropertyManager *QtProperty::propertyManager() const
+{
+ return d_ptr->m_manager;
+}
+
+/*!
+ Returns the property's tool tip.
+
+ \sa setToolTip()
+*/
+QString QtProperty::toolTip() const
+{
+ return d_ptr->m_toolTip;
+}
+
+/*!
+ Returns the property's status tip.
+
+ \sa setStatusTip()
+*/
+QString QtProperty::statusTip() const
+{
+ return d_ptr->m_statusTip;
+}
+
+/*!
+ Returns the property's "What's This" help text.
+
+ \sa setWhatsThis()
+*/
+QString QtProperty::whatsThis() const
+{
+ return d_ptr->m_whatsThis;
+}
+
+/*!
+ Returns the property's name.
+
+ \sa setPropertyName()
+*/
+QString QtProperty::propertyName() const
+{
+ return d_ptr->m_name;
+}
+
+/*!
+ Returns whether the property is enabled.
+
+ \sa setEnabled()
+*/
+bool QtProperty::isEnabled() const
+{
+ return d_ptr->m_enabled;
+}
+
+/*!
+ Returns whether the property is modified.
+
+ \sa setModified()
+*/
+bool QtProperty::isModified() const
+{
+ return d_ptr->m_modified;
+}
+
+/*!
+ Returns whether the property has a value.
+
+ \sa QtAbstractPropertyManager::hasValue()
+*/
+bool QtProperty::hasValue() const
+{
+ return d_ptr->m_manager->hasValue(this);
+}
+
+/*!
+ Returns an icon representing the current state of this property.
+
+ If the given property type can not generate such an icon, this
+ function returns an invalid icon.
+
+ \sa QtAbstractPropertyManager::valueIcon()
+*/
+QIcon QtProperty::valueIcon() const
+{
+ return d_ptr->m_manager->valueIcon(this);
+}
+
+/*!
+ Returns a string representing the current state of this property.
+
+ If the given property type can not generate such a string, this
+ function returns an empty string.
+
+ \sa QtAbstractPropertyManager::valueText()
+*/
+QString QtProperty::valueText() const
+{
+ return d_ptr->m_manager->valueText(this);
+}
+
+/*!
+ Sets the property's tool tip to the given \a text.
+
+ \sa toolTip()
+*/
+void QtProperty::setToolTip(const QString &text)
+{
+ if (d_ptr->m_toolTip == text)
+ return;
+
+ d_ptr->m_toolTip = text;
+ propertyChanged();
+}
+
+/*!
+ Sets the property's status tip to the given \a text.
+
+ \sa statusTip()
+*/
+void QtProperty::setStatusTip(const QString &text)
+{
+ if (d_ptr->m_statusTip == text)
+ return;
+
+ d_ptr->m_statusTip = text;
+ propertyChanged();
+}
+
+/*!
+ Sets the property's "What's This" help text to the given \a text.
+
+ \sa whatsThis()
+*/
+void QtProperty::setWhatsThis(const QString &text)
+{
+ if (d_ptr->m_whatsThis == text)
+ return;
+
+ d_ptr->m_whatsThis = text;
+ propertyChanged();
+}
+
+/*!
+ \fn void QtProperty::setPropertyName(const QString &name)
+
+ Sets the property's name to the given \a name.
+
+ \sa propertyName()
+*/
+void QtProperty::setPropertyName(const QString &text)
+{
+ if (d_ptr->m_name == text)
+ return;
+
+ d_ptr->m_name = text;
+ propertyChanged();
+}
+
+/*!
+ Enables or disables the property according to the passed \a enable value.
+
+ \sa isEnabled()
+*/
+void QtProperty::setEnabled(bool enable)
+{
+ if (d_ptr->m_enabled == enable)
+ return;
+
+ d_ptr->m_enabled = enable;
+ propertyChanged();
+}
+
+/*!
+ Sets the property's modified state according to the passed \a modified value.
+
+ \sa isModified()
+*/
+void QtProperty::setModified(bool modified)
+{
+ if (d_ptr->m_modified == modified)
+ return;
+
+ d_ptr->m_modified = modified;
+ propertyChanged();
+}
+
+/*!
+ Appends the given \a property to this property's subproperties.
+
+ If the given \a property already is added, this function does
+ nothing.
+
+ \sa insertSubProperty(), removeSubProperty()
+*/
+void QtProperty::addSubProperty(QtProperty *property)
+{
+ QtProperty *after = 0;
+ if (d_ptr->m_subItems.count() > 0)
+ after = d_ptr->m_subItems.last();
+ insertSubProperty(property, after);
+}
+
+/*!
+ \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty)
+
+ Inserts the given \a property after the specified \a
+ precedingProperty into this property's list of subproperties. If
+ \a precedingProperty is 0, the specified \a property is inserted
+ at the beginning of the list.
+
+ If the given \a property already is inserted, this function does
+ nothing.
+
+ \sa addSubProperty(), removeSubProperty()
+*/
+void QtProperty::insertSubProperty(QtProperty *property,
+ QtProperty *afterProperty)
+{
+ if (!property)
+ return;
+
+ if (property == this)
+ return;
+
+ // traverse all children of item. if this item is a child of item then cannot add.
+ QList<QtProperty *> pendingList = property->subProperties();
+ QMap<QtProperty *, bool> visited;
+ while (!pendingList.isEmpty()) {
+ QtProperty *i = pendingList.first();
+ if (i == this)
+ return;
+ pendingList.removeFirst();
+ if (visited.contains(i))
+ continue;
+ visited[i] = true;
+ pendingList += i->subProperties();
+ }
+
+ pendingList = subProperties();
+ int pos = 0;
+ int newPos = 0;
+ QtProperty *properAfterProperty = 0;
+ while (pos < pendingList.count()) {
+ QtProperty *i = pendingList.at(pos);
+ if (i == property)
+ return; // if item is already inserted in this item then cannot add.
+ if (i == afterProperty) {
+ newPos = pos + 1;
+ properAfterProperty = afterProperty;
+ }
+ pos++;
+ }
+
+ d_ptr->m_subItems.insert(newPos, property);
+ property->d_ptr->m_parentItems.insert(this);
+
+ d_ptr->m_manager->d_ptr->propertyInserted(property, this, properAfterProperty);
+}
+
+/*!
+ Removes the given \a property from the list of subproperties
+ without deleting it.
+
+ \sa addSubProperty(), insertSubProperty()
+*/
+void QtProperty::removeSubProperty(QtProperty *property)
+{
+ if (!property)
+ return;
+
+ d_ptr->m_manager->d_ptr->propertyRemoved(property, this);
+
+ QList<QtProperty *> pendingList = subProperties();
+ int pos = 0;
+ while (pos < pendingList.count()) {
+ if (pendingList.at(pos) == property) {
+ d_ptr->m_subItems.removeAt(pos);
+ property->d_ptr->m_parentItems.remove(this);
+
+ return;
+ }
+ pos++;
+ }
+}
+
+/*!
+ \internal
+*/
+void QtProperty::propertyChanged()
+{
+ d_ptr->m_manager->d_ptr->propertyChanged(this);
+}
+
+////////////////////////////////
+
+void QtAbstractPropertyManagerPrivate::propertyDestroyed(QtProperty *property)
+{
+ if (m_properties.contains(property)) {
+ emit q_ptr->propertyDestroyed(property);
+ q_ptr->uninitializeProperty(property);
+ m_properties.remove(property);
+ }
+}
+
+void QtAbstractPropertyManagerPrivate::propertyChanged(QtProperty *property) const
+{
+ emit q_ptr->propertyChanged(property);
+}
+
+void QtAbstractPropertyManagerPrivate::propertyRemoved(QtProperty *property,
+ QtProperty *parentProperty) const
+{
+ emit q_ptr->propertyRemoved(property, parentProperty);
+}
+
+void QtAbstractPropertyManagerPrivate::propertyInserted(QtProperty *property,
+ QtProperty *parentProperty, QtProperty *afterProperty) const
+{
+ emit q_ptr->propertyInserted(property, parentProperty, afterProperty);
+}
+
+/*!
+ \class QtAbstractPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtAbstractPropertyManager provides an interface for
+ property managers.
+
+ A manager can create and manage properties of a given type, and is
+ used in conjunction with the QtAbstractPropertyBrowser class.
+
+ When using a property browser widget, the properties are created
+ and managed by implementations of the QtAbstractPropertyManager
+ class. To ensure that the properties' values will be displayed
+ using suitable editing widgets, the managers are associated with
+ objects of QtAbstractEditorFactory subclasses. The property browser
+ will use these associations to determine which factories it should
+ use to create the preferred editing widgets.
+
+ The QtAbstractPropertyManager class provides common functionality
+ like creating a property using the addProperty() function, and
+ retrieving the properties created by the manager using the
+ properties() function. The class also provides signals that are
+ emitted when the manager's properties change: propertyInserted(),
+ propertyRemoved(), propertyChanged() and propertyDestroyed().
+
+ QtAbstractPropertyManager subclasses are supposed to provide their
+ own type specific API. Note that several ready-made
+ implementations are available:
+
+ \list
+ \o QtBoolPropertyManager
+ \o QtColorPropertyManager
+ \o QtDatePropertyManager
+ \o QtDateTimePropertyManager
+ \o QtDoublePropertyManager
+ \o QtEnumPropertyManager
+ \o QtFlagPropertyManager
+ \o QtFontPropertyManager
+ \o QtGroupPropertyManager
+ \o QtIntPropertyManager
+ \o QtPointPropertyManager
+ \o QtRectPropertyManager
+ \o QtSizePropertyManager
+ \o QtSizePolicyPropertyManager
+ \o QtStringPropertyManager
+ \o QtTimePropertyManager
+ \o QtVariantPropertyManager
+ \endlist
+
+ \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty
+*/
+
+/*!
+ \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty,
+ QtProperty *parentProperty, QtProperty *precedingProperty)
+
+ This signal is emitted when a new subproperty is inserted into an
+ existing property, passing pointers to the \a newProperty, \a
+ parentProperty and \a precedingProperty as parameters.
+
+ If \a precedingProperty is 0, the \a newProperty was inserted at
+ the beginning of the \a parentProperty's subproperties list.
+
+ Note that signal is emitted only if the \a parentProperty is created
+ by this manager.
+
+ \sa QtAbstractPropertyBrowser::itemInserted()
+*/
+
+/*!
+ \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property)
+
+ This signal is emitted whenever a property's data changes, passing
+ a pointer to the \a property as parameter.
+
+ Note that signal is only emitted for properties that are created by
+ this manager.
+
+ \sa QtAbstractPropertyBrowser::itemChanged()
+*/
+
+/*!
+ \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent)
+
+ This signal is emitted when a subproperty is removed, passing
+ pointers to the removed \a property and the \a parent property as
+ parameters.
+
+ Note that signal is emitted only when the \a parent property is
+ created by this manager.
+
+ \sa QtAbstractPropertyBrowser::itemRemoved()
+*/
+
+/*!
+ \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property)
+
+ This signal is emitted when the specified \a property is about to
+ be destroyed.
+
+ Note that signal is only emitted for properties that are created
+ by this manager.
+
+ \sa clear(), uninitializeProperty()
+*/
+
+/*!
+ \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current)
+
+ This signal is emitted when the current item changes. The current item is specified by \a current.
+
+ \sa QtAbstractPropertyBrowser::setCurrentItem()
+*/
+
+/*!
+ Creates an abstract property manager with the given \a parent.
+*/
+QtAbstractPropertyManager::QtAbstractPropertyManager(QObject *parent)
+ : QObject(parent)
+{
+ d_ptr = new QtAbstractPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys the manager. All properties created by the manager are
+ destroyed.
+*/
+QtAbstractPropertyManager::~QtAbstractPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Destroys all the properties that this manager has created.
+
+ \sa propertyDestroyed(), uninitializeProperty()
+*/
+void QtAbstractPropertyManager::clear() const
+{
+ while (!properties().isEmpty()) {
+ QSetIterator<QtProperty *> itProperty(properties());
+ QtProperty *prop = itProperty.next();
+ delete prop;
+ }
+}
+
+/*!
+ Returns the set of properties created by this manager.
+
+ \sa addProperty()
+*/
+QSet<QtProperty *> QtAbstractPropertyManager::properties() const
+{
+ return d_ptr->m_properties;
+}
+
+/*!
+ Returns whether the given \a property has a value.
+
+ The default implementation of this function returns true.
+
+ \sa QtProperty::hasValue()
+*/
+bool QtAbstractPropertyManager::hasValue(const QtProperty *property) const
+{
+ Q_UNUSED(property)
+ return true;
+}
+
+/*!
+ Returns an icon representing the current state of the given \a
+ property.
+
+ The default implementation of this function returns an invalid
+ icon.
+
+ \sa QtProperty::valueIcon()
+*/
+QIcon QtAbstractPropertyManager::valueIcon(const QtProperty *property) const
+{
+ Q_UNUSED(property)
+ return QIcon();
+}
+
+/*!
+ Returns a string representing the current state of the given \a
+ property.
+
+ The default implementation of this function returns an empty
+ string.
+
+ \sa QtProperty::valueText()
+*/
+QString QtAbstractPropertyManager::valueText(const QtProperty *property) const
+{
+ Q_UNUSED(property)
+ return QString();
+}
+
+/*!
+ Creates a property with the given \a name which then is owned by this manager.
+
+ Internally, this function calls the createProperty() and
+ initializeProperty() functions.
+
+ \sa initializeProperty(), properties()
+*/
+QtProperty *QtAbstractPropertyManager::addProperty(const QString &name)
+{
+ QtProperty *property = createProperty();
+ if (property) {
+ property->setPropertyName(name);
+ d_ptr->m_properties.insert(property);
+ initializeProperty(property);
+ }
+ return property;
+}
+
+/*!
+ Creates a property.
+
+ The base implementation produce QtProperty instances; Reimplement
+ this function to make this manager produce objects of a QtProperty
+ subclass.
+
+ \sa addProperty(), initializeProperty()
+*/
+QtProperty *QtAbstractPropertyManager::createProperty()
+{
+ return new QtProperty(this);
+}
+
+/*!
+ \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0
+
+ This function is called whenever a new valid property pointer has
+ been created, passing the pointer as parameter.
+
+ The purpose is to let the manager know that the \a property has
+ been created so that it can provide additional attributes for the
+ new property, e.g. QtIntPropertyManager adds \l
+ {QtIntPropertyManager::value()}{value}, \l
+ {QtIntPropertyManager::minimum()}{minimum} and \l
+ {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager
+ subclass adds type specific attributes, this function is pure
+ virtual and must be reimplemented when deriving from the
+ QtAbstractPropertyManager class.
+
+ \sa addProperty(), createProperty()
+*/
+
+/*!
+ This function is called just before the specified \a property is destroyed.
+
+ The purpose is to let the property manager know that the \a
+ property is being destroyed so that it can remove the property's
+ additional attributes.
+
+ \sa clear(), propertyDestroyed()
+*/
+void QtAbstractPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ Q_UNUSED(property)
+}
+
+////////////////////////////////////
+
+/*!
+ \class QtAbstractEditorFactoryBase
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtAbstractEditorFactoryBase provides an interface for
+ editor factories.
+
+ An editor factory is a class that is able to create an editing
+ widget of a specified type (e.g. line edits or comboboxes) for a
+ given QtProperty object, and it is used in conjunction with the
+ QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
+
+ When using a property browser widget, the properties are created
+ and managed by implementations of the QtAbstractPropertyManager
+ class. To ensure that the properties' values will be displayed
+ using suitable editing widgets, the managers are associated with
+ objects of QtAbstractEditorFactory subclasses. The property browser
+ will use these associations to determine which factories it should
+ use to create the preferred editing widgets.
+
+ Typically, an editor factory is created by subclassing the
+ QtAbstractEditorFactory template class which inherits
+ QtAbstractEditorFactoryBase. But note that several ready-made
+ implementations are available:
+
+ \list
+ \o QtCheckBoxFactory
+ \o QtDateEditFactory
+ \o QtDateTimeEditFactory
+ \o QtDoubleSpinBoxFactory
+ \o QtEnumEditorFactory
+ \o QtLineEditFactory
+ \o QtScrollBarFactory
+ \o QtSliderFactory
+ \o QtSpinBoxFactory
+ \o QtTimeEditFactory
+ \o QtVariantEditorFactory
+ \endlist
+
+ \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser
+*/
+
+/*!
+ \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property,
+ QWidget *parent) = 0
+
+ Creates an editing widget (with the given \a parent) for the given
+ \a property.
+
+ This function is reimplemented in QtAbstractEditorFactory template class
+ which also provides a pure virtual convenience overload of this
+ function enabling access to the property's manager.
+
+ \sa QtAbstractEditorFactory::createEditor()
+*/
+
+/*!
+ \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0)
+
+ Creates an abstract editor factory with the given \a parent.
+*/
+
+/*!
+ \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0
+
+ \internal
+
+ Detaches property manager from factory.
+ This method is reimplemented in QtAbstractEditorFactory template subclass.
+ You don't need to reimplement it in your subclasses. Instead implement more convenient
+ QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass.
+*/
+
+/*!
+ \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0
+
+ \internal
+
+ This method is called when property manager is being destroyed.
+ Basically it notifies factory not to produce editors for properties owned by \a manager.
+ You don't need to reimplement it in your subclass. This method is implemented in
+ QtAbstractEditorFactory template subclass.
+*/
+
+/*!
+ \class QtAbstractEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtAbstractEditorFactory is the base template class for editor
+ factories.
+
+ An editor factory is a class that is able to create an editing
+ widget of a specified type (e.g. line edits or comboboxes) for a
+ given QtProperty object, and it is used in conjunction with the
+ QtAbstractPropertyManager and QtAbstractPropertyBrowser classes.
+
+ Note that the QtAbstractEditorFactory functions are using the
+ PropertyManager template argument class which can be any
+ QtAbstractPropertyManager subclass. For example:
+
+ \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 0
+
+ Note that QtSpinBoxFactory by definition creates editing widgets
+ \e only for properties created by QtIntPropertyManager.
+
+ When using a property browser widget, the properties are created
+ and managed by implementations of the QtAbstractPropertyManager
+ class. To ensure that the properties' values will be displayed
+ using suitable editing widgets, the managers are associated with
+ objects of QtAbstractEditorFactory subclasses. The property browser will
+ use these associations to determine which factories it should use
+ to create the preferred editing widgets.
+
+ A QtAbstractEditorFactory object is capable of producing editors for
+ several property managers at the same time. To create an
+ association between this factory and a given manager, use the
+ addPropertyManager() function. Use the removePropertyManager() function to make
+ this factory stop producing editors for a given property
+ manager. Use the propertyManagers() function to retrieve the set of
+ managers currently associated with this factory.
+
+ Several ready-made implementations of the QtAbstractEditorFactory class
+ are available:
+
+ \list
+ \o QtCheckBoxFactory
+ \o QtDateEditFactory
+ \o QtDateTimeEditFactory
+ \o QtDoubleSpinBoxFactory
+ \o QtEnumEditorFactory
+ \o QtLineEditFactory
+ \o QtScrollBarFactory
+ \o QtSliderFactory
+ \o QtSpinBoxFactory
+ \o QtTimeEditFactory
+ \o QtVariantEditorFactory
+ \endlist
+
+ When deriving from the QtAbstractEditorFactory class, several pure virtual
+ functions must be implemented: the connectPropertyManager() function is
+ used by the factory to connect to the given manager's signals, the
+ createEditor() function is supposed to create an editor for the
+ given property controlled by the given manager, and finally the
+ disconnectPropertyManager() function is used by the factory to disconnect
+ from the specified manager's signals.
+
+ \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager
+*/
+
+/*!
+ \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0)
+
+ Creates an editor factory with the given \a parent.
+
+ \sa addPropertyManager()
+*/
+
+/*!
+ \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent)
+
+ Creates an editing widget (with the given \a parent) for the given
+ \a property.
+*/
+
+/*!
+ \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager)
+
+ Adds the given \a manager to this factory's set of managers,
+ making this factory produce editing widgets for properties created
+ by the given manager.
+
+ The PropertyManager type is a template argument class, and represents the chosen
+ QtAbstractPropertyManager subclass.
+
+ \sa propertyManagers(), removePropertyManager()
+*/
+
+/*!
+ \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager)
+
+ Removes the given \a manager from this factory's set of
+ managers. The PropertyManager type is a template argument class, and may be
+ any QtAbstractPropertyManager subclass.
+
+ \sa propertyManagers(), addPropertyManager()
+*/
+
+/*!
+ \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0
+
+ Connects this factory to the given \a manager's signals. The
+ PropertyManager type is a template argument class, and represents
+ the chosen QtAbstractPropertyManager subclass.
+
+ This function is used internally by the addPropertyManager() function, and
+ makes it possible to update an editing widget when the associated
+ property's data changes. This is typically done in custom slots
+ responding to the signals emitted by the property's manager,
+ e.g. QtIntPropertyManager::valueChanged() and
+ QtIntPropertyManager::rangeChanged().
+
+ \sa propertyManagers(), disconnectPropertyManager()
+*/
+
+/*!
+ \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property,
+ QWidget *parent) = 0
+
+ Creates an editing widget with the given \a parent for the
+ specified \a property created by the given \a manager. The
+ PropertyManager type is a template argument class, and represents
+ the chosen QtAbstractPropertyManager subclass.
+
+ This function must be implemented in derived classes: It is
+ recommended to store a pointer to the widget and map it to the
+ given \a property, since the widget must be updated whenever the
+ associated property's data changes. This is typically done in
+ custom slots responding to the signals emitted by the property's
+ manager, e.g. QtIntPropertyManager::valueChanged() and
+ QtIntPropertyManager::rangeChanged().
+
+ \sa connectPropertyManager()
+*/
+
+/*!
+ \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0
+
+ Disconnects this factory from the given \a manager's signals. The
+ PropertyManager type is a template argument class, and represents
+ the chosen QtAbstractPropertyManager subclass.
+
+ This function is used internally by the removePropertyManager() function.
+
+ \sa propertyManagers(), connectPropertyManager()
+*/
+
+/*!
+ \fn QSet<PropertyManager *> QtAbstractEditorFactory::propertyManagers() const
+
+ Returns the factory's set of associated managers. The
+ PropertyManager type is a template argument class, and represents
+ the chosen QtAbstractPropertyManager subclass.
+
+ \sa addPropertyManager(), removePropertyManager()
+*/
+
+/*!
+ \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const
+
+ Returns the property manager for the given \a property, or 0 if
+ the given \a property doesn't belong to any of this factory's
+ registered managers.
+
+ The PropertyManager type is a template argument class, and represents the chosen
+ QtAbstractPropertyManager subclass.
+
+ \sa propertyManagers()
+*/
+
+/*!
+ \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager)
+
+ \internal
+ \reimp
+*/
+
+////////////////////////////////////
+class QtBrowserItemPrivate
+{
+public:
+ QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
+ : m_browser(browser), m_property(property), m_parent(parent), q_ptr(0) {}
+
+ void addChild(QtBrowserItem *index, QtBrowserItem *after);
+ void removeChild(QtBrowserItem *index);
+
+ QtAbstractPropertyBrowser * const m_browser;
+ QtProperty *m_property;
+ QtBrowserItem *m_parent;
+
+ QtBrowserItem *q_ptr;
+
+ QList<QtBrowserItem *> m_children;
+
+};
+
+void QtBrowserItemPrivate::addChild(QtBrowserItem *index, QtBrowserItem *after)
+{
+ if (m_children.contains(index))
+ return;
+ int idx = m_children.indexOf(after) + 1; // we insert after returned idx, if it was -1 then we set idx to 0;
+ m_children.insert(idx, index);
+}
+
+void QtBrowserItemPrivate::removeChild(QtBrowserItem *index)
+{
+ m_children.removeAll(index);
+}
+
+
+/*!
+ \class QtBrowserItem
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtBrowserItem class represents a property in
+ a property browser instance.
+
+ Browser items are created whenever a QtProperty is inserted to the
+ property browser. A QtBrowserItem uniquely identifies a
+ browser's item. Thus, if the same QtProperty is inserted multiple
+ times, each occurrence gets its own unique QtBrowserItem. The
+ items are owned by QtAbstractPropertyBrowser and automatically
+ deleted when they are removed from the browser.
+
+ You can traverse a browser's properties by calling parent() and
+ children(). The property and the browser associated with an item
+ are available as property() and browser().
+
+ \sa QtAbstractPropertyBrowser, QtProperty
+*/
+
+/*!
+ Returns the property which is accosiated with this item. Note that
+ several items can be associated with the same property instance in
+ the same property browser.
+
+ \sa QtAbstractPropertyBrowser::items()
+*/
+
+QtProperty *QtBrowserItem::property() const
+{
+ return d_ptr->m_property;
+}
+
+/*!
+ Returns the parent item of \e this item. Returns 0 if \e this item
+ is associated with top-level property in item's property browser.
+
+ \sa children()
+*/
+
+QtBrowserItem *QtBrowserItem::parent() const
+{
+ return d_ptr->m_parent;
+}
+
+/*!
+ Returns the children items of \e this item. The properties
+ reproduced from children items are always the same as
+ reproduced from associated property' children, for example:
+
+ \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 1
+
+ The \e childrenItems list represents the same list as \e childrenProperties.
+*/
+
+QList<QtBrowserItem *> QtBrowserItem::children() const
+{
+ return d_ptr->m_children;
+}
+
+/*!
+ Returns the property browser which owns \e this item.
+*/
+
+QtAbstractPropertyBrowser *QtBrowserItem::browser() const
+{
+ return d_ptr->m_browser;
+}
+
+QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent)
+{
+ d_ptr = new QtBrowserItemPrivate(browser, property, parent);
+ d_ptr->q_ptr = this;
+}
+
+QtBrowserItem::~QtBrowserItem()
+{
+ delete d_ptr;
+}
+
+
+////////////////////////////////////
+
+typedef QMap<QtAbstractPropertyBrowser *, QMap<QtAbstractPropertyManager *,
+ QtAbstractEditorFactoryBase *> > Map1;
+typedef QMap<QtAbstractPropertyManager *, QMap<QtAbstractEditorFactoryBase *,
+ QList<QtAbstractPropertyBrowser *> > > Map2;
+Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory)
+Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews)
+
+class QtAbstractPropertyBrowserPrivate
+{
+ QtAbstractPropertyBrowser *q_ptr;
+ Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser)
+public:
+ QtAbstractPropertyBrowserPrivate();
+
+ void insertSubTree(QtProperty *property,
+ QtProperty *parentProperty);
+ void removeSubTree(QtProperty *property,
+ QtProperty *parentProperty);
+ void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty);
+ void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty);
+ QtBrowserItem *createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex);
+ void removeBrowserIndex(QtBrowserItem *index);
+ void clearIndex(QtBrowserItem *index);
+
+ void slotPropertyInserted(QtProperty *property,
+ QtProperty *parentProperty, QtProperty *afterProperty);
+ void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty);
+ void slotPropertyDestroyed(QtProperty *property);
+ void slotPropertyDataChanged(QtProperty *property);
+
+ QList<QtProperty *> m_subItems;
+ QMap<QtAbstractPropertyManager *, QList<QtProperty *> > m_managerToProperties;
+ QMap<QtProperty *, QList<QtProperty *> > m_propertyToParents;
+
+ QMap<QtProperty *, QtBrowserItem *> m_topLevelPropertyToIndex;
+ QList<QtBrowserItem *> m_topLevelIndexes;
+ QMap<QtProperty *, QList<QtBrowserItem *> > m_propertyToIndexes;
+
+ QtBrowserItem *m_currentItem;
+};
+
+QtAbstractPropertyBrowserPrivate::QtAbstractPropertyBrowserPrivate() :
+ m_currentItem(0)
+{
+}
+
+void QtAbstractPropertyBrowserPrivate::insertSubTree(QtProperty *property,
+ QtProperty *parentProperty)
+{
+ if (m_propertyToParents.contains(property)) {
+ // property was already inserted, so its manager is connected
+ // and all its children are inserted and theirs managers are connected
+ // we just register new parent (parent has to be new).
+ m_propertyToParents[property].append(parentProperty);
+ // don't need to update m_managerToProperties map since
+ // m_managerToProperties[manager] already contains property.
+ return;
+ }
+ QtAbstractPropertyManager *manager = property->propertyManager();
+ if (m_managerToProperties[manager].isEmpty()) {
+ // connect manager's signals
+ q_ptr->connect(manager, SIGNAL(propertyInserted(QtProperty *,
+ QtProperty *, QtProperty *)),
+ q_ptr, SLOT(slotPropertyInserted(QtProperty *,
+ QtProperty *, QtProperty *)));
+ q_ptr->connect(manager, SIGNAL(propertyRemoved(QtProperty *,
+ QtProperty *)),
+ q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ q_ptr->connect(manager, SIGNAL(propertyDestroyed(QtProperty *)),
+ q_ptr, SLOT(slotPropertyDestroyed(QtProperty *)));
+ q_ptr->connect(manager, SIGNAL(propertyChanged(QtProperty *)),
+ q_ptr, SLOT(slotPropertyDataChanged(QtProperty *)));
+ }
+ m_managerToProperties[manager].append(property);
+ m_propertyToParents[property].append(parentProperty);
+
+ QList<QtProperty *> subList = property->subProperties();
+ QListIterator<QtProperty *> itSub(subList);
+ while (itSub.hasNext()) {
+ QtProperty *subProperty = itSub.next();
+ insertSubTree(subProperty, property);
+ }
+}
+
+void QtAbstractPropertyBrowserPrivate::removeSubTree(QtProperty *property,
+ QtProperty *parentProperty)
+{
+ if (!m_propertyToParents.contains(property)) {
+ // ASSERT
+ return;
+ }
+
+ m_propertyToParents[property].removeAll(parentProperty);
+ if (!m_propertyToParents[property].isEmpty())
+ return;
+
+ m_propertyToParents.remove(property);
+ QtAbstractPropertyManager *manager = property->propertyManager();
+ m_managerToProperties[manager].removeAll(property);
+ if (m_managerToProperties[manager].isEmpty()) {
+ // disconnect manager's signals
+ q_ptr->disconnect(manager, SIGNAL(propertyInserted(QtProperty *,
+ QtProperty *, QtProperty *)),
+ q_ptr, SLOT(slotPropertyInserted(QtProperty *,
+ QtProperty *, QtProperty *)));
+ q_ptr->disconnect(manager, SIGNAL(propertyRemoved(QtProperty *,
+ QtProperty *)),
+ q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ q_ptr->disconnect(manager, SIGNAL(propertyDestroyed(QtProperty *)),
+ q_ptr, SLOT(slotPropertyDestroyed(QtProperty *)));
+ q_ptr->disconnect(manager, SIGNAL(propertyChanged(QtProperty *)),
+ q_ptr, SLOT(slotPropertyDataChanged(QtProperty *)));
+
+ m_managerToProperties.remove(manager);
+ }
+
+ QList<QtProperty *> subList = property->subProperties();
+ QListIterator<QtProperty *> itSub(subList);
+ while (itSub.hasNext()) {
+ QtProperty *subProperty = itSub.next();
+ removeSubTree(subProperty, property);
+ }
+}
+
+void QtAbstractPropertyBrowserPrivate::createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty)
+{
+ QMap<QtBrowserItem *, QtBrowserItem *> parentToAfter;
+ if (afterProperty) {
+ QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+ m_propertyToIndexes.find(afterProperty);
+ if (it == m_propertyToIndexes.constEnd())
+ return;
+
+ QList<QtBrowserItem *> indexes = it.value();
+ QListIterator<QtBrowserItem *> itIndex(indexes);
+ while (itIndex.hasNext()) {
+ QtBrowserItem *idx = itIndex.next();
+ QtBrowserItem *parentIdx = idx->parent();
+ if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
+ parentToAfter[idx->parent()] = idx;
+ }
+ } else if (parentProperty) {
+ QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+ m_propertyToIndexes.find(parentProperty);
+ if (it == m_propertyToIndexes.constEnd())
+ return;
+
+ QList<QtBrowserItem *> indexes = it.value();
+ QListIterator<QtBrowserItem *> itIndex(indexes);
+ while (itIndex.hasNext()) {
+ QtBrowserItem *idx = itIndex.next();
+ parentToAfter[idx] = 0;
+ }
+ } else {
+ parentToAfter[0] = 0;
+ }
+
+ const QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator pcend = parentToAfter.constEnd();
+ for (QMap<QtBrowserItem *, QtBrowserItem *>::ConstIterator it = parentToAfter.constBegin(); it != pcend; ++it)
+ createBrowserIndex(property, it.key(), it.value());
+}
+
+QtBrowserItem *QtAbstractPropertyBrowserPrivate::createBrowserIndex(QtProperty *property,
+ QtBrowserItem *parentIndex, QtBrowserItem *afterIndex)
+{
+ QtBrowserItem *newIndex = new QtBrowserItem(q_ptr, property, parentIndex);
+ if (parentIndex) {
+ parentIndex->d_ptr->addChild(newIndex, afterIndex);
+ } else {
+ m_topLevelPropertyToIndex[property] = newIndex;
+ m_topLevelIndexes.insert(m_topLevelIndexes.indexOf(afterIndex) + 1, newIndex);
+ }
+ m_propertyToIndexes[property].append(newIndex);
+
+ q_ptr->itemInserted(newIndex, afterIndex);
+
+ QList<QtProperty *> subItems = property->subProperties();
+ QListIterator<QtProperty *> itChild(subItems);
+ QtBrowserItem *afterChild = 0;
+ while (itChild.hasNext()) {
+ QtProperty *child = itChild.next();
+ afterChild = createBrowserIndex(child, newIndex, afterChild);
+ }
+ return newIndex;
+}
+
+void QtAbstractPropertyBrowserPrivate::removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty)
+{
+ QList<QtBrowserItem *> toRemove;
+ QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+ m_propertyToIndexes.find(property);
+ if (it == m_propertyToIndexes.constEnd())
+ return;
+
+ QList<QtBrowserItem *> indexes = it.value();
+ QListIterator<QtBrowserItem *> itIndex(indexes);
+ while (itIndex.hasNext()) {
+ QtBrowserItem *idx = itIndex.next();
+ QtBrowserItem *parentIdx = idx->parent();
+ if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx))
+ toRemove.append(idx);
+ }
+
+ QListIterator<QtBrowserItem *> itRemove(toRemove);
+ while (itRemove.hasNext()) {
+ QtBrowserItem *index = itRemove.next();
+ removeBrowserIndex(index);
+ }
+}
+
+void QtAbstractPropertyBrowserPrivate::removeBrowserIndex(QtBrowserItem *index)
+{
+ QList<QtBrowserItem *> children = index->children();
+ for (int i = children.count(); i > 0; i--) {
+ removeBrowserIndex(children.at(i - 1));
+ }
+
+ q_ptr->itemRemoved(index);
+
+ if (index->parent()) {
+ index->parent()->d_ptr->removeChild(index);
+ } else {
+ m_topLevelPropertyToIndex.remove(index->property());
+ m_topLevelIndexes.removeAll(index);
+ }
+
+ QtProperty *property = index->property();
+
+ m_propertyToIndexes[property].removeAll(index);
+ if (m_propertyToIndexes[property].isEmpty())
+ m_propertyToIndexes.remove(property);
+
+ delete index;
+}
+
+void QtAbstractPropertyBrowserPrivate::clearIndex(QtBrowserItem *index)
+{
+ QList<QtBrowserItem *> children = index->children();
+ QListIterator<QtBrowserItem *> itChild(children);
+ while (itChild.hasNext()) {
+ clearIndex(itChild.next());
+ }
+ delete index;
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyInserted(QtProperty *property,
+ QtProperty *parentProperty, QtProperty *afterProperty)
+{
+ if (!m_propertyToParents.contains(parentProperty))
+ return;
+ createBrowserIndexes(property, parentProperty, afterProperty);
+ insertSubTree(property, parentProperty);
+ //q_ptr->propertyInserted(property, parentProperty, afterProperty);
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyRemoved(QtProperty *property,
+ QtProperty *parentProperty)
+{
+ if (!m_propertyToParents.contains(parentProperty))
+ return;
+ removeSubTree(property, parentProperty); // this line should be probably moved down after propertyRemoved call
+ //q_ptr->propertyRemoved(property, parentProperty);
+ removeBrowserIndexes(property, parentProperty);
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (!m_subItems.contains(property))
+ return;
+ q_ptr->removeProperty(property);
+}
+
+void QtAbstractPropertyBrowserPrivate::slotPropertyDataChanged(QtProperty *property)
+{
+ if (!m_propertyToParents.contains(property))
+ return;
+
+ QMap<QtProperty *, QList<QtBrowserItem *> >::ConstIterator it =
+ m_propertyToIndexes.find(property);
+ if (it == m_propertyToIndexes.constEnd())
+ return;
+
+ QList<QtBrowserItem *> indexes = it.value();
+ QListIterator<QtBrowserItem *> itIndex(indexes);
+ while (itIndex.hasNext()) {
+ QtBrowserItem *idx = itIndex.next();
+ q_ptr->itemChanged(idx);
+ }
+ //q_ptr->propertyChanged(property);
+}
+
+/*!
+ \class QtAbstractPropertyBrowser
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief QtAbstractPropertyBrowser provides a base class for
+ implementing property browsers.
+
+ A property browser is a widget that enables the user to edit a
+ given set of properties. Each property is represented by a label
+ specifying the property's name, and an editing widget (e.g. a line
+ edit or a combobox) holding its value. A property can have zero or
+ more subproperties.
+
+ \image qtpropertybrowser.png
+
+ The top level properties can be retrieved using the
+ properties() function. To traverse each property's
+ subproperties, use the QtProperty::subProperties() function. In
+ addition, the set of top level properties can be manipulated using
+ the addProperty(), insertProperty() and removeProperty()
+ functions. Note that the QtProperty class provides a corresponding
+ set of functions making it possible to manipulate the set of
+ subproperties as well.
+
+ To remove all the properties from the property browser widget, use
+ the clear() function. This function will clear the editor, but it
+ will not delete the properties since they can still be used in
+ other editors.
+
+ The properties themselves are created and managed by
+ implementations of the QtAbstractPropertyManager class. A manager
+ can handle (i.e. create and manage) properties of a given type. In
+ the property browser the managers are associated with
+ implementations of the QtAbstractEditorFactory: A factory is a
+ class able to create an editing widget of a specified type.
+
+ When using a property browser widget, managers must be created for
+ each of the required property types before the properties
+ themselves can be created. To ensure that the properties' values
+ will be displayed using suitable editing widgets, the managers
+ must be associated with objects of the preferred factory
+ implementations using the setFactoryForManager() function. The
+ property browser will use these associations to determine which
+ factory it should use to create the preferred editing widget.
+
+ Note that a factory can be associated with many managers, but a
+ manager can only be associated with one single factory within the
+ context of a single property browser. The associations between
+ managers and factories can at any time be removed using the
+ unsetFactoryForManager() function.
+
+ Whenever the property data changes or a property is inserted or
+ removed, the itemChanged(), itemInserted() or
+ itemRemoved() functions are called, respectively. These
+ functions must be reimplemented in derived classes in order to
+ update the property browser widget. Be aware that some property
+ instances can appear several times in an abstract tree
+ structure. For example:
+
+ \table 100%
+ \row
+ \o
+ \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 2
+ \o \image qtpropertybrowser-duplicate.png
+ \endtable
+
+ The addProperty() function returns a QtBrowserItem that uniquely
+ identifies the created item.
+
+ To make a property editable in the property browser, the
+ createEditor() function must be called to provide the
+ property with a suitable editing widget.
+
+ Note that there are two ready-made property browser
+ implementations:
+
+ \list
+ \o QtGroupBoxPropertyBrowser
+ \o QtTreePropertyBrowser
+ \endlist
+
+ \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase
+*/
+
+/*!
+ \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager,
+ QtAbstractEditorFactory<PropertyManager> *factory)
+
+ Connects the given \a manager to the given \a factory, ensuring
+ that properties of the \a manager's type will be displayed with an
+ editing widget suitable for their value.
+
+ For example:
+
+ \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtpropertybrowser.cpp 3
+
+ In this example the \c myInteger property's value is displayed
+ with a QSpinBox widget, while the \c myDouble property's value is
+ displayed with a QDoubleSpinBox widget.
+
+ Note that a factory can be associated with many managers, but a
+ manager can only be associated with one single factory. If the
+ given \a manager already is associated with another factory, the
+ old association is broken before the new one established.
+
+ This function ensures that the given \a manager and the given \a
+ factory are compatible, and it automatically calls the
+ QtAbstractEditorFactory::addPropertyManager() function if necessary.
+
+ \sa unsetFactoryForManager()
+*/
+
+/*!
+ \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem,
+ QtBrowserItem *precedingItem) = 0
+
+ This function is called to update the widget whenever a property
+ is inserted or added to the property browser, passing pointers to
+ the \a insertedItem of property and the specified
+ \a precedingItem as parameters.
+
+ If \a precedingItem is 0, the \a insertedItem was put at
+ the beginning of its parent item's list of subproperties. If
+ the parent of \a insertedItem is 0, the \a insertedItem was added as a top
+ level property of \e this property browser.
+
+ This function must be reimplemented in derived classes. Note that
+ if the \a insertedItem's property has subproperties, this
+ method will be called for those properties as soon as the current call is finished.
+
+ \sa insertProperty(), addProperty()
+*/
+
+/*!
+ \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0
+
+ This function is called to update the widget whenever a property
+ is removed from the property browser, passing the pointer to the
+ \a item of the property as parameters. The passed \a item is
+ deleted just after this call is finished.
+
+ If the the parent of \a item is 0, the removed \a item was a
+ top level property in this editor.
+
+ This function must be reimplemented in derived classes. Note that
+ if the removed \a item's property has subproperties, this
+ method will be called for those properties just before the current call is started.
+
+ \sa removeProperty()
+*/
+
+/*!
+ \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0
+
+ This function is called whenever a property's data changes,
+ passing a pointer to the \a item of property as parameter.
+
+ This function must be reimplemented in derived classes in order to
+ update the property browser widget whenever a property's name,
+ tool tip, status tip, "what's this" text, value text or value icon
+ changes.
+
+ Note that if the property browser contains several occurrences of
+ the same property, this method will be called once for each
+ occurrence (with a different item each time).
+
+ \sa QtProperty, items()
+*/
+
+/*!
+ Creates an abstract property browser with the given \a parent.
+*/
+QtAbstractPropertyBrowser::QtAbstractPropertyBrowser(QWidget *parent)
+ : QWidget(parent)
+{
+ d_ptr = new QtAbstractPropertyBrowserPrivate;
+ d_ptr->q_ptr = this;
+
+}
+
+/*!
+ Destroys the property browser, and destroys all the items that were
+ created by this property browser.
+
+ Note that the properties that were displayed in the editor are not
+ deleted since they still can be used in other editors. Neither
+ does the destructor delete the property managers and editor
+ factories that were used by this property browser widget unless
+ this widget was their parent.
+
+ \sa QtAbstractPropertyManager::~QtAbstractPropertyManager()
+*/
+QtAbstractPropertyBrowser::~QtAbstractPropertyBrowser()
+{
+ QList<QtBrowserItem *> indexes = topLevelItems();
+ QListIterator<QtBrowserItem *> itItem(indexes);
+ while (itItem.hasNext())
+ d_ptr->clearIndex(itItem.next());
+ delete d_ptr;
+}
+
+/*!
+ Returns the property browser's list of top level properties.
+
+ To traverse the subproperties, use the QtProperty::subProperties()
+ function.
+
+ \sa addProperty(), insertProperty(), removeProperty()
+*/
+QList<QtProperty *> QtAbstractPropertyBrowser::properties() const
+{
+ return d_ptr->m_subItems;
+}
+
+/*!
+ Returns the property browser's list of all items associated
+ with the given \a property.
+
+ There is one item per instance of the property in the browser.
+
+ \sa topLevelItem()
+*/
+
+QList<QtBrowserItem *> QtAbstractPropertyBrowser::items(QtProperty *property) const
+{
+ return d_ptr->m_propertyToIndexes.value(property);
+}
+
+/*!
+ Returns the top-level items associated with the given \a property.
+
+ Returns 0 if \a property wasn't inserted into this property
+ browser or isn't a top-level one.
+
+ \sa topLevelItems(), items()
+*/
+
+QtBrowserItem *QtAbstractPropertyBrowser::topLevelItem(QtProperty *property) const
+{
+ return d_ptr->m_topLevelPropertyToIndex.value(property);
+}
+
+/*!
+ Returns the list of top-level items.
+
+ \sa topLevelItem()
+*/
+
+QList<QtBrowserItem *> QtAbstractPropertyBrowser::topLevelItems() const
+{
+ return d_ptr->m_topLevelIndexes;
+}
+
+/*!
+ Removes all the properties from the editor, but does not delete
+ them since they can still be used in other editors.
+
+ \sa removeProperty(), QtAbstractPropertyManager::clear()
+*/
+void QtAbstractPropertyBrowser::clear()
+{
+ QList<QtProperty *> subList = properties();
+ QListIterator<QtProperty *> itSub(subList);
+ itSub.toBack();
+ while (itSub.hasPrevious()) {
+ QtProperty *property = itSub.previous();
+ removeProperty(property);
+ }
+}
+
+/*!
+ Appends the given \a property (and its subproperties) to the
+ property browser's list of top level properties. Returns the item
+ created by property browser which is associated with the \a property.
+ In order to get all children items created by the property
+ browser in this call, the returned item should be traversed.
+
+ If the specified \a property is already added, this function does
+ nothing and returns 0.
+
+ \sa insertProperty(), QtProperty::addSubProperty(), properties()
+*/
+QtBrowserItem *QtAbstractPropertyBrowser::addProperty(QtProperty *property)
+{
+ QtProperty *afterProperty = 0;
+ if (d_ptr->m_subItems.count() > 0)
+ afterProperty = d_ptr->m_subItems.last();
+ return insertProperty(property, afterProperty);
+}
+
+/*!
+ \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
+ QtProperty *afterProperty)
+
+ Inserts the given \a property (and its subproperties) after
+ the specified \a afterProperty in the browser's list of top
+ level properties. Returns item created by property browser which
+ is associated with the \a property. In order to get all children items
+ created by the property browser in this call returned item should be traversed.
+
+ If the specified \a afterProperty is 0, the given \a property is
+ inserted at the beginning of the list. If \a property is
+ already inserted, this function does nothing and returns 0.
+
+ \sa addProperty(), QtProperty::insertSubProperty(), properties()
+*/
+QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property,
+ QtProperty *afterProperty)
+{
+ if (!property)
+ return 0;
+
+ // if item is already inserted in this item then cannot add.
+ QList<QtProperty *> pendingList = properties();
+ int pos = 0;
+ int newPos = 0;
+ QtProperty *properAfterProperty = 0;
+ while (pos < pendingList.count()) {
+ QtProperty *prop = pendingList.at(pos);
+ if (prop == property)
+ return 0;
+ if (prop == afterProperty) {
+ newPos = pos + 1;
+ properAfterProperty = afterProperty;
+ }
+ pos++;
+ }
+ d_ptr->createBrowserIndexes(property, 0, afterProperty);
+
+ // traverse inserted subtree and connect to manager's signals
+ d_ptr->insertSubTree(property, 0);
+
+ d_ptr->m_subItems.insert(newPos, property);
+ //propertyInserted(property, 0, properAfterProperty);
+ return topLevelItem(property);
+}
+
+/*!
+ Removes the specified \a property (and its subproperties) from the
+ property browser's list of top level properties. All items
+ that were associated with the given \a property and its children
+ are deleted.
+
+ Note that the properties are \e not deleted since they can still
+ be used in other editors.
+
+ \sa clear(), QtProperty::removeSubProperty(), properties()
+*/
+void QtAbstractPropertyBrowser::removeProperty(QtProperty *property)
+{
+ if (!property)
+ return;
+
+ QList<QtProperty *> pendingList = properties();
+ int pos = 0;
+ while (pos < pendingList.count()) {
+ if (pendingList.at(pos) == property) {
+ d_ptr->m_subItems.removeAt(pos); //perhaps this two lines
+ d_ptr->removeSubTree(property, 0); //should be moved down after propertyRemoved call.
+ //propertyRemoved(property, 0);
+
+ d_ptr->removeBrowserIndexes(property, 0);
+
+ // when item is deleted, item will call removeItem for top level items,
+ // and itemRemoved for nested items.
+
+ return;
+ }
+ pos++;
+ }
+}
+
+/*!
+ Creates an editing widget (with the given \a parent) for the given
+ \a property according to the previously established associations
+ between property managers and editor factories.
+
+ If the property is created by a property manager which was not
+ associated with any of the existing factories in \e this property
+ editor, the function returns 0.
+
+ To make a property editable in the property browser, the
+ createEditor() function must be called to provide the
+ property with a suitable editing widget.
+
+ Reimplement this function to provide additional decoration for the
+ editing widgets created by the installed factories.
+
+ \sa setFactoryForManager()
+*/
+QWidget *QtAbstractPropertyBrowser::createEditor(QtProperty *property,
+ QWidget *parent)
+{
+ QtAbstractEditorFactoryBase *factory = 0;
+ QtAbstractPropertyManager *manager = property->propertyManager();
+
+ if (m_viewToManagerToFactory()->contains(this) &&
+ (*m_viewToManagerToFactory())[this].contains(manager)) {
+ factory = (*m_viewToManagerToFactory())[this][manager];
+ }
+
+ if (!factory)
+ return 0;
+ return factory->createEditor(property, parent);
+}
+
+bool QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager *abstractManager,
+ QtAbstractEditorFactoryBase *abstractFactory)
+{
+ bool connectNeeded = false;
+ if (!m_managerToFactoryToViews()->contains(abstractManager) ||
+ !(*m_managerToFactoryToViews())[abstractManager].contains(abstractFactory)) {
+ connectNeeded = true;
+ } else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory]
+ .contains(this)) {
+ return connectNeeded;
+ }
+
+ if (m_viewToManagerToFactory()->contains(this) &&
+ (*m_viewToManagerToFactory())[this].contains(abstractManager)) {
+ unsetFactoryForManager(abstractManager);
+ }
+
+ (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(this);
+ (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory;
+
+ return connectNeeded;
+}
+
+/*!
+ Removes the association between the given \a manager and the
+ factory bound to it, automatically calling the
+ QtAbstractEditorFactory::removePropertyManager() function if necessary.
+
+ \sa setFactoryForManager()
+*/
+void QtAbstractPropertyBrowser::unsetFactoryForManager(QtAbstractPropertyManager *manager)
+{
+ if (!m_viewToManagerToFactory()->contains(this) ||
+ !(*m_viewToManagerToFactory())[this].contains(manager)) {
+ return;
+ }
+
+ QtAbstractEditorFactoryBase *abstractFactory =
+ (*m_viewToManagerToFactory())[this][manager];
+ (*m_viewToManagerToFactory())[this].remove(manager);
+ if ((*m_viewToManagerToFactory())[this].isEmpty()) {
+ (*m_viewToManagerToFactory()).remove(this);
+ }
+
+ (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(this);
+ if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty()) {
+ (*m_managerToFactoryToViews())[manager].remove(abstractFactory);
+ abstractFactory->breakConnection(manager);
+ if ((*m_managerToFactoryToViews())[manager].isEmpty()) {
+ (*m_managerToFactoryToViews()).remove(manager);
+ }
+ }
+}
+
+/*!
+ Returns the current item in the property browser.
+
+ \sa setCurrentItem()
+*/
+QtBrowserItem *QtAbstractPropertyBrowser::currentItem() const
+{
+ return d_ptr->m_currentItem;
+}
+
+/*!
+ Sets the current item in the property browser to \a item.
+
+ \sa currentItem(), currentItemChanged()
+*/
+void QtAbstractPropertyBrowser::setCurrentItem(QtBrowserItem *item)
+{
+ QtBrowserItem *oldItem = d_ptr->m_currentItem;
+ d_ptr->m_currentItem = item;
+ if (oldItem != item)
+ emit currentItemChanged(item);
+}
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#include "moc_qtpropertybrowser.cpp"
diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowser.h b/tools/shared/qtpropertybrowser/qtpropertybrowser.h
new file mode 100644
index 0000000000..649a9e3931
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertybrowser.h
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTPROPERTYBROWSER_H
+#define QTPROPERTYBROWSER_H
+
+#include <QtGui/QWidget>
+#include <QtCore/QSet>
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+
+
+class QtAbstractPropertyManager;
+class QtPropertyPrivate;
+
+class QtProperty
+{
+public:
+ virtual ~QtProperty();
+
+ QList<QtProperty *> subProperties() const;
+
+ QtAbstractPropertyManager *propertyManager() const;
+
+ QString toolTip() const;
+ QString statusTip() const;
+ QString whatsThis() const;
+ QString propertyName() const;
+ bool isEnabled() const;
+ bool isModified() const;
+
+ bool hasValue() const;
+ QIcon valueIcon() const;
+ QString valueText() const;
+
+ void setToolTip(const QString &text);
+ void setStatusTip(const QString &text);
+ void setWhatsThis(const QString &text);
+ void setPropertyName(const QString &text);
+ void setEnabled(bool enable);
+ void setModified(bool modified);
+
+ void addSubProperty(QtProperty *property);
+ void insertSubProperty(QtProperty *property, QtProperty *afterProperty);
+ void removeSubProperty(QtProperty *property);
+protected:
+ explicit QtProperty(QtAbstractPropertyManager *manager);
+ void propertyChanged();
+private:
+ friend class QtAbstractPropertyManager;
+ QtPropertyPrivate *d_ptr;
+};
+
+class QtAbstractPropertyManagerPrivate;
+
+class QtAbstractPropertyManager : public QObject
+{
+ Q_OBJECT
+public:
+
+ explicit QtAbstractPropertyManager(QObject *parent = 0);
+ ~QtAbstractPropertyManager();
+
+ QSet<QtProperty *> properties() const;
+ void clear() const;
+
+ QtProperty *addProperty(const QString &name = QString());
+Q_SIGNALS:
+
+ void propertyInserted(QtProperty *property,
+ QtProperty *parent, QtProperty *after);
+ void propertyChanged(QtProperty *property);
+ void propertyRemoved(QtProperty *property, QtProperty *parent);
+ void propertyDestroyed(QtProperty *property);
+protected:
+ virtual bool hasValue(const QtProperty *property) const;
+ virtual QIcon valueIcon(const QtProperty *property) const;
+ virtual QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property) = 0;
+ virtual void uninitializeProperty(QtProperty *property);
+ virtual QtProperty *createProperty();
+private:
+ friend class QtProperty;
+ QtAbstractPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtAbstractPropertyManager)
+ Q_DISABLE_COPY(QtAbstractPropertyManager)
+};
+
+class QtAbstractEditorFactoryBase : public QObject
+{
+ Q_OBJECT
+public:
+ virtual QWidget *createEditor(QtProperty *property, QWidget *parent) = 0;
+protected:
+ explicit QtAbstractEditorFactoryBase(QObject *parent = 0)
+ : QObject(parent) {}
+
+ virtual void breakConnection(QtAbstractPropertyManager *manager) = 0;
+protected Q_SLOTS:
+ virtual void managerDestroyed(QObject *manager) = 0;
+
+ friend class QtAbstractPropertyBrowser;
+};
+
+template <class PropertyManager>
+class QtAbstractEditorFactory : public QtAbstractEditorFactoryBase
+{
+public:
+ explicit QtAbstractEditorFactory(QObject *parent) : QtAbstractEditorFactoryBase(parent) {}
+ QWidget *createEditor(QtProperty *property, QWidget *parent)
+ {
+ QSetIterator<PropertyManager *> it(m_managers);
+ while (it.hasNext()) {
+ PropertyManager *manager = it.next();
+ if (manager == property->propertyManager()) {
+ return createEditor(manager, property, parent);
+ }
+ }
+ return 0;
+ }
+ void addPropertyManager(PropertyManager *manager)
+ {
+ if (m_managers.contains(manager))
+ return;
+ m_managers.insert(manager);
+ connectPropertyManager(manager);
+ connect(manager, SIGNAL(destroyed(QObject *)),
+ this, SLOT(managerDestroyed(QObject *)));
+ }
+ void removePropertyManager(PropertyManager *manager)
+ {
+ if (!m_managers.contains(manager))
+ return;
+ disconnect(manager, SIGNAL(destroyed(QObject *)),
+ this, SLOT(managerDestroyed(QObject *)));
+ disconnectPropertyManager(manager);
+ m_managers.remove(manager);
+ }
+ QSet<PropertyManager *> propertyManagers() const
+ {
+ return m_managers;
+ }
+ PropertyManager *propertyManager(QtProperty *property) const
+ {
+ QtAbstractPropertyManager *manager = property->propertyManager();
+ QSetIterator<PropertyManager *> itManager(m_managers);
+ while (itManager.hasNext()) {
+ PropertyManager *m = itManager.next();
+ if (m == manager) {
+ return m;
+ }
+ }
+ return 0;
+ }
+protected:
+ virtual void connectPropertyManager(PropertyManager *manager) = 0;
+ virtual QWidget *createEditor(PropertyManager *manager, QtProperty *property,
+ QWidget *parent) = 0;
+ virtual void disconnectPropertyManager(PropertyManager *manager) = 0;
+ void managerDestroyed(QObject *manager)
+ {
+ QSetIterator<PropertyManager *> it(m_managers);
+ while (it.hasNext()) {
+ PropertyManager *m = it.next();
+ if (m == manager) {
+ m_managers.remove(m);
+ return;
+ }
+ }
+ }
+private:
+ void breakConnection(QtAbstractPropertyManager *manager)
+ {
+ QSetIterator<PropertyManager *> it(m_managers);
+ while (it.hasNext()) {
+ PropertyManager *m = it.next();
+ if (m == manager) {
+ removePropertyManager(m);
+ return;
+ }
+ }
+ }
+private:
+ QSet<PropertyManager *> m_managers;
+ friend class QtAbstractPropertyEditor;
+};
+
+class QtAbstractPropertyBrowser;
+class QtBrowserItemPrivate;
+
+class QtBrowserItem
+{
+public:
+ QtProperty *property() const;
+ QtBrowserItem *parent() const;
+ QList<QtBrowserItem *> children() const;
+ QtAbstractPropertyBrowser *browser() const;
+private:
+ explicit QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent);
+ ~QtBrowserItem();
+ QtBrowserItemPrivate *d_ptr;
+ friend class QtAbstractPropertyBrowserPrivate;
+};
+
+class QtAbstractPropertyBrowserPrivate;
+
+class QtAbstractPropertyBrowser : public QWidget
+{
+ Q_OBJECT
+public:
+
+ explicit QtAbstractPropertyBrowser(QWidget *parent = 0);
+ ~QtAbstractPropertyBrowser();
+
+ QList<QtProperty *> properties() const;
+ QList<QtBrowserItem *> items(QtProperty *property) const;
+ QtBrowserItem *topLevelItem(QtProperty *property) const;
+ QList<QtBrowserItem *> topLevelItems() const;
+ void clear();
+
+ template <class PropertyManager>
+ void setFactoryForManager(PropertyManager *manager,
+ QtAbstractEditorFactory<PropertyManager> *factory) {
+ QtAbstractPropertyManager *abstractManager = manager;
+ QtAbstractEditorFactoryBase *abstractFactory = factory;
+
+ if (addFactory(abstractManager, abstractFactory))
+ factory->addPropertyManager(manager);
+ }
+
+ void unsetFactoryForManager(QtAbstractPropertyManager *manager);
+
+ QtBrowserItem *currentItem() const;
+ void setCurrentItem(QtBrowserItem *);
+
+Q_SIGNALS:
+ void currentItemChanged(QtBrowserItem *);
+
+public Q_SLOTS:
+
+ QtBrowserItem *addProperty(QtProperty *property);
+ QtBrowserItem *insertProperty(QtProperty *property, QtProperty *afterProperty);
+ void removeProperty(QtProperty *property);
+
+protected:
+
+ virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) = 0;
+ virtual void itemRemoved(QtBrowserItem *item) = 0;
+ // can be tooltip, statustip, whatsthis, name, icon, text.
+ virtual void itemChanged(QtBrowserItem *item) = 0;
+
+ virtual QWidget *createEditor(QtProperty *property, QWidget *parent);
+private:
+
+ bool addFactory(QtAbstractPropertyManager *abstractManager,
+ QtAbstractEditorFactoryBase *abstractFactory);
+
+ QtAbstractPropertyBrowserPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtAbstractPropertyBrowser)
+ Q_DISABLE_COPY(QtAbstractPropertyBrowser)
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *,
+ QtProperty *, QtProperty *))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *,
+ QtProperty *))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDataChanged(QtProperty *))
+
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#endif // QTPROPERTYBROWSER_H
diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowser.pri b/tools/shared/qtpropertybrowser/qtpropertybrowser.pri
new file mode 100644
index 0000000000..85c2b8d705
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertybrowser.pri
@@ -0,0 +1,19 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+SOURCES += $$PWD/qtpropertybrowser.cpp \
+ $$PWD/qtpropertymanager.cpp \
+ $$PWD/qteditorfactory.cpp \
+ $$PWD/qtvariantproperty.cpp \
+ $$PWD/qttreepropertybrowser.cpp \
+ $$PWD/qtbuttonpropertybrowser.cpp \
+ $$PWD/qtgroupboxpropertybrowser.cpp \
+ $$PWD/qtpropertybrowserutils.cpp
+HEADERS += $$PWD/qtpropertybrowser.h \
+ $$PWD/qtpropertymanager.h \
+ $$PWD/qteditorfactory.h \
+ $$PWD/qtvariantproperty.h \
+ $$PWD/qttreepropertybrowser.h \
+ $$PWD/qtbuttonpropertybrowser.h \
+ $$PWD/qtgroupboxpropertybrowser.h \
+ $$PWD/qtpropertybrowserutils_p.h
+RESOURCES += $$PWD/qtpropertybrowser.qrc
diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowser.qrc b/tools/shared/qtpropertybrowser/qtpropertybrowser.qrc
new file mode 100644
index 0000000000..4f91ab782c
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertybrowser.qrc
@@ -0,0 +1,23 @@
+<RCC version="1.0">
+ <qresource prefix="/trolltech/qtpropertybrowser">
+ <file>images/cursor-arrow.png</file>
+ <file>images/cursor-busy.png</file>
+ <file>images/cursor-closedhand.png</file>
+ <file>images/cursor-cross.png</file>
+ <file>images/cursor-forbidden.png</file>
+ <file>images/cursor-hand.png</file>
+ <file>images/cursor-hsplit.png</file>
+ <file>images/cursor-ibeam.png</file>
+ <file>images/cursor-openhand.png</file>
+ <file>images/cursor-sizeall.png</file>
+ <file>images/cursor-sizeb.png</file>
+ <file>images/cursor-sizef.png</file>
+ <file>images/cursor-sizeh.png</file>
+ <file>images/cursor-sizev.png</file>
+ <file>images/cursor-uparrow.png</file>
+ <file>images/cursor-vsplit.png</file>
+ <file>images/cursor-wait.png</file>
+ <file>images/cursor-whatsthis.png</file>
+ </qresource>
+</RCC>
+
diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowserutils.cpp b/tools/shared/qtpropertybrowser/qtpropertybrowserutils.cpp
new file mode 100644
index 0000000000..d689e603a0
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertybrowserutils.cpp
@@ -0,0 +1,434 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtpropertybrowserutils_p.h"
+#include <QtGui/QApplication>
+#include <QtGui/QPainter>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QMouseEvent>
+#include <QtGui/QCheckBox>
+#include <QtGui/QLineEdit>
+#include <QtGui/QMenu>
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+QtCursorDatabase::QtCursorDatabase()
+{
+ appendCursor(Qt::ArrowCursor, QApplication::translate("QtCursorDatabase", "Arrow", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-arrow.png")));
+ appendCursor(Qt::UpArrowCursor, QApplication::translate("QtCursorDatabase", "Up Arrow", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-uparrow.png")));
+ appendCursor(Qt::CrossCursor, QApplication::translate("QtCursorDatabase", "Cross", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-cross.png")));
+ appendCursor(Qt::WaitCursor, QApplication::translate("QtCursorDatabase", "Wait", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-wait.png")));
+ appendCursor(Qt::IBeamCursor, QApplication::translate("QtCursorDatabase", "IBeam", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-ibeam.png")));
+ appendCursor(Qt::SizeVerCursor, QApplication::translate("QtCursorDatabase", "Size Vertical", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-sizev.png")));
+ appendCursor(Qt::SizeHorCursor, QApplication::translate("QtCursorDatabase", "Size Horizontal", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-sizeh.png")));
+ appendCursor(Qt::SizeFDiagCursor, QApplication::translate("QtCursorDatabase", "Size Backslash", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-sizef.png")));
+ appendCursor(Qt::SizeBDiagCursor, QApplication::translate("QtCursorDatabase", "Size Slash", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-sizeb.png")));
+ appendCursor(Qt::SizeAllCursor, QApplication::translate("QtCursorDatabase", "Size All", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-sizeall.png")));
+ appendCursor(Qt::BlankCursor, QApplication::translate("QtCursorDatabase", "Blank", 0,
+ QApplication::UnicodeUTF8), QIcon());
+ appendCursor(Qt::SplitVCursor, QApplication::translate("QtCursorDatabase", "Split Vertical", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-vsplit.png")));
+ appendCursor(Qt::SplitHCursor, QApplication::translate("QtCursorDatabase", "Split Horizontal", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-hsplit.png")));
+ appendCursor(Qt::PointingHandCursor, QApplication::translate("QtCursorDatabase", "Pointing Hand", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-hand.png")));
+ appendCursor(Qt::ForbiddenCursor, QApplication::translate("QtCursorDatabase", "Forbidden", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-forbidden.png")));
+ appendCursor(Qt::OpenHandCursor, QApplication::translate("QtCursorDatabase", "Open Hand", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-openhand.png")));
+ appendCursor(Qt::ClosedHandCursor, QApplication::translate("QtCursorDatabase", "Closed Hand", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-closedhand.png")));
+ appendCursor(Qt::WhatsThisCursor, QApplication::translate("QtCursorDatabase", "What's This", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-whatsthis.png")));
+ appendCursor(Qt::BusyCursor, QApplication::translate("QtCursorDatabase", "Busy", 0,
+ QApplication::UnicodeUTF8), QIcon(QLatin1String(":/trolltech/qtpropertybrowser/images/cursor-busy.png")));
+}
+
+void QtCursorDatabase::appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon)
+{
+ if (m_cursorShapeToValue.contains(shape))
+ return;
+ int value = m_cursorNames.count();
+ m_cursorNames.append(name);
+ m_cursorIcons[value] = icon;
+ m_valueToCursorShape[value] = shape;
+ m_cursorShapeToValue[shape] = value;
+}
+
+QStringList QtCursorDatabase::cursorShapeNames() const
+{
+ return m_cursorNames;
+}
+
+QMap<int, QIcon> QtCursorDatabase::cursorShapeIcons() const
+{
+ return m_cursorIcons;
+}
+
+QString QtCursorDatabase::cursorToShapeName(const QCursor &cursor) const
+{
+ int val = cursorToValue(cursor);
+ if (val >= 0)
+ return m_cursorNames.at(val);
+ return QString();
+}
+
+QIcon QtCursorDatabase::cursorToShapeIcon(const QCursor &cursor) const
+{
+ int val = cursorToValue(cursor);
+ return m_cursorIcons.value(val);
+}
+
+int QtCursorDatabase::cursorToValue(const QCursor &cursor) const
+{
+#ifndef QT_NO_CURSOR
+ Qt::CursorShape shape = cursor.shape();
+ if (m_cursorShapeToValue.contains(shape))
+ return m_cursorShapeToValue[shape];
+#endif
+ return -1;
+}
+
+#ifndef QT_NO_CURSOR
+QCursor QtCursorDatabase::valueToCursor(int value) const
+{
+ if (m_valueToCursorShape.contains(value))
+ return QCursor(m_valueToCursorShape[value]);
+ return QCursor();
+}
+#endif
+
+QPixmap QtPropertyBrowserUtils::brushValuePixmap(const QBrush &b)
+{
+ QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+
+ QPainter painter(&img);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(0, 0, img.width(), img.height(), b);
+ QColor color = b.color();
+ if (color.alpha() != 255) { // indicate alpha by an inset
+ QBrush opaqueBrush = b;
+ color.setAlpha(255);
+ opaqueBrush.setColor(color);
+ painter.fillRect(img.width() / 4, img.height() / 4,
+ img.width() / 2, img.height() / 2, opaqueBrush);
+ }
+ painter.end();
+ return QPixmap::fromImage(img);
+}
+
+QIcon QtPropertyBrowserUtils::brushValueIcon(const QBrush &b)
+{
+ return QIcon(brushValuePixmap(b));
+}
+
+QString QtPropertyBrowserUtils::colorValueText(const QColor &c)
+{
+ return QApplication::translate("QtPropertyBrowserUtils", "[%1, %2, %3] (%4)", 0, QApplication::UnicodeUTF8)
+ .arg(QString::number(c.red()))
+ .arg(QString::number(c.green()))
+ .arg(QString::number(c.blue()))
+ .arg(QString::number(c.alpha()));
+}
+
+QPixmap QtPropertyBrowserUtils::fontValuePixmap(const QFont &font)
+{
+ QFont f = font;
+ QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+ QPainter p(&img);
+ p.setRenderHint(QPainter::TextAntialiasing, true);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ f.setPointSize(13);
+ p.setFont(f);
+ QTextOption t;
+ t.setAlignment(Qt::AlignCenter);
+ p.drawText(QRect(0, 0, 16, 16), QString(QLatin1Char('A')), t);
+ return QPixmap::fromImage(img);
+}
+
+QIcon QtPropertyBrowserUtils::fontValueIcon(const QFont &f)
+{
+ return QIcon(fontValuePixmap(f));
+}
+
+QString QtPropertyBrowserUtils::fontValueText(const QFont &f)
+{
+ return QApplication::translate("QtPropertyBrowserUtils", "[%1, %2]", 0, QApplication::UnicodeUTF8)
+ .arg(f.family())
+ .arg(f.pointSize());
+}
+
+
+QtBoolEdit::QtBoolEdit(QWidget *parent) :
+ QWidget(parent),
+ m_checkBox(new QCheckBox(this)),
+ m_textVisible(true)
+{
+ QHBoxLayout *lt = new QHBoxLayout;
+ if (QApplication::layoutDirection() == Qt::LeftToRight)
+ lt->setContentsMargins(4, 0, 0, 0);
+ else
+ lt->setContentsMargins(0, 0, 4, 0);
+ lt->addWidget(m_checkBox);
+ setLayout(lt);
+ connect(m_checkBox, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
+ setFocusProxy(m_checkBox);
+ m_checkBox->setText(tr("True"));
+}
+
+void QtBoolEdit::setTextVisible(bool textVisible)
+{
+ if (m_textVisible == textVisible)
+ return;
+
+ m_textVisible = textVisible;
+ if (m_textVisible)
+ m_checkBox->setText(isChecked() ? tr("True") : tr("False"));
+ else
+ m_checkBox->setText(QString());
+}
+
+Qt::CheckState QtBoolEdit::checkState() const
+{
+ return m_checkBox->checkState();
+}
+
+void QtBoolEdit::setCheckState(Qt::CheckState state)
+{
+ m_checkBox->setCheckState(state);
+}
+
+bool QtBoolEdit::isChecked() const
+{
+ return m_checkBox->isChecked();
+}
+
+void QtBoolEdit::setChecked(bool c)
+{
+ m_checkBox->setChecked(c);
+ if (!m_textVisible)
+ return;
+ m_checkBox->setText(isChecked() ? tr("True") : tr("False"));
+}
+
+bool QtBoolEdit::blockCheckBoxSignals(bool block)
+{
+ return m_checkBox->blockSignals(block);
+}
+
+void QtBoolEdit::mousePressEvent(QMouseEvent *event)
+{
+ if (event->buttons() == Qt::LeftButton) {
+ m_checkBox->click();
+ event->accept();
+ } else {
+ QWidget::mousePressEvent(event);
+ }
+}
+
+
+QtKeySequenceEdit::QtKeySequenceEdit(QWidget *parent)
+ : QWidget(parent), m_num(0), m_lineEdit(new QLineEdit(this))
+{
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ layout->addWidget(m_lineEdit);
+ layout->setMargin(0);
+ m_lineEdit->installEventFilter(this);
+ m_lineEdit->setReadOnly(true);
+ m_lineEdit->setFocusProxy(this);
+ setFocusPolicy(m_lineEdit->focusPolicy());
+ setAttribute(Qt::WA_InputMethodEnabled);
+}
+
+bool QtKeySequenceEdit::eventFilter(QObject *o, QEvent *e)
+{
+ if (o == m_lineEdit && e->type() == QEvent::ContextMenu) {
+ QContextMenuEvent *c = static_cast<QContextMenuEvent *>(e);
+ QMenu *menu = m_lineEdit->createStandardContextMenu();
+ const QList<QAction *> actions = menu->actions();
+ QListIterator<QAction *> itAction(actions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ action->setShortcut(QKeySequence());
+ QString actionString = action->text();
+ const int pos = actionString.lastIndexOf(QLatin1Char('\t'));
+ if (pos > 0)
+ actionString.remove(pos, actionString.length() - pos);
+ action->setText(actionString);
+ }
+ QAction *actionBefore = 0;
+ if (actions.count() > 0)
+ actionBefore = actions[0];
+ QAction *clearAction = new QAction(tr("Clear Shortcut"), menu);
+ menu->insertAction(actionBefore, clearAction);
+ menu->insertSeparator(actionBefore);
+ clearAction->setEnabled(!m_keySequence.isEmpty());
+ connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearShortcut()));
+ menu->exec(c->globalPos());
+ delete menu;
+ e->accept();
+ return true;
+ }
+
+ return QWidget::eventFilter(o, e);
+}
+
+void QtKeySequenceEdit::slotClearShortcut()
+{
+ if (m_keySequence.isEmpty())
+ return;
+ setKeySequence(QKeySequence());
+ emit keySequenceChanged(m_keySequence);
+}
+
+void QtKeySequenceEdit::handleKeyEvent(QKeyEvent *e)
+{
+ int nextKey = e->key();
+ if (nextKey == Qt::Key_Control || nextKey == Qt::Key_Shift ||
+ nextKey == Qt::Key_Meta || nextKey == Qt::Key_Alt ||
+ nextKey == Qt::Key_Super_L || nextKey == Qt::Key_AltGr)
+ return;
+
+ nextKey |= translateModifiers(e->modifiers(), e->text());
+ int k0 = m_keySequence[0];
+ int k1 = m_keySequence[1];
+ int k2 = m_keySequence[2];
+ int k3 = m_keySequence[3];
+ switch (m_num) {
+ case 0: k0 = nextKey; k1 = 0; k2 = 0; k3 = 0; break;
+ case 1: k1 = nextKey; k2 = 0; k3 = 0; break;
+ case 2: k2 = nextKey; k3 = 0; break;
+ case 3: k3 = nextKey; break;
+ default: break;
+ }
+ ++m_num;
+ if (m_num > 3)
+ m_num = 0;
+ m_keySequence = QKeySequence(k0, k1, k2, k3);
+ m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText));
+ e->accept();
+ emit keySequenceChanged(m_keySequence);
+}
+
+void QtKeySequenceEdit::setKeySequence(const QKeySequence &sequence)
+{
+ if (sequence == m_keySequence)
+ return;
+ m_num = 0;
+ m_keySequence = sequence;
+ m_lineEdit->setText(m_keySequence.toString(QKeySequence::NativeText));
+}
+
+QKeySequence QtKeySequenceEdit::keySequence() const
+{
+ return m_keySequence;
+}
+
+int QtKeySequenceEdit::translateModifiers(Qt::KeyboardModifiers state, const QString &text) const
+{
+ int result = 0;
+ if ((state & Qt::ShiftModifier) && (text.size() == 0 || !text.at(0).isPrint() || text.at(0).isLetter() || text.at(0).isSpace()))
+ result |= Qt::SHIFT;
+ if (state & Qt::ControlModifier)
+ result |= Qt::CTRL;
+ if (state & Qt::MetaModifier)
+ result |= Qt::META;
+ if (state & Qt::AltModifier)
+ result |= Qt::ALT;
+ return result;
+}
+
+void QtKeySequenceEdit::focusInEvent(QFocusEvent *e)
+{
+ m_lineEdit->event(e);
+ m_lineEdit->selectAll();
+ QWidget::focusInEvent(e);
+}
+
+void QtKeySequenceEdit::focusOutEvent(QFocusEvent *e)
+{
+ m_num = 0;
+ m_lineEdit->event(e);
+ QWidget::focusOutEvent(e);
+}
+
+void QtKeySequenceEdit::keyPressEvent(QKeyEvent *e)
+{
+ handleKeyEvent(e);
+ e->accept();
+}
+
+void QtKeySequenceEdit::keyReleaseEvent(QKeyEvent *e)
+{
+ m_lineEdit->event(e);
+}
+
+bool QtKeySequenceEdit::event(QEvent *e)
+{
+ if (e->type() == QEvent::Shortcut ||
+ e->type() == QEvent::ShortcutOverride ||
+ e->type() == QEvent::KeyRelease) {
+ e->accept();
+ return true;
+ }
+ return QWidget::event(e);
+}
+
+
+
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
diff --git a/tools/shared/qtpropertybrowser/qtpropertybrowserutils_p.h b/tools/shared/qtpropertybrowser/qtpropertybrowserutils_p.h
new file mode 100644
index 0000000000..2eab3c8e7d
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertybrowserutils_p.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QTPROPERTYBROWSERUTILS_H
+#define QTPROPERTYBROWSERUTILS_H
+
+#include <QtCore/QMap>
+#include <QtGui/QIcon>
+#include <QtGui/QWidget>
+#include <QtCore/QStringList>
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QMouseEvent;
+class QCheckBox;
+class QLineEdit;
+
+class QtCursorDatabase
+{
+public:
+ QtCursorDatabase();
+
+ QStringList cursorShapeNames() const;
+ QMap<int, QIcon> cursorShapeIcons() const;
+ QString cursorToShapeName(const QCursor &cursor) const;
+ QIcon cursorToShapeIcon(const QCursor &cursor) const;
+ int cursorToValue(const QCursor &cursor) const;
+#ifndef QT_NO_CURSOR
+ QCursor valueToCursor(int value) const;
+#endif
+private:
+ void appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon);
+ QStringList m_cursorNames;
+ QMap<int, QIcon> m_cursorIcons;
+ QMap<int, Qt::CursorShape> m_valueToCursorShape;
+ QMap<Qt::CursorShape, int> m_cursorShapeToValue;
+};
+
+class QtPropertyBrowserUtils
+{
+public:
+ static QPixmap brushValuePixmap(const QBrush &b);
+ static QIcon brushValueIcon(const QBrush &b);
+ static QString colorValueText(const QColor &c);
+ static QPixmap fontValuePixmap(const QFont &f);
+ static QIcon fontValueIcon(const QFont &f);
+ static QString fontValueText(const QFont &f);
+};
+
+class QtBoolEdit : public QWidget {
+ Q_OBJECT
+public:
+ QtBoolEdit(QWidget *parent = 0);
+
+ bool textVisible() const { return m_textVisible; }
+ void setTextVisible(bool textVisible);
+
+ Qt::CheckState checkState() const;
+ void setCheckState(Qt::CheckState state);
+
+ bool isChecked() const;
+ void setChecked(bool c);
+
+ bool blockCheckBoxSignals(bool block);
+
+Q_SIGNALS:
+ void toggled(bool);
+
+protected:
+ void mousePressEvent(QMouseEvent * event);
+
+private:
+ QCheckBox *m_checkBox;
+ bool m_textVisible;
+};
+
+class QtKeySequenceEdit : public QWidget
+{
+ Q_OBJECT
+public:
+ QtKeySequenceEdit(QWidget *parent = 0);
+
+ QKeySequence keySequence() const;
+ bool eventFilter(QObject *o, QEvent *e);
+public Q_SLOTS:
+ void setKeySequence(const QKeySequence &sequence);
+Q_SIGNALS:
+ void keySequenceChanged(const QKeySequence &sequence);
+protected:
+ void focusInEvent(QFocusEvent *e);
+ void focusOutEvent(QFocusEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void keyReleaseEvent(QKeyEvent *e);
+ bool event(QEvent *e);
+private slots:
+ void slotClearShortcut();
+private:
+ void handleKeyEvent(QKeyEvent *e);
+ int translateModifiers(Qt::KeyboardModifiers state, const QString &text) const;
+
+ int m_num;
+ QKeySequence m_keySequence;
+ QLineEdit *m_lineEdit;
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#endif
diff --git a/tools/shared/qtpropertybrowser/qtpropertymanager.cpp b/tools/shared/qtpropertybrowser/qtpropertymanager.cpp
new file mode 100644
index 0000000000..8b84eb9fae
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertymanager.cpp
@@ -0,0 +1,6493 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtpropertymanager.h"
+#include "qtpropertybrowserutils_p.h"
+#include <QtCore/QDateTime>
+#include <QtCore/QLocale>
+#include <QtCore/QMap>
+#include <QtCore/QTimer>
+#include <QtGui/QIcon>
+#include <QtCore/QMetaEnum>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QStyleOption>
+#include <QtGui/QStyle>
+#include <QtGui/QApplication>
+#include <QtGui/QPainter>
+#include <QtGui/QLabel>
+
+#include <limits.h>
+#include <float.h>
+
+#if defined(Q_CC_MSVC)
+# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */
+#endif
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+template <class PrivateData, class Value>
+static void setSimpleMinimumData(PrivateData *data, const Value &minVal)
+{
+ data->minVal = minVal;
+ if (data->maxVal < data->minVal)
+ data->maxVal = data->minVal;
+
+ if (data->val < data->minVal)
+ data->val = data->minVal;
+}
+
+template <class PrivateData, class Value>
+static void setSimpleMaximumData(PrivateData *data, const Value &maxVal)
+{
+ data->maxVal = maxVal;
+ if (data->minVal > data->maxVal)
+ data->minVal = data->maxVal;
+
+ if (data->val > data->maxVal)
+ data->val = data->maxVal;
+}
+
+template <class PrivateData, class Value>
+static void setSizeMinimumData(PrivateData *data, const Value &newMinVal)
+{
+ data->minVal = newMinVal;
+ if (data->maxVal.width() < data->minVal.width())
+ data->maxVal.setWidth(data->minVal.width());
+ if (data->maxVal.height() < data->minVal.height())
+ data->maxVal.setHeight(data->minVal.height());
+
+ if (data->val.width() < data->minVal.width())
+ data->val.setWidth(data->minVal.width());
+ if (data->val.height() < data->minVal.height())
+ data->val.setHeight(data->minVal.height());
+}
+
+template <class PrivateData, class Value>
+static void setSizeMaximumData(PrivateData *data, const Value &newMaxVal)
+{
+ data->maxVal = newMaxVal;
+ if (data->minVal.width() > data->maxVal.width())
+ data->minVal.setWidth(data->maxVal.width());
+ if (data->minVal.height() > data->maxVal.height())
+ data->minVal.setHeight(data->maxVal.height());
+
+ if (data->val.width() > data->maxVal.width())
+ data->val.setWidth(data->maxVal.width());
+ if (data->val.height() > data->maxVal.height())
+ data->val.setHeight(data->maxVal.height());
+}
+
+template <class SizeValue>
+static SizeValue qBoundSize(const SizeValue &minVal, const SizeValue &val, const SizeValue &maxVal)
+{
+ SizeValue croppedVal = val;
+ if (minVal.width() > val.width())
+ croppedVal.setWidth(minVal.width());
+ else if (maxVal.width() < val.width())
+ croppedVal.setWidth(maxVal.width());
+
+ if (minVal.height() > val.height())
+ croppedVal.setHeight(minVal.height());
+ else if (maxVal.height() < val.height())
+ croppedVal.setHeight(maxVal.height());
+
+ return croppedVal;
+}
+
+// Match the exact signature of qBound for VS 6.
+QSize qBound(QSize minVal, QSize val, QSize maxVal)
+{
+ return qBoundSize(minVal, val, maxVal);
+}
+
+QSizeF qBound(QSizeF minVal, QSizeF val, QSizeF maxVal)
+{
+ return qBoundSize(minVal, val, maxVal);
+}
+
+namespace {
+
+namespace {
+template <class Value>
+void orderBorders(Value &minVal, Value &maxVal)
+{
+ if (minVal > maxVal)
+ qSwap(minVal, maxVal);
+}
+
+template <class Value>
+static void orderSizeBorders(Value &minVal, Value &maxVal)
+{
+ Value fromSize = minVal;
+ Value toSize = maxVal;
+ if (fromSize.width() > toSize.width()) {
+ fromSize.setWidth(maxVal.width());
+ toSize.setWidth(minVal.width());
+ }
+ if (fromSize.height() > toSize.height()) {
+ fromSize.setHeight(maxVal.height());
+ toSize.setHeight(minVal.height());
+ }
+ minVal = fromSize;
+ maxVal = toSize;
+}
+
+void orderBorders(QSize &minVal, QSize &maxVal)
+{
+ orderSizeBorders(minVal, maxVal);
+}
+
+void orderBorders(QSizeF &minVal, QSizeF &maxVal)
+{
+ orderSizeBorders(minVal, maxVal);
+}
+
+}
+}
+////////
+
+template <class Value, class PrivateData>
+static Value getData(const QMap<const QtProperty *, PrivateData> &propertyMap,
+ Value PrivateData::*data,
+ const QtProperty *property, const Value &defaultValue = Value())
+{
+ typedef QMap<const QtProperty *, PrivateData> PropertyToData;
+ typedef Q_TYPENAME PropertyToData::const_iterator PropertyToDataConstIterator;
+ const PropertyToDataConstIterator it = propertyMap.constFind(property);
+ if (it == propertyMap.constEnd())
+ return defaultValue;
+ return it.value().*data;
+}
+
+template <class Value, class PrivateData>
+static Value getValue(const QMap<const QtProperty *, PrivateData> &propertyMap,
+ const QtProperty *property, const Value &defaultValue = Value())
+{
+ return getData<Value>(propertyMap, &PrivateData::val, property, defaultValue);
+}
+
+template <class Value, class PrivateData>
+static Value getMinimum(const QMap<const QtProperty *, PrivateData> &propertyMap,
+ const QtProperty *property, const Value &defaultValue = Value())
+{
+ return getData<Value>(propertyMap, &PrivateData::minVal, property, defaultValue);
+}
+
+template <class Value, class PrivateData>
+static Value getMaximum(const QMap<const QtProperty *, PrivateData> &propertyMap,
+ const QtProperty *property, const Value &defaultValue = Value())
+{
+ return getData<Value>(propertyMap, &PrivateData::maxVal, property, defaultValue);
+}
+
+template <class ValueChangeParameter, class Value, class PropertyManager>
+static void setSimpleValue(QMap<const QtProperty *, Value> &propertyMap,
+ PropertyManager *manager,
+ void (PropertyManager::*propertyChangedSignal)(QtProperty *),
+ void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter),
+ QtProperty *property, const Value &val)
+{
+ typedef QMap<const QtProperty *, Value> PropertyToData;
+ typedef Q_TYPENAME PropertyToData::iterator PropertyToDataIterator;
+ const PropertyToDataIterator it = propertyMap.find(property);
+ if (it == propertyMap.end())
+ return;
+
+ if (it.value() == val)
+ return;
+
+ it.value() = val;
+
+ emit (manager->*propertyChangedSignal)(property);
+ emit (manager->*valueChangedSignal)(property, val);
+}
+
+template <class ValueChangeParameter, class PropertyManagerPrivate, class PropertyManager, class Value>
+static void setValueInRange(PropertyManager *manager, PropertyManagerPrivate *managerPrivate,
+ void (PropertyManager::*propertyChangedSignal)(QtProperty *),
+ void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter),
+ QtProperty *property, const Value &val,
+ void (PropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, ValueChangeParameter))
+{
+ typedef Q_TYPENAME PropertyManagerPrivate::Data PrivateData;
+ typedef QMap<const QtProperty *, PrivateData> PropertyToData;
+ typedef Q_TYPENAME PropertyToData::iterator PropertyToDataIterator;
+ const PropertyToDataIterator it = managerPrivate->m_values.find(property);
+ if (it == managerPrivate->m_values.end())
+ return;
+
+ PrivateData &data = it.value();
+
+ if (data.val == val)
+ return;
+
+ const Value oldVal = data.val;
+
+ data.val = qBound(data.minVal, val, data.maxVal);
+
+ if (data.val == oldVal)
+ return;
+
+ if (setSubPropertyValue)
+ (managerPrivate->*setSubPropertyValue)(property, data.val);
+
+ emit (manager->*propertyChangedSignal)(property);
+ emit (manager->*valueChangedSignal)(property, data.val);
+}
+
+template <class ValueChangeParameter, class PropertyManagerPrivate, class PropertyManager, class Value>
+static void setBorderValues(PropertyManager *manager, PropertyManagerPrivate *managerPrivate,
+ void (PropertyManager::*propertyChangedSignal)(QtProperty *),
+ void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter),
+ void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter),
+ QtProperty *property, const Value &minVal, const Value &maxVal,
+ void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *,
+ ValueChangeParameter, ValueChangeParameter, ValueChangeParameter))
+{
+ typedef Q_TYPENAME PropertyManagerPrivate::Data PrivateData;
+ typedef QMap<const QtProperty *, PrivateData> PropertyToData;
+ typedef Q_TYPENAME PropertyToData::iterator PropertyToDataIterator;
+ const PropertyToDataIterator it = managerPrivate->m_values.find(property);
+ if (it == managerPrivate->m_values.end())
+ return;
+
+ Value fromVal = minVal;
+ Value toVal = maxVal;
+ orderBorders(fromVal, toVal);
+
+ PrivateData &data = it.value();
+
+ if (data.minVal == fromVal && data.maxVal == toVal)
+ return;
+
+ const Value oldVal = data.val;
+
+ data.setMinimumValue(fromVal);
+ data.setMaximumValue(toVal);
+
+ emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal);
+
+ if (setSubPropertyRange)
+ (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val);
+
+ if (data.val == oldVal)
+ return;
+
+ emit (manager->*propertyChangedSignal)(property);
+ emit (manager->*valueChangedSignal)(property, data.val);
+}
+
+template <class ValueChangeParameter, class PropertyManagerPrivate, class PropertyManager, class Value, class PrivateData>
+static void setBorderValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate,
+ void (PropertyManager::*propertyChangedSignal)(QtProperty *),
+ void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter),
+ void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter),
+ QtProperty *property,
+ Value (PrivateData::*getRangeVal)() const,
+ void (PrivateData::*setRangeVal)(ValueChangeParameter), const Value &borderVal,
+ void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *,
+ ValueChangeParameter, ValueChangeParameter, ValueChangeParameter))
+{
+ typedef QMap<const QtProperty *, PrivateData> PropertyToData;
+ typedef Q_TYPENAME PropertyToData::iterator PropertyToDataIterator;
+ const PropertyToDataIterator it = managerPrivate->m_values.find(property);
+ if (it == managerPrivate->m_values.end())
+ return;
+
+ PrivateData &data = it.value();
+
+ if ((data.*getRangeVal)() == borderVal)
+ return;
+
+ const Value oldVal = data.val;
+
+ (data.*setRangeVal)(borderVal);
+
+ emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal);
+
+ if (setSubPropertyRange)
+ (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val);
+
+ if (data.val == oldVal)
+ return;
+
+ emit (manager->*propertyChangedSignal)(property);
+ emit (manager->*valueChangedSignal)(property, data.val);
+}
+
+template <class ValueChangeParameter, class PropertyManagerPrivate, class PropertyManager, class Value, class PrivateData>
+static void setMinimumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate,
+ void (PropertyManager::*propertyChangedSignal)(QtProperty *),
+ void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter),
+ void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter),
+ QtProperty *property, const Value &minVal)
+{
+ void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *,
+ ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0;
+ setBorderValue<ValueChangeParameter, PropertyManagerPrivate, PropertyManager, Value, PrivateData>(manager, managerPrivate,
+ propertyChangedSignal, valueChangedSignal, rangeChangedSignal,
+ property, &PropertyManagerPrivate::Data::minimumValue, &PropertyManagerPrivate::Data::setMinimumValue, minVal, setSubPropertyRange);
+}
+
+template <class ValueChangeParameter, class PropertyManagerPrivate, class PropertyManager, class Value, class PrivateData>
+static void setMaximumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate,
+ void (PropertyManager::*propertyChangedSignal)(QtProperty *),
+ void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter),
+ void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter),
+ QtProperty *property, const Value &maxVal)
+{
+ void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *,
+ ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0;
+ setBorderValue<ValueChangeParameter, PropertyManagerPrivate, PropertyManager, Value, PrivateData>(manager, managerPrivate,
+ propertyChangedSignal, valueChangedSignal, rangeChangedSignal,
+ property, &PropertyManagerPrivate::Data::maximumValue, &PropertyManagerPrivate::Data::setMaximumValue, maxVal, setSubPropertyRange);
+}
+
+class QtMetaEnumWrapper : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QSizePolicy::Policy policy READ policy)
+public:
+ QSizePolicy::Policy policy() const { return QSizePolicy::Ignored; }
+private:
+ QtMetaEnumWrapper(QObject *parent) : QObject(parent) {}
+};
+
+class QtMetaEnumProvider
+{
+public:
+ QtMetaEnumProvider();
+
+ QStringList policyEnumNames() const { return m_policyEnumNames; }
+ QStringList languageEnumNames() const { return m_languageEnumNames; }
+ QStringList countryEnumNames(QLocale::Language language) const { return m_countryEnumNames.value(language); }
+
+ QSizePolicy::Policy indexToSizePolicy(int index) const;
+ int sizePolicyToIndex(QSizePolicy::Policy policy) const;
+
+ void indexToLocale(int languageIndex, int countryIndex, QLocale::Language *language, QLocale::Country *country) const;
+ void localeToIndex(QLocale::Language language, QLocale::Country country, int *languageIndex, int *countryIndex) const;
+
+private:
+ void initLocale();
+
+ QStringList m_policyEnumNames;
+ QStringList m_languageEnumNames;
+ QMap<QLocale::Language, QStringList> m_countryEnumNames;
+ QMap<int, QLocale::Language> m_indexToLanguage;
+ QMap<QLocale::Language, int> m_languageToIndex;
+ QMap<int, QMap<int, QLocale::Country> > m_indexToCountry;
+ QMap<QLocale::Language, QMap<QLocale::Country, int> > m_countryToIndex;
+ QMetaEnum m_policyEnum;
+};
+
+#if QT_VERSION < 0x040300
+
+static QList<QLocale::Country> countriesForLanguage(QLocale::Language language)
+{
+ QList<QLocale::Country> countries;
+ QLocale::Country country = QLocale::AnyCountry;
+ while (country <= QLocale::LastCountry) {
+ QLocale locale(language, country);
+ if (locale.language() == language && !countries.contains(locale.country()))
+ countries << locale.country();
+ country = (QLocale::Country)((uint)country + 1); // ++country
+ }
+ return countries;
+}
+
+#endif
+
+static QList<QLocale::Country> sortCountries(const QList<QLocale::Country> &countries)
+{
+ QMultiMap<QString, QLocale::Country> nameToCountry;
+ QListIterator<QLocale::Country> itCountry(countries);
+ while (itCountry.hasNext()) {
+ QLocale::Country country = itCountry.next();
+ nameToCountry.insert(QLocale::countryToString(country), country);
+ }
+ return nameToCountry.values();
+}
+
+void QtMetaEnumProvider::initLocale()
+{
+ QMultiMap<QString, QLocale::Language> nameToLanguage;
+ QLocale::Language language = QLocale::C;
+ while (language <= QLocale::LastLanguage) {
+ QLocale locale(language);
+ if (locale.language() == language)
+ nameToLanguage.insert(QLocale::languageToString(language), language);
+ language = (QLocale::Language)((uint)language + 1); // ++language
+ }
+
+ const QLocale system = QLocale::system();
+ if (!nameToLanguage.contains(QLocale::languageToString(system.language())))
+ nameToLanguage.insert(QLocale::languageToString(system.language()), system.language());
+
+ QList<QLocale::Language> languages = nameToLanguage.values();
+ QListIterator<QLocale::Language> itLang(languages);
+ while (itLang.hasNext()) {
+ QLocale::Language language = itLang.next();
+ QList<QLocale::Country> countries;
+#if QT_VERSION < 0x040300
+ countries = countriesForLanguage(language);
+#else
+ countries = QLocale::countriesForLanguage(language);
+#endif
+ if (countries.isEmpty() && language == system.language())
+ countries << system.country();
+
+ if (!countries.isEmpty() && !m_languageToIndex.contains(language)) {
+ countries = sortCountries(countries);
+ int langIdx = m_languageEnumNames.count();
+ m_indexToLanguage[langIdx] = language;
+ m_languageToIndex[language] = langIdx;
+ QStringList countryNames;
+ QListIterator<QLocale::Country> it(countries);
+ int countryIdx = 0;
+ while (it.hasNext()) {
+ QLocale::Country country = it.next();
+ countryNames << QLocale::countryToString(country);
+ m_indexToCountry[langIdx][countryIdx] = country;
+ m_countryToIndex[language][country] = countryIdx;
+ ++countryIdx;
+ }
+ m_languageEnumNames << QLocale::languageToString(language);
+ m_countryEnumNames[language] = countryNames;
+ }
+ }
+}
+
+QtMetaEnumProvider::QtMetaEnumProvider()
+{
+ QMetaProperty p;
+
+ p = QtMetaEnumWrapper::staticMetaObject.property(
+ QtMetaEnumWrapper::staticMetaObject.propertyOffset() + 0);
+ m_policyEnum = p.enumerator();
+ const int keyCount = m_policyEnum.keyCount();
+ for (int i = 0; i < keyCount; i++)
+ m_policyEnumNames << QLatin1String(m_policyEnum.key(i));
+
+ initLocale();
+}
+
+QSizePolicy::Policy QtMetaEnumProvider::indexToSizePolicy(int index) const
+{
+ return static_cast<QSizePolicy::Policy>(m_policyEnum.value(index));
+}
+
+int QtMetaEnumProvider::sizePolicyToIndex(QSizePolicy::Policy policy) const
+{
+ const int keyCount = m_policyEnum.keyCount();
+ for (int i = 0; i < keyCount; i++)
+ if (indexToSizePolicy(i) == policy)
+ return i;
+ return -1;
+}
+
+void QtMetaEnumProvider::indexToLocale(int languageIndex, int countryIndex, QLocale::Language *language, QLocale::Country *country) const
+{
+ QLocale::Language l = QLocale::C;
+ QLocale::Country c = QLocale::AnyCountry;
+ if (m_indexToLanguage.contains(languageIndex)) {
+ l = m_indexToLanguage[languageIndex];
+ if (m_indexToCountry.contains(languageIndex) && m_indexToCountry[languageIndex].contains(countryIndex))
+ c = m_indexToCountry[languageIndex][countryIndex];
+ }
+ if (language)
+ *language = l;
+ if (country)
+ *country = c;
+}
+
+void QtMetaEnumProvider::localeToIndex(QLocale::Language language, QLocale::Country country, int *languageIndex, int *countryIndex) const
+{
+ int l = -1;
+ int c = -1;
+ if (m_languageToIndex.contains(language)) {
+ l = m_languageToIndex[language];
+ if (m_countryToIndex.contains(language) && m_countryToIndex[language].contains(country))
+ c = m_countryToIndex[language][country];
+ }
+
+ if (languageIndex)
+ *languageIndex = l;
+ if (countryIndex)
+ *countryIndex = c;
+}
+
+Q_GLOBAL_STATIC(QtMetaEnumProvider, metaEnumProvider)
+
+// QtGroupPropertyManager
+
+/*!
+ \class QtGroupPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtGroupPropertyManager provides and manages group properties.
+
+ This class is intended to provide a grouping element without any value.
+
+ \sa QtAbstractPropertyManager
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtGroupPropertyManager::QtGroupPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtGroupPropertyManager::~QtGroupPropertyManager()
+{
+
+}
+
+/*!
+ \reimp
+*/
+bool QtGroupPropertyManager::hasValue(const QtProperty *property) const
+{
+ Q_UNUSED(property)
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QtGroupPropertyManager::initializeProperty(QtProperty *property)
+{
+ Q_UNUSED(property)
+}
+
+/*!
+ \reimp
+*/
+void QtGroupPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ Q_UNUSED(property)
+}
+
+// QtIntPropertyManager
+
+class QtIntPropertyManagerPrivate
+{
+ QtIntPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtIntPropertyManager)
+public:
+
+ struct Data
+ {
+ Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1) {}
+ int val;
+ int minVal;
+ int maxVal;
+ int singleStep;
+ int minimumValue() const { return minVal; }
+ int maximumValue() const { return maxVal; }
+ void setMinimumValue(int newMinVal) { setSimpleMinimumData(this, newMinVal); }
+ void setMaximumValue(int newMaxVal) { setSimpleMaximumData(this, newMaxVal); }
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*!
+ \class QtIntPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtIntPropertyManager provides and manages int properties.
+
+ An int property has a current value, and a range specifying the
+ valid values. The range is defined by a minimum and a maximum
+ value.
+
+ The property's value and range can be retrieved using the value(),
+ minimum() and maximum() functions, and can be set using the
+ setValue(), setMinimum() and setMaximum() slots. Alternatively,
+ the range can be defined in one go using the setRange() slot.
+
+ In addition, QtIntPropertyManager provides the valueChanged() signal which
+ is emitted whenever a property created by this manager changes,
+ and the rangeChanged() signal which is emitted whenever such a
+ property changes its range of valid values.
+
+ \sa QtAbstractPropertyManager, QtSpinBoxFactory, QtSliderFactory, QtScrollBarFactory
+*/
+
+/*!
+ \fn void QtIntPropertyManager::valueChanged(QtProperty *property, int value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtIntPropertyManager::rangeChanged(QtProperty *property, int minimum, int maximum)
+
+ This signal is emitted whenever a property created by this manager
+ changes its range of valid values, passing a pointer to the
+ \a property and the new \a minimum and \a maximum values.
+
+ \sa setRange()
+*/
+
+/*!
+ \fn void QtIntPropertyManager::singleStepChanged(QtProperty *property, int step)
+
+ This signal is emitted whenever a property created by this manager
+ changes its single step property, passing a pointer to the
+ \a property and the new \a step value
+
+ \sa setSingleStep()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtIntPropertyManager::QtIntPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtIntPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtIntPropertyManager::~QtIntPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns 0.
+
+ \sa setValue()
+*/
+int QtIntPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<int>(d_ptr->m_values, property, 0);
+}
+
+/*!
+ Returns the given \a property's minimum value.
+
+ \sa setMinimum(), maximum(), setRange()
+*/
+int QtIntPropertyManager::minimum(const QtProperty *property) const
+{
+ return getMinimum<int>(d_ptr->m_values, property, 0);
+}
+
+/*!
+ Returns the given \a property's maximum value.
+
+ \sa setMaximum(), minimum(), setRange()
+*/
+int QtIntPropertyManager::maximum(const QtProperty *property) const
+{
+ return getMaximum<int>(d_ptr->m_values, property, 0);
+}
+
+/*!
+ Returns the given \a property's step value.
+
+ The step is typically used to increment or decrement a property value while pressing an arrow key.
+
+ \sa setSingleStep()
+*/
+int QtIntPropertyManager::singleStep(const QtProperty *property) const
+{
+ return getData<int>(d_ptr->m_values, &QtIntPropertyManagerPrivate::Data::singleStep, property, 0);
+}
+
+/*!
+ \reimp
+*/
+QString QtIntPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtIntPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ return QString::number(it.value().val);
+}
+
+/*!
+ \fn void QtIntPropertyManager::setValue(QtProperty *property, int value)
+
+ Sets the value of the given \a property to \a value.
+
+ If the specified \a value is not valid according to the given \a
+ property's range, the \a value is adjusted to the nearest valid
+ value within the range.
+
+ \sa value(), setRange(), valueChanged()
+*/
+void QtIntPropertyManager::setValue(QtProperty *property, int val)
+{
+ void (QtIntPropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, int) = 0;
+ setValueInRange<int, QtIntPropertyManagerPrivate, QtIntPropertyManager, int>(this, d_ptr,
+ &QtIntPropertyManager::propertyChanged,
+ &QtIntPropertyManager::valueChanged,
+ property, val, setSubPropertyValue);
+}
+
+/*!
+ Sets the minimum value for the given \a property to \a minVal.
+
+ When setting the minimum value, the maximum and current values are
+ adjusted if necessary (ensuring that the range remains valid and
+ that the current value is within the range).
+
+ \sa minimum(), setRange(), rangeChanged()
+*/
+void QtIntPropertyManager::setMinimum(QtProperty *property, int minVal)
+{
+ setMinimumValue<int, QtIntPropertyManagerPrivate, QtIntPropertyManager, int, QtIntPropertyManagerPrivate::Data>(this, d_ptr,
+ &QtIntPropertyManager::propertyChanged,
+ &QtIntPropertyManager::valueChanged,
+ &QtIntPropertyManager::rangeChanged,
+ property, minVal);
+}
+
+/*!
+ Sets the maximum value for the given \a property to \a maxVal.
+
+ When setting maximum value, the minimum and current values are
+ adjusted if necessary (ensuring that the range remains valid and
+ that the current value is within the range).
+
+ \sa maximum(), setRange(), rangeChanged()
+*/
+void QtIntPropertyManager::setMaximum(QtProperty *property, int maxVal)
+{
+ setMaximumValue<int, QtIntPropertyManagerPrivate, QtIntPropertyManager, int, QtIntPropertyManagerPrivate::Data>(this, d_ptr,
+ &QtIntPropertyManager::propertyChanged,
+ &QtIntPropertyManager::valueChanged,
+ &QtIntPropertyManager::rangeChanged,
+ property, maxVal);
+}
+
+/*!
+ \fn void QtIntPropertyManager::setRange(QtProperty *property, int minimum, int maximum)
+
+ Sets the range of valid values.
+
+ This is a convenience function defining the range of valid values
+ in one go; setting the \a minimum and \a maximum values for the
+ given \a property with a single function call.
+
+ When setting a new range, the current value is adjusted if
+ necessary (ensuring that the value remains within range).
+
+ \sa setMinimum(), setMaximum(), rangeChanged()
+*/
+void QtIntPropertyManager::setRange(QtProperty *property, int minVal, int maxVal)
+{
+ void (QtIntPropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, int, int, int) = 0;
+ setBorderValues<int, QtIntPropertyManagerPrivate, QtIntPropertyManager, int>(this, d_ptr,
+ &QtIntPropertyManager::propertyChanged,
+ &QtIntPropertyManager::valueChanged,
+ &QtIntPropertyManager::rangeChanged,
+ property, minVal, maxVal, setSubPropertyRange);
+}
+
+/*!
+ Sets the step value for the given \a property to \a step.
+
+ The step is typically used to increment or decrement a property value while pressing an arrow key.
+
+ \sa singleStep()
+*/
+void QtIntPropertyManager::setSingleStep(QtProperty *property, int step)
+{
+ const QtIntPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtIntPropertyManagerPrivate::Data data = it.value();
+
+ if (step < 0)
+ step = 0;
+
+ if (data.singleStep == step)
+ return;
+
+ data.singleStep = step;
+
+ it.value() = data;
+
+ emit singleStepChanged(property, data.singleStep);
+}
+
+/*!
+ \reimp
+*/
+void QtIntPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtIntPropertyManagerPrivate::Data();
+}
+
+/*!
+ \reimp
+*/
+void QtIntPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtDoublePropertyManager
+
+class QtDoublePropertyManagerPrivate
+{
+ QtDoublePropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtDoublePropertyManager)
+public:
+
+ struct Data
+ {
+ Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1), decimals(2) {}
+ double val;
+ double minVal;
+ double maxVal;
+ double singleStep;
+ int decimals;
+ double minimumValue() const { return minVal; }
+ double maximumValue() const { return maxVal; }
+ void setMinimumValue(double newMinVal) { setSimpleMinimumData(this, newMinVal); }
+ void setMaximumValue(double newMaxVal) { setSimpleMaximumData(this, newMaxVal); }
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*!
+ \class QtDoublePropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtDoublePropertyManager provides and manages double properties.
+
+ A double property has a current value, and a range specifying the
+ valid values. The range is defined by a minimum and a maximum
+ value.
+
+ The property's value and range can be retrieved using the value(),
+ minimum() and maximum() functions, and can be set using the
+ setValue(), setMinimum() and setMaximum() slots.
+ Alternatively, the range can be defined in one go using the
+ setRange() slot.
+
+ In addition, QtDoublePropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the rangeChanged() signal which is emitted whenever
+ such a property changes its range of valid values.
+
+ \sa QtAbstractPropertyManager, QtDoubleSpinBoxFactory
+*/
+
+/*!
+ \fn void QtDoublePropertyManager::valueChanged(QtProperty *property, double value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtDoublePropertyManager::rangeChanged(QtProperty *property, double minimum, double maximum)
+
+ This signal is emitted whenever a property created by this manager
+ changes its range of valid values, passing a pointer to the
+ \a property and the new \a minimum and \a maximum values
+
+ \sa setRange()
+*/
+
+/*!
+ \fn void QtDoublePropertyManager::decimalsChanged(QtProperty *property, int prec)
+
+ This signal is emitted whenever a property created by this manager
+ changes its precision of value, passing a pointer to the
+ \a property and the new \a prec value
+
+ \sa setDecimals()
+*/
+
+/*!
+ \fn void QtDoublePropertyManager::singleStepChanged(QtProperty *property, double step)
+
+ This signal is emitted whenever a property created by this manager
+ changes its single step property, passing a pointer to the
+ \a property and the new \a step value
+
+ \sa setSingleStep()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtDoublePropertyManager::QtDoublePropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtDoublePropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtDoublePropertyManager::~QtDoublePropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns 0.
+
+ \sa setValue()
+*/
+double QtDoublePropertyManager::value(const QtProperty *property) const
+{
+ return getValue<double>(d_ptr->m_values, property, 0.0);
+}
+
+/*!
+ Returns the given \a property's minimum value.
+
+ \sa maximum(), setRange()
+*/
+double QtDoublePropertyManager::minimum(const QtProperty *property) const
+{
+ return getMinimum<double>(d_ptr->m_values, property, 0.0);
+}
+
+/*!
+ Returns the given \a property's maximum value.
+
+ \sa minimum(), setRange()
+*/
+double QtDoublePropertyManager::maximum(const QtProperty *property) const
+{
+ return getMaximum<double>(d_ptr->m_values, property, 0.0);
+}
+
+/*!
+ Returns the given \a property's step value.
+
+ The step is typically used to increment or decrement a property value while pressing an arrow key.
+
+ \sa setSingleStep()
+*/
+double QtDoublePropertyManager::singleStep(const QtProperty *property) const
+{
+ return getData<double>(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::singleStep, property, 0);
+}
+
+/*!
+ Returns the given \a property's precision, in decimals.
+
+ \sa setDecimals()
+*/
+int QtDoublePropertyManager::decimals(const QtProperty *property) const
+{
+ return getData<int>(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::decimals, property, 0);
+}
+
+/*!
+ \reimp
+*/
+QString QtDoublePropertyManager::valueText(const QtProperty *property) const
+{
+ const QtDoublePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ return QString::number(it.value().val, 'f', it.value().decimals);
+}
+
+/*!
+ \fn void QtDoublePropertyManager::setValue(QtProperty *property, double value)
+
+ Sets the value of the given \a property to \a value.
+
+ If the specified \a value is not valid according to the given
+ \a property's range, the \a value is adjusted to the nearest valid value
+ within the range.
+
+ \sa value(), setRange(), valueChanged()
+*/
+void QtDoublePropertyManager::setValue(QtProperty *property, double val)
+{
+ void (QtDoublePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, double) = 0;
+ setValueInRange<double, QtDoublePropertyManagerPrivate, QtDoublePropertyManager, double>(this, d_ptr,
+ &QtDoublePropertyManager::propertyChanged,
+ &QtDoublePropertyManager::valueChanged,
+ property, val, setSubPropertyValue);
+}
+
+/*!
+ Sets the step value for the given \a property to \a step.
+
+ The step is typically used to increment or decrement a property value while pressing an arrow key.
+
+ \sa singleStep()
+*/
+void QtDoublePropertyManager::setSingleStep(QtProperty *property, double step)
+{
+ const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtDoublePropertyManagerPrivate::Data data = it.value();
+
+ if (step < 0)
+ step = 0;
+
+ if (data.singleStep == step)
+ return;
+
+ data.singleStep = step;
+
+ it.value() = data;
+
+ emit singleStepChanged(property, data.singleStep);
+}
+
+/*!
+ \fn void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec)
+
+ Sets the precision of the given \a property to \a prec.
+
+ The valid decimal range is 0-13. The default is 2.
+
+ \sa decimals()
+*/
+void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec)
+{
+ const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtDoublePropertyManagerPrivate::Data data = it.value();
+
+ if (prec > 13)
+ prec = 13;
+ else if (prec < 0)
+ prec = 0;
+
+ if (data.decimals == prec)
+ return;
+
+ data.decimals = prec;
+
+ it.value() = data;
+
+ emit decimalsChanged(property, data.decimals);
+}
+
+/*!
+ Sets the minimum value for the given \a property to \a minVal.
+
+ When setting the minimum value, the maximum and current values are
+ adjusted if necessary (ensuring that the range remains valid and
+ that the current value is within in the range).
+
+ \sa minimum(), setRange(), rangeChanged()
+*/
+void QtDoublePropertyManager::setMinimum(QtProperty *property, double minVal)
+{
+ setMinimumValue<double, QtDoublePropertyManagerPrivate, QtDoublePropertyManager, double, QtDoublePropertyManagerPrivate::Data>(this, d_ptr,
+ &QtDoublePropertyManager::propertyChanged,
+ &QtDoublePropertyManager::valueChanged,
+ &QtDoublePropertyManager::rangeChanged,
+ property, minVal);
+}
+
+/*!
+ Sets the maximum value for the given \a property to \a maxVal.
+
+ When setting the maximum value, the minimum and current values are
+ adjusted if necessary (ensuring that the range remains valid and
+ that the current value is within in the range).
+
+ \sa maximum(), setRange(), rangeChanged()
+*/
+void QtDoublePropertyManager::setMaximum(QtProperty *property, double maxVal)
+{
+ setMaximumValue<double, QtDoublePropertyManagerPrivate, QtDoublePropertyManager, double, QtDoublePropertyManagerPrivate::Data>(this, d_ptr,
+ &QtDoublePropertyManager::propertyChanged,
+ &QtDoublePropertyManager::valueChanged,
+ &QtDoublePropertyManager::rangeChanged,
+ property, maxVal);
+}
+
+/*!
+ \fn void QtDoublePropertyManager::setRange(QtProperty *property, double minimum, double maximum)
+
+ Sets the range of valid values.
+
+ This is a convenience function defining the range of valid values
+ in one go; setting the \a minimum and \a maximum values for the
+ given \a property with a single function call.
+
+ When setting a new range, the current value is adjusted if
+ necessary (ensuring that the value remains within range).
+
+ \sa setMinimum(), setMaximum(), rangeChanged()
+*/
+void QtDoublePropertyManager::setRange(QtProperty *property, double minVal, double maxVal)
+{
+ void (QtDoublePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, double, double, double) = 0;
+ setBorderValues<double, QtDoublePropertyManagerPrivate, QtDoublePropertyManager, double>(this, d_ptr,
+ &QtDoublePropertyManager::propertyChanged,
+ &QtDoublePropertyManager::valueChanged,
+ &QtDoublePropertyManager::rangeChanged,
+ property, minVal, maxVal, setSubPropertyRange);
+}
+
+/*!
+ \reimp
+*/
+void QtDoublePropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtDoublePropertyManagerPrivate::Data();
+}
+
+/*!
+ \reimp
+*/
+void QtDoublePropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtStringPropertyManager
+
+class QtStringPropertyManagerPrivate
+{
+ QtStringPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtStringPropertyManager)
+public:
+
+ struct Data
+ {
+ Data() : regExp(QString(QLatin1Char('*')), Qt::CaseSensitive, QRegExp::Wildcard)
+ {
+ }
+ QString val;
+ QRegExp regExp;
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ QMap<const QtProperty *, Data> m_values;
+};
+
+/*!
+ \class QtStringPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtStringPropertyManager provides and manages QString properties.
+
+ A string property's value can be retrieved using the value()
+ function, and set using the setValue() slot.
+
+ The current value can be checked against a regular expression. To
+ set the regular expression use the setRegExp() slot, use the
+ regExp() function to retrieve the currently set expression.
+
+ In addition, QtStringPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the regExpChanged() signal which is emitted whenever
+ such a property changes its currently set regular expression.
+
+ \sa QtAbstractPropertyManager, QtLineEditFactory
+*/
+
+/*!
+ \fn void QtStringPropertyManager::valueChanged(QtProperty *property, const QString &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtStringPropertyManager::regExpChanged(QtProperty *property, const QRegExp &regExp)
+
+ This signal is emitted whenever a property created by this manager
+ changes its currenlty set regular expression, passing a pointer to
+ the \a property and the new \a regExp as parameters.
+
+ \sa setRegExp()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtStringPropertyManager::QtStringPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtStringPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtStringPropertyManager::~QtStringPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns an empty string.
+
+ \sa setValue()
+*/
+QString QtStringPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<QString>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's currently set regular expression.
+
+ If the given \a property is not managed by this manager, this
+ function returns an empty expression.
+
+ \sa setRegExp()
+*/
+QRegExp QtStringPropertyManager::regExp(const QtProperty *property) const
+{
+ return getData<QRegExp>(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::regExp, property, QRegExp());
+}
+
+/*!
+ \reimp
+*/
+QString QtStringPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtStringPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ return it.value().val;
+}
+
+/*!
+ \fn void QtStringPropertyManager::setValue(QtProperty *property, const QString &value)
+
+ Sets the value of the given \a property to \a value.
+
+ If the specified \a value doesn't match the given \a property's
+ regular expression, this function does nothing.
+
+ \sa value(), setRegExp(), valueChanged()
+*/
+void QtStringPropertyManager::setValue(QtProperty *property, const QString &val)
+{
+ const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtStringPropertyManagerPrivate::Data data = it.value();
+
+ if (data.val == val)
+ return;
+
+ if (data.regExp.isValid() && !data.regExp.exactMatch(val))
+ return;
+
+ data.val = val;
+
+ it.value() = data;
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ Sets the regular expression of the given \a property to \a regExp.
+
+ \sa regExp(), setValue(), regExpChanged()
+*/
+void QtStringPropertyManager::setRegExp(QtProperty *property, const QRegExp &regExp)
+{
+ const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtStringPropertyManagerPrivate::Data data = it.value() ;
+
+ if (data.regExp == regExp)
+ return;
+
+ data.regExp = regExp;
+
+ it.value() = data;
+
+ emit regExpChanged(property, data.regExp);
+}
+
+/*!
+ \reimp
+*/
+void QtStringPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtStringPropertyManagerPrivate::Data();
+}
+
+/*!
+ \reimp
+*/
+void QtStringPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtBoolPropertyManager
+
+class QtBoolPropertyManagerPrivate
+{
+ QtBoolPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtBoolPropertyManager)
+public:
+
+ QMap<const QtProperty *, bool> m_values;
+};
+
+/*!
+ \class QtBoolPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtBoolPropertyManager class provides and manages boolean properties.
+
+ The property's value can be retrieved using the value() function,
+ and set using the setValue() slot.
+
+ In addition, QtBoolPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes.
+
+ \sa QtAbstractPropertyManager, QtCheckBoxFactory
+*/
+
+/*!
+ \fn void QtBoolPropertyManager::valueChanged(QtProperty *property, bool value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtBoolPropertyManager::QtBoolPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtBoolPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtBoolPropertyManager::~QtBoolPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by \e this manager, this
+ function returns false.
+
+ \sa setValue()
+*/
+bool QtBoolPropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, false);
+}
+
+/*!
+ \reimp
+*/
+QString QtBoolPropertyManager::valueText(const QtProperty *property) const
+{
+ const QMap<const QtProperty *, bool>::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ static const QString trueText = tr("True");
+ static const QString falseText = tr("False");
+ return it.value() ? trueText : falseText;
+}
+
+// Return an icon containing a check box indicator
+static QIcon drawCheckBox(bool value)
+{
+ QStyleOptionButton opt;
+ opt.state |= value ? QStyle::State_On : QStyle::State_Off;
+ opt.state |= QStyle::State_Enabled;
+ const QStyle *style = QApplication::style();
+ // Figure out size of an indicator and make sure it is not scaled down in a list view item
+ // by making the pixmap as big as a list view icon and centering the indicator in it.
+ // (if it is smaller, it can't be helped)
+ const int indicatorWidth = style->pixelMetric(QStyle::PM_IndicatorWidth, &opt);
+ const int indicatorHeight = style->pixelMetric(QStyle::PM_IndicatorHeight, &opt);
+ const int listViewIconSize = indicatorWidth;
+ const int pixmapWidth = indicatorWidth;
+ const int pixmapHeight = qMax(indicatorHeight, listViewIconSize);
+
+ opt.rect = QRect(0, 0, indicatorWidth, indicatorHeight);
+ QPixmap pixmap = QPixmap(pixmapWidth, pixmapHeight);
+ pixmap.fill(Qt::transparent);
+ {
+ // Center?
+ const int xoff = (pixmapWidth > indicatorWidth) ? (pixmapWidth - indicatorWidth) / 2 : 0;
+ const int yoff = (pixmapHeight > indicatorHeight) ? (pixmapHeight - indicatorHeight) / 2 : 0;
+ QPainter painter(&pixmap);
+ painter.translate(xoff, yoff);
+ style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, &painter);
+ }
+ return QIcon(pixmap);
+}
+
+/*!
+ \reimp
+*/
+QIcon QtBoolPropertyManager::valueIcon(const QtProperty *property) const
+{
+ const QMap<const QtProperty *, bool>::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QIcon();
+
+ static const QIcon checkedIcon = drawCheckBox(true);
+ static const QIcon uncheckedIcon = drawCheckBox(false);
+ return it.value() ? checkedIcon : uncheckedIcon;
+}
+
+/*!
+ \fn void QtBoolPropertyManager::setValue(QtProperty *property, bool value)
+
+ Sets the value of the given \a property to \a value.
+
+ \sa value()
+*/
+void QtBoolPropertyManager::setValue(QtProperty *property, bool val)
+{
+ setSimpleValue<bool, bool, QtBoolPropertyManager>(d_ptr->m_values, this,
+ &QtBoolPropertyManager::propertyChanged,
+ &QtBoolPropertyManager::valueChanged,
+ property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtBoolPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = false;
+}
+
+/*!
+ \reimp
+*/
+void QtBoolPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtDatePropertyManager
+
+class QtDatePropertyManagerPrivate
+{
+ QtDatePropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtDatePropertyManager)
+public:
+
+ struct Data
+ {
+ Data() : val(QDate::currentDate()), minVal(QDate(1752, 9, 14)),
+ maxVal(QDate(7999, 12, 31)) {}
+ QDate val;
+ QDate minVal;
+ QDate maxVal;
+ QDate minimumValue() const { return minVal; }
+ QDate maximumValue() const { return maxVal; }
+ void setMinimumValue(const QDate &newMinVal) { setSimpleMinimumData(this, newMinVal); }
+ void setMaximumValue(const QDate &newMaxVal) { setSimpleMaximumData(this, newMaxVal); }
+ };
+
+ QString m_format;
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ QMap<const QtProperty *, Data> m_values;
+};
+
+/*!
+ \class QtDatePropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtDatePropertyManager provides and manages QDate properties.
+
+ A date property has a current value, and a range specifying the
+ valid dates. The range is defined by a minimum and a maximum
+ value.
+
+ The property's values can be retrieved using the minimum(),
+ maximum() and value() functions, and can be set using the
+ setMinimum(), setMaximum() and setValue() slots. Alternatively,
+ the range can be defined in one go using the setRange() slot.
+
+ In addition, QtDatePropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the rangeChanged() signal which is emitted whenever
+ such a property changes its range of valid dates.
+
+ \sa QtAbstractPropertyManager, QtDateEditFactory, QtDateTimePropertyManager
+*/
+
+/*!
+ \fn void QtDatePropertyManager::valueChanged(QtProperty *property, const QDate &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtDatePropertyManager::rangeChanged(QtProperty *property, const QDate &minimum, const QDate &maximum)
+
+ This signal is emitted whenever a property created by this manager
+ changes its range of valid dates, passing a pointer to the \a
+ property and the new \a minimum and \a maximum dates.
+
+ \sa setRange()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtDatePropertyManager::QtDatePropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtDatePropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ QLocale loc;
+ d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat);
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtDatePropertyManager::~QtDatePropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by \e this manager, this
+ function returns an invalid date.
+
+ \sa setValue()
+*/
+QDate QtDatePropertyManager::value(const QtProperty *property) const
+{
+ return getValue<QDate>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's minimum date.
+
+ \sa maximum(), setRange()
+*/
+QDate QtDatePropertyManager::minimum(const QtProperty *property) const
+{
+ return getMinimum<QDate>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's maximum date.
+
+ \sa minimum(), setRange()
+*/
+QDate QtDatePropertyManager::maximum(const QtProperty *property) const
+{
+ return getMaximum<QDate>(d_ptr->m_values, property);
+}
+
+/*!
+ \reimp
+*/
+QString QtDatePropertyManager::valueText(const QtProperty *property) const
+{
+ const QtDatePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ return it.value().val.toString(d_ptr->m_format);
+}
+
+/*!
+ \fn void QtDatePropertyManager::setValue(QtProperty *property, const QDate &value)
+
+ Sets the value of the given \a property to \a value.
+
+ If the specified \a value is not a valid date according to the
+ given \a property's range, the value is adjusted to the nearest
+ valid value within the range.
+
+ \sa value(), setRange(), valueChanged()
+*/
+void QtDatePropertyManager::setValue(QtProperty *property, const QDate &val)
+{
+ void (QtDatePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, const QDate &) = 0;
+ setValueInRange<const QDate &, QtDatePropertyManagerPrivate, QtDatePropertyManager, const QDate>(this, d_ptr,
+ &QtDatePropertyManager::propertyChanged,
+ &QtDatePropertyManager::valueChanged,
+ property, val, setSubPropertyValue);
+}
+
+/*!
+ Sets the minimum value for the given \a property to \a minVal.
+
+ When setting the minimum value, the maximum and current values are
+ adjusted if necessary (ensuring that the range remains valid and
+ that the current value is within in the range).
+
+ \sa minimum(), setRange()
+*/
+void QtDatePropertyManager::setMinimum(QtProperty *property, const QDate &minVal)
+{
+ setMinimumValue<const QDate &, QtDatePropertyManagerPrivate, QtDatePropertyManager, QDate, QtDatePropertyManagerPrivate::Data>(this, d_ptr,
+ &QtDatePropertyManager::propertyChanged,
+ &QtDatePropertyManager::valueChanged,
+ &QtDatePropertyManager::rangeChanged,
+ property, minVal);
+}
+
+/*!
+ Sets the maximum value for the given \a property to \a maxVal.
+
+ When setting the maximum value, the minimum and current
+ values are adjusted if necessary (ensuring that the range remains
+ valid and that the current value is within in the range).
+
+ \sa maximum(), setRange()
+*/
+void QtDatePropertyManager::setMaximum(QtProperty *property, const QDate &maxVal)
+{
+ setMaximumValue<const QDate &, QtDatePropertyManagerPrivate, QtDatePropertyManager, QDate, QtDatePropertyManagerPrivate::Data>(this, d_ptr,
+ &QtDatePropertyManager::propertyChanged,
+ &QtDatePropertyManager::valueChanged,
+ &QtDatePropertyManager::rangeChanged,
+ property, maxVal);
+}
+
+/*!
+ \fn void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minimum, const QDate &maximum)
+
+ Sets the range of valid dates.
+
+ This is a convenience function defining the range of valid dates
+ in one go; setting the \a minimum and \a maximum values for the
+ given \a property with a single function call.
+
+ When setting a new date range, the current value is adjusted if
+ necessary (ensuring that the value remains in date range).
+
+ \sa setMinimum(), setMaximum(), rangeChanged()
+*/
+void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal)
+{
+ void (QtDatePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, const QDate &,
+ const QDate &, const QDate &) = 0;
+ setBorderValues<const QDate &, QtDatePropertyManagerPrivate, QtDatePropertyManager, QDate>(this, d_ptr,
+ &QtDatePropertyManager::propertyChanged,
+ &QtDatePropertyManager::valueChanged,
+ &QtDatePropertyManager::rangeChanged,
+ property, minVal, maxVal, setSubPropertyRange);
+}
+
+/*!
+ \reimp
+*/
+void QtDatePropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtDatePropertyManagerPrivate::Data();
+}
+
+/*!
+ \reimp
+*/
+void QtDatePropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtTimePropertyManager
+
+class QtTimePropertyManagerPrivate
+{
+ QtTimePropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtTimePropertyManager)
+public:
+
+ QString m_format;
+
+ typedef QMap<const QtProperty *, QTime> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*!
+ \class QtTimePropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtTimePropertyManager provides and manages QTime properties.
+
+ A time property's value can be retrieved using the value()
+ function, and set using the setValue() slot.
+
+ In addition, QtTimePropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes.
+
+ \sa QtAbstractPropertyManager, QtTimeEditFactory
+*/
+
+/*!
+ \fn void QtTimePropertyManager::valueChanged(QtProperty *property, const QTime &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtTimePropertyManager::QtTimePropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtTimePropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ QLocale loc;
+ d_ptr->m_format = loc.timeFormat(QLocale::ShortFormat);
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtTimePropertyManager::~QtTimePropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns an invalid time object.
+
+ \sa setValue()
+*/
+QTime QtTimePropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QTime());
+}
+
+/*!
+ \reimp
+*/
+QString QtTimePropertyManager::valueText(const QtProperty *property) const
+{
+ const QtTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ return it.value().toString(d_ptr->m_format);
+}
+
+/*!
+ \fn void QtTimePropertyManager::setValue(QtProperty *property, const QTime &value)
+
+ Sets the value of the given \a property to \a value.
+
+ \sa value(), valueChanged()
+*/
+void QtTimePropertyManager::setValue(QtProperty *property, const QTime &val)
+{
+ setSimpleValue<const QTime &, QTime, QtTimePropertyManager>(d_ptr->m_values, this,
+ &QtTimePropertyManager::propertyChanged,
+ &QtTimePropertyManager::valueChanged,
+ property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtTimePropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QTime::currentTime();
+}
+
+/*!
+ \reimp
+*/
+void QtTimePropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtDateTimePropertyManager
+
+class QtDateTimePropertyManagerPrivate
+{
+ QtDateTimePropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtDateTimePropertyManager)
+public:
+
+ QString m_format;
+
+ typedef QMap<const QtProperty *, QDateTime> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*! \class QtDateTimePropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtDateTimePropertyManager provides and manages QDateTime properties.
+
+ A date and time property has a current value which can be
+ retrieved using the value() function, and set using the setValue()
+ slot. In addition, QtDateTimePropertyManager provides the
+ valueChanged() signal which is emitted whenever a property created
+ by this manager changes.
+
+ \sa QtAbstractPropertyManager, QtDateTimeEditFactory, QtDatePropertyManager
+*/
+
+/*!
+ \fn void QtDateTimePropertyManager::valueChanged(QtProperty *property, const QDateTime &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtDateTimePropertyManager::QtDateTimePropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtDateTimePropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ QLocale loc;
+ d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat);
+ d_ptr->m_format += QLatin1Char(' ');
+ d_ptr->m_format += loc.timeFormat(QLocale::ShortFormat);
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtDateTimePropertyManager::~QtDateTimePropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an invalid QDateTime object.
+
+ \sa setValue()
+*/
+QDateTime QtDateTimePropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QDateTime());
+}
+
+/*!
+ \reimp
+*/
+QString QtDateTimePropertyManager::valueText(const QtProperty *property) const
+{
+ const QtDateTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ return it.value().toString(d_ptr->m_format);
+}
+
+/*!
+ \fn void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &value)
+
+ Sets the value of the given \a property to \a value.
+
+ \sa value(), valueChanged()
+*/
+void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &val)
+{
+ setSimpleValue<const QDateTime &, QDateTime, QtDateTimePropertyManager>(d_ptr->m_values, this,
+ &QtDateTimePropertyManager::propertyChanged,
+ &QtDateTimePropertyManager::valueChanged,
+ property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtDateTimePropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QDateTime::currentDateTime();
+}
+
+/*!
+ \reimp
+*/
+void QtDateTimePropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtKeySequencePropertyManager
+
+class QtKeySequencePropertyManagerPrivate
+{
+ QtKeySequencePropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtKeySequencePropertyManager)
+public:
+
+ QString m_format;
+
+ typedef QMap<const QtProperty *, QKeySequence> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*! \class QtKeySequencePropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtKeySequencePropertyManager provides and manages QKeySequence properties.
+
+ A key sequence's value can be retrieved using the value()
+ function, and set using the setValue() slot.
+
+ In addition, QtKeySequencePropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes.
+
+ \sa QtAbstractPropertyManager
+*/
+
+/*!
+ \fn void QtKeySequencePropertyManager::valueChanged(QtProperty *property, const QKeySequence &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtKeySequencePropertyManager::QtKeySequencePropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtKeySequencePropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtKeySequencePropertyManager::~QtKeySequencePropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an empty QKeySequence object.
+
+ \sa setValue()
+*/
+QKeySequence QtKeySequencePropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QKeySequence());
+}
+
+/*!
+ \reimp
+*/
+QString QtKeySequencePropertyManager::valueText(const QtProperty *property) const
+{
+ const QtKeySequencePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ return it.value().toString(QKeySequence::NativeText);
+}
+
+/*!
+ \fn void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &value)
+
+ Sets the value of the given \a property to \a value.
+
+ \sa value(), valueChanged()
+*/
+void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &val)
+{
+ setSimpleValue<const QKeySequence &, QKeySequence, QtKeySequencePropertyManager>(d_ptr->m_values, this,
+ &QtKeySequencePropertyManager::propertyChanged,
+ &QtKeySequencePropertyManager::valueChanged,
+ property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtKeySequencePropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QKeySequence();
+}
+
+/*!
+ \reimp
+*/
+void QtKeySequencePropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtCharPropertyManager
+
+class QtCharPropertyManagerPrivate
+{
+ QtCharPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtCharPropertyManager)
+public:
+
+ typedef QMap<const QtProperty *, QChar> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*! \class QtCharPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtCharPropertyManager provides and manages QChar properties.
+
+ A char's value can be retrieved using the value()
+ function, and set using the setValue() slot.
+
+ In addition, QtCharPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes.
+
+ \sa QtAbstractPropertyManager
+*/
+
+/*!
+ \fn void QtCharPropertyManager::valueChanged(QtProperty *property, const QChar &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtCharPropertyManager::QtCharPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtCharPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtCharPropertyManager::~QtCharPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an null QChar object.
+
+ \sa setValue()
+*/
+QChar QtCharPropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QChar());
+}
+
+/*!
+ \reimp
+*/
+QString QtCharPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtCharPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ const QChar c = it.value();
+ return c.isNull() ? QString() : QString(c);
+}
+
+/*!
+ \fn void QtCharPropertyManager::setValue(QtProperty *property, const QChar &value)
+
+ Sets the value of the given \a property to \a value.
+
+ \sa value(), valueChanged()
+*/
+void QtCharPropertyManager::setValue(QtProperty *property, const QChar &val)
+{
+ setSimpleValue<const QChar &, QChar, QtCharPropertyManager>(d_ptr->m_values, this,
+ &QtCharPropertyManager::propertyChanged,
+ &QtCharPropertyManager::valueChanged,
+ property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtCharPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QChar();
+}
+
+/*!
+ \reimp
+*/
+void QtCharPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtLocalePropertyManager
+
+class QtLocalePropertyManagerPrivate
+{
+ QtLocalePropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtLocalePropertyManager)
+public:
+
+ QtLocalePropertyManagerPrivate();
+
+ void slotEnumChanged(QtProperty *property, int value);
+ void slotPropertyDestroyed(QtProperty *property);
+
+ typedef QMap<const QtProperty *, QLocale> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtEnumPropertyManager *m_enumPropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToLanguage;
+ QMap<const QtProperty *, QtProperty *> m_propertyToCountry;
+
+ QMap<const QtProperty *, QtProperty *> m_languageToProperty;
+ QMap<const QtProperty *, QtProperty *> m_countryToProperty;
+};
+
+QtLocalePropertyManagerPrivate::QtLocalePropertyManagerPrivate()
+{
+}
+
+void QtLocalePropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value)
+{
+ if (QtProperty *prop = m_languageToProperty.value(property, 0)) {
+ const QLocale loc = m_values[prop];
+ QLocale::Language newLanguage = loc.language();
+ QLocale::Country newCountry = loc.country();
+ metaEnumProvider()->indexToLocale(value, 0, &newLanguage, 0);
+ QLocale newLoc(newLanguage, newCountry);
+ q_ptr->setValue(prop, newLoc);
+ } else if (QtProperty *prop = m_countryToProperty.value(property, 0)) {
+ const QLocale loc = m_values[prop];
+ QLocale::Language newLanguage = loc.language();
+ QLocale::Country newCountry = loc.country();
+ metaEnumProvider()->indexToLocale(m_enumPropertyManager->value(m_propertyToLanguage.value(prop)), value, &newLanguage, &newCountry);
+ QLocale newLoc(newLanguage, newCountry);
+ q_ptr->setValue(prop, newLoc);
+ }
+}
+
+void QtLocalePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *subProp = m_languageToProperty.value(property, 0)) {
+ m_propertyToLanguage[subProp] = 0;
+ m_languageToProperty.remove(property);
+ } else if (QtProperty *subProp = m_countryToProperty.value(property, 0)) {
+ m_propertyToCountry[subProp] = 0;
+ m_countryToProperty.remove(property);
+ }
+}
+
+/*!
+ \class QtLocalePropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtLocalePropertyManager provides and manages QLocale properties.
+
+ A locale property has nested \e language and \e country
+ subproperties. The top-level property's value can be retrieved
+ using the value() function, and set using the setValue() slot.
+
+ The subproperties are created by QtEnumPropertyManager object.
+ These submanager can be retrieved using the subEnumPropertyManager()
+ function. In order to provide editing widgets for the subproperties
+ in a property browser widget, this manager must be associated with editor factory.
+
+ In addition, QtLocalePropertyManager provides the valueChanged()
+ signal which is emitted whenever a property created by this
+ manager changes.
+
+ \sa QtAbstractPropertyManager, QtEnumPropertyManager
+*/
+
+/*!
+ \fn void QtLocalePropertyManager::valueChanged(QtProperty *property, const QLocale &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtLocalePropertyManager::QtLocalePropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtLocalePropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this);
+ connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotEnumChanged(QtProperty *, int)));
+
+ connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtLocalePropertyManager::~QtLocalePropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e language
+ and \e country subproperties.
+
+ In order to provide editing widgets for the mentioned subproperties
+ in a property browser widget, this manager must be associated with
+ an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtEnumPropertyManager *QtLocalePropertyManager::subEnumPropertyManager() const
+{
+ return d_ptr->m_enumPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns the default locale.
+
+ \sa setValue()
+*/
+QLocale QtLocalePropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QLocale());
+}
+
+/*!
+ \reimp
+*/
+QString QtLocalePropertyManager::valueText(const QtProperty *property) const
+{
+ const QtLocalePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ QLocale loc = it.value();
+
+ int langIdx = 0;
+ int countryIdx = 0;
+ metaEnumProvider()->localeToIndex(loc.language(), loc.country(), &langIdx, &countryIdx);
+ QString str = tr("%1, %2")
+ .arg(metaEnumProvider()->languageEnumNames().at(langIdx))
+ .arg(metaEnumProvider()->countryEnumNames(loc.language()).at(countryIdx));
+ return str;
+}
+
+/*!
+ \fn void QtLocalePropertyManager::setValue(QtProperty *property, const QLocale &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ \sa value(), valueChanged()
+*/
+void QtLocalePropertyManager::setValue(QtProperty *property, const QLocale &val)
+{
+ const QtLocalePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ const QLocale loc = it.value();
+ if (loc == val)
+ return;
+
+ it.value() = val;
+
+ int langIdx = 0;
+ int countryIdx = 0;
+ metaEnumProvider()->localeToIndex(val.language(), val.country(), &langIdx, &countryIdx);
+ if (loc.language() != val.language()) {
+ d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToLanguage.value(property), langIdx);
+ d_ptr->m_enumPropertyManager->setEnumNames(d_ptr->m_propertyToCountry.value(property),
+ metaEnumProvider()->countryEnumNames(val.language()));
+ }
+ d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToCountry.value(property), countryIdx);
+
+ emit propertyChanged(property);
+ emit valueChanged(property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtLocalePropertyManager::initializeProperty(QtProperty *property)
+{
+ QLocale val;
+ d_ptr->m_values[property] = val;
+
+ int langIdx = 0;
+ int countryIdx = 0;
+ metaEnumProvider()->localeToIndex(val.language(), val.country(), &langIdx, &countryIdx);
+
+ QtProperty *languageProp = d_ptr->m_enumPropertyManager->addProperty();
+ languageProp->setPropertyName(tr("Language"));
+ d_ptr->m_enumPropertyManager->setEnumNames(languageProp, metaEnumProvider()->languageEnumNames());
+ d_ptr->m_enumPropertyManager->setValue(languageProp, langIdx);
+ d_ptr->m_propertyToLanguage[property] = languageProp;
+ d_ptr->m_languageToProperty[languageProp] = property;
+ property->addSubProperty(languageProp);
+
+ QtProperty *countryProp = d_ptr->m_enumPropertyManager->addProperty();
+ countryProp->setPropertyName(tr("Country"));
+ d_ptr->m_enumPropertyManager->setEnumNames(countryProp, metaEnumProvider()->countryEnumNames(val.language()));
+ d_ptr->m_enumPropertyManager->setValue(countryProp, countryIdx);
+ d_ptr->m_propertyToCountry[property] = countryProp;
+ d_ptr->m_countryToProperty[countryProp] = property;
+ property->addSubProperty(countryProp);
+}
+
+/*!
+ \reimp
+*/
+void QtLocalePropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *languageProp = d_ptr->m_propertyToLanguage[property];
+ if (languageProp) {
+ d_ptr->m_languageToProperty.remove(languageProp);
+ delete languageProp;
+ }
+ d_ptr->m_propertyToLanguage.remove(property);
+
+ QtProperty *countryProp = d_ptr->m_propertyToCountry[property];
+ if (countryProp) {
+ d_ptr->m_countryToProperty.remove(countryProp);
+ delete countryProp;
+ }
+ d_ptr->m_propertyToCountry.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtPointPropertyManager
+
+class QtPointPropertyManagerPrivate
+{
+ QtPointPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtPointPropertyManager)
+public:
+
+ void slotIntChanged(QtProperty *property, int value);
+ void slotPropertyDestroyed(QtProperty *property);
+
+ typedef QMap<const QtProperty *, QPoint> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtIntPropertyManager *m_intPropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToX;
+ QMap<const QtProperty *, QtProperty *> m_propertyToY;
+
+ QMap<const QtProperty *, QtProperty *> m_xToProperty;
+ QMap<const QtProperty *, QtProperty *> m_yToProperty;
+};
+
+void QtPointPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value)
+{
+ if (QtProperty *xprop = m_xToProperty.value(property, 0)) {
+ QPoint p = m_values[xprop];
+ p.setX(value);
+ q_ptr->setValue(xprop, p);
+ } else if (QtProperty *yprop = m_yToProperty.value(property, 0)) {
+ QPoint p = m_values[yprop];
+ p.setY(value);
+ q_ptr->setValue(yprop, p);
+ }
+}
+
+void QtPointPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_xToProperty.value(property, 0)) {
+ m_propertyToX[pointProp] = 0;
+ m_xToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) {
+ m_propertyToY[pointProp] = 0;
+ m_yToProperty.remove(property);
+ }
+}
+
+/*! \class QtPointPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtPointPropertyManager provides and manages QPoint properties.
+
+ A point property has nested \e x and \e y subproperties. The
+ top-level property's value can be retrieved using the value()
+ function, and set using the setValue() slot.
+
+ The subproperties are created by a QtIntPropertyManager object. This
+ manager can be retrieved using the subIntPropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ In addition, QtPointPropertyManager provides the valueChanged() signal which
+ is emitted whenever a property created by this manager changes.
+
+ \sa QtAbstractPropertyManager, QtIntPropertyManager, QtPointFPropertyManager
+*/
+
+/*!
+ \fn void QtPointPropertyManager::valueChanged(QtProperty *property, const QPoint &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtPointPropertyManager::QtPointPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtPointPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
+ connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotIntChanged(QtProperty *, int)));
+ connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtPointPropertyManager::~QtPointPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e x and \e y
+ subproperties.
+
+ In order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtIntPropertyManager *QtPointPropertyManager::subIntPropertyManager() const
+{
+ return d_ptr->m_intPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns a point with coordinates (0, 0).
+
+ \sa setValue()
+*/
+QPoint QtPointPropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QPoint());
+}
+
+/*!
+ \reimp
+*/
+QString QtPointPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtPointPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ const QPoint v = it.value();
+ return QString(tr("(%1, %2)").arg(QString::number(v.x()))
+ .arg(QString::number(v.y())));
+}
+
+/*!
+ \fn void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ \sa value(), valueChanged()
+*/
+void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &val)
+{
+ const QtPointPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ if (it.value() == val)
+ return;
+
+ it.value() = val;
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], val.x());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], val.y());
+
+ emit propertyChanged(property);
+ emit valueChanged(property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtPointPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QPoint(0, 0);
+
+ QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty();
+ xProp->setPropertyName(tr("X"));
+ d_ptr->m_intPropertyManager->setValue(xProp, 0);
+ d_ptr->m_propertyToX[property] = xProp;
+ d_ptr->m_xToProperty[xProp] = property;
+ property->addSubProperty(xProp);
+
+ QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty();
+ yProp->setPropertyName(tr("Y"));
+ d_ptr->m_intPropertyManager->setValue(yProp, 0);
+ d_ptr->m_propertyToY[property] = yProp;
+ d_ptr->m_yToProperty[yProp] = property;
+ property->addSubProperty(yProp);
+}
+
+/*!
+ \reimp
+*/
+void QtPointPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *xProp = d_ptr->m_propertyToX[property];
+ if (xProp) {
+ d_ptr->m_xToProperty.remove(xProp);
+ delete xProp;
+ }
+ d_ptr->m_propertyToX.remove(property);
+
+ QtProperty *yProp = d_ptr->m_propertyToY[property];
+ if (yProp) {
+ d_ptr->m_yToProperty.remove(yProp);
+ delete yProp;
+ }
+ d_ptr->m_propertyToY.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtPointFPropertyManager
+
+class QtPointFPropertyManagerPrivate
+{
+ QtPointFPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtPointFPropertyManager)
+public:
+
+ struct Data
+ {
+ Data() : decimals(2) {}
+ QPointF val;
+ int decimals;
+ };
+
+ void slotDoubleChanged(QtProperty *property, double value);
+ void slotPropertyDestroyed(QtProperty *property);
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtDoublePropertyManager *m_doublePropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToX;
+ QMap<const QtProperty *, QtProperty *> m_propertyToY;
+
+ QMap<const QtProperty *, QtProperty *> m_xToProperty;
+ QMap<const QtProperty *, QtProperty *> m_yToProperty;
+};
+
+void QtPointFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value)
+{
+ if (QtProperty *prop = m_xToProperty.value(property, 0)) {
+ QPointF p = m_values[prop].val;
+ p.setX(value);
+ q_ptr->setValue(prop, p);
+ } else if (QtProperty *prop = m_yToProperty.value(property, 0)) {
+ QPointF p = m_values[prop].val;
+ p.setY(value);
+ q_ptr->setValue(prop, p);
+ }
+}
+
+void QtPointFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_xToProperty.value(property, 0)) {
+ m_propertyToX[pointProp] = 0;
+ m_xToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) {
+ m_propertyToY[pointProp] = 0;
+ m_yToProperty.remove(property);
+ }
+}
+
+/*! \class QtPointFPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtPointFPropertyManager provides and manages QPointF properties.
+
+ A point property has nested \e x and \e y subproperties. The
+ top-level property's value can be retrieved using the value()
+ function, and set using the setValue() slot.
+
+ The subproperties are created by a QtDoublePropertyManager object. This
+ manager can be retrieved using the subDoublePropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ In addition, QtPointFPropertyManager provides the valueChanged() signal which
+ is emitted whenever a property created by this manager changes.
+
+ \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtPointPropertyManager
+*/
+
+/*!
+ \fn void QtPointFPropertyManager::valueChanged(QtProperty *property, const QPointF &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtPointFPropertyManager::decimalsChanged(QtProperty *property, int prec)
+
+ This signal is emitted whenever a property created by this manager
+ changes its precision of value, passing a pointer to the
+ \a property and the new \a prec value
+
+ \sa setDecimals()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtPointFPropertyManager::QtPointFPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtPointFPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this);
+ connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotDoubleChanged(QtProperty *, double)));
+ connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtPointFPropertyManager::~QtPointFPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e x and \e y
+ subproperties.
+
+ In order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtDoublePropertyManager *QtPointFPropertyManager::subDoublePropertyManager() const
+{
+ return d_ptr->m_doublePropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns a point with coordinates (0, 0).
+
+ \sa setValue()
+*/
+QPointF QtPointFPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<QPointF>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's precision, in decimals.
+
+ \sa setDecimals()
+*/
+int QtPointFPropertyManager::decimals(const QtProperty *property) const
+{
+ return getData<int>(d_ptr->m_values, &QtPointFPropertyManagerPrivate::Data::decimals, property, 0);
+}
+
+/*!
+ \reimp
+*/
+QString QtPointFPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtPointFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ const QPointF v = it.value().val;
+ const int dec = it.value().decimals;
+ return QString(tr("(%1, %2)").arg(QString::number(v.x(), 'f', dec))
+ .arg(QString::number(v.y(), 'f', dec)));
+}
+
+/*!
+ \fn void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ \sa value(), valueChanged()
+*/
+void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &val)
+{
+ const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ if (it.value().val == val)
+ return;
+
+ it.value().val = val;
+ d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], val.x());
+ d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], val.y());
+
+ emit propertyChanged(property);
+ emit valueChanged(property, val);
+}
+
+/*!
+ \fn void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec)
+
+ Sets the precision of the given \a property to \a prec.
+
+ The valid decimal range is 0-13. The default is 2.
+
+ \sa decimals()
+*/
+void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec)
+{
+ const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtPointFPropertyManagerPrivate::Data data = it.value();
+
+ if (prec > 13)
+ prec = 13;
+ else if (prec < 0)
+ prec = 0;
+
+ if (data.decimals == prec)
+ return;
+
+ data.decimals = prec;
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec);
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec);
+
+ it.value() = data;
+
+ emit decimalsChanged(property, data.decimals);
+}
+
+/*!
+ \reimp
+*/
+void QtPointFPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtPointFPropertyManagerPrivate::Data();
+
+ QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty();
+ xProp->setPropertyName(tr("X"));
+ d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(xProp, 0);
+ d_ptr->m_propertyToX[property] = xProp;
+ d_ptr->m_xToProperty[xProp] = property;
+ property->addSubProperty(xProp);
+
+ QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty();
+ yProp->setPropertyName(tr("Y"));
+ d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(yProp, 0);
+ d_ptr->m_propertyToY[property] = yProp;
+ d_ptr->m_yToProperty[yProp] = property;
+ property->addSubProperty(yProp);
+}
+
+/*!
+ \reimp
+*/
+void QtPointFPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *xProp = d_ptr->m_propertyToX[property];
+ if (xProp) {
+ d_ptr->m_xToProperty.remove(xProp);
+ delete xProp;
+ }
+ d_ptr->m_propertyToX.remove(property);
+
+ QtProperty *yProp = d_ptr->m_propertyToY[property];
+ if (yProp) {
+ d_ptr->m_yToProperty.remove(yProp);
+ delete yProp;
+ }
+ d_ptr->m_propertyToY.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtSizePropertyManager
+
+class QtSizePropertyManagerPrivate
+{
+ QtSizePropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtSizePropertyManager)
+public:
+
+ void slotIntChanged(QtProperty *property, int value);
+ void slotPropertyDestroyed(QtProperty *property);
+ void setValue(QtProperty *property, const QSize &val);
+ void setRange(QtProperty *property,
+ const QSize &minVal, const QSize &maxVal, const QSize &val);
+
+ struct Data
+ {
+ Data() : val(QSize(0, 0)), minVal(QSize(0, 0)), maxVal(QSize(INT_MAX, INT_MAX)) {}
+ QSize val;
+ QSize minVal;
+ QSize maxVal;
+ QSize minimumValue() const { return minVal; }
+ QSize maximumValue() const { return maxVal; }
+ void setMinimumValue(const QSize &newMinVal) { setSizeMinimumData(this, newMinVal); }
+ void setMaximumValue(const QSize &newMaxVal) { setSizeMaximumData(this, newMaxVal); }
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtIntPropertyManager *m_intPropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToW;
+ QMap<const QtProperty *, QtProperty *> m_propertyToH;
+
+ QMap<const QtProperty *, QtProperty *> m_wToProperty;
+ QMap<const QtProperty *, QtProperty *> m_hToProperty;
+};
+
+void QtSizePropertyManagerPrivate::slotIntChanged(QtProperty *property, int value)
+{
+ if (QtProperty *prop = m_wToProperty.value(property, 0)) {
+ QSize s = m_values[prop].val;
+ s.setWidth(value);
+ q_ptr->setValue(prop, s);
+ } else if (QtProperty *prop = m_hToProperty.value(property, 0)) {
+ QSize s = m_values[prop].val;
+ s.setHeight(value);
+ q_ptr->setValue(prop, s);
+ }
+}
+
+void QtSizePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_wToProperty.value(property, 0)) {
+ m_propertyToW[pointProp] = 0;
+ m_wToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) {
+ m_propertyToH[pointProp] = 0;
+ m_hToProperty.remove(property);
+ }
+}
+
+void QtSizePropertyManagerPrivate::setValue(QtProperty *property, const QSize &val)
+{
+ m_intPropertyManager->setValue(m_propertyToW.value(property), val.width());
+ m_intPropertyManager->setValue(m_propertyToH.value(property), val.height());
+}
+
+void QtSizePropertyManagerPrivate::setRange(QtProperty *property,
+ const QSize &minVal, const QSize &maxVal, const QSize &val)
+{
+ QtProperty *wProperty = m_propertyToW.value(property);
+ QtProperty *hProperty = m_propertyToH.value(property);
+ m_intPropertyManager->setRange(wProperty, minVal.width(), maxVal.width());
+ m_intPropertyManager->setValue(wProperty, val.width());
+ m_intPropertyManager->setRange(hProperty, minVal.height(), maxVal.height());
+ m_intPropertyManager->setValue(hProperty, val.height());
+}
+
+/*!
+ \class QtSizePropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtSizePropertyManager provides and manages QSize properties.
+
+ A size property has nested \e width and \e height
+ subproperties. The top-level property's value can be retrieved
+ using the value() function, and set using the setValue() slot.
+
+ The subproperties are created by a QtIntPropertyManager object. This
+ manager can be retrieved using the subIntPropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ A size property also has a range of valid values defined by a
+ minimum size and a maximum size. These sizes can be retrieved
+ using the minimum() and the maximum() functions, and set using the
+ setMinimum() and setMaximum() slots. Alternatively, the range can
+ be defined in one go using the setRange() slot.
+
+ In addition, QtSizePropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the rangeChanged() signal which is emitted whenever
+ such a property changes its range of valid sizes.
+
+ \sa QtAbstractPropertyManager, QtIntPropertyManager, QtSizeFPropertyManager
+*/
+
+/*!
+ \fn void QtSizePropertyManager::valueChanged(QtProperty *property, const QSize &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtSizePropertyManager::rangeChanged(QtProperty *property, const QSize &minimum, const QSize &maximum)
+
+ This signal is emitted whenever a property created by this manager
+ changes its range of valid sizes, passing a pointer to the \a
+ property and the new \a minimum and \a maximum sizes.
+
+ \sa setRange()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtSizePropertyManager::QtSizePropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtSizePropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
+ connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotIntChanged(QtProperty *, int)));
+ connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtSizePropertyManager::~QtSizePropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e width and \e height
+ subproperties.
+
+ In order to provide editing widgets for the \e width and \e height
+ properties in a property browser widget, this manager must be
+ associated with an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtIntPropertyManager *QtSizePropertyManager::subIntPropertyManager() const
+{
+ return d_ptr->m_intPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an invalid size
+
+ \sa setValue()
+*/
+QSize QtSizePropertyManager::value(const QtProperty *property) const
+{
+ return getValue<QSize>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's minimum size value.
+
+ \sa setMinimum(), maximum(), setRange()
+*/
+QSize QtSizePropertyManager::minimum(const QtProperty *property) const
+{
+ return getMinimum<QSize>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's maximum size value.
+
+ \sa setMaximum(), minimum(), setRange()
+*/
+QSize QtSizePropertyManager::maximum(const QtProperty *property) const
+{
+ return getMaximum<QSize>(d_ptr->m_values, property);
+}
+
+/*!
+ \reimp
+*/
+QString QtSizePropertyManager::valueText(const QtProperty *property) const
+{
+ const QtSizePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ const QSize v = it.value().val;
+ return QString(tr("%1 x %2").arg(QString::number(v.width()))
+ .arg(QString::number(v.height())));
+}
+
+/*!
+ \fn void QtSizePropertyManager::setValue(QtProperty *property, const QSize &value)
+
+ Sets the value of the given \a property to \a value.
+
+ If the specified \a value is not valid according to the given \a
+ property's size range, the \a value is adjusted to the nearest
+ valid value within the size range.
+
+ \sa value(), setRange(), valueChanged()
+*/
+void QtSizePropertyManager::setValue(QtProperty *property, const QSize &val)
+{
+ setValueInRange<const QSize &, QtSizePropertyManagerPrivate, QtSizePropertyManager, const QSize>(this, d_ptr,
+ &QtSizePropertyManager::propertyChanged,
+ &QtSizePropertyManager::valueChanged,
+ property, val, &QtSizePropertyManagerPrivate::setValue);
+}
+
+/*!
+ Sets the minimum size value for the given \a property to \a minVal.
+
+ When setting the minimum size value, the maximum and current
+ values are adjusted if necessary (ensuring that the size range
+ remains valid and that the current value is within the range).
+
+ \sa minimum(), setRange(), rangeChanged()
+*/
+void QtSizePropertyManager::setMinimum(QtProperty *property, const QSize &minVal)
+{
+ setBorderValue<const QSize &, QtSizePropertyManagerPrivate, QtSizePropertyManager, QSize, QtSizePropertyManagerPrivate::Data>(this, d_ptr,
+ &QtSizePropertyManager::propertyChanged,
+ &QtSizePropertyManager::valueChanged,
+ &QtSizePropertyManager::rangeChanged,
+ property,
+ &QtSizePropertyManagerPrivate::Data::minimumValue,
+ &QtSizePropertyManagerPrivate::Data::setMinimumValue,
+ minVal, &QtSizePropertyManagerPrivate::setRange);
+}
+
+/*!
+ Sets the maximum size value for the given \a property to \a maxVal.
+
+ When setting the maximum size value, the minimum and current
+ values are adjusted if necessary (ensuring that the size range
+ remains valid and that the current value is within the range).
+
+ \sa maximum(), setRange(), rangeChanged()
+*/
+void QtSizePropertyManager::setMaximum(QtProperty *property, const QSize &maxVal)
+{
+ setBorderValue<const QSize &, QtSizePropertyManagerPrivate, QtSizePropertyManager, QSize, QtSizePropertyManagerPrivate::Data>(this, d_ptr,
+ &QtSizePropertyManager::propertyChanged,
+ &QtSizePropertyManager::valueChanged,
+ &QtSizePropertyManager::rangeChanged,
+ property,
+ &QtSizePropertyManagerPrivate::Data::maximumValue,
+ &QtSizePropertyManagerPrivate::Data::setMaximumValue,
+ maxVal, &QtSizePropertyManagerPrivate::setRange);
+}
+
+/*!
+ \fn void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minimum, const QSize &maximum)
+
+ Sets the range of valid values.
+
+ This is a convenience function defining the range of valid values
+ in one go; setting the \a minimum and \a maximum values for the
+ given \a property with a single function call.
+
+ When setting a new range, the current value is adjusted if
+ necessary (ensuring that the value remains within the range).
+
+ \sa setMinimum(), setMaximum(), rangeChanged()
+*/
+void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal)
+{
+ setBorderValues<const QSize &, QtSizePropertyManagerPrivate, QtSizePropertyManager, QSize>(this, d_ptr,
+ &QtSizePropertyManager::propertyChanged,
+ &QtSizePropertyManager::valueChanged,
+ &QtSizePropertyManager::rangeChanged,
+ property, minVal, maxVal, &QtSizePropertyManagerPrivate::setRange);
+}
+
+/*!
+ \reimp
+*/
+void QtSizePropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtSizePropertyManagerPrivate::Data();
+
+ QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty();
+ wProp->setPropertyName(tr("Width"));
+ d_ptr->m_intPropertyManager->setValue(wProp, 0);
+ d_ptr->m_intPropertyManager->setMinimum(wProp, 0);
+ d_ptr->m_propertyToW[property] = wProp;
+ d_ptr->m_wToProperty[wProp] = property;
+ property->addSubProperty(wProp);
+
+ QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty();
+ hProp->setPropertyName(tr("Height"));
+ d_ptr->m_intPropertyManager->setValue(hProp, 0);
+ d_ptr->m_intPropertyManager->setMinimum(hProp, 0);
+ d_ptr->m_propertyToH[property] = hProp;
+ d_ptr->m_hToProperty[hProp] = property;
+ property->addSubProperty(hProp);
+}
+
+/*!
+ \reimp
+*/
+void QtSizePropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *wProp = d_ptr->m_propertyToW[property];
+ if (wProp) {
+ d_ptr->m_wToProperty.remove(wProp);
+ delete wProp;
+ }
+ d_ptr->m_propertyToW.remove(property);
+
+ QtProperty *hProp = d_ptr->m_propertyToH[property];
+ if (hProp) {
+ d_ptr->m_hToProperty.remove(hProp);
+ delete hProp;
+ }
+ d_ptr->m_propertyToH.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtSizeFPropertyManager
+
+class QtSizeFPropertyManagerPrivate
+{
+ QtSizeFPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtSizeFPropertyManager)
+public:
+
+ void slotDoubleChanged(QtProperty *property, double value);
+ void slotPropertyDestroyed(QtProperty *property);
+ void setValue(QtProperty *property, const QSizeF &val);
+ void setRange(QtProperty *property,
+ const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val);
+
+ struct Data
+ {
+ Data() : val(QSizeF(0, 0)), minVal(QSizeF(0, 0)), maxVal(QSizeF(INT_MAX, INT_MAX)), decimals(2) {}
+ QSizeF val;
+ QSizeF minVal;
+ QSizeF maxVal;
+ int decimals;
+ QSizeF minimumValue() const { return minVal; }
+ QSizeF maximumValue() const { return maxVal; }
+ void setMinimumValue(const QSizeF &newMinVal) { setSizeMinimumData(this, newMinVal); }
+ void setMaximumValue(const QSizeF &newMaxVal) { setSizeMaximumData(this, newMaxVal); }
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtDoublePropertyManager *m_doublePropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToW;
+ QMap<const QtProperty *, QtProperty *> m_propertyToH;
+
+ QMap<const QtProperty *, QtProperty *> m_wToProperty;
+ QMap<const QtProperty *, QtProperty *> m_hToProperty;
+};
+
+void QtSizeFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value)
+{
+ if (QtProperty *prop = m_wToProperty.value(property, 0)) {
+ QSizeF s = m_values[prop].val;
+ s.setWidth(value);
+ q_ptr->setValue(prop, s);
+ } else if (QtProperty *prop = m_hToProperty.value(property, 0)) {
+ QSizeF s = m_values[prop].val;
+ s.setHeight(value);
+ q_ptr->setValue(prop, s);
+ }
+}
+
+void QtSizeFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_wToProperty.value(property, 0)) {
+ m_propertyToW[pointProp] = 0;
+ m_wToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) {
+ m_propertyToH[pointProp] = 0;
+ m_hToProperty.remove(property);
+ }
+}
+
+void QtSizeFPropertyManagerPrivate::setValue(QtProperty *property, const QSizeF &val)
+{
+ m_doublePropertyManager->setValue(m_propertyToW.value(property), val.width());
+ m_doublePropertyManager->setValue(m_propertyToH.value(property), val.height());
+}
+
+void QtSizeFPropertyManagerPrivate::setRange(QtProperty *property,
+ const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val)
+{
+ m_doublePropertyManager->setRange(m_propertyToW[property], minVal.width(), maxVal.width());
+ m_doublePropertyManager->setValue(m_propertyToW[property], val.width());
+ m_doublePropertyManager->setRange(m_propertyToH[property], minVal.height(), maxVal.height());
+ m_doublePropertyManager->setValue(m_propertyToH[property], val.height());
+}
+
+/*!
+ \class QtSizeFPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtSizeFPropertyManager provides and manages QSizeF properties.
+
+ A size property has nested \e width and \e height
+ subproperties. The top-level property's value can be retrieved
+ using the value() function, and set using the setValue() slot.
+
+ The subproperties are created by a QtDoublePropertyManager object. This
+ manager can be retrieved using the subDoublePropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ A size property also has a range of valid values defined by a
+ minimum size and a maximum size. These sizes can be retrieved
+ using the minimum() and the maximum() functions, and set using the
+ setMinimum() and setMaximum() slots. Alternatively, the range can
+ be defined in one go using the setRange() slot.
+
+ In addition, QtSizeFPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the rangeChanged() signal which is emitted whenever
+ such a property changes its range of valid sizes.
+
+ \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtSizePropertyManager
+*/
+
+/*!
+ \fn void QtSizeFPropertyManager::valueChanged(QtProperty *property, const QSizeF &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtSizeFPropertyManager::rangeChanged(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum)
+
+ This signal is emitted whenever a property created by this manager
+ changes its range of valid sizes, passing a pointer to the \a
+ property and the new \a minimum and \a maximum sizes.
+
+ \sa setRange()
+*/
+
+/*!
+ \fn void QtSizeFPropertyManager::decimalsChanged(QtProperty *property, int prec)
+
+ This signal is emitted whenever a property created by this manager
+ changes its precision of value, passing a pointer to the
+ \a property and the new \a prec value
+
+ \sa setDecimals()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtSizeFPropertyManager::QtSizeFPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtSizeFPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this);
+ connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotDoubleChanged(QtProperty *, double)));
+ connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtSizeFPropertyManager::~QtSizeFPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e width and \e height
+ subproperties.
+
+ In order to provide editing widgets for the \e width and \e height
+ properties in a property browser widget, this manager must be
+ associated with an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtDoublePropertyManager *QtSizeFPropertyManager::subDoublePropertyManager() const
+{
+ return d_ptr->m_doublePropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an invalid size
+
+ \sa setValue()
+*/
+QSizeF QtSizeFPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<QSizeF>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's precision, in decimals.
+
+ \sa setDecimals()
+*/
+int QtSizeFPropertyManager::decimals(const QtProperty *property) const
+{
+ return getData<int>(d_ptr->m_values, &QtSizeFPropertyManagerPrivate::Data::decimals, property, 0);
+}
+
+/*!
+ Returns the given \a property's minimum size value.
+
+ \sa setMinimum(), maximum(), setRange()
+*/
+QSizeF QtSizeFPropertyManager::minimum(const QtProperty *property) const
+{
+ return getMinimum<QSizeF>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's maximum size value.
+
+ \sa setMaximum(), minimum(), setRange()
+*/
+QSizeF QtSizeFPropertyManager::maximum(const QtProperty *property) const
+{
+ return getMaximum<QSizeF>(d_ptr->m_values, property);
+}
+
+/*!
+ \reimp
+*/
+QString QtSizeFPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtSizeFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ const QSizeF v = it.value().val;
+ const int dec = it.value().decimals;
+ return QString(tr("%1 x %2").arg(QString::number(v.width(), 'f', dec))
+ .arg(QString::number(v.height(), 'f', dec)));
+}
+
+/*!
+ \fn void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &value)
+
+ Sets the value of the given \a property to \a value.
+
+ If the specified \a value is not valid according to the given \a
+ property's size range, the \a value is adjusted to the nearest
+ valid value within the size range.
+
+ \sa value(), setRange(), valueChanged()
+*/
+void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &val)
+{
+ setValueInRange<const QSizeF &, QtSizeFPropertyManagerPrivate, QtSizeFPropertyManager, QSizeF>(this, d_ptr,
+ &QtSizeFPropertyManager::propertyChanged,
+ &QtSizeFPropertyManager::valueChanged,
+ property, val, &QtSizeFPropertyManagerPrivate::setValue);
+}
+
+/*!
+ \fn void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec)
+
+ Sets the precision of the given \a property to \a prec.
+
+ The valid decimal range is 0-13. The default is 2.
+
+ \sa decimals()
+*/
+void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec)
+{
+ const QtSizeFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtSizeFPropertyManagerPrivate::Data data = it.value();
+
+ if (prec > 13)
+ prec = 13;
+ else if (prec < 0)
+ prec = 0;
+
+ if (data.decimals == prec)
+ return;
+
+ data.decimals = prec;
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec);
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec);
+
+ it.value() = data;
+
+ emit decimalsChanged(property, data.decimals);
+}
+
+/*!
+ Sets the minimum size value for the given \a property to \a minVal.
+
+ When setting the minimum size value, the maximum and current
+ values are adjusted if necessary (ensuring that the size range
+ remains valid and that the current value is within the range).
+
+ \sa minimum(), setRange(), rangeChanged()
+*/
+void QtSizeFPropertyManager::setMinimum(QtProperty *property, const QSizeF &minVal)
+{
+ setBorderValue<const QSizeF &, QtSizeFPropertyManagerPrivate, QtSizeFPropertyManager, QSizeF, QtSizeFPropertyManagerPrivate::Data>(this, d_ptr,
+ &QtSizeFPropertyManager::propertyChanged,
+ &QtSizeFPropertyManager::valueChanged,
+ &QtSizeFPropertyManager::rangeChanged,
+ property,
+ &QtSizeFPropertyManagerPrivate::Data::minimumValue,
+ &QtSizeFPropertyManagerPrivate::Data::setMinimumValue,
+ minVal, &QtSizeFPropertyManagerPrivate::setRange);
+}
+
+/*!
+ Sets the maximum size value for the given \a property to \a maxVal.
+
+ When setting the maximum size value, the minimum and current
+ values are adjusted if necessary (ensuring that the size range
+ remains valid and that the current value is within the range).
+
+ \sa maximum(), setRange(), rangeChanged()
+*/
+void QtSizeFPropertyManager::setMaximum(QtProperty *property, const QSizeF &maxVal)
+{
+ setBorderValue<const QSizeF &, QtSizeFPropertyManagerPrivate, QtSizeFPropertyManager, QSizeF, QtSizeFPropertyManagerPrivate::Data>(this, d_ptr,
+ &QtSizeFPropertyManager::propertyChanged,
+ &QtSizeFPropertyManager::valueChanged,
+ &QtSizeFPropertyManager::rangeChanged,
+ property,
+ &QtSizeFPropertyManagerPrivate::Data::maximumValue,
+ &QtSizeFPropertyManagerPrivate::Data::setMaximumValue,
+ maxVal, &QtSizeFPropertyManagerPrivate::setRange);
+}
+
+/*!
+ \fn void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum)
+
+ Sets the range of valid values.
+
+ This is a convenience function defining the range of valid values
+ in one go; setting the \a minimum and \a maximum values for the
+ given \a property with a single function call.
+
+ When setting a new range, the current value is adjusted if
+ necessary (ensuring that the value remains within the range).
+
+ \sa setMinimum(), setMaximum(), rangeChanged()
+*/
+void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal)
+{
+ setBorderValues<const QSizeF &, QtSizeFPropertyManagerPrivate, QtSizeFPropertyManager, QSizeF>(this, d_ptr,
+ &QtSizeFPropertyManager::propertyChanged,
+ &QtSizeFPropertyManager::valueChanged,
+ &QtSizeFPropertyManager::rangeChanged,
+ property, minVal, maxVal, &QtSizeFPropertyManagerPrivate::setRange);
+}
+
+/*!
+ \reimp
+*/
+void QtSizeFPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtSizeFPropertyManagerPrivate::Data();
+
+ QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty();
+ wProp->setPropertyName(tr("Width"));
+ d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(wProp, 0);
+ d_ptr->m_doublePropertyManager->setMinimum(wProp, 0);
+ d_ptr->m_propertyToW[property] = wProp;
+ d_ptr->m_wToProperty[wProp] = property;
+ property->addSubProperty(wProp);
+
+ QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty();
+ hProp->setPropertyName(tr("Height"));
+ d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(hProp, 0);
+ d_ptr->m_doublePropertyManager->setMinimum(hProp, 0);
+ d_ptr->m_propertyToH[property] = hProp;
+ d_ptr->m_hToProperty[hProp] = property;
+ property->addSubProperty(hProp);
+}
+
+/*!
+ \reimp
+*/
+void QtSizeFPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *wProp = d_ptr->m_propertyToW[property];
+ if (wProp) {
+ d_ptr->m_wToProperty.remove(wProp);
+ delete wProp;
+ }
+ d_ptr->m_propertyToW.remove(property);
+
+ QtProperty *hProp = d_ptr->m_propertyToH[property];
+ if (hProp) {
+ d_ptr->m_hToProperty.remove(hProp);
+ delete hProp;
+ }
+ d_ptr->m_propertyToH.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtRectPropertyManager
+
+class QtRectPropertyManagerPrivate
+{
+ QtRectPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtRectPropertyManager)
+public:
+
+ void slotIntChanged(QtProperty *property, int value);
+ void slotPropertyDestroyed(QtProperty *property);
+ void setConstraint(QtProperty *property, const QRect &constraint, const QRect &val);
+
+ struct Data
+ {
+ Data() : val(0, 0, 0, 0) {}
+ QRect val;
+ QRect constraint;
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtIntPropertyManager *m_intPropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToX;
+ QMap<const QtProperty *, QtProperty *> m_propertyToY;
+ QMap<const QtProperty *, QtProperty *> m_propertyToW;
+ QMap<const QtProperty *, QtProperty *> m_propertyToH;
+
+ QMap<const QtProperty *, QtProperty *> m_xToProperty;
+ QMap<const QtProperty *, QtProperty *> m_yToProperty;
+ QMap<const QtProperty *, QtProperty *> m_wToProperty;
+ QMap<const QtProperty *, QtProperty *> m_hToProperty;
+};
+
+void QtRectPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value)
+{
+ if (QtProperty *prop = m_xToProperty.value(property, 0)) {
+ QRect r = m_values[prop].val;
+ r.moveLeft(value);
+ q_ptr->setValue(prop, r);
+ } else if (QtProperty *prop = m_yToProperty.value(property)) {
+ QRect r = m_values[prop].val;
+ r.moveTop(value);
+ q_ptr->setValue(prop, r);
+ } else if (QtProperty *prop = m_wToProperty.value(property, 0)) {
+ Data data = m_values[prop];
+ QRect r = data.val;
+ r.setWidth(value);
+ if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) {
+ r.moveLeft(data.constraint.left() + data.constraint.width() - r.width());
+ }
+ q_ptr->setValue(prop, r);
+ } else if (QtProperty *prop = m_hToProperty.value(property, 0)) {
+ Data data = m_values[prop];
+ QRect r = data.val;
+ r.setHeight(value);
+ if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) {
+ r.moveTop(data.constraint.top() + data.constraint.height() - r.height());
+ }
+ q_ptr->setValue(prop, r);
+ }
+}
+
+void QtRectPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_xToProperty.value(property, 0)) {
+ m_propertyToX[pointProp] = 0;
+ m_xToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) {
+ m_propertyToY[pointProp] = 0;
+ m_yToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) {
+ m_propertyToW[pointProp] = 0;
+ m_wToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) {
+ m_propertyToH[pointProp] = 0;
+ m_hToProperty.remove(property);
+ }
+}
+
+void QtRectPropertyManagerPrivate::setConstraint(QtProperty *property,
+ const QRect &constraint, const QRect &val)
+{
+ const bool isNull = constraint.isNull();
+ const int left = isNull ? INT_MIN : constraint.left();
+ const int right = isNull ? INT_MAX : constraint.left() + constraint.width();
+ const int top = isNull ? INT_MIN : constraint.top();
+ const int bottom = isNull ? INT_MAX : constraint.top() + constraint.height();
+ const int width = isNull ? INT_MAX : constraint.width();
+ const int height = isNull ? INT_MAX : constraint.height();
+
+ m_intPropertyManager->setRange(m_propertyToX[property], left, right);
+ m_intPropertyManager->setRange(m_propertyToY[property], top, bottom);
+ m_intPropertyManager->setRange(m_propertyToW[property], 0, width);
+ m_intPropertyManager->setRange(m_propertyToH[property], 0, height);
+
+ m_intPropertyManager->setValue(m_propertyToX[property], val.x());
+ m_intPropertyManager->setValue(m_propertyToY[property], val.y());
+ m_intPropertyManager->setValue(m_propertyToW[property], val.width());
+ m_intPropertyManager->setValue(m_propertyToH[property], val.height());
+}
+
+/*!
+ \class QtRectPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtRectPropertyManager provides and manages QRect properties.
+
+ A rectangle property has nested \e x, \e y, \e width and \e height
+ subproperties. The top-level property's value can be retrieved
+ using the value() function, and set using the setValue() slot.
+
+ The subproperties are created by a QtIntPropertyManager object. This
+ manager can be retrieved using the subIntPropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ A rectangle property also has a constraint rectangle which can be
+ retrieved using the constraint() function, and set using the
+ setConstraint() slot.
+
+ In addition, QtRectPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the constraintChanged() signal which is emitted
+ whenever such a property changes its constraint rectangle.
+
+ \sa QtAbstractPropertyManager, QtIntPropertyManager, QtRectFPropertyManager
+*/
+
+/*!
+ \fn void QtRectPropertyManager::valueChanged(QtProperty *property, const QRect &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtRectPropertyManager::constraintChanged(QtProperty *property, const QRect &constraint)
+
+ This signal is emitted whenever property changes its constraint
+ rectangle, passing a pointer to the \a property and the new \a
+ constraint rectangle as parameters.
+
+ \sa setConstraint()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtRectPropertyManager::QtRectPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtRectPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
+ connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotIntChanged(QtProperty *, int)));
+ connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtRectPropertyManager::~QtRectPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e x, \e y, \e width
+ and \e height subproperties.
+
+ In order to provide editing widgets for the mentioned
+ subproperties in a property browser widget, this manager must be
+ associated with an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtIntPropertyManager *QtRectPropertyManager::subIntPropertyManager() const
+{
+ return d_ptr->m_intPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an invalid rectangle.
+
+ \sa setValue(), constraint()
+*/
+QRect QtRectPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<QRect>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's constraining rectangle. If returned value is null QRect it means there is no constraint applied.
+
+ \sa value(), setConstraint()
+*/
+QRect QtRectPropertyManager::constraint(const QtProperty *property) const
+{
+ return getData<QRect>(d_ptr->m_values, &QtRectPropertyManagerPrivate::Data::constraint, property, QRect());
+}
+
+/*!
+ \reimp
+*/
+QString QtRectPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtRectPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ const QRect v = it.value().val;
+ return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x()))
+ .arg(QString::number(v.y()))
+ .arg(QString::number(v.width()))
+ .arg(QString::number(v.height())));
+}
+
+/*!
+ \fn void QtRectPropertyManager::setValue(QtProperty *property, const QRect &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ If the specified \a value is not inside the given \a property's
+ constraining rectangle, the value is adjusted accordingly to fit
+ within the constraint.
+
+ \sa value(), setConstraint(), valueChanged()
+*/
+void QtRectPropertyManager::setValue(QtProperty *property, const QRect &val)
+{
+ const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtRectPropertyManagerPrivate::Data data = it.value();
+
+ QRect newRect = val.normalized();
+ if (!data.constraint.isNull() && !data.constraint.contains(newRect)) {
+ const QRect r1 = data.constraint;
+ const QRect r2 = newRect;
+ newRect.setLeft(qMax(r1.left(), r2.left()));
+ newRect.setRight(qMin(r1.right(), r2.right()));
+ newRect.setTop(qMax(r1.top(), r2.top()));
+ newRect.setBottom(qMin(r1.bottom(), r2.bottom()));
+ if (newRect.width() < 0 || newRect.height() < 0)
+ return;
+ }
+
+ if (data.val == newRect)
+ return;
+
+ data.val = newRect;
+
+ it.value() = data;
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height());
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ Sets the given \a property's constraining rectangle to \a
+ constraint.
+
+ When setting the constraint, the current value is adjusted if
+ necessary (ensuring that the current rectangle value is inside the
+ constraint). In order to reset the constraint pass a null QRect value.
+
+ \sa setValue(), constraint(), constraintChanged()
+*/
+void QtRectPropertyManager::setConstraint(QtProperty *property, const QRect &constraint)
+{
+ const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtRectPropertyManagerPrivate::Data data = it.value();
+
+ QRect newConstraint = constraint.normalized();
+ if (data.constraint == newConstraint)
+ return;
+
+ const QRect oldVal = data.val;
+
+ data.constraint = newConstraint;
+
+ if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) {
+ QRect r1 = data.constraint;
+ QRect r2 = data.val;
+
+ if (r2.width() > r1.width())
+ r2.setWidth(r1.width());
+ if (r2.height() > r1.height())
+ r2.setHeight(r1.height());
+ if (r2.left() < r1.left())
+ r2.moveLeft(r1.left());
+ else if (r2.right() > r1.right())
+ r2.moveRight(r1.right());
+ if (r2.top() < r1.top())
+ r2.moveTop(r1.top());
+ else if (r2.bottom() > r1.bottom())
+ r2.moveBottom(r1.bottom());
+
+ data.val = r2;
+ }
+
+ it.value() = data;
+
+ emit constraintChanged(property, data.constraint);
+
+ d_ptr->setConstraint(property, data.constraint, data.val);
+
+ if (data.val == oldVal)
+ return;
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ \reimp
+*/
+void QtRectPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtRectPropertyManagerPrivate::Data();
+
+ QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty();
+ xProp->setPropertyName(tr("X"));
+ d_ptr->m_intPropertyManager->setValue(xProp, 0);
+ d_ptr->m_propertyToX[property] = xProp;
+ d_ptr->m_xToProperty[xProp] = property;
+ property->addSubProperty(xProp);
+
+ QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty();
+ yProp->setPropertyName(tr("Y"));
+ d_ptr->m_intPropertyManager->setValue(yProp, 0);
+ d_ptr->m_propertyToY[property] = yProp;
+ d_ptr->m_yToProperty[yProp] = property;
+ property->addSubProperty(yProp);
+
+ QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty();
+ wProp->setPropertyName(tr("Width"));
+ d_ptr->m_intPropertyManager->setValue(wProp, 0);
+ d_ptr->m_intPropertyManager->setMinimum(wProp, 0);
+ d_ptr->m_propertyToW[property] = wProp;
+ d_ptr->m_wToProperty[wProp] = property;
+ property->addSubProperty(wProp);
+
+ QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty();
+ hProp->setPropertyName(tr("Height"));
+ d_ptr->m_intPropertyManager->setValue(hProp, 0);
+ d_ptr->m_intPropertyManager->setMinimum(hProp, 0);
+ d_ptr->m_propertyToH[property] = hProp;
+ d_ptr->m_hToProperty[hProp] = property;
+ property->addSubProperty(hProp);
+}
+
+/*!
+ \reimp
+*/
+void QtRectPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *xProp = d_ptr->m_propertyToX[property];
+ if (xProp) {
+ d_ptr->m_xToProperty.remove(xProp);
+ delete xProp;
+ }
+ d_ptr->m_propertyToX.remove(property);
+
+ QtProperty *yProp = d_ptr->m_propertyToY[property];
+ if (yProp) {
+ d_ptr->m_yToProperty.remove(yProp);
+ delete yProp;
+ }
+ d_ptr->m_propertyToY.remove(property);
+
+ QtProperty *wProp = d_ptr->m_propertyToW[property];
+ if (wProp) {
+ d_ptr->m_wToProperty.remove(wProp);
+ delete wProp;
+ }
+ d_ptr->m_propertyToW.remove(property);
+
+ QtProperty *hProp = d_ptr->m_propertyToH[property];
+ if (hProp) {
+ d_ptr->m_hToProperty.remove(hProp);
+ delete hProp;
+ }
+ d_ptr->m_propertyToH.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtRectFPropertyManager
+
+class QtRectFPropertyManagerPrivate
+{
+ QtRectFPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtRectFPropertyManager)
+public:
+
+ void slotDoubleChanged(QtProperty *property, double value);
+ void slotPropertyDestroyed(QtProperty *property);
+ void setConstraint(QtProperty *property, const QRectF &constraint, const QRectF &val);
+
+ struct Data
+ {
+ Data() : val(0, 0, 0, 0), decimals(2) {}
+ QRectF val;
+ QRectF constraint;
+ int decimals;
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtDoublePropertyManager *m_doublePropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToX;
+ QMap<const QtProperty *, QtProperty *> m_propertyToY;
+ QMap<const QtProperty *, QtProperty *> m_propertyToW;
+ QMap<const QtProperty *, QtProperty *> m_propertyToH;
+
+ QMap<const QtProperty *, QtProperty *> m_xToProperty;
+ QMap<const QtProperty *, QtProperty *> m_yToProperty;
+ QMap<const QtProperty *, QtProperty *> m_wToProperty;
+ QMap<const QtProperty *, QtProperty *> m_hToProperty;
+};
+
+void QtRectFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value)
+{
+ if (QtProperty *prop = m_xToProperty.value(property, 0)) {
+ QRectF r = m_values[prop].val;
+ r.moveLeft(value);
+ q_ptr->setValue(prop, r);
+ } else if (QtProperty *prop = m_yToProperty.value(property, 0)) {
+ QRectF r = m_values[prop].val;
+ r.moveTop(value);
+ q_ptr->setValue(prop, r);
+ } else if (QtProperty *prop = m_wToProperty.value(property, 0)) {
+ Data data = m_values[prop];
+ QRectF r = data.val;
+ r.setWidth(value);
+ if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) {
+ r.moveLeft(data.constraint.left() + data.constraint.width() - r.width());
+ }
+ q_ptr->setValue(prop, r);
+ } else if (QtProperty *prop = m_hToProperty.value(property, 0)) {
+ Data data = m_values[prop];
+ QRectF r = data.val;
+ r.setHeight(value);
+ if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) {
+ r.moveTop(data.constraint.top() + data.constraint.height() - r.height());
+ }
+ q_ptr->setValue(prop, r);
+ }
+}
+
+void QtRectFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_xToProperty.value(property, 0)) {
+ m_propertyToX[pointProp] = 0;
+ m_xToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) {
+ m_propertyToY[pointProp] = 0;
+ m_yToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) {
+ m_propertyToW[pointProp] = 0;
+ m_wToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) {
+ m_propertyToH[pointProp] = 0;
+ m_hToProperty.remove(property);
+ }
+}
+
+void QtRectFPropertyManagerPrivate::setConstraint(QtProperty *property,
+ const QRectF &constraint, const QRectF &val)
+{
+ const bool isNull = constraint.isNull();
+ const float left = isNull ? FLT_MIN : constraint.left();
+ const float right = isNull ? FLT_MAX : constraint.left() + constraint.width();
+ const float top = isNull ? FLT_MIN : constraint.top();
+ const float bottom = isNull ? FLT_MAX : constraint.top() + constraint.height();
+ const float width = isNull ? FLT_MAX : constraint.width();
+ const float height = isNull ? FLT_MAX : constraint.height();
+
+ m_doublePropertyManager->setRange(m_propertyToX[property], left, right);
+ m_doublePropertyManager->setRange(m_propertyToY[property], top, bottom);
+ m_doublePropertyManager->setRange(m_propertyToW[property], 0, width);
+ m_doublePropertyManager->setRange(m_propertyToH[property], 0, height);
+
+ m_doublePropertyManager->setValue(m_propertyToX[property], val.x());
+ m_doublePropertyManager->setValue(m_propertyToY[property], val.y());
+ m_doublePropertyManager->setValue(m_propertyToW[property], val.width());
+ m_doublePropertyManager->setValue(m_propertyToH[property], val.height());
+}
+
+/*!
+ \class QtRectFPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtRectFPropertyManager provides and manages QRectF properties.
+
+ A rectangle property has nested \e x, \e y, \e width and \e height
+ subproperties. The top-level property's value can be retrieved
+ using the value() function, and set using the setValue() slot.
+
+ The subproperties are created by a QtDoublePropertyManager object. This
+ manager can be retrieved using the subDoublePropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ A rectangle property also has a constraint rectangle which can be
+ retrieved using the constraint() function, and set using the
+ setConstraint() slot.
+
+ In addition, QtRectFPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the constraintChanged() signal which is emitted
+ whenever such a property changes its constraint rectangle.
+
+ \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtRectPropertyManager
+*/
+
+/*!
+ \fn void QtRectFPropertyManager::valueChanged(QtProperty *property, const QRectF &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtRectFPropertyManager::constraintChanged(QtProperty *property, const QRectF &constraint)
+
+ This signal is emitted whenever property changes its constraint
+ rectangle, passing a pointer to the \a property and the new \a
+ constraint rectangle as parameters.
+
+ \sa setConstraint()
+*/
+
+/*!
+ \fn void QtRectFPropertyManager::decimalsChanged(QtProperty *property, int prec)
+
+ This signal is emitted whenever a property created by this manager
+ changes its precision of value, passing a pointer to the
+ \a property and the new \a prec value
+
+ \sa setDecimals()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtRectFPropertyManager::QtRectFPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtRectFPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this);
+ connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotDoubleChanged(QtProperty *, double)));
+ connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtRectFPropertyManager::~QtRectFPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e x, \e y, \e width
+ and \e height subproperties.
+
+ In order to provide editing widgets for the mentioned
+ subproperties in a property browser widget, this manager must be
+ associated with an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtDoublePropertyManager *QtRectFPropertyManager::subDoublePropertyManager() const
+{
+ return d_ptr->m_doublePropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an invalid rectangle.
+
+ \sa setValue(), constraint()
+*/
+QRectF QtRectFPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<QRectF>(d_ptr->m_values, property);
+}
+
+/*!
+ Returns the given \a property's precision, in decimals.
+
+ \sa setDecimals()
+*/
+int QtRectFPropertyManager::decimals(const QtProperty *property) const
+{
+ return getData<int>(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::decimals, property, 0);
+}
+
+/*!
+ Returns the given \a property's constraining rectangle. If returned value is null QRectF it means there is no constraint applied.
+
+ \sa value(), setConstraint()
+*/
+QRectF QtRectFPropertyManager::constraint(const QtProperty *property) const
+{
+ return getData<QRectF>(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::constraint, property, QRect());
+}
+
+/*!
+ \reimp
+*/
+QString QtRectFPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtRectFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+ const QRectF v = it.value().val;
+ const int dec = it.value().decimals;
+ return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x(), 'f', dec))
+ .arg(QString::number(v.y(), 'f', dec))
+ .arg(QString::number(v.width(), 'f', dec))
+ .arg(QString::number(v.height(), 'f', dec)));
+}
+
+/*!
+ \fn void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ If the specified \a value is not inside the given \a property's
+ constraining rectangle, the value is adjusted accordingly to fit
+ within the constraint.
+
+ \sa value(), setConstraint(), valueChanged()
+*/
+void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &val)
+{
+ const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtRectFPropertyManagerPrivate::Data data = it.value();
+
+ QRectF newRect = val.normalized();
+ if (!data.constraint.isNull() && !data.constraint.contains(newRect)) {
+ const QRectF r1 = data.constraint;
+ const QRectF r2 = newRect;
+ newRect.setLeft(qMax(r1.left(), r2.left()));
+ newRect.setRight(qMin(r1.right(), r2.right()));
+ newRect.setTop(qMax(r1.top(), r2.top()));
+ newRect.setBottom(qMin(r1.bottom(), r2.bottom()));
+ if (newRect.width() < 0 || newRect.height() < 0)
+ return;
+ }
+
+ if (data.val == newRect)
+ return;
+
+ data.val = newRect;
+
+ it.value() = data;
+ d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x());
+ d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y());
+ d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width());
+ d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height());
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ Sets the given \a property's constraining rectangle to \a
+ constraint.
+
+ When setting the constraint, the current value is adjusted if
+ necessary (ensuring that the current rectangle value is inside the
+ constraint). In order to reset the constraint pass a null QRectF value.
+
+ \sa setValue(), constraint(), constraintChanged()
+*/
+void QtRectFPropertyManager::setConstraint(QtProperty *property, const QRectF &constraint)
+{
+ const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtRectFPropertyManagerPrivate::Data data = it.value();
+
+ QRectF newConstraint = constraint.normalized();
+ if (data.constraint == newConstraint)
+ return;
+
+ const QRectF oldVal = data.val;
+
+ data.constraint = newConstraint;
+
+ if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) {
+ QRectF r1 = data.constraint;
+ QRectF r2 = data.val;
+
+ if (r2.width() > r1.width())
+ r2.setWidth(r1.width());
+ if (r2.height() > r1.height())
+ r2.setHeight(r1.height());
+ if (r2.left() < r1.left())
+ r2.moveLeft(r1.left());
+ else if (r2.right() > r1.right())
+ r2.moveRight(r1.right());
+ if (r2.top() < r1.top())
+ r2.moveTop(r1.top());
+ else if (r2.bottom() > r1.bottom())
+ r2.moveBottom(r1.bottom());
+
+ data.val = r2;
+ }
+
+ it.value() = data;
+
+ emit constraintChanged(property, data.constraint);
+
+ d_ptr->setConstraint(property, data.constraint, data.val);
+
+ if (data.val == oldVal)
+ return;
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ \fn void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec)
+
+ Sets the precision of the given \a property to \a prec.
+
+ The valid decimal range is 0-13. The default is 2.
+
+ \sa decimals()
+*/
+void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec)
+{
+ const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtRectFPropertyManagerPrivate::Data data = it.value();
+
+ if (prec > 13)
+ prec = 13;
+ else if (prec < 0)
+ prec = 0;
+
+ if (data.decimals == prec)
+ return;
+
+ data.decimals = prec;
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec);
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec);
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec);
+ d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec);
+
+ it.value() = data;
+
+ emit decimalsChanged(property, data.decimals);
+}
+
+/*!
+ \reimp
+*/
+void QtRectFPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtRectFPropertyManagerPrivate::Data();
+
+ QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty();
+ xProp->setPropertyName(tr("X"));
+ d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(xProp, 0);
+ d_ptr->m_propertyToX[property] = xProp;
+ d_ptr->m_xToProperty[xProp] = property;
+ property->addSubProperty(xProp);
+
+ QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty();
+ yProp->setPropertyName(tr("Y"));
+ d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(yProp, 0);
+ d_ptr->m_propertyToY[property] = yProp;
+ d_ptr->m_yToProperty[yProp] = property;
+ property->addSubProperty(yProp);
+
+ QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty();
+ wProp->setPropertyName(tr("Width"));
+ d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(wProp, 0);
+ d_ptr->m_doublePropertyManager->setMinimum(wProp, 0);
+ d_ptr->m_propertyToW[property] = wProp;
+ d_ptr->m_wToProperty[wProp] = property;
+ property->addSubProperty(wProp);
+
+ QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty();
+ hProp->setPropertyName(tr("Height"));
+ d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property));
+ d_ptr->m_doublePropertyManager->setValue(hProp, 0);
+ d_ptr->m_doublePropertyManager->setMinimum(hProp, 0);
+ d_ptr->m_propertyToH[property] = hProp;
+ d_ptr->m_hToProperty[hProp] = property;
+ property->addSubProperty(hProp);
+}
+
+/*!
+ \reimp
+*/
+void QtRectFPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *xProp = d_ptr->m_propertyToX[property];
+ if (xProp) {
+ d_ptr->m_xToProperty.remove(xProp);
+ delete xProp;
+ }
+ d_ptr->m_propertyToX.remove(property);
+
+ QtProperty *yProp = d_ptr->m_propertyToY[property];
+ if (yProp) {
+ d_ptr->m_yToProperty.remove(yProp);
+ delete yProp;
+ }
+ d_ptr->m_propertyToY.remove(property);
+
+ QtProperty *wProp = d_ptr->m_propertyToW[property];
+ if (wProp) {
+ d_ptr->m_wToProperty.remove(wProp);
+ delete wProp;
+ }
+ d_ptr->m_propertyToW.remove(property);
+
+ QtProperty *hProp = d_ptr->m_propertyToH[property];
+ if (hProp) {
+ d_ptr->m_hToProperty.remove(hProp);
+ delete hProp;
+ }
+ d_ptr->m_propertyToH.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtEnumPropertyManager
+
+class QtEnumPropertyManagerPrivate
+{
+ QtEnumPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtEnumPropertyManager)
+public:
+
+ struct Data
+ {
+ Data() : val(-1) {}
+ int val;
+ QStringList enumNames;
+ QMap<int, QIcon> enumIcons;
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*!
+ \class QtEnumPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtEnumPropertyManager provides and manages enum properties.
+
+ Each enum property has an associated list of enum names which can
+ be retrieved using the enumNames() function, and set using the
+ corresponding setEnumNames() function. An enum property's value is
+ represented by an index in this list, and can be retrieved and set
+ using the value() and setValue() slots respectively.
+
+ Each enum value can also have an associated icon. The mapping from
+ values to icons can be set using the setEnumIcons() function and
+ queried with the enumIcons() function.
+
+ In addition, QtEnumPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes. The enumNamesChanged() or enumIconsChanged() signal is emitted
+ whenever the list of enum names or icons is altered.
+
+ \sa QtAbstractPropertyManager, QtEnumEditorFactory
+*/
+
+/*!
+ \fn void QtEnumPropertyManager::valueChanged(QtProperty *property, int value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtEnumPropertyManager::enumNamesChanged(QtProperty *property, const QStringList &names)
+
+ This signal is emitted whenever a property created by this manager
+ changes its enum names, passing a pointer to the \a property and
+ the new \a names as parameters.
+
+ \sa setEnumNames()
+*/
+
+/*!
+ \fn void QtEnumPropertyManager::enumIconsChanged(QtProperty *property, const QMap<int, QIcon> &icons)
+
+ This signal is emitted whenever a property created by this manager
+ changes its enum icons, passing a pointer to the \a property and
+ the new mapping of values to \a icons as parameters.
+
+ \sa setEnumIcons()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtEnumPropertyManager::QtEnumPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtEnumPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtEnumPropertyManager::~QtEnumPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value which is an index in the
+ list returned by enumNames()
+
+ If the given property is not managed by this manager, this
+ function returns -1.
+
+ \sa enumNames(), setValue()
+*/
+int QtEnumPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<int>(d_ptr->m_values, property, -1);
+}
+
+/*!
+ Returns the given \a property's list of enum names.
+
+ \sa value(), setEnumNames()
+*/
+QStringList QtEnumPropertyManager::enumNames(const QtProperty *property) const
+{
+ return getData<QStringList>(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumNames, property, QStringList());
+}
+
+/*!
+ Returns the given \a property's map of enum values to their icons.
+
+ \sa value(), setEnumIcons()
+*/
+QMap<int, QIcon> QtEnumPropertyManager::enumIcons(const QtProperty *property) const
+{
+ return getData<QMap<int, QIcon> >(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumIcons, property, QMap<int, QIcon>());
+}
+
+/*!
+ \reimp
+*/
+QString QtEnumPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ const QtEnumPropertyManagerPrivate::Data &data = it.value();
+
+ const int v = data.val;
+ if (v >= 0 && v < data.enumNames.count())
+ return data.enumNames.at(v);
+ return QString();
+}
+
+/*!
+ \reimp
+*/
+QIcon QtEnumPropertyManager::valueIcon(const QtProperty *property) const
+{
+ const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QIcon();
+
+ const QtEnumPropertyManagerPrivate::Data &data = it.value();
+
+ const int v = data.val;
+ return data.enumIcons.value(v);
+}
+
+/*!
+ \fn void QtEnumPropertyManager::setValue(QtProperty *property, int value)
+
+ Sets the value of the given \a property to \a value.
+
+ The specified \a value must be less than the size of the given \a
+ property's enumNames() list, and larger than (or equal to) 0.
+
+ \sa value(), valueChanged()
+*/
+void QtEnumPropertyManager::setValue(QtProperty *property, int val)
+{
+ const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtEnumPropertyManagerPrivate::Data data = it.value();
+
+ if (val >= data.enumNames.count())
+ return;
+
+ if (val < 0 && data.enumNames.count() > 0)
+ return;
+
+ if (val < 0)
+ val = -1;
+
+ if (data.val == val)
+ return;
+
+ data.val = val;
+
+ it.value() = data;
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ Sets the given \a property's list of enum names to \a
+ enumNames. The \a property's current value is reset to 0
+ indicating the first item of the list.
+
+ If the specified \a enumNames list is empty, the \a property's
+ current value is set to -1.
+
+ \sa enumNames(), enumNamesChanged()
+*/
+void QtEnumPropertyManager::setEnumNames(QtProperty *property, const QStringList &enumNames)
+{
+ const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtEnumPropertyManagerPrivate::Data data = it.value();
+
+ if (data.enumNames == enumNames)
+ return;
+
+ data.enumNames = enumNames;
+
+ data.val = -1;
+
+ if (enumNames.count() > 0)
+ data.val = 0;
+
+ it.value() = data;
+
+ emit enumNamesChanged(property, data.enumNames);
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ Sets the given \a property's map of enum values to their icons to \a
+ enumIcons.
+
+ Each enum value can have associated icon. This association is represented with passed \a enumIcons map.
+
+ \sa enumNames(), enumNamesChanged()
+*/
+void QtEnumPropertyManager::setEnumIcons(QtProperty *property, const QMap<int, QIcon> &enumIcons)
+{
+ const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ it.value().enumIcons = enumIcons;
+
+ emit enumIconsChanged(property, it.value().enumIcons);
+
+ emit propertyChanged(property);
+}
+
+/*!
+ \reimp
+*/
+void QtEnumPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtEnumPropertyManagerPrivate::Data();
+}
+
+/*!
+ \reimp
+*/
+void QtEnumPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+// QtFlagPropertyManager
+
+class QtFlagPropertyManagerPrivate
+{
+ QtFlagPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtFlagPropertyManager)
+public:
+
+ void slotBoolChanged(QtProperty *property, bool value);
+ void slotPropertyDestroyed(QtProperty *property);
+
+ struct Data
+ {
+ Data() : val(-1) {}
+ int val;
+ QStringList flagNames;
+ };
+
+ typedef QMap<const QtProperty *, Data> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtBoolPropertyManager *m_boolPropertyManager;
+
+ QMap<const QtProperty *, QList<QtProperty *> > m_propertyToFlags;
+
+ QMap<const QtProperty *, QtProperty *> m_flagToProperty;
+};
+
+void QtFlagPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value)
+{
+ QtProperty *prop = m_flagToProperty.value(property, 0);
+ if (prop == 0)
+ return;
+
+ QListIterator<QtProperty *> itProp(m_propertyToFlags[prop]);
+ int level = 0;
+ while (itProp.hasNext()) {
+ QtProperty *p = itProp.next();
+ if (p == property) {
+ int v = m_values[prop].val;
+ if (value) {
+ v |= (1 << level);
+ } else {
+ v &= ~(1 << level);
+ }
+ q_ptr->setValue(prop, v);
+ return;
+ }
+ level++;
+ }
+}
+
+void QtFlagPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ QtProperty *flagProperty = m_flagToProperty.value(property, 0);
+ if (flagProperty == 0)
+ return;
+
+ m_propertyToFlags[flagProperty].replace(m_propertyToFlags[flagProperty].indexOf(property), 0);
+ m_flagToProperty.remove(property);
+}
+
+/*!
+ \class QtFlagPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtFlagPropertyManager provides and manages flag properties.
+
+ Each flag property has an associated list of flag names which can
+ be retrieved using the flagNames() function, and set using the
+ corresponding setFlagNames() function.
+
+ The flag manager provides properties with nested boolean
+ subproperties representing each flag, i.e. a flag property's value
+ is the binary combination of the subproperties' values. A
+ property's value can be retrieved and set using the value() and
+ setValue() slots respectively. The combination of flags is represented
+ by single int value - that's why it's possible to store up to
+ 32 independent flags in one flag property.
+
+ The subproperties are created by a QtBoolPropertyManager object. This
+ manager can be retrieved using the subBoolPropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ In addition, QtFlagPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes, and the flagNamesChanged() signal which is emitted
+ whenever the list of flag names is altered.
+
+ \sa QtAbstractPropertyManager, QtBoolPropertyManager
+*/
+
+/*!
+ \fn void QtFlagPropertyManager::valueChanged(QtProperty *property, int value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtFlagPropertyManager::flagNamesChanged(QtProperty *property, const QStringList &names)
+
+ This signal is emitted whenever a property created by this manager
+ changes its flag names, passing a pointer to the \a property and the
+ new \a names as parameters.
+
+ \sa setFlagNames()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtFlagPropertyManager::QtFlagPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtFlagPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this);
+ connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)),
+ this, SLOT(slotBoolChanged(QtProperty *, bool)));
+ connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtFlagPropertyManager::~QtFlagPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that produces the nested boolean subproperties
+ representing each flag.
+
+ In order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtBoolPropertyManager *QtFlagPropertyManager::subBoolPropertyManager() const
+{
+ return d_ptr->m_boolPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns 0.
+
+ \sa flagNames(), setValue()
+*/
+int QtFlagPropertyManager::value(const QtProperty *property) const
+{
+ return getValue<int>(d_ptr->m_values, property, 0);
+}
+
+/*!
+ Returns the given \a property's list of flag names.
+
+ \sa value(), setFlagNames()
+*/
+QStringList QtFlagPropertyManager::flagNames(const QtProperty *property) const
+{
+ return getData<QStringList>(d_ptr->m_values, &QtFlagPropertyManagerPrivate::Data::flagNames, property, QStringList());
+}
+
+/*!
+ \reimp
+*/
+QString QtFlagPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtFlagPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ const QtFlagPropertyManagerPrivate::Data &data = it.value();
+
+ QString str;
+ int level = 0;
+ const QChar bar = QLatin1Char('|');
+ const QStringList::const_iterator fncend = data.flagNames.constEnd();
+ for (QStringList::const_iterator it = data.flagNames.constBegin(); it != fncend; ++it) {
+ if (data.val & (1 << level)) {
+ if (!str.isEmpty())
+ str += bar;
+ str += *it;
+ }
+
+ level++;
+ }
+ return str;
+}
+
+/*!
+ \fn void QtFlagPropertyManager::setValue(QtProperty *property, int value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ The specified \a value must be less than the binary combination of
+ the property's flagNames() list size (i.e. less than 2\sup n,
+ where \c n is the size of the list) and larger than (or equal to)
+ 0.
+
+ \sa value(), valueChanged()
+*/
+void QtFlagPropertyManager::setValue(QtProperty *property, int val)
+{
+ const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtFlagPropertyManagerPrivate::Data data = it.value();
+
+ if (data.val == val)
+ return;
+
+ if (val > (1 << data.flagNames.count()) - 1)
+ return;
+
+ if (val < 0)
+ return;
+
+ data.val = val;
+
+ it.value() = data;
+
+ QListIterator<QtProperty *> itProp(d_ptr->m_propertyToFlags[property]);
+ int level = 0;
+ while (itProp.hasNext()) {
+ QtProperty *prop = itProp.next();
+ if (prop)
+ d_ptr->m_boolPropertyManager->setValue(prop, val & (1 << level));
+ level++;
+ }
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ Sets the given \a property's list of flag names to \a flagNames. The
+ property's current value is reset to 0 indicating the first item
+ of the list.
+
+ \sa flagNames(), flagNamesChanged()
+*/
+void QtFlagPropertyManager::setFlagNames(QtProperty *property, const QStringList &flagNames)
+{
+ const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ QtFlagPropertyManagerPrivate::Data data = it.value();
+
+ if (data.flagNames == flagNames)
+ return;
+
+ data.flagNames = flagNames;
+ data.val = 0;
+
+ it.value() = data;
+
+ QListIterator<QtProperty *> itProp(d_ptr->m_propertyToFlags[property]);
+ while (itProp.hasNext()) {
+ QtProperty *prop = itProp.next();
+ if (prop) {
+ delete prop;
+ d_ptr->m_flagToProperty.remove(prop);
+ }
+ }
+ d_ptr->m_propertyToFlags[property].clear();
+
+ QStringListIterator itFlag(flagNames);
+ while (itFlag.hasNext()) {
+ const QString flagName = itFlag.next();
+ QtProperty *prop = d_ptr->m_boolPropertyManager->addProperty();
+ prop->setPropertyName(flagName);
+ property->addSubProperty(prop);
+ d_ptr->m_propertyToFlags[property].append(prop);
+ d_ptr->m_flagToProperty[prop] = property;
+ }
+
+ emit flagNamesChanged(property, data.flagNames);
+
+ emit propertyChanged(property);
+ emit valueChanged(property, data.val);
+}
+
+/*!
+ \reimp
+*/
+void QtFlagPropertyManager::initializeProperty(QtProperty *property)
+{
+ d_ptr->m_values[property] = QtFlagPropertyManagerPrivate::Data();
+
+ d_ptr->m_propertyToFlags[property] = QList<QtProperty *>();
+}
+
+/*!
+ \reimp
+*/
+void QtFlagPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QListIterator<QtProperty *> itProp(d_ptr->m_propertyToFlags[property]);
+ while (itProp.hasNext()) {
+ QtProperty *prop = itProp.next();
+ if (prop) {
+ delete prop;
+ d_ptr->m_flagToProperty.remove(prop);
+ }
+ }
+ d_ptr->m_propertyToFlags.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtSizePolicyPropertyManager
+
+class QtSizePolicyPropertyManagerPrivate
+{
+ QtSizePolicyPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtSizePolicyPropertyManager)
+public:
+
+ QtSizePolicyPropertyManagerPrivate();
+
+ void slotIntChanged(QtProperty *property, int value);
+ void slotEnumChanged(QtProperty *property, int value);
+ void slotPropertyDestroyed(QtProperty *property);
+
+ typedef QMap<const QtProperty *, QSizePolicy> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtIntPropertyManager *m_intPropertyManager;
+ QtEnumPropertyManager *m_enumPropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToHPolicy;
+ QMap<const QtProperty *, QtProperty *> m_propertyToVPolicy;
+ QMap<const QtProperty *, QtProperty *> m_propertyToHStretch;
+ QMap<const QtProperty *, QtProperty *> m_propertyToVStretch;
+
+ QMap<const QtProperty *, QtProperty *> m_hPolicyToProperty;
+ QMap<const QtProperty *, QtProperty *> m_vPolicyToProperty;
+ QMap<const QtProperty *, QtProperty *> m_hStretchToProperty;
+ QMap<const QtProperty *, QtProperty *> m_vStretchToProperty;
+};
+
+QtSizePolicyPropertyManagerPrivate::QtSizePolicyPropertyManagerPrivate()
+{
+}
+
+void QtSizePolicyPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value)
+{
+ if (QtProperty *prop = m_hStretchToProperty.value(property, 0)) {
+ QSizePolicy sp = m_values[prop];
+ sp.setHorizontalStretch(value);
+ q_ptr->setValue(prop, sp);
+ } else if (QtProperty *prop = m_vStretchToProperty.value(property, 0)) {
+ QSizePolicy sp = m_values[prop];
+ sp.setVerticalStretch(value);
+ q_ptr->setValue(prop, sp);
+ }
+}
+
+void QtSizePolicyPropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value)
+{
+ if (QtProperty *prop = m_hPolicyToProperty.value(property, 0)) {
+ QSizePolicy sp = m_values[prop];
+ sp.setHorizontalPolicy(metaEnumProvider()->indexToSizePolicy(value));
+ q_ptr->setValue(prop, sp);
+ } else if (QtProperty *prop = m_vPolicyToProperty.value(property, 0)) {
+ QSizePolicy sp = m_values[prop];
+ sp.setVerticalPolicy(metaEnumProvider()->indexToSizePolicy(value));
+ q_ptr->setValue(prop, sp);
+ }
+}
+
+void QtSizePolicyPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_hStretchToProperty.value(property, 0)) {
+ m_propertyToHStretch[pointProp] = 0;
+ m_hStretchToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_vStretchToProperty.value(property, 0)) {
+ m_propertyToVStretch[pointProp] = 0;
+ m_vStretchToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_hPolicyToProperty.value(property, 0)) {
+ m_propertyToHPolicy[pointProp] = 0;
+ m_hPolicyToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_vPolicyToProperty.value(property, 0)) {
+ m_propertyToVPolicy[pointProp] = 0;
+ m_vPolicyToProperty.remove(property);
+ }
+}
+
+/*!
+ \class QtSizePolicyPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtSizePolicyPropertyManager provides and manages QSizePolicy properties.
+
+ A size policy property has nested \e horizontalPolicy, \e
+ verticalPolicy, \e horizontalStretch and \e verticalStretch
+ subproperties. The top-level property's value can be retrieved
+ using the value() function, and set using the setValue() slot.
+
+ The subproperties are created by QtIntPropertyManager and QtEnumPropertyManager
+ objects. These managers can be retrieved using the subIntPropertyManager()
+ and subEnumPropertyManager() functions respectively. In order to provide
+ editing widgets for the subproperties in a property browser widget,
+ these managers must be associated with editor factories.
+
+ In addition, QtSizePolicyPropertyManager provides the valueChanged()
+ signal which is emitted whenever a property created by this
+ manager changes.
+
+ \sa QtAbstractPropertyManager, QtIntPropertyManager, QtEnumPropertyManager
+*/
+
+/*!
+ \fn void QtSizePolicyPropertyManager::valueChanged(QtProperty *property, const QSizePolicy &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtSizePolicyPropertyManager::QtSizePolicyPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtSizePolicyPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
+ connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotIntChanged(QtProperty *, int)));
+ d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this);
+ connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotEnumChanged(QtProperty *, int)));
+
+ connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+ connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtSizePolicyPropertyManager::~QtSizePolicyPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the nested \e horizontalStretch
+ and \e verticalStretch subproperties.
+
+ In order to provide editing widgets for the mentioned subproperties
+ in a property browser widget, this manager must be associated with
+ an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtIntPropertyManager *QtSizePolicyPropertyManager::subIntPropertyManager() const
+{
+ return d_ptr->m_intPropertyManager;
+}
+
+/*!
+ Returns the manager that creates the nested \e horizontalPolicy
+ and \e verticalPolicy subproperties.
+
+ In order to provide editing widgets for the mentioned subproperties
+ in a property browser widget, this manager must be associated with
+ an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtEnumPropertyManager *QtSizePolicyPropertyManager::subEnumPropertyManager() const
+{
+ return d_ptr->m_enumPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns the default size policy.
+
+ \sa setValue()
+*/
+QSizePolicy QtSizePolicyPropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QSizePolicy());
+}
+
+/*!
+ \reimp
+*/
+QString QtSizePolicyPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtSizePolicyPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ const QSizePolicy sp = it.value();
+ const QtMetaEnumProvider *mep = metaEnumProvider();
+ const int hIndex = mep->sizePolicyToIndex(sp.horizontalPolicy());
+ const int vIndex = mep->sizePolicyToIndex(sp.verticalPolicy());
+ //! Unknown size policy on reading invalid uic3 files
+ const QString hPolicy = hIndex != -1 ? mep->policyEnumNames().at(hIndex) : tr("<Invalid>");
+ const QString vPolicy = vIndex != -1 ? mep->policyEnumNames().at(vIndex) : tr("<Invalid>");
+ const QString str = tr("[%1, %2, %3, %4]").arg(hPolicy, vPolicy).arg(sp.horizontalStretch()).arg(sp.verticalStretch());
+ return str;
+}
+
+/*!
+ \fn void QtSizePolicyPropertyManager::setValue(QtProperty *property, const QSizePolicy &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ \sa value(), valueChanged()
+*/
+void QtSizePolicyPropertyManager::setValue(QtProperty *property, const QSizePolicy &val)
+{
+ const QtSizePolicyPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ if (it.value() == val)
+ return;
+
+ it.value() = val;
+
+ d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToHPolicy[property],
+ metaEnumProvider()->sizePolicyToIndex(val.horizontalPolicy()));
+ d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToVPolicy[property],
+ metaEnumProvider()->sizePolicyToIndex(val.verticalPolicy()));
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToHStretch[property],
+ val.horizontalStretch());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToVStretch[property],
+ val.verticalStretch());
+
+ emit propertyChanged(property);
+ emit valueChanged(property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtSizePolicyPropertyManager::initializeProperty(QtProperty *property)
+{
+ QSizePolicy val;
+ d_ptr->m_values[property] = val;
+
+ QtProperty *hPolicyProp = d_ptr->m_enumPropertyManager->addProperty();
+ hPolicyProp->setPropertyName(tr("Horizontal Policy"));
+ d_ptr->m_enumPropertyManager->setEnumNames(hPolicyProp, metaEnumProvider()->policyEnumNames());
+ d_ptr->m_enumPropertyManager->setValue(hPolicyProp,
+ metaEnumProvider()->sizePolicyToIndex(val.horizontalPolicy()));
+ d_ptr->m_propertyToHPolicy[property] = hPolicyProp;
+ d_ptr->m_hPolicyToProperty[hPolicyProp] = property;
+ property->addSubProperty(hPolicyProp);
+
+ QtProperty *vPolicyProp = d_ptr->m_enumPropertyManager->addProperty();
+ vPolicyProp->setPropertyName(tr("Vertical Policy"));
+ d_ptr->m_enumPropertyManager->setEnumNames(vPolicyProp, metaEnumProvider()->policyEnumNames());
+ d_ptr->m_enumPropertyManager->setValue(vPolicyProp,
+ metaEnumProvider()->sizePolicyToIndex(val.verticalPolicy()));
+ d_ptr->m_propertyToVPolicy[property] = vPolicyProp;
+ d_ptr->m_vPolicyToProperty[vPolicyProp] = property;
+ property->addSubProperty(vPolicyProp);
+
+ QtProperty *hStretchProp = d_ptr->m_intPropertyManager->addProperty();
+ hStretchProp->setPropertyName(tr("Horizontal Stretch"));
+ d_ptr->m_intPropertyManager->setValue(hStretchProp, val.horizontalStretch());
+ d_ptr->m_intPropertyManager->setRange(hStretchProp, 0, 0xff);
+ d_ptr->m_propertyToHStretch[property] = hStretchProp;
+ d_ptr->m_hStretchToProperty[hStretchProp] = property;
+ property->addSubProperty(hStretchProp);
+
+ QtProperty *vStretchProp = d_ptr->m_intPropertyManager->addProperty();
+ vStretchProp->setPropertyName(tr("Vertical Stretch"));
+ d_ptr->m_intPropertyManager->setValue(vStretchProp, val.verticalStretch());
+ d_ptr->m_intPropertyManager->setRange(vStretchProp, 0, 0xff);
+ d_ptr->m_propertyToVStretch[property] = vStretchProp;
+ d_ptr->m_vStretchToProperty[vStretchProp] = property;
+ property->addSubProperty(vStretchProp);
+
+}
+
+/*!
+ \reimp
+*/
+void QtSizePolicyPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *hPolicyProp = d_ptr->m_propertyToHPolicy[property];
+ if (hPolicyProp) {
+ d_ptr->m_hPolicyToProperty.remove(hPolicyProp);
+ delete hPolicyProp;
+ }
+ d_ptr->m_propertyToHPolicy.remove(property);
+
+ QtProperty *vPolicyProp = d_ptr->m_propertyToVPolicy[property];
+ if (vPolicyProp) {
+ d_ptr->m_vPolicyToProperty.remove(vPolicyProp);
+ delete vPolicyProp;
+ }
+ d_ptr->m_propertyToVPolicy.remove(property);
+
+ QtProperty *hStretchProp = d_ptr->m_propertyToHStretch[property];
+ if (hStretchProp) {
+ d_ptr->m_hStretchToProperty.remove(hStretchProp);
+ delete hStretchProp;
+ }
+ d_ptr->m_propertyToHStretch.remove(property);
+
+ QtProperty *vStretchProp = d_ptr->m_propertyToVStretch[property];
+ if (vStretchProp) {
+ d_ptr->m_vStretchToProperty.remove(vStretchProp);
+ delete vStretchProp;
+ }
+ d_ptr->m_propertyToVStretch.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtFontPropertyManager:
+// QtFontPropertyManagerPrivate has a mechanism for reacting
+// to QApplication::fontDatabaseChanged() [4.5], which is emitted
+// when someone loads an application font. The signals are compressed
+// using a timer with interval 0, which then causes the family
+// enumeration manager to re-set its strings and index values
+// for each property.
+
+Q_GLOBAL_STATIC(QFontDatabase, fontDatabase)
+
+class QtFontPropertyManagerPrivate
+{
+ QtFontPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtFontPropertyManager)
+public:
+
+ QtFontPropertyManagerPrivate();
+
+ void slotIntChanged(QtProperty *property, int value);
+ void slotEnumChanged(QtProperty *property, int value);
+ void slotBoolChanged(QtProperty *property, bool value);
+ void slotPropertyDestroyed(QtProperty *property);
+ void slotFontDatabaseChanged();
+ void slotFontDatabaseDelayedChange();
+
+ QStringList m_familyNames;
+
+ typedef QMap<const QtProperty *, QFont> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtIntPropertyManager *m_intPropertyManager;
+ QtEnumPropertyManager *m_enumPropertyManager;
+ QtBoolPropertyManager *m_boolPropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToFamily;
+ QMap<const QtProperty *, QtProperty *> m_propertyToPointSize;
+ QMap<const QtProperty *, QtProperty *> m_propertyToBold;
+ QMap<const QtProperty *, QtProperty *> m_propertyToItalic;
+ QMap<const QtProperty *, QtProperty *> m_propertyToUnderline;
+ QMap<const QtProperty *, QtProperty *> m_propertyToStrikeOut;
+ QMap<const QtProperty *, QtProperty *> m_propertyToKerning;
+
+ QMap<const QtProperty *, QtProperty *> m_familyToProperty;
+ QMap<const QtProperty *, QtProperty *> m_pointSizeToProperty;
+ QMap<const QtProperty *, QtProperty *> m_boldToProperty;
+ QMap<const QtProperty *, QtProperty *> m_italicToProperty;
+ QMap<const QtProperty *, QtProperty *> m_underlineToProperty;
+ QMap<const QtProperty *, QtProperty *> m_strikeOutToProperty;
+ QMap<const QtProperty *, QtProperty *> m_kerningToProperty;
+
+ bool m_settingValue;
+ QTimer *m_fontDatabaseChangeTimer;
+};
+
+QtFontPropertyManagerPrivate::QtFontPropertyManagerPrivate() :
+ m_settingValue(false),
+ m_fontDatabaseChangeTimer(0)
+{
+}
+
+void QtFontPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value)
+{
+ if (m_settingValue)
+ return;
+ if (QtProperty *prop = m_pointSizeToProperty.value(property, 0)) {
+ QFont f = m_values[prop];
+ f.setPointSize(value);
+ q_ptr->setValue(prop, f);
+ }
+}
+
+void QtFontPropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value)
+{
+ if (m_settingValue)
+ return;
+ if (QtProperty *prop = m_familyToProperty.value(property, 0)) {
+ QFont f = m_values[prop];
+ f.setFamily(m_familyNames.at(value));
+ q_ptr->setValue(prop, f);
+ }
+}
+
+void QtFontPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value)
+{
+ if (m_settingValue)
+ return;
+ if (QtProperty *prop = m_boldToProperty.value(property, 0)) {
+ QFont f = m_values[prop];
+ f.setBold(value);
+ q_ptr->setValue(prop, f);
+ } else if (QtProperty *prop = m_italicToProperty.value(property, 0)) {
+ QFont f = m_values[prop];
+ f.setItalic(value);
+ q_ptr->setValue(prop, f);
+ } else if (QtProperty *prop = m_underlineToProperty.value(property, 0)) {
+ QFont f = m_values[prop];
+ f.setUnderline(value);
+ q_ptr->setValue(prop, f);
+ } else if (QtProperty *prop = m_strikeOutToProperty.value(property, 0)) {
+ QFont f = m_values[prop];
+ f.setStrikeOut(value);
+ q_ptr->setValue(prop, f);
+ } else if (QtProperty *prop = m_kerningToProperty.value(property, 0)) {
+ QFont f = m_values[prop];
+ f.setKerning(value);
+ q_ptr->setValue(prop, f);
+ }
+}
+
+void QtFontPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_pointSizeToProperty.value(property, 0)) {
+ m_propertyToPointSize[pointProp] = 0;
+ m_pointSizeToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_familyToProperty.value(property, 0)) {
+ m_propertyToFamily[pointProp] = 0;
+ m_familyToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_boldToProperty.value(property, 0)) {
+ m_propertyToBold[pointProp] = 0;
+ m_boldToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_italicToProperty.value(property, 0)) {
+ m_propertyToItalic[pointProp] = 0;
+ m_italicToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_underlineToProperty.value(property, 0)) {
+ m_propertyToUnderline[pointProp] = 0;
+ m_underlineToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_strikeOutToProperty.value(property, 0)) {
+ m_propertyToStrikeOut[pointProp] = 0;
+ m_strikeOutToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_kerningToProperty.value(property, 0)) {
+ m_propertyToKerning[pointProp] = 0;
+ m_kerningToProperty.remove(property);
+ }
+}
+
+void QtFontPropertyManagerPrivate::slotFontDatabaseChanged()
+{
+ if (!m_fontDatabaseChangeTimer) {
+ m_fontDatabaseChangeTimer = new QTimer(q_ptr);
+ m_fontDatabaseChangeTimer->setInterval(0);
+ m_fontDatabaseChangeTimer->setSingleShot(true);
+ QObject::connect(m_fontDatabaseChangeTimer, SIGNAL(timeout()), q_ptr, SLOT(slotFontDatabaseDelayedChange()));
+ }
+ if (!m_fontDatabaseChangeTimer->isActive())
+ m_fontDatabaseChangeTimer->start();
+}
+
+void QtFontPropertyManagerPrivate::slotFontDatabaseDelayedChange()
+{
+ typedef QMap<const QtProperty *, QtProperty *> PropertyPropertyMap;
+ // rescan available font names
+ const QStringList oldFamilies = m_familyNames;
+ m_familyNames = fontDatabase()->families();
+
+ // Adapt all existing properties
+ if (!m_propertyToFamily.empty()) {
+ PropertyPropertyMap::const_iterator cend = m_propertyToFamily.constEnd();
+ for (PropertyPropertyMap::const_iterator it = m_propertyToFamily.constBegin(); it != cend; ++it) {
+ QtProperty *familyProp = it.value();
+ const int oldIdx = m_enumPropertyManager->value(familyProp);
+ int newIdx = m_familyNames.indexOf(oldFamilies.at(oldIdx));
+ if (newIdx < 0)
+ newIdx = 0;
+ m_enumPropertyManager->setEnumNames(familyProp, m_familyNames);
+ m_enumPropertyManager->setValue(familyProp, newIdx);
+ }
+ }
+}
+
+/*!
+ \class QtFontPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtFontPropertyManager provides and manages QFont properties.
+
+ A font property has nested \e family, \e pointSize, \e bold, \e
+ italic, \e underline, \e strikeOut and \e kerning subproperties. The top-level
+ property's value can be retrieved using the value() function, and
+ set using the setValue() slot.
+
+ The subproperties are created by QtIntPropertyManager, QtEnumPropertyManager and
+ QtBoolPropertyManager objects. These managers can be retrieved using the
+ corresponding subIntPropertyManager(), subEnumPropertyManager() and
+ subBoolPropertyManager() functions. In order to provide editing widgets
+ for the subproperties in a property browser widget, these managers
+ must be associated with editor factories.
+
+ In addition, QtFontPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes.
+
+ \sa QtAbstractPropertyManager, QtEnumPropertyManager, QtIntPropertyManager, QtBoolPropertyManager
+*/
+
+/*!
+ \fn void QtFontPropertyManager::valueChanged(QtProperty *property, const QFont &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtFontPropertyManager::QtFontPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtFontPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+#if QT_VERSION >= 0x040500
+ QObject::connect(qApp, SIGNAL(fontDatabaseChanged()), this, SLOT(slotFontDatabaseChanged()));
+#endif
+
+ d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
+ connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotIntChanged(QtProperty *, int)));
+ d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this);
+ connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotEnumChanged(QtProperty *, int)));
+ d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this);
+ connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)),
+ this, SLOT(slotBoolChanged(QtProperty *, bool)));
+
+ connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+ connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+ connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtFontPropertyManager::~QtFontPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that creates the \e pointSize subproperty.
+
+ In order to provide editing widgets for the \e pointSize property
+ in a property browser widget, this manager must be associated
+ with an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtIntPropertyManager *QtFontPropertyManager::subIntPropertyManager() const
+{
+ return d_ptr->m_intPropertyManager;
+}
+
+/*!
+ Returns the manager that create the \e family subproperty.
+
+ In order to provide editing widgets for the \e family property
+ in a property browser widget, this manager must be associated
+ with an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtEnumPropertyManager *QtFontPropertyManager::subEnumPropertyManager() const
+{
+ return d_ptr->m_enumPropertyManager;
+}
+
+/*!
+ Returns the manager that creates the \e bold, \e italic, \e underline,
+ \e strikeOut and \e kerning subproperties.
+
+ In order to provide editing widgets for the mentioned properties
+ in a property browser widget, this manager must be associated with
+ an editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtBoolPropertyManager *QtFontPropertyManager::subBoolPropertyManager() const
+{
+ return d_ptr->m_boolPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given property is not managed by this manager, this
+ function returns a font object that uses the application's default
+ font.
+
+ \sa setValue()
+*/
+QFont QtFontPropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QFont());
+}
+
+/*!
+ \reimp
+*/
+QString QtFontPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ return QtPropertyBrowserUtils::fontValueText(it.value());
+}
+
+/*!
+ \reimp
+*/
+QIcon QtFontPropertyManager::valueIcon(const QtProperty *property) const
+{
+ const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QIcon();
+
+ return QtPropertyBrowserUtils::fontValueIcon(it.value());
+}
+
+/*!
+ \fn void QtFontPropertyManager::setValue(QtProperty *property, const QFont &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ \sa value(), valueChanged()
+*/
+void QtFontPropertyManager::setValue(QtProperty *property, const QFont &val)
+{
+ const QtFontPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ const QFont oldVal = it.value();
+ if (oldVal == val && oldVal.resolve() == val.resolve())
+ return;
+
+ it.value() = val;
+
+ int idx = d_ptr->m_familyNames.indexOf(val.family());
+ if (idx == -1)
+ idx = 0;
+ bool settingValue = d_ptr->m_settingValue;
+ d_ptr->m_settingValue = true;
+ d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToFamily[property], idx);
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToPointSize[property], val.pointSize());
+ d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToBold[property], val.bold());
+ d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToItalic[property], val.italic());
+ d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToUnderline[property], val.underline());
+ d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToStrikeOut[property], val.strikeOut());
+ d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToKerning[property], val.kerning());
+ d_ptr->m_settingValue = settingValue;
+
+ emit propertyChanged(property);
+ emit valueChanged(property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtFontPropertyManager::initializeProperty(QtProperty *property)
+{
+ QFont val;
+ d_ptr->m_values[property] = val;
+
+ QtProperty *familyProp = d_ptr->m_enumPropertyManager->addProperty();
+ familyProp->setPropertyName(tr("Family"));
+ if (d_ptr->m_familyNames.empty())
+ d_ptr->m_familyNames = fontDatabase()->families();
+ d_ptr->m_enumPropertyManager->setEnumNames(familyProp, d_ptr->m_familyNames);
+ int idx = d_ptr->m_familyNames.indexOf(val.family());
+ if (idx == -1)
+ idx = 0;
+ d_ptr->m_enumPropertyManager->setValue(familyProp, idx);
+ d_ptr->m_propertyToFamily[property] = familyProp;
+ d_ptr->m_familyToProperty[familyProp] = property;
+ property->addSubProperty(familyProp);
+
+ QtProperty *pointSizeProp = d_ptr->m_intPropertyManager->addProperty();
+ pointSizeProp->setPropertyName(tr("Point Size"));
+ d_ptr->m_intPropertyManager->setValue(pointSizeProp, val.pointSize());
+ d_ptr->m_intPropertyManager->setMinimum(pointSizeProp, 1);
+ d_ptr->m_propertyToPointSize[property] = pointSizeProp;
+ d_ptr->m_pointSizeToProperty[pointSizeProp] = property;
+ property->addSubProperty(pointSizeProp);
+
+ QtProperty *boldProp = d_ptr->m_boolPropertyManager->addProperty();
+ boldProp->setPropertyName(tr("Bold"));
+ d_ptr->m_boolPropertyManager->setValue(boldProp, val.bold());
+ d_ptr->m_propertyToBold[property] = boldProp;
+ d_ptr->m_boldToProperty[boldProp] = property;
+ property->addSubProperty(boldProp);
+
+ QtProperty *italicProp = d_ptr->m_boolPropertyManager->addProperty();
+ italicProp->setPropertyName(tr("Italic"));
+ d_ptr->m_boolPropertyManager->setValue(italicProp, val.italic());
+ d_ptr->m_propertyToItalic[property] = italicProp;
+ d_ptr->m_italicToProperty[italicProp] = property;
+ property->addSubProperty(italicProp);
+
+ QtProperty *underlineProp = d_ptr->m_boolPropertyManager->addProperty();
+ underlineProp->setPropertyName(tr("Underline"));
+ d_ptr->m_boolPropertyManager->setValue(underlineProp, val.underline());
+ d_ptr->m_propertyToUnderline[property] = underlineProp;
+ d_ptr->m_underlineToProperty[underlineProp] = property;
+ property->addSubProperty(underlineProp);
+
+ QtProperty *strikeOutProp = d_ptr->m_boolPropertyManager->addProperty();
+ strikeOutProp->setPropertyName(tr("Strikeout"));
+ d_ptr->m_boolPropertyManager->setValue(strikeOutProp, val.strikeOut());
+ d_ptr->m_propertyToStrikeOut[property] = strikeOutProp;
+ d_ptr->m_strikeOutToProperty[strikeOutProp] = property;
+ property->addSubProperty(strikeOutProp);
+
+ QtProperty *kerningProp = d_ptr->m_boolPropertyManager->addProperty();
+ kerningProp->setPropertyName(tr("Kerning"));
+ d_ptr->m_boolPropertyManager->setValue(kerningProp, val.kerning());
+ d_ptr->m_propertyToKerning[property] = kerningProp;
+ d_ptr->m_kerningToProperty[kerningProp] = property;
+ property->addSubProperty(kerningProp);
+}
+
+/*!
+ \reimp
+*/
+void QtFontPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *familyProp = d_ptr->m_propertyToFamily[property];
+ if (familyProp) {
+ d_ptr->m_familyToProperty.remove(familyProp);
+ delete familyProp;
+ }
+ d_ptr->m_propertyToFamily.remove(property);
+
+ QtProperty *pointSizeProp = d_ptr->m_propertyToPointSize[property];
+ if (pointSizeProp) {
+ d_ptr->m_pointSizeToProperty.remove(pointSizeProp);
+ delete pointSizeProp;
+ }
+ d_ptr->m_propertyToPointSize.remove(property);
+
+ QtProperty *boldProp = d_ptr->m_propertyToBold[property];
+ if (boldProp) {
+ d_ptr->m_boldToProperty.remove(boldProp);
+ delete boldProp;
+ }
+ d_ptr->m_propertyToBold.remove(property);
+
+ QtProperty *italicProp = d_ptr->m_propertyToItalic[property];
+ if (italicProp) {
+ d_ptr->m_italicToProperty.remove(italicProp);
+ delete italicProp;
+ }
+ d_ptr->m_propertyToItalic.remove(property);
+
+ QtProperty *underlineProp = d_ptr->m_propertyToUnderline[property];
+ if (underlineProp) {
+ d_ptr->m_underlineToProperty.remove(underlineProp);
+ delete underlineProp;
+ }
+ d_ptr->m_propertyToUnderline.remove(property);
+
+ QtProperty *strikeOutProp = d_ptr->m_propertyToStrikeOut[property];
+ if (strikeOutProp) {
+ d_ptr->m_strikeOutToProperty.remove(strikeOutProp);
+ delete strikeOutProp;
+ }
+ d_ptr->m_propertyToStrikeOut.remove(property);
+
+ QtProperty *kerningProp = d_ptr->m_propertyToKerning[property];
+ if (kerningProp) {
+ d_ptr->m_kerningToProperty.remove(kerningProp);
+ delete kerningProp;
+ }
+ d_ptr->m_propertyToKerning.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtColorPropertyManager
+
+class QtColorPropertyManagerPrivate
+{
+ QtColorPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtColorPropertyManager)
+public:
+
+ void slotIntChanged(QtProperty *property, int value);
+ void slotPropertyDestroyed(QtProperty *property);
+
+ typedef QMap<const QtProperty *, QColor> PropertyValueMap;
+ PropertyValueMap m_values;
+
+ QtIntPropertyManager *m_intPropertyManager;
+
+ QMap<const QtProperty *, QtProperty *> m_propertyToR;
+ QMap<const QtProperty *, QtProperty *> m_propertyToG;
+ QMap<const QtProperty *, QtProperty *> m_propertyToB;
+ QMap<const QtProperty *, QtProperty *> m_propertyToA;
+
+ QMap<const QtProperty *, QtProperty *> m_rToProperty;
+ QMap<const QtProperty *, QtProperty *> m_gToProperty;
+ QMap<const QtProperty *, QtProperty *> m_bToProperty;
+ QMap<const QtProperty *, QtProperty *> m_aToProperty;
+};
+
+void QtColorPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value)
+{
+ if (QtProperty *prop = m_rToProperty.value(property, 0)) {
+ QColor c = m_values[prop];
+ c.setRed(value);
+ q_ptr->setValue(prop, c);
+ } else if (QtProperty *prop = m_gToProperty.value(property, 0)) {
+ QColor c = m_values[prop];
+ c.setGreen(value);
+ q_ptr->setValue(prop, c);
+ } else if (QtProperty *prop = m_bToProperty.value(property, 0)) {
+ QColor c = m_values[prop];
+ c.setBlue(value);
+ q_ptr->setValue(prop, c);
+ } else if (QtProperty *prop = m_aToProperty.value(property, 0)) {
+ QColor c = m_values[prop];
+ c.setAlpha(value);
+ q_ptr->setValue(prop, c);
+ }
+}
+
+void QtColorPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property)
+{
+ if (QtProperty *pointProp = m_rToProperty.value(property, 0)) {
+ m_propertyToR[pointProp] = 0;
+ m_rToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_gToProperty.value(property, 0)) {
+ m_propertyToG[pointProp] = 0;
+ m_gToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_bToProperty.value(property, 0)) {
+ m_propertyToB[pointProp] = 0;
+ m_bToProperty.remove(property);
+ } else if (QtProperty *pointProp = m_aToProperty.value(property, 0)) {
+ m_propertyToA[pointProp] = 0;
+ m_aToProperty.remove(property);
+ }
+}
+
+/*!
+ \class QtColorPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtColorPropertyManager provides and manages QColor properties.
+
+ A color property has nested \e red, \e green and \e blue
+ subproperties. The top-level property's value can be retrieved
+ using the value() function, and set using the setValue() slot.
+
+ The subproperties are created by a QtIntPropertyManager object. This
+ manager can be retrieved using the subIntPropertyManager() function. In
+ order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ In addition, QtColorPropertyManager provides the valueChanged() signal
+ which is emitted whenever a property created by this manager
+ changes.
+
+ \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser, QtIntPropertyManager
+*/
+
+/*!
+ \fn void QtColorPropertyManager::valueChanged(QtProperty *property, const QColor &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtColorPropertyManager::QtColorPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtColorPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_intPropertyManager = new QtIntPropertyManager(this);
+ connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotIntChanged(QtProperty *, int)));
+
+ connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)),
+ this, SLOT(slotPropertyDestroyed(QtProperty *)));
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtColorPropertyManager::~QtColorPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the manager that produces the nested \e red, \e green and
+ \e blue subproperties.
+
+ In order to provide editing widgets for the subproperties in a
+ property browser widget, this manager must be associated with an
+ editor factory.
+
+ \sa QtAbstractPropertyBrowser::setFactoryForManager()
+*/
+QtIntPropertyManager *QtColorPropertyManager::subIntPropertyManager() const
+{
+ return d_ptr->m_intPropertyManager;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by \e this manager, this
+ function returns an invalid color.
+
+ \sa setValue()
+*/
+QColor QtColorPropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QColor());
+}
+
+/*!
+ \reimp
+*/
+
+QString QtColorPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ return QtPropertyBrowserUtils::colorValueText(it.value());
+}
+
+/*!
+ \reimp
+*/
+
+QIcon QtColorPropertyManager::valueIcon(const QtProperty *property) const
+{
+ const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QIcon();
+ return QtPropertyBrowserUtils::brushValueIcon(QBrush(it.value()));
+}
+
+/*!
+ \fn void QtColorPropertyManager::setValue(QtProperty *property, const QColor &value)
+
+ Sets the value of the given \a property to \a value. Nested
+ properties are updated automatically.
+
+ \sa value(), valueChanged()
+*/
+void QtColorPropertyManager::setValue(QtProperty *property, const QColor &val)
+{
+ const QtColorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ if (it.value() == val)
+ return;
+
+ it.value() = val;
+
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToR[property], val.red());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToG[property], val.green());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToB[property], val.blue());
+ d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToA[property], val.alpha());
+
+ emit propertyChanged(property);
+ emit valueChanged(property, val);
+}
+
+/*!
+ \reimp
+*/
+void QtColorPropertyManager::initializeProperty(QtProperty *property)
+{
+ QColor val;
+ d_ptr->m_values[property] = val;
+
+ QtProperty *rProp = d_ptr->m_intPropertyManager->addProperty();
+ rProp->setPropertyName(tr("Red"));
+ d_ptr->m_intPropertyManager->setValue(rProp, val.red());
+ d_ptr->m_intPropertyManager->setRange(rProp, 0, 0xFF);
+ d_ptr->m_propertyToR[property] = rProp;
+ d_ptr->m_rToProperty[rProp] = property;
+ property->addSubProperty(rProp);
+
+ QtProperty *gProp = d_ptr->m_intPropertyManager->addProperty();
+ gProp->setPropertyName(tr("Green"));
+ d_ptr->m_intPropertyManager->setValue(gProp, val.green());
+ d_ptr->m_intPropertyManager->setRange(gProp, 0, 0xFF);
+ d_ptr->m_propertyToG[property] = gProp;
+ d_ptr->m_gToProperty[gProp] = property;
+ property->addSubProperty(gProp);
+
+ QtProperty *bProp = d_ptr->m_intPropertyManager->addProperty();
+ bProp->setPropertyName(tr("Blue"));
+ d_ptr->m_intPropertyManager->setValue(bProp, val.blue());
+ d_ptr->m_intPropertyManager->setRange(bProp, 0, 0xFF);
+ d_ptr->m_propertyToB[property] = bProp;
+ d_ptr->m_bToProperty[bProp] = property;
+ property->addSubProperty(bProp);
+
+ QtProperty *aProp = d_ptr->m_intPropertyManager->addProperty();
+ aProp->setPropertyName(tr("Alpha"));
+ d_ptr->m_intPropertyManager->setValue(aProp, val.alpha());
+ d_ptr->m_intPropertyManager->setRange(aProp, 0, 0xFF);
+ d_ptr->m_propertyToA[property] = aProp;
+ d_ptr->m_aToProperty[aProp] = property;
+ property->addSubProperty(aProp);
+}
+
+/*!
+ \reimp
+*/
+void QtColorPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ QtProperty *rProp = d_ptr->m_propertyToR[property];
+ if (rProp) {
+ d_ptr->m_rToProperty.remove(rProp);
+ delete rProp;
+ }
+ d_ptr->m_propertyToR.remove(property);
+
+ QtProperty *gProp = d_ptr->m_propertyToG[property];
+ if (gProp) {
+ d_ptr->m_gToProperty.remove(gProp);
+ delete gProp;
+ }
+ d_ptr->m_propertyToG.remove(property);
+
+ QtProperty *bProp = d_ptr->m_propertyToB[property];
+ if (bProp) {
+ d_ptr->m_bToProperty.remove(bProp);
+ delete bProp;
+ }
+ d_ptr->m_propertyToB.remove(property);
+
+ QtProperty *aProp = d_ptr->m_propertyToA[property];
+ if (aProp) {
+ d_ptr->m_aToProperty.remove(aProp);
+ delete aProp;
+ }
+ d_ptr->m_propertyToA.remove(property);
+
+ d_ptr->m_values.remove(property);
+}
+
+// QtCursorPropertyManager
+
+Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase)
+
+class QtCursorPropertyManagerPrivate
+{
+ QtCursorPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtCursorPropertyManager)
+public:
+ typedef QMap<const QtProperty *, QCursor> PropertyValueMap;
+ PropertyValueMap m_values;
+};
+
+/*!
+ \class QtCursorPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtCursorPropertyManager provides and manages QCursor properties.
+
+ A cursor property has a current value which can be
+ retrieved using the value() function, and set using the setValue()
+ slot. In addition, QtCursorPropertyManager provides the
+ valueChanged() signal which is emitted whenever a property created
+ by this manager changes.
+
+ \sa QtAbstractPropertyManager
+*/
+
+/*!
+ \fn void QtCursorPropertyManager::valueChanged(QtProperty *property, const QCursor &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the new
+ \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtCursorPropertyManager::QtCursorPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtCursorPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtCursorPropertyManager::~QtCursorPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns a default QCursor object.
+
+ \sa setValue()
+*/
+#ifndef QT_NO_CURSOR
+QCursor QtCursorPropertyManager::value(const QtProperty *property) const
+{
+ return d_ptr->m_values.value(property, QCursor());
+}
+#endif
+
+/*!
+ \reimp
+*/
+QString QtCursorPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QString();
+
+ return cursorDatabase()->cursorToShapeName(it.value());
+}
+
+/*!
+ \reimp
+*/
+QIcon QtCursorPropertyManager::valueIcon(const QtProperty *property) const
+{
+ const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property);
+ if (it == d_ptr->m_values.constEnd())
+ return QIcon();
+
+ return cursorDatabase()->cursorToShapeIcon(it.value());
+}
+
+/*!
+ \fn void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value)
+
+ Sets the value of the given \a property to \a value.
+
+ \sa value(), valueChanged()
+*/
+void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value)
+{
+#ifndef QT_NO_CURSOR
+ const QtCursorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property);
+ if (it == d_ptr->m_values.end())
+ return;
+
+ if (it.value().shape() == value.shape() && value.shape() != Qt::BitmapCursor)
+ return;
+
+ it.value() = value;
+
+ emit propertyChanged(property);
+ emit valueChanged(property, value);
+#endif
+}
+
+/*!
+ \reimp
+*/
+void QtCursorPropertyManager::initializeProperty(QtProperty *property)
+{
+#ifndef QT_NO_CURSOR
+ d_ptr->m_values[property] = QCursor();
+#endif
+}
+
+/*!
+ \reimp
+*/
+void QtCursorPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ d_ptr->m_values.remove(property);
+}
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#include "moc_qtpropertymanager.cpp"
+#include "qtpropertymanager.moc"
diff --git a/tools/shared/qtpropertybrowser/qtpropertymanager.h b/tools/shared/qtpropertybrowser/qtpropertymanager.h
new file mode 100644
index 0000000000..90fe5c02b1
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtpropertymanager.h
@@ -0,0 +1,750 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTPROPERTYMANAGER_H
+#define QTPROPERTYMANAGER_H
+
+#include "qtpropertybrowser.h"
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QDate;
+class QTime;
+class QDateTime;
+class QLocale;
+
+class QtGroupPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtGroupPropertyManager(QObject *parent = 0);
+ ~QtGroupPropertyManager();
+
+protected:
+ virtual bool hasValue(const QtProperty *property) const;
+
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+};
+
+class QtIntPropertyManagerPrivate;
+
+class QtIntPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtIntPropertyManager(QObject *parent = 0);
+ ~QtIntPropertyManager();
+
+ int value(const QtProperty *property) const;
+ int minimum(const QtProperty *property) const;
+ int maximum(const QtProperty *property) const;
+ int singleStep(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, int val);
+ void setMinimum(QtProperty *property, int minVal);
+ void setMaximum(QtProperty *property, int maxVal);
+ void setRange(QtProperty *property, int minVal, int maxVal);
+ void setSingleStep(QtProperty *property, int step);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, int val);
+ void rangeChanged(QtProperty *property, int minVal, int maxVal);
+ void singleStepChanged(QtProperty *property, int step);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtIntPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtIntPropertyManager)
+ Q_DISABLE_COPY(QtIntPropertyManager)
+};
+
+class QtBoolPropertyManagerPrivate;
+
+class QtBoolPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtBoolPropertyManager(QObject *parent = 0);
+ ~QtBoolPropertyManager();
+
+ bool value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, bool val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, bool val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ QIcon valueIcon(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtBoolPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtBoolPropertyManager)
+ Q_DISABLE_COPY(QtBoolPropertyManager)
+};
+
+class QtDoublePropertyManagerPrivate;
+
+class QtDoublePropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtDoublePropertyManager(QObject *parent = 0);
+ ~QtDoublePropertyManager();
+
+ double value(const QtProperty *property) const;
+ double minimum(const QtProperty *property) const;
+ double maximum(const QtProperty *property) const;
+ double singleStep(const QtProperty *property) const;
+ int decimals(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, double val);
+ void setMinimum(QtProperty *property, double minVal);
+ void setMaximum(QtProperty *property, double maxVal);
+ void setRange(QtProperty *property, double minVal, double maxVal);
+ void setSingleStep(QtProperty *property, double step);
+ void setDecimals(QtProperty *property, int prec);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, double val);
+ void rangeChanged(QtProperty *property, double minVal, double maxVal);
+ void singleStepChanged(QtProperty *property, double step);
+ void decimalsChanged(QtProperty *property, int prec);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtDoublePropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtDoublePropertyManager)
+ Q_DISABLE_COPY(QtDoublePropertyManager)
+};
+
+class QtStringPropertyManagerPrivate;
+
+class QtStringPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtStringPropertyManager(QObject *parent = 0);
+ ~QtStringPropertyManager();
+
+ QString value(const QtProperty *property) const;
+ QRegExp regExp(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QString &val);
+ void setRegExp(QtProperty *property, const QRegExp &regExp);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QString &val);
+ void regExpChanged(QtProperty *property, const QRegExp &regExp);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtStringPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtStringPropertyManager)
+ Q_DISABLE_COPY(QtStringPropertyManager)
+};
+
+class QtDatePropertyManagerPrivate;
+
+class QtDatePropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtDatePropertyManager(QObject *parent = 0);
+ ~QtDatePropertyManager();
+
+ QDate value(const QtProperty *property) const;
+ QDate minimum(const QtProperty *property) const;
+ QDate maximum(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QDate &val);
+ void setMinimum(QtProperty *property, const QDate &minVal);
+ void setMaximum(QtProperty *property, const QDate &maxVal);
+ void setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QDate &val);
+ void rangeChanged(QtProperty *property, const QDate &minVal, const QDate &maxVal);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtDatePropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtDatePropertyManager)
+ Q_DISABLE_COPY(QtDatePropertyManager)
+};
+
+class QtTimePropertyManagerPrivate;
+
+class QtTimePropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtTimePropertyManager(QObject *parent = 0);
+ ~QtTimePropertyManager();
+
+ QTime value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QTime &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QTime &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtTimePropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtTimePropertyManager)
+ Q_DISABLE_COPY(QtTimePropertyManager)
+};
+
+class QtDateTimePropertyManagerPrivate;
+
+class QtDateTimePropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtDateTimePropertyManager(QObject *parent = 0);
+ ~QtDateTimePropertyManager();
+
+ QDateTime value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QDateTime &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QDateTime &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtDateTimePropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtDateTimePropertyManager)
+ Q_DISABLE_COPY(QtDateTimePropertyManager)
+};
+
+class QtKeySequencePropertyManagerPrivate;
+
+class QtKeySequencePropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtKeySequencePropertyManager(QObject *parent = 0);
+ ~QtKeySequencePropertyManager();
+
+ QKeySequence value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QKeySequence &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QKeySequence &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtKeySequencePropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtKeySequencePropertyManager)
+ Q_DISABLE_COPY(QtKeySequencePropertyManager)
+};
+
+class QtCharPropertyManagerPrivate;
+
+class QtCharPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtCharPropertyManager(QObject *parent = 0);
+ ~QtCharPropertyManager();
+
+ QChar value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QChar &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QChar &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtCharPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtCharPropertyManager)
+ Q_DISABLE_COPY(QtCharPropertyManager)
+};
+
+class QtEnumPropertyManager;
+class QtLocalePropertyManagerPrivate;
+
+class QtLocalePropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtLocalePropertyManager(QObject *parent = 0);
+ ~QtLocalePropertyManager();
+
+ QtEnumPropertyManager *subEnumPropertyManager() const;
+
+ QLocale value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QLocale &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QLocale &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtLocalePropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtLocalePropertyManager)
+ Q_DISABLE_COPY(QtLocalePropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtPointPropertyManagerPrivate;
+
+class QtPointPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtPointPropertyManager(QObject *parent = 0);
+ ~QtPointPropertyManager();
+
+ QtIntPropertyManager *subIntPropertyManager() const;
+
+ QPoint value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QPoint &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QPoint &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtPointPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtPointPropertyManager)
+ Q_DISABLE_COPY(QtPointPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtPointFPropertyManagerPrivate;
+
+class QtPointFPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtPointFPropertyManager(QObject *parent = 0);
+ ~QtPointFPropertyManager();
+
+ QtDoublePropertyManager *subDoublePropertyManager() const;
+
+ QPointF value(const QtProperty *property) const;
+ int decimals(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QPointF &val);
+ void setDecimals(QtProperty *property, int prec);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QPointF &val);
+ void decimalsChanged(QtProperty *property, int prec);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtPointFPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtPointFPropertyManager)
+ Q_DISABLE_COPY(QtPointFPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtSizePropertyManagerPrivate;
+
+class QtSizePropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtSizePropertyManager(QObject *parent = 0);
+ ~QtSizePropertyManager();
+
+ QtIntPropertyManager *subIntPropertyManager() const;
+
+ QSize value(const QtProperty *property) const;
+ QSize minimum(const QtProperty *property) const;
+ QSize maximum(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QSize &val);
+ void setMinimum(QtProperty *property, const QSize &minVal);
+ void setMaximum(QtProperty *property, const QSize &maxVal);
+ void setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QSize &val);
+ void rangeChanged(QtProperty *property, const QSize &minVal, const QSize &maxVal);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtSizePropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtSizePropertyManager)
+ Q_DISABLE_COPY(QtSizePropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtSizeFPropertyManagerPrivate;
+
+class QtSizeFPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtSizeFPropertyManager(QObject *parent = 0);
+ ~QtSizeFPropertyManager();
+
+ QtDoublePropertyManager *subDoublePropertyManager() const;
+
+ QSizeF value(const QtProperty *property) const;
+ QSizeF minimum(const QtProperty *property) const;
+ QSizeF maximum(const QtProperty *property) const;
+ int decimals(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QSizeF &val);
+ void setMinimum(QtProperty *property, const QSizeF &minVal);
+ void setMaximum(QtProperty *property, const QSizeF &maxVal);
+ void setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal);
+ void setDecimals(QtProperty *property, int prec);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QSizeF &val);
+ void rangeChanged(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal);
+ void decimalsChanged(QtProperty *property, int prec);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtSizeFPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtSizeFPropertyManager)
+ Q_DISABLE_COPY(QtSizeFPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtRectPropertyManagerPrivate;
+
+class QtRectPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtRectPropertyManager(QObject *parent = 0);
+ ~QtRectPropertyManager();
+
+ QtIntPropertyManager *subIntPropertyManager() const;
+
+ QRect value(const QtProperty *property) const;
+ QRect constraint(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QRect &val);
+ void setConstraint(QtProperty *property, const QRect &constraint);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QRect &val);
+ void constraintChanged(QtProperty *property, const QRect &constraint);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtRectPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtRectPropertyManager)
+ Q_DISABLE_COPY(QtRectPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtRectFPropertyManagerPrivate;
+
+class QtRectFPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtRectFPropertyManager(QObject *parent = 0);
+ ~QtRectFPropertyManager();
+
+ QtDoublePropertyManager *subDoublePropertyManager() const;
+
+ QRectF value(const QtProperty *property) const;
+ QRectF constraint(const QtProperty *property) const;
+ int decimals(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QRectF &val);
+ void setConstraint(QtProperty *property, const QRectF &constraint);
+ void setDecimals(QtProperty *property, int prec);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QRectF &val);
+ void constraintChanged(QtProperty *property, const QRectF &constraint);
+ void decimalsChanged(QtProperty *property, int prec);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtRectFPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtRectFPropertyManager)
+ Q_DISABLE_COPY(QtRectFPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtEnumPropertyManagerPrivate;
+
+class QtEnumPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtEnumPropertyManager(QObject *parent = 0);
+ ~QtEnumPropertyManager();
+
+ int value(const QtProperty *property) const;
+ QStringList enumNames(const QtProperty *property) const;
+ QMap<int, QIcon> enumIcons(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, int val);
+ void setEnumNames(QtProperty *property, const QStringList &names);
+ void setEnumIcons(QtProperty *property, const QMap<int, QIcon> &icons);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, int val);
+ void enumNamesChanged(QtProperty *property, const QStringList &names);
+ void enumIconsChanged(QtProperty *property, const QMap<int, QIcon> &icons);
+protected:
+ QString valueText(const QtProperty *property) const;
+ QIcon valueIcon(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtEnumPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtEnumPropertyManager)
+ Q_DISABLE_COPY(QtEnumPropertyManager)
+};
+
+class QtFlagPropertyManagerPrivate;
+
+class QtFlagPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtFlagPropertyManager(QObject *parent = 0);
+ ~QtFlagPropertyManager();
+
+ QtBoolPropertyManager *subBoolPropertyManager() const;
+
+ int value(const QtProperty *property) const;
+ QStringList flagNames(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, int val);
+ void setFlagNames(QtProperty *property, const QStringList &names);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, int val);
+ void flagNamesChanged(QtProperty *property, const QStringList &names);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtFlagPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtFlagPropertyManager)
+ Q_DISABLE_COPY(QtFlagPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtSizePolicyPropertyManagerPrivate;
+
+class QtSizePolicyPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtSizePolicyPropertyManager(QObject *parent = 0);
+ ~QtSizePolicyPropertyManager();
+
+ QtIntPropertyManager *subIntPropertyManager() const;
+ QtEnumPropertyManager *subEnumPropertyManager() const;
+
+ QSizePolicy value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QSizePolicy &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QSizePolicy &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtSizePolicyPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtSizePolicyPropertyManager)
+ Q_DISABLE_COPY(QtSizePolicyPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtFontPropertyManagerPrivate;
+
+class QtFontPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtFontPropertyManager(QObject *parent = 0);
+ ~QtFontPropertyManager();
+
+ QtIntPropertyManager *subIntPropertyManager() const;
+ QtEnumPropertyManager *subEnumPropertyManager() const;
+ QtBoolPropertyManager *subBoolPropertyManager() const;
+
+ QFont value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QFont &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QFont &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ QIcon valueIcon(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtFontPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtFontPropertyManager)
+ Q_DISABLE_COPY(QtFontPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+ Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseChanged())
+ Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseDelayedChange())
+};
+
+class QtColorPropertyManagerPrivate;
+
+class QtColorPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtColorPropertyManager(QObject *parent = 0);
+ ~QtColorPropertyManager();
+
+ QtIntPropertyManager *subIntPropertyManager() const;
+
+ QColor value(const QtProperty *property) const;
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QColor &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QColor &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ QIcon valueIcon(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtColorPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtColorPropertyManager)
+ Q_DISABLE_COPY(QtColorPropertyManager)
+ Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *))
+};
+
+class QtCursorPropertyManagerPrivate;
+
+class QtCursorPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtCursorPropertyManager(QObject *parent = 0);
+ ~QtCursorPropertyManager();
+
+#ifndef QT_NO_CURSOR
+ QCursor value(const QtProperty *property) const;
+#endif
+
+public Q_SLOTS:
+ void setValue(QtProperty *property, const QCursor &val);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QCursor &val);
+protected:
+ QString valueText(const QtProperty *property) const;
+ QIcon valueIcon(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+private:
+ QtCursorPropertyManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtCursorPropertyManager)
+ Q_DISABLE_COPY(QtCursorPropertyManager)
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#endif
diff --git a/tools/shared/qtpropertybrowser/qttreepropertybrowser.cpp b/tools/shared/qtpropertybrowser/qttreepropertybrowser.cpp
new file mode 100644
index 0000000000..ed262e50ec
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qttreepropertybrowser.cpp
@@ -0,0 +1,1048 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qttreepropertybrowser.h"
+#include <QtCore/QSet>
+#include <QtGui/QIcon>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QItemDelegate>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QHeaderView>
+#include <QtGui/QPainter>
+#include <QtGui/QApplication>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QStyle>
+#include <QtGui/QPalette>
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtPropertyEditorView;
+
+class QtTreePropertyBrowserPrivate
+{
+ QtTreePropertyBrowser *q_ptr;
+ Q_DECLARE_PUBLIC(QtTreePropertyBrowser)
+
+public:
+ QtTreePropertyBrowserPrivate();
+ void init(QWidget *parent);
+
+ void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex);
+ void propertyRemoved(QtBrowserItem *index);
+ void propertyChanged(QtBrowserItem *index);
+ QWidget *createEditor(QtProperty *property, QWidget *parent) const
+ { return q_ptr->createEditor(property, parent); }
+ QtProperty *indexToProperty(const QModelIndex &index) const;
+ QTreeWidgetItem *indexToItem(const QModelIndex &index) const;
+ QtBrowserItem *indexToBrowserItem(const QModelIndex &index) const;
+ bool lastColumn(int column) const;
+ void disableItem(QTreeWidgetItem *item) const;
+ void enableItem(QTreeWidgetItem *item) const;
+ bool hasValue(QTreeWidgetItem *item) const;
+
+ void slotCollapsed(const QModelIndex &index);
+ void slotExpanded(const QModelIndex &index);
+
+ QColor calculatedBackgroundColor(QtBrowserItem *item) const;
+
+ QtPropertyEditorView *treeWidget() const { return m_treeWidget; }
+ bool markPropertiesWithoutValue() const { return m_markPropertiesWithoutValue; }
+
+ QtBrowserItem *currentItem() const;
+ void setCurrentItem(QtBrowserItem *browserItem, bool block);
+ void editItem(QtBrowserItem *browserItem);
+
+ void slotCurrentBrowserItemChanged(QtBrowserItem *item);
+ void slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *);
+
+ QTreeWidgetItem *editedItem() const;
+
+private:
+ void updateItem(QTreeWidgetItem *item);
+
+ QMap<QtBrowserItem *, QTreeWidgetItem *> m_indexToItem;
+ QMap<QTreeWidgetItem *, QtBrowserItem *> m_itemToIndex;
+
+ QMap<QtBrowserItem *, QColor> m_indexToBackgroundColor;
+
+ QtPropertyEditorView *m_treeWidget;
+
+ bool m_headerVisible;
+ QtTreePropertyBrowser::ResizeMode m_resizeMode;
+ class QtPropertyEditorDelegate *m_delegate;
+ bool m_markPropertiesWithoutValue;
+ bool m_browserChangedBlocked;
+ QIcon m_expandIcon;
+};
+
+// ------------ QtPropertyEditorView
+class QtPropertyEditorView : public QTreeWidget
+{
+ Q_OBJECT
+public:
+ QtPropertyEditorView(QWidget *parent = 0);
+
+ void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate)
+ { m_editorPrivate = editorPrivate; }
+
+ QTreeWidgetItem *indexToItem(const QModelIndex &index) const
+ { return itemFromIndex(index); }
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+private:
+ QtTreePropertyBrowserPrivate *m_editorPrivate;
+};
+
+QtPropertyEditorView::QtPropertyEditorView(QWidget *parent) :
+ QTreeWidget(parent),
+ m_editorPrivate(0)
+{
+ connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int)));
+}
+
+void QtPropertyEditorView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QStyleOptionViewItemV3 opt = option;
+ bool hasValue = true;
+ if (m_editorPrivate) {
+ QtProperty *property = m_editorPrivate->indexToProperty(index);
+ if (property)
+ hasValue = property->hasValue();
+ }
+ if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) {
+ const QColor c = option.palette.color(QPalette::Dark);
+ painter->fillRect(option.rect, c);
+ opt.palette.setColor(QPalette::AlternateBase, c);
+ } else {
+ const QColor c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
+ if (c.isValid()) {
+ painter->fillRect(option.rect, c);
+ opt.palette.setColor(QPalette::AlternateBase, c.lighter(112));
+ }
+ }
+ QTreeWidget::drawRow(painter, opt, index);
+ QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
+ painter->save();
+ painter->setPen(QPen(color));
+ painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
+ painter->restore();
+}
+
+void QtPropertyEditorView::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ case Qt::Key_Space: // Trigger Edit
+ if (!m_editorPrivate->editedItem())
+ if (const QTreeWidgetItem *item = currentItem())
+ if (item->columnCount() >= 2 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) {
+ event->accept();
+ // If the current position is at column 0, move to 1.
+ QModelIndex index = currentIndex();
+ if (index.column() == 0) {
+ index = index.sibling(index.row(), 1);
+ setCurrentIndex(index);
+ }
+ edit(index);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ QTreeWidget::keyPressEvent(event);
+}
+
+void QtPropertyEditorView::mousePressEvent(QMouseEvent *event)
+{
+ QTreeWidget::mousePressEvent(event);
+ QTreeWidgetItem *item = itemAt(event->pos());
+
+ if (item) {
+ if ((item != m_editorPrivate->editedItem()) && (event->button() == Qt::LeftButton)
+ && (header()->logicalIndexAt(event->pos().x()) == 1)
+ && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) {
+ editItem(item, 1);
+ } else if (!m_editorPrivate->hasValue(item) && m_editorPrivate->markPropertiesWithoutValue() && !rootIsDecorated()) {
+ if (event->pos().x() + header()->offset() < 20)
+ item->setExpanded(!item->isExpanded());
+ }
+ }
+}
+
+// ------------ QtPropertyEditorDelegate
+class QtPropertyEditorDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ QtPropertyEditorDelegate(QObject *parent = 0)
+ : QItemDelegate(parent), m_editorPrivate(0), m_editedItem(0), m_editedWidget(0)
+ {}
+
+ void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate)
+ { m_editorPrivate = editorPrivate; }
+
+ QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+ void setModelData(QWidget *, QAbstractItemModel *,
+ const QModelIndex &) const {}
+
+ void setEditorData(QWidget *, const QModelIndex &) const {}
+
+ bool eventFilter(QObject *object, QEvent *event);
+ void closeEditor(QtProperty *property);
+
+ QTreeWidgetItem *editedItem() const { return m_editedItem; }
+
+private slots:
+ void slotEditorDestroyed(QObject *object);
+
+private:
+ int indentation(const QModelIndex &index) const;
+
+ typedef QMap<QWidget *, QtProperty *> EditorToPropertyMap;
+ mutable EditorToPropertyMap m_editorToProperty;
+
+ typedef QMap<QtProperty *, QWidget *> PropertyToEditorMap;
+ mutable PropertyToEditorMap m_propertyToEditor;
+ QtTreePropertyBrowserPrivate *m_editorPrivate;
+ mutable QTreeWidgetItem *m_editedItem;
+ mutable QWidget *m_editedWidget;
+};
+
+int QtPropertyEditorDelegate::indentation(const QModelIndex &index) const
+{
+ if (!m_editorPrivate)
+ return 0;
+
+ QTreeWidgetItem *item = m_editorPrivate->indexToItem(index);
+ int indent = 0;
+ while (item->parent()) {
+ item = item->parent();
+ ++indent;
+ }
+ if (m_editorPrivate->treeWidget()->rootIsDecorated())
+ ++indent;
+ return indent * m_editorPrivate->treeWidget()->indentation();
+}
+
+void QtPropertyEditorDelegate::slotEditorDestroyed(QObject *object)
+{
+ if (QWidget *w = qobject_cast<QWidget *>(object)) {
+ const EditorToPropertyMap::iterator it = m_editorToProperty.find(w);
+ if (it != m_editorToProperty.end()) {
+ m_propertyToEditor.remove(it.value());
+ m_editorToProperty.erase(it);
+ }
+ if (m_editedWidget == w) {
+ m_editedWidget = 0;
+ m_editedItem = 0;
+ }
+ }
+}
+
+void QtPropertyEditorDelegate::closeEditor(QtProperty *property)
+{
+ if (QWidget *w = m_propertyToEditor.value(property, 0))
+ w->deleteLater();
+}
+
+QWidget *QtPropertyEditorDelegate::createEditor(QWidget *parent,
+ const QStyleOptionViewItem &, const QModelIndex &index) const
+{
+ if (index.column() == 1 && m_editorPrivate) {
+ QtProperty *property = m_editorPrivate->indexToProperty(index);
+ QTreeWidgetItem *item = m_editorPrivate->indexToItem(index);
+ if (property && item && (item->flags() & Qt::ItemIsEnabled)) {
+ QWidget *editor = m_editorPrivate->createEditor(property, parent);
+ if (editor) {
+ editor->setAutoFillBackground(true);
+ editor->installEventFilter(const_cast<QtPropertyEditorDelegate *>(this));
+ connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
+ m_propertyToEditor[property] = editor;
+ m_editorToProperty[editor] = property;
+ m_editedItem = item;
+ m_editedWidget = editor;
+ }
+ return editor;
+ }
+ }
+ return 0;
+}
+
+void QtPropertyEditorDelegate::updateEditorGeometry(QWidget *editor,
+ const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ editor->setGeometry(option.rect.adjusted(0, 0, 0, -1));
+}
+
+void QtPropertyEditorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ bool hasValue = true;
+ if (m_editorPrivate) {
+ QtProperty *property = m_editorPrivate->indexToProperty(index);
+ if (property)
+ hasValue = property->hasValue();
+ }
+ QStyleOptionViewItemV3 opt = option;
+ if ((m_editorPrivate && index.column() == 0) || !hasValue) {
+ QtProperty *property = m_editorPrivate->indexToProperty(index);
+ if (property && property->isModified()) {
+ opt.font.setBold(true);
+ opt.fontMetrics = QFontMetrics(opt.font);
+ }
+ }
+ QColor c;
+ if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) {
+ c = opt.palette.color(QPalette::Dark);
+ opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText));
+ } else {
+ c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
+ if (c.isValid() && (opt.features & QStyleOptionViewItemV2::Alternate))
+ c = c.lighter(112);
+ }
+ if (c.isValid())
+ painter->fillRect(option.rect, c);
+ opt.state &= ~QStyle::State_HasFocus;
+ QItemDelegate::paint(painter, opt, index);
+
+ opt.palette.setCurrentColorGroup(QPalette::Active);
+ QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
+ painter->save();
+ painter->setPen(QPen(color));
+ if (!m_editorPrivate || (!m_editorPrivate->lastColumn(index.column()) && hasValue)) {
+ int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left();
+ painter->drawLine(right, option.rect.y(), right, option.rect.bottom());
+ }
+ painter->restore();
+}
+
+QSize QtPropertyEditorDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ return QItemDelegate::sizeHint(option, index) + QSize(3, 4);
+}
+
+bool QtPropertyEditorDelegate::eventFilter(QObject *object, QEvent *event)
+{
+ if (event->type() == QEvent::FocusOut) {
+ QFocusEvent *fe = static_cast<QFocusEvent *>(event);
+ if (fe->reason() == Qt::ActiveWindowFocusReason)
+ return false;
+ }
+ return QItemDelegate::eventFilter(object, event);
+}
+
+// -------- QtTreePropertyBrowserPrivate implementation
+QtTreePropertyBrowserPrivate::QtTreePropertyBrowserPrivate() :
+ m_treeWidget(0),
+ m_headerVisible(true),
+ m_resizeMode(QtTreePropertyBrowser::Stretch),
+ m_delegate(0),
+ m_markPropertiesWithoutValue(false),
+ m_browserChangedBlocked(false)
+{
+}
+
+// Draw an icon indicating opened/closing branches
+static QIcon drawIndicatorIcon(const QPalette &palette, QStyle *style)
+{
+ QPixmap pix(14, 14);
+ pix.fill(Qt::transparent);
+ QStyleOption branchOption;
+ QRect r(QPoint(0, 0), pix.size());
+ branchOption.rect = QRect(2, 2, 9, 9); // ### hardcoded in qcommonstyle.cpp
+ branchOption.palette = palette;
+ branchOption.state = QStyle::State_Children;
+
+ QPainter p;
+ // Draw closed state
+ p.begin(&pix);
+ style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
+ p.end();
+ QIcon rc = pix;
+ rc.addPixmap(pix, QIcon::Selected, QIcon::Off);
+ // Draw opened state
+ branchOption.state |= QStyle::State_Open;
+ pix.fill(Qt::transparent);
+ p.begin(&pix);
+ style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
+ p.end();
+
+ rc.addPixmap(pix, QIcon::Normal, QIcon::On);
+ rc.addPixmap(pix, QIcon::Selected, QIcon::On);
+ return rc;
+}
+
+void QtTreePropertyBrowserPrivate::init(QWidget *parent)
+{
+ QHBoxLayout *layout = new QHBoxLayout(parent);
+ layout->setMargin(0);
+ m_treeWidget = new QtPropertyEditorView(parent);
+ m_treeWidget->setEditorPrivate(this);
+ m_treeWidget->setIconSize(QSize(18, 18));
+ layout->addWidget(m_treeWidget);
+
+ m_treeWidget->setColumnCount(2);
+ QStringList labels;
+ labels.append(QApplication::translate("QtTreePropertyBrowser", "Property", 0, QApplication::UnicodeUTF8));
+ labels.append(QApplication::translate("QtTreePropertyBrowser", "Value", 0, QApplication::UnicodeUTF8));
+ m_treeWidget->setHeaderLabels(labels);
+ m_treeWidget->setAlternatingRowColors(true);
+ m_treeWidget->setEditTriggers(QAbstractItemView::EditKeyPressed);
+ m_delegate = new QtPropertyEditorDelegate(parent);
+ m_delegate->setEditorPrivate(this);
+ m_treeWidget->setItemDelegate(m_delegate);
+ m_treeWidget->header()->setMovable(false);
+ m_treeWidget->header()->setResizeMode(QHeaderView::Stretch);
+
+ m_expandIcon = drawIndicatorIcon(q_ptr->palette(), q_ptr->style());
+
+ QObject::connect(m_treeWidget, SIGNAL(collapsed(const QModelIndex &)), q_ptr, SLOT(slotCollapsed(const QModelIndex &)));
+ QObject::connect(m_treeWidget, SIGNAL(expanded(const QModelIndex &)), q_ptr, SLOT(slotExpanded(const QModelIndex &)));
+ QObject::connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), q_ptr, SLOT(slotCurrentTreeItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
+}
+
+QtBrowserItem *QtTreePropertyBrowserPrivate::currentItem() const
+{
+ if (QTreeWidgetItem *treeItem = m_treeWidget->currentItem())
+ return m_itemToIndex.value(treeItem);
+ return 0;
+}
+
+void QtTreePropertyBrowserPrivate::setCurrentItem(QtBrowserItem *browserItem, bool block)
+{
+ const bool blocked = block ? m_treeWidget->blockSignals(true) : false;
+ if (browserItem == 0)
+ m_treeWidget->setCurrentItem(0);
+ else
+ m_treeWidget->setCurrentItem(m_indexToItem.value(browserItem));
+ if (block)
+ m_treeWidget->blockSignals(blocked);
+}
+
+QtProperty *QtTreePropertyBrowserPrivate::indexToProperty(const QModelIndex &index) const
+{
+ QTreeWidgetItem *item = m_treeWidget->indexToItem(index);
+ QtBrowserItem *idx = m_itemToIndex.value(item);
+ if (idx)
+ return idx->property();
+ return 0;
+}
+
+QtBrowserItem *QtTreePropertyBrowserPrivate::indexToBrowserItem(const QModelIndex &index) const
+{
+ QTreeWidgetItem *item = m_treeWidget->indexToItem(index);
+ return m_itemToIndex.value(item);
+}
+
+QTreeWidgetItem *QtTreePropertyBrowserPrivate::indexToItem(const QModelIndex &index) const
+{
+ return m_treeWidget->indexToItem(index);
+}
+
+bool QtTreePropertyBrowserPrivate::lastColumn(int column) const
+{
+ return m_treeWidget->header()->visualIndex(column) == m_treeWidget->columnCount() - 1;
+}
+
+void QtTreePropertyBrowserPrivate::disableItem(QTreeWidgetItem *item) const
+{
+ Qt::ItemFlags flags = item->flags();
+ if (flags & Qt::ItemIsEnabled) {
+ flags &= ~Qt::ItemIsEnabled;
+ item->setFlags(flags);
+ m_delegate->closeEditor(m_itemToIndex[item]->property());
+ const int childCount = item->childCount();
+ for (int i = 0; i < childCount; i++) {
+ QTreeWidgetItem *child = item->child(i);
+ disableItem(child);
+ }
+ }
+}
+
+void QtTreePropertyBrowserPrivate::enableItem(QTreeWidgetItem *item) const
+{
+ Qt::ItemFlags flags = item->flags();
+ flags |= Qt::ItemIsEnabled;
+ item->setFlags(flags);
+ const int childCount = item->childCount();
+ for (int i = 0; i < childCount; i++) {
+ QTreeWidgetItem *child = item->child(i);
+ QtProperty *property = m_itemToIndex[child]->property();
+ if (property->isEnabled()) {
+ enableItem(child);
+ }
+ }
+}
+
+bool QtTreePropertyBrowserPrivate::hasValue(QTreeWidgetItem *item) const
+{
+ QtBrowserItem *browserItem = m_itemToIndex.value(item);
+ if (browserItem)
+ return browserItem->property()->hasValue();
+ return false;
+}
+
+void QtTreePropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex)
+{
+ QTreeWidgetItem *afterItem = m_indexToItem.value(afterIndex);
+ QTreeWidgetItem *parentItem = m_indexToItem.value(index->parent());
+
+ QTreeWidgetItem *newItem = 0;
+ if (parentItem) {
+ newItem = new QTreeWidgetItem(parentItem, afterItem);
+ } else {
+ newItem = new QTreeWidgetItem(m_treeWidget, afterItem);
+ }
+ m_itemToIndex[newItem] = index;
+ m_indexToItem[index] = newItem;
+
+ newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+ m_treeWidget->setItemExpanded(newItem, true);
+
+ updateItem(newItem);
+}
+
+void QtTreePropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index)
+{
+ QTreeWidgetItem *item = m_indexToItem.value(index);
+
+ if (m_treeWidget->currentItem() == item) {
+ m_treeWidget->setCurrentItem(0);
+ }
+
+ delete item;
+
+ m_indexToItem.remove(index);
+ m_itemToIndex.remove(item);
+ m_indexToBackgroundColor.remove(index);
+}
+
+void QtTreePropertyBrowserPrivate::propertyChanged(QtBrowserItem *index)
+{
+ QTreeWidgetItem *item = m_indexToItem.value(index);
+
+ updateItem(item);
+}
+
+void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item)
+{
+ QtProperty *property = m_itemToIndex[item]->property();
+ QIcon expandIcon;
+ if (property->hasValue()) {
+ QString toolTip = property->toolTip();
+ if (toolTip.isEmpty())
+ toolTip = property->valueText();
+ item->setToolTip(1, toolTip);
+ item->setIcon(1, property->valueIcon());
+ item->setText(1, property->valueText());
+ } else if (markPropertiesWithoutValue() && !m_treeWidget->rootIsDecorated()) {
+ expandIcon = m_expandIcon;
+ }
+ item->setIcon(0, expandIcon);
+ item->setFirstColumnSpanned(!property->hasValue());
+ item->setToolTip(0, property->propertyName());
+ item->setStatusTip(0, property->statusTip());
+ item->setWhatsThis(0, property->whatsThis());
+ item->setText(0, property->propertyName());
+ bool wasEnabled = item->flags() & Qt::ItemIsEnabled;
+ bool isEnabled = wasEnabled;
+ if (property->isEnabled()) {
+ QTreeWidgetItem *parent = item->parent();
+ if (!parent || (parent->flags() & Qt::ItemIsEnabled))
+ isEnabled = true;
+ else
+ isEnabled = false;
+ } else {
+ isEnabled = false;
+ }
+ if (wasEnabled != isEnabled) {
+ if (isEnabled)
+ enableItem(item);
+ else
+ disableItem(item);
+ }
+ m_treeWidget->viewport()->update();
+}
+
+QColor QtTreePropertyBrowserPrivate::calculatedBackgroundColor(QtBrowserItem *item) const
+{
+ QtBrowserItem *i = item;
+ const QMap<QtBrowserItem *, QColor>::const_iterator itEnd = m_indexToBackgroundColor.constEnd();
+ while (i) {
+ QMap<QtBrowserItem *, QColor>::const_iterator it = m_indexToBackgroundColor.constFind(i);
+ if (it != itEnd)
+ return it.value();
+ i = i->parent();
+ }
+ return QColor();
+}
+
+void QtTreePropertyBrowserPrivate::slotCollapsed(const QModelIndex &index)
+{
+ QTreeWidgetItem *item = indexToItem(index);
+ QtBrowserItem *idx = m_itemToIndex.value(item);
+ if (item)
+ emit q_ptr->collapsed(idx);
+}
+
+void QtTreePropertyBrowserPrivate::slotExpanded(const QModelIndex &index)
+{
+ QTreeWidgetItem *item = indexToItem(index);
+ QtBrowserItem *idx = m_itemToIndex.value(item);
+ if (item)
+ emit q_ptr->expanded(idx);
+}
+
+void QtTreePropertyBrowserPrivate::slotCurrentBrowserItemChanged(QtBrowserItem *item)
+{
+ if (!m_browserChangedBlocked && item != currentItem())
+ setCurrentItem(item, true);
+}
+
+void QtTreePropertyBrowserPrivate::slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *)
+{
+ QtBrowserItem *browserItem = newItem ? m_itemToIndex.value(newItem) : 0;
+ m_browserChangedBlocked = true;
+ q_ptr->setCurrentItem(browserItem);
+ m_browserChangedBlocked = false;
+}
+
+QTreeWidgetItem *QtTreePropertyBrowserPrivate::editedItem() const
+{
+ return m_delegate->editedItem();
+}
+
+void QtTreePropertyBrowserPrivate::editItem(QtBrowserItem *browserItem)
+{
+ if (QTreeWidgetItem *treeItem = m_indexToItem.value(browserItem, 0)) {
+ m_treeWidget->setCurrentItem (treeItem, 1);
+ m_treeWidget->editItem(treeItem, 1);
+ }
+}
+
+/*!
+ \class QtTreePropertyBrowser
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtTreePropertyBrowser class provides QTreeWidget based
+ property browser.
+
+ A property browser is a widget that enables the user to edit a
+ given set of properties. Each property is represented by a label
+ specifying the property's name, and an editing widget (e.g. a line
+ edit or a combobox) holding its value. A property can have zero or
+ more subproperties.
+
+ QtTreePropertyBrowser provides a tree based view for all nested
+ properties, i.e. properties that have subproperties can be in an
+ expanded (subproperties are visible) or collapsed (subproperties
+ are hidden) state. For example:
+
+ \image qttreepropertybrowser.png
+
+ Use the QtAbstractPropertyBrowser API to add, insert and remove
+ properties from an instance of the QtTreePropertyBrowser class.
+ The properties themselves are created and managed by
+ implementations of the QtAbstractPropertyManager class.
+
+ \sa QtGroupBoxPropertyBrowser, QtAbstractPropertyBrowser
+*/
+
+/*!
+ \fn void QtTreePropertyBrowser::collapsed(QtBrowserItem *item)
+
+ This signal is emitted when the \a item is collapsed.
+
+ \sa expanded(), setExpanded()
+*/
+
+/*!
+ \fn void QtTreePropertyBrowser::expanded(QtBrowserItem *item)
+
+ This signal is emitted when the \a item is expanded.
+
+ \sa collapsed(), setExpanded()
+*/
+
+/*!
+ Creates a property browser with the given \a parent.
+*/
+QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent)
+ : QtAbstractPropertyBrowser(parent)
+{
+ d_ptr = new QtTreePropertyBrowserPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->init(this);
+ connect(this, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem*)));
+}
+
+/*!
+ Destroys this property browser.
+
+ Note that the properties that were inserted into this browser are
+ \e not destroyed since they may still be used in other
+ browsers. The properties are owned by the manager that created
+ them.
+
+ \sa QtProperty, QtAbstractPropertyManager
+*/
+QtTreePropertyBrowser::~QtTreePropertyBrowser()
+{
+ delete d_ptr;
+}
+
+/*!
+ \property QtTreePropertyBrowser::indentation
+ \brief indentation of the items in the tree view.
+*/
+int QtTreePropertyBrowser::indentation() const
+{
+ return d_ptr->m_treeWidget->indentation();
+}
+
+void QtTreePropertyBrowser::setIndentation(int i)
+{
+ d_ptr->m_treeWidget->setIndentation(i);
+}
+
+/*!
+ \property QtTreePropertyBrowser::rootIsDecorated
+ \brief whether to show controls for expanding and collapsing root items.
+*/
+bool QtTreePropertyBrowser::rootIsDecorated() const
+{
+ return d_ptr->m_treeWidget->rootIsDecorated();
+}
+
+void QtTreePropertyBrowser::setRootIsDecorated(bool show)
+{
+ d_ptr->m_treeWidget->setRootIsDecorated(show);
+ QMapIterator<QTreeWidgetItem *, QtBrowserItem *> it(d_ptr->m_itemToIndex);
+ while (it.hasNext()) {
+ QtProperty *property = it.next().value()->property();
+ if (!property->hasValue())
+ d_ptr->updateItem(it.key());
+ }
+}
+
+/*!
+ \property QtTreePropertyBrowser::alternatingRowColors
+ \brief whether to draw the background using alternating colors.
+ By default this property is set to true.
+*/
+bool QtTreePropertyBrowser::alternatingRowColors() const
+{
+ return d_ptr->m_treeWidget->alternatingRowColors();
+}
+
+void QtTreePropertyBrowser::setAlternatingRowColors(bool enable)
+{
+ d_ptr->m_treeWidget->setAlternatingRowColors(enable);
+ QMapIterator<QTreeWidgetItem *, QtBrowserItem *> it(d_ptr->m_itemToIndex);
+}
+
+/*!
+ \property QtTreePropertyBrowser::headerVisible
+ \brief whether to show the header.
+*/
+bool QtTreePropertyBrowser::isHeaderVisible() const
+{
+ return d_ptr->m_headerVisible;
+}
+
+void QtTreePropertyBrowser::setHeaderVisible(bool visible)
+{
+ if (d_ptr->m_headerVisible == visible)
+ return;
+
+ d_ptr->m_headerVisible = visible;
+ d_ptr->m_treeWidget->header()->setVisible(visible);
+}
+
+/*!
+ \enum QtTreePropertyBrowser::ResizeMode
+
+ The resize mode specifies the behavior of the header sections.
+
+ \value Interactive The user can resize the sections.
+ The sections can also be resized programmatically using setSplitterPosition().
+
+ \value Fixed The user cannot resize the section.
+ The section can only be resized programmatically using setSplitterPosition().
+
+ \value Stretch QHeaderView will automatically resize the section to fill the available space.
+ The size cannot be changed by the user or programmatically.
+
+ \value ResizeToContents QHeaderView will automatically resize the section to its optimal
+ size based on the contents of the entire column.
+ The size cannot be changed by the user or programmatically.
+
+ \sa setResizeMode()
+*/
+
+/*!
+ \property QtTreePropertyBrowser::resizeMode
+ \brief the resize mode of setions in the header.
+*/
+
+QtTreePropertyBrowser::ResizeMode QtTreePropertyBrowser::resizeMode() const
+{
+ return d_ptr->m_resizeMode;
+}
+
+void QtTreePropertyBrowser::setResizeMode(QtTreePropertyBrowser::ResizeMode mode)
+{
+ if (d_ptr->m_resizeMode == mode)
+ return;
+
+ d_ptr->m_resizeMode = mode;
+ QHeaderView::ResizeMode m = QHeaderView::Stretch;
+ switch (mode) {
+ case QtTreePropertyBrowser::Interactive: m = QHeaderView::Interactive; break;
+ case QtTreePropertyBrowser::Fixed: m = QHeaderView::Fixed; break;
+ case QtTreePropertyBrowser::ResizeToContents: m = QHeaderView::ResizeToContents; break;
+ case QtTreePropertyBrowser::Stretch:
+ default: m = QHeaderView::Stretch; break;
+ }
+ d_ptr->m_treeWidget->header()->setResizeMode(m);
+}
+
+/*!
+ \property QtTreePropertyBrowser::splitterPosition
+ \brief the position of the splitter between the colunms.
+*/
+
+int QtTreePropertyBrowser::splitterPosition() const
+{
+ return d_ptr->m_treeWidget->header()->sectionSize(0);
+}
+
+void QtTreePropertyBrowser::setSplitterPosition(int position)
+{
+ d_ptr->m_treeWidget->header()->resizeSection(0, position);
+}
+
+/*!
+ Sets the \a item to either collapse or expanded, depending on the value of \a expanded.
+
+ \sa isExpanded(), expanded(), collapsed()
+*/
+
+void QtTreePropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded)
+{
+ QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item);
+ if (treeItem)
+ treeItem->setExpanded(expanded);
+}
+
+/*!
+ Returns true if the \a item is expanded; otherwise returns false.
+
+ \sa setExpanded()
+*/
+
+bool QtTreePropertyBrowser::isExpanded(QtBrowserItem *item) const
+{
+ QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item);
+ if (treeItem)
+ return treeItem->isExpanded();
+ return false;
+}
+
+/*!
+ Returns true if the \a item is visible; otherwise returns false.
+
+ \sa setItemVisible()
+ \since 4.5
+*/
+
+bool QtTreePropertyBrowser::isItemVisible(QtBrowserItem *item) const
+{
+ if (const QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item))
+ return !treeItem->isHidden();
+ return false;
+}
+
+/*!
+ Sets the \a item to be visible, depending on the value of \a visible.
+
+ \sa isItemVisible()
+ \since 4.5
+*/
+
+void QtTreePropertyBrowser::setItemVisible(QtBrowserItem *item, bool visible)
+{
+ if (QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item))
+ treeItem->setHidden(!visible);
+}
+
+/*!
+ Sets the \a item's background color to \a color. Note that while item's background
+ is rendered every second row is being drawn with alternate color (which is a bit lighter than items \a color)
+
+ \sa backgroundColor(), calculatedBackgroundColor()
+*/
+
+void QtTreePropertyBrowser::setBackgroundColor(QtBrowserItem *item, const QColor &color)
+{
+ if (!d_ptr->m_indexToItem.contains(item))
+ return;
+ if (color.isValid())
+ d_ptr->m_indexToBackgroundColor[item] = color;
+ else
+ d_ptr->m_indexToBackgroundColor.remove(item);
+ d_ptr->m_treeWidget->viewport()->update();
+}
+
+/*!
+ Returns the \a item's color. If there is no color set for item it returns invalid color.
+
+ \sa calculatedBackgroundColor(), setBackgroundColor()
+*/
+
+QColor QtTreePropertyBrowser::backgroundColor(QtBrowserItem *item) const
+{
+ return d_ptr->m_indexToBackgroundColor.value(item);
+}
+
+/*!
+ Returns the \a item's color. If there is no color set for item it returns parent \a item's
+ color (if there is no color set for parent it returns grandparent's color and so on). In case
+ the color is not set for \a item and it's top level item it returns invalid color.
+
+ \sa backgroundColor(), setBackgroundColor()
+*/
+
+QColor QtTreePropertyBrowser::calculatedBackgroundColor(QtBrowserItem *item) const
+{
+ return d_ptr->calculatedBackgroundColor(item);
+}
+
+/*!
+ \property QtTreePropertyBrowser::propertiesWithoutValueMarked
+ \brief whether to enable or disable marking properties without value.
+
+ When marking is enabled the item's background is rendered in dark color and item's
+ foreground is rendered with light color.
+
+ \sa propertiesWithoutValueMarked()
+*/
+void QtTreePropertyBrowser::setPropertiesWithoutValueMarked(bool mark)
+{
+ if (d_ptr->m_markPropertiesWithoutValue == mark)
+ return;
+
+ d_ptr->m_markPropertiesWithoutValue = mark;
+ QMapIterator<QTreeWidgetItem *, QtBrowserItem *> it(d_ptr->m_itemToIndex);
+ while (it.hasNext()) {
+ QtProperty *property = it.next().value()->property();
+ if (!property->hasValue())
+ d_ptr->updateItem(it.key());
+ }
+ d_ptr->m_treeWidget->viewport()->update();
+}
+
+bool QtTreePropertyBrowser::propertiesWithoutValueMarked() const
+{
+ return d_ptr->m_markPropertiesWithoutValue;
+}
+
+/*!
+ \reimp
+*/
+void QtTreePropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem)
+{
+ d_ptr->propertyInserted(item, afterItem);
+}
+
+/*!
+ \reimp
+*/
+void QtTreePropertyBrowser::itemRemoved(QtBrowserItem *item)
+{
+ d_ptr->propertyRemoved(item);
+}
+
+/*!
+ \reimp
+*/
+void QtTreePropertyBrowser::itemChanged(QtBrowserItem *item)
+{
+ d_ptr->propertyChanged(item);
+}
+
+/*!
+ Sets the current item to \a item and opens the relevant editor for it.
+*/
+void QtTreePropertyBrowser::editItem(QtBrowserItem *item)
+{
+ d_ptr->editItem(item);
+}
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#include "moc_qttreepropertybrowser.cpp"
+#include "qttreepropertybrowser.moc"
diff --git a/tools/shared/qtpropertybrowser/qttreepropertybrowser.h b/tools/shared/qtpropertybrowser/qttreepropertybrowser.h
new file mode 100644
index 0000000000..63bd7f621b
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qttreepropertybrowser.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTTREEPROPERTYBROWSER_H
+#define QTTREEPROPERTYBROWSER_H
+
+#include "qtpropertybrowser.h"
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QTreeWidgetItem;
+class QtTreePropertyBrowserPrivate;
+
+class QtTreePropertyBrowser : public QtAbstractPropertyBrowser
+{
+ Q_OBJECT
+ Q_ENUMS(ResizeMode)
+ Q_PROPERTY(int indentation READ indentation WRITE setIndentation)
+ Q_PROPERTY(bool rootIsDecorated READ rootIsDecorated WRITE setRootIsDecorated)
+ Q_PROPERTY(bool alternatingRowColors READ alternatingRowColors WRITE setAlternatingRowColors)
+ Q_PROPERTY(bool headerVisible READ isHeaderVisible WRITE setHeaderVisible)
+ Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode)
+ Q_PROPERTY(int splitterPosition READ splitterPosition WRITE setSplitterPosition)
+ Q_PROPERTY(bool propertiesWithoutValueMarked READ propertiesWithoutValueMarked WRITE setPropertiesWithoutValueMarked)
+public:
+
+ enum ResizeMode
+ {
+ Interactive,
+ Stretch,
+ Fixed,
+ ResizeToContents
+ };
+
+ QtTreePropertyBrowser(QWidget *parent = 0);
+ ~QtTreePropertyBrowser();
+
+ int indentation() const;
+ void setIndentation(int i);
+
+ bool rootIsDecorated() const;
+ void setRootIsDecorated(bool show);
+
+ bool alternatingRowColors() const;
+ void setAlternatingRowColors(bool enable);
+
+ bool isHeaderVisible() const;
+ void setHeaderVisible(bool visible);
+
+ ResizeMode resizeMode() const;
+ void setResizeMode(ResizeMode mode);
+
+ int splitterPosition() const;
+ void setSplitterPosition(int position);
+
+ void setExpanded(QtBrowserItem *item, bool expanded);
+ bool isExpanded(QtBrowserItem *item) const;
+
+ bool isItemVisible(QtBrowserItem *item) const;
+ void setItemVisible(QtBrowserItem *item, bool visible);
+
+ void setBackgroundColor(QtBrowserItem *item, const QColor &color);
+ QColor backgroundColor(QtBrowserItem *item) const;
+ QColor calculatedBackgroundColor(QtBrowserItem *item) const;
+
+ void setPropertiesWithoutValueMarked(bool mark);
+ bool propertiesWithoutValueMarked() const;
+
+ void editItem(QtBrowserItem *item);
+
+Q_SIGNALS:
+
+ void collapsed(QtBrowserItem *item);
+ void expanded(QtBrowserItem *item);
+
+protected:
+ virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem);
+ virtual void itemRemoved(QtBrowserItem *item);
+ virtual void itemChanged(QtBrowserItem *item);
+
+private:
+
+ QtTreePropertyBrowserPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtTreePropertyBrowser)
+ Q_DISABLE_COPY(QtTreePropertyBrowser)
+
+ Q_PRIVATE_SLOT(d_func(), void slotCollapsed(const QModelIndex &))
+ Q_PRIVATE_SLOT(d_func(), void slotExpanded(const QModelIndex &))
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentBrowserItemChanged(QtBrowserItem *))
+ Q_PRIVATE_SLOT(d_func(), void slotCurrentTreeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *))
+
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#endif
diff --git a/tools/shared/qtpropertybrowser/qtvariantproperty.cpp b/tools/shared/qtpropertybrowser/qtvariantproperty.cpp
new file mode 100644
index 0000000000..7e1975e08a
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtvariantproperty.cpp
@@ -0,0 +1,2282 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtvariantproperty.h"
+#include "qtpropertymanager.h"
+#include "qteditorfactory.h"
+#include <QtCore/QVariant>
+#include <QtGui/QIcon>
+#include <QtCore/QDate>
+#include <QtCore/QLocale>
+
+#if defined(Q_CC_MSVC)
+# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */
+#endif
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+class QtEnumPropertyType
+{
+};
+
+
+class QtFlagPropertyType
+{
+};
+
+
+class QtGroupPropertyType
+{
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+Q_DECLARE_METATYPE(QtEnumPropertyType)
+Q_DECLARE_METATYPE(QtFlagPropertyType)
+Q_DECLARE_METATYPE(QtGroupPropertyType)
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+/*!
+ Returns the type id for an enum property.
+
+ Note that the property's value type can be retrieved using the
+ valueType() function (which is QVariant::Int for the enum property
+ type).
+
+ \sa propertyType(), valueType()
+*/
+int QtVariantPropertyManager::enumTypeId()
+{
+ return qMetaTypeId<QtEnumPropertyType>();
+}
+
+/*!
+ Returns the type id for a flag property.
+
+ Note that the property's value type can be retrieved using the
+ valueType() function (which is QVariant::Int for the flag property
+ type).
+
+ \sa propertyType(), valueType()
+*/
+int QtVariantPropertyManager::flagTypeId()
+{
+ return qMetaTypeId<QtFlagPropertyType>();
+}
+
+/*!
+ Returns the type id for a group property.
+
+ Note that the property's value type can be retrieved using the
+ valueType() function (which is QVariant::Invalid for the group
+ property type, since it doesn't provide any value).
+
+ \sa propertyType(), valueType()
+*/
+int QtVariantPropertyManager::groupTypeId()
+{
+ return qMetaTypeId<QtGroupPropertyType>();
+}
+
+/*!
+ Returns the type id for a icon map attribute.
+
+ Note that the property's attribute type can be retrieved using the
+ attributeType() function.
+
+ \sa attributeType(), QtEnumPropertyManager::enumIcons()
+*/
+int QtVariantPropertyManager::iconMapTypeId()
+{
+ return qMetaTypeId<QtIconMap>();
+}
+
+typedef QMap<const QtProperty *, QtProperty *> PropertyMap;
+Q_GLOBAL_STATIC(PropertyMap, propertyToWrappedProperty)
+
+static QtProperty *wrappedProperty(QtProperty *property)
+{
+ return propertyToWrappedProperty()->value(property, 0);
+}
+
+class QtVariantPropertyPrivate
+{
+ QtVariantProperty *q_ptr;
+public:
+ QtVariantPropertyPrivate(QtVariantPropertyManager *m) : manager(m) {}
+
+ QtVariantPropertyManager *manager;
+};
+
+/*!
+ \class QtVariantProperty
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtVariantProperty class is a convenience class handling
+ QVariant based properties.
+
+ QtVariantProperty provides additional API: A property's type,
+ value type, attribute values and current value can easily be
+ retrieved using the propertyType(), valueType(), attributeValue()
+ and value() functions respectively. In addition, the attribute
+ values and the current value can be set using the corresponding
+ setValue() and setAttribute() functions.
+
+ For example, instead of writing:
+
+ \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtvariantproperty.cpp 0
+
+ you can write:
+
+ \snippet doc/src/snippets/code/tools_shared_qtpropertybrowser_qtvariantproperty.cpp 1
+
+ QtVariantProperty instances can only be created by the
+ QtVariantPropertyManager class.
+
+ \sa QtProperty, QtVariantPropertyManager, QtVariantEditorFactory
+*/
+
+/*!
+ Creates a variant property using the given \a manager.
+
+ Do not use this constructor to create variant property instances;
+ use the QtVariantPropertyManager::addProperty() function
+ instead. This constructor is used internally by the
+ QtVariantPropertyManager::createProperty() function.
+
+ \sa QtVariantPropertyManager
+*/
+QtVariantProperty::QtVariantProperty(QtVariantPropertyManager *manager)
+ : QtProperty(manager), d_ptr(new QtVariantPropertyPrivate(manager))
+{
+
+}
+
+/*!
+ Destroys this property.
+
+ \sa QtProperty::~QtProperty()
+*/
+QtVariantProperty::~QtVariantProperty()
+{
+ delete d_ptr;
+}
+
+/*!
+ Returns the property's current value.
+
+ \sa valueType(), setValue()
+*/
+QVariant QtVariantProperty::value() const
+{
+ return d_ptr->manager->value(this);
+}
+
+/*!
+ Returns this property's value for the specified \a attribute.
+
+ QtVariantPropertyManager provides a couple of related functions:
+ \l{QtVariantPropertyManager::attributes()}{attributes()} and
+ \l{QtVariantPropertyManager::attributeType()}{attributeType()}.
+
+ \sa setAttribute()
+*/
+QVariant QtVariantProperty::attributeValue(const QString &attribute) const
+{
+ return d_ptr->manager->attributeValue(this, attribute);
+}
+
+/*!
+ Returns the type of this property's value.
+
+ \sa propertyType()
+*/
+int QtVariantProperty::valueType() const
+{
+ return d_ptr->manager->valueType(this);
+}
+
+/*!
+ Returns this property's type.
+
+ QtVariantPropertyManager provides several related functions:
+ \l{QtVariantPropertyManager::enumTypeId()}{enumTypeId()},
+ \l{QtVariantPropertyManager::flagTypeId()}{flagTypeId()} and
+ \l{QtVariantPropertyManager::groupTypeId()}{groupTypeId()}.
+
+ \sa valueType()
+*/
+int QtVariantProperty::propertyType() const
+{
+ return d_ptr->manager->propertyType(this);
+}
+
+/*!
+ Sets the value of this property to \a value.
+
+ The specified \a value must be of the type returned by
+ valueType(), or of a type that can be converted to valueType()
+ using the QVariant::canConvert() function; otherwise this function
+ does nothing.
+
+ \sa value()
+*/
+void QtVariantProperty::setValue(const QVariant &value)
+{
+ d_ptr->manager->setValue(this, value);
+}
+
+/*!
+ Sets the \a attribute of property to \a value.
+
+ QtVariantPropertyManager provides the related
+ \l{QtVariantPropertyManager::setAttribute()}{setAttribute()}
+ function.
+
+ \sa attributeValue()
+*/
+void QtVariantProperty::setAttribute(const QString &attribute, const QVariant &value)
+{
+ d_ptr->manager->setAttribute(this, attribute, value);
+}
+
+class QtVariantPropertyManagerPrivate
+{
+ QtVariantPropertyManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtVariantPropertyManager)
+public:
+ QtVariantPropertyManagerPrivate();
+
+ bool m_creatingProperty;
+ bool m_creatingSubProperties;
+ bool m_destroyingSubProperties;
+ int m_propertyType;
+
+ void slotValueChanged(QtProperty *property, int val);
+ void slotRangeChanged(QtProperty *property, int min, int max);
+ void slotSingleStepChanged(QtProperty *property, int step);
+ void slotValueChanged(QtProperty *property, double val);
+ void slotRangeChanged(QtProperty *property, double min, double max);
+ void slotSingleStepChanged(QtProperty *property, double step);
+ void slotDecimalsChanged(QtProperty *property, int prec);
+ void slotValueChanged(QtProperty *property, bool val);
+ void slotValueChanged(QtProperty *property, const QString &val);
+ void slotRegExpChanged(QtProperty *property, const QRegExp &regExp);
+ void slotValueChanged(QtProperty *property, const QDate &val);
+ void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max);
+ void slotValueChanged(QtProperty *property, const QTime &val);
+ void slotValueChanged(QtProperty *property, const QDateTime &val);
+ void slotValueChanged(QtProperty *property, const QKeySequence &val);
+ void slotValueChanged(QtProperty *property, const QChar &val);
+ void slotValueChanged(QtProperty *property, const QLocale &val);
+ void slotValueChanged(QtProperty *property, const QPoint &val);
+ void slotValueChanged(QtProperty *property, const QPointF &val);
+ void slotValueChanged(QtProperty *property, const QSize &val);
+ void slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max);
+ void slotValueChanged(QtProperty *property, const QSizeF &val);
+ void slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max);
+ void slotValueChanged(QtProperty *property, const QRect &val);
+ void slotConstraintChanged(QtProperty *property, const QRect &val);
+ void slotValueChanged(QtProperty *property, const QRectF &val);
+ void slotConstraintChanged(QtProperty *property, const QRectF &val);
+ void slotValueChanged(QtProperty *property, const QColor &val);
+ void slotEnumChanged(QtProperty *property, int val);
+ void slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames);
+ void slotEnumIconsChanged(QtProperty *property, const QMap<int, QIcon> &enumIcons);
+ void slotValueChanged(QtProperty *property, const QSizePolicy &val);
+ void slotValueChanged(QtProperty *property, const QFont &val);
+ void slotValueChanged(QtProperty *property, const QCursor &val);
+ void slotFlagChanged(QtProperty *property, int val);
+ void slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames);
+ void slotPropertyInserted(QtProperty *property, QtProperty *parent, QtProperty *after);
+ void slotPropertyRemoved(QtProperty *property, QtProperty *parent);
+
+ void valueChanged(QtProperty *property, const QVariant &val);
+
+ int internalPropertyToType(QtProperty *property) const;
+ QtVariantProperty *createSubProperty(QtVariantProperty *parent, QtVariantProperty *after,
+ QtProperty *internal);
+ void removeSubProperty(QtVariantProperty *property);
+
+ QMap<int, QtAbstractPropertyManager *> m_typeToPropertyManager;
+ QMap<int, QMap<QString, int> > m_typeToAttributeToAttributeType;
+
+ QMap<const QtProperty *, QPair<QtVariantProperty *, int> > m_propertyToType;
+
+ QMap<int, int> m_typeToValueType;
+
+
+ QMap<QtProperty *, QtVariantProperty *> m_internalToProperty;
+
+ const QString m_constraintAttribute;
+ const QString m_singleStepAttribute;
+ const QString m_decimalsAttribute;
+ const QString m_enumIconsAttribute;
+ const QString m_enumNamesAttribute;
+ const QString m_flagNamesAttribute;
+ const QString m_maximumAttribute;
+ const QString m_minimumAttribute;
+ const QString m_regExpAttribute;
+};
+
+QtVariantPropertyManagerPrivate::QtVariantPropertyManagerPrivate() :
+ m_constraintAttribute(QLatin1String("constraint")),
+ m_singleStepAttribute(QLatin1String("singleStep")),
+ m_decimalsAttribute(QLatin1String("decimals")),
+ m_enumIconsAttribute(QLatin1String("enumIcons")),
+ m_enumNamesAttribute(QLatin1String("enumNames")),
+ m_flagNamesAttribute(QLatin1String("flagNames")),
+ m_maximumAttribute(QLatin1String("maximum")),
+ m_minimumAttribute(QLatin1String("minimum")),
+ m_regExpAttribute(QLatin1String("regExp"))
+{
+}
+
+int QtVariantPropertyManagerPrivate::internalPropertyToType(QtProperty *property) const
+{
+ int type = 0;
+ QtAbstractPropertyManager *internPropertyManager = property->propertyManager();
+ if (qobject_cast<QtIntPropertyManager *>(internPropertyManager))
+ type = QVariant::Int;
+ else if (qobject_cast<QtEnumPropertyManager *>(internPropertyManager))
+ type = QtVariantPropertyManager::enumTypeId();
+ else if (qobject_cast<QtBoolPropertyManager *>(internPropertyManager))
+ type = QVariant::Bool;
+ else if (qobject_cast<QtDoublePropertyManager *>(internPropertyManager))
+ type = QVariant::Double;
+ return type;
+}
+
+QtVariantProperty *QtVariantPropertyManagerPrivate::createSubProperty(QtVariantProperty *parent,
+ QtVariantProperty *after, QtProperty *internal)
+{
+ int type = internalPropertyToType(internal);
+ if (!type)
+ return 0;
+
+ bool wasCreatingSubProperties = m_creatingSubProperties;
+ m_creatingSubProperties = true;
+
+ QtVariantProperty *varChild = q_ptr->addProperty(type, internal->propertyName());
+
+ m_creatingSubProperties = wasCreatingSubProperties;
+
+ varChild->setPropertyName(internal->propertyName());
+ varChild->setToolTip(internal->toolTip());
+ varChild->setStatusTip(internal->statusTip());
+ varChild->setWhatsThis(internal->whatsThis());
+
+ parent->insertSubProperty(varChild, after);
+
+ m_internalToProperty[internal] = varChild;
+ propertyToWrappedProperty()->insert(varChild, internal);
+ return varChild;
+}
+
+void QtVariantPropertyManagerPrivate::removeSubProperty(QtVariantProperty *property)
+{
+ QtProperty *internChild = wrappedProperty(property);
+ bool wasDestroyingSubProperties = m_destroyingSubProperties;
+ m_destroyingSubProperties = true;
+ delete property;
+ m_destroyingSubProperties = wasDestroyingSubProperties;
+ m_internalToProperty.remove(internChild);
+ propertyToWrappedProperty()->remove(property);
+}
+
+void QtVariantPropertyManagerPrivate::slotPropertyInserted(QtProperty *property,
+ QtProperty *parent, QtProperty *after)
+{
+ if (m_creatingProperty)
+ return;
+
+ QtVariantProperty *varParent = m_internalToProperty.value(parent, 0);
+ if (!varParent)
+ return;
+
+ QtVariantProperty *varAfter = 0;
+ if (after) {
+ varAfter = m_internalToProperty.value(after, 0);
+ if (!varAfter)
+ return;
+ }
+
+ createSubProperty(varParent, varAfter, property);
+}
+
+void QtVariantPropertyManagerPrivate::slotPropertyRemoved(QtProperty *property, QtProperty *parent)
+{
+ Q_UNUSED(parent)
+
+ QtVariantProperty *varProperty = m_internalToProperty.value(property, 0);
+ if (!varProperty)
+ return;
+
+ removeSubProperty(varProperty);
+}
+
+void QtVariantPropertyManagerPrivate::valueChanged(QtProperty *property, const QVariant &val)
+{
+ QtVariantProperty *varProp = m_internalToProperty.value(property, 0);
+ if (!varProp)
+ return;
+ emit q_ptr->valueChanged(varProp, val);
+ emit q_ptr->propertyChanged(varProp);
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, int val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, int min, int max)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
+ emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min));
+ emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max));
+ }
+}
+
+void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, int step)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, double val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, double min, double max)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
+ emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min));
+ emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max));
+ }
+}
+
+void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, double step)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step));
+}
+
+void QtVariantPropertyManagerPrivate::slotDecimalsChanged(QtProperty *property, int prec)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_decimalsAttribute, QVariant(prec));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, bool val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QString &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotRegExpChanged(QtProperty *property, const QRegExp &regExp)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_regExpAttribute, QVariant(regExp));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDate &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
+ emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min));
+ emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max));
+ }
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QTime &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDateTime &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val)
+{
+ QVariant v;
+ qVariantSetValue(v, val);
+ valueChanged(property, v);
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QChar &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QLocale &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPoint &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPointF &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSize &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
+ emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min));
+ emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max));
+ }
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizeF &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
+ emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min));
+ emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max));
+ }
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRect &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRect &constraint)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRectF &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRectF &constraint)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QColor &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_enumNamesAttribute, QVariant(enumNames));
+}
+
+void QtVariantPropertyManagerPrivate::slotEnumIconsChanged(QtProperty *property, const QMap<int, QIcon> &enumIcons)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
+ QVariant v;
+ qVariantSetValue(v, enumIcons);
+ emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, v);
+ }
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizePolicy &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QFont &val)
+{
+ valueChanged(property, QVariant(val));
+}
+
+void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QCursor &val)
+{
+#ifndef QT_NO_CURSOR
+ valueChanged(property, QVariant(val));
+#endif
+}
+
+void QtVariantPropertyManagerPrivate::slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames)
+{
+ if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0))
+ emit q_ptr->attributeChanged(varProp, m_flagNamesAttribute, QVariant(flagNames));
+}
+
+/*!
+ \class QtVariantPropertyManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtVariantPropertyManager class provides and manages QVariant based properties.
+
+ QtVariantPropertyManager provides the addProperty() function which
+ creates QtVariantProperty objects. The QtVariantProperty class is
+ a convenience class handling QVariant based properties inheriting
+ QtProperty. A QtProperty object created by a
+ QtVariantPropertyManager instance can be converted into a
+ QtVariantProperty object using the variantProperty() function.
+
+ The property's value can be retrieved using the value(), and set
+ using the setValue() slot. In addition the property's type, and
+ the type of its value, can be retrieved using the propertyType()
+ and valueType() functions respectively.
+
+ A property's type is a QVariant::Type enumerator value, and
+ usually a property's type is the same as its value type. But for
+ some properties the types differ, for example for enums, flags and
+ group types in which case QtVariantPropertyManager provides the
+ enumTypeId(), flagTypeId() and groupTypeId() functions,
+ respectively, to identify their property type (the value types are
+ QVariant::Int for the enum and flag types, and QVariant::Invalid
+ for the group type).
+
+ Use the isPropertyTypeSupported() function to check if a particular
+ property type is supported. The currently supported property types
+ are:
+
+ \table
+ \header
+ \o Property Type
+ \o Property Type Id
+ \row
+ \o int
+ \o QVariant::Int
+ \row
+ \o double
+ \o QVariant::Double
+ \row
+ \o bool
+ \o QVariant::Bool
+ \row
+ \o QString
+ \o QVariant::String
+ \row
+ \o QDate
+ \o QVariant::Date
+ \row
+ \o QTime
+ \o QVariant::Time
+ \row
+ \o QDateTime
+ \o QVariant::DateTime
+ \row
+ \o QKeySequence
+ \o QVariant::KeySequence
+ \row
+ \o QChar
+ \o QVariant::Char
+ \row
+ \o QLocale
+ \o QVariant::Locale
+ \row
+ \o QPoint
+ \o QVariant::Point
+ \row
+ \o QPointF
+ \o QVariant::PointF
+ \row
+ \o QSize
+ \o QVariant::Size
+ \row
+ \o QSizeF
+ \o QVariant::SizeF
+ \row
+ \o QRect
+ \o QVariant::Rect
+ \row
+ \o QRectF
+ \o QVariant::RectF
+ \row
+ \o QColor
+ \o QVariant::Color
+ \row
+ \o QSizePolicy
+ \o QVariant::SizePolicy
+ \row
+ \o QFont
+ \o QVariant::Font
+ \row
+ \o QCursor
+ \o QVariant::Cursor
+ \row
+ \o enum
+ \o enumTypeId()
+ \row
+ \o flag
+ \o flagTypeId()
+ \row
+ \o group
+ \o groupTypeId()
+ \endtable
+
+ Each property type can provide additional attributes,
+ e.g. QVariant::Int and QVariant::Double provides minimum and
+ maximum values. The currently supported attributes are:
+
+ \table
+ \header
+ \o Property Type
+ \o Attribute Name
+ \o Attribute Type
+ \row
+ \o \c int
+ \o minimum
+ \o QVariant::Int
+ \row
+ \o
+ \o maximum
+ \o QVariant::Int
+ \row
+ \o
+ \o singleStep
+ \o QVariant::Int
+ \row
+ \o \c double
+ \o minimum
+ \o QVariant::Double
+ \row
+ \o
+ \o maximum
+ \o QVariant::Double
+ \row
+ \o
+ \o singleStep
+ \o QVariant::Double
+ \row
+ \o
+ \o decimals
+ \o QVariant::Int
+ \row
+ \o QString
+ \o regExp
+ \o QVariant::RegExp
+ \row
+ \o QDate
+ \o minimum
+ \o QVariant::Date
+ \row
+ \o
+ \o maximum
+ \o QVariant::Date
+ \row
+ \o QPointF
+ \o decimals
+ \o QVariant::Int
+ \row
+ \o QSize
+ \o minimum
+ \o QVariant::Size
+ \row
+ \o
+ \o maximum
+ \o QVariant::Size
+ \row
+ \o QSizeF
+ \o minimum
+ \o QVariant::SizeF
+ \row
+ \o
+ \o maximum
+ \o QVariant::SizeF
+ \row
+ \o
+ \o decimals
+ \o QVariant::Int
+ \row
+ \o QRect
+ \o constraint
+ \o QVariant::Rect
+ \row
+ \o QRectF
+ \o constraint
+ \o QVariant::RectF
+ \row
+ \o
+ \o decimals
+ \o QVariant::Int
+ \row
+ \o \c enum
+ \o enumNames
+ \o QVariant::StringList
+ \row
+ \o
+ \o enumIcons
+ \o iconMapTypeId()
+ \row
+ \o \c flag
+ \o flagNames
+ \o QVariant::StringList
+ \endtable
+
+ The attributes for a given property type can be retrieved using
+ the attributes() function. Each attribute has a value type which
+ can be retrieved using the attributeType() function, and a value
+ accessible through the attributeValue() function. In addition, the
+ value can be set using the setAttribute() slot.
+
+ QtVariantManager also provides the valueChanged() signal which is
+ emitted whenever a property created by this manager change, and
+ the attributeChanged() signal which is emitted whenever an
+ attribute of such a property changes.
+
+ \sa QtVariantProperty, QtVariantEditorFactory
+*/
+
+/*!
+ \fn void QtVariantPropertyManager::valueChanged(QtProperty *property, const QVariant &value)
+
+ This signal is emitted whenever a property created by this manager
+ changes its value, passing a pointer to the \a property and the
+ new \a value as parameters.
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QtVariantPropertyManager::attributeChanged(QtProperty *property,
+ const QString &attribute, const QVariant &value)
+
+ This signal is emitted whenever an attribute of a property created
+ by this manager changes its value, passing a pointer to the \a
+ property, the \a attribute and the new \a value as parameters.
+
+ \sa setAttribute()
+*/
+
+/*!
+ Creates a manager with the given \a parent.
+*/
+QtVariantPropertyManager::QtVariantPropertyManager(QObject *parent)
+ : QtAbstractPropertyManager(parent)
+{
+ d_ptr = new QtVariantPropertyManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_creatingProperty = false;
+ d_ptr->m_creatingSubProperties = false;
+ d_ptr->m_destroyingSubProperties = false;
+ d_ptr->m_propertyType = 0;
+
+ // IntPropertyManager
+ QtIntPropertyManager *intPropertyManager = new QtIntPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Int] = intPropertyManager;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_minimumAttribute] = QVariant::Int;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_maximumAttribute] = QVariant::Int;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_singleStepAttribute] = QVariant::Int;
+ d_ptr->m_typeToValueType[QVariant::Int] = QVariant::Int;
+ connect(intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(intPropertyManager, SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(intPropertyManager, SIGNAL(singleStepChanged(QtProperty *, int)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, int)));
+ // DoublePropertyManager
+ QtDoublePropertyManager *doublePropertyManager = new QtDoublePropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Double] = doublePropertyManager;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_minimumAttribute] =
+ QVariant::Double;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_maximumAttribute] =
+ QVariant::Double;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_singleStepAttribute] =
+ QVariant::Double;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_decimalsAttribute] =
+ QVariant::Int;
+ d_ptr->m_typeToValueType[QVariant::Double] = QVariant::Double;
+ connect(doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotValueChanged(QtProperty *, double)));
+ connect(doublePropertyManager, SIGNAL(rangeChanged(QtProperty *, double, double)),
+ this, SLOT(slotRangeChanged(QtProperty *, double, double)));
+ connect(doublePropertyManager, SIGNAL(singleStepChanged(QtProperty *, double)),
+ this, SLOT(slotSingleStepChanged(QtProperty *, double)));
+ connect(doublePropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)),
+ this, SLOT(slotDecimalsChanged(QtProperty *, int)));
+ // BoolPropertyManager
+ QtBoolPropertyManager *boolPropertyManager = new QtBoolPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Bool] = boolPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Bool] = QVariant::Bool;
+ connect(boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)),
+ this, SLOT(slotValueChanged(QtProperty *, bool)));
+ // StringPropertyManager
+ QtStringPropertyManager *stringPropertyManager = new QtStringPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::String] = stringPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::String] = QVariant::String;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_regExpAttribute] =
+ QVariant::RegExp;
+ connect(stringPropertyManager, SIGNAL(valueChanged(QtProperty *, const QString &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QString &)));
+ connect(stringPropertyManager, SIGNAL(regExpChanged(QtProperty *, const QRegExp &)),
+ this, SLOT(slotRegExpChanged(QtProperty *, const QRegExp &)));
+ // DatePropertyManager
+ QtDatePropertyManager *datePropertyManager = new QtDatePropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Date] = datePropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Date] = QVariant::Date;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_minimumAttribute] =
+ QVariant::Date;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_maximumAttribute] =
+ QVariant::Date;
+ connect(datePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDate &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QDate &)));
+ connect(datePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)),
+ this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &)));
+ // TimePropertyManager
+ QtTimePropertyManager *timePropertyManager = new QtTimePropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Time] = timePropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Time] = QVariant::Time;
+ connect(timePropertyManager, SIGNAL(valueChanged(QtProperty *, const QTime &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QTime &)));
+ // DateTimePropertyManager
+ QtDateTimePropertyManager *dateTimePropertyManager = new QtDateTimePropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::DateTime] = dateTimePropertyManager;
+ d_ptr->m_typeToValueType[QVariant::DateTime] = QVariant::DateTime;
+ connect(dateTimePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QDateTime &)));
+ // KeySequencePropertyManager
+ QtKeySequencePropertyManager *keySequencePropertyManager = new QtKeySequencePropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::KeySequence] = keySequencePropertyManager;
+ d_ptr->m_typeToValueType[QVariant::KeySequence] = QVariant::KeySequence;
+ connect(keySequencePropertyManager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QKeySequence &)));
+ // CharPropertyManager
+ QtCharPropertyManager *charPropertyManager = new QtCharPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Char] = charPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Char] = QVariant::Char;
+ connect(charPropertyManager, SIGNAL(valueChanged(QtProperty *, const QChar &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QChar &)));
+ // LocalePropertyManager
+ QtLocalePropertyManager *localePropertyManager = new QtLocalePropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Locale] = localePropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Locale] = QVariant::Locale;
+ connect(localePropertyManager, SIGNAL(valueChanged(QtProperty *, const QLocale &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QLocale &)));
+ connect(localePropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(localePropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(localePropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // PointPropertyManager
+ QtPointPropertyManager *pointPropertyManager = new QtPointPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Point] = pointPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Point] = QVariant::Point;
+ connect(pointPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPoint &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QPoint &)));
+ connect(pointPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(pointPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(pointPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // PointFPropertyManager
+ QtPointFPropertyManager *pointFPropertyManager = new QtPointFPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::PointF] = pointFPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::PointF] = QVariant::PointF;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::PointF][d_ptr->m_decimalsAttribute] =
+ QVariant::Int;
+ connect(pointFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPointF &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QPointF &)));
+ connect(pointFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)),
+ this, SLOT(slotDecimalsChanged(QtProperty *, int)));
+ connect(pointFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotValueChanged(QtProperty *, double)));
+ connect(pointFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(pointFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // SizePropertyManager
+ QtSizePropertyManager *sizePropertyManager = new QtSizePropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Size] = sizePropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Size] = QVariant::Size;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_minimumAttribute] =
+ QVariant::Size;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_maximumAttribute] =
+ QVariant::Size;
+ connect(sizePropertyManager, SIGNAL(valueChanged(QtProperty *, const QSize &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QSize &)));
+ connect(sizePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSize &, const QSize &)),
+ this, SLOT(slotRangeChanged(QtProperty *, const QSize &, const QSize &)));
+ connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(sizePropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(sizePropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // SizeFPropertyManager
+ QtSizeFPropertyManager *sizeFPropertyManager = new QtSizeFPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::SizeF] = sizeFPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::SizeF] = QVariant::SizeF;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_minimumAttribute] =
+ QVariant::SizeF;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_maximumAttribute] =
+ QVariant::SizeF;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_decimalsAttribute] =
+ QVariant::Int;
+ connect(sizeFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QSizeF &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QSizeF &)));
+ connect(sizeFPropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSizeF &, const QSizeF &)),
+ this, SLOT(slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &)));
+ connect(sizeFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)),
+ this, SLOT(slotDecimalsChanged(QtProperty *, int)));
+ connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotValueChanged(QtProperty *, double)));
+ connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)),
+ this, SLOT(slotRangeChanged(QtProperty *, double, double)));
+ connect(sizeFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(sizeFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // RectPropertyManager
+ QtRectPropertyManager *rectPropertyManager = new QtRectPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Rect] = rectPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Rect] = QVariant::Rect;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::Rect][d_ptr->m_constraintAttribute] =
+ QVariant::Rect;
+ connect(rectPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRect &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QRect &)));
+ connect(rectPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRect &)),
+ this, SLOT(slotConstraintChanged(QtProperty *, const QRect &)));
+ connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(rectPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(rectPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // RectFPropertyManager
+ QtRectFPropertyManager *rectFPropertyManager = new QtRectFPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::RectF] = rectFPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::RectF] = QVariant::RectF;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_constraintAttribute] =
+ QVariant::RectF;
+ d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_decimalsAttribute] =
+ QVariant::Int;
+ connect(rectFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRectF &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QRectF &)));
+ connect(rectFPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRectF &)),
+ this, SLOT(slotConstraintChanged(QtProperty *, const QRectF &)));
+ connect(rectFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)),
+ this, SLOT(slotDecimalsChanged(QtProperty *, int)));
+ connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)),
+ this, SLOT(slotValueChanged(QtProperty *, double)));
+ connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)),
+ this, SLOT(slotRangeChanged(QtProperty *, double, double)));
+ connect(rectFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(rectFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // ColorPropertyManager
+ QtColorPropertyManager *colorPropertyManager = new QtColorPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Color] = colorPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Color] = QVariant::Color;
+ connect(colorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QColor &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QColor &)));
+ connect(colorPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(colorPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(colorPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // EnumPropertyManager
+ int enumId = enumTypeId();
+ QtEnumPropertyManager *enumPropertyManager = new QtEnumPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[enumId] = enumPropertyManager;
+ d_ptr->m_typeToValueType[enumId] = QVariant::Int;
+ d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumNamesAttribute] =
+ QVariant::StringList;
+ d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumIconsAttribute] =
+ iconMapTypeId();
+ connect(enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(enumPropertyManager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)),
+ this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &)));
+ connect(enumPropertyManager, SIGNAL(enumIconsChanged(QtProperty *, const QMap<int, QIcon> &)),
+ this, SLOT(slotEnumIconsChanged(QtProperty *, const QMap<int, QIcon> &)));
+ // SizePolicyPropertyManager
+ QtSizePolicyPropertyManager *sizePolicyPropertyManager = new QtSizePolicyPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::SizePolicy] = sizePolicyPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::SizePolicy] = QVariant::SizePolicy;
+ connect(sizePolicyPropertyManager, SIGNAL(valueChanged(QtProperty *, const QSizePolicy &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QSizePolicy &)));
+ connect(sizePolicyPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(sizePolicyPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(sizePolicyPropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(sizePolicyPropertyManager->subEnumPropertyManager(),
+ SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)),
+ this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &)));
+ connect(sizePolicyPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(sizePolicyPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // FontPropertyManager
+ QtFontPropertyManager *fontPropertyManager = new QtFontPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Font] = fontPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Font] = QVariant::Font;
+ connect(fontPropertyManager, SIGNAL(valueChanged(QtProperty *, const QFont &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QFont &)));
+ connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)),
+ this, SLOT(slotRangeChanged(QtProperty *, int, int)));
+ connect(fontPropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(fontPropertyManager->subEnumPropertyManager(),
+ SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)),
+ this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &)));
+ connect(fontPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)),
+ this, SLOT(slotValueChanged(QtProperty *, bool)));
+ connect(fontPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(fontPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // CursorPropertyManager
+ QtCursorPropertyManager *cursorPropertyManager = new QtCursorPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[QVariant::Cursor] = cursorPropertyManager;
+ d_ptr->m_typeToValueType[QVariant::Cursor] = QVariant::Cursor;
+ connect(cursorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QCursor &)),
+ this, SLOT(slotValueChanged(QtProperty *, const QCursor &)));
+ // FlagPropertyManager
+ int flagId = flagTypeId();
+ QtFlagPropertyManager *flagPropertyManager = new QtFlagPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[flagId] = flagPropertyManager;
+ d_ptr->m_typeToValueType[flagId] = QVariant::Int;
+ d_ptr->m_typeToAttributeToAttributeType[flagId][d_ptr->m_flagNamesAttribute] =
+ QVariant::StringList;
+ connect(flagPropertyManager, SIGNAL(valueChanged(QtProperty *, int)),
+ this, SLOT(slotValueChanged(QtProperty *, int)));
+ connect(flagPropertyManager, SIGNAL(flagNamesChanged(QtProperty *, const QStringList &)),
+ this, SLOT(slotFlagNamesChanged(QtProperty *, const QStringList &)));
+ connect(flagPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)),
+ this, SLOT(slotValueChanged(QtProperty *, bool)));
+ connect(flagPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)));
+ connect(flagPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)),
+ this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *)));
+ // FlagPropertyManager
+ int groupId = groupTypeId();
+ QtGroupPropertyManager *groupPropertyManager = new QtGroupPropertyManager(this);
+ d_ptr->m_typeToPropertyManager[groupId] = groupPropertyManager;
+ d_ptr->m_typeToValueType[groupId] = QVariant::Invalid;
+}
+
+/*!
+ Destroys this manager, and all the properties it has created.
+*/
+QtVariantPropertyManager::~QtVariantPropertyManager()
+{
+ clear();
+ delete d_ptr;
+}
+
+/*!
+ Returns the given \a property converted into a QtVariantProperty.
+
+ If the \a property was not created by this variant manager, the
+ function returns 0.
+
+ \sa createProperty()
+*/
+QtVariantProperty *QtVariantPropertyManager::variantProperty(const QtProperty *property) const
+{
+ const QMap<const QtProperty *, QPair<QtVariantProperty *, int> >::const_iterator it = d_ptr->m_propertyToType.constFind(property);
+ if (it == d_ptr->m_propertyToType.constEnd())
+ return 0;
+ return it.value().first;
+}
+
+/*!
+ Returns true if the given \a propertyType is supported by this
+ variant manager; otherwise false.
+
+ \sa propertyType()
+*/
+bool QtVariantPropertyManager::isPropertyTypeSupported(int propertyType) const
+{
+ if (d_ptr->m_typeToValueType.contains(propertyType))
+ return true;
+ return false;
+}
+
+/*!
+ Creates and returns a variant property of the given \a propertyType
+ with the given \a name.
+
+ If the specified \a propertyType is not supported by this variant
+ manager, this function returns 0.
+
+ Do not use the inherited
+ QtAbstractPropertyManager::addProperty() function to create a
+ variant property (that function will always return 0 since it will
+ not be clear what type the property should have).
+
+ \sa isPropertyTypeSupported()
+*/
+QtVariantProperty *QtVariantPropertyManager::addProperty(int propertyType, const QString &name)
+{
+ if (!isPropertyTypeSupported(propertyType))
+ return 0;
+
+ bool wasCreating = d_ptr->m_creatingProperty;
+ d_ptr->m_creatingProperty = true;
+ d_ptr->m_propertyType = propertyType;
+ QtProperty *property = QtAbstractPropertyManager::addProperty(name);
+ d_ptr->m_creatingProperty = wasCreating;
+ d_ptr->m_propertyType = 0;
+
+ if (!property)
+ return 0;
+
+ return variantProperty(property);
+}
+
+/*!
+ Returns the given \a property's value.
+
+ If the given \a property is not managed by this manager, this
+ function returns an invalid variant.
+
+ \sa setValue()
+*/
+QVariant QtVariantPropertyManager::value(const QtProperty *property) const
+{
+ QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
+ if (internProp == 0)
+ return QVariant();
+
+ QtAbstractPropertyManager *manager = internProp->propertyManager();
+ if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) {
+ return intManager->value(internProp);
+ } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) {
+ return doubleManager->value(internProp);
+ } else if (QtBoolPropertyManager *boolManager = qobject_cast<QtBoolPropertyManager *>(manager)) {
+ return boolManager->value(internProp);
+ } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) {
+ return stringManager->value(internProp);
+ } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) {
+ return dateManager->value(internProp);
+ } else if (QtTimePropertyManager *timeManager = qobject_cast<QtTimePropertyManager *>(manager)) {
+ return timeManager->value(internProp);
+ } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast<QtDateTimePropertyManager *>(manager)) {
+ return dateTimeManager->value(internProp);
+ } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast<QtKeySequencePropertyManager *>(manager)) {
+ return keySequenceManager->value(internProp);
+ } else if (QtCharPropertyManager *charManager = qobject_cast<QtCharPropertyManager *>(manager)) {
+ return charManager->value(internProp);
+ } else if (QtLocalePropertyManager *localeManager = qobject_cast<QtLocalePropertyManager *>(manager)) {
+ return localeManager->value(internProp);
+ } else if (QtPointPropertyManager *pointManager = qobject_cast<QtPointPropertyManager *>(manager)) {
+ return pointManager->value(internProp);
+ } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) {
+ return pointFManager->value(internProp);
+ } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) {
+ return sizeManager->value(internProp);
+ } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) {
+ return sizeFManager->value(internProp);
+ } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) {
+ return rectManager->value(internProp);
+ } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) {
+ return rectFManager->value(internProp);
+ } else if (QtColorPropertyManager *colorManager = qobject_cast<QtColorPropertyManager *>(manager)) {
+ return colorManager->value(internProp);
+ } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) {
+ return enumManager->value(internProp);
+ } else if (QtSizePolicyPropertyManager *sizePolicyManager =
+ qobject_cast<QtSizePolicyPropertyManager *>(manager)) {
+ return sizePolicyManager->value(internProp);
+ } else if (QtFontPropertyManager *fontManager = qobject_cast<QtFontPropertyManager *>(manager)) {
+ return fontManager->value(internProp);
+#ifndef QT_NO_CURSOR
+ } else if (QtCursorPropertyManager *cursorManager = qobject_cast<QtCursorPropertyManager *>(manager)) {
+ return cursorManager->value(internProp);
+#endif
+ } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) {
+ return flagManager->value(internProp);
+ }
+ return QVariant();
+}
+
+/*!
+ Returns the given \a property's value type.
+
+ \sa propertyType()
+*/
+int QtVariantPropertyManager::valueType(const QtProperty *property) const
+{
+ int propType = propertyType(property);
+ return valueType(propType);
+}
+
+/*!
+ \overload
+
+ Returns the value type associated with the given \a propertyType.
+*/
+int QtVariantPropertyManager::valueType(int propertyType) const
+{
+ if (d_ptr->m_typeToValueType.contains(propertyType))
+ return d_ptr->m_typeToValueType[propertyType];
+ return 0;
+}
+
+/*!
+ Returns the given \a property's type.
+
+ \sa valueType()
+*/
+int QtVariantPropertyManager::propertyType(const QtProperty *property) const
+{
+ const QMap<const QtProperty *, QPair<QtVariantProperty *, int> >::const_iterator it = d_ptr->m_propertyToType.constFind(property);
+ if (it == d_ptr->m_propertyToType.constEnd())
+ return 0;
+ return it.value().second;
+}
+
+/*!
+ Returns the given \a property's value for the specified \a
+ attribute
+
+ If the given \a property was not created by \e this manager, or if
+ the specified \a attribute does not exist, this function returns
+ an invalid variant.
+
+ \sa attributes(), attributeType(), setAttribute()
+*/
+QVariant QtVariantPropertyManager::attributeValue(const QtProperty *property, const QString &attribute) const
+{
+ int propType = propertyType(property);
+ if (!propType)
+ return QVariant();
+
+ QMap<int, QMap<QString, int> >::ConstIterator it =
+ d_ptr->m_typeToAttributeToAttributeType.find(propType);
+ if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd())
+ return QVariant();
+
+ QMap<QString, int> attributes = it.value();
+ QMap<QString, int>::ConstIterator itAttr = attributes.find(attribute);
+ if (itAttr == attributes.constEnd())
+ return QVariant();
+
+ QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
+ if (internProp == 0)
+ return QVariant();
+
+ QtAbstractPropertyManager *manager = internProp->propertyManager();
+ if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ return intManager->maximum(internProp);
+ if (attribute == d_ptr->m_minimumAttribute)
+ return intManager->minimum(internProp);
+ if (attribute == d_ptr->m_singleStepAttribute)
+ return intManager->singleStep(internProp);
+ return QVariant();
+ } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ return doubleManager->maximum(internProp);
+ if (attribute == d_ptr->m_minimumAttribute)
+ return doubleManager->minimum(internProp);
+ if (attribute == d_ptr->m_singleStepAttribute)
+ return doubleManager->singleStep(internProp);
+ if (attribute == d_ptr->m_decimalsAttribute)
+ return doubleManager->decimals(internProp);
+ return QVariant();
+ } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_regExpAttribute)
+ return stringManager->regExp(internProp);
+ return QVariant();
+ } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ return dateManager->maximum(internProp);
+ if (attribute == d_ptr->m_minimumAttribute)
+ return dateManager->minimum(internProp);
+ return QVariant();
+ } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_decimalsAttribute)
+ return pointFManager->decimals(internProp);
+ return QVariant();
+ } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ return sizeManager->maximum(internProp);
+ if (attribute == d_ptr->m_minimumAttribute)
+ return sizeManager->minimum(internProp);
+ return QVariant();
+ } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ return sizeFManager->maximum(internProp);
+ if (attribute == d_ptr->m_minimumAttribute)
+ return sizeFManager->minimum(internProp);
+ if (attribute == d_ptr->m_decimalsAttribute)
+ return sizeFManager->decimals(internProp);
+ return QVariant();
+ } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_constraintAttribute)
+ return rectManager->constraint(internProp);
+ return QVariant();
+ } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_constraintAttribute)
+ return rectFManager->constraint(internProp);
+ if (attribute == d_ptr->m_decimalsAttribute)
+ return rectFManager->decimals(internProp);
+ return QVariant();
+ } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_enumNamesAttribute)
+ return enumManager->enumNames(internProp);
+ if (attribute == d_ptr->m_enumIconsAttribute) {
+ QVariant v;
+ qVariantSetValue(v, enumManager->enumIcons(internProp));
+ return v;
+ }
+ return QVariant();
+ } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_flagNamesAttribute)
+ return flagManager->flagNames(internProp);
+ return QVariant();
+ }
+ return QVariant();
+}
+
+/*!
+ Returns a list of the given \a propertyType 's attributes.
+
+ \sa attributeValue(), attributeType()
+*/
+QStringList QtVariantPropertyManager::attributes(int propertyType) const
+{
+ QMap<int, QMap<QString, int> >::ConstIterator it =
+ d_ptr->m_typeToAttributeToAttributeType.find(propertyType);
+ if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd())
+ return QStringList();
+ return it.value().keys();
+}
+
+/*!
+ Returns the type of the specified \a attribute of the given \a
+ propertyType.
+
+ If the given \a propertyType is not supported by \e this manager,
+ or if the given \a propertyType does not possess the specified \a
+ attribute, this function returns QVariant::Invalid.
+
+ \sa attributes(), valueType()
+*/
+int QtVariantPropertyManager::attributeType(int propertyType, const QString &attribute) const
+{
+ QMap<int, QMap<QString, int> >::ConstIterator it =
+ d_ptr->m_typeToAttributeToAttributeType.find(propertyType);
+ if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd())
+ return 0;
+
+ QMap<QString, int> attributes = it.value();
+ QMap<QString, int>::ConstIterator itAttr = attributes.find(attribute);
+ if (itAttr == attributes.constEnd())
+ return 0;
+ return itAttr.value();
+}
+
+/*!
+ \fn void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &value)
+
+ Sets the value of the given \a property to \a value.
+
+ The specified \a value must be of a type returned by valueType(),
+ or of type that can be converted to valueType() using the
+ QVariant::canConvert() function, otherwise this function does
+ nothing.
+
+ \sa value(), QtVariantProperty::setValue(), valueChanged()
+*/
+void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &val)
+{
+ int propType = val.userType();
+ if (!propType)
+ return;
+
+ int valType = valueType(property);
+
+ if (propType != valType && !val.canConvert(static_cast<QVariant::Type>(valType)))
+ return;
+
+ QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
+ if (internProp == 0)
+ return;
+
+
+ QtAbstractPropertyManager *manager = internProp->propertyManager();
+ if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) {
+ intManager->setValue(internProp, qVariantValue<int>(val));
+ return;
+ } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) {
+ doubleManager->setValue(internProp, qVariantValue<double>(val));
+ return;
+ } else if (QtBoolPropertyManager *boolManager = qobject_cast<QtBoolPropertyManager *>(manager)) {
+ boolManager->setValue(internProp, qVariantValue<bool>(val));
+ return;
+ } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) {
+ stringManager->setValue(internProp, qVariantValue<QString>(val));
+ return;
+ } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) {
+ dateManager->setValue(internProp, qVariantValue<QDate>(val));
+ return;
+ } else if (QtTimePropertyManager *timeManager = qobject_cast<QtTimePropertyManager *>(manager)) {
+ timeManager->setValue(internProp, qVariantValue<QTime>(val));
+ return;
+ } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast<QtDateTimePropertyManager *>(manager)) {
+ dateTimeManager->setValue(internProp, qVariantValue<QDateTime>(val));
+ return;
+ } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast<QtKeySequencePropertyManager *>(manager)) {
+ keySequenceManager->setValue(internProp, qVariantValue<QKeySequence>(val));
+ return;
+ } else if (QtCharPropertyManager *charManager = qobject_cast<QtCharPropertyManager *>(manager)) {
+ charManager->setValue(internProp, qVariantValue<QChar>(val));
+ return;
+ } else if (QtLocalePropertyManager *localeManager = qobject_cast<QtLocalePropertyManager *>(manager)) {
+ localeManager->setValue(internProp, qVariantValue<QLocale>(val));
+ return;
+ } else if (QtPointPropertyManager *pointManager = qobject_cast<QtPointPropertyManager *>(manager)) {
+ pointManager->setValue(internProp, qVariantValue<QPoint>(val));
+ return;
+ } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) {
+ pointFManager->setValue(internProp, qVariantValue<QPointF>(val));
+ return;
+ } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) {
+ sizeManager->setValue(internProp, qVariantValue<QSize>(val));
+ return;
+ } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) {
+ sizeFManager->setValue(internProp, qVariantValue<QSizeF>(val));
+ return;
+ } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) {
+ rectManager->setValue(internProp, qVariantValue<QRect>(val));
+ return;
+ } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) {
+ rectFManager->setValue(internProp, qVariantValue<QRectF>(val));
+ return;
+ } else if (QtColorPropertyManager *colorManager = qobject_cast<QtColorPropertyManager *>(manager)) {
+ colorManager->setValue(internProp, qVariantValue<QColor>(val));
+ return;
+ } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) {
+ enumManager->setValue(internProp, qVariantValue<int>(val));
+ return;
+ } else if (QtSizePolicyPropertyManager *sizePolicyManager =
+ qobject_cast<QtSizePolicyPropertyManager *>(manager)) {
+ sizePolicyManager->setValue(internProp, qVariantValue<QSizePolicy>(val));
+ return;
+ } else if (QtFontPropertyManager *fontManager = qobject_cast<QtFontPropertyManager *>(manager)) {
+ fontManager->setValue(internProp, qVariantValue<QFont>(val));
+ return;
+#ifndef QT_NO_CURSOR
+ } else if (QtCursorPropertyManager *cursorManager = qobject_cast<QtCursorPropertyManager *>(manager)) {
+ cursorManager->setValue(internProp, qVariantValue<QCursor>(val));
+ return;
+#endif
+ } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) {
+ flagManager->setValue(internProp, qVariantValue<int>(val));
+ return;
+ }
+}
+
+/*!
+ Sets the value of the specified \a attribute of the given \a
+ property, to \a value.
+
+ The new \a value's type must be of the type returned by
+ attributeType(), or of a type that can be converted to
+ attributeType() using the QVariant::canConvert() function,
+ otherwise this function does nothing.
+
+ \sa attributeValue(), QtVariantProperty::setAttribute(), attributeChanged()
+*/
+void QtVariantPropertyManager::setAttribute(QtProperty *property,
+ const QString &attribute, const QVariant &value)
+{
+ QVariant oldAttr = attributeValue(property, attribute);
+ if (!oldAttr.isValid())
+ return;
+
+ int attrType = value.userType();
+ if (!attrType)
+ return;
+
+ if (attrType != attributeType(propertyType(property), attribute) &&
+ !value.canConvert((QVariant::Type)attrType))
+ return;
+
+ QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
+ if (internProp == 0)
+ return;
+
+ QtAbstractPropertyManager *manager = internProp->propertyManager();
+ if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ intManager->setMaximum(internProp, qVariantValue<int>(value));
+ else if (attribute == d_ptr->m_minimumAttribute)
+ intManager->setMinimum(internProp, qVariantValue<int>(value));
+ else if (attribute == d_ptr->m_singleStepAttribute)
+ intManager->setSingleStep(internProp, qVariantValue<int>(value));
+ return;
+ } else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ doubleManager->setMaximum(internProp, qVariantValue<double>(value));
+ if (attribute == d_ptr->m_minimumAttribute)
+ doubleManager->setMinimum(internProp, qVariantValue<double>(value));
+ if (attribute == d_ptr->m_singleStepAttribute)
+ doubleManager->setSingleStep(internProp, qVariantValue<double>(value));
+ if (attribute == d_ptr->m_decimalsAttribute)
+ doubleManager->setDecimals(internProp, qVariantValue<int>(value));
+ return;
+ } else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_regExpAttribute)
+ stringManager->setRegExp(internProp, qVariantValue<QRegExp>(value));
+ return;
+ } else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ dateManager->setMaximum(internProp, qVariantValue<QDate>(value));
+ if (attribute == d_ptr->m_minimumAttribute)
+ dateManager->setMinimum(internProp, qVariantValue<QDate>(value));
+ return;
+ } else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_decimalsAttribute)
+ pointFManager->setDecimals(internProp, qVariantValue<int>(value));
+ return;
+ } else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ sizeManager->setMaximum(internProp, qVariantValue<QSize>(value));
+ if (attribute == d_ptr->m_minimumAttribute)
+ sizeManager->setMinimum(internProp, qVariantValue<QSize>(value));
+ return;
+ } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_maximumAttribute)
+ sizeFManager->setMaximum(internProp, qVariantValue<QSizeF>(value));
+ if (attribute == d_ptr->m_minimumAttribute)
+ sizeFManager->setMinimum(internProp, qVariantValue<QSizeF>(value));
+ if (attribute == d_ptr->m_decimalsAttribute)
+ sizeFManager->setDecimals(internProp, qVariantValue<int>(value));
+ return;
+ } else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_constraintAttribute)
+ rectManager->setConstraint(internProp, qVariantValue<QRect>(value));
+ return;
+ } else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_constraintAttribute)
+ rectFManager->setConstraint(internProp, qVariantValue<QRectF>(value));
+ if (attribute == d_ptr->m_decimalsAttribute)
+ rectFManager->setDecimals(internProp, qVariantValue<int>(value));
+ return;
+ } else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_enumNamesAttribute)
+ enumManager->setEnumNames(internProp, qVariantValue<QStringList>(value));
+ if (attribute == d_ptr->m_enumIconsAttribute)
+ enumManager->setEnumIcons(internProp, qVariantValue<QtIconMap>(value));
+ return;
+ } else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) {
+ if (attribute == d_ptr->m_flagNamesAttribute)
+ flagManager->setFlagNames(internProp, qVariantValue<QStringList>(value));
+ return;
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QtVariantPropertyManager::hasValue(const QtProperty *property) const
+{
+ if (propertyType(property) == groupTypeId())
+ return false;
+ return true;
+}
+
+/*!
+ \reimp
+*/
+QString QtVariantPropertyManager::valueText(const QtProperty *property) const
+{
+ const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
+ return internProp ? internProp->valueText() : QString();
+}
+
+/*!
+ \reimp
+*/
+QIcon QtVariantPropertyManager::valueIcon(const QtProperty *property) const
+{
+ const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
+ return internProp ? internProp->valueIcon() : QIcon();
+}
+
+/*!
+ \reimp
+*/
+void QtVariantPropertyManager::initializeProperty(QtProperty *property)
+{
+ QtVariantProperty *varProp = variantProperty(property);
+ if (!varProp)
+ return;
+
+ QMap<int, QtAbstractPropertyManager *>::ConstIterator it =
+ d_ptr->m_typeToPropertyManager.find(d_ptr->m_propertyType);
+ if (it != d_ptr->m_typeToPropertyManager.constEnd()) {
+ QtProperty *internProp = 0;
+ if (!d_ptr->m_creatingSubProperties) {
+ QtAbstractPropertyManager *manager = it.value();
+ internProp = manager->addProperty();
+ d_ptr->m_internalToProperty[internProp] = varProp;
+ }
+ propertyToWrappedProperty()->insert(varProp, internProp);
+ if (internProp) {
+ QList<QtProperty *> children = internProp->subProperties();
+ QListIterator<QtProperty *> itChild(children);
+ QtVariantProperty *lastProperty = 0;
+ while (itChild.hasNext()) {
+ QtVariantProperty *prop = d_ptr->createSubProperty(varProp, lastProperty, itChild.next());
+ lastProperty = prop ? prop : lastProperty;
+ }
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+void QtVariantPropertyManager::uninitializeProperty(QtProperty *property)
+{
+ const QMap<const QtProperty *, QPair<QtVariantProperty *, int> >::iterator type_it = d_ptr->m_propertyToType.find(property);
+ if (type_it == d_ptr->m_propertyToType.end())
+ return;
+
+ PropertyMap::iterator it = propertyToWrappedProperty()->find(property);
+ if (it != propertyToWrappedProperty()->end()) {
+ QtProperty *internProp = it.value();
+ if (internProp) {
+ d_ptr->m_internalToProperty.remove(internProp);
+ if (!d_ptr->m_destroyingSubProperties) {
+ delete internProp;
+ }
+ }
+ propertyToWrappedProperty()->erase(it);
+ }
+ d_ptr->m_propertyToType.erase(type_it);
+}
+
+/*!
+ \reimp
+*/
+QtProperty *QtVariantPropertyManager::createProperty()
+{
+ if (!d_ptr->m_creatingProperty)
+ return 0;
+
+ QtVariantProperty *property = new QtVariantProperty(this);
+ d_ptr->m_propertyToType.insert(property, qMakePair(property, d_ptr->m_propertyType));
+
+ return property;
+}
+
+/////////////////////////////
+
+class QtVariantEditorFactoryPrivate
+{
+ QtVariantEditorFactory *q_ptr;
+ Q_DECLARE_PUBLIC(QtVariantEditorFactory)
+public:
+
+ QtSpinBoxFactory *m_spinBoxFactory;
+ QtDoubleSpinBoxFactory *m_doubleSpinBoxFactory;
+ QtCheckBoxFactory *m_checkBoxFactory;
+ QtLineEditFactory *m_lineEditFactory;
+ QtDateEditFactory *m_dateEditFactory;
+ QtTimeEditFactory *m_timeEditFactory;
+ QtDateTimeEditFactory *m_dateTimeEditFactory;
+ QtKeySequenceEditorFactory *m_keySequenceEditorFactory;
+ QtCharEditorFactory *m_charEditorFactory;
+ QtEnumEditorFactory *m_comboBoxFactory;
+ QtCursorEditorFactory *m_cursorEditorFactory;
+ QtColorEditorFactory *m_colorEditorFactory;
+ QtFontEditorFactory *m_fontEditorFactory;
+
+ QMap<QtAbstractEditorFactoryBase *, int> m_factoryToType;
+ QMap<int, QtAbstractEditorFactoryBase *> m_typeToFactory;
+};
+
+/*!
+ \class QtVariantEditorFactory
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtVariantEditorFactory class provides widgets for properties
+ created by QtVariantPropertyManager objects.
+
+ The variant factory provides the following widgets for the
+ specified property types:
+
+ \table
+ \header
+ \o Property Type
+ \o Widget
+ \row
+ \o \c int
+ \o QSpinBox
+ \row
+ \o \c double
+ \o QDoubleSpinBox
+ \row
+ \o \c bool
+ \o QCheckBox
+ \row
+ \o QString
+ \o QLineEdit
+ \row
+ \o QDate
+ \o QDateEdit
+ \row
+ \o QTime
+ \o QTimeEdit
+ \row
+ \o QDateTime
+ \o QDateTimeEdit
+ \row
+ \o QKeySequence
+ \o customized editor
+ \row
+ \o QChar
+ \o customized editor
+ \row
+ \o \c enum
+ \o QComboBox
+ \row
+ \o QCursor
+ \o QComboBox
+ \endtable
+
+ Note that QtVariantPropertyManager supports several additional property
+ types for which the QtVariantEditorFactory class does not provide
+ editing widgets, e.g. QPoint and QSize. To provide widgets for other
+ types using the variant approach, derive from the QtVariantEditorFactory
+ class.
+
+ \sa QtAbstractEditorFactory, QtVariantPropertyManager
+*/
+
+/*!
+ Creates a factory with the given \a parent.
+*/
+QtVariantEditorFactory::QtVariantEditorFactory(QObject *parent)
+ : QtAbstractEditorFactory<QtVariantPropertyManager>(parent)
+{
+ d_ptr = new QtVariantEditorFactoryPrivate();
+ d_ptr->q_ptr = this;
+
+ d_ptr->m_spinBoxFactory = new QtSpinBoxFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_spinBoxFactory] = QVariant::Int;
+ d_ptr->m_typeToFactory[QVariant::Int] = d_ptr->m_spinBoxFactory;
+
+ d_ptr->m_doubleSpinBoxFactory = new QtDoubleSpinBoxFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_doubleSpinBoxFactory] = QVariant::Double;
+ d_ptr->m_typeToFactory[QVariant::Double] = d_ptr->m_doubleSpinBoxFactory;
+
+ d_ptr->m_checkBoxFactory = new QtCheckBoxFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_checkBoxFactory] = QVariant::Bool;
+ d_ptr->m_typeToFactory[QVariant::Bool] = d_ptr->m_checkBoxFactory;
+
+ d_ptr->m_lineEditFactory = new QtLineEditFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_lineEditFactory] = QVariant::String;
+ d_ptr->m_typeToFactory[QVariant::String] = d_ptr->m_lineEditFactory;
+
+ d_ptr->m_dateEditFactory = new QtDateEditFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_dateEditFactory] = QVariant::Date;
+ d_ptr->m_typeToFactory[QVariant::Date] = d_ptr->m_dateEditFactory;
+
+ d_ptr->m_timeEditFactory = new QtTimeEditFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_timeEditFactory] = QVariant::Time;
+ d_ptr->m_typeToFactory[QVariant::Time] = d_ptr->m_timeEditFactory;
+
+ d_ptr->m_dateTimeEditFactory = new QtDateTimeEditFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_dateTimeEditFactory] = QVariant::DateTime;
+ d_ptr->m_typeToFactory[QVariant::DateTime] = d_ptr->m_dateTimeEditFactory;
+
+ d_ptr->m_keySequenceEditorFactory = new QtKeySequenceEditorFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_keySequenceEditorFactory] = QVariant::KeySequence;
+ d_ptr->m_typeToFactory[QVariant::KeySequence] = d_ptr->m_keySequenceEditorFactory;
+
+ d_ptr->m_charEditorFactory = new QtCharEditorFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_charEditorFactory] = QVariant::Char;
+ d_ptr->m_typeToFactory[QVariant::Char] = d_ptr->m_charEditorFactory;
+
+ d_ptr->m_cursorEditorFactory = new QtCursorEditorFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_cursorEditorFactory] = QVariant::Cursor;
+ d_ptr->m_typeToFactory[QVariant::Cursor] = d_ptr->m_cursorEditorFactory;
+
+ d_ptr->m_colorEditorFactory = new QtColorEditorFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_colorEditorFactory] = QVariant::Color;
+ d_ptr->m_typeToFactory[QVariant::Color] = d_ptr->m_colorEditorFactory;
+
+ d_ptr->m_fontEditorFactory = new QtFontEditorFactory(this);
+ d_ptr->m_factoryToType[d_ptr->m_fontEditorFactory] = QVariant::Font;
+ d_ptr->m_typeToFactory[QVariant::Font] = d_ptr->m_fontEditorFactory;
+
+ d_ptr->m_comboBoxFactory = new QtEnumEditorFactory(this);
+ const int enumId = QtVariantPropertyManager::enumTypeId();
+ d_ptr->m_factoryToType[d_ptr->m_comboBoxFactory] = enumId;
+ d_ptr->m_typeToFactory[enumId] = d_ptr->m_comboBoxFactory;
+}
+
+/*!
+ Destroys this factory, and all the widgets it has created.
+*/
+QtVariantEditorFactory::~QtVariantEditorFactory()
+{
+ delete d_ptr;
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager)
+{
+ QList<QtIntPropertyManager *> intPropertyManagers = qFindChildren<QtIntPropertyManager *>(manager);
+ QListIterator<QtIntPropertyManager *> itInt(intPropertyManagers);
+ while (itInt.hasNext())
+ d_ptr->m_spinBoxFactory->addPropertyManager(itInt.next());
+
+ QList<QtDoublePropertyManager *> doublePropertyManagers = qFindChildren<QtDoublePropertyManager *>(manager);
+ QListIterator<QtDoublePropertyManager *> itDouble(doublePropertyManagers);
+ while (itDouble.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itDouble.next());
+
+ QList<QtBoolPropertyManager *> boolPropertyManagers = qFindChildren<QtBoolPropertyManager *>(manager);
+ QListIterator<QtBoolPropertyManager *> itBool(boolPropertyManagers);
+ while (itBool.hasNext())
+ d_ptr->m_checkBoxFactory->addPropertyManager(itBool.next());
+
+ QList<QtStringPropertyManager *> stringPropertyManagers = qFindChildren<QtStringPropertyManager *>(manager);
+ QListIterator<QtStringPropertyManager *> itString(stringPropertyManagers);
+ while (itString.hasNext())
+ d_ptr->m_lineEditFactory->addPropertyManager(itString.next());
+
+ QList<QtDatePropertyManager *> datePropertyManagers = qFindChildren<QtDatePropertyManager *>(manager);
+ QListIterator<QtDatePropertyManager *> itDate(datePropertyManagers);
+ while (itDate.hasNext())
+ d_ptr->m_dateEditFactory->addPropertyManager(itDate.next());
+
+ QList<QtTimePropertyManager *> timePropertyManagers = qFindChildren<QtTimePropertyManager *>(manager);
+ QListIterator<QtTimePropertyManager *> itTime(timePropertyManagers);
+ while (itTime.hasNext())
+ d_ptr->m_timeEditFactory->addPropertyManager(itTime.next());
+
+ QList<QtDateTimePropertyManager *> dateTimePropertyManagers = qFindChildren<QtDateTimePropertyManager *>(manager);
+ QListIterator<QtDateTimePropertyManager *> itDateTime(dateTimePropertyManagers);
+ while (itDateTime.hasNext())
+ d_ptr->m_dateTimeEditFactory->addPropertyManager(itDateTime.next());
+
+ QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = qFindChildren<QtKeySequencePropertyManager *>(manager);
+ QListIterator<QtKeySequencePropertyManager *> itKeySequence(keySequencePropertyManagers);
+ while (itKeySequence.hasNext())
+ d_ptr->m_keySequenceEditorFactory->addPropertyManager(itKeySequence.next());
+
+ QList<QtCharPropertyManager *> charPropertyManagers = qFindChildren<QtCharPropertyManager *>(manager);
+ QListIterator<QtCharPropertyManager *> itChar(charPropertyManagers);
+ while (itChar.hasNext())
+ d_ptr->m_charEditorFactory->addPropertyManager(itChar.next());
+
+ QList<QtLocalePropertyManager *> localePropertyManagers = qFindChildren<QtLocalePropertyManager *>(manager);
+ QListIterator<QtLocalePropertyManager *> itLocale(localePropertyManagers);
+ while (itLocale.hasNext())
+ d_ptr->m_comboBoxFactory->addPropertyManager(itLocale.next()->subEnumPropertyManager());
+
+ QList<QtPointPropertyManager *> pointPropertyManagers = qFindChildren<QtPointPropertyManager *>(manager);
+ QListIterator<QtPointPropertyManager *> itPoint(pointPropertyManagers);
+ while (itPoint.hasNext())
+ d_ptr->m_spinBoxFactory->addPropertyManager(itPoint.next()->subIntPropertyManager());
+
+ QList<QtPointFPropertyManager *> pointFPropertyManagers = qFindChildren<QtPointFPropertyManager *>(manager);
+ QListIterator<QtPointFPropertyManager *> itPointF(pointFPropertyManagers);
+ while (itPointF.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itPointF.next()->subDoublePropertyManager());
+
+ QList<QtSizePropertyManager *> sizePropertyManagers = qFindChildren<QtSizePropertyManager *>(manager);
+ QListIterator<QtSizePropertyManager *> itSize(sizePropertyManagers);
+ while (itSize.hasNext())
+ d_ptr->m_spinBoxFactory->addPropertyManager(itSize.next()->subIntPropertyManager());
+
+ QList<QtSizeFPropertyManager *> sizeFPropertyManagers = qFindChildren<QtSizeFPropertyManager *>(manager);
+ QListIterator<QtSizeFPropertyManager *> itSizeF(sizeFPropertyManagers);
+ while (itSizeF.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itSizeF.next()->subDoublePropertyManager());
+
+ QList<QtRectPropertyManager *> rectPropertyManagers = qFindChildren<QtRectPropertyManager *>(manager);
+ QListIterator<QtRectPropertyManager *> itRect(rectPropertyManagers);
+ while (itRect.hasNext())
+ d_ptr->m_spinBoxFactory->addPropertyManager(itRect.next()->subIntPropertyManager());
+
+ QList<QtRectFPropertyManager *> rectFPropertyManagers = qFindChildren<QtRectFPropertyManager *>(manager);
+ QListIterator<QtRectFPropertyManager *> itRectF(rectFPropertyManagers);
+ while (itRectF.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itRectF.next()->subDoublePropertyManager());
+
+ QList<QtColorPropertyManager *> colorPropertyManagers = qFindChildren<QtColorPropertyManager *>(manager);
+ QListIterator<QtColorPropertyManager *> itColor(colorPropertyManagers);
+ while (itColor.hasNext()) {
+ QtColorPropertyManager *manager = itColor.next();
+ d_ptr->m_colorEditorFactory->addPropertyManager(manager);
+ d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager());
+ }
+
+ QList<QtEnumPropertyManager *> enumPropertyManagers = qFindChildren<QtEnumPropertyManager *>(manager);
+ QListIterator<QtEnumPropertyManager *> itEnum(enumPropertyManagers);
+ while (itEnum.hasNext())
+ d_ptr->m_comboBoxFactory->addPropertyManager(itEnum.next());
+
+ QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = qFindChildren<QtSizePolicyPropertyManager *>(manager);
+ QListIterator<QtSizePolicyPropertyManager *> itSizePolicy(sizePolicyPropertyManagers);
+ while (itSizePolicy.hasNext()) {
+ QtSizePolicyPropertyManager *manager = itSizePolicy.next();
+ d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager());
+ d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager());
+ }
+
+ QList<QtFontPropertyManager *> fontPropertyManagers = qFindChildren<QtFontPropertyManager *>(manager);
+ QListIterator<QtFontPropertyManager *> itFont(fontPropertyManagers);
+ while (itFont.hasNext()) {
+ QtFontPropertyManager *manager = itFont.next();
+ d_ptr->m_fontEditorFactory->addPropertyManager(manager);
+ d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager());
+ d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager());
+ d_ptr->m_checkBoxFactory->addPropertyManager(manager->subBoolPropertyManager());
+ }
+
+ QList<QtCursorPropertyManager *> cursorPropertyManagers = qFindChildren<QtCursorPropertyManager *>(manager);
+ QListIterator<QtCursorPropertyManager *> itCursor(cursorPropertyManagers);
+ while (itCursor.hasNext())
+ d_ptr->m_cursorEditorFactory->addPropertyManager(itCursor.next());
+
+ QList<QtFlagPropertyManager *> flagPropertyManagers = qFindChildren<QtFlagPropertyManager *>(manager);
+ QListIterator<QtFlagPropertyManager *> itFlag(flagPropertyManagers);
+ while (itFlag.hasNext())
+ d_ptr->m_checkBoxFactory->addPropertyManager(itFlag.next()->subBoolPropertyManager());
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+QWidget *QtVariantEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property,
+ QWidget *parent)
+{
+ const int propType = manager->propertyType(property);
+ QtAbstractEditorFactoryBase *factory = d_ptr->m_typeToFactory.value(propType, 0);
+ if (!factory)
+ return 0;
+ return factory->createEditor(wrappedProperty(property), parent);
+}
+
+/*!
+ \internal
+
+ Reimplemented from the QtAbstractEditorFactory class.
+*/
+void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager)
+{
+ QList<QtIntPropertyManager *> intPropertyManagers = qFindChildren<QtIntPropertyManager *>(manager);
+ QListIterator<QtIntPropertyManager *> itInt(intPropertyManagers);
+ while (itInt.hasNext())
+ d_ptr->m_spinBoxFactory->removePropertyManager(itInt.next());
+
+ QList<QtDoublePropertyManager *> doublePropertyManagers = qFindChildren<QtDoublePropertyManager *>(manager);
+ QListIterator<QtDoublePropertyManager *> itDouble(doublePropertyManagers);
+ while (itDouble.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itDouble.next());
+
+ QList<QtBoolPropertyManager *> boolPropertyManagers = qFindChildren<QtBoolPropertyManager *>(manager);
+ QListIterator<QtBoolPropertyManager *> itBool(boolPropertyManagers);
+ while (itBool.hasNext())
+ d_ptr->m_checkBoxFactory->removePropertyManager(itBool.next());
+
+ QList<QtStringPropertyManager *> stringPropertyManagers = qFindChildren<QtStringPropertyManager *>(manager);
+ QListIterator<QtStringPropertyManager *> itString(stringPropertyManagers);
+ while (itString.hasNext())
+ d_ptr->m_lineEditFactory->removePropertyManager(itString.next());
+
+ QList<QtDatePropertyManager *> datePropertyManagers = qFindChildren<QtDatePropertyManager *>(manager);
+ QListIterator<QtDatePropertyManager *> itDate(datePropertyManagers);
+ while (itDate.hasNext())
+ d_ptr->m_dateEditFactory->removePropertyManager(itDate.next());
+
+ QList<QtTimePropertyManager *> timePropertyManagers = qFindChildren<QtTimePropertyManager *>(manager);
+ QListIterator<QtTimePropertyManager *> itTime(timePropertyManagers);
+ while (itTime.hasNext())
+ d_ptr->m_timeEditFactory->removePropertyManager(itTime.next());
+
+ QList<QtDateTimePropertyManager *> dateTimePropertyManagers = qFindChildren<QtDateTimePropertyManager *>(manager);
+ QListIterator<QtDateTimePropertyManager *> itDateTime(dateTimePropertyManagers);
+ while (itDateTime.hasNext())
+ d_ptr->m_dateTimeEditFactory->removePropertyManager(itDateTime.next());
+
+ QList<QtKeySequencePropertyManager *> keySequencePropertyManagers = qFindChildren<QtKeySequencePropertyManager *>(manager);
+ QListIterator<QtKeySequencePropertyManager *> itKeySequence(keySequencePropertyManagers);
+ while (itKeySequence.hasNext())
+ d_ptr->m_keySequenceEditorFactory->removePropertyManager(itKeySequence.next());
+
+ QList<QtCharPropertyManager *> charPropertyManagers = qFindChildren<QtCharPropertyManager *>(manager);
+ QListIterator<QtCharPropertyManager *> itChar(charPropertyManagers);
+ while (itChar.hasNext())
+ d_ptr->m_charEditorFactory->removePropertyManager(itChar.next());
+
+ QList<QtLocalePropertyManager *> localePropertyManagers = qFindChildren<QtLocalePropertyManager *>(manager);
+ QListIterator<QtLocalePropertyManager *> itLocale(localePropertyManagers);
+ while (itLocale.hasNext())
+ d_ptr->m_comboBoxFactory->removePropertyManager(itLocale.next()->subEnumPropertyManager());
+
+ QList<QtPointPropertyManager *> pointPropertyManagers = qFindChildren<QtPointPropertyManager *>(manager);
+ QListIterator<QtPointPropertyManager *> itPoint(pointPropertyManagers);
+ while (itPoint.hasNext())
+ d_ptr->m_spinBoxFactory->removePropertyManager(itPoint.next()->subIntPropertyManager());
+
+ QList<QtPointFPropertyManager *> pointFPropertyManagers = qFindChildren<QtPointFPropertyManager *>(manager);
+ QListIterator<QtPointFPropertyManager *> itPointF(pointFPropertyManagers);
+ while (itPointF.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itPointF.next()->subDoublePropertyManager());
+
+ QList<QtSizePropertyManager *> sizePropertyManagers = qFindChildren<QtSizePropertyManager *>(manager);
+ QListIterator<QtSizePropertyManager *> itSize(sizePropertyManagers);
+ while (itSize.hasNext())
+ d_ptr->m_spinBoxFactory->removePropertyManager(itSize.next()->subIntPropertyManager());
+
+ QList<QtSizeFPropertyManager *> sizeFPropertyManagers = qFindChildren<QtSizeFPropertyManager *>(manager);
+ QListIterator<QtSizeFPropertyManager *> itSizeF(sizeFPropertyManagers);
+ while (itSizeF.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itSizeF.next()->subDoublePropertyManager());
+
+ QList<QtRectPropertyManager *> rectPropertyManagers = qFindChildren<QtRectPropertyManager *>(manager);
+ QListIterator<QtRectPropertyManager *> itRect(rectPropertyManagers);
+ while (itRect.hasNext())
+ d_ptr->m_spinBoxFactory->removePropertyManager(itRect.next()->subIntPropertyManager());
+
+ QList<QtRectFPropertyManager *> rectFPropertyManagers = qFindChildren<QtRectFPropertyManager *>(manager);
+ QListIterator<QtRectFPropertyManager *> itRectF(rectFPropertyManagers);
+ while (itRectF.hasNext())
+ d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itRectF.next()->subDoublePropertyManager());
+
+ QList<QtColorPropertyManager *> colorPropertyManagers = qFindChildren<QtColorPropertyManager *>(manager);
+ QListIterator<QtColorPropertyManager *> itColor(colorPropertyManagers);
+ while (itColor.hasNext()) {
+ QtColorPropertyManager *manager = itColor.next();
+ d_ptr->m_colorEditorFactory->removePropertyManager(manager);
+ d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager());
+ }
+
+ QList<QtEnumPropertyManager *> enumPropertyManagers = qFindChildren<QtEnumPropertyManager *>(manager);
+ QListIterator<QtEnumPropertyManager *> itEnum(enumPropertyManagers);
+ while (itEnum.hasNext())
+ d_ptr->m_comboBoxFactory->removePropertyManager(itEnum.next());
+
+ QList<QtSizePolicyPropertyManager *> sizePolicyPropertyManagers = qFindChildren<QtSizePolicyPropertyManager *>(manager);
+ QListIterator<QtSizePolicyPropertyManager *> itSizePolicy(sizePolicyPropertyManagers);
+ while (itSizePolicy.hasNext()) {
+ QtSizePolicyPropertyManager *manager = itSizePolicy.next();
+ d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager());
+ d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager());
+ }
+
+ QList<QtFontPropertyManager *> fontPropertyManagers = qFindChildren<QtFontPropertyManager *>(manager);
+ QListIterator<QtFontPropertyManager *> itFont(fontPropertyManagers);
+ while (itFont.hasNext()) {
+ QtFontPropertyManager *manager = itFont.next();
+ d_ptr->m_fontEditorFactory->removePropertyManager(manager);
+ d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager());
+ d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager());
+ d_ptr->m_checkBoxFactory->removePropertyManager(manager->subBoolPropertyManager());
+ }
+
+ QList<QtCursorPropertyManager *> cursorPropertyManagers = qFindChildren<QtCursorPropertyManager *>(manager);
+ QListIterator<QtCursorPropertyManager *> itCursor(cursorPropertyManagers);
+ while (itCursor.hasNext())
+ d_ptr->m_cursorEditorFactory->removePropertyManager(itCursor.next());
+
+ QList<QtFlagPropertyManager *> flagPropertyManagers = qFindChildren<QtFlagPropertyManager *>(manager);
+ QListIterator<QtFlagPropertyManager *> itFlag(flagPropertyManagers);
+ while (itFlag.hasNext())
+ d_ptr->m_checkBoxFactory->removePropertyManager(itFlag.next()->subBoolPropertyManager());
+}
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+#include "moc_qtvariantproperty.cpp"
diff --git a/tools/shared/qtpropertybrowser/qtvariantproperty.h b/tools/shared/qtpropertybrowser/qtvariantproperty.h
new file mode 100644
index 0000000000..91397d8f43
--- /dev/null
+++ b/tools/shared/qtpropertybrowser/qtvariantproperty.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTVARIANTPROPERTY_H
+#define QTVARIANTPROPERTY_H
+
+#include "qtpropertybrowser.h"
+#include <QtCore/QVariant>
+#include <QtGui/QIcon>
+
+#if QT_VERSION >= 0x040400
+QT_BEGIN_NAMESPACE
+#endif
+
+typedef QMap<int, QIcon> QtIconMap;
+
+class QtVariantPropertyManager;
+
+class QtVariantProperty : public QtProperty
+{
+public:
+ ~QtVariantProperty();
+ QVariant value() const;
+ QVariant attributeValue(const QString &attribute) const;
+ int valueType() const;
+ int propertyType() const;
+
+ void setValue(const QVariant &value);
+ void setAttribute(const QString &attribute, const QVariant &value);
+protected:
+ QtVariantProperty(QtVariantPropertyManager *manager);
+private:
+ friend class QtVariantPropertyManager;
+ class QtVariantPropertyPrivate *d_ptr;
+};
+
+class QtVariantPropertyManager : public QtAbstractPropertyManager
+{
+ Q_OBJECT
+public:
+ QtVariantPropertyManager(QObject *parent = 0);
+ ~QtVariantPropertyManager();
+
+ virtual QtVariantProperty *addProperty(int propertyType, const QString &name = QString());
+
+ int propertyType(const QtProperty *property) const;
+ int valueType(const QtProperty *property) const;
+ QtVariantProperty *variantProperty(const QtProperty *property) const;
+
+ virtual bool isPropertyTypeSupported(int propertyType) const;
+ virtual int valueType(int propertyType) const;
+ virtual QStringList attributes(int propertyType) const;
+ virtual int attributeType(int propertyType, const QString &attribute) const;
+
+ virtual QVariant value(const QtProperty *property) const;
+ virtual QVariant attributeValue(const QtProperty *property, const QString &attribute) const;
+
+ static int enumTypeId();
+ static int flagTypeId();
+ static int groupTypeId();
+ static int iconMapTypeId();
+public Q_SLOTS:
+ virtual void setValue(QtProperty *property, const QVariant &val);
+ virtual void setAttribute(QtProperty *property,
+ const QString &attribute, const QVariant &value);
+Q_SIGNALS:
+ void valueChanged(QtProperty *property, const QVariant &val);
+ void attributeChanged(QtProperty *property,
+ const QString &attribute, const QVariant &val);
+protected:
+ virtual bool hasValue(const QtProperty *property) const;
+ QString valueText(const QtProperty *property) const;
+ QIcon valueIcon(const QtProperty *property) const;
+ virtual void initializeProperty(QtProperty *property);
+ virtual void uninitializeProperty(QtProperty *property);
+ virtual QtProperty *createProperty();
+private:
+ class QtVariantPropertyManagerPrivate *d_ptr;
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int))
+ Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, double))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double))
+ Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double))
+ Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, bool))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QString &))
+ Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegExp &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDate &))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QDate &, const QDate &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QTime &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDateTime &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QKeySequence &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QChar &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QLocale &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPoint &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPointF &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSize &))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSize &, const QSize &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizeF &))
+ Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRect &))
+ Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRect &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRectF &))
+ Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRectF &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QColor &))
+ Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, const QStringList &))
+ Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *, const QMap<int, QIcon> &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizePolicy &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QFont &))
+ Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QCursor &))
+ Q_PRIVATE_SLOT(d_func(), void slotFlagNamesChanged(QtProperty *, const QStringList &))
+
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))
+ Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, QtProperty *))
+ Q_DECLARE_PRIVATE(QtVariantPropertyManager)
+ Q_DISABLE_COPY(QtVariantPropertyManager)
+};
+
+class QtVariantEditorFactory : public QtAbstractEditorFactory<QtVariantPropertyManager>
+{
+ Q_OBJECT
+public:
+ QtVariantEditorFactory(QObject *parent = 0);
+ ~QtVariantEditorFactory();
+protected:
+ void connectPropertyManager(QtVariantPropertyManager *manager);
+ QWidget *createEditor(QtVariantPropertyManager *manager, QtProperty *property,
+ QWidget *parent);
+ void disconnectPropertyManager(QtVariantPropertyManager *manager);
+private:
+ class QtVariantEditorFactoryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtVariantEditorFactory)
+ Q_DISABLE_COPY(QtVariantEditorFactory)
+};
+
+#if QT_VERSION >= 0x040400
+QT_END_NAMESPACE
+#endif
+
+Q_DECLARE_METATYPE(QIcon)
+Q_DECLARE_METATYPE(QtIconMap)
+#endif
diff --git a/tools/shared/qttoolbardialog/images/back.png b/tools/shared/qttoolbardialog/images/back.png
new file mode 100644
index 0000000000..e58177f43c
--- /dev/null
+++ b/tools/shared/qttoolbardialog/images/back.png
Binary files differ
diff --git a/tools/shared/qttoolbardialog/images/down.png b/tools/shared/qttoolbardialog/images/down.png
new file mode 100644
index 0000000000..29d1d4439a
--- /dev/null
+++ b/tools/shared/qttoolbardialog/images/down.png
Binary files differ
diff --git a/tools/shared/qttoolbardialog/images/forward.png b/tools/shared/qttoolbardialog/images/forward.png
new file mode 100644
index 0000000000..34b91f09fa
--- /dev/null
+++ b/tools/shared/qttoolbardialog/images/forward.png
Binary files differ
diff --git a/tools/shared/qttoolbardialog/images/minus.png b/tools/shared/qttoolbardialog/images/minus.png
new file mode 100644
index 0000000000..d6f233d739
--- /dev/null
+++ b/tools/shared/qttoolbardialog/images/minus.png
Binary files differ
diff --git a/tools/shared/qttoolbardialog/images/plus.png b/tools/shared/qttoolbardialog/images/plus.png
new file mode 100644
index 0000000000..40df1134f8
--- /dev/null
+++ b/tools/shared/qttoolbardialog/images/plus.png
Binary files differ
diff --git a/tools/shared/qttoolbardialog/images/up.png b/tools/shared/qttoolbardialog/images/up.png
new file mode 100644
index 0000000000..e437312217
--- /dev/null
+++ b/tools/shared/qttoolbardialog/images/up.png
Binary files differ
diff --git a/tools/shared/qttoolbardialog/qttoolbardialog.cpp b/tools/shared/qttoolbardialog/qttoolbardialog.cpp
new file mode 100644
index 0000000000..f15c4bc8b7
--- /dev/null
+++ b/tools/shared/qttoolbardialog/qttoolbardialog.cpp
@@ -0,0 +1,1877 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qttoolbardialog.h"
+#include "ui_qttoolbardialog.h"
+
+#include <QtCore/QSet>
+#include <QtGui/QtEvents>
+#include <QtGui/QAction>
+#include <QtGui/QToolBar>
+#include <QtGui/QMainWindow>
+#include <QtGui/QHeaderView>
+#include <QtGui/QPushButton>
+
+QT_BEGIN_NAMESPACE
+
+class QtFullToolBarManagerPrivate;
+
+class QtFullToolBarManager : public QObject
+{
+ Q_OBJECT
+public:
+ QtFullToolBarManager(QObject *parent);
+ ~QtFullToolBarManager();
+
+ void setMainWindow(QMainWindow *mainWindow);
+ QMainWindow *mainWindow() const;
+
+ void addCategory(const QString &category);
+ bool hasCategory(const QString &category) const;
+ QStringList categories() const;
+ QList<QAction *> categoryActions(const QString &category) const;
+ QString actionCategory(QAction *action) const;
+
+ // only non-separator
+ void addAction(QAction *action, const QString &category);
+
+ void removeAction(QAction *action);
+
+ QSet<QAction *> actions() const;
+ bool isWidgetAction(QAction *action) const;
+
+ /*
+ Adds (registers) toolBar. Adds (registers) actions that already exists in toolBar.
+ Remembers toolbar and its actions as a default.
+ */
+ void addDefaultToolBar(QToolBar *toolBar, const QString &category);
+
+ void removeDefaultToolBar(QToolBar *toolBar);
+ // NULL on action list means separator.
+ QMap<QToolBar *, QList<QAction *> > defaultToolBars() const;
+ bool isDefaultToolBar(QToolBar *toolBar) const;
+
+ QToolBar *createToolBar(const QString &toolBarName);
+ void deleteToolBar(QToolBar *toolBar); // only those which were created, not added
+
+ QList<QAction *> actions(QToolBar *toolBar) const;
+
+ void setToolBars(const QMap<QToolBar *, QList<QAction *> > &actions);
+ void setToolBar(QToolBar *toolBar, const QList<QAction *> &actions);
+
+ QMap<QToolBar *, QList<QAction *> > toolBarsActions() const;
+ QByteArray saveState(int version = 0) const;
+ bool restoreState(const QByteArray &state, int version = 0);
+
+public slots:
+
+ void resetToolBar(QToolBar *toolBar);
+ void resetAllToolBars();
+
+signals:
+ void toolBarCreated(QToolBar *toolBar);
+ void toolBarRemoved(QToolBar *toolBar);
+
+ /*
+ If QToolBarWidgetAction was in another tool bar and is inserted into
+ this toolBar, toolBarChanged is first emitted for other toolbar - without
+ that action. (Another approach may be that user first must call setToolBar
+ without that action for old tool bar)
+ */
+ void toolBarChanged(QToolBar *toolBar, const QList<QAction *> &actions);
+
+private:
+ QtFullToolBarManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtFullToolBarManager)
+ Q_DISABLE_COPY(QtFullToolBarManager)
+};
+
+class QtFullToolBarManagerPrivate
+{
+ class QtFullToolBarManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtFullToolBarManager)
+
+public:
+
+ QToolBar *toolBarWidgetAction(QAction *action) const;
+ void removeWidgetActions(const QMap<QToolBar *, QList<QAction *> > &actions);
+
+ enum {
+ VersionMarker = 0xff,
+ ToolBarMarker = 0xfe,
+ CustomToolBarMarker = 0xfd,
+ };
+
+ void saveState(QDataStream &stream) const;
+ bool restoreState(QDataStream &stream) const;
+ QToolBar *findDefaultToolBar(const QString &objectName) const;
+ QAction *findAction(const QString &actionName) const;
+
+ QToolBar *toolBarByName(const QString &toolBarName) const;
+
+ QtFullToolBarManagerPrivate();
+
+ QMap<QString, QList<QAction *> > categoryToActions;
+ QMap<QAction *, QString> actionToCategory;
+
+ QSet<QAction *> allActions;
+ QMap<QAction *, QToolBar *> widgetActions;
+ QSet<QAction *> regularActions;
+ QMap<QAction *, QList<QToolBar *> > actionToToolBars;
+
+ QMap<QToolBar *, QList<QAction *> > toolBars;
+ QMap<QToolBar *, QList<QAction *> > toolBarsWithSeparators;
+ QMap<QToolBar *, QList<QAction *> > defaultToolBars;
+ QList<QToolBar *> customToolBars;
+
+ QMainWindow *theMainWindow;
+};
+
+
+
+
+QtFullToolBarManagerPrivate::QtFullToolBarManagerPrivate()
+ : theMainWindow(0)
+{
+}
+
+QToolBar *QtFullToolBarManagerPrivate::toolBarWidgetAction(QAction *action) const
+{
+ if (widgetActions.contains(action))
+ return widgetActions.value(action);
+ return 0;
+}
+
+void QtFullToolBarManagerPrivate::removeWidgetActions(const QMap<QToolBar *, QList<QAction *> >
+ &actions)
+{
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = actions.constBegin();
+ while (itToolBar != actions.constEnd()) {
+ QToolBar *toolBar = itToolBar.key();
+ QList<QAction *> newActions = toolBars.value(toolBar);
+ QList<QAction *> newActionsWithSeparators = toolBarsWithSeparators.value(toolBar);
+
+ QList<QAction *> removedActions;
+ QList<QAction *> actionList = itToolBar.value();
+ QListIterator<QAction *> itAction(actionList);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ if (newActions.contains(action) && toolBarWidgetAction(action) == toolBar) {
+ newActions.removeAll(action);
+ newActionsWithSeparators.removeAll(action);
+ removedActions.append(action);
+ }
+ }
+
+ //emit q_ptr->toolBarChanged(toolBar, newActions);
+
+ toolBars.insert(toolBar, newActions);
+ toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
+ QListIterator<QAction *> itRemovedAction(removedActions);
+ while (itRemovedAction.hasNext()) {
+ QAction *oldAction = itRemovedAction.next();
+ widgetActions.insert(oldAction, 0);
+ actionToToolBars[oldAction].removeAll(toolBar);
+ }
+
+ ++itToolBar;
+ }
+}
+
+void QtFullToolBarManagerPrivate::saveState(QDataStream &stream) const
+{
+ stream << (uchar) ToolBarMarker;
+ stream << defaultToolBars.size();
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar =
+ defaultToolBars.constBegin();
+ while (itToolBar != defaultToolBars.constEnd()) {
+ QToolBar *tb = itToolBar.key();
+ if (tb->objectName().isEmpty()) {
+ qWarning("QtToolBarManager::saveState(): 'objectName' not set for QToolBar "
+ "%p '%s', using 'windowTitle' instead",
+ tb, tb->windowTitle().toLocal8Bit().constData());
+ stream << tb->windowTitle();
+ } else {
+ stream << tb->objectName();
+ }
+
+ stream << toolBars[tb].size();
+ QListIterator<QAction *> itAction(toolBars[tb]);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+
+ if (action) {
+ if (action->objectName().isEmpty()) {
+ qWarning("QtToolBarManager::saveState(): 'objectName' not set for QAction "
+ "%p '%s', using 'text' instead",
+ action, action->text().toLocal8Bit().constData());
+ stream << action->text();
+ } else {
+ stream << action->objectName();
+ }
+ } else {
+ stream << QString();
+ }
+ }
+ ++itToolBar;
+ }
+
+
+ stream << (uchar) CustomToolBarMarker;
+ stream << toolBars.size() - defaultToolBars.size();
+ itToolBar = toolBars.constBegin();
+ while (itToolBar != toolBars.constEnd()) {
+ QToolBar *tb = itToolBar.key();
+ if (!defaultToolBars.contains(tb)) {
+ stream << tb->objectName();
+ stream << tb->windowTitle();
+
+ stream << toolBars[tb].size();
+ QListIterator<QAction *> itAction(toolBars[tb]);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+
+ if (action) {
+ if (action->objectName().isEmpty()) {
+ qWarning("QtToolBarManager::saveState(): 'objectName' not set for QAction "
+ "%p '%s', using 'text' instead",
+ action, action->text().toLocal8Bit().constData());
+ stream << action->text();
+ } else {
+ stream << action->objectName();
+ }
+ } else {
+ stream << QString();
+ }
+ }
+ }
+ ++itToolBar;
+ }
+}
+
+bool QtFullToolBarManagerPrivate::restoreState(QDataStream &stream) const
+{
+ uchar tmarker;
+ stream >> tmarker;
+ if (tmarker != ToolBarMarker)
+ return false;
+
+ int toolBars;
+ stream >> toolBars;
+ for (int i = 0; i < toolBars; i++) {
+ QString objectName;
+ stream >> objectName;
+ int actionCount;
+ stream >> actionCount;
+ QList<QAction *> actions;
+ for (int j = 0; j < actionCount; j++) {
+ QString actionName;
+ stream >> actionName;
+
+ if (actionName.isEmpty())
+ actions.append(0);
+ else {
+ QAction *action = findAction(actionName);
+ if (action)
+ actions.append(action);
+ }
+ }
+
+ QToolBar *toolBar = findDefaultToolBar(objectName);
+ if (toolBar)
+ q_ptr->setToolBar(toolBar, actions);
+ }
+
+
+
+ uchar ctmarker;
+ stream >> ctmarker;
+ if (ctmarker != CustomToolBarMarker)
+ return false;
+
+ QList<QToolBar *> oldCustomToolBars = customToolBars;
+
+ stream >> toolBars;
+ for (int i = 0; i < toolBars; i++) {
+ QString objectName;
+ QString toolBarName;
+ int actionCount;
+ stream >> objectName;
+ stream >> toolBarName;
+ stream >> actionCount;
+ QList<QAction *> actions;
+ for (int j = 0; j < actionCount; j++) {
+ QString actionName;
+ stream >> actionName;
+
+ if (actionName.isEmpty())
+ actions.append(0);
+ else {
+ QAction *action = findAction(actionName);
+ if (action)
+ actions.append(action);
+ }
+ }
+
+ QToolBar *toolBar = toolBarByName(objectName);
+ if (toolBar) {
+ toolBar->setWindowTitle(toolBarName);
+ oldCustomToolBars.removeAll(toolBar);
+ }
+ else
+ toolBar = q_ptr->createToolBar(toolBarName);
+ if (toolBar) {
+ toolBar->setObjectName(objectName);
+ q_ptr->setToolBar(toolBar, actions);
+ }
+ }
+ QListIterator<QToolBar *> itToolBar(oldCustomToolBars);
+ while (itToolBar.hasNext())
+ q_ptr->deleteToolBar(itToolBar.next());
+ return true;
+}
+
+QToolBar *QtFullToolBarManagerPrivate::findDefaultToolBar(const QString &objectName) const
+{
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar =
+ defaultToolBars.constBegin();
+ while (itToolBar != defaultToolBars.constEnd()) {
+ QToolBar *tb = itToolBar.key();
+ if (tb->objectName() == objectName)
+ return tb;
+
+ ++itToolBar;
+ }
+
+ qWarning("QtToolBarManager::restoreState(): cannot find a QToolBar named "
+ "'%s', trying to match using 'windowTitle' instead.",
+ objectName.toLocal8Bit().constData());
+
+ itToolBar = defaultToolBars.constBegin();
+ while (itToolBar != defaultToolBars.constEnd()) {
+ QToolBar *tb = itToolBar.key();
+ if (tb->windowTitle() == objectName)
+ return tb;
+
+ ++itToolBar;
+ }
+ qWarning("QtToolBarManager::restoreState(): cannot find a QToolBar with "
+ "matching 'windowTitle' (looking for '%s').",
+ objectName.toLocal8Bit().constData());
+
+ return 0;
+}
+
+QAction *QtFullToolBarManagerPrivate::findAction(const QString &actionName) const
+{
+ QSetIterator<QAction *> itAction(allActions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+
+ if (action->objectName() == actionName)
+ return action;
+ }
+ qWarning("QtToolBarManager::restoreState(): cannot find a QAction named "
+ "'%s', trying to match using 'text' instead.",
+ actionName.toLocal8Bit().constData());
+
+ itAction.toFront();
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+
+ if (action->text() == actionName)
+ return action;
+ }
+ qWarning("QtToolBarManager::restoreState(): cannot find a QAction with "
+ "matching 'text' (looking for '%s').",
+ actionName.toLocal8Bit().constData());
+
+ return 0;
+}
+
+QToolBar *QtFullToolBarManagerPrivate::toolBarByName(const QString &toolBarName) const
+{
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = toolBars.constBegin();
+ while (itToolBar != toolBars.constEnd()) {
+ QToolBar *toolBar = itToolBar.key();
+ if (toolBar->objectName() == toolBarName)
+ return toolBar;
+
+ ++itToolBar;
+ }
+ return 0;
+}
+
+//////////////////////////////
+
+QtFullToolBarManager::QtFullToolBarManager(QObject *parent)
+ : QObject(parent)
+{
+ d_ptr = new QtFullToolBarManagerPrivate;
+ d_ptr->q_ptr = this;
+}
+
+QtFullToolBarManager::~QtFullToolBarManager()
+{
+ delete d_ptr;
+}
+
+void QtFullToolBarManager::setMainWindow(QMainWindow *mainWindow)
+{
+ d_ptr->theMainWindow = mainWindow;
+}
+
+QMainWindow *QtFullToolBarManager::mainWindow() const
+{
+ return d_ptr->theMainWindow;
+}
+
+void QtFullToolBarManager::addCategory(const QString &category)
+{
+ d_ptr->categoryToActions[category] = QList<QAction *>();
+}
+
+bool QtFullToolBarManager::hasCategory(const QString &category) const
+{
+ return d_ptr->categoryToActions.contains(category);
+}
+
+QStringList QtFullToolBarManager::categories() const
+{
+ return d_ptr->categoryToActions.keys();
+}
+
+QList<QAction *> QtFullToolBarManager::categoryActions(const QString &category) const
+{
+ QMap<QString, QList<QAction *> >::ConstIterator it =
+ d_ptr->categoryToActions.find(category);
+ if (it != d_ptr->categoryToActions.constEnd())
+ return it.value();
+ return QList<QAction *>();
+}
+
+QString QtFullToolBarManager::actionCategory(QAction *action) const
+{
+ QMap<QAction *, QString>::ConstIterator it = d_ptr->actionToCategory.find(action);
+ if (it != d_ptr->actionToCategory.constEnd())
+ return it.value();
+ return QString();
+}
+
+void QtFullToolBarManager::addAction(QAction *action, const QString &category)
+{
+ if (!action)
+ return;
+ if (action->isSeparator())
+ return;
+ if (d_ptr->allActions.contains(action))
+ return;
+ if (QLatin1String(action->metaObject()->className()) ==
+ QLatin1String("QToolBarWidgetAction"))
+ d_ptr->widgetActions.insert(action, 0);
+ else
+ d_ptr->regularActions.insert(action);
+ d_ptr->allActions.insert(action);
+ d_ptr->categoryToActions[category].append(action);
+ d_ptr->actionToCategory[action] = category;
+}
+
+void QtFullToolBarManager::removeAction(QAction *action)
+{
+ if (!d_ptr->allActions.contains(action))
+ return;
+
+ QList<QToolBar *> toolBars = d_ptr->actionToToolBars[action];
+ QListIterator<QToolBar *> itToolBar(toolBars);
+ while (itToolBar.hasNext()) {
+ QToolBar *toolBar = itToolBar.next();
+
+ d_ptr->toolBars[toolBar].removeAll(action);
+ d_ptr->toolBarsWithSeparators[toolBar].removeAll(action);
+
+ toolBar->removeAction(action);
+ }
+
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator itDefault =
+ d_ptr->defaultToolBars.constBegin();
+ while (itDefault != d_ptr->defaultToolBars.constEnd()) {
+ if (itDefault.value().contains(action))
+ d_ptr->defaultToolBars[itDefault.key()].removeAll(action);
+
+ itDefault++;
+ }
+
+ d_ptr->allActions.remove(action);
+ d_ptr->widgetActions.remove(action);
+ d_ptr->regularActions.remove(action);
+ d_ptr->actionToToolBars.remove(action);
+
+ QString category = d_ptr->actionToCategory.value(action);
+ d_ptr->actionToCategory.remove(action);
+ d_ptr->categoryToActions[category].removeAll(action);
+
+ if (d_ptr->categoryToActions[category].isEmpty())
+ d_ptr->categoryToActions.remove(category);
+}
+
+QSet<QAction *> QtFullToolBarManager::actions() const
+{
+ return d_ptr->allActions;
+}
+
+bool QtFullToolBarManager::isWidgetAction(QAction *action) const
+{
+ if (d_ptr->widgetActions.contains(action))
+ return true;
+ return false;
+}
+
+void QtFullToolBarManager::addDefaultToolBar(QToolBar *toolBar, const QString &category)
+{
+ if (!toolBar)
+ return;
+ if (d_ptr->toolBars.contains(toolBar))
+ return;
+ // could be also checked if toolBar belongs to mainwindow
+
+ QList<QAction *> newActionsWithSeparators;
+ QList<QAction *> newActions;
+ QList<QAction *> actions = toolBar->actions();
+ QListIterator<QAction *> itAction(actions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ addAction(action, category);
+ if (d_ptr->widgetActions.contains(action))
+ d_ptr->widgetActions.insert(action, toolBar);
+ newActionsWithSeparators.append(action);
+ if (action->isSeparator())
+ action = 0;
+ else
+ d_ptr->actionToToolBars[action].append(toolBar);
+ newActions.append(action);
+ }
+ d_ptr->defaultToolBars.insert(toolBar, newActions);
+ //Below could be done by call setToolBar() if we want signal emission here.
+ d_ptr->toolBars.insert(toolBar, newActions);
+ d_ptr->toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
+}
+
+void QtFullToolBarManager::removeDefaultToolBar(QToolBar *toolBar)
+{
+ if (!d_ptr->defaultToolBars.contains(toolBar))
+ return;
+
+ QList<QAction *> defaultActions = d_ptr->defaultToolBars[toolBar];
+ setToolBar(toolBar, QList<QAction *>());
+ QListIterator<QAction *> itAction(defaultActions);
+ while (itAction.hasNext())
+ removeAction(itAction.next());
+
+ d_ptr->toolBars.remove(toolBar);
+ d_ptr->toolBarsWithSeparators.remove(toolBar);
+ d_ptr->defaultToolBars.remove(toolBar);
+
+ itAction.toFront();
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ if (action)
+ toolBar->insertAction(0, action);
+ else
+ toolBar->insertSeparator(0);
+ }
+}
+
+QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::defaultToolBars() const
+{
+ return d_ptr->defaultToolBars;
+}
+
+bool QtFullToolBarManager::isDefaultToolBar(QToolBar *toolBar) const
+{
+ if (d_ptr->defaultToolBars.contains(toolBar))
+ return true;
+ return false;
+}
+
+QToolBar *QtFullToolBarManager::createToolBar(const QString &toolBarName)
+{
+ if (!mainWindow())
+ return 0;
+ QToolBar *toolBar = new QToolBar(toolBarName, mainWindow());
+ int i = 1;
+ const QString prefix = QLatin1String("_Custom_Toolbar_");
+ QString name = QString(QLatin1String("%1%2")).arg(prefix).arg(i);
+ while (d_ptr->toolBarByName(name))
+ name = QString(QLatin1String("%1%2")).arg(prefix).arg(++i);
+ toolBar->setObjectName(name);
+ mainWindow()->addToolBar(toolBar);
+ d_ptr->customToolBars.append(toolBar);
+ d_ptr->toolBars.insert(toolBar, QList<QAction *>());
+ d_ptr->toolBarsWithSeparators.insert(toolBar, QList<QAction *>());
+ return toolBar;
+}
+
+void QtFullToolBarManager::deleteToolBar(QToolBar *toolBar)
+{
+ if (!d_ptr->toolBars.contains(toolBar))
+ return;
+ if (d_ptr->defaultToolBars.contains(toolBar))
+ return;
+ setToolBar(toolBar, QList<QAction *>());
+ d_ptr->customToolBars.removeAll(toolBar);
+ d_ptr->toolBars.remove(toolBar);
+ d_ptr->toolBarsWithSeparators.remove(toolBar);
+ delete toolBar;
+}
+
+QList<QAction *> QtFullToolBarManager::actions(QToolBar *toolBar) const
+{
+ if (d_ptr->toolBars.contains(toolBar))
+ return d_ptr->toolBars.value(toolBar);
+ return QList<QAction *>();
+}
+
+void QtFullToolBarManager::setToolBars(const QMap<QToolBar *, QList<QAction *> > &actions)
+{
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator it = actions.constBegin();
+ while (it != actions.constEnd()) {
+ setToolBar(it.key(), it.value());
+ ++it;
+ }
+}
+
+void QtFullToolBarManager::setToolBar(QToolBar *toolBar, const QList<QAction *> &actions)
+{
+ if (!toolBar)
+ return;
+ if (!d_ptr->toolBars.contains(toolBar))
+ return;
+
+ if (actions == d_ptr->toolBars[toolBar])
+ return;
+
+ QMap<QToolBar *, QList<QAction *> > toRemove;
+
+ QList<QAction *> newActions;
+ QListIterator<QAction *> itAction(actions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ if (!action || (!newActions.contains(action) && d_ptr->allActions.contains(action)))
+ newActions.append(action);
+
+ QToolBar *oldToolBar = d_ptr->toolBarWidgetAction(action);
+ if (oldToolBar && oldToolBar != toolBar)
+ toRemove[oldToolBar].append(action);
+ }
+
+ d_ptr->removeWidgetActions(toRemove);
+
+ QList<QAction *> oldActions = d_ptr->toolBarsWithSeparators.value(toolBar);
+ QListIterator<QAction *> itOldAction(oldActions);
+ while (itOldAction.hasNext()) {
+ QAction *action = itOldAction.next();
+ /*
+ When addDefaultToolBar() separator actions could be checked if they are
+ inserted in other toolbars - if yes then create new one.
+ */
+ if (d_ptr->toolBarWidgetAction(action) == toolBar)
+ d_ptr->widgetActions.insert(action, 0);
+ toolBar->removeAction(action);
+ if (action->isSeparator())
+ delete action;
+ else
+ d_ptr->actionToToolBars[action].removeAll(toolBar);
+ }
+
+ QList<QAction *> newActionsWithSeparators;
+ QListIterator<QAction *> itNewActions(newActions);
+ while (itNewActions.hasNext()) {
+ QAction *action = itNewActions.next();
+ QAction *newAction = 0;
+ if (!action)
+ newAction = toolBar->insertSeparator(0);
+ if (d_ptr->allActions.contains(action)) {
+ toolBar->insertAction(0, action);
+ newAction = action;
+ d_ptr->actionToToolBars[action].append(toolBar);
+ }
+ newActionsWithSeparators.append(newAction);
+ }
+ d_ptr->toolBars.insert(toolBar, newActions);
+ d_ptr->toolBarsWithSeparators.insert(toolBar, newActionsWithSeparators);
+}
+
+QMap<QToolBar *, QList<QAction *> > QtFullToolBarManager::toolBarsActions() const
+{
+ return d_ptr->toolBars;
+}
+
+void QtFullToolBarManager::resetToolBar(QToolBar *toolBar)
+{
+ if (!isDefaultToolBar(toolBar))
+ return;
+ setToolBar(toolBar, defaultToolBars().value(toolBar));
+}
+
+void QtFullToolBarManager::resetAllToolBars()
+{
+ setToolBars(defaultToolBars());
+ QList<QToolBar *> oldCustomToolBars = d_ptr->customToolBars;
+ QListIterator<QToolBar *> itToolBar(oldCustomToolBars);
+ while (itToolBar.hasNext()) {
+ deleteToolBar(itToolBar.next());
+ }
+}
+
+QByteArray QtFullToolBarManager::saveState(int version) const
+{
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ stream << QtFullToolBarManagerPrivate::VersionMarker;
+ stream << version;
+ d_ptr->saveState(stream);
+ return data;
+}
+
+bool QtFullToolBarManager::restoreState(const QByteArray &state, int version)
+{
+ QByteArray sd = state;
+ QDataStream stream(&sd, QIODevice::ReadOnly);
+ int marker, v;
+ stream >> marker;
+ stream >> v;
+ if (marker != QtFullToolBarManagerPrivate::VersionMarker || v != version)
+ return false;
+ return d_ptr->restoreState(stream);
+}
+
+
+class QtToolBarManagerPrivate
+{
+ class QtToolBarManager *q_ptr;
+ Q_DECLARE_PUBLIC(QtToolBarManager)
+public:
+ QtFullToolBarManager *manager;
+};
+
+//////////////////////////////////////
+
+/*! \class QtToolBarManager
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtToolBarManager class provides toolbar management for
+ main windows.
+
+ The QtToolBarManager is typically used with a QtToolBarDialog
+ which allows the user to customize the toolbars for a given main
+ window. The QtToolBarDialog class's functionality is controlled by
+ an instance of the QtToolBarManager class, and the main window is
+ specified using the QtToolBarManager class's setMainWindow()
+ function.
+
+ The currently specified main window can be retrieved using the
+ mainWindow() function.
+
+ The toolbar manager holds lists of the given main window's actions
+ and toolbars, and can add actions and toolbars to these
+ lists using the addAction() and addToolBar() functions
+ respectively. The actions can in addition be categorized
+ acccording to the user's preferences. The toolbar manager can also
+ remove custom actions and toolbars using the removeAction() and
+ removeToolBar() functions.
+
+ Finally, the QtToolBarManager is able to save the customized state
+ of its toolbars using the saveState() function as well as restore
+ the toolbars' saved state using restoreState() function.
+
+ \sa QtToolBarDialog
+*/
+
+/*!
+ Creates a toolbar manager with the given \a parent.
+*/
+QtToolBarManager::QtToolBarManager(QObject *parent)
+ : QObject(parent)
+{
+ d_ptr = new QtToolBarManagerPrivate;
+ d_ptr->q_ptr = this;
+
+ d_ptr->manager = new QtFullToolBarManager(this);
+}
+
+/*!
+ Destroys the toolbar manager.
+*/
+QtToolBarManager::~QtToolBarManager()
+{
+ delete d_ptr;
+}
+
+/*!
+ Sets the main window upon which the toolbar manager operates, to
+ be the given \a mainWindow.
+*/
+void QtToolBarManager::setMainWindow(QMainWindow *mainWindow)
+{
+ d_ptr->manager->setMainWindow(mainWindow);
+}
+
+/*!
+ Returns the main window associated this toolbar manager.
+*/
+QMainWindow *QtToolBarManager::mainWindow() const
+{
+ return d_ptr->manager->mainWindow();
+}
+
+/*!
+ Adds the given \a action to the given \a category in the manager's
+ list of actions. If the \a category doesn't exist it is created.
+ Only non separator actions can be added. If the action is already
+ added to the list, the function doesn't do anything.
+
+ \sa removeAction()
+*/
+void QtToolBarManager::addAction(QAction *action, const QString &category)
+{
+ d_ptr->manager->addAction(action, category);
+}
+
+/*!
+ Removes the specified \a action from the manager's list of
+ actions. The action is also removed from all the registered
+ toolbars. If the specified \a action is the only action in its
+ category, that category is removed as well.
+
+ \sa addAction()
+*/
+void QtToolBarManager::removeAction(QAction *action)
+{
+ d_ptr->manager->removeAction(action);
+}
+
+/*!
+ Adds the given \a toolBar to the manager's toolbar list.
+
+ All the \a toolBar's actions are automatically added to the given
+ \a category in the manager's list of actions if they're not
+ already there. The manager remembers which toolbar the actions
+ belonged to, so, when the \a toolBar is removed, its actions will
+ be removed as well.
+
+ Custom toolbars are created with the main window returned by
+ the mainWindow() function, as its parent.
+
+ \sa removeToolBar()
+*/
+void QtToolBarManager::addToolBar(QToolBar *toolBar, const QString &category)
+{
+ d_ptr->manager->addDefaultToolBar(toolBar, category);
+}
+
+/*!
+ Removes the specified \a toolBar from the manager's list. All the
+ actions that existed in the specified \a toolBar when it was
+ added are removed as well.
+
+ \sa addToolBar()
+*/
+void QtToolBarManager::removeToolBar(QToolBar *toolBar)
+{
+ d_ptr->manager->removeDefaultToolBar(toolBar);
+}
+
+/*!
+ Returns the manager's toolbar list.
+*/
+QList<QToolBar *> QtToolBarManager::toolBars() const
+{
+ return d_ptr->manager->toolBarsActions().keys();
+}
+
+/*
+void QtToolBarManager::resetToolBar(QToolBar *toolBar)
+{
+ d_ptr->manager->resetToolBar(toolBar);
+}
+
+void QtToolBarManager::resetAllToolBars()
+{
+ d_ptr->manager->resetAllToolBars();
+}
+*/
+
+/*!
+ Saves the state of the toolbar manager's toolbars. The \a version
+ number is stored as part of the data.
+
+ Identifies all the QToolBar and QAction objects by their object
+ name property. Ensure that this property is unique for each
+ QToolBar and QAction that you add using the QtToolBarManager.
+
+ Returns an identifier for the state which can be passed along with
+ the version number to the restoreState() function to restore the
+ saved state.
+
+ \sa restoreState()
+*/
+QByteArray QtToolBarManager::saveState(int version) const
+{
+ return d_ptr->manager->saveState(version);
+}
+
+/*!
+ Restores the saved state of the toolbar manager's toolbars. The
+ \a version number is compared with the version number of the
+ stored \a state.
+
+ Returns true if the version numbers are matching and the toolbar
+ manager's state is restored; otherwise the toolbar manager's state
+ is left unchanged and the function returns false.
+
+ Note that the state of the toolbar manager's toolbars should be
+ restored before restoring the state of the main window's toolbars
+ and dockwidgets using the QMainWindow::restoreState() function. In
+ that way the restoreState() function can create the custom
+ toolbars before the QMainWindow::restoreState() function restores
+ the custom toolbars' positions.
+
+ \sa saveState()
+*/
+bool QtToolBarManager::restoreState(const QByteArray &state, int version)
+{
+ return d_ptr->manager->restoreState(state, version);
+}
+
+//////////////////////
+
+class ToolBarItem {
+public:
+ ToolBarItem() : tb(0) {}
+ ToolBarItem(QToolBar *toolBar) : tb(toolBar) {}
+ ToolBarItem(QToolBar *toolBar, const QString &toolBarName)
+ : tb(toolBar), tbName(toolBarName) {}
+ ToolBarItem(const QString &toolBarName) : tb(0), tbName(toolBarName) {}
+ QToolBar *toolBar() const
+ { return tb; }
+ void setToolBar(QToolBar *toolBar)
+ { tb = toolBar; }
+ QString toolBarName() const
+ { return tbName; }
+ void setToolBarName(const QString &toolBarName)
+ { tbName = toolBarName; }
+private:
+ QToolBar *tb;
+ QString tbName;
+};
+
+class QtToolBarDialogPrivate {
+ QtToolBarDialog *q_ptr;
+ Q_DECLARE_PUBLIC(QtToolBarDialog)
+public:
+ QtToolBarDialogPrivate()
+ : toolBarManager(0),
+ currentAction(0),
+ currentToolBar(0)
+ { }
+
+ ToolBarItem *createItem(QToolBar *toolBar);
+ ToolBarItem *createItem(const QString &toolBarName);
+ void deleteItem(ToolBarItem *item);
+
+ void newClicked();
+ void removeClicked();
+ void defaultClicked();
+ void okClicked();
+ void applyClicked();
+ void cancelClicked();
+ void upClicked();
+ void downClicked();
+ void leftClicked();
+ void rightClicked();
+ void renameClicked();
+ void toolBarRenamed(QListWidgetItem *item);
+ void currentActionChanged(QTreeWidgetItem *current);
+ void currentToolBarChanged(QListWidgetItem *current);
+ void currentToolBarActionChanged(QListWidgetItem *current);
+
+ void removeToolBar(ToolBarItem *item);
+ bool isDefaultToolBar(ToolBarItem *item) const;
+ void setButtons();
+ void clearOld();
+ void fillNew();
+ QtFullToolBarManager *toolBarManager;
+ QMap<ToolBarItem *, QList<QAction *> > currentState;
+ QMap<QToolBar *, ToolBarItem *> toolBarItems;
+ QSet<ToolBarItem *> createdItems;
+ QSet<ToolBarItem *> removedItems;
+
+ QSet<ToolBarItem *> allToolBarItems;
+
+ // static
+ QTreeWidgetItem *currentAction;
+ QMap<QAction *, QTreeWidgetItem *> actionToItem;
+ QMap<QTreeWidgetItem *, QAction *> itemToAction;
+
+ // dynamic
+ ToolBarItem *currentToolBar;
+ QMap<ToolBarItem *, QListWidgetItem *> toolBarToItem;
+ QMap<QListWidgetItem *, ToolBarItem *> itemToToolBar;
+
+ // dynamic
+ QMap<QAction *, QListWidgetItem *> actionToCurrentItem;
+ QMap<QListWidgetItem *, QAction *> currentItemToAction;
+
+ QMap<QAction *, ToolBarItem *> widgetActionToToolBar;
+ QMap<ToolBarItem *, QSet<QAction *> > toolBarToWidgetActions;
+
+ QString separatorText;
+ Ui::QtToolBarDialog ui;
+};
+
+ToolBarItem *QtToolBarDialogPrivate::createItem(QToolBar *toolBar)
+{
+ if (!toolBar)
+ return 0;
+ ToolBarItem *item = new ToolBarItem(toolBar, toolBar->windowTitle());
+ allToolBarItems.insert(item);
+ return item;
+}
+
+ToolBarItem *QtToolBarDialogPrivate::createItem(const QString &toolBarName)
+{
+ ToolBarItem *item = new ToolBarItem(toolBarName);
+ allToolBarItems.insert(item);
+ return item;
+}
+
+void QtToolBarDialogPrivate::deleteItem(ToolBarItem *item)
+{
+ if (!allToolBarItems.contains(item))
+ return;
+ allToolBarItems.remove(item);
+ delete item;
+}
+
+void QtToolBarDialogPrivate::clearOld()
+{
+ ui.actionTree->clear();
+ ui.toolBarList->clear();
+ ui.currentToolBarList->clear();
+ ui.removeButton->setEnabled(false);
+ ui.newButton->setEnabled(false);
+ ui.upButton->setEnabled(false);
+ ui.downButton->setEnabled(false);
+ ui.leftButton->setEnabled(false);
+ ui.rightButton->setEnabled(false);
+
+ actionToItem.clear();
+ itemToAction.clear();
+ toolBarToItem.clear();
+ itemToToolBar.clear();
+ actionToCurrentItem.clear();
+ currentItemToAction.clear();
+ widgetActionToToolBar.clear();
+ toolBarToWidgetActions.clear();
+
+ toolBarItems.clear();
+ currentState.clear();
+ createdItems.clear();
+ removedItems.clear();
+ QSetIterator<ToolBarItem *> itItem(allToolBarItems);
+ while (itItem.hasNext())
+ delete itItem.next();
+ allToolBarItems.clear();
+
+ currentToolBar = 0;
+ currentAction = 0;
+}
+
+void QtToolBarDialogPrivate::fillNew()
+{
+ if (!toolBarManager)
+ return;
+
+ QTreeWidgetItem *item = new QTreeWidgetItem(ui.actionTree);
+ item->setText(0, separatorText);
+ ui.actionTree->setCurrentItem(item);
+ currentAction = item;
+ actionToItem.insert(0, item);
+ itemToAction.insert(item, 0);
+ QStringList categories = toolBarManager->categories();
+ QStringListIterator itCategory(categories);
+ while (itCategory.hasNext()) {
+ QString category = itCategory.next();
+ QTreeWidgetItem *categoryItem = new QTreeWidgetItem(ui.actionTree);
+ categoryItem->setText(0, category);
+ QList<QAction *> actions = toolBarManager->categoryActions(category);
+ QListIterator<QAction *> itAction(actions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ item = new QTreeWidgetItem(categoryItem);
+ item->setText(0, action->text());
+ item->setIcon(0, action->icon());
+ item->setTextAlignment(0, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
+ actionToItem.insert(action, item);
+ itemToAction.insert(item, action);
+ if (toolBarManager->isWidgetAction(action)) {
+ item->setData(0, Qt::TextColorRole, QColor(Qt::blue));
+ widgetActionToToolBar.insert(action, 0);
+ }
+ item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
+ }
+ ui.actionTree->setItemExpanded(categoryItem, true);
+ }
+ //ui.actionTree->sortItems(0, Qt::AscendingOrder);
+
+ QMap<QToolBar *, QList<QAction *> > toolBars = toolBarManager->toolBarsActions();
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator it = toolBars.constBegin();
+ while (it != toolBars.constEnd()) {
+ QToolBar *toolBar = it.key();
+ ToolBarItem *tbItem = createItem(toolBar);
+ toolBarItems.insert(toolBar, tbItem);
+ QListWidgetItem *item = new QListWidgetItem(toolBar->windowTitle(),
+ ui.toolBarList);
+ toolBarToItem.insert(tbItem, item);
+ itemToToolBar.insert(item, tbItem);
+ QList<QAction *> actions = it.value();
+ QListIterator<QAction *> itAction(actions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ if (toolBarManager->isWidgetAction(action)) {
+ widgetActionToToolBar.insert(action, tbItem);
+ toolBarToWidgetActions[tbItem].insert(action);
+ }
+ }
+ currentState.insert(tbItem, actions);
+ if (it == toolBars.constBegin())
+ ui.toolBarList->setCurrentItem(item);
+ if (isDefaultToolBar(tbItem))
+ item->setData(Qt::TextColorRole, QColor(Qt::darkGreen));
+ else
+ item->setFlags(item->flags() | Qt::ItemIsEditable);
+
+ ++it;
+ }
+ ui.toolBarList->sortItems();
+ setButtons();
+}
+
+bool QtToolBarDialogPrivate::isDefaultToolBar(ToolBarItem *item) const
+{
+ if (!item)
+ return false;
+ if (!item->toolBar())
+ return false;
+ return toolBarManager->isDefaultToolBar(item->toolBar());
+}
+
+void QtToolBarDialogPrivate::setButtons()
+{
+ bool newEnabled = false;
+ bool removeEnabled = false;
+ bool renameEnabled = false;
+ bool upEnabled = false;
+ bool downEnabled = false;
+ bool leftEnabled = false;
+ bool rightEnabled = false;
+
+ if (toolBarManager) {
+ newEnabled = true;
+ removeEnabled = !isDefaultToolBar(currentToolBar);
+ renameEnabled = removeEnabled;
+ QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+ if (currentToolBarAction) {
+ int row = ui.currentToolBarList->row(currentToolBarAction);
+ upEnabled = row > 0;
+ downEnabled = row < ui.currentToolBarList->count() - 1;
+ leftEnabled = true;
+ }
+ if (currentAction && currentToolBar)
+ rightEnabled = true;
+ }
+ ui.newButton->setEnabled(newEnabled);
+ ui.removeButton->setEnabled(removeEnabled);
+ ui.renameButton->setEnabled(renameEnabled);
+ ui.upButton->setEnabled(upEnabled);
+ ui.downButton->setEnabled(downEnabled);
+ ui.leftButton->setEnabled(leftEnabled);
+ ui.rightButton->setEnabled(rightEnabled);
+}
+
+void QtToolBarDialogPrivate::newClicked()
+{
+ QString toolBarName = QtToolBarDialog::tr("Custom Toolbar"); // = QInputDialog::getString();
+ // produce unique name
+ ToolBarItem *item = createItem(toolBarName);
+ currentState.insert(item, QList<QAction *>());
+ createdItems.insert(item);
+ QListWidgetItem *i = new QListWidgetItem(toolBarName, ui.toolBarList);
+ i->setFlags(i->flags() | Qt::ItemIsEditable);
+ ui.toolBarList->setCurrentItem(i);
+ itemToToolBar.insert(i, item);
+ toolBarToItem.insert(item, i);
+ ui.toolBarList->sortItems();
+ ui.toolBarList->setCurrentItem(i);
+ currentToolBarChanged(i);
+ renameClicked();
+}
+
+void QtToolBarDialogPrivate::removeToolBar(ToolBarItem *item)
+{
+ if (!item)
+ return;
+ if (item->toolBar() && toolBarManager->isDefaultToolBar(item->toolBar()))
+ return;
+ if (!toolBarToItem.contains(item))
+ return;
+ QListWidgetItem *i = toolBarToItem.value(item);
+ bool wasCurrent = false;
+ if (i == ui.toolBarList->currentItem())
+ wasCurrent = true;
+ int row = ui.toolBarList->row(i);
+ QMap<ToolBarItem *, QSet<QAction *> >::ConstIterator itToolBar =
+ toolBarToWidgetActions.find(item);
+ if (itToolBar != toolBarToWidgetActions.constEnd()) {
+ QSet<QAction *> actions = itToolBar.value();
+ QSetIterator<QAction *> itAction(actions);
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ widgetActionToToolBar.insert(action, 0);
+ }
+ toolBarToWidgetActions.remove(item);
+ }
+
+ currentState.remove(item);
+ createdItems.remove(item);
+ toolBarToItem.remove(item);
+ itemToToolBar.remove(i);
+ delete i;
+ if (item->toolBar())
+ removedItems.insert(item);
+ else
+ deleteItem(item);
+ if (wasCurrent) {
+ if (row == ui.toolBarList->count())
+ row--;
+ if (row < 0)
+ ;
+ else
+ ui.toolBarList->setCurrentRow(row);
+ }
+ setButtons();
+}
+
+void QtToolBarDialogPrivate::removeClicked()
+{
+ QListWidgetItem *i = ui.toolBarList->currentItem();
+ if (!i)
+ return;
+ ToolBarItem *item = itemToToolBar.value(i);
+ removeToolBar(item);
+}
+
+void QtToolBarDialogPrivate::defaultClicked()
+{
+ QMap<QToolBar *, QList<QAction *> > defaultToolBars = toolBarManager->defaultToolBars();
+ QMap<QToolBar *, QList<QAction *> >::ConstIterator itToolBar = defaultToolBars.constBegin();
+ while (itToolBar != defaultToolBars.constEnd()) {
+ QToolBar *toolBar = itToolBar.key();
+ ToolBarItem *toolBarItem = toolBarItems.value(toolBar);
+
+ if (toolBarToWidgetActions.contains(toolBarItem)) {
+ QSetIterator<QAction *> itAction(toolBarToWidgetActions.value(toolBarItem));
+ while (itAction.hasNext())
+ widgetActionToToolBar.insert(itAction.next(), 0);
+ toolBarToWidgetActions.remove(toolBarItem);
+ }
+
+ currentState.remove(toolBarItem);
+
+ QListIterator<QAction *> itAction(itToolBar.value());
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ if (toolBarManager->isWidgetAction(action)) {
+ ToolBarItem *otherToolBar = widgetActionToToolBar.value(action);
+ if (otherToolBar) {
+ toolBarToWidgetActions[otherToolBar].remove(action);
+ currentState[otherToolBar].removeAll(action);
+ }
+ widgetActionToToolBar.insert(action, toolBarItem);
+ toolBarToWidgetActions[toolBarItem].insert(action);
+ }
+ }
+ currentState.insert(toolBarItem, itToolBar.value());
+
+ ++itToolBar;
+ }
+ currentToolBarChanged(toolBarToItem.value(currentToolBar));
+
+ QList<ToolBarItem *> toolBars = currentState.keys();
+ QListIterator<ToolBarItem *> itTb(toolBars);
+ while (itTb.hasNext())
+ removeToolBar(itTb.next());
+}
+
+void QtToolBarDialogPrivate::okClicked()
+{
+ applyClicked();
+ q_ptr->accept();
+}
+
+void QtToolBarDialogPrivate::applyClicked()
+{
+ QMap<ToolBarItem *, QList<QAction *> > toolBars = currentState;
+ QMap<ToolBarItem *, QList<QAction *> >::ConstIterator itToolBar = toolBars.constBegin();
+ while (itToolBar != toolBars.constEnd()) {
+ ToolBarItem *item = itToolBar.key();
+ QToolBar *toolBar = item->toolBar();
+ if (toolBar) {
+ toolBarManager->setToolBar(toolBar, itToolBar.value());
+ toolBar->setWindowTitle(item->toolBarName());
+ }
+
+ ++itToolBar;
+ }
+
+ QSet<ToolBarItem *> toRemove = removedItems;
+ QSetIterator<ToolBarItem *> itRemove(toRemove);
+ while (itRemove.hasNext()) {
+ ToolBarItem *item = itRemove.next();
+ QToolBar *toolBar = item->toolBar();
+ removedItems.remove(item);
+ currentState.remove(item);
+ deleteItem(item);
+ if (toolBar)
+ toolBarManager->deleteToolBar(toolBar);
+ }
+
+ QSet<ToolBarItem *> toCreate = createdItems;
+ QSetIterator<ToolBarItem *> itCreate(toCreate);
+ while (itCreate.hasNext()) {
+ ToolBarItem *item = itCreate.next();
+ QString toolBarName = item->toolBarName();
+ createdItems.remove(item);
+ QList<QAction *> actions = currentState.value(item);
+ QToolBar *toolBar = toolBarManager->createToolBar(toolBarName);
+ item->setToolBar(toolBar);
+ toolBarManager->setToolBar(toolBar, actions);
+ }
+}
+
+void QtToolBarDialogPrivate::upClicked()
+{
+ QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+ if (!currentToolBarAction)
+ return;
+ int row = ui.currentToolBarList->row(currentToolBarAction);
+ if (row == 0)
+ return;
+ ui.currentToolBarList->takeItem(row);
+ int newRow = row - 1;
+ ui.currentToolBarList->insertItem(newRow, currentToolBarAction);
+ QList<QAction *> actions = currentState.value(currentToolBar);
+ QAction *action = actions.at(row);
+ actions.removeAt(row);
+ actions.insert(newRow, action);
+ currentState.insert(currentToolBar, actions);
+ ui.currentToolBarList->setCurrentItem(currentToolBarAction);
+ setButtons();
+}
+
+void QtToolBarDialogPrivate::downClicked()
+{
+ QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+ if (!currentToolBarAction)
+ return;
+ int row = ui.currentToolBarList->row(currentToolBarAction);
+ if (row == ui.currentToolBarList->count() - 1)
+ return;
+ ui.currentToolBarList->takeItem(row);
+ int newRow = row + 1;
+ ui.currentToolBarList->insertItem(newRow, currentToolBarAction);
+ QList<QAction *> actions = currentState.value(currentToolBar);
+ QAction *action = actions.at(row);
+ actions.removeAt(row);
+ actions.insert(newRow, action);
+ currentState.insert(currentToolBar, actions);
+ ui.currentToolBarList->setCurrentItem(currentToolBarAction);
+ setButtons();
+}
+
+void QtToolBarDialogPrivate::leftClicked()
+{
+ QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+ if (!currentToolBarAction)
+ return;
+ int row = ui.currentToolBarList->row(currentToolBarAction);
+ currentState[currentToolBar].removeAt(row);
+ QAction *action = currentItemToAction.value(currentToolBarAction);
+ if (widgetActionToToolBar.contains(action)) {
+ ToolBarItem *item = widgetActionToToolBar.value(action);
+ if (item == currentToolBar) { // have to be
+ toolBarToWidgetActions[item].remove(action);
+ if (toolBarToWidgetActions[item].empty())
+ toolBarToWidgetActions.remove(item);
+ }
+ widgetActionToToolBar.insert(action, 0);
+ }
+ if (action)
+ actionToCurrentItem.remove(action);
+ currentItemToAction.remove(currentToolBarAction);
+ delete currentToolBarAction;
+ if (row == ui.currentToolBarList->count())
+ row--;
+ if (row >= 0) {
+ QListWidgetItem *item = ui.currentToolBarList->item(row);
+ ui.currentToolBarList->setCurrentItem(item);
+ }
+ setButtons();
+}
+
+void QtToolBarDialogPrivate::rightClicked()
+{
+ if (!currentAction)
+ return;
+ if (!currentToolBar)
+ return;
+ QListWidgetItem *currentToolBarAction = ui.currentToolBarList->currentItem();
+
+ QAction *action = itemToAction.value(currentAction);
+ QListWidgetItem *item = 0;
+ if (action) {
+ if (currentState[currentToolBar].contains(action)) {
+ item = actionToCurrentItem.value(action);
+ if (item == currentToolBarAction)
+ return;
+ int row = ui.currentToolBarList->row(item);
+ ui.currentToolBarList->takeItem(row);
+ currentState[currentToolBar].removeAt(row);
+ // only reorder here
+ } else {
+ item = new QListWidgetItem(action->text());
+ item->setIcon(action->icon());
+ item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
+ currentItemToAction.insert(item, action);
+ actionToCurrentItem.insert(action, item);
+ if (widgetActionToToolBar.contains(action)) {
+ item->setData(Qt::TextColorRole, QColor(Qt::blue));
+ ToolBarItem *toolBar = widgetActionToToolBar.value(action);
+ if (toolBar) {
+ currentState[toolBar].removeAll(action);
+ toolBarToWidgetActions[toolBar].remove(action);
+ if (toolBarToWidgetActions[toolBar].empty())
+ toolBarToWidgetActions.remove(toolBar);
+ }
+ widgetActionToToolBar.insert(action, currentToolBar);
+ toolBarToWidgetActions[currentToolBar].insert(action);
+ }
+ }
+ } else {
+ item = new QListWidgetItem(separatorText);
+ currentItemToAction.insert(item, 0);
+ }
+
+ int row = ui.currentToolBarList->count();
+ if (currentToolBarAction) {
+ row = ui.currentToolBarList->row(currentToolBarAction) + 1;
+ }
+ ui.currentToolBarList->insertItem(row, item);
+ currentState[currentToolBar].insert(row, action);
+ ui.currentToolBarList->setCurrentItem(item);
+
+ setButtons();
+}
+
+void QtToolBarDialogPrivate::renameClicked()
+{
+ if (!currentToolBar)
+ return;
+
+ QListWidgetItem *item = toolBarToItem.value(currentToolBar);
+ ui.toolBarList->editItem(item);
+}
+
+void QtToolBarDialogPrivate::toolBarRenamed(QListWidgetItem *item)
+{
+ if (!currentToolBar)
+ return;
+
+ ToolBarItem *tbItem = itemToToolBar.value(item);
+ if (!tbItem)
+ return;
+ tbItem->setToolBarName(item->text());
+ //ui.toolBarList->sortItems();
+}
+
+void QtToolBarDialogPrivate::currentActionChanged(QTreeWidgetItem *current)
+{
+ if (itemToAction.contains(current))
+ currentAction = current;
+ else
+ currentAction = NULL;
+ setButtons();
+}
+
+void QtToolBarDialogPrivate::currentToolBarChanged(QListWidgetItem *current)
+{
+ currentToolBar = itemToToolBar.value(current);
+ ui.currentToolBarList->clear();
+ actionToCurrentItem.clear();
+ currentItemToAction.clear();
+ setButtons();
+ if (!currentToolBar) {
+ return;
+ }
+ QList<QAction *> actions = currentState.value(currentToolBar);
+ QListIterator<QAction *> itAction(actions);
+ QListWidgetItem *first = 0;
+ while (itAction.hasNext()) {
+ QAction *action = itAction.next();
+ QString actionName = separatorText;
+ if (action)
+ actionName = action->text();
+ QListWidgetItem *item = new QListWidgetItem(actionName, ui.currentToolBarList);
+ if (action) {
+ item->setIcon(action->icon());
+ item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic);
+ actionToCurrentItem.insert(action, item);
+ if (widgetActionToToolBar.contains(action))
+ item->setData(Qt::TextColorRole, QColor(Qt::blue));
+ }
+ currentItemToAction.insert(item, action);
+ if (!first)
+ first = item;
+ }
+ if (first)
+ ui.currentToolBarList->setCurrentItem(first);
+}
+
+void QtToolBarDialogPrivate::currentToolBarActionChanged(QListWidgetItem *)
+{
+ setButtons();
+}
+
+void QtToolBarDialogPrivate::cancelClicked()
+{
+ // just nothing
+ q_ptr->reject();
+}
+
+//////////////////////
+/*
+class FeedbackItemDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ FeedbackItemDelegate(QObject *parent = 0) : QItemDelegate(parent) { }
+
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex & index) const;
+ virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+};
+
+void FeedbackItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if ()
+ painter->save();
+ QRect r = option.rect;
+ float yCentral = r.height() / 2.0;
+ float margin = 2.0;
+ float arrowWidth = 5.0;
+ float width = 20;
+ qDebug("rect: x %d, y %d, w %d, h %d", r.x(), r.y(), r.width(), r.height());
+ QLineF lineBase(0.0 + margin, r.y() + yCentral, width - margin, r.y() + yCentral);
+ QLineF lineArrowLeft(width - margin - arrowWidth, r.y() + yCentral - arrowWidth,
+ width - margin, r.y() + yCentral);
+ QLineF lineArrowRight(width - margin - arrowWidth, r.y() + yCentral + arrowWidth,
+ width - margin, r.y() + yCentral);
+ painter->drawLine(lineBase);
+ painter->drawLine(lineArrowLeft);
+ painter->drawLine(lineArrowRight);
+ painter->translate(QPoint(width, 0));
+ QItemDelegate::paint(painter, option, index);
+ painter->restore();
+}
+
+QSize FeedbackItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ //return QItemDelegate::sizeHint(option, index);
+ QSize s = QItemDelegate::sizeHint(option, index);
+ s.setWidth(s.width() - 20);
+ return s;
+}
+
+class QtToolBarListWidget : public QListWidget
+{
+ Q_OBJECT
+public:
+ QtToolBarListWidget(QWidget *parent) : QListWidget(parent), actionDrag(false) {}
+
+protected:
+ void startDrag(Qt::DropActions supportedActions);
+
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event);
+ void dragLeaveEvent(QDragLeaveEvent *);
+ void dropEvent(QDropEvent *event);
+
+ void setDragAction(const QString *action) { actionName = action; }
+private:
+ QPersistentModelIndex lastDropIndicator;
+ QString actionName;
+ bool actionDrag;
+};
+
+void QtToolBarListWidget::startDrag(Qt::DropActions supportedActions)
+{
+ QListWidgetItem *item = currentItem();
+ if (item) {
+ actionName = QString();
+ emit aboutToDrag(item);
+ if (!actionName.isEmpty()) {
+ QDrag *drag = new QDrag(this);
+ QMimeData *data = new QMimeData;
+ data->setData("action", actionName.toLocal8Bit().constData());
+ drag->setMimeData(data);
+ drag->start(supportedActions);
+ }
+ }
+}
+
+void QtToolBarListWidget::dragEnterEvent(QDragEnterEvent *event)
+{
+ const QMimeData *mime = event->mimeData();
+ actionDrag = mime->hasFormat("action");
+ if (actionDrag)
+ event->accept();
+ else
+ event->ignore();
+}
+
+void QtToolBarListWidget::dragMoveEvent(QDragMoveEvent *event)
+{
+ event->ignore();
+ if (actionDrag) {
+ QPoint p = event->pos();
+ QListWidgetItem *item = itemAt(p);
+ Indicator indic = QtToolBarListWidget::None;
+ if (item) {
+ QRect rect = visualItemRect(item);
+ if (p.y() - rect.top() < rect.height() / 2)
+ indic = QtToolBarListWidget::Above;
+ else
+ indic = QtToolBarListWidget::Below;
+ }
+ setIndicator(item, indic);
+ event->accept();
+ }
+}
+
+void QtToolBarListWidget::dragLeaveEvent(QDragLeaveEvent *)
+{
+ if (actionDrag) {
+ actionDrag = false;
+ setIndicator(item, QtToolBarListWidget::None);
+ }
+}
+
+void QtToolBarListWidget::dropEvent(QDropEvent *event)
+{
+ if (actionDrag) {
+ QListWidgetItem *item = indicatorItem();
+ Indicator indic = indicator();
+ QByteArray array = event->mimeData()->data("action");
+ QDataStream stream(&array, QIODevice::ReadOnly);
+ QString action;
+ stream >> action;
+ emit actionDropped(action, item, );
+
+ actionDrag = false;
+ setIndicator(item, QtToolBarListWidget::None);
+ }
+}
+*/
+
+/*! \class QtToolBarDialog
+ \internal
+ \inmodule QtDesigner
+ \since 4.4
+
+ \brief The QtToolBarDialog class provides a dialog for customizing
+ toolbars.
+
+ QtToolBarDialog allows the user to customize the toolbars for a
+ given main window.
+
+ \image qttoolbardialog.png
+
+ The dialog lets the users add, rename and remove custom toolbars.
+ Note that built-in toolbars are marked with a green color, and
+ cannot be removed or renamed.
+
+ The users can also add and remove actions from the toolbars. An
+ action can be added to many toolbars, but a toolbar can only
+ contain one instance of each action. Actions that contains a
+ widget are marked with a blue color in the list of actions, and
+ can only be added to one single toolbar.
+
+ Finally, the users can add separators to the toolbars.
+
+ The original toolbars can be restored by clicking the \gui
+ {Restore all} button. All custom toolbars will then be removed,
+ and all built-in toolbars will be restored to their original state.
+
+ The QtToolBarDialog class's functionality is controlled by an
+ instance of the QtToolBarManager class, and the main window is
+ specified using the QtToolBarManager::setMainWindow() function.
+
+ All you need to do to use QtToolBarDialog is to specify an
+ QtToolBarManager instance and call the QDialog::exec() slot:
+
+ \snippet doc/src/snippets/code/tools_shared_qttoolbardialog_qttoolbardialog.cpp 0
+
+ \sa QtToolBarManager
+*/
+
+/*!
+ Creates a toolbar dialog with the given \a parent and the specified
+ window \a flags.
+*/
+QtToolBarDialog::QtToolBarDialog(QWidget *parent, Qt::WindowFlags flags)
+ : QDialog(parent, flags)
+{
+ d_ptr = new QtToolBarDialogPrivate;
+ d_ptr->q_ptr = this;
+ d_ptr->ui.setupUi(this);
+ d_ptr->separatorText = tr("< S E P A R A T O R >");
+
+ d_ptr->ui.actionTree->setColumnCount(1);
+ d_ptr->ui.actionTree->setRootIsDecorated(false);
+ d_ptr->ui.actionTree->header()->hide();
+
+ d_ptr->ui.upButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/up.png")));
+ d_ptr->ui.downButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/down.png")));
+ d_ptr->ui.leftButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/back.png")));
+ d_ptr->ui.rightButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/forward.png")));
+ d_ptr->ui.newButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/plus.png")));
+ d_ptr->ui.removeButton->setIcon(QIcon(QLatin1String(":/trolltech/qttoolbardialog/images/minus.png")));
+
+ connect(d_ptr->ui.newButton, SIGNAL(clicked()), this, SLOT(newClicked()));
+ connect(d_ptr->ui.removeButton, SIGNAL(clicked()), this, SLOT(removeClicked()));
+ connect(d_ptr->ui.renameButton, SIGNAL(clicked()), this, SLOT(renameClicked()));
+ connect(d_ptr->ui.upButton, SIGNAL(clicked()), this, SLOT(upClicked()));
+ connect(d_ptr->ui.downButton, SIGNAL(clicked()), this, SLOT(downClicked()));
+ connect(d_ptr->ui.leftButton, SIGNAL(clicked()), this, SLOT(leftClicked()));
+ connect(d_ptr->ui.rightButton, SIGNAL(clicked()), this, SLOT(rightClicked()));
+
+ connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), this, SLOT(defaultClicked()));
+ connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(okClicked()));
+ connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyClicked()));
+ connect(d_ptr->ui.buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(cancelClicked()));
+
+ connect(d_ptr->ui.actionTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
+ this, SLOT(currentActionChanged(QTreeWidgetItem *)));
+ connect(d_ptr->ui.toolBarList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+ this, SLOT(currentToolBarChanged(QListWidgetItem *)));
+ connect(d_ptr->ui.currentToolBarList,
+ SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+ this, SLOT(currentToolBarActionChanged(QListWidgetItem *)));
+
+ connect(d_ptr->ui.actionTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+ this, SLOT(rightClicked()));
+ connect(d_ptr->ui.currentToolBarList, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
+ this, SLOT(leftClicked()));
+ connect(d_ptr->ui.toolBarList, SIGNAL(itemChanged(QListWidgetItem *)),
+ this, SLOT(toolBarRenamed(QListWidgetItem *)));
+}
+
+/*!
+ Destroys the toolbar dialog.
+*/
+QtToolBarDialog::~QtToolBarDialog()
+{
+ d_ptr->clearOld();
+ delete d_ptr;
+}
+
+/*!
+ Connects the toolbar dialog to the given \a toolBarManager. Then,
+ when exec() is called, the toolbar dialog will operate using the
+ given \a toolBarManager.
+*/
+void QtToolBarDialog::setToolBarManager(QtToolBarManager *toolBarManager)
+{
+ if (d_ptr->toolBarManager == toolBarManager->d_ptr->manager)
+ return;
+ if (isVisible())
+ d_ptr->clearOld();
+ d_ptr->toolBarManager = toolBarManager->d_ptr->manager;
+ if (isVisible())
+ d_ptr->fillNew();
+}
+
+/*!
+ \reimp
+*/
+void QtToolBarDialog::showEvent(QShowEvent *event)
+{
+ if (!event->spontaneous())
+ d_ptr->fillNew();
+}
+
+/*!
+ \reimp
+*/
+void QtToolBarDialog::hideEvent(QHideEvent *event)
+{
+ if (!event->spontaneous())
+ d_ptr->clearOld();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qttoolbardialog.cpp"
+#include "qttoolbardialog.moc"
diff --git a/tools/shared/qttoolbardialog/qttoolbardialog.h b/tools/shared/qttoolbardialog/qttoolbardialog.h
new file mode 100644
index 0000000000..879b437e81
--- /dev/null
+++ b/tools/shared/qttoolbardialog/qttoolbardialog.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt Designer. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QTTOOLBARDIALOG_H
+#define QTTOOLBARDIALOG_H
+
+#include <QtGui/QDialog>
+
+QT_BEGIN_NAMESPACE
+
+class QMainWindow;
+class QAction;
+class QToolBar;
+
+class QtToolBarManagerPrivate;
+
+class QtToolBarManager : public QObject
+{
+ Q_OBJECT
+public:
+
+ QtToolBarManager(QObject *parent = 0);
+ ~QtToolBarManager();
+
+ void setMainWindow(QMainWindow *mainWindow);
+ QMainWindow *mainWindow() const;
+
+ void addAction(QAction *action, const QString &category);
+ void removeAction(QAction *action);
+
+ void addToolBar(QToolBar *toolBar, const QString &category);
+ void removeToolBar(QToolBar *toolBar);
+
+ QList<QToolBar *> toolBars() const;
+
+ QByteArray saveState(int version = 0) const;
+ bool restoreState(const QByteArray &state, int version = 0);
+
+private:
+
+ friend class QtToolBarDialog;
+ QtToolBarManagerPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtToolBarManager)
+ Q_DISABLE_COPY(QtToolBarManager)
+};
+
+class QtToolBarDialogPrivate;
+
+class QtToolBarDialog : public QDialog
+{
+ Q_OBJECT
+public:
+
+ QtToolBarDialog(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ ~QtToolBarDialog();
+
+ void setToolBarManager(QtToolBarManager *toolBarManager);
+
+protected:
+
+ void showEvent(QShowEvent *event);
+ void hideEvent(QHideEvent *event);
+
+private:
+
+ QtToolBarDialogPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(QtToolBarDialog)
+ Q_DISABLE_COPY(QtToolBarDialog)
+
+ Q_PRIVATE_SLOT(d_func(), void newClicked())
+ Q_PRIVATE_SLOT(d_func(), void removeClicked())
+ Q_PRIVATE_SLOT(d_func(), void defaultClicked())
+ Q_PRIVATE_SLOT(d_func(), void okClicked())
+ Q_PRIVATE_SLOT(d_func(), void applyClicked())
+ Q_PRIVATE_SLOT(d_func(), void cancelClicked())
+ Q_PRIVATE_SLOT(d_func(), void upClicked())
+ Q_PRIVATE_SLOT(d_func(), void downClicked())
+ Q_PRIVATE_SLOT(d_func(), void leftClicked())
+ Q_PRIVATE_SLOT(d_func(), void rightClicked())
+ Q_PRIVATE_SLOT(d_func(), void renameClicked())
+ Q_PRIVATE_SLOT(d_func(), void toolBarRenamed(QListWidgetItem *))
+ Q_PRIVATE_SLOT(d_func(), void currentActionChanged(QTreeWidgetItem *))
+ Q_PRIVATE_SLOT(d_func(), void currentToolBarChanged(QListWidgetItem *))
+ Q_PRIVATE_SLOT(d_func(), void currentToolBarActionChanged(QListWidgetItem *))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/shared/qttoolbardialog/qttoolbardialog.pri b/tools/shared/qttoolbardialog/qttoolbardialog.pri
new file mode 100644
index 0000000000..5aca44757f
--- /dev/null
+++ b/tools/shared/qttoolbardialog/qttoolbardialog.pri
@@ -0,0 +1,6 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+SOURCES += $$PWD/qttoolbardialog.cpp
+HEADERS += $$PWD/qttoolbardialog.h
+FORMS += $$PWD/qttoolbardialog.ui
+RESOURCES += $$PWD/qttoolbardialog.qrc
diff --git a/tools/shared/qttoolbardialog/qttoolbardialog.qrc b/tools/shared/qttoolbardialog/qttoolbardialog.qrc
new file mode 100644
index 0000000000..ce0336682e
--- /dev/null
+++ b/tools/shared/qttoolbardialog/qttoolbardialog.qrc
@@ -0,0 +1,10 @@
+<RCC version="1.0">
+ <qresource prefix="/trolltech/qttoolbardialog">
+ <file>images/up.png</file>
+ <file>images/down.png</file>
+ <file>images/forward.png</file>
+ <file>images/back.png</file>
+ <file>images/plus.png</file>
+ <file>images/minus.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/shared/qttoolbardialog/qttoolbardialog.ui b/tools/shared/qttoolbardialog/qttoolbardialog.ui
new file mode 100644
index 0000000000..c4ad934f80
--- /dev/null
+++ b/tools/shared/qttoolbardialog/qttoolbardialog.ui
@@ -0,0 +1,207 @@
+<ui version="4.0" >
+ <class>QtToolBarDialog</class>
+ <widget class="QDialog" name="QtToolBarDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>583</width>
+ <height>508</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Customize Toolbars</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="3" row="1" column="0" >
+ <widget class="QTreeWidget" name="actionTree" >
+ <column>
+ <property name="text" >
+ <string>1</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Actions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2" >
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Toolbars</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="newButton" >
+ <property name="toolTip" >
+ <string>Add new toolbar</string>
+ </property>
+ <property name="text" >
+ <string>New</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="removeButton" >
+ <property name="toolTip" >
+ <string>Remove selected toolbar</string>
+ </property>
+ <property name="text" >
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="renameButton" >
+ <property name="toolTip" >
+ <string>Rename toolbar</string>
+ </property>
+ <property name="text" >
+ <string>Rename</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="1" >
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QToolButton" name="upButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Move action up</string>
+ </property>
+ <property name="text" >
+ <string>Up</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="leftButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Remove action from toolbar</string>
+ </property>
+ <property name="text" >
+ <string>&lt;-</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="rightButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Add action to toolbar</string>
+ </property>
+ <property name="text" >
+ <string>-></string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="downButton" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Minimum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="toolTip" >
+ <string>Move action down</string>
+ </property>
+ <property name="text" >
+ <string>Down</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>29</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="2" >
+ <widget class="QListWidget" name="currentToolBarList" />
+ </item>
+ <item row="2" column="1" colspan="2" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Current Toolbar Actions</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2" >
+ <widget class="QListWidget" name="toolBarList" />
+ </item>
+ <item row="5" column="0" colspan="3" >
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>newButton</tabstop>
+ <tabstop>removeButton</tabstop>
+ <tabstop>renameButton</tabstop>
+ <tabstop>toolBarList</tabstop>
+ <tabstop>upButton</tabstop>
+ <tabstop>leftButton</tabstop>
+ <tabstop>rightButton</tabstop>
+ <tabstop>downButton</tabstop>
+ <tabstop>currentToolBarList</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tools/tools.pro b/tools/tools.pro
new file mode 100644
index 0000000000..ffc5d63217
--- /dev/null
+++ b/tools/tools.pro
@@ -0,0 +1,30 @@
+TEMPLATE = subdirs
+
+no-png {
+ message("Some graphics-related tools are unavailable without PNG support")
+} else {
+ SUBDIRS += assistant \
+ pixeltool \
+ porting \
+ qtestlib
+ contains(QT_EDITION, Console) {
+ SUBDIRS += designer/src/uitools # Linguist depends on this
+ } else {
+ SUBDIRS += designer
+ }
+ SUBDIRS += linguist
+ wince*: SUBDIRS = qtestlib designer
+ unix:!mac:!embedded:contains(QT_CONFIG, qt3support):SUBDIRS += qtconfig
+ win32:!wince*:!contains(QT_EDITION, OpenSource|Console):SUBDIRS += activeqt
+}
+
+mac {
+ SUBDIRS += macdeployqt
+}
+
+contains(QT_CONFIG, dbus):SUBDIRS += qdbus
+!wince*:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns
+embedded: SUBDIRS += makeqpf
+
+CONFIG+=ordered
+QTDIR_build:REQUIRES = "contains(QT_CONFIG, full-config)"
diff --git a/tools/xmlpatterns/main.cpp b/tools/xmlpatterns/main.cpp
new file mode 100644
index 0000000000..ceb5f75f2b
--- /dev/null
+++ b/tools/xmlpatterns/main.cpp
@@ -0,0 +1,386 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Patternist project on Trolltech Labs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDir>
+#include <QtCore/QtDebug>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QtCore/QStringList>
+#include <QtCore/QTextCodec>
+#include <QtCore/QTextStream>
+#include <QtCore/QUrl>
+#include <QtCore/QVariant>
+#include <QtCore/QVector>
+
+#include <QtXmlPatterns/QXmlFormatter>
+#include <QtXmlPatterns/QXmlItem>
+#include <QtXmlPatterns/QXmlQuery>
+#include <QtXmlPatterns/QXmlSerializer>
+
+#include "private/qautoptr_p.h"
+#include "qapplicationargument_p.h"
+#include "qapplicationargumentparser_p.h"
+#include "qcoloringmessagehandler_p.h"
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+/* Needed for opening stdout with _fdopen & friends. io.h seems to not be
+ * needed on MinGW though. */
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#include "main.h"
+
+QT_USE_NAMESPACE
+
+/* The two Q_DECLARE_METATYPE macros must appear before the code
+ * on a couple of HPUX platforms. */
+
+/*!
+ \internal
+ \since 4.4
+ Represents the name and value found in "-param name=value".
+ */
+typedef QPair<QString, QString> Parameter;
+Q_DECLARE_METATYPE(Parameter);
+
+/*!
+ \internal
+ \since 4.4
+ For the -output switch.
+ */
+Q_DECLARE_METATYPE(QIODevice *);
+
+/*!
+ \class PatternistApplicationParser
+ \brief Subclass to handle -param name=value
+ \internal
+ \since 4.4
+ \reentrant
+ */
+class PatternistApplicationParser : public QApplicationArgumentParser
+{
+public:
+ inline PatternistApplicationParser(int argc, char **argv,
+ const QXmlNamePool &np) : QApplicationArgumentParser(argc, argv)
+ , m_namePool(np)
+#ifdef Q_OS_WIN
+ , m_stdout(0)
+#endif
+ {
+ }
+
+#ifdef Q_OS_WIN
+ virtual ~PatternistApplicationParser()
+ {
+ /* QFile::~QFile() nor QFile::close() frees the handle when
+ * we use QFile::open() so we have to do it manually.
+ *
+ * "If stream is NULL, the invalid parameter handler is invoked," so
+ * lets try to avoid that. */
+ if(m_stdout)
+ fclose(m_stdout);
+ }
+#endif
+
+protected:
+ virtual QVariant convertToValue(const QApplicationArgument &arg,
+ const QString &input) const
+ {
+ if(arg.name() == QLatin1String("param"))
+ {
+ const int assign = input.indexOf(QLatin1Char('='));
+
+ if(assign == -1)
+ {
+ message(QXmlPatternistCLI::tr("Each binding must contain an equal sign."));
+ return QVariant();
+ }
+
+ const QString name(input.left(assign));
+ const QString value(input.mid(assign + 1));
+
+ if(!QXmlName::isNCName(name))
+ {
+ message(QXmlPatternistCLI::tr("The variable name must be a valid NCName, which %1 isn't.").arg(name));
+ return QVariant();
+ }
+
+ /* The value.isNull() check ensures we can bind variables whose value is an empty string. */
+ return qVariantFromValue(Parameter(name, value.isNull() ? QString(QLatin1String("")) : value ));
+ }
+ else if(arg.name() == QLatin1String("output"))
+ {
+ QFile *const f = new QFile(input);
+
+ if(f->open(QIODevice::WriteOnly))
+ return qVariantFromValue(static_cast<QIODevice *>(f));
+ else
+ {
+ message(QXmlPatternistCLI::tr("Failed to open file %1 for writing: %2").arg(f->fileName(), f->errorString()));
+ return QVariant();
+ }
+ }
+ else if(arg.name() == QLatin1String("initial-template"))
+ {
+ const QXmlName name(QXmlName::fromClarkName(input, m_namePool));
+ if(name.isNull())
+ {
+ message(QXmlPatternistCLI::tr("%1 is an invalid Clark Name").arg(input));
+ return QVariant();
+ }
+ else
+ return qVariantFromValue(name);
+ }
+ else
+ return QApplicationArgumentParser::convertToValue(arg, input);
+ }
+
+ virtual QString typeToName(const QApplicationArgument &argument) const
+ {
+ if(argument.name() == QLatin1String("param"))
+ return QLatin1String("name=value");
+ else if(argument.name() == QLatin1String("output"))
+ return QLatin1String("local file");
+ else
+ return QApplicationArgumentParser::typeToName(argument);
+ }
+
+ virtual QVariant defaultValue(const QApplicationArgument &argument) const
+ {
+ if(argument.name() == QLatin1String("output"))
+ {
+ QFile *const out = new QFile();
+
+#ifdef Q_OS_WIN
+ /* If we don't open stdout in "binary" mode on Windows, it will translate
+ * 0xA into 0xD 0xA. See Trolltech task 173619, for an example. */
+ _setmode(_fileno(stdout), _O_BINARY);
+ m_stdout = QT_WA_INLINE(_wfdopen(_fileno(stdout), L"wb"),_fdopen(_fileno(stdout), "wb"));
+ out->open(m_stdout, QIODevice::WriteOnly);
+#else
+ out->open(stdout, QIODevice::WriteOnly);
+#endif
+
+ return qVariantFromValue(static_cast<QIODevice *>(out));
+ }
+ else
+ return QApplicationArgumentParser::defaultValue(argument);
+ }
+
+private:
+ QXmlNamePool m_namePool;
+#ifdef Q_OS_WIN
+ mutable FILE * m_stdout;
+#endif
+};
+
+static inline QUrl finalizeURI(const QApplicationArgumentParser &parser,
+ const QApplicationArgument &isURI,
+ const QApplicationArgument &arg)
+{
+ QUrl userURI;
+ {
+ const QString stringURI(parser.value(arg).toString());
+
+ if(parser.has(isURI))
+ userURI = QUrl::fromEncoded(stringURI.toLatin1());
+ else
+ userURI = QUrl::fromLocalFile(stringURI);
+ }
+
+ return QUrl::fromLocalFile(QDir::current().absolutePath() + QLatin1Char('/')).resolved(userURI);
+}
+
+int main(int argc, char **argv)
+{
+ enum ExitCode
+ {
+ /**
+ * We start from 2, because QApplicationArgumentParser
+ * uses 1.
+ */
+ QueryFailure = 2,
+ StdOutFailure
+ };
+
+ const QCoreApplication app(argc, argv);
+ QCoreApplication::setApplicationName(QLatin1String("xmlpatterns"));
+
+ QXmlNamePool namePool;
+ PatternistApplicationParser parser(argc, argv, namePool);
+ parser.setApplicationDescription(QLatin1String("A tool for running XQuery queries."));
+ parser.setApplicationVersion(QLatin1String("0.1"));
+
+ QApplicationArgument param(QLatin1String("param"),
+ QXmlPatternistCLI::tr("Binds an external variable. The value is directly available using the variable reference: $name."),
+ qMetaTypeId<Parameter>());
+ param.setMaximumOccurrence(-1);
+ parser.addArgument(param);
+
+ const QApplicationArgument noformat(QLatin1String("no-format"),
+ QXmlPatternistCLI::tr("By default output is formatted for readability. When specified, strict serialization is performed."));
+ parser.addArgument(noformat);
+
+ const QApplicationArgument isURI(QLatin1String("is-uri"),
+ QXmlPatternistCLI::tr("If specified, all filenames on the command line are interpreted as URIs instead of a local filenames."));
+ parser.addArgument(isURI);
+
+ const QApplicationArgument initialTemplateName(QLatin1String("initial-template"),
+ QXmlPatternistCLI::tr("The name of the initial template to call as a Clark Name."),
+ QVariant::String);
+ parser.addArgument(initialTemplateName);
+
+ /* The temporary object is required to compile with g++ 3.3. */
+ QApplicationArgument queryURI = QApplicationArgument(QLatin1String("query/stylesheet"),
+ QXmlPatternistCLI::tr("A local filename pointing to the query to run. If the name ends with .xsl it's assumed "
+ "to be an XSL-T stylesheet. If it ends with .xq, it's assumed to be an XQuery query. (In "
+ "other cases it's also assumed to be an XQuery query, but that interpretation may "
+ "change in a future release of Qt.)"),
+ QVariant::String);
+ queryURI.setMinimumOccurrence(1);
+ queryURI.setNameless(true);
+ parser.addArgument(queryURI);
+
+ QApplicationArgument focus = QApplicationArgument(QLatin1String("focus"),
+ QXmlPatternistCLI::tr("The document to use as focus. Mandatory "
+ "in case a stylesheet is used. This option is "
+ "also affected by the is-uris option."),
+ QVariant::String);
+ focus.setMinimumOccurrence(0);
+ focus.setNameless(true);
+ parser.addArgument(focus);
+
+ QApplicationArgument output(QLatin1String("output"),
+ QXmlPatternistCLI::tr("A local file to which the output should be written. "
+ "The file is overwritten, or if not exist, created. "
+ "If absent, stdout is used."),
+ qMetaTypeId<QIODevice *>());
+ parser.addArgument(output);
+
+ if(!parser.parse())
+ return parser.exitCode();
+
+ /* Get the query URI. */
+ const QUrl effectiveURI(finalizeURI(parser, isURI, queryURI));
+
+ QXmlQuery::QueryLanguage lang;
+
+ if(effectiveURI.toString().endsWith(QLatin1String(".xsl")))
+ lang = QXmlQuery::XSLT20;
+ else
+ lang = QXmlQuery::XQuery10;
+
+ if(lang == QXmlQuery::XQuery10 && parser.has(initialTemplateName))
+ {
+ parser.message(QXmlPatternistCLI::tr("An initial template name cannot be specified when running an XQuery."));
+ return QApplicationArgumentParser::ParseError;
+ }
+
+ QXmlQuery query(lang, namePool);
+
+ query.setInitialTemplateName(qVariantValue<QXmlName>(parser.value(initialTemplateName)));
+
+ /* Bind external variables. */
+ {
+ const QVariantList parameters(parser.values(param));
+ const int len = parameters.count();
+
+ /* For tracking duplicates. */
+ QSet<QString> usedParameters;
+
+ for(int i = 0; i < len; ++i)
+ {
+ const Parameter p(qVariantValue<Parameter>(parameters.at(i)));
+
+ if(usedParameters.contains(p.first))
+ {
+ parser.message(QXmlPatternistCLI::tr("Each parameter must be unique, %1 is specified at least twice.").arg(p.first));
+ return QApplicationArgumentParser::ParseError;
+ }
+ else
+ {
+ usedParameters.insert(p.first);
+ query.bindVariable(p.first, QXmlItem(p.second));
+ }
+ }
+ }
+
+ if(parser.has(focus))
+ {
+ if(!query.setFocus(finalizeURI(parser, isURI, focus)))
+ return QueryFailure;
+ }
+ else if(lang == QXmlQuery::XSLT20 && !parser.has(initialTemplateName))
+ {
+ parser.message(QXmlPatternistCLI::tr("When a stylesheet is used, a "
+ "document must be specified as a focus, or an "
+ "initial template name must be specified, or both."));
+ return QApplicationArgumentParser::ParseError;
+ }
+
+ query.setQuery(effectiveURI);
+
+ const QPatternist::AutoPtr<QIODevice> outDevice(qVariantValue<QIODevice *>(parser.value(output)));
+ Q_ASSERT(outDevice);
+ Q_ASSERT(outDevice->isWritable());
+
+ if(query.isValid())
+ {
+ typedef QPatternist::AutoPtr<QAbstractXmlReceiver> RecPtr;
+ RecPtr receiver;
+
+ if(parser.has(noformat))
+ receiver = RecPtr(new QXmlSerializer(query, outDevice.data()));
+ else
+ receiver = RecPtr(new QXmlFormatter(query, outDevice.data()));
+
+ const bool success = query.evaluateTo(receiver.data());
+
+ if(success)
+ return parser.exitCode();
+ else
+ return QueryFailure;
+ }
+ else
+ return QueryFailure;
+}
+
diff --git a/tools/xmlpatterns/main.h b/tools/xmlpatterns/main.h
new file mode 100644
index 0000000000..eaef3bbb60
--- /dev/null
+++ b/tools/xmlpatterns/main.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * ** * ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ * **
+ * ** This file is part of the Patternist project on Trolltech Labs. * **
+ * ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ * **
+ * ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * **
+ * ****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_main_h
+#define Patternist_main_h
+
+#include <QCoreApplication>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QXmlPatternistCLI
+{
+public:
+ Q_DECLARE_TR_FUNCTIONS(QXmlPatternistCLI)
+private:
+ inline QXmlPatternistCLI();
+ Q_DISABLE_COPY(QXmlPatternistCLI)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/xmlpatterns/qapplicationargument.cpp b/tools/xmlpatterns/qapplicationargument.cpp
new file mode 100644
index 0000000000..e88d5f8eda
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargument.cpp
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QHash>
+#include <QString>
+
+#include "qapplicationargument_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QApplicationArgument
+ \brief The QApplicationArgument class is a declared of a command line
+ argument for QApplicationArgumentParser.
+ \reentrant
+ \internal
+ \since 4.4
+
+ QApplicationArgument describes a valid command line argument,
+ by having a set of characteristics:
+
+ \table
+ \header
+ \o Characteristic
+ \o Functions
+ \row
+ \o A name. For instance, "backend"
+ \o setName() and name()
+ \row
+ \o A description, for human consumption.
+ \o setDescription() and description()
+ \row
+ \o How many times the argument can occur. For instance, whether the argument is optional or not.
+ \o setMinimumOccurrence() & minimumOccurrence(), setMaximumOccurrence() & maximumOccurrence()
+ \row
+ \o The type of the argument's value, if it has one. For instance, \c int or \c bool.
+ \o setType() and type()
+ \row
+ \o The value that should be used in case the argument isn't used.
+ \o setDefaultValue() and defaultValue()
+ \endtable
+
+ \sa QApplicationArgumentParser
+ */
+
+class QApplicationArgumentPrivate
+{
+public:
+ inline QApplicationArgumentPrivate(const QString &newName,
+ const QString &desc,
+ const int newType) : name(newName)
+ , description(desc)
+ , type(newType)
+ , minimum(0)
+ , maximum(1)
+ , isNameless(false)
+ {
+ }
+
+ QString name;
+ QString description;
+ int type;
+ QVariant defaultValue;
+ int minimum;
+ int maximum;
+ bool isNameless;
+};
+
+/*!
+ Constructs an invalid QApplicationArgument instance.
+ */
+QApplicationArgument::QApplicationArgument() : d_ptr(new QApplicationArgumentPrivate(QString(), QString(), QVariant::Invalid))
+{
+}
+
+/*!
+ Constructs an QApplicationArgument instance that is a copy of \a other.
+ */
+QApplicationArgument::QApplicationArgument(const QApplicationArgument &other) : d_ptr(new QApplicationArgumentPrivate(*other.d_ptr))
+{
+}
+
+/*!
+ Destructs this QApplicationArgument instance.
+ */
+QApplicationArgument::~QApplicationArgument()
+{
+ delete d_ptr;
+}
+
+/*!
+ Constructs an argument that has the name \a name and is of type
+ \a aType.
+
+ Calling this constructor is equivalent to calling setName() and setType()
+ on a default constructed QApplicationArgument instance.
+
+ \sa setName(), setType()
+ */
+QApplicationArgument::QApplicationArgument(const QString &name,
+ const QString &description,
+ int aType) : d_ptr(new QApplicationArgumentPrivate(name, description, aType))
+{
+}
+
+/*!
+ Assigns \a other to this QApplicationArgument instance.
+ */
+QApplicationArgument &QApplicationArgument::operator=(const QApplicationArgument &other)
+{
+ if(this != &other)
+ *d_ptr = *other.d_ptr;
+
+ return *this;
+}
+
+// TODO is this really what we want?
+/*!
+ Returns true if this QApplicationArgument instance is equal to \a other.
+
+ Equalness is defined to only consider name(). If for instance the type() differs
+ but the names are equal, this operator will return \c true.
+ */
+bool QApplicationArgument::operator==(const QApplicationArgument &other) const
+{
+ return name() == other.name();
+}
+
+/*!
+ \fn qHash(const QApplicationArgument &);
+ \internal
+
+ Returns a hash index of \a argument. This function is used when QApplicationArgument
+ is used with QHash.
+
+ The hash index is computed on name(). The other properties are ignored.
+
+ \relates QApplicationArgument
+ */
+
+/*!
+ Sets this argument's name to \a newName. The name does not
+ include any dash, or other prefix that is used by the parser.
+ */
+void QApplicationArgument::setName(const QString &newName)
+{
+ d_ptr->name = newName;
+}
+
+/*!
+ Returns the name that this argument has.
+
+ \sa setName()
+ */
+QString QApplicationArgument::name() const
+{
+ return d_ptr->name;
+}
+
+/*!
+ Sets the tupe to \a newType.
+
+ If \a newType is QVariant::Invalid, it signals that this
+ argument does not accept a value at all.
+
+ \a newType can be a QVariant::type() value, or QVariant::userType().
+
+ \sa type()
+ */
+void QApplicationArgument::setType(int newType)
+{
+ d_ptr->type = newType;
+}
+
+/*!
+ Returns the type that the value of this argument has. If it
+ is QVariant::Invalid, it means this argument cannot have a value
+ and is a switch only.
+
+ The type is by default QVariant::Invalid.
+\sa setType()
+ */
+int QApplicationArgument::type() const
+{
+ return d_ptr->type;
+}
+
+void QApplicationArgument::setDefaultValue(const QVariant &value)
+{
+ d_ptr->defaultValue = value;
+}
+
+QVariant QApplicationArgument::defaultValue() const
+{
+ return d_ptr->defaultValue;
+}
+
+/*!
+ Sets the minimum amount of times this argument can occur, to \a minimum.
+ For instance, if \a minimum is 2, the argument must be used at least two times.
+
+ If \a minimum is zero, it means the argument is optional.
+
+ \sa minimumOccurrence(), setMaximumOccurrence()
+ */
+void QApplicationArgument::setMinimumOccurrence(int minimum)
+{
+ Q_ASSERT_X(minimum >= 0, Q_FUNC_INFO,
+ "The minimum cannot be less than zero.");
+ d_ptr->minimum = minimum;
+}
+
+/*!
+ Returns the minimum amount of times an an argument must occur.
+
+ The default is 0.
+
+ \sa setMinimumOccurrence(), maximumOccurrence()
+ */
+int QApplicationArgument::minimumOccurrence() const
+{
+ return d_ptr->minimum;
+}
+
+/*!
+ Sets the maximum occurrence to \a maximum.
+
+ If \a maximum is -1, it means the argument can appear an unlimited
+ amount of times. Setting it to zero or less than -1, yields
+ undefined behavior.
+
+\sa maximumOccurrence(), setMinimumOccurrence()
+ */
+void QApplicationArgument::setMaximumOccurrence(int maximum)
+{
+ Q_ASSERT_X(maximum == -1 || maximum >= 1, Q_FUNC_INFO,
+ "The maximum can only be -1 or 1 or larger.");
+ d_ptr->maximum = maximum;
+}
+
+/*!
+ Returns the maximum amount of times this argument can occur. For instance,
+ if the maximum occurrence is 2, it would be an error if 3 were specified
+ on the command line.
+
+ If the maximum occurrence is -1, it signals the argument can appear an unlimited
+ amount of times.
+
+ The default is 1.
+
+ \sa setMaximumOccurrence()
+ */
+int QApplicationArgument::maximumOccurrence() const
+{
+ return d_ptr->maximum;
+}
+
+/*!
+ Sets the description to \a newDescription. The description
+ should describe the argument in a sentence or two. It is used
+ when displaying a help message, if requested.
+
+ The description should be terminated as if it was a paragraph. This
+ typically means a period.
+
+ The description should be translated by wrapping the
+ string literal in a call to tr().
+
+ */
+void QApplicationArgument::setDescription(const QString &newDescription)
+{
+ d_ptr->description = newDescription;
+}
+
+/*!
+ Returns the description of this argument.
+
+ \sa setDescription()
+ */
+QString QApplicationArgument::description() const
+{
+ return d_ptr->description;
+}
+
+/*!
+ \internal
+ \relates QApplicationArgument
+
+ Computes a hash key on \a argument's name and returns it.
+ */
+uint qHash(const QApplicationArgument &argument)
+{
+ return qHash(argument.name());
+}
+
+void QApplicationArgument::setNameless(bool value)
+{
+ d_ptr->isNameless = value;
+}
+
+bool QApplicationArgument::isNameless() const
+{
+ return d_ptr->isNameless;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/xmlpatterns/qapplicationargument_p.h b/tools/xmlpatterns/qapplicationargument_p.h
new file mode 100644
index 0000000000..3232bbcffe
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargument_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** ** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QApplicationArgument_H
+#define QApplicationArgument_H
+
+#include <QtCore/QVariant>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QApplicationArgumentPrivate;
+
+class QApplicationArgument
+{
+public:
+ QApplicationArgument();
+ QApplicationArgument(const QApplicationArgument &other);
+ QApplicationArgument(const QString &name,
+ const QString &description,
+ int aType = QVariant::Invalid);
+ ~QApplicationArgument();
+ QApplicationArgument &operator=(const QApplicationArgument &other);
+ bool operator==(const QApplicationArgument &other) const;
+
+ void setName(const QString &newName);
+ QString name() const;
+ void setDescription(const QString &newDescription);
+ QString description() const;
+
+ int type() const;
+ void setType(int newType);
+ void setDefaultValue(const QVariant &value);
+ QVariant defaultValue() const;
+
+ void setMinimumOccurrence(int minimum);
+ int minimumOccurrence() const;
+ void setMaximumOccurrence(int maximum);
+ int maximumOccurrence() const;
+ void setNameless(bool value);
+ bool isNameless() const;
+
+private:
+ QApplicationArgumentPrivate *d_ptr;
+};
+
+uint qHash(const QApplicationArgument &argument);
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif
+
diff --git a/tools/xmlpatterns/qapplicationargumentparser.cpp b/tools/xmlpatterns/qapplicationargumentparser.cpp
new file mode 100644
index 0000000000..7a9b902e70
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargumentparser.cpp
@@ -0,0 +1,1028 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtDebug>
+#include <QTextBoundaryFinder>
+#include <QCoreApplication>
+#include <QHash>
+#include <QPair>
+#include <QStringList>
+#include <QTextStream>
+#include <QUrl>
+
+#include "qapplicationargument_p.h"
+
+#include "qapplicationargumentparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QApplicationArgumentParser
+ \brief The QApplicationArgumentParser class parses the command
+ line arguments for an application.
+ \reentrant
+ \internal
+ \since 4.4
+
+ QApplicationArgumentParser simplifies writing command line applications by taking care of:
+
+ \list
+ \o Generating help and version arguments
+ \o Taking care of converting arguments to QVariant types, since each argument
+ has a type: QApplicationArgument::type()
+ \o Validates the command line such that the user operates on well-defined input. For instance,
+ that the argument is a valid integer if that is the case, that an argument does not
+ occur more times than allowed, and so on.
+ \o Allows customization through sub-classing.
+ \endlist
+
+ The user declares what arguments that can be given to the application with QApplicationArgument. Provided
+ with that information, QApplicationArgumentParser takes care of parsing the actual
+ command line, appropriately flag errors, generate help messages, and provide
+ convenient access to the values of the arguments.
+
+ The way to use it is to create a set of QApplicationArgument by ones choosing, call
+ addArgument() for each, and subsequently call parse(). If parse() returns \c false,
+ the caller should exit and return exitCode().
+
+ If parse() returns \c true the command line was successfully parsed, its
+ values are well-defined, and they can be spectated with count(),
+ has(), value() and values().
+
+ \snippet doc/src/snippets/code/tools_patternist_qapplicationargumentparser.cpp 0
+
+ For arguments without a name(such as filename passed to the \c ls utility on Linux) add a
+ QApplicationArgument that does not have a name. The minimum and maximum occurrences will be
+ respected as usual and the type applies too.
+
+ QApplicationArgumentParser always has two options builtin: \c version and \c help.
+
+ \section1 Changing Parsing Convention
+
+ QApplicationArgumentParser by default parses the command line in the style
+ of Qt's utilities, where arguments are preceded by a single dash, and identified
+ by a single name. However, in some cases it might be of interest to parse
+ another style, such as the well-established UNIX \c getopt convention(\c -l
+ and \c --long).
+
+ This can be achieved by sub-classing QApplicationArgumentParser and reimplementing
+ parse(). It would do the following:
+
+ \list
+ \o Call input() to retrieve the strings the user specified on the command line.
+ \o Call declaredArguments() to retrieve the arguments that the implementor has
+ decided can be specified.
+ \o Parse and validate the input. Salt and pepper as per taste.
+ \o If an error occurred, call setExitCode() and return \c false.
+ \o Otherwise, call setExitCode(Success), provide access to the
+ arguments by calling setUsedArguments(), and return \c true. If a
+ help message was requested, call setExitCode(Success) and return \c false.
+ \endlist
+
+ \sa QApplicationArgument, QCoreApplication
+*/
+class QApplicationArgumentParserPrivate
+{
+ Q_DECLARE_TR_FUNCTIONS(QApplicationArgumentParserPrivate)
+public:
+ // TODO Isn't it like ten times better with QHash<QApplicationArgument, QList<QVariant> >?
+ // TODO test QApplicationArgument::nameless()
+ typedef QList<QPair<QApplicationArgument, QVariant> > UsedList;
+
+ /*!
+ We initialize exitCode to ParseError such that we consciously flag success.
+ */
+ inline QApplicationArgumentParserPrivate(QApplicationArgumentParser *const master,
+ const QStringList &aInput) : exitCode(QApplicationArgumentParser::ParseError)
+ , input(aInput)
+ , q_ptr(master)
+ {
+ Q_ASSERT(!aInput.isEmpty());
+ }
+
+ QApplicationArgument nextNamelessArgument() const;
+ static QStringList argumentsFromLocal(const int argc, const char *const *const argv);
+
+ bool error(const QString &message);
+ static bool errorMessage(const QString &message);
+ static inline bool isSwitch(const QApplicationArgument &arg);
+ static inline QVariant conversionError(const QString &typeName,
+ const QString &input);
+ int count(const QApplicationArgument &arg) const;
+ bool contains(const QApplicationArgument &arg) const;
+ static inline bool isBuiltinVariant(const int type);
+ void displayVersion() const;
+ void displayHelp() const;
+ void parseNameless();
+ bool parseNamelessArguments(const QString &in);
+
+ QApplicationArgumentParser::ExitCode exitCode;
+ const QStringList input;
+
+ /*!
+ Since the QString is QApplicationArgument::name() anyway, why
+ not use a QSet?
+ */
+ QHash<QString, QApplicationArgument> declaredArguments;
+
+ QList<QApplicationArgument> declaredNamelessArguments;
+
+ UsedList usedArguments;
+ QString applicationDescription;
+ QString applicationVersion;
+
+private:
+ QApplicationArgumentParser *const q_ptr;
+ Q_DECLARE_PUBLIC(QApplicationArgumentParser)
+
+ static QString lineWrap(const QString &input,
+ const int leftIndent,
+ const int width);
+ static QList<QApplicationArgument> builtinArguments();
+};
+
+QApplicationArgument QApplicationArgumentParserPrivate::nextNamelessArgument() const
+{
+ /* Count how many nameless arguments we have so far. */
+ int count = 0;
+
+ for(int i = 0; i < usedArguments.count(); ++i)
+ {
+ if(usedArguments.at(i).first.isNameless())
+ ++count;
+ }
+
+ /* TODO this doesn't work for arguments that have more than one
+ * mandatory value(e.g nameless ones), since several values should
+ * then only count for one argument. */
+ for(int i = 0; i < declaredNamelessArguments.count(); ++i)
+ {
+ if(count)
+ {
+ /* Skip the ones we already have processed. */
+ --count;
+ continue;
+ }
+
+ if(declaredNamelessArguments.at(i).isNameless())
+ return declaredNamelessArguments.at(i);
+ }
+
+ return QApplicationArgument();
+}
+
+int QApplicationArgumentParserPrivate::count(const QApplicationArgument &arg) const
+{
+ const int len = usedArguments.count();
+ int count = 0;
+
+ for(int i = 0; i < len; ++i)
+ {
+ if(usedArguments.at(i).first == arg)
+ ++count;
+ }
+
+ return count;
+}
+
+/*!
+ Returns \c true if \a arg has appeared on the command line, not whether it has been declared.
+ */
+bool QApplicationArgumentParserPrivate::contains(const QApplicationArgument &arg) const
+{
+ const int len = usedArguments.count();
+
+ for(int i = 0; i < len; ++i)
+ {
+ if(usedArguments.at(i).first == arg)
+ return true;
+ }
+
+ return false;
+}
+
+/*!
+ Returns always \c false.
+ */
+bool QApplicationArgumentParserPrivate::error(const QString &message)
+{
+ exitCode = QApplicationArgumentParser::ParseError;
+ errorMessage(message);
+ return errorMessage(tr("Pass -help for information about the command line."));
+}
+
+/*!
+ Returns always \c false.
+ */
+bool QApplicationArgumentParserPrivate::errorMessage(const QString &message)
+{
+ QTextStream out(stderr, QIODevice::WriteOnly);
+ out << message << endl;
+ return false;
+}
+
+/*!
+ \internal
+ Determines whether \a arg carries a value or is on/off.
+ */
+bool QApplicationArgumentParserPrivate::isSwitch(const QApplicationArgument &arg)
+{
+ return arg.type() == QVariant::Invalid;
+}
+
+QVariant QApplicationArgumentParserPrivate::conversionError(const QString &typeName,
+ const QString &input)
+{
+ errorMessage(tr("Cannot convert %1 to type %2.").arg(input, typeName));
+ return QVariant();
+}
+
+bool QApplicationArgumentParserPrivate::isBuiltinVariant(const int type)
+{
+ return type < int(QVariant::UserType);
+}
+
+/*!
+ TODO Temporary, replace with a function in QCoreApplication.
+*/
+QStringList QApplicationArgumentParserPrivate::argumentsFromLocal(const int argc, const char *const *const argv)
+{
+ Q_ASSERT(argc >= 1);
+ Q_ASSERT(argv);
+ QStringList result;
+
+ for(int i = 0; i < argc; ++i)
+ result.append(QString::fromLocal8Bit(argv[i]));
+
+ return result;
+}
+
+void QApplicationArgumentParserPrivate::displayVersion() const
+{
+ QTextStream out(stderr);
+
+ out << tr("%1 version %2 using Qt %3").arg(QCoreApplication::applicationName(), applicationVersion, QString::fromAscii(qVersion()))
+ << endl;
+}
+
+/*!
+ \internal
+ \relates QApplicationArgument
+
+ qLess() functor for QApplicationArgument that considers the name.
+ */
+template<>
+class qLess <QApplicationArgument>
+{
+public:
+ inline bool operator()(const QApplicationArgument &o1,
+ const QApplicationArgument &o2) const
+ {
+ return o1.name().compare(o2.name()) < 0;
+ }
+};
+
+void QApplicationArgumentParserPrivate::displayHelp() const
+{
+ enum Constants
+ {
+ /**
+ * When we want to line wrap, 80 minus a couple of characters. This should
+ * be suitable for vt100 compatible terminals.
+ */
+ LineWrapAt = 78,
+
+ /**
+ * The initial " -" for each option.
+ */
+ IndentPadding = 3,
+
+ /**
+ * Pad for the brackets and space we use when we have a type.
+ */
+ ValueArgumentPadding = 4
+ };
+
+ QList<QApplicationArgument> args(declaredArguments.values());
+ args += builtinArguments();
+
+ /* Sort them, such that we get the nameless options at the end, and it
+ * generally looks tidy. */
+ qSort(args);
+
+ /* This is the basic approach:
+ * Switches:
+ * -name description
+ * Value arguments:
+ * -name <name-of-value-type> description
+ *
+ * Nameless arguments
+ * name <type> description
+ *
+ * It all line-wraps at OutputWidth and the description is indented,
+ * where the highest indent is the length of the name plus length of the name
+ * of the type. */
+
+ /* First we find the name with the largest width. */
+ int maxWidth = 0;
+
+ QList<QApplicationArgument> nameless(declaredNamelessArguments);
+ qSort(nameless);
+
+ /* Note, here the nameless arguments appear last, but are sorted
+ * with themselves. */
+ QList<QApplicationArgument> allArgs(args + nameless);
+ const int allArgsCount = allArgs.count();
+
+ for(int i = 0; i < allArgsCount; ++i)
+ {
+ const QApplicationArgument &at = allArgs.at(i);
+ const int nameLength = at.name().length();
+ const QString typeName(q_ptr->typeToName(at));
+ const int typeNameLength = typeName.length();
+ const int padding = at.type() == QVariant::Invalid ? 0 : ValueArgumentPadding;
+ maxWidth = qMax(maxWidth, nameLength + typeNameLength + padding);
+ }
+
+ QTextStream out(stderr);
+ out << endl
+ << QString(IndentPadding, QLatin1Char(' '))
+ << QCoreApplication::applicationName()
+ << QLatin1String(" -- ")
+ << applicationDescription
+ << endl;
+ // TODO synopsis
+
+ /* One extra so we get some space between the overview and the options. */
+ out << endl;
+
+ const int indentWidth = maxWidth + 3;
+
+ /* Ok, print them out. */
+ for(int i = 0; i < allArgsCount; ++i)
+ {
+ const QApplicationArgument &at = allArgs.at(i);
+ /* " -name ". Indent a bit first, inspired by Qt's moc. */
+ const QString &name = at.name();
+ QString prolog(QLatin1String(" "));
+
+ /* We have a special case for the single dash. */
+ if(name == QChar::fromLatin1('-'))
+ prolog.append(name);
+ else
+ {
+ if(!at.isNameless())
+ prolog.append(QLatin1Char('-'));
+
+ prolog.append(name + QLatin1Char(' '));
+ }
+
+ if(at.type() != QVariant::Invalid)
+ {
+ /* It's not a switch, it has a value. */
+
+ /* Do we have a default value? If so, the argument is optional. */
+ const QString typeName(q_ptr->typeToName(at));
+
+ if(at.defaultValue().isValid())
+ prolog.append(QLatin1Char('[') + typeName + QLatin1Char(']'));
+ else
+ prolog.append(QLatin1Char('<') + typeName + QLatin1Char('>'));
+ // TODO Don't we want to display the default value?
+
+ prolog.append(QLatin1Char(' '));
+ }
+
+ prolog = prolog.leftJustified(indentWidth);
+
+ out << prolog
+ << lineWrap(at.description(), indentWidth, LineWrapAt)
+ << endl;
+ }
+}
+
+/*!
+ Line wraps \a input and indents each line with \a leftIndent spaces, such that
+ the width does not go beyond \a maxWidth.
+
+ The addition of line endings is accounted for by the caller.
+
+ With QTextBoundaryFinder our line wrapping is relatively fancy, since it
+ does it the Unicode-way.
+ */
+QString QApplicationArgumentParserPrivate::lineWrap(const QString &input,
+ const int leftIndent,
+ const int maxWidth)
+{
+ const QString indent(QString(leftIndent, QLatin1Char(' ')));
+ const int len = input.length();
+ const int textWidth = maxWidth - leftIndent;
+
+ QString output;
+ QTextBoundaryFinder wrapFinder(QTextBoundaryFinder::Line, input);
+ wrapFinder.setPosition(textWidth);
+
+ if(input.length() + leftIndent <= maxWidth)
+ return input;
+
+ int from = wrapFinder.toPreviousBoundary();
+ output.append(input.left(from));
+
+ while(true)
+ {
+ if((len - from) + leftIndent > maxWidth)
+ {
+ /* We need to line wrap. */
+ wrapFinder.setPosition(from + textWidth);
+ const int currentWidthPos = wrapFinder.toPreviousBoundary();
+
+ output.append(QLatin1Char('\n'));
+ output.append(indent);
+ output.append(input.mid(from, currentWidthPos - from).trimmed());
+ from += (currentWidthPos - from);
+ }
+ else
+ {
+ /* Append the remains. */
+ output.append(QLatin1Char('\n'));
+ output.append(indent);
+ output.append(input.mid(from).trimmed());
+ break;
+ }
+ }
+
+ return output;
+}
+
+/*!
+ Returns a list with the builtin options that the parser has
+ */
+QList<QApplicationArgument> QApplicationArgumentParserPrivate::builtinArguments()
+{
+ QList<QApplicationArgument> result;
+
+ result.append(QApplicationArgument(QLatin1String("help"),
+ QLatin1String("Displays this help.")));
+ result.append(QApplicationArgument(QLatin1String("version"),
+ QLatin1String("Displays version information.")));
+
+ result.append(QApplicationArgument(QLatin1String("-"),
+ QLatin1String("When appearing, any following options are not interpreted as switches.")));
+ return result;
+}
+
+/* TODO, I don't think we want this function in a public API. Add it first when there is a demand. */
+
+/*!
+ Creates a QApplicationArgumentParser that will parse the input in \a argc and \a argv.
+These arguments should be passed directly from the \c main() function, and the decoding
+of the input will be taken care of appropriately, depending on platform.
+
+ It is preferred to use the QStringList overload, in case the input is in the form of QStrings.
+ */
+QApplicationArgumentParser::QApplicationArgumentParser(int argc, char **argv) : d(new QApplicationArgumentParserPrivate(this, QApplicationArgumentParserPrivate::argumentsFromLocal(argc, argv)))
+{
+ Q_ASSERT_X(argv, Q_FUNC_INFO, "Argv cannot be null.");
+ Q_ASSERT_X(argc >= 1, Q_FUNC_INFO,
+ "argc must at least contain the application name. "
+ "Use the QStringList overload instead.");
+}
+
+/*!
+ \overload
+
+ Creates a QApplicationArgumentParser that will parse \a input. That is, instead of passing in \c argc
+ and \c argv, one can pass in a QStringList.
+
+ The caller guarantees that the first string in \a input is the name of the application.
+ */
+QApplicationArgumentParser::QApplicationArgumentParser(const QStringList &input) : d(new QApplicationArgumentParserPrivate(this, input))
+{
+ Q_ASSERT_X(input.count() >= 1, Q_FUNC_INFO,
+ "The input must at least contain the application name.");
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Returns the strings that the user specified when starting the application. The first string
+ in the list is always the application name.
+ */
+QStringList QApplicationArgumentParser::input() const
+{
+ Q_ASSERT_X(d->input.count() >= 1, Q_FUNC_INFO, "Internal error, this should always hold true");
+ return d->input;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Sets the arguments that the user actually used on the command line to \a arguments.
+ The parse() function should call this, such that the result afterwards can be inspected
+ with for instance has() or count().
+
+\sa usedArguments()
+*/
+void QApplicationArgumentParser::setUsedArguments(const QList<QPair<QApplicationArgument, QVariant> > &arguments)
+{
+ d->usedArguments = arguments;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Returns the arguments that the user used on the command line.
+
+\sa setUsedArguments()
+*/
+QList<QPair<QApplicationArgument, QVariant> > QApplicationArgumentParser::usedArguments() const
+{
+ return d->usedArguments;
+}
+
+/*!
+ Destructs this QApplicationArgumentParser instance.
+ */
+QApplicationArgumentParser::~QApplicationArgumentParser()
+{
+ delete d;
+}
+
+/*!
+ Adds \a argument to this parser.
+
+ This function is provided for convenience. It is equivalent to creating a QList
+ containing \a argument, append the existing arguments, and then call setDeclaredArguments() with the list.
+
+ \sa setDeclaredArguments()
+ */
+void QApplicationArgumentParser::addArgument(const QApplicationArgument &argument)
+{
+ if(argument.isNameless())
+ d->declaredNamelessArguments.append(argument);
+ else
+ d->declaredArguments.insert(argument.name(), argument);
+}
+
+/*!
+ Makes the parser recognize all arguments in \a arguments.
+
+ Any arguments previously set, are discarded.
+
+ \sa addArgument(), declaredArguments()
+ */
+void QApplicationArgumentParser::setDeclaredArguments(const QList<QApplicationArgument> &arguments)
+{
+ // TODO If we have a QHash internally, why not use it in the public API too?
+ const int len = arguments.count();
+
+ for(int i = 0; i < len; ++i)
+ d->declaredArguments.insert(arguments.at(i).name(), arguments.at(i));
+}
+
+/*!
+ Returns the arguments that this parser recognizes.
+
+ \sa addArgument(), setDeclaredArguments()
+ */
+QList<QApplicationArgument> QApplicationArgumentParser::declaredArguments() const
+{
+ return d->declaredArguments.values();
+}
+
+bool QApplicationArgumentParserPrivate::parseNamelessArguments(const QString &in)
+{
+ /* It's a nameless options, such as simply "value". */
+ const QApplicationArgument nameless(nextNamelessArgument());
+
+ const QVariant val(q_ptr->convertToValue(nameless, in));
+ if(val.isValid())
+ {
+ usedArguments.append(qMakePair(nameless, val));
+ return true;
+ }
+ else
+ return false; // TODO error msg?
+}
+
+/*!
+ Parses input() together with declaredArguments() and returns \c false if the caller
+ should exit immediately, which is the case of which an error was encountered or
+ help or the version was requested.
+
+ In the case of \c true was returned, valid arguments were supplied, and they can
+ be requested with functions like value(), values(), count() and has().
+
+ parse() must only be called once per QApplicationArgumentParser instance. The
+ second time it's called, the effects and return value are undefined.
+
+ \sa convertToValue(), typeToName()
+ */
+bool QApplicationArgumentParser::parse()
+{
+ const QChar sep(QLatin1Char('-'));
+ const int inputCount = d->input.count();
+
+ /* We skip the first entry, which is the application name. */
+ int i = 1;
+
+ for(; i < inputCount; ++i)
+ {
+ const QString &in = d->input.at(i);
+
+ /* We have a single '-', signalling that the succeeding are not options. */
+ if(in == sep)
+ {
+ ++i;
+
+ for(; i < inputCount; ++i)
+ {
+ if(!d->parseNamelessArguments(d->input.at(i)))
+ return false;
+ /* Process nameless options. Have code for this elsewhere, factor it out. */
+ }
+
+ break;
+ }
+
+ if(in.startsWith(sep)) /* It is "-name". */
+ {
+ const QString name(in.mid(1));
+
+ if(name == QLatin1String("help"))
+ {
+ setExitCode(Success);
+ d->displayHelp();
+ return false;
+ }
+ else if(name == QLatin1String("version"))
+ {
+ setExitCode(Success);
+ d->displayVersion();
+ return false;
+ }
+
+ if(!d->declaredArguments.contains(name))
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" is an unknown argument.").arg(name));
+
+ const QApplicationArgument &arg = d->declaredArguments.value(name);
+ const int argCount = d->count(arg) + 1;
+ const int max = arg.maximumOccurrence();
+
+ if(argCount > max && max != -1)
+ {
+ /* Let's tailor the message for a common case. */
+ if(max == 1)
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" can only be used once.").arg(name));
+ else
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" can only be used %2 times.").arg(name, QString::number(max)));
+ }
+
+ if(QApplicationArgumentParserPrivate::isSwitch(arg))
+ {
+ d->usedArguments.append(qMakePair(arg, QVariant()));
+ continue;
+ }
+ else
+ {
+ ++i;
+
+ if(i == inputCount)
+ return d->error(QApplicationArgumentParserPrivate::tr("\"%1\" must be followed by a value.").arg(name));
+
+ /* Okidoki, got a value, always something. Let's
+ * see if it validates. */
+ const QString &value = d->input.at(i);
+
+ const QVariant val(convertToValue(arg, value));
+ if(val.isValid())
+ {
+ d->usedArguments.append(qMakePair(arg, val));
+ continue;
+ }
+ else
+ return false; // TODO error msg?
+ }
+ }
+ else
+ {
+ if(!d->parseNamelessArguments(in))
+ return false;
+ }
+ }
+
+ /* Check that all arguments that have been declared as mandatory, are actually
+ * specified. */
+ const QList<QApplicationArgument> declaredArguments(d->declaredArguments.values() + d->declaredNamelessArguments);
+ const int len = declaredArguments.count();
+ for(int i = 0; i < len; ++i)
+ {
+ const QApplicationArgument &at = declaredArguments.at(i);
+ const int min = at.minimumOccurrence();
+ const int max = at.maximumOccurrence(); // TODO What about infinite? -1
+ if(min == 0)
+ continue;
+ else
+ {
+ const int usedLen = d->usedArguments.count();
+ int useCount = 0;
+
+ for(int u = 0; u < usedLen; ++u)
+ {
+ const QPair<QApplicationArgument, QVariant> &used = d->usedArguments.at(u);
+ if(used.first == at)
+ ++useCount;
+ }
+
+ const QString originalName(at.name());
+ const QString effectiveName(originalName.isEmpty() ? QLatin1Char('<') + typeToName(at) + QLatin1Char('>') : originalName);
+
+ if(useCount < min)
+ {
+ /* For nameless options, we use the type as the name. Looks better. */
+ return d->error(QApplicationArgumentParserPrivate::tr("%1 must occur at least %2 times, therefore %3 times is insufficient.", "The number is for %2.", min)
+ .arg(effectiveName, QString::number(min), QString::number(useCount)));
+ }
+ else if(useCount > max)
+ return d->error(QApplicationArgumentParserPrivate::tr("%1 can occur at most %2 times", "", max).arg(effectiveName, QString::number(max)));
+ }
+ }
+
+ d->exitCode = Success;
+ return true;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ parse() calls this function each time a value, that is \a input, on the command line needs to be
+ validated and subsequently converted to the type of \a argument. A descriptive error message will
+ be outputted if \a input cannot be converted to the required type.
+
+ The default implementation uses QVariant::canConvert() and QVariant::convert() for doing conversions.
+
+ QApplicationArgumentParser can be subclassed and this function subsequently overridden, to handle custom types.
+
+ If \a input isn't valid input for \a argument, this function returns a default constructed
+ QVariant.
+
+ \sa typeToName(), parse()
+ */
+QVariant QApplicationArgumentParser::convertToValue(const QApplicationArgument &argument,
+ const QString &input) const
+{
+ const int type = argument.type();
+
+ switch(type)
+ {
+ case QVariant::Bool:
+ {
+ if(input == QLatin1String("true") || input == QChar::fromLatin1('1'))
+ return QVariant(true);
+ else if(input == QLatin1String("false") || input == QChar::fromLatin1('0'))
+ return QVariant(false);
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ case QVariant::RegExp:
+ {
+ const QRegExp exp(input);
+
+ if(exp.isValid())
+ return QVariant(exp);
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ case QVariant::Url:
+ {
+ const QUrl result(QUrl::fromEncoded(input.toLatin1()));
+
+ if(result.isValid())
+ return QVariant(result);
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ default:
+ {
+ QVariant result(input);
+
+ if(QApplicationArgumentParserPrivate::isBuiltinVariant(type) &&
+ result.convert(QVariant::Type(type)))
+ return result;
+ else
+ return QApplicationArgumentParserPrivate::conversionError(typeToName(argument), input);
+ }
+ }
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ convertToValue() calls this function when requiring a string for referring to \a type,
+ when generating user messages.
+
+ The implementation uses QVariant::typeToName() for most types, but special handles
+ some types, in order to let the message be better tailored for humans.
+
+ \sa convertToValue()
+ */
+QString QApplicationArgumentParser::typeToName(const QApplicationArgument &argument) const
+{
+ /* Personally I think nameForType() would be a better name but this is consistent
+ * with QVariant's function of the same name. */
+ const int type = argument.type();
+
+ switch(type)
+ {
+ case QVariant::RegExp:
+ return QApplicationArgumentParserPrivate::tr("regular expression");
+ case QVariant::Url:
+ return QLatin1String("URI");
+ case QVariant::String:
+ return QLatin1String("string");
+ default:
+ {
+ if(QApplicationArgumentParserPrivate::isBuiltinVariant(type))
+ return QString::fromLatin1(QVariant::typeToName(QVariant::Type(type)));
+ else
+ return QLatin1String(QVariant(type, static_cast<void *>(0)).typeName());
+ }
+ }
+}
+
+/*!
+ Returns the default value for \a argument. The default implementation returns
+ QApplicationArgument::defaultValue(), if \a argument has been added to this parser.
+
+ Overriding this function can be useful if creating the default value is resource
+ consuming, such as opening a file.
+ */
+QVariant QApplicationArgumentParser::defaultValue(const QApplicationArgument &argument) const
+{
+ return d->declaredArguments.value(argument.name()).defaultValue();
+}
+
+/*!
+ Returns the count of how many times \a argument was used on the command line.
+
+ \sa has()
+ */
+int QApplicationArgumentParser::count(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+ return d->count(argument);
+}
+
+/*!
+ Returns \c true if \a argument has been
+ specified one or more times on the command line, otherwise \a false.
+
+ \sa count()
+ */
+bool QApplicationArgumentParser::has(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+ return d->contains(argument);
+}
+
+/*!
+ // TODO docs
+
+ \sa values()
+ */
+QVariant QApplicationArgumentParser::value(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument), Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+
+ const int len = d->usedArguments.count();
+
+ for(int i = 0; i < len; ++i)
+ {
+ if(d->usedArguments.at(i).first == argument)
+ return d->usedArguments.at(i).second;
+ }
+
+ return defaultValue(argument);
+}
+
+/*!
+ // TODO docs
+ \sa value()
+ */
+QVariantList QApplicationArgumentParser::values(const QApplicationArgument &argument) const
+{
+ Q_ASSERT_X(d->declaredArguments.contains(argument.name()) ||
+ d->declaredNamelessArguments.contains(argument),
+ Q_FUNC_INFO,
+ "The argument isn't known to the parser. Has addArgument() been called?");
+
+ const int len = d->usedArguments.count();
+
+ QVariantList result;
+ for(int i = 0; i < len; ++i)
+ {
+ if(d->usedArguments.at(i).first == argument)
+ result.append(d->usedArguments.at(i).second);
+ }
+
+ // TODO how do we handle default values?
+ return result;
+}
+
+/*!
+ After parse() has been called, this function returns a code that can be used to
+ exit \c main() with. It returns zero upon success or if help was requested, and
+ otherwise a value signalling failure.
+ */
+QApplicationArgumentParser::ExitCode QApplicationArgumentParser::exitCode() const
+{
+ return d->exitCode;
+}
+
+/*!
+ This function is only of interest when subclassing.
+
+ Makes exitCode() return \a code.
+ */
+void QApplicationArgumentParser::setExitCode(ExitCode code)
+{
+ d->exitCode = code;
+}
+
+/*!
+ Sets the application description to \a description.
+
+ The application description is a sentence or two used for help and version
+ messages, that briefly describes the application.
+
+ The default is the empty string.
+ */
+void QApplicationArgumentParser::setApplicationDescription(const QString &description)
+{
+ d->applicationDescription = description;
+}
+
+/*!
+ Sets the application version to \a version.
+
+ This string, which is arbitrary but typically is "1.0" or so, is used when
+ generating a version statement.
+*/
+void QApplicationArgumentParser::setApplicationVersion(const QString &version)
+{
+ d->applicationVersion = version;
+}
+
+/*!
+ Writes out \a message to \c stderr.
+ */
+void QApplicationArgumentParser::message(const QString &message) const
+{
+ d->errorMessage(message);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/xmlpatterns/qapplicationargumentparser_p.h b/tools/xmlpatterns/qapplicationargumentparser_p.h
new file mode 100644
index 0000000000..16bcfe0ca0
--- /dev/null
+++ b/tools/xmlpatterns/qapplicationargumentparser_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+** ** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef QApplicationArgumentParser_H
+#define QApplicationArgumentParser_H
+
+#include <QtCore/QVariant> /* Needed, because we can't forward declare QVariantList. */
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+class QApplicationArgument;
+class QApplicationArgumentParserPrivate;
+class QStringList;
+template<typename A, typename B> struct QPair;
+template<typename T> class QList;
+template<typename Value> class QList;
+
+class QApplicationArgumentParser
+{
+public:
+ enum ExitCode
+ {
+ Success = 0,
+ ParseError = 1
+ };
+
+ QApplicationArgumentParser(int argc, char **argv);
+ QApplicationArgumentParser(const QStringList &input);
+ virtual ~QApplicationArgumentParser();
+ void addArgument(const QApplicationArgument &argument);
+ void setDeclaredArguments(const QList<QApplicationArgument> &arguments);
+ QList<QApplicationArgument> declaredArguments() const;
+
+ int count(const QApplicationArgument &argument) const;
+ bool has(const QApplicationArgument &argument) const;
+
+ virtual bool parse();
+ ExitCode exitCode() const;
+ QVariant value(const QApplicationArgument &argument) const;
+ QVariantList values(const QApplicationArgument &argument) const;
+ void setApplicationDescription(const QString &description);
+ void setApplicationVersion(const QString &version);
+ virtual void message(const QString &message) const;
+
+protected:
+ void setExitCode(ExitCode code);
+ void setUsedArguments(const QList<QPair<QApplicationArgument, QVariant> > &arguments);
+ QList<QPair<QApplicationArgument, QVariant> > usedArguments() const;
+ QStringList input() const;
+ virtual QVariant convertToValue(const QApplicationArgument &argument,
+ const QString &value) const;
+ virtual QString typeToName(const QApplicationArgument &argument) const;
+ virtual QVariant defaultValue(const QApplicationArgument &argument) const;
+
+private:
+ friend class QApplicationArgumentParserPrivate;
+ QApplicationArgumentParserPrivate *d;
+ Q_DISABLE_COPY(QApplicationArgumentParser)
+};
+
+QT_END_NAMESPACE
+QT_END_HEADER
+#endif
diff --git a/tools/xmlpatterns/qcoloringmessagehandler.cpp b/tools/xmlpatterns/qcoloringmessagehandler.cpp
new file mode 100644
index 0000000000..dd7e97fd4e
--- /dev/null
+++ b/tools/xmlpatterns/qcoloringmessagehandler.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QXmlStreamReader>
+
+#include "main.h"
+
+#include "qcoloringmessagehandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+ColoringMessageHandler::ColoringMessageHandler(QObject *parent) : QAbstractMessageHandler(parent)
+{
+ m_classToColor.insert(QLatin1String("XQuery-data"), Data);
+ m_classToColor.insert(QLatin1String("XQuery-expression"), Keyword);
+ m_classToColor.insert(QLatin1String("XQuery-function"), Keyword);
+ m_classToColor.insert(QLatin1String("XQuery-keyword"), Keyword);
+ m_classToColor.insert(QLatin1String("XQuery-type"), Keyword);
+ m_classToColor.insert(QLatin1String("XQuery-uri"), Data);
+ m_classToColor.insert(QLatin1String("XQuery-filepath"), Data);
+
+ /* If you're tuning the colors, take it easy laddie. Take into account:
+ *
+ * - Get over your own taste, there's others too on this planet
+ * - Make sure it works well on black & white
+ * - Make sure it works well on white & black
+ */
+ insertMapping(Location, CyanForeground);
+ insertMapping(ErrorCode, RedForeground);
+ insertMapping(Keyword, BlueForeground);
+ insertMapping(Data, BlueForeground);
+ insertMapping(RunningText, DefaultColor);
+}
+
+void ColoringMessageHandler::handleMessage(QtMsgType type,
+ const QString &description,
+ const QUrl &identifier,
+ const QSourceLocation &sourceLocation)
+{
+ const bool hasLine = sourceLocation.line() != -1;
+
+ switch(type)
+ {
+ case QtWarningMsg:
+ {
+ if(hasLine)
+ {
+ writeUncolored(QXmlPatternistCLI::tr("Warning in %1, at line %2, column %3: %4").arg(QString::fromLatin1(sourceLocation.uri().toEncoded()),
+ QString::number(sourceLocation.line()),
+ QString::number(sourceLocation.column()),
+ colorifyDescription(description)));
+ }
+ else
+ {
+ writeUncolored(QXmlPatternistCLI::tr("Warning in %1: %2").arg(QString::fromLatin1(sourceLocation.uri().toEncoded()),
+ colorifyDescription(description)));
+ }
+
+ break;
+ }
+ case QtFatalMsg:
+ {
+ Q_ASSERT(!sourceLocation.isNull());
+ const QString errorCode(identifier.fragment());
+ Q_ASSERT(!errorCode.isEmpty());
+ QUrl uri(identifier);
+ uri.setFragment(QString());
+
+ QString errorId;
+ /* If it's a standard error code, we don't want to output the
+ * whole URI. */
+ if(uri.toString() == QLatin1String("http://www.w3.org/2005/xqt-errors"))
+ errorId = errorCode;
+ else
+ errorId = QString::fromLatin1(identifier.toEncoded());
+
+ if(hasLine)
+ {
+ writeUncolored(QXmlPatternistCLI::tr("Error %1 in %2, at line %3, column %4: %5").arg(colorify(errorId, ErrorCode),
+ colorify(QString::fromLatin1(sourceLocation.uri().toEncoded()), Location),
+ colorify(QString::number(sourceLocation.line()), Location),
+ colorify(QString::number(sourceLocation.column()), Location),
+ colorifyDescription(description)));
+ }
+ else
+ {
+ writeUncolored(QXmlPatternistCLI::tr("Error %1 in %2: %3").arg(colorify(errorId, ErrorCode),
+ colorify(QString::fromLatin1(sourceLocation.uri().toEncoded()), Location),
+ colorifyDescription(description)));
+ }
+ break;
+ }
+ case QtCriticalMsg:
+ /* Fallthrough. */
+ case QtDebugMsg:
+ {
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "message() is not supposed to receive QtCriticalMsg or QtDebugMsg.");
+ return;
+ }
+ }
+}
+
+QString ColoringMessageHandler::colorifyDescription(const QString &in) const
+{
+ QXmlStreamReader reader(in);
+ QString result;
+ result.reserve(in.size());
+ ColorType currentColor = RunningText;
+
+ while(!reader.atEnd())
+ {
+ reader.readNext();
+
+ switch(reader.tokenType())
+ {
+ case QXmlStreamReader::StartElement:
+ {
+ if(reader.name() == QLatin1String("span"))
+ {
+ Q_ASSERT(m_classToColor.contains(reader.attributes().value(QLatin1String("class")).toString()));
+ currentColor = m_classToColor.value(reader.attributes().value(QLatin1String("class")).toString());
+ }
+
+ continue;
+ }
+ case QXmlStreamReader::Characters:
+ {
+ result.append(colorify(reader.text().toString(), currentColor));
+ continue;
+ }
+ case QXmlStreamReader::EndElement:
+ {
+ currentColor = RunningText;
+ continue;
+ }
+ /* Fallthrough, */
+ case QXmlStreamReader::StartDocument:
+ /* Fallthrough, */
+ case QXmlStreamReader::EndDocument:
+ continue;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO,
+ "Unexpected node.");
+ }
+ }
+
+ Q_ASSERT_X(!reader.hasError(), Q_FUNC_INFO,
+ "The output from Patternist must be well-formed.");
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/tools/xmlpatterns/qcoloringmessagehandler_p.h b/tools/xmlpatterns/qcoloringmessagehandler_p.h
new file mode 100644
index 0000000000..69ca5b0c0e
--- /dev/null
+++ b/tools/xmlpatterns/qcoloringmessagehandler_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+ * ** * ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ * **
+ * ** This file is part of the Patternist project on Trolltech Labs. * **
+ * ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ * **
+ * ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * **
+ * ****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_ColoringMessageHandler_h
+#define Patternist_ColoringMessageHandler_h
+
+#include <QHash>
+
+#include "qcoloroutput_p.h"
+#include "qabstractmessagehandler.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ class ColoringMessageHandler : public QAbstractMessageHandler
+ , private ColorOutput
+ {
+ public:
+ ColoringMessageHandler(QObject *parent = 0);
+
+ protected:
+ virtual void handleMessage(QtMsgType type,
+ const QString &description,
+ const QUrl &identifier,
+ const QSourceLocation &sourceLocation);
+
+ private:
+ QString colorifyDescription(const QString &in) const;
+
+ enum ColorType
+ {
+ RunningText,
+ Location,
+ ErrorCode,
+ Keyword,
+ Data
+ };
+
+ QHash<QString, ColorType> m_classToColor;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/xmlpatterns/qcoloroutput.cpp b/tools/xmlpatterns/qcoloroutput.cpp
new file mode 100644
index 0000000000..e401c5d93b
--- /dev/null
+++ b/tools/xmlpatterns/qcoloroutput.cpp
@@ -0,0 +1,350 @@
+/****************************************************************************
+ * ** * ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ * **
+ * ** This file is part of the Patternist project on Trolltech Labs.
+ * **
+ * ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ * **
+ * ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * **
+ * ****************************************************************************/
+
+#include <QFile>
+#include <QHash>
+#include <QTextCodec>
+
+#include "qcoloroutput_p.h"
+
+// TODO: rename insertMapping() to insertColorMapping()
+// TODO: Use a smart pointer for managing ColorOutputPrivate *d;
+// TODO: break out the C++ example into a snippet file
+
+/* This include must appear here, because if it appears at the beginning of the file for
+ * instance, it breaks build -- "qglobal.h:628: error: template with
+ * C linkage" -- on Mac OS X 10.4. */
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+namespace QPatternist
+{
+ class ColorOutputPrivate
+ {
+ public:
+ ColorOutputPrivate() : currentColorID(-1)
+
+ {
+ /* - QIODevice::Unbuffered because we want it to appear when the user actually calls, performance
+ * is considered of lower priority.
+ */
+ m_out.open(stderr, QIODevice::WriteOnly | QIODevice::Unbuffered);
+
+ coloringEnabled = isColoringPossible();
+ }
+
+ ColorOutput::ColorMapping colorMapping;
+ int currentColorID;
+ bool coloringEnabled;
+
+ static const char *const foregrounds[];
+ static const char *const backgrounds[];
+
+ inline void write(const QString &msg)
+ {
+ m_out.write(msg.toLocal8Bit());
+ }
+
+ static QString escapeCode(const QString &in)
+ {
+ QString result;
+ result.append(QChar(0x1B));
+ result.append(QLatin1Char('['));
+ result.append(in);
+ result.append(QLatin1Char('m'));
+ return result;
+ }
+
+ private:
+ QFile m_out;
+
+ /*!
+ Returns true if it's suitable to send colored output to \c stderr.
+ */
+ inline bool isColoringPossible() const
+ {
+# if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ /* Windows doesn't at all support ANSI escape codes, unless
+ * the user install a "device driver". See the Wikipedia links in the
+ * class documentation for details. */
+ return false;
+# else
+ /* We use QFile::handle() to get the file descriptor. It's a bit unsure
+ * whether it's 2 on all platforms and in all cases, so hopefully this layer
+ * of abstraction helps handle such cases. */
+ return isatty(m_out.handle());
+# endif
+ }
+ };
+}
+
+const char *const ColorOutputPrivate::foregrounds[] =
+{
+ "0;30",
+ "0;34",
+ "0;32",
+ "0;36",
+ "0;31",
+ "0;35",
+ "0;33",
+ "0;37",
+ "1;30",
+ "1;34",
+ "1;32",
+ "1;36",
+ "1;31",
+ "1;35",
+ "1;33",
+ "1;37"
+};
+
+const char *const ColorOutputPrivate::backgrounds[] =
+{
+ "0;40",
+ "0;44",
+ "0;42",
+ "0;46",
+ "0;41",
+ "0;45",
+ "0;43"
+};
+
+/*!
+ \since 4.4
+ \nonreentrant
+ \brief Outputs colored messages to \c stderr.
+ \internal
+
+ ColorOutput is a convenience class for outputting messages to \c stderr
+ using color escape codes, as mandated in ECMA-48. ColorOutput will only
+ color output when it is detected to be suitable. For instance, if \c stderr is
+ detected to be attached to a file instead of a TTY, no coloring will be done.
+
+ ColorOutput does its best attempt. but it is generally undefined what coloring
+ or effect the various coloring flags has. It depends strongly on what terminal
+ software that is being used.
+
+ When using `echo -e 'my escape sequence'`, \033 works as an initiator but not
+ when printing from a C++ program, despite having escaped the backslash.
+ That's why we below use characters with value 0x1B.
+
+ It can be convenient to subclass ColorOutput with a private scope, such that the
+ functions are directly available in the class using it.
+
+ \section1 Usage
+
+ To output messages, call write() or writeUncolored(). write() takes as second
+ argument an integer, which ColorOutput uses as a lookup key to find the color
+ it should color the text in. The mapping from keys to colors is done using
+ insertMapping(). Typically this is used by having enums for the various kinds
+ of messages, which subsequently are registered.
+
+ \code
+ enum MyMessage
+ {
+ Error,
+ Important
+ };
+
+ ColorOutput output;
+ output.insertMapping(Error, ColorOutput::RedForeground);
+ output.insertMapping(Import, ColorOutput::BlueForeground);
+
+ output.write("This is important", Important);
+ output.write("Jack, I'm only the selected official!", Error);
+ \endcode
+
+ \sa {http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html} {Bash Prompt HOWTO, 6.1. Colours}
+ {http://linuxgazette.net/issue51/livingston-blade.html} {Linux Gazette, Tweaking Eterm, Edward Livingston-Blade}
+ {http://www.ecma-international.org/publications/standards/Ecma-048.htm} {Standard ECMA-48, Control Functions for Coded Character Sets, ECMA International},
+ {http://en.wikipedia.org/wiki/ANSI_escape_code} {Wikipedia, ANSI escape code}
+ {http://linuxgazette.net/issue65/padala.html} {Linux Gazette, So You Like Color!, Pradeep Padala}
+ */
+
+/*!
+ \enum ColorOutput::ColorCode
+
+ \value DefaultColor ColorOutput performs no coloring. This typically means black on white
+ or white on black, depending on the settings of the user's terminal.
+ */
+
+/*!
+ Sets the color mapping to be \a cMapping.
+
+ Negative values are disallowed.
+
+ \sa colorMapping(), insertMapping()
+ */
+void ColorOutput::setColorMapping(const ColorMapping &cMapping)
+{
+ d->colorMapping = cMapping;
+}
+
+/*!
+ Returns the color mappings in use.
+
+ \sa setColorMapping(), insertMapping()
+ */
+ColorOutput::ColorMapping ColorOutput::colorMapping() const
+{
+ return d->colorMapping;
+}
+
+/*!
+ Constructs a ColorOutput instance, ready for use.
+ */
+ColorOutput::ColorOutput() : d(new ColorOutputPrivate())
+{
+}
+
+/*!
+ Destructs this ColorOutput instance.
+ */
+ColorOutput::~ColorOutput()
+{
+ delete d;
+}
+
+/*!
+ Sends \a message to \c stderr, using the color looked up in colorMapping() using \a colorID.
+
+ If \a color isn't available in colorMapping(), result and behavior is undefined.
+
+ If \a colorID is 0, which is the default value, the previously used coloring is used. ColorOutput
+ is initialized to not color at all.
+
+ If \a message is empty, effects are undefined.
+
+ \a message will be printed as is. For instance, no line endings will be inserted.
+ */
+void ColorOutput::write(const QString &message, int colorID)
+{
+ d->write(colorify(message, colorID));
+}
+
+/*!
+ Writes \a message to \c stderr as if for instance
+ QTextStream would have been used, and adds a line ending at the end.
+
+ This function can be practical to use such that one can use ColorOutput for all forms of writing.
+ */
+void ColorOutput::writeUncolored(const QString &message)
+{
+ d->write(message + QLatin1Char('\n'));
+}
+
+/*!
+ Treats \a message and \a colorID identically to write(), but instead of writing
+ \a message to \c stderr, it is prepared for being written to \c stderr, but is then
+ returned.
+
+ This is useful when the colored string is inserted into a translated string(dividing
+ the string into several small strings prevents proper translation).
+ */
+QString ColorOutput::colorify(const QString &message, int colorID) const
+{
+ Q_ASSERT_X(colorID == -1 || d->colorMapping.contains(colorID), Q_FUNC_INFO,
+ qPrintable(QString::fromLatin1("There is no color registered by id %1").arg(colorID)));
+ Q_ASSERT_X(!message.isEmpty(), Q_FUNC_INFO, "It makes no sense to attempt to print an empty string.");
+
+ if(colorID != -1)
+ d->currentColorID = colorID;
+
+ if(d->coloringEnabled && colorID != -1)
+ {
+ const int color(d->colorMapping.value(colorID));
+
+ /* If DefaultColor is set, we don't want to color it. */
+ if(color & DefaultColor)
+ return message;
+
+ const int foregroundCode = (int(color) & ForegroundMask) >> ForegroundShift;
+ const int backgroundCode = (int(color) & BackgroundMask) >> BackgroundShift;
+ QString finalMessage;
+ bool closureNeeded = false;
+
+ if(foregroundCode)
+ {
+ finalMessage.append(ColorOutputPrivate::escapeCode(QLatin1String(ColorOutputPrivate::foregrounds[foregroundCode - 1])));
+ closureNeeded = true;
+ }
+
+ if(backgroundCode)
+ {
+ finalMessage.append(ColorOutputPrivate::escapeCode(QLatin1String(ColorOutputPrivate::backgrounds[backgroundCode - 1])));
+ closureNeeded = true;
+ }
+
+ finalMessage.append(message);
+
+ if(closureNeeded)
+ {
+ finalMessage.append(QChar(0x1B));
+ finalMessage.append(QLatin1String("[0m"));
+ }
+
+ return finalMessage;
+ }
+ else
+ return message;
+}
+
+/*!
+ Adds a color mapping from \a colorID to \a colorCode, for this ColorOutput instance.
+
+ This is a convenience function for creating a ColorOutput::ColorMapping instance and
+ calling setColorMapping().
+
+ \sa colorMapping(), setColorMapping()
+ */
+void ColorOutput::insertMapping(int colorID, const ColorCode colorCode)
+{
+ d->colorMapping.insert(colorID, colorCode);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/xmlpatterns/qcoloroutput_p.h b/tools/xmlpatterns/qcoloroutput_p.h
new file mode 100644
index 0000000000..d9daa14013
--- /dev/null
+++ b/tools/xmlpatterns/qcoloroutput_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+ * ** * ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+ * **
+ * ** This file is part of the Patternist project on Trolltech Labs. * **
+ * ** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+ * **
+ * ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * **
+ * ****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_ColorOutput_h
+#define Patternist_ColorOutput_h
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QHash>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ class ColorOutputPrivate;
+
+ class ColorOutput
+ {
+ enum
+ {
+ ForegroundShift = 10,
+ BackgroundShift = 20,
+ SpecialShift = 20,
+ ForegroundMask = ((1 << ForegroundShift) - 1) << ForegroundShift,
+ BackgroundMask = ((1 << BackgroundShift) - 1) << BackgroundShift
+ };
+
+ public:
+ enum ColorCodeComponent
+ {
+ BlackForeground = 1 << ForegroundShift,
+ BlueForeground = 2 << ForegroundShift,
+ GreenForeground = 3 << ForegroundShift,
+ CyanForeground = 4 << ForegroundShift,
+ RedForeground = 5 << ForegroundShift,
+ PurpleForeground = 6 << ForegroundShift,
+ BrownForeground = 7 << ForegroundShift,
+ LightGrayForeground = 8 << ForegroundShift,
+ DarkGrayForeground = 9 << ForegroundShift,
+ LightBlueForeground = 10 << ForegroundShift,
+ LightGreenForeground = 11 << ForegroundShift,
+ LightCyanForeground = 12 << ForegroundShift,
+ LightRedForeground = 13 << ForegroundShift,
+ LightPurpleForeground = 14 << ForegroundShift,
+ YellowForeground = 15 << ForegroundShift,
+ WhiteForeground = 16 << ForegroundShift,
+
+ BlackBackground = 1 << BackgroundShift,
+ BlueBackground = 2 << BackgroundShift,
+ GreenBackground = 3 << BackgroundShift,
+ CyanBackground = 4 << BackgroundShift,
+ RedBackground = 5 << BackgroundShift,
+ PurpleBackground = 6 << BackgroundShift,
+ BrownBackground = 7 << BackgroundShift,
+ DefaultColor = 1 << SpecialShift
+ };
+
+ typedef QFlags<ColorCodeComponent> ColorCode;
+ typedef QHash<int, ColorCode> ColorMapping;
+
+ ColorOutput();
+ ~ColorOutput();
+
+ void setColorMapping(const ColorMapping &cMapping);
+ ColorMapping colorMapping() const;
+ void insertMapping(int colorID, const ColorCode colorCode);
+
+ void writeUncolored(const QString &message);
+ void write(const QString &message, int color = -1);
+ QString colorify(const QString &message, int color = -1) const;
+
+ private:
+ ColorOutputPrivate *d;
+ Q_DISABLE_COPY(ColorOutput)
+ };
+}
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPatternist::ColorOutput::ColorCode)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/tools/xmlpatterns/xmlpatterns.pro b/tools/xmlpatterns/xmlpatterns.pro
new file mode 100644
index 0000000000..9c1aac1d01
--- /dev/null
+++ b/tools/xmlpatterns/xmlpatterns.pro
@@ -0,0 +1,31 @@
+TEMPLATE = app
+TARGET = xmlpatterns
+DESTDIR = ../../bin
+QT -= gui
+QT += xmlpatterns
+
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+
+# This ensures we get stderr and stdout on Windows.
+CONFIG += console
+
+# This ensures that this is a command-line program on OS X and not a GUI application.
+CONFIG -= app_bundle
+
+# Note that qcoloroutput.cpp and qcoloringmessagehandler.cpp are also used internally
+# in libQtXmlPatterns. See src/xmlpatterns/api/api.pri.
+SOURCES = main.cpp \
+ qapplicationargument.cpp \
+ qapplicationargumentparser.cpp \
+ qcoloringmessagehandler.cpp \
+ qcoloroutput.cpp
+
+
+HEADERS = main.h \
+ qapplicationargument.cpp \
+ qapplicationargumentparser.cpp \
+ qcoloringmessagehandler_p.h \
+ qcoloroutput_p.h
+
+include(../src/common.pri)